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
|
@ -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
|
@ -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)
|
@ -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
|
@ -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
|
@ -0,0 +1,4 @@
|
||||
HHKB Bluetooth mod
|
||||
==================
|
||||
See this article:
|
||||
http://geekhack.org/showwiki.php?title=Island:20851
|
@ -0,0 +1,2 @@
|
||||
[Picasa]
|
||||
name=Bluetooth_img
|
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 |
@ -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");
|
||||
}
|
||||
}
|
@ -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
|
@ -0,0 +1,10 @@
|
||||
OPT_DEFS += -DHOST_IWRAP
|
||||
|
||||
SRC += iwrap.c \
|
||||
suart.S \
|
||||
sendchar_uart.c \
|
||||
uart.c
|
||||
|
||||
|
||||
# Search Path
|
||||
VPATH += $(COMMON_DIR)/iwrap
|
@ -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
|
@ -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
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
@ -0,0 +1,8 @@
|
||||
#ifndef SUART
|
||||
#define SUART
|
||||
|
||||
void xmit(uint8_t);
|
||||
uint8_t rcvr(void);
|
||||
uint8_t recv(void);
|
||||
|
||||
#endif /* SUART */
|
@ -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_ */
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 114 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 162 KiB |
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 162 KiB |
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 149 KiB |
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
@ -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();
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
// TODO: Teensy support(ATMega32u4/AT90USB128)
|
||||
// Fixed for Arduino Duemilanove ATmega168p by Jun Wako
|
||||
/* UART Example for Teensy USB Development Board
|
||||
* http://www.pjrc.com/teensy/
|
||||
* Copyright (c) 2009 PJRC.COM, LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Version 1.0: Initial Release
|
||||
// Version 1.1: Add support for Teensy 2.0, minor optimizations
|
||||
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
// These buffers may be any size from 2 to 256 bytes.
|
||||
#define RX_BUFFER_SIZE 64
|
||||
#define TX_BUFFER_SIZE 40
|
||||
|
||||
static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
|
||||
static volatile uint8_t tx_buffer_head;
|
||||
static volatile uint8_t tx_buffer_tail;
|
||||
static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
|
||||
static volatile uint8_t rx_buffer_head;
|
||||
static volatile uint8_t rx_buffer_tail;
|
||||
|
||||
// Initialize the UART
|
||||
void uart_init(uint32_t baud)
|
||||
{
|
||||
cli();
|
||||
UBRR0 = (F_CPU / 4 / baud - 1) / 2;
|
||||
UCSR0A = (1<<U2X0);
|
||||
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
|
||||
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
|
||||
tx_buffer_head = tx_buffer_tail = 0;
|
||||
rx_buffer_head = rx_buffer_tail = 0;
|
||||
sei();
|
||||
}
|
||||
|
||||
// Transmit a byte
|
||||
void uart_putchar(uint8_t c)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
i = tx_buffer_head + 1;
|
||||
if (i >= TX_BUFFER_SIZE) i = 0;
|
||||
while (tx_buffer_tail == i) ; // wait until space in buffer
|
||||
//cli();
|
||||
tx_buffer[i] = c;
|
||||
tx_buffer_head = i;
|
||||
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (1<<UDRIE0);
|
||||
//sei();
|
||||
}
|
||||
|
||||
// Receive a byte
|
||||
uint8_t uart_getchar(void)
|
||||
{
|
||||
uint8_t c, i;
|
||||
|
||||
while (rx_buffer_head == rx_buffer_tail) ; // wait for character
|
||||
i = rx_buffer_tail + 1;
|
||||
if (i >= RX_BUFFER_SIZE) i = 0;
|
||||
c = rx_buffer[i];
|
||||
rx_buffer_tail = i;
|
||||
return c;
|
||||
}
|
||||
|
||||
// Return the number of bytes waiting in the receive buffer.
|
||||
// Call this before uart_getchar() to check if it will need
|
||||
// to wait for a byte to arrive.
|
||||
uint8_t uart_available(void)
|
||||
{
|
||||
uint8_t head, tail;
|
||||
|
||||
head = rx_buffer_head;
|
||||
tail = rx_buffer_tail;
|
||||
if (head >= tail) return head - tail;
|
||||
return RX_BUFFER_SIZE + head - tail;
|
||||
}
|
||||
|
||||
// Transmit Interrupt
|
||||
ISR(USART_UDRE_vect)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
if (tx_buffer_head == tx_buffer_tail) {
|
||||
// buffer is empty, disable transmit interrupt
|
||||
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
|
||||
} else {
|
||||
i = tx_buffer_tail + 1;
|
||||
if (i >= TX_BUFFER_SIZE) i = 0;
|
||||
UDR0 = tx_buffer[i];
|
||||
tx_buffer_tail = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Receive Interrupt
|
||||
ISR(USART_RX_vect)
|
||||
{
|
||||
uint8_t c, i;
|
||||
|
||||
c = UDR0;
|
||||
i = rx_buffer_head + 1;
|
||||
if (i >= RX_BUFFER_SIZE) i = 0;
|
||||
if (i != rx_buffer_tail) {
|
||||
rx_buffer[i] = c;
|
||||
rx_buffer_head = i;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
#ifndef _uart_included_h_
|
||||
#define _uart_included_h_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void uart_init(uint32_t baud);
|
||||
void uart_putchar(uint8_t c);
|
||||
uint8_t uart_getchar(void);
|
||||
uint8_t uart_available(void);
|
||||
|
||||
#endif
|
@ -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
|
@ -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();
|
||||
}
|
||||
}
|
@ -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
|