Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_rf_ook.c
1 #include <bc_rf_ook.h>
2 #include <bc_timer.h>
3 
4 void _bc_rf_ook_irq_TIM3_handler(void *param);
5 
6 static struct
7 {
8  volatile uint16_t packet_bit_position;
9  uint8_t packet_length;
10  uint8_t packet_data[128];
11  volatile bool is_busy;
12  uint32_t bit_length_us;
13  bc_gpio_channel_t gpio;
14 } _bc_rf_ook;
15 
16 static int _bc_rf_ook_char_to_int(char input)
17 {
18  if(input >= '0' && input <= '9')
19  {
20  return input - '0';
21  }
22  else if(input >= 'A' && input <= 'F')
23  {
24  return input - 'A' + 10;
25  }
26  else if(input >= 'a' && input <= 'f')
27  {
28  return input - 'a' + 10;
29  }
30  else
31  {
32  return 0;
33  }
34 }
35 
36 static uint8_t _bc_rf_ook_string_to_array(char *str, uint8_t *array)
37 {
38  uint8_t array_length = (strlen(str) + 1) / 2;
39 
40  for(int i = 0; i < array_length; i++)
41  {
42  array[i] = _bc_rf_ook_char_to_int(str[i*2]) * 16;
43 
44  if(!(i == array_length - 1 && strlen(str) % 2 == 1))
45  {
46  array[i] += _bc_rf_ook_char_to_int(str[i*2 + 1]);
47  }
48  }
49 
50  return array_length;
51 }
52 
53 static void _bc_rf_ook_tim3_configure(uint32_t resolution_us, uint32_t period_cycles)
54 {
55  // Enable TIM3 clock
56  RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
57 
58  // Errata workaround
59  RCC->APB1ENR;
60 
61  // Disable counter if it is running
62  TIM3->CR1 &= ~TIM_CR1_CEN;
63 
64  // Set prescaler to 5 * 32 (5 microseconds resolution)
65  TIM3->PSC = resolution_us * 32 - 1;
66  TIM3->ARR = period_cycles - 1;
67 
68  TIM3->DIER |= TIM_DIER_UIE;
69  // Enable TIM3 interrupts
70  NVIC_EnableIRQ(TIM3_IRQn);
71 }
72 
74 {
75  memset(&_bc_rf_ook, 0, sizeof(_bc_rf_ook));
76 
77  _bc_rf_ook.gpio = gpio;
78 
79  bc_gpio_init(_bc_rf_ook.gpio);
80  bc_gpio_set_mode(_bc_rf_ook.gpio, BC_GPIO_MODE_OUTPUT);
81 
82  // TIM3 counter stopped when core is halted
83  //DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM3_STOP;
84 
85  // Set default bitrate
87 }
88 
89 void bc_rf_ook_set_bitrate(uint32_t bitrate)
90 {
91  _bc_rf_ook.bit_length_us = 1e6 / bitrate;
92 }
93 
94 void bc_rf_ook_set_bitlength(uint32_t bit_length_us)
95 {
96  _bc_rf_ook.bit_length_us = bit_length_us;
97 }
98 
99 bool bc_rf_ook_send(uint8_t *packet, uint8_t length)
100 {
101  if ((TIM3->CR1 & TIM_CR1_CEN) != 0)
102  {
103  // TIM3 is busy
104  return false;
105  }
106 
107  if (length > sizeof(_bc_rf_ook.packet_data))
108  {
109  // Packet is too long for library's buffer
110  return false;
111  }
112 
113  bc_system_pll_enable();
114 
115  _bc_rf_ook_tim3_configure(1, _bc_rf_ook.bit_length_us);
116 
117  _bc_rf_ook.packet_length = length;
118  _bc_rf_ook.packet_bit_position = 0;
119 
120  memcpy(_bc_rf_ook.packet_data, packet, _bc_rf_ook.packet_length);
121 
122  bc_timer_set_irq_handler(TIM3, _bc_rf_ook_irq_TIM3_handler, NULL);
123 
124  _bc_rf_ook.is_busy = true;
125 
126  TIM3->CR1 |= TIM_CR1_CEN;
127 
128  return true;
129 }
130 
131 bool bc_rf_ook_send_hex_string(char *hex_string)
132 {
133  uint8_t packet_length = _bc_rf_ook_string_to_array(hex_string, _bc_rf_ook.packet_data);
134 
135  return bc_rf_ook_send(_bc_rf_ook.packet_data, packet_length);
136 }
137 
139 {
140  return _bc_rf_ook.is_busy;
141 }
142 
144 {
145  if ((TIM3->CR1 & TIM_CR1_CEN) != 0)
146  {
147  // TIM3 is busy
148  return false;
149  }
150 
151  return _bc_rf_ook.is_busy;
152 }
153 
154 void _bc_rf_ook_irq_TIM3_handler(void *param)
155 {
156  (void) param;
157  TIM3->SR = ~TIM_DIER_UIE;
158 
159  uint8_t byte_index = _bc_rf_ook.packet_bit_position / 8;
160  uint8_t bit_index = _bc_rf_ook.packet_bit_position % 8;
161 
162  if(_bc_rf_ook.packet_bit_position / 8 == _bc_rf_ook.packet_length)
163  {
164  // Disable output after last bit is sent
165  bc_gpio_set_output(_bc_rf_ook.gpio, 0);
166 
167  // end of transmission
168  TIM3->CR1 &= ~TIM_CR1_CEN;
169  _bc_rf_ook.is_busy = false;
170 
171  bc_system_pll_disable();
172 
173  return;
174  }
175 
176  bc_gpio_set_output(_bc_rf_ook.gpio, _bc_rf_ook.packet_data[byte_index] & (1 << (7 - bit_index)));
177 
178  _bc_rf_ook.packet_bit_position++;
179 }
180 
bool bc_rf_ook_send(uint8_t *packet, uint8_t length)
Send data.
Definition: bc_rf_ook.c:99
void bc_rf_ook_init(bc_gpio_channel_t gpio)
Initialize RF OOK library.
Definition: bc_rf_ook.c:73
bool bc_rf_ook_is_busy()
Data sending in progress.
Definition: bc_rf_ook.c:138
void bc_gpio_set_output(bc_gpio_channel_t channel, int state)
Set output state for GPIO channel.
Definition: bc_gpio.c:442
void bc_rf_ook_set_bitrate(uint32_t bitrate)
Configure OOK bitrate.
Definition: bc_rf_ook.c:89
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
bool bc_rf_ook_send_hex_string(char *hex_string)
Send data with data in hex string.
Definition: bc_rf_ook.c:131
bool bc_timer_set_irq_handler(TIM_TypeDef *tim, void(*irq_handler)(void *), void *irq_param)
Register timer IRQ handler.
Definition: bc_timer.c:68
bc_gpio_channel_t
GPIO channels.
Definition: bc_gpio.h:12
bool bc_rf_ook_is_ready()
Data can be send.
Definition: bc_rf_ook.c:143
void bc_rf_ook_set_bitlength(uint32_t bit_length_us)
Configure OOK bitrate.
Definition: bc_rf_ook.c:94
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