From f4125707399d11a7d80587659c464b9bcddb8c56 Mon Sep 17 00:00:00 2001 From: tmk Date: Thu, 7 Jun 2012 02:25:15 +0900 Subject: Moved files to common, protocol and doc directory --- protocol/iwrap/iWRAP.txt | 376 ++++++++++++++++++++++++++++++++++++++ protocol/iwrap/iwrap.c | 467 +++++++++++++++++++++++++++++++++++++++++++++++ protocol/iwrap/iwrap.h | 49 +++++ protocol/iwrap/main.c | 378 ++++++++++++++++++++++++++++++++++++++ protocol/iwrap/suart.S | 156 ++++++++++++++++ protocol/iwrap/suart.h | 8 + protocol/iwrap/wd.h | 159 ++++++++++++++++ 7 files changed, 1593 insertions(+) create mode 100644 protocol/iwrap/iWRAP.txt create mode 100644 protocol/iwrap/iwrap.c create mode 100644 protocol/iwrap/iwrap.h create mode 100644 protocol/iwrap/main.c create mode 100644 protocol/iwrap/suart.S create mode 100644 protocol/iwrap/suart.h create mode 100644 protocol/iwrap/wd.h (limited to 'protocol/iwrap') diff --git a/protocol/iwrap/iWRAP.txt b/protocol/iwrap/iWRAP.txt new file mode 100644 index 0000000000..2a062d9d98 --- /dev/null +++ b/protocol/iwrap/iWRAP.txt @@ -0,0 +1,376 @@ +Bulegiga WT12 +============= +WT12 is a bluetooth module from Bluegiga. http://www.bluegiga.com/ + +iWRAP + higher layer interface for bluetooth firmware + communicate with UART + +iWRAP HID +default setting + 115200 8bit/n/1/n + + +TODO +---- +KiCAD circuit/PCB design +power saving + AVR sleep(15ms by watch dog timer) + WT12 sleep + measuring current consumption + measuring battery life of normal usage/idle/intensive usage +software reset/bootloarder +LED indicator(chaging/paring/connecting) +license confirmation of suart.c +consumer page is not working +authenticate method/SSP +SPP keyboard support +SPP debug console support +mouse wheel feature request to Bluegiga + + +Problems +-------- +power consumption +no consumer page support(bug?) +no mouse wheel support +no paring management +no interactive auth method + + +UART hardware flow control +-------------------------- +(iWRAP4 User Guide 9.5) +Hardware flow control is enabled by default and it should not be disabled unless mandatory, because without the hardware flow control the data transmission may not be reliable. +If the hardware flow control is enabled from PS-keys, but no flow control is used, the following steps should be implemented in the hardware design: +- CTS pin must be grounded +- RTS pin must be left floating + + +Power Saving +------------ +power consume + without opimization: 4hr to shutdown(310mAh) + 2011/08/25: 9hr(310mAh) SNIFF MASTER sleep/WDTO_120MS + +measure current consumption + HHKB keyswitch matrix board + idle + scanning + Bluegiga WT12 module + SLEEP command + deep sleep on/off in config bits + +HHKB keyswich + how to power off + I/O pin configuration when sleeping + FET switch for 5V regulator + +Bluetooth module + power off when in USB mode + power off by FET switch + +AVR configuration + unused pins + ADC + + + +SET CONTROL CONFIG +------------------ + SET CONTROL CONFIG 4810 + SET CONTROL CONFIG LIST + SET CONTROL CONFIG 0000 0000 4910 DEEP_SLEEP KLUDGE INTERACTIVE_PIN UART_LATENCY + + Bit14 UART low latency + Bit11 Interactive pairing mode + Bit04 Deep sleep + + +Reconnection +------------ +SET CONTROL AUTOCALL 1124 5000 HID + 1124 HID service class + 5000 interval ms + +HID profile +----------- +This is needed to configure only once. + SET PROFILE HID ON + RESET + +HID class +--------- + SET BT CLASS 005C0 // keyboard/mouse combined devie + +Pairing Security +---------------- +Secure Simple Pairing(SSP) + SET BT SSP 2 0 // Enables SSP for keyboard and Man-in-the-middle protection + SET BT SSP 3 0 // Enables SSP just works mode + +for keyboard with SSP + SET BT AUTH * 0000 + SET BT SSP 2 0 + SET CONTROL CONFIG 800 + RESET + +for keyboard without SSP + SET BT AUTH * 0000 + SET CONTROL CONFIG 800 + RESET + +AUTH + AUTH xx:xx:xx:xx:xx:xx? // Pairing request event + AUTH xx:xx:xx:xx:xx:xx 0000 + + SSP PASSKEY 78:dd:08:b7:e4:a2 ? + SSP PASSKEY 78:dd:08:b7:e4:a2 xxxxx + (SSP COMPLETE 78:dd:08:b7:e4:a2 HCI_ERROR_AUTH_FAIL // failed) + RING 0 78:dd:08:b7:e4:a2 11 HID + +Connecton + RING xx:xx:xx:xx:xx:xx xx HID // connection event + + KILL xx:xx:xx:xx:xx:xx + +Mode +---- +Command mode +Data mode + Raw mode + (Simple mode not for a real keyboard) + +Raw mode + Keyboard: + 0x9f, length(10), 0xa1, 0x01, mods, 0x00, key1, key2, key3, key4, key5, key6 + + Mouse: + 0x9f, length(5), 0xa1, 0x02, buttons, X, Y + + Consumer page: + 0x9f, length(5), 0xa1, 0x03, bitfield1, bitfield2, bitfield3 + + consumer page suage + Bitfield 1: + 0x01 Volume Increment + 0x02 Volume Decrement + 0x04 Mute + 0x08 Play/Pause + 0x10 Scan Next Track + 0x20 Scan Previous Track + 0x40 Stop + 0x80 Eject + Bitfield 2: + 0x01 Email Reader + 0x02 Application Control Search + 0x04 AC Bookmarks + 0x08 AC Home + 0x10 AC Back + 0x20 AC Forward + 0x40 AC Stop + 0x80 AC Refresh + Bitfield 3: + 0x01 Application Launch Generic Consumer Control + 0x02 AL Internet Browser + 0x04 AL Calculator + 0x08 AL Terminal Lock / Screensaver + 0x10 AL Local Machine Browser + 0x20 AC Minimize + 0x40 Record + 0x80 Rewind + + + + + +2011/07/13 +set +SET BT BDADDR 00:07:80:47:22:14 +SET BT NAME HHKB pro BT +SET BT CLASS 0005c0 +SET BT AUTH * 0000 +SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP +SET BT LAP 9e8b33 +SET BT PAGEMODE 4 2000 1 +SET BT PAIR 78:dd:08:b7:e4:a2 a191189cd7e51030ad6a07848ce879bb +SET BT POWER 3 3 3 +SET BT ROLE 0 f 7d00 +SET BT SNIFF 0 20 1 8 +SET BT SSP 2 1 +SET BT MTU 667 +SET CONTROL AUTOCALL 1124 3000 HID +SET CONTROL BAUD 38400,8n1 +SET CONTROL CD 00 0 +SET CONTROL ECHO 7 +SET CONTROL ESCAPE 43 00 1 +SET CONTROL GAIN 0 5 +SET CONTROL INIT SET CONTROL MUX 0 +SET CONTROL MSC DTE 00 00 00 00 00 00 +SET CONTROL MUX 1 +SET CONTROL PIO 00 00 +SET CONTROL READY 00 +SET PROFILE HID f HID +SET + +info config + +!!! THIS IS BETA RELEASE AND MAY BE USED FOR EVALUATION PURPOSES ONLY !!! + +WRAP THOR AI (4.1.0 build 435) +Copyright (c) 2003-2011 Bluegiga Technologies Inc. +Compiled on Jun 28 2011 17:19:51, running on WT12-A module, psr v31 + AVRCP BGIO FTP HFP HFP_AG HID HID_CONSUMER_PAGE HSP LEDS MAP OTA PBAP PIO=0x00fc SSP SUBRATE TEST VOLUME + - BOCK3 version 435 (Jun 28 2011 17:19:37) (max acl/sco 7/1) + - Bluetooth version 2.1, Power class 2 + - Loader 4279, firmware 6297 (56-bit encryption), native execution mode + - up 0 days, 06:23, 2 connections (pool 2) + - User configuration: +&028a = 0001 0000 0000 0011 0024 0000 0000 0010 0000 0080 0000 0000 0080 005f 009b 0034 00fb 0006 +&028b = 0000 0bb8 +&028d = 0001 +&0295 = 0000 0005 000b 0000 0003 0000 0000 0000 0000 0000 0000 +&0298 = a006 +&0299 = 0000 0000 +&02a3 = 0030 0030 0030 0030 +&02a4 = 009d 0000 +&02a5 = 0053 0045 0054 0020 0043 004f 004e 0054 0052 004f 004c 0020 004d 0055 0058 0020 0030 +&02a7 = 0000 05c0 +&02a8 = 4910 0000 0000 +&02aa = 0004 2000 0001 0033 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 +&02ac = 0000 0000 002b 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000 +&02ad = 4848 424b 7020 6f72 4220 0054 +&02b3 = 0005 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 +&02b7 = 000f 4948 0044 +&02bb = 8000 +READY. + + + + +2011/07/07 settings: +set +SET BT BDADDR 00:07:80:47:22:14 +SET BT NAME HHKB Pro BT +SET BT CLASS 0005c0 +SET BT AUTH * 000 +SET BT IDENT BT:47 f000 4.0.0 Bluegiga iWRAP +SET BT LAP 9e8b33 +SET BT PAGEMODE 4 2000 1 +SET BT PAIR 78:dd:08:b7:e4:a2 9e54d0aabb1b4d73cfccddb1ea4ef2d6 +SET BT POWER 3 3 3 +SET BT ROLE 0 f 7d00 +SET BT SNIFF 0 20 1 8 +SET BT SSP 3 0 +SET BT MTU 667 +SET CONTROL BAUD 38400,8n1 +SET CONTROL CD 00 0 +SET CONTROL ECHO 7 +SET CONTROL ESCAPE 255 00 1 +SET CONTROL GAIN 0 5 +SET CONTROL INIT set control mux 0 +SET CONTROL MSC DTE 00 00 00 00 00 00 +SET CONTROL PREAMP 1 1 +SET CONTROL READY 00 +SET PROFILE HID HID +SET PROFILE SPP Bluetooth Serial Port +SET + +info config +WRAP THOR AI (4.0.0 build 317) +Copyright (c) 2003-2010 Bluegiga Technologies Inc. +Compiled on Apr 20 2010 16:44:28, running on WT12-A module, psr v31 + AVRCP FTP PBAP PIO=0x00fc SSP SUBRATE VOLUME + - BOCK3 version 317 (Apr 20 2010 16:44:21) (max acl/sco 7/1) + - Bluetooth version 2.1, Power class 2 + - Loader 4279, firmware 6297 (56-bit encryption), native execution mode + - up 0 days, 00:00, 0 connections (pool 1) + - User configuration: +&028c = 0001 0020 0000 0001 0008 0000 +&028d = 0000 +&0296 = 0047 0001 f000 0400 6c42 6575 6967 6167 6920 5257 5041 +&0298 = c006 +&02a3 = 0030 0030 0030 +&02a4 = 009d 0000 +&02a5 = 0073 0065 0074 0020 0063 006f 006e 0074 0072 006f 006c 0020 006d 0075 0078 0020 0030 +&02a7 = 0000 05c0 +&02a8 = 0800 0000 0000 +&02ac = 0000 0000 00ff 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000 +&02ad = 4848 424b 5020 6f72 4220 0054 +&02b3 = 0004 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 +&02b7 = 0000 +&02bb = 6c42 6575 6f74 746f 2068 6553 6972 6c61 5020 726f 0074 +READY. + + + +2011/08/23: +SET BT BDADDR 00:07:80:47:22:14 +SET BT NAME HHKB pro BT +SET BT CLASS 0005c0 +SET BT AUTH * 0000 +SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP +SET BT LAP 9e8b33 +SET BT PAGEMODE 4 2000 1 +SET BT PAIRCOUNT 4 +SET BT POWER 3 3 3 +SET BT ROLE 1 f 12c0 +SET BT SNIFF 10 2 1 8 +SET BT SSP 3 0 +SET BT MTU 667 +SET CONTROL BAUD 38400,8n1 +SET CONTROL CD 00 0 +SET CONTROL ECHO 7 +SET CONTROL ESCAPE 43 00 1 +SET CONTROL GAIN 0 5 +SET CONTROL INIT SET CONTROL MUX 0 +SET CONTROL MSC DTE 00 00 00 00 00 00 +SET CONTROL MUX 1 +SET CONTROL PIO 00 00 +SET CONTROL READY 00 +SET PROFILE HID 7 HIDKeyboardMouse +SET + +SET CONTROL CONFIG 0000 0004 481e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE DEEP_SLEEP INTERACTIVE_PIN UART_LATENCY 23D_NOKLUDGE + + + +2011/08/25: +SET BT BDADDR 00:07:80:47:22:14 +SET BT NAME HHKB pro BT +SET BT CLASS 0005c0 + +SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP +SET BT LAP 9e8b33 +SET BT PAGEMODE 4 2000 1 +SET BT PAIRCOUNT 4 +SET BT PAIR 78:dd:08:b7:e4:a2 0be83335a03fed8ededae42e99554e28 +SET BT POWER 3 3 3 +SET BT ROLE 1 f 12c0 +SET BT SNIFF 100 20 1 8 +SET BT SSP 3 0 +SET BT MTU 667 +SET CONTROL BAUD 38400,8n1 +SET CONTROL CD 00 0 +SET CONTROL ECHO 7 +SET CONTROL ESCAPE - 20 1 +SET CONTROL GAIN 0 5 +SET CONTROL INIT SET CONTROL MUX 0 +SET CONTROL MSC DTE 00 00 00 00 00 00 +SET CONTROL MUX 1 +SET CONTROL PIO 00 00 +SET CONTROL READY 00 +SET PROFILE HID f HIDKeyboardMouse +SET + + +SET CONTROL CONFIG 0000 0000 490e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE INTERACTIVE_PIN UART_LATENCY + + +2011/09/08: +SET CONTROL CONFIG 0000 0000 410e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE UART_LATENCY + + Removed INTERACTIVE_PIN to avoid interactive auth and use SET BT AUTH pin(0000). + + +EOF diff --git a/protocol/iwrap/iwrap.c b/protocol/iwrap/iwrap.c new file mode 100644 index 0000000000..9c68761bf0 --- /dev/null +++ b/protocol/iwrap/iwrap.c @@ -0,0 +1,467 @@ +/* +Copyright 2011 Jun Wako + +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 . +*/ + +/* 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 +#include +#include +#include +#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<mods); + xmit(0x00); // reserved byte(always 0) + xmit(report->keys[0]); + xmit(report->keys[1]); + xmit(report->keys[2]); + xmit(report->keys[3]); + xmit(report->keys[4]); + xmit(report->keys[5]); + MUX_FOOTER(0x01); +} + +static void send_mouse(report_mouse_t *report) +{ +#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE) + if (!iwrap_connected() && !iwrap_check_connection()) return; + MUX_HEADER(0x01, 0x07); + // HID raw mode header + xmit(0x9f); + xmit(0x05); // Length + xmit(0xa1); // mouse report + xmit(0x02); + xmit(report->buttons); + xmit(report->x); + xmit(report->y); + MUX_FOOTER(0x01); +#endif +} + +static void send_system(uint16_t data) +{ + /* not supported */ +} + +static void send_consumer(uint16_t data) +{ +#ifdef EXTRAKEY_ENABLE + static uint16_t last_data = 0; + uint8_t bits1 = 0; + uint8_t bits2 = 0; + uint8_t bits3 = 0; + + if (!iwrap_connected() && !iwrap_check_connection()) return; + if (data == last_data) return; + last_data = data; + + // 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf) + switch (data) { + case AUDIO_VOL_UP: + bits1 = 0x01; + break; + case AUDIO_VOL_DOWN: + bits1 = 0x02; + break; + case AUDIO_MUTE: + bits1 = 0x04; + break; + case TRANSPORT_PLAY_PAUSE: + bits1 = 0x08; + break; + case TRANSPORT_NEXT_TRACK: + bits1 = 0x10; + break; + case TRANSPORT_PREV_TRACK: + bits1 = 0x20; + break; + case TRANSPORT_STOP: + bits1 = 0x40; + break; + case TRANSPORT_EJECT: + bits1 = 0x80; + break; + case AL_EMAIL: + bits2 = 0x01; + break; + case AC_SEARCH: + bits2 = 0x02; + break; + case AC_BOOKMARKS: + bits2 = 0x04; + break; + case AC_HOME: + bits2 = 0x08; + break; + case AC_BACK: + bits2 = 0x10; + break; + case AC_FORWARD: + bits2 = 0x20; + break; + case AC_STOP: + bits2 = 0x40; + break; + case AC_REFRESH: + bits2 = 0x80; + break; + case AL_CC_CONFIG: + bits3 = 0x01; + break; + case AL_CALCULATOR: + bits3 = 0x04; + break; + case AL_LOCK: + bits3 = 0x08; + break; + case AL_LOCAL_BROWSER: + bits3 = 0x10; + break; + case AC_MINIMIZE: + bits3 = 0x20; + break; + case TRANSPORT_RECORD: + bits3 = 0x40; + break; + case TRANSPORT_REWIND: + bits3 = 0x80; + break; + } + + MUX_HEADER(0x01, 0x07); + xmit(0x9f); + xmit(0x05); // Length + xmit(0xa1); // consumer report + xmit(0x03); + xmit(bits1); + xmit(bits2); + xmit(bits3); + MUX_FOOTER(0x01); +#endif +} diff --git a/protocol/iwrap/iwrap.h b/protocol/iwrap/iwrap.h new file mode 100644 index 0000000000..ffaad9395d --- /dev/null +++ b/protocol/iwrap/iwrap.h @@ -0,0 +1,49 @@ +/* +Copyright 2011 Jun Wako + +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 . +*/ + +#ifndef IWRAP_H +#define IWRAP_H + +#include +#include +#include "host_driver.h" + + +/* enable iWRAP MUX mode */ +#define MUX_MODE + + +host_driver_t *iwrap_driver(void); + +void iwrap_init(void); +void iwrap_send(const char *s); +void iwrap_mux_send(const char *s); +void iwrap_buf_send(void); +void iwrap_buf_add(uint8_t c); +void iwrap_buf_del(void); + +void iwrap_call(void); +void iwrap_kill(void); +void iwrap_unpair(void); +void iwrap_sleep(void); +void iwrap_sniff(void); +void iwrap_subrate(void); +bool iwrap_failed(void); +uint8_t iwrap_connected(void); +uint8_t iwrap_check_connection(void); + +#endif diff --git a/protocol/iwrap/main.c b/protocol/iwrap/main.c new file mode 100644 index 0000000000..a552afb67e --- /dev/null +++ b/protocol/iwrap/main.c @@ -0,0 +1,378 @@ +/* +Copyright 2011 Jun Wako + +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 . +*/ +#include +#include +#include +//#include +#include "wd.h" // in order to use watchdog in interrupt mode +#include +#include +#include +#include "keyboard.h" +#include "matrix.h" +#include "host.h" +#include "iwrap.h" +#ifdef HOST_VUSB +# include "vusb.h" +# include "usbdrv.h" +#endif +#include "uart.h" +#include "suart.h" +#include "timer.h" +#include "debug.h" +#include "usb_keycodes.h" +#include "command.h" + + +static void sleep(uint8_t term); +static bool console(void); +static uint8_t console_command(uint8_t c); +static uint8_t key2asc(uint8_t key); + + +/* +static void set_prr(void) +{ + power_adc_disable(); + power_spi_disable(); + power_twi_disable(); +#ifndef TIMER_H + //power_timer0_disable(); // used in timer.c +#endif + power_timer1_disable(); + power_timer2_disable(); +} +*/ + +/* +static void pullup_pins(void) +{ + // DDRs are set to 0(input) by default. +#ifdef PORTA + PORTA = 0xFF; +#endif + PORTB = 0xFF; + PORTC = 0xFF; + PORTD = 0xFF; +#ifdef PORTE + PORTE = 0xFF; +#endif +#ifdef PORTE + PORTF = 0xFF; +#endif +} +*/ + + +#ifdef HOST_VUSB +static void disable_vusb(void) +{ + // disable interrupt & disconnect to prevent host from enumerating + USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT); + usbDeviceDisconnect(); +} + +static void enable_vusb(void) +{ + USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); + usbDeviceConnect(); +} + +static void init_vusb(void) +{ + uint8_t i = 0; + + usbInit(); + disable_vusb(); + /* fake USB disconnect for > 250 ms */ + while(--i){ + _delay_ms(1); + } + enable_vusb(); +} +#endif + +void change_driver(host_driver_t *driver) +{ + host_clear_keyboard_report(); + host_swap_keyboard_report(); + host_clear_keyboard_report(); + host_send_keyboard_report(); + _delay_ms(1000); + host_set_driver(driver); +} + + +static bool sleeping = false; +static bool insomniac = false; // TODO: should be false for power saving +static uint16_t last_timer = 0; + +int main(void) +{ + MCUSR = 0; + clock_prescale_set(clock_div_1); + WD_SET(WD_OFF); + + // power saving: the result is worse than nothing... why? + //pullup_pins(); + //set_prr(); + + print_enable = true; + debug_enable = false; + +#ifdef HOST_VUSB + disable_vusb(); +#endif + uart_init(115200); + keyboard_init(); + print("\nSend BREAK for UART Console Commands.\n"); + + // TODO: move to iWRAP/suart file + print("suart init\n"); + // suart init + // PC4: Tx Output IDLE(Hi) + PORTC |= (1<<4); + DDRC |= (1<<4); + // PC5: Rx Input(pull-up) + PORTC |= (1<<5); + DDRC &= ~(1<<5); + // suart receive interrut(PC5/PCINT13) + PCMSK1 = 0b00100000; + PCICR = 0b00000010; + + host_set_driver(iwrap_driver()); + + print("iwrap_init()\n"); + iwrap_init(); + iwrap_call(); + + last_timer = timer_read(); + while (true) { +#ifdef HOST_VUSB + if (host_get_driver() == vusb_driver()) + usbPoll(); +#endif + keyboard_proc(); +#ifdef HOST_VUSB + if (host_get_driver() == vusb_driver()) + vusb_transfer_keyboard(); +#endif + if (matrix_is_modified() || console()) { + last_timer = timer_read(); + sleeping = false; + } else if (!sleeping && timer_elapsed(last_timer) > 4000) { + sleeping = true; + iwrap_check_connection(); + } + + if (host_get_driver() == iwrap_driver()) { + if (sleeping && !insomniac) { + _delay_ms(1); // wait for UART to send + iwrap_sleep(); + sleep(WDTO_60MS); + } + } + } +} + +static void sleep(uint8_t term) +{ + WD_SET(WD_IRQ, term); + + cli(); + set_sleep_mode(SLEEP_MODE_PWR_DOWN); + sleep_enable(); + sleep_bod_disable(); + sei(); + sleep_cpu(); + sleep_disable(); + + WD_SET(WD_OFF); +} + +ISR(WDT_vect) +{ + // wake up +} + +static bool console(void) +{ + // Send to Bluetoot module WT12 + static bool breaked = false; + if (!uart_available()) + return false; + else { + uint8_t c; + c = uart_getchar(); + uart_putchar(c); + switch (c) { + case 0x00: // BREAK signal + if (!breaked) { + print("break(? for help): "); + breaked = true; + } + break; + case '\r': + uart_putchar('\n'); + iwrap_buf_send(); + break; + case '\b': + iwrap_buf_del(); + break; + default: + if (breaked) { + print("\n"); + console_command(c); + breaked = false; + } else { + iwrap_buf_add(c); + } + break; + } + return true; + } +} + +uint8_t command_extra() +{ + return console_command(key2asc(host_get_first_key())); +} + +static uint8_t console_command(uint8_t c) +{ + switch (c) { + case 'h': + case '?': + print("\nCommands for Bluetooth(WT12/iWRAP):\n"); + print("r: reset. software reset by watchdog\n"); + print("i: insomniac. prevent KB from sleeping\n"); + print("c: iwrap_call. CALL for BT connection.\n"); +#ifdef HOST_VUSB + print("u: USB mode. switch to USB.\n"); + print("w: BT mode. switch to Bluetooth.\n"); +#endif + print("k: kill first connection.\n"); + print("Del: unpair first pairing.\n"); + print("\n"); + return 0; + case 'r': + print("reset\n"); + WD_AVR_RESET(); + return 1; + case 'i': + insomniac = !insomniac; + if (insomniac) + print("insomniac\n"); + else + print("not insomniac\n"); + return 1; + case 'c': + print("iwrap_call()\n"); + iwrap_call(); + return 1; +#ifdef HOST_VUSB + case 'u': + print("USB mode\n"); + init_vusb(); + change_driver(vusb_driver()); + //iwrap_kill(); + //iwrap_sleep(); + // disable suart receive interrut(PC5/PCINT13) + PCMSK1 &= ~(0b00100000); + PCICR &= ~(0b00000010); + return 1; + case 'w': + print("iWRAP mode\n"); + change_driver(iwrap_driver()); + disable_vusb(); + // enable suart receive interrut(PC5/PCINT13) + PCMSK1 |= 0b00100000; + PCICR |= 0b00000010; + return 1; +#endif + case 'k': + print("kill\n"); + iwrap_kill(); + return 1; + case 0x7F: // DELETE + print("unpair\n"); + iwrap_unpair(); + return 1; + } + return 0; +} + +// convert keycode into ascii charactor +static uint8_t key2asc(uint8_t key) +{ + switch (key) { + case KB_A: return 'a'; + case KB_B: return 'b'; + case KB_C: return 'c'; + case KB_D: return 'd'; + case KB_E: return 'e'; + case KB_F: return 'f'; + case KB_G: return 'g'; + case KB_H: return 'h'; + case KB_I: return 'i'; + case KB_J: return 'j'; + case KB_K: return 'k'; + case KB_L: return 'l'; + case KB_M: return 'm'; + case KB_N: return 'n'; + case KB_O: return 'o'; + case KB_P: return 'p'; + case KB_Q: return 'q'; + case KB_R: return 'r'; + case KB_S: return 's'; + case KB_T: return 't'; + case KB_U: return 'u'; + case KB_V: return 'v'; + case KB_W: return 'w'; + case KB_X: return 'x'; + case KB_Y: return 'y'; + case KB_Z: return 'z'; + case KB_1: return '1'; + case KB_2: return '2'; + case KB_3: return '3'; + case KB_4: return '4'; + case KB_5: return '5'; + case KB_6: return '6'; + case KB_7: return '7'; + case KB_8: return '8'; + case KB_9: return '9'; + case KB_0: return '0'; + case KB_ENTER: return '\n'; + case KB_ESCAPE: return 0x1B; + case KB_BSPACE: return '\b'; + case KB_TAB: return '\t'; + case KB_SPACE: return ' '; + case KB_MINUS: return '-'; + case KB_EQUAL: return '='; + case KB_LBRACKET: return '['; + case KB_RBRACKET: return ']'; + case KB_BSLASH: return '\\'; + case KB_NONUS_HASH: return '\\'; + case KB_SCOLON: return ';'; + case KB_QUOTE: return '\''; + case KB_GRAVE: return '`'; + case KB_COMMA: return ','; + case KB_DOT: return '.'; + case KB_SLASH: return '/'; + default: return 0x00; + } +} diff --git a/protocol/iwrap/suart.S b/protocol/iwrap/suart.S new file mode 100644 index 0000000000..1b02909638 --- /dev/null +++ b/protocol/iwrap/suart.S @@ -0,0 +1,156 @@ +;---------------------------------------------------------------------------; +; Software implemented UART module ; +; (C)ChaN, 2005 (http://elm-chan.org/) ; +;---------------------------------------------------------------------------; +; Bit rate settings: +; +; 1MHz 2MHz 4MHz 6MHz 8MHz 10MHz 12MHz 16MHz 20MHz +; 2.4kbps 138 - - - - - - - - +; 4.8kbps 68 138 - - - - - - - +; 9.6kbps 33 68 138 208 - - - - - +; 19.2kbps - 33 68 102 138 173 208 - - +; 38.4kbps - - 33 50 68 85 102 138 172 +; 57.6kbps - - 21 33 44 56 68 91 114 +; 115.2kbps - - - - 21 27 33 44 56 + +.nolist +#include +.list + +#define BPS 102 /* Bit delay. (see above table) */ +#define BIDIR 0 /* 0:Separated Tx/Rx, 1:Shared Tx/Rx */ + +#define OUT_1 sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 1 */ +#define OUT_0 cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 0 */ +#define SKIP_IN_1 sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 1 */ +#define SKIP_IN_0 sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 0 */ + + + +#ifdef SPM_PAGESIZE +.macro _LPMI reg + lpm \reg, Z+ +.endm +.macro _MOVW dh,dl, sh,sl + movw \dl, \sl +.endm +#else +.macro _LPMI reg + lpm + mov \reg, r0 + adiw ZL, 1 +.endm +.macro _MOVW dh,dl, sh,sl + mov \dl, \sl + mov \dh, \sh +.endm +#endif + + + +;---------------------------------------------------------------------------; +; Transmit a byte in serial format of N81 +; +;Prototype: void xmit (uint8_t data); +;Size: 16 words + +.global xmit +.func xmit +xmit: +#if BIDIR + ldi r23, BPS-1 ;Pre-idle time for bidirectional data line +5: dec r23 ; + brne 5b ;/ +#endif + in r0, _SFR_IO_ADDR(SREG) ;Save flags + + com r24 ;C = start bit + ldi r25, 10 ;Bit counter + cli ;Start critical section + +1: ldi r23, BPS-1 ;----- Bit transferring loop +2: dec r23 ;Wait for a bit time + brne 2b ;/ + brcs 3f ;MISO = bit to be sent + OUT_1 ; +3: brcc 4f ; + OUT_0 ;/ +4: lsr r24 ;Get next bit into C + dec r25 ;All bits sent? + brne 1b ; no, coutinue + + out _SFR_IO_ADDR(SREG), r0 ;End of critical section + ret +.endfunc + + + +;---------------------------------------------------------------------------; +; Receive a byte +; +;Prototype: uint8_t rcvr (void); +;Size: 19 words + +.global rcvr +.func rcvr +rcvr: + in r0, _SFR_IO_ADDR(SREG) ;Save flags + + ldi r24, 0x80 ;Receiving shift reg + cli ;Start critical section + +1: SKIP_IN_1 ;Wait for idle + rjmp 1b +2: SKIP_IN_0 ;Wait for start bit + rjmp 2b + ldi r25, BPS/2 ;Wait for half bit time +3: dec r25 + brne 3b + +4: ldi r25, BPS ;----- Bit receiving loop +5: dec r25 ;Wait for a bit time + brne 5b ;/ + lsr r24 ;Next bit + SKIP_IN_0 ;Get a data bit into r24.7 + ori r24, 0x80 + brcc 4b ;All bits received? no, continue + + out _SFR_IO_ADDR(SREG), r0 ;End of critical section + ret +.endfunc + + +; Not wait for start bit. This should be called after detecting start bit. +.global recv +.func recv +recv: + in r0, _SFR_IO_ADDR(SREG) ;Save flags + + ldi r24, 0x80 ;Receiving shift reg + cli ;Start critical section + +;1: SKIP_IN_1 ;Wait for idle +; rjmp 1b +;2: SKIP_IN_0 ;Wait for start bit +; rjmp 2b + ldi r25, BPS/2 ;Wait for half bit time +3: dec r25 + brne 3b + +4: ldi r25, BPS ;----- Bit receiving loop +5: dec r25 ;Wait for a bit time + brne 5b ;/ + lsr r24 ;Next bit + SKIP_IN_0 ;Get a data bit into r24.7 + ori r24, 0x80 + brcc 4b ;All bits received? no, continue + + ldi r25, BPS/2 ;Wait for half bit time +6: dec r25 + brne 6b +7: SKIP_IN_1 ;Wait for stop bit + rjmp 7b + + out _SFR_IO_ADDR(SREG), r0 ;End of critical section + ret +.endfunc diff --git a/protocol/iwrap/suart.h b/protocol/iwrap/suart.h new file mode 100644 index 0000000000..72725b998f --- /dev/null +++ b/protocol/iwrap/suart.h @@ -0,0 +1,8 @@ +#ifndef SUART +#define SUART + +void xmit(uint8_t); +uint8_t rcvr(void); +uint8_t recv(void); + +#endif /* SUART */ diff --git a/protocol/iwrap/wd.h b/protocol/iwrap/wd.h new file mode 100644 index 0000000000..99058f0331 --- /dev/null +++ b/protocol/iwrap/wd.h @@ -0,0 +1,159 @@ +/* This is from http://www.mtcnet.net/~henryvm/wdt/ */ +#ifndef _AVR_WD_H_ +#define _AVR_WD_H_ + +#include + +/* +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 //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<