qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

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 }