]> git.donarmstrong.com Git - tmk_firmware.git/blob - protocol/iwrap/main.c
Fix rn42.h API
[tmk_firmware.git] / protocol / iwrap / main.c
1 /*
2 Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include <stdint.h>
18 #include <avr/interrupt.h>
19 #include <avr/io.h>
20 //#include <avr/wdt.h>
21 #include "wd.h" // in order to use watchdog in interrupt mode
22 #include <avr/sleep.h>
23 #include <util/delay.h>
24 #include <avr/power.h>
25 #include "keyboard.h"
26 #include "matrix.h"
27 #include "host.h"
28 #include "action.h"
29 #include "iwrap.h"
30 #ifdef PROTOCOL_VUSB
31 #   include "vusb.h"
32 #   include "usbdrv.h"
33 #endif
34 #include "uart.h"
35 #include "suart.h"
36 #include "timer.h"
37 #include "debug.h"
38 #include "keycode.h"
39 #include "command.h"
40
41
42 static void sleep(uint8_t term);
43 static bool console(void);
44 static bool console_command(uint8_t c);
45 static uint8_t key2asc(uint8_t key);
46
47
48 /*
49 static void set_prr(void)
50 {
51     power_adc_disable();
52     power_spi_disable();
53     power_twi_disable();
54 #ifndef TIMER_H
55     //power_timer0_disable(); // used in timer.c
56 #endif
57     power_timer1_disable();
58     power_timer2_disable();
59 }
60 */
61
62 /*
63 static void pullup_pins(void)
64 {
65     // DDRs are set to 0(input) by default.
66 #ifdef PORTA
67     PORTA = 0xFF;
68 #endif
69     PORTB = 0xFF;
70     PORTC = 0xFF;
71     PORTD = 0xFF;
72 #ifdef PORTE
73     PORTE = 0xFF;
74 #endif
75 #ifdef PORTE
76     PORTF = 0xFF;
77 #endif
78 }
79 */
80
81
82 #ifdef PROTOCOL_VUSB
83 static void disable_vusb(void)
84 {
85     // disable interrupt & disconnect to prevent host from enumerating
86     USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT);
87     usbDeviceDisconnect();
88 }
89
90 static void enable_vusb(void)
91 {
92     USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
93     usbDeviceConnect();
94 }
95
96 static void init_vusb(void)
97 {
98     uint8_t i = 0;
99
100     usbInit();
101     disable_vusb();
102     /* fake USB disconnect for > 250 ms */
103     while(--i){
104         _delay_ms(1);
105     }
106     enable_vusb();
107 }
108 #endif
109
110 void change_driver(host_driver_t *driver)
111 {
112     /*
113     host_clear_keyboard_report();
114     host_swap_keyboard_report();
115     host_clear_keyboard_report();
116     host_send_keyboard_report();
117     */
118     clear_keyboard();
119     _delay_ms(1000);
120     host_set_driver(driver);
121 }
122
123
124 static bool sleeping = false;
125 static bool insomniac = false;   // TODO: should be false for power saving
126 static uint16_t last_timer = 0;
127
128 int main(void)
129 {
130     MCUSR = 0;
131     clock_prescale_set(clock_div_1);
132     WD_SET(WD_OFF);
133
134     // power saving: the result is worse than nothing... why?
135     //pullup_pins();
136     //set_prr();
137
138 #ifdef PROTOCOL_VUSB
139     disable_vusb();
140 #endif
141     uart_init(115200);
142     keyboard_init();
143     print("\nSend BREAK for UART Console Commands.\n");
144
145     // TODO: move to iWRAP/suart file
146     print("suart init\n");
147     // suart init
148     // PC4: Tx Output IDLE(Hi)
149     PORTC |= (1<<4);
150     DDRC  |= (1<<4);
151     // PC5: Rx Input(pull-up)
152     PORTC |= (1<<5);
153     DDRC  &= ~(1<<5);
154     // suart receive interrut(PC5/PCINT13)
155     PCMSK1 = 0b00100000;
156     PCICR  = 0b00000010;
157
158     host_set_driver(iwrap_driver());
159
160     print("iwrap_init()\n");
161     iwrap_init();
162     iwrap_call();
163
164     last_timer = timer_read();
165     while (true) {
166 #ifdef PROTOCOL_VUSB
167         if (host_get_driver() == vusb_driver())
168             usbPoll();
169 #endif
170         keyboard_task();
171 #ifdef PROTOCOL_VUSB
172         if (host_get_driver() == vusb_driver())
173             vusb_transfer_keyboard();
174 #endif
175         // TODO: depricated
176         if (matrix_is_modified() || console()) {
177             last_timer = timer_read();
178             sleeping = false;
179         } else if (!sleeping && timer_elapsed(last_timer) > 4000) {
180             sleeping = true;
181             iwrap_check_connection();
182         }
183
184         // TODO: suspend.h
185         if (host_get_driver() == iwrap_driver()) {
186             if (sleeping && !insomniac) {
187                 _delay_ms(1);   // wait for UART to send
188                 iwrap_sleep();
189                 sleep(WDTO_60MS);
190             }
191         }
192     }
193 }
194
195 static void sleep(uint8_t term)
196 {
197     WD_SET(WD_IRQ, term);
198
199     cli();
200     set_sleep_mode(SLEEP_MODE_PWR_DOWN);
201     sleep_enable();
202     sleep_bod_disable();
203     sei();
204     sleep_cpu();
205     sleep_disable();
206
207     WD_SET(WD_OFF);
208 }
209
210 static bool console(void)
211 {
212         // Send to Bluetoot module WT12
213         static bool breaked = false;
214         if (!uart_available())
215             return false;
216         else {
217             uint8_t c;
218             c = uart_getchar();
219             uart_putchar(c);
220             switch (c) {
221                 case 0x00: // BREAK signal
222                     if (!breaked) {
223                         print("break(? for help): ");
224                         breaked = true;
225                     }
226                     break;
227                 case '\r':
228                     uart_putchar('\n');
229                     iwrap_buf_send();
230                     break;
231                 case '\b':
232                     iwrap_buf_del();
233                     break;
234                 default:
235                     if (breaked) {
236                         print("\n");
237                         console_command(c);
238                         breaked = false;
239                     } else {
240                         iwrap_buf_add(c);
241                     }
242                     break;
243             }
244             return true;
245         }
246 }
247
248 bool command_extra(uint8_t code)
249 {
250     return console_command(key2asc(code));
251 }
252
253 static bool console_command(uint8_t c)
254 {
255     switch (c) {
256         case 'h':
257         case '?':
258             print("\nCommands for Bluetooth(WT12/iWRAP):\n");
259             print("r: reset. software reset by watchdog\n");
260             print("i: insomniac. prevent KB from sleeping\n");
261             print("c: iwrap_call. CALL for BT connection.\n");
262 #ifdef PROTOCOL_VUSB
263             print("u: USB mode. switch to USB.\n");
264             print("w: BT mode. switch to Bluetooth.\n");
265 #endif
266             print("k: kill first connection.\n");
267             print("Del: unpair first pairing.\n");
268             print("\n");
269             return 0;
270         case 'r':
271             print("reset\n");
272             WD_AVR_RESET();
273             return 1;
274         case 'i':
275             insomniac = !insomniac;
276             if (insomniac)
277                 print("insomniac\n");
278             else
279                 print("not insomniac\n");
280             return 1;
281         case 'c':
282             print("iwrap_call()\n");
283             iwrap_call();
284             return 1;
285 #ifdef PROTOCOL_VUSB
286         case 'u':
287             print("USB mode\n");
288             init_vusb();
289             change_driver(vusb_driver());
290             //iwrap_kill();
291             //iwrap_sleep();
292             // disable suart receive interrut(PC5/PCINT13)
293             PCMSK1 &= ~(0b00100000);
294             PCICR  &= ~(0b00000010);
295             return 1;
296         case 'w':
297             print("iWRAP mode\n");
298             change_driver(iwrap_driver());
299             disable_vusb();
300             // enable suart receive interrut(PC5/PCINT13)
301             PCMSK1 |= 0b00100000;
302             PCICR  |= 0b00000010;
303             return 1;
304 #endif
305         case 'k':
306             print("kill\n");
307             iwrap_kill();
308             return 1;
309         case 0x7F:  // DELETE
310             print("unpair\n");
311             iwrap_unpair();
312             return 1;
313     }
314     return 0;
315 }
316
317 // convert keycode into ascii charactor
318 static uint8_t key2asc(uint8_t key)
319 {
320     switch (key) {
321         case KC_A: return 'a';
322         case KC_B: return 'b';
323         case KC_C: return 'c';
324         case KC_D: return 'd';
325         case KC_E: return 'e';
326         case KC_F: return 'f';
327         case KC_G: return 'g';
328         case KC_H: return 'h';
329         case KC_I: return 'i';
330         case KC_J: return 'j';
331         case KC_K: return 'k';
332         case KC_L: return 'l';
333         case KC_M: return 'm';
334         case KC_N: return 'n';
335         case KC_O: return 'o';
336         case KC_P: return 'p';
337         case KC_Q: return 'q';
338         case KC_R: return 'r';
339         case KC_S: return 's';
340         case KC_T: return 't';
341         case KC_U: return 'u';
342         case KC_V: return 'v';
343         case KC_W: return 'w';
344         case KC_X: return 'x';
345         case KC_Y: return 'y';
346         case KC_Z: return 'z';
347         case KC_1: return '1';
348         case KC_2: return '2';
349         case KC_3: return '3';
350         case KC_4: return '4';
351         case KC_5: return '5';
352         case KC_6: return '6';
353         case KC_7: return '7';
354         case KC_8: return '8';
355         case KC_9: return '9';
356         case KC_0: return '0';
357         case KC_ENTER: return '\n';
358         case KC_ESCAPE: return 0x1B;
359         case KC_BSPACE: return '\b';
360         case KC_TAB: return '\t';
361         case KC_SPACE: return ' ';
362         case KC_MINUS: return '-';
363         case KC_EQUAL: return '=';
364         case KC_LBRACKET: return '[';
365         case KC_RBRACKET: return ']';
366         case KC_BSLASH: return '\\';
367         case KC_NONUS_HASH: return '\\';
368         case KC_SCOLON: return ';';
369         case KC_QUOTE: return '\'';
370         case KC_GRAVE: return '`';
371         case KC_COMMA: return ',';
372         case KC_DOT: return '.';
373         case KC_SLASH: return '/';
374         default: return 0x00;
375     }
376 }