diff --git a/keyboards/nuphy/air75_v2/ansi/ansi.c b/keyboards/nuphy/air75_v2/ansi/ansi.c new file mode 100644 index 000000000000..4fea648a86ab --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/ansi.c @@ -0,0 +1,274 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "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(); +} diff --git a/keyboards/nuphy/air75_v2/ansi/ansi.h b/keyboards/nuphy/air75_v2/ansi/ansi.h new file mode 100644 index 000000000000..4a79db0e2d7d --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/ansi.h @@ -0,0 +1,50 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#pragma once + +#include "quantum.h" + +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) diff --git a/keyboards/nuphy/air75_v2/ansi/config.h b/keyboards/nuphy/air75_v2/ansi/config.h new file mode 100644 index 000000000000..d60889c3bbdf --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/config.h @@ -0,0 +1,36 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#pragma once + +#define 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 diff --git a/keyboards/nuphy/air75_v2/ansi/halconf.h b/keyboards/nuphy/air75_v2/ansi/halconf.h new file mode 100644 index 000000000000..390f3d94cdee --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/halconf.h @@ -0,0 +1,23 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#pragma once + +#include_next + +#undef HAL_USE_SERIAL +#define HAL_USE_SERIAL TRUE diff --git a/keyboards/nuphy/air75_v2/ansi/info.json b/keyboards/nuphy/air75_v2/ansi/info.json new file mode 100644 index 000000000000..ac90d7ba5f14 --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/info.json @@ -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.5, "y": 30, "flags": 4}, + {"matrix": [3, 11], "x": 117.5, "y": 30, "flags": 4}, + {"matrix": [3, 10], "x": 107.5, "y": 30, "flags": 4}, + {"matrix": [3, 9], "x": 97.5, "y": 30, "flags": 4}, + {"matrix": [3, 8], "x": 87.5, "y": 30, "flags": 4}, + {"matrix": [3, 7], "x": 77.5, "y": 30, "flags": 4}, + {"matrix": [3, 6], "x": 67.5, "y": 30, "flags": 4}, + {"matrix": [3, 5], "x": 57.5, "y": 30, "flags": 4}, + {"matrix": [3, 4], "x": 47.5, "y": 30, "flags": 4}, + {"matrix": [3, 3], "x": 37.5, "y": 30, "flags": 4}, + {"matrix": [3, 2], "x": 27.5, "y": 30, "flags": 4}, + {"matrix": [3, 1], "x": 17.5, "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.5, "y": 40, "flags": 4}, + {"matrix": [4, 3], "x": 32.5, "y": 40, "flags": 4}, + {"matrix": [4, 4], "x": 42.5, "y": 40, "flags": 4}, + {"matrix": [4, 5], "x": 52.5, "y": 40, "flags": 4}, + {"matrix": [4, 6], "x": 62.5, "y": 40, "flags": 4}, + {"matrix": [4, 7], "x": 72.5, "y": 40, "flags": 4}, + {"matrix": [4, 8], "x": 82.5, "y": 40, "flags": 4}, + {"matrix": [4, 9], "x": 92.5, "y": 40, "flags": 4}, + {"matrix": [4, 10], "x": 102.5, "y": 40, "flags": 4}, + {"matrix": [4, 11], "x": 112.5, "y": 40, "flags": 4}, + {"matrix": [4, 13], "x": 122.5, "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.5, "y": 50, "flags": 4}, + {"matrix": [5, 2], "x": 25, "y": 50, "flags": 4}, + {"matrix": [5, 1], "x": 12.5, "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} + ] + } + } +} diff --git a/keyboards/nuphy/air75_v2/ansi/kb_util.c b/keyboards/nuphy/air75_v2/ansi/kb_util.c new file mode 100644 index 000000000000..3920f1fb2368 --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/kb_util.c @@ -0,0 +1,443 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "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; + } +} diff --git a/keyboards/nuphy/air75_v2/ansi/kb_util.h b/keyboards/nuphy/air75_v2/ansi/kb_util.h new file mode 100644 index 000000000000..5b3e8b87304e --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/kb_util.h @@ -0,0 +1,164 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#pragma once + +#include "quantum.h" + +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); diff --git a/keyboards/nuphy/air75_v2/ansi/keymaps/default/keymap.c b/keyboards/nuphy/air75_v2/ansi/keymaps/default/keymap.c new file mode 100644 index 000000000000..826a9789fcdf --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/keymaps/default/keymap.c @@ -0,0 +1,66 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include QMK_KEYBOARD_H + +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) +}; diff --git a/keyboards/nuphy/air75_v2/ansi/keymaps/via/keymap.c b/keyboards/nuphy/air75_v2/ansi/keymaps/via/keymap.c new file mode 100644 index 000000000000..826a9789fcdf --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/keymaps/via/keymap.c @@ -0,0 +1,66 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include QMK_KEYBOARD_H + +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) +}; diff --git a/keyboards/nuphy/air75_v2/ansi/keymaps/via/rules.mk b/keyboards/nuphy/air75_v2/ansi/keymaps/via/rules.mk new file mode 100644 index 000000000000..1e5b99807cb7 --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/keymaps/via/rules.mk @@ -0,0 +1 @@ +VIA_ENABLE = yes diff --git a/keyboards/nuphy/air75_v2/ansi/mcuconf.h b/keyboards/nuphy/air75_v2/ansi/mcuconf.h new file mode 100644 index 000000000000..8a16a1eaaa44 --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/mcuconf.h @@ -0,0 +1,23 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#pragma once + +#include_next + +#undef STM32_SERIAL_USE_USART1 +#define STM32_SERIAL_USE_USART1 TRUE diff --git a/keyboards/nuphy/air75_v2/ansi/readme.md b/keyboards/nuphy/air75_v2/ansi/readme.md new file mode 100644 index 000000000000..06fc1fac110a --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/readme.md @@ -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: Private + +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 diff --git a/keyboards/nuphy/air75_v2/ansi/rf.c b/keyboards/nuphy/air75_v2/ansi/rf.c new file mode 100644 index 000000000000..ecf772a4f027 --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/rf.c @@ -0,0 +1,660 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "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); +} diff --git a/keyboards/nuphy/air75_v2/ansi/rf_driver.c b/keyboards/nuphy/air75_v2/ansi/rf_driver.c new file mode 100644 index 000000000000..65db72c6deff --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/rf_driver.c @@ -0,0 +1,65 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "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); + } +} diff --git a/keyboards/nuphy/air75_v2/ansi/rf_driver.h b/keyboards/nuphy/air75_v2/ansi/rf_driver.h new file mode 100644 index 000000000000..ad0cf3cb384f --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/rf_driver.h @@ -0,0 +1,20 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#pragma once + +extern host_driver_t rf_host_driver; diff --git a/keyboards/nuphy/air75_v2/ansi/rules.mk b/keyboards/nuphy/air75_v2/ansi/rules.mk new file mode 100644 index 000000000000..31ccc14d28fe --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/rules.mk @@ -0,0 +1,3 @@ +SRC += side.c rf.c sleep.c rf_driver.c kb_util.c side_driver.c + +UART_DRIVER_REQUIRED = yes diff --git a/keyboards/nuphy/air75_v2/ansi/side.c b/keyboards/nuphy/air75_v2/ansi/side.c new file mode 100644 index 000000000000..2f168b2a0e84 --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/side.c @@ -0,0 +1,851 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "kb_util.h" +#include "ansi.h" +#include "side_table.h" +#include "ws2812.h" + +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}; + +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 side_rgb_brightness. + * @param light_temp: + */ +static void side_rgb_brightness(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 set left side leds. + * @param ... + */ +void set_left_rgb(uint8_t r, uint8_t g, uint8_t b, bool system) { + uint8_t bright = side_light; + if (bright == 0) { + if (system) { + bright = 1; + } else { + return; + } + } + r_temp = r; + g_temp = g; + b_temp = b; + side_rgb_brightness(side_light_tab[bright]); + + for (int i = 0; i < 6; i++) + side_rgb_set_color(i, r_temp >> 2, g_temp >> 2, b_temp >> 2); +} + +/** + * @brief set right side leds. + * @param ... + */ +void set_right_rgb(uint8_t r, uint8_t g, uint8_t b, bool system) { + uint8_t bright = side_light; + if (bright == 0) { + if (system) { + bright = 1; + } else { + return; + } + } + r_temp = r; + g_temp = g; + b_temp = b; + side_rgb_brightness(side_light_tab[bright]); + + for (int i = 6; i < 12; i++) + side_rgb_set_color(i, r_temp >> 2, g_temp >> 2, b_temp >> 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, true); + } else { + set_right_rgb(0x00, 0x00, 0x00, false); + } + 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, true); + } else { + set_right_rgb(0x00, 0x00, 0x00, false); + } + 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, true); + } + } + + else { + if (dev_info.rf_led & 0x02) { + set_left_rgb(0X00, 0x80, 0x80, true); + } + } +} + +/** + * @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 side_wave_mode_show. + */ +static void side_wave_mode_show(void) { + uint8_t play_index; + + if (side_play_cnt <= side_speed_tab[side_mode][side_speed]) { + return; + } else { + side_play_cnt -= side_speed_tab[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); + side_rgb_brightness(wave_data_tab[play_index]); + } + + side_rgb_brightness(side_light_tab[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_tab[side_mode][side_speed]) { + return; + } else { + side_play_cnt -= side_speed_tab[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]; + + side_rgb_brightness(side_light_tab[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_tab[side_mode][side_speed]) { + return; + } else { + side_play_cnt -= side_speed_tab[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]; + } + + side_rgb_brightness(breathe_data_tab[play_point]); + side_rgb_brightness(side_light_tab[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_tab[side_mode][side_speed]) { + return; + } else { + side_play_cnt -= side_speed_tab[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]; + } + + side_rgb_brightness(side_light_tab[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_tab[side_mode][side_speed]) { + return; + } else { + side_play_cnt -= side_speed_tab[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, true); +} + +/** + * @brief bat_num_led. + */ +void bat_num_led(uint8_t bat_percent) { + uint8_t r, g, b; + uint8_t bat_idx = bat_percent / 17; + uint8_t bat_lvl = 1 + ((bat_percent - 1) / 10); + + r = bat_percent_tab[bat_idx][0]; + g = bat_percent_tab[bat_idx][1]; + b = bat_percent_tab[bat_idx][2]; + + // set percent + for (uint8_t i = 0; i < bat_lvl; i++) { + rgb_matrix_set_color(29 - i, 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_idx = bat_percent / 17; + uint8_t bright = side_light; + if (bright < 1) { + bright = 1; + } + + r_temp = bat_percent_tab[bat_idx][0]; + g_temp = bat_percent_tab[bat_idx][1]; + b_temp = bat_percent_tab[bat_idx][2]; + side_rgb_brightness(side_light_tab[bright]); + + uint8_t i = 0; + for (; i <= bat_idx; i++) + side_rgb_set_color(11 - i, r_temp >> 2, g_temp >> 2, b_temp >> 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; + side_rgb_brightness(breathe_data_tab[play_point]); + set_right_rgb(r_temp, g_temp, b_temp, true); + } 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, true); + set_right_rgb(0x40, 0x40, 0x40, true); + 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, true); + set_right_rgb(0x00, 0x00, 0x00, true); + 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, true); + set_right_rgb(0xff, 0x00, 0x00, true); + 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, true); + set_right_rgb(0x00, 0xFF, 0x00, true); + 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, true); + set_right_rgb(0x00, 0x00, 0xFF, true); + 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, true); + set_right_rgb(0x80, 0x80, 0x80, true); + 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, true); + set_right_rgb(0x80, 0x80, 0x00, true); + 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, true); + set_right_rgb(0x80, 0x00, 0x80, true); + 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, true); + set_right_rgb(0x00, 0x80, 0x80, true); + 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(); + } +} diff --git a/keyboards/nuphy/air75_v2/ansi/side.h b/keyboards/nuphy/air75_v2/ansi/side.h new file mode 100644 index 000000000000..10787c5fc82c --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/side.h @@ -0,0 +1,35 @@ +/* +Copyright 2023 @ Nuphy + +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 . +*/ + +#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, +}; diff --git a/keyboards/nuphy/air75_v2/ansi/side_driver.c b/keyboards/nuphy/air75_v2/ansi/side_driver.c new file mode 100644 index 000000000000..4c1feb4b5bc7 --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/side_driver.c @@ -0,0 +1,103 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include +#include + +#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(); +} diff --git a/keyboards/nuphy/air75_v2/ansi/side_table.h b/keyboards/nuphy/air75_v2/ansi/side_table.h new file mode 100644 index 000000000000..3bd38513c32f --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/side_table.h @@ -0,0 +1,612 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#pragma once + +#include "side.h" + +#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}, +}; + +const uint8_t side_speed_tab[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_tab[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}, // +}; + +const uint8_t bat_percent_tab[6][3] = { + {0xff, 0x00, 0x00}, + {0xff, 0x66, 0x00}, + {0xff, 0xcc, 0x00}, + {0xcc, 0xff, 0x00}, + {0x66, 0xff, 0x00}, + {0x00, 0xff, 0x00}, +}; diff --git a/keyboards/nuphy/air75_v2/ansi/sleep.c b/keyboards/nuphy/air75_v2/ansi/sleep.c new file mode 100644 index 000000000000..0c23db9c7418 --- /dev/null +++ b/keyboards/nuphy/air75_v2/ansi/sleep.c @@ -0,0 +1,115 @@ +/* +Copyright 2023 @ Nuphy + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "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; + } + } +}