diff --git a/.gitignore b/.gitignore index d497553..991145c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,6 @@ t *.po romfs .DS_Store +*.hex +of816-neon.bin diff --git a/platforms/Neon816/Neon816-hw.inc b/platforms/Neon816/Neon816-hw.inc index 56dcd88..10ccf54 100644 --- a/platforms/Neon816/Neon816-hw.inc +++ b/platforms/Neon816/Neon816-hw.inc @@ -1,6 +1,31 @@ +; 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 ; ***************** diff --git a/platforms/Neon816/Neon816.l b/platforms/Neon816/Neon816.l index a6261ce..e8657a1 100644 --- a/platforms/Neon816/Neon816.l +++ b/platforms/Neon816/Neon816.l @@ -1,16 +1,18 @@ FEATURES { - STARTADDRESS: default = $0000; + STARTADDRESS: default = $200000; } MEMORY { - ROM: start = $0000, size = $10000, file = %O; + ROM: start = $200000, size = $10000, fillval=$FF, file = %O; ZP: start = $0000, size = $100; } SEGMENTS { - FStartup: load=ROM,type=ro; - FSystem: load=ROM, type=ro; - FCode: load=ROM, type=ro, optional=yes; + 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; } diff --git a/platforms/Neon816/Neon816.s b/platforms/Neon816/Neon816.s index a205b0d..53b3eb1 100644 --- a/platforms/Neon816/Neon816.s +++ b/platforms/Neon816/Neon816.s @@ -7,65 +7,31 @@ .import _Forth_ui .import _system_interface -; 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 - .pushseg .segment "FStartup" .proc startup clc xce - rep #SHORT_A|SHORT_I - .a16 - .i16 - ; MMU setup, maybe. Found at page $FF in Neon bank 0 - ldx #$001C - lda #$8000 -: sta f:NeonMMU,x - dex - dex - bpl :- - ; NeonFORTH does this, presumably to initialize the serial port - sep #SHORT_A ; not necessary unless we were already native & long - .a8 - lda #$8D - sta f:SERctrlA - lda #$06 - sta f:SERctrlB - lda #$00 - sta f:SERctrlC + phk + plb rep #SHORT_A|SHORT_I .a16 .i16 lda #$0000 ; direct page for Forth tcd - lda #.hiword($0A0000) ; top of dictionary memory + lda #.hiword(Neon_RAM1+$020000) ; top of dictionary memory pha - lda #.loword($0A0000) + lda #.loword(Neon_RAM1+$020000) pha - lda #.hiword($090000) ; bottom of dictionary + lda #.hiword(Neon_RAM1+$010000) ; bottom of dictionary pha - lda #.loword($090000) + lda #.loword(Neon_RAM1+$010000) pha - lda #$0200 ; first usable stack cell (relative to direct page) + lda #$0400 ; first usable stack cell (relative to direct page) pha - lda #$0100 ; last usable stack cell+1 (relative to direct page) + lda #$0204 ; last usable stack cell+1 (relative to direct page) pha - lda #$03FF ; return stack first usable byte + lda #$01EF ; return stack first usable byte pha lda #.hiword(_system_interface) pha @@ -73,7 +39,6 @@ pha jsl _Forth_initialize jsl _Forth_ui - brk - .byte $00 + jmp startup .endproc .popseg diff --git a/platforms/Neon816/README.md b/platforms/Neon816/README.md index e387e2a..7af6931 100644 --- a/platforms/Neon816/README.md +++ b/platforms/Neon816/README.md @@ -1,21 +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. +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. -At the time of commit 91af87fa4e42dced1d22d3cb620e84e6edb91817, OF816 for the Neon816 -is configured to run out of any available ROM bank at starting address $0000. It configures -the MMU hopefully like NeonFORTH does, sets the data stack from $0000-$01FF and the return stack from $0200-$03FF. It hopefully also configures the serial port. +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 binary named "forth" that can be started at address $0000 of the -bank it is loaded into. - -At this point nothing further can be done until we have the ability to use the debug port to -load OF816 into the flash ROM. +``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) +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 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. diff --git a/platforms/Neon816/build.sh b/platforms/Neon816/build.sh index d0effbc..480bc0e 100755 --- a/platforms/Neon816/build.sh +++ b/platforms/Neon816/build.sh @@ -1,7 +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 -m forth.map -o forth -ls -l forth +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 diff --git a/platforms/Neon816/platform-lib.s b/platforms/Neon816/platform-lib.s index 3596690..9614307 100644 --- a/platforms/Neon816/platform-lib.s +++ b/platforms/Neon816/platform-lib.s @@ -7,7 +7,7 @@ phx asl tax - jmp (table,x) + jmp (.loword(table),x) table: .addr _sf_pre_init .addr _sf_post_init .addr _sf_emit @@ -34,8 +34,19 @@ table: .addr _sf_pre_init .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 ; we'll see what we need to do + jmp _sf_success .endproc .proc _sf_post_init diff --git a/platforms/Neon816/romboot.s b/platforms/Neon816/romboot.s new file mode 100644 index 0000000..fa0c1ac --- /dev/null +++ b/platforms/Neon816/romboot.s @@ -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