diff options
Diffstat (limited to 'protocol/iwrap')
| -rw-r--r-- | protocol/iwrap/iWRAP.txt | 376 | ||||
| -rw-r--r-- | protocol/iwrap/iwrap.c | 467 | ||||
| -rw-r--r-- | protocol/iwrap/iwrap.h | 49 | ||||
| -rw-r--r-- | protocol/iwrap/main.c | 378 | ||||
| -rw-r--r-- | protocol/iwrap/suart.S | 156 | ||||
| -rw-r--r-- | protocol/iwrap/suart.h | 8 | ||||
| -rw-r--r-- | protocol/iwrap/wd.h | 159 |
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 @@ | |||
| 1 | Bulegiga WT12 | ||
| 2 | ============= | ||
| 3 | WT12 is a bluetooth module from Bluegiga. http://www.bluegiga.com/ | ||
| 4 | |||
| 5 | iWRAP | ||
| 6 | higher layer interface for bluetooth firmware | ||
| 7 | communicate with UART | ||
| 8 | |||
| 9 | iWRAP HID | ||
| 10 | default setting | ||
| 11 | 115200 8bit/n/1/n | ||
| 12 | |||
| 13 | |||
| 14 | TODO | ||
| 15 | ---- | ||
| 16 | KiCAD circuit/PCB design | ||
| 17 | power 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 | ||
| 22 | software reset/bootloarder | ||
| 23 | LED indicator(chaging/paring/connecting) | ||
| 24 | license confirmation of suart.c | ||
| 25 | consumer page is not working | ||
| 26 | authenticate method/SSP | ||
| 27 | SPP keyboard support | ||
| 28 | SPP debug console support | ||
| 29 | mouse wheel feature request to Bluegiga | ||
| 30 | |||
| 31 | |||
| 32 | Problems | ||
| 33 | -------- | ||
| 34 | power consumption | ||
| 35 | no consumer page support(bug?) | ||
| 36 | no mouse wheel support | ||
| 37 | no paring management | ||
| 38 | no interactive auth method | ||
| 39 | |||
| 40 | |||
| 41 | UART hardware flow control | ||
| 42 | -------------------------- | ||
| 43 | (iWRAP4 User Guide 9.5) | ||
| 44 | 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. | ||
| 45 | 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: | ||
| 46 | - CTS pin must be grounded | ||
| 47 | - RTS pin must be left floating | ||
| 48 | |||
| 49 | |||
| 50 | Power Saving | ||
| 51 | ------------ | ||
| 52 | power consume | ||
| 53 | without opimization: 4hr to shutdown(310mAh) | ||
| 54 | 2011/08/25: 9hr(310mAh) SNIFF MASTER sleep/WDTO_120MS | ||
| 55 | |||
| 56 | measure 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 | |||
| 64 | HHKB keyswich | ||
| 65 | how to power off | ||
| 66 | I/O pin configuration when sleeping | ||
| 67 | FET switch for 5V regulator | ||
| 68 | |||
| 69 | Bluetooth module | ||
| 70 | power off when in USB mode | ||
| 71 | power off by FET switch | ||
| 72 | |||
| 73 | AVR configuration | ||
| 74 | unused pins | ||
| 75 | ADC | ||
| 76 | |||
| 77 | |||
| 78 | |||
| 79 | SET 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 | |||
| 90 | Reconnection | ||
| 91 | ------------ | ||
| 92 | SET CONTROL AUTOCALL 1124 5000 HID | ||
| 93 | 1124 HID service class | ||
| 94 | 5000 interval ms | ||
| 95 | |||
| 96 | HID profile | ||
| 97 | ----------- | ||
| 98 | This is needed to configure only once. | ||
| 99 | SET PROFILE HID ON | ||
| 100 | RESET | ||
| 101 | |||
| 102 | HID class | ||
| 103 | --------- | ||
| 104 | SET BT CLASS 005C0 // keyboard/mouse combined devie | ||
| 105 | |||
| 106 | Pairing Security | ||
| 107 | ---------------- | ||
| 108 | Secure 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 | |||
| 112 | for keyboard with SSP | ||
| 113 | SET BT AUTH * 0000 | ||
| 114 | SET BT SSP 2 0 | ||
| 115 | SET CONTROL CONFIG 800 | ||
| 116 | RESET | ||
| 117 | |||
| 118 | for keyboard without SSP | ||
| 119 | SET BT AUTH * 0000 | ||
| 120 | SET CONTROL CONFIG 800 | ||
| 121 | RESET | ||
| 122 | |||
| 123 | AUTH | ||
| 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 | |||
| 132 | Connecton | ||
| 133 | RING xx:xx:xx:xx:xx:xx xx HID // connection event | ||
| 134 | |||
| 135 | KILL xx:xx:xx:xx:xx:xx | ||
| 136 | |||
| 137 | Mode | ||
| 138 | ---- | ||
| 139 | Command mode | ||
| 140 | Data mode | ||
| 141 | Raw mode | ||
| 142 | (Simple mode not for a real keyboard) | ||
| 143 | |||
| 144 | Raw 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 | |||
| 187 | 2011/07/13 | ||
| 188 | set | ||
| 189 | SET BT BDADDR 00:07:80:47:22:14 | ||
| 190 | SET BT NAME HHKB pro BT | ||
| 191 | SET BT CLASS 0005c0 | ||
| 192 | SET BT AUTH * 0000 | ||
| 193 | SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP | ||
| 194 | SET BT LAP 9e8b33 | ||
| 195 | SET BT PAGEMODE 4 2000 1 | ||
| 196 | SET BT PAIR 78:dd:08:b7:e4:a2 a191189cd7e51030ad6a07848ce879bb | ||
| 197 | SET BT POWER 3 3 3 | ||
| 198 | SET BT ROLE 0 f 7d00 | ||
| 199 | SET BT SNIFF 0 20 1 8 | ||
| 200 | SET BT SSP 2 1 | ||
| 201 | SET BT MTU 667 | ||
| 202 | SET CONTROL AUTOCALL 1124 3000 HID | ||
| 203 | SET CONTROL BAUD 38400,8n1 | ||
| 204 | SET CONTROL CD 00 0 | ||
| 205 | SET CONTROL ECHO 7 | ||
| 206 | SET CONTROL ESCAPE 43 00 1 | ||
| 207 | SET CONTROL GAIN 0 5 | ||
| 208 | SET CONTROL INIT SET CONTROL MUX 0 | ||
| 209 | SET CONTROL MSC DTE 00 00 00 00 00 00 | ||
| 210 | SET CONTROL MUX 1 | ||
| 211 | SET CONTROL PIO 00 00 | ||
| 212 | SET CONTROL READY 00 | ||
| 213 | SET PROFILE HID f HID | ||
| 214 | SET | ||
| 215 | |||
| 216 | info config | ||
| 217 | |||
| 218 | !!! THIS IS BETA RELEASE AND MAY BE USED FOR EVALUATION PURPOSES ONLY !!! | ||
| 219 | |||
| 220 | WRAP THOR AI (4.1.0 build 435) | ||
| 221 | Copyright (c) 2003-2011 Bluegiga Technologies Inc. | ||
| 222 | Compiled 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 | ||
| 246 | READY. | ||
| 247 | |||
| 248 | |||
| 249 | |||
| 250 | |||
| 251 | 2011/07/07 settings: | ||
| 252 | set | ||
| 253 | SET BT BDADDR 00:07:80:47:22:14 | ||
| 254 | SET BT NAME HHKB Pro BT | ||
| 255 | SET BT CLASS 0005c0 | ||
| 256 | SET BT AUTH * 000 | ||
| 257 | SET BT IDENT BT:47 f000 4.0.0 Bluegiga iWRAP | ||
| 258 | SET BT LAP 9e8b33 | ||
| 259 | SET BT PAGEMODE 4 2000 1 | ||
| 260 | SET BT PAIR 78:dd:08:b7:e4:a2 9e54d0aabb1b4d73cfccddb1ea4ef2d6 | ||
| 261 | SET BT POWER 3 3 3 | ||
| 262 | SET BT ROLE 0 f 7d00 | ||
| 263 | SET BT SNIFF 0 20 1 8 | ||
| 264 | SET BT SSP 3 0 | ||
| 265 | SET BT MTU 667 | ||
| 266 | SET CONTROL BAUD 38400,8n1 | ||
| 267 | SET CONTROL CD 00 0 | ||
| 268 | SET CONTROL ECHO 7 | ||
| 269 | SET CONTROL ESCAPE 255 00 1 | ||
| 270 | SET CONTROL GAIN 0 5 | ||
| 271 | SET CONTROL INIT set control mux 0 | ||
| 272 | SET CONTROL MSC DTE 00 00 00 00 00 00 | ||
| 273 | SET CONTROL PREAMP 1 1 | ||
| 274 | SET CONTROL READY 00 | ||
| 275 | SET PROFILE HID HID | ||
| 276 | SET PROFILE SPP Bluetooth Serial Port | ||
| 277 | SET | ||
| 278 | |||
| 279 | info config | ||
| 280 | WRAP THOR AI (4.0.0 build 317) | ||
| 281 | Copyright (c) 2003-2010 Bluegiga Technologies Inc. | ||
| 282 | Compiled 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 | ||
| 303 | READY. | ||
| 304 | |||
| 305 | |||
| 306 | |||
| 307 | 2011/08/23: | ||
| 308 | SET BT BDADDR 00:07:80:47:22:14 | ||
| 309 | SET BT NAME HHKB pro BT | ||
| 310 | SET BT CLASS 0005c0 | ||
| 311 | SET BT AUTH * 0000 | ||
| 312 | SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP | ||
| 313 | SET BT LAP 9e8b33 | ||
| 314 | SET BT PAGEMODE 4 2000 1 | ||
| 315 | SET BT PAIRCOUNT 4 | ||
| 316 | SET BT POWER 3 3 3 | ||
| 317 | SET BT ROLE 1 f 12c0 | ||
| 318 | SET BT SNIFF 10 2 1 8 | ||
| 319 | SET BT SSP 3 0 | ||
| 320 | SET BT MTU 667 | ||
| 321 | SET CONTROL BAUD 38400,8n1 | ||
| 322 | SET CONTROL CD 00 0 | ||
| 323 | SET CONTROL ECHO 7 | ||
| 324 | SET CONTROL ESCAPE 43 00 1 | ||
| 325 | SET CONTROL GAIN 0 5 | ||
| 326 | SET CONTROL INIT SET CONTROL MUX 0 | ||
| 327 | SET CONTROL MSC DTE 00 00 00 00 00 00 | ||
| 328 | SET CONTROL MUX 1 | ||
| 329 | SET CONTROL PIO 00 00 | ||
| 330 | SET CONTROL READY 00 | ||
| 331 | SET PROFILE HID 7 HIDKeyboardMouse | ||
| 332 | SET | ||
| 333 | |||
| 334 | SET CONTROL CONFIG 0000 0004 481e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE DEEP_SLEEP INTERACTIVE_PIN UART_LATENCY 23D_NOKLUDGE | ||
| 335 | |||
| 336 | |||
| 337 | |||
| 338 | 2011/08/25: | ||
| 339 | SET BT BDADDR 00:07:80:47:22:14 | ||
| 340 | SET BT NAME HHKB pro BT | ||
| 341 | SET BT CLASS 0005c0 | ||
| 342 | |||
| 343 | SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP | ||
| 344 | SET BT LAP 9e8b33 | ||
| 345 | SET BT PAGEMODE 4 2000 1 | ||
| 346 | SET BT PAIRCOUNT 4 | ||
| 347 | SET BT PAIR 78:dd:08:b7:e4:a2 0be83335a03fed8ededae42e99554e28 | ||
| 348 | SET BT POWER 3 3 3 | ||
| 349 | SET BT ROLE 1 f 12c0 | ||
| 350 | SET BT SNIFF 100 20 1 8 | ||
| 351 | SET BT SSP 3 0 | ||
| 352 | SET BT MTU 667 | ||
| 353 | SET CONTROL BAUD 38400,8n1 | ||
| 354 | SET CONTROL CD 00 0 | ||
| 355 | SET CONTROL ECHO 7 | ||
| 356 | SET CONTROL ESCAPE - 20 1 | ||
| 357 | SET CONTROL GAIN 0 5 | ||
| 358 | SET CONTROL INIT SET CONTROL MUX 0 | ||
| 359 | SET CONTROL MSC DTE 00 00 00 00 00 00 | ||
| 360 | SET CONTROL MUX 1 | ||
| 361 | SET CONTROL PIO 00 00 | ||
| 362 | SET CONTROL READY 00 | ||
| 363 | SET PROFILE HID f HIDKeyboardMouse | ||
| 364 | SET | ||
| 365 | |||
| 366 | |||
| 367 | SET CONTROL CONFIG 0000 0000 490e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE INTERACTIVE_PIN UART_LATENCY | ||
| 368 | |||
| 369 | |||
| 370 | 2011/09/08: | ||
| 371 | SET 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 | |||
| 376 | EOF | ||
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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along 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 | |||
| 51 | static uint8_t connected = 0; | ||
| 52 | //static uint8_t channel = 1; | ||
| 53 | |||
| 54 | /* iWRAP buffer */ | ||
| 55 | #define MUX_BUF_SIZE 64 | ||
| 56 | static char buf[MUX_BUF_SIZE]; | ||
| 57 | static uint8_t snd_pos = 0; | ||
| 58 | |||
| 59 | #define MUX_RCV_BUF_SIZE 256 | ||
| 60 | static char rcv_buf[MUX_RCV_BUF_SIZE]; | ||
| 61 | static uint8_t rcv_head = 0; | ||
| 62 | static uint8_t rcv_tail = 0; | ||
| 63 | |||
| 64 | |||
| 65 | /* receive buffer */ | ||
| 66 | static 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 | |||
| 75 | static 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 | /* | ||
| 86 | static char rcv_peek(void) | ||
| 87 | { | ||
| 88 | if (rcv_head == rcv_tail) | ||
| 89 | return 0; | ||
| 90 | return rcv_buf[rcv_tail]; | ||
| 91 | } | ||
| 92 | */ | ||
| 93 | |||
| 94 | static void rcv_clear(void) | ||
| 95 | { | ||
| 96 | rcv_tail = rcv_head = 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | /* iWRAP response */ | ||
| 100 | ISR(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 | *------------------------------------------------------------------*/ | ||
| 139 | void 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 | |||
| 150 | void 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 | |||
| 158 | void iwrap_send(const char *s) | ||
| 159 | { | ||
| 160 | while (*s) | ||
| 161 | xmit(*s++); | ||
| 162 | } | ||
| 163 | |||
| 164 | /* send buffer */ | ||
| 165 | void 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 | |||
| 172 | void iwrap_buf_del(void) | ||
| 173 | { | ||
| 174 | if (snd_pos) | ||
| 175 | snd_pos--; | ||
| 176 | } | ||
| 177 | |||
| 178 | void iwrap_buf_send(void) | ||
| 179 | { | ||
| 180 | buf[snd_pos] = '\0'; | ||
| 181 | snd_pos = 0; | ||
| 182 | iwrap_mux_send(buf); | ||
| 183 | } | ||
| 184 | |||
| 185 | void 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 | |||
| 227 | void 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 | |||
| 252 | void 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 | |||
| 265 | void iwrap_sleep(void) | ||
| 266 | { | ||
| 267 | iwrap_mux_send("SLEEP"); | ||
| 268 | } | ||
| 269 | |||
| 270 | void iwrap_sniff(void) | ||
| 271 | { | ||
| 272 | } | ||
| 273 | |||
| 274 | void iwrap_subrate(void) | ||
| 275 | { | ||
| 276 | } | ||
| 277 | |||
| 278 | bool iwrap_failed(void) | ||
| 279 | { | ||
| 280 | if (strncmp(rcv_buf, "SYNTAX ERROR", 12)) | ||
| 281 | return true; | ||
| 282 | else | ||
| 283 | return false; | ||
| 284 | } | ||
| 285 | |||
| 286 | uint8_t iwrap_connected(void) | ||
| 287 | { | ||
| 288 | return connected; | ||
| 289 | } | ||
| 290 | |||
| 291 | uint8_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 | *------------------------------------------------------------------*/ | ||
| 307 | static uint8_t keyboard_leds(void); | ||
| 308 | static void send_keyboard(report_keyboard_t *report); | ||
| 309 | static void send_mouse(report_mouse_t *report); | ||
| 310 | static void send_system(uint16_t data); | ||
| 311 | static void send_consumer(uint16_t data); | ||
| 312 | |||
| 313 | static host_driver_t driver = { | ||
| 314 | keyboard_leds, | ||
| 315 | send_keyboard, | ||
| 316 | send_mouse, | ||
| 317 | send_system, | ||
| 318 | send_consumer | ||
| 319 | }; | ||
| 320 | |||
| 321 | host_driver_t *iwrap_driver(void) | ||
| 322 | { | ||
| 323 | return &driver; | ||
| 324 | } | ||
| 325 | |||
| 326 | static uint8_t keyboard_leds(void) { | ||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | |||
| 330 | static 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 | |||
| 350 | static 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 | |||
| 367 | static void send_system(uint16_t data) | ||
| 368 | { | ||
| 369 | /* not supported */ | ||
| 370 | } | ||
| 371 | |||
| 372 | static 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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along 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 | |||
| 30 | host_driver_t *iwrap_driver(void); | ||
| 31 | |||
| 32 | void iwrap_init(void); | ||
| 33 | void iwrap_send(const char *s); | ||
| 34 | void iwrap_mux_send(const char *s); | ||
| 35 | void iwrap_buf_send(void); | ||
| 36 | void iwrap_buf_add(uint8_t c); | ||
| 37 | void iwrap_buf_del(void); | ||
| 38 | |||
| 39 | void iwrap_call(void); | ||
| 40 | void iwrap_kill(void); | ||
| 41 | void iwrap_unpair(void); | ||
| 42 | void iwrap_sleep(void); | ||
| 43 | void iwrap_sniff(void); | ||
| 44 | void iwrap_subrate(void); | ||
| 45 | bool iwrap_failed(void); | ||
| 46 | uint8_t iwrap_connected(void); | ||
| 47 | uint8_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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along 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 | |||
| 41 | static void sleep(uint8_t term); | ||
| 42 | static bool console(void); | ||
| 43 | static uint8_t console_command(uint8_t c); | ||
| 44 | static uint8_t key2asc(uint8_t key); | ||
| 45 | |||
| 46 | |||
| 47 | /* | ||
| 48 | static 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 | /* | ||
| 62 | static 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 | ||
| 82 | static 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 | |||
| 89 | static void enable_vusb(void) | ||
| 90 | { | ||
| 91 | USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); | ||
| 92 | usbDeviceConnect(); | ||
| 93 | } | ||
| 94 | |||
| 95 | static 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 | |||
| 109 | void 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 | |||
| 120 | static bool sleeping = false; | ||
| 121 | static bool insomniac = false; // TODO: should be false for power saving | ||
| 122 | static uint16_t last_timer = 0; | ||
| 123 | |||
| 124 | int 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 | |||
| 192 | static 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 | |||
| 207 | ISR(WDT_vect) | ||
| 208 | { | ||
| 209 | // wake up | ||
| 210 | } | ||
| 211 | |||
| 212 | static 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 | |||
| 250 | uint8_t command_extra() | ||
| 251 | { | ||
| 252 | return console_command(key2asc(host_get_first_key())); | ||
| 253 | } | ||
| 254 | |||
| 255 | static 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 | ||
| 320 | static 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 | ||
| 59 | xmit: | ||
| 60 | #if BIDIR | ||
| 61 | ldi r23, BPS-1 ;Pre-idle time for bidirectional data line | ||
| 62 | 5: 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 | |||
| 71 | 1: ldi r23, BPS-1 ;----- Bit transferring loop | ||
| 72 | 2: dec r23 ;Wait for a bit time | ||
| 73 | brne 2b ;/ | ||
| 74 | brcs 3f ;MISO = bit to be sent | ||
| 75 | OUT_1 ; | ||
| 76 | 3: brcc 4f ; | ||
| 77 | OUT_0 ;/ | ||
| 78 | 4: 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 | ||
| 96 | rcvr: | ||
| 97 | in r0, _SFR_IO_ADDR(SREG) ;Save flags | ||
| 98 | |||
| 99 | ldi r24, 0x80 ;Receiving shift reg | ||
| 100 | cli ;Start critical section | ||
| 101 | |||
| 102 | 1: SKIP_IN_1 ;Wait for idle | ||
| 103 | rjmp 1b | ||
| 104 | 2: SKIP_IN_0 ;Wait for start bit | ||
| 105 | rjmp 2b | ||
| 106 | ldi r25, BPS/2 ;Wait for half bit time | ||
| 107 | 3: dec r25 | ||
| 108 | brne 3b | ||
| 109 | |||
| 110 | 4: ldi r25, BPS ;----- Bit receiving loop | ||
| 111 | 5: 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 | ||
| 126 | recv: | ||
| 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 | ||
| 137 | 3: dec r25 | ||
| 138 | brne 3b | ||
| 139 | |||
| 140 | 4: ldi r25, BPS ;----- Bit receiving loop | ||
| 141 | 5: 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 | ||
| 149 | 6: dec r25 | ||
| 150 | brne 6b | ||
| 151 | 7: 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 | |||
| 4 | void xmit(uint8_t); | ||
| 5 | uint8_t rcvr(void); | ||
| 6 | uint8_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 | /* | ||
| 8 | Copyright (c) 2009, Curt Van Maanen | ||
| 9 | |||
| 10 | Permission to use, copy, modify, and/or distribute this software for any | ||
| 11 | purpose with or without fee is hereby granted, provided that the above | ||
| 12 | copyright notice and this permission notice appear in all copies. | ||
| 13 | |||
| 14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 15 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 16 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 17 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 18 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 19 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 20 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 21 | |||
| 22 | |||
| 23 | include usage- | ||
| 24 | #include "wd.h" //if in same directory as project | ||
| 25 | #include <avr/wd.h> //if wd.h is in avr directory | ||
| 26 | |||
| 27 | set watchdog modes and prescale | ||
| 28 | |||
| 29 | usage- | ||
| 30 | WD_SET(mode,[timeout]); //prescale always set | ||
| 31 | |||
| 32 | modes- | ||
| 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 | |||
| 38 | timeout- | ||
| 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 | |||
| 50 | examples- | ||
| 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 | |||
| 58 | for enhanced watchdogs, if the watchdog is not being used WDRF should be | ||
| 59 | cleared 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- | ||
| 115 | 1. save SREG | ||
| 116 | 2. turn off irq's | ||
| 117 | 3. reset watchdog timer | ||
| 118 | 4. enable watchdog change | ||
| 119 | 5. write watchdog value | ||
| 120 | 6. 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- | ||
| 138 | 1. reset watchdog timer | ||
| 139 | 2. enable watchdog change | ||
| 140 | 5. 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_ */ | ||
