3 #include <twr_atsha204.h>
4 #include <twr_scheduler.h>
5 #include <twr_eeprom.h>
7 #include <twr_radio_pub.h>
8 #include <twr_radio_node.h>
11 #define _TWR_RADIO_SCAN_CACHE_LENGTH 4
12 #define _TWR_RADIO_ACK_TIMEOUT 100
13 #define _TWR_RADIO_SLEEP_RX_TIMEOUT 100
14 #define _TWR_RADIO_TX_MAX_COUNT 6
15 #define _TWR_RADIO_ACK_SUB_REQUEST 0x11
19 TWR_RADIO_STATE_SLEEP = 0,
20 TWR_RADIO_STATE_TX = 1,
21 TWR_RADIO_STATE_RX = 2,
22 TWR_RADIO_STATE_TX_WAIT_ACK = 3,
23 TWR_RADIO_STATE_RX_SEND_ACK = 4,
24 TWR_RADIO_STATE_TX_SEND_ACK = 5,
32 twr_radio_state_t state;
36 void (*event_handler)(twr_radio_event_t,
void *);
39 bool pairing_request_to_gateway;
41 const char *firmware_version;
44 twr_queue_t pub_queue;
46 uint8_t pub_queue_buffer[TWR_RADIO_PUB_QUEUE_BUFFER_SIZE];
47 uint8_t rx_queue_buffer[TWR_RADIO_RX_QUEUE_BUFFER_SIZE];
49 uint8_t ack_tx_cache_buffer[15];
50 size_t ack_tx_cache_length;
51 int ack_transmit_count;
56 int peer_devices_length;
64 uint64_t scan_cache[_TWR_RADIO_SCAN_CACHE_LENGTH];
68 bool automatic_pairing;
69 bool save_peer_devices;
77 static void _twr_radio_task(
void *param);
78 static void _twr_radio_go_to_state_rx_or_sleep(
void);
80 static void _twr_radio_load_peer_devices(
void);
81 static void _twr_radio_save_peer_devices(
void);
83 static bool _twr_radio_peer_device_add(uint64_t
id);
84 static bool _twr_radio_peer_device_remove(uint64_t
id);
86 __attribute__((weak))
void twr_radio_on_info(uint64_t *
id,
char *firmware,
char *version,
twr_radio_mode_t mode) { (void)
id; (void) firmware; (void) version; (void) mode;}
87 __attribute__((weak))
void twr_radio_on_sub(uint64_t *
id, uint8_t *order,
twr_radio_sub_pt_t *pt,
char *topic) { (void)
id; (void) order; (void) pt; (void) topic; }
91 memset(&_twr_radio, 0,
sizeof(_twr_radio));
93 _twr_radio.mode = mode;
99 twr_queue_init(&_twr_radio.pub_queue, _twr_radio.pub_queue_buffer,
sizeof(_twr_radio.pub_queue_buffer));
100 twr_queue_init(&_twr_radio.rx_queue, _twr_radio.rx_queue_buffer,
sizeof(_twr_radio.rx_queue_buffer));
105 _twr_radio_load_peer_devices();
109 _twr_radio_go_to_state_rx_or_sleep();
112 void twr_radio_set_event_handler(
void (*event_handler)(twr_radio_event_t,
void *),
void *event_param)
114 _twr_radio.event_handler = event_handler;
115 _twr_radio.event_param = event_param;
120 _twr_radio.rx_timeout_sleeping =
twr_tick_get() + timeout;
125 void twr_radio_pairing_request(
const char *firmware,
const char *version)
127 _twr_radio.firmware = firmware == NULL ?
"" : firmware;
129 _twr_radio.firmware_version = version == NULL ?
"" : version;
131 _twr_radio.pairing_request_to_gateway =
true;
136 void twr_radio_pairing_mode_start(
void)
138 _twr_radio.pairing_mode =
true;
141 void twr_radio_pairing_mode_stop(
void)
143 _twr_radio.pairing_mode =
false;
146 bool twr_radio_peer_device_add(uint64_t
id)
149 if (!_twr_radio_peer_device_add(
id))
154 uint8_t buffer[1 + TWR_RADIO_ID_SIZE];
156 buffer[0] = TWR_RADIO_HEADER_NODE_ATTACH;
158 twr_radio_id_to_buffer(&
id, buffer + 1);
160 twr_queue_put(&_twr_radio.pub_queue, buffer,
sizeof(buffer));
167 bool twr_radio_peer_device_remove(uint64_t
id)
169 if (!_twr_radio_peer_device_remove(
id))
174 uint8_t buffer[1 + TWR_RADIO_ID_SIZE];
176 buffer[0] = TWR_RADIO_HEADER_NODE_DETACH;
178 twr_radio_id_to_buffer(&
id, buffer + 1);
180 twr_queue_put(&_twr_radio.pub_queue, buffer,
sizeof(buffer));
187 bool twr_radio_peer_device_purge_all(
void)
189 for (
int i = _twr_radio.peer_devices_length -1; i > -1 ; i--)
191 if (_twr_radio.peer_devices[i].id != 0)
193 if (!twr_radio_peer_device_remove(_twr_radio.peer_devices[i].id))
202 void twr_radio_get_peer_id(uint64_t *
id,
int length)
205 for (i = 0; (i < _twr_radio.peer_devices_length) && (i < length); i++)
207 id[i] = _twr_radio.peer_devices[i].id;
209 for (;i < length; i++)
215 void twr_radio_scan_start(
void)
217 memset(_twr_radio.scan_cache, 0x00,
sizeof(_twr_radio.scan_cache));
218 _twr_radio.scan_length = 0;
219 _twr_radio.scan_head = 0;
220 _twr_radio.scan =
true;
223 void twr_radio_scan_stop(
void)
225 _twr_radio.scan =
false;
228 void twr_radio_automatic_pairing_start(
void)
230 _twr_radio.automatic_pairing =
true;
233 void twr_radio_automatic_pairing_stop(
void)
235 _twr_radio.automatic_pairing =
false;
238 uint64_t twr_radio_get_my_id(
void)
240 return _twr_radio.my_id;
243 uint64_t twr_radio_get_event_id(
void)
245 return _twr_radio.peer_id;
248 bool twr_radio_is_peer_device(uint64_t
id)
250 for (
int i = 0; i < _twr_radio.peer_devices_length; i++)
252 if (
id == _twr_radio.peer_devices[i].id)
260 bool twr_radio_pub_queue_put(
const void *buffer,
size_t length)
279 _twr_radio.subs = subs;
281 _twr_radio.subs_length = length;
283 _twr_radio.sent_subs = 0;
286 bool twr_radio_send_sub_data(uint64_t *
id, uint8_t order,
void *payload,
size_t size)
288 uint8_t qbuffer[1 + TWR_RADIO_ID_SIZE + TWR_RADIO_NODE_MAX_BUFFER_SIZE];
290 if (size > TWR_RADIO_NODE_MAX_BUFFER_SIZE - 1)
295 qbuffer[0] = TWR_RADIO_HEADER_SUB_DATA;
297 uint8_t *pqbuffer = twr_radio_id_to_buffer(
id, qbuffer + 1);
308 memcpy(pqbuffer, payload, size);
311 return twr_radio_pub_queue_put(qbuffer, 1 + TWR_RADIO_ID_SIZE + 1 + size);
314 void twr_radio_set_rx_timeout_for_sleeping_node(
twr_tick_t timeout)
316 _twr_radio.sleeping_mode_rx_timeout = timeout;
319 static void _twr_radio_task(
void *param)
323 if (_twr_radio.my_id == 0)
332 if ((_twr_radio.state != TWR_RADIO_STATE_RX) && (_twr_radio.state != TWR_RADIO_STATE_SLEEP))
339 if (_twr_radio.save_peer_devices)
341 _twr_radio_save_peer_devices();
344 if (_twr_radio.pairing_request_to_gateway)
346 _twr_radio.pairing_request_to_gateway =
false;
348 size_t len_firmware = strlen(_twr_radio.firmware);
350 size_t len = len_firmware + strlen(_twr_radio.firmware_version);
352 if (len > TWR_RADIO_MAX_BUFFER_SIZE - 5)
359 twr_radio_id_to_buffer(&_twr_radio.my_id, buffer);
361 _twr_radio.message_id++;
363 buffer[6] = _twr_radio.message_id;
364 buffer[7] = _twr_radio.message_id >> 8;
366 buffer[8] = TWR_RADIO_HEADER_PAIRING;
367 buffer[9] = len_firmware;
369 strncpy((
char *)buffer + 10, _twr_radio.firmware, TWR_RADIO_MAX_BUFFER_SIZE - 2);
370 strncpy((
char *)buffer + 10 + len_firmware + 1, _twr_radio.firmware_version, TWR_RADIO_MAX_BUFFER_SIZE - 2 - len_firmware - 1);
372 buffer[10 + len + 1] = _twr_radio.mode;
378 _twr_radio.transmit_count = _TWR_RADIO_TX_MAX_COUNT;
380 _twr_radio.state = TWR_RADIO_STATE_TX;
385 if (_twr_radio.ack && (_twr_radio.sent_subs != _twr_radio.subs_length))
391 twr_radio_id_to_buffer(&_twr_radio.my_id, buffer);
393 _twr_radio.message_id++;
395 buffer[6] = _twr_radio.message_id;
396 buffer[7] = _twr_radio.message_id >> 8;
398 buffer[8] = TWR_RADIO_HEADER_SUB_REG;
400 buffer[9] = _twr_radio.sent_subs;
402 buffer[10] = sub->type;
404 strncpy((
char *)buffer + 11, sub->topic, TWR_RADIO_MAX_BUFFER_SIZE - 3);
410 _twr_radio.transmit_count = _TWR_RADIO_TX_MAX_COUNT;
412 _twr_radio.state = TWR_RADIO_STATE_TX;
417 uint8_t queue_item_buffer[
sizeof(_twr_radio.pub_queue_buffer)];
418 size_t queue_item_length;
421 while (
twr_queue_get(&_twr_radio.rx_queue, queue_item_buffer, &queue_item_length))
423 twr_radio_id_from_buffer(queue_item_buffer, &
id);
425 queue_item_length -= TWR_RADIO_HEAD_SIZE;
431 if (queue_item_buffer[TWR_RADIO_HEAD_SIZE] == TWR_RADIO_HEADER_SUB_DATA)
433 uint8_t order = queue_item_buffer[TWR_RADIO_HEAD_SIZE + 1 + TWR_RADIO_ID_SIZE];
435 if (order >= _twr_radio.subs_length)
442 if (sub->callback != NULL)
444 uint8_t *payload = NULL;
446 if (queue_item_length > 1 + TWR_RADIO_ID_SIZE + 1)
448 payload = queue_item_buffer + TWR_RADIO_HEAD_SIZE + 1 + TWR_RADIO_ID_SIZE + 1;
451 sub->callback(&
id, sub->topic, payload, sub->param);
454 else if (queue_item_buffer[TWR_RADIO_HEAD_SIZE] == TWR_RADIO_HEADER_PUB_INFO)
456 queue_item_buffer[queue_item_length + TWR_RADIO_HEAD_SIZE - 1] = 0;
460 else if (queue_item_buffer[TWR_RADIO_HEAD_SIZE] == TWR_RADIO_HEADER_SUB_REG)
462 uint8_t *order = queue_item_buffer + TWR_RADIO_HEAD_SIZE + 1;
466 char *topic = (
char *) queue_item_buffer + TWR_RADIO_HEAD_SIZE + 3;
468 twr_radio_on_sub(&
id, order, pt, topic);
472 if (
twr_queue_get(&_twr_radio.pub_queue, queue_item_buffer, &queue_item_length))
476 twr_radio_id_to_buffer(&_twr_radio.my_id, buffer);
478 _twr_radio.message_id++;
480 buffer[6] = _twr_radio.message_id;
481 buffer[7] = _twr_radio.message_id >> 8;
483 memcpy(buffer + 8, queue_item_buffer, queue_item_length);
489 _twr_radio.transmit_count = _TWR_RADIO_TX_MAX_COUNT;
491 _twr_radio.state = TWR_RADIO_STATE_TX;
495 static bool _twr_radio_scan_cache_push(
void)
497 for (uint8_t i = 0; i < _twr_radio.scan_length; i++)
499 if (_twr_radio.scan_cache[i] == _twr_radio.peer_id)
505 if (_twr_radio.scan_length < _TWR_RADIO_SCAN_CACHE_LENGTH)
507 _twr_radio.scan_length++;
510 _twr_radio.scan_cache[_twr_radio.scan_head++] = _twr_radio.peer_id;
512 if (_twr_radio.scan_head == _TWR_RADIO_SCAN_CACHE_LENGTH)
514 _twr_radio.scan_head = 0;
520 static void _twr_radio_send_ack(
void)
524 if (_twr_radio.state == TWR_RADIO_STATE_TX_WAIT_ACK)
526 _twr_radio.ack_transmit_count = _twr_radio.transmit_count;
530 memcpy(_twr_radio.ack_tx_cache_buffer, tx_buffer,
sizeof(_twr_radio.ack_tx_cache_buffer));
532 _twr_radio.state = TWR_RADIO_STATE_TX_SEND_ACK;
534 else if (_twr_radio.state == TWR_RADIO_STATE_RX)
536 _twr_radio.state = TWR_RADIO_STATE_RX_SEND_ACK;
545 memcpy(tx_buffer, rx_buffer, 8);
547 tx_buffer[8] = TWR_RADIO_HEADER_ACK;
551 _twr_radio.transmit_count = 2;
556 static void _twr_radio_go_to_state_rx_or_sleep(
void)
558 if (_twr_radio.state == TWR_RADIO_STATE_TX)
567 if (_twr_radio.rx_timeout_sleeping > now)
569 _twr_radio.rx_timeout = _twr_radio.rx_timeout_sleeping;
575 _twr_radio.state = TWR_RADIO_STATE_RX;
581 _twr_radio.state = TWR_RADIO_STATE_SLEEP;
592 _twr_radio.state = TWR_RADIO_STATE_RX;
604 if (_twr_radio.transmit_count > 0)
606 _twr_radio.transmit_count--;
609 if (_twr_radio.state == TWR_RADIO_STATE_TX)
611 twr_tick_t timeout = _TWR_RADIO_ACK_TIMEOUT - 50 + rand() % _TWR_RADIO_ACK_TIMEOUT;
619 _twr_radio.state = TWR_RADIO_STATE_TX_WAIT_ACK;
621 _twr_radio.ack =
false;
626 if (_twr_radio.state == TWR_RADIO_STATE_RX_SEND_ACK)
628 if (_twr_radio.transmit_count > 0)
636 if (_twr_radio.state == TWR_RADIO_STATE_TX_SEND_ACK)
638 if (_twr_radio.transmit_count > 0)
648 memcpy(tx_buffer, _twr_radio.ack_tx_cache_buffer,
sizeof(_twr_radio.ack_tx_cache_buffer));
650 twr_tick_t timeout = _TWR_RADIO_ACK_TIMEOUT - 50 + rand() % _TWR_RADIO_ACK_TIMEOUT;
654 _twr_radio.transmit_count = _twr_radio.ack_transmit_count;
662 _twr_radio.state = TWR_RADIO_STATE_TX_WAIT_ACK;
668 _twr_radio_go_to_state_rx_or_sleep();
672 if (_twr_radio.state == TWR_RADIO_STATE_TX_WAIT_ACK)
674 if (_twr_radio.transmit_count > 0)
678 _twr_radio.state = TWR_RADIO_STATE_TX;
684 if (_twr_radio.event_handler)
686 _twr_radio.event_handler(TWR_RADIO_EVENT_TX_ERROR, _twr_radio.event_param);
692 _twr_radio_go_to_state_rx_or_sleep();
701 if (_twr_radio.state == TWR_RADIO_STATE_TX_WAIT_ACK)
703 if (_twr_radio.transmit_count > 0)
707 _twr_radio.state = TWR_RADIO_STATE_TX;
713 _twr_radio_go_to_state_rx_or_sleep();
721 twr_radio_id_from_buffer(buffer, &_twr_radio.peer_id);
723 message_id = (uint16_t) buffer[6];
724 message_id |= (uint16_t) buffer[7] << 8;
727 if (buffer[8] == TWR_RADIO_HEADER_ACK)
729 if (_twr_radio.state == TWR_RADIO_STATE_TX_WAIT_ACK)
733 if ((_twr_radio.peer_id == _twr_radio.my_id) && (_twr_radio.message_id == message_id) )
735 _twr_radio.transmit_count = 0;
737 _twr_radio.ack =
true;
739 if (tx_buffer[8] == TWR_RADIO_HEADER_PAIRING)
743 twr_radio_id_from_buffer(buffer + 9, &_twr_radio.peer_id);
747 _twr_radio.peer_devices[0].id = _twr_radio.peer_id;
748 _twr_radio.peer_devices[0].message_id_synced =
false;
749 _twr_radio.peer_devices_length = 1;
751 _twr_radio.save_peer_devices =
true;
754 _twr_radio.sent_subs = 0;
756 if (_twr_radio.event_handler)
758 _twr_radio.event_handler(TWR_RADIO_EVENT_PAIRED, _twr_radio.event_param);
763 else if (tx_buffer[8] == TWR_RADIO_HEADER_SUB_REG)
765 _twr_radio.sent_subs++;
767 else if ((length == 10) && (buffer[9] == _TWR_RADIO_ACK_SUB_REQUEST))
769 _twr_radio.sent_subs = 0;
772 if (_twr_radio.sleeping_mode_rx_timeout != 0)
774 _twr_radio.rx_timeout_sleeping =
twr_tick_get() + _twr_radio.sleeping_mode_rx_timeout;
777 _twr_radio_go_to_state_rx_or_sleep();
779 if (_twr_radio.event_handler)
781 _twr_radio.event_handler(TWR_RADIO_EVENT_TX_DONE, _twr_radio.event_param);
790 if (buffer[8] == TWR_RADIO_HEADER_PAIRING)
792 if (_twr_radio.pairing_mode)
796 twr_radio_peer_device_add(_twr_radio.peer_id);
800 peer = twr_radio_get_peer_device(_twr_radio.peer_id);
804 _twr_radio_send_ack();
808 twr_radio_id_to_buffer(&_twr_radio.my_id, tx_buffer + 9);
812 if ((length > 10) && (peer->message_id != message_id))
814 if (10 + (
size_t) buffer[9] + 1 < length)
816 buffer[10 + buffer[9]] = 0;
818 peer->mode = buffer[length - 1];
820 buffer[length - 1] = 0;
822 twr_radio_on_info(&_twr_radio.peer_id, (
char *)buffer + 10, (
char *)buffer + 10 + buffer[9] + 1, peer->mode);
826 peer->message_id = message_id;
828 peer->message_id_synced =
true;
834 if ((length == 15) && ((buffer[8] == TWR_RADIO_HEADER_NODE_ATTACH) || (buffer[8] == TWR_RADIO_HEADER_NODE_DETACH)))
838 twr_radio_id_from_buffer(buffer + 9, &
id);
840 if (
id == _twr_radio.my_id)
842 if (buffer[8] == TWR_RADIO_HEADER_NODE_ATTACH)
844 _twr_radio.pairing_request_to_gateway =
true;
848 else if (buffer[8] == TWR_RADIO_HEADER_NODE_DETACH)
850 _twr_radio_peer_device_remove(_twr_radio.peer_id);
852 if (_twr_radio.event_handler)
854 _twr_radio.event_handler(TWR_RADIO_EVENT_UNPAIRED, _twr_radio.event_param);
859 _twr_radio_send_ack();
864 peer = twr_radio_get_peer_device(_twr_radio.peer_id);
868 if (peer->message_id != message_id)
870 bool send_subs_request = _twr_radio.mode ==
TWR_RADIO_MODE_GATEWAY && (!peer->message_id_synced || (peer->message_id > message_id));
872 peer->message_id = message_id;
874 peer->message_id_synced =
false;
878 if ((buffer[8] >= 0x15) && (buffer[8] <= 0x1d) && (length > 14))
882 twr_radio_id_from_buffer(buffer + 9, &for_id);
884 if (for_id != _twr_radio.my_id)
894 peer->message_id_synced =
true;
899 if (peer->message_id_synced)
901 _twr_radio_send_ack();
903 if (send_subs_request)
907 tx_buffer[9] = _TWR_RADIO_ACK_SUB_REQUEST;
918 if (_twr_radio.scan && (_twr_radio.event_handler != NULL) && _twr_radio_scan_cache_push())
920 _twr_radio.event_handler(TWR_RADIO_EVENT_SCAN_FIND_DEVICE, _twr_radio.event_param);
923 if (_twr_radio.automatic_pairing)
925 twr_radio_peer_device_add(_twr_radio.peer_id);
932 static void _twr_radio_load_peer_devices(
void)
936 uint32_t *pointer = (uint32_t *)buffer;
941 _twr_radio.peer_devices_length = 0;
943 for (
int i = 0; (i < length) && (i < TWR_RADIO_MAX_DEVICES); i++)
945 address -=
sizeof(buffer);
949 pointer[2] = ~pointer[2];
950 pointer[5] = ~pointer[5];
952 if ((buffer[0] != buffer[1]) && (buffer[0] != buffer[2]))
954 if (buffer[1] == buffer[2])
956 buffer[0] = buffer[1];
958 _twr_radio.save_peer_devices =
true;
970 _twr_radio.peer_devices[_twr_radio.peer_devices_length].id = buffer[0];
971 _twr_radio.peer_devices[_twr_radio.peer_devices_length].message_id_synced =
false;
972 _twr_radio.peer_devices_length++;
977 static void _twr_radio_save_peer_devices(
void)
980 uint64_t buffer_write[3];
981 uint32_t *pointer_write = (uint32_t *)buffer_write;
982 uint64_t buffer_read[3];
984 _twr_radio.save_peer_devices =
false;
986 for (
int i = 0; i < _twr_radio.peer_devices_length; i++)
988 buffer_write[0] = _twr_radio.peer_devices[i].id;
989 buffer_write[1] = _twr_radio.peer_devices[i].id;
990 buffer_write[2] = _twr_radio.peer_devices[i].id;
992 pointer_write[2] = ~pointer_write[2];
993 pointer_write[5] = ~pointer_write[5];
995 address -=
sizeof(buffer_write);
999 if (memcmp(buffer_read, buffer_write,
sizeof(buffer_write)) != 0)
1003 _twr_radio.save_peer_devices =
true;
1014 _twr_radio.save_peer_devices =
true;
1030 if (_twr_radio.event_handler != NULL)
1032 _twr_radio.event_handler(TWR_RADIO_EVENT_INIT_DONE, _twr_radio.event_param);
1037 if (_twr_radio.event_handler != NULL)
1039 _twr_radio.event_handler(TWR_RADIO_EVENT_INIT_FAILURE, _twr_radio.event_param);
1045 if (_twr_radio.event_handler != NULL)
1047 _twr_radio.event_handler(TWR_RADIO_EVENT_INIT_FAILURE, _twr_radio.event_param);
1052 static bool _twr_radio_peer_device_add(uint64_t
id)
1054 if (_twr_radio.peer_devices_length + 1 == TWR_RADIO_MAX_DEVICES)
1056 if (_twr_radio.event_handler != NULL)
1058 _twr_radio.peer_id = id;
1059 _twr_radio.event_handler(TWR_RADIO_EVENT_ATTACH_FAILURE, _twr_radio.event_param);
1064 if (twr_radio_is_peer_device(
id))
1069 _twr_radio.peer_devices[_twr_radio.peer_devices_length].id = id;
1070 _twr_radio.peer_devices[_twr_radio.peer_devices_length].message_id_synced =
false;
1071 _twr_radio.peer_devices_length++;
1073 _twr_radio.save_peer_devices =
true;
1076 if (_twr_radio.event_handler != NULL)
1078 _twr_radio.peer_id = id;
1079 _twr_radio.event_handler(TWR_RADIO_EVENT_ATTACH, _twr_radio.event_param);
1085 static bool _twr_radio_peer_device_remove(uint64_t
id)
1087 for (
int i = 0; i < _twr_radio.peer_devices_length; i++)
1089 if (
id == _twr_radio.peer_devices[i].id)
1091 _twr_radio.peer_devices_length--;
1092 _twr_radio.peer_devices[i].id = 0;
1094 if (i != _twr_radio.peer_devices_length)
1096 memcpy(_twr_radio.peer_devices + i, _twr_radio.peer_devices + _twr_radio.peer_devices_length,
sizeof(
twr_radio_peer_t));
1099 _twr_radio.save_peer_devices =
true;
1102 if (_twr_radio.event_handler != NULL)
1104 _twr_radio.peer_id = id;
1105 _twr_radio.event_handler(TWR_RADIO_EVENT_DETACH, _twr_radio.event_param);
1117 for (
int i = 0; i < _twr_radio.peer_devices_length; i++)
1119 if (
id == _twr_radio.peer_devices[i].id)
1121 return &_twr_radio.peer_devices[i];
1128 uint8_t *twr_radio_id_to_buffer(uint64_t *
id, uint8_t *buffer)
1131 buffer[1] = *
id >> 8;
1132 buffer[2] = *
id >> 16;
1133 buffer[3] = *
id >> 24;
1134 buffer[4] = *
id >> 32;
1135 buffer[5] = *
id >> 40;
1137 return buffer + TWR_RADIO_ID_SIZE;
1140 uint8_t *twr_radio_bool_to_buffer(
bool *value, uint8_t *buffer)
1142 *buffer = value == NULL ? TWR_RADIO_NULL_BOOL : *value;
1147 uint8_t *twr_radio_int_to_buffer(
int *value, uint8_t *buffer)
1151 const int null = TWR_RADIO_NULL_INT;
1153 memcpy(buffer, &
null,
sizeof(
int));
1157 memcpy(buffer, value,
sizeof(
int));
1160 return buffer +
sizeof(int);
1163 uint8_t *twr_radio_uint16_to_buffer(uint16_t *value, uint8_t *buffer)
1167 const int null = TWR_RADIO_NULL_UINT16;
1169 memcpy(buffer, &
null,
sizeof(uint16_t));
1173 memcpy(buffer, value,
sizeof(uint16_t));
1176 return buffer +
sizeof(uint16_t);
1179 uint8_t *twr_radio_uint32_to_buffer(uint32_t *value, uint8_t *buffer)
1183 const int null = TWR_RADIO_NULL_UINT32;
1185 memcpy(buffer, &
null,
sizeof(uint32_t));
1189 memcpy(buffer, value,
sizeof(uint32_t));
1192 return buffer +
sizeof(uint32_t);
1195 uint8_t *twr_radio_float_to_buffer(
float *value, uint8_t *buffer)
1199 const float null = TWR_RADIO_NULL_FLOAT;
1201 memcpy(buffer, &
null,
sizeof(
float));
1205 memcpy(buffer, value,
sizeof(
float));
1208 return buffer +
sizeof(float);
1211 uint8_t *twr_radio_data_to_buffer(
void *data,
size_t length, uint8_t *buffer)
1215 return buffer + length;
1218 memcpy(buffer, data, length);
1220 return buffer + length;
1223 uint8_t *twr_radio_id_from_buffer(uint8_t *buffer, uint64_t *
id)
1225 *
id = (uint64_t) buffer[0];
1226 *
id |= (uint64_t) buffer[1] << 8;
1227 *
id |= (uint64_t) buffer[2] << 16;
1228 *
id |= (uint64_t) buffer[3] << 24;
1229 *
id |= (uint64_t) buffer[4] << 32;
1230 *
id |= (uint64_t) buffer[5] << 40;
1232 return buffer + TWR_RADIO_ID_SIZE;
1235 uint8_t *twr_radio_bool_from_buffer(uint8_t *buffer,
bool *value,
bool **pointer)
1237 if (*buffer == TWR_RADIO_NULL_BOOL)
1243 *value = *(
bool *) buffer;
1250 uint8_t *twr_radio_int_from_buffer(uint8_t *buffer,
int *value,
int **pointer)
1252 memcpy(value, buffer,
sizeof(
int));
1254 if (*value == TWR_RADIO_NULL_INT)
1263 return buffer +
sizeof(int);
1266 uint8_t *twr_radio_uint16_from_buffer(uint8_t *buffer, uint16_t *value, uint16_t **pointer)
1268 memcpy(value, buffer,
sizeof(uint16_t));
1270 if (*value == TWR_RADIO_NULL_UINT16)
1279 return buffer +
sizeof(uint16_t);
1282 uint8_t *twr_radio_uint32_from_buffer(uint8_t *buffer, uint32_t *value, uint32_t **pointer)
1284 memcpy(value, buffer,
sizeof(uint32_t));
1286 if (*value == TWR_RADIO_NULL_UINT32)
1295 return buffer +
sizeof(uint32_t);
1298 uint8_t *twr_radio_float_from_buffer(uint8_t *buffer,
float *value,
float **pointer)
1300 memcpy(value, buffer,
sizeof(
float));
1311 return buffer +
sizeof(float);
1314 uint8_t *twr_radio_data_from_buffer(uint8_t *buffer,
void *data,
size_t length)
1318 return buffer + length;
1321 memcpy(data, buffer, length);
1323 return buffer + length;
1329 const char *firmware;
1330 const char *version;
1341 if (param->led != NULL)
1346 static uint16_t event_count = 0;
1354 twr_radio_pairing_request(param->firmware, param->version);
1356 if (param->led != NULL)
1364 void twr_radio_init_pairing_button(
const char *firmware,
const char *version)
1370 param.firmware = firmware;
1371 param.version = version;
bool twr_atsha204_get_serial_number(twr_atsha204_t *self, void *destination, size_t size)
Get serial number.
struct twr_atsha204_t twr_atsha204_t
ATSHA204 instance.
void twr_atsha204_init(twr_atsha204_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize ATSHA204 driver.
bool twr_atsha204_read_serial_number(twr_atsha204_t *self)
Reqeust for serial number.
void twr_atsha204_set_event_handler(twr_atsha204_t *self, void(*event_handler)(twr_atsha204_t *, twr_atsha204_event_t, void *), void *event_param)
Set callback function.
@ TWR_ATSHA204_EVENT_SERIAL_NUMBER
Event serial number is available.
@ TWR_ATSHA204_EVENT_ERROR
Error event.
bool twr_eeprom_read(uint32_t address, void *buffer, size_t length)
Read buffer from EEPROM area.
size_t twr_eeprom_get_size(void)
Return size of EEPROM area.
bool twr_eeprom_write(uint32_t address, const void *buffer, size_t length)
Write buffer to EEPROM area and verify it.
@ TWR_GPIO_BUTTON
GPIO channel BUTTON.
@ TWR_GPIO_LED
GPIO channel LED.
@ TWR_GPIO_PULL_DOWN
GPIO channel has pull-down.
@ TWR_I2C_I2C0
I2C channel I2C0.
struct twr_led_t twr_led_t
LED instance.
void twr_led_init(twr_led_t *self, twr_gpio_channel_t gpio_channel, bool open_drain_output, int idle_state)
Initialize LED.
void twr_led_pulse(twr_led_t *self, twr_tick_t duration)
Turn on LED for the specified duration of time.
void twr_led_set_mode(twr_led_t *self, twr_led_mode_t mode)
Set LED mode.
@ TWR_LED_MODE_OFF
LED has steady off state.
void twr_queue_init(twr_queue_t *queue, void *buffer, size_t size)
Initialize queue.
bool twr_queue_put(twr_queue_t *queue, const void *buffer, size_t length)
Put buffer to queue.
bool twr_queue_get(twr_queue_t *queue, void *buffer, size_t *length)
Get queue to buffer.
void twr_queue_clear(twr_queue_t *queue)
Clear queue.
twr_radio_mode_t
Radio mode.
void twr_radio_node_decode(uint64_t *id, uint8_t *buffer, size_t length)
Internal decode function for twr_radio.c.
void twr_radio_init(twr_radio_mode_t mode)
Initialize radio.
void twr_radio_pub_queue_clear()
Clear the publish message queue.
bool twr_radio_pub_push_button(uint16_t *event_count)
Publish push button event count, same as use twr_radio_pub_event_count with TWR_RADIO_PUB_EVENT_PUSH_...
void twr_radio_pub_decode(uint64_t *id, uint8_t *buffer, size_t length)
Internal decode function for twr_radio.c.
twr_radio_sub_pt_t
Subscribe payload type.
@ TWR_RADIO_MODE_UNKNOWN
Unknown mode.
@ TWR_RADIO_MODE_GATEWAY
Gateway mode.
@ TWR_RADIO_MODE_NODE_SLEEPING
Node sleeping mode, suitable for battery.
size_t twr_scheduler_task_id_t
Task ID assigned by scheduler.
void twr_scheduler_plan_now(twr_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
void twr_scheduler_plan_current_now(void)
Schedule current 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.
void * twr_spirit1_get_rx_buffer(void)
Get RX buffer.
void * twr_spirit1_get_tx_buffer(void)
Get TX buffer.
void twr_spirit1_tx(void)
Enter TX state.
twr_spirit1_event_t
Callback events.
void twr_spirit1_set_rx_timeout(twr_tick_t timeout)
Set TX timeout.
size_t twr_spirit1_get_tx_length(void)
Get TX buffer length.
int twr_spirit1_get_rx_rssi(void)
Get RSSI.
void twr_spirit1_sleep(void)
Enter sleep state.
void twr_spirit1_set_tx_length(size_t length)
Set TX buffer length.
bool twr_spirit1_init(void)
Initialize.
size_t twr_spirit1_get_rx_length(void)
Get RX buffer length.
void twr_spirit1_rx(void)
Enter RX state.
void twr_spirit1_set_event_handler(void(*event_handler)(twr_spirit1_event_t, void *), void *event_param)
Set callback function.
@ TWR_SPIRIT1_EVENT_RX_TIMEOUT
Event is RX timeout.
@ TWR_SPIRIT1_EVENT_TX_DONE
Event is TX done.
@ TWR_SPIRIT1_EVENT_RX_DONE
Event is RX done.
#define TWR_TICK_INFINITY
Maximum timestamp value.
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
uint64_t twr_tick_t
Timestamp data type.