mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-07-27 03:21:15 +00:00
Merge 519dea3e33
into 717b6b8f13
This commit is contained in:
commit
9f46a0d008
324
keyboards/hator/rockfall3/common/wireless/lowpower.c
Normal file
324
keyboards/hator/rockfall3/common/wireless/lowpower.c
Normal file
@ -0,0 +1,324 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "quantum.h"
|
||||
#include "wireless.h"
|
||||
#include "usb_main.h"
|
||||
|
||||
#ifndef LPWR_TIMEOUT
|
||||
# define LPWR_TIMEOUT 300000 // 5min
|
||||
#endif
|
||||
|
||||
#ifndef LPWR_PRESLEEP_DELAY
|
||||
# define LPWR_PRESLEEP_DELAY 200
|
||||
#endif
|
||||
|
||||
#ifndef LPWR_STOP_DELAY
|
||||
# define LPWR_STOP_DELAY 200
|
||||
#endif
|
||||
|
||||
#ifndef LPWR_WAKEUP_DELAY
|
||||
# define LPWR_WAKEUP_DELAY 200
|
||||
#endif
|
||||
|
||||
static lpwr_state_t lpwr_state = LPWR_NORMAL;
|
||||
static lpwr_mode_t lpwr_mode = LPWR_MODE_TIMEOUT;
|
||||
static uint32_t lpwr_timeout_value = LPWR_TIMEOUT;
|
||||
static uint32_t lpwr_timestamp = 0x00;
|
||||
static lpwr_wakeupcd_t lpwr_wakeupcd = LPWR_WAKEUP_NONE;
|
||||
static bool manual_timeout = false;
|
||||
|
||||
static bool rgb_enable_bak = false;
|
||||
|
||||
void last_matrix_activity_trigger(void);
|
||||
|
||||
void lpwr_clock_enable(void);
|
||||
void lpwr_enter_stop(void);
|
||||
void lpwr_exti_init(void);
|
||||
void mcu_stop_mode(void);
|
||||
|
||||
extern void matrix_init_pins(void);
|
||||
|
||||
lpwr_state_t lpwr_get_state(void) {
|
||||
return lpwr_state;
|
||||
}
|
||||
|
||||
void lpwr_set_state(lpwr_state_t state) {
|
||||
lpwr_state = state;
|
||||
}
|
||||
|
||||
lpwr_mode_t lpwr_get_mode(void) {
|
||||
return lpwr_mode;
|
||||
}
|
||||
|
||||
void lpwr_set_mode(lpwr_mode_t mode) {
|
||||
lpwr_mode = mode;
|
||||
}
|
||||
|
||||
void lpwr_set_timeout_value(uint32_t timeout) {
|
||||
lpwr_timeout_value = timeout;
|
||||
}
|
||||
|
||||
uint32_t lpwr_timeout_value_read(void) {
|
||||
return lpwr_timeout_value;
|
||||
}
|
||||
|
||||
void lpwr_update_timestamp(void) {
|
||||
lpwr_timestamp = sync_timer_read32();
|
||||
}
|
||||
|
||||
uint32_t lpwr_timestamp_read(void) {
|
||||
return lpwr_timestamp;
|
||||
}
|
||||
|
||||
void lpwr_set_sleep_wakeupcd(lpwr_wakeupcd_t wakeupcd) {
|
||||
lpwr_wakeupcd = wakeupcd;
|
||||
}
|
||||
|
||||
lpwr_wakeupcd_t lpwr_get_sleep_wakeupcd(void) {
|
||||
return lpwr_wakeupcd;
|
||||
}
|
||||
|
||||
void lpwr_clock_enable(void) __attribute__((weak));
|
||||
void lpwr_clock_enable(void) {}
|
||||
|
||||
void lpwr_exti_init(void) __attribute__((weak));
|
||||
void lpwr_exti_init(void) {}
|
||||
|
||||
void mcu_stop_mode(void) __attribute__((weak));
|
||||
void mcu_stop_mode(void) {}
|
||||
|
||||
void lpwr_enter_stop(void) {
|
||||
chSysLock();
|
||||
lpwr_exti_init();
|
||||
chSysUnlock();
|
||||
|
||||
chSysDisable();
|
||||
mcu_stop_mode();
|
||||
lpwr_clock_enable();
|
||||
matrix_init_pins();
|
||||
chSysEnable();
|
||||
}
|
||||
|
||||
void lpwr_set_timeout_manual(bool enable) {
|
||||
manual_timeout = enable;
|
||||
}
|
||||
|
||||
bool lpwr_get_timeout_manual(void) {
|
||||
return manual_timeout;
|
||||
}
|
||||
|
||||
// 2.4g mode, host state
|
||||
void md_receive_host_cb(bool resume) {
|
||||
|
||||
if (resume) {
|
||||
if (lpwr_get_state() != LPWR_NORMAL) {
|
||||
lpwr_update_timestamp();
|
||||
lpwr_set_state(LPWR_WAKEUP);
|
||||
}
|
||||
} else {
|
||||
if (lpwr_get_state() == LPWR_NORMAL) {
|
||||
manual_timeout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool lpwr_is_allow_timeout_hook(void) __attribute__((weak));
|
||||
bool lpwr_is_allow_timeout_hook(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lpwr_is_allow_timeout(void) __attribute__((weak));
|
||||
bool lpwr_is_allow_timeout(void) {
|
||||
uint32_t timeout = lpwr_timeout_value_read();
|
||||
|
||||
if (lpwr_is_allow_timeout_hook() != true) {
|
||||
manual_timeout = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((wireless_get_current_devs() == DEVS_USB) && (USB_DRIVER.state == USB_ACTIVE)) {
|
||||
manual_timeout = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (manual_timeout || (timeout && (last_input_activity_elapsed() >= timeout))) {
|
||||
manual_timeout = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lpwr_is_allow_presleep_hook(void) __attribute__((weak));
|
||||
bool lpwr_is_allow_presleep_hook(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lpwr_is_allow_presleep(void) __attribute__((weak));
|
||||
bool lpwr_is_allow_presleep(void) {
|
||||
uint32_t delay = LPWR_PRESLEEP_DELAY;
|
||||
|
||||
if (lpwr_is_allow_presleep_hook() != true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!delay || (sync_timer_elapsed32(lpwr_timestamp_read()) >= delay)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lpwr_is_allow_stop_hook(void) __attribute__((weak));
|
||||
bool lpwr_is_allow_stop_hook(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lpwr_is_allow_stop(void) __attribute__((weak));
|
||||
bool lpwr_is_allow_stop(void) {
|
||||
uint32_t delay = LPWR_STOP_DELAY;
|
||||
|
||||
if (lpwr_is_allow_stop_hook() != true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!delay || (sync_timer_elapsed32(lpwr_timestamp_read()) >= delay)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lpwr_is_allow_wakeup_hook(void) __attribute__((weak));
|
||||
bool lpwr_is_allow_wakeup_hook(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lpwr_is_allow_wakeup(void) __attribute__((weak));
|
||||
bool lpwr_is_allow_wakeup(void) {
|
||||
uint32_t delay = LPWR_WAKEUP_DELAY;
|
||||
|
||||
if (lpwr_is_allow_wakeup_hook() != true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!delay || (sync_timer_elapsed32(lpwr_timestamp_read()) >= delay)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void lpwr_presleep_hook(void) __attribute__((weak));
|
||||
void lpwr_presleep_hook(void) {}
|
||||
|
||||
void lpwr_presleep_cb(void) __attribute__((weak));
|
||||
void lpwr_presleep_cb(void) {
|
||||
|
||||
#if defined(RGB_MATRIX_ENABLE)
|
||||
rgb_enable_bak = rgb_matrix_is_enabled();
|
||||
rgb_matrix_disable_noeeprom();
|
||||
#elif defined(RGBLIGHT_ENABLE)
|
||||
rgb_enable_bak = rgblight_is_enabled();
|
||||
rgblight_disable_noeeprom();
|
||||
#else
|
||||
rgb_enable_bak = false;
|
||||
#endif
|
||||
suspend_power_down();
|
||||
lpwr_presleep_hook();
|
||||
}
|
||||
|
||||
void lpwr_stop_hook_pre(void) __attribute__((weak));
|
||||
void lpwr_stop_hook_pre(void) {}
|
||||
|
||||
void lpwr_stop_hook_post(void) __attribute__((weak));
|
||||
void lpwr_stop_hook_post(void) {}
|
||||
|
||||
void lpwr_stop_cb(void) __attribute__((weak));
|
||||
void lpwr_stop_cb(void) {
|
||||
|
||||
lpwr_set_sleep_wakeupcd(LPWR_WAKEUP_NONE);
|
||||
|
||||
lpwr_stop_hook_pre();
|
||||
lpwr_enter_stop();
|
||||
|
||||
switch (lpwr_get_sleep_wakeupcd()) {
|
||||
case LPWR_WAKEUP_UART: {
|
||||
lpwr_set_state(LPWR_STOP);
|
||||
} break;
|
||||
default: {
|
||||
lpwr_set_state(LPWR_WAKEUP);
|
||||
} break;
|
||||
}
|
||||
|
||||
lpwr_stop_hook_post();
|
||||
}
|
||||
|
||||
void lpwr_wakeup_hook(void) __attribute__((weak));
|
||||
void lpwr_wakeup_hook(void) {}
|
||||
|
||||
void lpwr_wakeup_cb(void) __attribute__((weak));
|
||||
void lpwr_wakeup_cb(void) {
|
||||
|
||||
if (rgb_enable_bak) {
|
||||
#if defined(RGB_MATRIX_ENABLE)
|
||||
rgb_matrix_enable_noeeprom();
|
||||
#elif defined(RGBLIGHT_ENABLE)
|
||||
rgblight_enable_noeeprom();
|
||||
#endif
|
||||
}
|
||||
|
||||
suspend_wakeup_init();
|
||||
lpwr_wakeup_hook();
|
||||
|
||||
last_matrix_activity_trigger();
|
||||
}
|
||||
|
||||
void lpwr_task(void) __attribute__((weak));
|
||||
void lpwr_task(void) {
|
||||
|
||||
switch (lpwr_get_state()) {
|
||||
case LPWR_NORMAL: {
|
||||
if (lpwr_is_allow_timeout()) {
|
||||
lpwr_update_timestamp();
|
||||
lpwr_set_state(LPWR_PRESLEEP);
|
||||
}
|
||||
} break;
|
||||
case LPWR_PRESLEEP: {
|
||||
if (lpwr_is_allow_presleep()) {
|
||||
lpwr_presleep_cb();
|
||||
lpwr_update_timestamp();
|
||||
lpwr_set_state(LPWR_STOP);
|
||||
}
|
||||
} break;
|
||||
case LPWR_STOP: {
|
||||
if (lpwr_is_allow_stop()) {
|
||||
lpwr_update_timestamp();
|
||||
lpwr_stop_cb();
|
||||
}
|
||||
} break;
|
||||
case LPWR_WAKEUP: {
|
||||
if (lpwr_is_allow_wakeup()) {
|
||||
lpwr_wakeup_cb();
|
||||
lpwr_update_timestamp();
|
||||
lpwr_set_state(LPWR_NORMAL);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
52
keyboards/hator/rockfall3/common/wireless/lowpower.h
Normal file
52
keyboards/hator/rockfall3/common/wireless/lowpower.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
LPWR_NORMAL = 0,
|
||||
LPWR_PRESLEEP,
|
||||
LPWR_STOP,
|
||||
LPWR_WAKEUP,
|
||||
} lpwr_state_t;
|
||||
|
||||
typedef enum {
|
||||
LPWR_WAKEUP_NONE = 0,
|
||||
LPWR_WAKEUP_MATRIX,
|
||||
LPWR_WAKEUP_UART,
|
||||
LPWR_WAKEUP_CABLE,
|
||||
LPWR_WAKEUP_USB,
|
||||
LPWR_WAKEUP_ONEKEY,
|
||||
LPWR_WAKEUP_ENCODER,
|
||||
LPWR_WAKEUP_SWITCH,
|
||||
} lpwr_wakeupcd_t;
|
||||
|
||||
typedef enum {
|
||||
LPWR_MODE_TIMEOUT = 0,
|
||||
} lpwr_mode_t;
|
||||
|
||||
lpwr_state_t lpwr_get_state(void);
|
||||
lpwr_mode_t lpwr_get_mode(void);
|
||||
uint32_t lpwr_timestamp_read(void);
|
||||
uint32_t lpwr_timeout_value_read(void);
|
||||
void lpwr_set_sleep_wakeupcd(lpwr_wakeupcd_t wakeupcd);
|
||||
lpwr_wakeupcd_t lpwr_get_sleep_wakeupcd(void);
|
||||
void lpwr_update_timestamp(void);
|
||||
void lpwr_set_timeout_manual(bool enable);
|
||||
bool lpwr_get_timeout_manual(void);
|
||||
void lpwr_set_state(lpwr_state_t state);
|
||||
void lpwr_set_mode(lpwr_mode_t mode);
|
||||
void lpwr_task(void);
|
222
keyboards/hator/rockfall3/common/wireless/lpwr_wb32.c
Normal file
222
keyboards/hator/rockfall3/common/wireless/lpwr_wb32.c
Normal file
@ -0,0 +1,222 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "quantum.h"
|
||||
#include "wireless.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifndef LPWR_UART_WAKEUP_DISABLE
|
||||
# include "uart.h"
|
||||
#endif
|
||||
|
||||
static ioline_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
|
||||
static ioline_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
|
||||
|
||||
#if PAL_USE_CALLBACKS != TRUE
|
||||
# error PAL_USE_CALLBACKS must be set to TRUE!
|
||||
#endif
|
||||
|
||||
#if !((DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW))
|
||||
# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
static const uint32_t pre_lp_code[] = {553863175u, 554459777u, 1208378049u, 4026624001u, 688390415u, 554227969u, 3204472833u, 1198571264u, 1073807360u, 1073808388u};
|
||||
#define PRE_LP() ((void (*)(void))((unsigned int)(pre_lp_code) | 0x01))()
|
||||
|
||||
static const uint32_t post_lp_code[] = {553863177u, 554459777u, 1208509121u, 51443856u, 4026550535u, 1745485839u, 3489677954u, 536895496u, 673389632u, 1198578684u, 1073807360u, 536866816u, 1073808388u};
|
||||
#define POST_LP() ((void (*)(void))((unsigned int)(post_lp_code) | 0x01))()
|
||||
// clang-format on
|
||||
|
||||
extern void __early_init(void);
|
||||
extern void matrix_init_pins(void);
|
||||
|
||||
void palcallback_cb(uint8_t line) __attribute__((weak));
|
||||
void palcallback_cb(uint8_t line) {}
|
||||
|
||||
void palcallback(void *arg) {
|
||||
uint8_t line = (uint32_t)arg & 0xFF;
|
||||
|
||||
switch (line) {
|
||||
#ifndef LPWR_UART_WAKEUP_DISABLE
|
||||
case PAL_PAD(UART_RX_PIN): {
|
||||
lpwr_set_sleep_wakeupcd(LPWR_WAKEUP_UART);
|
||||
} break;
|
||||
#endif
|
||||
default: {
|
||||
lpwr_set_sleep_wakeupcd(LPWR_WAKEUP_MATRIX);
|
||||
} break;
|
||||
}
|
||||
|
||||
palcallback_cb(line);
|
||||
|
||||
irqDeinit();
|
||||
EXTI->PR = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
void pal_events_init(void) {
|
||||
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
_pal_events[i].cb = palcallback;
|
||||
_pal_events[i].arg = (void *)(uint32_t)i;
|
||||
}
|
||||
}
|
||||
|
||||
void lpwr_exti_init_hook(void) __attribute__((weak));
|
||||
void lpwr_exti_init_hook(void) {}
|
||||
|
||||
void lpwr_exti_init(void) {
|
||||
|
||||
pal_events_init();
|
||||
|
||||
#if DIODE_DIRECTION == ROW2COL
|
||||
for (uint8_t i = 0; i < ARRAY_SIZE(col_pins); i++) {
|
||||
if (col_pins[i] != NO_PIN) {
|
||||
setPinOutputOpenDrain(col_pins[i]);
|
||||
writePinLow(col_pins[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < ARRAY_SIZE(row_pins); i++) {
|
||||
if (row_pins[i] != NO_PIN) {
|
||||
setPinInputHigh(row_pins[i]);
|
||||
waitInputPinDelay();
|
||||
palEnableLineEvent(row_pins[i], PAL_EVENT_MODE_BOTH_EDGES);
|
||||
}
|
||||
}
|
||||
#elif DIODE_DIRECTION == COL2ROW
|
||||
for (uint8_t i = 0; i < ARRAY_SIZE(row_pins); i++) {
|
||||
if (row_pins[i] != NO_PIN) {
|
||||
setPinOutputOpenDrain(row_pins[i]);
|
||||
writePinLow(row_pins[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < ARRAY_SIZE(col_pins); i++) {
|
||||
if (col_pins[i] != NO_PIN) {
|
||||
setPinInputHigh(col_pins[i]);
|
||||
waitInputPinDelay();
|
||||
palEnableLineEvent(col_pins[i], PAL_EVENT_MODE_BOTH_EDGES);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef LPWR_UART_WAKEUP_DISABLE
|
||||
setPinInput(UART_RX_PIN);
|
||||
waitInputPinDelay();
|
||||
palEnableLineEvent(UART_RX_PIN, PAL_EVENT_MODE_BOTH_EDGES);
|
||||
#endif
|
||||
|
||||
lpwr_exti_init_hook();
|
||||
|
||||
/* IRQ subsystem initialization.*/
|
||||
irqInit();
|
||||
}
|
||||
|
||||
void lpwr_clock_enable_user(void) __attribute__((weak));
|
||||
void lpwr_clock_enable_user(void) {}
|
||||
|
||||
void lpwr_clock_enable(void) {
|
||||
|
||||
__early_init();
|
||||
|
||||
rccEnableEXTI();
|
||||
|
||||
#if WB32_SERIAL_USE_UART1
|
||||
rccEnableUART1();
|
||||
#endif
|
||||
#if WB32_SERIAL_USE_UART2
|
||||
rccEnableUART2();
|
||||
#endif
|
||||
#if WB32_SERIAL_USE_UART3
|
||||
rccEnableUART3();
|
||||
#endif
|
||||
#if WB32_SPI_USE_QSPI
|
||||
rccEnableQSPI();
|
||||
#endif
|
||||
#if WB32_SPI_USE_SPIM2
|
||||
rccEnableSPIM2();
|
||||
#endif
|
||||
#if WB32_I2C_USE_I2C1
|
||||
rccEnableI2C1();
|
||||
#endif
|
||||
#if WB32_I2C_USE_I2C2
|
||||
rccEnableI2C2();
|
||||
#endif
|
||||
#if WB32_GPT_USE_TIM1 || WB32_ICU_USE_TIM1 || WB32_PWM_USE_TIM1
|
||||
rccEnableTIM1();
|
||||
#endif
|
||||
#if WB32_ST_USE_TIM2 || WB32_GPT_USE_TIM2 || WB32_ICU_USE_TIM2 || WB32_PWM_USE_TIM2
|
||||
rccEnableTIM2();
|
||||
#endif
|
||||
#if WB32_ST_USE_TIM3 || WB32_GPT_USE_TIM3 || WB32_ICU_USE_TIM3 || WB32_PWM_USE_TIM3
|
||||
rccEnableTIM3();
|
||||
#endif
|
||||
#if WB32_ST_USE_TIM4 || WB32_GPT_USE_TIM4 || WB32_ICU_USE_TIM4 || WB32_PWM_USE_TIM4
|
||||
rccEnableTIM4();
|
||||
#endif
|
||||
|
||||
#ifndef LPWR_UART_WAKEUP_DISABLE
|
||||
palSetLineMode(UART_RX_PIN, PAL_MODE_ALTERNATE(UART_RX_PAL_MODE) | PAL_OUTPUT_TYPE_PUSHPULL | PAL_OUTPUT_SPEED_HIGHEST);
|
||||
#endif
|
||||
|
||||
lpwr_clock_enable_user();
|
||||
}
|
||||
|
||||
void wb32_stop_mode(void) {
|
||||
|
||||
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
|
||||
|
||||
/* Prevent the chip from being unable to enter stop mode due to pending interrupts */
|
||||
#if 1
|
||||
EXTI->PR = 0x7FFFF;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
for (uint8_t j = 0; j < 32; j++) {
|
||||
if (NVIC->ISPR[i] & (0x01UL < j)) {
|
||||
NVIC->ICPR[i] = (0x01UL < j);
|
||||
}
|
||||
}
|
||||
}
|
||||
SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk; // Clear Systick IRQ Pending
|
||||
#endif
|
||||
|
||||
/* Clear all bits except DBP and FCLKSD bit */
|
||||
PWR->CR0 &= 0x09U;
|
||||
|
||||
// STOP LP4 MODE S32KON
|
||||
PWR->CR0 |= 0x3B004U;
|
||||
PWR->CFGR = 0x3B3;
|
||||
|
||||
PRE_LP();
|
||||
|
||||
/* Set SLEEPDEEP bit of Cortex System Control Register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
/* Request Wait For Interrupt */
|
||||
__WFI();
|
||||
|
||||
POST_LP();
|
||||
|
||||
/* Clear SLEEPDEEP bit of Cortex System Control Register */
|
||||
SCB->SCR &= (~SCB_SCR_SLEEPDEEP_Msk);
|
||||
|
||||
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
|
||||
}
|
||||
|
||||
void mcu_stop_mode(void) {
|
||||
|
||||
wb32_stop_mode();
|
||||
}
|
43
keyboards/hator/rockfall3/common/wireless/md_raw.c
Normal file
43
keyboards/hator/rockfall3/common/wireless/md_raw.c
Normal file
@ -0,0 +1,43 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if RAW_ENABLE
|
||||
|
||||
# include "quantum.h"
|
||||
# include "wireless.h"
|
||||
# include "usb_endpoints.h"
|
||||
# include "usb_main.h"
|
||||
|
||||
void replaced_hid_send(uint8_t *data, uint8_t length) {
|
||||
|
||||
if (length != RAW_EPSIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_transport() == TRANSPORT_USB) {
|
||||
send_report(USB_ENDPOINT_IN_RAW, data, length);
|
||||
} else {
|
||||
md_send_raw(data, length);
|
||||
}
|
||||
}
|
||||
|
||||
void md_receive_raw_cb(uint8_t *data, uint8_t length) {
|
||||
void raw_hid_receive(uint8_t * data, uint8_t length);
|
||||
|
||||
raw_hid_receive(data, length);
|
||||
}
|
||||
|
||||
#endif
|
23
keyboards/hator/rockfall3/common/wireless/md_raw.h
Normal file
23
keyboards/hator/rockfall3/common/wireless/md_raw.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define RENAME_WITH_LINE(A, B) COMBINE(A, B)
|
||||
#define COMBINE(A, B) A##B
|
||||
#define raw_hid_send(a, b) RENAME_WITH_LINE(_temp_rhs_, __LINE__)(a, b)
|
||||
#define _temp_rhs_29 replaced_hid_send // raw_hid.h
|
||||
#define _temp_rhs_461 replaced_hid_send // via.c
|
543
keyboards/hator/rockfall3/common/wireless/module.c
Normal file
543
keyboards/hator/rockfall3/common/wireless/module.c
Normal file
@ -0,0 +1,543 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "quantum.h"
|
||||
#include "module.h"
|
||||
#include "smsg.h"
|
||||
#include "uart.h"
|
||||
|
||||
#ifndef MD_BAUD_RATE
|
||||
# define MD_BAUD_RATE 115200
|
||||
#endif
|
||||
|
||||
#ifndef MD_SNED_PKT_TIMEOUT
|
||||
# define MD_SNED_PKT_TIMEOUT 10
|
||||
#endif
|
||||
|
||||
#ifndef MD_SEND_PKT_RETRY
|
||||
# define MD_SEND_PKT_RETRY 40
|
||||
#endif
|
||||
|
||||
#ifndef MD_SEND_PKT_PAYLOAD_MAX
|
||||
# define MD_SEND_PKT_PAYLOAD_MAX ((MD_RAW_SIZE) + 4)
|
||||
#endif
|
||||
|
||||
#ifndef MD_BT1_NAME
|
||||
# define MD_BT1_NAME PRODUCT " BT1"
|
||||
#endif
|
||||
|
||||
#ifndef MD_BT2_NAME
|
||||
# define MD_BT2_NAME PRODUCT " BT2"
|
||||
#endif
|
||||
|
||||
#ifndef MD_BT3_NAME
|
||||
# define MD_BT3_NAME PRODUCT " BT3"
|
||||
#endif
|
||||
|
||||
#ifndef MD_BT4_NAME
|
||||
# define MD_BT4_NAME PRODUCT " BT4"
|
||||
#endif
|
||||
|
||||
#ifndef MD_BT5_NAME
|
||||
# define MD_BT5_NAME PRODUCT " BT5"
|
||||
#endif
|
||||
|
||||
#ifndef MD_DONGLE_MANUFACTURER
|
||||
# define MD_DONGLE_MANUFACTURER MANUFACTURER
|
||||
#endif
|
||||
|
||||
#ifndef MD_DONGLE_PRODUCT
|
||||
# define MD_DONGLE_PRODUCT PRODUCT " Dongle"
|
||||
#endif
|
||||
|
||||
#ifndef MD_RAW_SIZE
|
||||
# define MD_RAW_SIZE 32
|
||||
#endif
|
||||
|
||||
#define USBCONCAT(a, b) a##b
|
||||
#define USBSTR(s) USBCONCAT(L, s)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t state;
|
||||
uint8_t indicator;
|
||||
uint8_t version;
|
||||
uint8_t bat;
|
||||
} md_info_t;
|
||||
|
||||
static uint8_t md_pkt_payload[MD_SEND_PKT_PAYLOAD_MAX] = {0};
|
||||
static uint8_t md_rev_payload[MD_SEND_PKT_PAYLOAD_MAX] = {0};
|
||||
static uint8_t md_raw_payload[MD_RAW_SIZE] = {0};
|
||||
|
||||
static md_info_t md_info = {
|
||||
.bat = 100,
|
||||
.indicator = 0,
|
||||
.version = 0,
|
||||
.state = MD_STATE_NONE,
|
||||
};
|
||||
|
||||
static void md_send_ack(void) {
|
||||
|
||||
uint8_t sdata[0x03] = {0x61, 0x0D, 0x0A};
|
||||
uart_transmit(sdata, sizeof(sdata));
|
||||
}
|
||||
|
||||
static bool md_check_sum(const uint8_t *data, uint32_t length) {
|
||||
uint8_t sum = 0;
|
||||
|
||||
for (uint32_t i = 0; i < (length - 1); i++) {
|
||||
sum += data[i];
|
||||
}
|
||||
|
||||
return sum == data[length - 1];
|
||||
}
|
||||
|
||||
static void md_calc_check_sum(uint8_t *data, uint32_t length) {
|
||||
uint8_t sum = 0;
|
||||
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
sum += data[i];
|
||||
}
|
||||
|
||||
data[length] = sum;
|
||||
}
|
||||
|
||||
bool md_receive_process_user(uint8_t *pdata, uint8_t len) __attribute__((weak));
|
||||
bool md_receive_process_user(uint8_t *pdata, uint8_t len) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool md_receive_process_kb(uint8_t *pdata, uint8_t len) __attribute__((weak));
|
||||
bool md_receive_process_kb(uint8_t *pdata, uint8_t len) {
|
||||
return md_receive_process_user(pdata, len);
|
||||
}
|
||||
|
||||
void md_receive_raw_cb(uint8_t *pdata, uint8_t len) __attribute__((weak));
|
||||
void md_receive_raw_cb(uint8_t *pdata, uint8_t len) {}
|
||||
|
||||
void md_receive_host_cb(bool resume) __attribute__((weak));
|
||||
void md_receive_host_cb(bool resume) {}
|
||||
|
||||
static void md_receive_msg_task(void) {
|
||||
static uint32_t data_count = 0x00;
|
||||
static uint8_t data_remain = 0x00;
|
||||
|
||||
while (uart_available()) {
|
||||
uint8_t data = uart_read();
|
||||
|
||||
switch (data_count) {
|
||||
case 0: { // cmd
|
||||
switch (data) {
|
||||
case MD_REV_CMD_INDICATOR:
|
||||
case MD_REV_CMD_DEVCTRL:
|
||||
case MD_REV_CMD_BATVOL:
|
||||
case MD_REV_CMD_MD_FW_VERSION:
|
||||
case MD_REV_CMD_HOST_STATE:
|
||||
case 0x61: {
|
||||
md_rev_payload[data_count++] = data;
|
||||
data_remain = 2;
|
||||
} break;
|
||||
case MD_REV_CMD_RAW: {
|
||||
md_rev_payload[data_count++] = data;
|
||||
data_remain = 33;
|
||||
} break;
|
||||
default: {
|
||||
data_count = 0;
|
||||
} break;
|
||||
}
|
||||
continue;
|
||||
} break;
|
||||
case 1: {
|
||||
md_rev_payload[data_count++] = data;
|
||||
data_remain--;
|
||||
continue;
|
||||
} break;
|
||||
case 2: {
|
||||
// ACK
|
||||
if ((md_rev_payload[0] == 0x61) && (md_rev_payload[1] == 0x0D) && (data == 0x0A)) {
|
||||
if (smsg_get_state() == smsg_state_busy) {
|
||||
smsg_set_state(smsg_state_replied);
|
||||
}
|
||||
data_count = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
default: {
|
||||
md_rev_payload[data_count++] = data;
|
||||
data_remain--;
|
||||
|
||||
if (data_remain) {
|
||||
continue;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
if (md_check_sum(md_rev_payload, data_count)) {
|
||||
md_send_ack();
|
||||
|
||||
if (md_receive_process_kb(md_rev_payload, data_count) != true) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (md_rev_payload[0]) {
|
||||
case MD_REV_CMD_RAW: {
|
||||
uint8_t *pdata;
|
||||
pdata = &md_rev_payload[1];
|
||||
|
||||
memcpy(md_raw_payload, pdata, 32);
|
||||
md_receive_raw_cb(md_raw_payload, 32);
|
||||
|
||||
} break;
|
||||
case MD_REV_CMD_INDICATOR: {
|
||||
md_info.indicator = md_rev_payload[1];
|
||||
} break;
|
||||
case MD_REV_CMD_DEVCTRL: {
|
||||
switch (md_rev_payload[1]) {
|
||||
case MD_REV_CMD_DEVCTRL_PAIRING: {
|
||||
md_info.state = MD_STATE_PAIRING;
|
||||
} break;
|
||||
case MD_REV_CMD_DEVCTRL_CONNECTED: {
|
||||
md_info.state = MD_STATE_CONNECTED;
|
||||
} break;
|
||||
case MD_REV_CMD_DEVCTRL_DISCONNECTED: {
|
||||
md_info.state = MD_STATE_DISCONNECTED;
|
||||
} break;
|
||||
case MD_REV_CMD_DEVCTRL_REJECT: {
|
||||
md_info.state = MD_STATE_REJECT;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case MD_REV_CMD_BATVOL: {
|
||||
md_info.bat = md_rev_payload[1];
|
||||
} break;
|
||||
case MD_REV_CMD_MD_FW_VERSION: {
|
||||
md_info.version = md_rev_payload[1];
|
||||
} break;
|
||||
case MD_REV_CMD_HOST_STATE: {
|
||||
md_receive_host_cb(md_rev_payload[1] == MD_REV_CMD_HOST_STATE_RESUME);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
data_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void md_send_pkt_task(void) {
|
||||
static uint32_t smsg_timer = 0x00;
|
||||
static uint8_t smsg_retry = 0;
|
||||
|
||||
switch (smsg_get_state()) {
|
||||
case smsg_state_busy: {
|
||||
if (sync_timer_elapsed32(smsg_timer) > (MD_SNED_PKT_TIMEOUT)) {
|
||||
smsg_retry = 0;
|
||||
smsg_set_state(smsg_state_retry);
|
||||
}
|
||||
} break;
|
||||
case smsg_state_retry: {
|
||||
if (++smsg_retry > MD_SEND_PKT_RETRY) {
|
||||
smsg_retry = 0;
|
||||
smsg_pop();
|
||||
}
|
||||
smsg_set_state(smsg_state_free);
|
||||
} break;
|
||||
case smsg_state_replied: {
|
||||
smsg_pop();
|
||||
smsg_set_state(smsg_state_free);
|
||||
} // break;
|
||||
case smsg_state_free: {
|
||||
uint32_t size = smsg_peek(md_pkt_payload);
|
||||
if (size) {
|
||||
if (md_send_pkt(md_pkt_payload, size)) {
|
||||
smsg_timer = sync_timer_read32();
|
||||
smsg_set_state(smsg_state_busy);
|
||||
} else {
|
||||
smsg_set_state(smsg_state_replied);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void md_init(void) {
|
||||
|
||||
uart_init(MD_BAUD_RATE);
|
||||
smsg_init();
|
||||
|
||||
memset(md_pkt_payload, 0, sizeof(md_pkt_payload));
|
||||
}
|
||||
|
||||
void md_main_task(void) {
|
||||
|
||||
md_send_pkt_task();
|
||||
md_receive_msg_task();
|
||||
}
|
||||
|
||||
uint8_t *md_getp_state(void) {
|
||||
|
||||
return &md_info.state;
|
||||
}
|
||||
|
||||
uint8_t *md_getp_bat(void) {
|
||||
|
||||
return &md_info.bat;
|
||||
}
|
||||
|
||||
uint8_t *md_getp_indicator(void) {
|
||||
|
||||
return &md_info.indicator;
|
||||
}
|
||||
|
||||
uint8_t md_get_version(void) {
|
||||
|
||||
return md_info.version;
|
||||
}
|
||||
|
||||
bool md_send_pkt(uint8_t *data, uint32_t len) {
|
||||
bool retval = true;
|
||||
|
||||
if (!data || !len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// switch (*data) {
|
||||
// case MD_SND_CMD_RAW: {
|
||||
// retval = false;
|
||||
// } break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
|
||||
// send
|
||||
uart_transmit(data, len);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void md_send_kb(uint8_t *data) {
|
||||
uint8_t sdata[MD_SND_CMD_KB_LEN + 2] = {0x00};
|
||||
|
||||
sdata[0] = MD_SND_CMD_SEND_KB;
|
||||
memcpy(&sdata[1], data, sizeof(sdata) - 2);
|
||||
md_calc_check_sum(sdata, sizeof(sdata) - 1);
|
||||
smsg_push(sdata, sizeof(sdata));
|
||||
}
|
||||
|
||||
void md_send_nkro(uint8_t *data) {
|
||||
uint8_t sdata[MD_SND_CMD_NKRO_LEN + 2] = {0x00};
|
||||
|
||||
sdata[0] = MD_SND_CMD_SEND_NKRO;
|
||||
memcpy(&sdata[1], data, sizeof(sdata) - 2);
|
||||
md_calc_check_sum(sdata, sizeof(sdata) - 1);
|
||||
smsg_push(sdata, sizeof(sdata));
|
||||
}
|
||||
|
||||
void md_send_consumer(uint8_t *data) {
|
||||
uint8_t sdata[MD_SND_CMD_CONSUMER_LEN + 2] = {0x00};
|
||||
|
||||
sdata[0] = MD_SND_CMD_SEND_CONSUMER;
|
||||
memcpy(&sdata[1], data, sizeof(sdata) - 2);
|
||||
md_calc_check_sum(sdata, sizeof(sdata) - 1);
|
||||
smsg_push(sdata, sizeof(sdata));
|
||||
}
|
||||
|
||||
void md_send_system(uint8_t *data) {
|
||||
uint8_t sdata[MD_SND_CMD_SYSTEM_LEN + 2] = {0x00};
|
||||
|
||||
sdata[0] = MD_SND_CMD_SEND_SYSTEM;
|
||||
memcpy(&sdata[1], data, sizeof(sdata) - 2);
|
||||
md_calc_check_sum(sdata, sizeof(sdata) - 1);
|
||||
smsg_push(sdata, sizeof(sdata));
|
||||
}
|
||||
|
||||
void md_send_fn(uint8_t *data) {
|
||||
uint8_t sdata[MD_SND_CMD_FN_LEN + 2] = {0x00};
|
||||
|
||||
sdata[0] = MD_SND_CMD_SEND_FN;
|
||||
memcpy(&sdata[1], data, sizeof(sdata) - 2);
|
||||
md_calc_check_sum(sdata, sizeof(sdata) - 1);
|
||||
smsg_push(sdata, sizeof(sdata));
|
||||
}
|
||||
|
||||
void md_send_mouse(uint8_t *data) {
|
||||
uint8_t sdata[MD_SND_CMD_MOUSE_LEN + 2] = {0x00};
|
||||
|
||||
sdata[0] = MD_SND_CMD_SEND_MOUSE;
|
||||
memcpy(&sdata[1], data, sizeof(sdata) - 2);
|
||||
md_calc_check_sum(sdata, sizeof(sdata) - 1);
|
||||
smsg_push(sdata, sizeof(sdata));
|
||||
}
|
||||
|
||||
void md_send_devinfo(const char *name) {
|
||||
uint8_t sdata[MD_SND_CMD_DEVINFO_LEN + 3] = {0x00};
|
||||
uint8_t infolen = strlen((const char *)name);
|
||||
|
||||
if (infolen > MD_SND_CMD_DEVINFO_LEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
sdata[0] = MD_SND_CMD_SEND_DEVINFO;
|
||||
sdata[1] = infolen;
|
||||
|
||||
memcpy(&sdata[2], name, infolen);
|
||||
md_calc_check_sum(sdata, infolen + 2);
|
||||
smsg_push(sdata, sizeof(sdata));
|
||||
}
|
||||
|
||||
void md_send_devctrl(uint8_t cmd) {
|
||||
uint8_t sdata[3] = {0x00};
|
||||
|
||||
sdata[0] = MD_SND_CMD_DEVCTRL;
|
||||
memcpy(&sdata[1], &cmd, sizeof(sdata) - 2);
|
||||
md_calc_check_sum(sdata, sizeof(sdata) - 1);
|
||||
smsg_push(sdata, sizeof(sdata));
|
||||
}
|
||||
|
||||
void md_send_manufacturer(char *str, uint8_t len) {
|
||||
uint8_t sdata[MD_SND_CMD_MANUFACTURER_LEN + 3] = {0x00};
|
||||
|
||||
if (len > MD_SND_CMD_MANUFACTURER_LEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
sdata[0] = MD_SND_CMD_MANUFACTURER;
|
||||
sdata[1] = len;
|
||||
memcpy(&sdata[2], str, len);
|
||||
md_calc_check_sum(sdata, len + 2);
|
||||
smsg_push(sdata, len + 3);
|
||||
}
|
||||
|
||||
void md_send_product(char *str, uint8_t len) {
|
||||
uint8_t sdata[MD_SND_CMD_PRODUCT_LEN + 3] = {0x00};
|
||||
|
||||
if (len > MD_SND_CMD_PRODUCT_LEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
sdata[0] = MD_SND_CMD_PRODUCT;
|
||||
sdata[1] = len;
|
||||
memcpy(&sdata[2], str, len);
|
||||
md_calc_check_sum(sdata, len + 2);
|
||||
smsg_push(sdata, len + 3);
|
||||
}
|
||||
|
||||
void md_send_vpid(uint16_t vid, uint16_t pid) {
|
||||
uint8_t sdata[4 + 2] = {0x00};
|
||||
uint32_t vpid;
|
||||
|
||||
vpid = (pid << 16) | vid;
|
||||
|
||||
sdata[0] = MD_SND_CMD_VPID;
|
||||
memcpy(&sdata[1], &vpid, sizeof(vpid));
|
||||
md_calc_check_sum(sdata, sizeof(sdata) - 1);
|
||||
smsg_push(sdata, sizeof(sdata));
|
||||
}
|
||||
|
||||
void md_send_raw(uint8_t *data, uint8_t length) {
|
||||
uint8_t sdata[MD_RAW_SIZE + 2] = {0x00};
|
||||
|
||||
if (length != MD_RAW_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
sdata[0] = MD_SND_CMD_RAW;
|
||||
memcpy(&sdata[1], data, length);
|
||||
md_calc_check_sum(sdata, sizeof(sdata) - 1);
|
||||
smsg_push(sdata, sizeof(sdata));
|
||||
}
|
||||
|
||||
void md_devs_change(uint8_t devs, bool reset) __attribute__((weak));
|
||||
void md_devs_change(uint8_t devs, bool reset) {
|
||||
|
||||
switch (devs) {
|
||||
case DEVS_USB: {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_USB);
|
||||
} break;
|
||||
case DEVS_2G4: {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_2G4);
|
||||
if (reset) {
|
||||
if (md_get_version() < 48) {
|
||||
md_send_manufacturer(MD_DONGLE_MANUFACTURER, strlen(MD_DONGLE_MANUFACTURER));
|
||||
md_send_product(MD_DONGLE_PRODUCT, strlen(MD_DONGLE_PRODUCT));
|
||||
} else { // Add Unicode character support starting from v48.
|
||||
md_send_manufacturer((char *)USBSTR(MD_DONGLE_MANUFACTURER), sizeof(USBSTR(MD_DONGLE_MANUFACTURER)));
|
||||
md_send_product((char *)USBSTR(MD_DONGLE_PRODUCT), sizeof(USBSTR(MD_DONGLE_PRODUCT)));
|
||||
}
|
||||
md_send_vpid(VENDOR_ID, PRODUCT_ID);
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_CLEAN);
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_PAIR);
|
||||
}
|
||||
} break;
|
||||
case DEVS_BT1: {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_BT1);
|
||||
if (reset) {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_CLEAN);
|
||||
md_send_devinfo(MD_BT1_NAME);
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_PAIR);
|
||||
}
|
||||
} break;
|
||||
case DEVS_BT2: {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_BT2);
|
||||
if (reset) {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_CLEAN);
|
||||
md_send_devinfo(MD_BT2_NAME);
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_PAIR);
|
||||
}
|
||||
} break;
|
||||
case DEVS_BT3: {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_BT3);
|
||||
if (reset) {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_CLEAN);
|
||||
md_send_devinfo(MD_BT3_NAME);
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_PAIR);
|
||||
}
|
||||
} break;
|
||||
case DEVS_BT4: {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_BT4);
|
||||
if (reset) {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_CLEAN);
|
||||
md_send_devinfo(MD_BT4_NAME);
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_PAIR);
|
||||
}
|
||||
} break;
|
||||
case DEVS_BT5: {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_BT5);
|
||||
if (reset) {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_CLEAN);
|
||||
md_send_devinfo(MD_BT5_NAME);
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_PAIR);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool md_inquire_bat(void) {
|
||||
|
||||
if (smsg_is_busy()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_INQVOL);
|
||||
|
||||
return true;
|
||||
}
|
135
keyboards/hator/rockfall3/common/wireless/module.h
Normal file
135
keyboards/hator/rockfall3/common/wireless/module.h
Normal file
@ -0,0 +1,135 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// device index
|
||||
enum {
|
||||
DEVS_USB = 0,
|
||||
DEVS_BT1,
|
||||
DEVS_BT2,
|
||||
DEVS_BT3,
|
||||
DEVS_BT4,
|
||||
DEVS_BT5,
|
||||
DEVS_2G4,
|
||||
};
|
||||
|
||||
enum {
|
||||
MD_STATE_NONE = 0,
|
||||
MD_STATE_PAIRING,
|
||||
MD_STATE_CONNECTED,
|
||||
MD_STATE_DISCONNECTED,
|
||||
MD_STATE_REJECT,
|
||||
};
|
||||
|
||||
enum {
|
||||
MD_SND_CMD_KB_LEN = 8,
|
||||
MD_SND_CMD_NKRO_LEN = 14,
|
||||
MD_SND_CMD_CONSUMER_LEN = 2,
|
||||
MD_SND_CMD_SYSTEM_LEN = 1,
|
||||
MD_SND_CMD_FN_LEN = 1,
|
||||
MD_SND_CMD_MOUSE_LEN = 5,
|
||||
MD_SND_CMD_DEVINFO_LEN = 18,
|
||||
MD_SND_CMD_MANUFACTURER_LEN = 46,
|
||||
MD_SND_CMD_PRODUCT_LEN = 46,
|
||||
};
|
||||
|
||||
enum {
|
||||
/* send report */
|
||||
MD_SND_CMD_SEND_KB = 0xA1,
|
||||
MD_SND_CMD_SEND_NKRO = 0xA2,
|
||||
MD_SND_CMD_SEND_CONSUMER = 0xA3,
|
||||
MD_SND_CMD_SEND_SYSTEM = 0xA4,
|
||||
MD_SND_CMD_SEND_FN = 0xA5,
|
||||
MD_SND_CMD_SEND_MOUSE = 0xA8,
|
||||
MD_SND_CMD_SEND_DEVINFO = 0xA9,
|
||||
/* Dongle */
|
||||
MD_SND_CMD_MANUFACTURER = 0xAB,
|
||||
MD_SND_CMD_PRODUCT = 0xAC,
|
||||
MD_SND_CMD_VPID = 0xAD,
|
||||
MD_SND_CMD_RAW = 0x91,
|
||||
/* device ctrl */
|
||||
MD_SND_CMD_DEVCTRL = 0xA6,
|
||||
MD_SND_CMD_DEVCTRL_USB = 0x11,
|
||||
MD_SND_CMD_DEVCTRL_2G4 = 0x30,
|
||||
MD_SND_CMD_DEVCTRL_BT1 = 0x31,
|
||||
MD_SND_CMD_DEVCTRL_BT2 = 0x32,
|
||||
MD_SND_CMD_DEVCTRL_BT3 = 0x33,
|
||||
MD_SND_CMD_DEVCTRL_BT4 = 0x34,
|
||||
MD_SND_CMD_DEVCTRL_BT5 = 0x35,
|
||||
MD_SND_CMD_DEVCTRL_PAIR = 0x51,
|
||||
MD_SND_CMD_DEVCTRL_CLEAN = 0x52,
|
||||
MD_SND_CMD_DEVCTRL_INQVOL = 0x53,
|
||||
MD_SND_CMD_DEVCTRL_SLEEP_INSTANT = 0x54, // reserved
|
||||
MD_SND_CMD_DEVCTRL_SLEEP_BT_EN = 0x55, // timeout 30min enable in BT mode
|
||||
MD_SND_CMD_DEVCTRL_SLEEP_BT_DIS = 0x56, // timeout 30min disable in BT mode
|
||||
MD_SND_CMD_DEVCTRL_SLEEP_2G4_EN = 0x57, // timeout 30min enable in 2.4G mode
|
||||
MD_SND_CMD_DEVCTRL_SLEEP_2G4_DIS = 0x58, // timeout 30min enable in 2.4G mode
|
||||
MD_SND_CMD_DEVCTRL_RSV_DEBUG = 0x60, // reserved
|
||||
MD_SND_CMD_DEVCTRL_RSV_SLEEP = 0x61, // reserved
|
||||
MD_SND_CMD_DEVCTRL_FORCED_PAIRING_BT = 0x62, // forced pairing, to be used in a factory environment.
|
||||
MD_SND_CMD_DEVCTRL_FORCED_PAIRING_2G4 = 0x63, // forced pairing, to be used in a factory environment.
|
||||
MD_SND_CMD_DEVCTRL_CHARGING = 0x64, // battery power control.
|
||||
MD_SND_CMD_DEVCTRL_CHARGING_STOP = 0x65, // battery power control.
|
||||
MD_SND_CMD_DEVCTRL_CHARGING_DONE = 0x66, // battery power control.
|
||||
MD_SND_CMD_DEVCTRL_FW_VERSION = 0x70, // module fw version.
|
||||
MD_SND_CMD_INVALID_DATA = 0x00, // unused
|
||||
};
|
||||
|
||||
enum {
|
||||
MD_REV_CMD_RAW = 0x81,
|
||||
MD_REV_CMD_INDICATOR = 0x5A,
|
||||
MD_REV_CMD_DEVCTRL = 0x5B,
|
||||
MD_REV_CMD_DEVCTRL_BAT_LOW = 0x21, // unused
|
||||
MD_REV_CMD_DEVCTRL_BAT_PWROFF = 0x22, // unused
|
||||
MD_REV_CMD_DEVCTRL_BAT_NORMAL = 0x23, // unused
|
||||
MD_REV_CMD_DEVCTRL_PAIRING = 0x31,
|
||||
MD_REV_CMD_DEVCTRL_CONNECTED = 0x32,
|
||||
MD_REV_CMD_DEVCTRL_DISCONNECTED = 0x33,
|
||||
MD_REV_CMD_DEVCTRL_DONE = 0x34, // reserved
|
||||
MD_REV_CMD_DEVCTRL_RECONNECT = 0x35, // reserved
|
||||
MD_REV_CMD_DEVCTRL_REJECT = 0x36,
|
||||
MD_REV_CMD_DEVCTRL_UNPAIRED = 0x37, // reserved
|
||||
MD_REV_CMD_DEVCTRL_MD_WAKEUP = 0x42, // unused
|
||||
MD_REV_CMD_DEVCTRL_CLS_UART = 0x43, // unused
|
||||
MD_REV_CMD_BATVOL = 0x5C,
|
||||
MD_REV_CMD_MD_FW_VERSION = 0x5D,
|
||||
MD_REV_CMD_HOST_STATE = 0x60,
|
||||
MD_REV_CMD_HOST_STATE_SUSPEND = 0x00,
|
||||
MD_REV_CMD_HOST_STATE_RESUME = 0x01,
|
||||
};
|
||||
|
||||
void md_init(void);
|
||||
void md_main_task(void);
|
||||
void md_send_kb(uint8_t *data);
|
||||
void md_send_nkro(uint8_t *data);
|
||||
void md_send_consumer(uint8_t *data);
|
||||
void md_send_system(uint8_t *data);
|
||||
void md_send_fn(uint8_t *data);
|
||||
void md_send_mouse(uint8_t *data);
|
||||
void md_send_devctrl(uint8_t cmd);
|
||||
void md_send_manufacturer(char *str, uint8_t len);
|
||||
void md_send_product(char *str, uint8_t len);
|
||||
void md_send_vpid(uint16_t vid, uint16_t pid);
|
||||
void md_send_raw(uint8_t *data, uint8_t length);
|
||||
bool md_send_pkt(uint8_t *data, uint32_t len);
|
||||
bool md_receive_process_user(uint8_t *pdata, uint8_t len);
|
||||
void md_devs_change(uint8_t devs, bool reset);
|
||||
bool md_inquire_bat(void);
|
||||
uint8_t md_get_version(void);
|
||||
uint8_t *md_getp_state(void);
|
||||
uint8_t *md_getp_bat(void);
|
||||
uint8_t *md_getp_indicator(void);
|
135
keyboards/hator/rockfall3/common/wireless/smsg.c
Normal file
135
keyboards/hator/rockfall3/common/wireless/smsg.c
Normal file
@ -0,0 +1,135 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "smsg.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifndef SMSG_NUM
|
||||
# define SMSG_NUM 40
|
||||
#endif
|
||||
|
||||
#ifndef SMSG_PAYLOAD_LEN
|
||||
# define SMSG_PAYLOAD_LEN 50
|
||||
#endif
|
||||
|
||||
#define SMSG_BUF_SIZE (SMSG_NUM * SMSG_PAYLOAD_LEN)
|
||||
#define END_PTR ((smsg_ptr_t *)&smsg_instance.ptr[SMSG_NUM - 1])
|
||||
#define FREE_SPACE ((uint32_t)(&smsg_buffer[SMSG_BUF_SIZE - 1] - smsg_instance.buffer))
|
||||
|
||||
typedef struct {
|
||||
uint8_t *head;
|
||||
uint8_t *tail;
|
||||
} smsg_ptr_t;
|
||||
|
||||
typedef struct {
|
||||
smsg_states_t state;
|
||||
smsg_ptr_t *ptr;
|
||||
smsg_ptr_t *in_ptr;
|
||||
smsg_ptr_t *out_ptr;
|
||||
uint8_t *buffer;
|
||||
} smsg_t;
|
||||
|
||||
static smsg_ptr_t smsg_ptr[SMSG_NUM];
|
||||
static uint8_t smsg_buffer[SMSG_BUF_SIZE];
|
||||
static smsg_t smsg_instance;
|
||||
|
||||
void smsg_init(void) {
|
||||
|
||||
smsg_instance.buffer = smsg_buffer;
|
||||
smsg_instance.ptr = smsg_ptr;
|
||||
smsg_instance.ptr->head = smsg_instance.buffer;
|
||||
smsg_instance.ptr->tail = smsg_instance.buffer;
|
||||
smsg_instance.in_ptr = smsg_instance.ptr;
|
||||
smsg_instance.out_ptr = smsg_instance.ptr;
|
||||
smsg_instance.state = smsg_state_free;
|
||||
}
|
||||
|
||||
bool smsg_push(uint8_t *buf, uint32_t size) {
|
||||
|
||||
if (smsg_instance.in_ptr == END_PTR) {
|
||||
if (smsg_instance.ptr == smsg_instance.out_ptr) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ((smsg_instance.in_ptr + 1) == smsg_instance.out_ptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (FREE_SPACE < SMSG_PAYLOAD_LEN) {
|
||||
smsg_instance.buffer = smsg_buffer;
|
||||
}
|
||||
|
||||
if (size > SMSG_PAYLOAD_LEN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(smsg_instance.buffer, buf, size);
|
||||
smsg_instance.in_ptr->head = smsg_instance.buffer;
|
||||
smsg_instance.buffer += size;
|
||||
smsg_instance.in_ptr->tail = smsg_instance.buffer;
|
||||
if (smsg_instance.in_ptr == END_PTR) {
|
||||
smsg_instance.in_ptr = smsg_instance.ptr;
|
||||
} else {
|
||||
smsg_instance.in_ptr++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t smsg_peek(uint8_t *buf) {
|
||||
|
||||
if (smsg_instance.out_ptr != smsg_instance.in_ptr) {
|
||||
uint32_t size;
|
||||
|
||||
size = smsg_instance.out_ptr->tail - smsg_instance.out_ptr->head;
|
||||
memcpy(buf, smsg_instance.out_ptr->head, size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void smsg_pop(void) {
|
||||
|
||||
if (smsg_instance.out_ptr != smsg_instance.in_ptr) {
|
||||
if (smsg_instance.out_ptr == END_PTR) {
|
||||
smsg_instance.out_ptr = smsg_instance.ptr;
|
||||
} else {
|
||||
smsg_instance.out_ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
smsg_states_t smsg_get_state(void) {
|
||||
|
||||
return smsg_instance.state;
|
||||
}
|
||||
|
||||
void smsg_set_state(smsg_states_t state) {
|
||||
|
||||
smsg_instance.state = state;
|
||||
}
|
||||
|
||||
bool smsg_is_busy(void) {
|
||||
|
||||
if (smsg_instance.out_ptr != smsg_instance.in_ptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
35
keyboards/hator/rockfall3/common/wireless/smsg.h
Normal file
35
keyboards/hator/rockfall3/common/wireless/smsg.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum {
|
||||
smsg_state_free = 0,
|
||||
smsg_state_busy,
|
||||
smsg_state_retry,
|
||||
smsg_state_replied
|
||||
} smsg_states_t;
|
||||
|
||||
void smsg_init(void);
|
||||
bool smsg_push(uint8_t *buf, uint32_t size);
|
||||
uint32_t smsg_peek(uint8_t *buf);
|
||||
void smsg_pop(void);
|
||||
smsg_states_t smsg_get_state(void);
|
||||
void smsg_set_state(smsg_states_t state);
|
||||
bool smsg_is_busy(void);
|
180
keyboards/hator/rockfall3/common/wireless/transport.c
Normal file
180
keyboards/hator/rockfall3/common/wireless/transport.c
Normal file
@ -0,0 +1,180 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "quantum.h"
|
||||
#include "module.h"
|
||||
#include "usb_main.h"
|
||||
#include "transport.h"
|
||||
|
||||
#ifndef USB_POWER_DOWN_DELAY
|
||||
# define USB_POWER_DOWN_DELAY 3000
|
||||
#endif
|
||||
|
||||
extern host_driver_t chibios_driver;
|
||||
extern host_driver_t wireless_driver;
|
||||
|
||||
static transport_t transport = TRANSPORT_USB;
|
||||
|
||||
void wls_transport_enable(bool enable) __attribute__((weak));
|
||||
void wls_transport_enable(bool enable) {
|
||||
|
||||
if (enable) {
|
||||
if (host_get_driver() != &wireless_driver) {
|
||||
host_set_driver(&wireless_driver);
|
||||
usb_device_state_set_protocol(true); // default with true
|
||||
}
|
||||
} else {
|
||||
if (*md_getp_state() == MD_STATE_CONNECTED) {
|
||||
wireless_driver.send_keyboard(NULL);
|
||||
wireless_driver.send_nkro(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Control USB device connection and disconnection by
|
||||
* controlling the power supply of the USB DP pull-up resistor.
|
||||
* Overwrite these two functions. */
|
||||
void usb_power_connect(void) __attribute__((weak));
|
||||
void usb_power_connect(void) {}
|
||||
|
||||
void usb_power_disconnect(void) __attribute__((weak));
|
||||
void usb_power_disconnect(void) {}
|
||||
|
||||
void usb_transport_enable(bool enable) __attribute__((weak));
|
||||
void usb_transport_enable(bool enable) {
|
||||
|
||||
if (enable) {
|
||||
if (host_get_driver() != &chibios_driver) {
|
||||
extern bool last_suspend_state;
|
||||
|
||||
/* This flag is not set to 1 with probability after usb restart */
|
||||
last_suspend_state = true;
|
||||
#if !defined(KEEP_USB_CONNECTION_IN_WIRELESS_MODE)
|
||||
usb_power_connect();
|
||||
restart_usb_driver(&USBD1);
|
||||
#endif
|
||||
host_set_driver(&chibios_driver);
|
||||
}
|
||||
} else {
|
||||
if (USB_DRIVER.state == USB_ACTIVE) {
|
||||
report_keyboard_t empty_report = {0};
|
||||
report_nkro_t empty_nkro_report = {0};
|
||||
host_keyboard_send(&empty_report);
|
||||
host_nkro_send(&empty_nkro_report);
|
||||
}
|
||||
|
||||
#if !defined(KEEP_USB_CONNECTION_IN_WIRELESS_MODE)
|
||||
usbStop(&USBD1);
|
||||
usbDisconnectBus(&USBD1);
|
||||
usb_power_disconnect();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void set_transport(transport_t new_transport) {
|
||||
|
||||
transport = new_transport;
|
||||
|
||||
switch (transport) {
|
||||
case TRANSPORT_USB: {
|
||||
usb_transport_enable(true);
|
||||
wls_transport_enable(false);
|
||||
} break;
|
||||
case TRANSPORT_WLS: {
|
||||
wls_transport_enable(true);
|
||||
usb_transport_enable(false);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
transport_t get_transport(void) {
|
||||
|
||||
return transport;
|
||||
}
|
||||
|
||||
void usb_remote_wakeup(void) {
|
||||
|
||||
#ifdef USB_REMOTE_USE_QMK
|
||||
if (USB_DRIVER.state == USB_SUSPENDED) {
|
||||
dprintln("suspending keyboard");
|
||||
while (USB_DRIVER.state == USB_SUSPENDED) {
|
||||
/* Do this in the suspended state */
|
||||
suspend_power_down(); // on AVR this deep sleeps for 15ms
|
||||
/* Remote wakeup */
|
||||
if ((USB_DRIVER.status & 2U) && suspend_wakeup_condition()) {
|
||||
usbWakeupHost(&USB_DRIVER);
|
||||
# if USB_SUSPEND_WAKEUP_DELAY > 0
|
||||
// Some hubs, kvm switches, and monitors do
|
||||
// weird things, with USB device state bouncing
|
||||
// around wildly on wakeup, yielding race
|
||||
// conditions that can corrupt the keyboard state.
|
||||
//
|
||||
// Pause for a while to let things settle...
|
||||
wait_ms(USB_SUSPEND_WAKEUP_DELAY);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
/* Woken up */
|
||||
}
|
||||
#else
|
||||
static uint32_t suspend_timer = 0x00;
|
||||
|
||||
if ((USB_DRIVER.state == USB_SUSPENDED)) {
|
||||
if (!suspend_timer) suspend_timer = sync_timer_read32();
|
||||
if (sync_timer_elapsed32(suspend_timer) >= USB_POWER_DOWN_DELAY) {
|
||||
suspend_timer = 0x00;
|
||||
suspend_power_down();
|
||||
}
|
||||
} else {
|
||||
suspend_timer = 0x00;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef USB_REMOTE_USE_QMK
|
||||
void usb_remote_host(void) {
|
||||
|
||||
if (USB_DRIVER.state == USB_SUSPENDED) {
|
||||
if ((USB_DRIVER.status & 2U) && suspend_wakeup_condition()) {
|
||||
usbWakeupHost(&USB_DRIVER);
|
||||
# if USB_SUSPEND_WAKEUP_DELAY > 0
|
||||
// Some hubs, kvm switches, and monitors do
|
||||
// weird things, with USB device state bouncing
|
||||
// around wildly on wakeup, yielding race
|
||||
// conditions that can corrupt the keyboard state.
|
||||
//
|
||||
// Pause for a while to let things settle...
|
||||
wait_ms(USB_SUSPEND_WAKEUP_DELAY);
|
||||
# endif
|
||||
}
|
||||
# if !defined(USB_REMOTE_USE_QMK) && USB_POWER_DOWN_DELAY
|
||||
suspend_wakeup_init();
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
bool process_action_kb(keyrecord_t *record) {
|
||||
|
||||
(void)record;
|
||||
if (get_transport() == TRANSPORT_USB){
|
||||
usb_remote_host();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
31
keyboards/hator/rockfall3/common/wireless/transport.h
Normal file
31
keyboards/hator/rockfall3/common/wireless/transport.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
TRANSPORT_NONE,
|
||||
TRANSPORT_USB,
|
||||
TRANSPORT_WLS,
|
||||
} transport_t;
|
||||
|
||||
void wls_transport_enable(bool enable);
|
||||
void usb_transport_enable(bool enable);
|
||||
void set_transport(transport_t new_transport);
|
||||
transport_t get_transport(void);
|
||||
void usb_power_connect(void);
|
||||
void usb_power_disconnect(void);
|
||||
void usb_remote_wakeup(void);
|
278
keyboards/hator/rockfall3/common/wireless/wireless.c
Normal file
278
keyboards/hator/rockfall3/common/wireless/wireless.c
Normal file
@ -0,0 +1,278 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "quantum.h"
|
||||
#include "wireless.h"
|
||||
|
||||
#ifndef WLS_INQUIRY_BAT_TIME
|
||||
# define WLS_INQUIRY_BAT_TIME 3000
|
||||
#endif
|
||||
|
||||
#ifndef WLS_KEYBOARD_REPORT_KEYS
|
||||
# define WLS_KEYBOARD_REPORT_KEYS KEYBOARD_REPORT_KEYS
|
||||
#endif
|
||||
|
||||
static uint8_t wls_devs = DEVS_USB;
|
||||
|
||||
void last_matrix_activity_trigger(void);
|
||||
|
||||
uint8_t wireless_keyboard_leds(void);
|
||||
void wireless_send_keyboard(report_keyboard_t *report);
|
||||
void wireless_send_nkro(report_nkro_t *report);
|
||||
void wireless_send_mouse(report_mouse_t *report);
|
||||
void wireless_send_extra(report_extra_t *report);
|
||||
|
||||
host_driver_t wireless_driver = {
|
||||
.keyboard_leds = wireless_keyboard_leds,
|
||||
.send_keyboard = wireless_send_keyboard,
|
||||
.send_nkro = wireless_send_nkro,
|
||||
.send_mouse = wireless_send_mouse,
|
||||
.send_extra = wireless_send_extra,
|
||||
};
|
||||
|
||||
void wireless_init(void) {
|
||||
|
||||
md_init();
|
||||
}
|
||||
|
||||
uint8_t wireless_keyboard_leds(void) __attribute__((weak));
|
||||
uint8_t wireless_keyboard_leds(void) {
|
||||
|
||||
if (*md_getp_state() == MD_STATE_CONNECTED) {
|
||||
return *md_getp_indicator();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wireless_send_keyboard(report_keyboard_t *report) __attribute__((weak));
|
||||
void wireless_send_keyboard(report_keyboard_t *report) {
|
||||
uint8_t wls_report_kb[MD_SND_CMD_KB_LEN] = {0};
|
||||
|
||||
if (*md_getp_state() != MD_STATE_CONNECTED) {
|
||||
wireless_devs_change(wls_devs, wls_devs, false);
|
||||
return;
|
||||
}
|
||||
|
||||
_Static_assert((MD_SND_CMD_KB_LEN) - (WLS_KEYBOARD_REPORT_KEYS) >= 2, "WLS_KEYBOARD_REPORT_KEYS cannot be greater than MD_SND_CMD_KB_LEN - 2.");
|
||||
|
||||
if (report != NULL) {
|
||||
memcpy(wls_report_kb, (uint8_t *)&report->mods, WLS_KEYBOARD_REPORT_KEYS + 2);
|
||||
}
|
||||
|
||||
md_send_kb(wls_report_kb);
|
||||
}
|
||||
|
||||
void wireless_send_nkro(report_nkro_t *report) __attribute__((weak));
|
||||
void wireless_send_nkro(report_nkro_t *report) {
|
||||
static report_keyboard_t temp_report_keyboard = {0};
|
||||
uint8_t wls_report_nkro[MD_SND_CMD_NKRO_LEN] = {0};
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
if (*md_getp_state() != MD_STATE_CONNECTED) {
|
||||
wireless_devs_change(wls_devs, wls_devs, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (report != NULL) {
|
||||
report_nkro_t temp_report_nkro = *report;
|
||||
uint8_t key_count = 0;
|
||||
|
||||
temp_report_keyboard.mods = temp_report_nkro.mods;
|
||||
for (uint8_t i = 0; i < NKRO_REPORT_BITS; i++) {
|
||||
key_count += __builtin_popcount(temp_report_nkro.bits[i]);
|
||||
}
|
||||
|
||||
// find key up and del it.
|
||||
uint8_t nkro_keys = key_count;
|
||||
for (uint8_t i = 0; i < WLS_KEYBOARD_REPORT_KEYS && temp_report_keyboard.keys[i]; i++) {
|
||||
report_nkro_t found_report_nkro;
|
||||
uint8_t usageid = 0x00;
|
||||
uint8_t n;
|
||||
|
||||
found_report_nkro = temp_report_nkro;
|
||||
|
||||
for (uint8_t c = 0; c < nkro_keys; c++) {
|
||||
for (n = 0; n < NKRO_REPORT_BITS && !found_report_nkro.bits[n]; n++) {}
|
||||
usageid = (n << 3) | biton(found_report_nkro.bits[n]);
|
||||
del_key_bit(&found_report_nkro, usageid);
|
||||
if (usageid == temp_report_keyboard.keys[i]) {
|
||||
del_key_bit(&temp_report_nkro, usageid);
|
||||
nkro_keys--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (usageid != temp_report_keyboard.keys[i]) {
|
||||
temp_report_keyboard.keys[i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Use NKRO for sending when more than 6 keys are pressed
|
||||
* to solve the issue of the lack of a protocol flag in wireless mode.
|
||||
*/
|
||||
|
||||
temp_report_nkro = *report;
|
||||
|
||||
for (uint8_t i = 0; i < key_count; i++) {
|
||||
uint8_t usageid;
|
||||
uint8_t idx, n = 0;
|
||||
|
||||
for (n = 0; n < NKRO_REPORT_BITS && !temp_report_nkro.bits[n]; n++) {}
|
||||
usageid = (n << 3) | biton(temp_report_nkro.bits[n]);
|
||||
del_key_bit(&temp_report_nkro, usageid);
|
||||
|
||||
for (idx = 0; idx < WLS_KEYBOARD_REPORT_KEYS; idx++) {
|
||||
if (temp_report_keyboard.keys[idx] == usageid) {
|
||||
break;
|
||||
}
|
||||
if (temp_report_keyboard.keys[idx] == 0x00) {
|
||||
temp_report_keyboard.keys[idx] = usageid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx == WLS_KEYBOARD_REPORT_KEYS && (usageid < (MD_SND_CMD_NKRO_LEN * 8))) {
|
||||
wls_report_nkro[usageid / 8] |= 0x01 << (usageid % 8);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memset(&temp_report_keyboard, 0, sizeof(temp_report_keyboard));
|
||||
}
|
||||
#endif
|
||||
|
||||
wireless_driver.send_keyboard(&temp_report_keyboard);
|
||||
md_send_nkro(wls_report_nkro);
|
||||
}
|
||||
|
||||
void wireless_send_mouse(report_mouse_t *report) __attribute__((weak));
|
||||
void wireless_send_mouse(report_mouse_t *report) {
|
||||
typedef struct {
|
||||
uint8_t buttons;
|
||||
int8_t x;
|
||||
int8_t y;
|
||||
int8_t z;
|
||||
int8_t h;
|
||||
} __attribute__((packed)) wls_report_mouse_t;
|
||||
|
||||
wls_report_mouse_t wls_report_mouse = {0};
|
||||
|
||||
if (*md_getp_state() != MD_STATE_CONNECTED) {
|
||||
wireless_devs_change(wls_devs, wls_devs, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (report != NULL) {
|
||||
wls_report_mouse.buttons = report->buttons;
|
||||
wls_report_mouse.x = report->x;
|
||||
wls_report_mouse.y = report->y;
|
||||
wls_report_mouse.z = report->h;
|
||||
wls_report_mouse.h = report->v;
|
||||
}
|
||||
|
||||
md_send_mouse((uint8_t *)&wls_report_mouse);
|
||||
}
|
||||
|
||||
void wireless_send_extra(report_extra_t *report) __attribute__((weak));
|
||||
void wireless_send_extra(report_extra_t *report) {
|
||||
uint16_t usage = 0;
|
||||
|
||||
if (*md_getp_state() != MD_STATE_CONNECTED) {
|
||||
wireless_devs_change(wls_devs, wls_devs, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (report != NULL) {
|
||||
usage = report->usage;
|
||||
|
||||
switch (usage) {
|
||||
case 0x81:
|
||||
case 0x82:
|
||||
case 0x83: { // system usage
|
||||
usage = 0x01 << (usage - 0x81);
|
||||
md_send_system((uint8_t *)&usage);
|
||||
} break;
|
||||
default: {
|
||||
md_send_consumer((uint8_t *)&usage);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wireless_devs_change_user(uint8_t old_devs, uint8_t new_devs, bool reset) __attribute__((weak));
|
||||
void wireless_devs_change_user(uint8_t old_devs, uint8_t new_devs, bool reset) {}
|
||||
|
||||
void wireless_devs_change_kb(uint8_t old_devs, uint8_t new_devs, bool reset) __attribute__((weak));
|
||||
void wireless_devs_change_kb(uint8_t old_devs, uint8_t new_devs, bool reset) {}
|
||||
|
||||
void wireless_devs_change(uint8_t old_devs, uint8_t new_devs, bool reset) {
|
||||
bool changed = (old_devs == DEVS_USB) ? (new_devs != DEVS_USB) : (new_devs == DEVS_USB);
|
||||
|
||||
if (changed) {
|
||||
set_transport((new_devs != DEVS_USB) ? TRANSPORT_WLS : TRANSPORT_USB);
|
||||
}
|
||||
|
||||
if ((wls_devs != new_devs) || reset) {
|
||||
*md_getp_state() = MD_STATE_DISCONNECTED;
|
||||
*md_getp_indicator() = 0;
|
||||
}
|
||||
|
||||
wls_devs = new_devs;
|
||||
last_matrix_activity_trigger();
|
||||
|
||||
md_devs_change(new_devs, reset);
|
||||
wireless_devs_change_kb(old_devs, new_devs, reset);
|
||||
wireless_devs_change_user(old_devs, new_devs, reset);
|
||||
}
|
||||
|
||||
uint8_t wireless_get_current_devs(void) {
|
||||
return wls_devs;
|
||||
}
|
||||
|
||||
void wireless_pre_task(void) __attribute__((weak));
|
||||
void wireless_pre_task(void) {}
|
||||
|
||||
void wireless_post_task(void) __attribute__((weak));
|
||||
void wireless_post_task(void) {}
|
||||
|
||||
void wireless_task(void) {
|
||||
|
||||
wireless_pre_task();
|
||||
lpwr_task();
|
||||
md_main_task();
|
||||
wireless_post_task();
|
||||
|
||||
/* usb_remote_wakeup() should be invoked last so that we have chance
|
||||
* to switch to wireless after start-up when usb is not connected
|
||||
*/
|
||||
if (get_transport() == TRANSPORT_USB) {
|
||||
usb_remote_wakeup();
|
||||
} else if (lpwr_get_state() == LPWR_NORMAL) {
|
||||
static uint32_t inqtimer = 0x00;
|
||||
|
||||
if (sync_timer_elapsed32(inqtimer) >= (WLS_INQUIRY_BAT_TIME)) {
|
||||
if (md_inquire_bat()) {
|
||||
inqtimer = sync_timer_read32();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void housekeeping_task_kb(void) {
|
||||
|
||||
wireless_task();
|
||||
}
|
27
keyboards/hator/rockfall3/common/wireless/wireless.h
Normal file
27
keyboards/hator/rockfall3/common/wireless/wireless.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "transport.h"
|
||||
#include "lowpower.h"
|
||||
#include "module.h"
|
||||
|
||||
void wireless_init(void);
|
||||
void wireless_devs_change(uint8_t old_devs, uint8_t new_devs, bool reset);
|
||||
uint8_t wireless_get_current_devs(void);
|
||||
void wireless_pre_task(void);
|
||||
void wireless_post_task(void);
|
26
keyboards/hator/rockfall3/common/wireless/wireless.mk
Normal file
26
keyboards/hator/rockfall3/common/wireless/wireless.mk
Normal file
@ -0,0 +1,26 @@
|
||||
WIRELESS_ENABLE ?= yes
|
||||
WIRELESS_DIR = $(TOP_DIR)/keyboards/hator/rockfall3/common/wireless
|
||||
|
||||
ifeq ($(strip $(WIRELESS_ENABLE)), yes)
|
||||
OPT_DEFS += -DWIRELESS_ENABLE -DNO_USB_STARTUP_CHECK
|
||||
|
||||
OPT_DEFS += -include $(WIRELESS_DIR)/md_raw.h
|
||||
|
||||
UART_DRIVER_REQUIRED ?= yes
|
||||
WIRELESS_LPWR_STOP_ENABLE ?= yes
|
||||
|
||||
VPATH += $(WIRELESS_DIR)
|
||||
|
||||
SRC += \
|
||||
$(WIRELESS_DIR)/wireless.c \
|
||||
$(WIRELESS_DIR)/transport.c \
|
||||
$(WIRELESS_DIR)/lowpower.c \
|
||||
$(WIRELESS_DIR)/md_raw.c \
|
||||
$(WIRELESS_DIR)/smsg.c \
|
||||
$(WIRELESS_DIR)/module.c
|
||||
|
||||
ifeq ($(strip $(WIRELESS_LPWR_STOP_ENABLE)), yes)
|
||||
OPT_DEFS += -DWIRELESS_LPWR_STOP_ENABLE
|
||||
SRC += $(WIRELESS_DIR)/lpwr_wb32.c
|
||||
endif
|
||||
endif
|
58
keyboards/hator/rockfall3/htk850/config.h
Normal file
58
keyboards/hator/rockfall3/htk850/config.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef WIRELESS_ENABLE
|
||||
# define LPWR_TIMEOUT RGB_MATRIX_TIMEOUT
|
||||
# define WLS_KEYBOARD_REPORT_KEYS 5
|
||||
# undef LPWR_TIMEOUT
|
||||
# define LPWR_TIMEOUT 600000 // 10min
|
||||
|
||||
#endif
|
||||
|
||||
#define USB_POWER_EN_PIN A14
|
||||
#define LED_POWER_EN_PIN A15
|
||||
|
||||
# define BT_CABLE_PIN B8 //
|
||||
# define BT_CHARGE_PIN B9 //
|
||||
|
||||
# define BT_MODE_SW_PIN C10 //
|
||||
# define RF_MODE_SW_PIN D2 //
|
||||
|
||||
/* UART */
|
||||
#define UART_TX_PIN A9
|
||||
#define UART_RX_PIN A10
|
||||
#define UART_RX_PAL_MODE 7
|
||||
|
||||
/* SPI Config for spi flash*/
|
||||
#define SPI_DRIVER SPIDQ
|
||||
#define SPI_SCK_PIN B3
|
||||
#define SPI_MOSI_PIN B5
|
||||
#define SPI_MISO_PIN B4
|
||||
#define SPI_MOSI_PAL_MODE 5
|
||||
|
||||
#define EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN C12
|
||||
#define WEAR_LEVELING_LOGICAL_SIZE (WEAR_LEVELING_BACKING_SIZE / 2)
|
||||
|
||||
/* I2C Config for LED Driver */
|
||||
#define SNLED27351_I2C_ADDRESS_1 0b1110100
|
||||
#define SNLED27351_I2C_ADDRESS_2 0b1110111
|
||||
#define I2C1_OPMODE OPMODE_I2C
|
||||
#define I2C1_CLOCK_SPEED 400000 /* 400000 */
|
||||
|
||||
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
|
||||
#define RGB_MATRIX_KEYPRESSES
|
24
keyboards/hator/rockfall3/htk850/halconf.h
Normal file
24
keyboards/hator/rockfall3/htk850/halconf.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define HAL_USE_I2C TRUE
|
||||
#define HAL_USE_SERIAL TRUE
|
||||
#define HAL_USE_SPI TRUE
|
||||
#define PAL_USE_CALLBACKS TRUE
|
||||
|
||||
#include_next <halconf.h>
|
690
keyboards/hator/rockfall3/htk850/htk850.c
Normal file
690
keyboards/hator/rockfall3/htk850/htk850.c
Normal file
@ -0,0 +1,690 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
#ifdef WIRELESS_ENABLE
|
||||
# include "wireless.h"
|
||||
#endif
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
const snled27351_led_t PROGMEM g_snled27351_leds[SNLED27351_LED_COUNT] = {
|
||||
/* Refer to IS31 manual for these locations
|
||||
* driver
|
||||
* | R location
|
||||
* | | G location
|
||||
* | | | B location
|
||||
* | | | | */
|
||||
{1, CB1_CA1, CB2_CA1, CB3_CA1},
|
||||
{1, CB1_CA2, CB2_CA2, CB3_CA2},
|
||||
{1, CB1_CA3, CB2_CA3, CB3_CA3},
|
||||
{1, CB1_CA4, CB2_CA4, CB3_CA4},
|
||||
{1, CB1_CA5, CB2_CA5, CB3_CA5},
|
||||
{1, CB1_CA6, CB2_CA6, CB3_CA6},
|
||||
{1, CB1_CA7, CB2_CA7, CB3_CA7},
|
||||
{1, CB1_CA8, CB2_CA8, CB3_CA8},
|
||||
{1, CB1_CA9, CB2_CA9, CB3_CA9},
|
||||
{1, CB1_CA10, CB2_CA10, CB3_CA10},
|
||||
{1, CB1_CA11, CB2_CA11, CB3_CA11},
|
||||
{1, CB1_CA12, CB2_CA12, CB3_CA12},
|
||||
{1, CB1_CA13, CB2_CA13, CB3_CA13},
|
||||
{1, CB1_CA14, CB2_CA14, CB3_CA14},
|
||||
{1, CB1_CA15, CB2_CA15, CB3_CA15},
|
||||
{1, CB1_CA16, CB2_CA16, CB3_CA16},
|
||||
|
||||
{0, CB1_CA1, CB2_CA1, CB3_CA1},
|
||||
{0, CB1_CA2, CB2_CA2, CB3_CA2},
|
||||
{0, CB1_CA3, CB2_CA3, CB3_CA3},
|
||||
{0, CB1_CA4, CB2_CA4, CB3_CA4},
|
||||
{0, CB1_CA5, CB2_CA5, CB3_CA5},
|
||||
{0, CB1_CA6, CB2_CA6, CB3_CA6},
|
||||
{0, CB1_CA7, CB2_CA7, CB3_CA7},
|
||||
{0, CB1_CA8, CB2_CA8, CB3_CA8},
|
||||
{0, CB1_CA9, CB2_CA9, CB3_CA9},
|
||||
{0, CB1_CA10, CB2_CA10, CB3_CA10},
|
||||
{0, CB1_CA11, CB2_CA11, CB3_CA11},
|
||||
{0, CB1_CA12, CB2_CA12, CB3_CA12},
|
||||
{0, CB1_CA13, CB2_CA13, CB3_CA13},
|
||||
{0, CB1_CA14, CB2_CA14, CB3_CA14},
|
||||
{1, CB4_CA1, CB5_CA1, CB6_CA1},
|
||||
{1, CB4_CA3, CB5_CA3, CB6_CA3},
|
||||
{1, CB4_CA5, CB5_CA5, CB6_CA5},
|
||||
|
||||
{0, CB4_CA1, CB5_CA1, CB6_CA1},
|
||||
{0, CB4_CA2, CB5_CA2, CB6_CA2},
|
||||
{0, CB4_CA3, CB5_CA3, CB6_CA3},
|
||||
{0, CB4_CA4, CB5_CA4, CB6_CA4},
|
||||
{0, CB4_CA5, CB5_CA5, CB6_CA5},
|
||||
{0, CB4_CA6, CB5_CA6, CB6_CA6},
|
||||
{0, CB4_CA7, CB5_CA7, CB6_CA7},
|
||||
{0, CB4_CA8, CB5_CA8, CB6_CA8},
|
||||
{0, CB4_CA9, CB5_CA9, CB6_CA9},
|
||||
{0, CB4_CA10, CB5_CA10, CB6_CA10},
|
||||
{0, CB4_CA11, CB5_CA11, CB6_CA11},
|
||||
{0, CB4_CA12, CB5_CA12, CB6_CA12},
|
||||
{0, CB4_CA13, CB5_CA13, CB6_CA13},
|
||||
{0, CB4_CA14, CB5_CA14, CB6_CA14},
|
||||
{1, CB4_CA2, CB5_CA2, CB6_CA2},
|
||||
{1, CB4_CA4, CB5_CA4, CB6_CA4},
|
||||
{1, CB4_CA6, CB5_CA6, CB6_CA6},
|
||||
|
||||
{0, CB7_CA1, CB8_CA1, CB9_CA1},
|
||||
{0, CB7_CA2, CB8_CA2, CB9_CA2},
|
||||
{0, CB7_CA3, CB8_CA3, CB9_CA3},
|
||||
{0, CB7_CA4, CB8_CA4, CB9_CA4},
|
||||
{0, CB7_CA5, CB8_CA5, CB9_CA5},
|
||||
{0, CB7_CA6, CB8_CA6, CB9_CA6},
|
||||
{0, CB7_CA7, CB8_CA7, CB9_CA7},
|
||||
{0, CB7_CA8, CB8_CA8, CB9_CA8},
|
||||
{0, CB7_CA9, CB8_CA9, CB9_CA9},
|
||||
{0, CB7_CA10, CB8_CA10, CB9_CA10},
|
||||
{0, CB7_CA11, CB8_CA11, CB9_CA11},
|
||||
{0, CB7_CA12, CB8_CA12, CB9_CA12},
|
||||
{0, CB1_CA15, CB2_CA15, CB3_CA15},
|
||||
{0, CB7_CA13, CB8_CA13, CB9_CA13},
|
||||
|
||||
{0, CB10_CA1, CB11_CA1, CB12_CA1},
|
||||
{0, CB1_CA16, CB2_CA16, CB3_CA16},
|
||||
{0, CB10_CA2, CB11_CA2, CB12_CA2},
|
||||
{0, CB10_CA3, CB11_CA3, CB12_CA3},
|
||||
{0, CB10_CA4, CB11_CA4, CB12_CA4},
|
||||
{0, CB10_CA5, CB11_CA5, CB12_CA5},
|
||||
{0, CB10_CA6, CB11_CA6, CB12_CA6},
|
||||
{0, CB10_CA7, CB11_CA7, CB12_CA7},
|
||||
{0, CB10_CA8, CB11_CA8, CB12_CA8},
|
||||
{0, CB10_CA9, CB11_CA9, CB12_CA9},
|
||||
{0, CB10_CA10, CB11_CA10, CB12_CA10},
|
||||
{0, CB10_CA11, CB11_CA11, CB12_CA11},
|
||||
{0, CB10_CA12, CB11_CA12, CB12_CA12},
|
||||
{1, CB4_CA9, CB5_CA9, CB6_CA9},
|
||||
|
||||
{0, CB10_CA13, CB11_CA13, CB12_CA13},
|
||||
{0, CB10_CA14, CB11_CA14, CB12_CA14},
|
||||
{0, CB10_CA15, CB11_CA15, CB12_CA15},
|
||||
{0, CB10_CA16, CB11_CA16, CB12_CA16},
|
||||
|
||||
{0, CB7_CA14, CB8_CA14, CB9_CA14},
|
||||
{0, CB7_CA15, CB8_CA15, CB9_CA15},
|
||||
{0, CB7_CA16, CB8_CA16, CB9_CA16},
|
||||
{0, CB4_CA16, CB5_CA16, CB6_CA16},
|
||||
|
||||
{0, CB4_CA15, CB5_CA15, CB6_CA15},
|
||||
{1, CB4_CA8, CB5_CA8, CB6_CA8},
|
||||
{1, CB4_CA7, CB5_CA7, CB6_CA7},
|
||||
|
||||
{1, CB4_CA10, CB5_CA10, CB6_CA10},
|
||||
{1, CB4_CA11, CB5_CA11, CB6_CA11},
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint8_t flag : 1;
|
||||
uint8_t devs : 3;
|
||||
uint8_t BTdevs : 3;
|
||||
};
|
||||
} confinfo_t;
|
||||
confinfo_t confinfo;
|
||||
|
||||
uint32_t post_init_timer = 0x00;
|
||||
|
||||
void eeconfig_confinfo_update(uint32_t raw) {
|
||||
|
||||
eeconfig_update_kb(raw);
|
||||
}
|
||||
|
||||
uint32_t eeconfig_confinfo_read(void) {
|
||||
|
||||
return eeconfig_read_kb();
|
||||
}
|
||||
|
||||
void eeconfig_confinfo_default(void) {
|
||||
|
||||
confinfo.flag = true;
|
||||
#ifdef WIRELESS_ENABLE
|
||||
confinfo.devs = DEVS_USB;
|
||||
confinfo.BTdevs = DEVS_BT1;
|
||||
#endif
|
||||
|
||||
eeconfig_confinfo_update(confinfo.raw);
|
||||
}
|
||||
|
||||
void eeconfig_confinfo_init(void) {
|
||||
|
||||
confinfo.raw = eeconfig_confinfo_read();
|
||||
if (!confinfo.raw) {
|
||||
eeconfig_confinfo_default();
|
||||
}
|
||||
}
|
||||
static void bt_scan_mode(void) {
|
||||
#ifdef BT_MODE_SW_PIN
|
||||
if (readPin(RF_MODE_SW_PIN) && !readPin(BT_MODE_SW_PIN)) {
|
||||
if ((wireless_get_current_devs() == DEVS_USB) || (wireless_get_current_devs() == DEVS_2G4)) {
|
||||
wireless_devs_change(wireless_get_current_devs(), confinfo.BTdevs, false);
|
||||
}
|
||||
}
|
||||
if (readPin(BT_MODE_SW_PIN) && !readPin(RF_MODE_SW_PIN)) {
|
||||
if (wireless_get_current_devs() != DEVS_2G4) {
|
||||
wireless_devs_change(wireless_get_current_devs(), DEVS_2G4, false); // 2_CA4G mode
|
||||
|
||||
}
|
||||
}
|
||||
if (readPin(BT_MODE_SW_PIN) && readPin(RF_MODE_SW_PIN)) {
|
||||
if (wireless_get_current_devs() != DEVS_USB) wireless_devs_change(wireless_get_current_devs(), DEVS_USB, false); // usb mode
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void keyboard_post_init_kb(void) {
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
debug_enable = true;
|
||||
#endif
|
||||
|
||||
eeconfig_confinfo_init();
|
||||
|
||||
#ifdef LED_POWER_EN_PIN
|
||||
gpio_set_pin_output(LED_POWER_EN_PIN);
|
||||
gpio_write_pin_high(LED_POWER_EN_PIN);
|
||||
#endif
|
||||
#ifdef LED_SCROLL_LOCK_PIN_G
|
||||
gpio_set_pin_output(LED_SCROLL_LOCK_PIN_G);
|
||||
gpio_set_pin_output(LED_SCROLL_LOCK_PIN_B);
|
||||
gpio_set_pin_output(LED_SCROLL_LOCK_PIN_R);
|
||||
gpio_write_pin_high(LED_SCROLL_LOCK_PIN_G);
|
||||
gpio_write_pin_high(LED_SCROLL_LOCK_PIN_B);
|
||||
gpio_write_pin_high(LED_SCROLL_LOCK_PIN_R);
|
||||
#endif
|
||||
|
||||
#ifdef USB_POWER_EN_PIN
|
||||
gpio_write_pin_low(USB_POWER_EN_PIN);
|
||||
gpio_set_pin_output(USB_POWER_EN_PIN);
|
||||
#endif
|
||||
#ifdef BT_MODE_SW_PIN
|
||||
gpio_set_pin_input_high(BT_MODE_SW_PIN);
|
||||
gpio_set_pin_input_high(RF_MODE_SW_PIN);
|
||||
#endif
|
||||
#ifdef BT_CABLE_PIN
|
||||
gpio_set_pin_input(BT_CABLE_PIN);
|
||||
gpio_set_pin_input(BT_CHARGE_PIN);
|
||||
#endif
|
||||
|
||||
#ifdef WIRELESS_ENABLE
|
||||
wireless_init();
|
||||
wireless_devs_change(!confinfo.devs, confinfo.devs, false);
|
||||
post_init_timer = timer_read32();
|
||||
#endif
|
||||
|
||||
keyboard_post_init_user();
|
||||
}
|
||||
|
||||
#ifdef WIRELESS_ENABLE
|
||||
|
||||
|
||||
void usb_power_connect(void) {
|
||||
|
||||
# ifdef USB_POWER_EN_PIN
|
||||
gpio_write_pin_low(USB_POWER_EN_PIN);
|
||||
# endif
|
||||
}
|
||||
|
||||
void usb_power_disconnect(void) {
|
||||
|
||||
# ifdef USB_POWER_EN_PIN
|
||||
gpio_write_pin_high(USB_POWER_EN_PIN);
|
||||
# endif
|
||||
}
|
||||
|
||||
void suspend_power_down_kb(void) {
|
||||
|
||||
# ifdef LED_POWER_EN_PIN
|
||||
gpio_write_pin_low(LED_POWER_EN_PIN);
|
||||
# endif
|
||||
suspend_power_down_user();
|
||||
}
|
||||
|
||||
void suspend_wakeup_init_kb(void) {
|
||||
|
||||
# ifdef LED_POWER_EN_PIN
|
||||
gpio_write_pin_high(LED_POWER_EN_PIN);
|
||||
# endif
|
||||
|
||||
wireless_devs_change(wireless_get_current_devs(), wireless_get_current_devs(), false);
|
||||
suspend_wakeup_init_user();
|
||||
}
|
||||
void matrix_scan_kb(void) {
|
||||
#ifdef LED_SCROLL_LOCK_PIN_G
|
||||
gpio_write_pin(LED_SCROLL_LOCK_PIN_G, !host_keyboard_led_state().scroll_lock);
|
||||
gpio_write_pin(LED_SCROLL_LOCK_PIN_B, !host_keyboard_led_state().scroll_lock);
|
||||
gpio_write_pin(LED_SCROLL_LOCK_PIN_R, !host_keyboard_led_state().scroll_lock);
|
||||
#endif
|
||||
bt_scan_mode();
|
||||
matrix_scan_user();
|
||||
}
|
||||
void wireless_post_task(void) {
|
||||
|
||||
// auto switching devs
|
||||
if (post_init_timer && timer_elapsed32(post_init_timer) >= 100) {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_FW_VERSION); // get the module fw version.
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_SLEEP_BT_EN); // timeout 30min to sleep in bt mode, enable
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_SLEEP_2G4_EN); // timeout 30min to sleep in 2.4g mode, enable
|
||||
wireless_devs_change(!confinfo.devs, confinfo.devs, false);
|
||||
post_init_timer = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t wls_process_long_press(uint32_t trigger_time, void *cb_arg) {
|
||||
uint16_t keycode = *((uint16_t *)cb_arg);
|
||||
|
||||
switch (keycode) {
|
||||
case KC_BT1: {
|
||||
if(wireless_get_current_devs() == DEVS_BT1)
|
||||
wireless_devs_change(wireless_get_current_devs(), DEVS_BT1, true);
|
||||
} break;
|
||||
case KC_BT2: {
|
||||
if(wireless_get_current_devs() == DEVS_BT2)
|
||||
wireless_devs_change(wireless_get_current_devs(), DEVS_BT2, true);
|
||||
} break;
|
||||
case KC_BT3: {
|
||||
if(wireless_get_current_devs() == DEVS_BT3)
|
||||
wireless_devs_change(wireless_get_current_devs(), DEVS_BT3, true);
|
||||
} break;
|
||||
case KC_2G4: {
|
||||
if(wireless_get_current_devs() == DEVS_2G4)
|
||||
wireless_devs_change(wireless_get_current_devs(), DEVS_2G4, true);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool process_record_wls(uint16_t keycode, keyrecord_t *record) {
|
||||
static uint16_t keycode_shadow = 0x00;
|
||||
static deferred_token wls_process_long_press_token = INVALID_DEFERRED_TOKEN;
|
||||
|
||||
keycode_shadow = keycode;
|
||||
|
||||
# ifndef WLS_KEYCODE_PAIR_TIME
|
||||
# define WLS_KEYCODE_PAIR_TIME 3000
|
||||
# endif
|
||||
|
||||
# define WLS_KEYCODE_EXEC(wls_dev) \
|
||||
do { \
|
||||
if (record->event.pressed) { \
|
||||
wireless_devs_change(wireless_get_current_devs(), wls_dev, false); \
|
||||
if (wls_process_long_press_token == INVALID_DEFERRED_TOKEN) { \
|
||||
wls_process_long_press_token = defer_exec(WLS_KEYCODE_PAIR_TIME, wls_process_long_press, &keycode_shadow); \
|
||||
} \
|
||||
} else { \
|
||||
cancel_deferred_exec(wls_process_long_press_token); \
|
||||
wls_process_long_press_token = INVALID_DEFERRED_TOKEN; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
switch (keycode) {
|
||||
case KC_BT1: {
|
||||
if ((wireless_get_current_devs() != DEVS_USB) && (wireless_get_current_devs() != DEVS_2G4)) {
|
||||
WLS_KEYCODE_EXEC(DEVS_BT1);
|
||||
}
|
||||
} break;
|
||||
case KC_BT2: {
|
||||
if ((wireless_get_current_devs() != DEVS_USB) && (wireless_get_current_devs() != DEVS_2G4)) {
|
||||
WLS_KEYCODE_EXEC(DEVS_BT2);
|
||||
}
|
||||
} break;
|
||||
case KC_BT3: {
|
||||
if ((wireless_get_current_devs() != DEVS_USB) && (wireless_get_current_devs() != DEVS_2G4)) {
|
||||
WLS_KEYCODE_EXEC(DEVS_BT3);
|
||||
}
|
||||
} break;
|
||||
case KC_2G4: {
|
||||
if (wireless_get_current_devs() == DEVS_2G4) {
|
||||
WLS_KEYCODE_EXEC(DEVS_2G4);
|
||||
}
|
||||
} break;
|
||||
case KC_USB: {
|
||||
if (record->event.pressed) {
|
||||
// wireless_devs_change(wireless_get_current_devs(), DEVS_USB, false);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
|
||||
|
||||
if (process_record_user(keycode, record) != true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WIRELESS_ENABLE
|
||||
if (process_record_wls(keycode, record) != true) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (keycode) {
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
|
||||
# ifdef WIRELESS_ENABLE
|
||||
bool wls_rgb_indicator_reset = false;
|
||||
uint32_t wls_rgb_indicator_timer = 0x00;
|
||||
uint32_t wls_rgb_indicator_interval = 0;
|
||||
uint32_t wls_rgb_indicator_times = 0;
|
||||
uint32_t wls_rgb_indicator_index = 0;
|
||||
RGB wls_rgb_indicator_rgb = {0};
|
||||
|
||||
void rgb_matrix_wls_indicator_set(uint8_t index, RGB rgb, uint32_t interval, uint8_t times) {
|
||||
|
||||
wls_rgb_indicator_timer = timer_read32();
|
||||
|
||||
wls_rgb_indicator_index = index;
|
||||
wls_rgb_indicator_interval = interval;
|
||||
wls_rgb_indicator_times = times * 2;
|
||||
wls_rgb_indicator_rgb = rgb;
|
||||
}
|
||||
|
||||
void wireless_devs_change_kb(uint8_t old_devs, uint8_t new_devs, bool reset) {
|
||||
|
||||
wls_rgb_indicator_reset = reset;
|
||||
|
||||
if (confinfo.devs != wireless_get_current_devs()) {
|
||||
confinfo.devs = wireless_get_current_devs();
|
||||
if ((wireless_get_current_devs() != DEVS_USB) && (wireless_get_current_devs() != DEVS_2G4)) {
|
||||
confinfo.BTdevs = wireless_get_current_devs();
|
||||
}
|
||||
eeconfig_confinfo_update(confinfo.raw);
|
||||
}
|
||||
|
||||
switch (new_devs) {
|
||||
case DEVS_BT1: {
|
||||
if (reset) {
|
||||
rgb_matrix_wls_indicator_set(17, (RGB){.r = 0, .g = 0, .b = 255}, 200, 1);
|
||||
} else {
|
||||
rgb_matrix_wls_indicator_set(17, (RGB){.r = 0, .g = 0, .b = 255}, 500, 1);
|
||||
}
|
||||
} break;
|
||||
case DEVS_BT2: {
|
||||
if (reset) {
|
||||
rgb_matrix_wls_indicator_set(18, (RGB){.r = 0, .g = 0, .b = 255}, 200, 1);
|
||||
} else {
|
||||
rgb_matrix_wls_indicator_set(18, (RGB){.r = 0, .g = 0, .b = 255}, 500, 1);
|
||||
}
|
||||
} break;
|
||||
case DEVS_BT3: {
|
||||
if (reset) {
|
||||
rgb_matrix_wls_indicator_set(19, (RGB){.r = 0, .g = 0, .b = 255}, 200, 1);
|
||||
} else {
|
||||
rgb_matrix_wls_indicator_set(19, (RGB){.r = 0, .g = 0, .b = 255}, 500, 1);
|
||||
}
|
||||
} break;
|
||||
case DEVS_2G4: {
|
||||
if (reset) {
|
||||
rgb_matrix_wls_indicator_set(20, (RGB){.r = 0, .g = 255, .b = 0}, 200, 1);
|
||||
} else {
|
||||
rgb_matrix_wls_indicator_set(20, (RGB){.r = 0, .g = 255, .b = 0}, 500, 1);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool rgb_matrix_wls_indicator_cb(void) {
|
||||
|
||||
if (*md_getp_state() != MD_STATE_CONNECTED) {
|
||||
wireless_devs_change_kb(wireless_get_current_devs(), wireless_get_current_devs(), wls_rgb_indicator_reset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// refresh led
|
||||
led_wakeup();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void rgb_matrix_wls_indicator(void) {
|
||||
|
||||
if (wls_rgb_indicator_timer) {
|
||||
|
||||
if (timer_elapsed32(wls_rgb_indicator_timer) >= wls_rgb_indicator_interval) {
|
||||
wls_rgb_indicator_timer = timer_read32();
|
||||
|
||||
if (wls_rgb_indicator_times) {
|
||||
wls_rgb_indicator_times--;
|
||||
}
|
||||
|
||||
if (wls_rgb_indicator_times <= 0) {
|
||||
wls_rgb_indicator_timer = 0x00;
|
||||
if (rgb_matrix_wls_indicator_cb() != true) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wls_rgb_indicator_times % 2) {
|
||||
rgb_matrix_set_color(wls_rgb_indicator_index, wls_rgb_indicator_rgb.r, wls_rgb_indicator_rgb.g, wls_rgb_indicator_rgb.b);
|
||||
} else {
|
||||
rgb_matrix_set_color(wls_rgb_indicator_index, 0x00, 0x00, 0x00);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
bool rgb_matrix_indicators_advanced_kb(uint8_t led_min, uint8_t led_max) {
|
||||
|
||||
if (rgb_matrix_indicators_advanced_user(led_min, led_max) != true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
# ifdef WIRELESS_ENABLE
|
||||
rgb_matrix_wls_indicator();
|
||||
# endif
|
||||
# if defined(BT_CABLE_PIN) && defined(BT_CHARGE_PIN)
|
||||
// Charging access
|
||||
static uint16_t charging_time;
|
||||
static uint16_t full_time;
|
||||
if (readPin(BT_CABLE_PIN)) {
|
||||
if (!readPin(BT_CHARGE_PIN)) {
|
||||
// Charging
|
||||
if (timer_elapsed(charging_time) >= 500) {
|
||||
rgb_matrix_set_color(90, 100, 0, 0);
|
||||
} else {
|
||||
rgb_matrix_set_color(90, 0, 0, 0);
|
||||
}
|
||||
full_time = timer_read32();
|
||||
} else {
|
||||
// full
|
||||
charging_time = timer_read32();
|
||||
if (timer_elapsed(full_time) >= 500) {
|
||||
rgb_matrix_set_color(90, 0, 100, 0);
|
||||
} else {
|
||||
rgb_matrix_set_color(90, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(*md_getp_bat()>5){
|
||||
rgb_matrix_set_color(90, 0, 0, 0);
|
||||
} else {
|
||||
static bool Low_power_bink;
|
||||
static uint16_t Low_power_time;
|
||||
if (timer_elapsed(Low_power_time) >= 300) {
|
||||
Low_power_bink = !Low_power_bink;
|
||||
Low_power_time = timer_read32();
|
||||
}
|
||||
if (Low_power_bink) {
|
||||
rgb_matrix_set_color(90, 100, 0, 0);
|
||||
} else {
|
||||
rgb_matrix_set_color(90, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
// caps lock red
|
||||
if (host_keyboard_led_state().caps_lock) {
|
||||
rgb_matrix_set_color(89, 100, 100, 100);
|
||||
} else {
|
||||
rgb_matrix_set_color(89, 0, 0, 0);
|
||||
}
|
||||
// scroll lock red
|
||||
if (host_keyboard_led_state().scroll_lock) {
|
||||
rgb_matrix_set_color(14, 100, 0, 0);
|
||||
}
|
||||
// GUI lock red
|
||||
if (keymap_config.no_gui) {
|
||||
rgb_matrix_set_color(79, 100, 0, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void md_devs_change(uint8_t devs, bool reset) {
|
||||
|
||||
switch (devs) {
|
||||
case DEVS_USB: {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_USB);
|
||||
} break;
|
||||
case DEVS_2G4: {
|
||||
if (reset) {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_PAIR);
|
||||
} else {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_2G4);
|
||||
}
|
||||
} break;
|
||||
case DEVS_BT1: {
|
||||
if (reset) {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_PAIR);
|
||||
} else {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_BT1);
|
||||
}
|
||||
} break;
|
||||
case DEVS_BT2: {
|
||||
if (reset) {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_PAIR);
|
||||
} else {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_BT2);
|
||||
}
|
||||
} break;
|
||||
case DEVS_BT3: {
|
||||
if (reset) {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_PAIR);
|
||||
} else {
|
||||
md_send_devctrl(MD_SND_CMD_DEVCTRL_BT3);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
void wireless_send_nkro(report_nkro_t *report) {
|
||||
static report_keyboard_t temp_report_keyboard = {0};
|
||||
uint8_t wls_report_nkro[MD_SND_CMD_NKRO_LEN] = {0};
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
|
||||
if (report != NULL) {
|
||||
report_nkro_t temp_report_nkro = *report;
|
||||
uint8_t key_count = 0;
|
||||
|
||||
temp_report_keyboard.mods = temp_report_nkro.mods;
|
||||
for (uint8_t i = 0; i < NKRO_REPORT_BITS; i++) {
|
||||
key_count += __builtin_popcount(temp_report_nkro.bits[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use NKRO for sending when more than 6 keys are pressed
|
||||
* to solve the issue of the lack of a protocol flag in wireless mode.
|
||||
*/
|
||||
|
||||
for (uint8_t i = 0; i < key_count; i++) {
|
||||
uint8_t usageid;
|
||||
uint8_t idx, n = 0;
|
||||
|
||||
for (n = 0; n < NKRO_REPORT_BITS && !temp_report_nkro.bits[n]; n++) {}
|
||||
usageid = (n << 3) | biton(temp_report_nkro.bits[n]);
|
||||
del_key_bit(&temp_report_nkro, usageid);
|
||||
|
||||
for (idx = 0; idx < WLS_KEYBOARD_REPORT_KEYS; idx++) {
|
||||
if (temp_report_keyboard.keys[idx] == usageid) {
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0; idx < WLS_KEYBOARD_REPORT_KEYS; idx++) {
|
||||
if (temp_report_keyboard.keys[idx] == 0x00) {
|
||||
temp_report_keyboard.keys[idx] = usageid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
next:
|
||||
if (idx == WLS_KEYBOARD_REPORT_KEYS && (usageid < (MD_SND_CMD_NKRO_LEN * 8))) {
|
||||
wls_report_nkro[usageid / 8] |= 0x01 << (usageid % 8);
|
||||
}
|
||||
}
|
||||
|
||||
temp_report_nkro = *report;
|
||||
|
||||
// find key up and del it.
|
||||
uint8_t nkro_keys = key_count;
|
||||
for (uint8_t i = 0; i < WLS_KEYBOARD_REPORT_KEYS; i++) {
|
||||
report_nkro_t found_report_nkro;
|
||||
uint8_t usageid = 0x00;
|
||||
uint8_t n;
|
||||
|
||||
found_report_nkro = temp_report_nkro;
|
||||
|
||||
for (uint8_t c = 0; c < nkro_keys; c++) {
|
||||
for (n = 0; n < NKRO_REPORT_BITS && !found_report_nkro.bits[n]; n++) {}
|
||||
usageid = (n << 3) | biton(found_report_nkro.bits[n]);
|
||||
del_key_bit(&found_report_nkro, usageid);
|
||||
if (usageid == temp_report_keyboard.keys[i]) {
|
||||
del_key_bit(&temp_report_nkro, usageid);
|
||||
nkro_keys--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (usageid != temp_report_keyboard.keys[i]) {
|
||||
temp_report_keyboard.keys[i] = 0x00;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memset(&temp_report_keyboard, 0, sizeof(temp_report_keyboard));
|
||||
}
|
||||
#endif
|
||||
void wireless_task(void);
|
||||
bool smsg_is_busy(void);
|
||||
while(smsg_is_busy()) {
|
||||
wireless_task();
|
||||
}
|
||||
extern host_driver_t wireless_driver;
|
||||
wireless_driver.send_keyboard(&temp_report_keyboard);
|
||||
md_send_nkro(wls_report_nkro);
|
||||
}
|
288
keyboards/hator/rockfall3/htk850/keyboard.json
Normal file
288
keyboards/hator/rockfall3/htk850/keyboard.json
Normal file
@ -0,0 +1,288 @@
|
||||
{
|
||||
"manufacturer": "HATOR",
|
||||
"keyboard_name": "Rockfall 3 Wireless",
|
||||
"url": "https://hator.com/",
|
||||
"maintainer": "koosikus",
|
||||
"bootloader": "wb32-dfu",
|
||||
"bootmagic": {
|
||||
"matrix": [0, 0]
|
||||
},
|
||||
"diode_direction": "ROW2COL",
|
||||
"eeprom": {
|
||||
"driver": "wear_leveling",
|
||||
"wear_leveling": {
|
||||
"backing_size": 4096,
|
||||
"driver": "spi_flash"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
"bootmagic": true,
|
||||
"command": false,
|
||||
"console": false,
|
||||
"deferred_exec": true,
|
||||
"extrakey": true,
|
||||
"haptic": false,
|
||||
"mousekey": true,
|
||||
"nkro": true,
|
||||
"rgb_matrix": true,
|
||||
"rgblight": false
|
||||
},
|
||||
"keycodes": [
|
||||
{
|
||||
"key": "KC_USB"
|
||||
},
|
||||
{
|
||||
"key": "KC_BT1"
|
||||
},
|
||||
{
|
||||
"key": "KC_BT2"
|
||||
},
|
||||
{
|
||||
"key": "KC_BT3"
|
||||
},
|
||||
{
|
||||
"key": "KC_BT4"
|
||||
},
|
||||
{
|
||||
"key": "KC_BT5"
|
||||
},
|
||||
{
|
||||
"key": "KC_2G4"
|
||||
}
|
||||
],
|
||||
"matrix_pins": {
|
||||
"cols": ["C1","C2","C3","A0","A1","A2","A3","A4","A5","A6","A7","C4","C5","B0","B1","B2","B10"],
|
||||
"rows": ["B15", "C6", "C7", "C8", "C9", "B14"]
|
||||
},
|
||||
"indicators": {
|
||||
"caps_lock": "C0",
|
||||
"on_state": 0
|
||||
},
|
||||
"processor": "WB32FQ95",
|
||||
"rgb_matrix": {
|
||||
"animations": {
|
||||
"breathing": true,
|
||||
"cycle_all": true,
|
||||
"cycle_left_right": true,
|
||||
"cycle_out_in": true,
|
||||
"cycle_out_in_dual": true,
|
||||
"cycle_pinwheel": true,
|
||||
"cycle_spiral": true,
|
||||
"cycle_up_down": true,
|
||||
"dual_beacon": true,
|
||||
"multisplash": true,
|
||||
"rainbow_beacon": true,
|
||||
"rainbow_moving_chevron": true,
|
||||
"raindrops": true,
|
||||
"solid_color": true,
|
||||
"solid_reactive": true,
|
||||
"solid_reactive_simple": true,
|
||||
"typing_heatmap": true
|
||||
},
|
||||
"driver": "snled27351",
|
||||
"layout": [
|
||||
{ "flags": 4, "matrix": [0,0], "x": 6, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,1], "x": 31, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,2], "x": 43, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,3], "x": 55, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,4], "x": 68, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,5], "x": 86, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,6], "x": 98, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,7], "x": 110, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,8], "x": 123, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,9], "x": 141, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,10], "x": 153, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,11], "x": 166, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,12], "x": 178, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,14], "x": 193, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,15], "x": 206, "y": 8 },
|
||||
{ "flags": 4, "matrix": [0,16], "x": 218, "y": 8 },
|
||||
{ "flags": 4, "matrix": [1,0], "x": 6, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,1], "x": 18, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,2], "x": 31, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,3], "x": 43, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,4], "x": 55, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,5], "x": 68, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,6], "x": 80, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,7], "x": 92, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,8], "x": 104, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,9], "x": 117, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,10], "x": 129, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,11], "x": 141, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,12], "x": 153, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,13], "x": 172, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,14], "x": 193, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,15], "x": 206, "y": 21},
|
||||
{ "flags": 4, "matrix": [1,16], "x": 218, "y": 21},
|
||||
{ "flags": 4, "matrix": [2,0], "x": 9, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,1], "x": 25, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,2], "x": 37, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,3], "x": 49, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,4], "x": 61, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,5], "x": 74, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,6], "x": 86, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,7], "x": 98, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,8], "x": 110, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,9], "x": 123, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,10], "x": 135, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,11], "x": 147, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,12], "x": 160, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,13], "x": 175, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,14], "x": 193, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,15], "x": 206, "y": 31},
|
||||
{ "flags": 4, "matrix": [2,16], "x": 218, "y": 31},
|
||||
{ "flags": 1, "matrix": [3,0], "x": 11, "y": 41},
|
||||
{ "flags": 4, "matrix": [3,1], "x": 28, "y": 41},
|
||||
{ "flags": 4, "matrix": [3,2], "x": 40, "y": 41},
|
||||
{ "flags": 4, "matrix": [3,3], "x": 52, "y": 41},
|
||||
{ "flags": 4, "matrix": [3,4], "x": 64, "y": 41},
|
||||
{ "flags": 4, "matrix": [3,5], "x": 77, "y": 41},
|
||||
{ "flags": 4, "matrix": [3,6], "x": 89, "y": 41},
|
||||
{ "flags": 4, "matrix": [3,7], "x": 101, "y": 41},
|
||||
{ "flags": 4, "matrix": [3,8], "x": 114, "y": 41},
|
||||
{ "flags": 4, "matrix": [3,9], "x": 126, "y": 41},
|
||||
{ "flags": 4, "matrix": [3,10], "x": 138, "y": 41},
|
||||
{ "flags": 4, "matrix": [3,11], "x": 150, "y": 41},
|
||||
{ "flags": 4, "matrix": [3,12], "x": 162, "y": 41},
|
||||
{ "flags": 1, "matrix": [3,13], "x": 170, "y": 41},
|
||||
{ "flags": 1, "matrix": [4,0], "x": 14, "y": 51},
|
||||
{ "flags": 1, "matrix": [5,3], "x": 22, "y": 51},
|
||||
{ "flags": 4, "matrix": [4,1], "x": 34, "y": 51},
|
||||
{ "flags": 4, "matrix": [4,2], "x": 46, "y": 51},
|
||||
{ "flags": 4, "matrix": [4,3], "x": 58, "y": 51},
|
||||
{ "flags": 4, "matrix": [4,4], "x": 71, "y": 51},
|
||||
{ "flags": 4, "matrix": [4,5], "x": 83, "y": 51},
|
||||
{ "flags": 4, "matrix": [4,6], "x": 95, "y": 51},
|
||||
{ "flags": 4, "matrix": [4,7], "x": 107, "y": 51},
|
||||
{ "flags": 4, "matrix": [4,8], "x": 120, "y": 51},
|
||||
{ "flags": 4, "matrix": [4,9], "x": 132, "y": 51},
|
||||
{ "flags": 4, "matrix": [4,10], "x": 144, "y": 51},
|
||||
{ "flags": 1, "matrix": [4,13], "x": 167, "y": 51},
|
||||
{ "flags": 1, "matrix": [4,15], "x": 206, "y": 51},
|
||||
{ "flags": 1, "matrix": [5,0], "x": 8, "y": 62},
|
||||
{ "flags": 1, "matrix": [5,1], "x": 23, "y": 62},
|
||||
{ "flags": 1, "matrix": [5,2], "x": 38, "y": 62},
|
||||
{ "flags": 4, "matrix": [5,5], "x": 84, "y": 62},
|
||||
{ "flags": 1, "matrix": [5,10], "x": 130, "y": 62},
|
||||
{ "flags": 1, "matrix": [5,11], "x": 146, "y": 62},
|
||||
{ "flags": 1, "matrix": [5,12], "x": 161, "y": 62},
|
||||
{ "flags": 1, "matrix": [5,13], "x": 176, "y": 62},
|
||||
{ "flags": 1, "matrix": [5,14], "x": 193, "y": 62},
|
||||
{ "flags": 1, "matrix": [5,15], "x": 206, "y": 62},
|
||||
{ "flags": 1, "matrix": [5,16], "x": 218, "y": 62},
|
||||
|
||||
{ "flags": 1},
|
||||
{ "flags": 1}
|
||||
],
|
||||
"max_brightness": 180,
|
||||
"sleep": false,
|
||||
"speed_steps": 64,
|
||||
"timeout": 60000,
|
||||
"val_steps": 45
|
||||
},
|
||||
"usb": {
|
||||
"device_version": "1.1.1",
|
||||
"force_nkro": true,
|
||||
"pid": "0x0300",
|
||||
"suspend_wakeup_delay": 1000,
|
||||
"vid": "0x379A"
|
||||
},
|
||||
"dynamic_keymap": {
|
||||
"layer_count": 6
|
||||
},
|
||||
"layouts": {
|
||||
"LAYOUT_ansi": {
|
||||
"layout": [
|
||||
{ "matrix": [0,0], "x": 0, "y": 0 },
|
||||
{ "matrix": [0,1], "x": 2, "y": 0 },
|
||||
{ "matrix": [0,2], "x": 3, "y": 0 },
|
||||
{ "matrix": [0,3], "x": 4, "y": 0 },
|
||||
{ "matrix": [0,4], "x": 5, "y": 0 },
|
||||
{ "matrix": [0,5], "x": 6.5, "y": 0 },
|
||||
{ "matrix": [0,6], "x": 7.5, "y": 0 },
|
||||
{ "matrix": [0,7], "x": 8.5, "y": 0 },
|
||||
{ "matrix": [0,8], "x": 9.5, "y": 0 },
|
||||
{ "matrix": [0,9], "x": 11, "y": 0 },
|
||||
{ "matrix": [0,10], "x": 12, "y": 0 },
|
||||
{ "matrix": [0,11], "x": 13, "y": 0 },
|
||||
{ "matrix": [0,12], "x": 14, "y": 0 },
|
||||
{ "matrix": [0,14], "x": 15.25, "y": 0 },
|
||||
{ "matrix": [0,15], "x": 16.25, "y": 0 },
|
||||
{ "matrix": [0,16], "x": 17.25, "y": 0 },
|
||||
{ "matrix": [1,0], "x": 0, "y": 1.25 },
|
||||
{ "matrix": [1,1], "x": 1, "y": 1.25 },
|
||||
{ "matrix": [1,2], "x": 2, "y": 1.25 },
|
||||
{ "matrix": [1,3], "x": 3, "y": 1.25 },
|
||||
{ "matrix": [1,4], "x": 4, "y": 1.25 },
|
||||
{ "matrix": [1,5], "x": 5, "y": 1.25 },
|
||||
{ "matrix": [1,6], "x": 6, "y": 1.25 },
|
||||
{ "matrix": [1,7], "x": 7, "y": 1.25 },
|
||||
{ "matrix": [1,8], "x": 8, "y": 1.25 },
|
||||
{ "matrix": [1,9], "x": 9, "y": 1.25 },
|
||||
{ "matrix": [1,10], "x": 10, "y": 1.25 },
|
||||
{ "matrix": [1,11], "x": 11, "y": 1.25 },
|
||||
{ "matrix": [1,12], "x": 12, "y": 1.25 },
|
||||
{ "matrix": [1,13], "x": 14, "y": 1.25 },
|
||||
{ "matrix": [1,14], "x": 15.25, "y": 1.25 },
|
||||
{ "matrix": [1,15], "x": 16.25, "y": 1.25 },
|
||||
{ "matrix": [1,16], "x": 17.25, "y": 1.25 },
|
||||
{ "matrix": [2,0], "w": 1.5, "x": 0, "y": 2.25 },
|
||||
{ "matrix": [2,1], "x": 1.5, "y": 2.25 },
|
||||
{ "matrix": [2,2], "x": 2.5, "y": 2.25 },
|
||||
{ "matrix": [2,3], "x": 3.5, "y": 2.25 },
|
||||
{ "matrix": [2,4], "x": 4.5, "y": 2.25 },
|
||||
{ "matrix": [2,5], "x": 5.5, "y": 2.25 },
|
||||
{ "matrix": [2,6], "x": 6.5, "y": 2.25 },
|
||||
{ "matrix": [2,7], "x": 7.5, "y": 2.25 },
|
||||
{ "matrix": [2,8], "x": 8.5, "y": 2.25 },
|
||||
{ "matrix": [2,9], "x": 9.5, "y": 2.25 },
|
||||
{ "matrix": [2,10], "x": 10.5, "y": 2.25 },
|
||||
{ "matrix": [2,11], "x": 11.5, "y": 2.25 },
|
||||
{ "matrix": [2,12], "x": 12.5, "y": 2.25 },
|
||||
{ "matrix": [2,13], "w": 1.5, "x": 13.5, "y": 2.25 },
|
||||
{ "matrix": [2,14], "x": 15.25, "y": 2.25 },
|
||||
{ "matrix": [2,15], "x": 16.25, "y": 2.25 },
|
||||
{ "matrix": [2,16], "x": 17.25, "y": 2.25 },
|
||||
{ "matrix": [3,0], "w": 1.75, "x": 0, "y": 3.25 },
|
||||
{ "matrix": [3,1], "x": 1.75, "y": 3.25 },
|
||||
{ "matrix": [3,2], "x": 2.75, "y": 3.25 },
|
||||
{ "matrix": [3,3], "x": 3.75, "y": 3.25 },
|
||||
{ "matrix": [3,4], "x": 4.75, "y": 3.25 },
|
||||
{ "matrix": [3,5], "x": 5.75, "y": 3.25 },
|
||||
{ "matrix": [3,6], "x": 6.75, "y": 3.25 },
|
||||
{ "matrix": [3,7], "x": 7.75, "y": 3.25 },
|
||||
{ "matrix": [3,8], "x": 8.75, "y": 3.25 },
|
||||
{ "matrix": [3,9], "x": 9.75, "y": 3.25 },
|
||||
{ "matrix": [3,10], "x": 10.75, "y": 3.25 },
|
||||
{ "matrix": [3,11], "x": 11.75, "y": 3.25 },
|
||||
{ "matrix": [3,12], "x": 12.75, "y": 3.25 },
|
||||
{ "matrix": [3,13], "w": 2.25, "x": 12.75, "y": 3.25 },
|
||||
{ "matrix": [4,0], "w": 2.25, "x": 0, "y": 4.25 },
|
||||
{ "matrix": [5,3], "x": 1.25, "y": 4.25 },
|
||||
{ "matrix": [4,1], "x": 2.25, "y": 4.25 },
|
||||
{ "matrix": [4,2], "x": 3.25, "y": 4.25 },
|
||||
{ "matrix": [4,3], "x": 4.25, "y": 4.25 },
|
||||
{ "matrix": [4,4], "x": 5.25, "y": 4.25 },
|
||||
{ "matrix": [4,5], "x": 6.25, "y": 4.25 },
|
||||
{ "matrix": [4,6], "x": 7.25, "y": 4.25 },
|
||||
{ "matrix": [4,7], "x": 8.25, "y": 4.25 },
|
||||
{ "matrix": [4,8], "x": 9.25, "y": 4.25 },
|
||||
{ "matrix": [4,9], "x": 10.25, "y": 4.25 },
|
||||
{ "matrix": [4,10], "x": 11.25, "y": 4.25 },
|
||||
{ "matrix": [4,13], "w": 2.75, "x": 12.25, "y": 4.25 },
|
||||
{ "matrix": [4,15], "x": 16.25, "y": 4.25 },
|
||||
{ "matrix": [5,0], "w": 1.25, "x": 0, "y": 5.25 },
|
||||
{ "matrix": [5,1], "w": 1.25, "x": 1.25, "y": 5.25 },
|
||||
{ "matrix": [5,2], "w": 1.25, "x": 2.5, "y": 5.25 },
|
||||
{ "matrix": [5,5], "w": 6.25, "x": 3.75, "y": 5.25 },
|
||||
{ "matrix": [5,10], "w": 1.25, "x": 10, "y": 5.25 },
|
||||
{ "matrix": [5,11], "w": 1.25, "x": 11.25, "y": 5.25 },
|
||||
{ "matrix": [5,12], "w": 1.25, "x": 12.5, "y": 5.25 },
|
||||
{ "matrix": [5,13], "w": 1.25, "x": 13.75, "y": 5.25 },
|
||||
{ "matrix": [5,14], "x": 15.25, "y": 5.25 },
|
||||
{ "matrix": [5,15], "x": 16.25, "y": 5.25 },
|
||||
{ "matrix": [5,16], "x": 17.25, "y": 5.25 }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
69
keyboards/hator/rockfall3/htk850/keymaps/default/keymap.c
Normal file
69
keyboards/hator/rockfall3/htk850/keymaps/default/keymap.c
Normal file
@ -0,0 +1,69 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
// clang-format off
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
||||
[0] = LAYOUT_ansi( /* Base */
|
||||
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_PSCR, KC_SCRL, KC_PAUS,
|
||||
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_HOME, KC_PGUP,
|
||||
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_END, KC_PGDN,
|
||||
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_NUHS, KC_ENT,
|
||||
KC_LSFT, KC_NUBS, 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_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), MO(4), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
|
||||
|
||||
[1] = LAYOUT_ansi( /* FN1 */
|
||||
EE_CLR, KC_BRID, KC_BRIU, KC_MAIL, KC_WSCH, KC_CALC, KC_MSEL, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______,
|
||||
NK_TOGG, KC_BT1, KC_BT2, KC_BT3, KC_2G4, _______, _______, _______, _______, _______, _______, _______, _______, RGB_MOD, _______, _______, RGB_HUI,
|
||||
TO(2), _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_HUD,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_VAI,
|
||||
_______, GU_TOGG, _______, _______, _______, _______, _______, _______, RGB_SPD, RGB_VAD, RGB_SPI),
|
||||
|
||||
[2] = LAYOUT_ansi( /* Base */
|
||||
KC_ESC,KC_BRID,KC_BRIU,C(KC_UP),C(S(KC_DOWN)),KC_F5, KC_F6, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, KC_PSCR, KC_SCRL, KC_PAUS,
|
||||
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_HOME, KC_PGUP,
|
||||
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_END, KC_PGDN,
|
||||
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_NUHS, KC_ENT,
|
||||
KC_LSFT, KC_NUBS, 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_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, MO(3), MO(4), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
|
||||
|
||||
[3] = LAYOUT_ansi( /* FN1 */
|
||||
EE_CLR, KC_F1, KC_F2, KC_F3, KC_F4, _______, _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______, _______,
|
||||
NK_TOGG, KC_BT1, KC_BT2, KC_BT3, KC_2G4, _______, _______, _______, _______, _______, _______, _______, _______, RGB_MOD, _______, _______, RGB_HUI,
|
||||
TO(0), _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_HUD,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_VAI,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, RGB_SPD, RGB_VAD, RGB_SPI),
|
||||
|
||||
[4] = LAYOUT_ansi( /* FN2 */
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_MOD, _______, _______, RGB_HUI,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_HUD,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_VAI,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, RGB_SPD, RGB_VAD, RGB_SPI),
|
||||
|
||||
[5] = LAYOUT_ansi( /* FNx */
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______)
|
||||
};
|
48
keyboards/hator/rockfall3/htk850/mcuconf.h
Normal file
48
keyboards/hator/rockfall3/htk850/mcuconf.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* Copyright (C) 2024 koosikus
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include_next <mcuconf.h>
|
||||
|
||||
#undef WB32_USB_HOST_WAKEUP_DURATION
|
||||
#define WB32_USB_HOST_WAKEUP_DURATION 2
|
||||
|
||||
#undef WB32_SERIAL_USE_UART1
|
||||
#define WB32_SERIAL_USE_UART1 TRUE
|
||||
|
||||
#undef WB32_SPI_USE_QSPI
|
||||
#define WB32_SPI_USE_QSPI TRUE
|
||||
|
||||
// // The interrupt priority of the WS2812 driver must be higher than that of other SPI devices.
|
||||
// #undef WB32_SPI_QSPI_IRQ_PRIORITY
|
||||
// #define WB32_SPI_QSPI_IRQ_PRIORITY 9
|
||||
|
||||
// #undef WB32_SPI_SPIM2_IRQ_PRIORITY
|
||||
// #define WB32_SPI_SPIM2_IRQ_PRIORITY 10
|
||||
|
||||
#undef WB32_I2C_USE_I2C1
|
||||
#define WB32_I2C_USE_I2C1 TRUE
|
||||
|
||||
/* system clock set to 96Mhz */
|
||||
#undef WB32_PLLDIV_VALUE
|
||||
#define WB32_PLLDIV_VALUE 2
|
||||
|
||||
#undef WB32_PLLMUL_VALUE
|
||||
#define WB32_PLLMUL_VALUE 16
|
||||
|
||||
#undef WB32_USBPRE
|
||||
#define WB32_USBPRE WB32_USBPRE_DIV2
|
1
keyboards/hator/rockfall3/htk850/post_rules.mk
Normal file
1
keyboards/hator/rockfall3/htk850/post_rules.mk
Normal file
@ -0,0 +1 @@
|
||||
include keyboards/hator/rockfall3/common/wireless/wireless.mk
|
25
keyboards/hator/rockfall3/htk850/readme.md
Normal file
25
keyboards/hator/rockfall3/htk850/readme.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Rockfall 3 Wireless
|
||||

|
||||
|
||||
TKL multimode keyboard
|
||||
|
||||
* Keyboard Maintainer: [koosikus](https://github.com/koosikus)
|
||||
* Hardware Supported: HATOR Rockfall 3 Wireless (HTK850)
|
||||
* Hardware Availability: [Rockfall 3 Wireless](https://hator.com/keyboards/rockfall-3-mecha-tkl-wireless/)
|
||||
|
||||
Make example for this keyboard (after setting up your build environment):
|
||||
|
||||
make hator/rockfall3/htk850:default
|
||||
|
||||
Flashing example for this keyboard:
|
||||
|
||||
make hator/rockfall3/htk850:default:flash
|
||||
|
||||
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).
|
||||
|
||||
## Bootloader
|
||||
|
||||
Enter the bootloader in 2 ways:
|
||||
|
||||
* **Bootmagic reset**: Hold down the Hold down the top left key (commonly programmed as *Esc*) and plug in the keyboard
|
||||
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available
|
Loading…
Reference in New Issue
Block a user