diff options
Diffstat (limited to 'keyboards/bioi/main.c')
-rw-r--r-- | keyboards/bioi/main.c | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/keyboards/bioi/main.c b/keyboards/bioi/main.c new file mode 100644 index 0000000000..14f0f8de7a --- /dev/null +++ b/keyboards/bioi/main.c @@ -0,0 +1,389 @@ +/* +Copyright 2019 Basic I/O Instruments(Scott Wei) <scot.wei@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 <avr/pgmspace.h> +#include <util/delay.h> + +#include "report.h" +#include "host.h" +#include "host_driver.h" +#include "keyboard.h" +#include "action.h" +#include "led.h" +#include "sendchar.h" +#include "debug.h" +#include "print.h" +#ifdef SLEEP_LED_ENABLE +#include "sleep_led.h" +#endif +#include "suspend.h" + +#include "usb_descriptor.h" +#include "lufa.h" +#include "quantum.h" +#include <util/atomic.h> +#include "outputselect.h" + +#ifdef NKRO_ENABLE +#include "keycode_config.h" + +extern keymap_config_t keymap_config; +#endif + +#ifdef AUDIO_ENABLE +#include <audio.h> +#endif + +#ifdef BLUETOOTH_ENABLE +#ifdef MODULE_ADAFRUIT_BLE +#include "adafruit_ble.h" +#else +#include "bluetooth.h" +#endif +#endif + +#ifdef VIRTSER_ENABLE +#include "virtser.h" +#endif + +#if (defined(RGB_MIDI) | defined(RGBLIGHT_ANIMATIONS)) & defined(RGBLIGHT_ENABLE) +#include "rgblight.h" +#endif + +#ifdef MIDI_ENABLE +#include "qmk_midi.h" +#endif + +#ifdef RAW_ENABLE +#include "raw_hid.h" +#endif + +#include "ble.h" +#include "usart.h" + +#include <avr/power.h> +#include <avr/sleep.h> + +bool force_usb = false; //Reserved for FORCE USB Mode function. +bool force_ble = false; //Reserved for FORCE USB Mode function. + +bool usb_connected = false; +bool ble_enabled = false; + +uint32_t kb_idle_timer = 0; + +bool usb_state_sent = false; + +uint8_t USB_DeviceLastState = 0; + +#ifdef RAW_ENABLE +/** \brief Raw HID Task + * + * FIXME: Needs doc + */ +static void raw_hid_task(void) +{ + // Create a temporary buffer to hold the read in data from the host + uint8_t data[RAW_EPSIZE]; + bool data_read = false; + + // Device must be connected and configured for the task to run + if (USB_DeviceState != DEVICE_STATE_Configured) + return; + + Endpoint_SelectEndpoint(RAW_OUT_EPNUM); + + // Check to see if a packet has been sent from the host + if (Endpoint_IsOUTReceived()) + { + // Check to see if the packet contains data + if (Endpoint_IsReadWriteAllowed()) + { + /* Read data */ + Endpoint_Read_Stream_LE(data, sizeof(data), NULL); + data_read = true; + } + + // Finalize the stream transfer to receive the last packet + Endpoint_ClearOUT(); + + if (data_read) + { + raw_hid_receive(data, sizeof(data)); + } + } +} +#endif + +static void setup_mcu(void) +{ + /* Disable watchdog if enabled by bootloader/fuses */ + MCUSR &= ~(1 << WDRF); + wdt_disable(); + + CLKPR = (1 << CLKPCE); + CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); +} + +static void setup_usb(void) +{ + // Leonardo needs. Without this USB device is not recognized. + USB_Disable(); + + USB_Init(); + + // for Console_Task + USB_Device_EnableSOFEvents(); + print_set_sendchar(sendchar); +} + +void power_saving(void) +{ + power_adc_disable(); + power_usart0_disable(); + power_spi_disable(); + power_twi_disable(); + + USBCON |= (1 << FRZCLK); // Freeze the USB Clock + PLLCSR &= ~(1 << PLLE); // Disable the USB Clock (PPL) + USBCON &= ~(1 << USBE); +} + +void power_recover(void) +{ + + USBCON |= (1 << USBE); + PLLCSR |= (1 << PLLE); // Resume the USB Clock (PPL) + USBCON &= ~(1 << FRZCLK); // Resume the USB Clock + + power_adc_enable(); + power_usart0_enable(); + power_spi_enable(); + power_twi_enable(); +} + +void ble_task_init(void) +{ + kb_idle_timer = timer_read32(); //Mark current time, reserved for further usage; +} + +void ble_task(void) +{ + + if (USB_DeviceLastState != USB_DeviceState) + { + usb_state_sent = false; +#ifdef BLE_DEBUG + send_str(PSTR("USB State Changed\r\n")); + if (USB_DeviceState == DEVICE_STATE_Unattached) + { + send_str(PSTR("USB State Unattached\r\n")); + } +#endif + if (USB_DeviceState == DEVICE_STATE_Powered) + { +#ifdef BLE_DEBUG + send_str(PSTR("USB State Powered\r\n")); +#endif + power_recover(); + host_set_driver(&null_driver); + } +#ifdef BLE_DEBUG + if ((USB_DeviceState == DEVICE_STATE_Default)) + { + send_str(PSTR("USB State Default\r\n")); + } + if ((USB_DeviceState == DEVICE_STATE_Addressed)) + { + send_str(PSTR("USB State Addressed\r\n")); + } + if (USB_DeviceState == DEVICE_STATE_Configured) + { + send_str(PSTR("USB State Configured\r\n")); + } + if (USB_DeviceState > DEVICE_STATE_Unattached) + { + } + else + { + // + } +#endif + } + else + { +#ifdef BLE_DEBUG + if (!usb_state_sent) + { + if (USB_DeviceState == DEVICE_STATE_Unattached) + { + send_str(PSTR("USB State Stopped at Unattached\r\n")); + } + if (USB_DeviceState == DEVICE_STATE_Powered) + { + send_str(PSTR("USB State Stopped at Powered\r\n")); + } + if ((USB_DeviceState == DEVICE_STATE_Default)) + { + send_str(PSTR("USB State Stopped at Default\r\n")); + } + if ((USB_DeviceState == DEVICE_STATE_Addressed)) + { + send_str(PSTR("USB State Stopped at Addressed\r\n")); + } + if (USB_DeviceState == DEVICE_STATE_Configured) + { + send_str(PSTR("USB State Stopped at Configured\r\n")); + } + } +#endif + if (USB_DeviceState == DEVICE_STATE_Unattached) + { + if (host_get_driver() && host_get_driver() != &bluefruit_driver) + { +#ifdef BLE_DEBUG + send_str(PSTR("USB State stopped at Unattached\r\n")); +#endif + ble_task_init(); + + force_usb = 0; + usb_connected = 0; + + //Reinit USB to prepare for next connection. + USB_Init(); + USB_Detach(); + USB_Attach(); + +#ifdef BLE_DEBUG + send_str(PSTR("Loading &bluefruit_driver\r\n")); +#endif + host_set_driver(&bluefruit_driver); + clear_keyboard(); + power_saving(); + } + else + { + //Do nothing if USB is unattached and the driver is &bluefruit_driver + } + } + if (USB_DeviceState == DEVICE_STATE_Configured) + { + if (host_get_driver() && host_get_driver() != &lufa_driver) + { +#ifdef BLE_DEBUG + send_str(PSTR("USB State stopped at Configured\r\n")); +#endif + power_recover(); + + usb_connected = 1; + ble_enabled = 0; +#ifdef BLE_DEBUG + send_str(PSTR("Loading &lufa_driver\r\n")); +#endif + host_set_driver(&lufa_driver); + clear_keyboard(); + } + else + { + //Do nothing if the driver is &lufa_driver + } + } + + usb_state_sent = true; + } + + USB_DeviceLastState = USB_DeviceState; +} + +// Use a custom main() function because the task logic is different from the common one. +int main(void) +{ +#ifdef MIDI_ENABLE + setup_midi(); +#endif + + setup_mcu(); + + keyboard_setup(); + + setup_usb(); + sei(); + +#if defined(MODULE_ADAFRUIT_EZKEY) || defined(MODULE_RN42) + serial_init(); +#endif + + /* wait for USB startup to get ready for debug output */ + uint8_t timeout = 255; // timeout when USB is not available(Bluetooth) + while (timeout-- && USB_DeviceState != DEVICE_STATE_Configured) + { + wait_ms(4); +#if defined(INTERRUPT_CONTROL_ENDPOINT) + ; +#else + USB_USBTask(); +#endif + } + + print("\nUSB init\n"); + + keyboard_init(); + host_set_driver(&lufa_driver); + + backlight_disable(); + //host_set_driver(&lufa_driver); + print("Keyboard initialized.\n"); + + //Init Hardware UART + usart_init(); + +#ifdef BLE_DEBUG + send_str(PSTR("Keyboard has been setup up\r\n")); + + if (usb_connected) + { + send_str(PSTR("usb_connected=1\r\n")); + } + else + { + send_str(PSTR("usb_connected=0\r\n")); + } +#endif + +#ifdef SLEEP_LED_ENABLE + sleep_led_init(); +#endif + +#ifdef VIRTSER_ENABLE + virtser_init(); +#endif + + while (1) + { + ble_task(); + keyboard_task(); + +#ifdef RAW_ENABLE + raw_hid_task(); +#endif + +#if defined(RGBLIGHT_ANIMATIONS) && defined(RGBLIGHT_ENABLE) + rgblight_task(); +#endif + +#if !defined(INTERRUPT_CONTROL_ENDPOINT) + USB_USBTask(); +#endif + } +} |