Procházet zdrojové kódy

首版提交,基于SDK_AB202X_WIRELESS_S2632_20251022修改
1、将发送和接收的代码整合到一份,通过宏开关 WIRELESS_TRANSMIT_EN 来选择,1: 发射端, 0: 接收端
2、lib里面,发射端要用 wireless.a ,接收端用 libbtstack.a ,两者不能同时添加使用,否则配对不上
3、下载固件的时候,要在工具的【开始】菜单里选择【擦除】,把之前的配对信息擦除掉,下载好后再次配对才会重新配对,串口打印出conneted信息

robbin před 4 dny
revize
e4f9b00c0d
100 změnil soubory, kde provedl 19030 přidání a 0 odebrání
  1. 2825 0
      driver/driver_adv_timer.c
  2. 1097 0
      driver/driver_adv_timer.h
  3. 406 0
      driver/driver_charge.c
  4. 193 0
      driver/driver_charge.h
  5. 486 0
      driver/driver_clk.c
  6. 259 0
      driver/driver_clk.h
  7. 1287 0
      driver/driver_com.h
  8. 452 0
      driver/driver_gpio.c
  9. 216 0
      driver/driver_gpio.h
  10. 350 0
      driver/driver_hsuart.c
  11. 131 0
      driver/driver_hsuart.h
  12. 318 0
      driver/driver_iic.c
  13. 77 0
      driver/driver_iic.h
  14. 665 0
      driver/driver_ir.h
  15. 117 0
      driver/driver_irrx.c
  16. 361 0
      driver/driver_irtx.c
  17. 235 0
      driver/driver_keyscan.c
  18. 135 0
      driver/driver_keyscan.h
  19. 277 0
      driver/driver_ledc.c
  20. 103 0
      driver/driver_ledc.h
  21. 825 0
      driver/driver_lowpwr.c
  22. 106 0
      driver/driver_lowpwr.h
  23. 183 0
      driver/driver_lpwm.c
  24. 78 0
      driver/driver_lpwm.h
  25. 176 0
      driver/driver_qdec.c
  26. 171 0
      driver/driver_qdec.h
  27. 191 0
      driver/driver_rtc.c
  28. 35 0
      driver/driver_rtc.h
  29. 354 0
      driver/driver_saradc.c
  30. 127 0
      driver/driver_saradc.h
  31. 284 0
      driver/driver_sdadc.c
  32. 96 0
      driver/driver_sdadc.h
  33. 133 0
      driver/driver_sddac.c
  34. 43 0
      driver/driver_sddac.h
  35. 252 0
      driver/driver_spi.c
  36. 94 0
      driver/driver_spi.h
  37. 387 0
      driver/driver_tmr.c
  38. 91 0
      driver/driver_tmr.h
  39. 376 0
      driver/driver_touch_key.c
  40. 504 0
      driver/driver_touch_key.h
  41. 285 0
      driver/driver_uart.c
  42. 98 0
      driver/driver_uart.h
  43. 148 0
      driver/driver_wdt.c
  44. 43 0
      driver/driver_wdt.h
  45. 67 0
      header/clib.h
  46. 16 0
      header/global.h
  47. 15 0
      header/include.h
  48. 42 0
      header/macro.h
  49. 6 0
      header/s_common.h
  50. 758 0
      header/sfr.h
  51. 17 0
      header/typedef.h
  52. 13 0
      libs/ains/api_ains3.h
  53. 7 0
      libs/ains/api_ains4.h
  54. binární
      libs/ains/libains3.a
  55. binární
      libs/ains/libains4.a
  56. binární
      libs/ains/libfft.a
  57. 23 0
      libs/api.h
  58. 1105 0
      libs/ble/api_btstack.h
  59. 325 0
      libs/ble/api_wireless.h
  60. binární
      libs/ble/libbtstack.a
  61. binární
      libs/ble/libbtstack_all_roles.a
  62. binární
      libs/ble/libbtstack_central.a
  63. binární
      libs/ble/libbtstack_scan_adv.a
  64. binární
      libs/ble/libbtstack_test.a
  65. binární
      libs/ble/wireless.a
  66. binární
      libs/ble/wireless_test.a
  67. 56 0
      libs/cpu/api_cm.h
  68. 147 0
      libs/cpu/api_codec.h
  69. 45 0
      libs/cpu/api_interrupt.h
  70. 19 0
      libs/cpu/api_key.h
  71. 47 0
      libs/cpu/api_list.h
  72. 13 0
      libs/cpu/api_msg.h
  73. 61 0
      libs/cpu/api_os.h
  74. 84 0
      libs/cpu/api_pwr.h
  75. 65 0
      libs/cpu/api_sdadc.h
  76. 107 0
      libs/cpu/api_sys.h
  77. 74 0
      libs/cpu/api_sysclk.h
  78. 47 0
      libs/cpu/api_update.h
  79. binární
      libs/cpu/libc.a
  80. binární
      libs/cpu/libgcc.a
  81. binární
      libs/cpu/libm.a
  82. binární
      libs/cpu/libplatform.a
  83. 73 0
      libs/motor/api_zerocross_detection.h
  84. binární
      libs/motor/libobservers.a
  85. 27 0
      libs/usb/api_device.h
  86. 115 0
      libs/usb/api_usb.h
  87. binární
      libs/usb/libusb.a
  88. 92 0
      libs/usb/usb_define.h
  89. 30 0
      libs/ver.h
  90. binární
      libs/wireless/libwireless_slave.a
  91. 202 0
      modules/ains/ains3.c
  92. 11 0
      modules/ains/ains3.h
  93. 197 0
      modules/ains/ains4.c
  94. 10 0
      modules/ains/ains4.h
  95. 6 0
      project/hidtouch.workspace
  96. 5 0
      project/hidtouch.workspace.layout
  97. 23 0
      project/solution/ble_hid_composite/Output/bin/Settings/standard.setting
  98. binární
      project/solution/ble_hid_composite/Output/bin/app.bin
  99. binární
      project/solution/ble_hid_composite/Output/bin/app.rv32
  100. 10 0
      project/solution/ble_hid_composite/Output/bin/app.xm

+ 2825 - 0
driver/driver_adv_timer.c

@@ -0,0 +1,2825 @@
+#include "driver_adv_timer.h"
+
+
+
+/* ---------------------- TIM registers bit mask ------------------------ */
+#define SMCR_ETR_MASK               ((uint16_t)0x00FF)
+#define CCMR_OFFSET                 ((uint16_t)0x0018)
+#define CCER_CCE_SET                ((uint16_t)0x0001)
+#define	CCER_CCNE_SET               ((uint16_t)0x0004)
+
+/**
+  * @}
+  */
+
+/** @defgroup tim_private_macros
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup tim_private_variables
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup tim_private_functionprototypes
+  * @{
+  */
+
+static void ti1_config(tim_typedef* TIMx, uint16_t tim_icpolarity, uint16_t tim_icselection,
+                       uint16_t tim_icfilter);
+static void ti2_config(tim_typedef* TIMx, uint16_t tim_icpolarity, uint16_t tim_icselection,
+                       uint16_t tim_icfilter);
+//static void ti3_config(tim_typedef* TIMx, uint16_t tim_icpolarity, uint16_t tim_icselection,
+//                       uint16_t tim_icfilter);
+//static void ti4_config(tim_typedef* TIMx, uint16_t tim_icpolarity, uint16_t tim_icselection,
+//                       uint16_t tim_icfilter);
+/**
+  * @}
+  */
+
+/** @defgroup tim_private_macros
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup tim_private_variables
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup tim_private_functionprototypes
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup tim_private_functions
+  * @{
+  */
+
+/**
+  * @brief  deinitializes the TIMx peripheral registers to their default reset values.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @retval none
+  */
+
+
+/**
+  * @brief  initializes the TIMx time base unit peripheral according to
+  *         the specified parameters in the tim_timebaseinitstruct.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  tim_timebaseinitstruct: pointer to a tim_timebaseinittypedef
+  *         structure that contains the configuration information for the
+  *         specified tim peripheral.
+  * @retval none
+  */
+void tim_timebaseinit(tim_typedef* TIMx, tim_timebaseinittypedef* tim_timebaseinitstruct)
+{
+  uint16_t tmpcr1 = 0;
+
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(IS_TIM_COUNTER_MODE(tim_timebaseinitstruct->tim_countermode));
+  assert_param(IS_TIM_CKD_DIV(tim_timebaseinitstruct->tim_clockdivision));
+
+  tmpcr1 = TIMx->cr1;
+
+  if(TIMx == TIM1)
+  {
+    /* select the counter mode */
+    tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));
+    tmpcr1 |= (uint32_t)tim_timebaseinitstruct->tim_countermode;
+  }
+
+//  if((TIMx != tim6) && (TIMx != tim7))
+//  {
+//    /* set the clock division */
+   tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD));
+   tmpcr1 |= (uint32_t)tim_timebaseinitstruct->tim_clockdivision;
+//  }
+
+  TIMx->cr1 = tmpcr1;
+
+  /* set the autoreload value */
+  TIMx->arr = tim_timebaseinitstruct->tim_period ;
+
+  /* set the prescaler value */
+  TIMx->psc = tim_timebaseinitstruct->tim_prescaler;
+
+  if (TIMx == TIM1)
+  {
+    /* set the repetition counter value */
+    TIMx->rcr = tim_timebaseinitstruct->tim_repetitioncounter;
+  }
+
+  /* generate an update event to reload the prescaler and the repetition counter
+     values immediately */
+  TIMx->egr = TIM_PSCRELOADMODE_IMMEDIATE;
+}
+
+/**
+  * @brief  initializes the TIMx channel1 according to the specified
+  *         parameters in the tim_ocinitstruct.
+  * @param  TIMx: where x can be  1 to 17 except 6 and 7 to select the tim peripheral.
+  * @param  tim_ocinitstruct: pointer to a tim_ocinittypedef structure
+  *         that contains the configuration information for the specified tim peripheral.
+  * @retval none
+  */
+void tim_oc1init(tim_typedef* TIMx, tim_ocinittypedef* tim_ocinitstruct)
+{
+  uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
+
+  /* check the parameters */
+  assert_param(IS_TIM_LIST8_PERIPH(TIMx));
+  assert_param(IS_TIM_OC_MODE(tim_ocinitstruct->tim_ocmode));
+  assert_param(IS_TIM_OUTPUT_STATE(tim_ocinitstruct->tim_outputstate));
+  assert_param(IS_TIM_OC_POLARITY(tim_ocinitstruct->tim_ocpolarity));
+ /* DISABLE the channel 1: reset the cc1e bit */
+  TIMx->ccer &= (uint16_t)(~(uint16_t)TIM_CCER_CC1E);
+  /* get the TIMx ccer register value */
+  tmpccer = TIMx->ccer;
+  /* get the TIMx cr2 register value */
+  tmpcr2 =  TIMx->cr2;
+
+  /* get the TIMx ccmr1 register value */
+  tmpccmrx = TIMx->ccmr1;
+
+  /* reset the output compare mode bits */
+  tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_OC1M));
+  tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_CC1S)); // 预留 ■
+
+  /* select the output compare mode */
+  tmpccmrx |= tim_ocinitstruct->tim_ocmode;
+
+  /* reset the output polarity level */
+  tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1P));
+  /* set the output compare polarity */
+  tmpccer |= tim_ocinitstruct->tim_ocpolarity;
+
+  /* set the output state */
+  tmpccer |= tim_ocinitstruct->tim_outputstate;
+
+  if(TIMx == TIM1)
+  {
+    assert_param(IS_TIM_OUTPUTN_STATE(tim_ocinitstruct->tim_outputnstate));
+    assert_param(IS_TIM_OCN_POLARITY(tim_ocinitstruct->tim_ocnpolarity));
+    assert_param(IS_TIM_OCNIDLE_STATE(tim_ocinitstruct->tim_ocnidlestate));
+    assert_param(IS_TIM_OCIDLE_STATE(tim_ocinitstruct->tim_ocidlestate));
+
+    /* reset the output n polarity level */
+    tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1NP));
+    /* set the output n polarity */
+    tmpccer |= tim_ocinitstruct->tim_ocnpolarity;
+
+    /* reset the output n state */
+    tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1NE));
+    /* set the output n state */
+    tmpccer |= tim_ocinitstruct->tim_outputnstate;
+
+    /* reset the output compare and output compare n idle state */
+    tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS1));   // 预留 ■
+
+    tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS1N)); 	// 预留 ■
+
+    /* set the output idle state */
+    tmpcr2 |= tim_ocinitstruct->tim_ocidlestate;
+    /* set the output n idle state */
+    tmpcr2 |= tim_ocinitstruct->tim_ocnidlestate;
+  }
+  /* write to TIMx cr2 */
+  TIMx->cr2 = tmpcr2;
+
+  /* write to TIMx ccmr1 */
+  TIMx->ccmr1 = tmpccmrx;
+
+  /* set the capture compare register value */
+  TIMx->ccr1 = tim_ocinitstruct->tim_pulse;
+
+  /* write to TIMx ccer */
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  initializes the TIMx channel2 according to the specified
+  *         parameters in the tim_ocinitstruct.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select
+  *         the tim peripheral.
+  * @param  tim_ocinitstruct: pointer to a tim_ocinittypedef structure
+  *         that contains the configuration information for the specified tim peripheral.
+  * @retval none
+  */
+void tim_oc2init(tim_typedef* TIMx, tim_ocinittypedef* tim_ocinitstruct)
+{
+  uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
+
+  /* check the parameters */
+  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+  assert_param(IS_TIM_OC_MODE(tim_ocinitstruct->tim_ocmode));
+  assert_param(IS_TIM_OUTPUT_STATE(tim_ocinitstruct->tim_outputstate));
+  assert_param(IS_TIM_OC_POLARITY(tim_ocinitstruct->tim_ocpolarity));
+   /* DISABLE the channel 2: reset the cc2e bit */
+  TIMx->ccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2E));
+
+  /* get the TIMx ccer register value */
+  tmpccer = TIMx->ccer;
+  /* get the TIMx cr2 register value */
+  tmpcr2 =  TIMx->cr2;
+
+  /* get the TIMx ccmr1 register value */
+  tmpccmrx = TIMx->ccmr1;
+
+  /* reset the output compare mode and capture/compare selection bits */
+  tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_OC2M));
+  tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_CC2S)); // 预留 ■
+
+  /* select the output compare mode */
+  tmpccmrx |= (uint16_t)(tim_ocinitstruct->tim_ocmode << 8);
+
+  /* reset the output polarity level */
+  tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2P));
+  /* set the output compare polarity */
+  tmpccer |= (uint16_t)(tim_ocinitstruct->tim_ocpolarity << 4);
+
+  /* set the output state */
+  tmpccer |= (uint16_t)(tim_ocinitstruct->tim_outputstate << 4);
+
+  if(TIMx == TIM1)
+  {
+    assert_param(IS_TIM_OUTPUTN_STATE(tim_ocinitstruct->tim_outputnstate));
+    assert_param(IS_TIM_OCN_POLARITY(tim_ocinitstruct->tim_ocnpolarity));
+    assert_param(IS_TIM_OCNIDLE_STATE(tim_ocinitstruct->tim_ocnidlestate));
+    assert_param(IS_TIM_OCIDLE_STATE(tim_ocinitstruct->tim_ocidlestate));
+
+    /* reset the output n polarity level */
+    tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2NP));
+    /* set the output n polarity */
+    tmpccer |= (uint16_t)(tim_ocinitstruct->tim_ocnpolarity << 4);
+
+    /* reset the output n state */
+    tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2NE));
+    /* set the output n state */
+    tmpccer |= (uint16_t)(tim_ocinitstruct->tim_outputnstate << 4);
+
+    /* reset the output compare and output compare n idle state */
+    tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS2));
+    tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS2N));
+
+    /* set the output idle state */
+    tmpcr2 |= (uint16_t)(tim_ocinitstruct->tim_ocidlestate << 2);
+    /* set the output n idle state */
+    tmpcr2 |= (uint16_t)(tim_ocinitstruct->tim_ocnidlestate << 2);
+  }
+  /* write to TIMx cr2 */
+  TIMx->cr2 = tmpcr2;
+
+  /* write to TIMx ccmr1 */
+  TIMx->ccmr1 = tmpccmrx;
+
+  /* set the capture compare register value */
+  TIMx->ccr2 = tim_ocinitstruct->tim_pulse;
+
+  /* write to TIMx ccer */
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  initializes the TIMx channel3 according to the specified
+  *         parameters in the tim_ocinitstruct.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_ocinitstruct: pointer to a tim_ocinittypedef structure
+  *         that contains the configuration information for the specified tim peripheral.
+  * @retval none
+  */
+void tim_oc3init(tim_typedef* TIMx, tim_ocinittypedef* tim_ocinitstruct)
+{
+  uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
+
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_OC_MODE(tim_ocinitstruct->tim_ocmode));
+  assert_param(IS_TIM_OUTPUT_STATE(tim_ocinitstruct->tim_outputstate));
+  assert_param(IS_TIM_OC_POLARITY(tim_ocinitstruct->tim_ocpolarity));
+  /* DISABLE the channel 2: reset the cc2e bit */
+  TIMx->ccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3E));
+
+  /* get the TIMx ccer register value */
+  tmpccer = TIMx->ccer;
+  /* get the TIMx cr2 register value */
+  tmpcr2 =  TIMx->cr2;
+
+  /* get the TIMx ccmr2 register value */
+  tmpccmrx = TIMx->ccmr2;
+
+  /* reset the output compare mode and capture/compare selection bits */
+  tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_OC3M));
+  tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_CC3S));// 预留 ■
+  /* select the output compare mode */
+  tmpccmrx |= tim_ocinitstruct->tim_ocmode;
+
+  /* reset the output polarity level */
+  tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3P));
+  /* set the output compare polarity */
+  tmpccer |= (uint16_t)(tim_ocinitstruct->tim_ocpolarity << 8);
+
+  /* set the output state */
+  tmpccer |= (uint16_t)(tim_ocinitstruct->tim_outputstate << 8);
+
+  if(TIMx == TIM1)
+  {
+    assert_param(IS_TIM_OUTPUTN_STATE(tim_ocinitstruct->tim_outputnstate));
+    assert_param(IS_TIM_OCN_POLARITY(tim_ocinitstruct->tim_ocnpolarity));
+    assert_param(IS_TIM_OCNIDLE_STATE(tim_ocinitstruct->tim_ocnidlestate));
+    assert_param(IS_TIM_OCIDLE_STATE(tim_ocinitstruct->tim_ocidlestate));
+
+    /* reset the output n polarity level */
+    tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3NP));
+    /* set the output n polarity */
+    tmpccer |= (uint16_t)(tim_ocinitstruct->tim_ocnpolarity << 8);
+    /* reset the output n state */
+    tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3NE));
+
+    /* set the output n state */
+    tmpccer |= (uint16_t)(tim_ocinitstruct->tim_outputnstate << 8);
+    /* reset the output compare and output compare n idle state */
+    tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS3));
+    tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS3N));
+    /* set the output idle state */
+    tmpcr2 |= (uint16_t)(tim_ocinitstruct->tim_ocidlestate << 4);
+    /* set the output n idle state */
+    tmpcr2 |= (uint16_t)(tim_ocinitstruct->tim_ocnidlestate << 4);
+  }
+  /* write to TIMx cr2 */
+  TIMx->cr2 = tmpcr2;
+
+  /* write to TIMx ccmr2 */
+  TIMx->ccmr2 = tmpccmrx;
+
+  /* set the capture compare register value */
+  TIMx->ccr3 = tim_ocinitstruct->tim_pulse;
+
+  /* write to TIMx ccer */
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  initializes the TIMx channel4 according to the specified
+  *         parameters in the tim_ocinitstruct.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_ocinitstruct: pointer to a tim_ocinittypedef structure
+  *         that contains the configuration information for the specified tim peripheral.
+  * @retval none
+  */
+void tim_oc4init(tim_typedef* TIMx, tim_ocinittypedef* tim_ocinitstruct)
+{
+  uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
+
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_OC_MODE(tim_ocinitstruct->tim_ocmode));
+  assert_param(IS_TIM_OUTPUT_STATE(tim_ocinitstruct->tim_outputstate));
+  assert_param(IS_TIM_OC_POLARITY(tim_ocinitstruct->tim_ocpolarity));
+  /* DISABLE the channel 2: reset the cc4e bit */
+  TIMx->ccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC4E));
+
+  /* get the TIMx ccer register value */
+  tmpccer = TIMx->ccer;
+  /* get the TIMx cr2 register value */
+  tmpcr2 =  TIMx->cr2;
+
+  /* get the TIMx ccmr2 register value */
+  tmpccmrx = TIMx->ccmr2;
+
+  /* reset the output compare mode and capture/compare selection bits */
+  tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_OC4M));
+  tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_CC4S)); // 预留 ■
+
+  /* select the output compare mode */
+  tmpccmrx |= (uint16_t)(tim_ocinitstruct->tim_ocmode << 8);
+
+  /* reset the output polarity level */
+  tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC4P));
+  /* set the output compare polarity */
+  tmpccer |= (uint16_t)(tim_ocinitstruct->tim_ocpolarity << 12);
+
+  /* set the output state */
+  tmpccer |= (uint16_t)(tim_ocinitstruct->tim_outputstate << 12);
+
+  if(TIMx == TIM1)
+  {
+    assert_param(IS_TIM_OCIDLE_STATE(tim_ocinitstruct->tim_ocidlestate));
+    /* reset the output compare idle state */
+    tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS4));
+    /* set the output idle state */
+    tmpcr2 |= (uint16_t)(tim_ocinitstruct->tim_ocidlestate << 6);
+  }
+  /* write to TIMx cr2 */
+  TIMx->cr2 = tmpcr2;
+
+  /* write to TIMx ccmr2 */
+  TIMx->ccmr2 = tmpccmrx;
+
+  /* set the capture compare register value */
+  TIMx->ccr4 = tim_ocinitstruct->tim_pulse;
+
+  /* write to TIMx ccer */
+  TIMx->ccer = tmpccer;
+}
+
+
+
+/**
+  * @brief  initializes the tim peripheral according to the specified
+  *         parameters in the tim_icinitstruct.
+  * @param  TIMx: where x can be  1 to 17 except 6 and 7 to select the tim peripheral.
+  * @param  tim_icinitstruct: pointer to a tim_icinittypedef structure
+  *         that contains the configuration information for the specified tim peripheral.
+  * @retval none
+  */
+//void tim_icinit(tim_typedef* TIMx, tim_icinittypedef* tim_icinitstruct)  // 预留
+//{
+//  /* check the parameters */
+//  assert_param(IS_TIM_CHANNEL(tim_icinitstruct->tim_channel));
+//  assert_param(IS_TIM_IC_SELECTION(tim_icinitstruct->tim_icselection));
+//  assert_param(IS_TIM_IC_PRESCALER(tim_icinitstruct->tim_icprescaler));
+//  assert_param(IS_TIM_IC_FILTER(tim_icinitstruct->tim_icfilter));
+//
+//  if(TIMx == TIM1)
+//  {
+//    assert_param(IS_TIM_IC_POLARITY(tim_icinitstruct->tim_icpolarity));
+//  }
+//  else
+//  {
+//    assert_param(IS_TIM_IC_POLARITY_LITE(tim_icinitstruct->tim_icpolarity));
+//  }
+//  if (tim_icinitstruct->tim_channel == TIM_CHANNEL_1)
+//  {
+//    assert_param(IS_TIM_LIST8_PERIPH(TIMx));
+//    /* ti1 configuration */
+//    ti1_config(TIMx, tim_icinitstruct->tim_icpolarity,
+//               tim_icinitstruct->tim_icselection,
+//               tim_icinitstruct->tim_icfilter);
+//    /* set the input capture prescaler value */
+//    tim_setic1prescaler(TIMx, tim_icinitstruct->tim_icprescaler);
+//  }
+//  else if (tim_icinitstruct->tim_channel == TIM_CHANNEL_2)
+//  {
+//    assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+//    /* ti2 configuration */
+//    ti2_config(TIMx, tim_icinitstruct->tim_icpolarity,
+//               tim_icinitstruct->tim_icselection,
+//               tim_icinitstruct->tim_icfilter);
+//    /* set the input capture prescaler value */
+//    tim_setic2prescaler(TIMx, tim_icinitstruct->tim_icprescaler);
+//  }
+//  else if (tim_icinitstruct->tim_channel == TIM_CHANNEL_3)
+//  {
+//    assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+//    /* ti3 configuration */
+//    ti3_config(TIMx,  tim_icinitstruct->tim_icpolarity,
+//               tim_icinitstruct->tim_icselection,
+//               tim_icinitstruct->tim_icfilter);
+//    /* set the input capture prescaler value */
+//    tim_setic3prescaler(TIMx, tim_icinitstruct->tim_icprescaler);
+//  }
+//  else
+//  {
+//    assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+//    /* ti4 configuration */
+//    ti4_config(TIMx, tim_icinitstruct->tim_icpolarity,
+//               tim_icinitstruct->tim_icselection,
+//               tim_icinitstruct->tim_icfilter);
+//    /* set the input capture prescaler value */
+//    tim_setic4prescaler(TIMx, tim_icinitstruct->tim_icprescaler);
+//  }
+//}
+
+/**
+  * @brief  configures the tim peripheral according to the specified
+  *         parameters in the tim_icinitstruct to measure an external pwm signal.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the tim peripheral.
+  * @param  tim_icinitstruct: pointer to a tim_icinittypedef structure
+  *         that contains the configuration information for the specified tim peripheral.
+  * @retval none
+  */
+//void tim_pwmiconfig(tim_typedef* TIMx, tim_icinittypedef* tim_icinitstruct) // 预留
+//{
+//  uint16_t icoppositepolarity = TIM_ICPOLARITY_RISING;
+//  uint16_t icoppositeselection = TIM_ICSELECTION_DIRECTTI;
+//  /* check the parameters */
+//  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+//  /* select the opposite input polarity */
+//  if (tim_icinitstruct->tim_icpolarity == TIM_ICPOLARITY_RISING)
+//  {
+//    icoppositepolarity = TIM_ICPOLARITY_FALLING;
+//  }
+//  else
+//  {
+//    icoppositepolarity = TIM_ICPOLARITY_RISING;
+//  }
+//  /* select the opposite input */
+//  if (tim_icinitstruct->tim_icselection == TIM_ICSELECTION_DIRECTTI)
+//  {
+//    icoppositeselection = TIM_ICSELECTION_INDIRECTTI;
+//  }
+//  else
+//  {
+//    icoppositeselection = TIM_ICSELECTION_DIRECTTI;
+//  }
+//  if (tim_icinitstruct->tim_channel == TIM_CHANNEL_1)
+//  {
+//    /* ti1 configuration */
+//    ti1_config(TIMx, tim_icinitstruct->tim_icpolarity, tim_icinitstruct->tim_icselection,
+//               tim_icinitstruct->tim_icfilter);
+//    /* set the input capture prescaler value */
+//    tim_setic1prescaler(TIMx, tim_icinitstruct->tim_icprescaler);
+//    /* ti2 configuration */
+//    ti2_config(TIMx, icoppositepolarity, icoppositeselection, tim_icinitstruct->tim_icfilter);
+//    /* set the input capture prescaler value */
+//    tim_setic2prescaler(TIMx, tim_icinitstruct->tim_icprescaler);
+//  }
+//  else
+//  {
+//    /* ti2 configuration */
+//    ti2_config(TIMx, tim_icinitstruct->tim_icpolarity, tim_icinitstruct->tim_icselection,
+//               tim_icinitstruct->tim_icfilter);
+//    /* set the input capture prescaler value */
+//    tim_setic2prescaler(TIMx, tim_icinitstruct->tim_icprescaler);
+//    /* ti1 configuration */
+//    ti1_config(TIMx, icoppositepolarity, icoppositeselection, tim_icinitstruct->tim_icfilter);
+//    /* set the input capture prescaler value */
+//    tim_setic1prescaler(TIMx, tim_icinitstruct->tim_icprescaler);
+//  }
+//}
+
+/**
+  * @brief  configures the: break feature, dead time, lock level, the ossi,
+  *         the ossr state and the aoe(automatic output enable).
+  * @param  TIMx: where x can be  1 or 8 to select the tim
+  * @param  tim_bdtrinitstruct: pointer to a tim_bdtrinittypedef structure that
+  *         contains the bdtr register configuration  information for the tim peripheral.
+  * @retval none
+  */
+void tim_bdtrconfig(tim_typedef* TIMx, tim_bdtrinittypedef *tim_bdtrinitstruct)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST2_PERIPH(TIMx));
+  assert_param(IS_TIM_OSSR_STATE(tim_bdtrinitstruct->tim_ossrstate));
+  assert_param(IS_TIM_OSSI_STATE(tim_bdtrinitstruct->tim_ossistate));
+  assert_param(IS_TIM_LOCK_LEVEL(tim_bdtrinitstruct->tim_locklevel));
+  assert_param(IS_TIM_BREAK_STATE(tim_bdtrinitstruct->tim_break));
+  assert_param(IS_TIM_BREAK_POLARITY(tim_bdtrinitstruct->tim_breakpolarity));
+  assert_param(IS_TIM_AUTOMATIC_OUTPUT_STATE(tim_bdtrinitstruct->tim_automaticoutput));
+  /* set the lock level, the break enable bit and the ploarity, the ossr state,
+     the ossi state, the dead time value and the automatic output enable bit */
+  TIMx->bdtr = (uint32_t)tim_bdtrinitstruct->tim_ossrstate | tim_bdtrinitstruct->tim_ossistate |
+             tim_bdtrinitstruct->tim_locklevel | tim_bdtrinitstruct->tim_deadtime |
+             tim_bdtrinitstruct->tim_break | tim_bdtrinitstruct->tim_breakpolarity |
+             tim_bdtrinitstruct->tim_automaticoutput;
+}
+
+/**
+  * @brief  fills each tim_timebaseinitstruct member with its default value.
+  * @param  tim_timebaseinitstruct : pointer to a tim_timebaseinittypedef
+  *         structure which will be initialized.
+  * @retval none
+  */
+void tim_timebasestructinit(tim_timebaseinittypedef* tim_timebaseinitstruct)
+{
+  /* set the default configuration */
+  tim_timebaseinitstruct->tim_period = 0xffff;
+  tim_timebaseinitstruct->tim_prescaler = 0x0000;
+  tim_timebaseinitstruct->tim_clockdivision = TIM_CKD_DIV1;
+  tim_timebaseinitstruct->tim_countermode = TIM_COUNTERMODE_UP;
+  tim_timebaseinitstruct->tim_repetitioncounter = 0x0000;
+}
+
+/**
+  * @brief  fills each tim_ocinitstruct member with its default value.
+  * @param  tim_ocinitstruct : pointer to a tim_ocinittypedef structure which will
+  *         be initialized.
+  * @retval none
+  */
+void tim_ocstructinit(tim_ocinittypedef* tim_ocinitstruct)
+{
+  /* set the default configuration */
+  tim_ocinitstruct->tim_ocmode = TIM_OCMODE_TIMING;
+  tim_ocinitstruct->tim_outputstate = TIM_OUTPUTSTATE_DISABLE;
+  tim_ocinitstruct->tim_outputnstate = TIM_OUTPUTNSTATE_DISABLE;
+  tim_ocinitstruct->tim_pulse = 0x0000;
+  tim_ocinitstruct->tim_ocpolarity = TIM_OCPOLARITY_HIGH;
+  tim_ocinitstruct->tim_ocnpolarity = TIM_OCNPOLARITY_HIGH;
+  tim_ocinitstruct->tim_ocidlestate = TIM_OCIDLESTATE_RESET;
+  tim_ocinitstruct->tim_ocnidlestate = TIM_OCNIDLESTATE_RESET;
+}
+
+/**
+  * @brief  fills each tim_icinitstruct member with its default value.
+  * @param  tim_icinitstruct: pointer to a tim_icinittypedef structure which will
+  *         be initialized.
+  * @retval none
+  */
+//void tim_icstructinit(tim_icinittypedef* tim_icinitstruct) // 预留
+//{
+//  /* set the default configuration */
+//  tim_icinitstruct->tim_channel = TIM_CHANNEL_1;
+//  tim_icinitstruct->tim_icpolarity = TIM_ICPOLARITY_RISING;
+//  tim_icinitstruct->tim_icselection = TIM_ICSELECTION_DIRECTTI;
+//  tim_icinitstruct->tim_icprescaler = TIM_ICPSC_DIV1;
+//  tim_icinitstruct->tim_icfilter = 0x00;
+//}
+
+/**
+  * @brief  fills each tim_bdtrinitstruct member with its default value.
+  * @param  tim_bdtrinitstruct: pointer to a tim_bdtrinittypedef structure which
+  *         will be initialized.
+  * @retval none
+  */
+void tim_bdtrstructinit(tim_bdtrinittypedef* tim_bdtrinitstruct)
+{
+  /* set the default configuration */
+  tim_bdtrinitstruct->tim_ossrstate = TIM_OSSRSTATE_DISABLE;
+  tim_bdtrinitstruct->tim_ossistate = TIM_OSSISTATE_DISABLE;
+  tim_bdtrinitstruct->tim_locklevel = TIM_LOCKLEVEL_OFF;
+  tim_bdtrinitstruct->tim_deadtime = 0x00;
+  tim_bdtrinitstruct->tim_break = TIM_BREAK_DISABLE;
+  tim_bdtrinitstruct->tim_breakpolarity = TIM_BREAKPOLARITY_LOW;
+  tim_bdtrinitstruct->tim_automaticoutput = TIM_AUTOMATICOUTPUT_DISABLE;
+}
+
+/**
+  * @brief  enables or DISABLEs the specified tim peripheral.
+  * @param  TIMx: where x can be 1 to 17 to select the TIMx peripheral.
+  * @param  newstate: new state of the TIMx peripheral.
+  *   this parameter can be: enable or DISABLE.
+  * @retval none
+  */
+AT(.com_text.tim.cmd)
+void tim_cmd(tim_typedef* TIMx, FUNCTIONAL_STATE newstate)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(IS_FUNCTIONAL_STATE(newstate));
+
+  if (newstate != DISABLE)
+  {
+    /* enable the tim counter */
+    TIMx->cr1 |= TIM_CR1_CEN;
+  }
+  else
+  {
+    /* DISABLE the tim counter */
+    TIMx->cr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CEN));
+  }
+}
+
+/**
+  * @brief  enables or DISABLEs the tim peripheral main outputs.
+  * @param  TIMx: where x can be 1, 8, 15, 16 or 17 to select the TIMx peripheral.
+  * @param  newstate: new state of the tim peripheral main outputs.
+  *   this parameter can be: enable or DISABLE.
+  * @retval none
+  */
+AT(.com_text.tim.ctrlpwmoutputs)
+void tim_ctrlpwmoutputs(tim_typedef* TIMx, FUNCTIONAL_STATE newstate)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST2_PERIPH(TIMx));
+  assert_param(IS_FUNCTIONAL_STATE(newstate));
+  if (newstate != DISABLE)
+  {
+    /* enable the tim main output */
+    TIMx->bdtr |= TIM_BDTR_MOE;
+  }
+  else
+  {
+    /* DISABLE the tim main output */
+    TIMx->bdtr &= (uint32_t)(~((uint32_t)TIM_BDTR_MOE));
+  }
+}
+
+/**
+  * @brief  enables or DISABLEs the specified tim interrupts.
+  * @param  TIMx: where x can be 1 to 17 to select the TIMx peripheral.
+  * @param  tim_it: specifies the tim interrupts sources to be enabled or DISABLEd.
+  *   this parameter can be any combination of the following values:
+  *     @arg tim_it_update: tim update interrupt source
+  *     @arg tim_it_cc1: tim capture compare 1 interrupt source
+  *     @arg tim_it_cc2: tim capture compare 2 interrupt source
+  *     @arg tim_it_cc3: tim capture compare 3 interrupt source
+  *     @arg tim_it_cc4: tim capture compare 4 interrupt source
+  *     @arg tim_it_com: tim commutation interrupt source
+  *     @arg tim_it_trigger: tim trigger interrupt source
+  *     @arg tim_it_break: tim break interrupt source
+  * @note
+  *   - tim6 and tim7 can only generate an update interrupt.
+  *   - tim9, TIM12 and TIM15 can have only tim_it_update, tim_it_cc1,
+  *      tim_it_cc2 or tim_it_trigger.
+  *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have tim_it_update or tim_it_cc1.
+  *   - tim_it_break is used only with TIM1, tim8 and TIM15.
+  *   - tim_it_com is used only with TIM1, tim8, TIM15, TIM16 and TIM17.
+  * @param  newstate: new state of the tim interrupts.
+  *   this parameter can be: enable or DISABLE.
+  * @retval none
+  */
+void tim_itconfig(tim_typedef* TIMx, uint16_t tim_it, FUNCTIONAL_STATE newstate)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(IS_TIM_IT(tim_it));
+  assert_param(IS_FUNCTIONAL_STATE(newstate));
+
+  if (newstate != DISABLE)
+  {
+    /* enable the interrupt sources */
+    TIMx->dier |= tim_it;
+  }
+  else
+  {
+    /* DISABLE the interrupt sources */
+    TIMx->dier &= (uint16_t)~tim_it;
+  }
+}
+
+/**
+  * @brief  configures the TIMx event to be generate by software.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  tim_eventsource: specifies the event source.
+  *   this parameter can be one or more of the following values:
+  *     @arg tim_eventsource_update: timer update event source
+  *     @arg tim_eventsource_cc1: timer capture compare 1 event source
+  *     @arg tim_eventsource_cc2: timer capture compare 2 event source
+  *     @arg tim_eventsource_cc3: timer capture compare 3 event source
+  *     @arg tim_eventsource_cc4: timer capture compare 4 event source
+  *     @arg tim_eventsource_com: timer com event source
+  *     @arg tim_eventsource_trigger: timer trigger event source
+  *     @arg tim_eventsource_break: timer break event source
+  * @note
+  *   - tim6 and tim7 can only generate an update event.
+  *   - tim_eventsource_com and tim_eventsource_break are used only with TIM1 and tim8.
+  * @retval none
+  */
+AT(.com_periph.tim.generateevent)
+void tim_generateevent(tim_typedef* TIMx, uint16_t tim_eventsource)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(IS_TIM_EVENT_SOURCE(tim_eventsource));
+
+  /* set the event sources */
+  TIMx->egr = tim_eventsource;
+}
+
+///**
+//  * @brief  configures the TIMx's dma interface.
+//  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 15, 16 or 17 to select
+//  *   the tim peripheral.
+//  * @param  tim_dmabase: dma base address.
+//  *   this parameter can be one of the following values:
+//  *     @arg tim_dmabase_cr, tim_dmabase_CR2, tim_dmabase_smcr,
+//  *          tim_dmabase_dier, TIM1_dmabase_sr, tim_dmabase_egr,
+//  *          tim_dmabase_CCMR1, tim_dmabase_ccmr2, tim_dmabase_CCER,
+//  *          tim_dmabase_cnt, tim_dmabase_psc, tim_dmabase_arr,
+//  *          tim_dmabase_rcr, tim_dmabase_CCR1, tim_dmabase_CCR2,
+//  *          tim_dmabase_ccr3, tim_dmabase_ccr4, tim_dmabase_bdtr,
+//  *          tim_dmabase_dcr.
+//  * @param  tim_dmaburstlength: dma burst length.
+//  *   this parameter can be one value between:
+//  *   tim_dmaburstlength_1transfer and tim_dmaburstlength_18transfers.
+//  * @retval none
+//  */
+//void tim_dmaconfig(tim_typedef* TIMx, uint16_t tim_dmabase, uint16_t tim_dmaburstlength)
+//{
+//  /* check the parameters */
+//  assert_param(is_tim_list4_periph(TIMx));
+//  assert_param(is_tim_dma_base(tim_dmabase));
+//  assert_param(is_tim_dma_length(tim_dmaburstlength));
+//  /* set the dma base and the dma burst length */
+//  TIMx->dcr = tim_dmabase | tim_dmaburstlength;
+//}
+
+/**
+  * @brief  enables or DISABLEs the TIMx's dma requests.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 6, 7, 8, 15, 16 or 17
+  *   to select the tim peripheral.
+  * @param  tim_dmasource: specifies the dma request sources.
+  *   this parameter can be any combination of the following values:
+  *     @arg tim_dma_update: tim update interrupt source
+  *     @arg tim_dma_cc1: tim capture compare 1 dma source
+  *     @arg tim_dma_cc2: tim capture compare 2 dma source
+  *     @arg tim_dma_cc3: tim capture compare 3 dma source
+  *     @arg tim_dma_cc4: tim capture compare 4 dma source
+  *     @arg tim_dma_com: tim commutation dma source
+  *     @arg tim_dma_trigger: tim trigger dma source
+  * @param  newstate: new state of the dma request sources.
+  *   this parameter can be: enable or DISABLE.
+  * @retval none
+  */
+//void tim_dmacmd(tim_typedef* TIMx, uint16_t tim_dmasource, FUNCTIONAL_STATE newstate)
+//{
+//  /* check the parameters */
+//  assert_param(IS_TIM_LIST9_PERIPH(TIMx));
+//  assert_param(IS_TIM_DMA_SOURCE(tim_dmasource));
+//  assert_param(IS_FUNCTIONAL_STATE(newstate));
+//
+//  if (newstate != DISABLE)
+//  {
+//    /* enable the dma sources */
+//    TIMx->dier |= tim_dmasource;
+//  }
+//  else
+//  {
+//    /* DISABLE the dma sources */
+//    TIMx->dier &= (uint16_t)~tim_dmasource;
+//  }
+//}
+
+/**
+  * @brief  configures the TIMx internal clock
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15
+  *         to select the tim peripheral.
+  * @retval none
+  */
+AT(.com_periph.tim.internalclock)
+void tim_internalclockconfig(tim_typedef* TIMx)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+  /* DISABLE slave mode to clock the prescaler directly with the internal clock */
+  TIMx->smcr &=  (uint16_t)(~((uint16_t)TIM_SMCR_SMS));
+}
+
+/**
+  * @brief  configures the TIMx internal trigger as external clock
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 9, 12 or 15 to select the tim peripheral.
+  * @param  tim_itrsource: trigger source.
+  *   this parameter can be one of the following values:
+  * @param  tim_ts_itr0: internal trigger 0
+  * @param  tim_ts_itr1: internal trigger 1
+  * @param  tim_ts_itr2: internal trigger 2
+  * @param  tim_ts_itr3: internal trigger 3
+  * @retval none
+  */
+AT(.com_periph.tim.itrxexternalclock)
+void tim_itrxexternalclockconfig(tim_typedef* TIMx, uint16_t tim_inputtriggersource)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+  assert_param(IS_TIM_INTERNAL_TRIGGER_SELECTION(tim_inputtriggersource));
+  /* select the internal trigger */
+  tim_selectinputtrigger(TIMx, tim_inputtriggersource);
+  /* select the external clock mode1 */
+  TIMx->smcr |= TIM_SLAVEMODE_EXTERNAL1;
+}
+
+/**
+  * @brief  configures the TIMx trigger as external clock
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 9, 12 or 15 to select the tim peripheral.
+  * @param  tim_tixexternalclksource: trigger source.
+  *   this parameter can be one of the following values:
+  *     @arg tim_tixexternalclk1source_ti1ed: ti1 edge detector
+  *     @arg tim_tixexternalclk1source_ti1: filtered timer input 1
+  *     @arg TIM_TIXEXTERNALCLK1SOURCE_TI2: filtered timer input 2
+  * @param  tim_icpolarity: specifies the tix polarity.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICPOLARITY_RISING
+  *     @arg TIM_ICPOLARITY_FALLING
+  * @param  icfilter : specifies the filter value.
+  *   this parameter must be a value between 0x0 and 0xf.
+  * @retval none
+  */
+AT(.com_periph.tim.tixexternalclock)
+void tim_tixexternalclockconfig(tim_typedef* TIMx, uint16_t tim_tixexternalclksource,
+                                uint16_t tim_icpolarity, uint16_t icfilter)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+  assert_param(IS_TIM_TIXCLK_SOURCE(tim_tixexternalclksource));
+  assert_param(IS_TIM_IC_POLARITY(tim_icpolarity));
+  assert_param(IS_TIM_IC_FILTER(icfilter));
+  /* configure the timer input clock source */
+  if (tim_tixexternalclksource == TIM_TIXEXTERNALCLK1SOURCE_TI2)
+  {
+    ti2_config(TIMx, tim_icpolarity, TIM_ICSELECTION_DIRECTTI, icfilter);
+  }
+  else
+  {
+    ti1_config(TIMx, tim_icpolarity, TIM_ICSELECTION_DIRECTTI, icfilter);
+  }
+  /* select the trigger source */
+  tim_selectinputtrigger(TIMx, tim_tixexternalclksource);
+  /* select the external clock mode1 */
+  TIMx->smcr |= TIM_SLAVEMODE_EXTERNAL1;
+}
+
+/**
+  * @brief  configures the external clock mode1
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_exttrgprescaler: the external trigger prescaler.
+  *   this parameter can be one of the following values:
+  *     @arg tim_exttrgpsc_off: etrp prescaler off.
+  *     @arg tim_exttrgpsc_div2: etrp frequency divided by 2.
+  *     @arg tim_exttrgpsc_div4: etrp frequency divided by 4.
+  *     @arg tim_exttrgpsc_div8: etrp frequency divided by 8.
+  * @param  tim_exttrgpolarity: the external trigger polarity.
+  *   this parameter can be one of the following values:
+  *     @arg tim_exttrgpolarity_inverted: active low or falling edge active.
+  *     @arg tim_exttrgpolarity_noninverted: active high or rising edge active.
+  * @param  exttrgfilter: external trigger filter.
+  *   this parameter must be a value between 0x00 and 0x0f
+  * @retval none
+  */
+AT(.com_periph.etrclockmode1)
+void tim_etrclockmode1config(tim_typedef* TIMx, uint16_t tim_exttrgprescaler, uint16_t tim_exttrgpolarity,
+                             uint16_t exttrgfilter)
+{
+  uint16_t tmpsmcr = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_EXT_PRESCALER(tim_exttrgprescaler));
+  assert_param(IS_TIM_EXT_POLARITY(tim_exttrgpolarity));
+  assert_param(IS_TIM_EXT_FILTER(exttrgfilter));
+  /* configure the etr clock source */
+  tim_etrconfig(TIMx, tim_exttrgprescaler, tim_exttrgpolarity, exttrgfilter);
+
+  /* get the TIMx smcr register value */
+  tmpsmcr = TIMx->smcr;
+  /* reset the sms bits */
+  tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS));
+  /* select the external clock mode1 */
+  tmpsmcr |= TIM_SLAVEMODE_EXTERNAL1;
+  /* select the trigger selection : etrf */
+  tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_TS));
+  tmpsmcr |= TIM_TS_ETRF;
+  /* write to TIMx smcr */
+  TIMx->smcr = tmpsmcr;
+}
+
+/**
+  * @brief  configures the external clock mode2
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_exttrgprescaler: the external trigger prescaler.
+  *   this parameter can be one of the following values:
+  *     @arg tim_exttrgpsc_off: etrp prescaler off.
+  *     @arg tim_exttrgpsc_div2: etrp frequency divided by 2.
+  *     @arg tim_exttrgpsc_div4: etrp frequency divided by 4.
+  *     @arg tim_exttrgpsc_div8: etrp frequency divided by 8.
+  * @param  tim_exttrgpolarity: the external trigger polarity.
+  *   this parameter can be one of the following values:
+  *     @arg tim_exttrgpolarity_inverted: active low or falling edge active.
+  *     @arg tim_exttrgpolarity_noninverted: active high or rising edge active.
+  * @param  exttrgfilter: external trigger filter.
+  *   this parameter must be a value between 0x00 and 0x0f
+  * @retval none
+  */
+AT(.com_periph.tim.etrclockmode2)
+void tim_etrclockmode2config(tim_typedef* TIMx, uint16_t tim_exttrgprescaler,
+                             uint16_t tim_exttrgpolarity, uint16_t exttrgfilter)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_EXT_PRESCALER(tim_exttrgprescaler));
+  assert_param(IS_TIM_EXT_POLARITY(tim_exttrgpolarity));
+  assert_param(IS_TIM_EXT_FILTER(exttrgfilter));
+  /* configure the etr clock source */
+  tim_etrconfig(TIMx, tim_exttrgprescaler, tim_exttrgpolarity, exttrgfilter);
+  /* enable the external clock mode2 */
+  TIMx->smcr |= TIM_SMCR_ECE;
+}
+
+/**
+  * @brief  configures the TIMx external trigger (etr).
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_exttrgprescaler: the external trigger prescaler.
+  *   this parameter can be one of the following values:
+  *     @arg tim_exttrgpsc_off: etrp prescaler off.
+  *     @arg tim_exttrgpsc_div2: etrp frequency divided by 2.
+  *     @arg tim_exttrgpsc_div4: etrp frequency divided by 4.
+  *     @arg tim_exttrgpsc_div8: etrp frequency divided by 8.
+  * @param  tim_exttrgpolarity: the external trigger polarity.
+  *   this parameter can be one of the following values:
+  *     @arg tim_exttrgpolarity_inverted: active low or falling edge active.
+  *     @arg tim_exttrgpolarity_noninverted: active high or rising edge active.
+  * @param  exttrgfilter: external trigger filter.
+  *   this parameter must be a value between 0x00 and 0x0f
+  * @retval none
+  */
+AT(.com_periph.tim.etrconfig)
+void tim_etrconfig(tim_typedef* TIMx, uint16_t tim_exttrgprescaler, uint16_t tim_exttrgpolarity,
+                   uint16_t exttrgfilter)
+{
+  uint16_t tmpsmcr = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_EXT_PRESCALER(tim_exttrgprescaler));
+  assert_param(IS_TIM_EXT_POLARITY(tim_exttrgpolarity));
+  assert_param(IS_TIM_EXT_FILTER(exttrgfilter));
+  tmpsmcr = TIMx->smcr;
+  /* reset the etr bits */
+  tmpsmcr &= SMCR_ETR_MASK;
+  /* set the PRESCALER, the filter value and the polarity */
+  tmpsmcr |= (uint16_t)(tim_exttrgprescaler | (uint16_t)(tim_exttrgpolarity | (uint16_t)(exttrgfilter << (uint16_t)8)));
+  /* write to TIMx smcr */
+  TIMx->smcr = tmpsmcr;
+}
+
+/**
+  * @brief  configures the TIMx prescaler.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  prescaler: specifies the prescaler register value
+  * @param  tim_pscreloadmode: specifies the tim prescaler reload mode
+  *   this parameter can be one of the following values:
+  *     @arg tim_pscreloadmode_update: the prescaler is loaded at the update event.
+  *     @arg TIM_PSCRELOADMODE_IMMEDIATE: the prescaler is loaded immediately.
+  * @retval none
+  */
+AT(.com_periph.tim.prescaler)
+void tim_prescalerconfig(tim_typedef* TIMx, uint16_t prescaler, uint16_t tim_pscreloadmode)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(IS_TIM_PRESCALER_RELOAD(tim_pscreloadmode));
+  /* set the prescaler value */
+  TIMx->psc = prescaler;
+  /* set or reset the ug bit */
+  TIMx->egr = tim_pscreloadmode;
+}
+
+/**
+  * @brief  specifies the TIMx counter mode to be used.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_countermode: specifies the counter mode to be used
+  *   this parameter can be one of the following values:
+  *     @arg TIM_COUNTERMODE_UP: tim up counting mode
+  *     @arg tim_countermode_down: tim down counting mode
+  *     @arg tim_countermode_centeraligned1: tim center aligned mode1
+  *     @arg tim_countermode_centeraligned2: tim center aligned mode2
+  *     @arg tim_countermode_centeraligned3: tim center aligned mode3
+  * @retval none
+  */
+AT(.com_periph.tim.countermode)
+void tim_countermodeconfig(tim_typedef* TIMx, uint16_t tim_countermode)
+{
+  uint16_t tmpcr1 = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_COUNTER_MODE(tim_countermode));
+  tmpcr1 = TIMx->cr1;
+  /* reset the cms and dir bits */
+  tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));
+  /* set the counter mode */
+  tmpcr1 |= tim_countermode;
+  /* write to TIMx cr1 register */
+  TIMx->cr1 = tmpcr1;
+}
+
+/**
+  * @brief  selects the input trigger source
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the tim peripheral.
+  * @param  tim_inputtriggersource: the input trigger source.
+  *   this parameter can be one of the following values:
+  *     @arg tim_ts_itr0: internal trigger 0
+  *     @arg tim_ts_itr1: internal trigger 1
+  *     @arg tim_ts_itr2: internal trigger 2
+  *     @arg tim_ts_itr3: internal trigger 3
+  *     @arg tim_ts_ti1f_ed: ti1 edge detector
+  *     @arg tim_ts_ti1fp1: filtered timer input 1
+  *     @arg tim_ts_ti2fp2: filtered timer input 2
+  *     @arg TIM_TS_ETRF: external trigger input
+  * @retval none
+  */
+AT(.com_periph.tim.selectinputtrigger)
+void tim_selectinputtrigger(tim_typedef* TIMx, uint16_t tim_inputtriggersource)
+{
+  uint16_t tmpsmcr = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+  assert_param(IS_TIM_TRIGGER_SELECTION(tim_inputtriggersource));
+  /* get the TIMx smcr register value */
+  tmpsmcr = TIMx->smcr;
+  /* reset the ts bits */
+  tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_TS));
+  /* set the input trigger source */
+  tmpsmcr |= tim_inputtriggersource;
+  /* write to TIMx smcr */
+  TIMx->smcr = tmpsmcr;
+}
+
+/**
+  * @brief  configures the TIMx encoder interface.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_encodermode: specifies the TIMx encoder mode.
+  *   this parameter can be one of the following values:
+  *     @arg tim_encodermode_ti1: counter counts on ti1fp1 edge depending on ti2fp2 level.
+  *     @arg tim_encodermode_ti2: counter counts on ti2fp2 edge depending on ti1fp1 level.
+  *     @arg tim_encodermode_ti12: counter counts on both ti1fp1 and ti2fp2 edges depending
+  *                                on the level of the other input.
+  * @param  tim_ic1polarity: specifies the ic1 polarity
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICPOLARITY_FALLING: ic falling edge.
+  *     @arg TIM_ICPOLARITY_RISING: ic rising edge.
+  * @param  tim_ic2polarity: specifies the ic2 polarity
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICPOLARITY_FALLING: ic falling edge.
+  *     @arg TIM_ICPOLARITY_RISING: ic rising edge.
+  * @retval none
+  */
+void tim_encoderinterfaceconfig(tim_typedef* TIMx, uint16_t tim_encodermode,
+                                uint16_t tim_ic1polarity, uint16_t tim_ic2polarity)
+{
+  uint16_t tmpsmcr = 0;
+  uint16_t tmpccmr1 = 0;
+  uint16_t tmpccer = 0;
+
+  /* check the parameters */
+  assert_param(IS_TIM_LIST5_PERIPH(TIMx));
+  assert_param(IS_TIM_ENCODER_MODE(tim_encodermode));
+  assert_param(IS_TIM_IC_POLARITY(tim_ic1polarity));
+  assert_param(IS_TIM_IC_POLARITY(tim_ic2polarity));
+
+  /* get the TIMx smcr register value */
+  tmpsmcr = TIMx->smcr;
+
+  /* get the TIMx ccmr1 register value */
+  tmpccmr1 = TIMx->ccmr1;
+
+  /* get the TIMx ccer register value */
+  tmpccer = TIMx->ccer;
+
+  /* set the encoder mode */
+  tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS));
+  tmpsmcr |= tim_encodermode;
+
+  /* select the capture compare 1 and the capture compare 2 as input */
+  tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC1S)) & (uint16_t)(~((uint16_t)TIM_CCMR1_CC2S))); // 预留 ■
+  tmpccmr1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0; // 预留 ■
+
+  /* set the ti1 and the ti2 polarities */
+  tmpccer &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCER_CC1P)) & ((uint16_t)~((uint16_t)TIM_CCER_CC2P)));
+  tmpccer |= (uint16_t)(tim_ic1polarity | (uint16_t)(tim_ic2polarity << (uint16_t)4));
+
+  /* write to TIMx smcr */
+  TIMx->smcr = tmpsmcr;
+  /* write to TIMx ccmr1 */
+  TIMx->ccmr1 = tmpccmr1;
+  /* write to TIMx ccer */
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  forces the TIMx output 1 waveform to active or inactive level.
+  * @param  TIMx: where x can be  1 to 17 except 6 and 7 to select the tim peripheral.
+  * @param  tim_forcedaction: specifies the forced action to be set to the output waveform.
+  *   this parameter can be one of the following values:
+  *     @arg tim_forcedaction_active: force active level on oc1ref
+  *     @arg tim_forcedaction_inactive: force inactive level on oc1ref.
+  * @retval none
+  */
+AT(.com_periph.tim.forcedoc1)
+void tim_forcedoc1config(tim_typedef* TIMx, uint16_t tim_forcedaction)
+{
+  uint16_t tmpccmr1 = 0;
+  /* check the parameters */
+  assert_param(is_tim_list8_periph(TIMx));
+  assert_param(IS_TIM_FORCED_ACTION(tim_forcedaction));
+  tmpccmr1 = TIMx->ccmr1;
+  /* reset the oc1m bits */
+  tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1M);
+  /* configure the forced output mode */
+  tmpccmr1 |= tim_forcedaction;
+  /* write to TIMx ccmr1 register */
+  TIMx->ccmr1 = tmpccmr1;
+}
+
+/**
+  * @brief  forces the TIMx output 2 waveform to active or inactive level.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the tim peripheral.
+  * @param  tim_forcedaction: specifies the forced action to be set to the output waveform.
+  *   this parameter can be one of the following values:
+  *     @arg tim_forcedaction_active: force active level on oc2ref
+  *     @arg tim_forcedaction_inactive: force inactive level on oc2ref.
+  * @retval none
+  */
+AT(.com_periph.tim.forcedoc2)
+void tim_forcedoc2config(tim_typedef* TIMx, uint16_t tim_forcedaction)
+{
+  uint16_t tmpccmr1 = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+  assert_param(IS_TIM_FORCED_ACTION(tim_forcedaction));
+  tmpccmr1 = TIMx->ccmr1;
+  /* reset the oc2m bits */
+  tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2M);
+  /* configure the forced output mode */
+  tmpccmr1 |= (uint16_t)(tim_forcedaction << 8);
+  /* write to TIMx ccmr1 register */
+  TIMx->ccmr1 = tmpccmr1;
+}
+
+/**
+  * @brief  forces the TIMx output 3 waveform to active or inactive level.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_forcedaction: specifies the forced action to be set to the output waveform.
+  *   this parameter can be one of the following values:
+  *     @arg tim_forcedaction_active: force active level on oc3ref
+  *     @arg tim_forcedaction_inactive: force inactive level on oc3ref.
+  * @retval none
+  */
+AT(.com_periph.tim.forcedoc3)
+void tim_forcedoc3config(tim_typedef* TIMx, uint16_t tim_forcedaction)
+{
+  uint16_t tmpccmr2 = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_FORCED_ACTION(tim_forcedaction));
+  tmpccmr2 = TIMx->ccmr2;
+  /* reset the oc1m bits */
+  tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3M);
+  /* configure the forced output mode */
+  tmpccmr2 |= tim_forcedaction;
+  /* write to TIMx ccmr2 register */
+  TIMx->ccmr2 = tmpccmr2;
+}
+
+/**
+  * @brief  forces the TIMx output 4 waveform to active or inactive level.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_forcedaction: specifies the forced action to be set to the output waveform.
+  *   this parameter can be one of the following values:
+  *     @arg tim_forcedaction_active: force active level on oc4ref
+  *     @arg tim_forcedaction_inactive: force inactive level on oc4ref.
+  * @retval none
+  */
+AT(.com_periph.tim.forcedoc4)
+void tim_forcedoc4config(tim_typedef* TIMx, uint16_t tim_forcedaction)
+{
+  uint16_t tmpccmr2 = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_FORCED_ACTION(tim_forcedaction));
+  tmpccmr2 = TIMx->ccmr2;
+  /* reset the oc2m bits */
+  tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4M);
+  /* configure the forced output mode */
+  tmpccmr2 |= (uint16_t)(tim_forcedaction << 8);
+  /* write to TIMx ccmr2 register */
+  TIMx->ccmr2 = tmpccmr2;
+}
+
+/**
+  * @brief  enables or DISABLEs TIMx peripheral preload register on arr.
+  * @param  TIMx: where x can be  1 to 17 to select the tim peripheral.
+  * @param  newstate: new state of the TIMx peripheral preload register
+  *   this parameter can be: enable or DISABLE.
+  * @retval none
+  */
+AT(.com_periph.tim.arrpreload)
+void tim_arrpreloadconfig(tim_typedef* TIMx, FUNCTIONAL_STATE newstate)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(is_FUNCTIONAL_STATE(newstate));
+  if (newstate != DISABLE)
+  {
+    /* set the arr preload bit */
+    TIMx->cr1 |= TIM_CR1_ARPE;
+  }
+  else
+  {
+    /* reset the arr preload bit */
+    TIMx->cr1 &= (uint16_t)~((uint16_t)TIM_CR1_ARPE);
+  }
+}
+
+/**
+  * @brief  selects the tim peripheral commutation event.
+  * @param  TIMx: where x can be  1, 8, 15, 16 or 17 to select the TIMx peripheral
+  * @param  newstate: new state of the commutation event.
+  *   this parameter can be: enable or DISABLE.
+  * @retval none
+  */
+AT(.com_periph.tim.selectcom)
+void tim_selectcom(tim_typedef* TIMx, FUNCTIONAL_STATE newstate)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST2_PERIPH(TIMx));
+  assert_param(is_FUNCTIONAL_STATE(newstate));
+  if (newstate != DISABLE)
+  {
+    /* set the com bit */
+    TIMx->cr2 |= TIM_CR2_CCUS;
+  }
+  else
+  {
+    /* reset the com bit */
+    TIMx->cr2 &= (uint16_t)~((uint16_t)TIM_CR2_CCUS);
+  }
+}
+
+/**
+  * @brief  selects the TIMx peripheral capture compare dma source.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 15, 16 or 17 to select
+  *         the tim peripheral.
+  * @param  newstate: new state of the capture compare dma source
+  *   this parameter can be: enable or DISABLE.
+  * @retval none
+  */
+//void tim_selectccdma(tim_typedef* TIMx, FUNCTIONAL_STATE newstate)预留
+//{
+//  /* check the parameters */
+//  assert_param(IS_TIM_LIST4_PERIPH(TIMx));
+//  assert_param(is_FUNCTIONAL_STATE(newstate));
+//  if (newstate != DISABLE)
+//  {
+//    /* set the ccds bit */
+//    TIMx->cr2 |= TIM_CR2_CCDS; // 预留 ■
+//  }
+//  else
+//  {
+//    /* reset the ccds bit */
+//    TIMx->cr2 &= (uint16_t)~((uint16_t)TIM_CR2_CCDS); // 预留 ■
+//  }
+//}
+
+/**
+  * @brief  sets or resets the tim peripheral capture compare preload control bit.
+  * @param  TIMx: where x can be   1, 2, 3, 4, 5, 8 or 15
+  *         to select the TIMx peripheral
+  * @param  newstate: new state of the capture compare preload control bit
+  *   this parameter can be: enable or DISABLE.
+  * @retval none
+  */
+AT(.com_periph.tim.ccpreloadcontrol)
+void tim_ccpreloadcontrol(tim_typedef* TIMx, FUNCTIONAL_STATE newstate)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST5_PERIPH(TIMx));
+  assert_param(is_FUNCTIONAL_STATE(newstate));
+  if (newstate != DISABLE)
+  {
+    /* set the ccpc bit */
+    TIMx->cr2 |= TIM_CR2_CCPC;
+  }
+  else
+  {
+    /* reset the ccpc bit */
+    TIMx->cr2 &= (uint16_t)~((uint16_t)TIM_CR2_CCPC);
+  }
+}
+
+/**
+  * @brief  enables or DISABLEs the TIMx peripheral preload register on ccr1.
+  * @param  TIMx: where x can be  1 to 17 except 6 and 7 to select the tim peripheral.
+  * @param  tim_ocpreload: new state of the TIMx peripheral preload register
+  *   this parameter can be one of the following values:
+  *     @arg tim_ocpreload_enable
+  *     @arg tim_ocpreload_DISABLE
+  * @retval none
+  */
+AT(.com_periph.tim.oc1preload)
+void tim_oc1preloadconfig(tim_typedef* TIMx, uint16_t tim_ocpreload)
+{
+  uint16_t tmpccmr1 = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST8_PERIPH(TIMx));
+  assert_param(IS_TIM_OCPRELOAD_STATE(tim_ocpreload));
+  tmpccmr1 = TIMx->ccmr1;
+  /* reset the oc1pe bit */
+  tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1PE);
+  /* enable or DISABLE the output compare preload feature */
+  tmpccmr1 |= tim_ocpreload;
+  /* write to TIMx ccmr1 register */
+  TIMx->ccmr1 = tmpccmr1;
+}
+
+/**
+  * @brief  enables or DISABLEs the TIMx peripheral preload register on ccr2.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select
+  *         the tim peripheral.
+  * @param  tim_ocpreload: new state of the TIMx peripheral preload register
+  *   this parameter can be one of the following values:
+  *     @arg tim_ocpreload_enable
+  *     @arg tim_ocpreload_DISABLE
+  * @retval none
+  */
+AT(.com_periph.tim.oc2preload)
+void tim_oc2preloadconfig(tim_typedef* TIMx, uint16_t tim_ocpreload)
+{
+  uint16_t tmpccmr1 = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+  assert_param(IS_TIM_OCPRELOAD_STATE(tim_ocpreload));
+  tmpccmr1 = TIMx->ccmr1;
+  /* reset the oc2pe bit */
+  tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2PE);
+  /* enable or DISABLE the output compare preload feature */
+  tmpccmr1 |= (uint16_t)(tim_ocpreload << 8);
+  /* write to TIMx ccmr1 register */
+  TIMx->ccmr1 = tmpccmr1;
+}
+
+/**
+  * @brief  enables or DISABLEs the TIMx peripheral preload register on ccr3.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_ocpreload: new state of the TIMx peripheral preload register
+  *   this parameter can be one of the following values:
+  *     @arg tim_ocpreload_enable
+  *     @arg tim_ocpreload_DISABLE
+  * @retval none
+  */
+AT(.com_periph.tim.oc3preload)
+void tim_oc3preloadconfig(tim_typedef* TIMx, uint16_t tim_ocpreload)
+{
+  uint16_t tmpccmr2 = 0;
+  /* check the parameters */
+//  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+//  assert_param(IS_TIM_OCPRELOAD_STATE(tim_ocpreload));
+  tmpccmr2 = TIMx->ccmr2;
+  /* reset the oc3pe bit */
+  tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3PE);
+  /* enable or DISABLE the output compare preload feature */
+  tmpccmr2 |= tim_ocpreload;
+  /* write to TIMx ccmr2 register */
+  TIMx->ccmr2 = tmpccmr2;
+}
+
+/**
+  * @brief  enables or DISABLEs the TIMx peripheral preload register on ccr4.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_ocpreload: new state of the TIMx peripheral preload register
+  *   this parameter can be one of the following values:
+  *     @arg tim_ocpreload_enable
+  *     @arg tim_ocpreload_DISABLE
+  * @retval none
+  */
+AT(.com_periph.tim.oc4preload)
+void tim_oc4preloadconfig(tim_typedef* TIMx, uint16_t tim_ocpreload)
+{
+  uint16_t tmpccmr2 = 0;
+  /* check the parameters */
+//  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+//  assert_param(IS_TIM_OCPRELOAD_STATE(tim_ocpreload));
+  tmpccmr2 = TIMx->ccmr2;
+  /* reset the oc4pe bit */
+  tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4PE);
+  /* enable or DISABLE the output compare preload feature */
+  tmpccmr2 |= (uint16_t)(tim_ocpreload << 8);
+  /* write to TIMx ccmr2 register */
+  TIMx->ccmr2 = tmpccmr2;
+}
+
+/**
+  * @brief  configures the TIMx output compare 1 fast feature.
+  * @param  TIMx: where x can be  1 to 17 except 6 and 7 to select the tim peripheral.
+  * @param  tim_ocfast: new state of the output compare fast enable bit.
+  *   this parameter can be one of the following values:
+  *     @arg tim_ocfast_enable: tim output compare fast enable
+  *     @arg tim_ocfast_DISABLE: tim output compare fast DISABLE
+  * @retval none
+  */
+//void tim_oc1fastconfig(tim_typedef* TIMx, uint16_t tim_ocfast) 预留
+//{
+//  uint16_t tmpccmr1 = 0;
+//  /* check the parameters */
+//  assert_param(IS_TIM_LIST8_PERIPH(TIMx));
+//  assert_param(IS_TIM_OCFAST_STATE(tim_ocfast));
+//  /* get the TIMx ccmr1 register value */
+//  tmpccmr1 = TIMx->ccmr1;
+//  /* reset the oc1fe bit */
+//  tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1FE); // 预留 ■
+//  /* enable or DISABLE the output compare fast bit */
+//  tmpccmr1 |= tim_ocfast;
+//  /* write to TIMx ccmr1 */
+//  TIMx->ccmr1 = tmpccmr1;
+//}
+
+/**
+  * @brief  configures the TIMx output compare 2 fast feature.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select
+  *         the tim peripheral.
+  * @param  tim_ocfast: new state of the output compare fast enable bit.
+  *   this parameter can be one of the following values:
+  *     @arg tim_ocfast_enable: tim output compare fast enable
+  *     @arg tim_ocfast_DISABLE: tim output compare fast DISABLE
+  * @retval none
+  */
+//void tim_oc2fastconfig(tim_typedef* TIMx, uint16_t tim_ocfast) 预留
+//{
+//  uint16_t tmpccmr1 = 0;
+//  /* check the parameters */
+////  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+////  assert_param(IS_TIM_OCFAST_STATE(tim_ocfast));
+//  /* get the TIMx ccmr1 register value */
+//  tmpccmr1 = TIMx->ccmr1;
+//  /* reset the oc2fe bit */
+//  tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2FE); // 预留 ■
+//  /* enable or DISABLE the output compare fast bit */
+//  tmpccmr1 |= (uint16_t)(tim_ocfast << 8);
+//  /* write to TIMx ccmr1 */
+//  TIMx->ccmr1 = tmpccmr1;
+//}
+
+/**
+  * @brief  configures the TIMx output compare 3 fast feature.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_ocfast: new state of the output compare fast enable bit.
+  *   this parameter can be one of the following values:
+  *     @arg tim_ocfast_enable: tim output compare fast enable
+  *     @arg tim_ocfast_DISABLE: tim output compare fast DISABLE
+  * @retval none
+  */
+//void tim_oc3fastconfig(tim_typedef* TIMx, uint16_t tim_ocfast)  预留
+//{
+//  uint16_t tmpccmr2 = 0;
+//  /* check the parameters */
+//  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+//  assert_param(IS_TIM_OCFAST_STATE(tim_ocfast));
+//  /* get the TIMx ccmr2 register value */
+//  tmpccmr2 = TIMx->ccmr2;
+//  /* reset the oc3fe bit */
+//  tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3FE); // 预留 ■
+//  /* enable or DISABLE the output compare fast bit */
+//  tmpccmr2 |= tim_ocfast;
+//  /* write to TIMx ccmr2 */
+//  TIMx->ccmr2 = tmpccmr2;
+//}
+
+/**
+  * @brief  configures the TIMx output compare 4 fast feature.
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_ocfast: new state of the output compare fast enable bit.
+  *   this parameter can be one of the following values:
+  *     @arg tim_ocfast_enable: tim output compare fast enable
+  *     @arg tim_ocfast_DISABLE: tim output compare fast DISABLE
+  * @retval none
+  */
+//void tim_oc4fastconfig(tim_typedef* TIMx, uint16_t tim_ocfast) 预留
+//{
+//  uint16_t tmpccmr2 = 0;
+//  /* check the parameters */
+//  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+//  assert_param(IS_TIM_OCFAST_STATE(tim_ocfast));
+//  /* get the TIMx ccmr2 register value */
+//  tmpccmr2 = TIMx->ccmr2;
+//  /* reset the oc4fe bit */
+//  tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4FE); // 预留 ■
+//  /* enable or DISABLE the output compare fast bit */
+//  tmpccmr2 |= (uint16_t)(tim_ocfast << 8);
+//  /* write to TIMx ccmr2 */
+//  TIMx->ccmr2 = tmpccmr2;
+//}
+
+/**
+  * @brief  clears or safeguards the ocref1 signal on an external event
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_occlear: new state of the output compare clear enable bit.
+  *   this parameter can be one of the following values:
+  *     @arg tim_occlear_enable: tim output clear enable
+  *     @arg tim_occlear_DISABLE: tim output clear DISABLE
+  * @retval none
+  */
+AT(.com_periph.tim.clearoc1)
+void tim_clearoc1ref(tim_typedef* TIMx, uint16_t tim_occlear)
+{
+  uint16_t tmpccmr1 = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_OCCLEAR_STATE(tim_occlear));
+
+  tmpccmr1 = TIMx->ccmr1;
+
+  /* reset the oc1ce bit */
+  tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1CE);
+  /* enable or DISABLE the output compare clear bit */
+  tmpccmr1 |= tim_occlear;
+  /* write to TIMx ccmr1 register */
+  TIMx->ccmr1 = tmpccmr1;
+}
+
+/**
+  * @brief  clears or safeguards the ocref2 signal on an external event
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_occlear: new state of the output compare clear enable bit.
+  *   this parameter can be one of the following values:
+  *     @arg tim_occlear_enable: tim output clear enable
+  *     @arg tim_occlear_DISABLE: tim output clear DISABLE
+  * @retval none
+  */
+AT(.com_periph.tim.clearoc2)
+void tim_clearoc2ref(tim_typedef* TIMx, uint16_t tim_occlear)
+{
+  uint16_t tmpccmr1 = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_OCCLEAR_STATE(tim_occlear));
+  tmpccmr1 = TIMx->ccmr1;
+  /* reset the oc2ce bit */
+  tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2CE);
+  /* enable or DISABLE the output compare clear bit */
+  tmpccmr1 |= (uint16_t)(tim_occlear << 8);
+  /* write to TIMx ccmr1 register */
+  TIMx->ccmr1 = tmpccmr1;
+}
+
+/**
+  * @brief  clears or safeguards the ocref3 signal on an external event
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_occlear: new state of the output compare clear enable bit.
+  *   this parameter can be one of the following values:
+  *     @arg tim_occlear_enable: tim output clear enable
+  *     @arg tim_occlear_DISABLE: tim output clear DISABLE
+  * @retval none
+  */
+AT(.com_periph.tim.clearoc3)
+void tim_clearoc3ref(tim_typedef* TIMx, uint16_t tim_occlear)
+{
+  uint16_t tmpccmr2 = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_OCCLEAR_STATE(tim_occlear));
+  tmpccmr2 = TIMx->ccmr2;
+  /* reset the oc3ce bit */
+  tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3CE);
+  /* enable or DISABLE the output compare clear bit */
+  tmpccmr2 |= tim_occlear;
+  /* write to TIMx ccmr2 register */
+  TIMx->ccmr2 = tmpccmr2;
+}
+
+/**
+  * @brief  clears or safeguards the ocref4 signal on an external event
+  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_occlear: new state of the output compare clear enable bit.
+  *   this parameter can be one of the following values:
+  *     @arg tim_occlear_enable: tim output clear enable
+  *     @arg tim_occlear_DISABLE: tim output clear DISABLE
+  * @retval none
+  */
+AT(.com_periph.tim.clearoc4)
+void tim_clearoc4ref(tim_typedef* TIMx, uint16_t tim_occlear)
+{
+  uint16_t tmpccmr2 = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_OCCLEAR_STATE(tim_occlear));
+  tmpccmr2 = TIMx->ccmr2;
+  /* reset the oc4ce bit */
+  tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4CE);
+  /* enable or DISABLE the output compare clear bit */
+  tmpccmr2 |= (uint16_t)(tim_occlear << 8);
+  /* write to TIMx ccmr2 register */
+  TIMx->ccmr2 = tmpccmr2;
+}
+
+/**
+  * @brief  configures the TIMx channel 1 polarity.
+  * @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the tim peripheral.
+  * @param  tim_ocpolarity: specifies the oc1 polarity
+  *   this parameter can be one of the following values:
+  *     @arg TIM_OCPOLARITY_HIGH: output compare active high
+  *     @arg tim_ocpolarity_low: output compare active low
+  * @retval none
+  */
+AT(.com_periph.tim.oc1polarity)
+void tim_oc1polarityconfig(tim_typedef* TIMx, uint16_t tim_ocpolarity)
+{
+  uint16_t tmpccer = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST8_PERIPH(TIMx));
+  assert_param(IS_TIM_OC_POLARITY(tim_ocpolarity));
+  tmpccer = TIMx->ccer;
+  /* set or reset the cc1p bit */
+  tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC1P);
+  tmpccer |= tim_ocpolarity;
+  /* write to TIMx ccer register */
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  configures the TIMx channel 1n polarity.
+  * @param  TIMx: where x can be 1, 8, 15, 16 or 17 to select the tim peripheral.
+  * @param  tim_ocnpolarity: specifies the oc1n polarity
+  *   this parameter can be one of the following values:
+  *     @arg tim_ocnpolarity_high: output compare active high
+  *     @arg tim_ocnpolarity_low: output compare active low
+  * @retval none
+  */
+AT(.com_periph.oc1npolarity)
+void tim_oc1npolarityconfig(tim_typedef* TIMx, uint16_t tim_ocnpolarity)
+{
+  uint16_t tmpccer = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST2_PERIPH(TIMx));
+  assert_param(IS_TIM_OCN_POLARITY(tim_ocnpolarity));
+
+  tmpccer = TIMx->ccer;
+  /* set or reset the cc1np bit */
+  tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC1NP);
+  tmpccer |= tim_ocnpolarity;
+  /* write to TIMx ccer register */
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  configures the TIMx channel 2 polarity.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the tim peripheral.
+  * @param  tim_ocpolarity: specifies the oc2 polarity
+  *   this parameter can be one of the following values:
+  *     @arg TIM_OCPOLARITY_HIGH: output compare active high
+  *     @arg tim_ocpolarity_low: output compare active low
+  * @retval none
+  */
+AT(.com_periph.oc2polarity)
+void tim_oc2polarityconfig(tim_typedef* TIMx, uint16_t tim_ocpolarity)
+{
+  uint16_t tmpccer = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+  assert_param(IS_TIM_OC_POLARITY(tim_ocpolarity));
+  tmpccer = TIMx->ccer;
+  /* set or reset the cc2p bit */
+  tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC2P);
+  tmpccer |= (uint16_t)(tim_ocpolarity << 4);
+  /* write to TIMx ccer register */
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  configures the TIMx channel 2n polarity.
+  * @param  TIMx: where x can be 1 or 8 to select the tim peripheral.
+  * @param  tim_ocnpolarity: specifies the oc2n polarity
+  *   this parameter can be one of the following values:
+  *     @arg tim_ocnpolarity_high: output compare active high
+  *     @arg tim_ocnpolarity_low: output compare active low
+  * @retval none
+  */
+AT(.com_periph.oc2npolarity)
+void tim_oc2npolarityconfig(tim_typedef* TIMx, uint16_t tim_ocnpolarity)
+{
+  uint16_t tmpccer = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST1_PERIPH(TIMx));
+  assert_param(IS_TIM_OCN_POLARITY(tim_ocnpolarity));
+
+  tmpccer = TIMx->ccer;
+  /* set or reset the cc2np bit */
+  tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC2NP);
+  tmpccer |= (uint16_t)(tim_ocnpolarity << 4);
+  /* write to TIMx ccer register */
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  configures the TIMx channel 3 polarity.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_ocpolarity: specifies the oc3 polarity
+  *   this parameter can be one of the following values:
+  *     @arg TIM_OCPOLARITY_HIGH: output compare active high
+  *     @arg tim_ocpolarity_low: output compare active low
+  * @retval none
+  */
+AT(.com_periph.oc3polarity)
+void tim_oc3polarityconfig(tim_typedef* TIMx, uint16_t tim_ocpolarity)
+{
+  uint16_t tmpccer = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_OC_POLARITY(tim_ocpolarity));
+  tmpccer = TIMx->ccer;
+  /* set or reset the cc3p bit */
+  tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC3P);
+  tmpccer |= (uint16_t)(tim_ocpolarity << 8);
+  /* write to TIMx ccer register */
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  configures the TIMx channel 3n polarity.
+  * @param  TIMx: where x can be 1 or 8 to select the tim peripheral.
+  * @param  tim_ocnpolarity: specifies the oc3n polarity
+  *   this parameter can be one of the following values:
+  *     @arg tim_ocnpolarity_high: output compare active high
+  *     @arg tim_ocnpolarity_low: output compare active low
+  * @retval none
+  */
+AT(.com_periph.oc3npolarity)
+void tim_oc3npolarityconfig(tim_typedef* TIMx, uint16_t tim_ocnpolarity)
+{
+  uint16_t tmpccer = 0;
+
+  /* check the parameters */
+  assert_param(IS_TIM_LIST1_PERIPH(TIMx));
+  assert_param(IS_TIM_OCN_POLARITY(tim_ocnpolarity));
+
+  tmpccer = TIMx->ccer;
+  /* set or reset the cc3np bit */
+  tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC3NP);
+  tmpccer |= (uint16_t)(tim_ocnpolarity << 8);
+  /* write to TIMx ccer register */
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  configures the TIMx channel 4 polarity.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_ocpolarity: specifies the oc4 polarity
+  *   this parameter can be one of the following values:
+  *     @arg TIM_OCPOLARITY_HIGH: output compare active high
+  *     @arg tim_ocpolarity_low: output compare active low
+  * @retval none
+  */
+AT(.com_periph.oc4polarity)
+void tim_oc4polarityconfig(tim_typedef* TIMx, uint16_t tim_ocpolarity)
+{
+  uint16_t tmpccer = 0;
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_OC_POLARITY(tim_ocpolarity));
+  tmpccer = TIMx->ccer;
+  /* set or reset the cc4p bit */
+  tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC4P);
+  tmpccer |= (uint16_t)(tim_ocpolarity << 12);
+  /* write to TIMx ccer register */
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  enables or DISABLEs the tim capture compare channel x.
+  * @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the tim peripheral.
+  * @param  tim_channel: specifies the tim channel
+  *   this parameter can be one of the following values:
+  *     @arg TIM_CHANNEL_1: tim channel 1
+  *     @arg TIM_CHANNEL_2: tim channel 2
+  *     @arg TIM_CHANNEL_3: tim channel 3
+  *     @arg TIM_CHANNEL_4: tim channel 4
+  * @param  tim_ccx: specifies the tim channel ccxe bit new state.
+  *   this parameter can be: tim_ccx_enable or tim_ccx_DISABLE.
+  * @retval none
+  */
+AT(.com_periph.ccxcmd)
+void tim_ccxcmd(tim_typedef* TIMx, uint16_t tim_channel, uint16_t tim_ccx)
+{
+  uint16_t tmp = 0;
+
+  /* check the parameters */
+  assert_param(IS_TIM_LIST8_PERIPH(TIMx));
+  assert_param(IS_TIM_CHANNEL(tim_channel));
+  assert_param(IS_TIM_CCX(tim_ccx));
+
+  tmp = CCER_CCE_SET << tim_channel;
+
+  /* reset the ccxe bit */
+  TIMx->ccer &= (uint16_t)~ tmp;
+
+  /* set or reset the ccxe bit */
+  TIMx->ccer |=  (uint16_t)(tim_ccx << tim_channel);
+}
+
+/**
+  * @brief  enables or DISABLEs the tim capture compare channel xn.
+  * @param  TIMx: where x can be 1, 8, 15, 16 or 17 to select the tim peripheral.
+  * @param  tim_channel: specifies the tim channel
+  *   this parameter can be one of the following values:
+  *     @arg TIM_CHANNEL_1: tim channel 1
+  *     @arg TIM_CHANNEL_2: tim channel 2
+  *     @arg TIM_CHANNEL_3: tim channel 3
+  * @param  tim_ccxn: specifies the tim channel ccxne bit new state.
+  *   this parameter can be: tim_ccxn_enable or tim_ccxn_DISABLE.
+  * @retval none
+  */
+AT(.com_periph.ccxncmd)
+void tim_ccxncmd(tim_typedef* TIMx, uint16_t tim_channel, uint16_t tim_ccxn)
+{
+  uint16_t tmp = 0;
+
+  /* check the parameters */
+  assert_param(IS_TIM_LIST2_PERIPH(TIMx));
+  assert_param(IS_TIM_COMPLEMENTARY_CHANNEL(tim_channel));
+  assert_param(IS_TIM_CCXN(tim_ccxn));
+
+  tmp = CCER_CCNE_SET << tim_channel;
+
+  /* reset the ccxne bit */
+  TIMx->ccer &= (uint16_t) ~tmp;
+
+  /* set or reset the ccxne bit */
+  TIMx->ccer |=  (uint16_t)(tim_ccxn << tim_channel);
+}
+
+/**
+  * @brief  selects the tim output compare mode.
+  * @note   this function DISABLEs the selected channel before changing the output
+  *         compare mode.
+  *         user has to enable this channel using tim_ccxcmd and tim_ccxncmd functions.
+  * @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the tim peripheral.
+  * @param  tim_channel: specifies the tim channel
+  *   this parameter can be one of the following values:
+  *     @arg TIM_CHANNEL_1: tim channel 1
+  *     @arg TIM_CHANNEL_2: tim channel 2
+  *     @arg TIM_CHANNEL_3: tim channel 3
+  *     @arg TIM_CHANNEL_4: tim channel 4
+  * @param  tim_ocmode: specifies the tim output compare mode.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_OCMODE_TIMING
+  *     @arg tim_ocmode_active
+  *     @arg tim_ocmode_toggle
+  *     @arg tim_ocmode_low
+  *     @arg tim_ocmode_high
+  *     @arg tim_ocmode_pwm1
+  *     @arg tim_ocmode_pwm2
+  *     @arg tim_forcedaction_active
+  *     @arg tim_forcedaction_inactive
+  * @retval none
+  */
+AT(.com_periph.selectocxm)
+void tim_selectocxm(tim_typedef* TIMx, uint16_t tim_channel, uint16_t tim_ocmode)
+{
+  uint32_t tmp = 0;
+  uint16_t tmp1 = 0;
+
+  /* check the parameters */
+  assert_param(IS_TIM_LIST8_PERIPH(TIMx));
+  assert_param(IS_TIM_CHANNEL(tim_channel));
+  assert_param(IS_TIM_OCM(tim_ocmode));
+
+  tmp = (uint32_t) TIMx;
+  tmp += CCMR_OFFSET;
+
+  tmp1 = CCER_CCE_SET << (uint16_t)tim_channel;
+
+  /* DISABLE the channel: reset the ccxe bit */
+  TIMx->ccer &= (uint16_t) ~tmp1;
+
+  if((tim_channel == TIM_CHANNEL_1) ||(tim_channel == TIM_CHANNEL_3))
+  {
+    tmp += (tim_channel>>1);
+
+    /* reset the ocxm bits in the ccmrx register */
+    *(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC1M);
+
+    /* configure the ocxm bits in the ccmrx register */
+    *(__IO uint32_t *) tmp |= tim_ocmode;
+  }
+  else
+  {
+    tmp += (uint16_t)(tim_channel - (uint16_t)4)>> (uint16_t)1;
+
+    /* reset the ocxm bits in the ccmrx register */
+    *(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC2M);
+
+    /* configure the ocxm bits in the ccmrx register */
+    *(__IO uint32_t *) tmp |= (uint16_t)(tim_ocmode << 8);
+  }
+}
+
+/**
+  * @brief  enables or DISABLEs the TIMx update event.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  newstate: new state of the TIMx udis bit
+  *   this parameter can be: enable or DISABLE.
+  * @retval none
+  */
+AT(.com_periph.tim.updatedisable)
+void tim_updatedisableconfig(tim_typedef* TIMx, FUNCTIONAL_STATE newstate)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(IS_FUNCTIONAL_STATE(newstate));
+  if (newstate != DISABLE)
+  {
+    /* set the update DISABLE bit */
+    TIMx->cr1 |= TIM_CR1_UDIS;
+  }
+  else
+  {
+    /* reset the update DISABLE bit */
+    TIMx->cr1 &= (uint16_t)~((uint16_t)TIM_CR1_UDIS);
+  }
+}
+
+/**
+  * @brief  configures the TIMx update request interrupt source.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  tim_updatesource: specifies the update source.
+  *   this parameter can be one of the following values:
+  *     @arg tim_updatesource_regular: source of update is the counter overflow/underflow
+                                       or the setting of ug bit, or an update generation
+                                       through the slave mode controller.
+  *     @arg tim_updatesource_global: source of update is counter overflow/underflow.
+  * @retval none
+  */
+AT(.com_periph.tim.updaterequest)
+void tim_updaterequestconfig(tim_typedef* TIMx, uint16_t tim_updatesource)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(IS_TIM_UPDATE_SOURCE(tim_updatesource));
+  if (tim_updatesource != TIM_UPDATESOURCE_GLOBAL)
+  {
+    /* set the urs bit */
+    TIMx->cr1 |= TIM_CR1_URS;
+  }
+  else
+  {
+    /* reset the urs bit */
+    TIMx->cr1 &= (uint16_t)~((uint16_t)TIM_CR1_URS);
+  }
+}
+
+/**
+  * @brief  enables or DISABLEs the TIMx's hall sensor interface.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  newstate: new state of the TIMx hall sensor interface.
+  *   this parameter can be: enable or DISABLE.
+  * @retval none
+  */
+//void tim_selecthallsensor(tim_typedef* TIMx, FUNCTIONAL_STATE newstate) 预留
+//{
+//  /* check the parameters */
+//  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+//  assert_param(IS_FUNCTIONAL_STATE(newstate));
+//  if (newstate != DISABLE)
+//  {
+//    /* set the ti1s bit */
+//    TIMx->cr2 |= TIM_CR2_TI1S; // 预留 ■
+//  }
+//  else
+//  {
+//    /* reset the ti1s bit */
+//   TIMx->cr2 &= (uint16_t)~((uint16_t)TIM_CR2_TI1S); // 预留 ■
+//  }
+//}
+
+/**
+  * @brief  selects the TIMx's one pulse mode.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  tim_opmode: specifies the opm mode to be used.
+  *   this parameter can be one of the following values:
+  *     @arg tim_opmode_single
+  *     @arg tim_opmode_repetitive
+  * @retval none
+  */
+AT(.com_periph.selectonepulsemode)
+void tim_selectonepulsemode(tim_typedef* TIMx, uint16_t tim_opmode)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(IS_TIM_OPM_MODE(tim_opmode));
+  /* reset the opm bit */
+  TIMx->cr1 &= (uint16_t)~((uint16_t)TIM_CR1_OPM);
+  /* configure the opm mode */
+  TIMx->cr1 |= tim_opmode;
+}
+
+/**
+  * @brief  selects the TIMx trigger output mode.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5, 6, 7, 8, 9, 12 or 15 to select the tim peripheral.
+  * @param  tim_trgosource: specifies the trigger output source.
+  *   this paramter can be one of the following values:
+  *
+  *  - for all TIMx
+  *     @arg tim_trgosource_reset:  the ug bit in the tim_egr register is used as the trigger output (trgo).
+  *     @arg tim_trgosource_enable: the counter enable cen is used as the trigger output (trgo).
+  *     @arg tim_trgosource_update: the update event is selected as the trigger output (trgo).
+  *
+  *  - for all TIMx except tim6 and tim7
+  *     @arg tim_trgosource_oc1: the trigger output sends a positive pulse when the cc1if flag
+  *                              is to be set, as soon as a capture or compare match occurs (trgo).
+  *     @arg tim_trgosource_oc1ref: oc1ref signal is used as the trigger output (trgo).
+  *     @arg tim_trgosource_oc2ref: oc2ref signal is used as the trigger output (trgo).
+  *     @arg tim_trgosource_oc3ref: oc3ref signal is used as the trigger output (trgo).
+  *     @arg tim_trgosource_oc4ref: oc4ref signal is used as the trigger output (trgo).
+  *
+  * @retval none
+  */
+AT(.com_periph.tim.selectoutputtrigger)
+void tim_selectoutputtrigger(tim_typedef* TIMx, uint16_t tim_trgosource)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST7_PERIPH(TIMx));
+  assert_param(IS_TIM_TRGO_SOURCE(tim_trgosource));
+  /* reset the mms bits */
+  TIMx->cr2 &= (uint16_t)~((uint16_t)TIM_CR2_MMS);
+  /* select the trgo source */
+  TIMx->cr2 |=  tim_trgosource;
+}
+
+/**
+  * @brief  selects the TIMx slave mode.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the tim peripheral.
+  * @param  tim_slavemode: specifies the timer slave mode.
+  *   this parameter can be one of the following values:
+  *     @arg tim_slavemode_reset: rising edge of the selected trigger signal (trgi) re-initializes
+  *                               the counter and triggers an update of the registers.
+  *     @arg tim_slavemode_gated:     the counter clock is enabled when the trigger signal (trgi) is high.
+  *     @arg tim_slavemode_trigger:   the counter starts at a rising edge of the trigger trgi.
+  *     @arg TIM_SLAVEMODE_EXTERNAL1: rising edges of the selected trigger (trgi) clock the counter.
+  * @retval none
+  */
+AT(.com_periph.tim.selectslavemode)
+void tim_selectslavemode(tim_typedef* TIMx, uint16_t tim_slavemode)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+  assert_param(IS_TIM_SLAVE_MODE(tim_slavemode));
+ /* reset the sms bits */
+  TIMx->smcr &= (uint16_t)~((uint16_t)TIM_SMCR_SMS);
+  /* select the slave mode */
+  TIMx->smcr |= tim_slavemode;
+}
+
+/**
+  * @brief  sets or resets the TIMx master/slave mode.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the tim peripheral.
+  * @param  tim_masterslavemode: specifies the timer master slave mode.
+  *   this parameter can be one of the following values:
+  *     @arg tim_masterslavemode_enable: synchronization between the current timer
+  *                                      and its slaves (through trgo).
+  *     @arg tim_masterslavemode_DISABLE: no action
+  * @retval none
+  */
+//void tim_selectmasterslavemode(tim_typedef* TIMx, uint16_t tim_masterslavemode) 预留
+//{
+//  /* check the parameters */
+//  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+//  assert_param(IS_TIM_MSM_STATE(tim_masterslavemode));
+//  /* reset the msm bit */
+//  TIMx->smcr &= (uint16_t)~((uint16_t)TIM_SMCR_MSM); // 预留 ■
+//
+//  /* set or reset the msm bit */
+//  TIMx->smcr |= tim_masterslavemode;
+//}
+
+/**
+  * @brief  sets the TIMx counter register value
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  counter: specifies the counter register new value.
+  * @retval none
+  */
+AT(.com_periph.tim.setcounter)
+void tim_setcounter(tim_typedef* TIMx, uint16_t counter)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  /* set the counter register value */
+  TIMx->cnt = counter;
+}
+
+/**
+  * @brief  sets the TIMx autoreload register value
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  autoreload: specifies the autoreload register new value.
+  * @retval none
+  */
+AT(.com_periph.tim.setautoreload)
+void tim_setautoreload(tim_typedef* TIMx, uint16_t autoreload)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  /* set the autoreload register value */
+  TIMx->arr = autoreload;
+}
+
+/**
+  * @brief  sets the TIMx capture compare1 register value
+  * @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the tim peripheral.
+  * @param  compare1: specifies the capture compare1 register new value.
+  * @retval none
+  */
+AT(.com_periph.setcompare1)
+void tim_setcompare1(tim_typedef* TIMx, uint16_t compare1)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST8_PERIPH(TIMx));
+  /* set the capture compare1 register value */
+  TIMx->ccr1 = compare1;
+}
+
+/**
+  * @brief  sets the TIMx capture compare2 register value
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the tim peripheral.
+  * @param  compare2: specifies the capture compare2 register new value.
+  * @retval none
+  */
+AT(.com_periph.setcompare2)
+void tim_setcompare2(tim_typedef* TIMx, uint16_t compare2)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+  /* set the capture compare2 register value */
+  TIMx->ccr2 = compare2;
+}
+
+/**
+  * @brief  sets the TIMx capture compare3 register value
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  compare3: specifies the capture compare3 register new value.
+  * @retval none
+  */
+AT(.com_periph.setcompare3)
+void tim_setcompare3(tim_typedef* TIMx, uint16_t compare3)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  /* set the capture compare3 register value */
+  TIMx->ccr3 = compare3;
+}
+
+/**
+  * @brief  sets the TIMx capture compare4 register value
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  compare4: specifies the capture compare4 register new value.
+  * @retval none
+  */
+AT(.com_periph.setcompare4)
+void tim_setcompare4(tim_typedef* TIMx, uint16_t compare4)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  /* set the capture compare4 register value */
+  TIMx->ccr4 = compare4;
+}
+
+/**
+  * @brief  sets the TIMx input capture 1 prescaler.
+  * @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the tim peripheral.
+  * @param  tim_icpsc: specifies the input capture1 prescaler new value.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICPSC_DIV1: no prescaler
+  *     @arg tim_icpsc_div2: capture is done once every 2 events
+  *     @arg tim_icpsc_div4: capture is done once every 4 events
+  *     @arg tim_icpsc_div8: capture is done once every 8 events
+  * @retval none
+  */
+AT(.com_periph.setic1prescaler)
+void tim_setic1prescaler(tim_typedef* TIMx, uint16_t tim_icpsc)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST8_PERIPH(TIMx));
+  assert_param(IS_TIM_IC_PRESCALER(tim_icpsc));
+  /* reset the ic1psc bits */
+  TIMx->ccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_IC1PSC); // 预留 ■
+  /* set the ic1psc value */
+  TIMx->ccmr1 |= tim_icpsc;
+}
+
+/**
+  * @brief  sets the TIMx input capture 2 prescaler.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the tim peripheral.
+  * @param  tim_icpsc: specifies the input capture2 prescaler new value.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICPSC_DIV1: no prescaler
+  *     @arg tim_icpsc_div2: capture is done once every 2 events
+  *     @arg tim_icpsc_div4: capture is done once every 4 events
+  *     @arg tim_icpsc_div8: capture is done once every 8 events
+  * @retval none
+  */
+AT(.com_periph.setic2prescaler)
+void tim_setic2prescaler(tim_typedef* TIMx, uint16_t tim_icpsc)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+  assert_param(IS_TIM_IC_PRESCALER(tim_icpsc));
+  /* reset the ic2psc bits */
+  TIMx->ccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_IC2PSC); // 预留 ■
+  /* set the ic2psc value */
+  TIMx->ccmr1 |= (uint16_t)(tim_icpsc << 8);
+}
+
+/**
+  * @brief  sets the TIMx input capture 3 prescaler.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_icpsc: specifies the input capture3 prescaler new value.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICPSC_DIV1: no prescaler
+  *     @arg tim_icpsc_div2: capture is done once every 2 events
+  *     @arg tim_icpsc_div4: capture is done once every 4 events
+  *     @arg tim_icpsc_div8: capture is done once every 8 events
+  * @retval none
+  */
+AT(.com_periph.setic3prescaler)
+void tim_setic3prescaler(tim_typedef* TIMx, uint16_t tim_icpsc)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_IC_PRESCALER(tim_icpsc));
+  /* reset the ic3psc bits */
+  TIMx->ccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_IC3PSC); // 预留 ■
+  /* set the ic3psc value */
+  TIMx->ccmr2 |= tim_icpsc;
+}
+
+/**
+  * @brief  sets the TIMx input capture 4 prescaler.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_icpsc: specifies the input capture4 prescaler new value.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICPSC_DIV1: no prescaler
+  *     @arg tim_icpsc_div2: capture is done once every 2 events
+  *     @arg tim_icpsc_div4: capture is done once every 4 events
+  *     @arg tim_icpsc_div8: capture is done once every 8 events
+  * @retval none
+  */
+AT(.com_periph.setic4prescaler)
+void tim_setic4prescaler(tim_typedef* TIMx, uint16_t tim_icpsc)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+  assert_param(IS_TIM_IC_PRESCALER(tim_icpsc));
+  /* reset the ic4psc bits */
+  TIMx->ccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_IC4PSC); // 预留 ■
+  /* set the ic4psc value */
+  TIMx->ccmr2 |= (uint16_t)(tim_icpsc << 8);
+}
+
+/**
+  * @brief  sets the TIMx clock division value.
+  * @param  TIMx: where x can be  1 to 17 except 6 and 7 to select
+  *   the tim peripheral.
+  * @param  tim_ckd: specifies the clock division value.
+  *   this parameter can be one of the following value:
+  *     @arg TIM_CKD_DIV1: tdts = tck_tim
+  *     @arg tim_ckd_div2: tdts = 2*tck_tim
+  *     @arg tim_ckd_div4: tdts = 4*tck_tim
+  * @retval none
+  */
+AT(.com_periph.tim.setclockdivision)
+void tim_setclockdivision(tim_typedef* TIMx, uint16_t tim_ckd)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_LIST8_PERIPH(TIMx));
+  assert_param(IS_TIM_CKD_DIV(tim_ckd));
+  /* reset the ckd bits */
+  TIMx->cr1 &= (uint16_t)~((uint16_t)TIM_CR1_CKD);
+  /* set the ckd value */
+  TIMx->cr1 |= tim_ckd;
+}
+
+/**
+  * @brief  gets the TIMx input capture 1 value.
+  * @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the tim peripheral.
+  * @retval capture compare 1 register value.
+  */
+//uint16_t tim_getcapture1(tim_typedef* TIMx)
+//{
+//  /* check the parameters */
+//  assert_param(IS_TIM_LIST8_PERIPH(TIMx));
+//  /* get the capture 1 register value */
+//  return TIMx->ccr1;
+//}
+
+/**
+  * @brief  gets the TIMx input capture 2 value.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the tim peripheral.
+  * @retval capture compare 2 register value.
+  */
+//uint16_t tim_getcapture2(tim_typedef* TIMx)
+//{
+//  /* check the parameters */
+//  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
+//  /* get the capture 2 register value */
+//  return TIMx->ccr2;
+//}
+
+/**
+  * @brief  gets the TIMx input capture 3 value.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @retval capture compare 3 register value.
+  */
+//uint16_t tim_getcapture3(tim_typedef* TIMx)
+//{
+//  /* check the parameters */
+//  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+//  /* get the capture 3 register value */
+//  return TIMx->ccr3;
+//}
+
+/**
+  * @brief  gets the TIMx input capture 4 value.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @retval capture compare 4 register value.
+  */
+//uint16_t tim_getcapture4(tim_typedef* TIMx)
+//{
+//  /* check the parameters */
+//  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
+//  /* get the capture 4 register value */
+//  return TIMx->ccr4;
+//}
+
+/**
+  * @brief  gets the TIMx counter value.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @retval counter register value.
+  */
+AT(.com_periph.tim.getcounter)
+uint16_t tim_getcounter(tim_typedef* TIMx)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  /* get the counter register value */
+  return TIMx->cnt;
+}
+
+/**
+  * @brief  gets the TIMx prescaler value.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @retval prescaler register value.
+  */
+AT(.com_periph.tim.getprescaler)
+uint16_t tim_getprescaler(tim_typedef* TIMx)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  /* get the prescaler register value */
+  return TIMx->psc;
+}
+
+/**
+  * @brief  checks whether the specified tim flag is set or not.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  tim_flag: specifies the flag to check.
+  *   this parameter can be one of the following values:
+  *     @arg tim_flag_update: tim update flag
+  *     @arg tim_flag_cc1: tim capture compare 1 flag
+  *     @arg tim_flag_cc2: tim capture compare 2 flag
+  *     @arg tim_flag_cc3: tim capture compare 3 flag
+  *     @arg tim_flag_cc4: tim capture compare 4 flag
+  *     @arg tim_flag_com: tim commutation flag
+  *     @arg tim_flag_trigger: tim trigger flag
+  *     @arg tim_flag_break: tim break flag
+  *     @arg tim_flag_cc1of: tim capture compare 1 overcapture flag
+  *     @arg tim_flag_cc2of: tim capture compare 2 overcapture flag
+  *     @arg tim_flag_cc3of: tim capture compare 3 overcapture flag
+  *     @arg tim_flag_cc4of: tim capture compare 4 overcapture flag
+  * @note
+  *   - tim6 and tim7 can have only one update flag.
+  *   - tim9, TIM12 and TIM15 can have only tim_flag_update, tim_flag_cc1,
+  *      tim_flag_cc2 or tim_flag_trigger.
+  *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have tim_flag_update or tim_flag_cc1.
+  *   - tim_flag_break is used only with TIM1, tim8 and TIM15.
+  *   - tim_flag_com is used only with TIM1, tim8, TIM15, TIM16 and TIM17.
+  * @retval the new state of tim_flag (set or reset).
+  */
+AT(.com_periph.getflagstatus)
+FLAG_STATE tim_getflagstatus(tim_typedef* TIMx, uint16_t tim_flag)
+{
+  IT_STATE bitstatus = RESET;
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(IS_TIM_GET_FLAG(tim_flag));
+
+  if ((TIMx->sr & tim_flag) != (uint16_t)RESET)
+  {
+    bitstatus = SET;
+  }
+  else
+  {
+    bitstatus = RESET;
+  }
+  return bitstatus;
+}
+
+/**
+  * @brief  clears the TIMx's pending flags.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  tim_flag: specifies the flag bit to clear.
+  *   this parameter can be any combination of the following values:
+  *     @arg tim_flag_update: tim update flag
+  *     @arg tim_flag_cc1: tim capture compare 1 flag
+  *     @arg tim_flag_cc2: tim capture compare 2 flag
+  *     @arg tim_flag_cc3: tim capture compare 3 flag
+  *     @arg tim_flag_cc4: tim capture compare 4 flag
+  *     @arg tim_flag_com: tim commutation flag
+  *     @arg tim_flag_trigger: tim trigger flag
+  *     @arg tim_flag_break: tim break flag
+  *     @arg tim_flag_cc1of: tim capture compare 1 overcapture flag
+  *     @arg tim_flag_cc2of: tim capture compare 2 overcapture flag
+  *     @arg tim_flag_cc3of: tim capture compare 3 overcapture flag
+  *     @arg tim_flag_cc4of: tim capture compare 4 overcapture flag
+  * @note
+  *   - tim6 and tim7 can have only one update flag.
+  *   - tim9, TIM12 and TIM15 can have only tim_flag_update, tim_flag_cc1,
+  *      tim_flag_cc2 or tim_flag_trigger.
+  *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have tim_flag_update or tim_flag_cc1.
+  *   - tim_flag_break is used only with TIM1, tim8 and TIM15.
+  *   - tim_flag_com is used only with TIM1, tim8, TIM15, TIM16 and TIM17.
+  * @retval none
+  */
+AT(.com_periph.clearflag)
+void tim_clearflag(tim_typedef* TIMx, uint16_t tim_flag)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(IS_TIM_CLEAR_FLAG(tim_flag));
+
+  /* clear the flags */
+  TIMx->sr = (uint16_t)tim_flag;
+}
+
+/**
+  * @brief  checks whether the tim interrupt has occurred or not.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  tim_it: specifies the tim interrupt source to check.
+  *   this parameter can be one of the following values:
+  *     @arg tim_it_update: tim update interrupt source
+  *     @arg tim_it_cc1: tim capture compare 1 interrupt source
+  *     @arg tim_it_cc2: tim capture compare 2 interrupt source
+  *     @arg tim_it_cc3: tim capture compare 3 interrupt source
+  *     @arg tim_it_cc4: tim capture compare 4 interrupt source
+  *     @arg tim_it_com: tim commutation interrupt source
+  *     @arg tim_it_trigger: tim trigger interrupt source
+  *     @arg tim_it_break: tim break interrupt source
+  * @note
+  *   - tim6 and tim7 can generate only an update interrupt.
+  *   - tim9, TIM12 and TIM15 can have only tim_it_update, tim_it_cc1,
+  *      tim_it_cc2 or tim_it_trigger.
+  *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have tim_it_update or tim_it_cc1.
+  *   - tim_it_break is used only with TIM1, tim8 and TIM15.
+  *   - tim_it_com is used only with TIM1, tim8, TIM15, TIM16 and TIM17.
+  * @retval the new state of the tim_it(set or reset).
+  */
+AT(.com_periph.getitstatus)
+IT_STATE tim_getitstatus(tim_typedef* TIMx, uint16_t tim_it)
+{
+  IT_STATE bitstatus = RESET;
+  uint16_t itstatus = 0x0, itenable = 0x0;
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(IS_TIM_GET_IT(tim_it));
+
+  itstatus = TIMx->sr & tim_it;
+
+  itenable = TIMx->dier & tim_it;
+  if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET))
+  {
+    bitstatus = SET;
+  }
+  else
+  {
+    bitstatus = RESET;
+  }
+  return bitstatus;
+}
+
+/**
+  * @brief  clears the TIMx's interrupt pending bits.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  tim_it: specifies the pending bit to clear.
+  *   this parameter can be any combination of the following values:
+  *     @arg tim_it_update: TIM1 update interrupt source
+  *     @arg tim_it_cc1: tim capture compare 1 interrupt source
+  *     @arg tim_it_cc2: tim capture compare 2 interrupt source
+  *     @arg tim_it_cc3: tim capture compare 3 interrupt source
+  *     @arg tim_it_cc4: tim capture compare 4 interrupt source
+  *     @arg tim_it_com: tim commutation interrupt source
+  *     @arg tim_it_trigger: tim trigger interrupt source
+  *     @arg tim_it_break: tim break interrupt source
+  * @note
+  *   - tim6 and tim7 can generate only an update interrupt.
+  *   - tim9, TIM12 and TIM15 can have only tim_it_update, tim_it_cc1,
+  *      tim_it_cc2 or tim_it_trigger.
+  *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have tim_it_update or tim_it_cc1.
+  *   - tim_it_break is used only with TIM1, tim8 and TIM15.
+  *   - tim_it_com is used only with TIM1, tim8, TIM15, TIM16 and TIM17.
+  * @retval none
+  */
+AT(.com_periph.clearitpendingbit)
+void tim_clearitpendingbit(tim_typedef* TIMx, uint16_t tim_it)
+{
+  /* check the parameters */
+  assert_param(IS_TIM_ALL_PERIPH(TIMx));
+  assert_param(IS_TIM_IT(tim_it));
+  /* clear the it pending bit */
+  TIMx->sr = (uint16_t)tim_it;
+}
+
+/**
+  * @brief  configure the ti1 as input.
+  * @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the tim peripheral.
+  * @param  tim_icpolarity : the input polarity.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICPOLARITY_RISING
+  *     @arg TIM_ICPOLARITY_FALLING
+  * @param  tim_icselection: specifies the input to be used.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICSELECTION_DIRECTTI: tim input 1 is selected to be connected to ic1.
+  *     @arg TIM_ICSELECTION_INDIRECTTI: tim input 1 is selected to be connected to ic2.
+  *     @arg tim_icselection_trc: tim input 1 is selected to be connected to trc.
+  * @param  tim_icfilter: specifies the input capture filter.
+  *   this parameter must be a value between 0x00 and 0x0f.
+  * @retval none
+  */
+static void ti1_config(tim_typedef* TIMx, uint16_t tim_icpolarity, uint16_t tim_icselection,
+                       uint16_t tim_icfilter)
+{
+  uint16_t tmpccmr1 = 0, tmpccer = 0;
+  /* DISABLE the channel 1: reset the cc1e bit */
+  TIMx->ccer &= (uint16_t)~((uint16_t)TIM_CCER_CC1E);
+  tmpccmr1 = TIMx->ccmr1;
+  tmpccer = TIMx->ccer;
+  /* select the input and set the filter */
+  tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC1S)) & ((uint16_t)~((uint16_t)TIM_CCMR1_IC1F))); // 预留 ■
+  tmpccmr1 |= (uint16_t)(tim_icselection | (uint16_t)(tim_icfilter << (uint16_t)4));
+
+  if(TIMx == TIM1)
+  {
+    /* select the polarity and set the cc1e bit */
+    tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC1P));
+    tmpccer |= (uint16_t)(tim_icpolarity | (uint16_t)TIM_CCER_CC1E);
+  }
+  else
+  {
+    /* select the polarity and set the cc1e bit */
+    tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC1P | TIM_CCER_CC1NP));
+    tmpccer |= (uint16_t)(tim_icpolarity | (uint16_t)TIM_CCER_CC1E);
+  }
+
+  /* write to TIMx ccmr1 and ccer registers */
+  TIMx->ccmr1 = tmpccmr1;
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  configure the ti2 as input.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the tim peripheral.
+  * @param  tim_icpolarity : the input polarity.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICPOLARITY_RISING
+  *     @arg TIM_ICPOLARITY_FALLING
+  * @param  tim_icselection: specifies the input to be used.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICSELECTION_DIRECTTI: tim input 2 is selected to be connected to ic2.
+  *     @arg TIM_ICSELECTION_INDIRECTTI: tim input 2 is selected to be connected to ic1.
+  *     @arg tim_icselection_trc: tim input 2 is selected to be connected to trc.
+  * @param  tim_icfilter: specifies the input capture filter.
+  *   this parameter must be a value between 0x00 and 0x0f.
+  * @retval none
+  */
+static void ti2_config(tim_typedef* TIMx, uint16_t tim_icpolarity, uint16_t tim_icselection,
+                       uint16_t tim_icfilter)
+{
+  uint16_t tmpccmr1 = 0, tmpccer = 0, tmp = 0;
+  /* DISABLE the channel 2: reset the cc2e bit */
+  TIMx->ccer &= (uint16_t)~((uint16_t)TIM_CCER_CC2E);
+  tmpccmr1 = TIMx->ccmr1;
+  tmpccer = TIMx->ccer;
+  tmp = (uint16_t)(tim_icpolarity << 4);
+  /* select the input and set the filter */
+  tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC2S)) & ((uint16_t)~((uint16_t)TIM_CCMR1_IC2F))); // 预留 ■
+  tmpccmr1 |= (uint16_t)(tim_icfilter << 12);
+  tmpccmr1 |= (uint16_t)(tim_icselection << 8);
+
+  if(TIMx == TIM1)
+  {
+    /* select the polarity and set the cc2e bit */
+    tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC2P));
+    tmpccer |=  (uint16_t)(tmp | (uint16_t)TIM_CCER_CC2E);
+  }
+  else
+  {
+    /* select the polarity and set the cc2e bit */
+    tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC2P | TIM_CCER_CC2NP));
+    tmpccer |= (uint16_t)(tim_icpolarity | (uint16_t)TIM_CCER_CC2E);
+  }
+
+  /* write to TIMx ccmr1 and ccer registers */
+  TIMx->ccmr1 = tmpccmr1 ;
+  TIMx->ccer = tmpccer;
+}
+
+/**
+  * @brief  configure the ti3 as input.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_icpolarity : the input polarity.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICPOLARITY_RISING
+  *     @arg TIM_ICPOLARITY_FALLING
+  * @param  tim_icselection: specifies the input to be used.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICSELECTION_DIRECTTI: tim input 3 is selected to be connected to ic3.
+  *     @arg TIM_ICSELECTION_INDIRECTTI: tim input 3 is selected to be connected to ic4.
+  *     @arg tim_icselection_trc: tim input 3 is selected to be connected to trc.
+  * @param  tim_icfilter: specifies the input capture filter.
+  *   this parameter must be a value between 0x00 and 0x0f.
+  * @retval none
+  */
+//static void ti3_config(tim_typedef* TIMx, uint16_t tim_icpolarity, uint16_t tim_icselection,  预留
+//                       uint16_t tim_icfilter)
+//{
+//  uint16_t tmpccmr2 = 0, tmpccer = 0, tmp = 0;
+//  /* DISABLE the channel 3: reset the cc3e bit */
+//  TIMx->ccer &= (uint16_t)~((uint16_t)TIM_CCER_CC3E);
+//  tmpccmr2 = TIMx->ccmr2;
+//  tmpccer = TIMx->ccer;
+//  tmp = (uint16_t)(tim_icpolarity << 8);
+//  /* select the input and set the filter */
+//  tmpccmr2 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR2_CC3S)) & ((uint16_t)~((uint16_t)TIM_CCMR2_IC3F))); // 预留 ■
+//  tmpccmr2 |= (uint16_t)(tim_icselection | (uint16_t)(tim_icfilter << (uint16_t)4));
+//
+//  if(TIMx == TIM1)
+//  {
+//    /* select the polarity and set the cc3e bit */
+//    tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC3P));
+//    tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CCER_CC3E);
+//  }
+//  else
+//  {
+//    /* select the polarity and set the cc3e bit */
+//    tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC3P | TIM_CCER_CC3NP));
+//    tmpccer |= (uint16_t)(tim_icpolarity | (uint16_t)TIM_CCER_CC3E);
+//  }
+//
+//  /* write to TIMx ccmr2 and ccer registers */
+//  TIMx->ccmr2 = tmpccmr2;
+//  TIMx->ccer = tmpccer;
+//}
+
+/**
+  * @brief  configure the ti4 as input.
+  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the tim peripheral.
+  * @param  tim_icpolarity : the input polarity.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICPOLARITY_RISING
+  *     @arg TIM_ICPOLARITY_FALLING
+  * @param  tim_icselection: specifies the input to be used.
+  *   this parameter can be one of the following values:
+  *     @arg TIM_ICSELECTION_DIRECTTI: tim input 4 is selected to be connected to ic4.
+  *     @arg TIM_ICSELECTION_INDIRECTTI: tim input 4 is selected to be connected to ic3.
+  *     @arg tim_icselection_trc: tim input 4 is selected to be connected to trc.
+  * @param  tim_icfilter: specifies the input capture filter.
+  *   this parameter must be a value between 0x00 and 0x0f.
+  * @retval none
+  */
+//static void ti4_config(tim_typedef* TIMx, uint16_t tim_icpolarity, uint16_t tim_icselection, 预留
+//                       uint16_t tim_icfilter)
+//{
+//  uint16_t tmpccmr2 = 0, tmpccer = 0, tmp = 0;
+//
+//   /* DISABLE the channel 4: reset the cc4e bit */
+//  TIMx->ccer &= (uint16_t)~((uint16_t)TIM_CCER_CC4E);
+//  tmpccmr2 = TIMx->ccmr2;
+//  tmpccer = TIMx->ccer;
+//  tmp = (uint16_t)(tim_icpolarity << 12);
+//  /* select the input and set the filter */
+//  tmpccmr2 &= (uint16_t)((uint16_t)(~(uint16_t)TIM_CCMR2_CC4S) & ((uint16_t)~((uint16_t)TIM_CCMR2_IC4F))); // 预留 ■
+//  tmpccmr2 |= (uint16_t)(tim_icselection << 8);
+//  tmpccmr2 |= (uint16_t)(tim_icfilter << 12);
+//
+//  if(TIMx == TIM1)
+//  {
+//    /* select the polarity and set the cc4e bit */
+//    tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC4P));
+//    tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CCER_CC4E);
+//  }
+//  else
+//  {
+//    /* select the polarity and set the cc4e bit */
+//    tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC3P | TIM_CCER_CC4NP)); // 预留 ■
+//    tmpccer |= (uint16_t)(tim_icpolarity | (uint16_t)TIM_CCER_CC4E);
+//  }
+//  /* write to TIMx ccmr2 and ccer registers */
+//  TIMx->ccmr2 = tmpccmr2;
+//  TIMx->ccer = tmpccer;
+//}
+
+/**
+  * @brief  enables or DISABLEs the TIMx saradc trgo enable or DISABLE.
+  * @param  TIMx: where x can be 1 to 17 to select the tim peripheral.
+  * @param  newstate: new state of the TIMx saradc trgo bit
+  *   this parameter can be: enable or DISABLE.
+  * @retval none
+  */
+AT(.com_periph.tim.trgosaradc)
+void tim_trgosaradc_config(tim_typedef* TIMx, FUNCTIONAL_STATE newstate)
+{
+
+  if(newstate != DISABLE)
+  {
+    /* set the update DISABLE bit */
+    TIMx->sarad |= TIM_SARAD_TRGOEN;
+  }
+  else
+  {
+    /* reset the update DISABLE bit */
+    TIMx->sarad &= (uint32_t)~((uint32_t)TIM_SARAD_TRGOEN);
+  }
+}
+
+
+
+

+ 1097 - 0
driver/driver_adv_timer.h

@@ -0,0 +1,1097 @@
+#ifndef __DRIVER_ADV_TIMER_H__
+#define __DRIVER_ADV_TIMER_H__
+
+/* Includes ------------------------------------------------------------------*/
+#include "driver_com.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define assert_param(expr) ((void)0)
+/** @addtogroup TIM
+  * @{
+  */
+
+#define     __IO    volatile
+
+
+/** @defgroup TIM_Exported_constants
+  * @{
+  */
+
+#define IS_TIM_ALL_PERIPH(PERIPH) (((PERIPH) == TIM1)
+
+/* LIST1: TIM 1 and 8 */
+#define IS_TIM_LIST1_PERIPH(PERIPH)  (((PERIPH) == TIM1)
+
+/* LIST2: TIM 1, 8, 15 16 and 17 */
+#define IS_TIM_LIST2_PERIPH(PERIPH) (((PERIPH) == TIM1)
+/* LIST3: TIM 1, 2, 3, 4, 5 and 8 */
+#define IS_TIM_LIST3_PERIPH(PERIPH) (((PERIPH) == TIM1)
+
+/* LIST4: TIM 1, 2, 3, 4, 5, 8, 15, 16 and 17 */
+#define IS_TIM_LIST4_PERIPH(PERIPH) (((PERIPH) == TIM1)
+
+
+/* LIST5: TIM 1, 2, 3, 4, 5, 8 and 15 */
+#define IS_TIM_LIST5_PERIPH(PERIPH) (((PERIPH) == TIM1)
+
+/* LIST6: TIM 1, 2, 3, 4, 5, 8, 9, 12 and 15 */
+#define IS_TIM_LIST6_PERIPH(PERIPH)  (((PERIPH) == TIM1)
+
+/* LIST7: TIM 1, 2, 3, 4, 5, 6, 7, 8, 9, 12 and 15 */
+#define IS_TIM_LIST7_PERIPH(PERIPH)  (((PERIPH) == TIM1)
+
+/* LIST8: TIM 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16 and 17 */
+#define IS_TIM_LIST8_PERIPH(PERIPH)  (((PERIPH) == TIM1)
+
+/* LIST9: TIM 1, 2, 3, 4, 5, 6, 7, 8, 15, 16, and 17 */
+#define IS_TIM_LIST9_PERIPH(PERIPH)  (((PERIPH) == TIM1)
+
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Output_Compare_and_PWM_modes
+  * @{
+  */
+
+#define TIM_OCMODE_TIMING                  ((uint16_t)0X0000)
+#define TIM_OCMODE_ACTIVE                  ((uint16_t)0X0010)
+#define TIM_OCMODE_INACTIVE                ((uint16_t)0X0020)
+#define TIM_OCMODE_TOGGLE                  ((uint16_t)0X0030)
+#define TIM_OCMODE_PWM1                    ((uint16_t)0X0060)
+#define TIM_OCMODE_PWM2                    ((uint16_t)0X0070)
+#define IS_TIM_OC_MODE(MODE) (((MODE) == TIM_OCMODE_FROZEN) || \
+                              ((MODE) == TIM_OCMODE_ACTIVE) || \
+                              ((MODE) == TIM_OCMODE_INACTIVE) || \
+                              ((MODE) == TIM_OCMODE_TOGGLE)|| \
+                              ((MODE) == TIM_OCMODE_PWM1) || \
+                              ((MODE) == TIM_OCMODE_PWM2))
+#define IS_TIM_OCM(MODE) (((MODE) == TIM_OCMODE_FROZEN) || \
+                          ((MODE) == TIM_OCMODE_ACTIVE) || \
+                          ((MODE) == TIM_OCMODE_INACTIVE) || \
+                          ((MODE) == TIM_OCMODE_TOGGLE)|| \
+                          ((MODE) == TIM_OCMODE_PWM1) || \
+                          ((MODE) == TIM_OCMODE_PWM2) ||	\
+                          ((MODE) == TIM_FORCEDACTION_ACTIVE) || \
+                          ((MODE) == TIM_FORCEDACTION_INACTIVE))
+/**
+  * @}
+  */
+
+/** @defgroup TIM_One_Pulse_Mode
+  * @{
+  */
+
+#define TIM_OPMODE_SINGLE                  ((uint16_t)0X0008)
+#define TIM_OPMODE_REPETITIVE              ((uint16_t)0X0000)
+#define IS_TIM_OPM_MODE(MODE) (((MODE) == TIM_OPMODE_SINGLE) || \
+                               ((MODE) == TIM_OPMODE_REPETITIVE))
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Channel
+  * @{
+  */
+
+#define TIM_CHANNEL_1                      ((uint16_t)0X0000)
+#define TIM_CHANNEL_2                      ((uint16_t)0X0004)
+#define TIM_CHANNEL_3                      ((uint16_t)0X0008)
+#define TIM_CHANNEL_4                      ((uint16_t)0X000C)
+#define IS_TIM_CHANNEL(CHANNEL) (((CHANNEL) == TIM_CHANNEL_1) || \
+                                 ((CHANNEL) == TIM_CHANNEL_2) || \
+                                 ((CHANNEL) == TIM_CHANNEL_3) || \
+                                 ((CHANNEL) == TIM_CHANNEL_4))
+#define IS_TIM_PWMI_CHANNEL(CHANNEL) (((CHANNEL) == TIM_CHANNEL_1) || \
+                                      ((CHANNEL) == TIM_CHANNEL_2))
+#define IS_TIM_COMPLEMENTARY_CHANNEL(CHANNEL) (((CHANNEL) == TIM_CHANNEL_1) || \
+                                               ((CHANNEL) == TIM_CHANNEL_2) || \
+                                               ((CHANNEL) == TIM_CHANNEL_3))
+/**
+  * @}
+  */
+
+/** @defgroup TIM_Clock_Division_CKD
+  * @{
+  */
+
+#define TIM_CKD_DIV1                       ((uint16_t)0X0000)
+#define TIM_CKD_DIV2                       ((uint16_t)0X0100)
+#define TIM_CKD_DIV4                       ((uint16_t)0X0200)
+#define IS_TIM_CKD_DIV(DIV) (((DIV) == TIM_CKD_DIV1) || \
+                             ((DIV) == TIM_CKD_DIV2) || \
+                             ((DIV) == TIM_CKD_DIV4))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_COUNTER_MODE
+  * @{
+  */
+
+#define TIM_COUNTERMODE_UP                 ((uint16_t)0X0000)
+#define TIM_COUNTERMODE_DOWN               ((uint16_t)0X0010)
+#define TIM_COUNTERMODE_CENTERALIGNED1     ((uint16_t)0X0020)
+#define TIM_COUNTERMODE_CENTERALIGNED2     ((uint16_t)0X0040)
+#define TIM_COUNTERMODE_CENTERALIGNED3     ((uint16_t)0X0060)
+#define IS_TIM_COUNTER_MODE(MODE) (((MODE) == TIM_COUNTERMODE_UP) ||  \
+                                   ((MODE) == TIM_COUNTERMODE_DOWN) || \
+                                   ((MODE) == TIM_COUNTERMODE_CENTERALIGNED1) || \
+                                   ((MODE) == TIM_COUNTERMODE_CENTERALIGNED2) || \
+                                   ((MODE) == TIM_COUNTERMODE_CENTERALIGNED3))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_OUTPUT_COMPARE_POLARITY
+  * @{
+  */
+
+#define TIM_OCPOLARITY_HIGH                ((uint16_t)0X0000)
+#define TIM_OCPOLARITY_LOW                 ((uint16_t)0X0002)
+#define IS_TIM_OC_POLARITY(POLARITY) (((POLARITY) == TIM_OCPOLARITY_HIGH) || \
+                                      ((POLARITY) == TIM_OCPOLARITY_LOW))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_OUTPUT_COMPARE_N_POLARITY
+  * @{
+  */
+
+#define TIM_OCNPOLARITY_HIGH               ((uint16_t)0X0000)
+#define TIM_OCNPOLARITY_LOW                ((uint16_t)0X0008)
+#define IS_TIM_OCN_POLARITY(POLARITY) (((POLARITY) == TIM_OCNPOLARITY_HIGH) || \
+                                       ((POLARITY) == TIM_OCNPOLARITY_LOW))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_OUTPUT_COMPARE_STATE
+  * @{
+  */
+
+#define TIM_OUTPUTSTATE_DISABLE            ((uint16_t)0X0000)
+#define TIM_OUTPUTSTATE_ENABLE             ((uint16_t)0X0001)
+#define IS_TIM_OUTPUT_STATE(STATE) (((STATE) == TIM_OUTPUTSTATE_DISABLE) || \
+                                    ((STATE) == TIM_OUTPUTSTATE_ENABLE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_OUTPUT_COMPARE_N_STATE
+  * @{
+  */
+
+#define TIM_OUTPUTNSTATE_DISABLE           ((uint16_t)0X0000)
+#define TIM_OUTPUTNSTATE_ENABLE            ((uint16_t)0X0004)
+#define IS_TIM_OUTPUTN_STATE(STATE) (((STATE) == TIM_OUTPUTNSTATE_DISABLE) || \
+                                     ((STATE) == TIM_OUTPUTNSTATE_ENABLE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_CAPTURE_COMPARE_STATE
+  * @{
+  */
+
+#define TIM_CCX_ENABLE                      ((uint16_t)0X0001)
+#define TIM_CCX_DISABLE                     ((uint16_t)0X0000)
+#define IS_TIM_CCX(CCX) (((CCX) == TIM_CCX_ENABLE) || \
+                         ((CCX) == TIM_CCX_DISABLE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_CAPTURE_COMPARE_N_STATE
+  * @{
+  */
+
+#define TIM_CCXN_ENABLE                     ((uint16_t)0X0004)
+#define TIM_CCXN_DISABLE                    ((uint16_t)0X0000)
+#define IS_TIM_CCXN(CCXN) (((CCXN) == TIM_CCXN_ENABLE) || \
+                           ((CCXN) == TIM_CCXN_DISABLE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP BREAK_INPUT_ENABLE_DISABLE
+  * @{
+  */
+
+#define TIM_BREAK_ENABLE                   ((uint16_t)0X1000)
+#define TIM_BREAK_DISABLE                  ((uint16_t)0X0000)
+#define IS_TIM_BREAK_STATE(STATE) (((STATE) == TIM_BREAK_ENABLE) || \
+                                   ((STATE) == TIM_BREAK_DISABLE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP BREAK_POLARITY
+  * @{
+  */
+
+#define TIM_BREAKPOLARITY_LOW              ((uint16_t)0X0000)
+#define TIM_BREAKPOLARITY_HIGH             ((uint16_t)0X2000)
+#define IS_TIM_BREAK_POLARITY(POLARITY) (((POLARITY) == TIM_BREAKPOLARITY_LOW) || \
+                                         ((POLARITY) == TIM_BREAKPOLARITY_HIGH))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_AOE_BIT_SET_RESET
+  * @{
+  */
+
+#define TIM_AUTOMATICOUTPUT_ENABLE         ((uint16_t)0X4000)
+#define TIM_AUTOMATICOUTPUT_DISABLE        ((uint16_t)0X0000)
+#define IS_TIM_AUTOMATIC_OUTPUT_STATE(STATE) (((STATE) == TIM_AUTOMATICOUTPUT_ENABLE) || \
+                                              ((STATE) == TIM_AUTOMATICOUTPUT_DISABLE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP LOCK_LEVEL
+  * @{
+  */
+
+#define TIM_LOCKLEVEL_OFF                  ((uint16_t)0X0000)
+#define TIM_LOCKLEVEL_1                    ((uint16_t)0X0100)
+#define TIM_LOCKLEVEL_2                    ((uint16_t)0X0200)
+#define TIM_LOCKLEVEL_3                    ((uint16_t)0X0300)
+#define IS_TIM_LOCK_LEVEL(LEVEL) (((LEVEL) == TIM_LOCKLEVEL_OFF) || \
+                                  ((LEVEL) == TIM_LOCKLEVEL_1) || \
+                                  ((LEVEL) == TIM_LOCKLEVEL_2) || \
+                                  ((LEVEL) == TIM_LOCKLEVEL_3))
+/**
+  * @}
+  */
+
+/** @DEFGROUP OSSI_OFF_STATE_SELECTION_FOR_IDLE_MODE_STATE
+  * @{
+  */
+
+#define TIM_OSSISTATE_ENABLE               ((uint16_t)0X0400)
+#define TIM_OSSISTATE_DISABLE              ((uint16_t)0X0000)
+#define IS_TIM_OSSI_STATE(STATE) (((STATE) == TIM_OSSISTATE_ENABLE) || \
+                                  ((STATE) == TIM_OSSISTATE_DISABLE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP OSSR_OFF_STATE_SELECTION_FOR_RUN_MODE_STATE
+  * @{
+  */
+
+#define TIM_OSSRSTATE_ENABLE               ((uint16_t)0X0800)
+#define TIM_OSSRSTATE_DISABLE              ((uint16_t)0X0000)
+#define IS_TIM_OSSR_STATE(STATE) (((STATE) == TIM_OSSRSTATE_ENABLE) || \
+                                  ((STATE) == TIM_OSSRSTATE_DISABLE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_OUTPUT_COMPARE_IDLE_STATE
+  * @{
+  */
+
+#define TIM_OCIDLESTATE_SET                ((uint16_t)0X0100)
+#define TIM_OCIDLESTATE_RESET              ((uint16_t)0X0000)
+#define IS_TIM_OCIDLE_STATE(STATE) (((STATE) == TIM_OCIDLESTATE_SET) || \
+                                    ((STATE) == TIM_OCIDLESTATE_RESET))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_OUTPUT_COMPARE_N_IDLE_STATE
+  * @{
+  */
+
+#define TIM_OCNIDLESTATE_SET               ((uint16_t)0X0200)
+#define TIM_OCNIDLESTATE_RESET             ((uint16_t)0X0000)
+#define IS_TIM_OCNIDLE_STATE(STATE) (((STATE) == TIM_OCNIDLESTATE_SET) || \
+                                     ((STATE) == TIM_OCNIDLESTATE_RESET))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_INPUT_CAPTURE_POLARITY
+  * @{
+  */
+
+#define  TIM_ICPOLARITY_RISING             ((uint16_t)0X0000)
+#define  TIM_ICPOLARITY_FALLING            ((uint16_t)0X0002)
+#define  TIM_ICPOLARITY_BOTHEDGE           ((uint16_t)0X000A)
+#define IS_TIM_IC_POLARITY(POLARITY) (((POLARITY) == TIM_ICPOLARITY_RISING) || \
+                                      ((POLARITY) == TIM_ICPOLARITY_FALLING))
+#define IS_TIM_IC_POLARITY_LITE(POLARITY) (((POLARITY) == TIM_ICPOLARITY_RISING) || \
+                                           ((POLARITY) == TIM_ICPOLARITY_FALLING)|| \
+                                           ((POLARITY) == TIM_ICPOLARITY_BOTHEDGE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_INPUT_CAPTURE_SELECTION
+  * @{
+  */
+
+#define TIM_ICSELECTION_DIRECTTI           ((uint16_t)0X0001) /*!< TIM INPUT 1, 2, 3 OR 4 IS SELECTED TO BE
+                                                                   CONNECTED TO IC1, IC2, IC3 OR IC4, RESPECTIVELY */
+#define TIM_ICSELECTION_INDIRECTTI         ((uint16_t)0X0002) /*!< TIM INPUT 1, 2, 3 OR 4 IS SELECTED TO BE
+                                                                   CONNECTED TO IC2, IC1, IC4 OR IC3, RESPECTIVELY. */
+#define TIM_ICSELECTION_TRC                ((uint16_t)0X0003) /*!< TIM INPUT 1, 2, 3 OR 4 IS SELECTED TO BE CONNECTED TO TRC. */
+#define IS_TIM_IC_SELECTION(SELECTION) (((SELECTION) == TIM_ICSELECTION_DIRECTTI) || \
+                                        ((SELECTION) == TIM_ICSELECTION_INDIRECTTI) || \
+                                        ((SELECTION) == TIM_ICSELECTION_TRC))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_INPUT_CAPTURE_PRESCALER
+  * @{
+  */
+
+#define TIM_ICPSC_DIV1                     ((uint16_t)0X0000) /*!< CAPTURE PERFORMED EACH TIME AN EDGE IS DETECTED ON THE CAPTURE INPUT. */
+#define TIM_ICPSC_DIV2                     ((uint16_t)0X0004) /*!< CAPTURE PERFORMED ONCE EVERY 2 EVENTS. */
+#define TIM_ICPSC_DIV4                     ((uint16_t)0X0008) /*!< CAPTURE PERFORMED ONCE EVERY 4 EVENTS. */
+#define TIM_ICPSC_DIV8                     ((uint16_t)0X000C) /*!< CAPTURE PERFORMED ONCE EVERY 8 EVENTS. */
+#define IS_TIM_IC_PRESCALER(PRESCALER) (((PRESCALER) == TIM_ICPSC_DIV1) || \
+                                        ((PRESCALER) == TIM_ICPSC_DIV2) || \
+                                        ((PRESCALER) == TIM_ICPSC_DIV4) || \
+                                        ((PRESCALER) == TIM_ICPSC_DIV8))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_INTERRUPT_SOURCES
+  * @{
+  */
+
+#define TIM_IT_UPDATE                      ((uint16_t)0X0001)
+#define TIM_IT_CC1                         ((uint16_t)0X0002)
+#define TIM_IT_CC2                         ((uint16_t)0X0004)
+#define TIM_IT_CC3                         ((uint16_t)0X0008)
+#define TIM_IT_CC4                         ((uint16_t)0X0010)
+#define TIM_IT_COM                         ((uint16_t)0X0020)
+#define TIM_IT_TRIGGER                     ((uint16_t)0X0040)
+#define TIM_IT_BREAK                       ((uint16_t)0X0080)
+#define IS_TIM_IT(IT) ((((IT) & (uint16_t)0XFF00) == 0X0000) && ((IT) != 0X0000))
+
+#define IS_TIM_GET_IT(IT) (((IT) == TIM_IT_UPDATE) || \
+                           ((IT) == TIM_IT_CC1) || \
+                           ((IT) == TIM_IT_CC2) || \
+                           ((IT) == TIM_IT_CC3) || \
+                           ((IT) == TIM_IT_CC4) || \
+                           ((IT) == TIM_IT_COM) || \
+                           ((IT) == TIM_IT_TRIGGER) || \
+                           ((IT) == TIM_IT_BREAK))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_DMA_BASE_ADDRESS
+  * @{
+  */
+
+#define TIM_DMABASE_CR1                    ((uint16_t)0X0000)
+#define TIM_DMABASE_CR2                    ((uint16_t)0X0001)
+#define TIM_DMABASE_SMCR                   ((uint16_t)0X0002)
+#define TIM_DMABASE_DIER                   ((uint16_t)0X0003)
+#define TIM_DMABASE_SR                     ((uint16_t)0X0004)
+#define TIM_DMABASE_EGR                    ((uint16_t)0X0005)
+#define TIM_DMABASE_CCMR1                  ((uint16_t)0X0006)
+#define TIM_DMABASE_CCMR2                  ((uint16_t)0X0007)
+#define TIM_DMABASE_CCER                   ((uint16_t)0X0008)
+#define TIM_DMABASE_CNT                    ((uint16_t)0X0009)
+#define TIM_DMABASE_PSC                    ((uint16_t)0X000A)
+#define TIM_DMABASE_ARR                    ((uint16_t)0X000B)
+#define TIM_DMABASE_RCR                    ((uint16_t)0X000C)
+#define TIM_DMABASE_CCR1                   ((uint16_t)0X000D)
+#define TIM_DMABASE_CCR2                   ((uint16_t)0X000E)
+#define TIM_DMABASE_CCR3                   ((uint16_t)0X000F)
+#define TIM_DMABASE_CCR4                   ((uint16_t)0X0010)
+#define TIM_DMABASE_BDTR                   ((uint16_t)0X0011)
+#define TIM_DMABASE_DCR                    ((uint16_t)0X0012)
+#define IS_TIM_DMA_BASE(BASE) (((BASE) == TIM_DMABASE_CR1) || \
+                               ((BASE) == TIM_DMABASE_CR2) || \
+                               ((BASE) == TIM_DMABASE_SMCR) || \
+                               ((BASE) == TIM_DMABASE_DIER) || \
+                               ((BASE) == TIM_DMABASE_SR) || \
+                               ((BASE) == TIM_DMABASE_EGR) || \
+                               ((BASE) == TIM_DMABASE_CCMR1) || \
+                               ((BASE) == TIM_DMABASE_CCMR2) || \
+                               ((BASE) == TIM_DMABASE_CCER) || \
+                               ((BASE) == TIM_DMABASE_CNT) || \
+                               ((BASE) == TIM_DMABASE_PSC) || \
+                               ((BASE) == TIM_DMABASE_ARR) || \
+                               ((BASE) == TIM_DMABASE_RCR) || \
+                               ((BASE) == TIM_DMABASE_CCR1) || \
+                               ((BASE) == TIM_DMABASE_CCR2) || \
+                               ((BASE) == TIM_DMABASE_CCR3) || \
+                               ((BASE) == TIM_DMABASE_CCR4) || \
+                               ((BASE) == TIM_DMABASE_BDTR) || \
+                               ((BASE) == TIM_DMABASE_DCR))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_DMA_BURST_LENGTH
+  * @{
+  */
+
+#define TIM_DMABURSTLENGTH_1TRANSFER           ((uint16_t)0X0000)
+#define TIM_DMABURSTLENGTH_2TRANSFERS          ((uint16_t)0X0100)
+#define TIM_DMABURSTLENGTH_3TRANSFERS          ((uint16_t)0X0200)
+#define TIM_DMABURSTLENGTH_4TRANSFERS          ((uint16_t)0X0300)
+#define TIM_DMABURSTLENGTH_5TRANSFERS          ((uint16_t)0X0400)
+#define TIM_DMABURSTLENGTH_6TRANSFERS          ((uint16_t)0X0500)
+#define TIM_DMABURSTLENGTH_7TRANSFERS          ((uint16_t)0X0600)
+#define TIM_DMABURSTLENGTH_8TRANSFERS          ((uint16_t)0X0700)
+#define TIM_DMABURSTLENGTH_9TRANSFERS          ((uint16_t)0X0800)
+#define TIM_DMABURSTLENGTH_10TRANSFERS         ((uint16_t)0X0900)
+#define TIM_DMABURSTLENGTH_11TRANSFERS         ((uint16_t)0X0A00)
+#define TIM_DMABURSTLENGTH_12TRANSFERS         ((uint16_t)0X0B00)
+#define TIM_DMABURSTLENGTH_13TRANSFERS         ((uint16_t)0X0C00)
+#define TIM_DMABURSTLENGTH_14TRANSFERS         ((uint16_t)0X0D00)
+#define TIM_DMABURSTLENGTH_15TRANSFERS         ((uint16_t)0X0E00)
+#define TIM_DMABURSTLENGTH_16TRANSFERS         ((uint16_t)0X0F00)
+#define TIM_DMABURSTLENGTH_17TRANSFERS         ((uint16_t)0X1000)
+#define TIM_DMABURSTLENGTH_18TRANSFERS         ((uint16_t)0X1100)
+#define IS_TIM_DMA_LENGTH(LENGTH) (((LENGTH) == TIM_DMABURSTLENGTH_1TRANSFER) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_2TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_3TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_4TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_5TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_6TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_7TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_8TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_9TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_10TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_11TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_12TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_13TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_14TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_15TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_16TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_17TRANSFERS) || \
+                                   ((LENGTH) == TIM_DMABURSTLENGTH_18TRANSFERS))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_DMA_SOURCES
+  * @{
+  */
+
+#define TIM_DMA_UPDATE                     ((uint16_t)0X0100)
+#define TIM_DMA_CC1                        ((uint16_t)0X0200)
+#define TIM_DMA_CC2                        ((uint16_t)0X0400)
+#define TIM_DMA_CC3                        ((uint16_t)0X0800)
+#define TIM_DMA_CC4                        ((uint16_t)0X1000)
+#define TIM_DMA_COM                        ((uint16_t)0X2000)
+#define TIM_DMA_TRIGGER                    ((uint16_t)0X4000)
+#define IS_TIM_DMA_SOURCE(SOURCE) ((((SOURCE) & (uint16_t)0X80FF) == 0X0000) && ((SOURCE) != 0X0000))
+
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_EXTERNAL_TRIGGER_PRESCALER
+  * @{
+  */
+
+#define TIM_EXTTRGPSC_OFF                  ((uint16_t)0X0000)
+#define TIM_EXTTRGPSC_DIV2                 ((uint16_t)0X1000)
+#define TIM_EXTTRGPSC_DIV4                 ((uint16_t)0X2000)
+#define TIM_EXTTRGPSC_DIV8                 ((uint16_t)0X3000)
+#define IS_TIM_EXT_PRESCALER(PRESCALER) (((PRESCALER) == TIM_EXTTRGPSC_OFF) || \
+                                         ((PRESCALER) == TIM_EXTTRGPSC_DIV2) || \
+                                         ((PRESCALER) == TIM_EXTTRGPSC_DIV4) || \
+                                         ((PRESCALER) == TIM_EXTTRGPSC_DIV8))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_INTERNAL_TRIGGER_SELECTION
+  * @{
+  */
+
+#define TIM_TS_ITR0                        ((uint16_t)0X0000)
+#define TIM_TS_ITR1                        ((uint16_t)0X0010)
+#define TIM_TS_ITR2                        ((uint16_t)0X0020)
+#define TIM_TS_ITR3                        ((uint16_t)0X0030)
+#define TIM_TS_TI1F_ED                     ((uint16_t)0X0040)
+#define TIM_TS_TI1FP1                      ((uint16_t)0X0050)
+#define TIM_TS_TI2FP2                      ((uint16_t)0X0060)
+#define TIM_TS_ETRF                        ((uint16_t)0X0070)
+#define IS_TIM_TRIGGER_SELECTION(SELECTION) (((SELECTION) == TIM_TS_ITR0) || \
+                                             ((SELECTION) == TIM_TS_ITR1) || \
+                                             ((SELECTION) == TIM_TS_ITR2) || \
+                                             ((SELECTION) == TIM_TS_ITR3) || \
+                                             ((SELECTION) == TIM_TS_TI1F_ED) || \
+                                             ((SELECTION) == TIM_TS_TI1FP1) || \
+                                             ((SELECTION) == TIM_TS_TI2FP2) || \
+                                             ((SELECTION) == TIM_TS_ETRF))
+#define IS_TIM_INTERNAL_TRIGGER_SELECTION(SELECTION) (((SELECTION) == TIM_TS_ITR0) || \
+                                                      ((SELECTION) == TIM_TS_ITR1) || \
+                                                      ((SELECTION) == TIM_TS_ITR2) || \
+                                                      ((SELECTION) == TIM_TS_ITR3))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_TIX_EXTERNAL_CLOCK_SOURCE
+  * @{
+  */
+
+#define TIM_TIXEXTERNALCLK1SOURCE_TI1      ((uint16_t)0X0050)
+#define TIM_TIXEXTERNALCLK1SOURCE_TI2      ((uint16_t)0X0060)
+#define TIM_TIXEXTERNALCLK1SOURCE_TI1ED    ((uint16_t)0X0040)
+#define IS_TIM_TIXCLK_SOURCE(SOURCE) (((SOURCE) == TIM_TIXEXTERNALCLK1SOURCE_TI1) || \
+                                      ((SOURCE) == TIM_TIXEXTERNALCLK1SOURCE_TI2) || \
+                                      ((SOURCE) == TIM_TIXEXTERNALCLK1SOURCE_TI1ED))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_EXTERNAL_TRIGGER_POLARITY
+  * @{
+  */
+#define TIM_EXTTRGPOLARITY_INVERTED        ((uint16_t)0X8000)
+#define TIM_EXTTRGPOLARITY_NONINVERTED     ((uint16_t)0X0000)
+#define IS_TIM_EXT_POLARITY(POLARITY) (((POLARITY) == TIM_EXTTRGPOLARITY_INVERTED) || \
+                                       ((POLARITY) == TIM_EXTTRGPOLARITY_NONINVERTED))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_PRESCALER_RELOAD_MODE
+  * @{
+  */
+
+#define TIM_PSCRELOADMODE_UPDATE           ((uint16_t)0X0000)
+#define TIM_PSCRELOADMODE_IMMEDIATE        ((uint16_t)0X0001)
+#define IS_TIM_PRESCALER_RELOAD(RELOAD) (((RELOAD) == TIM_PSCRELOADMODE_UPDATE) || \
+                                         ((RELOAD) == TIM_PSCRELOADMODE_IMMEDIATE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_FORCED_ACTION
+  * @{
+  */
+
+#define TIM_FORCEDACTION_ACTIVE            ((uint16_t)0X0050)
+#define TIM_FORCEDACTION_INACTIVE          ((uint16_t)0X0040)
+#define IS_TIM_FORCED_ACTION(ACTION) (((ACTION) == TIM_FORCEDACTION_ACTIVE) || \
+                                      ((ACTION) == TIM_FORCEDACTION_INACTIVE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_ENCODER_MODE
+  * @{
+  */
+
+#define TIM_ENCODERMODE_TI1                ((uint16_t)0X0001)
+#define TIM_ENCODERMODE_TI2                ((uint16_t)0X0002)
+#define TIM_ENCODERMODE_TI12               ((uint16_t)0X0003)
+#define IS_TIM_ENCODER_MODE(MODE) (((MODE) == TIM_ENCODERMODE_TI1) || \
+                                   ((MODE) == TIM_ENCODERMODE_TI2) || \
+                                   ((MODE) == TIM_ENCODERMODE_TI12))
+/**
+  * @}
+  */
+
+
+/** @DEFGROUP TIM_EVENT_SOURCE
+  * @{
+  */
+
+#define TIM_EVENTSOURCE_UPDATE             ((uint16_t)0X0001)
+#define TIM_EVENTSOURCE_CC1                ((uint16_t)0X0002)
+#define TIM_EVENTSOURCE_CC2                ((uint16_t)0X0004)
+#define TIM_EVENTSOURCE_CC3                ((uint16_t)0X0008)
+#define TIM_EVENTSOURCE_CC4                ((uint16_t)0X0010)
+#define TIM_EVENTSOURCE_COM                ((uint16_t)0X0020)
+#define TIM_EVENTSOURCE_TRIGGER            ((uint16_t)0X0040)
+#define TIM_EVENTSOURCE_BREAK              ((uint16_t)0X0080)
+#define IS_TIM_EVENT_SOURCE(SOURCE) ((((SOURCE) & (uint16_t)0XFF00) == 0X0000) && ((SOURCE) != 0X0000))
+
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_UPDATE_SOURCE
+  * @{
+  */
+
+#define TIM_UPDATESOURCE_GLOBAL            ((uint16_t)0X0000) /*!< SOURCE OF UPDATE IS THE COUNTER OVERFLOW/UNDERFLOW
+                                                                   OR THE SETTING OF UG BIT, OR AN UPDATE GENERATION
+                                                                   THROUGH THE SLAVE MODE CONTROLLER. */
+#define TIM_UPDATESOURCE_REGULAR           ((uint16_t)0X0001) /*!< SOURCE OF UPDATE IS COUNTER OVERFLOW/UNDERFLOW. */
+#define IS_TIM_UPDATE_SOURCE(SOURCE) (((SOURCE) == TIM_UPDATESOURCE_GLOBAL) || \
+                                      ((SOURCE) == TIM_UPDATESOURCE_REGULAR))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_OUTPUT_COMPARE_PRELOAD_STATE
+  * @{
+  */
+
+#define TIM_OCPRELOAD_ENABLE               ((uint16_t)0X0008)
+#define TIM_OCPRELOAD_DISABLE              ((uint16_t)0X0000)
+#define IS_TIM_OCPRELOAD_STATE(STATE) (((STATE) == TIM_OCPRELOAD_ENABLE) || \
+                                       ((STATE) == TIM_OCPRELOAD_DISABLE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_OUTPUT_COMPARE_FAST_STATE
+  * @{
+  */
+
+#define TIM_OCFAST_ENABLE                  ((uint16_t)0X0004)
+#define TIM_OCFAST_DISABLE                 ((uint16_t)0X0000)
+#define IS_TIM_OCFAST_STATE(STATE) (((STATE) == TIM_OCFAST_ENABLE) || \
+                                    ((STATE) == TIM_OCFAST_DISABLE))
+
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_OUTPUT_COMPARE_CLEAR_STATE
+  * @{
+  */
+
+#define TIM_OCCLEAR_ENABLE                 ((uint16_t)0X0080)
+#define TIM_OCCLEAR_DISABLE                ((uint16_t)0X0000)
+#define IS_TIM_OCCLEAR_STATE(STATE) (((STATE) == TIM_OCCLEAR_ENABLE) || \
+                                     ((STATE) == TIM_OCCLEAR_DISABLE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_TRIGGER_OUTPUT_SOURCE
+  * @{
+  */
+
+#define TIM_TRGOSOURCE_RESET               ((uint16_t)0X0000)
+#define TIM_TRGOSOURCE_ENABLE              ((uint16_t)0X0010)
+#define TIM_TRGOSOURCE_UPDATE              ((uint16_t)0X0020)
+#define TIM_TRGOSOURCE_OC1                 ((uint16_t)0X0030)
+#define TIM_TRGOSOURCE_OC1REF              ((uint16_t)0X0040)
+#define TIM_TRGOSOURCE_OC2REF              ((uint16_t)0X0050)
+#define TIM_TRGOSOURCE_OC3REF              ((uint16_t)0X0060)
+#define TIM_TRGOSOURCE_OC4REF              ((uint16_t)0X0070)
+#define IS_TIM_TRGO_SOURCE(SOURCE) (((SOURCE) == TIM_TRGOSOURCE_RESET) || \
+                                    ((SOURCE) == TIM_TRGOSOURCE_ENABLE) || \
+                                    ((SOURCE) == TIM_TRGOSOURCE_UPDATE) || \
+                                    ((SOURCE) == TIM_TRGOSOURCE_OC1) || \
+                                    ((SOURCE) == TIM_TRGOSOURCE_OC1REF) || \
+                                    ((SOURCE) == TIM_TRGOSOURCE_OC2REF) || \
+                                    ((SOURCE) == TIM_TRGOSOURCE_OC3REF) || \
+                                    ((SOURCE) == TIM_TRGOSOURCE_OC4REF))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_SLAVE_MODE
+  * @{
+  */
+
+#define TIM_SLAVEMODE_RESET                ((uint16_t)0X0004)
+#define TIM_SLAVEMODE_GATED                ((uint16_t)0X0005)
+#define TIM_SLAVEMODE_TRIGGER              ((uint16_t)0X0006)
+#define TIM_SLAVEMODE_EXTERNAL1            ((uint16_t)0X0007)
+#define IS_TIM_SLAVE_MODE(MODE) (((MODE) == TIM_SLAVEMODE_RESET) || \
+                                 ((MODE) == TIM_SLAVEMODE_GATED) || \
+                                 ((MODE) == TIM_SLAVEMODE_TRIGGER) || \
+                                 ((MODE) == TIM_SLAVEMODE_EXTERNAL1))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_MASTER_SLAVE_MODE
+  * @{
+  */
+
+#define TIM_MASTERSLAVEMODE_ENABLE         ((uint16_t)0X0080)
+#define TIM_MASTERSLAVEMODE_DISABLE        ((uint16_t)0X0000)
+#define IS_TIM_MSM_STATE(STATE) (((STATE) == TIM_MASTERSLAVEMODE_ENABLE) || \
+                                 ((STATE) == TIM_MASTERSLAVEMODE_DISABLE))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_FLAGS
+  * @{
+  */
+
+#define TIM_FLAG_UPDATE                    ((uint16_t)0X0001)
+#define TIM_FLAG_CC1                       ((uint16_t)0X0002)
+#define TIM_FLAG_CC2                       ((uint16_t)0X0004)
+#define TIM_FLAG_CC3                       ((uint16_t)0X0008)
+#define TIM_FLAG_CC4                       ((uint16_t)0X0010)
+#define TIM_FLAG_COM                       ((uint16_t)0X0020)
+#define TIM_FLAG_TRIGGER                   ((uint16_t)0X0040)
+#define TIM_FLAG_BREAK                     ((uint16_t)0X0080)
+#define TIM_FLAG_CC1OF                     ((uint16_t)0X0200)
+#define TIM_FLAG_CC2OF                     ((uint16_t)0X0400)
+#define TIM_FLAG_CC3OF                     ((uint16_t)0X0800)
+#define TIM_FLAG_CC4OF                     ((uint16_t)0X1000)
+#define IS_TIM_GET_FLAG(FLAG) (((FLAG) == TIM_FLAG_UPDATE) || \
+                               ((FLAG) == TIM_FLAG_CC1) || \
+                               ((FLAG) == TIM_FLAG_CC2) || \
+                               ((FLAG) == TIM_FLAG_CC3) || \
+                               ((FLAG) == TIM_FLAG_CC4) || \
+                               ((FLAG) == TIM_FLAG_COM) || \
+                               ((FLAG) == TIM_FLAG_TRIGGER) || \
+                               ((FLAG) == TIM_FLAG_BREAK) || \
+                               ((FLAG) == TIM_FLAG_CC1OF) || \
+                               ((FLAG) == TIM_FLAG_CC2OF) || \
+                               ((FLAG) == TIM_FLAG_CC3OF) || \
+                               ((FLAG) == TIM_FLAG_CC4OF))
+
+
+#define IS_TIM_CLEAR_FLAG(TIM_FLAG) ((((TIM_FLAG) & (uint16_t)0XE100) == 0X0000) && ((TIM_FLAG) != 0X0000))
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_INPUT_CAPTURE_FILER_VALUE
+  * @{
+  */
+
+#define IS_TIM_IC_FILTER(ICFILTER) ((ICFILTER) <= 0XF)
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_EXTERNAL_TRIGGER_FILTER
+  * @{
+  */
+
+#define IS_TIM_EXT_FILTER(EXTFILTER) ((EXTFILTER) <= 0XF)
+/**
+  * @}
+  */
+
+/** @DEFGROUP TIM_LEGACY
+  * @{
+  */
+
+#define TIM_DMABURSTLENGTH_1BYTE           TIM_DMABURSTLENGTH_1TRANSFER
+#define TIM_DMABURSTLENGTH_2BYTES          TIM_DMABURSTLENGTH_2TRANSFERS
+#define TIM_DMABURSTLENGTH_3BYTES          TIM_DMABURSTLENGTH_3TRANSFERS
+#define TIM_DMABURSTLENGTH_4BYTES          TIM_DMABURSTLENGTH_4TRANSFERS
+#define TIM_DMABURSTLENGTH_5BYTES          TIM_DMABURSTLENGTH_5TRANSFERS
+#define TIM_DMABURSTLENGTH_6BYTES          TIM_DMABURSTLENGTH_6TRANSFERS
+#define TIM_DMABURSTLENGTH_7BYTES          TIM_DMABURSTLENGTH_7TRANSFERS
+#define TIM_DMABURSTLENGTH_8BYTES          TIM_DMABURSTLENGTH_8TRANSFERS
+#define TIM_DMABURSTLENGTH_9BYTES          TIM_DMABURSTLENGTH_9TRANSFERS
+#define TIM_DMABURSTLENGTH_10BYTES         TIM_DMABURSTLENGTH_10TRANSFERS
+#define TIM_DMABURSTLENGTH_11BYTES         TIM_DMABURSTLENGTH_11TRANSFERS
+#define TIM_DMABURSTLENGTH_12BYTES         TIM_DMABURSTLENGTH_12TRANSFERS
+#define TIM_DMABURSTLENGTH_13BYTES         TIM_DMABURSTLENGTH_13TRANSFERS
+#define TIM_DMABURSTLENGTH_14BYTES         TIM_DMABURSTLENGTH_14TRANSFERS
+#define TIM_DMABURSTLENGTH_15BYTES         TIM_DMABURSTLENGTH_15TRANSFERS
+#define TIM_DMABURSTLENGTH_16BYTES         TIM_DMABURSTLENGTH_16TRANSFERS
+#define TIM_DMABURSTLENGTH_17BYTES         TIM_DMABURSTLENGTH_17TRANSFERS
+#define TIM_DMABURSTLENGTH_18BYTES         TIM_DMABURSTLENGTH_18TRANSFERS
+
+/** @defgroup tim_exported_types
+  * @{
+  */
+
+/**
+  * @brief  tim time base init structure definition
+  * @note   this structure is used with all TIMX except for tim6 and tim7.
+  */
+typedef struct
+{
+  __IO uint32_t cr1;
+//  uint16_t  RESERVED0;
+  __IO uint32_t cr2;
+//  uint16_t  RESERVED1;
+  __IO uint32_t smcr;
+//  uint16_t  RESERVED2;
+  __IO uint32_t dier;
+//  uint16_t  RESERVED3;
+  __IO uint32_t sr;
+//  uint16_t  RESERVED4;
+  __IO uint32_t egr;
+//  uint16_t  RESERVED5;
+  __IO uint32_t ccmr1;
+//  uint16_t  RESERVED6;
+  __IO uint32_t ccmr2;
+//  uint16_t  RESERVED7;
+  __IO uint32_t ccer;
+//  uint16_t  RESERVED8;
+  __IO uint32_t cnt;
+//  uint16_t  RESERVED9;
+  __IO uint32_t psc;
+//  uint16_t  RESERVED10;
+  __IO uint32_t arr;
+//  uint16_t  RESERVED11;
+  __IO uint32_t rcr;
+//  uint16_t  RESERVED12;
+  __IO uint32_t ccr1;
+//  uint16_t  RESERVED13;
+  __IO uint32_t ccr2;
+//  uint16_t  RESERVED14;
+  __IO uint32_t ccr3;
+//  uint16_t  RESERVED15;
+  __IO uint32_t ccr4;
+//  uint16_t  RESERVED16;
+  __IO uint32_t bdtr;
+//  uint16_t  RESERVED17;
+  __IO uint32_t sarad;
+//  __IO uint32_t DCR;
+////  uint16_t  RESERVED18;
+//  __IO uint32_t DMAR;
+////  uint16_t  RESERVED19;
+} tim_typedef;
+
+typedef struct
+{
+  uint16_t tim_prescaler;         /*!< specifies the prescaler value used to divide the tim clock.
+                                       this parameter can be a number between 0x0000 and 0xffff */
+
+  uint16_t tim_countermode;       /*!< specifies the counter mode.
+                                       this parameter can be a value of @ref tim_counter_mode */
+
+  uint16_t tim_period;            /*!< specifies the period value to be loaded into the active
+                                       auto-reload register at the next update event.
+                                       this parameter must be a number between 0x0000 and 0xffff.  */
+
+  uint16_t tim_clockdivision;     /*!< specifies the clock division.
+                                      this parameter can be a value of @ref tim_clock_division_ckd */
+
+  uint8_t tim_repetitioncounter;  /*!< specifies the repetition counter value. each time the rcr downcounter
+                                       reaches zero, an update event is generated and counting restarts
+                                       from the rcr value (n).
+                                       this means in pwm mode that (n+1) corresponds to:
+                                          - the number of pwm periods in edge-aligned mode
+                                          - the number of half pwm period in center-aligned mode
+                                       this parameter must be a number between 0x00 and 0xff.
+                                       @note this parameter is valid only for tim1 and tim8. */
+} tim_timebaseinittypedef;
+
+/**
+  * @brief  tim output compare init structure definition
+  */
+
+typedef struct
+{
+  uint16_t tim_ocmode;        /*!< specifies the tim mode.
+                                   this parameter can be a value of @ref tim_output_compare_and_pwm_modes */
+
+  uint16_t tim_outputstate;   /*!< specifies the tim output compare state.
+                                   this parameter can be a value of @ref tim_output_compare_state */
+
+  uint16_t tim_outputnstate;  /*!< specifies the tim complementary output compare state.
+                                   this parameter can be a value of @ref tim_output_compare_n_state
+                                   @note this parameter is valid only for tim1 and tim8. */
+
+  uint16_t tim_pulse;         /*!< specifies the pulse value to be loaded into the capture compare register.
+                                   this parameter can be a number between 0x0000 and 0xffff */
+
+  uint16_t tim_ocpolarity;    /*!< specifies the output polarity.
+                                   this parameter can be a value of @ref tim_output_compare_polarity */
+
+  uint16_t tim_ocnpolarity;   /*!< specifies the complementary output polarity.
+                                   this parameter can be a value of @ref tim_output_compare_n_polarity
+                                   @note this parameter is valid only for tim1 and tim8. */
+
+  uint16_t tim_ocidlestate;   /*!< specifies the tim output compare pin state during idle state.
+                                   this parameter can be a value of @ref tim_output_compare_idle_state
+                                   @note this parameter is valid only for tim1 and tim8. */
+
+  uint16_t tim_ocnidlestate;  /*!< specifies the tim output compare pin state during idle state.
+                                   this parameter can be a value of @ref tim_output_compare_n_idle_state
+                                   @note this parameter is valid only for tim1 and tim8. */
+} tim_ocinittypedef;
+
+/**
+  * @brief  tim input capture init structure definition
+  */
+
+typedef struct
+{
+
+  uint16_t tim_channel;      /*!< specifies the tim channel.
+                                  this parameter can be a value of @ref tim_channel */
+
+  uint16_t tim_icpolarity;   /*!< specifies the active edge of the input signal.
+                                  this parameter can be a value of @ref tim_input_capture_polarity */
+
+  uint16_t tim_icselection;  /*!< specifies the input.
+                                  this parameter can be a value of @ref tim_input_capture_selection */
+
+  uint16_t tim_icprescaler;  /*!< specifies the input capture prescaler.
+                                  this parameter can be a value of @ref tim_input_capture_prescaler */
+
+  uint16_t tim_icfilter;     /*!< specifies the input capture filter.
+                                  this parameter can be a number between 0x0 and 0xf */
+} tim_icinittypedef;
+
+/**
+  * @brief  bdtr structure definition
+  * @note   this structure is used only with tim1 and tim8.
+  */
+
+typedef struct
+{
+
+  uint16_t tim_ossrstate;        /*!< specifies the off-state selection used in run mode.
+                                      this parameter can be a value of @ref ossr_off_state_selection_for_run_mode_state */
+
+  uint16_t tim_ossistate;        /*!< specifies the off-state used in idle state.
+                                      this parameter can be a value of @ref ossi_off_state_selection_for_idle_mode_state */
+
+  uint16_t tim_locklevel;        /*!< specifies the lock level parameters.
+                                      this parameter can be a value of @ref lock_level */
+
+  uint16_t tim_deadtime;         /*!< specifies the delay time between the switching-off and the
+                                      switching-on of the outputs.
+                                      this parameter can be a number between 0x00 and 0xff  */
+
+  uint16_t tim_break;            /*!< specifies whether the tim break input is enabled or not.
+                                      this parameter can be a value of @ref break_input_enable_disable */
+
+  uint16_t tim_breakpolarity;    /*!< specifies the tim break input pin polarity.
+                                      this parameter can be a value of @ref break_polarity */
+
+  uint16_t tim_automaticoutput;  /*!< specifies whether the tim automatic output feature is enabled or not.
+                                      this parameter can be a value of @ref tim_aoe_bit_set_reset */
+} tim_bdtrinittypedef;
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup tim_exported_macros
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup tim_exported_functions
+  * @{
+  */
+
+void tim_timebaseinit(tim_typedef* TIMX, tim_timebaseinittypedef* tim_timebaseinitstruct);
+void tim_oc1init(tim_typedef* TIMX, tim_ocinittypedef* tim_ocinitstruct);
+void tim_oc2init(tim_typedef* TIMX, tim_ocinittypedef* tim_ocinitstruct);
+void tim_oc3init(tim_typedef* TIMX, tim_ocinittypedef* tim_ocinitstruct);
+void tim_oc4init(tim_typedef* TIMX, tim_ocinittypedef* tim_ocinitstruct);
+void tim_bdtrconfig(tim_typedef* TIMX, tim_bdtrinittypedef *tim_bdtrinitstruct);
+void tim_cmd(tim_typedef* TIMX, FUNCTIONAL_STATE newstate);
+void tim_ctrlpwmoutputs(tim_typedef* TIMX, FUNCTIONAL_STATE newstate);
+void tim_itconfig(tim_typedef* TIMX, uint16_t tim_it, FUNCTIONAL_STATE newstate);
+void tim_generateevent(tim_typedef* TIMX, uint16_t tim_eventsource);
+void tim_etrclockmode2config(tim_typedef* TIMX, uint16_t tim_exttrgprescaler,uint16_t tim_exttrgpolarity, uint16_t exttrgfilter);
+void tim_etrconfig(tim_typedef* TIMX, uint16_t tim_exttrgprescaler, uint16_t tim_exttrgpolarity,uint16_t exttrgfilter);
+void tim_selectinputtrigger(tim_typedef* TIMX, uint16_t tim_inputtriggersource);
+void tim_arrpreloadconfig(tim_typedef* TIMX, FUNCTIONAL_STATE newstate);
+void tim_ccpreloadcontrol(tim_typedef* TIMX, FUNCTIONAL_STATE newstate);
+void tim_oc1preloadconfig(tim_typedef* TIMX, uint16_t tim_ocpreload);
+void tim_oc2preloadconfig(tim_typedef* TIMX, uint16_t tim_ocpreload);
+void tim_oc3preloadconfig(tim_typedef* TIMX, uint16_t tim_ocpreload);
+void tim_oc4preloadconfig(tim_typedef* TIMX, uint16_t tim_ocpreload);
+void tim_oc1npolarityconfig(tim_typedef* TIMX, uint16_t tim_ocnpolarity);
+void tim_oc2npolarityconfig(tim_typedef* TIMX, uint16_t tim_ocnpolarity);
+void tim_oc3npolarityconfig(tim_typedef* TIMX, uint16_t tim_ocnpolarity);
+void tim_ccxcmd(tim_typedef* TIMX, uint16_t tim_channel, uint16_t tim_ccx);
+void tim_ccxncmd(tim_typedef* TIMX, uint16_t tim_channel, uint16_t tim_ccxn);
+void tim_selectocxm(tim_typedef* TIMX, uint16_t tim_channel, uint16_t tim_ocmode);
+void tim_selectonepulsemode(tim_typedef* TIMX, uint16_t tim_opmode);
+void tim_setcompare1(tim_typedef* TIMX, uint16_t compare1);
+void tim_setcompare2(tim_typedef* TIMX, uint16_t compare2);
+void tim_setcompare3(tim_typedef* TIMX, uint16_t compare3);
+void tim_setcompare4(tim_typedef* TIMX, uint16_t compare4);
+void tim_setic1prescaler(tim_typedef* TIMX, uint16_t tim_icpsc);
+void tim_setic2prescaler(tim_typedef* TIMX, uint16_t tim_icpsc);
+void tim_setic3prescaler(tim_typedef* TIMX, uint16_t tim_icpsc);
+void tim_setic4prescaler(tim_typedef* TIMX, uint16_t tim_icpsc);
+FLAG_STATE tim_getflagstatus(tim_typedef* TIMX, uint16_t tim_flag);
+void tim_clearflag(tim_typedef* TIMX, uint16_t tim_flag);
+IT_STATE tim_getitstatus(tim_typedef* TIMX, uint16_t tim_it);
+void tim_clearitpendingbit(tim_typedef* TIMX, uint16_t tim_it);
+void tim_etrclockmode1config(tim_typedef* TIMX, uint16_t tim_exttrgprescaler, uint16_t tim_exttrgpolarity,uint16_t exttrgfilter);
+void tim_prescalerconfig(tim_typedef* TIMX, uint16_t prescaler, uint16_t tim_pscreloadmode);
+void tim_countermodeconfig(tim_typedef* TIMX, uint16_t tim_countermode);
+void tim_encoderinterfaceconfig(tim_typedef* TIMX, uint16_t tim_encodermode,uint16_t tim_ic1polarity, uint16_t tim_ic2polarity);
+void tim_forcedoc1config(tim_typedef* TIMX, uint16_t tim_forcedaction);
+void tim_forcedoc2config(tim_typedef* TIMX, uint16_t tim_forcedaction);
+void tim_forcedoc3config(tim_typedef* TIMX, uint16_t tim_forcedaction);
+void tim_forcedoc4config(tim_typedef* TIMX, uint16_t tim_forcedaction);
+void tim_selectcom(tim_typedef* TIMX, FUNCTIONAL_STATE newstate);
+void tim_internalclockconfig(tim_typedef* TIMX);
+void tim_clearoc1ref(tim_typedef* TIMX, uint16_t tim_occlear);
+void tim_clearoc2ref(tim_typedef* TIMX, uint16_t tim_occlear);
+void tim_clearoc3ref(tim_typedef* TIMX, uint16_t tim_occlear);
+void tim_clearoc4ref(tim_typedef* TIMX, uint16_t tim_occlear);
+void tim_oc1polarityconfig(tim_typedef* TIMX, uint16_t tim_ocpolarity);
+void tim_oc2polarityconfig(tim_typedef* TIMX, uint16_t tim_ocpolarity);
+void tim_oc3polarityconfig(tim_typedef* TIMX, uint16_t tim_ocpolarity);
+void tim_oc4polarityconfig(tim_typedef* TIMX, uint16_t tim_ocpolarity);
+void tim_updatedisableconfig(tim_typedef* TIMX, FUNCTIONAL_STATE newstate);
+void tim_updaterequestconfig(tim_typedef* TIMX, uint16_t tim_updatesource);
+void tim_selectoutputtrigger(tim_typedef* TIMX, uint16_t tim_trgosource);
+void tim_selectslavemode(tim_typedef* TIMX, uint16_t tim_slavemode);
+void tim_setcounter(tim_typedef* TIMX, uint16_t counter);
+void tim_setautoreload(tim_typedef* TIMX, uint16_t autoreload);
+void tim_setclockdivision(tim_typedef* TIMX, uint16_t tim_ckd);
+uint16_t tim_getcounter(tim_typedef* TIMX);
+uint16_t tim_getprescaler(tim_typedef* TIMX);
+void tim_timebasestructinit(tim_timebaseinittypedef* tim_timebaseinitstruct);
+void tim_ocstructinit(tim_ocinittypedef* tim_ocinitstruct);
+void tim_trgosaradc_config(tim_typedef* TIMX,FUNCTIONAL_STATE newstate);
+void tim_bdtrstructinit(tim_bdtrinittypedef* tim_bdtrinitstruct);
+void tim_itrxexternalclockconfig(tim_typedef* TIMX, uint16_t tim_inputtriggersource);
+void tim_tixexternalclockconfig(tim_typedef* TIMX, uint16_t tim_tixexternalclksource,uint16_t tim_icpolarity, uint16_t icfilter);
+
+
+
+ /* 预留 */
+//void tim_deinit(tim_typedef* TIMX);
+//void tim_icinit(tim_typedef* TIMX, tim_icinittypedef* tim_icinitstruct);
+//void tim_pwmiconfig(tim_typedef* TIMX, tim_icinittypedef* tim_icinitstruct);
+//void tim_icstructinit(tim_icinittypedef* tim_icinitstruct);
+//void tim_dmaconfig(tim_typedef* TIMX, uint16_t tim_dmabase, uint16_t tim_dmaburstlength);
+//void tim_selectccdma(tim_typedef* TIMX, FUNCTIONAL_STATE newstate);
+//void tim_oc1fastconfig(tim_typedef* TIMX, uint16_t tim_ocfast);
+//void tim_oc2fastconfig(tim_typedef* TIMX, uint16_t tim_ocfast);
+//void tim_oc3fastconfig(tim_typedef* TIMX, uint16_t tim_ocfast);
+//void tim_oc4fastconfig(tim_typedef* TIMX, uint16_t tim_ocfast);
+//void tim_selecthallsensor(tim_typedef* TIMX, FUNCTIONAL_STATE newstate);
+//void tim_selectmasterslavemode(tim_typedef* TIMX, uint16_t tim_masterslavemode);
+//void tim_dmacmd(tim_typedef* TIMX, uint16_t tim_dmasource, FUNCTIONAL_STATE newstate);
+//uint16_t tim_getcapture1(tim_typedef* TIMX);
+//uint16_t tim_getcapture2(tim_typedef* TIMX);
+//uint16_t tim_getcapture3(tim_typedef* TIMX);
+//uint16_t tim_getcapture4(tim_typedef* TIMX);
+
+/*  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __DRIVER_ADV_TIMER_H__
+
+
+
+

+ 406 - 0
driver/driver_charge.c

@@ -0,0 +1,406 @@
+/*
+ * @File name    : driver_charge.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-06-20
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the Charge module.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_charge.h"
+
+
+static void charge_DC_online_handle(void);
+static bool charge_detect_off_condition(void);
+
+// charging process parameter struct
+static struct charge_status_def{
+    u8 sta;
+    u8 mode;
+    u8 cutoff_vol;
+    u8 cutoff_cur;
+    u8 const_cur;
+    u8 trickle_en;
+    u8 trickle_cur;
+} charge_status;
+
+// charging process control struct
+static struct charge_ctrl_def{
+    u8 dc_insert;
+    u8 dc_in_debounce_cnt;
+    u8 reach_trick_curr_state_condition_debounce_cnt;
+    u8 reach_const_curr_state_condition_debounce_cnt;
+    u8 reach_cutoff_curr_debounce_cnt;
+    u8 reach_cutoff_vol_debounce_cnt;
+    u8 reach_cutoff_debounce_cnt;
+    u16 cutoff_vol_2_stop_time;
+    u16 cutoff_vol_2_stop_time_cnt;
+    u32 vddio_tmp;
+} charge_ctrl;
+
+/**
+  * @brief  Initializes the charge according to the specified
+  *         parameters in the charge_init_struct.
+  * @param  charge_init_struct: pointer to a charge_init_typedef structure that
+  *         contains the configuration information for the charge register.
+  * @retval None
+  */
+void charge_init(charge_init_typedef *charge_init_struct)
+{
+    charge_init_struct->cutoff_curr = charge_cutoff_curr_trim(charge_init_struct->cutoff_curr >> 11) << 11;
+    charge_init_struct->const_curr = charge_const_curr_trim(charge_init_struct->const_curr);
+
+    RTCCON8 &= ~((uint32_t)(0x03 << 8));
+    RTCCON8 |= (uint32_t)(charge_init_struct->cutoff_volt);
+
+    RTCCON7 &= ~((uint32_t)(0x0f << 11));
+    RTCCON7 |= (uint32_t)(charge_init_struct->cutoff_curr);
+
+    RTCCON &= ~((uint32_t)(0x01 << 6));
+    RTCCON |= (uint32_t)charge_init_struct->dcin_reset;
+
+    // set VUSB leakage current.
+    RTCCON8 &= ~(0x07 << 16);
+    RTCCON8 |= (0x02 << 16);
+
+    memset(&charge_status, 0, sizeof(struct charge_status_def));
+    memset(&charge_ctrl, 0, sizeof(struct charge_ctrl_def));
+
+    // storage the configure value of charge.
+    charge_status.trickle_en = charge_init_struct->trick_curr_en;
+    charge_status.trickle_cur = charge_init_struct->trick_curr;
+    charge_status.const_cur = charge_init_struct->const_curr;
+    charge_status.mode = charge_init_struct->mode;
+
+    // set the charge initial status to CHARGE_STA_OFF.
+    charge_status.sta = CHARGE_STA_OFF;
+}
+
+/**
+ * @brief  De-initialize the specified uart peripheral.
+ * @retval None
+ */
+void charge_deinit(void)
+{
+    RTCCON8 &= ~(0x01 << 6);
+    RTCCON8 |= (0x01 << 1);
+    charge_status.sta = CHARGE_STA_UNINIT;
+}
+
+/**
+  * @brief  process state switch during charging, this func should be called continuously
+  *         during charging.
+  * @param  None.
+  * @retval None
+  */
+AT(.text.app.proc.charge)
+void charge_process(void)
+{
+    // exit if charge uninitial.
+    if (charge_status.sta == CHARGE_STA_UNINIT) {
+        return;
+    }
+
+    // detect whether DC insert
+    if ((charge_detect_dc()) != charge_ctrl.dc_insert) {
+        charge_ctrl.dc_in_debounce_cnt++;
+        if (charge_ctrl.dc_in_debounce_cnt > 5) {
+            charge_ctrl.dc_insert = charge_detect_dc();
+            charge_ctrl.dc_in_debounce_cnt = 0;
+        }
+    } else {
+        charge_ctrl.dc_in_debounce_cnt = 0;
+    }
+
+    if (charge_ctrl.dc_insert == CHARGE_DC_STATUS_ONLINE) {
+        charge_DC_online_handle();
+    } else {
+        if (charge_status.sta != CHARGE_STA_OFF) {
+            charge_status_update(CHARGE_STA_OFF);
+        }
+    }
+}
+
+/**
+  * @brief  Process event when VUSB insert.
+  * @param  None.
+  * @retval None
+  */
+static void charge_DC_online_handle(void)
+{
+    // if the charging is not begin.
+    if (charge_status.sta == CHARGE_STA_OFF) {
+        if (charge_status.trickle_en == DISABLE || (PWRCON1 & (1 << 29))) {         // trickle disable or battery higher then trickle voltage.
+            if (charge_ctrl.reach_const_curr_state_condition_debounce_cnt > 10) {
+                charge_ctrl.reach_const_curr_state_condition_debounce_cnt = 0;
+                charge_status_update(CHARGE_STA_ON_CON_CURR);                       // constant current charging.
+            } else {
+                charge_ctrl.reach_const_curr_state_condition_debounce_cnt++;
+            }
+            charge_ctrl.reach_trick_curr_state_condition_debounce_cnt = 0;
+        } else {
+            if (charge_ctrl.reach_trick_curr_state_condition_debounce_cnt > 10) {
+                charge_ctrl.reach_trick_curr_state_condition_debounce_cnt = 0;
+                charge_status_update(CHARGE_STA_ON_TRICKLE);                        // trickle current charging.
+            } else {
+                charge_ctrl.reach_trick_curr_state_condition_debounce_cnt++;
+            }
+            charge_ctrl.reach_const_curr_state_condition_debounce_cnt = 0;
+        }
+    // if the charging is begin.
+    } else if (charge_status.sta == CHARGE_STA_ON_TRICKLE) {
+        if (PWRCON1 & (1 << 29)) {
+            charge_ctrl.reach_const_curr_state_condition_debounce_cnt++;
+        } else {
+            charge_ctrl.reach_const_curr_state_condition_debounce_cnt = 0;
+        }
+
+        if (charge_ctrl.reach_const_curr_state_condition_debounce_cnt > 10) {
+            charge_status_update(CHARGE_STA_ON_CON_CURR);
+        }
+    // if the charging at the state[con_curr, con_vol], detect stop condition.
+    } else if (charge_status.sta > CHARGE_STA_ON_TRICKLE) {
+        if (charge_detect_off_condition()) {
+            charge_status_update(CHARGE_STA_OFF_BUT_DC_IN);
+        }
+    }
+}
+
+/**
+  * @brief  Update the charging status if needed, and perform relevant configuration.
+  * @param  status: the charging status that need to update.
+  *         this parameter can be one of the following values:
+  *             @arg CHARGE_STA_UNINIT: charge parameter uninitialized flag.
+  *             @arg CHARGE_STA_OFF: charge off flag.
+  *             @arg CHARGE_STA_OFF_BUT_DC_IN: charge off but VUSB still insert flag.
+  *             @arg CHARGE_STA_ON_TRICKLE: charge on trickle stage flag.
+  *             @arg CHARGE_STA_ON_CON_CURR: charge on const current stage flag.
+  *             @arg CHARGE_STA_ON_CON_VOL: charge on const voltage stage flag.
+  * @retval None
+  */
+void charge_status_update(u8 status)
+{
+    u32 reg_tmp;
+
+    if (status == CHARGE_STA_OFF) {
+        // Restore VDDIO Trim
+        PWRCON0 = (PWRCON0 & ~(0x0f<<5)) | (charge_ctrl.vddio_tmp << 5);
+
+        // VUSB to VDDIO LDO Disable
+        RTCCON8 &= ~(1 << 0);
+
+        // Stop Charge
+		RTCCON8 &= ~(1 << 6);
+        RTCCON8 |= (1 << 1);
+    } else if (status == CHARGE_STA_OFF_BUT_DC_IN) {
+        if (charge_status.mode == CHARGE_MODE_FULL_DISCONNECT) {
+            RTCCON8 |= (1 << 1);
+        }
+    } else if (status == CHARGE_STA_ON_TRICKLE || status == CHARGE_STA_ON_CON_CURR) {
+        reg_tmp = RTCCON7;
+
+        if ((charge_status.sta != CHARGE_STA_ON_TRICKLE) && (charge_status.sta != CHARGE_STA_ON_CON_CURR)) {
+            charge_ctrl.vddio_tmp = (PWRCON0 >> 5) & 0x0f;
+        }
+
+        // Enable VUSB to VDDIO LDO
+        RTCCON8 |= (1 << 0);
+
+        if (status == CHARGE_STA_ON_TRICKLE) {
+            // Config VUSB to VDDIO LDO Voltage,Ensure VUSB_VDDIO > VBAT_VDDIO
+            // 2.6:0.1:3.3  0x02 means 2.8V
+            RTCCON8 = (RTCCON8 & ~(0x07<<20)) | (2 << 20);
+
+            PWRCON0 &= ~(0x0f << 5);        //VBAT_VDDIO 2.4V
+
+            reg_tmp &= ~(uint32_t)0x3f;
+            reg_tmp |= charge_status.trickle_cur & 0x3f;
+        } else {
+            // Config VUSB to VDDIO LDO Voltage,Ensure VUSB_VDDIO > VBAT_VDDIO
+            // 2.6:0.1:3.3  0x05 means 3.1V
+            RTCCON8 = (RTCCON8 & ~(0x07<<20)) | (5 << 20);
+
+            PWRCON0 = (PWRCON0 & ~(0x0f<<5)) | (4 << 5);    //VBAT_VDDIO 2.8V
+
+            reg_tmp &= ~(uint32_t)0x3f;
+            reg_tmp |= charge_status.const_cur & 0x3f;
+        }
+        charge_ctrl.reach_cutoff_curr_debounce_cnt = 0;
+        charge_ctrl.reach_cutoff_vol_debounce_cnt = 0;
+
+        RTCCON7 = reg_tmp;
+        RTCCON8 |= (0x01 << 6);
+        RTCCON8 &= ~(0x01 << 1);
+    } else if (status == CHARGE_STA_ON_CON_VOL) {
+		RTCCON8 |= (0x01 << 6);
+        RTCCON8 &= ~(0x01 << 1);
+    }
+
+    charge_status.sta = status;
+}
+
+/**
+  * @brief  detect charge off condition and enter const voltage stage condition.
+  * @param  None.
+  * @retval true or false that can stop charge.
+  */
+static bool charge_detect_off_condition(void)
+{
+    if (charge_ctrl.reach_cutoff_debounce_cnt && (charge_status.sta != CHARGE_STA_ON_CON_VOL)) {
+        charge_ctrl.reach_cutoff_debounce_cnt--;
+        // judge if the charging current lower then setting val.
+        if (PWRCON1 & (1 << 30)) { //I
+            charge_ctrl.reach_cutoff_curr_debounce_cnt++;
+        }
+        // judge if the charging voltage higher then setting val.
+        if (PWRCON1 & (1 << 28)) { //V
+            charge_ctrl.reach_cutoff_vol_debounce_cnt++;
+        }
+    }
+
+    if (charge_ctrl.reach_cutoff_curr_debounce_cnt >= 98) {
+        return true;
+    } else if (charge_ctrl.reach_cutoff_vol_debounce_cnt >= 98) {
+        if (charge_status.sta != CHARGE_STA_ON_CON_VOL) {
+            charge_status_update(CHARGE_STA_ON_CON_VOL);
+            charge_ctrl.reach_cutoff_debounce_cnt = 0;
+        }
+
+        if (charge_ctrl.reach_cutoff_debounce_cnt == 0) {
+            charge_ctrl.reach_cutoff_debounce_cnt = 100;
+            charge_ctrl.reach_cutoff_curr_debounce_cnt = 0;
+        } else {
+            charge_ctrl.reach_cutoff_debounce_cnt--;
+            if (PWRCON1 & (1 << 30)) {            //I
+                charge_ctrl.reach_cutoff_curr_debounce_cnt++;
+            }
+        }
+
+        if (charge_ctrl.cutoff_vol_2_stop_time) {
+            charge_ctrl.cutoff_vol_2_stop_time_cnt++;
+            if (charge_ctrl.cutoff_vol_2_stop_time_cnt > charge_ctrl.cutoff_vol_2_stop_time) {
+                charge_ctrl.cutoff_vol_2_stop_time_cnt = 0;
+                return true;
+            }
+        }
+    } else {
+        if (charge_ctrl.reach_cutoff_debounce_cnt == 0) {
+            charge_ctrl.reach_cutoff_debounce_cnt = 100;
+            charge_ctrl.reach_cutoff_curr_debounce_cnt = 0;
+            charge_ctrl.reach_cutoff_vol_debounce_cnt = 0;
+        }
+    }
+
+    return false;
+}
+
+/**
+  * @brief  Update the charging status if needed, and perform relevant configuration.
+  * @param  None.
+  * @retval the status of charge stage. the value will be one in the CHARGE_STATUS_TYPEDEF.
+  */
+AT(.com_periph.charge)
+u8 charge_get_status(void) {
+    return charge_status.sta;
+}
+
+/**
+  * @brief  select the event to do when charge is finish.
+  * @param  mode: charge mode.
+  *         this parameter can be one of the following values:
+  *             @arg CHARGE_MODE_FULL_KEEP: keep VUSB connect when charge finish.
+  *             @arg CHARGE_MODE_FULL_DISCONNECT: disconnect VUSB when charge finish.
+  * @retval None
+  */
+void charge_change_mode(u8 mode)
+{
+    if ((mode == CHARGE_MODE_FULL_DISCONNECT) || (mode == CHARGE_MODE_FULL_KEEP)) {
+        charge_status.mode = mode;
+    }
+}
+
+/**
+  * @brief  Update the charging mode if needed, and perform relevant configuration.
+  * @param  None.
+  * @retval mode of charge stage. the value will be one in the CHARGE_MODE_TYPEDEF.
+  */
+u8 charge_get_mode(void)
+{
+    return charge_status.mode;
+}
+
+/**
+  * @brief  get state VUSB insert.
+  * @param  None.
+  * @retval VUSB insertion statue.
+  */
+AT(.com_periph.charge)
+CHARGE_DC_STATUS_TYPEDEF charge_detect_dc(void)
+{
+    u8 status = (RTCCON >> 19 & 0x02) | (RTCCON >> 22 & 0x01);
+
+    if (status > 1) {
+        return CHARGE_DC_STATUS_ONLINE;
+    } else {
+        return status & 0x03;
+    }
+}
+
+/**
+  * @brief  Judge if the charging current reach the cutoff current.
+  * @param  None.
+  * @retval the condition SET of RESET.
+  */
+FLAG_STATE charge_cutoff_cur_condition(void)
+{
+    if ((PWRCON1 & (1 << 30)) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+  * @brief  Judge if the charging voltage reach the cutoff voltage.
+  * @param  None.
+  * @retval the condition SET of RESET.
+  */
+FLAG_STATE charge_cutoff_vol_condition(void)
+{
+    if ((PWRCON1 & (1 << 28)) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+  * @brief  Judge if the charging voltage reach the trickle voltage.
+  * @param  None.
+  * @retval the condition SET of RESET.
+  */
+FLAG_STATE charge_trickle_vol_condition(void)
+{
+    if ((PWRCON1 & (1 << 29)) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+  * @brief  Set the time from the cut-off voltage to stop charging.
+  * @param  time, unit:100ms.
+  */
+void charge_cutoff_vol_to_stop_time_set(uint16_t time)
+{
+    charge_ctrl.cutoff_vol_2_stop_time = time;
+}
+
+/**
+  * @brief  Select charge current when power up charge.
+  */
+void charge_pwrup_charge_cur_sel(CHARGE_PWRUP_CHARGE_CUR_TYPEDEF pwrup_charge_cur)
+{
+    RTCCON7 = (RTCCON7 & ~(0x03<<6)) | (pwrup_charge_cur);
+}

+ 193 - 0
driver/driver_charge.h

@@ -0,0 +1,193 @@
+/*
+ * @File name    : driver_charge.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-06-20
+ * @Description  : This file contains all the functions prototypes for the Charge library.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_CHARGE_H
+#define _DRIVER_CHARGE_H
+
+#include "driver_com.h"
+
+
+/**
+ * @brief Charge Mode Enum
+ */
+typedef enum {
+    CHARGE_MODE_FULL_KEEP       = 0x00,
+    CHARGE_MODE_FULL_DISCONNECT = 0x01,
+} CHARGE_MODE_TYPEDEF;
+
+/**
+ * @brief Charge DC Detect Enum
+ */
+typedef enum {
+    CHARGE_DC_STATUS_OFF = 0x00,
+    CHARGE_DC_STATUS_ONLINE_BUT_ERR = 0x01,
+    CHARGE_DC_STATUS_ONLINE = 0x02,
+} CHARGE_DC_STATUS_TYPEDEF;
+
+/**
+ * @brief Charge Status Enum
+ */
+typedef enum {
+    CHARGE_STA_UNINIT           = 0x00,     // uninitialized.
+    CHARGE_STA_OFF              = 0x01,     // charge off.
+    CHARGE_STA_OFF_BUT_DC_IN    = 0x02,     // charge off but still connect to DC5V.
+    CHARGE_STA_ON_TRICKLE       = 0x03,     // trickle charging.
+    CHARGE_STA_ON_CON_CURR      = 0x04,     // constant current charging.
+    CHARGE_STA_ON_CON_VOL       = 0x05,     // constant voltage charging.
+} CHARGE_STATUS_TYPEDEF;
+
+/**
+ * @brief Charge DC In Reset System Enum
+ */
+typedef enum {
+    CHARGE_DCIN_RESET_DIS       = 0x0000,
+    CHARGE_DCIN_RESET_EN        = 0x0040,
+} CHARGE_DCIN_RESERT_TYPEDEF;
+
+/**
+ * @brief Current Charging Enum
+ */
+typedef enum {
+    CHARGE_CUR_5mA        = 0x0000,
+    CHARGE_CUR_10mA,
+    CHARGE_CUR_15mA,
+    CHARGE_CUR_20mA,
+    CHARGE_CUR_25mA,
+    CHARGE_CUR_30mA,
+    CHARGE_CUR_35mA,
+    CHARGE_CUR_40mA,
+    CHARGE_CUR_45mA,
+    CHARGE_CUR_50mA,
+    CHARGE_CUR_55mA,
+    CHARGE_CUR_60mA,
+    CHARGE_CUR_65mA,
+    CHARGE_CUR_70mA,
+    CHARGE_CUR_75mA,
+    CHARGE_CUR_80mA,
+    CHARGE_CUR_85mA,
+    CHARGE_CUR_90mA,
+    CHARGE_CUR_95mA,
+    CHARGE_CUR_100mA,
+    CHARGE_CUR_105mA,
+    CHARGE_CUR_110mA,
+    CHARGE_CUR_115mA,
+    CHARGE_CUR_120mA,
+    CHARGE_CUR_125mA,
+    CHARGE_CUR_130mA,
+    CHARGE_CUR_135mA,
+    CHARGE_CUR_140mA,
+    CHARGE_CUR_145mA,
+    CHARGE_CUR_150mA,
+    CHARGE_CUR_155mA,
+    CHARGE_CUR_160mA,
+    CHARGE_CUR_165mA,
+    CHARGE_CUR_170mA,
+    CHARGE_CUR_175mA,
+    CHARGE_CUR_180mA,
+    CHARGE_CUR_185mA,
+    CHARGE_CUR_190mA,
+    CHARGE_CUR_195mA,
+    CHARGE_CUR_200mA,
+    CHARGE_CUR_205mA,
+    CHARGE_CUR_210mA,
+    CHARGE_CUR_215mA,
+    CHARGE_CUR_220mA,
+    CHARGE_CUR_225mA,
+    CHARGE_CUR_230mA,
+    CHARGE_CUR_235mA,
+    CHARGE_CUR_240mA,
+    CHARGE_CUR_245mA,
+    CHARGE_CUR_250mA,
+    CHARGE_CUR_255mA,
+    CHARGE_CUR_260mA,
+    CHARGE_CUR_265mA,
+    CHARGE_CUR_270mA,
+    CHARGE_CUR_275mA,
+    CHARGE_CUR_280mA,
+    CHARGE_CUR_285mA,
+    CHARGE_CUR_290mA,
+    CHARGE_CUR_295mA,
+    CHARGE_CUR_300mA,
+    CHARGE_CUR_305mA,
+    CHARGE_CUR_310mA,
+    CHARGE_CUR_315mA,
+    CHARGE_CUR_320mA,
+} CHARGE_CUR_TYPEDEF;
+
+/**
+ * @brief Current of Cutoff charging Enum
+ */
+typedef enum {
+    CHARGE_CUTOFF_CUR_0m        = 0x0000,
+    CHARGE_CUTOFF_CUR_2mA5      = 0x0800,
+    CHARGE_CUTOFF_CUR_5mA       = 0x1000,
+    CHARGE_CUTOFF_CUR_7mA5      = 0x1800,
+    CHARGE_CUTOFF_CUR_10mA      = 0x2000,
+    CHARGE_CUTOFF_CUR_12mA5     = 0x2800,
+    CHARGE_CUTOFF_CUR_15mA      = 0x3000,
+    CHARGE_CUTOFF_CUR_17mA5     = 0x3800,
+    CHARGE_CUTOFF_CUR_20mA      = 0x4000,
+    CHARGE_CUTOFF_CUR_22mA5     = 0x4800,
+    CHARGE_CUTOFF_CUR_25mA      = 0x5000,
+    CHARGE_CUTOFF_CUR_27mA5     = 0x5800,
+    CHARGE_CUTOFF_CUR_30mA      = 0x6000,
+    CHARGE_CUTOFF_CUR_32mA5     = 0x6800,
+    CHARGE_CUTOFF_CUR_35mA      = 0x7000,
+    CHARGE_CUTOFF_CUR_37mA5     = 0x7800,
+} CHARGE_CUTOFF_CUR_TYPEDEF;
+
+/**
+ * @brief Voltage of Cutoff Charging Enum
+ */
+typedef enum {
+    CHARGE_CUTOFF_VOL_4V2       = 0x0000,
+    CHARGE_CUTOFF_VOL_4V35      = 0x0100,
+    CHARGE_CUTOFF_VOL_4V4       = 0x0200,
+    CHARGE_CUTOFF_VOL_4V45      = 0x0300,
+} CHARGE_CUTOFF_VOL_TYPEDEF;
+
+/**
+ * @brief Charge Current When Power Up Charge
+ */
+typedef enum {
+    CHARGE_PWRUP_CUR_5mA        = 0x0000,
+    CHARGE_PWRUP_CUR_10mA       = 0x0040,
+    CHARGE_PWRUP_CUR_15mA       = 0x0080,
+    CHARGE_PWRUP_CUR_20mA       = 0x00c0,
+} CHARGE_PWRUP_CHARGE_CUR_TYPEDEF;
+
+
+/**
+ * @brief Charging Initial Struct
+ */
+typedef struct {
+    CHARGE_DCIN_RESERT_TYPEDEF  dcin_reset;             // reset if DC insert.
+    CHARGE_CUR_TYPEDEF          const_curr;             // the current of the constant currrent charging.
+    CHARGE_CUR_TYPEDEF          trick_curr;             // the current of the trickle charging.
+    CHARGE_CUTOFF_CUR_TYPEDEF   cutoff_curr;            // charging cutoff current.
+    CHARGE_CUTOFF_VOL_TYPEDEF   cutoff_volt;            // charging cutoff voltage.
+    FUNCTIONAL_STATE            trick_curr_en;          // trickle charging enable.
+    CHARGE_MODE_TYPEDEF         mode;                   // disconnect or not when charge full.
+} charge_init_typedef;
+
+//--------------- Function used to configure charging ---------------//
+void charge_init(charge_init_typedef *charge_init_struct);
+void charge_deinit(void);
+void charge_process(void);
+CHARGE_DC_STATUS_TYPEDEF charge_detect_dc(void);
+uint8_t charge_get_status(void);
+void charge_status_update(u8 status);
+void charge_change_mode(u8 mode);
+u8 charge_get_mode(void);
+FLAG_STATE charge_cutoff_cur_condition(void);
+FLAG_STATE charge_cutoff_vol_condition(void);
+FLAG_STATE charge_trickle_vol_condition(void);
+void charge_cutoff_vol_to_stop_time_set(uint16_t time);
+void charge_pwrup_charge_cur_sel(CHARGE_PWRUP_CHARGE_CUR_TYPEDEF pwrup_charge_cur);
+
+#endif // _DRIVER_CHARGE_H

+ 486 - 0
driver/driver_clk.c

@@ -0,0 +1,486 @@
+/*
+ * @File name    : driver_clk.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-04-04
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the CLK peripheral.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_clk.h"
+
+void clk_gate0_cmd(uint32_t clock_gate, CLK_STATE state)
+{
+    if (state != CLK_DIS) {
+        CLKGAT0 |= clock_gate;
+    } else {
+        CLKGAT0 &= ~clock_gate;
+    }
+}
+
+void clk_gate1_cmd(uint32_t clock_gate, CLK_STATE state)
+{
+    if (state != CLK_DIS) {
+        CLKGAT1 |= clock_gate;
+    } else {
+        CLKGAT1 &= ~clock_gate;
+    }
+}
+
+void clk_gate2_cmd(uint32_t clock_gate, CLK_STATE state)
+{
+    if (state != CLK_DIS) {
+        CLKGAT2 |= clock_gate;
+    } else {
+        CLKGAT2 &= ~clock_gate;
+    }
+}
+
+void clk_clkout_set(CLK_CLKOUT_TYPEDEF clk_sel, uint8_t div, CLK_STATE state)
+{
+    if (state != CLK_DIS) {
+        CLKCON0 &= ~(0x0f << 13);
+        CLKCON0 |= ((clk_sel & 0x0f) << 13);
+
+        CLKDIVCON0 &= ~(0x1f << 17);
+        CLKDIVCON0 |= ((div & 0x1f) << 17);
+    } else {
+        CLKCON0 &= ~(0x0f << 13);
+        CLKDIVCON0 &= ~(0x1f << 17);
+    }
+}
+
+void clk_clk32k_rtc_set(CLK_CLK32K_RTC_TYPEDEF clk_sel)
+{
+    uint32_t rtccon0 = RTCCON0;
+
+    if ((CLK_CLK32K_RTC_RC2M_RTC == clk_sel) || (CLK_CLK32K_RTC_SNF_RC_RTC == clk_sel)) {
+        rtccon0  |= BIT(19);                                //RC2M_RTC enable
+    }
+
+    rtccon0 &= ~(0x03 << 8);
+    rtccon0 |= ((clk_sel & 0x03) << 8);
+
+    RTCCON0 = rtccon0;
+}
+
+uint32_t clk_clk32k_rtc_get(CLK_VALUE_MODE_TYPEDEF mode)
+{
+    uint32_t rtccon0 = RTCCON0;
+    u8 index;
+
+    index = (rtccon0 >> 8) & 0x03;
+
+    if (mode == CLK_VALUE_MODE_IDX) {
+        return index;
+    } else {
+        switch (index) {
+            case CLK_CLK32K_RTC_1BIT:
+                return -1L;
+
+            case CLK_CLK32K_RTC_RC2M_RTC:
+            case CLK_CLK32K_RTC_SNF_RC_RTC:
+                return rc2m_clk_nhz_get(1) / 64;
+
+            case CLK_CLK32K_RTC_X24MDIV12_RTC:
+                return 2000000 / 64;
+
+            default:
+                return 0;
+        }
+    }
+}
+
+void clk_hsut0_clk_set(CLK_HSUART_CLK_TYPEDEF clk_sel, uint8_t div)
+{
+    uint32_t clkcon0 = CLKCON0;
+
+    clkcon0 &= ~(0x03 << 17);
+    clkcon0 |= ((clk_sel & 0x03) << 17);
+
+    CLKCON0 = clkcon0;
+
+    if (clk_sel >= CLK_HSUT0_CLK_PLLDIV2_CLK) {
+        CLKDIVCON0 &= ~(0x03 << 22);
+        CLKDIVCON0 |= ((div & 0x03) << 22);
+        PLL0CON |= BIT(13);
+    }
+}
+
+uint32_t clk_hsut0_clk_get(CLK_VALUE_MODE_TYPEDEF mode)
+{
+    uint32_t clkcon0 = CLKCON0;
+    u8 index;
+
+    index = ((clkcon0 >> 17) & 0x03);
+
+    if (mode == CLK_VALUE_MODE_IDX) {
+        return index;
+    } else {
+        switch (index) {
+            case CLK_HSUT0_CLK_XOSC24M_CLK:
+                return 24000000;
+
+            case CLK_HSUT0_CLK_XOSC48M:
+                return 48000000;
+
+            case CLK_HSUT0_CLK_PLLDIV2_CLK:
+                return pll_clk_nhz_get() / 2 / (((CLKDIVCON0 >> 22) & 0x03) + 1);
+
+            case CLK_HSUT0_CLK_UDET_CLKPP:
+                return clk_udet_clk_get(CLK_VALUE_MODE_FREQ) / (((CLKDIVCON0 >> 22) & 0x03) + 1);
+
+            default:
+                return 0;
+        }
+    }
+}
+
+void clk_saradc_clk_set(CLK_SARADC_CLK_TYPEDEF clk_sel)
+{
+    uint32_t clkcon0 = CLKCON0;
+
+    clkcon0 &= ~(0x03 << 28);
+    clkcon0 |= ((clk_sel & 0x03) << 28);
+
+    CLKCON0 = clkcon0;
+}
+
+uint32_t clk_saradc_clk_get(CLK_VALUE_MODE_TYPEDEF mode)
+{
+    uint32_t clkcon0 = CLKCON0;
+    u8 index;
+
+    index = ((clkcon0 >> 28) & 0x03);
+
+    if (mode == CLK_VALUE_MODE_IDX) {
+        return index;
+    } else {
+        switch (index) {
+            case CLK_SARADC_CLK_RC2M_CLK:
+                return rc2m_clk_nhz_get(0);
+
+            case CLK_SARADC_CLK_X24M_CLKDIV4:
+                return 6000000;
+
+            case CLK_SARADC_CLK_X24M_CLKDIV2:
+                return 12000000;
+
+            case CLK_SARADC_CLK_X24Md32K_CLK:
+                return 32000;
+
+            default:
+                return 0;
+        }
+    }
+}
+
+void clk_udet_clk_set(CLK_UDET_CLK_TYPEDEF clk_sel)
+{
+    uint32_t clkcon1 = CLKCON1;
+
+    clkcon1 &= ~(0x03 << 28);
+    clkcon1 |= ((clk_sel & 0x03) << 28);
+
+    CLKCON1 = clkcon1;
+}
+
+uint32_t clk_udet_clk_get(CLK_VALUE_MODE_TYPEDEF mode)
+{
+    uint32_t clkcon1 = CLKCON1;
+    u8 index;
+
+    index = ((clkcon1 >> 28) & 0x03);
+
+    if (mode == CLK_VALUE_MODE_IDX) {
+        return index;
+    } else {
+        switch (index) {
+            case CLK_UDET_CLK_RC2M_CLK:
+                return rc2m_clk_nhz_get(0);
+
+            case CLK_UDET_CLK_RTC_RC2M:
+                return rc2m_clk_nhz_get(1);
+
+            case XOSC24M_CLK:
+                return 24000000;
+
+            case XOSC48M:
+                return 48000000;
+
+            default:
+                return 0;
+        }
+    }
+}
+
+void clk_tmr_inc_set(CLK_TMR_INC_TYPEDEF clk_sel)
+{
+    uint32_t clkcon0 = CLKCON0;
+
+    clkcon0 &= ~(0x03 << 23);
+    clkcon0 |= ((clk_sel & 0x03) << 23);
+
+    CLKCON0 = clkcon0;
+}
+
+uint32_t clk_tmr_inc_get(CLK_VALUE_MODE_TYPEDEF mode)
+{
+    uint32_t clkcon0 = CLKCON0;
+    u8 index;
+
+    index = (clkcon0 >> 23) & 0x03;
+
+    if (mode == CLK_VALUE_MODE_IDX) {
+        return index;
+    } else {
+        switch (index) {
+            case CLK_TMR_INC_OSC32K:
+                return clk_clk32k_rtc_get(CLK_VALUE_MODE_FREQ);
+
+            case CLK_TMR_INC_CLKOUOT_PIN:
+                return -1L;
+
+            case CLK_TMR_INC_X24M_DIV_CLK:
+                return 24000000 / (((CLKDIVCON0 >> 24) & 0xff) + 1);
+
+            case CLK_TMR_INC_RC2M_D0:
+                return rc2m_clk_nhz_get(0) / 2;
+
+            default:
+                return 0;
+        }
+    }
+}
+
+void clk_uart_inc_set(CLK_UART_INC_TPYEDEF clk_sel)
+{
+    uint32_t clkcon1 = CLKCON1;
+
+    clkcon1 &= ~(0x01 << 14);
+    clkcon1 |= ((clk_sel & 0x01) << 14);
+
+    CLKCON1 = clkcon1;
+}
+
+uint32_t clk_uart_inc_get(CLK_VALUE_MODE_TYPEDEF mode)
+{
+    uint32_t clkcon1 = CLKCON1;
+    u8 index;
+
+    index = (clkcon1 >> 14) & 0x01;
+
+    if (mode == CLK_VALUE_MODE_IDX) {
+        return index;
+    } else {
+        switch (index) {
+            case CLK_UART_INC_X24M_DIV_CLK:
+                return 24000000 / (((CLKDIVCON0 >> 24) & 0xff) + 1);
+
+            case CLK_UART_INC_X24M_CLKDIV4:
+                return 6000000;
+
+            default:
+                return 0;
+        }
+    }
+}
+
+void clk_clk2m_ks_set(CLK_CLK2M_KS_TYPEDEF clk_sel)
+{
+    uint32_t rtccon0 = RTCCON0;
+
+    rtccon0 &= ~(0x03 << 14);
+    rtccon0 |= ((clk_sel & 0x03) << 14);
+
+    RTCCON0 = rtccon0;
+}
+
+uint32_t clk_clk2m_ks_get(CLK_VALUE_MODE_TYPEDEF mode)
+{
+    uint32_t rtccon0 = RTCCON0;
+    u8 index;
+
+    index = (rtccon0 >> 14) & 0x03;
+
+    if (mode == CLK_VALUE_MODE_IDX) {
+        return index;
+    } else {
+        switch (index) {
+            case CLK_CLK2M_KS_1BIT:
+                return -1L;
+
+            case CLK_CLK2M_KS_RC2M_RTC:
+                return rc2m_clk_nhz_get(1);
+
+            case CLK_CLK2M_KS_SNF_RC_RTC:
+                return rc2m_clk_nhz_get(1);
+
+            case CLK_CLK2M_KS_X24MDIV12_RTC:
+                return 2000000;
+
+            default:
+                return 0;
+        }
+    }
+}
+
+void clk_sdadda_clk_set(CLK_SDADDA_CLK_TYPEDEF clk_sel, uint8_t div)
+{
+    u32 clkcon1 = CLKCON1;
+    u32 clkdivcon0 = CLKDIVCON0;
+
+    if (clk_sel == 4 || clk_sel > 5) {
+        return;
+    }
+
+    clkcon1 &= ~0x07;
+    clkcon1 |= clk_sel;
+    CLKCON1 = clkcon1;
+
+    if (clk_sel == CLK_SDADDA_CLK_ADDA_CLK24_A) {
+        CLKGAT2 |= BIT(14);
+        clkdivcon0 &= ~(0x0f << 4);
+        clkdivcon0 |= ((div & 0x0f) << 4);
+        CLKDIVCON0 = clkdivcon0;
+    }
+}
+
+uint32_t clk_sdadda_clk_get(CLK_VALUE_MODE_TYPEDEF mode)
+{
+    u32 clkcon1 = CLKCON1;
+    u8 div = ((CLKDIVCON0 >> 4) & 0x0f) + 1;
+    u8 index;
+
+    index = clkcon1 & 0x07;
+
+    if (mode == CLK_VALUE_MODE_IDX) {
+        return index;
+    } else {
+        switch (index) {
+            case CLK_SDADDA_CLK_ADDA_CLK24_A:
+                return (pll_clk_nhz_get() / 2 / div / 2);
+
+            case CLK_SDADDA_CLK_XOSC24M_CLK:
+                return 24000000;
+
+            case CLK_SDADDA_CLK_XOSC24M_CLK_2PLL:
+                return 24000000;
+
+            default:
+                return 0;
+        }
+    }
+}
+
+void clk_ledc_clk_set(CLK_LEDC_CLK_TYPEDEF clk_sel)
+{
+    u32 clkcon1 = CLKCON1;
+
+    clkcon1 &= ~(0x01 << 27);
+    clkcon1 |= (clk_sel & 0x01) << 27;
+
+    CLKCON1 = clkcon1;
+}
+
+uint32_t clk_ledc_clk_get(CLK_VALUE_MODE_TYPEDEF mode)
+{
+    u32 clkcon1 = CLKCON1;
+    u8 index;
+
+    index = (clkcon1 >> 27) & 0x01;
+
+    if (mode == CLK_VALUE_MODE_IDX) {
+        return index;
+    } else {
+        switch (index) {
+            case CLK_LEDC_CLK_XOSC24M:
+                return 24000000;
+
+            case CLK_LEDC_CLK_X24M_CLKDIV2:
+                return 12000000;
+
+            default:
+                return 0;
+        }
+    }
+}
+
+void clk_touch_key_clk_set(CLK_TOUCH_KEY_TYPEDEF clk_sel)
+{
+    if (CLK_TOUCH_KEY_CLK_XOSC24M == clk_sel) {
+        XOSCCON |= BIT(10);     //xosc enable
+        CLKCON4 &= ~BIT(26);    //select xosc24m_p
+    	CLKGAT1 |= BIT(29);     //x24m_clk enable
+    } else if (CLK_TOUCH_KEY_RC2M == clk_sel) {
+    	RTCCON0 |= BIT(19);                          //RC2M_RTC EN
+    }
+
+    RTCCON0 = (RTCCON0 & ~(3 << 12)) | (clk_sel << 12);
+
+	RTCCON &= ~BIT(0);	   //VRTC11 voltage select RTCCON4 bit26~24
+	RTCCON4 = (RTCCON4 & ~(0x07 << 24)) | (5 << 24);		//vrtc11 voltage select 0.7+0.065*5 = 1.025V
+}
+
+uint32_t clk_touch_key_clk_get(CLK_VALUE_MODE_TYPEDEF mode)
+{
+    u32 rtccon0 = RTCCON0;
+    u8 index;
+
+    index = (rtccon0 >> 12) & 0x03;
+
+    if (mode == CLK_VALUE_MODE_IDX) {
+        return index;
+    } else {
+        switch (index) {
+            case CLK_TOUCH_KEY_RC2M:
+                return rc2m_clk_nhz_get(1);
+
+            case CLK_TOUCH_KEY_CLK_XOSC24M:
+                return 2000000;
+
+            default:
+                return 0;
+        }
+    }
+}
+
+void clk_ttmr_inc_set(CLK_TTMR_INC_TYPEDEF clk_sel)
+{
+    uint32_t clkcon1 = CLKCON1;
+
+    clkcon1 &= ~(0x03 << 12);
+    clkcon1 |= ((clk_sel & 0x03) << 12);
+
+    CLKCON1 = clkcon1;
+}
+
+uint32_t clk_ttmr_inc_get(CLK_VALUE_MODE_TYPEDEF mode)
+{
+    uint32_t clkcon1 = CLKCON1;
+    uint8_t index;
+
+    index = (clkcon1 >> 12) & 0x03;
+
+    if (mode == CLK_VALUE_MODE_IDX) {
+        return index;
+    } else {
+        switch (index) {
+            case CLK_TTMR_INC_OSC_32K:
+                return clk_clk32k_rtc_get(CLK_VALUE_MODE_FREQ);
+
+            case CLK_TTMR_INC_CLKOUT_PIN:
+                /* TODO: */
+                return -1L;
+
+            case CLK_TTMR_INC_X24M_DIV_CLK:
+                return 24000000 / (((CLKDIVCON0 >> 24) & 0xff) + 1);
+
+            case CLK_TTMR_INC_RC2M_D0:
+                return rc2m_clk_nhz_get(0) / 2;
+
+            default:
+                return 0;
+        }
+    }
+}

+ 259 - 0
driver/driver_clk.h

@@ -0,0 +1,259 @@
+/*
+ * @File name    : driver_clk.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-04-04
+ * @Description  : This file contains all the functions prototypes for the CLK library.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_CLK_H
+#define _DRIVER_CLK_H
+
+#include "global.h"
+#include "api.h"
+
+
+#define CLK_GATE0_ROM0                  ((uint32_t)(0x00000001))        /* CLKGAT0[0] */
+#define CLK_GATE0_ROM1                  ((uint32_t)(0x00000002))        /* CLKGAT0[1] */
+#define CLK_GATE0_RAM0                  ((uint32_t)(0x00000004))        /* CLKGAT0[2] */
+#define CLK_GATE0_RAM1                  ((uint32_t)(0x00000008))        /* CLKGAT0[3] */
+#define CLK_GATE0_RAM2                  ((uint32_t)(0x00000010))        /* CLKGAT0[4] */
+#define CLK_GATE0_RAM3                  ((uint32_t)(0x00000020))        /* CLKGAT0[5] */
+#define CLK_GATE0_RAM4                  ((uint32_t)(0x00000040))        /* CLKGAT0[6] */
+#define CLK_GATE0_TMR0                  ((uint32_t)(0x00000100))        /* CLKGAT0[8] */
+#define CLK_GATE0_SD0                   ((uint32_t)(0x00000200))        /* CLKGAT0[9] */
+#define CLK_GATE0_UART                  ((uint32_t)(0x00000400))        /* CLKGAT0[10] */
+#define CLK_GATE0_HSUART                ((uint32_t)(0x00000800))        /* CLKGAT0[11] */
+#define CLK_GATE0_DAC                   ((uint32_t)(0x00001000))        /* CLKGAT0[12] */
+#define CLK_GATE0_SARADC                ((uint32_t)(0x00002000))        /* CLKGAT0[13] */
+#define CLK_GATE0_USB                   ((uint32_t)(0x00004000))        /* CLKGAT0[14] */
+#define CLK_GATE0_LP                    ((uint32_t)(0x00008000))        /* CLKGAT0[15] */
+#define CLK_GATE0_AUDEC                 ((uint32_t)(0x00010000))        /* CLKGAT0[16] */
+#define CLK_GATE0_POTR                  ((uint32_t)(0x00020000))        /* CLKGAT0[17] */
+#define CLK_GATE0_MBIST                 ((uint32_t)(0x00040000))        /* CLKGAT0[18] */
+#define CLK_GATE0_SPI0                  ((uint32_t)(0x00080000))        /* CLKGAT0[19] */
+#define CLK_GATE0_BT                    ((uint32_t)(0x00100000))        /* CLKGAT0[20] */
+#define CLK_GATE0_UDET                  ((uint32_t)(0x00200000))        /* CLKGAT0[21] */
+#define CLK_GATE0_SDADCL                ((uint32_t)(0x00400000))        /* CLKGAT0[22] */
+#define CLK_GATE0_SDADCR                ((uint32_t)(0x00800000))        /* CLKGAT0[23] */
+#define CLK_GATE0_TMR1                  ((uint32_t)(0x01000000))        /* CLKGAT0[24] */
+#define CLK_GATE0_TMR2                  ((uint32_t)(0x02000000))        /* CLKGAT0[25] */
+#define CLK_GATE0_RTCC                  ((uint32_t)(0x04000000))        /* CLKGAT0[26] */
+#define CLK_GATE0_RECSRC                ((uint32_t)(0x08000000))        /* CLKGAT0[27] */
+#define CLK_GATE0_SDADCM                ((uint32_t)(0x10000000))        /* CLKGAT0[28] */
+#define CLK_GATE0_SPF                   ((uint32_t)(0x20000000))        /* CLKGAT0[29] */
+#define CLK_GATE0_AEC                   ((uint32_t)(0x40000000))        /* CLKGAT0[30] */
+#define CLK_GATE0_CVSD                  ((uint32_t)(0x80000000))        /* CLKGAT0[31] */
+
+#define CLK_GATE1_IRTX                  ((uint32_t)(0x00000004))        /* CLKGAT1[2] */
+#define CLK_GATE1_IRRX                  ((uint32_t)(0x00000008))        /* CLKGAT1[3] */
+#define CLK_GATE1_SBCEC                 ((uint32_t)(0x00000020))        /* CLKGAT1[5] */
+#define CLK_GATE1_LPBK                  ((uint32_t)(0x00000040))        /* CLKGAT1[6] */
+#define CLK_GATE1_PLC                   ((uint32_t)(0x00000080))        /* CLKGAT1[7] */
+#define CLK_GATE1_TMR3                  ((uint32_t)(0x00000100))        /* CLKGAT1[8] */
+#define CLK_GATE1_UDET                  ((uint32_t)(0x00000800))        /* CLKGAT1[11] */
+#define CLK_GATE1_SPI1                  ((uint32_t)(0x00001000))        /* CLKGAT1[12] */
+#define CLK_GATE1_QDECX                 ((uint32_t)(0x00002000))        /* CLKGAT1[13] */
+#define CLK_GATE1_QDECY                 ((uint32_t)(0x00004000))        /* CLKGAT1[14] */
+#define CLK_GATE1_PIANO                 ((uint32_t)(0x00008000))        /* CLKGAT1[15] */
+#define CLK_GATE1_TICK0                 ((uint32_t)(0x00010000))        /* CLKGAT1[16] */
+#define CLK_GATE1_QDEC                  ((uint32_t)(0x00020000))        /* CLKGAT1[17] */
+#define CLK_GATE1_LPWM                  ((uint32_t)(0x00040000))        /* CLKGAT1[18] */
+#define CLK_GATE1_AECRAM                ((uint32_t)(0x00800000))        /* CLKGAT1[23] */
+#define CLK_GATE1_ROM2                  ((uint32_t)(0x01000000))        /* CLKGAT1[24] */
+#define CLK_GATE1_ROM3                  ((uint32_t)(0x02000000))        /* CLKGAT1[25] */
+#define CLK_GATE1_FREQDET               ((uint32_t)(0x04000000))        /* CLKGAT1[26] */
+#define CLK_GATE1_PBF                   ((uint32_t)(0x08000000))        /* CLKGAT1[27] */
+#define CLK_GATE1_DBG                   ((uint32_t)(0x10000000))        /* CLKGAT1[28] */
+#define CLK_GATE1_X24M                  ((uint32_t)(0x20000000))        /* CLKGAT1[29] */
+#define CLK_GATE1_M2M                   ((uint32_t)(0x40000000))        /* CLKGAT1[30] */
+#define CLK_GATE1_EFUS                  ((uint32_t)(0x80000000))        /* CLKGAT1[31] */
+
+#define CLK_GATE2_IIC                   ((uint32_t)(0x00000001))        /* CLKGAT2[0] */
+#define CLK_GATE2_IRFLT                 ((uint32_t)(0x00000002))        /* CLKGAT2[1] */
+#define CLK_GATE2_LEDC                  ((uint32_t)(0x00000004))        /* CLKGAT2[2] */
+#define CLK_GATE2_SYSX24M               ((uint32_t)(0x00000100))        /* CLKGAT2[8] */
+#define CLK_GATE2_X48M                  ((uint32_t)(0x00000200))        /* CLKGAT2[9] */
+#define CLK_GATE2_BSP                   ((uint32_t)(0x00000400))        /* CLKGAT2[10] */
+#define CLK_GATE2_CLKOUTDIV2            ((uint32_t)(0x00000800))        /* CLKGAT2[11] */
+#define CLK_GATE2_CLKOUTDIV4            ((uint32_t)(0x00001000))        /* CLKGAT2[12] */
+#define CLK_GATE2_SYSDIV                ((uint32_t)(0x00002000))        /* CLKGAT2[13] */
+#define CLK_GATE2_ADDIV                 ((uint32_t)(0x00004000))        /* CLKGAT2[14] */
+#define CLK_GATE2_DAC_CLK               ((uint32_t)(0x00008000))        /* CLKGAT2[15] */
+#define CLK_GATE2_DAC_CLK25             ((uint32_t)(0x00010000))        /* CLKGAT2[16] */
+#define CLK_GATE2_DAC_DIV2SEL           ((uint32_t)(0x00020000))        /* CLKGAT2[17] */
+#define CLK_GATE2_DRC_PCLK              ((uint32_t)(0x00040000))        /* CLKGAT2[18] */
+#define CLK_GATE2_RNN                   ((uint32_t)(0x00080000))        /* CLKGAT2[19] */
+#define CLK_GATE2_RDFT                  ((uint32_t)(0x00100000))        /* CLKGAT2[20] */
+#define CLK_GATE2_HWMATH                ((uint32_t)(0x00200000))        /* CLKGAT2[21] */
+
+/**
+ * @brief Clock Status Enumeration.
+ */
+typedef enum {
+    CLK_DIS                         = 0,
+    CLK_EN                          = 1,
+} CLK_STATE;
+
+/**
+ * @brief Clock Info Type Enumeration.
+ */
+typedef enum {
+    CLK_VALUE_MODE_IDX              = 0,
+    CLK_VALUE_MODE_FREQ             = 1,
+} CLK_VALUE_MODE_TYPEDEF;
+
+/**
+ * @brief Clock of CLKOUT Enumeration.
+ */
+typedef enum {
+    CLK_CLKOUT_XOSC24M              = 1,
+    CLK_CLKOUT_X24M_32K,
+    CLK_CLKOUT_OSC32K,
+    CLK_CLKOUT_PLLDIV4,
+    CLK_CLKOUT_XOSC48M,
+    CLK_CLKOUT_DAC_CLKPPP,
+    CLK_CLKOUT_RC2M,
+    CLK_CLKOUT_RTC_RC2M,
+    CLK_CLKOUT_SYS_CLK,
+    CLK_CLKOUT_BT24M_CLK,
+    CLK_CLKOUT_TKA_OUT,
+    CLK_CLKOUT_BTLP_CLK,
+} CLK_CLKOUT_TYPEDEF;
+
+/**
+ * @brief Clock of CLK32K_RTC Enumeration.
+ */
+typedef enum {
+    CLK_CLK32K_RTC_1BIT             = 0,
+    CLK_CLK32K_RTC_RC2M_RTC,
+    CLK_CLK32K_RTC_SNF_RC_RTC,
+    CLK_CLK32K_RTC_X24MDIV12_RTC,
+} CLK_CLK32K_RTC_TYPEDEF;
+
+/**
+ * @brief Clock of HSUART_CLK Enumeration.
+ */
+typedef enum {
+    CLK_HSUT0_CLK_XOSC24M_CLK       = 0,
+    CLK_HSUT0_CLK_XOSC48M,
+    CLK_HSUT0_CLK_PLLDIV2_CLK,
+    CLK_HSUT0_CLK_UDET_CLKPP,
+} CLK_HSUART_CLK_TYPEDEF;
+
+/**
+ * @brief Clock of SARADC_CLK Enumeration.
+ */
+typedef enum {
+    CLK_SARADC_CLK_RC2M_CLK         = 0,
+    CLK_SARADC_CLK_X24M_CLKDIV4,
+    CLK_SARADC_CLK_X24M_CLKDIV2,
+    CLK_SARADC_CLK_X24Md32K_CLK,
+} CLK_SARADC_CLK_TYPEDEF;
+
+/**
+ * @brief Clock of UDET_CLK Enumeration.
+ */
+typedef enum {
+    CLK_UDET_CLK_RC2M_CLK           = 0,
+    CLK_UDET_CLK_RTC_RC2M,
+    XOSC24M_CLK,
+    XOSC48M,
+} CLK_UDET_CLK_TYPEDEF;
+
+/**
+ * @brief Clock of TMR_INC Enumeration.
+ */
+typedef enum {
+    CLK_TMR_INC_OSC32K              = 0,
+    CLK_TMR_INC_CLKOUOT_PIN,
+    CLK_TMR_INC_X24M_DIV_CLK,
+    CLK_TMR_INC_RC2M_D0,
+} CLK_TMR_INC_TYPEDEF;
+
+/**
+ * @brief Clock of UART_INC Enumeration.
+ */
+typedef enum {
+    CLK_UART_INC_X24M_DIV_CLK       = 0,
+    CLK_UART_INC_X24M_CLKDIV4,
+} CLK_UART_INC_TPYEDEF;
+
+/**
+ * @brief Clock of CLK2M_KS(KeyScan) Enumeration.
+ */
+typedef enum {
+    CLK_CLK2M_KS_1BIT               = 0,
+    CLK_CLK2M_KS_RC2M_RTC,
+    CLK_CLK2M_KS_SNF_RC_RTC,
+    CLK_CLK2M_KS_X24MDIV12_RTC,
+} CLK_CLK2M_KS_TYPEDEF;
+
+/**
+ * @brief Clock of SDADDA_CLK Enumeration.
+ */
+typedef enum {
+    CLK_SDADDA_CLK_1BIT             = 0,
+    CLK_SDADDA_CLK_ADDA_CLK24_A,
+    CLK_SDADDA_CLK_XOSC24M_CLK,
+    CLK_SDADDA_CLK_PB4,
+    CLK_SDADDA_CLK_XOSC24M_CLK_2PLL = 5,
+} CLK_SDADDA_CLK_TYPEDEF;
+
+/**
+ * @brief Clock of LEDC_CLK Enumeration.
+ */
+typedef enum {
+    CLK_LEDC_CLK_XOSC24M            = 0,
+    CLK_LEDC_CLK_X24M_CLKDIV2,
+} CLK_LEDC_CLK_TYPEDEF;
+
+/**
+ * @brief Clock of TOUCH_KEY Enumeration.
+ */
+typedef enum {
+    CLK_TOUCH_KEY_RC2M              = 1,
+    CLK_TOUCH_KEY_CLK_XOSC24M       = 3,
+} CLK_TOUCH_KEY_TYPEDEF;
+
+/**
+ * @brief Clock of TTMR_INC(tick0) Enumeration.
+ */
+typedef enum {
+    CLK_TTMR_INC_OSC_32K             = 0,
+    CLK_TTMR_INC_CLKOUT_PIN,
+    CLK_TTMR_INC_X24M_DIV_CLK,
+    CLK_TTMR_INC_RC2M_D0,
+} CLK_TTMR_INC_TYPEDEF;
+
+
+void clk_gate0_cmd(uint32_t clock_gate, CLK_STATE state);
+void clk_gate1_cmd(uint32_t clock_gate, CLK_STATE state);
+void clk_gate2_cmd(uint32_t clock_gate, CLK_STATE state);
+
+void clk_clkout_set(CLK_CLKOUT_TYPEDEF clk_sel, uint8_t div, CLK_STATE state);
+void clk_clk32k_rtc_set(CLK_CLK32K_RTC_TYPEDEF clk_sel);
+void clk_hsut0_clk_set(CLK_HSUART_CLK_TYPEDEF clk_sel, uint8_t div);
+void clk_saradc_clk_set(CLK_SARADC_CLK_TYPEDEF clk_sel);
+void clk_udet_clk_set(CLK_UDET_CLK_TYPEDEF clk_sel);
+void clk_tmr_inc_set(CLK_TMR_INC_TYPEDEF clk_sel);
+void clk_uart_inc_set(CLK_UART_INC_TPYEDEF clk_sel);
+void clk_clk2m_ks_set(CLK_CLK2M_KS_TYPEDEF clk_sel);
+void clk_sdadda_clk_set(CLK_SDADDA_CLK_TYPEDEF clk_sel, uint8_t div);
+void clk_ledc_clk_set(CLK_LEDC_CLK_TYPEDEF clk_sel);
+void clk_touch_key_clk_set(CLK_TOUCH_KEY_TYPEDEF clk_sel);
+void clk_ttmr_inc_set(CLK_TTMR_INC_TYPEDEF clk_sel);
+
+uint32_t clk_clk32k_rtc_get(CLK_VALUE_MODE_TYPEDEF mode);
+uint32_t clk_hsut0_clk_get(CLK_VALUE_MODE_TYPEDEF mode);
+uint32_t clk_saradc_clk_get(CLK_VALUE_MODE_TYPEDEF mode);
+uint32_t clk_udet_clk_get(CLK_VALUE_MODE_TYPEDEF mode);
+uint32_t clk_tmr_inc_get(CLK_VALUE_MODE_TYPEDEF mode);
+uint32_t clk_uart_inc_get(CLK_VALUE_MODE_TYPEDEF mode);
+uint32_t clk_clk2m_ks_get(CLK_VALUE_MODE_TYPEDEF mode);
+uint32_t clk_sdadda_clk_get(CLK_VALUE_MODE_TYPEDEF mode);
+uint32_t clk_ledc_clk_get(CLK_VALUE_MODE_TYPEDEF mode);
+uint32_t clk_touch_key_clk_get(CLK_VALUE_MODE_TYPEDEF mode);
+uint32_t clk_ttmr_inc_get(CLK_VALUE_MODE_TYPEDEF mode);
+
+#endif // _DRIVER_CLK_H

+ 1287 - 0
driver/driver_com.h

@@ -0,0 +1,1287 @@
+/*
+ * @File name    : driver_com.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-10
+ * @Description  : AB202X Device Peripheral Access Layer Header File.
+ *                 This file contains all the peripheral register's definitions, bits
+ *                 definitions and memory mapping for AB202X devices.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_COM_H
+#define _DRIVER_COM_H
+
+#include "global.h"
+#include "api.h"
+#include "driver_clk.h"
+
+typedef enum {DISABLE = 0, ENABLE = !DISABLE} FUNCTIONAL_STATE;
+typedef enum {RESET = 0, SET = !RESET} FLAG_STATE, IT_STATE;
+typedef enum {FAILED = 0, SUCCESS = !FAILED} STATUS_STATE;
+
+//--------------------------- SFR BASE DECLARATION ---------------------------//
+#define SFR0_BASE                           (SFR_BASE + 0x000)
+#define SFR1_BASE                           (SFR_BASE + 0x100)
+#define SFR2_BASE                           (SFR_BASE + 0x200)
+#define SFR3_BASE                           (SFR_BASE + 0x300)
+#define SFR4_BASE                           (SFR_BASE + 0x400)
+#define SFR5_BASE                           (SFR_BASE + 0x500)
+#define SFR6_BASE                           (SFR_BASE + 0x600)
+#define SFR7_BASE                           (SFR_BASE + 0x700)
+#define SFR8_BASE                           (SFR_BASE + 0x800)
+#define SFR9_BASE                           (SFR_BASE + 0x900)
+#define SFR10_BASE                          (SFR_BASE + 0xa00)
+#define SFR11_BASE                          (SFR_BASE + 0xb00)
+#define SFR12_BASE                          (SFR_BASE + 0xc00)
+#define SFR13_BASE                          (SFR_BASE + 0xd00)
+#define SFR14_BASE                          (SFR_BASE + 0xe00)
+#define SFR15_BASE                          (SFR_BASE + 0xf00)
+
+//-------------------------------- SFR Group0 --------------------------------//
+#define TICK0_BASE                          (SFR0_BASE + 0x01*4)
+#define TICK1_BASE                          (SFR0_BASE + 0x05*4)
+#define UART0_BASE                          (SFR0_BASE + 0x10*4)
+#define TMR0_BASE                           (SFR0_BASE + 0x14*4)
+#define WDT_BASE                            (SFR0_BASE + 0x1a*4)
+#define SD0_BASE                            (SFR0_BASE + 0x20*4)
+#define SPI0_BASE                           (SFR0_BASE + 0x2a*4)
+#define UART1_BASE                          (SFR0_BASE + 0x30*4)
+#define TMR1_BASE                           (SFR0_BASE + 0x35*4)
+#define TMR2_BASE                           (SFR0_BASE + 0x3a*4)
+
+//---------------------------------- SFR Group1 -----------------------------------//
+
+//---------------------------------- SFR Group3 -----------------------------------//
+#define HSUART_BASE                         (SFR3_BASE + 0x30*4)
+
+//---------------------------------- SFR Group4 -----------------------------------//
+
+//---------------------------------- SFR Group5 -----------------------------------//
+#define IIC_BASE                            (SFR5_BASE + 0x07*4)
+#define SARADC_BASE                         (SFR5_BASE + 0x20*4)
+
+//---------------------------------- SFR Group6 -----------------------------------//
+#define GPIOA_BASE                          (SFR6_BASE + 0x00*4)
+#define GPIOB_BASE                          (SFR6_BASE + 0x10*4)
+#define FUNCMCON_BASE                       (SFR6_BASE + 0x30*4)
+
+//---------------------------------- SFR Group7 -----------------------------------//
+#define GPIOG_BASE                          (SFR7_BASE + 0x00*4)
+#define IRTX_BASE                           (SFR7_BASE + 0x20*4)
+#define IRRX_BASE                           (SFR7_BASE + 0x2f*4)
+
+//---------------------------------- SFR Group8 -----------------------------------//
+#define KEYSCAN_BASE                        (SFR8_BASE + 0x00*4)
+
+//---------------------------------- SFR Group9 -----------------------------------//
+#define TMR3_BASE                           (SFR9_BASE + 0x00*4)
+#define UDET_BASE                           (SFR9_BASE + 0x18*4)
+#define SPI1_BASE                           (SFR9_BASE + 0x20*4)
+
+//---------------------------------- SFR Group10 -----------------------------------//
+#define TOUCH_KEY_BASE                      (SFR10_BASE + 0x02*4)
+
+//---------------------------------- SFR Group12 -----------------------------------//
+#define TIM_BASE                            (SFR12_BASE + 0x00*4)
+#define LEDC_BASE                           (SFR12_BASE + 0x30*4)
+
+//---------------------------------- SFR Group13 -----------------------------------//
+#define SDADC_BASE                          (SFR13_BASE + 0x09*4)
+#define SDDAC_BASE                          (SFR13_BASE + 0x13*4)
+#define LPWM_BASE                           (SFR13_BASE + 0x20*4)
+
+/**
+ * @brief PERIPHERAL DECLARATION
+ */
+#define GPIOA_REG                           ((gpio_typedef *) GPIOA_BASE)
+#define GPIOB_REG                           ((gpio_typedef *) GPIOB_BASE)
+#define FUNCMAP                             ((func_map_typedef *) FUNCMCON_BASE)
+#define TMR0                                ((tmr_typedef *) TMR0_BASE)
+#define TMR1                                ((tmr_typedef *) TMR1_BASE)
+#define TMR2                                ((tmr_typedef *) TMR2_BASE)
+#define TMR3                                ((tmr_typedef *) TMR3_BASE)
+#define TIM1                                ((tim_typedef *) TIM_BASE)
+#define UART                                ((uart_typedef *) UART0_BASE)
+#define UDET                                ((uart_typedef *) UDET_BASE)
+#define HSUART                              ((hsuart_typedef *) HSUART_BASE)
+#define IIC                                 ((iic_typedef *) IIC_BASE)
+#define SPI0                                ((spi_typedef *) SPI0_BASE)
+#define SPI1                                ((spi_typedef *) SPI1_BASE)
+#define WDT                                 ((wdt_typedef *) WDT_BASE)
+#define SARADC                              ((sadc_typedef *) SARADC_BASE)
+#define LPWM                                ((lpwm_typedef *) LPWM_BASE)
+#define KEYSCAN                             ((keyscan_typedef *) KEYSCAN_BASE)
+#define IRTX                                ((irtx_typedef *) IRTX_BASE)
+#define IRRX                                ((irrx_typedef *) IRRX_BASE)
+#define TOUCH_KEY                           ((touch_key_typedef *) TOUCH_KEY_BASE)
+#define SDADC                               ((sdadc_typedef *) SDADC_BASE)
+#define SDDAC                               ((sddac_typedef *) SDDAC_BASE)
+#define LEDC                                ((ledc_typedef *) LEDC_BASE)
+#define TICK                                ((tick_typedef *) TICK0_BASE)
+
+/*---------------------------------------------------------------------------------*/
+/*                                     TMR                                         */
+/*---------------------------------------------------------------------------------*/
+/******************** Bit definition for TMR[0.1.2]CON register ********************/
+#define TMRxCON_TMREN                       ((uint32_t)0x00000001)
+
+#define TMRxCON_INCSEL                      ((uint32_t)0x0000000c)
+#define TMRxCON_INCSEL_0                    ((uint32_t)0x00000004)
+#define TMRxCON_INCSEL_1                    ((uint32_t)0x00000008)
+
+#define TMRxCON_INCSRC                      ((uint32_t)0x00000040)
+#define TMRxCON_TIE                         ((uint32_t)0x00000080)
+#define TMRxCON_TPND                        ((uint32_t)0x00000200)
+
+/*********************** Bit definition for TMR3CON register ***********************/
+#define TMR3CON_TMREN                       ((uint32_t)0x00000001)
+#define TMR3CON_CPTEN                       ((uint32_t)0x00000002)
+
+#define TMR3CON_INCSEL                      ((uint32_t)0x0000000c)
+#define TMR3CON_INCSEL_0                    ((uint32_t)0x00000004)
+#define TMR3CON_INCSEL_1                    ((uint32_t)0x00000008)
+
+#define TMR3CON_CPTEDSEL                    ((uint32_t)0x00000030)
+#define TMR3CON_CPTEDSEL_0                  ((uint32_t)0x00000010)
+#define TMR3CON_CPTEDSEL_1                  ((uint32_t)0x00000020)
+
+#define TMR3CON_INCSRC                      ((uint32_t)0x00000040)
+#define TMR3CON_TIE                         ((uint32_t)0x00000080)
+#define TMR3CON_CIE                         ((uint32_t)0x00000100)
+#define TMR3CON_PWM0EN                      ((uint32_t)0x00000200)
+#define TMR3CON_PWM1EN                      ((uint32_t)0x00000400)
+#define TMR3CON_PWM2EN                      ((uint32_t)0x00000800)
+#define TMR3CON_TIMS                        ((uint32_t)0x00001000)
+#define TMR3CON_TIS                         ((uint32_t)0x00002000)
+#define TMR3CON_CPT_CLREN                   ((uint32_t)0x00004000)
+#define TMR3CON_CPT_FLTEN                   ((uint32_t)0x00008000)
+#define TMR3CON_TPND                        ((uint32_t)0x00010000)
+#define TMR3CON_CPND                        ((uint32_t)0x00020000)
+
+/******************** Bit definition for TMR[0.1.2]CPND register *******************/
+#define TMRxCPND_TPCLR                      ((uint32_t)0x00000200)
+
+/*********************** Bit definition for TMR3CPND register **********************/
+#define TMR3CPND_TPCLR                      ((uint32_t)0x00010000)
+#define TMR3CPND_CPCLR                      ((uint32_t)0x00020000)
+
+/*---------------------------------------------------------------------------------*/
+/*                                     UART                                        */
+/*---------------------------------------------------------------------------------*/
+/*********************** Bit definition for UARTxCON register **********************/
+#define UARTxCON_UTEN                       ((uint32_t)0x00000001)
+#define UARTxCON_BIT9EN                     ((uint32_t)0x00000002)
+#define UARTxCON_RXIE                       ((uint32_t)0x00000004)
+#define UARTxCON_TXIE                       ((uint32_t)0x00000008)
+#define UARTxCON_SB2EN                      ((uint32_t)0x00000010)
+#define UARTxCON_CLKSRC                     ((uint32_t)0x00000020)
+/* UDETCON Register */
+#define UARTxCON_FIXBAUD                    ((uint32_t)0x00000020)
+#define UARTxCON_ONELINE                    ((uint32_t)0x00000040)
+#define UARTxCON_RXEN                       ((uint32_t)0x00000080)
+#define UARTxCON_TXPND                      ((uint32_t)0x00000100)
+#define UARTxCON_RXPND                      ((uint32_t)0x00000200)
+#define UARTxCON_RX4BUFEN                   ((uint32_t)0x00000400)
+/* UDETCON Register */
+#define UARTxCON_KEYMAT                     ((uint32_t)0x00000400)
+
+#define UARTxCON_RXBCNT                     ((uint32_t)0x00003800)
+#define UARTxCON_RXBCNT_0                   ((uint32_t)0x00000800)
+#define UARTxCON_RXBCNT_1                   ((uint32_t)0x00001000)
+#define UARTxCON_RXBCNT_2                   ((uint32_t)0x00002000)
+
+#define UARTxCON_RX4BUFPND                  ((uint32_t)0x00004000)
+#define UARTxCON_RX4BUFERROR                ((uint32_t)0x00008000)
+
+/*********************** Bit definition for UARTxCPND register *********************/
+#define UARTxCPND_ALL                       ((uint32_t)0x00038300)
+#define UARTxCPND_CTXPND                    ((uint32_t)0x00000100)
+#define UARTxCPND_CRXPND                    ((uint32_t)0x00000200)
+/* UDETCPND Register */
+#define UARTxCPND_CKEYMAT                   ((uint32_t)0x00000400)
+#define UARTxCPND_RX4BUF_ERR_CLR            ((uint32_t)0x00008000)
+#define UARTxCPND_CKEYPND                   ((uint32_t)0x00010000)
+#define UARTxCPND_CRSTKEYPND                ((uint32_t)0x00020000)
+/* UDETCPND Register */
+#define UARTxCPND_CBDCFM                    ((uint32_t)0x00040000)
+
+/*---------------------------------------------------------------------------------*/
+/*                                    HUART                                        */
+/*---------------------------------------------------------------------------------*/
+/*********************** Bit definition for HSUT0CON register **********************/
+#define HSUT0CON_URXEN                      ((uint32_t)0x00000001)
+#define HSUT0CON_UTXEN                      ((uint32_t)0x00000002)
+#define HSUT0CON_RXIE                       ((uint32_t)0x00000004)
+#define HSUT0CON_TXIE                       ((uint32_t)0x00000008)
+#define HSUT0CON_RXTRSMODE                  ((uint32_t)0x00000010)
+#define HSUT0CON_RXBITSEL                   ((uint32_t)0x00000020)
+#define HSUT0CON_RXLPBUFEN                  ((uint32_t)0x00000040)
+#define HSUT0CON_TXTRSMODE                  ((uint32_t)0x00000080)
+#define HSUT0CON_TXBITSEL                   ((uint32_t)0x00000100)
+#define HSUT0CON_SPBITSEL                   ((uint32_t)0x00000200)
+#define HSUT0CON_HSUTTMREN                  ((uint32_t)0x00000400)
+#define HSUT0CON_RXHF_PND                   ((uint32_t)0x00000800)
+#define HSUT0CON_RXPND                      ((uint32_t)0x00001000)
+#define HSUT0CON_TXPND                      ((uint32_t)0x00002000)
+#define HSUT0CON_RXFAIL                     ((uint32_t)0x00004000)
+#define HSUT0CON_TMROV                      ((uint32_t)0x00008000)
+#define HSUT0CON_RXOVE_PND                  ((uint32_t)0x00010000)
+#define HSUT0CON_RXHF_IE                    ((uint32_t)0x00020000)
+#define HSUT0CON_ONELINE                    ((uint32_t)0x00040000)
+
+/*********************** Bit definition for HSUT0CPND register *********************/
+#define HSUT0CPND_CUTRX                     ((uint32_t)0x00000001)
+#define HSUT0CPND_CUTTX                     ((uint32_t)0x00000002)
+#define HSUT0CPND_CCTSPND                   ((uint32_t)0x00000400)
+#define HSUT0CPND_CRXHFPND                  ((uint32_t)0x00000800)
+#define HSUT0CPND_CRXPND                    ((uint32_t)0x00001000)
+#define HSUT0CPND_CTXPND                    ((uint32_t)0x00002000)
+#define HSUT0CPND_CRXFAIL                   ((uint32_t)0x00004000)
+#define HSUT0CPND_CTMROV                    ((uint32_t)0x00008000)
+#define HSUT0CPND_CRXOVEPND                 ((uint32_t)0x00010000)
+#define HSUT0CPND_CRXLBBUF                  ((uint32_t)0x00020000)
+
+/*********************** Bit definition for HSUT0FCCON register ********************/
+#define HSUT0CCON_UCTS_EN                   ((uint32_t)0x00000001)
+#define HSUT0CCON_URTS_EN                   ((uint32_t)0x00000002)
+#define HSUT0CCON_CTSIE                     ((uint32_t)0x00000004)
+#define HSUT0CCON_RTS_MODE                  ((uint32_t)0x00000008)
+#define HSUT0CCON_CTSPND                    ((uint32_t)0x00000010)
+#define HSUT0CCON_CTSS                      ((uint32_t)0x00000020)
+#define HSUT0CCON_RTSS                      ((uint32_t)0x00000040)
+#define HSUT0CCON_RTS_SW                    ((uint32_t)0x00000080)
+
+/*---------------------------------------------------------------------------------*/
+/*                                     IIC                                         */
+/*---------------------------------------------------------------------------------*/
+/************************ Bit definition for IICCON0 register **********************/
+#define IICCON0_DONE                        ((uint32_t)0x80000000)
+#define IICCON0_ACKSTATUS                   ((uint32_t)0x40000000)
+#define IICCON0_CLR_DONE                    ((uint32_t)0x20000000)
+#define IICCON0_KS                          ((uint32_t)0x10000000)
+#define IICCON0_CLR_ALL                     ((uint32_t)0x08000000)
+#define IICCON0_RX_NACK_EN                  ((uint32_t)0x00004000)
+#define IICCON0_SMP_SEL                     ((uint32_t)0x00002000)
+#define IICCON0_MODE                        ((uint32_t)0x00001000)
+
+#define IICCON0_POSDIV                      ((uint32_t)0x000003f0)
+
+#define IICCON0_HOLDCNT                     ((uint32_t)0x0000000c)
+
+#define IICCON0_INTEN                       ((uint32_t)0x00000002)
+#define IICCON0_IICEN                       ((uint32_t)0x00000001)
+
+/************************ Bit definition for IICCON1 register **********************/
+#define IICCON1_DATA_CNT                    ((uint32_t)0x00000007)
+
+#define IICCON1_START0_EN                   ((uint32_t)0x00000008)
+#define IICCON1_CTL0_EN                     ((uint32_t)0x00000010)
+#define IICCON1_ADR0_EN                     ((uint32_t)0x00000020)
+#define IICCON1_ADR1_EN                     ((uint32_t)0x00000040)
+#define IICCON1_START1_EN                   ((uint32_t)0x00000080)
+#define IICCON1_CTL1_EN                     ((uint32_t)0x00000100)
+#define IICCON1_RDAT_EN                     ((uint32_t)0x00000200)
+#define IICCON1_WDAT_EN                     ((uint32_t)0x00000400)
+#define IICCON1_STOP_EN                     ((uint32_t)0x00000800)
+#define IICCON1_TXNAK_EN                    ((uint32_t)0x00001000)
+
+/************************ Bit definition for IICSSTS register **********************/
+#define IICSSTS_RXVLD                       ((uint32_t)0x00000001)
+#define IICSSTS_TXVLD                       ((uint32_t)0x00000002)
+#define IICSSTS_START                       ((uint32_t)0x00000004)
+#define IICSSTS_RESTART                     ((uint32_t)0x00000008)
+#define IICSSTS_STOP                        ((uint32_t)0x00000010)
+#define IICSSTS_SRX                         ((uint32_t)0x00000020)
+#define IICSSTS_STX                         ((uint32_t)0x00000040)
+
+#define IICSSTS_DATA_CNT                    ((uint32_t)0x00000700)
+
+#define IICSSTS_RXVLD_SET                   ((uint32_t)0x00010000)
+#define IICSSTS_TXVLD_SET                   ((uint32_t)0x00020000)
+#define IICSSTS_START_CLR                   ((uint32_t)0x00040000)
+#define IICSSTS_RESTART_CLR                 ((uint32_t)0x00080000)
+#define IICSSTS_STOP_CLR                    ((uint32_t)0x00100000)
+
+/*---------------------------------------------------------------------------------*/
+/*                                     RTC                                         */
+/*---------------------------------------------------------------------------------*/
+/************************ Bit definition for RTCCON register ***********************/
+#define RTCCON_VRTCVSEL                     ((uint32_t)0x00000001)
+
+#define RTCCON_BAUDSEL                      ((uint32_t)0x00000006)
+
+#define RTCCON_RTC1SIE                      ((uint32_t)0x00000008)
+#define RTCCON_ALMIE                        ((uint32_t)0x00000010)
+#define RTCCON_WKUPRSTEN                    ((uint32_t)0x00000020)
+#define RTCCON_VUSBRSTEN                    ((uint32_t)0x00000040)
+#define RTCCON_RTC_WKSLPEN                  ((uint32_t)0x00000080)
+#define RTCCON_ALM_WKEN                     ((uint32_t)0x00000100)
+#define RTCCON_VUSBON_WKSLPEN               ((uint32_t)0x00000200)
+#define RTCCON_INBOX_WKSLPEN                ((uint32_t)0x00000400)
+#define RTCCON_VUSBONIE                     ((uint32_t)0x00000800)
+#define RTCCON_INBOXIE                      ((uint32_t)0x00001000)
+#define RTCCON_RTC_ON                       ((uint32_t)0x00010000)
+#define RTCCON_ALMPND                       ((uint32_t)0x00020000)
+#define RTCCON_RTCWKSLPPND                  ((uint32_t)0x00040000)
+#define RTCCON_RTCWKP                       ((uint32_t)0x00080000)
+#define RTCCON_VUSBONLINE                   ((uint32_t)0x00100000)
+#define RTCCON_VUSBOFF                      ((uint32_t)0x00200000)
+#define RTCCON_INBOX                        ((uint32_t)0x00400000)
+
+/************************ Bit definition for RTCCPND register **********************/
+#define RTCCPND_TKTSOE                      ((uint32_t)0x00000003)
+
+#define RTCCPND_CALMPND                     ((uint32_t)0x00020000)
+#define RTCCPND_CWKSLPPND                   ((uint32_t)0x00040000)
+
+#define RTCCPND_VBCNTDIS                    ((uint32_t)0x30000000)
+
+#define RTCCPND_VBCNTKST                    ((uint32_t)0x40000000)
+#define RTCCPND_VBCNTCLR                    ((uint32_t)0x80000000)
+
+/************************ Bit definition for RTCCON11 register *********************/
+#define RTCCON11_RTCWKSLPEN                 ((uint32_t)0x00000400)
+
+/*---------------------------------------------------------------------------------*/
+/*                                     SPI                                         */
+/*---------------------------------------------------------------------------------*/
+/************************ Bit definition for SPIxCON register **********************/
+#define SPIxCON_SPIEN                       ((uint32_t)0x00000001)
+#define SPIxCON_SPISM                       ((uint32_t)0x00000002)
+
+#define SPIxCON_BUSMODE                     ((uint32_t)0x0000000c)
+#define SPIxCON_BUSMODE_0                   ((uint32_t)0x00000004)
+#define SPIxCON_BUSMODE_1                   ((uint32_t)0x00000008)
+
+#define SPIxCON_SPISEL                      ((uint32_t)0x00000010)
+#define SPIxCON_CLKIDS                      ((uint32_t)0x00000020)
+#define SPIxCON_SMPS                        ((uint32_t)0x00000040)
+#define SPIxCON_SPIIE                       ((uint32_t)0x00000080)
+#define SPIxCON_SPILF_EN                    ((uint32_t)0x00000100)
+#define SPIxCON_SPIMBEN                     ((uint32_t)0x00000200)
+#define SPIxCON_SPIOSS                      ((uint32_t)0x00000400)
+#define SPIxCON_HOLDENRX                    ((uint32_t)0x00000800)
+#define SPIxCON_HOLDENTX                    ((uint32_t)0x00001000)
+#define SPIxCON_HOLDENSW                    ((uint32_t)0x00002000)
+#define SPIxCON_SPIPND                      ((uint32_t)0x00010000)
+
+/*---------------------------------------------------------------------------------*/
+/*                                     WDT                                         */
+/*---------------------------------------------------------------------------------*/
+/************************ Bit definition for WDTCON register ***********************/
+#define WDTCON_WDTCLR                       ((uint32_t)0x0000000f)
+#define WDTCON_WDTCLR_0                     ((uint32_t)0x00000001)
+#define WDTCON_WDTCLR_1                     ((uint32_t)0x00000002)
+#define WDTCON_WDTCLR_2                     ((uint32_t)0x00000004)
+#define WDTCON_WDTCLR_3                     ((uint32_t)0x00000008)
+
+#define WDTCON_WDTEN_WR                     ((uint32_t)0x000000f0)
+#define WDTCON_WDTEN_WR_0                   ((uint32_t)0x00000010)
+#define WDTCON_WDTEN_WR_1                   ((uint32_t)0x00000020)
+#define WDTCON_WDTEN_WR_2                   ((uint32_t)0x00000040)
+#define WDTCON_WDTEN_WR_3                   ((uint32_t)0x00000080)
+
+#define WDTCON_RSTEN_WR                     ((uint32_t)0x00000f00)
+#define WDTCON_RSTEN_WR_0                   ((uint32_t)0x00000100)
+#define WDTCON_RSTEN_WR_1                   ((uint32_t)0x00000200)
+#define WDTCON_RSTEN_WR_2                   ((uint32_t)0x00000400)
+#define WDTCON_RSTEN_WR_3                   ((uint32_t)0x00000800)
+
+#define WDTCON_WDTIE_WR                     ((uint32_t)0x0000f000)
+#define WDTCON_WDTIE_WR_0                   ((uint32_t)0x00001000)
+#define WDTCON_WDTIE_WR_1                   ((uint32_t)0x00002000)
+#define WDTCON_WDTIE_WR_2                   ((uint32_t)0x00004000)
+#define WDTCON_WDTIE_WR_3                   ((uint32_t)0x00008000)
+
+#define WDTCON_WDTCSEL_WR                   ((uint32_t)0x000f0000)
+#define WDTCON_WDTCSEL_WR_0                 ((uint32_t)0x00010000)
+#define WDTCON_WDTCSEL_WR_1                 ((uint32_t)0x00020000)
+#define WDTCON_WDTCSEL_WR_2                 ((uint32_t)0x00040000)
+#define WDTCON_WDTCSEL_WR_3                 ((uint32_t)0x00080000)
+
+#define WDTCON_TMRSEL                       ((uint32_t)0x00700000)
+#define WDTCON_TMRSEL_0                     ((uint32_t)0x00100000)
+#define WDTCON_TMRSEL_1                     ((uint32_t)0x00200000)
+#define WDTCON_TMRSEL_2                     ((uint32_t)0x00400000)
+
+#define WDTCON_TMRSEL_WR                    ((uint32_t)0x0f000000)
+#define WDTCON_TMRSEL_WR_0                  ((uint32_t)0x01000000)
+#define WDTCON_TMRSEL_WR_1                  ((uint32_t)0x02000000)
+#define WDTCON_TMRSEL_WR_2                  ((uint32_t)0x04000000)
+#define WDTCON_TMRSEL_WR_3                  ((uint32_t)0x08000000)
+
+#define WDTCON_WDTPND                       ((uint32_t)0x80000000)
+
+/*---------------------------------------------------------------------------------*/
+/*                                    SARADC                                       */
+/*---------------------------------------------------------------------------------*/
+/************************ Bit definition for SADCCON register **********************/
+#define SADCCON_CH0PUEN                     ((uint32_t)0x00000001)
+#define SADCCON_CH1PUEN                     ((uint32_t)0x00000002)
+#define SADCCON_CH2PUEN                     ((uint32_t)0x00000004)
+#define SADCCON_CH3PUEN                     ((uint32_t)0x00000008)
+#define SADCCON_CH4PUEN                     ((uint32_t)0x00000010)
+#define SADCCON_CH5PUEN                     ((uint32_t)0x00000020)
+#define SADCCON_CH6PUEN                     ((uint32_t)0x00000040)
+#define SADCCON_CH7PUEN                     ((uint32_t)0x00000080)
+#define SADCCON_CH8PUEN                     ((uint32_t)0x00000100)
+#define SADCCON_CH9PUEN                     ((uint32_t)0x00000200)
+#define SADCCON_CH10PUEN                    ((uint32_t)0x00000400)
+#define SADCCON_CH11PUEN                    ((uint32_t)0x00000800)
+#define SADCCON_CH12PUEN                    ((uint32_t)0x00001000)
+#define SADCCON_CH13PUEN                    ((uint32_t)0x00002000)
+#define SADCCON_CH14PUEN                    ((uint32_t)0x00004000)
+#define SADCCON_CH15PUEN                    ((uint32_t)0x00008000)
+#define SADCCON_ADCEN                       ((uint32_t)0x00010000)
+#define SADCCON_ADCIE                       ((uint32_t)0x00020000)
+#define SADCCON_ADCANGIOEN                  ((uint32_t)0x00040000)
+#define SADCCON_ADCAEN                      ((uint32_t)0x00080000)
+#define SADCCON_ADCMODE                     ((uint32_t)0x00100000)
+
+/*---------------------------------------------------------------------------------*/
+/*                                    LPWM                                         */
+/*---------------------------------------------------------------------------------*/
+/********************** Bit definition for LPWMSTCON register **********************/
+#define LPWMSTCON_LPWM_DIR                  ((uint32_t)0x00000800)
+
+#define LPWMSTCON_ST_DUTY                   ((uint32_t)0x000007fc)
+#define LPWMSTCON_ST_DUTY_0                 ((uint32_t)0x00000004)
+
+#define LPWMSTCON_BREATH_MODE               ((uint32_t)0x00000002)
+#define LPWMSTCON_LPWM_EN                   ((uint32_t)0x00000001)
+
+/********************** Bit definition for LPWMSWCON register **********************/
+#define LPWMSWCON_DUTY_ON                   ((uint32_t)0x000000ff)
+#define LPWMSWCON_DUTY_ON_0                 ((uint32_t)0x00000001)
+
+/********************** Bit definition for LPWMCMCON register **********************/
+#define LPWMCMCON_SWT_CNTMAX                ((uint32_t)0x00ff0000)
+#define LPWMCMCON_SWT_CNTMAX_0              ((uint32_t)0x00010000)
+
+#define LPWMCMCON_BRT_CNTMAX                ((uint32_t)0x000001ff)
+#define LPWMCMCON_BRT_CNTMAX_0              ((uint32_t)0x00000001)
+
+/********************** Bit definition for LPWMxCON register ***********************/
+#define LPWMxCON_EN                         ((uint32_t)0x02000000)
+
+#define LPWMxCON_REPEAT                     ((uint32_t)0x01fe0000)
+#define LPWMxCON_REPEAT_0                   ((uint32_t)0x00020000)
+
+#define LPWMxCON_STEP                       ((uint32_t)0x0001fe00)
+#define LPWMxCON_STEP_0                     ((uint32_t)0x00000200)
+
+#define LPWMxCON_ST_DUTY                    ((uint32_t)0x000001ff)
+#define LPWMxCON_ST_DUTY_0                  ((uint32_t)0x00000001)
+
+/********************** Bit definition for LPWMHLCON register **********************/
+#define LPWMHLCON_H_EN                      ((uint32_t)0x00200000)
+#define LPWMHLCON_L_EN                      ((uint32_t)0x00100000)
+
+#define LPWMHLCON_H_REPEAT                  ((uint32_t)0x000ffc00)
+#define LPWMHLCON_H_REPEAT_0                ((uint32_t)0x00000400)
+
+#define LPWMHLCON_L_REPEAT                  ((uint32_t)0x000003ff)
+#define LPWMHLCON_L_REPEAT_0                ((uint32_t)0x00000001)
+
+/*********************** Bit definition for LPWMPND register ***********************/
+#define LPWMPND_LPWM_PND                    ((uint32_t)0x00000001)
+
+/*---------------------------------------------------------------------------------*/
+/*                                   KEYSCAN                                       */
+/*---------------------------------------------------------------------------------*/
+/********************* Bit definition for KEYSCAN_CON0 register ********************/
+#define KEYSCAN_CON0_KEYVALID_PND           ((uint32_t)0x80000000)
+#define KEYSCAN_CON0_KEYINVALID_PND         ((uint32_t)0x40000000)
+
+#define KEYSCAN_CON0_KEYPORT_EN             ((uint32_t)0x0000ff00)
+#define KEYSCAN_CON0_KEYPORT_EN_0           ((uint32_t)0x00000100)
+
+#define KEYSCAN_CON0_KEYSCAN_SWRSTN         ((uint32_t)0x00000080)
+#define KEYSCAN_CON0_KEYINVALID_INT_EN      ((uint32_t)0x00000020)
+#define KEYSCAN_CON0_KEYVALID_INT_EN        ((uint32_t)0x00000010)
+#define KEYSCAN_CON0_KEYVALID_WKUP_EN       ((uint32_t)0x00000008)
+#define KEYSCAN_CON0_KEYSCAN_LP             ((uint32_t)0x00000004)
+#define KEYSCAN_CON0_KEYSCAN_MODE           ((uint32_t)0x00000002)
+#define KEYSCAN_CON0_KEYSCAN_EN             ((uint32_t)0x00000001)
+
+/********************* Bit definition for KEYSCAN_CON1 register ********************/
+#define KEYSCAN_CON1_KEYPORT_STAB_TIME      ((uint32_t)0x00ff0000)
+#define KEYSCAN_CON1_KEYPORT_STAB_TIME_0    ((uint32_t)0x00010000)
+
+#define KEYSCAN_CON1_KEY_DEBO_TIMES         ((uint32_t)0x0000ff00)
+#define KEYSCAN_CON1_KEY_DEBO_TIMES_0       ((uint32_t)0x00000100)
+
+#define KEYSCAN_CON1_KEY_WAIT_TIMES         ((uint32_t)0x000000ff)
+#define KEYSCAN_CON1_KEY_WAIT_TIMES_0       ((uint32_t)0x00000001)
+
+/********************* Bit definition for KEYSCAN_CLR register *********************/
+#define KEYSCAN_CLR_KEYVALID_PND_CLR        ((uint32_t)0x80000000)
+#define KEYSCAN_CLR_KEYINVALID_PND_CLR      ((uint32_t)0x40000000)
+
+/********************* Bit definition for KEYSCAN_INFO0 register *******************/
+#define KEYSCAN_INFO0_KD7_KD0               ((uint32_t)0xff000000)
+#define KEYSCAN_INFO0_KD7_KD0_0             ((uint32_t)0x01000000)
+
+#define KEYSCAN_INFO0_KC7_KC0               ((uint32_t)0x00ff0000)
+#define KEYSCAN_INFO0_KC7_KC0_0             ((uint32_t)0x00010000)
+
+#define KEYSCAN_INFO0_KB7_KB0               ((uint32_t)0x0000ff00)
+#define KEYSCAN_INFO0_KB7_KB0_0             ((uint32_t)0x00000100)
+
+#define KEYSCAN_INFO0_KA7_KA0               ((uint32_t)0x000000ff)
+#define KEYSCAN_INFO0_KA7_KA0_0             ((uint32_t)0x00000001)
+
+/********************* Bit definition for KEYSCAN_INFO1 register *******************/
+#define KEYSCAN_INFO1_KH7_KH0               ((uint32_t)0xff000000)
+#define KEYSCAN_INFO1_KH7_KH0_0             ((uint32_t)0x01000000)
+
+#define KEYSCAN_INFO1_KG7_KG0               ((uint32_t)0x00ff0000)
+#define KEYSCAN_INFO1_KG7_KG0_0             ((uint32_t)0x00010000)
+
+#define KEYSCAN_INFO1_KF7_KF0               ((uint32_t)0x0000ff00)
+#define KEYSCAN_INFO1_KF7_KF0_0             ((uint32_t)0x00000100)
+
+#define KEYSCAN_INFO1_KE7_KE0               ((uint32_t)0x000000ff)
+#define KEYSCAN_INFO1_KE7_KE0_0             ((uint32_t)0x00000001)
+
+/********************* Bit definition for KEYSCAN_INFO2 register *******************/
+#define KEYSCAN_INFO2_KI7_KI0               ((uint32_t)0x0000ff00)
+#define KEYSCAN_INFO2_KI7_KI0_0             ((uint32_t)0x00000100)
+
+#define KEYSCAN_INFO2_KJ7_KJ0               ((uint32_t)0x000000ff)
+#define KEYSCAN_INFO2_KJ7_KJ0_0             ((uint32_t)0x00000001)
+
+
+/*---------------------------------------------------------------------------------*/
+/*                                    SDADC                                        */
+/*---------------------------------------------------------------------------------*/
+/*********************** Bit definition for SDADC_CON register *********************/
+#define SDADC_CON_GET_DC_FLAG               ((uint32_t)0x80000000)
+#define SDADC_CON_PHT_SP_SEL                ((uint32_t)0x00008000)
+#define SDADC_CON_ADC_SP_SEL                ((uint32_t)0x00004000)
+#define SDADC_CON_RMDC_FILTER_SEL           ((uint32_t)0x00001000)
+
+#define SDADC_CON_GETDC_SEL                 ((uint32_t)0x00000c00)
+#define SDADC_CON_GETDC_SEL_0               ((uint32_t)0x00000400)
+#define SDADC_CON_GETDC_SEL_1               ((uint32_t)0x00000800)
+
+#define SDADC_CON_RMDC_SEL                  ((uint32_t)0x00000300)
+#define SDADC_CON_RMDC_SEL_0                ((uint32_t)0x00000100)
+#define SDADC_CON_RMDC_SEL_1                ((uint32_t)0x00000200)
+
+#define SDADC_CON_SW_DC_EN                  ((uint32_t)0x00000080)
+#define SDADC_CON_GETDC_EN                  ((uint32_t)0x00000040)
+#define SDADC_CON_RMDC_EN                   ((uint32_t)0x00000020)
+#define SDADC_CON_GAIN_EN                   ((uint32_t)0x00000010)
+
+#define SDADC_CON_FSOUT_SEL                 ((uint32_t)0x0000000e)
+#define SDADC_CON_FSOUT_SEL_0               ((uint32_t)0x00000002)
+#define SDADC_CON_FSOUT_SEL_1               ((uint32_t)0x00000004)
+#define SDADC_CON_FSOUT_SEL_2               ((uint32_t)0x00000008)
+
+#define SDADC_CON_ADC_EN                    ((uint32_t)0x00000001)
+
+/********************* Bit definition for SDADC_GETDCCON register ******************/
+#define SDADC_GETDCCON_GETDC_SIZE           ((uint32_t)0xffff0000)
+#define SDADC_GETDCCON_SW_DC                ((uint32_t)0x0000ffff)
+
+/********************* Bit definition for SDADC_GAINCON register *******************/
+#define SDADC_GAINCON_GAIN                  ((uint32_t)0x0000ffff)
+
+/********************* Bit definition for SDADC_DMACON register ********************/
+#define SDADC_DMACON_SAMPLES_IE             ((uint32_t)0x00000400)
+#define SDADC_DMACON_DMA_ALLDONE_IE         ((uint32_t)0x00000200)
+#define SDADC_DMACON_DMA_HALFDONE_IE        ((uint32_t)0x00000100)
+#define SDADC_DMACON_DMA_EN                 ((uint32_t)0x00000001)
+
+/********************* Bit definition for SDADC_DMAPND register ********************/
+#define SDADC_DMAPND_SAMPLEDONE            ((uint32_t)0x00000004)
+#define SDADC_DMAPND_ALLDONE               ((uint32_t)0x00000002)
+#define SDADC_DMAPND_HALFDONE              ((uint32_t)0x00000001)
+
+/********************* Bit definition for SDADC_DMACPND register *******************/
+#define SDADC_DMACPND_SAMPLEDONE_CLR        ((uint32_t)0x00000004)
+#define SDADC_DMACPND_ALLDONE_CLR           ((uint32_t)0x00000002)
+#define SDADC_DMACPND_HALFDONE_CLR          ((uint32_t)0x00000001)
+
+
+/*---------------------------------------------------------------------------------*/
+/*                                    SDDAC                                        */
+/*---------------------------------------------------------------------------------*/
+/*********************** Bit definition for SDDACCON register **********************/
+#define SDDAC_DAC_EN                        ((uint32_t)0x00000001)
+#define SDDAC_FSIN_SEL                      ((uint32_t)0x0000000e)
+#define SDDAC_FSIN_SEL_0                    ((uint32_t)0x00000002)
+#define SDDAC_OSR_MODE                      ((uint32_t)0x00000010)
+
+/********************* Bit definition for DACDMAINCON register ********************/
+#define SDDAC_DMA_EN                        ((uint32_t)0x00000001)
+#define SDDAC_DMA_MODE                      ((uint32_t)0x00000002)
+#define SDDAC_DMA_HPEND_IE                  ((uint32_t)0x00000004)
+#define SDDAC_DMA_APEND_IE                  ((uint32_t)0x00000008)
+
+/********************* Bit definition for DACDMAINPEND register ********************/
+#define SDDAC_DMA_HALFPEND                  ((uint32_t)0x00000001)
+#define SDDAC_DMA_ALLPEND                   ((uint32_t)0x00000002)
+
+/********************* Bit definition for DACDMAINCPND register ********************/
+#define SDDAC_DMA_HALFPEND_CLR              ((uint32_t)0x00000001)
+#define SDDAC_DMA_ALLPEND_CLR               ((uint32_t)0x00000002)
+
+/*---------------------------------------------------------------------------------*/
+/*                                    LEDC                                         */
+/*---------------------------------------------------------------------------------*/
+/*********************** Bit definition for LEDCCON register ***********************/
+#define LEDC_CON_DMA_INT_EN                 ((uint32_t)0x04000000)
+#define LEDC_CON_OUT_INV                    ((uint32_t)0x02000000)
+#define LEDC_CON_RST_INT_EN                 ((uint32_t)0x01000000)
+
+#define LEDC_CON_BAUD                       ((uint32_t)0x00ff0000)
+
+#define LEDC_CON_DELAY                      ((uint32_t)0x0000ff00)
+
+#define LEDC_CON_IN_FORMAT                  ((uint32_t)0x00000080)
+#define LEDC_CON_INT_EN                     ((uint32_t)0x00000040)
+#define LEDC_CON_IDLE_LEVEL                 ((uint32_t)0x00000020)
+#define LEDC_CON_VLD_INV                    ((uint32_t)0x00000010)
+
+#define LEDC_CON_BYTE_INV                   ((uint32_t)0x0000000c)
+#define LEDC_CON_BYTE_INV_0                 ((uint32_t)0x00000004)
+#define LEDC_CON_BYTE_INV_1                 ((uint32_t)0x00000008)
+
+#define LEDC_CON_LEDC_KICK                  ((uint32_t)0x00000002)
+#define LEDC_CON_EN                         ((uint32_t)0x00000001)
+
+/*********************** Bit definition for LEDCPEND register **********************/
+#define LEDC_PEND_DMA_PND                   ((uint32_t)0x00000004)
+#define LEDC_PEND_RST_PND                   ((uint32_t)0x00000002)
+#define LEDC_PEND_LEDC_PND                  ((uint32_t)0x00000001)
+
+
+/*---------------------------------------------------------------------------------*/
+/*                                    TICK                                         */
+/*---------------------------------------------------------------------------------*/
+/*********************** Bit definition for TICK0CON register **********************/
+#define TICK_CON_TPND                       ((uint32_t)0x00000200)
+#define TICK_CON_TIE                        ((uint32_t)0x00000080)
+#define TICK_CON_INCSRC                     ((uint32_t)0x00000040)
+
+#define TICK_CON_INCSEL                     ((uint32_t)0x0000000c)
+#define TICK_CON_INCSEL_0                   ((uint32_t)0x00000004)
+#define TICK_CON_INCSEL_1                   ((uint32_t)0x00000008)
+
+#define TICK_CON_EN                         ((uint32_t)0x00000001)
+
+/*********************** Bit definition for TICK0CPND register *********************/
+#define TICK_CPND_TPCLR                     ((uint32_t)0x00000200)
+
+
+/*---------------------------------------------------------------------------------*/
+/*                                    TIM                                          */
+/*---------------------------------------------------------------------------------*/
+/*******************  Bit definition for TIM_CR1 register  ********************/
+#define  TIM_CR1_CEN                         ((uint16_t)0x0001)            /*!< Counter enable */
+#define  TIM_CR1_UDIS                        ((uint16_t)0x0002)            /*!< Update disable */
+#define  TIM_CR1_URS                         ((uint16_t)0x0004)            /*!< Update request source */
+#define  TIM_CR1_OPM                         ((uint16_t)0x0008)            /*!< One pulse mode */
+#define  TIM_CR1_DIR                         ((uint16_t)0x0010)            /*!< Direction */
+
+#define  TIM_CR1_CMS                         ((uint16_t)0x0060)            /*!< CMS[1:0] bits (Center-aligned mode selection) */
+#define  TIM_CR1_CMS_0                       ((uint16_t)0x0020)            /*!< Bit 0 */
+#define  TIM_CR1_CMS_1                       ((uint16_t)0x0040)            /*!< Bit 1 */
+
+#define  TIM_CR1_ARPE                        ((uint16_t)0x0080)            /*!< Auto-reload preload enable */
+
+#define  TIM_CR1_CKD                         ((uint16_t)0x0300)            /*!< CKD[1:0] bits (clock division) */
+#define  TIM_CR1_CKD_0                       ((uint16_t)0x0100)            /*!< Bit 0 */
+#define  TIM_CR1_CKD_1                       ((uint16_t)0x0200)            /*!< Bit 1 */
+
+/*******************  Bit definition for TIM_CR2 register  ********************/
+#define  TIM_CR2_CCPC                        ((uint16_t)0x0001)            /*!< Capture/Compare Preloaded Control */
+#define  TIM_CR2_CCUS                        ((uint16_t)0x0004)            /*!< Capture/Compare Control Update Selection */
+#define  TIM_CR2_CCDS                        ((uint16_t)0x0008)            /*!< Capture/Compare DMA Selection */
+
+#define  TIM_CR2_MMS                         ((uint16_t)0x0070)            /*!< MMS[2:0] bits (Master Mode Selection) */
+#define  TIM_CR2_MMS_0                       ((uint16_t)0x0010)            /*!< Bit 0 */
+#define  TIM_CR2_MMS_1                       ((uint16_t)0x0020)            /*!< Bit 1 */
+#define  TIM_CR2_MMS_2                       ((uint16_t)0x0040)            /*!< Bit 2 */
+
+#define  TIM_CR2_TI1S                        ((uint16_t)0x0080)            /*!< TI1 Selection */
+#define  TIM_CR2_OIS1                        ((uint16_t)0x0100)            /*!< Output Idle state 1 (OC1 output) */
+#define  TIM_CR2_OIS1N                       ((uint16_t)0x0200)            /*!< Output Idle state 1 (OC1N output) */
+#define  TIM_CR2_OIS2                        ((uint16_t)0x0400)            /*!< Output Idle state 2 (OC2 output) */
+#define  TIM_CR2_OIS2N                       ((uint16_t)0x0800)            /*!< Output Idle state 2 (OC2N output) */
+#define  TIM_CR2_OIS3                        ((uint16_t)0x1000)            /*!< Output Idle state 3 (OC3 output) */
+#define  TIM_CR2_OIS3N                       ((uint16_t)0x2000)            /*!< Output Idle state 3 (OC3N output) */
+#define  TIM_CR2_OIS4                        ((uint16_t)0x4000)            /*!< Output Idle state 4 (OC4 output) */
+
+/*******************  Bit definition for TIM_SMCR register  *******************/
+#define  TIM_SMCR_SMS                        ((uint16_t)0x0007)            /*!< SMS[2:0] bits (Slave mode selection) */
+#define  TIM_SMCR_SMS_0                      ((uint16_t)0x0001)            /*!< Bit 0 */
+#define  TIM_SMCR_SMS_1                      ((uint16_t)0x0002)            /*!< Bit 1 */
+#define  TIM_SMCR_SMS_2                      ((uint16_t)0x0004)            /*!< Bit 2 */
+
+#define  TIM_SMCR_TS                         ((uint16_t)0x0070)            /*!< TS[2:0] bits (Trigger selection) */
+#define  TIM_SMCR_TS_0                       ((uint16_t)0x0010)            /*!< Bit 0 */
+#define  TIM_SMCR_TS_1                       ((uint16_t)0x0020)            /*!< Bit 1 */
+#define  TIM_SMCR_TS_2                       ((uint16_t)0x0040)            /*!< Bit 2 */
+
+#define  TIM_SMCR_MSM                        ((uint16_t)0x0080)            /*!< Master/slave mode */
+
+#define  TIM_SMCR_ETF                        ((uint16_t)0x0F00)            /*!< ETF[3:0] bits (External trigger filter) */
+#define  TIM_SMCR_ETF_0                      ((uint16_t)0x0100)            /*!< Bit 0 */
+#define  TIM_SMCR_ETF_1                      ((uint16_t)0x0200)            /*!< Bit 1 */
+#define  TIM_SMCR_ETF_2                      ((uint16_t)0x0400)            /*!< Bit 2 */
+#define  TIM_SMCR_ETF_3                      ((uint16_t)0x0800)            /*!< Bit 3 */
+
+#define  TIM_SMCR_ETPS                       ((uint16_t)0x3000)            /*!< ETPS[1:0] bits (External trigger prescaler) */
+#define  TIM_SMCR_ETPS_0                     ((uint16_t)0x1000)            /*!< Bit 0 */
+#define  TIM_SMCR_ETPS_1                     ((uint16_t)0x2000)            /*!< Bit 1 */
+
+#define  TIM_SMCR_ECE                        ((uint16_t)0x4000)            /*!< External clock enable */
+#define  TIM_SMCR_ETP                        ((uint16_t)0x8000)            /*!< External trigger polarity */
+
+/*******************  Bit definition for TIM_DIER register  *******************/
+#define  TIM_DIER_UIE                        ((uint16_t)0x0001)            /*!< Update interrupt enable */
+#define  TIM_DIER_CC1IE                      ((uint16_t)0x0002)            /*!< Capture/Compare 1 interrupt enable */
+#define  TIM_DIER_CC2IE                      ((uint16_t)0x0004)            /*!< Capture/Compare 2 interrupt enable */
+#define  TIM_DIER_CC3IE                      ((uint16_t)0x0008)            /*!< Capture/Compare 3 interrupt enable */
+#define  TIM_DIER_CC4IE                      ((uint16_t)0x0010)            /*!< Capture/Compare 4 interrupt enable */
+#define  TIM_DIER_COMIE                      ((uint16_t)0x0020)            /*!< COM interrupt enable */
+#define  TIM_DIER_TIE                        ((uint16_t)0x0040)            /*!< Trigger interrupt enable */
+#define  TIM_DIER_BIE                        ((uint16_t)0x0080)            /*!< Break interrupt enable */
+#define  TIM_DIER_UDE                        ((uint16_t)0x0100)            /*!< Update DMA request enable */
+#define  TIM_DIER_CC1DE                      ((uint16_t)0x0200)            /*!< Capture/Compare 1 DMA request enable */
+#define  TIM_DIER_CC2DE                      ((uint16_t)0x0400)            /*!< Capture/Compare 2 DMA request enable */
+#define  TIM_DIER_CC3DE                      ((uint16_t)0x0800)            /*!< Capture/Compare 3 DMA request enable */
+#define  TIM_DIER_CC4DE                      ((uint16_t)0x1000)            /*!< Capture/Compare 4 DMA request enable */
+#define  TIM_DIER_COMDE                      ((uint16_t)0x2000)            /*!< COM DMA request enable */
+#define  TIM_DIER_TDE                        ((uint16_t)0x4000)            /*!< Trigger DMA request enable */
+
+/********************  Bit definition for TIM_SR register  ********************/
+#define  TIM_SR_UIF                          ((uint16_t)0x0001)            /*!< Update interrupt Flag */
+#define  TIM_SR_CC1IF                        ((uint16_t)0x0002)            /*!< Capture/Compare 1 interrupt Flag */
+#define  TIM_SR_CC2IF                        ((uint16_t)0x0004)            /*!< Capture/Compare 2 interrupt Flag */
+#define  TIM_SR_CC3IF                        ((uint16_t)0x0008)            /*!< Capture/Compare 3 interrupt Flag */
+#define  TIM_SR_CC4IF                        ((uint16_t)0x0010)            /*!< Capture/Compare 4 interrupt Flag */
+#define  TIM_SR_COMIF                        ((uint16_t)0x0020)            /*!< COM interrupt Flag */
+#define  TIM_SR_TIF                          ((uint16_t)0x0040)            /*!< Trigger interrupt Flag */
+#define  TIM_SR_BIF                          ((uint16_t)0x0080)            /*!< Break interrupt Flag */
+#define  TIM_SR_CC1OF                        ((uint16_t)0x0200)            /*!< Capture/Compare 1 Overcapture Flag */
+#define  TIM_SR_CC2OF                        ((uint16_t)0x0400)            /*!< Capture/Compare 2 Overcapture Flag */
+#define  TIM_SR_CC3OF                        ((uint16_t)0x0800)            /*!< Capture/Compare 3 Overcapture Flag */
+#define  TIM_SR_CC4OF                        ((uint16_t)0x1000)            /*!< Capture/Compare 4 Overcapture Flag */
+
+/*******************  Bit definition for TIM_EGR register  ********************/
+#define  TIM_EGR_UG                          ((uint8_t)0x01)               /*!< Update Generation */
+#define  TIM_EGR_CC1G                        ((uint8_t)0x02)               /*!< Capture/Compare 1 Generation */
+#define  TIM_EGR_CC2G                        ((uint8_t)0x04)               /*!< Capture/Compare 2 Generation */
+#define  TIM_EGR_CC3G                        ((uint8_t)0x08)               /*!< Capture/Compare 3 Generation */
+#define  TIM_EGR_CC4G                        ((uint8_t)0x10)               /*!< Capture/Compare 4 Generation */
+#define  TIM_EGR_COMG                        ((uint8_t)0x20)               /*!< Capture/Compare Control Update Generation */
+#define  TIM_EGR_TG                          ((uint8_t)0x40)               /*!< Trigger Generation */
+#define  TIM_EGR_BG                          ((uint8_t)0x80)               /*!< Break Generation */
+
+/******************  Bit definition for TIM_CCMR1 register  *******************/
+#define  TIM_CCMR1_CC1S                      ((uint16_t)0x0003)            /*!< CC1S[1:0] bits (Capture/Compare 1 Selection) */
+#define  TIM_CCMR1_CC1S_0                    ((uint16_t)0x0001)            /*!< Bit 0 */
+#define  TIM_CCMR1_CC1S_1                    ((uint16_t)0x0002)            /*!< Bit 1 */
+
+#define  TIM_CCMR1_OC1FE                     ((uint16_t)0x0004)            /*!< Output Compare 1 Fast enable */
+#define  TIM_CCMR1_OC1PE                     ((uint16_t)0x0008)            /*!< Output Compare 1 Preload enable */
+
+#define  TIM_CCMR1_OC1M                      ((uint16_t)0x0070)            /*!< OC1M[2:0] bits (Output Compare 1 Mode) */
+#define  TIM_CCMR1_OC1M_0                    ((uint16_t)0x0010)            /*!< Bit 0 */
+#define  TIM_CCMR1_OC1M_1                    ((uint16_t)0x0020)            /*!< Bit 1 */
+#define  TIM_CCMR1_OC1M_2                    ((uint16_t)0x0040)            /*!< Bit 2 */
+
+#define  TIM_CCMR1_OC1CE                     ((uint16_t)0x0080)            /*!< Output Compare 1Clear Enable */
+
+#define  TIM_CCMR1_CC2S                      ((uint16_t)0x0300)            /*!< CC2S[1:0] bits (Capture/Compare 2 Selection) */
+#define  TIM_CCMR1_CC2S_0                    ((uint16_t)0x0100)            /*!< Bit 0 */
+#define  TIM_CCMR1_CC2S_1                    ((uint16_t)0x0200)            /*!< Bit 1 */
+
+#define  TIM_CCMR1_OC2FE                     ((uint16_t)0x0400)            /*!< Output Compare 2 Fast enable */
+#define  TIM_CCMR1_OC2PE                     ((uint16_t)0x0800)            /*!< Output Compare 2 Preload enable */
+
+#define  TIM_CCMR1_OC2M                      ((uint16_t)0x7000)            /*!< OC2M[2:0] bits (Output Compare 2 Mode) */
+#define  TIM_CCMR1_OC2M_0                    ((uint16_t)0x1000)            /*!< Bit 0 */
+#define  TIM_CCMR1_OC2M_1                    ((uint16_t)0x2000)            /*!< Bit 1 */
+#define  TIM_CCMR1_OC2M_2                    ((uint16_t)0x4000)            /*!< Bit 2 */
+
+#define  TIM_CCMR1_OC2CE                     ((uint16_t)0x8000)            /*!< Output Compare 2 Clear Enable */
+
+/*----------------------------------------------------------------------------*/
+
+#define  TIM_CCMR1_IC1PSC                    ((uint16_t)0x000C)            /*!< IC1PSC[1:0] bits (Input Capture 1 Prescaler) */
+#define  TIM_CCMR1_IC1PSC_0                  ((uint16_t)0x0004)            /*!< Bit 0 */
+#define  TIM_CCMR1_IC1PSC_1                  ((uint16_t)0x0008)            /*!< Bit 1 */
+
+#define  TIM_CCMR1_IC1F                      ((uint16_t)0x00F0)            /*!< IC1F[3:0] bits (Input Capture 1 Filter) */
+#define  TIM_CCMR1_IC1F_0                    ((uint16_t)0x0010)            /*!< Bit 0 */
+#define  TIM_CCMR1_IC1F_1                    ((uint16_t)0x0020)            /*!< Bit 1 */
+#define  TIM_CCMR1_IC1F_2                    ((uint16_t)0x0040)            /*!< Bit 2 */
+#define  TIM_CCMR1_IC1F_3                    ((uint16_t)0x0080)            /*!< Bit 3 */
+
+#define  TIM_CCMR1_IC2PSC                    ((uint16_t)0x0C00)            /*!< IC2PSC[1:0] bits (Input Capture 2 Prescaler) */
+#define  TIM_CCMR1_IC2PSC_0                  ((uint16_t)0x0400)            /*!< Bit 0 */
+#define  TIM_CCMR1_IC2PSC_1                  ((uint16_t)0x0800)            /*!< Bit 1 */
+
+#define  TIM_CCMR1_IC2F                      ((uint16_t)0xF000)            /*!< IC2F[3:0] bits (Input Capture 2 Filter) */
+#define  TIM_CCMR1_IC2F_0                    ((uint16_t)0x1000)            /*!< Bit 0 */
+#define  TIM_CCMR1_IC2F_1                    ((uint16_t)0x2000)            /*!< Bit 1 */
+#define  TIM_CCMR1_IC2F_2                    ((uint16_t)0x4000)            /*!< Bit 2 */
+#define  TIM_CCMR1_IC2F_3                    ((uint16_t)0x8000)            /*!< Bit 3 */
+
+/******************  Bit definition for TIM_CCMR2 register  *******************/
+#define  TIM_CCMR2_CC3S                      ((uint16_t)0x0003)            /*!< CC3S[1:0] bits (Capture/Compare 3 Selection) */
+#define  TIM_CCMR2_CC3S_0                    ((uint16_t)0x0001)            /*!< Bit 0 */
+#define  TIM_CCMR2_CC3S_1                    ((uint16_t)0x0002)            /*!< Bit 1 */
+
+#define  TIM_CCMR2_OC3FE                     ((uint16_t)0x0004)            /*!< Output Compare 3 Fast enable */
+#define  TIM_CCMR2_OC3PE                     ((uint16_t)0x0008)            /*!< Output Compare 3 Preload enable */
+
+#define  TIM_CCMR2_OC3M                      ((uint16_t)0x0070)            /*!< OC3M[2:0] bits (Output Compare 3 Mode) */
+#define  TIM_CCMR2_OC3M_0                    ((uint16_t)0x0010)            /*!< Bit 0 */
+#define  TIM_CCMR2_OC3M_1                    ((uint16_t)0x0020)            /*!< Bit 1 */
+#define  TIM_CCMR2_OC3M_2                    ((uint16_t)0x0040)            /*!< Bit 2 */
+
+#define  TIM_CCMR2_OC3CE                     ((uint16_t)0x0080)            /*!< Output Compare 3 Clear Enable */
+
+#define  TIM_CCMR2_CC4S                      ((uint16_t)0x0300)            /*!< CC4S[1:0] bits (Capture/Compare 4 Selection) */
+#define  TIM_CCMR2_CC4S_0                    ((uint16_t)0x0100)            /*!< Bit 0 */
+#define  TIM_CCMR2_CC4S_1                    ((uint16_t)0x0200)            /*!< Bit 1 */
+
+#define  TIM_CCMR2_OC4FE                     ((uint16_t)0x0400)            /*!< Output Compare 4 Fast enable */
+#define  TIM_CCMR2_OC4PE                     ((uint16_t)0x0800)            /*!< Output Compare 4 Preload enable */
+
+#define  TIM_CCMR2_OC4M                      ((uint16_t)0x7000)            /*!< OC4M[2:0] bits (Output Compare 4 Mode) */
+#define  TIM_CCMR2_OC4M_0                    ((uint16_t)0x1000)            /*!< Bit 0 */
+#define  TIM_CCMR2_OC4M_1                    ((uint16_t)0x2000)            /*!< Bit 1 */
+#define  TIM_CCMR2_OC4M_2                    ((uint16_t)0x4000)            /*!< Bit 2 */
+
+#define  TIM_CCMR2_OC4CE                     ((uint16_t)0x8000)            /*!< Output Compare 4 Clear Enable */
+
+/*----------------------------------------------------------------------------*/
+
+#define  TIM_CCMR2_IC3PSC                    ((uint16_t)0x000C)            /*!< IC3PSC[1:0] bits (Input Capture 3 Prescaler) */
+#define  TIM_CCMR2_IC3PSC_0                  ((uint16_t)0x0004)            /*!< Bit 0 */
+#define  TIM_CCMR2_IC3PSC_1                  ((uint16_t)0x0008)            /*!< Bit 1 */
+
+#define  TIM_CCMR2_IC3F                      ((uint16_t)0x00F0)            /*!< IC3F[3:0] bits (Input Capture 3 Filter) */
+#define  TIM_CCMR2_IC3F_0                    ((uint16_t)0x0010)            /*!< Bit 0 */
+#define  TIM_CCMR2_IC3F_1                    ((uint16_t)0x0020)            /*!< Bit 1 */
+#define  TIM_CCMR2_IC3F_2                    ((uint16_t)0x0040)            /*!< Bit 2 */
+#define  TIM_CCMR2_IC3F_3                    ((uint16_t)0x0080)            /*!< Bit 3 */
+
+#define  TIM_CCMR2_IC4PSC                    ((uint16_t)0x0C00)            /*!< IC4PSC[1:0] bits (Input Capture 4 Prescaler) */
+#define  TIM_CCMR2_IC4PSC_0                  ((uint16_t)0x0400)            /*!< Bit 0 */
+#define  TIM_CCMR2_IC4PSC_1                  ((uint16_t)0x0800)            /*!< Bit 1 */
+
+#define  TIM_CCMR2_IC4F                      ((uint16_t)0xF000)            /*!< IC4F[3:0] bits (Input Capture 4 Filter) */
+#define  TIM_CCMR2_IC4F_0                    ((uint16_t)0x1000)            /*!< Bit 0 */
+#define  TIM_CCMR2_IC4F_1                    ((uint16_t)0x2000)            /*!< Bit 1 */
+#define  TIM_CCMR2_IC4F_2                    ((uint16_t)0x4000)            /*!< Bit 2 */
+#define  TIM_CCMR2_IC4F_3                    ((uint16_t)0x8000)            /*!< Bit 3 */
+
+/*******************  Bit definition for TIM_CCER register  *******************/
+#define  TIM_CCER_CC1E                       ((uint16_t)0x0001)            /*!< Capture/Compare 1 output enable */
+#define  TIM_CCER_CC1P                       ((uint16_t)0x0002)            /*!< Capture/Compare 1 output Polarity */
+#define  TIM_CCER_CC1NE                      ((uint16_t)0x0004)            /*!< Capture/Compare 1 Complementary output enable */
+#define  TIM_CCER_CC1NP                      ((uint16_t)0x0008)            /*!< Capture/Compare 1 Complementary output Polarity */
+#define  TIM_CCER_CC2E                       ((uint16_t)0x0010)            /*!< Capture/Compare 2 output enable */
+#define  TIM_CCER_CC2P                       ((uint16_t)0x0020)            /*!< Capture/Compare 2 output Polarity */
+#define  TIM_CCER_CC2NE                      ((uint16_t)0x0040)            /*!< Capture/Compare 2 Complementary output enable */
+#define  TIM_CCER_CC2NP                      ((uint16_t)0x0080)            /*!< Capture/Compare 2 Complementary output Polarity */
+#define  TIM_CCER_CC3E                       ((uint16_t)0x0100)            /*!< Capture/Compare 3 output enable */
+#define  TIM_CCER_CC3P                       ((uint16_t)0x0200)            /*!< Capture/Compare 3 output Polarity */
+#define  TIM_CCER_CC3NE                      ((uint16_t)0x0400)            /*!< Capture/Compare 3 Complementary output enable */
+#define  TIM_CCER_CC3NP                      ((uint16_t)0x0800)            /*!< Capture/Compare 3 Complementary output Polarity */
+#define  TIM_CCER_CC4E                       ((uint16_t)0x1000)            /*!< Capture/Compare 4 output enable */
+#define  TIM_CCER_CC4P                       ((uint16_t)0x2000)            /*!< Capture/Compare 4 output Polarity */
+#define  TIM_CCER_CC4NP                      ((uint16_t)0x8000)            /*!< Capture/Compare 4 Complementary output Polarity */
+
+/*******************  Bit definition for TIM_CNT register  ********************/
+#define  TIM_CNT_CNT                         ((uint16_t)0xFFFF)            /*!< Counter Value */
+
+/*******************  Bit definition for TIM_PSC register  ********************/
+#define  TIM_PSC_PSC                         ((uint16_t)0xFFFF)            /*!< Prescaler Value */
+
+/*******************  Bit definition for TIM_ARR register  ********************/
+#define  TIM_ARR_ARR                         ((uint16_t)0xFFFF)            /*!< actual auto-reload Value */
+
+/*******************  Bit definition for TIM_RCR register  ********************/
+#define  TIM_RCR_REP                         ((uint8_t)0xFF)               /*!< Repetition Counter Value */
+
+/*******************  Bit definition for TIM_CCR1 register  *******************/
+#define  TIM_CCR1_CCR1                       ((uint16_t)0xFFFF)            /*!< Capture/Compare 1 Value */
+
+/*******************  Bit definition for TIM_CCR2 register  *******************/
+#define  TIM_CCR2_CCR2                       ((uint16_t)0xFFFF)            /*!< Capture/Compare 2 Value */
+
+/*******************  Bit definition for TIM_CCR3 register  *******************/
+#define  TIM_CCR3_CCR3                       ((uint16_t)0xFFFF)            /*!< Capture/Compare 3 Value */
+
+/*******************  Bit definition for TIM_CCR4 register  *******************/
+#define  TIM_CCR4_CCR4                       ((uint16_t)0xFFFF)            /*!< Capture/Compare 4 Value */
+
+/*******************  Bit definition for TIM_BDTR register  *******************/
+#define  TIM_BDTR_DTG                        ((uint16_t)0x00FF)            /*!< DTG[0:7] bits (Dead-Time Generator set-up) */
+#define  TIM_BDTR_DTG_0                      ((uint16_t)0x0001)            /*!< Bit 0 */
+#define  TIM_BDTR_DTG_1                      ((uint16_t)0x0002)            /*!< Bit 1 */
+#define  TIM_BDTR_DTG_2                      ((uint16_t)0x0004)            /*!< Bit 2 */
+#define  TIM_BDTR_DTG_3                      ((uint16_t)0x0008)            /*!< Bit 3 */
+#define  TIM_BDTR_DTG_4                      ((uint16_t)0x0010)            /*!< Bit 4 */
+#define  TIM_BDTR_DTG_5                      ((uint16_t)0x0020)            /*!< Bit 5 */
+#define  TIM_BDTR_DTG_6                      ((uint16_t)0x0040)            /*!< Bit 6 */
+#define  TIM_BDTR_DTG_7                      ((uint16_t)0x0080)            /*!< Bit 7 */
+
+#define  TIM_BDTR_LOCK                       ((uint16_t)0x0300)            /*!< LOCK[1:0] bits (Lock Configuration) */
+#define  TIM_BDTR_LOCK_0                     ((uint16_t)0x0100)            /*!< Bit 0 */
+#define  TIM_BDTR_LOCK_1                     ((uint16_t)0x0200)            /*!< Bit 1 */
+
+#define  TIM_BDTR_OSSI                       ((uint16_t)0x0400)            /*!< Off-State Selection for Idle mode */
+#define  TIM_BDTR_OSSR                       ((uint16_t)0x0800)            /*!< Off-State Selection for Run mode */
+#define  TIM_BDTR_BKE                        ((uint16_t)0x1000)            /*!< Break enable */
+#define  TIM_BDTR_BKP                        ((uint16_t)0x2000)            /*!< Break Polarity */
+#define  TIM_BDTR_AOE                        ((uint16_t)0x4000)            /*!< Automatic Output enable */
+#define  TIM_BDTR_MOE                        ((uint16_t)0x8000)            /*!< Main Output enable */
+
+/*******************  Bit definition for TIM_DCR register  ********************/
+#define  TIM_DCR_DBA                         ((uint16_t)0x001F)            /*!< DBA[4:0] bits (DMA Base Address) */
+#define  TIM_DCR_DBA_0                       ((uint16_t)0x0001)            /*!< Bit 0 */
+#define  TIM_DCR_DBA_1                       ((uint16_t)0x0002)            /*!< Bit 1 */
+#define  TIM_DCR_DBA_2                       ((uint16_t)0x0004)            /*!< Bit 2 */
+#define  TIM_DCR_DBA_3                       ((uint16_t)0x0008)            /*!< Bit 3 */
+#define  TIM_DCR_DBA_4                       ((uint16_t)0x0010)            /*!< Bit 4 */
+
+#define  TIM_DCR_DBL                         ((uint16_t)0x1F00)            /*!< DBL[4:0] bits (DMA Burst Length) */
+#define  TIM_DCR_DBL_0                       ((uint16_t)0x0100)            /*!< Bit 0 */
+#define  TIM_DCR_DBL_1                       ((uint16_t)0x0200)            /*!< Bit 1 */
+#define  TIM_DCR_DBL_2                       ((uint16_t)0x0400)            /*!< Bit 2 */
+#define  TIM_DCR_DBL_3                       ((uint16_t)0x0800)            /*!< Bit 3 */
+#define  TIM_DCR_DBL_4                       ((uint16_t)0x1000)            /*!< Bit 4 */
+
+/*******************  Bit definition for TIM_DMAR register  *******************/
+#define  TIM_DMAR_DMAB                       ((uint16_t)0xFFFF)            /*!< DMA register for burst accesses */
+
+/*******************  Bit definition for TIM_SARAD register  *******************/
+#define  TIM_SARAD_MASK                      ((uint16_t)0xFFFF)            /*!< TIM_SARAD register for burst accesses */
+#define  TIM_SARAD_CH0                       ((uint16_t)0x0001)            /*!< Bit 0 */
+#define  TIM_SARAD_CH1                       ((uint16_t)0x0002)            /*!< Bit 1 */
+#define  TIM_SARAD_CH2                       ((uint16_t)0x0004)            /*!< Bit 2 */
+#define  TIM_SARAD_CH3                       ((uint16_t)0x0008)            /*!< Bit 3 */
+#define  TIM_SARAD_CH4                       ((uint16_t)0x0010)            /*!< Bit 4 */
+#define  TIM_SARAD_CH5                       ((uint16_t)0x0020)            /*!< Bit 5 */
+#define  TIM_SARAD_CH6                       ((uint16_t)0x0040)            /*!< Bit 6 */
+#define  TIM_SARAD_CH7                       ((uint16_t)0x0080)            /*!< Bit 7 */
+#define  TIM_SARAD_CH8                       ((uint16_t)0x0100)            /*!< Bit 8 */
+#define  TIM_SARAD_CH9                       ((uint16_t)0x0200)            /*!< Bit 9 */
+#define  TIM_SARAD_CH10                      ((uint16_t)0x0400)            /*!< Bit 10 */
+#define  TIM_SARAD_CH11                      ((uint16_t)0x0800)            /*!< Bit 11 */
+#define  TIM_SARAD_CH12                      ((uint16_t)0x1000)            /*!< Bit 12 */
+#define  TIM_SARAD_CH13                      ((uint16_t)0x2000)            /*!< Bit 13 */
+#define  TIM_SARAD_CH14                      ((uint16_t)0x4000)            /*!< Bit 14 */
+#define  TIM_SARAD_CH15                      ((uint16_t)0x8000)            /*!< Bit 15 */
+#define  TIM_SARAD_TRGOEN                    ((uint32_t)0x10000)           /*!< Bit 16 */
+
+
+/**
+ * @brief GPIO Register Structure
+ */
+typedef struct {
+    volatile u32 io_set;
+    volatile u32 io_clr;
+    volatile u32 data;
+    volatile u32 dir;
+    volatile u32 de;
+    volatile u32 fen;
+    volatile u32 fdir;
+    volatile u32 drv;
+    volatile u32 pupd[6];
+} gpio_typedef;
+
+/**
+ * @brief Function and IO Mapping Register Structure
+ */
+typedef struct {
+    volatile u32 func_output_map[8];
+    volatile u32 func_input_map[7];
+} func_map_typedef;
+
+/**
+ * @brief Timer Register Structure
+ */
+typedef struct {
+    volatile u32 con;
+    volatile u32 cpnd;
+    volatile u32 cnt;
+    volatile u32 period;
+    volatile u32 capture_val;
+    volatile u32 duty0;
+    volatile u32 duty1;
+    volatile u32 duty2;
+    volatile u32 psc;
+} tmr_typedef;
+
+/**
+ * @brief Uart Register Structure
+ */
+typedef struct {
+    volatile u32 con;
+    volatile u32 cpnd;
+    volatile u32 baud;
+    volatile u32 data;
+} uart_typedef;
+
+/**
+ * @brief High Speed UART Register Structure
+ */
+typedef struct {
+    volatile u32 con;
+    volatile u32 cpnd;
+    volatile u32 baud;
+    volatile u32 data;
+    volatile u32 tx_cnt;
+    volatile u32 tx_adr;
+    volatile u32 rx_cnt;
+    const    u32 reserved0;
+    const    u32 reserved1;
+    volatile u32 rx_adr;
+    volatile u32 fifo_cnt;
+    volatile u32 fifo;
+    volatile u32 fifo_adr;
+    volatile u32 tmr_cnt;
+    volatile u32 flow_ctrl;
+} hsuart_typedef;
+
+/**
+ * @brief IIC Register Structure
+ */
+typedef struct {
+    volatile u32 con0;
+    volatile u32 con1;
+    volatile u32 cmd_addr;
+    volatile u32 data;
+    volatile u32 dma_addr;
+    volatile u32 dma_cnt;
+    volatile u32 slave_sta;
+} iic_typedef;
+
+/**
+ * @brief SPI Register Structure
+ */
+typedef struct {
+    volatile u32 con;
+    volatile u32 buf;
+    volatile u32 baud;
+    volatile u32 cpnd;
+    volatile u32 dma_cnt;
+    volatile u32 dma_adr;
+} spi_typedef;
+
+/**
+ * @brief WDT Register Structure
+ */
+typedef struct {
+    volatile u32 con;
+} wdt_typedef;
+
+/**
+ * @brief SARADC Register Structure
+ */
+typedef struct {
+    volatile u32 dat[16];
+    volatile u32 con;
+    volatile u32 ch;
+    volatile u32 cst;
+    volatile u32 baud;
+    const    u32 reserved0;
+    const    u32 reserved1;
+    const    u32 reserved2;
+    const    u32 reserved3;
+    const    u32 reserved4;
+    volatile u32 ch_int;
+    volatile u32 ch_pnd;
+} sadc_typedef;
+
+/**
+ * @brief LPWM Register Structure
+ */
+typedef struct {
+    volatile u32 start_con;
+    volatile u32 switch_con;
+    volatile u32 cnt_max_con;
+    volatile u32 stageA_con;
+    volatile u32 stageB_con;
+    volatile u32 stageC_con;
+    volatile u32 stageD_con;
+    volatile u32 stageE_con;
+    volatile u32 stageF_con;
+    volatile u32 stageHL_con;
+    volatile u32 pend;
+} lpwm_typedef;
+
+/**
+ * @brief KEYSCAN Register Structure
+ */
+typedef struct {
+    volatile u32 con0;
+    volatile u32 con1;
+    volatile u32 clr;
+    volatile u32 info0;
+    volatile u32 info1;
+    volatile u32 info2;
+} keyscan_typedef;
+
+/**
+ * @brief IRRX Register Structure
+ */
+typedef struct {
+    // IR RX Control Register
+    volatile u32 con;
+    // IR RX Data Register
+    volatile u32 rxdata;
+    // IR RX Clear Pending Register
+    volatile u32 cpnd;
+    // IR RX Error Config Register0
+    volatile u32 err0;
+    // IR RX Error Config Register1
+    volatile u32 err1;
+    // IR RX Period Config Register0
+    volatile u32 period0;
+    // IR RX Period Config Register1
+    volatile u32 period1;
+} irrx_typedef;
+
+/**
+ * @brief IRTX Register Structure
+ */
+typedef struct {
+    // IR One Code Time Register
+    volatile u32 otime;
+    // IR One Zero Time Register
+    volatile u32 ztime;
+    // IR Start Code Time Register
+    volatile u32 stime;
+    // IR Repeat Code Time Register
+    volatile u32 rtime;
+    // IR Repeat Code Control Register
+    volatile u32 rctrl;
+    // IR TX Control Register
+    volatile u32 con;
+    // IR TX Data Register
+    volatile u32 txdata;
+    // IR TX Data Length Register
+    volatile u32 txlen;
+    // IR TX Pending Register
+    volatile u32 pend;
+    // IR TX DMA Control Register
+    volatile u32 dma_con;
+    // IR TX DMA Input Address Register
+    volatile u32 dma_iadr;
+    // IR TX DMA Input Size Register
+    volatile u32 dma_isize;
+    // IR TX DMA Output Address Register
+    volatile u32 dma_oadr;
+    // IR TX DMA Output Size Register
+    volatile u32 dma_osize;
+    // IR TX DMA Pending Register
+    volatile u32 dma_pend;
+} irtx_typedef;
+
+/**
+ * @brief Touch Key Register Structure
+ */
+typedef struct {
+    // Touch Key Control Register
+    volatile u32 tkcon;
+    // Touch Key Control Register 1
+    volatile u32 tkcon1;
+    // Touch Key Counter Register
+    volatile u32 tkcnt;
+    // Touch Key Charge And Discharge Period Register 0
+    volatile u32 tkcdpr0;
+    // Touch Key Charge And Discharge Period Register 1
+    volatile u32 tkcdpr1;
+    // Touch Key Times Register
+    volatile u32 tktmr;
+    // Touch Ear Times Register
+    volatile u32 tetmr;
+    // Touch Key Base Counter Register
+    volatile u32 tkbcnt;
+    // Touch Key Press Threshold Register
+    volatile u32 tkpthd;
+    // Touch Key Exception Threshold Register
+    volatile u32 tkethd;
+    // Touch Ear Base Counter Register
+    volatile u32 tebcnt;
+    // Touch Ear Press Threshold Register
+    volatile u32 tepthd;
+    // Touch Ear Exception Threshold Register
+    volatile u32 teethd;
+    // Touch Key Control Register 2
+    volatile u32 tkcon2;
+    // Touch Key Variance Register
+    volatile u32 tkvari;
+    // Touch Key Variance Threshold Register
+    volatile u32 tkvarithd;
+    // Touch Key Analog Control Register 0
+    volatile u32 tkacon0;
+    // Touch Key Analog Control Register 1
+    volatile u32 tkacon1;
+} touch_key_typedef;
+
+/**
+ * @brief SDADC Register Structure
+ */
+typedef struct {
+    volatile u32 con;
+    volatile u32 gain_con;
+    volatile u32 get_dc_con;
+    volatile u32 dma_con;
+    volatile u32 dma_addr;
+    volatile u32 dma_size;
+    volatile u32 dma_pend;
+    volatile u32 dma_cpnd;
+    volatile u32 ram_test_addr;
+    volatile u32 ram_test_data;
+} sdadc_typedef;
+
+/**
+ * @brief SDDAC Register Structure
+ */
+typedef struct {
+    volatile u32 dma_con;
+    volatile u32 dma_addr;
+    volatile u32 dma_size;
+    volatile u32 dma_pend;
+    volatile u32 dma_cpnd;
+    volatile u32 con;
+} sddac_typedef;
+
+/**
+ * @brief LEDC Register Structure
+ */
+typedef struct {
+    volatile u32 con;
+    volatile u32 fd;
+    volatile u32 lp;
+    volatile u32 tix;
+    volatile u32 rstx;
+    volatile u32 addr;
+    volatile u32 cnt;
+    volatile u32 pend;
+} ledc_typedef;
+
+/**
+ * @brief TICK0 Register Structure
+ */
+typedef struct {
+    volatile u32 con;
+    volatile u32 cpnd;
+    volatile u32 cnt;
+    volatile u32 pr;
+} tick_typedef;
+
+#endif // _DRIVER_COM_H

+ 452 - 0
driver/driver_gpio.c

@@ -0,0 +1,452 @@
+/*
+ * @File name    : driver_gpio.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-13
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the GPIO peripheral.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_gpio.h"
+
+const gpio_edge_cap_typedef separate_wakeup_io[WAKEUP_IDX_MAX] = {
+    /*edge is useless from PA7 to PB4 */
+    [WAKEUP_IDX_PA7] =          {GPIO_EDGE_RISING,      GPIOA_REG,  GPIO_PIN_7},
+    [WAKEUP_IDX_PB1] =          {GPIO_EDGE_RISING,      GPIOB_REG,  GPIO_PIN_1},
+    [WAKEUP_IDX_PB2] =          {GPIO_EDGE_RISING,      GPIOB_REG,  GPIO_PIN_2},
+    [WAKEUP_IDX_PB3] =          {GPIO_EDGE_RISING,      GPIOB_REG,  GPIO_PIN_3},
+    [WAKEUP_IDX_PB4] =          {GPIO_EDGE_RISING,      GPIOB_REG,  GPIO_PIN_4},
+
+    /*WK0 no used in this array*/
+    [WAKEUP_IDX_WK0] =          {GPIO_EDGE_RISING,      NULL,       0},
+
+    [WAKEUP_IDX_PORT_FALL] =    {GPIO_EDGE_FALLING,     NULL,       0},
+    [WAKEUP_IDX_PORT_RISE] =    {GPIO_EDGE_RISING,      NULL,       0},
+};
+
+/**
+  * @brief  Initializes the gpiox peripheral according to the specified
+  *         parameters in the gpio_init_struct.
+  * @param  gpiox: where x can be (A.B) to select the GPIO peripheral.
+  * @param  gpio_init_struct: pointer to a gpio_init_typedef structure that
+  *         contains the configuration information for the specified GPIO peripheral.
+  * @retval None
+  */
+void gpio_init(gpio_typedef* gpiox, gpio_init_typedef* gpio_init_struct)
+{
+    u32 reg;
+    uint32_t pin_idx = 0, pin_bit_offset = 0x00;
+    uint8_t i = 0x00;
+
+    /*--- Configure the port pins ---*/
+    for (pin_idx = 0; pin_idx < 16; pin_idx++) {
+        pin_bit_offset = ((uint32_t)0x01) << pin_idx;
+        if (gpio_init_struct->gpio_pin & pin_bit_offset) {
+            /*--- Input or Output Configuration ---*/
+            reg = gpiox->dir;
+            reg &= ~pin_bit_offset;
+            reg |= ((uint32_t)(gpio_init_struct->gpio_dir) << pin_idx);
+            gpiox->dir = reg;
+
+            /*--- Digital or Analog Configuration ---*/
+            reg = gpiox->de;
+            reg &= ~pin_bit_offset;
+            reg |= ((uint32_t)(gpio_init_struct->gpio_mode) << pin_idx);
+            gpiox->de = reg;
+
+            /*--- Function Mapping Enable Configuration ---*/
+            reg = gpiox->fen;
+            reg &= ~pin_bit_offset;
+            reg |= ((uint32_t)(gpio_init_struct->gpio_fen) << pin_idx);
+            gpiox->fen = reg;
+
+            /*--- GPIO Direction Select Configguratiopn ---*/
+            reg = gpiox->fdir;
+            reg &= ~pin_bit_offset;
+            reg |= ((uint32_t)(gpio_init_struct->gpio_fdir) << pin_idx);
+            gpiox->fdir = reg;
+
+            /*--- Pull Up or Pull Down Configuration and clear driving cfg ---*/
+            if (gpio_init_struct->gpio_dir == GPIO_DIR_INPUT) {
+                gpiox->drv &= ~pin_bit_offset;
+                for (i = 0; i < 6; i++) {
+                    reg = gpiox->pupd[i];
+                    reg &= ~pin_bit_offset;
+                    if ((i + 1) == gpio_init_struct->gpio_pupd) {
+                        reg |= pin_bit_offset;
+                    }
+                    gpiox->pupd[i] = reg;
+                }
+            /*--- Output driving Configuration and clear pupu cfg ---*/
+            } else if (gpio_init_struct->gpio_dir == GPIO_DIR_OUTPUT) {
+                for (i = 0; i < 6; i++) {
+                    gpiox->pupd[i] &= ~pin_bit_offset;
+                }
+                if (gpio_init_struct->gpio_mode == GPIO_MODE_DIGITAL) {
+                    if (GPIO_SUPPORT_STRONG_CURRENT(gpio_init_struct->gpio_drv, gpiox, pin_idx)) {
+                        reg = gpiox->drv;
+                        reg |= ((uint32_t)(gpio_init_struct->gpio_drv));
+                        gpiox->drv = reg;
+                    } else {
+                        reg = gpiox->drv;
+                        reg &= ~pin_bit_offset;
+                        reg |= ((uint32_t)(gpio_init_struct->gpio_drv) << pin_idx);
+                        gpiox->drv = reg;
+                    }
+                }
+            }
+        }
+    }
+}
+
+/**
+ * @brief  De-initialize the specified GPIO peripheral.
+ * @param  gpiox: where x can be (A.B) to select the GPIO peripheral.
+ * @param  gpio_pin: specifies the port bits to be written. This parameter
+ *         can be any combination of GPIO_PIN_x where x can be (0..15).
+ * @retval None
+ */
+uint32_t gpio_deinit(gpio_typedef *gpiox, uint16_t gpio_pin)
+{
+    u32 reg_original_sta;
+    if (gpiox == GPIOB_REG) {
+        gpio_pin &= 0x3ff;
+    }
+
+    reg_original_sta = gpiox->de;
+    gpiox->de &= ~gpio_pin;
+
+    return reg_original_sta;
+}
+
+/**
+  * @brief  Sets the selected data port bits.
+  * @param  gpiox: where x can be (A.B) to select the GPIO peripheral.
+  * @param  gpio_pin: specifies the port bits to be written. This parameter
+  *         can be any combination of GPIO_PIN_x where x can be (0..15).
+  * @retval None
+  */
+AT(.com_periph.gpio.set)
+void gpio_set_bits(gpio_typedef* gpiox, uint16_t gpio_pin)
+{
+    gpiox->io_set = gpio_pin;
+}
+
+/**
+  * @brief  Clears the selected data port bits.
+  * @param  gpiox: where x can be (A.B) to select the GPIO peripheral.
+  * @param  gpio_pin: specifies the port bits to be written.
+  *         This parameter can be any combination of GPIO_PIN_x where x can be (0..15).
+  * @retval None
+  */
+AT(.com_periph.gpio.reset)
+void gpio_reset_bits(gpio_typedef* gpiox, uint16_t gpio_pin)
+{
+    gpiox->io_clr = gpio_pin;
+}
+
+/**
+  * @brief  Writes the specified GPIO output data port.
+  * @param  gpiox: where x can be (A.B) to select the GPIO peripheral.
+  * @param  port_val: specifies the port bits to be written. This parameter
+  *         can be any combination of GPIO_PIN_x where x can be (0..15).
+  * @retval None
+  */
+AT(.com_periph.gpio.write)
+void gpio_write_data(gpio_typedef *gpiox, uint16_t port_val)
+{
+    gpiox->data = port_val;
+}
+
+/**
+  * @brief  Toggles the selected output data port bits.
+  * @param  gpiox: where x can be (A.B) to select the GPIO peripheral.
+  * @param  gpio_pin: specifies the port bits to be written. This parameter
+  *         can be any combination of GPIO_PIN_x where x can be (0..15).
+  * @retval None
+  */
+AT(.com_periph.gpio.toggle)
+void gpio_toggle_bits(gpio_typedef *gpiox, uint16_t gpio_pin)
+{
+    gpiox->data ^= gpio_pin;
+}
+
+/**
+  * @brief  Reads the specified GPIO input data port.
+  * @param  gpiox: where x can be (A.B) to select the GPIO peripheral.
+  * @retval GPIO output data port value.
+  */
+AT(.com_periph.gpio.read_data)
+uint16_t gpio_read_data(gpio_typedef* gpiox)
+{
+    return ((uint16_t)(gpiox->data));
+}
+
+/**
+  * @brief  Reads the specified input port pin.
+  * @param  gpiox: where x can be (A.B) to select the GPIO peripheral.
+  * @param  gpio_pin: specifies the port bit to read.
+  *         This parameter can be gpio_pin where x can be (0..15).
+  * @retval The input port pin value.
+  */
+AT(.com_periph.gpio.read_bit)
+uint8_t gpio_read_bit(gpio_typedef* gpiox, uint16_t gpio_pin)
+{
+    uint8_t bit_status;
+
+    if ((gpiox->data & gpio_pin) != BIT_RESET) {
+        bit_status = (uint8_t)SET;
+    } else {
+        bit_status = (uint8_t)RESET;
+    }
+
+    return bit_status;
+}
+
+/**
+ * @brief  Configure GPIO function mapping.
+ * @param  gpiox: where x can be (A.B) to select the GPIO peripheral.
+ * @param  gpio_pin: specifies the port bit to read.
+ *         This parameter can be gpio_pin where x can be (0..15).
+ * @param  func_idx: Peripheral index that need to config mapping. The value of this param
+ *         see enumeration "GPIO_CROSSBAR_PERIPHERAL_DEF" in the file "driver_gpio.h".
+ * @retval None
+ */
+void gpio_func_mapping_config(gpio_typedef* gpiox, uint16_t gpio_pin, GPIO_CROSSBAR_PERIPHERAL_DEF func_idx)
+{
+    u8 i;
+    u8 pin_idx;
+    uint8_t register_idx, register_offset;
+    u8 gpio_crossbar_idx_PA0 = 1;
+    u8 gpio_crossbar_idx_PB0 = 17;
+
+    /*--- Calculate the pin_dix for function mapping ---*/
+    for (i = 0; i < 16; i++) {
+        if ((1 << i) == gpio_pin) {
+            break;
+        }
+    }
+    if (gpiox == GPIOA_REG) {
+        pin_idx = gpio_crossbar_idx_PA0 + i;
+    } else {
+        pin_idx = gpio_crossbar_idx_PB0 + i;
+    }
+
+    /*--- Check parameter validity ---*/
+    if (func_idx >= GPIO_CROSSBAR_PERIPHERAL_MAX_IDX) {
+        return;
+    }
+    if ((gpiox == GPIOB_REG) && (gpio_pin > GPIO_PIN_9)) {
+        return;
+    }
+
+    /*--- function mapping config ---*/
+    if (func_idx > GPIO_CROSSBAR_PERIPHERAL_INPUT_BASE) {
+        register_idx = (func_idx - GPIO_CROSSBAR_PERIPHERAL_INPUT_BASE - 1) / 4;
+        register_offset = (func_idx - GPIO_CROSSBAR_PERIPHERAL_INPUT_BASE - 1) % 4 * 8;
+
+        /* Do nothing if the current peripheral is already mapped to the corresponding IO */
+        if (((FUNCMAP->func_input_map[register_idx] >> register_offset) & 0x1f) == pin_idx) {
+            return;
+        }
+
+        FUNCMAP->func_input_map[register_idx] |= (uint32_t)(0xff << register_offset);
+        FUNCMAP->func_input_map[register_idx] |= (uint32_t)(pin_idx << register_offset);
+    } else if (func_idx < GPIO_CROSSBAR_PERIPHERAL_INPUT_BASE) {
+        register_idx = (pin_idx - 1) / 4;
+        register_offset = (pin_idx - 1) % 4 * 8;
+
+        /* Do nothing if the current peripheral is already mapped to the corresponding IO */
+        if (((FUNCMAP->func_output_map[register_idx] >> register_offset) & 0x1f) == func_idx) {
+            return;
+        }
+
+        FUNCMAP->func_output_map[register_idx] |= (uint32_t)(0xff << register_offset);
+        FUNCMAP->func_output_map[register_idx] |= (uint32_t)(func_idx << register_offset);
+    }
+}
+
+/**
+ * @brief  Clear GPIO function mapping config.
+ * @param  gpiox: where x can be (A.B) to select the GPIO peripheral.
+ * @param  gpio_pin: specifies the port bit to read.
+ *         This parameter can be gpio_pin where x can be (0..15).
+ * @retval None
+ */
+void gpio_func_mapping_clear(gpio_typedef* gpiox, uint16_t gpio_pin)
+{
+    uint8_t register_idx, register_offset;
+    uint8_t i, j;
+    u8 pin_idx;
+    u8 gpio_crossbar_idx_PA0 = 1;
+    u8 gpio_crossbar_idx_PB0 = 17;
+
+    /* Calculate the pin_dix for function mapping */
+    for (i = 0; i < 16; i++) {
+        if ((1 << i) == gpio_pin) {
+            break;
+        }
+    }
+    if (gpiox == GPIOA_REG) {
+        pin_idx = gpio_crossbar_idx_PA0 + i;
+    } else {
+        pin_idx = gpio_crossbar_idx_PB0 + i;
+    }
+
+    /* Clear output mapping */
+    register_idx = (pin_idx - 1) / 4;
+    register_offset = (pin_idx - 1) % 4 * 8;
+    FUNCMAP->func_output_map[register_idx] |= (uint32_t)(0xff << register_offset);
+
+    for (i = 0; i < 7; i++) {
+        for (j = 0; j < 32; j += 8)
+        if (((FUNCMAP->func_input_map[i] >> j) & 0x1f) == pin_idx) {
+            FUNCMAP->func_input_map[i] |= (uint32_t)(0xff << j);
+        }
+    }
+}
+
+/**
+ * @brief  WK0 IO level detect config.
+ * @param  pull_up_en: Whether WK0 internal pull up enable.
+ * @param  pull_down_en: Whether WK0 internal pull down enable.
+ * @param  input_en: Whether WK0 input enable.
+ * @retval None
+ */
+void wko_io_config(FUNCTIONAL_STATE pull_up_en, FUNCTIONAL_STATE pull_down_en, FUNCTIONAL_STATE input_en)
+{
+    if (pull_up_en) {
+        RTCCON1 |= (uint32_t)(1 << 4);
+    } else {
+        RTCCON1 &= ~(uint32_t)(1 << 4);
+    }
+
+    if (pull_down_en) {
+        RTCCON1 |= (uint32_t)(1 << 1);
+        RTCCON11 |= (uint32_t)(1 << 4);     // Sure this bit is enable, and recommends it is enabled normally.
+    } else {
+        RTCCON1 &= ~(uint32_t)(1 << 1);
+    }
+
+    if (input_en) {
+        RTCCON1 |= (uint32_t)(1 << 0);
+    } else {
+        RTCCON1 &= ~(uint32_t)(1 << 0);
+    }
+}
+
+/**
+ * @brief  Read WK0 level.
+ * @retval The state of interrupt_type (SET or RESET).
+ */
+AT(.com_periph.wk0.read_bit)
+FLAG_STATE wko_io_read_bit(void)
+{
+    if (RTCCON & (1 << 19)) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+void wk0_edge_capture_config(GPIO_EDGE_SEL edge)
+{
+    clk_gate0_cmd(CLK_GATE0_LP, CLK_EN);
+
+    if(edge == GPIO_EDGE_FALLING){
+        wko_io_config(1, 0, 1);
+        WKUPEDG |= BIT(5);
+    }else{
+        wko_io_config(0, 1, 1);
+        WKUPEDG &= ~BIT(5);
+    }
+
+    WKUPCON |= BIT(5);
+
+    WKUPCPND = 0xff << 16;                  //clear wakeup pending
+}
+
+uint32_t gpio_edge_capture_idx_get(gpio_edge_cap_typedef* config)
+{
+    uint32_t ret_idx = WAKEUP_IDX_MAX;
+
+    /*we first considered wakeup source is general IO */
+    for (uint8_t i = WAKEUP_IDX_PORT_FALL; i < WAKEUP_IDX_MAX; i++) {
+        if (config->edge == separate_wakeup_io[i].edge) {
+            ret_idx = i;
+            break;
+        }
+    }
+
+    /*check if wakeup source is separate IO*/
+    for (uint8_t i = WAKEUP_IDX_PA7; i < WAKEUP_IDX_WK0; i++) {
+        if ((config->gpiox == separate_wakeup_io[i].gpiox) && (config->gpio_pin == separate_wakeup_io[i].gpio_pin)) {
+            ret_idx = i;
+            break;
+        }
+    }
+
+    return ret_idx;
+}
+
+void gpio_edge_capture_config(gpio_edge_cap_typedef* config)
+{
+    clk_gate0_cmd(CLK_GATE0_LP, CLK_EN);
+
+    gpio_init_typedef gpio_config;
+    uint32_t gpio_pin = config->gpio_pin;
+    if(config->gpiox == GPIOB_REG){
+        gpio_pin = ((uint32_t)config->gpio_pin) << 16;
+    }
+    gpio_config.gpio_pin = config->gpio_pin;
+    gpio_config.gpio_dir = GPIO_DIR_INPUT;
+    gpio_config.gpio_fen = GPIO_FEN_GPIO;
+    gpio_config.gpio_fdir = GPIO_FDIR_SELF;
+    gpio_config.gpio_mode = GPIO_MODE_DIGITAL;
+    gpio_config.gpio_pupd = config->gpio_pupd;
+
+    gpio_init(config->gpiox, &gpio_config);
+
+    uint32_t wakeup_idx = gpio_edge_capture_idx_get(config);
+    
+    if(config->edge == GPIO_EDGE_RISING){
+        PORTINTEDG &= ~gpio_pin;
+        PORTINTEN |= gpio_pin;
+        WKUPEDG &= ~BIT(wakeup_idx);
+        WKUPCON |= BIT(wakeup_idx);
+    }else{
+        PORTINTEDG |= gpio_pin;
+        PORTINTEN |= gpio_pin;
+        WKUPEDG |= BIT(wakeup_idx);
+        WKUPCON |= BIT(wakeup_idx);
+    }
+
+    WKUPCPND = 0xff << 16;
+}
+
+AT(.com_periph.gpio.pending_clr)
+void gpio_edge_pending_clear(void)
+{
+    WKUPCPND = 0xff << 16;
+}
+
+AT(.com_periph.gpio.pending_is)
+bool gpio_is_edge_pending(void)
+{
+   return ((WKUPEDG>>16) & 0xff) ? true : false;
+}
+
+
+void gpio_edge_pic_config(isr_t isr, int pr)
+{
+    sys_irq_init(IRQn_PORT, pr, isr);
+
+    WKUPCPND = 0xff << 16;
+    WKUPCON |= BIT(16);
+}
+
+void gpio_edge_pic_disable(void)
+{
+    PICEN &= ~BIT(IRQn_PORT);
+    WKUPCON &= ~BIT(16);
+}

+ 216 - 0
driver/driver_gpio.h

@@ -0,0 +1,216 @@
+/*
+ * @File name    : driver_gpio.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-13
+ * @Description  : This file contains all the functions prototypes for the GPIO library.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_GPIO_H
+#define _DRIVER_GPIO_H
+
+#include "driver_com.h"
+
+/**
+ * @brief GPIO_Pins_Definition
+ */
+#define GPIO_PIN_ALL                ((uint16_t)0xffff)      /* All PIN bits definition */
+#define GPIO_PIN_0                  ((uint16_t)0x0001)      /* PIN 0 bit definition */
+#define GPIO_PIN_1                  ((uint16_t)0x0002)      /* PIN 1 bit definition */
+#define GPIO_PIN_2                  ((uint16_t)0x0004)      /* PIN 2 bit definition */
+#define GPIO_PIN_3                  ((uint16_t)0x0008)      /* PIN 3 bit definition */
+#define GPIO_PIN_4                  ((uint16_t)0x0010)      /* PIN 4 bit definition */
+#define GPIO_PIN_5                  ((uint16_t)0x0020)      /* PIN 5 bit definition */
+#define GPIO_PIN_6                  ((uint16_t)0x0040)      /* PIN 6 bit definition */
+#define GPIO_PIN_7                  ((uint16_t)0x0080)      /* PIN 7 bit definition */
+#define GPIO_PIN_8                  ((uint16_t)0x0100)      /* PIN 8 bit definition */
+#define GPIO_PIN_9                  ((uint16_t)0x0200)      /* PIN 9 bit definition */
+#define GPIO_PIN_10                 ((uint16_t)0x0400)      /* PIN 10 bit definition */
+#define GPIO_PIN_11                 ((uint16_t)0x0800)      /* PIN 11 bit definition */
+#define GPIO_PIN_12                 ((uint16_t)0x1000)      /* PIN 12 bit definition */
+#define GPIO_PIN_13                 ((uint16_t)0x2000)      /* PIN 13 bit definition */
+#define GPIO_PIN_14                 ((uint16_t)0x4000)      /* PIN 14 bit definition */
+#define GPIO_PIN_15                 ((uint16_t)0x8000)      /* PIN 15 bit definition */
+
+
+/**
+ * @brief GPIO Function Mapping Crossbar Peripheral Definition
+ */
+typedef enum {
+    GPIO_CROSSBAR_OUT_I2CSCL = 5,
+    GPIO_CROSSBAR_OUT_I2CSDA,
+    GPIO_CROSSBAR_OUT_T3PWM0,
+    GPIO_CROSSBAR_OUT_T3PWM1,
+    GPIO_CROSSBAR_OUT_T3PWM2,
+    GPIO_CROSSBAR_OUT_TOC1,
+    GPIO_CROSSBAR_OUT_TOC1N,
+    GPIO_CROSSBAR_OUT_TOC2,
+    GPIO_CROSSBAR_OUT_TOC2N,
+    GPIO_CROSSBAR_OUT_TOC3,
+    GPIO_CROSSBAR_OUT_TOC3N,
+    GPIO_CROSSBAR_OUT_TOC4,
+    GPIO_CROSSBAR_OUT_UARTTX,
+    GPIO_CROSSBAR_OUT_UDETTX,
+    GPIO_CROSSBAR_OUT_HURTX,
+    GPIO_CROSSBAR_OUT_HURRTS,
+    GPIO_CROSSBAR_OUT_SPI1D0,
+    GPIO_CROSSBAR_OUT_SPI1D1,
+    GPIO_CROSSBAR_OUT_SPI1D2,
+    GPIO_CROSSBAR_OUT_SPI1D3,
+    GPIO_CROSSBAR_OUT_SPI1CLK,
+    GPIO_CROSSBAR_OUT_LPWM,
+    GPIO_CROSSBAR_OUT_LEDCDAT,
+    GPIO_CROSSBAR_OUT_IRTX,
+    GPIO_CROSSBAR_OUT_CLKOUT,
+
+    GPIO_CROSSBAR_PERIPHERAL_INPUT_BASE,
+    GPIO_CROSSBAR_IN_UARTRX,
+    GPIO_CROSSBAR_IN_UDETRX,
+    GPIO_CROSSBAR_IN_SPI1CLK,
+    GPIO_CROSSBAR_IN_SPI1DI0,
+    GPIO_CROSSBAR_IN_SPI1DI1,
+    GPIO_CROSSBAR_IN_HURRX,
+    GPIO_CROSSBAR_IN_HURCTS,
+    GPIO_CROSSBAR_IN_T0CAP,
+    GPIO_CROSSBAR_IN_T1CAP,
+    GPIO_CROSSBAR_IN_T2CAP,
+    GPIO_CROSSBAR_IN_T3CAP,
+    GPIO_CROSSBAR_IN_TBKIN,
+    GPIO_CROSSBAR_IN_TETR,
+    GPIO_CROSSBAR_IN_I2CSCL,
+    GPIO_CROSSBAR_IN_I2CSDA,
+    GPIO_CROSSBAR_IN_IRRX,
+    GPIO_CROSSBAR_IN_QDECXDI0,
+    GPIO_CROSSBAR_IN_QDECXDI1,
+    GPIO_CROSSBAR_IN_QDECYDI0,
+    GPIO_CROSSBAR_IN_QDECYDI1,
+    GPIO_CROSSBAR_IN_QDECZDI0,
+    GPIO_CROSSBAR_IN_QDECZDI1,
+    GPIO_CROSSBAR_IN_SDCMD,
+    GPIO_CROSSBAR_IN_SDDAT0,
+    GPIO_CROSSBAR_PERIPHERAL_MAX_IDX,
+} GPIO_CROSSBAR_PERIPHERAL_DEF;
+
+/**
+ * @brief Bits detinition for GPIO
+ */
+typedef enum {
+    BIT_RESET           = 0,
+    BIT_SET,
+} BIT_ACTION;
+
+/**
+ * @brief GPIO direction enumeration
+ */
+typedef enum {
+    GPIO_DIR_OUTPUT     = 0x00,
+    GPIO_DIR_INPUT      = 0x01,
+} GPIO_DIR_TYPEDEF;
+
+/**
+ * @brief GPIO input pull resistance enumeration
+ */
+typedef enum {
+    GPIO_PUPD_NULL      = 0x00,
+    GPIO_PUPD_PU10K     = 0x01,
+    GPIO_PUPD_PD10K     = 0x02,
+    GPIO_PUPD_PU200K    = 0x03,
+    GPIO_PUPD_PD200K    = 0x04,
+    GPIO_PUPD_PU300     = 0x05,
+    GPIO_PUPD_PD300     = 0x06,
+} GPIO_PUPD_TYPEDEF;
+
+/**
+ * @brief GPIO port type enumeration
+ */
+typedef enum {
+    GPIO_MODE_ANALOG    = 0x00,
+    GPIO_MODE_DIGITAL   = 0x01,
+} GPIO_MODE_TYPEDEF;
+
+/**
+ * @brief GPIO function mapping enable enumeration
+ */
+typedef enum {
+    GPIO_FEN_GPIO       = 0x00,
+    GPIO_FEN_PER        = 0x01,
+} GPIO_FEN_TYPEDEF;
+
+/**
+ * @brief GPIO function mapping direction select register
+ */
+typedef enum {
+    GPIO_FDIR_SELF      = 0x00,
+    GPIO_FDIR_MAP       = 0x01,
+} GPIO_FDIR_TYPEDEF;
+
+/**
+ * @brief GPIO output current enumeration, specially PB4 can output 64mA.
+ */
+typedef enum {
+    GPIO_DRV_6MA        = 0x00,
+    GPIO_DRV_24MA       = 0x01,
+    GPIO_DRV_64MA       = (3 << 10),
+} GPIO_DRV_TYPEDEF;
+
+typedef enum {
+    GPIO_EDGE_RISING        = 0x00,
+    GPIO_EDGE_FALLING       = 0x01,
+} GPIO_EDGE_SEL;
+
+typedef enum {
+    WAKEUP_IDX_PA7,
+    WAKEUP_IDX_PB1,
+    WAKEUP_IDX_PB2,
+    WAKEUP_IDX_PB3,
+    WAKEUP_IDX_PB4,
+    WAKEUP_IDX_WK0,
+    WAKEUP_IDX_PORT_FALL,
+    WAKEUP_IDX_PORT_RISE,
+    WAKEUP_IDX_MAX,
+} GPIO_WAKEUP_IDX;
+
+/**
+ * @brief GPIO Init Structure
+ */
+typedef struct {
+    uint32_t              gpio_pin;
+    GPIO_DIR_TYPEDEF      gpio_dir;
+    GPIO_PUPD_TYPEDEF     gpio_pupd;
+    GPIO_MODE_TYPEDEF     gpio_mode;
+    GPIO_FEN_TYPEDEF      gpio_fen;
+    GPIO_FDIR_TYPEDEF     gpio_fdir;
+    GPIO_DRV_TYPEDEF      gpio_drv;
+} gpio_init_typedef;
+
+typedef struct {
+    GPIO_EDGE_SEL edge;
+    gpio_typedef *gpiox;
+    uint16_t gpio_pin;
+    GPIO_PUPD_TYPEDEF     gpio_pupd;
+} gpio_edge_cap_typedef;
+
+#define GPIO_SUPPORT_STRONG_CURRENT(drv, gpiox, pin_idx)           ((GPIO_DRV_64MA == drv) && (GPIOB_REG == gpiox) && (GPIO_PIN_4 == (1 << pin_idx)))
+
+
+/************************ Function used to set or R/W GPIO *************************/
+void gpio_init(gpio_typedef *gpiox, gpio_init_typedef *gpio_init_struct);
+uint32_t gpio_deinit(gpio_typedef *gpiox, uint16_t gpio_pin);
+void gpio_set_bits(gpio_typedef *gpiox, uint16_t gpio_pin);
+void gpio_reset_bits(gpio_typedef *gpiox, uint16_t gpio_pin);
+void gpio_write_data(gpio_typedef *gpiox, uint16_t port_val);
+void gpio_toggle_bits(gpio_typedef *gpiox, uint16_t gpio_pin);
+uint16_t gpio_read_data(gpio_typedef *gpiox);
+uint8_t gpio_read_bit(gpio_typedef *gpiox, uint16_t gpio_pin);
+void gpio_func_mapping_config(gpio_typedef* gpiox, uint16_t gpio_pin, GPIO_CROSSBAR_PERIPHERAL_DEF func_idx);
+void gpio_func_mapping_clear(gpio_typedef* gpiox, uint16_t gpio_pin);
+void wko_io_config(FUNCTIONAL_STATE pull_up_en, FUNCTIONAL_STATE pull_down_en, FUNCTIONAL_STATE input_en);
+FLAG_STATE wko_io_read_bit(void);
+void wk0_edge_capture_config(GPIO_EDGE_SEL edge);
+void gpio_edge_capture_config(gpio_edge_cap_typedef* config);
+bool gpio_is_edge_pending(void);
+void gpio_edge_pending_clear(void);
+void gpio_edge_pic_config(isr_t isr, int pr);
+void gpio_edge_pic_disable(void);
+
+#endif  // _DRIVER_GPIO_H

+ 350 - 0
driver/driver_hsuart.c

@@ -0,0 +1,350 @@
+/*
+ * @File name    : driver_hsuart.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-14
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the HSUART peripheral.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_hsuart.h"
+
+/**
+  * @brief  Initializes the hsuart peripheral according to the specified
+  *         parameters in the hsuart_init_struct.
+  * @param  hsuart_init_struct: pointer to a hsuart_init_typedef structure that
+  *         contains the configuration information for the specified HSUART peripheral.
+  * @retval None
+  */
+void hsuart_init(hsuart_init_typedef *hsuart_init_struct)
+{
+    uint32_t tmp_reg, sys_clk_val, baud_reg;
+
+    /*--- Enable model function ---*/
+    RSTCON0 |= 1<<2;
+
+    tmp_reg = HSUART->con;
+    //---------- hsuart Tx configuration ----------//
+    tmp_reg &= ~(uint32_t)(HSUT0CON_SPBITSEL | HSUT0CON_TXBITSEL | HSUT0CON_TXTRSMODE);
+    tmp_reg |= hsuart_init_struct->tx_stop_bit;
+    tmp_reg |= hsuart_init_struct->tx_word_len;
+    tmp_reg |= hsuart_init_struct->tx_mode;
+
+    //---------- hsuart Rx configuration ----------//
+    tmp_reg &= ~(HSUT0CON_RXBITSEL | HSUT0CON_RXTRSMODE);
+    tmp_reg |= hsuart_init_struct->rx_word_len;
+    tmp_reg |= hsuart_init_struct->rx_mode;
+
+    /* hsuart one line configuration */
+    tmp_reg &= ~HSUT0CON_ONELINE;
+    tmp_reg |= hsuart_init_struct->one_line_en;
+
+    /* hsuart Rx dma mode loop buf configuration */
+    if (hsuart_init_struct->rx_mode == HSUT_RX_DMA_MODE) {
+        tmp_reg &= ~HSUT0CON_RXLPBUFEN;
+        tmp_reg |= hsuart_init_struct->rx_dma_buf_mode;
+    }
+
+    HSUART->con = tmp_reg;
+
+    //---------- hsuart baud and clock configuration ----------//
+    if (hsuart_init_struct->clk_source == HSUT_24M_CLK) {
+        clk_hsut0_clk_set(CLK_HSUT0_CLK_XOSC24M_CLK, 0);
+    } else if (hsuart_init_struct->clk_source == HSUT_48M_CLK) {
+        clk_hsut0_clk_set(CLK_HSUT0_CLK_XOSC48M, 0);
+    } else if (hsuart_init_struct->clk_source == HSUT_PLLDIV4_CLK) {
+        clk_hsut0_clk_set(CLK_HSUT0_CLK_PLLDIV2_CLK, 1);
+    }
+
+    sys_clk_val = clk_hsut0_clk_get(CLK_VALUE_MODE_FREQ);
+
+    if (hsuart_init_struct->baud == 0) {
+        return;
+    }
+
+    baud_reg = (sys_clk_val / hsuart_init_struct->baud) - 1;
+    tmp_reg = (uint32_t)((baud_reg << 16) | baud_reg);
+    HSUART->baud = tmp_reg;
+}
+
+/**
+ * @brief  De-initialize the specified HSUART peripheral.
+ * @retval None
+ */
+void hsuart_deinit(void)
+{
+    HSUART->con = 0;
+    clk_gate0_cmd(CLK_GATE0_HSUART, CLK_DIS);
+}
+
+/**
+  * @brief  Enable or disable the specified HSUART peripheral.
+  * @param  rec_tra_sel: select whether Rx or Tx needs to be configured.
+  *         this parameter cna be: HSUT_TRANSMIT or HSUT_RECEIVE.
+  * @param  state: the state of the HSUART peripheral.
+  *         this parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void hsuart_cmd(HSUT_REC_TRA_CMD rec_tra_sel, FUNCTIONAL_STATE state)
+{
+    if (state != DISABLE) {
+        HSUART->con |= (uint32_t)rec_tra_sel;
+    } else {
+        HSUART->con &= ~(uint32_t)rec_tra_sel;
+    }
+}
+
+/**
+  * @brief  Transmits data through the HSUART buf mode.
+  * @param  data: the data to transmit.
+  * @retval None
+  */
+AT(.com_periph.hsuart.send)
+void hsuart_send_data(uint16_t data)
+{
+    if (HSUART->con & HSUT0CON_TXBITSEL) {
+        HSUART->data = (uint32_t)(data & 0x1ff);
+    } else {
+        HSUART->data = (uint32_t)(data & 0xff);
+    }
+}
+
+/**
+  * @brief  Return the received data lastly by the buf mode.
+  * @retval The received data.
+  */
+AT(.com_periph.hsuart.recv)
+uint16_t hsuart_receive_data(void)
+{
+    return (HSUART->fifo & 0xff);
+}
+
+/**
+ * @brief  Get the receive data from Rx DMA FIFO.
+ * @param  buf: A buf pointer used to return data.
+ * @param  len: The data number need to read.
+ * @retval Result of func execution. It will be SUCCESS or FAILED.
+ */
+AT(.com_periph.hsuart.receive_data)
+STATUS_STATE hsuart_receive_data_from_fifo(uint8_t *buf, uint8_t len)
+{
+    u8 i = 0;
+
+    if (len > HSUART->fifo_cnt || !buf) {
+        return FAILED;
+    }
+
+    while (len--) {
+        HSUART->fifo |= (1 << 8);
+        while (!(HSUART->fifo & (1 << 9)));
+        buf[i++] = HSUART->fifo & 0xff;
+    }
+
+    return SUCCESS;
+}
+
+/**
+ * @brief  Get Rx DMA mode FIFO counter value.
+ * @retval The value of FIFO counter.
+ */
+AT(.com_periph.hsuart.fifo_get)
+uint16_t hsuart_get_fifo_counter(void)
+{
+    return HSUART->fifo_cnt;
+}
+
+/**
+ * @brief  Clear fifo counter.
+ * @retval None
+ */
+void hsuart_clear_fifo_counter(void)
+{
+    HSUART->cpnd |= (uint32_t)(1 << 17);
+}
+
+/**
+ * @brief  Change the HSUART baud.
+ * @param  baud: Specifies the baud rateof the serial port.
+ * @retval None.
+ */
+void hsuart_baud_config(uint32_t baud)
+{
+    u32 baud_reg, sys_clk_val;
+
+    //---------- hsuart baud and clock configuration ----------//
+    sys_clk_val = clk_hsut0_clk_get(CLK_VALUE_MODE_FREQ);
+
+    baud_reg = (sys_clk_val / baud) - 1;
+    HSUART->baud = (uint32_t)((baud_reg << 16) | baud_reg);
+}
+
+/**
+  * @brief  Enable or disable the specified HSUART interrupt.
+  * @param  isr: Function to be executed for service interruption.
+  * @param  pr: Priority of service interruption.
+  * @param  interrup_type: specifies the HSUART interrupt sources to be enable or disable.
+  *         this parameter can be one of the following values:
+  *             @arg HSUART_IT_RX_DMA_HF: RX DMA half-full interrupt enable bit.
+  *             @arg HSUART_IT_TX: Transmit single or n bytes data finish interrupt enable bit.
+  *             @arg HSUART_IT_RX: Receive single or n bytes data finish interrupt enable bit.
+  * @param  state: the state of the HSUART peripheral.
+  *         this parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void hsuart_pic_config(isr_t isr, int pr, HSUART_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state)
+{
+    uint32_t interrupt_pending_bit = 0;
+    uint32_t all_interrupt_type_mask = HSUART_IT_RX_DMA_HF | HSUART_IT_TX | HSUART_IT_RX;
+
+    if (interrupt_type == 0) {
+        return;
+    }
+
+    if (interrupt_type & HSUART_IT_RX) {
+        interrupt_pending_bit |= HSUT0CON_RXIE;
+    }
+
+    if (interrupt_type & HSUART_IT_TX) {
+        interrupt_pending_bit |= HSUT0CON_TXIE;
+    }
+
+    if (interrupt_type & HSUART_IT_RX_DMA_HF) {
+        interrupt_pending_bit |= HSUT0CON_RXHF_IE;
+    }
+
+    if (state != DISABLE) {
+        sys_irq_init(IRQn_HSUART, pr, isr);
+        HSUART->con |= interrupt_pending_bit;
+    } else {
+        HSUART->con &= ~interrupt_pending_bit;
+        if (interrupt_type == all_interrupt_type_mask) {
+            PICEN &= ~BIT(IRQn_HSUART);
+        }
+    }
+}
+
+/**
+  * @brief  Check the specified HSUART flag is set or not.
+  * @param  interrupt_type: specifies the flag to check.
+  *         this parameter can be one of the following values:
+  *             @arg HSUART_IT_RX_DMA_HF: RX DMA half-full interrupt pending bit.
+  *             @arg HSUART_IT_RX_TMR_OV: RX timer overflow interrupt pending bit.
+  *             @arg HSUART_IT_TX: Transmit single or n bytes data finish interrupt pending bit.
+  *             @arg HSUART_IT_RX: Receive single or n bytes data finish interrupt pending bit.
+  * @retval The state of uart_flag (SET or RESET).
+  */
+AT(.com_periph.hsuart.get_flag)
+FLAG_STATE hsuart_get_flag(HSUART_IT_TYPEDEF interrupt_type)
+{
+    uint32_t interrupt_pending_bit = 0;
+
+    if (interrupt_type & HSUART_IT_RX) {
+        interrupt_pending_bit |= HSUT0CON_RXPND;
+    }
+
+    if (interrupt_type & HSUART_IT_TX){
+        interrupt_pending_bit |= HSUT0CON_TXPND;
+    }
+
+    if (interrupt_type & HSUART_IT_RX_TMR_OV){
+        interrupt_pending_bit |= HSUT0CON_TMROV;
+    }
+
+    if (interrupt_type & HSUART_IT_RX_DMA_HF){
+        interrupt_pending_bit |= HSUT0CON_RXHF_PND;
+    }
+
+    if ((HSUART->con & interrupt_pending_bit) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+  * @brief  Clear the HSUART's pending flag.
+  * @param  hsuart_flag: specifies the flag to check.
+  *         this parameter can be one of the following values:
+  *             @arg HSUART_IT_RX_DMA_HF: RX DMA half-full interrupt pending bit.
+  *             @arg HSUART_IT_RX_TMR_OV: RX timer overflow interrupt pending bit.
+  *             @arg HSUART_IT_TX: Transmit single or n bytes data finish interrupt pending bit.
+  *             @arg HSUART_IT_RX: Receive single or n bytes data finish interrupt pending bit.
+  * @retval None
+  */
+AT(.com_periph.hsuart.clear)
+void hsuart_clear_flag(HSUART_IT_TYPEDEF interrupt_type)
+{
+    uint32_t interrupt_pending_bit = 0;
+
+    if (interrupt_type & HSUART_IT_RX) {
+        interrupt_pending_bit |= HSUT0CPND_CRXPND;
+    }
+
+    if (interrupt_type & HSUART_IT_TX){
+        interrupt_pending_bit |= HSUT0CPND_CTXPND;
+    }
+
+    if (interrupt_type & HSUART_IT_RX_TMR_OV){
+        interrupt_pending_bit |= HSUT0CPND_CTMROV;
+    }
+
+    if (interrupt_type & HSUART_IT_RX_DMA_HF){
+        interrupt_pending_bit |= HSUT0CPND_CRXHFPND;
+    }
+
+    HSUART->cpnd |= interrupt_pending_bit;
+}
+
+/**
+ * @brief  Config idle timer that can trigger an interrupt when Rx idle.
+ * @param  idle_time: The maximum number of idle clocks.
+ * @param  state: the state of the HSUART peripheral.
+*                 this parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void hsuart_rx_idle_config(uint16_t idle_time, FUNCTIONAL_STATE state)
+{
+    if (state != DISABLE) {
+        HSUART->tmr_cnt = idle_time;
+        HSUART->con |= HSUT0CON_HSUTTMREN;
+    } else {
+        HSUART->con &= ~HSUT0CON_HSUTTMREN;
+    }
+}
+
+/**
+  * @brief  Start send or receive dma. When receiving data of indefinite
+  *         length, need to enable the idle timer.
+  * @param  rec_tra_sel: Tx or Rx to configure.
+  *         this parameter can be: (HSUT_TRANSMIT or HSUT_RECEIVE)
+  * @param  addr: DMA start address.
+  * @param  len: DMA transmit len.
+  * @retval None
+  */
+AT(.com_periph.hsuart.dma)
+void hsuart_dma_start(HSUT_REC_TRA_CMD rec_tra_sel, uint32_t addr, uint16_t len)
+{
+    if (rec_tra_sel == HSUT_RECEIVE) {
+        HSUART->rx_adr = addr;
+        HSUART->rx_cnt = (uint32_t)len;
+    } else if (rec_tra_sel == HSUT_TRANSMIT) {
+        HSUART->tx_adr = addr;
+        HSUART->tx_cnt = (uint32_t)len;
+    }
+}
+
+/**
+  * @brief  stop send or receive dma.
+  * @param  rec_tra_sel: Tx or Rx to configure.
+  *         this parameter can be: (HSUT_TRANSMIT or HSUT_RECEIVE)
+  * @retval None
+  */
+AT(.com_periph.hsuart.stop)
+void hsuart_dma_stop(HSUT_REC_TRA_CMD rec_tra_sel)
+{
+    if (rec_tra_sel == HSUT_RECEIVE) {
+        HSUART->rx_cnt = 0;
+    } else if (rec_tra_sel == HSUT_TRANSMIT) {
+        HSUART->tx_cnt = 0;
+    }
+}

+ 131 - 0
driver/driver_hsuart.h

@@ -0,0 +1,131 @@
+/*
+ * @File name    : driver_hsuart.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-14
+ * @Description  : This file contains all the functions prototypes for the HSUART library.
+ * 
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_HSUART_H
+#define _DRIVER_HSUART_H
+
+#include "driver_com.h"
+
+/**
+ * @brief HSUART IT Flag Definition
+ */
+typedef enum {
+    HSUART_IT_RX_DMA_HF     = 0x01,
+    HSUART_IT_RX_TMR_OV     = 0x02,
+    HSUART_IT_TX            = 0x04,
+    HSUART_IT_RX            = 0x08,
+} HSUART_IT_TYPEDEF;
+
+/**
+ * @brief TX Stop Bit Enumeration
+ */
+typedef enum {
+    HSUT_STOP_BIT_1BIT      = 0x00000000,
+    HSUT_STOP_BIT_2BIT      = 0x00000200,
+} HSUT_TX_STOP_BIT_TYPEDEF;
+
+/**
+ * @brief TX Word Length Enumeration
+ */
+typedef enum {
+    HSUT_TX_LENGTH_8b       = 0x00000000,
+    HSUT_TX_LENGTH_9b       = 0x00000100,
+} HSUT_TX_WORD_LENGTH;
+
+/**
+ * @brief TX Transmit Mode Enumeration
+ */
+typedef enum {
+    HSUT_TX_BUF_MODE        = 0x00000000,
+    HSUT_TX_DMA_MODE        = 0x00000080,
+} HSUT_TX_MODE;
+
+/**
+ * @brief RX Word Length Enumeration
+ */
+typedef enum {
+    HSUT_RX_LENGTH_8b       = 0x00000000,
+    HSUT_RX_LENGTH_9b       = 0x00000020,
+} HSUT_RX_WORD_LENGTH;
+
+/**
+ * @brief RX Transmit Mode Enumeration
+ */
+typedef enum {
+    HSUT_RX_BUF_MODE        = 0x00000000,
+    HSUT_RX_DMA_MODE        = 0x00000010,
+} HSUT_RX_MODE;
+
+/**
+ * @brief Receive or Transmit Enumeration
+ */
+typedef enum {
+    HSUT_RECEIVE            = 0x00000001,
+    HSUT_TRANSMIT           = 0x00000002,
+} HSUT_REC_TRA_CMD;
+
+/**
+ * @brief One-line Mode Enumeration
+ */
+typedef enum {
+    HSUT_ONELINE_DIS        = 0x00000000,
+    HSUT_ONELINE_EN         = 0x00040000,
+} HSUT_ONELINE_TYPEDEF;
+
+/**
+ * @brief Rx DMA Mode Loop Buf Enumeration
+ */
+typedef enum {
+    HSUT_DMA_BUF_SINGLE     = 0x00000000,
+    HSUT_DMA_BUF_LOOP       = 0x00000040,
+} HSUT_DMA_BUF_TYPEDEF;
+
+/**
+ * @brief Clock Selection
+ */
+typedef enum {
+    HSUT_24M_CLK,
+    HSUT_48M_CLK,
+    HSUT_PLLDIV4_CLK,
+} HSUT_CLK_TYPEDEF;
+
+/**
+ * @brief HSUART Init Structure
+ */
+typedef struct {
+    uint32_t                    baud;
+    HSUT_TX_STOP_BIT_TYPEDEF    tx_stop_bit;
+    HSUT_TX_WORD_LENGTH         tx_word_len;
+    HSUT_RX_WORD_LENGTH         rx_word_len;
+    HSUT_TX_MODE                tx_mode;
+    HSUT_RX_MODE                rx_mode;
+    HSUT_DMA_BUF_TYPEDEF        rx_dma_buf_mode;
+    HSUT_CLK_TYPEDEF            clk_source;
+    HSUT_ONELINE_TYPEDEF        one_line_en;
+} hsuart_init_typedef;
+
+//--------------- Function used to configure hsuart ----------------//
+void hsuart_init(hsuart_init_typedef *hsuart_init_struct);
+void hsuart_deinit(void);
+void hsuart_cmd(HSUT_REC_TRA_CMD rec_tra_sel, FUNCTIONAL_STATE state);
+void hsuart_send_data(uint16_t data);
+uint16_t hsuart_receive_data(void);
+STATUS_STATE hsuart_receive_data_from_fifo(uint8_t *buf, uint8_t len);
+uint16_t hsuart_get_fifo_counter(void);
+void hsuart_clear_fifo_counter(void);
+void hsuart_baud_config(uint32_t baud);
+//---------- Function used to configure hsuart interrupt -----------//
+void hsuart_pic_config(isr_t isr, int pr, HSUART_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state);
+FLAG_STATE hsuart_get_flag(HSUART_IT_TYPEDEF interrupt_type);
+void hsuart_clear_flag(HSUART_IT_TYPEDEF interrupt_type);
+void hsuart_rx_idle_config(uint16_t idle_time, FUNCTIONAL_STATE state);
+//------------- Function used to configure hsuart DMA --------------//
+void hsuart_dma_start(HSUT_REC_TRA_CMD rec_tra_sel, uint32_t addr, uint16_t len);
+void hsuart_dma_stop(HSUT_REC_TRA_CMD rec_tra_sel);
+
+#endif // _DRIVER_HSUART_H

+ 318 - 0
driver/driver_iic.c

@@ -0,0 +1,318 @@
+/*
+ * @File name    : driver_iic.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-14
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the IIC peripheral.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_iic.h"
+
+/**
+  * @brief  Initializes the IIC peripheral according to the specified
+  *         parameters in the iic_init_typedef.
+  * @param  iic_init_struct: pointer to a iic_init_typedef structure that
+  *         contains the configuration information for the specified IIC peripheral.
+  * @retval None
+  */
+void iic_init(iic_init_typedef *iic_init_struct)
+{
+    /*--- Configure the iic clock source ---*/
+    CLKCON1 &= ~(1 << 23);
+    CLKCON1 |= iic_init_struct->clk_source;
+
+    /*--- Configure the iic SCL pose div conter ---*/
+    IIC->con0 &= ~IICCON0_POSDIV;
+    IIC->con0 |= ((iic_init_struct->scl_pose_div) << 4) & IICCON0_POSDIV;
+
+    /*--- Configure the iic SDA hold cnt when SCL falling ---*/
+    IIC->con0 &= ~IICCON0_HOLDCNT;
+    IIC->con0 |= ((iic_init_struct->sda_hold_cnt) << 2) & IICCON0_HOLDCNT;
+
+    /*--- Configure the iic controller work mode ---*/
+    IIC->con0 &= ~IICCON0_MODE;
+    IIC->con0 |= ((iic_init_struct->mode_sel) << 12) & IICCON0_MODE;
+    
+    /*--- Enable model function ---*/
+    RSTCON0 |= (1 << 3);
+}
+
+/**
+ * @brief  De-initialize the specified IIC peripheral.
+ * @retval None
+ */
+void iic_deinit(void)
+{
+    IIC->con0 = 0;
+    clk_gate2_cmd(CLK_GATE2_IIC, CLK_DIS);
+}
+
+/**
+  * @brief  Enable or disable the specified IIC peripheral.
+  * @param  state: state of the IIC peripheral.
+  *         This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void iic_cmd(FUNCTIONAL_STATE state)
+{
+    if (state != DISABLE) {
+        IIC->con0 |= IICCON0_IICEN;
+    } else {
+        IIC->con0 &= ~IICCON0_IICEN;
+    }
+}
+
+/**
+  * @brief  Initializes the IIC control regisger according to param.
+  * @param  transmit_mode: select the iic transmit direction.
+  *         This parameter can be: IIC_SEND_MODE or IIC_RECEIVE_MODE.
+  * @param  dev_addr: the slave device address.
+  * @param  reg_addr: the address of the slave device register.
+  * @param  len: the numbers of bytes of data.
+  * @retval None
+  */
+static void iic_transmit_config(IIC_TRANSMIT_MODE transmit_mode, uint8_t dev_addr, uint16_t reg_addr, uint8_t len)
+{
+    IIC->con1 = 0;
+    IIC->con1 |= IICCON1_STOP_EN;
+
+    IIC->con1 |= IICCON1_ADR0_EN;
+    IIC->con1 |= IICCON1_CTL0_EN;
+    IIC->con1 |= IICCON1_START0_EN;
+    IIC->con1 |= len & IICCON1_DATA_CNT;
+    if (reg_addr & 0xff00) {
+        IIC->con1 |= IICCON1_ADR1_EN;
+    }
+
+    IIC->cmd_addr = (dev_addr & 0xfe) | (reg_addr << 8);
+
+    if (transmit_mode == IIC_SEND_MODE) {
+        IIC->con1 |= IICCON1_WDAT_EN;
+    } else if (transmit_mode == IIC_RECEIVE_MODE) {
+        IIC->con1 |= IICCON1_TXNAK_EN;
+        IIC->con1 |= IICCON1_RDAT_EN;
+        IIC->con1 |= IICCON1_CTL1_EN;
+        IIC->con1 |= IICCON1_START1_EN;
+        IIC->cmd_addr |= ((dev_addr | 0x01) << 24);
+    }
+    IIC->dma_cnt &= ~(0x01 << 0);
+}
+
+/**
+  * @brief  Send data by iic bus, this function will block program.
+  * @param  dev_addr: the slave device address.
+  * @param  reg_addr: the address of the slave device register.
+  * @param  data: the data needed to transmit.
+  * @param  len: the numbers of bytes of data. A maximum of 4 bytes cna be
+  *              transmitted at a time. So len should less than or equal to 4.
+  * @param  timeout_ms: timeout period for waiting for a result.
+  * @retval The status of result. It can be (FAILED or SUCCESS).
+  */
+STATUS_STATE iic_send_data(uint8_t dev_addr, uint16_t reg_addr, uint32_t data, uint8_t len, uint8_t timeout_ms)
+{
+    iic_transmit_config(IIC_SEND_MODE, dev_addr, reg_addr, len);
+
+    IIC->data = data;
+
+    IIC->con0 |= IICCON0_KS;
+
+    if (timeout_ms == 0) {
+        while ((IIC->con0 & IICCON0_DONE) == RESET);
+        IIC->con0 |= IICCON0_CLR_DONE;
+        return SUCCESS;
+    } else {
+        while (timeout_ms) {
+            if ((IIC->con0 & IICCON0_DONE) != RESET) {
+                IIC->con0 |= IICCON0_CLR_DONE;
+                return SUCCESS;
+            }
+            timeout_ms--;
+            delay_ms(1);
+        }
+    }
+
+    return FAILED;
+}
+
+AT(.com_periph.iic.dma)
+STATUS_STATE iic_dma_start(IIC_TRANSMIT_MODE transmit_mode, uint8_t dev_addr, uint16_t reg_addr, uint8_t *buf, uint16_t len)
+{
+    if (!len) {
+        return FAILED;
+    }
+
+    IIC->con1 = 0;
+
+    IIC->con1 |= IICCON1_CTL0_EN;
+    IIC->con1 |= IICCON1_START0_EN;
+    IIC->con1 |= IICCON1_ADR0_EN;
+
+    if (reg_addr & 0xff00) {
+        IIC->con1 |= IICCON1_ADR1_EN;
+    }
+
+    IIC->con1 |= IICCON1_STOP_EN;
+    IIC->con1 |= len & IICCON1_DATA_CNT;
+
+    IIC->cmd_addr = (dev_addr & 0xfe) | (reg_addr << 8);
+
+    /* DMA Config */
+    IIC->dma_addr = ALIGN4_HI((u32)buf);
+    IIC->dma_cnt  = ((len - 1) << 16);
+    IIC->dma_cnt &= ~(0x01 << 1);            // dma enable
+    IIC->dma_cnt |= (0x01 << 0);            // dma enable
+
+#if 1
+    if (transmit_mode == IIC_SEND_MODE) {
+        /* Write Mode Config */
+        IIC->con1 |= IICCON1_WDAT_EN;
+        IIC->dma_cnt |= (0x01 << 1);        //dma read enable
+    } else if (transmit_mode == IIC_RECEIVE_MODE) {
+        /* Read Mode Config */
+        IIC->con1 |= IICCON1_CTL1_EN;
+        IIC->con1 |= IICCON1_RDAT_EN;
+        IIC->con1 |= IICCON1_START1_EN;
+        IIC->con1 |= IICCON1_TXNAK_EN;
+        IIC->cmd_addr |= (dev_addr | 0x01) << 24;
+    }
+#endif
+    IIC->con0 |= IICCON0_KS;
+
+    return SUCCESS;
+}
+
+/**
+  * @brief  Receive data by iic bus, this function will block program.
+  * @param  dev_addr: the slave device address.
+  * @param  reg_addr: the address of the slave device.
+  * @param  len: the numbers of bytes of data.
+  * @param  timeout_ms: timeout period for waiting for a result.
+  * @retval The status of result. It can be (FAILED or SUCCESS).
+  */
+STATUS_STATE iic_receive_data(uint8_t dev_addr, uint16_t reg_addr, uint32_t *data, uint8_t len, uint8_t timeout_ms)
+{
+    iic_transmit_config(IIC_RECEIVE_MODE, dev_addr, reg_addr, len);
+
+    IIC->con0 |= IICCON0_KS;
+    if (timeout_ms == 0) {
+        while ((IIC->con0 & IICCON0_DONE) == RESET);
+        IIC->con0 |= IICCON0_CLR_DONE;
+        *data = IIC->data;
+        return SUCCESS;
+    } else {
+        while (timeout_ms) {
+            if ((IIC->con0 & IICCON0_DONE) != RESET) {
+                IIC->con0 |= IICCON0_CLR_DONE;
+                *data = IIC->data;
+                return SUCCESS;
+            }
+            timeout_ms--;
+            delay_ms(1);
+        }
+    }
+
+    return FAILED;
+}
+
+/**
+  * @brief  Enable or disable the specified IIC interrupt.
+  * @param  isr: Function to be executed for service interruption.
+  * @param  pr: Priority of service interruption.
+  * @param  interrupt_type: specifies the IIC interrupt sources to be enable or disable.
+  *         this parameter can be one of the following values:
+  *             @arg IIC_IT_DONE: IIC transmit finished interrupt.
+  * @param  state: the state of the IIC peripheral.
+  *         this parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void iic_pic_config(isr_t isr, int pr, IIC_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state)
+{
+    uint32_t interrupt_bit = 0;
+    uint32_t all_interrupt_type_mask = IIC_IT_DONE;
+
+    if (interrupt_type == 0) {
+        return;
+    }
+
+    if (interrupt_type & IIC_IT_DONE) {
+        interrupt_bit |= IICCON0_INTEN;
+    }
+
+    if (state != DISABLE) {
+        IIC->con0 |= interrupt_bit;
+        sys_irq_init(IRQn_IIC, pr, isr);
+    } else {
+        IIC->con0 &= ~(uint32_t)interrupt_bit;
+        if (interrupt_type == all_interrupt_type_mask) {
+            PICEN &= ~BIT(IRQn_IIC);
+        }
+    }
+}
+
+/**
+  * @brief  Get the IIC interrupt pending.
+  * @param  interrupt_type: specifies the flag to get.
+  *         this parameter can be one of the following values:
+  *             @arg IIC_IT_DONE: IIC transmit finished flag.
+  *             @arg IIC_IT_ACK: IIC receive slave device ack flag.
+  * @retval The state of iic_flag (SET or RESET).
+  */
+AT(.com_periph.iic.get)
+FLAG_STATE iic_get_flag(IIC_IT_TYPEDEF interrupt_type)
+{
+    uint32_t interrupt_bit = 0;
+
+    if (interrupt_type & IIC_IT_DONE) {
+        interrupt_bit |= IICCON0_DONE;
+    }
+
+    if (interrupt_type & IIC_IT_ACK) {
+        interrupt_bit |= IICCON0_ACKSTATUS;
+    }
+
+    if ((IIC->con0 & interrupt_bit) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+  * @brief  Clear all status.
+  * @retval None
+  */
+AT(.com_periph.iic.clear)
+void iic_clear_all_flag(void)
+{
+    IIC->con0 |= IICCON0_CLR_ALL;
+}
+
+/**
+  * @brief  Send NACK to the master when in slave mode.
+  * @retval None
+  */
+AT(.com_periph.iic.nack_en)
+void iic_send_nack_en(FUNCTIONAL_STATE state)
+{
+    if (state != DISABLE) {
+        IIC->con0 |= IICCON0_RX_NACK_EN;
+    } else {
+        IIC->con0 &= ~IICCON0_RX_NACK_EN;
+    }
+}
+
+/**
+  * @brief  Data sample edge selection in slave mode.
+  * @retval None
+  */
+AT(.com_periph.iic.smp_sel)
+void iic_smp_sel(IIC_SMP_SEL_TYPEDEF edge)
+{
+    if (edge != IIC_SMP_SEL_FALLING) {
+        IIC->con0 |= IICCON0_SMP_SEL;
+    } else {
+        IIC->con0 &= ~IICCON0_SMP_SEL;
+    }
+}
+

+ 77 - 0
driver/driver_iic.h

@@ -0,0 +1,77 @@
+/*
+ * @File name    : driver_iic.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-15
+ * @Description  : This file contains all the functions prototypes for the IIC library.
+ * 
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_IIC_H
+#define _DRIVER_IIC_H
+
+#include "driver_com.h"
+
+/**
+ * @brief IIC IT and Flag Definition
+ */
+typedef enum {
+    IIC_IT_DONE             = 0x01,
+    IIC_IT_ACK              = 0x02,
+} IIC_IT_TYPEDEF;
+
+/**
+ * @brief IIC Clock Source Enumeration
+ */
+typedef enum {
+    IIC_CLK_RC2M            = 0x00000000,
+    IIC_CLK_X24MDIV8        = 0x00800000,
+} IIC_CLK_SOURCE_TYPEDEF;
+
+/**
+ * @brief IIC Role Mode Enumeration
+ */
+typedef enum {
+    IIC_ROLE_MODE_MASTER                    = 0,
+    IIC_ROLE_MODE_SLAVE                     = 1,
+} IIC_ROLE_MODE_TYPEDEF;
+
+/**
+ * @brief IIC Data Sample Edge Selection In Slave Mode.
+ */
+typedef enum {
+    IIC_SMP_SEL_FALLING                     = 0,
+    IIC_SMP_SEL_RISING                      = 1,
+} IIC_SMP_SEL_TYPEDEF;
+
+/**
+ * @brief IIC Transmit Direction Enumeration
+ */
+typedef enum {
+    IIC_SEND_MODE           = 1,
+    IIC_RECEIVE_MODE        = 2,
+} IIC_TRANSMIT_MODE;
+
+/**
+ * @brief IIC Init Structure
+ */
+typedef struct {
+    uint8_t                 scl_pose_div;
+    uint8_t                 sda_hold_cnt;
+    IIC_CLK_SOURCE_TYPEDEF  clk_source;
+    IIC_ROLE_MODE_TYPEDEF   mode_sel;
+} iic_init_typedef;
+
+//--------------- Function used to configure iic or transmit data ---------------//
+void iic_init(iic_init_typedef *iic_init_struct);
+void iic_deinit(void);
+void iic_cmd(FUNCTIONAL_STATE state);
+STATUS_STATE iic_send_data(uint8_t dev_addr, uint16_t reg_addr, uint32_t data, uint8_t len, uint8_t timeout_ms);
+STATUS_STATE iic_receive_data(uint8_t dev_addr, uint16_t reg_addr, uint32_t *data, uint8_t len, uint8_t timeout_ms);
+//------------------- Function used to configure interrupt -------------------//
+void iic_pic_config(isr_t isr, int pr, IIC_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state);
+FLAG_STATE iic_get_flag(IIC_IT_TYPEDEF interrupt_type);
+void iic_clear_all_flag(void);
+void iic_send_nack_en(FUNCTIONAL_STATE state);
+void iic_smp_sel(IIC_SMP_SEL_TYPEDEF edge);
+
+#endif // _DRIVER_IIC_H

+ 665 - 0
driver/driver_ir.h

@@ -0,0 +1,665 @@
+/**
+******************************************************************************************************************************
+*
+*@file driver_ir.h
+*
+*@brief Header file for IR driver
+*
+*Copyright (c) 2023, BLUETRUM
+******************************************************************************************************************************
+**/
+#ifndef _IR_H_
+#define _IR_H_
+
+#include "driver_com.h"
+
+//IRTX
+
+// IR One Code Time Register
+#define ADDR_REG_IRONETIME                          *(volatile unsigned long*) (SFR7_BASE + 0x20*4)
+
+// IR Zero Code Time Register
+#define ADDR_REG_IRZEROTIME                         *(volatile unsigned long*) (SFR7_BASE + 0x21*4)
+
+// IR Start Code Time Register
+#define ADDR_REG_IRSTARTTIME                        *(volatile unsigned long*) (SFR7_BASE + 0x22*4)
+
+// IR Repeat Code Time Register
+#define ADDR_REG_IRREPEATTIME                       *(volatile unsigned long*) (SFR7_BASE + 0x23*4)
+
+// IR Repeat Code Control Register
+#define ADDR_REG_IRREPEATCON                        *(volatile unsigned long*) (SFR7_BASE + 0x24*4)
+// IR TX Interval Between Repeat Time = (IRREPTIME + 1) * (1M Or 32K)
+#define POS_REG_IRREPEATCON_IRREPTIME               13
+#define BIT_REG_IRREPEATCON_IRREPTIME               0xFFFFE000
+#define SET_REG_IRREPEATCON_IRREPTIME(val)          ADDR_REG_IRREPEATCON = ((ADDR_REG_IRREPEATCON & (~BIT_REG_IRREPEATCON_IRREPTIME)) | ((val) << POS_REG_IRREPEATCON_IRREPTIME))
+#define GET_REG_IRREPEATCON_IRREPTIME()             ((ADDR_REG_IRREPEATCON & BIT_REG_IRREPEATCON_IRREPTIME) >> POS_REG_IRREPEATCON_IRREPTIME)
+// IR TX End Pulse Time(NEC Or TC9012) = (IRENDTIME  + 1) * (1M Or 32K)
+#define POS_REG_IRREPEATCON_IRENDTIME               3
+#define BIT_REG_IRREPEATCON_IRENDTIME               0x8FF8
+#define SET_REG_IRREPEATCON_IRENDTIME(val)          ADDR_REG_IRREPEATCON = ((ADDR_REG_IRREPEATCON & (~BIT_REG_IRREPEATCON_IRENDTIME)) | ((val) << POS_REG_IRREPEATCON_IRENDTIME))
+#define GET_REG_IRREPEATCON_IRENDTIME()             ((ADDR_REG_IRREPEATCON & BIT_REG_IRREPEATCON_IRENDTIME) >> POS_REG_IRREPEATCON_IRENDTIME)
+// IR TX If tc9012 Indicated As Sync Code
+#define POS_REG_IRREPEATCON_IRTX_SYC                2
+#define BIT_REG_IRREPEATCON_IRTX_SYC                0x4
+#define SETF_REG_IRREPEATCON_IRTX_SYC()             ADDR_REG_IRREPEATCON |= BIT_REG_IRREPEATCON_IRTX_SYC
+#define CLRF_REG_IRREPEATCON_IRTX_SYC()             ADDR_REG_IRREPEATCON &= ~BIT_REG_IRREPEATCON_IRTX_SYC
+#define GETF_REG_IRREPEATCON_IRTX_SYC()             ((ADDR_REG_IRREPEATCON & BIT_REG_IRREPEATCON_IRTX_SYC) >> POS_REG_IRREPEATCON_IRTX_SYC)
+// IR TX Repeat Mode
+#define POS_REG_IRREPEATCON_IRREP_SEL               1
+#define BIT_REG_IRREPEATCON_IRREP_SEL               0x2
+#define SETF_REG_IRREPEATCON_IRREP_SEL()            ADDR_REG_IRREPEATCON |= BIT_REG_IRREPEATCON_IRREP_SEL
+#define CLRF_REG_IRREPEATCON_IRREP_SEL()            ADDR_REG_IRREPEATCON &= ~BIT_REG_IRREPEATCON_IRREP_SEL
+#define GETF_REG_IRREPEATCON_IRREP_SEL()            ((ADDR_REG_IRREPEATCON & BIT_REG_IRREPEATCON_IRREP_SEL) >> POS_REG_IRREPEATCON_IRREP_SEL)
+// IR TX Whether Key Is Release
+#define POS_REG_IRREPEATCON_IRTX_KEY                0
+#define BIT_REG_IRREPEATCON_IRTX_KEY                0x1
+#define SETF_REG_IRREPEATCON_IRTX_KEY()             ADDR_REG_IRREPEATCON |= BIT_REG_IRREPEATCON_IRTX_KEY
+#define CLRF_REG_IRREPEATCON_IRTX_KEY()             ADDR_REG_IRREPEATCON &= ~BIT_REG_IRREPEATCON_IRTX_KEY
+#define GETF_REG_IRREPEATCON_IRTX_KEY()             ((ADDR_REG_IRREPEATCON & BIT_REG_IRREPEATCON_IRTX_KEY) >> POS_REG_IRREPEATCON_IRTX_KEY)
+
+// IR TX Control Register
+#define ADDR_REG_IRTXCON                            *(volatile unsigned long*) (SFR7_BASE + 0x25*4)
+// IR TX Carrier Duty = (IRCW_DUTY / IRCW_LENGTH + 1)
+#define POS_REG_IRTXCON_IRCW_DUTY                   20
+#define BIT_REG_IRTXCON_IRCW_DUTY                   0xFF00000
+#define SET_REG_IRTXCON_IRCW_DUTY(val)              ADDR_REG_IRTXCON = ((ADDR_REG_IRTXCON & (~BIT_REG_IRTXCON_IRCW_DUTY)) | ((val) << POS_REG_IRTXCON_IRCW_DUTY))
+#define GET_REG_IRTXCON_IRCW_DUTY()                 ((ADDR_REG_IRTXCON & BIT_REG_IRTXCON_IRCW_DUTY) >> POS_REG_IRTXCON_IRCW_DUTY)
+// IR TX Carrier Freq = (3M(or 4M) / IRCW_LENGTH + 1)
+#define POS_REG_IRTXCON_IRCW_LENGTH                 12
+#define BIT_REG_IRTXCON_IRCW_LENGTH                 0xFF000
+#define SET_REG_IRTXCON_IRCW_LENGTH(val)            ADDR_REG_IRTXCON = ((ADDR_REG_IRTXCON & (~BIT_REG_IRTXCON_IRCW_LENGTH)) | ((val) << POS_REG_IRTXCON_IRCW_LENGTH))
+#define GET_REG_IRTXCON_IRCW_LENGTH()               ((ADDR_REG_IRTXCON & BIT_REG_IRTXCON_IRCW_LENGTH) >> POS_REG_IRTXCON_IRCW_LENGTH)
+// IR TX Carrier Enable
+#define POS_REG_IRTXCON_IRTX_CARRIER_EN             11
+#define BIT_REG_IRTXCON_IRTX_CARRIER_EN             0x800
+#define SETF_REG_IRTXCON_IRTX_CARRIER_EN()          ADDR_REG_IRTXCON |= BIT_REG_IRTXCON_IRTX_CARRIER_EN
+#define CLRF_REG_IRTXCON_IRTX_CARRIER_EN()          ADDR_REG_IRTXCON &= ~BIT_REG_IRTXCON_IRTX_CARRIER_EN
+#define GETF_REG_IRTXCON_IRTX_CARRIER_EN()          ((ADDR_REG_IRTXCON & BIT_REG_IRTXCON_IRTX_CARRIER_EN) >> POS_REG_IRTXCON_IRTX_CARRIER_EN)
+// IR TX Select Fall Or Rise Trigger In Capture Mode
+#define POS_REG_IRTXCON_IREDGE_SEL                  10
+#define BIT_REG_IRTXCON_IREDGE_SEL                  0x400
+#define SETF_REG_IRTXCON_IREDGE_SEL()               ADDR_REG_IRTXCON |= BIT_REG_IRTXCON_IREDGE_SEL
+#define CLRF_REG_IRTXCON_IREDGE_SEL()               ADDR_REG_IRTXCON &= ~BIT_REG_IRTXCON_IREDGE_SEL
+#define GETF_REG_IRTXCON_IREDGE_SEL()               ((ADDR_REG_IRTXCON & BIT_REG_IRTXCON_IREDGE_SEL) >> POS_REG_IRTXCON_IREDGE_SEL)
+// IR TX Select Encoding Format In Modulation Mode
+#define POS_REG_IRTXCON_IRTX_SEL                    8
+#define BIT_REG_IRTXCON_IRTX_SEL                    0x300
+#define SET_REG_IRTXCON_IRTX_SEL(val)               ADDR_REG_IRTXCON = ((ADDR_REG_IRTXCON & (~BIT_REG_IRTXCON_IRTX_SEL)) | ((val) << POS_REG_IRTXCON_IRTX_SEL))
+#define GET_REG_IRTXCON_IRTX_SEL()                  ((ADDR_REG_IRTXCON & BIT_REG_IRTXCON_IRTX_SEL) >> POS_REG_IRTXCON_IRTX_SEL)
+// IR TX Interrup Enable In Modualtion Mode
+#define POS_REG_IRTXCON_IRTX_IE                     7
+#define BIT_REG_IRTXCON_IRTX_IE                     0x80
+#define SETF_REG_IRTXCON_IRTX_IE()                  ADDR_REG_IRTXCON |= BIT_REG_IRTXCON_IRTX_IE
+#define CLRF_REG_IRTXCON_IRTX_IE()                  ADDR_REG_IRTXCON &= ~BIT_REG_IRTXCON_IRTX_IE
+#define GETF_REG_IRTXCON_IRTX_IE()                  ((ADDR_REG_IRTXCON & BIT_REG_IRTXCON_IRTX_IE) >> POS_REG_IRTXCON_IRTX_IE)
+// IR Capture Enable
+#define POS_REG_IRTXCON_IR_CAPEN                    6
+#define BIT_REG_IRTXCON_IR_CAPEN                    0x40
+#define SETF_REG_IRTXCON_IR_CAPEN()                 ADDR_REG_IRTXCON |= BIT_REG_IRTXCON_IR_CAPEN
+#define CLRF_REG_IRTXCON_IR_CAPEN()                 ADDR_REG_IRTXCON &= ~BIT_REG_IRTXCON_IR_CAPEN
+#define GETF_REG_IRTXCON_IR_CAPEN()                 ((ADDR_REG_IRTXCON & BIT_REG_IRTXCON_IR_CAPEN) >> POS_REG_IRTXCON_IR_CAPEN)
+// IR TX Code "1" Mode
+#define POS_REG_IRTXCON_IRTX_1MODE                  5
+#define BIT_REG_IRTXCON_IRTX_1MODE                  0x20
+#define SETF_REG_IRTXCON_IRTX_1MODE()               ADDR_REG_IRTXCON |= BIT_REG_IRTXCON_IRTX_1MODE
+#define CLRF_REG_IRTXCON_IRTX_1MODE()               ADDR_REG_IRTXCON &= ~BIT_REG_IRTXCON_IRTX_1MODE
+#define GETF_REG_IRTXCON_IRTX_1MODE()               ((ADDR_REG_IRTXCON & BIT_REG_IRTXCON_IRTX_1MODE) >> POS_REG_IRTXCON_IRTX_1MODE)
+// IR TX Code "0" Mode
+#define POS_REG_IRTXCON_IRTX_0MODE                  4
+#define BIT_REG_IRTXCON_IRTX_0MODE                  0x10
+#define SETF_REG_IRTXCON_IRTX_0MODE()               ADDR_REG_IRTXCON |= BIT_REG_IRTXCON_IRTX_0MODE
+#define CLRF_REG_IRTXCON_IRTX_0MODE()               ADDR_REG_IRTXCON &= ~BIT_REG_IRTXCON_IRTX_0MODE
+#define GETF_REG_IRTXCON_IRTX_0MODE()               ((ADDR_REG_IRTXCON & BIT_REG_IRTXCON_IRTX_0MODE) >> POS_REG_IRTXCON_IRTX_0MODE)
+// IR TX Invert
+#define POS_REG_IRTXCON_IRTX_INV                    3
+#define BIT_REG_IRTXCON_IRTX_INV                    0x8
+#define SETF_REG_IRTXCON_IRTX_INV()                 ADDR_REG_IRTXCON |= BIT_REG_IRTXCON_IRTX_INV
+#define CLRF_REG_IRTXCON_IRTX_INV()                 ADDR_REG_IRTXCON &= ~BIT_REG_IRTXCON_IRTX_INV
+#define GETF_REG_IRTXCON_IRTX_INV()                 ((ADDR_REG_IRTXCON & BIT_REG_IRTXCON_IRTX_INV) >> POS_REG_IRTXCON_IRTX_INV)
+// IR TX Kick Start In Modulation Mode Or Learn Mode
+#define POS_REG_IRTXCON_IRTX_KST                    2
+#define BIT_REG_IRTXCON_IRTX_KST                    0x4
+#define SETF_REG_IRTXCON_IRTX_KST()                 ADDR_REG_IRTXCON |= BIT_REG_IRTXCON_IRTX_KST
+#define CLRF_REG_IRTXCON_IRTX_KST()                 ADDR_REG_IRTXCON &= ~BIT_REG_IRTXCON_IRTX_KST
+// IR TX Learn Mode Enable
+#define POS_REG_IRTXCON_IRTXLEN_EN                  1
+#define BIT_REG_IRTXCON_IRTXLEN_EN                  0x2
+#define SETF_REG_IRTXCON_IRTXLEN_EN()               ADDR_REG_IRTXCON |= BIT_REG_IRTXCON_IRTXLEN_EN
+#define CLRF_REG_IRTXCON_IRTXLEN_EN()               ADDR_REG_IRTXCON &= ~BIT_REG_IRTXCON_IRTXLEN_EN
+#define GETF_REG_IRTXCON_IRTXLEN_EN()               ((ADDR_REG_IRTXCON & BIT_REG_IRTXCON_IRTXLEN_EN) >> POS_REG_IRTXCON_IRTXLEN_EN)
+// IR TX Modulation Mode Enable
+#define POS_REG_IRTXCON_IRTXMOD_EN                  0
+#define BIT_REG_IRTXCON_IRTXMOD_EN                  0x1
+#define SETF_REG_IRTXCON_IRTXMOD_EN()               ADDR_REG_IRTXCON |= BIT_REG_IRTXCON_IRTXMOD_EN
+#define CLRF_REG_IRTXCON_IRTXMOD_EN()               ADDR_REG_IRTXCON &= ~BIT_REG_IRTXCON_IRTXMOD_EN
+#define GETF_REG_IRTXCON_IRTXMOD_EN()               ((ADDR_REG_IRTXCON & BIT_REG_IRTXCON_IRTXMOD_EN) >> POS_REG_IRTXCON_IRTXMOD_EN)
+
+// IR TX Data Register
+#define ADDR_REG_IRTXDAT                            *(volatile unsigned long*) (SFR7_BASE + 0x26*4)
+// IR TX Data
+#define POS_REG_IRTXDAT                             0
+#define BIT_REG_IRTXDAT                             0xFFFFFFFF
+#define SET_REG_IRTXDAT(val)                        ADDR_REG_IRTXDAT = ((ADDR_REG_IRTXDAT & (~BIT_REG_IRTXDAT)) | ((val) << POS_REG_IRTXDAT))
+#define GET_REG_IRTXDAT()                           ((ADDR_REG_IRTXDAT & BIT_REG_IRTXDAT) >> POS_REG_IRTXDAT)
+
+// IR TX Data Length Register
+#define ADDR_REG_IRTXLEN                            *(volatile unsigned long*) (SFR7_BASE + 0x27*4)
+// IR TX Length
+#define POS_REG_IRTXLEN                             0
+#define BIT_REG_IRTXLEN                             0xFFFFFFFF
+#define SET_REG_IRTXLEN(val)                        ADDR_REG_IRTXLEN = ((ADDR_REG_IRTXLEN & (~BIT_REG_IRTXLEN)) | ((val) << POS_REG_IRTXLEN))
+#define GET_REG_IRTXLEN()                           ((ADDR_REG_IRTXLEN & BIT_REG_IRTXLEN) >> POS_REG_IRTXLEN)
+
+// IR TX Clear Pending Register
+#define ADDR_REG_IRTXPEND                           *(volatile unsigned long*) (SFR7_BASE + 0x28*4)
+// IR TX Modulation Mode Enable
+#define POS_REG_IRTXPEND_IRTX_PND                   0
+#define BIT_REG_IRTXPEND_IRTX_PND                   0x1
+#define SETF_REG_IRTXPEND_IRTX_PND()                ADDR_REG_IRTXPEND |= BIT_REG_IRTXPEND_IRTX_PND
+#define CLRF_REG_IRTXPEND_IRTX_PND()                ADDR_REG_IRTXPEND &= ~BIT_REG_IRTXPEND_IRTX_PND
+#define GETF_REG_IRTXPEND_IRTX_PND()                ((ADDR_REG_IRTXPEND & BIT_REG_IRTXPEND_IRTX_PND) >> POS_REG_IRTXPEND_IRTX_PND)
+
+// IR DMA Control Register
+#define ADDR_REG_IRDMACON                           *(volatile unsigned long*) (SFR7_BASE + 0x29*4)
+// IR Write DMA Mode
+#define POS_REG_IRDMACON_IR_WDMA_MODE               7
+#define BIT_REG_IRDMACON_IR_WDMA_MODE               0x80
+#define SETF_REG_IRDMACON_IR_WDMA_MODE()            ADDR_REG_IRDMACON |= BIT_REG_IRDMACON_IR_WDMA_MODE
+#define CLRF_REG_IRDMACON_IR_WDMA_MODE()            ADDR_REG_IRDMACON &= ~BIT_REG_IRDMACON_IR_WDMA_MODE
+#define GETF_REG_IRDMACON_IR_WDMA_MODE()            ((ADDR_REG_IRDMACON & BIT_REG_IRDMACON_IR_WDMA_MODE) >> POS_REG_IRDMACON_IR_WDMA_MODE)
+// IR Write DMA Half Interrup Enable
+#define POS_REG_IRDMACON_IR_WDMA_HPND_IE            6
+#define BIT_REG_IRDMACON_IR_WDMA_HPND_IE            0x40
+#define SETF_REG_IRDMACON_IR_WDMA_HPND_IE()         ADDR_REG_IRDMACON |= BIT_REG_IRDMACON_IR_WDMA_HPND_IE
+#define CLRF_REG_IRDMACON_IR_WDMA_HPND_IE()         ADDR_REG_IRDMACON &= ~BIT_REG_IRDMACON_IR_WDMA_HPND_IE
+#define GETF_REG_IRDMACON_IR_WDMA_HPND_IE()         ((ADDR_REG_IRDMACON & BIT_REG_IRDMACON_IR_WDMA_HPND_IE) >> POS_REG_IRDMACON_IR_WDMA_HPND_IE)
+// IR Write DMA All Interrup Enable
+#define POS_REG_IRDMACON_IR_WDMA_APND_IE            5
+#define BIT_REG_IRDMACON_IR_WDMA_APND_IE            0x20
+#define SETF_REG_IRDMACON_IR_WDMA_APND_IE()         ADDR_REG_IRDMACON |= BIT_REG_IRDMACON_IR_WDMA_APND_IE
+#define CLRF_REG_IRDMACON_IR_WDMA_APND_IE()         ADDR_REG_IRDMACON &= ~BIT_REG_IRDMACON_IR_WDMA_APND_IE
+#define GETF_REG_IRDMACON_IR_WDMA_APND_IE()         ((ADDR_REG_IRDMACON & BIT_REG_IRDMACON_IR_WDMA_APND_IE) >> POS_REG_IRDMACON_IR_WDMA_APND_IE)
+// IR Write DMA Enable
+#define POS_REG_IRDMACON_IR_WDMA_EN                 4
+#define BIT_REG_IRDMACON_IR_WDMA_EN                 0x10
+#define SETF_REG_IRDMACON_IR_WDMA_EN()              ADDR_REG_IRDMACON |= BIT_REG_IRDMACON_IR_WDMA_EN
+#define CLRF_REG_IRDMACON_IR_WDMA_EN()              ADDR_REG_IRDMACON &= ~BIT_REG_IRDMACON_IR_WDMA_EN
+#define GETF_REG_IRDMACON_IR_WDMA_EN()              ((ADDR_REG_IRDMACON & BIT_REG_IRDMACON_IR_WDMA_EN) >> POS_REG_IRDMACON_IR_WDMA_EN)
+
+// IR Read DMA Mode
+#define POS_REG_IRDMACON_IR_RDMA_MODE               3
+#define BIT_REG_IRDMACON_IR_RDMA_MODE               0x8
+#define SETF_REG_IRDMACON_IR_RDMA_MODE()            ADDR_REG_IRDMACON |= BIT_REG_IRDMACON_IR_RDMA_MODE
+#define CLRF_REG_IRDMACON_IR_RDMA_MODE()            ADDR_REG_IRDMACON &= ~BIT_REG_IRDMACON_IR_RDMA_MODE
+#define GETF_REG_IRDMACON_IR_RDMA_MODE()            ((ADDR_REG_IRDMACON & BIT_REG_IRDMACON_IR_RDMA_MODE) >> POS_REG_IRDMACON_IR_RDMA_MODE)
+// IR Read DMA Half Interrup Enable
+#define POS_REG_IRDMACON_IR_RDMA_HPND_IE            2
+#define BIT_REG_IRDMACON_IR_RDMA_HPND_IE            0x4
+#define SETF_REG_IRDMACON_IR_RDMA_HPND_IE()         ADDR_REG_IRDMACON |= BIT_REG_IRDMACON_IR_RDMA_HPND_IE
+#define CLRF_REG_IRDMACON_IR_RDMA_HPND_IE()         ADDR_REG_IRDMACON &= ~BIT_REG_IRDMACON_IR_RDMA_HPND_IE
+#define GETF_REG_IRDMACON_IR_RDMA_HPND_IE()         ((ADDR_REG_IRDMACON & BIT_REG_IRDMACON_IR_RDMA_HPND_IE) >> POS_REG_IRDMACON_IR_RDMA_HPND_IE)
+// IR Read DMA All Interrup Enable
+#define POS_REG_IRDMACON_IR_RDMA_APND_IE            1
+#define BIT_REG_IRDMACON_IR_RDMA_APND_IE            0x2
+#define SETF_REG_IRDMACON_IR_RDMA_APND_IE()         ADDR_REG_IRDMACON |= BIT_REG_IRDMACON_IR_RDMA_APND_IE
+#define CLRF_REG_IRDMACON_IR_RDMA_APND_IE()         ADDR_REG_IRDMACON &= ~BIT_REG_IRDMACON_IR_RDMA_APND_IE
+#define GETF_REG_IRDMACON_IR_RDMA_APND_IE()         ((ADDR_REG_IRDMACON & BIT_REG_IRDMACON_IR_RDMA_APND_IE) >> POS_REG_IRDMACON_IR_RDMA_APND_IE)
+// IR Read DMA Enable
+#define POS_REG_IRDMACON_IR_RDMA_EN                 0
+#define BIT_REG_IRDMACON_IR_RDMA_EN                 0x1
+#define SETF_REG_IRDMACON_IR_RDMA_EN()              ADDR_REG_IRDMACON |= BIT_REG_IRDMACON_IR_RDMA_EN
+#define CLRF_REG_IRDMACON_IR_RDMA_EN()              ADDR_REG_IRDMACON &= ~BIT_REG_IRDMACON_IR_RDMA_EN
+#define GETF_REG_IRDMACON_IR_RDMA_EN()              ((ADDR_REG_IRDMACON & BIT_REG_IRDMACON_IR_RDMA_EN) >> POS_REG_IRDMACON_IR_RDMA_EN)
+
+// IR DMA Input Address Register
+#define ADDR_REG_IRDMAIADR                          *(volatile unsigned long*) (SFR7_BASE + 0x2A*4)
+
+// IR DMA Input Size Register
+#define ADDR_REG_IRDMAISIZE                         *(volatile unsigned long*) (SFR7_BASE + 0x2B*4)
+
+// IR DMA Output Address Register
+#define ADDR_REG_IRDMAOADR                          *(volatile unsigned long*) (SFR7_BASE + 0x2C*4)
+
+// IR DMA Output Size Register
+#define ADDR_REG_IRDMAOSIZE                         *(volatile unsigned long*) (SFR7_BASE + 0x2D*4)
+
+// IR DMA Pending Register
+#define ADDR_REG_IRDMAPEND                          *(volatile unsigned long*) (SFR7_BASE + 0x2E*4)
+// IR Write DMA Half Size Pending Bit
+#define POS_REG_IRDMAPEND_WDMA_HPND                 17
+#define BIT_REG_IRDMAPEND_WDMA_HPND                 0x20000
+#define SETF_REG_IRDMAPEND_WDMA_HPND()              ADDR_REG_IRDMAPEND |= BIT_REG_IRDMAPEND_WDMA_HPND
+#define CLRF_REG_IRDMAPEND_WDMA_HPND()              ADDR_REG_IRDMAPEND &= ~BIT_REG_IRDMAPEND_WDMA_HPND
+#define GETF_REG_IRDMAPEND_WDMA_HPND()              ((ADDR_REG_IRDMAPEND & BIT_REG_IRDMAPEND_WDMA_HPND) >> POS_REG_IRDMAPEND_WDMA_HPND)
+// IR Write DMA All Size Pending Bit
+#define POS_REG_IRDMAPEND_WDMA_APND                 16
+#define BIT_REG_IRDMAPEND_WDMA_APND                 0x10000
+#define SETF_REG_IRDMAPEND_WDMA_APND()              ADDR_REG_IRDMAPEND |= BIT_REG_IRDMAPEND_WDMA_APND
+#define CLRF_REG_IRDMAPEND_WDMA_APND()              ADDR_REG_IRDMAPEND &= ~BIT_REG_IRDMAPEND_WDMA_APND
+#define GETF_REG_IRDMAPEND_WDMA_APND()              ((ADDR_REG_IRDMAPEND & BIT_REG_IRDMAPEND_WDMA_APND) >> POS_REG_IRDMAPEND_WDMA_APND)
+// IR Read DMA Half Size Pending Bit
+#define POS_REG_IRDMAPEND_RDMA_HPND                 1
+#define BIT_REG_IRDMAPEND_RDMA_HPND                 0x2
+#define SETF_REG_IRDMAPEND_RDMA_HPND()              ADDR_REG_IRDMAPEND |= BIT_REG_IRDMAPEND_RDMA_HPND
+#define CLRF_REG_IRDMAPEND_RDMA_HPND()              ADDR_REG_IRDMAPEND &= ~BIT_REG_IRDMAPEND_RDMA_HPND
+#define GETF_REG_IRDMAPEND_RDMA_HPND()              ((ADDR_REG_IRDMAPEND & BIT_REG_IRDMAPEND_RDMA_HPND) >> POS_REG_IRDMAPEND_RDMA_HPND)
+// IR Read DMA All Size Pending Bit
+#define POS_REG_IRDMAPEND_RDMA_APND                 0
+#define BIT_REG_IRDMAPEND_RDMA_APND                 0x1
+#define SETF_REG_IRDMAPEND_RDMA_APND()              ADDR_REG_IRDMAPEND |= BIT_REG_IRDMAPEND_RDMA_APND
+#define CLRF_REG_IRDMAPEND_RDMA_APND()              ADDR_REG_IRDMAPEND &= ~BIT_REG_IRDMAPEND_RDMA_APND
+#define GETF_REG_IRDMAPEND_RDMA_APND()              ((ADDR_REG_IRDMAPEND & BIT_REG_IRDMAPEND_RDMA_APND) >> POS_REG_IRDMAPEND_RDMA_APND)
+
+// IRRX
+
+// IR RX Control Register
+#define ADDR_REG_IRRXCON                            *(volatile unsigned long*) (SFR7_BASE + 0x2F*4)
+// IR Key Release Pending
+#define POS_REG_IRRXCON_KEYRELS                     17
+#define BIT_REG_IRRXCON_KEYRELS                     0x20000
+#define SETF_REG_IRRXCON_KEYRELS()                  ADDR_REG_IRRXCON |= BIT_REG_IRRXCON_KEYRELS
+#define CLRF_REG_IRRXCON_KEYRELS()                  ADDR_REG_IRRXCON &= ~BIT_REG_IRRXCON_KEYRELS
+#define GETF_REG_IRRXCON_KEYRELS()                  ((ADDR_REG_IRRXCON & BIT_REG_IRRXCON_KEYRELS) >> POS_REG_IRRXCON_KEYRELS)
+// IR Rx Data Finish Pending
+#define POS_REG_IRRXCON_RXPND                       16
+#define BIT_REG_IRRXCON_RXPND                       0x10000
+#define SETF_REG_IRRXCON_RXPND()                    ADDR_REG_IRRXCON |= BIT_REG_IRRXCON_RXPND
+#define CLRF_REG_IRRXCON_RXPND()                    ADDR_REG_IRRXCON &= ~BIT_REG_IRRXCON_RXPND
+#define GETF_REG_IRRXCON_RXPND()                    ((ADDR_REG_IRRXCON & BIT_REG_IRRXCON_RXPND) >> POS_REG_IRRXCON_RXPND)
+// IR Rx Wake Up Sleep Mode Enable
+#define POS_REG_IRRXCON_IRWKEN                      4
+#define BIT_REG_IRRXCON_IRWKEN                      0x10
+#define SETF_REG_IRRXCON_IRWKEN()                   ADDR_REG_IRRXCON |= BIT_REG_IRRXCON_IRWKEN
+#define CLRF_REG_IRRXCON_IRWKEN()                   ADDR_REG_IRRXCON &= ~BIT_REG_IRRXCON_IRWKEN
+#define GETF_REG_IRRXCON_IRWKEN()                   ((ADDR_REG_IRRXCON & BIT_REG_IRRXCON_IRWKEN) >> POS_REG_IRRXCON_IRWKEN)
+// IR Rx 32K Configure Select
+#define POS_REG_IRRXCON_IR32KSEL                    3
+#define BIT_REG_IRRXCON_IR32KSEL                    0x8
+#define SETF_REG_IRRXCON_IR32KSEL()                 ADDR_REG_IRRXCON |= BIT_REG_IRRXCON_IR32KSEL
+#define CLRF_REG_IRRXCON_IR32KSEL()                 ADDR_REG_IRRXCON &= ~BIT_REG_IRRXCON_IR32KSEL
+#define GETF_REG_IRRXCON_IR32KSEL()                 ((ADDR_REG_IRRXCON & BIT_REG_IRRXCON_IR32KSEL) >> POS_REG_IRRXCON_IR32KSEL)
+// IR Rx Data Select
+#define POS_REG_IRRXCON_IRRXSEL                     2
+#define BIT_REG_IRRXCON_IRRXSEL                     0x4
+#define SETF_REG_IRRXCON_IRRXSEL()                  ADDR_REG_IRRXCON |= BIT_REG_IRRXCON_IRRXSEL
+#define CLRF_REG_IRRXCON_IRRXSEL()                  ADDR_REG_IRRXCON &= ~BIT_REG_IRRXCON_IRRXSEL
+#define GETF_REG_IRRXCON_IRRXSEL()                  ((ADDR_REG_IRRXCON & BIT_REG_IRRXCON_IRRXSEL) >> POS_REG_IRRXCON_IRRXSEL)
+// IR Rx Interrupt Enable
+#define POS_REG_IRRXCON_IRIE                        1
+#define BIT_REG_IRRXCON_IRIE                        0x2
+#define SETF_REG_IRRXCON_IRIE()                     ADDR_REG_IRRXCON |= BIT_REG_IRRXCON_IRIE
+#define CLRF_REG_IRRXCON_IRIE()                     ADDR_REG_IRRXCON &= ~BIT_REG_IRRXCON_IRIE
+#define GETF_REG_IRRXCON_IRIE()                     ((ADDR_REG_IRRXCON & BIT_REG_IRRXCON_IRIE) >> POS_REG_IRRXCON_IRIE)
+// IR Rx Enable
+#define POS_REG_IRRXCON_IREN                        0
+#define BIT_REG_IRRXCON_IREN                        0x1
+#define SETF_REG_IRRXCON_IREN()                     ADDR_REG_IRRXCON |= BIT_REG_IRRXCON_IREN
+#define CLRF_REG_IRRXCON_IREN()                     ADDR_REG_IRRXCON &= ~BIT_REG_IRRXCON_IREN
+#define GETF_REG_IRRXCON_IREN()                     ((ADDR_REG_IRRXCON & BIT_REG_IRRXCON_IREN) >> POS_REG_IRRXCON_IREN)
+
+// IR RX Data Register
+#define ADDR_REG_IRRXDAT                            *(volatile unsigned long*) (SFR7_BASE + 0x30*4)
+// IR RX Data
+#define POS_REG_IRRXDAT                             0
+#define BIT_REG_IRRXDAT                             0xFFFFFFFF
+#define GET_REG_IRRXDAT()                            ((ADDR_REG_IRRXDAT & BIT_REG_IRRXDAT) >> POS_REG_IRRXDAT)
+
+// IR RX Clear Pending Register
+#define ADDR_REG_IRRXCPND                           *(volatile unsigned long*) (SFR7_BASE + 0x31*4)
+// IR Clear Key Release Pending
+#define POS_REG_IRRXCPND_CRELSPND                   17
+#define BIT_REG_IRRXCPND_CRELSPND                   0x20000
+#define SETF_REG_IRRXCPND_CRELSPND()                ADDR_REG_IRRXCPND |= BIT_REG_IRRXCPND_CRELSPND
+#define CLRF_REG_IRRXCPND_CRELSPND()                ADDR_REG_IRRXCPND &= ~BIT_REG_IRRXCPND_CRELSPND
+#define GETF_REG_IRRXCPND_CRELSPND()                ((ADDR_REG_IRRXCPND & BIT_REG_IRRXCPND_CRELSPND) >> POS_REG_IRRXCPND_CRELSPND)
+// IR Clear RX Finish Pending
+#define POS_REG_IRRXCPND_CRXSPND                    16
+#define BIT_REG_IRRXCPND_CRXSPND                    0x10000
+#define SETF_REG_IRRXCPND_CRXSPND()                 ADDR_REG_IRRXCPND |= BIT_REG_IRRXCPND_CRXSPND
+#define CLRF_REG_IRRXCPND_CRXSPND()                 ADDR_REG_IRRXCPND &= ~BIT_REG_IRRXCPND_CRXSPND
+#define GETF_REG_IRRXCPND_CRXSPND()                 ((ADDR_REG_IRRXCPND & BIT_REG_IRRXCPND_CRXSPND) >> POS_REG_IRRXCPND_CRXSPND)
+
+// IR RX Error Configure Register 0
+#define ADDR_REG_IRRXERR0                           *(volatile unsigned long*) (SFR7_BASE + 0x32*4)
+// IR Repeat Time Error = (RPTERR + 1 ) * (1M or 32K)
+#define POS_REG_IRRXERR0_RPTERR                     16
+#define BIT_REG_IRRXERR0_RPTERR                     0xFFF0000
+#define SET_REG_IRRXERR0_RPTERR(val)                ADDR_REG_IRRXERR0 = ((ADDR_REG_IRRXERR0 & (~BIT_REG_IRRXERR0_RPTERR)) | ((val) << POS_REG_IRRXERR0_RPTERR))
+#define GET_REG_IRRXERR0_RPTERR()                   ((ADDR_REG_IRRXERR0 & BIT_REG_IRRXERR0_RPTERR) >> POS_REG_IRRXERR0_RPTERR)
+// IR Data Time Error = (DATERR + 1 ) * (1M or 32K)
+#define POS_REG_IRRXERR0_DATERR                     0
+#define BIT_REG_IRRXERR0_DATERR                     0xFFF
+#define SET_REG_IRRXERR0_DATERR(val)                ADDR_REG_IRRXERR0 = ((ADDR_REG_IRRXERR0 & (~BIT_REG_IRRXERR0_DATERR)) | ((val) << POS_REG_IRRXERR0_DATERR))
+#define GET_REG_IRRXERR0_DATERR()                   ((ADDR_REG_IRRXERR0 & BIT_REG_IRRXERR0_DATERR) >> POS_REG_IRRXERR0_DATERR)
+
+// IR RX Error Configure Register 1
+#define ADDR_REG_IRRXERR1                           *(volatile unsigned long*) (SFR7_BASE + 0x33*4)
+// IR Time Out Length = (TOPR + 1 ) * (1M or 32K)
+#define POS_REG_IRRXERR1_TOPR                       20
+#define BIT_REG_IRRXERR1_TOPR                       0xFFF00000
+#define SET_REG_IRRXERR1_TOPR(val)                  ADDR_REG_IRRXERR1 = ((ADDR_REG_IRRXERR1 & (~BIT_REG_IRRXERR1_TOPR)) | ((val) << POS_REG_IRRXERR1_TOPR))
+#define GET_REG_IRRXERR1_TOPR()                     ((ADDR_REG_IRRXERR1 & BIT_REG_IRRXERR1_TOPR) >> POS_REG_IRRXERR1_TOPR)
+// IR Data One Time Error = (ONEERR + 1 ) * (1M or 32K)
+#define POS_REG_IRRXERR1_ONEERR                     10
+#define BIT_REG_IRRXERR1_ONEERR                     0xFFC00
+#define SET_REG_IRRXERR1_ONEERR(val)                ADDR_REG_IRRXERR1 = ((ADDR_REG_IRRXERR1 & (~BIT_REG_IRRXERR1_ONEERR)) | ((val) << POS_REG_IRRXERR1_ONEERR))
+#define GET_REG_IRRXERR1_ONEERR()                   ((ADDR_REG_IRRXERR1 & BIT_REG_IRRXERR1_ONEERR) >> POS_REG_IRRXERR1_ONEERR)
+// IR Data Zero Time Error = (ZEROERR + 1 ) * (1M or 32K)
+#define POS_REG_IRRXERR1_ZEROERR                    0
+#define BIT_REG_IRRXERR1_ZEROERR                    0x3FF
+#define SET_REG_IRRXERR1_ZEROERR(val)               ADDR_REG_IRRXERR1 = ((ADDR_REG_IRRXERR1 & (~BIT_REG_IRRXERR1_ZEROERR)) | ((val) << POS_REG_IRRXERR1_ZEROERR))
+#define GET_REG_IRRXERR1_ZEROERR()                  ((ADDR_REG_IRRXERR1 & BIT_REG_IRRXERR1_ZEROERR) >> POS_REG_IRRXERR1_ZEROERR)
+
+// IR RX Period Configure Register 0
+#define ADDR_REG_IRRXPR0                            *(volatile unsigned long*) (SFR7_BASE + 0x34*4)
+// IR Repeat Time Period = (IRRXPR + 1 ) * (1M or 32K)
+#define POS_REG_IRRXPR0_RPTPR                       16
+#define BIT_REG_IRRXPR0_RPTPR                       0x7FFF0000
+#define SET_REG_IRRXPR0_RPTPR(val)                  ADDR_REG_IRRXPR0 = ((ADDR_REG_IRRXPR0 & (~BIT_REG_IRRXPR0_RPTPR)) | ((val) << POS_REG_IRRXPR0_RPTPR))
+#define GET_REG_IRRXPR0_RPTPR()                     ((ADDR_REG_IRRXPR0 & BIT_REG_IRRXPR0_RPTPR) >> POS_REG_IRRXPR0_RPTPR)
+// IR Data Time Period = (DATPR + 1 ) * (1M or 32K)
+#define POS_REG_IRRXPR0_DATPR                       0
+#define BIT_REG_IRRXPR0_DATPR                       0x7FFF
+#define SET_REG_IRRXPR0_DATPR(val)                  ADDR_REG_IRRXPR0 = ((ADDR_REG_IRRXPR0 & (~BIT_REG_IRRXPR0_DATPR)) | ((val) << POS_REG_IRRXPR0_DATPR))
+#define GET_REG_IRRXPR0_DATPR()                     ((ADDR_REG_IRRXPR0 & BIT_REG_IRRXPR0_DATPR) >> POS_REG_IRRXPR0_DATPR)
+
+// IR RX Period Configure Register 1
+#define ADDR_REG_IRRXPR1                            *(volatile unsigned long*) (SFR7_BASE + 0x35*4)
+// IR Data One Time Period = (IRRXPR + 1 ) * (1M or 32K)
+#define POS_REG_IRRXPR1_ONEPR                       16
+#define BIT_REG_IRRXPR1_ONEPR                       0x7FFF0000
+#define SET_REG_IRRXPR1_ONEPR(val)                  ADDR_REG_IRRXPR1 = ((ADDR_REG_IRRXPR1 & (~BIT_REG_IRRXPR1_ONEPR)) | ((val) << POS_REG_IRRXPR1_ONEPR))
+#define GET_REG_IRRXPR1_ONEPR()                     ((ADDR_REG_IRRXPR1 & BIT_REG_IRRXPR1_ONEPR) >> POS_REG_IRRXPR1_ONEPR)
+// IR Data Zero Time Period = (ZEROPR + 1 ) * (1M or 32K)
+#define POS_REG_IRRXPR1_ZEROPR                       0
+#define BIT_REG_IRRXPR1_ZEROPR                       0x7FFF
+#define SET_REG_IRRXPR1_ZEROPR(val)                  ADDR_REG_IRRXPR1 = ((ADDR_REG_IRRXPR1 & (~BIT_REG_IRRXPR1_ZEROPR)) | ((val) << POS_REG_IRRXPR1_ZEROPR))
+#define GET_REG_IRRXPR1_ZEROPR()                     ((ADDR_REG_IRRXPR1 & BIT_REG_IRRXPR1_ZEROPR) >> POS_REG_IRRXPR1_ZEROPR)
+
+// IR TX Filter Control Register
+#define ADDR_REG_IRFLTCON                            *(volatile unsigned long*) (SFR7_BASE + 0x36*4)
+// IR Filter Length
+#define POS_REG_IRFLTCON_IRFLT_LEN                   8
+#define BIT_REG_IRFLTCON_IRFLT_LEN                   0xFF00
+#define SET_REG_IRFLTCON_IRFLT_LEN(val)              ADDR_REG_IRFLTCON = ((ADDR_REG_IRFLTCON & (~BIT_REG_IRFLTCON_IRFLT_LEN)) | ((val) << POS_REG_IRFLTCON_IRFLT_LEN))
+#define GET_REG_IRFLTCON_IRFLT_LEN()                 ((ADDR_REG_IRFLTCON & BIT_REG_IRFLTCON_IRFLT_LEN) >> POS_REG_IRFLTCON_IRFLT_LEN)
+// IR Filter Input Source Select
+#define POS_REG_IRFLTCON_IRFLT_SRCS                  1
+#define BIT_REG_IRFLTCON_IRFLT_SRCS                  0x2
+#define SETF_REG_IRFLTCON_IRFLT_SRCS()               ADDR_REG_IRFLTCON |= BIT_REG_IRFLTCON_IRFLT_SRCS
+#define CLRF_REG_IRFLTCON_IRFLT_SRCS()               ADDR_REG_IRFLTCON &= ~BIT_REG_IRFLTCON_IRFLT_SRCS
+#define GETF_REG_IRFLTCON_IRFLT_SRCS()               ((ADDR_REG_IRFLTCON & BIT_REG_IRFLTCON_IRFLT_SRCS) >> POS_REG_IRFLTCON_IRFLT_SRCS)
+// IR Filter Enable
+#define POS_REG_IRFLTCON_IRFLT_EN                    0
+#define BIT_REG_IRFLTCON_IRFLT_EN                    0x1
+#define SETF_REG_IRFLTCON_IRFLT_EN()                 ADDR_REG_IRFLTCON |= BIT_REG_IRFLTCON_IRFLT_EN
+#define CLRF_REG_IRFLTCON_IRFLT_EN()                 ADDR_REG_IRFLTCON &= ~BIT_REG_IRFLTCON_IRFLT_EN
+#define GETF_REG_IRFLTCON_IRFLT_EN()                 ((ADDR_REG_IRFLTCON & BIT_REG_IRFLTCON_IRFLT_EN) >> POS_REG_IRFLTCON_IRFLT_EN)
+
+//1m时钟下的解码timing
+#define RPTERR_CNT              1000
+#define DATERR_CNT              1000
+#define ONEERR_CNT              250
+#define ZEROERR_CNT             125
+#define TOPR_CNT                1718
+#define RPTPR_CNT               11249
+#define DATPR_CNT               13499
+#define DATA_0_CNT              1119
+#define DATA_1_CNT              2249
+
+
+/**
+ * @brief Flag Enumeration.
+ */
+typedef enum {
+    IRTX_FLAG_WDMA_HPND         = (1 << 0),
+    IRTX_FLAG_WDMA_APND         = (1 << 1),
+    IRTX_FLAG_RDMA_HPND         = (1 << 2),
+    IRTX_FLAG_RDMA_APND         = (1 << 3),
+} IRTX_FLAG_TYPEDEF;
+
+// irrx
+typedef enum
+{
+    IRRX_WAKUP_SLEEP_DISABLE,
+    IRRX_WAKUP_SLEEP_ENABLE,
+}irrx_wakup_en_t;
+
+typedef enum
+{
+    IRRX_DATA_SELECT_32BIT,
+    IRRX_DATA_SELECT_16BIT,
+}irrx_data_select_t;
+
+typedef enum
+{
+    IRRX_INT_DISABLE,
+    IRRX_INT_ENABLE,
+}irrx_interrupt_en_t;
+
+typedef enum
+{
+    IRRX_DISABLE,
+    IRRX_ENABLE,
+}irrx_en_t;
+
+typedef struct
+{
+    uint8_t clk_sel;
+    irrx_wakup_en_t wakup_en;
+    irrx_data_select_t data_format;
+    irrx_interrupt_en_t int_en;
+    irrx_en_t irrx_en;
+}irrx_param_t;
+
+// irtx
+typedef enum
+{
+    IRTX_ENCODE_FORMAT_NEC,
+    IRTX_ENCODE_FORMAT_TC9012,
+    IRTX_ENCODE_FORMAT_RC5,
+    IRTX_ENCODE_FORMAT_RC6,
+}irtx_encode_format_t;
+
+typedef enum
+{
+    // irtx repeat
+    IRTX_KEY_RELEASED,
+    IRTX_KEY_PRESSED,
+}irtx_key_t;
+
+typedef enum
+{
+    IRTX_CAP_EDGE_FALLING,
+    IRTX_CAP_EDGE_RISING,
+}irtx_cap_edge_t;
+
+typedef enum
+{
+    IRTX_CARRIER_DISABLE,
+    IRTX_CARRIER_ENABLE,
+}irtx_carrier_en_t;
+
+/*if tc9012 indicated as sync code
+    0: sync code is "0"
+    1: sync code is "1"
+  if rc6 indicated as trailer code
+    0: trailer code is "0"
+    1: trailer code is "1"
+*/
+typedef enum
+{
+    IRTX_SYNC_OR_TRAILER_CODE_0,
+    IRTX_SYNC_OR_TRAILER_CODE_1,
+}irtx_sync_code_t;
+
+typedef enum
+{
+    IRTX_INVERT_OUTPUT_DISABLE,
+    IRTX_INVERT_OUTPUT_ENABLE,
+}irtx_invert_en_t;
+
+typedef enum
+{
+    IRTX_FILTER_DISABLE,
+    IRTX_FILTER_ENABLE,
+}irtx_filter_en_t;
+
+typedef enum
+{
+    IRTX_MODE_CLKSEL_4M,
+    IRTX_MODE_CLKSEL_3M,
+}irtx_mod_clksel_t;
+
+typedef enum
+{
+    IRTX_DMA_MODE_32BIT,
+    IRTX_DMA_MODE_16BIT,
+}irtx_dma_mode_t;
+
+//时钟选择
+typedef enum {
+    IR_CLK_X24M32K,
+    IR_CLK_X24MDIV,
+    IR_CLK_OSC32K,
+    IR_CLK_RC32K,
+}ir_clk_t;
+
+typedef struct
+{
+    irtx_filter_en_t filter_en;         // IR Filter Enable(In Capture Mode Or IR_RX Mode)
+    uint8_t filter_len;
+}irtx_filter_config_t;
+
+typedef struct
+{
+    irtx_carrier_en_t carrier_en;
+    irtx_mod_clksel_t mod_clksel;       // Tx Modulation Clock Select. 1-4M; 0-3M
+    uint8_t ircw_duty;                  // Tx Carrier Duty = (ircw_duty) / (ircw_length + 1))
+    uint8_t ircw_length;                // Tx Carrier Freq = (3M or 4M) / (ircw_length + 1))
+}irtx_carrier_config_t;
+
+typedef struct
+{
+    irtx_dma_mode_t wdma_mode;          //IR write DMA mode
+    irtx_dma_mode_t rdma_mode;          //IR read DMA mode
+}irtx_dma_config_t;
+
+typedef struct
+{
+    ir_clk_t clk_sel;
+    uint32_t tx_data;
+    irtx_encode_format_t encode_format;
+    irtx_key_t  key;
+    irtx_cap_edge_t cap_edge;
+    irtx_carrier_config_t carrier_config;
+    irtx_filter_config_t filter_config;
+    irtx_sync_code_t sync_code;
+    irtx_invert_en_t invert_en;
+    irtx_dma_config_t dma_config;
+}irtx_param_t;
+
+//TIMING信息结构体
+typedef struct
+{
+    // irtx select encoding format in modulatin mode. 0-nec;  1-tc9012;  2-rc5;  3-rc6.
+    uint16_t em;
+    // irtx code "1" mode. 0-mark + space;   1-space + mark.
+    uint16_t o;
+    // irtx code "0" mode. 0-mark + space;   1-space + mark.
+    uint16_t z;
+    // irtx code "1" mark time = (m1 + 1) * (1M or 32K).
+    uint16_t m1;
+    // irtx code "1" space time = (s1 + 1) * (1M or 32K).
+    uint16_t s1;
+    // irtx code "0" mark time = (m0 + 1) * (1M or 32K).
+    uint16_t m0;
+    // irtx code "0" space time = (s0 + 1) * (1M or 32K).
+    uint16_t s0;
+    // irtx start code "1" time = (t1 + 1) * (1M or 32K).
+    uint16_t t1;
+    // irtx start code "0" time = (t0 + 1) * (1M or 32K).
+    uint16_t t0;
+    //irtx repeat code "1" time = (r1 + 1) * (1M or 32K).
+    uint16_t r1;
+    // irtx repeat code "0" time = (r0 + 1) * (1M or 32K).
+    uint16_t r0;
+    // irtx the interval between repeat time = (rt + 1) * (1M or 32K).
+    uint32_t rt;
+    // irtx end pulse time = (et + 1) * (1M or 32K).
+    uint16_t et;
+    // irtx sync code in tc9012 or trailer code in rc6.
+    uint16_t sy;
+    // irtx repeat mode.   0-indicates duplicate code(nec or tc9012); 1-indicates no duplicate code(rc5 or rc6)
+    uint16_t rm;
+    // irtx length
+    uint16_t l;
+} IRTX_timingTypeDef;
+
+// #if IRTXCLK_SEL
+//                                                                         //em,   o,z, m1,  s1, m0, s0,  t1,  t0,  r1,  r0,    rt,et,sy,rm,l
+//     #define IRTX_TIMING_NEC    (const uint32_t[])IRTX_TIMING(IRTX_ENCMOD_NEC,   0,0,559,1689,559,559,8999,4499,8999,2249,108000,559,0,0,32)
+//     #define IRTX_TIMING_TC9012 (const uint32_t[])IRTX_TIMING(IRTX_ENCMOD_TC9012,0,0,559,1689,559,559,4499,4499,4499,2249,108000,559,1,0,32)
+//     #define IRTX_TIMING_RC5    (const uint32_t[])IRTX_TIMING(IRTX_ENCMOD_RC5,   1,0,844, 844,844,844,1687,1687,   0,   0,108000, 17,0,1,12)
+//     #define IRTX_TIMING_RC6    (const uint32_t[])IRTX_TIMING(IRTX_ENCMOD_RC6,   0,1,443, 443,443,443,2665, 888,   0,   0,106699, 17,0,1,16)
+// #else
+//     #define IRTX_TIMING_NEC    (const uint32_t[])IRTX_TIMING(IRTX_ENCMOD_NEC,   0,0, 18,  54, 18, 17, 293, 147, 294,  73,  3537, 18,0,0,32)
+//     #define IRTX_TIMING_TC9012 (const uint32_t[])IRTX_TIMING(IRTX_ENCMOD_TC9012,0,0, 18,  54, 18, 17, 147, 146, 147,  74,  3537, 18,1,0,32)
+//     #define IRTX_TIMING_RC5    (const uint32_t[])IRTX_TIMING(IRTX_ENCMOD_RC5,   1,0, 28,  26, 28, 26,  55,  55,   0,   0,  3537,  1,0,1,12)
+//     #define IRTX_TIMING_RC6    (const uint32_t[])IRTX_TIMING(IRTX_ENCMOD_RC6,   0,1, 14,  13, 14, 13,  87,  28,   0,   0,  3494,  1,0,1,16)
+// #endif
+
+//1m时钟下TIMING数据
+                                       //em,   o,z, m1,  s1, m0, s0,  t1,  t0,  r1,  r0,              rt,et,sy,rm,l
+#define IRTX_TIMING_NEC    {IRTX_ENCODE_FORMAT_NEC,   0,0,559,1689,559,559,8999,4499,8999,2249,(uint32_t)108000,559,0,0,32}
+#define IRTX_TIMING_TC9012 {IRTX_ENCODE_FORMAT_TC9012,0,0,559,1689,559,559,4499,4499,4499,2249,(uint32_t)108000,559,1,0,32}
+#define IRTX_TIMING_RC5    {IRTX_ENCODE_FORMAT_RC5,   1,0,844, 844,844,844,1687,1687,   0,   0,(uint32_t)108000, 17,0,1,12}
+#define IRTX_TIMING_RC6    {IRTX_ENCODE_FORMAT_RC6,   0,1,443, 443,443,443,2665, 888,   0,   0,(uint32_t)106699, 17,0,1,16}
+
+//以1m时钟的timing信息为基准缩放其他时钟下的timing信息
+//缩放使用浮点数防止精度丢失或直接为0
+static uint32_t timing_freq[4] = {32760, 1000000, 31250, 32812};
+
+static uint32_t inline ir_timing_freq_get(uint8_t clk_sel)
+{
+    return timing_freq[clk_sel];
+}
+
+void irtx_kick_wait(void);
+void irtx_clk_init (uint8_t clksel);
+void ir_clk_init(uint8_t clksel);
+
+void irtx_io_init (void);
+void irrx_io_init (void);
+
+void irrx_done_clr(void);
+void irtx_cap_done_clr(void);
+void irrx_done_set(void);
+void irtx_cap_done_set(void);
+uint8_t irrx_done_get(void);
+uint8_t irtx_cap_done_get(void);
+
+void irrx_decode_config(irrx_typedef *irrx_reg, const irrx_param_t *irrx_param);
+void irrx_decode_init(irrx_typedef *irrx_reg, const irrx_param_t *irrx_param);
+void irrx_init(irrx_typedef *irrx_reg, const irrx_param_t *irrx_param);
+void irrx_wake_init(irrx_typedef *irrx_reg, const irrx_param_t *irrx_param);
+
+void irtx_init(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param);
+void irtx_timing_init(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param);
+void irtx_capture_buf_init(irtx_typedef *irtx_reg, void *buf, uint32_t len);
+void irtx_learn_buf_init(irtx_typedef *irtx_reg, void *buf, uint32_t len);
+void irtx_capture_init(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param);
+void irtx_learn_init(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param);
+void irtx_base_init(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param);
+void irtx_data_set (irtx_typedef *irtx_reg, uint32_t code);
+
+void irtx_send(void);
+void irtx_repeat_send(void);
+void irtx_pic_config(isr_t isr, int pr, IRTX_FLAG_TYPEDEF flag_type, FUNCTIONAL_STATE state);
+
+/*function name of redefining*/
+#define irtx_softmodulation_init(x,y)           irtx_learn_init(x,y)
+#define irtx_softmodulation_buf_init(x,y,z)     irtx_learn_buf_init(x,y,z)
+
+#endif

+ 117 - 0
driver/driver_irrx.c

@@ -0,0 +1,117 @@
+/**
+******************************************************************************************************************************
+*
+*@file driver_irrx.c
+*
+*@brief Source file for IR rx driver
+*
+*Copyright (c) 2023, BLUETRUM
+******************************************************************************************************************************
+**/
+#include "driver_ir.h"
+
+/**
+  * @brief  Set the clock,and clock/rx io init.Set irrx register.
+  * @param  irrx_reg: irrx register address
+  * @param  irrx_param: irrx params,include wakup_en/clock/int_en/data_format.
+  * @retval None
+  */
+void irrx_base_init(irrx_typedef *irrx_reg, const irrx_param_t *irrx_param)
+{
+    irrx_decode_config(irrx_reg, irrx_param);
+
+    irrx_init(irrx_reg, irrx_param);
+}
+
+/**
+  * @brief  Set irrx wakup_en/int_en/data_format.
+  * @param  irrx_reg: irrx register address
+  * @param  irrx_param: irrx params,include wakup_en/clock/int_en/data_format.
+  * @retval None
+  */
+void irrx_init(irrx_typedef *irrx_reg, const irrx_param_t *irrx_param)
+{
+    // IR RX Wake Up Sleep Mode Enable
+    if (IRRX_WAKUP_SLEEP_ENABLE == irrx_param->wakup_en) {
+        SETF_REG_IRRXCON_IRWKEN();
+    }
+    else if (IRRX_WAKUP_SLEEP_DISABLE == irrx_param->wakup_en) {
+        CLRF_REG_IRRXCON_IRWKEN();
+    }
+
+    // IR RX Data Select 16 Bit Data
+    if (IRRX_DATA_SELECT_16BIT == irrx_param->data_format) {
+        SETF_REG_IRRXCON_IRRXSEL();
+    }
+    else if (IRRX_DATA_SELECT_32BIT == irrx_param->data_format) {
+        CLRF_REG_IRRXCON_IRRXSEL();
+    }
+
+    // IR RX Interrupt Enable
+    if (IRRX_INT_DISABLE == irrx_param->int_en) {
+        CLRF_REG_IRRXCON_IRIE();
+    }
+    else if (IRRX_INT_ENABLE == irrx_param->int_en) {
+        SETF_REG_IRRXCON_IRIE();
+    }
+
+    // IR RX Enable
+    if (IRRX_DISABLE == irrx_param->irrx_en) {
+        CLRF_REG_IRRXCON_IREN();
+    }
+    else if (IRRX_ENABLE == irrx_param->irrx_en) {
+        SETF_REG_IRRXCON_IREN();
+    }
+
+
+}
+
+/**
+  * @brief  irrx enable and set irrx period0/period1/err0/err1 value.
+  * @param  irrx_reg: irrx register address
+  * @retval None
+  */
+void irrx_decode_config(irrx_typedef *irrx_reg, const irrx_param_t *irrx_param)
+{
+    double prescale;
+    volatile u32 timing_prescale, period0, period1, err0, err1;
+
+    timing_prescale = ir_timing_freq_get(irrx_param->clk_sel);
+
+    prescale = ((double)timing_prescale/1000000);
+
+    period0       = BIT(16) * (uint16_t)(RPTPR_CNT   * prescale) |
+                                (uint16_t)(DATPR_CNT   * prescale);
+    period1       = BIT(16) * (uint16_t)(DATA_1_CNT  * prescale) |
+                                (uint16_t)(DATA_0_CNT  * prescale);
+    err0          = BIT(16) * (uint16_t)(RPTERR_CNT  * prescale) |
+                                (uint16_t)(DATERR_CNT  * prescale);
+    err1          = BIT(20) * (uint16_t)(TOPR_CNT    * prescale) |
+                    BIT(10) * (uint16_t)(ONEERR_CNT  * prescale) |
+                                (uint16_t)(ZEROERR_CNT * prescale);
+
+    irrx_reg->period0   = period0;
+    irrx_reg->period1   = period1;
+    irrx_reg->err0      = err0;
+    irrx_reg->err1      = err1;
+    //SETF_REG_IRRXCON_IREN();
+}
+
+void irrx_decode_init(irrx_typedef *irrx_reg, const irrx_param_t *irrx_param)
+{
+    ir_clk_init(irrx_param->clk_sel);
+
+    clk_gate1_cmd(CLK_GATE1_IRRX, CLK_EN);
+
+    irrx_base_init(irrx_reg, irrx_param);
+}
+
+void irrx_wake_init(irrx_typedef *irrx_reg, const irrx_param_t *irrx_param)
+{
+    ir_clk_init(irrx_param->clk_sel);
+
+    clk_gate1_cmd(CLK_GATE1_IRRX, CLK_EN);
+
+    irrx_base_init(irrx_reg, irrx_param);
+}
+

+ 361 - 0
driver/driver_irtx.c

@@ -0,0 +1,361 @@
+/**
+******************************************************************************************************************************
+*
+*@file driver_irtx.c
+*
+*@brief Source file for IR tx driver
+*
+*Copyright (c) 2023, BLUETRUM
+******************************************************************************************************************************
+**/
+#include "driver_ir.h"
+#include "driver_gpio.h"
+#include "macro.h"
+
+void ir_clk_init(uint8_t clksel)
+{
+    // irrx/irrx clock config
+    if ((IR_CLK_OSC32K == clksel) || (IR_CLK_X24M32K == clksel) || (IR_CLK_X24MDIV == clksel)) {
+        XOSCCON |= BIT(10);                                         //XOSC24M enable
+        CLKCON4 &= ~BIT(26);                                        //xoscrc24m_sel chose XOSC24M
+        clk_gate1_cmd(CLK_GATE1_X24M, CLK_EN);                      //XOSC24M gate open
+
+        if (IR_CLK_OSC32K == clksel) {
+            CLKCON1 &= ~BIT(17);                                    // k32_tscsel chose osc32k_p(CLK32K_RTC)
+            RTCCON0 |= (BIT(2));                                    // RTC output clock to core enable
+            RTCCON0 &= ~(BIT(19));                                  // osc core disable
+
+            RTCCON0 = (RTCCON0 & ~(3 << 8)) | (3 << 8);             // CLK32K_RTC source select x24mdiv12_rtc(x24m_clkdiv12)
+            CLKCON0 = (CLKCON0 & ~(0x0f << 13)) | (3 << 13);        // clkout sel, osc32k
+        } else if (IR_CLK_X24M32K == clksel) {
+            CLKCON0 = (CLKCON0 & ~(0x0f << 13)) | (2 << 13);        // clkout sel, x24m_32K
+        } else if (IR_CLK_X24MDIV == clksel) {
+            CLKCON0 = (CLKCON0 & ~(0x0f << 13)) | (1 << 13);        // clkout sel, x24mdiv unvisible,we can check xosc24m
+        }
+    } else if (IR_CLK_RC32K == clksel) {
+        CLKCON0 |= BIT(0);                                          //RC2M enable
+        CLKCON0 = (CLKCON0 & ~(0x0f << 13)) | (7 << 13);            // clkout sel, rc32k unvisible,we can check rc2m
+    }
+
+    //irrx clock select
+    CLKCON1 = (CLKCON1 & ~(3 << 4)) | (clksel << 4);            // 0:x24m_32k 1:x24m_div_clk 2:osc32k 3:rc32k_clk
+}
+
+void irtx_clk_init (uint8_t clksel)
+{
+    ir_clk_init(clksel);
+    clk_gate1_cmd(CLK_GATE1_IRTX, CLK_EN);
+    clk_gate2_cmd(CLK_GATE2_IRFLT, CLK_EN);
+}
+
+/*
+ * timing[0] : one     [31:16]mark  m1  [15:0]space  s1
+ * timing[1] : zeor    [31:16]mark  m0  [15:0]space  s0
+ * timing[2] : start   [31:16]1     t1  [15:0]0      t0
+ * timing[3] : repteat [31:16]1     r1  [15:0]0      r0
+ * timing[4] : IRREPEATCON          rt et sy rm
+ * timing[5] : IRTXCON              o  z
+ * timing[6] : IRTXLEN              l
+*/
+const IRTX_timingTypeDef Nec        = IRTX_TIMING_NEC;
+const IRTX_timingTypeDef Tc9012     = IRTX_TIMING_TC9012;
+const IRTX_timingTypeDef Rc5        = IRTX_TIMING_RC5;
+const IRTX_timingTypeDef Rc6        = IRTX_TIMING_RC6;
+
+void irtx_timing_set(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param, const IRTX_timingTypeDef timing)
+{
+    double prescale;
+    volatile u32 timing_prescale;
+
+    timing_prescale = ir_timing_freq_get(irtx_param->clk_sel);
+    prescale = ((double)timing_prescale/1000000);
+
+    irtx_reg->con   = BIT(8) *  timing.em |
+                      BIT(5) *  timing.o  |
+                      BIT(4) *  timing.z  |
+                      BIT(0);
+    irtx_reg->otime = BIT(16) * (uint16_t)(timing.m1 * prescale) |
+                      BIT(0) *  (uint16_t)(timing.s1 * prescale);
+    irtx_reg->ztime = BIT(16) * (uint16_t)(timing.m0 * prescale) |
+                      BIT(0) *  (uint16_t)(timing.s0 * prescale);
+    irtx_reg->stime = BIT(16) * (uint16_t)(timing.t1 * prescale) |
+                      BIT(0) *  (uint16_t)(timing.t0 * prescale);
+    irtx_reg->rtime = BIT(16) * (uint16_t)(timing.r1 * prescale) |
+                      BIT(0) *  (uint16_t)(timing.r0 * prescale);
+    irtx_reg->rctrl = BIT(13) * (uint32_t)(timing.rt * prescale) |
+                      BIT(3) *  (uint16_t)(timing.et * prescale) |
+                      BIT(2) *  timing.sy |
+                      BIT(1) *  timing.rm;
+    irtx_reg->txlen = timing.l;
+}
+
+void irtx_timing_init(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param)
+{
+    switch(irtx_param->encode_format)
+    {
+        case IRTX_ENCODE_FORMAT_NEC:
+            irtx_timing_set(irtx_reg, irtx_param, Nec);
+            break;
+        case IRTX_ENCODE_FORMAT_TC9012:
+            irtx_timing_set(irtx_reg, irtx_param, Tc9012);
+            break;
+        case IRTX_ENCODE_FORMAT_RC5:
+            irtx_timing_set(irtx_reg, irtx_param, Rc5);
+            break;
+        case IRTX_ENCODE_FORMAT_RC6:
+            irtx_timing_set(irtx_reg, irtx_param, Rc6);
+            break;
+        default:
+            break;
+    }
+}
+
+//edge set 0 to choose fall edge
+void irtx_capture_edge (irtx_typedef *irtx_reg, uint32_t edge)
+{
+    if (edge) {
+        SETF_REG_IRTXCON_IREDGE_SEL();
+    }else {
+        CLRF_REG_IRTXCON_IREDGE_SEL();
+    }
+}
+
+void irtx_carrier_init(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param)
+{
+    if (irtx_param->carrier_config.mod_clksel == IRTX_MODE_CLKSEL_3M) {
+        CLKCON1 &= ~BIT(9);//1:4m 0:3m
+    } else {
+        CLKCON1 |= BIT(9);//1:4m 0:3m
+    }
+
+    if (irtx_param->carrier_config.carrier_en) {
+        SETF_REG_IRTXCON_IRTX_CARRIER_EN();
+        SET_REG_IRTXCON_IRCW_LENGTH(irtx_param->carrier_config.ircw_length);
+        SET_REG_IRTXCON_IRCW_DUTY(irtx_param->carrier_config.ircw_duty);
+    }else {
+        CLRF_REG_IRTXCON_IRTX_CARRIER_EN();
+    }
+}
+
+void irtx_dma_init(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param)
+{
+    if (irtx_param->dma_config.rdma_mode == IRTX_DMA_MODE_16BIT) {
+        SETF_REG_IRDMACON_IR_RDMA_MODE();
+    } else {
+        CLRF_REG_IRDMACON_IR_RDMA_MODE();
+    }
+
+    if (irtx_param->dma_config.wdma_mode == IRTX_DMA_MODE_16BIT) {
+        SETF_REG_IRDMACON_IR_WDMA_MODE();
+    } else {
+        CLRF_REG_IRDMACON_IR_WDMA_MODE();
+    }
+}
+
+void irtx_data_set (irtx_typedef *irtx_reg, uint32_t code)
+{
+    irtx_reg->txdata = code;
+}
+
+void irtx_init(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param)
+{
+    irtx_data_set(irtx_reg, irtx_param->tx_data);
+    irtx_carrier_init(irtx_reg, irtx_param);
+
+    if (IRTX_SYNC_OR_TRAILER_CODE_1 == irtx_param->sync_code) {
+        SETF_REG_IRREPEATCON_IRTX_SYC();
+    }else {
+        CLRF_REG_IRREPEATCON_IRTX_SYC();
+    }
+}
+
+void irtx_set_repeat(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param)
+{
+    if (IRTX_KEY_PRESSED == irtx_param->key) {
+        SETF_REG_IRREPEATCON_IRTX_KEY();
+    }else {
+        CLRF_REG_IRREPEATCON_IRTX_KEY();
+    }
+}
+
+void irfilter_set(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param)
+{
+    if (IRTX_FILTER_ENABLE == irtx_param->filter_config.filter_en) {
+        SETF_REG_IRFLTCON_IRFLT_EN();
+        SET_REG_IRFLTCON_IRFLT_LEN(irtx_param->filter_config.filter_len);
+    } else {
+        CLRF_REG_IRFLTCON_IRFLT_EN();
+    }
+}
+
+//KICK
+inline void irtx_kick_do (void)
+{
+    SETF_REG_IRTXCON_IRTX_KST();
+}
+
+inline void irtx_wait(void)
+{
+    while (!GETF_REG_IRTXPEND_IRTX_PND());
+    SETF_REG_IRTXPEND_IRTX_PND();
+}
+
+void irtx_kick_wait(void)
+{
+    irtx_kick_do();
+    irtx_wait();
+}
+
+//CAPTURE DMA
+void irtx_capture_dma_init(irtx_typedef *irtx_reg, void *buf, uint32_t len)
+{
+    irtx_reg->dma_oadr = (uint32_t)buf;
+    irtx_reg->dma_osize = len - 1;
+
+    SETF_REG_IRDMACON_IR_WDMA_EN();
+    SETF_REG_IRDMACON_IR_WDMA_MODE();
+    //SETF_REG_IRDMACON_IR_WDMA_APND_IE();
+}
+
+void irtx_capture_dma_kick(irtx_typedef *irtx_reg)
+{
+    SETF_REG_IRTXCON_IR_CAPEN();
+}
+
+void irtx_learn_dma_init(irtx_typedef *irtx_reg, void *buf, uint32_t len)
+{
+    irtx_reg->dma_iadr = (uint32_t)buf;
+    irtx_reg->dma_isize = len - 1;
+}
+
+void irtx_learn_kick(irtx_typedef *irtx_reg)
+{
+    //SETF_REG_IRTXCON_IRTXLEN_EN();
+    SETF_REG_IRTXCON_IRTX_KST();
+}
+
+inline void irtx_set_invert(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param)
+{
+    if (IRTX_INVERT_OUTPUT_ENABLE == irtx_param->invert_en) {
+        SETF_REG_IRTXCON_IRTX_INV();
+    }else {
+        CLRF_REG_IRTXCON_IRTX_INV();
+    }
+}
+
+/**
+  * @brief  Set the clock,and clock/rx io init.Set irrx register.
+  * @param  irrx_reg: irrx register address
+  * @param  irrx_param: irrx params,include wakup_en/clock/int_en/data_format.
+  * @retval None
+  */
+void irtx_base_init(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param)
+{
+    irtx_clk_init(irtx_param->clk_sel);
+    irtx_timing_init(irtx_reg, irtx_param);
+    irfilter_set(irtx_reg, irtx_param);
+    irtx_set_invert(irtx_reg, irtx_param);
+
+    irtx_init(irtx_reg, irtx_param);
+    irtx_set_repeat(irtx_reg, irtx_param);
+}
+
+static bool irtx_is_repeat(void)
+{
+    bool ret = true;
+
+    if (GETF_REG_IRREPEATCON_IRTX_KEY()) {
+        ret = false;
+    }
+
+    return ret;
+}
+
+void irtx_repeat_send(void)
+{
+    if (irtx_is_repeat() && GETF_REG_IRFLTCON_IRFLT_EN()) {
+        irtx_kick_wait();
+    }
+}
+
+void irtx_send(void)
+{
+    irtx_kick_wait();
+}
+
+void irtx_capture_init(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param)
+{
+    irtx_clk_init(irtx_param->clk_sel);
+
+    irtx_capture_edge(irtx_reg, irtx_param->cap_edge); //edge set 1 to choose rising edge
+}
+
+void irtx_capture_buf_init(irtx_typedef *irtx_reg, void *buf, uint32_t len)
+{
+    irtx_capture_dma_init(irtx_reg, buf, len);
+    irtx_capture_dma_kick(irtx_reg);
+}
+
+void irtx_learn_init(irtx_typedef *irtx_reg, const irtx_param_t *irtx_param)
+{
+    irtx_clk_init(irtx_param->clk_sel);
+
+    irtx_carrier_init(irtx_reg, irtx_param);
+
+    irtx_dma_init(irtx_reg, irtx_param);
+
+    SETF_REG_IRDMACON_IR_RDMA_EN();
+    SETF_REG_IRTXCON_IRTXLEN_EN();
+}
+
+void irtx_learn_buf_init(irtx_typedef *irtx_reg, void *buf, uint32_t len)
+{
+    irtx_learn_dma_init(irtx_reg, buf, len);
+    irtx_learn_kick(irtx_reg);
+}
+
+/**
+ * @brief  Enable or disable the specified IRTX interrupt.
+ * @param  isr: Function to be executed for service interruption.
+ * @param  pr: Priority of service interruption.
+ * @param  flag_type: specifies the IRTX interrupt sources to be enable or disable.
+ *         This parameter can be one of the following values:
+ *             @arg IRTX_FLAG_WDMA_HPND: ir write DMA half interrupt.
+ *             @arg IRTX_FLAG_WDMA_APND: ir write DMA all interrupt.
+ *             @arg IRTX_FLAG_RDMA_HPND: ir read DMA half interrupt.
+ *             @arg IRTX_FLAG_RDMA_APND: ir read DMA all interrupt.
+ * @param  state: the new state need to config.
+ * @retval None
+ */
+void irtx_pic_config(isr_t isr, int pr, IRTX_FLAG_TYPEDEF flag_type, FUNCTIONAL_STATE state)
+{
+    u32 flag_pending_bit = 0;
+
+    if (flag_type == 0) {
+        return;
+    }
+
+    if (flag_type & IRTX_FLAG_WDMA_HPND) {
+        flag_pending_bit |= BIT_REG_IRDMACON_IR_WDMA_HPND_IE;
+    }
+
+    if (flag_type & IRTX_FLAG_WDMA_APND) {
+        flag_pending_bit |= BIT_REG_IRDMACON_IR_WDMA_APND_IE;
+    }
+
+    if (flag_type & IRTX_FLAG_RDMA_HPND) {
+        flag_pending_bit |= BIT_REG_IRDMACON_IR_RDMA_HPND_IE;
+    }
+
+    if (flag_type & IRTX_FLAG_RDMA_APND) {
+        flag_pending_bit |= BIT_REG_IRDMACON_IR_RDMA_APND_IE;
+    }
+
+    if (state != DISABLE) {
+        IRTX->dma_con |= flag_pending_bit;
+        sys_irq_init(IRQn_IR_QDEC_LEDC, pr, isr);
+    } else {
+        IRTX->dma_con &= ~flag_pending_bit;
+    }
+}
+

+ 235 - 0
driver/driver_keyscan.c

@@ -0,0 +1,235 @@
+/*
+ * @File name    : driver_keyscan.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-03-15
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the KEYSCAN peripheral.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_keyscan.h"
+
+/**
+ * @brief  Initializes the KEYSCAN peripheral according to the specified
+ *         parameters in the keyscan_init_struct.
+ * @param keyscan_init_struct: pointer to a keyscan_init_typedef structure that
+ *         contains the configuration information for the specified KEYSCAN peripheral.
+ * @retval
+ */
+void keyscan_init(keyscan_init_typedef *keyscan_init_struct)
+{
+    /* Configure Control0 Register */
+    KEYSCAN->con1 &= ~(KEYSCAN_CON1_KEYPORT_STAB_TIME | KEYSCAN_CON1_KEY_DEBO_TIMES | KEYSCAN_CON1_KEY_WAIT_TIMES);
+    KEYSCAN->con1 |= (keyscan_init_struct->stable_times * KEYSCAN_CON1_KEYPORT_STAB_TIME_0) & KEYSCAN_CON1_KEYPORT_STAB_TIME;
+    KEYSCAN->con1 |= (keyscan_init_struct->debounce_times * KEYSCAN_CON1_KEY_DEBO_TIMES_0) & KEYSCAN_CON1_KEY_DEBO_TIMES;
+    KEYSCAN->con1 |= (keyscan_init_struct->wait_times * KEYSCAN_CON1_KEY_WAIT_TIMES_0) & KEYSCAN_CON1_KEY_WAIT_TIMES;
+
+    /* Configure Key Scan Mode for Row/Column Scan */
+    KEYSCAN->con0 &= ~KEYSCAN_CON0_KEYSCAN_MODE;
+    KEYSCAN->con0 |= keyscan_init_struct->key_mode & KEYSCAN_CON0_KEYSCAN_MODE;
+
+    /* Configure Low Power Mode */
+    KEYSCAN->con0 &= ~KEYSCAN_CON0_KEYSCAN_LP;
+    KEYSCAN->con0 |= keyscan_init_struct->low_power_mode & KEYSCAN_CON0_KEYSCAN_LP;
+
+    /* Configure Key Valid Wakeup System */
+    KEYSCAN->con0 &= ~KEYSCAN_CON0_KEYVALID_WKUP_EN;
+    KEYSCAN->con0 |= keyscan_init_struct->wakeup & KEYSCAN_CON0_KEYVALID_WKUP_EN;
+
+    /* Configure Key Scan Software rstn */
+    KEYSCAN->con0 &= ~KEYSCAN_CON0_KEYSCAN_SWRSTN;
+    KEYSCAN->con0 |= keyscan_init_struct->sw_reset & KEYSCAN_CON0_KEYSCAN_SWRSTN;
+
+    /* Configure Port Mask */
+    KEYSCAN->con0 &= ~KEYSCAN_CON0_KEYPORT_EN;
+    KEYSCAN->con0 |= (keyscan_init_struct->key_mask * KEYSCAN_CON0_KEYPORT_EN_0) & KEYSCAN_CON0_KEYPORT_EN;
+}
+
+/**
+ * @brief  De-initialize the specified KeyScan peripheral.
+ * @retval None
+ */
+void keyscan_deinit(void)
+{
+    KEYSCAN->con0 = 0;
+    KEYSCAN->con1 = 0;
+
+    /* The clock is not unique to this module */
+    //clk_gate0_cmd(CLK_GATE0_LP, CLK_DIS);
+}
+
+/**
+ * @brief  Enable or disable the KEYSCAN peripheral.
+ * @param  state: state of the KEYSCAN peripheral.
+ *         This parameter can be: ENABLE or DISABLE.
+ * @retval None.
+ */
+AT(.com_periph.keyscan.en_ctrl)
+void keyscan_cmd(FUNCTIONAL_STATE state)
+{
+    if (state != DISABLE) {
+        KEYSCAN->con0 |= KEYSCAN_CON0_KEYSCAN_EN;
+    } else {
+        KEYSCAN->con0 &= ~KEYSCAN_CON0_KEYSCAN_EN;
+    }
+}
+
+/**
+ * @brief  Enable or disable the specified KEYSCAN interrupt.
+ * @param  isr: Function to be executed for service interruption.
+ * @param  pr: Priority of service interruption.
+ * @param  interrupt_type: specifies the KEYSCAN interrupt sources to be enable or disable.
+ *         this parameter can be one of the following values:
+ *             @arg KEYSCAN_IT_VALID: Any key has pressed interrupt.
+ *             @arg KEYSCAN_IT_INVALID: All key release interrupt.
+ * @param  state: the state of the KEYSCAN peripheral.
+ *         this parameter can be: ENABLE or DISABLE.
+ * @retval None.
+ */
+void keyscan_pic_config(isr_t isr, int pr, KEYSCAN_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state)
+{
+    uint32_t interrupt_pending_bit = 0;
+
+    if (interrupt_type == 0) {
+        return;
+    }
+
+    if (interrupt_type & KEYSCAN_IT_VALID) {
+        interrupt_pending_bit |= KEYSCAN_CON0_KEYVALID_INT_EN;
+    }
+
+    if (interrupt_type & KEYSCAN_IT_INVALID) {
+        interrupt_pending_bit |= KEYSCAN_CON0_KEYINVALID_INT_EN;
+    }
+
+    if (state != DISABLE) {
+        KEYSCAN->con0 |= interrupt_pending_bit;
+        sys_irq_init(IRQn_KEY_SCAN, pr, isr);
+    } else {
+        KEYSCAN->con0 &= ~interrupt_pending_bit;
+    }
+}
+
+/**
+ * @brief  Get interrupt pendding function.
+ * @param  interrupt_type: specifies the interrupt to get.
+ *         this parameter can be one of the following values:
+ *             @arg KEYSCAN_IT_VALID: Any key has pressed interrupt.
+ *             @arg KEYSCAN_IT_INVALID: All key release interrupt.
+ * @retval  The state of interrupt_type (SET or RESET).
+ */
+AT(.com_periph.keyscan.flag)
+FLAG_STATE keyscan_get_flag(KEYSCAN_IT_TYPEDEF interrupt_type)
+{
+    uint32_t interrupt_pending_bit = 0;
+
+    if (interrupt_type & KEYSCAN_IT_VALID) {
+        interrupt_pending_bit |= KEYSCAN_CLR_KEYVALID_PND_CLR;
+    }
+
+    if (interrupt_type & KEYSCAN_IT_INVALID) {
+        interrupt_pending_bit |= KEYSCAN_CLR_KEYINVALID_PND_CLR;
+    }
+
+    if (KEYSCAN->con0 & interrupt_pending_bit) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+ * @brief  Clear interrupt pending function.
+ * @param  interrupt_type: specifies the interrupt to clear.
+ *         this parameter can be one of the following values:
+ *             @arg KEYSCAN_IT_VALID: Any key has pressed interrupt.
+ *             @arg KEYSCAN_IT_INVALID: All key release interrupt.
+ * @retval None.
+ */
+AT(.com_periph.keyscan.flag)
+void keyscan_clear_flag(KEYSCAN_IT_TYPEDEF interrupt_type)
+{
+    uint32_t interrupt_pending_bit = 0;
+
+    if (interrupt_type & KEYSCAN_IT_VALID) {
+        interrupt_pending_bit |= KEYSCAN_CON0_KEYVALID_PND;
+    }
+
+    if (interrupt_type & KEYSCAN_IT_INVALID) {
+        interrupt_pending_bit |= KEYSCAN_CON0_KEYINVALID_PND;
+    }
+
+    KEYSCAN->clr |= interrupt_pending_bit;
+}
+
+/**
+ * @brief  Get Group A Key ID that be triggered.
+ * @retval Key ID. All Key ID please see enumeration "KEYSCAN_GROUP_A_KEY_ID_TYPEDEF".
+ */
+AT(.com_periph.keyscan.query)
+uint32_t keyscan_get_groupA_key_id(void)
+{
+    uint8_t  idx;
+    uint8_t  *p;
+    uint32_t info_reg[2];
+    uint32_t key_val = 0;
+    uint32_t key_val_img = 0;
+
+    info_reg[0] = KEYSCAN->info0;
+    info_reg[1] = KEYSCAN->info1;
+    p = (u8 *)info_reg;
+
+    key_val |= ((info_reg[0] & 0xfe) >> 1) * KA1;
+    key_val |= ((info_reg[0] & 0xfc00) >> 10) * KB2;
+    key_val |= ((info_reg[0] & 0xf80000) >> 19) * KC3;
+    key_val |= ((info_reg[0] & 0xf0000000) >> 28) * KD4;
+    key_val |= ((info_reg[1] & 0xe0) >> 5) * KE5;
+    key_val |= ((info_reg[1] & 0xc000) >> 14) * KF6;
+    key_val |= ((info_reg[1] & 0x800000) >> 23) * KG7;
+
+    if (KEYSCAN->con0 & KEYSCAN_CON0_KEYSCAN_MODE) {
+        //Resolve matrix keystroke conflicts
+        for (u8 i = 0; i < 8; i++) {
+            idx = i - 1;
+            for (u8 j = 0; j < i; j++) {
+                key_val_img |= (p[i] & (0x01  << j))? (0x01 << idx): 0;
+                idx = idx + 6 - j;
+            }
+        }
+    } else {
+        key_val_img = 0xffffffff;
+    }
+
+    return key_val & key_val_img;
+}
+
+/**
+ * @brief  Get Group B Key ID that be triggered.
+ * @retval Key ID. All Key ID please see enumeration "KEYSCAN_GROUP_B_KEY_ID_TYPEDEF".
+ */
+AT(.com_periph.keyscan.query)
+uint32_t keyscan_get_groupB_key_id(void)
+{
+    uint32_t info2_reg;
+    uint32_t key_val = 0;
+
+    info2_reg = KEYSCAN->info2;
+
+    key_val |= (info2_reg & 0xff) * KJ0;
+    key_val |= ((info2_reg & 0xff00) >> 8) * KI0;
+
+    return key_val;
+}
+
+/**
+ * @brief  Get low power mode configuration.
+ * @retval 1:low power mode en, 0:low power mode dis.
+ */
+AT(.com_periph.keyscan.lowpwr_mode)
+bool keyscan_is_lowpwr_mode(void)
+{
+    bool mode = (KEYSCAN->con0 & KEYSCAN_CON0_KEYSCAN_LP) >> 2;
+
+    return mode;
+}
+

+ 135 - 0
driver/driver_keyscan.h

@@ -0,0 +1,135 @@
+/*
+ * @File name    : driver_keyscan.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-03-15
+ * @Description  : This file contains all the functions prototypes for the KEYSCAN library.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_KEYSCAN_H
+#define _DRIVER_KEYSCAN_H
+
+#include "driver_com.h"
+
+/**
+ * @brief KEYSCAN Group A Key ID Enumeration
+ */
+typedef enum {
+    KA1     = 0x00000001,
+    KA2     = 0x00000002,
+    KA3     = 0x00000004,
+    KA4     = 0x00000008,
+    KA5     = 0x00000010,
+    KA6     = 0x00000020,
+    KA7     = 0x00000040,
+    KB2     = 0x00000080,
+    KB3     = 0x00000100,
+    KB4     = 0x00000200,
+    KB5     = 0x00000400,
+    KB6     = 0x00000800,
+    KB7     = 0x00001000,
+    KC3     = 0x00002000,
+    KC4     = 0x00004000,
+    KC5     = 0x00008000,
+    KC6     = 0x00010000,
+    KC7     = 0x00020000,
+    KD4     = 0x00040000,
+    KD5     = 0x00080000,
+    KD6     = 0x00100000,
+    KD7     = 0x00200000,
+    KE5     = 0x00400000,
+    KE6     = 0x00800000,
+    KE7     = 0x01000000,
+    KF6     = 0x02000000,
+    KF7     = 0x04000000,
+    KG7     = 0x08000000,
+} KEYSCAN_GROUP_A_KEY_ID_TYPEDEF;
+
+/**
+ * @brief KEYSCAN Group B Key ID Enumeration
+ */
+typedef enum {
+    KJ0     = 0x00000001,
+    KJ1     = 0x00000002,
+    KJ2     = 0x00000004,
+    KJ3     = 0x00000008,
+    KJ4     = 0x00000010,
+    KJ5     = 0x00000020,
+    KJ6     = 0x00000040,
+    KJ7     = 0x00000080,
+    KI0     = 0x00000100,
+    KI1     = 0x00000200,
+    KI2     = 0x00000400,
+    KI3     = 0x00000800,
+    KI4     = 0x00001000,
+    KI5     = 0x00002000,
+    KI6     = 0x00004000,
+    KI7     = 0x00008000,
+} KEYSCAN_GROUP_B_KEY_ID_TYPEDEF;
+
+/**
+ * @brief KEYSCAN Interrupt Flag Definition
+ */
+typedef enum {
+    KEYSCAN_IT_VALID                = 0x01,
+    KEYSCAN_IT_INVALID              = 0x02,
+} KEYSCAN_IT_TYPEDEF;
+
+/**
+ * @brief Key Scan Software Release Reset Enumeration
+ */
+typedef enum {
+    KEYSCAN_SWRSTN_RESET            = 0x00000000,
+    KEYSCAN_SWRSTN_RELEASE_RESET    = 0x00000080,
+} KEYSCAN_SWRSTN_TYPEDEF;
+
+/**
+ * @brief Key Valid Wakeup System Enumeration
+ */
+typedef enum {
+    KEYSCAN_WKUP_DIS                = 0x00000000,
+    KEYSCAN_WKUP_EN                 = 0x00000008,
+} KEYSCAN_WKUP_TYPEDEF;
+
+/**
+ * @brief Key Scan Lowpower Mode Enumeration
+ */
+typedef enum {
+    KEYSCAN_LOWPWR_DIS              = 0x00000000,
+    KEYSCAN_LOWPWR_EN               = 0x00000004,
+} KEYSCAN_LOWPWR_TYPEDEF;
+
+/**
+ * @brief Key Scan Mode Enumeration
+ */
+typedef enum {
+    KEYSCAN_MODE_NORMAL             = 0x00000000,
+    KEYSCAN_MODE_MATRIX             = 0x00000002,
+} KEYSCAN_MODE_TYPEDEF;
+
+/**
+ * @brief KEYSCAN Init Structure
+ */
+typedef struct {
+    uint8_t                     key_mask;
+    uint8_t                     stable_times;
+    uint8_t                     debounce_times;
+    uint8_t                     wait_times;
+    KEYSCAN_MODE_TYPEDEF        key_mode;
+    KEYSCAN_LOWPWR_TYPEDEF      low_power_mode;
+    KEYSCAN_SWRSTN_TYPEDEF      sw_reset;
+    KEYSCAN_WKUP_TYPEDEF        wakeup;
+} keyscan_init_typedef;
+
+/********************** Function used to configure key_scan base **********************/
+void keyscan_init(keyscan_init_typedef *keyscan_init_struct);
+void keyscan_deinit(void);
+void keyscan_cmd(FUNCTIONAL_STATE state);
+void keyscan_pic_config(isr_t isr, int pr, KEYSCAN_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state);
+FLAG_STATE keyscan_get_flag(KEYSCAN_IT_TYPEDEF interrupt_type);
+void keyscan_clear_flag(KEYSCAN_IT_TYPEDEF interrupt_type);
+uint32_t keyscan_get_groupA_key_id(void);
+uint32_t keyscan_get_groupB_key_id(void);
+bool keyscan_is_lowpwr_mode(void);
+
+#endif // _DRIVER_KEYSCAN_H

+ 277 - 0
driver/driver_ledc.c

@@ -0,0 +1,277 @@
+/*
+ * @File name    : driver_ledc.c
+ * @Author       : Bluetrum IOT Team K.
+ * @Date         : 2023-07-10
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the LEDC peripheral.
+ * @WARNING      : Due to IC logical error, we should make sure no other peripherals 
+                   use the same DMA address as LEDC(SRAM0), or dma of ledc would be error.
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_ledc.h"
+
+
+/**
+ * @brief  Initializes the LEDC peripheral according to the specified
+ *         parameters in the ledc_timing_init_struct.
+ * @param  ledc_timing_init_struct: pointer to a ledc_init_typedef structure that
+ *         contains the configuration information for the specified LEDC peripheral.
+ * @retval None
+ */
+void ledc_init(ledc_init_typedef *ledc_timing_init_struct)
+{
+    u32 tmp_reg;
+
+    /* Load the register value to variable */
+    tmp_reg = LEDC->con;
+
+    /* Clear value need to configure */
+    tmp_reg &= ~(uint32_t)(LEDC_CON_OUT_INV | \
+                           LEDC_CON_BAUD | \
+                           LEDC_CON_DELAY | \
+                           LEDC_CON_IN_FORMAT | \
+                           LEDC_CON_IDLE_LEVEL | \
+                           LEDC_CON_VLD_INV);
+
+    /* Config output data all invert */
+    tmp_reg |= ledc_timing_init_struct->output_invert & LEDC_CON_OUT_INV;
+    /* Config input format */
+    tmp_reg |= ledc_timing_init_struct->format & LEDC_CON_IN_FORMAT;
+    /* Config idle level */
+    tmp_reg |= ledc_timing_init_struct->idle_level & LEDC_CON_IDLE_LEVEL;
+    /* Config valid data direct or invert */
+    tmp_reg |= ledc_timing_init_struct->valid_data_mode & LEDC_CON_VLD_INV;
+    if (ledc_timing_init_struct->valid_data_mode & LEDC_CON_VLD_INV) {
+        tmp_reg &= ~LEDC_CON_BYTE_INV;
+        tmp_reg |= ledc_timing_init_struct->byte_inv_number & LEDC_CON_BYTE_INV;
+    }
+
+    /* Restore the value to register */
+    LEDC->con = tmp_reg;
+}
+
+/**
+ * @brief  Initialize the code element timing accordingto the specified
+ *         parameters in the ledc_timing_init_struct.
+ * @param  ledc_timing_init_struct: pointer to a ledc_timing_init_typedef structure that
+ *         contains the configuration information for the specified LEDC peripheral.
+ * @retval None
+ */
+void ledc_timing_init(ledc_timing_init_typedef *ledc_timing_init_struct)
+{
+    u32 tmp_reg;
+    ledc_timing_init_typedef *p = ledc_timing_init_struct;
+
+    /* Load the register value to variable */
+    tmp_reg = LEDC->con;
+    /* Config baud */
+    tmp_reg |= (ledc_timing_init_struct->baud << 16) & LEDC_CON_BAUD;
+    /* Config delay */
+    tmp_reg |= (ledc_timing_init_struct->delay << 8) & LEDC_CON_DELAY;
+    /* Restore the value to register */
+    LEDC->con = tmp_reg;
+
+    /* Config code element timing */
+    tmp_reg = 0;
+    if ((p->code_1_high <= p->baud) && (p->code_0_high <= p->baud)) {
+        tmp_reg = (p->code_1_high << 24) | \
+                  ((p->baud - p->code_1_high) << 16) | \
+                  (p->code_0_high << 8) | \
+                  ((p->baud - p->code_0_high));
+    }
+    LEDC->tix = tmp_reg;
+
+    /* Config reset timing */
+    tmp_reg = (p->reset_low << 16) | p->reset_high;
+    LEDC->rstx = tmp_reg;
+}
+
+/**
+ * @brief  De-initialize the specified LEDC peripheral.
+ * @retval None
+ */
+void ledc_deinit(void)
+{
+    LEDC->con &= ~(LEDC_CON_DMA_INT_EN | \
+                   LEDC_CON_RST_INT_EN | \
+                   LEDC_CON_INT_EN | \
+                   LEDC_CON_EN);
+    clk_gate2_cmd(CLK_GATE2_LEDC, CLK_DIS);
+}
+
+/**
+ * @brief  Enable or disable the specified LEDC peripheral.
+ * @param  state: the state of the LEDC peripheral.
+ *         This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void ledc_cmd(FUNCTIONAL_STATE state)
+{
+    if (state != DISABLE) {
+        LEDC->con |= LEDC_CON_EN;
+    } else {
+        LEDC->con &= ~LEDC_CON_EN;
+    }
+}
+
+/**
+ * @brief  Enable the LEDC DMA function.
+ * @param  addr: DMA start address.
+ * @param  len: DMA transmit len.
+ * @retval None
+ */
+AT(.com_periph.ledc.transport)
+void ledc_dma_kick(uint32_t addr, uint16_t len)
+{
+    LEDC->addr = addr;
+    LEDC->cnt = (0x01 << 31) | len;
+}
+
+/**
+ * @brief  Start ledc transmit.
+ * @retval None
+ */
+AT(.com_periph.ledc.transport)
+void ledc_kick(void)
+{
+    LEDC->con |= LEDC_CON_LEDC_KICK;
+}
+
+/**
+ * @brief  Enable or disable the specified LEDC interrupt.
+ * @param  isr: Function to be executed for service interruption.
+ * @param  pr: Priority of service interruption.
+ * @param  flag_type: specifies the LEDC interrupt sources to be enable or disable.
+ *         This parameter can be one of the following values:
+ *             @arg LEDC_FLAG_DONE: One frame has tx done.
+ *             @arg LEDC_FLAG_RST: One frame has tx done and reset time has finished.
+ *             @arg LEDC_FLAG_DMA: One DMA transmit finished.
+ * @param  state: the new state need to config.
+ * @retval None
+ */
+void ledc_pic_config(isr_t isr, int pr, LEDC_FLAG_TYPEDEF flag_type, FUNCTIONAL_STATE state)
+{
+    u32 flag_pending_bit = 0;
+
+    if (flag_type == 0) {
+        return;
+    }
+
+    if (flag_type & LEDC_FLAG_DONE) {
+        flag_pending_bit |= LEDC_CON_INT_EN;
+    }
+
+    if (flag_type & LEDC_FLAG_RST) {
+        flag_pending_bit |= LEDC_CON_RST_INT_EN;
+    }
+
+    if (flag_type & LEDC_FLAG_DMA) {
+        flag_pending_bit |= LEDC_CON_DMA_INT_EN;
+    }
+
+    if (state != DISABLE) {
+        LEDC->con |= flag_pending_bit;
+        sys_irq_init(IRQn_IR_QDEC_LEDC, pr, isr);
+    } else {
+        LEDC->con &= ~flag_pending_bit;
+    }
+}
+
+/**
+ * @brief  Check the specified LEDC flag is set or not.
+ * @param  flag_type: specifies the flag to check.
+ *         the parameter can be one of the following values:
+ *             @arg LEDC_FLAG_DONE: One frame has tx done.
+ *             @arg LEDC_FLAG_RST: One frame has tx done and reset time has finished.
+ *             @arg LEDC_FLAG_DMA: One DMA transmit finished.
+ * @retval The state of flag_type (SET or RESET).
+ */
+AT(.com_periph.ledc.flag)
+FLAG_STATE ledc_get_flag(LEDC_FLAG_TYPEDEF flag_type)
+{
+    u32 flag_pending_bit = 0;
+
+    if (flag_type & LEDC_FLAG_DONE) {
+        flag_pending_bit |= LEDC_PEND_LEDC_PND;
+    }
+
+    if (flag_type & LEDC_FLAG_RST) {
+        flag_pending_bit |= LEDC_PEND_RST_PND;
+    }
+
+    if (flag_type & LEDC_FLAG_DMA) {
+        flag_pending_bit |= LEDC_PEND_DMA_PND;
+    }
+
+    if ((LEDC->pend & flag_pending_bit) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+ * @brief  Clear the LEDC pending.
+ * @param  flag_type: specified flag to clear.
+ *             @arg LEDC_FLAG_DONE: One frame has tx done.
+ *             @arg LEDC_FLAG_RST: One frame has tx done and reset time has finished.
+ *             @arg LEDC_FLAG_DMA: One DMA transmit finished.
+ * @retval None
+ */
+AT(.com_periph.ledc.flag)
+void ledc_clear_flag(LEDC_FLAG_TYPEDEF flag_type)
+{
+    u32 flag_pending_bit = 0;
+
+    if (flag_type & LEDC_FLAG_DONE) {
+        flag_pending_bit |= LEDC_PEND_LEDC_PND;
+    }
+
+    if (flag_type & LEDC_FLAG_RST) {
+        flag_pending_bit |= LEDC_PEND_RST_PND;
+    }
+
+    if (flag_type & LEDC_FLAG_DMA) {
+        flag_pending_bit |= LEDC_PEND_DMA_PND;
+    }
+
+    LEDC->pend = flag_pending_bit;
+}
+
+/**
+ * @brief  Set the length of frame length.
+ * @param  frame_length: the length param of frame that need to config.
+ * @retval None
+ */
+void ledc_set_frame_length(uint16_t frame_length)
+{
+    LEDC->fd = frame_length & 0xfff;
+}
+
+/**
+ * @brief  Set the number of loop.
+ * @param  loop_n: the number param of loop that need to config.
+ * @retval None
+ */
+void ledc_set_loop_number(uint16_t loop_n)
+{
+    LEDC->lp = loop_n & 0x7ff;
+}
+
+/**
+ * @brief  Get the length of frame length.
+ * @retval None
+ */
+uint16_t ledc_get_frame_length(void)
+{
+    return (LEDC->fd & 0xfff);
+}
+
+/**
+ * @brief  Get the number of loop.
+ * @retval None
+ */
+uint16_t ledc_get_loop_number(void)
+{
+    return (LEDC->lp & 0x7ff);
+}

+ 103 - 0
driver/driver_ledc.h

@@ -0,0 +1,103 @@
+/*
+ * @File name    : driver_ledc.h
+ * @Author       : Bluetrum IOT Team K.
+ * @Date         : 2023-07-12
+ * @Description  : This file contains all the functions protorypes for the LEDC library.
+ * 
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_LEDC_H
+#define _DRIVER_LEDC_H
+
+#include "driver_com.h"
+
+/**
+ * @brief Flag Enumeration.
+ */
+typedef enum {
+    LEDC_FLAG_DONE          = 0x01,
+    LEDC_FLAG_RST           = 0x02,
+    LEDC_FLAG_DMA           = 0x04,
+} LEDC_FLAG_TYPEDEF;
+
+/**
+ * @brief Output Invert Enumeration.
+ */
+typedef enum {
+    LEDC_OUT_INV_DIS        = 0x00000000,
+    LEDC_OUT_INV_EN         = 0x02000000,
+} LEDC_OUT_INV_TYPEDEF;
+
+/**
+ * @brief DMA Buffer Data Format Enumeration.
+ */
+typedef enum {
+    LEDC_IN_FORMAT_RGB      = 0x00000000,
+    LEDC_IN_FORMAT_WRGB     = 0x00000080,
+} LEDC_IN_FORMAT_TYPEDEF;
+
+/**
+ * @brief Idle Level Enumeration.
+ */
+typedef enum {
+    LEDC_IDLE_LEVEL_LOW     = 0x00000000,
+    LEDC_IDLE_LEVEL_HIGH    = 0x00000020,
+} LEDC_IDLE_LEVEL_TYPEDEF;
+
+/**
+ * @brief Valid Data Direct or Invert Enumeration.
+ */
+typedef enum {
+    LEDC_VALID_DATA_DIR     = 0x00000000,
+    LEDC_VALID_DATA_INV     = 0x00000010,
+} LEDC_VALID_DATA_TYPEDEF;
+
+/**
+ * @brief Valid Data Invert Byte Number Enumeration.
+ */
+typedef enum {
+    LEDC_BYTE_INV_NO        = 0x00000000,
+    LEDC_BYTE_INV_1B        = 0x00000004,
+    LEDC_BYTE_INV_2B        = 0x00000008,
+    LEDC_BYTE_INV_4B        = 0x0000000c,
+} LEDC_BYTE_INV_TYPEDEF;
+
+/**
+ * @brief LEDC Ctrl Initialization Struct.
+ */
+typedef struct {
+    LEDC_OUT_INV_TYPEDEF    output_invert;
+    LEDC_IN_FORMAT_TYPEDEF  format;
+    LEDC_IDLE_LEVEL_TYPEDEF idle_level;
+    LEDC_VALID_DATA_TYPEDEF valid_data_mode;
+    LEDC_BYTE_INV_TYPEDEF   byte_inv_number;
+} ledc_init_typedef;
+
+/**
+ * @brief LEDC Code Element Timing Initialization Struct.
+ */
+typedef struct {
+    uint8_t                 baud;
+    uint8_t                 delay;
+    uint8_t                 code_0_high;
+    uint8_t                 code_1_high;
+    uint16_t                reset_high;
+    uint16_t                reset_low;
+} ledc_timing_init_typedef;
+
+
+void ledc_init(ledc_init_typedef *ledc_init_struct);
+void ledc_timing_init(ledc_timing_init_typedef *ledc_timing_init_struct);
+void ledc_deinit(void);
+void ledc_cmd(FUNCTIONAL_STATE state);
+void ledc_dma_kick(uint32_t addr, uint16_t len);
+void ledc_kick(void);
+void ledc_pic_config(isr_t isr, int pr, LEDC_FLAG_TYPEDEF flag_type, FUNCTIONAL_STATE state);
+FLAG_STATE ledc_get_flag(LEDC_FLAG_TYPEDEF flag_type);
+void ledc_clear_flag(LEDC_FLAG_TYPEDEF flag_type);
+void ledc_set_frame_length(uint16_t frame_length);
+void ledc_set_loop_number(uint16_t loop_n);
+uint16_t ledc_get_frame_length(void);
+uint16_t ledc_get_loop_number(void);
+
+#endif // _DRIVER_LEDC_H

+ 825 - 0
driver/driver_lowpwr.c

@@ -0,0 +1,825 @@
+/*
+ * @File name    : driver_lowpwr.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-15
+ * @Version      : v2.0
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+
+#include "driver_gpio.h"
+#include "driver_saradc.h"
+#include "driver_lowpwr.h"
+
+extern void io_sleep(void);
+extern void io_resume(void);
+
+
+extern u32 __comm_vma;
+
+static lowpwr_sfr_backup_t sfr_backup;
+static uint32_t wkupedg_bak = 0;
+
+AT(.com_sleep.lv2_get_wksrc)
+uint32_t lowpwr_sleep_get_io_wksrc(void)
+{
+    return wkupedg_bak;
+}
+
+AT(.com_sleep.lv2_clr_wksrc)
+void lowpwr_sleep_clr_io_wksrc(void)
+{
+    wkupedg_bak = 0;
+}
+
+u32 lowpwr_get_wakeup_source(void)
+{
+    u32 reason = RTCCON9;
+
+    if(reason){
+        if(reason & WK_LP_KEYSCAN){
+            printf("KEY_SCAN_WK\n");
+        }
+
+        if(reason & WK_LP_GPIO){
+            printf("GPIO_WK\n");
+        }
+
+        if(reason & WK_LP_TOUCH){
+            printf("TOUCH_WK\n");
+        }
+
+        if(reason & WK_LP_INBOX){
+            printf("INBOX_WK\n");
+        }
+
+        if(reason & WK_LP_VUSB){
+            printf("VUSB_WK\n");
+        }
+
+        if(reason & WK_LP_WK0){
+            printf("WKO_WK\n");
+        }
+
+        if(reason & WK_LP_RTC_1S){
+            printf("RTC1S_WK\n");
+        }
+
+        if(reason & WK_LP_ALARM){
+            printf("ALMWKP_WK\n");
+        }
+
+        RTCCON9 = 0x1fff;                                //Clr wakeup pending
+        RTCCON10 = 0xffff;
+    }
+
+    return reason;
+
+}
+
+void lowpwr_wakeup_disable(void)
+{
+    RTCCON9 = 0x1fff;                           //Clr wakeup pending
+    RTCCON10 = 0xffff;
+    RTCCON3 &= 0xFF;
+
+    WKUPCPND = 0xff << 16;                      //clear wakeup pending
+    WKUPEDG = 0;
+    WKUPCON = 0;
+    PORTINTEDG = 0;
+    PORTINTEN = 0;
+}
+
+void lowpwr_clr_wakeup_pending(void)
+{
+    WKUPCPND = 0xff << 16;                      //clear wakeup pending
+
+    RTCCON9 = 0x1fff;                           //Clr wakeup pending
+    RTCCON10 = 0xffff;
+}
+
+AT(.com_periph.lowpwr.sleep)
+bool lowpwr_is_wakeup_pending(u32 ignore_src)
+{
+    u32 wk_pending = 0x1fff;
+
+    if(ignore_src){
+        wk_pending &= ~ignore_src;
+    }
+
+    return (RTCCON9 & wk_pending);
+}
+
+void lowpwr_wk0_wakeup_config(lowpwr_wakeup_typedef *config)
+{
+    if (config->lp_type == LP_TYPE_SLEEP) {
+        wk0_edge_capture_config(config->edge);
+        WKUPCON |= BIT(17);             //wakeup sleep mode enable
+        RTCCON3 |= BIT(17);
+    } else if(config->lp_type == LP_TYPE_POWOFF) {
+        if (config->edge == WK_EDGE_FALLING) {
+            wko_io_config(1, 0, 1);
+            RTCCON1 &= ~BIT(6);         //wk pin low level wakeup
+        } else {
+            wko_io_config(0, 1, 1);
+            RTCCON1 |= BIT(6);          //wk pin high level wakeup
+        }
+        RTCCON3 |= BIT(10);
+    }
+}
+
+void lowpwr_gpio_wakeup_config(lowpwr_wakeup_typedef *config)
+{
+    if((config->gpiox == GPIOA_REG) || (config->gpiox == GPIOB_REG)){
+        gpio_edge_cap_typedef gpio_cfg;
+
+        gpio_cfg.edge = config->edge;
+        gpio_cfg.gpio_pin = config->gpio_pin;
+        gpio_cfg.gpiox = config->gpiox;
+        gpio_cfg.gpio_pupd = config->gpio_pupd;
+        gpio_edge_capture_config(&gpio_cfg);
+
+        RTCCON3 |= BIT(17);
+        WKUPCON |= BIT(17);                         //wakeup sleep mode enable
+        WKUPCPND = 0xff << 16;                      //clear wakeup pending
+    }
+}
+
+void lowpwr_wakeup_config_do(lowpwr_wakeup_typedef *config)
+{
+    if(config){
+        if(!(config->source & WK_LP_TOUCH)){
+            RTCCON0 &= ~BIT(4);     //disable touch key
+        }
+
+        if(config->source & WK_LP_WK0){
+            lowpwr_wk0_wakeup_config(config);
+        }
+
+        if(config->source & WK_LP_TOUCH){
+            RTCCON0 |= BIT(4);
+            RTCCON1 |= BIT(8);
+            RTCCON1 |= BIT(9);          //VDDTK enable for touch key logic
+            RTCCON3 |= BIT(14);         // Touch key long press wakeup enable
+        }
+
+        if(config->source & WK_LP_BT){
+            RTCCON3 |= BIT(13);
+        }
+
+        if(config->source & WK_LP_ALARM){
+            RTCCON0 |= BIT(19);
+            RTCCON3 |= BIT(8);
+        }
+
+        if(config->source & WK_LP_RTC_1S){
+            RTCCON3 |= BIT(9);
+        }
+
+        if(config->source & WK_LP_VUSB){
+            RTCCON3 |= BIT(11);
+        }
+
+        if(config->source & WK_LP_KEYSCAN){
+            RTCCON3 |= BIT(16);
+        }
+
+        if(config->source & WK_LP_INBOX){
+           RTCCON3 |= BIT(12);
+
+        }
+
+        if(config->source & WK_LP_GPIO){
+            lowpwr_gpio_wakeup_config(config);
+        }
+    }
+}
+
+void lowpwr_wakeup_config(lowpwr_wakeup_typedef *config)
+{
+    if(config){
+        RTCCON3 &= 0xFF;
+        lowpwr_wakeup_config_do(config);
+    }
+}
+
+void lowpwr_wakeup_config_2(lowpwr_wakeup_typedef *config)
+{
+    if(config){
+        lowpwr_wakeup_config_do(config);
+    }
+}
+
+void lowpwr_wakeup_source_enable(WK_LP_SRC_SEL wk_src)
+{
+    if(wk_src & WK_LP_WK0){
+        RTCCON3 |= BIT(17);
+    }
+
+    if(wk_src & WK_LP_TOUCH){
+        RTCCON3 |= BIT(14);
+    }
+
+    if(wk_src & WK_LP_BT){
+        RTCCON3 |= BIT(13);
+    }
+
+    if(wk_src & WK_LP_ALARM){
+        RTCCON3 |= BIT(8);
+    }
+
+    if(wk_src & WK_LP_RTC_1S){
+        RTCCON3 |= BIT(9);
+    }
+
+    if(wk_src & WK_LP_VUSB){
+        RTCCON3 |= BIT(11);
+    }
+
+    if(wk_src & WK_LP_KEYSCAN){
+        RTCCON3 |= BIT(16);
+    }
+
+    if(wk_src & WK_LP_INBOX){
+       RTCCON3 |= BIT(12);
+
+    }
+
+    if(wk_src & WK_LP_GPIO){
+        RTCCON3 |= BIT(17);
+    }
+}
+
+void lowpwr_wakeup_source_disable(WK_LP_SRC_SEL wk_src)
+{
+    if (wk_src == WK_LP_SRC_ALL) {
+        RTCCON3 &= 0xFF;
+        return;
+    }
+
+    if(wk_src & WK_LP_WK0){
+        RTCCON3 &= ~BIT(17);
+    }
+
+    if(wk_src & WK_LP_TOUCH){
+        RTCCON3 &= ~BIT(14);         // Touch key long press wakeup enable
+    }
+
+    if(wk_src & WK_LP_BT){
+        RTCCON3 &= ~BIT(13);
+    }
+
+    if(wk_src & WK_LP_ALARM){
+        RTCCON3 &= ~BIT(8);
+    }
+
+    if(wk_src & WK_LP_RTC_1S){
+        RTCCON3 &= ~BIT(9);
+    }
+
+    if(wk_src & WK_LP_VUSB){
+        RTCCON3 &= ~BIT(11);
+    }
+
+    if(wk_src & WK_LP_KEYSCAN){
+        RTCCON3 &= ~BIT(16);
+    }
+
+    if(wk_src & WK_LP_INBOX){
+       RTCCON3 &= ~BIT(12);
+
+    }
+
+    if(wk_src & WK_LP_GPIO){
+        RTCCON3 &= ~BIT(17);
+    }
+}
+
+ALIGNED(512)
+void lowpwr_pwroff_mode1_do(void)
+{
+    u32 rtccon3;
+
+    saradc_deinit();         //disable saradc
+
+    PICCONCLR = BIT(0);     //disable global interrupt
+    NMICON = 0;
+
+    RTCCON3 &= ~BIT(17);    //disable gpio wakeup
+
+    RTCCON9 = 0x1fff;       //Clr wakeup pending
+
+    if(RTCCON3 & BIT(14)){                          //Touch need rc2m clk
+        RTCCON0 |= BIT(19);                         //RC2M_RTC enable
+        asm("nop");asm("nop");asm("nop");
+        RTCCON0 = (RTCCON0 & ~(0x03 << 12)) | (0x02 << 12); //CLK2M in Touch select SNF_RC_RTC
+    }else{
+        RTCCON0  &= ~BIT(19);                       //RC2M_RTC disable
+    }
+
+    RTCCON4 &= ~BIT(17);    //FGS
+    RTCCON4 &= ~BIT(18);    //FGBUF
+    RTCCON4 &= ~BIT(15);    //VIO_PD not work
+
+    RTCCON4 = (RTCCON4 & ~(0x3f<<24)) | (5<<24) | (6<<27);  //no sfr access, bit26~bit24, VRTC11 is 1.025V; sfr access, bit29~27, VRTC11 is 1.09V
+
+    CLKCON0 &= ~0xc;        //sys_clk switch to RC
+    asm("nop");
+    asm("nop");
+    asm("nop");
+
+    XOSCCON = 0;
+    PLL0CON = 0;
+
+    rtccon3 = RTCCON3 & ~(0xFF);
+    rtccon3 |= BIT(5) | BIT(6);      //core power down enable
+
+    WDT_DIS();
+
+    RTCCON |= BIT(5);       //RTC wake up power down mode reset system enable
+    RTCCON3 = rtccon3;
+
+    LPMCON |= BIT(0);	    //sleep mode
+    LPMCON |= BIT(1);       //idle mode
+
+    asm("nop");asm("nop");asm("nop");
+
+    while(1);
+}
+
+//in pwroff_mode2_final, can't use subfunction
+AT(.com_text.pwroff.mode2)
+static void pwroff_mode2_final(void)
+{
+    u32 rtccon3 = RTCCON3;
+    u32 rtccon0 = RTCCON0;
+
+    RTCCON12 = (RTCCON12 & ~0xf) | 0xa | (0x3<<6) | (0x3<<4); //disable WKO reset, RTC WDT, GPIO reset
+
+    RTCCON4 &= ~(BIT(17) | BIT(18));    //FGS, FGBUF
+
+    if(RTCCON3 & (BIT(8) | BIT(14) | BIT(16))){     //wakeup source need rc2m clk
+        RTCCON0 |= BIT(19);                         //RC2M_RTC enable
+    }else{
+        RTCCON0  &= ~BIT(19);                       //RC2M_RTC disable
+    }
+
+    PWRCON1 = (PWRCON1 & ~(0XF<<14)) | (0X0<<14); //DI_SW DISABLE
+
+    RTCCON8 &= ~BIT(29);
+    RTCCON4 |= BIT(11);     //VDDIO_AON voltage
+    RTCCON3 |= BIT(7);     //enable vddio aon ldo
+
+    RTCCON4 = (RTCCON4 & ~(0x3f<<24)) | (5<<24) | (6<<27);  //no sfr access, bit26~bit24, VRTC11 is 1.025V; sfr access, bit29~27, VRTC11 is 1.09V
+
+    rtccon0 = RTCCON0;
+
+    if(RTCCON3 & BIT(14)){
+        rtccon0 = (rtccon0 & ~(0x03 << 12)) | (0x02 << 12); //CLK2M in Touch select SNF_RC_RTC
+    }
+
+    if(RTCCON3 & BIT(16)){
+        rtccon0 = (rtccon0 & ~(0x03 << 14)) | (0x02 << 14); //CLK2M in Keyscan select SNF_RC_RTC
+    }
+
+    RTCCON0 = rtccon0;
+
+    RTCCON5 &= ~(1<<12);   //CLEAR LP FLAG
+    WKUPCPND = 0xFF<<16;
+
+    CLKCON0 &= ~0xc;        //sys_clk switch to RC
+    asm("nop");
+    asm("nop");
+    asm("nop");
+
+    XOSCCON = 0;
+    PLL0CON = 0;
+
+//  when switch power, reduce lp_top power, disable ram0/1 clock
+    CLKGAT0 &= ~((3<<2) | BIT(15)); // sram0/1 & LP disable clock
+
+    RTCCON5 &= ~(1<<11); // dis sram if
+
+    RTCCON5 |= (BIT(15) | BIT(16));   //RAM0 RAM1 shutdown
+    //RTCCON5 |= BIT(13); //RAM0/1 light sleep
+    //RTCCON5 |= BIT(14); //RAM0/1 deep sleep
+
+    // pmu power down
+    LVDCON &= ~(BIT(3) | BIT(5));      //disable LVD reset
+
+    rtccon3 = RTCCON3 & ~BIT(5);    //disable C2RL
+    rtccon3 |= (BIT(4) | BIT(3));   //PD CORE2, disable all analog model except IO
+
+    rtccon3 &= ~0x7;     //disable VDDCORE & VDDIO & VDDBT LDO
+
+    //disable WDT
+    WDT_DIS();
+
+    RTCCON |= BIT(5);   //RTC wake up power down mode reset system enable
+
+    RTCCON3 = rtccon3;
+    LPMCON |= BIT(0);	//sleep mode
+    LPMCON |= BIT(1);   //idle mode
+    while(1);
+}
+
+AT(.com_text.lp_port_init)
+void lp_port_init(void)
+{
+    //config IO low power state
+    //when RTCCON5 bit12=0, will select LPGPIO; otherwise, select GPIO
+    //save IO
+
+    if(pmu_vddio_to_flash()){
+        GPIOGDE = BIT(2);
+        GPIOGPU = BIT(2);
+    }else{
+        GPIOGDE = 0;
+        GPIOGPU = 0;
+    }
+
+    CLKGAT0 |= BIT(15);         //lp_clk enable
+
+    io_sleep();
+}
+
+AT(.com_text.pwroff_mode2)
+void lowpwr_pwroff_mode2_do(void)
+{
+    u8 *src, *dst;
+    u32 i;
+    void (*p_func)(void);
+
+    p_func = (void (*)(void))CACHE_ADDR;
+
+    saradc_deinit();
+
+    PICCONCLR = BIT(0);     //disable global interrupt
+    NMICON = 0;
+
+    RTCCON9 = 0x1fff;       //Clr wakeup pending
+    RTCCON10 = 0xffff;
+
+    PWRCON1 &= ~(0xf<<14);  //disable flash power gate
+    PWRCON1 |= BIT(18);
+
+    //copy pwroff_mode2_final to cache ram
+
+    dst = (u8*) CACHE_ADDR;
+    src = (u8*) (&pwroff_mode2_final);
+    for(i = 0; i < 0x300; i++){
+        *dst++ = *src++;
+    }
+
+    lp_port_init();
+
+    //jmp to run lp_sniff_final()
+    p_func();
+}
+
+
+AT(.com_sleep.sleep.lv1)
+WEAK void lowpwr_sleep_lv1_proc(void)
+{
+    u32 pwrcon2 = PWRCON2;
+    u32 pwrcon0 = PWRCON0;
+    u32 lpmcon = LPMCON;
+
+    PWRCON2 = (PWRCON2 & ~(0xf<<0)) | (0x0<<0);           // vddbt set 0.85v
+
+    PLL0CON |= BIT(1);
+    PLL0CON = (PLL0CON & ~(0x1));                         // disable vdd12 from AVDD
+
+    XOSCCON &= ~(BIT(5) | 0xb<<24);                      // disable XOSC48M clkout
+
+    // vddio AON
+    RTCCON3 |= BIT(7);
+    PWRCON0 = (PWRCON0 & ~(0XF<<5)) | 4<<5;
+    delay_us(5);
+    RTCCON3 &= ~BIT(1);
+
+    //LPMCON = (LPMCON & ~(0X1F << 16)) | (0x0<<16);      // sniff vddcore set 0.7v
+
+    WDT_DIS();
+
+    LPMCON |= BIT(2);                                     // system sleep
+    asm("nop");asm("nop");
+    asm("nop");asm("nop");
+
+    PWRCON1 |= BIT(7);                                    // enable vddbt climit
+    PWRCON2 = pwrcon2;
+    delay_us(10);                                         // disable vddbt climit
+    PWRCON1 &= ~BIT(7);
+
+    LPMCON = lpmcon;                                      // resume vddcore
+
+    // vddio AON exit
+    RTCCON3 |= BIT(1);
+    PWRCON0 = pwrcon0;
+    delay_us(1);
+    RTCCON3 &= ~BIT(7);
+
+    XOSCCON |= BIT(5) | 0xb<<24;                         // resume XOSC clkout
+
+    WDT_EN();
+}
+
+AT(.com_sleep.lv2)
+WEAK void lowpwr_sleep_sfr_user_save(void)
+{
+
+}
+
+AT(.com_sleep.lv2)
+WEAK void lowpwr_sleep_sfr_user_resume(void)
+{
+
+}
+
+
+AT(.com_sleep.lv2_do)
+void lp_sleep_lv2_do(void)
+{
+    u32 rtccon3 = RTCCON3;
+
+    // 1. disable clock
+    CLKGAT0 &= ~(BIT(15) | BIT(3) | BIT(2)); //lp clk, sram0/1 disable clock
+    //RTCCON4 &= ~(0x3<<22);                //VRTC24 to 1.7V
+
+    // 2. disable interface
+    //    disable if, then deep sleep memory, can not do in 1 cycle
+    RTCCON5 &= ~(1<<11);    // dis sram if
+    //RTCCON5 = (RTCCON5 & ~(0x7<<13)) | (1<<13);
+    RTCCON5 |=  (2<<13);    // 1xx : shutdown
+                            // 01x : deep sleep
+                            // 001 : light sleep
+                            // 000 : normal
+    RTCCON5 |= (1<<17);     // set lp_flag
+
+    RTCCON5 |= BIT(0);
+
+    // pmu power down ...
+    rtccon3 &= ~(1<<5);     // VDDCORE and VLCORE
+    rtccon3 |= ((1<<3) | (1<<4));      // VLCORE LDO enable, RI_PD_CORE2 from rtc
+    rtccon3 &= ~(0x7<<0);   // VDDBT/VDDIO/VDDCORE LDO disable
+
+    RTCCON |= BIT(5);       //RTC wake up power down mode reset system enable
+    RTCCON3 = rtccon3;
+//    RTCCON3 |= (1<<6);          // PD CORE
+
+    LPMCON |= BIT(0);
+    LPMCON |= BIT(1);       //idle mode
+    asm("nop");
+    asm("nop");
+    asm("nop");
+    while(1);
+}
+
+AT(.com_sleep.lv2_proc)
+void lp_sleep_lv2_proc(void)
+{
+    u32 rtccon0 = RTCCON0;
+    u32 *dst = (u32 *)0x70000;
+    u32 *src = (u32 *)&lp_sleep_lv2_do;
+
+    for(uint i=0; i<512/4; i++) {
+        *dst++ = *src++;
+    }
+
+    // 1, save IO
+    CLKGAT0 |= (1<<15);         // LP_CLK Enable
+    io_sleep();
+    WKUPCPND = 0xFF<<16;
+    wkupedg_bak = 0;
+
+    sfr_backup.gpioa_fen = GPIOAFEN;
+    sfr_backup.gpiob_fen = GPIOBFEN;
+    sfr_backup.gpioa_fdiren = GPIOAFDIREN;
+    sfr_backup.gpiob_fdiren = GPIOBFDIREN;
+    sfr_backup.gpioa_drv = GPIOADRV;
+    sfr_backup.gpiob_drv = GPIOBDRV;
+
+    RTCCON9 = 0x1fff;           //Clr wakeup pending
+    RTCCON10 = 0xffff;
+
+    WDT_DIS();
+    RTCCON12 = (RTCCON12 & ~0xf) | 0xa | (0x3<<6) | (0x3<<4);   //disable WKO reset, RTC WDT, GPIO reset
+
+    // 2, analog disable
+    RTCCON4 &= ~(BIT(17) | BIT(18));    //FGS,FGBUF
+
+    RTCCON8 &= ~BIT(29);
+    RTCCON3 |= BIT(7);      //enable vddio aon ldo
+
+    RTCCON4 = (RTCCON4 & ~(0x3f<<24)) | (6<<24) | (6<<27);                  //no sfr access, bit26~bit24, VRTC11 is 0.83V; sfr access, bit29~27, VRTC11 is 1.1V
+
+    // PG OFF
+    PWRCON1 |= BIT(9) | BIT(18);            // SD/FS PG PD
+    PWRCON1  = PWRCON1 & ~((0x3f << 10)) ;  // PG off
+    // ... other analog pd
+
+    if(RTCCON3 & BIT(14)){
+        rtccon0 = (rtccon0 & ~(0x03 << 12)) | (0x02 << 12); //CLK2M in Touch select SNF_RC_RTC
+    }
+
+    if(RTCCON3 & BIT(16)){
+        rtccon0 = (rtccon0 & ~(0x03 << 14)) | (0x02 << 14); //CLK2M in Keyscan select SNF_RC_RTC
+    }
+
+    rtccon0 = (rtccon0 & ~(0x7<<22)) | (1<<22);     //sys reset delay
+
+    RTCCON0 = rtccon0;
+
+    // 3, select sniff rc clock and disable pll,xosc
+    CLKCON0  = (CLKCON0 & ~(3<<2)) | (0<<2); // sel rc2m
+    asm("nop");
+    asm("nop");
+    asm("nop");
+
+    // 4, PLL, XOSC, CLK2M_BT off
+    PLL0CON  = 0;
+    PLL0CON1 = 0;
+    XOSCCON = 0;
+
+    //RTCCON3 |= BIT(3) | BIT(5);             //enable RL2VLC & C2VLC
+    //PWRCON0 = (PWRCON0 & ~0x1f) | 0x8;      //VDDCORE is 0.9V
+
+    asm("j 0x70000");
+};
+
+AT(.com_sleep.lv2_wakeup)
+void lp_wakeup_lv2_proc(void)
+{
+    bool gpio_pending = true;
+
+    RTCCON4 &= ~BIT(6);                     //VDDBT to VCORE dis
+
+    RTCCON4 |= BIT(5) ;                     //VCORE from VDDIO
+
+    PICADR = (u32)&__comm_vma;
+
+    if(!(sfr_backup.rtccon5 & BIT(0))){
+        PWRCON1 = (PWRCON1 & ~(0X3<<2)) | (0X1<<2);       // DI_CLIMIT_S   109:85:366mA
+        RTCCON5 &= ~BIT(0);
+    }
+
+    PWRCON0 |= BIT(20);                     //pmu normal
+
+    wkupedg_bak = WKUPEDG;
+
+    //pending is generated due to burrs after the gpio is wakeup from sleep. In this case, manually clear pending
+    if(!(RTCCON9 & WK_LP_GPIO) && !(WKUPEDG & 0xff0000)){
+        gpio_pending = false;
+    }
+
+    //resume IO
+    io_resume();
+
+    if (gpio_pending == false) {
+        WKUPCPND = 0xFF<<16;
+    }
+
+    GPIOAFEN = sfr_backup.gpioa_fen;
+    GPIOBFEN = sfr_backup.gpiob_fen;
+    GPIOAFDIREN = sfr_backup.gpioa_fdiren;
+    GPIOBFDIREN = sfr_backup.gpiob_fdiren;
+    GPIOADRV = sfr_backup.gpioa_drv;
+    GPIOBDRV = sfr_backup.gpiob_drv;
+
+
+    // 2, analog init
+    RTCCON3 |= BIT(0);                                          //VDDDBT
+    PWRCON0 = (PWRCON0 & ~0x1f) | pmu_get_vddcore();            //VDDCORE is 1.15V
+    asm("nop");
+
+    PLL0CON |= BIT(12);                         //DI_EN_LDO
+    delay(10);
+
+    RSTCON0 = sfr_backup.rstcon0;               //pllsdm reset release
+    delay(25);                                  //delay 100us, by rc
+
+
+    // 3, PLL,XOSC,CLK2M_BT, on
+    XOSCCON = sfr_backup.xosccon;
+    PLL0CON  = sfr_backup.pll0con;
+    PLL0CON1 = sfr_backup.pll0con1;
+
+    delay(700);                                 //delay 1ms - 2ms for xosc to work
+
+    CLKDIVCON0 = sfr_backup.clkdivcon0;
+
+    // 4, resume CLK
+    CLKCON1 = sfr_backup.clkcon1;               //xosc_mux_clk select xosc24m
+    asm("nop");
+    asm("nop");
+    asm("nop");
+
+    CLKCON0 = sfr_backup.clkcon0;               //sysclk select xosc_mux_clk
+    asm("nop");
+    asm("nop");
+
+    LVDCON &= ~BIT(30);                         //Enable reset pending
+}
+
+AT(.com_sleep.lv2_proc)
+WEAK void lowpwr_sleep_lv2_proc(void)
+{
+    sfr_backup.piccon  = PICCON;
+    sfr_backup.picen   = PICEN;
+    sfr_backup.picpr   = PICPR;
+    sfr_backup.nmicon  = NMICON;
+
+    sfr_backup.clkgat0 = CLKGAT0;
+    sfr_backup.clkgat1 = CLKGAT1;
+    sfr_backup.clkgat2 = CLKGAT2;
+
+    sfr_backup.pwrcon0 = PWRCON0 & ~BIT(20);
+    sfr_backup.pwrcon1 = PWRCON1;
+    sfr_backup.pwrcon2 = PWRCON2;
+
+    sfr_backup.clkcon0 = CLKCON0;
+    sfr_backup.clkcon1 = CLKCON1;
+    sfr_backup.clkdivcon0 = CLKDIVCON0;
+
+    sfr_backup.xosccon = XOSCCON;
+    sfr_backup.pll0con = PLL0CON;
+    sfr_backup.pll0con1 = PLL0CON1;
+
+    sfr_backup.rstcon0 = RSTCON0;
+    sfr_backup.rtccon = RTCCON;
+    sfr_backup.rtccon5 = RTCCON5;
+
+    lowpwr_sleep_sfr_save();
+    lowpwr_sleep_sfr_user_save();
+
+    u32 gpiogde = GPIOGDE;
+    u32 gpiogpu = GPIOGPU;
+    if(pmu_vddio_to_flash()){
+        GPIOGDE = BIT(2);                      //SPICS
+        GPIOGPU = BIT(2);
+    }else{
+        GPIOGDE = 0;
+        GPIOGPU = 0;
+        PWRCON1 &= ~(0XF<<14);                          //DI_SW DISABLE
+    }
+
+    sfr_backup.rtccon0 = RTCCON0;
+    sfr_backup.rtccon12 = RTCCON12;
+
+    if(RTCCON3 & (BIT(8) | BIT(9) | BIT(13) | BIT(14) | BIT(16))){      //wakeup source need rc2m clk
+        RTCCON0 |= BIT(19);                         //RC2M_RTC enable
+    }else{
+        RTCCON0  &= ~BIT(19);                       //RC2M_RTC disable
+    }
+
+    lp_sleep(lp_sleep_lv2_proc, lp_wakeup_lv2_proc);
+
+    RTCCON4 |= BIT(5) | BIT(6);                     //VCORE from VDDBT & VDDIO
+
+    RTCCON12 = sfr_backup.rtccon12;
+    RTCCON0 = sfr_backup.rtccon0;
+    asm("nop");
+    asm("nop");
+
+    PWRCON1 = sfr_backup.pwrcon1 | BIT(7);
+    PWRCON2 = sfr_backup.pwrcon2;
+    PWRCON0 = sfr_backup.pwrcon0 | BIT(20);
+
+    CLKGAT0 = sfr_backup.clkgat0;
+    CLKGAT1 = sfr_backup.clkgat1;
+    CLKGAT2 = sfr_backup.clkgat2;
+
+	lowpwr_sleep_sfr_resume();
+    lowpwr_sleep_sfr_user_resume();
+
+    GPIOGDE = gpiogde;
+    GPIOGPU = gpiogpu;
+
+    RTCCON = sfr_backup.rtccon;
+
+	PICCON  = sfr_backup.piccon;
+	PICPR   = sfr_backup.picpr;
+	PICEN   = sfr_backup.picen;
+	NMICON  = sfr_backup.nmicon;
+
+    if(sfr_backup.rtccon5 & BIT(0)){
+        RTCCON4 &= ~BIT(6);                         //LDO Mode,VCORE disable VDDBT, from VDDIO
+    }else{
+        RTCCON4 &= ~BIT(5);                         //Buck Mode,VCORE disable VDDIO, from VDDBT
+    }
+
+    PWRCON1 &= ~BIT(7);
+
+
+}
+
+AT(.com_sleep.sleep)
+void lowpwr_sleep_proc(u8 lpclk_type)
+{
+    if (lpclk_type == CLK_RCDIV) {
+        lowpwr_sleep_lv2_proc();
+    } else {
+        lowpwr_sleep_lv1_proc();
+    }
+}
+

+ 106 - 0
driver/driver_lowpwr.h

@@ -0,0 +1,106 @@
+/*
+ * @File name    : driver_lowpwr.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-15
+ * @Version      : v1.0
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_LOWPWR_H
+#define _DRIVER_LOWPWR_H
+
+#include "driver_com.h"
+
+typedef enum {
+    WK_EDGE_RISING        = 0x00,
+    WK_EDGE_FALLING       = 0x01,
+} WK_EDGE_SEL;
+
+typedef enum {
+    LP_TYPE_POWOFF          = 0x00,
+    LP_TYPE_SLEEP           = 0x01,
+} LP_TYPE_SEL;
+
+typedef enum {
+    WK_LP_ALARM             = BIT(0),
+    WK_LP_RTC_1S            = BIT(1),
+    WK_LP_WK0               = BIT(2),
+    WK_LP_VUSB              = BIT(3),
+    WK_LP_INBOX             = BIT(4),
+    WK_LP_BT                = BIT(5),
+    WK_LP_TOUCH             = BIT(6),
+    WK_LP_GPIO              = BIT(7),
+    WK_LP_KEYSCAN           = BIT(12),
+    WK_LP_SRC_ALL           = 0xFFFF,
+} WK_LP_SRC_SEL;
+
+typedef struct {
+    u32 piccon;
+    u32 picen;
+    u32 picpr;
+    u32 nmicon;
+    u32 clkgat0;
+    u32 clkgat1;
+    u32 clkgat2;
+
+    u32 pwrcon0;
+    u32 pwrcon1;
+    u32 pwrcon2;
+
+    u32 xosccon;
+    u32 pll0con;
+    u32 pll0con1;
+
+    u32 clkcon0;
+    u32 clkcon1;
+    u32 clkdivcon0;
+
+    u16 gpioa_fen;
+    u16 gpiob_fen;
+    u16 gpioa_fdiren;
+    u16 gpiob_fdiren;
+    u16 gpioa_drv;
+    u16 gpiob_drv;
+
+    u16 rstcon0;
+    u32 rtccon;
+    u32 rtccon0;
+    u32 rtccon12;
+    u32 rtccon5;
+} lowpwr_sfr_backup_t;
+
+typedef struct {
+    LP_TYPE_SEL lp_type;
+    WK_LP_SRC_SEL source;
+    WK_EDGE_SEL edge;
+    gpio_typedef *gpiox;
+    uint16_t gpio_pin;
+    uint16_t gpio_pupd;
+} lowpwr_wakeup_typedef;
+
+u32 lowpwr_get_wakeup_source(void);
+void lowpwr_wakeup_disable(void);
+bool lowpwr_is_wakeup_pending(u32 ignore_src);
+void lowpwr_clr_wakeup_pending(void);
+void lowpwr_wakeup_config(lowpwr_wakeup_typedef *config);
+void lowpwr_wakeup_config_2(lowpwr_wakeup_typedef *config);
+void lowpwr_wakeup_source_enable(WK_LP_SRC_SEL wk_src);
+void lowpwr_wakeup_source_disable(WK_LP_SRC_SEL wk_src);
+void lowpwr_wk0_wakeup_config(lowpwr_wakeup_typedef *config);
+void lowpwr_gpio_wakeup_config(lowpwr_wakeup_typedef *config);
+void lowpwr_sleep_proc(u8 lpclk_type);
+uint32_t lowpwr_sleep_get_io_wksrc(void);
+void lowpwr_sleep_clr_io_wksrc(void);
+
+/**
+  * @brief  only rtc digital, vddio is disable, only wk0 can wakeup system
+  */
+void lowpwr_pwroff_mode1_do(void);
+
+/**
+  * @brief  rtc digital,low power and vddio is enable, wk0, keyscan, touch and gpio can wakeup system
+  */
+void lowpwr_pwroff_mode2_do(void);
+
+
+#endif

+ 183 - 0
driver/driver_lpwm.c

@@ -0,0 +1,183 @@
+/*
+ * @File name    : driver_lpwm.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-03-06
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the LPWM peripheral.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_lpwm.h"
+
+/**
+ * @brief  Initializes the LPWM peripheral according to the specified
+ *         parameters in the lpwm_init_struct.
+ * @param  lpwm_init_struct: pointer to a lpwm_base_init_typedef structure that
+ *         contains the configuration information for the specified LPWM peripheral.
+ * @retval None
+ */
+void lpwm_init(lpwm_base_init_typedef *lpwm_base_init_struct)
+{
+    /* Disable peripheral before config */
+    LPWM->start_con &= ~LPWMSTCON_LPWM_EN;
+
+    /* Configure mode */
+    LPWM->start_con &= ~LPWMSTCON_BREATH_MODE;
+    LPWM->start_con |= lpwm_base_init_struct->mode & LPWMSTCON_BREATH_MODE;
+
+    /* Configure period and duty of normal mode or first duty of breath mode */
+    if ((lpwm_base_init_struct->mode & LPWMSTCON_BREATH_MODE) != LPWM_MODE_NORMAL) {
+        LPWM->start_con &= ~LPWMSTCON_LPWM_DIR;
+        LPWM->start_con |= lpwm_base_init_struct->breath_start_dir & LPWMSTCON_LPWM_DIR;
+
+        LPWM->cnt_max_con &= ~LPWMCMCON_BRT_CNTMAX;
+        LPWM->cnt_max_con |= (lpwm_base_init_struct->period * LPWMCMCON_BRT_CNTMAX_0) & LPWMCMCON_BRT_CNTMAX;
+
+        LPWM->start_con &= ~LPWMSTCON_ST_DUTY;
+        LPWM->start_con |= (lpwm_base_init_struct->first_duty * LPWMSTCON_ST_DUTY_0) & LPWMSTCON_ST_DUTY;
+    } else {
+        LPWM->cnt_max_con &= ~LPWMCMCON_SWT_CNTMAX;
+        LPWM->cnt_max_con |= (lpwm_base_init_struct->period * LPWMCMCON_SWT_CNTMAX_0) & LPWMCMCON_SWT_CNTMAX;
+
+        LPWM->switch_con &= ~LPWMSWCON_DUTY_ON;
+        LPWM->switch_con |= (lpwm_base_init_struct->first_duty * LPWMSWCON_DUTY_ON_0) & LPWMSWCON_DUTY_ON;
+    }
+}
+
+/**
+ * @brief  De-initialize the specified LPWM peripheral.
+ * @retval None
+ */
+void lpwm_deinit(void)
+{
+    u8 i;
+    volatile uint32_t *lpwm_con_base = &(LPWM->stageA_con);
+
+    for (i = 0; i < 6; i++) {
+        lpwm_con_base[i] &= ~LPWMxCON_EN;
+    }
+
+    LPWM->stageHL_con &= ~(LPWMHLCON_L_EN | LPWMHLCON_H_EN);
+
+    LPWM->start_con = 0;
+
+    clk_gate1_cmd(CLK_GATE1_LPWM, CLK_EN);
+}
+
+/**
+ * @brief  Configure the LPWM stage that needs to be enabled or disabled.
+ * @param  stage: the stage that need to config.
+ * @param  stage_init_struct: pointer to a lpwm_stage_init_typedef structure that
+ *         contains the configuration information for the specified LPWM peripheral.
+ * @param  state: state of the stage of LPWM peripheral.
+ *         This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void lpwm_stage_config(LPWM_STAGE_TYPEDEF stage, lpwm_stage_init_typedef *stage_init_struct, FUNCTIONAL_STATE state)
+{
+    uint8_t i;
+    volatile uint32_t *lpwm_con_base = &(LPWM->stageA_con);
+
+    /* Configure A..F LPWM stage register */
+    for (i = 0; i < 6; i++) {
+        if (stage & (1 << i)) {
+            if (state != DISABLE) {
+                lpwm_con_base[i] &= ~LPWMxCON_EN;
+
+                lpwm_con_base[i] &= ~LPWMxCON_REPEAT;
+                lpwm_con_base[i] |= (stage_init_struct->repeat * LPWMxCON_REPEAT_0) & LPWMxCON_REPEAT;
+
+                lpwm_con_base[i] &= ~LPWMxCON_STEP;
+                lpwm_con_base[i] |= (stage_init_struct->step * LPWMxCON_STEP_0) & LPWMxCON_STEP;
+
+                lpwm_con_base[i] &= ~LPWMxCON_ST_DUTY;
+                lpwm_con_base[i] |= (stage_init_struct->start_duty * LPWMxCON_ST_DUTY_0) & LPWMxCON_ST_DUTY;
+
+                lpwm_con_base[i] |= LPWMxCON_EN;
+            } else {
+                lpwm_con_base[i] &= ~LPWMxCON_EN;
+            }
+        }
+    }
+
+    /* Configure max hold time */
+    if (stage & LPWM_STAGE_L) {
+        if (state != DISABLE) {
+            LPWM->stageHL_con &= ~LPWMHLCON_L_EN;
+
+            LPWM->stageHL_con &= ~LPWMHLCON_L_REPEAT;
+            LPWM->stageHL_con |= (stage_init_struct->repeat * LPWMHLCON_L_REPEAT_0) & LPWMHLCON_L_REPEAT;
+
+            LPWM->stageHL_con |= LPWMHLCON_L_EN;
+        } else {
+            LPWM->stageHL_con &= ~LPWMHLCON_L_EN;
+        }
+    }
+
+    /* Configure min hold time */
+    if (stage & LPWM_STAGE_H) {
+        if (state != DISABLE) {
+            LPWM->stageHL_con &= ~LPWMHLCON_H_EN;
+
+            LPWM->stageHL_con &= ~LPWMHLCON_H_REPEAT;
+            LPWM->stageHL_con |= (stage_init_struct->repeat * LPWMHLCON_H_REPEAT_0) & LPWMHLCON_H_REPEAT;
+
+            LPWM->stageHL_con |= LPWMHLCON_H_EN;
+        } else {
+            LPWM->stageHL_con &= ~LPWMHLCON_H_EN;
+        }
+    }
+}
+
+/**
+ * @brief  Enable or disable LPWM peripheral.
+ * @param  state: State of LPWM peripheral.
+ *         This parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void lpwm_cmd(FUNCTIONAL_STATE state)
+{
+    if (state != DISABLE) {
+        LPWM->start_con |= LPWMSTCON_LPWM_EN;
+    } else {
+        LPWM->start_con &= ~LPWMSTCON_LPWM_EN;
+    }
+}
+
+/**
+ * @brief  Get the LPWM flag state.
+ * @param  flag_type: specifies the flag to get.
+ * @retval state of the specified flag (SET or RESET)
+ */
+FLAG_STATE lpwm_get_flag(LPWM_FLAG_TYPEDEF flag_type)
+{
+    uint32_t pending_bit = 0;
+
+    if (flag_type & LPWM_FLAG_L_STAGE) {
+        pending_bit |= LPWMPND_LPWM_PND;
+    }
+
+    if ((LPWM->pend & pending_bit) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+ * @brief  Clear LPWM pending flag.
+ * @param  flag_type: specifies the flag to clear.
+ *         this parameter can be one of the following values:
+ *             @arg LPWM_FLAG_L_STAGE: stage L begin pending.
+ * @retval None
+ */
+void lpwm_clear_flag(LPWM_FLAG_TYPEDEF flag_type)
+{
+    uint32_t pending_bit = 0;
+
+    if (flag_type & LPWM_FLAG_L_STAGE) {
+        pending_bit |= LPWMPND_LPWM_PND;
+    }
+
+    LPWM->pend |= pending_bit;
+}

+ 78 - 0
driver/driver_lpwm.h

@@ -0,0 +1,78 @@
+/*
+ * @File name    : driver_lpwm.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-03-06
+ * @Description  : This file contains all the functions prototypes for the LPWM library.
+ * 
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_LPWM_H
+#define _DRIVER_LPWM_H
+
+#include "driver_com.h"
+
+/**
+ * @brief LPWM Pend Flag Definition
+ */
+typedef enum {
+    LPWM_FLAG_L_STAGE       = 0x01,
+} LPWM_FLAG_TYPEDEF;
+
+/**
+ * @brief LPWM Stage Select Enumeration
+ */
+typedef enum {
+    LPWM_STAGE_A            = 0x01,
+    LPWM_STAGE_B            = 0x02,
+    LPWM_STAGE_C            = 0x04,
+    LPWM_STAGE_D            = 0x08,
+    LPWM_STAGE_E            = 0x10,
+    LPWM_STAGE_F            = 0x20,
+    LPWM_STAGE_L            = 0x40,
+    LPWM_STAGE_H            = 0x80,
+} LPWM_STAGE_TYPEDEF;
+
+/**
+ * @brief LPWM Mode Select Enumeration
+ */
+typedef enum {
+    LPWM_MODE_NORMAL        = 0x00000000,
+    LPWM_MODE_BREATH        = 0x00000002,
+} LPWM_MODE_TYPEDEF;
+
+/**
+ * @brief LPWM Breath Mode Change Dir Select Enumeration
+ */
+typedef enum {
+    LPWM_DIR_INCREASE       = 0x00000000,
+    LPWM_DIR_DECREASE       = 0x00000800,
+} LPWM_DIR_TYPEDEF;
+
+/**
+ * @brief LPWM Stage Init Structure
+ */
+typedef struct {
+    uint8_t             step;
+    uint16_t            repeat;
+    uint16_t            start_duty;
+} lpwm_stage_init_typedef;
+
+/**
+ * @brief LPWM Init Structure
+ */
+typedef struct {
+    LPWM_MODE_TYPEDEF   mode;
+    LPWM_DIR_TYPEDEF    breath_start_dir;
+    uint16_t            period;
+    uint16_t            first_duty;
+} lpwm_base_init_typedef;
+
+/********************* Function used to config LPWM peripheral *********************/
+void lpwm_init(lpwm_base_init_typedef *lpwm_base_init_struct);
+void lpwm_deinit(void);
+void lpwm_stage_config(LPWM_STAGE_TYPEDEF stage, lpwm_stage_init_typedef *stage_init_struct, FUNCTIONAL_STATE state);
+void lpwm_cmd(FUNCTIONAL_STATE state);
+FLAG_STATE lpwm_get_flag(LPWM_FLAG_TYPEDEF flag_type);
+void lpwm_clear_flag(LPWM_FLAG_TYPEDEF flag_type);
+
+#endif // _DRIVER_LPWM_H

+ 176 - 0
driver/driver_qdec.c

@@ -0,0 +1,176 @@
+#include "driver_qdec.h"
+#include "driver_clk.h"
+
+volatile unsigned int pending_count = 0;
+volatile unsigned char symbol_state = 0;
+volatile int step_count = 0;
+volatile unsigned char state = 0;
+
+bool qdec_isr_flag_x = false;
+bool qdec_isr_flag_y = false;
+bool qdec_isr_flag_z = false;
+
+static void qdecx_init(void)
+{
+    QDECXCON |= BIT(2) | BIT(1);          //qdecx reserve and forward enable
+    QDECX_FILTER(40);                     //qdecx filter
+    QDECX_WKUP_ENABLE();                  //qdecx wakeup sleep enable
+    QDECX_ENABLB();                       //qdecx enable
+}
+
+static void qdecy_init(void)
+{
+    QDECYCON |= BIT(2) | BIT(1);        //qdecy reserve and forward enable
+    QDECY_FILTER(6);                    //qdecy filter
+    QDECY_WKUP_ENABLE();                //qdecy wakeup sleep enable
+    QDECY_ENABLB();                     //qdecy enable
+}
+
+static void qdecz_init(void)
+{
+    QDECZCON |= BIT(2) | BIT(1);       //qdecz reserve and forward enable
+    QDECZ_FILTER(54);                  //qdecz filter
+    QDECZ_WKUP_ENABLE();               //qdecz wakeup sleep enable
+    QDECZ_ENABLB();                    //qdecz enable
+}
+
+AT(.com_periph.qdec.isr)
+void qdec_isr(void)
+{
+if(qdec_isr_flag_x == true)
+{
+    if(QDECX_FORWARD_PENDING_GET)
+    {
+        QDECX_FORWARD_PENDING_CLEAR();
+        QDECXDATA_VALUE_GET(step_count);
+        QDECXDATA_SYMBOL_GET(symbol_state);
+        step_count <<= 20;
+        step_count >>= 20;
+        pending_count++;
+    }
+    else if(QDECX_REVERSE_PENDING_GET)
+    {
+        QDECX_REVERSE_PENDING_CLEAR();
+        QDECXDATA_VALUE_GET(step_count);
+        QDECXDATA_SYMBOL_GET(symbol_state);
+        step_count <<= 20;
+        step_count >>= 20;
+        pending_count++;
+    }
+    else if(QDECX_ERROR_PENDING_GET)
+    {
+        QDECX_ERROR_PENDING_CLEAR();
+        QDECXDATA_VALUE_GET(step_count);
+    }
+    else if(QDECX_OV_PNDING_GET)
+    {
+        QDECX_OV_PNDING_CLEAR();
+    }
+}
+
+if(qdec_isr_flag_y == true)
+{
+    if(QDECY_FORWARD_PENDING_GET)
+    {
+        QDECY_FORWARD_PENDING_CLEAR();
+        QDECYDATA_VALUE_GET(step_count);
+        QDECYDATA_SYMBOL_GET(symbol_state);
+        step_count <<= 20;
+        step_count >>= 20;
+        pending_count++;
+    }
+    else if(QDECY_REVERSE_PENDING_GET)
+    {
+        QDECY_REVERSE_PENDING_CLEAR();
+        QDECYDATA_VALUE_GET(step_count);
+        QDECYDATA_SYMBOL_GET(symbol_state);
+        step_count <<= 20;
+        step_count >>= 20;
+        pending_count++;
+    }
+    else if(QDECY_ERROR_PENDING_GET)
+    {
+        QDECY_ERROR_PENDING_CLEAR();
+        QDECYDATA_VALUE_GET(step_count);
+
+    }
+    else if(QDECY_OV_PNDING_GET)
+    {
+        QDECY_OV_PNDING_CLEAR();
+    }
+}
+
+if(qdec_isr_flag_z == true)
+{
+    if(QDECZ_FORWARD_PENDING_GET)
+    {
+        QDECZ_FORWARD_PENDING_CLEAR();
+        QDECZDATA_VALUE_GET(step_count);
+        QDECZDATA_SYMBOL_GET(symbol_state);
+        step_count <<= 20;
+        step_count >>= 20;
+        pending_count++;
+    }
+    else if(QDECZ_REVERSE_PENDING_GET)
+    {
+        QDECZ_REVERSE_PENDING_CLEAR();
+        QDECZDATA_VALUE_GET(step_count);
+        QDECZDATA_SYMBOL_GET(symbol_state);
+        step_count <<= 20;
+        step_count >>= 20;
+        pending_count++;
+    }
+    else if(QDECZ_ERROR_PENDING_GET)
+    {
+        QDECZ_ERROR_PENDING_CLEAR();
+        QDECZDATA_VALUE_GET(step_count);
+
+    }
+    else if(QDECZ_OV_PNDING_GET)
+    {
+        QDECZ_OV_PNDING_CLEAR();
+    }
+}
+
+}
+
+void qdec_init(qdec_init_typedef *qdec_cfg)
+{
+    printf("enter to test_qdec\n");
+
+    qdec_init_typedef *config = qdec_cfg;
+
+    if(config){
+
+        CLKCON1 |= BIT(8);    //xosc or rtc
+
+        if(qdec_cfg->qdec_asis_sel == QDEC_X_AXIS)                                 // sel qdec_x_axis
+        {
+            clk_gate1_cmd(CLK_GATE1_QDECX, CLK_EN);                                //qdecx_clken
+            QDECXCON |= ((qdec_cfg->qdec_cm_sel) << 12);
+            QDECXCON |= ((qdec_cfg->number_samples_sel) << 16);
+            qdec_isr_flag_x = true;
+
+            qdecx_init();
+        }
+        else if(qdec_cfg->qdec_asis_sel == QDEC_Y_AXIS)                            //sel qdec_y_axis
+        {
+            clk_gate1_cmd(CLK_GATE1_QDECY, CLK_EN);                                //qdecy_clken
+            QDECYCON |= ((qdec_cfg->qdec_cm_sel) << 12);
+            QDECYCON |= ((qdec_cfg->number_samples_sel) << 16);
+            qdec_isr_flag_y = true;
+
+            qdecy_init();
+        }
+        else if(qdec_cfg->qdec_asis_sel == QDEC_Z_AXIS)                            ////sel qdec_z_axis
+        {
+            clk_gate1_cmd(CLK_GATE1_QDEC, CLK_EN);                                 //qdecz_clken
+            QDECZCON |= ((qdec_cfg->qdec_cm_sel) << 12);
+            QDECZCON |= ((qdec_cfg->number_samples_sel) << 16);
+            qdec_isr_flag_z = true;
+
+            qdecz_init();
+        }
+        sys_irq_init(IRQn_IR_QDEC_LEDC, 0, qdec_isr);
+    }
+}

+ 171 - 0
driver/driver_qdec.h

@@ -0,0 +1,171 @@
+#ifndef __DRIVER_QDEC_H__
+#define __DRIVER_QDEC_H__
+
+#include "driver_com.h"
+
+//int qdec_init(void);
+
+#define QDECX_DISABLE()                    (QDECXCON &= ~(0x1))
+#define QDECY_DISABLE()                    (QDECYCON &= ~(0x1))
+#define QDECZ_DISABLE()                    (QDECZCON &= ~(0x1))
+#define QDECX_ENABLB()                     (QDECXCON |= 0x1)
+#define QDECY_ENABLB()                     (QDECYCON |= 0x1)
+#define QDECZ_ENABLB()                     (QDECZCON |= 0x1)
+
+#define QDECX_INTERRUPT_REVERSE_ENABLE()   (QDECXCON |= 1 << 2)
+#define QDECX_INTERRUPT_REVERSE_DISABLE()  (QDECXCON &= ~(1 << 2))
+#define QDECY_INTERRUPT_REVERSE_ENABLE()   (QDECYCON |= 1 << 2)
+#define QDECY_INTERRUPT_REVERSE_DISABLE()  (QDECYCON &= ~(1 << 2))
+#define QDECZ_INTERRUPT_REVERSE_ENABLE()   (QDECZCON |= 1 << 2)
+#define QDECZ_INTERRUPT_REVERSE_DISABLE()  (QDECZCON &= ~(1 << 2))
+
+#define QDECX_INTERRUPT_FORWARD_ENABLE()   (QDECXCON |= 1 << 1)
+#define QDECX_INTERRUPT_FORWARD_DISABLE()  (QDECXCON &= ~(1 << 1))
+#define QDECY_INTERRUPT_FORWARD_ENABLE()   (QDECYCON |= 1 << 1)
+#define QDECY_INTERRUPT_FORWARD_DISABLE()  (QDECYCON &= ~(1 << 1))
+#define QDECZ_INTERRUPT_FORWARD_ENABLE()   (QDECZCON |= 1 << 1)
+#define QDECZ_INTERRUPT_FORWARD_DISABLE()  (QDECZCON &= ~(1 << 1))
+
+#define QDECX_INTERRUPT_SMPIE_ENABLE     (QDECXCON |= 1 << 3)
+#define QDECX_INTERRUPT_SMPIE_DISABLE    (QDECXCON &= ~(1 << 3))
+#define QDECY_INTERRUPT_SMPIE_ENABLE     (QDECYCON |= 1 << 3)
+#define QDECY_INTERRUPT_SMPIE_DISABLE    (QDECYCON &= ~(1 << 3))
+#define QDECZ_INTERRUPT_SMPIE_ENABLE     (QDECZCON |= 1 << 3)
+#define QDECZ_INTERRUPT_SMPIE_DISABLE    (QDECZCON &= ~(1 << 3))
+
+#define QDECX_WKUP_ENABLE()                (QDECXCON |= 1 << 4)
+#define QDECX_WKUP_DISABLE()               (QDECXCON &= ~(1 << 4))
+#define QDECY_WKUP_ENABLE()                (QDECYCON |= 1 << 4)
+#define QDECY_WKUP_DISABLE()               (QDECYCON &= ~(1 << 4))
+#define QDECZ_WKUP_ENABLE()                (QDECZCON |= 1 << 4)
+#define QDECZ_WKUP_DISABLE()               (QDECZCON &= ~(1 << 4))
+
+/*5~11BIT*/
+#define QDECX_FILTER(x)                  (QDECXCON &= ~(0x7f << 5),QDECXCON |= ((x & 0x7f) << 5))
+#define QDECY_FILTER(x)                  (QDECYCON &= ~(0x7f << 5),QDECYCON |= ((x & 0x7f) << 5))
+#define QDECZ_FILTER(x)                  (QDECZCON &= ~(0x7f << 5),QDECZCON |= ((x & 0x7f) << 5))
+#define QDECX_FILTER_CLEAR               (QDECXCON &= ~(0x7f << 5))
+#define QDECY_FILTER_CLEAR               (QDECYCON &= ~(0x7f << 5))
+#define QDECZ_FILTER_CLEAR               (QDECZCON &= ~(0x7f << 5))
+
+/*bit 12~13
+select mode cap1/2/4 edge*/
+#define QDECX_MODE_CAP1()                  (QDECXCON &= ~(3 << 12))
+#define QDECX_MODE_CAP2()                  (QDECXCON |= (2 << 12))
+#define QDECX_MODE_CAP4()                  (QDECXCON |= (3 << 12))
+#define QDECY_MODE_CAP1()                  (QDECYCON &= ~(3 << 12))
+#define QDECY_MODE_CAP2()                  (QDECYCON |= (2 << 12))
+#define QDECY_MODE_CAP4()                  (QDECYCON |= (3 << 12))
+#define QDECZ_MODE_CAP1()                  (QDECZCON &= ~(3 << 12))
+#define QDECZ_MODE_CAP2()                  (QDECZCON |= (2 << 12))
+#define QDECZ_MODE_CAP4()                  (QDECZCON |= (3 << 12))
+
+#define QDECX_ERROR_PENDING_GET          (QDECXCON & (1 << 14))
+#define QDECY_ERROR_PENDING_GET          (QDECYCON & (1 << 14))
+#define QDECZ_ERROR_PENDING_GET          (QDECZCON & (1 << 14))
+
+//#define QDECX_MODE_WHEEL                 (QDECXCON |= 1 << 15)
+//#define QDECX_MODE_NORMAL                (QDECXCON &= ~(1 << 15))
+//#define QDECY_MODE_WHEEL                 (QDECYCON |= 1 << 15)
+//#define QDECY_MODE_NORMAL                (QDECYCON &= ~(1 << 15))
+//#define QDECZ_MODE_WHEEL                 (QDECZCON |= 1 << 15)
+//#define QDECZ_MODE_NORMAL                (QDECZCON &= ~(1 << 15))
+
+#define QDECX_TIME_MODE_ENABLE           (QDECXCON |= 1 << 15)
+#define QDECX_TIME_MODE_DISABLE          (QDECXCON &= ~(1 << 15))
+#define QDECY_TIME_MODE_ENABLE           (QDECYCON |= 1 << 15)
+#define QDECY_TIME_MODE_DISABLE          (QDECYCON &= ~(1 << 15))
+#define QDECZ_TIME_MODE_ENABLE           (QDECZCON |= 1 << 15)
+#define QDECZ_TIME_MODE_DISABLE          (QDECZCON &= ~(1 << 15))
+/*bit 16~19*/
+#define QDECX_SMP(x)                     (QDECXCON |= (x & 0x0f) << 16)
+#define QDECY_SMP(x)                     (QDECYCON |= (x & 0x0f) << 16)
+#define QDECZ_SMP(x)                     (QDECZCON |= (x & 0x0f) << 16)
+
+#define QDECX_SMP_PND                    (QDECXCON & (1 << 20))
+#define QDECY_SMP_PND                    (QDECYCON & (1 << 20))
+#define QDECZ_SMP_PND                    (QDECZCON & (1 << 20))
+
+#define QDECX_OV_PNDING_GET              (QDECXCON & (1 << 21))
+#define QDECY_OV_PNDING_GET              (QDECYCON & (1 << 21))
+#define QDECZ_OV_PNDING_GET              (QDECZCON & (1 << 21))
+
+#define QDECX_DAT_CLR                    (QDECXCON |= (1 << 22))
+#define QDECY_DAT_CLR                    (QDECYCON |= (1 << 22))
+#define QDECZ_DAT_CLR                    (QDECZCON |= (1 << 22))
+
+#define QDECX_REVERSE_PENDING_GET        (QDECXCON & (1 << 31))
+#define QDECX_FORWARD_PENDING_GET        (QDECXCON & (1 << 30))
+#define QDECY_REVERSE_PENDING_GET        (QDECYCON & (1 << 31))
+#define QDECY_FORWARD_PENDING_GET        (QDECYCON & (1 << 30))
+#define QDECZ_REVERSE_PENDING_GET        (QDECZCON & (1 << 31))
+#define QDECZ_FORWARD_PENDING_GET        (QDECZCON & (1 << 30))
+
+#define QDECX_REVERSE_PENDING_CLEAR()      (QDECXCPND = 1 << 31)
+#define QDECX_FORWARD_PENDING_CLEAR()      (QDECXCPND = 1 << 30)
+//#define QDECX_REOV_PNDING_CLEAR          (QDECXCPND = 1 << 22)
+#define QDECX_OV_PNDING_CLEAR()            (QDECXCPND = 1 << 21)
+#define QDECX_SMP_PENDING_CLEAR()          (QDECXCPND = 1 << 20)
+#define QDECX_ERROR_PENDING_CLEAR()        (QDECXCPND = 1 << 14)
+#define QDECY_REVERSE_PENDING_CLEAR()      (QDECYCPND = 1 << 31)
+#define QDECY_FORWARD_PENDING_CLEAR()      (QDECYCPND = 1 << 30)
+//#define QDECY_REOV_PNDING_CLEAR          (QDECYCPND = 1 << 22)
+#define QDECY_OV_PNDING_CLEAR()            (QDECYCPND = 1 << 21)
+#define QDECY_SMP_PENDING_CLEAR            (QDECYCPND = 1 << 20)
+#define QDECY_ERROR_PENDING_CLEAR()        (QDECYCPND = 1 << 14)
+#define QDECZ_REVERSE_PENDING_CLEAR()      (QDECZCPND = 1 << 31)
+#define QDECZ_FORWARD_PENDING_CLEAR()      (QDECZCPND = 1 << 30)
+//#define QDECZ_REOV_PNDING_CLEAR          (QDECZCPND = 1 << 22)
+#define QDECZ_OV_PNDING_CLEAR()            (QDECZCPND = 1 << 21)
+#define QDECZ_SMP_PENDING_CLEAR()          (QDECZCPND = 1 << 20)
+#define QDECZ_ERROR_PENDING_CLEAR()        (QDECZCPND = 1 << 14)
+
+#define QDECXDATA_VALUE_GET(x)           (x = (QDECXDAT & 0X00000fff))
+#define QDECXDATA_SYMBOL_GET(x)          (x = ((QDECXDAT & 0x00000800) >> 11))
+#define QDECYDATA_VALUE_GET(x)           (x = (QDECYDAT & 0X00000fff))
+#define QDECYDATA_SYMBOL_GET(x)          (x = ((QDECYDAT & 0x00000800) >> 11))
+#define QDECZDATA_VALUE_GET(x)           (x = (QDECZDAT & 0X00000fff))
+#define QDECZDATA_SYMBOL_GET(x)          (x = ((QDECZDAT & 0x00000800) >> 11))
+
+#define QDECX_FROV_PNDING_CLEAR         (QDECXCPND = 1 << 21)
+#define QDECX_FROV_PNDING_GET           (QDECXCON & (1 << 21))
+
+//QDEC clk
+#define XOSCCON_DI_EN_XOSC              10
+#define XOSCCON_DI_EN_CKOUT3            26
+#define XOSCCON_DI_EN_LDO               12
+
+typedef enum{
+    QDEC_X_AXIS,
+    QDEC_Y_AXIS,
+    QDEC_Z_AXIS,
+}QDEC_AXIS_SEL;
+
+typedef struct{
+    QDEC_AXIS_SEL qdec_asis_sel;
+    u8 number_samples_sel;
+    u8 qdec_cm_sel;
+}qdec_init_typedef;
+
+
+enum{
+    QDEC_SMP_NUM_SAMPLES_64        = 0x0,
+    QDEC_SMP_NUM_SAMPLES_640       = 0x1,
+    QDEC_SMP_NUM_SAMPLES_2560      = 0x2,
+    QDEC_SMP_NUM_SAMPLES_5120      = 0x3,
+    QDEC_SMP_NUM_SAMPLES_7680      = 0x4,
+    QDEC_SMP_NUM_SAMPLES_10240     = 0x5,
+    QDEC_SMP_NUM_SAMPLES_12800     = 0x6,
+    QDEC_SMP_NUM_SAMPLES_16360     = 0x7,
+    QDEC_SMP_NUM_SAMPLES_17920     = 0x8,
+};
+
+enum{
+    QDEC_CM_1_MODE                 = 0x1,
+    QDEC_CM_2_MODE                 = 0x2,
+    QDEC_CM_4_MODE                 = 0x3
+};
+
+void qdec_init(qdec_init_typedef *qdec_cfg);
+
+#endif // __DRIVER_QDEC_H__

+ 191 - 0
driver/driver_rtc.c

@@ -0,0 +1,191 @@
+/*
+ * @File name    : driver_rtc.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-15
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the RTC Base peripheral.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_rtc.h"
+
+/**
+  * @brief  Set the RTC counter register value.
+  * @param  cnt: specifies the counter register new value.
+  * @retval None
+  */
+AT(.com_periph.rtc.cnt_set)
+void rtc_set_counter(uint32_t cnt)
+{
+    RTCCNT = (uint32_t)cnt;
+}
+
+/**
+  * @brief  Get the RTC counter register value.
+  * @param  None
+  * @retval specifies the counter register value.
+  */
+AT(.com_periph.rtc.cnt_get)
+uint32_t rtc_get_counter(void)
+{
+    return (uint32_t)RTCCNT;
+}
+
+/**
+  * @brief  Set the RTC alarm register value.
+  * @param  alm: specifies the alarm register new value. RTCALM = (real time) - 1.
+  * @retval None
+  */
+AT(.com_periph.rtc.alarm_set)
+void rtc_set_alarm(uint32_t alarm)
+{
+    RTCALM = (uint32_t)alarm;
+}
+
+/**
+  * @brief  Get the RTC alarm register value.
+  * @param  None
+  * @retval specifies the alarm register value. (real time) = RTCALM + 1.
+  */
+AT(.com_periph.rtc.alarm_get)
+uint32_t rtc_get_alarm(void)
+{
+    return (uint32_t)RTCALM;
+}
+
+/**
+ * @brief  Config predivision factor for 1Hz counter.
+ * @param  psc: Predivision factor configuration function of 1hz second counter.
+ * @retval None
+ */
+void rtc_prescale_set(uint32_t psc)
+{
+    u32 reg_1s_period_mask = 0x1ffff;
+    u32 rtccon2 = RTCCON2;
+
+    rtccon2 &= ~reg_1s_period_mask;
+    rtccon2 |= psc & reg_1s_period_mask;;
+    RTCCON2 = rtccon2;
+}
+
+/**
+ * @brief  Get the RTC counter 1Hz prescale value.
+ * @retval the prescale value.
+ */
+uint32_t rtc_prescale_get(void)
+{
+    return RTCCON2 & 0x1ffff;
+}
+
+/**
+  * @brief  Enable or disable the RTC interrupt.
+  * @param  isr: Function to be executed for service interruption.
+  * @param  pr: Priority of service interruption.
+  * @param  interrupt_type: specifies the RTC interrupt sources to be enable or disable.
+  *         this parameter can be one of the following values:
+  *             @arg RTC_IT_ALM: RTC alarm interrupt enable bit.
+  *             @arg RTC_IT_1S: RTC 1S interrupt enable bit.
+  * @param  state: the state of the RTC peripheral.
+  *         this parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void rtc_pic_config(isr_t isr, int pr, RTC_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state)
+{
+    uint32_t interrupt_bit = 0;
+
+    if (interrupt_type == 0) {
+        return;
+    }
+
+    if (interrupt_type & RTC_IT_ALM) {
+        interrupt_bit |= RTCCON_ALMIE;
+    }
+
+    if (interrupt_type & RTC_IT_1S) {
+        interrupt_bit |= RTCCON_RTC1SIE;
+    }
+
+    if (state != DISABLE) {
+        RTCCON |= interrupt_bit;
+        sys_irq_init(IRQn_RTC_SECOND_ALARM_LVD_WDT, pr, isr);
+        if (interrupt_type & RTC_IT_1S){
+            RTCCON11 |= RTCCON11_RTCWKSLPEN;
+        }
+    } else {
+        RTCCON &= ~interrupt_bit;
+        if (interrupt_type & RTC_IT_1S){
+            RTCCON11 &= ~RTCCON11_RTCWKSLPEN;
+        }
+    }
+}
+
+/**
+  * @brief  Get the RTC interrupt pending.
+  * @param  interrupt_type: specifies the flag to get.
+  *         this parameter can be one of the following values:
+  *             @arg RTC_IT_1S: RTC 1S interrupt pending bit.
+  *             @arg RTC_IT_ALM: RTC alarm interrupt pending bit.
+  * @retval The state of rtc_flag (SET or RESET).
+  */
+AT(.com_periph.rct.get)
+FLAG_STATE rtc_get_flag(RTC_IT_TYPEDEF interrupt_type)
+{
+    uint32_t interrupt_bit = 0;
+
+    if (interrupt_type & RTC_IT_ALM) {
+        interrupt_bit |= RTCCON_ALMPND;
+    }
+
+    if (interrupt_type & RTC_IT_1S) {
+        interrupt_bit |= RTCCON_RTCWKSLPPND;
+    }
+
+    if ((RTCCON & interrupt_bit) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+  * @brief  Clear the RTC interrupt pending.
+  * @param  rtc_flag: specifies the flag to clear.
+  *         this parameter can be one of the following values:
+  *             @arg RTC_FLAG_1S: RTC 1S interrupt pending bit.
+  *             @arg RTC_FLAG_ALM: RTC alarm interrupt pending bit.
+  * @retval None
+  */
+AT(.com_periph.rct.clear)
+void rtc_clear_flag(RTC_IT_TYPEDEF interrupt_type)
+{
+    uint32_t interrupt_bit = 0;
+
+    if (interrupt_type & RTC_IT_ALM) {
+        interrupt_bit |= RTCCON_ALMPND;
+    }
+
+    if (interrupt_type & RTC_IT_1S) {
+        interrupt_bit |= RTCCON_RTCWKSLPPND;
+    }
+
+    RTCCPND |= (uint32_t)interrupt_bit;
+}
+
+/**
+  * @brief  Get the RTC count overflow flag.
+  * @param  interrupt_type: specifies the flag to get.
+  *         this parameter can be one of the following values:
+  *             @arg RTC_IT_ALM: RTC alarm interrupt pending bit.
+  * @retval The state of rtc_flag (SET or RESET).
+  */
+AT(.com_periph.rct.get)
+FLAG_STATE rtc_get_overflow_flag(RTC_IT_TYPEDEF interrupt_type)
+{
+    if (interrupt_type & RTC_IT_ALM) {
+        if (RTCCNT >= RTCALM) {
+            return SET;
+        }
+    }
+
+    return RESET;
+}

+ 35 - 0
driver/driver_rtc.h

@@ -0,0 +1,35 @@
+/*
+ * @File name    : driver_rtc.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-15
+ * @Description  : This file contains all the functions prototypes for the RTC Base library.
+ * 
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_RTC_H
+#define _DRIVER_RTC_H
+
+#include "driver_com.h"
+
+/**
+ * @brief RTC IT and Flag Definition
+ */
+typedef enum {
+    RTC_IT_ALM              = 0x01,
+    RTC_IT_1S               = 0x02,
+} RTC_IT_TYPEDEF;
+
+//--------------- Function used to configure or get get time ---------------//
+void rtc_set_counter(uint32_t cnt);
+uint32_t rtc_get_counter(void);
+void rtc_set_alarm(uint32_t alarm);
+uint32_t rtc_get_alarm(void);
+//------------- Function used to configure clock or interrupt --------------//
+void rtc_prescale_set(uint32_t psc);
+uint32_t rtc_prescale_get(void);
+void rtc_pic_config(isr_t isr, int pr, RTC_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state);
+FLAG_STATE rtc_get_flag(RTC_IT_TYPEDEF interrupt_type);
+void rtc_clear_flag(RTC_IT_TYPEDEF interrupt_type);
+FLAG_STATE rtc_get_overflow_flag(RTC_IT_TYPEDEF interrupt_type);
+
+#endif // _DRIVER_RTC_H

+ 354 - 0
driver/driver_saradc.c

@@ -0,0 +1,354 @@
+/*
+ * @File name    : driver_saradc.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-15
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the SARADC peripheral.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_saradc.h"
+
+
+/**
+ * @brief  This function is used to resolve bugs in the current version.
+ *         we will delete this function when the bugs are fixed in the future.
+ * @param  channel: the adc channel that need to patch.
+ * @retval None
+ */
+static void saradc_patch(uint32_t channel)
+{
+    /* Disable auto_analog_io */
+    SARADC->con &= ~BIT(18);
+    /* Set GPIO to Analog */
+    GPIOA_REG->de &= ~((channel & 0x3f) << 2);
+    GPIOB_REG->de &= ~((channel & 0xc0) >> 6);
+    GPIOB_REG->de &= ~((channel & 0x0300) >> 5);
+    GPIOB_REG->de &= ~((channel & 0x0400) >> 2);
+}
+
+
+/**
+ * @brief  Initializes the saradc peripheral according to the specified
+ *         parameters in the saradc_base_init_struct.
+ * @param  saradc_base_init_struct: pointer to a sadc_init_typedef structure that
+ *         contains the configuration information for the specified SARADC peripheral.
+ * @retval None
+ */
+void saradc_init(saradc_base_init_typedef* saradc_base_init_struct)
+{
+    u16 baud_reg;
+    u32 saradc_clk;
+
+    saradc_clk = clk_saradc_clk_get(CLK_VALUE_MODE_FREQ);
+
+    /* Configure Baud Register */
+    baud_reg = (saradc_clk / (2 * saradc_base_init_struct->baud - 1)) & 0x3ff;
+    SARADC->baud = baud_reg;
+
+    /* Configure SARADC Mode */
+    SARADC->con &= ~SADCCON_ADCMODE;
+    SARADC->con |=  saradc_base_init_struct->mode & SADCCON_ADCMODE;
+
+    /* Configure SARADC auto enable analog enable bit */
+    SARADC->con &= ~SADCCON_ADCAEN;
+    SARADC->con |= saradc_base_init_struct->auto_analog & SADCCON_ADCAEN;
+
+    /* Configure SARADC auto enable analog IO enable bit */
+    SARADC->con &= ~SADCCON_ADCANGIOEN;
+    SARADC->con |= saradc_base_init_struct->auto_analog_io & SADCCON_ADCANGIOEN;
+}
+
+/**
+ * @brief  Config saradc specified channel.
+ * @param  saradc_channel_init_struct: the struct including the info of specified channel.
+ * @retval None
+ */
+void saradc_channel_init(saradc_channel_init_typedef *saradc_channel_init_struct)
+{
+    u8 i = 0;
+
+    /* Battery channel config */
+    if (saradc_channel_init_struct->channel & ADC_CHANNEL_VBAT) {
+        PWRCON0  |= (uint32_t)(1 << 10);        // VBATDIV2 ADC enable
+    }
+
+    /* Bandgap channel config */
+    if (saradc_channel_init_struct->channel & ADC_CHANNEL_BG) {
+        PWRCON0  |= (uint32_t)(1 << 22);        // BG output ADC enable
+    }
+
+    /* PWRKEY channel config */
+    if (saradc_channel_init_struct->channel & ADC_CHANNEL_WK0) {
+        RTCCON1 |= (uint32_t)(1 << 5);          // WK0 output ADC enable
+        if (RTCCON1 & BIT(1)) {                 // Sure this bit is enable,
+            RTCCON11 |= BIT(4);                 // and recommends it is enabled normally.
+        }
+    }
+
+    /* VDDRTC channel config */
+    if (saradc_channel_init_struct->channel & ADC_CHANNEL_VRTC) {
+        RTCCON1 |= (uint32_t)(1 << 7);          // VRTC output ADC enable
+    }
+
+    /* VUSB channel config */
+    if (saradc_channel_init_struct->channel & ADC_CHANNEL_VUSB) {
+        RTCCON8 |= (uint32_t)(1 << 15);         // VUSB output ADC enable
+        PWRCON2 &= ~(uint32_t)(0x03 << 5);      // TSEN disable
+        AUANGCON0 |= BIT(8);                    // MICLDO bypass AVDD enable
+    /* TSEN channel config */
+    } else if (saradc_channel_init_struct->channel & ADC_CHANNEL_TSEN) {
+        RTCCON8 &= ~(uint32_t)(1 << 15);
+        PWRCON2 |= (uint32_t)(0x03 << 5);
+        saradc_channel_init_struct->channel &= ~ADC_CHANNEL_TSEN;
+        saradc_channel_init_struct->channel |= ADC_CHANNEL_VUSB;
+    }
+
+    /* Configure each channel */
+    for (i = 0; i < 16; i++) {
+        if (saradc_channel_init_struct->channel & (0x01 << i)) {
+            SARADC->cst &= ~(0x03 << (i * 2));
+            SARADC->cst |= (saradc_channel_init_struct->setup_time) << (i * 2);
+
+            SARADC->con &= ~(0x01 << i);
+            SARADC->con |= (saradc_channel_init_struct->pullup_en & 0x01) << i;
+
+            if (saradc_channel_init_struct->interrupt_en != DISABLE) {
+                SARADC->ch_int |= (0x01 << i);
+            } else {
+                SARADC->ch_int &= ~(0x01 << i);
+            }
+        }
+    }
+
+    saradc_patch(saradc_channel_init_struct->channel);
+}
+
+/**
+ * @brief  Deinit all channel config.
+ * @retval the enumeration of channels that has enable.
+ */
+uint8_t saradc_deinit(void)
+{
+    uint8_t saradc_analog_bits = 0;
+
+    /* Battery channel config */
+    if (PWRCON0 & (uint32_t)(1 << 10)) {
+        PWRCON0 &= ~((uint32_t)(1 << 10));
+        saradc_analog_bits |= SARADC_ANALOG_BIT_VBAT;
+    }
+
+    /* Bandgap channel config */
+    if (PWRCON0 & (uint32_t)(1 << 22)) {
+        PWRCON0 &= ~((uint32_t)(1 << 22));
+        saradc_analog_bits |= SARADC_ANALOG_BIT_BG;
+    }
+
+    /* PWRKEY channel config */
+    if (RTCCON1 & (uint32_t)(1 << 5)) {
+        RTCCON1 &= ~((uint32_t)(1 << 5));
+        saradc_analog_bits |= SARADC_ANALOG_BIT_WK0;
+    }
+
+    /* VDDRTC channel config */
+    if (RTCCON1 & (uint32_t)(1 << 7)) {
+        RTCCON1 &= ~((uint32_t)(1 << 7));
+        saradc_analog_bits |= SARADC_ANALOG_BIT_VRTC;
+    }
+
+    /* VUSB channel config */
+    if (RTCCON8 & (uint32_t)(1 << 15)) {
+        RTCCON8 &= ~((uint32_t)(1 << 15));
+        saradc_analog_bits |= SARADC_ANALOG_BIT_VUSB;
+    }
+
+    /* TSEN channel config */
+    if (PWRCON2 & (0x03 << 5)) {
+        PWRCON2 &= ~(0x03 << 5);
+        saradc_analog_bits |= ADC_CHANNEL_TSEN;
+    }
+
+    /* Clear saradc register config */
+    SARADC->con = 0;
+    SARADC->ch = 0;
+
+    /* Disable SARADC clock */
+    clk_gate0_cmd(CLK_GATE0_SARADC, CLK_DIS);
+
+    return saradc_analog_bits;
+}
+
+/**
+  * @brief  Enable or disable the specified SARADC peripheral.
+  * @param  state: state of the SARADC peripheral.
+            This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void saradc_cmd(FUNCTIONAL_STATE state)
+{
+    if(state) {
+        SARADC->con |= SADCCON_ADCEN;
+    } else {
+        SARADC->con &= (uint32_t)~SADCCON_ADCEN;
+    }
+}
+
+/**
+  * @brief  SARADC start kick.
+  * @param  adc_ch: the adc channels.
+  * @retval None
+  */
+AT(.com_periph.saradc.kick)
+void saradc_kick_start(uint32_t adc_ch)
+{
+    if (!adc_ch) {
+        return;
+    }
+
+    if (adc_ch & ADC_CHANNEL_TSEN) {
+        adc_ch &= ~ADC_CHANNEL_TSEN;
+        adc_ch |= ADC_CHANNEL_VUSB;
+    }
+
+    while(SARADC->ch & 0xffff);
+
+    SARADC->ch = (adc_ch & 0xffff);
+}
+
+/**
+  * @brief  Set the SARADC baud register value.
+  * @param  baud: specifies the baud register new value.
+  * @retval None
+  */
+void saradc_set_baud(uint32_t baud)
+{
+    u16 baud_reg;
+    u32 saradc_clk;
+
+    saradc_clk = clk_saradc_clk_get(CLK_VALUE_MODE_FREQ);
+
+    /* Configure Baud Register */
+    baud_reg = (saradc_clk / (2 * baud - 1)) & 0x3ff;
+    SARADC->baud = baud_reg;
+}
+
+/**
+ * @brief  Enable or disable the specified SARADC interrupt.
+ * @param  isr: Function to be executed for service interruption.
+ * @param  pr: Priority of service interruption.
+ * @param  interrupt_type: specifies the SARADC interrupt sources to be enable or disable.
+ *         this parameter can be one of the following values:
+ *             @arg SARADC_IT_FINISHED: All channel finished flag.
+ * @param  state: state of the SARADC peripheral.
+ *         this parameter can be: EANBLE or DISABLE.
+ * @retval None
+ */
+void saradc_pic_config(isr_t isr, int pr, SARADC_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state)
+{
+    uint32_t interrupt_bit = 0;
+
+    /* Get interrupt ctrl bit */
+    if (interrupt_type & SARADC_IT_FINISHED) {
+        interrupt_bit |= SADCCON_ADCIE;
+    }
+
+    if(state != DISABLE) {
+        SARADC->con |= interrupt_bit;
+        sys_irq_init(IRQn_SARADC, pr, isr);
+    } else {
+        SARADC->con &= ~interrupt_bit;
+        PICEN &= ~BIT(IRQn_SARADC);
+    }
+}
+
+/**
+ * @brief  Get the SARADC interrupt pending.
+ * @param  interrupt_type: specifies the IT to get.
+ *         this parameter can be on of the following values:
+ *             @arg SARADC_IT_FINISHED: SARADC all channel finished interrupt.
+ * @retval The state of interrupt_type (SET or RESET).
+ */
+AT(.com_periph.saradc.get)
+FLAG_STATE saradc_get_flag(SARADC_IT_TYPEDEF interrupt_type)
+{
+    uint32_t flag_bit = 0;
+
+    if (interrupt_type & SARADC_IT_FINISHED) {
+        flag_bit |= (0x01 << 16);
+    }
+
+    if ((SARADC->ch & flag_bit) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+  * @brief  Get the SARADC specifies channel finished statue.
+  * @param  adc_ch: the channel that wants to query.
+  * @retval The state of adc_ch finish (SET or RESET).
+  */
+AT(.com_periph.saradc.get_channel)
+FLAG_STATE saradc_get_channel_flag(uint32_t adc_ch)
+{
+    if (adc_ch & ADC_CHANNEL_TSEN) {
+        adc_ch &= ~ADC_CHANNEL_TSEN;
+        adc_ch |= ADC_CHANNEL_VUSB;
+    }
+
+    if (((SARADC->ch) & adc_ch) != RESET) {
+        return RESET;
+    } else {
+        return SET;
+    }
+}
+
+/**
+ * @brief  Clear the SARADC interrupt pending.
+ * @param  interrupt_type: specifies the IT to clear.
+ *         this parameter can be on of the following values:
+ *             @arg SARADC_IT_FINISHED: SARADC all channel finished interrupt.
+ * @retval None
+ */
+AT(.com_periph.saradc.clear)
+void saradc_clear_flag(SARADC_IT_TYPEDEF interrupt_type)
+{
+    uint32_t flag_bit = 0;
+
+    if (interrupt_type & SARADC_IT_FINISHED) {
+        flag_bit |= (0x01 << 16);
+    }
+
+    SARADC->ch |= flag_bit;
+}
+
+/**
+  * @brief  Get the SARADC specifies channel value.
+  * @param  adc_chx: the channel that wants to query.
+  * @retval saradc data.
+  */
+AT(.com_periph.saradc.get_data)
+uint32_t saradc_get_data(uint32_t adc_chx)
+{
+    u8 i = 0;
+
+    while (i < 17) {
+        if (adc_chx & (0x01 << i)) {
+            break;
+        }
+        i++;
+    }
+
+    if ((0x01 << i) == ADC_CHANNEL_VBAT) {
+        return SARADC->dat[i] * pmu_get_vbatdet() / 1000;
+    } else if ((0x01 << i) == ADC_CHANNEL_VUSB) {
+        return SARADC->dat[i] * 3;
+    } else if ((0x01 << i) == ADC_CHANNEL_TSEN) {
+        return SARADC->dat[15];
+    } else if (i < 16) {
+        return SARADC->dat[i];
+    } else {
+        return 0;
+    }
+}

+ 127 - 0
driver/driver_saradc.h

@@ -0,0 +1,127 @@
+/*
+ * @File name    : driver_saradc.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-15
+ * @Description  : This file contains all the functions prototypes for the SARADC library.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_SARADC_H
+#define _DRIVER_SARADC_H
+
+#include "driver_com.h"
+
+/**
+ * @brief ADC Channel
+ */
+#define ADC_CHANNEL_PA2                 0x00000001  // channel 0
+#define ADC_CHANNEL_PA3                 0x00000002  // channel 1
+#define ADC_CHANNEL_PA4                 0x00000004  // channel 2
+#define ADC_CHANNEL_PA5                 0x00000008  // channel 3
+#define ADC_CHANNEL_PA6                 0x00000010  // channel 4
+#define ADC_CHANNEL_PA7                 0x00000020  // channel 5
+#define ADC_CHANNEL_PB0                 0x00000040  // channel 6
+#define ADC_CHANNEL_PB1                 0x00000080  // channel 7
+#define ADC_CHANNEL_PB3                 0x00000100  // channel 8
+#define ADC_CHANNEL_PB4                 0x00000200  // channel 9
+#define ADC_CHANNEL_PB8                 0x00000400  // channel 10
+#define ADC_CHANNEL_VRTC                0x00000800  // channel 11
+#define ADC_CHANNEL_WK0                 0x00001000  // channel 12
+#define ADC_CHANNEL_BG                  0x00002000  // channel 13, please do not use this channel, abandon, can use VRTC channel
+#define ADC_CHANNEL_VBAT                0x00004000  // channel 14
+#define ADC_CHANNEL_VUSB                0x00008000  // channel 15
+#define ADC_CHANNEL_TSEN                0x00010000  // channel 15'
+
+/**
+ * @brief SARADC ANALOG BIT
+ */
+typedef enum {
+    SARADC_ANALOG_BIT_VBAT      = 0x01,
+    SARADC_ANALOG_BIT_BG        = 0x02,
+    SARADC_ANALOG_BIT_WK0       = 0x04 ,
+    SARADC_ANALOG_BIT_VRTC      = 0x08,
+    SARADC_ANALOG_BIT_VUSB      = 0x10,
+} SARADC_ANALOG_BIT_TYPEDEF;
+
+/**
+ * @brief SARADC Flag Definition
+ */
+typedef enum {
+    SARADC_IT_FINISHED                  = 0x01,
+} SARADC_IT_TYPEDEF;
+
+/**
+ * @brief SARADC Analog Mode Enumeration
+ */
+typedef enum {
+    SARADC_MODE_NORMAL                  = 0x00000000,
+    SARADC_MODE_TRIM                    = 0x00100000,
+} SARADC_MODE_TYPEDEF;
+
+/**
+ * @brief SARADC Auto Enable Analog Enumeration
+ */
+typedef enum {
+    SARADC_AUTO_ENABLE_ANALOG_DIS       = 0x00000000,
+    SARADC_AUTO_ENABLE_ANALOG_EN        = 0x00080000,
+} SARADC_AUTO_ENABLE_ANALOG_TYPEDEF;
+
+/**
+ * @brief SARADC Auto Enable IO Analog Enumeration
+ */
+typedef enum {
+    SARADC_AUTO_ENABLE_ANALOG_IO_DIS    = 0x00000000,
+    SARADC_AUTO_ENABLE_ANALOG_IO_EN     = 0x00040000,
+} SARADC_AUTO_ENABLE_ANALOG_IO_TYPEDEF;
+
+/**
+ * @brief SARADC Internel Pullup Enumeration
+ */
+typedef enum {
+    SARADC_PULLUP_DIS                   = 0x00000000,
+    SARADC_PULLUP_EN                    = 0x00000001,
+} SARADC_PULLUP_TYPEDEF;
+
+/**
+ * @brief SARADC setup timing enumeration
+ */
+typedef enum {
+    SARADC_ST_0_CLK                     = 0x00000000,
+    SARADC_ST_2_CLK                     = 0x00000001,
+    SARADC_ST_4_CLK                     = 0x00000010,
+    SARADC_ST_8_CLK                     = 0x00000011,
+} SARADC_SETUP_TYPEDEF;
+
+/**
+ * @brief SARADC Base Init Structure
+ */
+typedef struct {
+    uint32_t                                baud;
+    SARADC_MODE_TYPEDEF                     mode;
+    SARADC_AUTO_ENABLE_ANALOG_TYPEDEF       auto_analog;
+    SARADC_AUTO_ENABLE_ANALOG_IO_TYPEDEF    auto_analog_io;
+} saradc_base_init_typedef;
+
+/**
+ * @brief SARADC Channel Init structure
+ */
+typedef struct {
+    uint32_t                                channel;
+    FUNCTIONAL_STATE                        interrupt_en;
+    SARADC_PULLUP_TYPEDEF                   pullup_en;
+    SARADC_SETUP_TYPEDEF                    setup_time;
+} saradc_channel_init_typedef;
+
+void saradc_init(saradc_base_init_typedef* saradc_init_struct);
+uint8_t saradc_deinit(void);
+void saradc_channel_init(saradc_channel_init_typedef *saradc_channel_init_struct);
+void saradc_cmd(FUNCTIONAL_STATE state);
+void saradc_kick_start(uint32_t adc_ch);
+void saradc_set_baud(uint32_t baud);
+void saradc_pic_config(isr_t isr, int pr, SARADC_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state);
+FLAG_STATE saradc_get_flag(SARADC_IT_TYPEDEF interrupt_type);
+FLAG_STATE saradc_get_channel_flag(uint32_t adc_ch);
+void saradc_clear_flag(SARADC_IT_TYPEDEF interrupt_type);
+uint32_t saradc_get_data(uint32_t adc_chx);
+
+#endif  // _DRIVER_SARADC_H

+ 284 - 0
driver/driver_sdadc.c

@@ -0,0 +1,284 @@
+/*
+ * @File name    : driver_sdadc.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-07-03
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the SDADC peripheral.
+ * 
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_sdadc.h"
+#include "driver_clk.h"
+
+/**
+ * @brief  Initializes the sdadc peripheral according to the specified
+ *         parameters in the sdadc_init_struct.
+ * @param  sdadc_init_struct: pointer to a sdadc_init_typedef structure that
+ *         contains the configuration information for the specified SDADC peripheral.
+ * @retval None
+ */
+void sdadc_init(sdadc_init_typedef *sdadc_init_struct)
+{
+    /* Config sampling rate */
+    SDADC->con &= ~SDADC_CON_FSOUT_SEL;
+    SDADC->con |= sdadc_init_struct->sample_rate & SDADC_CON_FSOUT_SEL;
+
+    /* Config MIC analog register */
+    mic_adc_init(sdadc_init_struct->mic_analog_cfg);
+    
+    /* Config sw_sub dc status */
+    if (sdadc_init_struct->subtract_soft_dc_en != DISABLE) {
+        SDADC->con |= SDADC_CON_SW_DC_EN;
+    } else {
+        SDADC->con &= ~SDADC_CON_SW_DC_EN;
+    }
+
+    /* Config getdc status */
+    if (sdadc_init_struct->get_dc_en != DISABLE) {
+        SDADC->con |= SDADC_CON_GETDC_EN;
+    } else {
+        SDADC->con &= ~SDADC_CON_GETDC_EN;
+    }
+
+    /* Config remove dc status */
+    if (sdadc_init_struct->remove_dc_en != DISABLE) {
+        SDADC->con |= SDADC_CON_RMDC_EN;
+    } else {
+        SDADC->con &= ~SDADC_CON_RMDC_EN;
+    }
+
+    /* Config gain status */
+    if (sdadc_init_struct->dig_gain_en != DISABLE) {
+        SDADC->con |= SDADC_CON_GAIN_EN;
+    } else {
+        SDADC->con &= ~SDADC_CON_GAIN_EN;
+    }
+}
+
+/**
+ * @brief  De-initialize the specified SDADC peripheral.
+ * @retval None
+ */
+void sdadc_deinit(void)
+{    
+    SDADC->con &= ~(SDADC_CON_SW_DC_EN | \
+                    SDADC_CON_GETDC_EN | \
+                    SDADC_CON_RMDC_EN | \
+                    SDADC_CON_GAIN_EN | \
+                    SDADC_CON_ADC_EN);
+
+    SDADC->dma_con &= ~SDADC_DMACON_DMA_EN;
+    
+    mic_adc_deinit();
+
+    clk_gate0_cmd(CLK_GATE0_SDADCL, CLK_DIS);
+}
+
+/**
+ * @brief  Enable or disable the specified SDADC peripheral.
+ * @param  state: the state of the SDADC peripheral.
+ *         this parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void sdadc_cmd(FUNCTIONAL_STATE state)
+{
+    if (state != DISABLE) {
+        SDADC->con |= SDADC_CON_ADC_EN;
+    } else {
+        SDADC->con &= ~SDADC_CON_ADC_EN;
+    }
+}
+
+/**
+ * @brief  Enable or disable the SDADC DMA function.
+ * @param  addr: DMA start address.
+ * @param  len: DMA transmit len.
+ * @param  state: the new state need to config.
+ *         this parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void sdadc_dma_cmd(u32 addr, u16 len, FUNCTIONAL_STATE state)
+{
+    if (state != DISABLE) {
+        /* Config DMA address and size */
+        SDADC->dma_addr = addr;
+        SDADC->dma_size = len;
+        SDADC->dma_con |= SDADC_DMACON_DMA_EN;
+    } else {
+        SDADC->dma_con &= ~SDADC_DMACON_DMA_EN;
+    }
+}
+
+/**
+ * @brief  Enable or disable the specified SDADC interrupt.
+ * @param  isr: Function to be executed for service interruption.
+ * @param  pr: Priority of service interruption.
+ * @param  flag_type: specifies the SDADC interrupt sources to be enable or disable.
+ *         this parameter can be one of the following values:
+ *             @arg SDADC_FLAG_SINGLE_SAMPLE: Single sampling complete interrupt.
+ *             @arg SDADC_FLAG_DMA_ALL_DONE: DMA full-transfer interrupt.
+ *             @arg SDADC_FLAG_DMA_HALF_DONE: DMA half-transfer interrupt.
+ * @param  state: the state of the SDADC peripheral's interrupt.
+ *         this parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void sdadc_pic_config(isr_t isr, int pr, SDADC_FLAG_TYPEDEF flag_type, FUNCTIONAL_STATE state)
+{
+    u32 flag_pending_bit = 0;
+    u32 all_flag_mask = (SDADC_DMACON_SAMPLES_IE | SDADC_DMACON_DMA_ALLDONE_IE | SDADC_DMACON_DMA_HALFDONE_IE);
+
+    if (flag_type == 0) {
+        return;
+    }
+
+    if (flag_type & SDADC_FLAG_SINGLE_SAMPLE) {
+        flag_pending_bit |= SDADC_DMACON_SAMPLES_IE;
+    }
+
+    if (flag_type & SDADC_FLAG_DMA_ALL_DONE) {
+        flag_pending_bit |= SDADC_DMACON_DMA_ALLDONE_IE;
+    }
+
+    if (flag_type & SDADC_FLAG_DMA_HALF_DONE) {
+        flag_pending_bit |= SDADC_DMACON_DMA_HALFDONE_IE;
+    }
+
+    if (state != DISABLE) {
+        SDADC->dma_con |= flag_pending_bit;
+        sys_irq_init(IRQn_SDADC_DMA, pr, isr);
+    } else {
+        SDADC->dma_con &= ~flag_pending_bit;
+        if (flag_pending_bit & all_flag_mask) {
+            PICEN &= ~BIT(IRQn_SDADC_DMA);
+        }
+    }
+}
+
+/**
+ * @brief  Check the specified SDADC flag is set or not.
+ * @param  flag_type: specifies the flag to check.
+ *         the parameter can be one of the following values:
+ *             @arg SDADC_FLAG_SINGLE_SAMPLE: Single sampling complete interrupt.
+ *             @arg SDADC_FLAG_DMA_ALL_DONE: DMA full-transfer interrupt.
+ *             @arg SDADC_FLAG_DMA_HALF_DONE: DMA half-transfer interrupt.
+ * @retval the state of flag_type (SET or RESET).
+ */
+AT(.com_periph.sdadc.flag)
+FLAG_STATE sdadc_get_flag(SDADC_FLAG_TYPEDEF flag_type)
+{
+    u32 flag_pending_bit = 0;
+
+    if (flag_type & SDADC_FLAG_SINGLE_SAMPLE) {
+        flag_pending_bit |= SDADC_DMAPND_SAMPLEDONE;
+    }
+
+    if (flag_type & SDADC_FLAG_DMA_ALL_DONE) {
+        flag_pending_bit |= SDADC_DMAPND_ALLDONE;
+    }
+
+    if (flag_type & SDADC_FLAG_DMA_HALF_DONE) {
+        flag_pending_bit |= SDADC_DMAPND_HALFDONE;
+    }
+
+    if ((SDADC->dma_pend & flag_pending_bit) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+ * @brief  Clear the SDADC pending.
+ * @param  flag_type: specifies flag to clear.
+ *         the parameter can be one of the following values:
+ *             @arg SDADC_FLAG_SINGLE_SAMPLE: Single sampling complete interrupt.
+ *             @arg SDADC_FLAG_DMA_ALL_DONE: DMA full-transfer interrupt.
+ *             @arg SDADC_FLAG_DMA_HALF_DONE: DMA half-transfer interrupt.
+ * @retval None
+ */
+AT(.com_periph.sdadc.flag)
+void sdadc_clear_flag(SDADC_FLAG_TYPEDEF flag_type)
+{
+    u32 flag_pending_bit = 0;
+
+    if (flag_type & SDADC_FLAG_SINGLE_SAMPLE) {
+        flag_pending_bit |= SDADC_DMACPND_SAMPLEDONE_CLR;
+    }
+
+    if (flag_type & SDADC_FLAG_DMA_ALL_DONE) {
+        flag_pending_bit |= SDADC_DMACPND_ALLDONE_CLR;
+    }
+
+    if (flag_type & SDADC_FLAG_DMA_HALF_DONE) {
+        flag_pending_bit |= SDADC_DMACPND_HALFDONE_CLR;
+    }
+
+    SDADC->dma_cpnd |= flag_pending_bit;
+}
+
+/**
+ * @brief  Set digital gain function.
+ * @param  dig_gain: the value of digital gain need to set.
+ * @retval None
+ */
+void sdadc_digital_gain_set(SDADC_DIGITAL_GAIN_TYPEDEF dig_gain)
+{
+    SDADC->gain_con = dig_gain & SDADC_GAINCON_GAIN;
+}
+
+/**
+ * @brief  Set removeDC bits_len function.
+ * @param  removeDC_bits_sel: the enum value of removeDC need to set.
+ * @retval None
+ */
+void sdadc_removeDC_bits_set(SDADC_RMDC_BITS_TYPEDEF removeDC_bits_sel)
+{
+    u32 reg = SDADC->con;
+
+    reg &= ~SDADC_CON_GETDC_SEL;
+    reg |= removeDC_bits_sel & SDADC_CON_GETDC_SEL;
+
+    SDADC->con = reg;
+}
+
+/**
+ * @brief  Set getDC bits_len function.
+ * @param  getDC_bits_sel: the enum value of getDC need to set.
+ * @retval None
+ */
+void sdadc_getDC_bits_set(SDADC_GETDC_BITS_TYPEDEF getDC_bits_sel)
+{
+    u32 reg = SDADC->con;
+
+    reg &= ~SDADC_CON_RMDC_SEL;
+    reg |= getDC_bits_sel & SDADC_CON_RMDC_SEL;
+
+    SDADC->con = reg;
+}
+
+/**
+ * @brief  Get digital gain function.
+ * @retval the value of digital gain.
+ */
+uint16_t sdadc_digital_gain_get(void)
+{
+    return (SDADC->gain_con & SDADC_GAINCON_GAIN);
+}
+
+/**
+ * @brief  Get getDC bits_len function.
+ * @retval the enum value of getDC_bits.
+ */
+SDADC_GETDC_BITS_TYPEDEF sdadc_getDC_bits_get(void)
+{
+    return (SDADC->con & SDADC_CON_GETDC_SEL);
+}
+
+/**
+ * @brief  Get removeDC bits_len function.
+ * @retval the enum value of removeDC_bits.
+ */
+SDADC_RMDC_BITS_TYPEDEF sdadc_removeDC_bits_get(void)
+{
+    return (SDADC->con & SDADC_CON_RMDC_SEL);
+}

+ 96 - 0
driver/driver_sdadc.h

@@ -0,0 +1,96 @@
+/*
+ * @File name    : driver_sdadc.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-06-08
+ * @Description  : This file contains all the functions prototypes for the SDADC library.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_SDADC_H
+#define _DRIVER_SDADC_H
+
+#include "driver_com.h"
+
+
+/**
+ * @brief Flag Enumeration.
+ */
+typedef enum {
+    SDADC_FLAG_SINGLE_SAMPLE    = 0x01,
+    SDADC_FLAG_DMA_ALL_DONE     = 0x02,
+    SDADC_FLAG_DMA_HALF_DONE    = 0x04,
+} SDADC_FLAG_TYPEDEF;
+
+/**
+ * @brief Digital Gain Select Enumeration.
+ */
+typedef enum {
+    DIG_GAIN_400                = 0x0400,
+    DIG_GAIN_800                = 0x0800,
+    DIG_GAIN_1600               = 0x1600,
+    DIG_GAIN_3200               = 0x3200,
+    DIG_GAIN_4800               = 0x4800,
+    DIG_GAIN_6400               = 0x6400,
+    DIG_GAIN_8000               = 0x8000,
+} SDADC_DIGITAL_GAIN_TYPEDEF;
+
+/**
+ * @brief Sample Rate Enumeration.
+ */
+typedef enum {
+    SPR_48000                   = 0x00000000,
+    SPR_32000                   = 0x00000002,
+    SPR_24000                   = 0x00000004,
+    SPR_16000                   = 0x00000006,
+    SPR_12000                   = 0x00000008,
+    SPR_8000                    = 0x0000000a,
+} SDADC_SAMPLING_TYPEDEF;
+
+/**
+ * @brief GETDC Bits Enumeration.
+ */
+typedef enum{
+    SDADC_GETDC_BITS_13BITS     = 0x00000000,
+    SDADC_GETDC_BITS_12BITS     = 0x00000400,
+    SDADC_GETDC_BITS_11BITS     = 0x00000800,
+    SDADC_GETDC_BITS_10BITS     = 0x00000c00,
+} SDADC_GETDC_BITS_TYPEDEF;
+
+/**
+ * @brief RemoveDC Bits Enumeration.
+ */
+typedef enum{
+    SDADC_RMDC_BITS_10BITS      = 0x00000000,
+    SDADC_RMDC_BITS_9BITS       = 0x00000100,
+    SDADC_RMDC_BITS_8BITS       = 0x00000200,
+    SDADC_RMDC_BITS_7BITS       = 0x00000300,
+} SDADC_RMDC_BITS_TYPEDEF;
+
+/**
+ * @brief SDADC Initialization Struct.
+ */
+typedef struct{
+    SDADC_SAMPLING_TYPEDEF sample_rate;
+    MIC_ADC_CFG mic_analog_cfg;
+    FUNCTIONAL_STATE subtract_soft_dc_en;
+    FUNCTIONAL_STATE get_dc_en;
+    FUNCTIONAL_STATE remove_dc_en;
+    FUNCTIONAL_STATE dig_gain_en;
+} sdadc_init_typedef;
+
+
+void sdadc_init(sdadc_init_typedef *sdadc_init_struct);
+void sdadc_deinit(void);
+void sdadc_cmd(FUNCTIONAL_STATE state);
+void sdadc_dma_cmd(u32 addr, u16 len, FUNCTIONAL_STATE state);
+void sdadc_pic_config(isr_t isr, int pr, SDADC_FLAG_TYPEDEF flag_type, FUNCTIONAL_STATE state);
+FLAG_STATE sdadc_get_flag(SDADC_FLAG_TYPEDEF flag_type);
+void sdadc_clear_flag(SDADC_FLAG_TYPEDEF flag_type);
+void sdadc_digital_gain_set(SDADC_DIGITAL_GAIN_TYPEDEF dig_gain);
+void sdadc_removeDC_bits_set(SDADC_RMDC_BITS_TYPEDEF removeDC_bits_sel);
+void sdadc_getDC_bits_set(SDADC_GETDC_BITS_TYPEDEF getDC_bits_sel);
+uint16_t sdadc_digital_gain_get(void);
+SDADC_GETDC_BITS_TYPEDEF sdadc_getDC_bits_get(void);
+SDADC_RMDC_BITS_TYPEDEF sdadc_removeDC_bits_get(void);
+
+#endif

+ 133 - 0
driver/driver_sddac.c

@@ -0,0 +1,133 @@
+#include "driver_sddac.h"
+#include "driver_clk.h"
+
+/**
+ * @brief  Kick Start SDDAC DMA function.
+ * @param  buf: DMA start address.
+ * @param  size: DMA transmit len.
+ * @retval None
+ */
+AT(.com_periph.sddac.kick)
+void sddac_dma_kick_start(uint8_t *buf, uint16_t size)
+{
+    SDDAC->dma_addr = (s32)buf;
+    SDDAC->dma_size = size - 1;
+}
+
+/**
+ * @brief  Initializes the sddac peripheral according to the specified
+ *         parameters in the config
+ * @param  config: pointer to a sddac_init_typedef structure that
+ *         contains the configuration information for the specified SDDAC peripheral.
+ * @retval None
+ */
+void sddac_init(sddac_init_typedef *config)
+{
+    if(config){
+        if(config->sample_rate > SDDAC_NORMAL_SPR_8k){
+            SDDAC->con |= SDDAC_OSR_MODE;
+            config->sample_rate -= (SDDAC_NORMAL_SPR_8k + 1);
+        }else{
+            SDDAC->con &= ~SDDAC_OSR_MODE;
+        }
+        SDDAC->con &= ~SDDAC_FSIN_SEL;
+        SDDAC->con |= ((config->sample_rate * SDDAC_FSIN_SEL_0) & SDDAC_FSIN_SEL);
+        SDDAC->dma_addr = (s32)config->dma_buf;
+        SDDAC->dma_size = config->dma_size - 1;
+        SDDAC->dma_con |= SDDAC_DMA_EN;                              //dma_en
+    }
+}
+
+/**
+ * @brief  De-initialize the specified SDDAC peripheral.
+ * @retval None
+ */
+void sddac_deinit(void)
+{
+    SDDAC->dma_con &= ~SDDAC_DMA_EN;                    //dma disable
+    SDDAC->con &= ~SDDAC_DAC_EN;                        //dac disable
+
+    clk_gate0_cmd(CLK_GATE0_DAC, CLK_DIS);              //dac clk gate disable
+}
+
+/**
+ * @brief  Enable or disable the specified SDDAC interrupt.
+ * @param  isr: Function to be executed for service interruption.
+ * @param  pr: Priority of service interruption.
+ * @param  interrupt_type: specifies the SDDAC interrupt sources to be enable or disable.
+ *         this parameter can be one of the following values:
+ *             @arg SDDAC_IT_ALL_DONE: DMA full-transfer interrupt.
+ *             @arg SDDAC_IT_HALF_DONE: DMA half-transfer interrupt.
+ * @param  state: the state of the SDDAC peripheral's interrupt.
+ *         this parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+void sddac_pic_config(isr_t isr, int pr, SDDAC_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state)
+{
+    if(state == ENABLE){
+        if(interrupt_type & SDDAC_IT_ALL_DONE){
+            SDDAC->dma_con |= SDDAC_DMA_APEND_IE;
+        }
+        if(interrupt_type & SDDAC_IT_HALF_DONE){
+            SDDAC->dma_con |= SDDAC_DMA_HPEND_IE;
+        }
+        sys_irq_init(IRQn_DAC_DMAIN, pr, isr);
+    }else{
+        SDDAC->dma_con &= ~(SDDAC_DMA_APEND_IE | SDDAC_DMA_HPEND_IE);
+    }
+}
+
+/**
+ * @brief  Enable or disable the specified SDDAC peripheral.
+ * @param  state: the state of the SDDAC peripheral.
+ *         this parameter can be: ENABLE or DISABLE.
+ * @retval None
+ */
+AT(.com_periph.sddac.cmd)
+void sddac_cmd(FUNCTIONAL_STATE state)
+{
+    if(state == ENABLE){
+        SDDAC->con |= SDDAC_DMA_EN;
+    }else{
+        SDDAC->con &= ~SDDAC_DMA_EN;
+    }
+}
+
+/**
+ * @brief  Check the specified SDDAC flag is set or not.
+ * @param  interrupt_type: specifies the flag to check.
+ *         the parameter can be one of the following values:
+ *             @arg SDDAC_IT_ALL_DONE: DMA full-transfer interrupt.
+ *             @arg SDDAC_IT_HALF_DONE: DMA half-transfer interrupt.
+ * @retval the state of interrupt_type (SET or RESET).
+ */
+AT(.com_periph.sddac.get)
+FLAG_STATE sddac_get_flag(SDDAC_IT_TYPEDEF interrupt_type)
+{
+    if((interrupt_type == SDDAC_IT_ALL_DONE) && (SDDAC->dma_pend & SDDAC_DMA_ALLPEND)){
+        return SET;
+    }else if((interrupt_type == SDDAC_IT_HALF_DONE) && (SDDAC->dma_pend & SDDAC_DMA_HALFPEND)){
+        return SET;
+    }
+
+    return RESET;
+}
+
+/**
+ * @brief  Clear the SDDAC pending.
+ * @param  interrupt_type: specifies flag to clear.
+ *         the parameter can be one of the following values:
+ *             @arg SDDAC_IT_ALL_DONE: DMA full-transfer interrupt.
+ *             @arg SDDAC_IT_HALF_DONE: DMA half-transfer interrupt.
+ * @retval None
+ */
+AT(.com_periph.sddac.clear)
+void sddac_clear_flag(SDDAC_IT_TYPEDEF interrupt_type)
+{
+    if(interrupt_type == SDDAC_IT_ALL_DONE){
+        SDDAC->dma_cpnd = SDDAC_DMA_ALLPEND_CLR;
+    }else if (interrupt_type == SDDAC_IT_HALF_DONE){
+        SDDAC->dma_cpnd = SDDAC_DMA_HALFPEND_CLR;
+    }
+}
+

+ 43 - 0
driver/driver_sddac.h

@@ -0,0 +1,43 @@
+#ifndef _DRIVER_SDDAC_H
+#define _DRIVER_SDDAC_H
+
+#include "driver_com.h"
+
+enum {
+    SDDAC_NORMAL_SPR_48k      = 0x00,
+    SDDAC_NORMAL_SPR_24k,
+    SDDAC_NORMAL_SPR_16k,
+    SDDAC_NORMAL_SPR_12k,
+    SDDAC_NORMAL_SPR_8k,
+
+    SDDAC_HIGH_SPR_240k,
+    SDDAC_HIGH_SPR_120k,
+    SDDAC_HIGH_SPR_80k,
+    SDDAC_HIGH_SPR_60k,
+    SDDAC_HIGH_SPR_48k,
+};
+
+
+typedef enum {
+    SDDAC_IT_ALL_DONE       = BIT(0),
+    SDDAC_IT_HALF_DONE      = BIT(1),
+} SDDAC_IT_TYPEDEF;
+
+
+typedef struct{
+    u8  sample_rate;
+    u8  *dma_buf;
+    u16  dma_size;
+} sddac_init_typedef;
+
+
+void sddac_init(sddac_init_typedef *config);
+void sddac_clk_init(void);
+void sddac_pic_config(isr_t isr, int pr, SDDAC_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state);
+void sddac_cmd(FUNCTIONAL_STATE state);
+FLAG_STATE sddac_get_flag(SDDAC_IT_TYPEDEF interrupt_type);
+void sddac_clear_flag(SDDAC_IT_TYPEDEF interrupt_type);
+void sddac_dma_kick_start(uint8_t *buf, uint16_t size);
+void sddac_deinit(void);
+
+#endif

+ 252 - 0
driver/driver_spi.c

@@ -0,0 +1,252 @@
+/*
+ * @File name    : driver_spi.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-15
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the SPI peripheral.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_spi.h"
+
+/**
+  * @brief  Initializes the spix peripheral according to the specified
+  *         parameters in the spi_init_struct.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  spi_init_struct: pointer to a spi_init_typedef structure that
+  *         contains the configuration information for the specified SPI peripheral.
+  * @retval None
+  */
+void spi_init(spi_typedef* spix, spi_init_typedef* spi_init_struct)
+{
+    uint32_t temp = 0;
+
+    /* SPI_CLK freq configuration */
+    spix->baud = sys_clk_nhz_get() / spi_init_struct->baud - 1;
+
+    temp |= (uint32_t)(spi_init_struct->bus_mode & SPIxCON_BUSMODE);
+    temp |= (uint32_t)(spi_init_struct->role_mode & SPIxCON_SPISM);
+    temp |= (uint32_t)(spi_init_struct->output_data_edge & SPIxCON_SMPS);
+    temp |= (uint32_t)(spi_init_struct->sample_clk_edge & SPIxCON_SPIOSS);
+    temp |= (uint32_t)(spi_init_struct->clkids & SPIxCON_CLKIDS);
+
+    spix->con = temp;
+}
+
+/**
+ * @brief  De-initialize the specified SPI peripheral.
+ * @param  spix: where x can be (0..1) to select the SPI peripheral.
+ * @retval None
+ */
+void spi_deinit(spi_typedef* spix)
+{
+    if (spix == SPI0) {
+        /* Assert: This release disables disabling SPI0 peripherals using this API */
+    } else if (spix == SPI1) {
+        spix->con = 0;
+        clk_gate1_cmd(CLK_GATE1_SPI1, CLK_DIS);
+    }
+}
+
+/**
+  * @brief  Enable or disable the specified SPI peripheral.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  state: state of the SPIx peripheral.
+            This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void spi_cmd(spi_typedef* spix, FUNCTIONAL_STATE state)
+{
+    if (state) {
+        spix->con |= (uint32_t)SPIxCON_SPIEN;
+    } else {
+        spix->con &= (uint32_t)~SPIxCON_SPIEN;
+    }
+}
+
+/**
+  * @brief  Select the specified SPI direction when in DMA mode or 2-wire mode.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  direction: transmit or receive.
+            This parameter can be: SPI_DIR_TX or SPI_DIR_RX.
+  * @retval None
+  */
+void spi_dir_sel(spi_typedef* spix, SPI_DIR_TYPEDEF direction)
+{
+    if(direction == SPI_DIR_RX) {
+        spix->con |= BIT(4);
+    } else {
+        spix->con &= ~BIT(4);
+    }
+}
+
+/**
+  * @brief  Enable or disable the specified SPI interrupts.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  state: state of the SPIx interrupts.
+            This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void spi_it_cmd(spi_typedef* spix, FUNCTIONAL_STATE state)
+{
+    if (state) {
+        spix->con |= (uint32_t)SPIxCON_SPIIE;
+    } else {
+        spix->con &= (uint32_t)~SPIxCON_SPIIE;
+    }
+}
+
+/**
+  * @brief  Enable or disable the specified SPI LFSR.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  state: state of the SPIx interrupts.
+            This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void spi_lfsr_cmd(spi_typedef* spix, FUNCTIONAL_STATE state)
+{
+    if (state) {
+        spix->con |= (uint32_t)SPIxCON_SPILF_EN;
+    } else {
+        spix->con &= (uint32_t)~SPIxCON_SPILF_EN;
+    }
+}
+
+/**
+  * @brief  Enable or disable the specified SPI multiple bit bus.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  state: state of the SPIx interrupts.
+            This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void spi_multi_bit_bus_cmd(spi_typedef* spix, FUNCTIONAL_STATE state)
+{
+    if (state) {
+        spix->con |= (uint32_t)SPIxCON_SPIMBEN;
+    } else {
+        spix->con &= (uint32_t)~SPIxCON_SPIMBEN;
+    }
+}
+
+/**
+  * @brief  Enable or disable the specified SPI hold when bt rx.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  state: state of the SPIx interrupts.
+            This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void spi_hold_rx_cmd(spi_typedef* spix, FUNCTIONAL_STATE state)
+{
+    if (state) {
+        spix->con |= (uint32_t)SPIxCON_HOLDENRX;
+    } else {
+        spix->con &= (uint32_t)~SPIxCON_HOLDENRX;
+    }
+}
+
+/**
+  * @brief  Enable or disable the specified SPI hold when bt tx.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  state: state of the SPIx interrupts.
+            This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void spi_hold_tx_cmd(spi_typedef* spix, FUNCTIONAL_STATE state)
+{
+    if (state) {
+        spix->con |= (uint32_t)SPIxCON_HOLDENTX;
+    } else {
+        spix->con &= (uint32_t)~SPIxCON_HOLDENTX;
+    }
+}
+
+/**
+  * @brief  Enable or disable the specified SPI software hold.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  state: state of the SPIx interrupts.
+            This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void spi_soft_hold_cmd(spi_typedef* spix, FUNCTIONAL_STATE state)
+{
+    if (state) {
+        spix->con |= (uint32_t)SPIxCON_HOLDENSW;
+    } else {
+        spix->con &= (uint32_t)~SPIxCON_HOLDENSW;
+    }
+}
+
+/**
+  * @brief  Get the SPI pending.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  spi_flag: specifies the flag to set.
+  *         this parameter can be one of the following values:
+  *             @arg SPI_FLAG_PENDING: SPI(0..1) SPI pending.
+  * @retval The state of spi_flag (SET or RESET).
+  */
+AT(.com_periph.spi.get)
+FLAG_STATE spi_get_flag(spi_typedef* spix, uint32_t spi_flag)
+{
+    if ((spix->con & spi_flag) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+  * @brief  Clear the SPI pending.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  spi_flag: specifies the flag to clear.
+  *         this parameter can be one of the following values:
+  *             @arg SPI_FLAG_PENDING: SPI(0..1) SPI pending.
+  * @retval None
+  */
+AT(.com_periph.spi.clear)
+void spi_clear_flag(spi_typedef* spix, uint32_t spi_flag)
+{
+    spix->con |= (uint32_t)spi_flag;
+}
+
+/**
+  * @brief  Set the SPI counter register value.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  cnt: specifies the counter register new value.
+  * @retval None
+  */
+void spi_set_dma_cnt(spi_typedef* spix, uint32_t cnt)
+{
+    spix->dma_cnt = cnt;
+}
+
+/**
+  * @brief  Set the SPI DMA address register value.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  addr: specifies the SPI DMA address register new value.
+  * @retval None
+  */
+void spi_set_dma_addr(spi_typedef* spix, uint32_t addr)
+{
+    spix->dma_adr = (uint32_t)addr;
+}
+
+/**
+  * @brief  Get the spi receive data.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @retval spi receive data.
+  */
+uint8_t spi_receive_data(spi_typedef* spix)
+{
+    return (uint8_t)spix->buf;
+}
+
+/**
+  * @brief  Send the spi receive data.
+  * @param  spix: where x can be (0..1) to select the SPI peripheral.
+  * @param  data: specifies the SPI data to be sent.
+  * @retval None.
+  */
+void spi_send_data(spi_typedef* spix, uint8_t data)
+{
+    spix->buf = data;
+}

+ 94 - 0
driver/driver_spi.h

@@ -0,0 +1,94 @@
+/*
+ * @File name    : driver_spi.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-15
+ * @Description  : This file contains all the functions prototypes for the SPI library.
+ * 
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_SPI_H
+#define _DRIVER_SPI_H
+
+#include "driver_com.h"
+
+//--------------- SPI[0..1] Flag Definition ---------------//
+#define SPI_FLAG_PENDING                    ((uint32_t)0x00010000)
+
+/**
+ * @brief SPI Role Mode Enumeration
+ */
+typedef enum {
+    SPI_ROLE_MODE_MASTER                    = 0x00000000,
+    SPI_ROLE_MODE_SLAVE                     = 0x00000002,
+} SPI_ROLE_MODE_TYPEDEF;
+
+/**
+ * @brief SPI Bus Mode Enumeration
+ */
+typedef enum {
+    SPI_3WIRE_MODE                          = 0x00000000,
+    SPI_2WIRE_MODE                          = 0x00000004,
+    SPI_2BIT_BID_MODE                       = 0x00000008,
+    SPI_4BIT_BID_MODE                       = 0x0000000c,
+} SPI_BUS_MODE_TYPEDEF;
+
+/**
+ * @brief SPI Output Data Edge Enumeration
+ */
+typedef enum {
+    SPI_OUTPUT_DATA_EDGE_FALLING            = 0x00000000,
+    SPI_OUTPUT_DATA_EDGE_RISING             = 0x00000040,
+} SPI_OUTPUT_DATA_EDGE_TYPEDEF;
+
+/**
+ * @brief SPI Sample Clock Enumeration
+ */
+typedef enum {
+    SPI_SAMPLE_AND_OUTPUT_CLOCK_DIFF        = 0x00000000,
+    SPI_SAMPLE_AND_OUTPUT_CLOCK_SAME        = 0x00000400,
+} SPI_SAMPLE_AND_OUTPUT_CLOCK_TYPEDEF;
+
+/**
+ * @brief SPI Direction
+ */
+typedef enum {
+    SPI_DIR_TX                              = 0x00,
+    SPI_DIR_RX                              = 0x01,
+} SPI_DIR_TYPEDEF;
+
+/**
+ * @brief SPI Clock State When Idle
+ */
+typedef enum {
+    SPI_CLOCK_IDLE_LOW                      = 0x00000000,
+    SPI_CLOCK_IDLE_HIGH                     = 0x00000020,
+} SPI_CLOCK_IDLE_STATE_TYPEDEF;
+
+/* SPI Init Structure */
+typedef struct{
+    uint32_t baud;
+    SPI_ROLE_MODE_TYPEDEF role_mode;
+    SPI_BUS_MODE_TYPEDEF bus_mode;
+    SPI_OUTPUT_DATA_EDGE_TYPEDEF output_data_edge;
+    SPI_SAMPLE_AND_OUTPUT_CLOCK_TYPEDEF sample_clk_edge;
+    SPI_CLOCK_IDLE_STATE_TYPEDEF clkids;    //if SPI1BAUD is equal to 0, then CLKIDS forces 0 by designed
+} spi_init_typedef;
+
+void spi_init(spi_typedef* spix, spi_init_typedef* spi_init_struct);
+void spi_deinit(spi_typedef* spix);
+void spi_cmd(spi_typedef* spix, FUNCTIONAL_STATE state);
+void spi_dir_sel(spi_typedef* spix, SPI_DIR_TYPEDEF direction);
+void spi_it_cmd(spi_typedef* spix, FUNCTIONAL_STATE state);
+void spi_lfsr_cmd(spi_typedef* spix, FUNCTIONAL_STATE state);
+void spi_multi_bit_bus_cmd(spi_typedef* spix, FUNCTIONAL_STATE state);
+void spi_hold_rx_cmd(spi_typedef* spix, FUNCTIONAL_STATE state);
+void spi_hold_tx_cmd(spi_typedef* spix, FUNCTIONAL_STATE state);
+void spi_soft_hold_cmd(spi_typedef* spix, FUNCTIONAL_STATE state);
+FLAG_STATE spi_get_flag(spi_typedef* spix, uint32_t spi_flag);
+void spi_clear_flag(spi_typedef* spix, uint32_t spi_flag);
+void spi_set_dma_cnt(spi_typedef* spix, uint32_t cnt);
+void spi_set_dma_addr(spi_typedef* spix, uint32_t addr);
+uint8_t spi_receive_data(spi_typedef* spix);
+void spi_send_data(spi_typedef* spix, uint8_t data);
+
+#endif // _DRIVER_SPI_H

+ 387 - 0
driver/driver_tmr.c

@@ -0,0 +1,387 @@
+/*
+ * @File name    : driver_tmr.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-14
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the TMR peripheral.
+ *
+ * Copyright (c) by Bluetrum, All Rights reserved.
+ */
+#include "driver_tmr.h"
+
+/**
+  * @brief  Initializes the timer base peripheral according to the specified
+  *         parameters in the tmr_base_init_typedef.
+  * @param  tmrx: where x can be (0..3) to select the TMR peripheral.
+  * @param  tmr_base_init_struct: pointer to a tmr_base_init_typedef structure that
+  *         contains the configuration information for the specified TMR peripheral.
+  * @retval None
+  */
+void tmr_base_init(tmr_typedef *tmrx, tmr_base_init_typedef *tmr_base_init_struct)
+{
+    //---------- tmr controller register ----------//
+    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
+        tmrx->con &= ~(uint32_t)TMRxCON_INCSEL;
+        tmrx->con |= (uint32_t)tmr_base_init_struct->clock_source;
+
+        tmrx->con &= ~(uint32_t)TMRxCON_INCSRC;
+        tmrx->con |= (uint32_t)tmr_base_init_struct->counter_source;
+    } else if (tmrx == TMR3) {
+        tmrx->con &= ~(uint32_t)TMR3CON_INCSEL;
+        tmrx->con |= (uint32_t)tmr_base_init_struct->clock_source;
+
+        tmrx->con &= ~(uint32_t)TMR3CON_INCSRC;
+        tmrx->con |= (uint32_t)tmr_base_init_struct->counter_source;
+        tmrx->psc = (uint16_t)(tmr_base_init_struct->prescale);
+    }
+    tmrx->period = (uint32_t)(tmr_base_init_struct->period);
+}
+
+/**
+ * @brief  De-initialize the specified tmr peripheral.
+ * @retval None
+ */
+void tmr_deinit(tmr_typedef *tmrx)
+{
+    tmrx->con = 0;
+
+    if (tmrx == TMR0) {
+        clk_gate0_cmd(CLK_GATE0_TMR0, CLK_DIS);
+    } else if (tmrx == TMR1) {
+        clk_gate0_cmd(CLK_GATE0_TMR1, CLK_DIS);
+    } else if (tmrx == TMR2) {
+        clk_gate0_cmd(CLK_GATE0_TMR2, CLK_DIS);
+    } else if (tmrx == TMR3) {
+        clk_gate1_cmd(CLK_GATE1_TMR3, CLK_DIS);
+    }
+}
+
+/**
+  * @brief  Set the TMR counter register value.
+  * @param  tmrx: where x can be (0..3) to select the TMR peripheral.
+  * @param  cnt: specifies the counter register new value.
+  * @retval None
+  */
+void tmr_set_counter(tmr_typedef *tmrx, uint32_t cnt)
+{
+    tmrx->cnt = cnt;
+}
+
+/**
+  * @brief  Set the TMR period register value.
+  * @param  tmrx: where x can be (0..3) to select the TMR peripheral.
+  * @param  period: specifies the period register new value.
+  * @retval None
+  */
+AT(.com_periph.tmr.set_period)
+void tmr_set_period(tmr_typedef *tmrx, uint32_t period)
+{
+    tmrx->period = period;
+}
+
+/**
+ * @brief  Set the TMR prescale register value.
+ * @param  tmrx: where x can be (3) to select the TMR peripheral.
+ * @param  psc: specifies the prescale register new value.
+ * @retval None
+ */
+void tmr_set_prescale(tmr_typedef *tmrx, uint16_t psc)
+{
+	if (tmrx == TMR3) {
+	    tmrx->psc = (uint16_t)psc;
+	}
+}
+
+/**
+  * @brief  Get the TMR counter register value.
+  * @param  tmrx: where x can be (0..3) to select the TMR peripheral.
+  * @retval specifies the counter register value.
+  */
+uint32_t tmr_get_counter(tmr_typedef *tmrx)
+{
+    return (uint32_t)(tmrx->cnt);
+}
+
+/**
+  * @brief  Get the TMR period register value.
+  * @param  tmrx: where x can be (0..3) to select the TMR peripheral.
+  * @retval specifies the period register value.
+  */
+uint32_t tmr_get_period(tmr_typedef *tmrx)
+{
+    return (uint32_t)(tmrx->period);
+}
+
+/**
+ * @brief  Get the TMR prescale register value.
+ * @param  tmrx: where x can be (3) to select the TMR peripheral.
+ * @retval Specifies the prescale register value.
+ */
+uint16_t tmr_get_prescale(tmr_typedef *tmrx)
+{
+	if (tmrx == TMR3) {
+	    return (uint16_t)(tmrx->psc);
+	}
+	return 0;
+}
+
+/**
+  * @brief  Enable or disable the specified TMR peripheral.
+  * @param  tmrx: where x can be (0..3) to select the TMR peripheral.
+  * @param  state: state of the TMRx peripheral.
+            This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+AT(.com_periph.tmr.cmd)
+void tmr_cmd(tmr_typedef *tmrx, FUNCTIONAL_STATE state)
+{
+    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
+        if (state != DISABLE) {
+            tmrx->con |= TMRxCON_TMREN;
+        } else {
+            tmrx->con &= (uint32_t)(~TMRxCON_TMREN);
+        }
+    } else if (tmrx == TMR3) {
+        if (state != DISABLE) {
+            tmrx->con |= TMR3CON_TMREN;
+        } else {
+            tmrx->con &= (uint32_t)(~TMR3CON_TMREN);
+        }
+    }
+}
+
+/**
+ * @brief  Config pwm duty of specified TMR periperal.
+ * @param  tmrx: where x can be (3) to select the TMR peripheral.
+ * @param  pwm: the pwm channel that wants to config.
+ *         this parameter can be one of the following values:
+ *             @arg TMR_PWM0: pwm0 channel.
+ *             @arg TMR_PWM1: pwm1 channel.
+ *             @arg TMR_PWM2: pwm2 channel.
+ * @param  duty: The high level time of the pwm to be configured.
+ * @retval
+ */
+void tmr_pwm_duty_config(tmr_typedef *tmrx, TMR_PWM_TYPEDDEF pwm, uint16_t duty)
+{
+    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
+        return;
+    }
+
+    if (pwm == TMR_PWM0) {
+        tmrx->duty0 = duty;
+    } else if (pwm == TMR_PWM1) {
+        tmrx->duty1 = duty;
+    } else if (pwm == TMR_PWM2) {
+        tmrx->duty2 = duty;
+    }
+}
+
+/**
+  * @brief  Enable or disable the PWM of specified TMR peripheral.
+  * @param  tmrx: where x can be (3) to select the TMR peripheral.
+  * @param  pwm: The pwm channel that wants to config.
+  *         this parameter can be one of the following values:
+  *             @arg TMR_PWM0: pwm0 channel.
+  *             @arg TMR_PWM1: pwm1 channel.
+  *             @arg TMR_PWM2: pwm2 channel.
+  * @param  state: state of the TMRx peripheral.
+            This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void tmr_pwm_cmd(tmr_typedef *tmrx, TMR_PWM_TYPEDDEF pwm, FUNCTIONAL_STATE state)
+{
+    uint32_t pwm_con_mask = TMR3CON_PWM0EN | TMR3CON_PWM1EN | TMR3CON_PWM2EN;
+
+    if (tmrx == TMR3) {
+        if (state != DISABLE) {
+            tmrx->con |= pwm & pwm_con_mask;
+        } else {
+            tmrx->con &= (uint32_t)~(pwm & pwm_con_mask);
+        }
+    }
+}
+
+/**
+  * @brief  Get the TMR capture register value.
+  * @param  tmrx: where x can be (3) to select the TMR peripheral.
+  * @retval specifies the capture register value.
+  */
+uint32_t tmr_get_capture(tmr_typedef *tmrx)
+{
+    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
+        return ~((uint32_t)0);
+    }
+    return (uint32_t)(tmrx->capture_val);
+}
+
+/**
+  * @brief  Configure input capture for TMR.
+  * @param  tmrx: where x can be (0..3) to select the TMR peripheral.
+  * @param  edge_select: Captured edge selection.
+  *         this parameter can be one of the following values:
+  *             @arg TMR_CAP_NULL: no capture.
+  *             @arg TMR_CAP_RISING: capture rising edge.
+  *             @arg TMR_CAP_FALLING: capture falling edge.
+  *             @arg TMR_CAP_EDGE: capture bilateral edge.
+  * @retval None
+  */
+void tmr_capture_config(tmr_typedef *tmrx, TMR_CAP_EDGE_TYPEDEF edge_select)
+{
+    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
+        return;
+    }
+
+    tmrx->con &= ~((uint32_t)TMR3CON_CPTEDSEL);
+    tmrx->con |= (uint32_t)edge_select;
+}
+
+/**
+  * @brief  Enable or disable the capture function of specified TMR peripheral.
+  * @param  tmrx: where x can be (3) to select the TMR peripheral.
+  * @param  state: state of the TMRx peripheral.
+  *         This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void tmr_capture_cmd(tmr_typedef *tmrx, FUNCTIONAL_STATE state)
+{
+    if (tmrx == TMR3) {
+        if (state != DISABLE) {
+            tmrx->con |= TMR3CON_CPTEN;
+        } else {
+            tmrx->con &= (uint32_t)(~TMR3CON_CPTEN);
+        }
+    }
+}
+
+/**
+  * @brief  Enable or disable the specified TMRx interrupt.
+  * @param  tmrx: where x can be (0..3) to select the TMR peripheral.
+  * @param  isr: Function to be executed for service interruption.
+  * @param  pr: Priority of service interruption.
+  * @param  interrup_type: specifies the TRMx interrupt sources to be enable or disable.
+  *         this parameter can be one of the following values:
+  *             @arg TMR_IT_UPDATE1: TMR(1..2) overflow interrupt enable bit.
+  *             @arg TMR_IT_CAP: TMR(3..5) capture interrupt enable bit.
+  *             @arg TMR_IT_UPDATE2: TMR(3..5) overflow interrupt enable bit.
+  * @param  state: the state of the TMRx peripheral.
+  *         this parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void tmr_pic_config(tmr_typedef *tmrx, isr_t isr, int pr, TMR_IT_TYPEDEF interrup_type, FUNCTIONAL_STATE state)
+{
+    uint8_t irq_vector;
+    uint32_t tmr_interrupt_bit = 0;
+    uint32_t all_interrupt_type_mask = TMR_IT_UPDATE | TMR_IT_CAPTURE;
+
+    if (interrup_type == 0) {
+        return;
+    }
+
+    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
+        if (interrup_type & TMR_IT_CAPTURE) {
+            interrup_type &= ~TMR_IT_CAPTURE;
+        }
+    }
+
+    /*--- Get interrupt vector ---*/
+    if (tmrx == TMR0) {
+        irq_vector = IRQn_TMR0;
+    }else if (tmrx == TMR1) {
+        irq_vector = IRQn_TMR1;
+    } else if (tmrx == TMR2) {
+        irq_vector = IRQn_TMR2;
+    } else if (tmrx == TMR3) {
+        irq_vector = IRQn_TMR3;
+    } else {
+        return;
+    }
+
+    /*--- Get interrupt ctrl bit ---*/
+    if (interrup_type & TMR_IT_UPDATE) {
+        tmr_interrupt_bit |= TMRxCON_TIE;
+    }
+
+    if (interrup_type & TMR_IT_CAPTURE) {
+        tmr_interrupt_bit |= TMR3CON_CIE;
+    }
+
+    /*--- Execute configured ---*/
+    if (state != DISABLE) {
+        tmrx->con |= tmr_interrupt_bit;
+        sys_irq_init(irq_vector, pr, isr);
+    } else {
+        tmrx->con &= ~tmr_interrupt_bit;
+        if ((tmrx != TMR3) || (interrup_type == all_interrupt_type_mask)) {
+            PICENCLR = BIT(irq_vector);
+        }
+    }
+}
+
+/**
+  * @brief  Get the TMR interrupt pending.
+  * @param  tmrx: where x can be (0..3) to select the TMR peripheral.
+  * @param  interrupt_type: specifies the IT to clear.
+  *         this parameter can be one of the following values:
+  *             @arg TMR_IT_UPDATE: TMR overflow interrupt.
+  *             @arg TMR_IT_CAPTURE: TMR capture interrupt.
+  * @retval The state of interrupt_type (SET or RESET).
+  */
+AT(.com_periph.tmr.get)
+FLAG_STATE tmr_get_flag(tmr_typedef *tmrx, TMR_IT_TYPEDEF interrupt_type)
+{
+    uint32_t interrupt_pending_bit = 0;
+
+    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
+        if (interrupt_type & TMR_IT_CAPTURE) {
+            return RESET;
+        } else if (interrupt_type & TMR_IT_UPDATE) {
+            interrupt_pending_bit |= TMRxCON_TPND;
+        }
+    } else if (tmrx == TMR3) {
+        if (interrupt_type & TMR_IT_CAPTURE) {
+            interrupt_pending_bit |= TMR3CON_CPND;
+        }
+        if (interrupt_type & TMR_IT_UPDATE) {
+            interrupt_pending_bit |= TMR3CON_TPND;
+        }
+    } else {
+        return RESET;
+    }
+
+    if ((tmrx->con & interrupt_pending_bit) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+  * @brief  Clear the TMR interrupt pending.
+  * @param  tmrx: where x can be (0..3) to select the TMR peripheral.
+  * @param  interrupt_type: specifies the interrupt to clear.
+  *         this parameter can be one of the following values:
+  *             @arg TMR_IT_UPDATE: TMR overflow interrupt.
+  *             @arg TMR_IT_CAPTURE: TMR capture interrupt.
+  * @retval None
+  */
+AT(.com_periph.tmr.clear)
+void tmr_clear_flag(tmr_typedef *tmrx, TMR_IT_TYPEDEF interrupt_type)
+{
+    uint32_t interrupt_pending_bit = 0;
+
+    if (tmrx == TMR0 || tmrx == TMR1 || tmrx == TMR2) {
+        if (interrupt_type & TMR_IT_UPDATE) {
+            interrupt_pending_bit |= TMRxCPND_TPCLR;
+        }
+    } else if (tmrx == TMR3) {
+        if (interrupt_type & TMR_IT_CAPTURE) {
+            interrupt_pending_bit |= TMR3CPND_CPCLR;
+        } else if (interrupt_type & TMR_IT_UPDATE) {
+            interrupt_pending_bit |= TMR3CPND_TPCLR;
+        }
+    } else {
+        return;
+    }
+
+    tmrx->cpnd |= interrupt_pending_bit;
+}

+ 91 - 0
driver/driver_tmr.h

@@ -0,0 +1,91 @@
+/*
+ * @File name    : driver_tmr.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-14
+ * @Description  : This file contains all the functions prototypes for the TMR library.
+ * 
+ * Copyright (c) by Bluetrum, All Rights reserved.
+ */
+#ifndef _DRIVER_TMR_H
+#define _DRIVER_TMR_H
+
+#include "driver_com.h"
+
+/**
+ * @brief TMR Interrupt Flag Definition
+ */
+typedef enum {
+    TMR_IT_UPDATE           = 0x01,
+    TMR_IT_CAPTURE          = 0x02,
+} TMR_IT_TYPEDEF;
+
+/**
+ * @brief Clock Source Selection
+ */
+typedef enum {
+    TMR_INC_SOURCE          = 0x00000000,
+    TMR_PIN_SOURCE          = 0x00000040,
+} TMR_COUNTER_TYPEDEF;
+
+/**
+ * @brief Capture Edge Selection
+ */
+typedef enum {
+    TMR_CAP_NULL            = 0x00000000,
+    TMR_CAP_RISING          = 0x00000010,
+    TMR_CAP_FALLING         = 0x00000020,
+    TMR_CAP_EDGE            = 0x00000030,
+} TMR_CAP_EDGE_TYPEDEF;
+
+/**
+ * @brief Clock Triggle Selection
+ */
+typedef enum {
+    TMR_SYSTEM_CLOCK        = 0x00000000,
+    TMR_COUNTER_RISING      = 0x00000004,
+    TMR_COUNTER_FALLING     = 0x00000008,
+    TMR_COUNTER_EDGE        = 0x0000000c,
+} TMR_CLOCK_TYPEDEF;
+
+/**
+ * @brief PWM Mode Selection
+ */
+typedef enum {
+    TMR_PWM0                = 0x00000200,
+    TMR_PWM1                = 0x00000400,
+    TMR_PWM2                = 0x00000800,
+} TMR_PWM_TYPEDDEF;
+
+/**
+ * @brief Timer Init Structure
+ */
+typedef struct {
+    uint32_t                period;
+    uint32_t                prescale;
+    TMR_COUNTER_TYPEDEF     counter_source;
+    TMR_CLOCK_TYPEDEF       clock_source;
+} tmr_base_init_typedef;
+
+/********************** Function used to configure timer base **********************/
+void tmr_base_init(tmr_typedef *tmrx, tmr_base_init_typedef *tmr_base_init_struct);
+void tmr_deinit(tmr_typedef *tmrx);
+void tmr_set_counter(tmr_typedef *tmrx, uint32_t cnt);
+void tmr_set_period(tmr_typedef *tmrx, uint32_t period);
+void tmr_set_prescale(tmr_typedef *tmrx, uint16_t psc);
+uint32_t tmr_get_counter(tmr_typedef *tmrx);
+uint32_t tmr_get_period(tmr_typedef *tmrx);
+uint16_t tmr_get_prescale(tmr_typedef *tmrx);
+void tmr_cmd(tmr_typedef *tmrx, FUNCTIONAL_STATE state);
+/*************************** Function used to set pwm ******************************/
+void tmr_pwm_duty_config(tmr_typedef *tmrx, TMR_PWM_TYPEDDEF pwm, uint16_t duty);
+void tmr_pwm_cmd(tmr_typedef *tmrx, TMR_PWM_TYPEDDEF pwm, FUNCTIONAL_STATE state);
+/************************** Function used to set capture ***************************/
+uint32_t tmr_get_capture(tmr_typedef *tmrx);
+void tmr_capture_config(tmr_typedef *tmrx, TMR_CAP_EDGE_TYPEDEF edge_select);
+void tmr_capture_cmd(tmr_typedef *tmrx, FUNCTIONAL_STATE state);
+/********************** Function used to configure interrupt ***********************/
+void tmr_pic_config(tmr_typedef *tmrx, isr_t isr, int pr, TMR_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state);
+FLAG_STATE tmr_get_flag(tmr_typedef *tmrx, TMR_IT_TYPEDEF interrupt_type);
+void tmr_clear_flag(tmr_typedef *tmrx, TMR_IT_TYPEDEF interrupt_type);
+
+#endif // _DRIVER_TMR_H

+ 376 - 0
driver/driver_touch_key.c

@@ -0,0 +1,376 @@
+/**
+******************************************************************************************************************************
+*
+*@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;
+}
+

+ 504 - 0
driver/driver_touch_key.h

@@ -0,0 +1,504 @@
+/**
+******************************************************************************************************************************
+*
+*@file driver_touch_key.h
+*
+*@brief Header file for Touch Key Driver
+*
+*@Create date: 2023-03-23
+*
+*
+*Copyright (c) 2023, BLUETRUM
+******************************************************************************************************************************
+**/
+#ifndef _TOUCH_KEY_H_
+#define _TOUCH_KEY_H_
+
+#ifdef __cpluscplus
+extern "C" {
+#endif
+
+/*
+ * INCLUDE FILES
+ ***************************************************************************
+ */
+#include "driver_com.h"
+
+/*
+ * VARIABLE DEFINITION
+ ***************************************************************************
+ */
+
+#define SUPPORT_TOUCH_KEY_NUM           4
+
+typedef struct {
+    u16 cdpr;
+    u8  type;                           //0: disable channel, 1: touch key channel, 2: touch ear channel
+    u8  ctrim;                          //cur channel ctrim select
+    u8  itrim;                          //cur channel itrim select
+    u16 tkpthd;                         // TK Press Threshold
+    u16 tkrthd;                         // TK Release Threshold
+} tkey_ch_t;
+
+typedef struct {
+    const tkey_ch_t *key[SUPPORT_TOUCH_KEY_NUM];
+    union {
+        struct {
+            u32 fil_low     :  4;       //touch key state low state filter length, fil_low + 1
+            u32 fil_high    :  4;       //touch key state high state filter length, fil_high + 1
+            u32 fil_except  :  8;       //touch key state exception filter length, fil_except + 1
+            u32 fil_val     :  4;       //touch key base_cnt valid filter length, fil_val + 1
+            u32 to_except   :  12;      //touch key state high timeout length
+        };
+        u32 reg_tktmr;
+    };
+    union {
+        struct {
+            u32 tkpthd      :   12;     //touch key press threshold
+            u32 resv0       :   4;
+            u32 tkrthd      :   12;     //touch key release threshold
+            u32 pto_except  :   4;      //touch key press time out length. (pto_except << 8)
+        };
+        u32 reg_tkpthd;
+    };
+    union {
+        struct {
+            u32 tksthd      :   12;     //touch key smaller threshold
+            u32 resv1       :   4;
+            u32 tklthd      :   12;     //touch key larger threshold
+            u32 resv2       :   4;
+        };
+        u32 reg_tkethd;
+    };
+
+    union {
+        struct {
+            u32 tkvthd      :   16;     //touch key variance threshold
+            u32 val         :   16;     //touch key variance
+        };
+        u32 reg_tkvari;
+    };
+
+    union {
+        struct {
+            u32 tkarthd     :   12;     //touch key average range threshold
+            u32 tkaethd     :   4;      //touch key average equal threshold
+            u32 tkvfil      :   8;      //touch key variance filter count
+            u32 tkbadd      :   8;      //touch key base counter adder value
+        };
+        u32 reg_tkvarithd;
+    };
+
+    union {
+        struct {
+            u32 press_vari_en   :   1;  //press variance enable bit
+            u32 rels_vari_en    :   1;  //release variance enable bit
+            u32 press_fil_sel   :   1;  //press variance after filter
+            u32 rels_fil_sel    :   1;  //release variance after filter
+            u32 press_vari_thd  :   12; //press variance threshold
+            u32 rels_vari_thd   :   12; //release variance threshold
+            u32 to_bcnt_thd     :   4;  //time out base counter threshold
+        };
+        u32 reg_tkcon2;
+    };
+
+
+    //in ear
+    union {
+        struct {
+            u32 ear_fil_low     :  4;
+            u32 ear_fil_high    :  4;
+            u32 ear_fil_except  :  8;
+            u32 ear_fil_val     :  4;
+            u32 tkpwup          :  6;
+        };
+        u32 reg_tetmr;
+    };
+    union {
+        struct {
+            u32 tepthd      :   12;     //touch ear press threshold
+            u32 resv3       :   4;
+            u32 terthd      :   12;     //touch ear release threshold
+            u32 tefathd     :   4;
+        };
+        u32 reg_tepthd;
+    };
+    union {
+        struct {
+            u32 testhd      :   12;     //touch ear smaller threshold
+            u32 resv5       :   4;
+            u32 telthd      :   12;     //touch ear larger threshold
+            u32 resv6       :   4;
+        };
+        u32 reg_teethd;
+    };
+} tkey_cfg_t;
+
+typedef struct {
+    u8  ch;                     //channel index
+    u8  cnt;
+    u8  limit;                  //方差阈值
+    u8  stable_cnt;
+    u8  te_flag;                //是否为入耳检测
+    u8  range_thresh;           //rang校准的上限阈值
+    u16 avg;                    //平均值
+    u16 buf[8];
+    u32 anov_cnt;               //满足方差条件计数
+    psfr_t bcnt_sfr;            //BCNT寄存器
+    u8  fil_except;
+    u8  range_en;
+    u16 temp_tkcnt;
+    u32 tick;
+    u16 to_cnt;                 //定时校准时间
+    u8  resv[6];
+    u8 touch_key_sta[SUPPORT_TOUCH_KEY_NUM];
+} tk_cb_t;
+
+/*
+ * REGISTER DEFINITION
+ ***************************************************************************
+ */
+// Touch Key Control Register 0
+#define ADDR_REG_TKCON                          *(volatile unsigned long*) (SFR10_BASE + 0x02*4)
+// Touch Key base_cnt Valid
+#define POS_REG_TKCON_TKBCNTVAL                 27
+#define BIT_REG_TKCON_TKBCNTVAL                 0x8000000
+#define SETF_REG_TKCON_TKBCNTVAL()              ADDR_REG_TKCON |= BIT_REG_TKCON_TKBCNTVAL
+#define CLRF_REG_TKCON_TKBCNTVAL()              ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKBCNTVAL
+#define GETF_REG_TKCON_TKBCNTVAL()              ((ADDR_REG_TKCON & BIT_REG_TKCON_TKBCNTVAL) >> POS_REG_TKCON_TKBCNTVAL)
+// Touch Key Timeout Pending Update base_cnt Enable
+#define POS_REG_TKCON_TKTOUPDBEN                26
+#define BIT_REG_TKCON_TKTOUPDBEN                0x4000000
+#define SETF_REG_TKCON_TKTOUPDBEN()             ADDR_REG_TKCON |= BIT_REG_TKCON_TKTOUPDBEN
+#define CLRF_REG_TKCON_TKTOUPDBEN()             ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKTOUPDBEN
+#define GETF_REG_TKCON_TKTOUPDBEN()             ((ADDR_REG_TKCON & BIT_REG_TKCON_TKTOUPDBEN) >> POS_REG_TKCON_TKTOUPDBEN)
+// Touch Key Range Pending Update base_cnt Enable
+#define POS_REG_TKCON_TKRUPDBEN                 25
+#define BIT_REG_TKCON_TKRUPDBEN                 0x2000000
+#define SETF_REG_TKCON_TKRUPDBEN()              ADDR_REG_TKCON |= BIT_REG_TKCON_TKRUPDBEN
+#define CLRF_REG_TKCON_TKRUPDBEN()              ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKRUPDBEN
+#define GETF_REG_TKCON_TKRUPDBEN()              ((ADDR_REG_TKCON & BIT_REG_TKCON_TKRUPDBEN) >> POS_REG_TKCON_TKRUPDBEN)
+// Touch Key Large Pending Update base_cnt Enable
+#define POS_REG_TKCON_TKLUPDBEN                 24
+#define BIT_REG_TKCON_TKLUPDBEN                 0x1000000
+#define SETF_REG_TKCON_TKLUPDBEN()              ADDR_REG_TKCON |= BIT_REG_TKCON_TKLUPDBEN
+#define CLRF_REG_TKCON_TKLUPDBEN()              ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKLUPDBEN
+#define GETF_REG_TKCON_TKLUPDBEN()              ((ADDR_REG_TKCON & BIT_REG_TKCON_TKLUPDBEN) >> POS_REG_TKCON_TKLUPDBEN)
+// Touch Key Small Pending Update base_cnt Enable
+#define POS_REG_TKCON_TKSUPDBEN                 23
+#define BIT_REG_TKCON_TKSUPDBEN                 0x800000
+#define SETF_REG_TKCON_TKSUPDBEN()              ADDR_REG_TKCON |= BIT_REG_TKCON_TKSUPDBEN
+#define CLRF_REG_TKCON_TKSUPDBEN()              ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKSUPDBEN
+#define GETF_REG_TKCON_TKSUPDBEN()              ((ADDR_REG_TKCON & BIT_REG_TKCON_TKSUPDBEN) >> POS_REG_TKCON_TKSUPDBEN)
+// Touch Key State Wakeup Enable
+#define POS_REG_TKCON_TKSTAWKEN                 21
+#define BIT_REG_TKCON_TKSTAWKEN                 0x200000
+#define SETF_REG_TKCON_TKSTAWKEN()              ADDR_REG_TKCON |= BIT_REG_TKCON_TKSTAWKEN
+#define CLRF_REG_TKCON_TKSTAWKEN()              ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKSTAWKEN
+#define GETF_REG_TKCON_TKSTAWKEN()              ((ADDR_REG_TKCON & BIT_REG_TKCON_TKSTAWKEN) >> POS_REG_TKCON_TKSTAWKEN)
+// Touch Key Pending Wakeup Enable
+#define POS_REG_TKCON_TKPNDWKEN                 20
+#define BIT_REG_TKCON_TKPNDWKEN                 0x100000
+#define SETF_REG_TKCON_TKPNDWKEN()              ADDR_REG_TKCON |= BIT_REG_TKCON_TKPNDWKEN
+#define CLRF_REG_TKCON_TKPNDWKEN()              ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKPNDWKEN
+#define GETF_REG_TKCON_TKPNDWKEN()              ((ADDR_REG_TKCON & BIT_REG_TKCON_TKPNDWKEN) >> POS_REG_TKCON_TKPNDWKEN)
+// Touch Key Press Timeout Pending Update base_cnt Enable
+#define POS_REG_TKCON_TKPTOUPDBEN               19
+#define BIT_REG_TKCON_TKPTOUPDBEN               0x80000
+#define SETF_REG_TKCON_TKPTOUPDBEN()            ADDR_REG_TKCON |= BIT_REG_TKCON_TKPTOUPDBEN
+#define CLRF_REG_TKCON_TKPTOUPDBEN()            ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKPTOUPDBEN
+#define GETF_REG_TKCON_TKPTOUPDBEN()            ((ADDR_REG_TKCON & BIT_REG_TKCON_TKPTOUPDBEN) >> POS_REG_TKCON_TKPTOUPDBEN)
+// Touch Key Mode Select
+#define POS_REG_TKCON_TK_MODE                   18
+#define BIT_REG_TKCON_TK_MODE                   0x40000
+#define SETF_REG_TKCON_TK_MODE()                ADDR_REG_TKCON |= BIT_REG_TKCON_TK_MODE
+#define CLRF_REG_TKCON_TK_MODE()                ADDR_REG_TKCON &= ~BIT_REG_TKCON_TK_MODE
+#define GETF_REG_TKCON_TK_MODE()                ((ADDR_REG_TKCON & BIT_REG_TKCON_TK_MODE) >> POS_REG_TKCON_TK_MODE)
+// Touch Key Software Control Select
+#define POS_REG_TKCON_TKSWSEL                   17
+#define BIT_REG_TKCON_TKSWSEL                   0x20000
+#define SETF_REG_TKCON_TKSWSEL()                ADDR_REG_TKCON |= BIT_REG_TKCON_TKSWSEL
+#define CLRF_REG_TKCON_TKSWSEL()                ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKSWSEL
+#define GETF_REG_TKCON_TKSWSEL()                ((ADDR_REG_TKCON & BIT_REG_TKCON_TKSWSEL) >> POS_REG_TKCON_TKSWSEL)
+// Touch Key Analog Fix Channel Enable
+#define POS_REG_TKCON_TKCH_FIX                  16
+#define BIT_REG_TKCON_TKCH_FIX                  0x10000
+#define SETF_REG_TKCON_TKCH_FIX()               ADDR_REG_TKCON |= BIT_REG_TKCON_TKCH_FIX
+#define CLRF_REG_TKCON_TKCH_FIX()               ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKCH_FIX
+#define GETF_REG_TKCON_TKCH_FIX()               ((ADDR_REG_TKCON & BIT_REG_TKCON_TKCH_FIX) >> POS_REG_TKCON_TKCH_FIX)
+// Touch Key Analog Reset Disable
+#define POS_REG_TKCON_TKRST_DIS                 15
+#define BIT_REG_TKCON_TKRST_DIS                 0x8000
+#define SETF_REG_TKCON_TKRST_DIS()              ADDR_REG_TKCON |= BIT_REG_TKCON_TKRST_DIS
+#define CLRF_REG_TKCON_TKRST_DIS()              ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKRST_DIS
+#define GETF_REG_TKCON_TKRST_DIS()              ((ADDR_REG_TKCON & BIT_REG_TKCON_TKRST_DIS) >> POS_REG_TKCON_TKRST_DIS)
+// Touch Key Analog Hardware Auto Enable Select
+#define POS_REG_TKCON_TKAEN_ATSEL               14
+#define BIT_REG_TKCON_TKAEN_ATSEL               0x4000
+#define SETF_REG_TKCON_TKAEN_ATSEL()            ADDR_REG_TKCON |= BIT_REG_TKCON_TKAEN_ATSEL
+#define CLRF_REG_TKCON_TKAEN_ATSEL()            ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKAEN_ATSEL
+#define GETF_REG_TKCON_TKAEN_ATSEL()            ((ADDR_REG_TKCON & BIT_REG_TKCON_TKAEN_ATSEL) >> POS_REG_TKCON_TKAEN_ATSEL)
+// Touch Key Internal Channel 3 Enable
+#define POS_REG_TKCON_TK3_EN                    13
+#define BIT_REG_TKCON_TK3_EN                    0x2000
+#define SETF_REG_TKCON_TK3_EN()                 ADDR_REG_TKCON |= BIT_REG_TKCON_TK3_EN
+#define CLRF_REG_TKCON_TK3_EN()                 ADDR_REG_TKCON &= ~BIT_REG_TKCON_TK3_EN
+#define GETF_REG_TKCON_TK3_EN()                 ((ADDR_REG_TKCON & BIT_REG_TKCON_TK3_EN) >> POS_REG_TKCON_TK3_EN)
+// Touch Key Internal Channel 2 Enable
+#define POS_REG_TKCON_TK2_EN                    12
+#define BIT_REG_TKCON_TK2_EN                    0x1000
+#define SETF_REG_TKCON_TK2_EN()                 ADDR_REG_TKCON |= BIT_REG_TKCON_TK2_EN
+#define CLRF_REG_TKCON_TK2_EN()                 ADDR_REG_TKCON &=~BIT_REG_TKCON_TK2_EN
+#define GETF_REG_TKCON_TK2_EN()                  ((ADDR_REG_TKCON & BIT_REG_TKCON_TK2_EN) >> POS_REG_TKCON_TK2_EN)
+// Touch Key Internal Channel 1 Enable
+#define POS_REG_TKCON_TK1_EN                    11
+#define BIT_REG_TKCON_TK1_EN                    0x800
+#define SETF_REG_TKCON_TK1_EN()                 ADDR_REG_TKCON |= BIT_REG_TKCON_TK1_EN
+#define CLRF_REG_TKCON_TK1_EN()                 ADDR_REG_TKCON &=~BIT_REG_TKCON_TK1_EN
+#define GETF_REG_TKCON_TK1_EN()                 ((ADDR_REG_TKCON & BIT_REG_TKCON_TK1_EN) >> POS_REG_TKCON_TK1_EN)
+// Touch Key Internal Channel 0 Enable
+#define POS_REG_TKCON_TK0_EN                    10
+#define BIT_REG_TKCON_TK0_EN                    0x400
+#define SETF_REG_TKCON_TK0_EN()                 ADDR_REG_TKCON |= BIT_REG_TKCON_TK0_EN
+#define CLRF_REG_TKCON_TK0_EN()                 ADDR_REG_TKCON &=~BIT_REG_TKCON_TK0_EN
+#define GETF_REG_TKCON_TK0_EN()                 ((ADDR_REG_TKCON & BIT_REG_TKCON_TK0_EN) >> POS_REG_TKCON_TK0_EN)
+// Touch Key 3 Pending Enable
+#define POS_REG_TKCON_TK3_PND_EN                9
+#define BIT_REG_TKCON_TK3_PND_EN                0x200
+#define SETF_REG_TKCON_TK3_PND_EN()             ADDR_REG_TKCON |= BIT_REG_TKCON_TK3_PND_EN
+#define CLRF_REG_TKCON_TK3_PND_EN()             ADDR_REG_TKCON &= ~BIT_REG_TKCON_TK3_PND_EN
+#define GETF_REG_TKCON_TK3_PND_EN()             ((ADDR_REG_TKCON & BIT_REG_TKCON_TK3_PND_EN) >> POS_REG_TKCON_TK3_PND_EN)
+// Touch Key 2 Pending Enable
+#define POS_REG_TKCON_TK2_PND_EN                8
+#define BIT_REG_TKCON_TK2_PND_EN                0x100
+#define SETF_REG_TKCON_TK2_PND_EN()             ADDR_REG_TKCON |= BIT_REG_TKCON_TK2_PND_EN
+#define CLRF_REG_TKCON_TK2_PND_EN()             ADDR_REG_TKCON &= ~BIT_REG_TKCON_TK2_PND_EN
+#define GETF_REG_TKCON_TK2_PND_EN()             ((ADDR_REG_TKCON & BIT_REG_TKCON_TK2_PND_EN) >> POS_REG_TKCON_TK2_PND_EN)
+// Touch Key 1 Pending Enable
+#define POS_REG_TKCON_TK1_PND_EN                7
+#define BIT_REG_TKCON_TK1_PND_EN                0x80
+#define SETF_REG_TKCON_TK1_PND_EN()             ADDR_REG_TKCON |= BIT_REG_TKCON_TK1_PND_EN
+#define CLRF_REG_TKCON_TK1_PND_EN()             ADDR_REG_TKCON &= ~BIT_REG_TKCON_TK1_PND_EN
+#define GETF_REG_TKCON_TK1_PND_EN()             ((ADDR_REG_TKCON & BIT_REG_TKCON_TK1_PND_EN) >> POS_REG_TKCON_TK1_PND_EN)
+// Touch Key 0 Pending Enable
+#define POS_REG_TKCON_TK0_PND_EN                6
+#define BIT_REG_TKCON_TK0_PND_EN                0x40
+#define SETF_REG_TKCON_TK0_PND_EN()             ADDR_REG_TKCON |= BIT_REG_TKCON_TK0_PND_EN
+#define CLRF_REG_TKCON_TK0_PND_EN()             ADDR_REG_TKCON &= ~BIT_REG_TKCON_TK0_PND_EN
+#define GETF_REG_TKCON_TK0_PND_EN()             ((ADDR_REG_TKCON & BIT_REG_TKCON_TK0_PND_EN) >> POS_REG_TKCON_TK0_PND_EN)
+// Touch Key Pin Select
+#define POS_REG_TKCON_TKSEL                     4
+#define BIT_REG_TKCON_TKSEL                     0x30
+#define SET_REG_TKCON_TKSEL(val)                ADDR_REG_TKCON = ((ADDR_REG_TKCON & (~BIT_REG_TKCON_TKSEL)) | ((val) << POS_REG_TKCON_TKSEL))
+#define GET_REG_TKCON_TKSEL()                   ((ADDR_REG_TKCON & BIT_REG_TKCON_TKSEL) >> POS_REG_TKCON_TKSEL)
+// Touch Key Or Touch Ear New base_cnt Select BIT For Small Update
+#define POS_REG_TKCON_BCNTSEL                   1
+#define BIT_REG_TKCON_BCNTSEL                   0x2
+#define SETF_REG_TKCON_BCNTSEL()                ADDR_REG_TKCON |= BIT_REG_TKCON_BCNTSEL
+#define CLRF_REG_TKCON_BCNTSEL()                ADDR_REG_TKCON &= ~BIT_REG_TKCON_BCNTSEL
+#define GETF_REG_TKCON_BCNTSEL()                ((ADDR_REG_TKCON & BIT_REG_TKCON_BCNTSEL) >> POS_REG_TKCON_BCNTSEL)
+// Touch Key Enable
+#define POS_REG_TKCON_TKEN                      0
+#define BIT_REG_TKCON_TKEN                      0x1
+#define SETF_REG_TKCON_TKEN()                   ADDR_REG_TKCON |= BIT_REG_TKCON_TKEN
+#define CLRF_REG_TKCON_TKEN()                   ADDR_REG_TKCON &= ~BIT_REG_TKCON_TKEN
+#define GETF_REG_TKCON_TKEN()                   ((ADDR_REG_TKCON & BIT_REG_TKCON_TKEN) >> POS_REG_TKCON_TKEN)
+
+// Touch Key Control Register 1
+#define ADDR_REG_TKCON1                          *(volatile unsigned long*) (SFR10_BASE + 0x03*4)
+// Touch Key CLK2M Divide 2 Select
+#define POS_REG_TKCON1_DIV2SEL                  25
+#define BIT_REG_TKCON1_DIV2SEL                  0x2000000
+#define SETF_REG_TKCON1_DIV2SEL()               ADDR_REG_TKCON1 |= BIT_REG_TKCON1_DIV2SEL
+#define CLRF_REG_TKCON1_DIV2SEL()               ADDR_REG_TKCON1 &= ~BIT_REG_TKCON1_DIV2SEL
+#define GETF_REG_TKCON1_DIV2SEL()               ((ADDR_REG_TKCON1 & BIT_REG_TKCON1_DIV2SEL) >> POS_REG_TKCON1_DIV2SEL)
+// Touch Key Clock Enable
+#define POS_REG_TKCON1_TKCEN                    23
+#define BIT_REG_TKCON1_TKCEN                    0x800000
+#define SETF_REG_TKCON1_TKCEN()                 ADDR_REG_TKCON1 |= BIT_REG_TKCON1_TKCEN
+#define CLRF_REG_TKCON1_TKCEN()                 ADDR_REG_TKCON1 &= ~BIT_REG_TKCON1_TKCEN
+#define GETF_REG_TKCON1_TKCEN()                 ((ADDR_REG_TKCON1 & BIT_REG_TKCON1_TKCEN) >> POS_REG_TKCON1_TKCEN)
+// Touch Key Variance Clock Enable
+#define POS_REG_TKCON1_TKVCEN                   22
+#define BIT_REG_TKCON1_TKVCEN                   0x400000
+#define SETF_REG_TKCON1_TKVCEN()                ADDR_REG_TKCON1 |= BIT_REG_TKCON1_TKVCEN
+#define CLRF_REG_TKCON1_TKVCEN()                ADDR_REG_TKCON1 &= ~BIT_REG_TKCON1_TKVCEN
+#define GETF_REG_TKCON1_TKVCEN()                ((ADDR_REG_TKCON1 & BIT_REG_TKCON1_TKVCEN) >> POS_REG_TKCON1_TKVCEN)
+// Touch Key Each Channel Time. Counter Clock Is 256 Divider From CLK2M.
+#define POS_REG_TKCON1_TKCLK2MDIV               16
+#define BIT_REG_TKCON1_TKCLK2MDIV               0x1F0000
+#define SET_REG_TKCON1_TKCLK2MDIV(val)          ADDR_REG_TKCON1 = ((ADDR_REG_TKCON1 & (~BIT_REG_TKCON1_TKCLK2MDIV)) | ((val) << POS_REG_TKCON1_TKCLK2MDIV))
+#define GET_REG_TKCON1_TKCLK2MDIV()             ((ADDR_REG_TKCON1 & BIT_REG_TKCON1_TKCLK2MDIV) >> POS_REG_TKCON1_TKCLK2MDIV)
+// Touch Key Analog Enable
+#define POS_REG_TKCON1_TKAEN                    13
+#define BIT_REG_TKCON1_TKAEN                    0x2000
+#define SETF_REG_TKCON1_TKAEN()                 ADDR_REG_TKCON1 |= BIT_REG_TKCON1_TKAEN
+#define CLRF_REG_TKCON1_TKAEN()                 ADDR_REG_TKCON1 &= ~BIT_REG_TKCON1_TKAEN
+#define GETF_REG_TKCON1_TKAEN()                 ((ADDR_REG_TKCON1 & BIT_REG_TKCON1_TKAEN) >> POS_REG_TKCON1_TKAEN)
+// Touch Key---Reference to pinlist, TK Reference Voltage Select Bit, 0x00/0x01/0x10/0x11-1.0/1.1/1.2/1.3
+#define POS_REG_TKCON1_TKARTRIM                 0
+#define BIT_REG_TKCON1_TKARTRIM                 0x3
+#define SET_REG_TKCON1_TKARTRIM(val)            ADDR_REG_TKCON1 = ((ADDR_REG_TKCON1 & (~BIT_REG_TKCON1_TKARTRIM)) | ((val) << POS_REG_TKCON1_TKARTRIM))
+#define GET_REG_TKCON1_TKARTRIM()               ((ADDR_REG_TKCON1 & BIT_REG_TKCON1_TKARTRIM) >> POS_REG_TKCON1_TKARTRIM)
+
+// Touch Key Charge And Discharge Period Register 0, ###Read only
+#define ADDR_REG_TKCDPR0                        *(volatile unsigned long*) (SFR10_BASE + 0x05*4)
+// Touch Key Channel 1 Charge And Discharge Period, Can't Be Longer Than 500Hz
+// (TKCDPR + 1) * (One Cycle TKCNT) * (CLK2M_TK Frequency)
+#define POS_REG_TKCDPR0_TKCDPR1                 16
+#define BIT_REG_TKCDPR0_TKCDPR1                 0x3FF0000
+//#define SET_REG_TKCDPR0_TKCDPR1(val)            ADDR_REG_TKCDPR0 = ((ADDR_REG_TKCDPR0 & (~BIT_REG_TKCDPR0_TKCDPR1)) | ((val) << POS_REG_TKCDPR0_TKCDPR1))
+//#define GET_REG_TKCDPR0_TKCDPR1()               ((ADDR_REG_TKCDPR0 & BIT_REG_TKCDPR0_TKCDPR1) >> POS_REG_TKCDPR0_TKCDPR1)
+// Touch Key Channel 0 Charge And Discharge Period, Can't Be Longer Than 500Hz
+// (TKCDPR + 1) * (One Cycle TKCNT) * (CLK2M_TK Frequency)
+#define POS_REG_TKCDPR0_TKCDPR0                 0
+#define BIT_REG_TKCDPR0_TKCDPR0                 0x3FF
+//#define SET_REG_TKCDPR0_TKCDPR0(val)            ADDR_REG_TKCDPR0 = ((ADDR_REG_TKCDPR0 & (~BIT_REG_TKCDPR0_TKCDPR0)) | ((val) << POS_REG_TKCDPR0_TKCDPR0))
+//#define GET_REG_TKCDPR0_TKCDPR0()               ((ADDR_REG_TKCDPR0 & BIT_REG_TKCDPR0_TKCDPR0) >> POS_REG_TKCDPR0_TKCDPR0)
+
+// Touch Key Charge And Discharge Period Register 1, ###Read only
+#define ADDR_REG_TKCDPR1                        *(volatile unsigned long*) (SFR10_BASE + 0x06*4)
+// Touch Key Channel 3 Charge And Discharge Period, Can't Be Longer Than 500Hz
+// (TKCDPR + 1) * (One Cycle TKCNT) * (CLK2M_TK Frequency)
+#define POS_REG_TKCDPR1_TKCDPR3                 16
+#define BIT_REG_TKCDPR1_TKCDPR3                 0x3FF0000
+//#define SET_REG_TKCDPR1_TKCDPR3(val)            ADDR_REG_TKCDPR1 = ((ADDR_REG_TKCDPR1 & (~BIT_REG_TKCDPR1_TKCDPR3)) | ((val) << POS_REG_TKCDPR1_TKCDPR3))
+//#define GET_REG_TKCDPR1_TKCDPR3()               ((ADDR_REG_TKCDPR1 & BIT_REG_TKCDPR1_TKCDPR3) >> POS_REG_TKCDPR1_TKCDPR3)
+// Touch Key Channel 2 Charge And Discharge Period, Can't Be Longer Than 500Hz
+// (TKCDPR + 1) * (One Cycle TKCNT) * (CLK2M_TK Frequency)
+#define POS_REG_TKCDPR1_TKCDPR2                 0
+#define BIT_REG_TKCDPR1_TKCDPR2                 0x3FF
+//#define SET_REG_TKCDPR1_TKCDPR2(val)            ADDR_REG_TKCDPR1 = ((ADDR_REG_TKCDPR1 & (~BIT_REG_TKCDPR1_TKCDPR2)) | ((val) << POS_REG_TKCDPR1_TKCDPR2))
+//#define GET_REG_TKCDPR1_TKCDPR2()               ((ADDR_REG_TKCDPR1 & BIT_REG_TKCDPR1_TKCDPR2) >> POS_REG_TKCDPR1_TKCDPR2)
+
+// Touch Key Base Counter Register
+#define ADDR_REG_TKBCNT                         *(volatile unsigned long*) (SFR10_BASE + 0x09*4)
+// Touch Key Base Counter Average Value
+#define POS_REG_TKBCNT_TKBCNT_AVG               12
+#define BIT_REG_TKBCNT_TKBCNT_AVG               0xFFF000
+#define SET_REG_TKBCNT_TKBCNT_AVG(val)          ADDR_REG_TKBCNT = ((ADDR_REG_TKBCNT & (~BIT_REG_TKBCNT_TKBCNT_AVG)) | ((val) << POS_REG_TKBCNT_TKBCNT_AVG))
+#define GET_REG_TKBCNT_TKBCNT_AVG()             ((ADDR_REG_TKBCNT & BIT_REG_TKBCNT_TKBCNT_AVG) >> POS_REG_TKBCNT_TKBCNT_AVG)
+// Touch Key Base Counter
+#define POS_REG_TKBCNT_TKBCNT                   0
+#define BIT_REG_TKBCNT_TKBCNT                   0xFFF
+#define SET_REG_TKBCNT_TKBCNT(val)              ADDR_REG_TKBCNT = ((ADDR_REG_TKBCNT & (~BIT_REG_TKBCNT_TKBCNT)) | ((val) << POS_REG_TKBCNT_TKBCNT))
+#define GET_REG_TKBCNT_TKBCNT()                 ((ADDR_REG_TKBCNT & BIT_REG_TKBCNT_TKBCNT) >> POS_REG_TKBCNT_TKBCNT)
+
+// Touch Key Press Threshold Register
+#define ADDR_REG_TKPTHD                         *(volatile unsigned long*) (SFR10_BASE + 0x0a*4)
+// Touch Key Press Time Out
+#define POS_REG_TKPTHD_PTO                      28
+#define BIT_REG_TKPTHD_PTO                      0xF0000000
+#define SET_REG_TKPTHD_PTO(val)                 ADDR_REG_TKPTHD = ((ADDR_REG_TKPTHD & (~BIT_REG_TKPTHD_PTO)) | ((val) << POS_REG_TKPTHD_PTO))
+#define GET_REG_TKPTHD_PTO()                    ((ADDR_REG_TKPTHD & BIT_REG_TKPTHD_PTO) >> POS_REG_TKPTHD_PTO)
+// Touch Key Release Thresohld
+#define POS_REG_TKPTHD_RTHD                     16
+#define BIT_REG_TKPTHD_RTHD                     0xFFF0000
+#define SET_REG_TKPTHD_RTHD(val)                ADDR_REG_TKPTHD = ((ADDR_REG_TKPTHD & (~BIT_REG_TKPTHD_RTHD)) | ((val) << POS_REG_TKPTHD_RTHD))
+#define GET_REG_TKPTHD_RTHD()                   ((ADDR_REG_TKPTHD & BIT_REG_TKPTHD_RTHD) >> POS_REG_TKPTHD_RTHD)
+// Touch Key Press Thresohld
+#define POS_REG_TKPTHD_PTHD                     0
+#define BIT_REG_TKPTHD_PTHD                     0xFFF
+#define SET_REG_TKPTHD_PTHD(val)                ADDR_REG_TKPTHD = ((ADDR_REG_TKPTHD & (~BIT_REG_TKPTHD_PTHD)) | ((val) << POS_REG_TKPTHD_PTHD))
+#define GET_REG_TKPTHD_PTHD()                   ((ADDR_REG_TKPTHD & BIT_REG_TKPTHD_PTHD) >> POS_REG_TKPTHD_PTHD)
+
+// Touch Key Exception Threshold Register
+#define ADDR_REG_TKETHD                         *(volatile unsigned long*) (SFR10_BASE + 0x0b*4)
+// Touch Key Larger Threshold
+#define POS_REG_TKETHD_LTHD                     16
+#define BIT_REG_TKETHD_LTHD                     0xFFF0000
+#define SET_REG_TKETHD_LTHD(val)                ADDR_REG_TKETHD = ((ADDR_REG_TKETHD & (~BIT_REG_TKETHD_LTHD)) | ((val) << POS_REG_TKETHD_LTHD))
+#define GET_REG_TKETHD_LTHD()                   ((ADDR_REG_TKETHD & BIT_REG_TKETHD_LTHD) >> POS_REG_TKETHD_LTHD)
+// Touch Key Smaller Threshold
+#define POS_REG_TKETHD_STHD                     0
+#define BIT_REG_TKETHD_STHD                     0xFFF
+#define SET_REG_TKETHD_STHD(val)                ADDR_REG_TKETHD = ((ADDR_REG_TKETHD & (~BIT_REG_TKETHD_STHD)) | ((val) << POS_REG_TKETHD_STHD))
+#define GET_REG_TKETHD_STHD()                   ((ADDR_REG_TKETHD & BIT_REG_TKETHD_STHD) >> POS_REG_TKETHD_STHD)
+
+// Touch Key Analog Control Register 0
+#define ADDR_REG_TKACON0                        *(volatile unsigned long*) (SFR10_BASE + 0x12*4)
+// Touch Key Channel 1 ENCHN
+#define POS_REG_TKACON0_ENCHN1                  23
+#define BIT_REG_TKACON0_ENCHN1                  0x800000
+#define SETF_REG_TKACON0_ENCHN1()               ADDR_REG_TKACON0 |= BIT_REG_TKACON0_ENCHN1
+#define CLRF_REG_TKACON0_ENCHN1()               ADDR_REG_TKACON0 &= ~BIT_REG_TKACON0_ENCHN1
+#define GETF_REG_TKACON0_ENCHN1()               ((ADDR_REG_TKACON0 & BIT_REG_TKACON0_ENCHN1) >> POS_REG_TKACON0_ENCHN1)
+// Touch Key Channel 1 ITRIM Select, TK Charge Current Select Signal, 3.84u/1.92u/0.96u/0.48u/0.24u
+#define POS_REG_TKACON0_ITRIM1                  18
+#define BIT_REG_TKACON0_ITRIM1                  0x7C0000
+#define SET_REG_TKACON0_ITRIM1(val)             ADDR_REG_TKACON0 = ((ADDR_REG_TKACON0 & (~BIT_REG_TKACON0_ITRIM1)) | ((val) << POS_REG_TKACON0_ITRIM1))
+#define GET_REG_TKACON0_ITRIM1()                ((ADDR_REG_TKACON0 & BIT_REG_TKACON0_ITRIM1) >> POS_REG_TKACON0_ITRIM1)
+// Touch Key Channel 1 CTRIM Select, TK Internal Capacitance Select, 3.2p/1.6p/800f/400f/200f/200f
+#define POS_REG_TKACON0_CTRIM1                  12
+#define BIT_REG_TKACON0_CTRIM1                  0x3F000
+#define SET_REG_TKACON0_CTRIM1(val)             ADDR_REG_TKACON0 = ((ADDR_REG_TKACON0 & (~BIT_REG_TKACON0_CTRIM1)) | ((val) << POS_REG_TKACON0_CTRIM1))
+#define GET_REG_TKACON0_CTRIM1()                ((ADDR_REG_TKACON0 & BIT_REG_TKACON0_CTRIM1) >> POS_REG_TKACON0_CTRIM1)
+// Touch Key Channel 0 ENCHN
+#define POS_REG_TKACON0_ENCHN0                  11
+#define BIT_REG_TKACON0_ENCHN0                  0x800
+#define SETF_REG_TKACON0_ENCHN0()               ADDR_REG_TKACON0 |= BIT_REG_TKACON0_ENCHN0
+#define CLRF_REG_TKACON0_ENCHN0()               ADDR_REG_TKACON0 &= ~BIT_REG_TKACON0_ENCHN0
+#define GETF_REG_TKACON0_ENCHN0()               ((ADDR_REG_TKACON0 & BIT_REG_TKACON0_ENCHN0) >> POS_REG_TKACON0_ENCHN0)
+// Touch Key Channel 0 ITRIM Select, TK Charge Current Select Signal, 3.84u/1.92u/0.96u/0.48u/0.24u
+#define POS_REG_TKACON0_ITRIM0                  6
+#define BIT_REG_TKACON0_ITRIM0                  0x7C0
+#define SET_REG_TKACON0_ITRIM0(val)             ADDR_REG_TKACON0 = ((ADDR_REG_TKACON0 & (~BIT_REG_TKACON0_ITRIM0)) | ((val) << POS_REG_TKACON0_ITRIM0))
+#define GET_REG_TKACON0_ITRIM0()                  ((ADDR_REG_TKACON0 & BIT_REG_TKACON0_ITRIM0) >> POS_REG_TKACON0_ITRIM0)
+// Touch Key Channel 0 CTRIM Select, 3.2p/1.6p/800f/400f/200f/200f
+#define POS_REG_TKACON0_CTRIM0                  0
+#define BIT_REG_TKACON0_CTRIM0                  0x3F
+#define SET_REG_TKACON0_CTRIM0(val)             ADDR_REG_TKACON0 = ((ADDR_REG_TKACON0 & (~BIT_REG_TKACON0_CTRIM0)) | ((val) << POS_REG_TKACON0_CTRIM0))
+#define GET_REG_TKACON0_CTRIM0()                ((ADDR_REG_TKACON0 & BIT_REG_TKACON0_CTRIM0) >> POS_REG_TKACON0_CTRIM0)
+
+// Touch Key Analog Control Register 1
+#define ADDR_REG_TKACON1                        *(volatile unsigned long*) (SFR10_BASE + 0x13*4)
+// Touch Key Channel 3 ENCHN
+#define POS_REG_TKACON1_ENCHN3                  23
+#define BIT_REG_TKACON1_ENCHN3                  0x800000
+#define SETF_REG_TKACON1_ENCHN3()               ADDR_REG_TKACON1 |= BIT_REG_TKACON1_ENCHN3
+#define CLRF_REG_TKACON1_ENCHN3()               ADDR_REG_TKACON1 &= ~BIT_REG_TKACON1_ENCHN3
+#define GETF_REG_TKACON1_ENCHN3()               ((ADDR_REG_TKACON1 & BIT_REG_TKACON1_ENCHN3) >> POS_REG_TKACON1_ENCHN3)
+// Touch Key Channel 3 ITRIM Select, TK Charge Current Select Signal, 3.84u/1.92u/0.96u/0.48u/0.24u
+#define POS_REG_TKACON1_ITRIM3                  18
+#define BIT_REG_TKACON1_ITRIM3                  0x7C0000
+#define SET_REG_TKACON1_ITRIM3(val)             ADDR_REG_TKACON1 = ((ADDR_REG_TKACON1 & (~BIT_REG_TKACON1_ITRIM3)) | ((val) << POS_REG_TKACON1_ITRIM3))
+#define GET_REG_TKACON1_ITRIM3()                ((ADDR_REG_TKACON1 & BIT_REG_TKACON1_ITRIM3) >> POS_REG_TKACON1_ITRIM3)
+// Touch Key Channel 3 CTRIM Select, 3.2p/1.6p/800f/400f/200f/200f
+#define POS_REG_TKACON1_CTRIM3                  12
+#define BIT_REG_TKACON1_CTRIM3                  0x3F000
+#define SET_REG_TKACON1_CTRIM3(val)             ADDR_REG_TKACON1 = ((ADDR_REG_TKACON1 & (~BIT_REG_TKACON1_CTRIM3)) | ((val) << POS_REG_TKACON1_CTRIM3))
+#define GET_REG_TKACON1_CTRIM3()                ((ADDR_REG_TKACON1 & BIT_REG_TKACON1_CTRIM3) >> POS_REG_TKACON1_CTRIM3)
+// Touch Key Channel 2 ENCHN
+#define POS_REG_TKACON1_ENCHN2                  11
+#define BIT_REG_TKACON1_ENCHN2                  0x800
+#define SETF_REG_TKACON1_ENCHN2()               ADDR_REG_TKACON1 |= BIT_REG_TKACON1_ENCHN2
+#define CLRF_REG_TKACON1_ENCHN2()               ADDR_REG_TKACON1 &= ~BIT_REG_TKACON1_ENCHN2
+#define GETF_REG_TKACON1_ENCHN2()               ((ADDR_REG_TKACON1 & BIT_REG_TKACON1_ENCHN2) >> POS_REG_TKACON1_ENCHN2)
+// Touch Key Channel 2 ITRIM Select, TK Charge Current Select Signal, 3.84u/1.92u/0.96u/0.48u/0.24u
+#define POS_REG_TKACON1_ITRIM2                  6
+#define BIT_REG_TKACON1_ITRIM2                  0x7C0
+#define SET_REG_TKACON1_ITRIM2(val)             ADDR_REG_TKACON1 = ((ADDR_REG_TKACON1 & (~BIT_REG_TKACON1_ITRIM2)) | ((val) << POS_REG_TKACON1_ITRIM2))
+#define GET_REG_TKACON1_ITRIM2()                ((ADDR_REG_TKACON1 & BIT_REG_TKACON1_ITRIM2) >> POS_REG_TKACON1_ITRIM2)
+// Touch Key Channel 2 CTRIM Select, 3.2p/1.6p/800f/400f/200f/200f
+#define POS_REG_TKACON1_CTRIM2                  0
+#define BIT_REG_TKACON1_CTRIM2                  0x3F
+#define SET_REG_TKACON1_CTRIM2(val)             ADDR_REG_TKACON1 = ((ADDR_REG_TKACON1 & (~BIT_REG_TKACON1_CTRIM2)) | ((val) << POS_REG_TKACON1_CTRIM2))
+#define GET_REG_TKACON1_CTRIM2()                ((ADDR_REG_TKACON1 & BIT_REG_TKACON1_CTRIM2) >> POS_REG_TKACON1_CTRIM2)
+
+/*
+ * FUNCTION DECLARATION
+ ***************************************************************************
+ */
+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);
+void touch_key_tkcnt_isr(u32 tk_ch, u16 tkcnt);
+void touch_key_range_isr(u32 tk_ch, u16 tkcnt);
+u8 touch_key_get_key(void);
+void tkey_bcnt_range_exception(tk_cb_t *s, u16 tkcnt);
+void touch_key_sw_reset(void);
+
+#ifdef __cpluscplus
+}
+#endif
+
+#endif

+ 285 - 0
driver/driver_uart.c

@@ -0,0 +1,285 @@
+/*
+ * @File name    : driver_uart.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-14
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the UART peripheral.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#include "driver_uart.h"
+
+/**
+  * @brief  Initializes the uart peripheral according to the specified
+  *         parameters in the uart_init_struct.
+  * @param  uartx: where x can be (0..2) to select the uartx peripheral.
+  * @param  uart_init_struct: pointer to a uart_init_typedef structure that
+  *         contains the configuration information for the specified UART peripheral.
+  * @retval None
+  */
+void uart_init(uart_typedef *uartx, uart_init_typedef* uart_init_struct)
+{
+    uint32_t tmp_reg, sys_clk_val, baud_reg;
+
+    //---------- UART Controller Register ----------//
+    tmp_reg = uartx->con;
+    tmp_reg &= (uint32_t)(~UARTxCON_RXEN);
+    tmp_reg &= (uint32_t)(~UARTxCON_ONELINE);
+    tmp_reg &= (uint32_t)(~UARTxCON_BIT9EN);
+    tmp_reg &= (uint32_t)(~UARTxCON_SB2EN);
+    tmp_reg |= (uint32_t)(uart_init_struct->mode |
+                          uart_init_struct->one_line_enable |
+                          uart_init_struct->stop_bits |
+                          uart_init_struct->word_len);
+
+    if (uartx == UART) {
+        tmp_reg &= (uint32_t)(~UARTxCON_CLKSRC);
+        tmp_reg |= (uint32_t)(uart_init_struct->clock_source);
+    } else if (uartx == UDET) {
+        tmp_reg &= (uint32_t)(~UARTxCON_FIXBAUD);
+        tmp_reg |= (uint32_t)(uart_init_struct->baud_fix);
+    }
+
+    uartx->con = tmp_reg;
+
+    if (uartx == UART) {
+        //---------- UART Baud Configuration ----------//
+        sys_clk_val = sys_clk_nhz_get();
+        if (uart_init_struct->clock_source == UART_SYSTEM_CLOCK) {
+            baud_reg = (uint16_t)((sys_clk_val / uart_init_struct->baud) - 1);
+        } else {
+            // uart clk is double frequency of the clock source when select uart_inc
+            sys_clk_val = 2 * clk_uart_inc_get(CLK_VALUE_MODE_FREQ);
+            baud_reg = (uint16_t)((sys_clk_val / uart_init_struct->baud) - 1);
+        }
+        tmp_reg = (uint32_t)((baud_reg << 16) | baud_reg);
+        uartx->baud = tmp_reg;
+    } else if (uartx == UDET && uart_init_struct->baud_fix == UART_BAUD_FIX) {
+        sys_clk_val = clk_udet_clk_get(CLK_VALUE_MODE_FREQ);
+        baud_reg = (uint16_t)((sys_clk_val / uart_init_struct->baud) - 1);
+        uartx->baud = baud_reg;
+    }
+}
+
+/**
+ * @brief  De-initialize the specified uart peripheral.
+ * @param  uartx: which uart need to config. it should the one of [UART or UDET].
+ * @retval None
+ */
+void uart_deinit(uart_typedef *uartx)
+{
+    uartx->con = 0;
+
+    if (uartx == UART) {
+        clk_gate0_cmd(CLK_GATE0_UART, CLK_DIS);
+    } else if (uartx == UDET) {
+        clk_gate0_cmd(CLK_GATE0_UDET, CLK_DIS);
+    }
+}
+
+/**
+  * @brief  Enable or disable the specified UART peripheral.
+  * @param  uartx: where x can be (0..2) to select the uartx peripheral.
+  * @param  state: the state of the UARTx peripheral.
+  *         this parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void uart_cmd(uart_typedef *uartx, FUNCTIONAL_STATE state)
+{
+    if (state != DISABLE) {
+        uartx->con |= UARTxCON_UTEN;
+    } else {
+        uartx->con &= (uint32_t)(~UARTxCON_UTEN);
+    }
+}
+
+/**
+  * @brief  Transmits data through the UARTx peripheral.
+  * @param  uartx: where x can be (0..2) to select the uartx peripheral.
+  * @param  data: the data to transmit.
+  * @retval None
+  */
+AT(.com_periph.uart.send)
+void uart_send_data(uart_typedef *uartx, uint16_t data)
+{
+    uartx->data = (data & (uint16_t)0xff);
+}
+
+/**
+  * @brief  Return the received data lastly by the UARTx peripheral.
+  * @param  uartx: where x can be (0..2) to select the uartx peripheral.
+  * @retval The received data.
+  */
+AT(.com_periph.uart.recv)
+uint16_t uart_receive_data(uart_typedef *uartx)
+{
+    if (uartx->con & UARTxCON_BIT9EN) {
+        return (uartx->data & (uint16_t)0x1ff);
+    } else {
+        return (uartx->data & (uint16_t)0xff);
+    }
+}
+
+/**
+  * @brief  Enable or disable the specified UARTx interrupt.
+  * @param  uartx: where x can be (0..2) to select the uartx peripheral.
+  * @param  isr: Function to be executed for service interruption.
+  * @param  pr: Priority of service interruption.
+  * @param  interrupt_type: specifies the UART interrupt sources to be enable or disable.
+  *         this parameter can be one of the following values:
+  *             @arg UART_IT_TX: Transmit single data finish interrupt enable bit.
+  *             @arg UART_IT_RX: Receive single data finish interrupt enable bit.
+  *             @arg UART_IT_ERR: Raise error interrupt enable bit.
+  *             @arg UART_IT_KEY: Match key interrupt enable bit.
+  *             @arg UART_IT_RSTKEY: Reset match key interrupt enable bit.
+  * @param  state: the state of the UARTx peripheral.
+  *         this parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void uart_pic_config(uart_typedef *uartx, isr_t isr, int pr, UART_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state)
+{
+    uint32_t interrupt_con_bit = 0;
+    uint32_t all_interrupt_type_mask = UART_IT_TX | UART_IT_RX | UART_IT_ERR | UART_IT_KEY | UART_IT_RSTKEY;
+
+    if (interrupt_type == 0) {
+        return;
+    }
+
+    if (interrupt_type & UART_IT_TX) {
+        interrupt_con_bit |= UARTxCON_TXIE;
+    }
+
+    if (interrupt_type & UART_IT_RX) {
+        interrupt_con_bit |= UARTxCON_RXIE;
+    }
+
+    if (interrupt_type & UART_IT_ERR) {
+    }
+
+    if (interrupt_type & UART_IT_KEY) {
+    }
+
+    if (interrupt_type & UART_IT_RSTKEY) {
+    }
+
+    if (state != DISABLE) {
+        sys_irq_init(IRQn_UART0_UDET, pr, isr);
+        uartx->con |= interrupt_con_bit;
+    } else {
+        uartx->con &= ~interrupt_con_bit;
+        if (interrupt_type == all_interrupt_type_mask) {
+            PICEN &= ~BIT(IRQn_UART0_UDET);
+        }
+    }
+}
+
+/**
+  * @brief  Check the specified UART flag is set or not.
+  * @param  uartx: where x can be (0..2) to select the uartx peripheral.
+  * @param  interrupt_type: specifies the flag to check.
+  *         this parameter can be one of the following values:
+  *             @arg UART_IT_TX: Transmit single data finish interrupt enable bit.
+  *             @arg UART_IT_RX: Receive single data finish interrupt enable bit.
+  *             @arg UART_IT_ERR: Raise error interrupt enable bit.
+  *             @arg UART_IT_KEY: Match key interrupt enable bit.
+  *             @arg UART_IT_RSTKEY: Reset match key interrupt enable bit.
+  * @retval The state of uart_flag (SET or RESET).
+  */
+AT(.com_periph.uart.get_flag)
+FLAG_STATE uart_get_flag(uart_typedef *uartx, UART_IT_TYPEDEF interrupt_type)
+{
+    uint32_t interrupt_con_bit = 0;
+
+    if (interrupt_type & UART_IT_TX) {
+        interrupt_con_bit |= UARTxCON_TXPND;
+    }
+
+    if (interrupt_type & UART_IT_RX) {
+        interrupt_con_bit |= UARTxCON_RXPND;
+    }
+
+    if (interrupt_type & UART_IT_ERR) {
+    }
+
+    if (interrupt_type & UART_IT_KEY) {
+    }
+
+    if (interrupt_type & UART_IT_RSTKEY) {
+    }
+
+    if ((uartx->con & interrupt_con_bit) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+  * @brief  Clear the UART's pending flag.
+  * @param  uartx: where x can be (0..2) to select the uartx peripheral.
+  * @param  interrupt_type: specifies the flag to check.
+  *         this parameter can be one of the following values:
+  *             @arg UART_IT_TX: Transmit single data finish interrupt enable bit.
+  *             @arg UART_IT_RX: Receive single data finish interrupt enable bit.
+  *             @arg UART_IT_ERR: Raise error interrupt enable bit.
+  *             @arg UART_IT_KEY: Match key interrupt enable bit.
+  *             @arg UART_IT_RSTKEY: Reset match key interrupt enable bit.
+  * @retval None
+  */
+AT(.com_periph.uart.clear_flag)
+void uart_clear_flag(uart_typedef *uartx, UART_IT_TYPEDEF interrupt_type)
+{
+    uint32_t interrupt_con_bit = 0;
+
+    if (interrupt_type & UART_IT_TX) {
+        interrupt_con_bit |= UARTxCPND_CTXPND;
+    }
+
+    if (interrupt_type & UART_IT_RX) {
+        interrupt_con_bit |= UARTxCPND_CRXPND;
+    }
+
+    if (interrupt_type & UART_IT_ERR) {
+        interrupt_con_bit |= UARTxCPND_RX4BUF_ERR_CLR;
+    }
+
+    if (interrupt_type & UART_IT_KEY) {
+        interrupt_con_bit |= UARTxCPND_CKEYPND;
+    }
+
+    if (interrupt_type & UART_IT_RSTKEY) {
+        interrupt_con_bit |= UARTxCPND_CRSTKEYPND;
+    }
+
+    uartx->cpnd |= interrupt_con_bit;
+}
+
+/**
+ * @brief  Config the baud rate of the serial port.
+ * @param  uartx: The uart that need to config.
+ * @param  baud: The baudrate value need to set.
+ * @retval None
+ */
+void uart_baud_config(uart_typedef *uartx, uint32_t baud)
+{
+    uint32_t clk_val, baud_reg;
+
+    if (uartx->con & UARTxCON_UTEN)
+    while ((uartx->con & UARTxCON_TXPND) == 0);
+
+    if (uartx == UART) {
+        if ((uartx->con & UARTxCON_CLKSRC) == 0) {                  // if select is sys clk
+            clk_val = sys_clk_nhz_get();
+        } else {                                                    // if select is inc clk
+            clk_val = 2 * clk_uart_inc_get(CLK_VALUE_MODE_FREQ);    // uart clk is double frequency of the clock source when select uart_inc
+        }
+
+        baud_reg = (uint16_t)((clk_val / baud) - 1);
+        uartx->baud = (uint32_t)((baud_reg << 16) | baud_reg);
+
+    } else if (uartx == UDET && (uartx->con & UARTxCON_FIXBAUD)) {
+        clk_val = clk_udet_clk_get(CLK_VALUE_MODE_FREQ);
+        baud_reg = (uint16_t)((clk_val / baud) - 1);
+        uartx->baud = baud_reg;
+    }
+}

+ 98 - 0
driver/driver_uart.h

@@ -0,0 +1,98 @@
+/*
+ * @File name    : driver_uart.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-14
+ * @Description  : This file contains all the functions prototypes for the UART library.
+ *
+ * Copyright (c) by Bluetrum, All Rights Reserved.
+ */
+#ifndef _DRIVER_UART_H
+#define _DRIVER_UART_H
+
+#include "driver_com.h"
+
+/**
+ * @brief UART IT Flag Definition
+ */
+typedef enum {
+    UART_IT_TX          = 0x01,
+    UART_IT_RX          = 0x02,
+    UART_IT_ERR         = 0x04,
+    UART_IT_KEY         = 0x08,
+    UART_IT_RSTKEY      = 0x10,
+} UART_IT_TYPEDEF;
+
+/**
+ * @brief Rx Enable enumeration
+ */
+typedef enum {
+    UART_SEND_MODE      = 0x00000000,
+    UART_SEND_RECV_MODE = 0x00000080,
+} UART_MODE_TYPEDEF;
+
+/**
+ * @brief One-line Mode Enumeration
+ */
+typedef enum {
+    UART_SEPARATE       = 0x00000000,
+    UART_ONE_LINE       = 0x00000040,
+} UART_ONELINE_TYPEDEF;
+
+/**
+ * @brief Clock select Enumeration
+ */
+typedef enum {
+    UART_SYSTEM_CLOCK   = 0x00000000,
+    UART_INC_CLOCK      = 0x00000020,
+} UART_CLOCK_TYPEDEF;
+
+/**
+ * @brief Stop Bit Select Enumeration
+ */
+typedef enum {
+    UART_STOP_BIT_1BIT  = 0x00000000,
+    UART_STOP_BIT_2BIT  = 0x00000010,
+} UART_STOP_BIT_TYPEDEF;
+
+/**
+ * @brief Word Length Enumeration
+ */
+typedef enum {
+    UART_WORD_LENGTH_8b = 0x00000000,
+    UART_WORD_LENGTH_9b = 0x00000002,
+} UART_WORD_LENGTH;
+
+/**
+ * @brief Baud Fix Enumeration, only UDET Can Use.
+ */
+typedef enum {
+    UART_BAUD_AUTO      = 0x00000000,
+    UART_BAUD_FIX       = 0x00000020,
+} UART_BAUD_FIX_TYPEDEF;
+
+/**
+ * @brief UART Init Structure
+ */
+typedef struct {
+    uint32_t                baud;
+    UART_MODE_TYPEDEF       mode;
+    UART_ONELINE_TYPEDEF    one_line_enable;
+    UART_CLOCK_TYPEDEF      clock_source;
+    UART_STOP_BIT_TYPEDEF   stop_bits;
+    UART_WORD_LENGTH        word_len;
+    /* Only UDET */
+    UART_BAUD_FIX_TYPEDEF   baud_fix;
+} uart_init_typedef;
+
+/************************* Function used to configure UART *************************/
+void uart_init(uart_typedef *uartx, uart_init_typedef *uart_init_struct);
+void uart_deinit(uart_typedef *uartx);
+void uart_cmd(uart_typedef *uartx, FUNCTIONAL_STATE state);
+void uart_send_data(uart_typedef *uartx, uint16_t data);
+uint16_t uart_receive_data(uart_typedef *uartx);
+void uart_pic_config(uart_typedef *uartx, isr_t isr, int pr, UART_IT_TYPEDEF interrupt_type, FUNCTIONAL_STATE state);
+FLAG_STATE uart_get_flag(uart_typedef *uartx, UART_IT_TYPEDEF interrupt_type);
+void uart_clear_flag(uart_typedef *uartx, UART_IT_TYPEDEF interrupt_type);
+void uart_baud_config(uart_typedef *uartx, uint32_t baud);
+
+#endif // _DRIVER_UART_H

+ 148 - 0
driver/driver_wdt.c

@@ -0,0 +1,148 @@
+/*
+ * @File name    : driver_wdt.c
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-15
+ * @Description  : This file provides functions to manage the most functionalities
+ *                 of the WDT peripheral.
+ * 
+ * Copyright (c) by Bluetrum, All Rights reserved.
+ */
+#include "driver_wdt.h"
+
+/**
+  * @brief  Enable or disable the WDT peripheral.
+  * @param  state: the state of the WDT peripheral.
+  *         this parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void wdt_cmd(FUNCTIONAL_STATE state)
+{
+    uint32_t temp_reg = WDT->con;
+
+    if (state) {
+        temp_reg |= WDTCON_WDTEN_WR_0;
+    } else {
+        temp_reg &= ~WDTCON_WDTEN_WR;
+        temp_reg |= (uint32_t)(0x0a << 4);
+    }
+
+    WDT->con = temp_reg;
+}
+
+/**
+  * @brief  Enable or disable the WDT reset.
+  * @param  state: the state of the WDT reset.
+  *         this parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void wdt_reset_cmd(FUNCTIONAL_STATE state)
+{
+    uint32_t temp_reg = WDT->con;
+
+    if (state) {
+        temp_reg |= WDTCON_RSTEN_WR_0;
+    } else {
+        temp_reg &= ~WDTCON_RSTEN_WR;
+        temp_reg |= (uint32_t)(0x0a << 8);
+    }
+
+    WDT->con = temp_reg;
+}
+
+/**
+  * @brief  Enable or disable the WDT interrupt.
+  * @param  state: the state of the WDT interrupt.
+  *         this parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void wdt_it_cmd(FUNCTIONAL_STATE state)
+{
+    uint32_t temp_reg = WDT->con;
+
+    temp_reg &= ~WDTCON_WDTIE_WR;
+
+    if (state) {
+        temp_reg |= (uint32_t)(0x05 << 12);
+    } else {
+        temp_reg |= (uint32_t)(0x0a << 12);
+    }
+
+    WDT->con = temp_reg;
+}
+
+/**
+  * @brief  Secect the WDT clock.
+  * @param  clk: The WDT clock.
+  *         this parameter can be one of the following values:
+  *             @arg WDT_CLK_RC32K: RC32K.
+  *             @arg WDT_CLK_X32K: X32K from 26M divider.
+  * @retval None.
+  */
+void wdt_clk_select(WDT_CLK_TYPEDEF clk)
+{
+    uint32_t temp_reg = WDT->con;
+
+    temp_reg &= ~WDTCON_WDTCSEL_WR;
+    temp_reg |= clk;
+
+    if(clk) {
+        temp_reg |= (uint32_t)(0x05 << 16);
+    } else {
+        temp_reg |= (uint32_t)(0x0a << 16);
+    }
+
+    WDT->con = temp_reg;
+}
+
+/**
+  * @brief  Secect the WDT time.
+  * @param  time: The WDT time.
+  *         this parameter can be one of the following values:
+  *             @arg WDT_TIME_1MS: 1ms.
+  *             @arg WDT_TIME_256MS: 256ms.
+  *             @arg WDT_TIME_512MS: 512ms.
+  *             @arg WDT_TIME_1024MS: 1024ms.
+  *             @arg WDT_TIME_2048MS: 2048ms.
+  *             @arg WDT_TIME_4096MS: 4096ms.
+  *             @arg WDT_TIME_8192MS: 8192ms.
+  *             @arg WDT_TIME_16384MS: 16384ms.
+  * @retval None.
+  */
+void wdt_time_select(WDT_TIME_TYPEDEF time)
+{
+    uint32_t temp_reg;
+
+    temp_reg = WDT->con;
+
+    temp_reg &= ~(WDTCON_TMRSEL | WDTCON_TMRSEL_WR);
+    temp_reg |= time;
+    temp_reg |= (0x0a << 24);
+
+    WDT->con = temp_reg;
+}
+
+/**
+  * @brief  Get the WDT flag.
+  * @param  wdt_flag: specifies the flag to set.
+  *         this parameter can be one of the following values:
+  *             @arg WDT_FLAG_PENDING: WDT pending.
+  * @retval The state of wdt_flag (SET or RESET).
+  */
+FLAG_STATE wdt_get_flag(uint32_t wdt_flag)
+{
+    if ((WDT->con & WDT_FLAG_PENDING) != RESET) {
+        return SET;
+    } else {
+        return RESET;
+    }
+}
+
+/**
+  * @brief  Clear the WDT pending.
+  * @param  None
+  * @retval None
+  */
+void wdt_clear(void)
+{
+    WDT->con |= (uint32_t)0x0a;
+}

+ 43 - 0
driver/driver_wdt.h

@@ -0,0 +1,43 @@
+/*
+ * @File name    : driver_wdt.h
+ * @Author       : Bluetrum IOT Team
+ * @Date         : 2023-02-15
+ * @Description  : This file contains all the functions prototypes for the WDT library.
+ * 
+ * Copyright (c) by Bluetrum, All Rights reserved.
+ */
+#ifndef _DRIVER_WDT_H
+#define _DRIVER_WDT_H
+
+#include "driver_com.h"
+
+//--------------- WDT Flag Definition ---------------//
+#define WDT_FLAG_PENDING            ((uint32_t)0x80000000)
+
+//clk select enumeration
+typedef enum {
+    WDT_CLK_RC32K       = 0x00010000,
+    WDT_CLK_X32K        = 0x00000000,
+} WDT_CLK_TYPEDEF;
+
+//time select enumeration
+typedef enum {
+    WDT_TIME_1MS        = 0x00000000,
+    WDT_TIME_256MS      = 0x00100000,
+    WDT_TIME_512MS      = 0x00200000,
+    WDT_TIME_1024MS     = 0x00300000,
+    WDT_TIME_2048MS     = 0x00400000,
+    WDT_TIME_4096MS     = 0x00500000,
+    WDT_TIME_8192MS     = 0x00600000,
+    WDT_TIME_16384MS    = 0x00700000,
+} WDT_TIME_TYPEDEF;
+
+void wdt_cmd(FUNCTIONAL_STATE state);
+void wdt_reset_cmd(FUNCTIONAL_STATE state);
+void wdt_it_cmd(FUNCTIONAL_STATE state);
+void wdt_clk_select(WDT_CLK_TYPEDEF clk);
+void wdt_time_select(WDT_TIME_TYPEDEF time);
+FLAG_STATE wdt_get_flag(uint32_t wdt_flag);
+void wdt_clear(void);
+
+#endif // _DRIVER_WDT_H

+ 67 - 0
header/clib.h

@@ -0,0 +1,67 @@
+#ifndef _CLIB_H
+#define _CLIB_H
+
+#if A_CONTROL
+
+#define printf(...)                     a_printf(__VA_ARGS__)
+#define vprintf(...)                    a_vprintf(__VA_ARGS__)
+#define print_r(...)                    a_print_r(__VA_ARGS__)
+#define print_r16(...)                  a_print_r16(__VA_ARGS__)
+#define print_r32(...)                  a_print_r32(__VA_ARGS__)
+
+#define printk(...)                     my_printf(__VA_ARGS__)
+#define vprintk(...)                    my_vprintf(__VA_ARGS__)
+#define print_kr(...)                   my_print_r(__VA_ARGS__)
+#define print_kr16(...)                 my_print_r16(__VA_ARGS__)
+#define print_kr32(...)                 my_print_r32(__VA_ARGS__)
+
+#define printf_end(x)                   {WDT_DIS(); printf(x); printf("\nTEST_END\n"); while(1);}
+void a_printf(const char *format, ...);
+void a_vprintf(const char *format, va_list param);
+
+void a_print_r(const void *buf, uint cnt);
+void a_print_r16(const void *buf, uint cnt);
+void a_print_r32(const void *buf, uint cnt);
+
+#else
+
+#define printf(...)                     my_printf(__VA_ARGS__)
+#define vprintf(...)                    my_vprintf(__VA_ARGS__)
+#define print_r(...)                    my_print_r(__VA_ARGS__)
+#define print_r16(...)                  my_print_r16(__VA_ARGS__)
+#define print_r32(...)                  my_print_r32(__VA_ARGS__)
+
+#endif
+
+void uart_putchar(char ch);
+void my_printf_init(void (*putchar)(char));
+void my_printf(const char *format, ...);
+void my_vprintf(const char *format, va_list param);
+
+void my_print_r(const void *buf, uint cnt);
+void my_print_r16(const void *buf, uint cnt);
+void my_print_r32(const void *buf, uint cnt);
+
+int sprintf(char *buffer, const char *format, ...);
+int vsprintf(char *buffer, const char *format, va_list param);
+int snprintf(char *buffer, uint maxlen, const char *format, ...);
+int vsnprintf(char *buffer, uint maxlen, const char *format, va_list param);
+
+u32 swap32(u32 val);
+u16 swap16(u16 val);
+uint get_be16(void *ptr);
+u32 get_be32(void *ptr);
+void put_be16(void *ptr, uint val);
+void put_be32(void *ptr, u32 val);
+
+uint bitset_cnt(u32 val);
+
+void delay_5ms(uint n);
+void delay_ms(uint n);
+void delay_us(uint n);
+void delay(uint n);
+
+u32 tick_get(void);
+bool tick_check_expire(u32 tick, u32 expire_val);
+
+#endif // _CLIB_H

+ 16 - 0
header/global.h

@@ -0,0 +1,16 @@
+#ifndef _GLOBAL_H
+#define _GLOBAL_H
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "typedef.h"
+#include "macro.h"
+#include "clib.h"
+#include "sfr.h"
+
+#endif // _GLOBAL_H
+

+ 15 - 0
header/include.h

@@ -0,0 +1,15 @@
+#ifndef _INCLUDE_H
+#define _INCLUDE_H
+
+#define A_CONTROL           1
+#include "global.h"
+#include "xcfg.h"
+#include "config.h"
+
+//API头文件
+#include "api.h"
+
+//bsp头文件
+#include "bsp.h"
+
+#endif // _INCLUDE_H

+ 42 - 0
header/macro.h

@@ -0,0 +1,42 @@
+#ifndef _MACRO_H
+#define _MACRO_H
+
+#define UINT_MAX                0xffffffff
+
+#define BIT(n)                  (1ul << (n))
+
+#define STR(x)                  #x
+#define AT(x)                   __attribute__((section(STR(x))))
+#define ALIGNED(n)              __attribute__((aligned(n)))
+#define DMA_ADR(x)              ((u32)x)
+#define ALWAYS_INLINE           __attribute__((always_inline)) inline
+#define NO_INLINE               __attribute__((noinline))
+#define WEAK                    __attribute__((weak))
+#define PACKED                  __attribute__((packed))
+#define FIQ                     __attribute__((fiq("machine")))
+#define UNUSED(x)               ((void)x)
+
+#define WDT_CLR()               WDTCON = 0xa
+#define WDT_EN()                WDTCON = 0x110
+#define WDT_DIS()               WDTCON = 0xaa0
+#define WDT_RST()               WDTCON = 0xa000110; while (1)
+#define WDT_RST_DELAY()         WDTCON = 0xa100110; while (1)
+
+#define BYTE0(n)                ((unsigned char)(n))
+#define BYTE1(n)                ((unsigned char)((n)>>8))
+#define BYTE2(n)                ((unsigned char)((n)>>16))
+#define BYTE3(n)                ((unsigned char)((n)>>24))
+
+#define GET_LE16(ptr)           (u16)(*(u16*)(u8*)(ptr))
+#define GET_LE32(ptr)           (u32)(*(u32*)(u8*)(ptr))
+#define PUT_LE16(ptr, val)      *(u16*)(u8*)(ptr) = (u16)(val)
+#define PUT_LE32(ptr, val)      *(u32*)(u8*)(ptr) = (u32)(val)
+
+#define GET_BE16(ptr)           get_be16(ptr)
+#define GET_BE32(ptr)           get_be32(ptr)
+#define PUT_BE16(ptr, val)      put_be16(ptr, val)
+#define PUT_BE32(ptr, val)      put_be32(ptr, val)
+
+#define ALIGN4_HI(val)          (((val)+3)&~3)
+
+#endif // _MACRO_H

+ 6 - 0
header/s_common.h

@@ -0,0 +1,6 @@
+#ifndef _S_COMMON_H
+#define _S_COMMON_H
+
+#include "sfr.h"
+
+#endif

+ 758 - 0
header/sfr.h

@@ -0,0 +1,758 @@
+#ifndef _XBOX_SFR_
+#define _XBOX_SFR_
+
+
+#ifndef __ASSEMBLER__
+#define SFR_RO *(volatile unsigned long const *)
+#define SFR_WO *(volatile unsigned long*)
+#define SFR_RW *(volatile unsigned long*)
+#define LPSFR_RO *(volatile unsigned long const *)
+#define LPSFR_WO *(volatile unsigned long*)
+#define LPSFR_RW *(volatile unsigned long*)
+#define SWINT()      asm(".long 0xb0030057")
+#define EEBREAKINT() asm(".long 0xb0040057")
+#else
+#define SFR_RO
+#define SFR_WO
+#define SFR_RW
+#define SWINT      .long 0xb0030057
+#define EEBREAKINT .long 0xb0040057
+#endif
+
+#define SFR_BASE   0x00000100    // address 0~255 is reserved
+#define SFR0_BASE  (SFR_BASE + 0x000)
+#define SFR1_BASE  (SFR_BASE + 0x100)
+#define SFR2_BASE  (SFR_BASE + 0x200)
+#define SFR3_BASE  (SFR_BASE + 0x300)
+#define SFR4_BASE  (SFR_BASE + 0x400)
+#define SFR5_BASE  (SFR_BASE + 0x500)
+#define SFR6_BASE  (SFR_BASE + 0x600)
+#define SFR7_BASE  (SFR_BASE + 0x700)
+#define SFR8_BASE  (SFR_BASE + 0x800)
+#define SFR9_BASE  (SFR_BASE + 0x900)
+#define SFR10_BASE (SFR_BASE + 0xa00)
+#define SFR11_BASE (SFR_BASE + 0xb00)
+#define SFR12_BASE (SFR_BASE + 0xc00)
+#define SFR13_BASE (SFR_BASE + 0xd00)
+#define SFR14_BASE (SFR_BASE + 0xe00)
+#define SFR15_BASE (SFR_BASE + 0xf00)
+
+//------------------------- SFR Group0 ---------------------------------------//
+
+#define TICK0CON          SFR_RW (SFR0_BASE + 0x01*4)
+#define TICK0CPND         SFR_RW (SFR0_BASE + 0x02*4)
+#define TICK0CNT          SFR_RW (SFR0_BASE + 0x03*4)
+#define TICK0PR           SFR_RW (SFR0_BASE + 0x04*4)
+#define TICK1CON          SFR_RW (SFR0_BASE + 0x05*4)
+#define TICK1CPND         SFR_RW (SFR0_BASE + 0x06*4)
+
+#define TICK1CNT          SFR_RW (SFR0_BASE + 0x0a*4)
+#define TICK1PR           SFR_RW (SFR0_BASE + 0x0b*4)
+#define CPDATA            SFR_RW (SFR0_BASE + 0x0c*4)
+#define SPMODE            SFR_RW (SFR0_BASE + 0x0d*4)
+#define DEVICEID          SFR_RW (SFR0_BASE + 0x0e*4)
+#define VERSIONID         SFR_RW (SFR0_BASE + 0x0f*4)
+
+#define UART0CON          SFR_RW (SFR0_BASE + 0x10*4)
+#define UART0CPND         SFR_WO (SFR0_BASE + 0x11*4)
+#define UART0BAUD         SFR_RW (SFR0_BASE + 0x12*4)
+#define UART0DATA         SFR_RW (SFR0_BASE + 0x13*4)
+#define TMR0CON           SFR_RW (SFR0_BASE + 0x14*4)
+#define TMR0CPND          SFR_RW (SFR0_BASE + 0x15*4)
+#define TMR0CNT           SFR_RW (SFR0_BASE + 0x16*4)
+#define TMR0PR            SFR_RW (SFR0_BASE + 0x17*4)
+#define CRSTPND           SFR_RW (SFR0_BASE + 0x18*4)
+
+#define WDTCON            SFR_RW (SFR0_BASE + 0x1a*4)
+#define RTCCON            SFR_RW (SFR0_BASE + 0x1b*4)
+#define VBRSTCON          SFR_RW (SFR0_BASE + 0x1c*4)
+
+#define RTCCPND           SFR_WO (SFR0_BASE + 0x1e*4)
+#define U0KEYCON          SFR_RW (SFR0_BASE + 0x1f*4)
+
+#define SD0CON            SFR_RW (SFR0_BASE + 0x20*4)
+#define SD0CPND           SFR_WO (SFR0_BASE + 0x21*4)
+#define SD0BAUD           SFR_RW (SFR0_BASE + 0x22*4)
+#define SD0CMD            SFR_RW (SFR0_BASE + 0x23*4)
+#define SD0ARG3           SFR_RW (SFR0_BASE + 0x24*4)
+#define SD0ARG2           SFR_RW (SFR0_BASE + 0x25*4)
+#define SD0ARG1           SFR_RW (SFR0_BASE + 0x26*4)
+#define SD0ARG0           SFR_RW (SFR0_BASE + 0x27*4)
+#define SD0DMAADR         SFR_RW (SFR0_BASE + 0x28*4)
+#define SD0DMACNT         SFR_RW (SFR0_BASE + 0x29*4)
+#define SPI0CON           SFR_RW (SFR0_BASE + 0x2a*4)
+#define SPI0BUF           SFR_RW (SFR0_BASE + 0x2b*4)
+#define SPI0BAUD          SFR_RW (SFR0_BASE + 0x2c*4)
+#define SPI0CPND          SFR_RW (SFR0_BASE + 0x2d*4)
+#define SPI0DMACNT        SFR_RW (SFR0_BASE + 0x2e*4)
+#define SPI0DMAADR        SFR_RW (SFR0_BASE + 0x2f*4)
+
+#define TMR1CON           SFR_RW (SFR0_BASE + 0x35*4)
+#define TMR1CPND          SFR_RW (SFR0_BASE + 0x36*4)
+#define TMR1CNT           SFR_RW (SFR0_BASE + 0x37*4)
+#define TMR1PR            SFR_RW (SFR0_BASE + 0x38*4)
+
+#define TMR2CON           SFR_RW (SFR0_BASE + 0x3a*4)
+#define TMR2CPND          SFR_RW (SFR0_BASE + 0x3b*4)
+#define TMR2CNT           SFR_RW (SFR0_BASE + 0x3c*4)
+#define TMR2PR            SFR_RW (SFR0_BASE + 0x3d*4)
+
+//------------------------- SFR Group1 ---------------------------------------//
+#define CLKCON0           SFR_RW (SFR1_BASE + 0x00*4)
+#define CLKCON1           SFR_RW (SFR1_BASE + 0x01*4)
+#define CLKCON2           SFR_RW (SFR1_BASE + 0x02*4)
+#define CLKCON3           SFR_RW (SFR1_BASE + 0x03*4)
+#define CLKCON4           SFR_RW (SFR1_BASE + 0x04*4)
+#define CLKDIVCON0        SFR_RW (SFR1_BASE + 0x05*4)
+#define CLKDIVCON1        SFR_RW (SFR1_BASE + 0x06*4)
+#define CLKDIVCON2        SFR_RW (SFR1_BASE + 0x07*4)
+
+#define CLKGAT0           SFR_RW (SFR1_BASE + 0x0a*4)
+#define CLKGAT1           SFR_RW (SFR1_BASE + 0x0b*4)
+#define CLKGAT2           SFR_RW (SFR1_BASE + 0x0c*4)
+#define CLKGAT3           SFR_RW (SFR1_BASE + 0x0d*4)
+
+#define PLL0CON           SFR_RW (SFR1_BASE + 0x20*4)
+#define PLL0CON1          SFR_RW (SFR1_BASE + 0x21*4)
+#define PLL0DIV           SFR_RW (SFR1_BASE + 0x22*4)
+
+#define XOSCCON           SFR_RW (SFR1_BASE + 0x2f*4)
+
+#define RSTCON0           SFR_RW (SFR1_BASE + 0x30*4)
+#define LVDCON            SFR_RW (SFR1_BASE + 0x31*4)
+#define PWRCON0           SFR_RW (SFR1_BASE + 0x32*4)
+#define PWRCON1           SFR_RW (SFR1_BASE + 0x33*4)
+#define PWRCON2           SFR_RW (SFR1_BASE + 0x34*4)
+#define LPMCON            SFR_RW (SFR1_BASE + 0x35*4)
+
+#define MEMCON            SFR_RW (SFR1_BASE + 0x3a*4)
+#define MEMCON1           SFR_RW (SFR1_BASE + 0x3b*4)
+#define MEMCON2           SFR_RW (SFR1_BASE + 0x3c*4)
+
+#define PROTCON0          SFR_RW (SFR1_BASE + 0x3e*4)
+#define PROTCON1          SFR_RW (SFR1_BASE + 0x3f*4)
+
+//------------------------- SFR Group2 ---------------------------------------//
+#define UFADDR          SFR_RW (SFR2_BASE + 0x00*4)
+#define UPOWER          SFR_RW (SFR2_BASE + 0x01*4)
+#define UINTRTX1        SFR_RW (SFR2_BASE + 0x02*4)
+#define UINTRTX2        SFR_RW (SFR2_BASE + 0x03*4)
+#define UINTRRX1        SFR_RW (SFR2_BASE + 0x04*4)
+#define UINTRRX2        SFR_RW (SFR2_BASE + 0x05*4)
+#define UINTRUSB        SFR_RW (SFR2_BASE + 0x06*4)
+#define UINTRTX1E       SFR_RW (SFR2_BASE + 0x07*4)
+#define UINTRTX2E       SFR_RW (SFR2_BASE + 0x08*4)
+#define UINTRRX1E       SFR_RW (SFR2_BASE + 0x09*4)
+#define UINTRRX2E       SFR_RW (SFR2_BASE + 0x0a*4)
+#define UINTRUSBE       SFR_RW (SFR2_BASE + 0x0b*4)
+#define UFRAME1         SFR_RW (SFR2_BASE + 0x0c*4)
+#define UFRAME2         SFR_RW (SFR2_BASE + 0x0d*4)
+#define UINDEX          SFR_RW (SFR2_BASE + 0x0e*4)
+#define UDEVCTL         SFR_RW (SFR2_BASE + 0x0f*4)
+
+#define UTXMAXP         SFR_RW (SFR2_BASE + 0x10*4)
+#define UCSR0           SFR_RW (SFR2_BASE + 0x11*4)
+#define UTXCSR1         SFR_RW (SFR2_BASE + 0x11*4)
+#define UTXCSR2         SFR_RW (SFR2_BASE + 0x12*4)
+#define URXMAXP         SFR_RW (SFR2_BASE + 0x13*4)
+#define URXCSR1         SFR_RW (SFR2_BASE + 0x14*4)
+#define URXCSR2         SFR_RW (SFR2_BASE + 0x15*4)
+#define UCOUNT0         SFR_RW (SFR2_BASE + 0x16*4)
+#define URXCOUNT1       SFR_RW (SFR2_BASE + 0x16*4)
+#define URXCOUNT2       SFR_RW (SFR2_BASE + 0x17*4)
+#define UTXTYPE         SFR_RW (SFR2_BASE + 0x18*4)
+#define UTXINTERVAL     SFR_RW (SFR2_BASE + 0x19*4)
+#define URXTYPE         SFR_RW (SFR2_BASE + 0x1a*4)
+#define URXINTERVAL     SFR_RW (SFR2_BASE + 0x1b*4)
+
+#define UFIFO0          SFR_RW (SFR2_BASE + 0x20*4)
+#define UFIFO1          SFR_RW (SFR2_BASE + 0x21*4)
+#define UFIFO2          SFR_RW (SFR2_BASE + 0x22*4)
+#define UFIFO3          SFR_RW (SFR2_BASE + 0x23*4)
+#define UFIFO4          SFR_RW (SFR2_BASE + 0x24*4)
+#define UFIFO5          SFR_RW (SFR2_BASE + 0x25*4)
+#define UFIFO6          SFR_RW (SFR2_BASE + 0x26*4)
+#define UFIFO7          SFR_RW (SFR2_BASE + 0x27*4)
+#define UFIFO8          SFR_RW (SFR2_BASE + 0x28*4)
+#define UFIFO9          SFR_RW (SFR2_BASE + 0x29*4)
+#define UFIFO10         SFR_RW (SFR2_BASE + 0x2a*4)
+#define UFIFO11         SFR_RW (SFR2_BASE + 0x2b*4)
+#define UFIFO12         SFR_RW (SFR2_BASE + 0x2c*4)
+#define UFIFO13         SFR_RW (SFR2_BASE + 0x2d*4)
+#define UFIFO14         SFR_RW (SFR2_BASE + 0x2e*4)
+#define UFIFO15         SFR_RW (SFR2_BASE + 0x2f*4)
+
+//------------------------- SFR Group3 ---------------------------------------//
+#define USBCON0         SFR_RW (SFR3_BASE + 0x00*4)
+#define USBCON1         SFR_RW (SFR3_BASE + 0x01*4)
+#define USBCON2         SFR_RW (SFR3_BASE + 0x02*4)
+#define USBCON3         SFR_RW (SFR3_BASE + 0x03*4)
+#define USBCON4         SFR_RW (SFR3_BASE + 0x04*4)
+#define USBEP0ADR       SFR_RW (SFR3_BASE + 0x05*4)
+#define USBEP1RXADR     SFR_RW (SFR3_BASE + 0x06*4)
+#define USBEP1TXADR     SFR_RW (SFR3_BASE + 0x07*4)
+#define USBEP2RXADR     SFR_RW (SFR3_BASE + 0x08*4)
+#define USBEP2TXADR     SFR_RW (SFR3_BASE + 0x09*4)
+#define USBEP3RXADR     SFR_RW (SFR3_BASE + 0x0a*4)
+#define USBEP3TXADR     SFR_RW (SFR3_BASE + 0x0b*4)
+#define BTPHYTSCON      SFR_RW (SFR3_BASE + 0x0c*4)
+
+#define DBGCON1         SFR_RW (SFR3_BASE + 0x0e*4)
+#define DBGCON          SFR_RW (SFR3_BASE + 0x0f*4)
+
+#define CRCDAT          SFR_RW (SFR3_BASE + 0x10*4)
+#define CRCRES          SFR_RW (SFR3_BASE + 0x11*4)
+#define LFSRRES         SFR_RW (SFR3_BASE + 0x12*4)
+#define TESTDATA                LFSRRES
+#define LFCRCCON        SFR_RW (SFR3_BASE + 0x13*4)
+#define BTDMAADR        SFR_RW (SFR3_BASE + 0x14*4)
+
+#define BTRFDMACON      SFR_RW (SFR3_BASE + 0x18*4)
+#define BTADDMACNT      SFR_RW (SFR3_BASE + 0x19*4)
+#define BTADDMAADR      SFR_RW (SFR3_BASE + 0x1a*4)
+#define BTDADMACNT      SFR_RW (SFR3_BASE + 0x1b*4)
+#define BTDADMAADR      SFR_RW (SFR3_BASE + 0x1c*4)
+
+#define CRC1DAT         SFR_RW (SFR3_BASE + 0x20*4)
+#define CRC1RES         SFR_RW (SFR3_BASE + 0x21*4)
+
+#define HSUT0CON        SFR_RW (SFR3_BASE + 0x30*4)
+#define HSUT0CPND       SFR_RW (SFR3_BASE + 0x31*4)
+#define HSUT0BAUD       SFR_RW (SFR3_BASE + 0x32*4)
+#define HSUT0DATA       SFR_RW (SFR3_BASE + 0x33*4)
+#define HSUT0TXCNT      SFR_RW (SFR3_BASE + 0x34*4)
+#define HSUT0TXADR      SFR_RW (SFR3_BASE + 0x35*4)
+#define HSUT0RXCNT      SFR_RW (SFR3_BASE + 0x36*4)
+#define BTCON3          SFR_RW (SFR3_BASE + 0x37*4)
+#define BTCON4          SFR_RW (SFR3_BASE + 0x38*4)
+#define HSUT0RXADR      SFR_RW (SFR3_BASE + 0x39*4)
+#define HSUT0FIFOCNT    SFR_RW (SFR3_BASE + 0x3a*4)
+#define HSUT0FIFO       SFR_RW (SFR3_BASE + 0x3b*4)
+#define HSUT0FIFOADR    SFR_RW (SFR3_BASE + 0x3c*4)
+#define HSUT0TMRCNT     SFR_RW (SFR3_BASE + 0x3d*4)
+#define HSUT0FCCON      SFR_RW (SFR3_BASE + 0x3e*4)
+
+//------------------------- SFR Group4 ---------------------------------------//
+//0x00~0x3f reserve for CPU
+#define EXCEPTPND       SFR_RO (SFR4_BASE + 0x00*4)
+#define EXCEPTCPND      SFR_WO (SFR4_BASE + 0x01*4)
+#define NMICON          SFR_RW (SFR4_BASE + 0x02*4)
+#define BP0ADR          SFR_RW (SFR4_BASE + 0x03*4)
+#define BP1ADR          SFR_RW (SFR4_BASE + 0x04*4)
+#define BP2ADR          SFR_RW (SFR4_BASE + 0x05*4)
+#define BP3ADR          SFR_RW (SFR4_BASE + 0x06*4)
+#define BP4ADR          SFR_RW (SFR4_BASE + 0x07*4)
+#define BP5ADR          SFR_RW (SFR4_BASE + 0x08*4)
+#define BP6ADR          SFR_RW (SFR4_BASE + 0x09*4)
+#define ICLOCK1         SFR_RW (SFR4_BASE + 0x0a*4)
+#define ICVAL1          SFR_RW (SFR4_BASE + 0x0b*4)
+#define PICCONCLR       SFR_WO (SFR4_BASE + 0x0c*4)
+#define PICCONSET       SFR_WO (SFR4_BASE + 0x0d*4)
+#define PICENCLR        SFR_WO (SFR4_BASE + 0x0e*4)
+#define PICENSET        SFR_WO (SFR4_BASE + 0x0f*4)
+
+#define PICCON          SFR_RW (SFR4_BASE + 0x10*4)
+#define PICEN           SFR_RW (SFR4_BASE + 0x11*4)
+#define PICPR           SFR_RW (SFR4_BASE + 0x12*4)
+#define PICADR          SFR_RW (SFR4_BASE + 0x13*4)
+#define PICPND          SFR_RW (SFR4_BASE + 0x14*4)
+#define CACHCON0        SFR_RW (SFR4_BASE + 0x15*4)
+#define CACHCON1        SFR_RW (SFR4_BASE + 0x16*4)
+#define ICTAG           SFR_RW (SFR4_BASE + 0x17*4)
+#define ICINDEX         SFR_RW (SFR4_BASE + 0x18*4)
+#define ICADRMS         SFR_RW (SFR4_BASE + 0x19*4)
+#define ICLOCK          SFR_RW (SFR4_BASE + 0x1a*4)
+#define ICVAL           SFR_RW (SFR4_BASE + 0x1b*4)
+
+#define SWBK            SFR_RW (SFR4_BASE + 0x1d*4)
+#define EPICCON         SFR_RW (SFR4_BASE + 0x1e*4)
+#define EPC             SFR_RW (SFR4_BASE + 0x1f*4)
+
+#define BP7ADR          SFR_RW (SFR4_BASE + 0x20*4)
+#define BP8ADR          SFR_RW (SFR4_BASE + 0x21*4)
+#define BP9ADR          SFR_RW (SFR4_BASE + 0x22*4)
+#define BP10ADR         SFR_RW (SFR4_BASE + 0x23*4)
+#define BP11ADR         SFR_RW (SFR4_BASE + 0x24*4)
+#define BP12ADR         SFR_RW (SFR4_BASE + 0x25*4)
+#define BP13ADR         SFR_RW (SFR4_BASE + 0x26*4)
+#define BP14ADR         SFR_RW (SFR4_BASE + 0x27*4)
+#define BP15ADR         SFR_RW (SFR4_BASE + 0x28*4)
+#define PICPR1          SFR_RW (SFR4_BASE + 0x29*4)
+
+#define PCERR           SFR_RW (SFR4_BASE + 0x2e*4)
+#define PCST            SFR_RW (SFR4_BASE + 0x2f*4)
+
+//------------------------- SFR Group5 ---------------------------------------//
+
+#define IICCON0         SFR_RW (SFR5_BASE + 0x07*4)
+#define IICCON1         SFR_RW (SFR5_BASE + 0x08*4)
+#define IICCMDA         SFR_RW (SFR5_BASE + 0x09*4)
+#define IICDATA         SFR_RW (SFR5_BASE + 0x0a*4)
+#define IICDMAADR       SFR_RW (SFR5_BASE + 0x0b*4)
+#define IICDMACNT       SFR_RW (SFR5_BASE + 0x0c*4)
+#define IICSSTS         SFR_RW (SFR5_BASE + 0x0d*4)
+
+#define SADCDAT0        SFR_RO (SFR5_BASE + 0x20*4)
+#define SADCDAT1        SFR_RO (SFR5_BASE + 0x21*4)
+#define SADCDAT2        SFR_RO (SFR5_BASE + 0x22*4)
+#define SADCDAT3        SFR_RO (SFR5_BASE + 0x23*4)
+#define SADCDAT4        SFR_RO (SFR5_BASE + 0x24*4)
+#define SADCDAT5        SFR_RO (SFR5_BASE + 0x25*4)
+#define SADCDAT6        SFR_RO (SFR5_BASE + 0x26*4)
+#define SADCDAT7        SFR_RO (SFR5_BASE + 0x27*4)
+#define SADCDAT8        SFR_RO (SFR5_BASE + 0x28*4)
+#define SADCDAT9        SFR_RO (SFR5_BASE + 0x29*4)
+#define SADCDAT10       SFR_RO (SFR5_BASE + 0x2a*4)
+#define SADCDAT11       SFR_RO (SFR5_BASE + 0x2b*4)
+#define SADCDAT12       SFR_RO (SFR5_BASE + 0x2c*4)
+#define SADCDAT13       SFR_RO (SFR5_BASE + 0x2d*4)
+#define SADCDAT14       SFR_RO (SFR5_BASE + 0x2e*4)
+#define SADCDAT15       SFR_RO (SFR5_BASE + 0x2f*4)
+
+#define SADCCON         SFR_RW (SFR5_BASE + 0x30*4)
+#define SADCCH          SFR_RW (SFR5_BASE + 0x31*4)
+#define SADCST          SFR_WO (SFR5_BASE + 0x32*4)
+#define SADCBAUD        SFR_WO (SFR5_BASE + 0x33*4)
+#define MBISTCON        SFR_RW (SFR5_BASE + 0x34*4)
+#define MBISTEADR       SFR_WO (SFR5_BASE + 0x35*4)
+#define MBISTBADR       SFR_WO (SFR5_BASE + 0x36*4)
+#define MBISTCRC        SFR_RW (SFR5_BASE + 0x37*4)
+#define MBISTERR        SFR_RO (SFR5_BASE + 0x38*4)
+
+#define SADCCHIE        SFR_RW (SFR5_BASE + 0x39*4)
+#define SADCCHPND       SFR_RW (SFR5_BASE + 0x3a*4)
+
+#define EFCON0          SFR_RW (SFR5_BASE + 0x3d*4)
+#define EFCON1          SFR_WO (SFR5_BASE + 0x3e*4)
+#define EFDAT           SFR_RW (SFR5_BASE + 0x3f*4)
+
+//------------------------- SFR Group6 ---------------------------------------//
+#define GPIOASET        SFR_RW (SFR6_BASE + 0x00*4)
+#define GPIOACLR        SFR_RW (SFR6_BASE + 0x01*4)
+#define GPIOA           SFR_RW (SFR6_BASE + 0x02*4)
+#define GPIOADIR        SFR_RW (SFR6_BASE + 0x03*4)
+#define GPIOADE         SFR_RW (SFR6_BASE + 0x04*4)
+#define GPIOAFEN        SFR_RW (SFR6_BASE + 0x05*4)
+#define GPIOAFDIREN     SFR_RW (SFR6_BASE + 0x06*4)
+#define GPIOADRV        SFR_RW (SFR6_BASE + 0x07*4)
+#define GPIOAPU         SFR_RW (SFR6_BASE + 0x08*4)
+#define GPIOAPD         SFR_RW (SFR6_BASE + 0x09*4)
+#define GPIOAPU200K     SFR_RW (SFR6_BASE + 0x0a*4)
+#define GPIOAPD200K     SFR_RW (SFR6_BASE + 0x0b*4)
+#define GPIOAPU300      SFR_RW (SFR6_BASE + 0x0c*4)
+#define GPIOAPD300      SFR_RW (SFR6_BASE + 0x0d*4)
+
+#define GPIOBSET        SFR_RW (SFR6_BASE + 0x10*4)
+#define GPIOBCLR        SFR_RW (SFR6_BASE + 0x11*4)
+#define GPIOB           SFR_RW (SFR6_BASE + 0x12*4)
+#define GPIOBDIR        SFR_RW (SFR6_BASE + 0x13*4)
+#define GPIOBDE         SFR_RW (SFR6_BASE + 0x14*4)
+#define GPIOBFEN        SFR_RW (SFR6_BASE + 0x15*4)
+#define GPIOBFDIREN     SFR_RW (SFR6_BASE + 0x16*4)
+#define GPIOBDRV        SFR_RW (SFR6_BASE + 0x17*4)
+#define GPIOBPU         SFR_RW (SFR6_BASE + 0x18*4)
+#define GPIOBPD         SFR_RW (SFR6_BASE + 0x19*4)
+#define GPIOBPU200K     SFR_RW (SFR6_BASE + 0x1a*4)
+#define GPIOBPD200K     SFR_RW (SFR6_BASE + 0x1b*4)
+#define GPIOBPU300      SFR_RW (SFR6_BASE + 0x1c*4)
+#define GPIOBPD300      SFR_RW (SFR6_BASE + 0x1d*4)
+
+#define FUNCOMCON0    SFR_RW (SFR6_BASE + 0x30*4)
+#define FUNCOMCON1    SFR_RW (SFR6_BASE + 0x31*4)
+#define FUNCOMCON2    SFR_RW (SFR6_BASE + 0x32*4)
+#define FUNCOMCON3    SFR_RW (SFR6_BASE + 0x33*4)
+#define FUNCOMCON4    SFR_RW (SFR6_BASE + 0x34*4)
+#define FUNCOMCON5    SFR_RW (SFR6_BASE + 0x35*4)
+#define FUNCOMCON6    SFR_RW (SFR6_BASE + 0x36*4)
+#define FUNCOMCON7    SFR_RW (SFR6_BASE + 0x37*4)
+#define FUNCIMCON0    SFR_RW (SFR6_BASE + 0x38*4)
+#define FUNCIMCON1    SFR_RW (SFR6_BASE + 0x39*4)
+#define FUNCIMCON2    SFR_RW (SFR6_BASE + 0x3a*4)
+#define FUNCIMCON3    SFR_RW (SFR6_BASE + 0x3b*4)
+#define FUNCIMCON4    SFR_RW (SFR6_BASE + 0x3c*4)
+#define FUNCIMCON5    SFR_RW (SFR6_BASE + 0x3d*4)
+#define FUNCIMCON6    SFR_RW (SFR6_BASE + 0x3e*4)
+
+//------------------------- SFR Group7 ---------------------------------------//
+#define GPIOGSET        SFR_RW (SFR7_BASE + 0x00*4)
+#define GPIOGCLR        SFR_RW (SFR7_BASE + 0x01*4)
+#define GPIOG           SFR_RW (SFR7_BASE + 0x02*4)
+#define GPIOGDIR        SFR_RW (SFR7_BASE + 0x03*4)
+#define GPIOGDE         SFR_RW (SFR7_BASE + 0x04*4)
+#define GPIOGFEN        SFR_RW (SFR7_BASE + 0x05*4)
+#define GPIOGFDIREN     SFR_RW (SFR7_BASE + 0x06*4)
+#define GPIOGDRV        SFR_RW (SFR7_BASE + 0x07*4)
+#define GPIOGPU         SFR_RW (SFR7_BASE + 0x08*4)
+#define GPIOGPD         SFR_RW (SFR7_BASE + 0x09*4)
+#define GPIOGPU200K     SFR_RW (SFR7_BASE + 0x0a*4)
+#define GPIOGPD200K     SFR_RW (SFR7_BASE + 0x0b*4)
+#define GPIOGPU300      SFR_RW (SFR7_BASE + 0x0c*4)
+#define GPIOGPD300      SFR_RW (SFR7_BASE + 0x0d*4)
+
+#define IRONETIME       SFR_RW (SFR7_BASE + 0x20*4)
+#define IRZEROTIME      SFR_RW (SFR7_BASE + 0x21*4)
+#define IRSTARTTIME     SFR_RW (SFR7_BASE + 0x22*4)
+#define IRREPEATTIME    SFR_RW (SFR7_BASE + 0x23*4)
+#define IRREPEATCON     SFR_RW (SFR7_BASE + 0x24*4)
+#define IRTXCON         SFR_RW (SFR7_BASE + 0x25*4)
+#define IRTXDATA        SFR_RW (SFR7_BASE + 0x26*4)
+#define IRTXLEN         SFR_RW (SFR7_BASE + 0x27*4)
+#define IRTXPEND        SFR_RW (SFR7_BASE + 0x28*4)
+#define IRDMACON        SFR_RW (SFR7_BASE + 0x29*4)
+#define IRDMAIADR       SFR_RW (SFR7_BASE + 0x2a*4)
+#define IRDMAISIZE      SFR_RW (SFR7_BASE + 0x2b*4)
+#define IRDMAOADR       SFR_RW (SFR7_BASE + 0x2c*4)
+#define IRDMAOSIZE      SFR_RW (SFR7_BASE + 0x2d*4)
+#define IRDMAPEND       SFR_RW (SFR7_BASE + 0x2e*4)
+#define IRRXCON         SFR_RW (SFR7_BASE + 0x2f*4)
+#define IRRXDAT         SFR_RW (SFR7_BASE + 0x30*4)
+#define IRRXCPND        SFR_WO (SFR7_BASE + 0x31*4)
+#define IRRXERR0        SFR_WO (SFR7_BASE + 0x32*4)
+#define IRRXERR1        SFR_WO (SFR7_BASE + 0x33*4)
+#define IRRXPR0         SFR_WO (SFR7_BASE + 0x34*4)
+#define IRRXPR1         SFR_WO (SFR7_BASE + 0x35*4)
+#define IRFLTCON        SFR_RW (SFR7_BASE + 0x36*4)
+
+#define CORDICCON       SFR_RW (SFR7_BASE + 0x3b*4)
+#define CORDICINDATX    SFR_RW (SFR7_BASE + 0x3c*4)
+#define CORDICINDATY    SFR_RW (SFR7_BASE + 0x3d*4)
+#define CORDICOUTDATX   SFR_RW (SFR7_BASE + 0x3e*4)
+#define CORDICOUTDATY   SFR_RW (SFR7_BASE + 0x3f*4)
+
+//------------------------- SFR Group8 ---------------------------------------//
+
+#define KEYSCAN_CON0    LPSFR_RW (SFR8_BASE + 0x00*4)
+#define KEYSCAN_CON1    LPSFR_RW (SFR8_BASE + 0x01*4)
+#define KEYSCAN_CLR     LPSFR_RW (SFR8_BASE + 0x02*4)
+#define KEYSCAN_INFO0   LPSFR_RW (SFR8_BASE + 0x03*4)
+#define KEYSCAN_INFO1   LPSFR_RW (SFR8_BASE + 0x04*4)
+#define KEYSCAN_INFO2   LPSFR_RW (SFR8_BASE + 0x05*4)
+#define LP_GPIOA        LPSFR_RW (SFR8_BASE + 0x06*4)
+#define LP_GPIOADIR     LPSFR_RW (SFR8_BASE + 0x07*4)
+#define LP_GPIOADE      LPSFR_RW (SFR8_BASE + 0x08*4)
+#define LP_GPIOAPU0     LPSFR_RW (SFR8_BASE + 0x09*4)
+#define LP_GPIOAPD0     LPSFR_RW (SFR8_BASE + 0x0a*4)
+#define LP_GPIOB        LPSFR_RW (SFR8_BASE + 0x0b*4)
+#define LP_GPIOBDIR     LPSFR_RW (SFR8_BASE + 0x0c*4)
+#define LP_GPIOBDE      LPSFR_RW (SFR8_BASE + 0x0d*4)
+#define LP_GPIOBPU0     LPSFR_RW (SFR8_BASE + 0x0e*4)
+#define LP_GPIOBPD0     LPSFR_RW (SFR8_BASE + 0x0f*4)
+
+#define LP_GPIOE        LPSFR_RW (SFR8_BASE + 0x10*4)
+#define LP_GPIOEDIR     LPSFR_RW (SFR8_BASE + 0x11*4)
+#define LP_GPIOEDE      LPSFR_RW (SFR8_BASE + 0x12*4)
+#define LP_GPIOEPU0     LPSFR_RW (SFR8_BASE + 0x13*4)
+#define LP_GPIOEPD0     LPSFR_RW (SFR8_BASE + 0x14*4)
+#define LP_GPIOF        LPSFR_RW (SFR8_BASE + 0x15*4)
+#define LP_GPIOFDIR     LPSFR_RW (SFR8_BASE + 0x16*4)
+#define LP_GPIOFDE      LPSFR_RW (SFR8_BASE + 0x17*4)
+#define LP_GPIOFPU0     LPSFR_RW (SFR8_BASE + 0x18*4)
+#define LP_GPIOFPD0     LPSFR_RW (SFR8_BASE + 0x19*4)
+#define LP_GPIOG        LPSFR_RW (SFR8_BASE + 0x1a*4)
+#define LP_GPIOGDIR     LPSFR_RW (SFR8_BASE + 0x1b*4)
+#define LP_GPIOGDE      LPSFR_RW (SFR8_BASE + 0x1c*4)
+#define LP_GPIOGPU0     LPSFR_RW (SFR8_BASE + 0x1d*4)
+#define LP_GPIOGPD0     LPSFR_RW (SFR8_BASE + 0x1e*4)
+#define WKUPCON         LPSFR_RW (SFR8_BASE + 0x1f*4)
+
+#define WKUPEDG         LPSFR_RW (SFR8_BASE + 0x20*4)
+#define WKUPCPND        LPSFR_RW (SFR8_BASE + 0x21*4)
+#define PORTINTEDG      LPSFR_RW (SFR8_BASE + 0x22*4)
+#define PORTINTEN       LPSFR_RW (SFR8_BASE + 0x23*4)
+#define WKRSRC          LPSFR_RW (SFR8_BASE + 0x24*4)
+#define WKFSRC          LPSFR_RW (SFR8_BASE + 0x25*4)
+#define BTCON2          LPSFR_RW (SFR8_BASE + 0x26*4)
+
+//------------------------- SFR Group9 ---------------------------------------//
+#define TMR3CON         SFR_RW (SFR9_BASE + 0x00*4)
+#define TMR3CPND        SFR_WO (SFR9_BASE + 0x01*4)
+#define TMR3CNT         SFR_RW (SFR9_BASE + 0x02*4)
+#define TMR3PR          SFR_RW (SFR9_BASE + 0x03*4)
+#define TMR3CPT         SFR_RO (SFR9_BASE + 0x04*4)
+#define TMR3DUTY0       SFR_WO (SFR9_BASE + 0x05*4)
+#define TMR3DUTY1       SFR_WO (SFR9_BASE + 0x06*4)
+#define TMR3DUTY2       SFR_WO (SFR9_BASE + 0x07*4)
+#define TMR3PSC         SFR_RW (SFR9_BASE + 0x08*4)
+
+#define UDETCON         SFR_RW (SFR9_BASE + 0x18*4)
+#define UDETCPND        SFR_RW (SFR9_BASE + 0x19*4)
+#define UDETBAUD        SFR_RW (SFR9_BASE + 0x1a*4)
+#define UDETDATA        SFR_RW (SFR9_BASE + 0x1b*4)
+
+#define SPI1CON         SFR_RW (SFR9_BASE + 0x20*4)
+#define SPI1BUF         SFR_RW (SFR9_BASE + 0x21*4)
+#define SPI1BAUD        SFR_RW (SFR9_BASE + 0x22*4)
+#define SPI1CPND        SFR_RW (SFR9_BASE + 0x23*4)
+#define SPI1DMACNT      SFR_RW (SFR9_BASE + 0x24*4)
+#define SPI1DMAADR      SFR_RW (SFR9_BASE + 0x25*4)
+
+#define FREQDETCON      SFR_RW (SFR9_BASE + 0x28*4)
+#define FREQDETCPND     SFR_RW (SFR9_BASE + 0x29*4)
+#define FREQDETCNT      SFR_RW (SFR9_BASE + 0x2a*4)
+#define FREQDETTGT      SFR_RW (SFR9_BASE + 0x2b*4)
+
+//------------------------- SFR Group10 --------------------------------------//
+#define INPCON          SFR_RW (SFR10_BASE + 0x00*4)
+#define INPCPND         SFR_RW (SFR10_BASE + 0x01*4)
+#define TKCON           SFR_RW (SFR10_BASE + 0x02*4)
+#define TKCON1          SFR_RW (SFR10_BASE + 0x03*4)
+#define TKCNT           SFR_RW (SFR10_BASE + 0x04*4)
+#define TKCDPR0         SFR_RW (SFR10_BASE + 0x05*4)
+#define TKCDPR1         SFR_RW (SFR10_BASE + 0x06*4)
+#define TKTMR           SFR_RW (SFR10_BASE + 0x07*4)
+#define TETMR           SFR_RW (SFR10_BASE + 0x08*4)
+#define TKBCNT          SFR_RW (SFR10_BASE + 0x09*4)
+#define TKPTHD          SFR_RW (SFR10_BASE + 0x0a*4)
+#define TKETHD          SFR_RW (SFR10_BASE + 0x0b*4)
+#define TEBCNT          SFR_RW (SFR10_BASE + 0x0c*4)
+#define TEPTHD          SFR_RW (SFR10_BASE + 0x0d*4)
+#define TEETHD          SFR_RW (SFR10_BASE + 0x0e*4)
+#define TKCON2          SFR_RW (SFR10_BASE + 0x0f*4)
+
+#define TKVARI          SFR_RW (SFR10_BASE + 0x10*4)
+#define TKVARITHD       SFR_WO (SFR10_BASE + 0x11*4)
+#define TKACON0         SFR_RW (SFR10_BASE + 0x12*4)
+#define TKACON1         SFR_RW (SFR10_BASE + 0x13*4)
+
+#define RTCRAMADR       SFR_RW (SFR10_BASE + 0x1c*4)
+#define RTCRAMDAT       SFR_RW (SFR10_BASE + 0x1d*4)
+#define RTCALM          SFR_RW (SFR10_BASE + 0x1e*4)
+#define RTCCNT          SFR_RW (SFR10_BASE + 0x1f*4)
+
+#define RTCCON0         SFR_RW (SFR10_BASE + 0x20*4)
+#define RTCCON1         SFR_RW (SFR10_BASE + 0x21*4)
+#define RTCCON2         SFR_RW (SFR10_BASE + 0x22*4)
+#define RTCCON3         SFR_RW (SFR10_BASE + 0x23*4)
+#define RTCCON4         SFR_RW (SFR10_BASE + 0x24*4)
+#define RTCCON5         SFR_RW (SFR10_BASE + 0x25*4)
+#define RTCCON6         SFR_RW (SFR10_BASE + 0x26*4)
+#define RTCCON7         SFR_RW (SFR10_BASE + 0x27*4)
+#define RTCCON8         SFR_RW (SFR10_BASE + 0x28*4)
+#define RTCCON9         SFR_RW (SFR10_BASE + 0x29*4)
+#define RTCCON10        SFR_RW (SFR10_BASE + 0x2a*4)
+#define RTCCON11        SFR_RW (SFR10_BASE + 0x2b*4)
+#define RTCCON12        SFR_RW (SFR10_BASE + 0x2c*4)
+#define RTCCON13        SFR_RW (SFR10_BASE + 0x2d*4)
+#define RTCCON14        SFR_RW (SFR10_BASE + 0x2e*4)
+#define RTCCON15        SFR_RW (SFR10_BASE + 0x2f*4)
+
+#define WPTCON          SFR_RW (SFR10_BASE + 0x30*4)
+#define WPTPND          SFR_RW (SFR10_BASE + 0x31*4)
+#define WPTADR          SFR_RW (SFR10_BASE + 0x32*4)
+#define WPTDAT          SFR_RW (SFR10_BASE + 0x33*4)
+
+#define FPGATBBGCLR     SFR_RW (SFR10_BASE + 0x39*4)
+#define FPGATBBGSET     SFR_RW (SFR10_BASE + 0x3a*4)
+#define FPGAUTCON       SFR_RW (SFR10_BASE + 0x3b*4)
+#define FPGAUTDATA      SFR_RW (SFR10_BASE + 0x3c*4)
+#define FPGAUTCPND      SFR_RW (SFR10_BASE + 0x3d*4)
+#define FPGAUTBAUD      SFR_RW (SFR10_BASE + 0x3e*4)
+#define FPGATEST        SFR_RW (SFR10_BASE + 0x3f*4)
+
+#define FPGAUTCON2      SFR_RW (SFR11_BASE + 0x36*4)
+#define FPGAUTDATA2     SFR_RW (SFR11_BASE + 0x37*4)
+#define FPGAUTCPND2     SFR_RW (SFR11_BASE + 0x38*4)
+#define FPGAUTBAUD2     SFR_RW (SFR11_BASE + 0x39*4)
+
+#define TIM_CR1           SFR_RW (SFR12_BASE + 0x00*4)
+#define TIM_CR2           SFR_RW (SFR12_BASE + 0x01*4)
+#define TIM_SMCR          SFR_RW (SFR12_BASE + 0x02*4)
+#define TIM_DIER          SFR_RW (SFR12_BASE + 0x03*4)
+#define TIM_SR            SFR_RW (SFR12_BASE + 0x04*4)
+#define TIM_EGR           SFR_RW (SFR12_BASE + 0x05*4)
+#define TIM_CCMR1         SFR_RW (SFR12_BASE + 0x06*4)
+#define TIM_CCMR2         SFR_RW (SFR12_BASE + 0x07*4)
+#define TIM_CCER          SFR_RW (SFR12_BASE + 0x08*4)
+#define TIM_CNT           SFR_RW (SFR12_BASE + 0x09*4)
+#define TIM_PSC           SFR_RW (SFR12_BASE + 0x0a*4)
+#define TIM_ARR           SFR_RW (SFR12_BASE + 0x0b*4)
+#define TIM_RCR           SFR_RW (SFR12_BASE + 0x0c*4)
+#define TIM_CCR1          SFR_RW (SFR12_BASE + 0x0d*4)
+#define TIM_CCR2          SFR_RW (SFR12_BASE + 0x0e*4)
+#define TIM_CCR3          SFR_RW (SFR12_BASE + 0x0f*4)
+#define TIM_CCR4          SFR_RW (SFR12_BASE + 0x10*4)
+#define TIM_BDTR          SFR_RW (SFR12_BASE + 0x11*4)
+#define TIM_SARAD         SFR_RW (SFR12_BASE + 0x12*4)
+
+#define LEDCCON         SFR_RW (SFR12_BASE + 0x30*4)
+#define LEDCFD          SFR_RW (SFR12_BASE + 0x31*4)
+#define LEDCLP          SFR_RW (SFR12_BASE + 0x32*4)
+#define LEDCTIX         SFR_RW (SFR12_BASE + 0x33*4)
+#define LEDCRSTX        SFR_RW (SFR12_BASE + 0x34*4)
+#define LEDCADDR        SFR_RW (SFR12_BASE + 0x35*4)
+#define LEDCCNT         SFR_RW (SFR12_BASE + 0x36*4)
+#define LEDCPEND        SFR_RW (SFR12_BASE + 0x37*4)
+
+// SFR bank13 define
+#define QDECXCON        SFR_RW (SFR13_BASE + 0x00*4)
+#define QDECYCON        SFR_RW (SFR13_BASE + 0x01*4)
+#define QDECZCON        SFR_RW (SFR13_BASE + 0x02*4)
+#define QDECXCPND       SFR_WO (SFR13_BASE + 0x03*4)
+#define QDECYCPND       SFR_WO (SFR13_BASE + 0x04*4)
+#define QDECZCPND       SFR_WO (SFR13_BASE + 0x05*4)
+#define QDECXDAT        SFR_RW (SFR13_BASE + 0x06*4)
+#define QDECYDAT        SFR_RW (SFR13_BASE + 0x07*4)
+#define QDECZDAT        SFR_RW (SFR13_BASE + 0x08*4)
+
+#define SDADCCON        SFR_RW (SFR13_BASE + 0x09*4)
+#define SDADCGAINCON    SFR_RW (SFR13_BASE + 0x0a*4)
+#define SDADCGETDCCON   SFR_RW (SFR13_BASE + 0x0b*4)
+#define SDADCDMACON     SFR_RW (SFR13_BASE + 0x0c*4)
+#define SDADCDMAADDR    SFR_RW (SFR13_BASE + 0x0d*4)
+#define SDADCDMASIZE    SFR_RW (SFR13_BASE + 0x0e*4)
+#define SDADCDMAPEND    SFR_RO (SFR13_BASE + 0x0f*4)
+#define SDADCDMACPND    SFR_WO (SFR13_BASE + 0x10*4)
+#define SDADCRAMTADDR   SFR_RW (SFR13_BASE + 0x11*4)
+#define SDADCRAMTDATA   SFR_RW (SFR13_BASE + 0x12*4)
+
+#define DACDMAINCON     SFR_RW (SFR13_BASE + 0x13*4)
+#define DACDMAINADDR    SFR_RW (SFR13_BASE + 0x14*4)
+#define DACDMAINSIZE    SFR_RW (SFR13_BASE + 0x15*4)
+#define DACDMAINPEND    SFR_RO (SFR13_BASE + 0x16*4)
+#define DACDMAINCPND    SFR_WO (SFR13_BASE + 0x17*4)
+#define SDDACCON        SFR_RW (SFR13_BASE + 0x18*4)
+
+#define AUANGCON0       SFR_RW (SFR13_BASE + 0x19*4)
+#define AUANGCON1       SFR_RW (SFR13_BASE + 0x1a*4)
+
+#define LPWMSTCON       SFR_RW (SFR13_BASE + 0x20*4)
+#define LPWMSWCON       SFR_RW (SFR13_BASE + 0x21*4)
+#define LPWMCMCON       SFR_RW (SFR13_BASE + 0x22*4)
+#define LPWMACON        SFR_RW (SFR13_BASE + 0x23*4)
+#define LPWMBCON        SFR_RW (SFR13_BASE + 0x24*4)
+#define LPWMCCON        SFR_RW (SFR13_BASE + 0x25*4)
+#define LPWMDCON        SFR_RW (SFR13_BASE + 0x26*4)
+#define LPWMECON        SFR_RW (SFR13_BASE + 0x27*4)
+#define LPWMFCON        SFR_RW (SFR13_BASE + 0x28*4)
+#define LPWMHLCON       SFR_RW (SFR13_BASE + 0x29*4)
+#define LPWMPND         SFR_RW (SFR13_BASE + 0x2a*4)
+
+
+
+#ifndef __ASSEMBLER__
+enum funo_select_tbl {
+    FO_AUDIO          = 2,
+    FO_SDIO           = 3,
+    FO_I2CSCL         = 5,
+    FO_I2CSDA,
+    FO_T3PWM0,
+    FO_T3PWM1,
+    FO_T3PWM2,
+    FO_TOC1,            //10
+    FO_TOC1N,
+    FO_TOC2,
+    FO_TOC2N,
+    FO_TOC3,
+    FO_TOC3N,           //15
+    FO_TOC4,
+    FO_UR0TX,
+    FO_UR1TX,
+    FO_HURTX,
+    FO_HURRTS,         //20
+    FO_SPI1D0,
+    FO_SPI1D1,
+    FO_SPI1D2,
+    FO_SPI1D3,
+    FO_SPI1CLK,         //25
+    FO_LPWM,
+    FO_LEDCDAT,
+    FO_IRTX,
+    FO_CLKOUT,          //29
+};
+
+enum funi_io_tbl {
+    FI_PA0              = 1,
+    FI_PA1,
+    FI_PA2,
+    FI_PA3,
+    FI_PA4,
+    FI_PA5,
+    FI_PA6,
+    FI_PA7,
+    FI_PA8,
+    FI_PA9,
+    FI_PA10,
+    FI_PA11,
+    FI_PA12,
+    FI_PA13,
+    FI_PA14,
+    FI_PA15,
+    FI_PB0              = 17,
+    FI_PB1,
+    FI_PB2,
+    FI_PB3,
+    FI_PB4,
+    FI_PB5,
+    FI_PB6,
+    FI_PB7,
+    FI_PB8,
+    FI_PB9,
+    FI_PG1,
+    FI_PG2,
+    FI_PG4,
+    FI_PG5,
+};
+#endif
+
+#define FUNO_PA0SEL(funo_sel)   FUNCOMCON0 = (funo_sel<< 0)
+#define FUNO_PA1SEL(funo_sel)   FUNCOMCON0 = (funo_sel<< 8)
+#define FUNO_PA2SEL(funo_sel)   FUNCOMCON0 = (funo_sel<<16)
+#define FUNO_PA3SEL(funo_sel)   FUNCOMCON0 = (funo_sel<<24)
+#define FUNO_PA4SEL(funo_sel)   FUNCOMCON1 = (funo_sel<< 0)
+#define FUNO_PA5SEL(funo_sel)   FUNCOMCON1 = (funo_sel<< 8)
+#define FUNO_PA6SEL(funo_sel)   FUNCOMCON1 = (funo_sel<<16)
+#define FUNO_PA7SEL(funo_sel)   FUNCOMCON1 = (funo_sel<<24)
+#define FUNO_PA8SEL(funo_sel)   FUNCOMCON2 = (funo_sel<< 0)
+#define FUNO_PA9SEL(funo_sel)   FUNCOMCON2 = (funo_sel<< 8)
+#define FUNO_PA10SEL(funo_sel)  FUNCOMCON2 = (funo_sel<<16)
+#define FUNO_PA11SEL(funo_sel)  FUNCOMCON2 = (funo_sel<<24)
+#define FUNO_PA12SEL(funo_sel)  FUNCOMCON3 = (funo_sel<< 0)
+#define FUNO_PA13SEL(funo_sel)  FUNCOMCON3 = (funo_sel<< 8)
+#define FUNO_PA14SEL(funo_sel)  FUNCOMCON3 = (funo_sel<<16)
+#define FUNO_PA15SEL(funo_sel)  FUNCOMCON3 = (funo_sel<<24)
+
+#define FUNO_PB0SEL(funo_sel)   FUNCOMCON4 = (funo_sel<< 0)
+#define FUNO_PB1SEL(funo_sel)   FUNCOMCON4 = (funo_sel<< 8)
+#define FUNO_PB2SEL(funo_sel)   FUNCOMCON4 = (funo_sel<<16)
+#define FUNO_PB3SEL(funo_sel)   FUNCOMCON4 = (funo_sel<<24)
+#define FUNO_PB4SEL(funo_sel)   FUNCOMCON5 = (funo_sel<< 0)
+#define FUNO_PB5SEL(funo_sel)   FUNCOMCON5 = (funo_sel<< 8)
+#define FUNO_PB6SEL(funo_sel)   FUNCOMCON5 = (funo_sel<<16)
+#define FUNO_PB7SEL(funo_sel)   FUNCOMCON5 = (funo_sel<<24)
+#define FUNO_PB8SEL(funo_sel)   FUNCOMCON6 = (funo_sel<< 0)
+#define FUNO_PB9SEL(funo_sel)   FUNCOMCON6 = (funo_sel<< 8)
+
+#define FUNO_PG1SEL(funo_sel)   FUNCOMCON7 = (funo_sel<< 0)
+#define FUNO_PG2SEL(funo_sel)   FUNCOMCON7 = (funo_sel<< 8)
+#define FUNO_PG4SEL(funo_sel)   FUNCOMCON7 = (funo_sel<<16)
+#define FUNO_PG5SEL(funo_sel)   FUNCOMCON7 = (funo_sel<<24)
+
+#define FUNI_UR0RX(funi_io)     FUNCIMCON0 = (funi_io<< 0)          //0
+#define FUNI_UR1RX(funi_io)     FUNCIMCON0 = (funi_io<< 8)
+#define FUNI_SPI1CLK(funi_io)   FUNCIMCON0 = (funi_io<<16)
+#define FUNI_SPI1DI0(funi_io)   FUNCIMCON0 = (funi_io<<24)
+#define FUNI_SPI1DI1(funi_io)   FUNCIMCON1 = (funi_io<< 0)          //4
+#define FUNI_HURRX(funi_io)     FUNCIMCON1 = (funi_io<< 8)
+#define FUNI_HURCTS(funi_io)    FUNCIMCON1 = (funi_io<<16)
+#define FUNI_T0CAP(funi_io)     FUNCIMCON1 = (funi_io<<24)
+#define FUNI_T1CAP(funi_io)     FUNCIMCON2 = (funi_io<< 0)          //8
+#define FUNI_T2CAP(funi_io)     FUNCIMCON2 = (funi_io<< 8)
+#define FUNI_T3CAP(funi_io)     FUNCIMCON2 = (funi_io<<16)
+#define FUNI_TBKIN(funi_io)     FUNCIMCON2 = (funi_io<<24)
+#define FUNI_TETR(funi_io)      FUNCIMCON3 = (funi_io<< 0)          //12
+#define FUNI_I2CSCL(funi_io)    FUNCIMCON3 = (funi_io<< 8)
+#define FUNI_I2CSDA(funi_io)    FUNCIMCON3 = (funi_io<<16)
+#define FUNI_IRRX(funi_io)      FUNCIMCON3 = (funi_io<<24)
+#define FUNI_QDECXDI0(funi_io)  FUNCIMCON4 = (funi_io<< 0)          //16
+#define FUNI_QDECXDI1(funi_io)  FUNCIMCON4 = (funi_io<< 8)
+#define FUNI_QDECYDI0(funi_io)  FUNCIMCON4 = (funi_io<<16)
+#define FUNI_QDECYDI1(funi_io)  FUNCIMCON4 = (funi_io<<24)
+#define FUNI_QDECZDI0(funi_io)  FUNCIMCON5 = (funi_io<< 0)          //20
+#define FUNI_QDECZDI1(funi_io)  FUNCIMCON5 = (funi_io<< 8)
+#define FUNI_SDCMD(funi_io)     FUNCIMCON5 = (funi_io<<16)
+#define FUNI_SDDAT0(funi_io)    FUNCIMCON5 = (funi_io<<24)
+#define FUNI_SPI0CLK(funi_io)   FUNCIMCON6 = (funi_io<< 0)          //24
+#define FUNI_SPI0DI0(funi_io)   FUNCIMCON6 = (funi_io<< 8)
+#define FUNI_SP10DI1(funi_io)   FUNCIMCON6 = (funi_io<<16)
+#define FUNI_CH27(funi_io)      FUNCIMCON6 = (funi_io<<24)
+#endif

+ 17 - 0
header/typedef.h

@@ -0,0 +1,17 @@
+#ifndef _TYPEDEF_H
+#define _TYPEDEF_H
+
+typedef unsigned char u8, uint8_t, BYTE, uchar;
+typedef signed char s8, int8_t;
+typedef unsigned short u16, uint16_t, WORD, ushort;
+typedef signed short s16, int16_t;
+typedef unsigned int uint, UINT, ssize_t, size_t;
+typedef unsigned long u32, uint32_t, DWORD, ulong;
+typedef signed long s32, int32_t;
+typedef unsigned long long u64, uint64_t, ulonglong;
+typedef signed long long s64, int64_t;
+
+typedef volatile unsigned long *psfr_t;
+
+
+#endif // _TYPEDEF_H

+ 13 - 0
libs/ains/api_ains3.h

@@ -0,0 +1,13 @@
+#ifndef _API_AINS3_H
+#define _API_AINS3_H
+
+typedef struct {
+    u32 nt;
+    u8  prior_opt_idx;
+    s16 gain_floor;
+} ains3_cb_t;
+
+void ains3_mono_init(ains3_cb_t *ains3_cb);
+void ains3_mono_process(s32 *data);
+
+#endif

+ 7 - 0
libs/ains/api_ains4.h

@@ -0,0 +1,7 @@
+#ifndef _API_AINS4_H
+#define _API_AINS4_H
+
+void ains4_mono_init(s32 nr_suppress, s16 prior_opt_idx);
+void ains4_mono_process(s32 *data);
+
+#endif

binární
libs/ains/libains3.a


binární
libs/ains/libains4.a


binární
libs/ains/libfft.a


+ 23 - 0
libs/api.h

@@ -0,0 +1,23 @@
+#ifndef _API_H
+#define _API_H
+
+#include "api_interrupt.h"
+#include "api_btstack.h"
+#include "api_wireless.h"
+#include "api_cm.h"
+#include "api_update.h"
+#include "api_sysclk.h"
+#include "api_msg.h"
+#include "api_sys.h"
+#include "api_pwr.h"
+#include "api_key.h"
+#include "api_list.h"
+#include "api_sdadc.h"
+#include "api_codec.h"
+#include "api_usb.h"
+#include "api_device.h"
+#include "api_os.h"
+
+#include "ver.h"
+
+#endif //_API_H

+ 1105 - 0
libs/ble/api_btstack.h

@@ -0,0 +1,1105 @@
+#ifndef _API_BTSTACK_H
+#define _API_BTSTACK_H
+
+//BLE WORK MODE
+typedef enum {
+    MODE_NORMAL     = 0,       //normal mode
+    MODE_WIRELESS   = 1,       //wireless mode, 2.4G
+    MODE_FCC_TEST   = 2,       //fcc test mode, use uart for communication
+    MODE_BQB_RF_BLE = 4,       //bqb test mode,use uart for communication
+    MODE_IODM_TEST  = 5,       //iodm test mode,use uart for communication
+} BT_WORK_MODE;
+
+
+typedef enum {
+    FCC_TX_TONE = 1,
+    FCC_TX_TEST,
+    FCC_RX_TEST,
+} FCC_RF_MODE;
+
+enum {
+    TXPKT_KICK_DISABLE = 0,
+    TXPKT_KICK_ENABLE,
+    TXPKT_KICK_AUTO,
+};
+
+
+/**
+ * @format 21
+ * @param handle
+ * @param status
+ */
+#define BLE_EVT_PROFILE_FIND_DONE                                   0xA0
+
+/**
+ * @format 2228
+ * @param con_handle
+ * @param start_group_handle
+ * @param end_group_handle
+ * @param uuid128
+ */
+#define BLE_EVT_SERVICE_FIND_RESULT                                 0xA1
+
+/**
+ * @format 222228
+ * @param con_handle
+ * @param start_handle
+ * @param value_handle
+ * @param end_handle
+ * @param properties
+ * @param uuid128
+ */
+#define BLE_EVT_CHARACTERISTIC_FIND_RESULT                          0xA2
+
+
+/**
+ * @format 12222
+ * @param status
+ * @param handle
+ * @param interval
+ * @param latency
+ * @param timeout
+ */
+#define BLE_EVT_CONNECT_PARAM_UPDATE_DONE                           0xB2
+
+/**
+ * @format 1621
+ * @param address_type
+ * @param address
+ * @param handle
+ * @param role
+ */
+#define BLE_EVT_CONNECT                                             0xB3
+
+/**
+ * @format 21
+ * @param handle
+ * @param disconnect_reason
+ */
+#define BLE_EVT_DISCONNECT                                          0xB4
+
+/**
+ * @format 22
+ * @param handle
+ * @param MTU
+ */
+#define BLE_EVT_MTU_EXCHANGE_DONE                                   0xB5
+
+ /**
+  * @format 122
+  * @param status
+  * @param conn_handle
+  * @param attribute_handle
+  */
+#define BLE_EVT_INDICATE_DONE                                       0xB6
+
+/**
+ * @format 121
+ * @param status
+ * @param conn_handle
+ * @param encryption_enabled
+ */
+#define BLE_EVT_ENCRYPTION_CHANGE                                   0xC7
+
+ /**
+  * @format 21614
+  * @param handle
+  * @param addr_type
+  * @param address
+  * @param secure_connection - set to 1 if LE Secure Connection pairing will be used
+  * @param passkey
+  */
+#define BLE_EVT_PASSKEY_DISPLAY                                     0xC9
+
+
+ /**
+  * @format 2161
+  * @param handle
+  * @param addr_type
+  * @param address
+  * @param secure_connection - set to 1 if LE Secure Connection pairing will be used
+  */
+#define BLE_EVT_PASSKEY_INPUT                                       0xCB
+
+ /**
+  * @format 216
+  * @param handle
+  * @param addr_type
+  * @param address
+  */
+#define BLE_EVT_IDENTITY_RESOLVING_FAIL                             0xCE
+
+ /**
+  * @brief Identify resolving succeeded
+  *
+  * @format 216162
+  * @param handle
+  * @param addr_type
+  * @param address
+  * @param identity_addr_type
+  * @param identity_address
+  * @param index
+  *
+  */
+#define BLE_EVT_IDENTITY_RESOLVING_SUCCEED                          0xCF
+
+
+/**
+ * @brief Emitted to inform app that pairing has started.
+ * @format 216
+ * @param handle
+ * @param addr_type
+ * @param address
+ */
+#define BLE_EVT_PAIRING_START                                       0xD4
+
+/**
+  * @brief Emitted to inform app that pairing is complete.
+  * @format 21611
+  * @param handle
+  * @param addr_type
+  * @param address
+  * @param status
+  * @param reason
+  */
+#define BLE_EVT_PAIRING_DONE                                        0xD5
+
+/**
+ * @brief Emitted to inform app that ltk is missing.
+ * @format 216
+ * @param handle
+ * @param addr_type
+ * @param address
+ */
+#define BLE_EVT_LTK_MISSING                                         0xD8
+
+
+/**
+ * @format 11611N
+ * @param advertising_event_type
+ * @param address_type
+ * @param address
+ * @param rssi
+ * @param data_length
+ * @param data
+ */
+#define BLE_EVT_ADV_REPORT                                          0xE2
+
+
+// ATT_ERR_CODE
+#define ATT_ERR_NO_ERR                                              0x00
+#define ATT_ERR_INVALID_HANDLE                                      0x01
+#define ATT_ERR_READ_NOT_PERMITTED                                  0x02
+#define ATT_ERR_WRITE_NOT_PERMITTED                                 0x03
+#define ATT_ERR_INVALID_PDU                                         0x04
+#define ATT_ERR_INSUFFICIENT_AUTHENTICATION                         0x05
+#define ATT_ERR_REQUEST_NOT_SUPPORTED                               0x06
+#define ATT_ERR_INVALID_OFFSET                                      0x07
+#define ATT_ERR_INSUFFICIENT_AUTHORIZATION                          0x08
+#define ATT_ERR_PREPARE_QUEUE_FULL                                  0x09
+#define ATT_ERR_ATTRIBUTE_NOT_FOUND                                 0x0a
+#define ATT_ERR_ATTRIBUTE_NOT_LONG                                  0x0b
+#define ATT_ERR_INSUFFICIENT_ENCRYPTION_KEY_SIZE                    0x0c
+#define ATT_ERR_INVALID_ATTRIBUTE_VALUE_LENGTH                      0x0d
+#define ATT_ERR_UNLIKELY_ERROR                                      0x0e
+#define ATT_ERR_INSUFFICIENT_ENCRYPTION                             0x0f
+#define ATT_ERR_UNSUPPORTED_GROUP_TYPE                              0x10
+#define ATT_ERR_INSUFFICIENT_RESOURCES                              0x11
+#define ATT_ERR_VALUE_NOT_ALLOWED                                   0x13
+#define ATT_ERR_IN_WRONG_STATE                                      0x80
+#define ATT_ERR_NOTIFICATION_NOT_SUPPORTED                          0x81
+#define ATT_ERR_INDICATION_NOT_SUPPORTED                            0x82
+#define ATT_ERR_INDICATION_IN_PORGRESS                              0x83
+#define ATT_ERR_TIMEOUT                                             0x84
+#define ATT_ERR_DISCONNECT                                          0x85
+#define ATT_ERR_DATA_MISMATCH                                       0x86
+
+
+
+
+//Attribute Property
+#define ATT_PROPERTY_BROADCAST                                      0x01
+#define ATT_PROPERTY_READ                                           0x02
+#define ATT_PROPERTY_WRITE_WITHOUT_RESPONSE                         0x04
+#define ATT_PROPERTY_WRITE                                          0x08
+#define ATT_PROPERTY_NOTIFY                                         0x10
+#define ATT_PROPERTY_INDICATE                                       0x20
+#define ATT_PROPERTY_AUTHENTICATED_SIGNED_WRITE                     0x40
+#define ATT_PROPERTY_EXTENDED_PROPERTIES                            0x80
+
+
+//GATT_CLIENT_CHARACTERISTIC_CONFIGURATION
+#define GATT_CCC_NOTIFICATION                                       0x01
+#define GATT_CCC_INDICATION                                         0x02
+
+
+//ATT_TRANSACTION_MODE
+#define ATT_TRANSACTION_WRITE                                       0x00
+#define ATT_TRANSACTION_PREPARE_WRITE                               0x01
+#define ATT_TRANSACTION_WRITE_EXECUTE                               0x02
+#define ATT_TRANSACTION_WRITE_CANCEL                                0x03
+
+
+//SM_AUTHREQ
+#define SM_AUTHREQ_NO_BONDING                                       0x00
+#define SM_AUTHREQ_BONDING                                          0x01
+#define SM_AUTHREQ_MITM_PROTECTION                                  0x04
+#define SM_AUTHREQ_SECURE_CONNECTION                                0x08
+#define SM_AUTHREQ_KEYPRESS                                         0x10
+#define SM_AUTHREQ_CT2                                              0x20
+
+
+typedef uint16_t ble_con_handle_t;
+
+typedef uint32_t bt_timer_handle_t;
+
+typedef void (*kick_func_t)(uint16_t con_handle, uint16_t config);
+
+typedef uint16_t (*att_read_callback_t)(uint16_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size);
+
+typedef int (*att_write_callback_t)(uint16_t con_handle, uint16_t attribute_handle, uint16_t trans_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size);
+
+typedef uint16_t (*att_notify_callback_t)(uint16_t con_handle, uint16_t attribute_handle, uint8_t * buffer, uint16_t buffer_size);
+
+typedef void (*att_event_callback_t) (uint8_t event_type, uint8_t *param, uint16_t size);
+
+typedef void (*ble_init_callback_t)(void);
+
+typedef void (*bb_timer_proc_callback_t)(uint32_t time);
+
+typedef void (*ble_vs_tbox_init_callback_t)(void);
+
+// IO Capability Values
+enum {
+    IO_CAPABILITY_DISPLAY_ONLY = 0,
+    IO_CAPABILITY_DISPLAY_YES_NO,
+    IO_CAPABILITY_KEYBOARD_ONLY,
+    IO_CAPABILITY_NO_INPUT_NO_OUTPUT,
+    IO_CAPABILITY_KEYBOARD_DISPLAY, // not used by secure simple pairing
+};
+
+//ADDRESS TYPE
+typedef enum {
+    GAP_PUBLIC_ADDRESS_TYPE = 0,
+    GAP_RANDOM_ADDRESS_TYPE_STATIC,
+    GAP_RANDOM_ADDRESS_NON_RESOLVABLE,
+    GAP_RANDOM_ADDRESS_RESOLVABLE,
+} gap_random_address_type_t;
+
+typedef enum {
+    BD_ADDR_TYPE_PUBLIC = 0,
+    BD_ADDR_TYPE_RANDOM = 1,
+} bd_addr_type_t;
+
+
+//ADV_TYPE
+enum {
+    ADV_TYPE_IND = 0,
+    ADV_TYPE_DIRECT_HI_IND,
+    ADV_TYPE_SCAN_IND,
+    ADV_TYPE_NONCONN_IND,
+    ADV_TYPE_DIRECT_LO_IND,
+};
+
+//SCAN STA
+typedef enum {
+    LE_SCAN_IDLE,
+    LE_START_SCAN,
+    LE_SCANNING,
+    LE_STOP_SCAN,
+} le_scanning_state_t;
+
+typedef struct {
+    uint8_t adv_en;
+    uint8_t adv_data[31];
+    uint8_t adv_len;
+    uint8_t scan_rsp[31];
+    uint8_t scan_rsp_len;
+    uint16_t adv_int_min;           //advertisement interval
+    uint16_t adv_int_max;           //advertisement interval
+    uint8_t adv_type;
+    uint8_t direct_address_typ;     //only use for direct adv
+    uint8_t direct_address[6];      //only use for direct adv
+    uint8_t channel_map;
+    uint8_t filter_policy;
+} adv_param_t;
+
+typedef struct __attribute__((packed)){
+    uint8_t     event_type;
+    uint8_t     addr_type;
+    uint8_t     addr[6];
+    char        rssi;
+    uint8_t     report_len;
+    const uint8_t * report;
+    uint8_t     offset;
+} adv_report_t;
+
+typedef struct {
+     uint8_t   adv_type;
+     uint8_t   data_len;
+     uint8_t*  data;
+} adv_struct_t;
+
+typedef struct {
+    uint8_t scan_type;
+    uint16_t scan_interval;
+    uint16_t scan_window;
+} scan_param_t;
+
+typedef struct {
+    ///6-byte array address value
+    uint8_t  addr[6];
+}bd_addr_t;
+
+typedef struct {
+    // Key value MSB -> LSB
+    uint8_t key[16];
+}gap_sec_key_t;
+
+// Do not modify!!
+typedef struct {
+    // Address type of device. 0 public/1 random
+    uint8_t addr_type;
+    // BD Address of device
+    bd_addr_t addr;
+}gap_bdaddr_t;
+
+/**
+ * @brief Identity Resolving Key Information
+ */
+typedef struct {
+    // Identify Resolving Key
+    gap_sec_key_t irk;
+    // Identity broadcast address of device
+    gap_bdaddr_t addr;
+}gapc_irk_t;
+
+/**
+ * @brief Resolving list information about a device.
+ */
+typedef struct {
+    // Privacy Mode
+    uint8_t priv_mode;  //PRIV_TYPE_NETWORK = 0x00, Controller accept identity address only
+                        //PRIV_TYPE_DEVICE  = 0x01, Controller accept both identity address and resolvable address.
+    // Device Identity address
+    gap_bdaddr_t addr;
+    // Peer device identity resolve key
+    uint8_t peer_irk[16];
+}gap_ral_dev_info_t;
+
+typedef struct {
+    uint8_t rpa_en;
+    uint8_t privacy_mode;
+    uint16_t renew_to;
+    gap_sec_key_t peer_irk;
+    gap_bdaddr_t addr;
+}rpa_param_t;
+
+typedef struct {
+    // Number of entries to be added in the list. 0 means that list content has to be cleard.
+    uint8_t size;
+    // List of entries to be added in the list.
+    gap_bdaddr_t addr;
+}wlist_param_t;
+
+typedef struct {
+    uint16_t        address_type;
+    uint16_t        real_address_type;
+    bd_addr_t       address;
+    gap_sec_key_t   peer_irk;
+} sm_bonding_info_t;
+
+// Read & Write Callbacks for handle range
+typedef struct att_service_handler {
+    void * item;
+    uint16_t start_handle;
+    uint16_t end_handle;
+    att_read_callback_t read_callback;
+    att_write_callback_t write_callback;
+    att_event_callback_t event_handler;
+} att_service_handler_t;
+
+typedef struct att_client_handler {
+    void * item;
+    att_read_callback_t read_callback;
+    att_notify_callback_t notify_callback;
+    att_event_callback_t event_handler;
+} att_client_handler_t;
+
+typedef struct {
+    uint16_t start_group_handle;
+    uint16_t end_group_handle;
+    uint16_t uuid16;
+    uint8_t  uuid128[16];
+} gatt_client_service_t;
+
+typedef struct {
+    uint16_t start_handle;
+    uint16_t value_handle;
+    uint16_t end_handle;
+    uint16_t properties;
+    uint16_t uuid16;
+    uint8_t  uuid128[16];
+} gatt_client_characteristic_t;
+
+struct txbuf_tag {
+    uint8_t *ptr;
+    uint16_t len;
+    uint16_t att_handle;
+    uint16_t con_handle;
+    uint16_t config;
+} __attribute__ ((packed)) ;
+
+struct txpkt_tag {
+    struct txbuf_tag *buf;
+    uint16_t buf_size;
+    uint8_t total;
+    volatile uint8_t cnt;
+    uint8_t rptr;
+    volatile uint8_t wptr;
+    kick_func_t send_kick;
+};
+
+typedef struct {
+    uint8_t rf_mode;
+    uint8_t tx_power;
+    uint8_t tx_freq;
+    uint8_t rx_freq;
+    uint8_t phy_type;
+    uint8_t todo;
+} fcc_cfg_t;
+
+typedef struct {
+    uint8_t mem[28];
+} bt_timer_mem_t;
+
+extern struct txpkt_tag ble_tx;
+
+//control
+void bt_init(void);
+
+int bt_setup(void);
+
+void bt_off(void);
+
+//sleep
+bool bt_is_sleep(void);
+
+uint32_t bt_sleep_proc(void);
+
+void bt_enter_sleep(void);
+
+void bt_exit_sleep(void);
+
+uint32_t txpkt_init(struct txpkt_tag *txpkt, void *mem_pool, uint8_t total, uint16_t buf_size);
+
+bool txpkt_is_full(struct txpkt_tag *txpkt);
+
+uint8_t txpkt_available_num(struct txpkt_tag *txpkt);
+
+void txpkt_flush(struct txpkt_tag *txpkt);
+
+/**
+  * @brief  Triggers ble to start notify data, Can be used with ble_notify_for_handle_kick function
+  * @param  txpkt
+  * @param  con_handle
+  */
+void txpkt_server_send_tick(struct txpkt_tag *txpkt, uint16_t con_handle);
+
+/**
+  * @brief  Triggers ble to start write data, Can be used with ble_write_cmd_for_character_kick function(Todo)
+  * @param  txpkt
+  * @param  con_handle
+  */
+void txpkt_client_send_tick(struct txpkt_tag *txpkt, uint16_t con_handle);
+
+/**
+  * @brief  Triggers ble to start sending data
+  * @param  con_handle
+  */
+void ble_send_kick(uint16_t con_handle, uint16_t config);
+
+/**
+  * @brief  ble fcc test mode config
+  * @param  rf_mode: FCC_RF_MODE
+  * @param  tx_power: [0,7]
+  * @param  tx_freq: [0,39],freq = 2402 + tx_freq * 2
+  * @param  tx_freq: [0,39],freq = 2402 + tx_freq * 2
+  * @param  phy_type: 0:1M  1:2M
+  * @param  todo: 1
+  */
+void ble_fcc_cfg_init(fcc_cfg_t *cfg);
+
+/**
+ * @brief ble advertisement ctrl
+ * @param none
+ */
+void ble_adv_dis(void);
+
+void ble_adv_en(void);
+
+bool ble_adv_is_en(void);
+
+/**
+  * @brief  set up ble advertisement interval
+  * @param  interval: 0x20 - 0x4000(uint:0.625ms)
+  * @return return true if ok, invalid parameters will return false
+  */
+bool ble_set_adv_interval(uint16_t interval);
+
+/**
+  * @brief  get ble advertisement interval
+  * @param  interval: 0x20 - 0x4000(uint:0.625ms)
+  * @return return true if ok, invalid parameters will return false
+  */
+bool ble_get_adv_interval(uint16_t *interval);
+
+/**
+ * @brief set advertisement data
+ * @param advertising_data (max 31 octets)
+ * @param advertising_data_length
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_set_adv_data(const uint8_t *adv_buf, uint32_t size);
+
+/**
+ * @brief set scan response Data
+ * @param advertising_data (max 31 octets)
+ * @param advertising_data_length
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_set_scan_rsp_data(const uint8_t *scan_rsp_buf, uint32_t size);
+
+/**
+ * @brief initialize advertisement parameter
+ * @param advertisement parameter
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_set_adv_param(adv_param_t* param);
+
+adv_param_t* ble_get_adv_param(void);
+
+/**
+ * @brief initialize advertisement parameter
+ * @param advertisement parameter
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_set_ext_adv_param(adv_param_t* param);
+
+/**
+ * @brief analyse advertisement report, the results will be store in advertisement struct
+ * @param report, can be get by BLE_EVT_ADV_REPORT
+ * @param adv_struct
+ * @return analysis is complete will return true, else will return false
+ */
+bool ble_adv_report_info_analyse(adv_report_t* report, adv_struct_t* adv_struct);
+
+/**
+  * @brief  disconnect ble connection according to connect handle
+  * @param  con_handle
+  */
+void ble_disconnect(uint16_t con_handle);
+
+/**
+ * @brief ble master create connect by ble address
+ * @param addr_ptr
+ * @param addr type : 0-3(0:public, 1:random, 2:public identity 3:random identity)
+ * @param interval: 6 - 3200(unit: 1.25ms)
+ * @param latency
+ * @param timeout (unit: 10ms)
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_connect_by_addr(uint8_t *addr_ptr, uint8_t addr_type, uint16_t interval, uint16_t conn_latency, uint16_t supervision_timeout);
+
+/**
+ * @brief update of the connection parameter for a given LE connection
+ * @param con_handle
+ * @param interval: 6 - 3200(unit: 1.25ms)
+ * @param latency
+ * @param timeout (unit: 10ms)
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_update_conn_param(uint16_t con_handle, uint16_t interval, uint16_t latency, uint16_t timeout);
+
+/**
+ * @brief update of the connection parameter for a given LE connection
+ * @param con_handle
+ * @param interval_min: 6 - 3200(unit: 1.25ms)
+ * @param interval_max: 6 - 3200(unit: 1.25ms) interval_min <= interval_max
+ * @param latency
+ * @param timeout (unit: 10ms)
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_update_conn_param_2(uint16_t con_handle, uint16_t interval_min, uint16_t interval_max, uint16_t latency, uint16_t timeout);
+
+/**
+ * @brief get of the connection parameter for a given LE connection
+ * @param con_handle
+ * @param interval: 6 - 3200(unit: 1.25ms)
+ * @param latency
+ * @param timeout (unit: 10ms)
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_get_conn_param(uint16_t con_handle, uint16_t *interval, uint16_t *latency, uint16_t *timeout);
+
+/**
+ * @brief Disable latency, only valid for the slave role. Even if connection parameters are updated later, latency is disabled also
+ * @param con_handle
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_disable_latency(uint16_t con_handle);
+
+/**
+ * @brief Enable latency, only valid for the slave role.
+ * @param con_handle
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_enable_latency(uint16_t con_handle);
+
+/**
+  * @brief  notify data according to handle
+  * @param  connect handle
+  * @param  attribute handle
+  * @param  buf to be send
+  * @param  len(must be less than att mtu)
+  * @return return 0 if ok, other refer to ATT_ERR_CODE
+  */
+int ble_notify_for_handle(uint16_t con_handle, uint16_t att_handle, uint8_t* buf, uint16_t len);
+
+/**
+  * @brief  notify data according to handle
+  * @param  connect handle
+  * @param  attribute handle
+  * @param  buf to be send
+  * @param  len(must be less than att mtu)
+  * @param  kick_cfg, The value is as follows:
+            TXPKT_KICK_ENABLE: the Bluetooth thread is triggered to start sending data,
+            TXPKT_KICK_DISABLE: the Bluetooth thread will not be triggered to send data immediately, but the data will be cached
+            TXPKT_KICK_AUTO: Automatically managed by the Btstack
+            It is suitable for continuous data transmission, and can trigger the Bluetooth thread to send data at the last to reduce the switching of threads
+  * @return return 0 if ok, other refer to ATT_ERR_CODE
+  */
+int ble_notify_for_handle_kick(uint16_t con_handle, uint16_t att_handle, uint8_t* buf, uint16_t len, uint8_t kick_cfg);
+
+/**
+  * @brief  indicate data according to handle
+  * @param  connect handle
+  * @param  attribute handle
+  * @param  buf to be send
+  * @param  len(must be less than att mtu)
+  * @return return 0 if ok, other refer to ATT_ERR_CODE
+  */
+int ble_indicate_for_handle(uint16_t con_handle, uint16_t att_handle, uint8_t* buf, uint16_t len);
+
+
+/**
+  * @brief  Writes the characteristic value using the characteristic's value handle
+  * @param  connect handle
+  * @param  character
+  * @param  buf to be send
+  * @param  len(must be less than att mtu)
+  * @return return 0 if ok, other refer to ATT_ERR_CODE
+  */
+int ble_write_req_for_character(uint16_t con_handle, gatt_client_characteristic_t* character, uint8_t* buf, uint16_t len);
+
+/**
+  * @brief  Writes the characteristic value using the characteristic's value handle without an acknowledgment that the write was successfully performed.
+  * @param  connect handle
+  * @param  character
+  * @param  buf to be send
+  * @param  len(must be less than att mtu)
+  * @return return 0 if ok, other refer to ATT_ERR_CODE
+  */
+int ble_write_cmd_for_character(uint16_t con_handle, gatt_client_characteristic_t* character, uint8_t* buf, uint16_t len);
+
+/**
+ * @brief reads the characteristic value using the characteristic's value handle.
+ * @param  con_handle
+ * @param  character
+ * @return return 0 if ok, other refer to ATT_ERR_CODE
+ */
+int ble_read_req_for_character(uint16_t con_handle, gatt_client_characteristic_t* character);
+
+/**
+ * @brief reads the long characteristic value using the characteristic's value handle.
+ * @param  con_handle
+ * @param  character
+ * @param  offset
+ * @return return 0 if ok, other refer to ATT_ERR_CODE
+ */
+int ble_read_blob_for_character(uint16_t con_handle, gatt_client_characteristic_t* character, uint16_t offset);
+
+/**
+ * @brief set ble address type
+ * @param address type
+ */
+void gap_random_address_set_mode(gap_random_address_type_t random_address_type);
+
+/**
+ * @brief BLE initialize callback function registration,
+ * @param callback function, which will be called in bluetooth thread
+ */
+void ble_init_callback_register(ble_init_callback_t  func);
+
+/**
+ * @brief BLE test box initialize callback function registration,
+ * @param callback function, which will be called in bluetooth thread
+ */
+void ble_vs_tbox_init_callback_register(ble_vs_tbox_init_callback_t  func);
+
+/**
+ * @brief Register server packet handle
+ */
+void att_server_register_service_handler(att_service_handler_t * handler);
+
+/**
+ * @brief Register client packet handle
+ */
+void att_client_register_handler(att_client_handler_t * handler);
+
+/**
+ * @brief ble sm init
+ * @param security_req_en(whether to send an sm request when ble connecting)
+ * @param io_capability
+ * @param authentication_req_flag
+ */
+void ble_sm_init(uint8_t security_req_en, uint8_t io_capability, uint8_t authentication_req_flag);
+
+/**
+ * @brief Trigger Security Request
+ */
+void ble_sm_send_security_request(ble_con_handle_t con_handle);
+
+/**
+ * @brief setup ATT server
+ * @param db attribute database created by profile tool
+ */
+void att_server_init(uint8_t const * db);
+
+/**
+ * @brief Set up GATT client.
+ */
+void gatt_client_init(void);
+
+/**
+ * @brief get att mtu
+ * @param con_handle
+ * @return mtu if ok, 0 otherwise
+ */
+uint8_t att_server_get_mtu(uint16_t con_handle, uint16_t * mtu);
+
+/**
+ * @brief Get att mtu. If status is equal to ATT_ERROR_NO_ERROR, it returns the real value, otherwise the default value ATT_DEFAULT_MTU
+ * @param  con_handle
+ * @param  mtu
+ * @return return 0 if ok, other refer to ATT_ERR_CODE
+ */
+uint8_t gatt_client_get_mtu(uint16_t con_handle, uint16_t * mtu);
+
+/**
+ * @brief ble scan ctrl
+ * @param none
+ */
+void ble_scan_en(void);
+
+void ble_scan_dis(void);
+
+/**
+ * @brief  ble get scan status
+ * @param  none
+ * @return sta : 0-3(refer to le_scanning_state_t)
+ */
+le_scanning_state_t ble_get_scan_sta(void);
+
+/**
+ * @brief ble set scan param
+ * @param type    : 0 or 1,0(Passive scan,no scan_rsp),1(Active scan,adv+scan_rsp)
+ * @param interval: 4 - 16384(unit: 0.625ms)
+ * @param window  : 4 - 16384(less than or equal to interval unit: 0.625ms)
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_set_scan_param(scan_param_t* param);
+
+
+/**
+ * @brief Discovers all primary services. For each found service, BLE_EVT_SERVICE_FIND_RESULT will be generated and passed to the registered callback. BLE_EVT_PROFILE_FIND_DONE, marks the end of discovery.
+ * @param  con_handle
+ * @return return 0 if ok, other refer to ATT_ERR_CODE
+ */
+uint8_t ble_client_discover_primary_services(uint16_t con_handle);
+
+/**
+ * @brief Discovers a specific primary service given its UUID. For each found service, BLE_EVT_SERVICE_FIND_RESULT will be generated and passed to the registered callback. BLE_EVT_PROFILE_FIND_DONE, marks the end of discovery.
+ * @param con_handle
+ * @param uuid16
+ * @return return 0 if ok, other refer to ATT_ERR_CODE
+ */
+uint8_t ble_client_discover_primary_services_by_uuid16(uint16_t con_handle, uint16_t uuid16);
+
+uint8_t ble_client_discover_primary_services_by_uuid128(uint16_t con_handle, const uint8_t * uuid128);
+
+
+/**
+ * @brief Get field service from event BLE_EVT_SERVICE_FIND_RESULT
+ * @param event packet
+ * @param Pointer to storage for service
+ */
+void ble_service_query_result_get_service(const uint8_t * event, gatt_client_service_t * service);
+
+/**
+ * @brief Discovers all characteristics within the specified service. For each found characteristic, an le_characteristics_event_t with type set to BLE_EVT_CHARACTERISTIC_FIND_RESULT will be generated and passed to the registered callback. The gatt_complete_event_t with type set to BLE_EVT_PROFILE_FIND_DONE, marks the end of discovery.
+ * @param  callback
+ * @param  con_handle
+ * @param  service
+ * @return return 0 if ok, other refer to ATT_ERR_CODE
+ */
+uint8_t ble_client_discover_characteristics_for_service(uint16_t con_handle, gatt_client_service_t * service);
+
+/**
+ * @brief Get field characteristic from event BLE_EVT_CHARACTERISTIC_FIND_RESULT
+ * @param event packet
+ * @param Pointer to storage for characteristic
+ */
+void ble_characteristic_query_result_get_characteristic(const uint8_t * event, gatt_client_characteristic_t * characteristic);
+
+/**
+ * @brief Discover all characteristics within the specified service, and return those that match the given UUID. For each found characteristic, BLE_EVT_CHARACTERISTIC_FIND_RESULT will be generated and passed to the registered callback. BLE_EVT_PROFILE_FIND_DONE, marks the end of discovery.
+ * @param  con_handle
+ * @param  service
+ * @param  uuid
+ * @return return 0 if ok, other refer to ATT_ERR_CODE
+ */
+uint8_t ble_client_discover_characteristics_for_service_by_uuid16(uint16_t con_handle, gatt_client_service_t * service, uint16_t uuid16);
+
+uint8_t ble_client_discover_characteristics_for_service_by_uuid128(uint16_t con_handle, gatt_client_service_t * service, const uint8_t * uuid128);
+
+
+/**
+ * @brief Writes the client characteristic configuration of the specified characteristic.
+ * @param  con_handle
+ * @param  characteristic
+ * @param  configuration : GATT_CCC_NOTIFICATION, GATT_CCC_INDICATION
+ * @return return 0 if ok, other refer to ATT_ERR_CODE
+ */
+uint8_t ble_client_write_client_characteristic_configuration(uint16_t con_handle, gatt_client_characteristic_t * characteristic, uint16_t configuration);
+
+/**
+ * @brief Get specific characteristic struct by its uuid.
+ * @param  ALL characteristics to be matched
+ * @param  The number of characteristics
+ * @param  uuid
+ * @return return 0 if ok, other refer to ATT_ERR_CODE
+ */
+gatt_client_characteristic_t* ble_get_characteristic_for_uuid16(gatt_client_characteristic_t *characteristic, uint8_t num, uint16_t uuid16);
+
+gatt_client_characteristic_t* ble_get_characteristic_for_uuid128(gatt_client_characteristic_t *characteristic, uint8_t num, uint8_t *uuid128);
+
+
+/**
+  * @brief  Host renew resolvable private address timeout.
+  * @param  rpa params. mainly timeout in seconds and address resolution enable.
+  * @return none
+  */
+void ble_set_rslv_renew_to(rpa_param_t *param);
+
+/**
+  * @brief  Host set address resolution enable.
+  * @param  1 enable
+            0 disable.
+  * @return none
+  */
+void ble_set_rslv_enable(uint8_t enable);
+
+/**
+  * @brief  Host add device to resolvable address list.
+  * @param  privacy mode.
+  * @param  peer device address.
+  * @param  peer device irk.
+  * @return none
+  */
+void ble_add_dev_to_ral_list(gap_ral_dev_info_t *ral_dev_info);
+
+/**
+  * @brief  Host remove device from resolvable address list.
+  * @param  privacy mode.
+  * @param  peer device address.
+  * @param  peer device irk.
+  * @return none
+  */
+void ble_rmv_dev_from_ral_list(gap_ral_dev_info_t *ral_dev_info);
+
+/**
+  * @brief  Host add device to filter accept list.
+  * @param  size of wlist.
+  * @param  peer device identity address type.
+  * @param  peer device identity address.
+  * @return none
+  */
+void ble_add_dev_to_white_list(wlist_param_t *param);
+
+/**
+  * @brief  Host remove device from filter accept list.
+  * @param  peer device identity address type.
+  * @param  peer device identity address.
+  * @return none
+  */
+void ble_rmv_dev_from_white_list(wlist_param_t *param);
+
+/**
+  * @brief  Host read filter accept list size.
+  * @return none
+  */
+void ble_rd_dev_white_list(void);
+
+/**
+  * @brief  Host clear filter accept list.
+  * @return none
+  */
+void ble_clr_dev_white_list(void);
+
+/**
+  * @brief  Used by the user to enter passkey when BLE_EVT_PASSKEY_INPUT event is triggered.
+  * @return none
+  */
+bool ble_sm_passkey_input(uint16_t con_handle, uint32_t passkey);
+
+/**
+ * @brief Delete the bonding information of a specified address
+ * @param address_type
+ * @param address
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_delete_bonding_for_addr(bd_addr_type_t address_type, bd_addr_t address);
+
+/**
+ * @brief Delete the bonding information of a specified index
+ * @param index: [0,N), N can be get form ble_get_bonding_cnt() function
+ * @return return true if ok, invalid parameters will return false
+ */
+bool ble_delete_bonding_for_index(uint8_t index);
+
+/**
+ * @brief Delete all bonding information
+ */
+void ble_delete_bonding_all(void);
+
+/**
+ * @brief Get the number of bonding information
+ * @return The number of binding information
+ */
+uint8_t ble_get_bonding_cnt(void);
+
+
+/**
+ * @brief Gets the bonding information for the specified index
+ * @param index: [0,N), N can be get form ble_get_bonding_cnt() function
+ * @return specified bonding information
+ */
+sm_bonding_info_t* ble_get_bonding_info_for_index(uint8_t index);
+
+/**
+ * @brief  Initialize the timer memery pool.
+ * @note   This function and a series of related functions are invoked after bt init.
+ * @param  pool: memery pool head address.
+ * @param  size: byte size of memery pool, one alarm timer need 28Bytes memery.
+ * @retval None.
+ */
+void bt_alarm_timer_init(void *pool, uint32_t size);
+
+/**
+ * @brief  Extend the timer memery pool, it can be used before and after initialization.
+ * @param  pool: memery pool head address.
+ * @param  size: byte size of memery pool, one alarm timer need 28Bytes memery.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_mem_extend(void *pool, uint32_t size);
+
+/**
+ * @brief  Free the timer memery pool, and all timers in the space are released.
+ * @param  pool: memery pool head address.
+ * @param  size: byte size of memery pool, one alarm timer need 28Bytes memery.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_mem_free(void *pool, uint32_t size);
+
+/**
+ * @brief  Start specified id alarm timer.
+ * @param  handle: alarm timer handle.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_start(uint32_t handle);
+
+/**
+ * @brief  Stop specified id alarm timer.
+ * @param  handle: alarm timer handle.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_stop(uint32_t handle);
+
+/**
+ * @brief  Acquire a alarm timer.
+ * @param  handle: alarm timer handle.
+ * @param  interval: alarm timer trigger interval, unit [1, 0xffffff) ms.
+ * @param  is_repeat: trigger mode.
+ * @param  callback: callback function.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_acquire(uint32_t *handle, uint32_t interval, uint8_t is_repeat, void (*callback)(uint32_t handle));
+
+/**
+ * @brief  Release specified id alarm timer.
+ * @param  handle: alarm timer handle.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_release(uint32_t handle);
+
+/**
+ * @brief  Query specified id alarm timer remain time.
+ * @param  handle: alarm timer handle.
+ * @param  remain: the remain time for specified id alarm timer.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_query_time(uint32_t handle, uint32_t *remain);
+
+/**
+ * @brief  Modify specified id alarm timer interval, if the timer is start, it
+ *         will be re-start after update interval param.
+ * @param  handle: alarm timer handle.
+ * @param  interval: new interval, unit [1, 0xffffff) ms.
+ * @param  is_repeat: new is_repeat mode state.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_modify_interval(uint32_t handle, uint32_t interval, uint8_t is_repeat);
+
+/**
+ * @brief  Get the time that depends on the Bluetooth clock.
+ * @retval The value of current time, unit: (312.5 us).
+ */
+uint32_t bb_time_hs_get(void);
+
+/**
+ * @brief  Get connection rssi .
+ * @param  conhdl: connect handle.
+ * @retval -128 ~ 127dBm.
+ */
+int8_t ble_get_conn_rssi(uint16_t conhdl);
+
+/**
+ * @brief Set device random static address.
+ * @param device random static address.
+ * @return none
+ */
+void ble_set_static_addr(uint8_t *addr);
+
+void ble_event_start_hook_register(uint16_t con_handle, void (*callback)(void));
+
+/**
+ * @brief  Config BLE DataLength suggested max length, it should be invoke after stack init and before link created.
+ * @param  rx_octets: range [27, 251] in bytes, DataLengthExchange will refered to.
+ * @param  tx_octets: range [27, 251] in bytes, DataLengthExchange will refered to.
+ * @retval none
+ */
+void ble_suggested_max_length_write(uint16_t rx_octets, uint16_t tx_octets);
+
+
+#endif //_API_BTSTACK_H

+ 325 - 0
libs/ble/api_wireless.h

@@ -0,0 +1,325 @@
+#ifndef _API_WIRELESS_H
+#define _API_WIRELESS_H
+
+
+/**
+ * @format 216
+ * @param  con_handle
+ * @param  address_type
+ * @param  address
+ */
+#define WIRELESS_EVENT_CONNECTED                0x10
+
+/**
+ * @format 21
+ * @param  con_handle
+ * @param  disc_reason
+ */
+#define WIRELESS_EVENT_DISCONNECTED             0x11
+
+/**
+ * @format 11611N
+ * @param  advertising_event_type
+ * @param  address_type
+ * @param  address
+ * @param  rssi
+ * @param  data_length
+ * @param  data
+ */
+#define WIRELESS_EVENT_ADV_REPORT               0x12
+
+/**
+ * @format 1
+ * @param  reason
+ *      @var 0x04: init(page) state timeout.
+ *      @var 0x0c: connection command reject.
+ *      @var 0x0d: resource limit, bandwidth no enough for new link.
+ */
+#define WIRELESS_EVENT_INIT_TERMINATED          0x14
+
+
+typedef void (* wireless_event_callback_t)(uint8_t event_type, uint8_t *packet, uint8_t size);
+typedef void (* wireless_receive_callback_t)(uint16_t con_handle, uint8_t *packet, uint8_t size);
+
+
+typedef struct PACKED {
+    uint8_t  length;
+    uint8_t  type;
+    uint8_t  data[];
+} wireless_adv_slice_t;
+
+typedef struct PACKED {
+    uint8_t  event_type;
+    uint8_t  addr_type;
+    uint8_t  addr[6];
+    int8_t   rssi;
+    uint8_t  report_len;
+    uint8_t  report[];
+} wireless_adv_report_t;
+
+typedef struct PACKED {
+    uint8_t  reason;
+} wireless_init_terminated_t;
+
+typedef struct {
+    uint16_t intv;
+    uint8_t  adv_type;
+    uint8_t  peer_addr_type;
+    uint8_t  peer_addr[6];
+    uint8_t  data_len;
+    uint8_t  data_buf[31];
+} wireless_adv_param_t;
+
+typedef struct {
+    uint8_t conn_nb_support;
+    uint8_t conn_phy_forced;
+} wireless_setup_param_t;
+
+
+/**
+ * @brief  Wireless initialize event callback function registration.
+ * @param  handler: callback function which will be trigger when any event happen.
+ * @retval None.
+ */
+void wireless_event_handler_register(wireless_event_callback_t handler);
+
+/**
+ * @brief  Wireless initialize packet data receive callback function registration.
+ * @param  handler: callback function which will be trigger when new packet data received.
+ * @retval None.
+ */
+void wireless_receive_handler_register(wireless_receive_callback_t handler);
+
+/**
+ * @brief  Send data according to connection handle.
+ * @param  con_handle: connection handle.
+ * @param  buf: data buffer need to xfer.
+ * @param  size: length of data need to xfer in buf.
+ * @retval Return 0 if OK, other is wrong.
+ */
+int wireless_send_for_con(uint16_t con_handle, uint8_t *buf, uint16_t size);
+
+/**
+ * @brief  Release rxbuf and prepare for the next reception.
+ * @param  buffer: rxbuf, must be generated by the `wireless_receive_handler_register` callback func.
+ * @retval Return 0 if OK, other is wrong.
+ */
+int wireless_rxbuf_release(uint8_t *buffer);
+
+/**
+ * @brief  Wireless master create a connection by address.
+ *         interval, latency and timeout need to meet the follwing relationships:
+ *             (timeout * 10) > [(1 + latency) * interval * 1.25 * 2]
+ * @param  addr: peer device address.
+ * @param  addr_type: peer device address type.
+ * @param  interval: 2 - 3200 (unit: 1.25ms).
+ *                   4 - 3200 (unit: 1.25ms, more connections).
+ * @param  latency: 0 - 499 (unit: intv)
+ * @param  timeout: 10 - 3200 (unit: 10ms)
+ * @param  init_timeout: 1 - 0xfffffffe (unit: 1ms), and -1L means no timeout. timeout ind see `WIRELESS_EVENT_INIT_TERMINATED`
+ * @retval Return 0 if OK, other is wrong.
+ */
+int wireless_connect_by_addr(uint8_t *addr, uint8_t addr_type, uint16_t interval, uint16_t latency, uint16_t timeout, uint32_t init_timeout);
+
+/**
+ * @brief  Wireless set scan param.
+ * @param  type: scan type, select the following:
+ *             @arg 0: passive scanning.
+ *             @arg 1: active scanning.
+ * @param  interval: 4 - 16384 (unit: 0.625ms)
+ * @param  window: 4 - 16384 (unit: 0.625ms), should <= interval.
+ * @retval Return 0 if OK, other is wrong.
+ */
+int wireless_scan_param_set(uint8_t type, uint16_t interval, uint16_t window);
+
+/**
+ * @brief  Wireless scan control function.
+ * @param  enable: true will start scan if allow, or stop.
+ * @retval Return 0 if OK, other is wrong.
+ */
+int wireless_scan_ctrl(bool enable);
+
+/**
+ * @brief  Wireless scan state check, async exec by le msg.
+ * @retval Return true if scan active, else is stopped.
+ */
+bool wireless_scan_state_get(void);
+
+/**
+ * @brief  Wireless set advertisement param.
+ * @param  wireless_adv_param: adv param, see struct "wireless_adv_param_t".
+ * @retval Return 0 if OK, other is wrong.
+ */
+int wireless_adv_param_set(wireless_adv_param_t wireless_adv_param);
+
+/**
+ * @brief  Wireless adv control function.
+ * @param  enable: true will start adv if allow, or stop.
+ * @retval Return 0 if OK, other is wrong.
+ */
+int wireless_adv_ctrl(bool enable);
+
+/**
+ * @brief  Wireless adv state check, async exec by le msg.
+ * @retval Return true if ADV active, else is stopped.
+ */
+bool wireless_adv_state_get(void);
+
+/**
+ * @brief  Wireless config if prefem a latency.
+ * @param  con_handle: connection handle.
+ * @param  applied: true will allow wireless perform latency, or disallow.
+ * @retval Return 0 if OK, other is wrong.
+ */
+int wireless_latency_applied(uint16_t con_handle, bool applied);
+
+/**
+  * @brief  disconnect connection according to connect handle
+  * @param  con_handle
+  */
+int wireless_disconnect(uint16_t con_handle);
+
+/**
+  * @brief  Update connection parameter according to connection handle.
+  * @param  con_handle: connection handle.
+  * @param  intv_min: 2 - 3200(unit: 1.25ms)
+  *                   4 - 3200(unit: 1.25ms, more connection)
+  * @param  intv_max: 2 - 3200(unit: 1.25ms) interval_min <= interval_max
+  *                   4 - 3200(unit: 1.25ms, more connection)
+  * @param  lat: 0 - 499 (unit: intv)
+  * @param  sup_to: 10 - 3200 (unit: 10ms)
+  * @retval Return 0 if OK, other is wrong.
+  */
+int wireless_conn_update(uint16_t con_handle, uint16_t intv_min, uint16_t intv_max, uint16_t lat, uint16_t sup_to);
+
+/**
+ * @brief  Query connection parameter according to connction handle.
+ * @param  con_handle: connection handle.
+ * @param  intv: return conn interval value.
+ * @param  lat: return conn latency value.
+ * @param  sup_to: return conn supervise timeout value.
+ * @retval Return 0 if OK, other is wrong.
+ */
+int wireless_conn_query(uint16_t con_handle, uint16_t *intv, uint16_t *lat, uint16_t *sup_to);
+
+/**
+ * @brief Query maximum transmission unit according to connection handle.
+ * @param con_handle: connection handle.
+ * @param mtu[out]: return mtu value.
+ * @retval Return 0 if OK, other is wrong.
+ */
+int wireless_mtu_get(uint16_t con_handle, uint8_t *mtu);
+
+/**
+ * @brief  Register a function that will be invoke before each active frame start.
+ * @param  con_handle: connection handle.
+ * @param  callback: callback function when before frame start. It would be voke
+ * @retval Return 0 if OK, other is wrong.
+ */
+int wireless_frame_start_hook_register(uint16_t con_handle, void (*callback)(void));
+
+/**
+ * @brief  Initialize wireless module.
+ * @param  param: parameter configuration for wireless core setup.
+ * @retval None.
+ */
+void wireless_setup(wireless_setup_param_t const *param);
+
+/**
+ * @brief  De-initialize wireless module.
+ * @retval None.
+ */
+void wireless_off(void);
+
+/**
+  * @brief  ble fcc test mode config
+  * @param  rf_mode: FCC_RF_MODE
+  * @param  tx_power: [0,7]
+  * @param  tx_freq: [0,39],freq = 2402 + tx_freq * 2
+  * @param  tx_freq: [0,39],freq = 2402 + tx_freq * 2
+  * @param  phy_type: 0:1M  1:2M
+  * @param  todo: 1
+  */
+int fcc_test_ctrl(fcc_cfg_t *cfg);
+
+/**
+ * @brief  Initialize the timer memery pool.
+ * @note   This function and a series of related functions are invoked after bt init.
+ * @param  pool: memery pool head address.
+ * @param  size: byte size of memery pool, one alarm timer need 28Bytes memery.
+ * @retval None.
+ */
+void bt_alarm_timer_init(void *pool, uint32_t size);
+
+/**
+ * @brief  Extend the timer memery pool, it can be used before and after initialization.
+ * @param  pool: memery pool head address.
+ * @param  size: byte size of memery pool, one alarm timer need 28Bytes memery.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_mem_extend(void *pool, uint32_t size);
+
+/**
+ * @brief  Free the timer memery pool, and all timers in the space are released.
+ * @param  pool: memery pool head address.
+ * @param  size: byte size of memery pool, one alarm timer need 28Bytes memery.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_mem_free(void *pool, uint32_t size);
+
+/**
+ * @brief  Start specified id alarm timer.
+ * @param  handle: alarm timer handle.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_start(uint32_t handle);
+
+/**
+ * @brief  Stop specified id alarm timer.
+ * @param  handle: alarm timer handle.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_stop(uint32_t handle);
+
+/**
+ * @brief  Acquire a alarm timer.
+ * @param  handle: alarm timer handle.
+ * @param  interval: alarm timer trigger interval, unit [1, 0xffffff) ms.
+ * @param  is_repeat: trigger mode.
+ * @param  callback: callback function.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_acquire(uint32_t *handle, uint32_t interval, uint8_t is_repeat, void (*callback)(uint32_t handle));
+
+/**
+ * @brief  Release specified id alarm timer.
+ * @param  handle: alarm timer handle.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_release(uint32_t handle);
+
+/**
+ * @brief  Query specified id alarm timer remain time.
+ * @param  handle: alarm timer handle.
+ * @param  remain: the remain time for specified id alarm timer.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_query_time(uint32_t handle, uint32_t *remain);
+
+/**
+ * @brief  Modify specified id alarm timer interval, if the timer is start, it
+ *         will be re-start after update interval param.
+ * @param  handle: alarm timer handle.
+ * @param  interval: new interval, unit [1, 0xffffff) ms.
+ * @param  is_repeat: new is_repeat mode state.
+ * @retval result code.
+ */
+uint8_t bt_alarm_timer_modify_interval(uint32_t handle, uint32_t interval, uint8_t is_repeat);
+
+/* LPWR API */
+void bt_enter_sleep(void);
+bool bt_is_sleep(void);
+uint32_t bt_sleep_proc(void);
+void bt_exit_sleep(void);
+
+#endif // _API_WIRELESS_H

binární
libs/ble/libbtstack.a


binární
libs/ble/libbtstack_all_roles.a


binární
libs/ble/libbtstack_central.a


binární
libs/ble/libbtstack_scan_adv.a


binární
libs/ble/libbtstack_test.a


binární
libs/ble/wireless.a


binární
libs/ble/wireless_test.a


+ 56 - 0
libs/cpu/api_cm.h

@@ -0,0 +1,56 @@
+#ifndef _API_CM_H
+#define _API_CM_H
+
+#define PAGE_DATA_SIZE      250
+
+//每个Page 250 Byte
+#define PAGE0(x)            (x)
+#define PAGE1(x)            (0x100 + (x))
+#define PAGE2(x)            (0x200 + (x))
+#define PAGE3(x)            (0x300 + (x))
+
+#define MAX_CM_PAGE         2       //根据需要定义大小
+#define SYS_CM_PAGE_NUM     0
+#define BLE_CM_PAGE_NUM     1
+
+#define SYS_CM_PAGE(x)      PAGE0(x)
+#define BLE_CM_PAGE(x)      PAGE1(x)
+
+/**
+  * @brief  参数区初始化,用于保存一些掉电需要记忆的参数到内置的flash里面
+  * @param  page总数
+  * @param  参数区的起始地址,参数区一般设置在flash的最后那块区域
+  * @param  参数区总大小,至少8k
+  */
+void cm_init(uint max_page, u32 addr, uint len);    //
+
+/**
+  * @brief  将write写入cache的内容同步到spiflash中
+  */
+void cm_sync(void);
+void cm_read(void *buf, u32 addr, uint len);
+u8 cm_read8(u32 addr);
+u16 cm_read16(u32 addr);
+u32 cm_read32(u32 addr);
+
+/**
+  * @brief write数据到cache,需要调用cm_sync才会真正写入到spiflash中
+  */
+void cm_write(void *buf, u32 addr, uint len);
+
+void cm_write8(u32 addr, u8 val);
+void cm_write16(u32 addr, u16 val);
+void cm_write32(u32 addr, u32 val);
+
+/**
+  * @brief 清除CM的一整个Page
+  * @param 要清除的page起始地址
+  */
+void cm_clear(u32 addr);
+
+/**
+  * @brief 配置区(setting)初始化
+  */
+bool xcfg_init(void *xcfg, uint len);
+
+#endif

+ 147 - 0
libs/cpu/api_codec.h

@@ -0,0 +1,147 @@
+#ifndef _API_CODEC_H
+#define _API_CODEC_H
+
+
+/* 采样点数 -> PCM16字节数 */
+#define SAMPLE_2_PCM16_BYTE(x)              (x*2)
+/* PCM16字节数 -> 采样点数 */
+#define PCM16_BYTE_2_SAMPLE(x)              (x/2)
+/* 采样点数 -> ADPCM块字节数 */
+#define SAMPLE_2_ADPCM_BYTE(x)              ((x-1)/2+4)
+/* ADPCM块字节数 -> 采样点数 */
+#define ADPCM_BYTE_2_SAMPLE(x)              (((x-4)*2)+1)
+/* ADPCM块字节数 -> PCM16字节数 */
+#define ADPCM_BYTE_2_PCM16_BYTE(x)          (((x-4)*4)+2)
+
+
+//wav
+uint16_t wav_res_analize(u8 *head_buf, u8 *nch, u32 *spr, u16 *block_size);
+
+//sbc
+/* sampling frequency */
+enum {
+    SBC_FREQ_16000 = 0x00,
+    SBC_FREQ_32000 = 0x01,
+    SBC_FREQ_44100 = 0x02,
+    SBC_FREQ_48000 = 0x03,
+};
+
+/* blocks */
+enum {
+    SBC_BLK_4  = 0x00,
+    SBC_BLK_8  = 0x01,
+    SBC_BLK_12 = 0x02,
+    SBC_BLK_16 = 0x03,
+};
+
+/* subbands */
+enum {
+    SBC_SB_4 = 0x00,
+    SBC_SB_8 = 0x01,
+};
+
+/* channel mode */
+enum {
+    SBC_MODE_MONO         = 0x00,
+    SBC_MODE_DUAL_CHANNEL = 0x01,
+    SBC_MODE_STEREO       = 0x02,
+    SBC_MODE_JOINT_STEREO = 0x03,
+};
+
+/* allocation method */
+enum {
+    SBC_AM_LOUDNESS = 0x00,
+    SBC_AM_SNR      = 0x01,
+};
+/**
+  * @brief  Take the mono 16K sampling rate as an example
+  * @brief  mSBC:
+  * @brief  mSBC parameter cannot be changed, ilen = 120 * 2, olen = 57;
+  *
+  * @brief  SBC:
+  * @brief  subbands_l = subbands ? 8 : 4;
+  * @brief  blocks_l = 4 + (blocks * 4);
+  * @brief  channels_l = mode ? 2 : 1;
+  * @brief  SBC ilen = subbands_l * blocks_l * channels_l * 2;
+  * @brief  SBC olen = 4 + (4 * subbands_l * channels_l) / 8  +  ((blocks_l * channels_l * bitpool) + 7) / 8;  //Ignore the decimal point
+  *
+  * @brief  mic sample points = ilen / 2; (max: 128)
+  */
+void sbc_encode_init(uint8_t freq, uint8_t blocks, uint8_t subbands, uint8_t mode, uint8_t allocation, uint8_t bitpool);
+uint16_t sbc_encode_frame(uint8_t *ibuf, uint16_t ilen, uint8_t *obuf, uint16_t olen);
+void msbc_encode_init(void);
+uint16_t msbc_encode_frame(uint8_t *ibuf, uint16_t ilen, uint8_t *obuf, uint16_t olen);
+
+/**
+ * @brief  SBC decode
+ * 
+ * @brief  is_msbc:  1 -- msbc, 0 -- sbc.
+ * @brief  ibuf: SBC encoded buf
+ * @brief  ilen: SBC encoded buf len
+ * @brief  obuf: SBC decoded output buf
+ * 
+ * @brief  return: decode output buf sample points. (max: 128)
+ */
+void sbc_decode_init(bool is_msbc);
+uint16_t sbc_decode_frame(uint8_t *ibuf, uint16_t ilen, uint8_t *obuf);
+
+//adpcm
+/**
+  * @brief  ima adpcm encode compression ratio 4:1
+  * @brief  encode output buf format:2byte prediction sample, 1byte index, 1byte reserve, nbyte data
+  * @brief  decode input buf format:2byte prediction sample, 1byte index, 1byte reserve, nbyte data
+  * 
+  * @brief  ima adpcm need one more sample point. reference routine bsp_sdadc_voice.c
+  * 
+  * @param  p_dst: output buf
+  * @param  p_src: input buf
+  * @param  sample_len:sample points
+  */
+void adpcm_decode_block(uint8_t *p_dst,uint8_t *p_src,uint32_t sample_len);
+void adpcm_encode_block(uint8_t *p_dst, uint8_t *p_src, uint32_t sample_len);
+void adpcm_decode_block_big(uint8_t *p_dst, uint8_t *p_src, uint32_t sample_len);
+void adpcm_encode_block_big(uint8_t *p_dst, uint8_t *p_src, uint32_t sample_len);
+void adpcm_sample_idx_set(int16_t idx);
+void adpcm_sample_idx_reset(void);
+void adpcm_presample_set(int32_t pcm_16);
+uint16_t adpcm_sample_idx_get(void);
+int16_t adpcm_presample_get(void);
+
+//opus
+/**
+  * @brief  opus encode initialization, 16bit, 20ms one frame
+  * @brief  opus encode requires high computing power, so the system needs to raise the main frequency to more than 120M
+  * @param  samplerate: sampling rate, only support 8000 or 16000
+  * @param  nch: number of channels,only support 1 channel now
+  * @param  bit_rate:16000 or 32000, 16000-->1:16  32000-->1:8
+  * @return true or false
+  */
+bool opus_enc_init(u32 samplerate, u32 nch, u32 bit_rate);
+
+/**
+  * @brief  opus encode exit
+  * @return true or false
+  */
+bool opus_enc_exit(void);
+
+/**
+  * @brief  opus encode process
+  * @param  pcm: Data to be encoded
+            At a sample rate of 16K, 16bit, 20ms one frame, pcm_size = (16 * 20 * 2)byte
+            Ensure that there is a sufficient length of data
+  * @param  out: opus encoded data, out_len = pcm_size / 16
+            Ensure that there is a sufficient length of data
+  */
+int32_t opus_enc_process(int16_t *pcm, u8 *out);
+
+/**
+  * @brief  mp3 decode
+  */
+bool mp3_dec_frame(void);
+void mp3_music_pcm_kick(void);
+u8 mp3_music_dec_sta_get(void);
+void mp3_music_dec_sta_set(u8 sta);
+bool mp3_res_play_kick(u32 addr, u32 len);
+void mp3_res_play_exit(void);
+
+#endif // _API_CODEC_H

+ 45 - 0
libs/cpu/api_interrupt.h

@@ -0,0 +1,45 @@
+#ifndef _API_INTERRUPT_H
+#define _API_INTERRUPT_H
+
+#define GLOBAL_INT_DISABLE()    uint32_t cpu_ie = PICCON&BIT(0); PICCONCLR = BIT(0)
+#define GLOBAL_INT_RESTORE()    PICCON |= cpu_ie
+
+/**
+ * @brief XBOX Interrupt Number Definition.
+ */
+typedef enum {
+    IRQn_SOFT = 2,
+    IRQn_TMR0,
+    IRQn_TMR1,
+    IRQn_TMR2,
+    IRQn_IR_QDEC_LEDC,
+    IRQn_USB_CONTROL,
+    IRQn_SD,
+    IRQn_KEY_SCAN,
+    IRQn_SDADC_DMA,
+    IRQn_SDADC_SAMPLE               = 13,
+    IRQn_UART0_UDET,
+    IRQn_HSUART,
+    IRQn_TMR3,
+    IRQn_DAC_DMAIN                  = 19,
+    IRQn_SPIx,
+    IRQn_URAT0_KEY_UDET_KEY,
+    IRQn_FREQUENCY_DET_TOUCH_KEY    = 23,
+    IRQn_PORT                       = 26,
+    IRQn_SARADC                     = 28,
+    IRQn_RTC_SECOND_ALARM_LVD_WDT,
+    IRQn_IIC,
+    IRQn_TICK0,
+} IRQ_TYPEDEF;
+
+typedef void (*isr_t)(void);
+
+/**
+ * @brief system interrupt init
+ * @param interrupt number,define in IRQ_TYPEDEF
+ * @param interrupt priority, 1 is high priority, 0 is low priority
+ * @param interrupt callback function
+ */
+bool sys_irq_init(int vector, int pr, isr_t isr);
+
+#endif

+ 19 - 0
libs/cpu/api_key.h

@@ -0,0 +1,19 @@
+#ifndef _API_KEY_H
+#define _API_KEY_H
+
+// Key Type
+#define KEY_SHORT               0x0000
+#define KEY_SHORT_UP            0x0800
+#define KEY_LONG                0x0A00
+#define KEY_LONG_UP             0x0C00
+#define KEY_HOLD                0x0E00
+#define KEY_DOUBLE              0x1800      //2击
+#define KEY_THREE               0x1900      //3击
+#define KEY_FOUR                0x1A00      //4击
+#define KEY_FIVE                0x1B00      //5击
+
+
+void multiple_key_init(u16 internal, u16 *allow_multiple_key_table, u8 count_of_multiple_key);
+u16 key_multi_press_process(u16 key_val);
+
+#endif // _API_KEY_H

+ 47 - 0
libs/cpu/api_list.h

@@ -0,0 +1,47 @@
+#ifndef _API_LIST_H
+#define _API_LIST_H
+
+
+typedef struct list_hdr {
+    struct list_hdr *next;
+} list_hdr_t;
+
+typedef struct {
+    struct list_hdr *first;
+    struct list_hdr *last;
+} list_t;
+
+
+/**
+ * @brief  Initialize a list of free element in target pool.
+ * @param  list: Pointer to the list.
+ * @param  pool: Pointer to the free pool.
+ * @param  elt_size: Size of each element of the free pool.
+ * @param  elt_cnt: Count of elements in free pool.
+ * @retval None.
+ */
+void list_pool_init(list_t *list, void *pool, size_t elt_size, uint32_t elt_cnt);
+
+/**
+ * @brief  Push an element into target list rear.
+ * @param  list: Pointer to the list.
+ * @param  list_hdr: Pointer to the target element.
+ * @retval None.
+ */
+void list_push_back(list_t *list, list_hdr_t *list_hdr);
+
+/**
+ * @brief  Pop first element from target list.
+ * @param  list: Pointer to the list.
+ * @retval List element head pointer.
+ */
+list_hdr_t *list_pop_front(list_t *list);
+
+/**
+ * @brief  Statistic the element counts in list.
+ * @param  list: Pointer to the list.
+ * @retval Counts of element in list.
+ */
+uint16_t list_size(list_t *list);
+
+#endif // _API_LIST_H

+ 13 - 0
libs/cpu/api_msg.h

@@ -0,0 +1,13 @@
+#ifndef _API_MSG_H
+#define _API_MSG_H
+
+
+#define NO_MSG              0
+
+void msg_queue_init(void);
+void msg_queue_clear(void);
+void msg_enqueue(u16 msg);
+u16 msg_dequeue(void);
+void msg_queue_detach(u16 msg, u8 flag);        //flag=0,消息池中剔除msg消息; flag=1,消息池只保留msg消息
+
+#endif // _API_MSG_H

+ 61 - 0
libs/cpu/api_os.h

@@ -0,0 +1,61 @@
+#ifndef _API_OS_H_
+#define _API_OS_H_
+
+typedef struct _thread_cfg_t{
+    uint8_t enable;
+    uint8_t priority;
+    uint16_t stack_heap_size;
+}thread_cfg_t;
+
+struct thread_cfg_cb{
+    thread_cfg_t bt_hw;
+    thread_cfg_t bt_stack;
+    thread_cfg_t aupcm;
+    thread_cfg_t dirver;
+    thread_cfg_t timer;
+    thread_cfg_t main;
+};
+
+typedef void (*thd_drv_callback_t)(uint8_t msg);
+typedef void (*thd_aupcm_callback_t)(uint8_t msg);
+
+/**
+ * @brief  Post a msg to driver thread.
+ * @note   it should be called after 'thread_driver_user_callback_register', or failed.
+ * @param  msg: the msg need to post to driver thread.
+ * @retval true if msg post successfully, or false.
+ */
+bool thread_driver_msg_post(uint8_t msg);
+
+/**
+ * @brief  Register a callback func for driver vendor msg.
+ * @note   the driver thread should be exists, or will failed.
+ * @param  callback: the callback func.
+ * @retval true if func register successfully, or false.
+ */
+bool thread_driver_user_callback_register(thd_drv_callback_t callback);
+
+/**
+ * @brief  Post a msg to aupcm thread.
+ * @note   it should be called after 'thread_aupcm_callback_register', or failed.
+ * @param  msg: the msg need to post to aupcm thread.
+ * @retval true if msg post successfully, or false.
+ */
+bool thread_aupcm_msg_post(uint8_t msg);
+
+/**
+ * @brief  Register a callback func for aupcm thread msg.
+ * @note   the aupcm thread should be exists, or will failed.
+ * @param  callback: the callback func.
+ * @retval true if func register successfully, or false.
+ */
+bool thread_aupcm_callback_register(thd_aupcm_callback_t callback);
+
+void thread_driver_create(void);
+
+void thread_aupcm_create(void);
+
+void thread_btstack_create(void);
+
+#endif
+

+ 84 - 0
libs/cpu/api_pwr.h

@@ -0,0 +1,84 @@
+#ifndef _API_PWR_H_
+#define _API_PWR_H_
+
+typedef enum{
+    PMU_CFG_BUCK_EN = BIT(0),
+    PMU_CFG_CHARGE_DIS = BIT(1),
+    PMU_CFG_VUSB_TO_VDDIO = BIT(7),
+}PMU_CFG_ENUM;
+
+/**
+  * @brief  pmu initialization
+  * @param  pmu_cfg: PMU_CFG_ENUM
+  */
+void pmu_init(u8 pmu_cfg);
+
+/**
+  * @brief  get vddio level, vddio = 2.4V + 0.1V * level
+  * @return  level: 0 ~ 0xF
+  */
+u8 pmu_get_vddio(void);
+
+/**
+  * @brief  get vrtc24 voltage values, uint:mV
+  * @return  vrtc24 voltage value, about 2400mv
+  */
+u16 pmu_get_vrtc24_mv(void);
+
+/**
+  * @brief  set vddio level, vddio = 2.4V + 0.1V * level
+  * @param  level: 0 ~ 0xF
+  */
+void pmu_set_vddio(u8 level);
+
+/**
+  * @brief  get vddcore level, vddcore = 0.7 + 0.025 * x
+  * @return  level: 0 ~ 0x1F
+  */
+u8 pmu_get_vddcore(void);
+
+/**
+  * @brief  set vddcore level, vddcore = 0.7 + 0.025 * x
+  * @param  level: 0 ~ 0x1F
+  */
+void pmu_set_vddcore(uint8_t level);
+
+/**
+  * @brief  get vbat saradc voltage distribution coefficient
+  * @return  vbat saradc voltage distribution coefficient, about 2 * 1000
+  */
+u16 pmu_get_vbatdet(void);
+
+/**
+  * @brief  get lvd level
+  * @return  level: 0 ~ 0x7
+  */
+u8 pmu_get_lvd(void);
+
+/**
+  * @brief  set lvd level
+    0: 1.7V
+    1: 1.8V
+    2-7: 2.0V + 0.2V * (level - 2)
+  * @param  level: 0 ~ 0x7
+  */
+void pmu_set_lvd(u8 level);
+
+/**
+  * @brief  enable buck mode or disable buck mode
+  * @param 1:enable buck mode 0:disable buck mode, pmu work in ldo mode
+  */
+void pmu_set_buck_mode(u8 buck_en);
+
+bool pmu_vddio_to_flash(void);
+
+u8 charge_const_curr_trim(u8 val);
+u8 charge_cutoff_curr_trim(u8 val);
+
+void lowpwr_sleep_sfr_save(void);
+void lowpwr_sleep_sfr_resume(void);
+
+void lp_sleep(void (*sleep_cb)(void), void (*wakeup_cb)(void));
+
+#endif // _API_PWR_H_
+

+ 65 - 0
libs/cpu/api_sdadc.h

@@ -0,0 +1,65 @@
+#ifndef _API_SDADC_H
+#define _API_SDADC_H
+
+/* [Warming] please use new api "thread_aupcm_callback_register" and "thread_aupcm_msg_post */
+/* In the new api, you should use custom msg instead of following msg */
+#define SDADC_DONE_TYPEDEF      uint8_t
+#define SDADC_ALL_DONE          0
+#define SDADC_HALF_DONE         1
+
+typedef enum {
+    MIC_ANALOG_CFG_NOT_RC   = 0,
+    MIC_ANALOG_CFG_NOT_R,
+    MIC_ANALOG_CFG_NORMAL,
+    MIC_ANALOG_CFG_DIRECT,
+} MIC_ADC_CFG;
+
+/* [Warming] please use new api "thread_aupcm_callback_register" and "thread_aupcm_msg_post */
+typedef void (*sdadc_done_callback)(SDADC_DONE_TYPEDEF msg);
+
+/**
+  * @brief  Set the sdadc sampling completion callback function
+            This callback function will be called after sdadc_done_proc_kick is executed
+  * @param  func:callback function
+  */
+/* [WARMING] please use new api thread_aupcm_callback_register */
+void sdadc_done_callback_set(sdadc_done_callback func);
+
+/**
+  * @brief  Triggers the adpcm thread to handle the sdadc callback function, which will be set by sdadc_done_callback_set.
+            This function is usually called inside the sdadc interrupt function
+  * @param  type:SDADC_ALL_DONE or SDADC_HALF_DONE
+  */
+/* [WARMING] please use new api thread_aupcm_msg_post */
+void sdadc_done_proc_kick(SDADC_DONE_TYPEDEF msg);
+
+void mic_adc_init(MIC_ADC_CFG mic_type);
+
+void mic_adc_deinit(void);
+
+/**
+  * @brief  Enable and set the bias voltage of the mic pin, mic_bias pin only map to PB1.
+            Before use, you need to set the PB1 pin to analog output, turn off the pull up and down
+            This function must be called after sdadc_init
+  * @param  level: [0,7], bias voltage = 1.8V + level * 0.2V
+  * @param  res: [8,4,2,1], res = 8k, 4k, 2k, 1k
+  */
+void mic_bias_open(u8 level, u8 res);
+
+void mic_bias_close(void);
+
+/**
+  * @brief  Enable and set the bias voltage of the mic pin, mic_bias pin only map to PB1.
+            Before use, you need to set the PB1 pin to analog output, turn off the pull up and down
+            This function must be called after sdadc_init
+  * @param  level: [0,7], bias voltage = 1.8V + level * 0.2V
+  */
+void mic_bias_level_set(u8 level);
+
+/**
+  * @brief  Set mic analog gain
+  * @param  level: [0,7], analog gain = -6dB + level * 6dB
+  */
+void mic_analog_gain_set(u8 level);
+
+#endif //_API_SDADC_H

+ 107 - 0
libs/cpu/api_sys.h

@@ -0,0 +1,107 @@
+#ifndef _API_SYS_H_
+#define _API_SYS_H_
+
+#define CACHE_ADDR          0x70000
+
+typedef uint8_t flash_id_t[16];
+
+
+/**
+  * @brief  Sets whether to call the timer2 interrupt callback function
+  * @param  tmr5ms_en: set to true, usr_tmr5ms_thread_callback will be called once in 5ms
+  * @param  tmr1ms_en: set to true, usr_tmr1ms_isr_callback will be called once in 1ms
+  */
+void sys_set_tmr_enable(bool tmr5ms_en, bool tmr1ms_en);
+
+/**
+  * @brief  system reset init
+  * @param  wk pin 10s reset config
+  * @return system reset source
+    reset source:   BIT(31):PWRUP_RST
+                    BIT(24):SW_RST
+                    BIT(19):WK Pin 10S_RST
+                    BIT(18):WAKEUP_RST
+                    BIT(17):VUSB_RST
+                    BIT(16):WDT_RST
+                    BIT(20)|BIT(7):LVD_RST
+  */
+u32 sys_rst_init(bool wko10s_rst);
+
+/**
+  * @brief  dump the system reset source info
+  * @param  reason: system reset source, can be get by the return value of the function sys_rst_init
+  */
+void sys_rst_dump(u32 reason);
+
+/**
+  * @brief  The system reset can be triggered by software
+  * @param  software reset source, it can be define by the user
+  */
+void sw_reset_kick(u8 source);
+
+/**
+  * @brief  Get the software reset source,it must be called as soon as the system is reset
+  * @return software reset source
+  */
+u8 sw_reset_source_get(void);
+
+void xosc_init(void);
+
+
+/**
+  * @brief  Gets a random number between 0 and num
+  * @param  number
+  */
+u16 get_random(u16 num);
+
+/**
+  * @brief  get the number of bytes used by the UTF8 character
+  * @param  Returns the number of bytes used by the UTF8 character
+  */
+u8 utf8_char_size_get(u8 code);
+
+/**
+  * @brief  utf8 convert to unicode
+  * @param  in
+  * @param  char_size
+  */
+u16 utf8_convert_to_unicode(u8 *in, u8 char_size);
+
+int s_abs(int x);
+
+bool bt_get_ft_trim_value(void *rf_param);
+
+void io_sleep(void);
+
+void io_resume(void);
+
+/**
+  * @brief  Read data from the chip's built-in flash
+  * @param  buf
+  * @param  flash address to read
+  * @param  len
+  */
+uint os_spiflash_read(void *buf, u32 addr, uint len);
+
+/**
+  * @brief  Program data to the chip's built-in flash
+  * @param  buf
+  * @param  flash address to program to
+  * @param  len, must be less than or equal to 256
+  */
+void os_spiflash_program(void *buf, u32 addr, uint len);
+
+/**
+  * @brief  Erase the chip's built-in flash
+  * @param  flash base addresses that need to be erased, erase 4K bytes at a time
+  */
+void os_spiflash_erase(u32 addr);
+
+/**
+  * @brief  Get the chip's built-in flash id
+  * @param  flash id buf
+  */
+void os_spiflash_id_get(flash_id_t id);
+
+#endif // _API_SYS_H_
+

+ 74 - 0
libs/cpu/api_sysclk.h

@@ -0,0 +1,74 @@
+#ifndef _API_SYSCLK_H_
+#define _API_SYSCLK_H_
+
+enum {
+    SYS_RC2M,
+    SYS_24M,
+    SYS_48M,
+    SYS_60M,
+    SYS_80M,
+    SYS_120M,
+    SYS_160M,
+};
+
+enum {
+    CLK_31K25,
+    CLK_RCDIV,
+};
+
+enum {
+    INDEX_VOICE     = 0,
+    INDEX_DECODE,
+    INDEX_STACK,
+    INDEX_USER,
+    INDEX_MAX_NB,
+};
+
+/**
+  * @brief  Get the clock value last set for the function sys_clk_set()
+  * @return [SYS_RC2M - SYS_160M]
+  */
+u8 sys_clk_get(void);
+
+/**
+  * @brief  Get the current clock of the system
+  * @return [SYS_RC2M - SYS_160M]
+  */
+u8 sys_clk_get_cur(void);
+
+u32 sys_clk_nhz_get(void);
+
+/**
+  * @brief  Get RC2M clk frequency
+  * @param  type: 0: system rc2m  1:rtc rc2m
+  * @return RC2M clk frequency
+  */
+u32 rc2m_clk_nhz_get(u8 type);
+
+u32 pll_clk_nhz_get(void);
+
+/**
+  * @brief  Set system clock,
+  * @attention  If the clock to be set is lower than the value which be set by the function sys_clk_lower_limit_unlock, the setting will not take effect now
+  * @param [SYS_RC2M, SYS_160M]
+  */
+void sys_clk_set(u32 clk_sel);
+
+bool sys_clk_lower_limit_all_unlock(void);
+
+/**
+  * @brief Unset the value which be set by sys_clk_lower_limit_lock
+  * @param index: [INDEX_VOICE, INDEX_MAX_NB)
+  * @return true or false
+  */
+bool sys_clk_lower_limit_unlock(uint8_t index);
+
+/**
+  * @brief Set the minimum clock frequency for the system
+  * @attention  If the clock to be set is lower than the current clock of the system, the setting will not take effect now
+  * @param index: [INDEX_VOICE, INDEX_MAX_NB) sys_clk:[SYS_RC2M - SYS_160M]
+  * @return true or false
+  */
+bool sys_clk_lower_limit_lock(uint8_t index, uint8_t sys_clk);
+
+#endif

+ 47 - 0
libs/cpu/api_update.h

@@ -0,0 +1,47 @@
+#ifndef _API_UPDATE_H
+#define _API_UPDATE_H
+
+typedef enum {
+    FOT_ERR_OK,
+    FOT_ERR_NO_UPDATA,
+    FOT_ERR_KEY,
+    FOT_ERR_FILE_FORMAT,
+    FOT_ERR_FILE_TAG,
+    FOT_ERR_FILE_DATA,
+    FOT_ERR_MAC_SIZE,
+    FOT_ERR_START,
+    FOT_ERR_DOWN_START,
+    FOT_ERR_HEAD2_START,
+    FOT_ERR_DOWN_LAST,
+    FOT_ERR_CRC_VERIFY,
+    FOT_ERR_AREA_SIZE,
+    /*以上err类型和库里面对应,通过fot_get_err()获取到*/
+
+    FOT_ERR_SEQ = 0x40,
+    FOT_ERR_DATA_LEN,
+
+    FOT_UPDATE_PAUSE = 0xfd,
+    FOT_UPDATE_CONTINUE = 0xfe,
+    FOT_UPDATE_DONE = 0xff,
+} FOT_ERR_ENUM;
+
+//FOTA双备份升级
+void fot_init(void);
+void fot_deinit(void);
+u32 fot_get_curaddr(void);
+bool fot_write(void *buf, u32 addr, u32 len);
+u8 fot_get_err(void);
+bool fot_breakpoint_info_read(void);
+bool is_fot_update_success(void);
+u32 fot_head_crc_get(void);
+
+//FOTA压缩升级
+void ota_pack_init(void);
+void ota_pack_deinit(void);
+bool ota_pack_write(u8 *buf);
+u8 ota_pack_get_err(void);
+bool ota_pack_is_update_success(void);
+bool ota_pack_breakpoint_info_read(void);
+u32 ota_pack_get_curaddr(void);
+
+#endif

binární
libs/cpu/libc.a


binární
libs/cpu/libgcc.a


binární
libs/cpu/libm.a


binární
libs/cpu/libplatform.a


+ 73 - 0
libs/motor/api_zerocross_detection.h

@@ -0,0 +1,73 @@
+#ifndef __ZEROCROSS_DETECTION_H__
+#define __ZEROCROSS_DETECTION_H__
+
+#include "include.h"
+
+/*----------------------Macro definition----------------*/
+#define PHASE_AB										5
+#define PHASE_AC										1
+#define PHASE_BC										3
+#define PHASE_BA										2
+#define PHASE_CA										6
+#define PHASE_CB										4
+
+/*-------------------Observers variable-----------------*/
+
+
+typedef struct
+{
+    uint16_t closesendware_count;
+    uint16_t zco_delaytime_count;
+    uint16_t  zco_stream_time;
+    uint16_t  closeSendWare_AvgCount;
+    uint16_t  pastSendWare_count;
+    uint8_t  delay_time;
+//    uint8_t  zco_phase;
+//    uint16_t szco_compensation_value;
+} mc_zero_observers_t;
+
+//typedef struct
+//{
+//    uint16_t adc_convertedvaluetab_a[3];
+//    uint16_t adc_convertedvaluetab_b[3];
+//    uint16_t adc_convertedvaluetab_c[3];
+//    uint16_t adc_convertedvaluetab_vbus[3];
+//    uint16_t adc_centerreference_value[3];
+//} mc_adc_value_t;
+
+typedef struct
+{
+    uint32_t adc_convertedvaluetab_a[3];
+    uint32_t adc_convertedvaluetab_b[3];
+    uint32_t adc_convertedvaluetab_c[3];
+    uint32_t adc_convertedvaluetab_vbus[3];
+    uint32_t adc_centerreference_value[3];
+} mc_adc_value_t;
+
+typedef enum{
+	ADC_STATE_NULL = 0,
+	ADC_STATE_STREAM,
+	ADC_STATE_CHECK,
+	ADC_STATE_CLOSE,
+	ADC_STATE_SWITCHPHASE
+} ADCEXECUTESTATE_T;
+
+//AT(.motor.variable) ADCEXECUTESTATE_T gadcexecute_state;
+//AT(.motor.variable)
+extern mc_zero_observers_t mc_zero_observers;
+//AT(.motor.variable)
+//extern ADCEXECUTESTATE_T gadcexecute_state;
+//AT(.motor.variable)
+extern mc_adc_value_t gmc_sczco_advalue_params;
+
+void waitting_stream(uint16_t sczeo_stream_time,uint8_t* mc_observers_state);
+void bemf_to_zero_judge(uint8_t phase_mumber,uint8_t direction,uint8_t* mc_observers_state);
+//uint8_t zero_crossing_detection(uint8_t phase_number,uint8_t direction,
+//                                uint16_t sczeo_stream_time,uint8_t* mc_observers_state);
+void comparator_zero_detection(uint8_t phase_mumber,uint8_t direction,uint8_t* mc_observers_state);
+uint8_t comparator_delay_zero_time(uint8_t phase_number,uint8_t direction,uint8_t* mc_observers_state);
+uint8_t delay_zero_time(uint8_t phase_number,uint8_t direction,uint8_t* mc_observers_state);
+void szco_dataget(uint32_t vbus,uint32_t ua,uint32_t ub,
+                  uint32_t uc,uint8_t phase,uint16_t compensation_value,
+                  uint16_t duty_pwm,uint16_t timer_peroid);
+#endif // __ZEROCROSS_DETECTION_H__

binární
libs/motor/libobservers.a


+ 27 - 0
libs/usb/api_device.h

@@ -0,0 +1,27 @@
+#ifndef _API_DEVICE_H
+#define _API_DEVICE_H
+
+enum {
+    DEV_USBPC           = 0,
+    DEV_TOTAL_NUM,
+};
+
+typedef enum {
+    USB_BUS_EVENT_NONE          = 0,
+    USB_BUS_EVENT_DISCONNECT,
+    USB_BUS_EVENT_CONNECT
+} USB_BUS_EVENT_TYPEDEF;
+
+
+void dev_init(u8 online_cnt, u8 offline_cnt);
+bool dev_is_online(u16 dev_num);
+bool dev_online_filter(u16 dev_num);
+bool dev_offline_filter(u16 dev_num);
+void dev_delay_times(u8 dev_num, u8 times);          //同时设置, online去抖延时 和 offline 去抖延时, 它们的延时一样的,兼容以前.
+void dev_delay_online_times(u8 dev_num, u8 times);   //单独设置online去抖延时(新增).
+void dev_delay_offline_times(u8 dev_num, u8 times);  //单独设置offline 去抖延时.(新增)
+void dev_clr_sta(u8 dev_num);
+
+USB_BUS_EVENT_TYPEDEF usb_bus_event_check(void);
+
+#endif // _API_DEVICE_H

+ 115 - 0
libs/usb/api_usb.h

@@ -0,0 +1,115 @@
+#ifndef _USB_API_H
+#define _USB_API_H
+
+#include "usb_define.h"
+
+#define EP_CNT                  4
+
+#define USB_EP0_MAX_SIZE        64
+#define USB_EP1_MAX_SIZE        64
+#define USB_EP2_MAX_SIZE        256
+#define USB_EP3_MAX_SIZE        1023
+
+
+enum {
+    USBCHK_ONLY_HOST,
+    USBCHK_ONLY_DEVICE,
+    USBCHK_OTG,
+};
+
+enum {
+    USB_DISCONNECT,
+    USB_DEV_CONNECTED,
+    USB_HOST_CONNECTED,
+};
+
+enum {
+    ///usb device message.
+    MSG_USB_EP_RESET = 32,          //usb device ep0 reset message.
+    MSG_USB_EP0_CTL_FLOW,           //usb device control flow message.
+    MSG_USB_EP1_IN,
+    MSG_USB_EP1_OUT,
+    MSG_USB_EP2_IN,
+    MSG_USB_EP2_OUT,
+    MSG_USB_EP3_IN,
+    MSG_USB_EP3_OUT,
+    MSG_USB_SUSPEND,
+    MSG_USB_RESUME,
+};
+
+typedef struct _epcb_t {
+    psfr_t sfr;
+
+    u8 type;                        //EP Type: Ctrl, Bulk, Int, ISOC
+    u8 index;                       //EP Index
+    volatile u8  error      : 1,    //USB通信出错
+        dir                 : 1,    //EP的方向
+        halt                : 1,    //Halt标志
+        first_pkt           : 1;    //Transfer first packet
+
+    u8 *buf;                        //EP的BUF地址
+
+    const u8 *xptr;                 //当前发送/接收指针
+    u16 xlen;                       //当前发送/接收剩余
+    u16 xcnt;                       //已发送/接收统计
+    u16 epsize;                     //EP Size
+} epcb_t;
+
+typedef struct _spb_wrap_t {
+    union {
+        struct {
+            u8 recipient        : 5,
+                type            : 2,
+                dir             : 1;
+        };
+        u8 reqtype;
+    };
+    u8 req;
+    u16 val;
+    u16 index;
+    u16 len;
+} spb_wrap_t;
+
+
+typedef bool (*usb_init_handler)(void);
+typedef bool (*usb_evt_handler)(uint8_t event, spb_wrap_t *spb, uint8_t *data, uint8_t data_len);
+
+typedef struct {
+    usb_init_handler init;
+    usb_evt_handler evt;
+}usb_handler_cb_t;
+
+void usb_handler_register(usb_handler_cb_t *handler);
+void usb_sof_hook_register(void (*callback)(void));
+
+
+u8 usbchk_connect(u8 mode);
+u8 usbchk_host_connect(void);
+
+void usb_init2(void);
+void usb_deinit2(void);
+// void usb_init(void);
+// void usb_disable(void);
+// void usb_device_enter(void);
+// void usb_device_exit(void);
+bool usb_device_is_suspend(void);
+void usb_device_suspend_enable(void);
+void usb_device_resume(void);
+
+
+void usb_ep_init(epcb_t *epcb);
+uint16_t usb_ep_get_max_len(uint8_t ep_index);
+uint16_t usb_ep_get_rx_len(epcb_t *epcb);
+void usb_ep_clear_rx_fifo(epcb_t *epcb);
+bool usb_ep_transfer(epcb_t *epcb);
+bool usb_ep_start_transfer(epcb_t *epcb, uint len);
+bool usb_ep0_start_transfer(void *buf, uint len);
+epcb_t * usb_ep_get_for_index(uint8_t index, uint8_t dir);
+void usb_ep_reset(epcb_t *epcb);
+void usb_ep_clear(epcb_t *epcb);
+void usb_ep_halt(epcb_t *epcb);
+
+#define usb_init(...)           usb_init2(__VA_ARGS__)
+#define usb_device_exit(...)    usb_deinit2(__VA_ARGS__)
+
+#endif // _USB_API_H

binární
libs/usb/libusb.a


+ 92 - 0
libs/usb/usb_define.h

@@ -0,0 +1,92 @@
+#ifndef _USB_DEFINE_H
+#define _USB_DEFINE_H
+
+//ERROR CODE
+#define USB_ERR_OK          0x01
+#define USB_ERR_BUSY        0x02
+#define USB_ERR_PARSE       0x03
+#define USB_ERR_NO_CAP      0x04
+#define USB_ERR_NO_CONN     0x05
+#define USB_ERR_UNKNOW      0xff
+
+//EP Type
+#define EP_TYPE_CTRL                        0
+#define EP_TYPE_ISOC                        1
+#define EP_TYPE_BULK                        2
+#define EP_TYPE_INTR                        3
+
+//EP Dir
+#define EP_DIR_IN                           1           //device to host
+#define EP_DIR_OUT                          0           //host to device
+
+//Recipient
+#define ST_REQ_DEVICE                   0
+#define ST_REQ_INTERFACE                1
+#define ST_REQ_ENDPOINT                 2
+
+//Type
+#define ST_TYPE_STANDARD                0
+#define ST_TYPE_CLASS                   1
+#define ST_TYPE_VENDOR                  2
+
+//standard request
+#define UR_GET_STATUS                   0x00
+#define UR_CLEAR_FEATURE                0x01
+#define UR_SET_FEATURE                  0x03
+#define UR_SET_ADDRESS                  0x05
+#define UR_GET_DESCRIPTOR               0x06
+#define UR_GET_CONFIGURATION            0x08
+#define UR_SET_CONFIGURATION            0x09
+#define UR_GET_INTERFACE                0x0a
+#define UR_SET_INTERFACE                0x0b
+
+//hid request
+#define HR_SET_PROTOCOL                 0x0b
+#define HR_GET_PROTOCOL                 0x03
+#define HR_SET_IDLE                     0x0a
+#define HR_GET_IDLE                     0x02
+#define HR_SET_REPORT                   0x09
+#define HR_GET_REPORT                   0x01
+
+//Feature
+#define FT_EP_STALL                     0
+#define FT_DEV_REM_WAKEUP               1
+
+
+//Device Descriptor
+#define DEVICE_DESCRIPTOR                   1           //设备描述符
+#define CONFIGURATION_DESCRIPTOR            2           //配置描述符
+#define STRING_DESCRIPTOR                   3           //字符串描述符
+#define INTERFACE_DESCRIPTOR                4           //接口描述符
+#define ENDPOINT_DESCRIPTOR                 5           //断点描述符
+#define DEVICE_QUALIFIER_DESCRIPTOR         6
+
+#define HID_DESCRIPTOR                      0x21        //HID描述符
+#define HID_REPORT_DESCRIPTOR               0x22        //HID报表描述符
+#define AUDIO_INTERFACE_DESCRIPTOR          0x24        //音频类接口描述符
+#define AUDIO_ENDPOINT_DESCRIPTOR           0x25        //音频类传输端点描述符
+
+//USB Audio Class-Specific
+
+#define UA_HEADER_DESCRIPTOR                0x01        //音频类头接口描述符
+#define UA_INPUT_TERM_DESCRIPTOR            0x02        //音频类输入终端描述符
+#define UA_OUTPUT_TERM_DESCRIPTOR           0x03        //音频类输出终端描述符
+#define UA_FEATURE_UNIT_DESCRIPTOR          0x06        //音频类特征单元描述符
+
+#define UA_STREAM_GENERAL_DESCRIPTOR        0x01        //音频流接口描述符
+#define UA_STREAM_FORMAT_DESCRIPTOR         0x02        //音频流数据格式描述符
+
+#define UA_SET_CUR                          0x01
+#define UA_SET_MIN                          0x02
+#define UA_SET_MAX                          0x03
+#define UA_SET_RES                          0x04
+#define UA_GET_CUR                          0x81        //Current setting attribute
+#define UA_GET_MIN                          0x82        //Minimum setting attribute
+#define UA_GET_MAX                          0x83        //Maximum setting attribute
+#define UA_GET_RES                          0x84        //Resolution attribute
+
+//control for feature unit
+#define UA_MUTE_CTL                         0x01
+#define UA_VOL_CTL                          0x02
+
+#endif

+ 30 - 0
libs/ver.h

@@ -0,0 +1,30 @@
+#ifndef _VER_H
+#define _VER_H
+
+/**
+ * [WARNING]
+ * 
+ * this version update assist will be deleted in future, please update as soon as possible.
+ */
+
+#ifndef THREAD_STACK_PRIO
+#define THREAD_STACK_PRIO               1
+#endif
+#ifndef THREAD_STACK_STACK
+#define THREAD_STACK_STACK              1
+#endif
+
+#define thread_driver_create(...)       thread_driver_create()
+#define thread_aupcm_create(...)        thread_aupcm_create()
+#define thread_timer_create(...)
+#define thread_main_create(...)         thread_btstack_create()
+
+#define wireless_setup(...)             wireless_setup(NULL)
+
+#define ble_stack_init(...)             bt_init(); bt_setup();
+
+#define ble_stack_deinit(...)           bt_off()
+
+#define wireless_connect_by_addr(a, b, c, d, e)    wireless_connect_by_addr(a, b, c, d, e, -1)
+
+#endif // _VER_H

binární
libs/wireless/libwireless_slave.a


+ 202 - 0
modules/ains/ains3.c

@@ -0,0 +1,202 @@
+#include "include.h"
+#include "api_ains3.h"
+
+#if (AINS3_EN)
+
+#define PART_LEN			                    (AINS3_PART_LEN << 1)
+#define PART_LEN2			                    (PART_LEN << 1)
+#define PART_HALF_LEN                           (PART_LEN / 2)
+#define HANN_SHIFT                              (16)
+
+static ains3_cb_t ains3_cb;
+
+typedef struct {
+    // s16 input[PART_LEN];
+    // s16 fft_output[PART_LEN];
+    // s16 output[PART_LEN];
+    s16 input[128];
+    s16 fft_output[128];
+    s16 output[128];
+    u8 iptr;
+    u8 optr;
+} ains3_rdft_t;
+
+static ains3_rdft_t ains3_rdft AT(.ains3_buf.rdft);
+
+static struct nr_buf_t {
+	// int fft[PART_LEN2];
+	// s16 xbuf[PART_LEN2];
+	// int outBuf[PART_LEN];
+    int fft[256];    
+	s16 xbuf[256];
+	int outBuf[128];
+} nr_buf AT(.fft_buf.buf);
+
+
+typedef struct {
+    u8  sysclk;
+    bool init;
+} ains3_var_t;
+
+static ains3_var_t ains3_var;
+
+
+#if (PART_LEN == 120)
+//120
+AT(.fft_rodata)
+static const unsigned short sqrt_Hanning[121] = {
+	854, 1708, 2562, 3416, 4268, 5121, 5972, 6822, 7671, 8519, 9365, 10210, 11053, 11894, 12733,
+	13570, 14405, 15237, 16066, 16893, 17717, 18538, 19356, 20170, 20982, 21789, 22593, 23393,
+	24189, 24981, 25769, 26552, 27331, 28105, 28874, 29638, 30398, 31152, 31901, 32645, 33383,
+	34115, 34841, 35562, 36277, 36985, 37687, 38383, 39072, 39754, 40430, 41099, 41761, 42416,
+	43064, 43704, 44337, 44962, 45580, 46190, 46792, 47386, 47972, 48550, 49120, 49681, 50234,
+	50778, 51314, 51841, 52359, 52869, 53369, 53860, 54342, 54815, 55279, 55733, 56178, 56613,
+	57038, 57454, 57860, 58257, 58643, 59019, 59386, 59742, 60088, 60424, 60750, 61065, 61370,
+	61664, 61948, 62222, 62485, 62737, 62979, 63210, 63430, 63639, 63838, 64026, 64203, 64369,
+	64524, 64668, 64801, 64923, 65034, 65134, 65223, 65301, 65368, 65423, 65468, 65501, 65523,
+	65535, 65535,
+};
+#else
+//128
+AT(.fft_rodata)
+static const unsigned short sqrt_Hanning[129] = {
+	0x0000,0x0321,0x0642,0x0963,0x0C83,0x0FA3,0x12C2,0x15E1,
+	0x18FF,0x1C1C,0x1F37,0x2252,0x256B,0x2883,0x2B99,0x2EAE,
+	0x31C0,0x34D1,0x37E0,0x3AED,0x3DF7,0x40FF,0x4405,0x4708,
+	0x4A08,0x4D06,0x5000,0x52F8,0x55EC,0x58DD,0x5BCA,0x5EB5,
+	0x619B,0x647E,0x675D,0x6A38,0x6D0E,0x6FE1,0x72AF,0x7579,
+	0x783F,0x7B00,0x7DBC,0x8074,0x8326,0x85D4,0x887C,0x8B1F,
+	0x8DBD,0x9055,0x92E8,0x9575,0x97FD,0x9A7F,0x9CFA,0x9F70,
+	0xA1E0,0xA44A,0xA6AD,0xA90A,0xAB60,0xADB0,0xAFF9,0xB23B,
+	0xB477,0xB6AC,0xB8DA,0xBB00,0xBD20,0xBF38,0xC149,0xC353,
+	0xC555,0xC74F,0xC942,0xCB2E,0xCD11,0xCEED,0xD0C0,0xD28C,
+	0xD450,0xD60B,0xD7BF,0xD96A,0xDB0D,0xDCA7,0xDE39,0xDFC2,
+	0xE143,0xE2BC,0xE42B,0xE592,0xE6F0,0xE845,0xE992,0xEAD5,
+	0xEC10,0xED41,0xEE6A,0xEF89,0xF09F,0xF1AC,0xF2AF,0xF3AA,
+	0xF49B,0xF582,0xF661,0xF736,0xF801,0xF8C3,0xF97B,0xFA2A,
+	0xFACF,0xFB6B,0xFBFD,0xFC86,0xFD04,0xFD7A,0xFDE5,0xFE47,
+	0xFE9F,0xFEED,0xFF31,0xFF6C,0xFF9D,0xFFC4,0xFFE1,0xFFF5,
+	0xFFFF
+};
+#endif
+
+//extern u32 __code_start_alg, __code_end_alg;
+
+
+void fft_256(s32 *buf);
+void ifft_256(s32* buf);
+
+
+typedef signed long long __int64;
+__int64 lo;
+
+#define MZR()           do {(lo) = 0;} while(0)
+#define ML0(x, y)       ((lo)  =  (__int64)(x) * (__int64)(y))
+#define MS0(x, y)       ((lo)  = -(__int64)(x) * (__int64)(y))
+#define MLA(x, y)       ((lo) +=  (__int64)(x) * (__int64)(y))
+#define MSB(x, y)       ((lo) -=  (__int64)(x) * (__int64)(y))
+#define MLZ(n)          (int)(((lo) + (1<<(n-1)))>>(n))
+#define round(x,n)      ((int) ((x+(1<<(n-1)))>>n))
+
+#define MAC_LO()        ((int *)(void *)&lo)[0]
+#define MAC_HI()        ((int *)(void *)&lo)[1]
+
+#define MAC_SET_LO(x)   do {((int *)(void *)&lo)[0] = x;} while(0)
+#define MAC_SET_HI(x)   do {((int *)(void *)&lo)[1] = x;} while(0)
+#define AEC_SPL_SAT(A, B, C)    (B > A ? A : B < C ? C : B)
+#define AEC_SPL_WORD16_MAX      (32767)
+#define AEC_SPL_WORD16_MIN      (-32768)
+
+ALWAYS_INLINE int aec_spl_sat(int x0)
+{
+	int y0;
+	__asm__ volatile("p.clip %0, %1, %2" : "=r"(y0) : "r"(x0), "i"(15));
+	return y0;
+}
+
+AT(.ains3_text.alg)
+static void asr_kws_process(void)
+{
+    int i;
+    struct nr_buf_t *p = &nr_buf;
+    for(i = 0; i < PART_LEN; i++) {
+        p->xbuf[i + PART_LEN] = ains3_rdft.input[i];
+    }
+    for(i = 0; i < PART_LEN; i++) {
+        ML0(p->xbuf[i], sqrt_Hanning[i]);
+        p->fft[i] = MLZ(HANN_SHIFT);
+        ML0(p->xbuf[PART_LEN + i], sqrt_Hanning[PART_LEN - i]);
+        p->fft[PART_LEN + i] = MLZ(HANN_SHIFT);
+    }
+    fft_256((s32*)p->fft);
+    ains3_mono_process((s32*)p->fft);
+    ifft_256((s32*)p->fft);
+
+	for(i = 0; i < PART_LEN; i++) {
+		// Do we need saturation ?
+		p->fft[i] = AEC_SPL_SAT(AEC_SPL_WORD16_MAX, p->fft[i], AEC_SPL_WORD16_MIN);
+        ML0(p->fft[i], sqrt_Hanning[i]);
+		p->fft[i] = MLZ(HANN_SHIFT)+p->outBuf[i];
+        ains3_rdft.fft_output[i] = (short)AEC_SPL_SAT(AEC_SPL_WORD16_MAX, p->fft[i], AEC_SPL_WORD16_MIN);
+		ML0(p->fft[PART_LEN + i], sqrt_Hanning[PART_LEN - i]);
+		p->outBuf[i] = MLZ(HANN_SHIFT);
+	}
+	memcpy(p->xbuf, p->xbuf + PART_LEN, 2 * PART_LEN);
+}
+
+AT(.ains3_text.ains3)
+void ains3_process(s16 *buf)
+{
+    for (int i = 0; i < PART_HALF_LEN; i++) {
+        ains3_rdft.input[ains3_rdft.iptr * PART_HALF_LEN + i]  = buf[i];
+    }
+    ains3_rdft.iptr++;
+    if (ains3_rdft.iptr >= 2) {
+        ains3_rdft.iptr = 0;
+        memcpy(ains3_rdft.output, ains3_rdft.fft_output, PART_LEN * 2);
+        asr_kws_process();
+        ains3_rdft.optr = 0;
+    }
+
+    memcpy(buf, &ains3_rdft.output[ains3_rdft.optr * PART_HALF_LEN], PART_HALF_LEN * 2);
+    ains3_rdft.optr++;
+    if (ains3_rdft.optr >= 2) {
+        ains3_rdft.optr = 0;
+    }
+}
+
+void ains3_init(void)
+{
+    if (ains3_var.init == 0) {
+        memset(&ains3_rdft, 0, sizeof(ains3_rdft_t));
+        memset(&nr_buf, 0, sizeof(struct nr_buf_t));
+
+        ains3_cb.nt = AINS3_NT;
+        ains3_cb.prior_opt_idx = AINS3_PRIOR_OPT_IDX;
+        ains3_var.sysclk = sys_clk_get_cur();
+        printf("ains3_var.sysclk:%d\n",ains3_var.sysclk);
+
+        if (ains3_var.sysclk < SYS_120M) {
+            sys_clk_set(SYS_120M);
+        }
+
+        ains3_rdft.optr = 1;
+
+        //lock_code_alg((u32)&__code_start_alg, (u32)&__code_end_alg);
+
+        ains3_mono_init(&ains3_cb);
+
+        ains3_var.init = 1;
+    }
+}
+
+void ains3_exit(void)
+{
+    if (ains3_var.init) {
+        ains3_var.init = 0;
+        //unlock_code_alg();
+        sys_clk_set(ains3_var.sysclk);
+    }
+}
+
+#endif  //(AINS3_EN)

+ 11 - 0
modules/ains/ains3.h

@@ -0,0 +1,11 @@
+#ifndef _AINS3_H
+#define _AINS3_H
+
+/*
+    nt:降噪等级,值越大降噪越明显
+*/
+void ains3_init(void);
+void ains3_exit(void);
+void ains3_process(s16 *buf);
+
+#endif

+ 197 - 0
modules/ains/ains4.c

@@ -0,0 +1,197 @@
+#include "include.h"
+#include "api_ains4.h"
+
+#if (AINS4_EN)
+
+#define PART_LEN			                    (AINS4_PART_LEN << 1)
+#define PART_LEN2			                    (PART_LEN << 1)
+#define PART_HALF_LEN                           (PART_LEN / 2)
+#define HANN_SHIFT                              (16)
+
+typedef struct {
+    u8  sysclk;
+    bool init;
+} ains4_cb_t;
+
+static ains4_cb_t ains4_cb;
+
+typedef struct {
+    // s16 input[PART_LEN];
+    // s16 fft_output[PART_LEN];
+    // s16 output[PART_LEN];
+    s16 input[128];
+    s16 fft_output[128];
+    s16 output[128];
+    u8 iptr;
+    u8 optr;
+} ains4_rdft_t;
+
+static ains4_rdft_t ains4_rdft AT(.ains4_buf.rdft);
+
+static struct nr_buf_t {
+    // int fft[PART_LEN2];
+	// s16 xbuf[PART_LEN2];
+	// int outBuf[PART_LEN];
+	int fft[256];    
+	s16 xbuf[256];
+	int outBuf[128];
+} nr_buf AT(.fft_buf.buf);
+
+#if (PART_LEN == 120)
+//120
+AT(.fft_rodata)
+static const unsigned short sqrt_Hanning[121] = {
+	854, 1708, 2562, 3416, 4268, 5121, 5972, 6822, 7671, 8519, 9365, 10210, 11053, 11894, 12733,
+	13570, 14405, 15237, 16066, 16893, 17717, 18538, 19356, 20170, 20982, 21789, 22593, 23393,
+	24189, 24981, 25769, 26552, 27331, 28105, 28874, 29638, 30398, 31152, 31901, 32645, 33383,
+	34115, 34841, 35562, 36277, 36985, 37687, 38383, 39072, 39754, 40430, 41099, 41761, 42416,
+	43064, 43704, 44337, 44962, 45580, 46190, 46792, 47386, 47972, 48550, 49120, 49681, 50234,
+	50778, 51314, 51841, 52359, 52869, 53369, 53860, 54342, 54815, 55279, 55733, 56178, 56613,
+	57038, 57454, 57860, 58257, 58643, 59019, 59386, 59742, 60088, 60424, 60750, 61065, 61370,
+	61664, 61948, 62222, 62485, 62737, 62979, 63210, 63430, 63639, 63838, 64026, 64203, 64369,
+	64524, 64668, 64801, 64923, 65034, 65134, 65223, 65301, 65368, 65423, 65468, 65501, 65523,
+	65535, 65535,
+};
+#else
+//128
+AT(.fft_rodata)
+static const unsigned short sqrt_Hanning[129] = {
+	0x0000,0x0321,0x0642,0x0963,0x0C83,0x0FA3,0x12C2,0x15E1,
+	0x18FF,0x1C1C,0x1F37,0x2252,0x256B,0x2883,0x2B99,0x2EAE,
+	0x31C0,0x34D1,0x37E0,0x3AED,0x3DF7,0x40FF,0x4405,0x4708,
+	0x4A08,0x4D06,0x5000,0x52F8,0x55EC,0x58DD,0x5BCA,0x5EB5,
+	0x619B,0x647E,0x675D,0x6A38,0x6D0E,0x6FE1,0x72AF,0x7579,
+	0x783F,0x7B00,0x7DBC,0x8074,0x8326,0x85D4,0x887C,0x8B1F,
+	0x8DBD,0x9055,0x92E8,0x9575,0x97FD,0x9A7F,0x9CFA,0x9F70,
+	0xA1E0,0xA44A,0xA6AD,0xA90A,0xAB60,0xADB0,0xAFF9,0xB23B,
+	0xB477,0xB6AC,0xB8DA,0xBB00,0xBD20,0xBF38,0xC149,0xC353,
+	0xC555,0xC74F,0xC942,0xCB2E,0xCD11,0xCEED,0xD0C0,0xD28C,
+	0xD450,0xD60B,0xD7BF,0xD96A,0xDB0D,0xDCA7,0xDE39,0xDFC2,
+	0xE143,0xE2BC,0xE42B,0xE592,0xE6F0,0xE845,0xE992,0xEAD5,
+	0xEC10,0xED41,0xEE6A,0xEF89,0xF09F,0xF1AC,0xF2AF,0xF3AA,
+	0xF49B,0xF582,0xF661,0xF736,0xF801,0xF8C3,0xF97B,0xFA2A,
+	0xFACF,0xFB6B,0xFBFD,0xFC86,0xFD04,0xFD7A,0xFDE5,0xFE47,
+	0xFE9F,0xFEED,0xFF31,0xFF6C,0xFF9D,0xFFC4,0xFFE1,0xFFF5,
+	0xFFFF
+};
+#endif
+void fft_256(s32 *buf);
+void ifft_256(s32* buf);
+void lock_code_alg(u32 start_addr, u32 end_addr);
+void unlock_code_alg(void);
+
+extern u32 __code_start_alg, __code_end_alg;
+
+typedef signed long long __int64;
+__int64 lo;
+
+#define MZR()           do {(lo) = 0;} while(0)
+#define ML0(x, y)       ((lo)  =  (__int64)(x) * (__int64)(y))
+#define MS0(x, y)       ((lo)  = -(__int64)(x) * (__int64)(y))
+#define MLA(x, y)       ((lo) +=  (__int64)(x) * (__int64)(y))
+#define MSB(x, y)       ((lo) -=  (__int64)(x) * (__int64)(y))
+#define MLZ(n)          (int)(((lo) + (1<<(n-1)))>>(n))
+#define round(x,n)      ((int) ((x+(1<<(n-1)))>>n))
+
+#define MAC_LO()        ((int *)(void *)&lo)[0]
+#define MAC_HI()        ((int *)(void *)&lo)[1]
+
+#define MAC_SET_LO(x)   do {((int *)(void *)&lo)[0] = x;} while(0)
+#define MAC_SET_HI(x)   do {((int *)(void *)&lo)[1] = x;} while(0)
+#define AEC_SPL_SAT(A, B, C)    (B > A ? A : B < C ? C : B)
+#define AEC_SPL_WORD16_MAX      (32767)
+#define AEC_SPL_WORD16_MIN      (-32768)
+
+ALWAYS_INLINE int aec_spl_sat(int x0)
+{
+	int y0;
+	__asm__ volatile("p.clip %0, %1, %2" : "=r"(y0) : "r"(x0), "i"(15));
+	return y0;
+}
+
+AT(.ains4_text.alg)
+static void asr_kws_process(void)
+{
+    int i;
+    struct nr_buf_t *p = &nr_buf;
+    for(i = 0; i < PART_LEN; i++) {
+        p->xbuf[i + PART_LEN] = ains4_rdft.input[i];
+    }
+    for(i = 0; i < PART_LEN; i++) {
+        ML0(p->xbuf[i], sqrt_Hanning[i]);
+        p->fft[i] = MLZ(HANN_SHIFT);
+        ML0(p->xbuf[PART_LEN + i], sqrt_Hanning[PART_LEN - i]);
+        p->fft[PART_LEN + i] = MLZ(HANN_SHIFT);
+    }
+    fft_256((s32*)p->fft);
+    ains4_mono_process((s32*)p->fft);
+    ifft_256((s32*)p->fft);
+
+	for(i = 0; i < PART_LEN; i++) {
+		// Do we need saturation ?
+		p->fft[i] = AEC_SPL_SAT(AEC_SPL_WORD16_MAX, p->fft[i], AEC_SPL_WORD16_MIN);
+        ML0(p->fft[i], sqrt_Hanning[i]);
+		p->fft[i] = MLZ(HANN_SHIFT)+p->outBuf[i];
+        ains4_rdft.fft_output[i] = (short)AEC_SPL_SAT(AEC_SPL_WORD16_MAX, p->fft[i], AEC_SPL_WORD16_MIN);
+		ML0(p->fft[PART_LEN + i], sqrt_Hanning[PART_LEN - i]);
+		p->outBuf[i] = MLZ(HANN_SHIFT);
+	}
+	memcpy(p->xbuf, p->xbuf + PART_LEN, 2 * PART_LEN);
+}
+
+AT(.ains4_text.ains4)
+void ains4_process(s16 *buf)
+{
+    for (int i = 0; i < PART_HALF_LEN; i++) {
+        ains4_rdft.input[ains4_rdft.iptr * PART_HALF_LEN + i]  = buf[i];
+    }
+    ains4_rdft.iptr++;
+    if (ains4_rdft.iptr >= 2) {
+        ains4_rdft.iptr = 0;
+        memcpy(ains4_rdft.output, ains4_rdft.fft_output, PART_LEN * 2);
+        asr_kws_process();
+        ains4_rdft.optr = 0;
+    }
+
+    memcpy(buf, &ains4_rdft.output[ains4_rdft.optr * PART_HALF_LEN], PART_HALF_LEN * 2);
+    ains4_rdft.optr++;
+    if (ains4_rdft.optr >= 2) {
+        ains4_rdft.optr = 0;
+    }
+}
+
+AT(.text.ains4_init)
+void ains4_init(void)
+{
+    if (ains4_cb.init == 0) {
+        memset(&ains4_rdft, 0, sizeof(ains4_rdft_t));
+        memset(&nr_buf, 0, sizeof(struct nr_buf_t));
+
+        ains4_cb.sysclk = sys_clk_get_cur();
+        printf("ains4_cb.sysclk:%d\n",ains4_cb.sysclk);
+
+        if (ains4_cb.sysclk < SYS_160M) {
+            sys_clk_set(SYS_160M);
+        }
+
+        ains4_rdft.optr = 1;
+
+        // lock_code_alg((u32)&__code_start_alg, (u32)&__code_end_alg);
+
+        ains4_mono_init(AINS4_NR_SUPPRESS, AINS4_PRIOR_OPT_IDX);
+
+        ains4_cb.init = 1;
+    }
+}
+
+AT(.text.ains4_exit)
+void ains4_exit(void)
+{
+    if (ains4_cb.init) {
+        ains4_cb.init = 0;
+        // unlock_code_alg();
+        sys_clk_set(ains4_cb.sysclk);
+    }
+}
+
+#endif  //(AINS4_EN)

+ 10 - 0
modules/ains/ains4.h

@@ -0,0 +1,10 @@
+#ifndef _AINS4_H
+#define _AINS4_H
+
+#include "include.h"
+
+void ains4_init(void);
+void ains4_exit(void);
+void ains4_process(s16 *buf);
+
+#endif

+ 6 - 0
project/hidtouch.workspace

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_workspace_file>
+	<Workspace title="Workspace">
+		<Project filename="solution/ble_hid_composite/ble_hid_composite.cbp" />
+	</Workspace>
+</CodeBlocks_workspace_file>

+ 5 - 0
project/hidtouch.workspace.layout

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_workspace_layout_file>
+	<FileVersion major="1" minor="0" />
+	<ActiveProject path="solution/ble_hid_composite/ble_hid_composite.cbp" />
+</CodeBlocks_workspace_layout_file>

+ 23 - 0
project/solution/ble_hid_composite/Output/bin/Settings/standard.setting

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+    <appSettings>
+        <add key="uosci_cap" value="40" />
+        <add key="uosco_cap" value="40" />
+        <add key="ft_osc_cap_en" value="True" />
+        <add key="le_name" value="LE-AB2020" />
+        <add key="le_addr_mode" value="随机地址" />
+        <add key="le_addr" value="41:42:00:00:00:01" />
+        <add key="le_addr_start" value="41:42:00:00:00:00" />
+        <add key="le_addr_step" value="00:00:00:00:00:01" />
+        <add key="le_addr_end" value="41:42:FF:FF:FF:FF" />
+        <add key="bt_rf_pwrdec" value="0" />
+        <add key="bt_rf_mix_cap" value="8" />
+        <add key="bt_rf_param_en" value="False" />
+        <add key="rf_mix_gain" value="7" />
+        <add key="rf_dig_gain" value="58" />
+        <add key="rf_pa_cap" value="8" />
+        <add key="rf_mix_cap" value="8" />
+        <add key="uosc_both_cap" value="0PF" />
+        <add key="rf_tx_pwr" value="0" />
+    </appSettings>
+</configuration>

binární
project/solution/ble_hid_composite/Output/bin/app.bin


binární
project/solution/ble_hid_composite/Output/bin/app.rv32


+ 10 - 0
project/solution/ble_hid_composite/Output/bin/app.xm

@@ -0,0 +1,10 @@
+#include "config.h"
+depend(0x01010200);
+setflash(1, FLASH_SIZE, FLASH_ERASE_4K, FLASH_DUAL_READ, FLASH_QUAD_READ);
+setspace(FLASH_RESERVE_SIZE);
+#if (AB_FOT_EN && (AB_FOT_TYPE == AB_FOT_TYPE_PACK))
+setunpack(unpack.bin);
+setpkgarea(FOT_PACK_START, FOT_PACK_SIZE);
+#endif
+make(dcf_buf, header.bin, app.bin, res.bin, xcfg.bin, updater.bin);
+save(dcf_buf, app.dcf);

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů