diff options
author | Akshay <[email protected]> | 2022-04-10 12:13:40 +0100 |
---|---|---|
committer | Akshay <[email protected]> | 2022-04-10 12:13:40 +0100 |
commit | dc90387ce7d8ba7b607d9c48540bf6d8b560f14d (patch) | |
tree | 4ccb8fa5886b66fa9d480edef74236c27f035e16 /keyboards/converter/palm_usb/matrix.c |
Diffstat (limited to 'keyboards/converter/palm_usb/matrix.c')
-rw-r--r-- | keyboards/converter/palm_usb/matrix.c | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/keyboards/converter/palm_usb/matrix.c b/keyboards/converter/palm_usb/matrix.c new file mode 100644 index 000000000..289284b61 --- /dev/null +++ b/keyboards/converter/palm_usb/matrix.c | |||
@@ -0,0 +1,397 @@ | |||
1 | /* | ||
2 | Copyright 2018 milestogo | ||
3 | with elements Copyright 2014 cy384 under a modified BSD license | ||
4 | building on qmk structure Copyright 2012 Jun Wako <[email protected]> | ||
5 | |||
6 | This program is free software: you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation, either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include QMK_KEYBOARD_H | ||
21 | #include "protocol/serial.h" | ||
22 | #include "timer.h" | ||
23 | |||
24 | |||
25 | /* | ||
26 | * Matrix Array usage: | ||
27 | * | ||
28 | * ROW: 12(4bits) | ||
29 | * COL: 8(3bits) | ||
30 | * | ||
31 | * +---------+ | ||
32 | * 0|00 ... 07| | ||
33 | * 1|00 ... 07| | ||
34 | * :| ... | | ||
35 | * :| ... | | ||
36 | * A| | | ||
37 | * B| | | ||
38 | * +---------+ | ||
39 | */ | ||
40 | static uint8_t matrix[MATRIX_ROWS]; | ||
41 | |||
42 | |||
43 | // we're going to need a sleep timer | ||
44 | static uint16_t last_activity ; | ||
45 | // and a byte to track duplicate up events signalling all keys up. | ||
46 | static uint16_t last_upKey ; | ||
47 | // serial device can disconnect. Check every MAXDROP characters. | ||
48 | static uint16_t disconnect_counter = 0; | ||
49 | |||
50 | |||
51 | // bitmath masks. | ||
52 | #define KEY_MASK 0b10000000 | ||
53 | #define COL_MASK 0b00000111 | ||
54 | #define ROW_MASK 0b01111000 | ||
55 | |||
56 | |||
57 | #define ROW(code) (( code & ROW_MASK ) >>3) | ||
58 | #define COL(code) ((code & COL_MASK) ) | ||
59 | #define KEYUP(code) ((code & KEY_MASK) >>7 ) | ||
60 | |||
61 | static bool is_modified = false; | ||
62 | |||
63 | __attribute__ ((weak)) | ||
64 | void matrix_init_kb(void) { | ||
65 | matrix_init_user(); | ||
66 | } | ||
67 | |||
68 | __attribute__ ((weak)) | ||
69 | void matrix_scan_kb(void) { | ||
70 | matrix_scan_user(); | ||
71 | } | ||
72 | |||
73 | __attribute__ ((weak)) | ||
74 | void matrix_init_user(void) { | ||
75 | } | ||
76 | |||
77 | __attribute__ ((weak)) | ||
78 | void matrix_scan_user(void) { | ||
79 | } | ||
80 | |||
81 | inline | ||
82 | uint8_t matrix_rows(void) | ||
83 | { | ||
84 | return MATRIX_ROWS; | ||
85 | } | ||
86 | |||
87 | inline | ||
88 | uint8_t matrix_cols(void) | ||
89 | { | ||
90 | return MATRIX_COLS; | ||
91 | } | ||
92 | |||
93 | |||
94 | void pins_init(void) { | ||
95 | // set pins for pullups, Rts , power &etc. | ||
96 | |||
97 | //print ("pins setup\n"); | ||
98 | setPinOutput(VCC_PIN); | ||
99 | writePinLow(VCC_PIN); | ||
100 | |||
101 | #if ( HANDSPRING == 0) | ||
102 | |||
103 | #ifdef CY835 | ||
104 | setPinOutput(GND_PIN); | ||
105 | writePinLow(GND_PIN); | ||
106 | |||
107 | setPinOutput(PULLDOWN_PIN); | ||
108 | writePinLow(PULLDOWN_PIN); | ||
109 | #endif | ||
110 | |||
111 | setPinInput(DCD_PIN); | ||
112 | setPinInput(RTS_PIN); | ||
113 | #endif | ||
114 | |||
115 | /* check that the other side isn't powered up. | ||
116 | test=readPin(DCD_PIN); | ||
117 | xprintf("b%02X:", test); | ||
118 | test=readPin(RTS_PIN); | ||
119 | xprintf("%02X\n", test); | ||
120 | */ | ||
121 | |||
122 | } | ||
123 | |||
124 | uint8_t rts_reset(void) { | ||
125 | static uint8_t firstread ; | ||
126 | /* bounce RTS so device knows it is rebooted */ | ||
127 | |||
128 | // On boot, we keep rts as input, then switch roles here | ||
129 | // on leaving sleep, we toggle the same way | ||
130 | |||
131 | firstread=readPin(RTS_PIN); | ||
132 | // printf("r%02X:", firstread); | ||
133 | |||
134 | setPinOutput(RTS_PIN); | ||
135 | |||
136 | if (firstread) { | ||
137 | writePinLow(RTS_PIN); | ||
138 | } | ||
139 | _delay_ms(10); | ||
140 | writePinHigh(RTS_PIN); | ||
141 | |||
142 | |||
143 | /* the future is Arm | ||
144 | if (!palReadPad(RTS_PIN_IOPRT)) | ||
145 | { | ||
146 | _delay_ms(10); | ||
147 | palSetPadMode(RTS_PINn_IOPORT, PinDirectionOutput_PUSHPULL); | ||
148 | palSetPad(RTS_PORT, RTS_PIN); | ||
149 | } | ||
150 | else | ||
151 | { | ||
152 | palSetPadMode(RTS_PIN_RTS_PORT, PinDirectionOutput_PUSHPULL); | ||
153 | palSetPad(RTS_PORT, RTS_PIN); | ||
154 | palClearPad(RTS_PORT, RTS_PIN); | ||
155 | _delay_ms(10); | ||
156 | palSetPad(RTS_PORT, RTS_PIN); | ||
157 | } | ||
158 | */ | ||
159 | |||
160 | |||
161 | _delay_ms(5); | ||
162 | //print("rts\n"); | ||
163 | return 1; | ||
164 | } | ||
165 | |||
166 | uint8_t get_serial_byte(void) { | ||
167 | static uint8_t code; | ||
168 | while(1) { | ||
169 | code = serial_recv(); | ||
170 | if (code) { | ||
171 | debug_hex(code); debug(" "); | ||
172 | return code; | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | |||
177 | uint8_t palm_handshake(void) { | ||
178 | // assumes something has seen DCD go high, we've toggled RTS | ||
179 | // and we now need to verify handshake. | ||
180 | // listen for up to 4 packets before giving up. | ||
181 | // usually I get the sequence FF FA FD | ||
182 | static uint8_t codeA=0; | ||
183 | |||
184 | for (uint8_t i=0; i < 5; i++) { | ||
185 | codeA=get_serial_byte(); | ||
186 | if ( 0xFA == codeA) { | ||
187 | if( 0xFD == get_serial_byte()) { | ||
188 | return 1; | ||
189 | } | ||
190 | } | ||
191 | } | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | uint8_t palm_reset(void) { | ||
196 | print("@"); | ||
197 | rts_reset(); // shouldn't need to power cycle. | ||
198 | |||
199 | if ( palm_handshake() ) { | ||
200 | last_activity = timer_read(); | ||
201 | return 1; | ||
202 | } else { | ||
203 | print("failed reset"); | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | } | ||
208 | |||
209 | uint8_t handspring_handshake(void) { | ||
210 | // should be sent 15 ms after power up. | ||
211 | // listen for up to 4 packets before giving up. | ||
212 | static uint8_t codeA=0; | ||
213 | |||
214 | for (uint8_t i=0; i < 5; i++) { | ||
215 | codeA=get_serial_byte(); | ||
216 | if ( 0xF9 == codeA) { | ||
217 | if( 0xFB == get_serial_byte()) { | ||
218 | return 1; | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | uint8_t handspring_reset(void) { | ||
226 | writePinLow(VCC_PIN); | ||
227 | _delay_ms(5); | ||
228 | writePinHigh(VCC_PIN); | ||
229 | |||
230 | if ( handspring_handshake() ) { | ||
231 | last_activity = timer_read(); | ||
232 | disconnect_counter=0; | ||
233 | return 1; | ||
234 | } else { | ||
235 | print("-HSreset"); | ||
236 | return 0; | ||
237 | } | ||
238 | } | ||
239 | |||
240 | void matrix_init(void) | ||
241 | { | ||
242 | debug_enable = true; | ||
243 | //debug_matrix =true; | ||
244 | |||
245 | serial_init(); // arguments all #defined | ||
246 | |||
247 | #if (HANDSPRING == 0) | ||
248 | pins_init(); // set all inputs and outputs. | ||
249 | #endif | ||
250 | |||
251 | print("power up\n"); | ||
252 | writePinHigh(VCC_PIN); | ||
253 | |||
254 | // wait for DCD strobe from keyboard - it will do this | ||
255 | // up to 3 times, then the board needs the RTS toggled to try again | ||
256 | |||
257 | #if ( HANDSPRING == 1) | ||
258 | if ( handspring_handshake() ) { | ||
259 | last_activity = timer_read(); | ||
260 | } else { | ||
261 | print("failed handshake"); | ||
262 | _delay_ms(1000); | ||
263 | //BUG /should/ power cycle or toggle RTS & reset, but this usually works. | ||
264 | } | ||
265 | |||
266 | #else /// Palm / HP device with DCD | ||
267 | while( !readPin(DCD_PIN) ) {;} | ||
268 | print("dcd\n"); | ||
269 | |||
270 | rts_reset(); // at this point the keyboard should think all is well. | ||
271 | |||
272 | if ( palm_handshake() ) { | ||
273 | last_activity = timer_read(); | ||
274 | } else { | ||
275 | print("failed handshake"); | ||
276 | _delay_ms(1000); | ||
277 | //BUG /should/ power cycle or toggle RTS & reset, but this usually works. | ||
278 | } | ||
279 | |||
280 | #endif | ||
281 | |||
282 | // initialize matrix state: all keys off | ||
283 | for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | ||
284 | |||
285 | matrix_init_quantum(); | ||
286 | return; | ||
287 | |||
288 | |||
289 | } | ||
290 | |||
291 | |||
292 | uint8_t matrix_scan(void) | ||
293 | { | ||
294 | uint8_t code; | ||
295 | code = serial_recv(); | ||
296 | if (!code) { | ||
297 | /* | ||
298 | disconnect_counter ++; | ||
299 | if (disconnect_counter > MAXDROP) { | ||
300 | // set all keys off | ||
301 | for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | ||
302 | } | ||
303 | */ | ||
304 | // check if the keyboard is asleep. | ||
305 | if (timer_elapsed(last_activity) > SLEEP_TIMEOUT) { | ||
306 | #if(HANDSPRING ==0 ) | ||
307 | palm_reset(); | ||
308 | #else | ||
309 | handspring_reset(); | ||
310 | #endif | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | } | ||
315 | |||
316 | last_activity = timer_read(); | ||
317 | disconnect_counter=0; // if we are getting serial data, we're connected. | ||
318 | |||
319 | debug_hex(code); debug(" "); | ||
320 | |||
321 | |||
322 | switch (code) { | ||
323 | case 0xFD: // unexpected reset byte 2 | ||
324 | print("rstD "); | ||
325 | return 0; | ||
326 | case 0xFA: // unexpected reset | ||
327 | print("rstA "); | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | if (KEYUP(code)) { | ||
332 | if (code == last_upKey) { | ||
333 | // all keys are not pressed. | ||
334 | // Manual says to disable all modifiers left open now. | ||
335 | // but that could defeat sticky keys. | ||
336 | // BUG? dropping this byte. | ||
337 | last_upKey=0; | ||
338 | return 0; | ||
339 | } | ||
340 | // release | ||
341 | if (matrix_is_on(ROW(code), COL(code))) { | ||
342 | matrix[ROW(code)] &= ~(1<<COL(code)); | ||
343 | last_upKey=code; | ||
344 | } | ||
345 | } else { | ||
346 | // press | ||
347 | if (!matrix_is_on(ROW(code), COL(code))) { | ||
348 | matrix[ROW(code)] |= (1<<COL(code)); | ||
349 | |||
350 | } | ||
351 | } | ||
352 | |||
353 | matrix_scan_quantum(); | ||
354 | return code; | ||
355 | } | ||
356 | |||
357 | bool matrix_is_modified(void) | ||
358 | { | ||
359 | return is_modified; | ||
360 | } | ||
361 | |||
362 | inline | ||
363 | bool matrix_has_ghost(void) | ||
364 | { | ||
365 | return false; | ||
366 | } | ||
367 | |||
368 | inline | ||
369 | bool matrix_is_on(uint8_t row, uint8_t col) | ||
370 | { | ||
371 | return (matrix[row] & (1<<col)); | ||
372 | } | ||
373 | |||
374 | inline | ||
375 | uint8_t matrix_get_row(uint8_t row) | ||
376 | { | ||
377 | return matrix[row]; | ||
378 | } | ||
379 | |||
380 | void matrix_print(void) | ||
381 | { | ||
382 | print("\nr/c 01234567\n"); | ||
383 | for (uint8_t row = 0; row < matrix_rows(); row++) { | ||
384 | print_hex8(row); print(": "); | ||
385 | print_bin_reverse8(matrix_get_row(row)); | ||
386 | print("\n"); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | uint8_t matrix_key_count(void) | ||
391 | { | ||
392 | uint8_t count = 0; | ||
393 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||
394 | count += bitpop(matrix[i]); | ||
395 | } | ||
396 | return count; | ||
397 | } | ||