Added Bulegiga iWRAP support into HHKB.(Bluetooth)
|
@ -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
|
62
POWER.txt
Normal file
|
@ -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
|
4
README
|
@ -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
|
||||
|
|
|
@ -8,7 +8,7 @@ COMMON_DIR = ..
|
|||
TARGET_DIR = .
|
||||
|
||||
# keyboard dependent files
|
||||
TARGET_SRC = main_pjrc.c \
|
||||
SRC = main.c \
|
||||
keymap.c \
|
||||
matrix.c \
|
||||
led.c \
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) \
|
||||
)
|
||||
|
||||
|
||||
|
|
56
command.c
|
@ -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();
|
||||
|
@ -122,21 +147,27 @@ uint8_t command_proc(void)
|
|||
print("usb_keyboard_protocol: "); phex(usb_keyboard_protocol); print("\n");
|
||||
print("usb_keyboard_idle_config:"); phex(usb_keyboard_idle_config); print("\n");
|
||||
print("usb_keyboard_idle_count:"); phex(usb_keyboard_idle_count); print("\n");
|
||||
#endif
|
||||
|
||||
#ifdef HOST_VUSB
|
||||
# if USB_COUNT_SOF
|
||||
print("usbSofCount: "); phex(usbSofCount); print("\n");
|
||||
# endif
|
||||
#endif
|
||||
break;
|
||||
#ifdef 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
|
||||
|
|
|
@ -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
|
40
hhkb/FUSE.txt
Normal file
|
@ -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)
|
91
hhkb/Makefile.iwrap
Normal file
|
@ -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
|
|
@ -13,7 +13,7 @@ COMMON_DIR = ..
|
|||
TARGET_DIR = .
|
||||
|
||||
# keyboard dependent files
|
||||
TARGET_SRC = main_pjrc.c \
|
||||
SRC = main.c \
|
||||
keymap.c \
|
||||
matrix.c \
|
||||
led.c
|
||||
|
@ -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
|
|
@ -13,7 +13,7 @@ COMMON_DIR = ..
|
|||
TARGET_DIR = .
|
||||
|
||||
# keyboard dependent files
|
||||
TARGET_SRC = main_vusb.c \
|
||||
SRC = main.c \
|
||||
keymap.c \
|
||||
matrix.c \
|
||||
led.c
|
||||
|
@ -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
|
||||
|
|
113
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
|
||||
|
|
55
hhkb/config_iwrap.h
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
4
hhkb/doc/Bluetooth.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
HHKB Bluetooth mod
|
||||
==================
|
||||
See this article:
|
||||
http://geekhack.org/showwiki.php?title=Island:20851
|
2
hhkb/doc/Bluetooth_img/.picasa.ini
Executable file
|
@ -0,0 +1,2 @@
|
|||
[Picasa]
|
||||
name=Bluetooth_img
|
BIN
hhkb/doc/Bluetooth_img/BT_circuit.jpg
Executable file
After Width: | Height: | Size: 490 KiB |
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 146 KiB |
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 145 KiB |
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 189 KiB |
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 168 KiB |
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 188 KiB |
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 204 KiB After Width: | Height: | Size: 204 KiB |
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 151 KiB |
115
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
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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 |= 0x3E; \
|
||||
DDRB &= ~(1<<0); \
|
||||
PORTB |= (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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
190
host.c
Normal file
|
@ -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");
|
||||
}
|
||||
}
|
89
host.h
|
@ -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
|
||||
|
|
33
host_driver.h
Normal file
|
@ -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
|
10
iwrap.mk
Normal file
|
@ -0,0 +1,10 @@
|
|||
OPT_DEFS += -DHOST_IWRAP
|
||||
|
||||
SRC += iwrap.c \
|
||||
suart.S \
|
||||
sendchar_uart.c \
|
||||
uart.c
|
||||
|
||||
|
||||
# Search Path
|
||||
VPATH += $(COMMON_DIR)/iwrap
|
376
iwrap/iWRAP.txt
Normal file
|
@ -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
|
467
iwrap/iwrap.c
Normal file
|
@ -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
|
||||
}
|
49
iwrap/iwrap.h
Normal file
|
@ -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
|
378
iwrap/main.c
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
156
iwrap/suart.S
Normal file
|
@ -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
|
8
iwrap/suart.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef SUART
|
||||
#define SUART
|
||||
|
||||
void xmit(uint8_t);
|
||||
uint8_t rcvr(void);
|
||||
uint8_t recv(void);
|
||||
|
||||
#endif /* SUART */
|
159
iwrap/wd.h
Normal file
|
@ -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_ */
|
|
@ -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
|
||||
|
|
4
layer.c
|
@ -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;
|
||||
|
|
|
@ -8,7 +8,7 @@ COMMON_DIR = ..
|
|||
TARGET_DIR = .
|
||||
|
||||
# keyboard dependent files
|
||||
TARGET_SRC = main_pjrc.c \
|
||||
SRC = main.c \
|
||||
keymap.c \
|
||||
matrix.c \
|
||||
led.c
|
||||
|
@ -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
|
||||
|
|
|
@ -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)) \
|
||||
)
|
||||
|
||||
|
||||
|
|
0
macway/doc/back.jpg
Executable file → Normal file
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 119 KiB |
0
macway/doc/case.jpg
Executable file → Normal file
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
0
macway/doc/keys.jpg
Executable file → Normal file
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 114 KiB |
0
macway/doc/side.jpg
Executable file → Normal file
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
0
macway/doc/switch.jpg
Executable file → Normal file
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
0
macway/doc/teensy.jpg
Executable file → Normal file
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 162 KiB |
0
macway/doc/wiring.jpg
Executable file → Normal file
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 162 KiB |
0
macway/doc/withHHKB.jpg
Executable file → Normal file
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 149 KiB |
0
macway/doc/withThinkPad.jpg
Executable file → Normal file
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
58
main_vusb.c
|
@ -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();
|
||||
}
|
||||
}
|
10
mousekey.c
Normal file → Executable file
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
10
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);
|
||||
|
|
|
@ -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();
|
||||
}
|
76
pjrc/pjrc.c
Normal file
|
@ -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
|
||||
}
|
26
pjrc/pjrc.h
Normal file
|
@ -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
|
34
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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
13
print.c
|
@ -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;
|
||||
|
|
2
print.h
|
@ -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);
|
||||
|
|
|
@ -13,7 +13,7 @@ COMMON_DIR = ..
|
|||
TARGET_DIR = .
|
||||
|
||||
# keyboard dependent files
|
||||
TARGET_SRC = main_pjrc.c \
|
||||
SRC = main.c \
|
||||
keymap.c \
|
||||
matrix.c \
|
||||
led.c \
|
||||
|
@ -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
|
||||
|
|
|
@ -13,7 +13,7 @@ COMMON_DIR = ..
|
|||
TARGET_DIR = .
|
||||
|
||||
# keyboard dependent files
|
||||
TARGET_SRC = main_vusb.c \
|
||||
SRC = main.c \
|
||||
keymap.c \
|
||||
matrix.c \
|
||||
led.c \
|
||||
|
@ -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
|
||||
|
|
|
@ -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)) \
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -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)) \
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
),
|
||||
|
|
|
@ -349,6 +349,7 @@ uint8_t matrix_scan(void)
|
|||
default:
|
||||
state = INIT;
|
||||
}
|
||||
phex(code);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
96
report.h
Normal file
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
25
sendchar_uart.c
Normal file
|
@ -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;
|
||||
}
|
35
timer.c
|
@ -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++;
|
||||
}
|
||||
|
|
21
timer.h
|
@ -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;
|
||||
|
|
129
uart.c
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
11
uart.h
Normal file
|
@ -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
|
|
@ -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 */
|
||||
|
|
17
vusb.mk
Normal file
|
@ -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
|
99
vusb/main.c
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 vusb_keyboard_leds = 0;
|
||||
static uint8_t vusb_idle_rate = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 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]);
|
||||
}
|
||||
#endif
|
||||
return keyboard_report->keys[0];
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*
|
||||
* Keyboard report send buffer
|
||||
*------------------------------------------------------------------*/
|
||||
/* 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;
|
||||
|
||||
void host_vusb_keyboard_send(void)
|
||||
|
||||
/* transfer keyboard report from buffer */
|
||||
void vusb_transfer_keyboard(void)
|
||||
{
|
||||
if (usbInterruptIsReady() && kbuf_head != kbuf_tail) {
|
||||
if (usbInterruptIsReady()) {
|
||||
if (kbuf_head != kbuf_tail) {
|
||||
usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t));
|
||||
kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void host_send_keyboard_report(void)
|
||||
|
||||
/*------------------------------------------------------------------*
|
||||
* 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 *vusb_driver(void)
|
||||
{
|
||||
return &driver;
|
||||
}
|
||||
|
||||
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_hex(vusb_idle_rate);
|
||||
usbMsgPtr = &vusb_idle_rate;
|
||||
return 1;
|
||||
}else if(rq->bRequest == USBRQ_HID_SET_IDLE){
|
||||
idleRate = rq->wValue.bytes[1];
|
||||
vusb_idle_rate = rq->wValue.bytes[1];
|
||||
debug("SET_IDLE: ");
|
||||
debug_hex(idleRate);
|
||||
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
|
||||
}
|
||||
debug("\n");
|
||||
} else {
|
||||
debug("VENDOR\n");
|
||||
debug("UNKNOWN:");
|
||||
}
|
||||
}else{
|
||||
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,9 +432,17 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq)
|
|||
break;
|
||||
#endif
|
||||
case USBDESCR_HID:
|
||||
usbMsgPtr = (unsigned char *)(usbDescriptorConfiguration + 18);
|
||||
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 */
|
||||
switch (rq->wIndex.word) {
|
||||
|
@ -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;
|
||||
}
|
27
vusb/vusb.h
Normal file
|
@ -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
|