Merge branch 'master' of https://github.com/mgcaret/of816 into gosxb

This commit is contained in:
mgcaret 2019-12-27 11:05:56 -08:00
commit e5cf857866
7 changed files with 491 additions and 28 deletions

84
fcode-modules/tester.fs Normal file
View File

@ -0,0 +1,84 @@
\ Adapted from: https://raw.githubusercontent.com/gerryjackson/forth2012-test-suite/master/src/tester.fr
\ From: John Hayes S1I
\ Subject: tester.fr
\ Date: Mon, 27 Nov 95 13:10:09 PST
\ (C) 1995 JOHNS HOPKINS UNIVERSITY / APPLIED PHYSICS LABORATORY
\ MAY BE DISTRIBUTED FREELY AS LONG AS THIS COPYRIGHT NOTICE REMAINS.
\ VERSION 1.2
\ 24/11/2015 Replaced Core Ext word <> with = 0=
\ 31/3/2015 Variable #ERRORS added and incremented for each error reported.
\ 22/1/09 The words { and } have been changed to T{ and }T respectively to
\ agree with the Forth 200X file ttester.fs. This avoids clashes with
\ locals using { ... } and the FSL use of }
version1
headerless
defer >in s" ' >in" eval to >in
defer source s" ' source" eval to source
HEX
headers
\ SET THE FOLLOWING FLAG TO TRUE FOR MORE VERBOSE OUTPUT; THIS MAY
\ ALLOW YOU TO TELL WHICH TEST CAUSED YOUR SYSTEM TO HANG.
VARIABLE VERBOSE
FALSE VERBOSE !
\ TRUE VERBOSE !
\ : EMPTY-STACK \ ( ... -- ) EMPTY STACK: HANDLES UNDERFLOWED STACK TOO.
\ DEPTH ?DUP IF DUP 0< IF NEGATE 0 DO 0 LOOP ELSE 0 DO DROP LOOP THEN THEN ;
\ THE IEEE-1275 CLEAR word works the same but the standard does not define
\ an FCode for it...
defer EMPTY-STACK s" ' clear" eval to EMPTY-STACK
VARIABLE #ERRORS 0 #ERRORS !
: ERROR \ ( C-ADDR U -- ) DISPLAY AN ERROR MESSAGE FOLLOWED BY
\ THE LINE THAT HAD THE ERROR.
CR TYPE SOURCE TYPE \ DISPLAY LINE CORRESPONDING TO ERROR
EMPTY-STACK \ THROW AWAY EVERY THING ELSE
#ERRORS @ 1 + #ERRORS !
\ QUIT \ *** Uncomment this line to QUIT on an error
;
VARIABLE ACTUAL-DEPTH \ STACK RECORD
CREATE ACTUAL-RESULTS 20 CELLS ALLOT
: T{ \ ( -- ) SYNTACTIC SUGAR.
;
\ FCode tokenizer will issue a warning for this
\ it can be ignored
: -> \ ( ... -- ) RECORD DEPTH AND CONTENT OF STACK.
DEPTH DUP ACTUAL-DEPTH ! \ RECORD DEPTH
?DUP IF \ IF THERE IS SOMETHING ON STACK
0 DO ACTUAL-RESULTS I CELLS + ! LOOP \ SAVE THEM
THEN ;
: }T \ ( ... -- ) COMPARE STACK (EXPECTED) CONTENTS WITH SAVED
\ (ACTUAL) CONTENTS.
DEPTH ACTUAL-DEPTH @ = IF \ IF DEPTHS MATCH
DEPTH ?DUP IF \ IF THERE IS SOMETHING ON THE STACK
0 DO \ FOR EACH STACK ITEM
ACTUAL-RESULTS I CELLS + @ \ COMPARE ACTUAL WITH EXPECTED
= 0= IF S" INCORRECT RESULT: " ERROR LEAVE THEN
LOOP
THEN
ELSE \ DEPTH MISMATCH
S" WRONG NUMBER OF RESULTS: " ERROR
THEN ;
: TESTING \ ( -- ) TALKING COMMENT.
SOURCE VERBOSE @
IF DUP >R TYPE CR R> >IN !
ELSE >IN ! DROP [CHAR] * EMIT
THEN ;
fcode-end

View File

@ -1,9 +1,13 @@
#!/bin/bash
ACMD=~/bin/AppleCommander-ac-1.5.0.jar
set -e -x
cd $(dirname $0)
ca65 -I ../../inc IIgs.s -l IIgs.lst
../../build.sh IIgs
ld65 -C IIgs.l -S 0x8000 IIgs.o ../../forth.o -m forth.map -o forth
ls -l forth
java -jar ${ACMD} -pro140 forth.po FORTH
java -jar ${ACMD} -p forth.po FORTH SYS < forth
if [ -r "${ACMD}" ]; then
java -jar ${ACMD} -pro140 forth.po FORTH
java -jar ${ACMD} -p forth.po FORTH SYS < forth
fi

View File

@ -75,7 +75,7 @@ RTCday = $100108 ; 2 bytes
; *****************
I2C2io = $100014
I2C2ctrl = $100015 ; read: b3 = busy; write: $01 = start, $02 = stop, $04 = receive, $08 = send, $44 = receive/ack
I2C2ctrl = $100015 ; read: b7 = busy; write: $01 = start, $02 = stop, $04 = receive, $08 = send, $44 = receive/ack
; *****************
; SPI
@ -91,7 +91,7 @@ SPI2ctrl3 = $10001F ; init = $05
; VDC
; *****************
VDCio = $100120 ; read: 1 byte, write: 1 or 2 bytes
VDCbase = $100120 ; base address, there are $20 registers
; *****************
; FDC

View File

@ -1,21 +1,36 @@
# Neon816
This is a port to Lenore Byron's [Neon816](https://hackaday.io/project/164325-neon816) system. The Neon816 Developer Edition ships with a small 16-bit Forth.
This is a port to Lenore Byron's [Neon816](https://hackaday.io/project/164325-neon816) system. The Neon816 Developer
Edition ships with a small 16-bit Forth.
OF816 for the Neon816 is configured to run as an alternative firmware out of bank $20. With a little ajustment, it could be configured to run out of bank $21 (but starting it is an excercise for the reader).
OF816 for the Neon816 is configured to run as an alternative firmware out of bank $20. With a little ajustment, it
could be configured to run out of bank $21 (but starting it is an excercise for the reader).
It configures the MMU and serial port like NeonFORTH does. The direct page, stack, and return stack occupy the first $400 bytes of RAM.
It configures the MMU and serial port like NeonFORTH does. The direct page, stack, and return stack occupy the first
$400 bytes of RAM.
To build OF816 for the Neon816, change to the platform directory and run
``build.sh``. It will output a 64K binary named ``of816-neon.bin`` that can be flashed into the Neon's firmware. See below for installation instructions.
``build.sh``. It will output a 64K binary named ``of816-neon.bin`` that can be flashed into the Neon's firmware.
See below for installation instructions.
## Port Features
Hopefully this section will be filled up with stuff that works like Lenore's
Forth. See the [Neon816 Manual](https://cdn.hackaday.io/files/1643257030480800/sysmanual.pdf). But right now, it's just a bare port with no system-specific extensions.
Hardware access words with the same semantics as NeonFORTH are found in the NEON816 dictionary.
## Installation
The hardware access dictionary is currently not complete but has the words for accessing the PS/2 ports, I2C2,
and VDC.
Execute ``also neon816`` to gain access to the words.
See the [Neon816 Manual](https://cdn.hackaday.io/files/1643257030480800/sysmanual.pdf) for descriptions of the
specific words.
## Installation / Removal
The instructions assume you are running Linux. The Neon firmware loader is supported under Linux only.
### Installing OF816
**THIS WILL OVERWRITE THE NEON'S ORIGINAL FIRMWARE!**
@ -23,11 +38,15 @@ Forth. See the [Neon816 Manual](https://cdn.hackaday.io/files/1643257030480800/
**READ _ALL_ OF THE FOLLOWING BEFORE PROCEEDING AND DO NOT PROCEED IF ANY OF THIS MAKES YOU UNCOMFORTABLE!**
After building the firmware image, the image must be converted to Intel Hex format. I like the bin2hex tool found [here](https://grumpf.hope-2000.org) (page is in German). Build the ``bin2hex`` binary and execute: ``bin2hex of816-neon.bin > of816-neon.hex``
After building the firmware image, the image must be converted to Intel Hex format. I like the bin2hex tool originally
found [here](https://grumpf.hope-2000.org) (page is in German), also in my [Github repo](https://github.com/mgcaret/bin2hex).
Build the ``bin2hex`` binary and execute: ``bin2hex of816-neon.bin > of816-neon.hex``
Once you have the .hex file, you will need to use the [Neon firmware loader](https://hackaday.io/project/164325-neon816) to install the image. This requires an FTDI cable connected to the 3.3V UART header on the Neon816 system board.
Once you have the .hex file, you will need to use the [Neon firmware loader](https://hackaday.io/project/164325-neon816)
to install the image. This requires an FTDI cable connected to the 3.3V UART header on the Neon816 system board.
To back up the original firmware, you will need to add an additional command routine to neonprog.cpp (add it after the write command):
To back up the original firmware, you will need to add an additional command routine to neonprog.cpp (add it after the
write command):
```
else if(!strcmp(cmd,"dumprom")) {
@ -59,8 +78,40 @@ build neonprog then start it with ``neonprog /dev/ttyUSBx`` (replace device with
From within neonprog, execute ``dumprom backup.bin`` to save an image of both ROM banks to ``backup.bin``.
Once the backup has finished (it will take a while), you can proceed to the installation of OF816 with ``flash of816-neon.hex``. This will also take a while. When it is done, reset your Neon and OF816 should start.
Once the backup has finished (it will take a while), you can proceed to the installation of OF816 with
``flash of816-neon.hex``. This will also take a while. When it is done, reset your Neon and OF816 should start.
## Restoring the Original NeonFORTH Firmware
### Restoring the Original NeonFORTH Firmware
Since the Neon (at the time of this writing) only ships with the first bank of flash occupied, first, split your backup
with ``split -b 65536 backup.bin``. This will output two files, ``xaa`` and ``xab`` that are bank $20 and bank $21,
respectively. Then run ``bin2hex xaa > neonforth.hex``. You can then flash this with neonprog using
``flash neonforth.hex``. Once it's done, reset your Neon and you should see the original firmware running.
## A Comparison of OF816 and NeonFORTH
NeonFORTH, which comes with the Neon816, is a compact 16-bit Forth specifically designed for the system by its creator.
OF816 is a portable 32-bit Forth that is designed to run on many 65816 systems. As a result of its 32-bit cells, it has
a flat view of the 65816 address space. A negative consequence is that it is slower and uses more memory than a system
like NeonFORTH.
A general comparison:
| OF816 | NeonFORTH |
|------------------------------------------|----------------------------------------------|
| 32-bit cells | 16-bit cells |
| First-class access to '816 address space | Special words to access memory beyond bank 0 |
| Slower | Faster |
| More RAM/ROM use | Less RAM/ROM use |
| ANSI standard Forth | Not ANSI standard |
| FCode support | No FCode support |
| Larger dictionary | Smaller dictionary |
Additionally, as NeonFORTH is maintained by the creator of the Neon816, it is going to have features specific to the
Neon816 sooner than OF816 will have them.
Overall, NeonFORTH is small, and well suited to basic experiments with the Neon816's hardware. OF816 is more powerful
in the large built-in dictionary, and in the way it handles numbers, address space, exceptions, and stack over/
underflow. However, this makes it slower and use more memory.
Since the Neon (at the time of this writing) only ships with the first bank of flash occupied, first, split your backup with ``split -b 65536 backup.bin``. This will output two files, ``xaa`` and ``xab`` that are bank $20 and bank $21, respectively. Then run ``bin2hex xaa > neonforth.hex``. You can then flash this with neonprog using ``flash neonforth.hex``. Once it's done, reset your Neon and you should see the original firmware running.

View File

@ -1,12 +1,13 @@
#!/bin/bash
set -e -x
cd $(dirname $0)
ca65 -I ../../inc Neon816.s -l Neon816.lst
ca65 -I ../../inc romboot.s -l romboot.lst
../../build.sh Neon816
ld65 -C Neon816.l Neon816.o ../../forth.o ./romboot.o -m forth.map -o of816-neon.bin
ld65 -vm -C Neon816.l Neon816.o ../../forth.o ./romboot.o -m forth.map -o of816-neon.bin
ls -l of816-neon.bin
if which -s bin2hex; then
hex2bin of816-neon.bin > of816-neon.hex
bin2hex of816-neon.bin > of816-neon.hex
ls -l of816-neon.hex
fi

View File

@ -42,7 +42,6 @@ dword PS2K_QUERY,"PS2K?"
eword
dword PS2K_FETCH,"PS2K@"
lda #$0000
sep #SHORT_A
.a8
: lda f:PS2Kstat
@ -51,9 +50,9 @@ dword PS2K_FETCH,"PS2K@"
lda f:PS2Kio
rep #SHORT_A
.a16
tay
lda #$0000
PUSHNEXT
and #$00FF
jsr _pusha
NEXT
eword
dword PS2M_STORE,"PS2M!"
@ -85,7 +84,6 @@ dword PS2M_QUERY,"PS2M?"
eword
dword PS2M_FETCH,"PS2M@"
lda #$0000
sep #SHORT_A
.a8
: lda f:PS2Mstat
@ -94,9 +92,16 @@ dword PS2M_FETCH,"PS2M@"
lda f:PS2Mio
rep #SHORT_A
.a16
tay
lda #$0000
PUSHNEXT
and #$00FF
jsr _pusha
NEXT
eword
dword dKBDRESET,"$KBDRESET"
ENTER
ONLIT $FF
.dword PS2K_STORE
EXIT
eword
; this probably isn't fast enough to reliably set micro and milliseconds
@ -134,6 +139,321 @@ dword GETRTC,"GETRTC"
EXIT
eword
; NOTE: sets short accumulator and leaves it that way on exit!
.proc I2C2_busy_wait
sep #SHORT_A
nosep:
.a8
: lda f:I2C2ctrl
rol
bcs :-
rts
.a16
.endproc
dword I2C2START,"I2C2START"
jsr I2C2_busy_wait
.a8
lda #$01
sta f:I2C2ctrl
rep #SHORT_A
.a16
NEXT
eword
dword I2C2STOP,"I2C2STOP"
jsr I2C2_busy_wait
.a8
lda #$02
sta f:I2C2ctrl
rep #SHORT_A
.a16
NEXT
eword
dword I2C2_STORE,"I2C2!"
jsr _popay
jsr I2C2_busy_wait
.a8
tya
sta f:I2C2io
lda #$08
sta f:I2C2ctrl
rep #SHORT_A
.a16
NEXT
eword
dword I2C2_FETCH_ACK,"I2C2@+"
jsr I2C2_busy_wait
.a8
lda #$44
dofetch: sta f:I2C2ctrl
jsr I2C2_busy_wait::nosep
lda f:I2C2io
rep #SHORT_A
.a16
and #$00FF
jsr _pusha
NEXT
eword
dword I2C2_FETCH,"I2C2@+"
jsr I2C2_busy_wait
.a8
lda #$04
bra I2C2_FETCH_ACK::dofetch
.a16
eword
dword VDC_C_STORE,"VDCC!"
jsr _popay ; pop offset
phy ; save low word
jsr _popay ; pop value to write
pla ; get offset back
phx ; save SP
tax ; offset to x reg
sep #SHORT_A ; whew! that was fun!
.a8
tya ; value to A
sta f:VDCbase,x
rep #SHORT_A
.a16
plx ; restore SP
NEXT
eword
dword VDC_C_FETCH,"VDCC@"
jsr _popay ; pop offet
phx ; save SP
tya
tax
sep #SHORT_A ; whew! that was fun!
.a8
lda f:VDCbase,x
rep #SHORT_A
.a16
plx ; restore SP
and #$00FF
jsr _pusha
NEXT
eword
dword VDC_STORE,"VDC!"
jsr _popay ; again! again! again!
phy
jsr _popay
pla
phx
tax
tya
sta f:VDCbase,x
rep #SHORT_A
.a16
plx ; restore SP
NEXT
eword
dword VIDSTART,"VIDSTART"
ENTER
ONLIT $0799
ONLIT $10
.dword VDC_STORE
ONLIT $0839
ONLIT $12
.dword VDC_STORE
ONLIT $03C7
ONLIT $14
.dword VDC_STORE
ONLIT $041E
ONLIT $16
.dword VDC_STORE
ONLIT $0257
ONLIT $18
.dword VDC_STORE
ONLIT $0258
ONLIT $1A
.dword VDC_STORE
ONLIT $025C
ONLIT $1C
.dword VDC_STORE
ONLIT $0272
ONLIT $1E
.dword VDC_STORE
vid_on: ONLIT $92
: .dword ZERO
.dword VDC_C_STORE
.dword ZERO
.dword VDC_C_FETCH
.dword IF
.dword :- ; branch if false
.dword I2C2START
ONLIT $70
.dword I2C2_STORE
ONLIT $08
.dword I2C2_STORE
ONLIT $B9
.dword I2C2_STORE
.dword I2C2STOP
EXIT
eword
dword VMODELINE,"VMODELINE"
ENTER
.dword TWO
.dword MINUS
ONLIT $1E
.dword VDC_STORE
.dword DECR
ONLIT $1C
.dword VDC_STORE
.dword DECR
ONLIT $1A
.dword VDC_STORE
.dword DECR
ONLIT $18
.dword VDC_STORE
.dword TWO
.dword MINUS
ONLIT $16
.dword VDC_STORE
.dword DECR
ONLIT $14
.dword VDC_STORE
.dword DECR
ONLIT $12
.dword VDC_STORE
.dword DECR
ONLIT $10
.dword VDC_STORE
JUMP VIDSTART::vid_on
eword
dword VIDSTOP,"VIDSTOP"
ENTER
.dword I2C2START
ONLIT $70
.dword I2C2_STORE
ONLIT $08
.dword I2C2_STORE
ONLIT $FE
.dword I2C2_STORE
.dword I2C2STOP
.dword ZERO
.dword ZERO
.dword VDC_C_STORE
EXIT
eword
dword DUMPEDID,"DUMPEDID"
dump_size = $0100
ENTER
ONLIT dump_size
.dword ALLOC ; buffer for downloaded EDID data
.dword I2C2START
ONLIT $A0
.dword I2C2_STORE
.dword ZERO
.dword I2C2_STORE
.dword I2C2START
ONLIT $A1
.dword I2C2_STORE
ONLIT dump_size
.dword ZERO
.dword _DO
: .dword I2C2_FETCH_ACK
.dword OVER
.dword IX
.dword PLUS
.dword CSTORE
.dword ONE
.dword _PLOOP
.dword :-
.dword UNLOOP
.dword I2C2_FETCH ; NeonFORTH displays this
.dword I2C2STOP
.dword DUP
ONLIT dump_size
.dword DUMP
ONLIT dump_size
.dword FREE
EXIT
eword
dword SPI2INIT,"SPI2INIT"
sep #SHORT_A
.a8
lda #$00
sta f:SPI2ctrl
sta f:SPI2ctrl2
lda #$05
sta f:SPI2ctrl3
rep #SHORT_A
.a16
NEXT
eword
dword SPI2START,"SPI2START"
sep #SHORT_A
.a8
lda #$01
sta f:SPI2ctrl
rep #SHORT_A
.a16
NEXT
eword
dword SPI2STOP,"SPI2STOP"
sep #SHORT_A
.a8
: lda f:SPI2ctrl
and #$40
bne :-
sta f:SPI2ctrl ; note A=0
rep #SHORT_A
.a16
NEXT
eword
; NOTE: sets short accumulator and leaves it that way on exit!
.proc SPI2_busy_wait
sep #SHORT_A
nosep:
.a8
: lda f:SPI2ctrl
rol
bcs :-
rts
.a16
.endproc
dword SPI2_STORE,"SPI2!"
jsr _popay
jsr SPI2_busy_wait
.a8
tya
sta f:SPI2io
rep #SHORT_A
.a16
NEXT
eword
dword SPI2_FETCH,"SPI2@"
jsr SPI2_busy_wait
.a8
lda #$00
sta f:SPI2io
: lda f:SPI2ctrl
bit #$40
bne :-
lda f:SPI2io
rep #SHORT_A
.a16
and #$00FF
jsr _pusha
NEXT
eword
dend
; and now for the system interface
@ -199,6 +519,8 @@ table: .addr _sf_pre_init
.dword drXT ; last word defined in the neon816 dictionary
.dword rBODY
.dword STORE
.dword GETRTC ; start the clock
.dword CLEAR
CODE
jmp _sf_success
.endproc

View File

@ -1,9 +1,10 @@
#!/bin/bash
set -e -x
cd $(dirname $0)
toke fcode/romloader.fs
ruby mkromfs.rb romfs fs/*
ca65 -I ../../inc W65C816SXB.s -l W65C816SXB.lst
../../build.sh W65C816SXB
ld65 -C W65C816SXB.l -S 0x8000 W65C816SXB.o ../../forth.o -m forth.map -o forth
ld65 -vm -C W65C816SXB.l -S 0x8000 W65C816SXB.o ../../forth.o -m forth.map -o forth
ls -l forth