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