Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_td1207r.c
1 #include <bc_td1207r.h>
2 
3 #define BC_TD1207R_DELAY_RUN 100
4 #define BC_TD1207R_DELAY_INITIALIZATION_RESET_H 100
5 #define BC_TD1207R_DELAY_INITIALIZATION_AT_COMMAND 3000
6 #define BC_TD1207R_DELAY_INITIALIZATION_AT_RESPONSE 100
7 #define BC_TD1207R_DELAY_SEND_RF_FRAME_RESPONSE 8000
8 
9 static void _bc_td1207r_task(void *param);
10 
11 static bool _bc_td1207r_read_response(bc_td1207r_t *self);
12 
13 void bc_td1207r_init(bc_td1207r_t *self, bc_gpio_channel_t reset_signal, bc_uart_channel_t uart_channel)
14 {
15  memset(self, 0, sizeof(*self));
16 
17  self->_reset_signal = reset_signal;
18  self->_uart_channel = uart_channel;
19 
20  bc_gpio_init(self->_reset_signal);
21  bc_gpio_set_output(self->_reset_signal, 1);
22  bc_gpio_set_mode(self->_reset_signal, BC_GPIO_MODE_OUTPUT);
23 
24  bc_fifo_init(&self->_tx_fifo, self->_tx_fifo_buffer, sizeof(self->_tx_fifo_buffer));
25  bc_fifo_init(&self->_rx_fifo, self->_rx_fifo_buffer, sizeof(self->_rx_fifo_buffer));
26 
28  bc_uart_set_async_fifo(self->_uart_channel, &self->_tx_fifo, &self->_rx_fifo);
29  bc_uart_async_read_start(self->_uart_channel, BC_TICK_INFINITY);
30 
31  self->_task_id = bc_scheduler_register(_bc_td1207r_task, self, BC_TD1207R_DELAY_RUN);
32 
33  self->_state = BC_TD1207R_STATE_INITIALIZE;
34 }
35 
36 void bc_td1207r_set_event_handler(bc_td1207r_t *self, void (*event_handler)(bc_td1207r_t *, bc_td1207r_event_t, void *), void *event_param)
37 {
38  self->_event_handler = event_handler;
39  self->_event_param = event_param;
40 }
41 
43 {
44  return self->_state == BC_TD1207R_STATE_READY ? true : false;
45 }
46 
47 bool bc_td1207r_send_rf_frame(bc_td1207r_t *self, const void *buffer, size_t length)
48 {
49  if (!bc_td1207r_is_ready(self) || length == 0 || length > 12)
50  {
51  return false;
52  }
53 
54  self->_message_length = length;
55 
56  memcpy(self->_message_buffer, buffer, self->_message_length);
57 
58  self->_state = BC_TD1207R_STATE_SEND_RF_FRAME_COMMAND;
59 
60  bc_scheduler_plan_now(self->_task_id);
61 
62  return true;
63 }
64 
65 static void _bc_td1207r_task(void *param)
66 {
67  bc_td1207r_t *self = param;
68 
69  while (true)
70  {
71  switch (self->_state)
72  {
73  case BC_TD1207R_STATE_READY:
74  {
75  if (self->_event_handler != NULL)
76  {
77  self->_event_handler(self, BC_TD1207R_EVENT_READY, self->_event_param);
78  }
79 
80  return;
81  }
82  case BC_TD1207R_STATE_ERROR:
83  {
84  if (self->_event_handler != NULL)
85  {
86  self->_event_handler(self, BC_TD1207R_EVENT_ERROR, self->_event_param);
87  }
88 
89  self->_state = BC_TD1207R_STATE_INITIALIZE;
90 
91  continue;
92  }
93  case BC_TD1207R_STATE_INITIALIZE:
94  {
95  self->_state = BC_TD1207R_STATE_INITIALIZE_RESET_L;
96 
97  continue;
98  }
99  case BC_TD1207R_STATE_INITIALIZE_RESET_L:
100  {
101  bc_gpio_set_output(self->_reset_signal, 0);
102 
103  self->_state = BC_TD1207R_STATE_INITIALIZE_RESET_H;
104 
105  bc_scheduler_plan_current_from_now(BC_TD1207R_DELAY_INITIALIZATION_RESET_H);
106 
107  return;
108  }
109  case BC_TD1207R_STATE_INITIALIZE_RESET_H:
110  {
111  bc_gpio_set_output(self->_reset_signal, 1);
112 
113  self->_state = BC_TD1207R_STATE_INITIALIZE_AT_COMMAND;
114 
115  bc_scheduler_plan_current_from_now(BC_TD1207R_DELAY_INITIALIZATION_AT_COMMAND);
116 
117  return;
118  }
119  case BC_TD1207R_STATE_INITIALIZE_AT_COMMAND:
120  {
121  self->_state = BC_TD1207R_STATE_ERROR;
122 
123  // TODO Purge RX FIFO
124 
125  strcpy(self->_command, "\rAT\r");
126 
127  size_t length = strlen(self->_command);
128 
129  if (bc_uart_async_write(self->_uart_channel, self->_command, length) != length)
130  {
131  continue;
132  }
133 
134  self->_state = BC_TD1207R_STATE_INITIALIZE_AT_RESPONSE;
135 
136  bc_scheduler_plan_current_from_now(BC_TD1207R_DELAY_INITIALIZATION_AT_RESPONSE);
137 
138  return;
139  }
140  case BC_TD1207R_STATE_INITIALIZE_AT_RESPONSE:
141  {
142  self->_state = BC_TD1207R_STATE_ERROR;
143 
144  if (!_bc_td1207r_read_response(self))
145  {
146  continue;
147  }
148 
149  if (strcmp(self->_response, self->_command + 1) != 0)
150  {
151  continue;
152  }
153 
154  if (!_bc_td1207r_read_response(self))
155  {
156  continue;
157  }
158 
159  if (strcmp(self->_response, "OK\r") != 0)
160  {
161  continue;
162  }
163 
164  self->_state = BC_TD1207R_STATE_READY;
165 
166  continue;
167  }
168  case BC_TD1207R_STATE_SEND_RF_FRAME_COMMAND:
169  {
170  self->_state = BC_TD1207R_STATE_ERROR;
171 
172  static const char *hex_lookup_table[] =
173  {
174  "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
175  "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
176  "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
177  "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
178  "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
179  "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
180  "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
181  "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
182  "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
183  "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
184  "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
185  "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
186  "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
187  "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
188  "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
189  "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"
190  };
191 
192  strcpy(self->_command, "AT$SF=");
193 
194  for (size_t i = 0; i < self->_message_length; i++)
195  {
196  strcat(self->_command, hex_lookup_table[*((uint8_t *) self->_message_buffer + i)]);
197  }
198 
199  strcat(self->_command, "\r");
200 
201  size_t length = strlen(self->_command);
202 
203  if (bc_uart_async_write(self->_uart_channel, self->_command, length) != length)
204  {
205  continue;
206  }
207 
208  self->_state = BC_TD1207R_STATE_SEND_RF_FRAME_RESPONSE;
209 
210  if (self->_event_handler != NULL)
211  {
212  self->_event_handler(self, BC_TD1207R_EVENT_SEND_RF_FRAME_START, self->_event_param);
213  }
214 
215  bc_scheduler_plan_current_from_now(BC_TD1207R_DELAY_SEND_RF_FRAME_RESPONSE);
216 
217  return;
218  }
219  case BC_TD1207R_STATE_SEND_RF_FRAME_RESPONSE:
220  {
221  self->_state = BC_TD1207R_STATE_ERROR;
222 
223  if (!_bc_td1207r_read_response(self))
224  {
225  continue;
226  }
227 
228  if (strcmp(self->_response, self->_command) != 0)
229  {
230  continue;
231  }
232 
233  if (!_bc_td1207r_read_response(self))
234  {
235  continue;
236  }
237 
238  if (strcmp(self->_response, "OK\r") != 0)
239  {
240  continue;
241  }
242 
243  self->_state = BC_TD1207R_STATE_READY;
244 
245  if (self->_event_handler != NULL)
246  {
247  self->_event_handler(self, BC_TD1207R_EVENT_SEND_RF_FRAME_DONE, self->_event_param);
248  }
249 
250  continue;
251  }
252  default:
253  {
254  break;
255  }
256  }
257  }
258 }
259 
260 static bool _bc_td1207r_read_response(bc_td1207r_t *self)
261 {
262  size_t length = 0;
263 
264  while (true)
265  {
266  char rx_character;
267 
268  if (bc_uart_async_read(self->_uart_channel, &rx_character, 1) == 0)
269  {
270  return false;
271  }
272 
273  if (rx_character == '\n')
274  {
275  continue;
276  }
277 
278  self->_response[length++] = rx_character;
279 
280  if (rx_character == '\r')
281  {
282  if (length == 1)
283  {
284  length = 0;
285 
286  continue;
287  }
288 
289  self->_response[length] = '\0';
290 
291  break;
292  }
293 
294  if (length == sizeof(self->_response) - 1)
295  {
296  return false;
297  }
298  }
299 
300  return true;
301 }
bool bc_td1207r_send_rf_frame(bc_td1207r_t *self, const void *buffer, size_t length)
Send RF frame command.
Definition: bc_td1207r.c:47
bc_uart_channel_t
UART channels.
Definition: bc_uart.h:13
bool bc_uart_async_read_start(bc_uart_channel_t channel, bc_tick_t timeout)
Start async reading.
Definition: bc_uart.c:475
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
8N1: 8 data bits, none parity bit, 1 stop bit
Definition: bc_uart.h:70
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_output(bc_gpio_channel_t channel, int state)
Set output state for GPIO channel.
Definition: bc_gpio.c:442
RF frame transmission started event.
Definition: bc_td1207r.h:30
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_uart_init(bc_uart_channel_t channel, bc_uart_baudrate_t baudrate, bc_uart_setting_t setting)
Initialize UART channel.
Definition: bc_uart.c:53
struct bc_td1207r_t bc_td1207r_t
TD1207R instance.
Definition: bc_td1207r.h:39
void bc_fifo_init(bc_fifo_t *fifo, void *buffer, size_t size)
Initialize FIFO buffer.
Definition: bc_fifo.c:4
void bc_td1207r_set_event_handler(bc_td1207r_t *self, void(*event_handler)(bc_td1207r_t *, bc_td1207r_event_t, void *), void *event_param)
Set callback function.
Definition: bc_td1207r.c:36
bc_td1207r_event_t
Callback events.
Definition: bc_td1207r.h:21
void bc_scheduler_plan_current_from_now(bc_tick_t tick)
Schedule current task to tick relative from now.
Definition: bc_scheduler.c:154
size_t bc_uart_async_write(bc_uart_channel_t channel, const void *buffer, size_t length)
Add data to be transmited in async mode.
Definition: bc_uart.c:428
void bc_uart_set_async_fifo(bc_uart_channel_t channel, bc_fifo_t *write_fifo, bc_fifo_t *read_fifo)
Set buffers for async transfers.
Definition: bc_uart.c:422
RF frame transmission finished event.
Definition: bc_td1207r.h:33
void bc_td1207r_init(bc_td1207r_t *self, bc_gpio_channel_t reset_signal, bc_uart_channel_t uart_channel)
Initialize TD1207R.
Definition: bc_td1207r.c:13
#define BC_TICK_INFINITY
Maximum timestamp value.
Definition: bc_tick.h:12
bc_gpio_channel_t
GPIO channels.
Definition: bc_gpio.h:12
UART baudrat 9600 bps.
Definition: bc_uart.h:31
Error event.
Definition: bc_td1207r.h:27
Ready event.
Definition: bc_td1207r.h:24
size_t bc_uart_async_read(bc_uart_channel_t channel, void *buffer, size_t length)
Get data that has been received in async mode.
Definition: bc_uart.c:571
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
bool bc_td1207r_is_ready(bc_td1207r_t *self)
Check if modem is ready for commands.
Definition: bc_td1207r.c:42