bool command_extra(uint8_t code) { uint32_t t; uint16_t b; switch (code) { case KC_H: case KC_SLASH: /* ? */ print("\n\n----- Bluetooth RN-42 Help -----\n"); print("i: RN-42 info\n"); print("b: battery voltage\n"); print("Del: enter/exit RN-42 config mode\n"); print("Slck: RN-42 initialize\n"); print("1-4: restore link\n"); print("F1-F4: store link\n"); print("p: pairing\n"); if (config_mode) { return true; } else { print("u: toggle Force USB mode\n"); return false; // to display default command help } case KC_P: pairing(); return true; /* Store link address to EEPROM */ case KC_F1: store_link(RN42_LINK0); return true; case KC_F2: store_link(RN42_LINK1); return true; case KC_F3: store_link(RN42_LINK2); return true; case KC_F4: store_link(RN42_LINK3); return true; /* Restore link address to EEPROM */ case KC_1: restore_link(RN42_LINK0); return true; case KC_2: restore_link(RN42_LINK1); return true; case KC_3: restore_link(RN42_LINK2); return true; case KC_4: restore_link(RN42_LINK3); return true; case KC_5: xprintf("blah! \n"); //rn42_cts_hi(); if (stay_connected == 1){ dprintf("Disconnect after 5 min.\n"); stay_connected = !stay_connected; }else{ dprintf("Stay connected.\n"); stay_connected = 1; //last_press_timer = timer_read32(); } return true; case KC_6: clear_keyboard(); host_set_driver(&rn42_config_driver); // null driver; not to send a key to host rn42_disconnect(); return true; case KC_I: print("\n----- RN-42 info -----\n"); xprintf("protocol: %s\n", (host_get_driver() == &rn42_driver) ? "RN-42" : "LUFA"); xprintf("force_usb: %X\n", force_usb); xprintf("rn42: %s\n", rn42_rts() ? "OFF" : (rn42_linked() ? "CONN" : "ON")); xprintf("rn42_autoconnecting(): %X\n", rn42_autoconnecting()); xprintf("config_mode: %X\n", config_mode); xprintf("USB State: %s\n", (USB_DeviceState == DEVICE_STATE_Unattached) ? "Unattached" : (USB_DeviceState == DEVICE_STATE_Powered) ? "Powered" : (USB_DeviceState == DEVICE_STATE_Default) ? "Default" : (USB_DeviceState == DEVICE_STATE_Addressed) ? "Addressed" : (USB_DeviceState == DEVICE_STATE_Configured) ? "Configured" : (USB_DeviceState == DEVICE_STATE_Suspended) ? "Suspended" : "?"); xprintf("battery: "); switch (battery_status()) { case FULL_CHARGED: xprintf("FULL"); break; case CHARGING: xprintf("CHARG"); break; case DISCHARGING: xprintf("DISCHG"); break; case LOW_VOLTAGE: xprintf("LOW"); break; default: xprintf("?"); break; }; xprintf("\n"); xprintf("RemoteWakeupEnabled: %X\n", USB_Device_RemoteWakeupEnabled); xprintf("VBUS: %X\n", USBSTA&(1<<VBUS)); t = timer_read32()/1000; uint8_t d = t/3600/24; uint8_t h = t/3600; uint8_t m = t%3600/60; uint8_t s = t%60; xprintf("uptime: %02u %02u:%02u:%02u\n", d, h, m, s); xprintf("LINK0: %s\r\n", get_link(RN42_LINK0)); xprintf("LINK1: %s\r\n", get_link(RN42_LINK1)); xprintf("LINK2: %s\r\n", get_link(RN42_LINK2)); xprintf("LINK3: %s\r\n", get_link(RN42_LINK3)); return true; case KC_B: // battery monitor t = timer_read32()/1000; b = battery_voltage(); xprintf("BAT: %umV\t", b); xprintf("%02u:", t/3600); xprintf("%02u:", t%3600/60); xprintf("%02u\n", t%60); return true; case KC_U: if (config_mode) return false; if (force_usb) { print("Auto mode\n"); force_usb = false; } else { print("USB mode\n"); clear_keyboard(); host_set_driver(&rn42_driver); } return true; case KC_DELETE: /* RN-42 Command mode */ if (rn42_autoconnecting()) { enter_command_mode(); command_state = CONSOLE; config_mode = true; } else { exit_command_mode(); command_state = ONESHOT; config_mode = false; } return true; case KC_SCROLLLOCK: init_rn42(); return true; default: if (config_mode) return true; else return false; // yield to default command } return true; }
/* void pid_loop() Calculates the updated PID output and parameters for each iteration. */ void pid_loop() { if (pid_state != PID_RUNNING) return; uint32 dummy_time; boolean is_update_pid = timer_is_elapsed32((pid_last_timestamp + PID_LOOP_WAIT_IN_NS), &dummy_time); if (!is_update_pid) { DEBUG_MSG_HIGH(DEBUG_MODULE_PID, "Timer not expired. Time: %d", dummy_time); return; } /* Update the last time PID was read for scheduling next iteration. */ pid_last_timestamp = timer_read32(); /* Read updated temperatures. If last reading was invalid, skip this PID loop iteration. */ therm_reading_t *temp = &(pid_params.temp); therm_read(temp); if (!temp->is_valid) { DEBUG_MSG_HIGH(DEBUG_MODULE_PID, "Temperature read failed"); return; } /* Do PID calculation. */ float t_current = pid_params.temp.temperature; float t_desired = pid_params.temp_setpoint; pid_gain_params *gain_p = &(pid_params.gain); pid_error_params *error_p = &(pid_params.error); float err, err_i, err_d; err = t_desired - t_current; err_i = err + error_p->err_i; err_d = err - error_p->err; float p, i, d; p = gain_p->k_p * err; i = gain_p->k_i * err_i; d = gain_p->k_d * err_d; /* Scale/saturate the PID output and set the duty cycle. */ float pid_raw = p + i + d; /* Add 0.5 to do rounding with truncation. */ float pid_scaled = pid_raw + 0.5; pid_scaled = MAX(pid_raw, 0); pid_scaled = MIN(pid_scaled, 100); pwm_set_duty((uint32)pid_scaled); /* Calculate saturation error for anti-windup loop. */ float err_saturate = (pid_scaled - pid_raw) * (gain_p->k_windup); /* Update error for next iteration. */ error_p->err = err; error_p->err_d = err_d; error_p->err_i = err_i + err_saturate; DEBUG_MSG_MED(DEBUG_MODULE_PID, "err: %5.2f, err_d: %5.2f, err_i: %5.2f, err_sat: %5.2f", error_p->err, error_p->err_d, error_p->err_i, err_saturate); DEBUG_MSG_MED(DEBUG_MODULE_PID, "pid_raw: %5.2f, pid_scaled: %5.2f", pid_raw, pid_scaled); }
bool process_record_user(uint16_t keycode, keyrecord_t *record) { static uint32_t key_timer; switch (keycode) { case L_BRI: if (record->event.pressed) { if (LED_GCR_STEP > LED_GCR_MAX - gcr_desired) gcr_desired = LED_GCR_MAX; else gcr_desired += LED_GCR_STEP; if (led_animation_breathing) gcr_breathe = gcr_desired; } return false; case L_BRD: if (record->event.pressed) { if (LED_GCR_STEP > gcr_desired) gcr_desired = 0; else gcr_desired -= LED_GCR_STEP; if (led_animation_breathing) gcr_breathe = gcr_desired; } return false; case L_PTN: if (record->event.pressed) { if (led_animation_id == led_setups_count - 1) led_animation_id = 0; else led_animation_id++; } return false; case L_PTP: if (record->event.pressed) { if (led_animation_id == 0) led_animation_id = led_setups_count - 1; else led_animation_id--; } return false; case L_PSI: if (record->event.pressed) { led_animation_speed += ANIMATION_SPEED_STEP; } return false; case L_PSD: if (record->event.pressed) { led_animation_speed -= ANIMATION_SPEED_STEP; if (led_animation_speed < 0) led_animation_speed = 0; } return false; case L_T_MD: if (record->event.pressed) { led_lighting_mode++; if (led_lighting_mode > LED_MODE_MAX_INDEX) led_lighting_mode = LED_MODE_NORMAL; } return false; case L_T_ONF: if (record->event.pressed) { led_enabled = !led_enabled; I2C3733_Control_Set(led_enabled); } return false; case L_ON: if (record->event.pressed) { led_enabled = 1; I2C3733_Control_Set(led_enabled); } return false; case L_OFF: if (record->event.pressed) { led_enabled = 0; I2C3733_Control_Set(led_enabled); } return false; case L_T_BR: if (record->event.pressed) { led_animation_breathing = !led_animation_breathing; if (led_animation_breathing) { gcr_breathe = gcr_desired; led_animation_breathe_cur = BREATHE_MIN_STEP; breathe_dir = 1; } } return false; case L_T_PTD: if (record->event.pressed) { led_animation_direction = !led_animation_direction; } return false; case U_T_AGCR: if (record->event.pressed && MODS_SHIFT && MODS_CTRL) { TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode"); } return false; case DBG_TOG: if (record->event.pressed) { TOGGLE_FLAG_AND_PRINT(debug_enable, "Debug mode"); } return false; case DBG_MTRX: if (record->event.pressed) { TOGGLE_FLAG_AND_PRINT(debug_matrix, "Debug matrix"); } return false; case DBG_KBD: if (record->event.pressed) { TOGGLE_FLAG_AND_PRINT(debug_keyboard, "Debug keyboard"); } return false; case DBG_MOU: if (record->event.pressed) { TOGGLE_FLAG_AND_PRINT(debug_mouse, "Debug mouse"); } return false; case MD_BOOT: if (record->event.pressed) { key_timer = timer_read32(); } else { if (timer_elapsed32(key_timer) >= 500) { reset_keyboard(); } } return false; default: return true; //Process all other keycodes normally } }
uint8_t matrix_scan(void) { uint8_t *tmp; tmp = matrix_prev; matrix_prev = matrix; matrix = tmp; // power on if (!KEY_POWER_STATE()) KEY_POWER_ON(); for (uint8_t row = 0; row < MATRIX_ROWS; row++) { for (uint8_t col = 0; col < MATRIX_COLS; col++) { KEY_SELECT(row, col); _delay_us(5); // Not sure this is needed. This just emulates HHKB controller's behaviour. if (matrix_prev[row] & (1<<col)) { KEY_PREV_ON(); } _delay_us(10); // NOTE: KEY_STATE is valid only in 20us after KEY_ENABLE. // If V-USB interrupts in this section we could lose 40us or so // and would read invalid value from KEY_STATE. uint8_t last = TIMER_RAW; KEY_ENABLE(); // Wait for KEY_STATE outputs its value. // 1us was ok on one HHKB, but not worked on another. // no wait doesn't work on Teensy++ with pro(1us works) // no wait does work on tmk PCB(8MHz) with pro2 // 1us wait does work on both of above // 1us wait doesn't work on tmk(16MHz) // 5us wait does work on tmk(16MHz) // 5us wait does work on tmk(16MHz/2) // 5us wait does work on tmk(8MHz) // 10us wait does work on Teensy++ with pro // 10us wait does work on 328p+iwrap with pro // 10us wait doesn't work on tmk PCB(8MHz) with pro2(very lagged scan) _delay_us(5); if (KEY_STATE()) { matrix[row] &= ~(1<<col); } else { matrix[row] |= (1<<col); } // Ignore if this code region execution time elapses more than 20us. // MEMO: 20[us] * (TIMER_RAW_FREQ / 1000000)[count per us] // MEMO: then change above using this rule: a/(b/c) = a*1/(b/c) = a*(c/b) if (TIMER_DIFF_RAW(TIMER_RAW, last) > 20/(1000000/TIMER_RAW_FREQ)) { matrix[row] = matrix_prev[row]; } _delay_us(5); KEY_PREV_OFF(); KEY_UNABLE(); // NOTE: KEY_STATE keep its state in 20us after KEY_ENABLE. // This takes 25us or more to make sure KEY_STATE returns to idle state. #ifdef HHKB_JP // Looks like JP needs faster scan due to its twice larger matrix // or it can drop keys in fast key typing _delay_us(30); #else _delay_us(75); #endif } if (matrix[row] ^ matrix_prev[row]) matrix_last_modified = timer_read32(); } // power off if (KEY_POWER_STATE() && (USB_DeviceState == DEVICE_STATE_Suspended || USB_DeviceState == DEVICE_STATE_Unattached ) && timer_elapsed32(matrix_last_modified) > MATRIX_POWER_SAVE) { KEY_POWER_OFF(); suspend_power_down(); } return 1; }
void rn42_task(void) { int16_t c; // Raw mode: interpret output report of LED state while ((c = rn42_getc()) != -1) { // LED Out report: 0xFE, 0x02, 0x01, <leds> // To get the report over UART set bit3 with SH, command. static enum {LED_INIT, LED_FE, LED_02, LED_01} state = LED_INIT; switch (state) { case LED_INIT: if (c == 0xFE) state = LED_FE; else { if (0x0 <= c && c <= 0x7f) xprintf("%c", c); else xprintf(" %02X", c); } break; case LED_FE: if (c == 0x02) state = LED_02; else state = LED_INIT; break; case LED_02: if (c == 0x01) state = LED_01; else state = LED_INIT; break; case LED_01: dprintf("LED status: %02X\n", c); rn42_set_leds(c); state = LED_INIT; break; default: state = LED_INIT; } } /* Bluetooth mode when ready */ if (!config_mode && !force_usb) { if (!rn42_rts() && host_get_driver() != &rn42_driver) { clear_keyboard(); host_set_driver(&rn42_driver); } else if (rn42_rts() && host_get_driver() != &lufa_driver) { clear_keyboard(); host_set_driver(&lufa_driver); } } static uint16_t prev_timer = 0; uint16_t e = timer_elapsed(prev_timer); if (e > 1000) { /* every second */ prev_timer += e/1000*1000; /* Low voltage alert */ uint8_t bs = battery_status(); if (bs == LOW_VOLTAGE) { battery_led(LED_ON); } else { battery_led(LED_CHARGER); } /* every minute */ uint32_t t = timer_read32()/1000; if (t%60 == 0) { uint16_t v = battery_voltage(); uint8_t h = t/3600; uint8_t m = t%3600/60; uint8_t s = t%60; dprintf("%02u:%02u:%02u\t%umV\n", h, m, s, v); /* TODO: xprintf doesn't work for this. xprintf("%02u:%02u:%02u\t%umV\n", (t/3600), (t%3600/60), (t%60), v); */ } } /* Connection monitor */ if (!rn42_rts() && rn42_linked()) { status_led(true); } else { status_led(false); } }
uint32_t timer_elapsed32(uint32_t tlast) { return TIMER_DIFF_32(timer_read32(), tlast); }
static bool command_common(uint8_t code) { #ifdef KEYBOARD_LOCK_ENABLE static host_driver_t *host_driver = 0; #endif #ifdef SLEEP_LED_ENABLE static bool sleep_led_test = false; #endif switch (code) { #ifdef SLEEP_LED_ENABLE case KC_Z: // test breathing sleep LED print("Sleep LED test\n"); if (sleep_led_test) { sleep_led_disable(); led_set(host_keyboard_leds()); } else { sleep_led_enable(); } sleep_led_test = !sleep_led_test; break; #endif #ifdef BOOTMAGIC_ENABLE case KC_E: print("eeconfig:\n"); print_eeconfig(); break; #endif #ifdef KEYBOARD_LOCK_ENABLE case KC_CAPSLOCK: if (host_get_driver()) { host_driver = host_get_driver(); clear_keyboard(); host_set_driver(0); print("Locked.\n"); } else { host_set_driver(host_driver); print("Unlocked.\n"); } break; #endif case KC_H: case KC_SLASH: /* ? */ command_common_help(); break; case KC_C: debug_matrix = false; debug_keyboard = false; debug_mouse = false; debug_enable = false; command_console_help(); print("C> "); command_state = CONSOLE; break; case KC_PAUSE: clear_keyboard(); print("\n\nbootloader... "); wait_ms(1000); bootloader_jump(); // not return break; case KC_D: if (debug_enable) { print("\ndebug: off\n"); debug_matrix = false; debug_keyboard = false; debug_mouse = false; debug_enable = false; } else { print("\ndebug: on\n"); debug_enable = true; } break; case KC_X: // debug matrix toggle debug_matrix = !debug_matrix; if (debug_matrix) { print("\nmatrix: on\n"); debug_enable = true; } else { print("\nmatrix: off\n"); } break; case KC_K: // debug keyboard toggle debug_keyboard = !debug_keyboard; if (debug_keyboard) { print("\nkeyboard: on\n"); debug_enable = true; } else { print("\nkeyboard: off\n"); } break; case KC_M: // debug mouse toggle debug_mouse = !debug_mouse; if (debug_mouse) { print("\nmouse: on\n"); debug_enable = true; } else { print("\nmouse: off\n"); } break; case KC_V: // print version & information print("\n\t- Version -\n"); print("DESC: " STR(DESCRIPTION) "\n"); print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") " "PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") " "VER: " STR(DEVICE_VER) "\n"); print("BUILD: " STR(VERSION) " (" __TIME__ " " __DATE__ ")\n"); /* build options */ print("OPTIONS:" #ifdef PROTOCOL_PJRC " PJRC" #endif #ifdef PROTOCOL_LUFA " LUFA" #endif #ifdef PROTOCOL_VUSB " VUSB" #endif #ifdef PROTOCOL_CHIBIOS " CHIBIOS" #endif #ifdef BOOTMAGIC_ENABLE " BOOTMAGIC" #endif #ifdef MOUSEKEY_ENABLE " MOUSEKEY" #endif #ifdef EXTRAKEY_ENABLE " EXTRAKEY" #endif #ifdef CONSOLE_ENABLE " CONSOLE" #endif #ifdef COMMAND_ENABLE " COMMAND" #endif #ifdef NKRO_ENABLE " NKRO" #endif #ifdef KEYMAP_SECTION_ENABLE " KEYMAP_SECTION" #endif " " STR(BOOTLOADER_SIZE) "\n"); print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__) #if defined(__AVR__) " AVR-LIBC: " __AVR_LIBC_VERSION_STRING__ " AVR_ARCH: avr" STR(__AVR_ARCH__) "\n"); #elif defined(__arm__) // TODO ); #endif break; case KC_S: print("\n\t- Status -\n"); print_val_hex8(host_keyboard_leds()); print_val_hex8(keyboard_protocol); print_val_hex8(keyboard_idle); #ifdef NKRO_ENABLE print_val_hex8(keyboard_nkro); #endif print_val_hex32(timer_read32()); #ifdef PROTOCOL_PJRC print_val_hex8(UDCON); print_val_hex8(UDIEN); print_val_hex8(UDINT); print_val_hex8(usb_keyboard_leds); print_val_hex8(usb_keyboard_idle_count); #endif #ifdef PROTOCOL_PJRC # if USB_COUNT_SOF print_val_hex8(usbSofCount); # endif #endif break; #ifdef NKRO_ENABLE case KC_N: clear_keyboard(); //Prevents stuck keys. keyboard_nkro = !keyboard_nkro; if (keyboard_nkro) { print("NKRO: on\n"); } else { print("NKRO: off\n"); } break; #endif case KC_ESC: case KC_GRV: case KC_0: case KC_F10: switch_default_layer(0); break; case KC_1 ... KC_9: switch_default_layer((code - KC_1) + 1); break; case KC_F1 ... KC_F9: switch_default_layer((code - KC_F1) + 1); break; default: print("?"); return false; }
uint8_t matrix_scan(void) { if (mcp23018_status) { // if there was an error if (++mcp23018_reset_loop == 0) { // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans // this will be approx bit more frequent than once per second print("trying to reset mcp23018\n"); mcp23018_status = init_mcp23018(); if (mcp23018_status) { print("left side not responding\n"); } else { print("left side attached\n"); ergodox_blink_all_leds(); } } } #ifdef DEBUG_MATRIX_SCAN_RATE matrix_scan_count++; uint32_t timer_now = timer_read32(); if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) { print("matrix scan frequency: "); pdec(matrix_scan_count); print("\n"); matrix_timer = timer_now; matrix_scan_count = 0; } #endif #ifdef SHOW_LAYER_LEDS uint8_t layer = biton32(layer_state); // use the leds 2 and 3 to show which layer is currently active ergodox_board_led_off(); ergodox_right_led_2_off(); ergodox_right_led_3_off(); switch (layer) { case 0: // no leds break; case 1: ergodox_right_led_3_on(); break; case 2: ergodox_right_led_2_on(); break; case 3: ergodox_right_led_2_on(); ergodox_right_led_3_on(); break; } #endif #ifdef KEYMAP_CUB uint8_t layer = biton32(layer_state); ergodox_board_led_off(); ergodox_right_led_1_off(); ergodox_right_led_2_off(); ergodox_right_led_3_off(); switch (layer) { case 1: // no leds break; case 2: // blue ergodox_left_led_2_on(); break; case 8: // blue and green ergodox_left_led_2_on(); // break missed intentionally case 3: // green ergodox_left_led_3_on(); break; case 6: ergodox_board_led_on(); // break missed intentionally case 4: case 5: case 7: // white ergodox_left_led_1_on(); break; case 9: // white+green ergodox_left_led_1_on(); ergodox_left_led_3_on(); break; default: // none break; } mcp23018_status = ergodox_left_leds_update(); #endif for (uint8_t i = 0; i < MATRIX_ROWS; i++) { select_row(i); matrix_row_t cols = read_cols(i); if (matrix_debouncing[i] != cols) { matrix_debouncing[i] = cols; if (debouncing) { debug("bounce!: "); debug_hex(debouncing); debug("\n"); } debouncing = DEBOUNCE; } unselect_rows(); } if (debouncing) { if (--debouncing) { _delay_ms(1); } else { for (uint8_t i = 0; i < MATRIX_ROWS; i++) { matrix[i] = matrix_debouncing[i]; } } } return 1; }