recipes/sms/kbd: use Collapse OS' AVR assembler

This commit is contained in:
Virgil Dupras 2020-02-26 23:10:43 -05:00
parent 64a54c72f8
commit 97dcad9b15
7 changed files with 83 additions and 51 deletions

View File

@ -628,19 +628,19 @@ _parseArgs:
_readBit: _readBit:
ld a, 7 ld a, 7
jr _readExpr jp _readExpr
_readA6: _readA6:
ld a, 0x3f ld a, 0x3f
jr _readExpr jp _readExpr
_readA5: _readA5:
ld a, 0x1f ld a, 0x1f
jr _readExpr jp _readExpr
_readK8: _readK8:
ld a, 0xff ld a, 0xff
jr _readExpr jp _readExpr
_readDouble: _readDouble:
push de push de
@ -707,6 +707,12 @@ _readR5:
push de push de
ld a, (hl) ld a, (hl)
call upcase call upcase
cp 'X'
jr z, .rdXYZ
cp 'Y'
jr z, .rdXYZ
cp 'Z'
jr z, .rdXYZ
cp 'R' cp 'R'
jr nz, .end ; not a register jr nz, .end ; not a register
inc hl inc hl
@ -717,6 +723,34 @@ _readR5:
.end: .end:
pop de pop de
ret ret
.rdXYZ:
; First, let's get a base value, that is, (A-'X'+26)*2, because XL, our
; lowest register, is equivalent to r26.
sub 'X'
rla ; no carry from sub
add a, 26
ld d, a ; store that
inc hl
ld a, (hl)
call upcase
cp 'H'
jr nz, .skip1
; second char is 'H'? our value is +1
inc d
jr .skip2
.skip1:
cp 'L'
jr nz, .end ; not L either? then it's not good
.skip2:
; Good, we have our final value in D and we're almost sure it's a valid
; register. Our only check left is that the 3rd char is a null.
inc hl
ld a, (hl)
or a
jr nz, .end
; we're good
ld a, d
jr .end
; Put DE's LSB into A and, additionally, ensure that the new value is <= ; Put DE's LSB into A and, additionally, ensure that the new value is <=
; than what was previously in A. ; than what was previously in A.

View File

@ -1,12 +1,5 @@
; *** CPU registers aliases *** ; *** CPU registers aliases ***
.equ XH 27
.equ XL 26
.equ YH 29
.equ YL 28
.equ ZH 31
.equ ZL 30
.equ SREG_C 0 ; Carry Flag .equ SREG_C 0 ; Carry Flag
.equ SREG_Z 1 ; Zero Flag .equ SREG_Z 1 ; Zero Flag
.equ SREG_N 2 ; Negative Flag .equ SREG_N 2 ; Negative Flag

View File

@ -1,11 +1,13 @@
PROGNAME = ps2ctl PROGNAME = ps2ctl
AVRDUDEMCU ?= t45 AVRDUDEMCU ?= t45
AVRDUDEARGS ?= -c usbtiny -P usb AVRDUDEARGS ?= -c usbtiny -P usb
TARGETS = $(PROGNAME).hex os.sms TARGETS = $(PROGNAME).bin os.sms
BASEDIR = ../../.. BASEDIR = ../../..
ZASM = $(BASEDIR)/emul/zasm/zasm ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps APPS = $(BASEDIR)/apps
AVRA = $(BASEDIR)/emul/zasm/avra
AVRINC = $(BASEDIR)/avr
# Rules # Rules
@ -14,14 +16,14 @@ APPS = $(BASEDIR)/apps
all: $(TARGETS) all: $(TARGETS)
@echo Done! @echo Done!
send: $(PROGNAME).hex send: $(PROGNAME).bin
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$(PROGNAME).hex avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$(PROGNAME).bin
$(PROGNAME).hex: $(PROGNAME).asm $(PROGNAME).bin: $(PROGNAME).asm
avra -o $@ $(PROGNAME).asm $(AVRA) $(AVRINC) < $(PROGNAME).asm > $@
os.sms: glue.asm os.sms: glue.asm
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@ $(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
clean: clean:
rm -f $(TARGETS) *.eep.hex *.obj os.bin rm -f $(TARGETS)

View File

@ -55,7 +55,6 @@ either the low or high bits.
* 74xx157 (multiplexer) * 74xx157 (multiplexer)
* A NOR SR-latch. I used a 4043. * A NOR SR-latch. I used a 4043.
* Proto board, wires, IC sockets, etc. * Proto board, wires, IC sockets, etc.
* [AVRA][avra]
## Historical note ## Historical note
@ -114,4 +113,3 @@ Just hook it on. I've tried it, it works.
Did you get there? Feels pretty cool huh? Did you get there? Feels pretty cool huh?
[rc2014-ps2]: ../../rc2014/ps2 [rc2014-ps2]: ../../rc2014/ps2
[avra]: https://github.com/hsoft/avra

View File

@ -1,5 +1,3 @@
.include "tn45def.inc"
; Receives keystrokes from PS/2 keyboard and send them to the '164. On the PS/2 ; Receives keystrokes from PS/2 keyboard and send them to the '164. On the PS/2
; side, it works the same way as the controller in the rc2014/ps2 recipe. ; side, it works the same way as the controller in the rc2014/ps2 recipe.
; However, in this case, what we have on the other side isn't a z80 bus, it's ; However, in this case, what we have on the other side isn't a z80 bus, it's
@ -30,17 +28,22 @@
; written. ; written.
; Z: pointer to the next scan code to push to the 595 ; Z: pointer to the next scan code to push to the 595
; ;
.inc "avr.h"
.inc "tn254585.h"
.inc "tn45.h"
; *** Constants *** ; *** Constants ***
.equ CLK = PINB2 .equ CLK 2 ; Port B
.equ DATA = PINB1 .equ DATA 1 ; Port B
.equ CP = PINB3 .equ CP 3 ; Port B
; SR-Latch's Q pin ; SR-Latch's Q pin
.equ LQ = PINB0 .equ LQ 0 ; Port B
; SR-Latch's R pin ; SR-Latch's R pin
.equ LR = PINB4 .equ LR 4 ; Port B
; init value for TCNT0 so that overflow occurs in 100us ; init value for TCNT0 so that overflow occurs in 100us
.equ TIMER_INITVAL = 0x100-100 .equ TIMER_INITVAL 0x100-100
; *** Code *** ; *** Code ***
@ -56,9 +59,9 @@ hdlINT0:
reti reti
main: main:
ldi r16, low(RAMEND) ldi r16, RAMEND&0xff
out SPL, r16 out SPL, r16
ldi r16, high(RAMEND) ldi r16, RAMEND}8
out SPH, r16 out SPH, r16
; init variables ; init variables
@ -67,23 +70,23 @@ main:
; Setup int0 ; Setup int0
; INT0, falling edge ; INT0, falling edge
ldi r16, (1<<ISC01) ldi r16, 0x02 ; ISC01
out MCUCR, r16 out MCUCR, r16
; Enable INT0 ; Enable INT0
ldi r16, (1<<INT0) ldi r16, 0x40 ; INT0
out GIMSK, r16 out GIMSK, r16
; Setup buffer ; Setup buffer
clr YH clr YH
ldi YL, low(SRAM_START) ldi YL, SRAM_START&0xff
clr ZH clr ZH
ldi ZL, low(SRAM_START) ldi ZL, SRAM_START&0xff
; Setup timer. We use the timer to clear up "processbit" registers after ; Setup timer. We use the timer to clear up "processbit" registers after
; 100us without a clock. This allows us to start the next frame in a ; 100us without a clock. This allows us to start the next frame in a
; fresh state. at 1MHZ, no prescaling is necessary. Each TCNT0 tick is ; fresh state. at 1MHZ, no prescaling is necessary. Each TCNT0 tick is
; already 1us long. ; already 1us long.
ldi r16, (1<<CS00) ; no prescaler ldi r16, 0x01 ; CS00 - no prescaler
out TCCR0B, r16 out TCCR0B, r16
; init DDRB ; init DDRB
@ -101,7 +104,7 @@ loop:
; nothing to do. Before looping, let's check if our communication timer ; nothing to do. Before looping, let's check if our communication timer
; overflowed. ; overflowed.
in r16, TIFR in r16, TIFR
sbrc r16, TOV0 sbrc r16, 1 ; TOV0
rjmp processbitReset ; Timer0 overflow? reset processbit rjmp processbitReset ; Timer0 overflow? reset processbit
; Nothing to do for real. ; Nothing to do for real.
@ -220,7 +223,7 @@ sendTo164Loop:
resetTimer: resetTimer:
ldi r16, TIMER_INITVAL ldi r16, TIMER_INITVAL
out TCNT0, r16 out TCNT0, r16
ldi r16, (1<<TOV0) ldi r16, 0x02 ; TOV0
out TIFR, r16 out TIFR, r16
ret ret
@ -237,8 +240,8 @@ sendToPS2:
; Wait until the timer overflows ; Wait until the timer overflows
in r16, TIFR in r16, TIFR
sbrs r16, TOV0 sbrs r16, 1 ; TOV0
rjmp PC-2 rjmp $-4
; Good, 100us passed. ; Good, 100us passed.
; Pull Data low, that's our start bit. ; Pull Data low, that's our start bit.
@ -258,7 +261,7 @@ sendToPS2:
sendToPS2Loop: sendToPS2Loop:
; Wait for CLK to go low ; Wait for CLK to go low
sbic PINB, CLK sbic PINB, CLK
rjmp PC-1 rjmp $-2
; set up DATA ; set up DATA
cbi PORTB, DATA cbi PORTB, DATA
@ -268,7 +271,7 @@ sendToPS2Loop:
; Wait for CLK to go high ; Wait for CLK to go high
sbis PINB, CLK sbis PINB, CLK
rjmp PC-1 rjmp $-2
dec r16 dec r16
brne sendToPS2Loop ; not zero? loop brne sendToPS2Loop ; not zero? loop
@ -279,7 +282,7 @@ sendToPS2Loop:
; Wait for CLK to go low ; Wait for CLK to go low
sbic PINB, CLK sbic PINB, CLK
rjmp PC-1 rjmp $-2
; set parity bit ; set parity bit
cbi PORTB, DATA cbi PORTB, DATA
@ -288,22 +291,22 @@ sendToPS2Loop:
; Wait for CLK to go high ; Wait for CLK to go high
sbis PINB, CLK sbis PINB, CLK
rjmp PC-1 rjmp $-2
; Wait for CLK to go low ; Wait for CLK to go low
sbic PINB, CLK sbic PINB, CLK
rjmp PC-1 rjmp $-2
; We can now release the DATA line ; We can now release the DATA line
cbi DDRB, DATA cbi DDRB, DATA
; Wait for DATA to go low. That's our ACK ; Wait for DATA to go low. That's our ACK
sbic PINB, DATA sbic PINB, DATA
rjmp PC-1 rjmp $-2
; Wait for CLK to go low ; Wait for CLK to go low
sbic PINB, CLK sbic PINB, CLK
rjmp PC-1 rjmp $-2
; We're finished! Enable INT0, reset timer, everything back to normal! ; We're finished! Enable INT0, reset timer, everything back to normal!
rcall resetTimer rcall resetTimer
@ -314,21 +317,21 @@ sendToPS2Loop:
; Check that Y is within bounds, reset to SRAM_START if not. ; Check that Y is within bounds, reset to SRAM_START if not.
checkBoundsY: checkBoundsY:
tst YL tst YL
breq PC+2 breq $+4
ret ; not zero, nothing to do ret ; not zero, nothing to do
; YL is zero. Reset Y ; YL is zero. Reset Y
clr YH clr YH
ldi YL, low(SRAM_START) ldi YL, SRAM_START&0xff
ret ret
; Check that Z is within bounds, reset to SRAM_START if not. ; Check that Z is within bounds, reset to SRAM_START if not.
checkBoundsZ: checkBoundsZ:
tst ZL tst ZL
breq PC+2 breq $+4
ret ; not zero, nothing to do ret ; not zero, nothing to do
; ZL is zero. Reset Z ; ZL is zero. Reset Z
clr ZH clr ZH
ldi ZL, low(SRAM_START) ldi ZL, SRAM_START&0xff
ret ret
; Counts the number of 1s in r19 and set r16 to 1 if there's an even number of ; Counts the number of 1s in r19 and set r16 to 1 if there's an even number of
@ -336,10 +339,10 @@ checkBoundsZ:
checkParity: checkParity:
ldi r16, 1 ldi r16, 1
lsr r19 lsr r19
brcc PC+2 ; Carry unset? skip next brcc $+4 ; Carry unset? skip next
inc r16 ; Carry set? We had a 1 inc r16 ; Carry set? We had a 1
tst r19 ; is r19 zero yet? tst r19 ; is r19 zero yet?
brne checkParity+1 ; no? loop and skip first LDI brne checkParity+2 ; no? loop and skip first LDI
andi r16, 0x1 ; Sets Z accordingly andi r16, 0x1 ; Sets Z accordingly
ret ret

View File

@ -24,3 +24,5 @@ jmp bar
mov r6, r30 mov r6, r30
lsl r3 lsl r3
tst r12 tst r12
clr YH
clr r29

Binary file not shown.