From d722cbc2178a1821e870b058a6574577a8dca2a5 Mon Sep 17 00:00:00 2001 From: gxcreator Date: Tue, 5 Nov 2024 00:30:15 +0100 Subject: [PATCH] feat(k2v2rgb): add bluetooth support using iton_bt driver --- keyboards/keychron/k2/rgb/v2/ansi/ansi.c | 249 ++++++++++++++++++ .../k2/rgb/v2/ansi/keymaps/default/keymap.c | 45 +--- .../k2/rgb/v2/ansi/keymaps/default/keymap.h | 41 +++ .../k2/rgb/v2/ansi/keymaps/via/keymap.c | 23 -- keyboards/keychron/k2/rgb/v2/ansi/rules.mk | 4 + keyboards/keychron/k2/rgb/v2/config.h | 13 + keyboards/keychron/k2/rgb/v2/halconf.h | 29 ++ keyboards/keychron/k2/rgb/v2/mcuconf.h | 12 + .../boards/SN_SN32F240B/board/board.mk | 6 + 9 files changed, 361 insertions(+), 61 deletions(-) create mode 100644 keyboards/keychron/k2/rgb/v2/ansi/ansi.c create mode 100644 keyboards/keychron/k2/rgb/v2/ansi/keymaps/default/keymap.h create mode 100644 keyboards/keychron/k2/rgb/v2/ansi/rules.mk create mode 100644 keyboards/keychron/k2/rgb/v2/halconf.h create mode 100644 keyboards/keychron/k2/rgb/v2/mcuconf.h diff --git a/keyboards/keychron/k2/rgb/v2/ansi/ansi.c b/keyboards/keychron/k2/rgb/v2/ansi/ansi.c new file mode 100644 index 000000000000..7b79c07151fd --- /dev/null +++ b/keyboards/keychron/k2/rgb/v2/ansi/ansi.c @@ -0,0 +1,249 @@ +/* +Copyright 2024 mintyleaf + +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 "quantum.h" +#include "keymap.h" +#ifdef BLUETOOTH_ENABLE +# include "iton_bt.h" +# include "outputselect.h" + +static uint32_t last_update_time = 0; + +static bool ev_connecting = false; +static bool ev_pairing = false; +static uint32_t ev_disconnected = 0; +static uint32_t ev_connected = 0; +static uint32_t ev_battery_level = 0; + +static uint32_t battery_level = 0; // Battery level reported by Iton BT +static uint32_t bt_profile = 0; // Bluetooth profile number + +static bool dip_switch_bt_en = false; // Bluetooth ON by BT/OFF/Cable dip switch + +void iton_bt_connection_successful() { + set_output(OUTPUT_BLUETOOTH); + ev_connected = 2500; + ev_pairing = false; + ev_connecting = false; +} + +void iton_bt_entered_pairing() { + ev_pairing = true; + ev_connected = 0; + ev_connecting = false; +} + +void iton_bt_enters_connection_state() { + ev_connecting = true; + ev_connected = 0; + ev_pairing = false; +} + +void iton_bt_disconnected() { + set_output(OUTPUT_USB); + ev_disconnected = 2500; + ev_connected = 0; + ev_pairing = false; + ev_connecting = false; +} + +void iton_bt_battery_level(uint8_t level) { + battery_level = level; + ev_battery_level = 2500; +} + +#endif + +/** + * @brief Set the Bluetooth profile + * + * @param profile Bluetooth profile number + */ +static void set_bt_profile(uint8_t profile) { + iton_bt_switch_profile(profile); + bt_profile = profile; +} + +bool process_record_kb(uint16_t keycode, keyrecord_t *record) { +#ifdef BLUETOOTH_ENABLE + // Ignore BT commands if BT is disabled + if (dip_switch_bt_en && record->event.pressed) { + switch (keycode) { + case KC_BTPROF0: + set_bt_profile(0); + return false; + case KC_BTPROF1: + set_bt_profile(1); + return false; + case KC_BTPROF2: + set_bt_profile(2); + return false; + case KC_BTPAIR: + if (dip_switch_bt_en) { + iton_bt_enter_pairing(); + } + return false; + case KC_BTRST: + if (dip_switch_bt_en) { + iton_bt_reset_pairing(); + } + return false; + case KC_BTBATT: + if (dip_switch_bt_en && record->event.pressed) { + ev_battery_level = 10000; + iton_bt_query_battery_level(); + } + return false; + } + } +#endif + + switch (keycode) { + case KC_MISSION_CONTROL: + if (record->event.pressed) { + host_consumer_send(0x29F); + } else { + host_consumer_send(0); + } + return false; + case KC_LAUNCHPAD: + if (record->event.pressed) { + host_consumer_send(0x2A0); + } else { + host_consumer_send(0); + } + return false; + default: + break; + } + return process_record_user(keycode, record); +} + +bool rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { + uint8_t layer = get_highest_layer(layer_state); + if (layer != 0 && layer != 2) { + for (uint8_t row = 0; row < MATRIX_ROWS; ++row) { + for (uint8_t col = 0; col < MATRIX_COLS; ++col) { + uint8_t index = g_led_config.matrix_co[row][col]; + + if (index >= led_min && index < led_max && index != NO_LED && keymap_key_to_keycode(layer, (keypos_t){col, row}) > KC_TRNS) { + rgb_matrix_set_color(index, RGB_WHITE); + } + } + } + } + +#ifdef BLUETOOTH_ENABLE + if (!dip_switch_bt_en) { + return true; + } + + uint32_t current_time = timer_read(); // Get the current time in milliseconds + uint32_t elapsed; + if (current_time >= last_update_time) { + elapsed = current_time - last_update_time; + } else { + elapsed = 1; + } + last_update_time = current_time; + + if (ev_connected > 0) { + uint8_t profile_index = 16 + bt_profile; + if ((current_time / 250) % 2 == 0) { + rgb_matrix_set_color(profile_index, RGB_GREEN); + } + if (elapsed >= ev_connected) { + ev_connected = 0; + } else { + ev_connected -= elapsed; + } + } + + if (ev_connecting) { + uint8_t profile_index = 16 + bt_profile; + if ((current_time / 125) % 2 == 0) { + rgb_matrix_set_color(profile_index, RGB_YELLOW); + } + } + + if (ev_pairing) { + uint8_t profile_index = 16 + bt_profile; + if ((current_time / 62) % 2 == 0) { + rgb_matrix_set_color(profile_index, RGB_BLUE); + } + } + + if (ev_disconnected > 0) { + uint8_t profile_index = 16 + bt_profile; + if ((current_time / 250) % 2 == 0) { + rgb_matrix_set_color(profile_index, RGB_RED); + } + if (elapsed >= ev_disconnected) { + ev_disconnected = 0; + } else { + ev_disconnected -= elapsed; + } + } + + if (ev_battery_level > 0) { + if (battery_level == 4) { + rgb_matrix_set_color(49, RGB_GREEN); + } else if (battery_level == 3) { + rgb_matrix_set_color(49, RGB_YELLOW); + } else if (battery_level == 2) { + rgb_matrix_set_color(49, RGB_ORANGE); + } else if (battery_level == 1) { + rgb_matrix_set_color(49, RGB_RED); + } else { + rgb_matrix_set_color(49, RGB_WHITE); + } + + if (elapsed >= ev_battery_level) { + ev_battery_level = 0; + battery_level = 0; + } else { + ev_battery_level -= elapsed; + } + } + +#endif + return true; +} + +bool dip_switch_update_user(uint8_t index, bool active) { + dprintf("DIP #%d: %d\n", index, active); + switch (index) { + case DIP_WIN_MAC: + if (active) { + layer_move(MAC_BASE); + } else { + layer_move(WIN_BASE); + } + return false; +#ifdef BLUETOOTH_ENABLE + case DIP_BT_EN: + dip_switch_bt_en = !active; + if (active) { + set_output(OUTPUT_USB); + } else { + iton_bt_init(); + set_output(OUTPUT_NONE); + } + return false; +#endif + } + return true; +} diff --git a/keyboards/keychron/k2/rgb/v2/ansi/keymaps/default/keymap.c b/keyboards/keychron/k2/rgb/v2/ansi/keymaps/default/keymap.c index 5455fb701901..5e5604ba1feb 100644 --- a/keyboards/keychron/k2/rgb/v2/ansi/keymaps/default/keymap.c +++ b/keyboards/keychron/k2/rgb/v2/ansi/keymaps/default/keymap.c @@ -17,17 +17,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include QMK_KEYBOARD_H +#include "keymap.h" + -// Each layer gets a name for readability, which is then used in the keymap matrix below. -// The underscores don't mean anything - you can have a layer called STUFF or any other name. -// Layer names don't all need to be of the same length, obviously, and you can also skip them -// entirely and just use numbers. -enum layer_names { - WIN_BASE = 0, - WIN_FN = 1, - MAC_BASE = 2, - MAC_FN = 3, -}; #define KC_TASK LGUI(KC_TAB) // Task viewer #define KC_FLXP LGUI(KC_E) // Windows file explorer @@ -81,11 +73,11 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { */ [WIN_FN] = LAYOUT_ansi( /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ - Q_RESET, KC_BRID, KC_BRIU, KC_TASK, KC_FLXP, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, _______, KC_INS, RGB_TOG , - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ , + QK_BOOT, KC_BRID, KC_BRIU, KC_TASK, KC_FLXP, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, _______, KC_INS, RGB_TOG , + KC_BTPAIR, KC_BTPROF0, KC_BTPROF1, KC_BTPROF2, _______, _______, _______, _______, _______, _______, _______, KC_BTRST, _______, _______, _______ , _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ , _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ , - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_SAI, _______ , + _______, _______, _______, _______, _______, KC_BTBATT, _______, _______, _______, _______, _______, _______, RGB_SAI, _______ , _______, _______, _______, _______, _______, _______, _______, RGB_HUD, RGB_SAD, RGB_HUI ), @@ -131,8 +123,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { */ [MAC_FN] = LAYOUT_ansi( /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ - Q_RESET, KC_BRID, KC_BRIU, KC_MSSN, KC_FIND, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, KC_MSNP, KC_INS, RGB_TOG , - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ , + QK_BOOT, KC_BRID, KC_BRIU, KC_MSSN, KC_FIND, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, KC_MSNP, KC_INS, RGB_TOG , + KC_BTPAIR, KC_BTPROF0, KC_BTPROF1, KC_BTPROF2, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ , _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ , _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ , _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_SAI, _______ , @@ -140,29 +132,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ) }; -bool dip_switch_update_user(uint8_t index, bool active) { - switch(index) { - case 0: // OS switch - if (active) { // Mac/iOS mode - layer_move(MAC_BASE); - } - else { // Windows/Android mode - layer_move(WIN_BASE); - } - break; - case 1: // Connection switch - // Probably it's not possible to do anything sensible here as switching from Cable to BT requires turning off the board. (BT / OFF / Cable) - if (active) { // BT mode - // do stuff - } - else { //Cable mode - // do stuff - } - break; - } - return true; -} - void keyboard_post_init_user(void) { // Customise these values to desired behaviour // debug_enable = true; diff --git a/keyboards/keychron/k2/rgb/v2/ansi/keymaps/default/keymap.h b/keyboards/keychron/k2/rgb/v2/ansi/keymaps/default/keymap.h new file mode 100644 index 000000000000..78bf82cc5626 --- /dev/null +++ b/keyboards/keychron/k2/rgb/v2/ansi/keymaps/default/keymap.h @@ -0,0 +1,41 @@ +/* +Copyright 2024 mintyleaf + +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 QMK_KEYBOARD_H + +/* Extended keycodes for controlling Bluetooth */ +enum BT_keycodes { + KC_BTPROF0 = SAFE_RANGE, // Set bluetooth profile 0 + KC_BTPROF1, // Set bluetooth profile 1 + KC_BTPROF2, // Set bluetooth profile 2 + KC_BTPAIR, // Start pairing mode + KC_BTTOGL, // Toggle bluetooth mode + KC_BTRST, // Reset bluetooth module + KC_BTBATT, // Show battery level + K2_SAFE_RANGE +}; + +enum layer_names { + WIN_BASE = 0, // Windows base layer + WIN_FN = 1, // Windows with FN key + MAC_BASE = 2, // Mac base layer + MAC_FN = 3, // Mac with FN key +}; + +#define KC_TASK LGUI(KC_TAB) // Task viewer +#define KC_FLXP LGUI(KC_E) // Windows file explorer +#define KC_MCTL KC_MISSION_CONTROL // Mission Control +#define KC_LPAD KC_LAUNCHPAD // Launchpad diff --git a/keyboards/keychron/k2/rgb/v2/ansi/keymaps/via/keymap.c b/keyboards/keychron/k2/rgb/v2/ansi/keymaps/via/keymap.c index 5455fb701901..8ecfb12ea96c 100644 --- a/keyboards/keychron/k2/rgb/v2/ansi/keymaps/via/keymap.c +++ b/keyboards/keychron/k2/rgb/v2/ansi/keymaps/via/keymap.c @@ -140,29 +140,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ) }; -bool dip_switch_update_user(uint8_t index, bool active) { - switch(index) { - case 0: // OS switch - if (active) { // Mac/iOS mode - layer_move(MAC_BASE); - } - else { // Windows/Android mode - layer_move(WIN_BASE); - } - break; - case 1: // Connection switch - // Probably it's not possible to do anything sensible here as switching from Cable to BT requires turning off the board. (BT / OFF / Cable) - if (active) { // BT mode - // do stuff - } - else { //Cable mode - // do stuff - } - break; - } - return true; -} - void keyboard_post_init_user(void) { // Customise these values to desired behaviour // debug_enable = true; diff --git a/keyboards/keychron/k2/rgb/v2/ansi/rules.mk b/keyboards/keychron/k2/rgb/v2/ansi/rules.mk new file mode 100644 index 000000000000..0e1d0de931f6 --- /dev/null +++ b/keyboards/keychron/k2/rgb/v2/ansi/rules.mk @@ -0,0 +1,4 @@ +BLUETOOTH_ENABLE = yes +BLUETOOTH_DRIVER = iton_bt +BLUETOOTH_ITON_BT = yes + diff --git a/keyboards/keychron/k2/rgb/v2/config.h b/keyboards/keychron/k2/rgb/v2/config.h index 5147b70a57e2..c7ce8c3b71d8 100644 --- a/keyboards/keychron/k2/rgb/v2/config.h +++ b/keyboards/keychron/k2/rgb/v2/config.h @@ -17,5 +17,18 @@ */ #pragma once + +/* RGB defines */ #define SN32F2XX_RGB_MATRIX_ROW_PINS { C3, C1, C0, C6, C5, C4, C9, C8, C7, C12, C11, C10, B13, C14, C13, B14, B15, D3 } + +/* DIP switch defines */ +#define DIP_BT_EN (1) // 0: Disable, 1: Enable +#define DIP_WIN_MAC (0) // 0: Windows, 1: Mac #define DIP_SWITCH_PINS { D4, D5 } + +/* Bluetooth defines */ +#define ITON_BT_ENABLE_ACK +#define BLUETOOTH_MANUAL_INIT + +/* QMK defines */ +#define DYNAMIC_KEYMAP_LAYER_COUNT 4 diff --git a/keyboards/keychron/k2/rgb/v2/halconf.h b/keyboards/keychron/k2/rgb/v2/halconf.h new file mode 100644 index 000000000000..b6564c6d5fd9 --- /dev/null +++ b/keyboards/keychron/k2/rgb/v2/halconf.h @@ -0,0 +1,29 @@ +// Copyright 2021 1Conan (@1Conan) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#ifdef BLUETOOTH_ITON_BT +/* + * GPIO and SPI IRQs needs to be set to 0 to avoid erratic behavior + */ + +/** + * PAL driver settings + */ +# define PAL_USE_CALLBACKS TRUE +# define SN32_GPIOA_IRQ_PRIORITY 0 + +/** + * SPI driver settings + */ +# define HAL_USE_SPI TRUE +# define SPI_USE_MUTUAL_EXCLUSION FALSE +# define SPI_USE_WAIT FALSE +# define SPI_USE_ASSERT_ON_ERROR FALSE +# define SPI_SELECT_MODE SPI_SELECT_MODE_NONE + +# define SN32_SPI_SPI0_IRQ_PRIORITY 0 +#endif + +#include_next \ No newline at end of file diff --git a/keyboards/keychron/k2/rgb/v2/mcuconf.h b/keyboards/keychron/k2/rgb/v2/mcuconf.h new file mode 100644 index 000000000000..a9c4f1936fd7 --- /dev/null +++ b/keyboards/keychron/k2/rgb/v2/mcuconf.h @@ -0,0 +1,12 @@ +// Copyright 2021 1Conan (@1Conan) +// SPDX-License-Identifier: GPL-2.0-or-later + +/** + * SPI driver settings + */ +#ifdef BLUETOOTH_ITON_BT +# define SN32_SPI_USE_SPI0 TRUE +# define SN32 +#endif + +#include_next \ No newline at end of file diff --git a/platforms/chibios/boards/SN_SN32F240B/board/board.mk b/platforms/chibios/boards/SN_SN32F240B/board/board.mk index b3cf15dd678c..77cb01c43a1c 100644 --- a/platforms/chibios/boards/SN_SN32F240B/board/board.mk +++ b/platforms/chibios/boards/SN_SN32F240B/board/board.mk @@ -11,6 +11,12 @@ OPT_DEFS += -DCORTEX_ENABLE_WFI_IDLE=TRUE # Shave some extra bytes OPT_DEFS += -DCRT1_AREAS_NUMBER=1 +# Some options to reduce RAM usage +# USE_LINK_GC = yes +# LTO_ENABLE = yes + +# OPT = s + # Shared variables ALLCSRC += $(BOARDSRC) ALLINC += $(BOARDINC)