keyboard.c (17797B)
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_line(active_keymods); 335 render_keymods(active_keymods); 336 } 337 // if no more keys are held down, allow a new meta command 338 if (total_pressed < 1) { 339 last_meta_key = 0; 340 if (led_dimmed < 2) { 341 led_idle_counter++; 342 if (led_dimmed == 0 && led_idle_counter > 500000) { 343 led_dimmed = 1; 344 led_brightness = kbd_brightness_get(); 345 } else if (led_dimmed == 1) { 346 if (led_idle_counter % 1000 == 0) { 347 kbd_brightness_dec(); 348 } 349 if (kbd_brightness_get() == 0) { 350 led_dimmed = 2; 351 } 352 } 353 } 354 } 355 // If a key is held down, and the backlight is dimmed, brighten it and reset the timer 356 else { 357 led_idle_counter = 0; 358 if (led_dimmed > 0) { 359 kbd_brightness_set(led_brightness); 360 led_dimmed = 0; 361 } 362 } 363 364 return used_key_codes; 365 } 366 367 int main(void) 368 { 369 #ifdef KBD_VARIANT_QWERTY_US 370 matrix[KBD_COLS*4+1]=KEY_DELETE; 371 matrix_fn[KBD_COLS*4+1]=KEY_DELETE; 372 matrix_fn_toggled[KBD_COLS*4+1]=KEY_DELETE; 373 #endif 374 375 #ifdef KBD_VARIANT_NEO2 376 matrix[KBD_COLS*2+13]=KEY_ENTER; 377 matrix[KBD_COLS*3+0]=HID_KEYBOARD_SC_CAPS_LOCK; // left M3 378 matrix[KBD_COLS*3+13]=KEY_BACKSLASH_AND_PIPE; // M3 379 #ifdef KBD_VARIANT_3 380 matrix[KBD_COLS*3+12]=KEY_BACKSLASH_AND_PIPE; // M3 381 matrix[KBD_COLS*5+2]=HID_KEYBOARD_SC_RIGHT_CONTROL; 382 matrix[KBD_COLS*5+7]=HID_KEYBOARD_SC_LEFT_ALT; 383 matrix[KBD_COLS*5+8]=HID_KEYBOARD_SC_RIGHT_ALT; 384 #endif 385 #endif 386 387 setup_hardware(); 388 GlobalInterruptEnable(); 389 anim_hello(); 390 391 int counter = 0; 392 393 for (;;) 394 { 395 process_keyboard(NULL); 396 HID_Device_USBTask(&Keyboard_HID_Interface); 397 HID_Device_USBTask(&MediaControl_HID_Interface); 398 USB_USBTask(); 399 counter++; 400 401 if (counter%2048 == 0) { 402 refresh_menu_page(); 403 } 404 405 #ifndef KBD_MODE_STANDALONE 406 if (counter>=100000) { 407 remote_check_for_low_battery(); 408 counter = 0; 409 } 410 if (counter%750 == 0) { 411 remote_process_alerts(); 412 } 413 if (should_run_fade_anim) { 414 anim_kbd_hello(); 415 should_run_fade_anim = false; 416 } 417 #endif 418 } 419 } 420 421 void setup_hardware(void) 422 { 423 // Disable watchdog if enabled by bootloader/fuses 424 MCUSR &= ~(1 << WDRF); 425 wdt_disable(); 426 427 // Disable clock division 428 clock_prescale_set(clock_div_1); 429 430 // declare port pins as inputs (0) and outputs (1) 431 DDRB = 0b11110000; 432 DDRC = 0b00000000; 433 DDRD = 0b11011001; 434 DDRE = 0b00000000; 435 DDRF = 0b00000000; 436 437 // initial pin states 438 PORTB = 0b10001111; 439 PORTC = 0b11000000; 440 PORTD = 0b00100000; 441 PORTE = 0b01000000; 442 PORTF = 0b11111111; 443 444 // disable JTAG 445 MCUCR |=(1<<JTD); 446 MCUCR |=(1<<JTD); 447 448 kbd_brightness_init(); 449 gfx_init(false); 450 remote_init(); 451 USB_Init(); 452 } 453 454 ISR(WDT_vect) 455 { 456 // WDT interrupt enable and flag cleared on entry 457 Delay_MS(1); 458 } 459 460 /** Event handler for the library USB Connection event. */ 461 void EVENT_USB_Device_Connect(void) 462 { 463 should_run_fade_anim = true; 464 } 465 466 /** Event handler for the library USB Disconnection event. */ 467 void EVENT_USB_Device_Disconnect(void) 468 { 469 } 470 471 /** Event handler for the library USB Configuration Changed event. */ 472 void EVENT_USB_Device_ConfigurationChanged(void) 473 { 474 bool ConfigSuccess = true; 475 476 ConfigSuccess &= HID_Device_ConfigureEndpoints(&Keyboard_HID_Interface); 477 ConfigSuccess &= HID_Device_ConfigureEndpoints(&MediaControl_HID_Interface); 478 479 USB_Device_EnableSOFEvents(); 480 } 481 482 /** Event handler for the library USB Control Request reception event. */ 483 void EVENT_USB_Device_ControlRequest(void) 484 { 485 HID_Device_ProcessControlRequest(&Keyboard_HID_Interface); 486 HID_Device_ProcessControlRequest(&MediaControl_HID_Interface); 487 } 488 489 /** Event handler for the USB device Start Of Frame event. */ 490 void EVENT_USB_Device_StartOfFrame(void) 491 { 492 HID_Device_MillisecondElapsed(&Keyboard_HID_Interface); 493 HID_Device_MillisecondElapsed(&MediaControl_HID_Interface); 494 } 495 496 /** HID class driver callback function for the creation of HID reports to the host. 497 * 498 * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced 499 * \param[in,out] ReportID Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID 500 * \param[in] ReportType Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature 501 * \param[out] ReportData Pointer to a buffer where the created report should be stored 502 * \param[out] ReportSize Number of bytes written in the report (or zero if no report is to be sent) 503 * 504 * \return Boolean \c true to force the sending of the report, \c false to let the library determine if it needs to be sent 505 */ 506 507 bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, 508 uint8_t* const ReportID, 509 const uint8_t ReportType, 510 void* ReportData, 511 uint16_t* const ReportSize) 512 { 513 int num_keys = process_keyboard(pressed_scancodes); 514 if (num_keys > MAX_SCANCODES) num_keys = MAX_SCANCODES; 515 516 if (HIDInterfaceInfo == &Keyboard_HID_Interface) { 517 // host asks for a keyboard report 518 USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData; 519 *ReportSize = sizeof(USB_KeyboardReport_Data_t); 520 for (int i=0; i<num_keys; i++) { 521 uint8_t sc = pressed_scancodes[i]; 522 if (!is_media_key(sc)) { 523 KeyboardReport->KeyCode[i] = sc; 524 } 525 } 526 } else if (HIDInterfaceInfo == &MediaControl_HID_Interface) { 527 // host asks for a media control report 528 USB_MediaReport_Data_t* MediaControlReport = (USB_MediaReport_Data_t*)ReportData; 529 *ReportSize = sizeof(USB_MediaReport_Data_t); 530 for (int i=0; i<num_keys; i++) { 531 uint8_t sc = pressed_scancodes[i]; 532 if (is_media_key(sc)) { 533 get_media_keys(sc, MediaControlReport); 534 } 535 } 536 } 537 return false; 538 } 539 540 /** HID class driver callback function for the processing of HID reports from the host. 541 * 542 * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced 543 * \param[in] ReportID Report ID of the received report from the host 544 * \param[in] ReportType The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature 545 * \param[in] ReportData Pointer to a buffer where the received report has been stored 546 * \param[in] ReportSize Size in bytes of the received HID report 547 */ 548 void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, 549 const uint8_t ReportID, 550 const uint8_t ReportType, 551 const void* ReportData, 552 const uint16_t ReportSize) 553 { 554 uint8_t* data = (uint8_t*)ReportData; 555 if (ReportSize<4) return; 556 557 hid_report_cmd(data); 558 } 559 /* vim: set tabstop=2:softtabstop=2:shiftwidth=2:expandtab */