tags/v2.957d27a8
Merge branch 'core_update_150924' into core024abe3
core: Fix NKRO ifdef7aa2d30
core: Fix for disabling NKRO in Boot protocol95651fd
core: Fix message print of debug commandc20cd29
lufa: Fix endpoint bank mode for ATMega32u282ac21f
next_usb: Fix next_kbd_set_leds()537d9c7
Change to KC_BOOTLOADER(KC_BTLD)f2b3772
Add an assignable RESET keyfc99257
Fix parenthesise852582
Fix weak modifier clear in action macroc2a6c5c
core: Fix lufa suspend callback(#234)fa548c5
usb_usb: Ignore error usage(0x01-03) report513d95c
usb_usb: Support locking key indicator LEDcd78802
core: Add keymap section ldscript for ATMega32U270c9abd
Add description for non-US keys on keycode.h538c192
lufa: Fix console flush #22387628c9
Revert "Make action_for_key a weak symbol"3c0a1ba
Make action_for_key a weak symbol6bb0d7d
ibm4704_usb: Fix protocol handlingb6ef5cf
Add keyboard_setup() and matrix_setup()f4bb8b2
ibm4704_usb: Fix interrupt of clock(rising edge)0c1fcc1
usb_usb: Change debug LED pin config595710d
Reduce code size of magic commands6bed174
Add description of AVR bootloader and boot section54c6a01
Merge commit 'f6d56675f9f981c5464f0ca7a1fbb0162154e8c5'd18d42e
Merge branch 'core-update2' into corefebec88
Add compile options '-fdata-sections' git-subtree-dir: tmk_core git-subtree-split:57d27a8e39
ifdef KEYMAP_SECTION_ENABLE | ifdef KEYMAP_SECTION_ENABLE | ||||
OPT_DEFS += -DKEYMAP_SECTION_ENABLE | OPT_DEFS += -DKEYMAP_SECTION_ENABLE | ||||
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr5.x | |||||
ifeq ($(strip $(MCU)),atmega32u2) | |||||
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr35.x | |||||
else ifeq ($(strip $(MCU)),atmega32u4) | |||||
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr5.x | |||||
else | |||||
EXTRALDFLAGS = $(error no ldscript for keymap section) | |||||
endif | |||||
endif | endif | ||||
# Version string | # Version string |
#define ACTION_LAYER_ON_OFF(layer) ACTION_LAYER_TAP((layer), OP_ON_OFF) | #define ACTION_LAYER_ON_OFF(layer) ACTION_LAYER_TAP((layer), OP_ON_OFF) | ||||
#define ACTION_LAYER_OFF_ON(layer) ACTION_LAYER_TAP((layer), OP_OFF_ON) | #define ACTION_LAYER_OFF_ON(layer) ACTION_LAYER_TAP((layer), OP_OFF_ON) | ||||
#define ACTION_LAYER_SET_CLEAR(layer) ACTION_LAYER_TAP((layer), OP_SET_CLEAR) | #define ACTION_LAYER_SET_CLEAR(layer) ACTION_LAYER_TAP((layer), OP_SET_CLEAR) | ||||
#define ACTION_LAYER_MODS(layer, mods) ACTION_LAYER_TAP((layer), 0xe0 | (mods)&0x0f) | |||||
#define ACTION_LAYER_MODS(layer, mods) ACTION_LAYER_TAP((layer), 0xe0 | ((mods)&0x0f)) | |||||
/* With Tapping */ | /* With Tapping */ | ||||
#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key)) | #define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key)) | ||||
#define ACTION_LAYER_TAP_TOGGLE(layer) ACTION_LAYER_TAP((layer), OP_TAP_TOGGLE) | #define ACTION_LAYER_TAP_TOGGLE(layer) ACTION_LAYER_TAP((layer), OP_TAP_TOGGLE) |
dprintf("KEY_DOWN(%02X)\n", macro); | dprintf("KEY_DOWN(%02X)\n", macro); | ||||
if (IS_MOD(macro)) { | if (IS_MOD(macro)) { | ||||
add_weak_mods(MOD_BIT(macro)); | add_weak_mods(MOD_BIT(macro)); | ||||
send_keyboard_report(); | |||||
} else { | } else { | ||||
register_code(macro); | register_code(macro); | ||||
} | } | ||||
dprintf("KEY_UP(%02X)\n", macro); | dprintf("KEY_UP(%02X)\n", macro); | ||||
if (IS_MOD(macro)) { | if (IS_MOD(macro)) { | ||||
del_weak_mods(MOD_BIT(macro)); | del_weak_mods(MOD_BIT(macro)); | ||||
send_keyboard_report(); | |||||
} else { | } else { | ||||
unregister_code(macro); | unregister_code(macro); | ||||
} | } |
void add_key(uint8_t key) | void add_key(uint8_t key) | ||||
{ | { | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
if (keyboard_nkro) { | |||||
if (keyboard_protocol && keyboard_nkro) { | |||||
add_key_bit(key); | add_key_bit(key); | ||||
return; | return; | ||||
} | } | ||||
void del_key(uint8_t key) | void del_key(uint8_t key) | ||||
{ | { | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
if (keyboard_nkro) { | |||||
if (keyboard_protocol && keyboard_nkro) { | |||||
del_key_bit(key); | del_key_bit(key); | ||||
return; | return; | ||||
} | } | ||||
uint8_t get_first_key(void) | uint8_t get_first_key(void) | ||||
{ | { | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
if (keyboard_nkro) { | |||||
if (keyboard_protocol && keyboard_nkro) { | |||||
uint8_t i = 0; | uint8_t i = 0; | ||||
for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++) | for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++) | ||||
; | ; |
#endif | #endif | ||||
/* Boot Section Size in *BYTEs* | |||||
* Teensy halfKay 512 | |||||
* Teensy++ halfKay 1024 | |||||
* Atmel DFU loader 4096 | |||||
* LUFA bootloader 4096 | |||||
* USBaspLoader 2048 | |||||
/* Bootloader Size in *bytes* | |||||
* | |||||
* AVR Boot section size are defined by setting BOOTSZ fuse in fact. Consult with your MCU datasheet. | |||||
* Note that 'Word'(2 bytes) size and address are used in datasheet while TMK uses 'Byte'. | |||||
* | |||||
* | |||||
* Size of Bootloaders in bytes: | |||||
* Atmel DFU loader(ATmega32U4) 4096 | |||||
* Atmel DFU loader(AT90USB128) 8192 | |||||
* LUFA bootloader(ATmega32U4) 4096 | |||||
* Arduino Caterina(ATmega32U4) 4096 | |||||
* USBaspLoader(ATmega***) 2048 | |||||
* Teensy halfKay(ATmega32U4) 512 | |||||
* Teensy++ halfKay(AT90USB128) 1024 | |||||
* | |||||
* | |||||
* AVR Boot section is located at the end of Flash memory like the followings. | |||||
* | |||||
* | |||||
* byte Atmel/LUFA(ATMega32u4) byte Atmel(AT90SUB128) | |||||
* 0x0000 +---------------+ 0x00000 +---------------+ | |||||
* | | | | | |||||
* | | | | | |||||
* | Application | | Application | | |||||
* | | | | | |||||
* = = = = | |||||
* | | 32KB-4KB | | 128KB-8KB | |||||
* 0x6000 +---------------+ 0x1FC00 +---------------+ | |||||
* | Bootloader | 4KB | Bootloader | 8KB | |||||
* 0x7FFF +---------------+ 0x1FFFF +---------------+ | |||||
* | |||||
* | |||||
* byte Teensy(ATMega32u4) byte Teensy++(AT90SUB128) | |||||
* 0x0000 +---------------+ 0x00000 +---------------+ | |||||
* | | | | | |||||
* | | | | | |||||
* | Application | | Application | | |||||
* | | | | | |||||
* = = = = | |||||
* | | 32KB-512B | | 128KB-1KB | |||||
* 0x7E00 +---------------+ 0x1FC00 +---------------+ | |||||
* | Bootloader | 512B | Bootloader | 1KB | |||||
* 0x7FFF +---------------+ 0x1FFFF +---------------+ | |||||
*/ | */ | ||||
#ifndef BOOTLOADER_SIZE | #ifndef BOOTLOADER_SIZE | ||||
#warning To use bootloader_jump() you need to define BOOTLOADER_SIZE in config.h. | #warning To use bootloader_jump() you need to define BOOTLOADER_SIZE in config.h. |
power_down(WDTO_15MS); | power_down(WDTO_15MS); | ||||
} | } | ||||
__attribute__ ((weak)) void matrix_power_up(void) {} | |||||
__attribute__ ((weak)) void matrix_power_down(void) {} | |||||
bool suspend_wakeup_condition(void) | bool suspend_wakeup_condition(void) | ||||
{ | { | ||||
matrix_power_up(); | matrix_power_up(); |
***********************************************************/ | ***********************************************************/ | ||||
static void command_common_help(void) | static void command_common_help(void) | ||||
{ | { | ||||
print("\n\n----- Command Help -----\n"); | |||||
print("c: enter console mode\n"); | |||||
print("d: toggle debug enable\n"); | |||||
print("x: toggle matrix debug\n"); | |||||
print("k: toggle keyboard debug\n"); | |||||
print("m: toggle mouse debug\n"); | |||||
#ifdef SLEEP_LED_ENABLE | |||||
print("z: toggle sleep LED test\n"); | |||||
print("\n\t- Magic -\n" | |||||
"d: debug\n" | |||||
"x: debug matrix\n" | |||||
"k: debug keyboard\n" | |||||
"m: debug mouse\n" | |||||
"v: version\n" | |||||
"s: status\n" | |||||
"c: console mode\n" | |||||
"0-4: layer0-4(F10-F4)\n" | |||||
"Paus: bootloader\n" | |||||
#ifdef KEYBOARD_LOCK_ENABLE | |||||
"Caps: Lock\n" | |||||
#endif | |||||
#ifdef BOOTMAGIC_ENABLE | |||||
"e: eeprom\n" | |||||
#endif | #endif | ||||
print("v: print device version & info\n"); | |||||
print("t: print timer count\n"); | |||||
print("s: print status\n"); | |||||
print("e: print eeprom config\n"); | |||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
print("n: toggle NKRO\n"); | |||||
"n: NKRO\n" | |||||
#endif | |||||
#ifdef SLEEP_LED_ENABLE | |||||
"z: sleep LED test\n" | |||||
#endif | #endif | ||||
print("0/F10: switch to Layer0 \n"); | |||||
print("1/F1: switch to Layer1 \n"); | |||||
print("2/F2: switch to Layer2 \n"); | |||||
print("3/F3: switch to Layer3 \n"); | |||||
print("4/F4: switch to Layer4 \n"); | |||||
print("PScr: power down/remote wake-up\n"); | |||||
print("Caps: Lock Keyboard(Child Proof)\n"); | |||||
print("Paus: jump to bootloader\n"); | |||||
); | |||||
} | } | ||||
#ifdef BOOTMAGIC_ENABLE | #ifdef BOOTMAGIC_ENABLE | ||||
print_eeconfig(); | print_eeconfig(); | ||||
break; | break; | ||||
#endif | #endif | ||||
#ifdef KEYBOARD_LOCK_ENABLE | |||||
case KC_CAPSLOCK: | case KC_CAPSLOCK: | ||||
if (host_get_driver()) { | if (host_get_driver()) { | ||||
host_driver = host_get_driver(); | host_driver = host_get_driver(); | ||||
print("Unlocked.\n"); | print("Unlocked.\n"); | ||||
} | } | ||||
break; | break; | ||||
#endif | |||||
case KC_H: | case KC_H: | ||||
case KC_SLASH: /* ? */ | case KC_SLASH: /* ? */ | ||||
command_common_help(); | command_common_help(); | ||||
debug_mouse = false; | debug_mouse = false; | ||||
debug_enable = false; | debug_enable = false; | ||||
command_console_help(); | command_console_help(); | ||||
print("\nEnter Console Mode\n"); | |||||
print("C> "); | print("C> "); | ||||
command_state = CONSOLE; | command_state = CONSOLE; | ||||
break; | break; | ||||
case KC_PAUSE: | case KC_PAUSE: | ||||
clear_keyboard(); | clear_keyboard(); | ||||
print("\n\nJump to bootloader... "); | |||||
print("\n\nbootloader... "); | |||||
_delay_ms(1000); | _delay_ms(1000); | ||||
bootloader_jump(); // not return | bootloader_jump(); // not return | ||||
print("not supported.\n"); | |||||
break; | break; | ||||
case KC_D: | case KC_D: | ||||
if (debug_enable) { | if (debug_enable) { | ||||
print("\nDEBUG: disabled.\n"); | |||||
print("\ndebug: off\n"); | |||||
debug_matrix = false; | debug_matrix = false; | ||||
debug_keyboard = false; | debug_keyboard = false; | ||||
debug_mouse = false; | debug_mouse = false; | ||||
debug_enable = false; | debug_enable = false; | ||||
} else { | } else { | ||||
print("\nDEBUG: enabled.\n"); | |||||
print("\ndebug: on\n"); | |||||
debug_enable = true; | debug_enable = true; | ||||
} | } | ||||
break; | break; | ||||
case KC_X: // debug matrix toggle | case KC_X: // debug matrix toggle | ||||
debug_matrix = !debug_matrix; | debug_matrix = !debug_matrix; | ||||
if (debug_matrix) { | if (debug_matrix) { | ||||
print("\nDEBUG: matrix enabled.\n"); | |||||
print("\nmatrix: on\n"); | |||||
debug_enable = true; | debug_enable = true; | ||||
} else { | } else { | ||||
print("\nDEBUG: matrix disabled.\n"); | |||||
print("\nmatrix: off\n"); | |||||
} | } | ||||
break; | break; | ||||
case KC_K: // debug keyboard toggle | case KC_K: // debug keyboard toggle | ||||
debug_keyboard = !debug_keyboard; | debug_keyboard = !debug_keyboard; | ||||
if (debug_keyboard) { | if (debug_keyboard) { | ||||
print("\nDEBUG: keyboard enabled.\n"); | |||||
print("\nkeyboard: on\n"); | |||||
debug_enable = true; | debug_enable = true; | ||||
} else { | } else { | ||||
print("\nDEBUG: keyboard disabled.\n"); | |||||
print("\nkeyboard: off\n"); | |||||
} | } | ||||
break; | break; | ||||
case KC_M: // debug mouse toggle | case KC_M: // debug mouse toggle | ||||
debug_mouse = !debug_mouse; | debug_mouse = !debug_mouse; | ||||
if (debug_mouse) { | if (debug_mouse) { | ||||
print("\nDEBUG: mouse enabled.\n"); | |||||
print("\nmouse: on\n"); | |||||
debug_enable = true; | debug_enable = true; | ||||
} else { | } else { | ||||
print("\nDEBUG: mouse disabled.\n"); | |||||
print("\nmouse: off\n"); | |||||
} | } | ||||
break; | break; | ||||
case KC_V: // print version & information | case KC_V: // print version & information | ||||
print("\n\n----- Version -----\n"); | |||||
print("\n\t- Version -\n"); | |||||
print("DESC: " STR(DESCRIPTION) "\n"); | print("DESC: " STR(DESCRIPTION) "\n"); | ||||
print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") " | print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") " | ||||
"PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") " | "PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") " | ||||
" AVR-LIBC: " __AVR_LIBC_VERSION_STRING__ | " AVR-LIBC: " __AVR_LIBC_VERSION_STRING__ | ||||
" AVR_ARCH: avr" STR(__AVR_ARCH__) "\n"); | " AVR_ARCH: avr" STR(__AVR_ARCH__) "\n"); | ||||
break; | break; | ||||
case KC_T: // print timer | |||||
print_val_hex32(timer_count); | |||||
break; | |||||
case KC_S: | case KC_S: | ||||
print("\n\n----- Status -----\n"); | |||||
print("\n\t- Status -\n"); | |||||
print_val_hex8(host_keyboard_leds()); | print_val_hex8(host_keyboard_leds()); | ||||
print_val_hex8(keyboard_protocol); | print_val_hex8(keyboard_protocol); | ||||
print_val_hex8(keyboard_idle); | print_val_hex8(keyboard_idle); | ||||
#ifdef NKRO_ENABLE | |||||
print_val_hex8(keyboard_nkro); | |||||
#endif | |||||
print_val_hex32(timer_count); | |||||
#ifdef PROTOCOL_PJRC | #ifdef PROTOCOL_PJRC | ||||
print_val_hex8(UDCON); | print_val_hex8(UDCON); | ||||
print_val_hex8(UDIEN); | print_val_hex8(UDIEN); | ||||
clear_keyboard(); //Prevents stuck keys. | clear_keyboard(); //Prevents stuck keys. | ||||
keyboard_nkro = !keyboard_nkro; | keyboard_nkro = !keyboard_nkro; | ||||
if (keyboard_nkro) | if (keyboard_nkro) | ||||
print("NKRO: enabled\n"); | |||||
print("NKRO: on\n"); | |||||
else | else | ||||
print("NKRO: disabled\n"); | |||||
break; | |||||
#endif | |||||
#ifdef EXTRAKEY_ENABLE | |||||
case KC_PSCREEN: | |||||
// TODO: Power key should take this feature? otherwise any key during suspend. | |||||
#ifdef PROTOCOL_PJRC | |||||
if (suspend && remote_wakeup) { | |||||
usb_remote_wakeup(); | |||||
} else { | |||||
host_system_send(SYSTEM_POWER_DOWN); | |||||
host_system_send(0); | |||||
_delay_ms(500); | |||||
} | |||||
#else | |||||
host_system_send(SYSTEM_POWER_DOWN); | |||||
_delay_ms(100); | |||||
host_system_send(0); | |||||
_delay_ms(500); | |||||
#endif | |||||
print("NKRO: off\n"); | |||||
break; | break; | ||||
#endif | #endif | ||||
case KC_ESC: | case KC_ESC: | ||||
case KC_GRV: | case KC_GRV: | ||||
case KC_0: | case KC_0: | ||||
case KC_F10: | |||||
switch_default_layer(0); | switch_default_layer(0); | ||||
break; | break; | ||||
case KC_1 ... KC_9: | case KC_1 ... KC_9: | ||||
switch_default_layer((code - KC_1) + 1); | switch_default_layer((code - KC_1) + 1); | ||||
break; | break; | ||||
case KC_F1 ... KC_F12: | |||||
case KC_F1 ... KC_F9: | |||||
switch_default_layer((code - KC_F1) + 1); | switch_default_layer((code - KC_F1) + 1); | ||||
break; | break; | ||||
default: | default: | ||||
***********************************************************/ | ***********************************************************/ | ||||
static void command_console_help(void) | static void command_console_help(void) | ||||
{ | { | ||||
print("\n\n----- Console Help -----\n"); | |||||
print("ESC/q: quit\n"); | |||||
print("\n\t- Console -\n" | |||||
"ESC/q: quit\n" | |||||
#ifdef MOUSEKEY_ENABLE | #ifdef MOUSEKEY_ENABLE | ||||
print("m: mousekey\n"); | |||||
"m: mousekey\n" | |||||
#endif | #endif | ||||
); | |||||
} | } | ||||
static bool command_console(uint8_t code) | static bool command_console(uint8_t code) | ||||
break; | break; | ||||
case KC_Q: | case KC_Q: | ||||
case KC_ESC: | case KC_ESC: | ||||
print("\nQuit Console Mode\n"); | |||||
command_state = ONESHOT; | command_state = ONESHOT; | ||||
return false; | return false; | ||||
#ifdef MOUSEKEY_ENABLE | #ifdef MOUSEKEY_ENABLE | ||||
case KC_M: | case KC_M: | ||||
mousekey_console_help(); | mousekey_console_help(); | ||||
print("\nEnter Mousekey Console\n"); | |||||
print("M0>"); | |||||
print("M> "); | |||||
command_state = MOUSEKEY; | command_state = MOUSEKEY; | ||||
return true; | return true; | ||||
#endif | #endif | ||||
static void mousekey_param_print(void) | static void mousekey_param_print(void) | ||||
{ | { | ||||
print("\n\n----- Mousekey Parameters -----\n"); | |||||
print("1: mk_delay(*10ms): "); pdec(mk_delay); print("\n"); | |||||
print("2: mk_interval(ms): "); pdec(mk_interval); print("\n"); | |||||
print("3: mk_max_speed: "); pdec(mk_max_speed); print("\n"); | |||||
print("4: mk_time_to_max: "); pdec(mk_time_to_max); print("\n"); | |||||
print("5: mk_wheel_max_speed: "); pdec(mk_wheel_max_speed); print("\n"); | |||||
print("6: mk_wheel_time_to_max: "); pdec(mk_wheel_time_to_max); print("\n"); | |||||
print("\n\t- Values -\n"); | |||||
print("1: delay(*10ms): "); pdec(mk_delay); print("\n"); | |||||
print("2: interval(ms): "); pdec(mk_interval); print("\n"); | |||||
print("3: max_speed: "); pdec(mk_max_speed); print("\n"); | |||||
print("4: time_to_max: "); pdec(mk_time_to_max); print("\n"); | |||||
print("5: wheel_max_speed: "); pdec(mk_wheel_max_speed); print("\n"); | |||||
print("6: wheel_time_to_max: "); pdec(mk_wheel_time_to_max); print("\n"); | |||||
} | } | ||||
#define PRINT_SET_VAL(v) print(#v " = "); print_dec(v); print("\n"); | |||||
//#define PRINT_SET_VAL(v) print(#v " = "); print_dec(v); print("\n"); | |||||
#define PRINT_SET_VAL(v) xprintf(#v " = %d\n", (v)) | |||||
static void mousekey_param_inc(uint8_t param, uint8_t inc) | static void mousekey_param_inc(uint8_t param, uint8_t inc) | ||||
{ | { | ||||
switch (param) { | switch (param) { | ||||
static void mousekey_console_help(void) | static void mousekey_console_help(void) | ||||
{ | { | ||||
print("\n\n----- Mousekey Parameters Help -----\n"); | |||||
print("ESC/q: quit\n"); | |||||
print("1: select mk_delay(*10ms)\n"); | |||||
print("2: select mk_interval(ms)\n"); | |||||
print("3: select mk_max_speed\n"); | |||||
print("4: select mk_time_to_max\n"); | |||||
print("5: select mk_wheel_max_speed\n"); | |||||
print("6: select mk_wheel_time_to_max\n"); | |||||
print("p: print parameters\n"); | |||||
print("d: set default values\n"); | |||||
print("up: increase parameters(+1)\n"); | |||||
print("down: decrease parameters(-1)\n"); | |||||
print("pgup: increase parameters(+10)\n"); | |||||
print("pgdown: decrease parameters(-10)\n"); | |||||
print("\nspeed = delta * max_speed * (repeat / time_to_max)\n"); | |||||
print("where delta: cursor="); pdec(MOUSEKEY_MOVE_DELTA); | |||||
print(", wheel="); pdec(MOUSEKEY_WHEEL_DELTA); print("\n"); | |||||
print("See http://en.wikipedia.org/wiki/Mouse_keys\n"); | |||||
print("\n\t- Mousekey -\n" | |||||
"ESC/q: quit\n" | |||||
"1: delay(*10ms)\n" | |||||
"2: interval(ms)\n" | |||||
"3: max_speed\n" | |||||
"4: time_to_max\n" | |||||
"5: wheel_max_speed\n" | |||||
"6: wheel_time_to_max\n" | |||||
"\n" | |||||
"p: print values\n" | |||||
"d: set defaults\n" | |||||
"up: +1\n" | |||||
"down: -1\n" | |||||
"pgup: +10\n" | |||||
"pgdown: -10\n" | |||||
"\n" | |||||
"speed = delta * max_speed * (repeat / time_to_max)\n"); | |||||
xprintf("where delta: cursor=%d, wheel=%d\n" | |||||
"See http://en.wikipedia.org/wiki/Mouse_keys\n", MOUSEKEY_MOVE_DELTA, MOUSEKEY_WHEEL_DELTA); | |||||
} | } | ||||
static bool mousekey_console(uint8_t code) | static bool mousekey_console(uint8_t code) | ||||
break; | break; | ||||
case KC_Q: | case KC_Q: | ||||
case KC_ESC: | case KC_ESC: | ||||
mousekey_param = 0; | |||||
print("\nQuit Mousekey Console\n"); | |||||
print("C> "); | |||||
command_state = CONSOLE; | |||||
return false; | |||||
if (mousekey_param) { | |||||
mousekey_param = 0; | |||||
} else { | |||||
print("C> "); | |||||
command_state = CONSOLE; | |||||
return false; | |||||
} | |||||
break; | |||||
case KC_P: | case KC_P: | ||||
mousekey_param_print(); | mousekey_param_print(); | ||||
break; | break; | ||||
case KC_4: | case KC_4: | ||||
case KC_5: | case KC_5: | ||||
case KC_6: | case KC_6: | ||||
case KC_7: | |||||
case KC_8: | |||||
case KC_9: | |||||
case KC_0: | |||||
mousekey_param = numkey2num(code); | mousekey_param = numkey2num(code); | ||||
print("selected parameter: "); pdec(mousekey_param); print("\n"); | |||||
break; | break; | ||||
case KC_UP: | case KC_UP: | ||||
mousekey_param_inc(mousekey_param, 1); | mousekey_param_inc(mousekey_param, 1); | ||||
mk_time_to_max = MOUSEKEY_TIME_TO_MAX; | mk_time_to_max = MOUSEKEY_TIME_TO_MAX; | ||||
mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED; | mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED; | ||||
mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX; | mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX; | ||||
print("set default values.\n"); | |||||
print("set default\n"); | |||||
break; | break; | ||||
default: | default: | ||||
print("?"); | print("?"); | ||||
return false; | return false; | ||||
} | } | ||||
print("M"); pdec(mousekey_param); print("> "); | |||||
if (mousekey_param) | |||||
xprintf("M%d> ", mousekey_param); | |||||
else | |||||
print("M>" ); | |||||
return true; | return true; | ||||
} | } | ||||
#endif | #endif | ||||
static void switch_default_layer(uint8_t layer) | static void switch_default_layer(uint8_t layer) | ||||
{ | { | ||||
print("switch_default_layer: "); print_dec(biton32(default_layer_state)); | |||||
print(" to "); print_dec(layer); print("\n"); | |||||
xprintf("L%d\n", layer); | |||||
default_layer_set(1UL<<layer); | default_layer_set(1UL<<layer); | ||||
clear_keyboard(); | clear_keyboard(); | ||||
} | } |
#endif | #endif | ||||
__attribute__ ((weak)) void matrix_setup(void) {} | |||||
void keyboard_setup(void) | |||||
{ | |||||
matrix_setup(); | |||||
} | |||||
void keyboard_init(void) | void keyboard_init(void) | ||||
{ | { | ||||
timer_init(); | timer_init(); |
} | } | ||||
/* it runs once at early stage of startup before keyboard_init. */ | |||||
void keyboard_setup(void); | |||||
/* it runs once after initializing host side protocol, debug and MCU peripherals. */ | |||||
void keyboard_init(void); | void keyboard_init(void); | ||||
/* it runs repeatedly in main loop */ | |||||
void keyboard_task(void); | void keyboard_task(void); | ||||
/* it runs when host LED status is updated */ | |||||
void keyboard_set_leds(uint8_t leds); | void keyboard_set_leds(uint8_t leds); | ||||
__attribute__ ((weak)) void matrix_power_up(void) {} | |||||
__attribute__ ((weak)) void matrix_power_down(void) {} | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
#endif | #endif |
#define KC_WSTP KC_WWW_STOP | #define KC_WSTP KC_WWW_STOP | ||||
#define KC_WREF KC_WWW_REFRESH | #define KC_WREF KC_WWW_REFRESH | ||||
#define KC_WFAV KC_WWW_FAVORITES | #define KC_WFAV KC_WWW_FAVORITES | ||||
/* Jump to bootloader */ | |||||
#define KC_BTLD KC_BOOTLOADER | |||||
/* Transparent */ | /* Transparent */ | ||||
#define KC_TRANSPARENT 1 | #define KC_TRANSPARENT 1 | ||||
#define KC_TRNS KC_TRANSPARENT | #define KC_TRNS KC_TRANSPARENT | ||||
KC_LBRACKET, | KC_LBRACKET, | ||||
KC_RBRACKET, /* 0x30 */ | KC_RBRACKET, /* 0x30 */ | ||||
KC_BSLASH, /* \ (and |) */ | KC_BSLASH, /* \ (and |) */ | ||||
KC_NONUS_HASH, /* Non-US # and ~ */ | |||||
KC_NONUS_HASH, /* Non-US # and ~ (Typically near the Enter key) */ | |||||
KC_SCOLON, /* ; (and :) */ | KC_SCOLON, /* ; (and :) */ | ||||
KC_QUOTE, /* ' and " */ | KC_QUOTE, /* ' and " */ | ||||
KC_GRAVE, /* Grave accent and tilde */ | KC_GRAVE, /* Grave accent and tilde */ | ||||
KC_KP_9, | KC_KP_9, | ||||
KC_KP_0, | KC_KP_0, | ||||
KC_KP_DOT, | KC_KP_DOT, | ||||
KC_NONUS_BSLASH, /* Non-US \ and | */ | |||||
KC_NONUS_BSLASH, /* Non-US \ and | (Typically near the Left-Shift key) */ | |||||
KC_APPLICATION, | KC_APPLICATION, | ||||
KC_POWER, | KC_POWER, | ||||
KC_KP_EQUAL, | KC_KP_EQUAL, | ||||
KC_MEDIA_FAST_FORWARD, | KC_MEDIA_FAST_FORWARD, | ||||
KC_MEDIA_REWIND, /* 0xBC */ | KC_MEDIA_REWIND, /* 0xBC */ | ||||
/* Jump to bootloader */ | |||||
KC_BOOTLOADER = 0xBF, | |||||
/* Fn key */ | /* Fn key */ | ||||
KC_FN0 = 0xC0, | KC_FN0 = 0xC0, | ||||
KC_FN1, | KC_FN1, |
#include "action_layer.h" | #include "action_layer.h" | ||||
#include "action.h" | #include "action.h" | ||||
#include "action_macro.h" | #include "action_macro.h" | ||||
#include "wait.h" | |||||
#include "debug.h" | #include "debug.h" | ||||
case KC_TRNS: | case KC_TRNS: | ||||
action.code = ACTION_TRANSPARENT; | action.code = ACTION_TRANSPARENT; | ||||
break; | break; | ||||
case KC_BOOTLOADER: | |||||
clear_keyboard(); | |||||
wait_ms(50); | |||||
bootloader_jump(); // not return | |||||
break; | |||||
default: | default: | ||||
action.code = ACTION_NO; | action.code = ACTION_NO; | ||||
break; | break; |
#define USB_LED_KANA 4 | #define USB_LED_KANA 4 | ||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
void led_set(uint8_t usb_led); | void led_set(uint8_t usb_led); | ||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif | #endif |
uint8_t matrix_rows(void); | uint8_t matrix_rows(void); | ||||
/* number of matrix columns */ | /* number of matrix columns */ | ||||
uint8_t matrix_cols(void); | uint8_t matrix_cols(void); | ||||
/* intialize matrix for scaning. should be called once. */ | |||||
/* should be called at early stage of startup before matrix_init.(optional) */ | |||||
void matrix_setup(void); | |||||
/* intialize matrix for scaning. */ | |||||
void matrix_init(void); | void matrix_init(void); | ||||
/* scan all key states on matrix */ | /* scan all key states on matrix */ | ||||
uint8_t matrix_scan(void); | uint8_t matrix_scan(void); |
/* | |||||
* linker script for configurable keymap | |||||
* | |||||
* This adds keymap section which places keymap at fixed address and | |||||
* is based on binutils-avr ldscripts(/usr/lib/ldscripts/avr5.x). | |||||
*/ | |||||
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") | |||||
OUTPUT_ARCH(avr:35) | |||||
MEMORY | |||||
{ | |||||
/* With keymap section | |||||
* | |||||
* Flash Map of ATMega32U4(32KB) | |||||
* +------------+ 0x0000 | |||||
* | .vectors | | |||||
* | .progmem | | |||||
* | .init0-9 | > text region | |||||
* | .text | | |||||
* | .fini9-0 | | |||||
* | | | |||||
* |------------| _etext | |||||
* | .data | | |||||
* | .bss | > data region | |||||
* | .noinit | | |||||
* | | | |||||
* |------------| 0x6800 | |||||
* | .keymap | > keymap region(2KB) | |||||
* |------------| 0x7000 | |||||
* | bootloader | 4KB | |||||
* +------------+ 0x7FFF | |||||
*/ | |||||
text (rx) : ORIGIN = 0, LENGTH = 64K | |||||
keymap (rw!x) : ORIGIN = 0x6800, LENGTH = 2K | |||||
data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0 | |||||
eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K | |||||
fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K | |||||
lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K | |||||
signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K | |||||
} | |||||
SECTIONS | |||||
{ | |||||
/* Read-only sections, merged into text segment: */ | |||||
.hash : { *(.hash) } | |||||
.dynsym : { *(.dynsym) } | |||||
.dynstr : { *(.dynstr) } | |||||
.gnu.version : { *(.gnu.version) } | |||||
.gnu.version_d : { *(.gnu.version_d) } | |||||
.gnu.version_r : { *(.gnu.version_r) } | |||||
.rel.init : { *(.rel.init) } | |||||
.rela.init : { *(.rela.init) } | |||||
.rel.text : | |||||
{ | |||||
*(.rel.text) | |||||
*(.rel.text.*) | |||||
*(.rel.gnu.linkonce.t*) | |||||
} | |||||
.rela.text : | |||||
{ | |||||
*(.rela.text) | |||||
*(.rela.text.*) | |||||
*(.rela.gnu.linkonce.t*) | |||||
} | |||||
.rel.fini : { *(.rel.fini) } | |||||
.rela.fini : { *(.rela.fini) } | |||||
.rel.rodata : | |||||
{ | |||||
*(.rel.rodata) | |||||
*(.rel.rodata.*) | |||||
*(.rel.gnu.linkonce.r*) | |||||
} | |||||
.rela.rodata : | |||||
{ | |||||
*(.rela.rodata) | |||||
*(.rela.rodata.*) | |||||
*(.rela.gnu.linkonce.r*) | |||||
} | |||||
.rel.data : | |||||
{ | |||||
*(.rel.data) | |||||
*(.rel.data.*) | |||||
*(.rel.gnu.linkonce.d*) | |||||
} | |||||
.rela.data : | |||||
{ | |||||
*(.rela.data) | |||||
*(.rela.data.*) | |||||
*(.rela.gnu.linkonce.d*) | |||||
} | |||||
.rel.ctors : { *(.rel.ctors) } | |||||
.rela.ctors : { *(.rela.ctors) } | |||||
.rel.dtors : { *(.rel.dtors) } | |||||
.rela.dtors : { *(.rela.dtors) } | |||||
.rel.got : { *(.rel.got) } | |||||
.rela.got : { *(.rela.got) } | |||||
.rel.bss : { *(.rel.bss) } | |||||
.rela.bss : { *(.rela.bss) } | |||||
.rel.plt : { *(.rel.plt) } | |||||
.rela.plt : { *(.rela.plt) } | |||||
/* Internal text space or external memory. */ | |||||
.text : | |||||
{ | |||||
*(.vectors) | |||||
KEEP(*(.vectors)) | |||||
/* For data that needs to reside in the lower 64k of progmem. */ | |||||
*(.progmem.gcc*) | |||||
*(.progmem*) | |||||
. = ALIGN(2); | |||||
__trampolines_start = . ; | |||||
/* The jump trampolines for the 16-bit limited relocs will reside here. */ | |||||
*(.trampolines) | |||||
*(.trampolines*) | |||||
__trampolines_end = . ; | |||||
/* For future tablejump instruction arrays for 3 byte pc devices. | |||||
We don't relax jump/call instructions within these sections. */ | |||||
*(.jumptables) | |||||
*(.jumptables*) | |||||
/* For code that needs to reside in the lower 128k progmem. */ | |||||
*(.lowtext) | |||||
*(.lowtext*) | |||||
__ctors_start = . ; | |||||
*(.ctors) | |||||
__ctors_end = . ; | |||||
__dtors_start = . ; | |||||
*(.dtors) | |||||
__dtors_end = . ; | |||||
KEEP(SORT(*)(.ctors)) | |||||
KEEP(SORT(*)(.dtors)) | |||||
/* From this point on, we don't bother about wether the insns are | |||||
below or above the 16 bits boundary. */ | |||||
*(.init0) /* Start here after reset. */ | |||||
KEEP (*(.init0)) | |||||
*(.init1) | |||||
KEEP (*(.init1)) | |||||
*(.init2) /* Clear __zero_reg__, set up stack pointer. */ | |||||
KEEP (*(.init2)) | |||||
*(.init3) | |||||
KEEP (*(.init3)) | |||||
*(.init4) /* Initialize data and BSS. */ | |||||
KEEP (*(.init4)) | |||||
*(.init5) | |||||
KEEP (*(.init5)) | |||||
*(.init6) /* C++ constructors. */ | |||||
KEEP (*(.init6)) | |||||
*(.init7) | |||||
KEEP (*(.init7)) | |||||
*(.init8) | |||||
KEEP (*(.init8)) | |||||
*(.init9) /* Call main(). */ | |||||
KEEP (*(.init9)) | |||||
*(.text) | |||||
. = ALIGN(2); | |||||
*(.text.*) | |||||
. = ALIGN(2); | |||||
*(.fini9) /* _exit() starts here. */ | |||||
KEEP (*(.fini9)) | |||||
*(.fini8) | |||||
KEEP (*(.fini8)) | |||||
*(.fini7) | |||||
KEEP (*(.fini7)) | |||||
*(.fini6) /* C++ destructors. */ | |||||
KEEP (*(.fini6)) | |||||
*(.fini5) | |||||
KEEP (*(.fini5)) | |||||
*(.fini4) | |||||
KEEP (*(.fini4)) | |||||
*(.fini3) | |||||
KEEP (*(.fini3)) | |||||
*(.fini2) | |||||
KEEP (*(.fini2)) | |||||
*(.fini1) | |||||
KEEP (*(.fini1)) | |||||
*(.fini0) /* Infinite loop after program termination. */ | |||||
KEEP (*(.fini0)) | |||||
_etext = . ; | |||||
} > text | |||||
.data : AT (ADDR (.text) + SIZEOF (.text)) | |||||
{ | |||||
PROVIDE (__data_start = .) ; | |||||
*(.data) | |||||
*(.data*) | |||||
*(.rodata) /* We need to include .rodata here if gcc is used */ | |||||
*(.rodata*) /* with -fdata-sections. */ | |||||
*(.gnu.linkonce.d*) | |||||
. = ALIGN(2); | |||||
_edata = . ; | |||||
PROVIDE (__data_end = .) ; | |||||
} > data | |||||
.bss : AT (ADDR (.bss)) | |||||
{ | |||||
PROVIDE (__bss_start = .) ; | |||||
*(.bss) | |||||
*(.bss*) | |||||
*(COMMON) | |||||
PROVIDE (__bss_end = .) ; | |||||
} > data | |||||
__data_load_start = LOADADDR(.data); | |||||
__data_load_end = __data_load_start + SIZEOF(.data); | |||||
/* Global data not cleared after reset. */ | |||||
.noinit : | |||||
{ | |||||
PROVIDE (__noinit_start = .) ; | |||||
*(.noinit*) | |||||
PROVIDE (__noinit_end = .) ; | |||||
_end = . ; | |||||
PROVIDE (__heap_start = .) ; | |||||
} > data | |||||
/* keymap region is located at end of flash | |||||
* .fn_actions Fn actions definitions | |||||
* .keymaps Mapping layers | |||||
*/ | |||||
.keymap : | |||||
{ | |||||
PROVIDE(__keymap_start = .) ; | |||||
*(.keymap.fn_actions) /* 32*actions = 64bytes */ | |||||
. = ALIGN(0x40); | |||||
*(.keymap.keymaps) /* rest of .keymap section */ | |||||
*(.keymap*) | |||||
/* . = ALIGN(0x800); */ /* keymap section takes 2KB- */ | |||||
} > keymap = 0x00 /* zero fill */ | |||||
.eeprom : | |||||
{ | |||||
*(.eeprom*) | |||||
__eeprom_end = . ; | |||||
} > eeprom | |||||
.fuse : | |||||
{ | |||||
KEEP(*(.fuse)) | |||||
KEEP(*(.lfuse)) | |||||
KEEP(*(.hfuse)) | |||||
KEEP(*(.efuse)) | |||||
} > fuse | |||||
.lock : | |||||
{ | |||||
KEEP(*(.lock*)) | |||||
} > lock | |||||
.signature : | |||||
{ | |||||
KEEP(*(.signature*)) | |||||
} > signature | |||||
/* Stabs debugging sections. */ | |||||
.stab 0 : { *(.stab) } | |||||
.stabstr 0 : { *(.stabstr) } | |||||
.stab.excl 0 : { *(.stab.excl) } | |||||
.stab.exclstr 0 : { *(.stab.exclstr) } | |||||
.stab.index 0 : { *(.stab.index) } | |||||
.stab.indexstr 0 : { *(.stab.indexstr) } | |||||
.comment 0 : { *(.comment) } | |||||
/* DWARF debug sections. | |||||
Symbols in the DWARF debugging sections are relative to the beginning | |||||
of the section so we begin them at 0. */ | |||||
/* DWARF 1 */ | |||||
.debug 0 : { *(.debug) } | |||||
.line 0 : { *(.line) } | |||||
/* GNU DWARF 1 extensions */ | |||||
.debug_srcinfo 0 : { *(.debug_srcinfo) } | |||||
.debug_sfnames 0 : { *(.debug_sfnames) } | |||||
/* DWARF 1.1 and DWARF 2 */ | |||||
.debug_aranges 0 : { *(.debug_aranges) } | |||||
.debug_pubnames 0 : { *(.debug_pubnames) } | |||||
/* DWARF 2 */ | |||||
.debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) } | |||||
.debug_abbrev 0 : { *(.debug_abbrev) } | |||||
.debug_line 0 : { *(.debug_line) } | |||||
.debug_frame 0 : { *(.debug_frame) } | |||||
.debug_str 0 : { *(.debug_str) } | |||||
.debug_loc 0 : { *(.debug_loc) } | |||||
.debug_macinfo 0 : { *(.debug_macinfo) } | |||||
} |
/* | |||||
/* | |||||
* linker script for configurable keymap | * linker script for configurable keymap | ||||
* | * | ||||
* This adds keymap section which places keymap at fixed address and | * This adds keymap section which places keymap at fixed address and | ||||
OUTPUT_ARCH(avr:5) | OUTPUT_ARCH(avr:5) | ||||
MEMORY | MEMORY | ||||
{ | { | ||||
/* With keymap section | |||||
/* With keymap section | |||||
* | * | ||||
* Flash Map of ATMega32U4(32KB) | * Flash Map of ATMega32U4(32KB) | ||||
* +------------+ 0x0000 | * +------------+ 0x0000 | ||||
{ | { | ||||
PROVIDE(__keymap_start = .) ; | PROVIDE(__keymap_start = .) ; | ||||
*(.keymap.fn_actions) /* 32*actions = 64bytes */ | *(.keymap.fn_actions) /* 32*actions = 64bytes */ | ||||
. = ALIGN(0x40); | |||||
. = ALIGN(0x40); | |||||
*(.keymap.keymaps) /* rest of .keymap section */ | *(.keymap.keymaps) /* rest of .keymap section */ | ||||
*(.keymap*) | *(.keymap*) | ||||
/* . = ALIGN(0x800); */ /* keymap section takes 2KB- */ | /* . = ALIGN(0x800); */ /* keymap section takes 2KB- */ |
void ibm4704_init(void) | void ibm4704_init(void) | ||||
{ | { | ||||
inhibit(); // keep keyboard from sending | |||||
IBM4704_INT_INIT(); | IBM4704_INT_INIT(); | ||||
IBM4704_INT_ON(); | IBM4704_INT_ON(); | ||||
idle(); | |||||
idle(); // allow keyboard sending | |||||
} | } | ||||
/* | /* | ||||
return rbuf_dequeue(); | return rbuf_dequeue(); | ||||
} | } | ||||
uint8_t ibm4704_recv(void) | |||||
{ | |||||
if (rbuf_has_data()) { | |||||
return rbuf_dequeue(); | |||||
} else { | |||||
return -1; | |||||
} | |||||
} | |||||
/* | /* | ||||
Keyboard to Host | Keyboard to Host | ||||
---------------- | ---------------- | ||||
Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part. | Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part. | ||||
____ __ __ __ __ __ __ __ __ __ ________ | |||||
Clock \____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ | |||||
____ __ __ __ __ __ __ __ __ __ _______ | |||||
Clock \_____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ | |||||
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ | ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ | ||||
Data ____/ X____X____X____X____X____X____X____X____X____X________ | Data ____/ X____X____X____X____X____X____X____X____X____X________ | ||||
Start 0 1 2 3 4 5 6 7 P Stop | Start 0 1 2 3 4 5 6 7 P Stop | ||||
Start bit: can be long as 300-350us. | Start bit: can be long as 300-350us. | ||||
Inhibit: Pull Data line down to inhibit keyboard to send. | Inhibit: Pull Data line down to inhibit keyboard to send. | ||||
Timing: Host reads bit while Clock is hi. | |||||
Timing: Host reads bit while Clock is hi.(rising edge) | |||||
Stop bit: Keyboard pulls down Data line to lo after 9th clock. | Stop bit: Keyboard pulls down Data line to lo after 9th clock. | ||||
*/ | */ | ||||
uint8_t ibm4704_recv(void) | |||||
{ | |||||
if (rbuf_has_data()) { | |||||
return rbuf_dequeue(); | |||||
} else { | |||||
return -1; | |||||
} | |||||
} | |||||
ISR(IBM4704_INT_VECT) | ISR(IBM4704_INT_VECT) | ||||
{ | { | ||||
static enum { | static enum { | ||||
INIT, START, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY, | |||||
} state = INIT; | |||||
BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY, STOP | |||||
} state = BIT0; | |||||
// LSB first | // LSB first | ||||
static uint8_t data = 0; | static uint8_t data = 0; | ||||
// Odd parity | // Odd parity | ||||
static uint8_t parity = false; | static uint8_t parity = false; | ||||
ibm4704_error = 0; | ibm4704_error = 0; | ||||
// return unless falling edge | |||||
if (clock_in()) { goto RETURN; } // why this occurs? | |||||
state++; | |||||
switch (state) { | switch (state) { | ||||
case START: | |||||
// Data:Low | |||||
WAIT(data_hi, 10, state); | |||||
break; | |||||
case BIT0: | case BIT0: | ||||
case BIT1: | case BIT1: | ||||
case BIT2: | case BIT2: | ||||
} | } | ||||
if (!parity) | if (!parity) | ||||
goto ERROR; | goto ERROR; | ||||
break; | |||||
case STOP: | |||||
// Data:Low | |||||
WAIT(data_lo, 100, state); | |||||
rbuf_enqueue(data); | rbuf_enqueue(data); | ||||
ibm4704_error = IBM4704_ERR_NONE; | ibm4704_error = IBM4704_ERR_NONE; | ||||
goto DONE; | goto DONE; | ||||
default: | default: | ||||
goto ERROR; | goto ERROR; | ||||
} | } | ||||
state++; | |||||
goto RETURN; | goto RETURN; | ||||
ERROR: | ERROR: | ||||
ibm4704_error = state; | ibm4704_error = state; | ||||
while (ibm4704_send(0xFE)) _delay_ms(1); // resend | while (ibm4704_send(0xFE)) _delay_ms(1); // resend | ||||
xprintf("R:%02X%02X\n", state, data); | xprintf("R:%02X%02X\n", state, data); | ||||
DONE: | DONE: | ||||
state = INIT; | |||||
state = BIT0; | |||||
data = 0; | data = 0; | ||||
parity = false; | parity = false; | ||||
RETURN: | RETURN: |
#include "lufa.h" | #include "lufa.h" | ||||
uint8_t keyboard_idle = 0; | uint8_t keyboard_idle = 0; | ||||
/* 0: Boot Protocol, 1: Report Protocol(default) */ | |||||
uint8_t keyboard_protocol = 1; | uint8_t keyboard_protocol = 1; | ||||
static uint8_t keyboard_led_stats = 0; | static uint8_t keyboard_led_stats = 0; | ||||
void EVENT_USB_Device_Suspend() | void EVENT_USB_Device_Suspend() | ||||
{ | { | ||||
print("[S]"); | print("[S]"); | ||||
matrix_power_down(); | |||||
#ifdef SLEEP_LED_ENABLE | #ifdef SLEEP_LED_ENABLE | ||||
sleep_led_enable(); | sleep_led_enable(); | ||||
#endif | #endif | ||||
#endif | #endif | ||||
} | } | ||||
#ifdef CONSOLE_ENABLE | |||||
static bool console_flush = false; | |||||
#define CONSOLE_FLUSH_SET(b) do { \ | |||||
uint8_t sreg = SREG; cli(); console_flush = b; SREG = sreg; \ | |||||
} while (0) | |||||
// called every 1ms | |||||
void EVENT_USB_Device_StartOfFrame(void) | void EVENT_USB_Device_StartOfFrame(void) | ||||
{ | { | ||||
static uint8_t count; | |||||
if (++count % 50) return; | |||||
count = 0; | |||||
if (!console_flush) return; | |||||
Console_Task(); | Console_Task(); | ||||
console_flush = false; | |||||
} | } | ||||
#endif | |||||
/** Event handler for the USB_ConfigurationChanged event. | /** Event handler for the USB_ConfigurationChanged event. | ||||
* This is fired when the host sets the current configuration of the USB device after enumeration. | * This is fired when the host sets the current configuration of the USB device after enumeration. | ||||
* | |||||
* ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4, | |||||
* it is safe to use singl bank for all endpoints. | |||||
*/ | */ | ||||
void EVENT_USB_Device_ConfigurationChanged(void) | void EVENT_USB_Device_ConfigurationChanged(void) | ||||
{ | { | ||||
#ifdef CONSOLE_ENABLE | #ifdef CONSOLE_ENABLE | ||||
/* Setup Console HID Report Endpoints */ | /* Setup Console HID Report Endpoints */ | ||||
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | ||||
CONSOLE_EPSIZE, ENDPOINT_BANK_DOUBLE); | |||||
CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE); | |||||
#if 0 | #if 0 | ||||
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT, | ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT, | ||||
CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE); | CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE); | ||||
Endpoint_ClearSETUP(); | Endpoint_ClearSETUP(); | ||||
Endpoint_ClearStatusStage(); | Endpoint_ClearStatusStage(); | ||||
keyboard_protocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00); | |||||
#ifdef NKRO_ENABLE | |||||
keyboard_nkro = !!keyboard_protocol; | |||||
#endif | |||||
keyboard_protocol = (USB_ControlRequest.wValue & 0xFF); | |||||
clear_keyboard(); | clear_keyboard(); | ||||
} | } | ||||
} | } | ||||
/* Select the Keyboard Report Endpoint */ | /* Select the Keyboard Report Endpoint */ | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
if (keyboard_nkro) { | |||||
if (keyboard_protocol && keyboard_nkro) { | |||||
/* Report protocol - NKRO */ | /* Report protocol - NKRO */ | ||||
Endpoint_SelectEndpoint(NKRO_IN_EPNUM); | Endpoint_SelectEndpoint(NKRO_IN_EPNUM); | ||||
// Because sendchar() is called so many times, waiting each call causes big lag. | // Because sendchar() is called so many times, waiting each call causes big lag. | ||||
static bool timeouted = false; | static bool timeouted = false; | ||||
// prevents Console_Task() from running during sendchar() runs. | |||||
// or char will be lost. These two function is mutually exclusive. | |||||
CONSOLE_FLUSH_SET(false); | |||||
if (USB_DeviceState != DEVICE_STATE_Configured) | if (USB_DeviceState != DEVICE_STATE_Configured) | ||||
return -1; | return -1; | ||||
Endpoint_Write_8(c); | Endpoint_Write_8(c); | ||||
// send when bank is full | // send when bank is full | ||||
if (!Endpoint_IsReadWriteAllowed()) | |||||
if (!Endpoint_IsReadWriteAllowed()) { | |||||
while (!(Endpoint_IsINReady())); | |||||
Endpoint_ClearIN(); | Endpoint_ClearIN(); | ||||
} else { | |||||
CONSOLE_FLUSH_SET(true); | |||||
} | |||||
Endpoint_SelectEndpoint(ep); | Endpoint_SelectEndpoint(ep); | ||||
return 0; | return 0; | ||||
/******************************************************************************* | /******************************************************************************* | ||||
* main | * main | ||||
******************************************************************************/ | ******************************************************************************/ | ||||
static void SetupHardware(void) | |||||
static void setup_mcu(void) | |||||
{ | { | ||||
/* Disable watchdog if enabled by bootloader/fuses */ | /* Disable watchdog if enabled by bootloader/fuses */ | ||||
MCUSR &= ~(1 << WDRF); | MCUSR &= ~(1 << WDRF); | ||||
/* Disable clock division */ | /* Disable clock division */ | ||||
clock_prescale_set(clock_div_1); | clock_prescale_set(clock_div_1); | ||||
} | |||||
static void setup_usb(void) | |||||
{ | |||||
// Leonardo needs. Without this USB device is not recognized. | // Leonardo needs. Without this USB device is not recognized. | ||||
USB_Disable(); | USB_Disable(); | ||||
int main(void) __attribute__ ((weak)); | int main(void) __attribute__ ((weak)); | ||||
int main(void) | int main(void) | ||||
{ | { | ||||
SetupHardware(); | |||||
setup_mcu(); | |||||
keyboard_setup(); | |||||
setup_usb(); | |||||
sei(); | sei(); | ||||
/* wait for USB startup & debug output */ | /* wait for USB startup & debug output */ |
static inline void reset(void); | static inline void reset(void); | ||||
static inline uint32_t response(void); | static inline uint32_t response(void); | ||||
#define out_hi_delay(intervals) do { out_hi(); _delay_us(NEXT_KBD_TIMING * intervals); } while (0); | |||||
#define out_lo_delay(intervals) do { out_lo(); _delay_us(NEXT_KBD_TIMING * intervals); } while (0); | |||||
#define query_delay(intervals) do { query(); _delay_us(NEXT_KBD_TIMING * intervals); } while (0); | |||||
#define reset_delay(intervals) do { reset(); _delay_us(NEXT_KBD_TIMING * intervals); } while (0); | |||||
/* The keyboard sends signal with 50us pulse width on OUT line | |||||
* while it seems to miss the 50us pulse on In line. | |||||
* next_kbd_set_leds() often fails to sync LED status with 50us | |||||
* but it works well with 51us(+1us) on TMK converter(ATMeaga32u2) at least. | |||||
* TODO: test on Teensy and Pro Micro configuration | |||||
*/ | |||||
#define out_hi_delay(intervals) do { out_hi(); _delay_us((NEXT_KBD_TIMING+1) * intervals); } while (0); | |||||
#define out_lo_delay(intervals) do { out_lo(); _delay_us((NEXT_KBD_TIMING+1) * intervals); } while (0); | |||||
#define query_delay(intervals) do { query(); _delay_us((NEXT_KBD_TIMING+1) * intervals); } while (0); | |||||
#define reset_delay(intervals) do { reset(); _delay_us((NEXT_KBD_TIMING+1) * intervals); } while (0); | |||||
void next_kbd_init(void) | void next_kbd_init(void) | ||||
{ | { | ||||
void next_kbd_set_leds(bool left, bool right) | void next_kbd_set_leds(bool left, bool right) | ||||
{ | { | ||||
cli(); | |||||
out_lo_delay(9); | out_lo_delay(9); | ||||
out_hi_delay(3); | out_hi_delay(3); | ||||
out_lo_delay(7); | out_lo_delay(7); | ||||
out_hi(); | out_hi(); | ||||
sei(); | |||||
} | } | ||||
#define NEXT_KBD_READ (NEXT_KBD_IN_PIN&(1<<NEXT_KBD_IN_BIT)) | #define NEXT_KBD_READ (NEXT_KBD_IN_PIN&(1<<NEXT_KBD_IN_BIT)) |
// set for 16 MHz clock | // set for 16 MHz clock | ||||
CPU_PRESCALE(0); | CPU_PRESCALE(0); | ||||
keyboard_setup(); | |||||
// Initialize the USB, and then wait for the host to set configuration. | // Initialize the USB, and then wait for the host to set configuration. | ||||
// If the Teensy is powered without a PC connected to the USB port, | // If the Teensy is powered without a PC connected to the USB port, | ||||
// this will wait forever. | // this will wait forever. |
Subproject commit 94c560c854c7a1dfc35e9de9db05de1b202de6c6 |
Subproject commit c30fcdf1f112de581de7b145a97630539e5cff44 |
Subproject commit 77762338286535dabb9c94b87060e33e487ff0f3 |
Subproject commit 77b033420485f7d3d35430c0e8d4d844aa894834 |
#ifndef LEONARDO_LED_H | |||||
#define LEONARDO_LED_H | |||||
// Leonardo "TX" LED for debug | |||||
#define LED_TX_INIT (DDRD |= (1<<5)) | |||||
#define LED_TX_ON (PORTD &= ~(1<<5)) | |||||
#define LED_TX_OFF (PORTD |= (1<<5)) | |||||
#define LED_TX_TOGGLE (PORTD ^= (1<<5)) | |||||
#endif |
void KBDReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) | void KBDReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) | ||||
{ | { | ||||
::memcpy(&usb_hid_keyboard_report, buf, sizeof(report_keyboard_t)); | |||||
usb_hid_time_stamp = millis(); | |||||
bool is_error = false; | |||||
report_keyboard_t *report = (report_keyboard_t *)buf; | |||||
dprintf("KBDReport: %02X %02X", report->mods, report->reserved); | |||||
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { | |||||
if (IS_ERROR(report->keys[i])) { | |||||
is_error = true; | |||||
} | |||||
dprintf(" %02X", report->keys[i]); | |||||
} | |||||
dprint("\r\n"); | |||||
debug("KBDReport: "); | |||||
debug_hex(usb_hid_keyboard_report.mods); | |||||
debug(" --"); | |||||
for (uint8_t i = 0; i < 6; i++) { | |||||
debug(" "); | |||||
debug_hex(usb_hid_keyboard_report.keys[i]); | |||||
// ignore error and not send report to computer | |||||
if (is_error) { | |||||
dprint("Error usage! \r\n"); | |||||
return; | |||||
} | } | ||||
debug("\r\n"); | |||||
::memcpy(&usb_hid_keyboard_report, buf, sizeof(report_keyboard_t)); | |||||
usb_hid_time_stamp = millis(); | |||||
} | } |
CFLAGS += -funsigned-char | CFLAGS += -funsigned-char | ||||
CFLAGS += -funsigned-bitfields | CFLAGS += -funsigned-bitfields | ||||
CFLAGS += -ffunction-sections | CFLAGS += -ffunction-sections | ||||
CFLAGS += -fdata-sections | |||||
CFLAGS += -fno-inline-small-functions | CFLAGS += -fno-inline-small-functions | ||||
CFLAGS += -fpack-struct | CFLAGS += -fpack-struct | ||||
CFLAGS += -fshort-enums | CFLAGS += -fshort-enums |