matrix.c (8386B)
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 <wakojun@gmail.com> 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 "matrix.h" 21 #include "debug.h" 22 #include "wait.h" 23 #include "uart.h" 24 #include "timer.h" 25 26 27 /* 28 * Matrix Array usage: 29 * 30 * ROW: 12(4bits) 31 * COL: 8(3bits) 32 * 33 * +---------+ 34 * 0|00 ... 07| 35 * 1|00 ... 07| 36 * :| ... | 37 * :| ... | 38 * A| | 39 * B| | 40 * +---------+ 41 */ 42 static uint8_t matrix[MATRIX_ROWS]; 43 44 45 // we're going to need a sleep timer 46 static uint16_t last_activity ; 47 // and a byte to track duplicate up events signalling all keys up. 48 static uint16_t last_upKey ; 49 // serial device can disconnect. Check every MAXDROP characters. 50 static uint16_t disconnect_counter = 0; 51 52 53 // bitmath masks. 54 #define KEY_MASK 0b10000000 55 #define COL_MASK 0b00000111 56 #define ROW_MASK 0b01111000 57 58 59 #define ROW(code) (( code & ROW_MASK ) >>3) 60 #define COL(code) ((code & COL_MASK) ) 61 #define KEYUP(code) ((code & KEY_MASK) >>7 ) 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 gpio_set_pin_output(VCC_PIN); 99 gpio_write_pin_low(VCC_PIN); 100 101 #if ( HANDSPRING == 0) 102 103 #ifdef CY835 104 gpio_set_pin_output(GND_PIN); 105 gpio_write_pin_low(GND_PIN); 106 107 gpio_set_pin_output(PULLDOWN_PIN); 108 gpio_write_pin_low(PULLDOWN_PIN); 109 #endif 110 111 gpio_set_pin_input(DCD_PIN); 112 gpio_set_pin_input(RTS_PIN); 113 #endif 114 115 /* check that the other side isn't powered up. 116 test=gpio_read_pin(DCD_PIN); 117 xprintf("b%02X:", test); 118 test=gpio_read_pin(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=gpio_read_pin(RTS_PIN); 132 // printf("r%02X:", firstread); 133 134 gpio_set_pin_output(RTS_PIN); 135 136 if (firstread) { 137 gpio_write_pin_low(RTS_PIN); 138 } 139 wait_ms(10); 140 gpio_write_pin_high(RTS_PIN); 141 142 143 /* the future is Arm 144 if (!palReadPad(RTS_PIN_IOPRT)) 145 { 146 wait_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 wait_ms(10); 156 palSetPad(RTS_PORT, RTS_PIN); 157 } 158 */ 159 160 161 wait_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 = uart_read(); 170 if (code) { 171 dprintf("%02X ", code); 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 gpio_write_pin_low(VCC_PIN); 227 wait_ms(5); 228 gpio_write_pin_high(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 uart_init(9600); // 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 gpio_write_pin_high(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 wait_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( !gpio_read_pin(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 wait_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_kb(); 286 return; 287 288 289 } 290 291 292 uint8_t matrix_scan(void) 293 { 294 uint8_t code; 295 code = uart_read(); 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 dprintf("%02X ", code); 320 321 switch (code) { 322 case 0xFD: // unexpected reset byte 2 323 print("rstD "); 324 return 0; 325 case 0xFA: // unexpected reset 326 print("rstA "); 327 return 0; 328 } 329 330 if (KEYUP(code)) { 331 if (code == last_upKey) { 332 // all keys are not pressed. 333 // Manual says to disable all modifiers left open now. 334 // but that could defeat sticky keys. 335 // BUG? dropping this byte. 336 last_upKey=0; 337 return 0; 338 } 339 // release 340 if (matrix_is_on(ROW(code), COL(code))) { 341 matrix[ROW(code)] &= ~(1<<COL(code)); 342 last_upKey=code; 343 } 344 } else { 345 // press 346 if (!matrix_is_on(ROW(code), COL(code))) { 347 matrix[ROW(code)] |= (1<<COL(code)); 348 349 } 350 } 351 352 matrix_scan_kb(); 353 return code; 354 } 355 356 inline 357 bool matrix_has_ghost(void) 358 { 359 return false; 360 } 361 362 inline 363 bool matrix_is_on(uint8_t row, uint8_t col) 364 { 365 return (matrix[row] & (1<<col)); 366 } 367 368 inline 369 uint8_t matrix_get_row(uint8_t row) 370 { 371 return matrix[row]; 372 } 373 374 void matrix_print(void) 375 { 376 print("\nr/c 01234567\n"); 377 for (uint8_t row = 0; row < matrix_rows(); row++) { 378 print_hex8(row); print(": "); 379 print_bin_reverse8(matrix_get_row(row)); 380 print("\n"); 381 } 382 }