1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-02 10:30:55 +11:00

Compare commits

..

5 Commits

Author SHA1 Message Date
Virgil Dupras
4c7dfe0dfe Add drv/at28 2020-04-12 21:49:42 -04:00
Virgil Dupras
76e4422796 Add adev unit 2020-04-12 21:49:20 -04:00
Virgil Dupras
d996dd8c9e Add one layer of indirection in subsystem memory management
This allows optional subsystems to not needlessly reserve too much
system memory and it also reduces offsets bookkeeping.
2020-04-12 20:42:00 -04:00
Virgil Dupras
d4f65911c0 rc2014: add notes about stage3.bin 2020-04-12 14:15:06 -04:00
Virgil Dupras
420836276d readln: rename (c<) to (rdln<)
so that it isn't picked up automatically at boot. Only when (c<$) is
called do we override (c<). This fixes tricky boot problems.
2020-04-12 14:01:54 -04:00
10 changed files with 180 additions and 51 deletions

View File

@ -21,6 +21,23 @@ directly, but as part of another word.
"*I*" in description indicates an IMMEDIATE word.
*** Symbols ***
Throughout words, different symbols are used in different contexts, but we try
to been consistent in their use. Here's their definitions:
! - Store
@ - Fetch
$ - Initialize
^ - Arguments in their opposite order
< - Input
> - 1. Pointer in a buffer 2. Opposite of "<".
( - Lower boundary
) - Upper boundary
* - Word indirection (pointer to word)
~ - Container for native code. Usually not an executable word.
? - Is it ...? (example: IMMED?)
*** Defining words ***
(find) a -- a f Read at a and find it in dict. If found, f=1 and
a = wordref. If not found, f=0 and a = string addr.
@ -105,6 +122,16 @@ HERE -- a Push HERE's address
H@ -- a HERE @
MOVE a1 a2 u -- Copy u bytes from a1 to a2, starting with a1, going
up.
*** Addressed devices ***
See usage.txt for details.
ADEV$ -- Initialize adev subsystem
A@ a -- c Indirect C@
A! c a -- Indirect C!
A@* -- a Address for A@ word
A!* -- a Address for A! word
AMOVE src dst u -- Same as MOVE, but with A@ and A!
*** Arithmetic / Bits ***

17
drv/at28.fs Normal file
View File

@ -0,0 +1,17 @@
( With dst being assumed to be an AT28 EEPROM, perform !
operation while doing the right thing. Checks data integrity
and ABORT on mismatch.
)
( a n -- )
: AT28!
2DUP C! SWAP
( 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
value twice. )
BEGIN ( n1 a )
DUP C@ ( n1 a n2 )
OVER C@ ( n1 a n2 n3 )
= UNTIL
( We're finished writing. do we have a mismatch? )
C@ = NOT IF ABORT" mismatch" THEN
;

View File

@ -1 +1 @@
: INIT (c<$) INTERPRET ;
: INIT RDLN$ Z80A$ INTERPRET ;

Binary file not shown.

34
forth/adev.fs Normal file
View File

@ -0,0 +1,34 @@
( 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

@ -8,33 +8,23 @@
routine. )
64 CONSTANT INBUFSZ
( points to INBUF )
: IN( 0x53 RAM+ ;
( points to INBUF's end )
: IN) 0x55 RAM+ ;
: RDLNMEM+ 0x53 RAM+ @ + ;
( current position in INBUF )
: IN> 0x57 RAM+ ;
: IN> 0 RDLNMEM+ ;
( points to INBUF )
: IN( 2 RDLNMEM+ ;
( points to INBUF's end )
: IN) INBUFSZ 2 + RDLNMEM+ ;
( flush input buffer )
( set IN> to IN( and set IN> @ to null )
: (infl) 0 IN( @ DUP IN> ! ! ;
( Initializes the readln subsystem )
: (c<$)
H@ IN( !
INBUFSZ ALLOT
H@ IN) !
( We need two extra bytes. 1 for the last typed 0x0a and
one for the following NULL. )
2 ALLOT
(infl)
;
: (infl) 0 IN( DUP IN> ! ! ;
( handle backspace: go back one char in IN>, if possible, then
emit SPC + BS )
: (inbs)
( already at IN( ? )
IN> @ IN( @ = IF EXIT THEN
IN> @ IN( = IF EXIT THEN
IN> @ 1 - IN> !
SPC BS
;
@ -43,7 +33,7 @@
should continue, that is, whether CR was not met. )
: (rdlnc) ( -- f )
( buffer overflow? same as if we typed a newline )
IN> @ IN) @ = IF 0x0a ELSE KEY THEN ( c )
IN> @ IN) = IF 0x0a ELSE KEY THEN ( c )
( del? same as backspace )
DUP 0x7f = IF DROP 0x8 THEN
( lf? same as cr )
@ -69,14 +59,26 @@
FLAGS @ 0x1 AND NOT IF '>' EMIT SPC THEN
(infl)
BEGIN (rdlnc) NOT UNTIL
LF IN( @ IN> !
LF IN( IN> !
;
( And finally, implement a replacement for the (c<) routine )
: (c<)
: (rdln<)
IN> @ C@ ( c )
( not EOL? good, inc and return )
DUP IF 1 IN> +! EXIT THEN ( c )
( EOL ? readline. we still return typed char though )
(rdln) ( c )
;
( Initializes the readln subsystem )
: RDLN$
( 53 == rdln's memory )
H@ 0x53 RAM+ !
( 2 for IN>, plus 2 for extra bytes after buffer: 1 for
the last typed 0x0a and one for the following NULL. )
INBUFSZ 4 + ALLOT
(infl)
['] (rdln<) 0x0c RAM+ !
;

View File

@ -1,21 +1,11 @@
( Z80 assembler )
( Splits word into msb/lsb, lsb being on TOS )
: SPLITB
256 /MOD SWAP
;
: Z80AMEM+ 0x59 RAM+ @ + ;
( H@ offset at which we consider our PC 0. Used to compute
PC. To have a proper PC, call "H@ ORG !" at the beginning
of your assembly process. )
: ORG 0x59 RAM+ ;
: PC H@ ORG @ - ;
( A, spits an assembled byte, A,, spits an assembled word
Both increase PC. To debug, change C, to .X )
: A, C, ;
: A,, SPLITB A, A, ;
: ORG 0 Z80AMEM+ ;
( Labels are a convenient way of managing relative jump
calculations. Backward labels are easy. It is only a matter
@ -27,13 +17,31 @@
To avoid using dict memory in compilation targets, we
pre-declare label variables here, which means we have a
limited number of it. For now, 6 ought to be enough. )
: L1 2 Z80AMEM+ ;
: L2 4 Z80AMEM+ ;
: L3 6 Z80AMEM+ ;
: L4 8 Z80AMEM+ ;
: L5 10 Z80AMEM+ ;
: L6 12 Z80AMEM+ ;
: L1 0x5b RAM+ ;
: L2 0x5d RAM+ ;
: L3 0x5f RAM+ ;
: L4 0x61 RAM+ ;
: L5 0x63 RAM+ ;
: L6 0x65 RAM+ ;
: Z80A$
( 59 == z80a's memory )
H@ 0x59 RAM+ !
14 ALLOT
;
( Splits word into msb/lsb, lsb being on TOS )
: SPLITB
256 /MOD SWAP
;
: PC H@ ORG @ - ;
( A, spits an assembled byte, A,, spits an assembled word
Both increase PC. To debug, change C, to .X )
: A, C, ;
: A,, SPLITB A, A, ;
( There are 2 label types: backward and forward. For each
type, there are two actions: set and write. Setting a label

View File

@ -89,17 +89,11 @@ RAMSTART INITIAL_SP
+2e BOOT C< PTR
+4e INTJUMP
+51 CURRENTPTR
+53 readln's IN(
+55 readln's IN)
+57 readln's IN>
+59 z80a's ORG
+5b z80a's L1
+5d z80a's L2
+5f z80a's L3
+61 z80a's L4
+63 z80a's L5
+65 z80a's L6
+67 FUTURE USES
+53 readln's variables
+55 adev's variables
+57 FUTURE USES
+59 z80a's variables
+5b FUTURE USES
+70 DRIVERS
+80 RAMEND

View File

@ -214,6 +214,17 @@ And there you have it, a stage2 binary that you've assembled yourself. Now,
here's for your homework: use the same technique to add the contents of
`readln.fs` to stage2 so that you have a full-featured interpreter.
Name it `stage3.bin` (the version without any source code appended and no
`INIT` word defined), you'll need this binary for sub-recipes written for the
RC2014.
Here's a little cheatsheet, but seriously, you should figure most of it
yourself. Tough love they call it.
* `cat stage2.bin pre.fs ../../forth/readln.fs run.fs > stage2r.bin`
* Don't forget `(c<$)`.
* `RLDICT` is like `RLCORE` but with a chosen target.
[rc2014]: https://rc2014.co.uk
[romwrite]: https://github.com/hsoft/romwrite
[stage2]: ../../emul

View File

@ -86,3 +86,39 @@ flag to true. For example, "<>{ <>}" yields true.
To check whether A is in between B and C inclusively, you would write:
A <>{ B 1 - &> C 1 + &< <>}
*** Addressed devices
The adev unit provides a simple but powerful abstraction over C@ and C!: A@ and
A!. These work the same way as C@ and C! (but for performance reasons, aren't
used in core words), but are indirect calls.
Upon initialization, the default to C@ and C!, but can be set to any word
through A@* and A!*.
On top of that, it provides a few core-like words such as AMOVE.
Let's demonstrate its use through a toy example:
> : F! SWAP 1 + SWAP C! ;
> 8 H@ DUMP
:54 0000 0000 0000 0000 ........
> 9 H@ A!
> 8 H@ DUMP
:54 0900 0000 0000 0000 ........
> ' F! A!* !
> 9 H@ 1 + A!
> 8 H@ DUMP
:54 090a 0000 0000 0000 ........
> H@ H@ 2 + 2 AMOVE
> 8 H@ DUMP
:54 090a 0a0b 0000 0000 ........
>
Of course, you might want to end up using adev in this kind of ad-hoc way to
have some kind of mapping function, but what you'll mostly want to to is to
plug device drivers into those words.