mirror of
https://github.com/mgcaret/of816.git
synced 2025-01-14 02:32:09 +00:00
commit
84c936075c
4
.gitignore
vendored
4
.gitignore
vendored
@ -9,3 +9,7 @@ t
|
||||
/platform.inc
|
||||
*.po
|
||||
romfs
|
||||
.DS_Store
|
||||
*.hex
|
||||
of816-neon.bin
|
||||
|
||||
|
104
platforms/Neon816/Neon816-hw.inc
Normal file
104
platforms/Neon816/Neon816-hw.inc
Normal file
@ -0,0 +1,104 @@
|
||||
|
||||
; Bank Map from FB posting by Lenore:
|
||||
; 00 Bank Mapper (16 blocks of 4k each, configured via MMU)
|
||||
; 08-0F Bus Controller Peripherals
|
||||
; - 08 0000-003F MMU
|
||||
; -- 00: 0-3 Unused, 4-7: Upper RAM bits
|
||||
; -- 01: Bank
|
||||
; - 09 FDC
|
||||
; 10-1F Internal Bus Bridge
|
||||
; 20-27 Flash ROM
|
||||
; 28-3F Reserved for Flash
|
||||
; 30-3F Reserved for Expansion Flash
|
||||
; 40-47 Video RAM
|
||||
; 48-7F Reserved for VRAM
|
||||
; 80-87 RAM 1
|
||||
; 88-8F RAM 2
|
||||
; 90-FF Reserved for RAM
|
||||
|
||||
cpu_clk = 14000000
|
||||
|
||||
; *****************
|
||||
; Memory regions
|
||||
; *****************
|
||||
Neon_ROM = $200000
|
||||
Neon_VRAM = $400000
|
||||
Neon_RAM1 = $800000
|
||||
Neon_RAM2 = $880000
|
||||
|
||||
; *****************
|
||||
; MMU
|
||||
; *****************
|
||||
|
||||
NeonMMU = $080000
|
||||
|
||||
; *****************
|
||||
; I/O Ports
|
||||
;
|
||||
; Generally for the status ports, unless otherwise stated
|
||||
; b3 = transmit buffer full (output is busy)
|
||||
; b0 = receive buffer full (input is ready)
|
||||
; *****************
|
||||
|
||||
SERio = $100008
|
||||
SERstat = $100009
|
||||
; Presumably baud and line setup
|
||||
SERctrlA = $10000A ; NeonForth sets this to $8D
|
||||
SERctrlB = $10000B ; ditto $06
|
||||
SERctrlC = $10000C ; ditto $00
|
||||
|
||||
; MIDI ports
|
||||
MIDIio = $100020
|
||||
MIDIstat = $100021
|
||||
|
||||
; PS/2 Keyboard Port
|
||||
PS2Kio = $100022
|
||||
PS2Kstat = $100023
|
||||
|
||||
; PS/2 Mouse Port
|
||||
PS2Mio = $100024
|
||||
PS2Mstat = $100025
|
||||
|
||||
; *****************
|
||||
; RTC
|
||||
; *****************
|
||||
|
||||
RTCus = $100100 ; 2 bytes
|
||||
RTCms = $100102 ; 2 bytes
|
||||
RTCsec = $100104 ; 1 byte
|
||||
RTCmin = $100105 ; 1 byte
|
||||
RTChour = $100106 ; 1 byte
|
||||
RTCday = $100108 ; 2 bytes
|
||||
|
||||
; *****************
|
||||
; I2C
|
||||
; *****************
|
||||
|
||||
I2C2io = $100014
|
||||
I2C2ctrl = $100015 ; read: b3 = busy; write: $01 = start, $02 = stop, $04 = receive, $08 = send, $44 = receive/ack
|
||||
|
||||
; *****************
|
||||
; SPI
|
||||
; *****************
|
||||
|
||||
SPI2io = $10001C
|
||||
SPI2ctrl = $10001D ; read: b3 = tx busy, b2 = rx full; write: $01 = start, $00 = stop; init = $00
|
||||
SPI2ctrl2 = $10001E ; init = $00
|
||||
SPI2ctrl3 = $10001F ; init = $05
|
||||
|
||||
|
||||
; *****************
|
||||
; VDC
|
||||
; *****************
|
||||
|
||||
VDCio = $100120 ; read: 1 byte, write: 1 or 2 bytes
|
||||
|
||||
; *****************
|
||||
; FDC
|
||||
; *****************
|
||||
|
||||
FDCio = $090004
|
||||
FDCstat = $090005 ; b7=0 = tx busy
|
||||
|
||||
|
||||
|
18
platforms/Neon816/Neon816.l
Normal file
18
platforms/Neon816/Neon816.l
Normal file
@ -0,0 +1,18 @@
|
||||
FEATURES {
|
||||
STARTADDRESS: default = $200000;
|
||||
}
|
||||
|
||||
MEMORY {
|
||||
ROM: start = $200000, size = $10000, fillval=$FF, file = %O;
|
||||
ZP: start = $0000, size = $100;
|
||||
}
|
||||
|
||||
SEGMENTS {
|
||||
FStartup: load=ROM, type=ro, fillval=$00;
|
||||
FSystem: load=ROM, type=ro, fillval=$00;
|
||||
FCode: load=ROM, type=ro, fillval=$00, optional=yes;
|
||||
ROMBOOT: load=ROM, type=ro, offset=$FF00;
|
||||
VECTORS: load=ROM, type=ro, offset=$FFE0;
|
||||
ZEROPAGE: load=ZP, type=bss;
|
||||
}
|
||||
|
44
platforms/Neon816/Neon816.s
Normal file
44
platforms/Neon816/Neon816.s
Normal file
@ -0,0 +1,44 @@
|
||||
.p816
|
||||
.a16
|
||||
.i16
|
||||
.include "macros.inc"
|
||||
.include "./Neon816-hw.inc"
|
||||
.import _Forth_initialize
|
||||
.import _Forth_ui
|
||||
.import _system_interface
|
||||
|
||||
.pushseg
|
||||
.segment "FStartup"
|
||||
.proc startup
|
||||
clc
|
||||
xce
|
||||
phk
|
||||
plb
|
||||
rep #SHORT_A|SHORT_I
|
||||
.a16
|
||||
.i16
|
||||
lda #$0000 ; direct page for Forth
|
||||
tcd
|
||||
lda #.hiword(Neon_RAM1+$020000) ; top of dictionary memory
|
||||
pha
|
||||
lda #.loword(Neon_RAM1+$020000)
|
||||
pha
|
||||
lda #.hiword(Neon_RAM1+$010000) ; bottom of dictionary
|
||||
pha
|
||||
lda #.loword(Neon_RAM1+$010000)
|
||||
pha
|
||||
lda #$0400 ; first usable stack cell (relative to direct page)
|
||||
pha
|
||||
lda #$0204 ; last usable stack cell+1 (relative to direct page)
|
||||
pha
|
||||
lda #$01EF ; return stack first usable byte
|
||||
pha
|
||||
lda #.hiword(_system_interface)
|
||||
pha
|
||||
lda #.loword(_system_interface)
|
||||
pha
|
||||
jsl _Forth_initialize
|
||||
jsl _Forth_ui
|
||||
jmp startup
|
||||
.endproc
|
||||
.popseg
|
66
platforms/Neon816/README.md
Normal file
66
platforms/Neon816/README.md
Normal file
@ -0,0 +1,66 @@
|
||||
|
||||
# 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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## 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.
|
||||
|
||||
## Installation
|
||||
|
||||
**THIS WILL OVERWRITE THE NEON'S ORIGINAL FIRMWARE.**
|
||||
|
||||
**IT IS STRONGLY RECOMMENDED YOU BACK UP THE ORIGINAL FIRMWARE**
|
||||
|
||||
**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``
|
||||
|
||||
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):
|
||||
|
||||
```
|
||||
else if(!strcmp(cmd,"dumprom")) {
|
||||
char* fn=strtok(nullptr," ");
|
||||
char buf[0x40];
|
||||
if(!fn) return;
|
||||
auto st=Releaser(
|
||||
fopen(fn,"w"),
|
||||
[](auto f){if(f) fclose(f);});
|
||||
if(!st) {
|
||||
printf("Could not open file\n");
|
||||
return;
|
||||
}
|
||||
for (int addr=0x200000; addr<0x220000; addr+=sizeof(buf)) {
|
||||
writeHex(addr>>16,2); writeChar(':');
|
||||
writeHex(addr,4); writeChar('#');
|
||||
for (int i=0; i<sizeof(buf); i++) {
|
||||
writeChar('@');
|
||||
unsigned char c=readByte();
|
||||
buf[i]=c;
|
||||
}
|
||||
fwrite(&buf, sizeof(buf), 1, st);
|
||||
printf("%08X\n",addr);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
then start neonprog with ``neonprog /dev/ttyUSBx`` (replace device with actual serial device for FTDI cable.
|
||||
|
||||
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.
|
||||
|
||||
## 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 backup.bin``. This will output two files, ``xaa`` and ``xab`` that are bank $20 and bank $21, respectively. Then run ``hex2bin 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.
|
12
platforms/Neon816/build.sh
Executable file
12
platforms/Neon816/build.sh
Executable file
@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
set -e -x
|
||||
ca65 -I ../../inc Neon816.s -l Neon816.lst
|
||||
ca65 -I ../../inc romboot.s -l romboot.lst
|
||||
../../build.sh Neon816
|
||||
ld65 -C Neon816.l -S 0x8000 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
|
||||
ls -l of816-neon.hex
|
||||
fi
|
||||
|
2
platforms/Neon816/platform-config.inc
Normal file
2
platforms/Neon816/platform-config.inc
Normal file
@ -0,0 +1,2 @@
|
||||
; nothing here yet!
|
||||
|
128
platforms/Neon816/platform-lib.s
Normal file
128
platforms/Neon816/platform-lib.s
Normal file
@ -0,0 +1,128 @@
|
||||
; Platform support library for Neon816
|
||||
;
|
||||
.include "./Neon816-hw.inc"
|
||||
|
||||
.proc _system_interface
|
||||
;wdm 3
|
||||
phx
|
||||
asl
|
||||
tax
|
||||
jmp (.loword(table),x)
|
||||
table: .addr _sf_pre_init
|
||||
.addr _sf_post_init
|
||||
.addr _sf_emit
|
||||
.addr _sf_keyq
|
||||
.addr _sf_key
|
||||
.addr _sf_fcode
|
||||
.addr _sf_reset_all
|
||||
.endproc
|
||||
.export _system_interface
|
||||
|
||||
.proc _sf_success
|
||||
lda #$0000
|
||||
tay
|
||||
clc
|
||||
rtl
|
||||
.endproc
|
||||
|
||||
.proc _sf_fail
|
||||
ldy #.loword(-21)
|
||||
lda #.hiword(-21)
|
||||
sec
|
||||
rtl
|
||||
.endproc
|
||||
|
||||
|
||||
.proc _sf_pre_init
|
||||
; NeonFORTH does this, presumably to initialize the serial port
|
||||
sep #SHORT_A
|
||||
.a8
|
||||
lda #$8D
|
||||
sta f:SERctrlA
|
||||
lda #$06
|
||||
sta f:SERctrlB
|
||||
lda #$00
|
||||
sta f:SERctrlC
|
||||
rep #SHORT_A
|
||||
.a16
|
||||
plx
|
||||
jmp _sf_success
|
||||
.endproc
|
||||
|
||||
.proc _sf_post_init
|
||||
plx
|
||||
jmp _sf_success
|
||||
.endproc
|
||||
|
||||
.proc _sf_emit
|
||||
plx ; get forth SP
|
||||
jsr _popay ; grab the top item
|
||||
phx ; and save new SP
|
||||
sep #SHORT_A
|
||||
.a8
|
||||
tya
|
||||
sta f:SERio
|
||||
: lda f:SERstat
|
||||
bit #$08
|
||||
bne :-
|
||||
rep #SHORT_A
|
||||
.a16
|
||||
plx
|
||||
jmp _sf_success
|
||||
.endproc
|
||||
|
||||
.proc _sf_keyq
|
||||
ldy #$0000 ; anticipate false
|
||||
sep #SHORT_A
|
||||
.a8
|
||||
lda f:SERstat ; b0=1 if data ready
|
||||
ror
|
||||
bcc :+
|
||||
iny
|
||||
: rep #SHORT_A
|
||||
.a16
|
||||
tya
|
||||
plx
|
||||
jsr _pushay
|
||||
jmp _sf_success
|
||||
.endproc
|
||||
|
||||
.proc _sf_key
|
||||
sep #SHORT_A
|
||||
.a8
|
||||
: lda f:SERstat
|
||||
ror
|
||||
bcc :-
|
||||
lda f:SERio
|
||||
rep #SHORT_A
|
||||
.a16
|
||||
and #$00FF
|
||||
tay
|
||||
lda #$0000
|
||||
plx
|
||||
jsr _pushay
|
||||
jmp _sf_success
|
||||
.endproc
|
||||
|
||||
.proc _sf_fcode
|
||||
.if include_fcode
|
||||
ldy #.loword(list)
|
||||
lda #.hiword(list)
|
||||
.else
|
||||
lda #$0000
|
||||
tay
|
||||
.endif
|
||||
plx
|
||||
jsr _pushay
|
||||
jmp _sf_success
|
||||
.if include_fcode
|
||||
list:
|
||||
.dword 0
|
||||
.endif
|
||||
.endproc
|
||||
|
||||
; TODO....
|
||||
.proc _sf_reset_all
|
||||
plx
|
||||
jmp _sf_fail
|
||||
.endproc
|
2
platforms/Neon816/platform-words.s
Normal file
2
platforms/Neon816/platform-words.s
Normal file
@ -0,0 +1,2 @@
|
||||
; Platform support dictionary words for Neon816
|
||||
|
46
platforms/Neon816/romboot.s
Normal file
46
platforms/Neon816/romboot.s
Normal file
@ -0,0 +1,46 @@
|
||||
.p816
|
||||
.a16
|
||||
.i16
|
||||
.include "macros.inc"
|
||||
.include "./Neon816-hw.inc"
|
||||
|
||||
.segment "ROMBOOT"
|
||||
.proc romboot
|
||||
clc
|
||||
xce
|
||||
rep #SHORT_A|SHORT_I
|
||||
.a16
|
||||
.i16
|
||||
lda #$01FF
|
||||
tcs
|
||||
; Set up MMU for bank 0
|
||||
ldx #$001C
|
||||
lda #$8000
|
||||
: sta f:NeonMMU,x
|
||||
dex
|
||||
dex
|
||||
bpl :-
|
||||
jml f:Neon_ROM
|
||||
.endproc
|
||||
|
||||
.segment "VECTORS"
|
||||
.proc vectors
|
||||
; native mode vectors
|
||||
.word $FFFF ; FFE0 - reserved
|
||||
.word $FFFF ; FFE2 - reserved
|
||||
.word $FFFF ; FFE4 - COP
|
||||
.word $FFFF ; FFE6 - BRK
|
||||
.word $FFFF ; FFE8 - ABORT
|
||||
.word $FFFF ; FFEA - NMI
|
||||
.word $FFFF ; FFEC - reserved
|
||||
.word $FFFF ; FFEE - IRQ
|
||||
; emulation mode vectors
|
||||
.word $FFFF ; FFF0 - reserved
|
||||
.word $FFFF ; FFF2 - reserved
|
||||
.word $FFFF ; FFF4 - COP
|
||||
.word $FFFF ; FFF6 - reserved
|
||||
.word $FFFF ; FFF8 - ABORT
|
||||
.word $FFFF ; FFFA - NMI
|
||||
.word .loword(romboot) ; FFFC - RESET
|
||||
.word $FFFF ; FFFE - IRQ/BRK
|
||||
.endproc
|
Loading…
x
Reference in New Issue
Block a user