diff options
-rw-r--r-- | Makefile.vusb | 11 | ||||
-rw-r--r-- | POWER.txt | 62 | ||||
-rw-r--r-- | README | 4 | ||||
-rw-r--r-- | adb_usb/Makefile | 20 | ||||
-rw-r--r-- | adb_usb/README | 8 | ||||
-rw-r--r-- | adb_usb/config.h | 4 | ||||
-rw-r--r-- | command.c | 56 | ||||
-rw-r--r-- | command.h | 2 | ||||
-rw-r--r-- | common.mk (renamed from Makefile.common) | 15 | ||||
-rw-r--r-- | hhkb/FUSE.txt | 40 | ||||
-rw-r--r-- | hhkb/Makefile.iwrap | 91 | ||||
-rw-r--r-- | hhkb/Makefile.pjrc (renamed from hhkb/Makefile) | 19 | ||||
-rw-r--r-- | hhkb/Makefile.vusb | 29 | ||||
-rw-r--r-- | hhkb/README | 113 | ||||
-rw-r--r-- | hhkb/config_iwrap.h | 55 | ||||
-rw-r--r-- | hhkb/config_pjrc.h | 6 | ||||
-rw-r--r-- | hhkb/config_vusb.h | 12 | ||||
-rw-r--r-- | hhkb/doc/Bluetooth.txt | 4 | ||||
-rwxr-xr-x | hhkb/doc/Bluetooth_img/.picasa.ini | 2 | ||||
-rwxr-xr-x | hhkb/doc/Bluetooth_img/BT_circuit.jpg | bin | 0 -> 502118 bytes | |||
-rw-r--r-- | hhkb/doc/HHKB_img/HHKB_TP1684.jpg (renamed from hhkb/doc/HHKB_TP1684.jpg) | bin | 149082 -> 149082 bytes | |||
-rw-r--r-- | hhkb/doc/HHKB_img/HHKB_chart1.jpg (renamed from hhkb/doc/HHKB_chart1.jpg) | bin | 155342 -> 155342 bytes | |||
-rw-r--r-- | hhkb/doc/HHKB_img/HHKB_chart2.jpg (renamed from hhkb/doc/HHKB_chart2.jpg) | bin | 148225 -> 148225 bytes | |||
-rw-r--r-- | hhkb/doc/HHKB_img/HHKB_connector.jpg (renamed from hhkb/doc/HHKB_connector.jpg) | bin | 193900 -> 193900 bytes | |||
-rw-r--r-- | hhkb/doc/HHKB_img/HHKB_controller.jpg (renamed from hhkb/doc/HHKB_controller.jpg) | bin | 135100 -> 135100 bytes | |||
-rw-r--r-- | hhkb/doc/HHKB_img/HHKB_keyswitch.jpg (renamed from hhkb/doc/HHKB_keyswitch.jpg) | bin | 171469 -> 171469 bytes | |||
-rw-r--r-- | hhkb/doc/HHKB_img/connector_contact.jpg (renamed from hhkb/doc/connector_contact.jpg) | bin | 192830 -> 192830 bytes | |||
-rw-r--r-- | hhkb/doc/HHKB_img/logic_analyzer.jpg (renamed from hhkb/doc/logic_analyzer.jpg) | bin | 169564 -> 169564 bytes | |||
-rw-r--r-- | hhkb/doc/HHKB_img/probe_contact.jpg (renamed from hhkb/doc/probe_contact.jpg) | bin | 208477 -> 208477 bytes | |||
-rw-r--r-- | hhkb/doc/HHKB_img/teensy_install.jpg (renamed from hhkb/doc/teensy_install.jpg) | bin | 135851 -> 135851 bytes | |||
-rw-r--r-- | hhkb/doc/HHKB_img/teensy_wiring.jpg (renamed from hhkb/doc/teensy_wiring.jpg) | bin | 154695 -> 154695 bytes | |||
-rw-r--r-- | hhkb/keymap.c | 115 | ||||
-rw-r--r-- | hhkb/matrix.c | 66 | ||||
-rw-r--r-- | hhkb/usbconfig.h | 16 | ||||
-rw-r--r-- | host.c | 190 | ||||
-rw-r--r-- | host.h | 89 | ||||
-rw-r--r-- | host_driver.h | 33 | ||||
-rw-r--r-- | iwrap.mk | 10 | ||||
-rw-r--r-- | iwrap/iWRAP.txt | 376 | ||||
-rw-r--r-- | iwrap/iwrap.c | 467 | ||||
-rw-r--r-- | iwrap/iwrap.h | 49 | ||||
-rw-r--r-- | iwrap/main.c | 378 | ||||
-rw-r--r-- | iwrap/suart.S | 156 | ||||
-rw-r--r-- | iwrap/suart.h | 8 | ||||
-rw-r--r-- | iwrap/wd.h | 159 | ||||
-rw-r--r-- | keyboard.c | 9 | ||||
-rwxr-xr-x | layer.c | 4 | ||||
-rw-r--r-- | macway/Makefile | 16 | ||||
-rw-r--r-- | macway/config.h | 4 | ||||
-rw-r--r--[-rwxr-xr-x] | macway/doc/back.jpg | bin | 122135 -> 122135 bytes | |||
-rw-r--r--[-rwxr-xr-x] | macway/doc/case.jpg | bin | 146003 -> 146003 bytes | |||
-rw-r--r--[-rwxr-xr-x] | macway/doc/keys.jpg | bin | 116365 -> 116365 bytes | |||
-rw-r--r--[-rwxr-xr-x] | macway/doc/side.jpg | bin | 109755 -> 109755 bytes | |||
-rw-r--r--[-rwxr-xr-x] | macway/doc/switch.jpg | bin | 115526 -> 115526 bytes | |||
-rw-r--r--[-rwxr-xr-x] | macway/doc/teensy.jpg | bin | 165814 -> 165814 bytes | |||
-rw-r--r--[-rwxr-xr-x] | macway/doc/wiring.jpg | bin | 165569 -> 165569 bytes | |||
-rw-r--r--[-rwxr-xr-x] | macway/doc/withHHKB.jpg | bin | 152832 -> 152832 bytes | |||
-rw-r--r--[-rwxr-xr-x] | macway/doc/withThinkPad.jpg | bin | 118993 -> 118993 bytes | |||
-rw-r--r-- | main_vusb.c | 58 | ||||
-rwxr-xr-x[-rw-r--r--] | mousekey.c | 10 | ||||
-rw-r--r-- | pjrc.mk (renamed from Makefile.pjrc) | 10 | ||||
-rw-r--r-- | pjrc/host.c | 10 | ||||
-rw-r--r-- | pjrc/main.c (renamed from main_pjrc.c) | 3 | ||||
-rw-r--r-- | pjrc/pjrc.c | 76 | ||||
-rw-r--r-- | pjrc/pjrc.h | 26 | ||||
-rw-r--r-- | pjrc/usb.c | 34 | ||||
-rw-r--r-- | pjrc/usb.h | 2 | ||||
-rw-r--r-- | pjrc/usb_keyboard.c | 4 | ||||
-rw-r--r-- | print.c | 13 | ||||
-rw-r--r-- | print.h | 2 | ||||
-rw-r--r-- | ps2_usb/Makefile | 18 | ||||
-rw-r--r-- | ps2_usb/Makefile.vusb | 19 | ||||
-rw-r--r-- | ps2_usb/config_pjrc.h | 4 | ||||
-rw-r--r-- | ps2_usb/config_vusb.h | 4 | ||||
-rw-r--r-- | ps2_usb/keymap.c | 6 | ||||
-rw-r--r-- | ps2_usb/matrix.c | 1 | ||||
-rw-r--r-- | report.h | 96 | ||||
-rw-r--r-- | rules.mk (renamed from Makefile.rules) | 0 | ||||
-rw-r--r-- | sendchar.h | 4 | ||||
-rw-r--r-- | sendchar_null.c (renamed from vusb/host_vusb.h) | 10 | ||||
-rw-r--r-- | sendchar_uart.c | 25 | ||||
-rw-r--r-- | timer.c | 35 | ||||
-rw-r--r-- | timer.h | 21 | ||||
-rw-r--r-- | uart.c | 129 | ||||
-rw-r--r-- | uart.h | 11 | ||||
-rw-r--r-- | usb_keycodes.h | 8 | ||||
-rw-r--r-- | vusb.mk | 17 | ||||
-rw-r--r-- | vusb/main.c | 99 | ||||
-rw-r--r-- | vusb/vusb.c (renamed from vusb/host.c) | 207 | ||||
-rw-r--r-- | vusb/vusb.h | 27 |
90 files changed, 3150 insertions, 537 deletions
diff --git a/Makefile.vusb b/Makefile.vusb deleted file mode 100644 index b8e71a8e3..000000000 --- a/Makefile.vusb +++ /dev/null @@ -1,11 +0,0 @@ -OPT_DEFS += -DHOST_VUSB - -SRC = usbdrv.c \ - usbdrvasm.S \ - oddebug.c \ - sendchar_usart.c -SRC += $(TARGET_SRC) - - -# C source file search path -VPATH = $(TARGET_DIR):$(COMMON_DIR):$(COMMON_DIR)/vusb:$(COMMON_DIR)/vusb/usbdrv diff --git a/POWER.txt b/POWER.txt new file mode 100644 index 000000000..0abbbe48e --- /dev/null +++ b/POWER.txt @@ -0,0 +1,62 @@ +Time to Sleep +============= +USB suspend no activity on USB line for 3ms +No Interaction no user interaction + matrix has no change + matrix has no switch on + + +AVR Power Management +==================== + +V-USB suspend + USB suspend + http://vusb.wikidot.com/examples + +MCUSR MCU Status Register + WDRF Watchdog Reset Flag + BORF + EXTRF + PORF Power-on Reset Flag + +SMCR Sleep Mode Control Register + SE Sleep Enable + SM2:0 + #define set_sleep_mode(mode) \ + #define SLEEP_MODE_IDLE (0) + #define SLEEP_MODE_ADC _BV(SM0) + #define SLEEP_MODE_PWR_DOWN _BV(SM1) + #define SLEEP_MODE_PWR_SAVE (_BV(SM0) | _BV(SM1)) + #define SLEEP_MODE_STANDBY (_BV(SM1) | _BV(SM2)) + #define SLEEP_MODE_EXT_STANDBY (_BV(SM0) | _BV(SM1) | _BV(SM2)) + + +ACSR Analog Comparator Control and Status Register + To disable Analog Comparator + ACSR = 0x80; + or + ACSR &= ~_BV(ACIE); + ACSR |= _BV(ACD); + + ACD: Analog Comparator Disable + When this bit is written logic one, the power to the Analog Comparator is + switched off. This bit can be set at any time to turn off the Analog + Comparator. This will reduce power consumption in Active and Idle mode. + When changing the ACD bit, the Analog Comparator Interrupt must be disabled + by clearing the ACIE bit in ACSR. Otherwise an interrupt can occur when + the bit is changed. + +DIDR1 Digital Input Disable Register 1 + AIN1D + AIN0D + When this bit is written logic one, the digital input buffer on the AIN1/0 pin is disabled. The corresponding PIN Register bit will always read as zero when this bit is set. When an analog signal is applied to the AIN1/0 pin and the digital input from this pin is not needed, this bit should be written logic one to reduce power consumption in the digital input buffer. + + +PRR Power Reduction Register + PRTWI + PRTIM2 + PRTIM0 + PRTIM1 + PRSPI + PRUSART0 + PRADC @@ -96,8 +96,8 @@ Build Options 3. Choose optional modules as needed. Comment out to disable optional modules. MOUSEKEY_ENABLE = yes # Mouse keys PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support - USB_EXTRA_ENABLE = yes # Enhanced feature for Windows(Audio control and System control) - USB_NKRO_ENABLE = yes # USB Nkey Rollover + EXTRAKEY_ENABLE = yes # Enhanced feature for Windows(Audio control and System control) + NKRO_ENABLE = yes # USB Nkey Rollover <target>/config.h: 1. USB vendor/product ID and device description diff --git a/adb_usb/Makefile b/adb_usb/Makefile index 802b4248c..56b342df9 100644 --- a/adb_usb/Makefile +++ b/adb_usb/Makefile @@ -8,11 +8,11 @@ COMMON_DIR = .. TARGET_DIR = . # keyboard dependent files -TARGET_SRC = main_pjrc.c \ - keymap.c \ - matrix.c \ - led.c \ - adb.c +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c \ + adb.c CONFIG_H = config.h @@ -36,10 +36,10 @@ F_CPU = 16000000 # Build Options # comment out to disable the options. # -MOUSEKEY_ENABLE = yes # Mouse keys +#MOUSEKEY_ENABLE = yes # Mouse keys #PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support -USB_EXTRA_ENABLE = yes # Audio control and System control -#USB_NKRO_ENABLE = yes # USB Nkey Rollover +#EXTRAKEY_ENABLE = yes # Audio control and System control +#NKRO_ENABLE = yes # USB Nkey Rollover @@ -48,5 +48,5 @@ PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex -include $(COMMON_DIR)/Makefile.pjrc -include $(COMMON_DIR)/Makefile.common +include $(COMMON_DIR)/pjrc.mk +include $(COMMON_DIR)/common.mk diff --git a/adb_usb/README b/adb_usb/README index b4bd35bb3..5d0e1bc86 100644 --- a/adb_usb/README +++ b/adb_usb/README @@ -59,4 +59,12 @@ effort at this time. ), +Notes +----- +Many ADB keyboards has no discrimination between right modifier and left one, +you will always see left control even if you press right control key. +Apple Extended Keyboard and Apple Extended Keyboard II are the examples. +Though ADB protocol itsef has the ability of distinction between right and left. +And most ADB keyboard has no NKRO functionality, though ADB protocol itsef has that. + EOF diff --git a/adb_usb/config.h b/adb_usb/config.h index 27f31ca9e..6431ede4c 100644 --- a/adb_usb/config.h +++ b/adb_usb/config.h @@ -37,8 +37,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. /* key combination for command */ #define IS_COMMAND() ( \ - keyboard_report->mods == (BIT_LSHIFT | BIT_LCTRL | BIT_LALT | BIT_LGUI) || \ - keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_LCTRL) | MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) || \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) \ ) @@ -30,24 +30,49 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef HOST_PJRC # include "jump_bootloader.h" # include "usb_keyboard.h" -# ifdef USB_EXTRA_ENABLE +# 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; - uint8_t processed = 1; - bool last_print_enable = print_enable; 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(); @@ -123,20 +148,26 @@ uint8_t command_proc(void) 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 USB_NKRO_ENABLE +#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("USB_NKRO: enabled\n"); + print("NKRO: enabled\n"); else - print("USB_NKRO: disabled\n"); + print("NKRO: disabled\n"); break; #endif -#ifdef USB_EXTRA_ENABLE +#ifdef EXTRAKEY_ENABLE case KB_ESC: host_clear_keyboard_report(); host_send_keyboard_report(); @@ -175,12 +206,9 @@ uint8_t command_proc(void) switch_layer(4); break; default: - processed = 0; + return 0; } - if (processed) - _delay_ms(500); - print_enable = last_print_enable; - return processed; + return 1; } static void help(void) @@ -194,8 +222,8 @@ static void help(void) print("v: print version\n"); print("t: print timer count\n"); print("s: print status\n"); -#ifdef USB_NKRO_ENABLE - print("n: toggle USB_NKRO\n"); +#ifdef NKRO_ENABLE + print("n: toggle NKRO\n"); #endif print("Backspace: clear matrix\n"); print("ESC: power down/wake up\n"); @@ -19,5 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #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/Makefile.common b/common.mk index 1922def00..17c6816f6 100644 --- a/Makefile.common +++ b/common.mk @@ -19,17 +19,20 @@ ifdef PS2_MOUSE_ENABLE OPT_DEFS += -DPS2_MOUSE_ENABLE endif -ifdef USB_EXTRA_ENABLE - OPT_DEFS += -DUSB_EXTRA_ENABLE +ifdef EXTRAKEY_ENABLE + OPT_DEFS += -DEXTRAKEY_ENABLE endif -ifdef USB_NKRO_ENABLE - OPT_DEFS += -DUSB_NKRO_ENABLE +ifdef NKRO_ENABLE + OPT_DEFS += -DNKRO_ENABLE endif ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) - OPT_DEFS += -DUSB_MOUSE_ENABLE + OPT_DEFS += -DMOUSE_ENABLE endif +# Search Path +VPATH += $(COMMON_DIR) -include $(COMMON_DIR)/Makefile.rules + +include $(COMMON_DIR)/rules.mk diff --git a/hhkb/FUSE.txt b/hhkb/FUSE.txt new file mode 100644 index 000000000..40055e5ab --- /dev/null +++ b/hhkb/FUSE.txt @@ -0,0 +1,40 @@ +ATMega168P Fuse/Lock Bits +========================= +This configuration is from usbasploader's Makefile. + + HFUSE 0xD6 + LFUSE 0xDF + EFUSE 0x00 + LOCK 0x3F(intact) + +#--------------------------------------------------------------------- +# ATMega168P +#--------------------------------------------------------------------- +# Fuse extended byte: +# 0x00 = 0 0 0 0 0 0 0 0 <-- BOOTRST (boot reset vector at 0x1800) +# \+/ +# +------- BOOTSZ (00 = 2k bytes) +# Fuse high byte: +# 0xd6 = 1 1 0 1 0 1 1 0 +# ^ ^ ^ ^ ^ \-+-/ +# | | | | | +------ BODLEVEL 0..2 (110 = 1.8 V) +# | | | | + --------- EESAVE (preserve EEPROM over chip erase) +# | | | +-------------- WDTON (if 0: watchdog always on) +# | | +---------------- SPIEN (allow serial programming) +# | +------------------ DWEN (debug wire enable) +# +-------------------- RSTDISBL (reset pin is enabled) +# Fuse low byte: +# 0xdf = 1 1 0 1 1 1 1 1 +# ^ ^ \ / \--+--/ +# | | | +------- CKSEL 3..0 (external >8M crystal) +# | | +--------------- SUT 1..0 (crystal osc, BOD enabled) +# | +------------------ CKOUT (if 0: Clock output enabled) +# +-------------------- CKDIV8 (if 0: divide by 8) + + +# Lock Bits +# 0x3f = - - 1 1 1 1 1 1 +# \ / \-/ \-/ +# | | +----- LB 2..1 (No memory lock features enabled) +# | +--------- BLB0 2..1 (No restrictions for SPM or LPM accessing the Application section) +# +--------------- BLB1 2..1 (No restrictions for SPM or LPM accessing the Boot Loader section) diff --git a/hhkb/Makefile.iwrap b/hhkb/Makefile.iwrap new file mode 100644 index 000000000..cf020b94a --- /dev/null +++ b/hhkb/Makefile.iwrap @@ -0,0 +1,91 @@ +# +# Makefile for iWRAP +# + + +# Target file name (without extension). +TARGET = hhkb_iwrap + +# Directory common source filess exist +COMMON_DIR = .. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c + +CONFIG_H = config_iwrap.h + + +# V-USB debug level: To use ps2_usart.c level must be 0 +# ps2_usart.c requires USART to receive PS/2 signal. +OPT_DEFS = -DDEBUG_LEVEL=0 + + +# MCU name, you MUST set this to match the board you are using +# type "make clean" after changing this, so all files will be rebuilt +MCU = atmega168p +# avrdude doesn't know atmega168p +AVRDUDE_MCU = atmega168 + + +# Processor frequency. +# Normally the first thing your program should do is set the clock prescaler, +# so your program will run at the correct speed. You should also set this +# variable to same clock speed. The _delay_ms() macro uses this, and many +# examples use this variable to calculate timings. Do not add a "UL" here. +F_CPU = 12000000 + + +# Build Options +# comment out to disable the options. +# +MOUSEKEY_ENABLE = yes # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control +#NKRO_ENABLE = yes # USB Nkey Rollover + + + +#---------------- Programming Options -------------------------- +AVRDUDE = avrdude +# Type: avrdude -c ? to get a full listing. +AVRDUDE_PROGRAMMER = usbasp +AVRDUDE_PORT = +AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex +#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep + +# Uncomment the following if you want avrdude's erase cycle counter. +# Note that this counter needs to be initialized first using -Yn, +# see avrdude manual. +#AVRDUDE_ERASE_COUNTER = -y + +# Uncomment the following if you do /not/ wish a verification to be +# performed after programming the device. +#AVRDUDE_NO_VERIFY = -V + +# Increase verbosity level. Please use this when submitting bug +# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> +# to submit bug reports. +#AVRDUDE_VERBOSE = -v -v + +#AVRDUDE_FLAGS = -p $(AVRDUDE_MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS = -p $(AVRDUDE_MCU) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) +AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) +AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) + +PROGRAM_CMD = $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + + + +# Search Path +VPATH = $(TARGET_DIR) + +include $(COMMON_DIR)/iwrap.mk +# To be swatchable btween Bluetooth and USB. Comment out if you don't need USB. +include $(COMMON_DIR)/vusb.mk +include $(COMMON_DIR)/common.mk diff --git a/hhkb/Makefile b/hhkb/Makefile.pjrc index e1cc2f210..17aa865dd 100644 --- a/hhkb/Makefile +++ b/hhkb/Makefile.pjrc @@ -13,10 +13,10 @@ COMMON_DIR = .. TARGET_DIR = . # keyboard dependent files -TARGET_SRC = main_pjrc.c \ - keymap.c \ - matrix.c \ - led.c +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c CONFIG_H = config_pjrc.h @@ -41,8 +41,8 @@ F_CPU = 16000000 # comment out to disable the options. MOUSEKEY_ENABLE = yes # Mouse keys #PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support -USB_EXTRA_ENABLE = yes # Audio control and System control -USB_NKRO_ENABLE = yes # USB Nkey Rollover +EXTRAKEY_ENABLE = yes # Audio control and System control +NKRO_ENABLE = yes # USB Nkey Rollover @@ -51,5 +51,8 @@ PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex -include $(COMMON_DIR)/Makefile.pjrc -include $(COMMON_DIR)/Makefile.common +# Search Path +VPATH = $(TARGET_DIR) + +include $(COMMON_DIR)/pjrc.mk +include $(COMMON_DIR)/common.mk diff --git a/hhkb/Makefile.vusb b/hhkb/Makefile.vusb index 77841b824..5bfc233df 100644 --- a/hhkb/Makefile.vusb +++ b/hhkb/Makefile.vusb @@ -13,10 +13,10 @@ COMMON_DIR = .. TARGET_DIR = . # keyboard dependent files -TARGET_SRC = main_vusb.c \ - keymap.c \ - matrix.c \ - led.c +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c CONFIG_H = config_vusb.h @@ -28,7 +28,9 @@ OPT_DEFS = -DDEBUG_LEVEL=0 # MCU name, you MUST set this to match the board you are using # type "make clean" after changing this, so all files will be rebuilt -MCU = atmega168 +MCU = atmega168p +# avrdude doesn't know atmega168p +AVRDUDE_MCU = atmega168 # Processor frequency. @@ -36,15 +38,15 @@ MCU = atmega168 # so your program will run at the correct speed. You should also set this # variable to same clock speed. The _delay_ms() macro uses this, and many # examples use this variable to calculate timings. Do not add a "UL" here. -F_CPU = 20000000 +F_CPU = 12000000 # Build Options # comment out to disable the options. # MOUSEKEY_ENABLE = yes # Mouse keys -USB_EXTRA_ENABLE = yes # Audio control and System control -#USB_NKRO_ENABLE = yes # USB Nkey Rollover +EXTRAKEY_ENABLE = yes # Audio control and System control +#NKRO_ENABLE = yes # USB Nkey Rollover @@ -70,8 +72,8 @@ AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex # to submit bug reports. #AVRDUDE_VERBOSE = -v -v -#AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) -AVRDUDE_FLAGS = -p $(MCU) -c $(AVRDUDE_PROGRAMMER) +#AVRDUDE_FLAGS = -p $(AVRDUDE_MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS = -p $(AVRDUDE_MCU) -c $(AVRDUDE_PROGRAMMER) AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) @@ -80,5 +82,8 @@ PROGRAM_CMD = $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE -include $(COMMON_DIR)/Makefile.vusb -include $(COMMON_DIR)/Makefile.common +# Search Path +VPATH = $(TARGET_DIR) + +include $(COMMON_DIR)/vusb.mk +include $(COMMON_DIR)/common.mk diff --git a/hhkb/README b/hhkb/README index 2a4418101..65f7dcab5 100644 --- a/hhkb/README +++ b/hhkb/README @@ -4,7 +4,7 @@ Alternative Controller for HHKB Feature ------- - Mouse Keys -- NKRO on USB +- NKRO on USB(PJRC Tennsy only) - Keymap Layers @@ -13,8 +13,11 @@ Customize Keymap see keymap.c. -Build for Teensy ----------------- + +Build +===== +PJRC Teensy +----------- 0. Edit matrix.c. adjust scan code to your pin configuration.(see doc/HHKB.txt for pinouts) 1. Define macros in config_pjrc.h.(Optional) @@ -22,15 +25,15 @@ Build for Teensy IS_COMMAND 2. Edit Makefile for MCU setting and build options. MCU, F_CPU - MOUSEKEY_ENABLE, USB_EXTRA_ENABLE, USB_NKRO_ENABLE + MOUSEKEY_ENABLE, EXTRAKEY_ENABLE, NKRO_ENABLE 3. Build hex file. - $ make + $ make -f Makefile.pjrc 4. Program MCU. - $ make program + $ make -f Makefile.pjrc program -Build for V-USB ---------------- +V-USB +----- 0. Edit matrix.c and usbconfig.h. adjust scan code to your pin configuration.(see doc/HHKB.txt for pinouts) define macros for V-USB in usbconfig.h. @@ -38,7 +41,7 @@ Build for V-USB IS_COMMAND 2. Edit Makefile.vusb for MCU setting and build options. MCU, F_CPU - MOUSEKEY_ENABLE, USB_EXTRA_ENABLE, USB_NKRO_ENABLE + MOUSEKEY_ENABLE, EXTRAKEY_ENABLE 3. Build hex file. $ make -f Makefile.vusb 4. Program MCU. @@ -52,21 +55,59 @@ Build for V-USB http://www.obdev.at/products/vusb/usbasploader.html -V-USB Circuit -------------- +iWRAP +----- +0. Edit matrix.c and usbconfig.h. + adjust scan code to your pin configuration.(see doc/HHKB.txt for pinouts) + define macros for V-USB in usbconfig.h. +1. Define macros in config_iwrap.h.(Optional) + IS_COMMAND +2. Edit Makefile.iwrap for MCU setting and build options. + MCU, F_CPU + MOUSEKEY_ENABLE, EXTRAKEY_ENABLE +3. Build hex file. + $ make -f Makefile.iwrap +4. Program MCU. + $ make -f Makefile.iwrap program + + + +Hardware +======== +PJRC Teensy +----------- + +---------------+ + | Teensy++ | + | | + | | HHKB + | | ~~~~ + | PB0-2|------->ROW(6-8) + | PB3-5|------->COL(9-11) + | PB6|------->ENABLE(12) + | PE6|<-------KEY(4) + | PE7|------->PREV(5) + | | + | | + | | + +---------------+ + + +V-USB +----- +---+ +---------------+ USB GND | | ATmega168 | -=== C3 | | +~~~ C3 | | 5V <-------+--------+---|Vcc,AVCC | HHKB - R1 | | ==== -D- <----+--+-----R2-----|INT1 PB0-2|------->ROW -D+ <----|---+----R3-----|INT0 PB3-5|------->COL - Z1 Z2 | PB6|------->ENABLE -GND<----+---+--+--+-----|GND PE6|------->KEY - | | | PE7|------->PREV - | C2-+--|XTAL1 | (see doc/HHKB.txt for pinouts) - | X1 | | - +--C3-+--|XTAL2 RST|---SW--+GND + R1 | | ~~~~ +D- <----+--+-----R2-----|INT1 PB2-4|------->ROW(6-8) +D+ <----|---+----R3-----|INT0 PC0-2|------->COL(9-11) + Z1 Z2 | PC3|------->ENABLE(12) +GND<----+---+-----------|GND PB0|<-------KEY(4) + | PB1|------->PREV(5) + | | + GND+-C2--+--|XTAL1 RXD|------->Debug Console + X1 | TXD|<-------Debug Console + GND+-C3--+--|XTAL2 RST|---SW--+GND +---------------+ R1: 1.5K Ohm R2,R3: 68 Ohm @@ -77,4 +118,34 @@ X1: Crystal 20MHz(16MHz/12MHz) SW: Push Switch(Optional for bootloader) +iWRAP +----- + +---------------+ WT12 + 5V | ATmega168 | 5V/3.3V~~~~ + +-----+---|Vcc,AVCC PC4|---/--->iWRAP(RxD) +USB | C3 | PC5|<--/----iWRAP(TxD) +~~~ | + | | +5V <--BATT + GND | | HHKB + R1 | | ~~~~ +D- <----+-----+--R2-----|INT1 PB2-4|------->ROW(6-8) +D+ <----|---+----R3-----|INT0 PC0-2|------->COL(9-11) + Z1 Z2 | PC3|------->ENABLE(12) +GND<----+---+-----------|GND PB0|<-------KEY(4) + | PB1|------->PREV(5) + | | + GND+-C2--+--|XTAL1 RXD|------->Debug Console + X1 | TXD|<-------Debug Console + GND+-C3--+--|XTAL2 RST|---SW--+GND + +---------------+ + +R1: 1.5K Ohm +R2,R3: 68 Ohm +Z1,Z2: Zener 3.6V +C1,C2: 22pF +C3: 0.1uF +X1: Crystal 12MHz +SW: Push Switch(Optional) +BATT: Li-Po Battery, Battery Charger and Voltage Regulator(5V and 3.3V). + + EOF diff --git a/hhkb/config_iwrap.h b/hhkb/config_iwrap.h new file mode 100644 index 000000000..80ab64398 --- /dev/null +++ b/hhkb/config_iwrap.h @@ -0,0 +1,55 @@ +/* +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 CONFIG_H +#define CONFIG_H + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0xBEEA +// TODO: share these strings with usbconfig.h +// Edit usbconfig.h to change these. +#define MANUFACTURER t.m.k. +#define PRODUCT HHKB mod +#define DESCRIPTION t.m.k. keyboard firmware for HHKB mod + + +/* matrix size */ +#define MATRIX_ROWS 8 +#define MATRIX_COLS 8 + + +/* key combination for command */ +#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT))) + +/* mouse keys */ +#ifdef MOUSEKEY_ENABLE +# define MOUSEKEY_DELAY_TIME 255 +#endif + +/* pins for Software UART */ +#define SUART_IN_PIN PINC +#define SUART_IN_BIT 5 +#define SUART_OUT_PORT PORTC +#define SUART_OUT_BIT 4 + + +#define DEBUG_LED 1 +#define DEBUG_LED_CONFIG (DDRD |= (1<<4)) +#define DEBUG_LED_OFF (PORTD |= (1<<4)) +#define DEBUG_LED_ON (PORTD &= ~(1<<4)) + +#endif diff --git a/hhkb/config_pjrc.h b/hhkb/config_pjrc.h index ef2efe2d9..8379202ca 100644 --- a/hhkb/config_pjrc.h +++ b/hhkb/config_pjrc.h @@ -36,11 +36,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. /* key combination for command */ -#define IS_COMMAND() ( \ - keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \ - keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \ -) - +#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT))) /* mouse keys */ #ifdef MOUSEKEY_ENABLE diff --git a/hhkb/config_vusb.h b/hhkb/config_vusb.h index 115b73de3..268644849 100644 --- a/hhkb/config_vusb.h +++ b/hhkb/config_vusb.h @@ -18,7 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifndef CONFIG_H #define CONFIG_H - #define VENDOR_ID 0xFEED #define PRODUCT_ID 0xC0FE // TODO: share these strings with usbconfig.h @@ -34,11 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. /* key combination for command */ -#define IS_COMMAND() ( \ - keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \ - keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \ -) - +#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT))) /* mouse keys */ #ifdef MOUSEKEY_ENABLE @@ -46,4 +41,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #endif +#define DEBUG_LED 1 +#define DEBUG_LED_CONFIG (DDRD |= (1<<4)) +#define DEBUG_LED_OFF (PORTD |= (1<<4)) +#define DEBUG_LED_ON (PORTD &= ~(1<<4)) + #endif diff --git a/hhkb/doc/Bluetooth.txt b/hhkb/doc/Bluetooth.txt new file mode 100644 index 000000000..b27f19700 --- /dev/null +++ b/hhkb/doc/Bluetooth.txt @@ -0,0 +1,4 @@ +HHKB Bluetooth mod +================== +See this article: +http://geekhack.org/showwiki.php?title=Island:20851 diff --git a/hhkb/doc/Bluetooth_img/.picasa.ini b/hhkb/doc/Bluetooth_img/.picasa.ini new file mode 100755 index 000000000..f6a4f6067 --- /dev/null +++ b/hhkb/doc/Bluetooth_img/.picasa.ini @@ -0,0 +1,2 @@ +[Picasa]
+name=Bluetooth_img
diff --git a/hhkb/doc/Bluetooth_img/BT_circuit.jpg b/hhkb/doc/Bluetooth_img/BT_circuit.jpg Binary files differnew file mode 100755 index 000000000..2e5a25e81 --- /dev/null +++ b/hhkb/doc/Bluetooth_img/BT_circuit.jpg diff --git a/hhkb/doc/HHKB_TP1684.jpg b/hhkb/doc/HHKB_img/HHKB_TP1684.jpg Binary files differindex 0a0316409..0a0316409 100644 --- a/hhkb/doc/HHKB_TP1684.jpg +++ b/hhkb/doc/HHKB_img/HHKB_TP1684.jpg diff --git a/hhkb/doc/HHKB_chart1.jpg b/hhkb/doc/HHKB_img/HHKB_chart1.jpg Binary files differindex 1f09bd185..1f09bd185 100644 --- a/hhkb/doc/HHKB_chart1.jpg +++ b/hhkb/doc/HHKB_img/HHKB_chart1.jpg diff --git a/hhkb/doc/HHKB_chart2.jpg b/hhkb/doc/HHKB_img/HHKB_chart2.jpg Binary files differindex 45f5ada90..45f5ada90 100644 --- a/hhkb/doc/HHKB_chart2.jpg +++ b/hhkb/doc/HHKB_img/HHKB_chart2.jpg diff --git a/hhkb/doc/HHKB_connector.jpg b/hhkb/doc/HHKB_img/HHKB_connector.jpg Binary files differindex e8a09e9b2..e8a09e9b2 100644 --- a/hhkb/doc/HHKB_connector.jpg +++ b/hhkb/doc/HHKB_img/HHKB_connector.jpg diff --git a/hhkb/doc/HHKB_controller.jpg b/hhkb/doc/HHKB_img/HHKB_controller.jpg Binary files differindex e3dae8e86..e3dae8e86 100644 --- a/hhkb/doc/HHKB_controller.jpg +++ b/hhkb/doc/HHKB_img/HHKB_controller.jpg diff --git a/hhkb/doc/HHKB_keyswitch.jpg b/hhkb/doc/HHKB_img/HHKB_keyswitch.jpg Binary files differindex 3afc269e7..3afc269e7 100644 --- a/hhkb/doc/HHKB_keyswitch.jpg +++ b/hhkb/doc/HHKB_img/HHKB_keyswitch.jpg diff --git a/hhkb/doc/connector_contact.jpg b/hhkb/doc/HHKB_img/connector_contact.jpg Binary files differindex 5304bc8d7..5304bc8d7 100644 --- a/hhkb/doc/connector_contact.jpg +++ b/hhkb/doc/HHKB_img/connector_contact.jpg diff --git a/hhkb/doc/logic_analyzer.jpg b/hhkb/doc/HHKB_img/logic_analyzer.jpg Binary files differindex f1b438ae7..f1b438ae7 100644 --- a/hhkb/doc/logic_analyzer.jpg +++ b/hhkb/doc/HHKB_img/logic_analyzer.jpg diff --git a/hhkb/doc/probe_contact.jpg b/hhkb/doc/HHKB_img/probe_contact.jpg Binary files differindex dc79afa0c..dc79afa0c 100644 --- a/hhkb/doc/probe_contact.jpg +++ b/hhkb/doc/HHKB_img/probe_contact.jpg diff --git a/hhkb/doc/teensy_install.jpg b/hhkb/doc/HHKB_img/teensy_install.jpg Binary files differindex 873d988ed..873d988ed 100644 --- a/hhkb/doc/teensy_install.jpg +++ b/hhkb/doc/HHKB_img/teensy_install.jpg diff --git a/hhkb/doc/teensy_wiring.jpg b/hhkb/doc/HHKB_img/teensy_wiring.jpg Binary files differindex 1c4eb6743..1c4eb6743 100644 --- a/hhkb/doc/teensy_wiring.jpg +++ b/hhkb/doc/HHKB_img/teensy_wiring.jpg diff --git a/hhkb/keymap.c b/hhkb/keymap.c index f539a06cc..85a7c31b7 100644 --- a/hhkb/keymap.c +++ b/hhkb/keymap.c @@ -32,21 +32,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. // Convert physical keyboard layout to matrix array. // This is a macro to define keymap easily in keyboard layout form. #define KEYMAP( \ - R3C1, R3C0, R0C0, R1C0, R1C1, R2C0, R2C1, R4C0, R4C1, R6C0, R6C1, R7C0, R7C1, R5C0, R5C1, \ - R3C2, R0C1, R0C2, R1C3, R1C2, R2C3, R2C2, R4C2, R4C3, R6C2, R6C3, R7C3, R7C2, R5C2, \ - R3C3, R0C4, R0C3, R1C4, R1C5, R2C4, R2C5, R4C5, R4C4, R6C5, R6C4, R7C4, R5C3, \ - R3C4, R0C5, R0C6, R0C7, R1C6, R1C7, R2C6, R4C6, R6C6, R7C6, R7C5, R5C5, R5C4, \ - R3C5, R3C6, R3C7, R5C7, R5C6 \ + K31, K30, K00, K10, K11, K20, K21, K40, K41, K60, K61, K70, K71, K50, K51, \ + K32, K01, K02, K13, K12, K23, K22, K42, K43, K62, K63, K73, K72, K52, \ + K33, K04, K03, K14, K15, K24, K25, K45, K44, K65, K64, K74, K53, \ + K34, K05, K06, K07, K16, K17, K26, K46, K66, K76, K75, K55, K54, \ + K35, K36, K37, K57, K56 \ ) \ { \ - { R0C0, R0C1, R0C2, R0C3, R0C4, R0C5, R0C6, R0C7 }, \ - { R1C0, R1C1, R1C2, R1C3, R1C4, R1C5, R1C6, R1C7 }, \ - { R2C0, R2C1, R2C2, R2C3, R2C4, R2C5, R2C6, KB_NO }, \ - { R3C0, R3C1, R3C2, R3C3, R3C4, R3C5, R3C6, R3C7 }, \ - { R4C0, R4C1, R4C2, R4C3, R4C4, R4C5, R4C6, KB_NO }, \ - { R5C0, R5C1, R5C2, R5C3, R5C4, R5C5, R5C6, R5C7 }, \ - { R6C0, R6C1, R6C2, R6C3, R6C4, R6C5, R6C6, KB_NO }, \ - { R7C0, R7C1, R7C2, R7C3, R7C4, R7C5, R7C6, KB_NO } \ + { KB_##K00, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ + { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ + { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_NO }, \ + { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_##K37 }, \ + { KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_NO }, \ + { KB_##K50, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ + { KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_##K65, KB_##K66, KB_NO }, \ + { KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_NO } \ } #define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) @@ -58,8 +58,8 @@ static const uint8_t PROGMEM fn_layer[] = { 1, // Fn1 2, // Fn2 3, // Fn3 - 4, // Fn4 - 0, // Fn5 + 3, // Fn4 + 4, // Fn5 0, // Fn6 0 // Fn7 }; @@ -71,8 +71,8 @@ static const uint8_t PROGMEM fn_keycode[] = { KB_NO, // Fn1 KB_SLSH, // Fn2 KB_SCLN, // Fn3 - KB_SPC, // Fn4 - KB_NO, // Fn5 + KB_NO, // Fn4 + KB_SPC, // Fn5 KB_NO, // Fn6 KB_NO // Fn7 }; @@ -91,11 +91,11 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |Gui|Alt |Fn5 |Alt |Fn4| * `-------------------------------------------' */ - KEYMAP(KB_ESC, KB_1, KB_2, KB_3, KB_4, KB_5, KB_6, KB_7, KB_8, KB_9, KB_0, KB_MINS,KB_EQL, KB_BSLS,KB_GRV, \ - KB_TAB, KB_Q, KB_W, KB_E, KB_R, KB_T, KB_Y, KB_U, KB_I, KB_O, KB_P, KB_LBRC,KB_RBRC,KB_BSPC, \ - KB_LCTL,KB_A, KB_S, KB_D, KB_F, KB_G, KB_H, KB_J, KB_K, KB_L, KB_FN3, KB_QUOT,KB_ENT, \ - KB_LSFT,KB_Z, KB_X, KB_C, KB_V, KB_B, KB_N, KB_M, KB_COMM,KB_DOT, KB_FN2, KB_RSFT,KB_FN1, \ - KB_LGUI,KB_LALT,KB_FN4, KB_RALT,KB_RGUI), + KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \ + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \ + LCTL,A, S, D, F, G, H, J, K, L, FN3, QUOT,ENT, \ + LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \ + LGUI,LALT, FN5, RALT,FN4), /* Layer 1: HHKB mode (HHKB Fn) * ,-----------------------------------------------------------. @@ -110,11 +110,11 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |Gui |Alt |Space |Alt |xxx| * `--------------------------------------------' */ - KEYMAP(KB_ESC, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12, KB_INS, KB_DEL, \ - KB_CAPS,KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_PSCR,KB_SLCK,KB_BRK, KB_UP, KB_NO, KB_BSPC, \ - KB_LCTL,KB_VOLD,KB_VOLU,KB_MUTE,KB_NO, KB_NO, KB_PAST,KB_PSLS,KB_HOME,KB_PGUP,KB_LEFT,KB_RGHT,KB_ENT, \ - KB_LSFT,KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_PPLS,KB_PMNS,KB_END, KB_PGDN,KB_DOWN,KB_RSFT,KB_FN1, \ - KB_LGUI,KB_LALT,KB_SPC, KB_RALT,KB_FN7), + KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ + CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,BRK, UP, NO, BSPC, \ + LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \ + LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN1, \ + LGUI,LALT, SPC, RALT,FN7), /* Layer 2: Vi mode (Slash) * ,-----------------------------------------------------------. @@ -129,11 +129,11 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |Gui|Alt |Space |Alt |Gui| * `-------------------------------------------' */ - KEYMAP(KB_ESC, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12, KB_INS, KB_DEL, \ - KB_TAB, KB_HOME,KB_PGDN,KB_UP, KB_PGUP,KB_END, KB_HOME,KB_PGDN,KB_PGUP,KB_END, KB_NO, KB_NO, KB_NO, KB_BSPC, \ - KB_LCTL,KB_NO, KB_LEFT,KB_DOWN,KB_RGHT,KB_NO, KB_LEFT,KB_DOWN,KB_UP, KB_RGHT,KB_NO, KB_NO, KB_ENT, \ - KB_LSFT,KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_HOME,KB_PGDN,KB_PGUP,KB_END, KB_FN2, KB_RSFT,KB_NO, \ - KB_LGUI,KB_LALT,KB_SPC, KB_RALT,KB_RGUI), + KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ + TAB, HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, BSPC, \ + LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, \ + LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN2, RSFT,NO, \ + LGUI,LALT, SPC, RALT,RGUI), /* Layer 3: Mouse mode (Semicolon) * ,-----------------------------------------------------------. @@ -149,11 +149,24 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * `--------------------------------------------' * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel */ - KEYMAP(KB_ESC, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12, KB_INS, KB_DEL, \ - KB_TAB, KB_WH_L,KB_WH_U,KB_MS_U,KB_WH_D,KB_WH_R,KB_WH_L,KB_WH_D,KB_WH_U,KB_WH_R,KB_NO, KB_NO, KB_NO, KB_BSPC, \ - KB_LCTL,KB_NO, KB_MS_L,KB_MS_D,KB_MS_R,KB_NO, KB_MS_L,KB_MS_D,KB_MS_U,KB_MS_R,KB_FN3, KB_NO, KB_ENT, \ - KB_LSFT,KB_BTN4,KB_BTN5,KB_BTN1,KB_BTN2,KB_BTN3,KB_BTN2,KB_BTN1,KB_BTN4,KB_BTN5,KB_NO, KB_RSFT,KB_NO, \ - KB_LGUI,KB_LALT,KB_BTN1,KB_RALT,KB_RGUI), +#ifdef HOST_IWRAP +// iWRAP does not support mouse wheel, use these keycodes to remap as wheel +#define KB_KPPL KB_KP_PLUS +#define KB_KPMI KB_KP_MINUS +#define KB_KPAS KB_KP_ASTERISK +#define KB_KPSL KB_KP_SLASH + KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ + TAB, KPAS,KPPL,MS_U,KPMI,KPSL,KPAS,KPPL,KPMI,KPSL,NO, NO, NO, BSPC, \ + LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ + LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,NO, NO, NO, RSFT,NO, \ + LGUI,LALT, BTN1, RALT,FN4), +#else + KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ + TAB, WH_L,WH_U,MS_U,WH_D,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ + LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ + LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ + LGUI,LALT, BTN1, RALT,FN4), +#endif /* Layer 4: Matias half keyboard style (Space) * ,-----------------------------------------------------------. @@ -169,18 +182,26 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * `--------------------------------------------' */ /* - KEYMAP(KB_MINS,KB_0, KB_9, KB_8, KB_7, KB_6, KB_5, KB_4, KB_3, KB_2, KB_1, KB_NO, KB_NO, KB_NO, KB_ESC, \ - KB_BSPC,KB_P, KB_O, KB_I, KB_U, KB_Y, KB_T, KB_R, KB_E, KB_W, KB_Q, KB_NO, KB_NO, KB_TAB, \ - KB_LCTL,KB_SCLN,KB_L, KB_K, KB_J, KB_H, KB_G, KB_F, KB_D, KB_S, KB_A, KB_RCTL,KB_RCTL, \ - KB_LSFT,KB_SLSH,KB_DOT, KB_COMM,KB_M, KB_N, KB_B, KB_V, KB_C, KB_X, KB_Z, KB_RSFT,KB_NO, \ - KB_LGUI,KB_LALT,KB_FN4, KB_RALT,KB_RGUI) + KEYMAP(MINS,0, 9, 8, 7, 6, 5, 4, 3, 2, 1, NO, NO, NO, ESC, \ + BSPC,P, O, I, U, Y, T, R, E, W, Q, NO, NO, TAB, \ + LCTL,SCLN,L, K, J, H, G, F, D, S, A, RCTL,RCTL, \ + LSFT,SLSH,DOT, COMM,M, N, B, V, C, X, Z, RSFT,NO, \ + LGUI,LALT, FN5, RALT,RGUI) */ /* Mouse mode (Space) */ - KEYMAP(KB_ESC, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12, KB_INS, KB_DEL, \ - KB_TAB, KB_WH_L,KB_WH_U,KB_MS_U,KB_WH_D,KB_WH_R,KB_WH_L,KB_WH_D,KB_WH_U,KB_WH_R,KB_NO, KB_NO, KB_NO, KB_BSPC, \ - KB_LCTL,KB_NO, KB_MS_L,KB_MS_D,KB_MS_R,KB_NO, KB_MS_L,KB_MS_D,KB_MS_U,KB_MS_R,KB_FN3, KB_NO, KB_ENT, \ - KB_LSFT,KB_BTN4,KB_BTN5,KB_BTN1,KB_BTN2,KB_BTN3,KB_BTN2,KB_BTN1,KB_BTN4,KB_BTN5,KB_NO, KB_RSFT,KB_NO, \ - KB_LGUI,KB_LALT,KB_FN4, KB_RALT,KB_RGUI), +#ifdef HOST_IWRAP + KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ + TAB, KPAS,KPPL,MS_U,KPMI,KPSL,KPAS,KPPL,KPMI,KPSL,NO, NO, NO, BSPC, \ + LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ + LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ + LGUI,LALT, FN5, RALT,RGUI), +#else + KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ + TAB, WH_L,WH_U,MS_U,WH_D,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ + LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ + LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ + LGUI,LALT, FN5, RALT,RGUI), +#endif }; diff --git a/hhkb/matrix.c b/hhkb/matrix.c index a77febb29..350066b90 100644 --- a/hhkb/matrix.c +++ b/hhkb/matrix.c @@ -25,9 +25,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include <util/delay.h> #include "print.h" #include "util.h" +#include "timer.h" #include "matrix.h" +// Timer resolution check +#if (1000000/TIMER_RAW_FREQ > 20) +# error "Timer resolution(>20us) is not enough for HHKB matrix scan tweak on V-USB." +#endif + #if (MATRIX_COLS > 16) # error "MATRIX_COLS must not exceed 16" #endif @@ -82,18 +88,22 @@ static bool matrix_has_ghost_in_row(uint8_t row); #define KEY_STATE() (PINE & (1<<6)) #define KEY_PREV_ON() (PORTE |= (1<<7)) #define KEY_PREV_OFF() (PORTE &= ~(1<<7)) - +#define KEY_POWER_ON() +#define KEY_POWER_OFF() #else // Ports for V-USB // key: PB0(pull-uped) // prev: PB1 // row: PB2-4 // col: PC0-2,3 +// power: PB5(Low:on/Hi-z:off) #define KEY_INIT() do { \ - DDRB |= 0x1E; \ - DDRB &= ~(1<<0); \ - PORTB |= (1<<0); \ - DDRC |= 0x0F; \ + DDRB |= 0x3E; \ + DDRB &= ~(1<<0); \ + PORTB |= 1<<0; \ + DDRC |= 0x0F; \ + KEY_UNABLE(); \ + KEY_PREV_OFF(); \ } while (0) #define KEY_SELECT(ROW, COL) do { \ PORTB = (PORTB & 0xE3) | ((ROW) & 0x07)<<2; \ @@ -104,6 +114,18 @@ static bool matrix_has_ghost_in_row(uint8_t row); #define KEY_STATE() (PINB & (1<<0)) #define KEY_PREV_ON() (PORTB |= (1<<1)) #define KEY_PREV_OFF() (PORTB &= ~(1<<1)) +// Power supply switching +#define KEY_POWER_ON() do { \ + KEY_INIT(); \ + PORTB &= ~(1<<5); \ + _delay_us(200); \ +} while (0) +#define KEY_POWER_OFF() do { \ + DDRB &= ~0x3F; \ + PORTB &= ~0x3F; \ + DDRC &= ~0x0F; \ + PORTC &= ~0x0F; \ +} while (0) #endif @@ -138,36 +160,46 @@ uint8_t matrix_scan(void) matrix_prev = matrix; matrix = tmp; + KEY_POWER_ON(); for (uint8_t row = 0; row < MATRIX_ROWS; row++) { for (uint8_t col = 0; col < MATRIX_COLS; col++) { KEY_SELECT(row, col); - _delay_us(40); // from logic analyzer chart + _delay_us(40); + + // Not sure this is needed. This just emulates HHKB controller's behaviour. if (matrix_prev[row] & (1<<col)) { KEY_PREV_ON(); } - _delay_us(7); // from logic analyzer chart + _delay_us(7); + + // NOTE: KEY_STATE is valid only in 20us after KEY_ENABLE. + // If V-USB interrupts in this section we could lose 40us or so + // and would read invalid value from KEY_STATE. + uint8_t last = TIMER_RAW; -#if HOST_VUSB - // to avoid V-USB interrupt during read key state - uint8_t sreg = SREG; - cli(); -#endif KEY_ENABLE(); - _delay_us(10); // from logic analyzer chart + // Wait for KEY_STATE outputs its value. + // 1us was ok on one HHKB, but not worked on another. + _delay_us(10); if (KEY_STATE()) { matrix[row] &= ~(1<<col); } else { matrix[row] |= (1<<col); } -#if HOST_VUSB - SREG = sreg; -#endif + + // Ignore if this code region execution time elapses more than 20us. + if (TIMER_DIFF_RAW(TIMER_RAW, last) > 20/(1000000/TIMER_RAW_FREQ)) { + matrix[row] = matrix_prev[row]; + } KEY_PREV_OFF(); KEY_UNABLE(); - _delay_us(150); // from logic analyzer chart + // NOTE: KEY_STATE keep its state in 20us after KEY_ENABLE. + // This takes 25us or more to make sure KEY_STATE returns to idle state. + _delay_us(150); } } + KEY_POWER_OFF(); return 1; } diff --git a/hhkb/usbconfig.h b/hhkb/usbconfig.h index e8283505e..c3aad34be 100644 --- a/hhkb/usbconfig.h +++ b/hhkb/usbconfig.h @@ -171,7 +171,7 @@ section at the end of this file). /* This macro (if defined) is executed when a USB SET_ADDRESS request was * received. */ -#define USB_COUNT_SOF 0 +#define USB_COUNT_SOF 1 /* define this macro to 1 if you need the global variable "usbSofCount" which * counts SOF packets. This feature requires that the hardware interrupt is * connected to D- instead of D+. @@ -352,8 +352,8 @@ section at the end of this file). #define USB_CFG_DESCR_PROPS_STRING_VENDOR 0 #define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0 #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0 -//#define USB_CFG_DESCR_PROPS_HID USB_PROP_IS_DYNAMIC -#define USB_CFG_DESCR_PROPS_HID 0 +#define USB_CFG_DESCR_PROPS_HID USB_PROP_IS_DYNAMIC +//#define USB_CFG_DESCR_PROPS_HID 0 #define USB_CFG_DESCR_PROPS_HID_REPORT USB_PROP_IS_DYNAMIC //#define USB_CFG_DESCR_PROPS_HID_REPORT 0 #define USB_CFG_DESCR_PROPS_UNKNOWN 0 @@ -375,4 +375,14 @@ section at the end of this file). /* #define USB_INTR_PENDING_BIT INTF0 */ /* #define USB_INTR_VECTOR INT0_vect */ +/* Set INT1 for D- falling edge to count SOF */ +/* #define USB_INTR_CFG EICRA */ +#define USB_INTR_CFG_SET ((1 << ISC11) | (0 << ISC10)) +/* #define USB_INTR_CFG_CLR 0 */ +/* #define USB_INTR_ENABLE EIMSK */ +#define USB_INTR_ENABLE_BIT INT1 +/* #define USB_INTR_PENDING EIFR */ +#define USB_INTR_PENDING_BIT INTF1 +#define USB_INTR_VECTOR INT1_vect + #endif /* __usbconfig_h_included__ */ @@ -0,0 +1,190 @@ +/* +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 add_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_add_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_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_consumer)(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 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"); + } +} @@ -19,88 +19,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define HOST_H #include <stdint.h> +#include "report.h" +#include "host_driver.h" -/* report id */ -#define REPORT_ID_MOUSE 1 -#define REPORT_ID_SYSTEM 2 -#define REPORT_ID_CONSUMER 3 - -/* keyboard Modifiers in boot protocol report */ -#define BIT_LCTRL (1<<0) -#define BIT_LSHIFT (1<<1) -#define BIT_LALT (1<<2) -#define BIT_LGUI (1<<3) -#define BIT_RCTRL (1<<4) -#define BIT_RSHIFT (1<<5) -#define BIT_RALT (1<<6) -#define BIT_RGUI (1<<7) -#define BIT_LCTL BIT_LCTRL -#define BIT_RCTL BIT_RCTRL -#define BIT_LSFT BIT_LSHIFT -#define BIT_RSFT BIT_RSHIFT - -/* 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) -#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 - -// Generic Desktop Page(0x01) -#define SYSTEM_POWER_DOWN 0x0081 -#define SYSTEM_SLEEP 0x0082 -#define SYSTEM_WAKE_UP 0x0083 - - -#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 -#elif defined(HOST_VUSB) -# 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; - - -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE extern bool keyboard_nkro; #endif @@ -108,6 +31,8 @@ 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 */ @@ -122,12 +47,8 @@ uint8_t host_get_first_key(void); void host_send_keyboard_report(void); -#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE) void host_mouse_send(report_mouse_t *report); -#endif -#ifdef USB_EXTRA_ENABLE void host_system_send(uint16_t data); void host_consumer_send(uint16_t data); -#endif #endif diff --git a/host_driver.h b/host_driver.h new file mode 100644 index 000000000..edb9e5dd9 --- /dev/null +++ b/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/iwrap.mk b/iwrap.mk new file mode 100644 index 000000000..ea4a6e972 --- /dev/null +++ b/iwrap.mk @@ -0,0 +1,10 @@ +OPT_DEFS += -DHOST_IWRAP + +SRC += iwrap.c \ + suart.S \ + sendchar_uart.c \ + uart.c + + +# Search Path +VPATH += $(COMMON_DIR)/iwrap diff --git a/iwrap/iWRAP.txt b/iwrap/iWRAP.txt new file mode 100644 index 000000000..2a062d9d9 --- /dev/null +++ b/iwrap/iWRAP.txt @@ -0,0 +1,376 @@ +Bulegiga WT12 +============= +WT12 is a bluetooth module from Bluegiga. http://www.bluegiga.com/ + +iWRAP + higher layer interface for bluetooth firmware + communicate with UART + +iWRAP HID +default setting + 115200 8bit/n/1/n + + +TODO +---- +KiCAD circuit/PCB design +power saving + AVR sleep(15ms by watch dog timer) + WT12 sleep + measuring current consumption + measuring battery life of normal usage/idle/intensive usage +software reset/bootloarder +LED indicator(chaging/paring/connecting) +license confirmation of suart.c +consumer page is not working +authenticate method/SSP +SPP keyboard support +SPP debug console support +mouse wheel feature request to Bluegiga + + +Problems +-------- +power consumption +no consumer page support(bug?) +no mouse wheel support +no paring management +no interactive auth method + + +UART hardware flow control +-------------------------- +(iWRAP4 User Guide 9.5) +Hardware flow control is enabled by default and it should not be disabled unless mandatory, because without the hardware flow control the data transmission may not be reliable. +If the hardware flow control is enabled from PS-keys, but no flow control is used, the following steps should be implemented in the hardware design: +- CTS pin must be grounded +- RTS pin must be left floating + + +Power Saving +------------ +power consume + without opimization: 4hr to shutdown(310mAh) + 2011/08/25: 9hr(310mAh) SNIFF MASTER sleep/WDTO_120MS + +measure current consumption + HHKB keyswitch matrix board + idle + scanning + Bluegiga WT12 module + SLEEP command + deep sleep on/off in config bits + +HHKB keyswich + how to power off + I/O pin configuration when sleeping + FET switch for 5V regulator + +Bluetooth module + power off when in USB mode + power off by FET switch + +AVR configuration + unused pins + ADC + + + +SET CONTROL CONFIG +------------------ + SET CONTROL CONFIG 4810 + SET CONTROL CONFIG LIST + SET CONTROL CONFIG 0000 0000 4910 DEEP_SLEEP KLUDGE INTERACTIVE_PIN UART_LATENCY + + Bit14 UART low latency + Bit11 Interactive pairing mode + Bit04 Deep sleep + + +Reconnection +------------ +SET CONTROL AUTOCALL 1124 5000 HID + 1124 HID service class + 5000 interval ms + +HID profile +----------- +This is needed to configure only once. + SET PROFILE HID ON + RESET + +HID class +--------- + SET BT CLASS 005C0 // keyboard/mouse combined devie + +Pairing Security +---------------- +Secure Simple Pairing(SSP) + SET BT SSP 2 0 // Enables SSP for keyboard and Man-in-the-middle protection + SET BT SSP 3 0 // Enables SSP just works mode + +for keyboard with SSP + SET BT AUTH * 0000 + SET BT SSP 2 0 + SET CONTROL CONFIG 800 + RESET + +for keyboard without SSP + SET BT AUTH * 0000 + SET CONTROL CONFIG 800 + RESET + +AUTH + AUTH xx:xx:xx:xx:xx:xx? // Pairing request event + AUTH xx:xx:xx:xx:xx:xx 0000 + + SSP PASSKEY 78:dd:08:b7:e4:a2 ? + SSP PASSKEY 78:dd:08:b7:e4:a2 xxxxx + (SSP COMPLETE 78:dd:08:b7:e4:a2 HCI_ERROR_AUTH_FAIL // failed) + RING 0 78:dd:08:b7:e4:a2 11 HID + +Connecton + RING xx:xx:xx:xx:xx:xx xx HID // connection event + + KILL xx:xx:xx:xx:xx:xx + +Mode +---- +Command mode +Data mode + Raw mode + (Simple mode not for a real keyboard) + +Raw mode + Keyboard: + 0x9f, length(10), 0xa1, 0x01, mods, 0x00, key1, key2, key3, key4, key5, key6 + + Mouse: + 0x9f, length(5), 0xa1, 0x02, buttons, X, Y + + Consumer page: + 0x9f, length(5), 0xa1, 0x03, bitfield1, bitfield2, bitfield3 + + consumer page suage + Bitfield 1: + 0x01 Volume Increment + 0x02 Volume Decrement + 0x04 Mute + 0x08 Play/Pause + 0x10 Scan Next Track + 0x20 Scan Previous Track + 0x40 Stop + 0x80 Eject + Bitfield 2: + 0x01 Email Reader + 0x02 Application Control Search + 0x04 AC Bookmarks + 0x08 AC Home + 0x10 AC Back + 0x20 AC Forward + 0x40 AC Stop + 0x80 AC Refresh + Bitfield 3: + 0x01 Application Launch Generic Consumer Control + 0x02 AL Internet Browser + 0x04 AL Calculator + 0x08 AL Terminal Lock / Screensaver + 0x10 AL Local Machine Browser + 0x20 AC Minimize + 0x40 Record + 0x80 Rewind + + + + + +2011/07/13 +set +SET BT BDADDR 00:07:80:47:22:14 +SET BT NAME HHKB pro BT +SET BT CLASS 0005c0 +SET BT AUTH * 0000 +SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP +SET BT LAP 9e8b33 +SET BT PAGEMODE 4 2000 1 +SET BT PAIR 78:dd:08:b7:e4:a2 a191189cd7e51030ad6a07848ce879bb +SET BT POWER 3 3 3 +SET BT ROLE 0 f 7d00 +SET BT SNIFF 0 20 1 8 +SET BT SSP 2 1 +SET BT MTU 667 +SET CONTROL AUTOCALL 1124 3000 HID +SET CONTROL BAUD 38400,8n1 +SET CONTROL CD 00 0 +SET CONTROL ECHO 7 +SET CONTROL ESCAPE 43 00 1 +SET CONTROL GAIN 0 5 +SET CONTROL INIT SET CONTROL MUX 0 +SET CONTROL MSC DTE 00 00 00 00 00 00 +SET CONTROL MUX 1 +SET CONTROL PIO 00 00 +SET CONTROL READY 00 +SET PROFILE HID f HID +SET + +info config + +!!! THIS IS BETA RELEASE AND MAY BE USED FOR EVALUATION PURPOSES ONLY !!! + +WRAP THOR AI (4.1.0 build 435) +Copyright (c) 2003-2011 Bluegiga Technologies Inc. +Compiled on Jun 28 2011 17:19:51, running on WT12-A module, psr v31 + AVRCP BGIO FTP HFP HFP_AG HID HID_CONSUMER_PAGE HSP LEDS MAP OTA PBAP PIO=0x00fc SSP SUBRATE TEST VOLUME + - BOCK3 version 435 (Jun 28 2011 17:19:37) (max acl/sco 7/1) + - Bluetooth version 2.1, Power class 2 + - Loader 4279, firmware 6297 (56-bit encryption), native execution mode + - up 0 days, 06:23, 2 connections (pool 2) + - User configuration: +&028a = 0001 0000 0000 0011 0024 0000 0000 0010 0000 0080 0000 0000 0080 005f 009b 0034 00fb 0006 +&028b = 0000 0bb8 +&028d = 0001 +&0295 = 0000 0005 000b 0000 0003 0000 0000 0000 0000 0000 0000 +&0298 = a006 +&0299 = 0000 0000 +&02a3 = 0030 0030 0030 0030 +&02a4 = 009d 0000 +&02a5 = 0053 0045 0054 0020 0043 004f 004e 0054 0052 004f 004c 0020 004d 0055 0058 0020 0030 +&02a7 = 0000 05c0 +&02a8 = 4910 0000 0000 +&02aa = 0004 2000 0001 0033 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 +&02ac = 0000 0000 002b 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000 +&02ad = 4848 424b 7020 6f72 4220 0054 +&02b3 = 0005 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 +&02b7 = 000f 4948 0044 +&02bb = 8000 +READY. + + + + +2011/07/07 settings: +set +SET BT BDADDR 00:07:80:47:22:14 +SET BT NAME HHKB Pro BT +SET BT CLASS 0005c0 +SET BT AUTH * 000 +SET BT IDENT BT:47 f000 4.0.0 Bluegiga iWRAP +SET BT LAP 9e8b33 +SET BT PAGEMODE 4 2000 1 +SET BT PAIR 78:dd:08:b7:e4:a2 9e54d0aabb1b4d73cfccddb1ea4ef2d6 +SET BT POWER 3 3 3 +SET BT ROLE 0 f 7d00 +SET BT SNIFF 0 20 1 8 +SET BT SSP 3 0 +SET BT MTU 667 +SET CONTROL BAUD 38400,8n1 +SET CONTROL CD 00 0 +SET CONTROL ECHO 7 +SET CONTROL ESCAPE 255 00 1 +SET CONTROL GAIN 0 5 +SET CONTROL INIT set control mux 0 +SET CONTROL MSC DTE 00 00 00 00 00 00 +SET CONTROL PREAMP 1 1 +SET CONTROL READY 00 +SET PROFILE HID HID +SET PROFILE SPP Bluetooth Serial Port +SET + +info config +WRAP THOR AI (4.0.0 build 317) +Copyright (c) 2003-2010 Bluegiga Technologies Inc. +Compiled on Apr 20 2010 16:44:28, running on WT12-A module, psr v31 + AVRCP FTP PBAP PIO=0x00fc SSP SUBRATE VOLUME + - BOCK3 version 317 (Apr 20 2010 16:44:21) (max acl/sco 7/1) + - Bluetooth version 2.1, Power class 2 + - Loader 4279, firmware 6297 (56-bit encryption), native execution mode + - up 0 days, 00:00, 0 connections (pool 1) + - User configuration: +&028c = 0001 0020 0000 0001 0008 0000 +&028d = 0000 +&0296 = 0047 0001 f000 0400 6c42 6575 6967 6167 6920 5257 5041 +&0298 = c006 +&02a3 = 0030 0030 0030 +&02a4 = 009d 0000 +&02a5 = 0073 0065 0074 0020 0063 006f 006e 0074 0072 006f 006c 0020 006d 0075 0078 0020 0030 +&02a7 = 0000 05c0 +&02a8 = 0800 0000 0000 +&02ac = 0000 0000 00ff 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000 +&02ad = 4848 424b 5020 6f72 4220 0054 +&02b3 = 0004 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 +&02b7 = 0000 +&02bb = 6c42 6575 6f74 746f 2068 6553 6972 6c61 5020 726f 0074 +READY. + + + +2011/08/23: +SET BT BDADDR 00:07:80:47:22:14 +SET BT NAME HHKB pro BT +SET BT CLASS 0005c0 +SET BT AUTH * 0000 +SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP +SET BT LAP 9e8b33 +SET BT PAGEMODE 4 2000 1 +SET BT PAIRCOUNT 4 +SET BT POWER 3 3 3 +SET BT ROLE 1 f 12c0 +SET BT SNIFF 10 2 1 8 +SET BT SSP 3 0 +SET BT MTU 667 +SET CONTROL BAUD 38400,8n1 +SET CONTROL CD 00 0 +SET CONTROL ECHO 7 +SET CONTROL ESCAPE 43 00 1 +SET CONTROL GAIN 0 5 +SET CONTROL INIT SET CONTROL MUX 0 +SET CONTROL MSC DTE 00 00 00 00 00 00 +SET CONTROL MUX 1 +SET CONTROL PIO 00 00 +SET CONTROL READY 00 +SET PROFILE HID 7 HIDKeyboardMouse +SET + +SET CONTROL CONFIG 0000 0004 481e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE DEEP_SLEEP INTERACTIVE_PIN UART_LATENCY 23D_NOKLUDGE + + + +2011/08/25: +SET BT BDADDR 00:07:80:47:22:14 +SET BT NAME HHKB pro BT +SET BT CLASS 0005c0 + +SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP +SET BT LAP 9e8b33 +SET BT PAGEMODE 4 2000 1 +SET BT PAIRCOUNT 4 +SET BT PAIR 78:dd:08:b7:e4:a2 0be83335a03fed8ededae42e99554e28 +SET BT POWER 3 3 3 +SET BT ROLE 1 f 12c0 +SET BT SNIFF 100 20 1 8 +SET BT SSP 3 0 +SET BT MTU 667 +SET CONTROL BAUD 38400,8n1 +SET CONTROL CD 00 0 +SET CONTROL ECHO 7 +SET CONTROL ESCAPE - 20 1 +SET CONTROL GAIN 0 5 +SET CONTROL INIT SET CONTROL MUX 0 +SET CONTROL MSC DTE 00 00 00 00 00 00 +SET CONTROL MUX 1 +SET CONTROL PIO 00 00 +SET CONTROL READY 00 +SET PROFILE HID f HIDKeyboardMouse +SET + + +SET CONTROL CONFIG 0000 0000 490e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE INTERACTIVE_PIN UART_LATENCY + + +2011/09/08: +SET CONTROL CONFIG 0000 0000 410e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE UART_LATENCY + + Removed INTERACTIVE_PIN to avoid interactive auth and use SET BT AUTH pin(0000). + + +EOF diff --git a/iwrap/iwrap.c b/iwrap/iwrap.c new file mode 100644 index 000000000..9c68761bf --- /dev/null +++ b/iwrap/iwrap.c @@ -0,0 +1,467 @@ +/* +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/>. +*/ + +/* host driver for Bulegiga iWRAP */ +/* Bluegiga BT12 + * Connections + * Hardware UART Software UART BlueTooth + * PC=====UART=======AVR=====SUART====iWRAP(BT12)-----------PC + * + * - Hardware UART for Debug Console to communicate iWRAP + * - Software UART for iWRAP control to send keyboard/mouse data + */ + +#include <stdint.h> +#include <string.h> +#include <avr/interrupt.h> +#include <util/delay.h> +#include "usb_keycodes.h" +#include "suart.h" +#include "uart.h" +#include "report.h" +#include "host_driver.h" +#include "iwrap.h" +#include "print.h" + + +/* iWRAP MUX mode utils. 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf) */ +#define MUX_HEADER(LINK, LENGTH) do { \ + xmit(0xbf); /* SOF */ \ + xmit(LINK); /* Link */ \ + xmit(0x00); /* Flags */ \ + xmit(LENGTH); /* Length */ \ +} while (0) +#define MUX_FOOTER(LINK) xmit(LINK^0xff) + + +static uint8_t connected = 0; +//static uint8_t channel = 1; + +/* iWRAP buffer */ +#define MUX_BUF_SIZE 64 +static char buf[MUX_BUF_SIZE]; +static uint8_t snd_pos = 0; + +#define MUX_RCV_BUF_SIZE 256 +static char rcv_buf[MUX_RCV_BUF_SIZE]; +static uint8_t rcv_head = 0; +static uint8_t rcv_tail = 0; + + +/* receive buffer */ +static void rcv_enq(char c) +{ + uint8_t next = (rcv_head + 1) % MUX_RCV_BUF_SIZE; + if (next != rcv_tail) { + rcv_buf[rcv_head] = c; + rcv_head = next; + } +} + +static char rcv_deq(void) +{ + char c = 0; + if (rcv_head != rcv_tail) { + c = rcv_buf[rcv_tail++]; + rcv_tail %= MUX_RCV_BUF_SIZE; + } + return c; +} + +/* +static char rcv_peek(void) +{ + if (rcv_head == rcv_tail) + return 0; + return rcv_buf[rcv_tail]; +} +*/ + +static void rcv_clear(void) +{ + rcv_tail = rcv_head = 0; +} + +/* iWRAP response */ +ISR(PCINT1_vect, ISR_BLOCK) // recv() runs away in case of ISR_NOBLOCK +{ + if ((SUART_IN_PIN & (1<<SUART_IN_BIT))) + return; + + static volatile uint8_t mux_state = 0xff; + static volatile uint8_t mux_link = 0xff; + uint8_t c = recv(); + switch (mux_state) { + case 0xff: // SOF + if (c == 0xbf) + mux_state--; + break; + case 0xfe: // Link + mux_state--; + mux_link = c; + break; + case 0xfd: // Flags + mux_state--; + break; + case 0xfc: // Length + mux_state = c; + break; + case 0x00: + mux_state = 0xff; + mux_link = 0xff; + break; + default: + if (mux_state--) { + uart_putchar(c); + rcv_enq(c); + } + } +} + + +/*------------------------------------------------------------------* + * iWRAP communication + *------------------------------------------------------------------*/ +void iwrap_init(void) +{ + // reset iWRAP if in already MUX mode after AVR software-reset + iwrap_send("RESET"); + iwrap_mux_send("RESET"); + _delay_ms(3000); + iwrap_send("\r\nSET CONTROL MUX 1\r\n"); + _delay_ms(500); + iwrap_check_connection(); +} + +void iwrap_mux_send(const char *s) +{ + rcv_clear(); + MUX_HEADER(0xff, strlen((char *)s)); + iwrap_send(s); + MUX_FOOTER(0xff); +} + +void iwrap_send(const char *s) +{ + while (*s) + xmit(*s++); +} + +/* send buffer */ +void iwrap_buf_add(uint8_t c) +{ + // need space for '\0' + if (snd_pos < MUX_BUF_SIZE-1) + buf[snd_pos++] = c; +} + +void iwrap_buf_del(void) +{ + if (snd_pos) + snd_pos--; +} + +void iwrap_buf_send(void) +{ + buf[snd_pos] = '\0'; + snd_pos = 0; + iwrap_mux_send(buf); +} + +void iwrap_call(void) +{ + char *p; + + iwrap_mux_send("SET BT PAIR"); + _delay_ms(500); + + p = rcv_buf + rcv_tail; + while (!strncmp(p, "SET BT PAIR", 11)) { + p += 7; + strncpy(p, "CALL", 4); + strncpy(p+22, " 11 HID\n\0", 9); + print_S(p); + iwrap_mux_send(p); + // TODO: skip to next line + p += 57; + + DEBUG_LED_CONFIG; + DEBUG_LED_ON; + _delay_ms(500); + DEBUG_LED_OFF; + _delay_ms(500); + DEBUG_LED_ON; + _delay_ms(500); + DEBUG_LED_OFF; + _delay_ms(500); + DEBUG_LED_ON; + _delay_ms(500); + DEBUG_LED_OFF; + _delay_ms(500); + DEBUG_LED_ON; + _delay_ms(500); + DEBUG_LED_OFF; + _delay_ms(500); + DEBUG_LED_ON; + _delay_ms(500); + DEBUG_LED_OFF; + _delay_ms(500); + } + iwrap_check_connection(); +} + +void iwrap_kill(void) +{ + char c; + iwrap_mux_send("LIST"); + _delay_ms(500); + + while ((c = rcv_deq()) && c != '\n') ; + if (strncmp(rcv_buf + rcv_tail, "LIST ", 5)) { + print("no connection to kill.\n"); + return; + } + // skip 10 'space' chars + for (uint8_t i = 10; i; i--) + while ((c = rcv_deq()) && c != ' ') ; + + char *p = rcv_buf + rcv_tail - 5; + strncpy(p, "KILL ", 5); + strncpy(p + 22, "\n\0", 2); + print_S(p); + iwrap_mux_send(p); + _delay_ms(500); + + iwrap_check_connection(); +} + +void iwrap_unpair(void) +{ + iwrap_mux_send("SET BT PAIR"); + _delay_ms(500); + + char *p = rcv_buf + rcv_tail; + if (!strncmp(p, "SET BT PAIR", 11)) { + strncpy(p+29, "\n\0", 2); + print_S(p); + iwrap_mux_send(p); + } +} + +void iwrap_sleep(void) +{ + iwrap_mux_send("SLEEP"); +} + +void iwrap_sniff(void) +{ +} + +void iwrap_subrate(void) +{ +} + +bool iwrap_failed(void) +{ + if (strncmp(rcv_buf, "SYNTAX ERROR", 12)) + return true; + else + return false; +} + +uint8_t iwrap_connected(void) +{ + return connected; +} + +uint8_t iwrap_check_connection(void) +{ + iwrap_mux_send("LIST"); + _delay_ms(100); + + if (strncmp(rcv_buf, "LIST ", 5) || !strncmp(rcv_buf, "LIST 0", 6)) + connected = 0; + else + connected = 1; + return connected; +} + + +/*------------------------------------------------------------------* + * Host driver + *------------------------------------------------------------------*/ +static uint8_t keyboard_leds(void); +static void send_keyboard(report_keyboard_t *report); +static void send_mouse(report_mouse_t *report); +static void send_system(uint16_t data); +static void send_consumer(uint16_t data); + +static host_driver_t driver = { + keyboard_leds, + send_keyboard, + send_mouse, + send_system, + send_consumer +}; + +host_driver_t *iwrap_driver(void) +{ + return &driver; +} + +static uint8_t keyboard_leds(void) { + return 0; +} + +static void send_keyboard(report_keyboard_t *report) +{ + if (!iwrap_connected() && !iwrap_check_connection()) return; + MUX_HEADER(0x01, 0x0c); + // HID raw mode header + xmit(0x9f); + xmit(0x0a); // Length + xmit(0xa1); // keyboard report + xmit(0x01); + xmit(report->mods); + xmit(0x00); // reserved byte(always 0) + xmit(report->keys[0]); + xmit(report->keys[1]); + xmit(report->keys[2]); + xmit(report->keys[3]); + xmit(report->keys[4]); + xmit(report->keys[5]); + MUX_FOOTER(0x01); +} + +static void send_mouse(report_mouse_t *report) +{ +#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE) + if (!iwrap_connected() && !iwrap_check_connection()) return; + MUX_HEADER(0x01, 0x07); + // HID raw mode header + xmit(0x9f); + xmit(0x05); // Length + xmit(0xa1); // mouse report + xmit(0x02); + xmit(report->buttons); + xmit(report->x); + xmit(report->y); + MUX_FOOTER(0x01); +#endif +} + +static void send_system(uint16_t data) +{ + /* not supported */ +} + +static void send_consumer(uint16_t data) +{ +#ifdef EXTRAKEY_ENABLE + static uint16_t last_data = 0; + uint8_t bits1 = 0; + uint8_t bits2 = 0; + uint8_t bits3 = 0; + + if (!iwrap_connected() && !iwrap_check_connection()) return; + if (data == last_data) return; + last_data = data; + + // 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf) + switch (data) { + case AUDIO_VOL_UP: + bits1 = 0x01; + break; + case AUDIO_VOL_DOWN: + bits1 = 0x02; + break; + case AUDIO_MUTE: + bits1 = 0x04; + break; + case TRANSPORT_PLAY_PAUSE: + bits1 = 0x08; + break; + case TRANSPORT_NEXT_TRACK: + bits1 = 0x10; + break; + case TRANSPORT_PREV_TRACK: + bits1 = 0x20; + break; + case TRANSPORT_STOP: + bits1 = 0x40; + break; + case TRANSPORT_EJECT: + bits1 = 0x80; + break; + case AL_EMAIL: + bits2 = 0x01; + break; + case AC_SEARCH: + bits2 = 0x02; + break; + case AC_BOOKMARKS: + bits2 = 0x04; + break; + case AC_HOME: + bits2 = 0x08; + break; + case AC_BACK: + bits2 = 0x10; + break; + case AC_FORWARD: + bits2 = 0x20; + break; + case AC_STOP: + bits2 = 0x40; + break; + case AC_REFRESH: + bits2 = 0x80; + break; + case AL_CC_CONFIG: + bits3 = 0x01; + break; + case AL_CALCULATOR: + bits3 = 0x04; + break; + case AL_LOCK: + bits3 = 0x08; + break; + case AL_LOCAL_BROWSER: + bits3 = 0x10; + break; + case AC_MINIMIZE: + bits3 = 0x20; + break; + case TRANSPORT_RECORD: + bits3 = 0x40; + break; + case TRANSPORT_REWIND: + bits3 = 0x80; + break; + } + + MUX_HEADER(0x01, 0x07); + xmit(0x9f); + xmit(0x05); // Length + xmit(0xa1); // consumer report + xmit(0x03); + xmit(bits1); + xmit(bits2); + xmit(bits3); + MUX_FOOTER(0x01); +#endif +} diff --git a/iwrap/iwrap.h b/iwrap/iwrap.h new file mode 100644 index 000000000..ffaad9395 --- /dev/null +++ b/iwrap/iwrap.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 IWRAP_H +#define IWRAP_H + +#include <stdint.h> +#include <stdbool.h> +#include "host_driver.h" + + +/* enable iWRAP MUX mode */ +#define MUX_MODE + + +host_driver_t *iwrap_driver(void); + +void iwrap_init(void); +void iwrap_send(const char *s); +void iwrap_mux_send(const char *s); +void iwrap_buf_send(void); +void iwrap_buf_add(uint8_t c); +void iwrap_buf_del(void); + +void iwrap_call(void); +void iwrap_kill(void); +void iwrap_unpair(void); +void iwrap_sleep(void); +void iwrap_sniff(void); +void iwrap_subrate(void); +bool iwrap_failed(void); +uint8_t iwrap_connected(void); +uint8_t iwrap_check_connection(void); + +#endif diff --git a/iwrap/main.c b/iwrap/main.c new file mode 100644 index 000000000..a552afb67 --- /dev/null +++ b/iwrap/main.c @@ -0,0 +1,378 @@ +/* +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 <avr/io.h> +//#include <avr/wdt.h> +#include "wd.h" // in order to use watchdog in interrupt mode +#include <avr/sleep.h> +#include <util/delay.h> +#include <avr/power.h> +#include "keyboard.h" +#include "matrix.h" +#include "host.h" +#include "iwrap.h" +#ifdef HOST_VUSB +# include "vusb.h" +# include "usbdrv.h" +#endif +#include "uart.h" +#include "suart.h" +#include "timer.h" +#include "debug.h" +#include "usb_keycodes.h" +#include "command.h" + + +static void sleep(uint8_t term); +static bool console(void); +static uint8_t console_command(uint8_t c); +static uint8_t key2asc(uint8_t key); + + +/* +static void set_prr(void) +{ + power_adc_disable(); + power_spi_disable(); + power_twi_disable(); +#ifndef TIMER_H + //power_timer0_disable(); // used in timer.c +#endif + power_timer1_disable(); + power_timer2_disable(); +} +*/ + +/* +static void pullup_pins(void) +{ + // DDRs are set to 0(input) by default. +#ifdef PORTA + PORTA = 0xFF; +#endif + PORTB = 0xFF; + PORTC = 0xFF; + PORTD = 0xFF; +#ifdef PORTE + PORTE = 0xFF; +#endif +#ifdef PORTE + PORTF = 0xFF; +#endif +} +*/ + + +#ifdef HOST_VUSB +static void disable_vusb(void) +{ + // disable interrupt & disconnect to prevent host from enumerating + USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT); + usbDeviceDisconnect(); +} + +static void enable_vusb(void) +{ + USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); + usbDeviceConnect(); +} + +static void init_vusb(void) +{ + uint8_t i = 0; + + usbInit(); + disable_vusb(); + /* fake USB disconnect for > 250 ms */ + while(--i){ + _delay_ms(1); + } + enable_vusb(); +} +#endif + +void change_driver(host_driver_t *driver) +{ + host_clear_keyboard_report(); + host_swap_keyboard_report(); + host_clear_keyboard_report(); + host_send_keyboard_report(); + _delay_ms(1000); + host_set_driver(driver); +} + + +static bool sleeping = false; +static bool insomniac = false; // TODO: should be false for power saving +static uint16_t last_timer = 0; + +int main(void) +{ + MCUSR = 0; + clock_prescale_set(clock_div_1); + WD_SET(WD_OFF); + + // power saving: the result is worse than nothing... why? + //pullup_pins(); + //set_prr(); + + print_enable = true; + debug_enable = false; + +#ifdef HOST_VUSB + disable_vusb(); +#endif + uart_init(115200); + keyboard_init(); + print("\nSend BREAK for UART Console Commands.\n"); + + // TODO: move to iWRAP/suart file + print("suart init\n"); + // suart init + // PC4: Tx Output IDLE(Hi) + PORTC |= (1<<4); + DDRC |= (1<<4); + // PC5: Rx Input(pull-up) + PORTC |= (1<<5); + DDRC &= ~(1<<5); + // suart receive interrut(PC5/PCINT13) + PCMSK1 = 0b00100000; + PCICR = 0b00000010; + + host_set_driver(iwrap_driver()); + + print("iwrap_init()\n"); + iwrap_init(); + iwrap_call(); + + last_timer = timer_read(); + while (true) { +#ifdef HOST_VUSB + if (host_get_driver() == vusb_driver()) + usbPoll(); +#endif + keyboard_proc(); +#ifdef HOST_VUSB + if (host_get_driver() == vusb_driver()) + vusb_transfer_keyboard(); +#endif + if (matrix_is_modified() || console()) { + last_timer = timer_read(); + sleeping = false; + } else if (!sleeping && timer_elapsed(last_timer) > 4000) { + sleeping = true; + iwrap_check_connection(); + } + + if (host_get_driver() == iwrap_driver()) { + if (sleeping && !insomniac) { + _delay_ms(1); // wait for UART to send + iwrap_sleep(); + sleep(WDTO_60MS); + } + } + } +} + +static void sleep(uint8_t term) +{ + WD_SET(WD_IRQ, term); + + cli(); + set_sleep_mode(SLEEP_MODE_PWR_DOWN); + sleep_enable(); + sleep_bod_disable(); + sei(); + sleep_cpu(); + sleep_disable(); + + WD_SET(WD_OFF); +} + +ISR(WDT_vect) +{ + // wake up +} + +static bool console(void) +{ + // Send to Bluetoot module WT12 + static bool breaked = false; + if (!uart_available()) + return false; + else { + uint8_t c; + c = uart_getchar(); + uart_putchar(c); + switch (c) { + case 0x00: // BREAK signal + if (!breaked) { + print("break(? for help): "); + breaked = true; + } + break; + case '\r': + uart_putchar('\n'); + iwrap_buf_send(); + break; + case '\b': + iwrap_buf_del(); + break; + default: + if (breaked) { + print("\n"); + console_command(c); + breaked = false; + } else { + iwrap_buf_add(c); + } + break; + } + return true; + } +} + +uint8_t command_extra() +{ + return console_command(key2asc(host_get_first_key())); +} + +static uint8_t console_command(uint8_t c) +{ + switch (c) { + case 'h': + case '?': + print("\nCommands for Bluetooth(WT12/iWRAP):\n"); + print("r: reset. software reset by watchdog\n"); + print("i: insomniac. prevent KB from sleeping\n"); + print("c: iwrap_call. CALL for BT connection.\n"); +#ifdef HOST_VUSB + print("u: USB mode. switch to USB.\n"); + print("w: BT mode. switch to Bluetooth.\n"); +#endif + print("k: kill first connection.\n"); + print("Del: unpair first pairing.\n"); + print("\n"); + return 0; + case 'r': + print("reset\n"); + WD_AVR_RESET(); + return 1; + case 'i': + insomniac = !insomniac; + if (insomniac) + print("insomniac\n"); + else + print("not insomniac\n"); + return 1; + case 'c': + print("iwrap_call()\n"); + iwrap_call(); + return 1; +#ifdef HOST_VUSB + case 'u': + print("USB mode\n"); + init_vusb(); + change_driver(vusb_driver()); + //iwrap_kill(); + //iwrap_sleep(); + // disable suart receive interrut(PC5/PCINT13) + PCMSK1 &= ~(0b00100000); + PCICR &= ~(0b00000010); + return 1; + case 'w': + print("iWRAP mode\n"); + change_driver(iwrap_driver()); + disable_vusb(); + // enable suart receive interrut(PC5/PCINT13) + PCMSK1 |= 0b00100000; + PCICR |= 0b00000010; + return 1; +#endif + case 'k': + print("kill\n"); + iwrap_kill(); + return 1; + case 0x7F: // DELETE + print("unpair\n"); + iwrap_unpair(); + return 1; + } + return 0; +} + +// convert keycode into ascii charactor +static uint8_t key2asc(uint8_t key) +{ + switch (key) { + case KB_A: return 'a'; + case KB_B: return 'b'; + case KB_C: return 'c'; + case KB_D: return 'd'; + case KB_E: return 'e'; + case KB_F: return 'f'; + case KB_G: return 'g'; + case KB_H: return 'h'; + case KB_I: return 'i'; + case KB_J: return 'j'; + case KB_K: return 'k'; + case KB_L: return 'l'; + case KB_M: return 'm'; + case KB_N: return 'n'; + case KB_O: return 'o'; + case KB_P: return 'p'; + case KB_Q: return 'q'; + case KB_R: return 'r'; + case KB_S: return 's'; + case KB_T: return 't'; + case KB_U: return 'u'; + case KB_V: return 'v'; + case KB_W: return 'w'; + case KB_X: return 'x'; + case KB_Y: return 'y'; + case KB_Z: return 'z'; + case KB_1: return '1'; + case KB_2: return '2'; + case KB_3: return '3'; + case KB_4: return '4'; + case KB_5: return '5'; + case KB_6: return '6'; + case KB_7: return '7'; + case KB_8: return '8'; + case KB_9: return '9'; + case KB_0: return '0'; + case KB_ENTER: return '\n'; + case KB_ESCAPE: return 0x1B; + case KB_BSPACE: return '\b'; + case KB_TAB: return '\t'; + case KB_SPACE: return ' '; + case KB_MINUS: return '-'; + case KB_EQUAL: return '='; + case KB_LBRACKET: return '['; + case KB_RBRACKET: return ']'; + case KB_BSLASH: return '\\'; + case KB_NONUS_HASH: return '\\'; + case KB_SCOLON: return ';'; + case KB_QUOTE: return '\''; + case KB_GRAVE: return '`'; + case KB_COMMA: return ','; + case KB_DOT: return '.'; + case KB_SLASH: return '/'; + default: return 0x00; + } +} diff --git a/iwrap/suart.S b/iwrap/suart.S new file mode 100644 index 000000000..1b0290963 --- /dev/null +++ b/iwrap/suart.S @@ -0,0 +1,156 @@ +;---------------------------------------------------------------------------;
+; Software implemented UART module ;
+; (C)ChaN, 2005 (http://elm-chan.org/) ;
+;---------------------------------------------------------------------------;
+; Bit rate settings:
+;
+; 1MHz 2MHz 4MHz 6MHz 8MHz 10MHz 12MHz 16MHz 20MHz
+; 2.4kbps 138 - - - - - - - -
+; 4.8kbps 68 138 - - - - - - -
+; 9.6kbps 33 68 138 208 - - - - -
+; 19.2kbps - 33 68 102 138 173 208 - -
+; 38.4kbps - - 33 50 68 85 102 138 172
+; 57.6kbps - - 21 33 44 56 68 91 114
+; 115.2kbps - - - - 21 27 33 44 56
+
+.nolist
+#include <avr/io.h>
+.list
+
+#define BPS 102 /* Bit delay. (see above table) */
+#define BIDIR 0 /* 0:Separated Tx/Rx, 1:Shared Tx/Rx */
+
+#define OUT_1 sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 1 */
+#define OUT_0 cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 0 */
+#define SKIP_IN_1 sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 1 */
+#define SKIP_IN_0 sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 0 */
+
+
+
+#ifdef SPM_PAGESIZE
+.macro _LPMI reg
+ lpm \reg, Z+
+.endm
+.macro _MOVW dh,dl, sh,sl
+ movw \dl, \sl
+.endm
+#else
+.macro _LPMI reg
+ lpm
+ mov \reg, r0
+ adiw ZL, 1
+.endm
+.macro _MOVW dh,dl, sh,sl
+ mov \dl, \sl
+ mov \dh, \sh
+.endm
+#endif
+
+
+
+;---------------------------------------------------------------------------;
+; Transmit a byte in serial format of N81
+;
+;Prototype: void xmit (uint8_t data);
+;Size: 16 words
+
+.global xmit
+.func xmit
+xmit:
+#if BIDIR
+ ldi r23, BPS-1 ;Pre-idle time for bidirectional data line
+5: dec r23 ;
+ brne 5b ;/
+#endif
+ in r0, _SFR_IO_ADDR(SREG) ;Save flags
+
+ com r24 ;C = start bit
+ ldi r25, 10 ;Bit counter
+ cli ;Start critical section
+
+1: ldi r23, BPS-1 ;----- Bit transferring loop
+2: dec r23 ;Wait for a bit time
+ brne 2b ;/
+ brcs 3f ;MISO = bit to be sent
+ OUT_1 ;
+3: brcc 4f ;
+ OUT_0 ;/
+4: lsr r24 ;Get next bit into C
+ dec r25 ;All bits sent?
+ brne 1b ; no, coutinue
+
+ out _SFR_IO_ADDR(SREG), r0 ;End of critical section
+ ret
+.endfunc
+
+
+
+;---------------------------------------------------------------------------;
+; Receive a byte
+;
+;Prototype: uint8_t rcvr (void);
+;Size: 19 words
+
+.global rcvr
+.func rcvr
+rcvr:
+ in r0, _SFR_IO_ADDR(SREG) ;Save flags
+
+ ldi r24, 0x80 ;Receiving shift reg
+ cli ;Start critical section
+
+1: SKIP_IN_1 ;Wait for idle
+ rjmp 1b
+2: SKIP_IN_0 ;Wait for start bit
+ rjmp 2b
+ ldi r25, BPS/2 ;Wait for half bit time
+3: dec r25
+ brne 3b
+
+4: ldi r25, BPS ;----- Bit receiving loop
+5: dec r25 ;Wait for a bit time
+ brne 5b ;/
+ lsr r24 ;Next bit
+ SKIP_IN_0 ;Get a data bit into r24.7
+ ori r24, 0x80
+ brcc 4b ;All bits received? no, continue
+
+ out _SFR_IO_ADDR(SREG), r0 ;End of critical section
+ ret
+.endfunc
+
+
+; Not wait for start bit. This should be called after detecting start bit.
+.global recv
+.func recv
+recv:
+ in r0, _SFR_IO_ADDR(SREG) ;Save flags
+
+ ldi r24, 0x80 ;Receiving shift reg
+ cli ;Start critical section
+
+;1: SKIP_IN_1 ;Wait for idle
+; rjmp 1b
+;2: SKIP_IN_0 ;Wait for start bit
+; rjmp 2b
+ ldi r25, BPS/2 ;Wait for half bit time
+3: dec r25
+ brne 3b
+
+4: ldi r25, BPS ;----- Bit receiving loop
+5: dec r25 ;Wait for a bit time
+ brne 5b ;/
+ lsr r24 ;Next bit
+ SKIP_IN_0 ;Get a data bit into r24.7
+ ori r24, 0x80
+ brcc 4b ;All bits received? no, continue
+
+ ldi r25, BPS/2 ;Wait for half bit time
+6: dec r25
+ brne 6b
+7: SKIP_IN_1 ;Wait for stop bit
+ rjmp 7b
+
+ out _SFR_IO_ADDR(SREG), r0 ;End of critical section
+ ret
+.endfunc
diff --git a/iwrap/suart.h b/iwrap/suart.h new file mode 100644 index 000000000..72725b998 --- /dev/null +++ b/iwrap/suart.h @@ -0,0 +1,8 @@ +#ifndef SUART
+#define SUART
+
+void xmit(uint8_t);
+uint8_t rcvr(void);
+uint8_t recv(void);
+
+#endif /* SUART */
diff --git a/iwrap/wd.h b/iwrap/wd.h new file mode 100644 index 000000000..99058f033 --- /dev/null +++ b/iwrap/wd.h @@ -0,0 +1,159 @@ +/* This is from http://www.mtcnet.net/~henryvm/wdt/ */
+#ifndef _AVR_WD_H_
+#define _AVR_WD_H_
+
+#include <avr/io.h>
+
+/*
+Copyright (c) 2009, Curt Van Maanen
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+include usage-
+ #include "wd.h" //if in same directory as project
+ #include <avr/wd.h> //if wd.h is in avr directory
+
+set watchdog modes and prescale
+
+usage-
+ WD_SET(mode,[timeout]); //prescale always set
+
+modes-
+ WD_OFF disabled
+ WD_RST normal reset mode
+ WD_IRQ interrupt only mode (if supported)
+ WD_RST_IRQ interrupt+reset mode (if supported)
+
+timeout-
+ WDTO_15MS default if no timeout provided
+ WDTO_30MS
+ WDTO_60MS
+ WDTO_120MS
+ WDTO_250MS
+ WDTO_500MS
+ WDTO_1S
+ WDTO_2S
+ WDTO_4S (if supported)
+ WDTO_8S (if supported)
+
+examples-
+ WD_SET(WD_RST,WDTO_1S); //reset mode, 1s timeout
+ WD_SET(WD_OFF); //watchdog disabled (if not fused on)
+ WD_SET(WD_RST); //reset mode, 15ms (default timeout)
+ WD_SET(WD_IRQ,WDTO_120MS); //interrupt only mode, 120ms timeout
+ WD_SET(WD_RST_IRQ,WDTO_2S); //interrupt+reset mode, 2S timeout
+
+
+for enhanced watchdogs, if the watchdog is not being used WDRF should be
+cleared on every power up or reset, along with disabling the watchdog-
+ WD_DISABLE(); //clear WDRF, then turn off watchdog
+
+*/
+
+//reset registers to the same name (MCUCSR)
+#if !defined(MCUCSR)
+#define MCUCSR MCUSR
+#endif
+
+//watchdog registers to the same name (WDTCSR)
+#if !defined(WDTCSR)
+#define WDTCSR WDTCR
+#endif
+
+//if enhanced watchdog, define irq values, create disable macro
+#if defined(WDIF)
+#define WD_IRQ 0xC0
+#define WD_RST_IRQ 0xC8
+#define WD_DISABLE() do{ \
+ MCUCSR &= ~(1<<WDRF); \
+ WD_SET(WD_OFF); \
+ }while(0)
+#endif
+
+//all watchdogs
+#define WD_RST 8
+#define WD_OFF 0
+
+//prescale values
+#define WDTO_15MS 0
+#define WDTO_30MS 1
+#define WDTO_60MS 2
+#define WDTO_120MS 3
+#define WDTO_250MS 4
+#define WDTO_500MS 5
+#define WDTO_1S 6
+#define WDTO_2S 7
+
+//prescale values for avrs with WDP3
+#if defined(WDP3)
+#define WDTO_4S 0x20
+#define WDTO_8S 0x21
+#endif
+
+//watchdog reset
+#define WDR() __asm__ __volatile__("wdr")
+
+//avr reset using watchdog
+#define WD_AVR_RESET() do{ \
+ __asm__ __volatile__("cli"); \
+ WD_SET_UNSAFE(WD_RST); \
+ while(1); \
+ }while(0)
+
+/*set the watchdog-
+1. save SREG
+2. turn off irq's
+3. reset watchdog timer
+4. enable watchdog change
+5. write watchdog value
+6. restore SREG (restoring irq status)
+*/
+#define WD_SET(val,...) \
+ __asm__ __volatile__( \
+ "in __tmp_reg__,__SREG__" "\n\t" \
+ "cli" "\n\t" \
+ "wdr" "\n\t" \
+ "sts %[wdreg],%[wden]" "\n\t" \
+ "sts %[wdreg],%[wdval]" "\n\t" \
+ "out __SREG__,__tmp_reg__" "\n\t" \
+ : \
+ : [wdreg] "M" (&WDTCSR), \
+ [wden] "r" ((uint8_t)(0x18)), \
+ [wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0))) \
+ : "r0" \
+)
+
+/*set the watchdog when I bit in SREG known to be clear-
+1. reset watchdog timer
+2. enable watchdog change
+5. write watchdog value
+*/
+#define WD_SET_UNSAFE(val,...) \
+ __asm__ __volatile__( \
+ "wdr" "\n\t" \
+ "sts %[wdreg],%[wden]" "\n\t" \
+ "sts %[wdreg],%[wdval]" "\n\t" \
+ : \
+ : [wdreg] "M" (&WDTCSR), \
+ [wden] "r" ((uint8_t)(0x18)), \
+ [wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0))) \
+)
+
+
+//for compatibility with avr/wdt.h
+#define wdt_enable(val) WD_SET(WD_RST,val)
+#define wdt_disable() WD_SET(WD_OFF)
+
+
+#endif /* _AVR_WD_H_ */
diff --git a/keyboard.c b/keyboard.c index 9bba409f1..5c2643c95 100644 --- a/keyboard.c +++ b/keyboard.c @@ -27,7 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifdef MOUSEKEY_ENABLE #include "mousekey.h" #endif -#ifdef USB_EXTRA_ENABLE +#ifdef EXTRAKEY_ENABLE #include <util/delay.h> #endif @@ -47,7 +47,7 @@ void keyboard_init(void) void keyboard_proc(void) { uint8_t fn_bits = 0; -#ifdef USB_EXTRA_ENABLE +#ifdef EXTRAKEY_ENABLE uint16_t consumer_code = 0; #endif @@ -82,7 +82,8 @@ void keyboard_proc(void) } else if (IS_FN(code)) { fn_bits |= FN_BIT(code); } -#ifdef USB_EXTRA_ENABLE +// TODO: use table or something +#ifdef EXTRAKEY_ENABLE // System Control else if (code == KB_SYSTEM_POWER) { #ifdef HOST_PJRC @@ -170,7 +171,7 @@ void keyboard_proc(void) // TODO: should send only when changed from last report if (matrix_is_modified()) { host_send_keyboard_report(); -#ifdef USB_EXTRA_ENABLE +#ifdef EXTRAKEY_ENABLE host_consumer_send(consumer_code); #endif #ifdef DEBUG_LED @@ -69,10 +69,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ // LAYER_ENTER_DELAY: prevent from moving new layer -#define LAYER_ENTER_DELAY 10 +#define LAYER_ENTER_DELAY 150 // LAYER_SEND_FN_TERM: send keycode if release key in this term -#define LAYER_SEND_FN_TERM 40 +#define LAYER_SEND_FN_TERM 500 uint8_t default_layer = 0; diff --git a/macway/Makefile b/macway/Makefile index 6e7fa7fd9..b8b0a85e1 100644 --- a/macway/Makefile +++ b/macway/Makefile @@ -8,10 +8,10 @@ COMMON_DIR = .. TARGET_DIR = . # keyboard dependent files -TARGET_SRC = main_pjrc.c \ - keymap.c \ - matrix.c \ - led.c +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c CONFIG_H = config.h @@ -37,8 +37,8 @@ F_CPU = 16000000 # MOUSEKEY_ENABLE = yes # Mouse keys #PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support -USB_EXTRA_ENABLE = yes # Audio control and System control -#USB_NKRO_ENABLE = yes # USB Nkey Rollover +EXTRAKEY_ENABLE = yes # Audio control and System control +#NKRO_ENABLE = yes # USB Nkey Rollover @@ -47,5 +47,5 @@ PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex -include $(COMMON_DIR)/Makefile.pjrc -include $(COMMON_DIR)/Makefile.common +include $(COMMON_DIR)/pjrc.mk +include $(COMMON_DIR)/common.mk diff --git a/macway/config.h b/macway/config.h index ff62bfdb0..546067beb 100644 --- a/macway/config.h +++ b/macway/config.h @@ -37,8 +37,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. /* key combination for command */ #define IS_COMMAND() ( \ - keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \ - keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_LCTRL) | MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) || \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) \ ) diff --git a/macway/doc/back.jpg b/macway/doc/back.jpg Binary files differindex 0774401f6..0774401f6 100755..100644 --- a/macway/doc/back.jpg +++ b/macway/doc/back.jpg diff --git a/macway/doc/case.jpg b/macway/doc/case.jpg Binary files differindex c776d5e05..c776d5e05 100755..100644 --- a/macway/doc/case.jpg +++ b/macway/doc/case.jpg diff --git a/macway/doc/keys.jpg b/macway/doc/keys.jpg Binary files differindex f340ebe8e..f340ebe8e 100755..100644 --- a/macway/doc/keys.jpg +++ b/macway/doc/keys.jpg diff --git a/macway/doc/side.jpg b/macway/doc/side.jpg Binary files differindex bdf8268f2..bdf8268f2 100755..100644 --- a/macway/doc/side.jpg +++ b/macway/doc/side.jpg diff --git a/macway/doc/switch.jpg b/macway/doc/switch.jpg Binary files differindex a1500d707..a1500d707 100755..100644 --- a/macway/doc/switch.jpg +++ b/macway/doc/switch.jpg diff --git a/macway/doc/teensy.jpg b/macway/doc/teensy.jpg Binary files differindex 07207475d..07207475d 100755..100644 --- a/macway/doc/teensy.jpg +++ b/macway/doc/teensy.jpg diff --git a/macway/doc/wiring.jpg b/macway/doc/wiring.jpg Binary files differindex 0f3490f10..0f3490f10 100755..100644 --- a/macway/doc/wiring.jpg +++ b/macway/doc/wiring.jpg diff --git a/macway/doc/withHHKB.jpg b/macway/doc/withHHKB.jpg Binary files differindex 9921856e7..9921856e7 100755..100644 --- a/macway/doc/withHHKB.jpg +++ b/macway/doc/withHHKB.jpg diff --git a/macway/doc/withThinkPad.jpg b/macway/doc/withThinkPad.jpg Binary files differindex 231c61d03..231c61d03 100755..100644 --- a/macway/doc/withThinkPad.jpg +++ b/macway/doc/withThinkPad.jpg diff --git a/main_vusb.c b/main_vusb.c deleted file mode 100644 index 017888e97..000000000 --- a/main_vusb.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Name: main.c - * Project: hid-mouse, a very simple HID example - * Author: Christian Starkjohann - * Creation Date: 2008-04-07 - * Tabsize: 4 - * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - * This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $ - */ -#include <stdint.h> -#include <avr/wdt.h> -#include <avr/interrupt.h> -#include <util/delay.h> -#include "usbdrv.h" -#include "oddebug.h" -#include "host_vusb.h" -#include "keyboard.h" - - -#if 0 -#define DEBUGP_INIT() do { DDRC = 0xFF; } while (0) -#define DEBUGP(x) do { PORTC = x; } while (0) -#else -#define DEBUGP_INIT() -#define DEBUGP(x) -#endif - - -int main(void) -{ - DEBUGP_INIT(); - wdt_enable(WDTO_1S); - odDebugInit(); - usbInit(); - - /* enforce re-enumeration, do this while interrupts are disabled! */ - usbDeviceDisconnect(); - uint8_t i = 0; - /* fake USB disconnect for > 250 ms */ - while(--i){ - wdt_reset(); - _delay_ms(1); - } - usbDeviceConnect(); - - keyboard_init(); - - sei(); - while (1) { - DEBUGP(0x1); - wdt_reset(); - usbPoll(); - DEBUGP(0x2); - keyboard_proc(); - DEBUGP(0x3); - host_vusb_keyboard_send(); - } -} diff --git a/mousekey.c b/mousekey.c index 69b75240f..76bd0fd36 100644..100755 --- a/mousekey.c +++ b/mousekey.c @@ -63,10 +63,10 @@ void mousekey_decode(uint8_t code) 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 += 1; - else if (code == KB_MS_WH_DOWN) report.v -= 1; - else if (code == KB_MS_WH_LEFT) report.h -= 1; - else if (code == KB_MS_WH_RIGHT)report.h += 1; + 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) @@ -87,7 +87,7 @@ void mousekey_send(void) // send immediately when buttun state is changed if (report.buttons == report_prev.buttons) { - if (timer_elapsed(last_timer) < 5) { + if (timer_elapsed(last_timer) < 100) { mousekey_clear_report(); return; } diff --git a/Makefile.pjrc b/pjrc.mk index 894d4dcee..0bc47ac93 100644 --- a/Makefile.pjrc +++ b/pjrc.mk @@ -1,14 +1,14 @@ OPT_DEFS += -DHOST_PJRC -SRC = usb_keyboard.c \ +SRC += pjrc.c \ + usb_keyboard.c \ usb_debug.c \ usb.c \ jump_bootloader.c -SRC += $(TARGET_SRC) -# C source file search path -VPATH = $(TARGET_DIR):$(COMMON_DIR):$(COMMON_DIR)/pjrc +# Search Path +VPATH += $(COMMON_DIR):$(COMMON_DIR)/pjrc # Option modules @@ -16,6 +16,6 @@ ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) SRC += usb_mouse.c endif -ifdef USB_EXTRA_ENABLE +ifdef EXTRAKEY_ENABLE SRC += usb_extra.c endif diff --git a/pjrc/host.c b/pjrc/host.c index 35d59de80..fcf71d579 100644 --- a/pjrc/host.c +++ b/pjrc/host.c @@ -22,7 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE) #include "usb_mouse.h" #endif -#ifdef USB_EXTRA_ENABLE +#ifdef EXTRAKEY_ENABLE #include "usb_extra.h" #endif #include "debug.h" @@ -30,7 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "util.h" -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE bool keyboard_nkro = false; #endif @@ -51,7 +51,7 @@ uint8_t host_keyboard_leds(void) /* keyboard report operations */ void host_add_key(uint8_t key) { -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE if (keyboard_nkro) { add_key_bit(key); return; @@ -109,7 +109,7 @@ uint8_t host_has_anykey(void) uint8_t host_get_first_key(void) { -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE if (keyboard_nkro) { uint8_t i = 0; for (; i < REPORT_KEYS && !keyboard_report->keys[i]; i++) @@ -133,7 +133,7 @@ void host_mouse_send(report_mouse_t *report) } #endif -#ifdef USB_EXTRA_ENABLE +#ifdef EXTRAKEY_ENABLE void host_system_send(uint16_t data) { usb_extra_system_send(data); diff --git a/main_pjrc.c b/pjrc/main.c index 6ba62040d..f84925d7f 100644 --- a/main_pjrc.c +++ b/pjrc/main.c @@ -35,6 +35,8 @@ #ifdef PS2_MOUSE_ENABLE # include "ps2_mouse.h" #endif +#include "host.h" +#include "pjrc.h" #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) @@ -88,6 +90,7 @@ int main(void) } + host_set_driver(pjrc_driver()); while (1) { keyboard_proc(); } diff --git a/pjrc/pjrc.c b/pjrc/pjrc.c new file mode 100644 index 000000000..0562a12ff --- /dev/null +++ b/pjrc/pjrc.c @@ -0,0 +1,76 @@ +/* +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 "usb_keyboard.h" +#include "usb_mouse.h" +#include "usb_extra.h" +#include "host_driver.h" +#include "pjrc.h" + + +/*------------------------------------------------------------------* + * Host driver + *------------------------------------------------------------------*/ +static uint8_t keyboard_leds(void); +static void send_keyboard(report_keyboard_t *report); +static void send_mouse(report_mouse_t *report); +static void send_system(uint16_t data); +static void send_consumer(uint16_t data); + +static host_driver_t driver = { + keyboard_leds, + send_keyboard, + send_mouse, + send_system, + send_consumer +}; + +host_driver_t *pjrc_driver(void) +{ + return &driver; +} + +static uint8_t keyboard_leds(void) { + return usb_keyboard_leds; +} + +static void send_keyboard(report_keyboard_t *report) +{ + usb_keyboard_send_report(report); +} + +static void send_mouse(report_mouse_t *report) +{ +#ifdef MOUSE_ENABLE + usb_mouse_send(report->x, report->y, report->v, report->h, report->buttons); +#endif +} + +static void send_system(uint16_t data) +{ +#ifdef EXTRAKEY_ENABLE + usb_extra_system_send(data); +#endif +} + +static void send_consumer(uint16_t data) +{ +#ifdef EXTRAKEY_ENABLE + usb_extra_consumer_send(data); +#endif +} diff --git a/pjrc/pjrc.h b/pjrc/pjrc.h new file mode 100644 index 000000000..06e79626f --- /dev/null +++ b/pjrc/pjrc.h @@ -0,0 +1,26 @@ +/* +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 PJRC_H +#define PJRC_H + +#include "host_driver.h" + + +host_driver_t *pjrc_driver(void); + +#endif diff --git a/pjrc/usb.c b/pjrc/usb.c index ea2e71b3d..9989a4b2d 100644 --- a/pjrc/usb.c +++ b/pjrc/usb.c @@ -91,18 +91,18 @@ bool suspend = false; static const uint8_t PROGMEM endpoint_config_table[] = { // enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation) 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD_SIZE) | KBD_BUFFER, // 1 -#ifdef USB_MOUSE_ENABLE +#ifdef MOUSE_ENABLE 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, // 2 #else 0, // 2 #endif 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3 -#ifdef USB_EXTRA_ENABLE +#ifdef EXTRAKEY_ENABLE 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(EXTRA_SIZE) | EXTRA_BUFFER, // 4 #else 0, // 4 #endif -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD2_SIZE) | KBD2_BUFFER, // 5 #else 0, // 5 @@ -176,7 +176,7 @@ static uint8_t PROGMEM keyboard_hid_report_desc[] = { 0x81, 0x00, // Input (Data, Array), 0xc0 // End Collection }; -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE static uint8_t PROGMEM keyboard2_hid_report_desc[] = { 0x05, 0x01, // Usage Page (Generic Desktop), 0x09, 0x06, // Usage (Keyboard), @@ -213,7 +213,7 @@ static uint8_t PROGMEM keyboard2_hid_report_desc[] = { }; #endif -#ifdef USB_MOUSE_ENABLE +#ifdef MOUSE_ENABLE // Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension // http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521 // http://www.keil.com/forum/15671/ @@ -282,7 +282,7 @@ static uint8_t PROGMEM debug_hid_report_desc[] = { 0xC0 // end collection }; -#ifdef USB_EXTRA_ENABLE +#ifdef EXTRAKEY_ENABLE // audio controls & system controls // http://www.microsoft.com/whdc/archive/w2kbd.mspx static uint8_t PROGMEM extra_hid_report_desc[] = { @@ -318,7 +318,7 @@ static uint8_t PROGMEM extra_hid_report_desc[] = { #define KBD_HID_DESC_NUM 0 #define KBD_HID_DESC_OFFSET (9+(9+9+7)*KBD_HID_DESC_NUM+9) -#ifdef USB_MOUSE_ENABLE +#ifdef MOUSE_ENABLE # define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 1) # define MOUSE_HID_DESC_OFFSET (9+(9+9+7)*MOUSE_HID_DESC_NUM+9) #else @@ -328,14 +328,14 @@ static uint8_t PROGMEM extra_hid_report_desc[] = { #define DEBUG_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 1) #define DEBUG_HID_DESC_OFFSET (9+(9+9+7)*DEBUG_HID_DESC_NUM+9) -#ifdef USB_EXTRA_ENABLE +#ifdef EXTRAKEY_ENABLE # define EXTRA_HID_DESC_NUM (DEBUG_HID_DESC_NUM + 1) # define EXTRA_HID_DESC_OFFSET (9+(9+9+7)*EXTRA_HID_DESC_NUM+9) #else # define EXTRA_HID_DESC_NUM (DEBUG_HID_DESC_NUM + 0) #endif -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE # define KBD2_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 1) # define KBD2_HID_DESC_OFFSET (9+(9+9+7)*EXTRA_HID_DESC_NUM+9) #else @@ -383,7 +383,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { KBD_SIZE, 0, // wMaxPacketSize 10, // bInterval -#ifdef USB_MOUSE_ENABLE +#ifdef MOUSE_ENABLE // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType @@ -444,7 +444,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { DEBUG_TX_SIZE, 0, // wMaxPacketSize 1, // bInterval -#ifdef USB_EXTRA_ENABLE +#ifdef EXTRAKEY_ENABLE // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType @@ -473,7 +473,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { 10, // bInterval #endif -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType @@ -542,17 +542,17 @@ static struct descriptor_list_struct { // HID/REPORT descriptors {0x2100, KBD_INTERFACE, config1_descriptor+KBD_HID_DESC_OFFSET, 9}, {0x2200, KBD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, -#ifdef USB_MOUSE_ENABLE +#ifdef MOUSE_ENABLE {0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9}, {0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)}, #endif {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9}, {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)}, -#ifdef USB_EXTRA_ENABLE +#ifdef EXTRAKEY_ENABLE {0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9}, {0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)}, #endif -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE {0x2100, KBD2_INTERFACE, config1_descriptor+KBD2_HID_DESC_OFFSET, 9}, {0x2200, KBD2_INTERFACE, keyboard2_hid_report_desc, sizeof(keyboard2_hid_report_desc)}, #endif @@ -653,7 +653,7 @@ ISR(USB_GEN_vect) } } /* TODO: should keep IDLE rate on each keyboard interface */ -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE if (!keyboard_nkro && usb_keyboard_idle_config && (++div4 & 3) == 0) { #else if (usb_keyboard_idle_config && (++div4 & 3) == 0) { @@ -894,7 +894,7 @@ ISR(USB_COM_vect) } } } -#ifdef USB_MOUSE_ENABLE +#ifdef MOUSE_ENABLE if (wIndex == MOUSE_INTERFACE) { if (bmRequestType == 0xA1) { if (bRequest == HID_GET_REPORT) { diff --git a/pjrc/usb.h b/pjrc/usb.h index a4e40bdd1..82e18f176 100644 --- a/pjrc/usb.h +++ b/pjrc/usb.h @@ -120,7 +120,7 @@ void usb_remote_wakeup(void); #define KBD_REPORT_KEYS (KBD_SIZE - 2) // secondary keyboard -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE #define KBD2_INTERFACE 4 #define KBD2_ENDPOINT 5 #define KBD2_SIZE 16 diff --git a/pjrc/usb_keyboard.c b/pjrc/usb_keyboard.c index 34e9d495b..e057c77fa 100644 --- a/pjrc/usb_keyboard.c +++ b/pjrc/usb_keyboard.c @@ -55,7 +55,7 @@ int8_t usb_keyboard_send_report(report_keyboard_t *report) { int8_t result = 0; -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE if (keyboard_nkro) result = send_report(report, KBD2_ENDPOINT, 0, KBD2_REPORT_KEYS); else @@ -105,7 +105,7 @@ static inline int8_t send_report(report_keyboard_t *report, uint8_t endpoint, ui UENUM = endpoint; } UEDATX = report->mods; -#ifdef USB_NKRO_ENABLE +#ifdef NKRO_ENABLE if (!keyboard_nkro) UEDATX = 0; #else @@ -29,6 +29,19 @@ 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; @@ -24,6 +24,7 @@ #ifndef PRINT_H__ #define PRINT_H__ 1 +#include <stdint.h> #include <stdbool.h> #include <avr/pgmspace.h> @@ -34,6 +35,7 @@ extern bool print_enable; // 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); diff --git a/ps2_usb/Makefile b/ps2_usb/Makefile index a548b56d4..7352f6b13 100644 --- a/ps2_usb/Makefile +++ b/ps2_usb/Makefile @@ -13,11 +13,11 @@ COMMON_DIR = .. TARGET_DIR = . # keyboard dependent files -TARGET_SRC = main_pjrc.c \ - keymap.c \ - matrix.c \ - led.c \ - ps2.c +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c \ + ps2.c CONFIG_H = config_pjrc.h @@ -42,8 +42,8 @@ F_CPU = 16000000 # comment out to disable the options. # MOUSEKEY_ENABLE = yes # Mouse keys -USB_EXTRA_ENABLE = yes # Audio control and System control -USB_NKRO_ENABLE = yes # USB Nkey Rollover +EXTRAKEY_ENABLE = yes # Audio control and System control +NKRO_ENABLE = yes # USB Nkey Rollover @@ -52,5 +52,5 @@ PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex -include $(COMMON_DIR)/Makefile.pjrc -include $(COMMON_DIR)/Makefile.common +include $(COMMON_DIR)/pjrc.mk +include $(COMMON_DIR)/common.mk diff --git a/ps2_usb/Makefile.vusb b/ps2_usb/Makefile.vusb index ff86d7998..5b6978f01 100644 --- a/ps2_usb/Makefile.vusb +++ b/ps2_usb/Makefile.vusb @@ -13,11 +13,11 @@ COMMON_DIR = .. TARGET_DIR = . # keyboard dependent files -TARGET_SRC = main_vusb.c \ - keymap.c \ - matrix.c \ - led.c \ - ps2_usart.c +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c \ + ps2_usart.c CONFIG_H = config_vusb.h @@ -48,8 +48,9 @@ F_CPU = 20000000 # comment out to disable the options. # MOUSEKEY_ENABLE = yes # Mouse keys -USB_EXTRA_ENABLE = yes # Audio control and System control -#USB_NKRO_ENABLE = yes # USB Nkey Rollover +EXTRAKEY_ENABLE = yes # Audio control and System control +#NKRO_ENABLE = yes # USB Nkey Rollover +NO_UART = yes # UART is unavailable @@ -85,5 +86,5 @@ PROGRAM_CMD = $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE -include $(COMMON_DIR)/Makefile.vusb -include $(COMMON_DIR)/Makefile.common +include $(COMMON_DIR)/vusb.mk +include $(COMMON_DIR)/common.mk diff --git a/ps2_usb/config_pjrc.h b/ps2_usb/config_pjrc.h index 56917beec..883ffab27 100644 --- a/ps2_usb/config_pjrc.h +++ b/ps2_usb/config_pjrc.h @@ -35,8 +35,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. /* key combination for command */ #define IS_COMMAND() ( \ - keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \ - keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \ + keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ ) diff --git a/ps2_usb/config_vusb.h b/ps2_usb/config_vusb.h index 426bb61e2..afd2f7911 100644 --- a/ps2_usb/config_vusb.h +++ b/ps2_usb/config_vusb.h @@ -35,8 +35,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. /* key combination for command */ #define IS_COMMAND() ( \ - keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \ - keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \ + keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ ) diff --git a/ps2_usb/keymap.c b/ps2_usb/keymap.c index ef11daa28..e84e8c29b 100644 --- a/ps2_usb/keymap.c +++ b/ps2_usb/keymap.c @@ -124,7 +124,7 @@ static const uint8_t PROGMEM fn_layer[] = { static const uint8_t PROGMEM fn_keycode[] = { KB_SCLN, // Fn0 KB_SLSH, // Fn1 - KB_A, // Fn2 + KB_NO, // Fn2 KB_NO, // Fn3 KB_NO, // Fn4 KB_NO, // Fn5 @@ -154,7 +154,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, - CAPS,FN2, S, D, F, G, H, J, K, L, FN0, QUOT, ENT, P4, P5, P6, PPLS, + CAPS,A, S, D, F, G, H, J, K, L, FN0, QUOT, ENT, P4, P5, P6, PPLS, LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN1, RSFT, UP, P1, P2, P3, LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT ), @@ -204,7 +204,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, TAB, WH_L,WH_D,MS_U,WH_U,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9, - CAPS,FN2, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN0, NO, ENT, P4, P5, P6, PPLS, + CAPS,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN0, NO, ENT, P4, P5, P6, PPLS, LSFT,VOLD,VOLU,MUTE,BTN2,BTN3,BTN2,BTN1,VOLD,VOLU,MUTE, RSFT, UP, P1, P2, P3, LCTL,LGUI,LALT, BTN1, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT ), diff --git a/ps2_usb/matrix.c b/ps2_usb/matrix.c index 5d73cc2a3..1aac3f866 100644 --- a/ps2_usb/matrix.c +++ b/ps2_usb/matrix.c @@ -349,6 +349,7 @@ uint8_t matrix_scan(void) default: state = INIT; } + phex(code); } return 1; } diff --git a/report.h b/report.h new file mode 100644 index 000000000..b85b86c5f --- /dev/null +++ b/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/Makefile.rules b/rules.mk index f1d0a301c..f1d0a301c 100644 --- a/Makefile.rules +++ b/rules.mk diff --git a/sendchar.h b/sendchar.h index b31665441..7c81303c7 100644 --- a/sendchar.h +++ b/sendchar.h @@ -18,8 +18,10 @@ 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/vusb/host_vusb.h b/sendchar_null.c index be9886e88..293330622 100644 --- a/vusb/host_vusb.h +++ b/sendchar_null.c @@ -14,10 +14,10 @@ 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" -#ifndef HOST_VUSB_H -#define HOST_VUSB_H -void host_vusb_keyboard_send(void); - -#endif +int8_t sendchar(uint8_t c) +{ + return 0; +} diff --git a/sendchar_uart.c b/sendchar_uart.c new file mode 100644 index 000000000..0241859eb --- /dev/null +++ b/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; +} @@ -20,17 +20,31 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include <stdint.h> #include "timer.h" + +// counter resolution 1ms volatile uint16_t timer_count = 0; -// Configure timer 0 to generate a timer overflow interrupt every -// 256*1024 clock cycles, or approx 61 Hz when using 16 MHz clock -// This demonstrates how to use interrupts to implement a simple -// inactivity timeout. void timer_init(void) { - TCCR0A = 0x00; + // 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; - TIMSK0 = (1<<TOIE0); +#else +# error "Timer prescaler value is NOT vaild." +#endif + + OCR0A = TIMER_RAW_TOP; + TIMSK0 = (1<<OCIE0A); } inline @@ -65,14 +79,11 @@ uint16_t timer_elapsed(uint16_t last) t = timer_count; SREG = sreg; - return TIMER_DIFF(t, last); + return TIMER_DIFF_MS(t, last); } -// This interrupt routine is run approx 61 times per second. -// A very simple inactivity timeout is implemented, where we -// will send a space character and print a message to the -// hid_listen debug message window. -ISR(TIMER0_OVF_vect) +// excecuted once per 1ms.(excess for just timer count?) +ISR(TIMER0_COMPA_vect) { timer_count++; } @@ -20,7 +20,26 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include <stdint.h> -#define TIMER_DIFF(a, b) ((a) >= (b) ? (a) - (b) : UINT16_MAX - (b) + (a)) +#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; @@ -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; + } +} + @@ -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/usb_keycodes.h b/usb_keycodes.h index 8b8d4d350..391d21f20 100644 --- a/usb_keycodes.h +++ b/usb_keycodes.h @@ -16,7 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* - * Key codes from HID Keyboard/Keypad Page + * Key codes: HID Keyboard/Keypad Page(0x07) * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf */ #ifndef USB_KEYCODES_H @@ -353,7 +353,8 @@ enum keycodes { KB_CRSEL, KB_EXSEL, - /* NOTE: uses 0xB0-DF for special keycodes */ + /* NOTE: 0xB0-DF are used as special_keycodes */ +#if 0 KB_KP_00 = 0xB0, KB_KP_000, KB_THOUSANDS_SEPARATOR, @@ -400,6 +401,7 @@ enum keycodes { KB_KP_OCTAL, KB_KP_DECIMAL, KB_KP_HEXADECIMAL, +#endif /* Modifiers */ KB_LCTRL = 0xE0, @@ -411,7 +413,7 @@ enum keycodes { KB_RALT, KB_RGUI, - /* NOTE: uses 0xE8-FF for special keycodes */ + /* NOTE: 0xE8-FF are used as special_keycodes */ }; #endif /* USB_KEYCODES_H */ diff --git a/vusb.mk b/vusb.mk new file mode 100644 index 000000000..7fd5dc054 --- /dev/null +++ b/vusb.mk @@ -0,0 +1,17 @@ +OPT_DEFS += -DHOST_VUSB + +SRC += vusb.c \ + usbdrv.c \ + usbdrvasm.S \ + oddebug.c + +ifdef NO_UART +SRC += sendchar_null.c +else +SRC += sendchar_uart.c \ + uart.c +endif + + +# Search Path +VPATH += $(COMMON_DIR)/vusb:$(COMMON_DIR)/vusb/usbdrv diff --git a/vusb/main.c b/vusb/main.c new file mode 100644 index 000000000..1bf9035b3 --- /dev/null +++ b/vusb/main.c @@ -0,0 +1,99 @@ +/* Name: main.c + * Project: hid-mouse, a very simple HID example + * Author: Christian Starkjohann + * Creation Date: 2008-04-07 + * Tabsize: 4 + * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH + * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) + * This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $ + */ +#include <stdint.h> +#include <avr/interrupt.h> +#include <avr/wdt.h> +#include <avr/sleep.h> +#include <util/delay.h> +#include "usbdrv.h" +#include "oddebug.h" +#include "vusb.h" +#include "keyboard.h" +#include "host.h" +#include "timer.h" +#include "uart.h" +#include "debug.h" + + +#define UART_BAUD_RATE 115200 + + +/* This is from main.c of USBaspLoader */ +static void initForUsbConnectivity(void) +{ + uint8_t i = 0; + + usbInit(); + /* enforce USB re-enumerate: */ + usbDeviceDisconnect(); /* do this while interrupts are disabled */ + while(--i){ /* fake USB disconnect for > 250 ms */ + wdt_reset(); + _delay_ms(1); + } + usbDeviceConnect(); + sei(); +} + +int main(void) +{ + bool suspended = false; +#if USB_COUNT_SOF + uint16_t last_timer = timer_read(); +#endif + + CLKPR = 0x80, CLKPR = 0; +#ifndef PS2_USE_USART + uart_init(UART_BAUD_RATE); +#endif + + debug_enable = true; + print_enable = true; + + debug("keyboard_init()\n"); + keyboard_init(); + host_set_driver(vusb_driver()); + + debug("initForUsbConnectivity()\n"); + initForUsbConnectivity(); + + debug("main loop\n"); + while (1) { +#if USB_COUNT_SOF + if (usbSofCount != 0) { + suspended = false; + usbSofCount = 0; + last_timer = timer_read(); + } else { + // Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1) + if (timer_elapsed(last_timer) > 5) { + suspended = true; +/* + uart_putchar('S'); + _delay_ms(1); + cli(); + set_sleep_mode(SLEEP_MODE_PWR_DOWN); + sleep_enable(); + sleep_bod_disable(); + sei(); + sleep_cpu(); + sleep_disable(); + _delay_ms(10); + uart_putchar('W'); +*/ + } + } +#endif + if (!suspended) + usbPoll(); + keyboard_proc(); + if (!suspended) + vusb_transfer_keyboard(); + } +} diff --git a/vusb/host.c b/vusb/vusb.c index 8cd38d0b3..638611f32 100644 --- a/vusb/host.c +++ b/vusb/vusb.c @@ -16,133 +16,69 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <stdint.h> -#include <avr/interrupt.h> #include "usbdrv.h" #include "usbconfig.h" -#include "print.h" -#include "usb_keycodes.h" #include "host.h" -#include "host_vusb.h" +#include "report.h" +#include "print.h" #include "debug.h" +#include "host_driver.h" +#include "vusb.h" -static report_keyboard_t report0; -static report_keyboard_t report1; -report_keyboard_t *keyboard_report = &report0; -report_keyboard_t *keyboard_report_prev = &report1; - -static uint8_t keyboard_leds = 0; -static uchar idleRate = 0; - -uint8_t host_keyboard_leds(void) -{ - return keyboard_leds; -} - - -/*------------------------------------------------------------------* - * Keyboard report operations - *------------------------------------------------------------------*/ -void host_add_key(uint8_t 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] == KB_NO && keyboard_report->keys[i] == KB_NO) { - empty = i; - } - } - if (i == REPORT_KEYS && empty != -1) { - keyboard_report->keys[empty] = code; - } -} - -void host_add_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_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; -} +static uint8_t vusb_keyboard_leds = 0; +static uint8_t vusb_idle_rate = 0; -void host_clear_keyboard_report(void) -{ - keyboard_report->mods = 0; - for (int8_t i = 0; i < REPORT_KEYS; i++) { - keyboard_report->keys[i] = 0; - } -} +/* Keyboard report send buffer */ +#define KBUF_SIZE 16 +static report_keyboard_t kbuf[KBUF_SIZE]; +static uint8_t kbuf_head = 0; +static uint8_t kbuf_tail = 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) +/* transfer keyboard report from buffer */ +void vusb_transfer_keyboard(void) { -#ifdef USB_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]); + if (usbInterruptIsReady()) { + if (kbuf_head != kbuf_tail) { + usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t)); + kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE; + } } -#endif - return keyboard_report->keys[0]; } /*------------------------------------------------------------------* - * Keyboard report send buffer + * Host driver *------------------------------------------------------------------*/ -#define KBUF_SIZE 16 -static report_keyboard_t kbuf[KBUF_SIZE]; -static uint8_t kbuf_head = 0; -static uint8_t kbuf_tail = 0; +static uint8_t keyboard_leds(void); +static void send_keyboard(report_keyboard_t *report); +static void send_mouse(report_mouse_t *report); +static void send_system(uint16_t data); +static void send_consumer(uint16_t data); + +static host_driver_t driver = { + keyboard_leds, + send_keyboard, + send_mouse, + send_system, + send_consumer +}; -void host_vusb_keyboard_send(void) +host_driver_t *vusb_driver(void) { - if (usbInterruptIsReady() && kbuf_head != kbuf_tail) { - usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t)); - kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE; - } + return &driver; } -void host_send_keyboard_report(void) +static uint8_t keyboard_leds(void) { + return vusb_keyboard_leds; +} + +static void send_keyboard(report_keyboard_t *report) { uint8_t next = (kbuf_head + 1) % KBUF_SIZE; if (next != kbuf_tail) { - kbuf[kbuf_head] = *keyboard_report; + kbuf[kbuf_head] = *report; kbuf_head = next; } else { debug("kbuf: full\n"); @@ -150,20 +86,15 @@ void host_send_keyboard_report(void) } -#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE) -void host_mouse_send(report_mouse_t *report) +static void send_mouse(report_mouse_t *report) { report->report_id = REPORT_ID_MOUSE; if (usbInterruptIsReady3()) { usbSetInterrupt3((void *)report, sizeof(*report)); - } else { - debug("Int3 not ready\n"); } } -#endif -#ifdef USB_EXTRA_ENABLE -void host_system_send(uint16_t data) +static void send_system(uint16_t data) { // Not need static? static uint8_t report[] = { REPORT_ID_SYSTEM, 0, 0 }; @@ -171,12 +102,10 @@ void host_system_send(uint16_t data) report[2] = (data>>8)&0xFF; if (usbInterruptIsReady3()) { usbSetInterrupt3((void *)&report, sizeof(report)); - } else { - debug("Int3 not ready\n"); } } -void host_consumer_send(uint16_t data) +static void send_consumer(uint16_t data) { static uint16_t last_data = 0; if (data == last_data) return; @@ -188,11 +117,8 @@ void host_consumer_send(uint16_t data) report[2] = (data>>8)&0xFF; if (usbInterruptIsReady3()) { usbSetInterrupt3((void *)&report, sizeof(report)); - } else { - debug("Int3 not ready\n"); } } -#endif @@ -213,32 +139,36 @@ usbRequest_t *rq = (void *)data; if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */ if(rq->bRequest == USBRQ_HID_GET_REPORT){ - debug(" GET_REPORT"); + debug("GET_REPORT:"); /* we only have one report type, so don't look at wValue */ usbMsgPtr = (void *)keyboard_report_prev; return sizeof(*keyboard_report_prev); }else if(rq->bRequest == USBRQ_HID_GET_IDLE){ - debug(" GET_IDLE: "); - debug_hex(idleRate); - usbMsgPtr = &idleRate; + debug("GET_IDLE: "); + //debug_hex(vusb_idle_rate); + usbMsgPtr = &vusb_idle_rate; return 1; }else if(rq->bRequest == USBRQ_HID_SET_IDLE){ - idleRate = rq->wValue.bytes[1]; - debug(" SET_IDLE: "); - debug_hex(idleRate); + vusb_idle_rate = rq->wValue.bytes[1]; + debug("SET_IDLE: "); + debug_hex(vusb_idle_rate); }else if(rq->bRequest == USBRQ_HID_SET_REPORT){ - //debug(" SET_REPORT: "); + debug("SET_REPORT: "); + // Report Type: 0x02(Out)/ReportID: 0x00(none) && Interface: 0(keyboard) if (rq->wValue.word == 0x0200 && rq->wIndex.word == 0) { + debug("SET_LED: "); last_req.kind = SET_LED; last_req.len = rq->wLength.word; } return USB_NO_MSG; // to get data in usbFunctionWrite + } else { + debug("UNKNOWN:"); } - debug("\n"); }else{ - debug("VENDOR\n"); + debug("VENDOR:"); /* no vendor specific requests implemented */ } + debug("\n"); return 0; /* default for not implemented requests: return no data back to host */ } @@ -249,8 +179,10 @@ uchar usbFunctionWrite(uchar *data, uchar len) } switch (last_req.kind) { case SET_LED: - //debug("SET_LED\n"); - keyboard_leds = data[0]; + debug("SET_LED: "); + debug_hex(data[0]); + debug("\n"); + vusb_keyboard_leds = data[0]; last_req.len = 0; return 1; break; @@ -484,13 +416,14 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) { usbMsgLen_t len = 0; +/* debug("usbFunctionDescriptor: "); debug_hex(rq->bmRequestType); debug(" "); debug_hex(rq->bRequest); debug(" "); debug_hex16(rq->wValue.word); debug(" "); debug_hex16(rq->wIndex.word); debug(" "); debug_hex16(rq->wLength.word); debug("\n"); - +*/ switch (rq->wValue.bytes[1]) { #if USB_CFG_DESCR_PROPS_CONFIGURATION case USBDESCR_CONFIG: @@ -499,8 +432,16 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) break; #endif case USBDESCR_HID: - usbMsgPtr = (unsigned char *)(usbDescriptorConfiguration + 18); - len = 9; + switch (rq->wValue.bytes[0]) { + case 0: + usbMsgPtr = (unsigned char *)(usbDescriptorConfiguration + 9 + 9); + len = 9; + break; + case 1: + usbMsgPtr = (unsigned char *)(usbDescriptorConfiguration + 9 + (9 + 9 + 7) + 9); + len = 9; + break; + } break; case USBDESCR_HID_REPORT: /* interface index */ @@ -516,6 +457,6 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) } break; } - debug("desc len: "); debug_hex(len); debug("\n"); + //debug("desc len: "); debug_hex(len); debug("\n"); return len; } diff --git a/vusb/vusb.h b/vusb/vusb.h new file mode 100644 index 000000000..5accf233b --- /dev/null +++ b/vusb/vusb.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 VUSB_H +#define VUSB_H + +#include "host_driver.h" + + +host_driver_t *vusb_driver(void); +void vusb_transfer_keyboard(void); + +#endif |