shell: handle inputs with interrupts

This commit is contained in:
Virgil Dupras 2019-04-13 15:02:29 -04:00
parent 358c551bcc
commit ac22a206ae
1 changed files with 48 additions and 32 deletions

View File

@ -27,8 +27,10 @@ BUFIDX .equ INPTBUF+BUFSIZE
; *** CODE *** ; *** CODE ***
jr init jr init
.fill 0x38-$
jr handleInterrupt
init: init:
; disable interrupts we don't need them
di di
; setup stack ; setup stack
@ -39,12 +41,16 @@ init:
xor a xor a
ld (BUFIDX), a ; starts at 0 ld (BUFIDX), a ; starts at 0
; RC2014's serial I/O is based on interrupt mode 1. We'd prefer im 2,
; but for now, let's go with the simpler im 1.
im 1
; setup ACIA ; setup ACIA
; CR7 (1) - Receive Interrupt disabled ; CR7 (1) - Receive Interrupt enabled
; CR6:5 (00) - RTS low, transmit interrupt disabled. ; CR6:5 (00) - RTS low, transmit interrupt disabled.
; CR4:2 (101) - 8 bits + 1 stop bit ; CR4:2 (101) - 8 bits + 1 stop bit
; CR1:0 (10) - Counter divide: 64 ; CR1:0 (10) - Counter divide: 64
ld a, 0b00010110 ld a, 0b10010110
out (ACIA_CTL), a out (ACIA_CTL), a
; print prompt ; print prompt
@ -52,11 +58,42 @@ init:
call printstr call printstr
call printcrlf call printcrlf
; alright, ready to receive
ei
mainloop: mainloop:
call readc
call chkbuf call chkbuf
jr mainloop jr mainloop
; read char in the ACIA and put it in the read buffer
handleInterrupt:
push af
push hl
; Read our character from ACIA into our BUFIDX
in a, (ACIA_CTL)
bit 0, a ; is our ACIA rcv buffer full?
jr z, .end ; no? a interrupt was triggered for nothing.
call getbufptr ; HL set, A set
; is our input buffer full? If yes, we don't read anything. Something
; is wrong: we don't process data fast enough.
cp BUFSIZE
jr z, .end ; if BUFIDX == BUFSIZE, our buffer is full.
; increase our buf ptr while we still have it in A
inc a
ld (BUFIDX), a
in a, (ACIA_IO)
ld (hl), a
.end:
pop hl
pop af
ei
reti
; spits character in A in port SER_OUT ; spits character in A in port SER_OUT
printc: printc:
push af push af
@ -85,43 +122,17 @@ printcrlf:
call printc call printc
ret ret
; wait until a char is read in the ACIA and put it in the read buffer
readc:
; first thing first: is our input buffer full? If yes, we don't even
; bother reading the ACIA. Something is wrong: we don't process data
; fast enough.
ld a, (BUFIDX)
cp BUFSIZE
ret z ; if BUFIDX == BUFSIZE, our buffer is full.
call getbufptr
; increase our buf ptr while we still have it in A
inc a
ld (BUFIDX), a
.loop:
; Read our character from ACIA into our BUFIDX
in a, (ACIA_CTL)
bit 0, a ; is our ACIA rcv buffer full?
jr z, .loop ; no? loop
in a, (ACIA_IO)
ld (hl), a
ret
; check if the input buffer is full or ends in CR or LF. If it does, prints it ; check if the input buffer is full or ends in CR or LF. If it does, prints it
; back and empty it. ; back and empty it.
chkbuf: chkbuf:
ld a, (BUFIDX) call getbufptr
cp 0 cp 0
ret z ; BUFIDX is zero? nothing to check. ret z ; BUFIDX is zero? nothing to check.
cp BUFSIZE cp BUFSIZE
jr z, .do ; if BUFIDX == BUFSIZE? do! jr z, .do ; if BUFIDX == BUFSIZE? do!
call getbufptr
; our previous char is in BUFIDX - 1. Fetch this ; our previous char is in BUFIDX - 1. Fetch this
dec hl dec hl
ld a, (hl) ; now, that's our char we have in A ld a, (hl) ; now, that's our char we have in A
@ -149,12 +160,17 @@ chkbuf:
ret ret
; Set current buffer pointer in HL. The buffer pointer is where our *next* char ; Set current buffer pointer in HL. The buffer pointer is where our *next* char
; will be written. ; will be written. A is set to the value of (BUFIDX)
getbufptr: getbufptr:
push bc
ld a, (BUFIDX)
ld hl, INPTBUF ld hl, INPTBUF
xor b xor b
ld c, a ld c, a
add hl, bc ; hl now points to INPTBUF + BUFIDX add hl, bc ; hl now points to INPTBUF + BUFIDX
pop bc
ret ret
; *** DATA *** ; *** DATA ***