Move AT28 driver to blkfs

And adjust rc2014/eeprom recipe
This commit is contained in:
Virgil Dupras 2020-04-26 15:18:28 -04:00
parent 7c692c1111
commit 865f4f9256
12 changed files with 76 additions and 137 deletions

View File

@ -2,7 +2,8 @@ MASTER INDEX
3 Usage 30 Dictionary 3 Usage 30 Dictionary
70 Implementation notes 100 Block editor 70 Implementation notes 100 Block editor
120 Linker 120 Linker 140 Addressed devices
150 AT28 Driver
200 Z80 assembler 260 Cross compilation 200 Z80 assembler 260 Cross compilation
280 Z80 boot code 350 ACIA driver 280 Z80 boot code 350 ACIA driver
370 SD Card driver 390 Inner core 370 SD Card driver 390 Inner core
@ -14,4 +15,3 @@ MASTER INDEX

10
blk/140 Normal file
View File

@ -0,0 +1,10 @@
Addressed devices
Abstractions to read and write to devices that allow addressed
access. At all times, we have one active "fetch" device and
one active "store" device, A@ and A!.
Those words have the same signature as C@ and C!, and in fact,
initially default to proxy of those words.
Load with "142 LOAD"

1
blk/142 Normal file
View File

@ -0,0 +1 @@
143 144 LOADR

15
blk/143 Normal file
View File

@ -0,0 +1,15 @@
: ADEVMEM+ 0x55 RAM+ @ + ;
: A@* 0 ADEVMEM+ ;
: A!* 2 ADEVMEM+ ;
: ADEV$
H@ 0x55 RAM+ !
4 ALLOT
['] C@ A@* !
['] C! A!* !
;
: A@ A@* @ EXECUTE ;
: A! A!* @ EXECUTE ;

11
blk/144 Normal file
View File

@ -0,0 +1,11 @@
( Same as MOVE, but with A@ and A! )
( src dst u -- )
: AMOVE
( u ) 0 DO
SWAP DUP I + A@ ( dst src x )
ROT SWAP OVER I + ( src dst x dst )
A! ( src dst )
LOOP
2DROP
;

6
blk/150 Normal file
View File

@ -0,0 +1,6 @@
AT28 Driver
Write to an AT28 EEPROM while making sure that proper timing
is followed and verify data integrity.
Load with "151 LOAD"

View File

@ -1,9 +1,7 @@
( With dst being assumed to be an AT28 EEPROM, perform ! ( With dst being assumed to be an AT28 EEPROM, perform !
operation while doing the right thing. Checks data integrity operation while doing the right thing. Checks data integrity
and ABORT on mismatch. and ABORT on mismatch. )
) : AT28! ( n a -- )
( n a -- )
: AT28!
2DUP C! 2DUP C!
( as long as writing operation is running, IO/6 will toggle at each ( as long as writing operation is running, IO/6 will toggle at each
read attempt. We know that write is finished when we read the same read attempt. We know that write is finished when we read the same

View File

@ -1,69 +0,0 @@
( ACIA
Manage I/O from an asynchronous communication interface adapter
(ACIA). provides "EMIT" to put c char on the ACIA as well as
an input buffer. You have to call "~ACIA" on interrupt for
this module to work well.
CONFIGURATION
ACIA_CTL: IO port for the ACIA's control registers
ACIA_IO: IO port for the ACIA's data registers
ACIA_MEM: Address in memory that can be used variables shared
with ACIA's native words. 8 bytes used.
)
0x20 CONSTANT ACIABUFSZ
( Points to ACIA buf )
: ACIA( [ ACIA_MEM 4 + LITN ] ;
( Points to ACIA buf end )
: ACIA) [ ACIA_MEM 6 + LITN ] ;
( Read buf pointer. Pre-inc )
: ACIAR> [ ACIA_MEM LITN ] ;
( Write buf pointer. Post-inc )
: ACIAW> [ ACIA_MEM 2 + LITN ] ;
( This means that if W> == R>, buffer is full.
If R>+1 == W>, buffer is empty. )
: ACIA$
H@ DUP DUP ACIA( ! ACIAR> !
1+ ACIAW> ! ( write index starts one position later )
ACIABUFSZ ALLOT
H@ ACIA) !
( setup ACIA
CR7 (1) - Receive Interrupt enabled
CR6:5 (00) - RTS low, transmit interrupt disabled.
CR4:2 (101) - 8 bits + 1 stop bit
CR1:0 (10) - Counter divide: 64
)
0b10010110 ACIA_CTL PC!
( setup interrupt )
( 4e == INTJUMP )
0xc3 0x4e RAM+ C! ( JP upcode )
['] ~ACIA 0x4f RAM+ !
(im1)
;
: KEY
( inc then fetch )
ACIAR> @ 1+ DUP ACIA) @ = IF
DROP ACIA( @
THEN
( As long as R> == W>-1, it means that buffer is empty )
BEGIN DUP ACIAW> @ = NOT UNTIL
ACIAR> !
ACIAR> @ C@
;
: EMIT
( As long at CTL bit 1 is low, we are transmitting. wait )
BEGIN ACIA_CTL PC@ 0x02 AND UNTIL
( The way is clear, go! )
ACIA_IO PC!
;

View File

@ -1,7 +0,0 @@
# Forth
**WIP** A Forth interpreter. Far from complete, but you can do stuff like
KEY EMIT KEY EMIT
See dictionary.txt for a word reference.

View File

@ -1,34 +0,0 @@
( Addressed devices.
Abstractions to read and write to devices that allow addressed
access. At all times, we have one active "fetch" device and
one active "store" device, A@ and A!.
Those words have the same signature as C@ and C!, and in fact,
initially default to proxy of those words.
)
: ADEVMEM+ 0x55 RAM+ @ + ;
: A@* 0 ADEVMEM+ ;
: A!* 2 ADEVMEM+ ;
: ADEV$
H@ 0x55 RAM+ !
4 ALLOT
['] C@ A@* !
['] C! A!* !
;
: A@ A@* @ EXECUTE ;
: A! A!* @ EXECUTE ;
( Same as MOVE, but with A@ and A! )
( src dst u -- )
: AMOVE
( u ) 0 DO
SWAP DUP I + A@ ( dst src x )
ROT SWAP OVER I + ( src dst x dst )
A! ( src dst )
LOOP
2DROP
;

View File

@ -183,9 +183,15 @@ So, the end of our compiled dict is actually `99de`. Alright, let's extract it:
dd if=memdump bs=1 skip=36192 count=3198 > dict.bin dd if=memdump bs=1 skip=36192 count=3198 > dict.bin
`36192` is `8d60` and `3198` is `99de-8d60`. This needs to be prepended by the `36192` is `8d60` and `3198` is `99de-8d60`. This needs to be prepended by the
boot binary. But that one, we already have. It's `z80c.bin` boot binary. We already have `stage1.bin`, but this binary contains bootstrap
source code we don't need any more. To strip it, we'll need to `dd` it out to
`LATEST`, in my case `098b`:
cat z80c.bin dict.bin > stage2.bin dd if=stage1.bin bs=1 count=2443 > s1pre.bin
Now we can combine our binaries:
cat s1pre.bin dict.bin > stage2.bin
Is it ready to run yet? no. There are 3 adjustments we need to manually make Is it ready to run yet? no. There are 3 adjustments we need to manually make
using our hex editor. using our hex editor.
@ -203,7 +209,12 @@ using our hex editor.
Now are we ready yet? ALMOST! There's one last thing we need to do: add runtime Now are we ready yet? ALMOST! There's one last thing we need to do: add runtime
source. In our case, because we have a compiled dict, the only source we need source. In our case, because we have a compiled dict, the only source we need
to include is `run.fs`: to include is initialization code. We've stripped it from our stage1 earlier,
we need to re-add it.
Look at `xcomp.fs`. You see that `," bla bla bla"` line? That's initialization
code. Copy it to a file like `run.fs` (without the `,"`) and build your final
binary:
cat stage2.bin run.fs > stage2r.bin cat stage2.bin run.fs > stage2r.bin

View File

@ -38,20 +38,19 @@ I don't think you need a schematic. It's really simple.
Stage 2 gives you a full interpreter, but it's missing the "Addressed devices" Stage 2 gives you a full interpreter, but it's missing the "Addressed devices"
module and the AT28 driver. We'll need to assemble a stage 3. module and the AT28 driver. We'll need to assemble a stage 3.
TODO: fix these instructions. They are broken. When you'll have a system with function disk block system, you'll be able to
directly `LOAD` them, but for this recipe, we can't assume you have, so what
you'll have to do is to manually paste the code from the appropriate blocks.
However, now that we have a usable prompt, we can do a lot (be cautious though: Addressed devices are at B140. To know what you have to paste, open the loader
there is no `readln` yet, so you have no backspace), for example, build a block (B142) and see what blocks it loads. For each of the blocks, copy/paste
stage 3 with `readln`. the code in your interpreter.
Copy the unit's source Do the same thing with the AT28 driver (B150)
cat ../../forth/readln.fs | ../../tools/stripfc | xclip If you're doing the real thing and not using the emulator, pasting so much code
at once might freeze up the RC2014, so it is recommended that you use
and just paste it in your terminal. If you're doing the real thing and not `/tools/exec` that let the other side enough time to breathe.
using the emulator, pasting so much code at once might freeze up the RC2014, so
it is recommended that you use `/tools/exec` that let the other side enough
time to breathe.
After your pasting, you'll have a compiled dict of that code in memory. You'll After your pasting, you'll have a compiled dict of that code in memory. You'll
need to relocate it in the same way you did for stage 2, but instead of using need to relocate it in the same way you did for stage 2, but instead of using
@ -59,23 +58,21 @@ need to relocate it in the same way you did for stage 2, but instead of using
`RLDICT`, the word doing the real work. `RLDICT`, the word doing the real work.
`RLDICT` takes 2 arguments, `target` and `offset`. `target` is the first word `RLDICT` takes 2 arguments, `target` and `offset`. `target` is the first word
of your relocated dict. In our case, it's going to be `' INBUFSZ`. `offset` is of your relocated dict. In our case, it's going to be `' ADEVMEM+`. `offset` is
the offset we'll apply to every eligible word references in our dict. In our the offset we'll apply to every eligible word references in our dict. In our
case, that offset is the offset of the *beginning* of the `INBUFSZ` entry (that case, that offset is the offset of the *beginning* of the `ADEVMEM+` entry (that
is, `' INBUFSZ WORD(` minus the offset of the last word (which should be a hook is, `' ADEVMEM+ WORD(` minus the offset of the last word (which should be a hook
word) in the ROM binary. word) in the ROM binary.
That offset can be conveniently fetched from code because it is the value of That offset can be conveniently fetched from code because it is the value of
the `LATEST` constant in stable ABI, which is at offset `0x08`. Therefore, our the `LATEST` constant in stable ABI, which is at offset `0x08`. Therefore, our
offset value is: offset value is:
' INBUFSZ WORD( 0x08 @ - ' ADEVMEM+ WORD( 0x08 @ -
You can now run `RLDICT` and proceed with concatenation (and manual adjustments You can now run `RLDICT` and proceed with concatenation (and manual adjustments
of course) as you did with stage 2. Don't forget to adjust `run.fs` so that it of course) as you did with stage 2. Don't forget to adjust `run.fs` so that it
initializes `RDLN$` instead of creating a minimal `(c<)`. runs `ADEV$`.
Keep that `stage3.bin` around, you will need it for further recipes.
## Writing contents to the AT28 ## Writing contents to the AT28