aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keyboards/hhkb/config.h41
-rw-r--r--keyboards/hhkb/rn42/MEMO.txt262
-rw-r--r--keyboards/hhkb/rn42/PowerSave.txt88
-rw-r--r--keyboards/hhkb/rn42/RN42.txt408
-rw-r--r--keyboards/hhkb/rn42/battery.c130
-rw-r--r--keyboards/hhkb/rn42/battery.h35
-rw-r--r--keyboards/hhkb/rn42/main.c106
-rw-r--r--keyboards/hhkb/rn42/rn42.c265
-rw-r--r--keyboards/hhkb/rn42/rn42.h30
-rw-r--r--keyboards/hhkb/rn42/rn42_task.c467
-rw-r--r--keyboards/hhkb/rn42/rn42_task.h14
-rw-r--r--keyboards/hhkb/rn42/suart.S156
-rw-r--r--keyboards/hhkb/rn42/suart.h8
-rw-r--r--keyboards/hhkb/rules.mk30
14 files changed, 2040 insertions, 0 deletions
diff --git a/keyboards/hhkb/config.h b/keyboards/hhkb/config.h
index 3f0528b4b..af7ecc5e2 100644
--- a/keyboards/hhkb/config.h
+++ b/keyboards/hhkb/config.h
@@ -54,6 +54,47 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
54 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ 54 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
55) 55)
56 56
57#ifdef HHKB_RN42_ENABLE
58// rn42 support -- acquired from the tmk repo. This is almost certainly not
59// integrated with qmk in the correct way.
60
61#define SUART_OUT_PORT PORTD
62#define SUART_OUT_BIT 0
63#define SUART_IN_PIN PIND
64#define SUART_IN_BIT 1
65
66#ifdef __AVR_ATmega32U4__
67 /* iom32u4.h has no definition of UCSR1D. copy from iom32u2.h */
68 #define UCSR1D _SFR_MEM8(0xCB)
69 #define RTSEN 0
70 #define CTSEN 1
71
72 #define SERIAL_UART_BAUD 115200
73 #define SERIAL_UART_DATA UDR1
74 #define SERIAL_UART_UBRR ((F_CPU/(16.0*SERIAL_UART_BAUD)-1+0.5))
75 #define SERIAL_UART_RXD_VECT USART1_RX_vect
76 #define SERIAL_UART_TXD_READY (UCSR1A&(1<<UDRE1))
77 #define SERIAL_UART_INIT() do { \
78 UBRR1L = (uint8_t) SERIAL_UART_UBRR; /* baud rate */ \
79 UBRR1H = ((uint16_t)SERIAL_UART_UBRR>>8); /* baud rate */ \
80 UCSR1B |= (1<<RXCIE1) | (1<<RXEN1); /* RX interrupt, RX: enable */ \
81 UCSR1B |= (0<<TXCIE1) | (1<<TXEN1); /* TX interrupt, TX: enable */ \
82 UCSR1C |= (0<<UPM11) | (0<<UPM10); /* parity: none(00), even(01), odd(11) */ \
83 UCSR1D |= (0<<RTSEN) | (0<<CTSEN); /* RTS, CTS(no flow control by hardware) */ \
84 DDRD |= (1<<5); PORTD &= ~(1<<5); /* RTS for flow control by firmware */ \
85 sei(); \
86 } while(0)
87 #define SERIAL_UART_RTS_LO() do { PORTD &= ~(1<<5); } while (0)
88 #define SERIAL_UART_RTS_HI() do { PORTD |= (1<<5); } while (0)
89#else
90 #error "USART configuration is needed."
91#endif
92
93/* power control of key switch board */
94#define HHKB_POWER_SAVING
95
96#endif
97
57/* 98/*
58 * Feature disable options 99 * Feature disable options
59 * These options are also useful to firmware size reduction. 100 * These options are also useful to firmware size reduction.
diff --git a/keyboards/hhkb/rn42/MEMO.txt b/keyboards/hhkb/rn42/MEMO.txt
new file mode 100644
index 000000000..0ad56c79c
--- /dev/null
+++ b/keyboards/hhkb/rn42/MEMO.txt
@@ -0,0 +1,262 @@
1Memo of deveopment
2==================
3just memo, NOT WORTH READING
4
52015/11/24
6JP Bluetooth:
7 RN-42 cannot send Japanese keys like; henkan, mu-henkan and kana, JPY and RO.
8 It seems HID usage more than 0x65 cannot be send with the module.
9 http://shiki.esrille.com/2014/07/bluetoothnisse.html
10
11
12Bug:
13- Factory Reset PIO4 doesn't work
14 - the reason is unclear - 12/08 NOT LOOK INTO ANY MORE
15 - WORKAROUND: use serial pins(3.3V, GND, RX and TX)
16 - SF,1 and R,1 to set factory defalult
17
18
19Todo:
20- LED cover and switch knob and new Slide Switch
21- RN42 auto configuration
22 - configure the module as HID device every time powering up
23 - this'll reduce work load of assembly
24
25- move rn42 to protocol directory when it becomes reusable stack
26
27- sendchar() in lufa.c no buffer
28 - no buffering. character lost can be caused.
29- LUFA sendchar should be buffered and serial_uart.c buffur size is too large(256).
30
31- BT operations
32 - disconnect
33 - new connection
34 - remove connection
35
36- sendchar() in lufa.c block loop - DONE 11/29
37 - block loop when powered with AC adapter
38 - FrameNumber is not updated when adapter powered
39
40Improving:
41- ADC resolution
42 AVR120
43 AVR32138
44 - Enhancing ADC resolution by oversampling
45 AVR121 http://www.atmel.com/images/doc8003.pdf
46 - disable digital input buffer DIDR(7.8.6)
47
48Design:
49- suspend.h - DONE 11/26
50 - remove argument from suspend_power_down() for backward compatitibility
51- remove MCU dependent power saving code from core/keyboard - DONE 11/23
52 - it should be located in project matrix.c
53- HHKB matrix.c needs matrix_prev?
54 - is_modified() is obsolete now. really needs?
55- ADC: removing AREF capacitor C10
56 - seems to be better while usb powered
57 - still bad while battery powered
58 http://electronics.stackexchange.com/questions/105849/avcc-and-capacitor-using-adc
59- ADC: smaller resistors for voltage dividor
60 - 1K + 1K: not improved. - 11/27
61
62
63LUFA:
64USB connection check: state of USB deivce
65- USB_DeviceState:
66 USB_Deivce_State_t { Unattached, Powered, Default, Addressed, Configured*, Suspended* }
67 Unattached: unpluged
68 Powered: pluged with power adapter
69 Default: enumerate process bigin
70 Addressed: addressed
71 Configured: enumerated
72 Suspended: suspended
73
74- USB_IsInitialized: state of LUFA core setup
75 becomes true in USB_Init() USBController_AVR8.c
76 becomes false in USB_Disable() USBController_AVR8.c
77- USB_VBUS_GetStatus(): state of VBUS(power/connection)
78- USB_Disable() detaches, disables all interrupts, controller, PLL, regulater.
79
80- When connect to power adapter
81 - event happened: CW or CSW or C or DDC
82 - USB state: not configured
83
84- USB evnets
85 - USB connect: CSWRWRW
86 - USB connect but fail to enumeration: CWRWRWRWS
87 - USB disconnect: D
88 - Power adapter connect: CW, CSW, C
89 - Power adapter disconnect: D
90
91
92Power saving:
93- Pro2 current consumption
94 - active: 138.2mA(no device on Hub)
95 - suspended: 30.9mA(WakeUp enabled DIPSW6)
96 - suspended: 0mA->46.0mA(WakeUp disabled DIPSW6)
97- Pro current consumption
98 - active: 54.0mA
99 - suspended: 40.5mA(WakeUp enabled DIPSW6)
100 - suspended: 0.3mA(WakeUp disabled DIPSW6)
101
102- RN42 3.3V
103 - disconnected(Idle): 5mA (config mode)
104 - connected(Active):
105 SW,0000: 23-26mA
106 SW,0010: 27-29mA worse than 0000 for unknown reason
107 SW,0020: 17-19mA mouse NG
108 SW,0030: 13-16mA laggy mouse NG
109 SW,0050: 10-13mA laggy mouse NG
110
111- matrix power saving
112 - power saving while externally powered and not while unpluged
113- confirm suspend mode lufa.c: matrix_power_*, suspend_wakeup_condition
114- 8MHz clock
115- When not connected in a few minutes get into deep sleep to save battery life
116- CTS is needed for waking up from deep sleep? How deep sleep is activated?
117- firmware controlled 3.3V DC converter to switch on/off BT module
118- sleep MCU and BT module(keyboard is not used)
119- deep sleep MCU and BT module(keyboard is not used for long time)
120- deep sleep MCU and turn off BT module(keyboard is not used and not connected)
121- Battery ADC; switching, high resistance
122 - switching gnd end of divider with PF4
123 - high resistor 100K/1M?
124 capacitor 10nF
125 http://www.eevblog.com/forum/beginners/measuring-battery-voltage-without-consuming-current/
126- During USB suspend change clock source to internal RC from external Xtal(6.8)
127- FRZCLK: you can freeze clock for power saving. still WAKEUPI and VBUSTI interrupts are available while freezing.(21.7.3)
128- Suspend: Clear Suspend Bit, Freeze clock, disable PLL, MCU sleep(21.13)
129- Voltage reference(8.1.1)
130 - to reduce power consumption while power down mode
131- unset ADEN before sleep(24.7)
132
133
134
135
136
137
138
139Lipo
140----
141850mA lasts around 9 hours(07/28)
142
143Sparkfun Polymer Lithium Ion Battery 850mAh:
144https://www.sparkfun.com/products/341
145Lipo Cell spec:
146https://www.sparkfun.com/datasheets/Batteries/063048%20Li-polymer.pdf
147Protection spec:
148http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Prototyping/BatteryProtection.pdf
149 min typical max
150 over-charge 4.255 4.280 4.305
151 over-charge discover? 4.030 4.080 4.130
152 over-discharge 2.827 2.900 2.973
153 over-discharge discover 3.022 3.100 3.178
154
155ADC voltage monitor: voltage divider 10K+10K(0.5)
156 ADC=V*0.5/2.56*1024
157
158 V ADC
159 ------------------
160 4.20 0x347(839)
161 3.10 0x26b(619)
162
163
164
165
166TROUBLE SHOOT
167-------------
16807/16 After fix of voltage dividor on GPIO6, had a trouble that it could not send a char to BT module, though could receive.
169 Found R8 had wrong 1K resistor and changed to 10K, after that it can send to the module again. Not sure how it had sent with the wrong 1K before.
170
17107/18 On Linux, had an USB related trouble; keyboard or console didn't work for some reason. Changing PID cured this problem. Very annoying, took very long time before resolved it.
172
17312/07 rn42_rts() read 1 every time. R12 broke in open mode(no coductive), idk why, too much heat with soldering? and PF1 pin was not soldered.
174 It resolved with resoldering PF1 and new resistor on R12.
175
176
177
178
179Done:
180- low battery alert(solid light) 09/04
181- *** Rev.E BT test *** - DONE
182 - with MCP73832, new Schottky, tantalum caps - DONE 12/07
183 * MCP73832 doesn't leak from Vcc pin when unpluged and battery powered
184 34mV vs 2.07V(MCP73831) at Vcc pin
185 MCP73832 doesn't need revese protection diode D5
186 * PMEG2010ER is very low VF while reverse current/voltage is high
187 VF=0.96 vs 1.98(RB160M-30TR)with Fluke 175
188 Anode of D11 is 680mV vs 20mV(RB160M-30TR)
189 780mV is still low < 1.4V VBUS plugin detection(21.11)
190 this doesn't cause false VBUS detect
191 and 780mV on MCP73832 Vcc pin is also no problem.
192 D5 can be removed.
193 - ADC divider switching - DONE 12/07
194 * Drain and Source of Q4 Pch was reversed wrongly on Rev.E.
195
196 - reverse current from Lipo charger - DONE 12/07
197 * MCP73832 has no recverse current from Vcc pin unlike MCP73831
198
199
200- Rev.F design - DONE
201 - current measure point - DONE 12/08
202 - change value of cap 68->47 - DONE 12/08
203 - PPTC land pattern: no solder jumper, use 0Ohm resistor instead - CANCEL 12/08
204 - Q4 Pch FET: wrong Drain and Source - DONE 12/08
205 - D5 can be removed. - DONE 12/08
206
207
208
209- BT_INDICATOR LED turns on wrongly when touching line or pin. -- pull-up enabled on PF6/GPIO2 08/30
210- Lipo charger configuration: fast charge time: USB charger spec? -- used 2kohm
211- use LED of charger to alarm low battery. LED should be powered directly from Lipo? - cancel; powered from VUSB
212- Use RTS in serial_uart.c to resolve missing chars from help message of RN-42 - done
213- CTS/RTS lines are needed? just connect in loop back if no flow control is needed. - done
214- add IO pin to charger status CHRG; LED control(low) and detect charge status(input HiZ) 07.24
215- LINKED: add trace on PIO2 to PF6 07.24
216- Lipo voltage ADC sensing
217- Lipo charger MCP73831: needs capacitor 4.7uF *2
218- USB connection check - 07.01
219- BT on/off check: whether RX line is pulled up? - checking RTS 07.01
220- USB/BT switching BT is on -> BT, BT is off -> USB - 07.01
221- Under voltage lock out UVLO for protection of Lipo - Lipo has discharge protection at 3.100V 07.01
222- Power saving: HHKB scan, BT radio control - 9h with 850mAh, this is enough 07.01
223- Power selector doesn't work; Q4 MOSFET leaks from Lipo to USB power line. -- use Schottky instead 07/04
224
225- wrongly suspended when powered from adapter without USB connection - DONE
226 - suspend event may occur when plug into adapter
227 - and never wake until conected to real USB line
228 - without debug print via USB no problem; CSW(wake just after suspend as real USB line)
229 - seems like USB print causes this problem after suspended
230
231- lose USB connection during power-down mode - DONE
232 - USB initialize code in main() causes this - WRONG
233 - Do not power-down during USB connection is active - DONE 11/11
234 (USB_DeviceState == USB_DEVICE_Configured) is used to check USB connection
235 matrix_power_down() matrix.c - 11/23
236
237- with Nexus5 keyboard and mouse are very laggy.
238 Not confirmed. 01/15
239
240- switch BT host connections - CANCEL 01/15
241 - switch next connection
242 cannot switch connection with version 6.15 at least
243
244- When given power only from wall wart adapter - DONE? not confirmed 01/15
245 - it sleeps. it should not sleep
246 - Configured state without USB connection?
247
248- timer is slow while power down - DONE 11/26
249 - time out interrupt is lost while power down?
250 - interrupt of watchdog timer compensates timer counter(avr/suspend.c)
251
252- repeated CHARGING/FULL_CHARGED - No longer problem 01/15
253 - In LTC sharp pulses are observed.
254 - MCP has no pulse but still has a problem.
255 - needs more wait before read pin state? - NO
256
257- USB plug-in fails while BT - No longer problem 01/15
258 - it ends in suspend state
259 - maybe, not responsive to host enumeration process due to power-down.
260 - matrix_power_down() only when state is unattached - 11/26
261 - need to observe a while
262
diff --git a/keyboards/hhkb/rn42/PowerSave.txt b/keyboards/hhkb/rn42/PowerSave.txt
new file mode 100644
index 000000000..4b9c8f415
--- /dev/null
+++ b/keyboards/hhkb/rn42/PowerSave.txt
@@ -0,0 +1,88 @@
1Power Saving
2============
3
4
5MCU+HHKB Power Comsumption
6--------------------------
7Battery drive:
8 idle 18.9mA
9 active 35.8mA
10
11USB powered:
12 40.0mA
13 52mA 01/17
14
15Other keyboards:
16HHKB Pro 55mA
17HHKB Pro2 140mA
18HHKB Pro 42mA(Alt)
19HHKB Pro2 52mA(Alt BT controller USB mode)
20HHKB Pro2 88mA(Alt BT controller BT mode connected)
21HHKB Pro2 68mA(Alt BT controller BT mode config mode)
22Poker X 6mA
23Infinity 24mA(TMK)
24 65mA(kiibohd)
25
26
27HHKB key switch power control
28-----------------------------
29MOS FET Nch: BSS138 or IRLML6344T, either works and no apparent difference.
30Normally on(pull-up) or off(pull-down)? interms of power saving it prefers pull-down?
31
32Pull-down will be better for power saving, normally off.
33
34
35
36Used Timer
37----------
38
398MHz clock
40----------
411) 16MHz xtal with system prescaler div2: F_CPU=8MHz, F_USB=16MHz
422) 8MHz xtal with div1: F_CPU=8MHz, F_USB=8MHz
43Hardware USART doesn't work at 115200bps with 8MHz(F_CPU).
44
45workaround:
46a) use Sotwre serial for communcation with RN-42
47b) reduce baud of RN-42 to lower rate;(factory default is 115200bps)
4810/03
49
50
51
52Slave mode
53----------
54Discovery/Inquire
55Connect/Page
56
57SI,0012
58SJ,0012
59InqWindw=0100
60PagWindw=0100
61
62
63Sniff mode
64----------
650.625ms * <hex>
66SW,0320 Very sluggish. Type is not lost but very slow to register.
67SW,0160 Still sluggish. may transposed? can type but ...
68 Mouse point move intermittently
69SW,0020 feel a bit late like stumble(20ms)
70SW,0010 feel no latency(10ms)
71
72
73Deep sleep
74----------
75SW,8010
76
77
78TX power
79--------
80SY,fff4
81
82
83IO pins
84-------
85S%,1000 status led and connection control don't work
86 GPIO5: status LED
87 GPIO6: Connection control
88 GPIO2: linked status
diff --git a/keyboards/hhkb/rn42/RN42.txt b/keyboards/hhkb/rn42/RN42.txt
new file mode 100644
index 000000000..b30a0327d
--- /dev/null
+++ b/keyboards/hhkb/rn42/RN42.txt
@@ -0,0 +1,408 @@
1RN-42 Bluetooth Module Support
2==============================
3Bluetooth controller board works with HHKB Pro2, JP, Type-S and Type-S JP and it supports both USB and Bluetooth as keyboard output protocol. Bluetooth module Roving Networks/Microchip RN-42 is installed on the board.
4
5
6RN-42:
7http://www.microchip.com/wwwproducts/Devices.aspx?product=RN42
8
9
10Capabitlities:
11- USB keyboard functions
12 completely equivarent to USB controller including mouse keys and NKRO.
13- Switching between USB and Bluetooth
14 You can switch the two connections with BT switch or key combination.
15- RN-42 config mode
16 You can change power/connection configuration of the module if needed.
17- Low battery alert
18 Red LED turns on when low voltage.
19- RN-42 status indicator
20 LED indicates status of Bluetooth connection.
21- Pairing
22 The module stores up to 8 connections.
23- Auto connect
24 The module connects the last connected device automatically.
25- iOS support
26 works as keyboard with iPhone5. No tested completely.
27- Android support
28 works as keyboard and mouse with Nexus5. No tested completely.
29- Mouse keys over BT
30 Note that iOS doesn't accept mouse device.
31
32
33Limitations:
34- Short battery life
35 Around 12hr with 1000mAh
36- No connection switching
37 RN-42 auto-connects to the last connected device.
38 Some of consumer products can switch between devices, for example Logitech K480.
39 http://www.logitech.com/en-us/product/multi-device-keyboard-k480?crid=26
40- HHKB JP requires case modification for BT switch and LEDs.
41 without switch power controlled by MCU? Probably using 3.3V regulator enable pin power of RN-42 can be controlled.
42
43NOTE:
44- LIPO BATTERY IS VERY DANGEROUS, TAKE EXTRA CARE OF YOUR SAFETY AND PROPERTY.
45- RN-42 version 6.15 is supported.
46- No NKRO over Bluetooth
47- Check you country's wiress regulation and certification of RN-42.
48
49Bugs:
50
51Todos:
52
53
54Lipo Battery
55------------
56You can use 3.7V Lithium Ion battery with JST PH 2pin connector and protection circuit.
57Battery space inside HHKB is around 54mm x 50mm and its height is 7mm.
58
59Sparkfun 850mAh
60https://www.sparkfun.com/products/341
61Sparkfun 1000mAh
62https://www.sparkfun.com/products/339
63
64Sparkfun 2000mAh battery won't fit due to its size.
65
66Learn about Lipo battery:
67https://learn.adafruit.com/li-ion-and-lipoly-batteries
68
69
70
71
72
73LED Status
74----------
75Configuring 10 times per sec
76Startup/configuration timer 2 times per sec
77Discoverable/Inquiring/Idle once per sec
78Connected solid on
79
80
81RN-42 Magic Command
82--------------------
83Magic key combination is 'LShift+RShift' by default in case of HHKB.
84
85Here is help.
86
87 ----- Bluetooth RN-42 Help -----
88 i: RN-42 info
89 b: battery voltage
90 Del: enter/exit RN-42 config mode
91 Slck: RN-42 initialize
92 p: pairing
93 u: toggle Force USB mode
94
95 RN-42 info: displays information of the module on console.
96 battery voltage: displays current voltage of battery and uptime.
97 RN-42 initialize: does factory reset and configures RN-42
98 pairing: enters Pairing mode.
99 toggle Force USB mode: switch between USB and Bluetooth
100
101
102RN-42 Config mode
103-----------------
104You can tune/operate RN-42 yourself with config(command) mode.
105
1061. hook up USB cable
1072. run `hid_listen` command in console
1083. turn on Bluetooth switch
1094. press LShift+RShift+Delete(Fn+~) you will see output like followings:
110
111 Entering config mode ...
112 CMD
113 v
114 Ver 6.15 04/26/2013
115 (c) Roving Networks
116
1175. do config with RN-42 commands. See documentations of RN-42.
1186. to exit also press LShift+RShift+Delete(Fn+~)
119
120 Exiting config mode ...
121 ---
122 END
123
124
125RN-42 Initial Configuration
126---------------------------
127RN-42 is configured as SPP device at factory reset, you need to configure it as HID device. This is needed just once first time.
128
1291. hook up USB cable
1302. run `hid_listen` command in console
1313. turn on Bluetooth switch
1324. press LShift+RShift+ScrLk(Fn+O) you will see output like followings:
133
134 Entering config mode ...
135 CMD
136 Ver 6.15 04/26/2013
137 (c) Roving Networks
138 ECHO ON
139 SF,1
140 AOK
141 S-,TmkBT
142 AOK
143 SS,Keyboard/Mouse
144 AOK
145 SM,4
146 AOK
147 SW,8000
148 AOK
149 S~,6
150 AOK
151 SH,003C
152 AOK
153 SY,FFF4
154 AOK
155 R,1
156 Reboot!
157 Exiting config mode ...
158
1595. output of command 'X' after cofiguration
160
161 Ver 6.15 04/26/2013
162 (c) Roving Networks
163 ***Settings***
164 BTA=00066667BBE9
165 BTName=TmkBT-BBE9
166 Baudrt(SW4)=115K
167 Mode =DTR
168 Authen=1
169 PinCod=1234
170 Bonded=0
171 Rem=NONE SET
172 ***ADVANCED Settings***
173 SrvName= Keyboard/Mouse
174 SrvClass=0000
175 DevClass=1F00
176 InqWindw=0100
177 PagWindw=0100
178 CfgTimer=255
179 StatuStr=NULL
180 HidFlags=3c
181 DTRtimer=8
182 KeySwapr=0
183 ***OTHER Settings***
184 Profile= HID
185 CfgChar= $
186 SniffEna=8000
187 LowPower=0
188 TX Power=fff4
189 IOPorts= 0
190 IOValues=0
191 Sleeptmr=0
192 DebugMod=0
193 RoleSwch=0
194
195
196Switch to USB mode
197------------------
198You can switch between USB and Bluetooth with pressing 'LShift+RShift+u'.
199
200
201Pairing mode
202------------
203This disconnects current connect and enter pairing mode.
204
205
206
207
208For deveropment
209===============
210
211RN-42 Serial Connection
212-----------------------
213UART: 115200bps, 8bit, 1-stopbit, non-parity, no flow control
214SSP: 115200bps, 8bit, 1-stopbit, non-parity, no flow control(via Bluetooth)
215
216To enter command mode disconnect the module from host and type '$$$'.(you will see 'CMD') and type '+' to get local echo. To exit type '---'(you will see 'END').
217
218
219RN-42 Commands
220--------------
221S-,tmkBT // Device name
222SS,keyboard/mouse // service name
223SM,4 // Auto Connect DTR mode
224SW,8010 // Sniff enable 0x10*0.625ms=10ms; 50ms is laggish and not much power save
225S~,6 // HID profile
226S~,0 // SPP profile
227SH,003C // HID register
228SY,0004 // Transmit power
229SC,0000 // COD: 000005C0 (see HID spec/Bluegiga doc)
230SD,05C0 // bit 12-8 7 6 5-0
231 // 00101 1 1 0
232 // peripheral pointing keybaord joystick, gamepad, ...
233SM,6 // Pairing mode: auto connect
234SM,4 // Master mode: Connection can be controled with GPIO6
235SF,1 // Factroy reset
236R,1 // reboot
237SR,Z // removes all remote addresses for reconnecting.
238 // can be used to connect another host
239SR,I // registers last inquiry address
240
241
242Operation Modes
243---------------
244SM,3 Auto Connect Master mode
245SM,4 Auto Connect DTR Mode uses GPIO6 to make and break connection(Mode =DTR)
246 confirm: auto connect works and control connection with GPIO6
247SM,5 Auto Connect ANY Mode (Mode =ANY)
248 each time GPIO is set, make inquiry and connect to the first found device
249SM,6 automatically reconnect(Mode =Pair)
250 confirm: auto connect works well but difficult to enter command mode.
251
252
253HID flag register
254-----------------
255SH,0200
256GH
257
25810 0000 0000(0200) default
25900 0011 1000(0038) Combo
260|| | | |\_\____ number of paired devices to which the module can reconnect
261|| | | \_______ send out reports over UART (0xFF <len> <data>)
262|| \__\_________ descriptor type
263|\______________ toggle virtual keyboard on iOS when first connected
264\_______________ Force HID mode if GPIO11 is high on power-up
265
266 Descriptor type:
267 0000: keybaord
268 0001: Game Pad
269 0010: Mouse
270 0011: Combo
271 0100: Joystick
272 1xxx: reserved
273
274
275Out report - Indicator
276----------------------
2770xFE 0x02 0x01 <LED_state>
278
279
280Apple iOS
281---------
282Keyboard can be used with iPhone, but mouse cannot.
283
284
285Android
286-------
2873.7.1.5 Note: To connect with Android phone the modules must wake up 11ms every 2.5seconds.
288
289
290Power Management
291----------------
292Inquiry and Page window Idle or Active (3.1.1)
293 Downside: delay in discovery or connection time
294 SI, // set inquiry scan window(discovery) on/off duty?
295 SJ, // set page scan window(connection)
296 This reduces averaege power >20mA to 5mA(3mA in Sniff mode)
297
298Sniff mode Transmit
299 Sniff mode is disabled by default and radio is active continuously when connected.(25-30mA)
300 In Sniff mode the radio wakes up intermittently and sleeps in very low power mode.(2mA)
301 SW,<val> // set interval timer(*0.625ms) 0000-7FFF
302
303Deep sleep Idle (3.1.2)
304 In this mode the module shuts down completly and only draws about 300uA. To enable this set the most signifant bit(0x8000) of Sniff interaval timer.
305 SW,8320 // deep sleep enable(interval=0x320*0.625=500ms)
306 In normal sleep the firmware is still running in idle mode, and wakes up about 20 times per second to check ports, update LEDs, etc. During deep sleep, the firmware actually stops runnig some tasks and the LEDs only update about once per second.
307 To wake from deep sleep there are three ways: (in worst case wake up takes 5ms)
308 *send a charactor to the UART(first charactor will be lost)
309 *toggle CTS low to high and wait 5ms
310 *wake automatically every slot time(<val>*0.625ms)
311 Once the radio is awake it stay active for exactly 1 second of inactivity and then sleeps again.
312 Downside: latency and data loss
313
314Disable Output driver Idle or Active (3.1.3)
315 S%,1000 // set all GPIO pins(0-11) to inputs.
316
317Lower Transmit Power Idle or Active (3.1.4)
318 SY,<hex> // transmit power setting(takes effect after a power cycle and reboot)
319 Downside: reducing effective range
320
321
322Optimizig for Latency
323---------------------
324By default the firmware is optimized for throughput.
325SQ,16 // set latency bit
326SQ,0 // unset latency bit
327
328
329Configuration timer settings
330----------------------------
331Remote configuration is used for the module to be configured with various commands over Bluetooth(SPP profile only?).
332
333The module has remote configuration timer to allow remote configuration over Bluetooth after power up in Slave mode. In Master modes the remote configuration timer is set to 0(no remote configuration). (In Trigger Master mode the timer is used as an idle timer to break the connection after time expires with no charactors receive.)
334 ST,0 // no remote, no local when connected
335 ST,<1-252> // local and remote with timeout in seconds from power up
336 ST,253 // local only without timeout
337 ST,254 // remote only without timeout
338 ST,255 // local and remote without timeout
339
340
341Commands
342--------
343S7, 7bit mode
344SA, Authenticaiton
345SB, Send break
346SC, Service class
347SD, Device class
348SM,<val> Operation mode
349SP,<string> Pin code(alpahnumeric)
350SQ,<mask> Special configuration(GPIO, discovery mode, low latency, reboot, UART)
351SR,<hex> Store remote address
352SR,Z Erase all address
353SS,<string> Set service name(1-20)**
354ST,<val> Remote configuration timer(Master:0, Slave:0-255, Triger:as idle timer)
355SU,<val> UART baud rate
356SW,<val> low-power sniff mode** deep sleep and wake up every 625us * <val>
357SX,<0|1> bonding enable only acceps device that matches the stored address
358SY,<hex> power setting**
359SZ,<val> non-standard raw baud rate <val>=baud*0.004096
360S~,<val> Profile 0:SPP, 5:APL, 6:HID
361S-,<string> Device name -15 alphanumeric charactors
362S?,<0|1> role switch enable
363S$,<char> command mode char
364$|,<hex> low-power connect mode deep sleep/active(discoverable and connectable) cycle
365D display basic setting
366E display extended setting
367GB display the device's Bluetooth address
368GF display Bluetooth address of connected device
369GK show connection status
370GR show remote address for reconnecting
371G& show GPIO pin
372G<char> show stored setting
373+ toggle local echo on/off
374& show GPIO 3,4,6,7(DIP switch)
375C connect to stored remote address
376C,<address> connect last address
377CFI connect and go into fast data mode
378CFR connect and go into fast data mode
379CT,<address>,<val> connect to the address and disconnect after val?
380F,1 fast data mod:
381H display help
382I,<time>,<cod> inquiry scan with <cod>
383IN,<time>,<cod> inquiry scan with <cod>, return without BT name
384IR inquiry scan with 0055AA
385IS inquiry scan with 001F00
386J hide pin code
387K, kill disconnects current connection
388L link quality
389M show modem signlal status
390O display other settings
391P,<char> pass through?
392Q quiet mode make the module not discoverable
393Q,0 discoverable and connectable
394Q,1 not discoverable and not connectable
395Q,2 not discoverable and connectable
396Q,? display current quiet mode
397R,1 reboot
398T,<0|1> pass received data while in command mode
399U,<baud>,<parity> change UART setting tentatively
400V display firmware version
401W wake from quiet mode enable discovery and connection
402Z deep sleep mode(<2mA)
403
404
405Reset to Factory Default
406------------------------
407SF,1
408R,1
diff --git a/keyboards/hhkb/rn42/battery.c b/keyboards/hhkb/rn42/battery.c
new file mode 100644
index 000000000..c0c82bb80
--- /dev/null
+++ b/keyboards/hhkb/rn42/battery.c
@@ -0,0 +1,130 @@
1#include <avr/io.h>
2#include <util/delay.h>
3#include "battery.h"
4
5
6/*
7 * Battery
8 */
9void battery_init(void)
10{
11 // blink
12 battery_led(LED_ON); _delay_ms(100);
13 battery_led(LED_OFF); _delay_ms(100);
14 battery_led(LED_ON); _delay_ms(100);
15 battery_led(LED_OFF); _delay_ms(100);
16 // LED indicates charger status
17 battery_led(LED_CHARGER);
18
19 // ADC setting for voltage monitor
20 // Ref:2.56V band-gap, Input:ADC0(PF0), Prescale:128(16MHz/128=125KHz)
21 ADMUX = (1<<REFS1) | (1<<REFS0);
22 ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
23 // digital input buffer disable(24.9.5)
24 DIDR0 = (1<<ADC0D) | (1<<ADC4D) | (1<<ADC7D);
25 DIDR1 = (1<<AIN0D);
26 DIDR2 = (1<<ADC8D) | (1<<ADC9D) | (1<<ADC11D) | (1<<ADC12D) | (1<<ADC13D);
27
28 // ADC disable voltate divider(PF4)
29 DDRF |= (1<<4);
30 PORTF &= ~(1<<4);
31}
32
33// Indicator for battery
34void battery_led(battery_led_t val)
35{
36 if (val == LED_TOGGLE) {
37 // Toggle LED
38 DDRF |= (1<<5);
39 PINF |= (1<<5);
40 } else if (val == LED_ON) {
41 // On overriding charger status
42 DDRF |= (1<<5);
43 PORTF &= ~(1<<5);
44 } else if (val == LED_OFF) {
45 // Off overriding charger status
46 DDRF |= (1<<5);
47 PORTF |= (1<<5);
48 } else {
49 // Display charger status
50 DDRF &= ~(1<<5);
51 PORTF &= ~(1<<5);
52 }
53}
54
55bool battery_charging(void)
56{
57 if (!(USBSTA&(1<<VBUS))) return false;
58
59 // Charger Status:
60 // MCP73831 MCP73832 LTC4054 Status
61 // Hi-Z Hi-Z Hi-Z Shutdown/No Battery
62 // Low Low Low Charging
63 // Hi Hi-Z Hi-Z Charged
64
65 // preserve last register status
66 uint8_t ddrf_prev = DDRF;
67 uint8_t portf_prev = PORTF;
68
69 // Input with pullup
70 DDRF &= ~(1<<5);
71 PORTF |= (1<<5);
72 _delay_ms(1);
73 bool charging = PINF&(1<<5) ? false : true;
74
75 // restore last register status
76 DDRF = (DDRF&~(1<<5)) | (ddrf_prev&(1<<5));
77 PORTF = (PORTF&~(1<<5)) | (portf_prev&(1<<5));
78
79 // TODO: With MCP73831 this can not get stable status when charging.
80 // LED is powered from PSEL line(USB or Lipo)
81 // due to weak low output of STAT pin?
82 // due to pull-up'd via resitor and LED?
83 return charging;
84}
85
86// Returns voltage in mV
87uint16_t battery_voltage(void)
88{
89 // ADC disable voltate divider(PF4)
90 DDRF |= (1<<4);
91 PORTF |= (1<<4);
92
93 volatile uint16_t bat;
94 ADCSRA |= (1<<ADEN);
95 _delay_ms(1); // wait for charging S/H capacitance
96
97 ADCSRA |= (1<<ADSC);
98 while (ADCSRA & (1<<ADSC)) ;
99 bat = ADC;
100
101 ADCSRA &= ~(1<<ADEN);
102
103 // ADC disable voltate divider(PF4)
104 DDRF |= (1<<4);
105 PORTF &= ~(1<<4);
106
107 return (bat - BATTERY_ADC_OFFSET) * BATTERY_ADC_RESOLUTION;
108}
109
110static bool low_voltage(void) {
111 static bool low = false;
112 uint16_t v = battery_voltage();
113 if (v < BATTERY_VOLTAGE_LOW_LIMIT) {
114 low = true;
115 } else if (v > BATTERY_VOLTAGE_LOW_RECOVERY) {
116 low = false;
117 }
118 return low;
119}
120
121battery_status_t battery_status(void)
122{
123 if (USBSTA&(1<<VBUS)) {
124 /* powered */
125 return battery_charging() ? CHARGING : FULL_CHARGED;
126 } else {
127 /* not powered */
128 return low_voltage() ? LOW_VOLTAGE : DISCHARGING;
129 }
130}
diff --git a/keyboards/hhkb/rn42/battery.h b/keyboards/hhkb/rn42/battery.h
new file mode 100644
index 000000000..180d4dcfa
--- /dev/null
+++ b/keyboards/hhkb/rn42/battery.h
@@ -0,0 +1,35 @@
1#ifndef POWER_H
2#define POWER_H
3
4#include <stdint.h>
5#include <stdbool.h>
6
7typedef enum {
8 FULL_CHARGED,
9 CHARGING,
10 DISCHARGING,
11 LOW_VOLTAGE,
12 UNKNOWN,
13} battery_status_t;
14
15typedef enum {
16 LED_CHARGER = 0,
17 LED_ON,
18 LED_OFF,
19 LED_TOGGLE,
20} battery_led_t;
21
22/* Battery API */
23void battery_init(void);
24void battery_led(battery_led_t val);
25bool battery_charging(void);
26uint16_t battery_voltage(void);
27battery_status_t battery_status(void);
28
29#define BATTERY_VOLTAGE_LOW_LIMIT 3500
30#define BATTERY_VOLTAGE_LOW_RECOVERY 3700
31// ADC offset:16, resolution:5mV
32#define BATTERY_ADC_OFFSET 16
33#define BATTERY_ADC_RESOLUTION 5
34
35#endif
diff --git a/keyboards/hhkb/rn42/main.c b/keyboards/hhkb/rn42/main.c
new file mode 100644
index 000000000..8ec9220a2
--- /dev/null
+++ b/keyboards/hhkb/rn42/main.c
@@ -0,0 +1,106 @@
1#include <avr/io.h>
2#include <avr/power.h>
3#include <avr/wdt.h>
4#include "lufa.h"
5#include "print.h"
6#include "sendchar.h"
7#include "rn42.h"
8#include "rn42_task.h"
9#include "serial.h"
10#include "keyboard.h"
11#include "keycode.h"
12#include "action.h"
13#include "action_util.h"
14#include "wait.h"
15#include "suart.h"
16#include "suspend.h"
17#include "matrix.h"
18
19static int8_t sendchar_func(uint8_t c)
20{
21 xmit(c); // SUART
22 sendchar(c); // LUFA
23 return 0;
24}
25
26static void SetupHardware(void)
27{
28 /* Disable watchdog if enabled by bootloader/fuses */
29 MCUSR &= ~(1 << WDRF);
30 wdt_disable();
31
32 /* Disable clock division */
33 clock_prescale_set(clock_div_1);
34
35 // Leonardo needs. Without this USB device is not recognized.
36 USB_Disable();
37
38 USB_Init();
39
40 // for Console_Task
41 USB_Device_EnableSOFEvents();
42 print_set_sendchar(sendchar_func);
43
44 // SUART PD0:output, PD1:input
45 DDRD |= (1<<0);
46 PORTD |= (1<<0);
47 DDRD &= ~(1<<1);
48 PORTD |= (1<<1);
49}
50
51int main(void) __attribute__ ((weak));
52int main(void)
53{
54 SetupHardware();
55 sei();
56
57 /* wait for USB startup to get ready for debug output */
58 uint8_t timeout = 255; // timeout when USB is not available(Bluetooth)
59 while (timeout-- && USB_DeviceState != DEVICE_STATE_Configured) {
60 wait_ms(4);
61#if defined(INTERRUPT_CONTROL_ENDPOINT)
62 ;
63#else
64 USB_USBTask();
65#endif
66 }
67 print("\nUSB init\n");
68
69 rn42_init();
70 rn42_task_init();
71 print("RN-42 init\n");
72
73 /* init modules */
74 keyboard_init();
75
76#ifdef SLEEP_LED_ENABLE
77 sleep_led_init();
78#endif
79
80 print("Keyboard start\n");
81 while (1) {
82 while (rn42_rts() && // RN42 is off
83 USB_DeviceState == DEVICE_STATE_Suspended) {
84 print("[s]");
85 matrix_power_down();
86 suspend_power_down();
87 suspend_power_down();
88 suspend_power_down();
89 suspend_power_down();
90 suspend_power_down();
91 suspend_power_down();
92 suspend_power_down();
93 if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
94 USB_Device_SendRemoteWakeup();
95 }
96 }
97
98 keyboard_task();
99
100#if !defined(INTERRUPT_CONTROL_ENDPOINT)
101 USB_USBTask();
102#endif
103
104 rn42_task();
105 }
106} \ No newline at end of file
diff --git a/keyboards/hhkb/rn42/rn42.c b/keyboards/hhkb/rn42/rn42.c
new file mode 100644
index 000000000..859e40149
--- /dev/null
+++ b/keyboards/hhkb/rn42/rn42.c
@@ -0,0 +1,265 @@
1#include <avr/io.h>
2#include "host.h"
3#include "host_driver.h"
4#include "serial.h"
5#include "rn42.h"
6#include "print.h"
7#include "timer.h"
8#include "wait.h"
9
10
11/* Host driver */
12static uint8_t keyboard_leds(void);
13static void send_keyboard(report_keyboard_t *report);
14static void send_mouse(report_mouse_t *report);
15static void send_system(uint16_t data);
16static void send_consumer(uint16_t data);
17
18host_driver_t rn42_driver = {
19 keyboard_leds,
20 send_keyboard,
21 send_mouse,
22 send_system,
23 send_consumer
24};
25
26
27void rn42_init(void)
28{
29 // JTAG disable for PORT F. write JTD bit twice within four cycles.
30 MCUCR |= (1<<JTD);
31 MCUCR |= (1<<JTD);
32
33 // PF7: BT connection control(high: connect, low: disconnect)
34 rn42_autoconnect();
35
36 // PF6: linked(input without pull-up)
37 DDRF &= ~(1<<6);
38 PORTF |= (1<<6);
39
40 // PF1: RTS(low: allowed to send, high: not allowed)
41 DDRF &= ~(1<<1);
42 PORTF &= ~(1<<1);
43
44 // PD5: CTS(low: allow to send, high:not allow)
45 DDRD |= (1<<5);
46 PORTD &= ~(1<<5);
47
48 serial_init();
49}
50
51int16_t rn42_getc(void)
52{
53 return serial_recv2();
54}
55
56const char *rn42_gets(uint16_t timeout)
57{
58 static char s[24];
59 uint16_t t = timer_read();
60 uint8_t i = 0;
61 int16_t c;
62 while (i < 23 && timer_elapsed(t) < timeout) {
63 if ((c = rn42_getc()) != -1) {
64 if ((char)c == '\r') continue;
65 if ((char)c == '\n') break;
66 s[i++] = c;
67 }
68 }
69 s[i] = '\0';
70 return s;
71}
72
73void rn42_putc(uint8_t c)
74{
75 serial_send(c);
76}
77
78void rn42_puts(char *s)
79{
80 while (*s)
81 serial_send(*s++);
82}
83
84bool rn42_autoconnecting(void)
85{
86 // GPIO6 for control connection(high: auto connect, low: disconnect)
87 // Note that this needs config: SM,4(Auto-Connect DTR Mode)
88 return (PORTF & (1<<7) ? true : false);
89}
90
91void rn42_autoconnect(void)
92{
93 // hi to auto connect
94 DDRF |= (1<<7);
95 PORTF |= (1<<7);
96}
97
98void rn42_disconnect(void)
99{
100 // low to disconnect
101 DDRF |= (1<<7);
102 PORTF &= ~(1<<7);
103}
104
105bool rn42_rts(void)
106{
107 // low when RN-42 is powered and ready to receive
108 return PINF&(1<<1);
109}
110
111void rn42_cts_hi(void)
112{
113 // not allow to send
114 PORTD |= (1<<5);
115}
116
117void rn42_cts_lo(void)
118{
119 // allow to send
120 PORTD &= ~(1<<5);
121}
122
123bool rn42_linked(void)
124{
125 // RN-42 GPIO2
126 // Hi-Z: Not powered
127 // High: Linked
128 // Low: Connecting
129 return PINF&(1<<6);
130}
131
132
133static uint8_t leds = 0;
134static uint8_t keyboard_leds(void) { return leds; }
135void rn42_set_leds(uint8_t l) { leds = l; }
136
137
138void rn42_send_str(const char *str)
139{
140 uint8_t c;
141 while ((c = pgm_read_byte(str++)))
142 rn42_putc(c);
143}
144
145const char *rn42_send_command(const char *cmd)
146{
147 static const char *s;
148 rn42_send_str(cmd);
149 wait_ms(500);
150 s = rn42_gets(100);
151 xprintf("%s\r\n", s);
152 rn42_print_response();
153 return s;
154}
155
156void rn42_print_response(void)
157{
158 int16_t c;
159 while ((c = rn42_getc()) != -1) {
160 xprintf("%c", c);
161 }
162}
163
164
165static void send_keyboard(report_keyboard_t *report)
166{
167 // wake from deep sleep
168/*
169 PORTD |= (1<<5); // high
170 wait_ms(5);
171 PORTD &= ~(1<<5); // low
172*/
173
174 serial_send(0xFD); // Raw report mode
175 serial_send(9); // length
176 serial_send(1); // descriptor type
177 serial_send(report->mods);
178 serial_send(0x00);
179 serial_send(report->keys[0]);
180 serial_send(report->keys[1]);
181 serial_send(report->keys[2]);
182 serial_send(report->keys[3]);
183 serial_send(report->keys[4]);
184 serial_send(report->keys[5]);
185}
186
187static void send_mouse(report_mouse_t *report)
188{
189 // wake from deep sleep
190/*
191 PORTD |= (1<<5); // high
192 wait_ms(5);
193 PORTD &= ~(1<<5); // low
194*/
195
196 serial_send(0xFD); // Raw report mode
197 serial_send(5); // length
198 serial_send(2); // descriptor type
199 serial_send(report->buttons);
200 serial_send(report->x);
201 serial_send(report->y);
202 serial_send(report->v);
203}
204
205static void send_system(uint16_t data)
206{
207 // Table 5-6 of RN-BT-DATA-UB
208 // 81,82,83 scan codes can be used?
209}
210
211
212static uint16_t usage2bits(uint16_t usage)
213{
214 switch (usage) {
215 case AC_HOME: return 0x01;
216 case AL_EMAIL: return 0x02;
217 case AC_SEARCH: return 0x04;
218 //case AL_KBD_LAYOUT: return 0x08; // Apple virtual keybaord toggle
219 case AUDIO_VOL_UP: return 0x10;
220 case AUDIO_VOL_DOWN: return 0x20;
221 case AUDIO_MUTE: return 0x40;
222 case TRANSPORT_PLAY_PAUSE: return 0x80;
223 case TRANSPORT_NEXT_TRACK: return 0x100;
224 case TRANSPORT_PREV_TRACK: return 0x200;
225 case TRANSPORT_STOP: return 0x400;
226 case TRANSPORT_STOP_EJECT: return 0x800;
227 case TRANSPORT_FAST_FORWARD: return 0x1000;
228 case TRANSPORT_REWIND: return 0x2000;
229 //case return 0x4000; // Stop/eject
230 //case return 0x8000; // Internet browser
231 };
232 return 0;
233}
234
235static void send_consumer(uint16_t data)
236{
237 uint16_t bits = usage2bits(data);
238 serial_send(0xFD); // Raw report mode
239 serial_send(3); // length
240 serial_send(3); // descriptor type
241 serial_send(bits&0xFF);
242 serial_send((bits>>8)&0xFF);
243}
244
245
246/* Null driver for config_mode */
247static uint8_t config_keyboard_leds(void);
248static void config_send_keyboard(report_keyboard_t *report);
249static void config_send_mouse(report_mouse_t *report);
250static void config_send_system(uint16_t data);
251static void config_send_consumer(uint16_t data);
252
253host_driver_t rn42_config_driver = {
254 config_keyboard_leds,
255 config_send_keyboard,
256 config_send_mouse,
257 config_send_system,
258 config_send_consumer
259};
260
261static uint8_t config_keyboard_leds(void) { return leds; }
262static void config_send_keyboard(report_keyboard_t *report) {}
263static void config_send_mouse(report_mouse_t *report) {}
264static void config_send_system(uint16_t data) {}
265static void config_send_consumer(uint16_t data) {}
diff --git a/keyboards/hhkb/rn42/rn42.h b/keyboards/hhkb/rn42/rn42.h
new file mode 100644
index 000000000..dee214cc8
--- /dev/null
+++ b/keyboards/hhkb/rn42/rn42.h
@@ -0,0 +1,30 @@
1#ifndef RN42_H
2#define RN42_H
3
4#include <stdbool.h>
5#include "host_driver.h"
6
7host_driver_t rn42_driver;
8host_driver_t rn42_config_driver;
9
10void rn42_init(void);
11int16_t rn42_getc(void);
12const char *rn42_gets(uint16_t timeout);
13void rn42_putc(uint8_t c);
14void rn42_puts(char *s);
15bool rn42_autoconnecting(void);
16void rn42_autoconnect(void);
17void rn42_disconnect(void);
18bool rn42_rts(void);
19void rn42_cts_hi(void);
20void rn42_cts_lo(void);
21bool rn42_linked(void);
22void rn42_set_leds(uint8_t l);
23
24const char *rn42_send_command(const char *cmd);
25void rn42_send_str(const char *str);
26void rn42_print_response(void);
27#define SEND_STR(str) rn42_send_str(PSTR(str))
28#define SEND_COMMAND(cmd) rn42_send_command(PSTR(cmd))
29
30#endif
diff --git a/keyboards/hhkb/rn42/rn42_task.c b/keyboards/hhkb/rn42/rn42_task.c
new file mode 100644
index 000000000..88ae88c15
--- /dev/null
+++ b/keyboards/hhkb/rn42/rn42_task.c
@@ -0,0 +1,467 @@
1#include <stdint.h>
2#include <string.h>
3#include <avr/pgmspace.h>
4#include <avr/eeprom.h>
5#include "keycode.h"
6#include "serial.h"
7#include "host.h"
8#include "action.h"
9#include "action_util.h"
10#include "lufa.h"
11#include "rn42_task.h"
12#include "print.h"
13#include "debug.h"
14#include "timer.h"
15#include "wait.h"
16#include "command.h"
17#include "battery.h"
18#include "keycode_config.h"
19
20extern keymap_config_t keymap_config;
21
22static bool config_mode = false;
23static bool force_usb = false;
24
25static void status_led(bool on)
26{
27 if (on) {
28 DDRE |= (1<<6);
29 PORTE &= ~(1<<6);
30 } else {
31 DDRE |= (1<<6);
32 PORTE |= (1<<6);
33 }
34}
35
36void rn42_task_init(void)
37{
38 battery_init();
39#ifdef NKRO_ENABLE
40 rn42_nkro_last = keymap_config.nkro;
41#endif
42}
43
44void rn42_task(void)
45{
46 int16_t c;
47 // Raw mode: interpret output report of LED state
48 while ((c = rn42_getc()) != -1) {
49 // LED Out report: 0xFE, 0x02, 0x01, <leds>
50 // To get the report over UART set bit3 with SH, command.
51 static enum {LED_INIT, LED_FE, LED_02, LED_01} state = LED_INIT;
52 switch (state) {
53 case LED_INIT:
54 if (c == 0xFE) state = LED_FE;
55 else {
56 if (0x0 <= c && c <= 0x7f) xprintf("%c", c);
57 else xprintf(" %02X", c);
58 }
59 break;
60 case LED_FE:
61 if (c == 0x02) state = LED_02;
62 else state = LED_INIT;
63 break;
64 case LED_02:
65 if (c == 0x01) state = LED_01;
66 else state = LED_INIT;
67 break;
68 case LED_01:
69 dprintf("LED status: %02X\n", c);
70 rn42_set_leds(c);
71 state = LED_INIT;
72 break;
73 default:
74 state = LED_INIT;
75 }
76 }
77
78 /* Switch between USB and Bluetooth */
79 if (!config_mode) { // not switch while config mode
80 if (!force_usb && !rn42_rts()) {
81 if (host_get_driver() != &rn42_driver) {
82 clear_keyboard();
83#ifdef NKRO_ENABLE
84 rn42_nkro_last = keymap_config.nkro;
85 keymap_config.nkro = false;
86#endif
87 host_set_driver(&rn42_driver);
88 }
89 } else {
90 if (host_get_driver() != &lufa_driver) {
91 clear_keyboard();
92#ifdef NKRO_ENABLE
93 keymap_config.nkro = rn42_nkro_last;
94#endif
95 host_set_driver(&lufa_driver);
96 }
97 }
98 }
99
100
101 static uint16_t prev_timer = 0;
102 uint16_t e = timer_elapsed(prev_timer);
103 if (e > 1000) {
104 /* every second */
105 prev_timer += e/1000*1000;
106
107 /* Low voltage alert */
108 uint8_t bs = battery_status();
109 if (bs == LOW_VOLTAGE) {
110 battery_led(LED_ON);
111 } else {
112 battery_led(LED_CHARGER);
113 }
114
115 /* every minute */
116 uint32_t t = timer_read32()/1000;
117 if (t%60 == 0) {
118 uint16_t v = battery_voltage();
119 uint8_t h = t/3600;
120 uint8_t m = t%3600/60;
121 uint8_t s = t%60;
122 dprintf("%02u:%02u:%02u\t%umV\n", h, m, s, v);
123 /* TODO: xprintf doesn't work for this.
124 xprintf("%02u:%02u:%02u\t%umV\n", (t/3600), (t%3600/60), (t%60), v);
125 */
126 }
127 }
128
129
130 /* Connection monitor */
131 if (!rn42_rts() && rn42_linked()) {
132 status_led(true);
133 } else {
134 status_led(false);
135 }
136}
137
138
139
140/******************************************************************************
141 * Command
142 ******************************************************************************/
143static host_driver_t *prev_driver = &rn42_driver;
144
145static void enter_command_mode(void)
146{
147 prev_driver = host_get_driver();
148 clear_keyboard();
149 host_set_driver(&rn42_config_driver); // null driver; not to send a key to host
150 rn42_disconnect();
151 while (rn42_linked()) ;
152
153 print("Entering config mode ...\n");
154 wait_ms(1100); // need 1 sec
155 SEND_COMMAND("$$$");
156 wait_ms(600); // need 1 sec
157 rn42_print_response();
158 const char *s = SEND_COMMAND("v\r\n");
159 if (strncmp("v", s, 1) != 0) SEND_COMMAND("+\r\n"); // local echo on
160}
161
162static void exit_command_mode(void)
163{
164 print("Exiting config mode ...\n");
165 SEND_COMMAND("---\r\n"); // exit
166
167 rn42_autoconnect();
168 clear_keyboard();
169 host_set_driver(prev_driver);
170}
171
172static void init_rn42(void)
173{
174 // RN-42 configure
175 if (!config_mode) enter_command_mode();
176 SEND_COMMAND("SF,1\r\n"); // factory defaults
177 SEND_COMMAND("S-,TmkBT\r\n");
178 SEND_COMMAND("SS,Keyboard/Mouse\r\n");
179 SEND_COMMAND("SM,4\r\n"); // auto connect(DTR)
180 SEND_COMMAND("SW,8000\r\n"); // Sniff disable
181 SEND_COMMAND("S~,6\r\n"); // HID profile
182 SEND_COMMAND("SH,003C\r\n"); // combo device, out-report, 4-reconnect
183 SEND_COMMAND("SY,FFF4\r\n"); // transmit power -12
184 SEND_COMMAND("R,1\r\n");
185 if (!config_mode) exit_command_mode();
186}
187
188#if 0
189// Switching connections
190// NOTE: Remote Address doesn't work in the way manual says.
191// EEPROM address for link store
192#define RN42_LINK0 (uint8_t *)128
193#define RN42_LINK1 (uint8_t *)140
194#define RN42_LINK2 (uint8_t *)152
195#define RN42_LINK3 (uint8_t *)164
196static void store_link(uint8_t *eeaddr)
197{
198 enter_command_mode();
199 SEND_STR("GR\r\n"); // remote address
200 const char *s = rn42_gets(500);
201 if (strcmp("GR", s) == 0) s = rn42_gets(500); // ignore local echo
202 xprintf("%s(%d)\r\n", s, strlen(s));
203 if (strlen(s) == 12) {
204 for (int i = 0; i < 12; i++) {
205 eeprom_write_byte(eeaddr+i, *(s+i));
206 dprintf("%c ", *(s+i));
207 }
208 dprint("\r\n");
209 }
210 exit_command_mode();
211}
212
213static void restore_link(const uint8_t *eeaddr)
214{
215 enter_command_mode();
216 SEND_COMMAND("SR,Z\r\n"); // remove remote address
217 SEND_STR("SR,"); // set remote address from EEPROM
218 for (int i = 0; i < 12; i++) {
219 uint8_t c = eeprom_read_byte(eeaddr+i);
220 rn42_putc(c);
221 dprintf("%c ", c);
222 }
223 dprintf("\r\n");
224 SEND_COMMAND("\r\n");
225 SEND_COMMAND("R,1\r\n"); // reboot
226 exit_command_mode();
227}
228
229static const char *get_link(uint8_t * eeaddr)
230{
231 static char s[13];
232 for (int i = 0; i < 12; i++) {
233 uint8_t c = eeprom_read_byte(eeaddr+i);
234 s[i] = c;
235 }
236 s[12] = '\0';
237 return s;
238}
239#endif
240
241static void pairing(void)
242{
243 enter_command_mode();
244 SEND_COMMAND("SR,Z\r\n"); // remove remote address
245 SEND_COMMAND("R,1\r\n"); // reboot
246 exit_command_mode();
247}
248
249bool command_extra(uint8_t code)
250{
251 uint32_t t;
252 uint16_t b;
253 switch (code) {
254 case KC_H:
255 case KC_SLASH: /* ? */
256 print("\n\n----- Bluetooth RN-42 Help -----\n");
257 print("i: RN-42 info\n");
258 print("b: battery voltage\n");
259 print("Del: enter/exit RN-42 config mode\n");
260 print("Slck: RN-42 initialize\n");
261#if 0
262 print("1-4: restore link\n");
263 print("F1-F4: store link\n");
264#endif
265 print("p: pairing\n");
266
267 if (config_mode) {
268 return true;
269 } else {
270 print("u: toggle Force USB mode\n");
271 return false; // to display default command help
272 }
273 case KC_P:
274 pairing();
275 return true;
276#if 0
277 /* Store link address to EEPROM */
278 case KC_F1:
279 store_link(RN42_LINK0);
280 return true;
281 case KC_F2:
282 store_link(RN42_LINK1);
283 return true;
284 case KC_F3:
285 store_link(RN42_LINK2);
286 return true;
287 case KC_F4:
288 store_link(RN42_LINK3);
289 return true;
290 /* Restore link address to EEPROM */
291 case KC_1:
292 restore_link(RN42_LINK0);
293 return true;
294 case KC_2:
295 restore_link(RN42_LINK1);
296 return true;
297 case KC_3:
298 restore_link(RN42_LINK2);
299 return true;
300 case KC_4:
301 restore_link(RN42_LINK3);
302 return true;
303#endif
304 case KC_I:
305 print("\n----- RN-42 info -----\n");
306 xprintf("protocol: %s\n", (host_get_driver() == &rn42_driver) ? "RN-42" : "LUFA");
307 xprintf("force_usb: %X\n", force_usb);
308 xprintf("rn42: %s\n", rn42_rts() ? "OFF" : (rn42_linked() ? "CONN" : "ON"));
309 xprintf("rn42_autoconnecting(): %X\n", rn42_autoconnecting());
310 xprintf("config_mode: %X\n", config_mode);
311 xprintf("USB State: %s\n",
312 (USB_DeviceState == DEVICE_STATE_Unattached) ? "Unattached" :
313 (USB_DeviceState == DEVICE_STATE_Powered) ? "Powered" :
314 (USB_DeviceState == DEVICE_STATE_Default) ? "Default" :
315 (USB_DeviceState == DEVICE_STATE_Addressed) ? "Addressed" :
316 (USB_DeviceState == DEVICE_STATE_Configured) ? "Configured" :
317 (USB_DeviceState == DEVICE_STATE_Suspended) ? "Suspended" : "?");
318 xprintf("battery: ");
319 switch (battery_status()) {
320 case FULL_CHARGED: xprintf("FULL"); break;
321 case CHARGING: xprintf("CHARG"); break;
322 case DISCHARGING: xprintf("DISCHG"); break;
323 case LOW_VOLTAGE: xprintf("LOW"); break;
324 default: xprintf("?"); break;
325 };
326 xprintf("\n");
327 xprintf("RemoteWakeupEnabled: %X\n", USB_Device_RemoteWakeupEnabled);
328 xprintf("VBUS: %X\n", USBSTA&(1<<VBUS));
329 t = timer_read32()/1000;
330 uint8_t d = t/3600/24;
331 uint8_t h = t/3600;
332 uint8_t m = t%3600/60;
333 uint8_t s = t%60;
334 xprintf("uptime: %02u %02u:%02u:%02u\n", d, h, m, s);
335#if 0
336 xprintf("LINK0: %s\r\n", get_link(RN42_LINK0));
337 xprintf("LINK1: %s\r\n", get_link(RN42_LINK1));
338 xprintf("LINK2: %s\r\n", get_link(RN42_LINK2));
339 xprintf("LINK3: %s\r\n", get_link(RN42_LINK3));
340#endif
341 return true;
342 case KC_B:
343 // battery monitor
344 t = timer_read32()/1000;
345 b = battery_voltage();
346 xprintf("BAT: %umV\t", b);
347 xprintf("%02u:", t/3600);
348 xprintf("%02u:", t%3600/60);
349 xprintf("%02u\n", t%60);
350 return true;
351 case KC_U:
352 if (config_mode) return false;
353 if (force_usb) {
354 print("Auto mode\n");
355 force_usb = false;
356 } else {
357 print("USB mode\n");
358 force_usb = true;
359 }
360 return true;
361 case KC_DELETE:
362 /* RN-42 Command mode */
363 if (rn42_autoconnecting()) {
364 enter_command_mode();
365
366 command_state = CONSOLE;
367 config_mode = true;
368 } else {
369 exit_command_mode();
370
371 command_state = ONESHOT;
372 config_mode = false;
373 }
374 return true;
375 case KC_SCROLLLOCK:
376 init_rn42();
377 return true;
378#ifdef NKRO_ENABLE
379 case KC_N:
380 if (host_get_driver() != &lufa_driver) {
381 // ignored unless USB mode
382 return true;
383 }
384 return false;
385#endif
386 default:
387 if (config_mode)
388 return true;
389 else
390 return false; // yield to default command
391 }
392 return true;
393}
394
395/*
396 * RN-42 Command mode
397 * sends charactors to the module
398 */
399static uint8_t code2asc(uint8_t code);
400bool command_console_extra(uint8_t code)
401{
402 rn42_putc(code2asc(code));
403 return true;
404}
405
406// convert keycode into ascii charactor
407static uint8_t code2asc(uint8_t code)
408{
409 bool shifted = (get_mods() & (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT))) ? true : false;
410 switch (code) {
411 case KC_A: return (shifted ? 'A' : 'a');
412 case KC_B: return (shifted ? 'B' : 'b');
413 case KC_C: return (shifted ? 'C' : 'c');
414 case KC_D: return (shifted ? 'D' : 'd');
415 case KC_E: return (shifted ? 'E' : 'e');
416 case KC_F: return (shifted ? 'F' : 'f');
417 case KC_G: return (shifted ? 'G' : 'g');
418 case KC_H: return (shifted ? 'H' : 'h');
419 case KC_I: return (shifted ? 'I' : 'i');
420 case KC_J: return (shifted ? 'J' : 'j');
421 case KC_K: return (shifted ? 'K' : 'k');
422 case KC_L: return (shifted ? 'L' : 'l');
423 case KC_M: return (shifted ? 'M' : 'm');
424 case KC_N: return (shifted ? 'N' : 'n');
425 case KC_O: return (shifted ? 'O' : 'o');
426 case KC_P: return (shifted ? 'P' : 'p');
427 case KC_Q: return (shifted ? 'Q' : 'q');
428 case KC_R: return (shifted ? 'R' : 'r');
429 case KC_S: return (shifted ? 'S' : 's');
430 case KC_T: return (shifted ? 'T' : 't');
431 case KC_U: return (shifted ? 'U' : 'u');
432 case KC_V: return (shifted ? 'V' : 'v');
433 case KC_W: return (shifted ? 'W' : 'w');
434 case KC_X: return (shifted ? 'X' : 'x');
435 case KC_Y: return (shifted ? 'Y' : 'y');
436 case KC_Z: return (shifted ? 'Z' : 'z');
437 case KC_1: return (shifted ? '!' : '1');
438 case KC_2: return (shifted ? '@' : '2');
439 case KC_3: return (shifted ? '#' : '3');
440 case KC_4: return (shifted ? '$' : '4');
441 case KC_5: return (shifted ? '%' : '5');
442 case KC_6: return (shifted ? '^' : '6');
443 case KC_7: return (shifted ? '&' : '7');
444 case KC_8: return (shifted ? '*' : '8');
445 case KC_9: return (shifted ? '(' : '9');
446 case KC_0: return (shifted ? ')' : '0');
447 case KC_ENTER: return '\n';
448 case KC_ESCAPE: return 0x1B;
449 case KC_BSPACE: return '\b';
450 case KC_TAB: return '\t';
451 case KC_SPACE: return ' ';
452 case KC_MINUS: return (shifted ? '_' : '-');
453 case KC_EQUAL: return (shifted ? '+' : '=');
454 case KC_LBRACKET: return (shifted ? '{' : '[');
455 case KC_RBRACKET: return (shifted ? '}' : ']');
456 case KC_BSLASH: return (shifted ? '|' : '\\');
457 case KC_NONUS_HASH: return (shifted ? '|' : '\\');
458 case KC_SCOLON: return (shifted ? ':' : ';');
459 case KC_QUOTE: return (shifted ? '"' : '\'');
460 case KC_GRAVE: return (shifted ? '~' : '`');
461 case KC_COMMA: return (shifted ? '<' : ',');
462 case KC_DOT: return (shifted ? '>' : '.');
463 case KC_SLASH: return (shifted ? '?' : '/');
464 case KC_DELETE: return '\0'; // Delete to disconnect
465 default: return ' ';
466 }
467}
diff --git a/keyboards/hhkb/rn42/rn42_task.h b/keyboards/hhkb/rn42/rn42_task.h
new file mode 100644
index 000000000..ee00669ee
--- /dev/null
+++ b/keyboards/hhkb/rn42/rn42_task.h
@@ -0,0 +1,14 @@
1#ifndef RN42_TASK_H
2#define RN42_TASK_H
3
4#include <stdbool.h>
5#include "rn42.h"
6
7#ifdef NKRO_ENABLE
8bool rn42_nkro_last;
9#endif
10
11void rn42_task_init(void);
12void rn42_task(void);
13
14#endif
diff --git a/keyboards/hhkb/rn42/suart.S b/keyboards/hhkb/rn42/suart.S
new file mode 100644
index 000000000..09c45ce23
--- /dev/null
+++ b/keyboards/hhkb/rn42/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 44 /* Bit delay. (see above table) */
21#define BIDIR 0 /* 0:Separated Tx/Rx, 1:Shared Tx/Rx */
22
23#define OUT_1 sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 1 */
24#define OUT_0 cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 0 */
25#define SKIP_IN_1 sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 1 */
26#define SKIP_IN_0 sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 0 */
27
28
29
30#ifdef SPM_PAGESIZE
31.macro _LPMI reg
32 lpm \reg, Z+
33.endm
34.macro _MOVW dh,dl, sh,sl
35 movw \dl, \sl
36.endm
37#else
38.macro _LPMI reg
39 lpm
40 mov \reg, r0
41 adiw ZL, 1
42.endm
43.macro _MOVW dh,dl, sh,sl
44 mov \dl, \sl
45 mov \dh, \sh
46.endm
47#endif
48
49
50
51;---------------------------------------------------------------------------;
52; Transmit a byte in serial format of N81
53;
54;Prototype: void xmit (uint8_t data);
55;Size: 16 words
56
57.global xmit
58.func xmit
59xmit:
60#if BIDIR
61 ldi r23, BPS-1 ;Pre-idle time for bidirectional data line
625: dec r23 ;
63 brne 5b ;/
64#endif
65 in r0, _SFR_IO_ADDR(SREG) ;Save flags
66
67 com r24 ;C = start bit
68 ldi r25, 10 ;Bit counter
69 cli ;Start critical section
70
711: ldi r23, BPS-1 ;----- Bit transferring loop
722: dec r23 ;Wait for a bit time
73 brne 2b ;/
74 brcs 3f ;MISO = bit to be sent
75 OUT_1 ;
763: brcc 4f ;
77 OUT_0 ;/
784: lsr r24 ;Get next bit into C
79 dec r25 ;All bits sent?
80 brne 1b ; no, coutinue
81
82 out _SFR_IO_ADDR(SREG), r0 ;End of critical section
83 ret
84.endfunc
85
86
87
88;---------------------------------------------------------------------------;
89; Receive a byte
90;
91;Prototype: uint8_t rcvr (void);
92;Size: 19 words
93
94.global rcvr
95.func rcvr
96rcvr:
97 in r0, _SFR_IO_ADDR(SREG) ;Save flags
98
99 ldi r24, 0x80 ;Receiving shift reg
100 cli ;Start critical section
101
1021: SKIP_IN_1 ;Wait for idle
103 rjmp 1b
1042: SKIP_IN_0 ;Wait for start bit
105 rjmp 2b
106 ldi r25, BPS/2 ;Wait for half bit time
1073: dec r25
108 brne 3b
109
1104: ldi r25, BPS ;----- Bit receiving loop
1115: dec r25 ;Wait for a bit time
112 brne 5b ;/
113 lsr r24 ;Next bit
114 SKIP_IN_0 ;Get a data bit into r24.7
115 ori r24, 0x80
116 brcc 4b ;All bits received? no, continue
117
118 out _SFR_IO_ADDR(SREG), r0 ;End of critical section
119 ret
120.endfunc
121
122
123; Not wait for start bit. This should be called after detecting start bit.
124.global recv
125.func recv
126recv:
127 in r0, _SFR_IO_ADDR(SREG) ;Save flags
128
129 ldi r24, 0x80 ;Receiving shift reg
130 cli ;Start critical section
131
132;1: SKIP_IN_1 ;Wait for idle
133; rjmp 1b
134;2: SKIP_IN_0 ;Wait for start bit
135; rjmp 2b
136 ldi r25, BPS/2 ;Wait for half bit time
1373: dec r25
138 brne 3b
139
1404: ldi r25, BPS ;----- Bit receiving loop
1415: dec r25 ;Wait for a bit time
142 brne 5b ;/
143 lsr r24 ;Next bit
144 SKIP_IN_0 ;Get a data bit into r24.7
145 ori r24, 0x80
146 brcc 4b ;All bits received? no, continue
147
148 ldi r25, BPS/2 ;Wait for half bit time
1496: dec r25
150 brne 6b
1517: SKIP_IN_1 ;Wait for stop bit
152 rjmp 7b
153
154 out _SFR_IO_ADDR(SREG), r0 ;End of critical section
155 ret
156.endfunc
diff --git a/keyboards/hhkb/rn42/suart.h b/keyboards/hhkb/rn42/suart.h
new file mode 100644
index 000000000..7d92be069
--- /dev/null
+++ b/keyboards/hhkb/rn42/suart.h
@@ -0,0 +1,8 @@
1#ifndef SUART
2#define SUART
3
4void xmit(uint8_t);
5uint8_t rcvr(void);
6uint8_t recv(void);
7
8#endif /* SUART */
diff --git a/keyboards/hhkb/rules.mk b/keyboards/hhkb/rules.mk
index b8bfd73d2..3abd31c33 100644
--- a/keyboards/hhkb/rules.mk
+++ b/keyboards/hhkb/rules.mk
@@ -72,6 +72,36 @@ CUSTOM_MATRIX = yes # Custom matrix file for the HHKB
72# UNICODE_ENABLE = yes # Unicode 72# UNICODE_ENABLE = yes # Unicode
73# BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID 73# BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID
74 74
75
76# HHKB_RN42_ENABLE = yes # Enable support for hasu's BT alt controller -- code borrowed from tmk source tree.
77
78# Either uncomment the HHKB_RN42_ENABLE line above, or run make enabling the
79# feature. Be sure to clean any existing build before trying to enable rn42
80# support. For example:
81#
82# make hhkb-keymap-clean
83# make hhkb-keymap-dfu HHKB_RN42_ENABLE=yes
84
85ifeq ($(strip $(HHKB_RN42_ENABLE)), yes)
86
87OPT_DEFS += -DHHKB_RN42_ENABLE
88
89# Support for the RN42 Bluetooth module. This is the BT module in Hasu's BT
90# HHKB Alt controller.
91RN42_DIR = rn42
92
93SRC += serial_uart.c \
94 rn42/suart.S \
95 rn42/rn42.c \
96 rn42/rn42_task.c \
97 rn42/battery.c \
98 rn42/main.c
99
100VPATH += $(RN42_DIR)
101
102endif
103
104
75# debug-on: EXTRAFLAGS += -DDEBUG -DDEBUG_ACTION 105# debug-on: EXTRAFLAGS += -DDEBUG -DDEBUG_ACTION
76# debug-on: all 106# debug-on: all
77 107