| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- /**
- ******************************************************************************************************************************
- *
- *@file driver_touch_key.c
- *
- *@brief Source file for Touch Key Driver
- *
- *@Create date: 2023-03-23
- *
- *
- *Copyright (c) 2023, BLUETRUM
- ******************************************************************************************************************************
- **/
- #include "driver_touch_key.h"
- #include "driver_gpio.h"
- #define TRACE_EN 0
- #if TRACE_EN
- #define TRACE(...) printf(__VA_ARGS__)
- #else
- #define TRACE(...)
- #endif
- void touch_key_dump(void)
- {
- TRACE ("\n");
- TRACE ("INPCON: %08X\n", INPCON );
- TRACE ("INPCPND: %08X\n", INPCPND);
- TRACE ("TKCON: %08X\n", TKCON);
- TRACE ("TKCON1: %08X\n", TKCON1);
- TRACE ("TKCON2: %08X\n", TKCON2);
- TRACE ("TKACON0: %08X\n", TKACON0);
- TRACE ("TKACON1: %08X\n", TKACON1);
- TRACE ("TKCNT: %08X\n", TKCNT);
- TRACE ("TKBCNT: %08X\n", TKBCNT);
- TRACE ("TKCDPR0: %08X\n",TKCDPR0);
- TRACE ("TKCDPR1: %08X\n",TKCDPR1);
- TRACE ("TKVARI: %08X\n", TKVARI);
- TRACE ("TKTMR: %08X\n", TKTMR);
- if (GETF_REG_TKCON_TK0_PND_EN() & GETF_REG_TKCON_TK0_EN()) {
- TRACE("touch key ch0 enable\n");
- }
- if (GETF_REG_TKCON_TK1_PND_EN() & GETF_REG_TKCON_TK1_EN()) {
- TRACE("touch key ch1 enable\n");
- }
- if (GETF_REG_TKCON_TK2_PND_EN() & GETF_REG_TKCON_TK2_EN()) {
- TRACE("touch key ch2 enable\r");
- }
- if (GETF_REG_TKCON_TK3_PND_EN() & GETF_REG_TKCON_TK3_EN()) {
- TRACE("touch key ch3 enable\r");
- }
- TRACE("touch key ch = 0x%02x\r\n", GET_REG_TKCON_TKSEL());
- }
- AT(.com_periph.touch.get_key)
- u8 touch_key_get_key(void)
- {
- if (!GETF_REG_TKCON_TKEN()) {
- return 0;
- }
- return 1;
- }
- #if 1 //Already been implemented internal
- AT(.com_periph.tkey.isr)
- u32 tkey_tcnt_variance_calc(tk_cb_t *s, u16 tkcnt)
- {
- u32 i;
- u32 sum = 0, dela, variance = 0;
- s->buf[s->cnt++] = tkcnt;
- if (s->cnt > 7) {
- s->cnt = 0;
- }
- for (i = 0; i < 8; i++) {
- sum += s->buf[i];
- }
- s->avg = sum >> 3;
- for (i = 0; i < 8; i++) {
- if (s->buf[i] > s->avg) {
- dela = s->buf[i] - s->avg;
- } else {
- dela = s->avg - s->buf[i];
- }
- variance += (dela * dela);
- }
- return variance;
- }
- //根据方差检测进行range exception校准
- AT(.com_periph.tkey.isr)
- void tkey_bcnt_range_exception(tk_cb_t *s, u16 tkcnt)
- {
- u16 bcnt;
- u32 variance = tkey_tcnt_variance_calc(s, tkcnt);
- if (variance < s->limit) {
- s->anov_cnt++;
- bcnt = s->bcnt_sfr[0] & 0xfff;
- if ((s->avg > (bcnt+3)) && (s->avg < (bcnt + s->range_thresh))) {
- s->stable_cnt++;
- if (s->stable_cnt > s->fil_except) {
- if (s->range_en) {
- s->bcnt_sfr[0] = bcnt + 3;
- }
- s->stable_cnt = 0;
- }
- } else if(s->avg < bcnt - 3) {
- s->bcnt_sfr[0] = bcnt - 3;
- } else {
- s->stable_cnt = 0;
- }
- } else {
- s->anov_cnt = 0;
- s->stable_cnt = 0;
- }
- }
- #endif
- AT(.com_periph.tkey.isr)
- void touch_key_isr(void)
- {
- u32 inpcon = INPCON;
- u32 tk_exp_pnd = (inpcon >> 21) & (inpcon >> 5) & 0xf;
- u32 tk_pto_pnd = (inpcon >> 29) & (inpcon >> 13) & 0x1;
- u32 tk_pnd = (inpcon >> 16) & (inpcon >> 0) & 0x1;
- tk_exp_pnd |= (tk_pto_pnd << 4); //bit0-smaller exception pending
- //bit1-larger exception pending
- //bit2-range exception pending
- //bit3-timeout exception pending
- //bit4-press timeout exception pending
- if (tk_exp_pnd) { //touch key exception pending
- INPCPND = BIT(21);
- }
- if (tk_pnd) { //touch key timer pending
- INPCPND = BIT(16);
- touch_key_range_isr(inpcon >> 30, TKCNT & 0xfff);
- }
- }
- /**
- * @brief Touch key interrup enable and isr registered.
- *
- * @params[in] touch_pin To makesure touch key pin data from APP is legal.
- *
- * @retval none
- */
- void touch_key_isr_init(u32 touch_pin)
- {
- u32 inpcon;
- sys_irq_init(IRQn_FREQUENCY_DET_TOUCH_KEY, 0, touch_key_isr);
- inpcon = BIT(0); //touch key pending interrupt enable
- if (touch_pin & 0x0f) {
- //inpcon |= BIT(4) //touch key bcnt valid pending interrupt enable
- inpcon |= (0xf << 5); //touch key exception pending interrupt enable
- inpcon |= BIT(13); //tkey press timeout interrupt enable
- //inpcon |= BIT(14); //touch key variance interrupt enable
- }
- INPCON = inpcon;
- }
- /**
- * @brief To reset touch key,so that we can change REGISTER value without power off.
- *
- * @retval none
- */
- void touch_key_sw_reset(void)
- {
- RTCCON0 |= BIT(4);
- INPCPND = BIT(0); //inpwr_swrst
- RTCCON0 &= ~BIT(19); //osc core disable
- }
- /**
- * @brief To init touch key clock.
- *
- * @params[in] touch_key_reg Touch Key Register Base Address
- * @params[in] clk_sel Touch Key Clock Select.
- * @params[in] tkclk_div2_enable CLK2M_TK to CLK2M_P divide
- *
- * @retval none
- */
- void touch_key_clk_init(touch_key_typedef *touch_key_reg, CLK_TOUCH_KEY_TYPEDEF clk_sel, uint8_t tkclk_div2_enable)
- {
- u32 clk_freq;
- clk_touch_key_clk_set(clk_sel);
- clk_freq = clk_touch_key_clk_get(CLK_VALUE_MODE_FREQ);
- INPCPND = BIT(0); //inpwr_swrst
- touch_key_reg->tkcon1 = 0;
- if (tkclk_div2_enable) {
- SETF_REG_TKCON1_DIV2SEL(); //CLK2M_TK to CLK2M_P divide
- SET_REG_TKCON1_TKCLK2MDIV((u32)(clk_freq / (125 * 2048))); //CLK2M to 32k divide
- } else {
- SET_REG_TKCON1_TKCLK2MDIV((u32)(clk_freq / (125 * 1024))); //CLK2M to 32k divide
- }
- SETF_REG_TKCON1_TKAEN(); //touch key analog enable
- SETF_REG_TKCON1_TKCEN(); //touch key clock enable
- SETF_REG_TKCON1_TKVCEN(); //touch key variance clock enable
- TRACE("%s: %x, %d\n", __func__, touch_key_reg->tkcon1, clk_freq);
- }
- /**
- * @brief To init touch key configuration,including clock and other registers.
- *
- * @params[in] touch_key_reg Touch Key Register Base Address
- * @params[in] tkey_cfg Touch Key Params From APP.
- * @params[in] first_pwron To Tell The Driver Whether Touch Key Is First Time Init Or Not.
- * @params[in] clk_sel Touch Key Clock Select.
- * @params[in] tkclk_div2_enable CLK2M_TK to CLK2M_P divide, typical value is 0.
- *
- * @retval -1: If failed
- 0: If success
- */
- int touch_key_init(touch_key_typedef *touch_key_reg, void *tkey_cfg, u32 first_pwron, CLK_TOUCH_KEY_TYPEDEF clk_sel, uint8_t tkclk_div2_enable)
- {
- int ret_code = 1;
- u32 touch_pin = 0;
- u16 tkbcnt;
- uint32_t tkcdpr0 = 0, tkcdpr1 = 0;
- if (tkey_cfg == NULL) {
- return -1;
- }
- tkey_cfg_t *p = (tkey_cfg_t *)tkey_cfg;
- INPCPND = BIT(0);
- // BGUV Reset TKSWRSTN disable
- RTCCON0 &= ~BIT(21);
- // Between Core Interface Enable, SNF_RC_EN
- RTCCON0 |= BIT(4) | BIT(19);
- if ((first_pwron) || (!(RTCCON0 & BIT(5)))) {
- //Touch Key Reset, or it will cause register write failure
- RTCCON0 |= BIT(5);
- touch_key_clk_init(touch_key_reg, clk_sel, tkclk_div2_enable);
- touch_key_reg->tkbcnt = 0xfff;
- touch_key_reg->tkcon = 0;
- ret_code = 0;
- }
- tkbcnt = touch_key_reg->tkbcnt & 0xfff;
- for (u8 i = 0; i < 4; i++) {
- tkey_ch_t *ch = (tkey_ch_t *)p->key[i];
- if (ch != NULL) {
- if (i == 0) {
- tkcdpr0 |= ((tkcdpr0 & (~BIT_REG_TKCDPR0_TKCDPR0)) | ((ch->cdpr) << POS_REG_TKCDPR0_TKCDPR0));
- SET_REG_TKACON0_CTRIM0(ch->ctrim);
- SET_REG_TKACON0_ITRIM0(ch->itrim);
- SETF_REG_TKCON_TK0_EN(); //touch key 0 enable
- SETF_REG_TKCON_TK0_PND_EN(); //touch key 0 pending enable
- RTCCON1 &= ~(1 << 4); //WK pull up disable, or may cause TKCNT error
- RTCCON1 |= BIT(8); //10s reset source 0:WKO 1 touch key
- if (ch->type) {
- SETF_REG_TKACON0_ENCHN0();
- }
- } else if (i == 1) {
- tkcdpr0 |= ((tkcdpr0 & (~BIT_REG_TKCDPR0_TKCDPR1)) | ((ch->cdpr) << POS_REG_TKCDPR0_TKCDPR1));
- SET_REG_TKACON0_CTRIM1(ch->ctrim);
- SET_REG_TKACON0_ITRIM1(ch->itrim);
- SETF_REG_TKCON_TK1_EN(); //touch key 1 enable
- SETF_REG_TKCON_TK1_PND_EN(); //touch key 1 pending enable
- if (ch->type) {
- SETF_REG_TKACON0_ENCHN1();
- }
- } else if (i == 2) {
- tkcdpr1 |= ((tkcdpr1 & (~BIT_REG_TKCDPR1_TKCDPR2)) | ((ch->cdpr) << POS_REG_TKCDPR1_TKCDPR2));
- SET_REG_TKACON1_CTRIM2(ch->ctrim);
- SET_REG_TKACON1_ITRIM2(ch->itrim);
- SETF_REG_TKCON_TK2_EN(); //touch key 2 enable
- SETF_REG_TKCON_TK2_PND_EN(); //touch key 2 pending enable
- if (ch->type) {
- SETF_REG_TKACON1_ENCHN2();
- }
- } else if (i == 3) {
- tkcdpr1 |= ((tkcdpr1 & (~BIT_REG_TKCDPR1_TKCDPR3)) | ((ch->cdpr) << POS_REG_TKCDPR1_TKCDPR3));
- SET_REG_TKACON1_CTRIM3(ch->ctrim);
- SET_REG_TKACON1_ITRIM3(ch->itrim);
- SETF_REG_TKCON_TK3_EN(); //touch key 3 enable
- SETF_REG_TKCON_TK3_PND_EN(); //touch key 3 pending enable
- if (ch->type) {
- SETF_REG_TKACON1_ENCHN3();
- }
- }
- if (ch->type == 1) {
- SET_REG_TKCON_TKSEL(0); //Select WKO for hardware wakeup
- // Touch Key Pin Select
- touch_pin |= BIT(i);
- }
- }
- }
- SET_REG_TKCON1_TKARTRIM(2);
- //touch key configure
- if (touch_pin & 0x0f) {
- touch_key_reg->tkbcnt = tkbcnt;
- touch_key_reg->tktmr = p->reg_tktmr;
- touch_key_reg->tkpthd = p->reg_tkpthd;
- touch_key_reg->tkethd = p->reg_tkethd;
- touch_key_reg->tkvari = p->reg_tkvari;
- touch_key_reg->tkvarithd = p->reg_tkvarithd;
- touch_key_reg->tkcon2 = p->reg_tkcon2;
- touch_key_reg->tkcdpr0 = tkcdpr0;
- touch_key_reg->tkcdpr1 = tkcdpr1;
- SETF_REG_TKCON_TKPTOUPDBEN(); //press timeout update base_cnt enable
- SETF_REG_TKCON_TKSTAWKEN(); //touch key wakeup enable
- SETF_REG_TKCON_TKSUPDBEN(); //small pending update base_cnt enable
- SETF_REG_TKCON_TKLUPDBEN(); //large pending update base_cnt enable
- SETF_REG_TKCON_TKRUPDBEN(); //range pending update base_cnt enable
- //SETF_REG_TKCON_TKTOUPDBEN(); //timerout pending update base_cnt enable
- SETF_REG_TKCON_TKBCNTVAL(); //touch key base_cnt valid enable
- }
- /*tkcon bit 4 5 is key channel*/
- TKCON &= ~(BIT(5) | BIT(4));
- // TKCON |= BIT(4);
- // TKCON |= BIT(5);
- // TKCON |= (BIT(5) | BIT(4));
- /*tkcon1 bit 14 15 is key along channel*/
- TKCON1 &= ~(BIT(14) | BIT(15));
- // TKCON1 |= BIT(14);
- // TKCON1 |= BIT(15);
- // TKCON1 |= (BIT(14) | BIT(15));
- /*small thmod*/
- TKCON |= BIT(1);
- /*range thmeod*/
- // TKCON &= ~BIT(25);
- SETF_REG_TKCON_TKEN(); //touch key enable
- SETF_REG_TKCON_TKAEN_ATSEL(); //touch key auto enable
- SETF_REG_TKCON_TK_MODE();
- delay_5ms(10);
- touch_key_isr_init(touch_pin);
- touch_key_dump();
- return ret_code;
- }
|