From 5f6e4c1e351e0d358ff063adee8e67b70002d87f Mon Sep 17 00:00:00 2001 From: Michiel Visser Date: Sat, 13 Jul 2019 13:50:00 +0200 Subject: [PATCH] Add basic Bluetooth support --- keyboards/anne_pro/anne_pro.c | 33 ++++ keyboards/anne_pro/anne_pro.h | 3 +- keyboards/anne_pro/anne_pro_bluetooth.c | 176 ++++++++++++++++++++ keyboards/anne_pro/anne_pro_bluetooth.h | 27 +++ keyboards/anne_pro/halconf.h | 20 +++ keyboards/anne_pro/keymaps/default/keymap.c | 2 +- keyboards/anne_pro/mcuconf.h | 2 +- keyboards/anne_pro/rules.mk | 2 +- 8 files changed, 261 insertions(+), 4 deletions(-) create mode 100644 keyboards/anne_pro/anne_pro_bluetooth.c create mode 100644 keyboards/anne_pro/anne_pro_bluetooth.h diff --git a/keyboards/anne_pro/anne_pro.c b/keyboards/anne_pro/anne_pro.c index ea43a662c0..afce4f39c5 100644 --- a/keyboards/anne_pro/anne_pro.c +++ b/keyboards/anne_pro/anne_pro.c @@ -16,9 +16,15 @@ #include "anne_pro.h" #include "anne_pro_lighting.h" +#include "anne_pro_bluetooth.h" #include "ch.h" #include "hal.h" +#ifdef NKRO_ENABLE +static bool nkro_enabled_last = false; +#endif +static host_driver_t *host_driver_last; + /* Process the Anne Pro custom keycodes */ bool process_record_kb(uint16_t keycode, keyrecord_t *record) { /* Update the key status for the reactive effects */ @@ -49,6 +55,29 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) { anne_pro_lighting_mode_next(); } return false; + case APB_TOG: + /* Toggle the output driver between USB and Bluetooth */ + if (record->event.pressed) { + if (host_get_driver() != &anne_pro_bluetooth_driver) { + clear_keyboard(); + host_driver_last = host_get_driver(); +#ifdef NKRO_ENABLE + nkro_enabled_last = keymap_config.nkro; + keymap_config.nkro = false; +#endif + host_set_driver(&anne_pro_bluetooth_driver); + anne_pro_bluetooth_on(); + anne_pro_bluetooth_broadcast(); + } else { + clear_keyboard(); +#ifdef NKRO_ENABLE + keymap_config.nkro = nkro_enabled_last; +#endif + host_set_driver(host_driver_last); + anne_pro_bluetooth_off(); + } + } + return false; default: /* Handle other keycodes normally */ return process_record_user(keycode, record); @@ -59,6 +88,8 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) { void keyboard_pre_init_kb(void) { /* Initialize the ligthing controller */ anne_pro_lighting_init(); + /* Initialize the bluetooth controller */ + anne_pro_bluetooth_init(); keyboard_pre_init_user(); } @@ -79,6 +110,8 @@ void keyboard_post_init_kb(void) { void matrix_scan_kb(void) { /* Run some update code for the lighting */ anne_pro_lighting_update(); + /* Run some update code for the bluetooth */ + anne_pro_bluetooth_update(); /* Run matrix_scan_user code */ matrix_scan_user(); diff --git a/keyboards/anne_pro/anne_pro.h b/keyboards/anne_pro/anne_pro.h index 4d3c75bd7e..984a2ad4bc 100644 --- a/keyboards/anne_pro/anne_pro.h +++ b/keyboards/anne_pro/anne_pro.h @@ -22,7 +22,8 @@ enum anne_pro_keycodes { APL_RGB = SAFE_RANGE, APL_RAT, APL_BRT, - APL_MOD + APL_MOD, + APB_TOG, }; /* The fully-featured LAYOUT() that has every single key available in the matrix. */ diff --git a/keyboards/anne_pro/anne_pro_bluetooth.c b/keyboards/anne_pro/anne_pro_bluetooth.c new file mode 100644 index 0000000000..a5dc94dba8 --- /dev/null +++ b/keyboards/anne_pro/anne_pro_bluetooth.c @@ -0,0 +1,176 @@ +/* Copyright 2019 Michiel Visser + * + * 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 . + */ + +#include "anne_pro_bluetooth.h" +#include "uart_tx_ringbuf.h" +#include "host.h" +#include "host_driver.h" + +#define BLUETOOTH_UART (&UARTD2) +/* UART transmission ringbuffer for the Bluetooth UART */ +static uint8_t bluetooth_uart_tx_buffer[256] = {0}; +static uart_tx_ringbuf_t bluetooth_uart_ringbuf = { + .buf = bluetooth_uart_tx_buffer, + .uart = BLUETOOTH_UART, + .size = sizeof(bluetooth_uart_tx_buffer), + .sending_elements = 0, + .head = 0, + .tail = 0, +}; + +/* Handler for finsihed Bluetooth UART transmissions */ +static void bluetooth_uart_txend(UARTDriver *uart) { + uart_tx_ringbuf_finish_transmission(&bluetooth_uart_ringbuf); +} + +/* Wakeup bluetooth chip and wait for acknoledgement */ +msg_t bluetooth_wakeup(void) { + char rx_buf[3]; + size_t frames = 3; + palSetPad(GPIOA, 1); + msg_t result = uartReceiveTimeout(BLUETOOTH_UART, &frames, &rx_buf, 10); + palClearPad(GPIOA, 1); + return result; +} + +/* Update Bluetooth, should be called every matrix scan */ +void anne_pro_bluetooth_update(void) { + if (!uart_tx_ringbuf_empty(&bluetooth_uart_ringbuf)) { + if (bluetooth_wakeup() == MSG_OK) { + uart_tx_ringbuf_start_transmission(&bluetooth_uart_ringbuf); + } + } +} + +void bluetooth_rx_char(UARTDriver *driver, uint16_t c); +/* Bluetooth UART configuration */ +static UARTConfig bluetooth_uart_cfg = { + .txend1_cb = bluetooth_uart_txend, + .txend2_cb = NULL, + .rxend_cb = NULL, + .rxchar_cb = bluetooth_rx_char, + .rxerr_cb = NULL, + .speed = 38400, + .cr1 = 0, + .cr2 = USART_CR2_LINEN, + .cr3 = 0 +}; + +/* Receive buffer for the Bluetooth UART */ +uint8_t bluetooth_rx_buffer[256] = {0}; +size_t bluetooth_rx_index = 0; + +/* Lookup table for translation to hex */ +char hex_lookup[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + +/* Handle packets from the bluetooth receive buffer */ +void bluetooth_handle_packet(void) { + /* Packet type and length */ + uint8_t packet_type = bluetooth_rx_buffer[0]; + // uint8_t packet_len = bluetooth_rx_buffer[1]; + + /* Handle incomming packets over Bluetooth */ + switch (packet_type) { + case 2: // System + switch (bluetooth_rx_buffer[2]) { + case 1: // GetId + // [2, 15, 129, 10, 2, 0, 1, 2, 50, 55, 71, 1, 50, 48] + // [2, 15, 129, 8, 2, 1, 54, 48, 52, 0, 54, 0, 50, 48] + uart_tx_ringbuf_write(&bluetooth_uart_ringbuf, 28, "\x02\x0f\x81\x0a\x02\x00\x01\x02\x32\x37\x47\x01\x32\x30" + "\x02\x0f\x81\x08\x02\x01\x36\x30\x34\x00\x36\x00\x32\x30"); + break; + } + break; + } +} + +/* Receive single character from the Bluetooth UART */ +void bluetooth_rx_char(UARTDriver *driver, uint16_t c) { + bluetooth_rx_buffer[bluetooth_rx_index++] = c; + + if (bluetooth_rx_index > 2) { + uint8_t packet_len = bluetooth_rx_buffer[1]; + if (bluetooth_rx_index >= (2 + packet_len)) { + bluetooth_handle_packet(); + bluetooth_rx_index = 0; + } + } +} + +/* Initialize the Anne Pro Bluetooth */ +void anne_pro_bluetooth_init(void) { + /* Initialize the bleutooth UART */ + uartStart(BLUETOOTH_UART, &bluetooth_uart_cfg); + palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7)); + palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7)); + palSetPadMode(GPIOA, 1, PAL_MODE_OUTPUT_PUSHPULL); + palClearPad(GPIOA, 1); + + /* Disable bluetooth on startup */ + anne_pro_bluetooth_off(); +} + +/* Turn on Bluetooth */ +void anne_pro_bluetooth_on(void) { + uart_tx_ringbuf_write(&bluetooth_uart_ringbuf, 3, "\x06\x01\x01"); +} + +/* Turn off Bluetooth */ +void anne_pro_bluetooth_off(void) { + uart_tx_ringbuf_write(&bluetooth_uart_ringbuf, 3, "\x06\x01\x02"); +} + +/* Start broadcasting on Bluetooth */ +void anne_pro_bluetooth_broadcast(void) { + uart_tx_ringbuf_write(&bluetooth_uart_ringbuf, 3, "\x06\x01\x07"); +} + +/* Status of keyboard leds for Bluetooth driver*/ +static uint8_t keyboard_leds(void) { + return 0; +} + +/* Send keyboard HID report for Bluetooth driver */ +static void send_keyboard(report_keyboard_t *report) { + uint8_t bluetooth_report[11] = {7, 9, 1, 0}; + bluetooth_report[3] = report->mods; + bluetooth_report[4] = report->reserved; + for (int i = 0; i < 6; i++) { + bluetooth_report[5+i] = report->keys[i]; + } + uart_tx_ringbuf_write(&bluetooth_uart_ringbuf, 11, bluetooth_report); +} + +/* Send mouse HID report for Bluetooth driver */ +static void send_mouse(report_mouse_t *report) { +} + +/* Send system report for Bluetooth driver */ +static void send_system(uint16_t data) { +} + +/* Send consumer report for Bluetooth driver */ +static void send_consumer(uint16_t data) { +} + +/* Bluetooth host driver, this allows us to switch from USB output to Bluetooth output */ +host_driver_t anne_pro_bluetooth_driver = { + keyboard_leds, + send_keyboard, + send_mouse, + send_system, + send_consumer +}; diff --git a/keyboards/anne_pro/anne_pro_bluetooth.h b/keyboards/anne_pro/anne_pro_bluetooth.h new file mode 100644 index 0000000000..130adedc11 --- /dev/null +++ b/keyboards/anne_pro/anne_pro_bluetooth.h @@ -0,0 +1,27 @@ +/* Copyright 2019 Michiel Visser + * + * 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 . + */ + +#pragma once +#include "host_driver.h" + +extern host_driver_t anne_pro_bluetooth_driver; + +void anne_pro_bluetooth_init(void); +void anne_pro_bluetooth_update(void); + +void anne_pro_bluetooth_on(void); +void anne_pro_bluetooth_off(void); +void anne_pro_bluetooth_broadcast(void); diff --git a/keyboards/anne_pro/halconf.h b/keyboards/anne_pro/halconf.h index 1ceefe34a9..1a6f22bac1 100644 --- a/keyboards/anne_pro/halconf.h +++ b/keyboards/anne_pro/halconf.h @@ -336,6 +336,26 @@ #define SPI_USE_MUTUAL_EXCLUSION TRUE #endif +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + /*===========================================================================*/ /* USB driver related settings. */ /*===========================================================================*/ diff --git a/keyboards/anne_pro/keymaps/default/keymap.c b/keyboards/anne_pro/keymaps/default/keymap.c index 37cce3d48b..faed6117df 100644 --- a/keyboards/anne_pro/keymaps/default/keymap.c +++ b/keyboards/anne_pro/keymaps/default/keymap.c @@ -35,7 +35,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ), [2] = LAYOUT( RESET, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, - XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + APB_TOG, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, _______, _______, XXXXXXX, _______, _______, _______, _______ diff --git a/keyboards/anne_pro/mcuconf.h b/keyboards/anne_pro/mcuconf.h index 5fa5ff0129..337d12775c 100644 --- a/keyboards/anne_pro/mcuconf.h +++ b/keyboards/anne_pro/mcuconf.h @@ -177,7 +177,7 @@ * UART driver system settings. */ #define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART2 TRUE #define STM32_UART_USE_USART3 TRUE #define STM32_UART_USART1_IRQ_PRIORITY 12 #define STM32_UART_USART2_IRQ_PRIORITY 12 diff --git a/keyboards/anne_pro/rules.mk b/keyboards/anne_pro/rules.mk index 41d7ee92fb..9a00bb6921 100644 --- a/keyboards/anne_pro/rules.mk +++ b/keyboards/anne_pro/rules.mk @@ -24,7 +24,7 @@ ARMV = 7 DFU_ARGS = -d 0483:df11 -a 0 -s 0x08004000 # Extra source files -SRC += uart_tx_ringbuf.c anne_pro_lighting.c +SRC += uart_tx_ringbuf.c anne_pro_lighting.c anne_pro_bluetooth.c # Build Options # comment out to disable the options.