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