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