recipes/sms/kbd: use Collapse OS' AVR assembler
This commit is contained in:
parent
64a54c72f8
commit
97dcad9b15
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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.
Loading…
Reference in New Issue
Block a user