61 #include "interfaces/PJON_Interfaces.h"
62 #include "PJONDefines.h"
64 static void PJON_dummy_receiver_handler(
70 static void PJON_dummy_error_handler(
76 template<
typename Strategy>
81 uint8_t
config = PJON_TX_INFO_BIT | PJON_ACK_REQ_BIT;
82 uint8_t data[PJON_PACKET_MAX_LENGTH];
87 #if(PJON_INCLUDE_PACKET_ID)
91 #if(PJON_INCLUDE_PORT)
92 uint16_t port = PJON_BROADCAST;
104 PJON() : strategy(Strategy())
112 PJON(uint8_t device_id) : strategy(Strategy())
122 PJON(
const uint8_t *b_id, uint8_t device_id) : strategy(Strategy())
125 PJONTools::copy_id(tx.bus_id, b_id, 4);
130 #if(PJON_INCLUDE_MAC)
136 PJON(
const uint8_t *mac_addr) : strategy(Strategy())
138 PJONTools::copy_id(tx.mac, mac_addr, 6);
149 PJON_RANDOM_SEED(PJON_ANALOG_READ(_random_seed) + tx.id);
150 strategy.begin(tx.id);
151 #if(PJON_INCLUDE_PACKET_ID)
152 _packet_id_seed = PJON_RANDOM(65535) + tx.id;
158 uint16_t compose_packet(
165 info.header = (info.header == PJON_NO_HEADER) ?
config : info.header;
167 #
if(PJON_INCLUDE_PACKET_ID)
168 if(!info.id && (info.header & PJON_PACKET_ID_BIT)) {
169 info.id = PJONTools::new_packet_id(_packet_id_seed++);
172 #if(PJON_INCLUDE_PORT)
174 (port != PJON_BROADCAST) && (info.port == PJON_BROADCAST) &&
175 (info.header & PJON_PORT_BIT)
180 #if(PJON_INCLUDE_MAC)
181 if(info.header & PJON_MAC_BIT) {
182 PJONTools::copy_id(info.tx.mac, tx.mac, 6);
185 uint16_t l = PJONTools::compose_packet(
188 if(l < PJON_PACKET_MAX_LENGTH) {
191 _error(PJON_CONTENT_TOO_LONG, l, _custom_pointer);
197 uint8_t device_id()
const
209 uint16_t packet_index = PJON_FAIL
212 bool p = (packet_index != PJON_FAIL);
213 for(uint16_t i = ((p) ? packet_index : 0); i < PJON_MAX_PACKETS; i++)
214 if(packets[i].state == 0 || p) {
215 if(!(length = compose_packet(
216 info, packets[i].content, packet, length
220 packets[i].length = length;
221 packets[i].state = PJON_TO_BE_SENT;
222 packets[i].registration = PJON_MICROS();
223 packets[i].timing = timing;
226 _error(PJON_PACKETS_BUFFER_FULL, PJON_MAX_PACKETS, _custom_pointer);
232 const uint8_t *get_bus_id()
const
241 uint16_t get_packets_count(uint8_t device_id = PJON_NOT_ASSIGNED)
const
243 uint16_t packets_count = 0;
244 for(uint16_t i = 0; i < PJON_MAX_PACKETS; i++) {
245 if(packets[i].state == 0) {
249 device_id == PJON_NOT_ASSIGNED ||
250 packets[i].content[0] == device_id
255 return packets_count;
269 info.header = header;
270 PJONTools::copy_id(info.rx.bus_id, tx.bus_id, 4);
271 #if(PJON_INCLUDE_PACKET_ID)
276 #if(PJON_INCLUDE_PORT)
286 uint8_t packet_overhead(uint8_t header = PJON_NO_HEADER)
const
288 return PJONTools::packet_overhead(
289 (header == PJON_NO_HEADER) ?
config : header
297 PJONTools::parse_header(packet, packet_info);
298 packet_info.custom_pointer = _custom_pointer;
305 uint16_t length = PJON_PACKET_MAX_LENGTH;
306 uint16_t batch_length = 0;
307 uint8_t overhead = 0;
308 bool extended_length =
false, mac =
false, drop =
false;
309 for(uint16_t i = 0; i < length; i++) {
311 batch_length = strategy.receive_frame(
data + i, length - i);
312 if(batch_length == PJON_FAIL || batch_length == 0) {
319 if((
data[i] != tx.id) && (
data[i] != PJON_BROADCAST) && !_router) {
324 mac = (
data[1] & PJON_MAC_BIT);
328 ((
config & PJON_MODE_BIT) && !(
data[1] & PJON_MODE_BIT))
330 (
data[0] == PJON_BROADCAST) && (
data[1] & PJON_ACK_REQ_BIT)
332 (
data[1] & PJON_EXT_LEN_BIT) && !(
data[1] & PJON_CRC_BIT)
334 !PJON_INCLUDE_PACKET_ID && (
data[1] & PJON_PACKET_ID_BIT)
336 !PJON_INCLUDE_PORT && (
data[1] & PJON_PORT_BIT)
338 (!PJON_INCLUDE_MAC && mac) || (mac && !(
data[1] & PJON_CRC_BIT))
343 extended_length =
data[i] & PJON_EXT_LEN_BIT;
344 overhead = packet_overhead(
data[i]);
347 if((i == 2) && !extended_length) {
350 length < (uint8_t)(overhead + 1) ||
351 length >= PJON_PACKET_MAX_LENGTH
355 if(length > 15 && !(
data[1] & PJON_CRC_BIT)) {
360 if((i == 3) && extended_length) {
361 length = (
data[i - 1] << 8) | (
data[i] & 0xFF);
363 length < (uint8_t)(overhead + 1) ||
364 length >= PJON_PACKET_MAX_LENGTH
368 if(length > 15 && !(
data[1] & PJON_CRC_BIT)) {
374 ((
data[1] & PJON_MODE_BIT) && !_router && !mac) &&
375 (i > (uint8_t)(3 + extended_length)) &&
376 (i < (uint8_t)(8 + extended_length))
378 if(
config & PJON_MODE_BIT) {
379 if(tx.bus_id[i - 4 - extended_length] !=
data[i]) {
382 }
else if(
data[i] != 0) {
389 PJON_crc8::compute(
data, 3 + extended_length) !=
390 data[3 + extended_length]
395 if(
data[1] & PJON_CRC_BIT) {
397 !PJON_crc32::compare(
398 PJON_crc32::compute(
data, length - 4),
data + (length - 4)
403 }
else if(PJON_crc8::compute(
data, length - 1) !=
data[length - 1]) {
407 #if(PJON_INCLUDE_MAC)
408 if(mac && (length > 15) && !_router)
409 if(!PJONTools::id_equality(
data + (overhead - 16), tx.mac, 6))
411 PJONTools::id_equality(
412 data + (overhead - 16),
413 PJONTools::no_mac(), 6
420 if(
data[1] & PJON_ACK_REQ_BIT &&
data[0] != PJON_BROADCAST)
421 if((_mode != PJON_SIMPLEX) && !_router) {
422 strategy.send_response(PJON_ACK);
425 parse(
data, last_packet_info);
427 #if(PJON_INCLUDE_PACKET_ID)
430 (last_packet_info.header & PJON_PACKET_ID_BIT) &&
431 known_packet_id(last_packet_info)
437 #if(PJON_INCLUDE_PORT)
438 if((port != PJON_BROADCAST) && (port != last_packet_info.port)) {
444 data + (overhead - PJONTools::crc_overhead(
data[1])),
454 uint16_t receive(uint32_t duration)
456 uint32_t time = PJON_MICROS();
459 response = receive();
461 (response != PJON_ACK) &&
462 ((uint32_t)(PJON_MICROS() - time) <= duration)
469 void remove(uint16_t index)
471 if((index >= 0) && (index < PJON_MAX_PACKETS)) {
472 packets[index].attempts = 0;
473 packets[index].length = 0;
474 packets[index].registration = 0;
475 packets[index].state = 0;
483 void remove_all_packets(uint8_t device_id = 0)
485 for(uint16_t i = 0; i < PJON_MAX_PACKETS; i++) {
486 if(packets[i].state == 0) {
489 if(!device_id || packets[i].content[0] == device_id) {
497 bool reset_packet(uint16_t
id)
499 if(!packets[
id].timing) {
505 packets[id].attempts = 0;
506 packets[id].registration = PJON_MICROS();
507 packets[id].state = PJON_TO_BE_SENT;
516 uint16_t reply(
const void *payload, uint16_t length)
519 info = last_packet_info;
525 return dispatch(info, payload, length);
528 uint16_t reply_blocking(
const void *payload, uint16_t length)
531 info = last_packet_info;
537 return send_packet_blocking(info, payload, length);
546 uint8_t header = PJON_NO_HEADER,
547 uint16_t packet_id = 0,
548 uint16_t rx_port = PJON_BROADCAST
552 return dispatch(info, payload, length);
561 return dispatch(info, payload, length);
575 if(++info.hops > PJON_MAX_HOPS) {
579 uint16_t result = dispatch(info, payload, length);
580 tx = original_end_point;
586 uint16_t forward_blocking(
595 if(++info.hops > PJON_MAX_HOPS) {
599 uint16_t result = send_packet_blocking(info, payload, length);
600 tx = original_end_point;
607 uint16_t send_repeatedly(
612 uint8_t header = PJON_NO_HEADER,
613 uint16_t packet_id = 0,
614 uint16_t rx_port = PJON_BROADCAST
618 return dispatch(info, payload, length, timing);
621 uint16_t send_repeatedly(
628 return dispatch(info, payload, length, timing);
633 uint16_t send_packet(
const uint8_t *payload, uint16_t length)
638 if(_mode != PJON_SIMPLEX && !strategy.can_start()) {
641 strategy.send_frame((uint8_t *)payload, length);
643 payload[0] == PJON_BROADCAST ||
644 !(payload[1] & PJON_ACK_REQ_BIT) ||
645 _mode == PJON_SIMPLEX
649 return (strategy.receive_response() == PJON_ACK) ? PJON_ACK : PJON_FAIL;
654 uint16_t send_packet(
658 uint8_t header = PJON_NO_HEADER,
659 uint16_t packet_id = 0,
660 uint16_t rx_port = PJON_BROADCAST
664 if(!(length = compose_packet(info,
data, payload, length))) {
667 return send_packet(
data, length);
670 uint16_t send_packet(
676 if(!(length = compose_packet(info,
data, payload, length))) {
679 return send_packet(
data, length);
686 uint16_t send_packet_blocking(
690 uint32_t timeout = 3500000
693 uint16_t state = PJON_FAIL;
694 uint32_t attempts = 0;
695 uint32_t start = PJON_MICROS();
696 uint16_t old_length = length;
700 (state != PJON_ACK) && (attempts <= strategy.get_max_attempts()) &&
701 (uint32_t)(PJON_MICROS() - start) <= timeout
703 if(!(length = compose_packet(packet_info,
data, payload, old_length))) {
707 state = send_packet(
data, length);
708 if(state == PJON_ACK) {
713 if(state != PJON_FAIL) {
714 strategy.handle_collision();
716 #if(PJON_RECEIVE_WHILE_SENDING_BLOCKING)
717 if(_recursion <= 1) {
718 receive(strategy.back_off(attempts));
721 PJON_DELAY((uint32_t)(strategy.back_off(attempts) / 1000));
727 uint16_t send_packet_blocking(
731 uint8_t header = PJON_NO_HEADER,
732 uint16_t packet_id = 0,
733 uint16_t rx_port = PJON_BROADCAST,
734 uint32_t timeout = 3500000
738 return send_packet_blocking(info, payload, length, timeout);
744 void send_acknowledge()
746 strategy.send_response(PJON_ACK);
751 void set_config_bit(
bool new_state, uint8_t bit)
764 void set_acknowledge(
bool state)
766 set_config_bit(state, PJON_ACK_REQ_BIT);
773 void set_crc_32(
bool state)
775 set_config_bit(state, PJON_CRC_BIT);
782 void set_communication_mode(
bool mode)
790 void set_custom_pointer(
void *pointer)
792 _custom_pointer = pointer;
799 _mode = PJON_HALF_DUPLEX;
800 set_error(PJON_dummy_error_handler);
801 set_receiver(PJON_dummy_receiver_handler);
815 void set_error(PJON_Error e)
822 void set_id(uint8_t
id)
829 void set_bus_id(
const uint8_t *b_id)
831 PJONTools::copy_id(tx.bus_id, b_id, 4);
842 void include_sender_info(
bool state)
844 set_config_bit(state, PJON_TX_INFO_BIT);
851 void include_mac(
bool state)
853 set_config_bit(state, PJON_MAC_BIT);
856 #if(PJON_INCLUDE_MAC)
860 const uint8_t *get_mac()
const
868 void set_mac(
const uint8_t *mac)
870 PJONTools::copy_id(tx.mac, mac, 6);
879 void set_shared_network(
bool state)
881 set_config_bit(state, PJON_MODE_BIT);
888 void set_packet_auto_deletion(
bool state)
890 _auto_delete = state;
895 void set_random_seed(uint8_t seed)
904 void set_receiver(PJON_Receiver r)
913 void set_router(
bool state)
924 uint16_t packets_count = 0;
925 for(uint16_t i = 0; i < PJON_MAX_PACKETS; i++) {
926 if(packets[i].state == 0) {
932 (uint32_t)(PJON_MICROS() - packets[i].registration) >
935 strategy.back_off(packets[i].attempts)
938 if(packets[i].state != PJON_ACK)
940 send_packet(packets[i].content, packets[i].length);
945 packets[i].attempts++;
947 if(packets[i].state == PJON_ACK) {
948 packets_count -= reset_packet(i);
952 if(packets[i].state != PJON_FAIL && packets[i].state != PJON_ACK) {
953 strategy.handle_collision();
956 if(packets[i].attempts > strategy.get_max_attempts()) {
957 _error(PJON_CONNECTION_LOST, i, _custom_pointer);
958 packets_count -= reset_packet(i);
961 return packets_count;
964 #if(PJON_INCLUDE_PACKET_ID)
971 for(uint8_t i = 0; i < PJON_MAX_RECENT_PACKET_IDS; i++)
973 info.id == recent_packet_ids[i].id &&
974 info.tx.id == recent_packet_ids[i].sender_id && (
976 (info.header & PJON_MODE_BIT) &&
977 (recent_packet_ids[i].header & PJON_MODE_BIT) &&
978 PJONTools::id_equality(
979 (uint8_t *)info.tx.bus_id,
980 (uint8_t *)recent_packet_ids[i].sender_bus_id,
984 !(info.header & PJON_MODE_BIT) &&
985 !(recent_packet_ids[i].header & PJON_MODE_BIT)
991 save_packet_id(info);
999 for(uint8_t i = PJON_MAX_RECENT_PACKET_IDS - 1; i > 0; i--) {
1000 recent_packet_ids[i] = recent_packet_ids[i - 1];
1002 recent_packet_ids[0].id = info.id;
1003 recent_packet_ids[0].header = info.header;
1004 recent_packet_ids[0].sender_id = info.tx.id;
1006 recent_packet_ids[0].sender_bus_id,
1016 void set_packet_id(
bool state)
1018 set_config_bit(state, PJON_PACKET_ID_BIT);
1023 #if(PJON_INCLUDE_PORT)
1029 void include_port(uint16_t p)
1031 set_config_bit((p != 0) ? 1 : 0, PJON_PORT_BIT);
1038 bool _auto_delete =
true;
1039 void *_custom_pointer;
1042 uint16_t _packet_id_seed = 0;
1043 uint8_t _random_seed = A0;
1044 PJON_Receiver _receiver;
1045 uint8_t _recursion = 0;
1046 bool _router =
false;