changeset 17:f86967c0bc73

Add general keyboard input (blinking cursor) handler Add general I/O read handler with keyboard driver that blinks the cursor while waiting for a keypress. The cursor is blinked by the IRQ handler which should keep the timing consistent regardless of clock speed.
author William Astle <lost@l-w.ca>
date Sun, 06 Nov 2022 22:09:33 -0700
parents d5ae140d19d4
children 6a046bd8107f
files src/lwbasic.s
diffstat 1 files changed, 79 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/lwbasic.s	Sun Nov 06 15:00:27 2022 -0700
+++ b/src/lwbasic.s	Sun Nov 06 22:09:33 2022 -0700
@@ -31,6 +31,7 @@
                 *pragmapop list
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; Various constants
+console_curdel  equ 10                          ; delay between cursor blink cycles
 keyb_bufflen    equ 64                          ; keyboard ring buffer length
 keyb_repdeli    equ 40                          ; ticks before initial repeat (2/3 s)
 keyb_repdelr    equ 20                          ; 3 repeats per second
@@ -196,6 +197,9 @@
 RSTFLG          rmb 1                           ; 0x55 if RSTVEC is valid
 RSTVEC          rmb 2                           ; points to warm start routine (must start with NOP)
 console_curptr  rmb 2                           ; current cursor pointer for console driver
+console_blnkdel rmb 1                           ; cursor blink delay
+filenum         rmb 1                           ; current input/output channel
+fileeof         rmb 1                           ; flag for whether last read detected EOF
 keyb_flags      rmb 1                           ; shift flags for the keyboard
 keyb_joystate   rmb 1                           ; joystick button state
 keyb_repdel     rmb 1                           ; repeat delay
@@ -425,11 +429,12 @@
 warmstart       nop                             ; flag warm start routine as valid
                 endc
                 jsr console_clear               ; clear screen
+                clr filenum                     ; reset I/O channel to the screen
 warmstartb      jsr keyb_reset                  ; reset the keyboard
                 lda #0x35                       ; enable VSYNC interrupt in PIA
                 sta PIA0.CB
                 andcc #0xaf                     ; enable interrupts at the cpu
-                bra *
+                jmp immediate                   ; go start immediate mode
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; System startup message
 ; (start with form feed to clear screen; saves 2 bytes over 'jsr console_clear' in cold start)
@@ -454,7 +459,17 @@
 irqhandler0     lda PIA0.DB                     ; clear VSYNC flag
                 clra                            ; make sure DP is pointing to the right place
                 tfr a,dp
-                bsr keyb_read                   ; go handle the keyboard
+                lda console_blnkdel             ; is the cursor blinking?
+                beq irqhandler1                 ; brif not
+                dec console_blnkdel             ; time to cycle cursor?
+                bne irqhandler1                 ; brif not
+                lda #console_curdel             ; reset blink counter
+                sta console_blnkdel
+                lda [console_curptr]            ; get character at cursor
+                adda #0x10                      ; move to next colour
+                ora #0x8f                       ; force it to be a full 4x4 colour block
+                sta [console_curptr]            ; update cursor on screen
+irqhandler1     bsr keyb_read                   ; go handle the keyboard
                 rti
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; FIRQ handler
@@ -491,6 +506,23 @@
                 stx keyb_state+4
                 stx keyb_state+6
                 rts
+; Read character from keyboard ring buffer; return with C set if buffer empty; this doesn't actually need to have
+; interrupts disabled because the interrupt only ever updates the write pointer and then only to increase it. As a
+; result, worst case is that we don't detect the contents added to the buffer on this call and have to wait for the
+; next.
+keyb_getkey     pshs x                          ; save register
+                ldx keyb_buffr                  ; get read pointer
+                cmpx keyb_buffw                 ; same as write pointer?
+                bne keyb_getkey0                ; brif not - we have a result
+                coma                            ; set carry for empty buffer
+                puls x,pc                       ; restore register and return
+keyb_getkey0    lda ,x+                         ; get character from buffer
+                cmpx #keyb_buff+keyb_bufflen    ; did we run off end of buffer?
+                blo keyb_getkey1                ; brif not
+                ldx #keyb_buff                  ; reset to start
+keyb_getkey1    stx keyb_buffr                  ; save new read pointer
+                andcc #0xfe                     ; flag key retrieved
+                puls x,pc                       ; restore register and return
 ; The PIA reading loop is specifically set up to NOT read PIA0.DB to avoid prematurely clearing the VSYNC interrupt flag
 ; since that could lead to missing interrupts. Reading PIA0.DA will clear the HSYNC interrupt flag but that's less of a
 ; problem because that interrupt is basically useless.
@@ -690,6 +722,14 @@
 console_outstr  lda ,x+                         ; get byte from string
                 bne console_outstr0             ; brif not end of string
                 rts
+; Output NUL terminated string followed by a newline
+console_outstrn bsr console_outstr              ; output the string
+                ; fallthrough intentional
+; Output a newline (CR LF)
+console_outnl   lda #0x0d                       ; do the CR
+                bsr console_outchr
+                lda #0x0a                       ; do the LF
+                ; fallthrough intentional
 ; Output a single character to the screen; enter with character in A
 console_outchr  pshs d,x                        ; save registers
                 ldx console_curptr              ; get current cursor pointer
@@ -748,7 +788,44 @@
                 cmpb #8                         ; at next tab stop?
                 blo console_outchra             ; brif not
                 bra console_outchr2             ; go update details and check for scroll
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; General I/O handling package
+;
+; These routines operate on the I/O channel specified by filenum. The defined values of filenum are:
+;
+; 0: keyboard/screen console
+;
+; Read a character from the active file and return it in A; in the event that EOF is detected, readeof will be nonzero
+; and the call will return with carry set.
+readchr         clr fileeof                     ; flag not end of file (and clear carry)
+                lda filenum                     ; get input file number
+                beq readchr_kb                  ; brif keyboard input
+                com fileeof                     ; flag end of file (C set and fileeof nonzero)
+                rts
+; Read character from keyboard; blink cursor while doing so
+readchr_kb      pshs b                          ; preserve B as temp storage
+                ldb [console_curptr]            ; get character at cursor
+                inc console_blnkdel             ; activate cursor blinking (first interrupt will cycle it)
+readchr_kb0     jsr keyb_getkey                 ; read keyboard
+                bcc readchr_kb1                 ; brif we got a result
+                cwai #0xaf                      ; wait for interrupt to scan keyboard
+                bra readchr_kb0                 ; see if we have something yet
+readchr_kb1     clr console_blnkdel             ; disable cursor blinking
+                stb [console_curptr]            ; restore screen character
+                clrb                            ; clear carry to indicate not eof
+                puls b,pc                       ; restore temp and return
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Immediate mode handler
+prompt          fcn 'OK'
+immediate       ldx #prompt                     ; point to prompt string
+                jsr console_outstrn
+                jsr readchr
+                bra *
+immediate0      
+                ; handle line
+                bra immediate
                 ifndef COCO3
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; Need to ensure the vectors are at 0xbff2
                 zmb 0xbff2-*                    ; pad ROM up to the vector point
                 fdb SW3VEC                      ; SWI3 vector