qmk_firmware

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

matrix.c (5848B)


      1 /*
      2 Copyright 2011 Jun Wako <wakojun@gmail.com>
      3 
      4 This program is free software: you can redistribute it and/or modify
      5 it under the terms of the GNU General Public License as published by
      6 the Free Software Foundation, either version 2 of the License, or
      7 (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 GNU General Public License for more details.
     13 
     14 You should have received a copy of the GNU General Public License
     15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17 
     18 #include <stdint.h>
     19 #include <stdbool.h>
     20 #include <avr/io.h>
     21 #include <util/delay.h>
     22 #include "print.h"
     23 #include "util.h"
     24 #include "debug.h"
     25 #include "ps2.h"
     26 #include "matrix.h"
     27 
     28 #define print_matrix_row(row)  print_bin_reverse8(matrix_get_row(row))
     29 #define print_matrix_header()  print("\nr/c 01234567\n")
     30 #define ROW_SHIFTER ((uint8_t)1)
     31 
     32 
     33 static void matrix_make(uint8_t code);
     34 static void matrix_break(uint8_t code);
     35 
     36 
     37 /*
     38  * Matrix Array usage:
     39  * 'Scan Code Set 3' is assigned into 17x8 cell matrix.
     40  *
     41  *    8bit wide
     42  *   +---------+
     43  *  0|         |
     44  *  :|         | 0x00-0x87
     45  *  ;|         |
     46  * 17|         |
     47  *   +---------+
     48  */
     49 static uint8_t matrix[MATRIX_ROWS];
     50 #define ROW(code)      (code>>3)
     51 #define COL(code)      (code&0x07)
     52 
     53 
     54 __attribute__ ((weak))
     55 void matrix_init_user(void) {
     56 }
     57 
     58 void matrix_init(void)
     59 {
     60     debug_enable = true;
     61     //debug_matrix = true;
     62     //debug_keyboard = true;
     63     //debug_mouse = false;
     64 
     65     ps2_host_init();
     66 
     67     // initialize matrix state: all keys off
     68     for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
     69 
     70     matrix_init_user();
     71     return;
     72 }
     73 
     74 uint8_t matrix_scan(void)
     75 {
     76 
     77     // scan code reading states
     78     static enum {
     79         RESET,
     80         RESET_RESPONSE,
     81         KBD_ID0,
     82         KBD_ID1,
     83         CONFIG,
     84         READY,
     85         F0_BREAK,
     86     } state = RESET;
     87 
     88     uint8_t code;
     89     if ((code = ps2_host_recv())) {
     90         dprintf("r%02X ", code);
     91     }
     92 
     93     switch (state) {
     94         case RESET:
     95             dprint("wFF ");
     96             if (ps2_host_send(0xFF) == 0xFA) {
     97                 dprint("[ack]\nRESET_RESPONSE: ");
     98                 state = RESET_RESPONSE;
     99             }
    100             break;
    101         case RESET_RESPONSE:
    102             if (code == 0xAA) {
    103                 dprint("[ok]\nKBD_ID: ");
    104                 state = KBD_ID0;
    105             } else if (code) {
    106                 dprint("err\nRESET: ");
    107                 state = RESET;
    108             }
    109             break;
    110         // after reset receive keyboard ID(2 bytes)
    111         case KBD_ID0:
    112             if (code) {
    113                 state = KBD_ID1;
    114             }
    115             break;
    116         case KBD_ID1:
    117             if (code) {
    118                 dprint("\nCONFIG: ");
    119                 state = CONFIG;
    120             }
    121             break;
    122         case CONFIG:
    123             dprint("wF8 ");
    124             if (ps2_host_send(0xF8) == 0xFA) {
    125                 dprint("[ack]\nREADY\n");
    126                 state = READY;
    127             }
    128             break;
    129         case READY:
    130             switch (code) {
    131                 case 0x00:
    132                     break;
    133                 case 0xF0:
    134                     state = F0_BREAK;
    135                     dprint(" ");
    136                     break;
    137                 default:    // normal key make
    138                     if (code < 0x88) {
    139                         matrix_make(code);
    140                     } else {
    141                         dprintf("unexpected scan code at READY: %02X\n", code);
    142                     }
    143                     state = READY;
    144                     dprint("\n");
    145             }
    146             break;
    147         case F0_BREAK:    // Break code
    148             switch (code) {
    149                 case 0x00:
    150                     break;
    151                 default:
    152                     if (code < 0x88) {
    153                         matrix_break(code);
    154                     } else {
    155                         dprintf("unexpected scan code at F0: %02X\n", code);
    156                     }
    157                     state = READY;
    158                     dprint("\n");
    159             }
    160             break;
    161     }
    162     return 1;
    163 }
    164 
    165 inline
    166 uint8_t matrix_get_row(uint8_t row)
    167 {
    168     return matrix[row];
    169 }
    170 
    171 inline
    172 static void matrix_make(uint8_t code)
    173 {
    174     if (!matrix_is_on(ROW(code), COL(code))) {
    175         matrix[ROW(code)] |= 1<<COL(code);
    176     }
    177 }
    178 
    179 inline
    180 static void matrix_break(uint8_t code)
    181 {
    182     if (matrix_is_on(ROW(code), COL(code))) {
    183         matrix[ROW(code)] &= ~(1<<COL(code));
    184     }
    185 }
    186 
    187 bool matrix_is_on(uint8_t row, uint8_t col)
    188 {
    189     return (matrix_get_row(row) & (1<<col));
    190 }
    191 
    192 void matrix_print(void)
    193 {
    194 #if (MATRIX_COLS <= 8)
    195     print("r/c 01234567\n");
    196 #elif (MATRIX_COLS <= 16)
    197     print("r/c 0123456789ABCDEF\n");
    198 #elif (MATRIX_COLS <= 32)
    199     print("r/c 0123456789ABCDEF0123456789ABCDEF\n");
    200 #endif
    201 
    202     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
    203 
    204 #if (MATRIX_COLS <= 8)
    205         xprintf("%02X: %08b%s\n", row, bitrev(matrix_get_row(row)),
    206 #elif (MATRIX_COLS <= 16)
    207         xprintf("%02X: %016b%s\n", row, bitrev16(matrix_get_row(row)),
    208 #elif (MATRIX_COLS <= 32)
    209         xprintf("%02X: %032b%s\n", row, bitrev32(matrix_get_row(row)),
    210 #endif
    211 #ifdef MATRIX_HAS_GHOST
    212         matrix_has_ghost_in_row(row) ?  " <ghost" : ""
    213 #else
    214         ""
    215 #endif
    216         );
    217     }
    218 }
    219 
    220 #ifdef MATRIX_HAS_GHOST
    221 __attribute__ ((weak))
    222 bool matrix_has_ghost_in_row(uint8_t row)
    223 {
    224     matrix_row_t matrix_row = matrix_get_row(row);
    225     // No ghost exists when less than 2 keys are down on the row
    226     if (((matrix_row - 1) & matrix_row) == 0)
    227         return false;
    228 
    229     // Ghost occurs when the row shares column line with other row
    230     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
    231         if (i != row && (matrix_get_row(i) & matrix_row))
    232             return true;
    233     }
    234     return false;
    235 }
    236 #endif