Compare commits

...

4 Commits

Author SHA1 Message Date
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 216 additions and 27 deletions

View File

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

Binary file not shown.

View File

@ -6,22 +6,103 @@
.equ KBD_PORT 0x01
; *** Code ***
; Wait for a digit to be pressed and sets the A register to the value (0-9) of
; that digit.
;
; 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
; 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,
; if the result isn't 0xff, at least one key is pressed.
waitForKey:
push af
ld a, 0xff
out (KBD_PORT), a
ld a, 0x00
out (KBD_PORT), a
kbdGetC:
push bc
; loop until a digit is pressed
.loop:
in a, (KBD_PORT)
inc a ; if a was 0xff, will become 0 (z test)
jr z, .loop ; zero? nothing pressed
; When we check for digits, we go through all 3 groups containing them.
; for each group, we load the digit we check for in B and then test the
; bit for that key. If the bit is reset, our key is pressed. we can
; jump to the end, copy B into A and return.
pop af
; check group 2
ld a, 0xfb
call .get
ld b, '3'
bit 1, a
jr z, .end
ld b, '6'
bit 2, a
jr z, .end
ld b, '9'
bit 3, a
jr z, .end
ld a, 0xf7
call .get
ld b, '2'
bit 1, a
jr z, .end
ld b, '5'
bit 2, a
jr z, .end
ld b, '8'
bit 3, a
jr z, .end
; check group 4
ld a, 0xef
call .get
ld b, '0'
bit 0, a
jr z, .end
ld b, '1'
bit 1, a
jr z, .end
ld b, '4'
bit 2, a
jr z, .end
ld b, '7'
bit 3, a
jr z, .end
jr .loop ; nothing happened? loop
.end:
; loop until all keys are de-pressed
.loop2:
xor a
call .get
inc a ; if a was 0xff, will become 0 (nz test)
jr nz, .loop2 ; non-zero? something is pressed
; copy result into A
ld a, b
pop bc
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

View File

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

View File

@ -30,7 +30,7 @@
.inc "ti/lcd.asm"
.inc "ti/kbd.asm"
.equ STDIO_RAMSTART LCD_RAMEND
.equ STDIO_GETC GetC
.equ STDIO_GETC kbdGetC
.equ STDIO_PUTC lcdPutC
.inc "stdio.asm"
@ -66,10 +66,6 @@ main:
call shellInit
jp shellLoop
GetC:
call waitForKey
jr boot
handleInterrupt:
di
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
sFoo: .db "Foo", 0
saB: .db "aB", 0
s99: .db "99", 0
test:
ld hl, 0xffff
ld sp, hl
call testParseHex
call testParseHexPair
call testParseArgs
; success
xor a
halt
testParseHex:
ld a, '8'
call parseHex
jp c, fail
@ -34,29 +39,86 @@ test:
call parseHex
jp nc, fail
call nexttest
ret
ld hl, s99
testParseHexPair:
ld hl, .s99
call parseHexPair
jp c, fail
cp 0x99
jp nz, fail
call nexttest
ld hl, saB
ld hl, .saB
call parseHexPair
jp c, fail
cp 0xab
jp nz, fail
call nexttest
ld hl, sFoo
ld hl, .sFoo
call parseHexPair
jp nc, fail
call nexttest
ret
; success
xor a
halt
.sFoo: .db "Foo", 0
.saB: .db "aB", 0
.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:
ld a, (testNum)
@ -67,3 +129,6 @@ nexttest:
fail:
ld a, (testNum)
halt
; used as RAM
sandbox: