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