1 #include <twr_wssfm10r1at.h>
3 #define TWR_WSSFM10R1AT_DELAY_RUN 100
4 #define TWR_WSSFM10R1AT_DELAY_INITIALIZATION_RESET_H 100
5 #define TWR_WSSFM10R1AT_DELAY_INITIALIZATION_AT_COMMAND 100
6 #define TWR_WSSFM10R1AT_DELAY_INITIALIZATION_AT_RESPONSE 100
7 #define TWR_WSSFM10R1AT_DELAY_SET_POWER_RESPONSE 100
8 #define TWR_WSSFM10R1AT_DELAY_SEND_RF_FRAME_RESPONSE 12000
9 #define TWR_WSSFM10R1AT_DELAY_READ_ID_RESPONSE 100
10 #define TWR_WSSFM10R1AT_DELAY_READ_PAC_RESPONSE 100
11 #define TWR_WSSFM10R1AT_DELAY_CONTINUOUS_WAVE_RESPONSE 2000
12 #define TWR_WSSFM10R1AT_DELAY_DEEP_SLEEP_RESPONSE 100
14 static void _twr_wssfm10r1at_task(
void *param);
16 static void _twr_wssfm10r1at_set_state(
twr_wssfm10r1at_t *
self, twr_wssfm10r1at_state_t state);
22 memset(
self, 0,
sizeof(*
self));
24 self->_reset_signal = reset_signal;
25 self->_uart_channel = uart_channel;
31 twr_fifo_init(&self->_tx_fifo, self->_tx_fifo_buffer,
sizeof(self->_tx_fifo_buffer));
32 twr_fifo_init(&self->_rx_fifo, self->_rx_fifo_buffer,
sizeof(self->_rx_fifo_buffer));
40 self->_state = TWR_WSSFM10R1AT_STATE_INITIALIZE;
45 self->_event_handler = event_handler;
46 self->_event_param = event_param;
51 if (self->_state == TWR_WSSFM10R1AT_STATE_READY)
56 if (self->_state == TWR_WSSFM10R1AT_STATE_DEEP_SLEEP)
71 self->_message_length = length;
73 memcpy(self->_message_buffer, buffer, self->_message_length);
75 _twr_wssfm10r1at_set_state(
self, TWR_WSSFM10R1AT_STATE_SEND_RF_FRAME_COMMAND);
87 _twr_wssfm10r1at_set_state(
self, TWR_WSSFM10R1AT_STATE_READ_DEVICE_ID_COMMAND);
94 if (buffer_size < 8 + 1)
99 if (self->_state != TWR_WSSFM10R1AT_STATE_READ_DEVICE_ID_RESPONSE)
104 if (strlen(self->_response) != 9 || self->_response[8] !=
'\r')
109 strncpy(buffer, self->_response, 8);
123 _twr_wssfm10r1at_set_state(
self, TWR_WSSFM10R1AT_STATE_READ_DEVICE_PAC_COMMAND);
130 if (buffer_size < 16 + 1)
135 if (self->_state != TWR_WSSFM10R1AT_STATE_READ_DEVICE_PAC_RESPONSE)
140 if (strlen(self->_response) != 17 || self->_response[16] !=
'\r')
145 strncpy(buffer, self->_response, 16);
159 _twr_wssfm10r1at_set_state(
self, TWR_WSSFM10R1AT_STATE_CONTINUOUS_WAVE_COMMAND);
164 static void _twr_wssfm10r1at_task(
void *param)
170 switch (self->_state)
172 case TWR_WSSFM10R1AT_STATE_READY:
174 if (self->_deep_sleep)
176 self->_deep_sleep =
false;
178 self->_state =
self->_state_after_sleep;
183 if (self->_event_handler != NULL)
188 if (self->_state == TWR_WSSFM10R1AT_STATE_READY)
190 self->_state = TWR_WSSFM10R1AT_STATE_DEEP_SLEEP_COMMAND;
195 case TWR_WSSFM10R1AT_STATE_ERROR:
197 self->_deep_sleep =
false;
199 if (self->_event_handler != NULL)
204 self->_state = TWR_WSSFM10R1AT_STATE_INITIALIZE;
208 case TWR_WSSFM10R1AT_STATE_INITIALIZE:
210 self->_state = TWR_WSSFM10R1AT_STATE_INITIALIZE_RESET_L;
214 case TWR_WSSFM10R1AT_STATE_INITIALIZE_RESET_L:
218 self->_state = TWR_WSSFM10R1AT_STATE_INITIALIZE_RESET_H;
224 case TWR_WSSFM10R1AT_STATE_INITIALIZE_RESET_H:
228 self->_state = TWR_WSSFM10R1AT_STATE_INITIALIZE_AT_COMMAND;
234 case TWR_WSSFM10R1AT_STATE_INITIALIZE_AT_COMMAND:
236 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
240 strcpy(self->_command,
"\rAT\r");
242 size_t length = strlen(self->_command);
251 self->_state = TWR_WSSFM10R1AT_STATE_INITIALIZE_AT_RESPONSE;
257 case TWR_WSSFM10R1AT_STATE_INITIALIZE_AT_RESPONSE:
259 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
261 if (!_twr_wssfm10r1at_read_response(
self))
266 if (strcmp(self->_response,
"OK\r") != 0)
271 self->_state = TWR_WSSFM10R1AT_STATE_SET_POWER_COMMAND;
275 case TWR_WSSFM10R1AT_STATE_SET_POWER_COMMAND:
277 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
279 strcpy(self->_command,
"ATS302=15\r");
281 size_t length = strlen(self->_command);
288 self->_state = TWR_WSSFM10R1AT_STATE_SET_POWER_RESPONSE;
294 case TWR_WSSFM10R1AT_STATE_SET_POWER_RESPONSE:
296 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
298 if (!_twr_wssfm10r1at_read_response(
self))
303 if (strcmp(self->_response,
"OK\r") != 0)
308 self->_state = TWR_WSSFM10R1AT_STATE_READY;
312 case TWR_WSSFM10R1AT_STATE_SEND_RF_FRAME_COMMAND:
314 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
316 static const char *hex_lookup_table[] =
318 "00",
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"0A",
"0B",
"0C",
"0D",
"0E",
"0F",
319 "10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"1A",
"1B",
"1C",
"1D",
"1E",
"1F",
320 "20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"2A",
"2B",
"2C",
"2D",
"2E",
"2F",
321 "30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"3A",
"3B",
"3C",
"3D",
"3E",
"3F",
322 "40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"4A",
"4B",
"4C",
"4D",
"4E",
"4F",
323 "50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
"5A",
"5B",
"5C",
"5D",
"5E",
"5F",
324 "60",
"61",
"62",
"63",
"64",
"65",
"66",
"67",
"68",
"69",
"6A",
"6B",
"6C",
"6D",
"6E",
"6F",
325 "70",
"71",
"72",
"73",
"74",
"75",
"76",
"77",
"78",
"79",
"7A",
"7B",
"7C",
"7D",
"7E",
"7F",
326 "80",
"81",
"82",
"83",
"84",
"85",
"86",
"87",
"88",
"89",
"8A",
"8B",
"8C",
"8D",
"8E",
"8F",
327 "90",
"91",
"92",
"93",
"94",
"95",
"96",
"97",
"98",
"99",
"9A",
"9B",
"9C",
"9D",
"9E",
"9F",
328 "A0",
"A1",
"A2",
"A3",
"A4",
"A5",
"A6",
"A7",
"A8",
"A9",
"AA",
"AB",
"AC",
"AD",
"AE",
"AF",
329 "B0",
"B1",
"B2",
"B3",
"B4",
"B5",
"B6",
"B7",
"B8",
"B9",
"BA",
"BB",
"BC",
"BD",
"BE",
"BF",
330 "C0",
"C1",
"C2",
"C3",
"C4",
"C5",
"C6",
"C7",
"C8",
"C9",
"CA",
"CB",
"CC",
"CD",
"CE",
"CF",
331 "D0",
"D1",
"D2",
"D3",
"D4",
"D5",
"D6",
"D7",
"D8",
"D9",
"DA",
"DB",
"DC",
"DD",
"DE",
"DF",
332 "E0",
"E1",
"E2",
"E3",
"E4",
"E5",
"E6",
"E7",
"E8",
"E9",
"EA",
"EB",
"EC",
"ED",
"EE",
"EF",
333 "F0",
"F1",
"F2",
"F3",
"F4",
"F5",
"F6",
"F7",
"F8",
"F9",
"FA",
"FB",
"FC",
"FD",
"FE",
"FF"
336 strcpy(self->_command,
"AT$SF=");
338 for (
size_t i = 0; i <
self->_message_length; i++)
340 strcat(self->_command, hex_lookup_table[*((uint8_t *) self->_message_buffer + i)]);
343 strcat(self->_command,
"\r");
345 size_t length = strlen(self->_command);
352 self->_state = TWR_WSSFM10R1AT_STATE_SEND_RF_FRAME_RESPONSE;
354 if (self->_event_handler != NULL)
363 case TWR_WSSFM10R1AT_STATE_SEND_RF_FRAME_RESPONSE:
365 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
367 if (!_twr_wssfm10r1at_read_response(
self))
372 if (strcmp(self->_response,
"OK\r") != 0)
377 self->_state = TWR_WSSFM10R1AT_STATE_READY;
379 if (self->_event_handler != NULL)
386 case TWR_WSSFM10R1AT_STATE_READ_DEVICE_ID_COMMAND:
388 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
390 strcpy(self->_command,
"AT$I=10\r");
392 size_t length = strlen(self->_command);
399 self->_state = TWR_WSSFM10R1AT_STATE_READ_DEVICE_ID_RESPONSE;
405 case TWR_WSSFM10R1AT_STATE_READ_DEVICE_ID_RESPONSE:
407 if (!_twr_wssfm10r1at_read_response(
self))
409 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
414 if (self->_event_handler != NULL)
419 self->_state = TWR_WSSFM10R1AT_STATE_READY;
423 case TWR_WSSFM10R1AT_STATE_READ_DEVICE_PAC_COMMAND:
425 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
427 strcpy(self->_command,
"AT$I=11\r");
429 size_t length = strlen(self->_command);
436 self->_state = TWR_WSSFM10R1AT_STATE_READ_DEVICE_PAC_RESPONSE;
442 case TWR_WSSFM10R1AT_STATE_READ_DEVICE_PAC_RESPONSE:
444 if (!_twr_wssfm10r1at_read_response(
self))
446 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
451 if (self->_event_handler != NULL)
456 self->_state = TWR_WSSFM10R1AT_STATE_READY;
460 case TWR_WSSFM10R1AT_STATE_CONTINUOUS_WAVE_COMMAND:
462 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
464 strcpy(self->_command,
"AT$CW=868130000,1,15\r");
466 size_t length = strlen(self->_command);
473 self->_state = TWR_WSSFM10R1AT_STATE_CONTINUOUS_WAVE_RESPONSE;
479 case TWR_WSSFM10R1AT_STATE_CONTINUOUS_WAVE_RESPONSE:
481 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
483 if (!_twr_wssfm10r1at_read_response(
self))
488 if (strcmp(self->_response,
"OK\r") != 0)
493 self->_state = TWR_WSSFM10R1AT_STATE_CONTINUOUS_WAVE;
497 case TWR_WSSFM10R1AT_STATE_CONTINUOUS_WAVE:
501 case TWR_WSSFM10R1AT_STATE_DEEP_SLEEP_COMMAND:
503 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
505 strcpy(self->_command,
"AT$P=2\r");
507 size_t length = strlen(self->_command);
514 self->_state = TWR_WSSFM10R1AT_STATE_DEEP_SLEEP_RESPONSE;
520 case TWR_WSSFM10R1AT_STATE_DEEP_SLEEP_RESPONSE:
522 self->_state = TWR_WSSFM10R1AT_STATE_ERROR;
524 if (!_twr_wssfm10r1at_read_response(
self))
529 if (strcmp(self->_response,
"OK\r") != 0)
534 self->_state = TWR_WSSFM10R1AT_STATE_DEEP_SLEEP;
538 case TWR_WSSFM10R1AT_STATE_DEEP_SLEEP:
540 self->_deep_sleep =
true;
552 static void _twr_wssfm10r1at_set_state(
twr_wssfm10r1at_t *
self, twr_wssfm10r1at_state_t state)
554 if (self->_deep_sleep)
556 self->_state = TWR_WSSFM10R1AT_STATE_INITIALIZE;
558 self->_state_after_sleep = state;
562 self->_state = state;
581 if (rx_character ==
'\n')
586 self->_response[length++] = rx_character;
588 if (rx_character ==
'\r')
597 self->_response[length] =
'\0';
602 if (length ==
sizeof(self->_response) - 1)
void twr_fifo_init(twr_fifo_t *fifo, void *buffer, size_t size)
Initialize FIFO buffer.
void twr_gpio_set_output(twr_gpio_channel_t channel, int state)
Set output state for GPIO channel.
void twr_gpio_init(twr_gpio_channel_t channel)
Initialize GPIO channel.
twr_gpio_channel_t
GPIO channels.
void twr_gpio_set_mode(twr_gpio_channel_t channel, twr_gpio_mode_t mode)
Set mode of operation for GPIO channel.
@ TWR_GPIO_MODE_OUTPUT
GPIO channel operates as output.
void twr_scheduler_plan_current_from_now(twr_tick_t tick)
Schedule current task to tick relative from now.
void twr_scheduler_plan_now(twr_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
#define TWR_TICK_INFINITY
Maximum timestamp value.
twr_uart_channel_t
UART channels.
void twr_uart_init(twr_uart_channel_t channel, twr_uart_baudrate_t baudrate, twr_uart_setting_t setting)
Initialize UART channel.
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.
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.
bool twr_uart_async_read_start(twr_uart_channel_t channel, twr_tick_t timeout)
Start async reading.
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.
@ TWR_UART_BAUDRATE_9600
UART baudrat 9600 bps.
@ TWR_UART_SETTING_8N1
8N1: 8 data bits, none parity bit, 1 stop bit
bool twr_wssfm10r1at_get_device_id(twr_wssfm10r1at_t *self, char *buffer, size_t buffer_size)
Get device ID (can be called only in TWR_WSSFM10R1AT_EVENT_READ_DEVICE_ID event)
void twr_wssfm10r1at_set_event_handler(twr_wssfm10r1at_t *self, void(*event_handler)(twr_wssfm10r1at_t *, twr_wssfm10r1at_event_t, void *), void *event_param)
Set callback function.
twr_wssfm10r1at_event_t
Callback events.
bool twr_wssfm10r1at_is_ready(twr_wssfm10r1at_t *self)
Check if modem is ready for commands.
bool twr_wssfm10r1at_send_rf_frame(twr_wssfm10r1at_t *self, const void *buffer, size_t length)
Send RF frame command.
bool twr_wssfm10r1at_read_device_id(twr_wssfm10r1at_t *self)
Read device ID command.
void twr_wssfm10r1at_init(twr_wssfm10r1at_t *self, twr_gpio_channel_t reset_signal, twr_uart_channel_t uart_channel)
Initialize WSSFM10R1AT.
struct twr_wssfm10r1at_t twr_wssfm10r1at_t
WSSFM10R1AT instance.
bool twr_wssfm10r1at_read_device_pac(twr_wssfm10r1at_t *self)
Read device PAC command.
bool twr_wssfm10r1at_get_device_pac(twr_wssfm10r1at_t *self, char *buffer, size_t buffer_size)
Get device PAC (can be called only in TWR_WSSFM10R1AT_EVENT_READ_DEVICE_PAC event)
bool twr_wssfm10r1at_continuous_wave(twr_wssfm10r1at_t *self)
Generate continuous wave command.
@ TWR_WSSFM10R1AT_EVENT_SEND_RF_FRAME_DONE
RF frame transmission finished event.
@ TWR_WSSFM10R1AT_EVENT_ERROR
Error event.
@ TWR_WSSFM10R1AT_EVENT_SEND_RF_FRAME_START
RF frame transmission started event.
@ TWR_WSSFM10R1AT_EVENT_READY
Ready event.
@ TWR_WSSFM10R1AT_EVENT_READ_DEVICE_PAC
Device PAC has been read event.
@ TWR_WSSFM10R1AT_EVENT_READ_DEVICE_ID
Device ID has been read event.