Firmware SDK
twr_td1207r.c
1 #include <twr_td1207r.h>
2 
3 #define TWR_TD1207R_DELAY_RUN 100
4 #define TWR_TD1207R_DELAY_INITIALIZATION_RESET_H 100
5 #define TWR_TD1207R_DELAY_INITIALIZATION_AT_COMMAND 3000
6 #define TWR_TD1207R_DELAY_INITIALIZATION_AT_RESPONSE 100
7 #define TWR_TD1207R_DELAY_SEND_RF_FRAME_RESPONSE 8000
8 
9 static void _twr_td1207r_task(void *param);
10 
11 static bool _twr_td1207r_read_response(twr_td1207r_t *self);
12 
14 {
15  memset(self, 0, sizeof(*self));
16 
17  self->_reset_signal = reset_signal;
18  self->_uart_channel = uart_channel;
19 
20  twr_gpio_init(self->_reset_signal);
21  twr_gpio_set_output(self->_reset_signal, 1);
22  twr_gpio_set_mode(self->_reset_signal, TWR_GPIO_MODE_OUTPUT);
23 
24  twr_fifo_init(&self->_tx_fifo, self->_tx_fifo_buffer, sizeof(self->_tx_fifo_buffer));
25  twr_fifo_init(&self->_rx_fifo, self->_rx_fifo_buffer, sizeof(self->_rx_fifo_buffer));
26 
28  twr_uart_set_async_fifo(self->_uart_channel, &self->_tx_fifo, &self->_rx_fifo);
29  twr_uart_async_read_start(self->_uart_channel, TWR_TICK_INFINITY);
30 
31  self->_task_id = twr_scheduler_register(_twr_td1207r_task, self, TWR_TD1207R_DELAY_RUN);
32 
33  self->_state = TWR_TD1207R_STATE_INITIALIZE;
34 }
35 
36 void twr_td1207r_set_event_handler(twr_td1207r_t *self, void (*event_handler)(twr_td1207r_t *, twr_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 == TWR_TD1207R_STATE_READY ? true : false;
45 }
46 
47 bool twr_td1207r_send_rf_frame(twr_td1207r_t *self, const void *buffer, size_t length)
48 {
49  if (!twr_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 = TWR_TD1207R_STATE_SEND_RF_FRAME_COMMAND;
59 
60  twr_scheduler_plan_now(self->_task_id);
61 
62  return true;
63 }
64 
65 static void _twr_td1207r_task(void *param)
66 {
67  twr_td1207r_t *self = param;
68 
69  while (true)
70  {
71  switch (self->_state)
72  {
73  case TWR_TD1207R_STATE_READY:
74  {
75  if (self->_event_handler != NULL)
76  {
77  self->_event_handler(self, TWR_TD1207R_EVENT_READY, self->_event_param);
78  }
79 
80  return;
81  }
82  case TWR_TD1207R_STATE_ERROR:
83  {
84  if (self->_event_handler != NULL)
85  {
86  self->_event_handler(self, TWR_TD1207R_EVENT_ERROR, self->_event_param);
87  }
88 
89  self->_state = TWR_TD1207R_STATE_INITIALIZE;
90 
91  continue;
92  }
93  case TWR_TD1207R_STATE_INITIALIZE:
94  {
95  self->_state = TWR_TD1207R_STATE_INITIALIZE_RESET_L;
96 
97  continue;
98  }
99  case TWR_TD1207R_STATE_INITIALIZE_RESET_L:
100  {
101  twr_gpio_set_output(self->_reset_signal, 0);
102 
103  self->_state = TWR_TD1207R_STATE_INITIALIZE_RESET_H;
104 
105  twr_scheduler_plan_current_from_now(TWR_TD1207R_DELAY_INITIALIZATION_RESET_H);
106 
107  return;
108  }
109  case TWR_TD1207R_STATE_INITIALIZE_RESET_H:
110  {
111  twr_gpio_set_output(self->_reset_signal, 1);
112 
113  self->_state = TWR_TD1207R_STATE_INITIALIZE_AT_COMMAND;
114 
115  twr_scheduler_plan_current_from_now(TWR_TD1207R_DELAY_INITIALIZATION_AT_COMMAND);
116 
117  return;
118  }
119  case TWR_TD1207R_STATE_INITIALIZE_AT_COMMAND:
120  {
121  self->_state = TWR_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 (twr_uart_async_write(self->_uart_channel, self->_command, length) != length)
130  {
131  continue;
132  }
133 
134  self->_state = TWR_TD1207R_STATE_INITIALIZE_AT_RESPONSE;
135 
136  twr_scheduler_plan_current_from_now(TWR_TD1207R_DELAY_INITIALIZATION_AT_RESPONSE);
137 
138  return;
139  }
140  case TWR_TD1207R_STATE_INITIALIZE_AT_RESPONSE:
141  {
142  self->_state = TWR_TD1207R_STATE_ERROR;
143 
144  if (!_twr_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 (!_twr_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 = TWR_TD1207R_STATE_READY;
165 
166  continue;
167  }
168  case TWR_TD1207R_STATE_SEND_RF_FRAME_COMMAND:
169  {
170  self->_state = TWR_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 (twr_uart_async_write(self->_uart_channel, self->_command, length) != length)
204  {
205  continue;
206  }
207 
208  self->_state = TWR_TD1207R_STATE_SEND_RF_FRAME_RESPONSE;
209 
210  if (self->_event_handler != NULL)
211  {
212  self->_event_handler(self, TWR_TD1207R_EVENT_SEND_RF_FRAME_START, self->_event_param);
213  }
214 
215  twr_scheduler_plan_current_from_now(TWR_TD1207R_DELAY_SEND_RF_FRAME_RESPONSE);
216 
217  return;
218  }
219  case TWR_TD1207R_STATE_SEND_RF_FRAME_RESPONSE:
220  {
221  self->_state = TWR_TD1207R_STATE_ERROR;
222 
223  if (!_twr_td1207r_read_response(self))
224  {
225  continue;
226  }
227 
228  if (strcmp(self->_response, self->_command) != 0)
229  {
230  continue;
231  }
232 
233  if (!_twr_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 = TWR_TD1207R_STATE_READY;
244 
245  if (self->_event_handler != NULL)
246  {
247  self->_event_handler(self, TWR_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 _twr_td1207r_read_response(twr_td1207r_t *self)
261 {
262  size_t length = 0;
263 
264  while (true)
265  {
266  char rx_character;
267 
268  if (twr_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 }
void twr_gpio_set_mode(twr_gpio_channel_t channel, twr_gpio_mode_t mode)
Set mode of operation for GPIO channel.
Definition: twr_gpio.c:367
RF frame transmission started event.
Definition: twr_td1207r.h:30
twr_td1207r_event_t
Callback events.
Definition: twr_td1207r.h:21
bool twr_uart_async_read_start(twr_uart_channel_t channel, twr_tick_t timeout)
Start async reading.
Definition: twr_uart.c:458
GPIO channel operates as output.
Definition: twr_gpio.h:108
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
Definition: twr_scheduler.c:53
bool twr_td1207r_send_rf_frame(twr_td1207r_t *self, const void *buffer, size_t length)
Send RF frame command.
Definition: twr_td1207r.c:47
UART baudrat 9600 bps.
Definition: twr_uart.h:31
void twr_uart_init(twr_uart_channel_t channel, twr_uart_baudrate_t baudrate, twr_uart_setting_t setting)
Initialize UART channel.
Definition: twr_uart.c:54
struct twr_td1207r_t twr_td1207r_t
TD1207R instance.
Definition: twr_td1207r.h:39
void twr_fifo_init(twr_fifo_t *fifo, void *buffer, size_t size)
Initialize FIFO buffer.
Definition: twr_fifo.c:4
size_t twr_uart_async_read(twr_uart_channel_t channel, void *buffer, size_t length)
Get data that has been received in async mode.
Definition: twr_uart.c:554
void twr_scheduler_plan_current_from_now(twr_tick_t tick)
Schedule current task to tick relative from now.
void twr_gpio_init(twr_gpio_channel_t channel)
Initialize GPIO channel.
Definition: twr_gpio.c:325
twr_gpio_channel_t
GPIO channels.
Definition: twr_gpio.h:12
RF frame transmission finished event.
Definition: twr_td1207r.h:33
void twr_gpio_set_output(twr_gpio_channel_t channel, int state)
Set output state for GPIO channel.
Definition: twr_gpio.c:471
void twr_td1207r_set_event_handler(twr_td1207r_t *self, void(*event_handler)(twr_td1207r_t *, twr_td1207r_event_t, void *), void *event_param)
Set callback function.
Definition: twr_td1207r.c:36
void twr_td1207r_init(twr_td1207r_t *self, twr_gpio_channel_t reset_signal, twr_uart_channel_t uart_channel)
Initialize TD1207R.
Definition: twr_td1207r.c:13
twr_uart_channel_t
UART channels.
Definition: twr_uart.h:13
bool twr_td1207r_is_ready(twr_td1207r_t *self)
Check if modem is ready for commands.
Definition: twr_td1207r.c:42
#define TWR_TICK_INFINITY
Maximum timestamp value.
Definition: twr_tick.h:12
8N1: 8 data bits, none parity bit, 1 stop bit
Definition: twr_uart.h:70
void twr_uart_set_async_fifo(twr_uart_channel_t channel, twr_fifo_t *write_fifo, twr_fifo_t *read_fifo)
Set buffers for async transfers.
Definition: twr_uart.c:405
void twr_scheduler_plan_now(twr_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
size_t twr_uart_async_write(twr_uart_channel_t channel, const void *buffer, size_t length)
Add data to be transmited in async mode.
Definition: twr_uart.c:411