Compare commits

...

39 Commits

Author SHA1 Message Date
nuphy-src
d11aa2a13a
Merge 0f6d5f7ed6 into 9bea332a21 2024-11-20 22:22:13 -08:00
Ryan
9bea332a21
qmk via2json: Improve macro parsing (#24345) 2024-11-21 17:20:05 +11:00
Ryan
8cbcdcac62
qmk new-keymap: validate keymap name (#23420) 2024-11-21 17:18:51 +11:00
nuphy-src
0f6d5f7ed6 rename info.json to keyboard.json 2024-08-23 13:46:44 +08:00
nuphy-src
ae0f28c48c
Update keyboards/nuphy/air75_v2/ansi/readme.md
Co-authored-by: Drashna Jaelre <drashna@live.com>
2024-08-23 13:43:04 +08:00
nuphy-src
a4f5754d1f update
update

update

update

reset submodule
2024-07-03 09:20:36 +08:00
nuphy-src
00bc5afdd0 Merge remote-tracking branch 'upstream/master' into nuphy-air75 2024-07-02 17:58:49 +08:00
nuphy-src
889d8c3332
Update keyboards/nuphy/air75_v2/ansi/info.json
Co-authored-by: Duncan Sutherland <dunk2k_2000@hotmail.com>
2024-05-06 11:38:29 +08:00
nuphy-src
67c0c7f407 Merge branch 'nuphy-air75' of https://github.com/nuphy-src/qmk_firmware into nuphy-air75 2024-04-01 20:15:06 +08:00
nuphy-src
8d4f887847 Rename some variables in the code. 2024-04-01 20:14:28 +08:00
nuphy-src
e32773215e
Merge branch 'master' into nuphy-air75 2024-03-22 17:27:49 +08:00
nuphy-src
166eb067ac
Merge branch 'master' into nuphy-air75 2024-03-21 11:16:31 +08:00
nuphy-src
2b81cf366c
Merge branch 'master' into nuphy-air75 2024-03-20 21:38:02 +08:00
nuphy-src
29502d6a40 Modify readme.md 2024-03-20 21:34:39 +08:00
nuphy-src
7789c42a72 Merge branch 'nuphy-air75' of https://github.com/nuphy-src/qmk_firmware into nuphy-air75 2024-03-18 16:18:43 +08:00
nuphy-src
3c28a2e3c5 Fix some formatting issues. 2024-03-18 16:12:53 +08:00
nuphy-src
3e62c4bc4d
Merge branch 'master' into nuphy-air75 2024-02-29 15:50:52 +08:00
nuphy-src
98a848a517
Merge branch 'master' into nuphy-air75 2024-02-21 00:00:01 +08:00
nuphy-src
322c28fd89
Merge branch 'master' into nuphy-air75 2024-02-18 23:43:14 +08:00
nuphy-src
a3ba423adc
Merge branch 'master' into nuphy-air75 2024-02-16 17:19:07 +08:00
nuphy-src
2c03060b7c Merge branch 'nuphy-air75' of https://github.com/nuphy-src/qmk_firmware into nuphy-air75 2024-02-05 09:39:09 +08:00
nuphy-src
05d4515743 Fixed some issues as suggested 2024-02-05 09:38:43 +08:00
GateLi
26eaa3f348
Merge branch 'master' into nuphy-air75 2024-01-31 10:13:26 +08:00
nuphy-src
2cabdbdddf Use process_record_kb function at ansi.c 2024-01-24 15:21:18 +08:00
nuphy-src
47553feb28 Merge branch 'nuphy-air75' of https://github.com/nuphy-src/qmk_firmware into nuphy-air75 2024-01-16 10:30:16 +08:00
nuphy-src
f0c395b2e5 Fix error in info.json 2024-01-16 10:16:57 +08:00
nuphy-src
c56e210d26
Merge branch 'master' into nuphy-air75 2024-01-15 21:42:44 +08:00
nuphy-src
2263f4d907
Merge branch 'master' into nuphy-air75 2024-01-10 00:05:44 +08:00
nuphy-src
570bc9c30f Add nuphy license header 2024-01-09 00:11:18 +08:00
nuphy-src
dbab794c69 Solved the problem of not sending codes in RF mode 2024-01-08 22:52:14 +08:00
nuphy-src
1eb1205c5a Fix mac layer erroe. 2024-01-08 02:01:28 +08:00
nuphy-src
1b27fec04a
Merge branch 'master' into nuphy-air75 2024-01-08 01:45:25 +08:00
nuphy-src
9e0eb67f68 Merge branch 'nuphy-air75' of https://github.com/nuphy-src/qmk_firmware into nuphy-air75 2024-01-08 00:50:58 +08:00
nuphy-src
7642708bb6 [Keyboard] Adjusted the code format 2024-01-08 00:50:10 +08:00
nuphy-src
8c1c96726c
Merge branch 'master' into nuphy-air75 2024-01-02 14:56:26 +08:00
nuphy-src
f5f1262e0b Merge branch 'nuphy-air75' of https://github.com/nuphy-src/qmk_firmware into nuphy-air75 2023-12-28 01:03:49 +08:00
nuphy-src
f4495d4d41 Fixed some issues as suggested 2023-12-28 01:03:37 +08:00
nuphy-src
3bcceb8362
Merge branch 'master' into nuphy-air75 2023-12-25 22:37:31 +08:00
nuphy-src
3995b3669c [Keyboard] Add nuphy air75 v2 keyboard 2023-12-25 22:16:06 +08:00
22 changed files with 3866 additions and 9 deletions

View File

@ -0,0 +1,274 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 "kb_util.h"
#include "ansi.h"
#include "usb_main.h"
extern bool f_rf_sw_press;
extern bool f_sleep_show;
extern bool f_dev_reset_press;
extern bool f_bat_num_show;
extern bool f_rgb_test_press;
extern bool f_bat_hold;
extern uint16_t no_act_time;
extern uint8_t rf_sw_temp;
extern uint16_t rf_sw_press_delay;
extern uint16_t rf_linking_time;
extern kb_config_t kb_config;
extern DEV_INFO_STRUCT dev_info;
/* qmk process record */
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
if(!process_record_user(keycode, record)){
return false;
}
no_act_time = 0;
rf_linking_time = 0;
switch (keycode) {
case RF_DFU:
if (record->event.pressed) {
if (dev_info.link_mode != LINK_USB) return false;
uart_send_cmd(CMD_RF_DFU, 10, 20);
}
return false;
case LNK_USB:
if (record->event.pressed) {
break_all_key();
} else {
dev_info.link_mode = LINK_USB;
uart_send_cmd(CMD_SET_LINK, 10, 10);
}
return false;
case LNK_RF:
if (record->event.pressed) {
if (dev_info.link_mode != LINK_USB) {
rf_sw_temp = LINK_RF_24;
f_rf_sw_press = 1;
break_all_key();
}
} else if (f_rf_sw_press) {
f_rf_sw_press = 0;
if (rf_sw_press_delay < RF_LONG_PRESS_DELAY) {
dev_info.link_mode = rf_sw_temp;
dev_info.rf_channel = rf_sw_temp;
dev_info.ble_channel = rf_sw_temp;
uart_send_cmd(CMD_SET_LINK, 10, 20);
}
}
return false;
case LNK_BLE1:
if (record->event.pressed) {
if (dev_info.link_mode != LINK_USB) {
rf_sw_temp = LINK_BT_1;
f_rf_sw_press = 1;
break_all_key();
}
} else if (f_rf_sw_press) {
f_rf_sw_press = 0;
if (rf_sw_press_delay < RF_LONG_PRESS_DELAY) {
dev_info.link_mode = rf_sw_temp;
dev_info.rf_channel = rf_sw_temp;
dev_info.ble_channel = rf_sw_temp;
uart_send_cmd(CMD_SET_LINK, 10, 20);
}
}
return false;
case LNK_BLE2:
if (record->event.pressed) {
if (dev_info.link_mode != LINK_USB) {
rf_sw_temp = LINK_BT_2;
f_rf_sw_press = 1;
break_all_key();
}
} else if (f_rf_sw_press) {
f_rf_sw_press = 0;
if (rf_sw_press_delay < RF_LONG_PRESS_DELAY) {
dev_info.link_mode = rf_sw_temp;
dev_info.rf_channel = rf_sw_temp;
dev_info.ble_channel = rf_sw_temp;
uart_send_cmd(CMD_SET_LINK, 10, 20);
}
}
return false;
case LNK_BLE3:
if (record->event.pressed) {
if (dev_info.link_mode != LINK_USB) {
rf_sw_temp = LINK_BT_3;
f_rf_sw_press = 1;
break_all_key();
}
} else if (f_rf_sw_press) {
f_rf_sw_press = 0;
if (rf_sw_press_delay < RF_LONG_PRESS_DELAY) {
dev_info.link_mode = rf_sw_temp;
dev_info.rf_channel = rf_sw_temp;
dev_info.ble_channel = rf_sw_temp;
uart_send_cmd(CMD_SET_LINK, 10, 20);
}
}
return false;
case MAC_VOICE:
if (record->event.pressed) {
host_consumer_send(0xcf);
} else {
host_consumer_send(0);
}
return false;
case MAC_DND:
if (record->event.pressed) {
host_system_send(0x9b);
} else {
host_system_send(0);
}
return false;
case SIDE_VAI:
if (record->event.pressed) {
side_light_control(1);
}
return false;
case SIDE_VAD:
if (record->event.pressed) {
side_light_control(0);
}
return false;
case SIDE_MOD:
if (record->event.pressed) {
side_mode_control(1);
}
return false;
case SIDE_HUI:
if (record->event.pressed) {
side_colour_control(1);
}
return false;
case SIDE_SPI:
if (record->event.pressed) {
side_speed_control(1);
}
return false;
case SIDE_SPD:
if (record->event.pressed) {
side_speed_control(0);
}
return false;
case DEV_RESET:
if (record->event.pressed) {
f_dev_reset_press = 1;
break_all_key();
} else {
f_dev_reset_press = 0;
}
return false;
case SLEEP_MODE:
if (record->event.pressed) {
if(kb_config.sleep_enable) kb_config.sleep_enable = false;
else kb_config.sleep_enable = true;
f_sleep_show = 1;
eeconfig_update_kb_datablock(&kb_config);
}
return false;
case BAT_SHOW:
if (record->event.pressed) {
f_bat_hold = !f_bat_hold;
}
return false;
case BAT_NUM:
f_bat_num_show = record->event.pressed;
return false;
case RGB_TEST:
f_rgb_test_press = record->event.pressed;
return false;
default:
return true;
}
return true;
}
bool rgb_matrix_indicators_kb(void)
{
if(!rgb_matrix_indicators_user()){
return false;
}
if(f_bat_num_show) {
num_led_show();
}
// fix power-on brightness is abnormal
rgb_matrix_set_color(RGB_MATRIX_LED_COUNT-1, 0, 0, 0);
return true;
}
/* qmk keyboard post init */
void keyboard_post_init_kb(void) {
gpio_init();
rf_uart_init();
wait_ms(500);
rf_device_init();
break_all_key();
dial_sw_fast_scan();
londing_eeprom_data();
keyboard_post_init_user();
}
/* qmk housekeeping task */
void housekeeping_task_kb(void) {
timer_pro();
uart_receive_pro();
uart_send_report_repeat();
dev_sts_sync();
long_press_key();
dial_sw_scan();
side_led_show();
sleep_handle();
}

View File

@ -0,0 +1,50 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 "quantum.h"
enum custom_keycodes {
RF_DFU = QK_KB_0,
LNK_USB,
LNK_RF,
LNK_BLE1,
LNK_BLE2,
LNK_BLE3,
MAC_VOICE,
MAC_DND,
SIDE_VAI,
SIDE_VAD,
SIDE_MOD,
SIDE_HUI,
SIDE_SPI,
SIDE_SPD,
DEV_RESET,
SLEEP_MODE,
BAT_SHOW,
BAT_NUM,
RGB_TEST
};
#define SYS_PRT G(S(KC_3))
#define MAC_PRTA G(S(KC_4))
#define WIN_PRTA G(S(KC_S))
#define MAC_SEARCH G(KC_SPC)

View File

@ -0,0 +1,36 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 DEV_MODE_PIN C0
#define SYS_MODE_PIN C1
#define DC_BOOST_PIN C2
#define NRF_RESET_PIN B4
#define NRF_TEST_PIN B5
#define NRF_WAKEUP_PIN B8
#define DRIVER_LED_CS_PIN C6
#define DRIVER_SIDE_PIN C8
#define DRIVER_SIDE_CS_PIN C9
#define SERIAL_DRIVER SD1
#define SD1_TX_PIN B6
#define SD1_TX_PAL_MODE 0
#define SD1_RX_PIN B7
#define SD1_RX_PAL_MODE 0
#define EECONFIG_KB_DATA_SIZE 8

View File

@ -0,0 +1,23 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 <halconf.h>
#undef HAL_USE_SERIAL
#define HAL_USE_SERIAL TRUE

View File

@ -0,0 +1,419 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 "kb_util.h"
#include "ansi.h"
#include "usb_main.h"
#include "rf_driver.h"
kb_config_t kb_config;
DEV_INFO_STRUCT dev_info = {
.rf_battery = 100,
.link_mode = LINK_USB,
.rf_state = RF_IDLE,
};
bool f_bat_hold = 0;
bool f_sys_show = 0;
bool f_sleep_show = 0;
bool f_send_channel = 0;
bool f_dial_sw_init_ok = 0;
bool f_rf_sw_press = 0;
bool f_dev_reset_press = 0;
bool f_rgb_test_press = 0;
bool f_bat_num_show = 0;
uint8_t rf_blink_cnt = 0;
uint8_t rf_sw_temp = 0;
uint8_t host_mode = 0;
uint16_t rf_linking_time = 0;
uint16_t rf_link_show_time = 0;
uint16_t no_act_time = 0;
uint16_t dev_reset_press_delay = 0;
uint16_t rf_sw_press_delay = 0;
uint16_t rgb_test_press_delay = 0;
host_driver_t *m_host_driver = 0;
extern bool f_rf_new_adv_ok;
extern report_keyboard_t *keyboard_report;
extern report_nkro_t *nkro_report;
extern uint8_t bitkb_report_buf[32];
extern uint8_t bytekb_report_buf[8];
extern uint8_t side_mode;
extern uint8_t side_light;
extern uint8_t side_speed;
extern uint8_t side_rgb;
extern uint8_t side_colour;
/**
* @brief Initialize GPIO.
*/
void gpio_init(void) {
/* enable LED power driver */
gpio_set_pin_output_push_pull(DRIVER_LED_CS_PIN);
gpio_set_pin_output_push_pull(DRIVER_SIDE_CS_PIN);
gpio_write_pin_low(DRIVER_LED_CS_PIN);
gpio_write_pin_low(DRIVER_SIDE_CS_PIN);
/* set side LED pin output low */
gpio_set_pin_output_push_pull(DRIVER_SIDE_PIN);
gpio_write_pin_low(DRIVER_SIDE_PIN);
/* config RF module pin */
gpio_set_pin_output_push_pull(NRF_WAKEUP_PIN);
gpio_write_pin_high(NRF_WAKEUP_PIN);
gpio_set_pin_input_high(NRF_TEST_PIN);
/* reset RF module */
gpio_set_pin_output_push_pull(NRF_RESET_PIN);
gpio_write_pin_low(NRF_RESET_PIN);
wait_ms(50);
gpio_write_pin_high(NRF_RESET_PIN);
/* config dial switch pin */
gpio_set_pin_input_high(DEV_MODE_PIN);
gpio_set_pin_input_high(SYS_MODE_PIN);
/* open LED DC driver */
gpio_set_pin_output_push_pull(DC_BOOST_PIN);
gpio_write_pin_high(DC_BOOST_PIN);
}
/**
* @brief long press key process.
*/
void long_press_key(void) {
static uint32_t long_press_timer = 0;
if (timer_elapsed32(long_press_timer) < 100) return;
long_press_timer = timer_read32();
// Open a new RF device
if (f_rf_sw_press) {
rf_sw_press_delay++;
if (rf_sw_press_delay >= RF_LONG_PRESS_DELAY) {
f_rf_sw_press = 0;
dev_info.link_mode = rf_sw_temp;
dev_info.rf_channel = rf_sw_temp;
dev_info.ble_channel = rf_sw_temp;
uint8_t timeout = 5;
while (timeout--) {
uart_send_cmd(CMD_NEW_ADV, 0, 1);
wait_ms(20);
uart_receive_pro();
if (f_rf_new_adv_ok) break;
}
}
} else {
rf_sw_press_delay = 0;
}
// The device is restored to factory settings
if (f_dev_reset_press) {
dev_reset_press_delay++;
if (dev_reset_press_delay >= DEV_RESET_PRESS_DELAY) {
f_dev_reset_press = 0;
if (dev_info.link_mode != LINK_USB) {
if (dev_info.link_mode != LINK_RF_24) {
dev_info.link_mode = LINK_BT_1;
dev_info.ble_channel = LINK_BT_1;
dev_info.rf_channel = LINK_BT_1;
}
} else {
dev_info.ble_channel = LINK_BT_1;
dev_info.rf_channel = LINK_BT_1;
}
uart_send_cmd(CMD_SET_LINK, 10, 10);
wait_ms(500);
uart_send_cmd(CMD_CLR_DEVICE, 10, 10);
void device_reset_show(void);
void device_reset_init(void);
eeconfig_init();
device_reset_show();
device_reset_init();
if (dev_info.sys_sw_state == SYS_SW_MAC) {
default_layer_set(1 << 0);
keymap_config.nkro = 0;
} else {
default_layer_set(1 << 2);
keymap_config.nkro = 1;
}
}
} else {
dev_reset_press_delay = 0;
}
// Enter the RGB test mode
if (f_rgb_test_press) {
rgb_test_press_delay++;
if (rgb_test_press_delay >= RGB_TEST_PRESS_DELAY) {
f_rgb_test_press = 0;
rgb_test_show();
}
} else {
rgb_test_press_delay = 0;
}
}
/**
* @brief Release all keys, clear keyboard report.
*/
void break_all_key(void) {
uint8_t report_buf[NKRO_REPORT_BITS + 1];
bool nkro_temp = keymap_config.nkro;
clear_weak_mods();
clear_mods();
clear_keyboard();
// break nkro key
keymap_config.nkro = 1;
memset(nkro_report, 0, sizeof(report_nkro_t));
host_nkro_send(nkro_report);
wait_ms(10);
// break byte key
keymap_config.nkro = 0;
memset(keyboard_report, 0, sizeof(report_keyboard_t));
host_keyboard_send(keyboard_report);
wait_ms(10);
keymap_config.nkro = nkro_temp;
if (dev_info.link_mode != LINK_USB) {
memset(report_buf, 0, NKRO_REPORT_BITS + 1);
uart_send_report(CMD_RPT_BIT_KB, report_buf, 16);
wait_ms(10);
uart_send_report(CMD_RPT_BYTE_KB, report_buf, 8);
wait_ms(10);
}
memset(bitkb_report_buf, 0, sizeof(bitkb_report_buf));
memset(bytekb_report_buf, 0, sizeof(bytekb_report_buf));
}
/**
* @brief switch device link mode.
* @param mode : link mode
*/
void switch_dev_link(uint8_t mode) {
if (mode > LINK_USB) return;
break_all_key();
dev_info.link_mode = mode;
dev_info.rf_state = RF_IDLE;
f_send_channel = 1;
if (mode == LINK_USB) {
host_mode = HOST_USB_TYPE;
host_set_driver(m_host_driver);
rf_link_show_time = 0;
} else {
host_mode = HOST_RF_TYPE;
host_set_driver(&rf_host_driver);
}
}
/**
* @brief scan dial switch.
*/
void dial_sw_scan(void) {
uint8_t dial_scan = 0;
static uint8_t dial_save = 0xf0;
static uint8_t debounce = 0;
static uint32_t dial_scan_timer = 0;
static bool f_first = true;
if (!f_first) {
if (timer_elapsed32(dial_scan_timer) < 20) return;
}
dial_scan_timer = timer_read32();
gpio_set_pin_input_high(DEV_MODE_PIN);
gpio_set_pin_input_high(SYS_MODE_PIN);
if (gpio_read_pin(DEV_MODE_PIN)) dial_scan |= 0X01;
if (gpio_read_pin(SYS_MODE_PIN)) dial_scan |= 0X02;
if (dial_save != dial_scan) {
break_all_key();
no_act_time = 0;
rf_linking_time = 0;
dial_save = dial_scan;
debounce = 25;
f_dial_sw_init_ok = 0;
return;
} else if (debounce) {
debounce--;
return;
}
if (dial_scan & 0x01) {
if (dev_info.link_mode != LINK_USB) {
switch_dev_link(LINK_USB);
}
} else {
if (dev_info.link_mode != dev_info.rf_channel) {
switch_dev_link(dev_info.rf_channel);
}
}
if (dial_scan & 0x02) {
if (dev_info.sys_sw_state != SYS_SW_MAC) {
f_sys_show = 1;
default_layer_set(1 << 0);
dev_info.sys_sw_state = SYS_SW_MAC;
keymap_config.nkro = 0;
break_all_key();
}
} else {
if (dev_info.sys_sw_state != SYS_SW_WIN) {
f_sys_show = 1;
default_layer_set(1 << 2);
dev_info.sys_sw_state = SYS_SW_WIN;
keymap_config.nkro = 1;
break_all_key();
}
}
if (f_dial_sw_init_ok == 0) {
f_dial_sw_init_ok = 1;
f_first = false;
if (dev_info.link_mode != LINK_USB) {
host_set_driver(&rf_host_driver);
}
}
}
/**
* @brief power on scan dial switch.
*/
void dial_sw_fast_scan(void) {
{
uint8_t dial_scan_dev = 0;
uint8_t dial_scan_sys = 0;
uint8_t dial_check_dev = 0;
uint8_t dial_check_sys = 0;
uint8_t debounce = 0;
gpio_set_pin_input_high(DEV_MODE_PIN);
gpio_set_pin_input_high(SYS_MODE_PIN);
// Debounce to get a stable state
for(debounce=0; debounce<10; debounce++) {
dial_scan_dev = 0;
dial_scan_sys = 0;
if (gpio_read_pin(DEV_MODE_PIN)) dial_scan_dev = 0x01;
else dial_scan_dev = 0;
if (gpio_read_pin(SYS_MODE_PIN)) dial_scan_sys = 0x01;
else dial_scan_sys = 0;
if((dial_scan_dev != dial_check_dev)||(dial_scan_sys != dial_check_sys))
{
dial_check_dev = dial_scan_dev;
dial_check_sys = dial_scan_sys;
debounce = 0;
}
wait_ms(1);
}
// RF link mode
if (dial_scan_dev) {
if (dev_info.link_mode != LINK_USB) {
switch_dev_link(LINK_USB);
}
} else {
if (dev_info.link_mode != dev_info.rf_channel) {
switch_dev_link(dev_info.rf_channel);
}
}
// Win or Mac
if (dial_scan_sys) {
if (dev_info.sys_sw_state != SYS_SW_MAC) {
default_layer_set(1 << 0);
dev_info.sys_sw_state = SYS_SW_MAC;
keymap_config.nkro = 0;
break_all_key();
}
} else {
if (dev_info.sys_sw_state != SYS_SW_WIN) {
//f_sys_show = 1;
default_layer_set(1 << 2);
dev_info.sys_sw_state = SYS_SW_WIN;
keymap_config.nkro = 1;
break_all_key();
}
}
}
}
/**
* @brief timer process.
*/
void timer_pro(void) {
static uint32_t interval_timer = 0;
static bool f_first = true;
if (f_first) {
f_first = false;
interval_timer = timer_read32();
m_host_driver = host_get_driver();
}
// step 10ms
if (timer_elapsed32(interval_timer) < 10)
return;
else
interval_timer = timer_read32();
if (rf_link_show_time < RF_LINK_SHOW_TIME) rf_link_show_time++;
if (no_act_time < 0xffff) no_act_time++;
if (rf_linking_time < 0xffff) rf_linking_time++;
}
/**
* @brief londing eeprom data.
*/
void londing_eeprom_data(void) {
eeconfig_read_kb_datablock(&kb_config);
if (kb_config.default_brightness_flag != 0xA5) {
/* upon first power on, set RGB matrix brightness to middle level */
rgb_matrix_sethsv(255, 255, RGB_MATRIX_MAXIMUM_BRIGHTNESS - RGB_MATRIX_VAL_STEP * 2);
kb_config.default_brightness_flag = 0xA5;
kb_config.ee_side_mode = side_mode;
kb_config.ee_side_light = side_light;
kb_config.ee_side_speed = side_speed;
kb_config.ee_side_rgb = side_rgb;
kb_config.ee_side_colour = side_colour;
kb_config.sleep_enable = true;
eeconfig_update_kb_datablock(&kb_config);
} else {
side_mode = kb_config.ee_side_mode;
side_light = kb_config.ee_side_light;
side_speed = kb_config.ee_side_speed;
side_rgb = kb_config.ee_side_rgb;
side_colour = kb_config.ee_side_colour;
}
}

View File

@ -0,0 +1,167 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 "quantum.h"
typedef enum {
RX_Idle,
RX_Receiving,
RX_Done,
RX_Fail,
RX_OV_ERR,
RX_SUM_ERR,
RX_CMD_ERR,
RX_DATA_ERR,
RX_DATA_OV,
RX_FORMAT_ERR,
TX_OK = 0XE0,
TX_DONE,
TX_BUSY,
TX_TIMEOUT,
TX_DATA_ERR,
} TYPE_RX_STATE;
#define RF_IDLE 0
#define RF_PAIRING 1
#define RF_LINKING 2
#define RF_CONNECT 3
#define RF_DISCONNECT 4
#define RF_SLEEP 5
#define RF_SNIF 6
#define RF_INVALID 0XFE
#define RF_ERR_STATE 0XFF
#define CMD_POWER_UP 0XF0
#define CMD_SLEEP 0XF1
#define CMD_HAND 0XF2
#define CMD_SNIF 0XF3
#define CMD_24G_SUSPEND 0XF4
#define CMD_IDLE_EXIT 0XFE
#define CMD_RPT_MS 0XE0
#define CMD_RPT_BYTE_KB 0XE1
#define CMD_RPT_BIT_KB 0XE2
#define CMD_RPT_CONSUME 0XE3
#define CMD_RPT_SYS 0XE4
#define CMD_SET_LINK 0XC0
#define CMD_SET_CONFIG 0XC1
#define CMD_GET_CONFIG 0XC2
#define CMD_SET_NAME 0XC3
#define CMD_GET_NAME 0XC4
#define CMD_CLR_DEVICE 0XC5
#define CMD_NEW_ADV 0XC7
#define CMD_RF_STS_SYSC 0XC9
#define CMD_SET_24G_NAME 0XCA
#define CMD_GO_TEST 0XCF
#define CMD_RF_DFU 0XB1
#define CMD_WRITE_DATA 0X80
#define CMD_READ_DATA 0X81
#define LINK_RF_24 0
#define LINK_BT_1 1
#define LINK_BT_2 2
#define LINK_BT_3 3
#define LINK_USB 4
#define UART_HEAD 0x5A
#define FUNC_VALID_LEN 32
#define UART_MAX_LEN 64
#define SYS_SW_WIN 0xa1
#define SYS_SW_MAC 0xa2
#define RF_LINK_SHOW_TIME 300
#define HOST_USB_TYPE 0
#define HOST_BLE_TYPE 1
#define HOST_RF_TYPE 2
#define LINK_TIMEOUT (100 * 120)
#define SLEEP_TIME_DELAY (100 * 360)
#define POWER_DOWN_DELAY (24)
#define RF_LONG_PRESS_DELAY 30
#define DEV_RESET_PRESS_DELAY 30
#define RGB_TEST_PRESS_DELAY 30
typedef struct
{
uint8_t RXDState;
uint8_t RXDLen;
uint8_t RXDOverTime;
uint8_t TXDLenBack;
uint8_t TXDOffset;
uint8_t TXDBuf[UART_MAX_LEN];
uint8_t RXDBuf[UART_MAX_LEN];
} USART_MGR_STRUCT;
typedef struct
{
uint8_t link_mode;
uint8_t rf_channel;
uint8_t ble_channel;
uint8_t rf_state;
uint8_t rf_charge;
uint8_t rf_led;
uint8_t rf_battery;
uint8_t sys_sw_state;
} DEV_INFO_STRUCT;
typedef struct
{
uint8_t default_brightness_flag;
uint8_t ee_side_mode;
uint8_t ee_side_light;
uint8_t ee_side_speed;
uint8_t ee_side_rgb;
uint8_t ee_side_colour;
uint8_t sleep_enable;
uint8_t retain1;
uint8_t retain2;
} kb_config_t;
void dev_sts_sync(void);
void rf_uart_init(void);
void rf_device_init(void);
void uart_send_report_repeat(void);
void uart_receive_pro(void);
void uart_send_report(uint8_t report_type, uint8_t *report_buf, uint8_t report_size);
void side_speed_control(uint8_t dir);
void side_light_control(uint8_t dir);
void side_colour_control(uint8_t dir);
void side_mode_control(uint8_t dir);
void side_led_show(void);
void sleep_handle(void);
void bat_led_close(void);
void num_led_show(void);
void rgb_test_show(void);
void gpio_init(void);
void long_press_key(void);
void break_all_key(void);
void switch_dev_link(uint8_t mode);
void dial_sw_scan(void);
void dial_sw_fast_scan(void);
void timer_pro(void);
void londing_eeprom_data(void);
uint8_t uart_send_cmd(uint8_t cmd, uint8_t ack_cnt, uint8_t delayms);

View File

@ -0,0 +1,275 @@
{
"keyboard_name": "NuPhy Air75 V2",
"manufacturer": "NuPhy",
"usb":{
"vid": "0x19F5",
"pid": "0x3246",
"device_version": "0.0.1",
"no_startup_check": true
},
"features": {
"bootmagic": true,
"mousekey": true,
"extrakey": true,
"console": true,
"command": false,
"nkro": true,
"key_lock": true,
"rgb_matrix": true
},
"processor": "STM32F072",
"bootloader": "stm32-dfu",
"debounce": 2,
"matrix_pins": {
"cols": ["A4", "A5", "A6", "B9", "B0", "B1", "B10", "B11", "B12", "B13", "B14", "B15", "A8", "A9", "A10", "A15", "B3"],
"rows": ["C14", "C15", "A0", "A1", "A2", "A3"]
},
"diode_direction": "COL2ROW",
"dynamic_keymap": {
"layer_count": 8,
"micro_delay": 8
},
"qmk": {
"tap_keycode_delay": 8
},
"rgb_matrix": {
"driver": "ws2812",
"center_point": [80, 30],
"max_brightness": 128,
"val_steps": 26,
"speed_steps": 52,
"sleep": true,
"animations": {
"gradient_up_down": true,
"gradient_left_right": true,
"breathing": true,
"band_sat": true,
"band_val": true,
"band_pinwheel_sat": true,
"band_pinwheel_val": true,
"band_spiral_sat": true,
"band_spiral_val": true,
"cycle_all": true,
"cycle_left_right": true,
"cycle_up_down": true,
"rainbow_moving_chevron": true,
"cycle_out_in": true,
"cycle_out_in_dual": true,
"cycle_pinwheel": true,
"cycle_spiral": true,
"dual_beacon": true,
"rainbow_beacon": true,
"rainbow_pinwheels": true,
"raindrops": true,
"jellybean_raindrops": true,
"hue_breathing": true,
"hue_pendulum": true,
"hue_wave": true,
"typing_heatmap": true,
"digital_rain": true,
"solid_reactive_simple": true,
"solid_reactive": true,
"solid_reactive_wide": true,
"solid_reactive_multiwide": true,
"solid_reactive_cross": true,
"solid_reactive_multicross": true,
"solid_reactive_nexus": true,
"solid_reactive_multinexus": true,
"splash": true,
"multisplash": true,
"solid_splash": true,
"solid_multisplash": true
},
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0, "flags": 4},
{"matrix": [0, 1], "x": 10, "y": 0, "flags": 4},
{"matrix": [0, 2], "x": 20, "y": 0, "flags": 4},
{"matrix": [0, 3], "x": 30, "y": 0, "flags": 4},
{"matrix": [0, 4], "x": 40, "y": 0, "flags": 4},
{"matrix": [0, 5], "x": 50, "y": 0, "flags": 4},
{"matrix": [0, 6], "x": 60, "y": 0, "flags": 4},
{"matrix": [0, 7], "x": 70, "y": 0, "flags": 4},
{"matrix": [0, 8], "x": 80, "y": 0, "flags": 4},
{"matrix": [0, 9], "x": 90, "y": 0, "flags": 4},
{"matrix": [0, 10], "x": 100, "y": 0, "flags": 4},
{"matrix": [0, 11], "x": 110, "y": 0, "flags": 4},
{"matrix": [0, 12], "x": 120, "y": 0, "flags": 4},
{"matrix": [2, 14], "x": 130, "y": 0, "flags": 4},
{"matrix": [0, 15], "x": 140, "y": 0, "flags": 4},
{"matrix": [0, 14], "x": 150, "y": 0, "flags": 4},
{"matrix": [1, 16], "x": 150, "y": 10, "flags": 4},
{"matrix": [1, 13], "x": 130, "y": 10, "flags": 4},
{"matrix": [1, 12], "x": 120, "y": 10, "flags": 4},
{"matrix": [1, 11], "x": 110, "y": 10, "flags": 4},
{"matrix": [1, 10], "x": 100, "y": 10, "flags": 4},
{"matrix": [1, 9], "x": 90, "y": 10, "flags": 4},
{"matrix": [1, 8], "x": 80, "y": 10, "flags": 4},
{"matrix": [1, 7], "x": 70, "y": 10, "flags": 4},
{"matrix": [1, 6], "x": 60, "y": 10, "flags": 4},
{"matrix": [1, 5], "x": 50, "y": 10, "flags": 4},
{"matrix": [1, 4], "x": 40, "y": 10, "flags": 4},
{"matrix": [1, 3], "x": 30, "y": 10, "flags": 4},
{"matrix": [1, 2], "x": 20, "y": 10, "flags": 4},
{"matrix": [1, 1], "x": 10, "y": 10, "flags": 4},
{"matrix": [1, 0], "x": 0, "y": 10, "flags": 4},
{"matrix": [2, 0], "x": 0, "y": 20, "flags": 4},
{"matrix": [2, 1], "x": 15, "y": 20, "flags": 4},
{"matrix": [2, 2], "x": 25, "y": 20, "flags": 4},
{"matrix": [2, 3], "x": 35, "y": 20, "flags": 4},
{"matrix": [2, 4], "x": 45, "y": 20, "flags": 4},
{"matrix": [2, 5], "x": 55, "y": 20, "flags": 4},
{"matrix": [2, 6], "x": 65, "y": 20, "flags": 4},
{"matrix": [2, 7], "x": 75, "y": 20, "flags": 4},
{"matrix": [2, 8], "x": 85, "y": 20, "flags": 4},
{"matrix": [2, 9], "x": 95, "y": 20, "flags": 4},
{"matrix": [2, 10], "x": 105, "y": 20, "flags": 4},
{"matrix": [2, 11], "x": 115, "y": 20, "flags": 4},
{"matrix": [2, 12], "x": 125, "y": 20, "flags": 4},
{"matrix": [2, 13], "x": 135, "y": 20, "flags": 4},
{"matrix": [2, 16], "x": 150, "y": 20, "flags": 4},
{"matrix": [1, 15], "x": 150, "y": 30, "flags": 4},
{"matrix": [3, 13], "x": 127, "y": 30, "flags": 4},
{"matrix": [3, 11], "x": 117, "y": 30, "flags": 4},
{"matrix": [3, 10], "x": 107, "y": 30, "flags": 4},
{"matrix": [3, 9], "x": 97, "y": 30, "flags": 4},
{"matrix": [3, 8], "x": 87, "y": 30, "flags": 4},
{"matrix": [3, 7], "x": 77, "y": 30, "flags": 4},
{"matrix": [3, 6], "x": 67, "y": 30, "flags": 4},
{"matrix": [3, 5], "x": 57, "y": 30, "flags": 4},
{"matrix": [3, 4], "x": 47, "y": 30, "flags": 4},
{"matrix": [3, 3], "x": 37, "y": 30, "flags": 4},
{"matrix": [3, 2], "x": 27, "y": 30, "flags": 4},
{"matrix": [3, 1], "x": 17, "y": 30, "flags": 4},
{"matrix": [3, 0], "x": 0, "y": 30, "flags": 4},
{"matrix": [4, 0], "x": 0, "y": 40, "flags": 4},
{"matrix": [4, 2], "x": 22, "y": 40, "flags": 4},
{"matrix": [4, 3], "x": 32, "y": 40, "flags": 4},
{"matrix": [4, 4], "x": 42, "y": 40, "flags": 4},
{"matrix": [4, 5], "x": 52, "y": 40, "flags": 4},
{"matrix": [4, 6], "x": 62, "y": 40, "flags": 4},
{"matrix": [4, 7], "x": 72, "y": 40, "flags": 4},
{"matrix": [4, 8], "x": 82, "y": 40, "flags": 4},
{"matrix": [4, 9], "x": 92, "y": 40, "flags": 4},
{"matrix": [4, 10], "x": 102, "y": 40, "flags": 4},
{"matrix": [4, 11], "x": 112, "y": 40, "flags": 4},
{"matrix": [4, 13], "x": 122, "y": 40, "flags": 4},
{"matrix": [4, 14], "x": 140, "y": 40, "flags": 4},
{"matrix": [2, 15], "x": 150, "y": 40, "flags": 4},
{"matrix": [5, 15], "x": 150, "y": 50, "flags": 4},
{"matrix": [5, 14], "x": 140, "y": 50, "flags": 4},
{"matrix": [5, 13], "x": 130, "y": 50, "flags": 4},
{"matrix": [3, 14], "x": 120, "y": 50, "flags": 4},
{"matrix": [5, 10], "x": 110, "y": 50, "flags": 4},
{"matrix": [5, 9], "x": 100, "y": 50, "flags": 4},
{"matrix": [5, 6], "x": 37, "y": 50, "flags": 4},
{"matrix": [5, 2], "x": 25, "y": 50, "flags": 4},
{"matrix": [5, 1], "x": 12, "y": 50, "flags": 4},
{"matrix": [5, 0], "x": 0, "y": 50, "flags": 4},
{"flags": 4}
]
},
"ws2812": {
"pin": "A7"
},
"community_layouts": ["75_ansi"],
"layouts": {
"LAYOUT_75_ansi": {
"layout": [
{"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
{"label": "F1", "matrix": [0, 1], "x": 1, "y": 0},
{"label": "F2", "matrix": [0, 2], "x": 2, "y": 0},
{"label": "F3", "matrix": [0, 3], "x": 3, "y": 0},
{"label": "F4", "matrix": [0, 4], "x": 4, "y": 0},
{"label": "F5", "matrix": [0, 5], "x": 5, "y": 0},
{"label": "F6", "matrix": [0, 6], "x": 6, "y": 0},
{"label": "F7", "matrix": [0, 7], "x": 7, "y": 0},
{"label": "F8", "matrix": [0, 8], "x": 8, "y": 0},
{"label": "F9", "matrix": [0, 9], "x": 9, "y": 0},
{"label": "F10", "matrix": [0, 10], "x": 10, "y": 0},
{"label": "F11", "matrix": [0, 11], "x": 11, "y": 0},
{"label": "F12", "matrix": [0, 12], "x": 12, "y": 0},
{"label": "Print", "matrix": [2, 14], "x": 13, "y": 0},
{"label": "Ins", "matrix": [0, 15], "x": 14, "y": 0},
{"label": "Del", "matrix": [0, 14], "x": 15, "y": 0},
{"label": "~`", "matrix": [1, 0], "x": 0, "y": 1},
{"label": "!1", "matrix": [1, 1], "x": 1, "y": 1},
{"label": "@2", "matrix": [1, 2], "x": 2, "y": 1},
{"label": "#3", "matrix": [1, 3], "x": 3, "y": 1},
{"label": "$4", "matrix": [1, 4], "x": 4, "y": 1},
{"label": "%5", "matrix": [1, 5], "x": 5, "y": 1},
{"label": "^6", "matrix": [1, 6], "x": 6, "y": 1},
{"label": "&7", "matrix": [1, 7], "x": 7, "y": 1},
{"label": "*8", "matrix": [1, 8], "x": 8, "y": 1},
{"label": "(9", "matrix": [1, 9], "x": 9, "y": 1},
{"label": ")0", "matrix": [1, 10], "x": 10, "y": 1},
{"label": "_-", "matrix": [1, 11], "x": 11, "y": 1},
{"label": "+=", "matrix": [1, 12], "x": 12, "y": 1},
{"label": "Backsp", "matrix": [1, 13], "x": 13, "y": 1, "w": 2},
{"label": "PageUp", "matrix": [1, 16], "x": 15, "y": 1},
{"label": "Tab", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.5},
{"label": "Q", "matrix": [2, 1], "x": 1.5, "y": 2},
{"label": "W", "matrix": [2, 2], "x": 2.5, "y": 2},
{"label": "E", "matrix": [2, 3], "x": 3.5, "y": 2},
{"label": "R", "matrix": [2, 4], "x": 4.5, "y": 2},
{"label": "T", "matrix": [2, 5], "x": 5.5, "y": 2},
{"label": "Y", "matrix": [2, 6], "x": 6.5, "y": 2},
{"label": "U", "matrix": [2, 7], "x": 7.5, "y": 2},
{"label": "I", "matrix": [2, 8], "x": 8.5, "y": 2},
{"label": "O", "matrix": [2, 9], "x": 9.5, "y": 2},
{"label": "P", "matrix": [2, 10], "x": 10.5, "y": 2},
{"label": "{[", "matrix": [2, 11], "x": 11.5, "y": 2},
{"label": "}]", "matrix": [2, 12], "x": 12.5, "y": 2},
{"label": "|\\", "matrix": [2, 13], "x": 13.5, "y": 2, "w": 1.5},
{"label": "PageDn", "matrix": [2, 16], "x": 15, "y": 2},
{"label": "Caps", "matrix": [3, 0], "x": 0, "y": 3, "w": 1.75},
{"label": "A", "matrix": [3, 1], "x": 1.75, "y": 3},
{"label": "S", "matrix": [3, 2], "x": 2.75, "y": 3},
{"label": "D", "matrix": [3, 3], "x": 3.75, "y": 3},
{"label": "F", "matrix": [3, 4], "x": 4.75, "y": 3},
{"label": "G", "matrix": [3, 5], "x": 5.75, "y": 3},
{"label": "H", "matrix": [3, 6], "x": 6.75, "y": 3},
{"label": "J", "matrix": [3, 7], "x": 7.75, "y": 3},
{"label": "K", "matrix": [3, 8], "x": 8.75, "y": 3},
{"label": "L", "matrix": [3, 9], "x": 9.75, "y": 3},
{"label": ":", "matrix": [3, 10], "x": 10.75, "y": 3},
{"label": "\"", "matrix": [3, 11], "x": 11.75, "y": 3},
{"label": "Enter", "matrix": [3, 13], "x": 12.75, "y": 3, "w": 2.25},
{"label": "Home", "matrix": [1, 15], "x": 15, "y": 3},
{"label": "Shift", "matrix": [4, 0], "x": 0, "y": 4, "w": 2.25},
{"label": "Z", "matrix": [4, 2], "x": 2.25, "y": 4},
{"label": "X", "matrix": [4, 3], "x": 3.25, "y": 4},
{"label": "C", "matrix": [4, 4], "x": 4.25, "y": 4},
{"label": "V", "matrix": [4, 5], "x": 5.25, "y": 4},
{"label": "B", "matrix": [4, 6], "x": 6.25, "y": 4},
{"label": "N", "matrix": [4, 7], "x": 7.25, "y": 4},
{"label": "M", "matrix": [4, 8], "x": 8.25, "y": 4},
{"label": "<,", "matrix": [4, 9], "x": 9.25, "y": 4},
{"label": ">.", "matrix": [4, 10], "x": 10.25, "y": 4},
{"label": "?/", "matrix": [4, 11], "x": 11.25, "y": 4},
{"label": "Shift", "matrix": [4, 13], "x": 12.25, "y": 4, "w": 1.75},
{"label": "↑", "matrix": [4, 14], "x": 14, "y": 4},
{"label": "End", "matrix": [2, 15], "x": 15, "y": 4},
{"label": "Ctrl", "matrix": [5, 0], "x": 0, "y": 5, "w": 1.25},
{"label": "Opt", "matrix": [5, 1], "x": 1.25, "y": 5, "w": 1.25},
{"label": "Cmd", "matrix": [5, 2], "x": 2.5, "y": 5, "w": 1.25},
{"label": "Space", "matrix": [5, 6], "x": 3.75, "y": 5, "w": 6.25},
{"label": "Cmd", "matrix": [5, 9], "x": 10, "y": 5},
{"label": "Fn", "matrix": [5, 10], "x": 11, "y": 5},
{"label": "Ctrl", "matrix": [3, 14], "x": 12, "y": 5},
{"label": "←", "matrix": [5, 13], "x": 13, "y": 5},
{"label": "↓", "matrix": [5, 14], "x": 14, "y": 5},
{"label": "→", "matrix": [5, 15], "x": 15, "y": 5}
]
}
}
}

View File

@ -0,0 +1,66 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// layer Mac
[0] = LAYOUT_75_ansi(
KC_ESC, KC_BRID, KC_BRIU, KC_MCTL, MAC_SEARCH, MAC_VOICE, MAC_DND, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, MAC_PRTA, KC_INS, KC_DEL,
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_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_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_ENT, KC_HOME,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_END,
KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
// layer Mac Fn
[1] = LAYOUT_75_ansi(
_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, SYS_PRT, _______, _______,
_______, LNK_BLE1, LNK_BLE2, LNK_BLE3, LNK_RF, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, DEV_RESET, SLEEP_MODE, BAT_SHOW, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, RGB_TEST, _______, BAT_NUM, _______, MO(4), RGB_SPD, RGB_SPI, _______, _______, RGB_VAI, _______,
_______, _______, _______, _______, _______, MO(1), _______, RGB_MOD, RGB_VAD, RGB_HUI),
// layer win
[2] = LAYOUT_75_ansi(
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_INS, KC_DEL,
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_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_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_ENT, KC_HOME,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_END,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(3), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
// layer win Fn
[3] = LAYOUT_75_ansi(
_______, KC_BRID, KC_BRIU, _______, _______, _______, _______, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______,
_______, LNK_BLE1, LNK_BLE2, LNK_BLE3, LNK_RF, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, DEV_RESET, SLEEP_MODE, BAT_SHOW, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, RGB_TEST, _______, BAT_NUM, _______, MO(4), RGB_SPD, RGB_SPI, _______, _______, RGB_VAI, _______,
_______, _______, _______, _______, _______, MO(3), _______, RGB_MOD, RGB_VAD, RGB_HUI),
// layer 4
[4] = LAYOUT_75_ansi(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, SIDE_SPD, SIDE_SPI, _______, _______, SIDE_VAI, _______,
_______, _______, _______, _______, _______, MO(4), _______, SIDE_MOD, SIDE_VAD, SIDE_HUI)
};

View File

@ -0,0 +1,66 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// layer Mac
[0] = LAYOUT_75_ansi(
KC_ESC, KC_BRID, KC_BRIU, KC_MCTL, MAC_SEARCH, MAC_VOICE, MAC_DND, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, MAC_PRTA, KC_INS, KC_DEL,
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_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_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_ENT, KC_HOME,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_END,
KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
// layer Mac Fn
[1] = LAYOUT_75_ansi(
_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, SYS_PRT, _______, _______,
_______, LNK_BLE1, LNK_BLE2, LNK_BLE3, LNK_RF, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, DEV_RESET, SLEEP_MODE, BAT_SHOW, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, RGB_TEST, _______, BAT_NUM, _______, MO(4), RGB_SPD, RGB_SPI, _______, _______, RGB_VAI, _______,
_______, _______, _______, _______, _______, MO(1), _______, RGB_MOD, RGB_VAD, RGB_HUI),
// layer win
[2] = LAYOUT_75_ansi(
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_INS, KC_DEL,
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_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_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_ENT, KC_HOME,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_END,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(3), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
// layer win Fn
[3] = LAYOUT_75_ansi(
_______, KC_BRID, KC_BRIU, _______, _______, _______, _______, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______,
_______, LNK_BLE1, LNK_BLE2, LNK_BLE3, LNK_RF, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, DEV_RESET, SLEEP_MODE, BAT_SHOW, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, RGB_TEST, _______, BAT_NUM, _______, MO(4), RGB_SPD, RGB_SPI, _______, _______, RGB_VAI, _______,
_______, _______, _______, _______, _______, MO(3), _______, RGB_MOD, RGB_VAD, RGB_HUI),
// layer 4
[4] = LAYOUT_75_ansi(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, SIDE_SPD, SIDE_SPI, _______, _______, SIDE_VAI, _______,
_______, _______, _______, _______, _______, MO(4), _______, SIDE_MOD, SIDE_VAD, SIDE_HUI)
};

View File

@ -0,0 +1 @@
VIA_ENABLE = yes

View File

@ -0,0 +1,23 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 STM32_SERIAL_USE_USART1
#define STM32_SERIAL_USE_USART1 TRUE

View File

@ -0,0 +1,25 @@
# NuPhy Air75 V2
*NuPhy Air75 V2 is a standard 84 key keyboard.*
![NuPhy Air75 V2](https://i.imgur.com/R7jS2JC.jpeg)
* Keyboard Maintainer: [nuphy](https://github.com/nuphy-src)
* Hardware Supported: NuPhy Air75 V2 PCB
* Hardware Availability: [link](https://nuphy.com/products/air75-v2)
Make example for this keyboard (after setting up your build environment):
make nuphy/air75_v2/ansi:default
Flashing example for this keyboard:
make nuphy/air75_v2/ansi: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 one way:
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (usually the top left key or Escape) and plug in the keyboard
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available

View File

@ -0,0 +1,648 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 "kb_util.h"
#include "uart.h" // qmk uart.h
#include "ansi.h"
#include "rf_driver.h"
USART_MGR_STRUCT Usart_Mgr;
#define RX_SBYTE Usart_Mgr.RXDBuf[0]
#define RX_CMD Usart_Mgr.RXDBuf[1]
#define RX_ACK Usart_Mgr.RXDBuf[2]
#define RX_LEN Usart_Mgr.RXDBuf[3]
#define RX_DAT Usart_Mgr.RXDBuf[4]
bool f_uart_ack = 0;
bool f_rf_read_data_ok = 0;
bool f_rf_sts_sysc_ok = 0;
bool f_rf_new_adv_ok = 0;
bool f_rf_reset = 0;
bool f_rf_hand_ok = 0;
bool f_goto_sleep = 0;
bool f_wakeup_prepare = 0;
uint8_t uart_bit_report_buf[32] = {0};
uint8_t func_tab[32] = {0};
uint8_t bitkb_report_buf[32] = {0};
uint8_t bytekb_report_buf[8] = {0};
uint16_t conkb_report = 0;
uint16_t syskb_report = 0;
uint8_t sync_lost = 0;
uint8_t disconnect_delay = 0;
extern DEV_INFO_STRUCT dev_info;
extern host_driver_t *m_host_driver;
extern uint8_t host_mode;
extern uint8_t rf_blink_cnt;
extern uint16_t rf_link_show_time;
extern uint16_t rf_linking_time;
extern uint16_t no_act_time;
extern bool f_send_channel;
extern bool f_dial_sw_init_ok;
report_mouse_t mousekey_get_report(void);
void uart_init(uint32_t baud); // qmk uart.c
void uart_send_report(uint8_t report_type, uint8_t *report_buf, uint8_t report_size);
void UART_Send_Bytes(uint8_t *Buffer, uint32_t Length);
uint8_t get_checksum(uint8_t *buf, uint8_t len);
void uart_receive_pro(void);
void break_all_key(void);
uint16_t host_last_consumer_usage(void);
/**
* @brief Uart auto nkey send
*/
bool f_bit_kb_act = 0;
static void uart_auto_nkey_send(uint8_t *pre_bit_report, uint8_t *now_bit_report, uint8_t size)
{
uint8_t i, j, byte_index;
uint8_t change_mask, offset_mask;
uint8_t key_code = 0;
bool f_byte_send = 0, f_bit_send = 0;
if (pre_bit_report[0] ^ now_bit_report[0]) {
bytekb_report_buf[0] = now_bit_report[0];
f_byte_send = 1;
}
for (i = 1; i < size; i++) {
change_mask = pre_bit_report[i] ^ now_bit_report[i];
offset_mask = 1;
for (j = 0; j < 8; j++) {
if (change_mask & offset_mask) {
if (now_bit_report[i] & offset_mask) {
for (byte_index = 2; byte_index < 8; byte_index++) {
if (bytekb_report_buf[byte_index] == 0) {
bytekb_report_buf[byte_index] = key_code;
f_byte_send = 1;
break;
}
}
if (byte_index >= 8) {
uart_bit_report_buf[i] |= offset_mask;
f_bit_send = 1;
}
} else {
for (byte_index = 2; byte_index < 8; byte_index++) {
if (bytekb_report_buf[byte_index] == key_code) {
bytekb_report_buf[byte_index] = 0;
f_byte_send = 1;
break;
}
}
if (byte_index >= 8) {
uart_bit_report_buf[i] &= ~offset_mask;
f_bit_send = 1;
}
}
}
key_code++;
offset_mask <<= 1;
}
}
if (f_bit_send) {
f_bit_kb_act = 1;
uart_send_report(CMD_RPT_BIT_KB, uart_bit_report_buf, 16);
}
if (f_byte_send) {
uart_send_report(CMD_RPT_BYTE_KB, bytekb_report_buf, 8);
}
}
/**
* @brief Uart send keys report.
*/
void uart_send_report_repeat(void)
{
static uint32_t interval_timer = 0;
if (dev_info.link_mode == LINK_USB) return;
keyboard_protocol = 1;
if (timer_elapsed32(interval_timer) > 50) {
interval_timer = timer_read32();
if (no_act_time <= 200) {
uart_send_report(CMD_RPT_BYTE_KB, bytekb_report_buf, 8);
wait_us(200);
if(f_bit_kb_act)
uart_send_report(CMD_RPT_BIT_KB, uart_bit_report_buf, 16);
}
else {
f_bit_kb_act = 0;
}
}
}
/**
* @brief Uart send consumer keys report.
* @note Call in rf_driver.c
*/
void uart_send_consumer_report(report_extra_t *report) {
no_act_time = 0;
uart_send_report(CMD_RPT_CONSUME, (uint8_t *)(&report->usage), 2);
}
/**
* @brief Uart send mouse keys report.
* @note Call in rf_driver.c
*/
void uart_send_mouse_report(report_mouse_t *report) {
no_act_time = 0;
uart_send_report(CMD_RPT_MS, &report->buttons, 5);
}
/**
* @brief Uart send system keys report.
* @note Call in rf_driver.c
*/
void uart_send_system_report(report_extra_t *report) {
no_act_time = 0;
uart_send_report(CMD_RPT_SYS, (uint8_t *)(&report->usage), 2);
}
/**
* @brief Uart send byte keys report.
* @note Call in rf_driver.c
*/
void uart_send_report_keyboard(report_keyboard_t *report) {
no_act_time = 0;
report->reserved = 0;
uart_send_report(CMD_RPT_BYTE_KB, &report->mods, 8);
memcpy(bytekb_report_buf, &report->mods, 8);
}
/**
* @brief Uart send bit keys report.
* @note Call in rf_driver.c
*/
void uart_send_report_nkro(report_nkro_t *report) {
no_act_time = 0;
uart_auto_nkey_send(bitkb_report_buf, &nkro_report->mods, NKRO_REPORT_BITS + 1);
memcpy(&bitkb_report_buf[0], &nkro_report->mods, NKRO_REPORT_BITS + 1);
}
/**
* @brief Parsing the data received from the RF module.
*/
void RF_Protocol_Receive(void) {
uint8_t i, check_sum = 0;
if (Usart_Mgr.RXDState == RX_Done) {
f_uart_ack = 1;
sync_lost = 0;
if (Usart_Mgr.RXDLen > 4) {
for (i = 0; i < RX_LEN; i++)
check_sum += Usart_Mgr.RXDBuf[4 + i];
if (check_sum != Usart_Mgr.RXDBuf[4 + i]) {
Usart_Mgr.RXDState = RX_SUM_ERR;
return;
}
} else if (Usart_Mgr.RXDLen == 3) {
if (Usart_Mgr.RXDBuf[2] == 0xA0) {
f_uart_ack = 1;
}
}
switch (RX_CMD) {
case CMD_HAND: {
f_rf_hand_ok = 1;
break;
}
case CMD_24G_SUSPEND: {
f_goto_sleep = 1;
break;
}
case CMD_NEW_ADV: {
f_rf_new_adv_ok = 1;
break;
}
case CMD_RF_STS_SYSC: {
static uint8_t error_cnt = 0;
if (dev_info.link_mode == Usart_Mgr.RXDBuf[4]) {
error_cnt = 0;
dev_info.rf_state = Usart_Mgr.RXDBuf[5];
if ((dev_info.rf_state == RF_CONNECT) && ((Usart_Mgr.RXDBuf[6] & 0xf8) == 0)) {
dev_info.rf_led = Usart_Mgr.RXDBuf[6];
}
dev_info.rf_charge = Usart_Mgr.RXDBuf[7];
if (Usart_Mgr.RXDBuf[8] <= 100) dev_info.rf_battery = Usart_Mgr.RXDBuf[8];
if (dev_info.rf_charge & 0x01) dev_info.rf_battery = 100;
}
else {
if (dev_info.rf_state != RF_INVALID) {
if (error_cnt >= 5) {
error_cnt = 0;
f_send_channel = 1;
} else {
error_cnt++;
}
}
}
f_rf_sts_sysc_ok = 1;
break;
}
case CMD_READ_DATA: {
memcpy(func_tab, &Usart_Mgr.RXDBuf[4], 32);
if (func_tab[4] <= LINK_USB) {
dev_info.link_mode = func_tab[4];
}
if (func_tab[5] < LINK_USB) {
dev_info.rf_channel = func_tab[5];
}
if ((func_tab[6] <= LINK_BT_3) && (func_tab[6] >= LINK_BT_1)) {
dev_info.ble_channel = func_tab[6];
}
f_rf_read_data_ok = 1;
break;
}
}
Usart_Mgr.RXDLen = 0;
Usart_Mgr.RXDState = RX_Idle;
Usart_Mgr.RXDOverTime = 0;
}
}
/**
* @brief Uart send cmd.
* @param cmd: cmd.
* @param wait_ack: wait time for ack after sending.
* @param delayms: delay before sending.
*/
uint8_t uart_send_cmd(uint8_t cmd, uint8_t wait_ack, uint8_t delayms) {
wait_ms(delayms);
memset(&Usart_Mgr.TXDBuf[0], 0, UART_MAX_LEN);
Usart_Mgr.TXDBuf[0] = UART_HEAD;
Usart_Mgr.TXDBuf[1] = cmd;
Usart_Mgr.TXDBuf[2] = 0x00;
switch (cmd) {
case CMD_SLEEP: {
Usart_Mgr.TXDBuf[3] = 1;
Usart_Mgr.TXDBuf[4] = 0;
Usart_Mgr.TXDBuf[5] = 0;
break;
}
case CMD_HAND: {
Usart_Mgr.TXDBuf[3] = 1;
Usart_Mgr.TXDBuf[4] = 0;
Usart_Mgr.TXDBuf[5] = 0;
break;
}
case CMD_RF_STS_SYSC: {
Usart_Mgr.TXDBuf[3] = 1;
Usart_Mgr.TXDBuf[4] = dev_info.link_mode;
Usart_Mgr.TXDBuf[5] = dev_info.link_mode;
break;
}
case CMD_SET_LINK: {
dev_info.rf_state = RF_LINKING;
Usart_Mgr.TXDBuf[3] = 1;
Usart_Mgr.TXDBuf[4] = dev_info.link_mode;
Usart_Mgr.TXDBuf[5] = dev_info.link_mode;
rf_linking_time = 0;
disconnect_delay = 0xff;
break;
}
case CMD_NEW_ADV: {
dev_info.rf_state = RF_PAIRING;
Usart_Mgr.TXDBuf[3] = 2;
Usart_Mgr.TXDBuf[4] = dev_info.link_mode;
Usart_Mgr.TXDBuf[5] = 1;
Usart_Mgr.TXDBuf[6] = dev_info.link_mode + 1;
rf_linking_time = 0;
disconnect_delay = 0xff;
f_rf_new_adv_ok = 0;
break;
}
case CMD_CLR_DEVICE: {
Usart_Mgr.TXDBuf[3] = 1;
Usart_Mgr.TXDBuf[4] = 0;
Usart_Mgr.TXDBuf[5] = 0;
break;
}
case CMD_SET_CONFIG: {
Usart_Mgr.TXDBuf[3] = 1;
Usart_Mgr.TXDBuf[4] = POWER_DOWN_DELAY;
Usart_Mgr.TXDBuf[5] = POWER_DOWN_DELAY;
break;
}
case CMD_SET_NAME: {
Usart_Mgr.TXDBuf[3] = 17;
Usart_Mgr.TXDBuf[4] = 1;
Usart_Mgr.TXDBuf[5] = 15;
Usart_Mgr.TXDBuf[6] = 'N';
Usart_Mgr.TXDBuf[7] = 'u';
Usart_Mgr.TXDBuf[8] = 'P';
Usart_Mgr.TXDBuf[9] = 'h';
Usart_Mgr.TXDBuf[10] = 'y';
Usart_Mgr.TXDBuf[11] = ' ';
Usart_Mgr.TXDBuf[12] = 'A';
Usart_Mgr.TXDBuf[13] = 'i';
Usart_Mgr.TXDBuf[14] = 'r';
Usart_Mgr.TXDBuf[15] = '7';
Usart_Mgr.TXDBuf[16] = '5';
Usart_Mgr.TXDBuf[17] = ' ';
Usart_Mgr.TXDBuf[18] = 'V';
Usart_Mgr.TXDBuf[19] = '2';
Usart_Mgr.TXDBuf[20] = '-';
Usart_Mgr.TXDBuf[21] = get_checksum(Usart_Mgr.TXDBuf + 4, Usart_Mgr.TXDBuf[3]);
break;
}
case CMD_READ_DATA: {
Usart_Mgr.TXDBuf[3] = 2;
Usart_Mgr.TXDBuf[4] = 0x00;
Usart_Mgr.TXDBuf[5] = FUNC_VALID_LEN;
Usart_Mgr.TXDBuf[6] = FUNC_VALID_LEN;
break;
}
case CMD_RF_DFU: {
Usart_Mgr.TXDBuf[3] = 1;
Usart_Mgr.TXDBuf[4] = 0;
Usart_Mgr.TXDBuf[5] = 0;
break;
}
default:
break;
}
f_uart_ack = 0;
UART_Send_Bytes(Usart_Mgr.TXDBuf, Usart_Mgr.TXDBuf[3] + 5);
if (wait_ack) {
while (wait_ack--) {
wait_ms(1);
if (f_uart_ack) return TX_OK;
}
} else {
return TX_OK;
}
return TX_TIMEOUT;
}
/**
* @brief RF module state sync.
*/
void dev_sts_sync(void) {
static uint32_t interval_timer = 0;
static uint8_t link_state_temp = RF_DISCONNECT;
if (timer_elapsed32(interval_timer) < 200)
return;
else
interval_timer = timer_read32();
if (f_rf_reset) {
f_rf_reset = 0;
wait_ms(100);
gpio_write_pin_low(NRF_RESET_PIN);
wait_ms(50);
gpio_write_pin_high(NRF_RESET_PIN);
wait_ms(50);
}
else if (f_send_channel) {
f_send_channel = 0;
uart_send_cmd(CMD_SET_LINK, 10, 10);
}
if (dev_info.link_mode == LINK_USB) {
if (host_mode != HOST_USB_TYPE) {
host_mode = HOST_USB_TYPE;
host_set_driver(m_host_driver);
break_all_key();
}
rf_blink_cnt = 0;
}
else {
if (host_mode != HOST_RF_TYPE) {
host_mode = HOST_RF_TYPE;
break_all_key();
host_set_driver(&rf_host_driver);
}
if (dev_info.rf_state != RF_CONNECT) {
if (disconnect_delay >= 10) {
rf_blink_cnt = 3;
rf_link_show_time = 0;
link_state_temp = dev_info.rf_state;
} else {
disconnect_delay++;
}
}
else if (dev_info.rf_state == RF_CONNECT) {
rf_linking_time = 0;
disconnect_delay = 0;
rf_blink_cnt = 0;
if (link_state_temp != RF_CONNECT) {
link_state_temp = RF_CONNECT;
rf_link_show_time = 0;
}
}
}
uart_send_cmd(CMD_RF_STS_SYSC, 1, 1);
if (dev_info.link_mode != LINK_USB) {
if (++sync_lost >= 5) {
sync_lost = 0;
f_rf_reset = 1;
}
}
}
/**
* @brief Uart send bytes.
* @param Buffer data buf
* @param Length data length
*/
void UART_Send_Bytes(uint8_t *Buffer, uint32_t Length) {
gpio_write_pin_low(NRF_WAKEUP_PIN);
wait_us(50);
uart_transmit(Buffer, Length);
wait_us(50 + Length * 30);
gpio_write_pin_high(NRF_WAKEUP_PIN);
}
/**
* @brief get checksum.
* @param buf data buf
* @param len data length
*/
uint8_t get_checksum(uint8_t *buf, uint8_t len) {
uint8_t i;
uint8_t checksum = 0;
for (i = 0; i < len; i++)
checksum += *buf++;
checksum ^= UART_HEAD;
return checksum;
}
/**
* @brief Uart send report.
* @param report_type report_type
* @param report_buf report_buf
* @param report_size report_size
*/
void uart_send_report(uint8_t report_type, uint8_t *report_buf, uint8_t report_size) {
if (f_dial_sw_init_ok == 0) return;
if (dev_info.link_mode == LINK_USB) return;
if (dev_info.rf_state != RF_CONNECT) return;
Usart_Mgr.TXDBuf[0] = UART_HEAD;
Usart_Mgr.TXDBuf[1] = report_type;
Usart_Mgr.TXDBuf[2] = 0x01;
Usart_Mgr.TXDBuf[3] = report_size;
memcpy(&Usart_Mgr.TXDBuf[4], report_buf, report_size);
Usart_Mgr.TXDBuf[4 + report_size] = get_checksum(&Usart_Mgr.TXDBuf[4], report_size);
UART_Send_Bytes(&Usart_Mgr.TXDBuf[0], report_size + 5);
wait_us(200);
}
/**
* @brief Uart receives data and processes it after completion.
*/
void uart_receive_pro(void) {
static bool rcv_start = false;
// Receiving serial data from RF module
while (uart_available()) {
rcv_start = true;
if (Usart_Mgr.RXDLen >= UART_MAX_LEN) {
uart_read();
}
else {
Usart_Mgr.RXDBuf[Usart_Mgr.RXDLen++] = uart_read();
}
if (!uart_available()) {
wait_us(200);
}
}
// Processing received serial port protocol
if (rcv_start) {
rcv_start = false;
Usart_Mgr.RXDState = RX_Done;
RF_Protocol_Receive();
Usart_Mgr.RXDLen = 0;
}
}
/**
* @brief RF uart initial.
*/
void rf_uart_init(void) {
/* set uart buad as 460800 */
uart_init(460800);
/* Enable parity check */
USART1->CR1 &= ~((uint32_t)USART_CR1_UE);
USART1->CR1 |= USART_CR1_M0 | USART_CR1_PCE;
USART1->CR1 |= USART_CR1_UE;
/* set Rx and Tx pin pull up */
GPIOB->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7);
GPIOB->PUPDR |= (GPIO_PUPDR_PUPDR6_0 | GPIO_PUPDR_PUPDR7_0);
}
/**
* @brief RF module initial.
*/
void rf_device_init(void) {
uint8_t timeout = 0;
void uart_receive_pro(void);
timeout = 10;
f_rf_hand_ok = 0;
while (timeout--) {
uart_send_cmd(CMD_HAND, 0, 20);
wait_ms(5);
uart_receive_pro(); // receive data
uart_receive_pro(); // parsing data
if (f_rf_hand_ok) break;
}
timeout = 10;
f_rf_read_data_ok = 0;
while (timeout--) {
uart_send_cmd(CMD_READ_DATA, 0, 20);
wait_ms(5);
uart_receive_pro();
uart_receive_pro();
if (f_rf_read_data_ok) break;
}
timeout = 10;
f_rf_sts_sysc_ok = 0;
while (timeout--) {
uart_send_cmd(CMD_RF_STS_SYSC, 0, 20);
wait_ms(5);
uart_receive_pro();
uart_receive_pro();
if (f_rf_sts_sysc_ok) break;
}
uart_send_cmd(CMD_SET_NAME, 10, 20);
}

View File

@ -0,0 +1,65 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 "host_driver.h"
#include "rf_driver.h"
#include "host.h"
#include "kb_util.h"
/* Variable declaration */
extern DEV_INFO_STRUCT dev_info;
/* Host driver */
static uint8_t rf_keyboard_leds(void);
static void rf_send_keyboard(report_keyboard_t *report);
static void rf_send_nkro(report_nkro_t *report);
static void rf_send_mouse(report_mouse_t *report);
static void rf_send_extra(report_extra_t *report);
host_driver_t rf_host_driver = {rf_keyboard_leds, rf_send_keyboard, rf_send_nkro, rf_send_mouse, rf_send_extra};
/* defined in rf.c */
extern void uart_send_report_keyboard(report_keyboard_t *report);
extern void uart_send_report_nkro(report_nkro_t *report);
extern void uart_send_mouse_report(report_mouse_t *report);
extern void uart_send_consumer_report(report_extra_t *report);
extern void uart_send_system_report(report_extra_t *report);
static uint8_t rf_keyboard_leds(void) {
return dev_info.rf_led;
}
static void rf_send_keyboard(report_keyboard_t *report) {
keyboard_protocol = 1;
uart_send_report_keyboard(report);
}
static void rf_send_nkro(report_nkro_t *report) {
keyboard_protocol = 1;
uart_send_report_nkro(report);
}
static void rf_send_mouse(report_mouse_t *report) {
uart_send_mouse_report(report);
}
static void rf_send_extra(report_extra_t *report) {
if (report->report_id == REPORT_ID_CONSUMER) {
uart_send_consumer_report(report);
} else if (report->report_id == REPORT_ID_SYSTEM) {
uart_send_system_report(report);
}
}

View File

@ -0,0 +1,20 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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
extern host_driver_t rf_host_driver;

View File

@ -0,0 +1,3 @@
SRC += side.c rf.c sleep.c rf_driver.c kb_util.c side_driver.c
UART_DRIVER_REQUIRED = yes

View File

@ -0,0 +1,876 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 "kb_util.h"
#include "ansi.h"
#include "side_table.h"
#include "ws2812.h"
#define SIDE_BRIGHT_MAX 4
#define SIDE_SPEED_MAX 4
#define SIDE_COLOUR_MAX 8
#define SIDE_LINE 6
#define SIDE_LED_NUM 12
#define RF_LED_LINK_PERIOD 500
#define RF_LED_PAIR_PERIOD 250
/* side rgb mode */
enum {
SIDE_WAVE = 0,
SIDE_MIX,
SIDE_STATIC,
SIDE_BREATH,
SIDE_OFF,
};
uint8_t side_mode = 0;
uint8_t side_light = 3;
uint8_t side_speed = 2;
uint8_t side_rgb = 1;
uint8_t side_colour = 0;
uint8_t side_play_point = 0;
uint8_t side_play_cnt = 0;
uint32_t side_play_timer = 0;
uint8_t r_temp, g_temp, b_temp;
rgb_led_t side_leds[SIDE_LED_NUM] = {0};
const uint8_t side_speed_table[5][5] = {
[SIDE_WAVE] = {10, 14, 20, 28, 38}, //
[SIDE_MIX] = {10, 14, 20, 28, 38}, //
[SIDE_STATIC] = {50, 50, 50, 50, 50}, //
[SIDE_BREATH] = {10, 14, 20, 28, 38}, //
[SIDE_OFF] = {50, 50, 50, 50, 50}, //
};
const uint8_t side_light_table[6] = {
0, //
22, //
34, //
55, //
79, //
106, //
};
const uint8_t side_led_index_tab[SIDE_LINE][2] = {
{5, 6}, //
{4, 7}, //
{3, 8}, //
{2, 9}, //
{1, 10}, //
{0, 11}, //
};
extern DEV_INFO_STRUCT dev_info;
extern kb_config_t kb_config;
extern uint8_t rf_blink_cnt;
extern uint16_t rf_link_show_time;
extern bool f_bat_hold;
extern bool f_sys_show;
extern bool f_sleep_show;
void side_ws2812_setleds(rgb_led_t *ledarray, uint16_t leds);
void rgb_matrix_update_pwm_buffers(void);
/**
* @brief side leds set color value.
* @param index: index of side_leds[].
* @param ...
*/
void side_rgb_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
side_leds[index].r = red;
side_leds[index].g = green;
side_leds[index].b = blue;
}
/**
* @brief refresh side leds.
*/
void side_rgb_refresh(void) {
side_ws2812_setleds(side_leds, SIDE_LED_NUM);
}
/**
* @brief Adjusting the brightness of side lights.
* @param dir: 0 - decrease, 1 - increase.
* @note save to eeprom.
*/
void side_light_control(uint8_t dir) {
if (dir) {
if (side_light > SIDE_BRIGHT_MAX) {
return;
} else
side_light++;
} else {
if (side_light == 0) {
return;
} else
side_light--;
}
kb_config.ee_side_light = side_light;
eeconfig_update_kb_datablock(&kb_config);
}
/**
* @brief Adjusting the speed of side lights.
* @param dir: 0 - decrease, 1 - increase.
* @note save to eeprom.
*/
void side_speed_control(uint8_t dir) {
if ((side_speed) > SIDE_SPEED_MAX) (side_speed) = SIDE_SPEED_MAX / 2;
if (dir) {
if ((side_speed)) side_speed--;
} else {
if ((side_speed) < SIDE_SPEED_MAX) side_speed++;
}
kb_config.ee_side_speed = side_speed;
eeconfig_update_kb_datablock(&kb_config);
}
/**
* @brief Switch to the next color of side lights.
* @param dir: 0 - prev, 1 - next.
* @note save to eeprom.
*/
void side_colour_control(uint8_t dir) {
if (side_mode != SIDE_WAVE) {
if (side_rgb) {
side_rgb = 0;
side_colour = 0;
}
}
if (dir) {
if (side_rgb) {
side_rgb = 0;
side_colour = 0;
} else {
side_colour++;
if (side_colour >= SIDE_COLOUR_MAX) {
side_rgb = 1;
side_colour = 0;
}
}
} else {
if (side_rgb) {
side_rgb = 0;
side_colour = SIDE_COLOUR_MAX - 1;
} else {
side_colour--;
if (side_colour >= SIDE_COLOUR_MAX) {
side_rgb = 1;
side_colour = 0;
}
}
}
kb_config.ee_side_rgb = side_rgb;
kb_config.ee_side_colour = side_colour;
eeconfig_update_kb_datablock(&kb_config);
}
/**
* @brief Change the color mode of side lights.
* @param dir: 0 - prev, 1 - next.
* @note save to eeprom.
*/
void side_mode_control(uint8_t dir) {
if (dir) {
side_mode++;
if (side_mode > SIDE_OFF) {
side_mode = 0;
}
} else {
if (side_mode > 0) {
side_mode--;
} else {
side_mode = SIDE_OFF;
}
}
side_play_point = 0;
kb_config.ee_side_mode = side_mode;
eeconfig_update_kb_datablock(&kb_config);
}
/**
* @brief set left side leds.
* @param ...
*/
void set_left_rgb(uint8_t r, uint8_t g, uint8_t b) {
for (int i = 0; i < 6; i++)
side_rgb_set_color(i, r >> 2, g >> 2, b >> 2);
}
/**
* @brief set right side leds.
* @param ...
*/
void set_right_rgb(uint8_t r, uint8_t g, uint8_t b) {
for (int i = 6; i < 12; i++)
side_rgb_set_color(i, r >> 2, g >> 2, b >> 2);
}
/**
* @brief set left side leds.
*/
void sys_sw_led_show(void) {
static uint32_t sys_show_timer = 0;
static bool sys_show_flag = false;
if (f_sys_show) {
f_sys_show = false;
sys_show_timer = timer_read32();
sys_show_flag = true;
}
if (sys_show_flag) {
if (dev_info.sys_sw_state == SYS_SW_MAC) {
r_temp = 0x80;
g_temp = 0x80;
b_temp = 0x80;
} else {
r_temp = 0x00;
g_temp = 0x00;
b_temp = 0x80;
}
if ((timer_elapsed32(sys_show_timer) / 500) % 2 == 0) {
set_right_rgb(r_temp, g_temp, b_temp);
} else {
set_right_rgb(0x00, 0x00, 0x00);
}
if (timer_elapsed32(sys_show_timer) >= 3000) {
sys_show_flag = false;
}
}
}
/**
* @brief sleep_sw_led_show.
*/
void sleep_sw_led_show(void) {
static uint32_t sleep_show_timer = 0;
static bool sleep_show_flag = false;
if (f_sleep_show) {
f_sleep_show = false;
sleep_show_timer = timer_read32();
sleep_show_flag = true;
}
if (sleep_show_flag) {
if (kb_config.sleep_enable) {
r_temp = 0x00;
g_temp = 0x80;
b_temp = 0x00;
} else {
r_temp = 0x80;
g_temp = 0x00;
b_temp = 0x00;
}
if ((timer_elapsed32(sleep_show_timer) / 500) % 2 == 0) {
set_right_rgb(r_temp, g_temp, b_temp);
} else {
set_right_rgb(0x00, 0x00, 0x00);
}
if (timer_elapsed32(sleep_show_timer) >= 3000) {
sleep_show_flag = false;
}
}
}
/**
* @brief sys_led_show.
*/
void sys_led_show(void) {
if (dev_info.link_mode == LINK_USB) {
if (host_keyboard_led_state().caps_lock) {
set_left_rgb(0X00, 0x80, 0x80);
}
}
else {
if (dev_info.rf_led & 0x02) {
set_left_rgb(0X00, 0x80, 0x80);
}
}
}
/**
* @brief light_point_playing.
* @param trend:
* @param step:
* @param len:
* @param point:
*/
static void light_point_playing(uint8_t trend, uint8_t step, uint8_t len, uint8_t *point) {
if (trend) {
*point += step;
if (*point >= len) *point -= len;
} else {
*point -= step;
if (*point >= len) *point = len - (255 - *point) - 1;
}
}
/**
* @brief count_rgb_light.
* @param light_temp:
*/
static void count_rgb_light(uint8_t light_temp) {
uint16_t temp;
temp = (light_temp)*r_temp + r_temp;
r_temp = temp >> 8;
temp = (light_temp)*g_temp + g_temp;
g_temp = temp >> 8;
temp = (light_temp)*b_temp + b_temp;
b_temp = temp >> 8;
}
/**
* @brief side_wave_mode_show.
*/
static void side_wave_mode_show(void) {
uint8_t play_index;
if (side_play_cnt <= side_speed_table[side_mode][side_speed])
return;
else
side_play_cnt -= side_speed_table[side_mode][side_speed];
if (side_play_cnt > 20) side_play_cnt = 0;
if (side_rgb)
light_point_playing(0, 3, FLOW_COLOUR_TAB_LEN, &side_play_point);
else
light_point_playing(0, 2, WAVE_TAB_LEN, &side_play_point);
play_index = side_play_point;
for (int i = 0; i < SIDE_LINE; i++) {
if (side_rgb) {
r_temp = flow_rainbow_colour_tab[play_index][0];
g_temp = flow_rainbow_colour_tab[play_index][1];
b_temp = flow_rainbow_colour_tab[play_index][2];
light_point_playing(1, 24, FLOW_COLOUR_TAB_LEN, &play_index);
} else {
r_temp = colour_lib[side_colour][0];
g_temp = colour_lib[side_colour][1];
b_temp = colour_lib[side_colour][2];
light_point_playing(1, 12, WAVE_TAB_LEN, &play_index);
count_rgb_light(wave_data_tab[play_index]);
}
count_rgb_light(side_light_table[side_light]);
for (int j = 0; j < 2; j++) {
side_rgb_set_color(side_led_index_tab[i][j], r_temp >> 2, g_temp >> 2, b_temp >> 2);
}
}
}
/**
* @brief side_spectrum_mode_show.
*/
static void side_spectrum_mode_show(void) {
if (side_play_cnt <= side_speed_table[side_mode][side_speed])
return;
else
side_play_cnt -= side_speed_table[side_mode][side_speed];
if (side_play_cnt > 20) side_play_cnt = 0;
light_point_playing(1, 1, FLOW_COLOUR_TAB_LEN, &side_play_point);
r_temp = flow_rainbow_colour_tab[side_play_point][0];
g_temp = flow_rainbow_colour_tab[side_play_point][1];
b_temp = flow_rainbow_colour_tab[side_play_point][2];
count_rgb_light(side_light_table[side_light]);
for (int i = 0; i < SIDE_LINE; i++) {
for (int j = 0; j < 2; j++) {
side_rgb_set_color(side_led_index_tab[i][j], r_temp >> 2, g_temp >> 2, b_temp >> 2);
}
}
}
/**
* @brief side_breathe_mode_show.
*/
static void side_breathe_mode_show(void) {
static uint8_t play_point = 0;
if (side_play_cnt <= side_speed_table[side_mode][side_speed])
return;
else
side_play_cnt -= side_speed_table[side_mode][side_speed];
if (side_play_cnt > 20) side_play_cnt = 0;
light_point_playing(0, 1, BREATHE_TAB_LEN, &play_point);
if (0) {
if (play_point == 0) {
if (++side_play_point >= SIDE_COLOUR_MAX) side_play_point = 0;
}
r_temp = colour_lib[side_play_point][0];
g_temp = colour_lib[side_play_point][1];
b_temp = colour_lib[side_play_point][2];
} else {
r_temp = colour_lib[side_colour][0];
g_temp = colour_lib[side_colour][1];
b_temp = colour_lib[side_colour][2];
}
count_rgb_light(breathe_data_tab[play_point]);
count_rgb_light(side_light_table[side_light]);
for (int i = 0; i < SIDE_LINE; i++) {
for (int j = 0; j < 2; j++) {
side_rgb_set_color(side_led_index_tab[i][j], r_temp >> 2, g_temp >> 2, b_temp >> 2);
}
}
}
/**
* @brief side_static_mode_show.
*/
static void side_static_mode_show(void) {
uint8_t play_index;
if (side_play_cnt <= side_speed_table[side_mode][side_speed])
return;
else
side_play_cnt -= side_speed_table[side_mode][side_speed];
if (side_play_cnt > 20) side_play_cnt = 0;
if (side_play_point >= SIDE_COLOUR_MAX) side_play_point = 0;
for (int i = 0; i < SIDE_LINE; i++) {
if (0) {
r_temp = flow_rainbow_colour_tab[16 * i][0];
g_temp = flow_rainbow_colour_tab[16 * i][1];
b_temp = flow_rainbow_colour_tab[16 * i][2];
light_point_playing(0, 24, FLOW_COLOUR_TAB_LEN, &play_index);
} else {
r_temp = colour_lib[side_colour][0];
g_temp = colour_lib[side_colour][1];
b_temp = colour_lib[side_colour][2];
}
count_rgb_light(side_light_table[side_light]);
for (int j = 0; j < 2; j++) {
side_rgb_set_color(side_led_index_tab[i][j], r_temp >> 2, g_temp >> 2, b_temp >> 2);
}
}
}
/**
* @brief side_off_mode_show.
*/
static void side_off_mode_show(void) {
if (side_play_cnt <= side_speed_table[side_mode][side_speed])
return;
else
side_play_cnt -= side_speed_table[side_mode][side_speed];
if (side_play_cnt > 20) side_play_cnt = 0;
r_temp = 0x00;
g_temp = 0x00;
b_temp = 0x00;
for (int i = 0; i < SIDE_LINE; i++) {
for (int j = 0; j < 2; j++) {
side_rgb_set_color(side_led_index_tab[i][j], r_temp >> 2, g_temp >> 2, b_temp >> 2);
}
}
}
/**
* @brief rf_led_show.
*/
void rf_led_show(void) {
static uint32_t rf_blink_timer = 0;
uint16_t rf_blink_priod = 0;
if (rf_blink_cnt || (rf_link_show_time < RF_LINK_SHOW_TIME)) {
if (dev_info.link_mode == LINK_RF_24) {
r_temp = 0x00;
g_temp = 0x80;
b_temp = 0x00;
} else if (dev_info.link_mode == LINK_USB) {
r_temp = 0x80;
g_temp = 0x80;
b_temp = 0x00;
} else {
r_temp = 0x00;
g_temp = 0x00;
b_temp = 0x80;
}
} else {
rf_blink_timer = timer_read32();
return;
}
if (rf_blink_cnt) {
if (dev_info.rf_state == RF_PAIRING)
rf_blink_priod = RF_LED_PAIR_PERIOD;
else
rf_blink_priod = RF_LED_LINK_PERIOD;
if (timer_elapsed32(rf_blink_timer) > (rf_blink_priod >> 1)) {
r_temp = 0x00;
g_temp = 0x00;
b_temp = 0x00;
}
if (timer_elapsed32(rf_blink_timer) >= rf_blink_priod) {
rf_blink_cnt--;
rf_blink_timer = timer_read32();
}
}
set_left_rgb(r_temp, g_temp, b_temp);
}
/**
* @brief bat_num_led.
*/
void bat_num_led(uint8_t bat_percent)
{
uint8_t r, g, b;
// set color
if (bat_percent <= 15) {
r = 0xff; g = 0x00; b = 0x00;
}
else if (bat_percent <= 50) {
r = 0xff; g = 0x40; b = 0x00;
}
else if (bat_percent <= 80) {
r = 0xff; g = 0xff; b = 0x00;
}
else {
r = 0x00; g = 0xff; b = 0x00;
}
// set percent
if (bat_percent >= 1) rgb_matrix_set_color(29, r, g, b);
if (bat_percent > 10) rgb_matrix_set_color(28, r, g, b);
if (bat_percent > 20) rgb_matrix_set_color(27, r, g, b);
if (bat_percent > 30) rgb_matrix_set_color(26, r, g, b);
if (bat_percent > 40) rgb_matrix_set_color(25, r, g, b);
if (bat_percent > 50) rgb_matrix_set_color(24, r, g, b);
if (bat_percent > 60) rgb_matrix_set_color(23, r, g, b);
if (bat_percent > 70) rgb_matrix_set_color(22, r, g, b);
if (bat_percent > 80) rgb_matrix_set_color(21, r, g, b);
if (bat_percent > 90) rgb_matrix_set_color(20, r, g, b);
}
void num_led_show(void)
{
static uint8_t num_bat_temp = 0;
num_bat_temp = dev_info.rf_battery;
bat_num_led(num_bat_temp);
}
void bat_led_close(void)
{
for(int i=20; i<=29; i++) {
rgb_matrix_set_color(i,0,0,0);
}
}
/**
* @brief bat_percent_led.
*/
void bat_percent_led(uint8_t bat_percent) {
uint8_t bat_end_led = 0;
uint8_t bat_r, bat_g, bat_b;
if (bat_percent <= 15) {
bat_end_led = 0;
bat_r = 0x80, bat_g = 0, bat_b = 0;
} else if (bat_percent <= 20) {
bat_end_led = 1;
bat_r = 0x80, bat_g = 0x40, bat_b = 0;
} else if (bat_percent <= 40) {
bat_end_led = 2;
bat_r = 0x80, bat_g = 0x40, bat_b = 0;
} else if (bat_percent <= 60) {
bat_end_led = 3;
bat_r = 0x80, bat_g = 0x40, bat_b = 0;
} else if (bat_percent <= 80) {
bat_end_led = 4;
bat_r = 0x80, bat_g = 0x40, bat_b = 0;
} else if (bat_percent <= 95) {
bat_end_led = 5;
bat_r = 0x80, bat_g = 0x40, bat_b = 0;
} else {
bat_end_led = 5;
bat_r = 0, bat_g = 0x80, bat_b = 0;
}
uint8_t i = 0;
for (; i <= bat_end_led; i++)
side_rgb_set_color(11 - i, bat_r >> 2, bat_g >> 2, bat_b >> 2);
for (; i < 6; i++)
side_rgb_set_color(11 - i, 0, 0, 0);
}
/**
* @brief bat_led_show.
*/
void bat_led_show(void) {
static bool bat_show_flag = 1;
static bool bat_show_breath = 0;
static bool f_init = 1;
static uint8_t play_point = 0;
static uint32_t bat_play_timer = 0;
static uint32_t bat_show_time = 0;
static uint32_t bat_sts_debounce = 0;
static uint32_t bat_per_debounce = 0;
static uint8_t charge_state = 0;
static uint8_t bat_percent = 0;
if (f_init) {
f_init = 0;
bat_show_time = timer_read32();
charge_state = dev_info.rf_charge;
bat_percent = dev_info.rf_battery;
}
if (charge_state != dev_info.rf_charge) {
if (timer_elapsed32(bat_sts_debounce) > 1000) {
if (((charge_state & 0x01) == 0) && ((dev_info.rf_charge & 0x01) != 0)) {
bat_show_flag = true;
bat_show_breath = true;
bat_show_time = timer_read32();
}
charge_state = dev_info.rf_charge;
}
} else {
bat_sts_debounce = timer_read32();
if (timer_elapsed32(bat_show_time) > 5000) {
bat_show_flag = false;
bat_show_breath = false;
}
if (charge_state == 0x03) {
bat_show_breath = true;
} else if (charge_state & 0x01) {
dev_info.rf_battery = 100;
}
}
if (bat_percent != dev_info.rf_battery) {
if (timer_elapsed32(bat_per_debounce) > 1000) {
bat_percent = dev_info.rf_battery;
}
} else {
bat_per_debounce = timer_read32();
if (bat_percent < 15) {
bat_show_flag = true;
bat_show_time = timer_read32();
}
}
if (f_bat_hold || bat_show_flag) {
if (bat_show_breath) {
if (timer_elapsed32(bat_play_timer) > 10) {
bat_play_timer = timer_read32();
light_point_playing(0, 1, BREATHE_TAB_LEN, &play_point);
}
r_temp = 0x80;
g_temp = 0x40;
b_temp = 0x00;
count_rgb_light(breathe_data_tab[play_point]);
set_right_rgb(r_temp, g_temp, b_temp);
} else {
bat_percent_led(bat_percent);
}
}
}
/**
* @brief device_reset_show.
*/
void device_reset_show(void) {
gpio_write_pin_high(DC_BOOST_PIN);
gpio_set_pin_output_push_pull(DRIVER_SIDE_CS_PIN);
gpio_set_pin_output_push_pull(DRIVER_LED_CS_PIN);
gpio_write_pin_low(DRIVER_SIDE_CS_PIN);
gpio_write_pin_low(DRIVER_LED_CS_PIN);
for (int blink_cnt = 0; blink_cnt < 3; blink_cnt++) {
rgb_matrix_set_color_all(0x10, 0x10, 0x10);
set_left_rgb(0x40, 0x40, 0x40);
set_right_rgb(0x40, 0x40, 0x40);
rgb_matrix_update_pwm_buffers();
side_rgb_refresh();
wait_ms(200);
rgb_matrix_set_color_all(0x00, 0x00, 0x00);
set_left_rgb(0x00, 0x00, 0x00);
set_right_rgb(0x00, 0x00, 0x00);
rgb_matrix_update_pwm_buffers();
side_rgb_refresh();
wait_ms(200);
}
}
/**
* @brief device_reset_init.
*/
void device_reset_init(void) {
side_mode = 0;
side_light = 3;
side_speed = 2;
side_rgb = 1;
side_colour = 0;
side_play_point = 0;
side_play_cnt = 0;
side_play_timer = timer_read32();
f_bat_hold = false;
rgb_matrix_enable();
rgb_matrix_mode(RGB_MATRIX_CYCLE_LEFT_RIGHT);
rgb_matrix_set_speed(255 - RGB_MATRIX_SPD_STEP * 2);
rgb_matrix_sethsv(255, 255, RGB_MATRIX_MAXIMUM_BRIGHTNESS - RGB_MATRIX_VAL_STEP * 2);
kb_config.default_brightness_flag = 0xA5;
kb_config.ee_side_mode = side_mode;
kb_config.ee_side_light = side_light;
kb_config.ee_side_speed = side_speed;
kb_config.ee_side_rgb = side_rgb;
kb_config.ee_side_colour = side_colour;
kb_config.sleep_enable = true;
eeconfig_update_kb_datablock(&kb_config);
}
/**
* RGB test
*/
void rgb_test_show(void)
{
// open power control
gpio_write_pin_high(DC_BOOST_PIN);
gpio_set_pin_output_push_pull(DRIVER_LED_CS_PIN);
gpio_write_pin_low(DRIVER_LED_CS_PIN);
gpio_set_pin_output_push_pull(DRIVER_SIDE_CS_PIN);
gpio_write_pin_low(DRIVER_SIDE_CS_PIN);
// set test color
rgb_matrix_set_color_all(0xFF, 0x00, 0x00);
rgb_matrix_update_pwm_buffers();
set_left_rgb(0xff, 0x00, 0x00);
set_right_rgb(0xff, 0x00, 0x00);
side_rgb_refresh();
wait_ms(500);
rgb_matrix_set_color_all(0x00, 0xFF, 0x00);
rgb_matrix_update_pwm_buffers();
set_left_rgb(0x00, 0xFF, 0x00);
set_right_rgb(0x00, 0xFF, 0x00);
side_rgb_refresh();
wait_ms(500);
rgb_matrix_set_color_all(0x00, 0x00, 0xFF);
rgb_matrix_update_pwm_buffers();
set_left_rgb(0x00, 0x00, 0xFF);
set_right_rgb(0x00, 0x00, 0xFF);
side_rgb_refresh();
wait_ms(500);
rgb_matrix_set_color_all(0x80, 0x80, 0x80);
rgb_matrix_update_pwm_buffers();
set_left_rgb(0x80, 0x80, 0x80);
set_right_rgb(0x80, 0x80, 0x80);
side_rgb_refresh();
wait_ms(500);
rgb_matrix_set_color_all(0x80, 0x80, 0x00);
rgb_matrix_update_pwm_buffers();
set_left_rgb(0x80, 0x80, 0x00);
set_right_rgb(0x80, 0x80, 0x00);
side_rgb_refresh();
wait_ms(500);
rgb_matrix_set_color_all(0x80, 0x00, 0x80);
rgb_matrix_update_pwm_buffers();
set_left_rgb(0x80, 0x00, 0x80);
set_right_rgb(0x80, 0x00, 0x80);
side_rgb_refresh();
wait_ms(500);
rgb_matrix_set_color_all(0x00, 0x80, 0x80);
rgb_matrix_update_pwm_buffers();
set_left_rgb(0x00, 0x80, 0x80);
set_right_rgb(0x00, 0x80, 0x80);
side_rgb_refresh();
wait_ms(500);
}
/**
* @brief side_led_show.
*/
void side_led_show(void) {
static uint32_t side_refresh_time = 0;
side_play_cnt += timer_elapsed32(side_play_timer);
side_play_timer = timer_read32();
switch (side_mode) {
case SIDE_WAVE:
side_wave_mode_show();
break;
case SIDE_MIX:
side_spectrum_mode_show();
break;
case SIDE_BREATH:
side_breathe_mode_show();
break;
case SIDE_STATIC:
side_static_mode_show();
break;
case SIDE_OFF:
side_off_mode_show();
break;
}
bat_led_show();
sleep_sw_led_show();
sys_sw_led_show();
sys_led_show();
rf_led_show();
if (timer_elapsed32(side_refresh_time) > 30) {
side_refresh_time = timer_read32();
side_rgb_refresh();
}
}

View File

@ -0,0 +1,106 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 <ch.h>
#include <hal.h>
#include "quantum.h"
#include "ws2812.h"
/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */
#ifndef NOP_FUDGE
#if defined(STM32F0XX) || defined(STM32F1XX) || defined(GD32VF103) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX) || defined(WB32F3G71xx) || defined(WB32FQ95xx)
#define NOP_FUDGE 0.4
#else
#error("NOP_FUDGE configuration required")
#define NOP_FUDGE 1 // this just pleases the compiler so the above error is easier to spot
#endif
#endif
// Push Pull or Open Drain Configuration
// Default Push Pull
#ifndef WS2812_EXTERNAL_PULLUP
#define WS2812_OUTPUT_MODE PAL_MODE_OUTPUT_PUSHPULL
#else
#define WS2812_OUTPUT_MODE PAL_MODE_OUTPUT_OPENDRAIN
#endif
// The reset gap can be 6000 ns, but depending on the LED strip it may have to be increased
// to values like 600000 ns. If it is too small, the pixels will show nothing most of the time.
#ifndef WS2812_RES
#define WS2812_RES (1000 * WS2812_TRST_US) // Width of the low gap between bits to cause a frame to latch
#endif
#define NUMBER_NOPS 6
#define CYCLES_PER_SEC (CPU_CLOCK / NUMBER_NOPS * NOP_FUDGE)
#define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives
#define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC)
#define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE)
#define wait_ns(x) \
do { \
for (int i = 0; i < NS_TO_CYCLES(x); i++) { \
__asm__ volatile( \
"nop\n\t" \
"nop\n\t" \
"nop\n\t" \
"nop\n\t" \
"nop\n\t" \
"nop\n\t"); \
} \
} while (0)
void side_sendByte(uint8_t byte)
{
// WS2812 protocol wants most significant bits first
for (unsigned char bit = 0; bit < 8; bit++) {
bool is_one = byte & (1 << (7 - bit));
// using something like wait_ns(is_one ? T1L : T0L) here throws off timings
if (is_one) {
// 1
gpio_write_pin_high(DRIVER_SIDE_PIN);
wait_ns(WS2812_T1H);
gpio_write_pin_low(DRIVER_SIDE_PIN);
wait_ns(WS2812_T1L);
} else {
// 0
gpio_write_pin_high(DRIVER_SIDE_PIN);
wait_ns(WS2812_T0H);
gpio_write_pin_low(DRIVER_SIDE_PIN);
wait_ns(WS2812_T0L);
}
}
}
// Setleds for standard RGB
void side_ws2812_setleds(rgb_led_t *ledarray, uint16_t leds)
{
// this code is very time dependent, so we need to disable interrupts
chSysLock();
for (uint8_t i = 0; i < leds; i++) {
// WS2812 protocol dictates grb order
side_sendByte(ledarray[i].g);
side_sendByte(ledarray[i].r);
side_sendByte(ledarray[i].b);
}
wait_ns(WS2812_RES);
chSysUnlock();
}

View File

@ -0,0 +1,575 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 LIGHT_TAB_LEN 101
#define WAVE_TAB_LEN 112
#define BREATHE_TAB_LEN 128
#define FLOW_COLOUR_TAB_LEN 224
const uint8_t light_value_tab[256] =
{
0, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 36, 37, 39, 40, 42, 43,
45, 47, 49, 51, 53, 55, 57, 59,
61, 63, 65, 67, 69, 71, 73, 75,
77, 79, 81, 83, 85, 87, 89, 91,
94, 96, 99, 101, 104, 106, 109, 111,
114, 116, 119, 121, 124, 126, 129, 131,
134, 137, 140, 143, 146, 149, 152, 155,
158, 161, 164, 167, 170, 173, 176, 179,
182, 185, 188, 191, 194, 197, 200, 203,
206, 209, 213, 216, 220, 223, 227, 230,
234, 237, 241, 245, 248, 251, 255, 255,
255,
};
const uint8_t breathe_data_tab[256]=
{
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 12, 14, 16, 18, 20,
22, 24, 27, 30, 33, 36, 39, 42,
45, 49, 53, 57, 61, 65, 69, 73,
77, 81, 85, 89, 94, 99, 104, 109,
114, 119, 124, 129, 134, 140, 146, 152,
158, 164, 170, 176, 182, 188, 194, 200,
206, 213, 220, 227, 234, 241, 248, 255,
255, 248, 241, 234, 227, 220, 213, 206,
200, 194, 188, 182, 176, 170, 164, 158,
152, 146, 140, 134, 129, 124, 119, 114,
109, 104, 99, 94, 89, 85, 81, 77,
73, 69, 65, 61, 57, 53, 49, 45,
42, 39, 36, 33, 30, 27, 24, 22,
20, 18, 16, 14, 12, 10, 9, 8,
7, 6, 5, 4, 3, 2, 1, 0,
};
const uint8_t wave_data_tab[256]=
{
22, 23, 24, 25, 27, 28, 30, 31,
33, 34, 36, 37, 39, 40, 42, 43,
45, 47, 49, 51, 53, 55, 57, 59,
61, 63, 65, 76, 69, 71, 73, 75,
77, 81, 85, 89, 94, 99, 104, 109,
114, 119, 124, 129, 134, 140, 146, 152,
158, 164, 170, 176, 182, 188, 194, 200,
206, 213, 220, 227, 234, 241, 248, 255,
255, 248, 241, 234, 227, 220, 213, 206,
200, 194, 188, 182, 176, 170, 164, 158,
152, 146, 140, 134, 129, 124, 119, 114,
109, 104, 99, 94, 89, 85, 81, 77,
73, 69, 65, 61, 57, 53, 49, 45,
42, 39, 36, 33, 30, 27, 24, 22,
};
const uint8_t flow_rainbow_colour_tab[512][3]=
{
{255, 8, 8},
{255, 8, 8},
{255, 8, 8},
{255, 8, 8},
{255, 10, 8},
{255, 14, 8},
{255, 18, 8},
{255, 22, 8},
{255, 26, 8},
{255, 32, 8},
{255, 38, 8},
{255, 44, 8},
{255, 50, 8},
{255, 57, 8},
{255, 65, 8},
{255, 73, 8},
{255, 81, 8},
{255, 89, 8},
{255, 99, 8},
{255, 109, 8},
{255, 119, 8},
{255, 129, 8},
{255, 140, 8},
{255, 152, 8},
{255, 164, 8},
{255, 176, 8},
{255, 188, 8},
{255, 200, 8},
{255, 213, 8},
{255, 227, 8},
{255, 241, 8},
{255, 255, 8},
{248, 255, 8},
{234, 255, 8},
{220, 255, 8},
{206, 255, 8},
{194, 255, 8},
{182, 255, 8},
{170, 255, 8},
{158, 255, 8},
{146, 255, 8},
{134, 255, 8},
{124, 255, 8},
{114, 255, 8},
{104, 255, 8},
{94, 255, 8},
{85, 255, 8},
{77, 255, 8},
{69, 255, 8},
{61, 255, 8},
{53, 255, 8},
{47, 255, 8},
{41, 255, 8},
{35, 255, 8},
{29, 255, 8},
{24, 255, 8},
{20, 255, 8},
{16, 255, 8},
{12, 255, 8},
{8, 255, 8},
{8, 255, 8},
{8, 255, 8},
{8, 255, 8},
{8, 255, 8},
{8, 255, 8, },
{8, 255, 8, },
{8, 255, 8, },
{8, 255, 8, },
{8, 255, 10, },
{8, 255, 14, },
{8, 255, 18, },
{8, 255, 22, },
{8, 255, 26, },
{8, 255, 32, },
{8, 255, 38, },
{8, 255, 44, },
{8, 255, 50, },
{8, 255, 57, },
{8, 255, 65, },
{8, 255, 73, },
{8, 255, 81, },
{8, 255, 89, },
{8, 255, 99, },
{8, 255, 109,},
{8, 255, 119,},
{8, 255, 129,},
{8, 255, 140,},
{8, 255, 152,},
{8, 255, 164,},
{8, 255, 176,},
{8, 255, 188,},
{8, 255, 200,},
{8, 255, 213,},
{8, 255, 227,},
{8, 255, 241,},
{8, 255, 255,},
{8, 248, 255,},
{8, 234, 255,},
{8, 220, 255,},
{8, 206, 255,},
{8, 194, 255,},
{8, 182, 255,},
{8, 170, 255,},
{8, 158, 255,},
{8, 146, 255,},
{8, 134, 255,},
{8, 124, 255,},
{8, 114, 255,},
{8, 104, 255,},
{8, 94, 255,},
{8, 85, 255,},
{8, 77, 255,},
{8, 69, 255,},
{8, 61, 255,},
{8, 53, 255,},
{8, 47, 255,},
{8, 41, 255,},
{8, 35, 255,},
{8, 29, 255,},
{8, 24, 255,},
{8, 20, 255,},
{8, 16, 255,},
{8, 12, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{10, 8, 255,},
{14, 8, 255,},
{18, 8, 255,},
{22, 8, 255,},
{26, 8, 255,},
{32, 8, 255,},
{38, 8, 255,},
{44, 8, 255,},
{50, 8, 255,},
{57, 8, 255,},
{65, 8, 255,},
{73, 8, 255,},
{81, 8, 255,},
{89, 8, 255,},
{99, 8, 255,},
{109, 8, 255,},
{119, 8, 255,},
{129, 8, 255,},
{140, 8, 255,},
{152, 8, 255,},
{164, 8, 255,},
{176, 8, 255,},
{188, 8, 255,},
{200, 8, 255,},
{213, 8, 255,},
{227, 8, 255,},
{241, 8, 255,},
{255, 8, 255,},
{255, 8, 255,},
{255, 8, 255,},
{255, 8, 255,},
{255, 8, 255,},
{255, 10, 255,},
{255, 14, 255,},
{255, 18, 255,},
{255, 22, 255,},
{255, 26, 255,},
{255, 32, 255,},
{255, 38, 255,},
{255, 44, 255,},
{255, 50, 255,},
{255, 57, 255,},
{255, 65, 255,},
{255, 73, 255,},
{255, 81, 255,},
{255, 89, 255,},
{255, 99, 255,},
{255, 109, 255,},
{255, 119, 255,},
{255, 129, 255,},
{255, 140, 255,},
{255, 152, 255,},
{255, 164, 255,},
{255, 176, 255,},
{255, 188, 255,},
{255, 200, 255,},
{255, 213, 255,},
{255, 227, 255,},
{255, 241, 255,},
{255, 255, 255,},
{255, 248, 248,},
{255, 234, 234,},
{255, 220, 220,},
{255, 206, 206,},
{255, 194, 194,},
{255, 182, 182,},
{255, 170, 170,},
{255, 158, 158,},
{255, 146, 146,},
{255, 134, 134,},
{255, 124, 124,},
{255, 114, 114,},
{255, 104, 104,},
{255, 94, 94, },
{255, 85, 85, },
{255, 77, 77, },
{255, 69, 69, },
{255, 61, 61, },
{255, 53, 53, },
{255, 47, 47, },
{255, 41, 41, },
{255, 35, 35, },
{255, 29, 29, },
{255, 24, 24, },
{255, 20, 20, },
{255, 16, 16, },
{255, 12, 12, },
{255, 8, 8, },
{255, 8, 8, },
{255, 8, 8, },
{255, 8, 8, },
{255, 8, 8, },
//
{255, 8, 8},
{255, 8, 8},
{255, 8, 8},
{255, 8, 8},
{255, 10, 8},
{255, 14, 8},
{255, 18, 8},
{255, 22, 8},
{255, 26, 8},
{255, 32, 8},
{255, 38, 8},
{255, 44, 8},
{255, 50, 8},
{255, 57, 8},
{255, 65, 8},
{255, 73, 8},
{255, 81, 8},
{255, 89, 8},
{255, 99, 8},
{255, 109, 8},
{255, 119, 8},
{255, 129, 8},
{255, 140, 8},
{255, 152, 8},
{255, 164, 8},
{255, 176, 8},
{255, 188, 8},
{255, 200, 8},
{255, 213, 8},
{255, 227, 8},
{255, 241, 8},
{255, 255, 8},
{248, 255, 8},
{234, 255, 8},
{220, 255, 8},
{206, 255, 8},
{194, 255, 8},
{182, 255, 8},
{170, 255, 8},
{158, 255, 8},
{146, 255, 8},
{134, 255, 8},
{124, 255, 8},
{114, 255, 8},
{104, 255, 8},
{94, 255, 8},
{85, 255, 8},
{77, 255, 8},
{69, 255, 8},
{61, 255, 8},
{53, 255, 8},
{47, 255, 8},
{41, 255, 8},
{35, 255, 8},
{29, 255, 8},
{24, 255, 8},
{20, 255, 8},
{16, 255, 8},
{12, 255, 8},
{8, 255, 8},
{8, 255, 8},
{8, 255, 8},
{8, 255, 8},
{8, 255, 8},
{8, 255, 8, },
{8, 255, 8, },
{8, 255, 8, },
{8, 255, 8, },
{8, 255, 10, },
{8, 255, 14, },
{8, 255, 18, },
{8, 255, 22, },
{8, 255, 26, },
{8, 255, 32, },
{8, 255, 38, },
{8, 255, 44, },
{8, 255, 50, },
{8, 255, 57, },
{8, 255, 65, },
{8, 255, 73, },
{8, 255, 81, },
{8, 255, 89, },
{8, 255, 99, },
{8, 255, 109,},
{8, 255, 119,},
{8, 255, 129,},
{8, 255, 140,},
{8, 255, 152,},
{8, 255, 164,},
{8, 255, 176,},
{8, 255, 188,},
{8, 255, 200,},
{8, 255, 213,},
{8, 255, 227,},
{8, 255, 241,},
{8, 255, 255,},
{8, 248, 255,},
{8, 234, 255,},
{8, 220, 255,},
{8, 206, 255,},
{8, 194, 255,},
{8, 182, 255,},
{8, 170, 255,},
{8, 158, 255,},
{8, 146, 255,},
{8, 134, 255,},
{8, 124, 255,},
{8, 114, 255,},
{8, 104, 255,},
{8, 94, 255,},
{8, 85, 255,},
{8, 77, 255,},
{8, 69, 255,},
{8, 61, 255,},
{8, 53, 255,},
{8, 47, 255,},
{8, 41, 255,},
{8, 35, 255,},
{8, 29, 255,},
{8, 24, 255,},
{8, 20, 255,},
{8, 16, 255,},
{8, 12, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{8, 8, 255,},
{10, 8, 255,},
{14, 8, 255,},
{18, 8, 255,},
{22, 8, 255,},
{26, 8, 255,},
{32, 8, 255,},
{38, 8, 255,},
{44, 8, 255,},
{50, 8, 255,},
{57, 8, 255,},
{65, 8, 255,},
{73, 8, 255,},
{81, 8, 255,},
{89, 8, 255,},
{99, 8, 255,},
{109, 8, 255,},
{119, 8, 255,},
{129, 8, 255,},
{140, 8, 255,},
{152, 8, 255,},
{164, 8, 255,},
{176, 8, 255,},
{188, 8, 255,},
{200, 8, 255,},
{213, 8, 255,},
{227, 8, 255,},
{241, 8, 255,},
{255, 8, 255,},
{255, 8, 255,},
{255, 8, 255,},
{255, 8, 255,},
{255, 8, 255,},
{255, 10, 255,},
{255, 14, 255,},
{255, 18, 255,},
{255, 22, 255,},
{255, 26, 255,},
{255, 32, 255,},
{255, 38, 255,},
{255, 44, 255,},
{255, 50, 255,},
{255, 57, 255,},
{255, 65, 255,},
{255, 73, 255,},
{255, 81, 255,},
{255, 89, 255,},
{255, 99, 255,},
{255, 109, 255,},
{255, 119, 255,},
{255, 129, 255,},
{255, 140, 255,},
{255, 152, 255,},
{255, 164, 255,},
{255, 176, 255,},
{255, 188, 255,},
{255, 200, 255,},
{255, 213, 255,},
{255, 227, 255,},
{255, 241, 255,},
{255, 255, 255,},
{255, 248, 248,},
{255, 234, 234,},
{255, 220, 220,},
{255, 206, 206,},
{255, 194, 194,},
{255, 182, 182,},
{255, 170, 170,},
{255, 158, 158,},
{255, 146, 146,},
{255, 134, 134,},
{255, 124, 124,},
{255, 114, 114,},
{255, 104, 104,},
{255, 94, 94, },
{255, 85, 85, },
{255, 77, 77, },
{255, 69, 69, },
{255, 61, 61, },
{255, 53, 53, },
{255, 47, 47, },
{255, 41, 41, },
{255, 35, 35, },
{255, 29, 29, },
{255, 24, 24, },
{255, 20, 20, },
{255, 16, 16, },
{255, 12, 12, },
{255, 8, 8, },
{255, 8, 8, },
{255, 8, 8, },
{255, 8, 8, },
{255, 8, 8, },
};
const uint8_t colour_lib[9][3] =
{
{0xff, 0x00, 0x00},
{0xff, 0x80, 0x00},
{0xff, 0xff, 0x00},
{0x00, 0xff, 0x00},
{0x00, 0xff, 0xff},
{0x00, 0x00, 0xff},
{0x80, 0x00, 0xff},
{0xc0, 0xc0, 0xff},
{0x00, 0x00, 0x00},
};

View File

@ -0,0 +1,111 @@
/*
Copyright 2023 @ Nuphy <https://nuphy.com/>
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 "kb_util.h"
#include "ansi.h"
#include "hal_usb.h"
#include "usb_main.h"
extern kb_config_t kb_config;
extern DEV_INFO_STRUCT dev_info;
extern uint16_t rf_linking_time;
extern uint16_t no_act_time;
extern bool f_goto_sleep;
extern bool f_wakeup_prepare;
uint8_t uart_send_cmd(uint8_t cmd, uint8_t ack_cnt, uint8_t delayms);
/**
* @brief Sleep Handle.
*/
void sleep_handle(void) {
static uint32_t delay_step_timer = 0;
static uint8_t usb_suspend_debounce = 0;
static uint32_t rf_disconnect_time = 0;
/* 50ms interval */
if (timer_elapsed32(delay_step_timer) < 50) return;
delay_step_timer = timer_read32();
// sleep process
if (f_goto_sleep) {
f_goto_sleep = 0;
if(kb_config.sleep_enable) {
if (dev_info.rf_state == RF_CONNECT)
uart_send_cmd(CMD_SET_CONFIG, 5, 5);
else
uart_send_cmd(CMD_SLEEP, 5, 5);
// power off LED
gpio_set_pin_output_push_pull(DC_BOOST_PIN);
gpio_write_pin_low(DC_BOOST_PIN);
gpio_set_pin_input(DRIVER_LED_CS_PIN);
gpio_set_pin_input(DRIVER_SIDE_CS_PIN);
}
f_wakeup_prepare = 1;
}
// wakeup check
if (f_wakeup_prepare && (no_act_time < 10)) {
f_wakeup_prepare = 0;
gpio_write_pin_high(DC_BOOST_PIN);
gpio_set_pin_output_push_pull(DRIVER_LED_CS_PIN);
gpio_write_pin_low(DRIVER_LED_CS_PIN);
gpio_set_pin_output_push_pull(DRIVER_SIDE_CS_PIN);
gpio_write_pin_low(DRIVER_SIDE_CS_PIN);
uart_send_cmd(CMD_HAND, 0, 1);
if (dev_info.link_mode == LINK_USB) {
usb_lld_wakeup_host(&USB_DRIVER);
restart_usb_driver(&USB_DRIVER);
}
}
// sleep check
if (f_goto_sleep || f_wakeup_prepare)
return;
if (dev_info.link_mode == LINK_USB) {
if (USB_DRIVER.state == USB_SUSPENDED) {
usb_suspend_debounce++;
if (usb_suspend_debounce >= 20) {
f_goto_sleep = 1;
}
} else {
usb_suspend_debounce = 0;
}
} else if (dev_info.rf_state == RF_CONNECT) {
rf_disconnect_time = 0;
if (no_act_time >= SLEEP_TIME_DELAY) {
f_goto_sleep = 1;
}
} else if (rf_linking_time >= LINK_TIMEOUT) {
rf_linking_time = 0;
f_goto_sleep = 1;
} else if (dev_info.rf_state == RF_DISCONNECT) {
rf_disconnect_time++;
if (rf_disconnect_time > 5 * 20) {
rf_disconnect_time = 0;
f_goto_sleep = 1;
}
}
}

View File

@ -1,5 +1,6 @@
"""This script automates the copying of the default keymap into your own keymap. """This script automates the copying of the default keymap into your own keymap.
""" """
import re
import shutil import shutil
from milc import cli from milc import cli
@ -13,6 +14,13 @@ from qmk.keyboard import keyboard_completer, keyboard_folder
from qmk.userspace import UserspaceDefs from qmk.userspace import UserspaceDefs
def validate_keymap_name(name):
"""Returns True if the given keymap name contains only a-z, 0-9 and underscore characters.
"""
regex = re.compile(r'^[a-zA-Z0-9][a-zA-Z0-9_]+$')
return bool(regex.match(name))
def prompt_keyboard(): def prompt_keyboard():
prompt = """{fg_yellow}Select Keyboard{style_reset_all} prompt = """{fg_yellow}Select Keyboard{style_reset_all}
If you`re unsure you can view a full list of supported keyboards with {fg_yellow}qmk list-keyboards{style_reset_all}. If you`re unsure you can view a full list of supported keyboards with {fg_yellow}qmk list-keyboards{style_reset_all}.
@ -60,6 +68,10 @@ def new_keymap(cli):
cli.log.error(f'Default keymap {{fg_cyan}}{keymap_path_default}{{fg_reset}} does not exist!') cli.log.error(f'Default keymap {{fg_cyan}}{keymap_path_default}{{fg_reset}} does not exist!')
return False return False
if not validate_keymap_name(user_name):
cli.log.error('Keymap names must contain only {fg_cyan}a-z{fg_reset}, {fg_cyan}0-9{fg_reset} and {fg_cyan}_{fg_reset}! Please choose a different name.')
return False
if keymap_path_new.exists(): if keymap_path_new.exists():
cli.log.error(f'Keymap {{fg_cyan}}{user_name}{{fg_reset}} already exists! Please choose a different name.') cli.log.error(f'Keymap {{fg_cyan}}{user_name}{{fg_reset}} already exists! Please choose a different name.')
return False return False

View File

@ -29,6 +29,7 @@ def _convert_macros(via_macros):
if len(via_macros) == 0: if len(via_macros) == 0:
return list() return list()
split_regex = re.compile(r'(}\,)|(\,{)') split_regex = re.compile(r'(}\,)|(\,{)')
macro_group_regex = re.compile(r'({.+?})')
macros = list() macros = list()
for via_macro in via_macros: for via_macro in via_macros:
# Split VIA macro to its elements # Split VIA macro to its elements
@ -38,13 +39,28 @@ def _convert_macros(via_macros):
macro_data = list() macro_data = list()
for m in macro: for m in macro:
if '{' in m or '}' in m: if '{' in m or '}' in m:
# Found keycode(s) # Split macro groups
keycodes = m.split(',') macro_groups = macro_group_regex.findall(m)
# Remove whitespaces and curly braces from around keycodes for macro_group in macro_groups:
keycodes = list(map(lambda s: s.strip(' {}'), keycodes)) # Remove whitespaces and curly braces from around group
# Remove the KC prefix macro_group = macro_group.strip(' {}')
keycodes = list(map(lambda s: s.replace('KC_', ''), keycodes))
macro_data.append({"action": "tap", "keycodes": keycodes}) macro_action = 'tap'
macro_keycodes = []
if macro_group[0] == '+':
macro_action = 'down'
macro_keycodes.append(macro_group[1:])
elif macro_group[0] == '-':
macro_action = 'up'
macro_keycodes.append(macro_group[1:])
else:
macro_keycodes.extend(macro_group.split(',') if ',' in macro_group else [macro_group])
# Remove the KC prefixes
macro_keycodes = list(map(lambda s: s.replace('KC_', ''), macro_keycodes))
macro_data.append({"action": macro_action, "keycodes": macro_keycodes})
else: else:
# Found text # Found text
macro_data.append(m) macro_data.append(m)
@ -54,13 +70,13 @@ def _convert_macros(via_macros):
def _fix_macro_keys(keymap_data): def _fix_macro_keys(keymap_data):
macro_no = re.compile(r'MACRO0?([0-9]{1,2})') macro_no = re.compile(r'MACRO0?\(([0-9]{1,2})\)')
for i in range(0, len(keymap_data)): for i in range(0, len(keymap_data)):
for j in range(0, len(keymap_data[i])): for j in range(0, len(keymap_data[i])):
kc = keymap_data[i][j] kc = keymap_data[i][j]
m = macro_no.match(kc) m = macro_no.match(kc)
if m: if m:
keymap_data[i][j] = f'MACRO_{m.group(1)}' keymap_data[i][j] = f'MC_{m.group(1)}'
return keymap_data return keymap_data