mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-26 09:38:06 +11:00
Compare commits
No commits in common. "aad8efeff7262177172f03b1deadfc01c8667a9d" and "585e9f3b6e0fadd70063127a19bdf33b458206b5" have entirely different histories.
aad8efeff7
...
585e9f3b6e
@ -103,23 +103,3 @@ stored where specified. For example, `input x` stores the result of the
|
|||||||
evaluation in variable `x`. Before the variable name, a quoted string literal
|
evaluation in variable `x`. Before the variable name, a quoted string literal
|
||||||
can be specified. In that case, that string will be printed as-is just before
|
can be specified. In that case, that string will be printed as-is just before
|
||||||
the prompt.
|
the prompt.
|
||||||
|
|
||||||
**peek/deek**: Put the value at specified memory address into specified
|
|
||||||
variable. peek is for a single byte, deek is for a word (little endian). For
|
|
||||||
example, `peek 42 a` puts the byte value contained in memory address 0x002a
|
|
||||||
into variable `a`. `deek 42 a` does the same as peek, but also puts the value
|
|
||||||
of 0x002b into `a`'s MSB.
|
|
||||||
|
|
||||||
**poke/doke**: Put the value of specified expression into specified memory
|
|
||||||
address. For example, `poke 42 0x102+0x40` puts `0x42` in memory address
|
|
||||||
0x2a (MSB is ignored) and `doke 42 0x102+0x40` does the same as poke, but also
|
|
||||||
puts `0x01` in memory address 0x2b.
|
|
||||||
|
|
||||||
**in**: Same thing as `peek`, but for a I/O port. `in 42 a` generates an input
|
|
||||||
I/O on port 42 and stores the byte result in `a`.
|
|
||||||
|
|
||||||
**out**: Same thing as `poke`, but for a I/O port. `out 42 1+2` generates an
|
|
||||||
output I/O on port 42 with value 3.
|
|
||||||
|
|
||||||
**sleep**: Sleep a number of "units" specified by the supplied expression. A
|
|
||||||
"unit" depends on the CPU clock speed. At 4MHz, it is roughly 8 microseconds.
|
|
||||||
|
@ -56,17 +56,17 @@ basCallCmd:
|
|||||||
; let's see if it's a variable assignment.
|
; let's see if it's a variable assignment.
|
||||||
call varTryAssign
|
call varTryAssign
|
||||||
ret z ; Done!
|
ret z ; Done!
|
||||||
push de ; --> lvl 1.
|
; Second, get cmd length
|
||||||
ld de, SCRATCHPAD
|
call fnWSIdx
|
||||||
call rdWord
|
cp 7
|
||||||
; cmdname to find in (DE)
|
jp nc, unsetZ ; Too long, can't possibly fit anything.
|
||||||
; How lucky, we have a legitimate use of "ex (sp), hl"! We have the
|
; A contains whitespace IDX, save it in B
|
||||||
; cmd table in the stack, which we want in HL and we have the rest of
|
ld b, a
|
||||||
; the cmdline in (HL), which we want in the stack!
|
ex de, hl
|
||||||
ex (sp), hl
|
|
||||||
inc hl \ inc hl
|
inc hl \ inc hl
|
||||||
.loop:
|
.loop:
|
||||||
call strcmp
|
ld a, b ; whitespace IDX
|
||||||
|
call strncmp
|
||||||
jr z, .found
|
jr z, .found
|
||||||
ld a, 8
|
ld a, 8
|
||||||
call addHL
|
call addHL
|
||||||
@ -74,14 +74,15 @@ basCallCmd:
|
|||||||
cp 0xff
|
cp 0xff
|
||||||
jr nz, .loop
|
jr nz, .loop
|
||||||
; not found
|
; not found
|
||||||
pop hl ; <-- lvl 1
|
|
||||||
jp unsetZ
|
jp unsetZ
|
||||||
.found:
|
.found:
|
||||||
dec hl \ dec hl
|
dec hl \ dec hl
|
||||||
call intoHL
|
call intoHL
|
||||||
push hl \ pop ix
|
push hl \ pop ix
|
||||||
; Bring back rest of the command string from the stack
|
; Bring back command string from DE to HL
|
||||||
pop hl ; <-- lvl 1
|
ex de, hl
|
||||||
|
ld a, b ; cmd's length
|
||||||
|
call addHL
|
||||||
call rdSep
|
call rdSep
|
||||||
jp (ix)
|
jp (ix)
|
||||||
|
|
||||||
@ -266,89 +267,6 @@ basINPUT:
|
|||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
ret
|
ret
|
||||||
|
|
||||||
basPEEK:
|
|
||||||
call basDEEK
|
|
||||||
ret nz
|
|
||||||
ld d, 0
|
|
||||||
call varAssign
|
|
||||||
cp a ; ensure Z
|
|
||||||
ret
|
|
||||||
|
|
||||||
basPOKE:
|
|
||||||
call rdExpr
|
|
||||||
ret nz
|
|
||||||
; peek address in IX. Save it for later
|
|
||||||
push ix ; --> lvl 1
|
|
||||||
call rdSep
|
|
||||||
call rdExpr
|
|
||||||
push ix \ pop hl
|
|
||||||
pop ix ; <-- lvl 1
|
|
||||||
ret nz
|
|
||||||
; Poke!
|
|
||||||
ld (ix), l
|
|
||||||
ret
|
|
||||||
|
|
||||||
basDEEK:
|
|
||||||
call rdExpr
|
|
||||||
ret nz
|
|
||||||
; peek address in IX. Let's peek and put result in DE
|
|
||||||
ld e, (ix)
|
|
||||||
ld d, (ix+1)
|
|
||||||
call rdSep
|
|
||||||
ld a, (hl)
|
|
||||||
call varChk
|
|
||||||
ret nz ; not in variable range
|
|
||||||
; All good assign
|
|
||||||
call varAssign
|
|
||||||
cp a ; ensure Z
|
|
||||||
ret
|
|
||||||
|
|
||||||
basDOKE:
|
|
||||||
call basPOKE
|
|
||||||
ld (ix+1), h
|
|
||||||
ret
|
|
||||||
|
|
||||||
basOUT:
|
|
||||||
call rdExpr
|
|
||||||
ret nz
|
|
||||||
; out address in IX. Save it for later
|
|
||||||
push ix ; --> lvl 1
|
|
||||||
call rdSep
|
|
||||||
call rdExpr
|
|
||||||
push ix \ pop hl
|
|
||||||
pop bc ; <-- lvl 1
|
|
||||||
ret nz
|
|
||||||
; Out!
|
|
||||||
out (c), l
|
|
||||||
cp a ; ensure Z
|
|
||||||
ret
|
|
||||||
|
|
||||||
basIN:
|
|
||||||
call rdExpr
|
|
||||||
ret nz
|
|
||||||
push ix \ pop bc
|
|
||||||
ld d, 0
|
|
||||||
in e, (c)
|
|
||||||
call rdSep
|
|
||||||
ld a, (hl)
|
|
||||||
call varChk
|
|
||||||
ret nz ; not in variable range
|
|
||||||
; All good assign
|
|
||||||
call varAssign
|
|
||||||
cp a ; ensure Z
|
|
||||||
ret
|
|
||||||
|
|
||||||
basSLEEP:
|
|
||||||
call rdExpr
|
|
||||||
ret nz
|
|
||||||
push ix \ pop hl
|
|
||||||
.loop:
|
|
||||||
ld a, h ; 4T
|
|
||||||
or l ; 4T
|
|
||||||
ret z ; 5T
|
|
||||||
dec hl ; 6T
|
|
||||||
jr .loop ; 12T
|
|
||||||
|
|
||||||
; direct only
|
; direct only
|
||||||
basCmds1:
|
basCmds1:
|
||||||
.dw basBYE
|
.dw basBYE
|
||||||
@ -367,18 +285,4 @@ basCmds2:
|
|||||||
.db "if", 0, 0, 0, 0
|
.db "if", 0, 0, 0, 0
|
||||||
.dw basINPUT
|
.dw basINPUT
|
||||||
.db "input", 0
|
.db "input", 0
|
||||||
.dw basPEEK
|
|
||||||
.db "peek", 0, 0
|
|
||||||
.dw basPOKE
|
|
||||||
.db "poke", 0, 0
|
|
||||||
.dw basDEEK
|
|
||||||
.db "deek", 0, 0
|
|
||||||
.dw basDOKE
|
|
||||||
.db "doke", 0, 0
|
|
||||||
.dw basOUT
|
|
||||||
.db "out", 0, 0, 0
|
|
||||||
.dw basIN
|
|
||||||
.db "in", 0, 0, 0, 0
|
|
||||||
.dw basSLEEP
|
|
||||||
.db "sleep", 0
|
|
||||||
.db 0xff, 0xff, 0xff ; end of table
|
.db 0xff, 0xff, 0xff ; end of table
|
||||||
|
@ -32,6 +32,30 @@ rdSep:
|
|||||||
inc a ; unset Z
|
inc a ; unset Z
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; Find the first whitespace in (HL) and returns its index in A
|
||||||
|
; Sets Z if whitespace is found, unset if end of string was found.
|
||||||
|
; In the case where no whitespace was found, A returns the length of the string.
|
||||||
|
fnWSIdx:
|
||||||
|
push hl
|
||||||
|
push bc
|
||||||
|
ld b, 0
|
||||||
|
.loop:
|
||||||
|
ld a, (hl)
|
||||||
|
call isSep
|
||||||
|
jr z, .found
|
||||||
|
or a
|
||||||
|
jr z, .eos
|
||||||
|
inc hl
|
||||||
|
inc b
|
||||||
|
jr .loop
|
||||||
|
.eos:
|
||||||
|
inc a ; unset Z
|
||||||
|
.found: ; Z already set from isSep
|
||||||
|
ld a, b
|
||||||
|
pop bc
|
||||||
|
pop hl
|
||||||
|
ret
|
||||||
|
|
||||||
; Advance HL to the next separator or to the end of string.
|
; Advance HL to the next separator or to the end of string.
|
||||||
toSep:
|
toSep:
|
||||||
ld a, (hl)
|
ld a, (hl)
|
||||||
@ -61,15 +85,3 @@ rdWord:
|
|||||||
pop de
|
pop de
|
||||||
pop af
|
pop af
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Read word from HL in SCRATCHPAD and then intepret that word as an expression.
|
|
||||||
; Put the result in IX.
|
|
||||||
; Z for success.
|
|
||||||
rdExpr:
|
|
||||||
ld de, SCRATCHPAD
|
|
||||||
call rdWord
|
|
||||||
push hl
|
|
||||||
ex de, hl
|
|
||||||
call parseExpr
|
|
||||||
pop hl
|
|
||||||
ret
|
|
||||||
|
@ -27,7 +27,6 @@ are other recipes related to the RC2014:
|
|||||||
* [Accessing a MicroSD card](sdcard/README.md)
|
* [Accessing a MicroSD card](sdcard/README.md)
|
||||||
* [Assembling binaries](zasm/README.md)
|
* [Assembling binaries](zasm/README.md)
|
||||||
* [Interfacing a PS/2 keyboard](ps2/README.md)
|
* [Interfacing a PS/2 keyboard](ps2/README.md)
|
||||||
* [Replace shell by a BASIC interpreter](basic/README.md)
|
|
||||||
|
|
||||||
## Recipe
|
## Recipe
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
TARGET = os.bin
|
|
||||||
ZASM = ../../../tools/zasm.sh
|
|
||||||
KERNEL = ../../../kernel
|
|
||||||
APPS = ../../../apps
|
|
||||||
|
|
||||||
.PHONY: all
|
|
||||||
all: $(TARGET)
|
|
||||||
$(TARGET): glue.asm
|
|
||||||
$(ZASM) $(KERNEL) $(APPS) < $< > $@
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
|||||||
# BASIC as a shell
|
|
||||||
|
|
||||||
This recipe demonstrate the replacement of the usual shell with the BASIC
|
|
||||||
interpreter supplied in Collapse OS. To make things fun, we play with I/Os
|
|
||||||
using RC2014's Digital I/O module.
|
|
||||||
|
|
||||||
## Gathering parts
|
|
||||||
|
|
||||||
* Same parts as in the base recipe
|
|
||||||
* (Optional) RC2014's Digital I/O module
|
|
||||||
|
|
||||||
The Digital I/O module is only used in the example BASIC code. If you don't
|
|
||||||
have the module, just use BASIC in another fashion.
|
|
||||||
|
|
||||||
## Build the image
|
|
||||||
|
|
||||||
As usual, building `os.bin` is a matter of running `make`. Then, you can get
|
|
||||||
that image to your EEPROM like you did in the base recipe.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Upon boot, you'll directy be in a BASIC prompt. See documentation in
|
|
||||||
`apps/basic/README.md` for details.
|
|
||||||
|
|
||||||
For now, let's have some fun with the Digital I/O module. Type this:
|
|
||||||
|
|
||||||
```
|
|
||||||
> a=0
|
|
||||||
> 10 out 0 a
|
|
||||||
> 20 sleep 0xffff
|
|
||||||
> 30 a=a+1
|
|
||||||
> 40 goto 10
|
|
||||||
> run
|
|
||||||
```
|
|
||||||
|
|
||||||
You now have your Digital I/O lights doing a pretty dance, forever.
|
|
||||||
|
|
||||||
## Looking at the glue code
|
|
||||||
|
|
||||||
If you look at the glue code, you'll see that it's very similar to the one in
|
|
||||||
the base recipe, except that the shell includes have been replaced by the basic
|
|
||||||
includes. Those includes have been copy/pasted from `apps/basic/glue.asm` and
|
|
||||||
`USER_RAMSTART` has been replaced with `STDIO_RAMEND` so that BASIC's memory
|
|
||||||
gets placed properly (that is, right after the kernel's memory).
|
|
||||||
|
|
||||||
Simple, isn't it?
|
|
@ -1,56 +0,0 @@
|
|||||||
.equ RAMSTART 0x8000
|
|
||||||
.equ RAMEND 0xffff
|
|
||||||
.equ ACIA_CTL 0x80 ; Control and status. RS off.
|
|
||||||
.equ ACIA_IO 0x81 ; Transmit. RS on.
|
|
||||||
.equ DIGIT_IO 0x00 ; digital I/O's port
|
|
||||||
|
|
||||||
jp init
|
|
||||||
|
|
||||||
; interrupt hook
|
|
||||||
.fill 0x38-$
|
|
||||||
jp aciaInt
|
|
||||||
|
|
||||||
.inc "err.h"
|
|
||||||
.inc "ascii.h"
|
|
||||||
.inc "core.asm"
|
|
||||||
.inc "str.asm"
|
|
||||||
.equ ACIA_RAMSTART RAMSTART
|
|
||||||
.inc "acia.asm"
|
|
||||||
|
|
||||||
.equ STDIO_RAMSTART ACIA_RAMEND
|
|
||||||
.equ STDIO_GETC aciaGetC
|
|
||||||
.equ STDIO_PUTC aciaPutC
|
|
||||||
.inc "stdio.asm"
|
|
||||||
|
|
||||||
; *** BASIC ***
|
|
||||||
|
|
||||||
; RAM space used in different routines for short term processing.
|
|
||||||
.equ SCRATCHPAD_SIZE 0x20
|
|
||||||
.equ SCRATCHPAD STDIO_RAMEND
|
|
||||||
.inc "lib/util.asm"
|
|
||||||
.inc "lib/ari.asm"
|
|
||||||
.inc "lib/parse.asm"
|
|
||||||
.inc "lib/fmt.asm"
|
|
||||||
.equ EXPR_PARSE parseLiteralOrVar
|
|
||||||
.inc "lib/expr.asm"
|
|
||||||
.inc "basic/util.asm"
|
|
||||||
.inc "basic/parse.asm"
|
|
||||||
.inc "basic/tok.asm"
|
|
||||||
.equ VAR_RAMSTART SCRATCHPAD+SCRATCHPAD_SIZE
|
|
||||||
.inc "basic/var.asm"
|
|
||||||
.equ BUF_RAMSTART VAR_RAMEND
|
|
||||||
.inc "basic/buf.asm"
|
|
||||||
.equ BAS_RAMSTART BUF_RAMEND
|
|
||||||
.inc "basic/main.asm"
|
|
||||||
|
|
||||||
init:
|
|
||||||
di
|
|
||||||
; setup stack
|
|
||||||
ld sp, RAMEND
|
|
||||||
im 1
|
|
||||||
|
|
||||||
call aciaInit
|
|
||||||
ei
|
|
||||||
jp basStart
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user