Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_ir_rx.c
1 
2 #include <stm32l0xx.h>
3 #include <bc_common.h>
4 #include <bc_gpio.h>
5 #include <bc_exti.h>
6 #include <bc_scheduler.h>
7 #include <bc_system.h>
8 #include "bc_ir_rx.h"
9 
10 //#define _BC_IR_RX_DEBUG
11 
12 // IR receiver has to be connected on
13 // BC_GPIO_P10
14 // No external pull-up required, internal pull-up is activated
15 
16 static struct
17 {
18  TIM_HandleTypeDef ir_timer;
19  uint8_t counter;
20  uint32_t ir_rx_temp;
21  uint32_t ir_rx_value;
22 
23  bc_scheduler_task_id_t task_id_notify;
24 
25  void (*event_handler)(bc_ir_rx_event_t, void *);
26  void *event_param;
27 
28  #ifdef _BC_IR_RX_DEBUG
29  uint16_t lengths[40];
30  #endif
31 } _bc_ir_rx;
32 
33 
34 void bc_ir_rx_get_code(uint32_t *nec_code)
35 {
36  *nec_code = _bc_ir_rx.ir_rx_value;
37 }
38 
39 
40 static void _bc_ir_rx_task_notify(void *param)
41 {
42  (void) param;
43 
44  if (_bc_ir_rx.event_handler != NULL)
45  {
46  _bc_ir_rx.event_handler(BC_IR_RX_NEC_FORMAT, _bc_ir_rx.event_param);
47  }
48 }
49 
50 static void _bc_ir_rx_exti_int(bc_exti_line_t line, void *param)
51 {
52  (void) param;
53  (void) line;
54 
55  #ifdef _BC_IR_RX_DEBUG
57  #endif
58 
59  if(_bc_ir_rx.counter == 0)
60  {
61  // Start pulse, start timer
62  __HAL_TIM_DISABLE(&_bc_ir_rx.ir_timer);
63  __HAL_TIM_DISABLE_IT(&_bc_ir_rx.ir_timer, TIM_IT_UPDATE);
64  __HAL_TIM_CLEAR_IT(&_bc_ir_rx.ir_timer, TIM_IT_UPDATE);
65 
66  HAL_TIM_Base_Start_IT(&_bc_ir_rx.ir_timer);
67  _bc_ir_rx.counter++;
68  return;
69  }
70 
71  // Get value and clear the timer
72  uint16_t act_len = __HAL_TIM_GET_COUNTER(&_bc_ir_rx.ir_timer);
73  __HAL_TIM_SET_COUNTER(&_bc_ir_rx.ir_timer, 0);
74 
75  // Array for debugging
76  #ifdef _BC_IR_RX_DEBUG
77  _bc_ir_rx.lengths[_bc_ir_rx.counter] = act_len;
78  #endif
79 
80  // Check start pulse length
81  if(_bc_ir_rx.counter == 1)
82  {
83  if(act_len < 8000 || act_len > 14000)
84  {
85  // Ignore this packet
86  volatile int a = 5;
87  a++;
88  return;
89  }
90  }
91 
92  if(_bc_ir_rx.counter == 2)
93  {
94  _bc_ir_rx.ir_rx_temp = 0;
95  }
96 
97  // ignore first two items (first zero value and start pulse)
98  if(act_len > 1500 && _bc_ir_rx.counter >= 2)
99  {
100  _bc_ir_rx.ir_rx_temp |= (1 << (_bc_ir_rx.counter-2));
101  }
102 
103  // Received packet
104  if(_bc_ir_rx.counter == 33)
105  {
106  #ifdef _BC_IR_RX_DEBUG
107  // Debug toggle
111  #endif
112 
113  _bc_ir_rx.counter = 0;
114  _bc_ir_rx.ir_rx_value = _bc_ir_rx.ir_rx_temp;
115 
116  // The ir_rx_value should have inverted one addr and one command byte, but
117  // the test of my IR remotes shows, that only the second CMD byte is inversion of the fist one
118 
119  __HAL_TIM_DISABLE(&_bc_ir_rx.ir_timer);
120  __HAL_TIM_DISABLE_IT(&_bc_ir_rx.ir_timer, TIM_IT_UPDATE);
121  __HAL_TIM_CLEAR_IT(&_bc_ir_rx.ir_timer, TIM_IT_UPDATE);
122 
123  bc_scheduler_plan_now(_bc_ir_rx.task_id_notify);
124 
125  return;
126  }
127 
128  _bc_ir_rx.counter++;
129 }
130 
131 void bc_ir_rx_set_event_handler(void (*event_handler)(bc_ir_rx_event_t, void *), void *event_param)
132 {
133  _bc_ir_rx.event_handler = event_handler;
134  _bc_ir_rx.event_param = event_param;
135 }
136 
137 void bc_ir_rx_init()
138 {
139  // TODO: Needs fix to allow low power
140  bc_system_pll_enable();
141 
142  // IR input
146  // External interrupt
147  bc_exti_register(BC_EXTI_LINE_P10, BC_EXTI_EDGE_FALLING, _bc_ir_rx_exti_int, NULL);
148 
149  #ifdef _BC_IR_RX_DEBUG
150  // Debug output
153  #endif
154 
155  // Used TIM7 so we don't have collision of IRQ handlers functions
156  __TIM6_CLK_ENABLE();
157  _bc_ir_rx.ir_timer.Instance = TIM6;
158  // Running @ 32MHz, set timer to 1us resolution
159  _bc_ir_rx.ir_timer.Init.Prescaler = SystemCoreClock / 1000000;
160  _bc_ir_rx.ir_timer.Init.CounterMode = TIM_COUNTERMODE_UP;
161  // Period is also the timeout in case the IR code is not complete
162  _bc_ir_rx.ir_timer.Init.Period = 16000;
163  _bc_ir_rx.ir_timer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
164  HAL_TIM_Base_Init(&_bc_ir_rx.ir_timer);
165  HAL_NVIC_EnableIRQ(TIM6_IRQn);
166 
167  _bc_ir_rx.task_id_notify = bc_scheduler_register(_bc_ir_rx_task_notify, NULL, BC_TICK_INFINITY);
168 
169 }
170 
171 
172 void TIM6_IRQHandler()
173 {
174  #ifdef _BC_IR_RX_DEBUG
179  #endif
180 
181  if(__HAL_TIM_GET_FLAG(&_bc_ir_rx.ir_timer, TIM_FLAG_UPDATE) != RESET)
182  {
183  if(__HAL_TIM_GET_IT_SOURCE(&_bc_ir_rx.ir_timer, TIM_IT_UPDATE) !=RESET)
184  {
185  // Stop timer
186  __HAL_TIM_CLEAR_IT(&_bc_ir_rx.ir_timer, TIM_IT_UPDATE);
187  __HAL_TIM_DISABLE(&_bc_ir_rx.ir_timer);
188  __HAL_TIM_DISABLE_IT(&_bc_ir_rx.ir_timer, TIM_IT_UPDATE);
189 
190  _bc_ir_rx.counter = 0;
191  }
192  }
193 }
GPIO channel has pull-up.
Definition: bc_gpio.h:87
EXTI line P10.
Definition: bc_exti.h:165
bc_scheduler_task_id_t bc_scheduler_register(void(*task)(void *), void *param, bc_tick_t tick)
Register task in scheduler.
Definition: bc_scheduler.c:56
void bc_scheduler_plan_now(bc_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
Definition: bc_scheduler.c:119
void bc_gpio_set_mode(bc_gpio_channel_t channel, bc_gpio_mode_t mode)
Set mode of operation for GPIO channel.
Definition: bc_gpio.c:340
void bc_gpio_set_pull(bc_gpio_channel_t channel, bc_gpio_pull_t pull)
Set pull-up/pull-down configuration for GPIO channel.
Definition: bc_gpio.c:313
GPIO channel P10.
Definition: bc_gpio.h:45
size_t bc_scheduler_task_id_t
Task ID assigned by scheduler.
Definition: bc_scheduler.h:18
GPIO channel operates as input.
Definition: bc_gpio.h:99
void bc_exti_register(bc_exti_line_t line, bc_exti_edge_t edge, void(*callback)(bc_exti_line_t, void *), void *param)
Enable EXTI line interrupt and register callback function.
Definition: bc_exti.c:17
GPIO channel P11.
Definition: bc_gpio.h:48
bc_exti_line_t
EXTI lines.
Definition: bc_exti.h:21
void bc_gpio_toggle_output(bc_gpio_channel_t channel)
Toggle output state for GPIO channel.
Definition: bc_gpio.c:454
#define BC_TICK_INFINITY
Maximum timestamp value.
Definition: bc_tick.h:12
void bc_gpio_init(bc_gpio_channel_t channel)
Initialize GPIO channel.
Definition: bc_gpio.c:301
GPIO channel operates as output.
Definition: bc_gpio.h:102
EXTI line is configured to falling edge sensitivity.
Definition: bc_exti.h:201