comparison src/keyb.s @ 73:2d52cd154ed1

Split some code into separate files for easier management Because the source for lwbasic is so large, split it into several different files to make it easier to navigate and modify. This is part one of the split.
author William Astle <lost@l-w.ca>
date Sun, 06 Aug 2023 00:12:29 -0600
parents
children
comparison
equal deleted inserted replaced
72:f492fa6f6dc8 73:2d52cd154ed1
1 *pragmapush list
2 *pragma list
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4 ; Check for BREAK; this needs to check the keyboard directly instead of just using the usual key fetching routine so
5 ; we don't interfere with keyboard buffering if BREAK isn't pressed. We also need to scan the keyboard directly for this
6 ; so we react even if the keyboard buffer is full. If BREAK is pressed, the keyboard buffer is emptied.
7 breakcheck lda #0xfb ; strobe column for BREAK
8 sta PIA0.DB
9 clra ; clear carry for no BREAK
10 lda PIA0.DA ; read rows
11 bita #0x40 ; is BREAK down?
12 bne breakcheck0 ; brif not - check for SHIFT-@
13 sync ; wait for interrupt to scan keyboard
14 bsr keyb_clearbuff ; reset keyboard buffer
15 coma ; flag BREAK
16 breakcheck1 rts
17 breakcheck0 lda #0x7f ; check for SHIFT
18 sta PIA0.DB
19 lda PIA0.DA
20 bita #0x40 ; shift?
21 bne breakcheck1 ; brif not
22 lda #0xfe ; check for @
23 sta PIA0.DB
24 lda PIA0.DA
25 bita #1 ; @?
26 bne breakcheck1 ; brif not
27 bsr keyb_clearbuff ; clear buffer
28 breakcheck2 sync ; wait for keyboard to actually be scanned
29 bsr keyb_getkey
30 bcs breakcheck2 ; brif no key down
31 bra breakcheck ; go do the break/pause check dance again
32 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
33 ; Console keyboard input driver
34 ;
35 ; Reset the keyboard state, which means clearing the buffer and state flags
36 keyb_reset bsr keyb_clearbuff ; clear keyboard buffer
37 lda keyb_flags ; reset keyboard state flags but keep capslock
38 anda #keyb_caps
39 sta keyb_flags
40 clr keyb_joystate ; clear joystick button state
41 clr keyb_curscan ; stop any keyboard repeating
42 ldx #0xffff ; mark all key state as "unpressed"
43 stx keyb_state
44 stx keyb_state+2
45 stx keyb_state+4
46 stx keyb_state+6
47 rts
48 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
49 ; Empty the keyboard buffer
50 keyb_clearbuff ldx #keyb_buff ; point to start of buffer
51 stx keyb_buffr ; set both pointers to the start
52 stx keyb_buffw
53 rts
54 ; Read character from keyboard ring buffer; return with C set if buffer empty; this doesn't actually need to have
55 ; interrupts disabled because the interrupt only ever updates the write pointer and then only to increase it. As a
56 ; result, worst case is that we don't detect the contents added to the buffer on this call and have to wait for the
57 ; next.
58 keyb_getkey pshs x ; save register
59 ldx keyb_buffr ; get read pointer
60 cmpx keyb_buffw ; same as write pointer?
61 bne keyb_getkey0 ; brif not - we have a result
62 coma ; set carry for empty buffer
63 puls x,pc ; restore register and return
64 keyb_getkey0 lda ,x+ ; get character from buffer
65 cmpx #keyb_buff+keyb_bufflen ; did we run off end of buffer?
66 blo keyb_getkey1 ; brif not
67 ldx #keyb_buff ; reset to start
68 keyb_getkey1 stx keyb_buffr ; save new read pointer
69 andcc #0xfe ; flag key retrieved
70 puls x,pc ; restore register and return
71 ; The PIA reading loop is specifically set up to NOT read PIA0.DB to avoid prematurely clearing the VSYNC interrupt flag
72 ; since that could lead to missing interrupts. Reading PIA0.DA will clear the HSYNC interrupt flag but that's less of a
73 ; problem because that interrupt is basically useless.
74 ;
75 ; As a note, doing the PIA read in a loop ends up using an extra 27 CPU cycles for the BCS instruction. However, it
76 ; saves 70 code bytes. The trade off seems worth it in this case.
77 ;
78 ; Once keyboard state is read, we do the following:
79 ;
80 ; * update the state of SHIFT, CTRL, ALT
81 ; * decode all other keys in a loop
82 keyb_read0a pshs b ; save flag bit
83 ldb a,y ; get state flag
84 bitb #0x40 ; did it change state?
85 bne keyb_read0d ; brif so
86 puls b,pc ; clean up and return
87 keyb_read0d andb #0xbf ; flag it as not changed
88 stb a,y
89 ldb a,u ; get current modifier state
90 eorb #0x40 ; flip the state bit
91 stb a,u ; save new state flags
92 bitb #0x40 ; Z set if not down
93 puls b ; get back flag bit
94 beq keyb_read0b ; brif key is pressed
95 comb ; invert bit flag
96 andb keyb_flags ; clear bit in flags
97 bra keyb_read0c ; finish up
98 keyb_read0b orb keyb_flags ; set the flag
99 keyb_read0c stb keyb_flags ; update flags
100 rts
101 keyb_read leas -9,s ; make temporary buffer
102 leay 1,s ; point to temporary state buffer
103 clra ;* set to 0xff with C clear; start by strobing no columns for joystick
104 deca ;* then rotate the 0 bit through to do the actual keyboard columns
105 ldu #keyb_state ; point to end of keyboard state buffer
106 sta PIA0.DB ; strobe no columns
107 ldb PIA0.DA ; get joystick button state
108 stb keyb_joystate ; save it for later when needed
109 andb #0x7f ; mask off comparator (pretend "button" down)
110 stb ,s ; save button/comparator state mask
111 rola ; set up for first column
112 keyb_read0 sta PIA0.DB ; set column strobe
113 ldb PIA0.DA ; read row data
114 eorb ,u+ ; set bits if state changed
115 andb ,s ; mask off comparator and active buttons
116 stb ,y+ ; save state change information
117 rola ; shift to next column
118 bcs keyb_read0 ; brif we haven't done the last column
119 sta PIA0.DB ; reset column strobe to none
120 ldd #0xff00|keyb_shift
121 bsr keyb_read0a
122 ldd #0xfc00|keyb_ctrl
123 bsr keyb_read0a
124 ldd #0xfb00|keyb_alt
125 bsr keyb_read0a
126 keyb_read3 ldd #0x0701 ; initialize bit probe and counter
127 keyb_read4 leay -1,y ; move pointers to next byte
128 leau -1,u
129 keyb_read5 bitb ,y ; did this key change state?
130 bne keyb_read7 ; brif so
131 keyb_read6 adda #8 ; adjust scan code
132 lslb ; shift bit probe
133 bpl keyb_read5 ; brif we haven't done all bits
134 ldb ,y ; update state flags for this byte
135 eorb ,u
136 stb ,u
137 ldb #1 ; reset bit probe
138 anda #0x07 ; reset scan code
139 deca ; adjust for next column
140 bpl keyb_read4 ; brif not - do another
141 leas 9,s ; clean up stack
142 ldb keyb_curscan ; is key repeating?
143 bne keyb_read9 ; brif so
144 keyb_reada rts
145 keyb_read7 bitb ,u ; get current state
146 bne keyb_read8 ; brif key pressed (make)
147 cmpa keyb_curscan ; is it the currently repeating key?
148 bne keyb_read6 ; brif not - don't need to do anything
149 clr keyb_curscan ; clear the current repeat
150 bra keyb_read6
151 keyb_read8 sta keyb_curscan ; set the current scan code that is repeating
152 pshs d ; save current bit probe and scan code
153 ldb #keyb_repdeli ; intialize repeat delay
154 stb keyb_repdel
155 bsr keyb_tobuff ; decode key to buffer
156 puls d ; restore scan code and bit probe
157 bra keyb_read6 ; go handle the next bit
158 keyb_read9 dec keyb_repdel ; is it time to repeat it?
159 bne keyb_reada ; brif not
160 ldb #keyb_repdelr ; reset repeat delay
161 stb keyb_repdel
162 lda keyb_curscan ; get current scan code
163 keyb_tobuff tsta ; @?
164 beq keyb_tobuff7 ; brif so
165 cmpa #26 ; is it alpha or @?
166 bhi keyb_tobuff6 ; brif not
167 ldb keyb_flags ; get shift flags
168 bitb #keyb_ctrl|keyb_alt ; ALT or CTRL?
169 bne keyb_tobuff4 ; brif one or both
170 ora #0x60 ; make lower case
171 bitb #keyb_caps ; capslock enabled?
172 beq keyb_tobuff0 ; brif not
173 eora #0x20 ; flip to upper case
174 keyb_tobuff0 bitb #keyb_shift ; shifted?
175 beq keyb_tobuff1 ; brif not
176 eora #0x20 ; flip case if shifted
177 keyb_tobuff1 ldx keyb_buffw ; get write pointer for keyboard buffer
178 sta ,x+ ; put it in the buffer
179 cmpx #keyb_buff+keyb_bufflen ; end of buffer?
180 blo keyb_tobuff2 ; brif not
181 ldx #keyb_buff ; reset pointer to start
182 keyb_tobuff2 cmpx keyb_buffr ; did we run into the read pointer?
183 beq keyb_tobuff3 ; brif so - there wasn't room so don't save pointer
184 stx keyb_buffw ; update the write pointer
185 keyb_tobuff3 rts
186 keyb_tobuff4 bitb #keyb_alt ; is ALT?
187 beq keyb_tobuff1 ; brif not - scan code is CTRL-<letter> code
188 ora #0x80 ; set bit 7 for "ALT" codes
189 bitb #keyb_shift ; shifted?
190 beq keyb_tobuff5 ; brif not
191 ora #0x20 ; set bit 5
192 keyb_tobuff5 bitb #keyb_ctrl ; ctrl?
193 beq keyb_tobuff1 ; brif not - stash it in the buffer
194 ora #0x40 ; set bit 6 for "ctrl
195 bra keyb_tobuff1 ; stash it the buffer
196 keyb_tobuff6 suba #26 ; codes above 26 down to 1; @ will be 0
197 keyb_tobuff7 cmpa #6 ; is it "0"?
198 bne keyb_tobuff8 ; brif not
199 ldb keyb_flags ; get shift flags
200 bitb #keyb_shift|keyb_ctrl ; CTRL-0 or SHIFT-0?
201 beq keyb_tobuff8 ; brif not - not "capslock"
202 eorb #keyb_caps ; flip the capslock state
203 stb keyb_flags
204 keyb_tobuffa rts ; and don't put it in the buffer
205 keyb_tobuff8 cmpa #25 ; is it at or above ALT?
206 blo keyb_tobuff9 ; brif not
207 suba #2 ; close gap for ALT/CTRL
208 keyb_tobuff9 ldb #8 ;* 8 codes; multiply by 8 and move to B
209 mul ;*
210 ldx #keyb_codetab ; point to special code table
211 abx ; now X points to the base entry in the table
212 ldb keyb_flags ; get shift flags
213 andb #keyb_shift|keyb_ctrl|keyb_alt ; keep only shift/ctrl/alt
214 lda b,x ; fetch key code
215 beq keyb_tobuffa ; brif no code to return
216 bra keyb_tobuff1 ; go stash it in the buffer
217 ; This is the keyboard code table; there are 8 bytes per entry in the following order:
218 ; 0: unmodified
219 ; 1: shift
220 ; 2: ctrl
221 ; 3: ctrl-shift
222 ; 4: alt
223 ; 5: alt-shift
224 ; 6: alt-ctrl
225 ; 7: alt-ctrl-shift
226 ;
227 ; No entries for ALT, CTRL, SHIFT, or letters
228 keyb_codetab fcb 0x40,0x13,0x40,0x40,0x80,0xa0,0xc0,0xe0 ; @
229 fcb 0x5e,0x5f,0x00,0x00,0x00,0x00,0x00,0x00 ; <UP>
230 fcb 0x0a,0x5b,0x00,0x00,0x00,0x00,0x00,0x00 ; <DOWN>
231 fcb 0x08,0x15,0x00,0x00,0x00,0x00,0x00,0x00 ; <LEFT>
232 fcb 0x09,0x5d,0x00,0x00,0x00,0x00,0x00,0x00 ; <RIGHT>
233 fcb 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20 ; <SPACE>
234 fcb 0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; 0 (shift/ctrl variants shadowed above)
235 fcb 0x31,0x21,0x00,0x00,0x00,0x00,0x00,0x00 ; 1 !
236 fcb 0x32,0x22,0x00,0x00,0x00,0x00,0x00,0x00 ; 2 "
237 fcb 0x33,0x23,0x00,0x00,0x00,0x00,0x00,0x00 ; 3 #
238 fcb 0x34,0x24,0x00,0x00,0x00,0x00,0x00,0x00 ; 4 $
239 fcb 0x35,0x25,0x00,0x00,0x00,0x00,0x00,0x00 ; 5 %
240 fcb 0x36,0x26,0x00,0x00,0x00,0x00,0x00,0x00 ; 6 &
241 fcb 0x37,0x27,0x00,0x00,0x00,0x00,0x00,0x00 ; 7 '
242 fcb 0x38,0x28,0x00,0x00,0x00,0x00,0x00,0x00 ; 8 (
243 fcb 0x39,0x29,0x00,0x00,0x00,0x00,0x00,0x00 ; 9 )
244 fcb 0x3a,0x2a,0x00,0x00,0x00,0x00,0x00,0x00 ; : *
245 fcb 0x3b,0x2b,0x00,0x00,0x00,0x00,0x00,0x00 ; ; +
246 fcb 0x2c,0x3c,0x00,0x00,0x00,0x00,0x00,0x00 ; , <
247 fcb 0x2d,0x3d,0x00,0x00,0x00,0x00,0x00,0x00 ; - =
248 fcb 0x2e,0x3e,0x00,0x00,0x00,0x00,0x00,0x00 ; . >
249 fcb 0x2f,0x3f,0x00,0x00,0x00,0x00,0x00,0x00 ; / ?
250 fcb 0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d ; <ENTER>
251 fcb 0x0c,0x5c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c ; <CLEAR>
252 fcb 0x03,0x03,0x1b,0x1b,0x9b,0xbb,0xdb,0xfb ; <BREAK>
253 fcb 0x1c,0x1d,0x1c,0x1d,0x00,0x00,0x00,0x00 ; <F1>
254 fcb 0x1e,0x1f,0x1e,0x1f,0x00,0x00,0x00,0x00 ; <F2>
255 *pragmapop list