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 }