Added Bulegiga iWRAP support into HHKB.(Bluetooth)
This commit is contained in:
parent
b703de7b29
commit
e67c988824
90 changed files with 3154 additions and 541 deletions
376
iwrap/iWRAP.txt
Normal file
376
iwrap/iWRAP.txt
Normal file
|
@ -0,0 +1,376 @@
|
|||
Bulegiga WT12
|
||||
=============
|
||||
WT12 is a bluetooth module from Bluegiga. http://www.bluegiga.com/
|
||||
|
||||
iWRAP
|
||||
higher layer interface for bluetooth firmware
|
||||
communicate with UART
|
||||
|
||||
iWRAP HID
|
||||
default setting
|
||||
115200 8bit/n/1/n
|
||||
|
||||
|
||||
TODO
|
||||
----
|
||||
KiCAD circuit/PCB design
|
||||
power saving
|
||||
AVR sleep(15ms by watch dog timer)
|
||||
WT12 sleep
|
||||
measuring current consumption
|
||||
measuring battery life of normal usage/idle/intensive usage
|
||||
software reset/bootloarder
|
||||
LED indicator(chaging/paring/connecting)
|
||||
license confirmation of suart.c
|
||||
consumer page is not working
|
||||
authenticate method/SSP
|
||||
SPP keyboard support
|
||||
SPP debug console support
|
||||
mouse wheel feature request to Bluegiga
|
||||
|
||||
|
||||
Problems
|
||||
--------
|
||||
power consumption
|
||||
no consumer page support(bug?)
|
||||
no mouse wheel support
|
||||
no paring management
|
||||
no interactive auth method
|
||||
|
||||
|
||||
UART hardware flow control
|
||||
--------------------------
|
||||
(iWRAP4 User Guide 9.5)
|
||||
Hardware flow control is enabled by default and it should not be disabled unless mandatory, because without the hardware flow control the data transmission may not be reliable.
|
||||
If the hardware flow control is enabled from PS-keys, but no flow control is used, the following steps should be implemented in the hardware design:
|
||||
- CTS pin must be grounded
|
||||
- RTS pin must be left floating
|
||||
|
||||
|
||||
Power Saving
|
||||
------------
|
||||
power consume
|
||||
without opimization: 4hr to shutdown(310mAh)
|
||||
2011/08/25: 9hr(310mAh) SNIFF MASTER sleep/WDTO_120MS
|
||||
|
||||
measure current consumption
|
||||
HHKB keyswitch matrix board
|
||||
idle
|
||||
scanning
|
||||
Bluegiga WT12 module
|
||||
SLEEP command
|
||||
deep sleep on/off in config bits
|
||||
|
||||
HHKB keyswich
|
||||
how to power off
|
||||
I/O pin configuration when sleeping
|
||||
FET switch for 5V regulator
|
||||
|
||||
Bluetooth module
|
||||
power off when in USB mode
|
||||
power off by FET switch
|
||||
|
||||
AVR configuration
|
||||
unused pins
|
||||
ADC
|
||||
|
||||
|
||||
|
||||
SET CONTROL CONFIG
|
||||
------------------
|
||||
SET CONTROL CONFIG 4810
|
||||
SET CONTROL CONFIG LIST
|
||||
SET CONTROL CONFIG 0000 0000 4910 DEEP_SLEEP KLUDGE INTERACTIVE_PIN UART_LATENCY
|
||||
|
||||
Bit14 UART low latency
|
||||
Bit11 Interactive pairing mode
|
||||
Bit04 Deep sleep
|
||||
|
||||
|
||||
Reconnection
|
||||
------------
|
||||
SET CONTROL AUTOCALL 1124 5000 HID
|
||||
1124 HID service class
|
||||
5000 interval ms
|
||||
|
||||
HID profile
|
||||
-----------
|
||||
This is needed to configure only once.
|
||||
SET PROFILE HID ON
|
||||
RESET
|
||||
|
||||
HID class
|
||||
---------
|
||||
SET BT CLASS 005C0 // keyboard/mouse combined devie
|
||||
|
||||
Pairing Security
|
||||
----------------
|
||||
Secure Simple Pairing(SSP)
|
||||
SET BT SSP 2 0 // Enables SSP for keyboard and Man-in-the-middle protection
|
||||
SET BT SSP 3 0 // Enables SSP just works mode
|
||||
|
||||
for keyboard with SSP
|
||||
SET BT AUTH * 0000
|
||||
SET BT SSP 2 0
|
||||
SET CONTROL CONFIG 800
|
||||
RESET
|
||||
|
||||
for keyboard without SSP
|
||||
SET BT AUTH * 0000
|
||||
SET CONTROL CONFIG 800
|
||||
RESET
|
||||
|
||||
AUTH
|
||||
AUTH xx:xx:xx:xx:xx:xx? // Pairing request event
|
||||
AUTH xx:xx:xx:xx:xx:xx 0000
|
||||
|
||||
SSP PASSKEY 78:dd:08:b7:e4:a2 ?
|
||||
SSP PASSKEY 78:dd:08:b7:e4:a2 xxxxx
|
||||
(SSP COMPLETE 78:dd:08:b7:e4:a2 HCI_ERROR_AUTH_FAIL // failed)
|
||||
RING 0 78:dd:08:b7:e4:a2 11 HID
|
||||
|
||||
Connecton
|
||||
RING xx:xx:xx:xx:xx:xx xx HID // connection event
|
||||
|
||||
KILL xx:xx:xx:xx:xx:xx
|
||||
|
||||
Mode
|
||||
----
|
||||
Command mode
|
||||
Data mode
|
||||
Raw mode
|
||||
(Simple mode not for a real keyboard)
|
||||
|
||||
Raw mode
|
||||
Keyboard:
|
||||
0x9f, length(10), 0xa1, 0x01, mods, 0x00, key1, key2, key3, key4, key5, key6
|
||||
|
||||
Mouse:
|
||||
0x9f, length(5), 0xa1, 0x02, buttons, X, Y
|
||||
|
||||
Consumer page:
|
||||
0x9f, length(5), 0xa1, 0x03, bitfield1, bitfield2, bitfield3
|
||||
|
||||
consumer page suage
|
||||
Bitfield 1:
|
||||
0x01 Volume Increment
|
||||
0x02 Volume Decrement
|
||||
0x04 Mute
|
||||
0x08 Play/Pause
|
||||
0x10 Scan Next Track
|
||||
0x20 Scan Previous Track
|
||||
0x40 Stop
|
||||
0x80 Eject
|
||||
Bitfield 2:
|
||||
0x01 Email Reader
|
||||
0x02 Application Control Search
|
||||
0x04 AC Bookmarks
|
||||
0x08 AC Home
|
||||
0x10 AC Back
|
||||
0x20 AC Forward
|
||||
0x40 AC Stop
|
||||
0x80 AC Refresh
|
||||
Bitfield 3:
|
||||
0x01 Application Launch Generic Consumer Control
|
||||
0x02 AL Internet Browser
|
||||
0x04 AL Calculator
|
||||
0x08 AL Terminal Lock / Screensaver
|
||||
0x10 AL Local Machine Browser
|
||||
0x20 AC Minimize
|
||||
0x40 Record
|
||||
0x80 Rewind
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
2011/07/13
|
||||
set
|
||||
SET BT BDADDR 00:07:80:47:22:14
|
||||
SET BT NAME HHKB pro BT
|
||||
SET BT CLASS 0005c0
|
||||
SET BT AUTH * 0000
|
||||
SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP
|
||||
SET BT LAP 9e8b33
|
||||
SET BT PAGEMODE 4 2000 1
|
||||
SET BT PAIR 78:dd:08:b7:e4:a2 a191189cd7e51030ad6a07848ce879bb
|
||||
SET BT POWER 3 3 3
|
||||
SET BT ROLE 0 f 7d00
|
||||
SET BT SNIFF 0 20 1 8
|
||||
SET BT SSP 2 1
|
||||
SET BT MTU 667
|
||||
SET CONTROL AUTOCALL 1124 3000 HID
|
||||
SET CONTROL BAUD 38400,8n1
|
||||
SET CONTROL CD 00 0
|
||||
SET CONTROL ECHO 7
|
||||
SET CONTROL ESCAPE 43 00 1
|
||||
SET CONTROL GAIN 0 5
|
||||
SET CONTROL INIT SET CONTROL MUX 0
|
||||
SET CONTROL MSC DTE 00 00 00 00 00 00
|
||||
SET CONTROL MUX 1
|
||||
SET CONTROL PIO 00 00
|
||||
SET CONTROL READY 00
|
||||
SET PROFILE HID f HID
|
||||
SET
|
||||
|
||||
info config
|
||||
|
||||
!!! THIS IS BETA RELEASE AND MAY BE USED FOR EVALUATION PURPOSES ONLY !!!
|
||||
|
||||
WRAP THOR AI (4.1.0 build 435)
|
||||
Copyright (c) 2003-2011 Bluegiga Technologies Inc.
|
||||
Compiled on Jun 28 2011 17:19:51, running on WT12-A module, psr v31
|
||||
AVRCP BGIO FTP HFP HFP_AG HID HID_CONSUMER_PAGE HSP LEDS MAP OTA PBAP PIO=0x00fc SSP SUBRATE TEST VOLUME
|
||||
- BOCK3 version 435 (Jun 28 2011 17:19:37) (max acl/sco 7/1)
|
||||
- Bluetooth version 2.1, Power class 2
|
||||
- Loader 4279, firmware 6297 (56-bit encryption), native execution mode
|
||||
- up 0 days, 06:23, 2 connections (pool 2)
|
||||
- User configuration:
|
||||
&028a = 0001 0000 0000 0011 0024 0000 0000 0010 0000 0080 0000 0000 0080 005f 009b 0034 00fb 0006
|
||||
&028b = 0000 0bb8
|
||||
&028d = 0001
|
||||
&0295 = 0000 0005 000b 0000 0003 0000 0000 0000 0000 0000 0000
|
||||
&0298 = a006
|
||||
&0299 = 0000 0000
|
||||
&02a3 = 0030 0030 0030 0030
|
||||
&02a4 = 009d 0000
|
||||
&02a5 = 0053 0045 0054 0020 0043 004f 004e 0054 0052 004f 004c 0020 004d 0055 0058 0020 0030
|
||||
&02a7 = 0000 05c0
|
||||
&02a8 = 4910 0000 0000
|
||||
&02aa = 0004 2000 0001 0033 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
&02ac = 0000 0000 002b 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000
|
||||
&02ad = 4848 424b 7020 6f72 4220 0054
|
||||
&02b3 = 0005 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003
|
||||
&02b7 = 000f 4948 0044
|
||||
&02bb = 8000
|
||||
READY.
|
||||
|
||||
|
||||
|
||||
|
||||
2011/07/07 settings:
|
||||
set
|
||||
SET BT BDADDR 00:07:80:47:22:14
|
||||
SET BT NAME HHKB Pro BT
|
||||
SET BT CLASS 0005c0
|
||||
SET BT AUTH * 000
|
||||
SET BT IDENT BT:47 f000 4.0.0 Bluegiga iWRAP
|
||||
SET BT LAP 9e8b33
|
||||
SET BT PAGEMODE 4 2000 1
|
||||
SET BT PAIR 78:dd:08:b7:e4:a2 9e54d0aabb1b4d73cfccddb1ea4ef2d6
|
||||
SET BT POWER 3 3 3
|
||||
SET BT ROLE 0 f 7d00
|
||||
SET BT SNIFF 0 20 1 8
|
||||
SET BT SSP 3 0
|
||||
SET BT MTU 667
|
||||
SET CONTROL BAUD 38400,8n1
|
||||
SET CONTROL CD 00 0
|
||||
SET CONTROL ECHO 7
|
||||
SET CONTROL ESCAPE 255 00 1
|
||||
SET CONTROL GAIN 0 5
|
||||
SET CONTROL INIT set control mux 0
|
||||
SET CONTROL MSC DTE 00 00 00 00 00 00
|
||||
SET CONTROL PREAMP 1 1
|
||||
SET CONTROL READY 00
|
||||
SET PROFILE HID HID
|
||||
SET PROFILE SPP Bluetooth Serial Port
|
||||
SET
|
||||
|
||||
info config
|
||||
WRAP THOR AI (4.0.0 build 317)
|
||||
Copyright (c) 2003-2010 Bluegiga Technologies Inc.
|
||||
Compiled on Apr 20 2010 16:44:28, running on WT12-A module, psr v31
|
||||
AVRCP FTP PBAP PIO=0x00fc SSP SUBRATE VOLUME
|
||||
- BOCK3 version 317 (Apr 20 2010 16:44:21) (max acl/sco 7/1)
|
||||
- Bluetooth version 2.1, Power class 2
|
||||
- Loader 4279, firmware 6297 (56-bit encryption), native execution mode
|
||||
- up 0 days, 00:00, 0 connections (pool 1)
|
||||
- User configuration:
|
||||
&028c = 0001 0020 0000 0001 0008 0000
|
||||
&028d = 0000
|
||||
&0296 = 0047 0001 f000 0400 6c42 6575 6967 6167 6920 5257 5041
|
||||
&0298 = c006
|
||||
&02a3 = 0030 0030 0030
|
||||
&02a4 = 009d 0000
|
||||
&02a5 = 0073 0065 0074 0020 0063 006f 006e 0074 0072 006f 006c 0020 006d 0075 0078 0020 0030
|
||||
&02a7 = 0000 05c0
|
||||
&02a8 = 0800 0000 0000
|
||||
&02ac = 0000 0000 00ff 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000
|
||||
&02ad = 4848 424b 5020 6f72 4220 0054
|
||||
&02b3 = 0004 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003
|
||||
&02b7 = 0000
|
||||
&02bb = 6c42 6575 6f74 746f 2068 6553 6972 6c61 5020 726f 0074
|
||||
READY.
|
||||
|
||||
|
||||
|
||||
2011/08/23:
|
||||
SET BT BDADDR 00:07:80:47:22:14
|
||||
SET BT NAME HHKB pro BT
|
||||
SET BT CLASS 0005c0
|
||||
SET BT AUTH * 0000
|
||||
SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP
|
||||
SET BT LAP 9e8b33
|
||||
SET BT PAGEMODE 4 2000 1
|
||||
SET BT PAIRCOUNT 4
|
||||
SET BT POWER 3 3 3
|
||||
SET BT ROLE 1 f 12c0
|
||||
SET BT SNIFF 10 2 1 8
|
||||
SET BT SSP 3 0
|
||||
SET BT MTU 667
|
||||
SET CONTROL BAUD 38400,8n1
|
||||
SET CONTROL CD 00 0
|
||||
SET CONTROL ECHO 7
|
||||
SET CONTROL ESCAPE 43 00 1
|
||||
SET CONTROL GAIN 0 5
|
||||
SET CONTROL INIT SET CONTROL MUX 0
|
||||
SET CONTROL MSC DTE 00 00 00 00 00 00
|
||||
SET CONTROL MUX 1
|
||||
SET CONTROL PIO 00 00
|
||||
SET CONTROL READY 00
|
||||
SET PROFILE HID 7 HIDKeyboardMouse
|
||||
SET
|
||||
|
||||
SET CONTROL CONFIG 0000 0004 481e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE DEEP_SLEEP INTERACTIVE_PIN UART_LATENCY 23D_NOKLUDGE
|
||||
|
||||
|
||||
|
||||
2011/08/25:
|
||||
SET BT BDADDR 00:07:80:47:22:14
|
||||
SET BT NAME HHKB pro BT
|
||||
SET BT CLASS 0005c0
|
||||
|
||||
SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP
|
||||
SET BT LAP 9e8b33
|
||||
SET BT PAGEMODE 4 2000 1
|
||||
SET BT PAIRCOUNT 4
|
||||
SET BT PAIR 78:dd:08:b7:e4:a2 0be83335a03fed8ededae42e99554e28
|
||||
SET BT POWER 3 3 3
|
||||
SET BT ROLE 1 f 12c0
|
||||
SET BT SNIFF 100 20 1 8
|
||||
SET BT SSP 3 0
|
||||
SET BT MTU 667
|
||||
SET CONTROL BAUD 38400,8n1
|
||||
SET CONTROL CD 00 0
|
||||
SET CONTROL ECHO 7
|
||||
SET CONTROL ESCAPE - 20 1
|
||||
SET CONTROL GAIN 0 5
|
||||
SET CONTROL INIT SET CONTROL MUX 0
|
||||
SET CONTROL MSC DTE 00 00 00 00 00 00
|
||||
SET CONTROL MUX 1
|
||||
SET CONTROL PIO 00 00
|
||||
SET CONTROL READY 00
|
||||
SET PROFILE HID f HIDKeyboardMouse
|
||||
SET
|
||||
|
||||
|
||||
SET CONTROL CONFIG 0000 0000 490e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE INTERACTIVE_PIN UART_LATENCY
|
||||
|
||||
|
||||
2011/09/08:
|
||||
SET CONTROL CONFIG 0000 0000 410e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE UART_LATENCY
|
||||
|
||||
Removed INTERACTIVE_PIN to avoid interactive auth and use SET BT AUTH pin(0000).
|
||||
|
||||
|
||||
EOF
|
467
iwrap/iwrap.c
Normal file
467
iwrap/iwrap.c
Normal file
|
@ -0,0 +1,467 @@
|
|||
/*
|
||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* host driver for Bulegiga iWRAP */
|
||||
/* Bluegiga BT12
|
||||
* Connections
|
||||
* Hardware UART Software UART BlueTooth
|
||||
* PC=====UART=======AVR=====SUART====iWRAP(BT12)-----------PC
|
||||
*
|
||||
* - Hardware UART for Debug Console to communicate iWRAP
|
||||
* - Software UART for iWRAP control to send keyboard/mouse data
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include "usb_keycodes.h"
|
||||
#include "suart.h"
|
||||
#include "uart.h"
|
||||
#include "report.h"
|
||||
#include "host_driver.h"
|
||||
#include "iwrap.h"
|
||||
#include "print.h"
|
||||
|
||||
|
||||
/* iWRAP MUX mode utils. 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf) */
|
||||
#define MUX_HEADER(LINK, LENGTH) do { \
|
||||
xmit(0xbf); /* SOF */ \
|
||||
xmit(LINK); /* Link */ \
|
||||
xmit(0x00); /* Flags */ \
|
||||
xmit(LENGTH); /* Length */ \
|
||||
} while (0)
|
||||
#define MUX_FOOTER(LINK) xmit(LINK^0xff)
|
||||
|
||||
|
||||
static uint8_t connected = 0;
|
||||
//static uint8_t channel = 1;
|
||||
|
||||
/* iWRAP buffer */
|
||||
#define MUX_BUF_SIZE 64
|
||||
static char buf[MUX_BUF_SIZE];
|
||||
static uint8_t snd_pos = 0;
|
||||
|
||||
#define MUX_RCV_BUF_SIZE 256
|
||||
static char rcv_buf[MUX_RCV_BUF_SIZE];
|
||||
static uint8_t rcv_head = 0;
|
||||
static uint8_t rcv_tail = 0;
|
||||
|
||||
|
||||
/* receive buffer */
|
||||
static void rcv_enq(char c)
|
||||
{
|
||||
uint8_t next = (rcv_head + 1) % MUX_RCV_BUF_SIZE;
|
||||
if (next != rcv_tail) {
|
||||
rcv_buf[rcv_head] = c;
|
||||
rcv_head = next;
|
||||
}
|
||||
}
|
||||
|
||||
static char rcv_deq(void)
|
||||
{
|
||||
char c = 0;
|
||||
if (rcv_head != rcv_tail) {
|
||||
c = rcv_buf[rcv_tail++];
|
||||
rcv_tail %= MUX_RCV_BUF_SIZE;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
static char rcv_peek(void)
|
||||
{
|
||||
if (rcv_head == rcv_tail)
|
||||
return 0;
|
||||
return rcv_buf[rcv_tail];
|
||||
}
|
||||
*/
|
||||
|
||||
static void rcv_clear(void)
|
||||
{
|
||||
rcv_tail = rcv_head = 0;
|
||||
}
|
||||
|
||||
/* iWRAP response */
|
||||
ISR(PCINT1_vect, ISR_BLOCK) // recv() runs away in case of ISR_NOBLOCK
|
||||
{
|
||||
if ((SUART_IN_PIN & (1<<SUART_IN_BIT)))
|
||||
return;
|
||||
|
||||
static volatile uint8_t mux_state = 0xff;
|
||||
static volatile uint8_t mux_link = 0xff;
|
||||
uint8_t c = recv();
|
||||
switch (mux_state) {
|
||||
case 0xff: // SOF
|
||||
if (c == 0xbf)
|
||||
mux_state--;
|
||||
break;
|
||||
case 0xfe: // Link
|
||||
mux_state--;
|
||||
mux_link = c;
|
||||
break;
|
||||
case 0xfd: // Flags
|
||||
mux_state--;
|
||||
break;
|
||||
case 0xfc: // Length
|
||||
mux_state = c;
|
||||
break;
|
||||
case 0x00:
|
||||
mux_state = 0xff;
|
||||
mux_link = 0xff;
|
||||
break;
|
||||
default:
|
||||
if (mux_state--) {
|
||||
uart_putchar(c);
|
||||
rcv_enq(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*
|
||||
* iWRAP communication
|
||||
*------------------------------------------------------------------*/
|
||||
void iwrap_init(void)
|
||||
{
|
||||
// reset iWRAP if in already MUX mode after AVR software-reset
|
||||
iwrap_send("RESET");
|
||||
iwrap_mux_send("RESET");
|
||||
_delay_ms(3000);
|
||||
iwrap_send("\r\nSET CONTROL MUX 1\r\n");
|
||||
_delay_ms(500);
|
||||
iwrap_check_connection();
|
||||
}
|
||||
|
||||
void iwrap_mux_send(const char *s)
|
||||
{
|
||||
rcv_clear();
|
||||
MUX_HEADER(0xff, strlen((char *)s));
|
||||
iwrap_send(s);
|
||||
MUX_FOOTER(0xff);
|
||||
}
|
||||
|
||||
void iwrap_send(const char *s)
|
||||
{
|
||||
while (*s)
|
||||
xmit(*s++);
|
||||
}
|
||||
|
||||
/* send buffer */
|
||||
void iwrap_buf_add(uint8_t c)
|
||||
{
|
||||
// need space for '\0'
|
||||
if (snd_pos < MUX_BUF_SIZE-1)
|
||||
buf[snd_pos++] = c;
|
||||
}
|
||||
|
||||
void iwrap_buf_del(void)
|
||||
{
|
||||
if (snd_pos)
|
||||
snd_pos--;
|
||||
}
|
||||
|
||||
void iwrap_buf_send(void)
|
||||
{
|
||||
buf[snd_pos] = '\0';
|
||||
snd_pos = 0;
|
||||
iwrap_mux_send(buf);
|
||||
}
|
||||
|
||||
void iwrap_call(void)
|
||||
{
|
||||
char *p;
|
||||
|
||||
iwrap_mux_send("SET BT PAIR");
|
||||
_delay_ms(500);
|
||||
|
||||
p = rcv_buf + rcv_tail;
|
||||
while (!strncmp(p, "SET BT PAIR", 11)) {
|
||||
p += 7;
|
||||
strncpy(p, "CALL", 4);
|
||||
strncpy(p+22, " 11 HID\n\0", 9);
|
||||
print_S(p);
|
||||
iwrap_mux_send(p);
|
||||
// TODO: skip to next line
|
||||
p += 57;
|
||||
|
||||
DEBUG_LED_CONFIG;
|
||||
DEBUG_LED_ON;
|
||||
_delay_ms(500);
|
||||
DEBUG_LED_OFF;
|
||||
_delay_ms(500);
|
||||
DEBUG_LED_ON;
|
||||
_delay_ms(500);
|
||||
DEBUG_LED_OFF;
|
||||
_delay_ms(500);
|
||||
DEBUG_LED_ON;
|
||||
_delay_ms(500);
|
||||
DEBUG_LED_OFF;
|
||||
_delay_ms(500);
|
||||
DEBUG_LED_ON;
|
||||
_delay_ms(500);
|
||||
DEBUG_LED_OFF;
|
||||
_delay_ms(500);
|
||||
DEBUG_LED_ON;
|
||||
_delay_ms(500);
|
||||
DEBUG_LED_OFF;
|
||||
_delay_ms(500);
|
||||
}
|
||||
iwrap_check_connection();
|
||||
}
|
||||
|
||||
void iwrap_kill(void)
|
||||
{
|
||||
char c;
|
||||
iwrap_mux_send("LIST");
|
||||
_delay_ms(500);
|
||||
|
||||
while ((c = rcv_deq()) && c != '\n') ;
|
||||
if (strncmp(rcv_buf + rcv_tail, "LIST ", 5)) {
|
||||
print("no connection to kill.\n");
|
||||
return;
|
||||
}
|
||||
// skip 10 'space' chars
|
||||
for (uint8_t i = 10; i; i--)
|
||||
while ((c = rcv_deq()) && c != ' ') ;
|
||||
|
||||
char *p = rcv_buf + rcv_tail - 5;
|
||||
strncpy(p, "KILL ", 5);
|
||||
strncpy(p + 22, "\n\0", 2);
|
||||
print_S(p);
|
||||
iwrap_mux_send(p);
|
||||
_delay_ms(500);
|
||||
|
||||
iwrap_check_connection();
|
||||
}
|
||||
|
||||
void iwrap_unpair(void)
|
||||
{
|
||||
iwrap_mux_send("SET BT PAIR");
|
||||
_delay_ms(500);
|
||||
|
||||
char *p = rcv_buf + rcv_tail;
|
||||
if (!strncmp(p, "SET BT PAIR", 11)) {
|
||||
strncpy(p+29, "\n\0", 2);
|
||||
print_S(p);
|
||||
iwrap_mux_send(p);
|
||||
}
|
||||
}
|
||||
|
||||
void iwrap_sleep(void)
|
||||
{
|
||||
iwrap_mux_send("SLEEP");
|
||||
}
|
||||
|
||||
void iwrap_sniff(void)
|
||||
{
|
||||
}
|
||||
|
||||
void iwrap_subrate(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool iwrap_failed(void)
|
||||
{
|
||||
if (strncmp(rcv_buf, "SYNTAX ERROR", 12))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t iwrap_connected(void)
|
||||
{
|
||||
return connected;
|
||||
}
|
||||
|
||||
uint8_t iwrap_check_connection(void)
|
||||
{
|
||||
iwrap_mux_send("LIST");
|
||||
_delay_ms(100);
|
||||
|
||||
if (strncmp(rcv_buf, "LIST ", 5) || !strncmp(rcv_buf, "LIST 0", 6))
|
||||
connected = 0;
|
||||
else
|
||||
connected = 1;
|
||||
return connected;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*
|
||||
* Host driver
|
||||
*------------------------------------------------------------------*/
|
||||
static uint8_t keyboard_leds(void);
|
||||
static void send_keyboard(report_keyboard_t *report);
|
||||
static void send_mouse(report_mouse_t *report);
|
||||
static void send_system(uint16_t data);
|
||||
static void send_consumer(uint16_t data);
|
||||
|
||||
static host_driver_t driver = {
|
||||
keyboard_leds,
|
||||
send_keyboard,
|
||||
send_mouse,
|
||||
send_system,
|
||||
send_consumer
|
||||
};
|
||||
|
||||
host_driver_t *iwrap_driver(void)
|
||||
{
|
||||
return &driver;
|
||||
}
|
||||
|
||||
static uint8_t keyboard_leds(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void send_keyboard(report_keyboard_t *report)
|
||||
{
|
||||
if (!iwrap_connected() && !iwrap_check_connection()) return;
|
||||
MUX_HEADER(0x01, 0x0c);
|
||||
// HID raw mode header
|
||||
xmit(0x9f);
|
||||
xmit(0x0a); // Length
|
||||
xmit(0xa1); // keyboard report
|
||||
xmit(0x01);
|
||||
xmit(report->mods);
|
||||
xmit(0x00); // reserved byte(always 0)
|
||||
xmit(report->keys[0]);
|
||||
xmit(report->keys[1]);
|
||||
xmit(report->keys[2]);
|
||||
xmit(report->keys[3]);
|
||||
xmit(report->keys[4]);
|
||||
xmit(report->keys[5]);
|
||||
MUX_FOOTER(0x01);
|
||||
}
|
||||
|
||||
static void send_mouse(report_mouse_t *report)
|
||||
{
|
||||
#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE)
|
||||
if (!iwrap_connected() && !iwrap_check_connection()) return;
|
||||
MUX_HEADER(0x01, 0x07);
|
||||
// HID raw mode header
|
||||
xmit(0x9f);
|
||||
xmit(0x05); // Length
|
||||
xmit(0xa1); // mouse report
|
||||
xmit(0x02);
|
||||
xmit(report->buttons);
|
||||
xmit(report->x);
|
||||
xmit(report->y);
|
||||
MUX_FOOTER(0x01);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void send_system(uint16_t data)
|
||||
{
|
||||
/* not supported */
|
||||
}
|
||||
|
||||
static void send_consumer(uint16_t data)
|
||||
{
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
static uint16_t last_data = 0;
|
||||
uint8_t bits1 = 0;
|
||||
uint8_t bits2 = 0;
|
||||
uint8_t bits3 = 0;
|
||||
|
||||
if (!iwrap_connected() && !iwrap_check_connection()) return;
|
||||
if (data == last_data) return;
|
||||
last_data = data;
|
||||
|
||||
// 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf)
|
||||
switch (data) {
|
||||
case AUDIO_VOL_UP:
|
||||
bits1 = 0x01;
|
||||
break;
|
||||
case AUDIO_VOL_DOWN:
|
||||
bits1 = 0x02;
|
||||
break;
|
||||
case AUDIO_MUTE:
|
||||
bits1 = 0x04;
|
||||
break;
|
||||
case TRANSPORT_PLAY_PAUSE:
|
||||
bits1 = 0x08;
|
||||
break;
|
||||
case TRANSPORT_NEXT_TRACK:
|
||||
bits1 = 0x10;
|
||||
break;
|
||||
case TRANSPORT_PREV_TRACK:
|
||||
bits1 = 0x20;
|
||||
break;
|
||||
case TRANSPORT_STOP:
|
||||
bits1 = 0x40;
|
||||
break;
|
||||
case TRANSPORT_EJECT:
|
||||
bits1 = 0x80;
|
||||
break;
|
||||
case AL_EMAIL:
|
||||
bits2 = 0x01;
|
||||
break;
|
||||
case AC_SEARCH:
|
||||
bits2 = 0x02;
|
||||
break;
|
||||
case AC_BOOKMARKS:
|
||||
bits2 = 0x04;
|
||||
break;
|
||||
case AC_HOME:
|
||||
bits2 = 0x08;
|
||||
break;
|
||||
case AC_BACK:
|
||||
bits2 = 0x10;
|
||||
break;
|
||||
case AC_FORWARD:
|
||||
bits2 = 0x20;
|
||||
break;
|
||||
case AC_STOP:
|
||||
bits2 = 0x40;
|
||||
break;
|
||||
case AC_REFRESH:
|
||||
bits2 = 0x80;
|
||||
break;
|
||||
case AL_CC_CONFIG:
|
||||
bits3 = 0x01;
|
||||
break;
|
||||
case AL_CALCULATOR:
|
||||
bits3 = 0x04;
|
||||
break;
|
||||
case AL_LOCK:
|
||||
bits3 = 0x08;
|
||||
break;
|
||||
case AL_LOCAL_BROWSER:
|
||||
bits3 = 0x10;
|
||||
break;
|
||||
case AC_MINIMIZE:
|
||||
bits3 = 0x20;
|
||||
break;
|
||||
case TRANSPORT_RECORD:
|
||||
bits3 = 0x40;
|
||||
break;
|
||||
case TRANSPORT_REWIND:
|
||||
bits3 = 0x80;
|
||||
break;
|
||||
}
|
||||
|
||||
MUX_HEADER(0x01, 0x07);
|
||||
xmit(0x9f);
|
||||
xmit(0x05); // Length
|
||||
xmit(0xa1); // consumer report
|
||||
xmit(0x03);
|
||||
xmit(bits1);
|
||||
xmit(bits2);
|
||||
xmit(bits3);
|
||||
MUX_FOOTER(0x01);
|
||||
#endif
|
||||
}
|
49
iwrap/iwrap.h
Normal file
49
iwrap/iwrap.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef IWRAP_H
|
||||
#define IWRAP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "host_driver.h"
|
||||
|
||||
|
||||
/* enable iWRAP MUX mode */
|
||||
#define MUX_MODE
|
||||
|
||||
|
||||
host_driver_t *iwrap_driver(void);
|
||||
|
||||
void iwrap_init(void);
|
||||
void iwrap_send(const char *s);
|
||||
void iwrap_mux_send(const char *s);
|
||||
void iwrap_buf_send(void);
|
||||
void iwrap_buf_add(uint8_t c);
|
||||
void iwrap_buf_del(void);
|
||||
|
||||
void iwrap_call(void);
|
||||
void iwrap_kill(void);
|
||||
void iwrap_unpair(void);
|
||||
void iwrap_sleep(void);
|
||||
void iwrap_sniff(void);
|
||||
void iwrap_subrate(void);
|
||||
bool iwrap_failed(void);
|
||||
uint8_t iwrap_connected(void);
|
||||
uint8_t iwrap_check_connection(void);
|
||||
|
||||
#endif
|
378
iwrap/main.c
Normal file
378
iwrap/main.c
Normal file
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
Copyright 2011 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
//#include <avr/wdt.h>
|
||||
#include "wd.h" // in order to use watchdog in interrupt mode
|
||||
#include <avr/sleep.h>
|
||||
#include <util/delay.h>
|
||||
#include <avr/power.h>
|
||||
#include "keyboard.h"
|
||||
#include "matrix.h"
|
||||
#include "host.h"
|
||||
#include "iwrap.h"
|
||||
#ifdef HOST_VUSB
|
||||
# include "vusb.h"
|
||||
# include "usbdrv.h"
|
||||
#endif
|
||||
#include "uart.h"
|
||||
#include "suart.h"
|
||||
#include "timer.h"
|
||||
#include "debug.h"
|
||||
#include "usb_keycodes.h"
|
||||
#include "command.h"
|
||||
|
||||
|
||||
static void sleep(uint8_t term);
|
||||
static bool console(void);
|
||||
static uint8_t console_command(uint8_t c);
|
||||
static uint8_t key2asc(uint8_t key);
|
||||
|
||||
|
||||
/*
|
||||
static void set_prr(void)
|
||||
{
|
||||
power_adc_disable();
|
||||
power_spi_disable();
|
||||
power_twi_disable();
|
||||
#ifndef TIMER_H
|
||||
//power_timer0_disable(); // used in timer.c
|
||||
#endif
|
||||
power_timer1_disable();
|
||||
power_timer2_disable();
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
static void pullup_pins(void)
|
||||
{
|
||||
// DDRs are set to 0(input) by default.
|
||||
#ifdef PORTA
|
||||
PORTA = 0xFF;
|
||||
#endif
|
||||
PORTB = 0xFF;
|
||||
PORTC = 0xFF;
|
||||
PORTD = 0xFF;
|
||||
#ifdef PORTE
|
||||
PORTE = 0xFF;
|
||||
#endif
|
||||
#ifdef PORTE
|
||||
PORTF = 0xFF;
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HOST_VUSB
|
||||
static void disable_vusb(void)
|
||||
{
|
||||
// disable interrupt & disconnect to prevent host from enumerating
|
||||
USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT);
|
||||
usbDeviceDisconnect();
|
||||
}
|
||||
|
||||
static void enable_vusb(void)
|
||||
{
|
||||
USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
|
||||
usbDeviceConnect();
|
||||
}
|
||||
|
||||
static void init_vusb(void)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
usbInit();
|
||||
disable_vusb();
|
||||
/* fake USB disconnect for > 250 ms */
|
||||
while(--i){
|
||||
_delay_ms(1);
|
||||
}
|
||||
enable_vusb();
|
||||
}
|
||||
#endif
|
||||
|
||||
void change_driver(host_driver_t *driver)
|
||||
{
|
||||
host_clear_keyboard_report();
|
||||
host_swap_keyboard_report();
|
||||
host_clear_keyboard_report();
|
||||
host_send_keyboard_report();
|
||||
_delay_ms(1000);
|
||||
host_set_driver(driver);
|
||||
}
|
||||
|
||||
|
||||
static bool sleeping = false;
|
||||
static bool insomniac = false; // TODO: should be false for power saving
|
||||
static uint16_t last_timer = 0;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
MCUSR = 0;
|
||||
clock_prescale_set(clock_div_1);
|
||||
WD_SET(WD_OFF);
|
||||
|
||||
// power saving: the result is worse than nothing... why?
|
||||
//pullup_pins();
|
||||
//set_prr();
|
||||
|
||||
print_enable = true;
|
||||
debug_enable = false;
|
||||
|
||||
#ifdef HOST_VUSB
|
||||
disable_vusb();
|
||||
#endif
|
||||
uart_init(115200);
|
||||
keyboard_init();
|
||||
print("\nSend BREAK for UART Console Commands.\n");
|
||||
|
||||
// TODO: move to iWRAP/suart file
|
||||
print("suart init\n");
|
||||
// suart init
|
||||
// PC4: Tx Output IDLE(Hi)
|
||||
PORTC |= (1<<4);
|
||||
DDRC |= (1<<4);
|
||||
// PC5: Rx Input(pull-up)
|
||||
PORTC |= (1<<5);
|
||||
DDRC &= ~(1<<5);
|
||||
// suart receive interrut(PC5/PCINT13)
|
||||
PCMSK1 = 0b00100000;
|
||||
PCICR = 0b00000010;
|
||||
|
||||
host_set_driver(iwrap_driver());
|
||||
|
||||
print("iwrap_init()\n");
|
||||
iwrap_init();
|
||||
iwrap_call();
|
||||
|
||||
last_timer = timer_read();
|
||||
while (true) {
|
||||
#ifdef HOST_VUSB
|
||||
if (host_get_driver() == vusb_driver())
|
||||
usbPoll();
|
||||
#endif
|
||||
keyboard_proc();
|
||||
#ifdef HOST_VUSB
|
||||
if (host_get_driver() == vusb_driver())
|
||||
vusb_transfer_keyboard();
|
||||
#endif
|
||||
if (matrix_is_modified() || console()) {
|
||||
last_timer = timer_read();
|
||||
sleeping = false;
|
||||
} else if (!sleeping && timer_elapsed(last_timer) > 4000) {
|
||||
sleeping = true;
|
||||
iwrap_check_connection();
|
||||
}
|
||||
|
||||
if (host_get_driver() == iwrap_driver()) {
|
||||
if (sleeping && !insomniac) {
|
||||
_delay_ms(1); // wait for UART to send
|
||||
iwrap_sleep();
|
||||
sleep(WDTO_60MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sleep(uint8_t term)
|
||||
{
|
||||
WD_SET(WD_IRQ, term);
|
||||
|
||||
cli();
|
||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
||||
sleep_enable();
|
||||
sleep_bod_disable();
|
||||
sei();
|
||||
sleep_cpu();
|
||||
sleep_disable();
|
||||
|
||||
WD_SET(WD_OFF);
|
||||
}
|
||||
|
||||
ISR(WDT_vect)
|
||||
{
|
||||
// wake up
|
||||
}
|
||||
|
||||
static bool console(void)
|
||||
{
|
||||
// Send to Bluetoot module WT12
|
||||
static bool breaked = false;
|
||||
if (!uart_available())
|
||||
return false;
|
||||
else {
|
||||
uint8_t c;
|
||||
c = uart_getchar();
|
||||
uart_putchar(c);
|
||||
switch (c) {
|
||||
case 0x00: // BREAK signal
|
||||
if (!breaked) {
|
||||
print("break(? for help): ");
|
||||
breaked = true;
|
||||
}
|
||||
break;
|
||||
case '\r':
|
||||
uart_putchar('\n');
|
||||
iwrap_buf_send();
|
||||
break;
|
||||
case '\b':
|
||||
iwrap_buf_del();
|
||||
break;
|
||||
default:
|
||||
if (breaked) {
|
||||
print("\n");
|
||||
console_command(c);
|
||||
breaked = false;
|
||||
} else {
|
||||
iwrap_buf_add(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t command_extra()
|
||||
{
|
||||
return console_command(key2asc(host_get_first_key()));
|
||||
}
|
||||
|
||||
static uint8_t console_command(uint8_t c)
|
||||
{
|
||||
switch (c) {
|
||||
case 'h':
|
||||
case '?':
|
||||
print("\nCommands for Bluetooth(WT12/iWRAP):\n");
|
||||
print("r: reset. software reset by watchdog\n");
|
||||
print("i: insomniac. prevent KB from sleeping\n");
|
||||
print("c: iwrap_call. CALL for BT connection.\n");
|
||||
#ifdef HOST_VUSB
|
||||
print("u: USB mode. switch to USB.\n");
|
||||
print("w: BT mode. switch to Bluetooth.\n");
|
||||
#endif
|
||||
print("k: kill first connection.\n");
|
||||
print("Del: unpair first pairing.\n");
|
||||
print("\n");
|
||||
return 0;
|
||||
case 'r':
|
||||
print("reset\n");
|
||||
WD_AVR_RESET();
|
||||
return 1;
|
||||
case 'i':
|
||||
insomniac = !insomniac;
|
||||
if (insomniac)
|
||||
print("insomniac\n");
|
||||
else
|
||||
print("not insomniac\n");
|
||||
return 1;
|
||||
case 'c':
|
||||
print("iwrap_call()\n");
|
||||
iwrap_call();
|
||||
return 1;
|
||||
#ifdef HOST_VUSB
|
||||
case 'u':
|
||||
print("USB mode\n");
|
||||
init_vusb();
|
||||
change_driver(vusb_driver());
|
||||
//iwrap_kill();
|
||||
//iwrap_sleep();
|
||||
// disable suart receive interrut(PC5/PCINT13)
|
||||
PCMSK1 &= ~(0b00100000);
|
||||
PCICR &= ~(0b00000010);
|
||||
return 1;
|
||||
case 'w':
|
||||
print("iWRAP mode\n");
|
||||
change_driver(iwrap_driver());
|
||||
disable_vusb();
|
||||
// enable suart receive interrut(PC5/PCINT13)
|
||||
PCMSK1 |= 0b00100000;
|
||||
PCICR |= 0b00000010;
|
||||
return 1;
|
||||
#endif
|
||||
case 'k':
|
||||
print("kill\n");
|
||||
iwrap_kill();
|
||||
return 1;
|
||||
case 0x7F: // DELETE
|
||||
print("unpair\n");
|
||||
iwrap_unpair();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// convert keycode into ascii charactor
|
||||
static uint8_t key2asc(uint8_t key)
|
||||
{
|
||||
switch (key) {
|
||||
case KB_A: return 'a';
|
||||
case KB_B: return 'b';
|
||||
case KB_C: return 'c';
|
||||
case KB_D: return 'd';
|
||||
case KB_E: return 'e';
|
||||
case KB_F: return 'f';
|
||||
case KB_G: return 'g';
|
||||
case KB_H: return 'h';
|
||||
case KB_I: return 'i';
|
||||
case KB_J: return 'j';
|
||||
case KB_K: return 'k';
|
||||
case KB_L: return 'l';
|
||||
case KB_M: return 'm';
|
||||
case KB_N: return 'n';
|
||||
case KB_O: return 'o';
|
||||
case KB_P: return 'p';
|
||||
case KB_Q: return 'q';
|
||||
case KB_R: return 'r';
|
||||
case KB_S: return 's';
|
||||
case KB_T: return 't';
|
||||
case KB_U: return 'u';
|
||||
case KB_V: return 'v';
|
||||
case KB_W: return 'w';
|
||||
case KB_X: return 'x';
|
||||
case KB_Y: return 'y';
|
||||
case KB_Z: return 'z';
|
||||
case KB_1: return '1';
|
||||
case KB_2: return '2';
|
||||
case KB_3: return '3';
|
||||
case KB_4: return '4';
|
||||
case KB_5: return '5';
|
||||
case KB_6: return '6';
|
||||
case KB_7: return '7';
|
||||
case KB_8: return '8';
|
||||
case KB_9: return '9';
|
||||
case KB_0: return '0';
|
||||
case KB_ENTER: return '\n';
|
||||
case KB_ESCAPE: return 0x1B;
|
||||
case KB_BSPACE: return '\b';
|
||||
case KB_TAB: return '\t';
|
||||
case KB_SPACE: return ' ';
|
||||
case KB_MINUS: return '-';
|
||||
case KB_EQUAL: return '=';
|
||||
case KB_LBRACKET: return '[';
|
||||
case KB_RBRACKET: return ']';
|
||||
case KB_BSLASH: return '\\';
|
||||
case KB_NONUS_HASH: return '\\';
|
||||
case KB_SCOLON: return ';';
|
||||
case KB_QUOTE: return '\'';
|
||||
case KB_GRAVE: return '`';
|
||||
case KB_COMMA: return ',';
|
||||
case KB_DOT: return '.';
|
||||
case KB_SLASH: return '/';
|
||||
default: return 0x00;
|
||||
}
|
||||
}
|
156
iwrap/suart.S
Normal file
156
iwrap/suart.S
Normal file
|
@ -0,0 +1,156 @@
|
|||
;---------------------------------------------------------------------------;
|
||||
; Software implemented UART module ;
|
||||
; (C)ChaN, 2005 (http://elm-chan.org/) ;
|
||||
;---------------------------------------------------------------------------;
|
||||
; Bit rate settings:
|
||||
;
|
||||
; 1MHz 2MHz 4MHz 6MHz 8MHz 10MHz 12MHz 16MHz 20MHz
|
||||
; 2.4kbps 138 - - - - - - - -
|
||||
; 4.8kbps 68 138 - - - - - - -
|
||||
; 9.6kbps 33 68 138 208 - - - - -
|
||||
; 19.2kbps - 33 68 102 138 173 208 - -
|
||||
; 38.4kbps - - 33 50 68 85 102 138 172
|
||||
; 57.6kbps - - 21 33 44 56 68 91 114
|
||||
; 115.2kbps - - - - 21 27 33 44 56
|
||||
|
||||
.nolist
|
||||
#include <avr/io.h>
|
||||
.list
|
||||
|
||||
#define BPS 102 /* Bit delay. (see above table) */
|
||||
#define BIDIR 0 /* 0:Separated Tx/Rx, 1:Shared Tx/Rx */
|
||||
|
||||
#define OUT_1 sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 1 */
|
||||
#define OUT_0 cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 0 */
|
||||
#define SKIP_IN_1 sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 1 */
|
||||
#define SKIP_IN_0 sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 0 */
|
||||
|
||||
|
||||
|
||||
#ifdef SPM_PAGESIZE
|
||||
.macro _LPMI reg
|
||||
lpm \reg, Z+
|
||||
.endm
|
||||
.macro _MOVW dh,dl, sh,sl
|
||||
movw \dl, \sl
|
||||
.endm
|
||||
#else
|
||||
.macro _LPMI reg
|
||||
lpm
|
||||
mov \reg, r0
|
||||
adiw ZL, 1
|
||||
.endm
|
||||
.macro _MOVW dh,dl, sh,sl
|
||||
mov \dl, \sl
|
||||
mov \dh, \sh
|
||||
.endm
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------;
|
||||
; Transmit a byte in serial format of N81
|
||||
;
|
||||
;Prototype: void xmit (uint8_t data);
|
||||
;Size: 16 words
|
||||
|
||||
.global xmit
|
||||
.func xmit
|
||||
xmit:
|
||||
#if BIDIR
|
||||
ldi r23, BPS-1 ;Pre-idle time for bidirectional data line
|
||||
5: dec r23 ;
|
||||
brne 5b ;/
|
||||
#endif
|
||||
in r0, _SFR_IO_ADDR(SREG) ;Save flags
|
||||
|
||||
com r24 ;C = start bit
|
||||
ldi r25, 10 ;Bit counter
|
||||
cli ;Start critical section
|
||||
|
||||
1: ldi r23, BPS-1 ;----- Bit transferring loop
|
||||
2: dec r23 ;Wait for a bit time
|
||||
brne 2b ;/
|
||||
brcs 3f ;MISO = bit to be sent
|
||||
OUT_1 ;
|
||||
3: brcc 4f ;
|
||||
OUT_0 ;/
|
||||
4: lsr r24 ;Get next bit into C
|
||||
dec r25 ;All bits sent?
|
||||
brne 1b ; no, coutinue
|
||||
|
||||
out _SFR_IO_ADDR(SREG), r0 ;End of critical section
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------;
|
||||
; Receive a byte
|
||||
;
|
||||
;Prototype: uint8_t rcvr (void);
|
||||
;Size: 19 words
|
||||
|
||||
.global rcvr
|
||||
.func rcvr
|
||||
rcvr:
|
||||
in r0, _SFR_IO_ADDR(SREG) ;Save flags
|
||||
|
||||
ldi r24, 0x80 ;Receiving shift reg
|
||||
cli ;Start critical section
|
||||
|
||||
1: SKIP_IN_1 ;Wait for idle
|
||||
rjmp 1b
|
||||
2: SKIP_IN_0 ;Wait for start bit
|
||||
rjmp 2b
|
||||
ldi r25, BPS/2 ;Wait for half bit time
|
||||
3: dec r25
|
||||
brne 3b
|
||||
|
||||
4: ldi r25, BPS ;----- Bit receiving loop
|
||||
5: dec r25 ;Wait for a bit time
|
||||
brne 5b ;/
|
||||
lsr r24 ;Next bit
|
||||
SKIP_IN_0 ;Get a data bit into r24.7
|
||||
ori r24, 0x80
|
||||
brcc 4b ;All bits received? no, continue
|
||||
|
||||
out _SFR_IO_ADDR(SREG), r0 ;End of critical section
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
||||
; Not wait for start bit. This should be called after detecting start bit.
|
||||
.global recv
|
||||
.func recv
|
||||
recv:
|
||||
in r0, _SFR_IO_ADDR(SREG) ;Save flags
|
||||
|
||||
ldi r24, 0x80 ;Receiving shift reg
|
||||
cli ;Start critical section
|
||||
|
||||
;1: SKIP_IN_1 ;Wait for idle
|
||||
; rjmp 1b
|
||||
;2: SKIP_IN_0 ;Wait for start bit
|
||||
; rjmp 2b
|
||||
ldi r25, BPS/2 ;Wait for half bit time
|
||||
3: dec r25
|
||||
brne 3b
|
||||
|
||||
4: ldi r25, BPS ;----- Bit receiving loop
|
||||
5: dec r25 ;Wait for a bit time
|
||||
brne 5b ;/
|
||||
lsr r24 ;Next bit
|
||||
SKIP_IN_0 ;Get a data bit into r24.7
|
||||
ori r24, 0x80
|
||||
brcc 4b ;All bits received? no, continue
|
||||
|
||||
ldi r25, BPS/2 ;Wait for half bit time
|
||||
6: dec r25
|
||||
brne 6b
|
||||
7: SKIP_IN_1 ;Wait for stop bit
|
||||
rjmp 7b
|
||||
|
||||
out _SFR_IO_ADDR(SREG), r0 ;End of critical section
|
||||
ret
|
||||
.endfunc
|
8
iwrap/suart.h
Normal file
8
iwrap/suart.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef SUART
|
||||
#define SUART
|
||||
|
||||
void xmit(uint8_t);
|
||||
uint8_t rcvr(void);
|
||||
uint8_t recv(void);
|
||||
|
||||
#endif /* SUART */
|
159
iwrap/wd.h
Normal file
159
iwrap/wd.h
Normal file
|
@ -0,0 +1,159 @@
|
|||
/* This is from http://www.mtcnet.net/~henryvm/wdt/ */
|
||||
#ifndef _AVR_WD_H_
|
||||
#define _AVR_WD_H_
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
/*
|
||||
Copyright (c) 2009, Curt Van Maanen
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
include usage-
|
||||
#include "wd.h" //if in same directory as project
|
||||
#include <avr/wd.h> //if wd.h is in avr directory
|
||||
|
||||
set watchdog modes and prescale
|
||||
|
||||
usage-
|
||||
WD_SET(mode,[timeout]); //prescale always set
|
||||
|
||||
modes-
|
||||
WD_OFF disabled
|
||||
WD_RST normal reset mode
|
||||
WD_IRQ interrupt only mode (if supported)
|
||||
WD_RST_IRQ interrupt+reset mode (if supported)
|
||||
|
||||
timeout-
|
||||
WDTO_15MS default if no timeout provided
|
||||
WDTO_30MS
|
||||
WDTO_60MS
|
||||
WDTO_120MS
|
||||
WDTO_250MS
|
||||
WDTO_500MS
|
||||
WDTO_1S
|
||||
WDTO_2S
|
||||
WDTO_4S (if supported)
|
||||
WDTO_8S (if supported)
|
||||
|
||||
examples-
|
||||
WD_SET(WD_RST,WDTO_1S); //reset mode, 1s timeout
|
||||
WD_SET(WD_OFF); //watchdog disabled (if not fused on)
|
||||
WD_SET(WD_RST); //reset mode, 15ms (default timeout)
|
||||
WD_SET(WD_IRQ,WDTO_120MS); //interrupt only mode, 120ms timeout
|
||||
WD_SET(WD_RST_IRQ,WDTO_2S); //interrupt+reset mode, 2S timeout
|
||||
|
||||
|
||||
for enhanced watchdogs, if the watchdog is not being used WDRF should be
|
||||
cleared on every power up or reset, along with disabling the watchdog-
|
||||
WD_DISABLE(); //clear WDRF, then turn off watchdog
|
||||
|
||||
*/
|
||||
|
||||
//reset registers to the same name (MCUCSR)
|
||||
#if !defined(MCUCSR)
|
||||
#define MCUCSR MCUSR
|
||||
#endif
|
||||
|
||||
//watchdog registers to the same name (WDTCSR)
|
||||
#if !defined(WDTCSR)
|
||||
#define WDTCSR WDTCR
|
||||
#endif
|
||||
|
||||
//if enhanced watchdog, define irq values, create disable macro
|
||||
#if defined(WDIF)
|
||||
#define WD_IRQ 0xC0
|
||||
#define WD_RST_IRQ 0xC8
|
||||
#define WD_DISABLE() do{ \
|
||||
MCUCSR &= ~(1<<WDRF); \
|
||||
WD_SET(WD_OFF); \
|
||||
}while(0)
|
||||
#endif
|
||||
|
||||
//all watchdogs
|
||||
#define WD_RST 8
|
||||
#define WD_OFF 0
|
||||
|
||||
//prescale values
|
||||
#define WDTO_15MS 0
|
||||
#define WDTO_30MS 1
|
||||
#define WDTO_60MS 2
|
||||
#define WDTO_120MS 3
|
||||
#define WDTO_250MS 4
|
||||
#define WDTO_500MS 5
|
||||
#define WDTO_1S 6
|
||||
#define WDTO_2S 7
|
||||
|
||||
//prescale values for avrs with WDP3
|
||||
#if defined(WDP3)
|
||||
#define WDTO_4S 0x20
|
||||
#define WDTO_8S 0x21
|
||||
#endif
|
||||
|
||||
//watchdog reset
|
||||
#define WDR() __asm__ __volatile__("wdr")
|
||||
|
||||
//avr reset using watchdog
|
||||
#define WD_AVR_RESET() do{ \
|
||||
__asm__ __volatile__("cli"); \
|
||||
WD_SET_UNSAFE(WD_RST); \
|
||||
while(1); \
|
||||
}while(0)
|
||||
|
||||
/*set the watchdog-
|
||||
1. save SREG
|
||||
2. turn off irq's
|
||||
3. reset watchdog timer
|
||||
4. enable watchdog change
|
||||
5. write watchdog value
|
||||
6. restore SREG (restoring irq status)
|
||||
*/
|
||||
#define WD_SET(val,...) \
|
||||
__asm__ __volatile__( \
|
||||
"in __tmp_reg__,__SREG__" "\n\t" \
|
||||
"cli" "\n\t" \
|
||||
"wdr" "\n\t" \
|
||||
"sts %[wdreg],%[wden]" "\n\t" \
|
||||
"sts %[wdreg],%[wdval]" "\n\t" \
|
||||
"out __SREG__,__tmp_reg__" "\n\t" \
|
||||
: \
|
||||
: [wdreg] "M" (&WDTCSR), \
|
||||
[wden] "r" ((uint8_t)(0x18)), \
|
||||
[wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0))) \
|
||||
: "r0" \
|
||||
)
|
||||
|
||||
/*set the watchdog when I bit in SREG known to be clear-
|
||||
1. reset watchdog timer
|
||||
2. enable watchdog change
|
||||
5. write watchdog value
|
||||
*/
|
||||
#define WD_SET_UNSAFE(val,...) \
|
||||
__asm__ __volatile__( \
|
||||
"wdr" "\n\t" \
|
||||
"sts %[wdreg],%[wden]" "\n\t" \
|
||||
"sts %[wdreg],%[wdval]" "\n\t" \
|
||||
: \
|
||||
: [wdreg] "M" (&WDTCSR), \
|
||||
[wden] "r" ((uint8_t)(0x18)), \
|
||||
[wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0))) \
|
||||
)
|
||||
|
||||
|
||||
//for compatibility with avr/wdt.h
|
||||
#define wdt_enable(val) WD_SET(WD_RST,val)
|
||||
#define wdt_disable() WD_SET(WD_OFF)
|
||||
|
||||
|
||||
#endif /* _AVR_WD_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue