Mercurial > hg > index.cgi
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