qmk_firmware

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

custom_matrix.cpp (7237B)


      1 /*
      2 Copyright 2016 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 
     21 // USB HID host
     22 #include "Usb.h"
     23 #include "usbhub.h"
     24 #include "hid.h"
     25 #include "hidboot.h"
     26 #include "parser.h"
     27 
     28 #include "keycode.h"
     29 #include "util.h"
     30 #include "print.h"
     31 #include "debug.h"
     32 #include "timer.h"
     33 #include "matrix.h"
     34 #include "led.h"
     35 #include "host.h"
     36 #include "keyboard.h"
     37 
     38 /* KEY CODE to Matrix
     39  *
     40  * HID keycode(1 byte):
     41  * Higher 5 bits indicates ROW and lower 3 bits COL.
     42  *
     43  *  7 6 5 4 3 2 1 0
     44  * +---------------+
     45  * |  ROW  |  COL  |
     46  * +---------------+
     47  *
     48  * Matrix space(16 * 16):
     49  *   r\c0123456789ABCDEF
     50  *   0 +----------------+
     51  *   : |                |
     52  *   : |                |
     53  *  16 +----------------+
     54  */
     55 #define ROW_MASK 0xF0
     56 #define COL_MASK 0x0F
     57 #define CODE(row, col) (((row) << 4) | (col))
     58 #define ROW(code)      (((code) & ROW_MASK) >> 4)
     59 #define COL(code)      ((code) & COL_MASK)
     60 #define ROW_BITS(code) (1 << COL(code))
     61 
     62 // Integrated key state of all keyboards
     63 static report_keyboard_t local_keyboard_report;
     64 
     65 /*
     66  * USB Host Shield HID keyboards
     67  * This supports two cascaded hubs and four keyboards
     68  */
     69 USB usb_host;
     70 USBHub hub1(&usb_host);
     71 USBHub hub2(&usb_host);
     72 HIDBoot<HID_PROTOCOL_KEYBOARD> kbd1(&usb_host);
     73 HIDBoot<HID_PROTOCOL_KEYBOARD> kbd2(&usb_host);
     74 HIDBoot<HID_PROTOCOL_KEYBOARD> kbd3(&usb_host);
     75 HIDBoot<HID_PROTOCOL_KEYBOARD> kbd4(&usb_host);
     76 KBDReportParser kbd_parser1;
     77 KBDReportParser kbd_parser2;
     78 KBDReportParser kbd_parser3;
     79 KBDReportParser kbd_parser4;
     80 
     81 extern "C" {
     82     uint8_t matrix_rows(void) { return MATRIX_ROWS; }
     83     uint8_t matrix_cols(void) { return MATRIX_COLS; }
     84     bool matrix_has_ghost(void) { return false; }
     85     void matrix_init(void) {
     86         // USB Host Shield setup
     87         usb_host.Init();
     88         kbd1.SetReportParser(0, (HIDReportParser*)&kbd_parser1);
     89         kbd2.SetReportParser(0, (HIDReportParser*)&kbd_parser2);
     90         kbd3.SetReportParser(0, (HIDReportParser*)&kbd_parser3);
     91         kbd4.SetReportParser(0, (HIDReportParser*)&kbd_parser4);
     92         matrix_init_kb();
     93     }
     94 
     95     static void or_report(report_keyboard_t report) {
     96         // integrate reports into local_keyboard_report
     97         local_keyboard_report.mods |= report.mods;
     98         for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
     99             if (IS_ANY(report.keys[i])) {
    100                 for (uint8_t j = 0; j < KEYBOARD_REPORT_KEYS; j++) {
    101                     if (! local_keyboard_report.keys[j]) {
    102                         local_keyboard_report.keys[j] = report.keys[i];
    103                         break;
    104                     }
    105                 }
    106             }
    107         }
    108     }
    109 
    110     __attribute__ ((weak))
    111     void matrix_init_kb(void) {
    112         matrix_init_user();
    113     }
    114 
    115     __attribute__ ((weak))
    116     void matrix_init_user(void) {
    117     }
    118 
    119     __attribute__ ((weak))
    120     void matrix_scan_kb(void) {
    121         matrix_scan_user();
    122     }
    123 
    124     __attribute__ ((weak))
    125     void matrix_scan_user(void) {
    126     }
    127 
    128     uint8_t matrix_scan(void) {
    129         bool changed = false;
    130         static uint16_t last_time_stamp1 = 0;
    131         static uint16_t last_time_stamp2 = 0;
    132         static uint16_t last_time_stamp3 = 0;
    133         static uint16_t last_time_stamp4 = 0;
    134 
    135         // check report came from keyboards
    136         if (kbd_parser1.time_stamp != last_time_stamp1 ||
    137             kbd_parser2.time_stamp != last_time_stamp2 ||
    138             kbd_parser3.time_stamp != last_time_stamp3 ||
    139             kbd_parser4.time_stamp != last_time_stamp4) {
    140 
    141             last_time_stamp1 = kbd_parser1.time_stamp;
    142             last_time_stamp2 = kbd_parser2.time_stamp;
    143             last_time_stamp3 = kbd_parser3.time_stamp;
    144             last_time_stamp4 = kbd_parser4.time_stamp;
    145 
    146             // clear and integrate all reports
    147             local_keyboard_report = {};
    148             or_report(kbd_parser1.report);
    149             or_report(kbd_parser2.report);
    150             or_report(kbd_parser3.report);
    151             or_report(kbd_parser4.report);
    152 
    153             changed = true;
    154 
    155             dprintf("state:  %02X %02X", local_keyboard_report.mods, local_keyboard_report.reserved);
    156             for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
    157                 dprintf(" %02X", local_keyboard_report.keys[i]);
    158             }
    159             dprint("\r\n");
    160         }
    161 
    162         uint16_t timer;
    163         timer = timer_read();
    164         usb_host.Task();
    165         timer = timer_elapsed(timer);
    166         if (timer > 100) {
    167             dprintf("host.Task: %d\n", timer);
    168         }
    169 
    170         static uint8_t usb_state = 0;
    171         if (usb_state != usb_host.getUsbTaskState()) {
    172             usb_state = usb_host.getUsbTaskState();
    173             dprintf("usb_state: %02X\n", usb_state);
    174 
    175             // restore LED state when keyboard comes up
    176             if (usb_state == USB_STATE_RUNNING) {
    177                 dprintf("speed: %s\n", usb_host.getVbusState()==FSHOST ? "full" : "low");
    178                 led_set(host_keyboard_leds());
    179             }
    180         }
    181         matrix_scan_kb();
    182         return changed;
    183     }
    184 
    185     bool matrix_is_on(uint8_t row, uint8_t col) {
    186         uint8_t code = CODE(row, col);
    187 
    188         if (IS_MODIFIER_KEYCODE(code)) {
    189             if (local_keyboard_report.mods & ROW_BITS(code)) {
    190                 return true;
    191             }
    192         }
    193         for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
    194             if (local_keyboard_report.keys[i] == code) {
    195                 return true;
    196             }
    197         }
    198         return false;
    199     }
    200 
    201     matrix_row_t matrix_get_row(uint8_t row) {
    202         uint16_t row_bits = 0;
    203 
    204         if (IS_MODIFIER_KEYCODE(CODE(row, 0)) && local_keyboard_report.mods) {
    205             row_bits |= local_keyboard_report.mods;
    206         }
    207 
    208         for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
    209             if (IS_ANY(local_keyboard_report.keys[i])) {
    210                 if (row == ROW(local_keyboard_report.keys[i])) {
    211                     row_bits |= ROW_BITS(local_keyboard_report.keys[i]);
    212                 }
    213             }
    214         }
    215         return row_bits;
    216     }
    217 
    218     void matrix_print(void) {
    219         print("\nr/c 0123456789ABCDEF\n");
    220         for (uint8_t row = 0; row < matrix_rows(); row++) {
    221             xprintf("%02d: ", row);
    222             print_bin_reverse16(matrix_get_row(row));
    223             print("\n");
    224         }
    225     }
    226 
    227     void led_set(uint8_t usb_led) {
    228         if (kbd1.isReady()) kbd1.SetReport(0, 0, 2, 0, 1, &usb_led);
    229         if (kbd2.isReady()) kbd2.SetReport(0, 0, 2, 0, 1, &usb_led);
    230         if (kbd3.isReady()) kbd3.SetReport(0, 0, 2, 0, 1, &usb_led);
    231         if (kbd4.isReady()) kbd4.SetReport(0, 0, 2, 0, 1, &usb_led);
    232         led_update_kb((led_t){.raw = usb_led});
    233     }
    234 }