aboutsummaryrefslogtreecommitdiff
path: root/protocol/iwrap
diff options
context:
space:
mode:
Diffstat (limited to 'protocol/iwrap')
-rw-r--r--protocol/iwrap/iWRAP.txt376
-rw-r--r--protocol/iwrap/iwrap.c467
-rw-r--r--protocol/iwrap/iwrap.h49
-rw-r--r--protocol/iwrap/main.c378
-rw-r--r--protocol/iwrap/suart.S156
-rw-r--r--protocol/iwrap/suart.h8
-rw-r--r--protocol/iwrap/wd.h159
7 files changed, 1593 insertions, 0 deletions
diff --git a/protocol/iwrap/iWRAP.txt b/protocol/iwrap/iWRAP.txt
new file mode 100644
index 000000000..2a062d9d9
--- /dev/null
+++ b/protocol/iwrap/iWRAP.txt
@@ -0,0 +1,376 @@
1Bulegiga WT12
2=============
3WT12 is a bluetooth module from Bluegiga. http://www.bluegiga.com/
4
5iWRAP
6 higher layer interface for bluetooth firmware
7 communicate with UART
8
9iWRAP HID
10default setting
11 115200 8bit/n/1/n
12
13
14TODO
15----
16KiCAD circuit/PCB design
17power saving
18 AVR sleep(15ms by watch dog timer)
19 WT12 sleep
20 measuring current consumption
21 measuring battery life of normal usage/idle/intensive usage
22software reset/bootloarder
23LED indicator(chaging/paring/connecting)
24license confirmation of suart.c
25consumer page is not working
26authenticate method/SSP
27SPP keyboard support
28SPP debug console support
29mouse wheel feature request to Bluegiga
30
31
32Problems
33--------
34power consumption
35no consumer page support(bug?)
36no mouse wheel support
37no paring management
38no interactive auth method
39
40
41UART hardware flow control
42--------------------------
43(iWRAP4 User Guide 9.5)
44Hardware 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.
45If 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:
46- CTS pin must be grounded
47- RTS pin must be left floating
48
49
50Power Saving
51------------
52power consume
53 without opimization: 4hr to shutdown(310mAh)
54 2011/08/25: 9hr(310mAh) SNIFF MASTER sleep/WDTO_120MS
55
56measure current consumption
57 HHKB keyswitch matrix board
58 idle
59 scanning
60 Bluegiga WT12 module
61 SLEEP command
62 deep sleep on/off in config bits
63
64HHKB keyswich
65 how to power off
66 I/O pin configuration when sleeping
67 FET switch for 5V regulator
68
69Bluetooth module
70 power off when in USB mode
71 power off by FET switch
72
73AVR configuration
74 unused pins
75 ADC
76
77
78
79SET CONTROL CONFIG
80------------------
81 SET CONTROL CONFIG 4810
82 SET CONTROL CONFIG LIST
83 SET CONTROL CONFIG 0000 0000 4910 DEEP_SLEEP KLUDGE INTERACTIVE_PIN UART_LATENCY
84
85 Bit14 UART low latency
86 Bit11 Interactive pairing mode
87 Bit04 Deep sleep
88
89
90Reconnection
91------------
92SET CONTROL AUTOCALL 1124 5000 HID
93 1124 HID service class
94 5000 interval ms
95
96HID profile
97-----------
98This is needed to configure only once.
99 SET PROFILE HID ON
100 RESET
101
102HID class
103---------
104 SET BT CLASS 005C0 // keyboard/mouse combined devie
105
106Pairing Security
107----------------
108Secure Simple Pairing(SSP)
109 SET BT SSP 2 0 // Enables SSP for keyboard and Man-in-the-middle protection
110 SET BT SSP 3 0 // Enables SSP just works mode
111
112for keyboard with SSP
113 SET BT AUTH * 0000
114 SET BT SSP 2 0
115 SET CONTROL CONFIG 800
116 RESET
117
118for keyboard without SSP
119 SET BT AUTH * 0000
120 SET CONTROL CONFIG 800
121 RESET
122
123AUTH
124 AUTH xx:xx:xx:xx:xx:xx? // Pairing request event
125 AUTH xx:xx:xx:xx:xx:xx 0000
126
127 SSP PASSKEY 78:dd:08:b7:e4:a2 ?
128 SSP PASSKEY 78:dd:08:b7:e4:a2 xxxxx
129 (SSP COMPLETE 78:dd:08:b7:e4:a2 HCI_ERROR_AUTH_FAIL // failed)
130 RING 0 78:dd:08:b7:e4:a2 11 HID
131
132Connecton
133 RING xx:xx:xx:xx:xx:xx xx HID // connection event
134
135 KILL xx:xx:xx:xx:xx:xx
136
137Mode
138----
139Command mode
140Data mode
141 Raw mode
142 (Simple mode not for a real keyboard)
143
144Raw mode
145 Keyboard:
146 0x9f, length(10), 0xa1, 0x01, mods, 0x00, key1, key2, key3, key4, key5, key6
147
148 Mouse:
149 0x9f, length(5), 0xa1, 0x02, buttons, X, Y
150
151 Consumer page:
152 0x9f, length(5), 0xa1, 0x03, bitfield1, bitfield2, bitfield3
153
154 consumer page suage
155 Bitfield 1:
156 0x01 Volume Increment
157 0x02 Volume Decrement
158 0x04 Mute
159 0x08 Play/Pause
160 0x10 Scan Next Track
161 0x20 Scan Previous Track
162 0x40 Stop
163 0x80 Eject
164 Bitfield 2:
165 0x01 Email Reader
166 0x02 Application Control Search
167 0x04 AC Bookmarks
168 0x08 AC Home
169 0x10 AC Back
170 0x20 AC Forward
171 0x40 AC Stop
172 0x80 AC Refresh
173 Bitfield 3:
174 0x01 Application Launch Generic Consumer Control
175 0x02 AL Internet Browser
176 0x04 AL Calculator
177 0x08 AL Terminal Lock / Screensaver
178 0x10 AL Local Machine Browser
179 0x20 AC Minimize
180 0x40 Record
181 0x80 Rewind
182
183
184
185
186
1872011/07/13
188set
189SET BT BDADDR 00:07:80:47:22:14
190SET BT NAME HHKB pro BT
191SET BT CLASS 0005c0
192SET BT AUTH * 0000
193SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP
194SET BT LAP 9e8b33
195SET BT PAGEMODE 4 2000 1
196SET BT PAIR 78:dd:08:b7:e4:a2 a191189cd7e51030ad6a07848ce879bb
197SET BT POWER 3 3 3
198SET BT ROLE 0 f 7d00
199SET BT SNIFF 0 20 1 8
200SET BT SSP 2 1
201SET BT MTU 667
202SET CONTROL AUTOCALL 1124 3000 HID
203SET CONTROL BAUD 38400,8n1
204SET CONTROL CD 00 0
205SET CONTROL ECHO 7
206SET CONTROL ESCAPE 43 00 1
207SET CONTROL GAIN 0 5
208SET CONTROL INIT SET CONTROL MUX 0
209SET CONTROL MSC DTE 00 00 00 00 00 00
210SET CONTROL MUX 1
211SET CONTROL PIO 00 00
212SET CONTROL READY 00
213SET PROFILE HID f HID
214SET
215
216info config
217
218!!! THIS IS BETA RELEASE AND MAY BE USED FOR EVALUATION PURPOSES ONLY !!!
219
220WRAP THOR AI (4.1.0 build 435)
221Copyright (c) 2003-2011 Bluegiga Technologies Inc.
222Compiled on Jun 28 2011 17:19:51, running on WT12-A module, psr v31
223 AVRCP BGIO FTP HFP HFP_AG HID HID_CONSUMER_PAGE HSP LEDS MAP OTA PBAP PIO=0x00fc SSP SUBRATE TEST VOLUME
224 - BOCK3 version 435 (Jun 28 2011 17:19:37) (max acl/sco 7/1)
225 - Bluetooth version 2.1, Power class 2
226 - Loader 4279, firmware 6297 (56-bit encryption), native execution mode
227 - up 0 days, 06:23, 2 connections (pool 2)
228 - User configuration:
229&028a = 0001 0000 0000 0011 0024 0000 0000 0010 0000 0080 0000 0000 0080 005f 009b 0034 00fb 0006
230&028b = 0000 0bb8
231&028d = 0001
232&0295 = 0000 0005 000b 0000 0003 0000 0000 0000 0000 0000 0000
233&0298 = a006
234&0299 = 0000 0000
235&02a3 = 0030 0030 0030 0030
236&02a4 = 009d 0000
237&02a5 = 0053 0045 0054 0020 0043 004f 004e 0054 0052 004f 004c 0020 004d 0055 0058 0020 0030
238&02a7 = 0000 05c0
239&02a8 = 4910 0000 0000
240&02aa = 0004 2000 0001 0033 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
241&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
242&02ad = 4848 424b 7020 6f72 4220 0054
243&02b3 = 0005 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003
244&02b7 = 000f 4948 0044
245&02bb = 8000
246READY.
247
248
249
250
2512011/07/07 settings:
252set
253SET BT BDADDR 00:07:80:47:22:14
254SET BT NAME HHKB Pro BT
255SET BT CLASS 0005c0
256SET BT AUTH * 000
257SET BT IDENT BT:47 f000 4.0.0 Bluegiga iWRAP
258SET BT LAP 9e8b33
259SET BT PAGEMODE 4 2000 1
260SET BT PAIR 78:dd:08:b7:e4:a2 9e54d0aabb1b4d73cfccddb1ea4ef2d6
261SET BT POWER 3 3 3
262SET BT ROLE 0 f 7d00
263SET BT SNIFF 0 20 1 8
264SET BT SSP 3 0
265SET BT MTU 667
266SET CONTROL BAUD 38400,8n1
267SET CONTROL CD 00 0
268SET CONTROL ECHO 7
269SET CONTROL ESCAPE 255 00 1
270SET CONTROL GAIN 0 5
271SET CONTROL INIT set control mux 0
272SET CONTROL MSC DTE 00 00 00 00 00 00
273SET CONTROL PREAMP 1 1
274SET CONTROL READY 00
275SET PROFILE HID HID
276SET PROFILE SPP Bluetooth Serial Port
277SET
278
279info config
280WRAP THOR AI (4.0.0 build 317)
281Copyright (c) 2003-2010 Bluegiga Technologies Inc.
282Compiled on Apr 20 2010 16:44:28, running on WT12-A module, psr v31
283 AVRCP FTP PBAP PIO=0x00fc SSP SUBRATE VOLUME
284 - BOCK3 version 317 (Apr 20 2010 16:44:21) (max acl/sco 7/1)
285 - Bluetooth version 2.1, Power class 2
286 - Loader 4279, firmware 6297 (56-bit encryption), native execution mode
287 - up 0 days, 00:00, 0 connections (pool 1)
288 - User configuration:
289&028c = 0001 0020 0000 0001 0008 0000
290&028d = 0000
291&0296 = 0047 0001 f000 0400 6c42 6575 6967 6167 6920 5257 5041
292&0298 = c006
293&02a3 = 0030 0030 0030
294&02a4 = 009d 0000
295&02a5 = 0073 0065 0074 0020 0063 006f 006e 0074 0072 006f 006c 0020 006d 0075 0078 0020 0030
296&02a7 = 0000 05c0
297&02a8 = 0800 0000 0000
298&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
299&02ad = 4848 424b 5020 6f72 4220 0054
300&02b3 = 0004 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003
301&02b7 = 0000
302&02bb = 6c42 6575 6f74 746f 2068 6553 6972 6c61 5020 726f 0074
303READY.
304
305
306
3072011/08/23:
308SET BT BDADDR 00:07:80:47:22:14
309SET BT NAME HHKB pro BT
310SET BT CLASS 0005c0
311SET BT AUTH * 0000
312SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP
313SET BT LAP 9e8b33
314SET BT PAGEMODE 4 2000 1
315SET BT PAIRCOUNT 4
316SET BT POWER 3 3 3
317SET BT ROLE 1 f 12c0
318SET BT SNIFF 10 2 1 8
319SET BT SSP 3 0
320SET BT MTU 667
321SET CONTROL BAUD 38400,8n1
322SET CONTROL CD 00 0
323SET CONTROL ECHO 7
324SET CONTROL ESCAPE 43 00 1
325SET CONTROL GAIN 0 5
326SET CONTROL INIT SET CONTROL MUX 0
327SET CONTROL MSC DTE 00 00 00 00 00 00
328SET CONTROL MUX 1
329SET CONTROL PIO 00 00
330SET CONTROL READY 00
331SET PROFILE HID 7 HIDKeyboardMouse
332SET
333
334SET CONTROL CONFIG 0000 0004 481e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE DEEP_SLEEP INTERACTIVE_PIN UART_LATENCY 23D_NOKLUDGE
335
336
337
3382011/08/25:
339SET BT BDADDR 00:07:80:47:22:14
340SET BT NAME HHKB pro BT
341SET BT CLASS 0005c0
342
343SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP
344SET BT LAP 9e8b33
345SET BT PAGEMODE 4 2000 1
346SET BT PAIRCOUNT 4
347SET BT PAIR 78:dd:08:b7:e4:a2 0be83335a03fed8ededae42e99554e28
348SET BT POWER 3 3 3
349SET BT ROLE 1 f 12c0
350SET BT SNIFF 100 20 1 8
351SET BT SSP 3 0
352SET BT MTU 667
353SET CONTROL BAUD 38400,8n1
354SET CONTROL CD 00 0
355SET CONTROL ECHO 7
356SET CONTROL ESCAPE - 20 1
357SET CONTROL GAIN 0 5
358SET CONTROL INIT SET CONTROL MUX 0
359SET CONTROL MSC DTE 00 00 00 00 00 00
360SET CONTROL MUX 1
361SET CONTROL PIO 00 00
362SET CONTROL READY 00
363SET PROFILE HID f HIDKeyboardMouse
364SET
365
366
367SET CONTROL CONFIG 0000 0000 490e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE INTERACTIVE_PIN UART_LATENCY
368
369
3702011/09/08:
371SET CONTROL CONFIG 0000 0000 410e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE UART_LATENCY
372
373 Removed INTERACTIVE_PIN to avoid interactive auth and use SET BT AUTH pin(0000).
374
375
376EOF
diff --git a/protocol/iwrap/iwrap.c b/protocol/iwrap/iwrap.c
new file mode 100644
index 000000000..9c68761bf
--- /dev/null
+++ b/protocol/iwrap/iwrap.c
@@ -0,0 +1,467 @@
1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18/* host driver for Bulegiga iWRAP */
19/* Bluegiga BT12
20 * Connections
21 * Hardware UART Software UART BlueTooth
22 * PC=====UART=======AVR=====SUART====iWRAP(BT12)-----------PC
23 *
24 * - Hardware UART for Debug Console to communicate iWRAP
25 * - Software UART for iWRAP control to send keyboard/mouse data
26 */
27
28#include <stdint.h>
29#include <string.h>
30#include <avr/interrupt.h>
31#include <util/delay.h>
32#include "usb_keycodes.h"
33#include "suart.h"
34#include "uart.h"
35#include "report.h"
36#include "host_driver.h"
37#include "iwrap.h"
38#include "print.h"
39
40
41/* iWRAP MUX mode utils. 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf) */
42#define MUX_HEADER(LINK, LENGTH) do { \
43 xmit(0xbf); /* SOF */ \
44 xmit(LINK); /* Link */ \
45 xmit(0x00); /* Flags */ \
46 xmit(LENGTH); /* Length */ \
47} while (0)
48#define MUX_FOOTER(LINK) xmit(LINK^0xff)
49
50
51static uint8_t connected = 0;
52//static uint8_t channel = 1;
53
54/* iWRAP buffer */
55#define MUX_BUF_SIZE 64
56static char buf[MUX_BUF_SIZE];
57static uint8_t snd_pos = 0;
58
59#define MUX_RCV_BUF_SIZE 256
60static char rcv_buf[MUX_RCV_BUF_SIZE];
61static uint8_t rcv_head = 0;
62static uint8_t rcv_tail = 0;
63
64
65/* receive buffer */
66static void rcv_enq(char c)
67{
68 uint8_t next = (rcv_head + 1) % MUX_RCV_BUF_SIZE;
69 if (next != rcv_tail) {
70 rcv_buf[rcv_head] = c;
71 rcv_head = next;
72 }
73}
74
75static char rcv_deq(void)
76{
77 char c = 0;
78 if (rcv_head != rcv_tail) {
79 c = rcv_buf[rcv_tail++];
80 rcv_tail %= MUX_RCV_BUF_SIZE;
81 }
82 return c;
83}
84
85/*
86static char rcv_peek(void)
87{
88 if (rcv_head == rcv_tail)
89 return 0;
90 return rcv_buf[rcv_tail];
91}
92*/
93
94static void rcv_clear(void)
95{
96 rcv_tail = rcv_head = 0;
97}
98
99/* iWRAP response */
100ISR(PCINT1_vect, ISR_BLOCK) // recv() runs away in case of ISR_NOBLOCK
101{
102 if ((SUART_IN_PIN & (1<<SUART_IN_BIT)))
103 return;
104
105 static volatile uint8_t mux_state = 0xff;
106 static volatile uint8_t mux_link = 0xff;
107 uint8_t c = recv();
108 switch (mux_state) {
109 case 0xff: // SOF
110 if (c == 0xbf)
111 mux_state--;
112 break;
113 case 0xfe: // Link
114 mux_state--;
115 mux_link = c;
116 break;
117 case 0xfd: // Flags
118 mux_state--;
119 break;
120 case 0xfc: // Length
121 mux_state = c;
122 break;
123 case 0x00:
124 mux_state = 0xff;
125 mux_link = 0xff;
126 break;
127 default:
128 if (mux_state--) {
129 uart_putchar(c);
130 rcv_enq(c);
131 }
132 }
133}
134
135
136/*------------------------------------------------------------------*
137 * iWRAP communication
138 *------------------------------------------------------------------*/
139void iwrap_init(void)
140{
141 // reset iWRAP if in already MUX mode after AVR software-reset
142 iwrap_send("RESET");
143 iwrap_mux_send("RESET");
144 _delay_ms(3000);
145 iwrap_send("\r\nSET CONTROL MUX 1\r\n");
146 _delay_ms(500);
147 iwrap_check_connection();
148}
149
150void iwrap_mux_send(const char *s)
151{
152 rcv_clear();
153 MUX_HEADER(0xff, strlen((char *)s));
154 iwrap_send(s);
155 MUX_FOOTER(0xff);
156}
157
158void iwrap_send(const char *s)
159{
160 while (*s)
161 xmit(*s++);
162}
163
164/* send buffer */
165void iwrap_buf_add(uint8_t c)
166{
167 // need space for '\0'
168 if (snd_pos < MUX_BUF_SIZE-1)
169 buf[snd_pos++] = c;
170}
171
172void iwrap_buf_del(void)
173{
174 if (snd_pos)
175 snd_pos--;
176}
177
178void iwrap_buf_send(void)
179{
180 buf[snd_pos] = '\0';
181 snd_pos = 0;
182 iwrap_mux_send(buf);
183}
184
185void iwrap_call(void)
186{
187 char *p;
188
189 iwrap_mux_send("SET BT PAIR");
190 _delay_ms(500);
191
192 p = rcv_buf + rcv_tail;
193 while (!strncmp(p, "SET BT PAIR", 11)) {
194 p += 7;
195 strncpy(p, "CALL", 4);
196 strncpy(p+22, " 11 HID\n\0", 9);
197 print_S(p);
198 iwrap_mux_send(p);
199 // TODO: skip to next line
200 p += 57;
201
202 DEBUG_LED_CONFIG;
203 DEBUG_LED_ON;
204 _delay_ms(500);
205 DEBUG_LED_OFF;
206 _delay_ms(500);
207 DEBUG_LED_ON;
208 _delay_ms(500);
209 DEBUG_LED_OFF;
210 _delay_ms(500);
211 DEBUG_LED_ON;
212 _delay_ms(500);
213 DEBUG_LED_OFF;
214 _delay_ms(500);
215 DEBUG_LED_ON;
216 _delay_ms(500);
217 DEBUG_LED_OFF;
218 _delay_ms(500);
219 DEBUG_LED_ON;
220 _delay_ms(500);
221 DEBUG_LED_OFF;
222 _delay_ms(500);
223 }
224 iwrap_check_connection();
225}
226
227void iwrap_kill(void)
228{
229 char c;
230 iwrap_mux_send("LIST");
231 _delay_ms(500);
232
233 while ((c = rcv_deq()) && c != '\n') ;
234 if (strncmp(rcv_buf + rcv_tail, "LIST ", 5)) {
235 print("no connection to kill.\n");
236 return;
237 }
238 // skip 10 'space' chars
239 for (uint8_t i = 10; i; i--)
240 while ((c = rcv_deq()) && c != ' ') ;
241
242 char *p = rcv_buf + rcv_tail - 5;
243 strncpy(p, "KILL ", 5);
244 strncpy(p + 22, "\n\0", 2);
245 print_S(p);
246 iwrap_mux_send(p);
247 _delay_ms(500);
248
249 iwrap_check_connection();
250}
251
252void iwrap_unpair(void)
253{
254 iwrap_mux_send("SET BT PAIR");
255 _delay_ms(500);
256
257 char *p = rcv_buf + rcv_tail;
258 if (!strncmp(p, "SET BT PAIR", 11)) {
259 strncpy(p+29, "\n\0", 2);
260 print_S(p);
261 iwrap_mux_send(p);
262 }
263}
264
265void iwrap_sleep(void)
266{
267 iwrap_mux_send("SLEEP");
268}
269
270void iwrap_sniff(void)
271{
272}
273
274void iwrap_subrate(void)
275{
276}
277
278bool iwrap_failed(void)
279{
280 if (strncmp(rcv_buf, "SYNTAX ERROR", 12))
281 return true;
282 else
283 return false;
284}
285
286uint8_t iwrap_connected(void)
287{
288 return connected;
289}
290
291uint8_t iwrap_check_connection(void)
292{
293 iwrap_mux_send("LIST");
294 _delay_ms(100);
295
296 if (strncmp(rcv_buf, "LIST ", 5) || !strncmp(rcv_buf, "LIST 0", 6))
297 connected = 0;
298 else
299 connected = 1;
300 return connected;
301}
302
303
304/*------------------------------------------------------------------*
305 * Host driver
306 *------------------------------------------------------------------*/
307static uint8_t keyboard_leds(void);
308static void send_keyboard(report_keyboard_t *report);
309static void send_mouse(report_mouse_t *report);
310static void send_system(uint16_t data);
311static void send_consumer(uint16_t data);
312
313static host_driver_t driver = {
314 keyboard_leds,
315 send_keyboard,
316 send_mouse,
317 send_system,
318 send_consumer
319};
320
321host_driver_t *iwrap_driver(void)
322{
323 return &driver;
324}
325
326static uint8_t keyboard_leds(void) {
327 return 0;
328}
329
330static void send_keyboard(report_keyboard_t *report)
331{
332 if (!iwrap_connected() && !iwrap_check_connection()) return;
333 MUX_HEADER(0x01, 0x0c);
334 // HID raw mode header
335 xmit(0x9f);
336 xmit(0x0a); // Length
337 xmit(0xa1); // keyboard report
338 xmit(0x01);
339 xmit(report->mods);
340 xmit(0x00); // reserved byte(always 0)
341 xmit(report->keys[0]);
342 xmit(report->keys[1]);
343 xmit(report->keys[2]);
344 xmit(report->keys[3]);
345 xmit(report->keys[4]);
346 xmit(report->keys[5]);
347 MUX_FOOTER(0x01);
348}
349
350static void send_mouse(report_mouse_t *report)
351{
352#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE)
353 if (!iwrap_connected() && !iwrap_check_connection()) return;
354 MUX_HEADER(0x01, 0x07);
355 // HID raw mode header
356 xmit(0x9f);
357 xmit(0x05); // Length
358 xmit(0xa1); // mouse report
359 xmit(0x02);
360 xmit(report->buttons);
361 xmit(report->x);
362 xmit(report->y);
363 MUX_FOOTER(0x01);
364#endif
365}
366
367static void send_system(uint16_t data)
368{
369 /* not supported */
370}
371
372static void send_consumer(uint16_t data)
373{
374#ifdef EXTRAKEY_ENABLE
375 static uint16_t last_data = 0;
376 uint8_t bits1 = 0;
377 uint8_t bits2 = 0;
378 uint8_t bits3 = 0;
379
380 if (!iwrap_connected() && !iwrap_check_connection()) return;
381 if (data == last_data) return;
382 last_data = data;
383
384 // 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf)
385 switch (data) {
386 case AUDIO_VOL_UP:
387 bits1 = 0x01;
388 break;
389 case AUDIO_VOL_DOWN:
390 bits1 = 0x02;
391 break;
392 case AUDIO_MUTE:
393 bits1 = 0x04;
394 break;
395 case TRANSPORT_PLAY_PAUSE:
396 bits1 = 0x08;
397 break;
398 case TRANSPORT_NEXT_TRACK:
399 bits1 = 0x10;
400 break;
401 case TRANSPORT_PREV_TRACK:
402 bits1 = 0x20;
403 break;
404 case TRANSPORT_STOP:
405 bits1 = 0x40;
406 break;
407 case TRANSPORT_EJECT:
408 bits1 = 0x80;
409 break;
410 case AL_EMAIL:
411 bits2 = 0x01;
412 break;
413 case AC_SEARCH:
414 bits2 = 0x02;
415 break;
416 case AC_BOOKMARKS:
417 bits2 = 0x04;
418 break;
419 case AC_HOME:
420 bits2 = 0x08;
421 break;
422 case AC_BACK:
423 bits2 = 0x10;
424 break;
425 case AC_FORWARD:
426 bits2 = 0x20;
427 break;
428 case AC_STOP:
429 bits2 = 0x40;
430 break;
431 case AC_REFRESH:
432 bits2 = 0x80;
433 break;
434 case AL_CC_CONFIG:
435 bits3 = 0x01;
436 break;
437 case AL_CALCULATOR:
438 bits3 = 0x04;
439 break;
440 case AL_LOCK:
441 bits3 = 0x08;
442 break;
443 case AL_LOCAL_BROWSER:
444 bits3 = 0x10;
445 break;
446 case AC_MINIMIZE:
447 bits3 = 0x20;
448 break;
449 case TRANSPORT_RECORD:
450 bits3 = 0x40;
451 break;
452 case TRANSPORT_REWIND:
453 bits3 = 0x80;
454 break;
455 }
456
457 MUX_HEADER(0x01, 0x07);
458 xmit(0x9f);
459 xmit(0x05); // Length
460 xmit(0xa1); // consumer report
461 xmit(0x03);
462 xmit(bits1);
463 xmit(bits2);
464 xmit(bits3);
465 MUX_FOOTER(0x01);
466#endif
467}
diff --git a/protocol/iwrap/iwrap.h b/protocol/iwrap/iwrap.h
new file mode 100644
index 000000000..ffaad9395
--- /dev/null
+++ b/protocol/iwrap/iwrap.h
@@ -0,0 +1,49 @@
1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef IWRAP_H
19#define IWRAP_H
20
21#include <stdint.h>
22#include <stdbool.h>
23#include "host_driver.h"
24
25
26/* enable iWRAP MUX mode */
27#define MUX_MODE
28
29
30host_driver_t *iwrap_driver(void);
31
32void iwrap_init(void);
33void iwrap_send(const char *s);
34void iwrap_mux_send(const char *s);
35void iwrap_buf_send(void);
36void iwrap_buf_add(uint8_t c);
37void iwrap_buf_del(void);
38
39void iwrap_call(void);
40void iwrap_kill(void);
41void iwrap_unpair(void);
42void iwrap_sleep(void);
43void iwrap_sniff(void);
44void iwrap_subrate(void);
45bool iwrap_failed(void);
46uint8_t iwrap_connected(void);
47uint8_t iwrap_check_connection(void);
48
49#endif
diff --git a/protocol/iwrap/main.c b/protocol/iwrap/main.c
new file mode 100644
index 000000000..a552afb67
--- /dev/null
+++ b/protocol/iwrap/main.c
@@ -0,0 +1,378 @@
1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17#include <stdint.h>
18#include <avr/interrupt.h>
19#include <avr/io.h>
20//#include <avr/wdt.h>
21#include "wd.h" // in order to use watchdog in interrupt mode
22#include <avr/sleep.h>
23#include <util/delay.h>
24#include <avr/power.h>
25#include "keyboard.h"
26#include "matrix.h"
27#include "host.h"
28#include "iwrap.h"
29#ifdef HOST_VUSB
30# include "vusb.h"
31# include "usbdrv.h"
32#endif
33#include "uart.h"
34#include "suart.h"
35#include "timer.h"
36#include "debug.h"
37#include "usb_keycodes.h"
38#include "command.h"
39
40
41static void sleep(uint8_t term);
42static bool console(void);
43static uint8_t console_command(uint8_t c);
44static uint8_t key2asc(uint8_t key);
45
46
47/*
48static void set_prr(void)
49{
50 power_adc_disable();
51 power_spi_disable();
52 power_twi_disable();
53#ifndef TIMER_H
54 //power_timer0_disable(); // used in timer.c
55#endif
56 power_timer1_disable();
57 power_timer2_disable();
58}
59*/
60
61/*
62static void pullup_pins(void)
63{
64 // DDRs are set to 0(input) by default.
65#ifdef PORTA
66 PORTA = 0xFF;
67#endif
68 PORTB = 0xFF;
69 PORTC = 0xFF;
70 PORTD = 0xFF;
71#ifdef PORTE
72 PORTE = 0xFF;
73#endif
74#ifdef PORTE
75 PORTF = 0xFF;
76#endif
77}
78*/
79
80
81#ifdef HOST_VUSB
82static void disable_vusb(void)
83{
84 // disable interrupt & disconnect to prevent host from enumerating
85 USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT);
86 usbDeviceDisconnect();
87}
88
89static void enable_vusb(void)
90{
91 USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
92 usbDeviceConnect();
93}
94
95static void init_vusb(void)
96{
97 uint8_t i = 0;
98
99 usbInit();
100 disable_vusb();
101 /* fake USB disconnect for > 250 ms */
102 while(--i){
103 _delay_ms(1);
104 }
105 enable_vusb();
106}
107#endif
108
109void change_driver(host_driver_t *driver)
110{
111 host_clear_keyboard_report();
112 host_swap_keyboard_report();
113 host_clear_keyboard_report();
114 host_send_keyboard_report();
115 _delay_ms(1000);
116 host_set_driver(driver);
117}
118
119
120static bool sleeping = false;
121static bool insomniac = false; // TODO: should be false for power saving
122static uint16_t last_timer = 0;
123
124int main(void)
125{
126 MCUSR = 0;
127 clock_prescale_set(clock_div_1);
128 WD_SET(WD_OFF);
129
130 // power saving: the result is worse than nothing... why?
131 //pullup_pins();
132 //set_prr();
133
134 print_enable = true;
135 debug_enable = false;
136
137#ifdef HOST_VUSB
138 disable_vusb();
139#endif
140 uart_init(115200);
141 keyboard_init();
142 print("\nSend BREAK for UART Console Commands.\n");
143
144 // TODO: move to iWRAP/suart file
145 print("suart init\n");
146 // suart init
147 // PC4: Tx Output IDLE(Hi)
148 PORTC |= (1<<4);
149 DDRC |= (1<<4);
150 // PC5: Rx Input(pull-up)
151 PORTC |= (1<<5);
152 DDRC &= ~(1<<5);
153 // suart receive interrut(PC5/PCINT13)
154 PCMSK1 = 0b00100000;
155 PCICR = 0b00000010;
156
157 host_set_driver(iwrap_driver());
158
159 print("iwrap_init()\n");
160 iwrap_init();
161 iwrap_call();
162
163 last_timer = timer_read();
164 while (true) {
165#ifdef HOST_VUSB
166 if (host_get_driver() == vusb_driver())
167 usbPoll();
168#endif
169 keyboard_proc();
170#ifdef HOST_VUSB
171 if (host_get_driver() == vusb_driver())
172 vusb_transfer_keyboard();
173#endif
174 if (matrix_is_modified() || console()) {
175 last_timer = timer_read();
176 sleeping = false;
177 } else if (!sleeping && timer_elapsed(last_timer) > 4000) {
178 sleeping = true;
179 iwrap_check_connection();
180 }
181
182 if (host_get_driver() == iwrap_driver()) {
183 if (sleeping && !insomniac) {
184 _delay_ms(1); // wait for UART to send
185 iwrap_sleep();
186 sleep(WDTO_60MS);
187 }
188 }
189 }
190}
191
192static void sleep(uint8_t term)
193{
194 WD_SET(WD_IRQ, term);
195
196 cli();
197 set_sleep_mode(SLEEP_MODE_PWR_DOWN);
198 sleep_enable();
199 sleep_bod_disable();
200 sei();
201 sleep_cpu();
202 sleep_disable();
203
204 WD_SET(WD_OFF);
205}
206
207ISR(WDT_vect)
208{
209 // wake up
210}
211
212static bool console(void)
213{
214 // Send to Bluetoot module WT12
215 static bool breaked = false;
216 if (!uart_available())
217 return false;
218 else {
219 uint8_t c;
220 c = uart_getchar();
221 uart_putchar(c);
222 switch (c) {
223 case 0x00: // BREAK signal
224 if (!breaked) {
225 print("break(? for help): ");
226 breaked = true;
227 }
228 break;
229 case '\r':
230 uart_putchar('\n');
231 iwrap_buf_send();
232 break;
233 case '\b':
234 iwrap_buf_del();
235 break;
236 default:
237 if (breaked) {
238 print("\n");
239 console_command(c);
240 breaked = false;
241 } else {
242 iwrap_buf_add(c);
243 }
244 break;
245 }
246 return true;
247 }
248}
249
250uint8_t command_extra()
251{
252 return console_command(key2asc(host_get_first_key()));
253}
254
255static uint8_t console_command(uint8_t c)
256{
257 switch (c) {
258 case 'h':
259 case '?':
260 print("\nCommands for Bluetooth(WT12/iWRAP):\n");
261 print("r: reset. software reset by watchdog\n");
262 print("i: insomniac. prevent KB from sleeping\n");
263 print("c: iwrap_call. CALL for BT connection.\n");
264#ifdef HOST_VUSB
265 print("u: USB mode. switch to USB.\n");
266 print("w: BT mode. switch to Bluetooth.\n");
267#endif
268 print("k: kill first connection.\n");
269 print("Del: unpair first pairing.\n");
270 print("\n");
271 return 0;
272 case 'r':
273 print("reset\n");
274 WD_AVR_RESET();
275 return 1;
276 case 'i':
277 insomniac = !insomniac;
278 if (insomniac)
279 print("insomniac\n");
280 else
281 print("not insomniac\n");
282 return 1;
283 case 'c':
284 print("iwrap_call()\n");
285 iwrap_call();
286 return 1;
287#ifdef HOST_VUSB
288 case 'u':
289 print("USB mode\n");
290 init_vusb();
291 change_driver(vusb_driver());
292 //iwrap_kill();
293 //iwrap_sleep();
294 // disable suart receive interrut(PC5/PCINT13)
295 PCMSK1 &= ~(0b00100000);
296 PCICR &= ~(0b00000010);
297 return 1;
298 case 'w':
299 print("iWRAP mode\n");
300 change_driver(iwrap_driver());
301 disable_vusb();
302 // enable suart receive interrut(PC5/PCINT13)
303 PCMSK1 |= 0b00100000;
304 PCICR |= 0b00000010;
305 return 1;
306#endif
307 case 'k':
308 print("kill\n");
309 iwrap_kill();
310 return 1;
311 case 0x7F: // DELETE
312 print("unpair\n");
313 iwrap_unpair();
314 return 1;
315 }
316 return 0;
317}
318
319// convert keycode into ascii charactor
320static uint8_t key2asc(uint8_t key)
321{
322 switch (key) {
323 case KB_A: return 'a';
324 case KB_B: return 'b';
325 case KB_C: return 'c';
326 case KB_D: return 'd';
327 case KB_E: return 'e';
328 case KB_F: return 'f';
329 case KB_G: return 'g';
330 case KB_H: return 'h';
331 case KB_I: return 'i';
332 case KB_J: return 'j';
333 case KB_K: return 'k';
334 case KB_L: return 'l';
335 case KB_M: return 'm';
336 case KB_N: return 'n';
337 case KB_O: return 'o';
338 case KB_P: return 'p';
339 case KB_Q: return 'q';
340 case KB_R: return 'r';
341 case KB_S: return 's';
342 case KB_T: return 't';
343 case KB_U: return 'u';
344 case KB_V: return 'v';
345 case KB_W: return 'w';
346 case KB_X: return 'x';
347 case KB_Y: return 'y';
348 case KB_Z: return 'z';
349 case KB_1: return '1';
350 case KB_2: return '2';
351 case KB_3: return '3';
352 case KB_4: return '4';
353 case KB_5: return '5';
354 case KB_6: return '6';
355 case KB_7: return '7';
356 case KB_8: return '8';
357 case KB_9: return '9';
358 case KB_0: return '0';
359 case KB_ENTER: return '\n';
360 case KB_ESCAPE: return 0x1B;
361 case KB_BSPACE: return '\b';
362 case KB_TAB: return '\t';
363 case KB_SPACE: return ' ';
364 case KB_MINUS: return '-';
365 case KB_EQUAL: return '=';
366 case KB_LBRACKET: return '[';
367 case KB_RBRACKET: return ']';
368 case KB_BSLASH: return '\\';
369 case KB_NONUS_HASH: return '\\';
370 case KB_SCOLON: return ';';
371 case KB_QUOTE: return '\'';
372 case KB_GRAVE: return '`';
373 case KB_COMMA: return ',';
374 case KB_DOT: return '.';
375 case KB_SLASH: return '/';
376 default: return 0x00;
377 }
378}
diff --git a/protocol/iwrap/suart.S b/protocol/iwrap/suart.S
new file mode 100644
index 000000000..1b0290963
--- /dev/null
+++ b/protocol/iwrap/suart.S
@@ -0,0 +1,156 @@
1;---------------------------------------------------------------------------;
2; Software implemented UART module ;
3; (C)ChaN, 2005 (http://elm-chan.org/) ;
4;---------------------------------------------------------------------------;
5; Bit rate settings:
6;
7; 1MHz 2MHz 4MHz 6MHz 8MHz 10MHz 12MHz 16MHz 20MHz
8; 2.4kbps 138 - - - - - - - -
9; 4.8kbps 68 138 - - - - - - -
10; 9.6kbps 33 68 138 208 - - - - -
11; 19.2kbps - 33 68 102 138 173 208 - -
12; 38.4kbps - - 33 50 68 85 102 138 172
13; 57.6kbps - - 21 33 44 56 68 91 114
14; 115.2kbps - - - - 21 27 33 44 56
15
16.nolist
17#include <avr/io.h>
18.list
19
20#define BPS 102 /* Bit delay. (see above table) */
21#define BIDIR 0 /* 0:Separated Tx/Rx, 1:Shared Tx/Rx */
22
23#define OUT_1 sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 1 */
24#define OUT_0 cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 0 */
25#define SKIP_IN_1 sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 1 */
26#define SKIP_IN_0 sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 0 */
27
28
29
30#ifdef SPM_PAGESIZE
31.macro _LPMI reg
32 lpm \reg, Z+
33.endm
34.macro _MOVW dh,dl, sh,sl
35 movw \dl, \sl
36.endm
37#else
38.macro _LPMI reg
39 lpm
40 mov \reg, r0
41 adiw ZL, 1
42.endm
43.macro _MOVW dh,dl, sh,sl
44 mov \dl, \sl
45 mov \dh, \sh
46.endm
47#endif
48
49
50
51;---------------------------------------------------------------------------;
52; Transmit a byte in serial format of N81
53;
54;Prototype: void xmit (uint8_t data);
55;Size: 16 words
56
57.global xmit
58.func xmit
59xmit:
60#if BIDIR
61 ldi r23, BPS-1 ;Pre-idle time for bidirectional data line
625: dec r23 ;
63 brne 5b ;/
64#endif
65 in r0, _SFR_IO_ADDR(SREG) ;Save flags
66
67 com r24 ;C = start bit
68 ldi r25, 10 ;Bit counter
69 cli ;Start critical section
70
711: ldi r23, BPS-1 ;----- Bit transferring loop
722: dec r23 ;Wait for a bit time
73 brne 2b ;/
74 brcs 3f ;MISO = bit to be sent
75 OUT_1 ;
763: brcc 4f ;
77 OUT_0 ;/
784: lsr r24 ;Get next bit into C
79 dec r25 ;All bits sent?
80 brne 1b ; no, coutinue
81
82 out _SFR_IO_ADDR(SREG), r0 ;End of critical section
83 ret
84.endfunc
85
86
87
88;---------------------------------------------------------------------------;
89; Receive a byte
90;
91;Prototype: uint8_t rcvr (void);
92;Size: 19 words
93
94.global rcvr
95.func rcvr
96rcvr:
97 in r0, _SFR_IO_ADDR(SREG) ;Save flags
98
99 ldi r24, 0x80 ;Receiving shift reg
100 cli ;Start critical section
101
1021: SKIP_IN_1 ;Wait for idle
103 rjmp 1b
1042: SKIP_IN_0 ;Wait for start bit
105 rjmp 2b
106 ldi r25, BPS/2 ;Wait for half bit time
1073: dec r25
108 brne 3b
109
1104: ldi r25, BPS ;----- Bit receiving loop
1115: dec r25 ;Wait for a bit time
112 brne 5b ;/
113 lsr r24 ;Next bit
114 SKIP_IN_0 ;Get a data bit into r24.7
115 ori r24, 0x80
116 brcc 4b ;All bits received? no, continue
117
118 out _SFR_IO_ADDR(SREG), r0 ;End of critical section
119 ret
120.endfunc
121
122
123; Not wait for start bit. This should be called after detecting start bit.
124.global recv
125.func recv
126recv:
127 in r0, _SFR_IO_ADDR(SREG) ;Save flags
128
129 ldi r24, 0x80 ;Receiving shift reg
130 cli ;Start critical section
131
132;1: SKIP_IN_1 ;Wait for idle
133; rjmp 1b
134;2: SKIP_IN_0 ;Wait for start bit
135; rjmp 2b
136 ldi r25, BPS/2 ;Wait for half bit time
1373: dec r25
138 brne 3b
139
1404: ldi r25, BPS ;----- Bit receiving loop
1415: dec r25 ;Wait for a bit time
142 brne 5b ;/
143 lsr r24 ;Next bit
144 SKIP_IN_0 ;Get a data bit into r24.7
145 ori r24, 0x80
146 brcc 4b ;All bits received? no, continue
147
148 ldi r25, BPS/2 ;Wait for half bit time
1496: dec r25
150 brne 6b
1517: SKIP_IN_1 ;Wait for stop bit
152 rjmp 7b
153
154 out _SFR_IO_ADDR(SREG), r0 ;End of critical section
155 ret
156.endfunc
diff --git a/protocol/iwrap/suart.h b/protocol/iwrap/suart.h
new file mode 100644
index 000000000..72725b998
--- /dev/null
+++ b/protocol/iwrap/suart.h
@@ -0,0 +1,8 @@
1#ifndef SUART
2#define SUART
3
4void xmit(uint8_t);
5uint8_t rcvr(void);
6uint8_t recv(void);
7
8#endif /* SUART */
diff --git a/protocol/iwrap/wd.h b/protocol/iwrap/wd.h
new file mode 100644
index 000000000..99058f033
--- /dev/null
+++ b/protocol/iwrap/wd.h
@@ -0,0 +1,159 @@
1/* This is from http://www.mtcnet.net/~henryvm/wdt/ */
2#ifndef _AVR_WD_H_
3#define _AVR_WD_H_
4
5#include <avr/io.h>
6
7/*
8Copyright (c) 2009, Curt Van Maanen
9
10Permission to use, copy, modify, and/or distribute this software for any
11purpose with or without fee is hereby granted, provided that the above
12copyright notice and this permission notice appear in all copies.
13
14THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
22
23include usage-
24 #include "wd.h" //if in same directory as project
25 #include <avr/wd.h> //if wd.h is in avr directory
26
27set watchdog modes and prescale
28
29usage-
30 WD_SET(mode,[timeout]); //prescale always set
31
32modes-
33 WD_OFF disabled
34 WD_RST normal reset mode
35 WD_IRQ interrupt only mode (if supported)
36 WD_RST_IRQ interrupt+reset mode (if supported)
37
38timeout-
39 WDTO_15MS default if no timeout provided
40 WDTO_30MS
41 WDTO_60MS
42 WDTO_120MS
43 WDTO_250MS
44 WDTO_500MS
45 WDTO_1S
46 WDTO_2S
47 WDTO_4S (if supported)
48 WDTO_8S (if supported)
49
50examples-
51 WD_SET(WD_RST,WDTO_1S); //reset mode, 1s timeout
52 WD_SET(WD_OFF); //watchdog disabled (if not fused on)
53 WD_SET(WD_RST); //reset mode, 15ms (default timeout)
54 WD_SET(WD_IRQ,WDTO_120MS); //interrupt only mode, 120ms timeout
55 WD_SET(WD_RST_IRQ,WDTO_2S); //interrupt+reset mode, 2S timeout
56
57
58for enhanced watchdogs, if the watchdog is not being used WDRF should be
59cleared on every power up or reset, along with disabling the watchdog-
60 WD_DISABLE(); //clear WDRF, then turn off watchdog
61
62*/
63
64//reset registers to the same name (MCUCSR)
65#if !defined(MCUCSR)
66#define MCUCSR MCUSR
67#endif
68
69//watchdog registers to the same name (WDTCSR)
70#if !defined(WDTCSR)
71#define WDTCSR WDTCR
72#endif
73
74//if enhanced watchdog, define irq values, create disable macro
75#if defined(WDIF)
76#define WD_IRQ 0xC0
77#define WD_RST_IRQ 0xC8
78#define WD_DISABLE() do{ \
79 MCUCSR &= ~(1<<WDRF); \
80 WD_SET(WD_OFF); \
81 }while(0)
82#endif
83
84//all watchdogs
85#define WD_RST 8
86#define WD_OFF 0
87
88//prescale values
89#define WDTO_15MS 0
90#define WDTO_30MS 1
91#define WDTO_60MS 2
92#define WDTO_120MS 3
93#define WDTO_250MS 4
94#define WDTO_500MS 5
95#define WDTO_1S 6
96#define WDTO_2S 7
97
98//prescale values for avrs with WDP3
99#if defined(WDP3)
100#define WDTO_4S 0x20
101#define WDTO_8S 0x21
102#endif
103
104//watchdog reset
105#define WDR() __asm__ __volatile__("wdr")
106
107//avr reset using watchdog
108#define WD_AVR_RESET() do{ \
109 __asm__ __volatile__("cli"); \
110 WD_SET_UNSAFE(WD_RST); \
111 while(1); \
112 }while(0)
113
114/*set the watchdog-
1151. save SREG
1162. turn off irq's
1173. reset watchdog timer
1184. enable watchdog change
1195. write watchdog value
1206. restore SREG (restoring irq status)
121*/
122#define WD_SET(val,...) \
123 __asm__ __volatile__( \
124 "in __tmp_reg__,__SREG__" "\n\t" \
125 "cli" "\n\t" \
126 "wdr" "\n\t" \
127 "sts %[wdreg],%[wden]" "\n\t" \
128 "sts %[wdreg],%[wdval]" "\n\t" \
129 "out __SREG__,__tmp_reg__" "\n\t" \
130 : \
131 : [wdreg] "M" (&WDTCSR), \
132 [wden] "r" ((uint8_t)(0x18)), \
133 [wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0))) \
134 : "r0" \
135)
136
137/*set the watchdog when I bit in SREG known to be clear-
1381. reset watchdog timer
1392. enable watchdog change
1405. write watchdog value
141*/
142#define WD_SET_UNSAFE(val,...) \
143 __asm__ __volatile__( \
144 "wdr" "\n\t" \
145 "sts %[wdreg],%[wden]" "\n\t" \
146 "sts %[wdreg],%[wdval]" "\n\t" \
147 : \
148 : [wdreg] "M" (&WDTCSR), \
149 [wden] "r" ((uint8_t)(0x18)), \
150 [wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0))) \
151)
152
153
154//for compatibility with avr/wdt.h
155#define wdt_enable(val) WD_SET(WD_RST,val)
156#define wdt_disable() WD_SET(WD_OFF)
157
158
159#endif /* _AVR_WD_H_ */