keyboard.c (17762B)
1 /* 2 MNT Reform 2.0 Keyboard Firmware 3 Copyright 2019-2021 Lukas F. Hartmann / MNT Research GmbH, Berlin (lukas@mntre.com) 4 And Contributors: 5 Chartreuse 6 V Körbes 7 Robey Pointer (robey@lag.net) 8 9 Based on code from LUFA Library (lufa-lib.org): 10 Copyright 2018 Dean Camera (dean [at] fourwalledcubicle [dot] com) 11 12 SPDX-License-Identifier: MIT 13 */ 14 15 #include <stdlib.h> 16 #include <avr/io.h> 17 #include "backlight.h" 18 // Important: version and variant info moved here 19 #include "constants.h" 20 #include "hid_report.h" 21 #include "keyboard.h" 22 #include "menu.h" 23 #include "oled.h" 24 #include "powersave.h" 25 #include "remote.h" 26 #include "scancodes.h" 27 28 #ifdef KBD_VARIANT_ANRI 29 #include "matrix_anri.h" 30 #else 31 #ifdef KBD_VARIANT_3 32 #include "matrix_3.h" 33 #else 34 #ifdef KBD_VARIANT_V 35 #include "matrix_v.h" 36 #else 37 #include "matrix.h" 38 #endif 39 #endif 40 #endif 41 42 /** Buffer to hold the previously generated Keyboard HID report, for comparison purposes inside the HID class driver. */ 43 static uint8_t PrevKeyboardHIDReportBuffer[sizeof(USB_KeyboardReport_Data_t)]; 44 static uint8_t PrevMediaControlHIDReportBuffer[sizeof(USB_MediaReport_Data_t)]; 45 46 /** LUFA HID Class driver interface configuration and state information. This structure is 47 * passed to all HID Class driver functions, so that multiple instances of the same class 48 * within a device can be differentiated from one another. 49 */ 50 USB_ClassInfo_HID_Device_t Keyboard_HID_Interface = 51 { 52 .Config = 53 { 54 .InterfaceNumber = INTERFACE_ID_Keyboard, 55 .ReportINEndpoint = 56 { 57 .Address = KEYBOARD_EPADDR, 58 .Size = HID_EPSIZE, 59 .Banks = 1, 60 }, 61 .PrevReportINBuffer = PrevKeyboardHIDReportBuffer, 62 .PrevReportINBufferSize = sizeof(PrevKeyboardHIDReportBuffer), 63 }, 64 }; 65 66 /** LUFA HID Class driver interface configuration and state information for the Media Controller */ 67 USB_ClassInfo_HID_Device_t MediaControl_HID_Interface = 68 { 69 .Config = 70 { 71 .InterfaceNumber = INTERFACE_ID_MediaControl, 72 .ReportINEndpoint = 73 { 74 .Address = MEDIACONTROL_EPADDR, 75 .Size = HID_EPSIZE, 76 .Banks = 1, 77 }, 78 .PrevReportINBuffer = PrevMediaControlHIDReportBuffer, 79 .PrevReportINBufferSize = sizeof(PrevMediaControlHIDReportBuffer), 80 }, 81 }; 82 83 enum keymods { 84 SHIFT = 1, 85 CONTROL = 2, 86 AGR = 4, 87 ALT = 8, 88 SUPER = 16, 89 }; 90 91 uint8_t matrix_debounce[KBD_COLS*KBD_ROWS]; 92 uint8_t matrix_state[KBD_COLS*KBD_ROWS]; 93 94 int active_meta_mode = 0; 95 uint8_t last_meta_key = 0; 96 97 uint8_t* active_matrix = matrix; 98 int active_keymods = 0; 99 bool media_toggle = 0; 100 bool fn_key = 0; // Am I holding FN? 101 bool circle = 0; // Am I holding circle? 102 bool help_display = 0; // Is the Hyper help screen displayed? 103 bool should_run_fade_anim = false; 104 105 int led_brightness; 106 int led_dimmed = 0; 107 uint32_t led_idle_counter = 0; 108 109 // enter the menu 110 void enter_meta_mode(void) { 111 active_meta_mode = 1; 112 reset_and_render_menu(); 113 } 114 115 void reset_keyboard_state(void) { 116 for (int i = 0; i < KBD_COLS*KBD_ROWS; i++) { 117 matrix_debounce[i] = 0; 118 matrix_state[i] = 0; 119 } 120 last_meta_key = 0; 121 reset_menu(); 122 } 123 124 inline bool is_media_key(uint8_t keycode) { 125 return (keycode>=HID_KEYBOARD_SC_MEDIA_PLAY); 126 } 127 128 void get_media_keys(uint8_t keycode, USB_MediaReport_Data_t* mcr) { 129 switch (keycode) { 130 case HID_KEYBOARD_SC_MEDIA_BRIGHTNESS_DOWN: mcr->BrightnessDown = 1; break; 131 case HID_KEYBOARD_SC_MEDIA_BRIGHTNESS_UP: mcr->BrightnessUp = 1; break; 132 case HID_KEYBOARD_SC_MEDIA_PREVIOUS_TRACK: mcr->PreviousTrack = 1; break; 133 case HID_KEYBOARD_SC_MEDIA_PLAY: mcr->PlayPause = 1; break; 134 case HID_KEYBOARD_SC_MEDIA_NEXT_TRACK: mcr->NextTrack = 1; break; 135 case HID_KEYBOARD_SC_MEDIA_MUTE: mcr->Mute = 1; break; 136 case HID_KEYBOARD_SC_MEDIA_VOLUME_DOWN: mcr->VolumeDown = 1; break; 137 case HID_KEYBOARD_SC_MEDIA_VOLUME_UP: mcr->VolumeUp = 1; break; 138 } 139 } 140 141 #define MAX_SCANCODES 6 142 static uint8_t pressed_scancodes[MAX_SCANCODES] = {0,0,0,0,0,0}; 143 144 // number of cycles a key has to remain pressed to register a keypress 145 // is at least 1 but at most 8 146 #define DEBOUNCE_BITS 1 147 148 // usb_report_mode: if you pass 0, you can leave KeyboardReport NULL 149 int process_keyboard(uint8_t* resulting_scancodes) { 150 // how many keys are pressed this round 151 uint8_t total_pressed = 0; 152 uint8_t used_key_codes = 0; 153 154 // create a bitmask with the lowest DEBOUNCE_BITS number of bits set to 1 155 // 1 -> 0b00000001 156 // 2 -> 0b00000011 157 // ... 158 // 8 -> 0b11111111 159 uint8_t debounce_bitmask = (1<<DEBOUNCE_BITS)-1; 160 161 int old_keymods = active_keymods; 162 bool left_ctrl_pressed = 1; 163 bool left_shift_pressed = 1; 164 // pull ROWs low one after the other 165 for (int y = 0; y < KBD_ROWS; y++) { 166 switch (y) { 167 case 0: output_low(PORTB, 6); break; 168 case 1: output_low(PORTB, 5); break; 169 case 2: output_low(PORTB, 4); break; 170 case 3: output_low(PORTD, 7); break; 171 case 4: output_low(PORTD, 6); break; 172 case 5: output_low(PORTD, 4); break; 173 } 174 175 // wait for signal to stabilize 176 // TODO maybe not necessary 177 //_delay_us(10); 178 179 // check input COLs 180 for (int x=0; x<14; x++) { 181 uint16_t keycode; 182 uint16_t loc = y*KBD_COLS+x; 183 keycode = active_matrix[loc]; 184 uint8_t pressed = 0; 185 uint8_t debounced_pressed = 0; 186 187 // column pins are all over the place 188 switch (x) { 189 case 0: pressed = !(PIND&(1<<5)); break; 190 case 1: pressed = !(PINF&(1<<7)); break; 191 case 2: pressed = !(PINE&(1<<6)); break; 192 case 3: pressed = !(PINC&(1<<7)); break; 193 case 4: pressed = !(PINB&(1<<3)); break; 194 case 5: pressed = !(PINB&(1<<2)); break; 195 case 6: pressed = !(PINB&(1<<1)); break; 196 case 7: pressed = !(PINB&(1<<0)); break; 197 case 8: pressed = !(PINF&(1<<0)); break; 198 case 9: pressed = !(PINF&(1<<1)); break; 199 case 10: pressed = !(PINF&(1<<4)); break; 200 case 11: pressed = !(PINF&(1<<5)); break; 201 case 12: pressed = !(PINF&(1<<6)); break; 202 case 13: pressed = !(PINC&(1<<6)); break; 203 } 204 205 // shift new state as bit into debounce "register" 206 matrix_debounce[loc] = (matrix_debounce[loc]<<1)|pressed; 207 208 // if unclear state, we need to keep the last state of the key 209 if (matrix_debounce[loc] == 0x00) { 210 matrix_state[loc] = 0; 211 } else if (matrix_debounce[loc] == debounce_bitmask) { 212 // the key has been pressed for the last DEBOUNCE_BITS number of 213 // cycles -> register key press 214 matrix_state[loc] = 1; 215 } 216 debounced_pressed = matrix_state[loc]; 217 218 if (debounced_pressed) { 219 total_pressed++; 220 // set active keymod for OLED display 221 if (keycode == HID_KEYBOARD_SC_LEFT_CONTROL || keycode == HID_KEYBOARD_SC_RIGHT_CONTROL) { 222 active_keymods |= CONTROL; 223 } else if (keycode == HID_KEYBOARD_SC_LEFT_SHIFT || keycode == HID_KEYBOARD_SC_RIGHT_SHIFT) { 224 active_keymods |= SHIFT; 225 } else if (keycode == HID_KEYBOARD_SC_RIGHT_ALT) { 226 active_keymods |= AGR; 227 } else if (keycode == HID_KEYBOARD_SC_LEFT_ALT) { 228 active_keymods |= ALT; 229 } else if (keycode == HID_KEYBOARD_SC_LEFT_GUI) { 230 active_keymods |= SUPER; 231 } 232 // Is circle key pressed? 233 if (keycode == KEY_CIRCLE) { 234 if (fn_key) { 235 circle = 1; 236 } else { 237 if (!active_meta_mode && !last_meta_key) { 238 enter_meta_mode(); 239 } 240 } 241 } else if (keycode == HID_KEYBOARD_SC_EXECUTE) { 242 fn_key = 1; 243 active_matrix = matrix_fn; 244 if (!help_display) { 245 render_help(); 246 help_display = 1; 247 } 248 } else { 249 if (active_meta_mode) { 250 // not holding the same key? 251 if (last_meta_key != keycode) { 252 // hyper/circle/menu functions 253 int stay_meta = execute_meta_function(keycode); 254 // don't repeat action while key is held down 255 last_meta_key = keycode; 256 257 // exit meta mode 258 if (!stay_meta) { 259 active_meta_mode = 0; 260 } 261 262 // after wake-up from sleep mode, skip further keymap processing 263 if (stay_meta == 2) { 264 reset_keyboard_state(); 265 enter_meta_mode(); 266 return 0; 267 } 268 } 269 } else if (!last_meta_key) { 270 // not meta mode, regular key: report keypress via USB 271 // 6 keys is the limit in the HID descriptor 272 if (used_key_codes < MAX_SCANCODES && resulting_scancodes) { 273 resulting_scancodes[used_key_codes++] = keycode; 274 } 275 } 276 } 277 } else { 278 // key not pressed 279 if (keycode == HID_KEYBOARD_SC_EXECUTE) { 280 fn_key = 0; 281 if (help_display) { 282 clear_display(); 283 help_display = 0; 284 } 285 if (media_toggle) { 286 active_matrix = matrix_fn_toggled; 287 } else { 288 active_matrix = matrix; 289 } 290 } else if (keycode == KEY_CIRCLE) { 291 if (fn_key && circle) { 292 if (!media_toggle) { 293 media_toggle = 1; 294 active_matrix = matrix_fn_toggled; 295 } else { 296 media_toggle = 0; 297 active_matrix = matrix_fn; 298 } 299 } 300 circle = 0; 301 } 302 // disable active keymod for OLED display 303 if (active_keymods) { 304 if (keycode == HID_KEYBOARD_SC_LEFT_CONTROL) { 305 left_ctrl_pressed = 0; 306 } else if (keycode == HID_KEYBOARD_SC_LEFT_SHIFT) { 307 left_shift_pressed = 0; 308 } else if (!left_ctrl_pressed && keycode == HID_KEYBOARD_SC_RIGHT_CONTROL) { 309 active_keymods &= ~ CONTROL; 310 } else if (!left_shift_pressed && keycode == HID_KEYBOARD_SC_RIGHT_SHIFT) { 311 active_keymods &= ~ SHIFT; 312 } else if (keycode == HID_KEYBOARD_SC_RIGHT_ALT) { 313 active_keymods &= ~ AGR; 314 } else if (keycode == HID_KEYBOARD_SC_LEFT_ALT) { 315 active_keymods &= ~ ALT; 316 } else if (keycode == HID_KEYBOARD_SC_LEFT_GUI) { 317 active_keymods &= ~ SUPER; 318 } 319 } 320 } 321 } 322 323 switch (y) { 324 case 0: output_high(PORTB, 6); break; 325 case 1: output_high(PORTB, 5); break; 326 case 2: output_high(PORTB, 4); break; 327 case 3: output_high(PORTD, 7); break; 328 case 4: output_high(PORTD, 6); break; 329 case 5: output_high(PORTD, 4); break; 330 } 331 } 332 333 if (old_keymods != active_keymods) { 334 render_keymods(active_keymods); 335 } 336 // if no more keys are held down, allow a new meta command 337 if (total_pressed < 1) { 338 last_meta_key = 0; 339 if (led_dimmed < 2) { 340 led_idle_counter++; 341 if (led_dimmed == 0 && led_idle_counter > 500000) { 342 led_dimmed = 1; 343 led_brightness = kbd_brightness_get(); 344 } else if (led_dimmed == 1) { 345 if (led_idle_counter % 1000 == 0) { 346 kbd_brightness_dec(); 347 } 348 if (kbd_brightness_get() == 0) { 349 led_dimmed = 2; 350 } 351 } 352 } 353 } 354 // If a key is held down, and the backlight is dimmed, brighten it and reset the timer 355 else { 356 led_idle_counter = 0; 357 if (led_dimmed > 0) { 358 kbd_brightness_set(led_brightness); 359 led_dimmed = 0; 360 } 361 } 362 363 return used_key_codes; 364 } 365 366 int main(void) 367 { 368 #ifdef KBD_VARIANT_QWERTY_US 369 matrix[KBD_COLS*4+1]=KEY_DELETE; 370 matrix_fn[KBD_COLS*4+1]=KEY_DELETE; 371 matrix_fn_toggled[KBD_COLS*4+1]=KEY_DELETE; 372 #endif 373 374 #ifdef KBD_VARIANT_NEO2 375 matrix[KBD_COLS*2+13]=KEY_ENTER; 376 matrix[KBD_COLS*3+0]=HID_KEYBOARD_SC_CAPS_LOCK; // left M3 377 matrix[KBD_COLS*3+13]=KEY_BACKSLASH_AND_PIPE; // M3 378 #ifdef KBD_VARIANT_3 379 matrix[KBD_COLS*3+12]=KEY_BACKSLASH_AND_PIPE; // M3 380 matrix[KBD_COLS*5+2]=HID_KEYBOARD_SC_RIGHT_CONTROL; 381 matrix[KBD_COLS*5+7]=HID_KEYBOARD_SC_LEFT_ALT; 382 matrix[KBD_COLS*5+8]=HID_KEYBOARD_SC_RIGHT_ALT; 383 #endif 384 #endif 385 386 setup_hardware(); 387 GlobalInterruptEnable(); 388 anim_hello(); 389 390 int counter = 0; 391 392 for (;;) 393 { 394 process_keyboard(NULL); 395 HID_Device_USBTask(&Keyboard_HID_Interface); 396 HID_Device_USBTask(&MediaControl_HID_Interface); 397 USB_USBTask(); 398 counter++; 399 400 if (counter%2048 == 0) { 401 refresh_menu_page(); 402 } 403 404 #ifndef KBD_MODE_STANDALONE 405 if (counter>=100000) { 406 remote_check_for_low_battery(); 407 counter = 0; 408 } 409 if (counter%750 == 0) { 410 remote_process_alerts(); 411 } 412 if (should_run_fade_anim) { 413 anim_kbd_hello(); 414 should_run_fade_anim = false; 415 } 416 #endif 417 } 418 } 419 420 void setup_hardware(void) 421 { 422 // Disable watchdog if enabled by bootloader/fuses 423 MCUSR &= ~(1 << WDRF); 424 wdt_disable(); 425 426 // Disable clock division 427 clock_prescale_set(clock_div_1); 428 429 // declare port pins as inputs (0) and outputs (1) 430 DDRB = 0b11110000; 431 DDRC = 0b00000000; 432 DDRD = 0b11011001; 433 DDRE = 0b00000000; 434 DDRF = 0b00000000; 435 436 // initial pin states 437 PORTB = 0b10001111; 438 PORTC = 0b11000000; 439 PORTD = 0b00100000; 440 PORTE = 0b01000000; 441 PORTF = 0b11111111; 442 443 // disable JTAG 444 MCUCR |=(1<<JTD); 445 MCUCR |=(1<<JTD); 446 447 kbd_brightness_init(); 448 gfx_init(false); 449 remote_init(); 450 USB_Init(); 451 } 452 453 ISR(WDT_vect) 454 { 455 // WDT interrupt enable and flag cleared on entry 456 Delay_MS(1); 457 } 458 459 /** Event handler for the library USB Connection event. */ 460 void EVENT_USB_Device_Connect(void) 461 { 462 should_run_fade_anim = true; 463 } 464 465 /** Event handler for the library USB Disconnection event. */ 466 void EVENT_USB_Device_Disconnect(void) 467 { 468 } 469 470 /** Event handler for the library USB Configuration Changed event. */ 471 void EVENT_USB_Device_ConfigurationChanged(void) 472 { 473 bool ConfigSuccess = true; 474 475 ConfigSuccess &= HID_Device_ConfigureEndpoints(&Keyboard_HID_Interface); 476 ConfigSuccess &= HID_Device_ConfigureEndpoints(&MediaControl_HID_Interface); 477 478 USB_Device_EnableSOFEvents(); 479 } 480 481 /** Event handler for the library USB Control Request reception event. */ 482 void EVENT_USB_Device_ControlRequest(void) 483 { 484 HID_Device_ProcessControlRequest(&Keyboard_HID_Interface); 485 HID_Device_ProcessControlRequest(&MediaControl_HID_Interface); 486 } 487 488 /** Event handler for the USB device Start Of Frame event. */ 489 void EVENT_USB_Device_StartOfFrame(void) 490 { 491 HID_Device_MillisecondElapsed(&Keyboard_HID_Interface); 492 HID_Device_MillisecondElapsed(&MediaControl_HID_Interface); 493 } 494 495 /** HID class driver callback function for the creation of HID reports to the host. 496 * 497 * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced 498 * \param[in,out] ReportID Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID 499 * \param[in] ReportType Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature 500 * \param[out] ReportData Pointer to a buffer where the created report should be stored 501 * \param[out] ReportSize Number of bytes written in the report (or zero if no report is to be sent) 502 * 503 * \return Boolean \c true to force the sending of the report, \c false to let the library determine if it needs to be sent 504 */ 505 506 bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, 507 uint8_t* const ReportID, 508 const uint8_t ReportType, 509 void* ReportData, 510 uint16_t* const ReportSize) 511 { 512 int num_keys = process_keyboard(pressed_scancodes); 513 if (num_keys > MAX_SCANCODES) num_keys = MAX_SCANCODES; 514 515 if (HIDInterfaceInfo == &Keyboard_HID_Interface) { 516 // host asks for a keyboard report 517 USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData; 518 *ReportSize = sizeof(USB_KeyboardReport_Data_t); 519 for (int i=0; i<num_keys; i++) { 520 uint8_t sc = pressed_scancodes[i]; 521 if (!is_media_key(sc)) { 522 KeyboardReport->KeyCode[i] = sc; 523 } 524 } 525 } else if (HIDInterfaceInfo == &MediaControl_HID_Interface) { 526 // host asks for a media control report 527 USB_MediaReport_Data_t* MediaControlReport = (USB_MediaReport_Data_t*)ReportData; 528 *ReportSize = sizeof(USB_MediaReport_Data_t); 529 for (int i=0; i<num_keys; i++) { 530 uint8_t sc = pressed_scancodes[i]; 531 if (is_media_key(sc)) { 532 get_media_keys(sc, MediaControlReport); 533 } 534 } 535 } 536 return false; 537 } 538 539 /** HID class driver callback function for the processing of HID reports from the host. 540 * 541 * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced 542 * \param[in] ReportID Report ID of the received report from the host 543 * \param[in] ReportType The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature 544 * \param[in] ReportData Pointer to a buffer where the received report has been stored 545 * \param[in] ReportSize Size in bytes of the received HID report 546 */ 547 void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, 548 const uint8_t ReportID, 549 const uint8_t ReportType, 550 const void* ReportData, 551 const uint16_t ReportSize) 552 { 553 uint8_t* data = (uint8_t*)ReportData; 554 if (ReportSize<4) return; 555 556 hid_report_cmd(data); 557 } 558 /* vim: set tabstop=2:softtabstop=2:shiftwidth=2:expandtab */