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