drv_irrx.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * Copyright (c) 2020-2021, Bluetrum Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-04-12 greedyhao first version
  9. */
  10. #include <board.h>
  11. #ifdef BSP_USING_IRRX
  12. //#define DRV_DEBUG
  13. #define LOG_TAG "drv.irrx"
  14. #include <drv_log.h>
  15. #ifdef BSP_USING_TIM3
  16. #error "IRRX is conflict with hardware timer3!"
  17. #endif
  18. #ifdef BSP_USING_IRRX_HW
  19. ///硬件IR receiver参数
  20. #define IR32KSEL_EN 0 //IR clock source select 32K
  21. #if IR32KSEL_EN
  22. #define RPTERR_CNT 33 //配置11.25ms ± (RPTERR_CNT + 1)*32K的repeat code允许范围
  23. #define DATERR_CNT 33 //配置13.5ms ± (DATERR_CNT + 1)*32K引导码允许范围
  24. #define ONEERR_CNT 7 //配置2.25ms ± (ONEERR_CNT + 1)*32K的logic "1"允许范围
  25. #define ZEROERR_CNT 3 //配置1.12ms ± (ONEERR_CNT + 1)*32K数logic "0"允许范围
  26. #define TOPR_CNT 55 //IR time out length = (TOPR + 1) * 64 *32K
  27. #else
  28. #define RPTERR_CNT 1000 //配置11.25ms ± (RPTERR_CNT + 1)us的repeat code允许范围
  29. #define DATERR_CNT 1000 //配置13.5ms ± (DATERR_CNT + 1)us引导码允许范围
  30. #define ONEERR_CNT 250 //配置2.25ms ± (ONEERR_CNT + 1)us的logic "1"允许范围
  31. #define ZEROERR_CNT 125 //配置1.12ms ± (ONEERR_CNT + 1)us数logic "0"允许范围
  32. #define TOPR_CNT 1718 //IR time out length = (TOPR + 1) * 64 us
  33. #endif // IR32KSEL_EN
  34. #endif // BSP_USING_IRRX_HW
  35. #define NO_KEY (0u)
  36. struct ab32_irrx_data{
  37. rt_uint16_t cnt; //ir data bit counter
  38. rt_uint16_t rpt_cnt; //ir repeat counter
  39. rt_uint16_t addr; //address, inverted address Extended NEC: 16bits address
  40. rt_uint16_t cmd; //command, inverted command
  41. };
  42. typedef struct ab32_irrx_data *ab32_irrx_data_t;
  43. static struct ab32_irrx_data _irrx = {0};
  44. /**
  45. * @brief A non-zero value is returned
  46. * when IR key is detectedto be pressed.
  47. *
  48. * @param addr inverted address Extended NEC: 16bits address
  49. * @param cmd inverted command
  50. */
  51. rt_section(".irq.irrx")
  52. rt_uint8_t ab32_get_irkey(rt_uint16_t *addr, rt_uint16_t *cmd)
  53. {
  54. if (_irrx.cnt != 32) {
  55. return NO_KEY;
  56. }
  57. if (addr != RT_NULL) {
  58. *addr = _irrx.addr;
  59. }
  60. if (cmd != RT_NULL) {
  61. *cmd = _irrx.cmd;
  62. }
  63. return !NO_KEY;
  64. }
  65. /**
  66. * @brief Invalid the current IR key.
  67. *
  68. */
  69. void ab32_clr_irkey(void)
  70. {
  71. _irrx.cnt = 0;
  72. }
  73. #ifdef BSP_USING_IRRX_HW
  74. rt_section(".irq.irrx")
  75. static void irrx_isr(int vector, void *param)
  76. {
  77. rt_interrupt_enter();
  78. //IR RX data finish interrupt
  79. if (IRRXCON & BIT(16)) {
  80. IRRXCPND = BIT(16);
  81. _irrx.addr = (rt_uint16_t)IRRXDAT;
  82. _irrx.cmd = (rt_uint16_t)(IRRXDAT >> 16);
  83. _irrx.cnt = 32;
  84. }
  85. //IR key release interrupt
  86. if (IRRXCON & BIT(17)) {
  87. IRRXCPND = BIT(17);
  88. _irrx.cnt = 0;
  89. }
  90. rt_interrupt_leave();
  91. }
  92. static void _irrx_hw_init(void)
  93. {
  94. GPIOEDE |= BIT(6);
  95. GPIOEPU |= BIT(6);
  96. GPIOEDIR |= BIT(6);
  97. FUNCMCON2 |= 0xf << 20;
  98. FUNCMCON2 |= (7 << 20); //IR mapping to G6
  99. rt_memset(&_irrx, 0, sizeof(_irrx));
  100. IRRXERR0 = (RPTERR_CNT << 16) | DATERR_CNT; //RPTERR[27:16], DATERR[11:0]
  101. IRRXERR1 = (TOPR_CNT << 20) | (ONEERR_CNT << 10) | ZEROERR_CNT; //TOPR[31:20], ONEERR[19:10], ZEROERR[9:0]
  102. #if IR32KSEL_EN
  103. CLKCON1 &= ~BIT(5);
  104. CLKCON1 |= BIT(4); //enable 26M分频32K
  105. IRRXCON |= BIT(3); //ir clock source select 32K
  106. #endif // IR32KSEL_EN
  107. rt_hw_interrupt_install(IRQ_IRRX_VECTOR, irrx_isr, RT_NULL, "irrx_isr");
  108. IRRXCON = 0x03;
  109. // LOG_D("IRRXCON:%08x", IRRXCON);
  110. }
  111. #endif
  112. #ifdef BSP_USING_IRRX_SW
  113. #define TMR3_RCLK (1000u) //xosc26m_div 1M
  114. rt_section(".irq.irrx")
  115. static void irrx_isr(int vector, void *param)
  116. {
  117. rt_uint32_t tmrcnt;
  118. if (TMR3CON & BIT(17)) {
  119. //timer1 capture interrupt
  120. TMR3CNT = TMR3CNT - TMR3CPT;
  121. tmrcnt = TMR3CPT;
  122. TMR3CPND = BIT(17);
  123. tmrcnt /= TMR3_RCLK; //convert to ms
  124. } else if (TMR3CON & BIT(16)){
  125. //timer1 overflow interrupt
  126. TMR3CPND = BIT(16);
  127. tmrcnt = 110; //110ms overflow
  128. } else {
  129. return;
  130. }
  131. //processing repeat code
  132. if (_irrx.cnt == 32) {
  133. if ((tmrcnt >= 10) && (tmrcnt <= 12)) {
  134. //repeat code is simply 9ms+2.25ms
  135. _irrx.rpt_cnt = 0;
  136. } else {
  137. _irrx.rpt_cnt += tmrcnt;
  138. if (_irrx.rpt_cnt > 108) {
  139. _irrx.rpt_cnt = 0;
  140. _irrx.cnt = 0; //ir key release
  141. }
  142. }
  143. return;
  144. } else if ((tmrcnt > 7) || (tmrcnt == 0)) { //A message is started by a 9ms AGC burst
  145. _irrx.rpt_cnt = 0;
  146. _irrx.cnt = 0; //ir key message started
  147. return;
  148. }
  149. _irrx.cmd >>= 1;
  150. _irrx.cnt++;
  151. if (tmrcnt == 2) { //Bit time of 1.125ms(0) or 2.25ms(1)
  152. _irrx.cmd |= 0x8000;
  153. }
  154. if (_irrx.cnt == 16) {
  155. _irrx.addr = _irrx.cmd; //save address data
  156. } else if (_irrx.cnt == 32) {
  157. //got ir key message
  158. if ((rt_uint8_t)_irrx.cmd > 96) {
  159. _irrx.cmd = NO_KEY;
  160. }
  161. }
  162. }
  163. static void timer3_init(void)
  164. {
  165. rt_hw_interrupt_install(IRQ_IRRX_VECTOR, irrx_isr, RT_NULL, "irrx_isr");
  166. TMR3CNT = 0;
  167. TMR3PR = TMR3_RCLK*110 - 1; //110ms Timer overflow interrupt
  168. TMR3CON = BIT(8) | BIT(7) | BIT(5) | BIT(2) | BIT(1) | BIT(0); //capture & overflow interrupt enable, falling edge, Capture Mode
  169. }
  170. static void _irrx_hw_init(void)
  171. {
  172. GPIOEDE |= BIT(6);
  173. GPIOEPU |= BIT(6);
  174. GPIOEDIR |= BIT(6);
  175. FUNCMCON2 |= 0xf << 4;
  176. FUNCMCON2 |= (7 << 4); // timer3 G6 PE6 capture
  177. rt_memset(&_irrx, 0, sizeof(_irrx));
  178. timer3_init();
  179. }
  180. #endif
  181. static int ab32_irrx_init(void)
  182. {
  183. _irrx_hw_init();
  184. LOG_D("irrx init success");
  185. return RT_EOK;
  186. }
  187. INIT_BOARD_EXPORT(ab32_irrx_init);
  188. #endif