summaryrefslogtreecommitdiff
path: root/tmk_core/protocol/iwrap/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/protocol/iwrap/main.c')
-rw-r--r--tmk_core/protocol/iwrap/main.c376
1 files changed, 376 insertions, 0 deletions
diff --git a/tmk_core/protocol/iwrap/main.c b/tmk_core/protocol/iwrap/main.c
new file mode 100644
index 0000000000..3abdce8dfc
--- /dev/null
+++ b/tmk_core/protocol/iwrap/main.c
@@ -0,0 +1,376 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdint.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+//#include <avr/wdt.h>
+#include "wd.h" // in order to use watchdog in interrupt mode
+#include <avr/sleep.h>
+#include <util/delay.h>
+#include <avr/power.h>
+#include "keyboard.h"
+#include "matrix.h"
+#include "host.h"
+#include "action.h"
+#include "iwrap.h"
+#ifdef PROTOCOL_VUSB
+# include "vusb.h"
+# include "usbdrv.h"
+#endif
+#include "uart.h"
+#include "suart.h"
+#include "timer.h"
+#include "debug.h"
+#include "keycode.h"
+#include "command.h"
+
+
+static void sleep(uint8_t term);
+static bool console(void);
+static bool console_command(uint8_t c);
+static uint8_t key2asc(uint8_t key);
+
+
+/*
+static void set_prr(void)
+{
+ power_adc_disable();
+ power_spi_disable();
+ power_twi_disable();
+#ifndef TIMER_H
+ //power_timer0_disable(); // used in timer.c
+#endif
+ power_timer1_disable();
+ power_timer2_disable();
+}
+*/
+
+/*
+static void pullup_pins(void)
+{
+ // DDRs are set to 0(input) by default.
+#ifdef PORTA
+ PORTA = 0xFF;
+#endif
+ PORTB = 0xFF;
+ PORTC = 0xFF;
+ PORTD = 0xFF;
+#ifdef PORTE
+ PORTE = 0xFF;
+#endif
+#ifdef PORTE
+ PORTF = 0xFF;
+#endif
+}
+*/
+
+
+#ifdef PROTOCOL_VUSB
+static void disable_vusb(void)
+{
+ // disable interrupt & disconnect to prevent host from enumerating
+ USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT);
+ usbDeviceDisconnect();
+}
+
+static void enable_vusb(void)
+{
+ USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
+ usbDeviceConnect();
+}
+
+static void init_vusb(void)
+{
+ uint8_t i = 0;
+
+ usbInit();
+ disable_vusb();
+ /* fake USB disconnect for > 250 ms */
+ while(--i){
+ _delay_ms(1);
+ }
+ enable_vusb();
+}
+#endif
+
+void change_driver(host_driver_t *driver)
+{
+ /*
+ host_clear_keyboard_report();
+ host_swap_keyboard_report();
+ host_clear_keyboard_report();
+ host_send_keyboard_report();
+ */
+ clear_keyboard();
+ _delay_ms(1000);
+ host_set_driver(driver);
+}
+
+
+static bool sleeping = false;
+static bool insomniac = false; // TODO: should be false for power saving
+static uint16_t last_timer = 0;
+
+int main(void)
+{
+ MCUSR = 0;
+ clock_prescale_set(clock_div_1);
+ WD_SET(WD_OFF);
+
+ // power saving: the result is worse than nothing... why?
+ //pullup_pins();
+ //set_prr();
+
+#ifdef PROTOCOL_VUSB
+ disable_vusb();
+#endif
+ uart_init(115200);
+ keyboard_init();
+ print("\nSend BREAK for UART Console Commands.\n");
+
+ // TODO: move to iWRAP/suart file
+ print("suart init\n");
+ // suart init
+ // PC4: Tx Output IDLE(Hi)
+ PORTC |= (1<<4);
+ DDRC |= (1<<4);
+ // PC5: Rx Input(pull-up)
+ PORTC |= (1<<5);
+ DDRC &= ~(1<<5);
+ // suart receive interrut(PC5/PCINT13)
+ PCMSK1 = 0b00100000;
+ PCICR = 0b00000010;
+
+ host_set_driver(iwrap_driver());
+
+ print("iwrap_init()\n");
+ iwrap_init();
+ iwrap_call();
+
+ last_timer = timer_read();
+ while (true) {
+#ifdef PROTOCOL_VUSB
+ if (host_get_driver() == vusb_driver())
+ usbPoll();
+#endif
+ keyboard_task();
+#ifdef PROTOCOL_VUSB
+ if (host_get_driver() == vusb_driver())
+ vusb_transfer_keyboard();
+#endif
+ // TODO: depricated
+ if (matrix_is_modified() || console()) {
+ last_timer = timer_read();
+ sleeping = false;
+ } else if (!sleeping && timer_elapsed(last_timer) > 4000) {
+ sleeping = true;
+ iwrap_check_connection();
+ }
+
+ // TODO: suspend.h
+ if (host_get_driver() == iwrap_driver()) {
+ if (sleeping && !insomniac) {
+ _delay_ms(1); // wait for UART to send
+ iwrap_sleep();
+ sleep(WDTO_60MS);
+ }
+ }
+ }
+}
+
+static void sleep(uint8_t term)
+{
+ WD_SET(WD_IRQ, term);
+
+ cli();
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+ sleep_enable();
+ sleep_bod_disable();
+ sei();
+ sleep_cpu();
+ sleep_disable();
+
+ WD_SET(WD_OFF);
+}
+
+static bool console(void)
+{
+ // Send to Bluetoot module WT12
+ static bool breaked = false;
+ if (!uart_available())
+ return false;
+ else {
+ uint8_t c;
+ c = uart_getchar();
+ uart_putchar(c);
+ switch (c) {
+ case 0x00: // BREAK signal
+ if (!breaked) {
+ print("break(? for help): ");
+ breaked = true;
+ }
+ break;
+ case '\r':
+ uart_putchar('\n');
+ iwrap_buf_send();
+ break;
+ case '\b':
+ iwrap_buf_del();
+ break;
+ default:
+ if (breaked) {
+ print("\n");
+ console_command(c);
+ breaked = false;
+ } else {
+ iwrap_buf_add(c);
+ }
+ break;
+ }
+ return true;
+ }
+}
+
+bool command_extra(uint8_t code)
+{
+ return console_command(key2asc(code));
+}
+
+static bool console_command(uint8_t c)
+{
+ switch (c) {
+ case 'h':
+ case '?':
+ print("\nCommands for Bluetooth(WT12/iWRAP):\n");
+ print("r: reset. software reset by watchdog\n");
+ print("i: insomniac. prevent KB from sleeping\n");
+ print("c: iwrap_call. CALL for BT connection.\n");
+#ifdef PROTOCOL_VUSB
+ print("u: USB mode. switch to USB.\n");
+ print("w: BT mode. switch to Bluetooth.\n");
+#endif
+ print("k: kill first connection.\n");
+ print("Del: unpair first pairing.\n");
+ print("\n");
+ return 0;
+ case 'r':
+ print("reset\n");
+ WD_AVR_RESET();
+ return 1;
+ case 'i':
+ insomniac = !insomniac;
+ if (insomniac)
+ print("insomniac\n");
+ else
+ print("not insomniac\n");
+ return 1;
+ case 'c':
+ print("iwrap_call()\n");
+ iwrap_call();
+ return 1;
+#ifdef PROTOCOL_VUSB
+ case 'u':
+ print("USB mode\n");
+ init_vusb();
+ change_driver(vusb_driver());
+ //iwrap_kill();
+ //iwrap_sleep();
+ // disable suart receive interrut(PC5/PCINT13)
+ PCMSK1 &= ~(0b00100000);
+ PCICR &= ~(0b00000010);
+ return 1;
+ case 'w':
+ print("iWRAP mode\n");
+ change_driver(iwrap_driver());
+ disable_vusb();
+ // enable suart receive interrut(PC5/PCINT13)
+ PCMSK1 |= 0b00100000;
+ PCICR |= 0b00000010;
+ return 1;
+#endif
+ case 'k':
+ print("kill\n");
+ iwrap_kill();
+ return 1;
+ case 0x7F: // DELETE
+ print("unpair\n");
+ iwrap_unpair();
+ return 1;
+ }
+ return 0;
+}
+
+// convert keycode into ascii charactor
+static uint8_t key2asc(uint8_t key)
+{
+ switch (key) {
+ case KC_A: return 'a';
+ case KC_B: return 'b';
+ case KC_C: return 'c';
+ case KC_D: return 'd';
+ case KC_E: return 'e';
+ case KC_F: return 'f';
+ case KC_G: return 'g';
+ case KC_H: return 'h';
+ case KC_I: return 'i';
+ case KC_J: return 'j';
+ case KC_K: return 'k';
+ case KC_L: return 'l';
+ case KC_M: return 'm';
+ case KC_N: return 'n';
+ case KC_O: return 'o';
+ case KC_P: return 'p';
+ case KC_Q: return 'q';
+ case KC_R: return 'r';
+ case KC_S: return 's';
+ case KC_T: return 't';
+ case KC_U: return 'u';
+ case KC_V: return 'v';
+ case KC_W: return 'w';
+ case KC_X: return 'x';
+ case KC_Y: return 'y';
+ case KC_Z: return 'z';
+ case KC_1: return '1';
+ case KC_2: return '2';
+ case KC_3: return '3';
+ case KC_4: return '4';
+ case KC_5: return '5';
+ case KC_6: return '6';
+ case KC_7: return '7';
+ case KC_8: return '8';
+ case KC_9: return '9';
+ case KC_0: return '0';
+ case KC_ENTER: return '\n';
+ case KC_ESCAPE: return 0x1B;
+ case KC_BSPACE: return '\b';
+ case KC_TAB: return '\t';
+ case KC_SPACE: return ' ';
+ case KC_MINUS: return '-';
+ case KC_EQUAL: return '=';
+ case KC_LBRACKET: return '[';
+ case KC_RBRACKET: return ']';
+ case KC_BSLASH: return '\\';
+ case KC_NONUS_HASH: return '\\';
+ case KC_SCOLON: return ';';
+ case KC_QUOTE: return '\'';
+ case KC_GRAVE: return '`';
+ case KC_COMMA: return ',';
+ case KC_DOT: return '.';
+ case KC_SLASH: return '/';
+ default: return 0x00;
+ }
+}