diff --git a/keyboards/redragon/k715_pro/bluetooth/bluetooth.mk b/keyboards/redragon/k715_pro/bluetooth/bluetooth.mk new file mode 100644 index 00000000000..ebda4b804e2 --- /dev/null +++ b/keyboards/redragon/k715_pro/bluetooth/bluetooth.mk @@ -0,0 +1,9 @@ + +BLUETOOTH_DIR = bluetooth +SRC += \ + $(BLUETOOTH_DIR)/bluetooth_main.c \ + $(BLUETOOTH_DIR)/btfunc.c \ + $(BLUETOOTH_DIR)/btspi.c \ + $(BLUETOOTH_DIR)/btsys.c + +VPATH += $(TOP_DIR)/keyboards/redragon/k715_pro/$(BLUETOOTH_DIR) diff --git a/keyboards/redragon/k715_pro/bluetooth/bluetooth_main.c b/keyboards/redragon/k715_pro/bluetooth/bluetooth_main.c new file mode 100644 index 00000000000..6486ca3e954 --- /dev/null +++ b/keyboards/redragon/k715_pro/bluetooth/bluetooth_main.c @@ -0,0 +1,31 @@ +/* Copyright 2024 temp4gh + * + * 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" + +__attribute__((weak)) void bluetooth_pre_task(void) {} +__attribute__((weak)) void bluetooth_task(void) {} +__attribute__((weak)) void bluetooth_post_task(void) {} + +void bluetooth_tasks(void) { + bluetooth_pre_task(); + bluetooth_task(); + bluetooth_post_task(); +} + +void housekeeping_task_kb(void) { + bluetooth_tasks(); +} diff --git a/keyboards/redragon/k715_pro/bluetooth/btfunc.c b/keyboards/redragon/k715_pro/bluetooth/btfunc.c new file mode 100644 index 00000000000..8a38de228c4 --- /dev/null +++ b/keyboards/redragon/k715_pro/bluetooth/btfunc.c @@ -0,0 +1,78 @@ +/* Copyright 2023 temp4gh + * + * 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 +#include "quantum.h" +#include "btfunc.h" +#include "btspi.h" +#include "k715_pro.h" + +extern user_settings_config g_config; +extern tDevInfo dev_info; + +void k715bt_send_ble_req_bt_info(void) +{ + k715bt_send_spi_extend_single_packet(KBD_CMD_GET_INFO, NULL, 0); +} + +void k715bt_send_ble_req_bt_name(void) +{ + k715bt_send_spi_extend_single_packet(KBD_CMD_BT_GETNAME, NULL, 0); +} + +void k715bt_send_mcu_req_ble_fwver(void) +{ + k715bt_send_spi_extend_single_packet(KBD_CMD_MCU_REQ_BT_FWVER, NULL, 0); +} + +void k715bt_send_ble_switch_device_mode(uint8_t mode) +{ + k715bt_send_spi_extend_single_packet(KBD_CMD_MODE_SET, &mode, 1); +} + +void k715bt_send_ble_pair(uint8_t pair_timeout, uint8_t *adv_data, uint8_t adv_data_len) +{ + k715bt_send_spi_extend_single_packet(KBD_CMD_BT_PAIR, NULL, 0); +} + +void k715bt_send_ble_reconnect_bt(uint8_t reconn_timeout) +{ + k715bt_send_spi_extend_single_packet(KBD_CMD_BT_BACK, &reconn_timeout, 1); +} + +void k715bt_send_ble_disconnect_bt(void) +{ + k715bt_send_spi_extend_single_packet(KBD_CMD_BT_DISCONNECT, NULL, 0); +} + +void k715bt_send_ble_set_device_name(uint8_t *dev_name, uint8_t dev_name_len) +{ + k715bt_send_spi_extend_single_packet(KBD_CMD_BT_SETNAME, dev_name, dev_name_len); +} + +void k715bt_send_ble_set_bt_channel(uint8_t bt_channel) +{ + k715bt_send_spi_extend_single_packet(KBD_CMD_BT_SETCHN, &bt_channel, 1); +} + +void k715bt_switch_channel(uint8_t bt_channel) +{ + if(g_config.bt_ch != bt_channel) + { + k715bt_send_ble_set_bt_channel(bt_channel); + g_config.bt_ch = bt_channel; + } +} diff --git a/keyboards/redragon/k715_pro/bluetooth/btfunc.h b/keyboards/redragon/k715_pro/bluetooth/btfunc.h new file mode 100644 index 00000000000..0cf8dfa99d9 --- /dev/null +++ b/keyboards/redragon/k715_pro/bluetooth/btfunc.h @@ -0,0 +1,30 @@ +/* Copyright 2023 temp4gh + * + * 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 "stdint.h" + +void k715bt_send_ble_req_bt_info(void); +void k715bt_send_ble_req_bt_name(void); +void k715bt_send_mcu_req_ble_fwver(void); +void k715bt_send_ble_set_device_name(uint8_t *dev_name, uint8_t dev_name_len); +void k715bt_send_ble_switch_device_mode(uint8_t mode); +void k715bt_send_ble_set_bt_channel(uint8_t bt_channel); +void k715bt_send_ble_pair(uint8_t pair_timeout, uint8_t *adv_data, uint8_t adv_data_len); +void k715bt_send_ble_reconnect_bt(uint8_t reconn_timeout); +void k715bt_send_ble_disconnect_bt(void); +void k715bt_switch_channel(uint8_t bt_channel); diff --git a/keyboards/redragon/k715_pro/bluetooth/btspi.c b/keyboards/redragon/k715_pro/bluetooth/btspi.c new file mode 100644 index 00000000000..4875f360421 --- /dev/null +++ b/keyboards/redragon/k715_pro/bluetooth/btspi.c @@ -0,0 +1,1231 @@ +/* Copyright 2024 temp4gh + * + * 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 +#include "spi_master.h" +#include "host_driver.h" +#include "k715_pro.h" +#include "btspi.h" +#include "btfunc.h" + +#define SPI_SLAVE_NOTIFY_CMD_RETURN_VALUE (0xAAAABBBB) + +#define print_log(fmt,...) do{}while(0) + +static uint8_t spi_inited = 0; +static uint8_t last_device_mode = INVALID_DIP_DEVICE_MODE; +static uint8_t now_mode = KBD_BT_MODE; +static uint8_t kbd_dev_mode; +static uint8_t dev_mode_detect; +static uint8_t mode_bt_state = 0; +tDevInfo dev_info; + +static spi_read_data_t spi_salve_data; +user_settings_config g_config; + +#define now_ms timer_read32() +#define get_time_ms() timer_read32() + +static void spi_slave_start(void) +{ + spi_start(SPI_SLAVE_CS, false, SPI_MODE, SPI_DIVISOR); + wait_us(200); +} + +static void spi_slave_stop(void) +{ + spi_stop(); +} + +static bool check_dip_switch_usb_mode_enabled(void) +{ + palSetLineMode(EXT_READ_DIP_PIN_USB_MODE, PAL_MODE_INPUT_PULLUP); + if(palReadLine(EXT_READ_DIP_PIN_USB_MODE) == PAL_LOW) + { + return true; + } + + return false; +} + +static bool check_dip_switch_bt_mode_enabled(void) +{ + palSetLineMode(EXT_READ_DIP_PIN_BT_MODE, PAL_MODE_INPUT_PULLUP); + if(palReadLine(EXT_READ_DIP_PIN_BT_MODE) == PAL_LOW) + { + return true; + } + + return false; +} + +static uint8_t check_dip_device_mode(uint8_t debug_flag) +{ + uint8_t ret, reboot; + + reboot = 0; + + if(check_dip_switch_bt_mode_enabled()) + { + ret = KBD_BT_MODE; + } + else if(check_dip_switch_usb_mode_enabled()) + { + ret = KBD_USB_MODE; + } + else + { + ret = KBD_POWEROFF_MODE; + } + + if(last_device_mode == INVALID_DIP_DEVICE_MODE) + { + last_device_mode = ret; + } + else + { + if(last_device_mode != ret) + { + last_device_mode = ret; + reboot = 1; + } + } + + if(reboot) + { + wait_ms(100); + mcu_reset(); + } + + return ret; +} + +static uint8_t get_dev_mode_detected(void) +{ + return(dev_mode_detect); +} + +static void init_ext_read_spi_slave_gpio(void) +{ + palSetLineMode(EXT_READ_SPI_SLAVE_INT_PIN, EXT_READ_SPI_SLAVE_GPIO_INIT); +} + +static void set_IS31FL3733_normal_mode(void) +{ + palSetLineMode(EXT_IS31FL3733_SUSPEND_PIN, PAL_MODE_OUTPUT_PUSHPULL); + palSetLine(EXT_IS31FL3733_SUSPEND_PIN); +} + +static void init_dev_info(void) +{ + memset(&dev_info, 0, sizeof(dev_info)); +} + +static uint8_t ble_spi_notify_cmd_buf[MAX_BLE_SPI_NOTIFY_CMD_BUF_SIZE + 4]; +static uint8_t get_ble_spi_notify_cmd(void) +{ + return(ble_spi_notify_cmd_buf[2]); +} + +static uint8_t *get_ble_spi_notify_cmd_data(void) +{ + return(&(ble_spi_notify_cmd_buf[3])); +} + +static void set_ble_spi_notify_cmd_data_header(uint8_t cmd, uint8_t len) +{ + ble_spi_notify_cmd_buf[0] = SPI_BLE_PACKET_HEADER; + ble_spi_notify_cmd_buf[1] = len + 1; + ble_spi_notify_cmd_buf[2] = cmd; +} + +uint8_t get_ble_spi_notify_cmd_data_length(void) +{ + return(ble_spi_notify_cmd_buf[1]); +} + +uint8_t *get_ble_spi_notify_data(void) +{ + return(ble_spi_notify_cmd_buf); +} + +uint8_t buffer_get_sum(uint8_t *buf, int len) +{ + int i; + uint8_t chksum = 0; + + for(i = 1; i < len; i++) + { + chksum += buf[i]; + } + + return chksum; +} + +int ble_spi_req_recv(uint8_t cmd, uint8_t *buf, uint8_t len, uint8_t send_req_flag) +{ + uint8_t data[MAX_BLE_SPI_RX_FRAME_MAX_SIZE]; + int ret; + int i = 0; + uint8_t next_sn, rx_len; + int sum_err = 0; + uint8_t length; + + spi_use_begin(); + if(buf) + { + memset(buf, 0, len); + } + + if(cmd == KBD_CMD_GET_INFO) + { + k715bt_send_ble_req_bt_info(); + wait_ms(10); + } + else if(cmd == KBD_CMD_BT_GETNAME) + { + k715bt_send_ble_req_bt_name(); + wait_ms(10); + } + else if(cmd == KBD_CMD_MCU_REQ_BT_FWVER) + { + k715bt_send_mcu_req_ble_fwver(); + wait_ms(10); + } + else + { + k715bt_send_ble_req_bt_info(); + wait_ms(10); + } + + spi_slave_start(); + + length = MAX_BLE_SPI_RX_FRAME_MAX_SIZE; + next_sn = 1; + rx_len = 0; + +__SPI_RECEIVE: + memset(data, 0, sizeof(data)); + ret = -1; + + ret = spi_receive(data, length); + if(ret == SPI_STATUS_SUCCESS) + { + i = length; + if(data[0] == SPI_BLE_PACKET_HEADER) + { + if((data[1] == 0) || (data[1] > MAX_SPI_BLE_SINGLE_PACKET_LOAD_LENGTH)) + { + sum_err = 0xF0; + } + else + { + if(data[length - 1] == buffer_get_sum(&data[0], length - 1)) + { + if((cmd == KBD_CMD_UNKNOW) || ((data[2] & 0x7f) == cmd)) + { + if((data[2] & 0x80) == 0x80) + { + if((data[3] & 0x7F) == next_sn) + { + next_sn += 1; + + i = data[1] - 2; + if((rx_len + i) >= len) + { + sum_err = 0; + goto __EXIT; + } + + if((i > 0) && (i < MAX_BLE_SPI_RX_FRAME_MAX_SIZE)) + { + memcpy(&buf[rx_len], &data[4], i); + } + + rx_len += i; + + if((data[3] & 0x80) == 0x80) + { + cmd = data[2] & 0x7F; + } + else + { + goto __SPI_RECEIVE; + } + } + else + { + sum_err = 0xF2; + goto __EXIT; + } + } + else + { + len = MIN(len, (data[1] - 1)); + if(len) + { + + memcpy(buf, &data[3], len); + rx_len += len; + } + + if(cmd == KBD_CMD_UNKNOW) + { + cmd = data[2]; + } + + } + + sum_err = 0; + } + else + { + sum_err = 0xF1; + } + } + else + { + sum_err = 2; + } + } + } + else + { + sum_err = 0xFF; + } + } + else + { + sum_err = 3; + } + +__EXIT: + spi_slave_stop(); + spi_use_end(); + + if(sum_err) + { + return 0; + } + else + { + set_ble_spi_notify_cmd_data_header((data[2] & 0x7f), rx_len); + return(data[2] & 0x7f); + } +} + +static volatile uint8_t ble_spi_rx_reading = 0; +bool is_ble_spi_rx_reading(void) +{ + return(ble_spi_rx_reading); +} + +void set_ble_spi_rx_reading(uint8_t val) +{ + ble_spi_rx_reading = val; +} + +uint8_t ble_spi_read_dev_info(uint8_t cmd, uint8_t send_req_flag) +{ + uint8_t len = MAX_SPI_BLE_SINGLE_PACKET_LENGTH; + uint8_t cnt = 0; + spi_slave_dev_info_t dinf; + int ret = 0; + + set_ble_spi_rx_reading(1); + + memset(&dinf, 0, sizeof(dinf)); + if(cmd == KBD_CMD_GET_INFO) + { + ret = 0; + len = MAX_SPI_BLE_SINGLE_PACKET_LENGTH; + while(ret != cmd) + { + ret = ble_spi_req_recv(cmd, (uint8_t *)&dinf, len, send_req_flag); + if(ret == cmd) + { + break; + } + + if(++cnt < 20) + { + wait_ms(20); + } + else + { + cmd = KBD_CMD_INVALID; + goto __BLE_RX_EXIT; + } + } + + if(cmd == KBD_CMD_GET_INFO) + { + goto __SPI_RX_DEV_INFO; + } + else + { + goto __BLE_RX_EXIT; + } + } + else + { + uint8_t *rx_ptr; + + ret = 0; + memset(ble_spi_notify_cmd_buf, 0, sizeof(ble_spi_notify_cmd_buf)); + rx_ptr = (uint8_t *) & (ble_spi_notify_cmd_buf[3]); + len = MAX_BLE_SPI_NOTIFY_CMD_BUF_SIZE - 3; + while(ret == 0) + { + ret = ble_spi_req_recv(cmd, rx_ptr, len, send_req_flag); + if(ret) + { + break; + } + + if(++cnt < 20) + { + wait_ms(20); + } + else + { + cmd = KBD_CMD_INVALID; + goto __BLE_RX_EXIT; + } + } + + if(get_ble_spi_notify_cmd() == KBD_CMD_GET_INFO) + { + memcpy((uint8_t *)&dinf, rx_ptr, MAX_SPI_BLE_SINGLE_PACKET_LENGTH); + goto __SPI_RX_DEV_INFO; + } + + cmd = get_ble_spi_notify_cmd(); + goto __BLE_RX_EXIT; + } + +__SPI_RX_DEV_INFO: + spi_salve_data.spi_read_length = sizeof(dinf); + memcpy(spi_salve_data.spi_read_buf, (uint8_t *)&dinf, sizeof(dinf)); + + if(is_bt_mode_enabled()) + { + dev_info.CapsLock = dinf.CapsLock; + dev_info.NumLock = dinf.NumLock; + dev_info.ScrollLock = dinf.ScrollLock; + + update_caps_led(); + } + + dev_info.usbstate = dinf.state_usb; + if(dinf.mode != 0xff) + { + dev_info.btstate = dinf.state_bt; + dev_info.devmode = dinf.mode; + } + + if(dinf.state_bt == BTSTATECONNECTED) + { + dev_info.btconnected = 1; + } + else + { + dev_info.btconnected = 0; + } + + if(dinf.ch != 0xff) + { + if(g_config.bt_ch != dinf.ch) + { + g_config.bt_ch = dinf.ch; + } + } + + cmd = KBD_CMD_GET_INFO; + +__BLE_RX_EXIT: + set_ble_spi_rx_reading(0); + return(cmd); +} + +static int get_caps_state(void) +{ + int onoff; + + onoff = -1; + if(now_mode == KBD_POWEROFF_MODE) + { + return 0; + } + + if(is_bt_mode_enabled()) + { + onoff = dev_info.CapsLock; + } + else + { + if(is_usb_mode_enabled()) + { + if(host_keyboard_led_state().caps_lock) + { + onoff = 1; + } + else + { + onoff = 0; + } + } + } + + return(onoff); +} + +void update_caps_led(void) +{ + int onoff; + + if(now_mode == KBD_POWEROFF_MODE) + { + return; + } + + onoff = get_caps_state(); + if(onoff == 1) + { + set_caps_lock_on(); + } + else if(onoff == 0) + { + set_caps_lock_off(); + } +} + +int ble_spi_read_and_update_dev_mode(void) +{ + int ret; + unsigned short cnt; + + cnt = 0; + while(1) + { + ret = ble_spi_read_dev_info(KBD_CMD_GET_INFO, 1); + if(ret == KBD_CMD_INVALID) + { + wait_ms(100); + } + else + { + uint8_t mode; + + mode = get_dev_mode_detected(); + if(dev_info.devmode != mode) + { + k715bt_send_ble_switch_device_mode(mode); + wait_ms(200); + cnt &= 0xff00; + cnt += 0x100; + if(cnt > 0xa00) + { + ret = -1; + break; + } + } + else + { + ret = 0; + break; + } + } + + if(((++cnt) & 0xff) >= 10) + { + + ret = -2; + break; + } + } + + return ret; +} + +bool is_poweroff_mode_enabled(void) +{ + if(now_mode == KBD_POWEROFF_MODE) + { + return(true); + } + + return false; +} + +static int ble_spi_send(uint8_t cmd, uint8_t *buf, uint8_t len) +{ + int mul = 0; + uint8_t data[MAX_BLE_SPI_TX_FRAME_MAX_SIZE], s = len; + + memset(data, 0, sizeof(data)); + while(len || (buf == NULL && len == 0)) + { + int i = 0; + + data[i++] = SPI_BLE_PACKET_HEADER; + if(len > MAX_SPI_BLE_SINGLE_PACKET_LENGTH || mul) + { + mul++; + if(len > MAX_SPI_BLE_MUL_PACKET_LENGTH) + { + data[i++] = MAX_SPI_BLE_MUL_PACKET_LENGTH + 2; + data[i++] = cmd | 0x80; + data[i++] = mul; + s = MAX_SPI_BLE_MUL_PACKET_LENGTH; + } + else + { + data[i++] = len + 2; + data[i++] = cmd | 0x80; + data[i++] = mul | 0x80; + s = len; + } + } + else + { + data[i++] = len + 1; + data[i++] = cmd; + s = len; + } + + if(buf && s) + { + memcpy(&data[i], buf, s); + } + + data[s + i] = buffer_get_sum(data, s + i); + + spi_slave_start(); + spi_transmit(data, s + i + 1); + spi_slave_stop(); + + if(len >= s) + { + len -= s; + if(len) + { + wait_us(200); + } + } + + if(len == 0) + { + break; + } + + if(buf) + { + buf += s; + } + } + + return 0; +} + +void k715bt_send_spi_extend_single_packet(uint8_t param_type, uint8_t *param_data, uint8_t param_len) +{ + if(is_poweroff_mode_enabled()) + { + return; + } + + if(is_ble_spi_rx_reading()) + { + uint8_t loop_count = 0; + while(1) + { + wait_ms(2); + if(!is_ble_spi_rx_reading() || (++loop_count >= 20)) + { + break; + } + } + } + + if(spi_inited) + { + ble_spi_send(param_type, param_data, param_len); + } +} + +static void init_user_settings(void) +{ + memset(&g_config, 0, sizeof(g_config)); + + g_config.magic_num = KB_MAGIC_NUMBER; + g_config.kbd_dev_mode = 0xFF; + g_config.bt_ch = BT_CHANNEL_1; + g_config.bt_last_connected = BT_CHANNEL_INVALID; +} + +static int req_ble_exchange(uint8_t req_cmd, uint8_t ack_cmd, uint8_t *data, uint8_t len) +{ + int ret = 0; + uint8_t read_count = 0; + +__LOOP_READ_CMD: + memset(data, 0, len); + ret = ble_spi_req_recv(req_cmd, data, len, 1); + if(ret != ack_cmd) + { + read_count++; + if(read_count < 20) + { + wait_ms(20); + goto __LOOP_READ_CMD; + } + else + { + memset(data, 0, len); + } + } + else + { + ret = 1; + } + + return ret; +} + +#define BT_FW_VERINFO_LEN 19 +static uint8_t bt_mac_addr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +static uint8_t bt_fw_verinfo[BT_FW_VERINFO_LEN + 1] = {0}; + +uint8_t *get_bt_mac_addr(void) +{ + return(bt_mac_addr); +} + +uint8_t *get_bt_fw_verinfo(uint8_t *len) +{ + *len = BT_FW_VERINFO_LEN; + return(bt_fw_verinfo); +} + +int init_req_bt_ver(void) +{ + int ret; + uint8_t data[48]; + + ret = req_ble_exchange(KBD_CMD_MCU_REQ_BT_FWVER, KBD_CMD_MCU_REQ_BT_FWVER, data, sizeof(data)); + if(ret) + { + memset(bt_fw_verinfo, 0, sizeof(bt_fw_verinfo)); + memcpy(bt_fw_verinfo, data, BT_FW_VERINFO_LEN); + memcpy(bt_mac_addr, &(data[BT_FW_VERINFO_LEN]), 6); + + print_log("BT fw version:%s\r\n", bt_fw_verinfo); + print_log("BT addr:%02X:%02X:%02X:%02X:%02X:%02X\r\n", bt_mac_addr[0], bt_mac_addr[1], \ + bt_mac_addr[2], bt_mac_addr[3], \ + bt_mac_addr[4], bt_mac_addr[5]); + } + + return 0; +} + +uint8_t get_active_bt_chn(void) +{ + return(g_config.bt_ch); +} + +#define DEFAULT_BT_NAME "BLE Keyboard" +void send_bt_name_with_chn(uint8_t chn) +{ + k715bt_send_ble_set_device_name((uint8_t *)DEFAULT_BT_NAME, strlen(DEFAULT_BT_NAME)); +} + +void ble_mark_bt_disconnected(void) +{ + dev_info.btconnected = 0; +} + +void set_dev_info_bt_timeout(uint32_t timeout, int flag) +{ + if(timeout == 0) + { + if(flag) + { + dev_info.bt_timeout = timeout; + } + else + { + dev_info.bt_timeout = BT_BP_TIMEOUT - RF_TIMEOUT_OFFSET + get_time_ms(); + } + } + else + { + dev_info.bt_timeout = timeout; + } +} + +void set_dev_info_bt_pair_timeout(void) +{ + set_dev_info_bt_timeout(0, 0); +} + +void set_dev_info_bt_reconn_timeout(void) +{ + set_dev_info_bt_timeout(BT_BACK_TIMEOUT - RF_TIMEOUT_OFFSET + get_time_ms(), 1); +} + +int sys_tk_diff(uint32_t now, uint32_t start_time, int flag) +{ + int ret; + + if(now > start_time) + { + ret = 10; + } + else + { + ret = timer_elapsed32(start_time); + } + + if(ret >= 10) + { + return 1; + } + + return 0; +} + +bool is_bt_mode_enabled(void) +{ + if(mode_bt_state) + { + return true; + } + + return false; +} + +bool is_usb_mode_enabled(void) +{ + if(now_mode == KBD_USB_MODE) + { + return true; + } + + return false; +} + +static uint8_t last_spi_notify_line_level = 0xFF; +void invlaid_read_spi_slave_line(void) +{ + last_spi_notify_line_level = EXT_READ_SPI_SLAVE_READY; +} + +int check_read_spi_slave_line(void) +{ + uint8_t line_level; + int ret = 0; + + line_level = palReadLine(EXT_READ_SPI_SLAVE_INT_PIN); + if(line_level != last_spi_notify_line_level) + { + if(last_spi_notify_line_level != 0xFF) + { + last_spi_notify_line_level = line_level; + if(line_level == EXT_READ_SPI_SLAVE_READY) + { + ret = 1; + } + } + else + { + last_spi_notify_line_level = line_level; + if(line_level == EXT_READ_SPI_SLAVE_READY) + { + ret = 1; + } + } + } + + return ret; +} + +static void send_mcu_fwver_to_ble(void) +{ + uint8_t buf[14]; + + memset(buf, 0, sizeof(buf)); + + sprintf((char *)buf, "%d.%d.%d", (DEVICE_VER >> 8) & 0x000F, (DEVICE_VER >> 4) & 0x000F, DEVICE_VER & 0x000F); + k715bt_send_spi_extend_single_packet(KBD_CMD_SEND_BT_MCU_FWVER, buf, strlen((char *)buf)); +} + +void ble_spi_slave_cmd_notify(void) +{ + uint8_t rx_cmd; + uint8_t *rx_data; + + rx_cmd = get_ble_spi_notify_cmd(); + rx_data = get_ble_spi_notify_cmd_data(); + + switch(rx_cmd) + { + case KBD_CMD_MCU_RECV_BT_FWVER: + { + uint8_t offset = BT_FW_VERINFO_LEN; + + memset(bt_fw_verinfo, 0, sizeof(bt_fw_verinfo)); + memcpy(bt_fw_verinfo, rx_data, sizeof(bt_fw_verinfo) - 1); + memcpy(bt_mac_addr, &(rx_data[offset]), 6); + + print_log("BT fw version:%s\r\n", bt_fw_verinfo); + print_log("BT addr:%02X:%02X:%02X:%02X:%02X:%02X\r\n", bt_mac_addr[0], bt_mac_addr[1], \ + bt_mac_addr[2], bt_mac_addr[3], \ + bt_mac_addr[4], bt_mac_addr[5]); + + break; + } + + case KBD_CMD_BT_REQ_MCU_FWVER: + { + send_mcu_fwver_to_ble(); + break; + } + + default: + { + break; + } + } +} + +uint32_t ble_spi_slave_data_decode(uint32_t mode_set_timeout) +{ + uint8_t state_before_sleep; + uint32_t last_key_ms; + + if(now_ms > mode_set_timeout) + { + uint8_t cmd; + + cmd = ble_spi_read_dev_info(KBD_CMD_UNKNOW, 0); + + if(cmd == KBD_CMD_INVALID) + { + return 0xFFFFFFFF; + } + + + if(cmd != KBD_CMD_GET_INFO) + { + return SPI_SLAVE_NOTIFY_CMD_RETURN_VALUE; + } + + mode_set_timeout = 0xffffffff; + { + if(dev_info.devmode == KBD_BT_MODE) + { + char b = dev_info.btback; + char p = dev_info.btpair; + + if(g_config.bt_ch == 0) + { + g_config.bt_ch = BT_CHANNEL_1; + } + + if(dev_info.btstate == BTSTATEDISCONN) + { + ble_mark_bt_disconnected(); + if(dev_info.bt_timeout && sys_tk_diff(now_ms, dev_info.bt_timeout, 0) && (p || b)) + { + dev_info.bt_timeout = 0; + if(dev_info.btback) + { + dev_info.btback = 0; + } + + if(dev_info.btpair) + { + dev_info.btpair = 0; + if(g_config.bt_last_connected == g_config.bt_ch) + { + if(g_config.bt_used & (1 << (g_config.bt_ch - 1))) + { + dev_info.btback = 1; + k715bt_send_ble_reconnect_bt(BT_BACK_TIMEOUT / 1000); + set_dev_info_bt_reconn_timeout(); + } + } + } + } + else if(p && dev_info.bt_timeout) + { + dev_info.btpair = 1; + k715bt_send_ble_pair(BT_BP_TIMEOUT / 1000, NULL, 0); + } + else if(b && dev_info.bt_timeout) + { + dev_info.btback = 1; + k715bt_send_ble_reconnect_bt(BT_BACK_TIMEOUT / 1000); + } + else + { + if(g_config.bt_used & (1 << (g_config.bt_ch - 1))) + { + dev_info.btback = 1; + dev_info.btpair = 0; + k715bt_send_ble_reconnect_bt(BT_BACK_TIMEOUT / 1000); + set_dev_info_bt_reconn_timeout(); + } + else + { + dev_info.btpair = 1; + dev_info.btback = 0; + k715bt_send_ble_pair(BT_BP_TIMEOUT / 1000, NULL, 0); + set_dev_info_bt_pair_timeout(); + } + last_key_ms = now_ms; + } + + if((dev_info.btpair || dev_info.btback) != (b || p)) + { + mode_set_timeout = now_ms + 2000; + } + } + else if(dev_info.btstate == BTSTATEDISCOVER) + { + state_before_sleep = dev_info.btstate; + ble_mark_bt_disconnected(); + + if(dev_info.btpair == 0) + { + dev_info.btpair = 1; + if(dev_info.bt_timeout == 0) + { + set_dev_info_bt_pair_timeout(); + last_key_ms = now_ms; + } + } + + dev_info.btback = 0; + } + else if(dev_info.btstate == BTSTATECONNECTED) + { + last_key_ms = now_ms; + state_before_sleep = dev_info.btstate; + if((g_config.bt_used & (1 << (g_config.bt_ch - 1))) == 0 + && dev_info.btback == 0 + && dev_info.btpair == 0) + { + ble_mark_bt_disconnected(); + + dev_info.btpair = 1; + k715bt_send_ble_pair(BT_BP_TIMEOUT / 1000, NULL, 0); + set_dev_info_bt_pair_timeout(); + } + else + { + b = g_config.bt_used; + last_key_ms = get_time_ms(); + + dev_info.btback = 0; + dev_info.btpair = 0; + dev_info.bt_timeout = 0; + dev_info.btconnected = 1; + g_config.bt_last_connected = g_config.bt_ch; + g_config.bt_used |= (1 << (g_config.bt_ch - 1)); + } + } + else if(dev_info.btstate == BTSTATERECONN) + { + state_before_sleep = dev_info.btstate; + ble_mark_bt_disconnected(); + + if(dev_info.btback == 0) + { + if((g_config.bt_used & (1 << (g_config.bt_ch - 1))) == 0) + { + dev_info.btpair = 1; + k715bt_send_ble_pair(BT_BP_TIMEOUT / 1000, NULL, 0); + set_dev_info_bt_pair_timeout(); + } + else + { + dev_info.btback = 1; + if(dev_info.bt_timeout == 0) + { + set_dev_info_bt_reconn_timeout(); + } + + dev_info.btpair = 0; + } + } + } + } + } + } + + (void)state_before_sleep; + (void)last_key_ms; + + return 0; +} + +void check_read_spi_data(void) +{ + if(!is_bt_mode_enabled()) + { + return; + } + + if(check_read_spi_slave_line()) + { + uint32_t ret = 0; + + ret = ble_spi_slave_data_decode(0); + if(ret == SPI_SLAVE_NOTIFY_CMD_RETURN_VALUE) + { + ble_spi_slave_cmd_notify(); + invlaid_read_spi_slave_line(); + } + else if(ret != 0xFFFFFFFF) + { + invlaid_read_spi_slave_line(); + } + } +} + +void k715_bt_start_pair(uint8_t chn) +{ + ble_mark_bt_disconnected(); + + k715bt_switch_channel(chn); + + dev_info.btpair = 1; + dev_info.btback = 0; + set_dev_info_bt_pair_timeout(); + k715bt_send_ble_pair(BT_BP_TIMEOUT_MS, NULL, 0); +} + +void k715_ble_spi_init(void) +{ + spi_init(); + spi_inited = 1; + + wait_ms(500); + + dev_mode_detect = check_dip_device_mode(1); + now_mode = dev_mode_detect; + + init_ext_read_spi_slave_gpio(); + + init_user_settings(); + kbd_dev_mode = g_config.kbd_dev_mode; + + if(now_mode == KBD_BT_MODE) + { + mode_bt_state = 1; + } + else + { + mode_bt_state = 0; + } + + init_dev_info(); + wait_ms(500); + set_IS31FL3733_normal_mode(); + + if(now_mode != KBD_POWEROFF_MODE) + { + ble_spi_read_and_update_dev_mode(); + } + + init_req_bt_ver(); + + if(now_mode == KBD_BT_MODE) + { + send_bt_name_with_chn(get_active_bt_chn()); + wait_ms(20); + } + + if(now_mode != KBD_POWEROFF_MODE) + { + k715bt_send_ble_switch_device_mode(now_mode); + if(now_mode != kbd_dev_mode) + { + if(now_mode == KBD_BT_MODE) + { + wait_ms(500); + } + } + } + + if(now_mode != kbd_dev_mode) + { + kbd_dev_mode = now_mode; + g_config.kbd_dev_mode = kbd_dev_mode; + } + + if(now_mode != KBD_USB_MODE) + { + if(now_mode == KBD_BT_MODE) + { + if(g_config.bt_used & (1 << (g_config.bt_ch - 1))) + { + if(!dev_info.btconnected) + { + ble_mark_bt_disconnected(); + + k715bt_send_ble_set_bt_channel(g_config.bt_ch); + wait_ms(20); + + dev_info.btback = 1; + dev_info.btpair = 0; + k715bt_send_ble_reconnect_bt(BT_BACK_TIMEOUT / 1000); + set_dev_info_bt_reconn_timeout(); + } + else + { + uint8_t b; + + b = g_config.bt_used; + dev_info.btback = 0; + dev_info.btpair = 0; + dev_info.bt_timeout = 0; + dev_info.btconnected = 1; + g_config.bt_last_connected = g_config.bt_ch; + g_config.bt_used |= (1 << (g_config.bt_ch - 1)); + + if(b != g_config.bt_used) + { + } + } + } + else + { + ble_mark_bt_disconnected(); + + k715bt_send_ble_set_bt_channel(g_config.bt_ch); + wait_ms(20); + + dev_info.btpair = 1; + dev_info.btback = 0; + k715bt_send_ble_pair(BT_BP_TIMEOUT / 1000, NULL, 0); + set_dev_info_bt_pair_timeout(); + } + } + } +} diff --git a/keyboards/redragon/k715_pro/bluetooth/btspi.h b/keyboards/redragon/k715_pro/bluetooth/btspi.h new file mode 100644 index 00000000000..a9b9181f6db --- /dev/null +++ b/keyboards/redragon/k715_pro/bluetooth/btspi.h @@ -0,0 +1,204 @@ +/* Copyright 2023 temp4gh + * + * 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 "quantum.h" + +#define ENABLE_SPI_BLE_MODULE + +#define SPI_MODE 3 +#define SPI_DIVISOR 32 + +#define IS31FL3733_POWERON_PIN B2 +#define EXT_IS31FL3733_SUSPEND_PIN (IS31FL3733_POWERON_PIN) + +#define EXT_READ_DIP_PIN_USB_MODE C13 +#define EXT_READ_DIP_PIN_BT_MODE C14 + +#define CAPS_LOCK_DRV_PIN B8 +#define set_caps_lock_on() palClearLine(CAPS_LOCK_DRV_PIN) +#define set_caps_lock_off() palSetLine(CAPS_LOCK_DRV_PIN) + +#define EXT_READ_SPI_SLAVE_INT_PIN B9 +#define EXT_READ_SPI_SLAVE_GPIO_INIT (PAL_MODE_INPUT_PULLUP) +#define EXT_READ_SPI_SLAVE_READY (PAL_LOW) +#define EXT_READ_SPI_SLAVE_NOT_READY (PAL_HIGH) + +#define KBD_BT_MODE 0 +#define KBD_USB_MODE 2 +#define KBD_POWEROFF_MODE 8 +#define INVALID_DIP_DEVICE_MODE 0xFF + +#define DEVICE_MODE_BT KBD_BT_MODE +#define DEVICE_MODE_2D4G KBD_24G_MODE +#define DEVICE_MODE_USB KBD_USB_MODE + +#define BTSTATEDISCONN 0 +#define BTSTATEDISCOVER 1 +#define BTSTATECONNECTED 2 +#define BTSTATERECONN 3 + +#define BT_CHANNEL_1 1 +#define BT_CHANNEL_INVALID 0xFF + +#define BT_BACK_TIMEOUT 60000 +#define BT_BACK_TIMEOUT_MS ((BT_BACK_TIMEOUT) / 1000) + +#define BT_BP_TIMEOUT 60000 +#define BT_BP_TIMEOUT_MS ((BT_BP_TIMEOUT) / 1000) + +//means use default value +#define DEFAULT_BT_BP_TIMEOUT 0 + +//based on ms +#define RF_TIMEOUT_OFFSET 1000 + +#define MAX_SPI_BLE_SINGLE_PACKET_LENGTH 12 +#define MAX_SPI_BLE_MUL_PACKET_LENGTH 11 +#define MAX_SPI_BLE_SINGLE_PACKET_LOAD_LENGTH 13 +#define MAX_BLE_SPI_RX_FRAME_MAX_SIZE 16 +#define MAX_BLE_SPI_TX_FRAME_MAX_SIZE (MAX_BLE_SPI_RX_FRAME_MAX_SIZE) +#define MAX_BLE_SPI_NOTIFY_CMD_BUF_SIZE (32) + +#define SPI_BLE_PACKET_HEADER 0x5A + +#define SEND_BT_NAME_DELAY_MS 10 + +#define KBD_CMD_UNKNOW 0x0 +#define KBD_CMD_MODE_SET 0x11 +#define KBD_CMD_BT_PAIR 0x21 +#define KBD_CMD_BT_BACK 0x22 +#define KBD_CMD_BT_DISCONNECT 0x23 +#define KBD_CMD_BT_SETNAME 0x25 +#define KBD_CMD_BT_GETNAME 0x26 +#define KBD_CMD_BT_SETCHN 0x27 +#define KBD_CMD_GET_INFO 0x51 +#define KBD_CMD_INVALID 0x0 + +#define KBD_CMD_BT_QUERY_KEY_STATE 0x66 +#define KBD_CMD_MCU_RESP_KEY_STATE 0x67 +#define KBD_CMD_QUERY_LOST_KEY_STATE 0x68 + +#define KBD_CMD_SEND_BT_TEST_RF 0x71 +#define KBD_CMD_MCU_REQ_BT_FWVER 0x72 +#define KBD_CMD_MCU_RECV_BT_FWVER 0x72 +#define KBD_CMD_BT_REQ_MCU_FWVER 0x73 +#define KBD_CMD_SEND_BT_MCU_FWVER 0x73 +#define KBD_CMD_BT_REQ_DEV_STATUS 0x74 +#define KBD_CMD_SEND_BT_DEV_STATUS 0x74 +#define KBD_CMD_BT_REQ_LIGHT_CONTROL 0x75 +#define KBD_CMD_BT_REQ_DEEP_SLEEP 0x76 +#define KBD_CMD_BT_SET_TEST_MODE 0x77 + +typedef struct +{ + uint32_t NumLock: 1; + uint32_t CapsLock: 1; + uint32_t ScrollLock: 1; + uint32_t red: 1; + uint32_t green: 1; + uint32_t blue: 1; + uint32_t win_lock: 1; + uint32_t kbd_lock: 1; + + uint32_t btstate: 2; + uint32_t wifistate: 3; + uint32_t btpair: 1; + uint32_t btback: 1; + uint32_t lowVoltage: 1; + + uint32_t devmode: 7; + uint32_t btconnected: 1; + + uint32_t usbstate: 3; + uint32_t fn_down: 1; + uint32_t pair: 1; + uint32_t res_bt_isr: 1; + uint32_t usb_connected: 2; + + uint32_t last_key_ms; + uint32_t bt_timeout; +} tDevInfo; + +#define BLE_SPI_RX_BUF_MAX_SIZE 20 +typedef struct +{ + uint8_t spi_read_buf[BLE_SPI_RX_BUF_MAX_SIZE]; + uint8_t spi_read_length; +} spi_read_data_t; + +typedef struct __attribute__((__packed__)) +{ + uint32_t NumLock: 1; + uint32_t CapsLock: 1; + uint32_t ScrollLock: 1; + uint32_t res: 1; + uint32_t remote_btn_down: 1; + uint32_t remote_btn_dec: 1; + uint32_t remote_btn_add: 1; + uint32_t remote_chg: 1; + uint32_t state_bt: 8; + uint32_t state_24g: 8; + uint32_t state_usb: 8; + uint8_t mode; + uint8_t eff_mode; + uint8_t eff_bright; + uint8_t eff_speed; + uint8_t eff_r; + uint8_t eff_g; + uint8_t eff_b; + uint8_t ch; +} +spi_slave_dev_info_t; + +#define KB_MAGIC_NUMBER 0xBE +typedef struct +{ + uint8_t magic_num; + + uint8_t caps_lock: 1; + uint8_t num_lock: 1; + uint8_t scroll_lock: 1; + uint8_t winlock_state: 1; + + uint8_t kbd_lock: 1; + uint8_t reset_factory: 1; + uint8_t reserved_bit: 2; + + uint8_t kbd_dev_mode; + uint8_t bt_ch; + uint8_t bt_used; + uint8_t bt_last_connected; + + uint8_t reset_reason; + uint8_t unused; +} user_settings_config; + +#define spi_use_begin() do{}while(0) +#define spi_use_end() do{}while(0) + +#define kbd_spi_send_byte(_t_) spi_write(_t_) +#define kbd_spi_rec_byte(_t_) spi_read() + +void set_dev_info_bt_pair_timeout(void); +void set_dev_info_bt_reconn_timeout(void); +void check_read_spi_data(void); +void update_caps_led(void); +void k715_bt_start_pair(uint8_t chn); +bool is_usb_mode_enabled(void); +bool is_bt_mode_enabled(void); +void k715_ble_spi_init(void); +void k715bt_send_spi_extend_single_packet(uint8_t param_type, uint8_t *param_data, uint8_t param_len); diff --git a/keyboards/redragon/k715_pro/bluetooth/btsys.c b/keyboards/redragon/k715_pro/bluetooth/btsys.c new file mode 100644 index 00000000000..e2221dbcdab --- /dev/null +++ b/keyboards/redragon/k715_pro/bluetooth/btsys.c @@ -0,0 +1,50 @@ +/* Copyright 2024 temp4gh + * + * 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 "config.h" +#include "btspi.h" + +void init_set_IS31FL3733_poweron(void) +{ + palSetLineMode(IS31FL3733_POWERON_PIN, PAL_MODE_OUTPUT_PUSHPULL); + palSetLine(IS31FL3733_POWERON_PIN); +} + +void bootloader_jump(void) +{ + NVIC_SystemReset(); +} + +void mcu_reset(void) +{ + NVIC_SystemReset(); +} + +void board_init(void) +{ + AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_DISABLE; + + palSetLineMode(CAPS_LOCK_DRV_PIN, PAL_MODE_OUTPUT_PUSHPULL); + set_caps_lock_off(); + + palSetPadMode(GPIOC, 11, PAL_MODE_INPUT); + palSetPadMode(GPIOA, 13, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 14, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 15, PAL_MODE_OUTPUT_PUSHPULL); + + init_set_IS31FL3733_poweron(); +} diff --git a/keyboards/redragon/k715_pro/config.h b/keyboards/redragon/k715_pro/config.h new file mode 100644 index 00000000000..45e08cfe5f2 --- /dev/null +++ b/keyboards/redragon/k715_pro/config.h @@ -0,0 +1,27 @@ +/* Copyright 2023 temp4gh + * + * 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 + +#define IS31FL3733_I2C_ADDRESS_1 IS31FL3733_I2C_ADDRESS_GND_GND +#define IS31FL3733_I2C_ADDRESS_2 IS31FL3733_I2C_ADDRESS_GND_VCC + +#define SPI_DRIVER SPID2 +#define SPI_SCK_PIN B13 +#define SPI_MOSI_PIN B15 +#define SPI_MISO_PIN B14 + +#define SPI_SLAVE_CS B12 diff --git a/keyboards/redragon/k715_pro/halconf.h b/keyboards/redragon/k715_pro/halconf.h new file mode 100644 index 00000000000..42b470bae5a --- /dev/null +++ b/keyboards/redragon/k715_pro/halconf.h @@ -0,0 +1,28 @@ +/* Copyright 2020 QMK + * + * 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_next + +#undef HAL_USE_I2C +#define HAL_USE_I2C TRUE + +#undef HAL_USE_SPI +#define HAL_USE_SPI TRUE + +#undef SPI_SELECT_MODE +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD diff --git a/keyboards/redragon/k715_pro/k715_pro.c b/keyboards/redragon/k715_pro/k715_pro.c new file mode 100644 index 00000000000..2b8bb311f72 --- /dev/null +++ b/keyboards/redragon/k715_pro/k715_pro.c @@ -0,0 +1,303 @@ +/* Copyright 2023 temp4gh + * + * 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 +#include "spi_master.h" +#include "host_driver.h" +#include "config.h" + +#include "k715_pro.h" +#include "btspi.h" + +const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = +{ + {0, SW7_CS1, SW9_CS1, SW8_CS1}, + {0, SW7_CS3, SW9_CS3, SW8_CS3}, + {0, SW7_CS4, SW9_CS4, SW8_CS4}, + {0, SW7_CS5, SW9_CS5, SW8_CS5}, + {0, SW7_CS6, SW9_CS6, SW8_CS6}, + {0, SW7_CS7, SW9_CS7, SW8_CS7}, + {0, SW7_CS8, SW9_CS8, SW8_CS8}, + {0, SW7_CS9, SW9_CS9, SW8_CS9}, + {0, SW7_CS10, SW9_CS10, SW8_CS10}, + {0, SW7_CS11, SW9_CS11, SW8_CS11}, + {0, SW7_CS12, SW9_CS12, SW8_CS12}, + {0, SW7_CS13, SW9_CS13, SW8_CS13}, + {0, SW7_CS14, SW9_CS14, SW8_CS14}, + {0, SW7_CS15, SW9_CS15, SW8_CS15}, + {0, SW4_CS1, SW6_CS1, SW5_CS1}, + {0, SW4_CS2, SW6_CS2, SW5_CS2}, + {0, SW4_CS3, SW6_CS3, SW5_CS3}, + {0, SW4_CS4, SW6_CS4, SW5_CS4}, + {0, SW4_CS5, SW6_CS5, SW5_CS5}, + {0, SW4_CS6, SW6_CS6, SW5_CS6}, + {0, SW4_CS7, SW6_CS7, SW5_CS7}, + {0, SW4_CS8, SW6_CS8, SW5_CS8}, + {0, SW4_CS9, SW6_CS9, SW5_CS9}, + {0, SW4_CS10, SW6_CS10, SW5_CS10}, + {0, SW4_CS11, SW6_CS11, SW5_CS11}, + {0, SW4_CS12, SW6_CS12, SW5_CS12}, + {0, SW4_CS13, SW6_CS13, SW5_CS13}, + {0, SW4_CS14, SW6_CS14, SW5_CS14}, + {0, SW4_CS15, SW6_CS15, SW5_CS15}, + {0, SW1_CS1, SW3_CS1, SW2_CS1}, + {0, SW1_CS2, SW3_CS2, SW2_CS2}, + {0, SW1_CS3, SW3_CS3, SW2_CS3}, + {0, SW1_CS4, SW3_CS4, SW2_CS4}, + {0, SW1_CS5, SW3_CS5, SW2_CS5}, + {0, SW1_CS6, SW3_CS6, SW2_CS6}, + {0, SW1_CS7, SW3_CS7, SW2_CS7}, + {0, SW1_CS8, SW3_CS8, SW2_CS8}, + {0, SW1_CS9, SW3_CS9, SW2_CS9}, + {0, SW1_CS10, SW3_CS10, SW2_CS10}, + {0, SW1_CS11, SW3_CS11, SW2_CS11}, + {0, SW1_CS12, SW3_CS12, SW2_CS12}, + {0, SW1_CS13, SW3_CS13, SW2_CS13}, + {0, SW1_CS14, SW3_CS14, SW2_CS14}, + {0, SW1_CS15, SW3_CS15, SW2_CS15}, + {1, SW7_CS1, SW9_CS1, SW8_CS1}, + {1, SW7_CS2, SW9_CS2, SW8_CS2}, + {1, SW7_CS3, SW9_CS3, SW8_CS3}, + {1, SW7_CS4, SW9_CS4, SW8_CS4}, + {1, SW7_CS5, SW9_CS5, SW8_CS5}, + {1, SW7_CS6, SW9_CS6, SW8_CS6}, + {1, SW7_CS7, SW9_CS7, SW8_CS7}, + {1, SW7_CS8, SW9_CS8, SW8_CS8}, + {1, SW7_CS9, SW9_CS9, SW8_CS9}, + {1, SW7_CS10, SW9_CS10, SW8_CS10}, + {1, SW7_CS11, SW9_CS11, SW8_CS11}, + {1, SW7_CS12, SW9_CS12, SW8_CS12}, + {1, SW7_CS13, SW9_CS13, SW8_CS13}, + {1, SW7_CS14, SW9_CS14, SW8_CS14}, + {1, SW7_CS15, SW9_CS15, SW8_CS15}, + {1, SW4_CS1, SW6_CS1, SW5_CS1}, + {1, SW4_CS2, SW6_CS2, SW5_CS2}, + {1, SW4_CS3, SW6_CS3, SW5_CS3}, + {1, SW4_CS4, SW6_CS4, SW5_CS4}, + {1, SW4_CS5, SW6_CS5, SW5_CS5}, + {1, SW4_CS6, SW6_CS6, SW5_CS6}, + {1, SW4_CS7, SW6_CS7, SW5_CS7}, + {1, SW4_CS8, SW6_CS8, SW5_CS8}, + {1, SW4_CS9, SW6_CS9, SW5_CS9}, + {1, SW4_CS10, SW6_CS10, SW5_CS10}, + {1, SW4_CS11, SW6_CS11, SW5_CS11}, + {1, SW4_CS12, SW6_CS12, SW5_CS12}, + {1, SW4_CS13, SW6_CS13, SW5_CS13}, + {1, SW4_CS14, SW6_CS14, SW5_CS14}, + {1, SW4_CS15, SW6_CS15, SW5_CS15}, + {1, SW1_CS1, SW3_CS1, SW2_CS1}, + {1, SW1_CS2, SW3_CS2, SW2_CS2}, + {1, SW1_CS3, SW3_CS3, SW2_CS3}, + {1, SW1_CS5, SW3_CS5, SW2_CS5}, + {1, SW1_CS6, SW3_CS6, SW2_CS6}, + {1, SW1_CS7, SW3_CS7, SW2_CS7}, + {1, SW1_CS8, SW3_CS8, SW2_CS8}, + {1, SW1_CS9, SW3_CS9, SW2_CS9}, + {1, SW1_CS10, SW3_CS10, SW2_CS10}, + {1, SW1_CS11, SW3_CS11, SW2_CS11}, + {1, SW1_CS12, SW3_CS12, SW2_CS12}, + {1, SW1_CS13, SW3_CS13, SW2_CS13}, + {1, SW1_CS14, SW3_CS14, SW2_CS14}, + {1, SW1_CS15, SW3_CS15, SW2_CS15}, + {0, SW7_CS2, SW9_CS2, SW8_CS2}, + {1, SW1_CS4, SW3_CS4, SW2_CS4} +}; + +static void send_ble_hid_report(uint8_t report_type, uint8_t *hid_report_buf, uint8_t data_len) +{ + switch(report_type) + { + case BLE_HID_REPORT_TYPE_NORMAL_KEY: + { + k715bt_send_spi_extend_single_packet(report_type, hid_report_buf, data_len); + break; + } + + case BLE_HID_REPORT_TYPE_EXTRA_KEY: + { + k715bt_send_spi_extend_single_packet(report_type, hid_report_buf, data_len); + break; + } + + default: + { + break; + } + } +} + +static uint8_t k715_ble_leds(void) +{ + return 0; +} + +static void k715_send_keyboard(report_keyboard_t *report) +{ + uint8_t raw_data[KEYBOARD_REPORT_KEYS + 2]; + + raw_data[0] = report->mods; + raw_data[1] = 0; + for(int i = 0; i < KEYBOARD_REPORT_KEYS; i++) + { + raw_data[2 + i] = report->keys[i]; + } + + send_ble_hid_report(BLE_HID_REPORT_TYPE_NORMAL_KEY, raw_data, KEYBOARD_REPORT_KEYS + 2); +} + +#ifdef NKRO_ENABLE +static void k715_send_nkro(report_nkro_t *report) +{ + uint8_t raw_data[NKRO_REPORT_BITS + 2]; + + raw_data[0] = report->mods; + raw_data[1] = 0; + for(int i = 0; i < NKRO_REPORT_BITS; i++) + { + raw_data[2 + i] = report->bits[i]; + } + + send_ble_hid_report(BLE_HID_REPORT_TYPE_ALL_KEY, raw_data, NKRO_REPORT_BITS + 2); +} +#endif + +static void k715_send_mouse(report_mouse_t *report) +{ +} + +static void k715_send_extra(report_extra_t *report) +{ + if(report->report_id == REPORT_ID_CONSUMER) + { + uint8_t extra_buf[6]; + + memset(extra_buf, 0, sizeof(extra_buf)); + memcpy(extra_buf, &report->usage, 2); + send_ble_hid_report(BLE_HID_REPORT_TYPE_EXTRA_KEY, extra_buf, sizeof(extra_buf)); + } +} + +static host_driver_t k715_ble_driver = +{ +#ifdef NKRO_ENABLE + k715_ble_leds, k715_send_keyboard, k715_send_nkro, k715_send_mouse, k715_send_extra +#else + k715_ble_leds, k715_send_keyboard, NULL, k715_send_mouse, k715_send_extra +#endif +}; + +static bool _swtich_bt_driver(void) +{ + if(host_get_driver() == &k715_ble_driver) + { + return false; + } + + clear_keyboard(); + +#ifdef NKRO_ENABLE + keymap_config.nkro = true; +#else + keymap_config.nkro = false; +#endif + + host_set_driver(&k715_ble_driver); + return true; +} + +void k715bt_bt_swtich_ble_driver(void) +{ + if(is_bt_mode_enabled()) + { + _swtich_bt_driver(); + } +} + +void k715_rgb_matrix_flags_init(void) +{ + rgb_matrix_enable(); + rgb_matrix_set_flags(NORMAL_LED_FLAG_BIT); +} + +void k715_bt_init(void) +{ + k715_ble_spi_init(); + k715_rgb_matrix_flags_init(); +} + +bool led_update_kb(led_t led_state) +{ + bool res = led_update_user(led_state); + + if(res) + { + update_caps_led(); + } + + return res; +} + +bool process_record_kb_bt(uint16_t keycode, keyrecord_t *record) +{ + static uint8_t chn = 0; + + switch(keycode) + { + case BT_CHN1: + case BT_CHN2: + case BT_CHN3: + if(is_bt_mode_enabled()) + { + if(record->event.pressed) + { + chn = keycode - BT_CHN1 + 1; + k715_bt_start_pair(chn); + } + else + { + chn = 0; + } + } + break; + + default: + break; + } + + return true; +} + +bool process_record_kb(uint16_t keycode, keyrecord_t *record) +{ + if(!process_record_user(keycode, record)) + { + return false; + } + + return process_record_kb_bt(keycode, record); +} + +void bluetooth_task(void) +{ + k715bt_bt_swtich_ble_driver(); + check_read_spi_data(); +} + +void keyboard_post_init_kb(void) +{ + k715_bt_init(); + keyboard_post_init_user(); +} diff --git a/keyboards/redragon/k715_pro/k715_pro.h b/keyboards/redragon/k715_pro/k715_pro.h new file mode 100644 index 00000000000..d147b5d1207 --- /dev/null +++ b/keyboards/redragon/k715_pro/k715_pro.h @@ -0,0 +1,35 @@ +/* Copyright 2023 temp4gh + * + * 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 "quantum.h" + +#define BLE_HID_REPORT_TYPE_NORMAL_KEY 0x1 +#define BLE_HID_REPORT_TYPE_MOUSE_KEY 0x2 +#define BLE_HID_REPORT_TYPE_EXTRA_KEY 0x3 +#define BLE_HID_REPORT_TYPE_SYSTEM_KEY 0x4 +#define BLE_HID_REPORT_TYPE_ALL_KEY 0x5 + +enum { + BT_CHN1, + BT_CHN2, + BT_CHN3, + NEW_SAFE_RANGE +}; + +#define NORMAL_LED_FLAG_BIT (LED_FLAG_KEYLIGHT | LED_FLAG_MODIFIER) + diff --git a/keyboards/redragon/k715_pro/keyboard.json b/keyboards/redragon/k715_pro/keyboard.json new file mode 100644 index 00000000000..de477447ead --- /dev/null +++ b/keyboards/redragon/k715_pro/keyboard.json @@ -0,0 +1,242 @@ +{ + "manufacturer": "redragon", + "keyboard_name": "k715 pro", + "bootloader": "stm32duino", + "bootmagic": { + "matrix": [1, 0] + }, + "diode_direction": "COL2ROW", + "dynamic_keymap": { + "layer_count": 2 + }, + "encoder": { + "rotary": [ + {"pin_a": "B5", "pin_b": "B4"} + ] + }, + "features": { + "bootmagic": true, + "console": true, + "encoder": true, + "extrakey": true, + "mousekey": true, + "nkro": false, + "rgb_matrix": true + }, + "indicators": { + "caps_lock": "B8", + "on_state": 0 + }, + "matrix_pins": { + "cols": ["A6", "A7", "C4", "C5", "B0", "B1", "C6", "C7", "C8", "C9", "A8", "A9", "A10", "A13", "A14", "A15"], + "rows": ["A0", "A1", "A2", "A3", "A4", "A5"] + }, + "processor": "STM32F103", + "rgb_matrix": { + "animations": { + "solid_color": true, + "alphas_mods": true, + "gradient_up_down": true, + "gradient_left_right": true, + "breathing": true, + "band_sat": true, + "band_val": true, + "band_spiral_val": true, + "cycle_all": true, + "cycle_left_right": true, + "cycle_up_down": true, + "hue_wave": true, + "pixel_flow": true + }, + "driver": "is31fl3733", + "layout": [ + {"matrix": [0, 0], "x": 7, "y": 2, "flags": 4}, + {"matrix": [0, 2], "x": 34, "y": 2, "flags": 4}, + {"matrix": [0, 3], "x": 48, "y": 2, "flags": 4}, + {"matrix": [0, 4], "x": 61, "y": 2, "flags": 4}, + {"matrix": [0, 5], "x": 75, "y": 2, "flags": 4}, + {"matrix": [0, 6], "x": 95, "y": 2, "flags": 4}, + {"matrix": [0, 7], "x": 109, "y": 2, "flags": 4}, + {"matrix": [0, 8], "x": 122, "y": 2, "flags": 4}, + {"matrix": [0, 9], "x": 136, "y": 2, "flags": 4}, + {"matrix": [0, 10], "x": 157, "y": 2, "flags": 4}, + {"matrix": [0, 11], "x": 170, "y": 2, "flags": 4}, + {"matrix": [0, 12], "x": 184, "y": 2, "flags": 4}, + {"matrix": [0, 13], "x": 198, "y": 2, "flags": 4}, + {"matrix": [0, 14], "x": 217, "y": 2, "flags": 4}, + {"matrix": [1, 0], "x": 7, "y": 14, "flags": 4}, + {"matrix": [1, 1], "x": 20, "y": 14, "flags": 4}, + {"matrix": [1, 2], "x": 34, "y": 14, "flags": 4}, + {"matrix": [1, 3], "x": 48, "y": 14, "flags": 4}, + {"matrix": [1, 4], "x": 61, "y": 14, "flags": 4}, + {"matrix": [1, 5], "x": 75, "y": 14, "flags": 4}, + {"matrix": [1, 6], "x": 89, "y": 14, "flags": 4}, + {"matrix": [1, 7], "x": 102, "y": 14, "flags": 4}, + {"matrix": [1, 8], "x": 116, "y": 14, "flags": 4}, + {"matrix": [1, 9], "x": 129, "y": 14, "flags": 4}, + {"matrix": [1, 10], "x": 143, "y": 14, "flags": 4}, + {"matrix": [1, 11], "x": 157, "y": 14, "flags": 4}, + {"matrix": [1, 12], "x": 170, "y": 14, "flags": 4}, + {"matrix": [1, 13], "x": 190, "y": 14, "flags": 4}, + {"matrix": [1, 14], "x": 217, "y": 14, "flags": 4}, + {"matrix": [2, 0], "x": 10, "y": 24, "flags": 4}, + {"matrix": [2, 1], "x": 27, "y": 24, "flags": 4}, + {"matrix": [2, 2], "x": 40, "y": 24, "flags": 4}, + {"matrix": [2, 3], "x": 54, "y": 24, "flags": 4}, + {"matrix": [2, 4], "x": 68, "y": 24, "flags": 4}, + {"matrix": [2, 5], "x": 81, "y": 24, "flags": 4}, + {"matrix": [2, 6], "x": 95, "y": 24, "flags": 4}, + {"matrix": [2, 7], "x": 109, "y": 24, "flags": 4}, + {"matrix": [2, 8], "x": 122, "y": 24, "flags": 4}, + {"matrix": [2, 9], "x": 136, "y": 24, "flags": 4}, + {"matrix": [2, 10], "x": 150, "y": 24, "flags": 4}, + {"matrix": [2, 11], "x": 163, "y": 24, "flags": 4}, + {"matrix": [2, 12], "x": 177, "y": 24, "flags": 4}, + {"matrix": [2, 13], "x": 194, "y": 24, "flags": 4}, + {"matrix": [2, 14], "x": 217, "y": 24, "flags": 4}, + {"matrix": [3, 0], "x": 12, "y": 34, "flags": 4}, + {"matrix": [3, 1], "x": 30, "y": 34, "flags": 4}, + {"matrix": [3, 2], "x": 44, "y": 34, "flags": 4}, + {"matrix": [3, 3], "x": 58, "y": 34, "flags": 4}, + {"matrix": [3, 4], "x": 71, "y": 34, "flags": 4}, + {"matrix": [3, 5], "x": 85, "y": 34, "flags": 4}, + {"matrix": [3, 6], "x": 99, "y": 34, "flags": 4}, + {"matrix": [3, 7], "x": 112, "y": 34, "flags": 4}, + {"matrix": [3, 8], "x": 126, "y": 34, "flags": 4}, + {"matrix": [3, 9], "x": 140, "y": 34, "flags": 4}, + {"matrix": [3, 10], "x": 153, "y": 34, "flags": 4}, + {"matrix": [3, 11], "x": 167, "y": 34, "flags": 4}, + {"x": 180, "y": 34, "flags": 4}, + {"matrix": [3, 13], "x": 189, "y": 34, "flags": 4}, + {"matrix": [3, 14], "x": 217, "y": 34, "flags": 4}, + {"matrix": [4, 0], "x": 8, "y": 44, "flags": 4}, + {"x": 24, "y": 44, "flags": 4}, + {"matrix": [4, 2], "x": 38, "y": 44, "flags": 4}, + {"matrix": [4, 3], "x": 51, "y": 44, "flags": 4}, + {"matrix": [4, 4], "x": 65, "y": 44, "flags": 4}, + {"matrix": [4, 5], "x": 78, "y": 44, "flags": 4}, + {"matrix": [4, 6], "x": 92, "y": 44, "flags": 4}, + {"matrix": [4, 7], "x": 106, "y": 44, "flags": 4}, + {"matrix": [4, 8], "x": 119, "y": 44, "flags": 4}, + {"matrix": [4, 9], "x": 133, "y": 44, "flags": 4}, + {"matrix": [4, 10], "x": 147, "y": 44, "flags": 4}, + {"matrix": [4, 11], "x": 160, "y": 44, "flags": 4}, + {"matrix": [4, 12], "x": 179, "y": 44, "flags": 4}, + {"matrix": [4, 13], "x": 201, "y": 46, "flags": 4}, + {"matrix": [4, 14], "x": 217, "y": 44, "flags": 4}, + {"matrix": [5, 0], "x": 8, "y": 54, "flags": 4}, + {"matrix": [5, 1], "x": 25, "y": 54, "flags": 4}, + {"matrix": [5, 2], "x": 43, "y": 54, "flags": 4}, + {"x": 67, "y": 57, "flags": 4}, + {"x": 80, "y": 57, "flags": 4}, + {"x": 94, "y": 54, "flags": 4}, + {"matrix": [5, 6], "x": 107, "y": 57, "flags": 4}, + {"x": 120, "y": 57, "flags": 4}, + {"matrix": [5, 9], "x": 143, "y": 54, "flags": 4}, + {"matrix": [5, 10], "x": 157, "y": 54, "flags": 4}, + {"matrix": [5, 11], "x": 170, "y": 54, "flags": 4}, + {"matrix": [5, 12], "x": 187, "y": 56, "flags": 4}, + {"matrix": [5, 13], "x": 201, "y": 56, "flags": 4}, + {"matrix": [5, 14], "x": 214, "y": 56, "flags": 4}, + {"x": 207, "y": 23, "flags": 8}, + {"x": 207, "y": 27, "flags": 8} + ] + }, + "usb": { + "device_version": "0.0.1", + "pid": "0x00D1", + "vid": "0x369B", + "no_startup_check": true + }, + "layout_aliases": { + "LAYOUT_75_ansi": "LAYOUT" + }, + "layouts": { + "LAYOUT": { + "layout": [ + {"label": "ESC", "matrix": [0, 0], "x": 0, "y": 0}, + {"label": "F1", "matrix": [0, 2], "x": 1.5, "y": 0}, + {"label": "F2", "matrix": [0, 3], "x": 2.5, "y": 0}, + {"label": "F3", "matrix": [0, 4], "x": 3.5, "y": 0}, + {"label": "F4", "matrix": [0, 5], "x": 4.5, "y": 0}, + {"label": "F5", "matrix": [0, 6], "x": 6, "y": 0}, + {"label": "F6", "matrix": [0, 7], "x": 7, "y": 0}, + {"label": "F7", "matrix": [0, 8], "x": 8, "y": 0}, + {"label": "F8", "matrix": [0, 9], "x": 9, "y": 0}, + {"label": "F9", "matrix": [0, 10], "x": 10.5, "y": 0}, + {"label": "F10", "matrix": [0, 11], "x": 11.5, "y": 0}, + {"label": "F11", "matrix": [0, 12], "x": 12.5, "y": 0}, + {"label": "F12", "matrix": [0, 13], "x": 13.5, "y": 0}, + {"label": "END", "matrix": [0, 15], "x": 15, "y": 0}, + {"label": "GRV", "matrix": [1, 0], "x": 0, "y": 1.25}, + {"label": "1", "matrix": [1, 1], "x": 1, "y": 1.25}, + {"label": "2", "matrix": [1, 2], "x": 2, "y": 1.25}, + {"label": "3", "matrix": [1, 3], "x": 3, "y": 1.25}, + {"label": "4", "matrix": [1, 4], "x": 4, "y": 1.25}, + {"label": "5", "matrix": [1, 5], "x": 5, "y": 1.25}, + {"label": "6", "matrix": [1, 6], "x": 6, "y": 1.25}, + {"label": "7", "matrix": [1, 7], "x": 7, "y": 1.25}, + {"label": "8", "matrix": [1, 8], "x": 8, "y": 1.25}, + {"label": "9", "matrix": [1, 9], "x": 9, "y": 1.25}, + {"label": "0", "matrix": [1, 10], "x": 10, "y": 1.25}, + {"label": "MINS", "matrix": [1, 11], "x": 11, "y": 1.25}, + {"label": "EQL", "matrix": [1, 12], "x": 12, "y": 1.25}, + {"label": "BSPC", "matrix": [1, 13], "x": 13, "y": 1.25, "w": 2}, + {"label": "INS", "matrix": [1, 14], "x": 15, "y": 1.25}, + {"label": "TAB", "matrix": [2, 0], "x": 0, "y": 2.25, "w": 1.5}, + {"label": "Q", "matrix": [2, 1], "x": 1.5, "y": 2.25}, + {"label": "W", "matrix": [2, 2], "x": 2.5, "y": 2.25}, + {"label": "E", "matrix": [2, 3], "x": 3.5, "y": 2.25}, + {"label": "R", "matrix": [2, 4], "x": 4.5, "y": 2.25}, + {"label": "T", "matrix": [2, 5], "x": 5.5, "y": 2.25}, + {"label": "Y", "matrix": [2, 6], "x": 6.5, "y": 2.25}, + {"label": "U", "matrix": [2, 7], "x": 7.5, "y": 2.25}, + {"label": "I", "matrix": [2, 8], "x": 8.5, "y": 2.25}, + {"label": "O", "matrix": [2, 9], "x": 9.5, "y": 2.25}, + {"label": "P", "matrix": [2, 10], "x": 10.5, "y": 2.25}, + {"label": "LBRC", "matrix": [2, 11], "x": 11.5, "y": 2.25}, + {"label": "RBRC", "matrix": [2, 12], "x": 12.5, "y": 2.25}, + {"label": "BSLS", "matrix": [2, 13], "x": 13.5, "y": 2.25, "w": 1.5}, + {"label": "DEL", "matrix": [2, 14], "x": 15, "y": 2.25}, + {"label": "CAPS", "matrix": [3, 0], "x": 0, "y": 3.25, "w": 1.75}, + {"label": "A", "matrix": [3, 1], "x": 1.75, "y": 3.25}, + {"label": "S", "matrix": [3, 2], "x": 2.75, "y": 3.25}, + {"label": "D", "matrix": [3, 3], "x": 3.75, "y": 3.25}, + {"label": "F", "matrix": [3, 4], "x": 4.75, "y": 3.25}, + {"label": "G", "matrix": [3, 5], "x": 5.75, "y": 3.25}, + {"label": "H", "matrix": [3, 6], "x": 6.75, "y": 3.25}, + {"label": "J", "matrix": [3, 7], "x": 7.75, "y": 3.25}, + {"label": "K", "matrix": [3, 8], "x": 8.75, "y": 3.25}, + {"label": "L", "matrix": [3, 9], "x": 9.75, "y": 3.25}, + {"label": "SCLN", "matrix": [3, 10], "x": 10.75, "y": 3.25}, + {"label": "QUOT", "matrix": [3, 11], "x": 11.75, "y": 3.25}, + {"label": "ENT", "matrix": [3, 13], "x": 12.75, "y": 3.25, "w": 2.25}, + {"label": "PGUP", "matrix": [3, 14], "x": 15, "y": 3.25}, + {"label": "LSFT", "matrix": [4, 0], "x": 0, "y": 4.25, "w": 2.25}, + {"label": "Z", "matrix": [4, 2], "x": 2.25, "y": 4.25}, + {"label": "X", "matrix": [4, 3], "x": 3.25, "y": 4.25}, + {"label": "C", "matrix": [4, 4], "x": 4.25, "y": 4.25}, + {"label": "V", "matrix": [4, 5], "x": 5.25, "y": 4.25}, + {"label": "B", "matrix": [4, 6], "x": 6.25, "y": 4.25}, + {"label": "N", "matrix": [4, 7], "x": 7.25, "y": 4.25}, + {"label": "M", "matrix": [4, 8], "x": 8.25, "y": 4.25}, + {"label": "COMM", "matrix": [4, 9], "x": 9.25, "y": 4.25}, + {"label": "DOT", "matrix": [4, 10], "x": 10.25, "y": 4.25}, + {"label": "SLSH", "matrix": [4, 11], "x": 11.25, "y": 4.25}, + {"label": "RSFT", "matrix": [4, 12], "x": 12.25, "y": 4.25, "w": 1.75}, + {"label": "UP", "matrix": [4, 13], "x": 14, "y": 4.25}, + {"label": "PGDN", "matrix": [4, 14], "x": 15, "y": 4.25}, + {"label": "LCTL", "matrix": [5, 0], "x": 0, "y": 5.25, "w": 1.25}, + {"label": "LGUI", "matrix": [5, 1], "x": 1.25, "y": 5.25, "w": 1.25}, + {"label": "LALT", "matrix": [5, 2], "x": 2.5, "y": 5.25, "w": 1.25}, + {"label": "SPC", "matrix": [5, 6], "x": 3.75, "y": 5.25, "w": 6.25}, + {"label": "RALT", "matrix": [5, 9], "x": 10, "y": 5.25}, + {"label": "MO(1)", "matrix": [5, 10], "x": 11, "y": 5.25}, + {"label": "RCTL", "matrix": [5, 11], "x": 12, "y": 5.25}, + {"label": "LEFT", "matrix": [5, 12], "x": 13, "y": 5.25}, + {"label": "DOWN", "matrix": [5, 13], "x": 14, "y": 5.25}, + {"label": "RGHT", "matrix": [5, 14], "x": 15, "y": 5.25} + ] + } + } +} diff --git a/keyboards/redragon/k715_pro/keymaps/default/keymap.c b/keyboards/redragon/k715_pro/keymaps/default/keymap.c new file mode 100644 index 00000000000..b25e77be674 --- /dev/null +++ b/keyboards/redragon/k715_pro/keymaps/default/keymap.c @@ -0,0 +1,50 @@ +/* Copyright 2024 temp4gh + * + * 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 +#include "k715_pro.h" + +enum layer_names +{ + _BASE, + _FnLay, +}; + +#ifdef ENCODER_MAP_ENABLE +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = { + [_BASE] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU) }, + [_FnLay] = { ENCODER_CCW_CW(RGB_VAD, RGB_VAI) }, +}; +#endif + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [_BASE] = LAYOUT( + KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_MUTE, + KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_INS, + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL, + KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGUP, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_PGDN, + KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(_FnLay), KC_RCTL, KC_LEFT, KC_DOWN, KC_RIGHT + ), + [_FnLay] = LAYOUT( + EE_CLR, KC_BRID, KC_BRIU, A(KC_TAB),G(KC_H),G(KC_D), G(KC_S), KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, XXXXXXX, + XXXXXXX, BT_CHN1, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, RGB_MOD, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_HOME, KC_END, XXXXXXX, XXXXXXX, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_SCRL, KC_PSCR, XXXXXXX, XXXXXXX, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_PAUS, XXXXXXX, RGB_VAI, XXXXXXX, + XXXXXXX, XXXXXXX, XXXXXXX, RGB_TOG, XXXXXXX, _______, XXXXXXX, RGB_SPD, RGB_VAD, RGB_SPI + ) +}; diff --git a/keyboards/redragon/k715_pro/keymaps/default/rules.mk b/keyboards/redragon/k715_pro/keymaps/default/rules.mk new file mode 100644 index 00000000000..cb9527ac99e --- /dev/null +++ b/keyboards/redragon/k715_pro/keymaps/default/rules.mk @@ -0,0 +1,2 @@ +SPI_DRIVER_REQUIRED = yes +ENCODER_MAP_ENABLE = yes diff --git a/keyboards/redragon/k715_pro/mcuconf.h b/keyboards/redragon/k715_pro/mcuconf.h new file mode 100644 index 00000000000..bb4b34214a4 --- /dev/null +++ b/keyboards/redragon/k715_pro/mcuconf.h @@ -0,0 +1,25 @@ +/* Copyright 2020 QMK + * + * 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_next + +#undef STM32_I2C_USE_I2C1 +#define STM32_I2C_USE_I2C1 TRUE + +#undef STM32_SPI_USE_SPI2 +#define STM32_SPI_USE_SPI2 TRUE diff --git a/keyboards/redragon/k715_pro/post_rules.mk b/keyboards/redragon/k715_pro/post_rules.mk new file mode 100644 index 00000000000..7e8fbbed86d --- /dev/null +++ b/keyboards/redragon/k715_pro/post_rules.mk @@ -0,0 +1 @@ +include keyboards/redragon/k715_pro/bluetooth/bluetooth.mk \ No newline at end of file diff --git a/keyboards/redragon/k715_pro/readme.md b/keyboards/redragon/k715_pro/readme.md new file mode 100644 index 00000000000..cd8b539f92d --- /dev/null +++ b/keyboards/redragon/k715_pro/readme.md @@ -0,0 +1,21 @@ +# K715 Pro + +![k715_pro](https://i.imgur.com/kpoGXfc.png) + +A customizable 80% keyboard with wire and bluetooth. + +- Keyboard Maintainer: [temp4gh](https://github.com/temp4gh) +- Hardware Supported:K715 pro PCB +- Hardware Availability: www.redragonzone.com + +Make example for this keyboard (after setting up your build environment): + + make redragon/k715_pro:default + +Flashing example for this keyboard: + + make redragon/k715_pro:default:flash + +**Reset Key**: Hold down the key located at *K10*, commonly programmed as *Grave* while plugging in the keyboard. + +See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). diff --git a/keyboards/redragon/k715_pro/rules.mk b/keyboards/redragon/k715_pro/rules.mk new file mode 100644 index 00000000000..e69de29bb2d