diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/bootloader.c | 22 | ||||
-rw-r--r-- | common/bootloader.h | 25 | ||||
-rw-r--r-- | common/command.c | 243 | ||||
-rw-r--r-- | common/command.h | 25 | ||||
-rw-r--r-- | common/controller_teensy.h | 27 | ||||
-rw-r--r-- | common/debug.h | 36 | ||||
-rw-r--r-- | common/host.c | 237 | ||||
-rw-r--r-- | common/host.h | 57 | ||||
-rw-r--r-- | common/host_driver.h | 33 | ||||
-rw-r--r-- | common/keyboard.c | 203 | ||||
-rw-r--r-- | common/keyboard.h | 28 | ||||
-rw-r--r-- | common/keymap.h | 34 | ||||
-rw-r--r-- | common/layer.c | 207 | ||||
-rw-r--r-- | common/layer.h | 32 | ||||
-rw-r--r-- | common/led.h | 33 | ||||
-rw-r--r-- | common/matrix.h | 49 | ||||
-rwxr-xr-x | common/mousekey.c | 132 | ||||
-rw-r--r-- | common/mousekey.h | 29 | ||||
-rw-r--r-- | common/print.c | 93 | ||||
-rw-r--r-- | common/print.h | 45 | ||||
-rw-r--r-- | common/report.h | 96 | ||||
-rw-r--r-- | common/sendchar.h | 27 | ||||
-rw-r--r-- | common/sendchar_null.c | 23 | ||||
-rw-r--r-- | common/sendchar_uart.c | 25 | ||||
-rw-r--r-- | common/timer.c | 89 | ||||
-rw-r--r-- | common/timer.h | 53 | ||||
-rw-r--r-- | common/uart.c | 129 | ||||
-rw-r--r-- | common/uart.h | 11 | ||||
-rw-r--r-- | common/usb_keycodes.h | 423 | ||||
-rw-r--r-- | common/util.c | 37 | ||||
-rw-r--r-- | common/util.h | 34 |
31 files changed, 2537 insertions, 0 deletions
diff --git a/common/bootloader.c b/common/bootloader.c new file mode 100644 index 0000000000..5cbfc72e5b --- /dev/null +++ b/common/bootloader.c @@ -0,0 +1,22 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "bootloader.h" + + +void bootloader_jump(void) __attribute__ ((weak)); +void bootloader_jump(void) {} diff --git a/common/bootloader.h b/common/bootloader.h new file mode 100644 index 0000000000..44775039d5 --- /dev/null +++ b/common/bootloader.h @@ -0,0 +1,25 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef BOOTLOADER_H +#define BOOTLOADER_H + + +/* give code for your bootloader to come up if needed */ +void bootloader_jump(void); + +#endif diff --git a/common/command.c b/common/command.c new file mode 100644 index 0000000000..e325a5d847 --- /dev/null +++ b/common/command.c @@ -0,0 +1,243 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <stdint.h> +#include <stdbool.h> +#include <util/delay.h> +#include "usb_keycodes.h" +#include "host.h" +#include "print.h" +#include "debug.h" +#include "util.h" +#include "timer.h" +#include "layer.h" +#include "matrix.h" +#include "bootloader.h" +#include "command.h" + +#ifdef HOST_PJRC +# include "usb_keyboard.h" +# ifdef EXTRAKEY_ENABLE +# include "usb_extra.h" +# endif +#endif + +#ifdef HOST_VUSB +# include "usbdrv.h" +#endif + + +static uint8_t command_common(void); +static void help(void); +static void switch_layer(uint8_t layer); + +static bool last_print_enable; + +uint8_t command_proc(void) +{ + uint8_t processed = 0; + last_print_enable = print_enable; + + if (!IS_COMMAND()) + return 0; + + print_enable = true; + if (command_extra() || command_common()) { + processed = 1; + _delay_ms(500); + } + print_enable = last_print_enable; + return processed; +} + +/* This allows to define extra commands. return 0 when not processed. */ +uint8_t command_extra(void) __attribute__ ((weak)); +uint8_t command_extra(void) +{ + return 0; +} + + +static uint8_t command_common(void) +{ + switch (host_get_first_key()) { + case KB_H: + help(); + break; + case KB_B: + host_clear_keyboard_report(); + host_send_keyboard_report(); + print("jump to bootloader... "); + _delay_ms(1000); + bootloader_jump(); // not return + print("not supported.\n"); + break; + case KB_D: + debug_enable = !debug_enable; + if (debug_enable) { + last_print_enable = true; + print("debug enabled.\n"); + debug_matrix = true; + debug_keyboard = true; + debug_mouse = true; + } else { + print("debug disabled.\n"); + last_print_enable = false; + debug_matrix = false; + debug_keyboard = false; + debug_mouse = false; + } + break; + case KB_X: // debug matrix toggle + debug_matrix = !debug_matrix; + if (debug_matrix) + print("debug matrix enabled.\n"); + else + print("debug matrix disabled.\n"); + break; + case KB_K: // debug keyboard toggle + debug_keyboard = !debug_keyboard; + if (debug_keyboard) + print("debug keyboard enabled.\n"); + else + print("debug keyboard disabled.\n"); + break; + case KB_M: // debug mouse toggle + debug_mouse = !debug_mouse; + if (debug_mouse) + print("debug mouse enabled.\n"); + else + print("debug mouse disabled.\n"); + break; + case KB_V: // print version & information + print(STR(DESCRIPTION) "\n"); + break; + case KB_T: // print timer + print("timer: "); phex16(timer_count); print("\n"); + break; + case KB_P: // print toggle + if (last_print_enable) { + print("print disabled.\n"); + last_print_enable = false; + } else { + last_print_enable = true; + print("print enabled.\n"); + } + break; + case KB_S: +#ifdef HOST_PJRC + print("UDCON: "); phex(UDCON); print("\n"); + print("UDIEN: "); phex(UDIEN); print("\n"); + print("UDINT: "); phex(UDINT); print("\n"); + print("usb_keyboard_leds:"); phex(usb_keyboard_leds); print("\n"); + print("usb_keyboard_protocol: "); phex(usb_keyboard_protocol); print("\n"); + print("usb_keyboard_idle_config:"); phex(usb_keyboard_idle_config); print("\n"); + print("usb_keyboard_idle_count:"); phex(usb_keyboard_idle_count); print("\n"); +#endif + +#ifdef HOST_VUSB +# if USB_COUNT_SOF + print("usbSofCount: "); phex(usbSofCount); print("\n"); +# endif +#endif + break; +#ifdef NKRO_ENABLE + case KB_N: + // send empty report before change + host_clear_keyboard_report(); + host_send_keyboard_report(); + keyboard_nkro = !keyboard_nkro; + if (keyboard_nkro) + print("NKRO: enabled\n"); + else + print("NKRO: disabled\n"); + break; +#endif +#ifdef EXTRAKEY_ENABLE + case KB_ESC: + host_clear_keyboard_report(); + host_send_keyboard_report(); +#ifdef HOST_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); + host_system_send(0); + _delay_ms(500); +#endif + break; +#endif + case KB_BSPC: + matrix_init(); + print("clear matrix\n"); + break; + case KB_0: + switch_layer(0); + break; + case KB_1: + switch_layer(1); + break; + case KB_2: + switch_layer(2); + break; + case KB_3: + switch_layer(3); + break; + case KB_4: + switch_layer(4); + break; + default: + return 0; + } + return 1; +} + +static void help(void) +{ + print("b: jump to bootloader\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"); + print("p: toggle print enable\n"); + print("v: print version\n"); + print("t: print timer count\n"); + print("s: print status\n"); +#ifdef NKRO_ENABLE + print("n: toggle NKRO\n"); +#endif + print("Backspace: clear matrix\n"); + print("ESC: power down/wake up\n"); + print("0: switch to Layer0 \n"); + print("1: switch to Layer1 \n"); + print("2: switch to Layer2 \n"); + print("3: switch to Layer3 \n"); + print("4: switch to Layer4 \n"); +} + +static void switch_layer(uint8_t layer) +{ + print("current_layer: "); phex(current_layer); print("\n"); + print("default_layer: "); phex(default_layer); print("\n"); + current_layer = layer; + default_layer = layer; + print("switch to Layer: "); phex(layer); print("\n"); +} diff --git a/common/command.h b/common/command.h new file mode 100644 index 0000000000..4888f5ee0b --- /dev/null +++ b/common/command.h @@ -0,0 +1,25 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef COMMAND_H +#define COMMAND + +uint8_t command_proc(void); +/* This allows to extend commands. Return 0 when command is not processed. */ +uint8_t command_extra(void); + +#endif diff --git a/common/controller_teensy.h b/common/controller_teensy.h new file mode 100644 index 0000000000..6c3f47ce4e --- /dev/null +++ b/common/controller_teensy.h @@ -0,0 +1,27 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef TEENSY_H +#define TEENSY_H 1 + +// for Teensy/Teensy++ 2.0 +#define DEBUG_LED 1 +#define DEBUG_LED_CONFIG (DDRD |= (1<<6)) +#define DEBUG_LED_ON (PORTD |= (1<<6)) +#define DEBUG_LED_OFF (PORTD &= ~(1<<6)) + +#endif diff --git a/common/debug.h b/common/debug.h new file mode 100644 index 0000000000..230d3b3499 --- /dev/null +++ b/common/debug.h @@ -0,0 +1,36 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef DEBUG_H +#define DEBUG_H 1 + +#include "print.h" + + +#define debug(s) if(debug_enable) print(s) +#define debug_hex(c) if(debug_enable) phex(c) +#define debug_hex16(i) if(debug_enable) phex16(i) +#define debug_bin(c) if(debug_enable) pbin(c) +#define debug_bin_reverse(c) if(debug_enable) pbin_reverse(c) + + +bool debug_enable; +bool debug_matrix; +bool debug_keyboard; +bool debug_mouse; + +#endif diff --git a/common/host.c b/common/host.c new file mode 100644 index 0000000000..cc26d55c22 --- /dev/null +++ b/common/host.c @@ -0,0 +1,237 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <avr/interrupt.h> +#include "usb_keycodes.h" +#include "host.h" +#include "util.h" +#include "debug.h" + + +#ifdef NKRO_ENABLE +bool keyboard_nkro = false; +#endif + +static host_driver_t *driver; +static report_keyboard_t report0; +static report_keyboard_t report1; +report_keyboard_t *keyboard_report = &report0; +report_keyboard_t *keyboard_report_prev = &report1; + + +static inline void add_key_byte(uint8_t code); +static inline void del_key_byte(uint8_t code); +static inline void add_key_bit(uint8_t code); +static inline void del_key_bit(uint8_t code); + + +void host_set_driver(host_driver_t *d) +{ + driver = d; +} + +host_driver_t *host_get_driver(void) +{ + return driver; +} + +uint8_t host_keyboard_leds(void) +{ + if (!driver) return 0; + return (*driver->keyboard_leds)(); +} + +/* keyboard report operations */ +void host_add_key(uint8_t key) +{ +#ifdef NKRO_ENABLE + if (keyboard_nkro) { + add_key_bit(key); + return; + } +#endif + add_key_byte(key); +} + +void host_del_key(uint8_t key) +{ +#ifdef NKRO_ENABLE + if (keyboard_nkro) { + del_key_bit(key); + return; + } +#endif + del_key_byte(key); +} + +void host_add_mod_bit(uint8_t mod) +{ + keyboard_report->mods |= mod; +} + +void host_del_mod_bit(uint8_t mod) +{ + keyboard_report->mods &= ~mod; +} + +void host_set_mods(uint8_t mods) +{ + keyboard_report->mods = mods; +} + +void host_add_code(uint8_t code) +{ + if (IS_MOD(code)) { + host_add_mod_bit(MOD_BIT(code)); + } else { + host_add_key(code); + } +} + +void host_del_code(uint8_t code) +{ + if (IS_MOD(code)) { + host_del_mod_bit(MOD_BIT(code)); + } else { + host_del_key(code); + } +} + +void host_swap_keyboard_report(void) +{ + uint8_t sreg = SREG; + cli(); + report_keyboard_t *tmp = keyboard_report_prev; + keyboard_report_prev = keyboard_report; + keyboard_report = tmp; + SREG = sreg; +} + +void host_clear_keyboard_report(void) +{ + keyboard_report->mods = 0; + for (int8_t i = 0; i < REPORT_KEYS; i++) { + keyboard_report->keys[i] = 0; + } +} + +uint8_t host_has_anykey(void) +{ + uint8_t cnt = 0; + for (int i = 0; i < REPORT_KEYS; i++) { + if (keyboard_report->keys[i]) + cnt++; + } + return cnt; +} + +uint8_t host_get_first_key(void) +{ +#ifdef NKRO_ENABLE + if (keyboard_nkro) { + uint8_t i = 0; + for (; i < REPORT_KEYS && !keyboard_report->keys[i]; i++) + ; + return i<<3 | biton(keyboard_report->keys[i]); + } +#endif + return keyboard_report->keys[0]; +} + + +void host_send_keyboard_report(void) +{ + if (!driver) return; + (*driver->send_keyboard)(keyboard_report); +} + +void host_mouse_send(report_mouse_t *report) +{ + if (!driver) return; + (*driver->send_mouse)(report); +} + +void host_system_send(uint16_t data) +{ + if (!driver) return; + (*driver->send_system)(data); +} + +void host_consumer_send(uint16_t data) +{ + // TODO: this is needed? + static uint16_t last_data = 0; + if (data == last_data) return; + last_data = data; + + if (!driver) return; + (*driver->send_consumer)(data); +} + + +static inline void add_key_byte(uint8_t code) +{ + // TODO: fix ugly code + int8_t i = 0; + int8_t empty = -1; + for (; i < REPORT_KEYS; i++) { + if (keyboard_report_prev->keys[i] == code) { + keyboard_report->keys[i] = code; + break; + } + if (empty == -1 && + keyboard_report_prev->keys[i] == 0 && + keyboard_report->keys[i] == 0) { + empty = i; + } + } + if (i == REPORT_KEYS) { + if (empty != -1) { + keyboard_report->keys[empty] = code; + } + } +} + +static inline void del_key_byte(uint8_t code) +{ + int i = 0; + for (; i < REPORT_KEYS; i++) { + if (keyboard_report->keys[i] == code) { + keyboard_report->keys[i] = 0; + break; + } + } +} + +static inline void add_key_bit(uint8_t code) +{ + if ((code>>3) < REPORT_KEYS) { + keyboard_report->keys[code>>3] |= 1<<(code&7); + } else { + debug("add_key_bit: can't add: "); phex(code); debug("\n"); + } +} + +static inline void del_key_bit(uint8_t code) +{ + if ((code>>3) < REPORT_KEYS) { + keyboard_report->keys[code>>3] &= ~(1<<(code&7)); + } else { + debug("del_key_bit: can't del: "); phex(code); debug("\n"); + } +} diff --git a/common/host.h b/common/host.h new file mode 100644 index 0000000000..11b9aacd7c --- /dev/null +++ b/common/host.h @@ -0,0 +1,57 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef HOST_H +#define HOST_H + +#include <stdint.h> +#include "report.h" +#include "host_driver.h" + + +#ifdef NKRO_ENABLE +extern bool keyboard_nkro; +#endif + +extern report_keyboard_t *keyboard_report; +extern report_keyboard_t *keyboard_report_prev; + + +void host_set_driver(host_driver_t *driver); +host_driver_t *host_get_driver(void); +uint8_t host_keyboard_leds(void); + +/* keyboard report operations */ +void host_add_key(uint8_t key); +void host_del_key(uint8_t key); +void host_add_mod_bit(uint8_t mod); +void host_del_mod_bit(uint8_t mod); +void host_set_mods(uint8_t mods); +void host_add_code(uint8_t code); +void host_del_code(uint8_t code); +void host_swap_keyboard_report(void); +void host_clear_keyboard_report(void); +uint8_t host_has_anykey(void); +uint8_t host_get_first_key(void); + + +void host_send_keyboard_report(void); +void host_mouse_send(report_mouse_t *report); +void host_system_send(uint16_t data); +void host_consumer_send(uint16_t data); + +#endif diff --git a/common/host_driver.h b/common/host_driver.h new file mode 100644 index 0000000000..edb9e5dd9c --- /dev/null +++ b/common/host_driver.h @@ -0,0 +1,33 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef HOST_DRIVER_H +#define HOST_DRIVER_H + +#include <stdint.h> +#include "report.h" + + +typedef struct { + uint8_t (*keyboard_leds)(void); + void (*send_keyboard)(report_keyboard_t *); + void (*send_mouse)(report_mouse_t *); + void (*send_system)(uint16_t); + void (*send_consumer)(uint16_t); +} host_driver_t; + +#endif diff --git a/common/keyboard.c b/common/keyboard.c new file mode 100644 index 0000000000..5c2643c951 --- /dev/null +++ b/common/keyboard.c @@ -0,0 +1,203 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#include "keyboard.h" +#include "host.h" +#include "layer.h" +#include "matrix.h" +#include "led.h" +#include "usb_keycodes.h" +#include "timer.h" +#include "print.h" +#include "debug.h" +#include "command.h" +#ifdef MOUSEKEY_ENABLE +#include "mousekey.h" +#endif +#ifdef EXTRAKEY_ENABLE +#include <util/delay.h> +#endif + + +static uint8_t last_leds = 0; + + +void keyboard_init(void) +{ + timer_init(); + matrix_init(); +#ifdef PS2_MOUSE_ENABLE + ps2_mouse_init(); +#endif +} + +void keyboard_proc(void) +{ + uint8_t fn_bits = 0; +#ifdef EXTRAKEY_ENABLE + uint16_t consumer_code = 0; +#endif + + matrix_scan(); + + if (matrix_is_modified()) { + if (debug_matrix) matrix_print(); +#ifdef DEBUG_LED + // LED flash for debug + DEBUG_LED_CONFIG; + DEBUG_LED_ON; +#endif + } + + if (matrix_has_ghost()) { + // should send error? + debug("matrix has ghost!!\n"); + return; + } + + host_swap_keyboard_report(); + host_clear_keyboard_report(); + for (int row = 0; row < matrix_rows(); row++) { + for (int col = 0; col < matrix_cols(); col++) { + if (!matrix_is_on(row, col)) continue; + + uint8_t code = layer_get_keycode(row, col); + if (code == KB_NO) { + // do nothing + } else if (IS_MOD(code)) { + host_add_mod_bit(MOD_BIT(code)); + } else if (IS_FN(code)) { + fn_bits |= FN_BIT(code); + } +// TODO: use table or something +#ifdef EXTRAKEY_ENABLE + // System Control + else if (code == KB_SYSTEM_POWER) { +#ifdef HOST_PJRC + if (suspend && remote_wakeup) { + usb_remote_wakeup(); + } else { + host_system_send(SYSTEM_POWER_DOWN); + } +#else + host_system_send(SYSTEM_POWER_DOWN); +#endif + host_system_send(0); + _delay_ms(500); + } else if (code == KB_SYSTEM_SLEEP) { + host_system_send(SYSTEM_SLEEP); + host_system_send(0); + _delay_ms(500); + } else if (code == KB_SYSTEM_WAKE) { + host_system_send(SYSTEM_WAKE_UP); + host_system_send(0); + _delay_ms(500); + } + // Consumer Page + else if (code == KB_AUDIO_MUTE) { + consumer_code = AUDIO_MUTE; + } else if (code == KB_AUDIO_VOL_UP) { + consumer_code = AUDIO_VOL_UP; + } else if (code == KB_AUDIO_VOL_DOWN) { + consumer_code = AUDIO_VOL_DOWN; + } + else if (code == KB_MEDIA_NEXT_TRACK) { + consumer_code = TRANSPORT_NEXT_TRACK; + } else if (code == KB_MEDIA_PREV_TRACK) { + consumer_code = TRANSPORT_PREV_TRACK; + } else if (code == KB_MEDIA_STOP) { + consumer_code = TRANSPORT_STOP; + } else if (code == KB_MEDIA_PLAY_PAUSE) { + consumer_code = TRANSPORT_PLAY_PAUSE; + } else if (code == KB_MEDIA_SELECT) { + consumer_code = AL_CC_CONFIG; + } + else if (code == KB_MAIL) { + consumer_code = AL_EMAIL; + } else if (code == KB_CALCULATOR) { + consumer_code = AL_CALCULATOR; + } else if (code == KB_MY_COMPUTER) { + consumer_code = AL_LOCAL_BROWSER; + } + else if (code == KB_WWW_SEARCH) { + consumer_code = AC_SEARCH; + } else if (code == KB_WWW_HOME) { + consumer_code = AC_HOME; + } else if (code == KB_WWW_BACK) { + consumer_code = AC_BACK; + } else if (code == KB_WWW_FORWARD) { + consumer_code = AC_FORWARD; + } else if (code == KB_WWW_STOP) { + consumer_code = AC_STOP; + } else if (code == KB_WWW_REFRESH) { + consumer_code = AC_REFRESH; + } else if (code == KB_WWW_FAVORITES) { + consumer_code = AC_BOOKMARKS; + } +#endif + else if (IS_KEY(code)) { + host_add_key(code); + } +#ifdef MOUSEKEY_ENABLE + else if (IS_MOUSEKEY(code)) { + mousekey_decode(code); + } +#endif + else { + debug("ignore keycode: "); debug_hex(code); debug("\n"); + } + } + } + + layer_switching(fn_bits); + + if (command_proc()) { + return; + } + + // TODO: should send only when changed from last report + if (matrix_is_modified()) { + host_send_keyboard_report(); +#ifdef EXTRAKEY_ENABLE + host_consumer_send(consumer_code); +#endif +#ifdef DEBUG_LED + // LED flash for debug + DEBUG_LED_CONFIG; + DEBUG_LED_OFF; +#endif + } + +#ifdef MOUSEKEY_ENABLE + mousekey_send(); +#endif + +#ifdef PS2_MOUSE_ENABLE + // TODO: should comform new API + if (ps2_mouse_read() == 0) + ps2_mouse_usb_send(); +#endif + + if (last_leds != host_keyboard_leds()) { + keyboard_set_leds(host_keyboard_leds()); + last_leds = host_keyboard_leds(); + } +} + +void keyboard_set_leds(uint8_t leds) +{ + led_set(leds); +} diff --git a/common/keyboard.h b/common/keyboard.h new file mode 100644 index 0000000000..988dac36ed --- /dev/null +++ b/common/keyboard.h @@ -0,0 +1,28 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef KEYBOARD_H +#define KEYBOARD_H + +#include <stdint.h> + + +void keyboard_init(void); +void keyboard_proc(void); +void keyboard_set_leds(uint8_t leds); + +#endif diff --git a/common/keymap.h b/common/keymap.h new file mode 100644 index 0000000000..7dfd6c2a1b --- /dev/null +++ b/common/keymap.h @@ -0,0 +1,34 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef KEYMAP_H +#define KEYMAP_H + +#include <stdint.h> +#include <stdbool.h> + + +/* keycode in specific layer */ +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col); + +/* layer to move during press Fn key */ +uint8_t keymap_fn_layer(uint8_t fn_bits); + +/* keycode to send when release Fn key without using */ +uint8_t keymap_fn_keycode(uint8_t fn_bits); + +#endif diff --git a/common/layer.c b/common/layer.c new file mode 100644 index 0000000000..0854eede0d --- /dev/null +++ b/common/layer.c @@ -0,0 +1,207 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "keymap.h" +#include "host.h" +#include "debug.h" +#include "timer.h" +#include "usb_keycodes.h" +#include "layer.h" + + +/* + * Parameters: + * SWITCH_DELAY |=======| + * SEND_FN_TERM |================| + * + * Fn key processing cases: + * 1. release Fn after SEND_FN_TERM. + * Layer sw ___________|~~~~~~~~~~~|___ + * Fn press ___|~~~~~~~~~~~~~~~~~~~|___ + * Fn send ___________________________ + * + * 2. release Fn during SEND_FN_TERM.(not layer used) + * Layer sw ___________|~~~~~~|________ + * Fn press ___|~~~~~~~~~~~~~~|________ + * Fn key send __________________|~|______ + * other key press ___________________________ + * other key send ___________________________ + * + * 3. release Fn during SEND_FN_TERM.(layer used) + * Layer sw ___________|~~~~~~|________ + * Fn press ___|~~~~~~~~~~~~~~|________ + * Fn key send ___________________________ + * Fn send ___________________________ + * other key press _____________|~~|__________ + * other key send _____________|~~|__________ + * + * 4. press other key during SWITCH_DELAY. + * Layer sw ___________________________ + * Fn key press ___|~~~~~~~~~|_____________ + * Fn key send ______|~~~~~~|_____________ + * other key press ______|~~~|________________ + * other key send _______|~~|________________ + * + * 5. press Fn while press other key. + * Layer sw ___________________________ + * Fn key press ___|~~~~~~~~~|_____________ + * Fn key send ___|~~~~~~~~~|_____________ + * other key press ~~~~~~~|___________________ + * other key send ~~~~~~~|___________________ + * + * 6. press Fn twice quickly and keep holding down.(repeat) + * Layer sw ___________________________ + * Fn key press ___|~|____|~~~~~~~~~~~~~~~~ + * Fn key send _____|~|__|~~~~~~~~~~~~~~~~ + */ + +// LAYER_SWITCH_DELAY: prevent from moving to new layer +#ifndef LAYER_SWITCH_DELAY +# define LAYER_SWITCH_DELAY 150 +#endif + +// LAYER_SEND_FN_TERM: send keycode if release key in this term +#ifndef LAYER_SEND_FN_TERM +# define LAYER_SEND_FN_TERM 500 +#endif + + +uint8_t default_layer = 0; +uint8_t current_layer = 0; + +static bool layer_used = false; +static uint8_t new_layer(uint8_t fn_bits); + + +uint8_t layer_get_keycode(uint8_t row, uint8_t col) +{ + uint8_t code = keymap_get_keycode(current_layer, row, col); + // normal key or mouse key + if ((IS_KEY(code) || IS_MOUSEKEY(code))) { + layer_used = true; + } + return code; +} + +// bit substract b from a +#define BIT_SUBST(a, b) (a&(a^b)) +void layer_switching(uint8_t fn_bits) +{ + // layer switching + static uint8_t last_fn = 0; + static uint8_t last_mods = 0; + static uint16_t last_timer = 0; + static uint8_t sent_fn = 0; + + if (fn_bits == last_fn) { // Fn state is not changed + if (fn_bits == 0) { + // do nothing + } else { + if (!keymap_fn_keycode(BIT_SUBST(fn_bits, sent_fn)) || + timer_elapsed(last_timer) > LAYER_SWITCH_DELAY) { + uint8_t _layer_to_switch = new_layer(BIT_SUBST(fn_bits, sent_fn)); + if (current_layer != _layer_to_switch) { // not switch layer yet + debug("Fn case: 1,2,3(LAYER_SWITCH_DELAY passed)\n"); + debug("Switch Layer: "); debug_hex(current_layer); + current_layer = _layer_to_switch; + layer_used = false; + debug(" -> "); debug_hex(current_layer); debug("\n"); + } + } else { + if (host_has_anykey()) { // other keys is pressed + uint8_t _fn_to_send = BIT_SUBST(fn_bits, sent_fn); + if (_fn_to_send) { + debug("Fn case: 4(press other key during SWITCH_DELAY.)\n"); + // send only Fn key first + uint8_t tmp_mods = keyboard_report->mods; + host_add_code(keymap_fn_keycode(_fn_to_send)); + host_set_mods(last_mods); + host_send_keyboard_report(); + host_set_mods(tmp_mods); + host_del_code(keymap_fn_keycode(_fn_to_send)); + sent_fn |= _fn_to_send; + } + } + } + // add Fn keys to send + //host_add_code(keymap_fn_keycode(fn_bits&sent_fn)); // TODO: do all Fn keys + } + } else { // Fn state is changed(edge) + uint8_t fn_changed = 0; + + debug("fn_bits: "); debug_bin(fn_bits); debug("\n"); + debug("sent_fn: "); debug_bin(sent_fn); debug("\n"); + debug("last_fn: "); debug_bin(last_fn); debug("\n"); + debug("last_mods: "); debug_hex(last_mods); debug("\n"); + debug("last_timer: "); debug_hex16(last_timer); debug("\n"); + debug("timer_count: "); debug_hex16(timer_count); debug("\n"); + + // pressed Fn + if ((fn_changed = BIT_SUBST(fn_bits, last_fn))) { + debug("fn_changed: "); debug_bin(fn_changed); debug("\n"); + if (host_has_anykey()) { + debug("Fn case: 5(pressed Fn with other key)\n"); + sent_fn |= fn_changed; + } else if (fn_changed & sent_fn) { // pressed same Fn in a row + if (timer_elapsed(last_timer) > LAYER_SEND_FN_TERM) { + debug("Fn case: 6(not repeat)\n"); + // time passed: not repeate + sent_fn &= ~fn_changed; + } else { + debug("Fn case: 6(repeat)\n"); + } + } + } + // released Fn + if ((fn_changed = BIT_SUBST(last_fn, fn_bits))) { + debug("fn_changed: "); debug_bin(fn_changed); debug("\n"); + if (timer_elapsed(last_timer) < LAYER_SEND_FN_TERM) { + if (!layer_used && BIT_SUBST(fn_changed, sent_fn)) { + debug("Fn case: 2(send Fn one shot: released Fn during LAYER_SEND_FN_TERM)\n"); + // send only Fn key first + uint8_t tmp_mods = keyboard_report->mods; + host_add_code(keymap_fn_keycode(fn_changed)); + host_set_mods(last_mods); + host_send_keyboard_report(); + host_set_mods(tmp_mods); + host_del_code(keymap_fn_keycode(fn_changed)); + sent_fn |= fn_changed; + } + } + debug("Switch Layer(released Fn): "); debug_hex(current_layer); + current_layer = new_layer(BIT_SUBST(fn_bits, sent_fn)); + debug(" -> "); debug_hex(current_layer); debug("\n"); + } + + layer_used = false; + last_fn = fn_bits; + last_mods = keyboard_report->mods; + last_timer = timer_read(); + } + // send Fn keys + for (uint8_t i = 0; i < 8; i++) { + if ((sent_fn & fn_bits) & (1<<i)) { + host_add_code(keymap_fn_keycode(1<<i)); + } + } +} + +inline +static uint8_t new_layer(uint8_t fn_bits) +{ + return (fn_bits ? keymap_fn_layer(fn_bits) : default_layer); +} diff --git a/common/layer.h b/common/layer.h new file mode 100644 index 0000000000..d9e8cebb8f --- /dev/null +++ b/common/layer.h @@ -0,0 +1,32 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef LAYER_H +#define LAYER_H 1 + +#include <stdint.h> + +extern uint8_t default_layer; +extern uint8_t current_layer; + +/* return keycode for switch */ +uint8_t layer_get_keycode(uint8_t row, uint8_t col); + +/* process layer switching */ +void layer_switching(uint8_t fn_bits); + +#endif diff --git a/common/led.h b/common/led.h new file mode 100644 index 0000000000..402a247b9a --- /dev/null +++ b/common/led.h @@ -0,0 +1,33 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef LED_H +#define LED_H +#include "stdint.h" + + +/* keyboard LEDs */ +#define USB_LED_NUM_LOCK 0 +#define USB_LED_CAPS_LOCK 1 +#define USB_LED_SCROLL_LOCK 2 +#define USB_LED_COMPOSE 3 +#define USB_LED_KANA 4 + + +void led_set(uint8_t usb_led); + +#endif diff --git a/common/matrix.h b/common/matrix.h new file mode 100644 index 0000000000..c4b2cab518 --- /dev/null +++ b/common/matrix.h @@ -0,0 +1,49 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef MATRIX_H +#define MATRIX_H + +#include <stdbool.h> + +/* number of matrix rows */ +uint8_t matrix_rows(void); +/* number of matrix columns */ +uint8_t matrix_cols(void); +/* intialize matrix for scaning. should be called once. */ +void matrix_init(void); +/* scan all key states on matrix */ +uint8_t matrix_scan(void); +/* whether modified from previous scan. used after matrix_scan. */ +bool matrix_is_modified(void); +/* whether ghosting occur on matrix. */ +bool matrix_has_ghost(void); +/* whether a swtich is on */ +bool matrix_is_on(uint8_t row, uint8_t col); +/* matrix state on row */ +#if (MATRIX_COLS <= 8) +uint8_t matrix_get_row(uint8_t row); +#else +uint16_t matrix_get_row(uint8_t row); +#endif +/* count keys pressed */ +uint8_t matrix_key_count(void); +/* print matrix for debug */ +void matrix_print(void); + + +#endif diff --git a/common/mousekey.c b/common/mousekey.c new file mode 100755 index 0000000000..76bd0fd363 --- /dev/null +++ b/common/mousekey.c @@ -0,0 +1,132 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <util/delay.h> +#include "usb_keycodes.h" +#include "host.h" +#include "timer.h" +#include "print.h" +#include "debug.h" +#include "mousekey.h" + + +static report_mouse_t report; +static report_mouse_t report_prev; + +static uint8_t mousekey_repeat = 0; + +static void mousekey_debug(void); + + +/* + * TODO: fix acceleration algorithm + * see wikipedia http://en.wikipedia.org/wiki/Mouse_keys + */ +#ifndef MOUSEKEY_DELAY_TIME +# define MOUSEKEY_DELAY_TIME 255 +#endif + +// acceleration parameters +uint8_t mousekey_move_unit = 2; +uint8_t mousekey_resolution = 5; + + +static inline uint8_t move_unit(void) +{ + uint16_t unit = 5 + mousekey_repeat*2; + return (unit > 63 ? 63 : unit); +} + +void mousekey_decode(uint8_t code) +{ + if (code == KB_MS_UP) report.y = -move_unit(); + else if (code == KB_MS_DOWN) report.y = move_unit(); + else if (code == KB_MS_LEFT) report.x = -move_unit(); + else if (code == KB_MS_RIGHT) report.x = move_unit(); + else if (code == KB_MS_BTN1) report.buttons |= MOUSE_BTN1; + else if (code == KB_MS_BTN2) report.buttons |= MOUSE_BTN2; + else if (code == KB_MS_BTN3) report.buttons |= MOUSE_BTN3; + else if (code == KB_MS_BTN4) report.buttons |= MOUSE_BTN4; + else if (code == KB_MS_BTN5) report.buttons |= MOUSE_BTN5; + else if (code == KB_MS_WH_UP) report.v += move_unit()/4; + else if (code == KB_MS_WH_DOWN) report.v -= move_unit()/4; + else if (code == KB_MS_WH_LEFT) report.h -= move_unit()/4; + else if (code == KB_MS_WH_RIGHT)report.h += move_unit()/4; +} + +bool mousekey_changed(void) +{ + return (report.buttons != report_prev.buttons || + report.x || report.y || report.v || report.h); +} + +void mousekey_send(void) +{ + static uint16_t last_timer = 0; + + if (!mousekey_changed()) { + mousekey_repeat = 0; + mousekey_clear_report(); + return; + } + + // send immediately when buttun state is changed + if (report.buttons == report_prev.buttons) { + if (timer_elapsed(last_timer) < 100) { + mousekey_clear_report(); + return; + } + } + + if (mousekey_repeat != 0xFF) { + mousekey_repeat++; + } + + if (report.x && report.y) { + report.x *= 0.7; + report.y *= 0.7; + } + + mousekey_debug(); + host_mouse_send(&report); + report_prev = report; + last_timer = timer_read(); + mousekey_clear_report(); +} + +void mousekey_clear_report(void) +{ + report.buttons = 0; + report.x = 0; + report.y = 0; + report.v = 0; + report.h = 0; +} + +static void mousekey_debug(void) +{ + if (!debug_mouse) return; + print("mousekey[btn|x y v h]: "); + phex(report.buttons); print("|"); + phex(report.x); print(" "); + phex(report.y); print(" "); + phex(report.v); print(" "); + phex(report.h); + phex(mousekey_repeat); + print("\n"); +} diff --git a/common/mousekey.h b/common/mousekey.h new file mode 100644 index 0000000000..c2c24e9fa5 --- /dev/null +++ b/common/mousekey.h @@ -0,0 +1,29 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef MOUSEKEY_H +#define MOUSEKEY_H + +#include <stdbool.h> +#include "host.h" + +void mousekey_decode(uint8_t code); +bool mousekey_changed(void); +void mousekey_send(void); +void mousekey_clear_report(void); + +#endif diff --git a/common/print.c b/common/print.c new file mode 100644 index 0000000000..558181ea72 --- /dev/null +++ b/common/print.c @@ -0,0 +1,93 @@ +/* Very basic print functions, intended to be used with usb_debug_only.c + * http://www.pjrc.com/teensy/ + * Copyright (c) 2008 PJRC.COM, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <avr/io.h> +#include <avr/pgmspace.h> +#include "print.h" +#include "sendchar.h" + + +bool print_enable = false; + +void print_S(const char *s) +{ + if (!print_enable) return; + char c; + + while (1) { + c = *s++; + if (!c) break; + if (c == '\n') sendchar('\r'); + sendchar(c); + } +} + +void print_P(const char *s) +{ + if (!print_enable) return; + char c; + + while (1) { + c = pgm_read_byte(s++); + if (!c) break; + if (c == '\n') sendchar('\r'); + sendchar(c); + } +} + +void phex1(unsigned char c) +{ + if (!print_enable) return; + sendchar(c + ((c < 10) ? '0' : 'A' - 10)); +} + +void phex(unsigned char c) +{ + if (!print_enable) return; + phex1(c >> 4); + phex1(c & 15); +} + +void phex16(unsigned int i) +{ + if (!print_enable) return; + phex(i >> 8); + phex(i); +} + + +void pbin(unsigned char c) +{ + if (!print_enable) return; + for (int i = 7; i >= 0; i--) { + sendchar((c & (1<<i)) ? '1' : '0'); + } +} + +void pbin_reverse(unsigned char c) +{ + if (!print_enable) return; + for (int i = 0; i < 8; i++) { + sendchar((c & (1<<i)) ? '1' : '0'); + } +} diff --git a/common/print.h b/common/print.h new file mode 100644 index 0000000000..686fa89acc --- /dev/null +++ b/common/print.h @@ -0,0 +1,45 @@ +/* Very basic print functions, intended to be used with usb_debug_only.c + * http://www.pjrc.com/teensy/ + * Copyright (c) 2008 PJRC.COM, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PRINT_H__ +#define PRINT_H__ 1 + +#include <stdint.h> +#include <stdbool.h> +#include <avr/pgmspace.h> + + +extern bool print_enable; + +// this macro allows you to write print("some text") and +// the string is automatically placed into flash memory :) +#define print(s) print_P(PSTR(s)) + +void print_S(const char *s); +void print_P(const char *s); +void phex(unsigned char c); +void phex16(unsigned int i); +void pbin(unsigned char c); +void pbin_reverse(unsigned char c); + +#endif diff --git a/common/report.h b/common/report.h new file mode 100644 index 0000000000..b85b86c5f8 --- /dev/null +++ b/common/report.h @@ -0,0 +1,96 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef REPORT_H +#define REPORT_H + +#include <stdint.h> + + +/* report id */ +#define REPORT_ID_MOUSE 1 +#define REPORT_ID_SYSTEM 2 +#define REPORT_ID_CONSUMER 3 + +/* mouse buttons */ +#define MOUSE_BTN1 (1<<0) +#define MOUSE_BTN2 (1<<1) +#define MOUSE_BTN3 (1<<2) +#define MOUSE_BTN4 (1<<3) +#define MOUSE_BTN5 (1<<4) + +// Consumer Page(0x0C) +// following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx +#define AUDIO_MUTE 0x00E2 +#define AUDIO_VOL_UP 0x00E9 +#define AUDIO_VOL_DOWN 0x00EA +#define TRANSPORT_NEXT_TRACK 0x00B5 +#define TRANSPORT_PREV_TRACK 0x00B6 +#define TRANSPORT_STOP 0x00B7 +#define TRANSPORT_PLAY_PAUSE 0x00CD +#define AL_CC_CONFIG 0x0183 +#define AL_EMAIL 0x018A +#define AL_CALCULATOR 0x0192 +#define AL_LOCAL_BROWSER 0x0194 +#define AC_SEARCH 0x0221 +#define AC_HOME 0x0223 +#define AC_BACK 0x0224 +#define AC_FORWARD 0x0225 +#define AC_STOP 0x0226 +#define AC_REFRESH 0x0227 +#define AC_BOOKMARKS 0x022A +// supplement for Bluegiga iWRAP HID(not supported by Windows?) +#define AL_LOCK 0x019E +#define TRANSPORT_RECORD 0x00B2 +#define TRANSPORT_REWIND 0x00B4 +#define TRANSPORT_EJECT 0x00B8 +#define AC_MINIMIZE 0x0206 + +// Generic Desktop Page(0x01) +#define SYSTEM_POWER_DOWN 0x0081 +#define SYSTEM_SLEEP 0x0082 +#define SYSTEM_WAKE_UP 0x0083 + + +// key report size(NKRO or boot mode) +#if defined(HOST_PJRC) +# include "usb.h" +# if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS +# define REPORT_KEYS KBD2_REPORT_KEYS +# else +# define REPORT_KEYS KBD_REPORT_KEYS +# endif +#else +# define REPORT_KEYS 6 +#endif + +typedef struct { + uint8_t mods; + uint8_t rserved; + uint8_t keys[REPORT_KEYS]; +} report_keyboard_t; + +typedef struct { + uint8_t report_id; + uint8_t buttons; + int8_t x; + int8_t y; + int8_t v; + int8_t h; +} report_mouse_t; + +#endif diff --git a/common/sendchar.h b/common/sendchar.h new file mode 100644 index 0000000000..7c81303c7a --- /dev/null +++ b/common/sendchar.h @@ -0,0 +1,27 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef SENDCHAR_H +#define SENDCHAR_H + +#include <stdint.h> + + +/* transmit a character. return 0 on success, -1 on error. */ +int8_t sendchar(uint8_t c); + +#endif diff --git a/common/sendchar_null.c b/common/sendchar_null.c new file mode 100644 index 0000000000..2933306228 --- /dev/null +++ b/common/sendchar_null.c @@ -0,0 +1,23 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#include "sendchar.h" + + +int8_t sendchar(uint8_t c) +{ + return 0; +} diff --git a/common/sendchar_uart.c b/common/sendchar_uart.c new file mode 100644 index 0000000000..0241859eb7 --- /dev/null +++ b/common/sendchar_uart.c @@ -0,0 +1,25 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#include "uart.h" +#include "sendchar.h" + + +int8_t sendchar(uint8_t c) +{ + uart_putchar(c); + return 0; +} diff --git a/common/timer.c b/common/timer.c new file mode 100644 index 0000000000..48a38c9b68 --- /dev/null +++ b/common/timer.c @@ -0,0 +1,89 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <avr/io.h> +#include <avr/interrupt.h> +#include <stdint.h> +#include "timer.h" + + +// counter resolution 1ms +volatile uint16_t timer_count = 0; + +void timer_init(void) +{ + // Timer0 CTC mode + TCCR0A = 0x02; + +#if TIMER_PRESCALER == 1 + TCCR0B = 0x01; +#elif TIMER_PRESCALER == 8 + TCCR0B = 0x02; +#elif TIMER_PRESCALER == 64 + TCCR0B = 0x03; +#elif TIMER_PRESCALER == 256 + TCCR0B = 0x04; +#elif TIMER_PRESCALER == 1024 + TCCR0B = 0x05; +#else +# error "Timer prescaler value is NOT vaild." +#endif + + OCR0A = TIMER_RAW_TOP; + TIMSK0 = (1<<OCIE0A); +} + +inline +void timer_clear(void) +{ + uint8_t sreg = SREG; + cli(); + timer_count = 0; + SREG = sreg; +} + +inline +uint16_t timer_read(void) +{ + uint16_t t; + + uint8_t sreg = SREG; + cli(); + t = timer_count; + SREG = sreg; + + return t; +} + +inline +uint16_t timer_elapsed(uint16_t last) +{ + uint16_t t; + + uint8_t sreg = SREG; + cli(); + t = timer_count; + SREG = sreg; + + return TIMER_DIFF_MS(t, last); +} + +// excecuted once per 1ms.(excess for just timer count?) +ISR(TIMER0_COMPA_vect) +{ + timer_count++; +} diff --git a/common/timer.h b/common/timer.h new file mode 100644 index 0000000000..f9e8181e6f --- /dev/null +++ b/common/timer.h @@ -0,0 +1,53 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef TIMER_H +#define TIMER_H 1 + +#include <stdint.h> + +#ifndef TIMER_PRESCALER +# if F_CPU > 16000000 +# define TIMER_PRESCALER 256 +# elif F_CPU >= 4000000 +# define TIMER_PRESCALER 64 +# else +# define TIMER_PRESCALER 8 +# endif +#endif +#define TIMER_RAW_FREQ (F_CPU/TIMER_PRESCALER) +#define TIMER_RAW TCNT0 +#define TIMER_RAW_TOP (TIMER_RAW_FREQ/1000) + +#if (TIMER_RAW_TOP > 255) +# error "Timer0 can't count 1ms at this clock freq. Use larger prescaler." +#endif + +#define TIMER_DIFF(a, b, max) ((a) >= (b) ? (a) - (b) : (max) - (b) + (a)) +#define TIMER_DIFF_RAW(a, b) TIMER_DIFF(a, b, UINT8_MAX) +#define TIMER_DIFF_MS(a, b) TIMER_DIFF(a, b, UINT16_MAX) + + +extern volatile uint16_t timer_count; + + +void timer_init(void); +void timer_clear(void); +uint16_t timer_read(void); +uint16_t timer_elapsed(uint16_t last); + +#endif diff --git a/common/uart.c b/common/uart.c new file mode 100644 index 0000000000..c17649b082 --- /dev/null +++ b/common/uart.c @@ -0,0 +1,129 @@ +// TODO: Teensy support(ATMega32u4/AT90USB128) +// Fixed for Arduino Duemilanove ATmega168p by Jun Wako +/* UART Example for Teensy USB Development Board + * http://www.pjrc.com/teensy/ + * Copyright (c) 2009 PJRC.COM, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Version 1.0: Initial Release +// Version 1.1: Add support for Teensy 2.0, minor optimizations + + +#include <avr/io.h> +#include <avr/interrupt.h> + +#include "uart.h" + +// These buffers may be any size from 2 to 256 bytes. +#define RX_BUFFER_SIZE 64 +#define TX_BUFFER_SIZE 40 + +static volatile uint8_t tx_buffer[TX_BUFFER_SIZE]; +static volatile uint8_t tx_buffer_head; +static volatile uint8_t tx_buffer_tail; +static volatile uint8_t rx_buffer[RX_BUFFER_SIZE]; +static volatile uint8_t rx_buffer_head; +static volatile uint8_t rx_buffer_tail; + +// Initialize the UART +void uart_init(uint32_t baud) +{ + cli(); + UBRR0 = (F_CPU / 4 / baud - 1) / 2; + UCSR0A = (1<<U2X0); + UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0); + UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); + tx_buffer_head = tx_buffer_tail = 0; + rx_buffer_head = rx_buffer_tail = 0; + sei(); +} + +// Transmit a byte +void uart_putchar(uint8_t c) +{ + uint8_t i; + + i = tx_buffer_head + 1; + if (i >= TX_BUFFER_SIZE) i = 0; + while (tx_buffer_tail == i) ; // wait until space in buffer + //cli(); + tx_buffer[i] = c; + tx_buffer_head = i; + UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (1<<UDRIE0); + //sei(); +} + +// Receive a byte +uint8_t uart_getchar(void) +{ + uint8_t c, i; + + while (rx_buffer_head == rx_buffer_tail) ; // wait for character + i = rx_buffer_tail + 1; + if (i >= RX_BUFFER_SIZE) i = 0; + c = rx_buffer[i]; + rx_buffer_tail = i; + return c; +} + +// Return the number of bytes waiting in the receive buffer. +// Call this before uart_getchar() to check if it will need +// to wait for a byte to arrive. +uint8_t uart_available(void) +{ + uint8_t head, tail; + + head = rx_buffer_head; + tail = rx_buffer_tail; + if (head >= tail) return head - tail; + return RX_BUFFER_SIZE + head - tail; +} + +// Transmit Interrupt +ISR(USART_UDRE_vect) +{ + uint8_t i; + + if (tx_buffer_head == tx_buffer_tail) { + // buffer is empty, disable transmit interrupt + UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0); + } else { + i = tx_buffer_tail + 1; + if (i >= TX_BUFFER_SIZE) i = 0; + UDR0 = tx_buffer[i]; + tx_buffer_tail = i; + } +} + +// Receive Interrupt +ISR(USART_RX_vect) +{ + uint8_t c, i; + + c = UDR0; + i = rx_buffer_head + 1; + if (i >= RX_BUFFER_SIZE) i = 0; + if (i != rx_buffer_tail) { + rx_buffer[i] = c; + rx_buffer_head = i; + } +} + diff --git a/common/uart.h b/common/uart.h new file mode 100644 index 0000000000..41136a396f --- /dev/null +++ b/common/uart.h @@ -0,0 +1,11 @@ +#ifndef _uart_included_h_ +#define _uart_included_h_ + +#include <stdint.h> + +void uart_init(uint32_t baud); +void uart_putchar(uint8_t c); +uint8_t uart_getchar(void); +uint8_t uart_available(void); + +#endif diff --git a/common/usb_keycodes.h b/common/usb_keycodes.h new file mode 100644 index 0000000000..9b6cce1532 --- /dev/null +++ b/common/usb_keycodes.h @@ -0,0 +1,423 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + * Key codes: HID Keyboard/Keypad Page(0x07) + * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf + */ +#ifndef USB_KEYCODES_H +#define USB_KEYCODES_H + + +#define IS_ERROR(code) (KB_ROLL_OVER <= (code) && (code) <= KB_UNDEFINED) +#define IS_KEY(code) (KB_A <= (code) && (code) <= KB_EXSEL) +#define IS_MOD(code) (KB_LCTRL <= (code) && (code) <= KB_RGUI) +#define IS_FN(code) (KB_FN0 <= (code) && (code) <= KB_FN7) +#define IS_MOUSEKEY(code) (KB_MS_UP <= (code) && (code) <= KB_MS_WH_RIGHT) +#define IS_MOUSEKEY_MOVE(code) (KB_MS_UP <= (code) && (code) <= KB_MS_RIGHT) +#define IS_MOUSEKEY_BUTTON(code) (KB_MS_BTN1 <= (code) && (code) <= KB_MS_BTN5) +#define IS_MOUSEKEY_WHEEL(code) (KB_MS_WH_UP <= (code) && (code) <= KB_MS_WH_RIGHT) + +#define MOD_BIT(code) (1<<((code) & 0x07)) +#define FN_BIT(code) (1<<((code) - KB_FN0)) + + +/* Short names */ +#define KB_LCTL KB_LCTRL +#define KB_RCTL KB_RCTRL +#define KB_LSFT KB_LSHIFT +#define KB_RSFT KB_RSHIFT +#define KB_ESC KB_ESCAPE +#define KB_BSPC KB_BSPACE +#define KB_ENT KB_ENTER +#define KB_DEL KB_DELETE +#define KB_INS KB_INSERT +#define KB_CAPS KB_CAPSLOCK +#define KB_RGHT KB_RIGHT +#define KB_PGDN KB_PGDOWN +#define KB_PSCR KB_PSCREEN +#define KB_SLCK KB_SCKLOCK +#define KB_PAUS KB_PAUSE +#define KB_BRK KB_PAUSE +#define KB_NLCK KB_NUMLOCK +#define KB_SPC KB_SPACE +#define KB_MINS KB_MINUS +#define KB_EQL KB_EQUAL +#define KB_GRV KB_GRAVE +#define KB_RBRC KB_RBRACKET +#define KB_LBRC KB_LBRACKET +#define KB_COMM KB_COMMA +#define KB_BSLS KB_BSLASH +#define KB_SLSH KB_SLASH +#define KB_SCLN KB_SCOLON +#define KB_QUOT KB_QUOTE +#define KB_APP KB_APPLICATION +#define KB_NUHS KB_NONUS_HASH +#define KB_NUBS KB_NONUS_BSLASH +#define KB_ERAS KB_ALT_ERASE, +#define KB_CLR KB_CLEAR +/* for Japanese */ +#define KB_ZKHK KB_GRAVE +#define KB_RO KB_INT1 +#define KB_KANA KB_INT2 +#define KB_JYEN KB_INT3 +#define KB_HENK KB_INT4 +#define KB_MHEN KB_INT5 +/* Keypad */ +#define KB_P1 KB_KP_1 +#define KB_P2 KB_KP_2 +#define KB_P3 KB_KP_3 +#define KB_P4 KB_KP_4 +#define KB_P5 KB_KP_5 +#define KB_P6 KB_KP_6 +#define KB_P7 KB_KP_7 +#define KB_P8 KB_KP_8 +#define KB_P9 KB_KP_9 +#define KB_P0 KB_KP_0 +#define KB_PDOT KB_KP_DOT +#define KB_PCMM KB_KP_COMMA +#define KB_PSLS KB_KP_SLASH +#define KB_PAST KB_KP_ASTERISK +#define KB_PMNS KB_KP_MINUS +#define KB_PPLS KB_KP_PLUS +#define KB_PEQL KB_KP_EQUAL +#define KB_PENT KB_KP_ENTER +/* Mousekey */ +#define KB_MS_U KB_MS_UP +#define KB_MS_D KB_MS_DOWN +#define KB_MS_L KB_MS_LEFT +#define KB_MS_R KB_MS_RIGHT +#define KB_BTN1 KB_MS_BTN1 +#define KB_BTN2 KB_MS_BTN2 +#define KB_BTN3 KB_MS_BTN3 +#define KB_BTN4 KB_MS_BTN4 +#define KB_BTN5 KB_MS_BTN5 +#define KB_WH_U KB_MS_WH_UP +#define KB_WH_D KB_MS_WH_DOWN +#define KB_WH_L KB_MS_WH_LEFT +#define KB_WH_R KB_MS_WH_RIGHT +/* Sytem Control & Consumer usage */ +#define KB_PWR KB_SYSTEM_POWER +#define KB_SLEP KB_SYSTEM_SLEEP +#define KB_WAKE KB_SYSTEM_WAKE +#define KB_MUTE KB_AUDIO_MUTE +#define KB_VOLU KB_AUDIO_VOL_UP +#define KB_VOLD KB_AUDIO_VOL_DOWN +#define KB_MNXT KB_MEDIA_NEXT_TRACK +#define KB_MPRV KB_MEDIA_PREV_TRACK +#define KB_MSTP KB_MEDIA_STOP +#define KB_MPLY KB_MEDIA_PLAY_PAUSE +#define KB_MSEL KB_MEDIA_SELECT +#define KB_MAIL KB_MAIL +#define KB_CALC KB_CALCULATOR +#define KB_MYCM KB_MY_COMPUTER +#define KB_WSCH KB_WWW_SEARCH +#define KB_WHOM KB_WWW_HOME +#define KB_WBAK KB_WWW_BACK +#define KB_WFWD KB_WWW_FORWARD +#define KB_WSTP KB_WWW_STOP +#define KB_WREF KB_WWW_REFRESH +#define KB_WFAV KB_WWW_FAVORITES + + +/* Special keycode */ +enum special_keycodes { + /* System Control */ + KB_SYSTEM_POWER = 0xB0, + KB_SYSTEM_SLEEP, + KB_SYSTEM_WAKE, + + /* Consumer Page */ + KB_AUDIO_MUTE, + KB_AUDIO_VOL_UP, + KB_AUDIO_VOL_DOWN, + KB_MEDIA_NEXT_TRACK, + KB_MEDIA_PREV_TRACK, + KB_MEDIA_STOP, + KB_MEDIA_PLAY_PAUSE, + KB_MEDIA_SELECT, + KB_MAIL, + KB_CALCULATOR, + KB_MY_COMPUTER, + KB_WWW_SEARCH, + KB_WWW_HOME, + KB_WWW_BACK, /* 0xC0 */ + KB_WWW_FORWARD, + KB_WWW_STOP, + KB_WWW_REFRESH, + KB_WWW_FAVORITES, + + /* reserve 0xE0-E7 for Modifiers */ + + /* Layer Switching */ + KB_FN0 = 0xE8, + KB_FN1, + KB_FN2, + KB_FN3, + KB_FN4, + KB_FN5, + KB_FN6, + KB_FN7, + + /* Mousekey */ + KB_MS_UP = 0xF0, + KB_MS_DOWN, + KB_MS_LEFT, + KB_MS_RIGHT, + KB_MS_BTN1, + KB_MS_BTN2, + KB_MS_BTN3, + KB_MS_BTN4, + KB_MS_BTN5, + /* Mousekey wheel */ + KB_MS_WH_UP, + KB_MS_WH_DOWN, + KB_MS_WH_LEFT, + KB_MS_WH_RIGHT, +}; + +enum keycodes { + KB_NO = 0, + KB_ROLL_OVER, + KB_POST_FAIL, + KB_UNDEFINED, + KB_A, + KB_B, + KB_C, + KB_D, + KB_E, + KB_F, + KB_G, + KB_H, + KB_I, + KB_J, + KB_K, + KB_L, + KB_M, /* 0x10 */ + KB_N, + KB_O, + KB_P, + KB_Q, + KB_R, + KB_S, + KB_T, + KB_U, + KB_V, + KB_W, + KB_X, + KB_Y, + KB_Z, + KB_1, + KB_2, + KB_3, /* 0x20 */ + KB_4, + KB_5, + KB_6, + KB_7, + KB_8, + KB_9, + KB_0, + KB_ENTER, + KB_ESCAPE, + KB_BSPACE, + KB_TAB, + KB_SPACE, + KB_MINUS, + KB_EQUAL, + KB_LBRACKET, + KB_RBRACKET, /* 0x30 */ + KB_BSLASH, /* \ (and |) */ + KB_NONUS_HASH, /* Non-US # and ~ */ + KB_SCOLON, /* ; (and :) */ + KB_QUOTE, /* ' and " */ + KB_GRAVE, /* Grave accent and tilde */ + KB_COMMA, /* , and < */ + KB_DOT, /* . and > */ + KB_SLASH, /* / and ? */ + KB_CAPSLOCK, + KB_F1, + KB_F2, + KB_F3, + KB_F4, + KB_F5, + KB_F6, + KB_F7, /* 0x40 */ + KB_F8, + KB_F9, + KB_F10, + KB_F11, + KB_F12, + KB_PSCREEN, + KB_SCKLOCK, + KB_PAUSE, + KB_INSERT, + KB_HOME, + KB_PGUP, + KB_DELETE, + KB_END, + KB_PGDOWN, + KB_RIGHT, + KB_LEFT, /* 0x50 */ + KB_DOWN, + KB_UP, + KB_NUMLOCK, + KB_KP_SLASH, + KB_KP_ASTERISK, + KB_KP_MINUS, + KB_KP_PLUS, + KB_KP_ENTER, + KB_KP_1, + KB_KP_2, + KB_KP_3, + KB_KP_4, + KB_KP_5, + KB_KP_6, + KB_KP_7, + KB_KP_8, /* 0x60 */ + KB_KP_9, + KB_KP_0, + KB_KP_DOT, + KB_NONUS_BSLASH, /* Non-US \ and | */ + KB_APPLICATION, + KB_POWER, + KB_KP_EQUAL, + KB_F13, + KB_F14, + KB_F15, + KB_F16, + KB_F17, + KB_F18, + KB_F19, + KB_F20, + KB_F21, /* 0x70 */ + KB_F22, + KB_F23, + KB_F24, + KB_EXECUTE, + KB_HELP, + KB_MENU, + KB_SELECT, + KB_STOP, + KB_AGAIN, + KB_UNDO, + KB_CUT, + KB_COPY, + KB_PASTE, + KB_FIND, + KB__MUTE, + KB__VOLUP, /* 0x80 */ + KB__VOLDOWN, + KB_LOCKING_CAPS, /* locking Caps Lock */ + KB_LOCKING_NUM, /* locking Num Lock */ + KB_LOCKING_SCROLL, /* locking Scroll Lock */ + KB_KP_COMMA, + KB_KP_EQUAL_AS400, /* equal sign on AS/400 */ + KB_INT1, + KB_INT2, + KB_INT3, + KB_INT4, + KB_INT5, + KB_INT6, + KB_INT7, + KB_INT8, + KB_INT9, + KB_LANG1, /* 0x90 */ + KB_LANG2, + KB_LANG3, + KB_LANG4, + KB_LANG5, + KB_LANG6, + KB_LANG7, + KB_LANG8, + KB_LANG9, + KB_ALT_ERASE, + KB_SYSREQ, + KB_CANCEL, + KB_CLEAR, + KB_PRIOR, + KB_RETURN, + KB_SEPARATOR, + KB_OUT, /* 0xA0 */ + KB_OPER, + KB_CLEAR_AGAIN, + KB_CRSEL, + KB_EXSEL, + + /* NOTE: 0xB0-DF are used as special_keycodes */ +#if 0 + KB_KP_00 = 0xB0, + KB_KP_000, + KB_THOUSANDS_SEPARATOR, + KB_DECIMAL_SEPARATOR, + KB_CURRENCY_UNIT, + KB_CURRENCY_SUB_UNIT, + KB_KP_LPAREN, + KB_KP_RPAREN, + KB_KP_LCBRACKET, /* { */ + KB_KP_RCBRACKET, /* } */ + KB_KP_TAB, + KB_KP_BSPACE, + KB_KP_A, + KB_KP_B, + KB_KP_C, + KB_KP_D, + KB_KP_E, /* 0xC0 */ + KB_KP_F, + KB_KP_XOR, + KB_KP_HAT, + KB_KP_PERC, + KB_KP_LT, + KB_KP_GT, + KB_KP_AND, + KB_KP_LAZYAND, + KB_KP_OR, + KB_KP_LAZYOR, + KB_KP_COLON, + KB_KP_HASH, + KB_KP_SPACE, + KB_KP_ATMARK, + KB_KP_EXCLAMATION, + KB_KP_MEM_STORE, /* 0xD0 */ + KB_KP_MEM_RECALL, + KB_KP_MEM_CLEAR, + KB_KP_MEM_ADD, + KB_KP_MEM_SUB, + KB_KP_MEM_MUL, + KB_KP_MEM_DIV, + KB_KP_PLUS_MINUS, + KB_KP_CLEAR, + KB_KP_CLEAR_ENTRY, + KB_KP_BINARY, + KB_KP_OCTAL, + KB_KP_DECIMAL, + KB_KP_HEXADECIMAL, +#endif + + /* Modifiers */ + KB_LCTRL = 0xE0, + KB_LSHIFT, + KB_LALT, + KB_LGUI, + KB_RCTRL, + KB_RSHIFT, + KB_RALT, + KB_RGUI, + + /* NOTE: 0xE8-FF are used as special_keycodes */ +}; + +#endif /* USB_KEYCODES_H */ diff --git a/common/util.c b/common/util.c new file mode 100644 index 0000000000..36afdd4470 --- /dev/null +++ b/common/util.c @@ -0,0 +1,37 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "util.h" + +// bit population +int bitpop(uint8_t bits) +{ + int c; + for (c = 0; bits; c++) + bits &= bits -1; + return c; +} + +// most significant on-bit +int biton(uint8_t bits) +{ + int n = 0; + if (bits >> 4) { bits >>= 4; n += 4;} + if (bits >> 2) { bits >>= 2; n += 2;} + if (bits >> 1) { bits >>= 1; n += 1;} + return n; +} diff --git a/common/util.h b/common/util.h new file mode 100644 index 0000000000..66bccbfa58 --- /dev/null +++ b/common/util.h @@ -0,0 +1,34 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef UTIL_H +#define UTIL_H 1 + +#include <stdint.h> + +// convert to L string +#define LSTR(s) XLSTR(s) +#define XLSTR(s) L ## #s +// convert to string +#define STR(s) XSTR(s) +#define XSTR(s) #s + + +int bitpop(uint8_t bits); +int biton(uint8_t bits); + +#endif |