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)