1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 03:18:05 +11:00

Compare commits

...

6 Commits

Author SHA1 Message Date
Virgil Dupras
8d5c26f299 ti/kbd: add alpha support
no a-lock or lowercase yet.

ref #41
2019-11-08 15:45:45 -05:00
Virgil Dupras
ca8b315e9d ti/kbd: widen char detection
no alpha yet.

ref #41
2019-11-08 14:58:29 -05:00
Virgil Dupras
dca6ce4e8e ti/kbd: begin GetC implementation
For now, only digits are scanned. Lifted from my "tiseg7" example.

ref #41
2019-11-08 14:04:56 -05:00
Virgil Dupras
6a4bddc493 ti/lcd: ensure that variables are initialized 2019-11-08 11:45:37 -05:00
Virgil Dupras
a3c47f6272 Add tests for parseArgs 2019-11-08 10:53:52 -05:00
Virgil Dupras
e972dfe220 Add test documentation 2019-11-08 10:37:52 -05:00
7 changed files with 221 additions and 27 deletions

View File

@ -148,7 +148,7 @@
... ...
. .
. .
... ....
. . . .
. . . .
... ...

Binary file not shown.

View File

@ -6,22 +6,108 @@
.equ KBD_PORT 0x01 .equ KBD_PORT 0x01
; *** Code *** ; *** Code ***
; Wait for a digit to be pressed and sets the A register ASCII value
; corresponding to that key press.
;
; This routine waits for a key to be pressed, but before that, it waits for
; all keys to be de-pressed. It does that to ensure that two calls to
; waitForKey only go through after two actual key presses (otherwise, the user
; doesn't have enough time to de-press the button before the next waitForKey
; routine registers the same key press as a second one).
;
; Sending 0xff to the port resets the keyboard, and then we have to send groups ; Sending 0xff to the port resets the keyboard, and then we have to send groups
; we want to "listen" to, with a 0 in the group bit. Thus, to know if *any* key ; we want to "listen" to, with a 0 in the group bit. Thus, to know if *any* key
; is pressed, we send 0xff to reset the keypad, then 0x00 to select all groups, ; is pressed, we send 0xff to reset the keypad, then 0x00 to select all groups,
; if the result isn't 0xff, at least one key is pressed. ; if the result isn't 0xff, at least one key is pressed.
waitForKey: kbdGetC:
push af push bc
push hl
ld a, 0xff
out (KBD_PORT), a
ld a, 0x00
out (KBD_PORT), a
; During this GetC loop, register C holds the modificators (Alpha, 2nd)
ld c, 0
; loop until a digit is pressed
.loop: .loop:
in a, (KBD_PORT) ld hl, .dtbl
inc a ; if a was 0xff, will become 0 (z test) ; we go through the 7 rows of the table
jr z, .loop ; zero? nothing pressed ld b, 7
; is alpha mod enabled?
bit 0, c
jr z, .inner ; unset? skip next
ld hl, .atbl ; set? we're in alpha mode
.inner:
ld a, (hl) ; group mask
call .get
cp 0xff
jr nz, .something
; nothing for that group, let's scan the next group
ld a, 9
call addHL ; go to next row
djnz .inner
; found nothing, loop
jr .loop
.something:
; We have something on that row! Let's find out which char. Register A
; currently contains a mask with the pressed char bit unset.
ld b, 8
inc hl
.findchar:
rrca ; is next bit unset?
jr nc, .gotit ; yes? we have our char!
inc hl
djnz .findchar
.gotit:
ld a, (hl)
or a ; is char 0?
jr z, .loop ; yes? unsupported. loop.
cp 0x80 ; is it alpha?
jr nz, .notalpha
set 0, c
jr .loop
.notalpha:
pop af ; wait until all keys are de-pressed
push af ; --> lvl 1
.wait:
xor a
call .get
inc a ; if a was 0xff, will become 0 (nz test)
jr nz, .wait ; non-zero? something is pressed
pop af ; <-- lvl 1
pop hl
pop bc
ret ret
.get:
ex af, af'
ld a, 0xff
di
out (KBD_PORT), a
ex af, af'
out (KBD_PORT), a
in a, (KBD_PORT)
ei
ret
; digits table. each row represents a group. first item is group mask.
; 0 means unsupported. no group 7 because it has no keys.
; 0x80 is a special value for ALPHA key which is never returned directly.
.dtbl:
.db 0xfe, 0, 0, 0, 0, 0, 0, 0, 0
.db 0xfd, 0x0d, '+' ,'-' ,'*', '/', '^', 0, 0
.db 0xfb, 0, '3', '6', '9', ')', 0, 0, 0
.db 0xf7, '.', '2', '5', '8', '(', 0, 0, 0
.db 0xef, '0', '1', '4', '7', ',', 0, 0, 0
.db 0xdf, 0, 0, 0, 0, 0, 0, 0, 0x80
.db 0xbf, 0, 0, 0, 0, 0, 0, 0, 0x7f
; alpha table. same as .dtbl, for when we're in alpha mode.
.atbl:
.db 0xfe, 0, 0, 0, 0, 0, 0, 0, 0
.db 0xfd, 0x0d, '"' ,'W' ,'R', 'M', 'H', 0, 0
.db 0xfb, '?', 0, 'V', 'Q', 'L', 'G', 0, 0
.db 0xf7, ':', 'Z', 'U', 'P', 'K', 'F', 'C', 0
.db 0xef, '_', 'Y', 'T', 'O', 'J', 'E', 'B', 0
.db 0xdf, 0, 'X', 'S', 'N', 'I', 'D', 'A', 0x80
.db 0xbf, 0, 0, 0, 0, 0, 0, 0, 0x7f

View File

@ -19,6 +19,7 @@
.equ LCD_CMD_XINC 0x05 .equ LCD_CMD_XINC 0x05
.equ LCD_CMD_YINC 0x07 .equ LCD_CMD_YINC 0x07
.equ LCD_CMD_COL 0x20 .equ LCD_CMD_COL 0x20
.equ LCD_CMD_ZOFFSET 0x40
.equ LCD_CMD_ROW 0x80 .equ LCD_CMD_ROW 0x80
.equ LCD_CMD_CONTRAST 0xc0 .equ LCD_CMD_CONTRAST 0xc0
@ -30,6 +31,10 @@
; *** Code *** ; *** Code ***
lcdInit: lcdInit:
; Initialize variables
xor a
ld (LCD_CURROW), a
; Enable the LCD ; Enable the LCD
ld a, LCD_CMD_ENABLE ld a, LCD_CMD_ENABLE
call lcdWait call lcdWait

View File

@ -30,7 +30,7 @@
.inc "ti/lcd.asm" .inc "ti/lcd.asm"
.inc "ti/kbd.asm" .inc "ti/kbd.asm"
.equ STDIO_RAMSTART LCD_RAMEND .equ STDIO_RAMSTART LCD_RAMEND
.equ STDIO_GETC GetC .equ STDIO_GETC kbdGetC
.equ STDIO_PUTC lcdPutC .equ STDIO_PUTC lcdPutC
.inc "stdio.asm" .inc "stdio.asm"
@ -66,10 +66,6 @@ main:
call shellInit call shellInit
jp shellLoop jp shellLoop
GetC:
call waitForKey
jr boot
handleInterrupt: handleInterrupt:
di di
push af push af

42
tools/tests/README.md Normal file
View File

@ -0,0 +1,42 @@
# Testing Collapse OS
This folder contains Collapse OS' automated testing suite. To run, it needs
`tools/emul` to be built. You can run all tests with `make`.
## zasm
This folder tests zasm's assembling capabilities by assembling test source files
and compare the results with expected binaries. These binaries used to be tested
with a golden standard assembler, scas, but at some point compatibility with
scas was broken, so we test against previously generated binaries, making those
tests essentially regression tests.
Those reference binaries sometimes change, especially when we update code in
core libraries because some tests include them. In this case, we have to update
binaries to the new expected value by being extra careful not to introduce a
regression in test references.
## unit
Those tests target specific routines to test and test them using
`tools/emul/runbin` which:
1. Loads the specified binary
2. Runs it until it halts
3. Verifies that `A` is zero. If it's not, we're in error and we display the
value of `A`.
Test source code has no harnessing and is written in a very "hands on" approach.
At the moment, debugging a test failure is a bit tricky because the error code
often doesn't tell us much.
The convention is to keep a `testNum` counter variable around and call
`nexttest` after each success so that we can easily have an idea of where we
fail.
Then, if you need to debug the cause of a failure, well, you're on your own.
However, there are tricks.
1. Run `unit/runtests.sh <name of file to test>` to target a specific test unit.
2. Insert a `halt` to see the value of `A` at any given moment: it will be your
reported error code (if 0, runbin will report a success).

View File

@ -8,14 +8,19 @@ zasmGetPC:
testNum: .db 1 testNum: .db 1
sFoo: .db "Foo", 0
saB: .db "aB", 0
s99: .db "99", 0
test: test:
ld hl, 0xffff ld hl, 0xffff
ld sp, hl ld sp, hl
call testParseHex
call testParseHexPair
call testParseArgs
; success
xor a
halt
testParseHex:
ld a, '8' ld a, '8'
call parseHex call parseHex
jp c, fail jp c, fail
@ -34,29 +39,86 @@ test:
call parseHex call parseHex
jp nc, fail jp nc, fail
call nexttest call nexttest
ret
ld hl, s99 testParseHexPair:
ld hl, .s99
call parseHexPair call parseHexPair
jp c, fail jp c, fail
cp 0x99 cp 0x99
jp nz, fail jp nz, fail
call nexttest call nexttest
ld hl, saB ld hl, .saB
call parseHexPair call parseHexPair
jp c, fail jp c, fail
cp 0xab cp 0xab
jp nz, fail jp nz, fail
call nexttest call nexttest
ld hl, sFoo ld hl, .sFoo
call parseHexPair call parseHexPair
jp nc, fail jp nc, fail
call nexttest call nexttest
ret
; success .sFoo: .db "Foo", 0
xor a .saB: .db "aB", 0
halt .s99: .db "99", 0
testParseArgs:
ld hl, .t1+6
ld de, .t1
ld iy, .t1+3
call .testargs
ld hl, .t2+6
ld de, .t2
ld iy, .t2+3
call .testargs
ld hl, .t3+6
ld de, .t3
ld iy, .t3+3
call .testargs
ret
; HL and DE must be set, and IY must point to expected results in IX
.testargs:
ld ix, sandbox
call parseArgs
jp nz, fail
ld a, (ix)
cp (iy)
jp nz, fail
ld a, (ix+1)
cp (iy+1)
jp nz, fail
ld a, (ix+2)
cp (iy+2)
jp nz, fail
jp nexttest
; Test data format: 3 bytes specs, 3 bytes expected (IX), then the arg string.
; Empty args with empty specs
.t1:
.db 0b0000, 0b0000, 0b0000
.db 0, 0, 0
.db 0
; One arg, one byte spec
.t2:
.db 0b0001, 0b0000, 0b0000
.db 0xe4, 0, 0
.db "e4", 0
; 3 args, 3 bytes spec
.t3:
.db 0b0001, 0b0001, 0b0001
.db 0xe4, 0xab, 0x99
.db "e4 ab 99", 0
nexttest: nexttest:
ld a, (testNum) ld a, (testNum)
@ -67,3 +129,6 @@ nexttest:
fail: fail:
ld a, (testNum) ld a, (testNum)
halt halt
; used as RAM
sandbox: