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