From 54b4dc4ed12a52a2448b29fed5dcb7291ee41f3e Mon Sep 17 00:00:00 2001 From: LiuLiuQMK <1357050487@qq.com> Date: Thu, 14 Nov 2024 14:19:09 +0800 Subject: [PATCH] sk75 --- keyboards/womier/common/rdmctmzt_common.c | 485 +++++++++++ keyboards/womier/common/rdmctmzt_common.h | 198 +++++ keyboards/womier/common/three_mode.c | 209 +++++ keyboards/womier/common/three_mode.h | 45 + keyboards/womier/common/user_battery.c | 418 +++++++++ keyboards/womier/common/user_battery.h | 51 ++ keyboards/womier/common/user_eeprom.c | 630 ++++++++++++++ keyboards/womier/common/user_eeprom.h | 31 + keyboards/womier/common/user_emi.c | 64 ++ keyboards/womier/common/user_emi.h | 24 + keyboards/womier/common/user_led_custom.c | 256 ++++++ keyboards/womier/common/user_led_custom.h | 28 + keyboards/womier/common/user_spi.c | 322 +++++++ keyboards/womier/common/user_spi.h | 96 ++ keyboards/womier/common/user_system.c | 438 ++++++++++ keyboards/womier/common/user_system.h | 32 + keyboards/womier/sk75/chconf.h | 822 ++++++++++++++++++ keyboards/womier/sk75/config.h | 97 +++ keyboards/womier/sk75/keyboard.json | 172 ++++ .../womier/sk75/keymaps/default/keymap.c | 52 ++ keyboards/womier/sk75/mcuconf.h | 222 +++++ keyboards/womier/sk75/readme.md | 22 + keyboards/womier/sk75/rules.mk | 51 ++ keyboards/womier/sk75/sk75.c | 594 +++++++++++++ 24 files changed, 5359 insertions(+) create mode 100644 keyboards/womier/common/rdmctmzt_common.c create mode 100644 keyboards/womier/common/rdmctmzt_common.h create mode 100644 keyboards/womier/common/three_mode.c create mode 100644 keyboards/womier/common/three_mode.h create mode 100644 keyboards/womier/common/user_battery.c create mode 100644 keyboards/womier/common/user_battery.h create mode 100644 keyboards/womier/common/user_eeprom.c create mode 100644 keyboards/womier/common/user_eeprom.h create mode 100644 keyboards/womier/common/user_emi.c create mode 100644 keyboards/womier/common/user_emi.h create mode 100644 keyboards/womier/common/user_led_custom.c create mode 100644 keyboards/womier/common/user_led_custom.h create mode 100644 keyboards/womier/common/user_spi.c create mode 100644 keyboards/womier/common/user_spi.h create mode 100644 keyboards/womier/common/user_system.c create mode 100644 keyboards/womier/common/user_system.h create mode 100644 keyboards/womier/sk75/chconf.h create mode 100644 keyboards/womier/sk75/config.h create mode 100644 keyboards/womier/sk75/keyboard.json create mode 100644 keyboards/womier/sk75/keymaps/default/keymap.c create mode 100644 keyboards/womier/sk75/mcuconf.h create mode 100644 keyboards/womier/sk75/readme.md create mode 100644 keyboards/womier/sk75/rules.mk create mode 100644 keyboards/womier/sk75/sk75.c diff --git a/keyboards/womier/common/rdmctmzt_common.c b/keyboards/womier/common/rdmctmzt_common.c new file mode 100644 index 00000000000..422d379b72a --- /dev/null +++ b/keyboards/womier/common/rdmctmzt_common.c @@ -0,0 +1,485 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 "rdmctmzt_common.h" + +Keyboard_Info_t Keyboard_Info = { + .Key_Mode = INIT_WORK_MODE, + .Ble_Channel = INIT_BLE_CHANNEL, + .Batt_Number = INIT_BATT_NUMBER, + .Nkro = INIT_ALL_SIX_KEY, + .Mac_Win_Mode = INIT_WIN_MAC_MODE, + .Win_Lock = INIT_WIN_LOCK_NLOCK, +}; + +Keyboard_Status_t Keyboard_Status = { + .System_Work_Status = 0x00, + .System_Work_Mode = 0x00, + .System_Work_Channel = 0x00, + .System_Connect_Status = 0x00, + .System_Led_Status = 0x00, + .System_Sleep_Mode = 0x00 +}; + +const uint32_t g_es_dma_ch2pri_cfg = ((MD_DMA_CHANNEL_CFG_MODE_PERIPHERAL_PRIMARY) | \ + ((MD_DMA_CHANNEL_CFG_RPOWER_SIZE_4) << 14) | \ + ((MD_DMA_CHANNEL_CFG_SRCDATA_SIZE_WORD) << 24) | \ + ((MD_DMA_CHANNEL_CFG_SRCINC_WORD) << 26) | \ + ((MD_DMA_CHANNEL_CFG_DSTDATA_SIZE_WORD) << 28) | \ + ((MD_DMA_CHANNEL_CFG_DSTINC_WORD) << 30)); + +const uint32_t g_es_dma_ch2alt_cfg = ((MD_DMA_CHANNEL_CFG_MODE_PERIPHERAL_ALTERNATE) | \ + ((MD_DMA_CHANNEL_CFG_RPOWER_SIZE_1) << 14) | \ + ((MD_DMA_CHANNEL_CFG_SRCDATA_SIZE_BYTE) << 24) | \ + ((MD_DMA_CHANNEL_CFG_SRCINC_BYTE) << 26) | \ + ((MD_DMA_CHANNEL_CFG_DSTDATA_SIZE_BYTE) << 28) | \ + ((MD_DMA_CHANNEL_CFG_DSTINC_NO_INC) << 30)); + +bool Led_Rf_Pair_Flg = false; +bool Key_2p4g_Status = false; +bool Key_Ble_1_Status = false; +bool Key_Ble_2_Status = false; +bool Key_Ble_3_Status = false; +bool Key_Reset_Status = false; +bool Keyboard_Reset = false; +bool Init_Eeprom_Flg = false; +bool Led_Off_Start = false; +bool Led_Power_Up = false; +bool Usb_If_Ok_Led = false; +uint16_t Led_Power_Up_Delay = 0; +uint8_t Temp_System_Led_Status = 0xff; +uint8_t Systick_6ms_Count = 0U; +uint8_t Systick_10ms_Count = 0x00; +uint16_t Systick_Interval_Count = 0x00; +uint8_t Systick_Led_Count = 0x00; +uint8_t Batt_Led_Count = 0x00; +uint16_t Time_3s_Count = 0; +uint16_t Func_Time_3s_Count = 0; + +//WAKEUP_IRQHandler +OSAL_IRQ_HANDLER(Vector4C) { + md_syscfg_clear_flag_wakeup(SYSCFG); + md_exti_clear_it_wakeup(EXTI); //Clear Wakeup Flag +} + +//EXTI_0to1_IRQHandler +OSAL_IRQ_HANDLER(Vector54) { + uint32_t irq_ifm; + OSAL_IRQ_PROLOGUE(); + + irq_ifm = EXTI->IFM; + EXTI->ICR = irq_ifm; + + OSAL_IRQ_EPILOGUE(); +} + +//EXTI_2to3_IRQHandler +OSAL_IRQ_HANDLER(Vector58) { + uint32_t irq_ifm; + OSAL_IRQ_PROLOGUE(); + + irq_ifm = EXTI->IFM; + EXTI->ICR = irq_ifm; + + OSAL_IRQ_EPILOGUE(); +} + +//GP32C4T1_IRQHandler +OSAL_IRQ_HANDLER(Vector7C) { + uint32_t irq_ifm; + OSAL_IRQ_PROLOGUE(); + + irq_ifm = GP32C4T1->IFM; + GP32C4T1->ICR = irq_ifm; + + OSAL_IRQ_EPILOGUE(); +} + +//GP16C4T1_IRQHandler +OSAL_IRQ_HANDLER(Vector80) { + uint32_t irq_ifm; + OSAL_IRQ_PROLOGUE(); + + irq_ifm = GP16C4T1->IFM; + GP16C4T1->ICR = irq_ifm; + + OSAL_IRQ_EPILOGUE(); +} + +//GP16C4T2_IRQHandler +OSAL_IRQ_HANDLER(Vector84) { + uint32_t irq_ifm; + OSAL_IRQ_PROLOGUE(); + + irq_ifm = GP16C4T2->IFM; + GP16C4T2->ICR = irq_ifm; + + OSAL_IRQ_EPILOGUE(); +} + +//DMA1_CH12_IRQHandler +OSAL_IRQ_HANDLER(Vector68) { + uint32_t irq_ifm; + OSAL_IRQ_PROLOGUE(); + + irq_ifm = DMA1->IFM; + DMA1->ICR = irq_ifm; + + if(irq_ifm & (1U << 1)){ + /*DMA 收发完成*/ + } + + OSAL_IRQ_EPILOGUE(); +} + +//EXTI_4to15_IRQHandler +OSAL_IRQ_HANDLER(Vector5C) { + uint32_t irq_ifm; + OSAL_IRQ_PROLOGUE(); + + irq_ifm = EXTI->IFM; + EXTI->ICR = irq_ifm; + + if (!Init_Spi_Power_Up) { + if(irq_ifm & (1U << 4)) { + if (Spi_Send_Recv_Flg) { + if (Send_Key_Type == SPI_NACK) { + if (!gpio_read_pin(ES_SPI_ACK_IO)) { + Spi_Send_Recv_Flg = 0; + } + } else { + if (gpio_read_pin(ES_SPI_ACK_IO)) { + if (Spi_Send_Recv_Flg == 1) { + Spi_Send_Recv_Flg = 2; + memset((void *)g_es_spi_rx_buf, 0x00, USER_KEYBOARD_LENGTH); + es_spi_send_recv_by_dma(USER_KEYBOARD_LENGTH, g_es_spi_rx_buf, (void*)(0x1000)); + } + } else { + if (Spi_Send_Recv_Flg == 2) { + if (Emi_Test_Start && ((USER_EMI_COMMAND == g_es_spi_rx_buf[0]) || ((USER_EMI_COMMAND & 0X7F) == g_es_spi_rx_buf[0]))) { + Get_Spi_Return_Data(g_es_spi_rx_buf); + Spi_Send_Recv_Flg = 0; + } else if (USER_KEYBOARD_COMMAND == g_es_spi_rx_buf[0]) { + Get_Spi_Return_Data(g_es_spi_rx_buf); + Spi_Send_Recv_Flg = 0; + } else { + Repet_Send_Count++; + if (Repet_Send_Count >= 3) { + Repet_Send_Count = 0; + Spi_Send_Recv_Flg = 0; + } else { + Spi_Send_Recv_Flg = 1; + es_spi_send_recv_by_dma(USER_KEYBOARD_LENGTH, g_es_spi_rx_buf, g_es_spi_tx_buf); + } + } + } + } + } + } + } + } + OSAL_IRQ_EPILOGUE(); +} + +//BS16T1_IRQHandler 2ms +OSAL_IRQ_HANDLER(Vector78) { + OSAL_IRQ_PROLOGUE(); + + BS16T1->ICR = BS16T1->IFM; + + if (Init_Spi_Power_Up) { + Init_Spi_100ms_Delay++; + if (Init_Spi_100ms_Delay >= 10) { + Init_Spi_100ms_Delay = 0; + if (!gpio_read_pin(ES_SPI_ACK_IO)) { + Init_Spi_Power_Up = false; + } else { + Init_Spi_100ms_Delay = 5; + } + } + } + + if (Keyboard_Info.Key_Mode != QMK_USB_MODE) { + if (Keyboard_Status.System_Work_Status && (!Keyboard_Status.System_Sleep_Mode)) { + Spi_Ack_Send_Commad(USER_KEYBOARD_SLEEP); + } else { + Spi_Main_Loop(); + } + } + + if (User_Batt_Power_Up_Delay) { + User_Batt_Power_Up_Delay_100ms_Count++; + if (User_Batt_Power_Up_Delay_100ms_Count >= 50) { + User_Batt_Power_Up_Delay_100ms_Count = 0; + User_Batt_Power_Up_Delay = false; + } + } else { + if (User_Batt_Power_Up) { + User_Batt_10ms_Count++; + if (User_Batt_10ms_Count >= 4) { + User_Batt_10ms_Count = 0; + if((md_adc_is_active_flag_normal_status(ADC)) == 0) { + User_Adc_Batt[User_Adc_Batt_Count] = md_adc_get_normal_data(ADC); + md_adc_set_start_normal(ADC, MD_ADC_CON_NSTART_START_REGULAR); + User_Adc_Batt_Count++; + if (User_Adc_Batt_Count >= USER_BATT_POWER_SCAN_COUNT) { + User_Adc_Batt_Count = 0; + for(uint8_t i = 0; i < USER_BATT_POWER_SCAN_COUNT; i++) { + User_Scan_Batt[i] = User_Adc_Batt[i]; + } + User_Adc_Batt_Power_Up_Init(); + } + } + } + } else { + User_Batt_10ms_Count++; + if (User_Batt_10ms_Count >= 20) { + User_Batt_10ms_Count = 0; + if((md_adc_is_active_flag_normal_status(ADC)) == 0) { + User_Adc_Batt[User_Adc_Batt_Count] = md_adc_get_normal_data(ADC); + md_adc_set_start_normal(ADC, MD_ADC_CON_NSTART_START_REGULAR); + User_Adc_Batt_Count++; + if (User_Adc_Batt_Count >= USER_BATT_SCAN_COUNT) { + User_Adc_Batt_Count = 0; + for(uint8_t i = 0; i < USER_BATT_SCAN_COUNT; i++) { + User_Scan_Batt[i] = User_Adc_Batt[i]; + } + User_Adc_Batt_Number(); + } + } + User_Batt_Time_15S_Count++; + } + } + } + + Systick_6ms_Count++; + if (Systick_6ms_Count >= 3) { + Systick_6ms_Count = 0; + + host_driver_t * temp_driver; + temp_driver = host_get_driver(); + if((temp_driver != (&es_user_driver))&&(temp_driver)) { + es_qmk_driver = host_get_driver(); + host_set_driver((host_driver_t *)(&es_user_driver)); + } + } + + Systick_10ms_Count++; + if (Systick_10ms_Count >= 5) { + Systick_10ms_Count = 0; + + if (Mode_Synchronization_Signal) { + Mode_Synchronization_Signal = false; + Mode_Synchronization(); + } + + if (Ble_Name_Spi_Send) { + Ble_Name_Synchronization(); + } + + Systick_Led_Count++; + if (Systick_Led_Count >= 255) { + Systick_Led_Count = 0; + } + + Batt_Led_Count++; + if (Batt_Led_Count >= 255) { + Batt_Led_Count = 0; + } + + if (Led_Power_Up == false) { + Led_Power_Up_Delay++; + if (Led_Power_Up_Delay >= 50) { + Led_Power_Up_Delay = 0; + Led_Power_Up = true; + if (Keyboard_Info.Key_Mode == QMK_BLE_MODE) { + User_Batt_Send_Spi = true; + } + } + } + + Usb_Change_Mode_Delay++; + if (Usb_Change_Mode_Delay >= USER_TIME_3S_TIME) { + Usb_Change_Mode_Delay = 0; + Usb_Change_Mode_Wakeup = true; + } + + if (Save_Flash) { + Save_Flash_3S_Count++; + if (Save_Flash_3S_Count >= USER_TIME_3S_TIME) { + if (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO)) || (!Led_Flash_Busy)) { + Save_Flash_3S_Count = (USER_TIME_3S_TIME - 10); + } else { + Reset_Save_Flash = true; + eeprom_write_block_user((void *)&Keyboard_Info.Key_Mode, 0, sizeof(Keyboard_Info_t)); + Reset_Save_Flash = false; + Save_Flash = false; + Save_Flash_3S_Count = 0; + } + } + } else { + Save_Flash_3S_Count = 0; + } + + if (Keyboard_Info.Key_Mode != QMK_USB_MODE) { + if (User_Batt_Send_Spi) { + User_Batt_Send_Spi = false; + Spi_Send_Commad(USER_BATTERY_DATA); + } + Usb_If_Ok_Led = false; + } else { + g_usb_sof_frame_id = ((USB->FRAME1) | (USB->FRAME2 << 8)); + Usb_Dis_Connect = true; + } + + if (gpio_read_pin(ES_USB_POWER_IO)) { + if (gpio_read_pin(ES_BATT_STDBY_IO)) { + es_stdby_pin_state = 1; + } else { + es_stdby_pin_state = 2; + } + } else { + es_stdby_pin_state = 0; + } + + Time_3s_Count++; + if (Time_3s_Count >= USER_TIME_3S_TIME) { + Time_3s_Count = 0; + + if (Keyboard_Info.Key_Mode != QMK_USB_MODE) { + if (Key_2p4g_Status || Key_Ble_1_Status || Key_Ble_2_Status || Key_Ble_3_Status) { + switch (Keyboard_Info.Key_Mode) { + case QMK_2P4G_MODE: { + if (Key_2p4g_Status){ + Key_2p4g_Status = 0; + Spi_Send_Commad(USER_SWITCH_2P4G_PAIR); + Led_Rf_Pair_Flg = true; + } + break; + } + case QMK_BLE_MODE: { + if ((Keyboard_Info.Ble_Channel == QMK_BLE_CHANNEL_1) && Key_Ble_1_Status){ + Key_Ble_1_Status = 0; + Spi_Send_Commad(USER_SWITCH_BLE_1_PAIR); + Led_Rf_Pair_Flg = true; + } else if ((Keyboard_Info.Ble_Channel == QMK_BLE_CHANNEL_2) && Key_Ble_2_Status){ + Key_Ble_2_Status = 0; + Spi_Send_Commad(USER_SWITCH_BLE_2_PAIR); + Led_Rf_Pair_Flg = true; + } else if ((Keyboard_Info.Ble_Channel == QMK_BLE_CHANNEL_3) && Key_Ble_3_Status){ + Key_Ble_3_Status = 0; + Spi_Send_Commad(USER_SWITCH_BLE_3_PAIR); + Led_Rf_Pair_Flg = true; + } + break; + } + default: { + break; + } + } + } + } + } + + Func_Time_3s_Count++; + if (Func_Time_3s_Count >= USER_TIME_3S_TIME) { + Func_Time_3s_Count = 0; + + if (Key_Reset_Status) { + Key_Reset_Status = false; + Keyboard_Reset = true; + } + } + } + + Systick_Interval_Count++; + if (Systick_Interval_Count >= Spi_Interval) { + Systick_Interval_Count = 0; + + if (!Keyboard_Status.System_Work_Status) { + if(Spi_Ack_Send_Commad(USER_GET_RF_STATUS) == SPI_BUSY) { + Systick_Interval_Count = (Spi_Interval - 10); + } + } + } + + OSAL_IRQ_EPILOGUE(); +} + +void Init_Keyboard_Infomation(void) { + eeprom_read_block_user((void *)&Keyboard_Info.Key_Mode, 0, sizeof(Keyboard_Info_t)); + + if ((Keyboard_Info.Key_Mode == 0XFF) && (Keyboard_Info.Ble_Channel == 0XFF) && (Keyboard_Info.Batt_Number == 0XFF) && (Keyboard_Info.Nkro == 0XFF) && (Keyboard_Info.Mac_Win_Mode == 0XFF) && (Keyboard_Info.Win_Lock == 0XFF)) { + Keyboard_Info.Key_Mode = INIT_WORK_MODE; + Keyboard_Info.Ble_Channel = INIT_BLE_CHANNEL; + Keyboard_Info.Batt_Number = INIT_BATT_NUMBER; + Keyboard_Info.Nkro = INIT_ALL_KEY; + Keyboard_Info.Mac_Win_Mode = INIT_WIN_MODE; + Keyboard_Info.Win_Lock = INIT_WIN_NLOCK; + } else if ((Keyboard_Info.Key_Mode == 0) && (Keyboard_Info.Ble_Channel == 0) && (Keyboard_Info.Batt_Number == 0) && (Keyboard_Info.Nkro == 0) && (Keyboard_Info.Mac_Win_Mode == 0) && (Keyboard_Info.Win_Lock == 0)) { + Keyboard_Info.Key_Mode = INIT_WORK_MODE; + Keyboard_Info.Ble_Channel = INIT_BLE_CHANNEL; + Keyboard_Info.Batt_Number = INIT_BATT_NUMBER; + Keyboard_Info.Nkro = INIT_ALL_KEY; + Keyboard_Info.Mac_Win_Mode = INIT_WIN_MODE; + Keyboard_Info.Win_Lock = INIT_WIN_NLOCK; + } else { + if (Keyboard_Info.Key_Mode > QMK_USB_MODE) { + Keyboard_Info.Key_Mode = QMK_USB_MODE; + } + + if (Keyboard_Info.Ble_Channel > QMK_BLE_CHANNEL_3) { + Keyboard_Info.Ble_Channel = QMK_BLE_CHANNEL_3; + } + + if (Keyboard_Info.Batt_Number > 100) { + Keyboard_Info.Batt_Number = 100; + } + + if (Keyboard_Info.Nkro > INIT_ALL_KEY) { + Keyboard_Info.Nkro = INIT_ALL_KEY; + } + + if (Keyboard_Info.Mac_Win_Mode > INIT_MAC_MODE) { + Keyboard_Info.Mac_Win_Mode = INIT_WIN_MODE; + } + + if (Keyboard_Info.Win_Lock > INIT_WIN_LOCK) { + Keyboard_Info.Win_Lock = INIT_WIN_NLOCK; + } + } +} + +void es_change_qmk_nkro_mode_enable(void) { + if(!keymap_config.nkro) { + clear_keyboard(); // clear first buffer to prevent stuck keys + keymap_config.nkro = true; + + Keyboard_Info.Nkro = keymap_config.nkro; + Save_Flash_Set(); + } +} + +void es_change_qmk_nkro_mode_disable(void) { + if(keymap_config.nkro) { + clear_keyboard(); // clear first buffer to prevent stuck keys + keymap_config.nkro = false; + + Keyboard_Info.Nkro = keymap_config.nkro; + Save_Flash_Set(); + } +} diff --git a/keyboards/womier/common/rdmctmzt_common.h b/keyboards/womier/common/rdmctmzt_common.h new file mode 100644 index 00000000000..f76a01defd5 --- /dev/null +++ b/keyboards/womier/common/rdmctmzt_common.h @@ -0,0 +1,198 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 +#include +#include "quantum.h" +#include "quantum_keycodes.h" +#include "dynamic_keymap.h" +#include "md_adc.h" +#include "usb_main.h" +#include "raw_hid.h" +#include "usb_descriptor.h" + +#include "three_mode.h" +#include "user_battery.h" +#include "user_eeprom.h" +#include "user_emi.h" +#include "user_led_custom.h" +#include "user_spi.h" +#include "user_system.h" + +#define ES_BATT_ADC_IO (C4) +#define ES_BATT_STDBY_IO (A13) +#define ES_USB_POWER_IO (C5) +#define ES_SPI_ACK_IO (A4) +#define ES_PWM_DMA_IO (A2) + +#define ES_WUKEUP_IO (D1) +#define ES_SDB_POWER_IO (A3) +#define ES_LED_POWER_IO (D0) + +#define PAL_ES32_PUPDR_PULLDOWN PAL_ES32_PUD_PULLDOWN + +#define USER_KEY_BYTE_LENGTH 0X08 +#define USER_KEY_BIT_LENGTH 0X0F +#define USER_MOUSE_LENGTH 0X08 +#define USER_CONSUMER_LENGTH 0X03 +#define USER_SYSTEM_LENGTH 0X03 +#define USER_BATTERY_LENGTH 0X02 + +#define KB_REPORT_ID 0x06 // Extend keyboard report ID. +#define SYS_REPORT_ID 0x03 // Extend System report ID. +#define CON_REPORT_ID 0x04 // Extend Consumer report ID. +#define MOUSE_REPORT_ID 0x02 // Extend mouse report ID. + +#define USER_DEFINE_KEY (QK_KB) +enum Custom_Keycodes { + QMK_KB_MODE_2P4G = USER_DEFINE_KEY, + QMK_KB_MODE_BLE1, + QMK_KB_MODE_BLE2, + QMK_KB_MODE_BLE3, + QMK_KB_MODE_USB, + QMK_BATT_NUM, + QMK_WIN_LOCK, + QMK_KB_SIX_N_CH, + QMK_TEST_COLOUR, + QMK_KB_2P4G_PAIR, + QMK_KB_BLE1_PAIR, + QMK_KB_BLE2_PAIR, + QMK_KB_BLE3_PAIR +}; + +enum Custom_KeyModes { + QMK_BLE_MODE = 0, + QMK_2P4G_MODE, + QMK_USB_MODE +}; + +enum Custom_BleChannels { + QMK_BLE_CHANNEL_1 = 1, + QMK_BLE_CHANNEL_2, + QMK_BLE_CHANNEL_3 +}; + +enum Custom_Ble_24G_Status_S { + BLE_24G_NONE, + BLE_24G_PIAR, + BLE_24G_RETURN +}; + +typedef struct { + uint8_t Key_Mode; + uint8_t Ble_Channel; + uint8_t Batt_Number; + uint8_t Nkro; + uint8_t Mac_Win_Mode; + uint8_t Win_Lock; +} Keyboard_Info_t; + +typedef struct { + uint8_t System_Work_Status; + uint8_t System_Work_Mode; + uint8_t System_Work_Channel; + uint8_t System_Connect_Status; + uint8_t System_Led_Status; + uint8_t System_Sleep_Mode; +} Keyboard_Status_t; + +typedef enum { + KB_MODE_CONNECT_OK, + KB_MODE_CONNECT_PAIR, + KB_MODE_CONNECT_RETURN, +} keyboard_System_state_e; + +typedef enum { + USER_SLEEP_PASS, + USER_SLEEP_FIAL, +} keyboard_System_Sleep_Status_s; + +#define INIT_WORK_MODE (QMK_USB_MODE) +#define INIT_BLE_CHANNEL (QMK_BLE_CHANNEL_1) +#define INIT_BATT_NUMBER (50) + +#define INIT_SIX_KEY (0) +#define INIT_ALL_KEY (1) +#define INIT_ALL_SIX_KEY (INIT_ALL_KEY) + +#define INIT_WIN_MODE (0) +#define INIT_MAC_MODE (1) +#define INIT_WIN_MAC_MODE (INIT_WIN_MODE) + +#define INIT_WIN_NLOCK (0) +#define INIT_WIN_LOCK (1) +#define INIT_WIN_LOCK_NLOCK (INIT_WIN_NLOCK) + +#define U_PWM (RGB_MATRIX_MAXIMUM_BRIGHTNESS) + +#define USER_BATT_DELAY_TIME (100 * 25) //25S +#define USER_TIME_3S_TIME (100 * 3) //3S + +#define KC_K29 KC_BACKSLASH +#define KC_K42 KC_NONUS_HASH +#define KC_K45 KC_NONUS_BACKSLASH +#define KC_K56 KC_INTERNATIONAL_1 +#define KC_K14 KC_INTERNATIONAL_3 +#define KC_K132 KC_INTERNATIONAL_4 +#define KC_K131 KC_INTERNATIONAL_5 +#define KC_K133 KC_INTERNATIONAL_2 +#define KC_K151 KC_LANGUAGE_1 +#define KC_K150 KC_LANGUAGE_2 + +#define MD_24G QMK_KB_MODE_2P4G +#define MD_BLE1 QMK_KB_MODE_BLE1 +#define MD_BLE2 QMK_KB_MODE_BLE2 +#define MD_BLE3 QMK_KB_MODE_BLE3 +#define MD_USB QMK_KB_MODE_USB +#define QK_BAT QMK_BATT_NUM +#define QK_WLO QMK_WIN_LOCK +#define SIX_N QMK_KB_SIX_N_CH +#define TEST_CL QMK_TEST_COLOUR + +extern Keyboard_Info_t Keyboard_Info; +extern Keyboard_Status_t Keyboard_Status; + +extern const uint32_t g_es_dma_ch2pri_cfg; +extern const uint32_t g_es_dma_ch2alt_cfg; + +extern bool Led_Rf_Pair_Flg; +extern bool Key_2p4g_Status; +extern bool Key_Ble_1_Status; +extern bool Key_Ble_2_Status; +extern bool Key_Ble_3_Status; +extern bool Key_Reset_Status; +extern bool Keyboard_Reset; +extern bool Init_Eeprom_Flg; +extern bool Led_Off_Start; +extern bool Led_Power_Up; +extern bool Usb_If_Ok_Led; +extern uint16_t Led_Power_Up_Delay; +extern uint8_t Temp_System_Led_Status; + +extern uint8_t Systick_6ms_Count; +extern uint8_t Systick_10ms_Count; +extern uint16_t Systick_Interval_Count; +extern uint8_t Systick_Led_Count; +extern uint8_t Batt_Led_Count; +extern uint16_t Time_3s_Count; +extern uint16_t Func_Time_3s_Count; + +extern void Init_Keyboard_Infomation(void); +extern void es_change_qmk_nkro_mode_enable(void); +void es_change_qmk_nkro_mode_disable(void); diff --git a/keyboards/womier/common/three_mode.c b/keyboards/womier/common/three_mode.c new file mode 100644 index 00000000000..06756db487c --- /dev/null +++ b/keyboards/womier/common/three_mode.c @@ -0,0 +1,209 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 "rdmctmzt_common.h" + +uint16_t Usb_Suspend_Delay = 0; +uint16_t Usb_Change_Mode_Delay = 0; +bool Usb_Change_Mode_Wakeup = false; +bool Mode_Synchronization_Signal = false; + +uint16_t g_usb_sof_frame_id = 0; +uint16_t g_usb_sof_frame_id_last = 0; +bool Usb_Dis_Connect = false; + +void Mode_Synchronization(void) { + switch(Keyboard_Info.Key_Mode) { + case QMK_BLE_MODE: { + switch (Keyboard_Info.Ble_Channel) { + case QMK_BLE_CHANNEL_1: Spi_Send_Commad(USER_SWITCH_BLE_1_MODE); break; + case QMK_BLE_CHANNEL_2: Spi_Send_Commad(USER_SWITCH_BLE_2_MODE); break; + case QMK_BLE_CHANNEL_3: Spi_Send_Commad(USER_SWITCH_BLE_3_MODE); break; + default: break; + } + break; + } + case QMK_2P4G_MODE: Spi_Send_Commad(USER_SWITCH_2P4G_MODE); break; + case QMK_USB_MODE: Spi_Send_Commad(USER_SWITCH_USB_MODE); break; + default: break; + } +} + +void Ble_Name_Synchronization(void) { + switch(Ble_Name_Spi_Count) { + case QMK_BLE_CHANNEL_1: Spi_Send_Commad(USER_BLE1_WRITE_NAME); Ble_Name_Spi_Count++; break; + case QMK_BLE_CHANNEL_2: Spi_Send_Commad(USER_BLE2_WRITE_NAME); Ble_Name_Spi_Count++; break; + case QMK_BLE_CHANNEL_3: Spi_Send_Commad(USER_BLE3_WRITE_NAME); Ble_Name_Spi_Count++; break; + default: break; + } + + if(Ble_Name_Spi_Count > QMK_BLE_CHANNEL_3) { + Ble_Name_Spi_Count = QMK_BLE_CHANNEL_1; + Ble_Name_Spi_Send = false; + } +} + +uint8_t es_keyboard_leds(void) { + switch (Keyboard_Info.Key_Mode) { + case QMK_2P4G_MODE: break; + case QMK_BLE_MODE: break; + case QMK_USB_MODE: break; + default: break; + } + + if(es_qmk_driver) { + return((*es_qmk_driver->keyboard_leds)()); + } + + return 0; +} + +void es_send_keyboard(report_keyboard_t *report) { + switch (Keyboard_Info.Key_Mode) { + case QMK_2P4G_MODE: User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_keyboard_t)); break; + case QMK_BLE_MODE: User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_keyboard_t)); break; + case QMK_USB_MODE: break; + default: break; + } + + if(es_qmk_driver) { + (*es_qmk_driver->send_keyboard)(report); + } +} + +void es_send_nkro(report_nkro_t *report) { + switch (Keyboard_Info.Key_Mode) { + case QMK_2P4G_MODE: User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_nkro_t)); break; + case QMK_BLE_MODE: User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_nkro_t)); break; + case QMK_USB_MODE: break; + default: break; + } + + if(es_qmk_driver) { + (*es_qmk_driver->send_nkro)(report); + } +} + +void es_send_mouse(report_mouse_t *report) { + switch (Keyboard_Info.Key_Mode) { + case QMK_2P4G_MODE: User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_mouse_t)); break; + case QMK_BLE_MODE: User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_mouse_t)); break; + case QMK_USB_MODE: break; + default: break; + } + + + if(es_qmk_driver) { + (*es_qmk_driver->send_mouse)(report); + } +} + +void es_send_extra(report_extra_t *report) { + switch (Keyboard_Info.Key_Mode) { + case QMK_2P4G_MODE: User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_extra_t)); break; + case QMK_BLE_MODE: User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_extra_t)); break; + case QMK_USB_MODE: break; + default: break; + } + + if(es_qmk_driver) { + (*es_qmk_driver->send_extra)(report); + } +} + +volatile host_driver_t * es_qmk_driver = NULL; +const host_driver_t es_user_driver = {es_keyboard_leds, es_send_keyboard, es_send_nkro, es_send_mouse, es_send_extra}; + +void User_bluetooth_send_keyboard(uint8_t *report, uint32_t len) { + if(app_2g4_buffer_full()) { + return; + } + + if (len > USER_KEYBOARD_LENGTH - 3) { + len = USER_KEYBOARD_LENGTH - 3; + } + + uint8_t Temp_Tx_Buf[USER_KEYBOARD_LENGTH] = {0}; + + Temp_Tx_Buf[0] = USER_KEYBOARD_COMMAND; + Temp_Tx_Buf[1] = USER_KEYBOARD_LENGTH; + + if (len == sizeof(report_keyboard_t)) { //六键 + memcpy((void *)&Temp_Tx_Buf[3], report, len); + Temp_Tx_Buf[2] = USER_KEY_BYTE_DATA; + } else { + switch (report[0]) { + case KB_REPORT_ID: { //全键 + memcpy((void *)&Temp_Tx_Buf[3], report, len); + Temp_Tx_Buf[2] = USER_KEY_BIT_DATA; + break; + } + case SYS_REPORT_ID: { //系统键 + memcpy((void *)&Temp_Tx_Buf[3], report, len); + Temp_Tx_Buf[2] = USER_SYSTEM_DATA; + break; + } + case CON_REPORT_ID: { //多媒体键 + memcpy((void *)&Temp_Tx_Buf[3], report, len); + Temp_Tx_Buf[2] = USER_CONSUMER_DATA; + break; + } + case MOUSE_REPORT_ID: { //鼠标 + memcpy((void *)&Temp_Tx_Buf[3], report, len); + Temp_Tx_Buf[2] = USER_MOUSE_DATA; + break; + } + default: { + break; + } + } + } + + memcpy(app_2g4_data[app_2g4_data_rev], Temp_Tx_Buf, USER_KEYBOARD_LENGTH); + app_2g4_buffer_rev_add(); +} + +void User_Usb_Init(void) { + /*Using USB_SOF to calibrate the internal clock*/ + md_rcu_enable_csu(RCU); + CSU->CON |= CSU_CON_AUTOEN_MSK; + CSU->CON |= CSU_CON_CNTEN_MSK; +} + +void es_restart_usb_driver(void) { + md_rcu_enable_usb(RCU); + ald_usb_device_components_init(); + USB->TXIER = 0x7F; + USB->RXIER = 0x7E; + USB->IER = 0x2F; + usb_lld_connect_bus(0); + ald_usb_int_register(); +} + +void Usb_Disconnect(void) { + ald_usb_int_unregister(); + usb_lld_disconnect_bus(0); + + md_rcu_enable_usb_reset(RCU); + md_rcu_disable_usb_reset(RCU); + md_rcu_disable_usb(RCU); +} + +void User_Usb_Deinit(void) { + md_rcu_enable_csu_reset(RCU); + md_rcu_disable_csu_reset(RCU); + md_rcu_disable_csu(RCU); +} diff --git a/keyboards/womier/common/three_mode.h b/keyboards/womier/common/three_mode.h new file mode 100644 index 00000000000..c9969ad8fbe --- /dev/null +++ b/keyboards/womier/common/three_mode.h @@ -0,0 +1,45 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 uint16_t Usb_Suspend_Delay; +extern uint16_t Usb_Change_Mode_Delay; +extern bool Usb_Change_Mode_Wakeup; +extern bool Mode_Synchronization_Signal; + +extern uint16_t g_usb_sof_frame_id; +extern uint16_t g_usb_sof_frame_id_last; +extern bool Usb_Dis_Connect; + +extern void Mode_Synchronization(void); +extern void Ble_Name_Synchronization(void); + +extern uint8_t es_keyboard_leds(void); +extern void es_send_keyboard(report_keyboard_t *report); +extern void es_send_nkro(report_nkro_t *report); +extern void es_send_mouse(report_mouse_t *report); +extern void es_send_extra(report_extra_t *report); +extern void User_bluetooth_send_keyboard(uint8_t *report, uint32_t len); + +extern volatile host_driver_t * es_qmk_driver; +extern const host_driver_t es_user_driver; + +extern void User_Usb_Init(void); +extern void es_restart_usb_driver(void); +extern void Usb_Disconnect(void); +extern void User_Usb_Deinit(void); diff --git a/keyboards/womier/common/user_battery.c b/keyboards/womier/common/user_battery.c new file mode 100644 index 00000000000..d713d2b56d5 --- /dev/null +++ b/keyboards/womier/common/user_battery.c @@ -0,0 +1,418 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 "rdmctmzt_common.h" + +uint16_t User_Adc_Batt[USER_BATT_SCAN_COUNT] = {0}; +uint16_t User_Scan_Batt[USER_BATT_SCAN_COUNT] = {0}; +uint8_t User_Adc_Batt_Count = 0U; +uint8_t User_Batt_BaiFen = 0U; +uint8_t User_Batt_Old_BaiFen = 0U; +uint8_t User_Batt_10ms_Count = 0x00; +uint16_t User_Batt_Time_15S_Count = 0U; +bool User_Batt_Power_Up = false; +bool User_Batt_Send_Spi = false; +uint16_t User_Batt_Power_Up_Delay_100ms_Count = 0U; +bool User_Batt_Power_Up_Delay = false; + +bool User_Power_Low = false; +uint8_t User_Power_Low_Count = 0U; +uint8_t es_stdby_pin_state = 0U; + + +const md_adc_initial adc_initStruct = /**< ADC init structure */ +{ + MD_ADC_CFG_ALIGN_RIGHT, //Data alignment + MD_ADC_CFG_RSEL_12BIT, //Data resolution + MD_ADC_MODE_NCHS, //Regular or Injected + MD_ADC_CFG_CM_SINGLE, //Single mode + MD_ADC_NCHS1_NSL_1CON, //sample count + MD_ADC_SMPT1_CKDIV_DIV6, //ADC prescale +}; + +ErrorStatus rdmctmzt_adc_software_calibration(ADC_TypeDef *ADCx, md_adc_initial *ADC_InitStruct) { + //ADC input APB clock 12MHz + uint8_t clkdiv = 8; + uint16_t adc_data_1 = 0; + uint16_t adc_data_15 = 0; + + int16_t adc_offset = 0; + uint16_t adc_gain = 0; + + float temp_adc_offset = 0.0f; + + md_syscfg_set_vref_source(SYSCFG, MD_SYSCFG_PWR_VDDA); // VRES choose VDDA + md_syscfg_enable_vref(SYSCFG); + + //ADC Setting + md_adc_set_convsersion_mode(ADC, MD_ADC_CFG_CM_SINGLE); // 1:Continuous + md_adc_set_resolution_selection(ADC, MD_ADC_CFG_RSEL_12BIT); // 12-bit resolution + md_adc_set_normal_sequence_selection_1th(ADC, MD_ADC_NCHS1_NS1_CH18); // channel number(16:Temperature) + md_adc_set_adc_clock_predivider(ADC, ADC_InitStruct->CKDIV); + + if (ADC_InitStruct->CKDIV == MD_ADC_SMPT1_CKDIV_DIV1) { + clkdiv = 1; + } else if (ADC_InitStruct->CKDIV == MD_ADC_SMPT1_CKDIV_DIV2){ + clkdiv = 2; + } else if (ADC_InitStruct->CKDIV == MD_ADC_SMPT1_CKDIV_DIV4){ + clkdiv = 4; + } else if (ADC_InitStruct->CKDIV == MD_ADC_SMPT1_CKDIV_DIV6){ + clkdiv = 6; + } else if (ADC_InitStruct->CKDIV == MD_ADC_SMPT1_CKDIV_DIV8){ + clkdiv = 8; + } + + if ((SystemFrequency_APBClk / clkdiv) <= 12000000) { + md_adc_set_sampletime_channel_18(ADCx, 0x40); //Sample Time Cycle + } else { + md_adc_set_sampletime_channel_18(ADCx, 0x80); //Sample Time Cycle + } + + //CLEAR CALCR + md_adc_set_gain_factor(ADCx, 1024); + md_adc_set_offset_factor(ADCx, 0); + + //ADC ENABLE + md_adc_enable_adcpower(ADCx); + + while (!md_adc_is_active_flag_adc_ready(ADCx)); + + // -------------------------------------------------------- + // 1/16 Sample + md_adc_set_vref_level(ADCx, MD_ADC_CCR_REFINTS_1DIV16); + md_adc_set_start_normal(ADCx, MD_ADC_CON_NSTART_START_REGULAR); + + while (md_adc_is_active_flag_normal_status(ADCx)); + + adc_data_1 = md_adc_get_normal_data(ADCx); + + // -------------------------------------------------------- + // 15/16 Sample + md_adc_set_vref_level(ADCx, MD_ADC_CCR_REFINTS_15DIV16); + md_adc_set_start_normal(ADCx, MD_ADC_CON_NSTART_START_REGULAR); + + while (md_adc_is_active_flag_normal_status(ADCx)); + + adc_data_15 = md_adc_get_normal_data(ADCx); + + // -------------------------------------------------------- + temp_adc_offset = (float)((15 * adc_data_1) - adc_data_15) / 14; + + if (temp_adc_offset > 0) { + adc_offset = (int16_t)(temp_adc_offset + 0.5); + } else { + adc_offset = (int16_t)(temp_adc_offset - 0.5); + } + + adc_gain = (uint16_t)((3584 * 1024) / (float)(adc_data_15 - adc_data_1) + 0.5); + + md_adc_set_gain_factor(ADCx, adc_gain); + md_adc_set_offset_factor(ADCx, adc_offset); + + // -------------------------------------------------------- + md_adc_set_convsersion_mode(ADCx, 0); + md_adc_set_resolution_selection(ADCx, MD_ADC_CFG_RSEL_6BIT); + md_adc_set_normal_sequence_selection_1th(ADCx, MD_ADC_NCHS1_NS1_CH0); + md_adc_set_adc_clock_predivider(ADCx, MD_ADC_SMPT1_CKDIV_DIV1); + md_adc_set_sampletime_channel_18(ADCx, 0); + md_adc_set_icr(ADCx, 0xFFFE); + + return SUCCESS; +} + +ErrorStatus md_adc_optionbyte_calibration(ADC_TypeDef *ADCx, md_adc_initial *ADC_InitStruct) { + int8_t adc_offset = 0; + uint32_t adc_gain = 1024; + uint32_t cal_value = 0; + md_fc_read_info(ADC_CALIBRATION_ADDR, &cal_value); + + adc_gain = (cal_value & 0xFFF); + adc_offset = (cal_value >> 16) & 0xFF; + + //ADC ENABLE + md_adc_enable_adcpower(ADCx); + md_adc_set_gain_factor(ADCx, adc_gain); + md_adc_set_offset_factor(ADCx, adc_offset); + return SUCCESS; +} + +ErrorStatus rdmctmzt_adc_calibration(ADC_TypeDef *ADCx, md_adc_initial *ADC_InitStruct) { + uint32_t cal_value = 0; + md_fc_read_info(ADC_CALIBRATION_ADDR, &cal_value); + + if (cal_value == 0xFFFFFFFF) { + return rdmctmzt_adc_software_calibration(ADCx, ADC_InitStruct); + } else { + return md_adc_optionbyte_calibration(ADCx, ADC_InitStruct); + } +} + +void md_adc_init(ADC_TypeDef *ADCx, md_adc_initial *ADC_InitStruct) { + while (md_adc_is_enabled_calibration(ADCx)); + + md_adc_set_adc_clock_predivider(ADC, ADC_InitStruct->CKDIV); + + md_adc_enable_adcpower(ADCx); + + while (!md_adc_is_active_flag_adc_ready(ADCx)); + + while ((md_adc_get_start_inj(ADCx) == MD_ADC_CON_ISTART_START_INJECTED)); + + while ((md_adc_get_start_normal(ADCx) == MD_ADC_CON_NSTART_START_REGULAR)); + + md_adc_set_data_alignment(ADCx, ADC_InitStruct->ALIGN); + md_adc_set_resolution_selection(ADCx, ADC_InitStruct->RSEL); + md_adc_set_convsersion_mode(ADCx, ADC_InitStruct->Regular_CM); + +#ifdef ADC_DMA + md_adc_enable_dma_access(ADCx); +#else + md_adc_disable_dma_access(ADCx); +#endif + +} + +void User_Adc_Init(void) { //ES_BATT_ADC_IO + md_gpio_inittypedef gpiox; + + gpiox.OutputType = MD_GPIO_OUTPUT_PUSHPULL; + gpiox.Pull = MD_GPIO_PULL_FLOATING; + gpiox.OutDrive = MD_GPIO_DRIVING_8MA; + gpiox.Function = MD_GPIO_AF0; + gpiox.Mode = MD_GPIO_MODE_ANALOG; + gpiox.Pin = MD_GPIO_PIN_4; + md_gpio_init(GPIOC, &gpiox); + + md_rcu_enable_adc(RCU); + rdmctmzt_adc_calibration(ADC, (md_adc_initial *)(&adc_initStruct)); + md_adc_set_sampletime_channel_14(ADC, 0x40); + md_adc_init(ADC, (md_adc_initial *)(&adc_initStruct)); + + while ((ADC->RIF & 0x1) == 0); + + md_adc_set_normal_sequence_length(ADC, adc_initStruct.Cnt); + md_adc_set_normal_sequence_selection_1th(ADC, MD_ADC_NCHS1_NS1_CH14); + md_adc_set_start_normal(ADC, MD_ADC_CON_NSTART_START_REGULAR); +} + +void User_Adc_Deinit(void) { + md_rcu_enable_adc_reset(RCU); + md_rcu_disable_adc_reset(RCU); + md_rcu_disable_adc(RCU); +} + +void U16_Buff_Clear(uint16_t *Buff, uint8_t Len) { + for(uint8_t i = 0; i < Len; i++) { + Buff[i] = 0; + } +} + +void Init_Batt_Infomation(void) { + if (gpio_read_pin(ES_USB_POWER_IO)) { + User_Batt_BaiFen = Keyboard_Info.Batt_Number; + User_Batt_Old_BaiFen = User_Batt_BaiFen; + User_Batt_Power_Up = false; + } else { + User_Batt_Power_Up = true; + } + User_Batt_10ms_Count = 0; + User_Adc_Batt_Count = 0; + User_Batt_Time_15S_Count = 0; + User_Power_Low = false; + User_Power_Low_Count = 0; + + U16_Buff_Clear(User_Adc_Batt, USER_BATT_SCAN_COUNT); + U16_Buff_Clear(User_Scan_Batt, USER_BATT_SCAN_COUNT); + + User_Batt_Power_Up_Delay_100ms_Count = 0; + User_Batt_Power_Up_Delay = true; +} + +void User_Adc_Batt_Power_Up_Init(void) { + uint8_t Min_Batt = 0, Max_Batt = 0; + for (uint8_t i = 0; i < USER_BATT_POWER_SCAN_COUNT; i++) { + if (User_Scan_Batt[Min_Batt] < User_Scan_Batt[i]) { + Min_Batt = i; + } + + if (User_Scan_Batt[Max_Batt] > User_Scan_Batt[i]) { + Max_Batt = i; + } + } + + uint16_t Temp_Batt_Sub = 0; + if (Min_Batt == Max_Batt) { + for (uint8_t i = 0; i < (USER_BATT_POWER_SCAN_COUNT - 2); i++) { + Temp_Batt_Sub += User_Scan_Batt[i]; + } + } else { + for (uint8_t i = 0; i < USER_BATT_POWER_SCAN_COUNT; i++) { + if ((Min_Batt == i) || (Max_Batt == i)) { + continue; + } + Temp_Batt_Sub += User_Scan_Batt[i]; + } + } + + uint16_t Temp_Average = (Temp_Batt_Sub / (USER_BATT_POWER_SCAN_COUNT - 2)); + + uint8_t Temp_Batt_Number = 0; + if (Temp_Average >= USER_BATT_HIGH_POWER) { + Temp_Batt_Number = 100; + } else if (Temp_Average <= USER_BATT_STDOWN_POWER) { + Temp_Batt_Number = 0; + } else { + Temp_Batt_Number = (((Temp_Average - USER_BATT_STDOWN_POWER) * 100) / (USER_BATT_HIGH_POWER - USER_BATT_STDOWN_POWER)); + } + + if (Temp_Average <= USER_BATT_STDOWN_POWER) { + User_Power_Low_Count++; + if (User_Power_Low_Count >= 4) { + User_Power_Low_Count = 0; + User_Power_Low = true; + } + } else if (Temp_Average <= USER_BATT_LOW_POWER) { + User_Power_Low_Count++; + if (User_Power_Low_Count >= 10) { + User_Power_Low_Count = 0; + User_Power_Low = true; + } + } else { + User_Power_Low_Count = 0; + } + + User_Batt_BaiFen = Temp_Batt_Number; + User_Batt_Old_BaiFen = User_Batt_BaiFen; + + if (User_Batt_BaiFen != Keyboard_Info.Batt_Number) { + Keyboard_Info.Batt_Number = User_Batt_BaiFen; + Save_Flash_Set(); + } + + User_Adc_Batt_Count = 0; + User_Batt_10ms_Count = 0; + User_Batt_Time_15S_Count = 0; + User_Batt_Power_Up = false; +} + +void User_Adc_Batt_Number(void) { + if (es_stdby_pin_state == 2) { + User_Batt_BaiFen = 100; + User_Batt_Old_BaiFen = 100; + if (Keyboard_Info.Batt_Number != User_Batt_BaiFen) { + Keyboard_Info.Batt_Number = User_Batt_BaiFen; + User_Batt_Send_Spi = true; + Save_Flash_Set(); + } + User_Power_Low = false; + User_Power_Low_Count = 0; + return; + } + + uint8_t Min_Batt = 0, Max_Batt = 0; + for (uint8_t i = 0; i < USER_BATT_SCAN_COUNT; i++) { + if (User_Scan_Batt[Min_Batt] < User_Scan_Batt[i]) { + Min_Batt = i; + } + + if (User_Scan_Batt[Max_Batt] > User_Scan_Batt[i]) { + Max_Batt = i; + } + } + + uint16_t Temp_Batt_Sub = 0; + if (Min_Batt == Max_Batt) { + for (uint8_t i = 0; i < (USER_BATT_SCAN_COUNT - 2); i++) { + Temp_Batt_Sub += User_Scan_Batt[i]; + } + } else { + for (uint8_t i = 0; i < USER_BATT_SCAN_COUNT; i++) { + if ((Min_Batt == i) || (Max_Batt == i)) { + continue; + } + Temp_Batt_Sub += User_Scan_Batt[i]; + } + } + + uint16_t Temp_Average = (Temp_Batt_Sub / (USER_BATT_SCAN_COUNT - 2)); + + uint8_t Temp_Batt_Number = 0; + if (Temp_Average >= USER_BATT_HIGH_POWER) { + Temp_Batt_Number = 100; + } else if (Temp_Average <= USER_BATT_STDOWN_POWER) { + Temp_Batt_Number = 0; + } else { + Temp_Batt_Number = (((Temp_Average - USER_BATT_STDOWN_POWER) * 100) / (USER_BATT_HIGH_POWER - USER_BATT_STDOWN_POWER)); + } + + if (es_stdby_pin_state == 1) { + if (Temp_Batt_Number >= 100) { + Temp_Batt_Number = 99; + } else if (Temp_Batt_Number <= 0) { + Temp_Batt_Number = 1; + } + } else { + if (Temp_Average <= USER_BATT_STDOWN_POWER) { + User_Power_Low_Count++; + if (User_Power_Low_Count >= 5) { + User_Power_Low_Count = 0; + User_Power_Low = true; + } + } else if (Temp_Average <= USER_BATT_LOW_POWER) { + User_Power_Low_Count++; + if (User_Power_Low_Count >= 10) { + User_Power_Low_Count = 0; + User_Power_Low = true; + } + } else { + User_Power_Low_Count = 0; + } + } + + if (es_stdby_pin_state) { + if (Temp_Batt_Number > User_Batt_Old_BaiFen) { + if (User_Batt_Time_15S_Count >= USER_BATT_DELAY_TIME) { + User_Batt_Time_15S_Count = 0; + if (User_Batt_BaiFen <= 98) { + User_Batt_BaiFen++; + } + User_Batt_Old_BaiFen = User_Batt_BaiFen; + } + } else { + User_Batt_Time_15S_Count = 0; + } + User_Power_Low = false; + User_Power_Low_Count = 0; + } else { + if (Temp_Batt_Number < User_Batt_Old_BaiFen) { + if (User_Batt_Time_15S_Count >= USER_BATT_DELAY_TIME) { + User_Batt_Time_15S_Count = 0; + if (User_Batt_BaiFen) { + User_Batt_BaiFen--; + } + User_Batt_Old_BaiFen = User_Batt_BaiFen; + } + } else { + User_Batt_Time_15S_Count = 0; + } + } + + if (Keyboard_Info.Batt_Number != User_Batt_BaiFen) { + Keyboard_Info.Batt_Number = User_Batt_BaiFen; + User_Batt_Send_Spi = true; + Save_Flash_Set(); + } +} \ No newline at end of file diff --git a/keyboards/womier/common/user_battery.h b/keyboards/womier/common/user_battery.h new file mode 100644 index 00000000000..0380e9a5549 --- /dev/null +++ b/keyboards/womier/common/user_battery.h @@ -0,0 +1,51 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 USER_BATT_HIGH_POWER (2555) +#define USER_BATT_LOW_POWER (2065) +#define USER_BATT_STDOWN_POWER (1865) + +#define USER_BATT_POWER_SCAN_COUNT (10) +#define USER_BATT_SCAN_COUNT (10) + +extern uint16_t User_Adc_Batt[USER_BATT_SCAN_COUNT]; +extern uint16_t User_Scan_Batt[USER_BATT_SCAN_COUNT]; +extern uint8_t User_Adc_Batt_Count; +extern uint8_t User_Batt_BaiFen; +extern uint8_t User_Batt_Old_BaiFen; +extern uint8_t User_Batt_10ms_Count; +extern uint16_t User_Batt_Time_15S_Count; +extern bool User_Batt_Power_Up; +extern bool User_Batt_Send_Spi; +extern uint16_t User_Batt_Power_Up_Delay_100ms_Count; +extern bool User_Batt_Power_Up_Delay; + +extern bool User_Power_Low; +extern uint8_t User_Power_Low_Count; +extern uint8_t es_stdby_pin_state; + +extern const md_adc_initial adc_initStruct; + +extern void User_Adc_Init(void); +extern void User_Adc_Deinit(void); + +extern void U16_Buff_Clear(uint16_t *Buff, uint8_t Len); +extern void Init_Batt_Infomation(void); +extern void User_Adc_Batt_Power_Up_Init(void); +extern void User_Adc_Batt_Number(void); \ No newline at end of file diff --git a/keyboards/womier/common/user_eeprom.c b/keyboards/womier/common/user_eeprom.c new file mode 100644 index 00000000000..5c23a1e0041 --- /dev/null +++ b/keyboards/womier/common/user_eeprom.c @@ -0,0 +1,630 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 "rdmctmzt_common.h" + +#if defined(EEPROM_CUSTOM) +/* Exported Constants --------------------------------------------------------*/ +/* Define the size of the sectors to be used */ +#define MCU_PAGE_SIZE (uint32_t)0x200 /* MCU page size = 0.5kB */ +#define PAGE_SIZE (uint32_t)0x2000 /* Page size = 8kB */ +#define MCU_PAGE_NUM PAGE_SIZE / MCU_PAGE_SIZE + +/* EEPROM start address in Flash */ +#define EEPROM_START_ADDRESS ((uint32_t)0x1C000) + +/* Pages 0 and 1 base and end addresses */ +#define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS)) +#define PAGE0_END_ADDRESS ((uint32_t)(PAGE0_BASE_ADDRESS + (PAGE_SIZE - 1))) + +#define PAGE1_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + PAGE_SIZE)) +#define PAGE1_END_ADDRESS ((uint32_t)(PAGE1_BASE_ADDRESS + (PAGE_SIZE - 1))) + +/* Used Flash pages for EEPROM emulation */ +#define PAGE0 ((uint32_t)0x00000000) +#define PAGE1 ((uint32_t)0x00000001) + +/* No valid page define */ +#define NO_VALID_PAGE ((uint32_t)0x000000AB) + +/* Page status definitions */ +#define ERASED ((uint32_t)0xFFFFFFFF) /* Page is empty */ +#define RECEIVE_DATA ((uint32_t)0xEEEEEEEE) /* Page is marked to receive data */ +#define VALID_PAGE ((uint32_t)0x00000000) /* Page containing valid data */ + +/* Valid pages in read and write defines */ +#define READ_FROM_VALID_PAGE ((uint8_t)0x00) +#define WRITE_IN_VALID_PAGE ((uint8_t)0x01) + +/* Page full define */ +#define PAGE_FULL ((uint8_t)0x80) + +/* Variables' number */ +#define NB_OF_VAR (EEPROM_SIZE) +#define NB_OF_PRIVATE_VAR (64) + +#define ES_MCU_MEM_REMAP_OFFSET ((((SYSCFG->REMAP)&SYSCFG_REMAP_REALBASE_MSK) >> SYSCFG_REMAP_REALBASE_POSS) << 12) + +//__attribute__((aligned(4))) static uint8_t g_es_flash_eeprom_table[EEPROM_SIZE + 2]; +__attribute__((aligned(4))) static uint8_t g_es_flash_eeprom_table[EEPROM_SIZE + NB_OF_PRIVATE_VAR + 2]; + +volatile uint32_t g_tst_remap_offset; + +static uint32_t ee_format(void); +static uint32_t ee_find_valid_page(uint8_t operation); +static uint32_t ee_verify_pagefull_write_variable(uint32_t virt_address, uint32_t data); +static uint32_t ee_page_transfer(uint32_t virt_address, uint32_t data); + +static uint32_t IAPROM_PAGE_ERASE(uint32_t addr) +{ + md_fc_ControlTypeDef SErasePara; + + if ((addr & 0x1ff) != 0) + { + return !SET; + } + + __disable_irq(); + + md_fc_unlock(); + + SErasePara.SAddr = addr; + SErasePara.SAddrC = ~(addr); + + md_fc_page_erase(&SErasePara); + + md_fc_lock(); + + __enable_irq(); + + return SET; +} + +static uint32_t IAPROM_WORD_PROGRAM(uint32_t addr,uint32_t data) +{ + md_fc_ControlTypeDef ProgramPara; + + if ((addr & 0x3) != 0) + { + return !SET; + } + + if ((((uint32_t)(&data)) & 0x3) != 0) + { + return !SET; + } + + __disable_irq(); + + md_fc_unlock(); + + ProgramPara.BCnt = 4; + ProgramPara.pU32Buf = &data; + ProgramPara.SAddr = addr; + ProgramPara.SAddrC = ~(addr); + + md_fc_program(&ProgramPara); + + md_fc_lock(); + + __enable_irq(); + + return SET; +} + +static uint32_t ee_init(void) +{ + uint32_t page_status0 = 6U, page_status1 = 6U; + uint32_t var_idx = 0U; + uint32_t eeprom_status = 0U; + uint32_t flash_status; + uint8_t addr_index; + uint32_t rom_read_end; + + /* Get Page0 status */ + page_status0 = (*(__IO uint32_t *)(PAGE0_BASE_ADDRESS - ES_MCU_MEM_REMAP_OFFSET)); + /* Get Page1 status */ + page_status1 = (*(__IO uint32_t *)(PAGE1_BASE_ADDRESS - ES_MCU_MEM_REMAP_OFFSET)); + + if(page_status0 == VALID_PAGE) + { + rom_read_end = PAGE0_END_ADDRESS - ES_MCU_MEM_REMAP_OFFSET; + for(var_idx = PAGE0_BASE_ADDRESS - ES_MCU_MEM_REMAP_OFFSET + 4;var_idx < rom_read_end;var_idx += 4) + { + if(((*(__IO uint32_t *)var_idx) >> 16) < NB_OF_VAR) + { + *(((uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + ((*(__IO uint32_t *)var_idx) >> 16)) = (*(__IO uint32_t *)var_idx) & 0xFFFF; + } + else + { + break; + } + } + } + + if(page_status1 == VALID_PAGE) + { + rom_read_end = PAGE1_END_ADDRESS - ES_MCU_MEM_REMAP_OFFSET; + for(var_idx = PAGE1_BASE_ADDRESS - ES_MCU_MEM_REMAP_OFFSET + 4;var_idx < rom_read_end;var_idx += 4) + { + if(((*(__IO uint32_t *)var_idx) >> 16) < NB_OF_VAR) + { + *(((uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + ((*(__IO uint32_t *)var_idx) >> 16)) = (*(__IO uint32_t *)var_idx) & 0xFFFF; + } + else + { + break; + } + } + } + + /* Check for invalid header states and repair if necessary */ + switch (page_status0) + { + case ERASED: + if (page_status1 == VALID_PAGE) /* Page0 erased, Page1 valid */ + { + /* Erase Page0 */ + for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++) + { + IAPROM_PAGE_ERASE(PAGE0_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE); + } + } + else if (page_status1 == RECEIVE_DATA) /* Page0 erased, Page1 receive */ + { + /* Erase Page0 */ + for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++) + { + IAPROM_PAGE_ERASE(PAGE0_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE); + } + + IAPROM_WORD_PROGRAM(PAGE1_BASE_ADDRESS, VALID_PAGE); + } + else /* First EEPROM access (Page0&1 are erased) or invalid state -> format EEPROM */ + { + /* Erase both Page0 and Page1 and set Page0 as valid page */ + flash_status = ee_format(); + + if (flash_status != SET) + return flash_status; + } + + break; + + case RECEIVE_DATA: + if (page_status1 == VALID_PAGE) /* Page0 receive, Page1 valid */ + { + /* Transfer data from Page1 to Page0 */ + for (var_idx = 0; var_idx < (NB_OF_VAR / 2 + 1); var_idx++) + { + if((*(((__IO uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + var_idx)) != 0) + { + /* Transfer the variable to the Page0 */ + eeprom_status = ee_verify_pagefull_write_variable(var_idx, (*(((__IO uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + var_idx))); + + /* If program operation was failed, a Flash error code is returned */ + if (eeprom_status != SET) + return eeprom_status; + } + } + + IAPROM_WORD_PROGRAM(PAGE0_BASE_ADDRESS, VALID_PAGE); + + /* Erase Page1 */ + for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++) + { + IAPROM_PAGE_ERASE(PAGE1_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE); + } + } + else if (page_status1 == ERASED) /* Page0 receive, Page1 erased */ + { + /* Erase Page1 */ + for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++) + { + IAPROM_PAGE_ERASE(PAGE1_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE); + } + + IAPROM_WORD_PROGRAM(PAGE0_BASE_ADDRESS, VALID_PAGE); + } + else /* Invalid state -> format eeprom */ + { + flash_status = ee_format(); + if (flash_status != SET) + return flash_status; + } + + break; + + case VALID_PAGE: + if (page_status1 == VALID_PAGE) /* Invalid state -> format eeprom */ + { + flash_status = ee_format(); + if (flash_status != SET) + return flash_status; + } + else if (page_status1 == ERASED) /* Page0 valid, Page1 erased */ + { + for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++) + { + IAPROM_PAGE_ERASE(PAGE1_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE); + } + } + else /* Page0 valid, Page1 receive */ + { + /* Transfer data from Page0 to Page1 */ + for (var_idx = 0; var_idx < (NB_OF_VAR / 2 + 1); var_idx++) + { + if((*(((__IO uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + var_idx)) != 0) + { + /* Transfer the variable to the Page0 */ + eeprom_status = ee_verify_pagefull_write_variable(var_idx, (*(((__IO uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + var_idx))); + + /* If program operation was failed, a Flash error code is returned */ + if (eeprom_status != SET) + return eeprom_status; + } + } + + IAPROM_WORD_PROGRAM(PAGE1_BASE_ADDRESS, VALID_PAGE); + + for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++) + { + IAPROM_PAGE_ERASE(PAGE0_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE); + } + } + + break; + + default: /* Any other state -> format eeprom */ + flash_status = ee_format(); + if (flash_status != SET) + return flash_status; + + break; + } + + return SET; +} + +static uint32_t ee_write_variable(uint32_t virt_address) +{ + uint32_t status = 0U; + uint16_t data; + + if(virt_address >= NB_OF_VAR) + { + return !SET; + } + + virt_address = virt_address / 2; + + data = *(((uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + virt_address); + + /* Write the variable virtual address and value in the EEPROM */ + status = ee_verify_pagefull_write_variable(virt_address, data); + + /* In case the EEPROM active page is full */ + if (status == PAGE_FULL) + status = ee_page_transfer(virt_address, data); /* Perform Page transfer */ + + /* Return last operation status */ + return status; +} + +static uint32_t ee_format(void) +{ + uint32_t flash_status = SET; + uint8_t addr_index; + + /* Erase Page0 */ + for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++) + { + IAPROM_PAGE_ERASE(PAGE0_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE); + } + + /* Set Page0 as valid page: Write VALID_PAGE at Page0 base address */ + IAPROM_WORD_PROGRAM(PAGE0_BASE_ADDRESS, VALID_PAGE); + + /* Erase Page1 */ + for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++) + { + IAPROM_PAGE_ERASE(PAGE1_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE); + } + + /* Return Page1 erase operation status */ + return flash_status; +} + +static uint32_t ee_find_valid_page(uint8_t operation) +{ + uint32_t page_status0 = 6U, page_status1 = 6U; + + /* Get Page0 status */ + page_status0 = (*(__IO uint32_t *)(PAGE0_BASE_ADDRESS - ES_MCU_MEM_REMAP_OFFSET)); + /* Get Page1 status */ + page_status1 = (*(__IO uint32_t *)(PAGE1_BASE_ADDRESS - ES_MCU_MEM_REMAP_OFFSET)); + + /* Write or read operation */ + switch (operation) + { + case WRITE_IN_VALID_PAGE: /* ---- Write operation ---- */ + if (page_status1 == VALID_PAGE) + { + /* Page0 receiving data */ + if (page_status0 == RECEIVE_DATA) + return PAGE0; /* Page0 valid */ + else + return PAGE1; /* Page1 valid */ + } + else if (page_status0 == VALID_PAGE) + { + /* Page1 receiving data */ + if (page_status1 == RECEIVE_DATA) + return PAGE1; /* Page1 valid */ + else + return PAGE0; /* Page0 valid */ + } + else + { + return NO_VALID_PAGE; /* No valid Page */ + } + + case READ_FROM_VALID_PAGE: /* ---- Read operation ---- */ + if (page_status0 == VALID_PAGE) + return PAGE0; /* Page0 valid */ + else if (page_status1 == VALID_PAGE) + return PAGE1; /* Page1 valid */ + else + return NO_VALID_PAGE ; /* No valid Page */ + + default: + return PAGE0; /* Page0 valid */ + } +} + +static uint32_t ee_verify_pagefull_write_variable(uint32_t virt_address, uint32_t data) +{ + uint32_t flash_status = SET; + uint32_t valid_page = PAGE0; + uint32_t address = EEPROM_START_ADDRESS; + uint32_t page_endaddress = EEPROM_START_ADDRESS + PAGE_SIZE; + + /* Get valid Page for write operation */ + valid_page = ee_find_valid_page(WRITE_IN_VALID_PAGE); + + /* Check if there is no valid page */ + if (valid_page == NO_VALID_PAGE) + return NO_VALID_PAGE; + + /* Get the valid Page start address */ + address = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(valid_page * PAGE_SIZE)) - ES_MCU_MEM_REMAP_OFFSET; + + /* Get the valid Page end address */ + page_endaddress = (uint32_t)((EEPROM_START_ADDRESS - 4) + (uint32_t)((1 + valid_page) * PAGE_SIZE)) - ES_MCU_MEM_REMAP_OFFSET; + + /* Check each active page address starting from begining */ + while (address <= page_endaddress) + { + /* Verify if address and address+4 contents are 0xFFFFFFFF */ + if ((*(__IO uint32_t *)address) == 0xFFFFFFFF) + { + /* Set variable virtual address and data */ + flash_status = IAPROM_WORD_PROGRAM(address + ES_MCU_MEM_REMAP_OFFSET, (virt_address << 16) | data); + /* Return program operation status */ + return flash_status; + } + else + { + /* Next address location */ + address = address + 4; + } + } + + /* Return PAGE_FULL in case the valid page is full */ + return PAGE_FULL; +} + +static uint32_t ee_page_transfer(uint32_t virt_address, uint32_t data) +{ + uint32_t flash_status = SET; + uint32_t new_pageaddress = EEPROM_START_ADDRESS; + uint32_t old_pageaddress; + uint32_t valid_page = PAGE0, var_idx = 0U; + uint32_t eeprom_status = 0U; + uint8_t addr_index; + + /* Get active Page for read operation */ + valid_page = ee_find_valid_page(READ_FROM_VALID_PAGE); + + if (valid_page == PAGE1) /* Page1 valid */ + { + /* New page address where variable will be moved to */ + new_pageaddress = PAGE0_BASE_ADDRESS; + + /* Old page ID where variable will be taken from */ + old_pageaddress = PAGE1_BASE_ADDRESS; + } + else if (valid_page == PAGE0) /* Page0 valid */ + { + /* New page address where variable will be moved to */ + new_pageaddress = PAGE1_BASE_ADDRESS; + + /* Old page ID where variable will be taken from */ + old_pageaddress = PAGE0_BASE_ADDRESS; + } + else + { + return NO_VALID_PAGE; /* No valid Page */ + } + + /* Erase the new Page*/ + for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++) + { + IAPROM_PAGE_ERASE(new_pageaddress + addr_index * MCU_PAGE_SIZE); + } + + /* Set the new Page status to RECEIVE_DATA status */ + IAPROM_WORD_PROGRAM(new_pageaddress, RECEIVE_DATA); + + /* Write the variable passed as parameter in the new active page */ + eeprom_status = ee_verify_pagefull_write_variable(virt_address, data); + + /* If program operation was failed, a Flash error code is returned */ + if (eeprom_status != SET) + return eeprom_status; + + /* Transfer process: transfer variables from old to the new active page */ + //for (var_idx = 0; var_idx < NB_OF_VAR; var_idx++) + { + /* Transfer data from Page1 to Page0 */ + for (var_idx = 0; var_idx < (NB_OF_VAR / 2 + 1); var_idx++) + { + if((*(((__IO uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + var_idx)) != 0) + { + /* Transfer the variable to the Page0 */ + eeprom_status = ee_verify_pagefull_write_variable(var_idx, (*(((__IO uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + var_idx))); + + /* If program operation was failed, a Flash error code is returned */ + if (eeprom_status != SET) + return eeprom_status; + } + } + } + + /* Erase the old Page: Set old Page status to ERASED status */ + for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++) + { + IAPROM_PAGE_ERASE(old_pageaddress + addr_index * MCU_PAGE_SIZE); + } + + /* Set new Page status to VALID_PAGE status */ + IAPROM_WORD_PROGRAM(new_pageaddress, VALID_PAGE); + + /* Return last operation flash status */ + return flash_status; +} + +size_t clamp_length(intptr_t offset, size_t len) { + if (offset + len > EEPROM_SIZE) { + len = EEPROM_SIZE - offset; + } + + return len; +} + +size_t clamp_length_user(intptr_t offset, size_t len) { + if (offset + len > NB_OF_PRIVATE_VAR) { + len = NB_OF_PRIVATE_VAR - offset; + } + + return len; +} + +void eeprom_driver_erase(void) { + ee_format(); + memset(g_es_flash_eeprom_table, 0x00, sizeof(g_es_flash_eeprom_table)); +} + +#define USER_EEPROM_START_ADDRESS1 (EEPROM_START_ADDRESS - (MCU_PAGE_SIZE)) +volatile uint8_t es_eeprom_init_flag = 0U; + +void eeprom_driver_init(void) { + if(es_eeprom_init_flag) + return; + + g_tst_remap_offset = ES_MCU_MEM_REMAP_OFFSET; + (void)g_tst_remap_offset; + memset(g_es_flash_eeprom_table, 0x00, sizeof(g_es_flash_eeprom_table)); + ee_init(); + memcpy(g_es_flash_eeprom_table, (uint8_t*)(USER_EEPROM_START_ADDRESS1 - ES_MCU_MEM_REMAP_OFFSET), NB_OF_PRIVATE_VAR); + es_eeprom_init_flag = 1; +} + +void eeprom_read_block(void *buf, const void *addr, size_t len) { + intptr_t offset = (intptr_t)addr; + memset(buf, 0x00, len); + len = clamp_length(offset, len); + if (len > 0) { + memcpy(buf, &g_es_flash_eeprom_table[NB_OF_PRIVATE_VAR + offset], len); + } +} + +void eeprom_write_block(const void *buf, void *addr, size_t len) { + uint16_t i; + intptr_t offset = (intptr_t)addr; + len = clamp_length(offset, len); + if (len > 0) { + for(i = 0;i < len;i++) + { + if(g_es_flash_eeprom_table[i + offset + NB_OF_PRIVATE_VAR] != (*((uint8_t*)((uint32_t)buf) + i))) + { + g_es_flash_eeprom_table[i + offset + NB_OF_PRIVATE_VAR] = (*((uint8_t*)((uint32_t)buf) + i)); + ee_write_variable(i + offset + NB_OF_PRIVATE_VAR); + + } + } + + memcpy(&g_es_flash_eeprom_table[offset + NB_OF_PRIVATE_VAR], buf, len); + } +} + +void eeprom_read_block_user(void *buf, const void *addr, size_t len) { + intptr_t offset = (intptr_t)addr; + memset(buf, 0x00, len); + len = clamp_length_user(offset, len); + if (len > 0) { + memcpy(buf, (uint8_t*)(USER_EEPROM_START_ADDRESS1 - ES_MCU_MEM_REMAP_OFFSET) + offset, len); + } +} + +void eeprom_write_block_user(const void *buf, void *addr, size_t len) { + md_fc_ControlTypeDef ProgramPara; + intptr_t offset = (intptr_t)addr; + len = clamp_length_user(offset, len); + if (len > 0) { + __disable_irq(); + if(memcmp(buf,(uint8_t*)(USER_EEPROM_START_ADDRESS1 - ES_MCU_MEM_REMAP_OFFSET) + offset,len)) + { + memcpy(&g_es_flash_eeprom_table[offset], buf, len); + + md_fc_unlock(); + ProgramPara.SAddr = USER_EEPROM_START_ADDRESS1; + ProgramPara.SAddrC = ~(USER_EEPROM_START_ADDRESS1); + md_fc_page_erase(&ProgramPara); + md_fc_lock(); + + md_fc_unlock(); + ProgramPara.BCnt = NB_OF_PRIVATE_VAR; + ProgramPara.pU32Buf = (uint32_t*)(&g_es_flash_eeprom_table); + ProgramPara.SAddr = USER_EEPROM_START_ADDRESS1; + ProgramPara.SAddrC = ~(USER_EEPROM_START_ADDRESS1); + md_fc_program(&ProgramPara); + md_fc_lock(); + } + __enable_irq(); + } +} +#endif + +bool Save_Flash = false; +bool Reset_Save_Flash = false; +uint16_t Save_Flash_3S_Count = 0; +bool Led_Flash_Busy = false; + +void Save_Flash_Set(void) { + Save_Flash = true; + Save_Flash_3S_Count = 0; +} \ No newline at end of file diff --git a/keyboards/womier/common/user_eeprom.h b/keyboards/womier/common/user_eeprom.h new file mode 100644 index 00000000000..c7e18f56262 --- /dev/null +++ b/keyboards/womier/common/user_eeprom.h @@ -0,0 +1,31 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 + +#if defined(EEPROM_CUSTOM) +extern void eeprom_driver_init(void); +extern void eeprom_write_block_user(const void *buf, void *addr, size_t len); +extern void eeprom_read_block_user(void *buf, const void *addr, size_t len); +#endif + +extern bool Save_Flash; +extern bool Reset_Save_Flash; +extern uint16_t Save_Flash_3S_Count; +extern bool Led_Flash_Busy; + +extern void Save_Flash_Set(void); \ No newline at end of file diff --git a/keyboards/womier/common/user_emi.c b/keyboards/womier/common/user_emi.c new file mode 100644 index 00000000000..7fdec728d52 --- /dev/null +++ b/keyboards/womier/common/user_emi.c @@ -0,0 +1,64 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 "rdmctmzt_common.h" + +bool Emi_Test_Start = false; + +void Emi_Init(void) { + Spi_Interval = SPI_DELAY_USB_TIME; + Keyboard_Status.System_Work_Status = 0; + Keyboard_Status.System_Sleep_Mode = 0; + Mode_Synchronization_Signal = false; + Led_Rf_Pair_Flg = false; + Ble_Name_Spi_Send = false; +} + +void Emi_Read_Data(uint8_t *User_Data, uint8_t User_Length) { + if (Emi_Test_Start == false) { + return; + } + + if (Init_Spi_Power_Up) { + return; + } + + if (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO))) { + return; + } + + Spi_Send_Recv_Flg = 1; + Send_Key_Type = SPI_ACK; + Repet_Send_Count = 0; + + /*将需要发送的指令发送到680*/ + for (uint8_t i = 0; i < User_Length; i++) { + g_es_spi_tx_buf[i] = User_Data[i]; + } + es_spi_send_recv_by_dma(USER_KEYBOARD_LENGTH, g_es_spi_rx_buf, g_es_spi_tx_buf); + return; +} + +void Emi_Write_Data(uint8_t *User_Data, uint8_t User_Length) { + if (Emi_Test_Start == false) { + return; + } + + if (User_Data[0] == USER_KEYBOARD_COMMAND) { + return; + } + User_Data[0] = USER_EMI_COMMAND; +} diff --git a/keyboards/womier/common/user_emi.h b/keyboards/womier/common/user_emi.h new file mode 100644 index 00000000000..01cce7434c0 --- /dev/null +++ b/keyboards/womier/common/user_emi.h @@ -0,0 +1,24 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 bool Emi_Test_Start; + +extern void Emi_Init(void); +extern void Emi_Read_Data(uint8_t *User_Data, uint8_t User_Length); +extern void Emi_Write_Data(uint8_t *User_Data, uint8_t User_Length); diff --git a/keyboards/womier/common/user_led_custom.c b/keyboards/womier/common/user_led_custom.c new file mode 100644 index 00000000000..857d3d82632 --- /dev/null +++ b/keyboards/womier/common/user_led_custom.c @@ -0,0 +1,256 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 "rdmctmzt_common.h" + +uint8_t Led_Colour_Tab[9][3] = { + {255, 0, 0 }, + {255, 128, 0 }, + {255, 255, 0 }, + {0, 255, 0 }, + {0, 255, 255 }, + {0, 0, 255 }, + {128, 0, 255 }, + {255, 255, 255 } +}; + +uint8_t Led_Wave_Pwm_Tab[128] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, + 64, 68, 72, 76, 80, 84, 88, 92, + 96, 100, 104, 108, 112, 116, 120, 124, + 128, 132, 136, 140, 144, 148, 152, 156, + 160, 164, 168, 172, 176, 180, 184, 188, + 192, 196, 200, 204, 208, 212, 216, 220, + 224, 228, 232, 236, 240, 244, 248, 255, + + 255, 248, 244, 240, 236, 232, 228, 224, + 220, 216, 212, 208, 204, 200, 196, 192, + 188, 184, 180, 176, 172, 168, 164, 160, + 156, 152, 148, 144, 140, 136, 132, 128, + 124, 120, 116, 112, 108, 104, 100, 96, + 92, 88, 84, 80, 76, 72, 68, 64, + 60, 56, 52, 48, 44, 40, 36, 32, + 28, 24, 20, 16, 12, 8, 4, 0, +}; + +#define ES_PWM_LED_SIZE (42) +#define ES_PWM_LED_BYTE (24) +#define ES_PWM_DMA_SIZE (ES_PWM_LED_SIZE * ES_PWM_LED_BYTE) + +#define ES_PWM_WS2812_H_VALUE (43) +#define ES_PWM_WS2812_L_VALUE (17) + +rgb_led_t rgb_matrix_ws2812_array[RGB_MATRIX_LED_COUNT]; +uint8_t g_es_pwm_rgb_matrix_array_dma_buf[(RGB_MATRIX_LED_COUNT * ES_PWM_LED_BYTE) + 2] = {0}; +md_dma_channel_config_typedef DMA_list[5] = {0}; + +void rgb_matrix_driver_init(void) { + md_rcu_enable_dma1(RCU); + md_dma_set_configuration(DMA1, ENABLE); + + md_rcu_enable_gp16c2t1(RCU); + md_timer_set_auto_reload_value_arrv(GP16C2T1, 60); + md_timer_set_output_compare1_mode_ch1mod(GP16C2T1, MD_TIMER_OUTPUTMODE_PWMMODE1); + md_timer_set_capture_compare1_value_ccrv1(GP16C2T1, 0); + md_timer_enable_cc1_output_cc1en(GP16C2T1); + md_timer_enable_main_output_goen(GP16C2T1); + + md_timer_enable_output_compare1_preload_ch1pen(GP16C2T1); + md_timer_enable_dma_upd(GP16C2T1); + md_timer_enable_counter_cnten(GP16C2T1); + + gpio_set_pin_output(ES_PWM_DMA_IO); + + GPIOA->AFL &= 0xFFFFF0FF; + GPIOA->AFL |= 0x00000500; + + GPIOA->MOD &= 0xFFFFFFCF; + GPIOA->MOD |= 0x00000020; + + md_dma_set_request_peripherals(DMA1, MD_DMA_CHANNEL2, MD_DMA_PRS_GP16C2T1_UP); + + if (rgb_matrix_get_val() <= 0) { + memset((void *)g_es_pwm_rgb_matrix_array_dma_buf, ES_PWM_WS2812_L_VALUE, (RGB_MATRIX_LED_COUNT * ES_PWM_LED_BYTE) + 2); + } +} + +void User_Pwm_Deinit(void) { + md_rcu_enable_gp16c2t1_reset(RCU); + md_rcu_disable_gp16c2t1_reset(RCU); + md_rcu_disable_gp16c2t1(RCU); + md_rcu_enable_dma1_reset(RCU); + md_rcu_disable_dma1_reset(RCU); + md_rcu_disable_dma1(RCU); + + gpio_set_pin_output(ES_PWM_DMA_IO); + gpio_write_pin_low(ES_PWM_DMA_IO); +} + +void rgb_matrix_driver_flush_pwm_dma_start(void) { + while ((DMA1->CHENSET) & 0x4); + + if (Keyboard_Status.System_Sleep_Mode || ((Keyboard_Info.Key_Mode != QMK_USB_MODE) && Usb_Change_Mode_Wakeup && Keyboard_Status.System_Work_Status) || (!Led_Power_Up)) { + Led_Off_Start = true; + gpio_write_pin_low(ES_LED_POWER_IO); + return; + } + + if (rgblight_is_enabled()) { + gpio_write_pin_high(ES_LED_POWER_IO); + if (Led_Off_Start) { + Led_Off_Start = false; + wait_ms(3); + } + } else { + Led_Off_Start = true; + gpio_write_pin_low(ES_LED_POWER_IO); + } + + md_timer_disable_dma_upd(GP16C2T1); + + g_es_pwm_rgb_matrix_array_dma_buf[(RGB_MATRIX_LED_COUNT * ES_PWM_LED_BYTE)] = 0; + g_es_pwm_rgb_matrix_array_dma_buf[(RGB_MATRIX_LED_COUNT * ES_PWM_LED_BYTE) + 1] = 0; + + #if (RGB_MATRIX_LED_COUNT <= 42) + uint16_t Data_Size = ((RGB_MATRIX_LED_COUNT * ES_PWM_LED_BYTE) + 2); + DMA_list[0].control.word = ((Data_Size - 1) << 4) | g_es_dma_ch2alt_cfg; + DMA_list[0].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf + (Data_Size - 1)); + DMA_list[0].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1)); + + DMA1->PRI_CH02_SRC_DATA_END_PTR = ((uint32_t)(DMA_list)) + ((16 - 4)); + DMA1->PRI_CH02_CHANNEL_CFG = ((4 - 1) << 4) | g_es_dma_ch2pri_cfg; + #elif (RGB_MATRIX_LED_COUNT <= 84) + DMA_list[0].control.word = ((ES_PWM_DMA_SIZE - 1) << 4) | g_es_dma_ch2alt_cfg; + DMA_list[0].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf + (ES_PWM_DMA_SIZE - 1)); + DMA_list[0].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1)); + + uint16_t Data_Size = (((RGB_MATRIX_LED_COUNT - ES_PWM_LED_SIZE) * ES_PWM_LED_BYTE) + 2); + DMA_list[1].control.word = ((Data_Size - 1) << 4) | g_es_dma_ch2alt_cfg; + DMA_list[1].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf + (ES_PWM_DMA_SIZE + Data_Size - 1)); + DMA_list[1].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1)); + + DMA1->PRI_CH02_SRC_DATA_END_PTR = ((uint32_t)(DMA_list)) + ((32 - 4)); + DMA1->PRI_CH02_CHANNEL_CFG = ((8 - 1) << 4) | g_es_dma_ch2pri_cfg; + #elif (RGB_MATRIX_LED_COUNT <= 126) + DMA_list[0].control.word = ((ES_PWM_DMA_SIZE - 1) << 4) | g_es_dma_ch2alt_cfg; + DMA_list[0].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf + (ES_PWM_DMA_SIZE - 1)); + DMA_list[0].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1)); + + DMA_list[1].control.word = ((ES_PWM_DMA_SIZE - 1) << 4) | g_es_dma_ch2alt_cfg; + DMA_list[1].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf + ((ES_PWM_DMA_SIZE * 2) - 1)); + DMA_list[1].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1)); + + uint16_t Data_Size = (((RGB_MATRIX_LED_COUNT - (ES_PWM_LED_SIZE * 2)) * ES_PWM_LED_BYTE) + 2); + DMA_list[2].control.word = ((Data_Size - 1) << 4) | g_es_dma_ch2alt_cfg; + DMA_list[2].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf + ((ES_PWM_DMA_SIZE * 2) + Data_Size - 1)); + DMA_list[2].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1)); + + DMA1->PRI_CH02_SRC_DATA_END_PTR = ((uint32_t)(DMA_list)) + ((48 - 4)); + DMA1->PRI_CH02_CHANNEL_CFG = ((12 - 1) << 4) | g_es_dma_ch2pri_cfg; + #elif (RGB_MATRIX_LED_COUNT <= 168) + DMA_list[0].control.word = ((ES_PWM_DMA_SIZE - 1) << 4) | g_es_dma_ch2alt_cfg; + DMA_list[0].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf + (ES_PWM_DMA_SIZE - 1)); + DMA_list[0].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1)); + + DMA_list[1].control.word = ((ES_PWM_DMA_SIZE - 1) << 4) | g_es_dma_ch2alt_cfg; + DMA_list[1].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf + ((ES_PWM_DMA_SIZE * 2) - 1)); + DMA_list[1].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1)); + + DMA_list[2].control.word = ((ES_PWM_DMA_SIZE - 1) << 4) | g_es_dma_ch2alt_cfg; + DMA_list[2].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf + ((ES_PWM_DMA_SIZE * 3) - 1)); + DMA_list[2].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1)); + + uint16_t Data_Size = (((RGB_MATRIX_LED_COUNT - (ES_PWM_LED_SIZE * 3)) * ES_PWM_LED_BYTE) + 2); + DMA_list[3].control.word = ((Data_Size - 1) << 4) | g_es_dma_ch2alt_cfg; + DMA_list[3].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf + ((ES_PWM_DMA_SIZE * 3) + Data_Size - 1)); + DMA_list[3].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1)); + + DMA1->PRI_CH02_SRC_DATA_END_PTR = ((uint32_t)(DMA_list)) + ((64 - 4)); + DMA1->PRI_CH02_CHANNEL_CFG = ((16 - 1) << 4) | g_es_dma_ch2pri_cfg; + #endif + + DMA1->PRI_CH02_DST_DATA_END_PTR = ((uint32_t)(&(DMA1->ALT_CH02_SRC_DATA_END_PTR))) + 16 - 4; + DMA1->CHENSET = 0x4; + md_timer_enable_dma_upd(GP16C2T1); +} + +void rgb_matrix_driver_flush(void) { + Led_Flash_Busy = false; + if((GP16C2T1->AR) != 60) { + rgb_matrix_driver_init(); + } + + rgb_matrix_driver_flush_pwm_dma_start(); +} + +void rgb_matrix_driver_set_color(int index, uint8_t r, uint8_t g, uint8_t b) { + uint8_t * buf; + + if (index == (RGB_MATRIX_LED_COUNT - 1)) { + Led_Flash_Busy = false; + } else if(index == 0) { + Led_Flash_Busy = true; + } + + if (rgb_matrix_ws2812_array[index].r == r && rgb_matrix_ws2812_array[index].g == g && rgb_matrix_ws2812_array[index].b == b) { + return; + } + + rgb_matrix_ws2812_array[index].r = r; + rgb_matrix_ws2812_array[index].g = g; + rgb_matrix_ws2812_array[index].b = b; + + buf = g_es_pwm_rgb_matrix_array_dma_buf + (index * 24); + + for (unsigned char bit = 0; bit < 8; bit++) { + bool is_one = g & (1 << (7 - bit)); + // using something like wait_ns(is_one ? T1L : T0L) here throws off timings + + *buf = (is_one)? ES_PWM_WS2812_H_VALUE : ES_PWM_WS2812_L_VALUE; + buf++; + } + + for (unsigned char bit = 0; bit < 8; bit++) { + bool is_one = r & (1 << (7 - bit)); + // using something like wait_ns(is_one ? T1L : T0L) here throws off timings + + *buf = (is_one)? ES_PWM_WS2812_H_VALUE : ES_PWM_WS2812_L_VALUE; + buf++; + } + + for (unsigned char bit = 0; bit < 8; bit++) { + bool is_one = b & (1 << (7 - bit)); + // using something like wait_ns(is_one ? T1L : T0L) here throws off timings + + *buf = (is_one)? ES_PWM_WS2812_H_VALUE : ES_PWM_WS2812_L_VALUE; + buf++; + } +} + +void rgb_matrix_driver_set_color_all(uint8_t r, uint8_t g, uint8_t b) { + for(uint32_t i = 0;i < RGB_MATRIX_LED_COUNT;i++) { + rgb_matrix_driver_set_color(i,r,g,b); + } +} + +// clang-format off +const rgb_matrix_driver_t rgb_matrix_driver = { + .init = rgb_matrix_driver_init, + .flush = rgb_matrix_driver_flush, + .set_color = rgb_matrix_driver_set_color, + .set_color_all = rgb_matrix_driver_set_color_all, +}; diff --git a/keyboards/womier/common/user_led_custom.h b/keyboards/womier/common/user_led_custom.h new file mode 100644 index 00000000000..996bae2b528 --- /dev/null +++ b/keyboards/womier/common/user_led_custom.h @@ -0,0 +1,28 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 uint8_t Led_Colour_Tab[9][3]; +extern uint8_t Led_Wave_Pwm_Tab[128]; + +extern void rgb_matrix_driver_init(void); +extern void User_Pwm_Deinit(void); +extern void rgb_matrix_driver_flush_pwm_dma_start(void); +extern void rgb_matrix_driver_flush(void); +extern void rgb_matrix_driver_set_color(int index, uint8_t r, uint8_t g, uint8_t b); +extern void rgb_matrix_driver_set_color_all(uint8_t r, uint8_t g, uint8_t b); +extern const rgb_matrix_driver_t rgb_matrix_driver; diff --git a/keyboards/womier/common/user_spi.c b/keyboards/womier/common/user_spi.c new file mode 100644 index 00000000000..a894139ce53 --- /dev/null +++ b/keyboards/womier/common/user_spi.c @@ -0,0 +1,322 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 "rdmctmzt_common.h" + +volatile uint8_t Spi_Send_Recv_Flg = 0U; +uint8_t g_es_spi_rx_buf[64] = {0}; +uint8_t g_es_spi_tx_buf[64] = {0}; +uint8_t Repet_Send_Count = 0x00; +uint8_t Send_Key_Type = SPI_NACK; + +bool Init_Spi_Power_Up = true; +uint8_t Init_Spi_100ms_Delay = 0; +uint16_t Spi_Interval = SPI_DELAY_RF_TIME; +bool Ble_Name_Spi_Send = false; +uint8_t Ble_Name_Spi_Count = QMK_BLE_CHANNEL_1; + +uint8_t app_2g4_data[APP_2G4_BUF_CNT][APP_2G4_BUF_SIZE]; +volatile uint8_t app_2g4_data_send = 0; +volatile uint8_t app_2g4_data_rev = 0; + +const md_spi_inittypedef SPI2_InitStruct = /**< SPI init structure */ +{ + MD_SPI_MODE_MASTER, + MD_SPI_PHASE_2EDGE, + MD_SPI_POLARITY_HIGH, + MD_SPI_BAUDRATEPRESCALER_DIV8, + MD_SPI_MSB_FIRST, + MD_SPI_FULL_DUPLEX, + MD_SPI_FRAME_FORMAT_8BIT, + MD_SPI_NSS_HARD, +}; + +uint8_t app_2g4_buffer_full(void) { + uint8_t tmp_rev = app_2g4_data_rev + 1; + if(tmp_rev == APP_2G4_BUF_CNT) + { + tmp_rev = 0; + } + return (tmp_rev == app_2g4_data_send); +} + +uint8_t app_2g4_buffer_empty(void) { + return (app_2g4_data_rev == app_2g4_data_send); +} + +void app_2g4_buffer_rev_add(void) { + app_2g4_data_rev++; + if(app_2g4_data_rev >= APP_2G4_BUF_CNT) + app_2g4_data_rev = 0; +} + +void app_2g4_buffer_send_add(void) { + app_2g4_data_send++; + if(app_2g4_data_send >= APP_2G4_BUF_CNT) + app_2g4_data_send = 0; +} + +void Spi_Main_Loop(void) { + if (Init_Spi_Power_Up || Keyboard_Status.System_Work_Status) { + return; + } + + if ((!app_2g4_buffer_empty()) && (!Spi_Send_Recv_Flg) && (!gpio_read_pin(ES_SPI_ACK_IO))) { + Spi_Send_Recv_Flg = 1; + Send_Key_Type = SPI_NACK; + es_spi_send_recv_by_dma(USER_KEYBOARD_LENGTH, g_es_spi_rx_buf, app_2g4_data[app_2g4_data_send]); + app_2g4_buffer_send_add(); + } +} + +void es_ble_spi_init(void) { + md_gpio_inittypedef gpiox; + + md_rcu_enable_spi2(RCU); + + gpiox.Pin = MD_GPIO_PIN_0; + gpiox.Mode = MD_GPIO_MODE_FUNCTION; + gpiox.OutputType = MD_GPIO_OUTPUT_PUSHPULL; + gpiox.Pull = MD_GPIO_PULL_UP; + gpiox.OutDrive = MD_GPIO_DRIVING_8MA; + gpiox.Function = MD_GPIO_AF0; + md_gpio_init(GPIOC, &gpiox); + + gpiox.Pin = MD_GPIO_PIN_1; + md_gpio_init(GPIOC, &gpiox); + + gpiox.Pin = MD_GPIO_PIN_2; + md_gpio_init(GPIOC, &gpiox); + + gpiox.Pin = MD_GPIO_PIN_3; + md_gpio_init(GPIOC, &gpiox); + + md_spi_init(SPI2, (md_spi_inittypedef *)(&SPI2_InitStruct)); +} + +void es_ble_spi_deinit(void) { + + md_rcu_enable_spi2_reset(RCU); + md_rcu_disable_spi2_reset(RCU); + md_rcu_disable_spi2(RCU); + + GPIOC->MOD |= 0x000000FF; + GPIOC->PUD &= 0xFFFFFF00; + GPIOC->OT &= 0xFFFFFF00; + GPIOC->DS &= 0xFFFFFF00; + GPIOC->IST &= 0xFFFFFF00; +} + +void es_spi_send_recv_by_dma(uint32_t num, uint8_t *rx_buf, uint8_t *tx_buf) { + uint32_t tx_index = 0; + uint32_t rx_index = 0; + + __disable_irq(); + + if(((uint32_t)tx_buf) >= 0x20000000) { + if(num & 0x1) { + SPI2->DATA = tx_buf[tx_index++]; + } + + while(tx_index < num) { + if(md_spi_get_txfifo_value(SPI2) <= 2) { + SPI2->DATA = tx_buf[tx_index++]; + SPI2->DATA = tx_buf[tx_index++]; + } + + if(md_spi_get_rxfifo_value(SPI2)) { + rx_buf[rx_index++] = SPI2->DATA; + } + } + + while(rx_index < num) { + if(md_spi_get_rxfifo_value(SPI2)) { + rx_buf[rx_index++] = SPI2->DATA; + } + } + } else { + if(num & 0x1) { + SPI2->DATA = 0X00; + } + + while(tx_index < num) { + if(md_spi_get_txfifo_value(SPI2) <= 2) { + SPI2->DATA = 0X00; + SPI2->DATA = 0X00; + tx_index += 2; + } + + if(md_spi_get_rxfifo_value(SPI2)) { + rx_buf[rx_index++] = SPI2->DATA; + } + } + + while(rx_index < num) { + if(md_spi_get_rxfifo_value(SPI2)) { + rx_buf[rx_index++] = SPI2->DATA; + } + } + } + + __enable_irq(); +} + +void Spi_Send_Commad(uint8_t Commad) { + if (Init_Spi_Power_Up || Keyboard_Status.System_Work_Status) { + return; + } + + uint16_t Time_Delay = 0; + while (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO))){ + Time_Delay++; + if (Time_Delay >= 2000) { + Time_Delay = 0; + return; + } + } + + Spi_Send_Recv_Flg = 1; + Send_Key_Type = SPI_NACK; + Spi_Interval = SPI_DELAY_RF_TIME; + + g_es_spi_tx_buf[0] = USER_KEYBOARD_COMMAND; + g_es_spi_tx_buf[1] = USER_KEYBOARD_LENGTH; + g_es_spi_tx_buf[2] = Commad; + if (Commad == USER_BATTERY_DATA) { + g_es_spi_tx_buf[3] = Keyboard_Info.Batt_Number; + } else if (Commad == USER_BLE1_WRITE_NAME) { + g_es_spi_tx_buf[3] = ((USER_BlE_ID >> 8) & 0XFF); + g_es_spi_tx_buf[4] = (USER_BlE_ID & 0X00FF); + g_es_spi_tx_buf[5] = strlen(USER_BlE1_NAME); + for (uint8_t len = 0; len < strlen(USER_BlE1_NAME); len++) { + g_es_spi_tx_buf[6 + len] = USER_BlE1_NAME[len]; + } + } else if (Commad == USER_BLE2_WRITE_NAME) { + g_es_spi_tx_buf[3] = ((USER_BlE_ID >> 8) & 0XFF); + g_es_spi_tx_buf[4] = (USER_BlE_ID & 0X00FF); + g_es_spi_tx_buf[5] = strlen(USER_BlE2_NAME); + for (uint8_t len = 0; len < strlen(USER_BlE2_NAME); len++) { + g_es_spi_tx_buf[6 + len] = USER_BlE2_NAME[len]; + } + } else if (Commad == USER_BLE3_WRITE_NAME) { + g_es_spi_tx_buf[3] = ((USER_BlE_ID >> 8) & 0XFF); + g_es_spi_tx_buf[4] = (USER_BlE_ID & 0X00FF); + g_es_spi_tx_buf[5] = strlen(USER_BlE3_NAME); + for (uint8_t len = 0; len < strlen(USER_BlE3_NAME); len++) { + g_es_spi_tx_buf[6 + len] = USER_BlE3_NAME[len]; + } + } + + es_spi_send_recv_by_dma(USER_KEYBOARD_LENGTH, g_es_spi_rx_buf, g_es_spi_tx_buf); +} + +uint8_t Spi_Ack_Send_Commad(uint8_t Commad) { + if (Init_Spi_Power_Up) { + return SPI_BUSY; + } + + if (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO))) { + return SPI_BUSY; + } + + Spi_Send_Recv_Flg = 1; + Send_Key_Type = SPI_ACK; + Repet_Send_Count = 0; + + g_es_spi_tx_buf[0] = USER_KEYBOARD_COMMAND; + g_es_spi_tx_buf[1] = USER_KEYBOARD_LENGTH; + g_es_spi_tx_buf[2] = Commad; + es_spi_send_recv_by_dma(USER_KEYBOARD_LENGTH, g_es_spi_rx_buf, g_es_spi_tx_buf); + return SPI_IDLE; +} + +void Get_Spi_Return_Data(uint8_t *Data) { + if (Emi_Test_Start) { + Emi_Write_Data(Data, USER_KEYBOARD_LENGTH); + } else { + if (Data[2] == USER_GET_RF_STATUS) { + Keyboard_Status.System_Work_Status = Data[3]; + if (Keyboard_Status.System_Work_Status) { + if (Keyboard_Info.Key_Mode != QMK_USB_MODE) { + if (Usb_Change_Mode_Wakeup) { + User_Sleep(); + } else { + Keyboard_Status.System_Work_Status = 0; + } + } else { + Keyboard_Status.System_Work_Status = 0; + Spi_Interval = SPI_DELAY_USB_TIME; + } + } + + Keyboard_Status.System_Work_Mode = Data[4]; + if (Keyboard_Info.Key_Mode != Keyboard_Status.System_Work_Mode) { + Mode_Synchronization_Signal = true; + if (Keyboard_Status.System_Work_Status) { + Keyboard_Status.System_Work_Status = 0; + } + } else { + if (Keyboard_Info.Key_Mode == QMK_USB_MODE) { + Spi_Interval = SPI_DELAY_USB_TIME; + } + } + + Keyboard_Status.System_Work_Channel = Data[5]; + if ((Keyboard_Info.Ble_Channel != Keyboard_Status.System_Work_Channel) && (Keyboard_Info.Key_Mode == QMK_BLE_MODE)) { + Mode_Synchronization_Signal = true; + if (Keyboard_Status.System_Work_Status) { + Keyboard_Status.System_Work_Status = 0; + } + } + + Keyboard_Status.System_Connect_Status = Data[6]; + if (Temp_System_Led_Status != Keyboard_Status.System_Connect_Status) { + Temp_System_Led_Status = Keyboard_Status.System_Connect_Status; + if (Keyboard_Info.Key_Mode != QMK_USB_MODE) { + Led_Rf_Pair_Flg = true; + } else { + Led_Rf_Pair_Flg = false; + } + } + + Keyboard_Status.System_Led_Status = Data[7]; + + uint16_t Ble_ID = ((Data[8] << 8) | (Data[9])); + if (Ble_ID != USER_BlE_ID) { + if (Ble_Name_Spi_Send == false) { + Ble_Name_Spi_Send = true; + Ble_Name_Spi_Count = QMK_BLE_CHANNEL_1; + } + } + } else if (Data[2] == USER_KEYBOARD_SLEEP) { + if (Keyboard_Status.System_Work_Status && (Data[3] == USER_SLEEP_PASS)) { + if (Keyboard_Info.Key_Mode != QMK_USB_MODE) { + Keyboard_Status.System_Sleep_Mode = 1; + } else { + Keyboard_Status.System_Sleep_Mode = 0; + } + } else if (Data[3] == USER_SLEEP_FIAL) { + Keyboard_Status.System_Work_Status = 0; + Keyboard_Status.System_Sleep_Mode = 0; + } + } + + if (0XBB == Data[10]) { + Emi_Test_Start = true; + Emi_Init(); + } + } +} \ No newline at end of file diff --git a/keyboards/womier/common/user_spi.h b/keyboards/womier/common/user_spi.h new file mode 100644 index 00000000000..129520a6af3 --- /dev/null +++ b/keyboards/womier/common/user_spi.h @@ -0,0 +1,96 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 USER_EMI_COMMAND 0XBB +#define USER_KEYBOARD_COMMAND 0X0A +#define USER_KEYBOARD_LENGTH (64) + +#define USER_SWITCH_2P4G_MODE 0X00 +#define USER_SWITCH_BLE_1_MODE 0X01 +#define USER_SWITCH_BLE_2_MODE 0X02 +#define USER_SWITCH_BLE_3_MODE 0X03 +#define USER_SWITCH_2P4G_PAIR 0X04 +#define USER_SWITCH_BLE_1_PAIR 0X05 +#define USER_SWITCH_BLE_2_PAIR 0X06 +#define USER_SWITCH_BLE_3_PAIR 0X07 +#define USER_SWITCH_USB_MODE 0X08 + +#define USER_KEYBOARD_SLEEP 0X09 +#define USER_KEYBOARD_WAKEUP 0X0A + +#define USER_KEY_BYTE_DATA 0X0B +#define USER_KEY_BIT_DATA 0X0C +#define USER_MOUSE_DATA 0X0D +#define USER_CONSUMER_DATA 0X0E +#define USER_SYSTEM_DATA 0X0F + +#define USER_BATTERY_DATA 0X10 + +#define USER_GET_RF_STATUS 0X11 + +#define USER_BLE1_WRITE_NAME 0X12 +#define USER_BLE2_WRITE_NAME 0X13 +#define USER_BLE3_WRITE_NAME 0X14 + +#define APP_2G4_BUF_SIZE (USER_KEYBOARD_LENGTH) +#define APP_2G4_BUF_CNT (20) + +#define SPI_DELAY_RF_TIME (60) +#define SPI_DELAY_USB_TIME (500 * 3) + +enum Custom_Spi_Ack_S { + SPI_NACK, + SPI_ACK +}; + +enum Custom_Spi_Busy_S { + SPI_BUSY, + SPI_IDLE +}; + +extern volatile uint8_t Spi_Send_Recv_Flg; +extern uint8_t g_es_spi_rx_buf[64]; +extern uint8_t g_es_spi_tx_buf[64]; +extern uint8_t Repet_Send_Count; +extern uint8_t Send_Key_Type; + +extern bool Init_Spi_Power_Up; +extern uint8_t Init_Spi_100ms_Delay; +extern uint16_t Spi_Interval; +extern bool Ble_Name_Spi_Send; +extern uint8_t Ble_Name_Spi_Count; + +extern uint8_t app_2g4_data[APP_2G4_BUF_CNT][APP_2G4_BUF_SIZE]; +extern volatile uint8_t app_2g4_data_send; +extern volatile uint8_t app_2g4_data_rev; + +extern const md_spi_inittypedef SPI2_InitStruct; + +extern uint8_t app_2g4_buffer_full(void); +extern uint8_t app_2g4_buffer_empty(void); +extern void app_2g4_buffer_rev_add(void); +extern void app_2g4_buffer_send_add(void); +extern void Spi_Main_Loop(void); + +extern void es_ble_spi_init(void); +extern void es_ble_spi_deinit(void); +extern void es_spi_send_recv_by_dma(uint32_t num, uint8_t *rx_buf, uint8_t *tx_buf); +extern void Spi_Send_Commad(uint8_t Commad); +extern uint8_t Spi_Ack_Send_Commad(uint8_t Commad); +extern void Get_Spi_Return_Data(uint8_t *Data); \ No newline at end of file diff --git a/keyboards/womier/common/user_system.c b/keyboards/womier/common/user_system.c new file mode 100644 index 00000000000..b7c2828dd54 --- /dev/null +++ b/keyboards/womier/common/user_system.c @@ -0,0 +1,438 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 "rdmctmzt_common.h" + +void es_mcu_reset(void) { + uint16_t Time_Delay = 0; + while (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO)) || Reset_Save_Flash) { + Time_Delay++; + if (Time_Delay >= 36000) { + Time_Delay = 0; + break; + } + } + gpio_write_pin_low(ES_LED_POWER_IO); + + NVIC_SystemReset(); +} + +void bootloader_jump(void) { + uint16_t Time_Delay = 0; + while (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO)) || Reset_Save_Flash) { + Time_Delay++; + if (Time_Delay >= 36000) { + Time_Delay = 0; + break; + } + } + + gpio_write_pin_low(ES_LED_POWER_IO); + + /*Remap EFLASH,remap to boot*/ + md_fc_lock(); + md_syscfg_set_memory_mapping(SYSCFG, MD_SYSCFG_MEMMOD_MAIN); + md_syscfg_set_flash_remap_base(SYSCFG, 0); + md_syscfg_enable_memory_remap(SYSCFG); + NVIC_SystemReset(); +} + +void mcu_reset(void) { + uint16_t Time_Delay = 0; + while (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO)) || Reset_Save_Flash) { + Time_Delay++; + if (Time_Delay >= 36000) { + Time_Delay = 0; + break; + } + } + + gpio_write_pin_low(ES_LED_POWER_IO); + + NVIC_SystemReset(); +} + +void User_Systime_Init(void) { //2ms + md_rcu_enable_bs16t1(RCU); + BS16T1->PRES = 48 - 1; + BS16T1->AR = 2000; + BS16T1->IER = 0x1; + BS16T1->CON1 = 0x1; + NVIC_SetPriority(BS16T1_IRQn, 2); + NVIC_EnableIRQ(BS16T1_IRQn); +} + +void User_Systime_Deinit(void) { + md_rcu_enable_bs16t1_reset(RCU); + md_rcu_disable_bs16t1_reset(RCU); + md_rcu_disable_bs16t1(RCU); +} + +void User_Sleep(void) { + gpio_set_pin_output(ES_LED_POWER_IO); + gpio_write_pin_low(ES_LED_POWER_IO); + + gpio_set_pin_output(ES_SDB_POWER_IO); + gpio_write_pin_low(ES_SDB_POWER_IO); + + gpio_set_pin_output(ES_WUKEUP_IO); + gpio_write_pin_low(ES_WUKEUP_IO); +} + +void User_Wakeup(void) { + gpio_set_pin_output(ES_WUKEUP_IO); + gpio_write_pin_high(ES_WUKEUP_IO); +} + +void Init_Gpio_Infomation(void) { + gpio_write_pin_low(ES_LED_POWER_IO); + gpio_set_pin_output(ES_LED_POWER_IO); + gpio_write_pin_low(ES_LED_POWER_IO); + + gpio_write_pin_high(ES_SDB_POWER_IO); + gpio_set_pin_output(ES_SDB_POWER_IO); + gpio_write_pin_high(ES_SDB_POWER_IO); + + gpio_write_pin_high(ES_WUKEUP_IO); + gpio_set_pin_output(ES_WUKEUP_IO); + gpio_write_pin_high(ES_WUKEUP_IO); + + //STDBT + gpio_set_pin_input_high(ES_BATT_STDBY_IO); + + //USB POWER + gpio_set_pin_input(ES_USB_POWER_IO); + + md_gpio_inittypedef gpiox; + + gpiox.Pin = MD_GPIO_PIN_4; + gpiox.Mode = MD_GPIO_MODE_INPUT; + gpiox.OutputType = MD_GPIO_OUTPUT_PUSHPULL; + gpiox.Pull = MD_GPIO_PULL_DOWN; + gpiox.OutDrive = MD_GPIO_DRIVING_8MA; + gpiox.Function = MD_GPIO_AF0; + md_gpio_init(GPIOA, &gpiox); + + md_exti_set_interrupt_pin_0_7(EXTI, MD_EXTI_GPIOA4); + md_exti_enable_it_gpio_pin(EXTI, MD_EXTI_GPIO4); + md_exti_enable_rising_edge_trigger(EXTI, MD_EXTI_GPIO4); + md_exti_enable_falling_edge_trigger(EXTI, MD_EXTI_GPIO4); + + NVIC_SetPriority(EXTI_4to15_IRQn, 3); + NVIC_EnableIRQ((IRQn_Type) EXTI_4to15_IRQn); /* EXTI_4to15_IRQn interrupt */ +} + +void Board_Wakeup_Init(void) { + /*Using USB_SOF to calibrate the internal clock*/ + md_rcu_enable_csu(RCU); + CSU->CON |= CSU_CON_AUTOEN_MSK; + CSU->CON |= CSU_CON_CNTEN_MSK; + + es_ble_spi_init(); //SPI + + User_Adc_Init(); //ADC + + rgb_matrix_driver_init(); //PWM DMA + + Init_Gpio_Infomation(); //GPIO + + User_Systime_Init(); //time + + if (Keyboard_Info.Key_Mode == QMK_USB_MODE) { + User_Usb_Init(); //USB + } else { + Usb_Disconnect(); + } + + Init_Spi_Power_Up = true; + Init_Spi_100ms_Delay = 0; + Spi_Interval = SPI_DELAY_RF_TIME; + + NVIC_SetPriority(PendSV_IRQn, 3); + NVIC_SetPriority(SysTick_IRQn, 3); + + Keyboard_Status.System_Work_Status = 0; + Keyboard_Status.System_Sleep_Mode = 0; + Usb_Change_Mode_Wakeup = false; + + Init_Batt_Infomation(); + + Led_Power_Up = false; + Emi_Test_Start = false; +} + +void es_chibios_user_idle_loop_hook(void) { + uint32_t i; + + if(Keyboard_Info.Key_Mode == QMK_USB_MODE) { + if (Usb_Dis_Connect) { + Usb_Dis_Connect = false; + + if((g_usb_sof_frame_id != g_usb_sof_frame_id_last) || (Usb_Change_Mode_Wakeup == false)) { //正常通信 + g_usb_sof_frame_id_last = g_usb_sof_frame_id; + Usb_Suspend_Delay = 0; + return; + } else { + Usb_If_Ok_Led = false; + Usb_Suspend_Delay++; + if (Usb_Suspend_Delay < 800) { //8S + return; + } + Usb_Suspend_Delay = 0; + + while ((DMA1->CHENSET) & 0x4); + + User_Sleep(); + uint32_t delay = 0; + while (SPI_IDLE != Spi_Ack_Send_Commad(USER_KEYBOARD_SLEEP)) { + delay++; + if(delay >= 3600) { + delay = 0; + User_Wakeup(); + Usb_Suspend_Delay = 6000; + return; + } + } + + delay = 0; + while (Spi_Send_Recv_Flg) { + delay++; + if(delay >= 36000) { + delay = 0; + User_Wakeup(); + return; + } + } + } + } else { + return; + } + } else { + if(!Keyboard_Status.System_Sleep_Mode) { //无线休眠 + return; + } + } + + /*等待SPI数据发送完成*/ + if(Spi_Send_Recv_Flg) { + return; + } + + /*680进入休眠之后,1.2ms 之后 ACK_IO 会高电平,说明休眠完成*/ + uint32_t delay = 0; + while (!gpio_read_pin(ES_SPI_ACK_IO)) { + wait_ms(1); + delay++; + if(delay >= 100) { + delay = 0; + return; + } + } + + gpio_set_pin_input_high(ES_SPI_ACK_IO); //ACK_IO + + md_tick_disable_csr_tickie(TICK); + NVIC_DisableIRQ((IRQn_Type) SysTick_IRQn); + + User_Systime_Deinit(); + + es_ble_spi_deinit(); + + User_Pwm_Deinit(); + + User_Usb_Deinit(); + + User_Adc_Deinit(); + + Save_Flash = false; + Save_Flash_3S_Count = 0; + Usb_Change_Mode_Wakeup = false; + Usb_Change_Mode_Delay = 0; + Led_Power_Up = false; + + ioline_t User_Pin_Tab_Col[KEYBAORD_COL] = MATRIX_USER_COL_PINS; + ioline_t User_Pin_Tab_Rol[KEYBAORD_ROL] = MATRIX_USER_ROW_PINS; + + //唤醒源配置 + for(i = 0; i < KEYBAORD_COL; i++) { //COL + gpio_set_pin_output(User_Pin_Tab_Col[i]); + gpio_write_pin_low(User_Pin_Tab_Col[i]); + } + + for(i = 0; i < KEYBAORD_ROL; i++) { //ROL + gpio_set_pin_input_high(User_Pin_Tab_Rol[i]); + } + + gpio_set_pin_input(ES_USB_POWER_IO); + + /*B0 B3 B4 B6 B7 B1*/ + uint32_t Gpio_Enable = 0X000000DB; + uint32_t Gpio_Status_H = 0X00000000; + uint32_t Gpio_Status_L = 0X000000DB; + + if (gpio_read_pin(ES_USB_POWER_IO)) { //USB C5 + Gpio_Status_L |= 0X20; + } else { + Gpio_Status_H |= 0X20; + } + Gpio_Enable |= 0X20; + + //GP16C4T2_CH2 PB5 + /*PB5 和 PC5 冲突只能用一个*/ + GPIOB->MOD &= 0xFFFFF3FF; //选择复用模式 GP16C4T2_CH2 + GPIOB->MOD |= 0x00000800; //选择复用模式 NABLE:1 DISABLE:0 + + GPIOB->AFL &= 0xFF0FFFFF; //选择复用功能 + GPIOB->AFL |= 0x00300000; //选择复用模式 NABLE:1 DISABLE:0 + + md_exti_set_interrupt_pin_0_7(EXTI, MD_EXTI_GPIOB0 | MD_EXTI_GPIOB1 | MD_EXTI_GPIOB3 | MD_EXTI_GPIOB4 | MD_EXTI_GPIOC5 | MD_EXTI_GPIOB6 | MD_EXTI_GPIOB7); + //md_exti_set_interrupt_pin_8_15(EXTI, MD_EXTI_GPIOB10); + + md_exti_enable_it_gpio_pin(EXTI, Gpio_Enable); /*0~7 , 10*/ + md_exti_enable_rising_edge_trigger(EXTI, Gpio_Status_H); /*0~7 , 10*/ + md_exti_enable_falling_edge_trigger(EXTI, Gpio_Status_L); /*0~7 , 10*/ + + NVIC_EnableIRQ((IRQn_Type) EXTI_0to1_IRQn); /* EXTI_0to1_IRQn interrupt */ + NVIC_EnableIRQ((IRQn_Type) EXTI_2to3_IRQn); /* EXTI_2to3_IRQn interrupt */ + NVIC_EnableIRQ((IRQn_Type) EXTI_4to15_IRQn); /* EXTI_4to15_IRQn interrupt */ + + //GP16C4T2_CH2 PB5 + md_rcu_enable_gp16c4t2(RCU); + md_timer_set_prescaler_value_pscv(GP16C4T2, 1); //分频系数 + md_timer_set_auto_reload_value_arrv(GP16C4T2, 0xffff); //计数最大值 + md_timer_set_cc2_func_cc2ssel(GP16C4T2, MD_TIMER_CHMODE_INPUT_DIRECT); //使用当前通道 + md_timer_set_cc2_input_edge_cc2pol(GP16C4T2, MD_TIMER_OUTPUTPOLARITY_LOW); //捕捉极性 + md_timer_enable_cc2_output_cc2en(GP16C4T2); //通道使能 + md_timer_enable_counter_cnten(GP16C4T2); //定时器使能 + md_timer_enable_it_ch2(GP16C4T2); //通道中断使能 + NVIC_EnableIRQ((IRQn_Type) GP16C4T2_IRQn); /* GP16C4T2_IRQHandler */ + md_rcu_enable_gp16c4t2_in_sleep_mode(RCU); /*保持休眠下工作*/ + + uint8_t Usb_Sleep_Status = 0XAA; + if (!gpio_read_pin(ES_USB_POWER_IO) && (Keyboard_Info.Key_Mode == QMK_USB_MODE)) { + NVIC_DisableIRQ((IRQn_Type) USB_IRQn); /* USB_IRQHandler */ + Usb_Sleep_Status = 0XFF; + } + + //进入低功耗 + SCB->SCR &= ~(1UL << 2); // SCR[2] = 0 (SLEEP) + + md_rcu_set_system_clock_source(RCU, MD_RCU_SW_SYSCLK_HRC); + md_rcu_disable_pll0(RCU); + + if(Keyboard_Info.Key_Mode != QMK_USB_MODE) { + md_rcu_disable_usb(RCU); + md_rcu_disable_hrc48(RCU); + + __WFI(); //Wait For Interrupt + + /*唤醒*/ + md_rcu_enable_hrc48(RCU); + for(i = 0;i < 99999;) { + if(md_rcu_is_active_flag_hrc48_ready(RCU) == MD_RCU_HRC48RDY_READY) + break; + i++; + } + md_rcu_enable_usb(RCU); + } else { //在USB模式下 + md_rcu_enable_usb_in_sleep_mode(RCU); + __WFI(); //Wait For Interrupt + } + + md_rcu_set_system_clock_source(RCU, MD_RCU_SW_SYSCLK_HRC48); + + if ((Keyboard_Info.Key_Mode == QMK_USB_MODE) && (Usb_Sleep_Status == 0XFF)) { + NVIC_EnableIRQ((IRQn_Type) USB_IRQn); + Usb_Sleep_Status = 0XAA; + } + + /*休眠唤醒之后记录唤醒按下按键的位置*/ + uint8_t Sleep_Status = 0x00; + for(i = 0; i < KEYBAORD_ROL; i++) { //ROL + if (!gpio_read_pin(User_Pin_Tab_Rol[i])) { + Sleep_Status |= (1 << i); + } + } + + NVIC_DisableIRQ((IRQn_Type) EXTI_0to1_IRQn); /* EXTI_0to1_IRQn interrupt */ + NVIC_DisableIRQ((IRQn_Type) EXTI_2to3_IRQn); /* EXTI_2to3_IRQn interrupt */ + NVIC_DisableIRQ((IRQn_Type) EXTI_4to15_IRQn); /* EXTI_4to15_IRQn interrupt */ + NVIC_DisableIRQ((IRQn_Type) GP16C4T2_IRQn); /* GP16C4T2_IRQHandler */ + + //唤醒源配置输出高电平 + for(i = 0; i < KEYBAORD_COL; i++) { //COL + gpio_write_pin_high(User_Pin_Tab_Col[i]); + } + + delay = 50; + while(delay--); + + uint8_t Rol_Count = 0,Col_Count = 0; + for (i = 0; i < KEYBAORD_ROL; i++) { + if ((1 << i) & Sleep_Status) { + for(uint8_t j = 0; j < KEYBAORD_COL; j++) { + gpio_write_pin_low(User_Pin_Tab_Col[j]); + + delay = 50; + while(delay--); + + if (!gpio_read_pin(User_Pin_Tab_Rol[i])) { + Rol_Count = i; + Col_Count = j; + break; + } + + for(uint8_t k = 0; k < KEYBAORD_COL; k++) { + gpio_write_pin_high(User_Pin_Tab_Col[j]); + } + + delay = 50; + while(delay--); + } + } + } + + //唤醒源配置输出高电平 + for(i = 0; i < KEYBAORD_COL; i++) { //COL + gpio_write_pin_high(User_Pin_Tab_Col[i]); + } + + gpio_set_pin_input_low(ES_SPI_ACK_IO); //ACK_IO + + md_tick_enable_csr_tickie(TICK); + NVIC_EnableIRQ((IRQn_Type) SysTick_IRQn); + + //在USB模式下 + if(Keyboard_Info.Key_Mode == QMK_USB_MODE) { + if (USBD1.status & 0x2) { + usb_lld_wakeup_host(0); + + uint16_t cnt = 200; + while(cnt--) { + if(USBD1.state != USB_ACTIVE) { + wait_ms(10); + } + } + } + + register_code(dynamic_keymap_get_keycode(0, Rol_Count, Col_Count)); + wait_ms(2); + unregister_code(dynamic_keymap_get_keycode(0, Rol_Count, Col_Count)); + wait_ms(2); + } + + Board_Wakeup_Init(); +} diff --git a/keyboards/womier/common/user_system.h b/keyboards/womier/common/user_system.h new file mode 100644 index 00000000000..a7a47b35d33 --- /dev/null +++ b/keyboards/womier/common/user_system.h @@ -0,0 +1,32 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 void es_mcu_reset(void); +extern void bootloader_jump(void); +extern void mcu_reset(void); + +extern void User_Systime_Init(void); +extern void User_Systime_Deinit(void); + +extern void User_Sleep(void); +extern void User_Wakeup(void); + +extern void Init_Gpio_Infomation(void); +extern void Board_Wakeup_Init(void); +extern void es_chibios_user_idle_loop_hook(void); \ No newline at end of file diff --git a/keyboards/womier/sk75/chconf.h b/keyboards/womier/sk75/chconf.h new file mode 100644 index 00000000000..614e1602a31 --- /dev/null +++ b/keyboards/womier/sk75/chconf.h @@ -0,0 +1,822 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 . + */ + +/** + * @file rt/templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ +#define _CHIBIOS_RT_CONF_VER_7_0_ + +#define CH_CFG_ST_TIMEDELTA 0 +#define CH_CFG_ST_RESOLUTION 16 + +#define CH_CFG_ST_FREQUENCY 1000 +/*===========================================================================*/ +/** + * @name System settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Handling of instances. + * @note If enabled then threads assigned to various instances can + * interact each other using the same synchronization objects. + * If disabled then each OS instance is a separate world, no + * direct interactions are handled by the OS. + */ +#if !defined(CH_CFG_SMP_MODE) +#define CH_CFG_SMP_MODE FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16, 32 or 64 bits. + */ +#if !defined(CH_CFG_ST_RESOLUTION) +#define CH_CFG_ST_RESOLUTION 32 +#endif + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#if !defined(CH_CFG_ST_FREQUENCY) +#define CH_CFG_ST_FREQUENCY 100000 +#endif + +/** + * @brief Time intervals data size. + * @note Allowed values are 16, 32 or 64 bits. + */ +#if !defined(CH_CFG_INTERVALS_SIZE) +#define CH_CFG_INTERVALS_SIZE 32 +#endif + +/** + * @brief Time types data size. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(CH_CFG_TIME_TYPES_SIZE) +#define CH_CFG_TIME_TYPES_SIZE 32 +#endif + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#if !defined(CH_CFG_ST_TIMEDELTA) +#define CH_CFG_ST_TIMEDELTA 2 +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#if !defined(CH_CFG_TIME_QUANTUM) +#define CH_CFG_TIME_QUANTUM 0 +#endif + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#if !defined(CH_CFG_NO_IDLE_THREAD) +#define CH_CFG_NO_IDLE_THREAD FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_OPTIMIZE_SPEED) +#define CH_CFG_OPTIMIZE_SPEED TRUE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_TM) +#define CH_CFG_USE_TM FALSE +#endif + +/** + * @brief Time Stamps APIs. + * @details If enabled then the time stamps APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_TIMESTAMP) +#define CH_CFG_USE_TIMESTAMP TRUE +#endif + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_REGISTRY) +#define CH_CFG_USE_REGISTRY FALSE +#endif + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_WAITEXIT) +#define CH_CFG_USE_WAITEXIT FALSE +#endif + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_SEMAPHORES) +#define CH_CFG_USE_SEMAPHORES TRUE +#endif + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY) +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE +#endif + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MUTEXES) +#define CH_CFG_USE_MUTEXES TRUE +#endif + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE) +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE +#endif + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#if !defined(CH_CFG_USE_CONDVARS) +#define CH_CFG_USE_CONDVARS FALSE +#endif + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT) +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE +#endif + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_EVENTS) +#define CH_CFG_USE_EVENTS TRUE +#endif + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#if !defined(CH_CFG_USE_EVENTS_TIMEOUT) +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE +#endif + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MESSAGES) +#define CH_CFG_USE_MESSAGES FALSE +#endif + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#if !defined(CH_CFG_USE_MESSAGES_PRIORITY) +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE +#endif + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#if !defined(CH_CFG_USE_DYNAMIC) +#define CH_CFG_USE_DYNAMIC FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name OSLIB options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#if !defined(CH_CFG_USE_MAILBOXES) +#define CH_CFG_USE_MAILBOXES FALSE +#endif + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMCORE) +#define CH_CFG_USE_MEMCORE TRUE +#endif + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#if !defined(CH_CFG_MEMCORE_SIZE) +#define CH_CFG_MEMCORE_SIZE 0 +#endif + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#if !defined(CH_CFG_USE_HEAP) +#define CH_CFG_USE_HEAP FALSE +#endif + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_MEMPOOLS) +#define CH_CFG_USE_MEMPOOLS FALSE +#endif + +/** + * @brief Objects FIFOs APIs. + * @details If enabled then the objects FIFOs APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_OBJ_FIFOS) +#define CH_CFG_USE_OBJ_FIFOS FALSE +#endif + +/** + * @brief Pipes APIs. + * @details If enabled then the pipes APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_PIPES) +#define CH_CFG_USE_PIPES FALSE +#endif + +/** + * @brief Objects Caches APIs. + * @details If enabled then the objects caches APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_OBJ_CACHES) +#define CH_CFG_USE_OBJ_CACHES FALSE +#endif + +/** + * @brief Delegate threads APIs. + * @details If enabled then the delegate threads APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_DELEGATES) +#define CH_CFG_USE_DELEGATES FALSE +#endif + +/** + * @brief Jobs Queues APIs. + * @details If enabled then the jobs queues APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(CH_CFG_USE_JOBS) +#define CH_CFG_USE_JOBS FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Objects factory options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Objects Factory APIs. + * @details If enabled then the objects factory APIs are included in the + * kernel. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_CFG_USE_FACTORY) +#define CH_CFG_USE_FACTORY FALSE +#endif + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 +#endif + +/** + * @brief Enables the registry of generic objects. + */ +#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) +#define CH_CFG_FACTORY_OBJECTS_REGISTRY FALSE +#endif + +/** + * @brief Enables factory for generic buffers. + */ +#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) +#define CH_CFG_FACTORY_GENERIC_BUFFERS FALSE +#endif + +/** + * @brief Enables factory for semaphores. + */ +#if !defined(CH_CFG_FACTORY_SEMAPHORES) +#define CH_CFG_FACTORY_SEMAPHORES FALSE +#endif + +/** + * @brief Enables factory for mailboxes. + */ +#if !defined(CH_CFG_FACTORY_MAILBOXES) +#define CH_CFG_FACTORY_MAILBOXES FALSE +#endif + +/** + * @brief Enables factory for objects FIFOs. + */ +#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) +#define CH_CFG_FACTORY_OBJ_FIFOS FALSE +#endif + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_STATISTICS) +#define CH_DBG_STATISTICS FALSE +#endif + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_SYSTEM_STATE_CHECK) +#define CH_DBG_SYSTEM_STATE_CHECK FALSE +#endif + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_CHECKS) +#define CH_DBG_ENABLE_CHECKS FALSE +#endif + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_ENABLE_ASSERTS) +#define CH_DBG_ENABLE_ASSERTS FALSE +#endif + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_MASK) +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED +#endif + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#if !defined(CH_DBG_TRACE_BUFFER_SIZE) +#define CH_DBG_TRACE_BUFFER_SIZE 128 +#endif + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#if !defined(CH_DBG_ENABLE_STACK_CHECK) +#define CH_DBG_ENABLE_STACK_CHECK FALSE +#endif + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#if !defined(CH_DBG_FILL_THREADS) +#define CH_DBG_FILL_THREADS FALSE +#endif + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#if !defined(CH_DBG_THREADS_PROFILING) +#define CH_DBG_THREADS_PROFILING FALSE +#endif + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System structure extension. + * @details User fields added to the end of the @p ch_system_t structure. + */ +#define CH_CFG_SYSTEM_EXTRA_FIELDS \ + /* Add system custom fields here.*/ + +/** + * @brief System initialization hook. + * @details User initialization code added to the @p chSysInit() function + * just before interrupts are enabled globally. + */ +#define CH_CFG_SYSTEM_INIT_HOOK() { \ + /* Add system initialization code here.*/ \ +} + +/** + * @brief OS instance structure extension. + * @details User fields added to the end of the @p os_instance_t structure. + */ +#define CH_CFG_OS_INSTANCE_EXTRA_FIELDS \ + /* Add OS instance custom fields here.*/ + +/** + * @brief OS instance initialization hook. + * + * @param[in] oip pointer to the @p os_instance_t structure + */ +#define CH_CFG_OS_INSTANCE_INIT_HOOK(oip) { \ + /* Add OS instance initialization code here.*/ \ +} + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p _thread_init() function. + * + * @note It is invoked from within @p _thread_init() and implicitly from all + * the threads creation APIs. + * + * @param[in] tp pointer to the @p thread_t structure + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + * + * @param[in] tp pointer to the @p thread_t structure + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + * + * @param[in] ntp thread being switched in + * @param[in] otp thread being switched out + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** + * @brief Runtime Faults Collection Unit hook. + * @details This hook is invoked each time new faults are collected and stored. + */ +#define CH_CFG_RUNTIME_FAULTS_HOOK(mask) { \ + /* Faults handling code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/keyboards/womier/sk75/config.h b/keyboards/womier/sk75/config.h new file mode 100644 index 00000000000..9199606e613 --- /dev/null +++ b/keyboards/womier/sk75/config.h @@ -0,0 +1,97 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 + +/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ +#define LOCKING_SUPPORT_ENABLE +/* Locking resynchronize hack */ +#define LOCKING_RESYNC_ENABLE + +/* Define less important options */ + +/* + * Force NKRO + * + * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved + * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the + * makefile for this to work.) + * + * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) + * until the next keyboard reset. + * + * NKRO may prevent your keystrokes from being detected in the BIOS, but it is + * fully operational during normal computer usage. + * + * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) + * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by + * bootmagic, NKRO mode will always be enabled until it is toggled again during a + * power-up. + * + */ +#define FORCE_NKRO +/* + * Feature disable options + * These options are also useful to firmware size reduction. + */ + +#define MATRIX_UNSELECT_DRIVE_HIGH +#define CORTEX_ENABLE_WFI_IDLE FALSE + +/* Ensure we jump to bootloader if the RESET keycode was pressed */ +#define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE + +#define DEBOUNCE 2 + +#define RGB_MATRIX_LED_COUNT 81 +#define RGB_MATRIX_KEYPRESSES +#define RGB_MATRIX_KEYRELEASES +#define RGB_MATRIX_FRAMEBUFFER_EFFECTS +#define RGB_DISABLE_AFTER_TIMEOUT 0 +#define RGB_MATRIX_LED_FLUSH_LIMIT 16 +#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 180 +#define RGB_MATRIX_SLEEP + + +#define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 1151 +#define EEPROM_SIZE 1152 + +#define FEE_PAGE_SIZE (0x200) +#define FEE_PAGE_COUNT (8) + +#define FEE_PAGE_BASE_ADDRESS (0x1F000) +#define FEE_MCU_FLASH_SIZE (0x1000) + +#define EECONFIG_USER_DATA_SIZE 4 + + +#define MAX_NAME_LEN (18) +#define USER_BlE_ID (0X0036) +#define USER_BlE1_NAME "SK75-1" +#define USER_BlE2_NAME "SK75-2" +#define USER_BlE3_NAME "SK75-3" + +#define KEYBAORD_COL (16) +#define KEYBAORD_ROL (6) + +#define MATRIX_USER_COL_PINS { D15, D14, C15, C14, C13, D3, D2, C12, C11, C10, A14, C9, C8, C7, C6, B15 } +#define MATRIX_USER_ROW_PINS { B0, B3, B4, B5, B6, B7 } + +#define WIN_COL (1) +#define WIN_ROL (3) + +#define MAC_COL (2) +#define MAC_ROL (3) diff --git a/keyboards/womier/sk75/keyboard.json b/keyboards/womier/sk75/keyboard.json new file mode 100644 index 00000000000..19af721cbcb --- /dev/null +++ b/keyboards/womier/sk75/keyboard.json @@ -0,0 +1,172 @@ +{ + "keyboard_name": "SK 75", + "manufacturer": "WOMIER", + "maintainer": "WOMIER", + "url": "womierkeyboard.com", + "usb": { + "vid": "0x36B0", + "pid": "0x3044", + "device_version": "0.0.0" + }, + "matrix_pins": { + "cols": [ "D15", "D14", "C15", "C14", "C13", "D3", "D2", "C12", "C11", "C10", "A14", "C9", "C8", "C7", "C6", "B15" ], + "rows": [ "B0", "B3", "B4", "B5", "B6", "B7" ] + }, + "diode_direction": "ROW2COL", + "features": { + "bootmagic": true, + "extrakey": true, + "nkro": true, + "mousekey": true, + "consolekey": true, + "command": false, + "rgb_matrix": true + }, + "rgb_matrix": { + "driver": "custom", + "animations": { + "solid_color": true, + "alphas_mods": true, + "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, + "cycle_out_in": true, + "cycle_out_in_dual": true, + "rainbow_moving_chevron": true, + "cycle_pinwheel": true, + "cycle_spiral": true, + "dual_beacon": true, + "rainbow_beacon": true, + "rainbow_pinwheels": true, + "flower_blooming": true, + "raindrops": true, + "jellybean_raindrops": true, + "hue_breathing": true, + "hue_pendulum": true, + "hue_wave": true, + "pixel_fractal": false, + "pixel_flow": true, + "pixel_rain": false, + "typing_heatmap": false, + "digital_rain": true, + "solid_reactive_simple": false, + "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, + "starlight": true, + "starlight_dual_hue": true, + "starlight_dual_sat": true, + "riverflow": true + } + }, + "bootloader": "custom", + "layouts": { + "LAYOUT_tkl_ansi": { + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0}, + {"matrix": [0, 1], "x": 1.25, "y": 0}, + {"matrix": [0, 2], "x": 2.25, "y": 0}, + {"matrix": [0, 3], "x": 3.25, "y": 0}, + {"matrix": [0, 4], "x": 4.25, "y": 0}, + {"matrix": [0, 5], "x": 5.5, "y": 0}, + {"matrix": [0, 6], "x": 6.5, "y": 0}, + {"matrix": [0, 7], "x": 7.5, "y": 0}, + {"matrix": [0, 8], "x": 8.5, "y": 0}, + {"matrix": [0, 9], "x": 9.75, "y": 0}, + {"matrix": [0, 10], "x": 10.75, "y": 0}, + {"matrix": [0, 11], "x": 11.75, "y": 0}, + {"matrix": [0, 12], "x": 12.75, "y": 0}, + {"matrix": [2, 14], "x": 14.0, "y": 0}, + {"matrix": [1, 15], "x": 15.0, "y": 0}, + + {"matrix": [1, 0], "x": 0, "y": 1.25}, + {"matrix": [1, 1], "x": 1, "y": 1.25}, + {"matrix": [1, 2], "x": 2, "y": 1.25}, + {"matrix": [1, 3], "x": 3, "y": 1.25}, + {"matrix": [1, 4], "x": 4, "y": 1.25}, + {"matrix": [1, 5], "x": 5, "y": 1.25}, + {"matrix": [1, 6], "x": 6, "y": 1.25}, + {"matrix": [1, 7], "x": 7, "y": 1.25}, + {"matrix": [1, 8], "x": 8, "y": 1.25}, + {"matrix": [1, 9], "x": 9, "y": 1.25}, + {"matrix": [1, 10], "x": 10, "y": 1.25}, + {"matrix": [1, 11], "x": 11, "y": 1.25}, + {"matrix": [1, 12], "x": 12, "y": 1.25}, + {"matrix": [1, 13], "x": 13, "y": 1.25, "w": 2.0}, + {"matrix": [2, 15], "x": 15.0, "y": 1.25}, + + {"matrix": [2, 0], "x": 0, "y": 2.25, "w": 1.5}, + {"matrix": [2, 1], "x": 1.5, "y": 2.25}, + {"matrix": [2, 2], "x": 2.5, "y": 2.25}, + {"matrix": [2, 3], "x": 3.5, "y": 2.25}, + {"matrix": [2, 4], "x": 4.5, "y": 2.25}, + {"matrix": [2, 5], "x": 5.5, "y": 2.25}, + {"matrix": [2, 6], "x": 6.5, "y": 2.25}, + {"matrix": [2, 7], "x": 7.5, "y": 2.25}, + {"matrix": [2, 8], "x": 8.5, "y": 2.25}, + {"matrix": [2, 9], "x": 9.5, "y": 2.25}, + {"matrix": [2, 10], "x": 10.5, "y": 2.25}, + {"matrix": [2, 11], "x": 11.5, "y": 2.25}, + {"matrix": [2, 12], "x": 12.5, "y": 2.25}, + {"matrix": [2, 13], "x": 13.5, "y": 2.25, "w": 1.5}, + {"matrix": [3, 14], "x": 15.0, "y": 2.25}, + + {"matrix": [3, 0], "x": 0, "y": 3.25, "w": 1.75}, + {"matrix": [3, 1], "x": 1.75, "y": 3.25}, + {"matrix": [3, 2], "x": 2.75, "y": 3.25}, + {"matrix": [3, 3], "x": 3.75, "y": 3.25}, + {"matrix": [3, 4], "x": 4.75, "y": 3.25}, + {"matrix": [3, 5], "x": 5.75, "y": 3.25}, + {"matrix": [3, 6], "x": 6.75, "y": 3.25}, + {"matrix": [3, 7], "x": 7.75, "y": 3.25}, + {"matrix": [3, 8], "x": 8.75, "y": 3.25}, + {"matrix": [3, 9], "x": 9.75, "y": 3.25}, + {"matrix": [3, 10], "x": 10.75, "y": 3.25}, + {"matrix": [3, 11], "x": 11.75, "y": 3.25}, + {"matrix": [3, 13], "x": 12.75, "y": 3.25, "w": 2.25}, + {"matrix": [3, 15], "x": 15.0, "y": 3.25}, + + {"matrix": [4, 0], "x": 0, "y": 4.25, "w": 2.25}, + {"matrix": [4, 2], "x": 2.25, "y": 4.25}, + {"matrix": [4, 3], "x": 3.25, "y": 4.25}, + {"matrix": [4, 4], "x": 4.25, "y": 4.25}, + {"matrix": [4, 5], "x": 5.25, "y": 4.25}, + {"matrix": [4, 6], "x": 6.25, "y": 4.25}, + {"matrix": [4, 7], "x": 7.25, "y": 4.25}, + {"matrix": [4, 8], "x": 8.25, "y": 4.25}, + {"matrix": [4, 9], "x": 9.25, "y": 4.25}, + {"matrix": [4, 10], "x": 10.25, "y": 4.25}, + {"matrix": [4, 11], "x": 11.25, "y": 4.25}, + {"matrix": [4, 13], "x": 12.25, "y": 4.25, "w": 1.75}, + {"matrix": [4, 14], "x": 14.0, "y": 4.25}, + + {"matrix": [5, 0], "x": 0, "y": 5.25, "w": 1.25}, + {"matrix": [5, 1], "x": 1.25, "y": 5.25, "w": 1.25}, + {"matrix": [5, 2], "x": 2.5, "y": 5.25, "w": 1.25}, + {"matrix": [5, 5], "x": 3.75, "y": 5.25, "w": 6.25}, + {"matrix": [5, 9], "x": 10, "y": 5.25, "w": 1.25}, + {"matrix": [5, 10], "x": 11.25, "y": 5.25, "w": 1.25}, + {"matrix": [5, 13], "x": 13.0, "y": 5.25}, + {"matrix": [5, 14], "x": 14.0, "y": 5.25}, + {"matrix": [5, 15], "x": 15.0, "y": 5.25} + ] + } + } +} diff --git a/keyboards/womier/sk75/keymaps/default/keymap.c b/keyboards/womier/sk75/keymaps/default/keymap.c new file mode 100644 index 00000000000..f952ca421cd --- /dev/null +++ b/keyboards/womier/sk75/keymaps/default/keymap.c @@ -0,0 +1,52 @@ +/* Copyright 2024 Yiancar-Designs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include QMK_KEYBOARD_H +#include "rdmctmzt_common.h" + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [0] = LAYOUT_tkl_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_DEL, KC_HOME, + 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_END, + 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_K29, KC_PGUP, + 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_PGDN, + 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_LCTL, KC_LGUI, KC_LALT, KC_SPC, MO(2), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + [1] = LAYOUT_tkl_ansi( + KC_ESC, KC_BRID, KC_BRIU, KC_MCTL, KC_LPAD, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, KC_DEL, KC_HOME, + 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_END, + 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_K29, KC_PGUP, + 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_PGDN, + 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_LCTL, KC_LALT, KC_LGUI, KC_SPC, MO(3), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + [2] = LAYOUT_tkl_ansi( + KC_ESC, KC_BRID, KC_BRIU, KC_WHOM, KC_MAIL, KC_CALC, KC_MSEL, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, RGB_TOG, KC_HOME, + KC_GRV, MD_BLE1, MD_BLE2, MD_BLE3, MD_24G, MD_USB, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, QK_BAT, EE_CLR, + 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, RGB_MOD, RGB_SAI, + KC_CAPS, TO(0), TO(1), KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, RGB_HUI, RGB_SAD, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, SIX_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, RGB_VAI, + TEST_CL, QK_WLO, KC_LALT, KC_SPC, KC_NO, KC_RCTL, RGB_SPD, RGB_VAD, RGB_SPI + ), + [3] = LAYOUT_tkl_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, RGB_TOG, KC_HOME, + KC_GRV, MD_BLE1, MD_BLE2, MD_BLE3, MD_24G, MD_USB, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, QK_BAT, EE_CLR, + 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, RGB_MOD, RGB_SAI, + KC_CAPS, TO(0), TO(1), KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, RGB_HUI, RGB_SAD, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, SIX_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, RGB_VAI, + TEST_CL, QK_WLO, KC_LGUI, KC_SPC, KC_NO, KC_RCTL, RGB_SPD, RGB_VAD, RGB_SPI + ) +}; diff --git a/keyboards/womier/sk75/mcuconf.h b/keyboards/womier/sk75/mcuconf.h new file mode 100644 index 00000000000..2f77da756bf --- /dev/null +++ b/keyboards/womier/sk75/mcuconf.h @@ -0,0 +1,222 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 . + */ + +#ifndef MCUCONF_H +#define MCUCONF_H + +#define ES32_FS026_MCUCONF +#define ES32_ES32F0283_MCUCONF + +/* + * HAL driver system settings. + */ +#define ES32_NO_INIT FALSE + +/*system_clk select + +MD_RCU_SW_SYSCLK_HRC = HRC selected as system clock +MD_RCU_SW_SYSCLK_HOSC = HOSC selected as system clock +MD_RCU_SW_SYSCLK_PLL0 = PLL0 selected as system clock +MD_RCU_SW_SYSCLK_HRC48 = HRC48 selected as system clock +*/ +#define ES32_SYSCLK_SOURSE_SELECT MD_RCU_SW_SYSCLK_PLL0 + +/*external clk config*/ +#define ES32_HOSC_CLK_EN FALSE +#define ES32_HOSC_CLK_FREQ 8 + +/*pll clk config + +MD_RCU_PLLSRC_HRC = HRC selected as PLL reference clock +MD_RCU_PLLSRC_HOSC = HOSC selected as PLL reference clock +MD_RCU_PLLSRC_HRC48 = HRC48 selected as PLL reference clock + +MD_RCU_PLLCLK_PASS = 0 +MD_RCU_PLLCLK_4M = 4000000 +MD_RCU_PLLCLK_8M = 8000000 +MD_RCU_PLLCLK_12M = 12000000 +MD_RCU_PLLCLK_16M = 16000000 +MD_RCU_PLLCLK_24M = 24000000 +MD_RCU_PLLCLK_32M = 32000000 +MD_RCU_PLLCLK_36M = 36000000 +MD_RCU_PLLCLK_40M = 40000000 +MD_RCU_PLLCLK_48M = 48000000 +MD_RCU_PLLCLK_64M = 64000000 +MD_RCU_PLLCLK_72M = 72000000 +*/ +#define ES32_PLL_CLK_EN TRUE +#define ES32_PLL_SOURSE_SELECT MD_RCU_PLLSRC_HRC48 +#define ES32_PLL_CLK_FREQ MD_RCU_PLLCLK_72M + +/*bus clk config + +MD_RCU_HPRE_SYSCLK_DIV_1 = SYSCLK not divided +MD_RCU_HPRE_SYSCLK_DIV_2 = SYSCLK divided by 2 +MD_RCU_HPRE_SYSCLK_DIV_4 = SYSCLK divided by 4 +MD_RCU_HPRE_SYSCLK_DIV_8 = SYSCLK divided by 8 +MD_RCU_HPRE_SYSCLK_DIV_16 = SYSCLK divided by 16 +MD_RCU_HPRE_SYSCLK_DIV_64 = SYSCLK divided by 64 +MD_RCU_HPRE_SYSCLK_DIV_128 = SYSCLK divided by 128 +MD_RCU_HPRE_SYSCLK_DIV_256 = SYSCLK divided by 256 +MD_RCU_HPRE_SYSCLK_DIV_512 = @brief SYSCLK divided by 512 + +MD_RCU_PPRE_HCLK_DIV_1 = HCLK not divided +MD_RCU_PPRE_HCLK_DIV_2 = HCLK divided by 2 +MD_RCU_PPRE_HCLK_DIV_4 = HCLK divided by 4 +MD_RCU_PPRE_HCLK_DIV_8 = HCLK divided by 8 +MD_RCU_PPRE_HCLK_DIV_16 = HCLK divided by 16 +*/ +#define ES32_BUS_DIV_HPRE MD_RCU_HPRE_SYSCLK_DIV_1 +#define ES32_BUS_DIV_PPRE MD_RCU_PPRE_HCLK_DIV_1 + +/* + * GPIO driver system settings. + */ +#define ES32_USB_USE_GPIO TRUE + +/* + * EXTI driver system settings. + */ +#define ES32_IRQ_EXTI0_1_PRIORITY 6 +#define ES32_IRQ_EXTI2_3_PRIORITY 6 +#define ES32_IRQ_EXTI4_15_PRIORITY 6 + +/* + * GPT driver system settings. + */ +#define ES32_GPT_USE_AD16C4T1 FALSE +#define ES32_GPT_USE_GP32C4T1 FALSE +#define ES32_GPT_USE_GP16C4T1 FALSE +#define ES32_GPT_USE_GP16C4T2 FALSE +#define ES32_GPT_USE_GP16C4T3 FALSE +#define ES32_GPT_USE_GP16C2T1 FALSE +#define ES32_GPT_USE_GP16C2T2 FALSE +#define ES32_GPT_USE_GP16C2T3 FALSE +#define ES32_GPT_USE_GP16C2T4 FALSE +#define ES32_GPT_USE_BS16T1 FALSE +#define ES32_GPT_AD16C4T1_IRQ_PRIORITY 7 +#define ES32_GPT_GP32C4T1_IRQ_PRIORITY 7 +#define ES32_GPT_GP16C4T1_IRQ_PRIORITY 7 +#define ES32_GPT_GP16C4T2_IRQ_PRIORITY 7 +#define ES32_GPT_GP16C4T3_IRQ_PRIORITY 7 +#define ES32_GPT_GP16C2T1_IRQ_PRIORITY 7 +#define ES32_GPT_GP16C2T2_IRQ_PRIORITY 7 +#define ES32_GPT_GP16C2T3_IRQ_PRIORITY 7 +#define ES32_GPT_GP16C2T4_IRQ_PRIORITY 7 +#define ES32_GPT_BS16T1_IRQ_PRIORITY 7 + +/* + * ICU driver system settings. + */ +#define ES32_ICU_USE_AD16C4T1 FALSE +#define ES32_ICU_USE_GP32C4T1 FALSE +#define ES32_ICU_USE_GP16C4T1 FALSE +#define ES32_ICU_USE_GP16C4T2 FALSE +#define ES32_ICU_USE_GP16C4T3 FALSE +#define ES32_ICU_USE_GP16C2T1 FALSE +#define ES32_ICU_USE_GP16C2T2 FALSE +#define ES32_ICU_USE_GP16C2T3 FALSE +#define ES32_ICU_USE_GP16C2T4 FALSE +#define ES32_ICU_AD16C4T1_IRQ_PRIORITY 7 +#define ES32_ICU_GP32C4T1_IRQ_PRIORITY 7 +#define ES32_ICU_GP16C4T1_IRQ_PRIORITY 7 +#define ES32_ICU_GP16C4T2_IRQ_PRIORITY 7 +#define ES32_ICU_GP16C4T3_IRQ_PRIORITY 7 +#define ES32_ICU_GP16C2T1_IRQ_PRIORITY 7 +#define ES32_ICU_GP16C2T2_IRQ_PRIORITY 7 +#define ES32_ICU_GP16C2T3_IRQ_PRIORITY 7 +#define ES32_ICU_GP16C2T4_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define ES32_I2C_USE_I2C1 FALSE +#define ES32_I2C_USE_I2C2 FALSE +#define ES32_I2C_BUSY_TIMEOUT 50 +#define ES32_I2C_I2C1_IRQ_PRIORITY 5 +#define ES32_I2C_I2C2_IRQ_PRIORITY 5 + +/* + * SERIAL driver system settings. + */ +#define ES32_SERIAL_USE_UART1 FALSE +#define ES32_SERIAL_USE_UART2 FALSE +#define ES32_SERIAL_USE_UART3 FALSE +#define ES32_SERIAL_USE_UART4 FALSE +#define ES32_SERIAL_UART1_PRIORITY 7 +#define ES32_SERIAL_UART2_PRIORITY 7 +#define ES32_SERIAL_UART3_PRIORITY 7 +#define ES32_SERIAL_UART4_PRIORITY 7 + +/* + * SPI driver system settings. + */ +#define ES32_SPI_USE_SPI1 FALSE +#define ES32_SPI_USE_SPI2 FALSE +#define ES32_SPI_USE_SPI3 FALSE +#define ES32_SPI_SPI1_IRQ_PRIORITY 10 +#define ES32_SPI_SPI2_IRQ_PRIORITY 10 +#define ES32_SPI_SPI3_IRQ_PRIORITY 10 + +/* + * ST driver system settings. + */ +#define ES32_ST_IRQ_PRIORITY 8 +#define ES32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define ES32_UART_USE_UART1 FALSE +#define ES32_UART_USE_UART2 FALSE +#define ES32_UART_USE_UART3 FALSE +#define ES32_UART_USE_UART4 FALSE +#define ES32_UART_UART1_IRQ_PRIORITY 12 +#define ES32_UART_UART2_IRQ_PRIORITY 12 +#define ES32_UART_UART3_IRQ_PRIORITY 12 +#define ES32_UART_UART4_IRQ_PRIORITY 12 + +/* + * PWM driver system settings. + */ +#define ES32_PWM_USE_AD16C4T1 FALSE +#define ES32_PWM_USE_GP32C4T1 FALSE +#define ES32_PWM_USE_GP16C4T1 FALSE +#define ES32_PWM_USE_GP16C4T2 TRUE +#define ES32_PWM_USE_GP16C4T3 FALSE +#define ES32_PWM_USE_GP16C2T1 FALSE +#define ES32_PWM_USE_GP16C2T2 FALSE +#define ES32_PWM_USE_GP16C2T3 FALSE +#define ES32_PWM_USE_GP16C2T4 FALSE +#define ES32_PWM_AD16C4T1_IRQ_PRIORITY 7 +#define ES32_PWM_GP32C4T1_IRQ_PRIORITY 7 +#define ES32_PWM_GP16C4T1_IRQ_PRIORITY 7 +#define ES32_PWM_GP16C4T2_IRQ_PRIORITY 7 +#define ES32_PWM_GP16C4T3_IRQ_PRIORITY 7 +#define ES32_PWM_GP16C2T1_IRQ_PRIORITY 7 +#define ES32_PWM_GP16C2T2_IRQ_PRIORITY 7 +#define ES32_PWM_GP16C2T3_IRQ_PRIORITY 7 +#define ES32_PWM_GP16C2T4_IRQ_PRIORITY 7 + +/* + * USB driver system settings. + */ +#define ES32_USB_USE_USB1 TRUE +#define ES32_USB_USB1_IRQ_PRIORITY 13 +#define ES32_USE_USB_SOF_TRIM_HRC48 TRUE + +#endif /* MCUCONF_H */ diff --git a/keyboards/womier/sk75/readme.md b/keyboards/womier/sk75/readme.md new file mode 100644 index 00000000000..6f760a38e0f --- /dev/null +++ b/keyboards/womier/sk75/readme.md @@ -0,0 +1,22 @@ +# sk75 + +![sk75](https://imgur.com/nmvoI6z) + +A customizable 81key keyboard. + +* Keyboard Maintainer: [LiWenLiu](https://github.com/LiuLiuQMK) +* Hardware Supported: sk75 PCB with ES32FS026 microcontroller +* Hardware Availability: Check the wob page on [sk75's website](www.womierkeyboard.com) + + +Make example for this keyboard (after setting up your build environment): + + make womier/sk75:default + +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 1 ways: + +* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (Esc key) and plug in the keyboard diff --git a/keyboards/womier/sk75/rules.mk b/keyboards/womier/sk75/rules.mk new file mode 100644 index 00000000000..140d5742f96 --- /dev/null +++ b/keyboards/womier/sk75/rules.mk @@ -0,0 +1,51 @@ + +VPATH += keyboards/womier/common +SRC += rdmctmzt_common.c +SRC += quantum/dynamic_keymap.c +SRC += three_mode.c +SRC += user_battery.c +SRC += user_eeprom.c +SRC += user_emi.c +SRC += user_led_custom.c +SRC += user_spi.c +SRC += user_system.c + +VPATH += lib/chibios-contrib/os/common/ext/CMSIS/ES32/FS026/md +# SRC += lib/chibios-contrib/os/common/ext/CMSIS/ES32/FS026/md/md_adc.c +SRC += lib/chibios-contrib/os/common/ext/CMSIS/ES32/FS026/md/md_spi.c + +# Board: it should exist either in /os/hal/boards/ +# or /boards +BOARD = FS026 + +# Cortex version +MCU = cortex-m0 + +# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 +ARMV = 6 + +## chip/board settings +# - the next two should match the directories in +# /os/hal/ports/$(MCU_PORT_NAME)/$(MCU_SERIES) +# OR +# /os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +MCU_FAMILY = ES32 +MCU_SERIES = FS026 + +# Linker script to use +# - it should exist either in /os/common/startup/ARMCMx/compilers/GCC/ld/ +# or /ld/ +MCU_LDSCRIPT ?= FS026 + +# Startup code to use +# - it should exist in /os/common/startup/ARMCMx/compilers/GCC/mk/ +MCU_STARTUP ?= FS026 + +USE_FPU ?= no + +EEPROM_DRIVER = custom +NO_USB_STARTUP_CHECK = yes +BLUETOOTH_CUSTOM = yes + +DEBOUNCE_TYPE = asym_eager_defer_pk + diff --git a/keyboards/womier/sk75/sk75.c b/keyboards/womier/sk75/sk75.c new file mode 100644 index 00000000000..d21fd9600e6 --- /dev/null +++ b/keyboards/womier/sk75/sk75.c @@ -0,0 +1,594 @@ +/* Copyright 2024 Finalkey + * Copyright 2024 LiWenLiu + * + * 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 "rdmctmzt_common.h" + +bool Key_Fn_Status = false; +bool User_Key_Batt_Num_Show = false; +uint8_t User_Key_Batt_Count = 0; +uint8_t Led_Point_Count = 0U; +uint8_t Mac_Win_Point_Count = 0U; +bool Test_Led = false; +uint8_t Test_Colour = 0U; + +uint8_t Led_Batt_Index_Tab[10] = { + 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 +}; + + +#define LED_CAP_INDEX (45) +#define LED_WIN_L_INDEX (73) +#define LED_BATT_INDEX (0) + +#define LED_A_INDEX (46) +#define LED_S_INDEX (47) + +#define LED_BLE_1_INDEX (16) +#define LED_BLE_2_INDEX (17) +#define LED_BLE_3_INDEX (18) +#define LED_2P4G_INDEX (19) +#define LED_USB_INDEX (20) + +led_config_t g_led_config = { { + { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , NO_LED , NO_LED , NO_LED }, + { 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , NO_LED , 14 }, + { 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 13 , 29 }, + { 45 , 46 , 47 , 48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 , NO_LED , 57 , 44 , 58 }, + { 59 , NO_LED , 60 , 61 , 62 , 63 , 64 , 65 , 66 , 67 , 68 , 69 , NO_LED , 70 , 71 , NO_LED }, + { 72 , 73 , 74 , NO_LED , NO_LED , 75 , NO_LED , NO_LED , NO_LED , 76 , 77 , NO_LED , NO_LED , 78 , 79 , 80 } +},{ + // "Fine-tuned" complex configuration + { 0, 10}, { 15, 10}, { 30, 10}, { 45, 10}, { 60, 10}, { 75, 10}, { 90, 10}, { 105, 10}, { 120, 10}, { 135, 10}, { 150, 10}, { 165, 10}, { 180, 10}, { 195, 10}, { 208, 10}, + { 0, 20}, { 15, 20}, { 30, 20}, { 45, 20}, { 60, 20}, { 75, 20}, { 90, 20}, { 105, 20}, { 120, 20}, { 135, 20}, { 150, 20}, { 165, 20}, { 180, 20}, { 195, 20}, { 208, 20}, + { 0, 30}, { 15, 30}, { 30, 30}, { 45, 30}, { 60, 30}, { 75, 30}, { 90, 30}, { 105, 30}, { 120, 30}, { 135, 30}, { 150, 30}, { 165, 30}, { 180, 30}, { 195, 30}, { 208, 30}, + { 0, 40}, { 15, 40}, { 30, 40}, { 45, 40}, { 60, 40}, { 75, 40}, { 90, 40}, { 105, 40}, { 120, 40}, { 135, 40}, { 150, 40}, { 165, 40}, { 195, 40}, { 208, 40}, + { 0, 50}, { 15, 50}, { 30, 50}, { 45, 50}, { 60, 50}, { 75, 50}, { 90, 50}, { 105, 50}, { 120, 50}, { 135, 50}, { 150, 50}, { 165, 50}, { 180, 50}, + { 0, 60}, { 15, 60}, { 30, 60}, { 75, 60}, { 135, 60}, { 150, 60}, { 180, 60}, { 195, 60}, { 208, 60} +}, { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1 +} }; + +void Led_Rf_Mode_Show(void) { + uint8_t Temp_Colour = 0,Led_Index = 0; + if (Keyboard_Info.Key_Mode == QMK_BLE_MODE) { + if (Keyboard_Info.Ble_Channel == QMK_BLE_CHANNEL_1) { + Temp_Colour = 5; + Led_Index = LED_BLE_1_INDEX; + } else if (Keyboard_Info.Ble_Channel == QMK_BLE_CHANNEL_2) { + Temp_Colour = 5; + Led_Index = LED_BLE_2_INDEX; + } else if (Keyboard_Info.Ble_Channel == QMK_BLE_CHANNEL_3) { + Temp_Colour = 5; + Led_Index = LED_BLE_3_INDEX; + } + } else if (Keyboard_Info.Key_Mode == QMK_2P4G_MODE) { + Temp_Colour = 3; + Led_Index = LED_2P4G_INDEX; + } + + if (Keyboard_Status.System_Connect_Status == KB_MODE_CONNECT_PAIR) { + if (Systick_Led_Count < 10) { + rgb_matrix_set_color(Led_Index, Led_Colour_Tab[Temp_Colour][0], Led_Colour_Tab[Temp_Colour][1], Led_Colour_Tab[Temp_Colour][2]); + } else { + rgb_matrix_set_color(Led_Index, 0, 0, 0); + } + + if (Systick_Led_Count >= 20) { + Systick_Led_Count = 0; + } + } else if (Keyboard_Status.System_Connect_Status == KB_MODE_CONNECT_RETURN) { + if (Systick_Led_Count < 25) { + rgb_matrix_set_color(Led_Index, Led_Colour_Tab[Temp_Colour][0], Led_Colour_Tab[Temp_Colour][1], Led_Colour_Tab[Temp_Colour][2]); + } else { + rgb_matrix_set_color(Led_Index, 0, 0, 0); + } + + if (Systick_Led_Count >= 50) { + Systick_Led_Count = 0; + } + } else { + rgb_matrix_set_color(Led_Index, Led_Colour_Tab[Temp_Colour][0], Led_Colour_Tab[Temp_Colour][1], Led_Colour_Tab[Temp_Colour][2]); + + if (Systick_Led_Count >= 240) { + Systick_Led_Count = 0; + Led_Rf_Pair_Flg = false; + if (Keyboard_Info.Key_Mode == QMK_BLE_MODE) { + User_Batt_Send_Spi = true; + } + } + } +} + +void Led_Power_Low_Show(void) { + for (uint8_t i = 0; i < RGB_MATRIX_LED_COUNT; i++) { + rgb_matrix_set_color(i, 0, 0, 0); + } + + if (Systick_Led_Count < 25) { + rgb_matrix_set_color(LED_BATT_INDEX, U_PWM, 0x00, 0x00); + } else { + rgb_matrix_set_color(LED_BATT_INDEX, 0x00, 0x00, 0x00); + } + + if (Systick_Led_Count >= 50) { + Systick_Led_Count = 0; + } +} + +void Led_Point_Flash_Show(void) { + if (Systick_Led_Count < 25) { + if (Led_Point_Count) { + rgb_matrix_driver_set_color_all(U_PWM, U_PWM, U_PWM); + } else { + rgb_matrix_driver_set_color_all(U_PWM, U_PWM, 0X00); + } + } else { + rgb_matrix_driver_set_color_all(0X00, 0X00, 0X00); + } + + if (Systick_Led_Count >= 50) { + Systick_Led_Count = 0; + + if (Led_Point_Count) { + Led_Point_Count--; + } else if (Mac_Win_Point_Count) { + Mac_Win_Point_Count--; + } + } +} + +void Led_Batt_Number_Show(void) { + if (es_stdby_pin_state == 1) { + if (Batt_Led_Count >= 2) { + Batt_Led_Count = 0; + + if (User_Key_Batt_Count > 3) { + User_Key_Batt_Count -= 3; + } else { + User_Key_Batt_Count = 127; + } + } + + uint8_t Tmep_Pwm = User_Key_Batt_Count; + + for (uint8_t i = 0; i < 10; i++) { + rgb_matrix_set_color(Led_Batt_Index_Tab[i], 0X00, Led_Wave_Pwm_Tab[Tmep_Pwm], 0X00); + Tmep_Pwm += 8; + if (Tmep_Pwm >= 128) { + Tmep_Pwm -= 128; + } + } + } else if (es_stdby_pin_state == 2) { + for (uint8_t i = 0; i < 10; i++) { + rgb_matrix_set_color(Led_Batt_Index_Tab[i], 0X00, 0XFF, 0X00); + } + } else { + uint8_t Colour_R = 0, Colour_G = 0, Colour_B = 0; + uint8_t Temp_Count = (Keyboard_Info.Batt_Number / 10) + 1; + if (Temp_Count >= 10) { + Temp_Count = 10; + } + + if (Temp_Count < 3) { + Colour_R = 0XFF; Colour_G = 0X00; Colour_B = 0X00; + } else if (Temp_Count < 6) { + Colour_R = 0XFF; Colour_G = 0XFF; Colour_B = 0X00; + } else { + Colour_R = 0X00; Colour_G = 0XFF; Colour_B = 0X00; + } + + for (uint8_t i = 0; i < Temp_Count; i++) { + rgb_matrix_set_color(Led_Batt_Index_Tab[i], Colour_R, Colour_G, Colour_B); + } + } +} + +void User_Point_Show(void){ + if (Led_Point_Count || Mac_Win_Point_Count) { + Led_Point_Flash_Show(); + } else { + Systick_Led_Count = 0; + + if (Keyboard_Info.Key_Mode == QMK_USB_MODE) { + if (host_keyboard_led_state().caps_lock && Usb_If_Ok_Led) { + rgb_matrix_set_color(LED_CAP_INDEX, U_PWM, U_PWM, U_PWM); + } + } else { + if (Keyboard_Status.System_Led_Status & 0x02) { + rgb_matrix_set_color(LED_CAP_INDEX, U_PWM, U_PWM, U_PWM); + } + } + + if (Keyboard_Info.Win_Lock) { + rgb_matrix_set_color(LED_WIN_L_INDEX, U_PWM, U_PWM, U_PWM); + } + } +} + +void User_Test_Colour_Show(void){ + uint8_t Test_R = 0, Test_G = 0, Test_B = 0; + switch(Test_Colour) { + case 0: Test_R = RGB_MATRIX_MAXIMUM_BRIGHTNESS; Test_G = 0; Test_B = 0; break; + case 1: Test_R = 0; Test_G = RGB_MATRIX_MAXIMUM_BRIGHTNESS; Test_B = 0; break; + case 2: Test_R = 0; Test_G = 0; Test_B = RGB_MATRIX_MAXIMUM_BRIGHTNESS; break; + case 3: Test_R = RGB_MATRIX_MAXIMUM_BRIGHTNESS; Test_G = RGB_MATRIX_MAXIMUM_BRIGHTNESS; Test_B = RGB_MATRIX_MAXIMUM_BRIGHTNESS; break; + default: Test_R = RGB_MATRIX_MAXIMUM_BRIGHTNESS; Test_G = RGB_MATRIX_MAXIMUM_BRIGHTNESS; Test_B = RGB_MATRIX_MAXIMUM_BRIGHTNESS; break; + } + rgb_matrix_driver_set_color_all(Test_R, Test_G, Test_B); +} + +bool rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { + if (User_Power_Low) { + Led_Power_Low_Show(); + } else if (Test_Led) { + User_Test_Colour_Show(); + } else if (Led_Rf_Pair_Flg && (Keyboard_Info.Key_Mode != QMK_USB_MODE)) { + Led_Rf_Mode_Show(); + } else if (User_Key_Batt_Num_Show) { + Led_Batt_Number_Show(); + } else { + User_Point_Show(); + + if (Key_Fn_Status) { + switch (Keyboard_Info.Key_Mode) { + case QMK_BLE_MODE: { + switch (Keyboard_Info.Ble_Channel) { + case QMK_BLE_CHANNEL_1: rgb_matrix_set_color(LED_BLE_1_INDEX, U_PWM, U_PWM, U_PWM); break; + case QMK_BLE_CHANNEL_2: rgb_matrix_set_color(LED_BLE_2_INDEX, U_PWM, U_PWM, U_PWM); break; + case QMK_BLE_CHANNEL_3: rgb_matrix_set_color(LED_BLE_3_INDEX, U_PWM, U_PWM, U_PWM); break; + default: break; + } + } break; + case QMK_2P4G_MODE: rgb_matrix_set_color(LED_2P4G_INDEX, U_PWM, U_PWM, U_PWM); break; + case QMK_USB_MODE: rgb_matrix_set_color(LED_USB_INDEX, U_PWM, U_PWM, U_PWM); break; + default: break; + } + } + } + + return false; +} + +void notify_usb_device_state_change_user(enum usb_device_state usb_device_state) { + if (Keyboard_Info.Key_Mode == QMK_USB_MODE) { + if(usb_device_state == USB_DEVICE_STATE_CONFIGURED) { + Usb_If_Ok_Led = true; + } else { + Usb_If_Ok_Led = false; + } + } else { + Usb_If_Ok_Led = false; + } +} + +void matrix_io_delay(void) { +} + +void matrix_output_select_delay(void) { +} + +void matrix_output_unselect_delay(uint8_t line, bool key_pressed) { +} + +void housekeeping_task_user(void) { + if (Keyboard_Reset) { + Keyboard_Reset = false; + + Keyboard_Info.Nkro = INIT_ALL_KEY; + Keyboard_Info.Mac_Win_Mode = INIT_WIN_MODE; + Keyboard_Info.Win_Lock = INIT_WIN_NLOCK; + Reset_Save_Flash = true; + /*将当前模式写入flash*/ + eeprom_write_block_user((void *)&Keyboard_Info.Key_Mode, 0, sizeof(Keyboard_Info_t)); + Reset_Save_Flash = false; + + #ifdef NO_RESET + eeconfig_init(); + #else + eeconfig_disable(); + soft_reset_keyboard(); + #endif + return; + } + + es_chibios_user_idle_loop_hook(); +} + +void board_init(void) { + es_ble_spi_init(); //SPI + + User_Adc_Init(); //ADC + + eeprom_driver_init(); //EEPROM + + rgb_matrix_driver_init(); //PWM DMA + + Init_Gpio_Infomation(); //GPIO + + Init_Keyboard_Infomation(); + + Init_Batt_Infomation(); + + User_Systime_Init(); + + if (Keyboard_Info.Key_Mode == QMK_USB_MODE) { + User_Usb_Init(); + Led_Rf_Pair_Flg = false; + } else { + Usb_Disconnect(); + } + + Init_Spi_Power_Up = true; + Init_Spi_100ms_Delay = 0; + Spi_Interval = SPI_DELAY_RF_TIME; + NVIC_SetPriority(PendSV_IRQn, 3); + NVIC_SetPriority(SysTick_IRQn, 3); + + Usb_If_Ok_Led = false; + Led_Power_Up = false; + Emi_Test_Start = false; + Keyboard_Reset = false; +} + +void keyboard_post_init_user(void) { + if (keymap_config.nkro != Keyboard_Info.Nkro) { + keymap_config.nkro = Keyboard_Info.Nkro; + } + + if (Keyboard_Info.Mac_Win_Mode) { + uint8_t current_layer = get_highest_layer(layer_state); + if (current_layer != 1) { + layer_on(1); + } + } +} + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + Usb_Change_Mode_Delay = 0; + Usb_Change_Mode_Wakeup = false; + + if (Test_Led) { + if ((keycode != KC_SPC) && (keycode != MO(2)) && (keycode != MO(3)) && (keycode != KC_LCTL)) { + Test_Led = false; + } + } + + switch (keycode) { + case QMK_KB_MODE_2P4G: { //2.4G + if (record->event.pressed) { + Key_2p4g_Status = true; + Usb_Disconnect(); + if (Keyboard_Info.Key_Mode != QMK_2P4G_MODE) { + Keyboard_Info.Key_Mode = QMK_2P4G_MODE; + Spi_Send_Commad(USER_SWITCH_2P4G_MODE); + Save_Flash_Set(); + Led_Rf_Pair_Flg = true; + } + } else { + Key_2p4g_Status = false; + } + Time_3s_Count = 0; + } return true; + case QMK_KB_MODE_BLE1: { + if (record->event.pressed) { + Key_Ble_1_Status = true; + Usb_Disconnect(); + if ((Keyboard_Info.Key_Mode != QMK_BLE_MODE) || ((Keyboard_Info.Key_Mode == QMK_BLE_MODE) && (Keyboard_Info.Ble_Channel != QMK_BLE_CHANNEL_1))) { /*如果当前模式不是BLE模式则切换为BLE,或者BLE通道不相同*/ + Keyboard_Info.Key_Mode = QMK_BLE_MODE; + Keyboard_Info.Ble_Channel = QMK_BLE_CHANNEL_1; + Spi_Send_Commad(USER_SWITCH_BLE_1_MODE); + Save_Flash_Set(); + Led_Rf_Pair_Flg = true; + } + } else { + Key_Ble_1_Status = false; + } + Time_3s_Count = 0; + } return true; + case QMK_KB_MODE_BLE2: { + if (record->event.pressed) { + Key_Ble_2_Status = true; + Usb_Disconnect(); + if ((Keyboard_Info.Key_Mode != QMK_BLE_MODE) || ((Keyboard_Info.Key_Mode == QMK_BLE_MODE) && (Keyboard_Info.Ble_Channel != QMK_BLE_CHANNEL_2))) { /*如果当前模式不是BLE模式则切换为BLE,或者BLE通道不相同*/ + Keyboard_Info.Key_Mode = QMK_BLE_MODE; + Keyboard_Info.Ble_Channel = QMK_BLE_CHANNEL_2; + Spi_Send_Commad(USER_SWITCH_BLE_2_MODE); + Save_Flash_Set(); + Led_Rf_Pair_Flg = true; + } + } else { + Key_Ble_2_Status = false; + } + Time_3s_Count = 0; + } return true; + case QMK_KB_MODE_BLE3: { + if (record->event.pressed) { + Key_Ble_3_Status = true; + Usb_Disconnect(); + if ((Keyboard_Info.Key_Mode != QMK_BLE_MODE) || ((Keyboard_Info.Key_Mode == QMK_BLE_MODE) && (Keyboard_Info.Ble_Channel != QMK_BLE_CHANNEL_3))) { /*如果当前模式不是BLE模式则切换为BLE,或者BLE通道不相同*/ + Keyboard_Info.Key_Mode = QMK_BLE_MODE; + Keyboard_Info.Ble_Channel = QMK_BLE_CHANNEL_3; + Spi_Send_Commad(USER_SWITCH_BLE_3_MODE); + Save_Flash_Set(); + Led_Rf_Pair_Flg = true; + } + } else { + Key_Ble_3_Status = false; + } + Time_3s_Count = 0; + } return true; + case QMK_KB_MODE_USB: { + if (record->event.pressed) { + if (Keyboard_Info.Key_Mode != QMK_USB_MODE) { + Keyboard_Info.Key_Mode = QMK_USB_MODE; + Spi_Send_Commad(USER_SWITCH_USB_MODE); + es_restart_usb_driver(); + Save_Flash_Set(); + Led_Rf_Pair_Flg = false; + } + } + } return true; + case QMK_BATT_NUM: { + if (record->event.pressed) { + User_Key_Batt_Num_Show = true; + User_Key_Batt_Count = 0; + } else { + User_Key_Batt_Num_Show = false; + User_Key_Batt_Count = 0; + } + } return true; + case QMK_WIN_LOCK: { + if (!record->event.pressed) { + if (Keyboard_Info.Mac_Win_Mode == INIT_MAC_MODE) { + if (Keyboard_Info.Win_Lock == INIT_WIN_LOCK) { + Keyboard_Info.Win_Lock = INIT_WIN_NLOCK; + Save_Flash_Set(); + } + } else { + if (Keyboard_Info.Win_Lock == INIT_WIN_NLOCK) { + Keyboard_Info.Win_Lock = INIT_WIN_LOCK; + unregister_code(KC_LGUI); unregister_code(KC_RGUI); unregister_code(KC_APP); + } else { + Keyboard_Info.Win_Lock = INIT_WIN_NLOCK; + } + Save_Flash_Set(); + } + } + } return true; + case QMK_KB_SIX_N_CH: { + if (record->event.pressed) { + if(keymap_config.nkro) { + es_change_qmk_nkro_mode_disable(); + Mac_Win_Point_Count = 3; + } else { + es_change_qmk_nkro_mode_enable(); + Led_Point_Count = 3; + } + } + } return true; + case QMK_TEST_COLOUR: { + if (!record->event.pressed) { + if (Test_Led == false) { + Test_Led = true; + Test_Colour = 0; + } + } + } return true; + case KC_SPC: { + if (!record->event.pressed) { + if (Test_Led) { + Test_Colour++; + if (Test_Colour >= 4) { + Test_Colour = 0; + } + } + } + } return true; + case KC_LGUI: { //key_win_l + if (Keyboard_Info.Win_Lock) { + record->event.pressed = false; + } + } return true; + case KC_RGUI: { //key_win_r + if (Keyboard_Info.Win_Lock) { + record->event.pressed = false; + } + } return true; + case KC_APP: { //key_app + if (Keyboard_Info.Win_Lock) { + record->event.pressed = false; + } + } return true; + case RGB_VAI: { + if (!record->event.pressed) { + if (rgb_matrix_get_val() >= RGB_MATRIX_MAXIMUM_BRIGHTNESS) { + Led_Point_Count = 3; + } + } + } return true; + case RGB_VAD: { + if (!record->event.pressed) { + if (rgb_matrix_get_val() <= 0) { + Led_Point_Count = 3; + } + } + } return true; + case RGB_SPI: { + if (!record->event.pressed) { + if (rgb_matrix_get_speed() >= 255) { + Led_Point_Count = 3; + } + } + } return true; + case RGB_SPD: { + if (!record->event.pressed) { + if (rgb_matrix_get_speed() <= 0) { + Led_Point_Count = 3; + } + } + } return true; + case MO(2): { //FN + if (record->event.pressed) { + Key_Fn_Status = true; + } else { + Key_Fn_Status = false; + } + } return true; + case MO(3): { //FN + if (record->event.pressed) { + Key_Fn_Status = true; + } else { + Key_Fn_Status = false; + } + } return true; + case TO(0): { //WIN + if (!record->event.pressed) { + if ((record->event.key.col == WIN_COL) && (record->event.key.row == WIN_ROL) && (Keyboard_Info.Mac_Win_Mode != INIT_WIN_MODE)) { + Keyboard_Info.Mac_Win_Mode = INIT_WIN_MODE; + Mac_Win_Point_Count = 1; + unregister_code(KC_LALT); unregister_code(KC_LGUI); unregister_code(KC_RALT); unregister_code(KC_RGUI); unregister_code(KC_APP); + Save_Flash_Set(); + } + } + } return true; + case TO(1): { //MAC + if (!record->event.pressed) { + if ((record->event.key.col == MAC_COL) && (record->event.key.row == MAC_ROL) && (Keyboard_Info.Mac_Win_Mode != INIT_MAC_MODE)) { + Keyboard_Info.Mac_Win_Mode = INIT_MAC_MODE; + Keyboard_Info.Win_Lock = INIT_WIN_NLOCK; + Mac_Win_Point_Count = 3; + unregister_code(KC_LALT); unregister_code(KC_LGUI); unregister_code(KC_RALT); unregister_code(KC_RGUI); unregister_code(KC_APP); + Save_Flash_Set(); + } + } + } return true; + case EE_CLR: { + if (record->event.pressed) { + Key_Reset_Status = true; + record->event.pressed = false; + } else { + Key_Reset_Status = false; + } + Func_Time_3s_Count = 0; + } return true; + default: return true; // Process all other keycodes normally + } +}