From fe169b64f641f6c893a91faff1420573866a333c Mon Sep 17 00:00:00 2001 From: true Date: Fri, 8 May 2026 20:07:06 -0700 Subject: [PATCH] basic button handler routines added, hard buttons tested touch sensors were also preliminary tested but not all have been analyzed yet. --- firmware/app/driver/adc.c | 24 ++++++--- firmware/app/main.c | 18 ++++--- firmware/app/ui/btn.c | 97 ++++++++++++++++++++++++++++++++++++- firmware/app/ui/btn.h | 43 ++++++++++++++++ firmware/linker/ch32x035.ld | 9 ++++ 5 files changed, 175 insertions(+), 16 deletions(-) create mode 100644 firmware/app/ui/btn.h diff --git a/firmware/app/driver/adc.c b/firmware/app/driver/adc.c index 2768be4..a1b2b48 100644 --- a/firmware/app/driver/adc.c +++ b/firmware/app/driver/adc.c @@ -19,6 +19,7 @@ #define TOUCH_DEFAULT_CHARGE 0x4c #define TOUCH_DEFAULT_THRESH 0x800 +#define TOUCH_HYSTERESIS 66 typedef struct AdcChan { @@ -35,6 +36,8 @@ typedef struct AdcChan { static uint8_t adc_idx = 0; static AdcChan adc_chan[ADC_CHANNELS] = {0}; +static uint32_t touch_status = 0; + void adc_init() @@ -57,6 +60,7 @@ void adc_init() adc_chan[1].thresh = 3580; adc_chan[2].chan = ADC_Channel_2; + adc_chan[2].timing = 0x6f; adc_chan[2].thresh = 3380; adc_chan[3].chan = ADC_Channel_3; @@ -108,16 +112,10 @@ void adc_init() int8_t adc_get_tkey(uint8_t key_idx) { - if (key_idx > ADC_CHANNELS) - return 0; - - if (adc_chan[key_idx].avg < adc_chan[key_idx].thresh) { - return 1; - } - - return 0; + return (touch_status & (1 << key_idx) ? 1 : 0); } +__attribute((section(".ramfunc"))) void adc_next() { AdcChan *chan; @@ -205,6 +203,16 @@ void adc_isr() v += chan->rawval[i]; } chan->avg = v >> ashift; + + // calculate if touched if measuring a touch sensor + if (amax == 4) { + if (chan->avg <= chan->thresh) { + touch_status |= (1 << adc_idx); + } + if (chan->avg > (chan->thresh + TOUCH_HYSTERESIS)) { + touch_status &= ~(1 << adc_idx); + } + } } } diff --git a/firmware/app/main.c b/firmware/app/main.c index bc64605..206b66d 100644 --- a/firmware/app/main.c +++ b/firmware/app/main.c @@ -26,6 +26,8 @@ #include "led/matrix.h" #include "led/ledprog.h" +#include "ui/btn.h" + /* *@Note ***Only PA0--PA15 and PC16--PC17 support input pull-down. @@ -39,13 +41,13 @@ volatile uint8_t lp_render = 0; -void clk_init() +inline void clk_init() { SystemCoreClockUpdate(); } -void periphclk_init() +static inline void periphclk_init() { // needed for GPIO, remap, ADC, SPI RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | @@ -59,7 +61,7 @@ void periphclk_init() RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 | RCC_AHBPeriph_USBPD, ENABLE); } -void gpio_init() +static inline void gpio_init() { GPIO_InitTypeDef gpio = {0}; @@ -90,7 +92,7 @@ void gpio_init() gpio.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_11 | GPIO_Pin_12; GPIO_Init(GPIOB, &gpio); - // PC10 USB DP (btn2), PC11 USB DM (unused) + // PC16 USB DM (unused), PC17 USB DP (btn2) gpio.GPIO_Mode = GPIO_Mode_IPD; gpio.GPIO_Pin = GPIO_Pin_16 | GPIO_Pin_17; GPIO_Init(GPIOC, &gpio); @@ -105,7 +107,7 @@ void gpio_init() // todo later } -void awu_init() +static inline void awu_init() { NVIC_InitTypeDef nvic; EXTI_InitTypeDef exti = {0}; @@ -174,12 +176,13 @@ int main(void) // stay a while // __WFI(); - PWR_EnterSTANDBYMode(); + // PWR_EnterSTANDBYMode(); } } void AWU_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); + void AWU_IRQHandler(void) { // clear interrupt flag @@ -204,5 +207,6 @@ void AWU_IRQHandler(void) // handle ADC adc_next(); - // handle buttons + // handle buttons and touch sensors + btn_process(); } \ No newline at end of file diff --git a/firmware/app/ui/btn.c b/firmware/app/ui/btn.c index 4909e19..6db4676 100644 --- a/firmware/app/ui/btn.c +++ b/firmware/app/ui/btn.c @@ -3,4 +3,99 @@ */ #include "ch32x035_conf.h" -#include "driver/adc.h" \ No newline at end of file +#include "btn.h" + +#include "driver/adc.h" + + + +BtnSub btn[BTN_COUNT]; + +uint16_t btn_pushed; +uint16_t btn_held; + + + +void btn_push_cb(uint8_t idx) +{ + if (!(btn_pushed & (1 << idx))) { + btn_pushed |= (1 << idx); + if (btn[idx].cb_push) btn[idx].cb_push(idx); + } +} + +void btn_hold_cb(uint8_t idx) +{ + btn_held |= (1 << idx); + if (btn[idx].cb_hold) btn[idx].cb_hold(idx); +} + +void btn_release_cb(uint8_t idx) +{ + btn_pushed &= ~(1 << idx); + btn_held &= ~(1 << idx); + if (btn[idx].cb_release) btn[idx].cb_release(idx); +} + +void btn_process() +{ + uint16_t i; + uint32_t x; + uint16_t btn_state[4] = {0}; + + // fill button bitfield + for (i = 0; i < BTN_COUNT; i++) { + if (i == 0) { + // GPIOC pulldown button + x = GPIOC->INDR & (1 << 10); // PC10 (or PC17) + } else if (i < 3) { + // GPIOB pullup buttons + x = !(GPIOB->INDR & (1 << (i + 10))); // PB11, PB12 + } else { + // touch sensors + x = adc_get_tkey(i - 3); + } + + // is pushed? + if (x) { + if (btn[i].hold != 0xffff) + btn[i].hold++; + + if (btn[i].hold == DEBOUNCE) { + btn_state[1] |= (1 << (i + 3)); + } + } + + // is held? + if (btn[i].hold == HOLD_COUNTS) { + btn_state[2] |= (1 << (i + 3)); + } + + // is repeated? + if (btn[i].repeat && (btn[i].hold == (HOLD_COUNTS + btn[i].repeat))) { + btn_state[2] |= (1 << (i + 3)); + btn[i].hold = HOLD_COUNTS; + } + + // is released? + if (!x) { + if (btn[i].hold) { + btn[i].hold = 0; + btn_state[3] |= (1 << (i + 3)); + } + } + } + + // process callbacks for new events + for (i = 0; i < BTN_COUNT; i++) { + if (btn_state[1] & (1 << i)) { + btn_push_cb(i); + } + if (btn_state[2] & (1 << i)) { + btn_hold_cb(i); + } + if (btn_state[3] & (1 << i)) { + btn_release_cb(i); + } + } +} diff --git a/firmware/app/ui/btn.h b/firmware/app/ui/btn.h new file mode 100644 index 0000000..f58b804 --- /dev/null +++ b/firmware/app/ui/btn.h @@ -0,0 +1,43 @@ +/* + * btn.h + * + * Created on: Oct 13, 2024 + * Author: true + */ + +#ifndef USER_UI_BTN_H_ +#define USER_UI_BTN_H_ + + +#include + + + +#define HB_COUNT 3 // total hard buttons in system +#define TS_COUNT 7 // total touch sensors in system +#define BTN_COUNT (HB_COUNT + TS_COUNT) // total buttons in system + +#define DEBOUNCE 12 +#define HOLD_COUNTS 600 // how long until a push-and-hold is detected + + + +typedef struct BtnSub { + uint16_t hold; // initial hold + uint16_t repeat; // repeated hold + void (*cb_push)(uint8_t); + void (*cb_hold)(uint8_t); + void (*cb_release)(uint8_t); +} BtnSub; + + + +extern BtnSub btn[BTN_COUNT]; + + + +void btn_process(); + + + +#endif /* USER_UI_BTN_H_ */ diff --git a/firmware/linker/ch32x035.ld b/firmware/linker/ch32x035.ld index a12249a..9c50bdb 100644 --- a/firmware/linker/ch32x035.ld +++ b/firmware/linker/ch32x035.ld @@ -23,6 +23,12 @@ SECTIONS _einit = .; } >FLASH AT>FLASH + .ramfunclalign : + { + . = ALIGN(4); + PROVIDE(_ramfunc_lma = .); + } >FLASH AT>FLASH + .vector : { *(.vector); @@ -132,6 +138,9 @@ SECTIONS *(.srodata.cst2) *(.srodata .srodata.*) . = ALIGN(4); + *(.ramfunc) + *(.ramfunc*) + . = ALIGN(4); PROVIDE( _edata = .); } >RAM AT>FLASH