From 13b972b9f46fb1a4dfb751e813dafdd4c1927eac Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 15 Apr 2020 01:00:17 +0200 Subject: [PATCH 001/323] Asynchronous acknowledge feature removed (-300B of progmem) --- src/PJON.h | 244 ++++++++++++---------------------------------- src/PJONDefines.h | 40 ++------ 2 files changed, 70 insertions(+), 214 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 2d6b69b687..def978187c 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -86,14 +86,13 @@ class PJON { uint16_t port = PJON_BROADCAST; uint8_t random_seed = A0; - #if(PJON_INCLUDE_ASYNC_ACK || PJON_INCLUDE_PACKET_ID) + #if(PJON_INCLUDE_PACKET_ID) PJON_Packet_Record recent_packet_ids[PJON_MAX_RECENT_PACKET_IDS]; #endif /* PJON initialization with no parameters: State: Local (bus_id: 0.0.0.0) Synchronous acknowledge: true - Asynchronous acknowledge: false device id: PJON_NOT_ASSIGNED (255) Mode: PJON_HALF_DUPLEX Sender info: true (Sender info are included in the packet) @@ -128,7 +127,7 @@ class PJON { void begin() { PJON_RANDOM_SEED(PJON_ANALOG_READ(random_seed) + _device_id); strategy.begin(_device_id); - #if(PJON_INCLUDE_ASYNC_ACK || PJON_INCLUDE_PACKET_ID) + #if(PJON_INCLUDE_PACKET_ID) _packet_id_seed = PJON_RANDOM(65535) + _device_id; #endif }; @@ -205,32 +204,6 @@ class PJON { return PJON_FAIL; }; - /* Check if a packet id is already dispatched in buffer: */ - - bool dispatched(PJON_Packet_Info info) { - PJON_Packet_Info actual_info; - for(uint16_t i = 0; i < PJON_MAX_PACKETS; i++) { - parse((uint8_t *)packets[i].content, actual_info); - if( - packets[i].state && packets[i].state != PJON_ACK && - (actual_info.header & PJON_ACK_MODE_BIT) && - (actual_info.header & PJON_TX_INFO_BIT) - ) - if( - actual_info.id == info.id && - info.sender_id == actual_info.receiver_id && - ( - !(info.header & PJON_MODE_BIT) ? true : - PJONTools::bus_id_equality( - info.receiver_bus_id, - actual_info.receiver_bus_id - ) - ) - ) return true; - } - return false; - }; - /* Get count of packets: Don't pass any parameter to count all dispatched packets Pass a device id to count all it's related packets */ @@ -269,7 +242,6 @@ class PJON { uint16_t batch_length = 0; uint8_t overhead = 0; bool extended_length = false; - bool async_ack = false; for(uint16_t i = 0; i < length; i++) { if(!batch_length) { batch_length = strategy.receive_frame(data + i, length - i); @@ -288,31 +260,21 @@ class PJON { !_router && ((config & PJON_MODE_BIT) && !(data[1] & PJON_MODE_BIT)) ) || ( - data[0] == PJON_BROADCAST && - ((data[1] & PJON_ACK_MODE_BIT) || (data[1] & PJON_ACK_REQ_BIT)) - ) || ( - (data[1] & PJON_ACK_MODE_BIT) && !(data[1] & PJON_TX_INFO_BIT) + (data[0] == PJON_BROADCAST) && (data[1] & PJON_ACK_REQ_BIT) ) || ( (data[1] & PJON_EXT_LEN_BIT) && !(data[1] & PJON_CRC_BIT) - ) || ( - !PJON_INCLUDE_ASYNC_ACK && (data[1] & PJON_ACK_MODE_BIT) ) || ( !PJON_INCLUDE_PACKET_ID && (data[1] & PJON_PACKET_ID_BIT) ) ) return PJON_BUSY; extended_length = data[i] & PJON_EXT_LEN_BIT; overhead = packet_overhead(data[i]); - async_ack = ( - PJON_INCLUDE_ASYNC_ACK && - (data[1] & PJON_ACK_MODE_BIT) && - (data[1] & PJON_TX_INFO_BIT) - ); } if((i == 2) && !extended_length) { length = data[i]; if( - length < (uint8_t)(overhead + !async_ack) || + length < (uint8_t)(overhead + 1) || length >= PJON_PACKET_MAX_LENGTH ) return PJON_BUSY; if(length > 15 && !(data[1] & PJON_CRC_BIT)) return PJON_BUSY; @@ -321,7 +283,7 @@ class PJON { if((i == 3) && extended_length) { length = (data[i - 1] << 8) | (data[i] & 0xFF); if( - length < (uint8_t)(overhead + !async_ack) || + length < (uint8_t)(overhead + 1) || length >= PJON_PACKET_MAX_LENGTH ) return PJON_BUSY; if(length > 15 && !(data[1] & PJON_CRC_BIT)) return PJON_BUSY; @@ -358,34 +320,12 @@ class PJON { parse(data, last_packet_info); - #if(PJON_INCLUDE_ASYNC_ACK || PJON_INCLUDE_PACKET_ID) - bool filter = - (last_packet_info.header & PJON_PACKET_ID_BIT) ? true : false; - /* If a packet requesting asynchronous acknowledgement is received - send the acknowledgement packet back to the packet's transmitter */ - if(async_ack && !_router) { - if(_auto_delete && length == overhead) - if(handle_asynchronous_acknowledgment(last_packet_info)) - return PJON_ACK; - if(length > overhead) { - if(!dispatched(last_packet_info)) { - dispatch( - last_packet_info.sender_id, - (uint8_t *)last_packet_info.sender_bus_id, - NULL, - 0, - 0, - config | PJON_ACK_MODE_BIT | PJON_TX_INFO_BIT, - last_packet_info.id, - last_packet_info.port - ); - update(); - } - filter = true; - } - } - if(filter && known_packet_id(last_packet_info) && !_router) - return PJON_ACK; + #if(PJON_INCLUDE_PACKET_ID) + if( + !_router && + (last_packet_info.header & PJON_PACKET_ID_BIT) && + known_packet_id(last_packet_info) + ) return PJON_ACK; #endif if((port != PJON_BROADCAST) && (port != last_packet_info.port)) @@ -424,46 +364,6 @@ class PJON { } }; - /* Remove a packet from buffer passing its packet id as reference: */ - - bool handle_asynchronous_acknowledgment(PJON_Packet_Info packet_info) { - PJON_Packet_Info actual_info; - for(uint16_t i = 0; i < PJON_MAX_PACKETS; i++) { - parse((uint8_t *)packets[i].content, actual_info); - if(actual_info.id == packet_info.id) - if(actual_info.receiver_id == packet_info.sender_id && ( - (!(actual_info.header & PJON_MODE_BIT) && - !(packet_info.header & PJON_MODE_BIT)) ? true : - PJONTools::bus_id_equality( - actual_info.receiver_bus_id, - packet_info.sender_bus_id - ) - )) { - if(packets[i].timing) { - uint8_t offset = packet_overhead(actual_info.header); - uint8_t crc_offset = - PJONTools::crc_overhead(actual_info.header); - dispatch( - actual_info.receiver_id, - (uint8_t *)actual_info.receiver_bus_id, - packets[i].content + (offset - crc_offset), - packets[i].length - offset, - packets[i].timing, - actual_info.header, - PJONTools::new_packet_id(_packet_id_seed++), - actual_info.port, - i - ); - packets[i].attempts = 0; - return true; - } - remove(i); - return true; - } - } - return false; - }; - /* Remove all packets from the buffer: Don't pass any parameter to delete all packets Pass a device id to delete all it's related packets */ @@ -475,6 +375,22 @@ class PJON { } }; + /* Reset a packet sending present in the buffer: */ + + bool reset_packet(uint16_t id) { + if(!packets[id].timing) { + if(_auto_delete) { + remove(id); + return true; + } + } else { + packets[id].attempts = 0; + packets[id].registration = PJON_MICROS(); + packets[id].state = PJON_TO_BE_SENT; + } + return false; + }; + /* Schedule a packet sending to the sender of the last packet received. This function is typically called within the receive callback to deliver a response to a request. */ @@ -737,14 +653,6 @@ class PJON { set_config_bit(state, PJON_ACK_REQ_BIT); }; - /* Configure asynchronous acknowledge presence: - TRUE: Send back asynchronous acknowledge packet - FALSE: Avoid acknowledge packet transmission */ - - void set_asynchronous_acknowledge(bool state) { - set_config_bit(state, PJON_ACK_MODE_BIT); - }; - /* Configure CRC selected for packet checking: TRUE: CRC32, FALSE: CRC8 */ @@ -875,9 +783,6 @@ class PJON { for(uint16_t i = 0; i < PJON_MAX_PACKETS; i++) { if(packets[i].state == 0) continue; packets_count++; - bool async_ack = (packets[i].content[1] & PJON_ACK_MODE_BIT) && - (packets[i].content[1] & PJON_TX_INFO_BIT); - bool sync_ack = (packets[i].content[1] & PJON_ACK_REQ_BIT); if( (uint32_t)(PJON_MICROS() - packets[i].registration) > @@ -886,34 +791,16 @@ class PJON { strategy.back_off(packets[i].attempts) ) ) { - if(!(sync_ack && async_ack && packets[i].state == PJON_ACK)) - packets[i].state = // Avoid resending sync-acked async ack packets + if(packets[i].state != PJON_ACK) + packets[i].state = send_packet(packets[i].content, packets[i].length); } else continue; packets[i].attempts++; if(packets[i].state == PJON_ACK) { - if(!packets[i].timing) { - if( - _auto_delete && ( - ( - packets[i].length == packet_overhead(packets[i].content[1]) - && async_ack - ) || !(packets[i].content[1] & PJON_ACK_MODE_BIT) - ) - ) { - remove(i); - packets_count--; - } - } else { - if(!async_ack) { - packets[i].attempts = 0; - packets[i].registration = PJON_MICROS(); - packets[i].state = PJON_TO_BE_SENT; - } - } - if(!async_ack) continue; + packets_count -= reset_packet(i); + continue; } if(packets[i].state != PJON_FAIL && packets[i].state != PJON_ACK) @@ -921,64 +808,55 @@ class PJON { if(packets[i].attempts > strategy.get_max_attempts()) { _error(PJON_CONNECTION_LOST, i, _custom_pointer); - if(!packets[i].timing) { - if(_auto_delete) { - remove(i); - packets_count--; - } - } else { - packets[i].attempts = 0; - packets[i].registration = PJON_MICROS(); - packets[i].state = PJON_TO_BE_SENT; - } + packets_count -= reset_packet(i); } } return packets_count; }; + #if(PJON_INCLUDE_PACKET_ID) + /* Check if the packet id and its transmitter info are already present in buffer of recently received packets, if not add it to the buffer. */ bool known_packet_id(PJON_Packet_Info info) { - #if(PJON_INCLUDE_ASYNC_ACK || PJON_INCLUDE_PACKET_ID) - for(uint8_t i = 0; i < PJON_MAX_RECENT_PACKET_IDS; i++) - if( - info.id == recent_packet_ids[i].id && - info.sender_id == recent_packet_ids[i].sender_id && ( - ( - (info.header & PJON_MODE_BIT) && - (recent_packet_ids[i].header & PJON_MODE_BIT) && - PJONTools::bus_id_equality( - (uint8_t *)info.sender_bus_id, - (uint8_t *)recent_packet_ids[i].sender_bus_id - ) - ) || ( - !(info.header & PJON_MODE_BIT) && - !(recent_packet_ids[i].header & PJON_MODE_BIT) + for(uint8_t i = 0; i < PJON_MAX_RECENT_PACKET_IDS; i++) + if( + info.id == recent_packet_ids[i].id && + info.sender_id == recent_packet_ids[i].sender_id && ( + ( + (info.header & PJON_MODE_BIT) && + (recent_packet_ids[i].header & PJON_MODE_BIT) && + PJONTools::bus_id_equality( + (uint8_t *)info.sender_bus_id, + (uint8_t *)recent_packet_ids[i].sender_bus_id ) + ) || ( + !(info.header & PJON_MODE_BIT) && + !(recent_packet_ids[i].header & PJON_MODE_BIT) ) - ) return true; - save_packet_id(info); - #endif + ) + ) return true; + save_packet_id(info); return false; }; /* Save packet id in the buffer: */ void save_packet_id(PJON_Packet_Info info) { - #if(PJON_INCLUDE_ASYNC_ACK || PJON_INCLUDE_PACKET_ID) - for(uint8_t i = PJON_MAX_RECENT_PACKET_IDS - 1; i > 0; i--) - recent_packet_ids[i] = recent_packet_ids[i - 1]; - recent_packet_ids[0].id = info.id; - recent_packet_ids[0].header = info.header; - recent_packet_ids[0].sender_id = info.sender_id; - PJONTools::copy_bus_id( - recent_packet_ids[0].sender_bus_id, - info.sender_bus_id - ); - #endif + for(uint8_t i = PJON_MAX_RECENT_PACKET_IDS - 1; i > 0; i--) + recent_packet_ids[i] = recent_packet_ids[i - 1]; + recent_packet_ids[0].id = info.id; + recent_packet_ids[0].header = info.header; + recent_packet_ids[0].sender_id = info.sender_id; + PJONTools::copy_bus_id( + recent_packet_ids[0].sender_bus_id, + info.sender_bus_id + ); }; + #endif + private: bool _auto_delete = true; void *_custom_pointer; diff --git a/src/PJONDefines.h b/src/PJONDefines.h index a0efeb6f5a..04a1920fbb 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -98,9 +98,9 @@ limitations under the License. */ /* 0 - Synchronous acknowledgement disabled 1 - Synchronous acknowledgement enabled */ #define PJON_ACK_REQ_BIT 0B00000100 -/* 0 - Asynchronous acknowledgement disabled - 1 - Asynchronous acknowledgement enabled */ -#define PJON_ACK_MODE_BIT 0B00001000 + +// RESERVED FOR MAC FEATURE 0B00001000 + /* 0 - No port id contained 1 - Port id contained (2 bytes integer) */ #define PJON_PORT_BIT 0B00010000 @@ -136,12 +136,6 @@ limitations under the License. */ #define PJON_PACKET_MAX_LENGTH 50 #endif -/* If set to false async ack feature is not included saving memory - (it saves around 1kB of memory) */ -#ifndef PJON_INCLUDE_ASYNC_ACK - #define PJON_INCLUDE_ASYNC_ACK false -#endif - /* If set to false packet id feature is not included saving memory (it saves around 1kB of memory) */ #ifndef PJON_INCLUDE_PACKET_ID @@ -219,14 +213,7 @@ struct PJONTools { ) + (header & PJON_EXT_LEN_BIT ? 2 : 1) + (header & PJON_CRC_BIT ? 4 : 1) + (header & PJON_PORT_BIT ? 2 : 0) - + ( - ( - ( - (header & PJON_ACK_MODE_BIT) && - (header & PJON_TX_INFO_BIT) - ) || (header & PJON_PACKET_ID_BIT) - ) ? 2 : 0 - ) + + (header & PJON_PACKET_ID_BIT ? 2 : 0) + 2 // header + header's CRC ); }; @@ -282,8 +269,7 @@ struct PJONTools { (destination_port == PJON_BROADCAST) && (source_port == PJON_BROADCAST) ) header &= ~PJON_PORT_BIT; - if(receiver_id == PJON_BROADCAST) - header &= ~(PJON_ACK_REQ_BIT | PJON_ACK_MODE_BIT); + if(receiver_id == PJON_BROADCAST) header &= ~(PJON_ACK_REQ_BIT); uint16_t new_length = length + packet_overhead(header); bool extended_length = header & PJON_EXT_LEN_BIT; if(new_length > 15 && !(header & PJON_CRC_BIT)) { @@ -319,12 +305,8 @@ struct PJONTools { (void)receiver_bus_id; #endif if(header & PJON_TX_INFO_BIT) destination[index++] = sender_id; - #if(PJON_INCLUDE_ASYNC_ACK || PJON_INCLUDE_PACKET_ID) - if( - (header & PJON_PACKET_ID_BIT) || ( - (header & PJON_ACK_MODE_BIT) && (header & PJON_TX_INFO_BIT) - ) - ) { + #if(PJON_INCLUDE_PACKET_ID) + if(header & PJON_PACKET_ID_BIT) { destination[index++] = (uint8_t)(packet_id >> 8); destination[index++] = (uint8_t)packet_id; } @@ -379,12 +361,8 @@ struct PJONTools { if(info.header & PJON_TX_INFO_BIT) info.sender_id = packet[index++]; else info.sender_id = 0; - #if(PJON_INCLUDE_ASYNC_ACK || PJON_INCLUDE_PACKET_ID) - if( - (info.header & PJON_PACKET_ID_BIT) || ( - (info.header & PJON_ACK_MODE_BIT) && (info.header & PJON_TX_INFO_BIT) - ) - ) { + #if(PJON_INCLUDE_PACKET_ID) + if(info.header & PJON_PACKET_ID_BIT) { info.id = (packet[index] << 8) | (packet[index + 1] & 0xFF); index += 2; } From c142f673e5b25575edfbd5ae4fade98907c9eb72 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 15 Apr 2020 01:45:39 +0200 Subject: [PATCH 002/323] async ack spec, examples and keywords removed --- documentation/configuration.md | 16 ---- .../HC-12-AsyncAck/Receiver/Receiver.ino | 40 ---------- .../Transmitter/Transmitter.ino | 51 ------------- .../RS485-AsyncAck/Receiver/Receiver.ino | 44 ----------- .../Transmitter/Transmitter.ino | 47 ------------ .../HalfDuplex/Receiver/Receiver.ino | 5 -- .../HalfDuplex/Transmitter/Transmitter.ino | 9 --- .../AsyncAck/Receiver/Receiver.ino | 35 --------- .../AsyncAck/Transmitter/Transmitter.ino | 31 -------- .../RecursiveAcknowledge/Device1/Device1.ino | 39 ---------- .../RecursiveAcknowledge/Device2/Device2.ino | 45 ----------- .../RecursiveAcknowledge/README.md | 22 ------ .../RecursiveAcknowledge/Router/Router.ino | 76 ------------------- .../AsyncAck/Receiver/Receiver.ino | 35 --------- .../AsyncAck/Transmitter/Transmitter.ino | 42 ---------- keywords.txt | 3 - specification/PJON-network-services-list.md | 2 +- ...protocol-acknowledge-specification-v2.0.md | 38 ++++++++++ .../PJON-protocol-specification-v3.2.md | 9 +-- ...FSP-frame-separation-specification-v1.0.md | 2 +- ...protocol-acknowledge-specification-v1.0.md | 0 .../PJON-protocol-specification-v1.0.md | 2 +- src/PJONLocal.h | 6 +- .../specification/PJDLS-specification-v2.0.md | 2 +- .../specification/PJDLR-specification-v3.0.md | 2 +- .../specification/PJDL-specification-v4.1.md | 2 +- src/strategies/ThroughSerial/README.md | 4 +- .../specification/TSDL-specification-v2.1.md | 2 +- src/strategies/ThroughSerialAsync/README.md | 4 +- .../specification/TSDL-specification-v2.1.md | 2 +- 30 files changed, 57 insertions(+), 560 deletions(-) delete mode 100644 examples/ARDUINO/Local/ThroughSerial/HC-12-AsyncAck/Receiver/Receiver.ino delete mode 100644 examples/ARDUINO/Local/ThroughSerial/HC-12-AsyncAck/Transmitter/Transmitter.ino delete mode 100644 examples/ARDUINO/Local/ThroughSerial/RS485-AsyncAck/Receiver/Receiver.ino delete mode 100644 examples/ARDUINO/Local/ThroughSerial/RS485-AsyncAck/Transmitter/Transmitter.ino delete mode 100644 examples/ARDUINO/Network/SoftwareBitBang/AsyncAck/Receiver/Receiver.ino delete mode 100644 examples/ARDUINO/Network/SoftwareBitBang/AsyncAck/Transmitter/Transmitter.ino delete mode 100644 examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/Device1/Device1.ino delete mode 100644 examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/Device2/Device2.ino delete mode 100644 examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/README.md delete mode 100644 examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/Router/Router.ino delete mode 100644 examples/ARDUINO/Network/ThroughSerial/AsyncAck/Receiver/Receiver.ino delete mode 100644 examples/ARDUINO/Network/ThroughSerial/AsyncAck/Transmitter/Transmitter.ino create mode 100644 specification/PJON-protocol-acknowledge-specification-v2.0.md rename specification/{ => obsolete}/PJON-protocol-acknowledge-specification-v1.0.md (100%) diff --git a/documentation/configuration.md b/documentation/configuration.md index d64233da6c..bb7586a5f3 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -121,22 +121,6 @@ The [synchronous acknowledgement](/specification/PJON-protocol-acknowledge-speci bus.set_synchronous_acknowledge(false); ``` -If the [asynchronous acknowledgement](/specification/PJON-protocol-acknowledge-specification-v1.0.md#asynchronous-acknowledge) feature is required you need to define the `PJON_INCLUDE_ASYNC_ACK` as following. The use of a constant has been chosen to save more than 1kB on sketches where this feature is not used (the packet id is used by the asynchronous acknowledgement process, so if necessary, play with that responsibly): -```cpp -#define PJON_INCLUDE_ASYNC_ACK true -// Max number of old packet ids stored to avoid duplication -#define PJON_MAX_RECENT_PACKET_IDS 10 // by default 10 -// If packet duplication occurs, higher PJON_MAX_RECENT_PACKET_IDS -#include -``` -Use `set_asynchronous_acknowledge` to enable the asynchronous acknowledgement: -```cpp - // Enable async ack - bus.set_asynchronous_acknowledge(true); -``` -See the [AsyncAck](/examples/ARDUINO/Network/SoftwareBitBang/AsyncAck) example to see more in detail how the asynchronous acknowledgement can be used. - - ### Packet identification If packet duplication avoidance is required it is possible to add a 2 bytes [packet identifier](/specification/PJON-protocol-specification-v3.2.md#packet-identification) to guarantee uniqueness. define the `PJON_INCLUDE_PACKET_ID` as following. The use of a constant has been chosen to save more than 1kB on sketches where this feature is not used: diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-AsyncAck/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-AsyncAck/Receiver/Receiver.ino deleted file mode 100644 index b70c86bed5..0000000000 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-AsyncAck/Receiver/Receiver.ino +++ /dev/null @@ -1,40 +0,0 @@ - -// Include asynchronous acknowledgement feature -#define PJON_INCLUDE_ASYNC_ACK true - -#include -#include - -SoftwareSerial HC12(2, 3); - -uint8_t bus_id[] = {0, 0, 0, 1}; -// bus(selected device id) -PJON bus(bus_id, 44); - -void setup() { - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); // Initialize LED 13 to be off - - // Set HC12 baudrate (you must use the one configured in HC12, default 9600) - HC12.begin(9600); - - bus.strategy.set_serial(&HC12); - bus.begin(); - bus.set_receiver(receiver_function); -}; - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ - if(payload[0] == 'B') { - digitalWrite(LED_BUILTIN, HIGH); - delay(3); - digitalWrite(LED_BUILTIN, LOW); - delay(3); - } -} - -void loop() { - bus.update(); - bus.receive(1000); -}; diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-AsyncAck/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-AsyncAck/Transmitter/Transmitter.ino deleted file mode 100644 index 000902353b..0000000000 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-AsyncAck/Transmitter/Transmitter.ino +++ /dev/null @@ -1,51 +0,0 @@ - -// Include asynchronous acknowledgement feature -#define PJON_INCLUDE_ASYNC_ACK true - -#include -#include - -SoftwareSerial HC12(2, 3); - -uint8_t bus_id[] = {0, 0, 0, 1}; -// bus(selected device id) -PJON bus(bus_id, 45); - -int latency = 1000; -/* 1 millisecond maximum expected latency having modules in close proximity - higher latency if communication fails when modules are physically distant */ - -void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { - if(code == PJON_CONNECTION_LOST) - digitalWrite(LED_BUILTIN, HIGH); // Light up LED 13 if a packet transmission failed -} - -void setup() { - // Initialize LED 13 to be off - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); - - // Set HC12 baudrate (you must use the one configured in HC12, default 9600) - HC12.begin(9600); - - bus.strategy.set_serial(&HC12); - - /* Set configuration to send packet disabling synchronous and - enabling asynchronous acknowledgement response */ - bus.set_synchronous_acknowledge(false); - bus.set_asynchronous_acknowledge(true); - - bus.set_error(error_handler); - bus.begin(); - - // Send B to device 44 every 1.5s - bus.send_repeatedly(44, "B", 1, 1500000); -}; - -void loop() { - bus.update(); - bus.receive(TS_TIME_IN + latency); - /* Receive for, at least, the minumum timeframe necessary - for receiver to respond back an acknowledgement packet - (Avoid unnecessary retransmissions) */ -}; diff --git a/examples/ARDUINO/Local/ThroughSerial/RS485-AsyncAck/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/RS485-AsyncAck/Receiver/Receiver.ino deleted file mode 100644 index eecab8d3dc..0000000000 --- a/examples/ARDUINO/Local/ThroughSerial/RS485-AsyncAck/Receiver/Receiver.ino +++ /dev/null @@ -1,44 +0,0 @@ - -/* PJON MAX485 serial modules RS485 communication example */ - -// Include async ack defining PJON_INCLUDE_ASYNC_ACK before including PJON.h -#define PJON_INCLUDE_ASYNC_ACK true -// Synchronous acknowledgement is not used, set TS_RESPONSE_TIME_OUT to 0 -#define TS_RESPONSE_TIME_OUT 0 - -#include - -// bus(selected device id) -PJON bus(44); - -void setup() { - // Initialize LED 13 to be off - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); - // Initialize Serial instance used for PJON communication - Serial.begin(9600); - bus.strategy.set_serial(&Serial); - // Avoid default sync ack - bus.set_synchronous_acknowledge(false); - // Set enable pins - bus.strategy.set_RS485_rxe_pin(3); - bus.strategy.set_RS485_txe_pin(2); - bus.begin(); - bus.set_receiver(receiver_function); -}; - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ - if(payload[0] == 'B') { - digitalWrite(LED_BUILTIN, HIGH); - delay(3); - digitalWrite(LED_BUILTIN, LOW); - delay(3); - } -} - -void loop() { - bus.update(); - bus.receive(); -}; diff --git a/examples/ARDUINO/Local/ThroughSerial/RS485-AsyncAck/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/RS485-AsyncAck/Transmitter/Transmitter.ino deleted file mode 100644 index b01cf68e29..0000000000 --- a/examples/ARDUINO/Local/ThroughSerial/RS485-AsyncAck/Transmitter/Transmitter.ino +++ /dev/null @@ -1,47 +0,0 @@ - -/* PJON MAX485 serial modules RS485 communication example */ - -// Include async ack defining PJON_INCLUDE_ASYNC_ACK before including PJON.h -#define PJON_INCLUDE_ASYNC_ACK true -// Synchronous acknowledgement is not used, set TS_RESPONSE_TIME_OUT to 0 -#define TS_RESPONSE_TIME_OUT 0 - -#include - -// bus(selected device id) -PJON bus(45); - -// 5 milliseconds maximum expected latency, higher if necessary -uint32_t latency = 5000; - -void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { - if(code == PJON_CONNECTION_LOST) - digitalWrite(LED_BUILTIN, HIGH); // Light up LED 13 if a packet transmission failed -}; - -void setup() { - // Initialize LED 13 to be off - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); - // Initialize Serial instance used for PJON communication - Serial.begin(9600); - bus.strategy.set_serial(&Serial); - // Set asynchronous acknowledgement response, avoid sync - bus.set_synchronous_acknowledge(false); - bus.set_asynchronous_acknowledge(true); - // Set enable pins - bus.strategy.set_RS485_rxe_pin(3); - bus.strategy.set_RS485_txe_pin(2); - bus.set_error(error_handler); - bus.begin(); - // Send B to device 44 every 1.5s - bus.send_repeatedly(44, "B", 1, 1500000); -}; - -void loop() { - bus.update(); - bus.receive(TS_TIME_IN + latency); - /* Receive for, at least, the minumum timeframe necessary - for receiver to respond back an acknowledgement packet - (Avoid unnecessary retransmissions) */ -}; diff --git a/examples/ARDUINO/Network/OverSampling/HalfDuplex/Receiver/Receiver.ino b/examples/ARDUINO/Network/OverSampling/HalfDuplex/Receiver/Receiver.ino index 2bbff67603..fa06c763a1 100644 --- a/examples/ARDUINO/Network/OverSampling/HalfDuplex/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/OverSampling/HalfDuplex/Receiver/Receiver.ino @@ -1,7 +1,4 @@ -/* Include Async ACK code setting PJON_INCLUDE_ASYNC_ACK as true before including PJON.h */ -#define PJON_INCLUDE_ASYNC_ACK true - #include uint8_t bus_id[] = {0, 0, 0, 1}; @@ -27,9 +24,7 @@ void setup() { /* When using more than one pin always use pins connected to a different port group to avoid cross-talk. */ bus.strategy.set_pins(7, 12); - bus.set_receiver(receiver_function); - bus.set_synchronous_acknowledge(false); bus.begin(); }; diff --git a/examples/ARDUINO/Network/OverSampling/HalfDuplex/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/OverSampling/HalfDuplex/Transmitter/Transmitter.ino index 8b25e61d57..76d7708fa7 100644 --- a/examples/ARDUINO/Network/OverSampling/HalfDuplex/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/OverSampling/HalfDuplex/Transmitter/Transmitter.ino @@ -1,7 +1,4 @@ -/* Include Async ACK code setting PJON_INCLUDE_ASYNC_ACK as true before including PJON.h */ -#define PJON_INCLUDE_ASYNC_ACK true - #include uint16_t packet; uint8_t bus_id[] = {0, 0, 0, 1}; @@ -37,12 +34,6 @@ void setup() { /* When using more than one pin always use pins connected to a different port group to avoid cross-talk. */ bus.strategy.set_pins(7, 12); - - /* A packet containing the id of every packet received will be sent back - by this device to the packet's sender to acknowledge packet reception. - (With this setup you can avoid sending packet duplicates) */ - bus.set_asynchronous_acknowledge(true); - bus.set_synchronous_acknowledge(false); bus.set_error(error_handler); bus.begin(); diff --git a/examples/ARDUINO/Network/SoftwareBitBang/AsyncAck/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/AsyncAck/Receiver/Receiver.ino deleted file mode 100644 index 7e4148f3cb..0000000000 --- a/examples/ARDUINO/Network/SoftwareBitBang/AsyncAck/Receiver/Receiver.ino +++ /dev/null @@ -1,35 +0,0 @@ - -/* Include Async ACK code setting PJON_INCLUDE_ASYNC_ACK as true before including PJON.h */ -#define PJON_INCLUDE_ASYNC_ACK true - -#include - -uint8_t bus_id[] = {0, 0, 0, 1}; - -// bus(selected device id) -PJON bus(bus_id, 44); - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ - if(payload[0] == 'B') { - digitalWrite(LED_BUILTIN, HIGH); - delay(3); - digitalWrite(LED_BUILTIN, LOW); - delay(3); - } -}; - -void setup() { - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); // Initialize LED 13 to be off - - bus.strategy.set_pin(12); - bus.begin(); - bus.set_receiver(receiver_function); -}; - -void loop() { - bus.update(); - bus.receive(1000); -}; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/AsyncAck/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/AsyncAck/Transmitter/Transmitter.ino deleted file mode 100644 index 6e3b6121d1..0000000000 --- a/examples/ARDUINO/Network/SoftwareBitBang/AsyncAck/Transmitter/Transmitter.ino +++ /dev/null @@ -1,31 +0,0 @@ - -/* Include Async ACK code setting PJON_INCLUDE_ASYNC_ACK as true before including PJON.h */ -#define PJON_INCLUDE_ASYNC_ACK true - -#include - -uint8_t bus_id[] = {0, 0, 0, 1}; - -// 1 milliseconds maximum expected latency, higher if necessary -uint32_t latency = 1000; - -// bus(selected device id) -PJON bus(bus_id, 45); - -void setup() { - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); // Initialize LED 13 to be off - - bus.strategy.set_pin(12); - /* A packet containing the id of every packet received will be sent back - by this device to the packet's sender to acknowledge packet reception. */ - bus.set_asynchronous_acknowledge(true); - bus.begin(); - - bus.send_repeatedly(44, "B", 1, 1000000); // Send B to device 44 every second -} - -void loop() { - bus.update(); - bus.receive(latency); -}; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/Device1/Device1.ino b/examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/Device1/Device1.ino deleted file mode 100644 index b969fd4bb3..0000000000 --- a/examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/Device1/Device1.ino +++ /dev/null @@ -1,39 +0,0 @@ - -#define PJON_INCLUDE_ASYNC_ACK true -#include - -// Maximum expected latency or response time, higher if necessary -uint32_t latency = 6000; - -// Bus id definition -uint8_t bus_id_A[] = {0, 0, 0, 1}; -uint8_t bus_id_B[] = {0, 0, 0, 2}; - -// bus(selected device id) -PJON bus(bus_id_A, 1); - -void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { - if(code == PJON_CONNECTION_LOST) - digitalWrite(LED_BUILTIN, HIGH); - // Light up LED 13 if a packet transmission failed -} - -void setup() { - // Initialize LED 13 to be off - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); - - bus.set_error(error_handler); - bus.set_synchronous_acknowledge(true); - bus.set_asynchronous_acknowledge(true); - bus.strategy.set_pin(12); - bus.begin(); - - // Send B to device 44 every 1.5s - bus.send_repeatedly(2, bus_id_B, "B", 1, 1000000); -} - -void loop() { - bus.update(); - bus.receive(latency); -}; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/Device2/Device2.ino b/examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/Device2/Device2.ino deleted file mode 100644 index 30d9ea9b10..0000000000 --- a/examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/Device2/Device2.ino +++ /dev/null @@ -1,45 +0,0 @@ - -#define PJON_INCLUDE_ASYNC_ACK true -#include - -// Maximum expected latency or response time, higher if necessary -uint32_t latency = 6000; - -// Bus id definition -uint8_t bus_id_A[] = {0, 0, 0, 1}; -uint8_t bus_id_B[] = {0, 0, 0, 2}; - -// bus(selected device id) -PJON bus(bus_id_B, 2); - -void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { - if(code == PJON_CONNECTION_LOST) - digitalWrite(LED_BUILTIN, HIGH); - // Light up LED 13 if a packet transmission failed -} - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - if(payload[0] == 'B') { - digitalWrite(LED_BUILTIN, HIGH); - delay(30); - digitalWrite(LED_BUILTIN, LOW); - } -} - -void setup() { - // Initialize LED 13 to be off - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); - - bus.set_error(error_handler); - bus.set_receiver(receiver_function); - bus.set_synchronous_acknowledge(true); - bus.set_asynchronous_acknowledge(true); - bus.strategy.set_pin(12); - bus.begin(); -} - -void loop() { - bus.update(); - bus.receive(latency); -}; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/README.md b/examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/README.md deleted file mode 100644 index 73e11aa6ab..0000000000 --- a/examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/README.md +++ /dev/null @@ -1,22 +0,0 @@ -## RecursiveAcknowledge example -This example implements the [recursive acknowledgement ](/specification/PJON-protocol-acknowledge-specification-v1.0.md#pjon-recursive-acknowledgement-pattern) pattern. The setup is made by 2 buses: -- `0.0.0.1` that connects device `1` to the router -- `0.0.0.2` that connects device `2` to the router - -Device `1` and device `2` are indirectly connected by the router. - -```cpp - DEVICE 1 0.0.0.1 ROUTER 0.0.0.2 DEVICE 2 - _________ _________ _________ - | || |_||___ | | ___| || |_|| - || P12|| | || || | ||P12 || - || || | P11|| ||P12 | || || - || || |____|| ||____| || || - |_________| |_|_|__||_| |_________| - -- Devices must share common ground -``` -When running device `2` LED should blink (pin 13) every second. If LED (pin 13) of device `1` or `2` lights up an error occurred. -If the example is run removing the router and physically connecting bus `0.0.0.1` and `0.0.0.2`, the end result is the same. The router is trasparently handling the synchronous acknowledgement and forwarding data in both directions. - -The asynchronous acknowledgement used along with the synchronous acknowledgement can be useful to send information if absolute certainty of delivery and duplication avoidance is required, although it consumes more bandwidth than using only the synchronous acknowledgement. It can be a solution (also in a local bus) in critical cases like door lock control. diff --git a/examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/Router/Router.ino b/examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/Router/Router.ino deleted file mode 100644 index d5bf8f47b9..0000000000 --- a/examples/ARDUINO/Network/SoftwareBitBang/RecursiveAcknowledge/Router/Router.ino +++ /dev/null @@ -1,76 +0,0 @@ - -#define PJON_INCLUDE_ASYNC_ACK true -#include - -// Bus id definition -uint8_t bus_id_A[] = {0, 0, 0, 1}; -uint8_t bus_id_B[] = {0, 0, 0, 2}; -// Tunneler is trasparently forwarding data, does not need a device id -PJON busA(bus_id_A, PJON_NOT_ASSIGNED); -PJON busB(bus_id_B, PJON_NOT_ASSIGNED); -// Maximum expected latency or response time, higher if necessary -uint32_t latency = 6000; - -void receiver_functionA(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - if(!PJONTools::bus_id_equality(packet_info.receiver_bus_id, bus_id_B)) return; - // Forward packet to bus 0.0.0.2 - if(packet_info.header & PJON_ACK_REQ_BIT) - busA.strategy.send_response(PJON_ACK); - busB.send_from_id( - packet_info.sender_id, - packet_info.sender_bus_id, - packet_info.receiver_id, - packet_info.receiver_bus_id, - (uint8_t *)payload, - length, - packet_info.header, - packet_info.id - ); -} - -void receiver_functionB(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - if(!PJONTools::bus_id_equality(packet_info.receiver_bus_id, bus_id_A)) return; - // Forward packet to bus 0.0.0.1 - if(packet_info.header & PJON_ACK_REQ_BIT) - busB.strategy.send_response(PJON_ACK); - busA.send_from_id( - packet_info.sender_id, - packet_info.sender_bus_id, - packet_info.receiver_id, - packet_info.receiver_bus_id, - (uint8_t *)payload, - length, - packet_info.header, - packet_info.id - ); -} - -void setup() { - // Initialize LED 13 to be off - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); - // Bus 0.0.0.1 configuration - busA.set_synchronous_acknowledge(true); - busA.set_asynchronous_acknowledge(true); - busA.set_receiver(receiver_functionA); - busA.set_router(true); - busA.strategy.set_pin(11); - busA.begin(); - // Bus 0.0.0.2 configuration - busB.set_synchronous_acknowledge(true); - busB.set_asynchronous_acknowledge(true); - busB.set_receiver(receiver_functionB); - busB.set_router(true); - busB.strategy.set_pin(12); - busB.begin(); -} - -void loop() { - busB.update(); - busA.update(); - long time = micros(); - while((micros() - time) < latency) { - busA.receive(); - busB.receive(); - } -} diff --git a/examples/ARDUINO/Network/ThroughSerial/AsyncAck/Receiver/Receiver.ino b/examples/ARDUINO/Network/ThroughSerial/AsyncAck/Receiver/Receiver.ino deleted file mode 100644 index 03d55773c8..0000000000 --- a/examples/ARDUINO/Network/ThroughSerial/AsyncAck/Receiver/Receiver.ino +++ /dev/null @@ -1,35 +0,0 @@ - -/* Include Async ACK code setting PJON_INCLUDE_ASYNC_ACK as true before including PJON.h */ -#define PJON_INCLUDE_ASYNC_ACK true -#include - -uint8_t bus_id[] = {0, 0, 0, 1}; -// bus(selected device id) -PJON bus(bus_id, 44); - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ - if(payload[0] == 'B') { - digitalWrite(LED_BUILTIN, HIGH); - delay(3); - digitalWrite(LED_BUILTIN, LOW); - delay(3); - } -}; - -void setup() { - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); // Initialize LED 13 to be off - - Serial.begin(9600); - bus.strategy.set_serial(&Serial); - bus.set_synchronous_acknowledge(false); - bus.begin(); - bus.set_receiver(receiver_function); -}; - -void loop() { - bus.update(); - bus.receive(); -}; diff --git a/examples/ARDUINO/Network/ThroughSerial/AsyncAck/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/ThroughSerial/AsyncAck/Transmitter/Transmitter.ino deleted file mode 100644 index c07d21a1af..0000000000 --- a/examples/ARDUINO/Network/ThroughSerial/AsyncAck/Transmitter/Transmitter.ino +++ /dev/null @@ -1,42 +0,0 @@ -/* Include Async ACK code setting PJON_INCLUDE_ASYNC_ACK as true before including PJON.h */ -#define PJON_INCLUDE_ASYNC_ACK true - -#include - -uint8_t bus_id[] = {0, 0, 0, 1}; -// bus(selected device id) -PJON bus(bus_id, 45); - -void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { - if(code == PJON_CONNECTION_LOST) - digitalWrite(LED_BUILTIN, HIGH); // Light up LED 13 if a packet transmission failed -}; - -void setup() { - // Initialize LED 13 to be off - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); - - /* Initialize the Serial instance used for communication - and pass it to PJON's ThroughSerial strategy */ - Serial.begin(9600); - bus.strategy.set_serial(&Serial); - - /* Set configuration to send packet requesting - asynchronous acknowledgement response */ - bus.set_synchronous_acknowledge(false); - bus.set_asynchronous_acknowledge(true); - - bus.set_error(error_handler); - bus.begin(); - - // Send B to device 44 every 1.5s - bus.send_repeatedly(44, "B", 1, 1500000); -}; - -void loop() { - bus.update(); - bus.receive(TS_TIME_IN + TS_BYTE_TIME_OUT); - /* Do not retransmit for the duration of the reception timeout - (Avoid unnecessary retransmissions) */ -}; diff --git a/keywords.txt b/keywords.txt index 8b47c64c51..92cb86b805 100644 --- a/keywords.txt +++ b/keywords.txt @@ -58,7 +58,6 @@ send_repeatedly KEYWORD2 send_packet KEYWORD2 send_packet_blocking KEYWORD2 set_synchronous_acknowledge KEYWORD2 -set_asynchronous_acknowledge KEYWORD2 set_random_seed KEYWORD2 set_communication_mode KEYWORD2 set_error KEYWORD2 @@ -101,13 +100,11 @@ localhost LITERAL1 PJON_MODE_BIT LITERAL1 PJON_TX_INFO_BIT LITERAL1 PJON_ACK_REQ_BIT LITERAL1 -PJON_ACK_MODE_BIT LITERAL1 PJON_CRC_BIT LITERAL1 PJON_EXT_LEN_BIT LITERAL1 PJON_PORT_BIT LITERAL1 PJON_PACKET_ID_BIT LITERAL1 PJON_INCLUDE_PACKET_ID LITERAL1 -PJON_INCLUDE_ASYNC_ACK LITERAL1 PJON_MAX_RECENT_PACKET_IDS LITERAL1 AS_MODE LITERAL1 SWBB_MODE LITERAL1 diff --git a/specification/PJON-network-services-list.md b/specification/PJON-network-services-list.md index 4f2271e860..6b46f6700b 100644 --- a/specification/PJON-network-services-list.md +++ b/specification/PJON-network-services-list.md @@ -2,7 +2,7 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) -- [Acknowledge specification v1.0](/specification/PJON-protocol-acknowledge-specification-v1.0.md) +- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - **[Network services list](/specification/PJON-network-services-list.md)** #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) diff --git a/specification/PJON-protocol-acknowledge-specification-v2.0.md b/specification/PJON-protocol-acknowledge-specification-v2.0.md new file mode 100644 index 0000000000..c74b003775 --- /dev/null +++ b/specification/PJON-protocol-acknowledge-specification-v2.0.md @@ -0,0 +1,38 @@ +### Specifications index + +#### Network layer +- [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) +- **[Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md)** +- [Network services list](/specification/PJON-network-services-list.md) +#### Data link layer +- [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) +- [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) +- [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) +- [TSDL (Tardy Serial Data Link) v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) +- [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) + +--- + +## PJON® acknowledge v2.0 +``` +Invented by Giovanni Blu Mitolo +Originally published: 17/10/2016 +Latest revision: 15/04/2020 +Related implementation: https://github.com/gioblu/PJON/ +Compliant versions: PJON v13.0 and following +Released into the public domain +``` +PJON supports the synchronous acknowledgement feature used to have reception certainty. + +### Synchronous acknowledge +The synchronous acknowledgement is a blocking procedure, can be used only within one collision domain, although it is efficient and has a short response delay and is composed by a single byte (decimal 6) at the network layer but each data link may implement it differently according to it features and limitations. +```cpp +Channel analysis Transmission Response + _____ ____________________________________________ _____ +| C-A || ID | HEADER | LENGTH |CRC8| CONTENT |CRC8|| ACK | +|-----||----|----------|--------|----|---------|----||-----| +| 0 || 12 | 00000100 | 6 | | 64 | || 6 | +|_____||____|__________|________|____|_________|____||_____| +``` + +The graph above contains a packet transmission where the character `@` (decimal 64) is sent to device id `12`. As defined by the [PJON protocol layer specification v3.2](/specification/PJON-protocol-specification-v3.2.md), the header's `ACK` bit high requests a synchronous acknowledgement response, see [PJDL v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md), [PJDLR v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md), [PJDLS v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) and [TSDL v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) specification for additional information. diff --git a/specification/PJON-protocol-specification-v3.2.md b/specification/PJON-protocol-specification-v3.2.md index bd3e3d7cf0..958d3c204e 100644 --- a/specification/PJON-protocol-specification-v3.2.md +++ b/specification/PJON-protocol-specification-v3.2.md @@ -2,7 +2,7 @@ #### Network layer - **[PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md)** -- [Acknowledge specification v1.0](/specification/PJON-protocol-acknowledge-specification-v1.0.md) +- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) @@ -32,7 +32,6 @@ The graph below shows the conceptual model that characterizes and standardizes t | 3 Network layer: PJON | |- Optional features ----------------------------| | Routing and switching | -| Asynchronous acknowledgement | | Service identification (16 bits) | | Packet identification (16 bits) | | Bus identification (32 bits) | @@ -61,7 +60,7 @@ The graph below shows the conceptual model that characterizes and standardizes t * Devices are identified by a unique 8 bits device id * Buses are identified with a 32 bits bus id * Many buses can coexist on the same medium -* Synchronous and or asynchronous acknowledgement can be requested (see [Acknowledge specification v1.0](/specification/PJON-protocol-acknowledge-specification-v1.0.md)) +* A synchronous acknowledgement can be requested (see [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md)) * Network services are identified with a 16 bits port id @@ -205,7 +204,7 @@ Depending on header's `MODE` bit, PJON packets can contain basic or extended sup ``` -In local mode packets can be broadcasted to all devices sending to device id `0`. Acknowledgement is not supported therefore any broadcasted packet that requests synchronous and or asynchronous acknowledgement is ignored by recipients. +In local mode packets can be broadcasted to all devices sending to device id `0`. Acknowledgement is not supported therefore any broadcasted packet that requests an acknowledgement is ignored by recipients. ```cpp _________________________________ @@ -249,7 +248,7 @@ If header's `MODE` bit is high [bus](/specification/PJON-protocol-specification- ``` -In shared mode packets can be broadcasted to all devices sharing the same bus id sending to device id `0`. Acknowledgement is not supported, therefore any broadcasted packet that requests synchronous and or asynchronous acknowledgement is ignored by recipients. +In shared mode packets can be broadcasted to all devices sharing the same bus id sending to device id `0`. Acknowledgement is not supported, therefore any broadcasted packet that requests an acknowledgement is ignored by recipients. ```cpp ________________________________________ diff --git a/specification/SFSP-frame-separation-specification-v1.0.md b/specification/SFSP-frame-separation-specification-v1.0.md index 7abe425e85..73ea1ab60e 100644 --- a/specification/SFSP-frame-separation-specification-v1.0.md +++ b/specification/SFSP-frame-separation-specification-v1.0.md @@ -2,7 +2,7 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) -- [Acknowledge specification v1.0](/specification/PJON-protocol-acknowledge-specification-v1.0.md) +- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) diff --git a/specification/PJON-protocol-acknowledge-specification-v1.0.md b/specification/obsolete/PJON-protocol-acknowledge-specification-v1.0.md similarity index 100% rename from specification/PJON-protocol-acknowledge-specification-v1.0.md rename to specification/obsolete/PJON-protocol-acknowledge-specification-v1.0.md diff --git a/specification/obsolete/PJON-protocol-specification-v1.0.md b/specification/obsolete/PJON-protocol-specification-v1.0.md index e2d4411b1a..a7dc10681b 100644 --- a/specification/obsolete/PJON-protocol-specification-v1.0.md +++ b/specification/obsolete/PJON-protocol-specification-v1.0.md @@ -60,7 +60,7 @@ In the graph below is shown the protocol stack model proposed. The differences b * Transmission occurs only if the communication medium is not in use * Devices communicate through packets with a maximum length of 255 or 65535 bytes * Packet transmission is regulated by a 1, 2 or 3 byte header -* Synchronous and or asynchronous acknowledgement can be requested (see [Acknowledge specification v0.1](/specification/PJON-protocol-acknowledge-specification-v0.1.md)) +* A synchronous acknowledgement can be requested (see [Acknowledge specification v0.1](/specification/PJON-protocol-acknowledge-specification-v0.1.md)) The PJON protocol v1.0 handles internal bus connectivity and unique addressing for 254 devices, through bus communication with unique bus addressing for 4.294.967.295 buses and supports up to 1.090.921.692.930 devices. It regulates the exchange of packets with a configurable set of features driven by its header. Depending on the packet configuration a certain overhead is added to information varying from 4 up to 19 bytes. diff --git a/src/PJONLocal.h b/src/PJONLocal.h index 273d1b99a4..33f15c9040 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -14,9 +14,9 @@ ______-| |-__________________________________________________________________ PJONLocal implements a subset of the PJON protocol's features. It does support -only local mode, does not support the asynchronous acknowledge and packet -queueing, infact it can transmit only one packet at a time without any -buffering, although it conserves interoperability with other classes. +only local mode and does not support packet queueing, infact it can transmit +only one packet at a time without any buffering, although it conserves +interoperability with other classes. This class has been developed to enable PJON networking on very limited microcontrollers, like ATtiny45, ATtiny84 and ATtiny85, where even 1kB diff --git a/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md b/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md index 028b006ba3..21923ba7ee 100644 --- a/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md +++ b/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md @@ -2,7 +2,7 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) -- [Acknowledge specification v1.0](/specification/PJON-protocol-acknowledge-specification-v1.0.md) +- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) diff --git a/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md b/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md index 829740d670..09adbc9fef 100644 --- a/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md +++ b/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md @@ -3,7 +3,7 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) -- [Acknowledge specification v1.0](/specification/PJON-protocol-acknowledge-specification-v1.0.md) +- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index bf96684e95..003e2be2ca 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -3,7 +3,7 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) -- [Acknowledge specification v1.0](/specification/PJON-protocol-acknowledge-specification-v1.0.md) +- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - **[PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md)** diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index ed33d6ab06..3a79792bc9 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -53,9 +53,9 @@ In some cases it may be required to add a delay before disabling the RS485 pins bus.strategy.set_RS485_delay(1); ``` -See [RS485-Blink](../../../examples/ARDUINO/Local/ThroughSerial/RS485-Blink) and [RS485-AsyncAck](../../../examples/ARDUINO/Local/ThroughSerial/RS485-AsyncAck) examples. +If you need to interface devices using RS485 see the [RS485-Blink](../../../examples/ARDUINO/Local/ThroughSerial/RS485-Blink) example. -HC-12 wireless module supports both synchronous and asynchronous acknowledgement, see [HC-12-Blink](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-Blink), [HC-12-SendAndReceive](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive), [HC-12-LocalChat](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat) and [HC-12-AsyncAck](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-AsyncAck) examples. +HC-12 wireless module supports the synchronous acknowledgement, see [HC-12-Blink](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-Blink), [HC-12-SendAndReceive](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive) and [HC-12-LocalChat](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat) examples. All the other necessary information is present in the general [Documentation](/documentation). diff --git a/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md b/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md index c747c96c9b..110989024b 100644 --- a/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md +++ b/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md @@ -2,7 +2,7 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) -- [Acknowledge specification v1.0](/specification/PJON-protocol-acknowledge-specification-v1.0.md) +- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) diff --git a/src/strategies/ThroughSerialAsync/README.md b/src/strategies/ThroughSerialAsync/README.md index 245ac68c92..465546e5e8 100644 --- a/src/strategies/ThroughSerialAsync/README.md +++ b/src/strategies/ThroughSerialAsync/README.md @@ -57,9 +57,9 @@ bus.strategy.set_RS485_txe_pin(12); ``` See the [Blink](../../../examples/ARDUINO/Local/ThroughSerialAsync/Blink) and [BlinkWithResponse](https://github.com/gioblu/PJON/tree/master/examples/ARDUINO/Local/ThroughSerialAsync/BlinkWithResponse) examples. -Examples for `ThroughSerial` can be easily modifed to work with `ThroughSerialAsync`, see [RS485-Blink](../../../examples/ARDUINO/Local/ThroughSerial/RS485-Blink) and [RS485-AsyncAck](../../../examples/ARDUINO/Local/ThroughSerial/RS485-AsyncAck) examples. +Examples for `ThroughSerial` can be easily modifed to work with `ThroughSerialAsync`, if you need to interface devices using RS485 see the [RS485-Blink](../../../examples/ARDUINO/Local/ThroughSerial/RS485-Blink) example. -HC-12 wireless module supports both synchronous and asynchronous acknowledgement, see [HC-12-Blink](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-Blink), [HC-12-SendAndReceive](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive), [HC-12-LocalChat](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat) and [HC-12-AsyncAck](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-AsyncAck) examples. +HC-12 wireless module supports the synchronous acknowledgement, see [HC-12-Blink](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-Blink), [HC-12-SendAndReceive](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive) and [HC-12-LocalChat](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat) examples. All the other necessary information is present in the general [Documentation](/documentation). diff --git a/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md b/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md index c747c96c9b..110989024b 100644 --- a/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md +++ b/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md @@ -2,7 +2,7 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) -- [Acknowledge specification v1.0](/specification/PJON-protocol-acknowledge-specification-v1.0.md) +- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) From 37fa6ddad0e018f7e540dbc9ddf299b54a06572f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 15 Apr 2020 17:02:37 +0200 Subject: [PATCH 003/323] copy_bus_id and bus_id_equality generalised in copy_id and id_equality --- src/PJON.h | 26 ++++++++++++++------------ src/PJONDefines.h | 24 ++++++++++++++---------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index def978187c..d295f1b88a 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -69,9 +69,9 @@ static void PJON_dummy_receiver_handler( ) {}; static void PJON_dummy_error_handler( - uint8_t, // code - uint16_t, // data - void * // custom_pointer + uint8_t, // code + uint16_t, // data + void * // custom_pointer ) {}; template @@ -117,7 +117,7 @@ class PJON { PJON bus(my_bys, 1); */ PJON(const uint8_t *b_id, uint8_t device_id) : strategy(Strategy()) { - PJONTools::copy_bus_id(bus_id, b_id); + PJONTools::copy_id(bus_id, b_id, 4); _device_id = device_id; set_default(); }; @@ -460,9 +460,9 @@ class PJON { ) { uint8_t original_device_id = _device_id; uint8_t original_bus_id[4]; - PJONTools::copy_bus_id(original_bus_id, bus_id); + PJONTools::copy_id(original_bus_id, bus_id, 4); set_id(tx_id); - PJONTools::copy_bus_id(bus_id, tx_bus_id); + PJONTools::copy_id(bus_id, tx_bus_id, 4); uint16_t result = PJON_FAIL; #if(PJON_MAX_PACKETS > 0) result = dispatch( @@ -473,7 +473,7 @@ class PJON { result = send_packet_blocking( rx_id, rx_bus_id, payload, length, header, packet_id, rx_port ); - PJONTools::copy_bus_id(bus_id, original_bus_id); + PJONTools::copy_id(bus_id, original_bus_id, 4); set_id(original_device_id); return result; }; @@ -686,7 +686,7 @@ class PJON { void set_default() { _mode = PJON_HALF_DUPLEX; - if(!PJONTools::bus_id_equality(bus_id, PJONTools::localhost())) + if(!PJONTools::id_equality(bus_id, PJONTools::localhost(), 4)) set_shared_network(true); set_error(PJON_dummy_error_handler); set_receiver(PJON_dummy_receiver_handler); @@ -827,9 +827,10 @@ class PJON { ( (info.header & PJON_MODE_BIT) && (recent_packet_ids[i].header & PJON_MODE_BIT) && - PJONTools::bus_id_equality( + PJONTools::id_equality( (uint8_t *)info.sender_bus_id, - (uint8_t *)recent_packet_ids[i].sender_bus_id + (uint8_t *)recent_packet_ids[i].sender_bus_id, + 4 ) ) || ( !(info.header & PJON_MODE_BIT) && @@ -849,9 +850,10 @@ class PJON { recent_packet_ids[0].id = info.id; recent_packet_ids[0].header = info.header; recent_packet_ids[0].sender_id = info.sender_id; - PJONTools::copy_bus_id( + PJONTools::copy_id( recent_packet_ids[0].sender_bus_id, - info.sender_bus_id + info.sender_bus_id, + 4 ); }; diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 04a1920fbb..069ff035ee 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -233,14 +233,18 @@ struct PJONTools { /* Copy a bus id: */ - static void copy_bus_id(uint8_t dest[], const uint8_t src[]) { - memcpy(dest, src, 4); + static void copy_id(uint8_t dest[], const uint8_t src[], uint8_t length) { + memcpy(dest, src, length); }; /* Check equality between two bus ids */ - static bool bus_id_equality(const uint8_t *n_one, const uint8_t *n_two) { - for(uint8_t i = 0; i < 4; i++) + static bool id_equality( + const uint8_t *n_one, + const uint8_t *n_two, + uint8_t length + ) { + for(uint8_t i = 0; i < length; i++) if(n_one[i] != n_two[i]) return false; return true; @@ -293,10 +297,10 @@ struct PJONTools { } #ifndef PJON_LOCAL if(header & PJON_MODE_BIT) { - PJONTools::copy_bus_id((uint8_t*) &destination[index], receiver_bus_id); + copy_id((uint8_t*) &destination[index], receiver_bus_id, 4); index += 4; if(header & PJON_TX_INFO_BIT) { - PJONTools::copy_bus_id((uint8_t*) &destination[index], sender_bus_id); + copy_id((uint8_t*) &destination[index], sender_bus_id, 4); index += 4; } } @@ -350,13 +354,13 @@ struct PJONTools { index += extended_length + 2; // + LENGTH + HEADER CRC #ifndef PJON_LOCAL if(info.header & PJON_MODE_BIT) { - copy_bus_id(info.receiver_bus_id, packet + index); + copy_id(info.receiver_bus_id, packet + index, 4); index += 4; if(info.header & PJON_TX_INFO_BIT) { - copy_bus_id(info.sender_bus_id, packet + index); + copy_id(info.sender_bus_id, packet + index, 4); index += 4; - } else copy_bus_id(info.sender_bus_id, localhost()); - } else copy_bus_id(info.receiver_bus_id, localhost()); + } else copy_id(info.sender_bus_id, localhost(), 4); + } else copy_id(info.receiver_bus_id, localhost(), 4); #endif if(info.header & PJON_TX_INFO_BIT) info.sender_id = packet[index++]; From 069886863b1d8d76753f6a0a98da9fa9a2d8198e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 15 Apr 2020 17:03:48 +0200 Subject: [PATCH 004/323] copy_id and id_equality comments update --- src/PJONDefines.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 069ff035ee..27ca926d2a 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -231,13 +231,13 @@ struct PJONTools { return seed; }; - /* Copy a bus id: */ + /* Copy an id: */ static void copy_id(uint8_t dest[], const uint8_t src[], uint8_t length) { memcpy(dest, src, length); }; - /* Check equality between two bus ids */ + /* Check equality between two ids: */ static bool id_equality( const uint8_t *n_one, From 0f6a764c191727aeb6abe21e76464364bbae0bf7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Apr 2020 12:13:11 +0200 Subject: [PATCH 005/323] MAC address feature added (breaking compatibility) --- src/PJON.h | 268 ++++++++++++++++++++++++---------------------- src/PJONDefines.h | 147 +++++++++++++------------ 2 files changed, 218 insertions(+), 197 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index d295f1b88a..0cd71e4592 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -79,12 +79,12 @@ class PJON { public: Strategy strategy; uint8_t config = PJON_TX_INFO_BIT | PJON_ACK_REQ_BIT; - uint8_t bus_id[4] = {0, 0, 0, 0}; uint8_t data[PJON_PACKET_MAX_LENGTH]; PJON_Packet_Info last_packet_info; PJON_Packet packets[PJON_MAX_PACKETS]; uint16_t port = PJON_BROADCAST; uint8_t random_seed = A0; + PJON_End_Point tx; #if(PJON_INCLUDE_PACKET_ID) PJON_Packet_Record recent_packet_ids[PJON_MAX_RECENT_PACKET_IDS]; @@ -100,15 +100,26 @@ class PJON { PJON bus; */ PJON() : strategy(Strategy()) { - _device_id = PJON_NOT_ASSIGNED; set_default(); }; + /* PJON initialization passing the mac address: + const uint8_t mac[6] = {1, 2, 3, 4, 5, 6}; + PJON bus(mac); */ + + #if(PJON_INCLUDE_MAC) + PJON(const uint8_t *mac_addr) : strategy(Strategy()) { + PJONTools::copy_id(tx.mac, mac_addr, 6); + config |= PJON_MAC_BIT; + set_default(); + }; + #endif + /* PJON initialization passing device id: PJON bus(1); */ PJON(uint8_t device_id) : strategy(Strategy()) { - _device_id = device_id; + tx.id = device_id; set_default(); }; @@ -117,45 +128,40 @@ class PJON { PJON bus(my_bys, 1); */ PJON(const uint8_t *b_id, uint8_t device_id) : strategy(Strategy()) { - PJONTools::copy_id(bus_id, b_id, 4); - _device_id = device_id; + tx.id = device_id; + PJONTools::copy_id(tx.bus_id, b_id, 4); + config |= PJON_MODE_BIT; set_default(); }; /* Begin function to be called after initialization: */ void begin() { - PJON_RANDOM_SEED(PJON_ANALOG_READ(random_seed) + _device_id); - strategy.begin(_device_id); + PJON_RANDOM_SEED(PJON_ANALOG_READ(random_seed) + tx.id); + strategy.begin(tx.id); #if(PJON_INCLUDE_PACKET_ID) - _packet_id_seed = PJON_RANDOM(65535) + _device_id; + _packet_id_seed = PJON_RANDOM(65535) + tx.id; #endif }; /* Compose packet in PJON format: */ uint16_t compose_packet( - const uint8_t rx_id, - const uint8_t *rx_bus_id, + PJON_Packet_Info info, uint8_t *destination, const void *source, - uint16_t length, - uint8_t header = PJON_NO_HEADER, - uint16_t packet_id = 0, - uint16_t rx_port = PJON_BROADCAST + uint16_t length ) { + info.header = (info.header == PJON_NO_HEADER) ? config : info.header; + info.tx = tx; + if(!info.id && (info.header & PJON_PACKET_ID_BIT)) + info.id = PJONTools::new_packet_id(_packet_id_seed++); + if( + (port != PJON_BROADCAST) && (info.port == PJON_BROADCAST) && + (info.header & PJON_PORT_BIT) + ) info.port = port; uint16_t l = PJONTools::compose_packet( - _device_id, - bus_id, - rx_id, - rx_bus_id, - destination, - source, - length, - (header == PJON_NO_HEADER) ? config : header, - (!packet_id) ? PJONTools::new_packet_id(_packet_id_seed++) : packet_id, - rx_port, - port + info, destination, source, length ); if(l < PJON_PACKET_MAX_LENGTH) return l; _error(PJON_CONTENT_TOO_LONG, l, _custom_pointer); @@ -164,35 +170,22 @@ class PJON { /* Get device id: */ - uint8_t device_id() const { - return _device_id; - }; + uint8_t device_id() const { return tx.id; }; /* Add packet to buffer (delivery attempt by the next update() call): */ uint16_t dispatch( - uint8_t rx_id, - const uint8_t *rx_bus_id, + const PJON_Packet_Info info, const void *packet, uint16_t length, - uint32_t timing, - uint8_t header = PJON_NO_HEADER, - uint16_t packet_id = 0, - uint16_t rx_port = PJON_BROADCAST, + uint32_t timing = 0, uint16_t packet_index = PJON_FAIL ) { bool p = (packet_index != PJON_FAIL); for(uint16_t i = ((p) ? packet_index : 0); i < PJON_MAX_PACKETS; i++) if(packets[i].state == 0 || p) { if(!(length = compose_packet( - rx_id, - rx_bus_id, - packets[i].content, - packet, - length, - header, - packet_id, - rx_port + info, packets[i].content, packet, length ))) return PJON_FAIL; packets[i].length = length; packets[i].state = PJON_TO_BE_SENT; @@ -251,7 +244,7 @@ class PJON { batch_length--; if(i == 0) - if(data[i] != _device_id && data[i] != PJON_BROADCAST && !_router) + if((data[i] != tx.id) && (data[i] != PJON_BROADCAST) && !_router) return PJON_BUSY; if(i == 1) { @@ -265,6 +258,9 @@ class PJON { (data[1] & PJON_EXT_LEN_BIT) && !(data[1] & PJON_CRC_BIT) ) || ( !PJON_INCLUDE_PACKET_ID && (data[1] & PJON_PACKET_ID_BIT) + ) || ( + (!PJON_INCLUDE_MAC && (data[1] & PJON_MAC_BIT)) || + ((data[1] & PJON_MAC_BIT) && !(data[1] & PJON_CRC_BIT)) ) ) return PJON_BUSY; extended_length = data[i] & PJON_EXT_LEN_BIT; @@ -295,7 +291,8 @@ class PJON { (i < (uint8_t)(8 + extended_length)) ) { if(config & PJON_MODE_BIT) { - if(bus_id[i - 4 - extended_length] != data[i]) return PJON_BUSY; + if(tx.bus_id[i - 4 - extended_length] != data[i]) + return PJON_BUSY; } else if(data[i] != 0) return PJON_BUSY; // Do not reject localhost } } @@ -314,6 +311,12 @@ class PJON { } else if(PJON_crc8::compute(data, length - 1) != data[length - 1]) return PJON_NAK; + #if(PJON_INCLUDE_MAC) + if((data[1] & PJON_MAC_BIT) && (length > 15) && !_router) + if(!PJONTools::id_equality(data + (overhead - 16), tx.mac, 6)) + return PJON_BUSY; + #endif + if(data[1] & PJON_ACK_REQ_BIT && data[0] != PJON_BROADCAST) if((_mode != PJON_SIMPLEX) && !_router) strategy.send_response(PJON_ACK); @@ -391,29 +394,32 @@ class PJON { return false; }; + /* Fill a PJON_Packet_Info using parameters: */ + + PJON_Packet_Info fill_info( + uint8_t rx_id, + uint8_t header, + uint16_t packet_id, + uint16_t rx_port + ) { + PJON_Packet_Info info; + info.rx.id = rx_id; + info.header = header; + info.id = packet_id; + info.port = rx_port; + return info; + }; + /* Schedule a packet sending to the sender of the last packet received. This function is typically called within the receive callback to deliver a response to a request. */ - uint16_t reply( - const void *payload, - uint16_t length, - uint8_t header = PJON_NO_HEADER, - uint16_t packet_id = 0, - uint16_t rx_port = PJON_BROADCAST - ) { - if(last_packet_info.sender_id != PJON_BROADCAST) - return dispatch( - last_packet_info.sender_id, - last_packet_info.sender_bus_id, - payload, - length, - 0, - ((header == PJON_NO_HEADER) ? last_packet_info.header : header), - packet_id, - rx_port - ); - return false; + uint16_t reply(const void *payload, uint16_t length) { + PJON_Packet_Info info; + info = last_packet_info; + info.rx = info.tx; + info.header = config; + return dispatch(info, payload, length); }; /* Schedule a packet sending: */ @@ -426,9 +432,9 @@ class PJON { uint16_t packet_id = 0, uint16_t rx_port = PJON_BROADCAST ) { - return dispatch( - rx_id, bus_id, payload, length, 0, header, packet_id, rx_port - ); + PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); + PJONTools::copy_id(info.rx.bus_id, tx.bus_id, 4); + return dispatch(info, payload, length); }; uint16_t send( @@ -440,41 +446,31 @@ class PJON { uint16_t packet_id = 0, uint16_t rx_port = PJON_BROADCAST ) { - return dispatch( - rx_id, rx_bus_id, payload, length, 0, header, packet_id, rx_port - ); + PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); + PJONTools::copy_id(info.rx.bus_id, rx_bus_id, 4); + return dispatch(info, payload, length); }; - /* Schedule a packet sending configuring its sender info: */ + uint16_t send(PJON_Packet_Info info, const void *payload, uint16_t length) { + return dispatch(info, payload, length); + }; - uint16_t send_from_id( - uint8_t tx_id, - const uint8_t *tx_bus_id, - uint8_t rx_id, - const uint8_t *rx_bus_id, + /* Forward a packet: */ + + uint16_t forward( + PJON_Packet_Info info, const void *payload, - uint16_t length, - uint8_t header = PJON_NO_HEADER, - uint16_t packet_id = 0, - uint16_t rx_port = PJON_BROADCAST + uint16_t length ) { - uint8_t original_device_id = _device_id; - uint8_t original_bus_id[4]; - PJONTools::copy_id(original_bus_id, bus_id, 4); - set_id(tx_id); - PJONTools::copy_id(bus_id, tx_bus_id, 4); + PJON_End_Point original_end_point = tx; + tx = info.tx; uint16_t result = PJON_FAIL; #if(PJON_MAX_PACKETS > 0) - result = dispatch( - rx_id, rx_bus_id, payload, length, 0, header, packet_id, rx_port - ); + result = dispatch(info, payload, length); #endif if(result == PJON_FAIL) - result = send_packet_blocking( - rx_id, rx_bus_id, payload, length, header, packet_id, rx_port - ); - PJONTools::copy_id(bus_id, original_bus_id, 4); - set_id(original_device_id); + result = send_packet_blocking(info, payload, length); + tx = original_end_point; return result; }; @@ -490,9 +486,9 @@ class PJON { uint16_t packet_id = 0, uint16_t rx_port = PJON_BROADCAST ) { - return dispatch( - rx_id, bus_id, payload, length, timing, header, packet_id, rx_port - ); + PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); + PJONTools::copy_id(info.rx.bus_id, tx.bus_id, 4); + return dispatch(info, payload, length, timing); }; /* IMPORTANT: send_repeatedly timing maximum @@ -508,9 +504,18 @@ class PJON { uint16_t packet_id = 0, uint16_t rx_port = PJON_BROADCAST ) { - return dispatch( - rx_id, rx_bus_id, payload, length, timing, header, packet_id, rx_port - ); + PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); + PJONTools::copy_id(info.rx.bus_id, rx_bus_id, 4); + return dispatch(info, payload, length, timing); + }; + + uint16_t send_repeatedly( + PJON_Packet_Info info, + const void *payload, + uint16_t length, + uint32_t timing + ) { + return dispatch(info, payload, length, timing); }; /* Transmit an already composed packet: */ @@ -542,9 +547,10 @@ class PJON { uint16_t packet_id = 0, uint16_t rx_port = PJON_BROADCAST ) { - if(!(length = compose_packet( - rx_id, bus_id, data, payload, length, header, packet_id, rx_port - ))) return PJON_FAIL; + PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); + PJONTools::copy_id(info.rx.bus_id, tx.bus_id, 4); + if(!(length = compose_packet(info, data, payload, length))) + return PJON_FAIL; return send_packet(data, length); }; @@ -557,9 +563,20 @@ class PJON { uint16_t packet_id = 0, uint16_t rx_port = PJON_BROADCAST ) { - if(!(length = compose_packet( - rx_id, rx_bus_id, data, payload, length, header, packet_id, rx_port - ))) return PJON_FAIL; + PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); + PJONTools::copy_id(info.rx.bus_id, rx_bus_id, 4); + if(!(length = compose_packet(info, data, payload, length))) + return PJON_FAIL; + return send_packet(data, length); + }; + + uint16_t send_packet( + PJON_Packet_Info info, + const void *payload, + uint16_t length + ) { + if(!(length = compose_packet(info, data, payload, length))) + return PJON_FAIL; return send_packet(data, length); }; @@ -587,16 +604,9 @@ class PJON { (state != PJON_ACK) && (attempts <= strategy.get_max_attempts()) && (uint32_t)(PJON_MICROS() - start) <= timeout ) { - if(!(length = compose_packet( - rx_id, - rx_bus_id, - data, - payload, - old_length, - header, - packet_id, - rx_port - ))) { + PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); + PJONTools::copy_id(info.rx.bus_id, rx_bus_id, 4); + if(!(length = compose_packet(info, data, payload, old_length))) { _recursion--; return PJON_FAIL; } @@ -627,7 +637,8 @@ class PJON { uint32_t timeout = 3000000 ) { return send_packet_blocking( - rx_id, bus_id, payload, length, header, packet_id, rx_port, timeout + rx_id, tx.bus_id, payload, length, header, + packet_id, rx_port, timeout ); }; @@ -686,15 +697,8 @@ class PJON { void set_default() { _mode = PJON_HALF_DUPLEX; - if(!PJONTools::id_equality(bus_id, PJONTools::localhost(), 4)) - set_shared_network(true); set_error(PJON_dummy_error_handler); set_receiver(PJON_dummy_receiver_handler); - for(uint16_t i = 0; i < PJON_MAX_PACKETS; i++) { - packets[i].state = 0; - packets[i].timing = 0; - packets[i].attempts = 0; - } }; /* Pass as a parameter a function you previously defined in the code. @@ -715,7 +719,7 @@ class PJON { /* Set the device id passing a single byte (watch out to id collision): */ void set_id(uint8_t id) { - _device_id = id; + tx.id = id; }; /* Include the port passing a boolean state and an unsigned integer: */ @@ -736,6 +740,14 @@ class PJON { set_config_bit(state, PJON_TX_INFO_BIT); }; + /* Configure network interface identification inclusion in the packet. + state = true -> +96 bits (sender's and recipient's MAC address) + state = false -> No overhead added */ + + void include_mac(bool state) { + set_config_bit(state, PJON_MAC_BIT); + } + /* Configure the bus network behaviour. TRUE: Include 4 bytes bus id or group identification. FALSE: Use only 1 byte local device identification. */ @@ -823,12 +835,12 @@ class PJON { for(uint8_t i = 0; i < PJON_MAX_RECENT_PACKET_IDS; i++) if( info.id == recent_packet_ids[i].id && - info.sender_id == recent_packet_ids[i].sender_id && ( + info.tx.id == recent_packet_ids[i].sender_id && ( ( (info.header & PJON_MODE_BIT) && (recent_packet_ids[i].header & PJON_MODE_BIT) && PJONTools::id_equality( - (uint8_t *)info.sender_bus_id, + (uint8_t *)info.tx.bus_id, (uint8_t *)recent_packet_ids[i].sender_bus_id, 4 ) @@ -849,10 +861,10 @@ class PJON { recent_packet_ids[i] = recent_packet_ids[i - 1]; recent_packet_ids[0].id = info.id; recent_packet_ids[0].header = info.header; - recent_packet_ids[0].sender_id = info.sender_id; + recent_packet_ids[0].sender_id = info.tx.id; PJONTools::copy_id( recent_packet_ids[0].sender_bus_id, - info.sender_bus_id, + info.tx.bus_id, 4 ); }; @@ -868,6 +880,4 @@ class PJON { PJON_Receiver _receiver; uint8_t _recursion = 0; bool _router = false; - protected: - uint8_t _device_id; }; diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 27ca926d2a..46a8b5de5e 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -98,9 +98,9 @@ limitations under the License. */ /* 0 - Synchronous acknowledgement disabled 1 - Synchronous acknowledgement enabled */ #define PJON_ACK_REQ_BIT 0B00000100 - -// RESERVED FOR MAC FEATURE 0B00001000 - +/* 0 - MAC address inclusion disabled + 1 - MAC address inclusion enabled (2x 48 bits) */ +#define PJON_MAC_BIT 0B00001000 /* 0 - No port id contained 1 - Port id contained (2 bytes integer) */ #define PJON_PORT_BIT 0B00010000 @@ -147,15 +147,20 @@ limitations under the License. */ #define PJON_MAX_RECENT_PACKET_IDS 10 #endif +/* If set to false mac feature is not included saving memory */ +#ifndef PJON_INCLUDE_MAC + #define PJON_INCLUDE_MAC false +#endif + /* Data structures: */ struct PJON_Packet { - uint8_t attempts; + uint8_t attempts = 0; uint8_t content[PJON_PACKET_MAX_LENGTH]; uint16_t length; uint32_t registration; - uint16_t state; - uint32_t timing; + uint16_t state = 0; + uint32_t timing = 0; }; struct PJON_Packet_Record { @@ -167,15 +172,23 @@ struct PJON_Packet_Record { #endif }; +struct PJON_End_Point { + uint8_t id = PJON_NOT_ASSIGNED; + #ifndef PJON_LOCAL + uint8_t bus_id[4] = {0, 0, 0, 0}; + #endif + #if(PJON_INCLUDE_MAC) + uint8_t mac[6] = {0, 0, 0, 0, 0, 0}; + #endif +}; + struct PJON_Packet_Info { - uint8_t header; - uint16_t id; - uint8_t receiver_id; - uint8_t sender_id; - uint16_t port; + PJON_End_Point tx; + PJON_End_Point rx; + uint8_t header = PJON_NO_HEADER; + uint16_t id = 0; + uint16_t port = PJON_BROADCAST; #ifndef PJON_LOCAL - uint8_t receiver_bus_id[4]; - uint8_t sender_bus_id[4]; void *custom_pointer; #endif }; @@ -214,6 +227,7 @@ struct PJONTools { + (header & PJON_CRC_BIT ? 4 : 1) + (header & PJON_PORT_BIT ? 2 : 0) + (header & PJON_PACKET_ID_BIT ? 2 : 0) + + (header & PJON_MAC_BIT ? 12 : 0) + 2 // header + header's CRC ); }; @@ -253,40 +267,30 @@ struct PJONTools { /* Composes a packet in PJON format: */ static uint16_t compose_packet( - const uint8_t sender_id, - const uint8_t *sender_bus_id, - const uint8_t receiver_id, - const uint8_t *receiver_bus_id, + PJON_Packet_Info info, uint8_t *destination, const void *source, - uint16_t length, - uint8_t header = 0, - uint16_t packet_id = 0, - uint16_t destination_port = PJON_BROADCAST, - uint16_t source_port = PJON_BROADCAST + uint16_t length ) { uint8_t index = 0; - if(length > 255) header |= PJON_EXT_LEN_BIT; - if(destination_port != PJON_BROADCAST) header |= PJON_PORT_BIT; - if( - (header & PJON_PORT_BIT) && - (destination_port == PJON_BROADCAST) && - (source_port == PJON_BROADCAST) - ) header &= ~PJON_PORT_BIT; - if(receiver_id == PJON_BROADCAST) header &= ~(PJON_ACK_REQ_BIT); - uint16_t new_length = length + packet_overhead(header); - bool extended_length = header & PJON_EXT_LEN_BIT; - if(new_length > 15 && !(header & PJON_CRC_BIT)) { - header |= PJON_CRC_BIT; - new_length = (uint16_t)(length + packet_overhead(header)); + if(length > 255) info.header |= PJON_EXT_LEN_BIT; + if(info.port != PJON_BROADCAST) info.header |= PJON_PORT_BIT; + if((info.header & PJON_PORT_BIT) && (info.port == PJON_BROADCAST)) + info.header &= ~PJON_PORT_BIT; + if(info.rx.id == PJON_BROADCAST) info.header &= ~(PJON_ACK_REQ_BIT); + uint16_t new_length = length + packet_overhead(info.header); + bool extended_length = info.header & PJON_EXT_LEN_BIT; + if(new_length > 15 && !(info.header & PJON_CRC_BIT)) { + info.header |= PJON_CRC_BIT; + new_length = (uint16_t)(length + packet_overhead(info.header)); } if(new_length > 255 && !extended_length) { - header |= PJON_EXT_LEN_BIT; - new_length = (uint16_t)(length + packet_overhead(header)); + info.header |= PJON_EXT_LEN_BIT; + new_length = (uint16_t)(length + packet_overhead(info.header)); } if(new_length >= PJON_PACKET_MAX_LENGTH) return new_length; - destination[index++] = receiver_id; - destination[index++] = (uint8_t)header; + destination[index++] = info.rx.id; + destination[index++] = (uint8_t)info.header; if(extended_length) { destination[index++] = (uint8_t)(new_length >> 8); destination[index++] = (uint8_t)new_length; @@ -296,38 +300,40 @@ struct PJONTools { destination[index++] = PJON_crc8::compute((uint8_t *)destination, 3); } #ifndef PJON_LOCAL - if(header & PJON_MODE_BIT) { - copy_id((uint8_t*) &destination[index], receiver_bus_id, 4); + if(info.header & PJON_MODE_BIT) { + copy_id((uint8_t*) &destination[index], info.rx.bus_id, 4); index += 4; - if(header & PJON_TX_INFO_BIT) { - copy_id((uint8_t*) &destination[index], sender_bus_id, 4); + if(info.header & PJON_TX_INFO_BIT) { + copy_id((uint8_t*) &destination[index], info.tx.bus_id, 4); index += 4; } } - #else - (void)sender_bus_id; - (void)receiver_bus_id; #endif - if(header & PJON_TX_INFO_BIT) destination[index++] = sender_id; + if(info.header & PJON_TX_INFO_BIT) destination[index++] = info.tx.id; #if(PJON_INCLUDE_PACKET_ID) - if(header & PJON_PACKET_ID_BIT) { - destination[index++] = (uint8_t)(packet_id >> 8); - destination[index++] = (uint8_t)packet_id; + if(info.header & PJON_PACKET_ID_BIT) { + destination[index++] = (uint8_t)(info.id >> 8); + destination[index++] = (uint8_t)info.id; } #else - (void)packet_id; // Avoid unused variable compiler warning + (void)info.id; // Avoid unused variable compiler warning #endif - if(header & PJON_PORT_BIT) { - if(destination_port != PJON_BROADCAST) { - destination[index++] = (uint8_t)(destination_port >> 8); - destination[index++] = (uint8_t)destination_port; - } else if(source_port != PJON_BROADCAST) { - destination[index++] = (uint8_t)(source_port >> 8); - destination[index++] = (uint8_t)source_port; + if(info.header & PJON_PORT_BIT) { + if(info.port != PJON_BROADCAST) { + destination[index++] = (uint8_t)(info.port >> 8); + destination[index++] = (uint8_t)info.port; } } + #if(PJON_INCLUDE_MAC) + if(info.header & PJON_MAC_BIT) { + copy_id(&destination[index], info.rx.mac, 6); + index += 6; + copy_id(&destination[index], info.tx.mac, 6); + index += 6; + } + #endif memcpy(destination + index, source, length); - if(header & PJON_CRC_BIT) { + if(info.header & PJON_CRC_BIT) { uint32_t computed_crc = PJON_crc32::compute((uint8_t *)destination, new_length - 4); destination[new_length - 4] = @@ -348,23 +354,22 @@ struct PJONTools { static void parse_header(const uint8_t *packet, PJON_Packet_Info &info) { memset(&info, 0, sizeof info); uint8_t index = 0; - info.receiver_id = packet[index++]; + info.rx.id = packet[index++]; bool extended_length = packet[index] & PJON_EXT_LEN_BIT; info.header = packet[index++]; index += extended_length + 2; // + LENGTH + HEADER CRC #ifndef PJON_LOCAL if(info.header & PJON_MODE_BIT) { - copy_id(info.receiver_bus_id, packet + index, 4); + copy_id(info.rx.bus_id, packet + index, 4); index += 4; if(info.header & PJON_TX_INFO_BIT) { - copy_id(info.sender_bus_id, packet + index, 4); + copy_id(info.tx.bus_id, packet + index, 4); index += 4; - } else copy_id(info.sender_bus_id, localhost(), 4); - } else copy_id(info.receiver_bus_id, localhost(), 4); + } + } #endif if(info.header & PJON_TX_INFO_BIT) - info.sender_id = packet[index++]; - else info.sender_id = 0; + info.tx.id = packet[index++]; #if(PJON_INCLUDE_PACKET_ID) if(info.header & PJON_PACKET_ID_BIT) { info.id = (packet[index] << 8) | (packet[index + 1] & 0xFF); @@ -373,8 +378,14 @@ struct PJONTools { #else info.id = 0; #endif - if(info.header & PJON_PORT_BIT) + if(info.header & PJON_PORT_BIT) { info.port = (packet[index] << 8) | (packet[index + 1] & 0xFF); - else info.port = PJON_BROADCAST; + index += 2; + } + #if(PJON_INCLUDE_MAC) + copy_id(info.rx.mac, packet + index, 6); + index += 6; + copy_id(info.tx.mac, packet + index, 6); + #endif }; }; From c2a414fd38bc52f827950b17a7d33aa3a6ad6b74 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Apr 2020 12:17:50 +0200 Subject: [PATCH 006/323] examples and strategies updated --- .../Surrogate/Surrogate.ino | 10 ++++----- .../SWBB-MQTT-Gateway/Gateway/Gateway.ino | 12 +++++----- .../Receiver/Receiver.ino | 4 ++-- .../Receiver/Receiver.ino | 4 ++-- .../SendArbitraryValues/Receiver/Receiver.ino | 4 ++-- .../HC-12-LocalChat/HC-12-LocalChat.ino | 6 ++--- .../Surrogate/Surrogate.ino | 8 +++---- .../Device1/Device1.ino | 20 ++++++++--------- .../Device2/Device2.ino | 20 ++++++++--------- .../BlinkTest/Receiver/Receiver.ino | 20 ++++++++--------- .../LongPacketCRC32/Receiver/Receiver.ino | 22 +++++++++---------- .../PortsUseExample/Receiver/Receiver.ino | 20 ++++++++--------- .../SendArbitraryValues/Receiver/Receiver.ino | 20 ++++++++--------- .../SpeedTest/Receiver/Receiver.ino | 22 +++++++++---------- src/strategies/DualUDP/DualUDP.h | 12 +++++----- src/strategies/ESPNOW/ESPNOW.h | 2 +- src/strategies/GlobalUDP/GlobalUDP.h | 2 +- src/strategies/MQTTTranslate/MQTTTranslate.h | 12 +++++----- 18 files changed, 110 insertions(+), 110 deletions(-) diff --git a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino index dd27c61cab..c2e2677c9c 100644 --- a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino +++ b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino @@ -56,8 +56,8 @@ void setup() { void receiver_functionA(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { // Forward packet to RemoteWorker on bus B, preserving the original sender id busB.send_from_id( - packet_info.sender_id, - packet_info.sender_bus_id, + packet_info.tx.id, + packet_info.tx.bus_id, DEVICE_ID, PJONTools::localhost(), (uint8_t *)payload, @@ -73,8 +73,8 @@ void receiver_functionB(uint8_t *payload, uint16_t length, const PJON_Packet_Inf // single_initiate_direction listening mode. // Forward packet to specified target device on bus A busA.send_packet_blocking( - packet_info.receiver_id, - packet_info.receiver_bus_id, + packet_info.rx.id, + packet_info.rx.bus_id, (uint8_t *)payload, length, packet_info.header, @@ -97,4 +97,4 @@ void loop() { Serial.print(F("CONNECT COUNT: ")); Serial.println(busB.strategy.link.get_connection_count()); } -}; \ No newline at end of file +}; diff --git a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino index fd852c995c..505011b93e 100644 --- a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino +++ b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino @@ -23,15 +23,15 @@ bool router = false; void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { const char *msg = (const char *)payload; // Forward to MQTT topic pjon/device45/output if from device 45 - mqtt.send_from_id(packet_info.sender_id, PJONTools::localhost(), - packet_info.receiver_id, PJONTools::localhost(), + mqtt.send_from_id(packet_info.tx.id, PJONTools::localhost(), + packet_info.rx.id, PJONTools::localhost(), payload, length, packet_info.header, packet_info.id, packet_info.port); - cnt_to_mqtt++; + cnt_to_mqtt++; }; void receiver_function_mqtt(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { // Send to device 45 if source topic is pjon/device45/input - bus.send(packet_info.receiver_id, payload, length); + bus.send(packet_info.rx.id, payload, length); cnt_from_mqtt++; }; @@ -64,8 +64,8 @@ void loop() { if(millis() - start > 1000) { start = millis(); - Serial.print("Routed packets to MQTT: "); Serial.print(cnt_to_mqtt); + Serial.print("Routed packets to MQTT: "); Serial.print(cnt_to_mqtt); Serial.print(", from MQTT: "); Serial.println(cnt_from_mqtt); cnt_from_mqtt = cnt_to_mqtt = 0; } -}; \ No newline at end of file +}; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino index 9b45ae532e..e24aaea759 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino @@ -36,9 +36,9 @@ void loop() { if(length) { uint8_t *payload = bus.get_payload(data); Serial.print("Receiver device id: "); - Serial.print(info.receiver_id); + Serial.print(info.rx.id); Serial.print(" | Transmitter device id: "); - Serial.println(info.sender_id); + Serial.println(info.tx.id); /* Copy received data in buffer */ memcpy(&r, payload, sizeof(r)); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Receiver/Receiver.ino index 0bddba7584..be630af822 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Receiver/Receiver.ino @@ -20,9 +20,9 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info /* Make use of the payload before sending something, the buffer where payload points to is overwritten when a new message is dispatched */ Serial.print("Receiver device id: "); - Serial.print(packet_info.receiver_id); + Serial.print(packet_info.rx.id); Serial.print(" | Transmitter device id: "); - Serial.println(packet_info.sender_id); + Serial.println(packet_info.tx.id); /* Copy received data in buffer */ memcpy(&r, payload, sizeof(r)); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino index a8ba65c515..7b1d7ed84b 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino @@ -15,10 +15,10 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info overwritten when a new message is dispatched */ Serial.print("RX:"); Serial.print(" Device id: "); - Serial.print(packet_info.receiver_id); + Serial.print(packet_info.rx.id); Serial.print(" | TX: "); Serial.print(" Device id: "); - Serial.print(packet_info.sender_id); + Serial.print(packet_info.tx.id); if((char)payload[0] == 'V') { Serial.print(" | Voltage: "); diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino index 6621d40c2f..586761b43e 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino @@ -56,10 +56,10 @@ uint8_t recipient = 0; void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { // Received messages sender id and content are printed here - if(packet_info.sender_id == recipient || packet_info.sender_id == PJON_BROADCAST) { + if(packet_info.tx.id == recipient || packet_info.tx.id == PJON_BROADCAST) { Serial.print("user "); - Serial.print(packet_info.sender_id); - Serial.print((packet_info.receiver_id == PJON_BROADCAST) ? " " : ": "); + Serial.print(packet_info.tx.id); + Serial.print((packet_info.rx.id == PJON_BROADCAST) ? " " : ": "); for(uint16_t i = 0; i < length; i++) Serial.print((char)payload[i]); Serial.println(); diff --git a/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino b/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino index f6171e7417..9ddcf82bfb 100644 --- a/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino +++ b/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino @@ -63,8 +63,8 @@ void setup() { void receiver_functionA(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { // Forward packet to RemoteWorker on bus B, preserving the original sender id busB.send_from_id( - packet_info.sender_id, - packet_info.sender_bus_id, + packet_info.tx.id, + packet_info.tx.bus_id, DEVICE_ID, PJONTools::localhost(), (uint8_t *)payload, @@ -81,8 +81,8 @@ void receiver_functionB(uint8_t *payload, uint16_t length, const PJON_Packet_Inf // single_initiate_direction listening mode. // Forward packet to specified target device on bus A busA.send_packet_blocking( - packet_info.receiver_id, - packet_info.receiver_bus_id, + packet_info.rx.id, + packet_info.rx.bus_id, (uint8_t *)payload, length, packet_info.header, diff --git a/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino b/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino index 5c7ba17ac2..65d9c8dd1c 100644 --- a/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino +++ b/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino @@ -10,20 +10,20 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info /* Make use of the payload before sending something, the buffer where payload points to is overwritten when a new message is dispatched */ Serial.print("Receiver bus id: "); - Serial.print(packet_info.receiver_bus_id[0]); - Serial.print(packet_info.receiver_bus_id[1]); - Serial.print(packet_info.receiver_bus_id[2]); - Serial.print(packet_info.receiver_bus_id[3]); + Serial.print(packet_info.rx.bus_id[0]); + Serial.print(packet_info.rx.bus_id[1]); + Serial.print(packet_info.rx.bus_id[2]); + Serial.print(packet_info.rx.bus_id[3]); Serial.print(" - device id: "); - Serial.println(packet_info.receiver_id); + Serial.println(packet_info.rx.id); Serial.print("Sender bus id: "); - Serial.print(packet_info.sender_bus_id[0]); - Serial.print(packet_info.sender_bus_id[1]); - Serial.print(packet_info.sender_bus_id[2]); - Serial.print(packet_info.sender_bus_id[3]); + Serial.print(packet_info.tx.bus_id[0]); + Serial.print(packet_info.tx.bus_id[1]); + Serial.print(packet_info.tx.bus_id[2]); + Serial.print(packet_info.tx.bus_id[3]); Serial.print(" - device id: "); - Serial.println(packet_info.sender_id); + Serial.println(packet_info.tx.id); if((char)payload[0] == 'B') { digitalWrite(LED_BUILTIN, HIGH); diff --git a/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino b/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino index 0a05e8afa3..d20e5b2b6c 100644 --- a/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino +++ b/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino @@ -10,20 +10,20 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info /* Make use of the payload before sending something, the buffer where payload points to is overwritten when a new message is dispatched */ Serial.print("Receiver bus id: "); - Serial.print(packet_info.receiver_bus_id[0]); - Serial.print(packet_info.receiver_bus_id[1]); - Serial.print(packet_info.receiver_bus_id[2]); - Serial.print(packet_info.receiver_bus_id[3]); + Serial.print(packet_info.rx.bus_id[0]); + Serial.print(packet_info.rx.bus_id[1]); + Serial.print(packet_info.rx.bus_id[2]); + Serial.print(packet_info.rx.bus_id[3]); Serial.print(" - device id: "); - Serial.println(packet_info.receiver_id); + Serial.println(packet_info.rx.id); Serial.print("Sender bus id: "); - Serial.print(packet_info.sender_bus_id[0]); - Serial.print(packet_info.sender_bus_id[1]); - Serial.print(packet_info.sender_bus_id[2]); - Serial.print(packet_info.sender_bus_id[3]); + Serial.print(packet_info.tx.bus_id[0]); + Serial.print(packet_info.tx.bus_id[1]); + Serial.print(packet_info.tx.bus_id[2]); + Serial.print(packet_info.tx.bus_id[3]); Serial.print(" - device id: "); - Serial.println(packet_info.sender_id); + Serial.println(packet_info.tx.id); if((char)payload[0] == 'B') { digitalWrite(LED_BUILTIN, HIGH); diff --git a/examples/ARDUINO/Network/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino index 05932278e6..82b9cab0a3 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino @@ -10,20 +10,20 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info /* Make use of the payload before sending something, the buffer where payload points to is overwritten when a new message is dispatched */ Serial.print("Receiver bus id: "); - Serial.print(packet_info.receiver_bus_id[0]); - Serial.print(packet_info.receiver_bus_id[1]); - Serial.print(packet_info.receiver_bus_id[2]); - Serial.print(packet_info.receiver_bus_id[3]); + Serial.print(packet_info.rx.bus_id[0]); + Serial.print(packet_info.rx.bus_id[1]); + Serial.print(packet_info.rx.bus_id[2]); + Serial.print(packet_info.rx.bus_id[3]); Serial.print(" - device id: "); - Serial.println(packet_info.receiver_id); + Serial.println(packet_info.rx.id); Serial.print("Sender bus id: "); - Serial.print(packet_info.sender_bus_id[0]); - Serial.print(packet_info.sender_bus_id[1]); - Serial.print(packet_info.sender_bus_id[2]); - Serial.print(packet_info.sender_bus_id[3]); + Serial.print(packet_info.tx.bus_id[0]); + Serial.print(packet_info.tx.bus_id[1]); + Serial.print(packet_info.tx.bus_id[2]); + Serial.print(packet_info.tx.bus_id[3]); Serial.print(" - device id: "); - Serial.println(packet_info.sender_id); + Serial.println(packet_info.tx.id); if(payload[0] == 'B') { Serial.println(" BLINK!"); diff --git a/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino index 2a29ce1ab8..9dc246a29f 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino @@ -36,25 +36,25 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info // If packet formatted for a shared medium if(packet_info.header & PJON_MODE_BIT) { Serial.print(" Receiver bus id: "); - Serial.print(packet_info.receiver_bus_id[0]); - Serial.print(packet_info.receiver_bus_id[1]); - Serial.print(packet_info.receiver_bus_id[2]); - Serial.print(packet_info.receiver_bus_id[3]); + Serial.print(packet_info.rx.bus_id[0]); + Serial.print(packet_info.rx.bus_id[1]); + Serial.print(packet_info.rx.bus_id[2]); + Serial.print(packet_info.rx.bus_id[3]); Serial.print(" Device id: "); - Serial.print(packet_info.receiver_id); + Serial.print(packet_info.rx.id); // If sender info is included if((packet_info.header & PJON_TX_INFO_BIT) != 0) { Serial.print(" Sender bus id: "); - Serial.print(packet_info.sender_bus_id[0]); - Serial.print(packet_info.sender_bus_id[1]); - Serial.print(packet_info.sender_bus_id[2]); - Serial.print(packet_info.sender_bus_id[3]); + Serial.print(packet_info.tx.bus_id[0]); + Serial.print(packet_info.tx.bus_id[1]); + Serial.print(packet_info.tx.bus_id[2]); + Serial.print(packet_info.tx.bus_id[3]); Serial.print(" device id: "); - Serial.print(packet_info.sender_id);\ + Serial.print(packet_info.tx.id);\ // If local format and sender info included } else if(packet_info.header & PJON_TX_INFO_BIT) { Serial.print(" Sender id: "); - Serial.print(packet_info.sender_id); + Serial.print(packet_info.tx.id); } } diff --git a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino index 67a209a40c..697adf6f54 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino @@ -21,25 +21,25 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info // If packet formatted for a shared medium if(packet_info.header & PJON_MODE_BIT) { Serial.print(" Receiver bus id: "); - Serial.print(packet_info.receiver_bus_id[0]); - Serial.print(packet_info.receiver_bus_id[1]); - Serial.print(packet_info.receiver_bus_id[2]); - Serial.print(packet_info.receiver_bus_id[3]); + Serial.print(packet_info.rx.bus_id[0]); + Serial.print(packet_info.rx.bus_id[1]); + Serial.print(packet_info.rx.bus_id[2]); + Serial.print(packet_info.rx.bus_id[3]); Serial.print(" Receiver id: "); - Serial.print(packet_info.receiver_id); + Serial.print(packet_info.rx.id); // If sender info is included if(packet_info.header & PJON_TX_INFO_BIT) { Serial.print(" Sender bus id: "); - Serial.print(packet_info.sender_bus_id[0]); - Serial.print(packet_info.sender_bus_id[1]); - Serial.print(packet_info.sender_bus_id[2]); - Serial.print(packet_info.sender_bus_id[3]); + Serial.print(packet_info.tx.bus_id[0]); + Serial.print(packet_info.tx.bus_id[1]); + Serial.print(packet_info.tx.bus_id[2]); + Serial.print(packet_info.tx.bus_id[3]); } } // If sender device id is included if(packet_info.header & PJON_TX_INFO_BIT) { Serial.print(" Sender id: "); - Serial.print(packet_info.sender_id); + Serial.print(packet_info.tx.id); } // Payload Length Serial.print(" Length: "); diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino index f539b7b9e4..723b162b45 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino @@ -18,21 +18,21 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info overwritten when a new message is dispatched */ Serial.print("RX:"); Serial.print(" Bus id: "); - Serial.print(packet_info.receiver_bus_id[0]); - Serial.print(packet_info.receiver_bus_id[1]); - Serial.print(packet_info.receiver_bus_id[2]); - Serial.print(packet_info.receiver_bus_id[3]); + Serial.print(packet_info.rx.bus_id[0]); + Serial.print(packet_info.rx.bus_id[1]); + Serial.print(packet_info.rx.bus_id[2]); + Serial.print(packet_info.rx.bus_id[3]); Serial.print(" Device id: "); - Serial.print(packet_info.receiver_id); + Serial.print(packet_info.rx.id); Serial.print(" | TX: "); Serial.print("Bus id: "); - Serial.print(packet_info.sender_bus_id[0]); - Serial.print(packet_info.sender_bus_id[1]); - Serial.print(packet_info.sender_bus_id[2]); - Serial.print(packet_info.sender_bus_id[3]); + Serial.print(packet_info.tx.bus_id[0]); + Serial.print(packet_info.tx.bus_id[1]); + Serial.print(packet_info.tx.bus_id[2]); + Serial.print(packet_info.tx.bus_id[3]); Serial.print(" Device id: "); - Serial.print(packet_info.sender_id); + Serial.print(packet_info.tx.id); if((char)payload[0] == 'V') { Serial.print(" | Voltage: "); diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino index b3958fc398..d792f86854 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino @@ -21,25 +21,25 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info // If packet formatted for a shared medium if(packet_info.header & PJON_MODE_BIT) { Serial.print(" Receiver bus id: "); - Serial.print(packet_info.receiver_bus_id[0]); - Serial.print(packet_info.receiver_bus_id[1]); - Serial.print(packet_info.receiver_bus_id[2]); - Serial.print(packet_info.receiver_bus_id[3]); + Serial.print(packet_info.rx.bus_id[0]); + Serial.print(packet_info.rx.bus_id[1]); + Serial.print(packet_info.rx.bus_id[2]); + Serial.print(packet_info.rx.bus_id[3]); Serial.print(" Device id: "); - Serial.print(packet_info.receiver_id); + Serial.print(packet_info.rx.id); // If sender info is included if((packet_info.header & PJON_TX_INFO_BIT) != 0) { Serial.print(" Sender bus id: "); - Serial.print(packet_info.sender_bus_id[0]); - Serial.print(packet_info.sender_bus_id[1]); - Serial.print(packet_info.sender_bus_id[2]); - Serial.print(packet_info.sender_bus_id[3]); + Serial.print(packet_info.tx.bus_id[0]); + Serial.print(packet_info.tx.bus_id[1]); + Serial.print(packet_info.tx.bus_id[2]); + Serial.print(packet_info.tx.bus_id[3]); Serial.print(" device id: "); - Serial.print(packet_info.sender_id);\ + Serial.print(packet_info.tx.id);\ // If local format and sender info included } else if(packet_info.header & PJON_TX_INFO_BIT) { Serial.print(" Sender id: "); - Serial.print(packet_info.sender_id); + Serial.print(packet_info.tx.id); } Serial.print(" Length: "); Serial.println(length); diff --git a/src/strategies/DualUDP/DualUDP.h b/src/strategies/DualUDP/DualUDP.h index 8fcc345b08..6ae35ceb0b 100644 --- a/src/strategies/DualUDP/DualUDP.h +++ b/src/strategies/DualUDP/DualUDP.h @@ -257,13 +257,13 @@ class DualUDP { if(length != PJON_FAIL && length > 4) { // Extract some info from the header PJONTools::parse_header(data, _packet_info); - _last_in_receiver_id = _packet_info.receiver_id; - _last_in_sender_id = _packet_info.sender_id; + _last_in_receiver_id = _packet_info.rx.id; + _last_in_sender_id = _packet_info.tx.id; // Autoregister sender if the packet was sent directly if( - _packet_info.sender_id != PJON_NOT_ASSIGNED && + _packet_info.tx.id != PJON_NOT_ASSIGNED && _last_out_sender_id != PJON_NOT_ASSIGNED && - _packet_info.receiver_id == _last_out_sender_id + _packet_info.rx.id == _last_out_sender_id ) autoregister_sender(); } return length; @@ -330,8 +330,8 @@ class DualUDP { if(length > 4) { // Extract some info from the header PJONTools::parse_header(data, _packet_info); - _last_out_receiver_id = _packet_info.receiver_id; - _last_out_sender_id = _packet_info.sender_id; + _last_out_receiver_id = _packet_info.rx.id; + _last_out_sender_id = _packet_info.tx.id; // Locate receiver in table unless it is a PJON broadcast (receiver 0) int16_t pos = -1; diff --git a/src/strategies/ESPNOW/ESPNOW.h b/src/strategies/ESPNOW/ESPNOW.h index 2fc4d1818f..2d3159e47c 100644 --- a/src/strategies/ESPNOW/ESPNOW.h +++ b/src/strategies/ESPNOW/ESPNOW.h @@ -69,7 +69,7 @@ class ESPNOW { // First get PJON sender id from incoming packet PJON_Packet_Info packet_info; PJONTools::parse_header(message, packet_info); - uint8_t sender_id = packet_info.sender_id; + uint8_t sender_id = packet_info.tx.id; if(sender_id == 0) { ESP_LOGE("ESPNOW", "AutoRegister parsing failed"); return; // If parsing fails, it will be 0 diff --git a/src/strategies/GlobalUDP/GlobalUDP.h b/src/strategies/GlobalUDP/GlobalUDP.h index 4a849bef7d..941c02777e 100644 --- a/src/strategies/GlobalUDP/GlobalUDP.h +++ b/src/strategies/GlobalUDP/GlobalUDP.h @@ -75,7 +75,7 @@ class GlobalUDP { // First get PJON sender id from incoming packet PJON_Packet_Info packet_info; PJONTools::parse_header(message, packet_info); - uint8_t sender_id = packet_info.sender_id; + uint8_t sender_id = packet_info.tx.id; if (sender_id == 0) return; // If parsing fails, it will be 0 // Then get the IP address and port number of the sender diff --git a/src/strategies/MQTTTranslate/MQTTTranslate.h b/src/strategies/MQTTTranslate/MQTTTranslate.h index c213681922..8bbc7c8adb 100644 --- a/src/strategies/MQTTTranslate/MQTTTranslate.h +++ b/src/strategies/MQTTTranslate/MQTTTranslate.h @@ -395,18 +395,18 @@ class MQTTTranslate { if (p-mqttclient.topic_buf()+7+3+7 >= SMCTOPICSIZE) return; strcpy(p, "/device"); p += 7; #if (MQTTT_MODE == MQTTT_MODE_MIRROR_TRANSLATE || MQTTT_MODE == MQTTT_MODE_MIRROR_DIRECT) - p += mqttclient.uint8toa(_packet_info.sender_id, p); + p += mqttclient.uint8toa(_packet_info.tx.id, p); strcat(p, "/output"); // Like pjon/device44/output p = &p[strlen(p)]; // End of /output #else // One of the bus modes, publish to receiver device - mqttclient.uint8toa(_packet_info.receiver_id, p); + mqttclient.uint8toa(_packet_info.rx.id, p); #endif #endif #if (MQTTT_MODE != MQTTT_MODE_BUS_RAW) uint8_t overhead = PJONTools::packet_overhead(_packet_info.header); - uint8_t crc_size = PJONTools::crc_overhead(_packet_info.header); + uint8_t crc_size = PJONTools::crc_overhead(_packet_info.header); #endif - + // Re-compose packet in other modes than RAW #if (MQTTT_MODE == MQTTT_MODE_MIRROR_TRANSLATE) // Split into multiple topics (must assume a specific payload format to parse): @@ -447,9 +447,9 @@ class MQTTTranslate { p = (char *) packet_buffer; if (6+3+8+3+9+payload_len+2 >= MQTTT_BUFFER_SIZE) return; strcpy(p, "{\"to\":"); p += 6; - p += mqttclient.uint8toa(_packet_info.receiver_id, p); + p += mqttclient.uint8toa(_packet_info.rx.id, p); strcpy(p, ",\"from\":"); p+= 8; - p += mqttclient.uint8toa(_packet_info.sender_id, p); + p += mqttclient.uint8toa(_packet_info.tx.id, p); strcpy(p, ",\"data\":\""); p+= 9; uint8_t payload_len = length - overhead; strncpy(p, (const char*)&data[overhead - crc_size], payload_len); p[payload_len] = 0; From 152ef3cf8b3bb16410e913f6058e4666ffcd55f2 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Apr 2020 12:18:15 +0200 Subject: [PATCH 007/323] comments updated --- src/PJON.h | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 0cd71e4592..596da4e63d 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -657,30 +657,32 @@ class PJON { }; /* Configure synchronous acknowledge presence: - TRUE: Send 1 byte synchronous acknowledge when a packet is received - FALSE: Avoid acknowledge transmission */ + state = true -> Request 8 bits synchronous acknowledgement + state = false -> Do not request synchronous acknowledgement */ void set_synchronous_acknowledge(bool state) { set_config_bit(state, PJON_ACK_REQ_BIT); }; /* Configure CRC selected for packet checking: - TRUE: CRC32, FALSE: CRC8 */ + state = true -> CRC32 + state = false -> CRC8 */ void set_crc_32(bool state) { set_config_bit(state, PJON_CRC_BIT); }; /* Set communication mode: - Passing PJON_SIMPLEX communication is mono-directional - Padding PJON_HALF_DUPLEX communication is bi-directional */ + mode = PJON_SIMPLEX -> communication is mono-directional + mode = PJON_HALF_DUPLEX -> communication is bi-directional */ void set_communication_mode(uint8_t mode) { _mode = mode; }; /* Configure packet id presence: - TRUE: include packet id, FALSE: Avoid packet id inclusion */ + state = true -> Include 16 bits packet id + state = false -> Avoid packet id inclusion */ void set_packet_id(bool state) { set_config_bit(state, PJON_PACKET_ID_BIT); @@ -730,8 +732,9 @@ class PJON { }; /* Configure sender's information inclusion in the packet. - TRUE: +1 byte (device id) local, +5 bytes (bus id + device id) shared - FALSE: No inclusion -1 byte overhead in local, -5 in shared + state = true -> +8 bits (device id) in local mode + +40 bits (bus id + device id) in shared mode + state = false -> No overhead added If you don't need the sender info disable the inclusion to reduce overhead and higher communication speed. */ @@ -749,16 +752,16 @@ class PJON { } /* Configure the bus network behaviour. - TRUE: Include 4 bytes bus id or group identification. - FALSE: Use only 1 byte local device identification. */ + state = true -> Include 32 bits bus id or group identification. + state = false -> Use only a 8 bits local device identification. */ void set_shared_network(bool state) { set_config_bit(state, PJON_MODE_BIT); }; - /* Set if delivered or undeliverable packets are auto deleted: - TRUE: Automatic deletion - FALSE: No packet deleted from buffer, (deletion from buffer by user) */ + /* Set if packets are automatically deleted in case of success or failure: + state = true -> Packets are deleted automatically + state = false -> Packets are not deleted */ void set_packet_auto_deletion(bool state) { _auto_delete = state; @@ -779,8 +782,8 @@ class PJON { }; /* Configure if device acts as a router: - TRUE: device receives messages only for its bus and device id - FALSE: receiver function is always called if data is received */ + state = true -> All packets are received (acknowledgement not sent) + state = false -> Normal operation */ void set_router(bool state) { _router = state; From 619105dd8b8a2caf4ae3e24a152b3bfa98e1cd9e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Apr 2020 12:35:18 +0200 Subject: [PATCH 008/323] First MAC example added --- .../BlinkTestMAC/Receiver/Receiver.ino | 34 +++++++++++++++++++ .../BlinkTestMAC/Transmitter/Transmitter.ino | 20 +++++++++++ 2 files changed, 54 insertions(+) create mode 100644 examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Receiver/Receiver.ino create mode 100644 examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Transmitter/Transmitter.ino diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Receiver/Receiver.ino new file mode 100644 index 0000000000..c2142ed645 --- /dev/null +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Receiver/Receiver.ino @@ -0,0 +1,34 @@ +#define PJON_INCLUDE_SWBB true +#define PJON_INCLUDE_MAC true +#include + +// bus(mac address of the network interface) +const uint8_t mac[6] = {1, 2, 3, 4, 5, 6}; +PJON bus(mac); + +void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { + /* Make use of the payload before sending something, the buffer where payload points to is + overwritten when a new message is dispatched */ + if(payload[0] == 'B') { + Serial.print("BLINK sent by MAC "); + for(uint8_t i = 0; i < 6; i++) + Serial.print(packet_info.tx.mac[i], DEC); + Serial.println(); + digitalWrite(LED_BUILTIN, HIGH); + delay(30); + digitalWrite(LED_BUILTIN, LOW); + } +}; + +void setup() { + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, LOW); // Initialize LED 13 to be off + bus.strategy.set_pin(12); + bus.begin(); + bus.set_receiver(receiver_function); + Serial.begin(115200); +}; + +void loop() { + bus.receive(1000); +}; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Transmitter/Transmitter.ino new file mode 100644 index 0000000000..9a1a655748 --- /dev/null +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Transmitter/Transmitter.ino @@ -0,0 +1,20 @@ +#define PJON_INCLUDE_MAC true +#include + +// bus(mac address of the network interface) +const uint8_t mac[6] = {2, 3, 4, 5, 6, 7}; +const uint8_t rx_mac[6] = {1, 2, 3, 4, 5, 6}; +PJON bus(mac); + +void setup() { + bus.strategy.set_pin(12); + bus.begin(); + PJON_Packet_Info info; + info.header = bus.config | PJON_MAC_BIT; + memcpy(info.rx.mac, rx_mac, 6); + bus.send_repeatedly(info, "B", 1, 1000000); // Send B to MAC 1,2,3,4,5,6 every second +} + +void loop() { + bus.update(); +}; From 732537f220cf586d9716196544a2458a99c37203 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Apr 2020 15:11:38 +0200 Subject: [PATCH 009/323] PJONLocal update --- src/PJONLocal.h | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/src/PJONLocal.h b/src/PJONLocal.h index 33f15c9040..a5214734b1 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -119,19 +119,16 @@ class PJONLocal { uint16_t packet_id = 0, uint16_t rx_port = PJON_BROADCAST ) { - uint16_t l = PJONTools::compose_packet( - _device_id, - PJONTools::localhost(), - id, - PJONTools::localhost(), - destination, - source, - length, - (header == PJON_NO_HEADER) ? config : header, - (!packet_id) ? PJONTools::new_packet_id(_packet_id_seed++) : packet_id, - rx_port, - port - ); + PJON_Packet_Info info; + info.rx.id = id; + info.tx.id = _device_id; + info.header = (header == PJON_NO_HEADER) ? config : header; + if(!packet_id && (info.header & PJON_PACKET_ID_BIT)) + info.id = PJONTools::new_packet_id(_packet_id_seed++); + else info.id = packet_id; + info.port = (rx_port == PJON_BROADCAST) ? port : rx_port; + uint16_t l = + PJONTools::compose_packet(info, destination, source, length); return l; }; @@ -181,15 +178,12 @@ class PJONLocal { if(i == 1) { if( (buffer[1] & PJON_MODE_BIT) || - (buffer[1] & PJON_ACK_MODE_BIT) || ( - (buffer[0] == PJON_BROADCAST) && - (buffer[1] & PJON_ACK_REQ_BIT) + (buffer[1] & PJON_MAC_BIT) || ( + (buffer[0] == PJON_BROADCAST) && (buffer[1] & PJON_ACK_REQ_BIT) ) || ( - (buffer[1] & PJON_EXT_LEN_BIT) && - !(buffer[1] & PJON_CRC_BIT) + (buffer[1] & PJON_EXT_LEN_BIT) && !(buffer[1] & PJON_CRC_BIT) ) || ( - !PJON_INCLUDE_PACKET_ID && - (buffer[1] & PJON_PACKET_ID_BIT) + !PJON_INCLUDE_PACKET_ID && (buffer[1] & PJON_PACKET_ID_BIT) ) ) return 0; extended_length = buffer[i] & PJON_EXT_LEN_BIT; From 8682330f4fc03ced718c3619dd7ee6e1f33f3906 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Apr 2020 22:31:56 +0200 Subject: [PATCH 010/323] Hop count feature added (breaking compatibility) --- src/PJON.h | 1 + src/PJONDefines.h | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/PJON.h b/src/PJON.h index 596da4e63d..5989a37b3d 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -464,6 +464,7 @@ class PJON { ) { PJON_End_Point original_end_point = tx; tx = info.tx; + if(++info.hops > PJON_MAX_HOPS) return PJON_FAIL; uint16_t result = PJON_FAIL; #if(PJON_MAX_PACKETS > 0) result = dispatch(info, payload, length); diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 46a8b5de5e..4f812632e1 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -122,6 +122,11 @@ limitations under the License. */ /* Constraints: */ +/* Maximum amount of routers a packet can pass before being discarded: */ +#ifndef PJON_MAX_HOPS + #define PJON_MAX_HOPS 15 +#endif + /* Packet buffer length, if full PJON_PACKETS_BUFFER_FULL error is thrown. The packet buffer is preallocated, so its length strongly affects memory consumption */ @@ -190,6 +195,7 @@ struct PJON_Packet_Info { uint16_t port = PJON_BROADCAST; #ifndef PJON_LOCAL void *custom_pointer; + uint8_t hops = 0; #endif }; @@ -221,7 +227,7 @@ struct PJONTools { return ( ( (header & PJON_MODE_BIT) ? - (header & PJON_TX_INFO_BIT ? 10 : 5) : + (header & PJON_TX_INFO_BIT ? 11 : 6) : (header & PJON_TX_INFO_BIT ? 2 : 1) ) + (header & PJON_EXT_LEN_BIT ? 2 : 1) + (header & PJON_CRC_BIT ? 4 : 1) @@ -307,6 +313,7 @@ struct PJONTools { copy_id((uint8_t*) &destination[index], info.tx.bus_id, 4); index += 4; } + destination[index++] = info.hops; } #endif if(info.header & PJON_TX_INFO_BIT) destination[index++] = info.tx.id; @@ -366,6 +373,7 @@ struct PJONTools { copy_id(info.tx.bus_id, packet + index, 4); index += 4; } + info.hops = packet[index++]; } #endif if(info.header & PJON_TX_INFO_BIT) From f4575fa91fa721ac446c5f222ba5a6563cb60786 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Apr 2020 23:45:44 +0200 Subject: [PATCH 011/323] PJON specification v4.0 added --- README.md | 4 +- documentation/addressing.md | 2 +- documentation/configuration.md | 6 +- specification/PJON-network-services-list.md | 2 +- ...protocol-acknowledge-specification-v2.0.md | 4 +- .../PJON-protocol-specification-v4.0.md | 334 ++++++++++++++++++ ...FSP-frame-separation-specification-v1.0.md | 2 +- .../PJON-protocol-specification-v3.2.md | 9 +- .../specification/PJDLS-specification-v2.0.md | 2 +- src/strategies/MQTTTranslate/MQTTTranslate.h | 2 +- .../specification/PJDLR-specification-v3.0.md | 2 +- .../specification/PJDL-specification-v4.1.md | 2 +- .../specification/TSDL-specification-v2.1.md | 2 +- .../specification/TSDL-specification-v2.1.md | 2 +- 14 files changed, 355 insertions(+), 20 deletions(-) create mode 100644 specification/PJON-protocol-specification-v4.0.md rename specification/{ => obsolete}/PJON-protocol-specification-v3.2.md (96%) diff --git a/README.md b/README.md index 61ac521b31..930bef6d58 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ PJON® (Padded Jittering Operative Network) is an arduino-compatible, multi-mast [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) PJON is used in thousands of devices and its community has spread worldwide because of the following 5 key factors: -- **New technology**: [PJON](specification/PJON-protocol-specification-v3.2.md) is an experimental network protocol stack crafted in 10 years of research and experimentation. It was originally developed as an open-source alternative to i2c and 1-Wire but during development its scope and features have been extended to cover use cases where IP is generally applied. PJON has been engineered to have a variable footprint (4.2-8.2 kB program memory) and overhead (5-22 bytes per packet) depending on its configuration. +- **New technology**: [PJON](specification/PJON-protocol-specification-v4.0.md) is an experimental network protocol stack crafted in 10 years of research and experimentation. It was originally developed as an open-source alternative to i2c and 1-Wire but during development its scope and features have been extended to cover use cases where IP is generally applied. PJON has been engineered to have a variable footprint (4.2-8.2 kB program memory) and overhead (5-22 bytes per packet) depending on its configuration. - **Multi-media support**: PJON operates on a wide range of media and protocols like TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485 and LoRa. The PJON network protocol stack specifies and implements also [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) able to communicate data over a single wire shared by up to 255 devices, [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) able to operate with many ASK/FSK/OOK radio modules and also [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md), able to communicate wirelessly with light pulses using off the shelf LEDs and laser diodes. - **Increased reliability**: Many protocols massively applied worldwide expose dangerous vulnerabilities, have weak error detection algorithms and are not resilient to interference. PJON is based on years of analysis and study not to make the same mistakes present in most alternatives and provide with a set of simpler and more efficient solutions. - **High flexibility**: PJON is totally software-defined and its implementation is designed to be easily extensible. it builds out-of-the-box in all supported devices and operates transparently on top of any supported protocol or medium. @@ -25,7 +25,7 @@ PJON is used in thousands of devices and its community has spread worldwide beca - Error handling ### Specifications -- [PJON v3.2](specification/PJON-protocol-specification-v3.2.md) +- [PJON v4.0](specification/PJON-protocol-specification-v4.0.md) - [PJON Acknowledge v1.0](specification/PJON-protocol-acknowledge-specification-v1.0.md) - [PJDL v4.1](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) - [PJDLR v3.0](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS v2.0](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) - [TSDL v2.1](src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) diff --git a/documentation/addressing.md b/documentation/addressing.md index b84d5f9269..96f8a7d5b7 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -11,7 +11,7 @@ --- ## Addressing -PJON objects can operate in local or shared mode. The PJON protocol v3.2 in [local](/specification/PJON-protocol-specification-v3.2.md#local-mode) mode supports connectivity for up to 254 devices using a 8bits device identifier, in [shared](/specification/PJON-protocol-specification-v3.2.md#shared-mode) mode supports connectivity for up to 4.294.967.295 buses (groups of devices) and up to 1.090.921.692.930 devices using a 32bits bus identifier and a 8bits device identifier. +PJON objects can operate in local or shared mode. The PJON protocol v4.0 in [local](/specification/PJON-protocol-specification-v4.0.md#local-mode) mode supports connectivity for up to 254 devices using a 8bits device identifier, in [shared](/specification/PJON-protocol-specification-v4.0.md#shared-mode) mode supports connectivity for up to 4.294.967.295 buses (groups of devices) and up to 1.090.921.692.930 devices using a 32bits bus identifier and a 8bits device identifier. ### Local mode diff --git a/documentation/configuration.md b/documentation/configuration.md index bb7586a5f3..78749f8ebf 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -77,7 +77,7 @@ Before using `ESPNOW` be sure to have installed the required tools as described Before using `MQTTTranslate` be sure to have the [ReconnectingMqttClient](https://github.com/fredilarsen/ReconnectingMqttClient) library available and to have defined the `PJON_INCLUDE_MQTT` constant before including `PJON.h`. ### Network mode -The network mode can be changed with `set_shared_network` during runtime, for example moving from [local](/specification/PJON-protocol-specification-v3.2.md#local-mode) to [shared](https://github.com/gioblu/PJON/blob/master/specification/PJON-protocol-specification-v3.2.md#shared-mode) mode: +The network mode can be changed with `set_shared_network` during runtime, for example moving from [local](/specification/PJON-protocol-specification-v4.0.md#local-mode) to [shared](https://github.com/gioblu/PJON/blob/master/specification/PJON-protocol-specification-v4.0.md#shared-mode) mode: ```cpp bus.set_shared_network(true); ``` @@ -122,7 +122,7 @@ The [synchronous acknowledgement](/specification/PJON-protocol-acknowledge-speci ``` ### Packet identification -If packet duplication avoidance is required it is possible to add a 2 bytes [packet identifier](/specification/PJON-protocol-specification-v3.2.md#packet-identification) to guarantee uniqueness. +If packet duplication avoidance is required it is possible to add a 2 bytes [packet identifier](/specification/PJON-protocol-specification-v4.0.md#packet-identification) to guarantee uniqueness. define the `PJON_INCLUDE_PACKET_ID` as following. The use of a constant has been chosen to save more than 1kB on sketches where this feature is not used: ```cpp #define PJON_INCLUDE_PACKET_ID true @@ -138,7 +138,7 @@ Use `set_packet_id` to enable the packet identification feature: See the [UsePacketId](/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId) example to see more in detail how the packet id can be used. ### Network service identification -Configure the instance to include a [network service identifier](/specification/PJON-protocol-specification-v3.2.md#network-services) in the packet. Ports from 0 to 8000 are reserved to known network services which index is present in the [known network services list](/specification/PJON-network-services-list.md), ports from 8001 to 65535 are free for custom use cases: +Configure the instance to include a [network service identifier](/specification/PJON-protocol-specification-v4.0.md#network-services) in the packet. Ports from 0 to 8000 are reserved to known network services which index is present in the [known network services list](/specification/PJON-network-services-list.md), ports from 8001 to 65535 are free for custom use cases: ```cpp bus.include_port(false); // Avoid port inclusion (default) bus.include_port(true, 8001); // Include custom port diff --git a/specification/PJON-network-services-list.md b/specification/PJON-network-services-list.md index 6b46f6700b..5f178de9b9 100644 --- a/specification/PJON-network-services-list.md +++ b/specification/PJON-network-services-list.md @@ -1,7 +1,7 @@ ### Specifications index #### Network layer -- [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) +- [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - **[Network services list](/specification/PJON-network-services-list.md)** #### Data link layer diff --git a/specification/PJON-protocol-acknowledge-specification-v2.0.md b/specification/PJON-protocol-acknowledge-specification-v2.0.md index c74b003775..17f5ec00f0 100644 --- a/specification/PJON-protocol-acknowledge-specification-v2.0.md +++ b/specification/PJON-protocol-acknowledge-specification-v2.0.md @@ -1,7 +1,7 @@ ### Specifications index #### Network layer -- [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) +- [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - **[Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md)** - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer @@ -35,4 +35,4 @@ Channel analysis Transmission Response |_____||____|__________|________|____|_________|____||_____| ``` -The graph above contains a packet transmission where the character `@` (decimal 64) is sent to device id `12`. As defined by the [PJON protocol layer specification v3.2](/specification/PJON-protocol-specification-v3.2.md), the header's `ACK` bit high requests a synchronous acknowledgement response, see [PJDL v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md), [PJDLR v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md), [PJDLS v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) and [TSDL v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) specification for additional information. +The graph above contains a packet transmission where the character `@` (decimal 64) is sent to device id `12`. As defined by the [PJON protocol layer specification v4.0](/specification/PJON-protocol-specification-v4.0.md), the header's `ACK` bit high requests a synchronous acknowledgement response, see [PJDL v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md), [PJDLR v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md), [PJDLS v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) and [TSDL v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) specification for additional information. diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md new file mode 100644 index 0000000000..f8ef6e0aed --- /dev/null +++ b/specification/PJON-protocol-specification-v4.0.md @@ -0,0 +1,334 @@ +### Specifications index + +#### Network layer +- **[PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md)** +- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) +- [Network services list](/specification/PJON-network-services-list.md) +#### Data link layer +- [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) +- [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) +- [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) +- [TSDL (Tardy Serial Data Link) v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) +- [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) + +--- + +## PJON® v4.0 +``` +Invented by Giovanni Blu Mitolo +Header feature proposed by Fred Larsen +Originally published: 10/04/2010 +Latest revision: 27/04/2020 +Related work: https://github.com/gioblu/PJON/ +Compliant implementations: PJON v13.0 and following +Released into the public domain +``` +The PJON protocol v4.0 in local mode supports connectivity for up to 254 devices, in shared mode supports connectivity for up to 4.294.967.295 buses (groups of devices) and up to 1.090.921.692.930 devices. The packet format is dynamic therefore meta-data can be optionally included using the header as a bitmap of selected features. It supports interoperability between systems that use a different configuration and provides with high efficiency including only the protocol's features used and the overhead effectively required (5-35 bytes). PJON can be used for simple low-data-rate applications as an alternative to 1-Wire, i2c or CAN but can also be applied in place of IP to interconnect more complex networks. + +The graph below shows the conceptual model that characterizes and standardizes the communication. Its goal is the interoperability of diverse systems on a wide range of media with the use of a new set of Open Standards. The graph partitions represent abstraction layers. + +``` + ________________________________________________ +| 3 Network layer: PJON | +|- Optional features ----------------------------| +| Routing and switching | +| Hop count (8 bits) | +| Hardware identification (48 bits) | +| Service identification (16 bits) | +| Packet identification (16 bits) | +| Bus identification (32 bits) | +| Sender identification | +| Packet transmission, maximum length 65535B | +|- Core features --------------------------------| +| Congestion control | +| Packet transmission, maximum length 255B | +| Error detection (16 or 40 bits) | +| Device identification (8 bits) | +| Broadcast | +|________________________________________________| +| 2 Data link layer: PJDL, PJDLR, PJDLS, TSDL | +| Synchronous acknowledgement | +| Frame transmission | +| Medium access control | +|________________________________________________| +| 1 Physical layer: | +| Electric, radio or light impulses | +|________________________________________________| +``` + +### Basic concepts +* Packet transmission is regulated by a 8 bits header +* Devices communicate using packets with a maximum length of 255 or 65535 bytes +* Devices are identified by a unique 8 bits device id +* Buses are identified with a 32 bits bus id +* A synchronous acknowledgement can be requested (see [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md)) +* Packets can be optionally identified with a 16 bits packet id +* Network services are optionally identified with a 16 bits port id +* Hardware can be optionally identified using a MAC address + +### Bus +A PJON bus is a group of up to 254 devices. Devices use PJON packets to communicate with each other. Devices can send packets and optionally request a synchronous acknowledgement. Devices can also broadcast packets. When the device id is not known, devices must use id 255. +```cpp + _______ _______ _______ _______ +| | | | | | | | +| ID 1 | | ID 2 | | ID 3 | | ID 4 | +|_______| |_______| |_______| |_______| +____|___________|___________|___________|___ + ___|___ ___|___ ___|___ + | | | | | | + | ID 5 | | ID 6 | | ID 7 | + |_______| |_______| |_______| + +ID 0 = BROADCAST +ID 255 = NOT ASSIGNED +``` + +### Bus network +A PJON bus network is composed by buses present on the same collision domain or interconnected through switches or routers. On a shared medium an additional 32 bits bus id must be used to isolate groups of devices from foreign traffic, enabling many to coexist and network on the same medium. +```cpp +TWO BUSES SHARING THE SAME MEDIUM +1 collision domain + + BUS ID 0.0.0.1 BUS ID 0.0.0.2 + _______ _______ _______ _______ +| | | | | | | | +| ID 1 | | ID 2 | | ID 1 | | ID 2 | +|_______| |_______| |_______| |_______| +______|___________|__________|___________|___ + ___|___ ___|___ + | | | | + | ID 3 | | ID 3 | + |_______| |_______| +``` + +### Switch +A Switch is a device that forwards packets transparently between connected buses. The switch can operate also if different physical layers are in use. It can rely on a default gateway to operate as a leaf in a larger tree network. +```cpp + ______ ________ ______ +| | PJDL bus | | PJDLR bus | | +| ID 1 |__________| SWITCH |___________| ID 2 | +|______| |________| |______| + +ID 254 = DEFAULT GATEWAY +``` + +### Router +A router is a device, connected to more than one PJON bus, able to route packets from a device, a bus or a medium to another. Thanks to the hop count, the bus and the device indexing, many routing techniques are supported. Packets can be routed between indirectly connected buses if a routing table or a default gateway is used. +```cpp +TWO BUSES CONNECTED THROUGH A ROUTER +2 collision domains + + BUS ID 0.0.0.1 BUS ID 0.0.0.2 + _______ _______ _______ _______ +| | | | | | | | +| ID 1 | | ID 2 | | ID 1 | | ID 2 | +|_______| |_______| ______ |_______| |_______| +_____|___________|____|ROUTER|_____|___________|____ + ___|___ | ID 3 | ___|___ + | | |______| | | + | ID 3 | | ID 3 | + |_______| |_______| +``` + +### Header configuration +The header is a bitmap of the meta-data contained and the configuration required. Unlike other protocols, PJON has a dynamic packet format designed to include in each packet only what is strictly required to carry out the exchange. Depending on the bitmap configuration a variable overhead (5-35 bytes) is added to information. +```cpp +HEADER BITMAP + 8 7 6 5 4 3 2 1 + ______ ______ ____ _____ _____ _____ _____ _____ +|PACKET|EXT. |CRC |PORT | MAC | ACK |TX |MODE | +|ID |LENGTH| | | | |INFO | | +|______|______|____|_____|_____|_____|_____|_____| +``` +1. `MODE` bit informs if the packet is formatted in [shared](/specification/PJON-protocol-specification-v4.0.md#shared-mode) (value 1) or [local](/specification/PJON-protocol-specification-v4.0.md#local-mode) mode (value 0) +2. `TX INFO` bit informs if the sender info are included (value 1) or not (value 0) +3. `ACK` bit informs if the [synchronous acknowledgement](/specification/PJON-protocol-acknowledge-specification-v1.0.md#synchronous-acknowledge) is requested (value 1) or not (value 0) +4. `MAC` bit informs if sender's and recipient's [network interface identification](/specification/PJON-protocol-specification-v4.0.md#hardware-identification), or MAC address, are included (value 1) or not (value 0) +5. `PORT` bit informs if a 16 bits [network service identifier](/specification/PJON-protocol-specification-v4.0.md#network-services) is included (value 1) or not (value 0) +6. `CRC` bit signals which CRC is used, [CRC8](/specification/PJON-protocol-specification-v4.0.md#crc8-polynomial) (value 0) or [CRC32](/specification/PJON-protocol-specification-v4.0.md#crc32-polynomial) (value 1) +7. `EXT. LENGTH` bit informs if the packet contains 8 (value 0) or 16 bits (value 1) [length](/specification/PJON-protocol-specification-v4.0.md#extended-length) +8. `PACKET ID` bit informs if the packet contains (value 1) or not (value 0) a 16 bits [packet id](/specification/PJON-protocol-specification-v4.0.md#packet-identification) + +Unacceptable header configuration states for standard transmission: +* `----1-0-` or `ACK MODE` bit high, and `TX INFO` bit low (requires transmitter info) +* `-10-----` or `EXT. LENGTH` bit high and `CRC` bit low (forced CRC32 for length > 15) + +Unacceptable header configuration states for a broadcast transmission: +* `-----1--` or `ACK` bit high (acknowledgement not supported if broadcasting) +* `----1---` or `ACK MODE` bit high (acknowledgement not supported if broadcasting) + +`-` symbol means irrelevant bit value + +### Cyclic redundancy check +PJON supports both CRC8 and CRC32 to ensure safety on a wide range of use cases and packet lengths. + +#### CRC8 polynomial +```cpp +0x97 = (x + 1)(x^7 + x^6 + x^5 + x^2 + 1)^2 +``` +`CRC8 C2`, discovered by Tsonka Baicheva, is used (in implicit +1 notation) because it has the longest possible length (119 bits) at which `HD=4` can be achieved with an 8-bit CRC. Other protocols specify the use of polynomials with much lower overall performance like `CRC-8 0xEA` or `DOWCRC 0x8C` used by 1-Wire. + +#### CRC32 polynomial +```cpp +0x82608edb = x^32 + x^26 + x^23 + x^22 + x^16 + + x^12 + x^11 + x^10 + x^8 + x^7 + + x^5 + x^4 + x^2 + x + 1 +``` +`CRC32 IEEE 802.3` bit-reversed polynomial implicit +1 notation, or `0xedb88320`, is selected for its high performance on a wide range of lengths, while also being widely evaluated and accepted as a good polynomial. + +#### Initial meta-data CRC8 +CRC8 is calculated and appended to the initial meta-data (device id, header and length) to ensure consistency and avoid the length corruption vulnerability that affects CAN (Controlled Area Network) and many other protocols. + +#### End CRC8/CRC32 +CRC8 is appended at the end of packets of up to 15 bytes length (overhead included). CRC32 is instead used if the packet's length exceeds 15 bytes but can be optionally applied in shorter packets setting the `CRC` bit high if more secure error detection is required. + +### Packet transmission +A local packet transmission is an optionally bidirectional communication between two devices that can be divided in 3 phases: **channel analysis**, **transmission** and optional **response**. In the channel analysis phase the medium's state is assessed before starting transmission to avoid collision. If the medium is free for use, the transmission phase starts in which the packet is entirely transmitted in network byte order. The receiving device computes the CRC and starts the response phase transmitting an acknowledge (decimal 6) in case of correct data reception. If no acknowledgement is received, after an exponential back-off delay, the transmitter retries until the acknowledgement is received or a maximum number of attempts is reached. + +```cpp +Channel analysis Transmission Response + _____ _______________________________________________ _____ +| C-A || ID | HEADER | LENGTH | CRC8 | DATA | CRC8 || ACK | +|-----||----|----------|--------|------|--------|------||-----| +| 0 || 12 | 00000100 | 6 | | 64 | || 6 | +|_____||____|__________|________|______|________|______||_____| + BITS: | 8 | 8 | 8 | 8 | 8 | 8 | + |____|__________|________|______|________|______| +``` + +#### Local mode +Depending on header's `MODE` bit, PJON packets can contain basic or extended support to identification. Local mode required by header's `MODE` bit low supports connectivity for up to 254 devices. In the graph below is represented the simplest local mode packet format sending `@` (decimal 64) to device `12`: + +```cpp + _________________________________ +|ID| HEADER |LENGTH|CRC8|DATA|CRC8| +|--|--------|------|----|----|----| +|12|00000000| 6 | | 64 | | +|__|________|______|____|____|____| +|8 | 8 | 8 | 8 | 8 | 8 | 48 bits +|__|________|______|____|____|____| + +``` + +In local mode packets can be broadcasted to all devices sending to device id `0`. Acknowledgement is not supported therefore any broadcasted packet that requests an acknowledgement is ignored by recipients. + +```cpp + _________________________________ +|ID| HEADER |LENGTH|CRC8|DATA|CRC8| +|--|--------|------|----|----|----| +|0 |00000000| 6 | | 64 | | +|__|________|______|____|____|____| +|8 | 8 | 8 | 8 | 8 | 8 | 48 bits +|__|________|______|____|____|____| + + +``` + +If header's `TX INFO` bit is high the sender's device id is included in the packet. In the example below device id `11` sends `@` to device id `12`. + +```cpp + ____ + | TX | + | ID | + _______________________\__/_________ +|ID| HEADER |LENGTH|CRC8|ID|DATA|CRC8| +|--|--------|------|----|--|----|----| +|12|00000010| 7 | |11| 64 | | +|__|________|______|____|__|____|____| +|8 | 8 | 8 | 8 |8 | 8 | 8 | 56 bits +|__|________|______|____|__|____|____| + + +``` + +#### Shared mode +If header's `MODE` bit is high [bus](/specification/PJON-protocol-specification-v4.0.md#bus) identification is added to the packet. The same local transmission used as an example above is formatted to be sent in shared mode to device id `12` of bus id `0.0.0.1`. The packet's payload is prepended with the bus id of the recipient and the hop count as requested by header's `MODE` bit: +```cpp + _____________________________________________ +|ID| HEADER |LENGTH|CRC8|BUS ID|HOP|DATA|CRC8| +|--|--------|------|----|------|---|----|----| +|12|00000001| 11 | | 0001 | 0 | 64 | | +|__|________|______|____|______|___|____|____| +|8 | 8 | 8 | 8 | 32 | 8 | 8 | 8 | 88 bits +|__|________|______|____|______|___|____|____| + +``` + +In shared mode packets can be broadcasted to all devices sharing the same bus id sending to device id `0`. Acknowledgement is not supported, therefore any broadcasted packet that requests an acknowledgement is ignored by recipients. + +```cpp + ____________________________________________ +|ID| HEADER |LENGTH|CRC8|BUS ID|HOP|DATA|CRC8| +|--|--------|------|----|------|---|----|----| +|0 |00000001| 11 | | 0001 | 0 | 64 | | +|__|________|______|____|______|___|____|____| +|8 | 8 | 8 | 8 | 32 | 8 | 8 | 8 | 88 bits +|__|________|______|____|______|___|____|____| + +``` + +If header's `TX INFO` bit is high the sender's device and bus id are included in the packet. In the example below device id `11` of bus id `0.0.0.1` sends to device id `12` of bus id `0.0.0.1`. + +```cpp + _________ + | TX INFO | + ______________________________|_________|_____________ +|ID| HEADER |LENGTH|CRC8|BUS ID|BUS ID|ID|HOP|DATA|CRC8| +|--|--------|------|----|------|------|--|---|----|----| +|12|00000011| 16 | | 0001 | 0001 |11| 0 | 64 | | +|__|________|______|____|______|______|__|___|____|____| +|8 | 8 | 8 | 8 | 32 | 32 |8 | 8 | 8 | 8 | 128 bits +|__|________|______|____|______|______|__|___|____|____| +``` + +The hop count must be incremented each time the packet is forwarded and routers must ignore packets when a maximum amount of hops is reached. + +#### Extended length +The graph below shows a packet transmission where the length is represented with 16 bits supporting up to 65535 bytes length as requested by the header's `EXT. LENGTH` bit. If the extended length feature is used, CRC32 must be applied setting the header's `CRC` bit high. +```cpp + _______________________________________ +|ID| HEADER |LEN 1|LEN 2|CRC8|DATA|CRC32| +|--|--------|-----|-----|----|----|-----| +|12|01100000| 0 | 10 | | 64 | | +|__|________|_____|_____|____|____|_____| +|8 | 8 | 8 | 8 | 8 | 8 | 32 | 80 bits +|__|________|_____|_____|____|____|_____| + +``` + +#### Packet identification +The graph below shows a packet in which a 16 bits packet identifier is added as requested by header's `PACKET ID` bit. This feature is provided to avoid duplications and guarantee packet uniqueness. The receiver filters packets containing a packet identifier and sender information that already appeared previously. +```cpp + ____________________________________________ +|ID| HEADER |LENGTH|CRC8|PACKET ID|DATA|CRC32| +|--|--------|------|----|---------|----|-----| +|12|10000000| 11 | | 999 | 64 | | +|__|________|______|____|_________|____|_____| +|8 | 8 | 8 | 8 | 16 | 8 | 32 | 88 bits +|__|________|______|____|_________|____|_____| + +``` + +#### Network services +PJON supports a network service identifier using a 16 bits port id. Thanks to this feature different services, protocols or formats can coexist and be identified safely. Ports from `0` to `8000` are reserved to known services which index is present in the [known network services list](/specification/PJON-network-services-list.md), ports from `8001` to `65535` are free for use. The graph below shows a packet transmission where port 8002 is inserted in the packet and header's `PORT` bit is high to signal its presence. +```cpp + _________________________________________ +|ID| HEADER |LENGTH|CRC8|PORT ID|DATA|CRC8| +|--|--------|------|----|-------|----|----| +|12|00010000| 8 | | 8002 | 64 | | +|__|________|______|____|_______|____|____| +|8 | 8 | 8 | 8 | 16 | 8 | 8 | 64 bits +|__|________|______|____|_______|____|____| +``` + +#### Hardware identification +If the header's `MAC` bit is high both recipient's and sender's 48 bits MAC addresses are included in the packet. Device id and bus id filtering does not vary. When MAC addresses are included and device ids are not set all devices must use device id 255 and transmit packets to device id 255 (or use broadcast if the acknowledgement is not required). The graph below shows a broadcast packet transmission where MAC address `111111` sends to MAC address `222222` the payload 64. +```cpp + ________________________________________________ +|ID| HEADER |LENGTH|CRC8|RX MAC|TX MAC|DATA|CRC32| +|--|--------|------|----|------|------|----|-----| +|0 |00001000| 12 | |222222|111111| 64 | | +|__|________|______|____|______|______|____|_____| +|8 | 8 | 8 | 8 | 48 | 48 | 8 | 32 | 168 bits +|__|________|______|____|______|______|____|_____| +``` diff --git a/specification/SFSP-frame-separation-specification-v1.0.md b/specification/SFSP-frame-separation-specification-v1.0.md index 73ea1ab60e..73566e5b3b 100644 --- a/specification/SFSP-frame-separation-specification-v1.0.md +++ b/specification/SFSP-frame-separation-specification-v1.0.md @@ -1,7 +1,7 @@ ### Specifications index #### Network layer -- [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) +- [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer diff --git a/specification/PJON-protocol-specification-v3.2.md b/specification/obsolete/PJON-protocol-specification-v3.2.md similarity index 96% rename from specification/PJON-protocol-specification-v3.2.md rename to specification/obsolete/PJON-protocol-specification-v3.2.md index 958d3c204e..bd3e3d7cf0 100644 --- a/specification/PJON-protocol-specification-v3.2.md +++ b/specification/obsolete/PJON-protocol-specification-v3.2.md @@ -2,7 +2,7 @@ #### Network layer - **[PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md)** -- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) +- [Acknowledge specification v1.0](/specification/PJON-protocol-acknowledge-specification-v1.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) @@ -32,6 +32,7 @@ The graph below shows the conceptual model that characterizes and standardizes t | 3 Network layer: PJON | |- Optional features ----------------------------| | Routing and switching | +| Asynchronous acknowledgement | | Service identification (16 bits) | | Packet identification (16 bits) | | Bus identification (32 bits) | @@ -60,7 +61,7 @@ The graph below shows the conceptual model that characterizes and standardizes t * Devices are identified by a unique 8 bits device id * Buses are identified with a 32 bits bus id * Many buses can coexist on the same medium -* A synchronous acknowledgement can be requested (see [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md)) +* Synchronous and or asynchronous acknowledgement can be requested (see [Acknowledge specification v1.0](/specification/PJON-protocol-acknowledge-specification-v1.0.md)) * Network services are identified with a 16 bits port id @@ -204,7 +205,7 @@ Depending on header's `MODE` bit, PJON packets can contain basic or extended sup ``` -In local mode packets can be broadcasted to all devices sending to device id `0`. Acknowledgement is not supported therefore any broadcasted packet that requests an acknowledgement is ignored by recipients. +In local mode packets can be broadcasted to all devices sending to device id `0`. Acknowledgement is not supported therefore any broadcasted packet that requests synchronous and or asynchronous acknowledgement is ignored by recipients. ```cpp _________________________________ @@ -248,7 +249,7 @@ If header's `MODE` bit is high [bus](/specification/PJON-protocol-specification- ``` -In shared mode packets can be broadcasted to all devices sharing the same bus id sending to device id `0`. Acknowledgement is not supported, therefore any broadcasted packet that requests an acknowledgement is ignored by recipients. +In shared mode packets can be broadcasted to all devices sharing the same bus id sending to device id `0`. Acknowledgement is not supported, therefore any broadcasted packet that requests synchronous and or asynchronous acknowledgement is ignored by recipients. ```cpp ________________________________________ diff --git a/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md b/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md index 21923ba7ee..13c33ed602 100644 --- a/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md +++ b/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md @@ -1,7 +1,7 @@ ### Specifications index #### Network layer -- [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) +- [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer diff --git a/src/strategies/MQTTTranslate/MQTTTranslate.h b/src/strategies/MQTTTranslate/MQTTTranslate.h index 8bbc7c8adb..0925ab75d2 100644 --- a/src/strategies/MQTTTranslate/MQTTTranslate.h +++ b/src/strategies/MQTTTranslate/MQTTTranslate.h @@ -56,7 +56,7 @@ pjon/AE7804FEA7D0/output. This can be useful to avoid setting a device id and instead just use the MAC address as a unique subject identifier. - Compliant with the PJON protocol layer specification v3.2 + Compliant with the PJON protocol layer specification v4.0 _____________________________________________________________________________ MQTTTranslate strategy proposed and developed by Fred Larsen 07/12/2019 diff --git a/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md b/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md index 09adbc9fef..1ee6b2a43c 100644 --- a/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md +++ b/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md @@ -2,7 +2,7 @@ ### Specifications index #### Network layer -- [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) +- [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index 003e2be2ca..5fe80d47d5 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -2,7 +2,7 @@ ### Specifications index #### Network layer -- [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) +- [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer diff --git a/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md b/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md index 110989024b..5ac28ebad7 100644 --- a/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md +++ b/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md @@ -1,7 +1,7 @@ ### Specifications index #### Network layer -- [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) +- [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer diff --git a/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md b/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md index 110989024b..5ac28ebad7 100644 --- a/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md +++ b/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md @@ -1,7 +1,7 @@ ### Specifications index #### Network layer -- [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) +- [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer From f544391700b820c30b750640b85b08050ad5fb60 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Apr 2020 23:58:19 +0200 Subject: [PATCH 012/323] spec minor fix --- specification/PJON-protocol-specification-v4.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index f8ef6e0aed..2a2d0ed657 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -143,7 +143,7 @@ HEADER BITMAP 1. `MODE` bit informs if the packet is formatted in [shared](/specification/PJON-protocol-specification-v4.0.md#shared-mode) (value 1) or [local](/specification/PJON-protocol-specification-v4.0.md#local-mode) mode (value 0) 2. `TX INFO` bit informs if the sender info are included (value 1) or not (value 0) 3. `ACK` bit informs if the [synchronous acknowledgement](/specification/PJON-protocol-acknowledge-specification-v1.0.md#synchronous-acknowledge) is requested (value 1) or not (value 0) -4. `MAC` bit informs if sender's and recipient's [network interface identification](/specification/PJON-protocol-specification-v4.0.md#hardware-identification), or MAC address, are included (value 1) or not (value 0) +4. `MAC` bit informs if sender's and recipient's [hardware identification](/specification/PJON-protocol-specification-v4.0.md#hardware-identification), or MAC address, are included (value 1) or not (value 0) 5. `PORT` bit informs if a 16 bits [network service identifier](/specification/PJON-protocol-specification-v4.0.md#network-services) is included (value 1) or not (value 0) 6. `CRC` bit signals which CRC is used, [CRC8](/specification/PJON-protocol-specification-v4.0.md#crc8-polynomial) (value 0) or [CRC32](/specification/PJON-protocol-specification-v4.0.md#crc32-polynomial) (value 1) 7. `EXT. LENGTH` bit informs if the packet contains 8 (value 0) or 16 bits (value 1) [length](/specification/PJON-protocol-specification-v4.0.md#extended-length) From 31bd9ad762ac627db521efc1491e7c553311106f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Apr 2020 14:54:47 +0200 Subject: [PATCH 013/323] Avoid packet id implementation when not required, -48B progmem --- src/PJON.h | 12 +++++++++--- src/PJONDefines.h | 12 ++++++------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 5989a37b3d..e9ac20fa82 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -154,8 +154,10 @@ class PJON { ) { info.header = (info.header == PJON_NO_HEADER) ? config : info.header; info.tx = tx; - if(!info.id && (info.header & PJON_PACKET_ID_BIT)) - info.id = PJONTools::new_packet_id(_packet_id_seed++); + #if(PJON_INCLUDE_PACKET_ID) + if(!info.id && (info.header & PJON_PACKET_ID_BIT)) + info.id = PJONTools::new_packet_id(_packet_id_seed++); + #endif if( (port != PJON_BROADCAST) && (info.port == PJON_BROADCAST) && (info.header & PJON_PORT_BIT) @@ -405,7 +407,11 @@ class PJON { PJON_Packet_Info info; info.rx.id = rx_id; info.header = header; - info.id = packet_id; + #if(PJON_INCLUDE_PACKET_ID) + info.id = packet_id; + #else + (void)packet_id; + #endif info.port = rx_port; return info; }; diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 4f812632e1..35190c8c99 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -169,12 +169,14 @@ struct PJON_Packet { }; struct PJON_Packet_Record { - uint16_t id; uint8_t header; uint8_t sender_id; #ifndef PJON_LOCAL uint8_t sender_bus_id[4]; #endif + #if(PJON_INCLUDE_PACKET_ID) + uint16_t id; + #endif }; struct PJON_End_Point { @@ -191,12 +193,14 @@ struct PJON_Packet_Info { PJON_End_Point tx; PJON_End_Point rx; uint8_t header = PJON_NO_HEADER; - uint16_t id = 0; uint16_t port = PJON_BROADCAST; #ifndef PJON_LOCAL void *custom_pointer; uint8_t hops = 0; #endif + #if(PJON_INCLUDE_PACKET_ID) + uint16_t id = 0; + #endif }; typedef void (* PJON_Receiver)( @@ -322,8 +326,6 @@ struct PJONTools { destination[index++] = (uint8_t)(info.id >> 8); destination[index++] = (uint8_t)info.id; } - #else - (void)info.id; // Avoid unused variable compiler warning #endif if(info.header & PJON_PORT_BIT) { if(info.port != PJON_BROADCAST) { @@ -383,8 +385,6 @@ struct PJONTools { info.id = (packet[index] << 8) | (packet[index + 1] & 0xFF); index += 2; } - #else - info.id = 0; #endif if(info.header & PJON_PORT_BIT) { info.port = (packet[index] << 8) | (packet[index + 1] & 0xFF); From 15abd7380001d8a62e9e8bd6cbc50568387086b6 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Apr 2020 17:14:48 +0200 Subject: [PATCH 014/323] Added PJON_INCLUDE_PORT to enable port feature -98B progmem, -4B RAM --- src/PJON.h | 49 +++++++++++++++++++++++----------- src/PJONDefines.h | 67 +++++++++++++++++++++++++++++++---------------- src/PJONLocal.h | 33 ++++++++++++++++------- 3 files changed, 102 insertions(+), 47 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index e9ac20fa82..9f735656a6 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -82,7 +82,6 @@ class PJON { uint8_t data[PJON_PACKET_MAX_LENGTH]; PJON_Packet_Info last_packet_info; PJON_Packet packets[PJON_MAX_PACKETS]; - uint16_t port = PJON_BROADCAST; uint8_t random_seed = A0; PJON_End_Point tx; @@ -90,6 +89,10 @@ class PJON { PJON_Packet_Record recent_packet_ids[PJON_MAX_RECENT_PACKET_IDS]; #endif + #if(PJON_INCLUDE_PORT) + uint16_t port = PJON_BROADCAST; + #endif + /* PJON initialization with no parameters: State: Local (bus_id: 0.0.0.0) Synchronous acknowledge: true @@ -158,10 +161,12 @@ class PJON { if(!info.id && (info.header & PJON_PACKET_ID_BIT)) info.id = PJONTools::new_packet_id(_packet_id_seed++); #endif - if( - (port != PJON_BROADCAST) && (info.port == PJON_BROADCAST) && - (info.header & PJON_PORT_BIT) - ) info.port = port; + #if(PJON_INCLUDE_PORT) + if( + (port != PJON_BROADCAST) && (info.port == PJON_BROADCAST) && + (info.header & PJON_PORT_BIT) + ) info.port = port; + #endif uint16_t l = PJONTools::compose_packet( info, destination, source, length ); @@ -260,6 +265,8 @@ class PJON { (data[1] & PJON_EXT_LEN_BIT) && !(data[1] & PJON_CRC_BIT) ) || ( !PJON_INCLUDE_PACKET_ID && (data[1] & PJON_PACKET_ID_BIT) + ) || ( + !PJON_INCLUDE_PORT && (data[1] & PJON_PORT_BIT) ) || ( (!PJON_INCLUDE_MAC && (data[1] & PJON_MAC_BIT)) || ((data[1] & PJON_MAC_BIT) && !(data[1] & PJON_CRC_BIT)) @@ -333,8 +340,10 @@ class PJON { ) return PJON_ACK; #endif - if((port != PJON_BROADCAST) && (port != last_packet_info.port)) - return PJON_BUSY; + #if(PJON_INCLUDE_PORT) + if((port != PJON_BROADCAST) && (port != last_packet_info.port)) + return PJON_BUSY; + #endif _receiver( data + (overhead - PJONTools::crc_overhead(data[1])), @@ -412,7 +421,11 @@ class PJON { #else (void)packet_id; #endif - info.port = rx_port; + #if(PJON_INCLUDE_PORT) + info.port = rx_port; + #else + (void)rx_port; + #endif return info; }; @@ -691,9 +704,11 @@ class PJON { state = true -> Include 16 bits packet id state = false -> Avoid packet id inclusion */ - void set_packet_id(bool state) { - set_config_bit(state, PJON_PACKET_ID_BIT); - }; + #if(PJON_INCLUDE_PACKET_ID) + void set_packet_id(bool state) { + set_config_bit(state, PJON_PACKET_ID_BIT); + }; + #endif /* Set a custom receiver callback pointer: (Generally needed to call a custom member function) */ @@ -733,10 +748,14 @@ class PJON { /* Include the port passing a boolean state and an unsigned integer: */ - void include_port(bool state, uint16_t p = PJON_BROADCAST) { - set_config_bit(state, PJON_PORT_BIT); - port = p; - }; + #if(PJON_INCLUDE_PORT) + + void include_port(bool state, uint16_t p = PJON_BROADCAST) { + set_config_bit(state, PJON_PORT_BIT); + port = p; + }; + + #endif /* Configure sender's information inclusion in the packet. state = true -> +8 bits (device id) in local mode diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 35190c8c99..4f15d45f3c 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -141,20 +141,35 @@ limitations under the License. */ #define PJON_PACKET_MAX_LENGTH 50 #endif -/* If set to false packet id feature is not included saving memory - (it saves around 1kB of memory) */ -#ifndef PJON_INCLUDE_PACKET_ID - #define PJON_INCLUDE_PACKET_ID false -#endif - /* Maximum packet ids record kept in memory (to avoid duplicated exchanges) */ #ifndef PJON_MAX_RECENT_PACKET_IDS #define PJON_MAX_RECENT_PACKET_IDS 10 #endif -/* If set to false mac feature is not included saving memory */ -#ifndef PJON_INCLUDE_MAC - #define PJON_INCLUDE_MAC false +/* Optional features: */ + +/* If defined includes the packet id feature */ +#ifdef PJON_INCLUDE_PACKET_ID + #undef PJON_INCLUDE_PACKET_ID + #define PJON_INCLUDE_PACKET_ID true +#else + #define PJON_INCLUDE_PACKET_ID false +#endif + +/* If defined includes the port id feature */ +#ifdef PJON_INCLUDE_PORT + #undef PJON_INCLUDE_PORT + #define PJON_INCLUDE_PORT true +#else + #define PJON_INCLUDE_PORT false +#endif + +/* If defined includes the mac address feature */ +#ifdef PJON_INCLUDE_MAC + #undef PJON_INCLUDE_MAC + #define PJON_INCLUDE_MAC true +#else + #define PJON_INCLUDE_MAC false #endif /* Data structures: */ @@ -193,7 +208,6 @@ struct PJON_Packet_Info { PJON_End_Point tx; PJON_End_Point rx; uint8_t header = PJON_NO_HEADER; - uint16_t port = PJON_BROADCAST; #ifndef PJON_LOCAL void *custom_pointer; uint8_t hops = 0; @@ -201,6 +215,9 @@ struct PJON_Packet_Info { #if(PJON_INCLUDE_PACKET_ID) uint16_t id = 0; #endif + #if(PJON_INCLUDE_PORT) + uint16_t port = PJON_BROADCAST; + #endif }; typedef void (* PJON_Receiver)( @@ -284,9 +301,11 @@ struct PJONTools { ) { uint8_t index = 0; if(length > 255) info.header |= PJON_EXT_LEN_BIT; - if(info.port != PJON_BROADCAST) info.header |= PJON_PORT_BIT; - if((info.header & PJON_PORT_BIT) && (info.port == PJON_BROADCAST)) - info.header &= ~PJON_PORT_BIT; + #if(PJON_INCLUDE_PORT) + if(info.port != PJON_BROADCAST) info.header |= PJON_PORT_BIT; + if((info.header & PJON_PORT_BIT) && (info.port == PJON_BROADCAST)) + info.header &= ~PJON_PORT_BIT; + #endif if(info.rx.id == PJON_BROADCAST) info.header &= ~(PJON_ACK_REQ_BIT); uint16_t new_length = length + packet_overhead(info.header); bool extended_length = info.header & PJON_EXT_LEN_BIT; @@ -327,12 +346,14 @@ struct PJONTools { destination[index++] = (uint8_t)info.id; } #endif - if(info.header & PJON_PORT_BIT) { - if(info.port != PJON_BROADCAST) { - destination[index++] = (uint8_t)(info.port >> 8); - destination[index++] = (uint8_t)info.port; + #if(PJON_INCLUDE_PORT) + if(info.header & PJON_PORT_BIT) { + if(info.port != PJON_BROADCAST) { + destination[index++] = (uint8_t)(info.port >> 8); + destination[index++] = (uint8_t)info.port; + } } - } + #endif #if(PJON_INCLUDE_MAC) if(info.header & PJON_MAC_BIT) { copy_id(&destination[index], info.rx.mac, 6); @@ -386,10 +407,12 @@ struct PJONTools { index += 2; } #endif - if(info.header & PJON_PORT_BIT) { - info.port = (packet[index] << 8) | (packet[index + 1] & 0xFF); - index += 2; - } + #if(PJON_INCLUDE_PORT) + if(info.header & PJON_PORT_BIT) { + info.port = (packet[index] << 8) | (packet[index + 1] & 0xFF); + index += 2; + } + #endif #if(PJON_INCLUDE_MAC) copy_id(info.rx.mac, packet + index, 6); index += 6; diff --git a/src/PJONLocal.h b/src/PJONLocal.h index a5214734b1..ab91b27eb0 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -77,12 +77,15 @@ class PJONLocal { public: Strategy strategy; uint8_t config = PJON_TX_INFO_BIT | PJON_ACK_REQ_BIT; - uint16_t port = PJON_BROADCAST; #if(PJON_INCLUDE_PACKET_ID) PJON_Packet_Record recent_packet_ids[PJON_MAX_RECENT_PACKET_IDS]; #endif + #if(PJON_INCLUDE_PORT) + uint16_t port = PJON_BROADCAST; + #endif + /* PJONLocal initialization with no parameters: PJONLocal bus; */ @@ -123,10 +126,14 @@ class PJONLocal { info.rx.id = id; info.tx.id = _device_id; info.header = (header == PJON_NO_HEADER) ? config : header; - if(!packet_id && (info.header & PJON_PACKET_ID_BIT)) - info.id = PJONTools::new_packet_id(_packet_id_seed++); - else info.id = packet_id; - info.port = (rx_port == PJON_BROADCAST) ? port : rx_port; + #if(PJON_INCLUDE_PACKET_ID) + if(!packet_id && (info.header & PJON_PACKET_ID_BIT)) + info.id = PJONTools::new_packet_id(_packet_id_seed++); + else info.id = packet_id; + #endif + #if(PJON_INCLUDE_PORT) + info.port = (rx_port == PJON_BROADCAST) ? port : rx_port; + #endif uint16_t l = PJONTools::compose_packet(info, destination, source, length); return l; @@ -228,7 +235,9 @@ class PJONLocal { known_packet_id(info) && !_router ) return 0; #endif - if((port != PJON_BROADCAST) && (port != info.port)) return 0; + #if(PJON_INCLUDE_PORT) + if((port != PJON_BROADCAST) && (port != info.port)) return 0; + #endif return length - overhead; }; @@ -333,10 +342,14 @@ class PJONLocal { /* Include the port passing a boolean state and an unsigned integer: */ - void include_port(bool state, uint16_t p = PJON_BROADCAST) { - set_config_bit(state, PJON_PORT_BIT); - port = p; - }; + #if(PJON_INCLUDE_PORT) + + void include_port(bool state, uint16_t p = PJON_BROADCAST) { + set_config_bit(state, PJON_PORT_BIT); + port = p; + }; + + #endif /* Configure sender's information inclusion in the packet. TRUE: sender's device id (+8bits overhead) From 33c57fca306dad817276db450914a68df1844b91 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Apr 2020 17:18:58 +0200 Subject: [PATCH 015/323] documentation/configuration updated --- documentation/configuration.md | 37 ++++++++++++++++--- .../BlinkTestMAC/Receiver/Receiver.ino | 4 +- .../BlinkTestMAC/Transmitter/Transmitter.ino | 2 +- .../UsePacketId/Receiver/Receiver.ino | 2 +- .../UsePacketId/Transmitter/Transmitter.ino | 2 +- .../HC-12-LocalChat/HC-12-LocalChat.ino | 2 +- .../PortsUseExample/Receiver/Receiver.ino | 1 + .../Transmitter/Transmitter.ino | 2 +- 8 files changed, 39 insertions(+), 13 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index 78749f8ebf..a244046ee6 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -122,25 +122,50 @@ The [synchronous acknowledgement](/specification/PJON-protocol-acknowledge-speci ``` ### Packet identification -If packet duplication avoidance is required it is possible to add a 2 bytes [packet identifier](/specification/PJON-protocol-specification-v4.0.md#packet-identification) to guarantee uniqueness. -define the `PJON_INCLUDE_PACKET_ID` as following. The use of a constant has been chosen to save more than 1kB on sketches where this feature is not used: +The instance can be configured to include a 16 bits [packet identifier](/specification/PJON-protocol-specification-v4.0.md#packet-identification) to guarantee packet uniqueness. Define `PJON_INCLUDE_PACKET_ID` as described below, if this constant is not present it saves around 300 bytes of program memory and 80 bytes of RAM: ```cpp -#define PJON_INCLUDE_PACKET_ID true +// Include the packet id feature +#define PJON_INCLUDE_PACKET_ID + // Max number of old packet ids stored to avoid duplication -#define PJON_MAX_RECENT_PACKET_IDS 10 // by default 10 // If packet duplication occurs, higher PJON_MAX_RECENT_PACKET_IDS +#define PJON_MAX_RECENT_PACKET_IDS 10 // By default 10 + #include ``` -Use `set_packet_id` to enable the packet identification feature: +Use `set_packet_id` to enable the packet identification: ```cpp bus.set_packet_id(true); ``` See the [UsePacketId](/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId) example to see more in detail how the packet id can be used. ### Network service identification -Configure the instance to include a [network service identifier](/specification/PJON-protocol-specification-v4.0.md#network-services) in the packet. Ports from 0 to 8000 are reserved to known network services which index is present in the [known network services list](/specification/PJON-network-services-list.md), ports from 8001 to 65535 are free for custom use cases: +The instance can be configured to include a [network service identifier](/specification/PJON-protocol-specification-v4.0.md#network-services) in the packet. Ports from 0 to 8000 are reserved to known network services which index is present in the [known network services list](/specification/PJON-network-services-list.md), ports from 8001 to 65535 are free for custom use cases. Define `PJON_INCLUDE_PORT` as described below, if this constant is not present it saves around 100 bytes of program memory and 2 bytes of RAM: ```cpp + // Include the port id feature + #define PJON_INCLUDE_PORT + #include +``` +Use `include_port` to enable the network service identification: +```cpp bus.include_port(false); // Avoid port inclusion (default) bus.include_port(true, 8001); // Include custom port ``` See the [PortsUseExample](/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample) example to see more in detail how the port feature can be used. + +### Hardware identification +The instance can be configured to include the [hardware identification](/specification/PJON-protocol-specification-v4.0.md#hardware-identification). If the feature is used both recipient's and sender's MAC addresses are included in the packet. Define `PJON_INCLUDE_MAC` as described below, if this constant is not present it saves around 200 bytes of program memory and 20 bytes of RAM: +```cpp + // Include the port id feature + #define PJON_INCLUDE_MAC + #include + + // Device's MAC address + uint8_t mac[6] = {0, 0, 0, 0, 0, 0}; + PJON bus(mac); +``` +Use `include_mac` to enable the network service identification by default: +```cpp + bus.include_mac(true); // Include MAC address by default +``` +See the [BlinkTestMAC](/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC) example to see more in detail how the MAC feature can be used. diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Receiver/Receiver.ino index c2142ed645..720f0c4685 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Receiver/Receiver.ino @@ -1,5 +1,5 @@ -#define PJON_INCLUDE_SWBB true -#define PJON_INCLUDE_MAC true +#define PJON_INCLUDE_SWBB +#define PJON_INCLUDE_MAC #include // bus(mac address of the network interface) diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Transmitter/Transmitter.ino index 9a1a655748..147b35034a 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Transmitter/Transmitter.ino @@ -1,4 +1,4 @@ -#define PJON_INCLUDE_MAC true +#define PJON_INCLUDE_MAC #include // bus(mac address of the network interface) diff --git a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino index b9ceb77405..1456bf0887 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino @@ -1,5 +1,5 @@ // Include packet id feature -#define PJON_INCLUDE_PACKET_ID true +#define PJON_INCLUDE_PACKET_ID // Uncomment to run SoftwareBitBang in MODE 2 // #define SWBB_MODE 2 diff --git a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino index 21cb9b9920..6bf5b87d16 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino @@ -1,5 +1,5 @@ // Include packet id feature -#define PJON_INCLUDE_PACKET_ID true +#define PJON_INCLUDE_PACKET_ID // Uncomment to run SoftwareBitBang in MODE 2 // #define SWBB_MODE 2 diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino index 586761b43e..c7fd123661 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino @@ -32,7 +32,7 @@ user 1: Ciao! user 1: Ciao! user 1: Ciao! */ -#define PJON_INCLUDE_PACKET_ID true +#define PJON_INCLUDE_PACKET_ID /* Use 63 characters maximum packet length. HC-12 has two 64-byte Rx and Tx FIFO memories built into the chip, diff --git a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino index 697adf6f54..43793d7610 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino @@ -1,3 +1,4 @@ +#define PJON_INCLUDE_PORT #include int busy; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Transmitter/Transmitter.ino index b4edbf5286..86c880b90c 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Transmitter/Transmitter.ino @@ -1,4 +1,4 @@ - +#define PJON_INCLUDE_PORT #include // Bus id definition From b640760559f31e1b00ae5adcaae8d33c457561b4 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Apr 2020 17:31:20 +0200 Subject: [PATCH 016/323] documentation/configuration minor fix' --- documentation/configuration.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index a244046ee6..761f34d798 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -16,12 +16,11 @@ PJON uses predefined constants, setters and getters to support features and cons ### Buffers configuration Before instantiating PJON it is possible to define the length of its buffers. Predefining `PJON_MAX_PACKETS` and `PJON_PACKET_MAX_LENGTH` it is possible to configure this constraints to reach the project memory requirements. Obviously, the less memory is dedicated to buffers, the more memory can be used for something else: ```cpp -#define PJON_MAX_PACKETS 1 -#define PJON_PACKET_MAX_LENGTH 20 -#include -/* PJON can store up to 1 packet of up to - 20 bytes - packet overhead - (from 5 to 22 bytes depending by configuration) */ + #define PJON_MAX_PACKETS 1 + #define PJON_PACKET_MAX_LENGTH 20 + #include + /* PJON can dispatch up to 1 packet with a payload of up to + 20 bytes - packet overhead (5-35 bytes depending on configuration) */ ``` ### Data link configuration @@ -124,14 +123,14 @@ The [synchronous acknowledgement](/specification/PJON-protocol-acknowledge-speci ### Packet identification The instance can be configured to include a 16 bits [packet identifier](/specification/PJON-protocol-specification-v4.0.md#packet-identification) to guarantee packet uniqueness. Define `PJON_INCLUDE_PACKET_ID` as described below, if this constant is not present it saves around 300 bytes of program memory and 80 bytes of RAM: ```cpp -// Include the packet id feature -#define PJON_INCLUDE_PACKET_ID + // Include the packet id feature + #define PJON_INCLUDE_PACKET_ID -// Max number of old packet ids stored to avoid duplication -// If packet duplication occurs, higher PJON_MAX_RECENT_PACKET_IDS -#define PJON_MAX_RECENT_PACKET_IDS 10 // By default 10 + // Max number of old packet ids stored to avoid duplication + // If packet duplication occurs, higher PJON_MAX_RECENT_PACKET_IDS + #define PJON_MAX_RECENT_PACKET_IDS 10 // By default 10 -#include + #include ``` Use `set_packet_id` to enable the packet identification: ```cpp From a8ee82de4b343b185df9a8de2e879fc80a3a597c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Apr 2020 17:50:38 +0200 Subject: [PATCH 017/323] PJON and PJONLocal packet id and port setters moved --- src/PJON.h | 110 ++++++++++++++++++++++++------------------------ src/PJONLocal.h | 37 ++++++++-------- 2 files changed, 74 insertions(+), 73 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 9f735656a6..bd803ca983 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -700,16 +700,6 @@ class PJON { _mode = mode; }; - /* Configure packet id presence: - state = true -> Include 16 bits packet id - state = false -> Avoid packet id inclusion */ - - #if(PJON_INCLUDE_PACKET_ID) - void set_packet_id(bool state) { - set_config_bit(state, PJON_PACKET_ID_BIT); - }; - #endif - /* Set a custom receiver callback pointer: (Generally needed to call a custom member function) */ @@ -746,17 +736,6 @@ class PJON { tx.id = id; }; - /* Include the port passing a boolean state and an unsigned integer: */ - - #if(PJON_INCLUDE_PORT) - - void include_port(bool state, uint16_t p = PJON_BROADCAST) { - set_config_bit(state, PJON_PORT_BIT); - port = p; - }; - - #endif - /* Configure sender's information inclusion in the packet. state = true -> +8 bits (device id) in local mode +40 bits (bus id + device id) in shared mode @@ -857,46 +836,65 @@ class PJON { #if(PJON_INCLUDE_PACKET_ID) - /* Check if the packet id and its transmitter info are already present in - buffer of recently received packets, if not add it to the buffer. */ + /* Check if the packet id and its transmitter info are already present + in the known packets buffer, if not add it to the buffer */ - bool known_packet_id(PJON_Packet_Info info) { - for(uint8_t i = 0; i < PJON_MAX_RECENT_PACKET_IDS; i++) - if( - info.id == recent_packet_ids[i].id && - info.tx.id == recent_packet_ids[i].sender_id && ( - ( - (info.header & PJON_MODE_BIT) && - (recent_packet_ids[i].header & PJON_MODE_BIT) && - PJONTools::id_equality( - (uint8_t *)info.tx.bus_id, - (uint8_t *)recent_packet_ids[i].sender_bus_id, - 4 + bool known_packet_id(PJON_Packet_Info info) { + for(uint8_t i = 0; i < PJON_MAX_RECENT_PACKET_IDS; i++) + if( + info.id == recent_packet_ids[i].id && + info.tx.id == recent_packet_ids[i].sender_id && ( + ( + (info.header & PJON_MODE_BIT) && + (recent_packet_ids[i].header & PJON_MODE_BIT) && + PJONTools::id_equality( + (uint8_t *)info.tx.bus_id, + (uint8_t *)recent_packet_ids[i].sender_bus_id, + 4 + ) + ) || ( + !(info.header & PJON_MODE_BIT) && + !(recent_packet_ids[i].header & PJON_MODE_BIT) ) - ) || ( - !(info.header & PJON_MODE_BIT) && - !(recent_packet_ids[i].header & PJON_MODE_BIT) ) - ) - ) return true; - save_packet_id(info); - return false; - }; + ) return true; + save_packet_id(info); + return false; + }; - /* Save packet id in the buffer: */ + /* Save packet id in the buffer: */ + + void save_packet_id(PJON_Packet_Info info) { + for(uint8_t i = PJON_MAX_RECENT_PACKET_IDS - 1; i > 0; i--) + recent_packet_ids[i] = recent_packet_ids[i - 1]; + recent_packet_ids[0].id = info.id; + recent_packet_ids[0].header = info.header; + recent_packet_ids[0].sender_id = info.tx.id; + PJONTools::copy_id( + recent_packet_ids[0].sender_bus_id, + info.tx.bus_id, + 4 + ); + }; - void save_packet_id(PJON_Packet_Info info) { - for(uint8_t i = PJON_MAX_RECENT_PACKET_IDS - 1; i > 0; i--) - recent_packet_ids[i] = recent_packet_ids[i - 1]; - recent_packet_ids[0].id = info.id; - recent_packet_ids[0].header = info.header; - recent_packet_ids[0].sender_id = info.tx.id; - PJONTools::copy_id( - recent_packet_ids[0].sender_bus_id, - info.tx.bus_id, - 4 - ); - }; + /* Configure packet id presence: + state = true -> Include 16 bits packet id + state = false -> Avoid packet id inclusion */ + + void set_packet_id(bool state) { + set_config_bit(state, PJON_PACKET_ID_BIT); + }; + + #endif + + #if(PJON_INCLUDE_PORT) + + /* Include the port passing a boolean state and an unsigned integer: */ + + void include_port(bool state, uint16_t p = PJON_BROADCAST) { + set_config_bit(state, PJON_PORT_BIT); + port = p; + }; #endif diff --git a/src/PJONLocal.h b/src/PJONLocal.h index ab91b27eb0..c2576c71b8 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -327,12 +327,7 @@ class PJONLocal { void set_communication_mode(uint8_t mode) { _mode = mode; }; - /* Configure packet id presence: - TRUE: include packet id, FALSE: Avoid packet id inclusion */ - - void set_packet_id(bool state) { - set_config_bit(state, PJON_PACKET_ID_BIT); - }; + /* Set default configuration: */ void set_default() { _mode = PJON_HALF_DUPLEX; }; @@ -340,17 +335,6 @@ class PJONLocal { void set_id(uint8_t id) { _device_id = id; }; - /* Include the port passing a boolean state and an unsigned integer: */ - - #if(PJON_INCLUDE_PORT) - - void include_port(bool state, uint16_t p = PJON_BROADCAST) { - set_config_bit(state, PJON_PORT_BIT); - port = p; - }; - - #endif - /* Configure sender's information inclusion in the packet. TRUE: sender's device id (+8bits overhead) FALSE: No sender's device id inclusion (-8bits overhead) @@ -393,8 +377,27 @@ class PJONLocal { recent_packet_ids[0].sender_id = info.sender_id; }; + /* Configure packet id presence: + TRUE: include packet id, FALSE: Avoid packet id inclusion */ + + void set_packet_id(bool state) { + set_config_bit(state, PJON_PACKET_ID_BIT); + }; + #endif + #if(PJON_INCLUDE_PORT) + + /* Include the port passing a boolean state and an unsigned integer: */ + + void include_port(bool state, uint16_t p = PJON_BROADCAST) { + set_config_bit(state, PJON_PORT_BIT); + port = p; + }; + + #endif + + private: uint32_t _last_send = 0; uint8_t _mode; From ea82ea8c5646ffb15584e999716c85ab1c1b6ea5 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Apr 2020 18:20:01 +0200 Subject: [PATCH 018/323] PJON _mode now type bool, -2B progmem --- src/PJON.h | 8 ++++---- src/PJONDefines.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index bd803ca983..518d2de8f5 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -693,10 +693,10 @@ class PJON { }; /* Set communication mode: - mode = PJON_SIMPLEX -> communication is mono-directional - mode = PJON_HALF_DUPLEX -> communication is bi-directional */ + mode = 0 or PJON_SIMPLEX -> communication is mono-directional + mode = 1 or PJON_HALF_DUPLEX -> communication is bi-directional */ - void set_communication_mode(uint8_t mode) { + void set_communication_mode(bool mode) { _mode = mode; }; @@ -902,7 +902,7 @@ class PJON { bool _auto_delete = true; void *_custom_pointer; PJON_Error _error; - uint8_t _mode; + bool _mode; uint16_t _packet_id_seed = 0; PJON_Receiver _receiver; uint8_t _recursion = 0; diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 4f15d45f3c..25e3d78e90 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -81,8 +81,8 @@ limitations under the License. */ #define PJON_TO_BE_SENT 74 /* Communication modes: */ -#define PJON_SIMPLEX 150 -#define PJON_HALF_DUPLEX 151 +#define PJON_SIMPLEX false +#define PJON_HALF_DUPLEX true /* Header bits definition: */ From 7e7e43ba0848d0c338ac770417eab33490f8a601 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Apr 2020 18:20:58 +0200 Subject: [PATCH 019/323] documentation/configuration minor fix --- documentation/configuration.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index 761f34d798..1b70e67927 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -121,7 +121,7 @@ The [synchronous acknowledgement](/specification/PJON-protocol-acknowledge-speci ``` ### Packet identification -The instance can be configured to include a 16 bits [packet identifier](/specification/PJON-protocol-specification-v4.0.md#packet-identification) to guarantee packet uniqueness. Define `PJON_INCLUDE_PACKET_ID` as described below, if this constant is not present it saves around 300 bytes of program memory and 80 bytes of RAM: +The instance can be configured to include a 16 bits [packet identifier](/specification/PJON-protocol-specification-v4.0.md#packet-identification) to guarantee packet uniqueness. Define `PJON_INCLUDE_PACKET_ID` as described below, if this constant is not present the feature is not included and around 300 bytes of program memory and 80 bytes of RAM are spared: ```cpp // Include the packet id feature #define PJON_INCLUDE_PACKET_ID @@ -139,7 +139,7 @@ Use `set_packet_id` to enable the packet identification: See the [UsePacketId](/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId) example to see more in detail how the packet id can be used. ### Network service identification -The instance can be configured to include a [network service identifier](/specification/PJON-protocol-specification-v4.0.md#network-services) in the packet. Ports from 0 to 8000 are reserved to known network services which index is present in the [known network services list](/specification/PJON-network-services-list.md), ports from 8001 to 65535 are free for custom use cases. Define `PJON_INCLUDE_PORT` as described below, if this constant is not present it saves around 100 bytes of program memory and 2 bytes of RAM: +The instance can be configured to include a [network service identifier](/specification/PJON-protocol-specification-v4.0.md#network-services) in the packet. Ports from 0 to 8000 are reserved to known network services which index is present in the [known network services list](/specification/PJON-network-services-list.md), ports from 8001 to 65535 are free for custom use cases. Define `PJON_INCLUDE_PORT` as described below, if this constant is not present the feature is not used and around 100 bytes of program memory and 2 bytes of RAM are spared: ```cpp // Include the port id feature #define PJON_INCLUDE_PORT @@ -153,7 +153,7 @@ Use `include_port` to enable the network service identification: See the [PortsUseExample](/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample) example to see more in detail how the port feature can be used. ### Hardware identification -The instance can be configured to include the [hardware identification](/specification/PJON-protocol-specification-v4.0.md#hardware-identification). If the feature is used both recipient's and sender's MAC addresses are included in the packet. Define `PJON_INCLUDE_MAC` as described below, if this constant is not present it saves around 200 bytes of program memory and 20 bytes of RAM: +The instance can be configured to include the [hardware identification](/specification/PJON-protocol-specification-v4.0.md#hardware-identification). If the feature is used both recipient's and sender's MAC addresses are included in the packet. Define `PJON_INCLUDE_MAC` as described below, if this constant is not present the feature is not included and around 200 bytes of program memory and 20 bytes of RAM are spared: ```cpp // Include the port id feature #define PJON_INCLUDE_MAC From bc6a0d94fa91968eb2c1f40cb61c8bf9639ee6e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Apr 2020 18:21:16 +0200 Subject: [PATCH 020/323] PJONLocal avoid warning --- src/PJONLocal.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PJONLocal.h b/src/PJONLocal.h index c2576c71b8..58032deee9 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -130,9 +130,13 @@ class PJONLocal { if(!packet_id && (info.header & PJON_PACKET_ID_BIT)) info.id = PJONTools::new_packet_id(_packet_id_seed++); else info.id = packet_id; + #else + (void)packet_id; #endif #if(PJON_INCLUDE_PORT) info.port = (rx_port == PJON_BROADCAST) ? port : rx_port; + #else + (void)rx_port; #endif uint16_t l = PJONTools::compose_packet(info, destination, source, length); From 59c59d05b92a000210cbd7fd930b9b927a523568 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Apr 2020 19:09:11 +0200 Subject: [PATCH 021/323] include_port changed, docs and examples updated (breaking compatibility) --- documentation/configuration.md | 6 +++--- .../SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino | 2 +- .../PortsUseExample/Transmitter/Transmitter.ino | 2 +- src/PJON.h | 8 +++++--- src/PJONLocal.h | 8 +++++--- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index 1b70e67927..311e149547 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -147,10 +147,10 @@ The instance can be configured to include a [network service identifier](/specif ``` Use `include_port` to enable the network service identification: ```cpp - bus.include_port(false); // Avoid port inclusion (default) - bus.include_port(true, 8001); // Include custom port + bus.include_port(false); // Avoid port inclusion (default) + bus.include_port(8001); // Include a port ``` -See the [PortsUseExample](/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample) example to see more in detail how the port feature can be used. +When a port is configured, packets that contain a different port are discarded. See the [PortsUseExample](/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample) to see more in detail how the port feature can be used. ### Hardware identification The instance can be configured to include the [hardware identification](/specification/PJON-protocol-specification-v4.0.md#hardware-identification). If the feature is used both recipient's and sender's MAC addresses are included in the packet. Define `PJON_INCLUDE_MAC` as described below, if this constant is not present the feature is not included and around 200 bytes of program memory and 20 bytes of RAM are spared: diff --git a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino index 43793d7610..816c35b60e 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino @@ -57,7 +57,7 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info void setup() { /* Include a custom port, only packet including port 8001 are received others are filtered out. */ - bus.include_port(true, 8001); + bus.include_port(8001); bus.strategy.set_pin(12); bus.set_receiver(receiver_function); bus.begin(); diff --git a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Transmitter/Transmitter.ino index 86c880b90c..1e8408bd57 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Transmitter/Transmitter.ino @@ -19,7 +19,7 @@ void setup() { bus.begin(); /* Include a custom port, only packet including port 8001 are received others are filtered out. */ - bus.include_port(true, 8001); + bus.include_port(8001); bus.strategy.set_pin(12); bus.set_error(error_handler); diff --git a/src/PJON.h b/src/PJON.h index 518d2de8f5..923d977bf3 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -889,10 +889,12 @@ class PJON { #if(PJON_INCLUDE_PORT) - /* Include the port passing a boolean state and an unsigned integer: */ + /* Include the port: + p = 1-65535 -> Include 16 bits port id + p = 0 -> Avoid port id inclusion */ - void include_port(bool state, uint16_t p = PJON_BROADCAST) { - set_config_bit(state, PJON_PORT_BIT); + void include_port(uint16_t p) { + set_config_bit((p != 0) ? 1 : 0, PJON_PORT_BIT); port = p; }; diff --git a/src/PJONLocal.h b/src/PJONLocal.h index 58032deee9..2127de6f6a 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -392,10 +392,12 @@ class PJONLocal { #if(PJON_INCLUDE_PORT) - /* Include the port passing a boolean state and an unsigned integer: */ + /* Include the port: + p = 1-65535 -> Include 16 bits port id + p = 0 -> Avoid port id inclusion */ - void include_port(bool state, uint16_t p = PJON_BROADCAST) { - set_config_bit(state, PJON_PORT_BIT); + void include_port(uint16_t p) { + set_config_bit((p != 0) ? 1 : 0, PJON_PORT_BIT); port = p; }; From c061267888eb8f5317a12ae7c3de3969baadd806 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Apr 2020 19:47:31 +0200 Subject: [PATCH 022/323] README overhead update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 930bef6d58..195c2a11a2 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ PJON® (Padded Jittering Operative Network) is an arduino-compatible, multi-mast [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) PJON is used in thousands of devices and its community has spread worldwide because of the following 5 key factors: -- **New technology**: [PJON](specification/PJON-protocol-specification-v4.0.md) is an experimental network protocol stack crafted in 10 years of research and experimentation. It was originally developed as an open-source alternative to i2c and 1-Wire but during development its scope and features have been extended to cover use cases where IP is generally applied. PJON has been engineered to have a variable footprint (4.2-8.2 kB program memory) and overhead (5-22 bytes per packet) depending on its configuration. +- **New technology**: [PJON](specification/PJON-protocol-specification-v4.0.md) is an experimental network protocol stack crafted in 10 years of research and experimentation. It was originally developed as an open-source alternative to i2c and 1-Wire but during development its scope and features have been extended to cover use cases where IP is generally applied. PJON has been engineered to have a variable footprint (4.2-8.2 kB program memory) and overhead (5-35 bytes per packet) depending on its configuration. - **Multi-media support**: PJON operates on a wide range of media and protocols like TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485 and LoRa. The PJON network protocol stack specifies and implements also [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) able to communicate data over a single wire shared by up to 255 devices, [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) able to operate with many ASK/FSK/OOK radio modules and also [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md), able to communicate wirelessly with light pulses using off the shelf LEDs and laser diodes. - **Increased reliability**: Many protocols massively applied worldwide expose dangerous vulnerabilities, have weak error detection algorithms and are not resilient to interference. PJON is based on years of analysis and study not to make the same mistakes present in most alternatives and provide with a set of simpler and more efficient solutions. - **High flexibility**: PJON is totally software-defined and its implementation is designed to be easily extensible. it builds out-of-the-box in all supported devices and operates transparently on top of any supported protocol or medium. From f1dcb2047baa39ab1c40f88b4afda50a5c4c14ae Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Apr 2020 21:22:45 +0200 Subject: [PATCH 023/323] keywords cleanup --- keywords.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/keywords.txt b/keywords.txt index 92cb86b805..edd40816f9 100644 --- a/keywords.txt +++ b/keywords.txt @@ -39,13 +39,10 @@ PJON_Error KEYWORD1 # Methods and Functions (KEYWORD2) ####################################### -acquire_id KEYWORD2 begin KEYWORD2 can_start KEYWORD2 device_id KEYWORD2 -discard_device_id KEYWORD2 get_packets_count KEYWORD2 -get_rid KEYWORD2 include_sender_info KEYWORD2 include_port KEYWORD2 receive KEYWORD2 @@ -83,12 +80,10 @@ PJON_LOCAL LITERAL1 PJON_ACK LITERAL1 PJON_BROADCAST LITERAL1 PJON_BUSY LITERAL1 -COLLISION_MAX_DELAY LITERAL1 PJON_CONNECTION_LOST LITERAL1 PJON_CONTENT_TOO_LONG LITERAL1 PJON_FAIL LITERAL1 PJON_MAX_PACKETS LITERAL1 -PJON_MASTER_ID LITERAL1 PJON_NAK LITERAL1 PJON_NOT_ASSIGNED LITERAL1 PJON_PACKETS_BUFFER_FULL LITERAL1 @@ -100,6 +95,7 @@ localhost LITERAL1 PJON_MODE_BIT LITERAL1 PJON_TX_INFO_BIT LITERAL1 PJON_ACK_REQ_BIT LITERAL1 +PJON_MAC_BIT LITERAL1 PJON_CRC_BIT LITERAL1 PJON_EXT_LEN_BIT LITERAL1 PJON_PORT_BIT LITERAL1 From dbacb9b06d6935625596af14aa6f92e1b625772f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Apr 2020 22:38:29 +0200 Subject: [PATCH 024/323] keywords update --- keywords.txt | 146 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 95 insertions(+), 51 deletions(-) diff --git a/keywords.txt b/keywords.txt index edd40816f9..b94167243e 100644 --- a/keywords.txt +++ b/keywords.txt @@ -2,11 +2,10 @@ # Syntax Coloring Map For PJON ####################################### -####################################### # Datatypes (KEYWORD1) -####################################### -Any KEYWORD1 +## PJON classes and data types + StrategyLink KEYWORD1 PJON KEYWORD1 PJONLocal KEYWORD1 @@ -18,36 +17,40 @@ PJONDynamicRouter KEYWORD1 PJONInteractiveRouter KEYWORD1 PJONVirtualBusRouter KEYWORD1 PJONTools KEYWORD1 +PJON_Packet KEYWORD1 +PJON_End_Point KEYWORD1 +PJON_Packet_Info KEYWORD1 +PJON_Error KEYWORD1 + +## Strategies + AnalogSampling KEYWORD1 -SoftwareBitBang KEYWORD1 -OverSampling KEYWORD1 -ThroughSerial KEYWORD1 -ThroughSerialAsync KEYWORD1 -ThroughLora KEYWORD1 +Any KEYWORD1 +DualUDP KEYWORD1 +ESPNOW KEYWORD1 EthernetTCP KEYWORD1 -LocalUDP KEYWORD1 +GlobalUDP KEYWORD1 LocalFile KEYWORD1 +LocalUDP KEYWORD1 MQTTTranslate KEYWORD1 -GlobalUDP KEYWORD1 -DualUDP KEYWORD1 -ESPNOW KEYWORD1 -PJON_Packet KEYWORD1 -PJON_Packet_Info KEYWORD1 -PJON_Error KEYWORD1 +OverSampling KEYWORD1 +SoftwareBitBang KEYWORD1 +ThroughLora KEYWORD1 +ThroughSerial KEYWORD1 +ThroughSerialAsync KEYWORD1 -####################################### # Methods and Functions (KEYWORD2) -####################################### begin KEYWORD2 can_start KEYWORD2 device_id KEYWORD2 get_packets_count KEYWORD2 -include_sender_info KEYWORD2 +include_mac KEYWORD2 include_port KEYWORD2 +include_sender_info KEYWORD2 receive KEYWORD2 remove KEYWORD2 -remove_all KEYWORD2 +remove_all_packets KEYWORD2 ready_to_send KEYWORD2 reply KEYWORD2 send KEYWORD2 @@ -68,30 +71,37 @@ set_packet_id KEYWORD2 strategy KEYWORD2 update KEYWORD2 -####################################### # Instances (KEYWORD2) -####################################### - -####################################### # Constants (LITERAL1) -####################################### -PJON_LOCAL LITERAL1 -PJON_ACK LITERAL1 + +## PJON basic constants + +localhost LITERAL1 +PJON_NOT_ASSIGNED LITERAL1 PJON_BROADCAST LITERAL1 -PJON_BUSY LITERAL1 -PJON_CONNECTION_LOST LITERAL1 -PJON_CONTENT_TOO_LONG LITERAL1 -PJON_FAIL LITERAL1 -PJON_MAX_PACKETS LITERAL1 +PJON_ACK LITERAL1 PJON_NAK LITERAL1 -PJON_NOT_ASSIGNED LITERAL1 -PJON_PACKETS_BUFFER_FULL LITERAL1 -PJON_PACKET_MAX_LENGTH LITERAL1 +PJON_FAIL LITERAL1 +PJON_BUSY LITERAL1 PJON_SIMPLEX LITERAL1 PJON_HALF_DUPLEX LITERAL1 PJON_TO_BE_SENT LITERAL1 -localhost LITERAL1 + +## PJON errors + +PJON_PACKETS_BUFFER_FULL LITERAL1 +PJON_CONNECTION_LOST LITERAL1 +PJON_CONTENT_TOO_LONG LITERAL1 + +## Constraints + +PJON_PACKET_MAX_LENGTH LITERAL1 +PJON_MAX_PACKETS LITERAL1 +PJON_MAX_RECENT_PACKET_IDS LITERAL1 + +## Header bits + PJON_MODE_BIT LITERAL1 PJON_TX_INFO_BIT LITERAL1 PJON_ACK_REQ_BIT LITERAL1 @@ -100,28 +110,62 @@ PJON_CRC_BIT LITERAL1 PJON_EXT_LEN_BIT LITERAL1 PJON_PORT_BIT LITERAL1 PJON_PACKET_ID_BIT LITERAL1 + +## Conditional feature inclusion + +PJON_LOCAL LITERAL1 PJON_INCLUDE_PACKET_ID LITERAL1 -PJON_MAX_RECENT_PACKET_IDS LITERAL1 -AS_MODE LITERAL1 -SWBB_MODE LITERAL1 -SWBB_RESPONSE_TIMEOUT LITERAL1 -OS_TIMEOUT LITERAL1 -AS_TIMEOUT LITERAL1 -MQTTT_MODE_BUS_RAW LITERAL1 -MQTTT_MODE_BUS_JSON LITERAL1 -MQTTT_MODE_MIRROR_TRANSLATE LITERAL1 -MQTTT_MODE_MIRROR_DIRECT LITERAL1 -PJON_INCLUDE_MQTT LITERAL1 -PJON_INCLUDE_SWBB LITERAL1 +PJON_INCLUDE_PORT LITERAL1 +PJON_INCLUDE_MAC LITERAL1 + +## Strategy inclusion constants + PJON_INCLUDE_AS LITERAL1 +PJON_INCLUDE_ANY LITERAL1 +PJON_INCLUDE_DUDP LITERAL1 +PJON_INCLUDE_EN LITERAL1 PJON_INCLUDE_ETCP LITERAL1 PJON_INCLUDE_GUDP LITERAL1 +PJON_INCLUDE_LF LITERAL1 PJON_INCLUDE_LUDP LITERAL1 +PJON_INCLUDE_MQTT LITERAL1 PJON_INCLUDE_OS LITERAL1 +PJON_INCLUDE_SWBB LITERAL1 +PJON_INCLUDE_TL LITERAL1 PJON_INCLUDE_TS LITERAL1 PJON_INCLUDE_TSA LITERAL1 -PJON_INCLUDE_TL LITERAL1 -PJON_INCLUDE_EN LITERAL1 -PJON_INCLUDE_ANY LITERAL1 -PJON_INCLUDE_LF LITERAL1 PJON_INCLUDE_NONE LITERAL1 + +## AnalogSampling + +AS_BIT_WIDTH LITERAL1 +AS_BIT_SPACER LITERAL1 +AS_READ_DELAY LITERAL1 +AS_MODE LITERAL1 +AS_TIMEOUT LITERAL1 +AS_RESPONSE_TIMEOUT LITERAL1 +AS_MAX_ATTEMPTS LITERAL1 + +## MQTTTranslate + +MQTTT_MODE_BUS_RAW LITERAL1 +MQTTT_MODE_BUS_JSON LITERAL1 +MQTTT_MODE_MIRROR_TRANSLATE LITERAL1 +MQTTT_MODE_MIRROR_DIRECT LITERAL1 + +## OverSampling + +OS_TIMEOUT LITERAL1 +OS_BIT_WIDTH LITERAL1 +OS_BIT_SPACER LITERAL1 +OS_ACCEPTANCE LITERAL1 +OS_MAX_ATTEMPTS LITERAL1 + +## SoftwareBitBang +SWBB_BIT_WIDTH LITERAL1 +SWBB_BIT_SPACER LITERAL1 +SWBB_ACCEPTANCE LITERAL1 +SWBB_READ_DELAY LITERAL1 +SWBB_MODE LITERAL1 +SWBB_RESPONSE_TIMEOUT LITERAL1 +SWBB_MAX_ATTEMPTS LITERAL1 From 041979db5f49b44ed4d42c59b9f41c3c721a6281 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Apr 2020 13:09:24 +0200 Subject: [PATCH 025/323] PJON.h minor fix --- src/PJON.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 923d977bf3..0f6f60e884 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -106,18 +106,6 @@ class PJON { set_default(); }; - /* PJON initialization passing the mac address: - const uint8_t mac[6] = {1, 2, 3, 4, 5, 6}; - PJON bus(mac); */ - - #if(PJON_INCLUDE_MAC) - PJON(const uint8_t *mac_addr) : strategy(Strategy()) { - PJONTools::copy_id(tx.mac, mac_addr, 6); - config |= PJON_MAC_BIT; - set_default(); - }; - #endif - /* PJON initialization passing device id: PJON bus(1); */ @@ -137,6 +125,20 @@ class PJON { set_default(); }; + #if(PJON_INCLUDE_MAC) + + /* PJON initialization passing the mac address: + const uint8_t mac[6] = {1, 2, 3, 4, 5, 6}; + PJON bus(mac); */ + + PJON(const uint8_t *mac_addr) : strategy(Strategy()) { + PJONTools::copy_id(tx.mac, mac_addr, 6); + config |= PJON_MAC_BIT; + set_default(); + }; + + #endif + /* Begin function to be called after initialization: */ void begin() { From 227564ee0c52f236e353b8f80d52e5afb5732b9e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Apr 2020 14:20:25 +0200 Subject: [PATCH 026/323] Strategies README initial info update --- src/strategies/AnalogSampling/README.md | 4 +++- src/strategies/Any/README.md | 4 ++++ src/strategies/DualUDP/README.md | 4 +++- src/strategies/ESPNOW/README.md | 5 ++++- src/strategies/EthernetTCP/README.md | 4 +++- src/strategies/GlobalUDP/README.md | 4 +++- src/strategies/LocalFile/README.md | 4 +++- src/strategies/LocalUDP/README.md | 4 +++- src/strategies/MQTTTranslate/README.md | 4 +++- src/strategies/OverSampling/README.md | 5 +++-- src/strategies/SoftwareBitBang/README.md | 3 ++- src/strategies/ThroughLoRa/README.md | 4 +++- src/strategies/ThroughSerial/README.md | 5 +++-- src/strategies/ThroughSerialAsync/README.md | 5 +++-- 14 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/strategies/AnalogSampling/README.md b/src/strategies/AnalogSampling/README.md index 5313d49e79..32b35529e7 100644 --- a/src/strategies/AnalogSampling/README.md +++ b/src/strategies/AnalogSampling/README.md @@ -1,6 +1,8 @@ ## AnalogSampling -**Medium**: light pulses over air or optic-fibre | **Pins used**: 1 or 2 +**Medium:** Light pulses over air or optic-fibre | +**Pins used:** 1 or 2 | +**Inclusion constant:** `PJON_INCLUDE_AS` `AnalogSampling` strategy or data link complies with [PJDLS v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md), it is designed to communicate data wirelessly using light impulses and its sampling technique is based on analog readings. This strategy is able to use a single LED for both photo-emission and photo-reception phases providing with wireless half-duplex connectivity between devices with a range of up to 5 meters. Most appliances have at least a useless energy consuming LED on board, right? diff --git a/src/strategies/Any/README.md b/src/strategies/Any/README.md index 659df8f036..1bd01636c7 100644 --- a/src/strategies/Any/README.md +++ b/src/strategies/Any/README.md @@ -1,5 +1,9 @@ ## Any +**Medium:** Any | +**Pins used:** NA | +**Inclusion constant:** `PJON_INCLUDE_ANY` + The `Any` strategy includes virtual inheritance and let PJON objects change from a strategy to another after instantiation or a collection of PJON objects with different strategies to be treated agnostically. ### How to use Any diff --git a/src/strategies/DualUDP/README.md b/src/strategies/DualUDP/README.md index 4c0468911f..42e38d986c 100644 --- a/src/strategies/DualUDP/README.md +++ b/src/strategies/DualUDP/README.md @@ -1,6 +1,8 @@ ## DualUDP -**Medium:** Ethernet port, wired or WiFi +**Medium:** Ethernet port, wired or WiFi | +**Pins used:** NA | +**Inclusion constant:** `PJON_INCLUDE_DUDP` With the `DualUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other over an Ethernet network, wired or over WiFi or both. Like the `GlobalUDP` strategy, this strategy is not limited to the local network and can therefore reach devices farther away, to another LAN connected through VPN, or potentially across the Internet (beware of security issues). Like the `DualUDP` strategy it will reach devices on the LAN without configuration. diff --git a/src/strategies/ESPNOW/README.md b/src/strategies/ESPNOW/README.md index f4bf1ed6b3..15dc354f13 100644 --- a/src/strategies/ESPNOW/README.md +++ b/src/strategies/ESPNOW/README.md @@ -1,5 +1,8 @@ ## ESPNOW -**Medium:** 802.11 Peer-to-peer + +**Medium:** ESPNOW protocol | +**Pins used:** NA | +**Inclusion constant:** `PJON_INCLUDE_EN` With the `ESPNOW` PJON strategy, up to 10 ESP32 devices can use PJON to communicate with each other over the [Espressif ESPNOW protocol](https://www.espressif.com/en/products/software/esp-now/overview) (peer-to-peer 802.11). diff --git a/src/strategies/EthernetTCP/README.md b/src/strategies/EthernetTCP/README.md index ef8e9e4680..ccc7e7f0a1 100644 --- a/src/strategies/EthernetTCP/README.md +++ b/src/strategies/EthernetTCP/README.md @@ -1,6 +1,8 @@ ## EthernetTCP -**Medium:** Ethernet port, wired or WiFi +**Medium:** Ethernet port, wired or WiFi | +**Pins used:** NA | +**Inclusion constant:** `PJON_INCLUDE_ETCP` With the `EthernetTCP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other on a LAN, WAN or across the Internet. Take a look at the [video introduction](https://www.youtube.com/watch?v=DQzcAv38yxM) for a brief showcase of its features. diff --git a/src/strategies/GlobalUDP/README.md b/src/strategies/GlobalUDP/README.md index b5c1dc9daa..882d7ae445 100644 --- a/src/strategies/GlobalUDP/README.md +++ b/src/strategies/GlobalUDP/README.md @@ -1,6 +1,8 @@ ## GlobalUDP -**Medium:** Ethernet port, wired or WiFi +**Medium:** Ethernet port, wired or WiFi | +**Pins used:** NA | +**Inclusion constant:** `PJON_INCLUDE_GUDP` With the `GlobalUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other over an Ethernet network, wired or over WiFi or both. This strategy demands a little more configuration than the `LocalUDP` strategy diff --git a/src/strategies/LocalFile/README.md b/src/strategies/LocalFile/README.md index b91db9b9c2..bd9aeba9c3 100644 --- a/src/strategies/LocalFile/README.md +++ b/src/strategies/LocalFile/README.md @@ -1,6 +1,8 @@ ## LocalFile -**Medium:** Hard disk +**Medium:** File on hard disk | +**Pins used:** NA | +**Inclusion constant:** `PJON_INCLUDE_LF` `LocalFile` uses a file present on the hard drive to let multiple processes communicate on the same machine. It can be used for inter-process communication and for developing, simulating and testing applications and networks on a real time operative system without having to deploy physical hardware. diff --git a/src/strategies/LocalUDP/README.md b/src/strategies/LocalUDP/README.md index b5b9f4e280..7663227563 100644 --- a/src/strategies/LocalUDP/README.md +++ b/src/strategies/LocalUDP/README.md @@ -1,6 +1,8 @@ ## LocalUDP -**Medium:** Ethernet port, wired or WiFi +**Medium:** Ethernet port, wired or WiFi | +**Pins used:** NA | +**Inclusion constant:** `PJON_INCLUDE_LUDP` With the `LocalUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other on a local subnet, wired or over WiFi or both. Take a look at the [video introduction](https://www.youtube.com/watch?v=cxEUqkK5BQg) for a brief showcase of its features. diff --git a/src/strategies/MQTTTranslate/README.md b/src/strategies/MQTTTranslate/README.md index e8c754c499..541abe91c2 100644 --- a/src/strategies/MQTTTranslate/README.md +++ b/src/strategies/MQTTTranslate/README.md @@ -1,6 +1,8 @@ ## MQTTTranslate -**Medium:** MQTT protocol +**Medium:** MQTT protocol | +**Pins used:** NA | +**Inclusion constant:** `PJON_INCLUDE_MQTT` MQTTTranslate uses the [ReconnectingMqttClient](https://github.com/fredilarsen/ReconnectingMqttClient) library (minimum version required v1.1.1) to deliver PJON packets over TCP on local network (LAN) as a MQTT protocol client. It may be useful to connect PJON networks and more standard applications to each other using the MQTT protocol. This strategy works in one of four modes. The first two modes enable to implement a PJON bus via MQTT, the first mode is "closed" and the second is "open" to use by non-PJON programs. The last two modes are for behaving like MQTT devices normally do. diff --git a/src/strategies/OverSampling/README.md b/src/strategies/OverSampling/README.md index 37fc5dece7..ae7f005f57 100644 --- a/src/strategies/OverSampling/README.md +++ b/src/strategies/OverSampling/README.md @@ -1,7 +1,8 @@ ## OverSampling -**Media:** Radio, Wire | -**Pins used:** 1 / 2 +**Medium:** ASK/FSK radio modules | +**Pins used:** 1 or 2 | +**Inclusion constant:** `PJON_INCLUDE_OS` `OverSampling` is a software implementation of [PJDLR (Padded Jittering Data Link over Radio)](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md). It supports simplex and half-duplex asynchronous serial communication and implements a carrier-sense, non-persistent random multiple access method (non-persistent CSMA). This implementation can run on limited microcontrollers with low clock accuracy, supports communication for many devices connected to the same medium and stable operation in spite of interference. Its procedure is a more efficient alternative to the LoRa Open Standard (that specifies a variation of Slotted ALOHA) and it is designed to obtain long range and high reliability using FSK, ASK or OOK modulation radio transceivers. Take a look at the [video introduction](https://www.youtube.com/watch?v=G1ckfsMzPns) for a brief showcase of its features. diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index 1c113ec89d..4d9b6774e5 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -1,7 +1,8 @@ ## SoftwareBitBang **Medium:** Wire | -**Pins used:** 1 / 2 +**Pins used:** 1 or 2 | +**Inclusion constant:** `PJON_INCLUDE_SWBB` `SoftwareBitBang` is a software implementation of [PJDL (Padded Jittering Data Link)](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md). It supports simplex and half-duplex asynchronous serial communication for up to 254 devices over a single wire. The maximum length of the bus can reach between 800 and 2000 meters depending on the mode used. It is a valid alternative to 1-Wire because of its flexibility and reliability. Fault tolerance schemes can be easily implemented because communication pins can be configured at runtime. Take a look at the [video introduction](https://www.youtube.com/watch?v=GWlhKD5lz5w) for a brief showcase of its features. ```cpp diff --git a/src/strategies/ThroughLoRa/README.md b/src/strategies/ThroughLoRa/README.md index e8916ce538..a54b7cdbd4 100644 --- a/src/strategies/ThroughLoRa/README.md +++ b/src/strategies/ThroughLoRa/README.md @@ -1,6 +1,8 @@ ## ThroughLoRa -**Medium:** Radio, Wire | **Pins used:** 6 +**Medium:** LoRa radio modules | +**Pins used:** 6 | +**Inclusion constant:** `PJON_INCLUDE_TL` With `ThroughLora` strategy, PJON can run through a software or hardware SPI in order to communicate with supported LoRa modules. See [Supported Shields/Modules](https://github.com/gioblu/PJON/tree/master/src/strategies/ThroughLoRa#supported-shieldsmodules). diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index 3a79792bc9..2fafed7655 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -1,7 +1,8 @@ ## ThroughSerial -**Medium:** Hardware/Software Serial port | -**Pins used:** 1 or 2 +**Medium:** Hardware or software serial port | +**Pins used:** 1 or 2 | +**Inclusion constant:** `PJON_INCLUDE_TS` With `ThroughSerial` strategy, PJON can run through a software or hardware Serial port working out-of-the-box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). Take a look at the [video introduction](https://www.youtube.com/watch?v=H4jUsgvM-lw) for a brief showcase of its features. It complies with [TSDL v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md). diff --git a/src/strategies/ThroughSerialAsync/README.md b/src/strategies/ThroughSerialAsync/README.md index 465546e5e8..3e9ed090b2 100644 --- a/src/strategies/ThroughSerialAsync/README.md +++ b/src/strategies/ThroughSerialAsync/README.md @@ -1,7 +1,8 @@ ## ThroughSerialAsync -**Medium:** Hardware/Software Serial port | -**Pins used:** 1 or 2 +**Medium:** Hardware or software serial port | +**Pins used:** 1 or 2 | +**Inclusion constant:** `PJON_INCLUDE_TSA` With `ThroughSerialAsync` strategy, PJON can run through a software or hardware Serial port working out of the box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). It complies with [TSDL v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md). From ef4903b244ab71ba53ea7a04b1a08a7ecd17852e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Apr 2020 14:23:31 +0200 Subject: [PATCH 027/323] Strategies README initial info separator change --- src/strategies/Any/README.md | 4 ++-- src/strategies/DualUDP/README.md | 4 ++-- src/strategies/ESPNOW/README.md | 4 ++-- src/strategies/EthernetTCP/README.md | 4 ++-- src/strategies/GlobalUDP/README.md | 4 ++-- src/strategies/LocalFile/README.md | 4 ++-- src/strategies/LocalUDP/README.md | 4 ++-- src/strategies/OverSampling/README.md | 4 ++-- src/strategies/SoftwareBitBang/README.md | 4 ++-- src/strategies/ThroughLoRa/README.md | 4 ++-- src/strategies/ThroughSerial/README.md | 4 ++-- src/strategies/ThroughSerialAsync/README.md | 4 ++-- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/strategies/Any/README.md b/src/strategies/Any/README.md index 1bd01636c7..7274baad23 100644 --- a/src/strategies/Any/README.md +++ b/src/strategies/Any/README.md @@ -1,7 +1,7 @@ ## Any -**Medium:** Any | -**Pins used:** NA | +**Medium:** Any - +**Pins used:** NA - **Inclusion constant:** `PJON_INCLUDE_ANY` The `Any` strategy includes virtual inheritance and let PJON objects change from a strategy to another after instantiation or a collection of PJON objects with different strategies to be treated agnostically. diff --git a/src/strategies/DualUDP/README.md b/src/strategies/DualUDP/README.md index 42e38d986c..e119989976 100644 --- a/src/strategies/DualUDP/README.md +++ b/src/strategies/DualUDP/README.md @@ -1,7 +1,7 @@ ## DualUDP -**Medium:** Ethernet port, wired or WiFi | -**Pins used:** NA | +**Medium:** Ethernet port, wired or WiFi - +**Pins used:** NA - **Inclusion constant:** `PJON_INCLUDE_DUDP` With the `DualUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other over an Ethernet network, wired or over WiFi or both. Like the `GlobalUDP` strategy, this strategy is not limited to the local network diff --git a/src/strategies/ESPNOW/README.md b/src/strategies/ESPNOW/README.md index 15dc354f13..ccaeaa97a8 100644 --- a/src/strategies/ESPNOW/README.md +++ b/src/strategies/ESPNOW/README.md @@ -1,7 +1,7 @@ ## ESPNOW -**Medium:** ESPNOW protocol | -**Pins used:** NA | +**Medium:** ESPNOW protocol - +**Pins used:** NA - **Inclusion constant:** `PJON_INCLUDE_EN` With the `ESPNOW` PJON strategy, up to 10 ESP32 devices can use PJON to communicate with each other over diff --git a/src/strategies/EthernetTCP/README.md b/src/strategies/EthernetTCP/README.md index ccc7e7f0a1..0ce839e247 100644 --- a/src/strategies/EthernetTCP/README.md +++ b/src/strategies/EthernetTCP/README.md @@ -1,7 +1,7 @@ ## EthernetTCP -**Medium:** Ethernet port, wired or WiFi | -**Pins used:** NA | +**Medium:** Ethernet port, wired or WiFi - +**Pins used:** NA - **Inclusion constant:** `PJON_INCLUDE_ETCP` With the `EthernetTCP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other on a LAN, WAN or across the Internet. Take a look at the [video introduction](https://www.youtube.com/watch?v=DQzcAv38yxM) for a brief showcase of its features. diff --git a/src/strategies/GlobalUDP/README.md b/src/strategies/GlobalUDP/README.md index 882d7ae445..979ad43230 100644 --- a/src/strategies/GlobalUDP/README.md +++ b/src/strategies/GlobalUDP/README.md @@ -1,7 +1,7 @@ ## GlobalUDP -**Medium:** Ethernet port, wired or WiFi | -**Pins used:** NA | +**Medium:** Ethernet port, wired or WiFi - +**Pins used:** NA - **Inclusion constant:** `PJON_INCLUDE_GUDP` With the `GlobalUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other over an diff --git a/src/strategies/LocalFile/README.md b/src/strategies/LocalFile/README.md index bd9aeba9c3..acbee1ba49 100644 --- a/src/strategies/LocalFile/README.md +++ b/src/strategies/LocalFile/README.md @@ -1,7 +1,7 @@ ## LocalFile -**Medium:** File on hard disk | -**Pins used:** NA | +**Medium:** File on hard disk - +**Pins used:** NA - **Inclusion constant:** `PJON_INCLUDE_LF` `LocalFile` uses a file present on the hard drive to let multiple processes communicate on the same machine. It can be used for inter-process communication and for developing, simulating and testing applications and networks on a real time operative system without having to deploy physical hardware. diff --git a/src/strategies/LocalUDP/README.md b/src/strategies/LocalUDP/README.md index 7663227563..844cf1be45 100644 --- a/src/strategies/LocalUDP/README.md +++ b/src/strategies/LocalUDP/README.md @@ -1,7 +1,7 @@ ## LocalUDP -**Medium:** Ethernet port, wired or WiFi | -**Pins used:** NA | +**Medium:** Ethernet port, wired or WiFi - +**Pins used:** NA - **Inclusion constant:** `PJON_INCLUDE_LUDP` With the `LocalUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other on a local subnet, wired or over WiFi or both. Take a look at the [video introduction](https://www.youtube.com/watch?v=cxEUqkK5BQg) for a brief showcase of its features. diff --git a/src/strategies/OverSampling/README.md b/src/strategies/OverSampling/README.md index ae7f005f57..df9acfec1f 100644 --- a/src/strategies/OverSampling/README.md +++ b/src/strategies/OverSampling/README.md @@ -1,7 +1,7 @@ ## OverSampling -**Medium:** ASK/FSK radio modules | -**Pins used:** 1 or 2 | +**Medium:** ASK/FSK radio modules - +**Pins used:** 1 or 2 - **Inclusion constant:** `PJON_INCLUDE_OS` `OverSampling` is a software implementation of [PJDLR (Padded Jittering Data Link over Radio)](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md). It supports simplex and half-duplex asynchronous serial communication and implements a carrier-sense, non-persistent random multiple access method (non-persistent CSMA). This implementation can run on limited microcontrollers with low clock accuracy, supports communication for many devices connected to the same medium and stable operation in spite of interference. Its procedure is a more efficient alternative to the LoRa Open Standard (that specifies a variation of Slotted ALOHA) and it is designed to obtain long range and high reliability using FSK, ASK or OOK modulation radio transceivers. Take a look at the [video introduction](https://www.youtube.com/watch?v=G1ckfsMzPns) for a brief showcase of its features. diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index 4d9b6774e5..b5d57df9d0 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -1,7 +1,7 @@ ## SoftwareBitBang -**Medium:** Wire | -**Pins used:** 1 or 2 | +**Medium:** Wire - +**Pins used:** 1 or 2 - **Inclusion constant:** `PJON_INCLUDE_SWBB` `SoftwareBitBang` is a software implementation of [PJDL (Padded Jittering Data Link)](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md). It supports simplex and half-duplex asynchronous serial communication for up to 254 devices over a single wire. The maximum length of the bus can reach between 800 and 2000 meters depending on the mode used. It is a valid alternative to 1-Wire because of its flexibility and reliability. Fault tolerance schemes can be easily implemented because communication pins can be configured at runtime. Take a look at the [video introduction](https://www.youtube.com/watch?v=GWlhKD5lz5w) for a brief showcase of its features. diff --git a/src/strategies/ThroughLoRa/README.md b/src/strategies/ThroughLoRa/README.md index a54b7cdbd4..d5f1622a31 100644 --- a/src/strategies/ThroughLoRa/README.md +++ b/src/strategies/ThroughLoRa/README.md @@ -1,7 +1,7 @@ ## ThroughLoRa -**Medium:** LoRa radio modules | -**Pins used:** 6 | +**Medium:** LoRa radio modules - +**Pins used:** 6 - **Inclusion constant:** `PJON_INCLUDE_TL` With `ThroughLora` strategy, PJON can run through a software or hardware SPI in order to communicate with supported LoRa modules. See [Supported Shields/Modules](https://github.com/gioblu/PJON/tree/master/src/strategies/ThroughLoRa#supported-shieldsmodules). diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index 2fafed7655..37768888e6 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -1,7 +1,7 @@ ## ThroughSerial -**Medium:** Hardware or software serial port | -**Pins used:** 1 or 2 | +**Medium:** Hardware or software serial port - +**Pins used:** 1 or 2 - **Inclusion constant:** `PJON_INCLUDE_TS` With `ThroughSerial` strategy, PJON can run through a software or hardware Serial port working out-of-the-box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). Take a look at the [video introduction](https://www.youtube.com/watch?v=H4jUsgvM-lw) for a brief showcase of its features. It complies with [TSDL v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md). diff --git a/src/strategies/ThroughSerialAsync/README.md b/src/strategies/ThroughSerialAsync/README.md index 3e9ed090b2..98506e0e77 100644 --- a/src/strategies/ThroughSerialAsync/README.md +++ b/src/strategies/ThroughSerialAsync/README.md @@ -1,7 +1,7 @@ ## ThroughSerialAsync -**Medium:** Hardware or software serial port | -**Pins used:** 1 or 2 | +**Medium:** Hardware or software serial port - +**Pins used:** 1 or 2 - **Inclusion constant:** `PJON_INCLUDE_TSA` With `ThroughSerialAsync` strategy, PJON can run through a software or hardware Serial port working out of the box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). It complies with [TSDL v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md). From 4d64a1adf258f2ea6f1a3ad78adbd6c4a7ba3d70 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Apr 2020 02:39:35 +0200 Subject: [PATCH 028/323] SWBB examples comments update --- .../Transmitter1/Transmitter1.ino | 9 ++++---- .../Transmitter2/Transmitter2.ino | 9 ++++---- .../Transmitter/Transmitter.ino | 9 ++++---- .../ClassMemberCallback/Receiver/Receiver.ino | 22 +++++++++--------- .../Transmitter/Transmitter.ino | 22 +++++++++--------- .../NetworkAnalysis/Receiver/Receiver.ino | 20 ++++++++-------- .../Transmitter/Transmitter.ino | 20 ++++++++-------- .../NetworkAnalysis/Receiver/Receiver.ino | 14 +++++++++++ .../Transmitter/Transmitter.ino | 19 ++++++++------- .../Receiver/Receiver.ino | 9 ++++---- .../Transmitter/Transmitter.ino | 9 ++++---- .../SendAndReceive/Device1/Device1.ino | 13 +++++++++++ .../SendAndReceive/Device2/Device2.ino | 13 +++++++++++ .../SpeedTest/Receiver/Receiver.ino | 20 ++++++++-------- .../SpeedTest/Transmitter/Transmitter.ino | 22 +++++++++--------- .../UsePacketId/Receiver/Receiver.ino | 18 +++++++++++---- .../UsePacketId/Transmitter/Transmitter.ino | 18 +++++++++++---- .../NetworkAnalysis/Receiver/Receiver.ino | 23 ++++++++++--------- .../Transmitter/Transmitter.ino | 21 +++++++++-------- .../SpeedTest/Receiver/Receiver.ino | 14 +++++++++++ .../SpeedTest/Transmitter/Transmitter.ino | 13 +++++++++++ 21 files changed, 213 insertions(+), 124 deletions(-) diff --git a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino index 77dd0ae64a..8812350967 100644 --- a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino +++ b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino @@ -1,8 +1,9 @@ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 +// Transmission speed modes (see Timing.h) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd /* Acknowledge Latency maximum duration (1000 microseconds default). Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to diff --git a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino index 72b5706876..4b38652cd3 100644 --- a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino +++ b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino @@ -1,8 +1,9 @@ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 +// Transmission speed modes (see Timing.h) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd /* Acknowledge Latency maximum duration (1000 microseconds default). Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to diff --git a/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Transmitter/Transmitter.ino index 0428463830..1af2986715 100644 --- a/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Transmitter/Transmitter.ino @@ -1,8 +1,9 @@ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 +// Transmission speed modes (see Timing.h) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd /* Acknowledge Latency maximum duration (1000 microseconds default). Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to diff --git a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino index f5963244b7..a5cc4bddc7 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino @@ -1,15 +1,15 @@ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 - -/* Acknowledge Latency maximum duration (1000 microseconds default). - Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to - receiver to compute the CRC and to respond with a synchronous acknowledgement - SWBB_RESPONSE_TIMEOUT can be reduced to higher communication speed if - devices are near and able to compute CRC fast enough. */ -//#define SWBB_RESPONSE_TIMEOUT 1000 +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd + +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino index 8732e49d4f..83bb06add6 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino @@ -1,15 +1,15 @@ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 - -/* Acknowledge Latency maximum duration (1000 microseconds default). - Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to - receiver to compute the CRC and to respond with a synchronous acknowledgement - SWBB_RESPONSE_TIMEOUT can be reduced to higher communication speed if - devices are near and able to compute CRC fast enough. */ -//#define SWBB_RESPONSE_TIMEOUT 1000 +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd + +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino index f2d9a3e554..d020e972f0 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino @@ -1,15 +1,15 @@ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Acknowledge Latency maximum duration (1000 microseconds default). - Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to - receiver to compute the CRC and to respond with a synchronous acknowledgement - SWBB_RESPONSE_TIMEOUT can be reduced to higher communication speed if - devices are near and able to compute CRC fast enough. */ -//#define SWBB_RESPONSE_TIMEOUT 1000 +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino index 9b0377c30f..56fa5b6206 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino @@ -1,15 +1,15 @@ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Acknowledge Latency maximum duration (1000 microseconds default). - Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to - receiver to compute the CRC and to respond with a synchronous acknowledgement - SWBB_RESPONSE_TIMEOUT can be reduced to higher communication speed if - devices are near and able to compute CRC fast enough. */ -//#define SWBB_RESPONSE_TIMEOUT 1000 +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino index abf9b513c9..8eb3aba50c 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino @@ -1,8 +1,22 @@ +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd + +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 + // Include only SoftwareBitBang #define PJON_INCLUDE_SWBB + // Include PJONLocal #include + // bus(selected device id) PJONLocal bus(44); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino index 53bf65fc43..65ee27d3e4 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino @@ -1,16 +1,15 @@ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Acknowledge Latency maximum duration (1000 microseconds default). - Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to - receiver to compute the CRC and to respond with a synchronous acknowledgement - SWBB_RESPONSE_TIMEOUT can be reduced to higher communication speed if - devices are near and able to compute CRC fast enough. */ +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ -//#define SWBB_RESPONSE_TIMEOUT 1000 +//#define SWBB_RESPONSE_TIMEOUT 1500 // Include only SoftwareBitBang #define PJON_INCLUDE_SWBB diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino index f4825eff5c..bc2362ce56 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino @@ -6,10 +6,11 @@ transmits a continuous random byte stream. If an incoming packet is detected a false positive occurred. */ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 +// Transmission speed modes (see Timing.h) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Transmitter/Transmitter.ino index 2c6409b0e7..23d81f804a 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Transmitter/Transmitter.ino @@ -6,10 +6,11 @@ The receiver device attempts to receive packets from pin 12. If an incoming packet is detected a false positive occurred. */ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 +// Transmission speed modes (see Timing.h) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino index e3e8c923a3..5ccd572e7c 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino @@ -1,3 +1,16 @@ + +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd + +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 + #include // bus(selected device id) diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino index fe3e57d9c6..efc01733be 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino @@ -1,3 +1,16 @@ + +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd + +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 + #include // bus(selected device id) diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino index 99afacffe9..706a0f824d 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino @@ -1,15 +1,15 @@ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Acknowledge Latency maximum duration (1000 microseconds default). - Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to - receiver to compute the CRC and to respond with a synchronous acknowledgement - SWBB_RESPONSE_TIMEOUT can be reduced to higher communication speed if - devices are near and able to compute CRC fast enough. */ -//#define SWBB_RESPONSE_TIMEOUT 1000 +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino index 4b98dcfdf8..0fae1e6091 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino @@ -1,15 +1,15 @@ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 - -/* Acknowledge Latency maximum duration (1000 microseconds default). - Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to - receiver to compute the CRC and to respond with a synchronous acknowledgement - SWBB_RESPONSE_TIMEOUT can be reduced to higher communication speed if - devices are near and able to compute CRC fast enough. */ -//#define SWBB_RESPONSE_TIMEOUT 1000 +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd + +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino index 1456bf0887..133d844a0d 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino @@ -1,11 +1,19 @@ + +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd + +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 + // Include packet id feature #define PJON_INCLUDE_PACKET_ID -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 - #include float test; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino index 6bf5b87d16..344d2dd6a3 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino @@ -1,11 +1,19 @@ + +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd + +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 + // Include packet id feature #define PJON_INCLUDE_PACKET_ID -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 - #include // bus(selected device id) diff --git a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino index 8d8e581122..82296d2495 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino @@ -1,15 +1,16 @@ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 - -/* Acknowledge Latency maximum duration (1000 microseconds default). - Can be necessary to higher SWBB_SYNC_ACK_TIMEOUT to leave enough time to - receiver to compute the CRC and to respond with a synchronous acknowledgement - SWBB_SYNC_ACK_TIMEOUT can be reduced to higher communication speed if - devices are near and able to compute CRC fast enough. */ -//#define SWBB_SYNC_ACK_TIMEOUT 1000 +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd + +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 + #include diff --git a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino index 939e34f316..3eb0d0eab2 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino @@ -1,15 +1,16 @@ -// Uncomment to run SoftwareBitBang in MODE 2 -// #define SWBB_MODE 2 -// Uncomment to run SoftwareBitBang in MODE 3 -// #define SWBB_MODE 3 +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd + +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 -/* Acknowledge Latency maximum duration (1000 microseconds default). - Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to - receiver to compute the CRC and to respond with a synchronous acknowledgement - SWBB_RESPONSE_TIMEOUT can be reduced to higher communication speed if - devices are near and able to compute CRC fast enough. */ -//#define SWBB_RESPONSE_TIMEOUT 1000 #include diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino index d792f86854..295685912f 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino @@ -1,3 +1,17 @@ + +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd + +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 + + #include float test; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino index 75993c8492..d6cbfd6f38 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino @@ -1,3 +1,16 @@ + +// Uncomment to use the mode you prefer (default SWBB_MODE 1) +// #define SWBB_MODE 1 // 1.95kB/s - 15625Bd +// #define SWBB_MODE 2 // 2.21kB/s - 17696Bd +// #define SWBB_MODE 3 // 2.94kB/s - 23529Bd +// #define SWBB_MODE 4 // 3.40kB/s - 27210Bd + +/* Response timeout (1500 microseconds default). + If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short + specially if long packets are sent or if devices are far from each other */ + +//#define SWBB_RESPONSE_TIMEOUT 1500 + #include // Bus id definition From b55077d089a6e8c2da76420e303379dfd1157c6c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Apr 2020 03:33:01 +0200 Subject: [PATCH 029/323] documentation/addressing update --- documentation/addressing.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/documentation/addressing.md b/documentation/addressing.md index 96f8a7d5b7..016e028f82 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -39,11 +39,11 @@ The device identifier of an object can be read after instantiation using `device ```cpp uint8_t id = bus.device_id(); // Get device id ``` -`device_id` returns 255 or `PJON_NOT_ASSIGNED` if the instance is initialised without configuring its device identifier. +`device_id` returns `PJON_NOT_ASSIGNED` or 255 if the instance is initialised without configuring its device identifier. ### Shared mode -if the medium used is private and not accessible from the outside world (wired network in home, business, industry) any bus indexing scheme can be used without worrying about bus id collision; if instead the network uses a shared medium, such as commonly used radio frequencies like LoRa, it is strongly suggested to request a unique PJON bus id [here](http://www.pjon.org/get-bus-id.php) to avoid collisions. +if the medium used is private and not accessible from the outside world (wired network in home, business, industry) bus ids can be used arbitrarily without any risk of collision; if instead the network uses a shared medium, for example on unlicensed radio frequencies with [ThroughLoRa](/src/strategies/ThroughLoRa), it is strongly suggested to request a unique PJON bus id [here](http://www.pjon.org/get-bus-id.php) to avoid collisions. Instantiation in shared mode: ```cpp @@ -57,3 +57,22 @@ The bus id can be read and set after initialisation using `bus_id`: ```cpp bus.bus_id; // Get or set bus id ``` + +### Hardware identifier + +PJON can optionally operate using the MAC address of the device: +```cpp +// Include MAC address feature +#define PJON_INCLUDE_MAC + +// MAC address of the device +uint8_t mac[6] = {1, 2, 3, 4, 5, 6}; + +PJON bus(mac); +// Local mode, device id PJON_NOT_ASSIGNED +``` +This instantiation sets the MAC address, the device id set to `PJON_NOT_ASSIGNED` or 255 but can be changed afterwards as required. Packets containing a recipient's MAC address that is not equal to the one configured are discarded. PJON can operate in both local and shared mode while including MAC addresses. The feature can be disabled using `includ_mac`: + +```cpp +bus.include_mac(false); +``` From 8ba6e14eb5a8cb6ff91acc55764db9064454c417 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Apr 2020 04:42:11 +0200 Subject: [PATCH 030/323] docs and specs update --- documentation/configuration.md | 4 ++-- .../PJON-protocol-acknowledge-specification-v2.0.md | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index 311e149547..2e268de560 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -23,12 +23,12 @@ Before instantiating PJON it is possible to define the length of its buffers. Pr 20 bytes - packet overhead (5-35 bytes depending on configuration) */ ``` -### Data link configuration +### Strategy configuration PJON is instantiated passing a [strategy](/src/strategies/README.md) template parameter: ```cpp PJON bus; ``` -In the example above the PJON object is instantiated passing [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) strategy. Strategies are classes abstracting the data link layer, making PJON easy to be used on different media. It is possible to instantiate more than one PJON object using different strategies in the same program: +In the example above the PJON object is instantiated passing the [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) strategy. Strategies are classes that abstract the physical transmission of data. It is possible to instantiate more than one PJON object using different strategies in the same program: ```cpp PJON wiredBus; PJON tcpBus; diff --git a/specification/PJON-protocol-acknowledge-specification-v2.0.md b/specification/PJON-protocol-acknowledge-specification-v2.0.md index 17f5ec00f0..ad7e597fe8 100644 --- a/specification/PJON-protocol-acknowledge-specification-v2.0.md +++ b/specification/PJON-protocol-acknowledge-specification-v2.0.md @@ -17,7 +17,7 @@ ``` Invented by Giovanni Blu Mitolo Originally published: 17/10/2016 -Latest revision: 15/04/2020 +Latest revision: 30/04/2020 Related implementation: https://github.com/gioblu/PJON/ Compliant versions: PJON v13.0 and following Released into the public domain @@ -25,7 +25,7 @@ Released into the public domain PJON supports the synchronous acknowledgement feature used to have reception certainty. ### Synchronous acknowledge -The synchronous acknowledgement is a blocking procedure, can be used only within one collision domain, although it is efficient and has a short response delay and is composed by a single byte (decimal 6) at the network layer but each data link may implement it differently according to it features and limitations. +When the synchronous acknowledgement is requested, the transmitter has reception certainty. The acknowledgement is composed by a single byte (`ACK` or 6) at the network layer but each strategy may implement it according to their features and limitations. ```cpp Channel analysis Transmission Response _____ ____________________________________________ _____ @@ -35,4 +35,6 @@ Channel analysis Transmission Response |_____||____|__________|________|____|_________|____||_____| ``` -The graph above contains a packet transmission where the character `@` (decimal 64) is sent to device id `12`. As defined by the [PJON protocol layer specification v4.0](/specification/PJON-protocol-specification-v4.0.md), the header's `ACK` bit high requests a synchronous acknowledgement response, see [PJDL v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md), [PJDLR v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md), [PJDLS v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) and [TSDL v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) specification for additional information. +A receiver device responds `ACK` if transmission occurs correctly, instead does not respond nothing if an error is detected. + +The graph above contains a packet transmission where the character `@` or 64 is sent to device id `12`. As defined by the [PJON protocol layer specification v4.0](/specification/PJON-protocol-specification-v4.0.md), the header's `ACK` bit high requests a synchronous acknowledgement response, see [PJDL v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md), [PJDLR v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md), [PJDLS v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) and [TSDL v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) specification for additional information. From 4879455f4de9f6a5ce70222593aa02b03d2180c1 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Apr 2020 05:42:54 +0200 Subject: [PATCH 031/323] Acknowledge specification update --- README.md | 1 - documentation/configuration.md | 2 +- specification/PJON-network-services-list.md | 1 - .../PJON-protocol-specification-v4.0.md | 22 +++++++++---------- ...FSP-frame-separation-specification-v1.0.md | 1 - ...protocol-acknowledge-specification-v2.0.md | 0 .../specification/PJDLS-specification-v2.0.md | 1 - .../specification/PJDLR-specification-v3.0.md | 1 - .../specification/PJDL-specification-v4.1.md | 1 - .../specification/TSDL-specification-v2.1.md | 1 - .../specification/TSDL-specification-v2.1.md | 1 - 11 files changed, 11 insertions(+), 21 deletions(-) rename specification/{ => obsolete}/PJON-protocol-acknowledge-specification-v2.0.md (100%) diff --git a/README.md b/README.md index 195c2a11a2..0a9cf5c7d5 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,6 @@ PJON is used in thousands of devices and its community has spread worldwide beca ### Specifications - [PJON v4.0](specification/PJON-protocol-specification-v4.0.md) -- [PJON Acknowledge v1.0](specification/PJON-protocol-acknowledge-specification-v1.0.md) - [PJDL v4.1](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) - [PJDLR v3.0](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS v2.0](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) - [TSDL v2.1](src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) ### Publications diff --git a/documentation/configuration.md b/documentation/configuration.md index 2e268de560..aefbe7e488 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -115,7 +115,7 @@ If manual packet handling is required, packet automatic deletion can be avoided ``` ### Acknowledgement -The [synchronous acknowledgement](/specification/PJON-protocol-acknowledge-specification-v1.0.md#synchronous-acknowledge) is by default enabled but can be disabled if required: +With the acknowledgement enabled the transmitter has reception certainty. It is by default enabled but can be disabled if required: ```cpp bus.set_synchronous_acknowledge(false); ``` diff --git a/specification/PJON-network-services-list.md b/specification/PJON-network-services-list.md index 5f178de9b9..c6f111dc76 100644 --- a/specification/PJON-network-services-list.md +++ b/specification/PJON-network-services-list.md @@ -2,7 +2,6 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) -- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - **[Network services list](/specification/PJON-network-services-list.md)** #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index 2a2d0ed657..b463f83135 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -2,7 +2,6 @@ #### Network layer - **[PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md)** -- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) @@ -47,7 +46,7 @@ The graph below shows the conceptual model that characterizes and standardizes t | Broadcast | |________________________________________________| | 2 Data link layer: PJDL, PJDLR, PJDLS, TSDL | -| Synchronous acknowledgement | +| Acknowledgement | | Frame transmission | | Medium access control | |________________________________________________| @@ -61,13 +60,13 @@ The graph below shows the conceptual model that characterizes and standardizes t * Devices communicate using packets with a maximum length of 255 or 65535 bytes * Devices are identified by a unique 8 bits device id * Buses are identified with a 32 bits bus id -* A synchronous acknowledgement can be requested (see [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md)) +* An acknowledgement can be requested * Packets can be optionally identified with a 16 bits packet id * Network services are optionally identified with a 16 bits port id * Hardware can be optionally identified using a MAC address ### Bus -A PJON bus is a group of up to 254 devices. Devices use PJON packets to communicate with each other. Devices can send packets and optionally request a synchronous acknowledgement. Devices can also broadcast packets. When the device id is not known, devices must use id 255. +A PJON bus is a group of up to 254 devices. Devices use PJON packets to communicate with each other. Devices can send packets and optionally request an acknowledgement. Devices can also broadcast packets. When the device id is not known, devices must use id 255. ```cpp _______ _______ _______ _______ | | | | | | | | @@ -84,7 +83,7 @@ ID 255 = NOT ASSIGNED ``` ### Bus network -A PJON bus network is composed by buses present on the same collision domain or interconnected through switches or routers. On a shared medium an additional 32 bits bus id must be used to isolate groups of devices from foreign traffic, enabling many to coexist and network on the same medium. +A PJON bus network is composed by buses present on the same collision domain or interconnected through switches or routers. On a shared medium an additional 32 bits bus id must be used to isolate groups of devices from foreign traffic. ```cpp TWO BUSES SHARING THE SAME MEDIUM 1 collision domain @@ -102,7 +101,7 @@ ______|___________|__________|___________|___ ``` ### Switch -A Switch is a device that forwards packets transparently between connected buses. The switch can operate also if different physical layers are in use. It can rely on a default gateway to operate as a leaf in a larger tree network. +A Switch is a device that forwards packets transparently between connected buses. The switch can operate also if different physical layers are in use and can rely on a default gateway. ```cpp ______ ________ ______ | | PJDL bus | | PJDLR bus | | @@ -113,7 +112,7 @@ ID 254 = DEFAULT GATEWAY ``` ### Router -A router is a device, connected to more than one PJON bus, able to route packets from a device, a bus or a medium to another. Thanks to the hop count, the bus and the device indexing, many routing techniques are supported. Packets can be routed between indirectly connected buses if a routing table or a default gateway is used. +A router is a device connected to more than one PJON bus that routes packets from a device, a bus or a medium to another. Packets can be routed between indirectly connected buses if a routing table or a default gateway is used. ```cpp TWO BUSES CONNECTED THROUGH A ROUTER 2 collision domains @@ -142,7 +141,7 @@ HEADER BITMAP ``` 1. `MODE` bit informs if the packet is formatted in [shared](/specification/PJON-protocol-specification-v4.0.md#shared-mode) (value 1) or [local](/specification/PJON-protocol-specification-v4.0.md#local-mode) mode (value 0) 2. `TX INFO` bit informs if the sender info are included (value 1) or not (value 0) -3. `ACK` bit informs if the [synchronous acknowledgement](/specification/PJON-protocol-acknowledge-specification-v1.0.md#synchronous-acknowledge) is requested (value 1) or not (value 0) +3. `ACK` bit informs if the [acknowledgement](/specification/PJON-protocol-specification-v4.0.md#packet-transmission) is requested (value 1) or not (value 0) 4. `MAC` bit informs if sender's and recipient's [hardware identification](/specification/PJON-protocol-specification-v4.0.md#hardware-identification), or MAC address, are included (value 1) or not (value 0) 5. `PORT` bit informs if a 16 bits [network service identifier](/specification/PJON-protocol-specification-v4.0.md#network-services) is included (value 1) or not (value 0) 6. `CRC` bit signals which CRC is used, [CRC8](/specification/PJON-protocol-specification-v4.0.md#crc8-polynomial) (value 0) or [CRC32](/specification/PJON-protocol-specification-v4.0.md#crc32-polynomial) (value 1) @@ -183,12 +182,11 @@ CRC8 is calculated and appended to the initial meta-data (device id, header and CRC8 is appended at the end of packets of up to 15 bytes length (overhead included). CRC32 is instead used if the packet's length exceeds 15 bytes but can be optionally applied in shorter packets setting the `CRC` bit high if more secure error detection is required. ### Packet transmission -A local packet transmission is an optionally bidirectional communication between two devices that can be divided in 3 phases: **channel analysis**, **transmission** and optional **response**. In the channel analysis phase the medium's state is assessed before starting transmission to avoid collision. If the medium is free for use, the transmission phase starts in which the packet is entirely transmitted in network byte order. The receiving device computes the CRC and starts the response phase transmitting an acknowledge (decimal 6) in case of correct data reception. If no acknowledgement is received, after an exponential back-off delay, the transmitter retries until the acknowledgement is received or a maximum number of attempts is reached. - +A local packet transmission is an optionally bidirectional communication between two devices that can be divided in 3 phases: **medium access**, **transmission** and optional **acknowledgement**. In the medium access phase the medium's state is assessed before starting transmission to avoid collision. If the medium is free for use, the transmission phase starts in which the packet is entirely transmitted in network byte order. The receiving device computes the CRC and starts the acknowledgement phase transmitting `ACK` (decimal 6) in case of correct data reception. If no acknowledgement is received, after an exponential back-off delay, the transmitter retries until the acknowledgement is received or a maximum number of attempts is reached. ```cpp -Channel analysis Transmission Response +Medium access Transmission Response _____ _______________________________________________ _____ -| C-A || ID | HEADER | LENGTH | CRC8 | DATA | CRC8 || ACK | +| M-A || ID | HEADER | LENGTH | CRC8 | DATA | CRC8 || ACK | |-----||----|----------|--------|------|--------|------||-----| | 0 || 12 | 00000100 | 6 | | 64 | || 6 | |_____||____|__________|________|______|________|______||_____| diff --git a/specification/SFSP-frame-separation-specification-v1.0.md b/specification/SFSP-frame-separation-specification-v1.0.md index 73566e5b3b..21fb9b0ba9 100644 --- a/specification/SFSP-frame-separation-specification-v1.0.md +++ b/specification/SFSP-frame-separation-specification-v1.0.md @@ -2,7 +2,6 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) -- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) diff --git a/specification/PJON-protocol-acknowledge-specification-v2.0.md b/specification/obsolete/PJON-protocol-acknowledge-specification-v2.0.md similarity index 100% rename from specification/PJON-protocol-acknowledge-specification-v2.0.md rename to specification/obsolete/PJON-protocol-acknowledge-specification-v2.0.md diff --git a/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md b/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md index 13c33ed602..1aae7cbe33 100644 --- a/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md +++ b/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md @@ -2,7 +2,6 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) -- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) diff --git a/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md b/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md index 1ee6b2a43c..b55fbe05e1 100644 --- a/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md +++ b/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md @@ -3,7 +3,6 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) -- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index 5fe80d47d5..40f8df58a8 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -3,7 +3,6 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) -- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - **[PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md)** diff --git a/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md b/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md index 5ac28ebad7..0dd6783371 100644 --- a/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md +++ b/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md @@ -2,7 +2,6 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) -- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) diff --git a/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md b/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md index 5ac28ebad7..0dd6783371 100644 --- a/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md +++ b/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md @@ -2,7 +2,6 @@ #### Network layer - [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) -- [Acknowledge specification v2.0](/specification/PJON-protocol-acknowledge-specification-v2.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) From 2c1b1adccca73e7f93237c6b5cf5402273388625 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Apr 2020 16:43:52 +0200 Subject: [PATCH 032/323] PJON specification v4.0 refactoring --- .../PJON-protocol-specification-v4.0.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index b463f83135..539a70d5ed 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -22,7 +22,7 @@ Related work: https://github.com/gioblu/PJON/ Compliant implementations: PJON v13.0 and following Released into the public domain ``` -The PJON protocol v4.0 in local mode supports connectivity for up to 254 devices, in shared mode supports connectivity for up to 4.294.967.295 buses (groups of devices) and up to 1.090.921.692.930 devices. The packet format is dynamic therefore meta-data can be optionally included using the header as a bitmap of selected features. It supports interoperability between systems that use a different configuration and provides with high efficiency including only the protocol's features used and the overhead effectively required (5-35 bytes). PJON can be used for simple low-data-rate applications as an alternative to 1-Wire, i2c or CAN but can also be applied in place of IP to interconnect more complex networks. +The PJON protocol v4.0 in local mode supports connectivity for up to 254 devices, in shared mode supports connectivity for up to 4.294.967.295 buses (groups of devices) and up to 1.090.921.692.930 devices. The packet format is dynamic therefore meta-data can be optionally included using the header as a bitmap of selected features. It supports interoperability between systems that use a different configuration and provides with high efficiency including only the protocol's features used and the overhead effectively required (5-35 bytes). PJON can be used for low-data-rate applications as an alternative to 1-Wire, i2c or CAN but can also be applied in place of IP to interconnect more complex networks. The graph below shows the conceptual model that characterizes and standardizes the communication. Its goal is the interoperability of diverse systems on a wide range of media with the use of a new set of Open Standards. The graph partitions represent abstraction layers. @@ -56,14 +56,14 @@ The graph below shows the conceptual model that characterizes and standardizes t ``` ### Basic concepts -* Packet transmission is regulated by a 8 bits header -* Devices communicate using packets with a maximum length of 255 or 65535 bytes * Devices are identified by a unique 8 bits device id * Buses are identified with a 32 bits bus id +* Devices can be optionally identified a 48 bits MAC address +* Devices communicate using packets with a maximum length of 255 or 65535 bytes +* Packet transmission is regulated by a 8 bits header * An acknowledgement can be requested * Packets can be optionally identified with a 16 bits packet id * Network services are optionally identified with a 16 bits port id -* Hardware can be optionally identified using a MAC address ### Bus A PJON bus is a group of up to 254 devices. Devices use PJON packets to communicate with each other. Devices can send packets and optionally request an acknowledgement. Devices can also broadcast packets. When the device id is not known, devices must use id 255. @@ -195,7 +195,7 @@ Medium access Transmission Response ``` #### Local mode -Depending on header's `MODE` bit, PJON packets can contain basic or extended support to identification. Local mode required by header's `MODE` bit low supports connectivity for up to 254 devices. In the graph below is represented the simplest local mode packet format sending `@` (decimal 64) to device `12`: +Depending on header's `MODE` bit packets can contain basic or extended support to identification. Local mode required by header's `MODE` bit low supports connectivity for up to 254 devices. In the graph below is represented the simplest local mode packet format sending `@` (decimal 64) to device `12`: ```cpp _________________________________ @@ -208,7 +208,7 @@ Depending on header's `MODE` bit, PJON packets can contain basic or extended sup ``` -In local mode packets can be broadcasted to all devices sending to device id `0`. Acknowledgement is not supported therefore any broadcasted packet that requests an acknowledgement is ignored by recipients. +In local mode a broadcast can be sent to all devices sending to device id `0`. Acknowledgement is not supported therefore any broadcast that requests an acknowledgement is ignored by recipients. ```cpp _________________________________ @@ -240,7 +240,7 @@ If header's `TX INFO` bit is high the sender's device id is included in the pack ``` #### Shared mode -If header's `MODE` bit is high [bus](/specification/PJON-protocol-specification-v4.0.md#bus) identification is added to the packet. The same local transmission used as an example above is formatted to be sent in shared mode to device id `12` of bus id `0.0.0.1`. The packet's payload is prepended with the bus id of the recipient and the hop count as requested by header's `MODE` bit: +If header's `MODE` bit is high [bus](/specification/PJON-protocol-specification-v4.0.md#bus) identification is added to the packet. The same local transmission used as an example above is formatted to be sent in shared mode to device id `12` of bus id `0.0.0.1`. The packet's payload is prepended with the bus id of the recipient and the hop count: ```cpp _____________________________________________ |ID| HEADER |LENGTH|CRC8|BUS ID|HOP|DATA|CRC8| @@ -252,7 +252,7 @@ If header's `MODE` bit is high [bus](/specification/PJON-protocol-specification- ``` -In shared mode packets can be broadcasted to all devices sharing the same bus id sending to device id `0`. Acknowledgement is not supported, therefore any broadcasted packet that requests an acknowledgement is ignored by recipients. +In shared mode broadcasts can be sent to all devices sharing the same bus id sending to device id `0`. Acknowledgement is not supported therefore any broadcast that requests an acknowledgement is ignored by recipients. ```cpp ____________________________________________ @@ -282,7 +282,7 @@ If header's `TX INFO` bit is high the sender's device and bus id are included in The hop count must be incremented each time the packet is forwarded and routers must ignore packets when a maximum amount of hops is reached. #### Extended length -The graph below shows a packet transmission where the length is represented with 16 bits supporting up to 65535 bytes length as requested by the header's `EXT. LENGTH` bit. If the extended length feature is used, CRC32 must be applied setting the header's `CRC` bit high. +if the header's `EXT. LENGTH` bit is high the length of the packet is represented with 16 bits supporting a maximum length of up to 65535 bytes. If the `EXT. LENGTH` bit is low the packet length is represented with 8 bits supporting a maximum length of up to 255 bytes. If the extended length feature is used, CRC32 must be applied setting the header's `CRC` bit high. ```cpp _______________________________________ |ID| HEADER |LEN 1|LEN 2|CRC8|DATA|CRC32| @@ -295,7 +295,7 @@ The graph below shows a packet transmission where the length is represented with ``` #### Packet identification -The graph below shows a packet in which a 16 bits packet identifier is added as requested by header's `PACKET ID` bit. This feature is provided to avoid duplications and guarantee packet uniqueness. The receiver filters packets containing a packet identifier and sender information that already appeared previously. +if the header's `PACKET ID` bit is high a 16 bits packet identifier is added to the packet. The graph below shows a packet in which a 16 bits packet identifier is included. This feature is provided to avoid duplications and guarantee packet uniqueness. The receiver discards packets containing a packet identifier and sender information already appeared previously. ```cpp ____________________________________________ |ID| HEADER |LENGTH|CRC8|PACKET ID|DATA|CRC32| @@ -308,7 +308,7 @@ The graph below shows a packet in which a 16 bits packet identifier is added as ``` #### Network services -PJON supports a network service identifier using a 16 bits port id. Thanks to this feature different services, protocols or formats can coexist and be identified safely. Ports from `0` to `8000` are reserved to known services which index is present in the [known network services list](/specification/PJON-network-services-list.md), ports from `8001` to `65535` are free for use. The graph below shows a packet transmission where port 8002 is inserted in the packet and header's `PORT` bit is high to signal its presence. +if the header's `PORT` bit is high a 16 bits port id is added to the packet. Thanks to this feature different services, protocols or formats can coexist and be identified safely. Ports from `0` to `8000` are reserved for the [known network services](/specification/PJON-network-services-list.md), ports from `8001` to `65535` are free for use. The graph below shows a packet transmission where port 8002 is inserted in the packet and header's `PORT` bit is high to signal its presence. ```cpp _________________________________________ |ID| HEADER |LENGTH|CRC8|PORT ID|DATA|CRC8| From e8d06ca763e7359023d652d30b074d846b5d0ad9 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 May 2020 14:33:32 +0200 Subject: [PATCH 033/323] documentation/data-reception update --- documentation/data-reception.md | 86 +++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 25 deletions(-) diff --git a/documentation/data-reception.md b/documentation/data-reception.md index 3dcc182811..30ab9ff555 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -12,52 +12,88 @@ ## Data reception A function of type `void` can be defined and register to be called by the PJON object when a packet is received. This function receives 3 parameters: the received payload of type `uint8_t *`, its length of type `uint16_t` and a pointer to a data structure of type `const PJON_Packet_Info` that contains all packet's metadata: + +```cpp +void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &info) { + // Print received data in the serial monitor + for(uint16_t i = 0; i < length; i++) + Serial.print(payload[i]); +}; +``` + +Register the `receiver_function` as the receiver callback: ```cpp -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ +bus.set_receiver(receiver_function); +``` + +Within `receiver_function` it is possible to process data and meta-data. The `PJON_Packet_Info` struct contains all the protocol fields present in the packet: + +```cpp +struct PJON_Packet_Info { + PJON_End_Point tx; + PJON_End_Point rx; + void *custom_pointer; + uint8_t header = PJON_NO_HEADER; + uint8_t hops = 0; + uint16_t id = 0; + uint16_t port = PJON_BROADCAST; +}; +``` +`PJON_Packet_Info` contains `port` if [`PJON_INCLUDE_PORT`](/documentation/configuration.md#network-service-identification) is defined and `id` if [`PJON_INCLUDE_PACKET_ID`](/documentation/configuration.md#packet-identification) is defined. The conditional inclusion is present to reduce the footprint of programs where the port and the packet id are not used. + +The `PJON_Packet_Info` struct contains `tx` and `rx` of type `PJON_End_point` where the packet's sender and recipient information is contained: +```cpp +struct PJON_End_Point { + uint8_t id = PJON_NOT_ASSIGNED; + uint8_t bus_id[4] = {0, 0, 0, 0}; + uint8_t mac[6] = {0, 0, 0, 0, 0, 0}; +}; +``` +`PJON_End_Point` contains `mac` if [`PJON_INCLUDE_MAC`](/documentation/configuration.md#hardware-identification) is defined. The conditional inclusion is present to reduce the footprint of programs where the MAC address is not used. + +The code below is part of the Arduino compatible [PortsUseExample](/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino). When the `receiver_function` is called meta-data present in the `info` parameter is transmitted over serial: +```cpp +void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &info) { Serial.print("Header: "); - Serial.print(packet_info.header, BIN); + Serial.print(info.header, BIN); // If packet formatted for a shared medium - if(packet_info.header & PJON_MODE_BIT) { + if(info.header & PJON_MODE_BIT) { Serial.print(" Receiver bus id: "); - Serial.print(packet_info.receiver_bus_id[0]); - Serial.print(packet_info.receiver_bus_id[1]); - Serial.print(packet_info.receiver_bus_id[2]); - Serial.print(packet_info.receiver_bus_id[3]); + Serial.print(info.rx.bus_id[0]); + Serial.print(info.rx.bus_id[1]); + Serial.print(info.rx.bus_id[2]); + Serial.print(info.rx.bus_id[3]); Serial.print(" Receiver id: "); - Serial.print(packet_info.receiver_id); + Serial.print(info.rx.id); // If sender info is included - if(packet_info.header & PJON_TX_INFO_BIT) { + if(info.header & PJON_TX_INFO_BIT) { Serial.print(" Sender bus id: "); - Serial.print(packet_info.sender_bus_id[0]); - Serial.print(packet_info.sender_bus_id[1]); - Serial.print(packet_info.sender_bus_id[2]); - Serial.print(packet_info.sender_bus_id[3]); + Serial.print(info.tx.bus_id[0]); + Serial.print(info.tx.bus_id[1]); + Serial.print(info.tx.bus_id[2]); + Serial.print(info.tx.bus_id[3]); } } // If sender device id is included - if(packet_info.header & PJON_TX_INFO_BIT) { + if(info.header & PJON_TX_INFO_BIT) { Serial.print(" Sender id: "); - Serial.print(packet_info.sender_id); + Serial.print(info.tx.id); } // Payload Length Serial.print(" Length: "); Serial.print(length); // If port id is included - if(packet_info.header & PJON_PORT_BIT) { + if(info.header & PJON_PORT_BIT) { Serial.print(" Port bit: "); - Serial.print(packet_info.port); + Serial.print(info.port); } Serial.println(); -} -``` -Register the `receiver_function` as the receiver callback: -```cpp -bus.set_receiver(receiver_function); +}; ``` -To pass custom data to the receiver callback function, se the [ClassMemberCallback](../examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback) example. This feature can be used for a lot of different use cases. Could be used to let multiple PJON objects call the same callback function, passing an `int` specifying which PJON instance has to be called, or a pointer to the PJON object, or an `enum` or whatever. +To pass custom data to the receiver callback function, se the [ClassMemberCallback](../examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback) example. This feature can be used to link other classes or instances passing any sort of data structure. + +Use `payload` before any transmission, the buffer where `payload` points to is overwritten when a new packet is dispatched. To receive the `receive` function must be called at least once per loop cycle: ```cpp From 96279fae62df3b3219e3e398351bce650de3e165 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 May 2020 15:34:15 +0200 Subject: [PATCH 034/323] documentation/data-reception minor fix --- documentation/data-reception.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/documentation/data-reception.md b/documentation/data-reception.md index 30ab9ff555..b8b2e47d00 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -11,7 +11,7 @@ --- ## Data reception -A function of type `void` can be defined and register to be called by the PJON object when a packet is received. This function receives 3 parameters: the received payload of type `uint8_t *`, its length of type `uint16_t` and a pointer to a data structure of type `const PJON_Packet_Info` that contains all packet's metadata: +A function of type `void` is called by the PJON object when a packet is received. This function receives 3 parameters: the received payload of type `uint8_t *`, its length of type `uint16_t` and a pointer to a data structure of type `const PJON_Packet_Info` that contains all packet's metadata: ```cpp void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &info) { @@ -23,10 +23,11 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info Register the `receiver_function` as the receiver callback: ```cpp +PJON bus; bus.set_receiver(receiver_function); ``` -Within `receiver_function` it is possible to process data and meta-data. The `PJON_Packet_Info` struct contains all the protocol fields present in the packet: +Within `receiver_function` it is possible to process data and meta-data when a packet is received. The `PJON_Packet_Info` struct contains all the protocol fields present in the packet: ```cpp struct PJON_Packet_Info { @@ -41,7 +42,7 @@ struct PJON_Packet_Info { ``` `PJON_Packet_Info` contains `port` if [`PJON_INCLUDE_PORT`](/documentation/configuration.md#network-service-identification) is defined and `id` if [`PJON_INCLUDE_PACKET_ID`](/documentation/configuration.md#packet-identification) is defined. The conditional inclusion is present to reduce the footprint of programs where the port and the packet id are not used. -The `PJON_Packet_Info` struct contains `tx` and `rx` of type `PJON_End_point` where the packet's sender and recipient information is contained: +`PJON_Packet_Info` contains `tx` and `rx` of type `PJON_End_point` where the packet's sender and recipient information is contained: ```cpp struct PJON_End_Point { uint8_t id = PJON_NOT_ASSIGNED; @@ -90,12 +91,11 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info Serial.println(); }; ``` - -To pass custom data to the receiver callback function, se the [ClassMemberCallback](../examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback) example. This feature can be used to link other classes or instances passing any sort of data structure. - Use `payload` before any transmission, the buffer where `payload` points to is overwritten when a new packet is dispatched. -To receive the `receive` function must be called at least once per loop cycle: +To understand how to pass custom data to the receiver callback function, see the [ClassMemberCallback](../examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback) example. This feature can be used to link other classes or instances passing any sort of data structure. + +To receive data the `receive` function must be called as often as possible: ```cpp uint16_t response = bus.receive(); ``` @@ -105,7 +105,7 @@ uint16_t response = bus.receive(); - `PJON_BUSY` (666) if a transmission for other devices is occurring - `PJON_FAIL` (65535) if no data is received -If you want to dedicate a certain timeframe to reception call the `receive` function passing the maximum reception time in microseconds: +If it is required to dedicate a certain time to reception call the `receive` function passing the maximum reception time in microseconds: ```cpp uint16_t response = bus.receive(1000); ``` From d4664836af50e835b7afb77c64e70c76b0992f87 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 May 2020 15:35:04 +0200 Subject: [PATCH 035/323] PJON protocol specification minor fix --- specification/PJON-protocol-specification-v4.0.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index 539a70d5ed..a334b9c924 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -15,7 +15,7 @@ ## PJON® v4.0 ``` Invented by Giovanni Blu Mitolo -Header feature proposed by Fred Larsen +with the help Fred Larsen Originally published: 10/04/2010 Latest revision: 27/04/2020 Related work: https://github.com/gioblu/PJON/ @@ -58,7 +58,7 @@ The graph below shows the conceptual model that characterizes and standardizes t ### Basic concepts * Devices are identified by a unique 8 bits device id * Buses are identified with a 32 bits bus id -* Devices can be optionally identified a 48 bits MAC address +* Devices can be optionally identified with a 48 bits MAC address * Devices communicate using packets with a maximum length of 255 or 65535 bytes * Packet transmission is regulated by a 8 bits header * An acknowledgement can be requested @@ -66,7 +66,7 @@ The graph below shows the conceptual model that characterizes and standardizes t * Network services are optionally identified with a 16 bits port id ### Bus -A PJON bus is a group of up to 254 devices. Devices use PJON packets to communicate with each other. Devices can send packets and optionally request an acknowledgement. Devices can also broadcast packets. When the device id is not known, devices must use id 255. +A bus is a group of up to 254 devices. Devices use packets to communicate with each other. Devices can send packets and optionally request an acknowledgement. Devices can also broadcast packets. When the device id is not known, devices must use id 255. ```cpp _______ _______ _______ _______ | | | | | | | | @@ -83,7 +83,7 @@ ID 255 = NOT ASSIGNED ``` ### Bus network -A PJON bus network is composed by buses present on the same collision domain or interconnected through switches or routers. On a shared medium an additional 32 bits bus id must be used to isolate groups of devices from foreign traffic. +A bus network is composed by buses present on the same collision domain or interconnected through switches or routers. On a shared medium an additional 32 bits bus id must be used to isolate groups of devices from foreign traffic. ```cpp TWO BUSES SHARING THE SAME MEDIUM 1 collision domain @@ -101,7 +101,7 @@ ______|___________|__________|___________|___ ``` ### Switch -A Switch is a device that forwards packets transparently between connected buses. The switch can operate also if different physical layers are in use and can rely on a default gateway. +A switch is a device that forwards packets transparently between connected buses. The switch can operate also if different physical layers are in use and can rely on a default gateway. ```cpp ______ ________ ______ | | PJDL bus | | PJDLR bus | | @@ -252,7 +252,7 @@ If header's `MODE` bit is high [bus](/specification/PJON-protocol-specification- ``` -In shared mode broadcasts can be sent to all devices sharing the same bus id sending to device id `0`. Acknowledgement is not supported therefore any broadcast that requests an acknowledgement is ignored by recipients. +In shared mode a broadcast can be sent to all devices sharing the same bus id sending to device id `0`. Acknowledgement is not supported therefore any broadcast that requests an acknowledgement is ignored by recipients. ```cpp ____________________________________________ From e448f445261d5e2fca320cdb6266fee8fa185bb9 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 May 2020 19:19:53 +0200 Subject: [PATCH 036/323] configuration and specification minor fix --- documentation/configuration.md | 6 +++--- documentation/data-reception.md | 2 +- specification/PJON-protocol-specification-v4.0.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index aefbe7e488..cffd624553 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -14,7 +14,7 @@ PJON uses predefined constants, setters and getters to support features and constraints configuration. ### Buffers configuration -Before instantiating PJON it is possible to define the length of its buffers. Predefining `PJON_MAX_PACKETS` and `PJON_PACKET_MAX_LENGTH` it is possible to configure this constraints to reach the project memory requirements. Obviously, the less memory is dedicated to buffers, the more memory can be used for something else: +Before instantiating PJON it is possible to define the length of its buffers. Predefining `PJON_MAX_PACKETS` and `PJON_PACKET_MAX_LENGTH` it is possible to configure these constraints to reach the project memory requirements. Obviously, the less memory is dedicated to buffers, the more memory can be used for something else: ```cpp #define PJON_MAX_PACKETS 1 #define PJON_PACKET_MAX_LENGTH 20 @@ -51,7 +51,7 @@ In the example above the PJON object is instantiated passing the [SoftwareBitBan | [LocalFile](/src/strategies/LocalFile) | Shared file system in memory | None | None | | [Any](/src/strategies/Any) | Virtual inheritance, any of the above | Any of the above | Any of the above | -By default all strategies are included except `MQTTTranslate`, `LocalFile`, `ThroughLoRa` and `ESPNOW`. To reduce memory footprint add for example `#define PJON_INCLUDE_SWBB` before including the library to select only the `SoftwareBitBang` strategy. More than one strategy related constants can defined in the same program if that is required. +By default all strategies are included except `MQTTTranslate`, `LocalFile`, `ThroughLoRa` and `ESPNOW`. To reduce memory footprint add for example `#define PJON_INCLUDE_SWBB` before including the library to select only the `SoftwareBitBang` strategy. More than one strategy related constants can be defined in the same program if that is required. Supported definitions: - `PJON_INCLUDE_SWBB` includes `SoftwareBitBang` @@ -91,7 +91,7 @@ The communication mode can be configured using the `set_communication_mode` pass ``` ### Router mode -Use `set_router` to configure the device in router mode, simply receiving all the incoming packets: +When an instance is configured in router mode it is able to receive all incoming packets without any bus or device id filtering. Use `set_router` to configure the router mode: ```cpp bus.set_router(true); ``` diff --git a/documentation/data-reception.md b/documentation/data-reception.md index b8b2e47d00..a128c10853 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -109,4 +109,4 @@ If it is required to dedicate a certain time to reception call the `receive` fun ```cpp uint16_t response = bus.receive(1000); ``` -Consider that SoftwareBitBang, OverSampling or AnalogSampling are strategies able receive data only while `bus.receive` is being executed, otherwise data is lost and transmitter will try again in future. In this particular case it is mandatory to dedicate a certain timeframe, depending on the duration of the other tasks, to efficiently receive data and avoid repetitions. +Consider that SoftwareBitBang, OverSampling or AnalogSampling are strategies able to receive data only while `bus.receive` is being executed, otherwise data is lost and transmitter will try again in future. In this particular case it is mandatory to dedicate a certain timeframe, depending on the duration of the other tasks, to efficiently receive data and avoid repetitions. diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index a334b9c924..86d48a9cc4 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -15,7 +15,7 @@ ## PJON® v4.0 ``` Invented by Giovanni Blu Mitolo -with the help Fred Larsen +with the help of Fred Larsen Originally published: 10/04/2010 Latest revision: 27/04/2020 Related work: https://github.com/gioblu/PJON/ From 8594d2307658ab4bf78bfc6c49ccffedf4def16b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 May 2020 20:55:04 +0200 Subject: [PATCH 037/323] PJON_End_point -> PJON_Endpoint --- documentation/data-reception.md | 10 +++++----- keywords.txt | 2 +- src/PJON.h | 4 ++-- src/PJONDefines.h | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/documentation/data-reception.md b/documentation/data-reception.md index a128c10853..452f81690e 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -31,8 +31,8 @@ Within `receiver_function` it is possible to process data and meta-data when a p ```cpp struct PJON_Packet_Info { - PJON_End_Point tx; - PJON_End_Point rx; + PJON_Endpoint tx; + PJON_Endpoint rx; void *custom_pointer; uint8_t header = PJON_NO_HEADER; uint8_t hops = 0; @@ -42,15 +42,15 @@ struct PJON_Packet_Info { ``` `PJON_Packet_Info` contains `port` if [`PJON_INCLUDE_PORT`](/documentation/configuration.md#network-service-identification) is defined and `id` if [`PJON_INCLUDE_PACKET_ID`](/documentation/configuration.md#packet-identification) is defined. The conditional inclusion is present to reduce the footprint of programs where the port and the packet id are not used. -`PJON_Packet_Info` contains `tx` and `rx` of type `PJON_End_point` where the packet's sender and recipient information is contained: +`PJON_Packet_Info` contains `tx` and `rx` of type `PJON_Endpoint` where the packet's sender and recipient information is contained: ```cpp -struct PJON_End_Point { +struct PJON_Endpoint { uint8_t id = PJON_NOT_ASSIGNED; uint8_t bus_id[4] = {0, 0, 0, 0}; uint8_t mac[6] = {0, 0, 0, 0, 0, 0}; }; ``` -`PJON_End_Point` contains `mac` if [`PJON_INCLUDE_MAC`](/documentation/configuration.md#hardware-identification) is defined. The conditional inclusion is present to reduce the footprint of programs where the MAC address is not used. +`PJON_Endpoint` contains `mac` if [`PJON_INCLUDE_MAC`](/documentation/configuration.md#hardware-identification) is defined. The conditional inclusion is present to reduce the footprint of programs where the MAC address is not used. The code below is part of the Arduino compatible [PortsUseExample](/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino). When the `receiver_function` is called meta-data present in the `info` parameter is transmitted over serial: ```cpp diff --git a/keywords.txt b/keywords.txt index b94167243e..44c014206a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -18,7 +18,7 @@ PJONInteractiveRouter KEYWORD1 PJONVirtualBusRouter KEYWORD1 PJONTools KEYWORD1 PJON_Packet KEYWORD1 -PJON_End_Point KEYWORD1 +PJON_Endpoint KEYWORD1 PJON_Packet_Info KEYWORD1 PJON_Error KEYWORD1 diff --git a/src/PJON.h b/src/PJON.h index 0f6f60e884..acd5f38219 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -83,7 +83,7 @@ class PJON { PJON_Packet_Info last_packet_info; PJON_Packet packets[PJON_MAX_PACKETS]; uint8_t random_seed = A0; - PJON_End_Point tx; + PJON_Endpoint tx; #if(PJON_INCLUDE_PACKET_ID) PJON_Packet_Record recent_packet_ids[PJON_MAX_RECENT_PACKET_IDS]; @@ -483,7 +483,7 @@ class PJON { const void *payload, uint16_t length ) { - PJON_End_Point original_end_point = tx; + PJON_Endpoint original_end_point = tx; tx = info.tx; if(++info.hops > PJON_MAX_HOPS) return PJON_FAIL; uint16_t result = PJON_FAIL; diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 25e3d78e90..a218189bfd 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -194,7 +194,7 @@ struct PJON_Packet_Record { #endif }; -struct PJON_End_Point { +struct PJON_Endpoint { uint8_t id = PJON_NOT_ASSIGNED; #ifndef PJON_LOCAL uint8_t bus_id[4] = {0, 0, 0, 0}; @@ -205,8 +205,8 @@ struct PJON_End_Point { }; struct PJON_Packet_Info { - PJON_End_Point tx; - PJON_End_Point rx; + PJON_Endpoint tx; + PJON_Endpoint rx; uint8_t header = PJON_NO_HEADER; #ifndef PJON_LOCAL void *custom_pointer; From 5b1921993e1dc490fcc19b212199f1c45de03419 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 2 May 2020 03:03:12 +0200 Subject: [PATCH 038/323] set_synchronous_acknowledge -> set_acknowledge (breaking compatibility) --- documentation/configuration.md | 2 +- .../OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino | 2 +- .../OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino | 2 +- .../ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino | 2 +- .../Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino | 2 +- .../ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino | 2 +- .../ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino | 2 +- examples/ARDUINO/Local/ThroughLoRa/JSON/Receiver/Receiver.ino | 2 +- .../Local/ThroughLoRa/JSON/Transmitter/Transmitter.ino | 2 +- .../Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino | 2 +- .../ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino | 2 +- .../ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino | 2 +- .../RS485-BlinkWithResponse/Receiver/Receiver.ino | 2 +- .../RS485-BlinkWithResponse/Transmitter/Transmitter.ino | 2 +- .../OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino | 2 +- .../OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino | 2 +- .../RPI/Local/ThroughSerial/BlinkWithResponse/Transmitter.cpp | 2 +- .../ThroughSerial/RS485-BlinkWithResponse/Transmitter.cpp | 2 +- keywords.txt | 2 +- src/PJON.h | 2 +- src/PJONLocal.h | 2 +- src/strategies/ThroughLoRa/README.md | 4 ++-- 22 files changed, 23 insertions(+), 23 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index cffd624553..e410b4d2fb 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -117,7 +117,7 @@ If manual packet handling is required, packet automatic deletion can be avoided ### Acknowledgement With the acknowledgement enabled the transmitter has reception certainty. It is by default enabled but can be disabled if required: ```cpp - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); ``` ### Packet identification diff --git a/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino b/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino index 8769d7adab..84e86b4341 100644 --- a/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino +++ b/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino @@ -24,7 +24,7 @@ void setup() { a different port group to avoid cross-talk. */ bus.strategy.set_pins(7, 12); - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); bus.set_receiver(receiver_function); bus.begin(); diff --git a/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino b/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino index d5f5831460..22e71b4911 100644 --- a/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino +++ b/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino @@ -24,7 +24,7 @@ void setup() { a different port group to avoid cross-talk. */ bus.strategy.set_pins(7, 12); - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); bus.set_receiver(receiver_function); bus.begin(); diff --git a/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino index 9a78a13587..442d8dd8d7 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino @@ -23,7 +23,7 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); // Initialize LED 13 to be off // Synchronous acknowledgement is not supported - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); // Obligatory to initialize Radio with correct frequency bus.strategy.setFrequency(868100000UL); // Optional diff --git a/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino index 66dd0996df..fb9a18b9c0 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino @@ -10,7 +10,7 @@ PJON bus(45); void setup() { // Synchronous acknowledgement is not supported - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); // Obligatory to initialize Radio with correct frequency bus.strategy.setFrequency(868100000UL); // Optional diff --git a/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino b/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino index 28a6922875..0b60c4e853 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino @@ -40,7 +40,7 @@ void setup() { bus.set_receiver(receiver_function); bus.set_error(error_handler); // Synchronous acknowledgement is not supported - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); // Obligatory to initialize Radio with correct frequency bus.strategy.setFrequency(868100000UL); // Optional diff --git a/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino b/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino index c1ab33db99..30984fe768 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino @@ -40,7 +40,7 @@ void setup() { bus.set_error(error_handler); bus.set_receiver(receiver_function); // Synchronous acknowledgement is not supported - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); // Obligatory to initialize Radio with correct frequency bus.strategy.setFrequency(868100000UL); // Optional diff --git a/examples/ARDUINO/Local/ThroughLoRa/JSON/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughLoRa/JSON/Receiver/Receiver.ino index e0454bf699..26eb93ae30 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/JSON/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/JSON/Receiver/Receiver.ino @@ -14,7 +14,7 @@ void setup() { Serial.begin(115200); Serial.println("LoRa Receiver"); // Synchronous acknowledgement is not supported - LoraPJON.set_synchronous_acknowledge(false); + LoraPJON.set_acknowledge(false); // Obligatory to initialize Radio with correct frequency LoraPJON.strategy.setFrequency(868100000UL); // Optional diff --git a/examples/ARDUINO/Local/ThroughLoRa/JSON/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughLoRa/JSON/Transmitter/Transmitter.ino index 00a6c36c37..250dddd61f 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/JSON/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/JSON/Transmitter/Transmitter.ino @@ -17,7 +17,7 @@ void setup() { Serial.begin(115200); Serial.println("LoRa Transmitter"); // Synchronous acknowledgement is not supported - LoraPJON.set_synchronous_acknowledge(false); + LoraPJON.set_acknowledge(false); // Obligatory to initialize Radio with correct frequency LoraPJON.strategy.setFrequency(868100000UL); // Optional diff --git a/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino index 06d4779f18..e5bb54b6c2 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino @@ -11,7 +11,7 @@ PJON bus(44); void setup() { // Synchronous acknowledgement is not supported - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); // Obligatory to initialize Radio with correct frequency bus.strategy.setFrequency(868100000UL); // Optional diff --git a/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino index 27c9962acd..22a3db819b 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino @@ -32,7 +32,7 @@ void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { void setup() { // Synchronous acknowledgement is not supported - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); // Obligatory to initialize Radio with correct frequency bus.strategy.setFrequency(868100000UL); // Optional diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino index 649910eec3..dc72840008 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino @@ -20,7 +20,7 @@ void setup() { bus.strategy.set_serial(&HC12); // Avoid synchronous acknowledgement - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); bus.begin(); diff --git a/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Receiver/Receiver.ino index b483c19870..e6cd650b0f 100644 --- a/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Receiver/Receiver.ino @@ -12,7 +12,7 @@ void setup() { bus.strategy.set_serial(&Serial); bus.strategy.set_enable_RS485_pin(2); bus.set_receiver(receiver_function); - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); bus.begin(); }; diff --git a/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter/Transmitter.ino index 356db121a2..57eaa6dc05 100644 --- a/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter/Transmitter.ino @@ -26,7 +26,7 @@ void setup() { bus.strategy.set_serial(&Serial); bus.strategy.set_enable_RS485_pin(2); - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); bus.set_receiver(receiver_function); bus.begin(); diff --git a/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino b/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino index 65d9c8dd1c..4bb2ad571d 100644 --- a/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino +++ b/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino @@ -41,7 +41,7 @@ void setup() { a different port group to avoid cross-talk. */ bus.strategy.set_pins(7, 12); - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); bus.set_receiver(receiver_function); bus.begin(); diff --git a/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino b/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino index d20e5b2b6c..089cdb5dff 100644 --- a/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino +++ b/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino @@ -41,7 +41,7 @@ void setup() { a different port group to avoid cross-talk. */ bus.strategy.set_pins(7, 12); - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); bus.set_receiver(receiver_function); bus.begin(); diff --git a/examples/RPI/Local/ThroughSerial/BlinkWithResponse/Transmitter.cpp b/examples/RPI/Local/ThroughSerial/BlinkWithResponse/Transmitter.cpp index 193cc26a39..7a85f773d6 100644 --- a/examples/RPI/Local/ThroughSerial/BlinkWithResponse/Transmitter.cpp +++ b/examples/RPI/Local/ThroughSerial/BlinkWithResponse/Transmitter.cpp @@ -56,7 +56,7 @@ int main() { bus.strategy.set_baud_rate(baud_rate); printf("Bus initialization \n"); - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); bus.set_receiver(receiver_function); bus.begin(); diff --git a/examples/RPI/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter.cpp b/examples/RPI/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter.cpp index fe8d361e33..bf916bf8d0 100644 --- a/examples/RPI/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter.cpp +++ b/examples/RPI/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter.cpp @@ -57,7 +57,7 @@ int main() { bus.strategy.set_enable_RS485_pin(1); // GPIO pin 18 = WiringPi pin 1 printf("Bus initialization \n"); - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); bus.set_receiver(receiver_function); bus.begin(); diff --git a/keywords.txt b/keywords.txt index 44c014206a..493443a260 100644 --- a/keywords.txt +++ b/keywords.txt @@ -57,7 +57,7 @@ send KEYWORD2 send_repeatedly KEYWORD2 send_packet KEYWORD2 send_packet_blocking KEYWORD2 -set_synchronous_acknowledge KEYWORD2 +set_acknowledge KEYWORD2 set_random_seed KEYWORD2 set_communication_mode KEYWORD2 set_error KEYWORD2 diff --git a/src/PJON.h b/src/PJON.h index acd5f38219..372d5cc3f5 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -682,7 +682,7 @@ class PJON { state = true -> Request 8 bits synchronous acknowledgement state = false -> Do not request synchronous acknowledgement */ - void set_synchronous_acknowledge(bool state) { + void set_acknowledge(bool state) { set_config_bit(state, PJON_ACK_REQ_BIT); }; diff --git a/src/PJONLocal.h b/src/PJONLocal.h index 2127de6f6a..eec940edec 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -315,7 +315,7 @@ class PJONLocal { TRUE: Send 8bits synchronous acknowledge when a packet is received FALSE: Avoid acknowledge transmission */ - void set_synchronous_acknowledge(bool state) { + void set_acknowledge(bool state) { set_config_bit(state, PJON_ACK_REQ_BIT); }; diff --git a/src/strategies/ThroughLoRa/README.md b/src/strategies/ThroughLoRa/README.md index d5f1622a31..6bfbf828f9 100644 --- a/src/strategies/ThroughLoRa/README.md +++ b/src/strategies/ThroughLoRa/README.md @@ -75,7 +75,7 @@ void setup() { bus.strategy.setFrequency(868100000UL); bus.begin(); // Synchronous acknowledgement is not supported - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); // Send B to device 44 every second bus.send_repeatedly(44, "B", 1, 1000000); }; @@ -103,7 +103,7 @@ void setup() { // Obligatory to initialize Radio with correct frequency bus.strategy.setFrequency(868100000UL); // Synchronous acknowledgement is not supported - bus.set_synchronous_acknowledge(false); + bus.set_acknowledge(false); // Optional bus.strategy.setSignalBandwidth(250E3); bus.begin(); From 2581fcb262f682ee14a2f53459e35252b4e8be21 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 2 May 2020 03:06:17 +0200 Subject: [PATCH 039/323] send_synchronous_acknowledge -> send_acknowledge (breaking compatibility) --- src/PJON.h | 2 +- src/PJONLocal.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 372d5cc3f5..7ca4b36240 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -667,7 +667,7 @@ class PJON { /* In router mode, the receiver function can acknowledge for selected receiver device ids for which the route is known */ - void send_synchronous_acknowledge() { + void send_acknowledge() { strategy.send_response(PJON_ACK); }; diff --git a/src/PJONLocal.h b/src/PJONLocal.h index eec940edec..2a60004601 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -302,7 +302,7 @@ class PJONLocal { /* In router mode, the receiver function can acknowledge for selected receiver device ids for which the route is known */ - void send_synchronous_acknowledge() { strategy.send_response(PJON_ACK); }; + void send_acknowledge() { strategy.send_response(PJON_ACK); }; /* Set the config bit state: */ From 5ad080e609552a19a8e74bd8d53fb9038f03223c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 May 2020 03:41:14 +0200 Subject: [PATCH 040/323] ThroughSerialAsync ack vulnerability fix (breaking compatibility) --- .../ThroughSerialAsync/ThroughSerialAsync.h | 42 +++++++++++++++---- src/strategies/ThroughSerialAsync/Timing.h | 14 ++++++- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/strategies/ThroughSerialAsync/ThroughSerialAsync.h b/src/strategies/ThroughSerialAsync/ThroughSerialAsync.h index 51117121cb..4afd35dca2 100644 --- a/src/strategies/ThroughSerialAsync/ThroughSerialAsync.h +++ b/src/strategies/ThroughSerialAsync/ThroughSerialAsync.h @@ -109,11 +109,15 @@ class ThroughSerialAsync { uint16_t receive_response() { uint32_t time = PJON_MICROS(); + uint8_t i = 0; while((uint32_t)(PJON_MICROS() - time) < TSA_RESPONSE_TIME_OUT) { if(PJON_SERIAL_AVAILABLE(serial)) { int16_t read = PJON_SERIAL_READ(serial); _last_reception_time = PJON_MICROS(); - if(read >= 0) return (uint8_t)read; + if(read >= 0) { + if(_response[i++] != read) return TSA_FAIL; + if(i == TSA_RESPONSE_LENGTH) return PJON_ACK; + } } #if defined(_WIN32) PJON_DELAY_MICROSECONDS(TSA_RESPONSE_TIME_OUT / 10); @@ -242,6 +246,7 @@ class ThroughSerialAsync { case TSA_DONE: { memcpy(&data[0], &buffer[0], position); + prepare_response(buffer, position); state = TSA_WAITING; return position; } @@ -262,15 +267,35 @@ class ThroughSerialAsync { }; + /* The last 5 bytes of the frame are used as a unique identifier within + the response. PJON has CRC8 or CRC32 at the end of the packet, encoding + a CRC (that is a good hashing algorithm) and using 40 bits looks enough + to provide a relatively safe response that should be nearly flawless + (yield few false positives per millennia). */ + + void prepare_response(const uint8_t *buffer, uint16_t position) { + uint8_t raw = 0; + for(int8_t i = 0; i < TSA_RESPONSE_LENGTH; i++) { + raw = buffer[(position - ((TSA_RESPONSE_LENGTH - 1) - i)) - 1]; + _response[i] = ( + (raw == TSA_START) || (raw == TSA_ESC) || (raw == TSA_END) + ) ? (raw - 1) : raw; // Avoid encoding symbols + } + }; + + /* Send byte response to the packet's transmitter */ void send_response(uint8_t response) { - start_tx(); - wait_RS485_pin_change(); - send_byte(response); - PJON_SERIAL_FLUSH(serial); - wait_RS485_pin_change(); - end_tx(); + if(response == PJON_ACK) { + start_tx(); + wait_RS485_pin_change(); + for(uint8_t i = 0; i < TSA_RESPONSE_LENGTH; i++) + send_byte(_response[i]); + PJON_SERIAL_FLUSH(serial); + wait_RS485_pin_change(); + end_tx(); + } }; @@ -304,6 +329,8 @@ class ThroughSerialAsync { #endif PJON_SERIAL_FLUSH(serial); end_tx(); + // Prepare expected response for the receive_response call + prepare_response(data, length); }; @@ -390,6 +417,7 @@ class ThroughSerialAsync { uint16_t _flush_offset = TSA_FLUSH_OFFSET; uint32_t _bd; #endif + uint8_t _response[TSA_RESPONSE_LENGTH]; uint32_t _last_reception_time = 0; uint32_t _last_call_time = 0; uint8_t _enable_RS485_rxe_pin = TSA_NOT_ASSIGNED; diff --git a/src/strategies/ThroughSerialAsync/Timing.h b/src/strategies/ThroughSerialAsync/Timing.h index a271f4eff4..d1df878a75 100644 --- a/src/strategies/ThroughSerialAsync/Timing.h +++ b/src/strategies/ThroughSerialAsync/Timing.h @@ -38,12 +38,12 @@ /* Set 10 milliseconds as the maximum timeframe between transmission and synchronous acknowledgement response. Its optimal configuration is strictly related to the maximum time needed by receiver to receive, compute - and transmit back an ACK (decimal 6) */ + and transmit back a response. */ #ifndef TSA_RESPONSE_TIME_OUT #define TSA_RESPONSE_TIME_OUT 10000 #endif -/* Minum timeframe with channel free for use before transmission. +/* Minum duration of channel free for use before transmission. (Avoid disrupting synchronous acknowledgement exchange) */ #ifndef TSA_TIME_IN #define TSA_TIME_IN TSA_RESPONSE_TIME_OUT + TSA_COLLISION_DELAY @@ -62,6 +62,16 @@ #define TSA_BYTE_TIME_OUT 1000000 #endif +/* Response length (the response is composed by the last TSA_RESPONSE_LENGTH + bytes of the packet received). By default should be relatively safe. + (Few false positives per millennia) + If you are ready to trade safety for bandwidth reduce it, consider that + setting TSA_RESPONSE_LENGTH < 4 reduces reliability and leads to higher + chances of detecting a false positive. */ +#ifndef TSA_RESPONSE_LENGTH + #define TSA_RESPONSE_LENGTH 5 +#endif + /* Maximum transmission attempts */ #ifndef TSA_MAX_ATTEMPTS #define TSA_MAX_ATTEMPTS 20 From 1ad29471fbff37ed5e36bebf896a5d5a1764bd34 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 May 2020 03:44:03 +0200 Subject: [PATCH 041/323] docs minor fix --- documentation/configuration.md | 2 +- documentation/error-handling.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index e410b4d2fb..d4fe8d9beb 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -115,7 +115,7 @@ If manual packet handling is required, packet automatic deletion can be avoided ``` ### Acknowledgement -With the acknowledgement enabled the transmitter has reception certainty. It is by default enabled but can be disabled if required: +With the acknowledgement enabled the transmitter has reception certainty. It is by default enabled but can be disabled: ```cpp bus.set_acknowledge(false); ``` diff --git a/documentation/error-handling.md b/documentation/error-handling.md index f3e9f122d5..a3e7d0542c 100644 --- a/documentation/error-handling.md +++ b/documentation/error-handling.md @@ -14,9 +14,9 @@ PJON is designed to inform the user if an error is detected. A function of type `void` can be defined and registered to be called by the PJON object in case of error; it receives 3 parameters, the first is the error code of type `uint8_t`, the second is additional data related to the error of type `uint16_t` and the third is a general purpose custom pointer of type `void *`. Error types: -- `PJON_CONNECTION_LOST` (value 101), `data` parameter contains lost packet's index in the packets buffer. -- `PJON_PACKETS_BUFFER_FULL` (value 102), `data` parameter contains buffer length. -- `PJON_CONTENT_TOO_LONG` (value 104), `data` parameter contains content length. +- `PJON_CONNECTION_LOST` or 101, `data` parameter contains lost packet's index in the buffer. +- `PJON_PACKETS_BUFFER_FULL` or 102, `data` parameter contains buffer length. +- `PJON_CONTENT_TOO_LONG` or 104, `data` parameter contains content length. ```cpp void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { From ebd5cbde17366d331717d1c6a210546d76811cc6 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 May 2020 14:54:33 +0200 Subject: [PATCH 042/323] ThroughLora ack support added (breaking compatibility) --- src/strategies/PJON_Strategies.h | 2 +- src/strategies/ThroughLoRa/README.md | 8 +---- src/strategies/ThroughLoRa/ThroughLora.h | 45 +++++++++++++++++++----- src/strategies/ThroughLoRa/Timing.h | 16 +++++++-- 4 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/strategies/PJON_Strategies.h b/src/strategies/PJON_Strategies.h index 1050a2f7f5..39d3941c1d 100644 --- a/src/strategies/PJON_Strategies.h +++ b/src/strategies/PJON_Strategies.h @@ -73,7 +73,7 @@ !defined(PJON_INCLUDE_TS) && !defined(PJON_INCLUDE_NONE) && \ !defined(PJON_INCLUDE_TSA) && !defined(PJON_INCLUDE_DUDP) && \ !defined(PJON_INCLUDE_LF) && !defined(PJON_INCLUDE_SM) && \ - !defined(PJON_INCLUDE_MQTT) + !defined(PJON_INCLUDE_MQTT) && !defined(PJON_INCLUDE_TL) #include "Any/Any.h" #include "AnalogSampling/AnalogSampling.h" #include "OverSampling/OverSampling.h" diff --git a/src/strategies/ThroughLoRa/README.md b/src/strategies/ThroughLoRa/README.md index 6bfbf828f9..dda75b134d 100644 --- a/src/strategies/ThroughLoRa/README.md +++ b/src/strategies/ThroughLoRa/README.md @@ -8,8 +8,6 @@ With `ThroughLora` strategy, PJON can run through a software or hardware SPI in This strategy is a wrapper around [Arduino LoRa library](https://github.com/sandeepmistry/arduino-LoRa) created by [Sandeep Mistry](https://github.com/sandeepmistry) so all the credit to the specific LoRa implementation goes to him. -Consider that, because of the inherent limitations of LoRa, the synchronous acknowledgement is not supported. - ### Compatibility - ATmega88/168/328 16MHz (Diecimila, Duemilanove, Uno, Nano, Mini, Lillypad) - ATmega2560 16MHz (Arduino Mega) @@ -56,7 +54,7 @@ bus.strategy.setFrequency(868100000UL); //initialize 868 MHZ module - `DIO0` pin is optional, it is only needed for receive callback mode. If `DIO0` pin is used, it **must** be interrupt capable via [`attachInterrupt(...)`](https://www.arduino.cc/en/Reference/AttachInterrupt). ### Usage Example -Here are listed basic examples of a transmitter and receiver code. After tou include the necessary code to initialize the Lora module you can use the normal PJON functions to handle data communication. +Here are listed basic examples of a transmitter and receiver code. After you include the necessary code to initialize the Lora module you can use the normal PJON functions to handle data communication. Keep in mind that to use the LoRa startegy you must download the [Arduino LoRa library](https://github.com/sandeepmistry/arduino-LoRa). @@ -74,8 +72,6 @@ void setup() { // Obligatory to initialize Radio with correct frequency bus.strategy.setFrequency(868100000UL); bus.begin(); - // Synchronous acknowledgement is not supported - bus.set_acknowledge(false); // Send B to device 44 every second bus.send_repeatedly(44, "B", 1, 1000000); }; @@ -102,8 +98,6 @@ void setup() { // Obligatory to initialize Radio with correct frequency bus.strategy.setFrequency(868100000UL); - // Synchronous acknowledgement is not supported - bus.set_acknowledge(false); // Optional bus.strategy.setSignalBandwidth(250E3); bus.begin(); diff --git a/src/strategies/ThroughLoRa/ThroughLora.h b/src/strategies/ThroughLoRa/ThroughLora.h index 5247f23035..bfe86bf6b4 100644 --- a/src/strategies/ThroughLoRa/ThroughLora.h +++ b/src/strategies/ThroughLoRa/ThroughLora.h @@ -84,11 +84,11 @@ class ThroughLora { LoRa.setTxPower(txPower, boostPin); }; - void idle(uint8_t txPower, uint8_t boostPin) { + void idle() { LoRa.idle(); }; - void sleep(uint8_t txPower, uint8_t boostPin) { + void sleep() { LoRa.sleep(); }; @@ -100,9 +100,7 @@ class ThroughLora { (returns always true) */ bool begin(uint8_t did = 0) { - PJON_DELAY_MICROSECONDS( - PJON_RANDOM(TL_INITIAL_DELAY) + did - ); + PJON_DELAY_MICROSECONDS(PJON_RANDOM(TL_INITIAL_DELAY) + did); return true; }; @@ -125,21 +123,45 @@ class ThroughLora { PJON_DELAY_MICROSECONDS(PJON_RANDOM(TL_COLLISION_DELAY)); }; + /* The last 5 bytes of the frame are used as a unique identifier within + the response. PJON has CRC8 or CRC32 at the end of the packet, encoding + a CRC (that is a good hashing algorithm) and using 40 bits looks enough + to provide a relatively safe response that should be nearly flawless + (yield few false positives per millennia). */ + + void prepare_response(const uint8_t *buffer, uint16_t position) { + for(int8_t i = 0; i < TL_RESPONSE_LENGTH; i++) + _response[i] = + buffer[(position - ((TL_RESPONSE_LENGTH - 1) - i)) - 1]; + }; + /* Receive byte response (not supported) */ uint16_t receive_response() { - return PJON_ACK; + uint32_t time = PJON_MICROS(); + while((uint32_t)(PJON_MICROS() - time) < TL_RESPONSE_TIME_OUT) { + uint8_t frame_size = LoRa.parsePacket(); + if(frame_size == TL_RESPONSE_LENGTH) { + for(uint8_t i = 0; i < TL_RESPONSE_LENGTH; i++) + if(LoRa.read() != _response[i]) return PJON_FAIL; + return PJON_ACK; + } + } + return PJON_FAIL; }; /* Receive a frame: */ uint16_t receive_frame(uint8_t *data, uint16_t max_length) { uint8_t frameSize = LoRa.parsePacket(); - if(frameSize > 0) { + /* Filter frames if too short to contain a PJON packet + or if too long to be received */ + if((frameSize > 5) && (frameSize <= max_length)) { while(LoRa.available()) { *data = LoRa.read(); data++; } + prepare_response(data, frameSize); return frameSize; } else return PJON_FAIL; }; @@ -153,7 +175,12 @@ class ThroughLora { /* Send byte response to the packet's transmitter (not supported) */ void send_response(uint8_t response) { - return; + if(response == PJON_ACK) { + start_tx(); + for(uint8_t i = 0; i < TL_RESPONSE_LENGTH; i++) + send_byte(_response[i]); + end_tx(); + } }; /* Send a frame: */ @@ -162,6 +189,7 @@ class ThroughLora { start_tx(); for(uint8_t b = 0; b < length; b++) send_byte(data[b]); + prepare_response(data, length); end_tx(); }; @@ -175,4 +203,5 @@ class ThroughLora { private: uint32_t _last_reception_time; + uint8_t _response[TL_RESPONSE_LENGTH]; }; diff --git a/src/strategies/ThroughLoRa/Timing.h b/src/strategies/ThroughLoRa/Timing.h index 732fa9a759..dfe933b339 100644 --- a/src/strategies/ThroughLoRa/Timing.h +++ b/src/strategies/ThroughLoRa/Timing.h @@ -32,15 +32,25 @@ Higher if necessary. */ #ifndef TL_RESPONSE_TIME_OUT - #define TL_RESPONSE_TIME_OUT 100000UL + #define TL_RESPONSE_TIME_OUT 100000 #endif /* Maximum transmission attempts (re-transmission not supported) */ #ifndef TL_MAX_ATTEMPTS - #define TL_MAX_ATTEMPTS 0 + #define TL_MAX_ATTEMPTS 5 #endif /* Back-off exponential degree (re-transmission not supported) */ #ifndef TL_BACK_OFF_DEGREE - #define TL_BACK_OFF_DEGREE 1 + #define TL_BACK_OFF_DEGREE 5 +#endif + +/* Response length (the response is composed by the last TL_RESPONSE_LENGTH + bytes of the packet received). By default should be relatively safe. + (Few false positives per millennia) + If you are ready to trade safety for bandwidth reduce it, consider that + setting TL_RESPONSE_LENGTH < 4 reduces reliability and leads to higher + chances of detecting a false positive. */ +#ifndef TL_RESPONSE_LENGTH + #define TL_RESPONSE_LENGTH 5 #endif From 85c15abda18f0a5946e1079d76ba41ad2531eefd Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 10 May 2020 23:36:35 +0200 Subject: [PATCH 043/323] TSDL v3.0 specification update --- .../specification/TSDL-specification-v3.0.md | 51 +++++++++++++++++++ .../{ => obsolete}/TSDL-specification-v2.1.md | 0 2 files changed, 51 insertions(+) create mode 100644 src/strategies/ThroughSerialAsync/specification/TSDL-specification-v3.0.md rename src/strategies/ThroughSerialAsync/specification/{ => obsolete}/TSDL-specification-v2.1.md (100%) diff --git a/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v3.0.md b/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v3.0.md new file mode 100644 index 0000000000..214aabd9b1 --- /dev/null +++ b/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v3.0.md @@ -0,0 +1,51 @@ +### Specifications index + +#### Network layer +- [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) +- [Network services list](/specification/PJON-network-services-list.md) +#### Data link layer +- [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) +- [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) +- [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) +- **[TSDL (Tardy Serial Data Link) v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md)** +- [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) + +--- + +## TSDL v3.0 +``` +Invented by Giovanni Blu Mitolo +Originally published: 20/11/2017, latest revision: 09/05/2020 +Related implementation: /src/strategies/ThroughSerial/ +Compliant versions: PJON v13.0 and following +Released into the public domain +``` +TSDL (Tardy Serial Data Link) is a simplex or half-duplex serial data link that supports both master-slave and multi-master modes. It supports collision avoidance, reliable frame separation and optional synchronous response to frame transmissions. +```cpp + ______ TX RX ______ +| |-------| | +|DEVICE| |DEVICE| +|______|-------|______| + RX TX +``` +TSDL can be used to establish a point-to-point link between two devices if used with a bare serial link, or to support one or many to many communication using radio or RS485 transceivers. + +### Medium access control +TSDL operates in master-slave mode applying the request-response procedure and specifies a variation of slotted ALOHA medium access method for multi-master mode. Before a frame transmission the serial buffer is read, if not empty ongoing communication is detected and collision avoided, if empty for a duration longer than the response time-out plus a short random time, frame transmission starts in which the packet is entirely transmitted. Of all contention based random multiple access methods, slotted ALOHA, which maximum data throughput is only 36.8% of the available bandwidth, is one of the least efficient, therefore TSDL in multi-master mode should not be used in networks where many devices often need to arbitrarily transmit data. + +### Frame transmission +Before a frame transmission the communication medium is analysed, if any data is received communication is detected and collision is avoided, if logic 0 is detected for a duration longer than the response time-out plus a small random time, data is transmitted encapsulated in a [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) frame. + +### Synchronous response +A frame transmission in both master-slave and multi-master modes can be optionally followed by a synchronous response of its recipient, all devices must use the same response time-out to avoid collisions. The acknowledgment reception phase must occur before the response time-out to be successful. The synchronous response is composed by the last 5 bytes of the received frame that are used by both devices as the frame identifier. If any SFSP flag occurs in the response payload its value is reduced by 1. PJON has a CRC8 or CRC32 at the end of the packet, encoding a CRC (that is a good hashing algorithm) and using 40 bits looks enough to provide a relatively safe response that should yield few false positives per millennia. +```cpp + Transmission Response + _____ ____ ____ ____ ____ ____ ___ _____ + |START|BYTE|BYTE|BYTE|BYTE|BYTE|END| | ACK | + |-----|----|----|----|----|----|---|--|-----| + | 149 | C | I | A | O | ! |234| |CIAO!| + |_____|____|____|____|____|____|___| |_____| +BITS: | 8 | 8 | 8 | 8 | 8 | 8 | 8 | | 40 | + |_____|____|____|____|____|____|___| |_____| +``` +The required response time-out for a given application can be determined practically transmitting the longest supported frame with the farthest physical distance between the two devices. The highest interval between packet transmission and acknowledgement measured plus a small margin is the correct time-out that should exclude acknowledgement losses. diff --git a/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md b/src/strategies/ThroughSerialAsync/specification/obsolete/TSDL-specification-v2.1.md similarity index 100% rename from src/strategies/ThroughSerialAsync/specification/TSDL-specification-v2.1.md rename to src/strategies/ThroughSerialAsync/specification/obsolete/TSDL-specification-v2.1.md From b7b2bfbe8433c0465d772717bc1db74b3af23c05 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 10 May 2020 23:51:16 +0200 Subject: [PATCH 044/323] TSDL specification links update --- README.md | 2 +- documentation/configuration.md | 4 ++-- specification/PJON-network-services-list.md | 2 +- specification/PJON-protocol-specification-v4.0.md | 2 +- specification/SFSP-frame-separation-specification-v1.0.md | 2 +- .../AnalogSampling/specification/PJDLS-specification-v2.0.md | 2 +- .../OverSampling/specification/PJDLR-specification-v3.0.md | 2 +- src/strategies/README.md | 4 ++-- .../SoftwareBitBang/specification/PJDL-specification-v4.1.md | 2 +- src/strategies/ThroughSerial/README.md | 2 +- src/strategies/ThroughSerialAsync/README.md | 2 +- .../specification/TSDL-specification-v3.0.md | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 0a9cf5c7d5..79a872c38f 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ PJON is used in thousands of devices and its community has spread worldwide beca ### Specifications - [PJON v4.0](specification/PJON-protocol-specification-v4.0.md) -- [PJDL v4.1](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) - [PJDLR v3.0](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS v2.0](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) - [TSDL v2.1](src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) +- [PJDL v4.1](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) - [PJDLR v3.0](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS v2.0](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) - [TSDL v3.0](src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) ### Publications - [PJON protocol handbook](https://www.pjon-technologies.com/collections/frontpage/products/pjon-protocol-hand-book) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) diff --git a/documentation/configuration.md b/documentation/configuration.md index d4fe8d9beb..2301f3b935 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -39,8 +39,8 @@ In the example above the PJON object is instantiated passing the [SoftwareBitBan | [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Electrical impulses over wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | 1 or 2 | | [OverSampling](/src/strategies/OverSampling) | Electrical/radio impulses over wire/air | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | 1 or 2 | | [AnalogSampling](/src/strategies/AnalogSampling) | Light pulses over air or optic fiber | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | 1 or 2 | -| [ThroughSerial](/src/strategies/ThroughSerial) | Electrical/radio impulses over wire/air | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) | 1 or 2 | -| [ThroughSerialAsync](/src/strategies/ThroughSerialAsync) | Electrical/radio impulses over wire/air | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) | 1 or 2 | +| [ThroughSerial](/src/strategies/ThroughSerial) | Electrical/radio impulses over wire/air | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | +| [ThroughSerialAsync](/src/strategies/ThroughSerialAsync) | Electrical/radio impulses over wire/air | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | | [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio impulses over air | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | 3 or 4 | | [EthernetTCP](/src/strategies/EthernetTCP) | Electrical/radio impulses over wire/air | [TCP](https://tools.ietf.org/html/rfc793) | Ethernet or WiFi | | [LocalUDP](/src/strategies/LocalUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | diff --git a/specification/PJON-network-services-list.md b/specification/PJON-network-services-list.md index c6f111dc76..cc13b5c754 100644 --- a/specification/PJON-network-services-list.md +++ b/specification/PJON-network-services-list.md @@ -7,7 +7,7 @@ - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) - [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) -- [TSDL (Tardy Serial Data Link) v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) +- [TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) - [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) --- diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index 86d48a9cc4..1f28047fe6 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -7,7 +7,7 @@ - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) - [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) -- [TSDL (Tardy Serial Data Link) v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) +- [TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) - [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) --- diff --git a/specification/SFSP-frame-separation-specification-v1.0.md b/specification/SFSP-frame-separation-specification-v1.0.md index 21fb9b0ba9..37cdeb2e71 100644 --- a/specification/SFSP-frame-separation-specification-v1.0.md +++ b/specification/SFSP-frame-separation-specification-v1.0.md @@ -7,7 +7,7 @@ - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) - [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) -- [TSDL (Tardy Serial Data Link) v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) +- [TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) - **[SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md)** --- diff --git a/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md b/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md index 1aae7cbe33..2bbcac0b72 100644 --- a/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md +++ b/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md @@ -7,7 +7,7 @@ - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) - [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - **[PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md)** -- [TSDL (Tardy Serial Data Link) v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) +- [TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) - [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) --- diff --git a/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md b/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md index b55fbe05e1..5b435c4daf 100644 --- a/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md +++ b/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md @@ -8,7 +8,7 @@ - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) - **[PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md)** - [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) -- [TSDL (Tardy Serial Data Link) v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) +- [TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) - [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) --- diff --git a/src/strategies/README.md b/src/strategies/README.md index 4fbe38071a..67ddce6856 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -7,8 +7,8 @@ A strategy is an abstraction layer used to physically transmit data. Thanks to t | [SoftwareBitBang](SoftwareBitBang) | Electrical impulses over wire | [PJDL](SoftwareBitBang/specification/PJDL-specification-v4.1.md) | 1 or 2 | | [OverSampling](OverSampling) | Electrical/radio impulses over wire/air | [PJDLR](OverSampling/specification/PJDLR-specification-v3.0.md) | 1 or 2 | | [AnalogSampling](AnalogSampling) | Light pulses over air or optic fiber | [PJDLS](AnalogSampling/specification/PJDLS-specification-v2.0.md) | 1 or 2 | -| [ThroughSerial](ThroughSerial) | Electrical/radio impulses over wire/air | [TSDL](ThroughSerial/specification/TSDL-specification-v2.1.md) | 1 or 2 | -| [ThroughSerialAsync](ThroughSerialAsync) | Electrical/radio impulses over wire/air | [TSDL](ThroughSerial/specification/TSDL-specification-v2.1.md) | 1 or 2 | +| [ThroughSerial](ThroughSerial) | Electrical/radio impulses over wire/air | [TSDL](ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | +| [ThroughSerialAsync](ThroughSerialAsync) | Electrical/radio impulses over wire/air | [TSDL](ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | | [ThroughLoRa](ThroughLoRa) | Radio impulses over air | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | 3 or 4 | | [EthernetTCP](EthernetTCP) | Electrical/radio impulses over wire/air | [TCP](https://tools.ietf.org/html/rfc793) | Ethernet of WiFi | | [LocalUDP](LocalUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet of WiFi | diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index 40f8df58a8..d05b7ba3b2 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -8,7 +8,7 @@ - **[PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md)** - [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) -- [TSDL (Tardy Serial Data Link) v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) +- [TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) - [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) --- diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index 37768888e6..0ba20eb4bd 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -4,7 +4,7 @@ **Pins used:** 1 or 2 - **Inclusion constant:** `PJON_INCLUDE_TS` -With `ThroughSerial` strategy, PJON can run through a software or hardware Serial port working out-of-the-box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). Take a look at the [video introduction](https://www.youtube.com/watch?v=H4jUsgvM-lw) for a brief showcase of its features. It complies with [TSDL v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md). +With `ThroughSerial` strategy, PJON can run through a software or hardware Serial port working out-of-the-box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). Take a look at the [video introduction](https://www.youtube.com/watch?v=H4jUsgvM-lw) for a brief showcase of its features. It complies with [TSDL v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md). ### Why PJON over Serial? Serial communication is fast and reliable but it is often useless without all the features PJON contains. `ThroughSerial` has been developed to enable PJON communication through a serial data link. Adding PJON on top of Serial it is possible to leverage of the PJON protocol layer features like acknowledge, addressing, multiplexing, packet handling, 8 or 32-bit CRC and traffic control. diff --git a/src/strategies/ThroughSerialAsync/README.md b/src/strategies/ThroughSerialAsync/README.md index 98506e0e77..75e1d03b0b 100644 --- a/src/strategies/ThroughSerialAsync/README.md +++ b/src/strategies/ThroughSerialAsync/README.md @@ -4,7 +4,7 @@ **Pins used:** 1 or 2 - **Inclusion constant:** `PJON_INCLUDE_TSA` -With `ThroughSerialAsync` strategy, PJON can run through a software or hardware Serial port working out of the box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). It complies with [TSDL v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md). +With `ThroughSerialAsync` strategy, PJON can run through a software or hardware Serial port working out of the box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). It complies with [TSDL v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md). This strategy is based upon the `ThroughSerial` but reception is asynchronous and completely non-blocking, making good use of hardware buffers and sparing time that `ThroughSerial` looses polling. It is not required to call `bus.receive()` with any delay, just call it frequently to see if there are any packets that have been received. diff --git a/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v3.0.md b/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v3.0.md index 214aabd9b1..f8a41f4c93 100644 --- a/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v3.0.md +++ b/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v3.0.md @@ -7,7 +7,7 @@ - [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) - [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) -- **[TSDL (Tardy Serial Data Link) v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md)** +- **[TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md)** - [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) --- From d560f39919aad88b9adaf208bd60eed2b0d84227 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 May 2020 00:10:36 +0200 Subject: [PATCH 045/323] ThroughSerial blocking implementation deleted --- src/strategies/ThroughSerial/README.md | 67 ---- src/strategies/ThroughSerial/ThroughSerial.h | 293 ------------------ src/strategies/ThroughSerial/Timing.h | 77 ----- .../specification/TSDL-specification-v2.1.md | 49 --- .../obsolete/TSDL-specification-v1.0.md | 62 ---- .../obsolete/TSDL-specification-v2.0.md | 36 --- 6 files changed, 584 deletions(-) delete mode 100644 src/strategies/ThroughSerial/README.md delete mode 100644 src/strategies/ThroughSerial/ThroughSerial.h delete mode 100644 src/strategies/ThroughSerial/Timing.h delete mode 100644 src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md delete mode 100644 src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v1.0.md delete mode 100644 src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v2.0.md diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md deleted file mode 100644 index 0ba20eb4bd..0000000000 --- a/src/strategies/ThroughSerial/README.md +++ /dev/null @@ -1,67 +0,0 @@ -## ThroughSerial - -**Medium:** Hardware or software serial port - -**Pins used:** 1 or 2 - -**Inclusion constant:** `PJON_INCLUDE_TS` - -With `ThroughSerial` strategy, PJON can run through a software or hardware Serial port working out-of-the-box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). Take a look at the [video introduction](https://www.youtube.com/watch?v=H4jUsgvM-lw) for a brief showcase of its features. It complies with [TSDL v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md). - -### Why PJON over Serial? -Serial communication is fast and reliable but it is often useless without all the features PJON contains. `ThroughSerial` has been developed to enable PJON communication through a serial data link. Adding PJON on top of Serial it is possible to leverage of the PJON protocol layer features like acknowledge, addressing, multiplexing, packet handling, 8 or 32-bit CRC and traffic control. - -Being impossible to detect or avoid collisions over a serial port, `ThroughSerial` has been developed primarily to be used in master-slave mode. `ThroughSerial` in multi-master mode, being unable to detect or avoid collisions, operates using the slotted ALOHA medium access method. Of all contention based random multiple access methods, slotted ALOHA, which maximum data throughput is only 36.8% of the available bandwidth, is one of the least efficient and should not be applied in networks where many devices often need to arbitrarily transmit data. - -### Configuration -Before including `PJON.h` it is possible to configure `ThroughSerial` using predefined constants: - -| Constant | Purpose | Supported value | -| ----------------------- |------------------------------------ | ------------------------------------------ | -| `TS_BYTE_TIME_OUT` | Maximum byte response time-out | Duration in microseconds (50000 by default) | -| `TS_RESPONSE_TIME_OUT` | Maximum response time-out | Duration in microseconds (10000 by default) | -| `TS_BACK_OFF_DEGREE` | Maximum back-off exponential degree | Numeric value (4 by default) | -| `TS_MAX_ATTEMPTS` | Maximum transmission attempts | Numeric value (20 by default) | - - -Pass the `ThroughSerial` type as PJON template parameter to instantiate a PJON object ready to communicate through this Strategy. -```cpp -PJON bus; -``` -Call the `begin` method on the `Serial` or `SoftwareSerial` object you want to use for PJON communication and pass it to the `set_serial` method: -```cpp -#include - -PJON bus; - -void setup() { - Serial.begin(9600); - bus.strategy.set_serial(&Serial); -} -``` -For a simple use with RS485 serial modules a transmission enable pin setter has been added: -```cpp -bus.strategy.set_enable_RS485_pin(11); -``` -If separate enable setters are needed use: -```cpp -// Set RS485 reception enable pin -bus.strategy.set_RS485_rxe_pin(11); -// Set RS485 transmission enable pin -bus.strategy.set_RS485_txe_pin(12); -``` -In some cases it may be required to add a delay before disabling the RS485 pins txe and or rxe: -```cpp -// Set RS485 txe/rxe pins disable delay in milliseconds -bus.strategy.set_RS485_delay(1); -``` - -If you need to interface devices using RS485 see the [RS485-Blink](../../../examples/ARDUINO/Local/ThroughSerial/RS485-Blink) example. - -HC-12 wireless module supports the synchronous acknowledgement, see [HC-12-Blink](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-Blink), [HC-12-SendAndReceive](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive) and [HC-12-LocalChat](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat) examples. - -All the other necessary information is present in the general [Documentation](/documentation). - -### Known issues -- Being PJON not an interrupt driven, its communication can be affected and potentially disrupted by long delays added in the user's sketch. Try to reduce as possible the interval between every `receive` call. - -### Safety warning -In all cases, when installing or maintaining a PJON network, extreme care must be taken to avoid any danger. Before any practical test or hardware purchase for a wireless [ThroughSerial](/src/strategies/ThroughSerial) radio setup, compliance with government requirements and regulations must be ensured. diff --git a/src/strategies/ThroughSerial/ThroughSerial.h b/src/strategies/ThroughSerial/ThroughSerial.h deleted file mode 100644 index 0f23990df8..0000000000 --- a/src/strategies/ThroughSerial/ThroughSerial.h +++ /dev/null @@ -1,293 +0,0 @@ - -/* ThroughSerial digital communication data link layer - used as a Strategy by the PJON framework (included in version v4.1) - Compliant with TSDL (Tardy Serial Data Link) specification v2.0 - - Contributors: - - Fred Larsen, Development, testing and debugging - - Zbigniew Zasieczny, collision avoidance multi-drop RS485 (latency) - and SoftwareSerial compatibility - - Franketto (Arduino forum user) RS485 TX enable pin compatibility - - Endre Karlson separate RS485 enable pins handling, flush timing hack - - hyndruide github user added set_RS485_delay - - fabpolli github user RS485 missing ack delay report and testing - ___________________________________________________________________________ - - ThroughSerial, - copyright 2016-2018 by Giovanni Blu Mitolo All rights reserved - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. */ - -#pragma once - -// START frame symbol 10010101 - 0x95 - • -#define TS_START 149 -// END frame symbol 11101010 - 0xea - ê -#define TS_END 234 -// ESCAPE symbol 10111011 - 0xBB - » -#define TS_ESC 187 - -// Used to signal communication failure -#define TS_FAIL 65535 - -// Used for pin handling -#define TS_NOT_ASSIGNED 255 - -#include "Timing.h" - -class ThroughSerial { - public: - PJON_SERIAL_TYPE serial; - - /* Returns suggested delay related to the attempts passed as parameter: */ - - uint32_t back_off(uint8_t attempts) { - uint32_t result = attempts; - for(uint8_t d = 0; d < TS_BACK_OFF_DEGREE; d++) - result *= (uint32_t)(attempts); - return result; - }; - - /* Begin method, to be called on initialization: - (returns always true) */ - - bool begin(uint8_t did = 0) { - PJON_DELAY(PJON_RANDOM(TS_INITIAL_DELAY) + did); - _last_reception_time = 0; - _last_byte = receive_byte(); - return true; - }; - - - /* Check if the channel is free for transmission: */ - - bool can_start() { - PJON_DELAY_MICROSECONDS(PJON_RANDOM(TS_COLLISION_DELAY)); - if(PJON_SERIAL_AVAILABLE(serial)) return false; - if((uint32_t)(PJON_MICROS() - _last_reception_time) < TS_TIME_IN) - return false; - return true; - }; - - - /* Returns the maximum number of attempts for each transmission: */ - - static uint8_t get_max_attempts() { - return TS_MAX_ATTEMPTS; - }; - - - /* Handle a collision: */ - - void handle_collision() { - PJON_DELAY_MICROSECONDS(PJON_RANDOM(TS_COLLISION_DELAY)); - }; - - - /* Try to receive a byte with a maximum waiting time */ - - uint16_t receive_byte(uint32_t time_out = TS_BYTE_TIME_OUT) { - uint32_t time = PJON_MICROS(); - while((uint32_t)(PJON_MICROS() - time) < time_out) { - if(PJON_SERIAL_AVAILABLE(serial)) { - _last_reception_time = PJON_MICROS(); - int16_t read = PJON_SERIAL_READ(serial); - #if defined(_WIN32) - read = (uint8_t)read; - #endif - if(read >= 0) { - _last_byte = (uint8_t)read; - return _last_byte; - } - } - #if defined(_WIN32) - PJON_DELAY_MICROSECONDS(time_out / 10); - #endif - } - return TS_FAIL; - }; - - - /* Receive byte response */ - - uint16_t receive_response() { - return receive_byte(TS_RESPONSE_TIME_OUT); - }; - - - /* Receive a frame: */ - - uint16_t receive_frame(uint8_t *data, uint16_t max_length) { - uint16_t result; - // No initial flag, byte-stuffing violation - if(max_length == PJON_PACKET_MAX_LENGTH) - if( - (receive_byte() != TS_START) || - (_last_byte == TS_ESC) - ) return TS_FAIL; - - result = receive_byte(); - if(result == TS_FAIL) return TS_FAIL; - - // Unescaped START byte stuffing violation - if(result == TS_START) return TS_FAIL; - - if(result == TS_ESC) { - result = receive_byte(); - result ^= TS_ESC; - // Avoid byte-stuffing violation - if((result != TS_START) && (result != TS_ESC) && (result != TS_END)) - return TS_FAIL; - } - - // No end flag, byte-stuffing violation - if((max_length == 1) && (receive_byte() != TS_END)) - return TS_FAIL; - *data = (uint8_t)result; - return 1; - }; - - - /* Send a byte and wait for its transmission end */ - - void send_byte(uint8_t b) { - uint32_t time = PJON_MICROS(); - while( - (PJON_SERIAL_WRITE(serial, b) != 1) && - ((uint32_t)(PJON_MICROS() - time) < TS_BYTE_TIME_OUT) - ); - }; - - /* Send byte response to the packet's transmitter */ - - void send_response(uint8_t response) { - start_tx(); - wait_RS485_pin_change(); - send_byte(response); - PJON_SERIAL_FLUSH(serial); - wait_RS485_pin_change(); - end_tx(); - }; - - - /* Send a frame: */ - - void send_frame(uint8_t *data, uint16_t length) { - start_tx(); - uint16_t overhead = 2; - // Add frame flag - send_byte(TS_START); - for(uint16_t b = 0; b < length; b++) { - // Byte-stuffing - if( - (data[b] == TS_START) || - (data[b] == TS_ESC) || - (data[b] == TS_END) - ) { - send_byte(TS_ESC); - send_byte(data[b] ^ TS_ESC); - overhead++; - } else send_byte(data[b]); - } - send_byte(TS_END); - /* On RPI flush fails to wait until all bytes are transmitted - here RPI forced to wait blocking using delayMicroseconds */ - #if defined(RPI) || defined(LINUX) - if(_bd) - PJON_DELAY_MICROSECONDS( - ((1000000 / (_bd / 8)) + _flush_offset) * (overhead + length) - ); - #endif - PJON_SERIAL_FLUSH(serial); - end_tx(); - }; - - - /* Pass the Serial port where you want to operate with */ - - void set_serial(PJON_SERIAL_TYPE serial_port) { - serial = serial_port; - }; - - void wait_RS485_pin_change() { - if(_enable_RS485_txe_pin != TS_NOT_ASSIGNED) - PJON_DELAY(_RS485_delay); - }; - - /* RS485 enable pins handling: */ - - void start_tx() { - if(_enable_RS485_txe_pin != TS_NOT_ASSIGNED) { - PJON_IO_WRITE(_enable_RS485_txe_pin, HIGH); - if(_enable_RS485_rxe_pin != TS_NOT_ASSIGNED) - PJON_IO_WRITE(_enable_RS485_rxe_pin, HIGH); - wait_RS485_pin_change(); - } - }; - - void end_tx() { - if(_enable_RS485_txe_pin != TS_NOT_ASSIGNED) { - wait_RS485_pin_change(); - PJON_IO_WRITE(_enable_RS485_txe_pin, LOW); - if(_enable_RS485_rxe_pin != TS_NOT_ASSIGNED) - PJON_IO_WRITE(_enable_RS485_rxe_pin, LOW); - } - }; - - #if defined(RPI) || defined(LINUX) - /* Pass baudrate to ThroughSerial - (needed only for RPI flush hack): */ - - void set_baud_rate(uint32_t baud) { - _bd = baud; - }; - - /* Set flush timing offset in microseconds between expected and real - serial byte transmission: */ - - void set_flush_offset(uint16_t offset) { - _flush_offset = offset; - }; - #endif - - /* RS485 enable pins setters: */ - - void set_enable_RS485_pin(uint8_t pin) { - set_RS485_txe_pin(pin); - }; - - void set_RS485_rxe_pin(uint8_t pin) { - _enable_RS485_rxe_pin = pin; - PJON_IO_MODE(_enable_RS485_rxe_pin, OUTPUT); - } - - void set_RS485_txe_pin(uint8_t pin) { - _enable_RS485_txe_pin = pin; - PJON_IO_MODE(_enable_RS485_txe_pin, OUTPUT); - } - - void set_RS485_delay(uint32_t d) { - _RS485_delay = d; - }; - - private: - #if defined(RPI) || defined(LINUX) - uint16_t _flush_offset = TS_FLUSH_OFFSET; - uint32_t _bd; - #endif - uint8_t _last_byte; - uint32_t _last_reception_time; - uint8_t _enable_RS485_rxe_pin = TS_NOT_ASSIGNED; - uint8_t _enable_RS485_txe_pin = TS_NOT_ASSIGNED; - uint32_t _RS485_delay = TS_RS485_DELAY; -}; diff --git a/src/strategies/ThroughSerial/Timing.h b/src/strategies/ThroughSerial/Timing.h deleted file mode 100644 index d0d58984fd..0000000000 --- a/src/strategies/ThroughSerial/Timing.h +++ /dev/null @@ -1,77 +0,0 @@ -/* ThroughSerial digital communication data link layer - used as a Strategy by the PJON framework (included in version v4.1) - - Contributors: - - Fred Larsen, Development, testing and debugging - - Zbigniew Zasieczny, collision avoidance multi-drop RS485 (latency) - and SoftwareSerial compatibility - - Franketto (Arduino forum user) RS485 TX enable pin compatibility - ____________________________________________________________________________ - - ThroughSerial, Copyright (c) 2016 by Giovanni Blu Mitolo All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. */ - -#pragma once - -/* Maximum 1 second random initial delay */ -#ifndef TS_INITIAL_DELAY - #define TS_INITIAL_DELAY 1000 -#endif - -/* Maximum 32 microseconds random delay in case of collision */ -#ifndef TS_COLLISION_DELAY - #define TS_COLLISION_DELAY 32 -#endif - -/* Set 10 milliseconds as the maximum timeframe between transmission and - synchronous acknowledgement response. This value is strictly related to the - maximum time needed by receiver to receive, compute and transmit a response. - Higher if necessary. */ -#ifndef TS_RESPONSE_TIME_OUT - #define TS_RESPONSE_TIME_OUT 10000 -#endif - -/* Minum timeframe with channel free for use before transmission. - (Avoid disrupting synchronous acknowledgement exchange) */ -#ifndef TS_TIME_IN - #define TS_TIME_IN TS_RESPONSE_TIME_OUT + TS_COLLISION_DELAY -#endif - -/* Set 50 milliseconds as the maximum timeframe for byte reception. - This value depends on the latency, baud rate and computation time. - Always set TS_BYTE_TIME_OUT > (byte transmission time + latency) */ -#ifndef TS_BYTE_TIME_OUT - #define TS_BYTE_TIME_OUT 50000 -#endif - -/* Maximum transmission attempts */ -#ifndef TS_MAX_ATTEMPTS - #define TS_MAX_ATTEMPTS 20 -#endif - -/* Back-off exponential degree */ -#ifndef TS_BACK_OFF_DEGREE - #define TS_BACK_OFF_DEGREE 4 -#endif - -/* Delay before enabling and disabling RS485 DE and or RE pin */ -#ifndef TS_RS485_DELAY - #define TS_RS485_DELAY 1 -#endif - -/* Force blocking sending hack (adds a delay for each character sent). */ - -#ifndef TS_FLUSH_OFFSET - #define TS_FLUSH_OFFSET 152 -#endif diff --git a/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md b/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md deleted file mode 100644 index 0dd6783371..0000000000 --- a/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md +++ /dev/null @@ -1,49 +0,0 @@ -### Specifications index - -#### Network layer -- [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) -- [Network services list](/specification/PJON-network-services-list.md) -#### Data link layer -- [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) -- [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) -- [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) -- **[TSDL (Tardy Serial Data Link) v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md)** -- [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) - ---- - -## TSDL v2.1 -``` -Invented by Giovanni Blu Mitolo -Originally published: 20/11/2017, latest revision: 9/11/2018 -Related implementation: /src/strategies/ThroughSerial/ -Compliant versions: PJON v10.0 and following -Released into the public domain -``` -TSDL (Tardy Serial Data Link) is a simplex or half-duplex serial data link that supports both master-slave and multi-master modes. It supports collision avoidance, reliable frame separation and optional synchronous response to frame transmissions. -```cpp - ______ TX RX ______ -| |-------| | -|DEVICE| |DEVICE| -|______|-------|______| - RX TX -``` -TSDL can be used to establish a point-to-point link between two devices if used with a bare serial link, or to support one or many to many communication using radio or RS485 transceivers. - -### Medium access control -TSDL operates in master-slave mode applying the request-response procedure. Being impossible to implement a carrier-sense procedure over a serial port TSDL uses variation of slotted ALOHA medium access method for multi-master mode. Before a frame transmission the serial buffer is read, if not empty ongoing communication is detected and collision avoided, if empty for a duration longer than the response time-out plus a short random time, frame transmission starts in which the packet is entirely transmitted. Of all contention based random multiple access methods, slotted ALOHA, which maximum data throughput is only 36.8% of the available bandwidth, is one of the least efficient, therefore TSDL in multi-master mode should not be used in networks where many devices often need to arbitrarily transmit data. - -### Frame transmission -Before a frame transmission the communication medium is analysed, if any data is received communication is detected and collision is avoided, if logic 0 is detected for a duration longer than the response time-out plus a small random time, data is transmitted encapsulated in a [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) frame. - -### Synchronous response -A frame transmission in both master-slave and multi-master modes can be optionally followed by a synchronous response of its recipient, all devices must use the same response time-out to avoid collisions. The acknowledgment reception phase must be shorter than the response time-out to be successful. -```cpp -Transmission Response - _______ ______ ______ _____ _____ -| START || BYTE || BYTE || END | CRC COMPUTATION | ACK | -|-------||------||------||-----|-----------------|-----| -| 149 || H || I || 234 | LATENCY | 6 | -|_______||______||______||_____| |_____| -``` -The required response time-out for a given application can be determined practically transmitting the longest supported frame with the farthest physical distance between the two devices. The highest interval between packet transmission and acknowledgement measured plus a small margin is the correct time-out that should exclude acknowledgement losses. diff --git a/src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v1.0.md b/src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v1.0.md deleted file mode 100644 index 0dc73942b8..0000000000 --- a/src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v1.0.md +++ /dev/null @@ -1,62 +0,0 @@ - -```cpp -/* -Milan, Italy -Originally published: 27/09/2017 -TSDL (Tardy Serial Data Link) v1.0 specification -Invented by Giovanni Blu Mitolo, -released into the public domain - -Related implementation: /src/strategies/ThroughSerial/ -Compliant versions: PJON v9.0 and following -*/ -``` -### TSDL v1.0 - -TSDL (Tardy Serial Data Link) is a simplex or half-duplex serial data link that supports both master-slave and multi-master configuration. It supports collision avoidance, reliable frame separation through byte stuffing and optional synchronous response to frame transmissions. - -### Basic concepts -* Use start, end and escape flags to support frame separation -* Support collision avoidance -* Support optional 1 byte synchronous response to frame transmissions - -```cpp - ______ TX RX ______ -| |-------| | -|DEVICE| |DEVICE| -|______|-------|______| - RX TX -``` -TSDL can be used to establish a point-to-point link between two devices if used with a bare serial link, or supporting one or many to many communication with physical layers that are supporting this feature, like serial radio or RS485 transceivers. - -#### Frame transmission -Before a frame transmission, the serial buffer is read, if not empty ongoing communication is detected and collision avoided, if empty for a duration longer than the time-in before transmission, frame transmission starts with `START` flag, followed by data bytes, if necessary escaped with `ESC` flag and terminates the frame with an `END` flag. -```cpp - ______________________________ - | DATA 1-65535 bytes | - _______ |______ _____ _______ ______| _____ -| START | | BYTE || ESC || START || BYTE | | END | -|-------| |------||-----||-------||------| |-----| -| 149 | | 23 || 76 || 149 || 52 | | 234 | -|_______| |______||_____||_______||______| |_____| - | - Flags inside data are escaped - -START: 149 - 10010101 - 0x95 - • -END: 234 - 11101010 - 0xea - ê -ESC: 187 - 10111011 - 0xBB - » -``` -`START` and `END` flag bytes are special characters that signal when a frame begins and ends. -Whenever any of the special character appears in the data, transmitter inserts a special `ESC` character before it, that will be ignored and excluded from data during the reception process. Any corrupted special character or data byte causes the receiver to discard the frame and be ready to receive the next one nominally. - -#### Synchronous response -A frame transmission can be optionally followed by a synchronous response by its recipient. -```cpp -Transmission Response - _______ ______ ______ _____ _____ -| START || BYTE || BYTE || END | CRC COMPUTATION | ACK | -|-------||------||------||-----|-----------------|-----| -| 149 || H || I || 234 | LATENCY | 6 | -|_______||______||______||_____| |_____| -``` -Between frame transmission and a synchronous response there is a variable timeframe influenced by latency and CRC computation time. The maximum time dedicated to potential acknowledgement reception must be shorter than the transmission time-in, to avoid other devices to disrupt a response exchange, and it is estimated adding the maximum frame length CRC computation time to the expected latency. diff --git a/src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v2.0.md b/src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v2.0.md deleted file mode 100644 index 5c7f979d78..0000000000 --- a/src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v2.0.md +++ /dev/null @@ -1,36 +0,0 @@ - -## TSDL v2.0 -``` -Invented by Giovanni Blu Mitolo -Originally published: 20/11/2017, latest revision: 9/11/2018 -Related implementation: /src/strategies/ThroughSerial/ -Compliant versions: PJON v10.0 and following -Released into the public domain -``` -TSDL (Tardy Serial Data Link) is a simplex or half-duplex serial data link that supports both master-slave and multi-master modes. It supports collision avoidance, reliable frame separation and optional synchronous response to frame transmissions. -```cpp - ______ TX RX ______ -| |-------| | -|DEVICE| |DEVICE| -|______|-------|______| - RX TX -``` -TSDL can be used to establish a point-to-point link between two devices if used with a bare serial link, or to support one or many to many communication using radio or RS485 transceivers. - -### Medium access control -TSDL operates in master-slave mode applying the request-response procedure. Being impossible to implement a carrier-sense procedure over a serial port TSDL uses variation of slotted ALOHA medium access method for multi-master mode. Before a frame transmission the serial buffer is read, if not empty ongoing communication is detected and collision avoided, if empty for a duration longer than the response time-out plus a short random time, frame transmission starts in which the packet is entirely transmitted. Of all contention based random multiple access methods, slotted ALOHA, which maximum data throughput is only 36.8% of the available bandwidth, is one of the least efficient, therefore TSDL in multi-master mode should not be used in networks where many devices often need to arbitrarily transmit data. - -### Frame transmission -Before a frame transmission the communication medium is analysed, if any data is received communication is detected and collision is avoided, if logic 0 is detected for a duration longer than the response time-out plus a small random time, data is transmitted encapsulated in a [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) frame. - -### Synchronous response -A frame transmission in both master-slave and multi-master modes can be optionally followed by a synchronous response of its recipient, all devices must use the same response time-out to avoid collisions. The acknowledgment reception phase must be shorter than the response time-out to be successful. -```cpp -Transmission Response - _______ ______ ______ _____ _____ -| START || BYTE || BYTE || END | CRC COMPUTATION | ACK | -|-------||------||------||-----|-----------------|-----| -| 149 || H || I || 234 | LATENCY | 6 | -|_______||______||______||_____| |_____| -``` -The required response time-out for a given application can be determined practically transmitting the longest supported frame with the farthest physical distance between the two devices. The highest interval between packet transmission and acknowledgement measured plus a small margin is the correct time-out that should exclude acknowledgement losses. From a1d716aff10826a9a55bc5f10df0c4b257c1f4b1 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 May 2020 00:28:02 +0200 Subject: [PATCH 046/323] ThroughSerialAsync -> ThroughSerial --- src/strategies/PJON_Strategies.h | 7 +- src/strategies/ThroughSerialAsync/README.md | 26 +-- .../ThroughSerialAsync/ThroughSerialAsync.h | 202 +++++++++--------- src/strategies/ThroughSerialAsync/Timing.h | 52 ++--- 4 files changed, 141 insertions(+), 146 deletions(-) diff --git a/src/strategies/PJON_Strategies.h b/src/strategies/PJON_Strategies.h index 39d3941c1d..f18a625d2f 100644 --- a/src/strategies/PJON_Strategies.h +++ b/src/strategies/PJON_Strategies.h @@ -51,9 +51,6 @@ #if defined(PJON_INCLUDE_TS) #include "ThroughSerial/ThroughSerial.h" #endif -#if defined(PJON_INCLUDE_TSA) - #include "ThroughSerialAsync/ThroughSerialAsync.h" -#endif #if defined(PJON_INCLUDE_TL) #include "ThroughLoRa/ThroughLora.h" #endif @@ -71,15 +68,13 @@ !defined(PJON_INCLUDE_GUDP) && !defined(PJON_INCLUDE_LUDP) && \ !defined(PJON_INCLUDE_OS) && !defined(PJON_INCLUDE_SWBB) && \ !defined(PJON_INCLUDE_TS) && !defined(PJON_INCLUDE_NONE) && \ - !defined(PJON_INCLUDE_TSA) && !defined(PJON_INCLUDE_DUDP) && \ - !defined(PJON_INCLUDE_LF) && !defined(PJON_INCLUDE_SM) && \ + !defined(PJON_INCLUDE_DUDP) && !defined(PJON_INCLUDE_LF) && \ !defined(PJON_INCLUDE_MQTT) && !defined(PJON_INCLUDE_TL) #include "Any/Any.h" #include "AnalogSampling/AnalogSampling.h" #include "OverSampling/OverSampling.h" #include "SoftwareBitBang/SoftwareBitBang.h" #include "ThroughSerial/ThroughSerial.h" - #include "ThroughSerialAsync/ThroughSerialAsync.h" /* Avoid ATtiny44/84/45/85 and STM32F1 missing inclusion error */ #if !defined(__AVR_ATtiny45__) && !defined(__AVR_ATtiny85__) && \ !defined(__AVR_ATtiny44__) && !defined(__AVR_ATtiny84__) && !defined(ARDUINO_ARCH_STM32) diff --git a/src/strategies/ThroughSerialAsync/README.md b/src/strategies/ThroughSerialAsync/README.md index 75e1d03b0b..5e1c5799c8 100644 --- a/src/strategies/ThroughSerialAsync/README.md +++ b/src/strategies/ThroughSerialAsync/README.md @@ -1,32 +1,32 @@ -## ThroughSerialAsync +## ThroughSerial **Medium:** Hardware or software serial port - **Pins used:** 1 or 2 - **Inclusion constant:** `PJON_INCLUDE_TSA` -With `ThroughSerialAsync` strategy, PJON can run through a software or hardware Serial port working out of the box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). It complies with [TSDL v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md). +With `ThroughSerial` strategy, PJON can run through a software or hardware Serial port working out of the box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). It complies with [TSDL v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md). -This strategy is based upon the `ThroughSerial` but reception is asynchronous and completely non-blocking, making good use of hardware buffers and sparing time that `ThroughSerial` looses polling. It is not required to call `bus.receive()` with any delay, just call it frequently to see if there are any packets that have been received. +This strategy is based upon the obsolete blocking implementation although reception is now asynchronous and completely non-blocking. It is not required to call `bus.receive()` with any delay, just call it frequently to see if there are any packets that have been received. ### Why PJON over Serial? Serial communication is fast and reliable but it is often useless without all the features PJON contains. `ThroughAsyncSerial` has been developed to enable PJON communication through a serial data link. Adding PJON on top of Serial it is possible to leverage of the PJON protocol layer features like acknowledge, addressing, multiplexing, packet handling, 8 or 32-bit CRC and traffic control. -Being impossible to detect or avoid collisions over a serial port, `ThroughSerial` has been developed primarily to be used in master-slave mode. `ThroughSerial` in multi-master mode, being unable to detect or avoid collisions, operates using the slotted ALOHA medium access method. Of all contention based random multiple access methods, slotted ALOHA, which maximum data throughput is only 36.8% of the available bandwidth, is one of the least efficient and should not be applied in networks where many devices often need to arbitrarily transmit data. +`ThroughSerial` has been developed primarily to be used in master-slave mode. `ThroughSerial` in multi-master mode, being unable to detect or avoid collisions, operates using the slotted ALOHA medium access method. Of all contention based random multiple access methods, slotted ALOHA, which maximum data throughput is only 36.8% of the available bandwidth, is one of the least efficient and should not be applied in networks where many devices often need to arbitrarily transmit data. -`ThroughSerialAsync` performs well if used with ESP8266 and ESP32 where blocking procedures can strongly degrade functionality. The reception phase is entirely non-blocking. Sending and acknowledgement however are still blocking. +`ThroughSerial` performs well if used with ESP8266 and ESP32 where blocking procedures can strongly degrade functionality. The reception phase is entirely non-blocking. Sending and acknowledgement however are still blocking. There is a default reception interval of 100 microseconds used to allow data to accumulate in the hardware UART buffer. This value is configurable using `bus.strategy.set_read_interval(100)` passing an arbitrary interval in microseconds. The read interval may require adjustment depending on UART RX buffer size and baud rate. ### Configuration -Before including `PJON.h` it is possible to configure `ThroughSerialAsync` using predefined constants: +Before including `PJON.h` it is possible to configure `ThroughSerial` using predefined constants: | Constant | Purpose | Supported value | | ----------------------- |------------------------------------ | ------------------------------------------ | -| `TSA_READ_INTERVAL` | minimum interval between receptions | Duration in microseconds (100 by default) | -| `TSA_BYTE_TIME_OUT` | Maximum byte reception time-out | Duration in microseconds (1000000 by default) | -| `TSA_RESPONSE_TIME_OUT` | Maximum response time-out | Duration in microseconds (10000 by default) | -| `TSA_BACK_OFF_DEGREE` | Maximum back-off exponential degree | Numeric value (4 by default) | -| `TSA_MAX_ATTEMPTS` | Maximum transmission attempts | Numeric value (20 by default) | +| `TS_READ_INTERVAL` | minimum interval between receptions | Duration in microseconds (100 by default) | +| `TS_BYTE_TIME_OUT` | Maximum byte reception time-out | Duration in microseconds (1000000 by default) | +| `TS_RESPONSE_TIME_OUT` | Maximum response time-out | Duration in microseconds (10000 by default) | +| `TS_BACK_OFF_DEGREE` | Maximum back-off exponential degree | Numeric value (4 by default) | +| `TS_MAX_ATTEMPTS` | Maximum transmission attempts | Numeric value (20 by default) | Pass the `ThroughSerial` type as PJON template parameter to instantiate a PJON object ready to communicate through this Strategy. ```cpp @@ -56,9 +56,9 @@ bus.strategy.set_RS485_rxe_pin(11); // Set RS485 transmission enable pin bus.strategy.set_RS485_txe_pin(12); ``` -See the [Blink](../../../examples/ARDUINO/Local/ThroughSerialAsync/Blink) and [BlinkWithResponse](https://github.com/gioblu/PJON/tree/master/examples/ARDUINO/Local/ThroughSerialAsync/BlinkWithResponse) examples. +See the [Blink](../../../examples/ARDUINO/Local/ThroughSerial/Blink) and [BlinkWithResponse](https://github.com/gioblu/PJON/tree/master/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse) examples. -Examples for `ThroughSerial` can be easily modifed to work with `ThroughSerialAsync`, if you need to interface devices using RS485 see the [RS485-Blink](../../../examples/ARDUINO/Local/ThroughSerial/RS485-Blink) example. +Examples for `ThroughSerial` can be easily modifed to work with `ThroughSerial`, if you need to interface devices using RS485 see the [RS485-Blink](../../../examples/ARDUINO/Local/ThroughSerial/RS485-Blink) example. HC-12 wireless module supports the synchronous acknowledgement, see [HC-12-Blink](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-Blink), [HC-12-SendAndReceive](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive) and [HC-12-LocalChat](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat) examples. diff --git a/src/strategies/ThroughSerialAsync/ThroughSerialAsync.h b/src/strategies/ThroughSerialAsync/ThroughSerialAsync.h index 4afd35dca2..b9e480fc6d 100644 --- a/src/strategies/ThroughSerialAsync/ThroughSerialAsync.h +++ b/src/strategies/ThroughSerialAsync/ThroughSerialAsync.h @@ -1,5 +1,5 @@ -/* ThroughSerialAsync data link layer +/* ThroughSerial data link layer used as a Strategy by the PJON framework (included in version v11.2) Compliant with TSDL (Tardy Serial Data Link) specification v2.0 @@ -12,7 +12,7 @@ - Endre Karlson separate RS485 enable pins handling, flush timing hack ___________________________________________________________________________ - ThroughSerialAsync, based on ThroughSerial, developed by sticilface + ThroughSerial, based on ThroughSerial, developed by sticilface copyright 2018 by Giovanni Blu Mitolo All rights reserved Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,39 +30,39 @@ #pragma once // START symbol 10010101 - 0x95 - • -#define TSA_START 149 +#define TS_START 149 // END symbol 11101010 - 0xea - ê -#define TSA_END 234 +#define TS_END 234 // ESCAPE symbol 10111011 - 0xBB - » -#define TSA_ESC 187 +#define TS_ESC 187 // Used to signal communication failure -#define TSA_FAIL 65535 +#define TS_FAIL 65535 // Used for unused pin handling -#define TSA_NOT_ASSIGNED 255 +#define TS_NOT_ASSIGNED 255 #include "Timing.h" -enum TSA_state_t : uint8_t { - TSA_WAITING, - TSA_RECEIVING, - TSA_WAITING_ESCAPE, - TSA_WAITING_END, - TSA_DONE +enum TS_state_t : uint8_t { + TS_WAITING, + TS_RECEIVING, + TS_WAITING_ESCAPE, + TS_WAITING_END, + TS_DONE }; -class ThroughSerialAsync { +class ThroughSerial { public: uint8_t buffer[PJON_PACKET_MAX_LENGTH] = {0}; uint16_t position = 0; - TSA_state_t state = TSA_WAITING; + TS_state_t state = TS_WAITING; PJON_SERIAL_TYPE serial; /* Returns suggested delay related to the attempts passed as parameter: */ uint32_t back_off(uint8_t attempts) { uint32_t result = attempts; - for (uint8_t d = 0; d < TSA_BACK_OFF_DEGREE; d++) + for (uint8_t d = 0; d < TS_BACK_OFF_DEGREE; d++) result *= (uint32_t)(attempts); return result; }; @@ -72,7 +72,7 @@ class ThroughSerialAsync { (returns always true) */ bool begin(uint8_t did = 0) { - PJON_DELAY(PJON_RANDOM(TSA_INITIAL_DELAY) + did); + PJON_DELAY(PJON_RANDOM(TS_INITIAL_DELAY) + did); _last_reception_time = PJON_MICROS(); return true; }; @@ -82,11 +82,11 @@ class ThroughSerialAsync { bool can_start() { if( - (state != TSA_WAITING) || + (state != TS_WAITING) || PJON_SERIAL_AVAILABLE(serial) || - ((uint32_t)(PJON_MICROS() - _last_reception_time) < TSA_TIME_IN) + ((uint32_t)(PJON_MICROS() - _last_reception_time) < TS_TIME_IN) ) return false; - PJON_DELAY_MICROSECONDS(PJON_RANDOM(TSA_COLLISION_DELAY)); + PJON_DELAY_MICROSECONDS(PJON_RANDOM(TS_COLLISION_DELAY)); return true; }; @@ -94,14 +94,14 @@ class ThroughSerialAsync { /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { - return TSA_MAX_ATTEMPTS; + return TS_MAX_ATTEMPTS; }; /* Handle a collision: */ void handle_collision() { - PJON_DELAY_MICROSECONDS(PJON_RANDOM(TSA_COLLISION_DELAY)); + PJON_DELAY_MICROSECONDS(PJON_RANDOM(TS_COLLISION_DELAY)); }; @@ -110,20 +110,20 @@ class ThroughSerialAsync { uint16_t receive_response() { uint32_t time = PJON_MICROS(); uint8_t i = 0; - while((uint32_t)(PJON_MICROS() - time) < TSA_RESPONSE_TIME_OUT) { + while((uint32_t)(PJON_MICROS() - time) < TS_RESPONSE_TIME_OUT) { if(PJON_SERIAL_AVAILABLE(serial)) { int16_t read = PJON_SERIAL_READ(serial); _last_reception_time = PJON_MICROS(); if(read >= 0) { - if(_response[i++] != read) return TSA_FAIL; - if(i == TSA_RESPONSE_LENGTH) return PJON_ACK; + if(_response[i++] != read) return TS_FAIL; + if(i == TS_RESPONSE_LENGTH) return PJON_ACK; } } #if defined(_WIN32) - PJON_DELAY_MICROSECONDS(TSA_RESPONSE_TIME_OUT / 10); + PJON_DELAY_MICROSECONDS(TS_RESPONSE_TIME_OUT / 10); #endif } - return TSA_FAIL; + return TS_FAIL; }; @@ -133,57 +133,57 @@ class ThroughSerialAsync { if( // Reception attempts are spaced by an interval _last_call_time && (uint32_t)(PJON_MICROS() - _last_call_time) < _read_interval - ) return TSA_FAIL; + ) return TS_FAIL; _last_call_time = PJON_MICROS(); if( // If reception timeout is reached discard data ( - (state == TSA_RECEIVING) || - (state == TSA_WAITING_END) || - (state == TSA_WAITING_ESCAPE) + (state == TS_RECEIVING) || + (state == TS_WAITING_END) || + (state == TS_WAITING_ESCAPE) ) && - ((uint32_t)(PJON_MICROS() - _last_reception_time) > TSA_BYTE_TIME_OUT) + ((uint32_t)(PJON_MICROS() - _last_reception_time) > TS_BYTE_TIME_OUT) ) { - state = TSA_WAITING; - return TSA_FAIL; + state = TS_WAITING; + return TS_FAIL; } switch(state) { - case TSA_WAITING: { + case TS_WAITING: { while(PJON_SERIAL_AVAILABLE(serial)) { uint8_t value = PJON_SERIAL_READ(serial); _last_reception_time = PJON_MICROS(); - if(value == TSA_START) { - state = TSA_RECEIVING; + if(value == TS_START) { + state = TS_RECEIVING; position = 0; - return TSA_FAIL; + return TS_FAIL; } }; break; } - case TSA_RECEIVING: { + case TS_RECEIVING: { while(PJON_SERIAL_AVAILABLE(serial)) { uint8_t value = PJON_SERIAL_READ(serial); _last_reception_time = PJON_MICROS(); - if(value == TSA_START) { - state = TSA_WAITING; - return TSA_FAIL; + if(value == TS_START) { + state = TS_WAITING; + return TS_FAIL; } - if(value == TSA_ESC) { + if(value == TS_ESC) { if(!PJON_SERIAL_AVAILABLE(serial)) { - state = TSA_WAITING_ESCAPE; - return TSA_FAIL; + state = TS_WAITING_ESCAPE; + return TS_FAIL; } else { - value = PJON_SERIAL_READ(serial) ^ TSA_ESC; + value = PJON_SERIAL_READ(serial) ^ TS_ESC; _last_reception_time = PJON_MICROS(); if( - (value != TSA_START) && - (value != TSA_ESC) && - (value != TSA_END) + (value != TS_START) && + (value != TS_ESC) && + (value != TS_END) ) { - state = TSA_WAITING; - return TSA_FAIL; + state = TS_WAITING; + return TS_FAIL; } buffer[position++] = value; continue; @@ -191,68 +191,68 @@ class ThroughSerialAsync { } if(max_length == 1) { - state = TSA_WAITING_END; - return TSA_FAIL; + state = TS_WAITING_END; + return TS_FAIL; } if(position + 1 >= PJON_PACKET_MAX_LENGTH) { - state = TSA_WAITING; - return TSA_FAIL; + state = TS_WAITING; + return TS_FAIL; } - if(value == TSA_END) { - state = TSA_DONE; - return TSA_FAIL; + if(value == TS_END) { + state = TS_DONE; + return TS_FAIL; } buffer[position++] = value; } - return TSA_FAIL; + return TS_FAIL; } - case TSA_WAITING_ESCAPE: { + case TS_WAITING_ESCAPE: { if(PJON_SERIAL_AVAILABLE(serial)) { - uint8_t value = PJON_SERIAL_READ(serial) ^ TSA_ESC; + uint8_t value = PJON_SERIAL_READ(serial) ^ TS_ESC; _last_reception_time = PJON_MICROS(); if( - (value != TSA_START) && - (value != TSA_ESC) && - (value != TSA_END) + (value != TS_START) && + (value != TS_ESC) && + (value != TS_END) ) { - state = TSA_WAITING; - return TSA_FAIL; + state = TS_WAITING; + return TS_FAIL; } buffer[position++] = value; - state = TSA_RECEIVING; - return TSA_FAIL; + state = TS_RECEIVING; + return TS_FAIL; } break; } - case TSA_WAITING_END: { + case TS_WAITING_END: { if(PJON_SERIAL_AVAILABLE(serial)) { uint8_t value = PJON_SERIAL_READ(serial); _last_reception_time = PJON_MICROS(); - if(value == TSA_END) { - state = TSA_DONE; - return TSA_FAIL; + if(value == TS_END) { + state = TS_DONE; + return TS_FAIL; } else { - state = TSA_WAITING; - return TSA_FAIL; + state = TS_WAITING; + return TS_FAIL; } } break; } - case TSA_DONE: { + case TS_DONE: { memcpy(&data[0], &buffer[0], position); prepare_response(buffer, position); - state = TSA_WAITING; + state = TS_WAITING; return position; } }; - return TSA_FAIL; + return TS_FAIL; }; @@ -262,7 +262,7 @@ class ThroughSerialAsync { uint32_t time = PJON_MICROS(); while( (PJON_SERIAL_WRITE(serial, b) != 1) && - ((uint32_t)(PJON_MICROS() - time) < TSA_BYTE_TIME_OUT) + ((uint32_t)(PJON_MICROS() - time) < TS_BYTE_TIME_OUT) ); }; @@ -275,10 +275,10 @@ class ThroughSerialAsync { void prepare_response(const uint8_t *buffer, uint16_t position) { uint8_t raw = 0; - for(int8_t i = 0; i < TSA_RESPONSE_LENGTH; i++) { - raw = buffer[(position - ((TSA_RESPONSE_LENGTH - 1) - i)) - 1]; + for(int8_t i = 0; i < TS_RESPONSE_LENGTH; i++) { + raw = buffer[(position - ((TS_RESPONSE_LENGTH - 1) - i)) - 1]; _response[i] = ( - (raw == TSA_START) || (raw == TSA_ESC) || (raw == TSA_END) + (raw == TS_START) || (raw == TS_ESC) || (raw == TS_END) ) ? (raw - 1) : raw; // Avoid encoding symbols } }; @@ -290,7 +290,7 @@ class ThroughSerialAsync { if(response == PJON_ACK) { start_tx(); wait_RS485_pin_change(); - for(uint8_t i = 0; i < TSA_RESPONSE_LENGTH; i++) + for(uint8_t i = 0; i < TS_RESPONSE_LENGTH; i++) send_byte(_response[i]); PJON_SERIAL_FLUSH(serial); wait_RS485_pin_change(); @@ -305,20 +305,20 @@ class ThroughSerialAsync { start_tx(); uint16_t overhead = 2; // Add frame flag - send_byte(TSA_START); + send_byte(TS_START); for(uint16_t b = 0; b < length; b++) { // Byte-stuffing if( - (data[b] == TSA_START) || - (data[b] == TSA_ESC) || - (data[b] == TSA_END) + (data[b] == TS_START) || + (data[b] == TS_ESC) || + (data[b] == TS_END) ) { - send_byte(TSA_ESC); - send_byte(data[b] ^ TSA_ESC); + send_byte(TS_ESC); + send_byte(data[b] ^ TS_ESC); overhead++; } else send_byte(data[b]); } - send_byte(TSA_END); + send_byte(TS_END); /* On RPI flush fails to wait until all bytes are transmitted here RPI forced to wait blocking using delayMicroseconds */ #if defined(RPI) || defined(LINUX) @@ -344,19 +344,19 @@ class ThroughSerialAsync { /* RS485 enable pins handling: */ void start_tx() { - if(_enable_RS485_txe_pin != TSA_NOT_ASSIGNED) { + if(_enable_RS485_txe_pin != TS_NOT_ASSIGNED) { PJON_IO_WRITE(_enable_RS485_txe_pin, HIGH); - if(_enable_RS485_rxe_pin != TSA_NOT_ASSIGNED) + if(_enable_RS485_rxe_pin != TS_NOT_ASSIGNED) PJON_IO_WRITE(_enable_RS485_rxe_pin, HIGH); wait_RS485_pin_change(); } }; void end_tx() { - if(_enable_RS485_txe_pin != TSA_NOT_ASSIGNED) { + if(_enable_RS485_txe_pin != TS_NOT_ASSIGNED) { wait_RS485_pin_change(); PJON_IO_WRITE(_enable_RS485_txe_pin, LOW); - if(_enable_RS485_rxe_pin != TSA_NOT_ASSIGNED) + if(_enable_RS485_rxe_pin != TS_NOT_ASSIGNED) PJON_IO_WRITE(_enable_RS485_rxe_pin, LOW); } }; @@ -379,7 +379,7 @@ class ThroughSerialAsync { #endif /* Sets the interval between each read attempt from serial - (TSA_READ_INTERVAL or 100 microseconds by default) to allow the buffer + (TS_READ_INTERVAL or 100 microseconds by default) to allow the buffer to fill and to reduce the computation time consumed while polling for incoming data. */ @@ -408,20 +408,20 @@ class ThroughSerialAsync { } void wait_RS485_pin_change() { - if(_enable_RS485_txe_pin != TSA_NOT_ASSIGNED) + if(_enable_RS485_txe_pin != TS_NOT_ASSIGNED) PJON_DELAY(_RS485_delay); }; private: #if defined(RPI) || defined(LINUX) - uint16_t _flush_offset = TSA_FLUSH_OFFSET; + uint16_t _flush_offset = TS_FLUSH_OFFSET; uint32_t _bd; #endif - uint8_t _response[TSA_RESPONSE_LENGTH]; + uint8_t _response[TS_RESPONSE_LENGTH]; uint32_t _last_reception_time = 0; uint32_t _last_call_time = 0; - uint8_t _enable_RS485_rxe_pin = TSA_NOT_ASSIGNED; - uint8_t _enable_RS485_txe_pin = TSA_NOT_ASSIGNED; - uint32_t _RS485_delay = TSA_RS485_DELAY; - uint32_t _read_interval = TSA_READ_INTERVAL; + uint8_t _enable_RS485_rxe_pin = TS_NOT_ASSIGNED; + uint8_t _enable_RS485_txe_pin = TS_NOT_ASSIGNED; + uint32_t _RS485_delay = TS_RS485_DELAY; + uint32_t _read_interval = TS_READ_INTERVAL; }; diff --git a/src/strategies/ThroughSerialAsync/Timing.h b/src/strategies/ThroughSerialAsync/Timing.h index d1df878a75..0af44232de 100644 --- a/src/strategies/ThroughSerialAsync/Timing.h +++ b/src/strategies/ThroughSerialAsync/Timing.h @@ -26,69 +26,69 @@ #pragma once /* Maximum 1 second random initial delay */ -#ifndef TSA_INITIAL_DELAY - #define TSA_INITIAL_DELAY 1000 +#ifndef TS_INITIAL_DELAY + #define TS_INITIAL_DELAY 1000 #endif /* Maximum 32 microseconds random delay in case of collision */ -#ifndef TSA_COLLISION_DELAY - #define TSA_COLLISION_DELAY 32 +#ifndef TS_COLLISION_DELAY + #define TS_COLLISION_DELAY 32 #endif /* Set 10 milliseconds as the maximum timeframe between transmission and synchronous acknowledgement response. Its optimal configuration is strictly related to the maximum time needed by receiver to receive, compute and transmit back a response. */ -#ifndef TSA_RESPONSE_TIME_OUT - #define TSA_RESPONSE_TIME_OUT 10000 +#ifndef TS_RESPONSE_TIME_OUT + #define TS_RESPONSE_TIME_OUT 10000 #endif /* Minum duration of channel free for use before transmission. (Avoid disrupting synchronous acknowledgement exchange) */ -#ifndef TSA_TIME_IN - #define TSA_TIME_IN TSA_RESPONSE_TIME_OUT + TSA_COLLISION_DELAY +#ifndef TS_TIME_IN + #define TS_TIME_IN TS_RESPONSE_TIME_OUT + TS_COLLISION_DELAY #endif /* Set 100 microseconds as the interval between each byte read. Depending on the latency, baud rate and computation time the - optimal TSA_READ_INTERVAL value may variate. - Always set: TSA_READ_INTERVAL > (byte transmission time + latency) */ -#ifndef TSA_READ_INTERVAL - #define TSA_READ_INTERVAL 100 + optimal TS_READ_INTERVAL value may variate. + Always set: TS_READ_INTERVAL > (byte transmission time + latency) */ +#ifndef TS_READ_INTERVAL + #define TS_READ_INTERVAL 100 #endif /* Byte reception timeout */ -#ifndef TSA_BYTE_TIME_OUT - #define TSA_BYTE_TIME_OUT 1000000 +#ifndef TS_BYTE_TIME_OUT + #define TS_BYTE_TIME_OUT 1000000 #endif -/* Response length (the response is composed by the last TSA_RESPONSE_LENGTH +/* Response length (the response is composed by the last TS_RESPONSE_LENGTH bytes of the packet received). By default should be relatively safe. (Few false positives per millennia) If you are ready to trade safety for bandwidth reduce it, consider that - setting TSA_RESPONSE_LENGTH < 4 reduces reliability and leads to higher + setting TS_RESPONSE_LENGTH < 4 reduces reliability and leads to higher chances of detecting a false positive. */ -#ifndef TSA_RESPONSE_LENGTH - #define TSA_RESPONSE_LENGTH 5 +#ifndef TS_RESPONSE_LENGTH + #define TS_RESPONSE_LENGTH 5 #endif /* Maximum transmission attempts */ -#ifndef TSA_MAX_ATTEMPTS - #define TSA_MAX_ATTEMPTS 20 +#ifndef TS_MAX_ATTEMPTS + #define TS_MAX_ATTEMPTS 20 #endif /* Back-off exponential degree */ -#ifndef TSA_BACK_OFF_DEGREE - #define TSA_BACK_OFF_DEGREE 4 +#ifndef TS_BACK_OFF_DEGREE + #define TS_BACK_OFF_DEGREE 4 #endif /* Delay before enabling and disabling RS485 DE and or RE pin */ -#ifndef TSA_RS485_DELAY - #define TSA_RS485_DELAY 1 +#ifndef TS_RS485_DELAY + #define TS_RS485_DELAY 1 #endif /* Force blocking sending hack (adds a delay for each character sent). */ -#ifndef TSA_FLUSH_OFFSET - #define TSA_FLUSH_OFFSET 152 +#ifndef TS_FLUSH_OFFSET + #define TS_FLUSH_OFFSET 152 #endif From a3b247daa7bbd03cb99ca88458deec2f617c854f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 May 2020 00:33:53 +0200 Subject: [PATCH 047/323] TSA implementation moved in ThroughSerial --- src/strategies/{ThroughSerialAsync => ThroughSerial}/README.md | 0 .../ThroughSerialAsync.h => ThroughSerial/ThroughSerial.h} | 0 src/strategies/{ThroughSerialAsync => ThroughSerial}/Timing.h | 0 .../specification/TSDL-specification-v3.0.md | 0 .../specification/obsolete/TSDL-specification-v1.0.md | 0 .../specification/obsolete/TSDL-specification-v2.0.md | 0 .../specification/obsolete/TSDL-specification-v2.1.md | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename src/strategies/{ThroughSerialAsync => ThroughSerial}/README.md (100%) rename src/strategies/{ThroughSerialAsync/ThroughSerialAsync.h => ThroughSerial/ThroughSerial.h} (100%) rename src/strategies/{ThroughSerialAsync => ThroughSerial}/Timing.h (100%) rename src/strategies/{ThroughSerialAsync => ThroughSerial}/specification/TSDL-specification-v3.0.md (100%) rename src/strategies/{ThroughSerialAsync => ThroughSerial}/specification/obsolete/TSDL-specification-v1.0.md (100%) rename src/strategies/{ThroughSerialAsync => ThroughSerial}/specification/obsolete/TSDL-specification-v2.0.md (100%) rename src/strategies/{ThroughSerialAsync => ThroughSerial}/specification/obsolete/TSDL-specification-v2.1.md (100%) diff --git a/src/strategies/ThroughSerialAsync/README.md b/src/strategies/ThroughSerial/README.md similarity index 100% rename from src/strategies/ThroughSerialAsync/README.md rename to src/strategies/ThroughSerial/README.md diff --git a/src/strategies/ThroughSerialAsync/ThroughSerialAsync.h b/src/strategies/ThroughSerial/ThroughSerial.h similarity index 100% rename from src/strategies/ThroughSerialAsync/ThroughSerialAsync.h rename to src/strategies/ThroughSerial/ThroughSerial.h diff --git a/src/strategies/ThroughSerialAsync/Timing.h b/src/strategies/ThroughSerial/Timing.h similarity index 100% rename from src/strategies/ThroughSerialAsync/Timing.h rename to src/strategies/ThroughSerial/Timing.h diff --git a/src/strategies/ThroughSerialAsync/specification/TSDL-specification-v3.0.md b/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md similarity index 100% rename from src/strategies/ThroughSerialAsync/specification/TSDL-specification-v3.0.md rename to src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md diff --git a/src/strategies/ThroughSerialAsync/specification/obsolete/TSDL-specification-v1.0.md b/src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v1.0.md similarity index 100% rename from src/strategies/ThroughSerialAsync/specification/obsolete/TSDL-specification-v1.0.md rename to src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v1.0.md diff --git a/src/strategies/ThroughSerialAsync/specification/obsolete/TSDL-specification-v2.0.md b/src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v2.0.md similarity index 100% rename from src/strategies/ThroughSerialAsync/specification/obsolete/TSDL-specification-v2.0.md rename to src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v2.0.md diff --git a/src/strategies/ThroughSerialAsync/specification/obsolete/TSDL-specification-v2.1.md b/src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v2.1.md similarity index 100% rename from src/strategies/ThroughSerialAsync/specification/obsolete/TSDL-specification-v2.1.md rename to src/strategies/ThroughSerial/specification/obsolete/TSDL-specification-v2.1.md From 5dab94f1cad44af3f91ed1fad97f74264f8be199 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 May 2020 00:43:02 +0200 Subject: [PATCH 048/323] ThroughSerialAsync examples removed --- .../Blink/Receiver/Receiver.ino | 32 ----------- .../Blink/Transmitter/Transmitter.ino | 21 ------- .../BlinkWithResponse/Receiver/Receiver.ino | 32 ----------- .../Transmitter/Transmitter.ino | 31 ----------- .../BlinkTest/Receiver/Makefile | 2 - .../BlinkTest/Receiver/Receiver.cpp | 55 ------------------- .../BlinkTest/Transmitter/Makefile | 2 - .../BlinkTest/Transmitter/Transmitter.cpp | 48 ---------------- .../BlinkWithAck/Receiver/Makefile | 2 - .../BlinkWithAck/Receiver/Receiver.cpp | 55 ------------------- .../BlinkWithAck/Transmitter/Makefile | 2 - .../BlinkWithAck/Transmitter/Transmitter.cpp | 49 ----------------- .../BlinkWithResponse/Receiver/Makefile | 2 - .../BlinkWithResponse/Receiver/Receiver.cpp | 50 ----------------- .../BlinkWithResponse/Transmitter/Makefile | 2 - .../Transmitter/Transmitter.cpp | 50 ----------------- .../BlinkWithResponse/Transmitter/README.md | 8 +-- .../Transmitter/Transmitter.cpp | 6 +- .../Transmitter/Transmitter.vcxproj | 0 .../Transmitter/Transmitter.vcxproj.filters | 0 20 files changed, 7 insertions(+), 442 deletions(-) delete mode 100644 examples/ARDUINO/Local/ThroughSerialAsync/Blink/Receiver/Receiver.ino delete mode 100644 examples/ARDUINO/Local/ThroughSerialAsync/Blink/Transmitter/Transmitter.ino delete mode 100644 examples/ARDUINO/Local/ThroughSerialAsync/BlinkWithResponse/Receiver/Receiver.ino delete mode 100644 examples/ARDUINO/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.ino delete mode 100644 examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Receiver/Makefile delete mode 100644 examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Receiver/Receiver.cpp delete mode 100644 examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Transmitter/Makefile delete mode 100644 examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Transmitter/Transmitter.cpp delete mode 100644 examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Receiver/Makefile delete mode 100644 examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Receiver/Receiver.cpp delete mode 100644 examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Transmitter/Makefile delete mode 100644 examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Transmitter/Transmitter.cpp delete mode 100644 examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Receiver/Makefile delete mode 100644 examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Receiver/Receiver.cpp delete mode 100644 examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Makefile delete mode 100644 examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.cpp rename examples/WINX86/Local/{ThroughSerialAsync => ThroughSerial}/BlinkWithResponse/Transmitter/README.md (53%) rename examples/WINX86/Local/{ThroughSerialAsync => ThroughSerial}/BlinkWithResponse/Transmitter/Transmitter.cpp (93%) rename examples/WINX86/Local/{ThroughSerialAsync => ThroughSerial}/BlinkWithResponse/Transmitter/Transmitter.vcxproj (100%) rename examples/WINX86/Local/{ThroughSerialAsync => ThroughSerial}/BlinkWithResponse/Transmitter/Transmitter.vcxproj.filters (100%) diff --git a/examples/ARDUINO/Local/ThroughSerialAsync/Blink/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerialAsync/Blink/Receiver/Receiver.ino deleted file mode 100644 index 1330141bf1..0000000000 --- a/examples/ARDUINO/Local/ThroughSerialAsync/Blink/Receiver/Receiver.ino +++ /dev/null @@ -1,32 +0,0 @@ - -// Include the ThroughSerialAsync strategy -#define PJON_INCLUDE_TSA true -#include - -// Use ThroughSerialAsync as a PJON Strategy -PJON bus(44); - -void setup() { - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); - // Initialize LED 13 to be off - - Serial.begin(9600); - bus.set_receiver(receiver_function); - bus.strategy.set_serial(&Serial); - bus.begin(); -}; - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ - if(payload[0] == 'B') { - digitalWrite(LED_BUILTIN, HIGH); - delay(30); - digitalWrite(LED_BUILTIN, LOW); - } -}; - -void loop() { - bus.receive(1000); -}; diff --git a/examples/ARDUINO/Local/ThroughSerialAsync/Blink/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerialAsync/Blink/Transmitter/Transmitter.ino deleted file mode 100644 index d4237590c3..0000000000 --- a/examples/ARDUINO/Local/ThroughSerialAsync/Blink/Transmitter/Transmitter.ino +++ /dev/null @@ -1,21 +0,0 @@ - -// Include the ThroughSerialAsync strategy -#define PJON_INCLUDE_TSA true - -#include - -// Use ThroughSerialAsync as a PJON Strategy -PJON bus(45); - -void setup() { - Serial.begin(9600); - - bus.strategy.set_serial(&Serial); - bus.begin(); - // Send B to device 44 every second - bus.send_repeatedly(44, "B", 1, 1000000); -}; - -void loop() { - bus.update(); -}; diff --git a/examples/ARDUINO/Local/ThroughSerialAsync/BlinkWithResponse/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerialAsync/BlinkWithResponse/Receiver/Receiver.ino deleted file mode 100644 index 95a2027dc1..0000000000 --- a/examples/ARDUINO/Local/ThroughSerialAsync/BlinkWithResponse/Receiver/Receiver.ino +++ /dev/null @@ -1,32 +0,0 @@ -#define PJON_INCLUDE_TSA true -#include - -// bus(selected device id) -PJON bus(44); - -void setup() { - pinMode(13, OUTPUT); - digitalWrite(13, LOW); // Initialize LED 13 to be off - - Serial.begin(9600); - - bus.strategy.set_serial(&Serial); - bus.set_receiver(receiver_function); - bus.begin(); -}; - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ - if(payload[0] == 'B') { - digitalWrite(13, HIGH); - delay(30); - digitalWrite(13, LOW); - bus.reply("B", 1); - } -}; - -void loop() { - bus.update(); - bus.receive(); -}; diff --git a/examples/ARDUINO/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.ino deleted file mode 100644 index d1cc0d3222..0000000000 --- a/examples/ARDUINO/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.ino +++ /dev/null @@ -1,31 +0,0 @@ -#define PJON_INCLUDE_TSA true -#include - -// bus(selected device id) -PJON bus(45); - -void setup() { - pinMode(13, OUTPUT); - digitalWrite(13, LOW); - // Initialize LED 13 to be off - Serial.begin(9600); - bus.set_receiver(receiver_function); - bus.strategy.set_serial(&Serial); // Pass the Serial object you want to use for communication - bus.begin(); - bus.send_repeatedly(44, "B", 1, 1000000); // Send B to device id 44 every second -}; - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ - if(payload[0] == 'B') { - digitalWrite(13, HIGH); - delay(30); - digitalWrite(13, LOW); - } -}; - -void loop() { - bus.update(); - bus.receive(); -}; diff --git a/examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Receiver/Makefile b/examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Receiver/Makefile deleted file mode 100644 index eb8134529a..0000000000 --- a/examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Receiver/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -all: - g++ -DLINUX -I. -I ../../../../../../src -std=gnu++11 Receiver.cpp -o Receiver -lpthread -lcrypt -lm -lrt diff --git a/examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Receiver/Receiver.cpp b/examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Receiver/Receiver.cpp deleted file mode 100644 index 3f0b710b74..0000000000 --- a/examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Receiver/Receiver.cpp +++ /dev/null @@ -1,55 +0,0 @@ - -// For printf used below -#include -// PJON library -#include -#include -#include - -#define TSA_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ - -#define PJON_INCLUDE_TSA true // Include only ThroughSerialAsync -#include - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ - printf("BLINK... \n"); - fflush(stdout); -}; - - -int main() { - printf("PJON instantiation... \n"); - PJON bus(44); - bus.set_receiver(receiver_function); - uint32_t baud_rate = 9600; - printf("Opening serial... \n"); - - // The name of the serial port may need to be edited - int s = serialOpen("/dev/ttyUSB0", baud_rate); - - if(int(s) < 0) printf("Serial open fail!"); - printf("Setting serial... \n"); - bus.strategy.set_serial(s); - bus.strategy.set_baud_rate(baud_rate); - - printf("Opening bus... \n"); - bus.begin(); - printf("Attempting to roll bus... \n"); - bus.update(); - printf("Attempting to receive from bus... \n"); - bus.receive(); - printf("Success! \n"); - - while(true) { - bus.update(); - bus.receive(); - } - - return 0; -}; diff --git a/examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Transmitter/Makefile b/examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Transmitter/Makefile deleted file mode 100644 index 80dc51b6c3..0000000000 --- a/examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Transmitter/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -all: - g++ -DLINUX -I. -I ../../../../../../src -std=gnu++11 Transmitter.cpp -o Transmitter -lpthread -lcrypt -lm -lrt diff --git a/examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Transmitter/Transmitter.cpp b/examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Transmitter/Transmitter.cpp deleted file mode 100644 index 5e2a959a89..0000000000 --- a/examples/LINUX/Local/ThroughSerialAsync/BlinkTest/Transmitter/Transmitter.cpp +++ /dev/null @@ -1,48 +0,0 @@ - -// For printf used below -#include -// PJON library -#include -#include -#include - -#define TSA_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ - -#define PJON_INCLUDE_TSA true // Include only ThroughSerialAsync -#include - -int main() { - printf("PJON instantiation... \n"); - PJON bus(45); - uint32_t baud_rate = 9600; - printf("Opening serial... \n"); - - // The name of the serial port may need to be edited - int s = serialOpen("/dev/ttyUSB0", baud_rate); - - if(int(s) < 0) printf("Serial open fail!"); - printf("Setting serial... \n"); - bus.strategy.set_serial(s); - bus.strategy.set_baud_rate(baud_rate); - - printf("Opening bus... \n"); - bus.begin(); - printf("Attempting to send B every second... \n"); - bus.send_repeatedly(44, "B", 1, 1000000); - printf("Attempting to roll bus... \n"); - bus.update(); - printf("Attempting to receive from bus... \n"); - bus.receive(); - printf("Success! \n"); - - while(true) { - bus.update(); - bus.receive(); - } - - return 0; -}; diff --git a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Receiver/Makefile b/examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Receiver/Makefile deleted file mode 100644 index eb8134529a..0000000000 --- a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Receiver/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -all: - g++ -DLINUX -I. -I ../../../../../../src -std=gnu++11 Receiver.cpp -o Receiver -lpthread -lcrypt -lm -lrt diff --git a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Receiver/Receiver.cpp b/examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Receiver/Receiver.cpp deleted file mode 100644 index 3f0b710b74..0000000000 --- a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Receiver/Receiver.cpp +++ /dev/null @@ -1,55 +0,0 @@ - -// For printf used below -#include -// PJON library -#include -#include -#include - -#define TSA_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ - -#define PJON_INCLUDE_TSA true // Include only ThroughSerialAsync -#include - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ - printf("BLINK... \n"); - fflush(stdout); -}; - - -int main() { - printf("PJON instantiation... \n"); - PJON bus(44); - bus.set_receiver(receiver_function); - uint32_t baud_rate = 9600; - printf("Opening serial... \n"); - - // The name of the serial port may need to be edited - int s = serialOpen("/dev/ttyUSB0", baud_rate); - - if(int(s) < 0) printf("Serial open fail!"); - printf("Setting serial... \n"); - bus.strategy.set_serial(s); - bus.strategy.set_baud_rate(baud_rate); - - printf("Opening bus... \n"); - bus.begin(); - printf("Attempting to roll bus... \n"); - bus.update(); - printf("Attempting to receive from bus... \n"); - bus.receive(); - printf("Success! \n"); - - while(true) { - bus.update(); - bus.receive(); - } - - return 0; -}; diff --git a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Transmitter/Makefile b/examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Transmitter/Makefile deleted file mode 100644 index 80dc51b6c3..0000000000 --- a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Transmitter/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -all: - g++ -DLINUX -I. -I ../../../../../../src -std=gnu++11 Transmitter.cpp -o Transmitter -lpthread -lcrypt -lm -lrt diff --git a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Transmitter/Transmitter.cpp b/examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Transmitter/Transmitter.cpp deleted file mode 100644 index 384baf02b3..0000000000 --- a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithAck/Transmitter/Transmitter.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// For printf used below -#include -// PJON library -#include -#include -#include -#include - -#define TSA_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ - -#define PJON_INCLUDE_TSA true // Include only ThroughSerialAsync -#include - -#define BLINK_FREQUENCY 1000000 // 1 Blink per second - -int main() { - printf("PJON instantiation... \n"); - PJON bus(45); - uint32_t baud_rate = 9600; - printf("Opening serial... \n"); - - // The name of the serial port may need to be edited - int s = serialOpen("/dev/ttyUSB0", baud_rate); - - if(int(s) < 0) printf("Serial open fail!"); - printf("Setting serial... \n"); - bus.strategy.set_serial(s); - bus.strategy.set_baud_rate(baud_rate); - - printf("Opening bus... \n"); - bus.begin(); - printf("Success, initiating BlinkTest repeated transmission... \n"); - uint32_t myTime = PJON_MICROS(); - while(true) { - if((uint32_t)(PJON_MICROS() - myTime) > BLINK_FREQUENCY) { - uint16_t result = bus.send_packet(44, "B", 1); - if(result == PJON_ACK) - printf("Packet transmission successful! \n"); - else printf("Packet transmission unsuccessful! Result: %d \n", result); - myTime = PJON_MICROS(); - } - bus.update(); - bus.receive(); - } -}; diff --git a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Receiver/Makefile b/examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Receiver/Makefile deleted file mode 100644 index eb8134529a..0000000000 --- a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Receiver/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -all: - g++ -DLINUX -I. -I ../../../../../../src -std=gnu++11 Receiver.cpp -o Receiver -lpthread -lcrypt -lm -lrt diff --git a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Receiver/Receiver.cpp b/examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Receiver/Receiver.cpp deleted file mode 100644 index d5a5bf30c5..0000000000 --- a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Receiver/Receiver.cpp +++ /dev/null @@ -1,50 +0,0 @@ - -// For printf used below -#include -// PJON library -#include -#include -#include - -#define TSA_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ - -#define PJON_INCLUDE_TSA true // Include only ThroughSerialAsync -#include -PJON bus(44); - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ - if(payload[0] == 'B') { - printf("BLINK\n"); - bus.reply("B", 1); // Reply B to 45 - } -} - -int main() { - printf("PJON instantiation... \n"); - uint32_t baud_rate = 9600; - printf("Opening serial... \n"); - - // The name of the serial port may need to be edited - int s = serialOpen("/dev/ttyUSB0", baud_rate); - - if(int(s) < 0) printf("Serial open fail!"); - printf("Setting serial... \n"); - bus.strategy.set_serial(s); - bus.strategy.set_baud_rate(baud_rate); - bus.set_receiver(receiver_function); - - printf("Opening bus... \n"); - bus.begin(); - printf("Success, initiating BlinkTest Receiver example... \n"); - - while(true) { - bus.update(); - bus.receive(1000); - } -}; diff --git a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Makefile b/examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Makefile deleted file mode 100644 index 80dc51b6c3..0000000000 --- a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -all: - g++ -DLINUX -I. -I ../../../../../../src -std=gnu++11 Transmitter.cpp -o Transmitter -lpthread -lcrypt -lm -lrt diff --git a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.cpp b/examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.cpp deleted file mode 100644 index d28a680e7e..0000000000 --- a/examples/LINUX/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.cpp +++ /dev/null @@ -1,50 +0,0 @@ - -// For printf used below -#include -// PJON library -#include -#include -#include - -#define TSA_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ - -#define PJON_INCLUDE_TSA true // Include only ThroughSerialAsync -#include - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ - if(payload[0] == 'B') { - printf("BLINK\n"); - } -} - -int main() { - printf("PJON instantiation... \n"); - PJON bus(45); - uint32_t baud_rate = 9600; - printf("Opening serial... \n"); - - // The name of the serial port may need to be edited - int s = serialOpen("/dev/ttyUSB0", baud_rate); - - if(int(s) < 0) printf("Serial open fail!"); - printf("Setting serial... \n"); - bus.strategy.set_serial(s); - bus.strategy.set_baud_rate(baud_rate); - bus.set_receiver(receiver_function); - - printf("Opening bus... \n"); - bus.begin(); - printf("Success, initiating BlinkTest repeated transmission... \n"); - bus.send_repeatedly(44, "B", 1, 1000000); // Send B to device 44 every second - - while(true) { - bus.update(); - bus.receive(1000); - } -}; diff --git a/examples/WINX86/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/README.md b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/README.md similarity index 53% rename from examples/WINX86/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/README.md rename to examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/README.md index fd3fe797bb..ac7357b90d 100644 --- a/examples/WINX86/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/README.md +++ b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/README.md @@ -1,14 +1,14 @@ -In this example is described how to connect a Windows x86 machine with an Arduino compatible device using the `ThroughSerialAsync` strategy. Connect the USB port of the windows computer/laptop to the Arduino compatible device used as a receiver. +In this example is described how to connect a Windows x86 machine with an Arduino compatible device using the `ThroughSerial` strategy. Connect the USB port of the windows computer/laptop to the Arduino compatible device used as a receiver. -Program the Arduino with the `PJON\examples\ARDUINO\Local\ThroughSerialAsync\BlinkWithResponse\Receiver.cpp` sketch and remember the device COM port assigned to that particular Arduino board (the COM selected to program the device in the Arduino IDE) because will be useful later. +Program the Arduino with the `PJON\examples\ARDUINO\Local\ThroughSerial\BlinkWithResponse\Receiver.cpp` sketch and remember the device COM port assigned to that particular Arduino board (the COM selected to program the device in the Arduino IDE) because will be useful later. Visual Studio 2017 Community is used to compile the program on the Windows x86 machine: - Click on `file` top menu option, `open` and then `folder...` -- Select the `PJON\examples\WINX86\Local\ThroughSerialAsync\BlinkWithResponse\Transmitter` directory +- Select the `PJON\examples\WINX86\Local\ThroughSerial\BlinkWithResponse\Transmitter` directory - Double click on `Transmitter.cpp` in the solution explorer (panel on right) - Edit the COM port number (at line 40) inserting the one assigned to the receiver device and save the file - Click on `Build` top menu option and then click `Build Solution` -- If the building process ended positively, you should find the executable in `PJON\examples\WINX86\Local\ThroughSerialAsync\BlinkWithResponse\Transmitter\Debug`, execute `Transmitter.exe` double clicking on it +- If the building process ended positively, you should find the executable in `PJON\examples\WINX86\Local\ThroughSerial\BlinkWithResponse\Transmitter\Debug`, execute `Transmitter.exe` double clicking on it You should see the Arduino blinking every second and at the same time see a `B` logged in the console (that is the response coming from the Arduino). diff --git a/examples/WINX86/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.cpp b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp similarity index 93% rename from examples/WINX86/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.cpp rename to examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp index 047392e8d6..04ff8a1cd0 100644 --- a/examples/WINX86/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp @@ -10,9 +10,9 @@ #define WINX86 true #endif -#define PJON_INCLUDE_TSA true +#define PJON_INCLUDE_TS true -#define TSA_RESPONSE_TIME_OUT 35000 +#define TS_RESPONSE_TIME_OUT 35000 /* Maximum accepted timeframe between transmission and synchronous acknowledgement. This timeframe is affected by latency and CRC computation. Could be necessary to higher this value if devices are separated by long @@ -33,7 +33,7 @@ static void receiver_function( int main() { printf("PJON instantiation... \n"); - PJON bus(45); + PJON bus(45); bus.set_receiver(receiver_function); // Set here the COM port assigned to the device you want to communicate with diff --git a/examples/WINX86/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.vcxproj b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.vcxproj similarity index 100% rename from examples/WINX86/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.vcxproj rename to examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.vcxproj diff --git a/examples/WINX86/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.vcxproj.filters b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.vcxproj.filters similarity index 100% rename from examples/WINX86/Local/ThroughSerialAsync/BlinkWithResponse/Transmitter/Transmitter.vcxproj.filters rename to examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.vcxproj.filters From c8865320fddbd92889987aaeb3eb27c9b7bd6785 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 May 2020 00:50:14 +0200 Subject: [PATCH 049/323] ThroughSerial docs, keywords and README update --- documentation/configuration.md | 2 -- .../Local/ThroughSerial/BlinkTest/Receiver/Receiver.ino | 5 ----- .../ThroughSerial/BlinkTest/Transmitter/Transmitter.ino | 5 ----- .../ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino | 5 ----- .../BlinkWithResponse/Transmitter/Transmitter.ino | 5 ----- keywords.txt | 2 -- src/strategies/README.md | 1 - src/strategies/ThroughSerial/README.md | 6 +++--- src/strategies/ThroughSerial/Timing.h | 2 +- 9 files changed, 4 insertions(+), 29 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index 2301f3b935..c5debd7aef 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -40,7 +40,6 @@ In the example above the PJON object is instantiated passing the [SoftwareBitBan | [OverSampling](/src/strategies/OverSampling) | Electrical/radio impulses over wire/air | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | 1 or 2 | | [AnalogSampling](/src/strategies/AnalogSampling) | Light pulses over air or optic fiber | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | 1 or 2 | | [ThroughSerial](/src/strategies/ThroughSerial) | Electrical/radio impulses over wire/air | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | -| [ThroughSerialAsync](/src/strategies/ThroughSerialAsync) | Electrical/radio impulses over wire/air | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | | [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio impulses over air | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | 3 or 4 | | [EthernetTCP](/src/strategies/EthernetTCP) | Electrical/radio impulses over wire/air | [TCP](https://tools.ietf.org/html/rfc793) | Ethernet or WiFi | | [LocalUDP](/src/strategies/LocalUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | @@ -61,7 +60,6 @@ Supported definitions: - `PJON_INCLUDE_GUDP` includes `GlobalUDP` - `PJON_INCLUDE_OS` includes `OverSampling` - `PJON_INCLUDE_TS` includes `ThroughSerial` -- `PJON_INCLUDE_TSA` includes `ThroughSerialAsync` - `PJON_INCLUDE_TL` includes `ThroughLoRa` - `PJON_INCLUDE_MQTT` includes `MQTTTranslate` - `PJON_INCLUDE_EN` includes `ESPNOW` diff --git a/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Receiver/Receiver.ino index 0fe2186c4a..60d8ebff15 100644 --- a/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Receiver/Receiver.ino @@ -1,11 +1,6 @@ -/* If you need non-blocking asynchronous operation include the - ThroughSerialAsync strategy using: - #define PJON_INCLUDE_TSA true */ #include PJON bus(44); -/* Use PJON bus(44); - instead if non-blocking asynchronous operation is required */ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.ino index f67c555248..bfe7229718 100644 --- a/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.ino @@ -1,12 +1,7 @@ -/* If you need non-blocking asynchronous operation include the - ThroughSerialAsync strategy using: - #define PJON_INCLUDE_TSA true */ #include PJON bus(45); -/* Use PJON bus(45); - instead if non-blocking asynchronous operation is required */ void setup() { Serial.begin(9600); diff --git a/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino index e42ce2d1e7..b434f26940 100644 --- a/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino @@ -1,11 +1,6 @@ -/* If you need non-blocking asynchronous operation include the - ThroughSerialAsync strategy using: - #define PJON_INCLUDE_TSA true */ #include PJON bus(44); -/* Use PJON bus(45); - instead if non-blocking asynchronous operation is required */ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.ino index 37da630821..bf1dc83f34 100644 --- a/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.ino @@ -1,12 +1,7 @@ -/* If you need non-blocking asynchronous operation include the - ThroughSerialAsync strategy using: - #define PJON_INCLUDE_TSA true */ #include PJON bus(45); -/* Use PJON bus(45); - instead if non-blocking asynchronous operation is required */ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/keywords.txt b/keywords.txt index 493443a260..e6aeeb8763 100644 --- a/keywords.txt +++ b/keywords.txt @@ -37,7 +37,6 @@ OverSampling KEYWORD1 SoftwareBitBang KEYWORD1 ThroughLora KEYWORD1 ThroughSerial KEYWORD1 -ThroughSerialAsync KEYWORD1 # Methods and Functions (KEYWORD2) @@ -133,7 +132,6 @@ PJON_INCLUDE_OS LITERAL1 PJON_INCLUDE_SWBB LITERAL1 PJON_INCLUDE_TL LITERAL1 PJON_INCLUDE_TS LITERAL1 -PJON_INCLUDE_TSA LITERAL1 PJON_INCLUDE_NONE LITERAL1 ## AnalogSampling diff --git a/src/strategies/README.md b/src/strategies/README.md index 67ddce6856..1b582a3e27 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -8,7 +8,6 @@ A strategy is an abstraction layer used to physically transmit data. Thanks to t | [OverSampling](OverSampling) | Electrical/radio impulses over wire/air | [PJDLR](OverSampling/specification/PJDLR-specification-v3.0.md) | 1 or 2 | | [AnalogSampling](AnalogSampling) | Light pulses over air or optic fiber | [PJDLS](AnalogSampling/specification/PJDLS-specification-v2.0.md) | 1 or 2 | | [ThroughSerial](ThroughSerial) | Electrical/radio impulses over wire/air | [TSDL](ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | -| [ThroughSerialAsync](ThroughSerialAsync) | Electrical/radio impulses over wire/air | [TSDL](ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | | [ThroughLoRa](ThroughLoRa) | Radio impulses over air | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | 3 or 4 | | [EthernetTCP](EthernetTCP) | Electrical/radio impulses over wire/air | [TCP](https://tools.ietf.org/html/rfc793) | Ethernet of WiFi | | [LocalUDP](LocalUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet of WiFi | diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index 5e1c5799c8..e0801f1177 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -2,7 +2,7 @@ **Medium:** Hardware or software serial port - **Pins used:** 1 or 2 - -**Inclusion constant:** `PJON_INCLUDE_TSA` +**Inclusion constant:** `PJON_INCLUDE_TS` With `ThroughSerial` strategy, PJON can run through a software or hardware Serial port working out of the box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). It complies with [TSDL v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md). @@ -30,14 +30,14 @@ Before including `PJON.h` it is possible to configure `ThroughSerial` using pred Pass the `ThroughSerial` type as PJON template parameter to instantiate a PJON object ready to communicate through this Strategy. ```cpp -#include PJON_INCLUDE_TSA +#include PJON_INCLUDE_TS PJON bus; ``` Call the `begin` method on the `Serial` or `SoftwareSerial` object you want to use for PJON communication and pass it to the `set_serial` method: ```cpp #include -PJON bus; +PJON bus; void setup() { Serial.begin(9600); diff --git a/src/strategies/ThroughSerial/Timing.h b/src/strategies/ThroughSerial/Timing.h index 0af44232de..8c5c1e8f09 100644 --- a/src/strategies/ThroughSerial/Timing.h +++ b/src/strategies/ThroughSerial/Timing.h @@ -8,7 +8,7 @@ - Franketto (Arduino forum user) RS485 TX enable pin compatibility ____________________________________________________________________________ - ThroughSerialAsync timing, based on ThroughSerial, developed by sticilface + Based on ThroughSerial, developed by sticilface copyright 2018 by Giovanni Blu Mitolo All rights reserved Licensed under the Apache License, Version 2.0 (the "License"); From 6ba09629ba52c98c87d3cd1fa232b9392b13661b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 May 2020 23:38:35 +0200 Subject: [PATCH 050/323] ThroughSerial reading failure detection added --- src/interfaces/WINX86/Serial/Serial.cpp | 13 ++++--- src/interfaces/WINX86/Serial/Serial.h | 13 ++++--- src/strategies/ThroughSerial/ThroughSerial.h | 40 +++++++++++++------- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/interfaces/WINX86/Serial/Serial.cpp b/src/interfaces/WINX86/Serial/Serial.cpp index ba7ff8c630..8cf2c7a8f3 100644 --- a/src/interfaces/WINX86/Serial/Serial.cpp +++ b/src/interfaces/WINX86/Serial/Serial.cpp @@ -10,6 +10,9 @@ * - modified flush method to use WIN API * - added initial tests * - changed timeouts to 1s + * + * + * 11/05/2020 - getByte function simplified, now returns -1 in case of failure */ #if defined(_WIN32) @@ -123,19 +126,17 @@ int Serial::writeByte(uint8_t *buffer) { return numWritten; }; -uint8_t Serial::getByte() { +int16_t Serial::getByte() { uint8_t buff; - read(&buff, 1, false); + if(read(&buff, 1) == -1) return -1; return buff; }; -int Serial::read(uint8_t *buffer, int buffLen, bool nullTerminate) { +int Serial::read(uint8_t *buffer, int buffLen) { DWORD numRead; - if(nullTerminate) --buffLen; BOOL ret = ReadFile(commHandle, buffer, buffLen, &numRead, NULL); - if(!ret) return 0; - if(nullTerminate) buffer[numRead] = '\0'; + if(!ret) return -1; return numRead; }; diff --git a/src/interfaces/WINX86/Serial/Serial.h b/src/interfaces/WINX86/Serial/Serial.h index 3bd07d2676..df34790b52 100644 --- a/src/interfaces/WINX86/Serial/Serial.h +++ b/src/interfaces/WINX86/Serial/Serial.h @@ -13,6 +13,8 @@ * @version 0.1 -- 28 October 2008 * @version 0.2 -- 20 April 2017 (Zbigniew Zasieczny) * - added methods needed by PJON to handle WINX86 abstraction interface + * + * 11/05/2020 getByte function simplified, now returns -1 in case of failure */ #pragma once @@ -50,15 +52,16 @@ * * @param buffer pointer to the buffer to be written to * @param buffLen the size of the buffer - * @param nullTerminate if set to true it will null terminate the string * * @return int the number of bytes read */ - int read(uint8_t *buffer, int buffLen, bool nullTerminate = true); + int read(uint8_t *buffer, int buffLen); - /** Returns single byte (uint8_t) from the receive buffer - */ - uint8_t getByte(); + /** Returns an integer (uint16_t) + * + * @return a value < 256 or -1 in case of failure + */ + int16_t getByte(); /** Returns true if there is data available in receive buffer */ diff --git a/src/strategies/ThroughSerial/ThroughSerial.h b/src/strategies/ThroughSerial/ThroughSerial.h index b9e480fc6d..b9aeb3d695 100644 --- a/src/strategies/ThroughSerial/ThroughSerial.h +++ b/src/strategies/ThroughSerial/ThroughSerial.h @@ -105,7 +105,17 @@ class ThroughSerial { }; - /* Receive byte response */ + /* Receive Byte */ + + int16_t receive_byte() { + int16_t value = PJON_SERIAL_READ(serial); + if(value == -1) return -1; + _last_reception_time = PJON_MICROS(); + return value; + }; + + + /* It returns the state of the previous transmission: */ uint16_t receive_response() { uint32_t time = PJON_MICROS(); @@ -152,8 +162,8 @@ class ThroughSerial { switch(state) { case TS_WAITING: { while(PJON_SERIAL_AVAILABLE(serial)) { - uint8_t value = PJON_SERIAL_READ(serial); - _last_reception_time = PJON_MICROS(); + int16_t value = receive_byte(); + if(value == -1) return TS_FAIL; if(value == TS_START) { state = TS_RECEIVING; position = 0; @@ -164,8 +174,8 @@ class ThroughSerial { } case TS_RECEIVING: { while(PJON_SERIAL_AVAILABLE(serial)) { - uint8_t value = PJON_SERIAL_READ(serial); - _last_reception_time = PJON_MICROS(); + int16_t value = receive_byte(); + if(value == -1) return TS_FAIL; if(value == TS_START) { state = TS_WAITING; return TS_FAIL; @@ -175,8 +185,9 @@ class ThroughSerial { state = TS_WAITING_ESCAPE; return TS_FAIL; } else { - value = PJON_SERIAL_READ(serial) ^ TS_ESC; - _last_reception_time = PJON_MICROS(); + value = receive_byte(); + if(value == -1) return TS_FAIL; + value = value ^ TS_ESC; if( (value != TS_START) && (value != TS_ESC) && @@ -185,7 +196,7 @@ class ThroughSerial { state = TS_WAITING; return TS_FAIL; } - buffer[position++] = value; + buffer[position++] = (uint8_t)value; continue; } } @@ -205,15 +216,16 @@ class ThroughSerial { return TS_FAIL; } - buffer[position++] = value; + buffer[position++] = (uint8_t)value; } return TS_FAIL; } case TS_WAITING_ESCAPE: { if(PJON_SERIAL_AVAILABLE(serial)) { - uint8_t value = PJON_SERIAL_READ(serial) ^ TS_ESC; - _last_reception_time = PJON_MICROS(); + int16_t value = receive_byte(); + if(value == -1) return TS_FAIL; + value = value ^ TS_ESC; if( (value != TS_START) && (value != TS_ESC) && @@ -222,7 +234,7 @@ class ThroughSerial { state = TS_WAITING; return TS_FAIL; } - buffer[position++] = value; + buffer[position++] = (uint8_t)value; state = TS_RECEIVING; return TS_FAIL; } @@ -231,8 +243,8 @@ class ThroughSerial { case TS_WAITING_END: { if(PJON_SERIAL_AVAILABLE(serial)) { - uint8_t value = PJON_SERIAL_READ(serial); - _last_reception_time = PJON_MICROS(); + int16_t value = receive_byte(); + if(value == -1) return TS_FAIL; if(value == TS_END) { state = TS_DONE; return TS_FAIL; From b343bfc833e83c33561fcd71e6a1a7bc727f2f2a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 May 2020 23:49:08 +0200 Subject: [PATCH 051/323] ThroughSerial WINX86 Serial init simplified, examples updated --- .../BlinkTest/Transmitter/Transmitter.cpp | 88 +++++++++++-------- .../BlinkWithResponse/Transmitter/README.md | 2 +- .../Transmitter/Transmitter.cpp | 74 +++++++++++----- src/interfaces/WINX86/Serial/Serial.cpp | 26 +----- src/interfaces/WINX86/Serial/Serial.h | 4 +- 5 files changed, 106 insertions(+), 88 deletions(-) diff --git a/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp b/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp index 86969df23a..6dcb5f2adc 100644 --- a/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp @@ -1,71 +1,85 @@ + +// This example shows how to send and receive packets over the serial port + +/* WINX86 constant may not be defined + used by PJON to detect windows */ +#ifndef WINX86 + #define WINX86 true +#endif + #include #include + // PJON library #include #include #include #include -#ifndef WINX86 - #define WINX86 true -#endif +// Set the preferred baudrate +#define BAUDRATE 9600 -#define TS_RESPONSE_TIME_OUT 60000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ +// Set the USB COM port used +#define COM_PORT "COM9" -#define TS_COLLISION_DELAY 3000 +// Include only ThroughSerial +#define PJON_INCLUDE_TS -#define PJON_INCLUDE_TS true +// Include PJON library #include -static void receiver_function( - uint8_t *payload, - uint16_t length, - const PJON_Packet_Info &packet_info -) { - for (uint32_t i = 0; i != length; i++) - std::cout << payload[i]; - std::cout << std::endl; +PJON bus(45); + +// Error handler called when something goes wrong + +void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { + if(code == PJON_CONNECTION_LOST) { + printf("Packet transmission for device id "); + printf("%d", bus.packets[data].content[0]); + printf(" failed, some error occurred. \n"); + } + if(code == PJON_PACKETS_BUFFER_FULL) { + printf("Packet buffer is full with a length of "); + std::cout << data; + printf("\ndefine PJON_MAX_PACKETS setting a higher value. \n"); + } + if(code == PJON_CONTENT_TOO_LONG) { + printf("Packet is too long, length: "); + printf(" %d \n", data); + } + fflush(stdout); }; int main() { printf("PJON instantiation... \n"); - PJON bus(45); - bus.set_receiver(receiver_function); + bus.set_error(error_handler); // Set here the COM port assigned to the device you want to communicate with - tstring commPortName(TEXT("COM9")); - int bitRate = 9600; + tstring com_port(TEXT(COM_PORT)); try { printf("Opening serial... \n"); - Serial serial_handle( - commPortName, - bitRate, - false, - false - ); + Serial serial_handle(com_port, BAUDRATE); printf("Setting serial... \n"); bus.strategy.set_serial(&serial_handle); + printf("Opening bus... \n"); bus.begin(); - printf("Success, initiating BlinkTest repeated transmission... \n"); - while(true) - if(bus.send_packet(44, "B", 1) == PJON_ACK) { - bus.receive(1000000); - printf("Device blinked as requested! \n"); - } else printf("Failure! \n"); - } - catch (const char* msg) { + printf("Success, initiating BlinkTest 1s repeated transmission... \n"); + bus.send_repeatedly(44, "B", 1, 1000000); + + while(true) { + bus.update(); + bus.receive(); + // This line helps to reduce the CPU's usage + PJON_DELAY_MICROSECONDS(10); + } + } catch (const char* msg) { printf("exc: "); printf(msg); printf("\n"); return 1; } - }; diff --git a/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/README.md b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/README.md index ac7357b90d..ed9f3e1b81 100644 --- a/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/README.md +++ b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/README.md @@ -7,7 +7,7 @@ Visual Studio 2017 Community is used to compile the program on the Windows x86 m - Click on `file` top menu option, `open` and then `folder...` - Select the `PJON\examples\WINX86\Local\ThroughSerial\BlinkWithResponse\Transmitter` directory - Double click on `Transmitter.cpp` in the solution explorer (panel on right) -- Edit the COM port number (at line 40) inserting the one assigned to the receiver device and save the file +- Edit the COM port number (at line 23) inserting the one assigned to the receiver device and save the file - Click on `Build` top menu option and then click `Build Solution` - If the building process ended positively, you should find the executable in `PJON\examples\WINX86\Local\ThroughSerial\BlinkWithResponse\Transmitter\Debug`, execute `Transmitter.exe` double clicking on it diff --git a/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp index 04ff8a1cd0..5588b4a679 100644 --- a/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp @@ -1,72 +1,100 @@ + +// This example shows how to send and receive packets over the serial port + +/* WINX86 constant may not be defined + used by PJON to detect windows */ +#ifndef WINX86 + #define WINX86 true +#endif + #include #include + // PJON library #include #include #include #include -#ifndef WINX86 - #define WINX86 true -#endif +// Set the preferred baudrate +#define BAUDRATE 9600 -#define PJON_INCLUDE_TS true +// Set the USB COM port used +#define COM_PORT "COM9" -#define TS_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ +// Include only ThroughSerial +#define PJON_INCLUDE_TS +// Include PJON library #include +PJON bus(45); + +// The function called when data is received + static void receiver_function( uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info ) { + // Print data received for (uint32_t i = 0; i != length; i++) std::cout << payload[i]; std::cout << std::endl; fflush(stdout); }; +// Error handler called when something goes wrong + +void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { + if(code == PJON_CONNECTION_LOST) { + printf("Packet transmission for device id "); + printf("%d", bus.packets[data].content[0]); + printf(" failed, some error occurred. \n"); + } + if(code == PJON_PACKETS_BUFFER_FULL) { + printf("Packet buffer is full with a length of "); + std::cout << data; + printf("\ndefine PJON_MAX_PACKETS setting a higher value. \n"); + } + if(code == PJON_CONTENT_TOO_LONG) { + printf("Packet is too long, length: "); + printf(" %d \n", data); + } + fflush(stdout); +}; + int main() { printf("PJON instantiation... \n"); - PJON bus(45); bus.set_receiver(receiver_function); + bus.set_error(error_handler); // Set here the COM port assigned to the device you want to communicate with - tstring commPortName(TEXT("COM5")); - uint32_t bitRate = 9600; + tstring com_port(TEXT(COM_PORT)); try { printf("Opening serial... \n"); - Serial serial_handle( - commPortName, - bitRate, - false, - false - ); + Serial serial_handle(com_port, BAUDRATE); printf("Setting serial... \n"); bus.strategy.set_serial(&serial_handle); + printf("Opening bus... \n"); bus.begin(); + + printf("Success, initiating BlinkTest 1s repeated transmission... \n"); bus.send_repeatedly(44, "B", 1, 1000000); - printf("Success, initiating BlinkTest repeated transmission... \n"); while(true) { bus.update(); bus.receive(); + // This line helps to reduce the CPU's usage + PJON_DELAY_MICROSECONDS(10); } - } - - catch (const char* msg) { + } catch (const char* msg) { printf("exc: "); printf(msg); printf("\n"); return 1; } - }; diff --git a/src/interfaces/WINX86/Serial/Serial.cpp b/src/interfaces/WINX86/Serial/Serial.cpp index 8cf2c7a8f3..4da114175c 100644 --- a/src/interfaces/WINX86/Serial/Serial.cpp +++ b/src/interfaces/WINX86/Serial/Serial.cpp @@ -35,12 +35,7 @@ std::wstring s2ws(const std::string& s){ }; -Serial::Serial( - std::string &commPortName, - int bitRate, - bool testOnStartup, - bool cycleDtrOnStartup -) { +Serial::Serial(std::string &commPortName, int bd) { std::wstring com_name_ws = s2ws(commPortName); commHandle = @@ -83,7 +78,7 @@ Serial::Serial( // set DCB; disabling harware flow control; setting 1N8 mode memset(&dcb, 0, sizeof(dcb)); dcb.DCBlength = sizeof(dcb); - dcb.BaudRate = bitRate; + dcb.BaudRate = bd; dcb.fBinary = 1; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fRtsControl = RTS_CONTROL_DISABLE; @@ -96,23 +91,6 @@ Serial::Serial( throw("ERROR: Could not set com port parameters"); } } - - if(cycleDtrOnStartup) { - if(!EscapeCommFunction(commHandle, CLRDTR)) - throw("ERROR: clearing DTR"); - Sleep(200); - if(!EscapeCommFunction(commHandle, SETDTR)) - throw("ERROR: setting DTR"); - } - - if(testOnStartup) { - DWORD numWritten; - char init[] = "PJON-python init"; - if(!WriteFile(commHandle, init, sizeof(init), &numWritten, NULL)) - throw("writing initial data to port failed"); - if(numWritten != sizeof(init)) - throw("ERROR: not all test data written to port"); - } }; diff --git a/src/interfaces/WINX86/Serial/Serial.h b/src/interfaces/WINX86/Serial/Serial.h index df34790b52..5626154783 100644 --- a/src/interfaces/WINX86/Serial/Serial.h +++ b/src/interfaces/WINX86/Serial/Serial.h @@ -33,9 +33,7 @@ public: Serial( std::string &commPortName, - int bitRate = 115200, - bool testOnStartup = false, - bool cycleDtrOnStartup = false + int bitRate = 115200 ); virtual ~Serial(); From 61b55bc92757833a2a0f1128edd384e0164f301e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 May 2020 01:30:44 +0200 Subject: [PATCH 052/323] ThroughSerial buffer write failure detection added --- src/strategies/ThroughSerial/ThroughSerial.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/strategies/ThroughSerial/ThroughSerial.h b/src/strategies/ThroughSerial/ThroughSerial.h index b9aeb3d695..abb195913f 100644 --- a/src/strategies/ThroughSerial/ThroughSerial.h +++ b/src/strategies/ThroughSerial/ThroughSerial.h @@ -62,9 +62,9 @@ class ThroughSerial { uint32_t back_off(uint8_t attempts) { uint32_t result = attempts; - for (uint8_t d = 0; d < TS_BACK_OFF_DEGREE; d++) + for(uint8_t d = 0; d < TS_BACK_OFF_DEGREE; d++) result *= (uint32_t)(attempts); - return result; + return result + PJON_RANDOM(TS_COLLISION_DELAY); }; @@ -81,12 +81,12 @@ class ThroughSerial { /* Check if the channel is free for transmission: */ bool can_start() { + PJON_DELAY_MICROSECONDS(PJON_RANDOM(TS_COLLISION_DELAY)); if( (state != TS_WAITING) || PJON_SERIAL_AVAILABLE(serial) || ((uint32_t)(PJON_MICROS() - _last_reception_time) < TS_TIME_IN) ) return false; - PJON_DELAY_MICROSECONDS(PJON_RANDOM(TS_COLLISION_DELAY)); return true; }; @@ -118,6 +118,7 @@ class ThroughSerial { /* It returns the state of the previous transmission: */ uint16_t receive_response() { + if(_fail) return TS_FAIL; uint32_t time = PJON_MICROS(); uint8_t i = 0; while((uint32_t)(PJON_MICROS() - time) < TS_RESPONSE_TIME_OUT) { @@ -272,10 +273,12 @@ class ThroughSerial { void send_byte(uint8_t b) { uint32_t time = PJON_MICROS(); + int16_t result = 0; while( - (PJON_SERIAL_WRITE(serial, b) != 1) && + ((result = PJON_SERIAL_WRITE(serial, b)) != 1) && ((uint32_t)(PJON_MICROS() - time) < TS_BYTE_TIME_OUT) ); + if(result != 1) _fail = true; }; @@ -314,11 +317,13 @@ class ThroughSerial { /* Send a string: */ void send_frame(uint8_t *data, uint16_t length) { + _fail = false; start_tx(); uint16_t overhead = 2; // Add frame flag send_byte(TS_START); for(uint16_t b = 0; b < length; b++) { + if(_fail) return; // Byte-stuffing if( (data[b] == TS_START) || @@ -429,6 +434,7 @@ class ThroughSerial { uint16_t _flush_offset = TS_FLUSH_OFFSET; uint32_t _bd; #endif + bool _fail = false; uint8_t _response[TS_RESPONSE_LENGTH]; uint32_t _last_reception_time = 0; uint32_t _last_call_time = 0; From 3018caa471775bcb8e74db8d171959490cd8cb4d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 May 2020 01:31:13 +0200 Subject: [PATCH 053/323] ThroughSerial default configuration update --- src/strategies/ThroughSerial/Timing.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategies/ThroughSerial/Timing.h b/src/strategies/ThroughSerial/Timing.h index 8c5c1e8f09..d31bafb11d 100644 --- a/src/strategies/ThroughSerial/Timing.h +++ b/src/strategies/ThroughSerial/Timing.h @@ -32,15 +32,15 @@ /* Maximum 32 microseconds random delay in case of collision */ #ifndef TS_COLLISION_DELAY - #define TS_COLLISION_DELAY 32 + #define TS_COLLISION_DELAY 64 #endif -/* Set 10 milliseconds as the maximum timeframe between transmission and +/* Set 40 milliseconds as the maximum timeframe between transmission and synchronous acknowledgement response. Its optimal configuration is strictly related to the maximum time needed by receiver to receive, compute and transmit back a response. */ #ifndef TS_RESPONSE_TIME_OUT - #define TS_RESPONSE_TIME_OUT 10000 + #define TS_RESPONSE_TIME_OUT 40000 #endif /* Minum duration of channel free for use before transmission. @@ -69,7 +69,7 @@ setting TS_RESPONSE_LENGTH < 4 reduces reliability and leads to higher chances of detecting a false positive. */ #ifndef TS_RESPONSE_LENGTH - #define TS_RESPONSE_LENGTH 5 + #define TS_RESPONSE_LENGTH 1 #endif /* Maximum transmission attempts */ From 8b5eddc8b4f3fc87f339a4aa2331832ea17cc6cf Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 May 2020 01:38:44 +0200 Subject: [PATCH 054/323] docs and READMEs minor fix --- documentation/addressing.md | 8 +++++++- .../ThroughSerial/BlinkTest/Transmitter/README.md | 2 +- src/strategies/README.md | 10 +++++----- src/strategies/ThroughSerial/README.md | 5 ++++- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/documentation/addressing.md b/documentation/addressing.md index 016e028f82..43b9e35ede 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -55,7 +55,7 @@ PJON bus(bus_id, 44); The bus id can be read and set after initialisation using `bus_id`: ```cpp - bus.bus_id; // Get or set bus id + bus.tx.bus_id; // Get or set bus id ``` ### Hardware identifier @@ -76,3 +76,9 @@ This instantiation sets the MAC address, the device id set to `PJON_NOT_ASSIGNED ```cpp bus.include_mac(false); ``` +### Get or set hardware identifier + +The MAC address can be read and set after initialisation using `tx.mac`: +```cpp + bus.tx.mac; // Get or set MAC +``` diff --git a/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/README.md b/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/README.md index 5b48a98cb8..72074e0191 100644 --- a/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/README.md +++ b/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/README.md @@ -7,7 +7,7 @@ Visual Studio 2017 Community is used to compile the program on the Windows x86 m - Click on `file` top menu option, `open` and then `folder...` - Select the `PJON\examples\WINX86\Local\ThroughSerial\BlinkTest\Transmitter` directory - Double click on `Transmitter.cpp` in the solution explorer (panel on right) -- Edit the COM port number (at line 40) inserting the one assigned to the receiver device and save the file +- Edit the COM port number (at line 23) inserting the one assigned to the receiver device and save the file - Click on `Build` top menu option and then click `Build Solution` - If the building process ended positively, you should find the executable in `PJON\examples\WINX86\Local\ThroughSerial\BlinkTest\Transmitter\Debug`, execute `Transmitter.exe` double clicking on it diff --git a/src/strategies/README.md b/src/strategies/README.md index 1b582a3e27..8d521b5910 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -9,11 +9,11 @@ A strategy is an abstraction layer used to physically transmit data. Thanks to t | [AnalogSampling](AnalogSampling) | Light pulses over air or optic fiber | [PJDLS](AnalogSampling/specification/PJDLS-specification-v2.0.md) | 1 or 2 | | [ThroughSerial](ThroughSerial) | Electrical/radio impulses over wire/air | [TSDL](ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | | [ThroughLoRa](ThroughLoRa) | Radio impulses over air | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | 3 or 4 | -| [EthernetTCP](EthernetTCP) | Electrical/radio impulses over wire/air | [TCP](https://tools.ietf.org/html/rfc793) | Ethernet of WiFi | -| [LocalUDP](LocalUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet of WiFi | -| [GlobalUDP](GlobalUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet of WiFi | -| [DualUDP](DualUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet of WiFi | -| [MQTTTranslate](MQTTTranslate) | Electrical/radio impulses over wire/air | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | Ethernet of WiFi | +| [EthernetTCP](EthernetTCP) | Electrical/radio impulses over wire/air | [TCP](https://tools.ietf.org/html/rfc793) | Ethernet or WiFi | +| [LocalUDP](LocalUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | +| [GlobalUDP](GlobalUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | +| [DualUDP](DualUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | +| [MQTTTranslate](MQTTTranslate) | Electrical/radio impulses over wire/air | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | Ethernet or WiFi | | [ESPNOW](ESPNOW) | Radio impulses over air | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | WiFi link | | [LocalFile](LocalFile) | Shared file system in memory | None | None | | [Any](Any) | Virtual inheritance, any of the above | Any of the above | Any of the above | diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index e0801f1177..7d49db9b36 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -42,9 +42,12 @@ PJON bus; void setup() { Serial.begin(9600); bus.strategy.set_serial(&Serial); - bus.strategy.set_read_interval(100); } ``` +There is a default reception interval of 100 microseconds used to allow data to accumulate in the hardware UART buffer. This value is configurable using `bus.strategy.set_read_interval(100)` passing an arbitrary interval in microseconds. The read interval may require adjustment depending on UART RX buffer size and baud rate. +```cpp +bus.strategy.set_read_interval(100); +``` For a simple use with RS485 serial modules a transmission enable pin setter has been added: ```cpp bus.strategy.set_enable_RS485_pin(11); From f70641522896bab4b5f49ba28ff38e276f69766a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 May 2020 02:13:20 +0200 Subject: [PATCH 055/323] documentation/configuration strategies table update --- documentation/configuration.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index c5debd7aef..fe307a1196 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -36,19 +36,19 @@ In the example above the PJON object is instantiated passing the [SoftwareBitBan | Strategy | Physical layer | Protocol | Pins needed | | ------------- | -------------- | -------- | ------------- | -| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Electrical impulses over wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | 1 or 2 | -| [OverSampling](/src/strategies/OverSampling) | Electrical/radio impulses over wire/air | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | 1 or 2 | -| [AnalogSampling](/src/strategies/AnalogSampling) | Light pulses over air or optic fiber | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | 1 or 2 | -| [ThroughSerial](/src/strategies/ThroughSerial) | Electrical/radio impulses over wire/air | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | -| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio impulses over air | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | 3 or 4 | -| [EthernetTCP](/src/strategies/EthernetTCP) | Electrical/radio impulses over wire/air | [TCP](https://tools.ietf.org/html/rfc793) | Ethernet or WiFi | -| [LocalUDP](/src/strategies/LocalUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | -| [GlobalUDP](/src/strategies/GlobalUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | -| [DualUDP](/src/strategies/DualUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | -| [MQTTTranslate](/src/strategies/MQTTTranslate) | Electrical/radio impulses over wire/air | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | Ethernet or WiFi | -| [ESPNOW](/src/strategies/ESPNOW) | Radio impulses over air | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | WiFi link | -| [LocalFile](/src/strategies/LocalFile) | Shared file system in memory | None | None | -| [Any](/src/strategies/Any) | Virtual inheritance, any of the above | Any of the above | Any of the above | +| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | 1 or 2 | +| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | 1 or 2 | +| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | 1 or 2 | +| [ThroughSerial](/src/strategies/ThroughSerial) | Radio | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | +| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | 3 or 4 | +| [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | Ethernet or WiFi | +| [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | +| [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | +| [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | +| [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | Ethernet or WiFi | +| [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | WiFi link | +| [LocalFile](/src/strategies/LocalFile) | System memory | None | None | +| [Any](/src/strategies/Any) | Virtual inheritance, any of the above | Any | Any | By default all strategies are included except `MQTTTranslate`, `LocalFile`, `ThroughLoRa` and `ESPNOW`. To reduce memory footprint add for example `#define PJON_INCLUDE_SWBB` before including the library to select only the `SoftwareBitBang` strategy. More than one strategy related constants can be defined in the same program if that is required. From e860403e1d0a9409d22385f46447638c935c08a8 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 May 2020 02:18:39 +0200 Subject: [PATCH 056/323] strategies table removed pins needed column --- documentation/configuration.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index fe307a1196..3fbb5bae01 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -34,21 +34,21 @@ In the example above the PJON object is instantiated passing the [SoftwareBitBan PJON tcpBus; ``` -| Strategy | Physical layer | Protocol | Pins needed | -| ------------- | -------------- | -------- | ------------- | -| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | 1 or 2 | -| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | 1 or 2 | -| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | 1 or 2 | -| [ThroughSerial](/src/strategies/ThroughSerial) | Radio | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | -| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | 3 or 4 | -| [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | Ethernet or WiFi | -| [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | -| [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | -| [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | -| [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | Ethernet or WiFi | -| [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | WiFi link | -| [LocalFile](/src/strategies/LocalFile) | System memory | None | None | -| [Any](/src/strategies/Any) | Virtual inheritance, any of the above | Any | Any | +| Strategy | Physical layer | Protocol | +| ------------- | -------------- | -------- | +| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | +| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | +| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | +| [ThroughSerial](/src/strategies/ThroughSerial) | Radio | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | +| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | +| [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | +| [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | +| [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | +| [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | +| [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | +| [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | +| [LocalFile](/src/strategies/LocalFile) | System memory | None | +| [Any](/src/strategies/Any) | Virtual inheritance, any of the above | Any | By default all strategies are included except `MQTTTranslate`, `LocalFile`, `ThroughLoRa` and `ESPNOW`. To reduce memory footprint add for example `#define PJON_INCLUDE_SWBB` before including the library to select only the `SoftwareBitBang` strategy. More than one strategy related constants can be defined in the same program if that is required. From 69f45c5d504fb463c0e4c02b8e110cf4bddb3d6d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 May 2020 03:30:20 +0200 Subject: [PATCH 057/323] ThroughSerial comments, codestyle and READMEs minor fix --- .../BlinkWithResponse/Receiver/Receiver.ino | 2 +- src/PJON.h | 70 +++++++++---------- src/PJONDefines.h | 10 +-- src/strategies/ThroughSerial/README.md | 2 +- src/strategies/ThroughSerial/Timing.h | 7 +- 5 files changed, 45 insertions(+), 46 deletions(-) diff --git a/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino index b434f26940..9efa95bb20 100644 --- a/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino @@ -9,7 +9,7 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info digitalWrite(LED_BUILTIN, HIGH); delay(30); digitalWrite(LED_BUILTIN, LOW); - bus.reply("B", 1); + if(!bus.update()) bus.reply("B", 1); } }; diff --git a/src/PJON.h b/src/PJON.h index 7ca4b36240..3188bad4f1 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -95,10 +95,10 @@ class PJON { /* PJON initialization with no parameters: State: Local (bus_id: 0.0.0.0) - Synchronous acknowledge: true + Acknowledge: true device id: PJON_NOT_ASSIGNED (255) Mode: PJON_HALF_DUPLEX - Sender info: true (Sender info are included in the packet) + Sender info: true (Sender info is included in the packet) PJON bus; */ @@ -222,6 +222,30 @@ class PJON { return packets_count; }; + /* Fill a PJON_Packet_Info using parameters: */ + + PJON_Packet_Info fill_info( + uint8_t rx_id, + uint8_t header, + uint16_t packet_id, + uint16_t rx_port + ) { + PJON_Packet_Info info; + info.rx.id = rx_id; + info.header = header; + #if(PJON_INCLUDE_PACKET_ID) + info.id = packet_id; + #else + (void)packet_id; + #endif + #if(PJON_INCLUDE_PORT) + info.port = rx_port; + #else + (void)rx_port; + #endif + return info; + }; + /* Calculate packet overhead: */ uint8_t packet_overhead(uint8_t header = PJON_NO_HEADER) const { @@ -407,30 +431,6 @@ class PJON { return false; }; - /* Fill a PJON_Packet_Info using parameters: */ - - PJON_Packet_Info fill_info( - uint8_t rx_id, - uint8_t header, - uint16_t packet_id, - uint16_t rx_port - ) { - PJON_Packet_Info info; - info.rx.id = rx_id; - info.header = header; - #if(PJON_INCLUDE_PACKET_ID) - info.id = packet_id; - #else - (void)packet_id; - #endif - #if(PJON_INCLUDE_PORT) - info.port = rx_port; - #else - (void)rx_port; - #endif - return info; - }; - /* Schedule a packet sending to the sender of the last packet received. This function is typically called within the receive callback to deliver a response to a request. */ @@ -678,25 +678,25 @@ class PJON { else config &= ~bit; }; - /* Configure synchronous acknowledge presence: - state = true -> Request 8 bits synchronous acknowledgement - state = false -> Do not request synchronous acknowledgement */ + /* Configure acknowledge: + state = true -> Request acknowledgement + state = false -> Do not request acknowledgement */ void set_acknowledge(bool state) { set_config_bit(state, PJON_ACK_REQ_BIT); }; /* Configure CRC selected for packet checking: - state = true -> CRC32 - state = false -> CRC8 */ + state = true -> Use CRC32 + state = false -> Use CRC8 */ void set_crc_32(bool state) { set_config_bit(state, PJON_CRC_BIT); }; /* Set communication mode: - mode = 0 or PJON_SIMPLEX -> communication is mono-directional - mode = 1 or PJON_HALF_DUPLEX -> communication is bi-directional */ + mode = 0 or PJON_SIMPLEX -> Communication is mono-directional + mode = 1 or PJON_HALF_DUPLEX -> Communication is bi-directional */ void set_communication_mode(bool mode) { _mode = mode; @@ -797,7 +797,7 @@ class PJON { }; /* Update the state of the send list: - Check if there are packets to be sent or to be erased if correctly + Checks if there are packets to be sent or to be erased if correctly delivered. Returns the actual number of packets to be sent. */ uint16_t update() { @@ -838,7 +838,7 @@ class PJON { #if(PJON_INCLUDE_PACKET_ID) - /* Check if the packet id and its transmitter info are already present + /* Checks if the packet id and its transmitter info are already present in the known packets buffer, if not add it to the buffer */ bool known_packet_id(PJON_Packet_Info info) { diff --git a/src/PJONDefines.h b/src/PJONDefines.h index a218189bfd..c00b58c07f 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -151,7 +151,7 @@ limitations under the License. */ /* If defined includes the packet id feature */ #ifdef PJON_INCLUDE_PACKET_ID #undef PJON_INCLUDE_PACKET_ID - #define PJON_INCLUDE_PACKET_ID true + #define PJON_INCLUDE_PACKET_ID true #else #define PJON_INCLUDE_PACKET_ID false #endif @@ -159,17 +159,17 @@ limitations under the License. */ /* If defined includes the port id feature */ #ifdef PJON_INCLUDE_PORT #undef PJON_INCLUDE_PORT - #define PJON_INCLUDE_PORT true + #define PJON_INCLUDE_PORT true #else - #define PJON_INCLUDE_PORT false + #define PJON_INCLUDE_PORT false #endif /* If defined includes the mac address feature */ #ifdef PJON_INCLUDE_MAC #undef PJON_INCLUDE_MAC - #define PJON_INCLUDE_MAC true + #define PJON_INCLUDE_MAC true #else - #define PJON_INCLUDE_MAC false + #define PJON_INCLUDE_MAC false #endif /* Data structures: */ diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index 7d49db9b36..b6e6aa87e4 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -24,7 +24,7 @@ Before including `PJON.h` it is possible to configure `ThroughSerial` using pred | ----------------------- |------------------------------------ | ------------------------------------------ | | `TS_READ_INTERVAL` | minimum interval between receptions | Duration in microseconds (100 by default) | | `TS_BYTE_TIME_OUT` | Maximum byte reception time-out | Duration in microseconds (1000000 by default) | -| `TS_RESPONSE_TIME_OUT` | Maximum response time-out | Duration in microseconds (10000 by default) | +| `TS_RESPONSE_TIME_OUT` | Maximum response time-out | Duration in microseconds (40000 by default) | | `TS_BACK_OFF_DEGREE` | Maximum back-off exponential degree | Numeric value (4 by default) | | `TS_MAX_ATTEMPTS` | Maximum transmission attempts | Numeric value (20 by default) | diff --git a/src/strategies/ThroughSerial/Timing.h b/src/strategies/ThroughSerial/Timing.h index d31bafb11d..dc7bb8a544 100644 --- a/src/strategies/ThroughSerial/Timing.h +++ b/src/strategies/ThroughSerial/Timing.h @@ -63,10 +63,9 @@ #endif /* Response length (the response is composed by the last TS_RESPONSE_LENGTH - bytes of the packet received). By default should be relatively safe. - (Few false positives per millennia) - If you are ready to trade safety for bandwidth reduce it, consider that - setting TS_RESPONSE_LENGTH < 4 reduces reliability and leads to higher + bytes of the packet received). By default should be relatively safe if + used in master-slave mode. Setting TS_RESPONSE_LENGTH < 4 when using + ThroughSerial in multi-master mode reduces reliability and leads to higher chances of detecting a false positive. */ #ifndef TS_RESPONSE_LENGTH #define TS_RESPONSE_LENGTH 1 From 5575b8163034bc705139eb76c53f029167d715ba Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 May 2020 14:43:46 +0200 Subject: [PATCH 058/323] Strategies README initial info update --- src/strategies/AnalogSampling/README.md | 6 +++--- src/strategies/Any/README.md | 7 ++++--- src/strategies/DualUDP/README.md | 6 +++--- src/strategies/ESPNOW/README.md | 6 +++--- src/strategies/EthernetTCP/README.md | 6 +++--- src/strategies/GlobalUDP/README.md | 6 +++--- src/strategies/LocalFile/README.md | 6 +++--- src/strategies/LocalUDP/README.md | 6 +++--- src/strategies/MQTTTranslate/README.md | 6 +++--- src/strategies/OverSampling/README.md | 7 +++---- src/strategies/SoftwareBitBang/README.md | 6 +++--- src/strategies/ThroughLoRa/README.md | 6 +++--- 12 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/strategies/AnalogSampling/README.md b/src/strategies/AnalogSampling/README.md index 32b35529e7..58e4301298 100644 --- a/src/strategies/AnalogSampling/README.md +++ b/src/strategies/AnalogSampling/README.md @@ -1,8 +1,8 @@ ## AnalogSampling -**Medium:** Light pulses over air or optic-fibre | -**Pins used:** 1 or 2 | -**Inclusion constant:** `PJON_INCLUDE_AS` +| Medium | Pins used | Inclusion Constant | Included by default | +|--------|-----------|--------------------|---------------------| +| Light pulses over air or optic-fibre | 1 or 2 | `PJON_INCLUDE_AS`| yes | `AnalogSampling` strategy or data link complies with [PJDLS v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md), it is designed to communicate data wirelessly using light impulses and its sampling technique is based on analog readings. This strategy is able to use a single LED for both photo-emission and photo-reception phases providing with wireless half-duplex connectivity between devices with a range of up to 5 meters. Most appliances have at least a useless energy consuming LED on board, right? diff --git a/src/strategies/Any/README.md b/src/strategies/Any/README.md index 7274baad23..d0dd32e788 100644 --- a/src/strategies/Any/README.md +++ b/src/strategies/Any/README.md @@ -1,8 +1,9 @@ ## Any -**Medium:** Any - -**Pins used:** NA - -**Inclusion constant:** `PJON_INCLUDE_ANY` +| Medium | Pins used | Inclusion Constant | Included by default | +|--------|-----------|--------------------|---------------------| +| Any | NA | `PJON_INCLUDE_ANY` | yes | + The `Any` strategy includes virtual inheritance and let PJON objects change from a strategy to another after instantiation or a collection of PJON objects with different strategies to be treated agnostically. diff --git a/src/strategies/DualUDP/README.md b/src/strategies/DualUDP/README.md index e119989976..99c3f4c1ae 100644 --- a/src/strategies/DualUDP/README.md +++ b/src/strategies/DualUDP/README.md @@ -1,8 +1,8 @@ ## DualUDP -**Medium:** Ethernet port, wired or WiFi - -**Pins used:** NA - -**Inclusion constant:** `PJON_INCLUDE_DUDP` +| Medium | Pins used | Inclusion Constant | Included by default | +|--------|-----------|--------------------|---------------------| +| Ethernet port, wired or WiFi | NA | `PJON_INCLUDE_DUDP`| yes | With the `DualUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other over an Ethernet network, wired or over WiFi or both. Like the `GlobalUDP` strategy, this strategy is not limited to the local network and can therefore reach devices farther away, to another LAN connected through VPN, or potentially across the Internet (beware of security issues). Like the `DualUDP` strategy it will reach devices on the LAN without configuration. diff --git a/src/strategies/ESPNOW/README.md b/src/strategies/ESPNOW/README.md index ccaeaa97a8..a65c417ef3 100644 --- a/src/strategies/ESPNOW/README.md +++ b/src/strategies/ESPNOW/README.md @@ -1,8 +1,8 @@ ## ESPNOW -**Medium:** ESPNOW protocol - -**Pins used:** NA - -**Inclusion constant:** `PJON_INCLUDE_EN` +| Medium | Pins used | Inclusion Constant | Included by default | +|--------|-----------|--------------------|---------------------| +| ESPNOW over WiFi | NA | `PJON_INCLUDE_EN`| no | With the `ESPNOW` PJON strategy, up to 10 ESP32 devices can use PJON to communicate with each other over the [Espressif ESPNOW protocol](https://www.espressif.com/en/products/software/esp-now/overview) (peer-to-peer 802.11). diff --git a/src/strategies/EthernetTCP/README.md b/src/strategies/EthernetTCP/README.md index 0ce839e247..f7ec3a7add 100644 --- a/src/strategies/EthernetTCP/README.md +++ b/src/strategies/EthernetTCP/README.md @@ -1,8 +1,8 @@ ## EthernetTCP -**Medium:** Ethernet port, wired or WiFi - -**Pins used:** NA - -**Inclusion constant:** `PJON_INCLUDE_ETCP` +| Medium | Pins used | Inclusion Constant | Included by default | +|--------|-----------|--------------------|---------------------| +| Ethernet port, wired or WiFi | NA | `PJON_INCLUDE_ETCP`| yes | With the `EthernetTCP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other on a LAN, WAN or across the Internet. Take a look at the [video introduction](https://www.youtube.com/watch?v=DQzcAv38yxM) for a brief showcase of its features. diff --git a/src/strategies/GlobalUDP/README.md b/src/strategies/GlobalUDP/README.md index 979ad43230..1266894e9c 100644 --- a/src/strategies/GlobalUDP/README.md +++ b/src/strategies/GlobalUDP/README.md @@ -1,8 +1,8 @@ ## GlobalUDP -**Medium:** Ethernet port, wired or WiFi - -**Pins used:** NA - -**Inclusion constant:** `PJON_INCLUDE_GUDP` +| Medium | Pins used | Inclusion Constant | Included by default | +|--------|-----------|--------------------|---------------------| +| Ethernet port, wired or WiFi | NA | `PJON_INCLUDE_GUDP`| yes | With the `GlobalUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other over an Ethernet network, wired or over WiFi or both. This strategy demands a little more configuration than the `LocalUDP` strategy diff --git a/src/strategies/LocalFile/README.md b/src/strategies/LocalFile/README.md index acbee1ba49..1b0b28eb21 100644 --- a/src/strategies/LocalFile/README.md +++ b/src/strategies/LocalFile/README.md @@ -1,8 +1,8 @@ ## LocalFile -**Medium:** File on hard disk - -**Pins used:** NA - -**Inclusion constant:** `PJON_INCLUDE_LF` +| Medium | Pins used | Inclusion Constant | Included by default | +|--------|-----------|--------------------|---------------------| +| System memory | NA | `PJON_INCLUDE_LF`| no | `LocalFile` uses a file present on the hard drive to let multiple processes communicate on the same machine. It can be used for inter-process communication and for developing, simulating and testing applications and networks on a real time operative system without having to deploy physical hardware. diff --git a/src/strategies/LocalUDP/README.md b/src/strategies/LocalUDP/README.md index 844cf1be45..a90b2cf17b 100644 --- a/src/strategies/LocalUDP/README.md +++ b/src/strategies/LocalUDP/README.md @@ -1,8 +1,8 @@ ## LocalUDP -**Medium:** Ethernet port, wired or WiFi - -**Pins used:** NA - -**Inclusion constant:** `PJON_INCLUDE_LUDP` +| Medium | Pins used | Inclusion Constant | Included by default | +|--------|-----------|--------------------|---------------------| +| Ethernet port, wired or WiFi | NA | `PJON_INCLUDE_LUDP`| yes | With the `LocalUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other on a local subnet, wired or over WiFi or both. Take a look at the [video introduction](https://www.youtube.com/watch?v=cxEUqkK5BQg) for a brief showcase of its features. diff --git a/src/strategies/MQTTTranslate/README.md b/src/strategies/MQTTTranslate/README.md index 541abe91c2..89375230ae 100644 --- a/src/strategies/MQTTTranslate/README.md +++ b/src/strategies/MQTTTranslate/README.md @@ -1,8 +1,8 @@ ## MQTTTranslate -**Medium:** MQTT protocol | -**Pins used:** NA | -**Inclusion constant:** `PJON_INCLUDE_MQTT` +| Medium | Pins used | Inclusion Constant | Included by default | +|--------|-----------|--------------------|---------------------| +| MQTT protocol | NA | `PJON_INCLUDE_MQTT`| no | MQTTTranslate uses the [ReconnectingMqttClient](https://github.com/fredilarsen/ReconnectingMqttClient) library (minimum version required v1.1.1) to deliver PJON packets over TCP on local network (LAN) as a MQTT protocol client. It may be useful to connect PJON networks and more standard applications to each other using the MQTT protocol. This strategy works in one of four modes. The first two modes enable to implement a PJON bus via MQTT, the first mode is "closed" and the second is "open" to use by non-PJON programs. The last two modes are for behaving like MQTT devices normally do. diff --git a/src/strategies/OverSampling/README.md b/src/strategies/OverSampling/README.md index df9acfec1f..a5d9e6732d 100644 --- a/src/strategies/OverSampling/README.md +++ b/src/strategies/OverSampling/README.md @@ -1,8 +1,7 @@ ## OverSampling - -**Medium:** ASK/FSK radio modules - -**Pins used:** 1 or 2 - -**Inclusion constant:** `PJON_INCLUDE_OS` +| Medium | Pins used | Inclusion Constant | Included by default | +|--------|-----------|--------------------|---------------------| +| ASK/FSK radio modules | 1 or 2 | `PJON_INCLUDE_OS`| yes | `OverSampling` is a software implementation of [PJDLR (Padded Jittering Data Link over Radio)](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md). It supports simplex and half-duplex asynchronous serial communication and implements a carrier-sense, non-persistent random multiple access method (non-persistent CSMA). This implementation can run on limited microcontrollers with low clock accuracy, supports communication for many devices connected to the same medium and stable operation in spite of interference. Its procedure is a more efficient alternative to the LoRa Open Standard (that specifies a variation of Slotted ALOHA) and it is designed to obtain long range and high reliability using FSK, ASK or OOK modulation radio transceivers. Take a look at the [video introduction](https://www.youtube.com/watch?v=G1ckfsMzPns) for a brief showcase of its features. diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index b5d57df9d0..efaafa924c 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -1,8 +1,8 @@ ## SoftwareBitBang -**Medium:** Wire - -**Pins used:** 1 or 2 - -**Inclusion constant:** `PJON_INCLUDE_SWBB` +| Medium | Pins used | Inclusion Constant | Included by default | +|--------|-----------|--------------------|---------------------| +| Wire | 1 or 2 | `PJON_INCLUDE_SWBB`| yes | `SoftwareBitBang` is a software implementation of [PJDL (Padded Jittering Data Link)](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md). It supports simplex and half-duplex asynchronous serial communication for up to 254 devices over a single wire. The maximum length of the bus can reach between 800 and 2000 meters depending on the mode used. It is a valid alternative to 1-Wire because of its flexibility and reliability. Fault tolerance schemes can be easily implemented because communication pins can be configured at runtime. Take a look at the [video introduction](https://www.youtube.com/watch?v=GWlhKD5lz5w) for a brief showcase of its features. ```cpp diff --git a/src/strategies/ThroughLoRa/README.md b/src/strategies/ThroughLoRa/README.md index dda75b134d..fd26160f6a 100644 --- a/src/strategies/ThroughLoRa/README.md +++ b/src/strategies/ThroughLoRa/README.md @@ -1,8 +1,8 @@ ## ThroughLoRa -**Medium:** LoRa radio modules - -**Pins used:** 6 - -**Inclusion constant:** `PJON_INCLUDE_TL` +| Medium | Pins used | Inclusion Constant | Included by default | +|--------|-----------|--------------------|---------------------| +| LoRa radio | 6 | `PJON_INCLUDE_TL`| no | With `ThroughLora` strategy, PJON can run through a software or hardware SPI in order to communicate with supported LoRa modules. See [Supported Shields/Modules](https://github.com/gioblu/PJON/tree/master/src/strategies/ThroughLoRa#supported-shieldsmodules). From f9de5f0dbe9361ca615e4d68478cdbef8a5bb365 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 May 2020 14:47:16 +0200 Subject: [PATCH 059/323] Strategies README removed pins needed column from table --- src/strategies/README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/strategies/README.md b/src/strategies/README.md index 8d521b5910..8a738dd3cc 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -2,21 +2,21 @@ ### What is a Strategy? A strategy is an abstraction layer used to physically transmit data. Thanks to the strategies PJON can operate transparently on a wide range of media and protocols. Take a look at the [strategies video introduction](https://www.youtube.com/watch?v=yPu45xoAHGg) for a brief showcase of their features. -| Strategy | Physical layer | Protocol | Pins needed | -| ------------- | -------------- | -------- | ------------- | -| [SoftwareBitBang](SoftwareBitBang) | Electrical impulses over wire | [PJDL](SoftwareBitBang/specification/PJDL-specification-v4.1.md) | 1 or 2 | -| [OverSampling](OverSampling) | Electrical/radio impulses over wire/air | [PJDLR](OverSampling/specification/PJDLR-specification-v3.0.md) | 1 or 2 | -| [AnalogSampling](AnalogSampling) | Light pulses over air or optic fiber | [PJDLS](AnalogSampling/specification/PJDLS-specification-v2.0.md) | 1 or 2 | -| [ThroughSerial](ThroughSerial) | Electrical/radio impulses over wire/air | [TSDL](ThroughSerial/specification/TSDL-specification-v3.0.md) | 1 or 2 | -| [ThroughLoRa](ThroughLoRa) | Radio impulses over air | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | 3 or 4 | -| [EthernetTCP](EthernetTCP) | Electrical/radio impulses over wire/air | [TCP](https://tools.ietf.org/html/rfc793) | Ethernet or WiFi | -| [LocalUDP](LocalUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | -| [GlobalUDP](GlobalUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | -| [DualUDP](DualUDP) | Electrical/radio impulses over wire/air | [UDP](https://tools.ietf.org/html/rfc768) | Ethernet or WiFi | -| [MQTTTranslate](MQTTTranslate) | Electrical/radio impulses over wire/air | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | Ethernet or WiFi | -| [ESPNOW](ESPNOW) | Radio impulses over air | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | WiFi link | -| [LocalFile](LocalFile) | Shared file system in memory | None | None | -| [Any](Any) | Virtual inheritance, any of the above | Any of the above | Any of the above | +| Strategy | Physical layer | Protocol | +| ------------- | -------------- | -------- | +| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | +| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | +| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | +| [ThroughSerial](/src/strategies/ThroughSerial) | Radio | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | +| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | +| [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | +| [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | +| [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | +| [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | +| [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | +| [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | +| [LocalFile](/src/strategies/LocalFile) | System memory | None | +| [Any](/src/strategies/Any) | Virtual inheritance, any of the above | Any | A `Strategy` is a class containing a set of methods used to physically send and receive data along with the required getters to handle retransmission and collision: From 384256013ef57d2c0a2ef009af63cb50aacc31ea Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 May 2020 18:12:22 +0200 Subject: [PATCH 060/323] If MAC matches packet is not dropped when device/bus id do not match --- src/PJON.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 3188bad4f1..368d26c1e7 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -267,7 +267,7 @@ class PJON { uint16_t length = PJON_PACKET_MAX_LENGTH; uint16_t batch_length = 0; uint8_t overhead = 0; - bool extended_length = false; + bool extended_length = false, mac = false, drop = false; for(uint16_t i = 0; i < length; i++) { if(!batch_length) { batch_length = strategy.receive_frame(data + i, length - i); @@ -278,9 +278,10 @@ class PJON { if(i == 0) if((data[i] != tx.id) && (data[i] != PJON_BROADCAST) && !_router) - return PJON_BUSY; + drop = true; if(i == 1) { + mac = (data[1] & PJON_MAC_BIT); if( ( !_router && @@ -294,10 +295,10 @@ class PJON { ) || ( !PJON_INCLUDE_PORT && (data[1] & PJON_PORT_BIT) ) || ( - (!PJON_INCLUDE_MAC && (data[1] & PJON_MAC_BIT)) || - ((data[1] & PJON_MAC_BIT) && !(data[1] & PJON_CRC_BIT)) + (!PJON_INCLUDE_MAC && mac) || (mac && !(data[1] & PJON_CRC_BIT)) ) ) return PJON_BUSY; + if(drop && !mac) return PJON_BUSY; extended_length = data[i] & PJON_EXT_LEN_BIT; overhead = packet_overhead(data[i]); } @@ -321,7 +322,7 @@ class PJON { } if( - ((data[1] & PJON_MODE_BIT) && !_router) && + ((data[1] & PJON_MODE_BIT) && !_router && !mac) && (i > (uint8_t)(3 + extended_length)) && (i < (uint8_t)(8 + extended_length)) ) { From 9056b017c6b45d2bc46217132ec576d86a661c5f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 May 2020 18:14:00 +0200 Subject: [PATCH 061/323] Packet is not discarded if receiver's MAC is empty --- src/PJON.h | 9 +++++++-- src/PJONDefines.h | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 368d26c1e7..42179e3794 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -348,9 +348,14 @@ class PJON { return PJON_NAK; #if(PJON_INCLUDE_MAC) - if((data[1] & PJON_MAC_BIT) && (length > 15) && !_router) + if(mac && (length > 15) && !_router) if(!PJONTools::id_equality(data + (overhead - 16), tx.mac, 6)) - return PJON_BUSY; + if(! + PJONTools::id_equality( + data + (overhead - 16), + PJONTools::no_mac(), 6 + ) + ) return PJON_BUSY; #endif if(data[1] & PJON_ACK_REQ_BIT && data[0] != PJON_BROADCAST) diff --git a/src/PJONDefines.h b/src/PJONDefines.h index c00b58c07f..311d7fcda0 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -242,6 +242,13 @@ struct PJONTools { return lh; }; + /* Unused MAC address value */ + + static const uint8_t* no_mac() { + static const uint8_t lh[6] = {0, 0, 0, 0, 0, 0}; + return lh; + }; + /* Calculates the packet's overhead using the header: */ static uint8_t packet_overhead(uint8_t header) { From 5d198423231ec73d513c724ec48698ea8c9b63b9 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 May 2020 18:31:54 +0200 Subject: [PATCH 062/323] PJON v4.0 specification MAC address section update --- specification/PJON-protocol-specification-v4.0.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index 1f28047fe6..08dbee323d 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -320,7 +320,7 @@ if the header's `PORT` bit is high a 16 bits port id is added to the packet. Tha ``` #### Hardware identification -If the header's `MAC` bit is high both recipient's and sender's 48 bits MAC addresses are included in the packet. Device id and bus id filtering does not vary. When MAC addresses are included and device ids are not set all devices must use device id 255 and transmit packets to device id 255 (or use broadcast if the acknowledgement is not required). The graph below shows a broadcast packet transmission where MAC address `111111` sends to MAC address `222222` the payload 64. +If the header's `MAC` bit is high both recipient's and sender's 48 bits MAC addresses are included in the packet. The recipient's MAC address must match the MAC address of the receiver otherwise the packet is discarded. When the hardware identification is present the packet is received even if the bus id and or the device id don't match. If a packet contains an empty recipient's MAC or `0.0.0.0.0.0` it is not discarded even if the MAC address do not match. The graph below shows a broadcast packet transmission where MAC address `1.1.1.1.1.1` sends to MAC address `2.2.2.2.2.2` the payload 64. ```cpp ________________________________________________ |ID| HEADER |LENGTH|CRC8|RX MAC|TX MAC|DATA|CRC32| @@ -330,3 +330,14 @@ If the header's `MAC` bit is high both recipient's and sender's 48 bits MAC addr |8 | 8 | 8 | 8 | 48 | 48 | 8 | 32 | 168 bits |__|________|______|____|______|______|____|_____| ``` +When a device knows its own MAC address but doesn't know its own device id it must use device id 255. To reach another device in the same configuration, it can transmit packets to device id 255 and include the MAC addresses setting the `MAC` bit high. In this case even if many devices could be present using device id 255, only the one with the matching MAC address receives the packet. If the `ACK` bit is high the receiver can send an acknowledge, although also a broadcast can be used if the acknowledgement is not required. + +```cpp + _________________________________________________ ___ +|ID | HEADER |LENGTH|CRC8|RX MAC|TX MAC|DATA|CRC32||ACK| +|---|--------|------|----|------|------|----|-----||---| +|255|00001100| 12 | |222222|111111| 64 | || 6 | +|___|________|______|____|______|______|____|_____||___| +| 8 | 8 | 8 | 8 | 48 | 48 | 8 | 32 | 168 bits +|___|________|______|____|______|______|____|_____| +``` From 58aa0ff2ee02a2a2fe0bdc6931b9b3c258cc0114 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 May 2020 19:29:52 +0200 Subject: [PATCH 063/323] configuration and strategies README update --- documentation/configuration.md | 55 ++++++++++++++++------------------ src/strategies/README.md | 43 +++++++++++++------------- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index 3fbb5bae01..5d56bdb696 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -34,38 +34,35 @@ In the example above the PJON object is instantiated passing the [SoftwareBitBan PJON tcpBus; ``` -| Strategy | Physical layer | Protocol | -| ------------- | -------------- | -------- | -| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | -| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | -| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | -| [ThroughSerial](/src/strategies/ThroughSerial) | Radio | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | -| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | -| [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | -| [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | -| [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | -| [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | -| [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | -| [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | -| [LocalFile](/src/strategies/LocalFile) | System memory | None | -| [Any](/src/strategies/Any) | Virtual inheritance, any of the above | Any | +| Strategy | Physical layer | Protocol | Inclusion constant | Included by default | +| ------------- | -------------- | -------- | ------------------ | ------------------- | +| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | `PJON_INCLUDE_AS` | yes | +| [Any](/src/strategies/Any) | Virtual inheritance | Any | `PJON_INCLUDE_ANY` | yes | +| [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `PJON_INCLUDE_DUDP` | yes | +| [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | `PJON_INCLUDE_EN` | no | +| [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | `PJON_INCLUDE_ETCP` | yes | +| [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `PJON_INCLUDE_GUDP` | yes | +| [LocalFile](/src/strategies/LocalFile) | System memory | None | `PJON_INCLUDE_LF` | no | +| [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `PJON_INCLUDE_LUDP` | yes | +| [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | `PJON_INCLUDE_MQTT` | no | +| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | `PJON_INCLUDE_OS` | yes | +| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | `PJON_INCLUDE_SWBB` | yes | +| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | `PJON_INCLUDE_TL` | no | +| [ThroughSerial](/src/strategies/ThroughSerial) | Radio | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | `PJON_INCLUDE_TS` | yes | By default all strategies are included except `MQTTTranslate`, `LocalFile`, `ThroughLoRa` and `ESPNOW`. To reduce memory footprint add for example `#define PJON_INCLUDE_SWBB` before including the library to select only the `SoftwareBitBang` strategy. More than one strategy related constants can be defined in the same program if that is required. -Supported definitions: -- `PJON_INCLUDE_SWBB` includes `SoftwareBitBang` -- `PJON_INCLUDE_AS` includes `AnalogSampling` -- `PJON_INCLUDE_ETCP` includes `EthernetTCP` -- `PJON_INCLUDE_LUDP` includes `LocalUDP` -- `PJON_INCLUDE_GUDP` includes `GlobalUDP` -- `PJON_INCLUDE_OS` includes `OverSampling` -- `PJON_INCLUDE_TS` includes `ThroughSerial` -- `PJON_INCLUDE_TL` includes `ThroughLoRa` -- `PJON_INCLUDE_MQTT` includes `MQTTTranslate` -- `PJON_INCLUDE_EN` includes `ESPNOW` -- `PJON_INCLUDE_ANY` includes `Any` -- `PJON_INCLUDE_LF` includes `LocalFile` -- `PJON_INCLUDE_NONE` does not include any strategy +When a strategy is included by default the usage is really simple: +```cpp +#include // Include the library +PJON bus; // Instantiation +``` +If the strategy you want to use is not included by default, like ESPNOW, you can force its inclusion using its constant: +```cpp +#define PJON_INCLUDE_EN // Force the inclusion of ESPNOW strategy +#include // Include the library +PJON bus; // Instantiation +``` Before using `ThroughLoRa` be sure to have [arduino-LoRa](https://github.com/sandeepmistry/arduino-LoRa) library available and to have defined the `PJON_INCLUDE_TL` constant before including `PJON.h`. diff --git a/src/strategies/README.md b/src/strategies/README.md index 8a738dd3cc..7b13e6fa08 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -1,23 +1,26 @@ -### What is a Strategy? +### What is a Strategy A strategy is an abstraction layer used to physically transmit data. Thanks to the strategies PJON can operate transparently on a wide range of media and protocols. Take a look at the [strategies video introduction](https://www.youtube.com/watch?v=yPu45xoAHGg) for a brief showcase of their features. -| Strategy | Physical layer | Protocol | -| ------------- | -------------- | -------- | -| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | -| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | -| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | -| [ThroughSerial](/src/strategies/ThroughSerial) | Radio | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | -| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | -| [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | -| [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | -| [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | -| [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | -| [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | -| [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | -| [LocalFile](/src/strategies/LocalFile) | System memory | None | -| [Any](/src/strategies/Any) | Virtual inheritance, any of the above | Any | - +The table below lists the available strategies: + +| Strategy | Physical layer | Protocol | Inclusion constant | Included by default | +| ------------- | -------------- | -------- | ------------------ | ------------------- | +| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | `PJON_INCLUDE_AS` | yes | +| [Any](/src/strategies/Any) | Virtual inheritance | Any | `PJON_INCLUDE_ANY` | yes | +| [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `PJON_INCLUDE_DUDP` | yes | +| [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | `PJON_INCLUDE_EN` | no | +| [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | `PJON_INCLUDE_ETCP` | yes | +| [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `PJON_INCLUDE_GUDP` | yes | +| [LocalFile](/src/strategies/LocalFile) | System memory | None | `PJON_INCLUDE_LF` | no | +| [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `PJON_INCLUDE_LUDP` | yes | +| [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | `PJON_INCLUDE_MQTT` | no | +| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | `PJON_INCLUDE_OS` | yes | +| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | `PJON_INCLUDE_SWBB` | yes | +| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | `PJON_INCLUDE_TL` | no | +| [ThroughSerial](/src/strategies/ThroughSerial) | Radio | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | `PJON_INCLUDE_TS` | yes | + +### How the strategy is implemented A `Strategy` is a class containing a set of methods used to physically send and receive data along with the required getters to handle retransmission and collision: ```cpp @@ -73,9 +76,9 @@ void send_response(uint8_t response) { ``` Above it is demonstrated how simply other communication protocols can be used to define a new custom strategy. -### How to define a new strategy -To define the strategy it is required to create a new folder named for example `YourStrategyName` in the `strategies` -directory and write the necessary file `YourStrategyName.h`: +### How to implement a custom strategy +To define a new custom strategy you need to create a new folder named for example `YourStrategyName` in the `src/strategies` +directory and create the necessary file `YourStrategyName.h`: ```cpp class YourStrategyName { From 4b203633fa0b384c514c47a3ba004ca2dbdc0719 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 May 2020 20:34:42 +0200 Subject: [PATCH 064/323] fix to various minor inconsistencies --- documentation/configuration.md | 2 ++ documentation/data-reception.md | 2 +- .../Local/ThroughSerial/BlinkTest/Receiver/Receiver.cpp | 8 +------- .../ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp | 8 +------- .../ThroughSerial/BlinkWithAck/Receiver/Receiver.cpp | 6 +----- .../BlinkWithAck/Transmitter/Transmitter.cpp | 6 +----- .../ThroughSerial/BlinkWithResponse/Receiver/Receiver.cpp | 8 +------- .../BlinkWithResponse/Transmitter/Transmitter.cpp | 8 +------- .../Local/ThroughSerial/BlinkTestReceiver/Receiver.cpp | 8 ++++---- .../ThroughSerial/BlinkTestTransmitter/Transmitter.cpp | 8 ++++---- src/strategies/README.md | 2 +- src/strategies/ThroughSerial/README.md | 2 -- 12 files changed, 18 insertions(+), 50 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index 5d56bdb696..d917b5dcd3 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -34,6 +34,8 @@ In the example above the PJON object is instantiated passing the [SoftwareBitBan PJON tcpBus; ``` +The table below lists the strategies available: + | Strategy | Physical layer | Protocol | Inclusion constant | Included by default | | ------------- | -------------- | -------- | ------------------ | ------------------- | | [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | `PJON_INCLUDE_AS` | yes | diff --git a/documentation/data-reception.md b/documentation/data-reception.md index 452f81690e..a053132c12 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -52,7 +52,7 @@ struct PJON_Endpoint { ``` `PJON_Endpoint` contains `mac` if [`PJON_INCLUDE_MAC`](/documentation/configuration.md#hardware-identification) is defined. The conditional inclusion is present to reduce the footprint of programs where the MAC address is not used. -The code below is part of the Arduino compatible [PortsUseExample](/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino). When the `receiver_function` is called meta-data present in the `info` parameter is transmitted over serial: +The code below is part of the Arduino compatible [PortsUseExample](/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino). When the `receiver_function` is called meta-data present in the `info` parameter is printed in the serial monitor: ```cpp void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &info) { Serial.print("Header: "); diff --git a/examples/LINUX/Local/ThroughSerial/BlinkTest/Receiver/Receiver.cpp b/examples/LINUX/Local/ThroughSerial/BlinkTest/Receiver/Receiver.cpp index 135e4a573c..b64d914092 100644 --- a/examples/LINUX/Local/ThroughSerial/BlinkTest/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/ThroughSerial/BlinkTest/Receiver/Receiver.cpp @@ -6,13 +6,7 @@ #include #include -#define TS_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ - -#define PJON_INCLUDE_TS true // Include only ThroughSerial +#define PJON_INCLUDE_TS // Include only ThroughSerial #include void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/LINUX/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp b/examples/LINUX/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp index d721b9ac11..4f51ec632b 100644 --- a/examples/LINUX/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp @@ -6,13 +6,7 @@ #include #include -#define TS_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ - -#define PJON_INCLUDE_TS true // Include only ThroughSerial +#define PJON_INCLUDE_TS // Include only ThroughSerial #include int main() { diff --git a/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Receiver/Receiver.cpp b/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Receiver/Receiver.cpp index 4fc98cdc22..eb651cdd5e 100644 --- a/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Receiver/Receiver.cpp @@ -7,12 +7,8 @@ #include #define TS_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ -#define PJON_INCLUDE_TS true // Include only ThroughSerial +#define PJON_INCLUDE_TS // Include only ThroughSerial #include void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Transmitter/Transmitter.cpp b/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Transmitter/Transmitter.cpp index 390da1c950..260eeff35e 100644 --- a/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Transmitter/Transmitter.cpp @@ -7,12 +7,8 @@ #include #define TS_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ -#define PJON_INCLUDE_TS true // Include only ThroughSerial +#define PJON_INCLUDE_TS // Include only ThroughSerial #include #define BLINK_FREQUENCY 1000000 // 1 Blink per second diff --git a/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.cpp b/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.cpp index 098e336d85..afb6236098 100644 --- a/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.cpp @@ -6,13 +6,7 @@ #include #include -#define TS_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ - -#define PJON_INCLUDE_TS true // Include only ThroughSerial +#define PJON_INCLUDE_TS // Include only ThroughSerial #include PJON bus(44); diff --git a/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp b/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp index e487d5060b..81ab47e1db 100644 --- a/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp @@ -6,13 +6,7 @@ #include #include -#define TS_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ - -#define PJON_INCLUDE_TS true // Include only ThroughSerial +#define PJON_INCLUDE_TS // Include only ThroughSerial #include void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/Receiver.cpp b/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/Receiver.cpp index 22b12bba4a..498ddad671 100644 --- a/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/Receiver.cpp +++ b/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/Receiver.cpp @@ -14,10 +14,10 @@ #endif #define TS_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ +/* Maximum accepted duration between transmission and acknowledgement. + May be necessary to set a higher value if devices are separated by a long + physical distance and or if long packets are transmitted. */ + #define PJON_INCLUDE_TS true // Include only ThroughSerial #include diff --git a/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/Transmitter.cpp b/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/Transmitter.cpp index 622b0b5bb2..71b18d0655 100644 --- a/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/Transmitter.cpp +++ b/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/Transmitter.cpp @@ -14,10 +14,10 @@ #endif #define TS_RESPONSE_TIME_OUT 35000 -/* Maximum accepted timeframe between transmission and synchronous - acknowledgement. This timeframe is affected by latency and CRC computation. - Could be necessary to higher this value if devices are separated by long - physical distance and or if transmitting long packets. */ +/* Maximum accepted duration between transmission and acknowledgement. + May be necessary to set a higher value if devices are separated by a long + physical distance and or if long packets are transmitted. */ + #define PJON_INCLUDE_TS true // Include only ThroughSerial #include diff --git a/src/strategies/README.md b/src/strategies/README.md index 7b13e6fa08..6a4f39fbe9 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -2,7 +2,7 @@ ### What is a Strategy A strategy is an abstraction layer used to physically transmit data. Thanks to the strategies PJON can operate transparently on a wide range of media and protocols. Take a look at the [strategies video introduction](https://www.youtube.com/watch?v=yPu45xoAHGg) for a brief showcase of their features. -The table below lists the available strategies: +The table below lists the strategies available: | Strategy | Physical layer | Protocol | Inclusion constant | Included by default | | ------------- | -------------- | -------- | ------------------ | ------------------- | diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index b6e6aa87e4..91190c5380 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -15,8 +15,6 @@ Serial communication is fast and reliable but it is often useless without all th `ThroughSerial` performs well if used with ESP8266 and ESP32 where blocking procedures can strongly degrade functionality. The reception phase is entirely non-blocking. Sending and acknowledgement however are still blocking. -There is a default reception interval of 100 microseconds used to allow data to accumulate in the hardware UART buffer. This value is configurable using `bus.strategy.set_read_interval(100)` passing an arbitrary interval in microseconds. The read interval may require adjustment depending on UART RX buffer size and baud rate. - ### Configuration Before including `PJON.h` it is possible to configure `ThroughSerial` using predefined constants: From 17a6144ff343c7532aab99873864b005fab47b4a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 24 May 2020 02:28:45 +0200 Subject: [PATCH 065/323] When MAC bit is high sender's MAC address is included by default --- src/PJON.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PJON.h b/src/PJON.h index 42179e3794..ab6c209e78 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -169,6 +169,10 @@ class PJON { (info.header & PJON_PORT_BIT) ) info.port = port; #endif + #if(PJON_INCLUDE_MAC) + if(info.header & PJON_MAC_BIT) + PJONTools::copy_id(info.tx.mac, tx.mac, 6); + #endif uint16_t l = PJONTools::compose_packet( info, destination, source, length ); From b013a083f570cd4a4b4dfab28d0cc0475dcda742 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 24 May 2020 02:29:19 +0200 Subject: [PATCH 066/323] PJON specification acknowledge remark added --- specification/PJON-protocol-specification-v4.0.md | 1 + 1 file changed, 1 insertion(+) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index 08dbee323d..5e98f9b7ff 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -193,6 +193,7 @@ Medium access Transmission Response BITS: | 8 | 8 | 8 | 8 | 8 | 8 | |____|__________|________|______|________|______| ``` +The acknowledgment gives reception certainty only when a packet transmission occurs directly without the intermediation of routers or switches. When a packet needs to traverse a network the acknowledgment is generally sent by the nearest router or switch, although does not necessarily mean that the packet is received by its recipient. #### Local mode Depending on header's `MODE` bit packets can contain basic or extended support to identification. Local mode required by header's `MODE` bit low supports connectivity for up to 254 devices. In the graph below is represented the simplest local mode packet format sending `@` (decimal 64) to device `12`: From e857bea7214bb8d1a5c57643794c0e8891c538ff Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 May 2020 16:24:21 +0200 Subject: [PATCH 067/323] documentation/configuration.md strategy inclusion fix --- documentation/configuration.md | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index d917b5dcd3..7964b54362 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -52,26 +52,23 @@ The table below lists the strategies available: | [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | `PJON_INCLUDE_TL` | no | | [ThroughSerial](/src/strategies/ThroughSerial) | Radio | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | `PJON_INCLUDE_TS` | yes | -By default all strategies are included except `MQTTTranslate`, `LocalFile`, `ThroughLoRa` and `ESPNOW`. To reduce memory footprint add for example `#define PJON_INCLUDE_SWBB` before including the library to select only the `SoftwareBitBang` strategy. More than one strategy related constants can be defined in the same program if that is required. +By default all strategies are included except `MQTTTranslate`, `LocalFile`, `ThroughLoRa` and `ESPNOW`. Before using `ThroughLoRa` be sure to have [arduino-LoRa](https://github.com/sandeepmistry/arduino-LoRa) library available and to have defined the `PJON_INCLUDE_TL` constant before including `PJON.h`. Before using `ESPNOW` be sure to have installed the required tools as described [here](/src/strategies/ESPNOW/README.md) and to have defined the `PJON_INCLUDE_EN` constant before including `PJON.h`. Before using `MQTTTranslate` be sure to have the [ReconnectingMqttClient](https://github.com/fredilarsen/ReconnectingMqttClient) library available and to have defined the `PJON_INCLUDE_MQTT` constant before including `PJON.h`. -When a strategy is included by default the usage is really simple: +To reduce memory footprint add for example `#define PJON_INCLUDE_SWBB` before including the library to select only the `SoftwareBitBang` strategy. ```cpp +#define PJON_INCLUDE_SWBB // Include only SoftwareBitBang strategy #include // Include the library PJON bus; // Instantiation ``` +More than one strategy related constants can be defined in the same program if that is required. + If the strategy you want to use is not included by default, like ESPNOW, you can force its inclusion using its constant: ```cpp -#define PJON_INCLUDE_EN // Force the inclusion of ESPNOW strategy -#include // Include the library -PJON bus; // Instantiation +#define PJON_INCLUDE_EN // Force the inclusion of ESPNOW strategy +#include // Include the library +PJON bus; // Instantiation ``` -Before using `ThroughLoRa` be sure to have [arduino-LoRa](https://github.com/sandeepmistry/arduino-LoRa) library available and to have defined the `PJON_INCLUDE_TL` constant before including `PJON.h`. - -Before using `ESPNOW` be sure to have installed the required tools as described [here](/src/strategies/ESPNOW/README.md) and to have defined the `PJON_INCLUDE_EN` constant before including `PJON.h`. - -Before using `MQTTTranslate` be sure to have the [ReconnectingMqttClient](https://github.com/fredilarsen/ReconnectingMqttClient) library available and to have defined the `PJON_INCLUDE_MQTT` constant before including `PJON.h`. - ### Network mode The network mode can be changed with `set_shared_network` during runtime, for example moving from [local](/specification/PJON-protocol-specification-v4.0.md#local-mode) to [shared](https://github.com/gioblu/PJON/blob/master/specification/PJON-protocol-specification-v4.0.md#shared-mode) mode: ```cpp From 8a1603eaf07f2c3bee0fc754be3d5f85f572d7bb Mon Sep 17 00:00:00 2001 From: fredilarsen Date: Mon, 1 Jun 2020 21:34:58 +0200 Subject: [PATCH 068/323] Routing related updates and improvements - Updated to match new use of PJON_Endpoint - Removed support for segmented buses (virtual bus support made it redundant) - Removed the PJONBus class - Added get_receive_time() to all strategies, with overridable default values - Added specialized routing classes for 2 and 3 buses with easier declaration - Moved all routing related examples to examples/routing --- .../Switch/DynamicSwitch/DynamicSwitch.ino | 33 ----- .../Switch/SimpleSwitch/SimpleSwitch.ino | 28 ---- .../SoftwareBitBang/Switch/Switch/Switch.ino | 29 ----- .../SegmentedSwitch/Device1/Device1.ino | 41 ------ .../SegmentedSwitch/Device2/Device2.ino | 43 ------ .../SegmentedSwitch/Switch/Switch.ino | 30 ----- .../BlinkingRGBSwitch/BlinkingRGBSwitch.fzz | Bin .../BlinkingRGBSwitch/BlinkingRGBSwitch.ino | 17 +-- .../BlinkingRGBSwitch_bb.png | Bin .../ARDUINO/Local}/Tunneler/README.md | 10 +- .../Local}/Tunneler/SwitchA/SwitchA.ino | 18 +-- .../Local}/Tunneler/SwitchB/SwitchB.ino | 18 +-- .../VirtualBusRouter}/Device1/Device1.ino | 0 .../VirtualBusRouter}/Device2/Device2.ino | 0 .../VirtualBusRouter/VirtualBusRouter.ino | 39 ++++++ .../VirtualBusRouter2/VirtualBusRouter2.ino | 25 ++++ .../LocalDevice/LocalDevice.ino | 9 +- .../NATSwitch/NATSwitch.ino | 18 +-- .../NetworkDevice/NetworkDevice.ino | 4 +- .../Router/DynamicRouter/DynamicRouter.ino | 14 +- .../ARDUINO/Network}/Router/Router/Router.ino | 17 ++- .../Switch/BlinkingSwitch/BlinkingSwitch.ino | 14 +- .../Network}/Switch/Device1/Device1.ino | 0 .../Network}/Switch/Device2/Device2.ino | 0 .../ARDUINO/Network}/Switch/Switch/Switch.ino | 14 +- src/PJON.h | 43 ++++-- src/PJONDynamicRouter.h | 50 ++++++- src/PJONInteractiveRouter.h | 55 +++++++- src/PJONRouter.h | 50 ++++++- src/PJONSimpleSwitch.h | 122 +++++++----------- src/PJONSwitch.h | 79 ++++++++---- src/PJONVirtualBusRouter.h | 77 ++++++++--- .../AnalogSampling/AnalogSampling.h | 12 ++ src/strategies/Any/Any.h | 5 + src/strategies/Any/StrategyLink.h | 5 + src/strategies/Any/StrategyLinkBase.h | 3 + src/strategies/DualUDP/DualUDP.h | 9 ++ src/strategies/ESPNOW/ESPNOW.h | 10 ++ src/strategies/EthernetTCP/EthernetTCP.h | 12 ++ src/strategies/GlobalUDP/GlobalUDP.h | 10 ++ src/strategies/LocalFile/LocalFile.h | 9 ++ src/strategies/LocalUDP/LocalUDP.h | 10 ++ src/strategies/MQTTTranslate/MQTTTranslate.h | 10 ++ src/strategies/OverSampling/OverSampling.h | 12 ++ .../SoftwareBitBang/SoftwareBitBang.h | 12 ++ src/strategies/ThroughLoRa/ThroughLora.h | 11 ++ src/strategies/ThroughSerial/ThroughSerial.h | 12 ++ 47 files changed, 602 insertions(+), 437 deletions(-) delete mode 100644 examples/ARDUINO/Local/SoftwareBitBang/Switch/DynamicSwitch/DynamicSwitch.ino delete mode 100644 examples/ARDUINO/Local/SoftwareBitBang/Switch/SimpleSwitch/SimpleSwitch.ino delete mode 100644 examples/ARDUINO/Local/SoftwareBitBang/Switch/Switch/Switch.ino delete mode 100644 examples/ARDUINO/Network/SoftwareBitBang/SegmentedSwitch/Device1/Device1.ino delete mode 100644 examples/ARDUINO/Network/SoftwareBitBang/SegmentedSwitch/Device2/Device2.ino delete mode 100644 examples/ARDUINO/Network/SoftwareBitBang/SegmentedSwitch/Switch/Switch.ino rename examples/{ARDUINO/Local/SoftwareBitBang => routing/ARDUINO/Local}/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.fzz (100%) rename examples/{ARDUINO/Local/SoftwareBitBang => routing/ARDUINO/Local}/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino (85%) rename examples/{ARDUINO/Local/SoftwareBitBang => routing/ARDUINO/Local}/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch_bb.png (100%) rename examples/{ARDUINO/Local/SoftwareBitBang => routing/ARDUINO/Local}/Tunneler/README.md (72%) rename examples/{ARDUINO/Local/SoftwareBitBang => routing/ARDUINO/Local}/Tunneler/SwitchA/SwitchA.ino (57%) rename examples/{ARDUINO/Local/SoftwareBitBang => routing/ARDUINO/Local}/Tunneler/SwitchB/SwitchB.ino (57%) rename examples/{ARDUINO/Local/SoftwareBitBang/Switch => routing/ARDUINO/Local/VirtualBusRouter}/Device1/Device1.ino (100%) rename examples/{ARDUINO/Local/SoftwareBitBang/Switch => routing/ARDUINO/Local/VirtualBusRouter}/Device2/Device2.ino (100%) create mode 100644 examples/routing/ARDUINO/Local/VirtualBusRouter/VirtualBusRouter/VirtualBusRouter.ino create mode 100644 examples/routing/ARDUINO/Local/VirtualBusRouter/VirtualBusRouter2/VirtualBusRouter2.ino rename examples/{ARDUINO/Network/SoftwareBitBang => routing/ARDUINO/Network}/LocalBusViaNATSwitch/LocalDevice/LocalDevice.ino (92%) rename examples/{ARDUINO/Network/SoftwareBitBang => routing/ARDUINO/Network}/LocalBusViaNATSwitch/NATSwitch/NATSwitch.ino (72%) rename examples/{ARDUINO/Network/SoftwareBitBang => routing/ARDUINO/Network}/LocalBusViaNATSwitch/NetworkDevice/NetworkDevice.ino (97%) rename examples/{ARDUINO/Network/SoftwareBitBang => routing/ARDUINO/Network}/Router/DynamicRouter/DynamicRouter.ino (78%) rename examples/{ARDUINO/Network/SoftwareBitBang => routing/ARDUINO/Network}/Router/Router/Router.ino (75%) rename examples/{ARDUINO/Network/SoftwareBitBang => routing/ARDUINO/Network}/Switch/BlinkingSwitch/BlinkingSwitch.ino (70%) rename examples/{ARDUINO/Network/SoftwareBitBang => routing/ARDUINO/Network}/Switch/Device1/Device1.ino (100%) rename examples/{ARDUINO/Network/SoftwareBitBang => routing/ARDUINO/Network}/Switch/Device2/Device2.ino (100%) rename examples/{ARDUINO/Network/SoftwareBitBang => routing/ARDUINO/Network}/Switch/Switch/Switch.ino (62%) diff --git a/examples/ARDUINO/Local/SoftwareBitBang/Switch/DynamicSwitch/DynamicSwitch.ino b/examples/ARDUINO/Local/SoftwareBitBang/Switch/DynamicSwitch/DynamicSwitch.ino deleted file mode 100644 index 9b2608b5e7..0000000000 --- a/examples/ARDUINO/Local/SoftwareBitBang/Switch/DynamicSwitch/DynamicSwitch.ino +++ /dev/null @@ -1,33 +0,0 @@ -#include - -/* This sketch does the same as the Switch example, routing between two local - buses to form one larger local bus. But instead of requiring the device ids - to be in a fixed range in each of the buses, this will discover which - attached bus each device is connected to, and route packets dynamically. - So devices can be placed on any of the attached buses as long as device - ids are unique, forming a "virtual bus". - - // SWITCH forwarding from bus 1 to bus 2 and vice versa - __________ ________ __________ - | | Bus 1 Pin 7 | | Pin 12 Bus 2 | | - | DEVICE 1 |_______________| SWITCH |_______________| DEVICE 2 | - |__________| |________| |__________| */ - -StrategyLink link1; -StrategyLink link2; - -PJONAny bus1(&link1); -PJONAny bus2(&link2); - -PJONVirtualBusRouter router(2, (PJONAny*[2]){&bus1, &bus2}); - -void setup() { - link1.strategy.set_pin(7); - link2.strategy.set_pin(12); - router.set_virtual_bus(0); - router.begin(); -}; - -void loop() { - router.loop(); -}; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/Switch/SimpleSwitch/SimpleSwitch.ino b/examples/ARDUINO/Local/SoftwareBitBang/Switch/SimpleSwitch/SimpleSwitch.ino deleted file mode 100644 index c6e7774b28..0000000000 --- a/examples/ARDUINO/Local/SoftwareBitBang/Switch/SimpleSwitch/SimpleSwitch.ino +++ /dev/null @@ -1,28 +0,0 @@ -#define PJON_INCLUDE_SWBB - -#include - -/* Route packets between a collection of buses with the same strategy. - SimpleSwitch operates as Switch but is limited to one strategy although - uses less memory. - - // SWITCH forwarding from bus 1 to bus 2 and vice versa - __________ ________ __________ - | | Bus 1 Pin 7 | | Pin 12 Bus 2 | | - | DEVICE 1 | ______________| SWITCH |_______________| DEVICE 2 | - |__________| Range 1-127 |________| Range 128-253 |__________| */ - -PJONBus bus1(PJON_NOT_ASSIGNED, 1000, 2, 0), // Devices with id 1-127 - bus2(PJON_NOT_ASSIGNED, 1000, 2, 1); // Devices with id 128-253 - -PJONSimpleSwitch router(2, (PJONBus*[2]){&bus1,&bus2}); - -void setup() { - bus1.strategy.set_pin(7); - bus2.strategy.set_pin(12); - router.begin(); -} - -void loop() { - router.loop(); -}; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/Switch/Switch/Switch.ino b/examples/ARDUINO/Local/SoftwareBitBang/Switch/Switch/Switch.ino deleted file mode 100644 index 40f761e0ca..0000000000 --- a/examples/ARDUINO/Local/SoftwareBitBang/Switch/Switch/Switch.ino +++ /dev/null @@ -1,29 +0,0 @@ -#include - -/* Route packets between a collection of buses with the same - or different strategies or media. All physical buses are taking part - of the same local bus, with the device id range being segmented. - - // SWITCH forwarding from bus 1 to bus 2 and vice versa - __________ ________ __________ - | | Bus 1 Pin 7 | | Pin 12 Bus 2 | | - | DEVICE 1 |_______________| SWITCH |_______________| DEVICE 2 | - |__________| Range 1-127 |________| Range 128-253 |__________| */ - -StrategyLink link1; -StrategyLink link2; - -PJONAny bus1(&link1, PJON_NOT_ASSIGNED, 1000, 2, 0); // Devices with id 1-127 -PJONAny bus2(&link2, PJON_NOT_ASSIGNED, 1000, 2, 1); // Devices with id 128-253 - -PJONSwitch router(2, (PJONAny*[2]){&bus1, &bus2}); - -void setup() { - link1.strategy.set_pin(7); - link2.strategy.set_pin(12); - router.begin(); -}; - -void loop() { - router.loop(); -}; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SegmentedSwitch/Device1/Device1.ino b/examples/ARDUINO/Network/SoftwareBitBang/SegmentedSwitch/Device1/Device1.ino deleted file mode 100644 index 89b9efd6bf..0000000000 --- a/examples/ARDUINO/Network/SoftwareBitBang/SegmentedSwitch/Device1/Device1.ino +++ /dev/null @@ -1,41 +0,0 @@ - -/* This example illustrates how to route packets between devices sharing the - same bus id although potentially using different strategies or media to - be connected. - - PJONSwitch routing between two separate SoftwareBitBang buses - __________ ________ __________ - | | 0.0.0.1 | | 0.0.0.1 | | - | DEVICE 1 |_________| SWITCH |_________| DEVICE 2 | - |__________| Pin 7 |________| Pin 12 |__________| */ - -#include - -// Bus id definition -uint8_t bus_id[] = {0, 0, 0, 1}; -uint8_t remote_bus_id[] = {0, 0, 0, 1}; - -// PJON object -PJON bus(bus_id, 100); - -void setup() { - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); // Initialize LED to be off - bus.strategy.set_pin(7); - bus.set_receiver(receiver_function); - bus.begin(); - bus.send_repeatedly(200, remote_bus_id, "B", 1, 250000); -} - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - if((char)payload[0] == 'B') { - static bool led_on = false; - digitalWrite(LED_BUILTIN, led_on ? HIGH : LOW); - led_on = !led_on; - } -} - -void loop() { - bus.receive(1000); - bus.update(); -} diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SegmentedSwitch/Device2/Device2.ino b/examples/ARDUINO/Network/SoftwareBitBang/SegmentedSwitch/Device2/Device2.ino deleted file mode 100644 index f4a8f58ff6..0000000000 --- a/examples/ARDUINO/Network/SoftwareBitBang/SegmentedSwitch/Device2/Device2.ino +++ /dev/null @@ -1,43 +0,0 @@ - -/* This example illustrates how to route packets between devices sharing the - same bus id although potentially using different strategies or media to - be connected. - - PJONSwitch routing between two separate SoftwareBitBang buses - __________ ________ __________ - | | 0.0.0.1 | | 0.0.0.1 | | - | DEVICE 1 |_________| SWITCH |_________| DEVICE 2 | - |__________| Pin 7 |________| Pin 12 |__________| */ - -#include - -// Bus id definition -uint8_t bus_id[] = {0, 0, 0, 1}; -uint8_t remote_bus_id[] = {0, 0, 0, 1}; - -// PJON object -PJON bus(bus_id, 200); - -void setup() { - pinMode(LED_BUILTIN, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); // Initialize LED to be off - - bus.strategy.set_pin(12); - bus.set_receiver(receiver_function); - bus.begin(); - bus.send(100, remote_bus_id, "B", 1); -} - -void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - if((char)payload[0] == 'B') { - bus.reply("B", 1); - static bool led_on = false; - digitalWrite(LED_BUILTIN, led_on ? HIGH : LOW); - led_on = !led_on; - } -} - -void loop() { - bus.receive(1000); - bus.update(); -} diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SegmentedSwitch/Switch/Switch.ino b/examples/ARDUINO/Network/SoftwareBitBang/SegmentedSwitch/Switch/Switch.ino deleted file mode 100644 index 8cead9ef7f..0000000000 --- a/examples/ARDUINO/Network/SoftwareBitBang/SegmentedSwitch/Switch/Switch.ino +++ /dev/null @@ -1,30 +0,0 @@ - -/* This example illustrates how to route packets between devices sharing the - same bus id although potentially using different strategies or media to - be connected. - - PJONSwitch routing between two separate SoftwareBitBang buses - __________ ________ __________ - | | 0.0.0.1 | | 0.0.0.1 | | - | DEVICE 1 |_________| SWITCH |_________| DEVICE 2 | - |__________| Pin 7 |________| Pin 12 |__________| */ - -#include - -StrategyLink link1; -StrategyLink link2; - -PJONAny bus1(&link1, (uint8_t[4]){0,0,0,1}, PJON_NOT_ASSIGNED, 1000, 2, 0); -PJONAny bus2(&link2, (uint8_t[4]){0,0,0,1}, PJON_NOT_ASSIGNED, 1000, 2, 1); - -PJONSwitch router(2, (PJONAny*[2]){&bus1, &bus2}, PJON_NOT_ASSIGNED); - -void setup() { - link1.strategy.set_pin(7); - link2.strategy.set_pin(12); - router.begin(); -} - -void loop() { - router.loop(); -} diff --git a/examples/ARDUINO/Local/SoftwareBitBang/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.fzz b/examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.fzz similarity index 100% rename from examples/ARDUINO/Local/SoftwareBitBang/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.fzz rename to examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.fzz diff --git a/examples/ARDUINO/Local/SoftwareBitBang/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino b/examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino similarity index 85% rename from examples/ARDUINO/Local/SoftwareBitBang/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino rename to examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino index 8008342772..8a7c58afa9 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino +++ b/examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino @@ -1,6 +1,9 @@ /* Similar to the Switch but with a blinking RGB led indicating each packet that is forwarded with blue and green for each direction respectively, - plus errors in red. */ + plus errors in red. + + This demonstrates how the PJONInteractiveRouter class supports user hooks + for error handling and to catch every packet being forwarded. */ #define PJON_MAX_PACKETS 3 #include @@ -8,13 +11,7 @@ // Ethernet configuration for this device, MAC must be unique! byte mac[] = {0xDE, 0x34, 0x4E, 0xEF, 0xFE, 0xE1}; -StrategyLink link1; -StrategyLink link2; - -PJONAny bus1(&link1); -PJONAny bus2(&link2); - -PJONInteractiveRouter> router(2, (PJONAny*[2]){&bus1, &bus2}); +PJONInteractiveRouter> router; // Pins for blinking RGB LED for showing traffic in each direction // (Use resistors approximately R:3.3k G:33k, B:8.2k) @@ -30,8 +27,8 @@ void error_handler(uint8_t code, uint16_t data, void *custom_ptr) { void setup() { while (Ethernet.begin(mac) == 0) delay(5000); // Wait for DHCP response - link1.strategy.set_pin(7); - link2.strategy.set_port(7200); // Use a "private" UDP port + router.get_strategy_0().set_pin(7); + router.get_strategy_1().set_port(7200); // Use a "private" UDP port router.set_sendnotification(sendnotification_function); router.set_error(error_handler); router.set_virtual_bus(0); // Enable virtual bus diff --git a/examples/ARDUINO/Local/SoftwareBitBang/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch_bb.png b/examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch_bb.png similarity index 100% rename from examples/ARDUINO/Local/SoftwareBitBang/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch_bb.png rename to examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch_bb.png diff --git a/examples/ARDUINO/Local/SoftwareBitBang/Tunneler/README.md b/examples/routing/ARDUINO/Local/Tunneler/README.md similarity index 72% rename from examples/ARDUINO/Local/SoftwareBitBang/Tunneler/README.md rename to examples/routing/ARDUINO/Local/Tunneler/README.md index 0994d1c9fa..290d6440f1 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/Tunneler/README.md +++ b/examples/routing/ARDUINO/Local/Tunneler/README.md @@ -2,27 +2,27 @@ You can connect multiple routers, or in this case switches with virtual bus support, in series, with or without devices connected to the buses between the switches. -This pair of examples, `SwitchA` and `SwitchB`, is named `Tunneler` because without changes it allows a collection of `SoftwareBitBang` devices to be connected to another collection of `SoftwareBitBang` devices through two switches connected via a LAN using the `LocalUDP` strategy. +This pair of examples, `SwitchA` and `SwitchB`, is named `Tunneler` because without changes it allows a collection of `SoftwareBitBang` devices to be connected to another collection of `SoftwareBitBang` devices through two switches connected via a LAN using the `DualUDP` strategy. The `SoftwareBitBang` traffic is "tunnelled" through another bus and medium. This is not limited to two groups of devices. You can add another 'SwitchC' and a third group of devices connected with the other two groups by just copying SwitchA.ino and modifying the MAC address so that it is unique on the network. -You can also have a switch or other program using the LocalUDP strategy and the same UDP port running on +You can also have a switch or other program using the DualUDP strategy and the same UDP port running on a Windows or Linux computer. This enables easy connectivity to programs running on a computer, and with the outside world. This setup is running in local mode, not using any bus ids, so all device ids involved must be unique. The switches themselves work in router mode and do not have device ids. -These sketches do not use the default LocalUDP port. Instead they use port 7200 (randomly selected) to have a "private" connection, not mixing with any other LocalUDP setups sharing the same LAN. +These sketches do not use the default DualUDP port. Instead they use port 7200 (randomly selected) to have a "private" or "tunneled" connection, not mixing with any other DualUDP setups sharing the same LAN. ## SwitchA The device is a switch with virtual bus support, meaning that multiple attached buses can use the same bus id or local mode, with the switch adapting to where devices are located. The user does not have to manually assign a specific device range to each attached bus. -It has two buses, a `SoftwareBitBang` bus named `A` and a `LocalUDP` bus named `B`. +It has two buses, a `SoftwareBitBang` bus named `A` and a `DualUDP` bus named `B`. The Ethernet setup is using DHCP to avoid manually configured IP addresses in the skethes. This means that you need to connect both devices to your LAN, not just connect a cable betwen them. -But because LocalUDP is based on UDP broadcasts, it will actually start working with a direct Ethernet cable between `SwitchA` and `SwitchB` after the attempt to get an IP address times out after 60 seconds. +But because DualUDP is based on UDP broadcasts, it will actually start working with a direct Ethernet cable between `SwitchA` and `SwitchB` after the attempt to get an IP address times out after 60 seconds. ## SwitchB diff --git a/examples/ARDUINO/Local/SoftwareBitBang/Tunneler/SwitchA/SwitchA.ino b/examples/routing/ARDUINO/Local/Tunneler/SwitchA/SwitchA.ino similarity index 57% rename from examples/ARDUINO/Local/SoftwareBitBang/Tunneler/SwitchA/SwitchA.ino rename to examples/routing/ARDUINO/Local/Tunneler/SwitchA/SwitchA.ino index 68c8594c37..b2a620ee85 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/Tunneler/SwitchA/SwitchA.ino +++ b/examples/routing/ARDUINO/Local/Tunneler/SwitchA/SwitchA.ino @@ -1,7 +1,9 @@ /* Tunnel packets through another medium using one switch on each end. / For example, two SoftwareBitBang buses that are far from each other -/ can be joined transparently through a LAN using the LocalUDP strategy, or -/ through a WAN or Internet using the EthernetTCP strategy. */ +/ can be joined transparently through a LAN/WAN using the DualUDP strategy +/ or the EthernetTCP strategy. +/ In this case, use a non-default UDP port to isolate the "tunnel" from +/ potential other DualUDP communication on the same network. */ #define PJON_MAX_PACKETS 3 #include @@ -9,18 +11,12 @@ // Ethernet configuration for this device, MAC must be unique! byte mac[] = {0xDE, 0x34, 0x4E, 0xEF, 0xFE, 0xE1}; -StrategyLink link1; -StrategyLink link2; - -PJONAny bus1(&link1); -PJONAny bus2(&link2); - -PJONVirtualBusRouter router(2, (PJONAny*[2]){&bus1, &bus2}); +PJONVirtualBusRouter2 router; void setup() { while (Ethernet.begin(mac) == 0) delay(5000); // Wait for DHCP response - link1.strategy.set_pin(7); - link2.strategy.set_port(7200); // Use a "private" UDP port + router.get_strategy_0().set_pin(7); + router.get_strategy_1().set_port(7200); // Use a "private" UDP port router.set_virtual_bus(0); // Enable virtual bus router.begin(); } diff --git a/examples/ARDUINO/Local/SoftwareBitBang/Tunneler/SwitchB/SwitchB.ino b/examples/routing/ARDUINO/Local/Tunneler/SwitchB/SwitchB.ino similarity index 57% rename from examples/ARDUINO/Local/SoftwareBitBang/Tunneler/SwitchB/SwitchB.ino rename to examples/routing/ARDUINO/Local/Tunneler/SwitchB/SwitchB.ino index 367da6cb63..8953959dd7 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/Tunneler/SwitchB/SwitchB.ino +++ b/examples/routing/ARDUINO/Local/Tunneler/SwitchB/SwitchB.ino @@ -1,7 +1,9 @@ /* Tunnel packets through another medium using one switch on each end. / For example, two SoftwareBitBang buses that are far from each other -/ can be joined transparently through a LAN using the LocalUDP strategy, or -/ through a WAN or Internet using the EthernetTCP strategy. */ +/ can be joined transparently through a LAN/WAN using the DualUDP strategy +/ or the EthernetTCP strategy. +/ In this case, use a non-default UDP port to isolate the "tunnel" from +/ potential other DualUDP communication on the same network. */ #define PJON_MAX_PACKETS 3 #include @@ -9,18 +11,12 @@ // Ethernet configuration for this device, MAC must be unique! byte mac[] = {0xEE, 0x79, 0x4E, 0xEF, 0xFE, 0x6D}; -StrategyLink link1; -StrategyLink link2; - -PJONAny bus1(&link1); -PJONAny bus2(&link2); - -PJONVirtualBusRouter router(2, (PJONAny*[2]){&bus1, &bus2}); +PJONVirtualBusRouter2 router; void setup() { while (Ethernet.begin(mac) == 0) delay(5000); // Wait for DHCP response - link1.strategy.set_pin(7); - link2.strategy.set_port(7200); // Use a "private" UDP port + router.get_strategy_0().set_pin(7); + router.get_strategy_1().set_port(7200); // Use a "private" UDP port router.set_virtual_bus(0); // Enable virtual bus router.begin(); } diff --git a/examples/ARDUINO/Local/SoftwareBitBang/Switch/Device1/Device1.ino b/examples/routing/ARDUINO/Local/VirtualBusRouter/Device1/Device1.ino similarity index 100% rename from examples/ARDUINO/Local/SoftwareBitBang/Switch/Device1/Device1.ino rename to examples/routing/ARDUINO/Local/VirtualBusRouter/Device1/Device1.ino diff --git a/examples/ARDUINO/Local/SoftwareBitBang/Switch/Device2/Device2.ino b/examples/routing/ARDUINO/Local/VirtualBusRouter/Device2/Device2.ino similarity index 100% rename from examples/ARDUINO/Local/SoftwareBitBang/Switch/Device2/Device2.ino rename to examples/routing/ARDUINO/Local/VirtualBusRouter/Device2/Device2.ino diff --git a/examples/routing/ARDUINO/Local/VirtualBusRouter/VirtualBusRouter/VirtualBusRouter.ino b/examples/routing/ARDUINO/Local/VirtualBusRouter/VirtualBusRouter/VirtualBusRouter.ino new file mode 100644 index 0000000000..80a7c560c0 --- /dev/null +++ b/examples/routing/ARDUINO/Local/VirtualBusRouter/VirtualBusRouter/VirtualBusRouter.ino @@ -0,0 +1,39 @@ +#include + +/* This sketch is routing between two local buses to form one larger local bus. + It will discover which attached bus each device is connected to, and route + packets dynamically. + Devices can be placed on any of the attached buses as long as device + ids are unique, forming a "virtual bus". + Using this router class, two or more physical buses can be merged. + It can also be used as a range extender. + + Note that this example demonstrates the general way which allows any + number of buses to be connected. For the simple two-bus case there is + a specialized class allowing for less code. See the example + VirtualBusRouter2.ino for this. + + // ROUTER forwarding from bus 1 to bus 2 and vice versa + __________ ________ __________ + | | Bus 1 Pin 7 | | Pin 12 Bus 2 | | + | DEVICE 1 |_______________| ROUTER |_______________| DEVICE 2 | + |__________| |________| |__________| */ + +StrategyLink link1; +StrategyLink link2; + +PJONAny bus1(&link1); +PJONAny bus2(&link2); + +PJONVirtualBusRouter router(2, (PJONAny*[2]){&bus1, &bus2}); + +void setup() { + link1.strategy.set_pin(7); + link2.strategy.set_pin(12); + router.set_virtual_bus(0); + router.begin(); +}; + +void loop() { + router.loop(); +}; diff --git a/examples/routing/ARDUINO/Local/VirtualBusRouter/VirtualBusRouter2/VirtualBusRouter2.ino b/examples/routing/ARDUINO/Local/VirtualBusRouter/VirtualBusRouter2/VirtualBusRouter2.ino new file mode 100644 index 0000000000..80414477cb --- /dev/null +++ b/examples/routing/ARDUINO/Local/VirtualBusRouter/VirtualBusRouter2/VirtualBusRouter2.ino @@ -0,0 +1,25 @@ +#include + +/* This sketch is routing between two local buses to form one larger local bus, + just like the VirtualBusRouter example, but it uses the class + PJONVirtualBusRouter2 which is specialized to using two buses to provide + a simpler declaration. + + // ROUTER forwarding from bus 1 to bus 2 and vice versa + __________ ________ __________ + | | Bus 1 Pin 7 | | Pin 12 Bus 2 | | + | DEVICE 1 |_______________| ROUTER |_______________| DEVICE 2 | + |__________| |________| |__________| */ + +PJONVirtualBusRouter2 router; + +void setup() { + router.get_strategy_0().set_pin(7); + router.get_strategy_1().set_pin(12); + router.set_virtual_bus(0); + router.begin(); +}; + +void loop() { + router.loop(); +}; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/LocalBusViaNATSwitch/LocalDevice/LocalDevice.ino b/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/LocalDevice/LocalDevice.ino similarity index 92% rename from examples/ARDUINO/Network/SoftwareBitBang/LocalBusViaNATSwitch/LocalDevice/LocalDevice.ino rename to examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/LocalDevice/LocalDevice.ino index b4e6daf8c6..4f383892db 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/LocalBusViaNATSwitch/LocalDevice/LocalDevice.ino +++ b/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/LocalDevice/LocalDevice.ino @@ -1,19 +1,18 @@ /* Route packets between a local bus and a network bus in both directions, using a switch that supports NAT (network address translation). - A device on the local bus can send to a device on a network buse by + A device on the local bus can send to a device on a network bus by specifying the bus id. If the switch has configured a public bus id (a NAT bus id) for this local bus, the remote devices can also reply. __________ ________ __________ | LOCAL | Pin 7 | NAT | Pin 12 | NETWORK | | DEVICE |_______________| SWITCH |_______________| DEVICE | - |__________| Local bus |________| Bus 0.0.0.2 |__________| */ + |__________| Local bus |________| Bus 0.0.0.2 |__________| + (NAT 0.0.0.1) +*/ #include -// Bus id definition for the network device -uint8_t remote_bus_id[] = {0, 0, 0, 2}; - // PJON object for a local bus PJON bus(44); diff --git a/examples/ARDUINO/Network/SoftwareBitBang/LocalBusViaNATSwitch/NATSwitch/NATSwitch.ino b/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NATSwitch/NATSwitch.ino similarity index 72% rename from examples/ARDUINO/Network/SoftwareBitBang/LocalBusViaNATSwitch/NATSwitch/NATSwitch.ino rename to examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NATSwitch/NATSwitch.ino index 620969c1b8..175b918862 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/LocalBusViaNATSwitch/NATSwitch/NATSwitch.ino +++ b/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NATSwitch/NATSwitch.ino @@ -11,21 +11,17 @@ #include -StrategyLink link1; -StrategyLink link2; - -PJONAny bus1(&link1, (uint8_t[4]){0,0,0,1}); // This is a local bus -PJONAny bus2(&link2, (uint8_t[4]){0,0,0,2}); - -PJONSwitch router(2, (PJONAny*[2]){&bus1, &bus2}); +PJONSwitch2 router; void setup() { + router.get_strategy_0().set_pin(7); + router.get_strategy_1().set_pin(12); + router.get_bus(0).set_bus_id((const uint8_t[4]){0, 0, 0, 1}); + router.get_bus(1).set_bus_id((const uint8_t[4]){0, 0, 0, 2}); + // We did specify a bus id for the first bus, so it will be in network mode. // Switch it to local mode before starting, activating NAT. - bus1.set_shared_network(false); - - link1.strategy.set_pin(7); - link2.strategy.set_pin(12); + router.get_bus(0).set_shared_network(false); router.begin(); } diff --git a/examples/ARDUINO/Network/SoftwareBitBang/LocalBusViaNATSwitch/NetworkDevice/NetworkDevice.ino b/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NetworkDevice/NetworkDevice.ino similarity index 97% rename from examples/ARDUINO/Network/SoftwareBitBang/LocalBusViaNATSwitch/NetworkDevice/NetworkDevice.ino rename to examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NetworkDevice/NetworkDevice.ino index c8619fbd18..957b173137 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/LocalBusViaNATSwitch/NetworkDevice/NetworkDevice.ino +++ b/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NetworkDevice/NetworkDevice.ino @@ -6,7 +6,9 @@ __________ ________ __________ | LOCAL | Pin 7 | NAT | Pin 12 | NETWORK | | DEVICE |_______________| SWITCH |_______________| DEVICE | - |__________| Local bus |________| Bus 0.0.0.2 |__________| */ + |__________| Local bus |________| Bus 0.0.0.2 |__________| + (NAT 0.0.0.1) +*/ #include diff --git a/examples/ARDUINO/Network/SoftwareBitBang/Router/DynamicRouter/DynamicRouter.ino b/examples/routing/ARDUINO/Network/Router/DynamicRouter/DynamicRouter.ino similarity index 78% rename from examples/ARDUINO/Network/SoftwareBitBang/Router/DynamicRouter/DynamicRouter.ino rename to examples/routing/ARDUINO/Network/Router/DynamicRouter/DynamicRouter.ino index 4b7d131414..5ad2eff384 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/Router/DynamicRouter/DynamicRouter.ino +++ b/examples/routing/ARDUINO/Network/Router/DynamicRouter/DynamicRouter.ino @@ -23,17 +23,13 @@ You may need to restart Device2 so that the packet it sends at startup will be registered and the reverse route established. */ -StrategyLink link1; -StrategyLink link2; - -PJONAny bus1(&link1, (const uint8_t[4]){0,0,0,3}); -PJONAny bus2(&link2, (const uint8_t[4]){0,0,0,4}); - -PJONDynamicRouter router(2, (PJONAny*[2]){&bus1, &bus2}); +PJONDynamicRouter2 router; void setup() { - link1.strategy.set_pin(7); - link2.strategy.set_pin(12); + router.get_strategy_0().set_pin(7); + router.get_strategy_1().set_pin(12); + router.get_bus(0).set_bus_id((const uint8_t[4]){0, 0, 0, 3}); + router.get_bus(1).set_bus_id((const uint8_t[4]){0, 0, 0, 4}); router.begin(); } diff --git a/examples/ARDUINO/Network/SoftwareBitBang/Router/Router/Router.ino b/examples/routing/ARDUINO/Network/Router/Router/Router.ino similarity index 75% rename from examples/ARDUINO/Network/SoftwareBitBang/Router/Router/Router.ino rename to examples/routing/ARDUINO/Network/Router/Router/Router.ino index 3d21da19f4..4e77a5496c 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/Router/Router/Router.ino +++ b/examples/routing/ARDUINO/Network/Router/Router/Router.ino @@ -23,18 +23,17 @@ Use Device1 and Device2 from the Switch example */ -StrategyLink link1; -StrategyLink link2; - -PJONAny bus1(&link1, (const uint8_t[4]){0,0,0,3}); -PJONAny bus2(&link2, (const uint8_t[4]){0,0,0,4}); - -PJONRouter router(2, (PJONAny*[2]){&bus1, &bus2}); +PJONRouter2 router; void setup() { - link1.strategy.set_pin(7); - link2.strategy.set_pin(12); + router.get_strategy_0().set_pin(7); + router.get_strategy_1().set_pin(12); + + // Set bus ids + router.get_bus(0).set_bus_id((const uint8_t[4]){0, 0, 0, 3}); + router.get_bus(1).set_bus_id((const uint8_t[4]){0, 0, 0, 4}); + // Populate routing table (which physical bus to use to reach remote bus) router.add((const uint8_t[4]){0,0,0,1}, 0); router.add((const uint8_t[4]){0,0,0,2}, 1); diff --git a/examples/ARDUINO/Network/SoftwareBitBang/Switch/BlinkingSwitch/BlinkingSwitch.ino b/examples/routing/ARDUINO/Network/Switch/BlinkingSwitch/BlinkingSwitch.ino similarity index 70% rename from examples/ARDUINO/Network/SoftwareBitBang/Switch/BlinkingSwitch/BlinkingSwitch.ino rename to examples/routing/ARDUINO/Network/Switch/BlinkingSwitch/BlinkingSwitch.ino index 34b2efa337..d24c21f71c 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/Switch/BlinkingSwitch/BlinkingSwitch.ino +++ b/examples/routing/ARDUINO/Network/Switch/BlinkingSwitch/BlinkingSwitch.ino @@ -5,18 +5,14 @@ #include -StrategyLink link1; -StrategyLink link2; - -PJONAny bus1(&link1, (const uint8_t[4]){0,0,0,1}); -PJONAny bus2(&link2, (const uint8_t[4]){0,0,0,2}); - -PJONInteractiveRouter router(2, (PJONAny*[2]) {&bus1, &bus2}); +PJONInteractiveRouter2 router; void setup() { pinMode(LED_BUILTIN, OUTPUT); - link1.strategy.set_pin(7); - link2.strategy.set_pin(12); + router.get_strategy_0().set_pin(7); + router.get_strategy_1().set_pin(12); + router.get_bus(0).set_bus_id((const uint8_t[4]){0, 0, 0, 1}); + router.get_bus(1).set_bus_id((const uint8_t[4]){0, 0, 0, 2}); router.set_receiver(receiver_function); router.set_router(true); // Pick up every packet passing router.begin(); diff --git a/examples/ARDUINO/Network/SoftwareBitBang/Switch/Device1/Device1.ino b/examples/routing/ARDUINO/Network/Switch/Device1/Device1.ino similarity index 100% rename from examples/ARDUINO/Network/SoftwareBitBang/Switch/Device1/Device1.ino rename to examples/routing/ARDUINO/Network/Switch/Device1/Device1.ino diff --git a/examples/ARDUINO/Network/SoftwareBitBang/Switch/Device2/Device2.ino b/examples/routing/ARDUINO/Network/Switch/Device2/Device2.ino similarity index 100% rename from examples/ARDUINO/Network/SoftwareBitBang/Switch/Device2/Device2.ino rename to examples/routing/ARDUINO/Network/Switch/Device2/Device2.ino diff --git a/examples/ARDUINO/Network/SoftwareBitBang/Switch/Switch/Switch.ino b/examples/routing/ARDUINO/Network/Switch/Switch/Switch.ino similarity index 62% rename from examples/ARDUINO/Network/SoftwareBitBang/Switch/Switch/Switch.ino rename to examples/routing/ARDUINO/Network/Switch/Switch/Switch.ino index a974162d6b..5ffbcbf664 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/Switch/Switch/Switch.ino +++ b/examples/routing/ARDUINO/Network/Switch/Switch/Switch.ino @@ -7,17 +7,13 @@ | DEVICE 1 |_______________| SWITCH |_______________| DEVICE 2 | |__________| Bus 0.0.0.1 |________| Bus 0.0.0.2 |__________| */ -StrategyLink link1; -StrategyLink link2; - -PJONAny bus1(&link1, (uint8_t[4]){0,0,0,1}); -PJONAny bus2(&link2, (uint8_t[4]){0,0,0,2}); - -PJONSwitch router(2, (PJONAny*[2]){&bus1, &bus2}); +PJONSwitch2 router; void setup() { - link1.strategy.set_pin(7); - link2.strategy.set_pin(12); + router.get_strategy_0().set_pin(7); + router.get_strategy_1().set_pin(12); + router.get_bus(0).set_bus_id((const uint8_t[4]){0, 0, 0, 1}); + router.get_bus(1).set_bus_id((const uint8_t[4]){0, 0, 0, 2}); router.begin(); } diff --git a/src/PJON.h b/src/PJON.h index ab6c209e78..2b7b8152da 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -188,7 +188,7 @@ class PJON { /* Add packet to buffer (delivery attempt by the next update() call): */ uint16_t dispatch( - const PJON_Packet_Info info, + const PJON_Packet_Info &info, const void *packet, uint16_t length, uint32_t timing = 0, @@ -482,7 +482,7 @@ class PJON { return dispatch(info, payload, length); }; - uint16_t send(PJON_Packet_Info info, const void *payload, uint16_t length) { + uint16_t send(const PJON_Packet_Info &info, const void *payload, uint16_t length) { return dispatch(info, payload, length); }; @@ -542,7 +542,7 @@ class PJON { }; uint16_t send_repeatedly( - PJON_Packet_Info info, + const PJON_Packet_Info &info, const void *payload, uint16_t length, uint32_t timing @@ -603,7 +603,7 @@ class PJON { }; uint16_t send_packet( - PJON_Packet_Info info, + const PJON_Packet_Info &info, const void *payload, uint16_t length ) { @@ -617,13 +617,9 @@ class PJON { delivered, or timing limit is reached. */ uint16_t send_packet_blocking( - uint8_t rx_id, - const uint8_t *rx_bus_id, + const PJON_Packet_Info &packet_info, const void *payload, uint16_t length, - uint8_t header = PJON_NO_HEADER, - uint16_t packet_id = 0, - uint16_t rx_port = PJON_BROADCAST, uint32_t timeout = 3500000 ) { uint16_t state = PJON_FAIL; @@ -636,9 +632,7 @@ class PJON { (state != PJON_ACK) && (attempts <= strategy.get_max_attempts()) && (uint32_t)(PJON_MICROS() - start) <= timeout ) { - PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); - PJONTools::copy_id(info.rx.bus_id, rx_bus_id, 4); - if(!(length = compose_packet(info, data, payload, old_length))) { + if(!(length = compose_packet(packet_info, data, payload, old_length))) { _recursion--; return PJON_FAIL; } @@ -659,6 +653,20 @@ class PJON { return state; }; + uint16_t send_packet_blocking( + uint8_t rx_id, + const uint8_t *rx_bus_id, + const void *payload, + uint16_t length, + uint8_t header = PJON_NO_HEADER, + uint16_t packet_id = 0, + uint16_t rx_port = PJON_BROADCAST, + uint32_t timeout = 3500000 + ) { + PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); + return send_packet_blocking(info, payload, length, timeout); + }; + uint16_t send_packet_blocking( uint8_t rx_id, const void *payload, @@ -748,6 +756,13 @@ class PJON { tx.id = id; }; + /* Setting bus id */ + + void set_bus_id(const uint8_t *b_id) { + PJONTools::copy_id(tx.bus_id, b_id, 4); + config |= PJON_MODE_BIT; + } + /* Configure sender's information inclusion in the packet. state = true -> +8 bits (device id) in local mode +40 bits (bus id + device id) in shared mode @@ -851,7 +866,7 @@ class PJON { /* Checks if the packet id and its transmitter info are already present in the known packets buffer, if not add it to the buffer */ - bool known_packet_id(PJON_Packet_Info info) { + bool known_packet_id(const PJON_Packet_Info &info) { for(uint8_t i = 0; i < PJON_MAX_RECENT_PACKET_IDS; i++) if( info.id == recent_packet_ids[i].id && @@ -876,7 +891,7 @@ class PJON { /* Save packet id in the buffer: */ - void save_packet_id(PJON_Packet_Info info) { + void save_packet_id(const PJON_Packet_Info &info) { for(uint8_t i = PJON_MAX_RECENT_PACKET_IDS - 1; i > 0; i--) recent_packet_ids[i] = recent_packet_ids[i - 1]; recent_packet_ids[0].id = info.id; diff --git a/src/PJONDynamicRouter.h b/src/PJONDynamicRouter.h index 99d0e7c8d2..c2d5c97017 100644 --- a/src/PJONDynamicRouter.h +++ b/src/PJONDynamicRouter.h @@ -53,13 +53,13 @@ class PJONDynamicRouter : public PJONRouter { ) { uint8_t start_search = 0; uint8_t found_bus = find_bus_with_id( - packet_info.sender_bus_id, - packet_info.sender_id, + packet_info.tx.bus_id, + packet_info.tx.id, start_search ); // Not found among attached buses or in routing table. Add to table. if(found_bus == PJON_NOT_ASSIGNED) - add(packet_info.sender_bus_id, sender_bus); + add(packet_info.tx.bus_id, sender_bus); }; virtual void dynamic_receiver_function( @@ -77,8 +77,50 @@ class PJONDynamicRouter : public PJONRouter { PJONDynamicRouter( uint8_t bus_count, - PJONAny *buses[], + PJONAny * const buses[], uint8_t default_gateway = PJON_NOT_ASSIGNED ) : PJONRouter(bus_count, buses, default_gateway) { }; +}; + +// Specialized class to simplify declaration when using 2 buses +template +class PJONDynamicRouter2 : public PJONDynamicRouter { + StrategyLink linkA; + StrategyLink linkB; + PJONAny busA, busB; +public: + PJONDynamicRouter2(uint8_t default_gateway = PJON_NOT_ASSIGNED) { + PJON* buses[2] = { &busA, &busB }; + PJONSimpleSwitch::connect_buses(2, buses, default_gateway); + busA.set_link(&linkA); + busB.set_link(&linkB); + }; + + PJONAny &get_bus(const uint8_t ix) { return ix == 0 ? busA : busB; } + + A &get_strategy_0() { return linkA.strategy; } + B &get_strategy_1() { return linkB.strategy; } +}; + +// Specialized class to simplify declaration when using 3 buses +template +class PJONDynamicRouter3 : public PJONDynamicRouter { + StrategyLink linkA; + StrategyLink linkB; + StrategyLink linkC; + PJONAny busA, busB, busC; +public: + PJONDynamicRouter3(uint8_t default_gateway = PJON_NOT_ASSIGNED) { + PJON *buses[3] = { &busA, &busB, &busC }; + PJONSimpleSwitch::connect_buses(3, buses, default_gateway); + busA.set_link(&linkA); + busB.set_link(&linkB); + busC.set_link(&linkC); + }; + PJONAny &get_bus(const uint8_t ix) { return ix == 0 ? busA : (ix == 1 ? busB : busC); } + + A &get_strategy_0() { return linkA.strategy; } + B &get_strategy_1() { return linkB.strategy; } + C &get_strategy_2() { return linkC.strategy; } }; diff --git a/src/PJONInteractiveRouter.h b/src/PJONInteractiveRouter.h index fcbbed1b00..890dc21cc5 100644 --- a/src/PJONInteractiveRouter.h +++ b/src/PJONInteractiveRouter.h @@ -58,7 +58,7 @@ typedef void (* PJON_SendNotification)( const PJON_Packet_Info &packet_info ); -template +template class PJONInteractiveRouter : public RouterClass { protected: void *custom_pointer = NULL; @@ -72,16 +72,16 @@ class PJONInteractiveRouter : public RouterClass { // (If this device has a device id on the source bus, and it is equal to // the packets receiver_id, the packet is for this device.) bool packet_is_for_me = ( - RouterClass::buses[RouterClass::current_bus]->device_id() != PJON_NOT_ASSIGNED && - memcmp(RouterClass::buses[RouterClass::current_bus]->bus_id, packet_info.receiver_bus_id, 4) == 0 && - RouterClass::buses[RouterClass::current_bus]->device_id() == packet_info.receiver_id + RouterClass::buses[RouterClass::current_bus]->tx.id != PJON_NOT_ASSIGNED && + memcmp(RouterClass::buses[RouterClass::current_bus]->tx.bus_id, packet_info.rx.bus_id, 4) == 0 && + RouterClass::buses[RouterClass::current_bus]->tx.id == packet_info.rx.id ); // Take care of other's packets if(!packet_is_for_me) RouterClass::dynamic_receiver_function(payload, length, packet_info); else if(packet_info.header & PJON_ACK_REQ_BIT) - RouterClass::buses[RouterClass::current_bus]->send_synchronous_acknowledge(); + RouterClass::buses[RouterClass::current_bus]->send_acknowledge(); // Call the receive callback _after_ the packet has been delivered if(router || packet_is_for_me) { // The packet is for ME :-) @@ -112,7 +112,7 @@ class PJONInteractiveRouter : public RouterClass { PJONInteractiveRouter() : RouterClass() {} PJONInteractiveRouter( uint8_t bus_count, - PJONAny*buses[], + PJONAny* const buses[], uint8_t default_gateway = PJON_NOT_ASSIGNED) : RouterClass(bus_count, buses, default_gateway) {} @@ -135,3 +135,46 @@ class PJONInteractiveRouter : public RouterClass { // Deliver every packet to receiver callback, or just for this device? void set_router(bool on) { router = on; }; }; + +// Specialized class to simplify declaration when using 2 buses +template +class PJONInteractiveRouter2 : public PJONInteractiveRouter { + StrategyLink linkA; + StrategyLink linkB; + PJONAny busA, busB; +public: + PJONInteractiveRouter2(uint8_t default_gateway = PJON_NOT_ASSIGNED) { + PJON* buses[2] = { &busA, &busB }; + PJONSimpleSwitch::connect_buses(2, buses, default_gateway); + busA.set_link(&linkA); + busB.set_link(&linkB); + }; + + PJONAny &get_bus(const uint8_t ix) { return ix == 0 ? busA : busB; } + + A &get_strategy_0() { return linkA.strategy; } + B &get_strategy_1() { return linkB.strategy; } +}; + +// Specialized class to simplify declaration when using 3 buses +template +class PJONInteractiveRouter3 : public PJONInteractiveRouter { + StrategyLink linkA; + StrategyLink linkB; + StrategyLink linkC; + PJONAny busA, busB, busC; +public: + PJONInteractiveRouter3(uint8_t default_gateway = PJON_NOT_ASSIGNED) { + PJON* buses[3] = { &busA, &busB, &busC }; + PJONSimpleSwitch::connect_buses(3, buses, default_gateway); + busA.set_link(&linkA); + busB.set_link(&linkB); + busC.set_link(&linkC); + }; + + PJONAny &get_bus(const uint8_t ix) { return ix == 0 ? busA : (ix == 1 ? busB : busC); } + + A &get_strategy_0() { return linkA.strategy; } + B &get_strategy_1() { return linkB.strategy; } + C &get_strategy_2() { return linkC.strategy; } +}; \ No newline at end of file diff --git a/src/PJONRouter.h b/src/PJONRouter.h index 411db0c888..0c508f8ef8 100644 --- a/src/PJONRouter.h +++ b/src/PJONRouter.h @@ -61,7 +61,7 @@ class PJONRouter : public PJONSwitch { ) { uint8_t start = start_bus - bus_count; for(uint8_t i = start; i < table_size; i++) { - if(PJONTools::bus_id_equality(bus_id, remote_bus_ids[i])) { + if(memcmp(bus_id, remote_bus_ids[i], 4) == 0) { start_bus = bus_count + i + 1; // Continue searching for matches return remote_bus_via_attached_bus[i]; // Explicit bus id match } @@ -98,15 +98,59 @@ class PJONRouter : public PJONSwitch { PJONRouter() {}; PJONRouter( uint8_t bus_count, - PJONAny *buses[], + PJONAny * const buses[], uint8_t default_gateway = PJON_NOT_ASSIGNED ) : PJONSwitch(bus_count, buses, default_gateway) { }; void add(const uint8_t bus_id[], uint8_t via_attached_bus) { if(table_size < PJON_ROUTER_TABLE_SIZE) { - PJONTools::copy_bus_id(remote_bus_ids[table_size], bus_id); + memcpy(remote_bus_ids[table_size], bus_id, 4); remote_bus_via_attached_bus[table_size] = via_attached_bus; table_size++; } }; }; + + +// Specialized class to simplify declaration when using 2 buses +template +class PJONRouter2 : public PJONRouter { + StrategyLink linkA; + StrategyLink linkB; + PJONAny busA, busB; +public: + PJONRouter2(uint8_t default_gateway = PJON_NOT_ASSIGNED) { + PJON* buses[2] = { &busA, &busB }; + PJONSimpleSwitch::connect_buses(2, buses, default_gateway); + busA.set_link(&linkA); + busB.set_link(&linkB); + }; + + PJONAny &get_bus(const uint8_t ix) { return ix == 0 ? busA : busB; } + + A &get_strategy_0() { return linkA.strategy; } + B &get_strategy_1() { return linkB.strategy; } +}; + +// Specialized class to simplify declaration when using 3 buses +template +class PJONRouter3 : public PJONRouter { + StrategyLink linkA; + StrategyLink linkB; + StrategyLink linkC; + PJONAny busA, busB, busC; +public: + PJONRouter3(uint8_t default_gateway = PJON_NOT_ASSIGNED) { + PJON *buses[3] = { &busA, &busB, &busC }; + PJONSimpleSwitch::connect_buses(3, buses, default_gateway); + busA.set_link(&linkA); + busB.set_link(&linkB); + busC.set_link(&linkC); + }; + + PJONAny &get_bus(const uint8_t ix) { return ix == 0 ? busA : (ix == 1 ? busB : busC); } + + A &get_strategy_0() { return linkA.strategy; } + B &get_strategy_1() { return linkB.strategy; } + C &get_strategy_2() { return linkC.strategy; } +}; \ No newline at end of file diff --git a/src/PJONSimpleSwitch.h b/src/PJONSimpleSwitch.h index 5267fcd22f..b5eba4859b 100644 --- a/src/PJONSimpleSwitch.h +++ b/src/PJONSimpleSwitch.h @@ -15,17 +15,14 @@ PJONSimpleSwitch has been contributed by Fred Larsen. -It routes packets between buses with different bus ids, and between segmented -buses as well, even for local buses with no bus ids. It is limited to one -single strategy in contrast to its descendant PJONSwitch. +It routes packets between buses with different bus ids, and also between +local buses with no bus ids. It is limited to one single strategy in contrast +to its descendant PJONSwitch. A default gateway can be specified, identifying one of the attached buses to receive packets to other target buses than any of the attached buses. It is possible to use a PJONSimpleSwitch to handle leaf buses in a tree structure. -A segmented bus is a "virtual" bus where ranges of its devices are located -in separate physical buses. - NAT (network address translation) support is present, allowing a local bus to communicate with shared buses. To do this, the local bus must have the bus id set to a public/NAT bus id with which it can be reached from other @@ -58,36 +55,6 @@ limitations under the License. */ #pragma once #include "PJON.h" -template -class PJONBus : public PJON { -public: - PJONBus( - const uint8_t id = PJON_NOT_ASSIGNED, - const uint32_t receive_time_in = 0, - const uint8_t num_device_id_segments = 1, - const uint8_t device_id_segment = 0 - ) : PJON(id) { - receive_time = receive_time_in; - segment_count = num_device_id_segments; - segment = device_id_segment; - }; - - PJONBus( - const uint8_t bus_id[], - const uint8_t id = PJON_NOT_ASSIGNED, - const uint32_t receive_time_in = 0, - const uint8_t num_device_id_segments = 1, - const uint8_t device_id_segment = 0 - ) : PJON(bus_id, id) { - receive_time = receive_time_in; - segment_count = num_device_id_segments; - segment = device_id_segment; - } - - uint32_t receive_time; - uint8_t segment_count, segment; -}; - #ifndef PJON_ROUTER_MAX_BUSES #define PJON_ROUTER_MAX_BUSES 5 #endif @@ -98,11 +65,11 @@ class PJONSimpleSwitch { uint8_t bus_count = 0; uint8_t default_gateway = PJON_NOT_ASSIGNED; uint8_t current_bus = PJON_NOT_ASSIGNED; - PJONBus *buses[PJON_ROUTER_MAX_BUSES]; + PJON *buses[PJON_ROUTER_MAX_BUSES]; void connect( uint8_t bus_count_in, - PJONBus *buses_in[], + PJON * const buses_in[], uint8_t default_gateway_in, void *custom_pointer, PJON_Receiver receiver, @@ -126,16 +93,9 @@ class PJONSimpleSwitch { uint8_t &start_bus ) { for(uint8_t i=start_bus; ibus_id)) { - // Check if bus is segmented and if device belongs to bus's segment - if( - (buses[i]->segment_count <= 1) || // Not segmented - (device_id == PJON_BROADCAST) || // Broadcast to all segments - ((device_id / (256 / buses[i]->segment_count)) == buses[i]->segment) - ) { // Segment match - start_bus = i + 1; // Continue searching for more matches after this - return i; // Explicit bus id match - } + if(memcmp(bus_id, buses[i]->tx.bus_id, 4) == 0) { + start_bus = i + 1; // Continue searching for more matches after this + return i; // Explicit bus id match } } start_bus = PJON_NOT_ASSIGNED; @@ -152,7 +112,7 @@ class PJONSimpleSwitch { if( !ack_sent && (packet_info.header & PJON_ACK_REQ_BIT) && - (packet_info.receiver_id != PJON_BROADCAST) + (packet_info.rx.id != PJON_BROADCAST) ) { buses[sender_bus]->strategy.send_response(PJON_ACK); ack_sent = true; @@ -165,41 +125,31 @@ class PJONSimpleSwitch { // NAT support: If a shared packet comes from a local bus destined to a // non-local receiver, then put the NAT address of the bus as the sender // bus id so that replies can find the route back via NAT. - uint8_t sender_bus_id[4]; - memcpy(sender_bus_id, packet_info.sender_bus_id, 4); + PJON_Packet_Info p_info = packet_info; if ((packet_info.header & PJON_MODE_BIT) && !(buses[sender_bus]->config & PJON_MODE_BIT) && - memcmp(buses[sender_bus]->bus_id, PJONTools::localhost(), 4)!=0 && - memcmp(packet_info.sender_bus_id, PJONTools::localhost(), 4)==0) { + memcmp(buses[sender_bus]->tx.bus_id, PJONTools::localhost(), 4)!=0 && + memcmp(packet_info.tx.bus_id, PJONTools::localhost(), 4)==0) { // Replace sender bus id with public/NAT bus id in the packet - memcpy(&sender_bus_id, buses[sender_bus]->bus_id, 4); + memcpy(&p_info.tx.bus_id, buses[sender_bus]->tx.bus_id, 4); } // NAT support: If a shared packet comes with receiver bus id matching the // NAT address of a local bus, then change the receiver bus id to 0.0.0.0 // before forwarding the shared packet to the local bus. - uint8_t receiver_bus_id[4]; - memcpy(receiver_bus_id, packet_info.receiver_bus_id, 4); if ((packet_info.header & PJON_MODE_BIT) && !(buses[receiver_bus]->config & PJON_MODE_BIT) && - memcmp(buses[receiver_bus]->bus_id, PJONTools::localhost(), 4)!=0 && - memcmp(packet_info.receiver_bus_id, buses[receiver_bus]->bus_id, 4)==0) { + memcmp(buses[receiver_bus]->tx.bus_id, PJONTools::localhost(), 4)!=0 && + memcmp(packet_info.rx.bus_id, buses[receiver_bus]->tx.bus_id, 4)==0) { // Replace receiver bus id with 0.0.0.0 when sending to local bus - memcpy(receiver_bus_id, PJONTools::localhost(), 4); + memcpy(p_info.rx.bus_id, PJONTools::localhost(), 4); } // Forward the packet - uint16_t result = buses[receiver_bus]->send_from_id( - packet_info.sender_id, - sender_bus_id, - packet_info.receiver_id, - receiver_bus_id, - (const uint8_t*)payload, - length, - packet_info.header, - packet_info.id, - packet_info.port - ); + uint16_t result = buses[receiver_bus]->forward( + p_info, + (const uint8_t *)payload, + length); #if PJON_MAX_PACKETS == 0 // Call error function explicitly, because that will not be done while sending @@ -242,8 +192,8 @@ class PJONSimpleSwitch { do { uint8_t receiver_bus = find_bus_with_id((const uint8_t*) ((packet_info.header & PJON_MODE_BIT) != 0 ? - packet_info.receiver_bus_id : PJONTools::localhost()), - packet_info.receiver_id, start_search + packet_info.rx.bus_id : PJONTools::localhost()), + packet_info.rx.id, start_search ); /* The NAT case: @@ -274,12 +224,31 @@ class PJONSimpleSwitch { PJONSimpleSwitch( uint8_t bus_count, - PJONBus *buses[], + PJON * const buses[], uint8_t default_gateway = PJON_NOT_ASSIGNED ) { connect_buses(bus_count, buses, default_gateway); }; + // Specialized constructor to simplify syntax when using 2 buses + PJONSimpleSwitch( + PJON &bus0, + PJON &bus1, + uint8_t default_gateway = PJON_NOT_ASSIGNED + ) { + connect_buses(2, (PJON*[2]){&bus0, &bus1}, default_gateway); + }; + + // Specialized constructor to simplify syntax when using 3 buses + PJONSimpleSwitch( + PJON &bus0, + PJON &bus1, + PJON &bus2, + uint8_t default_gateway = PJON_NOT_ASSIGNED + ) { + connect_buses(3, (PJON*[3]){&bus0, &bus1, &bus2}, default_gateway); + }; + void begin() { for(uint8_t i = 0; i < bus_count; i++) buses[i]->begin(); }; @@ -287,7 +256,7 @@ class PJONSimpleSwitch { void loop() { for(current_bus = 0; current_bus < bus_count; current_bus++) { uint16_t code = - buses[current_bus]->receive(buses[current_bus]->receive_time); + buses[current_bus]->receive(buses[current_bus]->strategy.get_receive_time()); if(PJON_MAX_PACKETS < bus_count && code == PJON_ACK) break; } for(current_bus = 0; current_bus < bus_count; current_bus++) @@ -297,7 +266,7 @@ class PJONSimpleSwitch { void connect_buses( uint8_t bus_count_in, - PJONBus *buses_in[], + PJON * const buses_in[], uint8_t default_gateway_in = PJON_NOT_ASSIGNED ) { connect( @@ -315,7 +284,7 @@ class PJONSimpleSwitch { uint8_t get_callback_bus() const { return current_bus; } // Return one of the buses, in the same order as sent to the constructor - PJONBus &get_bus(const uint8_t ix) { return *(buses[ix]); } + PJON &get_bus(const uint8_t ix) { return *(buses[ix]); } static void receiver_function( uint8_t *payload, @@ -335,3 +304,4 @@ class PJONSimpleSwitch { ((PJONSimpleSwitch*)custom_pointer)->dynamic_error_function(code, data); } }; + diff --git a/src/PJONSwitch.h b/src/PJONSwitch.h index d722a18ce0..3e36f61c84 100644 --- a/src/PJONSwitch.h +++ b/src/PJONSwitch.h @@ -40,39 +40,31 @@ limitations under the License. */ #include "PJONSimpleSwitch.h" -class PJONAny : public PJONBus { +class PJONAny : public PJON { public: + PJONAny( + const uint8_t id = PJON_NOT_ASSIGNED + ) : PJON(id) {}; + PJONAny( StrategyLinkBase *link, - const uint8_t id = PJON_NOT_ASSIGNED, - const uint32_t receive_time_in = 0, - const uint8_t num_device_id_segments = 1, - const uint8_t device_id_segment = 0 - ) : PJONBus( - id, - receive_time_in, - num_device_id_segments, - device_id_segment - ) { + const uint8_t id = PJON_NOT_ASSIGNED + ) : PJON(id) { strategy.set_link(link); }; PJONAny( StrategyLinkBase *link, const uint8_t bus_id[], - const uint8_t id = PJON_NOT_ASSIGNED, - const uint32_t receive_time_in = 0, - const uint8_t num_device_id_segments = 1, - const uint8_t device_id_segment = 0 - ) : PJONBus( + const uint8_t id = PJON_NOT_ASSIGNED + ) : PJON( bus_id, - id, - receive_time_in, - num_device_id_segments, - device_id_segment + id ) { strategy.set_link(link); } + + void set_link(StrategyLinkBase *link) { strategy.set_link(link); } }; class PJONSwitch : public PJONSimpleSwitch { @@ -81,7 +73,50 @@ class PJONSwitch : public PJONSimpleSwitch { PJONSwitch( uint8_t bus_count, - PJONAny *bus_list[], + PJONAny * const bus_list[], uint8_t default_gateway = PJON_NOT_ASSIGNED - ) : PJONSimpleSwitch(bus_count, (PJONBus**)bus_list, default_gateway) { }; + ) : PJONSimpleSwitch(bus_count, (PJON* const *)bus_list, default_gateway) { }; +}; + +// Specialized class to simplify declaration when using 2 buses +template +class PJONSwitch2 : public PJONSwitch { + StrategyLink linkA; + StrategyLink linkB; + PJONAny busA, busB; +public: + PJONSwitch2(uint8_t default_gateway = PJON_NOT_ASSIGNED) { + PJON* buses[2] = { &busA, &busB }; + PJONSimpleSwitch::connect_buses(2, buses, default_gateway); + busA.set_link(&linkA); + busB.set_link(&linkB); + }; + + PJONAny &get_bus(const uint8_t ix) { return ix == 0 ? busA : busB; } + + A &get_strategy_0() { return linkA.strategy; } + B &get_strategy_1() { return linkB.strategy; } }; + +// Specialized class to simplify declaration when using 3 buses +template +class PJONSwitch3 : public PJONSwitch { + StrategyLink linkA; + StrategyLink linkB; + StrategyLink linkC; + PJONAny busA, busB, busC; +public: + PJONSwitch3(uint8_t default_gateway = PJON_NOT_ASSIGNED) { + PJON *buses[3] = { &busA, &busB, &busC }; + PJONSimpleSwitch::connect_buses(3, buses, default_gateway); + busA.set_link(&linkA); + busB.set_link(&linkB); + busC.set_link(&linkC); + }; + + PJONAny &get_bus(const uint8_t ix) { return ix == 0 ? busA : (ix == 1 ? busB : busC); } + + A &get_strategy_0() { return linkA.strategy; } + B &get_strategy_1() { return linkB.strategy; } + C &get_strategy_2() { return linkC.strategy; } +}; \ No newline at end of file diff --git a/src/PJONVirtualBusRouter.h b/src/PJONVirtualBusRouter.h index 84aca65cb9..7afa6e6909 100644 --- a/src/PJONVirtualBusRouter.h +++ b/src/PJONVirtualBusRouter.h @@ -18,8 +18,7 @@ PJONVirtualBusRouter has been contributed by Fred Larsen. This class adds functionality to the PJONSwitch, PJONRouter, PJONDynamicRouter and potential future classes derived from them. This functionality allows a switch or router to treat multiple attached buses with the same bus id as a -"virtual" bus, where devices can be placed anywhere independent of device id, -and without any explicit segmentation of the device id range. +"virtual" bus, where devices can be placed anywhere independent of device id. It will start in promiscuous mode, delivering every packet to all attached buses except the one where the packet comes from. As it learns by looking at @@ -66,7 +65,7 @@ limitations under the License. */ #define PJON_VIRTUALBUS_ROUTE_TIMEOUT_S 0 #endif -template +template class PJONVirtualBusRouter : public RouterClass { protected: // The array position of one (any) of the parts of the virtual bus. @@ -81,7 +80,7 @@ class PJONVirtualBusRouter : public RouterClass { void init_vbus() { for (uint8_t i=0; ibus_id, bus_id, 4)==0; + memcmp(RouterClass::buses[virtual_bus]->tx.bus_id, bus_id, 4)==0; } void register_device_on_vbus(const uint8_t device_id, const uint8_t attached_bus) { @@ -121,10 +120,9 @@ class PJONVirtualBusRouter : public RouterClass { bool &ack_sent, const PJON_Packet_Info &packet_info) { // Override the base class send_packet to disable requesting and sending ACK // if the receiver's location is not registered. - bool disable_ack = unknown_device_location && is_vbus(RouterClass::buses[receiver_bus]->bus_id); + bool disable_ack = unknown_device_location && is_vbus(RouterClass::buses[receiver_bus]->tx.bus_id); if (disable_ack) { - PJON_Packet_Info info; - memcpy(&info, &packet_info, sizeof info); + PJON_Packet_Info info = packet_info; info.header &= ~PJON_ACK_REQ_BIT; bool disable_ack = true; @@ -137,7 +135,7 @@ class PJONVirtualBusRouter : public RouterClass { else { RouterClass::send_packet(payload, length, receiver_bus, sender_bus, ack_sent, packet_info); #ifdef DEBUG_PRINT_PACKETS - Serial.print(F("FORWARD ")); Serial.print(packet_info.receiver_id); Serial.print(F(" to bus ")); + Serial.print(F("FORWARD ")); Serial.print(packet_info.rx.id); Serial.print(F(" to bus ")); Serial.println(receiver_bus); #endif } @@ -146,7 +144,7 @@ class PJONVirtualBusRouter : public RouterClass { void handle_send_error(uint8_t code, uint8_t packet) { // Find out which device id does not receive if (PJON_CONNECTION_LOST == code && - is_vbus(RouterClass::buses[RouterClass::current_bus]->bus_id) && + is_vbus(RouterClass::buses[RouterClass::current_bus]->tx.bus_id) && (packet < PJON_MAX_PACKETS || PJON_MAX_PACKETS == 0)) { PJON_Packet_Info info; @@ -157,14 +155,14 @@ class PJONVirtualBusRouter : public RouterClass { RouterClass::buses[RouterClass::current_bus]-> parse((RouterClass::buses[RouterClass::current_bus]->packets[packet].content), info); #endif - if (info.receiver_id < PJON_VIRTUALBUS_MAX_DEVICES && is_vbus(info.receiver_bus_id)) { + if (info.rx.id < PJON_VIRTUALBUS_MAX_DEVICES && is_vbus(info.rx.bus_id)) { // Unregister the device if we got an error trying to deliver to the attached // bus on which it is registered. This will step back from pointed delivery // to duplication on all parts of the virtual bus for this device. - if (device_via_attached_bus[info.receiver_id] == RouterClass::current_bus) { - device_via_attached_bus[info.receiver_id] = PJON_NOT_ASSIGNED; + if (device_via_attached_bus[info.rx.id] == RouterClass::current_bus) { + device_via_attached_bus[info.rx.id] = PJON_NOT_ASSIGNED; #ifdef DEBUG_PRINT - Serial.print("Unregister "); Serial.print(info.receiver_id); + Serial.print("Unregister "); Serial.print(info.rx.id); Serial.print(" from bus "); Serial.println(RouterClass::current_bus); #endif } @@ -177,11 +175,11 @@ class PJONVirtualBusRouter : public RouterClass { // If a packet is sent to this device later, it is possible to fall back // from delivering a copy to each part of the virtual bus, to just // delivering to the part where the device is actually present. - if (is_vbus(packet_info.sender_bus_id)) - register_device_on_vbus(packet_info.sender_id, RouterClass::current_bus); + if (is_vbus(packet_info.tx.bus_id)) + register_device_on_vbus(packet_info.tx.id, RouterClass::current_bus); // Search for the device on the virtual bus - uint8_t receiver_bus = find_vbus_with_device(packet_info.receiver_bus_id, packet_info.receiver_id); + uint8_t receiver_bus = find_vbus_with_device(packet_info.rx.bus_id, packet_info.rx.id); // If found on part of a virtual bus, do not deliver copies to others if (receiver_bus != PJON_NOT_ASSIGNED) { @@ -203,7 +201,7 @@ class PJONVirtualBusRouter : public RouterClass { PJONVirtualBusRouter() : RouterClass() { init_vbus(); } PJONVirtualBusRouter( uint8_t bus_count, - PJONAny*buses[], + PJONAny* const *buses, uint8_t default_gateway = PJON_NOT_ASSIGNED) : RouterClass(bus_count, buses, default_gateway) { init_vbus(); } @@ -214,3 +212,46 @@ class PJONVirtualBusRouter : public RouterClass { virtual_bus = first_bus; } }; + +// Specialized class to simplify declaration when using 2 buses +template +class PJONVirtualBusRouter2 : public PJONVirtualBusRouter { + StrategyLink linkA; + StrategyLink linkB; + PJONAny busA, busB; +public: + PJONVirtualBusRouter2(uint8_t default_gateway = PJON_NOT_ASSIGNED) { + PJON* buses[2] = { &busA, &busB }; + PJONSimpleSwitch::connect_buses(2, buses, default_gateway); + busA.set_link(&linkA); + busB.set_link(&linkB); + }; + + PJONAny &get_bus(const uint8_t ix) { return ix == 0 ? busA : busB; } + + A &get_strategy_0() { return linkA.strategy; } + B &get_strategy_1() { return linkB.strategy; } +}; + +// Specialized class to simplify declaration when using 3 buses +template +class PJONVirtualBusRouter3 : public PJONVirtualBusRouter { + StrategyLink linkA; + StrategyLink linkB; + StrategyLink linkC; + PJONAny busA, busB, busC; +public: + PJONVirtualBusRouter3(uint8_t default_gateway = PJON_NOT_ASSIGNED) { + PJON* buses[3] = { &busA, &busB, &busC }; + PJONSimpleSwitch::connect_buses(3, buses, default_gateway); + busA.set_link(&linkA); + busB.set_link(&linkB); + busC.set_link(&linkC); + }; + + PJONAny &get_bus(const uint8_t ix) { return ix == 0 ? busA : (ix == 1 ? busB : busC); } + + A &get_strategy_0() { return linkA.strategy; } + B &get_strategy_1() { return linkB.strategy; } + C &get_strategy_2() { return linkC.strategy; } +}; \ No newline at end of file diff --git a/src/strategies/AnalogSampling/AnalogSampling.h b/src/strategies/AnalogSampling/AnalogSampling.h index 7f3a716308..ecdf9359ab 100644 --- a/src/strategies/AnalogSampling/AnalogSampling.h +++ b/src/strategies/AnalogSampling/AnalogSampling.h @@ -87,6 +87,11 @@ #include "Timing.h" +// Recommended receive time for this strategy, in microseconds +#ifndef AS_RECEIVE_TIME + #define AS_RECEIVE_TIME 1000 +#endif + class AnalogSampling { public: @@ -159,6 +164,13 @@ class AnalogSampling { }; + /* Returns the recommended receive time for this strategy: */ + + static uint16_t get_receive_time() { + return AS_RECEIVE_TIME; + }; + + /* Handle a collision: */ void handle_collision() { diff --git a/src/strategies/Any/Any.h b/src/strategies/Any/Any.h index dd67e34846..9583024c93 100644 --- a/src/strategies/Any/Any.h +++ b/src/strategies/Any/Any.h @@ -58,6 +58,11 @@ class Any { uint8_t get_max_attempts() { return s->get_max_attempts(); } + /* Returns the recommended receive time for this strategy: */ + + uint16_t get_receive_time() { return s->get_receive_time(); } + + /* Handle a collision: */ void handle_collision() { s->handle_collision(); }; diff --git a/src/strategies/Any/StrategyLink.h b/src/strategies/Any/StrategyLink.h index 188acf50b4..f8f761d41d 100644 --- a/src/strategies/Any/StrategyLink.h +++ b/src/strategies/Any/StrategyLink.h @@ -49,6 +49,11 @@ class StrategyLink : public StrategyLinkBase { uint8_t get_max_attempts() { return strategy.get_max_attempts(); } + /* Returns the recommended receive time for this strategy: */ + + uint16_t get_receive_time() { return strategy.get_receive_time(); } + + /* Handle a collision: */ void handle_collision() { strategy.handle_collision(); }; diff --git a/src/strategies/Any/StrategyLinkBase.h b/src/strategies/Any/StrategyLinkBase.h index 077f5a9e32..e2871c5e60 100644 --- a/src/strategies/Any/StrategyLinkBase.h +++ b/src/strategies/Any/StrategyLinkBase.h @@ -42,6 +42,9 @@ class StrategyLinkBase { virtual uint8_t get_max_attempts() = 0; + /* Returns the recommended receive time for this strategy: */ + + virtual uint16_t get_receive_time() = 0; /* Handle a collision: */ diff --git a/src/strategies/DualUDP/DualUDP.h b/src/strategies/DualUDP/DualUDP.h index 6ae35ceb0b..d5f00b1fc2 100644 --- a/src/strategies/DualUDP/DualUDP.h +++ b/src/strategies/DualUDP/DualUDP.h @@ -79,6 +79,11 @@ #define DUDP_DEFAULT_PORT 7500 #define DUDP_MAGIC_HEADER (uint32_t) 0x0EFA23FF +// Recommended receive time for this strategy, in microseconds +#ifndef DUDP_RECEIVE_TIME + #define DUDP_RECEIVE_TIME 0 +#endif + //#define DUDP_DEBUG_PRINT class DualUDP { @@ -244,6 +249,10 @@ class DualUDP { static uint8_t get_max_attempts() { return DUDP_MAX_RETRIES; }; + /* Returns the recommended receive time for this strategy: */ + + static uint16_t get_receive_time() { return DUDP_RECEIVE_TIME; }; + /* Handle a collision (empty because handled on Ethernet level): */ void handle_collision() { }; diff --git a/src/strategies/ESPNOW/ESPNOW.h b/src/strategies/ESPNOW/ESPNOW.h index 2d3159e47c..d5696c5560 100644 --- a/src/strategies/ESPNOW/ESPNOW.h +++ b/src/strategies/ESPNOW/ESPNOW.h @@ -31,6 +31,11 @@ #define EN_MAX_REMOTE_NODES 10 #endif +// Recommended receive time for this strategy, in microseconds +#ifndef EN_RECEIVE_TIME + #define EN_RECEIVE_TIME 0 +#endif + #define EN_MAGIC_HEADER (uint8_t*)"\xEE\xFE\x0E\xEF" class ESPNOW { @@ -155,6 +160,11 @@ class ESPNOW { static uint8_t get_max_attempts() { return 10; }; + /* Returns the recommended receive time for this strategy: */ + + static uint16_t get_receive_time() { return EN_RECEIVE_TIME; }; + + /* Handle a collision (empty because handled on Ethernet level): */ void handle_collision() { }; diff --git a/src/strategies/EthernetTCP/EthernetTCP.h b/src/strategies/EthernetTCP/EthernetTCP.h index 6984ef3c6b..021d6f60d7 100644 --- a/src/strategies/EthernetTCP/EthernetTCP.h +++ b/src/strategies/EthernetTCP/EthernetTCP.h @@ -24,6 +24,11 @@ #include "EthernetLink.h" #include +// Recommended receive time for this strategy, in microseconds +#ifndef ETCP_RECEIVE_TIME + #define ETCP_RECEIVE_TIME 0 +#endif + class EthernetTCP { public: EthernetLink link; @@ -100,6 +105,13 @@ class EthernetTCP { }; + /* Returns the recommended receive time for this strategy: */ + + static uint16_t get_receive_time() { + return ETCP_RECEIVE_TIME; + }; + + /* Handle a collision (empty because handled on Ethernet level): */ void handle_collision() { }; diff --git a/src/strategies/GlobalUDP/GlobalUDP.h b/src/strategies/GlobalUDP/GlobalUDP.h index 941c02777e..9337a14b4b 100644 --- a/src/strategies/GlobalUDP/GlobalUDP.h +++ b/src/strategies/GlobalUDP/GlobalUDP.h @@ -38,6 +38,11 @@ #define GUDP_MAX_REMOTE_NODES 10 #endif +// Recommended receive time for this strategy, in microseconds +#ifndef GUDP_RECEIVE_TIME + #define GUDP_RECEIVE_TIME 0 +#endif + #define GUDP_DEFAULT_PORT 7000 #define GUDP_MAGIC_HEADER (uint32_t) 0x0DFAC3FF @@ -150,6 +155,11 @@ class GlobalUDP { static uint8_t get_max_attempts() { return 10; }; + /* Returns the recommended receive time for this strategy: */ + + static uint16_t get_receive_time() { return GUDP_RECEIVE_TIME; }; + + /* Handle a collision (empty because handled on Ethernet level): */ void handle_collision() { }; diff --git a/src/strategies/LocalFile/LocalFile.h b/src/strategies/LocalFile/LocalFile.h index 51c8661ba3..7a997e04ad 100644 --- a/src/strategies/LocalFile/LocalFile.h +++ b/src/strategies/LocalFile/LocalFile.h @@ -20,6 +20,11 @@ #define LF_POLLDELAY 10 #endif +// Recommended receive time for this strategy, in microseconds +#ifndef LF_RECEIVE_TIME + #define LF_RECEIVE_TIME 0 +#endif + #define PJON_LF_DEBUG class LocalFile { @@ -233,6 +238,10 @@ class LocalFile { return 10; }; + static uint16_t get_receive_time() { + return LF_RECEIVE_TIME; + }; + uint16_t receive_frame(uint8_t *data, uint16_t max_length) { Record record; if(readNextPacketFromFile(record)) { diff --git a/src/strategies/LocalUDP/LocalUDP.h b/src/strategies/LocalUDP/LocalUDP.h index 0e6a37f85d..807f60f956 100644 --- a/src/strategies/LocalUDP/LocalUDP.h +++ b/src/strategies/LocalUDP/LocalUDP.h @@ -34,6 +34,11 @@ #endif #define LUDP_MAGIC_HEADER (uint32_t) 0x0DFAC3D0 +// Recommended receive time for this strategy, in microseconds +#ifndef LUDP_RECEIVE_TIME + #define LUDP_RECEIVE_TIME 0 +#endif + class LocalUDP { bool _udp_initialized = false; uint16_t _port = LUDP_DEFAULT_PORT; @@ -78,6 +83,11 @@ class LocalUDP { static uint8_t get_max_attempts() { return 10; }; + /* Returns the recommended receive time for this strategy: */ + + static uint16_t get_receive_time() { return LUDP_RECEIVE_TIME; }; + + /* Handle a collision (empty because handled on Ethernet level): */ void handle_collision() { }; diff --git a/src/strategies/MQTTTranslate/MQTTTranslate.h b/src/strategies/MQTTTranslate/MQTTTranslate.h index 0925ab75d2..f82fb788fa 100644 --- a/src/strategies/MQTTTranslate/MQTTTranslate.h +++ b/src/strategies/MQTTTranslate/MQTTTranslate.h @@ -113,6 +113,11 @@ #define MQTTT_TRANSLATION_TABLE_SIZE 5 #endif +// Recommended receive time for this strategy, in microseconds +#ifndef MQTTT_RECEIVE_TIME + #define MQTTT_RECEIVE_TIME 0 +#endif + #if defined(MQTTT_USE_MAC) && ((MQTTT_MODE == MQTTT_MODE_MIRROR_TRANSLATE) || (MQTTT_MODE == MQTTT_MODE_MIRROR_DIRECT)) #define MQTTT_MAC #endif @@ -343,6 +348,11 @@ class MQTTTranslate { static uint8_t get_max_attempts() { return 0; }; + /* Returns the recommended receive time for this strategy: */ + + static uint16_t get_receive_time() { return MQTTT_RECEIVE_TIME; }; + + /* Handle a collision (empty because handled on Ethernet level): */ void handle_collision() { }; diff --git a/src/strategies/OverSampling/OverSampling.h b/src/strategies/OverSampling/OverSampling.h index 986039727e..ef2939e49f 100644 --- a/src/strategies/OverSampling/OverSampling.h +++ b/src/strategies/OverSampling/OverSampling.h @@ -40,6 +40,11 @@ #define OS_MODE 1 #endif +// Recommended receive time for this strategy, in microseconds +#ifndef OS_RECEIVE_TIME + #define OS_RECEIVE_TIME 1000 +#endif + // Used to signal communication failure #define OS_FAIL 65535 @@ -95,6 +100,13 @@ class OverSampling { }; + /* Returns the recommended receive time for this strategy: */ + + static uint16_t get_receive_time() { + return OS_RECEIVE_TIME; + }; + + /* Handle a collision: */ void handle_collision() { diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index 2c06e69e32..415b1dc506 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -39,6 +39,11 @@ MODE 4: 3.40kB/s - 27210Bd */ #include "Timing.h" +// Recommended receive time for this strategy, in microseconds +#ifndef SWBB_RECEIVE_TIME + #define SWBB_RECEIVE_TIME 1000 +#endif + class SoftwareBitBang { public: /* Returns the delay related to the attempts passed as parameter: */ @@ -89,6 +94,13 @@ class SoftwareBitBang { }; + /* Returns the recommended receive time for this strategy: */ + + static uint16_t get_receive_time() { + return SWBB_RECEIVE_TIME; + }; + + /* Handle a collision: */ void handle_collision() { diff --git a/src/strategies/ThroughLoRa/ThroughLora.h b/src/strategies/ThroughLoRa/ThroughLora.h index bfe86bf6b4..b92e129472 100644 --- a/src/strategies/ThroughLoRa/ThroughLora.h +++ b/src/strategies/ThroughLoRa/ThroughLora.h @@ -23,6 +23,11 @@ #include #include "Timing.h" +// Recommended receive time for this strategy, in microseconds +#ifndef TL_RECEIVE_TIME + #define TL_RECEIVE_TIME 0 +#endif + class ThroughLora { public: /* Returns the suggested delay related to the attempts @@ -117,6 +122,12 @@ class ThroughLora { return TL_MAX_ATTEMPTS; }; + /* Returns the recommended receive time for this strategy: */ + + static uint16_t get_receive_time() { + return TL_RECEIVE_TIME; + }; + /* Handle a collision: */ void handle_collision() { diff --git a/src/strategies/ThroughSerial/ThroughSerial.h b/src/strategies/ThroughSerial/ThroughSerial.h index abb195913f..27f4c8a1f6 100644 --- a/src/strategies/ThroughSerial/ThroughSerial.h +++ b/src/strategies/ThroughSerial/ThroughSerial.h @@ -51,6 +51,11 @@ enum TS_state_t : uint8_t { TS_DONE }; +// Recommended receive time for this strategy, in microseconds +#ifndef TS_RECEIVE_TIME + #define TS_RECEIVE_TIME 0 +#endif + class ThroughSerial { public: uint8_t buffer[PJON_PACKET_MAX_LENGTH] = {0}; @@ -98,6 +103,13 @@ class ThroughSerial { }; + /* Returns the recommended receive time for this strategy: */ + + static uint16_t get_receive_time() { + return TS_RECEIVE_TIME; + }; + + /* Handle a collision: */ void handle_collision() { From e16ec0e167c077d8bcc9ae52c26ab29eea4872c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 5 Jun 2020 16:20:38 +0200 Subject: [PATCH 069/323] rx bus id was not copied in the new send_packet_blocking --- src/PJON.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PJON.h b/src/PJON.h index 2b7b8152da..ca87f540c2 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -664,6 +664,7 @@ class PJON { uint32_t timeout = 3500000 ) { PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); + PJONTools::copy_id(info.rx.bus_id, rx_bus_id, 4); return send_packet_blocking(info, payload, length, timeout); }; From dc2e9e6fbc3c8a6aa3aa2be0687589fe05a94b74 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 6 Jun 2020 00:46:07 +0200 Subject: [PATCH 070/323] PJON.h reply hop fix --- src/PJON.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/PJON.h b/src/PJON.h index ca87f540c2..7669c41c25 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -450,6 +450,9 @@ class PJON { info = last_packet_info; info.rx = info.tx; info.header = config; + #ifndef PJON_LOCAL + info.hops = 0; + #endif return dispatch(info, payload, length); }; @@ -495,7 +498,9 @@ class PJON { ) { PJON_Endpoint original_end_point = tx; tx = info.tx; - if(++info.hops > PJON_MAX_HOPS) return PJON_FAIL; + #ifndef PJON_LOCAL + if(++info.hops > PJON_MAX_HOPS) return PJON_FAIL; + #endif uint16_t result = PJON_FAIL; #if(PJON_MAX_PACKETS > 0) result = dispatch(info, payload, length); From 5f223f92cb751b7144b50b0c5041c7f650bf1ec4 Mon Sep 17 00:00:00 2001 From: fredilarsen Date: Sat, 6 Jun 2020 01:10:35 +0200 Subject: [PATCH 071/323] Routing related improvements and new example --- .../Switch/BlinkingSwitch/BlinkingSwitch.ino | 10 +++++-- .../Network/Switch/Device1/Device1.ino | 11 +++++++- .../Network/Switch/Device2/Device2.ino | 1 - .../Switch/SimpleSwitch/SimpleSwitch.ino | 26 +++++++++++++++++++ .../ARDUINO/Network/Switch/Switch/Switch.ino | 4 +++ src/PJONSimpleSwitch.h | 6 +++-- 6 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino diff --git a/examples/routing/ARDUINO/Network/Switch/BlinkingSwitch/BlinkingSwitch.ino b/examples/routing/ARDUINO/Network/Switch/BlinkingSwitch/BlinkingSwitch.ino index d24c21f71c..546ee4680e 100644 --- a/examples/routing/ARDUINO/Network/Switch/BlinkingSwitch/BlinkingSwitch.ino +++ b/examples/routing/ARDUINO/Network/Switch/BlinkingSwitch/BlinkingSwitch.ino @@ -1,7 +1,13 @@ -/* This sketch is just the Router example with a user defined receive callback. +/* This sketch is just the Switch example with a user defined receive callback. It demonstrates how to spy on the packets being routed by a switch or router object. - In this case it just makes the on-board LED blink for every packet that passes. */ + In this case it just makes the on-board LED blink for every packet that passes. + + Note that the default basis for the PJONInteractiveRouter is PJONSwitch, + but that you can specify to use PJONRouter, PJONDynamicRouter or + PJONVirtualBusRouter instead by adding the class as an additional + template parameter, to get additional functionality. + */ #include diff --git a/examples/routing/ARDUINO/Network/Switch/Device1/Device1.ino b/examples/routing/ARDUINO/Network/Switch/Device1/Device1.ino index 6474f95331..7ff0ec3ee4 100644 --- a/examples/routing/ARDUINO/Network/Switch/Device1/Device1.ino +++ b/examples/routing/ARDUINO/Network/Switch/Device1/Device1.ino @@ -21,11 +21,14 @@ void setup() { bus.strategy.set_pin(7); bus.set_receiver(receiver_function); bus.begin(); - bus.send_repeatedly(45, remote_bus_id, "B", 1, 250000); + bus.send(45, remote_bus_id, "B", 1); } +uint32_t last_incoming = 0; // Time of last incoming packet + void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { if((char)payload[0] == 'B') { + last_incoming = millis(); static bool led_on = false; digitalWrite(LED_BUILTIN, led_on ? HIGH : LOW); led_on = !led_on; @@ -35,4 +38,10 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info void loop() { bus.receive(1000); bus.update(); + + // Send a reply 1 second after receiving a packet + if (last_incoming != 0 && (uint32_t)(millis() - last_incoming) > 1000) { + bus.reply("B", 1); + last_incoming = 0; + } } diff --git a/examples/routing/ARDUINO/Network/Switch/Device2/Device2.ino b/examples/routing/ARDUINO/Network/Switch/Device2/Device2.ino index d3cca2cf7e..7dad8823b2 100644 --- a/examples/routing/ARDUINO/Network/Switch/Device2/Device2.ino +++ b/examples/routing/ARDUINO/Network/Switch/Device2/Device2.ino @@ -22,7 +22,6 @@ void setup() { bus.strategy.set_pin(12); bus.set_receiver(receiver_function); bus.begin(); - bus.send(44, remote_bus_id, "B", 1); } void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino b/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino new file mode 100644 index 0000000000..7b6bad2311 --- /dev/null +++ b/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino @@ -0,0 +1,26 @@ +#include + +/* Route packets between a collection of buses with the same + or different strategies or media. + + PJONSimpleSwitch routes between buses of the same strategy. + It uses less storage and RAM than the more general PJONSwitch. + __________ ________ __________ + | | Pin 7 | | Pin 12 | | + | DEVICE 1 |_______________| SWITCH |_______________| DEVICE 2 | + |__________| Bus 0.0.0.1 |________| Bus 0.0.0.2 |__________| */ + +PJON bus1((const uint8_t[4]){0, 0, 0, 1}, PJON_NOT_ASSIGNED), + bus2((const uint8_t[4]){0, 0, 0, 2}, PJON_NOT_ASSIGNED); + +PJONSimpleSwitch router(bus1, bus2); + +void setup() { + bus1.strategy.set_pin(7); + bus2.strategy.set_pin(12); + router.begin(); +} + +void loop() { + router.loop(); +} diff --git a/examples/routing/ARDUINO/Network/Switch/Switch/Switch.ino b/examples/routing/ARDUINO/Network/Switch/Switch/Switch.ino index 5ffbcbf664..7983d87c1d 100644 --- a/examples/routing/ARDUINO/Network/Switch/Switch/Switch.ino +++ b/examples/routing/ARDUINO/Network/Switch/Switch/Switch.ino @@ -2,6 +2,10 @@ /* Route packets between a collection of buses with the same or different strategies or media. + + PJONSwitch can route between buses of different strategies, + though not shown here. If using only one strategy, some + resources can be saved by using PJONSimpleSwitch instead. __________ ________ __________ | | Pin 7 | | Pin 12 | | | DEVICE 1 |_______________| SWITCH |_______________| DEVICE 2 | diff --git a/src/PJONSimpleSwitch.h b/src/PJONSimpleSwitch.h index b5eba4859b..84e78264b9 100644 --- a/src/PJONSimpleSwitch.h +++ b/src/PJONSimpleSwitch.h @@ -236,7 +236,8 @@ class PJONSimpleSwitch { PJON &bus1, uint8_t default_gateway = PJON_NOT_ASSIGNED ) { - connect_buses(2, (PJON*[2]){&bus0, &bus1}, default_gateway); + PJON *buses[2] = { &bus0, &bus1 }; + connect_buses(2, buses, default_gateway); }; // Specialized constructor to simplify syntax when using 3 buses @@ -246,7 +247,8 @@ class PJONSimpleSwitch { PJON &bus2, uint8_t default_gateway = PJON_NOT_ASSIGNED ) { - connect_buses(3, (PJON*[3]){&bus0, &bus1, &bus2}, default_gateway); + PJON *buses[3] = { &bus0, &bus1, &bus2 }; + connect_buses(3, buses, default_gateway); }; void begin() { From 93f8daa568d16f2e429a1e23b6f92b14567cc8fb Mon Sep 17 00:00:00 2001 From: fredilarsen Date: Sat, 6 Jun 2020 01:23:58 +0200 Subject: [PATCH 072/323] Got rid of unused variable compiler warnings --- src/PJONSimpleSwitch.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/PJONSimpleSwitch.h b/src/PJONSimpleSwitch.h index 84e78264b9..1ea4e3e646 100644 --- a/src/PJONSimpleSwitch.h +++ b/src/PJONSimpleSwitch.h @@ -89,7 +89,7 @@ class PJONSimpleSwitch { uint8_t find_attached_bus_with_id( const uint8_t *bus_id, - const uint8_t device_id, + const uint8_t /*device_id*/, uint8_t &start_bus ) { for(uint8_t i=start_bus; iforward( + #if PJON_MAX_PACKETS == 0 + uint16_t result = + #endif + buses[receiver_bus]->forward( p_info, (const uint8_t *)payload, length); From ce04d3ff78ef34502e379085679990565e219757 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 6 Jun 2020 16:29:56 +0200 Subject: [PATCH 073/323] PJONRouter avoid compiler warning --- src/PJONRouter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PJONRouter.h b/src/PJONRouter.h index 0c508f8ef8..ed45e6a819 100644 --- a/src/PJONRouter.h +++ b/src/PJONRouter.h @@ -56,7 +56,7 @@ class PJONRouter : public PJONSwitch { uint8_t find_bus_in_table( const uint8_t *bus_id, - const uint8_t device_id, + const uint8_t /* device_id */, uint8_t &start_bus ) { uint8_t start = start_bus - bus_count; From 8c831f5a92fe03ccc6631a3867d671cf4f1cfa71 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 6 Jun 2020 16:37:42 +0200 Subject: [PATCH 074/323] PJONInteractiveRouter set_sendnotification -> set_send_notification --- .../Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino | 4 ++-- src/PJONInteractiveRouter.h | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino b/examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino index 8a7c58afa9..b0cfe6bbe4 100644 --- a/examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino +++ b/examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino @@ -22,14 +22,14 @@ uint32_t error_on_time = 0, swbb_on_time = 0, ludp_on_time = 0; void error_handler(uint8_t code, uint16_t data, void *custom_ptr) { digitalWrite(ERROR_LED_PIN, HIGH); - error_on_time = millis(); + error_on_time = millis(); } void setup() { while (Ethernet.begin(mac) == 0) delay(5000); // Wait for DHCP response router.get_strategy_0().set_pin(7); router.get_strategy_1().set_port(7200); // Use a "private" UDP port - router.set_sendnotification(sendnotification_function); + router.set_send_notification(sendnotification_function); router.set_error(error_handler); router.set_virtual_bus(0); // Enable virtual bus router.begin(); diff --git a/src/PJONInteractiveRouter.h b/src/PJONInteractiveRouter.h index 890dc21cc5..7810cc5efb 100644 --- a/src/PJONInteractiveRouter.h +++ b/src/PJONInteractiveRouter.h @@ -50,7 +50,7 @@ limitations under the License. */ #include #include -typedef void (* PJON_SendNotification)( +typedef void (* PJON_Send_Notification)( const uint8_t * const payload, const uint16_t length, const uint8_t receiver_bus, @@ -64,7 +64,7 @@ class PJONInteractiveRouter : public RouterClass { void *custom_pointer = NULL; PJON_Receiver receiver = NULL; PJON_Error error = NULL; - PJON_SendNotification sendnotification = NULL; + PJON_Send_Notification send_notification = NULL; bool router = false; virtual void dynamic_receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { @@ -105,7 +105,7 @@ class PJONInteractiveRouter : public RouterClass { RouterClass::send_packet(payload, length, receiver_bus, sender_bus, ack_sent, packet_info); // Call any user registered send notification function - if (sendnotification) sendnotification(payload, length, receiver_bus, sender_bus, packet_info); + if (send_notification) send_notification(payload, length, receiver_bus, sender_bus, packet_info); } public: @@ -120,7 +120,7 @@ class PJONInteractiveRouter : public RouterClass { void set_error(PJON_Error e) { error = e; }; - void set_sendnotification(PJON_SendNotification s) { sendnotification = s; }; + void set_send_notification(PJON_Send_Notification s) { send_notification = s; }; void set_custom_ptr(void *custom_ptr) { custom_pointer = custom_ptr; }; @@ -177,4 +177,4 @@ class PJONInteractiveRouter3 : public PJONInteractiveRouter { A &get_strategy_0() { return linkA.strategy; } B &get_strategy_1() { return linkB.strategy; } C &get_strategy_2() { return linkC.strategy; } -}; \ No newline at end of file +}; From ea0fdb90e13176d90c746cf83c6415e0750150df Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 6 Jun 2020 22:21:37 +0200 Subject: [PATCH 075/323] PJONSimpleSwitch documentation update --- documentation/routing.md | 66 +++++++++++----------------------------- 1 file changed, 17 insertions(+), 49 deletions(-) diff --git a/documentation/routing.md b/documentation/routing.md index 1f88ac6252..881a6ebb19 100644 --- a/documentation/routing.md +++ b/documentation/routing.md @@ -11,76 +11,44 @@ --- ## Routing -Transparent routing based on a tree topology has been implemented by Fred Larsen with the [PJONSimpleSwitch](#simpleswitch), [PJONSwitch](#switch), [PJONRouter](#router), [PJONDynamicRouter](#dynamicrouter), [PJONInteractiveRouter](#interactiverouter) and [PJONVirtualBusRouter](#virtual-bus). +Transparent routing based on a tree topology that may include loops has been implemented by Fred Larsen with the [PJONSimpleSwitch](#simpleswitch), [PJONSwitch](#switch), [PJONRouter](#router), [PJONDynamicRouter](#dynamicrouter), [PJONInteractiveRouter](#interactiverouter) and [PJONVirtualBusRouter](#virtual-bus). ### SimpleSwitch -The [PJONSimpleSwitch](/examples/ARDUINO/Local/SoftwareBitBang/Switch/SimpleSwitch) class connects two buses using the same strategy. In this example a `SoftwareBitBang` <=> `SoftwareBitBang` switch is created. It can be used to amplify signals and so extend the maximum range or in more complex setups selectively switch packets as requested by its configuration. It can be used instead of `PJONSwitch` to save memory when the same strategy is used in all buses. It avoids virtual inheritance so it is faster and has a smaller footprint. +The [PJONSimpleSwitch](/examples/routing/Network/Switch/SimpleSwitch/SimpleSwitch.ino) class connects two or more buses using the same strategy. In this example a `SoftwareBitBang` <=> `SoftwareBitBang` switch is created. It can be used to amplify signals and so extend the maximum range or in more complex setups selectively switch packets as requested by its configuration. It can be used instead of `PJONSwitch` to save memory when the same strategy is used in all buses. It avoids virtual inheritance so it is faster and has a smaller footprint. ```cpp - __________ ________ __________ -| | SWBB bus | | SWBB bus | | -| DEVICE 1 |___________| SWITCH |____________| DEVICE 2 | -|__________| |________| |__________| +/* __________ ________ __________ + | | Pin 7 | | Pin 12 | | + | DEVICE 1 |_______________| SWITCH |_______________| DEVICE 2 | + |__________| Bus 0.0.0.1 |________| Bus 0.0.0.2 |__________| */ + ``` The first thing to do is to include the `PJONSimpleSwitch` class: ```cpp #include ``` -The `SimpleSwitch` class provides with configurable transparent packet switching between buses using the same strategy. `SimpleSwitch` requires a tree topology (it does not contain any loop detection procedure). The `SimpleSwitch` class receives as a parameter the length and the array of 2 or more `PJONBus` instances: -```cpp -/* In both cases the switch does not have an assigned id it is - transparently switching packets in both directions */ -PJONBus bus1(PJON_NOT_ASSIGNED); -PJONBus bus2(PJON_NOT_ASSIGNED); -``` -Polling time can be optionally configured: -```cpp -PJONBus bus2( - PJON_NOT_ASSIGNED, // Switch device id - 1000 // Polling time in microseconds -); -``` -Device id ranges can be optionally configured: -```cpp -PJONBus bus2( - PJON_NOT_ASSIGNED, // Switch device id - 1000, // Polling time in microseconds - 2, // 2 ranges present (1-127, 128-254) - 0, // range 1 in use here (1-127) -); -``` -After the `PJONBus` definitions, a `PJONSimpleSwitch` instance can be created: -```cpp -// PJONSimpleSwitch definition: -PJONSimpleSwitch router( - 2, // Length of the bus array - (PJONBus*[2]){&bus1,&bus2} // Bus array -); -``` -A default gateway can be optionally configured: +The `SimpleSwitch` class provides with configurable transparent packet switching between buses using the same strategy: ```cpp -PJONSimpleSwitch router( - 2, // Length of the bus array - (PJONBus*[2]){&bus1,&bus2}, // Bus array - 122 // Statically defined default gateway device id -); +PJON bus1((const uint8_t[4]){0, 0, 0, 1}, PJON_NOT_ASSIGNED), + bus2((const uint8_t[4]){0, 0, 0, 2}, PJON_NOT_ASSIGNED); + +PJONSimpleSwitch router(bus1, bus2); + ``` -Configure each strategy and the `router` instance as required: +In the example above two PJON instances using SoftwareBitBang, operating in shared mode, with bus id `0.0.0.1` and `0.0.0.2` are merged with the `SimpleSwitch` instance. Packets are switched between the two buses. In the `setup` just include strategy related configuration, for example the pin used for communication: + ```cpp void setup() { - // Set each SoftwareBitBang bus pin connection bus1.strategy.set_pin(7); bus2.strategy.set_pin(12); router.begin(); } -``` -Call the `loop` function as often as possible to achieve optimal performance: -```cpp void loop() { router.loop(); -}; +} ``` +Then the `PJONSimpleSwitch` should work transparently. `PJONSimpleSwitch` can be used also in local mode although, because the hop count field is not included, the network topology cannot include loops. ### Switch The [PJONSwitch](/examples/ARDUINO/Local/SoftwareBitBang/Switch/Switch) class transparently switches packets between locally attached buses also if different strategies or media are in use. It supports a default gateway to be able to act as a leaf in a larger network setup. Thanks to the `PJONSwitch` class, with few lines of code, a switch that operates multiple strategies can be created. In this example a `SoftwareBitBang` <=> `AnalogSampling` switch is created: From bca33ce3f6e8648fd2634a528d16e1ce7a09f9f9 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 6 Jun 2020 22:37:31 +0200 Subject: [PATCH 076/323] forward and forward_blocking splitted, PJONSimpleSwitch update --- src/PJON.h | 33 ++++++++++++---- src/PJONSimpleSwitch.h | 88 +++++++++++++++++++++++++++--------------- 2 files changed, 83 insertions(+), 38 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 7669c41c25..84e6759a6a 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -81,10 +81,13 @@ class PJON { uint8_t config = PJON_TX_INFO_BIT | PJON_ACK_REQ_BIT; uint8_t data[PJON_PACKET_MAX_LENGTH]; PJON_Packet_Info last_packet_info; - PJON_Packet packets[PJON_MAX_PACKETS]; uint8_t random_seed = A0; PJON_Endpoint tx; + #if(PJON_MAX_PACKETS > 0) + PJON_Packet packets[PJON_MAX_PACKETS]; + #endif + #if(PJON_INCLUDE_PACKET_ID) PJON_Packet_Record recent_packet_ids[PJON_MAX_RECENT_PACKET_IDS]; #endif @@ -485,7 +488,11 @@ class PJON { return dispatch(info, payload, length); }; - uint16_t send(const PJON_Packet_Info &info, const void *payload, uint16_t length) { + uint16_t send( + const PJON_Packet_Info &info, + const void *payload, + uint16_t length + ) { return dispatch(info, payload, length); }; @@ -501,12 +508,24 @@ class PJON { #ifndef PJON_LOCAL if(++info.hops > PJON_MAX_HOPS) return PJON_FAIL; #endif - uint16_t result = PJON_FAIL; - #if(PJON_MAX_PACKETS > 0) - result = dispatch(info, payload, length); + uint16_t result = dispatch(info, payload, length); + tx = original_end_point; + return result; + }; + + /* Forward a packet: */ + + uint16_t forward_blocking( + PJON_Packet_Info info, + const void *payload, + uint16_t length + ) { + PJON_Endpoint original_end_point = tx; + tx = info.tx; + #ifndef PJON_LOCAL + if(++info.hops > PJON_MAX_HOPS) return PJON_FAIL; #endif - if(result == PJON_FAIL) - result = send_packet_blocking(info, payload, length); + uint16_t result = send_packet_blocking(info, payload, length); tx = original_end_point; return result; }; diff --git a/src/PJONSimpleSwitch.h b/src/PJONSimpleSwitch.h index 1ea4e3e646..06fc598b62 100644 --- a/src/PJONSimpleSwitch.h +++ b/src/PJONSimpleSwitch.h @@ -16,7 +16,7 @@ PJONSimpleSwitch has been contributed by Fred Larsen. It routes packets between buses with different bus ids, and also between -local buses with no bus ids. It is limited to one single strategy in contrast +local buses with no bus ids. It is limited to one single strategy in contrast to its descendant PJONSwitch. A default gateway can be specified, identifying one of the attached buses to @@ -118,13 +118,14 @@ class PJONSimpleSwitch { ack_sent = true; } - // Set current_bus to receiver bus before potentially calling error callback for that bus + /* Set current_bus to receiver bus before potentially calling error + callback for that bus */ uint8_t send_bus = current_bus; current_bus = receiver_bus; - // NAT support: If a shared packet comes from a local bus destined to a - // non-local receiver, then put the NAT address of the bus as the sender - // bus id so that replies can find the route back via NAT. + /* NAT support: If a shared packet comes from a local bus destined to a + non-local receiver, then put the NAT address of the bus as the sender + bus id so that replies can find the route back via NAT. */ PJON_Packet_Info p_info = packet_info; if ((packet_info.header & PJON_MODE_BIT) && !(buses[sender_bus]->config & PJON_MODE_BIT) && @@ -134,9 +135,9 @@ class PJONSimpleSwitch { memcpy(&p_info.tx.bus_id, buses[sender_bus]->tx.bus_id, 4); } - // NAT support: If a shared packet comes with receiver bus id matching the - // NAT address of a local bus, then change the receiver bus id to 0.0.0.0 - // before forwarding the shared packet to the local bus. + /* NAT support: If a shared packet comes with receiver bus id matching the + NAT address of a local bus, then change the receiver bus id to 0.0.0.0 + before forwarding the shared packet to the local bus. */ if ((packet_info.header & PJON_MODE_BIT) && !(buses[receiver_bus]->config & PJON_MODE_BIT) && memcmp(buses[receiver_bus]->tx.bus_id, PJONTools::localhost(), 4)!=0 && @@ -145,30 +146,44 @@ class PJONSimpleSwitch { memcpy(p_info.rx.bus_id, PJONTools::localhost(), 4); } - // Forward the packet + uint16_t result = #if PJON_MAX_PACKETS == 0 - uint16_t result = - #endif - buses[receiver_bus]->forward( - p_info, - (const uint8_t *)payload, - length); - - #if PJON_MAX_PACKETS == 0 - // Call error function explicitly, because that will not be done while sending - // when PJON_MAX_PACKETS=0. - if (result == PJON_FAIL) dynamic_error_function(PJON_CONNECTION_LOST, 0); + buses[receiver_bus]->forward_blocking( + p_info, + (const uint8_t *)payload, + length + ); + /* Call error function explicitly, because it is not called by + forward_blocking */ + if(result == PJON_FAIL) dynamic_error_function(PJON_CONNECTION_LOST, 0); + #else + buses[receiver_bus]->forward( + p_info, + (const uint8_t *)payload, + length + ); #endif current_bus = send_bus; } - void forward_packet(const uint8_t *payload, const uint16_t length, - const uint8_t receiver_bus, const uint8_t sender_bus, - bool &ack_sent, const PJON_Packet_Info &packet_info) { + void forward_packet( + const uint8_t *payload, + const uint16_t length, + const uint8_t receiver_bus, + const uint8_t sender_bus, + bool &ack_sent, + const PJON_Packet_Info &packet_info + ) { // If receiving bus matches and not equal to sending bus, then route packet - if(receiver_bus != PJON_NOT_ASSIGNED && receiver_bus != sender_bus) { - send_packet(payload, length, receiver_bus, sender_bus, ack_sent, packet_info); - } + if(receiver_bus != PJON_NOT_ASSIGNED && receiver_bus != sender_bus) + send_packet( + payload, + length, + receiver_bus, + sender_bus, + ack_sent, + packet_info + ); } #ifdef PJON_ROUTER_NEED_INHERITANCE @@ -191,7 +206,7 @@ class PJONSimpleSwitch { const PJON_Packet_Info &packet_info ) { uint8_t start_search = 0; - bool ack_sent = false; // Send ACK only once even if delivering copies to multiple buses + bool ack_sent = false; // Send ACK once even if delivering to multiple buses do { uint8_t receiver_bus = find_bus_with_id((const uint8_t*) ((packet_info.header & PJON_MODE_BIT) != 0 ? @@ -211,7 +226,14 @@ class PJONSimpleSwitch { if(receiver_bus == PJON_NOT_ASSIGNED) receiver_bus = default_gateway; - forward_packet(payload, length, receiver_bus, current_bus, ack_sent, packet_info); + forward_packet( + payload, + length, + receiver_bus, + current_bus, + ack_sent, + packet_info + ); } while(start_search != PJON_NOT_ASSIGNED); }; @@ -261,7 +283,9 @@ class PJONSimpleSwitch { void loop() { for(current_bus = 0; current_bus < bus_count; current_bus++) { uint16_t code = - buses[current_bus]->receive(buses[current_bus]->strategy.get_receive_time()); + buses[current_bus]->receive( + buses[current_bus]->strategy.get_receive_time() + ); if(PJON_MAX_PACKETS < bus_count && code == PJON_ACK) break; } for(current_bus = 0; current_bus < bus_count; current_bus++) @@ -306,7 +330,9 @@ class PJONSimpleSwitch { } static void error_function(uint8_t code, uint16_t data, void *custom_pointer) { - ((PJONSimpleSwitch*)custom_pointer)->dynamic_error_function(code, data); + ((PJONSimpleSwitch*)custom_pointer)->dynamic_error_function( + code, + data + ); } }; - From f3778f6e8149f5068ac6ddfe0b3f992c6bf1e831 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Jun 2020 15:45:22 +0200 Subject: [PATCH 077/323] packets always defined --- src/PJON.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 84e6759a6a..8682304df8 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -81,13 +81,10 @@ class PJON { uint8_t config = PJON_TX_INFO_BIT | PJON_ACK_REQ_BIT; uint8_t data[PJON_PACKET_MAX_LENGTH]; PJON_Packet_Info last_packet_info; + PJON_Packet packets[PJON_MAX_PACKETS]; uint8_t random_seed = A0; PJON_Endpoint tx; - #if(PJON_MAX_PACKETS > 0) - PJON_Packet packets[PJON_MAX_PACKETS]; - #endif - #if(PJON_INCLUDE_PACKET_ID) PJON_Packet_Record recent_packet_ids[PJON_MAX_RECENT_PACKET_IDS]; #endif From c2dde55e3d0d20d6b892321715438052749845f9 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Jun 2020 16:54:40 +0200 Subject: [PATCH 078/323] documentation/data-transmission update --- documentation/data-transmission.md | 140 ++++++++++++++++------------- 1 file changed, 79 insertions(+), 61 deletions(-) diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index ac40cc2f9d..8bc1fbce6f 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -11,67 +11,69 @@ --- ## Data transmission -The begin function must be called before starting communication, the lack of this call can lead to collisions after boot, so be sure to call it before making use of the instance. +### `begin` +The begin method must be called before starting communication, the lack of this call can lead to collisions after boot, so be sure not to forget it. ```cpp bus.begin(); ``` -The simplest way to send data is to use `send_packet`, this method composes the packet and tries to send it once. The first parameter is the device id of the recipient of type `uint8_t`, optionally you can pass the bus id of type `uint8_t *`, then follows the payload of type `const void *` and its length of type `uint16_t`. This call implies a single attempt and has no guarantee of success, but logs the result of the attempted transmission: +### `send_packet` +The simplest way to send data is to use `send_packet`, this method composes the packet and tries to send it once. Consider that if the bus is busy or interference is present the transmission may not be attempted. The method returns the result of its operation. The first parameter is the device id of the recipient of type `uint8_t` then follows the payload of type `const void *` and its length of type `uint16_t`. This call implies a single attempt and has no guarantee of success, but logs the result of the attempted transmission: ```cpp -// Local - // Send to device id 10 the string "Hi!" bus.send_packet(10, "Hi!", 3); - +``` +The payload length is boring to be added in each call but is there to prevent buffer overflow. If sending arbitrary values `NULL` terminator strategy based on `strlen` is not safe to detect the end of a string. The `send` method can receive other 3 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id and including the port `8002`. +```cpp // All optional parameters available bus.send_packet( 10, // Device id (uint8_t) "Hello", // Payload (const void *) - 12, // Length (uint16_t) + 5, // Length (uint16_t) bus.config, // Header (uint8_t) - Use default config 0, // Packet id (uint16_t) - Don't include packet id 8002 // Port (uint16_t) ); +``` -// Shared or using bus indexing - -// Send to bus id 0.0.0.1 - device id 10 the string "Hi!" +If you need to transmit data in shared mode you can use the same `send_packet` method including also the bus id. In the example below a packet containing the payload "Hi!" is sent to device id 10: +```cpp +// Send to bus id 0.0.0.1 uint8_t bus_id[] = {0, 0, 0, 1}; bus.send_packet(10, bus_id, "Hi!", 3); - +``` +As its local version, `send_packet` can receive other 3 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id and including the port `8002`. +```cpp // All optional parameters available bus.send_packet( 10, // Device id (uint8_t) bus_id, // Bus id (uint8_t *) "Hello", // Payload (const void *) - 12, // Length (uint16_t) + 5, // Length (uint16_t) bus.config, // Header (uint8_t) - Use default config 0, // Packet id (uint16_t) - Don't include packet id 8002 // Port (uint16_t) ); ``` -The sending is executed as soon as the method is called and it returns the following values: + +When using `send_packet` the transmission may occur as soon as the method is called and it returns the following values: - `PJON_ACK` (6) if transmission occurred and acknowledgement is received if requested - `PJON_BUSY` (666) if bus is busy - `PJON_FAIL` (65535) if transmission failed +The `send_packet` result, of type `uint16_t`, can be used to determine if the transmission occurred successfully or not: ```cpp -// Use the value returned by send_packet to determine transmission result +uint16_t result = bus.send_packet(10, "All is ok?!", 11); -// Local -if(bus.send_packet(10, "All is ok?!", 11) == PJON_ACK) - Serial.println("10 is ok!"); - -// Shared or using bus indexing -if(bus.send_packet(10, bus_id, "All is ok?!", 11) == PJON_ACK) - Serial.println("10 is ok!"); +if(result == PJON_ACK) Serial.println("10 is ok!"); ``` To broadcast a message to all connected devices, use the `PJON_BROADCAST` constant as recipient ID: ```cpp bus.send_packet(PJON_BROADCAST, "Message for all connected devices.", 34); ``` +### `send_packet_blocking` +Use `send_packet_blocking` if it is necessary to try until the packet is effectively received by the recipient or a maximum amount of retries is reached. Consider that the method may block the operation of the program for up to 4 seconds in case of transmission failure. -Use `send_packet_blocking` if it is necessary to try until the packet is effectively received by the recipient and so comply with the specified back-off. ```cpp // Send to device id 10 the string "Hi!" bus.send_packet_blocking(10, "Hi!", 3); @@ -80,46 +82,61 @@ bus.send_packet_blocking(10, "Hi!", 3); if(bus.send_packet_blocking(10, "All is ok?!", 11) == PJON_ACK) Serial.println("10 is ok!"); ``` -`send_packet_blocking` returns the result of transmission as `send_packet` does. +`send_packet_blocking` optional parameters and return values are the same as `send_packet`. -PJON can also optionally handle packets for you, although a little more memory is required. The first thing to do and never forget is to call the `update()` function once per loop cycle: +### `send` + +When using the `send` method, PJON operates using its internal buffer, although a little more memory is required. The first thing to do and never forget is to call the `update()` method once per loop cycle: ```cpp bus.update(); ``` -To send data to another device connected to the bus simply call `send` passing the recipient's id (and its bus id if necessary), the payload you want to send and its length: +Every time `update` is called the transmission is attempted for each packet present in the buffer. + +One way to insert packets in the buffer is to use the `send` method. To send data to another device connected to the bus simply call `send` passing the device id of the recipient of type `uint8_t` then the payload of type `const void *` and its length of type `uint16_t`. The return value of `send` is of type `uint16_t` and it is the id of the packet in the buffer or `PJON_FAIL` in case of error. ```cpp -// Local bus.send(100, "Ciao, this is a test!", 21); - -// Shared or using bus indexing -uint8_t bus_id[] = {0, 0, 0, 1}; -bus.send(100, bus_id, "Ciao, this is a test!", 21); - -// All optional parameters available - -// Local mode +``` +`send` can receive 3 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 2 using the actual instance's header configuration, without including the packet id and including the port `8002`: +```cpp +// Shared mode or using bus indexing bus.send( - 100, // (uint8_t) Recipient device id - "Test port id", // (const void *) Payload - 23, // (uint16_t) Length - bus.config, // (uint8_t) Packet header - 1, // (uint16_t) Packet id - 8002 // (uint16_t) Port identification + 2, // (uint8_t) Recipient device id + "Hello", // (const void *) Payload + 5, // (uint16_t) Length + bus.config, // (uint8_t) Packet header + 0, // (uint16_t) Packet id + 8002 // (uint16_t) Port identification ); +``` +`send` can be used in shared mode passing the bus id after the device id: +```cpp +uint8_t bus_id[] = {0, 0, 0, 1}; +bus.send(100, bus_id, "Ciao, this is a test!", 21); +``` +`send` can receive 3 optional parameters also when used in shared mode, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 2 using the actual instance's header configuration, without including the packet id and including the port `8002`: +```cpp // Shared mode or using bus indexing bus.send( - 100, // (uint8_t) Recipient device id - bus_id, // (uint8_t *) Recipient bus id - "Test port id", // (const void *) Payload - 23, // (uint16_t) Length - bus.config, // (uint8_t) Packet header - 1, // (uint16_t) Packet id - 8002 // (uint16_t) Port identification + 2, // (uint8_t) Recipient device id + bus_id, // (uint8_t *) Recipient bus id + "Hello", // (const void *) Payload + 5, // (uint16_t) Length + bus.config, // (uint8_t) Packet header + 0, // (uint16_t) Packet id + 8002 // (uint16_t) Port identification ); ``` -Payload length is boring to be added but is there to prevent buffer overflow. If sending arbitrary values `NULL` terminator strategy based on `strlen` is not safe to detect the end of a string. The `send` call returns an id, that is the reference to the packet you have dispatched. To send a value repeatedly simply call `send_repeatedly` and pass as last parameter the interval in microseconds you want between every sending: +To use the return value of `send` just save it in a variable of type `uint16_t`: +```cpp +uint16_t packet = bus.send(100, "Ciao, this is a test!", 21); + +if(packet == PJON_FAIL) Serial.print("Something went wrong"); +``` + +### `send_repeatedly` +The `send_repeatedly` method can be used when it is required to schedule a repeated sending with a given interval. The first parameter is the device id of the recipient of type `uint8_t` then follows the payload of type `const void *`, its length of type `uint16_t` and the interval of type `uint32_t`: ```cpp // Local sending example uint16_t one_second_test = @@ -127,20 +144,21 @@ uint16_t one_second_test = /* IMPORTANT: maximum interval supported is 4293014170 microseconds or 71.55 minutes */ -// Shared sending example including all optional parameters -uint16_t one_second_test_shared = - bus.send_repeatedly( - 100, // (uint8_t) Recipient device id - bus_id, // (uint8_t *) Recipient bus id - "Test port id", // (const void *) Payload - 23, // (uint16_t) Length - 1000000, // (uint32_t) Interval in microseconds - bus.config, // (uint8_t) Packet header - 1, // (uint16_t) Packet id - 8002 // (uint16_t) Port identification - ); -``` -`send_repeatedly` returns the id of the packet in the packet's buffer as `send` does, to remove this repeated transmission simply: +``` +`send_repeatedly` returns the id of the packet in the buffer as `send` does, to remove the repeated transmission simply call: ```cpp bus.remove(one_second_test); ``` +`send_repeatedly` can receive 3 optional parameters both in local and shared mode: the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 2 using the actual instance's header configuration, without including the packet id and including the port `8002`: +```cpp +// Shared mode or using bus indexing +bus.send_repeatedly( + 2, // (uint8_t) Recipient device id + bus_id, // (uint8_t *) Recipient bus id + "Hello", // (const void *) Payload + 5, // (uint16_t) Length + 1000000 // (uint32_t) Interval + bus.config, // (uint8_t) Packet header + 0, // (uint16_t) Packet id + 8002 // (uint16_t) Port identification +); From 05a7d6fbc5c63240ec682e0d162e9806f5da0e82 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Jun 2020 17:10:03 +0200 Subject: [PATCH 079/323] documentation/data-transmission minor fix --- documentation/data-transmission.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index 8bc1fbce6f..3d830c7745 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -55,7 +55,7 @@ bus.send_packet( ); ``` -When using `send_packet` the transmission may occur as soon as the method is called and it returns the following values: +`send_packet` returns the following values: - `PJON_ACK` (6) if transmission occurred and acknowledgement is received if requested - `PJON_BUSY` (666) if bus is busy - `PJON_FAIL` (65535) if transmission failed @@ -77,22 +77,28 @@ Use `send_packet_blocking` if it is necessary to try until the packet is effecti ```cpp // Send to device id 10 the string "Hi!" bus.send_packet_blocking(10, "Hi!", 3); +``` +`send_packet_blocking` returns the following values: +- `PJON_ACK` (6) if transmission occurred and acknowledgement is received if requested +- `PJON_BUSY` (666) if bus is busy +- `PJON_FAIL` (65535) if transmission failed -// Use the value returned by send_packet to determine transmission result -if(bus.send_packet_blocking(10, "All is ok?!", 11) == PJON_ACK) - Serial.println("10 is ok!"); +The `send_packet_blocking` result, of type `uint16_t`, can be used to determine if the transmission occurred successfully or not: +```cpp +uint16_t result = bus.send_packet_blocking(10, "All is ok?!", 11); + +if(result == PJON_ACK) Serial.println("10 is ok!"); ``` -`send_packet_blocking` optional parameters and return values are the same as `send_packet`. ### `send` -When using the `send` method, PJON operates using its internal buffer, although a little more memory is required. The first thing to do and never forget is to call the `update()` method once per loop cycle: +When using the `send` method, PJON operates using its internal buffer, although a little more memory is required. The first thing to do and never forget is to call the `update` method once per loop cycle: ```cpp bus.update(); ``` Every time `update` is called the transmission is attempted for each packet present in the buffer. -One way to insert packets in the buffer is to use the `send` method. To send data to another device connected to the bus simply call `send` passing the device id of the recipient of type `uint8_t` then the payload of type `const void *` and its length of type `uint16_t`. The return value of `send` is of type `uint16_t` and it is the id of the packet in the buffer or `PJON_FAIL` in case of error. +To send data to another device connected to the bus simply call `send` passing the device id of the recipient of type `uint8_t` then the payload of type `const void *` and its length of type `uint16_t`. The return value of `send` is of type `uint16_t` and it is the id of the packet in the buffer or `PJON_FAIL` in case of error. ```cpp bus.send(100, "Ciao, this is a test!", 21); ``` From f256125caba35b251d98f4827989b66004e09679 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Jun 2020 17:17:52 +0200 Subject: [PATCH 080/323] documentation/data-transmission send_packet_blocking remarks added --- documentation/data-transmission.md | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index 3d830c7745..471db5e9cb 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -78,6 +78,39 @@ Use `send_packet_blocking` if it is necessary to try until the packet is effecti // Send to device id 10 the string "Hi!" bus.send_packet_blocking(10, "Hi!", 3); ``` +The `send_packet_blocking` method can receive other 4 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion), a port of type `uint16_t` and a timeout of type `uint32_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id, including the port `8002` and passing a maximum timeout of 1 second: +```cpp +// All optional parameters available +bus.send_packet_blocking( + 10, // Device id (uint8_t) + "Hello", // Payload (const void *) + 5, // Length (uint16_t) + bus.config, // Header (uint8_t) - Use default config + 0, // Packet id (uint16_t) - Don't include packet id + 8002, // Port (uint16_t) + 1000000 // Timeout (uint32_t) - 1 second +); +``` +If you need to transmit data in shared mode you can use the same `send_packet_blocking` method including also the bus id. In the example below a packet containing the payload "Hi!" is sent to device id 10: +```cpp +// Send to bus id 0.0.0.1 +uint8_t bus_id[] = {0, 0, 0, 1}; +bus.send_packet(10, bus_id, "Hi!", 3); +``` +As its local version, `send_packet_blocking` can receive other 4 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion), a port of type `uint16_t` and a timeout of type `uint32_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id, including the port `8002` and passing a maximum timeout of 1 second: +```cpp +// All optional parameters available +bus.send_packet( + 10, // Device id (uint8_t) + bus_id, // Bus id (uint8_t *) + "Hello", // Payload (const void *) + 5, // Length (uint16_t) + bus.config, // Header (uint8_t) - Use default config + 0, // Packet id (uint16_t) - Don't include packet id + 8002, // Port (uint16_t) + 1000000 // Timeout (uint32_t) - 1 second +); +``` `send_packet_blocking` returns the following values: - `PJON_ACK` (6) if transmission occurred and acknowledgement is received if requested - `PJON_BUSY` (666) if bus is busy From 4244f02fb94919971512173bcb9d3f00f53ad97f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Jun 2020 17:19:20 +0200 Subject: [PATCH 081/323] documentation/data-transmission minor fix --- documentation/data-transmission.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index 471db5e9cb..24095274bc 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -95,12 +95,12 @@ If you need to transmit data in shared mode you can use the same `send_packet_bl ```cpp // Send to bus id 0.0.0.1 uint8_t bus_id[] = {0, 0, 0, 1}; -bus.send_packet(10, bus_id, "Hi!", 3); +bus.send_packet_blocking(10, bus_id, "Hi!", 3); ``` As its local version, `send_packet_blocking` can receive other 4 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion), a port of type `uint16_t` and a timeout of type `uint32_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id, including the port `8002` and passing a maximum timeout of 1 second: ```cpp // All optional parameters available -bus.send_packet( +bus.send_packet_blocking( 10, // Device id (uint8_t) bus_id, // Bus id (uint8_t *) "Hello", // Payload (const void *) From 433039f549dab9472851178ece6f257647da17fb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Jun 2020 23:00:57 +0200 Subject: [PATCH 082/323] shared send functions version removed (breaking compatibility) --- src/PJON.h | 80 ++++++++---------------------------------------------- 1 file changed, 12 insertions(+), 68 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 8682304df8..074a9fb147 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -237,6 +237,7 @@ class PJON { PJON_Packet_Info info; info.rx.id = rx_id; info.header = header; + PJONTools::copy_id(info.rx.bus_id, tx.bus_id, 4); #if(PJON_INCLUDE_PACKET_ID) info.id = packet_id; #else @@ -456,24 +457,21 @@ class PJON { return dispatch(info, payload, length); }; - /* Schedule a packet sending: */ - - uint16_t send( - uint8_t rx_id, - const void *payload, - uint16_t length, - uint8_t header = PJON_NO_HEADER, - uint16_t packet_id = 0, - uint16_t rx_port = PJON_BROADCAST - ) { - PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); - PJONTools::copy_id(info.rx.bus_id, tx.bus_id, 4); - return dispatch(info, payload, length); + uint16_t reply_blocking(const void *payload, uint16_t length) { + PJON_Packet_Info info; + info = last_packet_info; + info.rx = info.tx; + info.header = config; + #ifndef PJON_LOCAL + info.hops = 0; + #endif + return send_packet_blocking(info, payload, length); }; + /* Schedule a packet sending: */ + uint16_t send( uint8_t rx_id, - const uint8_t *rx_bus_id, const void *payload, uint16_t length, uint8_t header = PJON_NO_HEADER, @@ -481,7 +479,6 @@ class PJON { uint16_t rx_port = PJON_BROADCAST ) { PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); - PJONTools::copy_id(info.rx.bus_id, rx_bus_id, 4); return dispatch(info, payload, length); }; @@ -540,25 +537,6 @@ class PJON { uint16_t rx_port = PJON_BROADCAST ) { PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); - PJONTools::copy_id(info.rx.bus_id, tx.bus_id, 4); - return dispatch(info, payload, length, timing); - }; - - /* IMPORTANT: send_repeatedly timing maximum - is 4293014170 microseconds or 71.55 minutes */ - - uint16_t send_repeatedly( - uint8_t rx_id, - const uint8_t *rx_bus_id, - const void *payload, - uint16_t length, - uint32_t timing, - uint8_t header = PJON_NO_HEADER, - uint16_t packet_id = 0, - uint16_t rx_port = PJON_BROADCAST - ) { - PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); - PJONTools::copy_id(info.rx.bus_id, rx_bus_id, 4); return dispatch(info, payload, length, timing); }; @@ -601,23 +579,6 @@ class PJON { uint16_t rx_port = PJON_BROADCAST ) { PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); - PJONTools::copy_id(info.rx.bus_id, tx.bus_id, 4); - if(!(length = compose_packet(info, data, payload, length))) - return PJON_FAIL; - return send_packet(data, length); - }; - - uint16_t send_packet( - uint8_t rx_id, - const uint8_t *rx_bus_id, - const void *payload, - uint16_t length, - uint8_t header = PJON_NO_HEADER, - uint16_t packet_id = 0, - uint16_t rx_port = PJON_BROADCAST - ) { - PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); - PJONTools::copy_id(info.rx.bus_id, rx_bus_id, 4); if(!(length = compose_packet(info, data, payload, length))) return PJON_FAIL; return send_packet(data, length); @@ -676,7 +637,6 @@ class PJON { uint16_t send_packet_blocking( uint8_t rx_id, - const uint8_t *rx_bus_id, const void *payload, uint16_t length, uint8_t header = PJON_NO_HEADER, @@ -685,25 +645,9 @@ class PJON { uint32_t timeout = 3500000 ) { PJON_Packet_Info info = fill_info(rx_id, header, packet_id, rx_port); - PJONTools::copy_id(info.rx.bus_id, rx_bus_id, 4); return send_packet_blocking(info, payload, length, timeout); }; - uint16_t send_packet_blocking( - uint8_t rx_id, - const void *payload, - uint16_t length, - uint8_t header = PJON_NO_HEADER, - uint16_t packet_id = 0, - uint16_t rx_port = PJON_BROADCAST, - uint32_t timeout = 3000000 - ) { - return send_packet_blocking( - rx_id, tx.bus_id, payload, length, header, - packet_id, rx_port, timeout - ); - }; - /* In router mode, the receiver function can acknowledge for selected receiver device ids for which the route is known */ From abe1de3c226f6a5ce39fff28cbe8f1db94e848cf Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Jun 2020 19:38:21 +0200 Subject: [PATCH 083/323] documentation/data-structures added, data-transmission updated --- documentation/README.md | 1 + documentation/addressing.md | 1 + documentation/configuration.md | 1 + documentation/data-reception.md | 23 -------- documentation/data-transmission.md | 89 +++++++++++++++--------------- documentation/error-handling.md | 1 + documentation/io-setup.md | 1 + documentation/routing.md | 1 + 8 files changed, 52 insertions(+), 66 deletions(-) diff --git a/documentation/README.md b/documentation/README.md index 302d10532a..9500760baf 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -3,6 +3,7 @@ - [Addressing](/documentation/addressing.md) - [Configuration](/documentation/configuration.md) - [Data reception](/documentation/data-reception.md) +- [Data structures](/documentation/data-structures.md) - [Data transmission](/documentation/data-transmission.md) - [Error handling](/documentation/error-handling.md) - [IO setup](/documentation/io-setup.md) diff --git a/documentation/addressing.md b/documentation/addressing.md index 43b9e35ede..8d251a4da8 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -3,6 +3,7 @@ - **[Addressing](/documentation/addressing.md)** - [Configuration](/documentation/configuration.md) - [Data reception](/documentation/data-reception.md) +- [Data structures](/documentation/data-structures.md) - [Data transmission](/documentation/data-transmission.md) - [Error handling](/documentation/error-handling.md) - [IO setup](/documentation/io-setup.md) diff --git a/documentation/configuration.md b/documentation/configuration.md index 7964b54362..6bea8fa019 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -3,6 +3,7 @@ - [Addressing](/documentation/addressing.md) - **[Configuration](/documentation/configuration.md)** - [Data reception](/documentation/data-reception.md) +- [Data structures](/documentation/data-structures.md) - [Data transmission](/documentation/data-transmission.md) - [Error handling](/documentation/error-handling.md) - [IO setup](/documentation/io-setup.md) diff --git a/documentation/data-reception.md b/documentation/data-reception.md index a053132c12..96101c9993 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -29,29 +29,6 @@ bus.set_receiver(receiver_function); Within `receiver_function` it is possible to process data and meta-data when a packet is received. The `PJON_Packet_Info` struct contains all the protocol fields present in the packet: -```cpp -struct PJON_Packet_Info { - PJON_Endpoint tx; - PJON_Endpoint rx; - void *custom_pointer; - uint8_t header = PJON_NO_HEADER; - uint8_t hops = 0; - uint16_t id = 0; - uint16_t port = PJON_BROADCAST; -}; -``` -`PJON_Packet_Info` contains `port` if [`PJON_INCLUDE_PORT`](/documentation/configuration.md#network-service-identification) is defined and `id` if [`PJON_INCLUDE_PACKET_ID`](/documentation/configuration.md#packet-identification) is defined. The conditional inclusion is present to reduce the footprint of programs where the port and the packet id are not used. - -`PJON_Packet_Info` contains `tx` and `rx` of type `PJON_Endpoint` where the packet's sender and recipient information is contained: -```cpp -struct PJON_Endpoint { - uint8_t id = PJON_NOT_ASSIGNED; - uint8_t bus_id[4] = {0, 0, 0, 0}; - uint8_t mac[6] = {0, 0, 0, 0, 0, 0}; -}; -``` -`PJON_Endpoint` contains `mac` if [`PJON_INCLUDE_MAC`](/documentation/configuration.md#hardware-identification) is defined. The conditional inclusion is present to reduce the footprint of programs where the MAC address is not used. - The code below is part of the Arduino compatible [PortsUseExample](/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino). When the `receiver_function` is called meta-data present in the `info` parameter is printed in the serial monitor: ```cpp void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &info) { diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index 24095274bc..abf9bd0497 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -3,6 +3,7 @@ - [Addressing](/documentation/addressing.md) - [Configuration](/documentation/configuration.md) - [Data reception](/documentation/data-reception.md) +- [Data structures](/documentation/data-structures.md) - **[Data transmission](/documentation/data-transmission.md)** - [Error handling](/documentation/error-handling.md) - [IO setup](/documentation/io-setup.md) @@ -11,13 +12,15 @@ --- ## Data transmission + ### `begin` The begin method must be called before starting communication, the lack of this call can lead to collisions after boot, so be sure not to forget it. ```cpp bus.begin(); ``` + ### `send_packet` -The simplest way to send data is to use `send_packet`, this method composes the packet and tries to send it once. Consider that if the bus is busy or interference is present the transmission may not be attempted. The method returns the result of its operation. The first parameter is the device id of the recipient of type `uint8_t` then follows the payload of type `const void *` and its length of type `uint16_t`. This call implies a single attempt and has no guarantee of success, but logs the result of the attempted transmission: +The simplest way to send data is to use `send_packet`, this method composes the packet and tries to send it once. Consider that if the bus is busy or interference is present the transmission may not be attempted. The method returns the result of its operation. The first parameter is the device id of the recipient of type `uint8_t`, the second is the payload of type `const void *` and the third is the length of type `uint16_t`. This call implies a single attempt and has no guarantee of success, but logs the result of the attempted transmission: ```cpp // Send to device id 10 the string "Hi!" bus.send_packet(10, "Hi!", 3); @@ -35,26 +38,6 @@ bus.send_packet( ); ``` -If you need to transmit data in shared mode you can use the same `send_packet` method including also the bus id. In the example below a packet containing the payload "Hi!" is sent to device id 10: -```cpp -// Send to bus id 0.0.0.1 -uint8_t bus_id[] = {0, 0, 0, 1}; -bus.send_packet(10, bus_id, "Hi!", 3); -``` -As its local version, `send_packet` can receive other 3 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id and including the port `8002`. -```cpp -// All optional parameters available -bus.send_packet( - 10, // Device id (uint8_t) - bus_id, // Bus id (uint8_t *) - "Hello", // Payload (const void *) - 5, // Length (uint16_t) - bus.config, // Header (uint8_t) - Use default config - 0, // Packet id (uint16_t) - Don't include packet id - 8002 // Port (uint16_t) -); -``` - `send_packet` returns the following values: - `PJON_ACK` (6) if transmission occurred and acknowledgement is received if requested - `PJON_BUSY` (666) if bus is busy @@ -71,6 +54,17 @@ To broadcast a message to all connected devices, use the `PJON_BROADCAST` consta ```cpp bus.send_packet(PJON_BROADCAST, "Message for all connected devices.", 34); ``` + +If you need to transmit in shared mode or configure other protocol fields you can use `send_packet` passing a struct of type `PJON_Packet_Info`, the payload of type `const void *` and the length of type `uint16_t`: +```cpp +uint8_t bus_id[4] = {0, 0, 0, 1}; +PJON_Packet_Info info; +info.rx.id = 10; // The recipient's device id is 10 +info.rx.port = 8000; // The packet includes the port 8000 +memcpy(info.rx.bus_id, bus_id, 4); // Copy recipient's bus id in info +bus.send_packet(info, "Ciao!", 5); +``` + ### `send_packet_blocking` Use `send_packet_blocking` if it is necessary to try until the packet is effectively received by the recipient or a maximum amount of retries is reached. Consider that the method may block the operation of the program for up to 4 seconds in case of transmission failure. @@ -123,6 +117,16 @@ uint16_t result = bus.send_packet_blocking(10, "All is ok?!", 11); if(result == PJON_ACK) Serial.println("10 is ok!"); ``` +If you need to transmit in shared mode or configure other protocol fields you can use `send_packet_blocking` passing a struct of type `PJON_Packet_Info`, the payload of type `const void *` and the length of type `uint16_t`: +```cpp +uint8_t bus_id[4] = {0, 0, 0, 1}; +PJON_Packet_Info info; +info.rx.id = 10; // The recipient's device id is 10 +info.rx.port = 8000; // The packet includes the port 8000 +memcpy(info.rx.bus_id, bus_id, 4); // Copy recipient's bus id in info +bus.send_packet_blocking(info, "Ciao!", 5); +``` + ### `send` When using the `send` method, PJON operates using its internal buffer, although a little more memory is required. The first thing to do and never forget is to call the `update` method once per loop cycle: @@ -146,26 +150,6 @@ bus.send( 0, // (uint16_t) Packet id 8002 // (uint16_t) Port identification ); -``` - -`send` can be used in shared mode passing the bus id after the device id: -```cpp -uint8_t bus_id[] = {0, 0, 0, 1}; -bus.send(100, bus_id, "Ciao, this is a test!", 21); -``` -`send` can receive 3 optional parameters also when used in shared mode, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 2 using the actual instance's header configuration, without including the packet id and including the port `8002`: -```cpp -// Shared mode or using bus indexing -bus.send( - 2, // (uint8_t) Recipient device id - bus_id, // (uint8_t *) Recipient bus id - "Hello", // (const void *) Payload - 5, // (uint16_t) Length - bus.config, // (uint8_t) Packet header - 0, // (uint16_t) Packet id - 8002 // (uint16_t) Port identification -); - ``` To use the return value of `send` just save it in a variable of type `uint16_t`: ```cpp @@ -174,6 +158,16 @@ uint16_t packet = bus.send(100, "Ciao, this is a test!", 21); if(packet == PJON_FAIL) Serial.print("Something went wrong"); ``` +If you need to transmit in shared mode or configure other protocol fields you can use `send` passing a struct of type `PJON_Packet_Info`, the payload of type `const void *` and the length of type `uint16_t`: +```cpp +uint8_t bus_id[4] = {0, 0, 0, 1}; +PJON_Packet_Info info; +info.rx.id = 10; // The recipient's device id is 10 +info.rx.port = 8000; // The packet includes the port 8000 +memcpy(info.rx.bus_id, bus_id, 4); // Copy recipient's bus id in info +bus.send(info, "Ciao!", 5); +``` + ### `send_repeatedly` The `send_repeatedly` method can be used when it is required to schedule a repeated sending with a given interval. The first parameter is the device id of the recipient of type `uint8_t` then follows the payload of type `const void *`, its length of type `uint16_t` and the interval of type `uint32_t`: ```cpp @@ -188,12 +182,11 @@ uint16_t one_second_test = ```cpp bus.remove(one_second_test); ``` -`send_repeatedly` can receive 3 optional parameters both in local and shared mode: the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 2 using the actual instance's header configuration, without including the packet id and including the port `8002`: +`send_repeatedly` can receive 3 optional parameters: the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 2 every second using the actual instance's header configuration, without including the packet id and including the port `8002`: ```cpp // Shared mode or using bus indexing bus.send_repeatedly( 2, // (uint8_t) Recipient device id - bus_id, // (uint8_t *) Recipient bus id "Hello", // (const void *) Payload 5, // (uint16_t) Length 1000000 // (uint32_t) Interval @@ -201,3 +194,13 @@ bus.send_repeatedly( 0, // (uint16_t) Packet id 8002 // (uint16_t) Port identification ); + +If you need to transmit in shared mode or configure other protocol fields you can use `send_repeatedly` passing a struct of type `PJON_Packet_Info`, the payload of type `const void *`, the length of type `uint16_t` and the interval of type `uint32_t`: +```cpp +uint8_t bus_id[4] = {0, 0, 0, 1}; +PJON_Packet_Info info; +info.rx.id = 10; // The recipient's device id is 10 +info.rx.port = 8000; // The packet includes the port 8000 +memcpy(info.rx.bus_id, bus_id, 4); // Copy recipient's bus id in info +bus.send_repeatedly(info, "Ciao!", 5, 1000000); // Send "Ciao!" every second +``` diff --git a/documentation/error-handling.md b/documentation/error-handling.md index a3e7d0542c..a27ef7aca9 100644 --- a/documentation/error-handling.md +++ b/documentation/error-handling.md @@ -3,6 +3,7 @@ - [Addressing](/documentation/addressing.md) - [Configuration](/documentation/configuration.md) - [Data reception](/documentation/data-reception.md) +- [Data structures](/documentation/data-structures.md) - [Data transmission](/documentation/data-transmission.md) - **[Error handling](/documentation/error-handling.md)** - [IO setup](/documentation/io-setup.md) diff --git a/documentation/io-setup.md b/documentation/io-setup.md index 911c3dfa0e..6abaf600b3 100644 --- a/documentation/io-setup.md +++ b/documentation/io-setup.md @@ -3,6 +3,7 @@ - [Addressing](/documentation/addressing.md) - [Configuration](/documentation/configuration.md) - [Data reception](/documentation/data-reception.md) +- [Data structures](/documentation/data-structures.md) - [Data transmission](/documentation/data-transmission.md) - [Error handling](/documentation/error-handling.md) - **[IO setup](/documentation/io-setup.md)** diff --git a/documentation/routing.md b/documentation/routing.md index 881a6ebb19..2c71861285 100644 --- a/documentation/routing.md +++ b/documentation/routing.md @@ -3,6 +3,7 @@ - [Addressing](/documentation/addressing.md) - [Configuration](/documentation/configuration.md) - [Data reception](/documentation/data-reception.md) +- [Data structures](/documentation/data-structures.md) - [Data transmission](/documentation/data-transmission.md) - [Error handling](/documentation/error-handling.md) - [IO setup](/documentation/io-setup.md) From 2dade54f6774e140799aecc47379d564072338b2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Jun 2020 19:39:19 +0200 Subject: [PATCH 084/323] data-structures minor fix --- documentation/data-structures.md | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 documentation/data-structures.md diff --git a/documentation/data-structures.md b/documentation/data-structures.md new file mode 100644 index 0000000000..d1c228a97c --- /dev/null +++ b/documentation/data-structures.md @@ -0,0 +1,43 @@ + +### Documentation index +- [Addressing](/documentation/addressing.md) +- [Configuration](/documentation/configuration.md) +- [Data reception](/documentation/data-reception.md) +- **[Data structures](/documentation/data-structures.md)** +- [Data transmission](/documentation/data-transmission.md) +- [Error handling](/documentation/error-handling.md) +- [IO setup](/documentation/io-setup.md) +- [Routing](/documentation/routing.md) + +--- + +## Data structures + +### `PJON_Endpoint` +`PJON_Endpoint` contains the device id, bus id and MAC address of a device: +```cpp +struct PJON_Endpoint { + uint8_t id = PJON_NOT_ASSIGNED; + uint8_t bus_id[4] = {0, 0, 0, 0}; + uint8_t mac[6] = {0, 0, 0, 0, 0, 0}; +}; +``` +`PJON_Endpoint` contains `mac` if [`PJON_INCLUDE_MAC`](/documentation/configuration.md#hardware-identification) is defined. The conditional inclusion is present to reduce the footprint of programs where the MAC address is not used. + +### `PJON_Packet_Info` +`PJON_Packet_Info` contains all meta-data supported by the PJON packet format. The `tx` and `rx` data structures of type `PJON_Endpoint` contain the transmitter and receiver information. + +```cpp +struct PJON_Packet_Info { + PJON_Endpoint tx; + PJON_Endpoint rx; + void *custom_pointer; + uint8_t header = PJON_NO_HEADER; + uint8_t hops = 0; + uint16_t id = 0; + uint16_t port = PJON_BROADCAST; +}; +``` +`PJON_Packet_Info` contains `port` if [`PJON_INCLUDE_PORT`](/documentation/configuration.md#network-service-identification) is defined and `id` if [`PJON_INCLUDE_PACKET_ID`](/documentation/configuration.md#packet-identification) is defined. The conditional inclusion is present to reduce the footprint of programs where the port and the packet id are not used. + +The `custom_pointer` can be used to link other classes or instances passing any sort of data structure. To understand how to use it see the [ClassMemberCallback](../examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback) example. From c0b125c8bc49793a3b11a038d643ec60bb6ff601 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 Jun 2020 19:45:12 +0200 Subject: [PATCH 085/323] documentation links update --- documentation/data-reception.md | 4 ++-- documentation/data-transmission.md | 30 ++++++------------------------ 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/documentation/data-reception.md b/documentation/data-reception.md index 96101c9993..19a8f60676 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -11,7 +11,7 @@ --- ## Data reception -A function of type `void` is called by the PJON object when a packet is received. This function receives 3 parameters: the received payload of type `uint8_t *`, its length of type `uint16_t` and a pointer to a data structure of type `const PJON_Packet_Info` that contains all packet's metadata: +A function of type `void` is called by the PJON object when a packet is received. This function receives 3 parameters: the received payload of type `uint8_t *`, its length of type `uint16_t` and a pointer to a data structure of type [`const PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) that contains all packet's metadata: ```cpp void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &info) { @@ -27,7 +27,7 @@ PJON bus; bus.set_receiver(receiver_function); ``` -Within `receiver_function` it is possible to process data and meta-data when a packet is received. The `PJON_Packet_Info` struct contains all the protocol fields present in the packet: +Within `receiver_function` it is possible to process data and meta-data when a packet is received. The [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) struct contains all the protocol fields present in the packet: The code below is part of the Arduino compatible [PortsUseExample](/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino). When the `receiver_function` is called meta-data present in the `info` parameter is printed in the serial monitor: ```cpp diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index abf9bd0497..5b8d858294 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -55,7 +55,7 @@ To broadcast a message to all connected devices, use the `PJON_BROADCAST` consta bus.send_packet(PJON_BROADCAST, "Message for all connected devices.", 34); ``` -If you need to transmit in shared mode or configure other protocol fields you can use `send_packet` passing a struct of type `PJON_Packet_Info`, the payload of type `const void *` and the length of type `uint16_t`: +If you need to transmit in shared mode or configure other protocol fields you can use `send_packet` passing a struct of type [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info), the payload of type `const void *` and the length of type `uint16_t`: ```cpp uint8_t bus_id[4] = {0, 0, 0, 1}; PJON_Packet_Info info; @@ -85,26 +85,7 @@ bus.send_packet_blocking( 1000000 // Timeout (uint32_t) - 1 second ); ``` -If you need to transmit data in shared mode you can use the same `send_packet_blocking` method including also the bus id. In the example below a packet containing the payload "Hi!" is sent to device id 10: -```cpp -// Send to bus id 0.0.0.1 -uint8_t bus_id[] = {0, 0, 0, 1}; -bus.send_packet_blocking(10, bus_id, "Hi!", 3); -``` -As its local version, `send_packet_blocking` can receive other 4 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion), a port of type `uint16_t` and a timeout of type `uint32_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id, including the port `8002` and passing a maximum timeout of 1 second: -```cpp -// All optional parameters available -bus.send_packet_blocking( - 10, // Device id (uint8_t) - bus_id, // Bus id (uint8_t *) - "Hello", // Payload (const void *) - 5, // Length (uint16_t) - bus.config, // Header (uint8_t) - Use default config - 0, // Packet id (uint16_t) - Don't include packet id - 8002, // Port (uint16_t) - 1000000 // Timeout (uint32_t) - 1 second -); -``` + `send_packet_blocking` returns the following values: - `PJON_ACK` (6) if transmission occurred and acknowledgement is received if requested - `PJON_BUSY` (666) if bus is busy @@ -117,7 +98,7 @@ uint16_t result = bus.send_packet_blocking(10, "All is ok?!", 11); if(result == PJON_ACK) Serial.println("10 is ok!"); ``` -If you need to transmit in shared mode or configure other protocol fields you can use `send_packet_blocking` passing a struct of type `PJON_Packet_Info`, the payload of type `const void *` and the length of type `uint16_t`: +If you need to transmit in shared mode or configure other protocol fields you can use `send_packet_blocking` passing a struct of type [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info), the payload of type `const void *` and the length of type `uint16_t`: ```cpp uint8_t bus_id[4] = {0, 0, 0, 1}; PJON_Packet_Info info; @@ -158,7 +139,7 @@ uint16_t packet = bus.send(100, "Ciao, this is a test!", 21); if(packet == PJON_FAIL) Serial.print("Something went wrong"); ``` -If you need to transmit in shared mode or configure other protocol fields you can use `send` passing a struct of type `PJON_Packet_Info`, the payload of type `const void *` and the length of type `uint16_t`: +If you need to transmit in shared mode or configure other protocol fields you can use `send` passing a struct of type [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info), the payload of type `const void *` and the length of type `uint16_t`: ```cpp uint8_t bus_id[4] = {0, 0, 0, 1}; PJON_Packet_Info info; @@ -194,8 +175,9 @@ bus.send_repeatedly( 0, // (uint16_t) Packet id 8002 // (uint16_t) Port identification ); +``` -If you need to transmit in shared mode or configure other protocol fields you can use `send_repeatedly` passing a struct of type `PJON_Packet_Info`, the payload of type `const void *`, the length of type `uint16_t` and the interval of type `uint32_t`: +If you need to transmit in shared mode or configure other protocol fields you can use `send_repeatedly` passing a struct of type [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info), the payload of type `const void *`, the length of type `uint16_t` and the interval of type `uint32_t`: ```cpp uint8_t bus_id[4] = {0, 0, 0, 1}; PJON_Packet_Info info; From f04bc16714839bc3f260b09a9ccb669ddad788e0 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 13 Jun 2020 17:23:07 +0200 Subject: [PATCH 086/323] Shared examples update --- .../NetworkAnalysis/Transmitter/Transmitter.ino | 6 ++++-- .../NetworkAnalysis/Transmitter/Transmitter.ino | 6 +++++- .../SendArbitraryValues/Transmitter/Transmitter.ino | 5 ++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/examples/ARDUINO/Network/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino index 0875310999..d4d0ee0010 100644 --- a/examples/ARDUINO/Network/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino @@ -33,8 +33,10 @@ void loop() { /* Here send_packet low level function is used to be able to catch every single sending result. */ - - unsigned int response = bus.send_packet(44, bus_id, content, 20); + PJON_Packet_Info info; + info.rx.id = 44; + memcpy(info.rx.bus_id, bus_id); + unsigned int response = bus.send_packet(info, content, 20); if(response == PJON_ACK) test++; if(response == PJON_NAK) diff --git a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino index 3eb0d0eab2..065121ed15 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino @@ -46,7 +46,11 @@ void loop() { /* Here send_packet low level function is used to be able to catch every single sending result. */ - unsigned int response = bus.send_packet(44, bus_id, content, 20, header); + PJON_Packet_Info info; + info.rx.id = 44; + memcpy(info.rx.bus_id, bus_id); + unsigned int response = bus.send_packet(info, content, 20); + if(response == PJON_ACK) test++; if(response == PJON_NAK) diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino index a7f26e1b87..4b47ad4434 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino @@ -43,7 +43,10 @@ void loop() { unsigned long send_time = micros(); /* Use a blocking version of send. */ - packet = bus.send_packet_blocking(44, bus_id, content, 3); + PJON_Packet_Info info; + info.rx.id = 44; + memcpy(info.rx.bus_id, bus_id); + packet = bus.send_packet_blocking(info, content, 3); /* Determine communication result and duration */ send_time = micros() - send_time; From d2585c3f0fbebb5b2cde26301f3520b50816e255 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 13 Jun 2020 19:51:48 +0200 Subject: [PATCH 087/323] New strategy inclusion scheme (breaking compatibility) --- documentation/addressing.md | 8 +- documentation/configuration.md | 70 +++++++-------- .../BlinkTest/Receiver/Receiver.ino | 4 +- .../BlinkTest/Transmitter/Transmitter.ino | 4 +- .../NetworkAnalysis/Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../MultiStrategyLink/Receiver/Receiver.ino | 6 +- .../Transmitter1/Transmitter1.ino | 2 +- .../Transmitter2/Transmitter2.ino | 2 +- .../Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../DualUDP/PingPong/Receiver/Receiver.ino | 4 +- .../PingPong/Transmitter/Transmitter.ino | 4 +- .../PingPong/Receiver/Receiver.ino | 4 +- .../PingPong/Transmitter/Transmitter.ino | 4 +- .../RemoteWorker/Transmitter/Transmitter.ino | 4 +- .../Surrogate/Surrogate.ino | 4 +- .../GlobalUDP/PingPong/Receiver/Receiver.ino | 4 +- .../PingPong/Transmitter/Transmitter.ino | 4 +- .../LocalUDP/PingPong/Receiver/Receiver.ino | 4 +- .../PingPong/Transmitter/Transmitter.ino | 4 +- .../PingPong/Receiver/Receiver.ino | 6 +- .../PingPong/Transmitter/Transmitter.ino | 6 +- .../SWBB-MQTT-Gateway/Gateway/Gateway.ino | 8 +- .../SomeDevice/SomeDevice.ino | 12 +-- .../HalfDuplex/Device1/Device1.ino | 4 +- .../HalfDuplex/Device2/Device2.ino | 4 +- .../Device1/Device1.ino | 4 +- .../Device2/Device2.ino | 4 +- .../NetworkAnalysis/Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../Simplex/Receiver/Receiver.ino | 4 +- .../Simplex/Transmitter/Transmitter.ino | 4 +- .../BlinkTest/Receiver/Receiver.ino | 4 +- .../BlinkTest/Transmitter/Transmitter.ino | 4 +- .../BlinkTestMAC/Receiver/Receiver.ino | 6 +- .../BlinkTestMAC/Transmitter/Transmitter.ino | 4 +- .../BlinkWithResponse/Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../ClassMemberCallback/Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../NetworkAnalysis/Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../PJONLocal/BlinkTest/Receiver/Receiver.ino | 2 +- .../BlinkTest/Transmitter/Transmitter.ino | 2 +- .../NetworkAnalysis/Receiver/Receiver.ino | 2 +- .../Transmitter/Transmitter.ino | 2 +- .../Receiver/Receiver.ino | 2 +- .../Transmitter/Transmitter.ino | 2 +- .../Receiver/Receiver.ino | 2 +- .../Transmitter/Transmitter.ino | 2 +- .../SendAndReceive/Device1/Device1.ino | 4 +- .../SendAndReceive/Device2/Device2.ino | 4 +- .../Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../SendArbitraryValues/Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../SpeedTest/Receiver/Receiver.ino | 4 +- .../SpeedTest/Transmitter/Transmitter.ino | 4 +- .../UsePacketId/Receiver/Receiver.ino | 4 +- .../UsePacketId/Transmitter/Transmitter.ino | 4 +- .../BlinkTest/Receiver/Receiver.ino | 6 +- .../BlinkTest/Transmitter/Transmitter.ino | 6 +- .../HalfDuplex/Device1/Device1.ino | 6 +- .../HalfDuplex/Device2/Device2.ino | 6 +- .../ThroughLoRa/JSON/Receiver/Receiver.ino | 6 +- .../JSON/Transmitter/Transmitter.ino | 6 +- .../NetworkAnalysis/Receiver/Receiver.ino | 6 +- .../Transmitter/Transmitter.ino | 6 +- .../ThroughLoRa/Simplex/Receiver/Receiver.ino | 6 +- .../Simplex/Transmitter/Transmitter.ino | 6 +- .../BlinkTest/Receiver/Receiver.ino | 13 ++- .../BlinkTest/Transmitter/Transmitter.ino | 4 +- .../BlinkWithResponse/Receiver/Receiver.ino | 5 +- .../Transmitter/Transmitter.ino | 4 +- .../HC-12-Blink/Receiver/Receiver.ino | 4 +- .../HC-12-Blink/Transmitter/Transmitter.ino | 4 +- .../HC-12-LocalChat/HC-12-LocalChat.ino | 4 +- .../Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../NucleoBlinkTest/Receiver/Receiver.ino | 6 +- .../Transmitter/Transmitter.ino | 6 +- .../RS485-Blink/Receiver/Receiver.ino | 4 +- .../RS485-Blink/Transmitter/Transmitter.ino | 4 +- .../Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../Surrogate/Surrogate.ino | 4 +- .../HalfDuplex/Receiver/Receiver.ino | 4 +- .../HalfDuplex/Transmitter/Transmitter.ino | 4 +- .../Device1/Device1.ino | 4 +- .../Device2/Device2.ino | 4 +- .../NetworkAnalysis/Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../Simplex/Receiver/Receiver.ino | 4 +- .../Simplex/Transmitter/Transmitter.ino | 4 +- .../BlinkTest/Receiver/Receiver.ino | 4 +- .../BlinkTest/Transmitter/Transmitter.ino | 4 +- .../LongPacketCRC32/Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../NetworkAnalysis/Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 6 +- .../PortsUseExample/Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../SendAndReceive/Device1/Device1.ino | 4 +- .../SendAndReceive/Device2/Device2.ino | 4 +- .../SendArbitraryValues/Receiver/Receiver.ino | 4 +- .../Transmitter/Transmitter.ino | 4 +- .../SpeedTest/Receiver/Receiver.ino | 4 +- .../SpeedTest/Transmitter/Transmitter.ino | 4 +- .../DualUDP/PingPong/Receiver/Receiver.ino | 4 +- .../PingPong/Transmitter/Transmitter.ino | 4 +- .../PingPong-esp-idf/Receiver/main/main.cpp | 8 +- .../Transmitter/main/main.cpp | 6 +- .../PingPongArduinoIDE/Device1/Device1.ino | 8 +- .../PingPongArduinoIDE/Device2/Device2.ino | 7 +- .../ESPNOW/PlatformIO/Device1/src/main.cpp | 8 +- .../ESPNOW/PlatformIO/Device2/src/main.cpp | 10 +-- .../DualUDP/PingPong/Receiver/Receiver.ino | 4 +- .../PingPong/Transmitter/Transmitter.ino | 4 +- .../GlobalUDP/PingPong/Receiver/Receiver.ino | 4 +- .../PingPong/Transmitter/Transmitter.ino | 4 +- .../EnvironmentController.ino | 11 ++- .../SendAndReceive/Arduino/Arduino.ino | 5 +- .../SendAndReceive/ESP8266/ESP8266.ino | 7 +- .../ESPTransmitter/ESPTransmitter.ino | 9 +- .../SpeedTest/Receiver/Receiver.ino | 5 +- .../PingPong/Receiver/Receiver.cpp | 6 +- .../PingPong/Transmitter/Transmitter.cpp | 6 +- .../GlobalUDP/PingPong/Receiver/Receiver.cpp | 6 +- .../PingPong/Transmitter/Transmitter.cpp | 6 +- .../LocalFile/PingPong/Receiver/Receiver.cpp | 6 +- .../PingPong/Transmitter/Transmitter.cpp | 6 +- .../LocalUDP/PingPong/Receiver/Receiver.cpp | 6 +- .../PingPong/Transmitter/Transmitter.cpp | 6 +- .../BlinkTest/Receiver/Receiver.cpp | 6 +- .../BlinkTest/Transmitter/Transmitter.cpp | 6 +- .../BlinkWithAck/Receiver/Receiver.cpp | 6 +- .../BlinkWithAck/Transmitter/Transmitter.cpp | 6 +- .../BlinkWithResponse/Receiver/Receiver.cpp | 6 +- .../Transmitter/Transmitter.cpp | 6 +- .../BlinkTestReceiver/Receiver.cpp | 6 +- .../BlinkTestTransmitter/Transmitter.cpp | 6 +- .../BlinkWithResponse/Transmitter.cpp | 6 +- .../RS485-BlinkWithResponse/Transmitter.cpp | 6 +- .../PingPong/Receiver/Receiver.cpp | 6 +- .../PingPong/Transmitter/Transmitter.cpp | 6 +- .../RemoteWorker/Transmitter/Transmitter.cpp | 6 +- .../GlobalUDP/PingPong/Receiver/Receiver.cpp | 6 +- .../PingPong/Transmitter/Transmitter.cpp | 6 +- .../LocalUDP/PingPong/Receiver/Receiver.cpp | 2 +- .../PingPong/Transmitter/Transmitter.cpp | 2 +- .../PingPong/Receiver/Receiver.cpp | 8 +- .../PingPong/Transmitter/Transmitter.cpp | 8 +- .../BlinkTest/Transmitter/Transmitter.cpp | 6 +- .../Transmitter/Transmitter.cpp | 6 +- keywords.txt | 17 ---- src/PJON.h | 1 - src/PJONAny.h | 7 ++ src/PJONDualUDP.h | 7 ++ src/PJONESPNOW.h | 7 ++ src/PJONEthernetTCP.h | 7 ++ src/PJONGlobalUDP.h | 7 ++ src/PJONLocal.h | 1 - src/PJONLocalFile.h | 7 ++ src/PJONLocalUDP.h | 7 ++ src/PJONMQTTTranslate.h | 7 ++ src/PJONSoftwareBitBang.h | 7 ++ src/PJONThroughLora.h | 7 ++ src/PJONThroughSerial.h | 7 ++ src/strategies/AnalogSampling/README.md | 14 +-- src/strategies/Any/README.md | 10 +-- src/strategies/DualUDP/README.md | 15 ++-- src/strategies/ESPNOW/README.md | 16 ++-- src/strategies/EthernetTCP/README.md | 13 +-- src/strategies/GlobalUDP/README.md | 13 +-- src/strategies/LocalFile/README.md | 15 ++-- src/strategies/LocalUDP/README.md | 13 +-- src/strategies/MQTTTranslate/README.md | 15 ++-- src/strategies/OverSampling/README.md | 14 +-- src/strategies/PJON_Strategies.h | 86 ------------------- src/strategies/README.md | 31 ++++--- src/strategies/SoftwareBitBang/README.md | 12 +-- src/strategies/ThroughLoRa/README.md | 30 +++---- src/strategies/ThroughSerial/README.md | 19 ++-- 184 files changed, 581 insertions(+), 651 deletions(-) create mode 100644 src/PJONAny.h create mode 100644 src/PJONDualUDP.h create mode 100644 src/PJONESPNOW.h create mode 100644 src/PJONEthernetTCP.h create mode 100644 src/PJONGlobalUDP.h create mode 100644 src/PJONLocalFile.h create mode 100644 src/PJONLocalUDP.h create mode 100644 src/PJONMQTTTranslate.h create mode 100644 src/PJONSoftwareBitBang.h create mode 100644 src/PJONThroughLora.h create mode 100644 src/PJONThroughSerial.h delete mode 100644 src/strategies/PJON_Strategies.h diff --git a/documentation/addressing.md b/documentation/addressing.md index 8d251a4da8..b64b9829ee 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -18,11 +18,11 @@ PJON objects can operate in local or shared mode. The PJON protocol v4.0 in [loc The simples way to instantiate PJON in local mode is the following: ```cpp - PJON bus; + PJONSoftwareBitBang bus; ``` When the object is instantiated without passing parameters it operates in local mode and the device identifier is set to 255 or `PJON_NOT_ASSIGNED`. PJON objects can be instantiated passing the device identifier: ```cpp - PJON bus(44); + PJONSoftwareBitBang bus(44); ``` `bus` receives packets for device identifier 44 and ignores all others. @@ -49,7 +49,7 @@ if the medium used is private and not accessible from the outside world (wired n Instantiation in shared mode: ```cpp uint8_t bus_id[4] = {1, 2, 3, 4}; -PJON bus(bus_id, 44); +PJONSoftwareBitBang bus(bus_id, 44); // Device id 44, bus id 1.2.3.4 in shared mode ``` ### Get or set bus identifier @@ -69,7 +69,7 @@ PJON can optionally operate using the MAC address of the device: // MAC address of the device uint8_t mac[6] = {1, 2, 3, 4, 5, 6}; -PJON bus(mac); +PJONSoftwareBitBang bus(mac); // Local mode, device id PJON_NOT_ASSIGNED ``` This instantiation sets the MAC address, the device id set to `PJON_NOT_ASSIGNED` or 255 but can be changed afterwards as required. Packets containing a recipient's MAC address that is not equal to the one configured are discarded. PJON can operate in both local and shared mode while including MAC addresses. The feature can be disabled using `includ_mac`: diff --git a/documentation/configuration.md b/documentation/configuration.md index 6bea8fa019..48d60a35b4 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -15,60 +15,48 @@ PJON uses predefined constants, setters and getters to support features and constraints configuration. ### Buffers configuration -Before instantiating PJON it is possible to define the length of its buffers. Predefining `PJON_MAX_PACKETS` and `PJON_PACKET_MAX_LENGTH` it is possible to configure these constraints to reach the project memory requirements. Obviously, the less memory is dedicated to buffers, the more memory can be used for something else: +Before including the library it is possible to define the length of its buffers defining the `PJON_MAX_PACKETS` and `PJON_PACKET_MAX_LENGTH` constants: ```cpp #define PJON_MAX_PACKETS 1 #define PJON_PACKET_MAX_LENGTH 20 - #include /* PJON can dispatch up to 1 packet with a payload of up to 20 bytes - packet overhead (5-35 bytes depending on configuration) */ ``` ### Strategy configuration -PJON is instantiated passing a [strategy](/src/strategies/README.md) template parameter: -```cpp - PJON bus; +The `PJON` class abstracts the [strategy](/src/strategies/README.md) using templates although since version 13.0 that complexity is hidden behind a [macro](../src/PJONSoftwareBitBang.h): +```cpp + #include + PJONSoftwareBitBang bus; ``` -In the example above the PJON object is instantiated passing the [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) strategy. Strategies are classes that abstract the physical transmission of data. It is possible to instantiate more than one PJON object using different strategies in the same program: -```cpp - PJON wiredBus; - PJON tcpBus; +In the example above the PJON object is instantiated using the [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) strategy. Strategies are classes that abstract the physical transmission of data. It is possible to instantiate more than one PJON object using different strategies in the same program: +```cpp +#include +#include + +PJONSoftwareBitBang wiredBus; +PJONEthernetTCP tcpBus; ``` The table below lists the strategies available: -| Strategy | Physical layer | Protocol | Inclusion constant | Included by default | -| ------------- | -------------- | -------- | ------------------ | ------------------- | -| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | `PJON_INCLUDE_AS` | yes | -| [Any](/src/strategies/Any) | Virtual inheritance | Any | `PJON_INCLUDE_ANY` | yes | -| [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `PJON_INCLUDE_DUDP` | yes | -| [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | `PJON_INCLUDE_EN` | no | -| [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | `PJON_INCLUDE_ETCP` | yes | -| [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `PJON_INCLUDE_GUDP` | yes | -| [LocalFile](/src/strategies/LocalFile) | System memory | None | `PJON_INCLUDE_LF` | no | -| [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `PJON_INCLUDE_LUDP` | yes | -| [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | `PJON_INCLUDE_MQTT` | no | -| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | `PJON_INCLUDE_OS` | yes | -| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | `PJON_INCLUDE_SWBB` | yes | -| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | `PJON_INCLUDE_TL` | no | -| [ThroughSerial](/src/strategies/ThroughSerial) | Radio | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | `PJON_INCLUDE_TS` | yes | - -By default all strategies are included except `MQTTTranslate`, `LocalFile`, `ThroughLoRa` and `ESPNOW`. Before using `ThroughLoRa` be sure to have [arduino-LoRa](https://github.com/sandeepmistry/arduino-LoRa) library available and to have defined the `PJON_INCLUDE_TL` constant before including `PJON.h`. Before using `ESPNOW` be sure to have installed the required tools as described [here](/src/strategies/ESPNOW/README.md) and to have defined the `PJON_INCLUDE_EN` constant before including `PJON.h`. Before using `MQTTTranslate` be sure to have the [ReconnectingMqttClient](https://github.com/fredilarsen/ReconnectingMqttClient) library available and to have defined the `PJON_INCLUDE_MQTT` constant before including `PJON.h`. - -To reduce memory footprint add for example `#define PJON_INCLUDE_SWBB` before including the library to select only the `SoftwareBitBang` strategy. -```cpp -#define PJON_INCLUDE_SWBB // Include only SoftwareBitBang strategy -#include // Include the library -PJON bus; // Instantiation -``` -More than one strategy related constants can be defined in the same program if that is required. - -If the strategy you want to use is not included by default, like ESPNOW, you can force its inclusion using its constant: -```cpp -#define PJON_INCLUDE_EN // Force the inclusion of ESPNOW strategy -#include // Include the library -PJON bus; // Instantiation -``` +| Strategy | Physical layer | Protocol | Inclusion | +| ------------- | -------------- | -------- | --------- | +| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | `#include ` | +| [Any](/src/strategies/Any) | Virtual inheritance | Any | `#include ` | +| [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | +| [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | `#include ` | +| [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | `#include ` | +| [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | +| [LocalFile](/src/strategies/LocalFile) | System memory | None | `#include ` | +| [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | +| [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | `#include ` | +| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | `#include ` | +| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | `#include ` | +| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | `#include ` | +| [ThroughSerial](/src/strategies/ThroughSerial) | Wire | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | `#include ` | + +Before using `ThroughLoRa` be sure to have [arduino-LoRa](https://github.com/sandeepmistry/arduino-LoRa) library available. Before using `ESPNOW` be sure to have installed the required tools as described [here](/src/strategies/ESPNOW/README.md). Before using `MQTTTranslate` be sure to have the [ReconnectingMqttClient](https://github.com/fredilarsen/ReconnectingMqttClient) library available. ### Network mode The network mode can be changed with `set_shared_network` during runtime, for example moving from [local](/specification/PJON-protocol-specification-v4.0.md#local-mode) to [shared](https://github.com/gioblu/PJON/blob/master/specification/PJON-protocol-specification-v4.0.md#shared-mode) mode: diff --git a/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Receiver/Receiver.ino index 28c771a724..d250511643 100644 --- a/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Receiver/Receiver.ino @@ -1,11 +1,11 @@ -#include +#include /* Use a couple of visible light / IR / UV LEDs as wireless bidirectional transceivers To know how to wire up the circuit see the AnalogSampling README: https://github.com/gioblu/PJON/tree/master/src/strategies/AnalogSampling */ // bus(selected device id) -PJON bus(44); +PJONAnalogSampling bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Transmitter/Transmitter.ino index c970c61979..121a935ce2 100644 --- a/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Transmitter/Transmitter.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(45); +PJONAnalogSampling bus(45); void setup() { pinMode(LED_BUILTIN, OUTPUT); diff --git a/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Receiver/Receiver.ino index 96ca6b86d7..6f03c9adc9 100644 --- a/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Receiver/Receiver.ino @@ -3,10 +3,10 @@ To know how to wire up the circuit see the AnalogSampling README: https://github.com/gioblu/PJON/tree/master/src/strategies/AnalogSampling */ -#include +#include // bus(selected device id) -PJON bus(44); +PJONAnalogSampling bus(44); void setup() { pinMode(LED_BUILTIN, OUTPUT); diff --git a/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Transmitter/Transmitter.ino index 2bff1ccd0f..266a358660 100644 --- a/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Transmitter/Transmitter.ino @@ -6,7 +6,7 @@ Try different resistor values to find the optimal to maximize range Higher resistance can higher the range but can also higher background noise. */ -#include +#include float test; float mistakes; @@ -14,7 +14,7 @@ int busy; int fail; // bus(selected device id) -PJON bus(45); +PJONAnalogSampling bus(45); int packet; uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Local/Any/MultiStrategyLink/Receiver/Receiver.ino b/examples/ARDUINO/Local/Any/MultiStrategyLink/Receiver/Receiver.ino index 00f0a37eaa..95bc5444ba 100644 --- a/examples/ARDUINO/Local/Any/MultiStrategyLink/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/Any/MultiStrategyLink/Receiver/Receiver.ino @@ -1,4 +1,4 @@ -#include +#include /* Defining strategies using StrategyLink template class it is possible to leverage of virtual inheritance to handle PJON instances dynamically, for @@ -7,10 +7,10 @@ StrategyLink link1; StrategyLink link2; -PJON bus1(44), bus2(45); +PJONAny bus1(44), bus2(45); const uint8_t bus_count = 2; -PJON *buses[] = { &bus1, &bus2 }; +PJONAny *buses[] = { &bus1, &bus2 }; void setup() { pinMode(LED_BUILTIN, OUTPUT); diff --git a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino index 8812350967..a4c85afc41 100644 --- a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino +++ b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino @@ -13,7 +13,7 @@ //#define SWBB_RESPONSE_TIMEOUT 1000 -#include +#include // bus(selected device id) PJON bus(1); diff --git a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino index 4b38652cd3..9fbff25405 100644 --- a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino +++ b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino @@ -13,7 +13,7 @@ //#define SWBB_RESPONSE_TIMEOUT 1000 -#include +#include // bus(selected device id) PJON bus(1); diff --git a/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Receiver/Receiver.ino index e1ce1e65c5..8738606b92 100644 --- a/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Receiver/Receiver.ino @@ -1,4 +1,4 @@ -#include +#include /* Defining strategies using StrategyLink template class it is possible to leverage of virtual inheritance to handle PJON instances dynamically, for @@ -6,7 +6,7 @@ StrategyLink link; -PJON bus(44); +PJONAny bus(44); void setup() { link.strategy.set_pin(12); diff --git a/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Transmitter/Transmitter.ino index 1af2986715..70bd92094d 100644 --- a/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Transmitter/Transmitter.ino @@ -12,7 +12,7 @@ devices are near and able to compute CRC fast enough. */ //#define SWBB_RESPONSE_TIMEOUT 1000 -#include +#include float test; float mistakes; @@ -21,7 +21,7 @@ int fail; StrategyLink link; -PJON bus(44); +PJONAny bus(44); int packet; uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Local/DualUDP/PingPong/Receiver/Receiver.ino b/examples/ARDUINO/Local/DualUDP/PingPong/Receiver/Receiver.ino index 84cfa298d7..a1b178c4c6 100644 --- a/examples/ARDUINO/Local/DualUDP/PingPong/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/DualUDP/PingPong/Receiver/Receiver.ino @@ -1,10 +1,10 @@ -#include +#include // Ethernet configuration for this device byte mac[] = {0xDA, 0x5A, 0x4E, 0xEF, 0xAE, 0xED}; // bus(selected device id) -PJON bus(44); +PJONDualUDP bus(44); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ARDUINO/Local/DualUDP/PingPong/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/DualUDP/PingPong/Transmitter/Transmitter.ino index 64810133e5..9bf4b028e3 100644 --- a/examples/ARDUINO/Local/DualUDP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/DualUDP/PingPong/Transmitter/Transmitter.ino @@ -1,10 +1,10 @@ -#include +#include // Ethernet configuration for this device byte mac[] = {0xDA, 0xCA, 0x7E, 0xEF, 0xFE, 0x5D}; // bus(selected device id) -PJON bus(45); +PJONDualUDP bus(45); uint32_t cnt = 0, wait_for_reply = 0; uint32_t start = millis(); diff --git a/examples/ARDUINO/Local/EthernetTCP/PingPong/Receiver/Receiver.ino b/examples/ARDUINO/Local/EthernetTCP/PingPong/Receiver/Receiver.ino index 682d5718c3..824022a36c 100644 --- a/examples/ARDUINO/Local/EthernetTCP/PingPong/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/EthernetTCP/PingPong/Receiver/Receiver.ino @@ -1,4 +1,4 @@ -#include +#include // Ethernet configuration for this device byte gateway[] = { 192, 1, 1, 1 }; @@ -8,7 +8,7 @@ uint8_t local_ip[] = { 192, 1, 1, 144 }, remote_ip[] = { 192, 1, 1, 145 }; // bus(selected device id) -PJON bus(44); +PJONEthernetTCP bus(44); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ARDUINO/Local/EthernetTCP/PingPong/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/EthernetTCP/PingPong/Transmitter/Transmitter.ino index bb64946980..a09fce777c 100644 --- a/examples/ARDUINO/Local/EthernetTCP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/EthernetTCP/PingPong/Transmitter/Transmitter.ino @@ -1,4 +1,4 @@ -#include +#include // Ethernet configuration for this device byte gateway[] = { 192, 1, 1, 1 }; @@ -8,7 +8,7 @@ uint8_t local_ip[] = { 192, 1, 1, 145 }, remote_ip[] = { 192, 1, 1, 144 }; // bus(selected device id) -PJON bus(45); +PJONEthernetTCP bus(45); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/RemoteWorker/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/RemoteWorker/Transmitter/Transmitter.ino index e18243c6b6..9d65c6e71b 100644 --- a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/RemoteWorker/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/RemoteWorker/Transmitter/Transmitter.ino @@ -25,10 +25,10 @@ #define ETCP_SINGLE_DIRECTION //#define ETCP_SINGLE_SOCKET_WITH_ACK -#include +#include // bus(selected device id) -PJON bus(45); +PJONEthernetTCP bus(45); // Ethernet configuration for this device uint8_t gateway[] = { 192, 1, 1, 1 }; diff --git a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino index c2e2677c9c..3d465a439f 100644 --- a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino +++ b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino @@ -14,14 +14,14 @@ #define ETCP_SINGLE_DIRECTION //#define ETCP_SINGLE_SOCKET_WITH_ACK -#include +#include const uint8_t DEVICE_ID = 45; // SWBB Device ID for this device and the RemoteWorker // bus(selected device id) PJON busA(DEVICE_ID); -PJON busB(1); +PJONEthernetTCP busB(1); // Ethernet configuration for this device uint8_t gateway[] = { 192, 1, 1, 1 }; diff --git a/examples/ARDUINO/Local/GlobalUDP/PingPong/Receiver/Receiver.ino b/examples/ARDUINO/Local/GlobalUDP/PingPong/Receiver/Receiver.ino index 43d9b88813..3d7dcb4b08 100644 --- a/examples/ARDUINO/Local/GlobalUDP/PingPong/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/GlobalUDP/PingPong/Receiver/Receiver.ino @@ -1,4 +1,4 @@ -#include +#include // Ethernet configuration for this device byte gateway[] = { 192, 1, 1, 1 }; @@ -10,7 +10,7 @@ uint8_t local_ip[] = { 192, 1, 1, 151 }; uint8_t remote_ip[] = { 192, 1, 1, 150 }; // bus(selected device id) -PJON bus(44); +PJONGlobalUDP bus(44); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ARDUINO/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino index 055f4c9423..f1300e8f08 100644 --- a/examples/ARDUINO/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino @@ -1,4 +1,4 @@ -#include +#include // Ethernet configuration for this device byte gateway[] = { 192, 1, 1, 1 }; @@ -10,7 +10,7 @@ uint8_t local_ip[] = { 192, 1, 1, 150 }; uint8_t remote_ip[] = { 192, 1, 1, 151 }; // bus(selected device id) -PJON bus(45); +PJONGlobalUDP bus(45); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ARDUINO/Local/LocalUDP/PingPong/Receiver/Receiver.ino b/examples/ARDUINO/Local/LocalUDP/PingPong/Receiver/Receiver.ino index 4940e4113f..cc3c3cc6c6 100644 --- a/examples/ARDUINO/Local/LocalUDP/PingPong/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/LocalUDP/PingPong/Receiver/Receiver.ino @@ -1,4 +1,4 @@ -#include +#include // Ethernet configuration for this device byte gateway[] = { 192, 1, 1, 1 }; @@ -7,7 +7,7 @@ byte mac[] = {0xDA, 0x5A, 0x4E, 0xEF, 0xAE, 0xED}; uint8_t local_ip[] = { 192, 1, 1, 151 }; // bus(selected device id) -PJON bus(44); +PJONLocalUDP bus(44); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ARDUINO/Local/LocalUDP/PingPong/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/LocalUDP/PingPong/Transmitter/Transmitter.ino index e82a56db93..e2e246add4 100644 --- a/examples/ARDUINO/Local/LocalUDP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/LocalUDP/PingPong/Transmitter/Transmitter.ino @@ -1,4 +1,4 @@ -#include +#include // Ethernet configuration for this device byte gateway[] = { 192, 1, 1, 1 }; @@ -7,7 +7,7 @@ byte mac[] = {0xDA, 0xCA, 0x7E, 0xEF, 0xFE, 0x5D}; uint8_t local_ip[] = { 192, 1, 1, 150 }; // bus(selected device id) -PJON bus(45); +PJONLocalUDP bus(45); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ARDUINO/Local/MQTTTranslate/PingPong/Receiver/Receiver.ino b/examples/ARDUINO/Local/MQTTTranslate/PingPong/Receiver/Receiver.ino index 804812720b..92a06d6032 100644 --- a/examples/ARDUINO/Local/MQTTTranslate/PingPong/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/MQTTTranslate/PingPong/Receiver/Receiver.ino @@ -1,12 +1,12 @@ -#define PJON_INCLUDE_MQTT -#include + +#include // Ethernet configuration for this device byte mac[] = {0xDE, 0x5A, 0x4E, 0xEF, 0xAE, 0xED}; uint8_t broker_ip[] = { 192, 1, 1, 71 }; // bus(selected device id) -PJON bus(44); +PJONMQTTTranslate bus(44); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ARDUINO/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.ino index ed9dff6bc8..e07bd155ab 100644 --- a/examples/ARDUINO/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.ino @@ -1,12 +1,12 @@ -#define PJON_INCLUDE_MQTT -#include + +#include // Ethernet configuration for this device byte mac[] = {0xDA, 0xCA, 0x7E, 0xEF, 0xFE, 0x5D}; uint8_t broker_ip[] = { 192, 1, 1, 71 }; // bus(selected device id) -PJON bus(45); +PJONMQTTTranslate bus(45); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino index 505011b93e..b3e54cf6d9 100644 --- a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino +++ b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino @@ -1,8 +1,8 @@ -#define PJON_INCLUDE_MQTT + #define MQTTT_MODE MQTTT_MODE_MIRROR_DIRECT -#define PJON_INCLUDE_SWBB + #define PJON_MAX_PACKETS 2 -#include +#include // Ethernet configuration for this device byte mac[] = {0xDA, 0xCA, 0x7E, 0xEF, 0xFE, 0x5D}; @@ -11,7 +11,7 @@ uint8_t broker_ip[] = { 192, 168, 1, 71 }; // bus(selected device id) #define PJON_GATEWAY_ID 254 PJON bus(PJON_GATEWAY_ID); -PJON mqtt; +PJONMQTTTranslate mqtt; uint32_t cnt_to_mqtt = 0, cnt_from_mqtt = 0; uint32_t start = millis(); diff --git a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino index 06e9a5f874..a79de74505 100644 --- a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino +++ b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino @@ -1,19 +1,19 @@ // This PJON device is a simulated environmental controller, trying to change -// temperature so that measurement is equal to the target that can be set +// temperature so that measurement is equal to the target that can be set // from other devices. In this case we will let it send messages to and receive // messages from another device which is this setup is an MQTT gateway. -// Using the free MQTT Explorer or similar, publish the value "temperature=24" +// Using the free MQTT Explorer or similar, publish the value "temperature=24" // to the topic pjon/device42/input. Observe the value of the topic // pjon/device42/output change gradually from "temperature=20" to "temperature=24". // NOTE: The gateway used in this setup is using MIRROR_DIRECT mode, just forwarding // packets both ways without trying to locate or translate variable names, -// therefore packets are sent to pjon/device42/output instead of -// pjon/device42/output/temperature as would have been the case with +// therefore packets are sent to pjon/device42/output instead of +// pjon/device42/output/temperature as would have been the case with // the MIRROR_TRANSLATE mode. -#include +#include #define PJON_GATEWAY_ID 254 @@ -58,4 +58,4 @@ void loop() { // Adjust to get closer to target, simulate a regulator temperature += (temperature_target - temperature) / 20; } -}; \ No newline at end of file +}; diff --git a/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device1/Device1.ino b/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device1/Device1.ino index 7b9bf66102..cb58c120d7 100644 --- a/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device1/Device1.ino +++ b/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device1/Device1.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(44); +PJONOverSampling bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device2/Device2.ino b/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device2/Device2.ino index db103c94d4..1b7ceeac39 100644 --- a/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device2/Device2.ino +++ b/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device2/Device2.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(45); +PJONOverSampling bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino b/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino index 84e86b4341..03539c763c 100644 --- a/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino +++ b/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(44); +PJONOverSampling bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino b/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino index 22e71b4911..49c37802a2 100644 --- a/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino +++ b/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(45); +PJONOverSampling bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Receiver/Receiver.ino index fa8e50c7dc..985e621706 100644 --- a/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Receiver/Receiver.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(44); +PJONOverSampling bus(44); void setup() { /* When using more than one pin always use pins connected to diff --git a/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino index 670254bff8..f374a3917e 100644 --- a/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino @@ -1,4 +1,4 @@ -#include +#include float test; float mistakes; @@ -6,7 +6,7 @@ int busy; int fail; // bus(selected device id) -PJON bus(45); +PJONOverSampling bus(45); int packet; uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Local/OverSampling/Simplex/Receiver/Receiver.ino b/examples/ARDUINO/Local/OverSampling/Simplex/Receiver/Receiver.ino index a404782ff4..445b20ddaf 100644 --- a/examples/ARDUINO/Local/OverSampling/Simplex/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/OverSampling/Simplex/Receiver/Receiver.ino @@ -1,5 +1,5 @@ -#include +#include float test; float mistakes; @@ -8,7 +8,7 @@ int fail; // bus(selected device id) -PJON bus(44); +PJONOverSampling bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { // Do nothing to avoid affecting speed analysis diff --git a/examples/ARDUINO/Local/OverSampling/Simplex/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/OverSampling/Simplex/Transmitter/Transmitter.ino index 10c7dbb86d..1cf7524867 100644 --- a/examples/ARDUINO/Local/OverSampling/Simplex/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/OverSampling/Simplex/Transmitter/Transmitter.ino @@ -1,8 +1,8 @@ -#include +#include // bus(selected device id) -PJON bus(45); +PJONOverSampling bus(45); uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino index 7db2f3a433..614034a2a2 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(44); +PJONSoftwareBitBang bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino index 2778f9ac16..50e89e121f 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(45); +PJONSoftwareBitBang bus(45); void setup() { bus.strategy.set_pin(12); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Receiver/Receiver.ino index 720f0c4685..0e839025d5 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Receiver/Receiver.ino @@ -1,10 +1,10 @@ -#define PJON_INCLUDE_SWBB + #define PJON_INCLUDE_MAC -#include +#include // bus(mac address of the network interface) const uint8_t mac[6] = {1, 2, 3, 4, 5, 6}; -PJON bus(mac); +PJONSoftwareBitBang bus(mac); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Transmitter/Transmitter.ino index 147b35034a..9fa75cce71 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTestMAC/Transmitter/Transmitter.ino @@ -1,10 +1,10 @@ #define PJON_INCLUDE_MAC -#include +#include // bus(mac address of the network interface) const uint8_t mac[6] = {2, 3, 4, 5, 6, 7}; const uint8_t rx_mac[6] = {1, 2, 3, 4, 5, 6}; -PJON bus(mac); +PJONSoftwareBitBang bus(mac); void setup() { bus.strategy.set_pin(12); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Receiver/Receiver.ino index efe013f2e6..2d686ce56b 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Receiver/Receiver.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(44); +PJONSoftwareBitBang bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Transmitter/Transmitter.ino index faed57ceaf..786f0fdb0f 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Transmitter/Transmitter.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(45); +PJONSoftwareBitBang bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino index a5cc4bddc7..88f4b423c6 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino @@ -11,10 +11,10 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 -#include +#include // bus(selected device id) -PJON bus(44); +PJONSoftwareBitBang bus(44); // Custom class class MyClass { diff --git a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino index 83bb06add6..dc8f22651f 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino @@ -11,10 +11,10 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 -#include +#include // bus(selected device id) -PJON bus(45); +PJONSoftwareBitBang bus(45); int packet; uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino index d020e972f0..936fc69db0 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino @@ -11,10 +11,10 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 -#include +#include // bus(selected device id) -PJON bus(44); +PJONSoftwareBitBang bus(44); void setup() { bus.strategy.set_pin(12); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino index 56fa5b6206..9199f426cc 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino @@ -11,7 +11,7 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 -#include +#include float test; float mistakes; @@ -19,7 +19,7 @@ int busy; int fail; // bus(selected device id) -PJON bus(45); +PJONSoftwareBitBang bus(45); int packet; uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino index 6efb630b2f..391275f1ca 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino @@ -1,6 +1,6 @@ // Include only SoftwareBitBang -#define PJON_INCLUDE_SWBB + // Set maximum packet length #define PJON_PACKET_MAX_LENGTH 10 // Include PJONLocal diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Transmitter/Transmitter.ino index bad8ab65bb..4a06206d7f 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Transmitter/Transmitter.ino @@ -1,6 +1,6 @@ // Include only SoftwareBitBang -#define PJON_INCLUDE_SWBB + // Set maximum packet length #define PJON_PACKET_MAX_LENGTH 10 // Include PJONLocal diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino index 8eb3aba50c..20c8036881 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino @@ -12,7 +12,7 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 // Include only SoftwareBitBang -#define PJON_INCLUDE_SWBB + // Include PJONLocal #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino index 65ee27d3e4..5c0c92874b 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino @@ -12,7 +12,7 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 // Include only SoftwareBitBang -#define PJON_INCLUDE_SWBB + // Include PJONLocal #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino index e24aaea759..745499f5fc 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino @@ -3,7 +3,7 @@ is printed the record transmitted by the other device. */ // Include only SoftwareBitBang -#define PJON_INCLUDE_SWBB + // Include PJONLocal #include // bus(selected device id) diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino index ac880b218e..8ac3496b89 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino @@ -2,7 +2,7 @@ This sketch contains the transmitter side. */ // Include only SoftwareBitBang -#define PJON_INCLUDE_SWBB + // Include PJONLocal #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino index bc2362ce56..2284f589ca 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino @@ -12,7 +12,7 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -#include +#include SoftwareBitBang swbb; uint32_t attempts = 100000; // Number of random string reception attempts diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Transmitter/Transmitter.ino index 23d81f804a..b8fd0077ce 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Transmitter/Transmitter.ino @@ -12,7 +12,7 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -#include +#include SoftwareBitBang swbb; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino index 5ccd572e7c..4602481374 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino @@ -11,10 +11,10 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 -#include +#include // bus(selected device id) -PJON bus(44); +PJONSoftwareBitBang bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino index efc01733be..73f92af246 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino @@ -11,10 +11,10 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 -#include +#include // bus(selected device id) -PJON bus(45); +PJONSoftwareBitBang bus(45); void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { if(code == PJON_CONNECTION_LOST) { diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Receiver/Receiver.ino index be630af822..87919e2818 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Receiver/Receiver.ino @@ -1,10 +1,10 @@ -#include +#include /* ARBITRARY DATA TYPE RECEPTION EXAMPLE This sketch contains the receiver side. In the Serial monitor is printed the record transmitted by the other device. */ // PJON object -PJON bus(44); +PJONSoftwareBitBang bus(44); /* A custom struct is defined just to clarify that any kind of custom data type can be easily transmitted using the PJON send functions. */ diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Transmitter/Transmitter.ino index f2d12f606a..a1a4ec2150 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Transmitter/Transmitter.ino @@ -1,10 +1,10 @@ -#include +#include /* ARBITRARY DATA TYPE TRANSMISSION EXAMPLE This sketch contains the transmitter side. */ // bus(selected device id) -PJON bus(45); +PJONSoftwareBitBang bus(45); int packet; int voltage; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino index 7b1d7ed84b..42555944b9 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino @@ -1,4 +1,4 @@ -#include +#include /* VOLTAGE TESTER DEVICE This is a basic example to show how PJON can be used practically. Lets print in the Serial monitor the voltage detected by the analog @@ -8,7 +8,7 @@ is printed the voltage detected and transmitted by the other device. */ // PJON object -PJON bus(44); +PJONSoftwareBitBang bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino index a8adef9430..53dcc8de20 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino @@ -1,5 +1,5 @@ -#include +#include /* VOLTAGE TESTER DEVICE This is a basic example to show how PJON can be used practically. Lets print in the Serial monitor the voltage detected by the analog @@ -10,7 +10,7 @@ for easy benchmarking and nominal functionality assessment. */ // bus(selected device id) -PJON bus(45); +PJONSoftwareBitBang bus(45); uint32_t myTime; int packet; int voltage; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino index 706a0f824d..0a7f651668 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino @@ -11,7 +11,7 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 -#include +#include float test; float mistakes; @@ -19,7 +19,7 @@ int busy; int fail; // bus(selected device id) -PJON bus(44); +PJONSoftwareBitBang bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { // Do nothing to avoid affecting speed analysis diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino index 0fae1e6091..6d2cf9ca2b 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino @@ -11,10 +11,10 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 -#include +#include // bus(selected device id) -PJON bus(45); +PJONSoftwareBitBang bus(45); uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino index 133d844a0d..48168d3b94 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino @@ -14,7 +14,7 @@ // Include packet id feature #define PJON_INCLUDE_PACKET_ID -#include +#include float test; float mistakes; @@ -22,7 +22,7 @@ int busy; int fail; // bus(selected device id) -PJON bus(44); +PJONSoftwareBitBang bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { Serial.print("Packet id: "); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino index 344d2dd6a3..7d4c6b5e56 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino @@ -14,10 +14,10 @@ // Include packet id feature #define PJON_INCLUDE_PACKET_ID -#include +#include // bus(selected device id) -PJON bus(45); +PJONSoftwareBitBang bus(45); int packet; uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino index 442d8dd8d7..c11fff1b2f 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino @@ -1,13 +1,13 @@ -#define PJON_INCLUDE_TL -#include + +#include /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ // bus(selected device id) -PJON bus(44); +PJONThroughLora bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino index fb9a18b9c0..c4bdfaef9a 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino @@ -1,12 +1,12 @@ -#define PJON_INCLUDE_TL -#include + +#include /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ // bus(selected device id) -PJON bus(45); +PJONThroughLora bus(45); void setup() { // Synchronous acknowledgement is not supported diff --git a/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino b/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino index 0b60c4e853..720bf22dda 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino @@ -1,13 +1,13 @@ -#define PJON_INCLUDE_TL -#include + +#include /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ // bus(selected device id) -PJON bus(44); +PJONThroughLora bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino b/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino index 30984fe768..11b8085874 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino @@ -1,13 +1,13 @@ -#define PJON_INCLUDE_TL -#include + +#include /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ // bus(selected device id) -PJON bus(45); +PJONThroughLora bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/ThroughLoRa/JSON/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughLoRa/JSON/Receiver/Receiver.ino index 26eb93ae30..0842f2e318 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/JSON/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/JSON/Receiver/Receiver.ino @@ -1,14 +1,14 @@ -#define PJON_INCLUDE_TL -#include + +#include #include /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ and JSON library from https://github.com/bblanchon/ArduinoJson */ -PJON LoraPJON(44); +PJONThroughLora LoraPJON(44); void setup() { Serial.begin(115200); diff --git a/examples/ARDUINO/Local/ThroughLoRa/JSON/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughLoRa/JSON/Transmitter/Transmitter.ino index 250dddd61f..c8a773cfc4 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/JSON/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/JSON/Transmitter/Transmitter.ino @@ -1,8 +1,8 @@ -#define PJON_INCLUDE_TL + #include -#include +#include #include /* To use this example, please download the LoRa third party Library @@ -11,7 +11,7 @@ #define EVENT_TIME 1000 //1 message every 1 second -PJON LoraPJON(45); +PJONThroughLora LoraPJON(45); void setup() { Serial.begin(115200); diff --git a/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino index e5bb54b6c2..06095ad566 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino @@ -1,13 +1,13 @@ -#define PJON_INCLUDE_TL -#include + +#include /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ // bus(selected device id) -PJON bus(44); +PJONThroughLora bus(44); void setup() { // Synchronous acknowledgement is not supported diff --git a/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino index 22a3db819b..b3f494327d 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino @@ -1,7 +1,7 @@ -#define PJON_INCLUDE_TL -#include + +#include /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ @@ -12,7 +12,7 @@ int busy; int fail; // bus(selected device id) -PJON bus(45); +PJONThroughLora bus(45); int packet; uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Local/ThroughLoRa/Simplex/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughLoRa/Simplex/Receiver/Receiver.ino index 89cbd68498..7c8f7d7e30 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/Simplex/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/Simplex/Receiver/Receiver.ino @@ -1,7 +1,7 @@ -#define PJON_INCLUDE_TL -#include + +#include /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ @@ -11,7 +11,7 @@ int busy; int fail; // bus(selected device id) -PJON bus(44); +PJONThroughLora bus(44); void setup() { // Obligatory to initialize Radio with correct frequency diff --git a/examples/ARDUINO/Local/ThroughLoRa/Simplex/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughLoRa/Simplex/Transmitter/Transmitter.ino index f68f39b105..1b8e523e9b 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/Simplex/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/Simplex/Transmitter/Transmitter.ino @@ -1,7 +1,7 @@ -#define PJON_INCLUDE_TL -#include + +#include /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ @@ -12,7 +12,7 @@ int busy; int fail; // bus(selected device id) -PJON bus(45); +PJONThroughLora bus(45); int packet; uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Receiver/Receiver.ino index 60d8ebff15..54872ae39d 100644 --- a/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Receiver/Receiver.ino @@ -1,10 +1,11 @@ -#include -PJON bus(44); +#include + +PJONThroughSerial bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { - /* Make use of the payload before sending something, the buffer where payload points to is - overwritten when a new message is dispatched */ + /* Make use of the payload before sending something, the buffer where payload points to is + overwritten when a new message is dispatched */ if(payload[0] == 'B') { digitalWrite(LED_BUILTIN, HIGH); delay(30); @@ -15,12 +16,10 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info void setup() { pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); // Initialize LED 13 to be off - Serial.begin(9600); bus.strategy.set_serial(&Serial); - bus.begin(); - bus.set_receiver(receiver_function); + bus.begin(); }; void loop() { diff --git a/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.ino index bfe7229718..753df3288c 100644 --- a/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.ino @@ -1,7 +1,7 @@ -#include +#include -PJON bus(45); +PJONThroughSerial bus(45); void setup() { Serial.begin(9600); diff --git a/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino index 9efa95bb20..7f0fe5343b 100644 --- a/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.ino @@ -1,6 +1,7 @@ -#include -PJON bus(44); +#include + +PJONThroughSerial bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.ino index bf1dc83f34..49964ad217 100644 --- a/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.ino @@ -1,7 +1,7 @@ -#include +#include -PJON bus(45); +PJONThroughSerial bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Receiver/Receiver.ino index 9a662bddbf..6cd33cc3cf 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Receiver/Receiver.ino @@ -4,13 +4,13 @@ emulated Serial port is used on pin 2 and 3 to communicate with HC12. The receiver device should blink every second.*/ -#include +#include #include SoftwareSerial HC12(2, 3); // bus(selected device id) -PJON bus(44); +PJONThroughSerial bus(44); void setup() { // Initialize LED 13 to be off diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino index dc72840008..d39222b507 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino @@ -4,13 +4,13 @@ emulated Serial port is used on pin 2 and 3 to communicate with HC12. The receiver device should blink every second. */ -#include +#include #include SoftwareSerial HC12(2, 3); // bus(selected device id) -PJON bus(45); +PJONThroughSerial bus(45); void setup() { // Set HC12 baudrate (you must use the one configured in HC12, default 9600) diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino index c7fd123661..493cedd7d9 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino @@ -39,13 +39,13 @@ supporting up to 64 bytes maximum packet length */ #define PJON_PACKET_MAX_LENGTH 63 -#include +#include #include SoftwareSerial HC12(2, 3); // bus(selected device id) -PJON bus; +PJONThroughSerial bus; uint8_t packet[100]; String string_number; diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Receiver/Receiver.ino index a5b5f80832..6f9510c073 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Receiver/Receiver.ino @@ -9,13 +9,13 @@ If operating at less than 9600Bd TS_RESPONSE_TIME_OUT should be longer */ #define TS_RESPONSE_TIME_OUT 100000 -#include +#include #include SoftwareSerial HC12(2, 3); // bus(selected device id) -PJON bus(44); +PJONThroughSerial bus(44); void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { if(code == PJON_CONNECTION_LOST) { diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Transmitter/Transmitter.ino index 51026294dc..55e6f4eff9 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Transmitter/Transmitter.ino @@ -9,13 +9,13 @@ If operating at less than 9600Bd TS_RESPONSE_TIME_OUT should be longer */ #define TS_RESPONSE_TIME_OUT 100000 -#include +#include #include SoftwareSerial HC12(2, 3); // bus(selected device id) -PJON bus(45); +PJONThroughSerial bus(45); void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { if(code == PJON_CONNECTION_LOST) { diff --git a/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Receiver/Receiver.ino index fc11713114..9d8bba6650 100644 --- a/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Receiver/Receiver.ino @@ -1,12 +1,12 @@ /* Include only ThroughSerial (not all data-link are still compatible with STM32 microcontrollers) */ -#define PJON_INCLUDE_TS true -#include + +#include // bus(selected device id) -PJON bus(44); +PJONThroughSerial bus(44); void setup() { pinMode(LED_BUILTIN, OUTPUT); diff --git a/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Transmitter/Transmitter.ino index 83e28a0e44..58693f032a 100644 --- a/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Transmitter/Transmitter.ino @@ -1,12 +1,12 @@ /* Include only ThroughSerial (not all data-link are still compatible with STM32 microcontrollers) */ -#define PJON_INCLUDE_TS true -#include + +#include // bus(selected device id) -PJON bus(45); +PJONThroughSerial bus(45); void setup() { // Serial1 or pin 2 and 8 on F401RE and L053R8 diff --git a/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Receiver/Receiver.ino index 4be8ae2450..37638ab185 100644 --- a/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Receiver/Receiver.ino @@ -1,10 +1,10 @@ /* PJON MAX485 serial modules RS485 communication example */ -#include +#include // bus(selected device id) -PJON bus(44); +PJONThroughSerial bus(44); void setup() { // Initialize LED 13 to be off diff --git a/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Transmitter/Transmitter.ino index 64df10f62f..65d0fa5ef6 100644 --- a/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Transmitter/Transmitter.ino @@ -1,10 +1,10 @@ /* PJON MAX485 serial modules RS485 communication example */ -#include +#include // bus(selected device id) -PJON bus(45); +PJONThroughSerial bus(45); void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { if(code == PJON_CONNECTION_LOST) diff --git a/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Receiver/Receiver.ino index e6cd650b0f..ee847f8c5a 100644 --- a/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Receiver/Receiver.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(44); +PJONThroughSerial bus(44); void setup() { pinMode(13, OUTPUT); diff --git a/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter/Transmitter.ino index 57eaa6dc05..b319ee25d3 100644 --- a/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter/Transmitter.ino @@ -1,10 +1,10 @@ /* PJON MAX485 serial modules RS485 communication example */ -#include +#include // bus(selected device id) -PJON bus(45); +PJONThroughSerial bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino b/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino index 9ddcf82bfb..ac0dd55023 100644 --- a/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino +++ b/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino @@ -14,7 +14,7 @@ //#define ETCP_SINGLE_DIRECTION ////#define ETCP_SINGLE_SOCKET_WITH_ACK -#include +#include const uint8_t DEVICE_ID = 45; // SWBB Device ID for this device and the RemoteWorker @@ -22,7 +22,7 @@ const uint8_t DEVICE_ID = 45; // bus(selected device id) PJON busA(DEVICE_ID); //PJON busB(1); -PJON busB(1); +PJONThroughSerial busB(1); //// Ethernet configuration for this device //uint8_t gateway[] = { 192, 1, 1, 1 }; diff --git a/examples/ARDUINO/Network/OverSampling/HalfDuplex/Receiver/Receiver.ino b/examples/ARDUINO/Network/OverSampling/HalfDuplex/Receiver/Receiver.ino index fa06c763a1..1e032eda87 100644 --- a/examples/ARDUINO/Network/OverSampling/HalfDuplex/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/OverSampling/HalfDuplex/Receiver/Receiver.ino @@ -1,10 +1,10 @@ -#include +#include uint8_t bus_id[] = {0, 0, 0, 1}; // bus(selected device id) -PJON bus(bus_id, 44); +PJONOverSampling bus(bus_id, 44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Network/OverSampling/HalfDuplex/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/OverSampling/HalfDuplex/Transmitter/Transmitter.ino index 76d7708fa7..b8f0ecd73e 100644 --- a/examples/ARDUINO/Network/OverSampling/HalfDuplex/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/OverSampling/HalfDuplex/Transmitter/Transmitter.ino @@ -1,10 +1,10 @@ -#include +#include uint16_t packet; uint8_t bus_id[] = {0, 0, 0, 1}; // bus(selected device id) -PJON bus(bus_id, 45); +PJONOverSampling bus(bus_id, 45); void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { if(code == PJON_CONNECTION_LOST) { diff --git a/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino b/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino index 4bb2ad571d..7e8b59ff5e 100644 --- a/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino +++ b/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino @@ -1,10 +1,10 @@ -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 44); +PJONOverSampling bus(bus_id, 44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino b/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino index 089cdb5dff..2abc9e9c1e 100644 --- a/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino +++ b/examples/ARDUINO/Network/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino @@ -1,10 +1,10 @@ -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 45); +PJONOverSampling bus(bus_id, 45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Network/OverSampling/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Network/OverSampling/NetworkAnalysis/Receiver/Receiver.ino index 7e29fb9366..4d485400f2 100644 --- a/examples/ARDUINO/Network/OverSampling/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/OverSampling/NetworkAnalysis/Receiver/Receiver.ino @@ -1,10 +1,10 @@ -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 44); +PJONOverSampling bus(bus_id, 44); void setup() { /* When using more than one pin always use pins connected to diff --git a/examples/ARDUINO/Network/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino index d4d0ee0010..c2c38ad59d 100644 --- a/examples/ARDUINO/Network/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino @@ -1,4 +1,4 @@ -#include +#include float test; float mistakes; @@ -9,7 +9,7 @@ int fail; uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 44); +PJONOverSampling bus(bus_id, 44); int packet; uint8_t content[] = "01234567890123456789"; // First 4 bytes left empty for bus id diff --git a/examples/ARDUINO/Network/OverSampling/Simplex/Receiver/Receiver.ino b/examples/ARDUINO/Network/OverSampling/Simplex/Receiver/Receiver.ino index 3d340aec62..b66f522961 100644 --- a/examples/ARDUINO/Network/OverSampling/Simplex/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/OverSampling/Simplex/Receiver/Receiver.ino @@ -1,5 +1,5 @@ -#include +#include float test; float mistakes; @@ -10,7 +10,7 @@ int fail; uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 44); +PJONOverSampling bus(bus_id, 44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { // Do nothing to avoid affecting speed analysis diff --git a/examples/ARDUINO/Network/OverSampling/Simplex/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/OverSampling/Simplex/Transmitter/Transmitter.ino index 914553a5b8..3f684c1c1a 100644 --- a/examples/ARDUINO/Network/OverSampling/Simplex/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/OverSampling/Simplex/Transmitter/Transmitter.ino @@ -1,11 +1,11 @@ -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 45); +PJONOverSampling bus(bus_id, 45); uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino index 82b9cab0a3..01f424f2d4 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino @@ -1,10 +1,10 @@ -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 44); +PJONSoftwareBitBang bus(bus_id, 44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Network/SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino index a2c8a566bf..40dbbaf894 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino @@ -1,10 +1,10 @@ -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 45); +PJONSoftwareBitBang bus(bus_id, 45); void setup() { bus.strategy.set_pin(12); diff --git a/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino index 9dc246a29f..6fc1b99278 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino @@ -9,7 +9,7 @@ the receiver to compute CRC32 of a 300 bytes string. */ #define SWBB_RESPONSE_TIMEOUT 4000 -#include +#include float test; float mistakes; @@ -25,7 +25,7 @@ uint8_t bus_id[] = {0, 0, 0, 1}; bool debug = true; // PJON object -PJON bus(bus_id, 44); +PJONSoftwareBitBang bus(bus_id, 44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Transmitter/Transmitter.ino index 6d30961dac..d0885bfbb2 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Transmitter/Transmitter.ino @@ -9,13 +9,13 @@ the receiver to compute CRC32 of a 300 bytes string. */ #define SWBB_RESPONSE_TIMEOUT 4000 -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 45); +PJONSoftwareBitBang bus(bus_id, 45); uint8_t content[] = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino index 82296d2495..30ecc2c15e 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino @@ -12,13 +12,13 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 44); +PJONSoftwareBitBang bus(bus_id, 44); void setup() { bus.strategy.set_pin(12); diff --git a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino index 065121ed15..6e1ef28848 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino @@ -11,20 +11,18 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 - -#include +#include float test; float mistakes; int busy; int fail; -uint8_t header; // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 45); +PJONSoftwareBitBang bus(bus_id, 45); int packet; uint8_t content[] = "01234567890123456789"; // First 10 bytes left empty for bus id diff --git a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino index 816c35b60e..ac18a154f2 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Receiver/Receiver.ino @@ -1,5 +1,5 @@ #define PJON_INCLUDE_PORT -#include +#include int busy; bool debug = true; @@ -11,7 +11,7 @@ float test; uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 44); +PJONSoftwareBitBang bus(bus_id, 44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Transmitter/Transmitter.ino index 1e8408bd57..96f3cf03eb 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/PortsUseExample/Transmitter/Transmitter.ino @@ -1,10 +1,10 @@ #define PJON_INCLUDE_PORT -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 45); +PJONSoftwareBitBang bus(bus_id, 45); int packet; uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SendAndReceive/Device1/Device1.ino b/examples/ARDUINO/Network/SoftwareBitBang/SendAndReceive/Device1/Device1.ino index 0c97acba1f..245ba65206 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SendAndReceive/Device1/Device1.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SendAndReceive/Device1/Device1.ino @@ -1,10 +1,10 @@ -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 44); +PJONSoftwareBitBang bus(bus_id, 44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SendAndReceive/Device2/Device2.ino b/examples/ARDUINO/Network/SoftwareBitBang/SendAndReceive/Device2/Device2.ino index a2ce9d789c..41ecdfca0c 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SendAndReceive/Device2/Device2.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SendAndReceive/Device2/Device2.ino @@ -1,10 +1,10 @@ -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 45); +PJONSoftwareBitBang bus(bus_id, 45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino index 723b162b45..01836c1502 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Receiver/Receiver.ino @@ -1,4 +1,4 @@ -#include +#include /* VOLTAGE TESTER DEVICE This is a basic example to show how PJON can be used practically. Lets print in the Serial monitor the voltage detected by the analog @@ -11,7 +11,7 @@ uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 44); +PJONSoftwareBitBang bus(bus_id, 44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino index 4b47ad4434..fcd4ed0bfe 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino @@ -1,4 +1,4 @@ -#include +#include /* VOLTAGE TESTER DEVICE This is a basic example to show how PJON can be used practically. Lets print in the Serial monitor the voltage detected by the analog @@ -15,7 +15,7 @@ int packet; int voltage; // PJON object -PJON bus(bus_id, 45); +PJONSoftwareBitBang bus(bus_id, 45); void setup() { bus.strategy.set_pin(12); diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino index 295685912f..c01826f7c0 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino @@ -12,7 +12,7 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 -#include +#include float test; float mistakes; @@ -24,7 +24,7 @@ bool debug = false; uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 44); +PJONSoftwareBitBang bus(bus_id, 44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino index d6cbfd6f38..37d9d044db 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino @@ -11,13 +11,13 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 45); +PJONSoftwareBitBang bus(bus_id, 45); uint8_t content[] = "01234567890123456789"; diff --git a/examples/ESP32/DualUDP/PingPong/Receiver/Receiver.ino b/examples/ESP32/DualUDP/PingPong/Receiver/Receiver.ino index 11f4428214..6564c6e2b1 100644 --- a/examples/ESP32/DualUDP/PingPong/Receiver/Receiver.ino +++ b/examples/ESP32/DualUDP/PingPong/Receiver/Receiver.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(44); +PJONDualUDP bus(44); const char* ssid = "MyNetworkSSID"; const char* password = "MyNetworkPassword"; diff --git a/examples/ESP32/DualUDP/PingPong/Transmitter/Transmitter.ino b/examples/ESP32/DualUDP/PingPong/Transmitter/Transmitter.ino index a5499ecbe7..9d94c0834c 100644 --- a/examples/ESP32/DualUDP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ESP32/DualUDP/PingPong/Transmitter/Transmitter.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(45); +PJONDualUDP bus(45); const char* ssid = "MyNetworkSSID"; const char* password = "MyNetworkPassword"; diff --git a/examples/ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp b/examples/ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp index 16223e7c71..1c144012ab 100644 --- a/examples/ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp +++ b/examples/ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp @@ -13,11 +13,11 @@ static wifi_country_t wifi_country = { #include "Arduino.h" -#define PJON_INCLUDE_EN -#include -// bus(selected device id) -PJON bus(44); +#include + + +PJONESPNOW bus(44); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp b/examples/ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp index 28268760a9..c8e30f06b7 100644 --- a/examples/ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp +++ b/examples/ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp @@ -13,11 +13,9 @@ static wifi_country_t wifi_country = { #include "Arduino.h" -#define PJON_INCLUDE_EN -#include +#include -// bus(selected device id) -PJON bus(45); +PJONESPNOW bus(45); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino b/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino index 23ccfca88e..753a7ca49a 100644 --- a/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino +++ b/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino @@ -13,13 +13,9 @@ static wifi_country_t wifi_country = { policy: WIFI_COUNTRY_POLICY_MANUAL }; -// Use the PJON_INCLUDE_EN to include the ESPNOW strategy -#define PJON_INCLUDE_EN +#include -#include - -// bus(selected device id) -PJON bus(44); +PJONESPNOW bus(44); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino b/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino index cdcbacf70c..3f91cce4c9 100644 --- a/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino +++ b/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino @@ -14,13 +14,10 @@ static wifi_country_t wifi_country = { policy: WIFI_COUNTRY_POLICY_MANUAL }; -// Use the PJON_INCLUDE_EN to include the ESPNOW strategy -#define PJON_INCLUDE_EN -#include +#include -// bus(selected device id) -PJON bus(45); +PJONESPNOW bus(45); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp b/examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp index b0dacf781e..c6f020b7a8 100644 --- a/examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp +++ b/examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp @@ -15,13 +15,9 @@ static wifi_country_t wifi_country = { policy : WIFI_COUNTRY_POLICY_MANUAL }; -// Use the PJON_INCLUDE_EN to include the ESPNOW strategy -#define PJON_INCLUDE_EN +#include -#include - -// bus(selected device id) -PJON bus(44); +PJONESPNOW bus(44); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp b/examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp index ee23b89a66..4f253bc920 100644 --- a/examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp +++ b/examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp @@ -14,13 +14,9 @@ static wifi_country_t wifi_country = { policy : WIFI_COUNTRY_POLICY_MANUAL }; -// Use the PJON_INCLUDE_EN to include the ESPNOW strategy -#define PJON_INCLUDE_EN +#include -#include - -// bus(selected device id) -PJON bus(45); +PJONESPNOW bus(45); uint32_t cnt = 0; uint32_t start = millis(); @@ -55,4 +51,4 @@ void loop() start = millis(); cnt = 0; } -}; \ No newline at end of file +}; diff --git a/examples/ESP8266/Local/DualUDP/PingPong/Receiver/Receiver.ino b/examples/ESP8266/Local/DualUDP/PingPong/Receiver/Receiver.ino index 11f4428214..6564c6e2b1 100644 --- a/examples/ESP8266/Local/DualUDP/PingPong/Receiver/Receiver.ino +++ b/examples/ESP8266/Local/DualUDP/PingPong/Receiver/Receiver.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(44); +PJONDualUDP bus(44); const char* ssid = "MyNetworkSSID"; const char* password = "MyNetworkPassword"; diff --git a/examples/ESP8266/Local/DualUDP/PingPong/Transmitter/Transmitter.ino b/examples/ESP8266/Local/DualUDP/PingPong/Transmitter/Transmitter.ino index a5499ecbe7..9d94c0834c 100644 --- a/examples/ESP8266/Local/DualUDP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ESP8266/Local/DualUDP/PingPong/Transmitter/Transmitter.ino @@ -1,7 +1,7 @@ -#include +#include // bus(selected device id) -PJON bus(45); +PJONDualUDP bus(45); const char* ssid = "MyNetworkSSID"; const char* password = "MyNetworkPassword"; diff --git a/examples/ESP8266/Local/GlobalUDP/PingPong/Receiver/Receiver.ino b/examples/ESP8266/Local/GlobalUDP/PingPong/Receiver/Receiver.ino index d5f7bd543e..ea1a2e4e33 100644 --- a/examples/ESP8266/Local/GlobalUDP/PingPong/Receiver/Receiver.ino +++ b/examples/ESP8266/Local/GlobalUDP/PingPong/Receiver/Receiver.ino @@ -1,4 +1,4 @@ -#include +#include // Ethernet configuration for this device IPAddress gateway = { 192, 1, 1, 1 }; @@ -6,7 +6,7 @@ IPAddress subnet = { 255, 255, 255, 0 }; IPAddress local_ip = { 192, 1, 1, 163 }; // bus(selected device id) -PJON bus(44); +PJONGlobalUDP bus(44); const char* ssid = "MyNetworkSSID"; const char* password = "MyNetworkPassword"; diff --git a/examples/ESP8266/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino b/examples/ESP8266/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino index c7eb7d413b..c41ef0a4be 100644 --- a/examples/ESP8266/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ESP8266/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino @@ -1,10 +1,10 @@ -#include +#include // Address of remote device uint8_t remote_ip[] = { 192, 1, 1, 163 }; // bus(selected device id) -PJON bus(45); +PJONGlobalUDP bus(45); const char* ssid = "MyNetworkSSID"; const char* password = "MyNetworkPassword"; diff --git a/examples/ESP8266/Local/MQTTTranslate/EnvironmentController/EnvironmentController.ino b/examples/ESP8266/Local/MQTTTranslate/EnvironmentController/EnvironmentController.ino index 1dc3264159..bb84b4aff3 100644 --- a/examples/ESP8266/Local/MQTTTranslate/EnvironmentController/EnvironmentController.ino +++ b/examples/ESP8266/Local/MQTTTranslate/EnvironmentController/EnvironmentController.ino @@ -1,5 +1,5 @@ // This PJON device is a simulated environmental controller, trying to change -// temperature and pressure so that measurements are equal to targets that +// temperature and pressure so that measurements are equal to targets that // can be set from external systems through an MQTT broker. // Using the free MQTT Explorer or similar, publish the value "24" to the @@ -11,13 +11,12 @@ // a device id does not need to be set. This can be useful to produce a // series of identical devices without flashing with individual ids. -#define PJON_INCLUDE_MQTT + #define MQTTT_MODE MQTTT_MODE_MIRROR_TRANSLATE //#define MQTTT_USE_MAC -#include +#include -// bus(selected device id) -PJON bus(45); +PJONMQTTTranslate bus(45); // Use device id 45 // WiFi network to connect to const char* ssid = "MyNetworkSSID"; @@ -71,4 +70,4 @@ void loop() { pressure += (pressure_target - pressure) / 10; temperature += (temperature_target - temperature) / 20; } -}; \ No newline at end of file +}; diff --git a/examples/ESP8266/Local/SoftwareBitBang/SendAndReceive/Arduino/Arduino.ino b/examples/ESP8266/Local/SoftwareBitBang/SendAndReceive/Arduino/Arduino.ino index 343ea0864a..b7d90765b9 100644 --- a/examples/ESP8266/Local/SoftwareBitBang/SendAndReceive/Arduino/Arduino.ino +++ b/examples/ESP8266/Local/SoftwareBitBang/SendAndReceive/Arduino/Arduino.ino @@ -1,4 +1,4 @@ -#include +#include /* In this example it is demonstrated how to connect an ESP8266 module and an Arduino compatible device exchanging the character "B" in both directions @@ -16,8 +16,7 @@ character "B" is received. The string "BLINK" is printed in the ESP866 Serial monitor each time the character "B" is received. */ -// bus(selected device id) -PJON bus(45); +PJONSoftwareBitBang bus(45); // Use device id 45 void setup() { Serial.begin(115200); diff --git a/examples/ESP8266/Local/SoftwareBitBang/SendAndReceive/ESP8266/ESP8266.ino b/examples/ESP8266/Local/SoftwareBitBang/SendAndReceive/ESP8266/ESP8266.ino index 8dcc46e920..7292000ec9 100644 --- a/examples/ESP8266/Local/SoftwareBitBang/SendAndReceive/ESP8266/ESP8266.ino +++ b/examples/ESP8266/Local/SoftwareBitBang/SendAndReceive/ESP8266/ESP8266.ino @@ -1,8 +1,6 @@ // Include only SoftwareBitBang strategy -#define PJON_INCLUDE_SWBB - -#include +#include /* In this example it is demonstrated how to connect an ESP8266 module and an Arduino compatible device exchanging the character "B" in both directions @@ -20,8 +18,7 @@ character "B" is received. The string "BLINK" is printed in the ESP866 Serial monitor each time the character "B" is received. */ -// bus(selected device id) -PJON bus(44); +PJONSoftwareBitBang bus(44); // Use device id 44 void setup() { Serial.begin(115200); diff --git a/examples/ESP8266/Local/SoftwareBitBang/SpeedTest/ESPTransmitter/ESPTransmitter.ino b/examples/ESP8266/Local/SoftwareBitBang/SpeedTest/ESPTransmitter/ESPTransmitter.ino index 39db8f8c80..29ccd740f5 100644 --- a/examples/ESP8266/Local/SoftwareBitBang/SpeedTest/ESPTransmitter/ESPTransmitter.ino +++ b/examples/ESP8266/Local/SoftwareBitBang/SpeedTest/ESPTransmitter/ESPTransmitter.ino @@ -2,13 +2,10 @@ /* ESP8266 - Node MCU side Devices can be wired directly being ESP8266 5v tolerant */ - // Include only SoftwareBitBang strategy - #define PJON_INCLUDE_SWBB +// Include only SoftwareBitBang strategy +#include -#include - -// bus(selected device id) -PJON bus(45); +PJONSoftwareBitBang bus(45); // Use device id 45 uint8_t content[] = "01234567890123456789"; diff --git a/examples/ESP8266/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino b/examples/ESP8266/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino index 43dc8fb38e..943075da27 100644 --- a/examples/ESP8266/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino +++ b/examples/ESP8266/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino @@ -2,15 +2,14 @@ /* Arduino compatible device Devices can be wired directly being ESP8266 5v tolerant */ -#include +#include float test; float mistakes; int busy; int fail; -// bus(selected device id) -PJON bus(44); +PJONSoftwareBitBang bus(44); // Use device id 44 void setup() { bus.strategy.set_pin(12); diff --git a/examples/LINUX/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp b/examples/LINUX/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp index 192798fef4..018e0333a1 100644 --- a/examples/LINUX/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp @@ -1,10 +1,10 @@ -#define PJON_INCLUDE_ETCP -#include + +#include uint8_t remote_ip[] = { 192, 1, 1, 161 }; // bus(selected device id) -PJON bus(44); +PJONEthernetTCP bus(44); uint32_t cnt = 0; diff --git a/examples/LINUX/Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp b/examples/LINUX/Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp index da650b1957..6968565755 100644 --- a/examples/LINUX/Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp @@ -1,11 +1,11 @@ -#define PJON_INCLUDE_ETCP -#include + +#include // Address of remote device uint8_t remote_ip[] = { 192, 1, 1, 161 }; // bus(selected device id) -PJON bus(45); +PJONEthernetTCP bus(45); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/LINUX/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp b/examples/LINUX/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp index a454d913ec..8b31e5cbfe 100644 --- a/examples/LINUX/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp @@ -1,8 +1,8 @@ -#define PJON_INCLUDE_GUDP -#include + +#include // bus(selected device id) -PJON bus(44); +PJONGlobalUDP bus(44); //uint32_t millis() { return PJON_MICROS()/1000; } // TODO: Move to interface diff --git a/examples/LINUX/Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp b/examples/LINUX/Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp index 8162408cd1..6c217f7762 100644 --- a/examples/LINUX/Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp @@ -1,8 +1,8 @@ -#define PJON_INCLUDE_GUDP -#include + +#include // bus(selected device id) -PJON bus(45); +PJONGlobalUDP bus(45); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/LINUX/Local/LocalFile/PingPong/Receiver/Receiver.cpp b/examples/LINUX/Local/LocalFile/PingPong/Receiver/Receiver.cpp index 24a42819a6..14b346339a 100644 --- a/examples/LINUX/Local/LocalFile/PingPong/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/LocalFile/PingPong/Receiver/Receiver.cpp @@ -1,9 +1,9 @@ //#define PJON_MAX_PACKETS 1 -#define PJON_INCLUDE_LF -#include + +#include // bus(selected device id) -PJON bus(44); +PJONLocalFile bus(44); uint32_t cnt = 0, cnt2 = 1; uint32_t start = millis(); diff --git a/examples/LINUX/Local/LocalFile/PingPong/Transmitter/Transmitter.cpp b/examples/LINUX/Local/LocalFile/PingPong/Transmitter/Transmitter.cpp index eeff39c6ca..3cdaa10f81 100644 --- a/examples/LINUX/Local/LocalFile/PingPong/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/LocalFile/PingPong/Transmitter/Transmitter.cpp @@ -1,8 +1,8 @@ -#define PJON_INCLUDE_LF -#include + +#include // bus(selected device id) -PJON bus(45); +PJONLocalFile bus(45); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/LINUX/Local/LocalUDP/PingPong/Receiver/Receiver.cpp b/examples/LINUX/Local/LocalUDP/PingPong/Receiver/Receiver.cpp index 01a8975606..57773bc0fd 100644 --- a/examples/LINUX/Local/LocalUDP/PingPong/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/LocalUDP/PingPong/Receiver/Receiver.cpp @@ -1,8 +1,8 @@ -#define PJON_INCLUDE_LUDP -#include + +#include // bus(selected device id) -PJON bus(44); +PJONLocalUDP bus(44); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/LINUX/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp b/examples/LINUX/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp index cf91b5f745..0beae999b8 100644 --- a/examples/LINUX/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp @@ -1,8 +1,8 @@ -#define PJON_INCLUDE_LUDP -#include + +#include // bus(selected device id) -PJON bus(45); +PJONLocalUDP bus(45); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/LINUX/Local/ThroughSerial/BlinkTest/Receiver/Receiver.cpp b/examples/LINUX/Local/ThroughSerial/BlinkTest/Receiver/Receiver.cpp index b64d914092..77083c6d1e 100644 --- a/examples/LINUX/Local/ThroughSerial/BlinkTest/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/ThroughSerial/BlinkTest/Receiver/Receiver.cpp @@ -6,8 +6,8 @@ #include #include -#define PJON_INCLUDE_TS // Include only ThroughSerial -#include + // Include only ThroughSerial +#include void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is @@ -19,7 +19,7 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info int main() { printf("PJON instantiation... \n"); - PJON bus(44); + PJONThroughSerial bus(44); bus.set_receiver(receiver_function); uint32_t baud_rate = 9600; printf("Opening serial... \n"); diff --git a/examples/LINUX/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp b/examples/LINUX/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp index 4f51ec632b..33c6e2693e 100644 --- a/examples/LINUX/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp @@ -6,12 +6,12 @@ #include #include -#define PJON_INCLUDE_TS // Include only ThroughSerial -#include + // Include only ThroughSerial +#include int main() { printf("PJON instantiation... \n"); - PJON bus(45); + PJONThroughSerial bus(45); uint32_t baud_rate = 9600; printf("Opening serial... \n"); diff --git a/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Receiver/Receiver.cpp b/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Receiver/Receiver.cpp index eb651cdd5e..b6b27804ab 100644 --- a/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Receiver/Receiver.cpp @@ -8,8 +8,8 @@ #define TS_RESPONSE_TIME_OUT 35000 -#define PJON_INCLUDE_TS // Include only ThroughSerial -#include + // Include only ThroughSerial +#include void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is @@ -21,7 +21,7 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info int main() { printf("PJON instantiation... \n"); - PJON bus(44); + PJONThroughSerial bus(44); bus.set_receiver(receiver_function); uint32_t baud_rate = 9600; printf("Opening serial... \n"); diff --git a/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Transmitter/Transmitter.cpp b/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Transmitter/Transmitter.cpp index 260eeff35e..b76abac457 100644 --- a/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/ThroughSerial/BlinkWithAck/Transmitter/Transmitter.cpp @@ -8,14 +8,14 @@ #define TS_RESPONSE_TIME_OUT 35000 -#define PJON_INCLUDE_TS // Include only ThroughSerial -#include + // Include only ThroughSerial +#include #define BLINK_FREQUENCY 1000000 // 1 Blink per second int main() { printf("PJON instantiation... \n"); - PJON bus(45); + PJONThroughSerial bus(45); uint32_t baud_rate = 9600; printf("Opening serial... \n"); diff --git a/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.cpp b/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.cpp index afb6236098..ec0be94723 100644 --- a/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Receiver/Receiver.cpp @@ -6,9 +6,9 @@ #include #include -#define PJON_INCLUDE_TS // Include only ThroughSerial -#include -PJON bus(44); + // Include only ThroughSerial +#include +PJONThroughSerial bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp b/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp index 81ab47e1db..53204414f2 100644 --- a/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp @@ -6,8 +6,8 @@ #include #include -#define PJON_INCLUDE_TS // Include only ThroughSerial -#include + // Include only ThroughSerial +#include void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is @@ -19,7 +19,7 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info int main() { printf("PJON instantiation... \n"); - PJON bus(45); + PJONThroughSerial bus(45); uint32_t baud_rate = 9600; printf("Opening serial... \n"); diff --git a/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/Receiver.cpp b/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/Receiver.cpp index 498ddad671..e6ab1b30a6 100644 --- a/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/Receiver.cpp +++ b/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/Receiver.cpp @@ -19,8 +19,8 @@ physical distance and or if long packets are transmitted. */ -#define PJON_INCLUDE_TS true // Include only ThroughSerial -#include + // Include only ThroughSerial +#include void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is @@ -33,7 +33,7 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info int main() { printf("PJON instantiation... \n"); - PJON bus(44); + PJONThroughSerial bus(44); uint32_t baud_rate = 9600; printf("Opening serial... \n"); int s = serialOpen("/dev/ttyAMA0", baud_rate); diff --git a/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/Transmitter.cpp b/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/Transmitter.cpp index 71b18d0655..80afa77006 100644 --- a/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/Transmitter.cpp +++ b/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/Transmitter.cpp @@ -19,12 +19,12 @@ physical distance and or if long packets are transmitted. */ -#define PJON_INCLUDE_TS true // Include only ThroughSerial -#include + // Include only ThroughSerial +#include int main() { printf("PJON instantiation... \n"); - PJON bus(45); + PJONThroughSerial bus(45); uint32_t baud_rate = 9600; printf("Opening serial... \n"); int s = serialOpen("/dev/ttyAMA0", baud_rate); diff --git a/examples/RPI/Local/ThroughSerial/BlinkWithResponse/Transmitter.cpp b/examples/RPI/Local/ThroughSerial/BlinkWithResponse/Transmitter.cpp index 7a85f773d6..342a467d2c 100644 --- a/examples/RPI/Local/ThroughSerial/BlinkWithResponse/Transmitter.cpp +++ b/examples/RPI/Local/ThroughSerial/BlinkWithResponse/Transmitter.cpp @@ -13,11 +13,11 @@ #define RPI true #endif -#define PJON_INCLUDE_TS true // Include only ThroughSerial + // Include only ThroughSerial -#include +#include -PJON bus(45); +PJONThroughSerial bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/RPI/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter.cpp b/examples/RPI/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter.cpp index bf916bf8d0..3073d88e04 100644 --- a/examples/RPI/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter.cpp +++ b/examples/RPI/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter.cpp @@ -13,11 +13,11 @@ #define RPI true #endif -#define PJON_INCLUDE_TS true // Include only ThroughSerial + // Include only ThroughSerial -#include +#include -PJON bus(45); +PJONThroughSerial bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/WINX86/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp b/examples/WINX86/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp index 7d4434234d..3846b4bcbd 100644 --- a/examples/WINX86/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp +++ b/examples/WINX86/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp @@ -1,10 +1,10 @@ -#define PJON_INCLUDE_ETCP -#include + +#include // Address of remote device uint8_t remote_ip[] = {127, 0, 0, 1}; -PJON bus(44); +PJONEthernetTCP bus(44); uint32_t count = 0; diff --git a/examples/WINX86/Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp b/examples/WINX86/Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp index 1fabce1414..3faded59ad 100644 --- a/examples/WINX86/Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp @@ -1,11 +1,11 @@ -#define PJON_INCLUDE_ETCP + #define _WIN32 -#include +#include // Address of remote device uint8_t remote_ip[] = {127, 0, 0, 1}; -PJON bus(45); +PJONEthernetTCP bus(45); uint32_t count = 0; diff --git a/examples/WINX86/Local/EthernetTCP/RemoteWorker/Transmitter/Transmitter.cpp b/examples/WINX86/Local/EthernetTCP/RemoteWorker/Transmitter/Transmitter.cpp index 65c4ed5a36..6388356519 100644 --- a/examples/WINX86/Local/EthernetTCP/RemoteWorker/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/EthernetTCP/RemoteWorker/Transmitter/Transmitter.cpp @@ -24,10 +24,10 @@ Ethernet strategies and related concepts are contributed by Fred Larsen. */ #define ETCP_SINGLE_DIRECTION //#define ETCP_SINGLE_SOCKET_WITH_ACK -#define PJON_INCLUDE_ETCP -#include -PJON bus(45); +#include + +PJONEthernetTCP bus(45); static void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { printf("BLINK\n"); diff --git a/examples/WINX86/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp b/examples/WINX86/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp index b50e841f65..6635aebe11 100644 --- a/examples/WINX86/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp +++ b/examples/WINX86/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp @@ -1,10 +1,10 @@ -#define PJON_INCLUDE_GUDP -#include + +#include // IP Address of the receiver uint8_t remote_ip[] = {127, 0, 0, 1}; -PJON bus(44); +PJONGlobalUDP bus(44); uint32_t count = 0; diff --git a/examples/WINX86/Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp b/examples/WINX86/Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp index e2417034e4..3b582aad0a 100644 --- a/examples/WINX86/Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp @@ -1,10 +1,10 @@ -#define PJON_INCLUDE_GUDP -#include + +#include // Address of remote device uint8_t remote_ip[] = {127, 0, 0, 1}; -PJON bus(45); +PJONGlobalUDP bus(45); uint32_t count = 0; diff --git a/examples/WINX86/Local/LocalUDP/PingPong/Receiver/Receiver.cpp b/examples/WINX86/Local/LocalUDP/PingPong/Receiver/Receiver.cpp index cd63eba410..3ba52e85ea 100644 --- a/examples/WINX86/Local/LocalUDP/PingPong/Receiver/Receiver.cpp +++ b/examples/WINX86/Local/LocalUDP/PingPong/Receiver/Receiver.cpp @@ -1,4 +1,4 @@ -#define PJON_INCLUDE_LUDP + #include PJON bus(44); diff --git a/examples/WINX86/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp b/examples/WINX86/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp index f8571a90fa..caa9c7ec4d 100644 --- a/examples/WINX86/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp @@ -1,4 +1,4 @@ -#define PJON_INCLUDE_LUDP + #include PJON bus(45); diff --git a/examples/WINX86/Local/MQTTTranslate/PingPong/Receiver/Receiver.cpp b/examples/WINX86/Local/MQTTTranslate/PingPong/Receiver/Receiver.cpp index c5e084e6be..875c44f981 100644 --- a/examples/WINX86/Local/MQTTTranslate/PingPong/Receiver/Receiver.cpp +++ b/examples/WINX86/Local/MQTTTranslate/PingPong/Receiver/Receiver.cpp @@ -1,15 +1,15 @@ // Use the following define to activate debug // #define MQTT_DEBUGPRINT -#define PJON_INCLUDE_ETCP -#define PJON_INCLUDE_MQTT -#include + + +#include // Ethernet address of the broker uint8_t broker_ip[] = { 127, 0, 0, 1 }; // bus(selected device id) -PJON bus(44); +PJONMQTTTranslate bus(44); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/WINX86/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.cpp b/examples/WINX86/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.cpp index ff0366f134..19228464a1 100644 --- a/examples/WINX86/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.cpp @@ -1,15 +1,15 @@ // Use the following define to activate debug // #define MQTT_DEBUGPRINT -#define PJON_INCLUDE_ETCP -#define PJON_INCLUDE_MQTT -#include + + +#include // Ethernet address of the broker uint8_t broker_ip[] = { 127, 0, 0, 1 }; // bus(selected device id) -PJON bus(45); +PJONMQTTTranslate bus(45); uint32_t cnt = 0; uint32_t start = millis(); diff --git a/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp b/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp index 6dcb5f2adc..cb00cdf27c 100644 --- a/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp @@ -23,12 +23,12 @@ #define COM_PORT "COM9" // Include only ThroughSerial -#define PJON_INCLUDE_TS + // Include PJON library -#include +#include -PJON bus(45); +PJONThroughSerial bus(45); // Error handler called when something goes wrong diff --git a/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp index 5588b4a679..9c77121938 100644 --- a/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp @@ -23,12 +23,12 @@ #define COM_PORT "COM9" // Include only ThroughSerial -#define PJON_INCLUDE_TS + // Include PJON library -#include +#include -PJON bus(45); +PJONThroughSerial bus(45); // The function called when data is received diff --git a/keywords.txt b/keywords.txt index e6aeeb8763..4d8854da1e 100644 --- a/keywords.txt +++ b/keywords.txt @@ -117,23 +117,6 @@ PJON_INCLUDE_PACKET_ID LITERAL1 PJON_INCLUDE_PORT LITERAL1 PJON_INCLUDE_MAC LITERAL1 -## Strategy inclusion constants - -PJON_INCLUDE_AS LITERAL1 -PJON_INCLUDE_ANY LITERAL1 -PJON_INCLUDE_DUDP LITERAL1 -PJON_INCLUDE_EN LITERAL1 -PJON_INCLUDE_ETCP LITERAL1 -PJON_INCLUDE_GUDP LITERAL1 -PJON_INCLUDE_LF LITERAL1 -PJON_INCLUDE_LUDP LITERAL1 -PJON_INCLUDE_MQTT LITERAL1 -PJON_INCLUDE_OS LITERAL1 -PJON_INCLUDE_SWBB LITERAL1 -PJON_INCLUDE_TL LITERAL1 -PJON_INCLUDE_TS LITERAL1 -PJON_INCLUDE_NONE LITERAL1 - ## AnalogSampling AS_BIT_WIDTH LITERAL1 diff --git a/src/PJON.h b/src/PJON.h index 074a9fb147..87ed27a3df 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -60,7 +60,6 @@ limitations under the License. */ #pragma once #include "interfaces/PJON_Interfaces.h" #include "PJONDefines.h" -#include "strategies/PJON_Strategies.h" static void PJON_dummy_receiver_handler( uint8_t *, // payload diff --git a/src/PJONAny.h b/src/PJONAny.h new file mode 100644 index 0000000000..53715f3dcf --- /dev/null +++ b/src/PJONAny.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/Any/Any.h" + +#define PJONAny PJON diff --git a/src/PJONDualUDP.h b/src/PJONDualUDP.h new file mode 100644 index 0000000000..0477c2b692 --- /dev/null +++ b/src/PJONDualUDP.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/DualUDP/DualUDP.h" + +#define PJONDualUDP PJON diff --git a/src/PJONESPNOW.h b/src/PJONESPNOW.h new file mode 100644 index 0000000000..5df99e8db4 --- /dev/null +++ b/src/PJONESPNOW.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/ESPNOW/ESPNOW.h" + +#define PJONESPNOW PJON diff --git a/src/PJONEthernetTCP.h b/src/PJONEthernetTCP.h new file mode 100644 index 0000000000..18ebf62b0c --- /dev/null +++ b/src/PJONEthernetTCP.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/EthernetTCP/EthernetTCP.h" + +#define PJONEthernetTCP PJON diff --git a/src/PJONGlobalUDP.h b/src/PJONGlobalUDP.h new file mode 100644 index 0000000000..832eb1b2fa --- /dev/null +++ b/src/PJONGlobalUDP.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/GlobalUDP/GlobalUDP.h" + +#define PJONGlobalUDP PJON diff --git a/src/PJONLocal.h b/src/PJONLocal.h index 2a60004601..e4fe86a2fc 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -70,7 +70,6 @@ limitations under the License. */ #define PJON_INCLUDE_NONE #include "interfaces/PJON_Interfaces.h" #include "PJONDefines.h" -#include "strategies/PJON_Strategies.h" template class PJONLocal { diff --git a/src/PJONLocalFile.h b/src/PJONLocalFile.h new file mode 100644 index 0000000000..85f5f6dd05 --- /dev/null +++ b/src/PJONLocalFile.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/LocalFile/LocalFile.h" + +#define PJONLocalFile PJON diff --git a/src/PJONLocalUDP.h b/src/PJONLocalUDP.h new file mode 100644 index 0000000000..85632a5ed3 --- /dev/null +++ b/src/PJONLocalUDP.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/LocalUDP/LocalUDP.h" + +#define PJONLocalUDP PJON diff --git a/src/PJONMQTTTranslate.h b/src/PJONMQTTTranslate.h new file mode 100644 index 0000000000..7546d407bf --- /dev/null +++ b/src/PJONMQTTTranslate.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/MQTTTranslate/MQTTTranslate.h" + +#define PJONMQTTTranslate PJON diff --git a/src/PJONSoftwareBitBang.h b/src/PJONSoftwareBitBang.h new file mode 100644 index 0000000000..3964b7a1c9 --- /dev/null +++ b/src/PJONSoftwareBitBang.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/SoftwareBitBang/SoftwareBitBang.h" + +#define PJONSoftwareBitBang PJON diff --git a/src/PJONThroughLora.h b/src/PJONThroughLora.h new file mode 100644 index 0000000000..b9af20952e --- /dev/null +++ b/src/PJONThroughLora.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/ThroughLoRa/ThroughLora.h" + +#define PJONThroughLora PJON diff --git a/src/PJONThroughSerial.h b/src/PJONThroughSerial.h new file mode 100644 index 0000000000..66f020dd1d --- /dev/null +++ b/src/PJONThroughSerial.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/ThroughSerial/ThroughSerial.h" + +#define PJONThroughSerial PJON diff --git a/src/strategies/AnalogSampling/README.md b/src/strategies/AnalogSampling/README.md index 58e4301298..7ab0e11ef0 100644 --- a/src/strategies/AnalogSampling/README.md +++ b/src/strategies/AnalogSampling/README.md @@ -1,8 +1,8 @@ ## AnalogSampling -| Medium | Pins used | Inclusion Constant | Included by default | -|--------|-----------|--------------------|---------------------| -| Light pulses over air or optic-fibre | 1 or 2 | `PJON_INCLUDE_AS`| yes | +| Medium | Pins used | Inclusion | +|--------|-----------|--------------------| +| Light pulses over air or optic-fibre | 1 or 2 | `#include `| `AnalogSampling` strategy or data link complies with [PJDLS v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md), it is designed to communicate data wirelessly using light impulses and its sampling technique is based on analog readings. This strategy is able to use a single LED for both photo-emission and photo-reception phases providing with wireless half-duplex connectivity between devices with a range of up to 5 meters. Most appliances have at least a useless energy consuming LED on board, right? @@ -38,7 +38,7 @@ It is possible to use LEDs as wireless (bidirectional) transceivers. This means `AnalogSampling` can be used to experiment with short range infrared or visible light communication (remote control, robot swarms, data streaming using lighting), medium range using light sources (cars transmitting data through front and backlights) or long range laser communication (data between ground and LEO). ### Configuration -Before including `PJON.h` it is possible to configure `AnalogSampling` using predefined constants: +Before including the library it is possible to configure `AnalogSampling` using predefined constants: | Constant | Purpose | Supported value | | ------------------------- |------------------------------------ | ------------------------------------------ | @@ -48,11 +48,11 @@ Before including `PJON.h` it is possible to configure `AnalogSampling` using pre | `AS_MAX_ATTEMPTS` | Maximum transmission attempts | Numeric value (10 by default) | | `AS_PRESCALE` | Set ADC pre-scaler | 8, 16, 32 | -Pass the `AnalogSampling` type as PJON template parameter to instantiate a PJON object ready to communicate through this Strategy. All the other necessary information is present in the general [Documentation](/documentation). +Use `PJONAnalogSampling` to instantiate a PJON object ready to communicate using `AnalogSampling` strategy. All the other necessary information is present in the general [Documentation](/documentation). ```cpp -#include +#include -PJON bus; +PJONAnalogSampling bus; void setup() { // Set the pin A0 as the communication pin diff --git a/src/strategies/Any/README.md b/src/strategies/Any/README.md index d0dd32e788..4e97a71f8e 100644 --- a/src/strategies/Any/README.md +++ b/src/strategies/Any/README.md @@ -1,8 +1,8 @@ ## Any -| Medium | Pins used | Inclusion Constant | Included by default | -|--------|-----------|--------------------|---------------------| -| Any | NA | `PJON_INCLUDE_ANY` | yes | +| Medium | Pins used | Inclusion | +|--------|-----------|--------------------| +| Any | NA | `#include ` | The `Any` strategy includes virtual inheritance and let PJON objects change from a strategy to another after instantiation or a collection of PJON objects with different strategies to be treated agnostically. @@ -15,10 +15,10 @@ PJON bus; ``` Call the `set_link` method passing the `StrategyLink` instance: ```cpp -#include +#include StrategyLink link; -PJON bus; +PJONAny bus; void setup() { Serial.begin(9600); diff --git a/src/strategies/DualUDP/README.md b/src/strategies/DualUDP/README.md index 99c3f4c1ae..19578860b6 100644 --- a/src/strategies/DualUDP/README.md +++ b/src/strategies/DualUDP/README.md @@ -1,8 +1,8 @@ ## DualUDP -| Medium | Pins used | Inclusion Constant | Included by default | -|--------|-----------|--------------------|---------------------| -| Ethernet port, wired or WiFi | NA | `PJON_INCLUDE_DUDP`| yes | +| Medium | Pins used | Inclusion | +|--------|-----------|--------------------| +| Ethernet port, wired or WiFi | NA |`#include `| With the `DualUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other over an Ethernet network, wired or over WiFi or both. Like the `GlobalUDP` strategy, this strategy is not limited to the local network and can therefore reach devices farther away, to another LAN connected through VPN, or potentially across the Internet (beware of security issues). Like the `DualUDP` strategy it will reach devices on the LAN without configuration. @@ -18,10 +18,11 @@ If a cabled or wireless Ethernet network exists, using this to let devices commu It can also be useful for connecting physically separate clusters of devices that are connected wired with the `SoftwareBitBang` strategy, or wirelessly with the `Oversampling` strategy, when a LAN or WAN is connecting the locations. ### How to use DualUDP -Pass the `DualUDP` type as PJON template parameter to instantiate a PJON object ready to communicate through this Strategy. -```cpp - // Use DualUDP strategy with PJON device id 44 - PJON bus(44); +Use `PJONDualUDP` to instantiate a PJON object ready to communicate using the `DualUDP` strategy: +```cpp + #include + + PJONDualUDP bus(44); // Use device id 44 ``` Now the Ethernet card must be set up. This can be done by using a static IP address or by getting an address assigned by DHCP. diff --git a/src/strategies/ESPNOW/README.md b/src/strategies/ESPNOW/README.md index a65c417ef3..361c12a15c 100644 --- a/src/strategies/ESPNOW/README.md +++ b/src/strategies/ESPNOW/README.md @@ -1,8 +1,8 @@ ## ESPNOW -| Medium | Pins used | Inclusion Constant | Included by default | -|--------|-----------|--------------------|---------------------| -| ESPNOW over WiFi | NA | `PJON_INCLUDE_EN`| no | +| Medium | Pins used | Constant | +|--------|-----------|--------------------| +| ESPNOW over WiFi | NA | `#include ` | With the `ESPNOW` PJON strategy, up to 10 ESP32 devices can use PJON to communicate with each other over the [Espressif ESPNOW protocol](https://www.espressif.com/en/products/software/esp-now/overview) (peer-to-peer 802.11). @@ -18,12 +18,12 @@ PJON over WiFi has the following benefit: ### How to use ESPNOW ESPNOW strategy can be used within the Arduino IDE or as an esp-idf component with [arduino-esp32](https://github.com/espressif/arduino-esp32). -Pass the `ESPNOW` type as PJON template parameter to instantiate a -PJON object ready to communicate through this Strategy. +Use `PJONESPNOW` to instantiate a PJON object ready to communicate using `ESPNOW` strategy: -```cpp - // Use ESPNOW strategy with PJON device id 44 - PJON bus(44); +```cpp + #include + + PJONESPNOW bus(44); // Use device id 44 ``` You can customise the channel (default is channel 1) and PMK (encryption) as follows (all devices must be the same): diff --git a/src/strategies/EthernetTCP/README.md b/src/strategies/EthernetTCP/README.md index f7ec3a7add..9432adda2c 100644 --- a/src/strategies/EthernetTCP/README.md +++ b/src/strategies/EthernetTCP/README.md @@ -1,8 +1,8 @@ ## EthernetTCP -| Medium | Pins used | Inclusion Constant | Included by default | -|--------|-----------|--------------------|---------------------| -| Ethernet port, wired or WiFi | NA | `PJON_INCLUDE_ETCP`| yes | +| Medium | Pins used | Inclusion | +|--------|-----------|--------------------| +| Ethernet port, wired or WiFi | NA | `#include `| With the `EthernetTCP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other on a LAN, WAN or across the Internet. Take a look at the [video introduction](https://www.youtube.com/watch?v=DQzcAv38yxM) for a brief showcase of its features. @@ -14,10 +14,11 @@ It can also be useful for connecting physically separate clusters of devices tha It also enables devices to be connected through the Internet if firewalls are configured to allow this. ### How to use EthernetTCP -Pass the `EthernetTCP` type as PJON template parameter to instantiate a PJON object ready to communicate through this Strategy. +Use `PJONEthernetTCP` to instantiate a PJON object ready to communicate using `EthernetTCP` strategy: ```cpp - // Use EthernetTCP strategy with PJON device id 44 - PJON bus(44); + #include + + PJONEthernetTCP bus(44); // Use device id 44 ``` Set up the Ethernet card in the usual manner by calling `Ethernet.begin`, then call setter functions for the link object in the EthernetTCP strategy, and then call the `begin` method on the PJON object: ```cpp diff --git a/src/strategies/GlobalUDP/README.md b/src/strategies/GlobalUDP/README.md index 1266894e9c..3947c9d993 100644 --- a/src/strategies/GlobalUDP/README.md +++ b/src/strategies/GlobalUDP/README.md @@ -1,8 +1,8 @@ ## GlobalUDP -| Medium | Pins used | Inclusion Constant | Included by default | -|--------|-----------|--------------------|---------------------| -| Ethernet port, wired or WiFi | NA | `PJON_INCLUDE_GUDP`| yes | +| Medium | Pins used | Inclusion | +|--------|-----------|--------------------| +| Ethernet port, wired or WiFi | NA | `#include `| With the `GlobalUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other over an Ethernet network, wired or over WiFi or both. This strategy demands a little more configuration than the `LocalUDP` strategy @@ -15,10 +15,11 @@ If a cabled or wireless Ethernet network exists, using this to let devices commu It can also be useful for connecting physically separate clusters of devices that are connected wired with the `SoftwareBitBang` strategy, or wirelessly with the `Oversampling` strategy, when a LAN or WAN is connecting the locations. ### How to use GlobalUDP -Pass the `GlobalUDP` type as PJON template parameter to instantiate a PJON object ready to communicate through this Strategy. +Use `PJONGlobalUDP` to instantiate a PJON object ready to communicate using `PJONGlobalUDP` strategy: ```cpp - // Use LocalUDP strategy with PJON device id 44 - PJON bus(44); + #include + + PJONGlobalUDP bus(44); // Use device id 44 ``` Set up the Ethernet card in the usual manner by calling `Ethernet.begin`, register the other devices to send to, then call the `begin` method on the PJON object: diff --git a/src/strategies/LocalFile/README.md b/src/strategies/LocalFile/README.md index 1b0b28eb21..1c5e1efbf7 100644 --- a/src/strategies/LocalFile/README.md +++ b/src/strategies/LocalFile/README.md @@ -1,14 +1,14 @@ ## LocalFile -| Medium | Pins used | Inclusion Constant | Included by default | -|--------|-----------|--------------------|---------------------| -| System memory | NA | `PJON_INCLUDE_LF`| no | +| Medium | Pins used | Inclusion | +|--------|-----------|--------------------| +| System memory | NA | `#include `| `LocalFile` uses a file present on the hard drive to let multiple processes communicate on the same machine. It can be used for inter-process communication and for developing, simulating and testing applications and networks on a real time operative system without having to deploy physical hardware. ### Configuration -Before including `PJON.h` it is possible to configure `LocalFile` using predefined constants: +Before including the library it is possible to configure `LocalFile` using predefined constants: | Constant | Purpose | Supported value | | ------------------ |--------------------------------------------- | ------------------------------------------ | @@ -16,10 +16,11 @@ Before including `PJON.h` it is possible to configure `LocalFile` using predefin | `LF_FILENAME` | Name and location of the file used as medium | Duration in microseconds (1500 by default) | | `LF_QUEUESIZE` | Size of the packets queue | > 0 (20 by default) | -Pass the `LocalFile` type as PJON template parameter to instantiate a PJON object ready to communicate through this strategy. +Use `PJONLocalFile` to instantiate a PJON object ready to communicate using `LocalFile` strategy: ```cpp - // Use LocalFile strategy with PJON device id 44 - PJON bus(44); + #include + + PJONLocalFile bus(44); // Use device id 44 ``` After testing or simulation you may want to use conditional compiling and exchange this strategy with the actual one on your target hardware. diff --git a/src/strategies/LocalUDP/README.md b/src/strategies/LocalUDP/README.md index a90b2cf17b..05dc32c422 100644 --- a/src/strategies/LocalUDP/README.md +++ b/src/strategies/LocalUDP/README.md @@ -1,8 +1,8 @@ ## LocalUDP -| Medium | Pins used | Inclusion Constant | Included by default | -|--------|-----------|--------------------|---------------------| -| Ethernet port, wired or WiFi | NA | `PJON_INCLUDE_LUDP`| yes | +| Medium | Pins used | Inclusion | +|--------|-----------|--------------------| +| Ethernet port, wired or WiFi | NA | `#include `| With the `LocalUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other on a local subnet, wired or over WiFi or both. Take a look at the [video introduction](https://www.youtube.com/watch?v=cxEUqkK5BQg) for a brief showcase of its features. @@ -12,10 +12,11 @@ If a cabled or wireless Ethernet network exists, using this to let devices commu It can also be useful for connecting physically separate clusters of devices that are connected wired with the SoftwareBitBang strategy, or wirelessly with the Oversampling strategy, when a LAN is connecting the locations. ### How to use LocalUDP -Pass the `LocalUDP` type as PJON template parameter to instantiate a PJON object ready to communicate through this Strategy. +Use `PJONLocalUDP` to instantiate a PJON object ready to communicate using `LocalUDP` strategy: ```cpp - // Use LocalUDP strategy with PJON device id 44 - PJON bus(44); + #include + + PJONLocalUDP bus(44); // Device id 44 ``` Set up the Ethernet card in the usual manner by calling `Ethernet.begin`, then call the `begin` method on the PJON object: ```cpp diff --git a/src/strategies/MQTTTranslate/README.md b/src/strategies/MQTTTranslate/README.md index 89375230ae..3fe3cdb6e7 100644 --- a/src/strategies/MQTTTranslate/README.md +++ b/src/strategies/MQTTTranslate/README.md @@ -1,8 +1,8 @@ ## MQTTTranslate -| Medium | Pins used | Inclusion Constant | Included by default | -|--------|-----------|--------------------|---------------------| -| MQTT protocol | NA | `PJON_INCLUDE_MQTT`| no | +| Medium | Pins used | Inclusion Constant | +|--------|-----------|--------------------| +| MQTT protocol | NA | `#include `| MQTTTranslate uses the [ReconnectingMqttClient](https://github.com/fredilarsen/ReconnectingMqttClient) library (minimum version required v1.1.1) to deliver PJON packets over TCP on local network (LAN) as a MQTT protocol client. It may be useful to connect PJON networks and more standard applications to each other using the MQTT protocol. This strategy works in one of four modes. The first two modes enable to implement a PJON bus via MQTT, the first mode is "closed" and the second is "open" to use by non-PJON programs. The last two modes are for behaving like MQTT devices normally do. @@ -26,19 +26,18 @@ Note that this functionality does not cover Windows/Linux/OsX in this release. ### Configuration -Before including `PJON.h` it is possible to configure `MQTTTranslate` using predefined constants: +Before including the library it is possible to configure `MQTTTranslate` using predefined constants: | Constant | Purpose | Supported value | | ------------------ |--------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | `MQTTT_MODE` | Select mode | `MQTTT_MODE_BUS_RAW`, `MQTTT_MODE_BUS_JSON`, `MQTTT_MODE_MIRROR_TRANSLATE`, `MQTTT_MODE_MIRROR_DIRECT` | -Define the `PJON_INCLUDE_MQTT` constant before including the library and pass the `MQTTTranslate` type as PJON template parameter to instantiate an object ready to communicate using this strategy: +Use `PJONMQTTTranslate` to instantiate an object ready to communicate using `MQTTTranslate` strategy: ```cpp - #define PJON_INCLUDE_MQTT // Include MQTTTranslate strategy - #include // Include the PJON library + #include // Include the PJON library // Use MQTTTranslate strategy with PJON device id 44 - PJON bus(44); + PJONMQTTTranslate bus(44); uint8_t broker_ip[] = { 127, 0, 0, 1 }; void setup() { diff --git a/src/strategies/OverSampling/README.md b/src/strategies/OverSampling/README.md index a5d9e6732d..d18e508c04 100644 --- a/src/strategies/OverSampling/README.md +++ b/src/strategies/OverSampling/README.md @@ -1,7 +1,7 @@ ## OverSampling -| Medium | Pins used | Inclusion Constant | Included by default | -|--------|-----------|--------------------|---------------------| -| ASK/FSK radio modules | 1 or 2 | `PJON_INCLUDE_OS`| yes | +| Medium | Pins used | Inclusion | +|--------|-----------|--------------------| +| ASK/FSK radio modules | 1 or 2 | `#include `| `OverSampling` is a software implementation of [PJDLR (Padded Jittering Data Link over Radio)](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md). It supports simplex and half-duplex asynchronous serial communication and implements a carrier-sense, non-persistent random multiple access method (non-persistent CSMA). This implementation can run on limited microcontrollers with low clock accuracy, supports communication for many devices connected to the same medium and stable operation in spite of interference. Its procedure is a more efficient alternative to the LoRa Open Standard (that specifies a variation of Slotted ALOHA) and it is designed to obtain long range and high reliability using FSK, ASK or OOK modulation radio transceivers. Take a look at the [video introduction](https://www.youtube.com/watch?v=G1ckfsMzPns) for a brief showcase of its features. @@ -19,7 +19,7 @@ - Range: 250 meters with no line of sight, 5 km with line of sight and ideal atmospheric conditions ### Configuration -Before including `PJON.h` it is possible to configure `OverSampling` using predefined constants: +Before including the library it is possible to configure `OverSampling` using predefined constants: | Constant | Purpose | Supported value | | ------------------------- |------------------------------------ | ------------------------------------------- | @@ -27,12 +27,12 @@ Before including `PJON.h` it is possible to configure `OverSampling` using prede | `OS_BACK_OFF_DEGREE` | Maximum back-off exponential degree | Numeric value (5 by default) | | `OS_MAX_ATTEMPTS` | Maximum transmission attempts | Numeric value (10 by default) | -Pass the `OverSampling` type as PJON template parameter to instantiate a new PJON object. All the other necessary information is present in the general [Documentation](/documentation). +Use `PJONOverSampling` to instantiate a new PJON object ready to communicate using the `OverSampling` strategy. All the other necessary information is present in the general [Documentation](/documentation). ```cpp -#include +#include -PJON bus; +PJONOverSampling bus; void setup() { // Set the pin 12 as the communication pin diff --git a/src/strategies/PJON_Strategies.h b/src/strategies/PJON_Strategies.h deleted file mode 100644 index f18a625d2f..0000000000 --- a/src/strategies/PJON_Strategies.h +++ /dev/null @@ -1,86 +0,0 @@ - -/* PJON dynamic Strategy inclusion - ___________________________________________________________________________ - - Copyright 2018 Giovanni Blu Mitolo gioscarab@gmail.com - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. */ - -#pragma once - -/* Strategy related constant predefinition memory optimization */ - -#if defined(PJON_INCLUDE_ANY) - #include "Any/Any.h" -#endif -#if defined(PJON_INCLUDE_AS) - #include "AnalogSampling/AnalogSampling.h" -#endif -#if defined(PJON_INCLUDE_ETCP) - #include "EthernetTCP/EthernetTCP.h" -#endif -#if defined(PJON_INCLUDE_LUDP) - #include "LocalUDP/LocalUDP.h" -#endif -#if defined(PJON_INCLUDE_GUDP) - #include "GlobalUDP/GlobalUDP.h" -#endif -#if defined(PJON_INCLUDE_DUDP) - #include "DualUDP/DualUDP.h" -#endif -#if defined(PJON_INCLUDE_MQTT) - #include "EthernetTCP/EthernetTCP.h" - #include "MQTTTranslate/MQTTTranslate.h" -#endif -#if defined(PJON_INCLUDE_OS) - #include "OverSampling/OverSampling.h" -#endif -#if defined(PJON_INCLUDE_SWBB) - #include "SoftwareBitBang/SoftwareBitBang.h" -#endif -#if defined(PJON_INCLUDE_TS) - #include "ThroughSerial/ThroughSerial.h" -#endif -#if defined(PJON_INCLUDE_TL) - #include "ThroughLoRa/ThroughLora.h" -#endif -#if defined(PJON_INCLUDE_EN) - #include "ESPNOW/ESPNOW.h" -#endif -#if defined(PJON_INCLUDE_LF) - #include "LocalFile/LocalFile.h" -#endif -#if defined(PJON_INCLUDE_NONE) - /* None for custom strategy inclusion */ -#endif - -#if !defined(PJON_INCLUDE_AS) && !defined(PJON_INCLUDE_ETCP) && \ - !defined(PJON_INCLUDE_GUDP) && !defined(PJON_INCLUDE_LUDP) && \ - !defined(PJON_INCLUDE_OS) && !defined(PJON_INCLUDE_SWBB) && \ - !defined(PJON_INCLUDE_TS) && !defined(PJON_INCLUDE_NONE) && \ - !defined(PJON_INCLUDE_DUDP) && !defined(PJON_INCLUDE_LF) && \ - !defined(PJON_INCLUDE_MQTT) && !defined(PJON_INCLUDE_TL) - #include "Any/Any.h" - #include "AnalogSampling/AnalogSampling.h" - #include "OverSampling/OverSampling.h" - #include "SoftwareBitBang/SoftwareBitBang.h" - #include "ThroughSerial/ThroughSerial.h" - /* Avoid ATtiny44/84/45/85 and STM32F1 missing inclusion error */ - #if !defined(__AVR_ATtiny45__) && !defined(__AVR_ATtiny85__) && \ - !defined(__AVR_ATtiny44__) && !defined(__AVR_ATtiny84__) && !defined(ARDUINO_ARCH_STM32) - #include "EthernetTCP/EthernetTCP.h" - #include "LocalUDP/LocalUDP.h" - #include "GlobalUDP/GlobalUDP.h" - #include "DualUDP/DualUDP.h" - #endif -#endif diff --git a/src/strategies/README.md b/src/strategies/README.md index 6a4f39fbe9..9717e68817 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -4,21 +4,21 @@ A strategy is an abstraction layer used to physically transmit data. Thanks to t The table below lists the strategies available: -| Strategy | Physical layer | Protocol | Inclusion constant | Included by default | -| ------------- | -------------- | -------- | ------------------ | ------------------- | -| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | `PJON_INCLUDE_AS` | yes | -| [Any](/src/strategies/Any) | Virtual inheritance | Any | `PJON_INCLUDE_ANY` | yes | -| [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `PJON_INCLUDE_DUDP` | yes | -| [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | `PJON_INCLUDE_EN` | no | -| [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | `PJON_INCLUDE_ETCP` | yes | -| [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `PJON_INCLUDE_GUDP` | yes | -| [LocalFile](/src/strategies/LocalFile) | System memory | None | `PJON_INCLUDE_LF` | no | -| [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `PJON_INCLUDE_LUDP` | yes | -| [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | `PJON_INCLUDE_MQTT` | no | -| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | `PJON_INCLUDE_OS` | yes | -| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | `PJON_INCLUDE_SWBB` | yes | -| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | `PJON_INCLUDE_TL` | no | -| [ThroughSerial](/src/strategies/ThroughSerial) | Radio | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | `PJON_INCLUDE_TS` | yes | +| Strategy | Physical layer | Protocol | Inclusion | +| ------------- | -------------- | -------- | --------- | +| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | `#include ` | +| [Any](/src/strategies/Any) | Virtual inheritance | Any | `#include ` | +| [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | +| [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | `#include ` | +| [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | `#include ` | +| [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | +| [LocalFile](/src/strategies/LocalFile) | System memory | None | `#include ` | +| [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | +| [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | `#include ` | +| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | `#include ` | +| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | `#include ` | +| [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | `#include ` | +| [ThroughSerial](/src/strategies/ThroughSerial) | Wire | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | `#include ` | ### How the strategy is implemented A `Strategy` is a class containing a set of methods used to physically send and receive data along with the required getters to handle retransmission and collision: @@ -94,7 +94,6 @@ class YourStrategyName { }; ``` -The last thing to do is to add the inclusion of the new strategy in `PJON_Strategies.h`. If all is correct it should be possible to instantiate PJON using the new strategy: ```cpp diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index efaafa924c..0c705320a7 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -1,8 +1,8 @@ ## SoftwareBitBang -| Medium | Pins used | Inclusion Constant | Included by default | -|--------|-----------|--------------------|---------------------| -| Wire | 1 or 2 | `PJON_INCLUDE_SWBB`| yes | +| Medium | Pins used | Inclusion | +|--------|-----------|--------------------| +| Wire | 1 or 2 | `#include `| `SoftwareBitBang` is a software implementation of [PJDL (Padded Jittering Data Link)](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md). It supports simplex and half-duplex asynchronous serial communication for up to 254 devices over a single wire. The maximum length of the bus can reach between 800 and 2000 meters depending on the mode used. It is a valid alternative to 1-Wire because of its flexibility and reliability. Fault tolerance schemes can be easily implemented because communication pins can be configured at runtime. Take a look at the [video introduction](https://www.youtube.com/watch?v=GWlhKD5lz5w) for a brief showcase of its features. ```cpp @@ -54,7 +54,7 @@ Communication over a single wire enables quick and creative experimentation. The The picture above shows a [PJDL](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) frame transmitted over a 800m twisted pair using mode `4` (test done by [Jack Anderson](https://github.com/jdaandersj)). Although bits are substantially deformed the exchange occurs nominally and performance is not affected. ### Configuration -Before including `PJON.h` it is possible to configure `SoftwareBitBang` using predefined constants: +Before including the library it is possible to configure `SoftwareBitBang` using predefined constants: | Constant | Purpose | Supported value | | ----------------------- |------------------------------------ | ------------------------------------------ | @@ -66,9 +66,9 @@ Before including `PJON.h` it is possible to configure `SoftwareBitBang` using pr `SoftwareBitBang` supports the use of input and output pins because separated signals may be required if additional circuitry is used for amplification or noise filtering. It also works if pins are directly connected as a simple point-to-point null-modem or cross-over serial link. ```cpp -#include +#include -PJON bus; +PJONSoftwareBitBang bus; void setup() { // Set the pin 12 as the communication pin diff --git a/src/strategies/ThroughLoRa/README.md b/src/strategies/ThroughLoRa/README.md index fd26160f6a..0db79c3497 100644 --- a/src/strategies/ThroughLoRa/README.md +++ b/src/strategies/ThroughLoRa/README.md @@ -1,8 +1,8 @@ ## ThroughLoRa -| Medium | Pins used | Inclusion Constant | Included by default | -|--------|-----------|--------------------|---------------------| -| LoRa radio | 6 | `PJON_INCLUDE_TL`| no | +| Medium | Pins used | Inclusion | +|--------|-----------|--------------------| +| LoRa radio | 6 | `#include `| With `ThroughLora` strategy, PJON can run through a software or hardware SPI in order to communicate with supported LoRa modules. See [Supported Shields/Modules](https://github.com/gioblu/PJON/tree/master/src/strategies/ThroughLoRa#supported-shieldsmodules). @@ -15,17 +15,16 @@ This strategy is a wrapper around [Arduino LoRa library](https://github.com/san - STM32F103 ([Blue Pill](http://wiki.stm32duino.com/index.php?title=Blue_Pill)) ### Getting started -1. Define `PJON_INCLUDE_TL` before including PJON header `` -2. Pass the `ThroughLora` type as PJON template parameter to instantiate a PJON object ready to communicate through this Strategy. -3. Configure the shield/module pins according to the correct connection. See [Hardware connection](#hardware-connection). -4. Initialize the module with its specified frequency. +1. Pass the `ThroughLora` type as PJON template parameter to instantiate a PJON object ready to communicate through this Strategy. +2. Configure the shield/module pins according to the correct connection. See [Hardware connection](#hardware-connection). +3. Initialize the module with its specified frequency. ```cpp -#define PJON_INCLUDE_TL //Definition to enable ThroughLora strategy -#include //PJON header +#include + +PJONThroughLora bus; //PJON Lora bus instance -PJON bus; //PJON Lora bus instance bus.strategy.setPins(10,9,2); //CS pin, Reset pin, Interrupt pin bus.strategy.setFrequency(868100000UL); //initialize 868 MHZ module ``` @@ -62,11 +61,10 @@ More examples can be found in https://github.com/gioblu/PJON/tree/master/example ### Transmitter ```cpp -#define PJON_INCLUDE_TL -#include +#include -PJON bus(45); +PJONThroughLora bus(45); void setup() { // Obligatory to initialize Radio with correct frequency @@ -84,12 +82,10 @@ void loop() { ### Receiver ```cpp -#define PJON_INCLUDE_TL - -#include +#include // bus(selected device id) -PJON bus(44); +PJONThroughLora bus(44); void setup() { pinMode(13, OUTPUT); diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index 91190c5380..7e5d5b2024 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -1,8 +1,8 @@ ## ThroughSerial -**Medium:** Hardware or software serial port - -**Pins used:** 1 or 2 - -**Inclusion constant:** `PJON_INCLUDE_TS` +| Medium | Pins used | Inclusion | +|--------|-----------|--------------------| +| Wires | 2 | `#include `| With `ThroughSerial` strategy, PJON can run through a software or hardware Serial port working out of the box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). It complies with [TSDL v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md). @@ -16,7 +16,7 @@ Serial communication is fast and reliable but it is often useless without all th `ThroughSerial` performs well if used with ESP8266 and ESP32 where blocking procedures can strongly degrade functionality. The reception phase is entirely non-blocking. Sending and acknowledgement however are still blocking. ### Configuration -Before including `PJON.h` it is possible to configure `ThroughSerial` using predefined constants: +Before including the library it is possible to configure `ThroughSerial` using predefined constants: | Constant | Purpose | Supported value | | ----------------------- |------------------------------------ | ------------------------------------------ | @@ -26,16 +26,15 @@ Before including `PJON.h` it is possible to configure `ThroughSerial` using pred | `TS_BACK_OFF_DEGREE` | Maximum back-off exponential degree | Numeric value (4 by default) | | `TS_MAX_ATTEMPTS` | Maximum transmission attempts | Numeric value (20 by default) | -Pass the `ThroughSerial` type as PJON template parameter to instantiate a PJON object ready to communicate through this Strategy. +Use `PJONThroughSerial` to instantiate a PJON object ready to communicate using `ThroughSerial` strategy: ```cpp -#include PJON_INCLUDE_TS -PJON bus; +#include +PJONThroughSerial bus; ``` Call the `begin` method on the `Serial` or `SoftwareSerial` object you want to use for PJON communication and pass it to the `set_serial` method: ```cpp -#include - -PJON bus; +#include +PJONThroughSerial bus; void setup() { Serial.begin(9600); From 87e3e1a6988f23852434f40d9ede6ff6a44f4c1d Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 13 Jun 2020 20:13:49 +0200 Subject: [PATCH 088/323] Outdated comments removed --- .../Local/AnalogSampling/BlinkTest/Receiver/Receiver.ino | 2 +- .../AnalogSampling/BlinkTest/Transmitter/Transmitter.ino | 2 +- .../AnalogSampling/NetworkAnalysis/Receiver/Receiver.ino | 2 +- .../NetworkAnalysis/Transmitter/Transmitter.ino | 2 +- .../Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino | 2 +- .../Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino | 2 +- examples/ARDUINO/Local/DualUDP/PingPong/Receiver/Receiver.ino | 2 +- .../Local/DualUDP/PingPong/Transmitter/Transmitter.ino | 2 +- .../ARDUINO/Local/EthernetTCP/PingPong/Receiver/Receiver.ino | 2 +- .../Local/EthernetTCP/PingPong/Transmitter/Transmitter.ino | 2 +- .../RemoteWorker/Transmitter/Transmitter.ino | 2 +- .../SoftwareBitBangSurrogate/Surrogate/Surrogate.ino | 2 +- .../ARDUINO/Local/GlobalUDP/PingPong/Receiver/Receiver.ino | 2 +- .../Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino | 2 +- .../ARDUINO/Local/LocalUDP/PingPong/Receiver/Receiver.ino | 2 +- .../Local/LocalUDP/PingPong/Transmitter/Transmitter.ino | 2 +- .../Local/MQTTTranslate/PingPong/Receiver/Receiver.ino | 2 +- .../Local/MQTTTranslate/PingPong/Transmitter/Transmitter.ino | 2 +- .../Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino | 2 +- .../MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino | 2 +- .../ARDUINO/Local/OverSampling/HalfDuplex/Device1/Device1.ino | 2 +- .../ARDUINO/Local/OverSampling/HalfDuplex/Device2/Device2.ino | 2 +- .../OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino | 2 +- .../OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino | 2 +- .../Local/OverSampling/NetworkAnalysis/Receiver/Receiver.ino | 2 +- .../OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino | 2 +- .../ARDUINO/Local/OverSampling/Simplex/Receiver/Receiver.ino | 2 +- .../Local/OverSampling/Simplex/Transmitter/Transmitter.ino | 2 +- .../Local/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino | 2 +- .../SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino | 2 +- .../SoftwareBitBang/BlinkWithResponse/Receiver/Receiver.ino | 2 +- .../BlinkWithResponse/Transmitter/Transmitter.ino | 2 +- .../SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino | 2 +- .../ClassMemberCallback/Transmitter/Transmitter.ino | 2 +- .../SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino | 2 +- .../NetworkAnalysis/Transmitter/Transmitter.ino | 2 +- .../SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino | 2 +- .../PJONLocal/NetworkAnalysis/Receiver/Receiver.ino | 2 +- .../PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino | 2 +- .../Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino | 2 +- .../Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino | 2 +- .../SendArbitraryDataType/Transmitter/Transmitter.ino | 2 +- .../SendArbitraryValues/Transmitter/Transmitter.ino | 2 +- .../Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino | 2 +- .../SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino | 2 +- .../Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino | 2 +- .../SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino | 2 +- .../ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino | 2 +- .../Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino | 2 +- .../ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino | 2 +- .../ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino | 2 +- .../Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino | 2 +- .../ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino | 2 +- .../ARDUINO/Local/ThroughLoRa/Simplex/Receiver/Receiver.ino | 2 +- .../Local/ThroughLoRa/Simplex/Transmitter/Transmitter.ino | 2 +- .../Local/ThroughSerial/HC-12-Blink/Receiver/Receiver.ino | 2 +- .../ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino | 4 ++-- .../Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino | 4 ++-- .../ThroughSerial/HC-12-SendAndReceive/Receiver/Receiver.ino | 2 +- .../HC-12-SendAndReceive/Transmitter/Transmitter.ino | 2 +- .../Local/ThroughSerial/NucleoBlinkTest/Receiver/Receiver.ino | 2 +- .../ThroughSerial/NucleoBlinkTest/Transmitter/Transmitter.ino | 2 +- .../Local/ThroughSerial/RS485-Blink/Receiver/Receiver.ino | 2 +- .../ThroughSerial/RS485-Blink/Transmitter/Transmitter.ino | 2 +- .../RS485-BlinkWithResponse/Receiver/Receiver.ino | 2 +- .../RS485-BlinkWithResponse/Transmitter/Transmitter.ino | 2 +- .../SoftwareBitBangSurrogate/Surrogate/Surrogate.ino | 2 +- .../Network/OverSampling/HalfDuplex/Receiver/Receiver.ino | 2 +- .../OverSampling/HalfDuplex/Transmitter/Transmitter.ino | 2 +- examples/ESP32/DualUDP/PingPong/Receiver/Receiver.ino | 2 +- examples/ESP32/DualUDP/PingPong/Transmitter/Transmitter.ino | 2 +- examples/ESP8266/Local/DualUDP/PingPong/Receiver/Receiver.ino | 2 +- .../Local/DualUDP/PingPong/Transmitter/Transmitter.ino | 2 +- .../ESP8266/Local/GlobalUDP/PingPong/Receiver/Receiver.ino | 2 +- .../Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino | 2 +- .../LINUX/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp | 2 +- .../Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp | 2 +- examples/LINUX/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp | 2 +- .../Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp | 2 +- examples/LINUX/Local/LocalFile/PingPong/Receiver/Receiver.cpp | 2 +- .../Local/LocalFile/PingPong/Transmitter/Transmitter.cpp | 2 +- examples/LINUX/Local/LocalUDP/PingPong/Receiver/Receiver.cpp | 2 +- .../LINUX/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp | 2 +- .../WINX86/Local/MQTTTranslate/PingPong/Receiver/Receiver.cpp | 2 +- .../Local/MQTTTranslate/PingPong/Transmitter/Transmitter.cpp | 2 +- 85 files changed, 87 insertions(+), 87 deletions(-) diff --git a/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Receiver/Receiver.ino index d250511643..817ca115c0 100644 --- a/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Receiver/Receiver.ino @@ -4,7 +4,7 @@ To know how to wire up the circuit see the AnalogSampling README: https://github.com/gioblu/PJON/tree/master/src/strategies/AnalogSampling */ -// bus(selected device id) + PJONAnalogSampling bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Transmitter/Transmitter.ino index 121a935ce2..071fe3c817 100644 --- a/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/AnalogSampling/BlinkTest/Transmitter/Transmitter.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONAnalogSampling bus(45); void setup() { diff --git a/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Receiver/Receiver.ino index 6f03c9adc9..53a01e1284 100644 --- a/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Receiver/Receiver.ino @@ -5,7 +5,7 @@ #include -// bus(selected device id) + PJONAnalogSampling bus(44); void setup() { diff --git a/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Transmitter/Transmitter.ino index 266a358660..b061fc9cd1 100644 --- a/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/AnalogSampling/NetworkAnalysis/Transmitter/Transmitter.ino @@ -13,7 +13,7 @@ float mistakes; int busy; int fail; -// bus(selected device id) + PJONAnalogSampling bus(45); int packet; diff --git a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino index a4c85afc41..d5e8659a05 100644 --- a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino +++ b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino @@ -15,7 +15,7 @@ #include -// bus(selected device id) + PJON bus(1); void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { diff --git a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino index 9fbff25405..0ec5e22748 100644 --- a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino +++ b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino @@ -15,7 +15,7 @@ #include -// bus(selected device id) + PJON bus(1); void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { diff --git a/examples/ARDUINO/Local/DualUDP/PingPong/Receiver/Receiver.ino b/examples/ARDUINO/Local/DualUDP/PingPong/Receiver/Receiver.ino index a1b178c4c6..4d600baa16 100644 --- a/examples/ARDUINO/Local/DualUDP/PingPong/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/DualUDP/PingPong/Receiver/Receiver.ino @@ -3,7 +3,7 @@ // Ethernet configuration for this device byte mac[] = {0xDA, 0x5A, 0x4E, 0xEF, 0xAE, 0xED}; -// bus(selected device id) + PJONDualUDP bus(44); uint32_t cnt = 0; diff --git a/examples/ARDUINO/Local/DualUDP/PingPong/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/DualUDP/PingPong/Transmitter/Transmitter.ino index 9bf4b028e3..d62bca99a2 100644 --- a/examples/ARDUINO/Local/DualUDP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/DualUDP/PingPong/Transmitter/Transmitter.ino @@ -3,7 +3,7 @@ // Ethernet configuration for this device byte mac[] = {0xDA, 0xCA, 0x7E, 0xEF, 0xFE, 0x5D}; -// bus(selected device id) + PJONDualUDP bus(45); uint32_t cnt = 0, wait_for_reply = 0; diff --git a/examples/ARDUINO/Local/EthernetTCP/PingPong/Receiver/Receiver.ino b/examples/ARDUINO/Local/EthernetTCP/PingPong/Receiver/Receiver.ino index 824022a36c..3880b4a92b 100644 --- a/examples/ARDUINO/Local/EthernetTCP/PingPong/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/EthernetTCP/PingPong/Receiver/Receiver.ino @@ -7,7 +7,7 @@ byte mac[] = {0xDE, 0x5D, 0x4E, 0xEF, 0xAE, 0xED}; uint8_t local_ip[] = { 192, 1, 1, 144 }, remote_ip[] = { 192, 1, 1, 145 }; -// bus(selected device id) + PJONEthernetTCP bus(44); uint32_t cnt = 0; diff --git a/examples/ARDUINO/Local/EthernetTCP/PingPong/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/EthernetTCP/PingPong/Transmitter/Transmitter.ino index a09fce777c..138651700a 100644 --- a/examples/ARDUINO/Local/EthernetTCP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/EthernetTCP/PingPong/Transmitter/Transmitter.ino @@ -7,7 +7,7 @@ byte mac[] = {0xDE, 0xCD, 0x7E, 0xEF, 0xFE, 0x5D}; uint8_t local_ip[] = { 192, 1, 1, 145 }, remote_ip[] = { 192, 1, 1, 144 }; -// bus(selected device id) + PJONEthernetTCP bus(45); uint32_t cnt = 0; diff --git a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/RemoteWorker/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/RemoteWorker/Transmitter/Transmitter.ino index 9d65c6e71b..815259b7ef 100644 --- a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/RemoteWorker/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/RemoteWorker/Transmitter/Transmitter.ino @@ -27,7 +27,7 @@ #include -// bus(selected device id) + PJONEthernetTCP bus(45); // Ethernet configuration for this device diff --git a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino index 3d465a439f..860939c536 100644 --- a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino +++ b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino @@ -19,7 +19,7 @@ const uint8_t DEVICE_ID = 45; // SWBB Device ID for this device and the RemoteWorker -// bus(selected device id) + PJON busA(DEVICE_ID); PJONEthernetTCP busB(1); diff --git a/examples/ARDUINO/Local/GlobalUDP/PingPong/Receiver/Receiver.ino b/examples/ARDUINO/Local/GlobalUDP/PingPong/Receiver/Receiver.ino index 3d7dcb4b08..14e5aaa765 100644 --- a/examples/ARDUINO/Local/GlobalUDP/PingPong/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/GlobalUDP/PingPong/Receiver/Receiver.ino @@ -9,7 +9,7 @@ uint8_t local_ip[] = { 192, 1, 1, 151 }; // Address of remote device uint8_t remote_ip[] = { 192, 1, 1, 150 }; -// bus(selected device id) + PJONGlobalUDP bus(44); uint32_t cnt = 0; diff --git a/examples/ARDUINO/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino index f1300e8f08..9812b1c17b 100644 --- a/examples/ARDUINO/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino @@ -9,7 +9,7 @@ uint8_t local_ip[] = { 192, 1, 1, 150 }; // Address of remote device uint8_t remote_ip[] = { 192, 1, 1, 151 }; -// bus(selected device id) + PJONGlobalUDP bus(45); uint32_t cnt = 0; diff --git a/examples/ARDUINO/Local/LocalUDP/PingPong/Receiver/Receiver.ino b/examples/ARDUINO/Local/LocalUDP/PingPong/Receiver/Receiver.ino index cc3c3cc6c6..5782ad0a3b 100644 --- a/examples/ARDUINO/Local/LocalUDP/PingPong/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/LocalUDP/PingPong/Receiver/Receiver.ino @@ -6,7 +6,7 @@ byte subnet[] = { 255, 255, 255, 0 }; byte mac[] = {0xDA, 0x5A, 0x4E, 0xEF, 0xAE, 0xED}; uint8_t local_ip[] = { 192, 1, 1, 151 }; -// bus(selected device id) + PJONLocalUDP bus(44); uint32_t cnt = 0; diff --git a/examples/ARDUINO/Local/LocalUDP/PingPong/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/LocalUDP/PingPong/Transmitter/Transmitter.ino index e2e246add4..dda176f7f4 100644 --- a/examples/ARDUINO/Local/LocalUDP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/LocalUDP/PingPong/Transmitter/Transmitter.ino @@ -6,7 +6,7 @@ byte subnet[] = { 255, 255, 255, 0 }; byte mac[] = {0xDA, 0xCA, 0x7E, 0xEF, 0xFE, 0x5D}; uint8_t local_ip[] = { 192, 1, 1, 150 }; -// bus(selected device id) + PJONLocalUDP bus(45); uint32_t cnt = 0; diff --git a/examples/ARDUINO/Local/MQTTTranslate/PingPong/Receiver/Receiver.ino b/examples/ARDUINO/Local/MQTTTranslate/PingPong/Receiver/Receiver.ino index 92a06d6032..a570ee0ec6 100644 --- a/examples/ARDUINO/Local/MQTTTranslate/PingPong/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/MQTTTranslate/PingPong/Receiver/Receiver.ino @@ -5,7 +5,7 @@ byte mac[] = {0xDE, 0x5A, 0x4E, 0xEF, 0xAE, 0xED}; uint8_t broker_ip[] = { 192, 1, 1, 71 }; -// bus(selected device id) + PJONMQTTTranslate bus(44); uint32_t cnt = 0; diff --git a/examples/ARDUINO/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.ino index e07bd155ab..2f44de591a 100644 --- a/examples/ARDUINO/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.ino @@ -5,7 +5,7 @@ byte mac[] = {0xDA, 0xCA, 0x7E, 0xEF, 0xFE, 0x5D}; uint8_t broker_ip[] = { 192, 1, 1, 71 }; -// bus(selected device id) + PJONMQTTTranslate bus(45); uint32_t cnt = 0; diff --git a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino index b3e54cf6d9..f85edbd01d 100644 --- a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino +++ b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino @@ -8,7 +8,7 @@ byte mac[] = {0xDA, 0xCA, 0x7E, 0xEF, 0xFE, 0x5D}; uint8_t broker_ip[] = { 192, 168, 1, 71 }; -// bus(selected device id) + #define PJON_GATEWAY_ID 254 PJON bus(PJON_GATEWAY_ID); PJONMQTTTranslate mqtt; diff --git a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino index a79de74505..647f42873d 100644 --- a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino +++ b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino @@ -17,7 +17,7 @@ #define PJON_GATEWAY_ID 254 -// bus(selected device id) + PJON bus(42); float temperature = 20.0; // "Measurement" diff --git a/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device1/Device1.ino b/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device1/Device1.ino index cb58c120d7..ec95f5c3fe 100644 --- a/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device1/Device1.ino +++ b/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device1/Device1.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONOverSampling bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device2/Device2.ino b/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device2/Device2.ino index 1b7ceeac39..dee08b91b4 100644 --- a/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device2/Device2.ino +++ b/examples/ARDUINO/Local/OverSampling/HalfDuplex/Device2/Device2.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONOverSampling bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino b/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino index 03539c763c..ae54176c86 100644 --- a/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino +++ b/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device1/Device1.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONOverSampling bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino b/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino index 49c37802a2..a75fda6674 100644 --- a/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino +++ b/examples/ARDUINO/Local/OverSampling/HalfDuplexNoAcknowledge/Device2/Device2.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONOverSampling bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Receiver/Receiver.ino index 985e621706..bb3aeccf27 100644 --- a/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Receiver/Receiver.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONOverSampling bus(44); void setup() { diff --git a/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino index f374a3917e..9318e1f2f3 100644 --- a/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/OverSampling/NetworkAnalysis/Transmitter/Transmitter.ino @@ -5,7 +5,7 @@ float mistakes; int busy; int fail; -// bus(selected device id) + PJONOverSampling bus(45); int packet; diff --git a/examples/ARDUINO/Local/OverSampling/Simplex/Receiver/Receiver.ino b/examples/ARDUINO/Local/OverSampling/Simplex/Receiver/Receiver.ino index 445b20ddaf..3d32bfcbf6 100644 --- a/examples/ARDUINO/Local/OverSampling/Simplex/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/OverSampling/Simplex/Receiver/Receiver.ino @@ -7,7 +7,7 @@ int busy; int fail; -// bus(selected device id) + PJONOverSampling bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/OverSampling/Simplex/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/OverSampling/Simplex/Transmitter/Transmitter.ino index 1cf7524867..1b13596aef 100644 --- a/examples/ARDUINO/Local/OverSampling/Simplex/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/OverSampling/Simplex/Transmitter/Transmitter.ino @@ -1,7 +1,7 @@ #include -// bus(selected device id) + PJONOverSampling bus(45); uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino index 614034a2a2..f6457aa152 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Receiver/Receiver.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONSoftwareBitBang bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino index 50e89e121f..f774ed0d16 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkTest/Transmitter/Transmitter.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONSoftwareBitBang bus(45); void setup() { diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Receiver/Receiver.ino index 2d686ce56b..490ebd7b59 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Receiver/Receiver.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONSoftwareBitBang bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Transmitter/Transmitter.ino index 786f0fdb0f..09616ccec9 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/BlinkWithResponse/Transmitter/Transmitter.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONSoftwareBitBang bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino index 88f4b423c6..c4db327eb4 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino @@ -13,7 +13,7 @@ #include -// bus(selected device id) + PJONSoftwareBitBang bus(44); // Custom class diff --git a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino index dc8f22651f..0760e2890c 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino @@ -13,7 +13,7 @@ #include -// bus(selected device id) + PJONSoftwareBitBang bus(45); int packet; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino index 936fc69db0..5688a76d74 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino @@ -13,7 +13,7 @@ #include -// bus(selected device id) + PJONSoftwareBitBang bus(44); void setup() { diff --git a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino index 9199f426cc..38a42a3be2 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino @@ -18,7 +18,7 @@ float mistakes; int busy; int fail; -// bus(selected device id) + PJONSoftwareBitBang bus(45); int packet; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino index 391275f1ca..114f319efb 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino @@ -5,7 +5,7 @@ #define PJON_PACKET_MAX_LENGTH 10 // Include PJONLocal #include -// bus(selected device id) + PJONLocal bus(44); uint8_t data[PJON_PACKET_MAX_LENGTH]; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino index 20c8036881..bdfd3e618d 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino @@ -17,7 +17,7 @@ // Include PJONLocal #include -// bus(selected device id) + PJONLocal bus(44); uint8_t data[PJON_PACKET_MAX_LENGTH]; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino index 745499f5fc..2a7816742c 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino @@ -6,7 +6,7 @@ // Include PJONLocal #include -// bus(selected device id) + PJONLocal bus(44); uint8_t data[PJON_PACKET_MAX_LENGTH]; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino index 4602481374..6a932df11b 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino @@ -13,7 +13,7 @@ #include -// bus(selected device id) + PJONSoftwareBitBang bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino index 73f92af246..633762822a 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino @@ -13,7 +13,7 @@ #include -// bus(selected device id) + PJONSoftwareBitBang bus(45); void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Transmitter/Transmitter.ino index a1a4ec2150..8a8d78a637 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryDataType/Transmitter/Transmitter.ino @@ -3,7 +3,7 @@ /* ARBITRARY DATA TYPE TRANSMISSION EXAMPLE This sketch contains the transmitter side. */ -// bus(selected device id) + PJONSoftwareBitBang bus(45); int packet; int voltage; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino index 53dcc8de20..e52f1c8fc8 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendArbitraryValues/Transmitter/Transmitter.ino @@ -9,7 +9,7 @@ is printed transmitted data, exchange duration and transmission speed for easy benchmarking and nominal functionality assessment. */ -// bus(selected device id) + PJONSoftwareBitBang bus(45); uint32_t myTime; int packet; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino index 0a7f651668..403ec19aad 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino @@ -18,7 +18,7 @@ float mistakes; int busy; int fail; -// bus(selected device id) + PJONSoftwareBitBang bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino index 6d2cf9ca2b..0df80f7c80 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino @@ -13,7 +13,7 @@ #include -// bus(selected device id) + PJONSoftwareBitBang bus(45); uint8_t content[] = "01234567890123456789"; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino index 48168d3b94..3e0d682232 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino @@ -21,7 +21,7 @@ float mistakes; int busy; int fail; -// bus(selected device id) + PJONSoftwareBitBang bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino index 7d4c6b5e56..9c24311664 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino @@ -16,7 +16,7 @@ #include -// bus(selected device id) + PJONSoftwareBitBang bus(45); int packet; diff --git a/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino index c11fff1b2f..7af7bb2f1c 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Receiver/Receiver.ino @@ -6,7 +6,7 @@ /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ -// bus(selected device id) + PJONThroughLora bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino index c4bdfaef9a..6e8a786061 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/BlinkTest/Transmitter/Transmitter.ino @@ -5,7 +5,7 @@ /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ -// bus(selected device id) + PJONThroughLora bus(45); void setup() { diff --git a/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino b/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino index 720bf22dda..e5f05c7b63 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device1/Device1.ino @@ -6,7 +6,7 @@ /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ -// bus(selected device id) + PJONThroughLora bus(44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino b/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino index 11b8085874..8577944a0a 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/HalfDuplex/Device2/Device2.ino @@ -6,7 +6,7 @@ /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ -// bus(selected device id) + PJONThroughLora bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino index 06095ad566..4eeb37a0e1 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Receiver/Receiver.ino @@ -6,7 +6,7 @@ /* To use this example, please download the LoRa third party Library from https://github.com/sandeepmistry/arduino-LoRa/ */ -// bus(selected device id) + PJONThroughLora bus(44); void setup() { diff --git a/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino index b3f494327d..e6922245cd 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/NetworkAnalysis/Transmitter/Transmitter.ino @@ -11,7 +11,7 @@ float mistakes; int busy; int fail; -// bus(selected device id) + PJONThroughLora bus(45); int packet; diff --git a/examples/ARDUINO/Local/ThroughLoRa/Simplex/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughLoRa/Simplex/Receiver/Receiver.ino index 7c8f7d7e30..fba15857ec 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/Simplex/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/Simplex/Receiver/Receiver.ino @@ -10,7 +10,7 @@ float mistakes; int busy; int fail; -// bus(selected device id) + PJONThroughLora bus(44); void setup() { diff --git a/examples/ARDUINO/Local/ThroughLoRa/Simplex/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughLoRa/Simplex/Transmitter/Transmitter.ino index 1b8e523e9b..1dce59865e 100644 --- a/examples/ARDUINO/Local/ThroughLoRa/Simplex/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughLoRa/Simplex/Transmitter/Transmitter.ino @@ -11,7 +11,7 @@ float mistakes; int busy; int fail; -// bus(selected device id) + PJONThroughLora bus(45); int packet; diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Receiver/Receiver.ino index 6cd33cc3cf..836d57cdc6 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Receiver/Receiver.ino @@ -9,7 +9,7 @@ SoftwareSerial HC12(2, 3); -// bus(selected device id) + PJONThroughSerial bus(44); void setup() { diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino index d39222b507..e30e53dcfb 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-Blink/Transmitter/Transmitter.ino @@ -9,7 +9,7 @@ SoftwareSerial HC12(2, 3); -// bus(selected device id) + PJONThroughSerial bus(45); void setup() { @@ -19,7 +19,7 @@ void setup() { // Pass the HC12 Serial instance you want to use for PJON communication bus.strategy.set_serial(&HC12); - // Avoid synchronous acknowledgement + // Avoid acknowledgement bus.set_acknowledge(false); bus.begin(); diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino index 493cedd7d9..10a13dbe4e 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat/HC-12-LocalChat.ino @@ -22,7 +22,7 @@ Giovanni Blu Mitolo 2018 */ -/* Set synchronous response timeout to 100 milliseconds. +/* Set synchronous response timeout to 200 milliseconds. If operating at less than 9600Bd TS_RESPONSE_TIME_OUT should be longer */ #define TS_RESPONSE_TIME_OUT 200000 @@ -44,7 +44,7 @@ SoftwareSerial HC12(2, 3); -// bus(selected device id) + PJONThroughSerial bus; uint8_t packet[100]; diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Receiver/Receiver.ino index 6f9510c073..7c36536684 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Receiver/Receiver.ino @@ -14,7 +14,7 @@ SoftwareSerial HC12(2, 3); -// bus(selected device id) + PJONThroughSerial bus(44); void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { diff --git a/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Transmitter/Transmitter.ino index 55e6f4eff9..500a93cf59 100644 --- a/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive/Transmitter/Transmitter.ino @@ -14,7 +14,7 @@ SoftwareSerial HC12(2, 3); -// bus(selected device id) + PJONThroughSerial bus(45); void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { diff --git a/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Receiver/Receiver.ino index 9d8bba6650..019571bb2c 100644 --- a/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Receiver/Receiver.ino @@ -5,7 +5,7 @@ #include -// bus(selected device id) + PJONThroughSerial bus(44); void setup() { diff --git a/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Transmitter/Transmitter.ino index 58693f032a..8ddfe9859d 100644 --- a/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/NucleoBlinkTest/Transmitter/Transmitter.ino @@ -5,7 +5,7 @@ #include -// bus(selected device id) + PJONThroughSerial bus(45); void setup() { diff --git a/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Receiver/Receiver.ino index 37638ab185..5f4d6a9cf2 100644 --- a/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Receiver/Receiver.ino @@ -3,7 +3,7 @@ #include -// bus(selected device id) + PJONThroughSerial bus(44); void setup() { diff --git a/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Transmitter/Transmitter.ino index 65d0fa5ef6..e8e53531b8 100644 --- a/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/RS485-Blink/Transmitter/Transmitter.ino @@ -3,7 +3,7 @@ #include -// bus(selected device id) + PJONThroughSerial bus(45); void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { diff --git a/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Receiver/Receiver.ino b/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Receiver/Receiver.ino index ee847f8c5a..99e263ef3c 100644 --- a/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Receiver/Receiver.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONThroughSerial bus(44); void setup() { diff --git a/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter/Transmitter.ino index b319ee25d3..826f11e797 100644 --- a/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/ThroughSerial/RS485-BlinkWithResponse/Transmitter/Transmitter.ino @@ -3,7 +3,7 @@ #include -// bus(selected device id) + PJONThroughSerial bus(45); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino b/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino index ac0dd55023..713bcd0ca3 100644 --- a/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino +++ b/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino @@ -19,7 +19,7 @@ const uint8_t DEVICE_ID = 45; // SWBB Device ID for this device and the RemoteWorker -// bus(selected device id) + PJON busA(DEVICE_ID); //PJON busB(1); PJONThroughSerial busB(1); diff --git a/examples/ARDUINO/Network/OverSampling/HalfDuplex/Receiver/Receiver.ino b/examples/ARDUINO/Network/OverSampling/HalfDuplex/Receiver/Receiver.ino index 1e032eda87..9186c15902 100644 --- a/examples/ARDUINO/Network/OverSampling/HalfDuplex/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/OverSampling/HalfDuplex/Receiver/Receiver.ino @@ -3,7 +3,7 @@ uint8_t bus_id[] = {0, 0, 0, 1}; -// bus(selected device id) + PJONOverSampling bus(bus_id, 44); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { diff --git a/examples/ARDUINO/Network/OverSampling/HalfDuplex/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/OverSampling/HalfDuplex/Transmitter/Transmitter.ino index b8f0ecd73e..ebd8357570 100644 --- a/examples/ARDUINO/Network/OverSampling/HalfDuplex/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/OverSampling/HalfDuplex/Transmitter/Transmitter.ino @@ -3,7 +3,7 @@ uint16_t packet; uint8_t bus_id[] = {0, 0, 0, 1}; -// bus(selected device id) + PJONOverSampling bus(bus_id, 45); void error_handler(uint8_t code, uint16_t data, void *custom_pointer) { diff --git a/examples/ESP32/DualUDP/PingPong/Receiver/Receiver.ino b/examples/ESP32/DualUDP/PingPong/Receiver/Receiver.ino index 6564c6e2b1..7750046329 100644 --- a/examples/ESP32/DualUDP/PingPong/Receiver/Receiver.ino +++ b/examples/ESP32/DualUDP/PingPong/Receiver/Receiver.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONDualUDP bus(44); const char* ssid = "MyNetworkSSID"; diff --git a/examples/ESP32/DualUDP/PingPong/Transmitter/Transmitter.ino b/examples/ESP32/DualUDP/PingPong/Transmitter/Transmitter.ino index 9d94c0834c..a5dc9cedd3 100644 --- a/examples/ESP32/DualUDP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ESP32/DualUDP/PingPong/Transmitter/Transmitter.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONDualUDP bus(45); const char* ssid = "MyNetworkSSID"; diff --git a/examples/ESP8266/Local/DualUDP/PingPong/Receiver/Receiver.ino b/examples/ESP8266/Local/DualUDP/PingPong/Receiver/Receiver.ino index 6564c6e2b1..7750046329 100644 --- a/examples/ESP8266/Local/DualUDP/PingPong/Receiver/Receiver.ino +++ b/examples/ESP8266/Local/DualUDP/PingPong/Receiver/Receiver.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONDualUDP bus(44); const char* ssid = "MyNetworkSSID"; diff --git a/examples/ESP8266/Local/DualUDP/PingPong/Transmitter/Transmitter.ino b/examples/ESP8266/Local/DualUDP/PingPong/Transmitter/Transmitter.ino index 9d94c0834c..a5dc9cedd3 100644 --- a/examples/ESP8266/Local/DualUDP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ESP8266/Local/DualUDP/PingPong/Transmitter/Transmitter.ino @@ -1,6 +1,6 @@ #include -// bus(selected device id) + PJONDualUDP bus(45); const char* ssid = "MyNetworkSSID"; diff --git a/examples/ESP8266/Local/GlobalUDP/PingPong/Receiver/Receiver.ino b/examples/ESP8266/Local/GlobalUDP/PingPong/Receiver/Receiver.ino index ea1a2e4e33..6cfefe8a8e 100644 --- a/examples/ESP8266/Local/GlobalUDP/PingPong/Receiver/Receiver.ino +++ b/examples/ESP8266/Local/GlobalUDP/PingPong/Receiver/Receiver.ino @@ -5,7 +5,7 @@ IPAddress gateway = { 192, 1, 1, 1 }; IPAddress subnet = { 255, 255, 255, 0 }; IPAddress local_ip = { 192, 1, 1, 163 }; -// bus(selected device id) + PJONGlobalUDP bus(44); const char* ssid = "MyNetworkSSID"; diff --git a/examples/ESP8266/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino b/examples/ESP8266/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino index c41ef0a4be..539d4438b0 100644 --- a/examples/ESP8266/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino +++ b/examples/ESP8266/Local/GlobalUDP/PingPong/Transmitter/Transmitter.ino @@ -3,7 +3,7 @@ // Address of remote device uint8_t remote_ip[] = { 192, 1, 1, 163 }; -// bus(selected device id) + PJONGlobalUDP bus(45); const char* ssid = "MyNetworkSSID"; diff --git a/examples/LINUX/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp b/examples/LINUX/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp index 018e0333a1..c18d88cbee 100644 --- a/examples/LINUX/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/EthernetTCP/PingPong/Receiver/Receiver.cpp @@ -3,7 +3,7 @@ uint8_t remote_ip[] = { 192, 1, 1, 161 }; -// bus(selected device id) + PJONEthernetTCP bus(44); diff --git a/examples/LINUX/Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp b/examples/LINUX/Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp index 6968565755..9eb605e179 100644 --- a/examples/LINUX/Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/EthernetTCP/PingPong/Transmitter/Transmitter.cpp @@ -4,7 +4,7 @@ // Address of remote device uint8_t remote_ip[] = { 192, 1, 1, 161 }; -// bus(selected device id) + PJONEthernetTCP bus(45); uint32_t cnt = 0; diff --git a/examples/LINUX/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp b/examples/LINUX/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp index 8b31e5cbfe..edffd00159 100644 --- a/examples/LINUX/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/GlobalUDP/PingPong/Receiver/Receiver.cpp @@ -1,7 +1,7 @@ #include -// bus(selected device id) + PJONGlobalUDP bus(44); //uint32_t millis() { return PJON_MICROS()/1000; } // TODO: Move to interface diff --git a/examples/LINUX/Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp b/examples/LINUX/Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp index 6c217f7762..dbba94b932 100644 --- a/examples/LINUX/Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/GlobalUDP/PingPong/Transmitter/Transmitter.cpp @@ -1,7 +1,7 @@ #include -// bus(selected device id) + PJONGlobalUDP bus(45); uint32_t cnt = 0; diff --git a/examples/LINUX/Local/LocalFile/PingPong/Receiver/Receiver.cpp b/examples/LINUX/Local/LocalFile/PingPong/Receiver/Receiver.cpp index 14b346339a..9ea9b6d2b6 100644 --- a/examples/LINUX/Local/LocalFile/PingPong/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/LocalFile/PingPong/Receiver/Receiver.cpp @@ -2,7 +2,7 @@ #include -// bus(selected device id) + PJONLocalFile bus(44); uint32_t cnt = 0, cnt2 = 1; diff --git a/examples/LINUX/Local/LocalFile/PingPong/Transmitter/Transmitter.cpp b/examples/LINUX/Local/LocalFile/PingPong/Transmitter/Transmitter.cpp index 3cdaa10f81..a5080b23d2 100644 --- a/examples/LINUX/Local/LocalFile/PingPong/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/LocalFile/PingPong/Transmitter/Transmitter.cpp @@ -1,7 +1,7 @@ #include -// bus(selected device id) + PJONLocalFile bus(45); uint32_t cnt = 0; diff --git a/examples/LINUX/Local/LocalUDP/PingPong/Receiver/Receiver.cpp b/examples/LINUX/Local/LocalUDP/PingPong/Receiver/Receiver.cpp index 57773bc0fd..adf763323c 100644 --- a/examples/LINUX/Local/LocalUDP/PingPong/Receiver/Receiver.cpp +++ b/examples/LINUX/Local/LocalUDP/PingPong/Receiver/Receiver.cpp @@ -1,7 +1,7 @@ #include -// bus(selected device id) + PJONLocalUDP bus(44); uint32_t cnt = 0; diff --git a/examples/LINUX/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp b/examples/LINUX/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp index 0beae999b8..1985dcc55a 100644 --- a/examples/LINUX/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp +++ b/examples/LINUX/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp @@ -1,7 +1,7 @@ #include -// bus(selected device id) + PJONLocalUDP bus(45); uint32_t cnt = 0; diff --git a/examples/WINX86/Local/MQTTTranslate/PingPong/Receiver/Receiver.cpp b/examples/WINX86/Local/MQTTTranslate/PingPong/Receiver/Receiver.cpp index 875c44f981..c966d5eda2 100644 --- a/examples/WINX86/Local/MQTTTranslate/PingPong/Receiver/Receiver.cpp +++ b/examples/WINX86/Local/MQTTTranslate/PingPong/Receiver/Receiver.cpp @@ -8,7 +8,7 @@ // Ethernet address of the broker uint8_t broker_ip[] = { 127, 0, 0, 1 }; -// bus(selected device id) + PJONMQTTTranslate bus(44); uint32_t cnt = 0; diff --git a/examples/WINX86/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.cpp b/examples/WINX86/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.cpp index 19228464a1..5bf501a570 100644 --- a/examples/WINX86/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/MQTTTranslate/PingPong/Transmitter/Transmitter.cpp @@ -8,7 +8,7 @@ // Ethernet address of the broker uint8_t broker_ip[] = { 127, 0, 0, 1 }; -// bus(selected device id) + PJONMQTTTranslate bus(45); uint32_t cnt = 0; From 05e6e8faecf9ef6f7b8560145472783c96dab6b4 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 14 Jun 2020 01:39:33 +0200 Subject: [PATCH 089/323] documentation minor fix --- documentation/configuration.md | 6 +++--- documentation/data-reception.md | 1 + documentation/data-transmission.md | 4 ++-- documentation/routing.md | 2 +- src/strategies/README.md | 7 +++++-- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index 48d60a35b4..2aace7fc02 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -24,12 +24,12 @@ Before including the library it is possible to define the length of its buffers ``` ### Strategy configuration -The `PJON` class abstracts the [strategy](/src/strategies/README.md) using templates although since version 13.0 that complexity is hidden behind a [macro](../src/PJONSoftwareBitBang.h): +Strategies are classes that abstract the physical transmission of data. `PJON` uses [strategies](/src/strategies/README.md) as template parameters although since version 13.0 that complexity is hidden behind a [macro](../src/PJONSoftwareBitBang.h): ```cpp #include PJONSoftwareBitBang bus; ``` -In the example above the PJON object is instantiated using the [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) strategy. Strategies are classes that abstract the physical transmission of data. It is possible to instantiate more than one PJON object using different strategies in the same program: +In the example above the PJON object is instantiated using the [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) strategy. It is possible to instantiate more than one PJON object using different strategies in the same program: ```cpp #include #include @@ -48,7 +48,7 @@ The table below lists the strategies available: | [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | `#include ` | | [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | `#include ` | | [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | -| [LocalFile](/src/strategies/LocalFile) | System memory | None | `#include ` | +| [LocalFile](/src/strategies/LocalFile) | File system | None | `#include ` | | [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | | [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | `#include ` | | [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | `#include ` | diff --git a/documentation/data-reception.md b/documentation/data-reception.md index 19a8f60676..590fa77840 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -3,6 +3,7 @@ - [Addressing](/documentation/addressing.md) - [Configuration](/documentation/configuration.md) - **[Data reception](/documentation/data-reception.md)** +- [Data structures](/documentation/data-structures.md) - [Data transmission](/documentation/data-transmission.md) - [Error handling](/documentation/error-handling.md) - [IO setup](/documentation/io-setup.md) diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index 5b8d858294..6493088b0f 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -116,7 +116,7 @@ When using the `send` method, PJON operates using its internal buffer, although ``` Every time `update` is called the transmission is attempted for each packet present in the buffer. -To send data to another device connected to the bus simply call `send` passing the device id of the recipient of type `uint8_t` then the payload of type `const void *` and its length of type `uint16_t`. The return value of `send` is of type `uint16_t` and it is the id of the packet in the buffer or `PJON_FAIL` in case of error. +To send data to another device connected to the bus simply call `send` passing the device id of the recipient of type `uint8_t` then the payload of type `const void *` and its length of type `uint16_t`. The return value of `send` of type `uint16_t` is the index of the packet in the `packets` buffer or `PJON_FAIL` in case of error. ```cpp bus.send(100, "Ciao, this is a test!", 21); ``` @@ -159,7 +159,7 @@ uint16_t one_second_test = 4293014170 microseconds or 71.55 minutes */ ``` -`send_repeatedly` returns the id of the packet in the buffer as `send` does, to remove the repeated transmission simply call: +`send_repeatedly` returns the index of the packet in the `packets` buffer as `send` does, to remove the repeated transmission simply call: ```cpp bus.remove(one_second_test); ``` diff --git a/documentation/routing.md b/documentation/routing.md index 2c71861285..d9d546cc67 100644 --- a/documentation/routing.md +++ b/documentation/routing.md @@ -15,7 +15,7 @@ Transparent routing based on a tree topology that may include loops has been implemented by Fred Larsen with the [PJONSimpleSwitch](#simpleswitch), [PJONSwitch](#switch), [PJONRouter](#router), [PJONDynamicRouter](#dynamicrouter), [PJONInteractiveRouter](#interactiverouter) and [PJONVirtualBusRouter](#virtual-bus). ### SimpleSwitch -The [PJONSimpleSwitch](/examples/routing/Network/Switch/SimpleSwitch/SimpleSwitch.ino) class connects two or more buses using the same strategy. In this example a `SoftwareBitBang` <=> `SoftwareBitBang` switch is created. It can be used to amplify signals and so extend the maximum range or in more complex setups selectively switch packets as requested by its configuration. It can be used instead of `PJONSwitch` to save memory when the same strategy is used in all buses. It avoids virtual inheritance so it is faster and has a smaller footprint. +The [PJONSimpleSwitch](/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino) class connects two or more buses using the same strategy. In this example a `SoftwareBitBang` <=> `SoftwareBitBang` switch is created. It can be used to amplify signals and so extend the maximum range or in more complex setups selectively switch packets as requested by its configuration. It can be used instead of `PJONSwitch` to save memory when the same strategy is used in all buses. It avoids virtual inheritance so it is faster and has a smaller footprint. ```cpp /* __________ ________ __________ | | Pin 7 | | Pin 12 | | diff --git a/src/strategies/README.md b/src/strategies/README.md index 9717e68817..d4a22cce3d 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -12,7 +12,7 @@ The table below lists the strategies available: | [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | `#include ` | | [EthernetTCP](/src/strategies/EthernetTCP) | Ethernet/WiFi | [TCP](https://tools.ietf.org/html/rfc793) | `#include ` | | [GlobalUDP](/src/strategies/GlobalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | -| [LocalFile](/src/strategies/LocalFile) | System memory | None | `#include ` | +| [LocalFile](/src/strategies/LocalFile) | File system | None | `#include ` | | [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | | [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | `#include ` | | [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | `#include ` | @@ -47,7 +47,10 @@ Handles a collision. uint8_t get_max_attempts() ``` Returns the maximum number of attempts in case of failed transmission. - +```cpp +uint16_t get_receive_time() +``` +Returns the minimum polling time required to successfully receive a frame. ```cpp void send_frame(uint8_t *data, uint16_t length) ``` From ca39facd3cdd8c60877d0b36dac887b2a4bf94c2 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 14 Jun 2020 01:53:15 +0200 Subject: [PATCH 090/323] new keywords added --- keywords.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/keywords.txt b/keywords.txt index 4d8854da1e..118b2933ea 100644 --- a/keywords.txt +++ b/keywords.txt @@ -72,6 +72,19 @@ update KEYWORD2 # Instances (KEYWORD2) +PJONAnalogSampling +PJONAny KEYWORD2 +PJONDualUDP KEYWORD2 +PJONESPNOW KEYWORD2 +PJONEthernetTCP KEYWORD2 +PJONGlobalUDP KEYWORD2 +PJONLocalUDP KEYWORD2 +PJONMQTTTranslate KEYWORD2 +PJONOverSampling KEYWORD2 +PJONSoftwareBitBang KEYWORD2 +PJONThroughLora KEYWORD2 +PJONThroughSerial KEYWORD2 + # Constants (LITERAL1) ## PJON basic constants From 0425c7f2790f561de8f066abaaad14c3b9cd8aa8 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 14 Jun 2020 01:53:59 +0200 Subject: [PATCH 091/323] PJONLocal update, examples update --- .../PJONLocal/BlinkTest/Receiver/Receiver.ino | 7 +++---- .../PJONLocal/BlinkTest/Transmitter/Transmitter.ino | 8 +++----- .../PJONLocal/NetworkAnalysis/Receiver/Receiver.ino | 6 ++---- .../PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino | 6 ++---- .../PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino | 6 ++---- .../SendArbitraryDataType/Transmitter/Transmitter.ino | 6 ++---- src/PJONLocal.h | 1 - 7 files changed, 14 insertions(+), 26 deletions(-) diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino index 114f319efb..228184cb90 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino @@ -1,10 +1,9 @@ -// Include only SoftwareBitBang - // Set maximum packet length #define PJON_PACKET_MAX_LENGTH 10 -// Include PJONLocal -#include + +#include // Include PJONLocal +#include // Include only SoftwareBitBang PJONLocal bus(44); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Transmitter/Transmitter.ino index 4a06206d7f..71ca685500 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Transmitter/Transmitter.ino @@ -1,10 +1,8 @@ -// Include only SoftwareBitBang +#define PJON_PACKET_MAX_LENGTH 10 // Set maximum packet length -// Set maximum packet length -#define PJON_PACKET_MAX_LENGTH 10 -// Include PJONLocal -#include +#include // Include PJONLocal +#include // Include only SoftwareBitBang /* Create PJONLocal object: Class name instance name ( device id ) */ diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino index bdfd3e618d..6b4104c333 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino @@ -13,10 +13,8 @@ // Include only SoftwareBitBang - -// Include PJONLocal -#include - +#include // Include PJONLocal +#include // Include SoftwareBitBang PJONLocal bus(44); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino index 5c0c92874b..cc8c89293f 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino @@ -11,10 +11,8 @@ //#define SWBB_RESPONSE_TIMEOUT 1500 -// Include only SoftwareBitBang - -// Include PJONLocal -#include +#include // Include PJONLocal +#include // Include only SoftwareBitBang /* Create PJONLocal object: Class name instance name ( device id ) */ diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino index 2a7816742c..a5820a72c3 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino @@ -2,10 +2,8 @@ This sketch contains the receiver side. In the Serial monitor is printed the record transmitted by the other device. */ -// Include only SoftwareBitBang - -// Include PJONLocal -#include +#include // Include PJONLocal +#include // Include only SoftwareBitBang PJONLocal bus(44); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino index 8ac3496b89..5ea76e0cad 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino @@ -1,10 +1,8 @@ /* ARBITRARY DATA TYPE TRANSMISSION EXAMPLE This sketch contains the transmitter side. */ -// Include only SoftwareBitBang - -// Include PJONLocal -#include +#include // Include PJONLocal +#include // Include only SoftwareBitBang /* Create PJONLocal object: Class name instance name ( device id ) */ diff --git a/src/PJONLocal.h b/src/PJONLocal.h index e4fe86a2fc..2c1275eab1 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -67,7 +67,6 @@ limitations under the License. */ #pragma once #define PJON_LOCAL -#define PJON_INCLUDE_NONE #include "interfaces/PJON_Interfaces.h" #include "PJONDefines.h" From c1602532751dd7bda17082d5616367ea1e9cfca3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 14 Jun 2020 02:36:55 +0200 Subject: [PATCH 092/323] routing documentation update --- documentation/routing.md | 117 +++++++++++++-------------------------- 1 file changed, 39 insertions(+), 78 deletions(-) diff --git a/documentation/routing.md b/documentation/routing.md index d9d546cc67..b97b5311a3 100644 --- a/documentation/routing.md +++ b/documentation/routing.md @@ -23,9 +23,10 @@ The [PJONSimpleSwitch](/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/Sim |__________| Bus 0.0.0.1 |________| Bus 0.0.0.2 |__________| */ ``` -The first thing to do is to include the `PJONSimpleSwitch` class: +The first thing to do is to include `PJONSimpleSwitch` and the required strategy: ```cpp #include +#include ``` The `SimpleSwitch` class provides with configurable transparent packet switching between buses using the same strategy: ```cpp @@ -49,10 +50,10 @@ void loop() { router.loop(); } ``` -Then the `PJONSimpleSwitch` should work transparently. `PJONSimpleSwitch` can be used also in local mode although, because the hop count field is not included, the network topology cannot include loops. +Then the `PJONSimpleSwitch` should work transparently. `PJONSimpleSwitch` can be used also in local mode, although, because the hop count field is not included, the network topology cannot include loops. ### Switch -The [PJONSwitch](/examples/ARDUINO/Local/SoftwareBitBang/Switch/Switch) class transparently switches packets between locally attached buses also if different strategies or media are in use. It supports a default gateway to be able to act as a leaf in a larger network setup. Thanks to the `PJONSwitch` class, with few lines of code, a switch that operates multiple strategies can be created. In this example a `SoftwareBitBang` <=> `AnalogSampling` switch is created: +[PJONSwitch](/examples/routing/ARDUINO/Network/Switch/Switch) transparently switches packets between locally attached buses also if different strategies or media are in use. It supports a default gateway to be able to act as a leaf in a larger network setup. Thanks to the `PJONSwitch` class, with few lines of code, a switch that operates multiple strategies can be created. In this example a `SoftwareBitBang` <=> `AnalogSampling` switch is created: ```cpp /* Connect SoftwareBitBang bus with an AnalogSampling bus: @@ -61,51 +62,25 @@ The [PJONSwitch](/examples/ARDUINO/Local/SoftwareBitBang/Switch/Switch) class tr |DEVICE1|_______________|SWITCH| _ _ _ _ _ _ _|DEVICE2| |_______|BUS ID 0.0.0.1 |______|BUS ID 0.0.0.2|_______| */ ``` -The first thing to do is to include the `PJONSwitch` class: +First include the `PJONSwitch` class and the strategies used: ```cpp #include +#include +#include ``` -Create `StrategyLink` instances with the selected strategies: +The simplest way to use the `PJONSwitch` class is to use `PJONSwitch2` that is able to handle up to 2 buses: ```cpp -StrategyLink link1; -StrategyLink link2; +PJONSwitch2 router; ``` -Create `PJONAny` instances configuring the bus id: +Use `get_strategy_0` and `get_strategy_1` to access one of the two strategies: ```cpp -PJONAny bus1(&link1, (uint8_t[4]){0, 0, 0, 1}); -PJONAny bus2(&link2, (uint8_t[4]){0, 0, 0, 2}); +router.get_strategy_0().set_pin(12); // SoftwareBitBang pin used is 12 +router.get_strategy_1().set_pin(A0); // AnalogSampling pin used is A0 ``` -Polling time can be optionally configured: +Use `get_bus` to access one of the two instances: ```cpp -PJONAny bus1( - &link1, - (uint8_t[4]){0,0,0,1}, - PJON_NOT_ASSIGNED, // Switch device id - 1000 // Polling in microseconds -); -``` -Device id ranges can be optionally configured: -```cpp -PJONAny bus1( - &link1, - (uint8_t[4]){0,0,0,1}, - PJON_NOT_ASSIGNED, // Switch device id - 1000, // Polling in microseconds - 2, // 2 ranges present (1-127, 128-254) - 0 // Range 1 in use (1-127) -); -``` -Create the `PJONSwitch` instance passing the `PJONAny` instances: -```cpp -PJONSwitch router(2, (PJONAny*[2]){&bus1, &bus2}); -``` -Configure each strategy and the `router` instance as required: -```cpp -void setup() { - link1.strategy.set_pin(12); - link2.strategy.set_pin(A0); - router.begin(); -} +router.get_bus(0).set_bus_id((const uint8_t[4]){0, 0, 0, 1}); +router.get_bus(1).set_bus_id((const uint8_t[4]){0, 0, 0, 2}); ``` Call the `loop` function as often as possible to achieve optimal performance: ```cpp @@ -113,8 +88,11 @@ void loop() { router.loop(); } ``` + +Consider that exists also `PJONSwitch3` able to handle up to 3 buses, and `PJONSwitch` able to handle an array of buses. `PJONSwitch` can be used also in local mode, although, because the hop count field is not included, the network topology cannot include loops. + ### Router -The [PJONRouter](/examples/ARDUINO/Network/SoftwareBitBang/Router) class routes between both locally attached buses also if different strategies or media are in use, and remote buses reachable through the locally attached buses. In this example simple a router is created: +The [PJONRouter](/examples/routing/ARDUINO/Network/Router/Router) class routes between both locally attached buses also if different strategies or media are in use, and remote buses reachable through the locally attached buses. In this example simple a router is created: ```cpp ________ Bus 0.0.0.3 | | Bus 0.0.0.4 @@ -127,33 +105,20 @@ ________________| ROUTER |________________ | DEVICE 1 | | DEVICE 2 | |__________| |__________| ``` -The first thing to do is to include the `PJONRouter` class: +The first thing to do is to include the `PJONRouter` class and include the required strategy: ```cpp #include +#include ``` -Create `StrategyLink` instances with the selected strategies: +The simplest way to use the `PJONRouter` class is to use `PJONRouter2` that is able to handle up to 2 buses: ```cpp -StrategyLink link1; -StrategyLink link2; -``` -Create `PJONAny` instances configuring the bus id: -```cpp -PJONAny bus1(&link1, (uint8_t[4]){0, 0, 0, 3}); -PJONAny bus2(&link2, (uint8_t[4]){0, 0, 0, 4}); -``` -Create the `PJONRouter` instance passing the `PJONAny` instances: -```cpp -PJONRouter router(2, (PJONAny*[2]){&bus1, &bus2}); +PJONRouter2 router; ``` Configure each strategy and the `router` instance as required: ```cpp void setup() { - link1.strategy.set_pin(7); - link2.strategy.set_pin(12); - - router.add((const uint8_t[4]){0,0,0,1}, 0); - router.add((const uint8_t[4]){0,0,0,2}, 1); - + router.get_strategy_0().set_pin(7); + router.get_strategy_1().set_pin(12); router.begin(); } ``` @@ -167,8 +132,10 @@ void loop() { router.loop(); } ``` +Consider that exists also `PJONRouter3` able to handle up to 3 buses, and `PJONRouter` able to handle an array of buses. `PJONRouter` can be used also in local mode, although, because the hop count field is not included, the network topology cannot include loops. + ### DynamicRouter -The [PJONDynamicRouter](/examples/ARDUINO/Network/SoftwareBitBang/Router/DynamicRouter) is a router that also populates a routing table of remote (not directly attached) buses observing traffic. It can offer the same features provided by the `PJONRouter` class with no need of manual configuration. To do so, the `PJONDynamicRouter` class uses a routing table that is dynamically updated, for this reason uses more memory if compared with `PJONRouter`. Use the `PJON_ROUTER_TABLE_SIZE` constant to configure the number of entries that are `100` by default. +The [PJONDynamicRouter](/examples/routing/ARDUINO/Network/DynamicRouter/DynamicRouter.ino) is a router that also populates a routing table of remote (not directly attached) buses observing traffic. It can offer the same features provided by the `PJONRouter` class with no need of manual configuration. To do so, the `PJONDynamicRouter` class uses a routing table that is dynamically updated, for this reason uses more memory if compared with `PJONRouter`. Use the `PJON_ROUTER_TABLE_SIZE` constant to configure the number of entries that are `100` by default. ```cpp ________ Bus 0.0.0.3 | | Bus 0.0.0.4 @@ -181,29 +148,21 @@ ________________| ROUTER |________________ | DEVICE 1 | | DEVICE 2 | |__________| |__________| ``` -The first thing to do is to include the `PJONDynamicRouter` class: +The first thing to do is to include the `PJONDynamicRouter` class and the required strategies: ```cpp #include +#include +#include ``` -Create `StrategyLink` instances with the selected strategies: -```cpp -StrategyLink link1; -StrategyLink link2; -``` -Create `PJONAny` instances configuring the bus id: +The simplest way to use the `PJONDynamicRouter` class is to use `PJONDynamicRouter2` that is able to handle up to 2 buses: ```cpp -PJONAny bus1(&link1, (uint8_t[4]){0, 0, 0, 3}); -PJONAny bus2(&link2, (uint8_t[4]){0, 0, 0, 4}); -``` -Create the `PJONRouter` instance passing the `PJONAny` instances: -```cpp -PJONDynamicRouter router(2, (PJONAny*[2]){&bus1, &bus2}); +PJONDynamicRouter2 router; ``` Configure each strategy and the `router` instance as required: ```cpp void setup() { - link1.strategy.set_pin(7); - link2.strategy.set_pin(12); + router.get_strategy_0().set_pin(7); + router.get_strategy_1().set_pin(12); router.begin(); } ``` @@ -214,8 +173,10 @@ void loop() { } ``` +Consider that exists also `PJONDynamicRouter3` able to handle up to 3 buses, and `PJONDynamicRouter` able to handle an array of buses. `PJONDynamicRouter` can be used also in local mode, although, because the hop count field is not included, the network topology cannot include loops. + ### InteractiveRouter -[Interactive router](/examples/ARDUINO/Network/SoftwareBitBang/Switch/BlinkingSwitch) routes packets as a switch or router but it is also able to act as a device and have user-defined receive and error call-back. +[Interactive router](/examples/routing/ARDUINO/Network/Switch/BlinkingSwitch) routes packets as a switch or router but it is also able to act as a device and have user-defined receive and error call-back. ### Virtual bus -[Virtual bus](/examples/ARDUINO/Local/SoftwareBitBang/Tunneler) is a bus where multiple buses using potentially different media or strategies, connected through a router, have the same bus id (including the local bus case), and where the location of each device is automatically registered observing traffic. +[Virtual bus](/examples/routing/ARDUINO/Local/Tunneler) is a bus where multiple buses using potentially different media or strategies, connected through a router, have the same bus id (including the local bus case), and where the location of each device is automatically registered observing traffic. From ff9f5c3a5c2b53977f71f55fcb65b74072748911 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 14 Jun 2020 03:01:36 +0200 Subject: [PATCH 093/323] added missing link files --- src/PJONAnalogSampling.h | 7 +++++++ src/PJONOverSampling.h | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 src/PJONAnalogSampling.h create mode 100644 src/PJONOverSampling.h diff --git a/src/PJONAnalogSampling.h b/src/PJONAnalogSampling.h new file mode 100644 index 0000000000..15353a73ba --- /dev/null +++ b/src/PJONAnalogSampling.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/AnalogSampling/AnalogSampling.h" + +#define PJONAnalogSampling PJON diff --git a/src/PJONOverSampling.h b/src/PJONOverSampling.h new file mode 100644 index 0000000000..d4fd7e8d87 --- /dev/null +++ b/src/PJONOverSampling.h @@ -0,0 +1,7 @@ + +#pragma once + +#include "PJON.h" +#include "strategies/OverSampling/OverSampling.h" + +#define PJONOverSampling PJON From 1df2bbe83f460718291408c81e0676fbfa7a7f46 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 14 Jun 2020 03:40:10 +0200 Subject: [PATCH 094/323] documentation minor fix --- documentation/routing.md | 10 +++++----- src/strategies/README.md | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/documentation/routing.md b/documentation/routing.md index b97b5311a3..3f82ede426 100644 --- a/documentation/routing.md +++ b/documentation/routing.md @@ -26,7 +26,7 @@ The [PJONSimpleSwitch](/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/Sim The first thing to do is to include `PJONSimpleSwitch` and the required strategy: ```cpp #include -#include +#include ``` The `SimpleSwitch` class provides with configurable transparent packet switching between buses using the same strategy: ```cpp @@ -65,8 +65,8 @@ Then the `PJONSimpleSwitch` should work transparently. `PJONSimpleSwitch` can be First include the `PJONSwitch` class and the strategies used: ```cpp #include -#include -#include +#include +#include ``` The simplest way to use the `PJONSwitch` class is to use `PJONSwitch2` that is able to handle up to 2 buses: ```cpp @@ -151,8 +151,8 @@ ________________| ROUTER |________________ The first thing to do is to include the `PJONDynamicRouter` class and the required strategies: ```cpp #include -#include -#include +#include +#include ``` The simplest way to use the `PJONDynamicRouter` class is to use `PJONDynamicRouter2` that is able to handle up to 2 buses: ```cpp diff --git a/src/strategies/README.md b/src/strategies/README.md index d4a22cce3d..5019f9fb76 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -90,6 +90,7 @@ class YourStrategyName { bool begin(uint8_t did) { }; bool can_start() { }; uint8_t get_max_attempts() { }; + uint16_t get_receive_time() { }; uint16_t receive_frame(uint8_t *data, uint16_t max_length) { }; uint16_t receive_response() { }; void send_response(uint8_t response) { }; From 7e9a04a6c3d5371dc9b263aaf5fba29cba1da9db Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 14 Jun 2020 17:57:15 +0200 Subject: [PATCH 095/323] documentation/routing.md minor fix --- documentation/routing.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/documentation/routing.md b/documentation/routing.md index 3f82ede426..af4e96df04 100644 --- a/documentation/routing.md +++ b/documentation/routing.md @@ -89,10 +89,10 @@ void loop() { } ``` -Consider that exists also `PJONSwitch3` able to handle up to 3 buses, and `PJONSwitch` able to handle an array of buses. `PJONSwitch` can be used also in local mode, although, because the hop count field is not included, the network topology cannot include loops. +Consider that there is also `PJONSwitch3` able to handle up to 3 buses, and `PJONSwitch` able to handle an array of buses. `PJONSwitch` can be used also in local mode, although, because the hop count field is not included, the network topology cannot include loops. ### Router -The [PJONRouter](/examples/routing/ARDUINO/Network/Router/Router) class routes between both locally attached buses also if different strategies or media are in use, and remote buses reachable through the locally attached buses. In this example simple a router is created: +The [PJONRouter](/examples/routing/ARDUINO/Network/Router/Router) class routes between both locally attached buses also if different strategies or media are in use, and remote buses reachable through the locally attached buses using a static routing table. In this example simple a router is created: ```cpp ________ Bus 0.0.0.3 | | Bus 0.0.0.4 @@ -132,7 +132,7 @@ void loop() { router.loop(); } ``` -Consider that exists also `PJONRouter3` able to handle up to 3 buses, and `PJONRouter` able to handle an array of buses. `PJONRouter` can be used also in local mode, although, because the hop count field is not included, the network topology cannot include loops. +Consider that there is also `PJONRouter3` able to handle up to 3 buses, and `PJONRouter` able to handle an array of buses. `PJONRouter` can be used also in local mode, although, because the hop count field is not included, the network topology cannot include loops. ### DynamicRouter The [PJONDynamicRouter](/examples/routing/ARDUINO/Network/DynamicRouter/DynamicRouter.ino) is a router that also populates a routing table of remote (not directly attached) buses observing traffic. It can offer the same features provided by the `PJONRouter` class with no need of manual configuration. To do so, the `PJONDynamicRouter` class uses a routing table that is dynamically updated, for this reason uses more memory if compared with `PJONRouter`. Use the `PJON_ROUTER_TABLE_SIZE` constant to configure the number of entries that are `100` by default. @@ -173,10 +173,17 @@ void loop() { } ``` -Consider that exists also `PJONDynamicRouter3` able to handle up to 3 buses, and `PJONDynamicRouter` able to handle an array of buses. `PJONDynamicRouter` can be used also in local mode, although, because the hop count field is not included, the network topology cannot include loops. +Consider that there is also `PJONDynamicRouter3` able to handle up to 3 buses, and `PJONDynamicRouter` able to handle an array of buses. `PJONDynamicRouter` can be used also in local mode, although, because the hop count field is not included, the network topology cannot include loops. ### InteractiveRouter [Interactive router](/examples/routing/ARDUINO/Network/Switch/BlinkingSwitch) routes packets as a switch or router but it is also able to act as a device and have user-defined receive and error call-back. +This class implements functionality that can be added to any of the routing classes except PJONSimpleSwitch. Adding the functionality to PJONDynamicRouter can be done as: +```cpp +PJONInteractiveRouter> router; +``` + ### Virtual bus [Virtual bus](/examples/routing/ARDUINO/Local/Tunneler) is a bus where multiple buses using potentially different media or strategies, connected through a router, have the same bus id (including the local bus case), and where the location of each device is automatically registered observing traffic. + +This class makes it easy to create a bus that consists of multiple physical buses using one or more strategies. It can for example connect several clusters of SWBB local buses together through another strategy like DualUDP, to form one larger local bus. also including DualUDP devices. From 275209b9861f24931b674cd62a7f6bb3bf055f3c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 15 Jun 2020 18:18:11 +0200 Subject: [PATCH 096/323] routing documentation minor fix --- documentation/routing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/routing.md b/documentation/routing.md index af4e96df04..e4dd28fc31 100644 --- a/documentation/routing.md +++ b/documentation/routing.md @@ -184,6 +184,6 @@ PJONInteractiveRouter> route ``` ### Virtual bus -[Virtual bus](/examples/routing/ARDUINO/Local/Tunneler) is a bus where multiple buses using potentially different media or strategies, connected through a router, have the same bus id (including the local bus case), and where the location of each device is automatically registered observing traffic. +[Virtual bus](/examples/routing/ARDUINO/Local/Tunneler) is a bus where multiple buses using potentially different media or strategies, connected through a router, have the same bus id (including the local bus case), and where the location of each device is automatically registered observing traffic. Just like `PJONInteractiveRouter`, this class implements functionality that can be added to any of the routing classes except `PJONSimpleSwitch`. It can also be combined with the functionality added by `PJONInteractiveRouter`. This class makes it easy to create a bus that consists of multiple physical buses using one or more strategies. It can for example connect several clusters of SWBB local buses together through another strategy like DualUDP, to form one larger local bus. also including DualUDP devices. From 9b03415b5e9ff8fa5fd0e44fc75b8b6ef46c3627 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Jun 2020 23:39:53 +0200 Subject: [PATCH 097/323] added reply and reply_blocking to documentation (https://github.com/gioblu/PJON/issues/355) --- documentation/data-transmission.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index 6493088b0f..f3c99156ce 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -186,3 +186,25 @@ info.rx.port = 8000; // The packet includes the port 8000 memcpy(info.rx.bus_id, bus_id, 4); // Copy recipient's bus id in info bus.send_repeatedly(info, "Ciao!", 5, 1000000); // Send "Ciao!" every second ``` + +### `reply` +The `reply` method can be called within the [receiver function](/data-reception.md#data-reception) to reply to a packet received previously: +```cpp +bus.reply("All fine!", 9); +``` +Consider that `reply` dispatches a packet in the buffer like `send` or `send_repeatedly`. To use the return value of `send` just save it in a variable of type `uint16_t`: +```cpp +uint16_t packet = bus.reply("Ciao, this is a test!", 21); +if(packet == PJON_FAIL) Serial.print("Something went wrong"); +``` + +### `reply_blocking` +The `reply_blocking` method can be called within the [receiver function](/data-reception.md#data-reception) to reply to a packet received previously: +```cpp +bus.reply_blocking("All fine!", 9); +``` +Consider that `reply_blocking` is a blocking procedure that in case of failure can last a considerable amount of time. The `reply_blocking` result, of type `uint16_t`, can be used to determine if the transmission occurred successfully or not: +```cpp +uint16_t result = bus.reply_blocking("All is ok!", 11); +if(result == PJON_ACK) Serial.println("Responded successfully!"); +``` From 7b50acb6528c71c4075c9d1c898462d44f81f90d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Jun 2020 23:55:53 +0200 Subject: [PATCH 098/323] documentation/data-transmission added remark abouts accepted data types --- documentation/data-transmission.md | 75 ++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index f3c99156ce..5ef8ace021 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -14,7 +14,7 @@ ## Data transmission ### `begin` -The begin method must be called before starting communication, the lack of this call can lead to collisions after boot, so be sure not to forget it. +The `begin` method must be called before starting communication, the lack of this call can lead to collisions so be sure not to forget it: ```cpp bus.begin(); ``` @@ -25,6 +25,18 @@ The simplest way to send data is to use `send_packet`, this method composes the // Send to device id 10 the string "Hi!" bus.send_packet(10, "Hi!", 3); ``` +The `send_packet` method accepts any kind of data, in the example below a custom `struct` is sent to device id 1: +```cpp +// Define a custom data type +struct voltage_record { uint16_t v1; uint16_t v2; }; +// Fill it with information +voltage_record record; +record.v1 = analogRead(A1); +record.v2 = analogRead(A2); +// Send to device id 1 the record struct +bus.send_packet(1, record, sizeof(record)); +``` + The payload length is boring to be added in each call but is there to prevent buffer overflow. If sending arbitrary values `NULL` terminator strategy based on `strlen` is not safe to detect the end of a string. The `send` method can receive other 3 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id and including the port `8002`. ```cpp // All optional parameters available @@ -85,6 +97,17 @@ bus.send_packet_blocking( 1000000 // Timeout (uint32_t) - 1 second ); ``` +The `send_packet_blocking` method accepts any type of data, in the example below a custom `struct` is sent to device id 1: +```cpp +// Define a custom data type +struct voltage_record { uint16_t v1; uint16_t v2; }; +// Fill it with information +voltage_record record; +record.v1 = analogRead(A1); +record.v2 = analogRead(A2); +// Send to device id 1 the record struct +bus.send_packet_blocking(1, record, sizeof(record)); +``` `send_packet_blocking` returns the following values: - `PJON_ACK` (6) if transmission occurred and acknowledgement is received if requested @@ -132,6 +155,19 @@ bus.send( 8002 // (uint16_t) Port identification ); ``` + +The `send` method accepts any type of data, in the example below a custom `struct` is sent to device id 1: +```cpp +// Define a custom data type +struct voltage_record { uint16_t v1; uint16_t v2; }; +// Fill it with information +voltage_record record; +record.v1 = analogRead(A1); +record.v2 = analogRead(A2); +// Send to device id 1 the record struct +bus.send(1, record, sizeof(record)); +``` + To use the return value of `send` just save it in a variable of type `uint16_t`: ```cpp uint16_t packet = bus.send(100, "Ciao, this is a test!", 21); @@ -176,6 +212,17 @@ bus.send_repeatedly( 8002 // (uint16_t) Port identification ); ``` +The `send_repeatedly` method accepts any type of data, in the example below a custom `struct` is sent to device id 1: +```cpp +// Define a custom data type +struct voltage_record { uint16_t v1; uint16_t v2; }; +// Fill it with information +voltage_record record; +record.v1 = analogRead(A1); +record.v2 = analogRead(A2); +// Send to device id 1 the record struct +bus.send_repeatedly(1, record, sizeof(record)); +``` If you need to transmit in shared mode or configure other protocol fields you can use `send_repeatedly` passing a struct of type [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info), the payload of type `const void *`, the length of type `uint16_t` and the interval of type `uint32_t`: ```cpp @@ -188,7 +235,7 @@ bus.send_repeatedly(info, "Ciao!", 5, 1000000); // Send "Ciao!" every second ``` ### `reply` -The `reply` method can be called within the [receiver function](/data-reception.md#data-reception) to reply to a packet received previously: +The `reply` method can be called within the [receiver function](/documentation/data-reception.md#data-reception) to reply to a packet received previously: ```cpp bus.reply("All fine!", 9); ``` @@ -197,9 +244,20 @@ Consider that `reply` dispatches a packet in the buffer like `send` or `send_rep uint16_t packet = bus.reply("Ciao, this is a test!", 21); if(packet == PJON_FAIL) Serial.print("Something went wrong"); ``` +The `reply` method accepts any type of data, in the example below a custom struct is sent to device id 1: +```cpp +// Define a custom data type +struct voltage_record { uint16_t v1; uint16_t v2; }; +// Fill it with information +voltage_record record; +record.v1 = analogRead(A1); +record.v2 = analogRead(A2); +// Reply with the record struct +bus.reply(record, sizeof(record)); +``` ### `reply_blocking` -The `reply_blocking` method can be called within the [receiver function](/data-reception.md#data-reception) to reply to a packet received previously: +The `reply_blocking` method can be called within the [receiver function](/documentation/data-reception.md#data-reception) to reply to a packet received previously: ```cpp bus.reply_blocking("All fine!", 9); ``` @@ -208,3 +266,14 @@ Consider that `reply_blocking` is a blocking procedure that in case of failure c uint16_t result = bus.reply_blocking("All is ok!", 11); if(result == PJON_ACK) Serial.println("Responded successfully!"); ``` +The `reply_blocking` method accepts any type of data, in the example below a custom `struct` is sent to device id 1: +```cpp +// Define a custom data type +struct voltage_record { uint16_t v1; uint16_t v2; }; +// Fill it with information +voltage_record record; +record.v1 = analogRead(A1); +record.v2 = analogRead(A2); +// Reply with the record struct +bus.reply_blocking(record, sizeof(record)); +``` From 1306644ba08c6048bac3636eb26783afa7f79a05 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Jun 2020 23:58:57 +0200 Subject: [PATCH 099/323] documentation minor fix --- documentation/data-transmission.md | 34 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index 5ef8ace021..4924aa0b91 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -25,18 +25,6 @@ The simplest way to send data is to use `send_packet`, this method composes the // Send to device id 10 the string "Hi!" bus.send_packet(10, "Hi!", 3); ``` -The `send_packet` method accepts any kind of data, in the example below a custom `struct` is sent to device id 1: -```cpp -// Define a custom data type -struct voltage_record { uint16_t v1; uint16_t v2; }; -// Fill it with information -voltage_record record; -record.v1 = analogRead(A1); -record.v2 = analogRead(A2); -// Send to device id 1 the record struct -bus.send_packet(1, record, sizeof(record)); -``` - The payload length is boring to be added in each call but is there to prevent buffer overflow. If sending arbitrary values `NULL` terminator strategy based on `strlen` is not safe to detect the end of a string. The `send` method can receive other 3 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id and including the port `8002`. ```cpp // All optional parameters available @@ -50,6 +38,18 @@ bus.send_packet( ); ``` +The `send_packet` method accepts any kind of data, in the example below a custom `struct` is sent to device id 1: +```cpp +// Define a custom data type +struct voltage_record { uint16_t v1; uint16_t v2; }; +// Fill it with information +voltage_record record; +record.v1 = analogRead(A1); +record.v2 = analogRead(A2); +// Send to device id 1 the record struct +bus.send_packet(1, &record, sizeof(record)); +``` + `send_packet` returns the following values: - `PJON_ACK` (6) if transmission occurred and acknowledgement is received if requested - `PJON_BUSY` (666) if bus is busy @@ -106,7 +106,7 @@ voltage_record record; record.v1 = analogRead(A1); record.v2 = analogRead(A2); // Send to device id 1 the record struct -bus.send_packet_blocking(1, record, sizeof(record)); +bus.send_packet_blocking(1, &record, sizeof(record)); ``` `send_packet_blocking` returns the following values: @@ -165,7 +165,7 @@ voltage_record record; record.v1 = analogRead(A1); record.v2 = analogRead(A2); // Send to device id 1 the record struct -bus.send(1, record, sizeof(record)); +bus.send(1, &record, sizeof(record)); ``` To use the return value of `send` just save it in a variable of type `uint16_t`: @@ -221,7 +221,7 @@ voltage_record record; record.v1 = analogRead(A1); record.v2 = analogRead(A2); // Send to device id 1 the record struct -bus.send_repeatedly(1, record, sizeof(record)); +bus.send_repeatedly(1, &record, sizeof(record)); ``` If you need to transmit in shared mode or configure other protocol fields you can use `send_repeatedly` passing a struct of type [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info), the payload of type `const void *`, the length of type `uint16_t` and the interval of type `uint32_t`: @@ -253,7 +253,7 @@ voltage_record record; record.v1 = analogRead(A1); record.v2 = analogRead(A2); // Reply with the record struct -bus.reply(record, sizeof(record)); +bus.reply(&record, sizeof(record)); ``` ### `reply_blocking` @@ -275,5 +275,5 @@ voltage_record record; record.v1 = analogRead(A1); record.v2 = analogRead(A2); // Reply with the record struct -bus.reply_blocking(record, sizeof(record)); +bus.reply_blocking(&record, sizeof(record)); ``` From 47d0a8840f60f0b674b809b8a1b85f3220c991e7 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Jun 2020 00:55:21 +0200 Subject: [PATCH 100/323] documentation index update --- documentation/README.md | 11 +++++++++-- documentation/addressing.md | 10 +++++++++- documentation/configuration.md | 11 +++++++++-- documentation/data-reception.md | 11 +++++++++-- documentation/data-structures.md | 11 +++++++++-- documentation/data-transmission.md | 11 +++++++++-- documentation/error-handling.md | 11 +++++++++-- documentation/io-setup.md | 11 +++++++++-- documentation/routing.md | 10 +++++++++- 9 files changed, 81 insertions(+), 16 deletions(-) diff --git a/documentation/README.md b/documentation/README.md index 9500760baf..b2b33ff587 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -1,14 +1,21 @@ ### Documentation index - [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) -- [IO setup](/documentation/io-setup.md) + - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) +- [IO setup](/documentation/io-setup.md) + - [`strategy`](/documentation/io-setup.md#io-setup) --- ## Documentation diff --git a/documentation/addressing.md b/documentation/addressing.md index b64b9829ee..27fb676205 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -1,13 +1,21 @@ ### Documentation index - **[Addressing](/documentation/addressing.md)** + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) -- [IO setup](/documentation/io-setup.md) + - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) +- [IO setup](/documentation/io-setup.md) + - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/configuration.md b/documentation/configuration.md index 2aace7fc02..da0fd3e560 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -1,14 +1,21 @@ ### Documentation index - [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - **[Configuration](/documentation/configuration.md)** + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) -- [IO setup](/documentation/io-setup.md) + - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) +- [IO setup](/documentation/io-setup.md) + - [`strategy`](/documentation/io-setup.md#io-setup) --- ## Configuration diff --git a/documentation/data-reception.md b/documentation/data-reception.md index 590fa77840..f9397c602b 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -1,14 +1,21 @@ ### Documentation index - [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - **[Data reception](/documentation/data-reception.md)** + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) -- [IO setup](/documentation/io-setup.md) + - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) +- [IO setup](/documentation/io-setup.md) + - [`strategy`](/documentation/io-setup.md#io-setup) --- ## Data reception diff --git a/documentation/data-structures.md b/documentation/data-structures.md index d1c228a97c..e0bb80adf5 100644 --- a/documentation/data-structures.md +++ b/documentation/data-structures.md @@ -1,14 +1,21 @@ ### Documentation index - [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - **[Data structures](/documentation/data-structures.md)** + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) -- [IO setup](/documentation/io-setup.md) + - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) +- [IO setup](/documentation/io-setup.md) + - [`strategy`](/documentation/io-setup.md#io-setup) --- ## Data structures diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index 4924aa0b91..b0b38be9ca 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -1,14 +1,21 @@ ### Documentation index - [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - **[Data transmission](/documentation/data-transmission.md)** + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) -- [IO setup](/documentation/io-setup.md) + - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) +- [IO setup](/documentation/io-setup.md) + - [`strategy`](/documentation/io-setup.md#io-setup) --- ## Data transmission diff --git a/documentation/error-handling.md b/documentation/error-handling.md index a27ef7aca9..72ec6bec4d 100644 --- a/documentation/error-handling.md +++ b/documentation/error-handling.md @@ -1,14 +1,21 @@ ### Documentation index - [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - **[Error handling](/documentation/error-handling.md)** -- [IO setup](/documentation/io-setup.md) + - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) +- [IO setup](/documentation/io-setup.md) + - [`strategy`](/documentation/io-setup.md#io-setup) --- ## Error handling diff --git a/documentation/io-setup.md b/documentation/io-setup.md index 6abaf600b3..38df4fbeb8 100644 --- a/documentation/io-setup.md +++ b/documentation/io-setup.md @@ -1,14 +1,21 @@ ### Documentation index - [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) -- **[IO setup](/documentation/io-setup.md)** + - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) +- **[IO setup](/documentation/io-setup.md)** + - [`strategy`](/documentation/io-setup.md#io-setup) --- ## IO setup diff --git a/documentation/routing.md b/documentation/routing.md index e4dd28fc31..0fc40e2f49 100644 --- a/documentation/routing.md +++ b/documentation/routing.md @@ -1,13 +1,21 @@ ### Documentation index - [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) -- [IO setup](/documentation/io-setup.md) + - [`set_error`](/documentation/error-handling.md#error-handling) - **[Routing](/documentation/routing.md)** + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) +- [IO setup](/documentation/io-setup.md) + - [`strategy`](/documentation/io-setup.md#io-setup) --- From 014f39393edeaac467f1c152c5f67ee77c9bef6e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Jun 2020 01:33:17 +0200 Subject: [PATCH 101/323] documentation index minor fix --- documentation/README.md | 40 +++++++++++++++++++++++----- documentation/addressing.md | 38 ++++++++++++++++++++++----- documentation/configuration.md | 40 +++++++++++++++++++++++----- documentation/data-reception.md | 40 +++++++++++++++++++++++----- documentation/data-structures.md | 40 +++++++++++++++++++++++----- documentation/data-transmission.md | 40 +++++++++++++++++++++++----- documentation/error-handling.md | 40 +++++++++++++++++++++++----- documentation/io-setup.md | 42 ++++++++++++++++++++++++------ documentation/routing.md | 34 +++++++++++++++++++----- 9 files changed, 292 insertions(+), 62 deletions(-) diff --git a/documentation/README.md b/documentation/README.md index b2b33ff587..69c5c332a8 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -1,19 +1,45 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`device_id`](/documentation/addressing.md#local-mode) + - [`get_bus_id`](/documentation/addressing.md#shared-mode) + - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) + - [`set_bus_id`](/documentation/addressing.md#shared-mode) + - [`set_id`](/documentation/addressing.md#local-mode) + - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_port`](/documentation/configuration.md#network-service-identification) + - [`include_sender_info`](/documentation/configuration.md#sender-information) + - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) + - [`set_crc_32`](/documentation/configuration.md#crc-configuration) + - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) + - [`set_packet_id`](/documentation/configuration.md#packet-identification) + - [`set_router`](/documentation/configuration.md#router-mode) + - [`set_shared_network`](/documentation/configuration.md#network-mode) - [Data reception](/documentation/data-reception.md) - - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) + - [`receive`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) + - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) + - [`reply`](/documentation/data-transmission.md#reply) + - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) + - [`send`](/documentation/data-transmission.md#send) + - [`send_packet`](/documentation/data-transmission.md#send_packet) + - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) + - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) + - [`PJONSwitch`](/documentation/routing.md#switch) + - [`PJONRouter`](/documentation/routing.md#router) + - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) + - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/addressing.md b/documentation/addressing.md index 27fb676205..1f832d3281 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -1,19 +1,45 @@ ### Documentation index - **[Addressing](/documentation/addressing.md)** - - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) + - [`device_id`](/documentation/addressing.md#local-mode) + - [`get_bus_id`](/documentation/addressing.md#shared-mode) + - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) + - [`set_bus_id`](/documentation/addressing.md#shared-mode) + - [`set_id`](/documentation/addressing.md#local-mode) + - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_port`](/documentation/configuration.md#network-service-identification) + - [`include_sender_info`](/documentation/configuration.md#sender-information) + - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) + - [`set_crc_32`](/documentation/configuration.md#crc-configuration) + - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) + - [`set_packet_id`](/documentation/configuration.md#packet-identification) + - [`set_router`](/documentation/configuration.md#router-mode) + - [`set_shared_network`](/documentation/configuration.md#network-mode) - [Data reception](/documentation/data-reception.md) - - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) + - [`receive`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) + - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) + - [`reply`](/documentation/data-transmission.md#reply) + - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) + - [`send`](/documentation/data-transmission.md#send) + - [`send_packet`](/documentation/data-transmission.md#send_packet) + - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) + - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) + - [`PJONSwitch`](/documentation/routing.md#switch) + - [`PJONRouter`](/documentation/routing.md#router) + - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) + - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) diff --git a/documentation/configuration.md b/documentation/configuration.md index da0fd3e560..99d01b628f 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -1,19 +1,45 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`device_id`](/documentation/addressing.md#local-mode) + - [`get_bus_id`](/documentation/addressing.md#shared-mode) + - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) + - [`set_bus_id`](/documentation/addressing.md#shared-mode) + - [`set_id`](/documentation/addressing.md#local-mode) + - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - **[Configuration](/documentation/configuration.md)** - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_port`](/documentation/configuration.md#network-service-identification) + - [`include_sender_info`](/documentation/configuration.md#sender-information) + - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) + - [`set_crc_32`](/documentation/configuration.md#crc-configuration) + - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) + - [`set_packet_id`](/documentation/configuration.md#packet-identification) + - [`set_router`](/documentation/configuration.md#router-mode) + - [`set_shared_network`](/documentation/configuration.md#network-mode) - [Data reception](/documentation/data-reception.md) - - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) + - [`receive`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) + - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) + - [`reply`](/documentation/data-transmission.md#reply) + - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) + - [`send`](/documentation/data-transmission.md#send) + - [`send_packet`](/documentation/data-transmission.md#send_packet) + - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) + - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) + - [`PJONSwitch`](/documentation/routing.md#switch) + - [`PJONRouter`](/documentation/routing.md#router) + - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) + - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/data-reception.md b/documentation/data-reception.md index f9397c602b..1636eb62d1 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -1,19 +1,45 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`device_id`](/documentation/addressing.md#local-mode) + - [`get_bus_id`](/documentation/addressing.md#shared-mode) + - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) + - [`set_bus_id`](/documentation/addressing.md#shared-mode) + - [`set_id`](/documentation/addressing.md#local-mode) + - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_port`](/documentation/configuration.md#network-service-identification) + - [`include_sender_info`](/documentation/configuration.md#sender-information) + - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) + - [`set_crc_32`](/documentation/configuration.md#crc-configuration) + - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) + - [`set_packet_id`](/documentation/configuration.md#packet-identification) + - [`set_router`](/documentation/configuration.md#router-mode) + - [`set_shared_network`](/documentation/configuration.md#network-mode) - **[Data reception](/documentation/data-reception.md)** - - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) + - [`receive`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) + - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) + - [`reply`](/documentation/data-transmission.md#reply) + - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) + - [`send`](/documentation/data-transmission.md#send) + - [`send_packet`](/documentation/data-transmission.md#send_packet) + - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) + - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) + - [`PJONSwitch`](/documentation/routing.md#switch) + - [`PJONRouter`](/documentation/routing.md#router) + - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) + - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/data-structures.md b/documentation/data-structures.md index e0bb80adf5..1927259732 100644 --- a/documentation/data-structures.md +++ b/documentation/data-structures.md @@ -1,19 +1,45 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`device_id`](/documentation/addressing.md#local-mode) + - [`get_bus_id`](/documentation/addressing.md#shared-mode) + - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) + - [`set_bus_id`](/documentation/addressing.md#shared-mode) + - [`set_id`](/documentation/addressing.md#local-mode) + - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_port`](/documentation/configuration.md#network-service-identification) + - [`include_sender_info`](/documentation/configuration.md#sender-information) + - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) + - [`set_crc_32`](/documentation/configuration.md#crc-configuration) + - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) + - [`set_packet_id`](/documentation/configuration.md#packet-identification) + - [`set_router`](/documentation/configuration.md#router-mode) + - [`set_shared_network`](/documentation/configuration.md#network-mode) - [Data reception](/documentation/data-reception.md) - - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) + - [`receive`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) - **[Data structures](/documentation/data-structures.md)** - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) + - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) + - [`reply`](/documentation/data-transmission.md#reply) + - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) + - [`send`](/documentation/data-transmission.md#send) + - [`send_packet`](/documentation/data-transmission.md#send_packet) + - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) + - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) + - [`PJONSwitch`](/documentation/routing.md#switch) + - [`PJONRouter`](/documentation/routing.md#router) + - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) + - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index b0b38be9ca..b23821cf6a 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -1,19 +1,45 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`device_id`](/documentation/addressing.md#local-mode) + - [`get_bus_id`](/documentation/addressing.md#shared-mode) + - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) + - [`set_bus_id`](/documentation/addressing.md#shared-mode) + - [`set_id`](/documentation/addressing.md#local-mode) + - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_port`](/documentation/configuration.md#network-service-identification) + - [`include_sender_info`](/documentation/configuration.md#sender-information) + - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) + - [`set_crc_32`](/documentation/configuration.md#crc-configuration) + - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) + - [`set_packet_id`](/documentation/configuration.md#packet-identification) + - [`set_router`](/documentation/configuration.md#router-mode) + - [`set_shared_network`](/documentation/configuration.md#network-mode) - [Data reception](/documentation/data-reception.md) - - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) + - [`receive`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) + - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - **[Data transmission](/documentation/data-transmission.md)** - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) + - [`reply`](/documentation/data-transmission.md#reply) + - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) + - [`send`](/documentation/data-transmission.md#send) + - [`send_packet`](/documentation/data-transmission.md#send_packet) + - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) + - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) + - [`PJONSwitch`](/documentation/routing.md#switch) + - [`PJONRouter`](/documentation/routing.md#router) + - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) + - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/error-handling.md b/documentation/error-handling.md index 72ec6bec4d..5008c887ef 100644 --- a/documentation/error-handling.md +++ b/documentation/error-handling.md @@ -1,19 +1,45 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`device_id`](/documentation/addressing.md#local-mode) + - [`get_bus_id`](/documentation/addressing.md#shared-mode) + - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) + - [`set_bus_id`](/documentation/addressing.md#shared-mode) + - [`set_id`](/documentation/addressing.md#local-mode) + - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_port`](/documentation/configuration.md#network-service-identification) + - [`include_sender_info`](/documentation/configuration.md#sender-information) + - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) + - [`set_crc_32`](/documentation/configuration.md#crc-configuration) + - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) + - [`set_packet_id`](/documentation/configuration.md#packet-identification) + - [`set_router`](/documentation/configuration.md#router-mode) + - [`set_shared_network`](/documentation/configuration.md#network-mode) - [Data reception](/documentation/data-reception.md) - - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) + - [`receive`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) + - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) + - [`reply`](/documentation/data-transmission.md#reply) + - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) + - [`send`](/documentation/data-transmission.md#send) + - [`send_packet`](/documentation/data-transmission.md#send_packet) + - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) + - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - **[Error handling](/documentation/error-handling.md)** - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) + - [`PJONSwitch`](/documentation/routing.md#switch) + - [`PJONRouter`](/documentation/routing.md#router) + - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) + - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/io-setup.md b/documentation/io-setup.md index 38df4fbeb8..0158585cb7 100644 --- a/documentation/io-setup.md +++ b/documentation/io-setup.md @@ -1,19 +1,45 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`device_id`](/documentation/addressing.md#local-mode) + - [`get_bus_id`](/documentation/addressing.md#shared-mode) + - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) + - [`set_bus_id`](/documentation/addressing.md#shared-mode) + - [`set_id`](/documentation/addressing.md#local-mode) + - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) -- [Data reception](/documentation/data-reception.md) - - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) + - [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_port`](/documentation/configuration.md#network-service-identification) + - [`include_sender_info`](/documentation/configuration.md#sender-information) + - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) + - [`set_crc_32`](/documentation/configuration.md#crc-configuration) + - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) + - [`set_packet_id`](/documentation/configuration.md#packet-identification) + - [`set_router`](/documentation/configuration.md#router-mode) + - [`set_shared_network`](/documentation/configuration.md#network-mode) +- [Data reception](/documentation/data-reception.md) + - [`receive`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) + - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) + - [`reply`](/documentation/data-transmission.md#reply) + - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) + - [`send`](/documentation/data-transmission.md#send) + - [`send_packet`](/documentation/data-transmission.md#send_packet) + - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) + - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) + - [`PJONSwitch`](/documentation/routing.md#switch) + - [`PJONRouter`](/documentation/routing.md#router) + - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) + - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - **[IO setup](/documentation/io-setup.md)** - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/routing.md b/documentation/routing.md index 0fc40e2f49..b2e01c24ef 100644 --- a/documentation/routing.md +++ b/documentation/routing.md @@ -1,15 +1,37 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`device_id`](/documentation/addressing.md#local-mode) + - [`get_bus_id`](/documentation/addressing.md#shared-mode) + - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) + - [`set_bus_id`](/documentation/addressing.md#shared-mode) + - [`set_id`](/documentation/addressing.md#local-mode) + - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_mac`](/documentation/configuration.md#hardware-identification) + - [`include_port`](/documentation/configuration.md#network-service-identification) + - [`include_sender_info`](/documentation/configuration.md#sender-information) + - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) + - [`set_crc_32`](/documentation/configuration.md#crc-configuration) + - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) + - [`set_packet_id`](/documentation/configuration.md#packet-identification) + - [`set_router`](/documentation/configuration.md#router-mode) + - [`set_shared_network`](/documentation/configuration.md#network-mode) - [Data reception](/documentation/data-reception.md) - - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) + - [`receive`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) + - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) + - [`reply`](/documentation/data-transmission.md#reply) + - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) + - [`send`](/documentation/data-transmission.md#send) + - [`send_packet`](/documentation/data-transmission.md#send_packet) + - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) + - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - **[Routing](/documentation/routing.md)** From 4358b608be1335ce21d9b76296f6aebd20865140 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Jun 2020 01:38:38 +0200 Subject: [PATCH 102/323] documentation index minor fix --- documentation/README.md | 40 +++++----------------------- documentation/addressing.md | 38 +++++---------------------- documentation/configuration.md | 40 +++++----------------------- documentation/data-reception.md | 40 +++++----------------------- documentation/data-structures.md | 40 +++++----------------------- documentation/data-transmission.md | 40 +++++----------------------- documentation/error-handling.md | 40 +++++----------------------- documentation/io-setup.md | 42 ++++++------------------------ documentation/routing.md | 34 +++++------------------- 9 files changed, 62 insertions(+), 292 deletions(-) diff --git a/documentation/README.md b/documentation/README.md index 69c5c332a8..b2b33ff587 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -1,45 +1,19 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`device_id`](/documentation/addressing.md#local-mode) - - [`get_bus_id`](/documentation/addressing.md#shared-mode) - - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - - [`set_bus_id`](/documentation/addressing.md#shared-mode) - - [`set_id`](/documentation/addressing.md#local-mode) - - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`include_mac`](/documentation/configuration.md#hardware-identification) - - [`include_port`](/documentation/configuration.md#network-service-identification) - - [`include_sender_info`](/documentation/configuration.md#sender-information) - - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) - - [`set_crc_32`](/documentation/configuration.md#crc-configuration) - - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) - - [`set_packet_id`](/documentation/configuration.md#packet-identification) - - [`set_router`](/documentation/configuration.md#router-mode) - - [`set_shared_network`](/documentation/configuration.md#network-mode) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) - - [`receive`](/documentation/data-reception.md#data-reception) - - [`set_receiver`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) - - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) - - [`reply`](/documentation/data-transmission.md#reply) - - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) - - [`send`](/documentation/data-transmission.md#send) - - [`send_packet`](/documentation/data-transmission.md#send_packet) - - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) - - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) - - [`PJONSwitch`](/documentation/routing.md#switch) - - [`PJONRouter`](/documentation/routing.md#router) - - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) - - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/addressing.md b/documentation/addressing.md index 1f832d3281..27fb676205 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -1,45 +1,19 @@ ### Documentation index - **[Addressing](/documentation/addressing.md)** - - [`device_id`](/documentation/addressing.md#local-mode) - - [`get_bus_id`](/documentation/addressing.md#shared-mode) - - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - - [`set_bus_id`](/documentation/addressing.md#shared-mode) - - [`set_id`](/documentation/addressing.md#local-mode) - - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`include_mac`](/documentation/configuration.md#hardware-identification) - - [`include_port`](/documentation/configuration.md#network-service-identification) - - [`include_sender_info`](/documentation/configuration.md#sender-information) - - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) - - [`set_crc_32`](/documentation/configuration.md#crc-configuration) - - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) - - [`set_packet_id`](/documentation/configuration.md#packet-identification) - - [`set_router`](/documentation/configuration.md#router-mode) - - [`set_shared_network`](/documentation/configuration.md#network-mode) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) - - [`receive`](/documentation/data-reception.md#data-reception) - - [`set_receiver`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) - - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) - - [`reply`](/documentation/data-transmission.md#reply) - - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) - - [`send`](/documentation/data-transmission.md#send) - - [`send_packet`](/documentation/data-transmission.md#send_packet) - - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) - - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) - - [`PJONSwitch`](/documentation/routing.md#switch) - - [`PJONRouter`](/documentation/routing.md#router) - - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) - - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) diff --git a/documentation/configuration.md b/documentation/configuration.md index 99d01b628f..da0fd3e560 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -1,45 +1,19 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`device_id`](/documentation/addressing.md#local-mode) - - [`get_bus_id`](/documentation/addressing.md#shared-mode) - - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - - [`set_bus_id`](/documentation/addressing.md#shared-mode) - - [`set_id`](/documentation/addressing.md#local-mode) - - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - **[Configuration](/documentation/configuration.md)** - - [`include_mac`](/documentation/configuration.md#hardware-identification) - - [`include_port`](/documentation/configuration.md#network-service-identification) - - [`include_sender_info`](/documentation/configuration.md#sender-information) - - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) - - [`set_crc_32`](/documentation/configuration.md#crc-configuration) - - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) - - [`set_packet_id`](/documentation/configuration.md#packet-identification) - - [`set_router`](/documentation/configuration.md#router-mode) - - [`set_shared_network`](/documentation/configuration.md#network-mode) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) - - [`receive`](/documentation/data-reception.md#data-reception) - - [`set_receiver`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) - - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) - - [`reply`](/documentation/data-transmission.md#reply) - - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) - - [`send`](/documentation/data-transmission.md#send) - - [`send_packet`](/documentation/data-transmission.md#send_packet) - - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) - - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) - - [`PJONSwitch`](/documentation/routing.md#switch) - - [`PJONRouter`](/documentation/routing.md#router) - - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) - - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/data-reception.md b/documentation/data-reception.md index 1636eb62d1..f9397c602b 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -1,45 +1,19 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`device_id`](/documentation/addressing.md#local-mode) - - [`get_bus_id`](/documentation/addressing.md#shared-mode) - - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - - [`set_bus_id`](/documentation/addressing.md#shared-mode) - - [`set_id`](/documentation/addressing.md#local-mode) - - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`include_mac`](/documentation/configuration.md#hardware-identification) - - [`include_port`](/documentation/configuration.md#network-service-identification) - - [`include_sender_info`](/documentation/configuration.md#sender-information) - - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) - - [`set_crc_32`](/documentation/configuration.md#crc-configuration) - - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) - - [`set_packet_id`](/documentation/configuration.md#packet-identification) - - [`set_router`](/documentation/configuration.md#router-mode) - - [`set_shared_network`](/documentation/configuration.md#network-mode) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - **[Data reception](/documentation/data-reception.md)** - - [`receive`](/documentation/data-reception.md#data-reception) - - [`set_receiver`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) - - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) - - [`reply`](/documentation/data-transmission.md#reply) - - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) - - [`send`](/documentation/data-transmission.md#send) - - [`send_packet`](/documentation/data-transmission.md#send_packet) - - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) - - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) - - [`PJONSwitch`](/documentation/routing.md#switch) - - [`PJONRouter`](/documentation/routing.md#router) - - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) - - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/data-structures.md b/documentation/data-structures.md index 1927259732..e0bb80adf5 100644 --- a/documentation/data-structures.md +++ b/documentation/data-structures.md @@ -1,45 +1,19 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`device_id`](/documentation/addressing.md#local-mode) - - [`get_bus_id`](/documentation/addressing.md#shared-mode) - - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - - [`set_bus_id`](/documentation/addressing.md#shared-mode) - - [`set_id`](/documentation/addressing.md#local-mode) - - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`include_mac`](/documentation/configuration.md#hardware-identification) - - [`include_port`](/documentation/configuration.md#network-service-identification) - - [`include_sender_info`](/documentation/configuration.md#sender-information) - - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) - - [`set_crc_32`](/documentation/configuration.md#crc-configuration) - - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) - - [`set_packet_id`](/documentation/configuration.md#packet-identification) - - [`set_router`](/documentation/configuration.md#router-mode) - - [`set_shared_network`](/documentation/configuration.md#network-mode) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) - - [`receive`](/documentation/data-reception.md#data-reception) - - [`set_receiver`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - **[Data structures](/documentation/data-structures.md)** - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) - - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) - - [`reply`](/documentation/data-transmission.md#reply) - - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) - - [`send`](/documentation/data-transmission.md#send) - - [`send_packet`](/documentation/data-transmission.md#send_packet) - - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) - - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) - - [`PJONSwitch`](/documentation/routing.md#switch) - - [`PJONRouter`](/documentation/routing.md#router) - - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) - - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index b23821cf6a..b0b38be9ca 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -1,45 +1,19 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`device_id`](/documentation/addressing.md#local-mode) - - [`get_bus_id`](/documentation/addressing.md#shared-mode) - - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - - [`set_bus_id`](/documentation/addressing.md#shared-mode) - - [`set_id`](/documentation/addressing.md#local-mode) - - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`include_mac`](/documentation/configuration.md#hardware-identification) - - [`include_port`](/documentation/configuration.md#network-service-identification) - - [`include_sender_info`](/documentation/configuration.md#sender-information) - - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) - - [`set_crc_32`](/documentation/configuration.md#crc-configuration) - - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) - - [`set_packet_id`](/documentation/configuration.md#packet-identification) - - [`set_router`](/documentation/configuration.md#router-mode) - - [`set_shared_network`](/documentation/configuration.md#network-mode) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) - - [`receive`](/documentation/data-reception.md#data-reception) - - [`set_receiver`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) - - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - **[Data transmission](/documentation/data-transmission.md)** - - [`begin`](/documentation/data-transmission.md#begin) - - [`reply`](/documentation/data-transmission.md#reply) - - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) - - [`send`](/documentation/data-transmission.md#send) - - [`send_packet`](/documentation/data-transmission.md#send_packet) - - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) - - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) - - [`PJONSwitch`](/documentation/routing.md#switch) - - [`PJONRouter`](/documentation/routing.md#router) - - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) - - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/error-handling.md b/documentation/error-handling.md index 5008c887ef..72ec6bec4d 100644 --- a/documentation/error-handling.md +++ b/documentation/error-handling.md @@ -1,45 +1,19 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`device_id`](/documentation/addressing.md#local-mode) - - [`get_bus_id`](/documentation/addressing.md#shared-mode) - - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - - [`set_bus_id`](/documentation/addressing.md#shared-mode) - - [`set_id`](/documentation/addressing.md#local-mode) - - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`include_mac`](/documentation/configuration.md#hardware-identification) - - [`include_port`](/documentation/configuration.md#network-service-identification) - - [`include_sender_info`](/documentation/configuration.md#sender-information) - - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) - - [`set_crc_32`](/documentation/configuration.md#crc-configuration) - - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) - - [`set_packet_id`](/documentation/configuration.md#packet-identification) - - [`set_router`](/documentation/configuration.md#router-mode) - - [`set_shared_network`](/documentation/configuration.md#network-mode) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) - - [`receive`](/documentation/data-reception.md#data-reception) - - [`set_receiver`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) - - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) - - [`reply`](/documentation/data-transmission.md#reply) - - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) - - [`send`](/documentation/data-transmission.md#send) - - [`send_packet`](/documentation/data-transmission.md#send_packet) - - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) - - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - **[Error handling](/documentation/error-handling.md)** - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) - - [`PJONSwitch`](/documentation/routing.md#switch) - - [`PJONRouter`](/documentation/routing.md#router) - - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) - - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/io-setup.md b/documentation/io-setup.md index 0158585cb7..38df4fbeb8 100644 --- a/documentation/io-setup.md +++ b/documentation/io-setup.md @@ -1,45 +1,19 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`device_id`](/documentation/addressing.md#local-mode) - - [`get_bus_id`](/documentation/addressing.md#shared-mode) - - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - - [`set_bus_id`](/documentation/addressing.md#shared-mode) - - [`set_id`](/documentation/addressing.md#local-mode) - - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`include_mac`](/documentation/configuration.md#hardware-identification) - - [`include_port`](/documentation/configuration.md#network-service-identification) - - [`include_sender_info`](/documentation/configuration.md#sender-information) - - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) - - [`set_crc_32`](/documentation/configuration.md#crc-configuration) - - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) - - [`set_packet_id`](/documentation/configuration.md#packet-identification) - - [`set_router`](/documentation/configuration.md#router-mode) - - [`set_shared_network`](/documentation/configuration.md#network-mode) -- [Data reception](/documentation/data-reception.md) - - [`receive`](/documentation/data-reception.md#data-reception) - - [`set_receiver`](/documentation/data-reception.md#data-reception) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) +- [Data reception](/documentation/data-reception.md) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) - - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) - - [`reply`](/documentation/data-transmission.md#reply) - - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) - - [`send`](/documentation/data-transmission.md#send) - - [`send_packet`](/documentation/data-transmission.md#send_packet) - - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) - - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) - - [`PJONSwitch`](/documentation/routing.md#switch) - - [`PJONRouter`](/documentation/routing.md#router) - - [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) - - [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - **[IO setup](/documentation/io-setup.md)** - [`strategy`](/documentation/io-setup.md#io-setup) --- diff --git a/documentation/routing.md b/documentation/routing.md index b2e01c24ef..0fc40e2f49 100644 --- a/documentation/routing.md +++ b/documentation/routing.md @@ -1,37 +1,15 @@ ### Documentation index -- [Addressing](/documentation/addressing.md) - - [`device_id`](/documentation/addressing.md#local-mode) - - [`get_bus_id`](/documentation/addressing.md#shared-mode) - - [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - - [`set_bus_id`](/documentation/addressing.md#shared-mode) - - [`set_id`](/documentation/addressing.md#local-mode) - - [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`include_mac`](/documentation/configuration.md#hardware-identification) - - [`include_port`](/documentation/configuration.md#network-service-identification) - - [`include_sender_info`](/documentation/configuration.md#sender-information) - - [`set_acknowledge`](/documentation/configuration.md#acknowledgement) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) - - [`set_crc_32`](/documentation/configuration.md#crc-configuration) - - [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) - - [`set_packet_id`](/documentation/configuration.md#packet-identification) - - [`set_router`](/documentation/configuration.md#router-mode) - - [`set_shared_network`](/documentation/configuration.md#network-mode) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) - - [`receive`](/documentation/data-reception.md#data-reception) - - [`set_receiver`](/documentation/data-reception.md#data-reception) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) - - [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) - - [`reply`](/documentation/data-transmission.md#reply) - - [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) - - [`send`](/documentation/data-transmission.md#send) - - [`send_packet`](/documentation/data-transmission.md#send_packet) - - [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) - - [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - **[Routing](/documentation/routing.md)** From d6a1531c8b36372f3bdc971a11039469bedfd85d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Jun 2020 18:52:45 +0200 Subject: [PATCH 103/323] get_bus_id, get_mac, set_mac source and documentation added --- documentation/addressing.md | 22 ++++++++++++++++++---- src/PJON.h | 25 ++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/documentation/addressing.md b/documentation/addressing.md index 27fb676205..2860586a9e 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -62,9 +62,16 @@ PJONSoftwareBitBang bus(bus_id, 44); ``` ### Get or set bus identifier -The bus id can be read and set after initialisation using `bus_id`: +Use `get_bus_id` to get a pointer to the bus id used by the instance: ```cpp - bus.tx.bus_id; // Get or set bus id + uint8_t bus_id[4]; + memcpy(bus_id, bus.get_bus_id(bus_id), 4); // Copy bus id in bus_id +``` + +The bus id can set after initialisation using `set_bus_id`: +```cpp + uint8_t bus_id[4] = {0, 0, 0, 1}; + bus.set_bus_id(bus_id); // Set bus id ``` ### Hardware identifier @@ -87,7 +94,14 @@ bus.include_mac(false); ``` ### Get or set hardware identifier -The MAC address can be read and set after initialisation using `tx.mac`: +Use `get_mac` to get a pointer to the mac address used by the instance: +```cpp + uint8_t mac[4]; + memcpy(mac, bus.get_mac(mac), 6); // Copy mac in variable +``` + +The mac address can set after initialisation using `set_mac`: ```cpp - bus.tx.mac; // Get or set MAC + uint8_t mac[6] = {0, 0, 0, 0, 0, 1}; + bus.set_mac(mac); // Set mac ``` diff --git a/src/PJON.h b/src/PJON.h index 87ed27a3df..e003196e8b 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -209,6 +209,12 @@ class PJON { return PJON_FAIL; }; + /* Returns a pointer to the bus id used by the instance: */ + + const uint8_t *get_bus_id() const { + return tx.bus_id; + }; + /* Get count of packets: Don't pass any parameter to count all dispatched packets Pass a device id to count all it's related packets */ @@ -746,7 +752,24 @@ class PJON { void include_mac(bool state) { set_config_bit(state, PJON_MAC_BIT); - } + }; + + #if(PJON_INCLUDE_MAC) + + /* Returns a pointer to the mac address used by the instance: */ + + const uint8_t *get_mac() const { + return tx.mac; + }; + + /* Set the mac address used by the instance: + It receives a pointer to the mac address */ + + void set_mac(const uint8_t *mac) { + PJONTools::copy_id(tx.mac, mac, 6); + }; + + #endif /* Configure the bus network behaviour. state = true -> Include 32 bits bus id or group identification. From 06ab967683729c74714eac96825e60f3fbcdd287 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Jun 2020 18:54:58 +0200 Subject: [PATCH 104/323] set_bus_id just sets the bus id, does not change the configuration --- src/PJON.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index e003196e8b..2fee28d302 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -731,8 +731,7 @@ class PJON { void set_bus_id(const uint8_t *b_id) { PJONTools::copy_id(tx.bus_id, b_id, 4); - config |= PJON_MODE_BIT; - } + }; /* Configure sender's information inclusion in the packet. state = true -> +8 bits (device id) in local mode From 0449888f130f4e52164f03ecd848c464b3933b5e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Jun 2020 18:57:15 +0200 Subject: [PATCH 105/323] documentation/addressing mac length fix --- documentation/addressing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/addressing.md b/documentation/addressing.md index 2860586a9e..84c38c0628 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -96,7 +96,7 @@ bus.include_mac(false); Use `get_mac` to get a pointer to the mac address used by the instance: ```cpp - uint8_t mac[4]; + uint8_t mac[6]; memcpy(mac, bus.get_mac(mac), 6); // Copy mac in variable ``` From 0eed9d9c5047a00a07f365b1d1895c51477071a4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Jun 2020 22:46:57 +0200 Subject: [PATCH 106/323] Documentation index added, minor fix to README --- README.md | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 79a872c38f..75aefc6b82 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,51 @@ ![PJON](http://www.gioblu.com/PJON/PJON-github-header-tiny.png) ## PJON 12.1 -PJON® (Padded Jittering Operative Network) is an arduino-compatible, multi-master, multi-media network protocol. It proposes a new Open Standard, it is designed as a framework and implements a totally software-defined network protocol stack that can be easily cross-compiled on many MCUs and architectures like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media and protocols like TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485, LoRa, PJDL, PJDLR and PJDLS. +PJON® (Padded Jittering Operative Network) is an arduino-compatible, multi-master, multi-media network protocol. It proposes a new Open Standard, it is designed as a framework and implements a totally software-defined network protocol stack that can be easily cross-compiled on many MCUs and architectures like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media and protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. [![Get PJON bus id](https://img.shields.io/badge/get-PJON%20bus%20id-lightgrey.svg)](http://www.pjon.org/get-bus-id.php) [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) PJON is used in thousands of devices and its community has spread worldwide because of the following 5 key factors: - **New technology**: [PJON](specification/PJON-protocol-specification-v4.0.md) is an experimental network protocol stack crafted in 10 years of research and experimentation. It was originally developed as an open-source alternative to i2c and 1-Wire but during development its scope and features have been extended to cover use cases where IP is generally applied. PJON has been engineered to have a variable footprint (4.2-8.2 kB program memory) and overhead (5-35 bytes per packet) depending on its configuration. -- **Multi-media support**: PJON operates on a wide range of media and protocols like TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485 and LoRa. The PJON network protocol stack specifies and implements also [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) able to communicate data over a single wire shared by up to 255 devices, [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) able to operate with many ASK/FSK/OOK radio modules and also [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md), able to communicate wirelessly with light pulses using off the shelf LEDs and laser diodes. -- **Increased reliability**: Many protocols massively applied worldwide expose dangerous vulnerabilities, have weak error detection algorithms and are not resilient to interference. PJON is based on years of analysis and study not to make the same mistakes present in most alternatives and provide with a set of simpler and more efficient solutions. +- **Multi-media support**: PJON operates upon a wide range of protocols like TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485 and LoRa. The PJON network protocol stack specifies and implements also [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) that operates over a single wire of up to 2000m shared by up to 255 devices, [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) that operates with many ASK/FSK/OOK radio modules, and also [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) that operates wirelessly with light pulses using off-the-shelf LEDs and laser diodes. +- **Increased reliability**: Many protocols massively applied worldwide expose dangerous vulnerabilities, have weak error detection algorithms and are not resilient to interference. PJON is based on years of analysis and study not to make the same mistakes present in most alternatives and provide with a simpler and more efficient solution. - **High flexibility**: PJON is totally software-defined and its implementation is designed to be easily extensible. it builds out-of-the-box in all supported devices and operates transparently on top of any supported protocol or medium. - **Low cost**: Without any additional hardware needed to operate, minimal network wiring requirements and direct pin-to-pin or LED-to-LED communication, PJON is extremely energy efficient, cheap to be implemented and maintained. This implementation is kept updated and meticulously tested thanks to the strong commitment of its growing community of end users, testers and developers. ### Features -- Cross-compilation support with the [interfaces](src/interfaces) system calls abstraction +- Cross-compilation support with the [interfaces](src/interfaces) system calls abstraction - Multi-media support with the [strategies](src/strategies) data link layer abstraction +- Modular packet format that includes only the field used (overhead 5-35 bytes) - Hot-swap support, no need of system reset or shut down when replacing or adding devices -- Configurable synchronous and/or asynchronous [acknowledgement](specification/PJON-protocol-acknowledge-specification-v1.0.md) -- Configurable 2 level addressing (device and bus id) for scalable applications -- Configurable 1 or 2 bytes packet length (max 255 or 65535 bytes) -- Configurable CRC8 or CRC32 table-less cyclic redundancy check -- Packet manager to handle, track and if necessary retransmit a packet sending in background +- Flexible local (device id) and shared (bus id) network identification +- Safe error detection done with modern CRC8 and CRC32 polynomials +- Optional inclusion of MAC addresses +- Optional acknowledgement - Error handling ### Specifications - [PJON v4.0](specification/PJON-protocol-specification-v4.0.md) - [PJDL v4.1](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) - [PJDLR v3.0](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS v2.0](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) - [TSDL v3.0](src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) +### Documentation +- [Addressing](/documentation/addressing.md) + - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) +- [Configuration](/documentation/configuration.md) + - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) +- [Data reception](/documentation/data-reception.md) + - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) +- [Data structures](/documentation/data-structures.md) + - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) +- [Data transmission](/documentation/data-transmission.md) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) +- [Error handling](/documentation/error-handling.md) + - [`set_error`](/documentation/error-handling.md#error-handling) +- [Routing](/documentation/routing.md) + - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) +- [IO setup](/documentation/io-setup.md) + - [`strategy`](/documentation/io-setup.md#io-setup) + ### Publications - [PJON protocol handbook](https://www.pjon-technologies.com/collections/frontpage/products/pjon-protocol-hand-book) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) - [PJON 12.0 big box](https://www.pjon-technologies.com/collections/frontpage/products/pjon-protocol-12-0-big-box) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) From 16e2eb53e873aed0f2cc81d037b455e6a53b1e4f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Jun 2020 22:49:35 +0200 Subject: [PATCH 107/323] README Flexibility remark minor fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 75aefc6b82..5b4eec2528 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ PJON is used in thousands of devices and its community has spread worldwide beca - **New technology**: [PJON](specification/PJON-protocol-specification-v4.0.md) is an experimental network protocol stack crafted in 10 years of research and experimentation. It was originally developed as an open-source alternative to i2c and 1-Wire but during development its scope and features have been extended to cover use cases where IP is generally applied. PJON has been engineered to have a variable footprint (4.2-8.2 kB program memory) and overhead (5-35 bytes per packet) depending on its configuration. - **Multi-media support**: PJON operates upon a wide range of protocols like TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485 and LoRa. The PJON network protocol stack specifies and implements also [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) that operates over a single wire of up to 2000m shared by up to 255 devices, [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) that operates with many ASK/FSK/OOK radio modules, and also [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) that operates wirelessly with light pulses using off-the-shelf LEDs and laser diodes. - **Increased reliability**: Many protocols massively applied worldwide expose dangerous vulnerabilities, have weak error detection algorithms and are not resilient to interference. PJON is based on years of analysis and study not to make the same mistakes present in most alternatives and provide with a simpler and more efficient solution. -- **High flexibility**: PJON is totally software-defined and its implementation is designed to be easily extensible. it builds out-of-the-box in all supported devices and operates transparently on top of any supported protocol or medium. +- **High flexibility**: PJON is totally software-defined and it is designed to be easily extensible. it builds out-of-the-box in all supported devices and operates transparently on top of any supported protocol or medium. - **Low cost**: Without any additional hardware needed to operate, minimal network wiring requirements and direct pin-to-pin or LED-to-LED communication, PJON is extremely energy efficient, cheap to be implemented and maintained. This implementation is kept updated and meticulously tested thanks to the strong commitment of its growing community of end users, testers and developers. ### Features From 579ad8839dfe7d191e0f74606b3aba76a76c7a16 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Jun 2020 23:02:40 +0200 Subject: [PATCH 108/323] README simplified doc and spec index --- README.md | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 5b4eec2528..4b6e7228be 100644 --- a/README.md +++ b/README.md @@ -26,25 +26,20 @@ PJON is used in thousands of devices and its community has spread worldwide beca ### Specifications - [PJON v4.0](specification/PJON-protocol-specification-v4.0.md) -- [PJDL v4.1](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) - [PJDLR v3.0](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS v2.0](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) - [TSDL v3.0](src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) +- [PJDL v4.1](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) +- [PJDLR v3.0](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) +- [PJDLS v2.0](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) +- [TSDL v3.0](src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) ### Documentation - [Addressing](/documentation/addressing.md) - - [`set_id`](/documentation/addressing.md#local-mode) [`device_id`](/documentation/addressing.md#local-mode) [`get_bus_id`](/documentation/addressing.md#shared-mode) [`set_bus_id`](/documentation/addressing.md#shared-mode) [`get_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) [`set_mac`](/documentation/addressing.md#get-or-set-hardware-identifier) - [Configuration](/documentation/configuration.md) - - [`set_communication_mode`](/documentation/configuration.md#communication-mode) [`set_shared_network`](/documentation/configuration.md#network-mode) [`set_router`](/documentation/configuration.md#router-mode) [`include_sender_info`](/documentation/configuration.md#sender-information) [`set_crc_32`](/documentation/configuration.md#crc-configuration) [`set_packet_auto_deletion`](/documentation/configuration.md#packet-handling) [`set_acknowledge`](/documentation/configuration.md#acknowledgement) [`set_packet_id`](/documentation/configuration.md#packet-identification) [`include_port`](/documentation/configuration.md#network-service-identification) [`include_mac`](/documentation/configuration.md#hardware-identification) - [Data reception](/documentation/data-reception.md) - - [`set_receiver`](/documentation/data-reception.md#data-reception) [`receive`](/documentation/data-reception.md#data-reception) - [Data structures](/documentation/data-structures.md) - - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) - [Error handling](/documentation/error-handling.md) - - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) - - [`PJONSimpleSwitch`](/documentation/routing.md#simpleswitch) [`PJONSwitch`](/documentation/routing.md#switch) [`PJONRouter`](/documentation/routing.md#router) [`PJONDynamicRouter`](/documentation/routing.md#dynamicrouter) [`PJONInteractiveRouter`](/documentation/routing.md#interactiverouter) - [IO setup](/documentation/io-setup.md) - - [`strategy`](/documentation/io-setup.md#io-setup) ### Publications - [PJON protocol handbook](https://www.pjon-technologies.com/collections/frontpage/products/pjon-protocol-hand-book) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) From 5156a02d76ea80c34b0a7187f32273b829e74a38 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 28 Jun 2020 16:36:03 +0200 Subject: [PATCH 109/323] PJON protocol specification changelog added --- specification/PJON-protocol-specification-v4.0.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index 5e98f9b7ff..52fc288c18 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -21,7 +21,19 @@ Latest revision: 27/04/2020 Related work: https://github.com/gioblu/PJON/ Compliant implementations: PJON v13.0 and following Released into the public domain + +10/04/2010 0.1 - First local mode draft +19/08/2015 0.2 - First local and shared mode draft +04/09/2016 0.3 - Added header proposed by Fred Larsen +03/10/2016 1.0 - 16 bits length support, CRC8 or CRC32 support +28/03/2017 1.1 - NAK removed, unacceptable headers added +15/10/2017 2.0 - CRC8 added to meta-data, CRC32 when length > 15 +14/12/2017 3.0 - Added port and packet id +31/10/2018 3.1 - Model simplified +10/03/2020 3.2 - Encoding specification completed +28/08/2020 4.0 - Added MAC and hops, removed async-ack ``` + The PJON protocol v4.0 in local mode supports connectivity for up to 254 devices, in shared mode supports connectivity for up to 4.294.967.295 buses (groups of devices) and up to 1.090.921.692.930 devices. The packet format is dynamic therefore meta-data can be optionally included using the header as a bitmap of selected features. It supports interoperability between systems that use a different configuration and provides with high efficiency including only the protocol's features used and the overhead effectively required (5-35 bytes). PJON can be used for low-data-rate applications as an alternative to 1-Wire, i2c or CAN but can also be applied in place of IP to interconnect more complex networks. The graph below shows the conceptual model that characterizes and standardizes the communication. Its goal is the interoperability of diverse systems on a wide range of media with the use of a new set of Open Standards. The graph partitions represent abstraction layers. From 241ed5560e74c27d3775f101351084c6f574a0a9 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 28 Jun 2020 16:45:50 +0200 Subject: [PATCH 110/323] PJON specification changelog minor fix --- specification/PJON-protocol-specification-v4.0.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index 52fc288c18..63cc21ef93 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -17,7 +17,7 @@ Invented by Giovanni Blu Mitolo with the help of Fred Larsen Originally published: 10/04/2010 -Latest revision: 27/04/2020 +Latest revision: 28/08/2020 Related work: https://github.com/gioblu/PJON/ Compliant implementations: PJON v13.0 and following Released into the public domain @@ -25,9 +25,9 @@ Released into the public domain 10/04/2010 0.1 - First local mode draft 19/08/2015 0.2 - First local and shared mode draft 04/09/2016 0.3 - Added header proposed by Fred Larsen -03/10/2016 1.0 - 16 bits length support, CRC8 or CRC32 support -28/03/2017 1.1 - NAK removed, unacceptable headers added -15/10/2017 2.0 - CRC8 added to meta-data, CRC32 when length > 15 +03/10/2016 1.0 - 16 bits length, CRC8 and CRC32 added +28/03/2017 1.1 - Removed NAK, added unacceptable headers +15/10/2017 2.0 - Length corruption vulnerability avoided 14/12/2017 3.0 - Added port and packet id 31/10/2018 3.1 - Model simplified 10/03/2020 3.2 - Encoding specification completed From 8fabd71a1e23a164437d0a9a26bf1975c159b201 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 28 Jun 2020 19:13:54 +0200 Subject: [PATCH 111/323] @fotosettore added to contributors --- README.md | 2 +- src/PJON.h | 2 +- src/PJONDefines.h | 2 +- src/PJONLocal.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4b6e7228be..1afdba96b7 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Telecomunicación - [Universidad de Cantabria](https://web.unican.es/) (ES) ### Contribute Feel free to send a pull request sharing something you have made that could help, if you want to support this project you can also try to solve an [issue](https://github.com/gioblu/PJON/issues). Thanks to support, expertise, kindness and talent of the following contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: -[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj) and [callalilychen](https://github.com/callalilychen). +[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj) and [callalilychen](https://github.com/callalilychen). ### Compliant tools - [ModuleInterface](https://github.com/fredilarsen/ModuleInterface) - easy config and value sync between IoT modules by Fred Larsen diff --git a/src/PJON.h b/src/PJON.h index 2fee28d302..a71dbf9c8e 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -20,7 +20,7 @@ contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: Fred Larsen, Zbigniew Zasieczny, Matheus Garbelini, sticilface, - Felix Barbalet, Oleh Halitskiy, fabpolli, Adrian Sławiński, + Felix Barbalet, Oleh Halitskiy, fotosettore, fabpolli, Adrian Sławiński, Osman Selçuk Aktepe, Jorgen-VikingGod, drtrigon, Endre Karlson, Wilfried Klaas, budaics, ibantxo, gonnavis, maxidroms83, Evgeny Dontsov, zcattacz, Valerii Koval, Ivan Kravets, Esben Soeltoft, Alex Grishin, diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 311d7fcda0..78330b588e 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -20,7 +20,7 @@ contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: Fred Larsen, Zbigniew Zasieczny, Matheus Garbelini, sticilface, - Felix Barbalet, Oleh Halitskiy, fabpolli, Adrian Sławiński, + Felix Barbalet, Oleh Halitskiy, fotosettore, fabpolli, Adrian Sławiński, Osman Selçuk Aktepe, Jorgen-VikingGod, drtrigon, Endre Karlson, Wilfried Klaas, budaics, ibantxo, gonnavis, maxidroms83, Evgeny Dontsov, zcattacz, Valerii Koval, Ivan Kravets, Esben Soeltoft, Alex Grishin, diff --git a/src/PJONLocal.h b/src/PJONLocal.h index 2c1275eab1..a21009821f 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -29,7 +29,7 @@ contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: Fred Larsen, Zbigniew Zasieczny, Matheus Garbelini, sticilface, - Felix Barbalet, Oleh Halitskiy, fabpolli, Adrian Sławiński, + Felix Barbalet, Oleh Halitskiy, fotosettore, fabpolli, Adrian Sławiński, Osman Selçuk Aktepe, Jorgen-VikingGod, drtrigon, Endre Karlson, Wilfried Klaas, budaics, ibantxo, gonnavis, maxidroms83, Evgeny Dontsov, zcattacz, Valerii Koval, Ivan Kravets, Esben Soeltoft, Alex Grishin, From 51e8744521540a28fe686b2ec04a1ea76217b769 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 28 Jun 2020 19:37:08 +0200 Subject: [PATCH 112/323] PJON specification changelog minor fix --- specification/PJON-protocol-specification-v4.0.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index 63cc21ef93..cb099a630f 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -28,10 +28,10 @@ Released into the public domain 03/10/2016 1.0 - 16 bits length, CRC8 and CRC32 added 28/03/2017 1.1 - Removed NAK, added unacceptable headers 15/10/2017 2.0 - Length corruption vulnerability avoided -14/12/2017 3.0 - Added port and packet id +14/12/2017 3.0 - Port and packet id added 31/10/2018 3.1 - Model simplified -10/03/2020 3.2 - Encoding specification completed -28/08/2020 4.0 - Added MAC and hops, removed async-ack +10/03/2020 3.2 - Missing encoding specification added +28/08/2020 4.0 - MAC and hops added, async-ack removed ``` The PJON protocol v4.0 in local mode supports connectivity for up to 254 devices, in shared mode supports connectivity for up to 4.294.967.295 buses (groups of devices) and up to 1.090.921.692.930 devices. The packet format is dynamic therefore meta-data can be optionally included using the header as a bitmap of selected features. It supports interoperability between systems that use a different configuration and provides with high efficiency including only the protocol's features used and the overhead effectively required (5-35 bytes). PJON can be used for low-data-rate applications as an alternative to 1-Wire, i2c or CAN but can also be applied in place of IP to interconnect more complex networks. From 78c5b39134ccde7a9ac6b668ae742b14a2601fad Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 28 Jun 2020 20:51:53 +0200 Subject: [PATCH 113/323] new getters and setters keywords added --- keywords.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/keywords.txt b/keywords.txt index 118b2933ea..8df241623d 100644 --- a/keywords.txt +++ b/keywords.txt @@ -44,6 +44,8 @@ begin KEYWORD2 can_start KEYWORD2 device_id KEYWORD2 get_packets_count KEYWORD2 +get_bus_id KEYWORD2 +get_mac KEYWORD2 include_mac KEYWORD2 include_port KEYWORD2 include_sender_info KEYWORD2 @@ -57,6 +59,8 @@ send_repeatedly KEYWORD2 send_packet KEYWORD2 send_packet_blocking KEYWORD2 set_acknowledge KEYWORD2 +set_bus_id KEYWORD2 +set_mac KEYWORD2 set_random_seed KEYWORD2 set_communication_mode KEYWORD2 set_error KEYWORD2 From 7fa31fff4c6a1dcfd2548ef2fb4c1d014a47ba72 Mon Sep 17 00:00:00 2001 From: Julio Aguirre Date: Fri, 10 Jul 2020 00:31:56 +0400 Subject: [PATCH 114/323] Add bluepill timings.h for modes 1,2,3-4 and fixed arduino uno mode 3 to be more in line with spec --- src/strategies/SoftwareBitBang/.DS_Store | Bin 0 -> 6148 bytes .../Dumps and pic stm32f103/.DS_Store | Bin 0 -> 6148 bytes .../ArduinoMasterBluePillSlaveSpeedMode2.sr | Bin 0 -> 2728 bytes .../ArduinoMasterBluePillSlaveSpeedMode3.sr | Bin 0 -> 2286 bytes .../ArduinoMasterBluePillSlaveSpeedMode4.sr | Bin 0 -> 2157 bytes .../ArduinoMasterBluepillSlaveMode1.sr | Bin 0 -> 2913 bytes .../BluePillMasterArduinoSlaveSpeedMode1.sr | Bin 0 -> 1038 bytes ...luePillMasterArduinoSlaveSpeedMode2full.sr | Bin 0 -> 40044 bytes ...luePillMasterArduinoSlaveSpeedMode3full.sr | Bin 0 -> 10729 bytes ...luePillMasterArduinoSlaveSpeedMode4full.sr | Bin 0 -> 11489 bytes .../swbb_acceptance.png | Bin 0 -> 148874 bytes .../Dumps and pic stm32f103/unomode3.png | Bin 0 -> 51210 bytes src/strategies/SoftwareBitBang/Timing.h | 43 +++++++++++++++--- 13 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 src/strategies/SoftwareBitBang/.DS_Store create mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/.DS_Store create mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluePillSlaveSpeedMode2.sr create mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluePillSlaveSpeedMode3.sr create mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluePillSlaveSpeedMode4.sr create mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluepillSlaveMode1.sr create mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode1.sr create mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode2full.sr create mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode3full.sr create mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode4full.sr create mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/swbb_acceptance.png create mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/unomode3.png diff --git a/src/strategies/SoftwareBitBang/.DS_Store b/src/strategies/SoftwareBitBang/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8bfb6584b4a58b8077f4e299d5e05de0da9abf22 GIT binary patch literal 6148 zcmeHK!A`?441F0p6mi)NE=c(V%07THl@CBWa)GTHAg#30*uCGzXYe&V#}?{TI7}cU zCR=h|n#4~1BE>O)Fxyr+FaeNJ1xLqhz7Uxg9mvQ=#>9|(Y!LB)7gR)-|GEVuc(Rn64l5`Le0oUU++YsGG7}teXWrWLM|6c)xqQ-v2-9 zruqdh?b9HdUSQsJ2AlzB;2;?Y8dY|3kkNTi&VV!U69(jdh*ZJCuv1J|2b)v^5ak(} zgng+c#3mXRhMgj3C_zn$Y8tG>2x`vpXzL2YPEpMftoR7FbFc~}q}}O1rsW8QqPNa~ zGqB6Rk$z4j|KEIH|L+?4mowlD925g#T+YiGL$cgD2u^Zsq~23SWL>BDX~IrQ#at_? c_>7u_<54=q!mv~12*n=)i3V?+fj?#71CR7P+5i9m literal 0 HcmV?d00001 diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/.DS_Store b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 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 G4e%e_e&~My literal 0 HcmV?d00001 diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluePillSlaveSpeedMode3.sr b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluePillSlaveSpeedMode3.sr new file mode 100644 index 0000000000000000000000000000000000000000..c519e3601ddce2a5023e63dfdb2749ffada525bb GIT binary patch literal 2286 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�U zm-fNsO>8%EnWSyadunB$PK~ic1%ix=Q=~kJ;wNRd2a`F%{QkBM3I!MSTm48=%28B%(IsSi@203?c=@obaK_HPzz?c6 z^suHjJ>3dXExIJJYF)KdEy>=Eo4$$9ELO+$HFqqX8Vn8dL7$#+=UODGREvrLu64c| zJ^<4P;X4ZQb;$<)C)2umF3;wU-1&YW(K6+Yc(#g~^-e=^YjF4xtZDU;IrvxhZq&`s z&f}>z?7^mv4ytf``elPz={Jn94e4CX7B))mWR}df%6#sf|FC)sjIs~FuMY*O)U7UD z{BdC7)vUA1;Q~jufpf=?G))PvAuTsg6Wky5Y(cuoq=q!BQ-5ZaR$oDIdXjvlim4JdFl5`^=? ztuUkT$@slgB_-h~Oer$zCv}+?w>;BS(RhP$;QYRB8$I9&1 z(dKbnWVA!{96N#Cm+^r6dtT?^MNml9fQJFDF3-ubt=rcDH8MV@GCx{=-`8_KO)?^d zDzWqFJ!z+b*RvBe1lHPxhBu>(?gEE`*$GwH?XVT|%R69sc{_i1o+cm!x zHb*TFLMO!tL#$P-V&SfY*M=T??^FvZIhJ8a6W0>?#zoamucp=TR_;*Geu}rkn6|fQ z5>NTp&?B<%4K6Ee$RE$qImQ50n~6#k6PuPTl1oP$PjM%1Q}?ZnX~oWk;A(2Mbr7VY znX1QQMX*a}{k)m{jI?_^#9O&Gc$h0MP&w(DUg_MD=ya=P+0|N=J0kH&d`yxufvmqv zWxt7LxeUh7{1EXQgNleU-D#KW~o8nm}SMT99DQ8+(V0(j9Q{62M zwscop2Y=~nVLYf+RrgDPA3N(pvrKN>wT-fKWah@4b|KhHw4_o3-`>6X1JB{7_RfA# z#41DuF(8UFmko%*r@nK;7m5R>~I^M%W2=SkB=o=tqI{Bb^tL# z|Bh_|?Eb8VpOpR^;(vwyo#KB*0Dy*Ab%Fhx>Hkdq6RQ79^$F~M5sP=&DIhNZASCDl L!CU|HHv#wq%l*Ub literal 0 HcmV?d00001 diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluepillSlaveMode1.sr b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluepillSlaveMode1.sr new file mode 100644 index 0000000000000000000000000000000000000000..d0c78551bd6bed6b573104e629786357ee0db660 GIT binary patch literal 2913 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 b|Cf4uX#b0qHWqB`zgH}WU3fUl|9tj8tGg?( literal 0 HcmV?d00001 diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode1.sr b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode1.sr new file mode 100644 index 0000000000000000000000000000000000000000..b6aecc152c48618b71809fdf1cdc0580bc3a860f GIT binary patch literal 1038 zcmWIWW@h1H0D-QJF9Ue@U6o=4vO$;~h|5xoiZk=`i~@kFL>QPDIKZkteRX@#2$Y=x z#2i4Jn_7~Xl30?c+il3#Y{0`%zF$e6L3PUly?YY7J}@15z+%2>)+7y1o;~|QZ@*o# zdvCeeutWtjGDj`DRU=eDQ!Zsx#I6Y6Fs( z7#Lp1GBR)iotcxLo|&v`sB8H4Ze-qJ10Gfffwqai@9%gKFC@~c8!2sC+_*%`b?+rF zsgKWo#G5>HW#6~r>eofC`oDgan0;I{J=t_>>T~mTOxl0STuPTSEPv6|FMl}8k$2kn zqkVzp{M%Yyn8jVc}Cs-MZ94q`31Uy(6lp1F< ze>xCx-~QmAc%LN`88nL`EUpjy2EJBP89uExHI!v&X zxbc-iJbK;h=uZuSj14XioVGhWc*1@oTP&ci`GBD|$RRt08xtFB6vP=$us&35bWjjv z@L*ZTdxAN$xiOc&VDHmiei{N2qCi2r1O)-G59X}3nDvyglObW|wAW9>Ip+Lfs6NXy z@25GNP@@e{yNVCX!zbdLPnZ}E9$3rRsF1F*;XY&D))@8u4hbO)2R_zKlMp?@EW~(V z-ee}A7|=ZvI1cGJ$W7p2*fxvxO6`#Yf!aWex;N=wxS6wC`;OFx>`$&tk`4_U-|HBf zN3WY4FE?YQ;m=<=u8Id%a5}Hknaren!|eM9h8xxbIk$`6?-12Zt4)5`8)?9uc2H*q z>*fU8d)GbXHp=Wb{@Q+bQ3Yc|TpdGzHzSihGwyr^OpRc$4U~;wxeTHScQ%7)VPM$S ls0L)hG99`u^i+?~br#5k=YarkRyL3nGY~EU(qYUX9srCcf{6eC literal 0 HcmV?d00001 diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode2full.sr b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode2full.sr new file mode 100644 index 0000000000000000000000000000000000000000..62004d9207007b0391b8b4bf6ff905869b429aa9 GIT binary patch literal 40044 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 literal 0 HcmV?d00001 diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode3full.sr b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode3full.sr new file mode 100644 index 0000000000000000000000000000000000000000..dd54daa1b37a6504a31d077e74d25e093c62e60d GIT binary patch literal 10729 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 Us1_dn^(9>3l>@ws@?HP-AK^Fv`Tzg` literal 0 HcmV?d00001 diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode4full.sr b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode4full.sr new file mode 100644 index 0000000000000000000000000000000000000000..fe6048ad9dbd1497d65d08c8da6e5918725d9288 GIT binary patch literal 11489 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 h-oJtR~GOc%yIME{{yL7CtUyl literal 0 HcmV?d00001 diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/swbb_acceptance.png b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/swbb_acceptance.png new file mode 100644 index 0000000000000000000000000000000000000000..57d98d2d9a84a74bee9927e6737508e56e44f658 GIT binary patch literal 148874 zcmeFYWmsI>vM!9fySux)yF+j%K(OHM?jGD7fjg9$b0YNZm zXk@gs1teS~voOM_pa)1#fa=GtOK;PSk4CeADo)8%$Rdm=B`Z@+XZDP~ zHH3cFozbjPP%_DGU?BKgJ7Rk;Io3Oy;sgethKm(NV~-vkogPI`+(63A2sh3@ zb)yT2J^$?N^!=n8fm^cTUwhkUnb2j}1?s?9j7DH}dGH(MGx7d8#RxMA)0MEm^T%XI zXV6FH?JMz+`vWVN#C=ei6!fxt6kN|MTd1^}ac!&p@Jbnie&kIo$2PmbonO6~z zh$1`~CnR`2VVv0|W`UlK1xA>ffHsp!2UlWgL%XMETo4DpH-BYM5l>e7kelZ%pLbsn znc{-%8volBa**RE1dx@TEuRSAc_(L(<6JicB$($5abf@9LOz9n*tYhoPwv>TB;XhU zaMJfeH<2GS)9B%%ET5O$AsgT9zmrM45<; z;fvz@`Tf&r)0oGgco?w|h;c*VRN>!)&4Ukvv4T@$H6s^87Q-LFF3?wrk8zIGj|q-d zk5`YIkKd1%rlY4X3*3v8i)!=zhkN=1jA4w+Otg)kOesv(do25K2DJN@`v(S!`!NR8 zhZ_eGddCN<2G9Gl2iFIJOlC}Ajjc?0O(cymKW_}<4ZTFT#wf;3L|2DhL=eUr#B2l! zMs~&p2Z9eL46*jZ_Ko&h4d4zw$3%yXMbJlEhvLWSg{(#KhquQ|2Mx!UMjr*IMJ`2f z2e!m22TTRm#$E>J#cqXsfcfVIWQ&CKB$H(4C+CN6gOlQs(iiX*U>hSD!|%}dp_AdD zCXS@g1eZlx<{qcxNL4AE%Vx{3E4}7IM2Ex=BvZugGmRpQ($dnG6IoH5*v?`X3y<=Q z#EkBa5`F6=9j3&lb|;;p_Lu5X?v*K!MwOnCxDHGVQ4M4Zs1I|BgG-W&`IS?V{59w_ zM)%ulWLtz+@=J19{7~Tc0P~Q;kkqurT&_H~^oJ+7Da>|yPpz<;*ZjT0hJvvIZ>h)F z+}O=*q1diyzpTJq(QwkR9ie`H98v|SL)dmu{4n2O_FmVWnJe!rNGSv$op}w(+uYv_W1;T^U_TSrK2k{Ly{bv-fT1>Y(f}{a|1lWAAR8VJ~|>$N|>zr$dTE ztaFYdyc54OwsXAW$1du=<00)1?h#~1Ux!_XS;w5uvCpoLq0fTP?Q836{cGT>>#IG4 z41_ua8Du7eCZrYQJp?)=KjdSGb_heLQ)pO-QYd8TMhJb#k%WUJhJ=_To}{LPmE^r- zlBBmpccf!9Z$wIjVzg=GSX6ifcT}y+v@DKXvFx2Zfjpc{o4lqxlN_pix$K~9le}-r z;kV{Ari9#t-jq+tk;zsGD~V>!2K}~IL$-6$dJa{>3>9xdO`1dmNeDkEkW~{W-tVPCZGuzhYShtLa zLZpKQ$Op#uw5~NbIlHA(rO#94&OPec`YlW+!S-m;6S)-ZWjlfOF4f&#LO@3{7 z4VizNABP8nzr$66r;T68LBJ)^Ey^9wmCB9FwZ_5Fb;k|X<-{qp?Q5%{yYI!&{^8Ez zuG?CCy~dHH_E$@8!1nX$Rb349N0FKiG0tDPIz>yt;yE6&I2`;FVA z2l?x)M~l11>r1#EBo?Gr+#mQf=;=hQI0IN11RN*|cs9iA7(Q5q=&GpogmmbcxG!8W z)C^QMYy?=pu{ViDv33Y%up$YqP*-p~vCL3h=}&2N+1uD&NTevgbC`2u;p!2z6PDs= zVYK*SdNw_sDs`y(SiLSmG==;M>9<~8`dXVqg-5waT|lWrDJVxJs?gOuZP$$P5i@0zRDLVfgYXkS0oTlZX4VS;0)Pq-?oRT8bNYms+o07BO z{)>LDilN=6U6+!dDX3qdMenWHWM5<7J=uL>`(W!J(V!`%J|!;Y8n=r*M@nKcRO)0} zWJ*eMPV!pvqXr3GBHbc=6J1utNQGFXq1Kq@()vK#iKla$RO|QRL#=Ali(|%3z2_Fc z_2y1N?O}~HJ$IMk!^v%f-|e36@s}%G_|-?X%yuA%c8GJayRjONj=uq0{%;`9`2~@M zwBJwU8~mJ?#1F%DkmGd;^r(m;1>07lw(wS8$`#wI-&k+=&WDFDm@e1}>j@wEX!-Z} z-P;)2!}4H+%YRdy$DO~=ny$}njcw^|hA&}nwmi%~oiz9bzW=fanJUb)MbbuyL5f1& z#4W^=BjO`)!}a4WWSiys#ie^k0PtMCy=RTCt8>h_2B2R>uFE!#ZjUz6-j-imt(+WU zM_`At^RRzn_il)5s6FI3^g4t*Ix{r%%y@%)(|D@9fD8`}mAn{yU)rs`WM*aF@DP8c zI+>Vi3AE?lT~x?hTz8IUg5TG`K(v6roQIMFTs!7zT6(^J>9w7IaiBn6#o$Xh>Qe=^zeT5 zYzoL)YMBs^?~lFwy|om-9>3`C@w&|OAh5}IEwsXWFZlMtes$DhRL~taRX92M9tb%N zG6V^W0%9WK)eG84QxgbE)$>XXepOI*kPSk?wA&39Wv?E<7X{)HK*Rzu)PtZ6X8k#Q zm+(j)>nY77@N9r^fLP{-?33)c?5^yo?4c|uEp<8TiN-9{tRx!(n<$%JJwm-wy{i+Q z6Xwn58{HdTI2Sl$IEyH-DAK6QWP)U@WZY!IWTSEv^&xdybpv(&`IvdB`O$fUd47%< zjv)?O4rNO>E7V4+#`4CEMsF63 zA%gM6N&7+iwQ#@{z_Gw8!(#i9c34{Z1V9X-h=VTKW?9H^J8`3N^4RQH64*ysf3hF2 zy0TZ3%Am}`U`rqs!q@#$7-twgAJ6VzAMN-h7DEPxol20(lsZ*KQ8im-SLInHSaoKD zVRK`XYa?m%X2XBZK|^;0Q6+h1bVM?xJ52@Y+Bw@7uzPHL5c25Jl-4NssQa&} zQTxff@vWh5IuWXTnr&tkN)}27su6li#&p^z2?zNIB^h}dxiZn?SeC#aF+Y%_(7sCq zLh-#Dkz#wSZ7W(PB&sS z)qE9P2(uis9=3Ws0U?CUspM03EohV3fY<;PL=eR6#OVCwE8xrc#_(nZt_n^bEEWtY zt}AZcPuH(3#UN!TbuZOE6g1R3L^vd@xUX1~5tELVewu}q-o+K1!JE0ky2gdghRlB1 zEYhITGE$%3P~6nmQq{2DjMg00c-k^lx7ff`?`P5fb+PK83fJ6231M(fhu`hP6ZLg<(auLI@4X4B3PiglC6q$9KcB z!|-DUlSr4~kSLVQl;)B&mRyl&l0=u{mwp^j8G0H(816IeH?`Pp-9y{kG)n2n^mpYp zB!AZgqv+);*uxua3b0m-T#qb|w3huP%Q-szrG0-BBP=;Rxuu+~{Ghyh)@IggZs$a6 zE{#2z{glm-O^}_s0iyn)DbbnB`QAydcFr)qvn#VSVJTTTgE*&KKmXIT zzKj8m-qTN+(z5FG0-kb@(t*a}M<_t-IzDxYQVBW@RvFVUJu=gWO2MZYUD#TMT7jzi zTD)2;=>(9OiIFU8&M;2jru8Pu78X0mbuWLtGdF2MYlC;f5yCBg``=&JZM%oPn7fH| zFSR~uMB5806N>7dgcjen0rbcS#CP1++!|cyT+-b3f{k80i)1TKkEr)W$g)}wMn%Nh0*!+ZPsUz2T4a8XdCWcWnPJ1UH5$VlMl2HoPwc( z6Miq1TkRhg?9~>^P_59vpst~dpjyJJ!l}Z{!ii&gq@1J*iUN!1r(*Mv<0IoY@JsQh zGC|Nm(dm<@l8V$+)nezaPCBsDnfnZFCYQ&@$LXe;ryM6VCX*(qCy2Z6{GP82zDSh-W&ctb@(gwd2zmZ*6j#sYqHv4 zbt79argNmTvv$%b?cx3*9H|&7^ZoO4(H;JE%YglGcvm?6)l7(Nz>-o#zW94DYDZ^WyHb_um;O#i@A@b)4A__<$JRQ#zvI^K~Gy>>` zWE@D`E;v??pD45#4c9k`gkCelZKDjx_h0Z=iRp<0iR+}EqE2GJ#46MIP@CZ%KpZgB`O$e-2vmqx zh<`=;Du1eQDs<|LhlR(U>5^%e*(q$b4SVrBk7L?Z6kN(h)`id|>ki@0>+brF@vagf z8KDBf7{MJE%b14+HXXkThYJD#CEatsQ+EZp;*Rl%NsRd&GZ@n!6RuFDFr*Nv5TCAz zvJXQkfl`RYIu+B)(0AUaKOoTe8XTH5m`E91l4X{LIr+86E4C^29v+`D3ri0{4}Fb| zAF>_Kn*!kb5KpjAP(gr75KBPJJIcGjL(WU=z~ubN(aLGismZ~2=lkB`p3?sB{mmWG ztMuzHH+Q!_M+b+l+l;$8+rc-Hx6fA#SBy94*Yvm2H{7@WsGm_-&}6VZ=o~0UsE^6C zsd(r^=!;1(sOBjesm4ic$g*h#NPOtX7F1*sk-QUsf?*Vk+G6TQb#7oB-*5`r=r;RU* z$+Pq0cVQ>^>e(&am7IF)M=XzQ{-3+-Nx!1nT@RpXlQAYS4p&7~Ayh|IrB>}MDlNKK zwb(+~irMBai`i({%-NP+&|ENFR9q~cd!B<|@Sjf+s1vXem=jtNTo9ZQxMxdb7iL3c zUuPrc$ma-VWQ2&dwz{1Q{CHA=wI9KlyMWPT^}| zuB4ijw}kufw*j8P#$mL9)#2u$ouQQ>!L}&pg@@B3k9Cjsr)G#(2x#?r>b66tYW@U) z8TLBiNG@6uD~=3SUI9<4PQSdEx3t=8a;XD`_@#KZ_X0Nipn+X z7Av^2n**9lhUMb%*J#)FR+sn@_}lnb_?-Eb+p^og=gJ6_Ur?PQT^gRuT%4SnolKkv zUN~Q5`O*RI428}7eLg1H$1M86`@l7T3tQA+YjG)YJ}FIUL}@_Yt#B<4 zIZiae8V)xxaRy3OtDr1z2G6tYFRQP1x>heU@Tu64?CI>J?A8tD4Mon0&iA)2w>q~L z%x^|aMIN6$L`@2e6O36OIbY7Em+<8m<>&0b*%Ngi_~>27-5Jcb?>!1#rU|F};e3=` z)m@-3l~$NV9o%95K&!8BI{ndhrE_%KlR2+@i~Ycya+Z9Sfq#sjfDfHTl$F=a&}`n! z*_?MFbJ2M2bh)`|x=jBf_sZ!?Y%BcrO2bXu5GtY~`iT7o~{--nK zKw`w<^Wi4ytE76h)48BL3gHI7op(7Qap7oTet<#rbHgO)vpZ(|hr~zCQZ{}Q4T$Rv z2+lBQ{sOcJWJO&*hfswuGbHXP_{d`xNPRg}zKUr;n4e+b)0%?H{8=_X3)5FL9+1l* z{`U&G*Ob`S;@FSaMn|2{)+#Z5O;V;xlr)WqF}i^*4N|7PkB{gl{|wvKaV~vxe5MA( zw3VGGBe$Yry+}YU9#Z*T_?S z2WHn{9b|Nzfk}4CKW|W3Rf;PR5YSvJb!``IMFl=nds`;sFZL#8OdhrlKxq&V0S`W4 z(bmkxn8d@@#?G0~Ly+t*2|i%?&t+yZlD|Y;tOd!m6;(*Y?VZd>IGH$@SjdFnNJvNo zoW7XzsY*!wQyq9FNM`Bc;=squ?C$Q)NPgV08Ahb20W{ zv~wo^yOIBDN5ah6)XB=h#me4}RF-63XhpZ?HeM0a{K3 z_(AjcH?Ry!8Qg4snFj(Q0wOCRs_p@Lo&)WozvS99bq9suMc%WSH9%FNLT2VVmPjex ztiRtnKv_5Etuy+oJF$v_o}OM%$&rAcNtOV6G?j7m6ib5!t1ij}8WyF~)a&E%=e7t* zglHBiOb|deE&b-O3()0mv}V8M%z&%F24CvF=_!pwEW}V!QsOiv__)8&muBRr!^h9B zNEk2la@=^D`IRuLsk&P6a3afn^k(*?vEzCOe|C1(q-(9ivw^{&?Jn`z$@ho%qaCmJ zLsdCoQO|yYb1glOnAb@nj!2O2)xg)c(`K#N_UUcmjx0qka>6|6_GoJC;bKj3&VP^F zPu%Y$&2O|rQ_6kaG2HWQt@~~5CY0Hyw?oMNcXr2-;3aFV|1Gz_n%_0H|4hfCf7e|J z^Qh6sy%BOZ@!4SQ+iLCT*4xHbM(ywROQGAWy2CL)x0gGspMc-(4ff2>fLq~@+ne@o zKs&Z?m;0sR=)*!(6x_+l$Zp*-cTo0Qs-#cDlif7emK3CqvoM0jF>`+2qg zHJ>{HAgZN4&tpbi$9uwn2H~WS*Qt+=@Fz)ST?dz}F5#iT< zVFZ8o!|{xrrMI^?r;oQsd2jFbXN9AMcR?>Xsw8t>z~d#iQRk)aWs?8vus?xd)=q^F zHT&E8)LZuJ4)ObrWP{(C-d3XUOObHfaf7~nuFs9EPP?0JP3^?d+yS3miQ1FX+si!~ zTqxD+AhggGsPlTAHbdHYYq)y>H7TY%0j^o=7Y#nnf7IXR}6w&}Nf z_Ppnqj=NcTY{tD7zq6M8XrtF%$vm?y%dJ_V)SRxj3;Qud?)7iJ{D($@-6zfSvbDrr z@AtLQhPB7njBC<%Z6{REL)=}ghYxeN0lCO7vt6YCV@Jn2&%C#zrX@r6;e_i+y%o>< zr{|=+R|>%5tDxg<$nj5CwmGBML8BN?g!$XIW3S;#WkBLX+Dy_zXZ!Cq>$~Cp%lq}3 zCA<~qo-SWNaaEPgleaJH4G+i0?VxGApm_~`Q&;4}j_})@FlLT_{haz#f!9UF@Z~w* zk?tg5>%-4kzhUj-r#bGs4 zvj59m+IZ3M*g3C$tx>N3yJvZM`Ohz1*hW5|ga9j3Nd7{L&rgxmxh%scI~i0SteV}n zc6Ox$en??z+FFPL%pO5_CE$Vcu`|r=9#qO38hKr)4kLb8wl*T9tNt< z8P;M|aPSE-`(*oG#so;=6Bb_L{7z1MIfc|y32LOL)A*>J+6(YbouBBKnYp8<(SK}C zLk5f9Zl2vo<$fM&10`Pho=|&>YI1LG5ZanB2QB>6E3foG-ko<*D-BoY#rp9)<-f_n zn}$+J{Z@PZUO17L!(bZGudCmX&W$K45s{iq2e%WwDYO5$iCl-VxfMaUMvT5gHet$M)V*2mk{STM3snUMj^mThh-2!VT_v*VFgHzQ?K8@u?W^-~vFl-SEu4&3fyn_e1-4DfNJ{hm*PxZNVW+ z;RV@2t{m$2jRxD9EW6H`QA)m83=@sL zfQ_3c9g*K{))t5D$iwKl`-|4#7eV6Ijo%5x@c`ZU_7@fT_~@dudDHRZJ(~i+nM|+1 z+VpkEat^=yFKXfE(eo;&*C$6u9)kYMVXuN=N6gNKB%wP^RLOWqJ}cpAp~N%o8nV{h zq~vfVx~K90Hm}*e_Nd~Y1GWZnzsI~3a2Xx$?(ZXsj9mEl+jy7uQhxLQB%-h;o^{T6 z0L;8uebIC6epx>f;;vE2e-jJcm;sA2Y(EjoNA9l|7(z2?7~b-k#3m2b#!SE8(RIt4 ztchn^fd105<>&oSB>R!`i&vd~;p`kpPr}?w97WiL7t`T3=z9It+AI9c2W7{*3rdrQ_!5d zq>)WXOK|FVpaqPt%sNUn$iTrYOeb0s6IbSrQ4Sy>A!VM$X&L$6Ck}q~U$Xw}8^N1u zDR=|zW%wNb@r3N`ga7RL&}5e<{1hzAGCY{T@W*w10F{RH$3MjpMSoIt`YqgAEH<(& z`mDCx1s)#@eZM`eQ;NUzGR!#6F21dtt`5tX@kyyBlJ*07mGDth`Fk!pEYQ96V<8T+ zQ7V-`-%AgK`C zc-8N_u!3U#zAsd_2U~zFL7JJdD~tC3wCr9Kx?HtgU}uQAJ|EcVb$?3xm?PF$-_oKr zUpK$7V3y5G_uW$tq80p%89Q{)Sm71^pwgbtS0zfGhQQ5q(?uXa!-#qD8?;IQG10UUDW>9y>=lW z1}>tl`}kqzKBKB%yroXaMYV3?z-jcmViuDlnUa}?hRi2pt;Zuy>qQ**J&)ZJOH$22 zQ`;ms&o;w0gZo3qv~R*G&5CA*2j$3u8aB~`CiONeY|i?bqi*9(?|hi==o6JTcRQs* z`7=wak4?3fTY2MLv*9Q&-WR4`orOz^ZI=p%Jc+hh@0#{^4Z}&Nr(e~=iQ-+1GRKRT zT-%UzT__TWOsUCP_A9(Aj-r7v%W$~-s$_{48kq=#u-V<3(d#w9HOFrz%XP7!KwIXGL`!E^m&WxpIhfD(qC)m1%$`l(! zAf+^keP$qi(A9CTp@!AB0t3catu{q{p+6JypQGmvW}KJQ%?pR=vi1%(PsmpNT5UuB zxeXdfBCd+}vK4LOcabH03Oo}+U>GJATU^G`hg_h9ZUT!aXXQ0bVW2pKPR13k<3rE1 z1CvA5eOw0g5HtgZ^m>_RvS5Go03HsEDETPfn05y~q05yHDYZYT)FL_$xp=jn;LxX4 zU{?11o;eQqx1Qr7Te6f18?IY`9qnlvXVqW=yR1!NoVcd|MI-s^XvKmV_afCqw>?IA zpGg|J&y!LMGs!gGo40hk4*oj72lCTL0FtI?p1f_UEcH zDHnD|<%hH4OR-M3>q`%`5Q+Z{wZGGSEyhv+ggGl{>{+$3-c1fwmJj{b!T8;!w7J)! z%?Yy5)3yS4;23$Jb!yL%&?E0klXaTTM`^CtFN%ks=Ee?#vj5eu%r+f0i*=~>1X+2_ zlzx(VY;9TD$o+lxlm3zs?|vr7rj4wuY)$Pm?|+%@UpD+#p@)GK*ut_-U--n|aQ)Ap zfgP|a5fk{N^#Akizp)Oy1_}}8A$L>$7xw>y^#8U*^1nEd{O>IIe_<8`M#DmYfdbP5 z37=VLG%FX9qmQ=v{|USQxPG7*noQ|j;^>#+;$jIpdiuc&H|%<^Mah2xJtV0JX)_6q z4lHbk{Psu!`OWL?)L6M%>A-RXG|7e+!Bj!>B|sB1kWaf%QWedYw={-=uXj#Ky+f+pclx zwAgK2x%-Iz7j6AbUMe17?e3SU2JLR6gzoF4d2ip++#)|FBY^z@Ko6PU5cw zRs`E|^Naqbsn%DKL-V{;_|59)$2&lJs_*e1js9*^1PqemYQo-6t?N40{!c3906p(1 zgu$q*BcQ2)?jOu)5P-^u?u_Wld`<_lm@&rxXJqVR0b=JdpAW_UX096w5mGMYfLC7F z7%CA`HxAS;>i-UQ;Fvs6{NP}0^>4y~6AuuxG3KeqLc{qZjst1*?==AstDYDjW%HA# z|3vv~H2@Bf&0tsQ@s6oy?@Ie&@gvj9)A!pN;j1C4>= z;h(M`|AP|8VSvD~2W7yM{sq8D5)eHB(3>L)mP}x2M&c>=-((NOj_J=NOG{(6{u{6V zJFusMp^bcD>u-wnv8~e{KU(STXIH#3`9er;WN|k7o|B&`>#s=aHe1F+{vWDgga9=N z`uv6RZ#dI3fTv>!=?ls^JsIp4#dUR`yu7@MYipHN%aeHskjg7667SEJ#%4?8sST_c zu#%jQCS}#slI|WK$9j4Kis!8AR&2g^QOc*v*xFV<`3O0-ZzR>Yci_?v#7T#5{o^$M zxXupHl8gdsi!y)t2hc4rOyH-IIS)le2rHR8?-Dz%`rw^*2VnmsLkIR8uRR3n%_s1l zN2GFs_A|5I~gql@aj5(j$d zawN?4e@+1!hCj}5FuMBpWM@MDW3zC2>xtl=8iRHTd28!R$3Zt&*T~eD7q92}QXxuY zfvcX7CTcWT@;)~g7aY_FU{VXccF8&luI@Bh1KY;Ttc1a^Lz~NPon|bJIq%2j=s3_1 z*phjW{}b^zAjExjUljjAJpK>j!>OFgNj<>GCLzy(hw0jsE8wZBF0*h2k%Vay+?$^* z?7tbpv)t}pd%o79Y}ftfw$kO>UM8~!{N+C$*v|1x(U2|RsvkM)^83nuw4W5|0~vvj z_t}~VTW@~Mo6vCD}`BG%U_SIA zDj~;arC4T;8m%#4-jbP!%>MrH3uW4u6g6Is3@b&QfnwBBh9U<|05s!=C|~%(4p!C} zy<3`ew%w~M5B2MY2Rp?st8Ag*s0YMFWWN8(zz!`MbgFT~+ThoQ_{Uq=?r7D5u1#UN ze0+vr;>ADRqW{@m{GF8s$o~8On^dwFivS;k33>=dIc@s*K%ewsxwX~K20r!A-yQ=R`F3R-Yf?1GPqo>wjb7`;Kx%@ zqD^NlCvPT+W!Fco9kCqf{%+7ZYpWdLTwbCKd}oSu;gm0KUx85)7d!Vbse)4^i`#{B zOqob3jN+p$uR^cwW?;tX4J3li7fg6ZioA0bX?2R~cB?DjLYxtYEVWYf>W?HwawA`t zJ;Q~4Y?kMnr?!fiLRX@*Db1(X7b2-MPU(L^3U(6vBI-G6x-~);{Pm-;qMT<;>e>umdaLq) z*H;+bvi}UZfu$0hpiisEZeVZ$&i&`ZO0O=P3IWFdO)InFfr}>GdXq za5KA3hz1H3DgfXbW1`ib*mEB>sden~QQpz`sb(c@qH z1i-D3tRG#KW?`TGG5RE6Ol$~{7@~O$+-NJWZE!M6`VE!dMu`cGp3i*NN|8 zqC#>7FT@%2i_ukw(EKEkQ-Irw*d+J~rWh5*d&kgLt|;Hzb{{u~fgxGMq1Hq1>t=_5y;CkEzEK0lTJInyHa8%5}aOV&?moAJVD?@1Nj_ z_AaL9kQtW9-(OO8?X^jf{2?K(og4yjDs3IxV#J$OOiCP)sdiD0UHN-C3Gu#J8c{cE zWQFvwLR@#@nEb@jvT8y-x^S?f!^ezSAkCT^jk!n;!RJ8@MF|l444LKfMdd|LN#1CT zwqYD2RWGJXLx_0TZa&ZPWgw{S;u=4?HS6yrm63ZC7~1s90CDYHp$Nl?cvTlt%-T14n#@?@m9jK(9E>1 zy+{xF$StFv$6#R_bN#d;2rtvaQ>IO035Nw3DQ{C{toogt8D!RGkY}(7X}DU=hWV%r zWTBk>R(R5mpCR~J?(RrMH(I%OwmF8w#0ZF~f;@I!n1iRatSHhaECb6$2urc}R|BVY zH3g1a$h3N6l)RYcxkCGn0miqwTlh+!OM)t&l?Jtv)mcc&K@7w1Nhy`?j&HjVm!jSG zpz25qsuvNf4j#x4v_lT!!qGB=>mO1mWPI4+QoRqIT1XOiH)zHEQ*zF=6LrCIDU zZ!D1{K)F}Y>k%vhqmVd(bsGUpEb|3RQb z{#I*p5sE&#fyKb;8iUXsHusC7Y76>HGF+`2PgoPOrFVX2R3(<(M%43nM!QxwX=R-{ z0R#&ZqcfdIw;c90*_IT}WqPiNIb4_`yxg8376i?R^y@-8SWGM8EM!ufpBUoX^A0d^ z@WXdAW9jGKM7j(6NegqJ#-$vB9J1^YSxxMiyd3$3?2Y2nc()JFn6XU=nhg>~yA0IjHg{Cj7OeGsLb`Qnkx`&aTVh?s@`s<#L zTE_*}wSBjS{_RmT;?jsFH_?yD-AJ)>hD{zDyua48JuE<1>Zf@!X+|B9j#!Y;-vWAo zWIx`z$6l;cKO(n`xOnjV(o$BjQCp4o!+C%ww7zqlx;h^X(2u3)UM zU%6Z{+SPb$jcMTu2LU!@)(+hAe(uBWB0(0sn}%pI5H#W@zD#K`5@gO%40hPq0qY!R zthB30!_@m)o14-arkknBtqq3^!;~BmWyoj|gU;aj{^QH)RSyYaN`->NIo)Yb3HQF6 z=rQPez(Jg`-jPp9F%`%N76`qspO$CY2cWKDyrYY=}rRdF}ibVWP&A*nhKeRB)_ZxjA}cBRG*R^ukL>kT z>99`FLr;NTw^S6CJ)8IraB>YmLf179nk=gAoy9Rm#OtTSshR`-gXCT?1woqpXv*VL zc91@hi4@fdh*75!R}J$s70+tgkR7j_>=$aE`Z21`jJ{Qfs5<}SS4hfLvL>P}c_Vev z8nHn5X?$n)8Be=%M0>5QToo>DT|ijWB+aLB;=p_qhm;W!$6y)6m&JNT z)nB7u^O(-4N6Mo!f;aI6GKT*ZF-=#>$WyIrD?I zCewumbSQ3IM55iEdIUMcDsj=mn38(4;sEFnp^$SZ>~mtQ_B-qe@GP%#{jL=Z?Ce=L zWD}V7_0Py$mfcbP&b)Ew4j&6|N~Q+i9c+TU`6Iqj^d7oX__%d1Urm>?36YeX{D@qu ztn*eh`n1C#oi}5;F}*nS9_Y0|Nz}t?4??+{M_pHexm#nzs3E^3OWPN^9f{Ce#K~s5U4{@Wo*rpAQT9g8KN?i(%fEw@S&2M+h2<5|&hbij&S~b<9CO z#KDrDp3ogv?H%oc#C{vl7ySnw-Hk6b_X*`viY7sdaS;4XYWJpATxgaE#*Qa0Tz_=jj z`_gF11CFVu5wX$cdKMy9HCaS<{v|})wc9)?%IxF&T_M3-Bs#Uk-qhEQl_|f6hMVnR zWJAw%$giTebws=!=wjzTK_iGX$p>nFmKbVos%Yg?Diq2r&&rk^xh>C!u$ z#3P_KlER>xpor7ywxA!nw^p_fV4|iT_bYm#6i*o=O-j98~VGhEY^~-3~%-qlrM~R zAgcwoR_OGr`I2jB!QvcyJwFr?1Y7!T4}-?kB^PLRzfmoa!h%kP*&Z@gOTvWcMjG>e zGAhxQJ9FqaV8(?}gpJUOuqOHaIjuD)CvkdbA18=FtHs_01&$$vwiT^2!ul*6<}i?c zMq%#`5_6WrSPi2;qu;?+%3F6jwOHHLK;C*fl~1;}95Zd*7SG zrfcQ{1#_dMfrlfHlSWltg*e)oT2M2Fs5+O}G>;PB0g-t9cN%@aok?e^>=4czoUhSr z;s&_>oXhGm6~$0w17MEHMRu-6=1Z=YvBR%gq5UGv`oE63Rn8?}rlJwo29c=E@%)RH zCt*WsMtV>!Me`hu0be6cHcYl-Ql#|I9QLrHp>3+3lvRI2`R7w2 zY`@?h_i)V`e;mhemlV+13~GE1E*#z7_E3asr>ybCF)0^Er|k7TV;FWDehHg_?sM3A zslXlu)o=(c2PSE?$@zdVm?p@=#q);<6CZ9W^zY?9U!ad5l|H zZ2ac#ox-(W7opxys!I>)IXiT(Dv+wN?A6ysY7Ta#UQ^NNOdi-T%5ZNCaH*MB4Ao?` z*{{C_!}oIM_9XKpN1`2@%RO;|-%Nj;2}H47hKwv)5lQg~I+T*%g%ARMKmrUJWdOdh zPdm$tg{(=jC_;vBI-5xu)clv6SKKRenK!1@~=rE**b`f)4?xm@tw3M zx6;K`myO8~s{_=uj{Qq3)}k9&X%dxMa*b})Ur02UIrexYsPx7}dDN$5IM-{f%f_JGq=@#Sc_Cj$NAi{TQkSz3)5yYUoM`esk)?EDKP1VD`eWlbnP zMQj^+XY0(lZQ|@EyDHx_1xzN1qyx%>m0pz{tQJE8&g!n7N9R1_7KvFCd~6w)p??gS zW-b*6zJzvQV3NIDv18tR82@yxTU~#GnYf-8q2z2>^8g)ov~w?1Z@MQr2{lP#%6+bw z_x4bzN2M)nKkqvDZ&Cl?9TR(P>f7nmiqJ|@qOTou>ysJ>L?Vd{ihPUyK4}Q~^C4>` zP_~YxCi&?J0Sn|8pV4VVJpw582Ee&eZh!cmVZ|Qp%o|!uOvgD7OUQqJ4uFyKY}ERy zO6n*A6Cdc;qr;Fhcx#sbrQivrbdlS>BqYnRKTb%KZ`x*6ExYHnj1_99bK-ZJoqY-q zmW{;9=K+1p-<``+@3~34@eh&2zEIXozT0fuG^q{~c#-+bsEIvs(BMDN zmkom>56~>8cPat~;Vb|h`}y+}C?6R5yT?fzxnF;jqvOA5twd!N7lVqy4R|P?b7__G z?4G#wUvE`20U7`lajK#3l{N$(4v8Yf_yb+5JC#Wy&uFybd9-?d!5AsYMV9Fi1Zx-q zisOdo{L)aUpILdO+Z_K)yu7VC(l2EW|a!xM3a z?08b7wFGQY!Wu4NIatFp?};Q3Ezip&VYWd{^)H9FTV3M6hVwDV#2xkf9U$kuqeClYYFL? zp&JH@ zQNiFPu2d+>?8)Ls_T@7jRiwR$lX)Q*tWS_UI$W?8Pf6q^)irVnKs$}5RM-7VS3KR6r#5*k2g(WbDOoB##fRaZ zZl5<_hwhbg&AdS6r3JR@E0{5xWxUfKLq;#kB!Vn3#X0n2l2*}<{<3Pv->3fc6yFnG zNk)nNTb0O-Y1?)26L8RQx%ja1Sf!Wo-IP-;mrkPsp#kG0b1Fp~iKexN^tXr`on@PF zn=i;PvA{x3!&bYy3{O|M;r8Z}ogp_Ww-Iw{81IoO5bl`ZCHU6M&Oddd#A&iCyEoY} z&P{2q44dx`S1S8Oqh zDW{ub0qRN=o(R6gM$s~RRCC3)=-UVfT;x!9x8BZN`7i-adrur2)BT{`2>)rM!LnJ$ zauXGz`D{q!jRAIbmFsS=LV{%ViJ8pZz$(-!^%D=yN_3alj2o#QNw$l}kcAva>&*_CRHlna>le_8) zH-Y8pxng0je8Urw5{#-AO)I`qSE8~7oJqGNk=APAQ+@YX2j--|7oFdXO$e32!Iu?y zn?rpQc3~-;$RBpc9hN=PC_gqtmx@x0Y-hYq>!QV{)M)hfX*m$XUaM8Ap#`3#QUDc@zhl8k0>F6@o{9CSo zej}lins^cDJxER?dkwsH+sDTQ5^lOhwkcMVBGxG{fG0+Tcp!FU2Cf>QK%Bu>c(HT@ zI+SX#NrwLmBNZ!wm#exF*xsDi>K^7$i7WTCM&Zg3NM!c6OwX1t zS+m0C2TukgBEekV$TthX9udkO%~Vy8K=s4X$U7*ZcT|t2WAMN2xi1I%>^yB` z1kbYKOm@l29u0YFPm1Eg_`<|)pNz@M2&amD#?1WiJd!7evef<5FKy96LANS~IkqsC z5E?3XUPVaW((5{IHwG7oQg$dxVrlr~ohwQwk$~PG*IK>CB|sj!RpB5$%od& z=~d@es=%J9dLBEj8=hSt^dhuH)SzBLY=*q@a>=gym3R``4I|%I#!lwTce)fIeLOR0 zNHid1I`@hseH-)vKB$p{C&+@;Oyc|y9;OSkD%CF%*{GLS$A!DVZx>(U2(s^X%bjdt z^Ip=yOF$e001CQTuwh{NdMZuh;Ig;oh+GX+hEnL%_L!|~Yd}2a!kf~T$JueWM&Z^B zo@^FkoQiD}Ly0FoP12~e-JHoj>#;x8}((y^bU&y3+V)nQ+rS=juL z!7QF5>hl>&`GS2pQ-Mk229hr?9IFoc9ZLLw&E!jkyom|ebHCrlMCKMs7B8!AE8(55 z%ZofYZPjb*QCLhz`=Ul3OL`NH?nHCaEg}h$Aj{3^w;QFUoH{Ch zh5nf@)in&yONI`fe9c3(T*zNRJ61)AQWiwqZlG<%l?L$uR#fdJ?05T(sex);u}(cw zz!OFcfeN@=CiP$7UpQ;c`G|s^4*C=7UCBxz{5}kBaGJ|WB)IGgsN{o>#N)0$?k4rV zy=`vwqj+kMU5fLvV&c8lmegHvhsuNo#V>EyNe#YwN3n}&16`eVZT`M!I8H8`79oK(fXiD%{ifhL26cT&iiidYgf(`GHtGp!?fO`2XogJ+bpXoV_V~W8 z8$c0`(A&G2Oaj?;#cxw2QZL|-u3cKN248{3ENx|xjE_Dk$*7msq!j;9mhZ!)5{Yo{ zfrro9M07UD-nOj7e?`vOg!lIuf>-%=jo|SENT1U;Z8#G-|2#*V7c7+U2by{%MI^od z(&rNAGOfrO{D8tV6W)nstu^yZ44WAX_R+PtUgaO@;4gg^lOTx46k~@0-rV=8-eI2W znfng(Id$hy$9`Fkx{j?XY9eOBcI9x}n`g8)3xhlP{wKWjPKFhET+yF6;Q4{=rutAP zv1$A)pe&)j&x<=J+=lP3L=qG=I>~63!mPVb2kvwygS2A-;k|(@<+MK{`bX`qayHIy+y(de zf}KN6wewO)UO2b(05d}n_8r!oDDwvPtB})q4xX@`9r>P>1cObL)z5D5`y&^rxK@~L z|5MUN%0d8#)r(L)tw<9VJ*W~kGj2md`6gZhotGn(bI(*8qi$F#du9>Vh+C_s4d5fP zQ@M_23@HdNcB7a0MdLhK16yo1TnTzd7M;eE_~&V&EoZ+gU*>x|lIs9wbE5?Q4~c`) zgXEY+5(ifo9~g{nbb3qQM)ADTlOcC=YvQE%Xt10ja|)WX!;BrxSw|^2^4oJg5?QeU ziM+^27{*F!uDIcQdNEA5k^v}YzUfJ6A11J> z$@U^Cf9#%IP6X5QT@mMSK9lP{5q`4)ftl`tq2X^O%AkUXv}Z_Mtd0)?EBlGD*AU1z zdd!^3YJEB~!4H%os4X@nq;A3O6pXmh4WzJFovt}d_4&iv-9SjZ^s|E&o6aW4%>tcs z*`|ehkropyxWZu_c|OSAGdx{?yXoFFzB%5&vUVaqjuxM=@c}O^j^vweL@H7mky&nA zpuh)`uoc8L_DWhQnM}w<`rKF+Ut>QN^PpXvXlY+~AV&082eWHf;`COO+#KZzP_1IV zUd85tS4->FXOtqd+_MKNQ?*C~j5DF%=3-_&K+B8>x&hHj5>>ZV-BWt6rh#EQ>}QV6XmX(M78c#5N}mo7-@;KoXBhcIjGI5eQMet zR}#@QT1$xA$kB^bKu>jj-nkGAjI&&QYcduT z`zu*g2Hi4nRYY!FI{;dIf4r>YOidu^hAXlkXp)2oZ{lZOW8ikIqcwJ3@V2{tQLr^? zhI#b4jdFLhl1;a0B`~VAZ7HB!?q0939@QeyAk5`tps(12Ku$S)%hZ|gSjYB5Z1bNR zRxP_M6#_I~AKULTw zUf<(cQMkL2LD%K2uX2)_*E#+UNo~(xyV1cvJLV$T1AmG3kL;}f$bJQasAoXPO|rly z8CPx+gU)9JJ81`pi-p!_14&N++ntTiF+fb&plX%%H@S>iRDfj13=`=EXXrw#5y2iK>t&lO-`X*Q&`>c(S&~^brm$N>U+qHOrV= z=RU}9-RIHy>~RjY1}7)#Yk6DMi(OT#)P$ZeJ5vO@G=vp1WlXzbDquKhBS&|k(|>GM zxQUlcp1dG}@ZFK(gY=VUC5!P47qWGFp==>{#rv%>pB$AIP_*nbe0d535DcHFrLg;) zZBW{rORIFUh6Am(8%?h_j!Km*Mgk9p&$N*)QjZ$OY$q z6uRl)^G%}Mm`}!<#0kFAP|5PZsjxuxJ{Zo1^^6r|DucZbYDD4JJO14WC)<9Z4|vVl zQ@EGDrq}MQCT_(7X2I=Ouq3lMy&~Ls>|Im3iY}%=Eh!uM!PI4E;`IRy*POYx))&ZG zouXo#S5?JSW2n}qg!<&W2VE`dx5l1Rl_*U|o0mDRPepInTJ@Nb=XCM0dC zV5eRY#nMvjOARWqbjqUNL1vh-3ei^%R2z<;`2>$bqV&FAHS2)KD5RlJi3L{y0urNH zDw7GOrDPyjE^d~El*WQUYbXCZ0UXWMjT{$>LL-GW7J10=`UQPKt0y@RozEQoT665c zJ395{NWRUIUE!HL#eLsf^r>H+KPZJ8{7)gLPHW(PvF04WQ^Glqr>_tI;OTn=$oe0D zSnn@mcVy@)d{jf)rup^03=S9P!Ru87vl4z9VbQOf@XaI^TQ%XE=$mk{H?ZpCvmR=l z_)T3lw8l-@`;|`~4G76PL!0wbqY8rk2+fXE(J5?3agNK(Bw-D8*hJ{2>)b|3AgkXS z0sbXw7gYdkrK5U4yG^Ldg5W!I?`@#{(nC=R2>yjugfXMgYZ6rl2)9k>C9WFwS#d4$ zBZUmnp~{k`p2dGN*3Zhz%pQQx;Or#0s2t23LS)oc$G>nvWhms;I{_;;iV+GIr)JLh z>`@u*fMu%1x!%L_V38DOUra^_r>ryh6j90Ixf(nl@WsWGMO^c9l-b61{z=H2dCW9o>(4db)xK3l3g&C+zu{-x;)^E7zEWYbey^B#S3mCD(p^| zZJlqOopu_9yK?8t-NX+(pDR2Lv?^X6!#in9%6#ppbKE_>Q=~S9uCPfLr6-4hBTE+F z=j+fq<_R)XdSds`FDJ=~_v`1AEj>Ko%~nn7gO~)~c^^nDM5MtDo{+#GdD(gg98|%k z;knLPCwRDSDZ!7qXzLUSs##;gHKhdv_r=~)dJ@k8qTiE6hrjuGE?n~PX*Z$gdCTNj8M<72)Dw(~u-D}xwimn&5w$cRn=R_5eg0t!&imj)#hy|ziy)XukfMUn*OJu+L5Ds9p?ll z^(q|{`1ml;Eax+K-9m|YvTPHA^0oAxm^^5xFP7Zrlq1ZOUe{w$mAM+liwokd{`!5; zCbIXlXH0~t($PHIXwQ7N3{ z7%DVu7rzTH1id1YiV&fetkG1UToG9!5laon>DL_V>>MzyJ-Iv(&_j2oa@G%Yid@#1 z*Xbvv4ieW(8xWtp0B^=mi+o^(zFs2X!~@H_6-n?5zKzziN{M(<$+d&JKnb!FH?nAU zBXI<7v$ZfJG7%(gZbC)9%h@5g5-fVmEL%ddWHZMl!p9Uz3rJZtgpOyJafRpX4(9XV zh#=0s6S)B4$r5X^>OE#TCz(|0)IU20@$(d*V zhA+W#zuX+tSvi6On}}qLS!jR_d?b)@oW9Sp5aKnT?X2u?@h$c_)eho2)j*`zXLEn# zuoFortUaD*-~8he&acbbL6n`@D)kDK1XG7E=SvfcS_^f8)<&Wsla#H^xJCJUi%e#6 z0x`DzScF_Mhf{#3UJ+v1c2jUum23=s$2sHr&6Xs39Hd%X*BXaj03A+vl=#p0d4JXt z9ju9c$5AFeNd6YsU1&s|8NS(4BTIOLW(`OdA;cVHll+-X1lrFACJS=FIo=_#Yf-}I zvPZ4S4kCGkm??tX7%}z|nwTbadG!dL?W^aXaETYclObLIux+3)cUaeLQQLkZ>hVkT z%}1#>)8^Ray;x=|2+!Su=wy~n4V>kr@CX#P@0Imc!W~{vq|r^;g=VK5pfx){SS=40 znf<*Da5MKSVam^M2xzLipK|D835_tf!GPJ~$v^|~3NbH6ZhM}yCY=w5)R~~Az)bk7 z`~h10`Y>a(s(CuaLqAsYupDr!&TLF2BmxNBaGtK--u%L(()Tpy*?sInaX4V9BbCdN z#X3SnnR6lJCt6%-HOZ+obM}l3Y2;pEOeVccw_U8m`=^^&$>UVdH_)pLW2B*+=50E+ z=cAJ(1@;rk{+u8njzrRX&X|GDRLOfiII6t3G=?fk>wzq`OZr~#IMYm6?8r5SI$F-?~dZc7yvysN^e<6z7&%1ZvcI8b0fLUL%Gd zRDGhI3`o^_R`bpg*erzWZGv0FYI`^jCc6IwtnIji7aN; zqJMP^irJ_m#uuE`I8?wuCiYxaRzIBcso&6tvIhKo@3!(fwPB;{&dP}O<>fkazwnyf z$}n5}L>YqH=D0-Ri2Xlqn=}{Vy4E9QbJr+d+K|TpNr*~Om&&ZCGR+{;fLL4btsx^< zMV0HRux`XGn*Zqwi$0P)%RB-y!%|3X6v7+aaQn-FivV8r7o+Ivrf<-^Qsg>9SSJ?m zxIO4XyZp$XCUHS8P_7V@t+QcM0z0`L+ZstxW7QT z!bE+#2CXrb<=NVn{#gOn4J^SlU4nlRQ#Y-cgEZx*UJ; z;(&0ee1XTls=0aPr2_)03&NcdV9Wrd0X3-*X#{@_Agp*$}1}%t8Tk-Lq z=BCOzE)7jBgFEfw^ywD0$QyDz{z)!FhY7y^q!{-v$b6N{&Hjg?lw?XHM5|g(jc7BTaNxxbHJ*9%^6G7OJ zHz1UZa$4IQBrXzFJf~yI5EOsJw&wNAbtsCpKWu#Qt9Q4yurr#1!hZgb0B;r?**kG) zcU39s$rgR1n5|uuchy^%5dyN|2$IVGZ?2P!jv&GM_H1jZSaBeGm_Q{KSp5qW?2ttu zHD2tg0N)qed2u^!$5~j(tK}DJ(hN!t>cMzYOGa| z83Y$OjwYP__yQJFP+9bPGP3YIiXC;z5hG-yR+tfk)S0Zvb_cHFwk_Nb5SxV^C|V#9 zOZ|FVG?=8e!_v!jBzN>2T6MrPyYR8=a4rtt8ee=UIGIAas6G@a%~5?BAQqSX2|-pY zs+c{NH4b-A+fmzYY6FnYJ&mp-X87Eg4Y$4)aGi0{sECr64Xf+q3X}>mfk26?3Z8u* zPdmG0D5QeBVJoKFzr{r;1sCgy7tkI>r!fd^ZyprT%^b=~kUc7UWKRqUc2_jf#EWFo z26;`J10ddJ6a`H;Gp19w-;=;WuL|@dmrGU-ftUW03@4_+B+fJ0U;xeghaRmG@5}A2 zeNoO?6`YUZ+f9o`+;@qP4-r15z}Hy<4dx693E)hZtgD0eetz0b?8?Ig46%L<{_jUB z8W-W}^C*LsStqMn(9->o88GtJXWfZn&f_%-R(x4yye3TXPP-U|EnG@)^8pvkX2I?m zWcnS>uFc#R{C|>KI$nPiS0el1ILG>UsyYz||1x8Y`wi;*?q$RjRA2lhq#f z>`H?Svq2w#3&ML1aMqshjnw`1R*Mq-d&z3nJ4dW}is3HF{p$OcyNo6;b;bdL;d#&{?0)NgFus0uVmSAx-Q<~oXA6Tz}u=yMHph*q4mV< zpe6d+qq&-`Sy!~;?GcNzdw^p6f=uHgyi8)6#jwDLP3o+|?bo{!^X-VZR&@=Ek0w|! z8^~t#KV@9}Uu9gg%tCHeK~F9T1pm!YzU`NxYiwCZ`wT2tTuS|+E~t5TN7CN!mkI{V zzm$H8^`+};9}wJ+4*o8F?L$PwW;|}b1bF{@AH@C{vheF9@Uio-bU@Q!_?EIf*t}Dp z4+?USTR>j!#oemyNfv1hKO1MuKem6@!yZYwscc(}IzgQ&KWz=mS2Fc`2aaqm5lG}* zDpCMQ8M0+TpJH}4a(+4J-{R!TYi1W-M!SEs$!HbAESYBAcXCS4Z~nL?b()$^8*Cw4 zOJMKPD#HhW9A<8Zu6Hob6Xkx*X=e-pn{P5GG2$pyIGoadxc|*ux`QVI;Y?FE^O7-} zExe<^vjWsEh@3qIx3wp$M2w!Qg<^z-)o@OY4Co9#PwJR6eu+Xmbz0;I zg2E__3?t1L0=~lp1>CZ*;B0*OT@BM<6tzZgI+ZNqO?)Anp$Ap)w}Vu9+j7hlfLIdZ z=ZBOI<@roJyDH_3d_{IANO#3CevjC^nSzNgWgV8oKH4(+{iYW21#%&)j0re~IpaUn zEUOpsI!%|fXw*g$ZFoFNQ~xP*#SrB+i<+0zwFdY%30a9D1(KY*TEE}DFlRK7TnxCR z2OpXE48J;g_Q~ko+7(h1>^SYrt|h&fQwJ3^=YKdj4v@w{O@G0`5o2eJrq#tN;U5g1 z3Q(?01+i)>G3LUQ7Y@?Lmf9IVey2H|$NVTtnUCo6*pS&)#hRM3BNV}`%_e3kGzmG@6j5f^^#-Ev+@M39tfhtbZs zK@y18QObAW{A8Ahg$Cog^qxtbH#ZY1DOfO4CQsxK41zO3CTLp68SI`&;a;kJ zI~$)TN`I1Dgu>lHHxVGjD`DjT0JS(-{Br6Eo70%tw z@wfA};OJ$gdsW@<%r9H@v5SUl;hKr2nsgX(+pEljRyYR_qi(tA4SpM=s1d&ekR|$k zzY#r9H zdo=)?aF7)P<{}xW`i1s~;BcF2l|Iy*9sxXkhJ}uw!A!q&-?z%s!874E{g(Ri3${|x zJ`PE^6IH_R>!Zk+U-PYSe@^t6^8fQb!hflx!a0U$9t2Z-w)L4_GJkxNpbEDSnS1%E zWG=s*CKk+r&`zzf#oTX#Dm}E!W+0&|(ahy#xDVT5|K>%E#xfsDA5ygS>7%_uPcHa9 zKGM0hmEF8I_-bUHQRFLUxMp`NiBqy~i#R=TRm=GB`Ijc$aPCeHl!;q;0T~12uu^oG z8N1|}wV9N9IEvuvPH^n6sW#QsxZwzuyFwHPNsU$ju~5^PB|#A)j8Gk?x6jUExC%_&Yoas$jF% z+ph-lGKsimctj8mP{f;Xu(R=T3atqr5n- z(B&%GBZqZLvIQ>PnEU(zGmKEeB260nTu}r31Hm1ASMTTDK7O!KDHrd{HT8Gw_U$G z&NySvbCrrz<9tY~vnrQq(o&nmYAad=rzx#AKJAu13~H%RX&NRd96WE*9g#w?Iiu`E zk1=<>wi^|y7lvX8%bYzk{pLa6+q)MKWILh!jG~13Vn@IaG@{$ttLiKd)y8JLNKFwh zoK4J)mHwZ>^YrjAg)qK}1B0?`A?c9LRAk%C(1A%@dd2F2*x9eZrM0tYn)I_vDJywL zLJy;5zepxgNFBh3EAxM7)JhfM&Y_7(YReQFgE^)En!_mF$Cj;TIuu<)5oU=n7J;;^ zwGd&plb9oyU0&r(oh>1RINv!>8Ig65xYMSn3sO@}rM!ka{)BQdM2ghFe!d59^R{Xt zgn#13p7~2-3W1xD-o(WaAnj{YfizDlrx+z!yJ*`APOoUp1lMb`PYe{FvmO&`o+uO# z&g{~MqK<%a3Vv&j#+>~kE`D?CjNfs578N7LxW*2m40bD{7>B@VOhT`(C&W1vgjchT z0+I?5OS^xqL~zLrV>?kdvsD3clI*=-!j22%8$Rys^Ajj4MPIe>w0gl7obO5&=GR!g$`2d*l?$Apv$)GQcY}4O`^X`BI%p|Il*{DSl+s7@1Sr7WWx z#$5`rbVEzAadp}LS+b6wg`crMI_$LK{Pll9tEfI(V&Wl1*j8XU8>CO8)4}gw3<0Zz zF&K$yKAi@RzWBA8g#`;7TuaVG1e_Q-kT%sR^f>GLCHKxQGr7&?+8n*E1i59Q?ZW-u4DQ^8b71-J$Ct84!P{@GxK8lMf<^W}6u zlbR!|j){ortK?c4J%;B6^l{}+!frqToY2i*Av{ zwzs=l!$xltWshE>jU7C823QEkA4eIU1_A<~tR6EWh#ms@4mak80os2&$AB^Wjbq&) z#s#J)cj;XHH<<`vk%!mYHX#*vX0k?pWDKYt9yiLh)0?=Gieq4kG;Man-vEJdJD^_4leGtFqTS>vRw{%UDCt0IwQcG!d*sOFwR{!DM&1}AY>w+_#6iWy*>72J@ z4#FrsFyw@%Bdmb0K6w;DARWciFBs10ZbR|vTIio;sU!-Xg_QxY^K3lrvZDb6UXkm5 zYGF`PN?F#HJzzoL5C$A0=Dk+E-T1dpB@w!ZqPi1i$H_YK zWkv@$`jPp$i_0x{fwdpKAbG(mNx-N!Mf=W^FZiy8&&42!SGSJjtHk-6R^$ zBreXGEL%qxQa8E3C2l&1*6S5wU6x*>df@k}EQ|t+tfCNvHGZ7jIEKf&X%a*aFx@*q znCIS5jX!7OjREl5Ul9@sZ)nf6&M=wNMvQ}x$0 zZ@pI&KTTlGW3OVUeZ8KoduwKJpnLALLZ{H;OgM2c8~Hq#Lr$CTG$Okd26$Ctkz~Aj z(mNB3JChnS$T+*seZVy*0t>G@BKq;ibF2N{&yDjr{g+7Ws8p|U9_;`BpF(~7} z-{P@g+<6&uK-r^A|EwWJ446>6fg`}?r&82LuHBmfY03GN!;}kg zz`!lcomT2evK-FNiT{GXr^v&v|21vwf15U9ZuV}HzelzZjfN_RI2cajv!C0TPvZ_J z=>t~9vg%U1WXd8Jna#IC+*GQiP5@G=e|@Jcpw)3OxXtgw_jrx$iD|9^dy`V(ZM zpL?TIH`6Z4dn?u|#?(Wy-O`mVH&FextDo@h?%3TSFaiB=$(y@6QAjtJP>WhDfOf9M zH|?s~QRZl})aZ0+e7vlRU&ssLC`CcpkAyU*qh|v-GU>2@EgbWAO(E{}sGgBN8dCA# zA_f5ENC{G)&{GV=Ll~~sPipsyK=AJyRhFV6jawW)`Nuf61{N;lxxz)A`l3=1ceu3$ zL5M;bo(fMWsp+sdaK5XbL9|14H$NYZ??N4Nr3<1i7O$OR@+Ii<_2oNCXLbE<%HhGk zs1jj#NJ|lz(qXkH4-;$tS52PzcMr5+Fe);9Z5eyn=Ld0}h(EK&(oy4`&7(QZ4(Yu;kEM2!sb`lymIv6UbDp&~eZjq_ zE#6j*uNZ8bl#Pd>UOuk0&n|Co>(F<45p|*u*Z7 zM~oLfzSooNCkjW@#oLi!R~zIuBG^3!vQ+GXhbr7l(=KjexW#Jr?%bG(elFcwzOAv! z`@)y&C|WOO;p8I*IlnyI(4M~8@orieZP51L%~S~LhNDzyS8)MoDv;tS61pQjcs$24 z(*D@PeK+R$I~A6@j%Q_D$uVE!d^@53;;uozV+@&vBqo@0q-t^qU>X`Gt2*Y@8FAS{ z$V9N|s7&g#|9Ok8$RYl{1TeMJBPmEH(Hp+(L+h{}hI+pL)^kp8=rq&x#({H;gjLE) z(^-fA>Hd9hC**36STq_5yw_g`O*JTtcBv0Mn7lWrqssaE(_wkr>peAbRUu=oh`5w`F28;vc+ z-NzzK?V5$|S5%I?v}PJfz3qE43$Y{C?6o1E=@170`_O)XTRi=NtJUpj-Nx;XUiRon za!Vk4HM^m5;KC=KjI4e8ezQ>lzR19rq@?*}{IIZvb+czoUngN;>Av6lIOS_et*I2EK>hF^UE}Dod@J z|2_m~%7*wGxyNw$!z8;W`J?ArP8HtP=<{;-d3}ICZl+^xR6iTN;gSLHu)ChLRw5V( z^rxZuhOFb|(b=o9Zua{VFr77i{K>xa!hVFFc_i8})#rn0=jdZBQO7v!afx=NkjiB9z4c zkiLZZR#?DL4A{MU?M7M`zo}f`z7UAjHX@bHGj}~+jgDEBqVrfYBND&QW`bzEEamzB zjq%%($o^Xf#A-dNpAkH+Ht%m#czAWBqB<)hHh69qD+Zc30(Fvb?}VDSm7>K78-Umc z6_ih8H9HRnE$URgbWX>)F`y)0GDoTD-Z_j zV+86u`tSYj2&eKRCLJe;&CX~k87 z9=w1f=-A97*{gbkwcoE1Zx zmiQVI+DKv$e~i_Ce|4+>j&9`-%I!O7XNb=54rbO6XT~9o(zk=?pimmi|FcNdM(ya_ zhG1-AxQ^ z$3d$iwkHXEiS)}n=m(}Ye9gb?DCMypto?oSm+Ff)v488qxpJU!i=6z?Q*-Y&h#Z-saiA z7}%J{^!dY8_%OumYPpcq@s-S-S+3qONWo$M`KJc!`3cGw_kJ!PZ{mmR9kG^Ha31zw z`Do=u?dtQp&s8g)R&hJf3vtSI?FqhpbxAMM9)Vb;h7X3wqkn0rDI(YWv6FqUFjw&Y zg@XH4Q~ZJ&Ga6z@A17>RT?k!pOsQYI&Mc63)R%YMQv!m2AwUgx2ObIpw?sM8`|_`c0({=ZPA{u`=;sS+t6ihm1M24gnaY4L6^ zOFGo^_gyZqYJ`Bp%qWx!vBalRaSO(Wmrxd!k@F&RsrqyerADJ6QP?EzJRGPKp z@NDtvRjHxlm$C$w>pRMNE>o96$PUDlr02=gFQ{ZTwXqdI9p`CewqEhn2rpM}fOn}HSbBK5WYEWbdjY2h>8jlbQeX|o$R!(#f0qnUdytbw%Z1!6{v8_EH zi9NmbHt$9+zVh;=EfAJv-7?#!$3*Y-?XJS4`Pc~K?B)Ljg|Y}nw=MEyA^VWXDQL>H ztJmtYIL^+5oXRwbKKDABnsXtSG%N6Mt&_6$hZlo55A^3xC=(>k!Vma7j&vWAU*f{xH8zkf|q><O-`&H%faGt1vhp%chv6k=Wu|jyB5ClyvkQsf$_4q%E?Vdg|kY#X4BlpT;KiD!mVgin$8+V`MvhnADQeIIBnCEI=iWwVp ziOfgJrQS>IHWKp}d|@0=r9GA}ufHqi;?37W?v_QwgO}L|LHtD=v~y2>aM3!Y0fB9E zacU52&Y*{=RS&U`%Zk&;fC&hI?WASl!I9prYVt>Bt)mKX)#qWAjHW@6be4}~D#Xga zj@&}y6GV=6#m=34lJ2l2(};uggkp`PqRuqBWfWyTaY@_LU#weNnVF0ohmItVFSY`o zcKedNO~8HwQ{;mDK`c#E$|mvA;Mw&OffIk^gZ$}25C3-}{HZSvq(MO1qF=et1(~|$ z@6}WvU-TJTt;O=~WW7}RNKb(cqQdEMb>kk3e!zQB#`nYi-lsPi@p?F_=JnDWYVP~T zFGhU2dLS3V5G;sb^kSulr{ObJMm1J<{48sKu*M<{gu8iSEMjh6>V4Ic>R(_ku+|ki z(IpVI-9{r4zXNmp+GURN?ZtV;&b1VgAP_%D1px2E<2!bp`S z7y0PVA;BcDUxt}+P|jJfqs%9R2J3K)Kb`cD%g^pd=BSFt^`rv5<}g%2wU+nprvs+o z;pzXoVG7%pBNMshj?cYCer7G~F2`j&FBx8aV-fkG0u8MgXm8)3_lkhlt$U{EVSaE* zGL>3tTbVy6rPCVatiT5+^OHxK&&%9D>WIbWsVq^&J;s3M-xy$hW}$>E40^8wtUBlu z^~*qP>|qCVq0m9T`bFQD=N7SHXO2XM#z4I5jmtLcjz-$I%xg+t7xDckWrv~Wu?LJf zI-l(BG=@&?|1Z5BzyQ~0R#NwjXgS`+EA!FrE>iJT1u{$DjjTCpmD+}@hZi0?xZVaC z($8IgjwVaXe5D%AE2boWB)TJUi^2C@06eWLGLQOqXXyg){_X7O-<>5V)&hr`GCc0A zlHbZ+=Z^fPFZuui^*O$3em)wN_pw?Z>?nj)5*bEwwX&`3A{A1t_aJW<0Jzxdr-x(} zw%IeVk=Aw!CW}9A0-_UnA~Qku=L>a@>mevzjJpW(o1Q+-8&tpbJe%!%-)r`e#ng{&(yq_XHDST(6L|2B0O5je?8pvg8dX@j0e}(L$_UmqgkbB$%%>UYfa-;^2CyLOmpPfH}wfs z5cM|Y_cNi#dRz0i-WuqNC!sp0gm5WTJI)BsdmVxh}Ggfc5^hX45%?8$&Bj{NL0=Q{x2L{wVjuL{D8|p5EC^ACxuNX%ulzMYK8^4IyrAe~-=NB1C-X3H&s>_zgthF#}3ZTu;py z<0k9*t04r!Wut8F`asq%_~~8z`6y>P*DheHjw2oS>F(Ya7 zlnIf+gj{AiU$&Fd7z1PSS^zdfurDFGfx*!0^i*tzIXc^E#q4jkG+HGzi3e3d|JKbiFcHr}0H! zv%_&Ne!3ZNCeP^$EjM)*?T`W2fTqz*`*hPe)=(W(aFa8=rhnP~jvQ7|ANd1uo=Bp< z;54QHQ+lZoHW=0YKgRwtF6!?40)_#RuAw`I?naUB77*zkLK+l7Lg^Sv5G15SloA+} z?rsp2RzkWJr0YJTUcdXf-~2z%OW)vk&e^f{+H3EVST^k?pz#Ln|NIdkQ_mJT=h~pX zfWq{BL$D()V=}s(5?!W=zw#18OjBbXyh6-JK{(B=C?NjmXA~{+L;Lc9tJFTu22pVH zmj~h+UKE~u@PFvyT}<2Cz5ySe2#3$OC+*Lw?Fsx}2~vf&TajXC1gj~W4@ahsqbH1` zQ^jSxs^4==DP7n{IuQKEb^;%UoQtC+`7;tM5 zYmrBr0u^#I1_r~w6{#iw-+dGl$uz1W24+OJ_qbn~2_(b82Y!pxkkTq^XA1IyGT;PR z_}Rah?qd2|?Ma4&)VLF+%Ftq#Otu?x+hMQqDH$v1RYjy6{!59$VGy{Aya(;gLucRi z$E3Z_1!7{G$MRNOHAmvZ6;xxCtl%m^-4ekU^Rg!2)hS~))4Q6-s)f(Ky~SFqlL;#N zg54{zZ~Z&#*{f;?rYDo-5ng9cZ22rP^wjz_??>6N3Ih9KA)tSMA4%_WDgu`d4;d~T z!2<|?+O6NIS(1+mVY8tJ_5QscYs8BD37~#*9F~#}8Vlx2lX#h5bS0q~aYtLiKW?7@bjd$^Uh}ijjs41AIhHoQ+z|pR8Mvc+t7;k`zt;X z)`#(J0)fo=G?u}{2)2*6H`xyHE3*38*$Z?*!KrNPgFZqi-L-MS(9!S-yPigj(Rt>9 ztr)MepYGWI{UfBJr}Owy*{m;=I*u)=Zj8I^-{^cXdRu)UF82D)O24xC3yLVJ(M| zI$I73N7Jm7N^KZZ*W`{zrB?j|5#r2;%Bdq8o=Hmr`8LaNJiLyxv0lonDV08pdbFAg zF=pp}Vk2@MS-+*7IWre!rpJ}0NaA9!$Orl-mdc`mMr%XCf-*PnrVeit*QJ1bRV{Lw_UEju zYLGzT!>gsH#1w$LcXD06+PUk^RN7E(&_?>ZsCU_OKqOjqOi;PjRyFXapU?D_(sW9t zDt6JUIIag2YfyB1T!E5(o0Y~}I=Xb7&DBNx@xOGSih*XLyc15c;V$v=N4szlwRDV6 zw|rfyH0sw6As=$ljm3SjE!8C{72mcp0ZP`XpNHv zY6&>_f!1WG4ZCuKz}Jb0*u7~V?2qfDBFekr4*imvJbsiQ@SL$G_tlVHKbH%k@4gBM^Y{Vqr znb#N99P@vf3k4fo(DYbH-b+u89jS;X7mvemwieAiWX4&T4X*e`lFOzQ86M|oCsnp< z?0W3Z#9%uDqbOMH@3nq&hw$AvF=g4LqIS|UJCcrJ!6tqG=K(U#`{1*?7f{Tuo7s_g z(W#RQBEeyYt-Rx=)z!0{Bw#wOE6&c4?8(aQ-TshNsLA@yD05J#OHWMxFf&xQM*&<8DH$}+XA*G#G+C!Gi*V6P2#c2 z{KHecIJewpX(j_zSU+mg|2)d_47VDB&NrDKp+~Pd|ruvR^&zsnKObT zg1zy~#F?STq+BewdS7P~JX#LL8u=a@QbkSr+CYop`LX7IeKZtS*hJ48=H}E_3%)3< zbpA`Dd`ZK?cbK&lT^zs5uOzcvpFAGgRnDy@3r;!oU=YVSSt{rY{0$)mLnT7gTh>Fv zN+uC+AgsZrP!K#c(tQ5Xin1Zd;Bgm))*=x7HwWxuw)gXd5Z4<~5)T5uCC}RsGDwD- zkP~rDzBJ(kuH6^DSBQ~djR&daR4JfPf5C1o_C}CTbTj0z#(`L@qE0?gZaw;6C1FJl zjv7Wuw=r%qzbeJyvVd=C4~Zz5a;8G8dZsY8mWeG1zpOX=nInaJ^XB8v%)8j5zmguL zEMk+k{)P%|Ia&7&$fv83iT{v8YX#PDJVo^j?~i8(cOjXk=XiH-Wg+obwIwmceKlSiv|8Uo-|smsx0XW+CD_=DjGyRNRM}${v?3ot_Nh&v2mBF&jPb zl>G7k9+9)B2=Rms-okZJBAo?)yJ1ofVbh#>jfS*?oz5l>X$Gy#3@ zHZnrT+<%%)2ASLL3G2jcWoIeGX0z73llzIyFde@-CPs%_XwtDYs3nFyVP-CNAkW^` zsA|#T;I8~(trM}gm{u-_Fp z$)i6mSd4VRi3L=%8!4m<&dq_o!4SMgH+6860zxzC)KxN$-mNdrQ4CgOCBcnefvmDV zw%|=m?k`*tG18Hkj6YiSp2(sSU;K7=Uq5%l`p^v1|H_I{bT*|fKXaR(b(wwlPTY+$ zWIE7?HuxRWi2*g3TV&rpO2M+B`&ArcKTqK&y%fexq4x()i0MI(vw)$&eKn)#X>=v_ zvxq{tR!iFBovzy%kD z>a88G(NjqFZ6w{onk#kHNy_Ap5{EfT%wKzGj*aQoo$OLj`J=a&^ErO!xE%K62w2un z<2KThUP4u`LVB5T+gaBY=^&C@ zDQW6_q!FXbFXa7coo8pA&>31YFcw{wDS2vmh4Cs}!Ya9U3n2Xe7=|w@vQg8j96=r& z@ZTgiVVivmg5*)1+5D?mui@r3_}xc|bQz1xTOMskSA;)l@4~^>ZuzTQ96ra6q^;*d zL#wOU*>sWG$QEBex!}m38HEQ)C`v9)Jz1sM%4mLM2*dk?)}Iz|DB=1@LK*zspdxBIolHVk@{w_eoRYHg;`y3{&+)E;&(|pUm#C2U*@|N^ ztt61aVJQ;&T$T**U5U42zaZ7y!KAE!ZORW`uX-O30EElQnXZ|%DEfMkN+}@?j`AvD z6D3}R$O@UMDAinLlVTF0!2JD~zqd@)`Dos(FT}tUBEM~+`1IG6Nwbm0JFoM_kB|Q0 z2S(Jmpb`=ZaVnL|pZ@Uu8{y1rMnI%m6`4kDO%Ue$>_vwqMdK0L`~a=JYiq)MdO{dI zKTh^@+VD{sLOo;0j`dz_77CTbqlYL~2QH=0JnE%QgMp; z1t^SJ@GU^gWOhv2vzcV-T`B6yJDk6>XJRxV2vM8ez7c*opXEU~e*lWT2HOzTn=d`t z|5~vCJe#o!a6-x9^Z^u0&4E2>Q!z}=w_{60+S65ZBm*ZVNJx&|Z5^=d?G+ z>c^b>tCSRsGX_A|5FHds1{c3&Svp)sPXv6p%aiVykAIBdA<_s+UadF0k3$;4dOgJK z9(W`d|4am%2A>;3lPZ%I1QuBJ0jS8WAxgEqarfo?mjw;S5b}qO_gHLdh=1|ATRqtf z6?mIrCGt+2#^3vYiPu94we>aI&%HBTvpwusQylAZ%ixkD?YyGL-;dbY7T;I8jEEkO z2Eu-nR#;aWeX{reiOS0@)?9ZNRrp6jzb3fxHwC@*NVFuo1qwi|EF;fC0IO4>$2(Yj z^fYa!l?=L^YDCFdsmXBtes1G>s`S{b+7ePg-?cwpc;gzOZ@bepVVBmbuDG+xydib=0X}_Lbnu%|ThV2-SY|X`Y)be( zPFmuBPG6T2wB3hENdno<@Mz0%Q?kE$^3dfx4nD0lm7S8%YwgcKyWbT0D=-i>$+j)M zkXCN**tK%EfnhT|9QzFkrj`XVFwsbiWFo7E2T|bexs)=Tvmi);#Bis>g>KgX+Yr1r zfD|GB6(-6g+#7oag;A98MHXCD!l&J>Kx<@kQ^~@SH+JrZ0WTe%OltD~#!g{ntDU|` zkG%_;%Vh;Dn&G|@)0YRs{JBYa9&oZIhB%vDs~%vc{`cBzFbngd7n;9N(Ahy2TV z{rTa9bNTMJ(}JO8V^ZJ|2aG=lG#m-t9$A%q3KED@_eBdwDp8c}?@>?b=jz(-Y!rrW zNL{lI-TJ_BgwI$}M!!aPL%7MsoPznk>>o?)L3>5ni8-${Jrnt<|8A9YYOd|}U?uOo zSixc4m{r~$J>Jb3KTx7zm*LVNsfenn3YC$bBhVWEzCkPvSY+Vu{(2(M|29Pc)C5JO zQv2e=a`wevJ_3S*!NI|(Prba_H=jDeCT)fC6rJG32FAw4qDSB22w2S(@)9QbEL&p1 zGDt=uEVyE<(~IJ%j~_qknwpj#CGpQt_&z&pw*)Twm1u-vEA$Z$R>9+vrl1ng6eN9{ zfoEb+#s-^8?)2S6@r%ErdDkxX`V`Ze+g-NjSf)c0;$Kk9k@FY&F$O!b3OwJ@!=ro7 zFg8a2wzspd*f=ErLj_~4NQAN7}{OPew)X%@!DR@Q|Kuj^^aL;ip@cvZ(`}dgdwR0j8Gj?}((Ts3|MM%UBV+J7H*U zp2cS8K0U)LT@1ipz!Rc%!sB)c`mbH3Z@Zlev41?sZ*vf7vlW9a`Srt-*P7}Wj%{)} zL5qw-AU|pvq$sLE`Ua&C$-in4WO;^ui`|ZueOAQ$PC)8~}n4xY*lL@S?%?GqLK??zLdiV6S-sewr zq6VI&MpE+i&Bnwy>Z6g&_V!Rr&{S4s$xkNJc~epHJZNEmO31XQ&~WM`M#b-2w`-Ojk<-clYvcO?fdy^GO= zV0tMF%drp(FM<<76QkwyOUD=yBlZxsgux1WC;=;alo5P+0*kV4-LyuvH>l*%({nGl ze?9*fjO(1yLfKnnZ`RFL7vks8GZDwL}V#*X$zMLOK)4zvH5ey1->gl(LuSUk8B}-;1LOL!XoH z&qUQqY`623Vyvo7s$C3@W@{G$Vj>v=D3LF^XxrU>ZQFdTGgGM^OMlk`<;|Nn>1D1C z4ze~j%&))FF)&Q6l-+w@Q9;PxdMRY_{8zVgW8H2q=pdxNhJSaD93>kcAfjZ!6(f&R z`%<$Pa_;-9N1Z2e&1H@odQ76#wRStJG73IS4#`l1_|NULTKtDZpJ`Yvu1sx690h` z=<~H@IkZ{@VD8=yzs&v|X|N(Pe3AOT^w&e<($KH2XuYOpc>XguW%nFBQfd9cR-NNb zNtLzC^{LJC^Ue1r;;8x$tX}SXGS$;7nDB3|u}OX2XV~ElcByf2agCek>5&+en_;uM z(h*>qn3()LThDPWBn-H@SXe%qvTUu1nF}aWf%yNbgHOL`{#oDI*C*7T#s@`;D%eEl z-%17#Jg{ggRySeo;oAu|x0}bS?IfoL4VU^pP%c;Rw9nc1|!U&_^HT1(XwUB0YwK@bZC`=3?P zNFf;{-b}Sm=v@+hZ9v_%dqT|rpB}1_^>g5w|8#s{RBWEu>oZ#tt+QsA`D2y0+z@Wd zw`@P){>|{dN0qX3O0h4lZ-0v*Xby9dPalUgI@uRF0ZXV%K)kns|w?ktN7#cn9puN=!`LK0g}3ykb^)xd`6!G*P?d z<(B2rSM9MRPl<;S8yhR@it~=eg@d%CAYM9Jh2D3iLE7!Nf|>V){+oIyzAej%ubx{D zZf=uRUi!Y_GM7t)COLPunBQbO1GZb6|1w*k>WQ!-taKb5YR&vukww_xgIE8WlZYz> zGS^@#cKeLtM`!9Qx?ha%pGY6nGzah45wd(q6gT`AGCto9zW(Sx=D$T_i*F$t{+^o6R%x*$YFOYr*i;}w~oC;ZwOA~LYC-50pDK;vr zje<939knKW^tIGxUFT}@%F1>c0+M}pH#g5hBEFD z9;w7w@lA79VS_5RI|DE92r>OK3bZC4dc4|{Dw zw0VItF$uq-!2=z4OD6Dd8nn{+usy!*+_ftjXSu`(fTb} zWL5T(;gL3yT`QJHR%OsE#cdaN z_bJ79#8v9vT#$>!P(r6w%&$TZuZ&n7^!3K|MD-87)OQPxs;@VttqLaK}v9UVEnccz2!X~c3{S}X?Bn#+@DE_2sDPfkX}Q1ClxNf|sb zpewmqTC)C-b92#p)0w0#?Hfv;xLu5^az1vcKp4`3_2ht8;L%$ku%dp+Od89`WsK0M zowO<@Mo_eLx3v=zkwKiJFcO%nH*gfY*7&r{cpFyohiCpx7PK`pe_rsTY<_eM_0PRM zv7Gu!&n&L5$B@YK6UjTgqt&e;+|i;hQJ<5!f7WJ3I*&^Gtl}Pbu;<9O>uCcT&%9;m z{zW{#(LNpI_^lyGxPEawQ-2x)=YTpat?=1`iE?E;?4R~$f+aibZfw+*udc4#jEzNf>7d56Mg@)dVj@|P$>uCbtblqs&IJ>wTn0%Pa+7z9o6 zeX8t2KbUL{#qu5IN|AuT_5SO>W}=OLKKHUcV2`otVl*F=_r|wZvC3bdBEsja`v+d7 zNG%V>4OpPa6%%fgpl(ZhV71`7a`^30k*W);z2Pi)ZlIB5axJO4=nY(Eo`5&|?-WA< z2RMW%=;&j2^~KrP>GEMonR%(%@_Tj$@EudP^%>N+#m3SRwvj`Ui3SzLk|8c`&3u)1WgC zB(3?uV{3cgu1lGPS&Y%k1~fJ8=A0@ut6=OVtv!p^Cq&*)J4xdi8%rSFrk3HZn^&!2 zaTR|Rji9X7ycHZA!*1;^h333K^-#jZ8bQ`xdqAZ~?xIlh0cA3?$&vCXwK29YO98b% z;wVQP_hiiG=OD$;Zhp!59}CSW1ujiaef@Ij&+Y%u99%*hOkAm6!=+ZDPEu6%pqeT5 z-orSfYNnLgA&n@5AOnSba^l+Fu3c%*56e}LRAX#PZ8n!WH`R!D@$1N4pq`?Z@A-|%7ABB za=rm)K<6^&v?P5)7D3Py^I4TJHc1eIz*XvM327>naHsZc`45V)2uPu0@aM=`&OJ8T z9WJ7kj=^)L|E9s9;&V+tjWd{#WGEta>qfo;at8gj@Ek+>OmbcPF;4pkA8G3)G}_V^ zTRFqkseo_hVKOFC#t2YeUbp98Jsz@cBG%>25R(LN zXB#14;ofnH6}|BcQ?n~8ED!ZETt1lA60kmzn5&NDV)!}LdQG+!I-{p8RXE|SZ-?!2 zz+@R^;PrvHCGh-9j>qo}-KO8;8mHg)12Fa9$-4fqs|%Gu104M*11aRfoT8(h5@$fM z%VgLjZW?ae;l~zY(jT%a;iS|v+2MJufwvz>A*Vt(&bC}>z%Sqbf}c4DdOTap#_*pU zJeG)Z%cWh`U%1LoJ1_r+RP&8NEWaP+QhmnC-~<;?u|KkOP7|=p`dkyO6>wX}hLB(XM1aP!pgti-57w*84jO>z zyYA07pZ(F?39HjA^-z?a%HaQ!q2uEU&I4J*qt=ayMqZ9@QKfYsDTM8M`^3|RYqvZ-skV^y zu~KCLlDmp_M#~6i;uPqypTp&*At+g{xuDs9txy0L1e1{vMh~1R61bx6A-iKv;I%k- zddXF*T>9qn(4?ny!YO=oz4KzfHJ(uBQfJOc!?j%B(C~e~esZ_puArFMyJWi4je_`3 z;}~3?2FdI?KMX)q_W5YPGDQ6=7t@8z&7sUJhA9`x@%<|6iD|zfxU0BTZ@;@@*T9;Y zQnGm8K>w+3m+}%de%m^>bs^k{)#e4SrIqc%0ukk|!jM%aF~ZbBu|2U^>vMS=;s1Le zn*6AdS3(hrJ@(#o3XUgCZ~OP{dox|JzE-HH4V%3}9DR`pruj|3wHds=D0g~4Q!)1n z2YS$5KLF>wZno{Rw-ul{#uz&NS^@esS6<4Jp?_jD<1b_-!*FY4Q3k8%2`bPWUL5as zzRw9LvHLKRBV#!SAA})PUB@@HMPbi&XKzou4$?m`aP3KEVpyCQRi7<_&KrVqO6JUrmhhED_t^iwclK7rS?Vd9mlex~pE|X+1og zaJLIWpeV5PvvV57$ic@{cUb**-TCJf|Wbuwc za$$+s%)qPfPdz<7tMMCZTxLREy@GtIu6F!UE$cm}Ukyuk(O-Y+?d_yx*HTh8WyJFi z+gOy4)hqdvzL$f3KU(!>s?#%1K;UK1O~oujVKz|MpwppMwVHC7qyg01r3*9uHM>!@ zhGLmW;NZH)-U}M(M>6utuYOEuL1BS09q&Fo3r(K-hbK_5zo7;rm?ScxHp2G^3MyaJ zej6k1u{!cYcQPz^KJwu8r0Bd{#j|H>l?5bw-y6Y@kD`wQ<>MK6^+q9uF3|JncFohx zJ#0ybiX|6}R{xzO`eU zRu)VqrEIYleY=!Y+WFp8?8Ezyu=>Un95p5vOL)SxJRrAXd5ZHYm*G}&=~Ah2_`n&r z&gAE(kx~n1cI|_Pi|6Mwyv$6bBK(LtR6Bx`j}X0s8n{Zwx~#Tn_WW;uCwb#@IA`t*Mxc({lx(en~kheD17=- zv%e^cc_rTJXOV4}-hn?=l=vyw%-8 z%YKY$X45H9yRWiWKMFah7tpDpZP_9#GO5F`^W5LNpDU3@9FjUKc-@`)6TDM5Q;B-! zks2XClUDun&L|UaCs@OOKuwII#Iu0@*WUXP>M7 z!ZeZVWhT$R3)%<{8WrZN{?=>NP)9Mj7Ekn4V$AXzy5+=^hoY{sXP5fIEknp6Gw}Qk ze46Bd)g2E*0|O^J0O$6oWSmIx`Y7tX-yKL4G}fM@`GL zi!ODg6;f^{LQI>l)kyij321fA{1-rwvv)=K>Jxz@FJh)G&aNbi~rQV;yZTYw^a9;aN1meucofIck`l`_r)8%CUEj){FgYz@Lk_!&{8;w7^73h%k zj~r2b7?>ypl{Bakx!zQ)6V5)~YUHDgbu4n_2?4SY5#mrwA=pI)9G-j+v8~uua)6%1 z%fQSSxS`e8!&va9P+*czW%#^T_gh_n_wDG9ev$L8`s+U5Sj zZa}LARoZr89IJ2UUVESAe?osXe)~!9z;clh!nx;{kMoJli1~P~hbtE?@I|^XP5v_SSFBAGxR#>Ru%p!Bdq=I+mbqmcV8}k-9 z8B@h{iR^2YY+v84#4petoaqR;P*TR}m z?{fT$NJH{y?J4_jBQ7i#w;GEkJmQmwzBtvTR`_|W*>k_ChxaZ?`QmiCx7=Qc(yJ8X zO`JsEKKJUIucUX}+!VgU@bWD;C^;K&*eU*Od};vQj?%f$PpqS$xik>&K<@BR-LP9w z7~x5tul5~Hd%!Qph(b!mwjV%i48bHYwifu*T-0}y@emnC=;U&Tl{Z6OX7ZbGZ&2iC9KjJt(2jtx5OO3((IJ-?&+i03(1Ya;y1*IDk|0f%L(i_ zTukY1wPZ-6ABFnb z2XzOtyLbOx_*)^=XM=$QRC$Q^A_S^dc`sH^Wb;)kF{7s2)Dk z?b=i9|F#;1huiy~lKC~8z*qyJ0_J>Z>jf>cj3s@DY!Y&q-3-M(j?$_l@``mR#0Ep) zc3m)u7hm0Ls{Ie1WG%xN(zCubi20r-7qsyT94>vqfGF$hpmN1Bb{?81 z;g5e!qnHrg#X#cdLk=^JwZARMxc=XR1uCqT1^mgdc2DdJ<`QVuHbCSrZLfx%A1PLCWiZ#1rS39FJ4Fi{^3ZaqJ*72Ns}gJT}>xe zmoqOF~AAsBnh4JxFU11H-D&zEo~r1%r*yQ&8OD8)ovW8}jpEH&$)NZ9q682}|I z9ef`}r6mS;g#WIR@+6HpmBaN738ltUPSAeHISJJkDDS{70r(rkqwx)alS0-u5jiT541-@ zlpzQcUw`%OW{Q?D7Z@l4Oo@)pXuy${jhIAjmg8~4hEIGpX zZG2X#tA=h{us2~75+!E??4ypo>Mo!Z|Sx@;e6=3!!ao!Yx3URrNBXyzjmNB9@-*yXl95B~~J zj-3v7)_Euu*pTqi@?YJ-h#XDcxEl%-Pq)6m*InLH%>L3RJwXVf3t&7uR;mO#h&QB`l5ChnOGmcJ@^Tob`bKB=!p$x8`@;i~i zPmj7W9=E#JY^icR7WuIHV*gtw*-ouze~lPd%0&YJxcdF)(CFX`h&p|1a7}gMjlD z4tW#$mKa$gTg&tmdcnbbnfEFgP;=>svcl{>@@aKtQzlGB>WItG>5p?|Me59)@P-(R zQII;j@cqE4y*Q;vU(ZgbdI`dv+bn}xY%{4xC*R%hdZF?y;rM(GEX znep*)7H%(U!d5J!6GHzbnP&ufEdj2f)_?&*W<^iKV4{e9$Ns=9%X z?5C3%2_Pp1r7<1DfsIRFy^`|@be-Xc^7yJ8jJ zu_*m+NO~Rv(a1=z&Ua<4u9OLWa)_w}Zb3Kazb1>U6OqU9Ggxl3F}IeEpa(G+lI@|8 zLepNp>f`?)AD~wF+A(W>xav9keb|rfiY52vptQNT-yvwE*T=V4WR4x2(1S}e4ZtCO ziB8S>8>GH5gMXf2u{1ITmm=YF)-CB+d>`Z>uNN$Gg|OO%XXZiNICVw}WZN6#v-c;$ zT|nn;vFjR8q-LeX=Xu-mL&a}XmMr8avvHJ~!Y`}ROW~(~_pt&n*@g%Dlsi3Ey}sb* zoY04h-o;oCG4~jrV_OZ~(tW6VXBRr@zeCw`b9Ec7N_Wau09{WF8|SUG3n=V|1@H;p ztAMZbi{+a71EJ4>GPJZc?THdL8>s2$_PdKdl^?2i5oj1Vi>0^~%Q=3)7v$8+Rdm^g zKoIXSR_fCxoxb(zu1`l6eZXSIHx)E)RnN9$w8JkUrllhI(|`r{U#wvTn|_(M7n2U> z-Ia#(>b=KyDw@ z8E`wP%GmI6uZ5A>6=nHctRN@zLz7mWJtt!hsMrgWM_b}PST*PGsO`Zid4Azi+e%MDrDsm_B5M zdYkeNY#)N93A~v8W8O`cPJ`i}4EANhBYr8Q@$gMKje=IG{xd$qE*`@FC8#bUFp(@M zJq~2xO}LiO7b`dzTn3%G)i}wAhWW5-9Lg_RU+#&YWH(d3*k{1<^6Gr}5Pi_>EZ<;& zc*SK#^22h~;aB9=0qVzVTz{yX8Bjp6`J;>97^?t)TGJc%suXOF>LNE>g`K_JR@$it z<+EL9dB;KSBsJQ5fnG1lg!D?AI6^>2O>iW{H9WypxBvehV!$Z6*$4#ap0Y3SBHG1% zC-X)YJQpt^FIQUa5dFdjGhett>0OwYt9y^RR-$gpXM{5Ma<^~3ZmB^)^ZtD(eGD^o z43s`z;i`-}{wq@g&@@ksfB6D9zHY<7YgTZkt%{NV8o5K{;GZ8^i8CYJur}1X2%a?x zep{B0x9#$_^yssvuLrdr0U7=SW&>_5qPF_0<~olqzADimdB>yRFKO%I(VxbhKr7D{ zNXQMCBq~%v;VS=6j>I^Fg?>fvV{Q}l6<#eCh(2v<#qZdmx=H--j;rFt5Bx9uu-3Ua zFa@nV?G{;>hYFTZFg@BPx2-V0AQ>qg7p27OSU+T<#bG9oca%SVpL8mFg8ursR%&{; zv9WPqmHqd`*h2Wk)m#YfpZsW!B&w7s>)|tspg8m{nhRgzgCJZB(qnmxhr0)|jyNbF z68g+yK_4&tKH)dwsDl{#tAJ@b_H4dD;Pq7d#BZF}*)@PxtLjE=5)WNnP(&(;4d zS~~p(pyul71^h^)(_$L_>PL5xMT62TphMO+t@EplS6fMd9PU+XQ+Qt+qYw>6TfUK0a3J#oqfRZI?~sDUUJ6%=_osw9XZ_!YLUx}*SgtNhdcVtfmCc0b z9SNZBRgM__hbY;Qm%~Y&8N-LQ0hY2g2(UnFPV$ixFs#*LWwWeQ2+spi$Ts!S^3c4+ zC;Ba=0ED))XU8Lf(Pwx)(SBe6u{g@e)S9!b{;UDcPa*d&Pxq@bQe$g)JL-@i-gO45 zyj{M#b9N|TR)-?WT~pvUBSxw9g#~6KsHvWDx+Vdd3__BzJB3=6U^utbw$r}9)sV1t zp~9|1nOV;cdmK+@Av@rR_PW#^O})XA>>xrUl+9LHSlGJS*fzmn0s^t|KIZ* zf+Bwr2W4io^dEEct`nFRN4-#D_v4GpFT1a}bL*(6Nx4gGf3w|prjom&FXmF7a7}Rp z)^dYBUb@!yamP_ptW4Q0K(OkG%Q=>S;eS6#4UEB>#AysqsBvlmf|gA_m7rkCAbu&N zzR0*n^Z-4W%*!JJ#jIz|Mc5H98h=~)` z?AJ17HZGsE2)_vvkyq7LEjWQyZelFY$GDKqC0?Ag45sP0(6%Y1%u7v0?|%3`*?er~ zvJi0cF`diIp+OFMoK8~xmG~o%(YYph;*;wlIPZ*QXpD-J6)Uzg!uOQ|RBXW#Ps@a$ zfxKCf3^8a`HB00wfZ2Zy@xCHP(^ZPm{hW~Jw%tqxkTV3%4}qBMkv*Ags@jiJ8(f*q%P z>*Gur3s2zao4l$p4Ad6Gi;D~WLm$b-9_XZ7ZRqNyPYiteS6`nW6C*nK04x?XDD0M_ z$cjlwh^#==bPr9I0}ngI|9h05QyOf4vx))?&Uxi04I#$1e|j9zl9y1pNx0 zSsN`eLYL}n!{Pu(mJETRhxgRaMklu7sXP`ID)O(lxv&YSf|W#VH+dHW)*>`XpRKi2 zW)B{{YH%5R9W~8Vk-Acfxp#&6xyAVoMq{IuMK#VlJB_>o?8c|Q^|c8#wY3EwKHy(+ z`MK~k>nbFPhKGlLKR0W^rbFYgRoTZRM?9DL`9g3W3iXy0s}K^;wb2v|UEkt3;a6;A^J3IX@3?cTqmt@^`1GcX$kl5up@1pZ&>a zhtN(_nw6p6RQYlC4qoTEl$M)ee=i9uct$g~b&K{A^9Fx^Rl#AZx6}2$+}6PQtA-zE zoFs_QtSri0F2j>x1&@G3x(LqF$%9i9%3>~q)Eq)rgEii_1wZ1#P0h?e1HM-JwY&UF z6b)ZDC``d^qp%a$09J4=DznFT9=sFJ|p&^P)f`EhOCehG0(yf^w?gB zCuVw~)Z>~c%BYlvEe5wt)P7DPky)ZKP|Vai|N_0u9G2+3tR<} z6Z*Momp9!dp(G2;{2on%R+Osok)cx{6GTGv#(*$EmBzsh$p}2X{8^A*H+bHKk!DaH zBqo8Y>*!b;A*Z;*OL~A0A%bw%2LC+_bQ;jbX&1{M&!J)`(uCGrQ)3%B;j>uNaJ*xD z!)0yg!UV~9#1O^C2r<1hWgTHCGa#OHY2k!ns^^ZriM-aIbEx7YM$9@WDr;%&eTyZm zGyCTXSi#1MZI=3ICwYWmeVX!{r8`|vyCV%%i)u26t{yY&A|w5?E|qabzaRBrqbI|gXM-Dr z*r~bhjXhL@ip6umYF85A)z%JHlzilfR)hTCvSgZT_tP}9`e<6h(1;NcO;EhD`SN^h z5f*D^sHm{C*b~&h#|qw1%?he$Af=0x4$0txy?EvKTV*bxX^o8KLxA0YqKlZ%@&ASb#%U}#9KQyVd_8nG z*oqk8Wtdsiyv2gOEwAVGp16`LoiRsohcU*8VdU~b@c0!AOp8vvYb_C;C1HePb1jc2 zbzM%3fIz6j23>lE1KbC0|MkNlqK#td_+tf$MJQyB0TRxXMHS_I6Y*9wP~ntRzw6jQ zzu=??-$y$;B<2Z>nd4^SICb6H;v@B|*SBakD;KCKA&6R?*fV@>D^US~p!s$l5``9J;|?IM9Szxz08eQ~!jha57`I%}Sdh*q=jx(FF z!zILKJ4WD3m^nm@23nS4YEA;IqdRS(GHiEmFCvLeMk3&{&S`t9qW6ooOk7%8n&8Qs zVQ!_ak+rcTXNo`06N~^iLKhQVMuHYE%b2Fk6l2d< zgzNZp?Y4d<40yzwpOF8c4@^>Y`E8rE_Hy}jaA2|VDb>7i_s{IRN(Z7Ch>B*M!-n4E z*Z6m+-Cg;i$K=t1t()81p@XaP3JSNp_vhm(TF!CiYFz)wi^9Uf{{Q$rM|Q-BuO`ml z9ZF9gu)5%-xUEDRkt2e7H#>`^?s)8-WIzq}74J`z4N*xGaz{;j5F?gm1{s3i{r}zw z8>;&-s|ekdyndH5{*fFF6>4w8Ze>zz7SO^F*Q{UqJ|)XxrSd0FuQTduIb-9YnPf6! zh!gnEkQ5dLZ@zJefz#c@-_Ch{fGrI~{Xo`D>)v`L_Qcb3pHNTwzaS=X3pn)%%2RPW z4-zach<`D@e(J1Rhu`P14W%dL_!`;$51}b4j~{kr+d*h{!-5rEyr=C}2rYxEJvgCv zn&PoQzW zL{xj_YLxvgmu(N{i{dp&AWVa(=^T}OY`j@-%BQ=1c&+l{2nw|> zzTgxt7;_b8x-2;|>HcvOMn){3t@7OK(RY z7HNY9f9}PBonqlT=w8+?GgK^d#iENr`~V8u56t++2W!1N&>+)pBg=K3EDJU$Rnpdu zzlRd&jxb8d%q*+25g!OLm6JnV8_sx-&aE-h&~WctZq!$!fpQ}Rnv#-It?gdD=eo!7 zj`7=ZA70ZMO)V_%o6?L+ZKbaJ(t6_g|F91a$RxspmLv3G$gF2z;h?k{E_RouanWg4 zSxAY5$CoRK%SMGQ)C%H%PLW>b>`wN3)?lMxHUSbqHnT)w%?v4JhS2m=A*%ihc0_2X za&3Bs5e*~@9WRcsV3+re#&DM-POQvs<^k;BOMhFsJuUd#>@7TGd-b#ZTjss}ePB>` zNFj)4B=v{ub4okq=8do6)pNV5nwnvw>v~B(zvv5yy?_1a?i(0*AfH^gbvP;$pK9T! zrgf^XJk!jso&En1_LfmmZ*SPJgoNaPbPuJpN~a(x0)muugD@)6T@nLGi6GJfDh)$- z4xk_@F*JfmBOOxD9?|pv@UHiH);eF#S?eh5-`;mz_jO%2vdQ;kV0JbJO@;4tC~5pC z&!hKs6NSKH@;iD@R*@=esITv_)bXHQ0}4E_%ToW=NFNhGx$>lgmy_TsrYyTfe|1(6 ztzLWGq_?(U>pbV3b5aC@bgDU|zJzu#S$AZJRT&v-Ecdm6ec+K`prSnN#?--((&blA zV#l7^AA9J&itAC#7?SH!N=*2?Uf-D|`n;J+*7Mn7{eY_8sm=scNrS(&i2X;=8` z+Sv5Hr;?DhH70pWTax4{>AeG@HVv6sAA*Z?OYEU*_i+RGxG=@luwNH?v2`rpe0vyk zZ4S3_R1;!oYD&^4f428cBZ1kt!VdC)BR+z4%c~KHCUkX*Jv}|`$x2?oCUXo~n>{}e zY1kh%ypKv3bH?fD=*WNZs+I0}L!fPj?}09?HAdzf{;TN(m}>PIE!t14n8+j5MP7(y z{EhZP;Ceh#(~o9y`g1+rRApvWP^9r1Z^gQ(eN?HVl#+!C+vY$=dw^*K*PG3fAigr4 z%8ISq5u7#Hbm96~XIfP3P~jivGRzE=ml3^%eePLJblo?Z_D62l@r|S4bbHW<8MDDy zbi7&<^Px`nJ^9Yx94Ji|T(?dyI^#wDvukVy%U%*PIXE5ph+;$3a2kWk_t)xX`v8vs z0`lFwl(qtXOWyo(A{KY$tu?+sw3dv$?vi&cM25=LHb;6=Cx!QKU-y z(tf(3WwA2!!DBH&FE&1Y*OuRTsEQmS@#Mzh-M?iXGl-BlpYMLQ#wH2OBtx+C*2qR# z;y3VJz~R%e(K(ayu9hp+cZb(l?SofH&^9j#=EbfC@)%NWJ*qWt`} z5zW)pUdB9e}i4tXr#3xIryAi9XOP|7{F{!ArYB zgID`%js=vg2c5MxQ=&@HL<{`7sYd&<;t;x_*f&xJkhQLHbcKDFA`3XVszx`2?tSKV ze5hFH**>d)#OW{Mm4aN}BWC8gXZi9QwZ6-BZkRVW@3ZY!S=w#XQ=6O+w`Hrr;lsIO zlbq!Ro3n>)`wNVF!o!xiVOgX==V06x zbucRI80uhPkem;*_VipCVmE5^q5ztU{P~fE?EqE+{ahz?o)TL~&zgQIPO|tw+A2ZQs@T#+!_jZXuvA$owXD2zLI9)omWCQsDhe~p< zu69SKC3&Cr`Uj+$c^#4B(;xRt7dN18OG^?6=Oy)qlg;|0l8bYGA#*Aw)QU@xCB8n= z35Q3ov&@W$ghcNaR?l00B?X16HTJ@{Z<7HXuy!1d5yRy0a1I+!%p=f}*#kwCf~IC% zewFVsf&XU)1*9~a=(yV7i<1a0P5=XKZRz-Zkeb)`=OK`u$EDKU7OL-Gp|V_`D1WWH zX@T~c47n#XKq$oOR70Z@x2W8B)1qi?R>5WT^|<&Or|Ew^Lr`=;{RbRZs_3kOQ$ejX zy*SkLm5Z|G*6MX3J6>XWx?VWk!$VV)va}CucIncaHES72z^U!iI#T=Bm9%EclvYpyP_GeG*&yv5+{SM5@_>a*tXj|w8Ho$ zGYyb}6%M{7^2^Vi$H5GB%g688z6Z8-g`*s7lUr_AMedk;d;d;=r(JlgGC-@WOojMf z!=uMk?6WA*6!^Bom3gl+7E8w5Yy zz=d}vqF8}n_PJ`np#3MVFJT!E>zk07lTmo_kl&smrLb|#_IZUvm~=Y4 z(YBq`_(eT@Q6KXex@J5-?)QhXvn%M-lr{XYN0pV`-cN8gQ7SM5AV_Q1T>kjzsIHZ* z?Lr8Z$wRq=$>+^F@jg+VWTlzY6;I+{m%7z6h^IZ9$cu!hx&3gG`5)taT|E02t>@f>)_ z+gHSU?HdtIo*yq!uWp8ha>Nf&^@c6J`}F=(L{B}{-&#czv>ruFzI$=@p!CmA4v6H| zdn!yvOGoztNJ`kvy}i7&N4fRdoa)^+Xp2p1Bi?^!S>E?bxaclR;9Q$edI|2u4b7gV z@8OLm{%5XioSdxU;sz=+5+ydP{$vn|{a1^Gmls!{5hNFN{^w$bc%*n75JR{8a4Q(O zmt^DeFFI`s#O`PryfQb=3S#J$Nl6tm49#kWd_U`jvqDl_9wEg?p8_xr^RU51^YTsE zkYJRQ;}eak4jR88{u0#zf7%RegnE}#>uG)l6QYzmoz&N@`1*|N2hX=TsiC!039qrS z@b!1e>2hzo%}9L$MinHlC3HcJdU5v4|K+4}zf>5|+gS9aip}9ydO%A|{f-sXJ_{M( zOK@5EpKOS%A3uqSpt+G`c%?7WxY@5U`G*6z^>g|98U47;voVJ=-Xs^l$C}@?G%i3t zZsUS5iD#(Jj{PSgev`W^zg}UM7#~cAZp!sEgx{}gv-%kOQs?jp_rZCM;)8-;r9cy* z1by-FMwbd=b6++K?-WuxSFG@fwS1_s+q9v8vI6YJ^!bq9<(gIllBZ@Ytv ztB+Y)nz2B)NDG=+{e7{AzZuytb3s^~WldB6bW#{L+hp89JLO67?JyoZd`n(ivdf3R z!U7(?muSypIr!a&;VAN`8m}^lUw0S-Ej=RyQ4kODPk}c&<`Tb+8O3BXZ$FK4l-FSf z4Va_?IkMQFp!2Ku?yTIhTWs;QKW`s^jyEuki-jw+-?r-cGH&ZAnLCKbjIQt7W!tFs zC>h!FWn~e?yZ5qTO@gf-MNFr-=H}lA`qQwm!tZ@s)fre^nso+$?;&%oWk)U?h}<8} zy8yNK{WnfNcSRIr95>hI=9ph8vWn&h?3#+eP?^|Ise9=Unt}fEDC6RoDdD6p#L4R| zuVLualo25z;T#arx167yB)}If8+W?7xzbx?Uy$9Ygu~Nr?l_tJjRIWgC=gLdFJgs{ z4H{N@`ZgVK7t{qaOKb!3xdPstQh)V*B@g?}M1i0piHA$+;vOaE3bhrpLkhU{C=lCg zGuI(>WfvN;(f=YK*|M8^W>FLUd9teGlxRRworR!nv8-yRJ?hT2n|^kD6@#5BwR`5T zy{BrRRS8@c?UkAWTGBikL)Q9DgyLi&?);!p<8WH)=XqRfF``DEk?`hCW<`azieCBn zD}d5?G@5K#8K$muBd|d`_PM8r6`%1VvCBH@)>b)}?U%l6J9tHfppYgN)8Wtu)f&Gu zaSu6uX-d5bC(AsEMRO@35b8yH>p^dEk-X0yQ9j%l9^Ca9$wxTuEi2A<`I_XI2k`bhj2(q_+D*M_ z4jh`>jeN<}^0>7ldrbmzQlWPHAC;P6zX>*Do2lB__9onY!>cr;6|mKat&Pg470D1@ zWIhvxU%mSPnV6Byy>PAugR&@FF7X4*!$TAbg=$~NC|L^0m=vUqN{&_ibi%s(R)M$r z^Jisthf0HuB9)pW{Zyi!rMb>{PZ~lT*HZ~T3tE5BdqOH z-j%*pX)}@5jloFH<(54C2seKBs>Y?9cIcTNKcANL`pCk*Ah}bvy_+$`{GN!y`otKp zbfLRn-Mse~@4-wBD4BfOr~8}L;Y>%L|5qSl9*;IYF^lC1{=5?vi2z{Q>ejc>B!d#~6@;hcn#LTHM)ES3r%$QezjLDqgopuCL4RG?Ln@;pLxfcuKo zLH^Y+K%NpoLtx`1`eW)}ffC&E6x+*p+7aMpzC>eYOKdO0N*%6F@SWuiw1d z^Zt&(^T`F4<`4P37|DY6rRC%dvuAg2A2`TQYzUNiKF~p~{=Cl2#eSUr5_rGkswkI` zLgm^69d@%gz5@}RoPJhO->O=cr7-U_BIC&{xmmKUMl7dFDiG3D%t zjwtvm6abRPOOSl#MzU^bagNp4IOhPW2K8xdRaQwKmBo_D%y|7HCt1+&a%k|sueAmGcC*cXHL zUj&Pv(2tN^(_^i)~HuS)ef$t$5Bc|Ha`}Ywj>L2{7Y!Hdt;YuP3e2%X5YTpCMHCdyKdczoh8ED#ZsG~$&cyU9Q=*!EsLRYp5f z;CDvf-6_xqJ-?}g{CLV@QIZZrR(@kMH;!7)wy}md6xZIgFb!q*oynei5PvIdytk*?mB6j%xWB6NCNVMJ(#^#s zpunLvE0G=MxFL1$md6Ot= zn2b_7yuzAJ1vx`Uvz4jW3LW*|psifnqL;z}KBWWwyaB#zrU18;&*=?y{C)2T-DcE> z2Osodo76 zB)5^|_j7iZ;^N{~cLy&@0~n&9qHgQdH7^KdA3S&!AvCvfoHSL#Rh5}}w{q}|>8C?! zIBEz>2rmXNto1h7Pec_DS7SWx$m{y{$pXI^{F|$A+w34Vccgxg8l-*|K(QetFEtPT zUO@0!KE}2@l<2^T1q*(rLTv7l8SI5C8=Vqry?riQA+#CSFZp#_>n(q~`^vQjPK{RQ zdA2=;-R~Y76zmqPUu}XPA&37Tzw(ocpnaea?!smA$#gO__1RY7F{~m?o$a(5;X+=V@ieG8jrNOvG^ zCDe7q)LbP+!s+gD$t8$@o+k=m>w@ z*I|JNR$uU964rSg+-4Om3~t>?*Hg>>_p!kn|E+?oBRR$0Bsb0C?tai4d}Q6vV!hwPW*>2-;okpW2~b}DNK%EW8jXWa)jH=p?U(qU zaZ~c>XNq@16UQ>7yeW;gyAhbD3iA-4P$+#0 z)s|a$+3~L1OY~|jPqRWS36D_p-U1Vf)|f;^6FXwhMHLB7@&Ccbua+M3u-6 zre?V8Txsls3`vTm{SWM~8VV>U@X78v;Ee}B_=IlQ>?XUHzw0+~As7`zb(Mw6_( zyhOmSth2#$cewIkZ!f@lsUwnVq+ML5)OqTP##BO*#}Yp=kBS)G0g%!NhniMQ8}cy(9hd_f*S5GhO&713|Yo-@%rsq3v z5yX(KHGO3IS(^O%FP(uEA$YjR4M@skB-Bk__e3A5B?MD=LQt3dxU;Io!Ui&_JcxZP z_`R!~&0-g;sl+MpUjZN&bvL7&aU;wvbK!^HGC_=-zx?%i-O~{H_1VlycB$LMl!)|~ zxZkBb@S5`Nk5*#VZO9Oa=gn6^k-NYMRG~F?aywWM1dG`E&=YhHy!#N$#^{FIB_t$( zM}SaiKv7|#ysK*^83H7A?W{N6NU}YU0`rB0gaYZh$Rv+{#NW@EnQ=(ZSxb4|)apL# zi+iWH&*AnvQbxvNY#!S-Cu{DdKBo|#$ZsKnp4cKYp_3j2dh@#4+PMxtN~T0@6RG^n z3iI=|4&QCk2?4$ge-w5mi;QeHE0JZ}w;h_Bn}(z_5)8dZ4I6zy(ws z$%b?6G!C~!T7g|5l5Y~*Ap!u0jCQr6mzf+-1rrR14N3fi4&rCcL|>&x-QZw$>(E8Y zoOkBHQ7m4%JL}W9{Y}2hPwnn9NpU7EZ?JczJin_!?iF1PrqC&0m#wPKe9x9wH?^LJ zL`hFd+ZT?aYzbdg0tSyI{SU57_}**>jI7fn6PuIU?^qSHemr@edt+Gz+!xh@Bu^=Qfp_s(T7AW0%=^qK~ZeKh~-A`^~x^ z&_l$kgA_kM;L2Lz&Do}eAS~m*FFi;s<*Qbu;Hs#qg7WigRGv_fyz;FWFV~e{U#H=& z)w(?8BWKXPor|fLjR=y>>76N=9xjbtC}rb&$nlvdX5)*do9&tVHrQb%7VwzYLfu@- ziiI3Tb91r!A{HCQLDpOVXQFhoclqRJ%JX?(;1gz2qPJnr2z&XYtoTl|cGl6@ed@2` z$dAc73NWwt#vRwU^pEO(-(UhmSpJH(>CZ((y4*U*PLb*B2#xmS)Si@X=-uMzo`ZQt5&3* zWBd+$Hd0t%BKx(@JrnUs@-`)9N!qMmSTxvlP@3Vi7Zz&f^D4dBnv%SHXb*NmVPGg~o*u#xo8FL9*N6mz|8& zH478kG=WTlcDsB~g{=PSi|}4H3uk4dG`@otu)2oMUV=dAVLis(mf7*(-6?plSxCHNcCGoIA8m{mkQlQl7(rPt@Z*h%wPOiavPu6U9^ zq*}^-lfK3)k=wSGf`TG&0e{_10w7etT{Oe*H?S>}L{N$pr!GusaImg4yNo0o8@m0>)+$ZxE{$8!{ZC0jiTaU*#X(mp>W$D_+4n z5>L_epO+v*?2SHrE&+!5`TD*@o%_F7+R}f2))O86hP6ax+E(j8)po;OrcFNnW3d57 z&rh`h>zE5A0}wc}OG-+*#>;IJ0v0WD&@4+h{JCW8$Ng%d!Q*?| zRloLEoFCPcl^;fp^@aj~6-Lcot9bd7c#wiKVhT=#N$_GHl^ja4V5p)t`?8PPNK zr2qpZY>m#&5n+{*GS+Edb*Ymmjx$}zFD%r4>Oxius*!wO{jHss zT+I`emR-QYan@^%7dBZ%l&advYjwvWEU*>K6xhr)Hfk{- zf^(ed&_l3%waWju*o4dpJwy>pa8LL33-)l-r;H%sJI+SnH|$bu?=P4I9;HXU1rrkn z6%`e^wpQiuZl9`@mf0-^T{ZED#-8b1amlyW_xrdQg!627383dHox3bw|8EE8%Jqz1 zW^1iPaI$!^h>csuZU>7aaw0#UOUQB^*x}(nJN2S?-er2+I%IV_ulovR`6+34Q~_Si zw(V(4cNZ-+^}~~qk&(a;8=X;f+kkOU(2Y@i-6LtNDu^XHV9PS|`NIw}N5Q}mzy#>} z$Yl|~o4Yzs44KT8FD!3;No-$*5@yQ*aE&dbo^mvJ+kZSck?y|w|AO+=y_O|=g^d*{ zyPM;Y!J9b9N8i8%%iuz~trnV?p2ukYJpxt5z?8kQpaD^#NSSzJMXgsDa2&orFvK*_ zW!MRBx%BN=%!1QC{aiJ4{xyT$-DU}>} zfeoXA`}T{Y$!$3{DJ#zu}UR|!uK-Xrp!I1`kLbat%JG3UrDdSxb!Ui+gt#yqN?=7HV*`%4EX%b2`Ql27!q z17l;K%FKX&p-uu%vtLJ90@K~cu}(jEnkPC)T>YAX3t2StoX5+-b^YS&W*8>|WQisG z)bi^C16yhk!|*$TkKYQ72D~w%MBGx&Dxp*obf;)4Hqm|)9ih*kN@QHxRmpm*lH!Z= z?O1VtqHq*pWznh9Wj_O|5j=WKX?HsNNdJ4zD}HR=4zcrjvTT1yWaiNoVSdE48{bJg z?p2;Iu~zuiU}@rS!~6Pz;!Hk>6dAwFt=P^c0f#%Sp1C9X(3y7mg?Y{7)!#j5%PW|N z+_u%U7FQZ6J{#d%N#QK>koYvxPj~Fza8z7Bob@k>AeiylRcqMpq|5*9x>tJ)szWZX zx!R@lM%zK1bwEyT#ocTkxk(PW+UY$BX|ZQ?CBCIms^Q}CJivX&*CLo+Il zu7vC?y1KYzR#t*|N3r@oo^xyd{`g>O0f5gF2vSl~3OEku3wbCJJi1~R37k`9LxzH;74Wel6y~g zFVcdhqQTmFSGA@R@JtVGhcaGBv@xu}Gry#@DMO{VvKZMyZ!K>?At&$25Ou@XmkEBh zl*00oOSvQRE&p6%`>kH)ONx+y? z@=3SCwR-nooq3Nwp*bs9znU+kft6QDzLkT${hPwx&!4YE>Zel$&K}J#&49XsUc!A7 z34HHDKpCMcb?7t#%T&4!hx@kBDG2}NSO#zctYT+MPq z$=|z6jJ8d8kME?bCCV&4Hb2(k2DzmqJF;s*b8@Td^r5(TJWr&tG+;8^u92{HbGeW? z5u%poS!zEh2UvIyFGnl9!bjq@3X;Rd(7bBa1Y)QGt%{Q`j7esSJ|bqbsn8U}2uHOg zuvvUN=Mf)Q|L^i9abQZvkXL@d9dug3(~{_ko6wAY-{CKNVfmazl8;<-!j9dN>Bvbx z`hdhNHoe|JIwt}ZyFKZIp6}yGRlO)STp= z8i1h=SxB!#tNigAn=n$(8n4;<7X(KstkZYF;k{*TR!r}%KV?hKjFyLCsh~_o*74Jn z`&?ebKODhp1#c=%9hET6;AZ=<{a2JeV8O`vgyl*VleyT9pHpS35V6bkJ2E}Q|9F;^ zCL_x3C4QVHNxJp@pCs*jO1}b$sSIS!v7cu6L@b|5CMEKOnr}mwsd$4zv#xcbgQ0W; zG?yELmj9vfYpQnXex5w|2fHAYo^!D;ZAdzxJ3Q-()Hv0|jC zmbu;n7!4Jl-CTH+2h=FBguYA2wvT>aD0Igg%M*|XK4-Iz{VgC#?ty`9`@?wO;1*xJ zuU?RX9rNep2=9V9Wj2Um3v@Iz_yNI#DosG;iP8ed2AlcGjpWRjDpyvqNGlj)I4bA^ zo5iEed#cix^Gytp2d-*Yt?6j;aw`&4TZhZhd})?|=i{ zN7y-79!5B@w)Iq^`L2YJuQ|(CZZH=%#ye~9gujYpI4oTN8^WYB>(h43C7vh_`kBT0 zrBe{7jZ)-cKyzu=`}u$GXocsu=K(+h@tZ%r@qX+xk(gRw;ENYTJ2E zZeu3){2x+8C`FR8k~QouqjVus)gAMzi3&bV)my@Y0F) zKX2J(DTSk1j%Yds8Ys~!s;IaQyy#_tg?@4pH!EvA$B&61U~gJ*Oqq03W3*%A3ugxM zqgu+FoW<~`)@8*A&mMz+}9*!oaO8vArS!Dz$v*FOJXkmd(~ z{eA5>x^ck_q2=Km;mQZBVqF@8*ec3>8Mu+G-=!;lu>Lz`IWrEty#tr`AAWO*+ZQu8 zt>Vq+M`zt}#WyG)V-@$6o*&vV6PRQ?8VdFD8qhP0oQb&aa(*CD*;ra={4%LGh158f zM9t|o^ufm$F@GXAAahe^o=!(ZTm!!ORH%CQl4M728JUcqN_1Kof9nDsy~mx&y*8Ci zz+#{8t*XNHLepkO4XOR>^u)MXSy=#il0Lx4vH~R>nu17p`LiYoqFb*&6vbDhcsP)? zUz38DekGw^lvoBI#B) zIq(fJF80?PH)Qa}0$-LsLtU99=$BQh%}G8I4W=VpVAMlnal^QkY_-h*g+KkhR&u`> zm`ZWfrU4uQ$@P4A9H15>V=p^k`ufx^;tYv=#`y-Cnvfcr%{w@U%|RPjYb03M#%_1jWJ~W?|TPoWcL5Mr}Ri@ib%w){-EA|<3)(wePayY zQD|~zIXnx_csjeq(tT?mC_{d&>eP@hg`9lWM8bS%4~qD;q+!HR*e$%6Xhy17IO@e< zE{T4bNrMMOFZ?-)4wG}aK@t4@)HI+ER1%deY}Bbll*1RVjqmNbP$&UhH9S1LI%ngo zUwAhIfcnR`V!1E7u)r^9FyG0udocKlO*5P!OCK{I?s^OcY2WAL4A`vnFGvwz6qlce zqZr?0)T`3~;29uh!U_-f*O|jnvad@4Sg>PO)zxjx@?W0DrVczekrAJyoqJlW_;pdL z^r3_6kL+7d@CnBwSBetZ1;&{qP3#610)OpL9Pyb1Eg@A#VExZR7b^8Kd%NYZ8~KWBr)deXRqiRbA|dc*4s{O7~ntQjp*0yw5@qaoOctHEKy@VT+g2nB~Uc>4GWP-us@B0=D%J*{;f;E1>S?m}I%o(R6v} zsN@d8n|?serqw|vK2m`FfWy^rwU!9ugQGs(cxgn2AUQW!IC5De|MxBB%x>cm?j5#$ z8;sbj@=EIS$GubeGl^c1jVFM`_NLag#BYYYDkMJnvek4_AC`1>({F}W*HBkAHw2(W zW&`-{V3}(Z(Ycj7ITr%r0Yl{d~>@50arL`jm<&``~&a7yEl<4z-~caUT$7BZVTi2f&AZ7Lt*3K z{vKRh324ry`CVRbE_z6j{B$cTZU9*@$21X z=uHQIPwx2{Pr8W;!C*}xj$TrsO^7@)I+BA;26T0=+xgP|j99VJ>~~qIhN0Sb%%p_S zs+4^5Mlh7^TFV{bhNM)pY3g)NknO>RqjZsOj}+D^wBH!LEPt#D6~4Aj15xINXTrpi zr?|PvIVNBB*GQ5ta4cQsT>ui?#}388om<<^>Ypaw$m@SE(MYb=d3|_%DHd)VSaH?C zJX+P;j15arR(tHrqh)DV+Ue_>1NVB*S9{>z?h;vca(M!Yr6Q*9nbzjeVlT2fU^*DO ziBj$VGZt^XkJj8p7w$Q9{>kgBIb#%Q(ncJh9vABh^nAi5DK5)) zqk}v>f-FcQ;87a>ZbhI&|NnE;qB0fD{V{>X>UPoog$9-`lJ-Tl0*fW`t8GN3Y*w!t zcYQ~RMbp3n!O-Fb&bj&*SWP?EP^K&pRSJaW%`b-ur9Qy2xFFgXrPxf$17*XdlU1Y%v8SC{kqlp+cC3|A^m08n^zk}c_GbJ(OLK=a_f_mqzRHQ zeij0xFE?~k9D;Z+aWLeJek^xO(dcd=EB9IQEzDMC3#m6GYtPnNN8;Hm@;>|+7qERy z7Oq3UgK!T=%@bT#b9@J6L(6uzV&Nk!mg&(Ps}Tx5US)6;O+ESIfA@J)DFF2S0-y-J7-MlMZg==LVft5x|`_28jS)7gEaT@sr(0-JL+atktmFO_@ceOo&!m@y2$)$ z9!}2Bc(}1N)S{Ods4Zo1-lh#IP0S22_S>4Qa9P7l{mWrjE; ztDidY{r98JVc?a*H(2o3vLp0uYcTqjMfHCcD**klxq6>>0BaO%Vs`3PAJbuOK8mH8 zoq^>RFHY^YaIo&uF;3YdON`~ls z$3QAp|KD_9fDeNbF@tpxdN_yc8204*(1Z$7I(oS4{F?Lq^O}>WLs|bva4O27Lrr^oB6trI_nIC%E8jF` zwi@o!JtkVU+gCo(`Oy2lEhl9}HexfN<(Zy$9$VlcQ$gzmheBy?_h;(+oh0qJc;kfe; zRtSO|dM%F#M6O{+Rog!Y%OVR7R++He#Yr3=-GSNb+ggeMUWA-j<(?ewPpL#e7%4K4 zp9Tu}HyP4ufb*?QKB2JmZZaKKs&mT;o6}@&O(F&07LV*`LUpQ&s=N zX*{lA-t(2Nhz))!b$S!$5MIfj5@@W|whE>JL$SzgS%BCb|B_D5h znNO55#tBabcL50%OIGXz`l}OFyXd0-SW+?o`-LI}R5?Gz-xYxC+uj=k?qR^+6Q-*v z88I3SN7+5PE;s>nf|}Z?Vrpc<80xl|uXpJ`KmNfCp~F%tOF$Mq6W{Ksy&TB?xdF`J z2CQt^+DY$-4NOMCzsmx0Yz)fvd26in1xB=d$`I11QAo({Y}wMqXO}n2xeSt)cJsMVpU_Lu;?1Iok`}2?E6i;do>|W%n@M@HV)*3y6tby(Lm zH1+l2p1VI;cz9q=8V96G9*DqTP!?EN$w*>6&vdw#|DgEvDW5a zJZ6y%P=K`$@(+6Wh-7(*lTObP5h#$OMw_vWe+S9*2e7RRs5H!UbD@E0^#~3DKAxZ# zvJk?aL`}o{@$Qc~B-7z2e2CgAj`}C^goFe;uxicLma|6A?aOQS{BU@h_OO${zrQO2 zE%Ap0x3Hlrj8Pf*s5ps%gJiA+5HVAT5vU-GZ6OY!x=fycMU9Li$5lZxezHdaecnyw zUQS58hc+@<8L6mt+gvR5e?j^&HqOauuFN?_<@3y6&qDJ0iNH`zU$}wb>F+ifU)sdd z_C2rq<}5M*)P+W89JExpAnboDL}r@SkV0&B|6Y5Q=>S&z8nUW_0s=4z0Brq^4i;%? z5WhJSD(D~l0~hc>Hgw_yG)E2r(1vFC2jrXQL8~UB@>QP>DTTe65&;2$DTxpw*R zkzj6nX%VoX<3!W*_l*gOA(hULc@d~o1$^bNSrI7te7F!0*ZeSiK+O5Ku`wG0d9g@h zn|D>ik0iSq|JJ!%k}{H3q#-Q#6)q`4TSaVnzs=MSYr}LsXzlH+nL#Dy&x9U`l)rS= ziq0Wk{FAmdO7MiC?5bitmDSaHI;BpF_J9hmut!|bsYGo|MMIM(z3>^MFJSSh$M=0r zO-*|Vldi6X&e>hBXP~v`$`3eP?97Pa^YM8moo3@&a@slj03ZD7V@6t+zCi}kkUV8-SMsg5r3 zP{GFe+M?aXszc2oLxAUoebSg@=yI(yM9P-9jVKfy5Dw1a`q54l1ziiR=#>iF^9t1P zf^asG$j8MnYuWsGiy zfg3EwduVDJ1BQN;M5YX?v!EfY`~}T-1D!BJeCe#@^t&_#JPO5lyvBEA(lJr zN4L#Q^sD66CYm%-fgaqavoEe-ef|VWDJ2HA5SqY~myZU$N#@ScuUu(Y>Y}uFY?gQ8 zQr{}SD|?X-9hIFQ151!NoY#%1C?RQ!EGx z)I#MaQAJg&o*NOvtUoZsX1)HrR9(o}gwaJz43ASxbP#M`Jr5RbPvAt&KNy>?cQ5$q zD60MD3V{ygCmstRjMCE5dZ?|P)5Iv_M-PClM`UkV@qlawJ+OUwXg&UAD1mc*zTZQt z8Yst%ntW)`TPMMwV|Xc>OgDQl*Z1$VR_)99iRp2>FBkOSd(9V<%a2N0gB})bqCO|| zYN0``-#FSrFy{{hLVA-rJ%)+!4h?INaD$b3^<)9HxFGuC{-0n=qJY8>8$tp9N<8 zK=`+4OvW_W$b6Tzb;Ppy6gjN*jb$(i&i06`0zz`3v zgXd4z8xCF^mr*V+D@65a-;O+wr#LyFkR{^73y!M5=C$f$h<3By;A}sQx%8WpL zRwg>DXA(1K!p*y19%EwqtJddgG2o&cy4DQ$z18nRpMk3pHT0Nju-)6(V zMcF%T zzbFytg+gv%0Vs=<)rruLU{zjJJ5@ z@AWi8Ur$uP=f$sn=#G(2rA>I68RA`(mP~%NC%$y=-Ggo)p*$bd*4Cu_IzlQ}x;920 zCT(Eksr)ruX;cynfZ?hlUuXg17{+x?HM&-19PNhuA3oeAxq}o-^JwFIazN@6Ps)6hz;IOhr9kx z6*X{wWwrjqWzQwEee8w9d|r68SbT<3umZCp6IRMhsLq#yQVv%k9)q5HrbD^##R&bx z96)xyW#YXd)Npn%c^~P-2R7=y-2xzdCZIT3Bg^c3SMxq?0f`*goU^)Wf1Qfz<-#=& zr{bU>O!i0MIKdD@OQ*VuI;A_Xx4TaZf_Lg%Ax&!pDTo|p`K_TXE&~H5x6(Xf;~JOg z5EE_KaF>Cmw)n9sx|ubJ;IL~L4DZ}gA2$A#37n%8$P%A^{TQL2ogYe6uZGlRI*S8z zN;dPQ%nqqAY#8S4YnFMpg>kldEG%8h-FOz;{#{H^UbUV}4;xEH7}(<%y^ULKh}haw zSbls?+creSI$;;8EApah?XI`P=^K(sHF9OoX!?61_>a3(`P~bvzP}m|wJBj%RyoNnYhW2&8_)&}=NK8?toJ!~;xVq%?x1vxUXNo{ z+5#pxdExbdeH#EcwcbECdAhCSbFxwGSU=6x6p&4Lqz|^r=D)zeX9nk6{LdH(Y1`$gJI{Qy!92^@2+<9} zHX=Id_dkE6)4UT6*w)&Z39NYfsXqtgpGZC#1FtnfdjoLpfihtWFa=-6RNDVGqHHlsF5Xu^$YcyoerORVenHb~IIj;6O^=8*F#UM(1LH&(%>RBE4yPYcsHJEfu17t%9`ZSO+OxN`a_X4k{5)_wAWqLd5*vA$ea zi%qho07vIu{om0=U5P|>uCZTN(Y~hSd+RlApBb|-Zdyo60=%;0!^4?+%eH5SnjtnM z_^4vwr(^8Jc)m)DY%FI$OwKA|t8HEX$Z~wdna|!ujvzO=3x_$@!>!}MmHO+?%KMDdn*sARqwR(oe)*@dq!o6|<919d3uo$*)@ty|KKUvfO0`!!8%8AR zT6aXzj|kNDLX;d-IL<_^VI!*C1UQT-H33ctIjs~yo@S@MBK^=$QEf#SSqFL2#-q1% zl-eTE|BfTLg^(1;1++c!dnw+Ul}LpkC&-s8KeWHQcteJW&UujZber7dG4MRAQ%{#W z1hNm)+6Vx@ARAAJEoP^q@uaN3IyE(brb$e_qSYk=2(QDy9%6RO+On}ro{^>)R>avi37J|mDL-Y<5&CZFVCJ_d|D(K+}fwbdVSj0IKn#@^kz zuIh*dFi`l31h6doUMIu!h>Zeqs3esJbrVdyTQJgQfe2{c(EY-VO9dH&9>} z*c$D zS|j-u?1GSh0oWdA%x2LHdP3~|nGVOCI3VU=2~mI*6WN4mgWS%`^_KN-S2afoK)k2> z6#0*z)61<#oh=I^-?Li^g`?P&Kc_|}9Ss{!#vH2ge-Z0%y|*mwi*r694rmR(=v7Hi z4um0y1zB(S{?m-#%$%7Zj|GvKi6qwdj-yvCY(q1I?xgm>1XxP_re^v2<#? zUDCV*2SDj2T+wOhB|-G(?ioE%+MwVxu$Qtc0(KZ8)~&*!@TZauBD|N9@oWSi|E+FQY%wCYAgOYh2g!a1|E(PLP8LwrE6$GKtLKn8U~bZh87g0K|s0@ zkgngE=h63le|N2W?_Vz0LY#AEpR?oa{rRS;Jbb8290(6t!ER*nNhsH0(1nOUlxz97 zWdigNfYZap$bN-&7kQJE@YV)fJNjh2<9I5O(#S!fCSu)@>|zVj;F8-K;nK=WaA%z@ zld$P>>&lP1ijH@pChtbFfg+Gvz03dds8r28?XWV3^gXYoeQY~Od)x|s*5;5mP}yZ0 zxC0{gr$8ojtg>Vxrk=N~ftlsmC-+b!M?TE?J zgoo$;7X^hAyLq$PJ@tn!^9?cIe&gB5)8C!D`I7dmpU{+vB~lYoB-EbP zMyl3QQc`}KoMdC20UfM~(4xh4pk#bsL_{qaOi|`eISNlH43&tQE;mIk$=}xmSl|Og zdZVsAKzXVH(-?ie1qB69rAjAR$UZ;e&cjh?1yh$*5qMK;@Jg63jb6PLOB;I1En*lm zFjn}7uWP37(8ohzPBrqqlM(df-Iy6nmV%XA;d&5<@6y6Ha)?;tvs;W4H<*&;lI!_4 zU#b`wvvRQuDTNzhirZFgr{w?sI&;*L=m5{L*|it#Y8sC&*omI|!mtmVu8MAJYu}gE z+^|Ryc8u{Jn~S|8dVOAB3X3_t)JF6$?tH9xbb-CtGDH?LjlI*xaNL)O@Qh#yDScC% z`|R_R$N3M;k~l(&40-(``>Ge8aVfZ$oKn;8^Td*mm08m6KXxR(fJt@jVJB{I9+!4TghlFMYdjp@C97Bx&vA91Shh;0br83_`2KV3R ztW1`iAEGq|KGFLwO)%6&rHAhunxL}o8{kaF~g( z*IYa{-#?oq8&+fpT;pJYO#jG*KQAZPZS<311qq^sF z38a+|3z_?jnneNet|o7zpY*0pT9b5po1jQIg3M4!oO#~~thX6d@dK;T^;hoWcZA^G&?>*ccIOcFh}Yb|csTCKEmsgC*c6 zr&lO$>wib}x@g8j%?kPRE!-kL9YWu(9kTqe+6tlB3+5mS0gb)Um|FDD26760y(lU9 z{Z{4KEumzBqp1{pmkVro%5hb&n1^v5hLK>i^Lu}J|GN{0CFlT%GZw$JW%?Q2lHIb$ z+m`Rt949#A?fPDdOps~l!Mj6HGkoOcnEoXy24hHV?32k+o~Md{yG=jtTB26}?8rM; zauui!MBMAlBzgjLAL!|p$W)DCysSwn90+MDTfO}PV|eK6OzJEF* z>p97bW1hR0k5u}3!mbxuWgAyumjVX#En_B@FDAx1uX|1a&-|&aY&AVWSZ8?r>vg)Q zN#>OO&2{jRm243{|5{|*Gy^!cPBG+WJCt<5d>lSW|6`h?kin91n< z!1tUFrH1+T8`9aU!#I$O?B{y@hVMEFCO#3oS6xn~VSzY!Nu<#&-|b$`_uzkg$SUzm ze-Wi`l8Fdjz!eX1=nmUiy-oajFe}_&;GctlTun(-oA#9=-s~A_TD-gAk6@KgEAsF? zl0`MsTw5$5p|J$=?eem&$&HhR245=dv$Jnbb0HtDE}lM;_*v)d(L0Pj&vIaSGX(62 z#=phqA3O2}PgCxau^jV{)Ugq|h*$zq{%OHr0Q8sSb}ziYKk4-pO?an9HX}Q+RXLbZ z!Evn_LZL7xLG#6ijy(SngeZPEWr*muk(lUw{1{OluCwg(&rQS^sEiG~Ng{^74eHkb87{?b z#2Z{IUrh?NZ$Ivbc@_tdCY8Q-pUNICS|?z$9u+4c_H~=P7Y~Iq@alik(9>yLG9StX z`Y{Kz3!oa3#kB2fM*7Nzv(JE0kvJvZj6=cEa`ffF9dPIUxsbN8qhF0%RqhD?zH;lm zTNeKCUC@S84}@zLGnoBe-?QY~e>{x$hO7G*ey-hKXn@1XK_L#BA;vFS%+LuREzg7(@R)bVt= z6af*Qy2~kBIKLr&ze6H;DE(lDaSmdIsE9#5k;OGA~>tXQXV zzkK9%5zocn#E?|)!aGA@ZYJkn#UN^9m7pEtvl5kVsUF10G3T%f=8JdtrsI!yGbbf> ziN?2d{Xm{pUh!t!ou)m2ypv+(*Yd7{k_AO6RV`25Icy@T^1CVs()q53vwl8vl6SSf zoxstb^P?eYnv4vNTeu&&LSznUG}djR{o~(Ak^Ze;W#6rw0_oqrFPXxMCqcrLaS{fJ z_+q&=$3>F(Bu8twmkj?yxPXQDbAlzQE@Jd63v^T_OZI8=nQOrFjUiMqV$QZmX9^6fk`l`^{Z5??OOAajs_#zEFU`2Tc|&xM z)jLm}=fk6OC2@HK<%opu3*9DqD-&Bi(t*AIEEDxb=U8u{~ce&rL z`_%Ny5tpUemltb|Hvjl)TjW{}*AJSzLXhXT+ z%NNb5$`ih`shf_8ANZX)@_f{jm>RND_s`CNO=$z0Vg@!<|G`uGk40%)p!{9 zg}}4i*q%J>5ZDo5wU~+rgVqA>K#oFPM->5zc==)U_wF;`re_`!|M#fhA~w8-&JfSn ztU)ZBy`gqm-h{iR&C2o_#DwqPK)p~mn53dc)xH0 zxs3N}+~JDbwK@BH11w-AQ-z+&e^$bXTuFT3;()O@awR{$`_-}du0Nwt9*99Hw#UvX zlt81ZNsYH0<}S1|i7sB3kDQ#*)1gAKVV{#xKZfdpwgaY@v?d`ieB*P1Qx$~p*-5S{ z%rF=~qWhB=#3=L5OELq1EQpr=d+!?VpwDXfhc5|4OkV4ICOtr;iqQGaQ&lFm)+~$! zTUmjISxuvb_9Ml>ND-jg8WC z@{0(!T<5am{k68PbKh|=YcA!GJNxIvA<{scU>J8R%l`)imJd66faW58x&9oUS8o%* zGL2(N46R;u5@H-I_^A5nw~iMsWCn;0bQ8Y`OS&M}re%ia0yrAxug64iSt9tg18p{c z<+~@OiG9NBj{xb?u+mElBWkh`;f49{SAg`T0eLGp-Q|9_w48|-2?M)Run(`Z7|RY= zae3~GO5oiD^E`%#`<~$hEiI{Be4Kc5p7$>2Q%X*ip&^1NyXJsYt^+Ahke7${g9L5( z`}bf3LV;ZksMJ?_?3q4&b1SX}=EqW)<^`~v1hi5igmC203}_7hHZ~TDNkC)n>Z)7Q z(IJ=k?p>$-XQi#pi;977VE+c*k}j@AXyBA%}hz(CB-J3JepFo;2h5Sa_&@Ig(#--Op+{@kJ3Mm1?OVTkW0JwYrm>y${QHsN;7kdRGq$anc_7cw zRVLwU&`hl1e&0A}0-b$N$iI=azKew@SC!9(MQMeb!%|VmX=YFs!MQ|8OB;SEz!}LY zNHdT^nnYavC^#iQdeUVOvk+H552*1m4C7?b1K?UHY%qX1T+vZ)y$S7Kx4;(&RWQH2 zzW00n+$_Xr)BGTsj+vig^Xg-Ev1mk{C$l6iTWkFje=XjoL2j3~b?@uFa4l-7RzJ zXE7RIKNzJfb3Ak%n?EAVJok=dDa>;xfcW29&1wa+{9PPGM1;yte)B7{VjwxyWGBJt z`!WtDMwWhf%y%IluNSj47d}sz28S-vDug*u`+Cvb`KnQOY{#1$^f(WAS!J*0+z8bv zL`$w&yf`QLOrG6VkP9}+|5)(C6!72|j$W?L>bHQy&XKt*>wlMks>fwdjv)Q5=`!j2 zc$23gPQkMMlXmh<%T9+vL~t{FxqNy^i4FshRalkWnAbxLMTVbf6UO(UAk4&Lrl@E^ zI>v74M#jW66fv35%w?Ikzq<3Et)L3rZ*j-FKM&$Yf>f(P6(z#m5#nEtl3~kwf(avB z%ld093kN^;LN0bqfXu+cb325iDC$7#6=$^bB?(S(I`kWp?z}aidy8^IRKJanvoNA5 z2sujj?K#cV^syA1D^drhyjELoiF{~4|0Gn8bOfqi1=Z6FSwNTJ+9go79 zi+O&2zT6`2zWrt&4Y*EPG}D2ZfFR?TpW5g-=I8`e-7Y821pJb_ zin}(9RfYL$A5|zWdh>ZeGxM*U4SVS);K`jxPuoEiv715+SAC{8CZ`s{!4`x<%Rqdk zZR$@DY2>eD0?WmggQjRy%H-XI!#?XW^YH%Nnv}L_dOoqym>f*}DhA=^8#1D+JCnF( zL3s;wUs9=_F$}#XdcA)T*5tI~@}o(07#(0Sp2(&uRbC(5OPPCcmce1MwowV<}=_bm*9Oz~qhLt|!uZ<#4X zwb4X`ZTys4IH7ag3q9|~gf$*wtAY`)pBxJJ$qL=r1sL7c+*nHM!|XmT|Hph%+Bg{a z1o?yZ+j-b6HBN5s9O+4iRde#C8lf0n3wviy@>E-PG5Z)jS!mKn^YBG$B526gE-7L- zCf9>poC}h|A;kwI#KE`2!y)@4@7fbzL{34`or=_Q3sCOoT<>%c%oNk!r0cpCFe2}V6NQl+~+TmJ~O zC0&>(2cGV! z{?j+nF*R6_85i(|yiNBh!akBh`z=h!>U+6AY?82x=v0y?WLxsvtOVLhb2WGyRV<|_ z4iSSietv+9d}$s|IduPf&6Pw1^ayF}D_IGo(G^{D@y*7{9_mL=)zCYrkyaITv9B>; zO2lZmm^R>fSTSB+U1{67@nxNhStG8WD%O4i<1;YRJdfe0=Ff@ZEfQjK*fE=Pt1;BM zpje!b9zFg3?j0k%3U&WJ{kVt8s-We}%*>1P-_KryIVR7;L6H{+%c|?I9u%qu^n9;Z zAPMXZA=N+-{QmvBm!--Y;Ar;yIV% zN?)YT4l%gr=e70xTLuMDwirlzIcwk|63TkOAJ%!NW`QC;?rd9B_DrooZ`4=;NL;h!1=re zeQH3hoNm8+GGh9;5?OY19L=7+rf!M7^DJExJmL5kaN;oK~iibo}c6@WBY zrwY6jj=qXvTo2L z3$z<@x<5Xu*j>s!oa~-z#_FcZfoXyIBUKG8A%igUrr3YuU3K#$NVb9FrKFpSsT98L z7F2Xh_17kM@8rb;ffE1o7?|6zf>vy+-yLToDh8%YJu=)8wq&}MBrDE_93bcZrYUok z<OsYmY-KC-m zhH(?Vb&lw3(BnvoX2-%{*Np78wzI?POsu#VFuNvdy*{d776;${z1vc;e=00({h**@ zA|@`CfX(<nIL~Ya?#ox*g`*7NHlFX(OVEEG-cg7bsSo4JXMV#;=+&H4HA^IF9Ok ze+YSRW*bf2GH?$yk^Ne86I=(&VGkfU^4>0_WaF2Ju#4%E*fmM>yVzV zrJcOGIntm=VLa(n*oS6JhZVup>eUAVZd4VjfRO~%wp+9@$ zNq>w3Whljrvd&;KVz^w@^^UXu+pm?N;{*xZ$&~bYlbOj=Vy?Kd1z0ZoQ?^;Mut^{- zQVS{@KU?uznEzzfRLIOa=7l$Xg>I8RGuW@UxBwT`Z%~YmMXy#}U2Q$^^=l8vOLB5B zZ&r8~QT(4iRcL8}8X0j4elC7?5CWXzUAqJH;Y^#yV5e%`j8~hcFKn_!nCJ!zl-o6_ z6rc{D6k(IoxL}szgnq2}9qH$KImGi?nJj^xDe&NAK^x>;h{isc#R%VFNLyT0D0LQ& zaqW2pu4?&>pT-~7UMf1?Uv0|xYwGq)e1hL%1K<0%t2^LFx4if;gz-j(Ncd-)IFpGR zVZ{&eiZOHWD$qVLcAHsJp4oBoR%e{4(m_rzX9F`CT&ue#1=j4jpPSyKM#4ctLIRqe z(DU>2RdPi`!on~>m-SDu)~X25r~%iq`C|0<=9ADux+hkX-HReDSOms{bs>@cTkNK_ zM1swciYgOLO%m+poSdBWX`bImlB#mKKg0SB;ID>hapbngM@JVx6&mkT-g)CeVvG_a^0d8O7$xelFHuqJ5_NAPitU7eBvzeDS3`m10B@0J~%#p z`z7Tn9Oh=}`iWNR9F6<)5p}`?o;x!zh0#*W zj?NfRy5fDa3kt3E(Ja%W}zm77<>#L7;ftSB%FV4RS-`bUYXpk?|421OwHM)u+ZIUsE1^)Zp^DK0CVOcG8y zfoeo_mE5Ljz3XiTt&+E{};%^G_a>_A$DvO=Qpyc`om` zH&aAeo9_=#q{D=4So-@~LSUq4Roj?!_<7Y4(nvvFhz@Jwx- zAlb4~7`J!_gD{87T;N~J;$Y?zoQ}FKaB!J#jfswMH#Cv|wR?#z(P$dZGp6+Q_A?ig zdW;L7Jw}Lg^aQyx|g zM;4Ytq6=6z*rnJ1vr8JtU1IriHf6gx-0c0@*v*Xv zjF}0MX?Zu8-_*S6q~BHleMZ4x?X!!f%Fv~$K* zy&S6NL$Q8oCJzF32)#2JUsgaXgCW9jd6{>`ydqd+$yVWJM>(N5pg;F^|SHE@0K##&8obe zXl$!1&4AU+0Pr2LFB{0;wbII%7SVWh<0Y04DLr!%{zTDd?~^ry z5>-S#*Y41}^8iQwE5#?~opvG0%m5l$e}R7cL->9?4oStArX_ys+w^qkfBL|Vu{<-# zq6tiuvu|)*eYEJlk4Enw+~a$_H=@_t#hx=F#Juww7s}9si_s$qKhdYh&4Jo zN+)>ubN>5ax(A>!1NzHY`f5WB5WwP@^IE$n)H7k`fA8`lkn7)uCpvV?7@2g~q+uhI ztJG`x-ldLET=SyG#>S-z+u&x0(9%{g?W79Ywgq=_#Q~0?`S${ihtt>8vMo~*Zkvge z0MM|h^!)W}Y7m@mcE7y2zS=BsDuPYMKNp|=8q+qrrXWf!Ywt}ozRS_Rxzi;bzNTCO zhc*9#5~Rf)=Vi|ZTneB)bSO}COp{VA+j=j9DVg3^>o5X@z4FOg%f)f z1X*^VqT^U+>$98TkY&vOd?V(v=%}V5)Wj_48asTS{IH!)u%nlq1Bxo|cqJXNJ$W40 zmZ}tev*Vi!6A1T;T?<5xt?(HJoi=_q37Xk!7e_d|81JRLXbfr|YF zx5dT9Q5Aq{GdmNaX&Q{4UCrwJ$;ZOVIwpITnYQ=V)^zFW;G5n3O}Dv;P9P{I<+$i7 z@$YBy{03Ucr0hDXZoG&W?4j2Kmt!RcNo+!tF`htusog(+E%at_9!LX)&F^6n_&Eav zVy#~F!62gn_OA!hm%q>ed>i|^#Lw4P@{5gN>^<>0VBeDC#!mVXC8ALX0+r`(84FUjO>!j5#ofzr>DW(d}0i%^Oj>j<|u5xleA-i z7#Uh*$73%Qa{<-Z;{ur5lz9OTh4T$``RF=e`x@6yZ7STIlE>`9>sBr0uwR%on>pFl{&M z2iS%*&t91&Hx#(b5)(lh=^WME!9b+i@kl@7pVKse)IGBH*|73h1lildFsNGt9xW35 zq9w5(QtZ7_y=oT(sxv~TtI^Jr0B{C%06HCUEZrT6w2c5IDe8Ov$ve?O5^5&_Xk^8k z$JJk@9?g6;KvYexynHWNhZ;yOMI$}Z)o}tkY^xJ`r5_Z9|LU}>K%1cI;hWx4Xrl^Z z5ksLmPAV>*oT14KdI-?8K;4}{kyBud5A<4L_f1kjw%ndr>^d7T2)FJrRfSWkcI+xE zZ%T^`53gM)fmnaz@~t$lpe51Y4k8Vli9iTUhJ~z3YKf2$ghKO3mHX z-$ct$XXWAI3@l-j;1yb0hDBHTR$m}`si9)hh{0Y`On#pe0>|yBc`5?->nU%U`aey| zm5zWkX;Sk}%AIv+N}o&A$H!+FgaacZy3Cpm4j(x=4TD_A*yD8i8JF7Ow?XM&L1#El zP}}QAZ0sE&n-APklgL4p^nZYY(C#4vgliJF?a+bP(CZAZ(kMPMUM9{CVv zY+#zdEJ*kg8p$$wslXf!W+bZXRuunUSW%%ey#nYn1kRl=t{;Ugz9oF9BB#$Rv|TI} zurT)A@aBkCU1z1#;znw{#tBL!9Fb}Fq!+Xz(~l@fEDs{*l07?<*$FW^t;mim1ZTt%|H*N4XdYrWJ-AdM(DX&haM zEt&QD+}vz}{b z)AeaKt}iz+ljTljYV)U7_WRnV0OQ^@^w~vdTQ70>2px*>`w=xTf5M4kq?=L3uC^xRpO>=|8GMuY~RVSLEZfB(b8fX%!3O=!T|il<2H>}0Re$gLluunLqa&Q{PW+n39y|Ss}96i!=p)c zud*Y|fwiUst_nsAGPvJ;zwf~VJs61!LZG2O*M2fL3FAY7mNK!Yqn^`@8^vxW3rQ+v zyofug$+_~kd>?c&BZ2KzzK85-=38$WEZ5L^od1P%gVi&kqt@u84EbTaTzbcczSD~( z_C~LYIAZ1E=ic3*rQQ=*p0uUyJwNJ(3~`kXGTFCTt=Ur%FcZQW=Eiu~B(u*mYfGeq z542VT^IlcWzv1F9l0Skj@48#bXPd?20=TZffT)FjaEUb)B_)u4 z%wy>uMwyj}Iyu~J+$%0NEO%Yuf3&iBPs}+=5Vx$j9hg|%e&Ti%=Nxl>7NE(suGc5^0Pmt&G5Lvn5Xo~ z=Z8BVTUtyNNj~J~%a)84JFULlZF&xNX$yuae@~y;QrTw*>o()0tEUp8J3hL_O@A0m zXelLHGiq}0++`&kC83DPQni~5%&!<*$n@hwwrYUo)fEDXO+&$ho|)mdXQJNtphGb? zu#1EN<$Y9HxGEx{7us`?YBlFgb`bfWNnSz+^h-_LFeAT!`Xi=DM-#SB9`tYEcjmrm z{5sKS^M_-rrl$7#U5h>4{t<(IE)|%`^Z$F}i0KFPAR~N{`Pal;21xk`#~%$)>qgha zw)vZD59mriX{m&$E8TkzUN8{3>utkjK|Wo&<&GI~8{$B9WO>>Uqfm<9c|YiyPgREq zo=7~P`>KG$^H{ z+I(Q@tF&`{z>j)$UqK!3wo2QooHYXYZR5+Y1M^co@Am%sW30eQrUj1~i(LPc9&z4W z&(hn>znxnJi-^V(g|P6%2%kAA+xyYGntEYVT%0guR-GDk>(5rgUjQNSr~x!4t-+;P8)hrtYR-^ugf2zC7W#RsyNY>ZYg z9XeWCmync);YoG{#f^$is%4Simwg^w2KZzG{p**|#Xc0wb!B9@r4iPD6 zIM3ncmfv;u4~|B=fN1&OjmtYN36=_fA^#BUfXk2m0kRqat z`3ewA^Yd@V#KbJHm^QiaIC^=BA!l8IWOYgVo=KCZ&Ps=CjRW9yad2>G8ybqPslTg& ztrU+Bn}$cS+;yyNTf0+iKY4z&qN1J)!_es9-basjA))sVQ79!JoIlAs`u&CoPU_&Q zQ^|nlWnHaUiY;Ge`?J9hg_*dF?bDGt-5xvMvQ)${+%pBUiOn=MSR<}1+b-A<42Inr z_%DAKtUf1zwg!$Os_gw{Y@fSox;3yXD`Hq1!ZPTGAc&>+wH7*?=YqHwg+dsGYa&UZ7g^;@+__BlGWh-&PbMf;EjkYB`^QCsz z(H+iE7BNT~2^n0PERV}FxP|X3ccp8^3a!rF28-0;(C!T^-+r=5Kr-Pwh`o%7JMT7l zrvX9uyWBg8q!Ur?K_B^3Ztg27FY-;V z_>Pn1hW>0Yi@t1wSY7lppHDUavs8tSI^qUsNfK<34pOqq&-UJ*9*mQPY8y4ofN->7 zLf_^eTBcz+$ai=qI9st+CB?*w5XJL*2KWs@?b(sc3k62$w+9%7gh*!%IZ1NO2n!>~ zqox&#JIo&s@MB!Mm4}`TyukSBVkoq_c=fABV%Hkn4_j5|{8H-$o~Tsb6|tR81lfN6 z6ytmR3=vQ5T`8f(mkJ2iyz*>kqIBLF*K~#LDT`9WcONl&h?Xhcsui{g!^+b`N)D-` z$2CbFob&6Qa)se$wfAE2jV$Gg26Nq)(9KD6E8>{Vijc1(AF3+*&n@}O1xsDW{pKlK zKxI#C-S@ph3pk7AY>xb-?1||R-S3hK`jeB^N5kl~67GU=-$@|i1cn3VKz?grfnk8; zpA8*|My50F?bZzhnKIy_ujRfqP-z539DhprS#@4%;Yl=_x?#da)3;#Wd(?fgHx&VS^CjPvfZ z^QV-mwULwBBz{_0!qdC`eX^f21an;FrSwO7ImZ~^D>`mQ!|ox>5BcjJ40WupE5-X@ z<#n&|=^jvrg)`jUe8uL~xc}{yVkwK5to8Rf+tDiVzwxu&0zG8mV{9%8FE#62*kO2U zyE6_09|q!V<5{i>(a6LY{hCOHT&wMgWCjR?W|pk5xAr~T(oZuFm;2s|zFH?lVy{UD z-7d<==NrKlH!t*7@Q-fy3^5_Z$4Ba*oG?Ws5QKZC%7pIy-Ye0QTN+lQ0RzFG#UECB z8)1*&_kFWrVU)V=p+I&!NRcC9q0Qi?-dWQyd~6`I6b9pds5}x46C!v6yP_#S7UX;2 zqrJ^O`LmJQetf?DYXbSrGEc;`Dpg zbx2T9(2R2v);uYs5sNo1z3SgzKa0${XBOi{LfbB}5kat{`gIoHSwJwm^U9c7=LMQW z4Jpvb?gnc0|HKpqD`yy(B_mdxQR!F<(w`i%g7h9?j#>>BkH;w80w6s)$T5 zJ`!%ZhxLV&*CM@J#vkjdjI2L#EHBpe*<*z32NZ*@|Mf(ssPWmfjJ8tUy&G|md8@#J zub~LOs}~~7Xw&#q@kf_0zwJ!=X%UlvZ{jtB<)bz9-yjBEL_S?5a~u5vgvh+&V*4St z75u*j(Mkdmp;i(vvE2k_q)qPKX}8|*9JTt`KMqMEZ}fJ6=sR%)NwJbr)E7x}TGl6w zTe>byr&=((l!%b!Mk;Blo_~UA)I&7*z&z)Ohf7VCT#?T$#W@{yy%topm4Wp={9+6X zv91TBJMYQh>`(CTvm=wwa8s5)u;76p8K&i)Z)Z2=zh+zGXD#G5k6th-sUkLCzR{lu zC^eIe`dwzU8xe}M#)~50|0Y2pUlrQ5y1ZQ2{kaMAd4E5?U41>b{|d`zsVuFlFZlMv zL`0(xsKp==3VOR-d++lI>L_>!{4y|Ghk{$Pnt$=zjIW%C)h55+9J=4SQgJEB` z3zPO@Z9KJkFLf`U!96VG^*^LBtiXJvxU6n{fDLfEM;*R|R5E=%;LsZH-KePj&pYYY7^0Jf(K)6i`PuLI5c7{EY z`L05sGxc#&Md9!~m5kPaXjRmAXfPkBEZGwl)IZjs5+r}9`Inj-K$t=vsKORN@6BLS zxq+2X{+sS-^A^!ZHV-LIf@eom@gURx<}@Wy;d}kc8UmMQK3K|n>^Y=B{QCE>GDl{1 zP7Vr~XqDI1B?7h4>44jg&!6*v5zg?%May()f76(Th6j#wO%xcxvSnW{UOvbu-Z${@ z5b5seX}_5H^o$s2M}P;U^NR~mU&)4R9b0>EW?xV2r|3)H=-svd}snB*{cMj%L4-Hpr6*c!ilvPg#d?+=t$wJAkG$qL(DR7x{aaXmN55jDHp+%1 zZ?)n!kfFs&hJ%pg;d56|fwzbDn4>%~F^NIyuTX7FU(VlL(f-4=2O71T@GDSYao=wjj!+{Vw_}L1+<@(DmczD z#xYvSU;WtKwVimchHy=8{=S&U>W8|p=fxEny39E*{Vai~U@6CSpTx zKsQlP#|sd9O`-WVU_M{@+JuKZEG#VX{)#=aU5Z)tapI6N!nDpsR@E>$$9TB^1uB1v1r+LZ7IrF?Ev?T=3{1<7RH9F1R7kGxXd+@Nb= zP2Bqi@@XlU3y zf8GtC6y6i0aHRe=65LT3IfhRqY`)T;1R8=-aOeB_RGF>3<|UBvJZQ59OzNUj6w|%4 zwJc0!`d?!22W>7vufU_=5~rJA;nLZamD+tjQmLo1E*4Z2x4-JdPy8Dhne&7Ap)sW* zGu=m>2zDDnbw`nq3Et08b9Ui}XI7hI=|mG_yqvTdZ&1*xh&VW(U2u5)Ei@LFalHj- z)Kb1KYoWKS@0%Em1dk_UrJXN!FqeVZ>h}h=Z5ludy>2&8T&>$v=Ch%3gE&%F)lGN= zpTW}Vpp%33kBqpSISqPl4qd6OX1nV-Q^&*u!e_0qE;f`b4r&1Xo9)>{|8&eTrH97Z z#7z^jg_GMlmix4HLXjca&lHdUHsFOEfo;yNns!Y5-aOfS`NF#f<_jL%5+`48DB6!7 zHO?1re&619jE;^D*i)XFp4MXqU?`o0M8yrzRr0=(3~uIoM0yS6(o2+#(%1T5U~uY} zYNIBtl<1d02OH|-k{KbV(-~5}PgKpHQ+JQm8kY@JREu7Nsw5JA-gJ2|z%djs@iWY< z)<^*{7aQC3hu{^36m9JC99vGeN&|uQWbacw$*LYeyTcM1-~5zYDok!&@={wnJ}~G2 zkLhw5UYE^_w-%x$biCOl8k9M(WY}DG_p?z{5raOi37OlEW{Adu4a8?RtFrbwpfuoi zDm}T}=L&{TX$p=X;|{Eq+etq;c+3&PQ~Ojjv?4dQz^l)HV(QsUnM4|`T3RvG3y*pF z(TONNYZ%4`K}Gv#B~lIZ*#kD$Vp>pdjWU41wa4;jOQT9mZ>~>Tm#$9cdiG3j?p?3> zUn@gPTswJ^-*H)poqW#AlNXv^WHB~QdO!;qIQf)LHSic1x2>yfy+Cp(U>${MetZ zcNGFgS!5APjE~GI#HSsUmuh|2ovX8>X+j0Zm$O|$Q9_f#j1Kzh+TU5FD{w&(?!vLT zwbs<1XQJRXM%Z|_pM7UYJ{a_T5%|&x7l6hBt@|i4~bWA2J$Hv4B zpYORZxTAxgjdz`}ulkW&Pc;%|OVeOBzm1|#4d9RpB#C5D(Nz1unjr8-ON*H~pJ^!k zI&M6p2xbkrXuqH>oE;OH^F;H%zPT>tfO=Uc7XaZchU99a3Q+A8cp~;ONs&t#&Bcw= z;FIfTuDz(Po&BYrq)!>(|C@O^+7_*Vd@#W49{hX?exmBlO1l@FD=_X&;TpA}>G9rt zMJ~is`s(URq{Oz?X(kNRHaH)b=r;}CM8KNyslEPCBFT`7(@_UieX2bI$kgG{FneV* zsAEN$o#a-yp(+vOGDD}>%KH@{F)P=w9L+++@Wkdr@z#;tT6xV?S(FOCrf z?Ds0243T@JpllI#;!$Uu`B{%LOtT@t(>^`vU66Sy%JdNxd)k87(+S5cD^`z_1LI+2 zwFM=iLLwKE(D74|kkH4fA3Nd&2T>#=w(ciYm{#4@(rGQ@5x`;%R@9-4Q?+IpAxs-y zZ4|)3LnH@JfZ~=TWPr4S%kqpSxx~O$p>$>k!(cu(CZ-+eEIl-u!;CU5uf)d)F5V{- znYR>k;Jcf6y7KzT^J&my{vj8$j^ka)i><9Ks1@(?<*wkBoeYp_dN45U{lRouG9vw! z3BTBU3M*h`=>F%0Af?jpVG>ZW4GDF`Qse1Q+?RiKl(t)h)G}K?YCU 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 literal 0 HcmV?d00001 diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/unomode3.png b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/unomode3.png new file mode 100644 index 0000000000000000000000000000000000000000..1538b8538750313be7be1f1a7493797ebae924e9 GIT binary patch literal 51210 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πD!?%Vg$fcWu`WEZ7N0PS=9Wnz9Fu1E;Zt;_^}i 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 Date: Fri, 10 Jul 2020 00:37:51 +0400 Subject: [PATCH 115/323] Add bluepill timings.h for modes 1,2,3-4 and fixed arduino uno mode 3 to be more in line with spec and some sigrock dumps to justify numbers. --- src/strategies/SoftwareBitBang/Timing.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index cab6bde2d0..32bb1f3e23 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -218,7 +218,6 @@ #if defined(__STM32F1__) #if SWBB_MODE == 1 #if F_CPU == 72000000L - #define SWBB_BIT_WIDTH 43 #define SWBB_BIT_SPACER 115 #define SWBB_ACCEPTANCE 60 @@ -227,7 +226,6 @@ #endif #if SWBB_MODE == 2 #if F_CPU == 72000000L - /* Added by github user osman-aktepe - 22/06/2018 */ #define SWBB_BIT_WIDTH 39 #define SWBB_BIT_SPACER 91 #define SWBB_ACCEPTANCE 47 @@ -236,7 +234,6 @@ #endif #if SWBB_MODE == 3 #if F_CPU == 72000000L - /* Added by github user osman-aktepe - 22/06/2018 */ #define SWBB_BIT_WIDTH 27 #define SWBB_BIT_SPACER 87 #define SWBB_ACCEPTANCE 45 @@ -245,7 +242,6 @@ #endif #if SWBB_MODE == 4 #if F_CPU == 72000000L - /* Added by github user osman-aktepe - 22/06/2018 */ #define SWBB_BIT_WIDTH 25 #define SWBB_BIT_SPACER 59 #define SWBB_ACCEPTANCE 30 // From 1afca01cdaa72eda90f12bd16923dcc47c289f4e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Jul 2020 15:08:47 +0200 Subject: [PATCH 116/323] DualUDP README minor fix (https://github.com/gioblu/PJON/issues/319) --- src/strategies/DualUDP/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/DualUDP/README.md b/src/strategies/DualUDP/README.md index 19578860b6..d3cb2d1987 100644 --- a/src/strategies/DualUDP/README.md +++ b/src/strategies/DualUDP/README.md @@ -5,7 +5,7 @@ | Ethernet port, wired or WiFi | NA |`#include `| With the `DualUDP` PJON strategy, multiple devices with Ethernet ports can use PJON to communicate with each other over an Ethernet network, wired or over WiFi or both. Like the `GlobalUDP` strategy, this strategy is not limited to the local network -and can therefore reach devices farther away, to another LAN connected through VPN, or potentially across the Internet (beware of security issues). Like the `DualUDP` strategy it will reach devices on the LAN without configuration. +and can therefore reach devices farther away, to another LAN connected through VPN, or potentially across the Internet (beware of security issues). Like the `LocalUDP` strategy it will reach devices on the LAN without configuration. Feature summary: * Will autodiscover devices on the LAN. These can use DHCP assigned IP addresses. From b032c36e1b288eaafa904acef9bb952d16a898cb Mon Sep 17 00:00:00 2001 From: Julio Aguirre Date: Fri, 10 Jul 2020 21:11:57 +0400 Subject: [PATCH 117/323] Update Timing.h Fixed arduino uno mode 3 timing. Added tested pins on bluepill PB15, PB14, PB13, PB12, PB11, PB10, PB9, PB8, PB7, PB6, PB4, PB3, PA15, PA10 all 5v Tolerant. --- src/strategies/SoftwareBitBang/Timing.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 32bb1f3e23..6ac9240573 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -47,9 +47,9 @@ #if F_CPU == 16000000L /* Working on pin: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, A0, A1 */ #define SWBB_BIT_WIDTH 24 - #define SWBB_BIT_SPACER 84 //changed to comm with bluepill - #define SWBB_ACCEPTANCE 30 //changed to comm with bluepill - #define SWBB_READ_DELAY 4 //changed to comm with bluepill + #define SWBB_BIT_SPACER 84 + #define SWBB_ACCEPTANCE 30 + #define SWBB_READ_DELAY 8 #endif #endif #if SWBB_MODE == 4 @@ -214,7 +214,7 @@ /* STM32F1 ---------------------------------------------------------------- */ /* Mod by @jcallano on 09-jul-2020 see dumps and pics folder for info*/ -//only tested on PB9 pin. +// tested on PB15, PB14, PB13, PB12, PB11, PB10, PB9, PB8, PB7, PB6, PB4, PB3, PA15, PA10. 5v tolerant pins on bluepill. #if defined(__STM32F1__) #if SWBB_MODE == 1 #if F_CPU == 72000000L From 0cb115e8227c187ca0d82c6de07896d9dc6d5f6c Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 Jul 2020 17:59:30 +0200 Subject: [PATCH 118/323] removed Dumps and pics --- .../Dumps and pic stm32f103/.DS_Store | Bin 6148 -> 0 bytes .../ArduinoMasterBluePillSlaveSpeedMode2.sr | Bin 2728 -> 0 bytes .../ArduinoMasterBluePillSlaveSpeedMode3.sr | Bin 2286 -> 0 bytes .../ArduinoMasterBluePillSlaveSpeedMode4.sr | Bin 2157 -> 0 bytes .../ArduinoMasterBluepillSlaveMode1.sr | Bin 2913 -> 0 bytes .../BluePillMasterArduinoSlaveSpeedMode1.sr | Bin 1038 -> 0 bytes ...BluePillMasterArduinoSlaveSpeedMode2full.sr | Bin 40044 -> 0 bytes ...BluePillMasterArduinoSlaveSpeedMode3full.sr | Bin 10729 -> 0 bytes ...BluePillMasterArduinoSlaveSpeedMode4full.sr | Bin 11489 -> 0 bytes .../swbb_acceptance.png | Bin 148874 -> 0 bytes .../Dumps and pic stm32f103/unomode3.png | Bin 51210 -> 0 bytes 11 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/.DS_Store delete mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluePillSlaveSpeedMode2.sr delete mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluePillSlaveSpeedMode3.sr delete mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluePillSlaveSpeedMode4.sr delete mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluepillSlaveMode1.sr delete mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode1.sr delete mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode2full.sr delete mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode3full.sr delete mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode4full.sr delete mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/swbb_acceptance.png delete mode 100644 src/strategies/SoftwareBitBang/Dumps and pic stm32f103/unomode3.png diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/.DS_Store b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 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 G4e%e_e&~My diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluePillSlaveSpeedMode3.sr b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluePillSlaveSpeedMode3.sr deleted file mode 100644 index c519e3601ddce2a5023e63dfdb2749ffada525bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2286 zcmZ`*cQhMnAC4U{8bk?7MTA|C=m|G6exp1Au={{n*o+jiPj)PynRB&m+*q-6haP^1cjfv@|myqzNVf z5U$LXn&z(CqHdq1RV>fMi!w4dG}=tAzo^d&k56xlJz@i|OMFLkozS2-kHI(GTv6?&f%h;=vdb_*{gte`nVjAUbau(Rp?yg!ns(IxKr zPa<6>>%OVaqf}xu@Bgnk+TYBjP5H&_0sz2BS<}}a?d>KhBPp})xawLd#yo68IKYzL zB#zcQ;0^B$=0vRjEE8gEhqC9s+Alo~-$Sm1k#8NNXEb`Q30Kl&ul1{ieO^2mIrGZw zx52t<$gaq=t!2#YTwuL_1<7>hn*6?6Xm2y-$$B2Anfh_ZLLMn4do481d^#uv5}Ea7 zPlqqI#rCYj-M@dXQ{+psAv3oD5zMH(o{gHD;)^y3O%CE9*CXyEwdIjhh}u2FzKk_^-i_^eh7hE69uOxMB-wJ8>1Im`q} z9(1I}-x7I!gH?Lz2UJPD?9uarZ4VDQv^WEXC(hM0OUX5f|=LZ6(GnVSWb1qI`6jFdqh8BDP=X>YOnUTci zWoj0^ctHz*>r;hj6@+befRaXdLUdQdv)#EWHHW^V2dUgN+Y$4TIH3LR2f-Ey#JcTO zHHa^FCVue2K-vDhW=uk0ih_96M2sT3d|nA_-mPZ zR0LxZ&g}KL6zo@)LZ6{lmD)vCGSlLcy0A@z7i_%cFFzSEzSzQXBD`^x93lkgvxxm( zT!0eiQ~SyMilxv1I6XeZV=KX;&$QuY-%Gnzs519Pwcl|3GlY%A1jIiGml6g^V~z>j z6Y$*cWXy12Jwx=Rp1vJK zLJnA2X6@5|-`&%=ImPgfsH^sJ-Ls1rMGkoKmz;dlo|~>r8%sLzsutwRr_lV?x$Vg- zn6BMvE3;79x_Q>t&>BtuuA)P~{nO*L%kwPz_qS2)-WKewB5LLQB{5mkrYD}*G*YA- zOq+IJc5k>!LubYmOC@U_Yo5doh9&6p$iZ`rJ}b$TO7Qz%bgHHvaQrqM65p8G?Qi8O*%sjOB zdLr~p`qSePC9g$xlOHtRQ*^f4sYq$>^l+^-#B%p!12$e4zGWZio!ZSV*6=V&;Lu^e zTdA(S>&-W9RIew1^C=){P&ERx7R*)>1qKC7g35pdoyHo=$I9 zb<6qY3pNGu0)qsl%F!%Ri3vO{bvIdxb2jF>?5Fo(dJLBW$8# zo^#WjD0w4S_3gmd+wk%}+E?3P5#ZL6vIrxdY%g|1H`wq1w~c?v&BrK+H!)o`Ix99? z-ljVL&~s7Ct|p=*@kmmcMOEF%8DT)pprIi(9rZp!2zI_GY30c_l~e5%Nw9%V(KpV6 z=UdQ>V$q`ABy?}C!kj?1Wmv_fXI`VmgoVh_qZ^2wB`=OJMrbq>-z{hX>UfX2?WshJ z%0{r0ek+F^<>lH9$#>vV+kjkLeu0VBy^}d@$Cxoo;oJ#zHu>AG+=8K;V3|uV(hBP! z@a_PH(v!x-31{sf)lgZeP5KB4RxwG2hB6o)erv)#?qd;P9^k3R%y#{;T>EvZ>8nP+ zZzsK-o~Q}N6IvjnCudZah6s}icC77GUBc7VV27l1fZ-P!LxclJH%e1jtk2!d0u|@M zF-_g5plavN7X*RClJq#IWc`vKa|C4=Eoh8Cy~04vKzYYuCA`8GZrUinndgf0p)Wk- zinvkybK$3Nz}fThg&{QkJtMFH+cUzNxL6J<(o(Rj{#{{KuOa zO{JpHr%p6x90)gaMcD5`wC}_0T?2R+LRfebMAJ0y>bbuA2#wfY%qbcKXxQf4b#kM~ z<81FIkT0;aLFjA!S}o*L0Lqw(8cFl-xq;%ge^&LcnDBRs_)GNfG2$-?08kx;pwPcV i#XnX5boKwK`Y80j9*;7nqyN>Sp`3imt?(P6q6Ks~%*3kCoJz<+LiSvmT9tYCUuAh1AW?+_x17(&!e)P-I{ zi2=f%swe}Hb$L1ydz%-5oxckk{g%blgor(Eb?5MlTC$^VWOM*+X$z#{Iq-O=K?JFPA+_!hpr zBHv207P(RK+t*LbK1Jvy8K^andJyE z*uchi46Sm+L#a!WiJW4Gnk@TFgdlf}I{`zuEpZvh*b?NJJ&-lw3 z<}*X6V~Xj47$vipo#s0In%VKA5>0$(IL;~TR_-q|`&QA3=k=S-w)J{t!!tAyrh^vQJ5t>Y99M0i3;ki6bkeL> z$)yf#97!OxjvwmG+zc3l$l12Lu}?U}&)$53$x!gx?SCd@1RdkHR(@a#&#^|pQn(wU z9vta?#2g)eU##gv>oN!KDsj&09zJ{sDAC$3atEHgmN zvT%?#WoX4Zp&*N4u0d(DEd6{i7GpJ`-j6j+qiEXT_9)xbpwXEZ)z*u*MPcq!0O{Qb z40EV)IYMUS0my;ZrN=04tDz^yd-8%mHpZzW+uheXAK2LxHJE%g{P76uov~%Y10{08 z;;Hswd%9{uVlY`MwA$9!;?6EuPx-e-yjL%`!QMb2x75#6+INTQNJgh_DdQ6C2Wlgjk!E9UAt*Nma3X^(rS;~K;`8}03~M6^jatz0V7QxwjBcXZ{p@K+7VgErr?7c`iSlL1uO zcwUDgM`pV4hK|t~t48BSqftX9NPlRuF);xD*-NPawg)oRCFU3A4C)WcS2$XqC7!~q zm@0%iNy5O}cKNJoN7>W+gK+xBpWD%i$HK?P83?w$Nmh+U$fA*kBi^d>EM4B_0�U zm-fNsO>8%EnWSyadunB$PK~ic1%ix=Q=~kJ;wNRd2a`F%{QkBM3I!MSTm48=%28B%(IsSi@203?c=@obaK_HPzz?c6 z^suHjJ>3dXExIJJYF)KdEy>=Eo4$$9ELO+$HFqqX8Vn8dL7$#+=UODGREvrLu64c| zJ^<4P;X4ZQb;$<)C)2umF3;wU-1&YW(K6+Yc(#g~^-e=^YjF4xtZDU;IrvxhZq&`s z&f}>z?7^mv4ytf``elPz={Jn94e4CX7B))mWR}df%6#sf|FC)sjIs~FuMY*O)U7UD z{BdC7)vUA1;Q~jufpf=?G))PvAuTsg6Wky5Y(cuoq=q!BQ-5ZaR$oDIdXjvlim4JdFl5`^=? ztuUkT$@slgB_-h~Oer$zCv}+?w>;BS(RhP$;QYRB8$I9&1 z(dKbnWVA!{96N#Cm+^r6dtT?^MNml9fQJFDF3-ubt=rcDH8MV@GCx{=-`8_KO)?^d zDzWqFJ!z+b*RvBe1lHPxhBu>(?gEE`*$GwH?XVT|%R69sc{_i1o+cm!x zHb*TFLMO!tL#$P-V&SfY*M=T??^FvZIhJ8a6W0>?#zoamucp=TR_;*Geu}rkn6|fQ z5>NTp&?B<%4K6Ee$RE$qImQ50n~6#k6PuPTl1oP$PjM%1Q}?ZnX~oWk;A(2Mbr7VY znX1QQMX*a}{k)m{jI?_^#9O&Gc$h0MP&w(DUg_MD=ya=P+0|N=J0kH&d`yxufvmqv zWxt7LxeUh7{1EXQgNleU-D#KW~o8nm}SMT99DQ8+(V0(j9Q{62M zwscop2Y=~nVLYf+RrgDPA3N(pvrKN>wT-fKWah@4b|KhHw4_o3-`>6X1JB{7_RfA# z#41DuF(8UFmko%*r@nK;7m5R>~I^M%W2=SkB=o=tqI{Bb^tL# z|Bh_|?Eb8VpOpR^;(vwyo#KB*0Dy*Ab%Fhx>Hkdq6RQ79^$F~M5sP=&DIhNZASCDl L!CU|HHv#wq%l*Ub diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluepillSlaveMode1.sr b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/ArduinoMasterBluepillSlaveMode1.sr deleted file mode 100644 index d0c78551bd6bed6b573104e629786357ee0db660..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2913 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 b|Cf4uX#b0qHWqB`zgH}WU3fUl|9tj8tGg?( diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode1.sr b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode1.sr deleted file mode 100644 index b6aecc152c48618b71809fdf1cdc0580bc3a860f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1038 zcmWIWW@h1H0D-QJF9Ue@U6o=4vO$;~h|5xoiZk=`i~@kFL>QPDIKZkteRX@#2$Y=x z#2i4Jn_7~Xl30?c+il3#Y{0`%zF$e6L3PUly?YY7J}@15z+%2>)+7y1o;~|QZ@*o# zdvCeeutWtjGDj`DRU=eDQ!Zsx#I6Y6Fs( z7#Lp1GBR)iotcxLo|&v`sB8H4Ze-qJ10Gfffwqai@9%gKFC@~c8!2sC+_*%`b?+rF zsgKWo#G5>HW#6~r>eofC`oDgan0;I{J=t_>>T~mTOxl0STuPTSEPv6|FMl}8k$2kn zqkVzp{M%Yyn8jVc}Cs-MZ94q`31Uy(6lp1F< ze>xCx-~QmAc%LN`88nL`EUpjy2EJBP89uExHI!v&X zxbc-iJbK;h=uZuSj14XioVGhWc*1@oTP&ci`GBD|$RRt08xtFB6vP=$us&35bWjjv z@L*ZTdxAN$xiOc&VDHmiei{N2qCi2r1O)-G59X}3nDvyglObW|wAW9>Ip+Lfs6NXy z@25GNP@@e{yNVCX!zbdLPnZ}E9$3rRsF1F*;XY&D))@8u4hbO)2R_zKlMp?@EW~(V z-ee}A7|=ZvI1cGJ$W7p2*fxvxO6`#Yf!aWex;N=wxS6wC`;OFx>`$&tk`4_U-|HBf zN3WY4FE?YQ;m=<=u8Id%a5}Hknaren!|eM9h8xxbIk$`6?-12Zt4)5`8)?9uc2H*q z>*fU8d)GbXHp=Wb{@Q+bQ3Yc|TpdGzHzSihGwyr^OpRc$4U~;wxeTHScQ%7)VPM$S ls0L)hG99`u^i+?~br#5k=YarkRyL3nGY~EU(qYUX9srCcf{6eC diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode2full.sr b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode2full.sr deleted file mode 100644 index 62004d9207007b0391b8b4bf6ff905869b429aa9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40044 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 diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode3full.sr b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode3full.sr deleted file mode 100644 index dd54daa1b37a6504a31d077e74d25e093c62e60d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10729 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 Us1_dn^(9>3l>@ws@?HP-AK^Fv`Tzg` diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode4full.sr b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/BluePillMasterArduinoSlaveSpeedMode4full.sr deleted file mode 100644 index fe6048ad9dbd1497d65d08c8da6e5918725d9288..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11489 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 h-oJtR~GOc%yIME{{yL7CtUyl diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/swbb_acceptance.png b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/swbb_acceptance.png deleted file mode 100644 index 57d98d2d9a84a74bee9927e6737508e56e44f658..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 148874 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%0Af?jpVG>ZW4GDF`Qse1Q+?RiKl(t)h)G}K?YCU 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 diff --git a/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/unomode3.png b/src/strategies/SoftwareBitBang/Dumps and pic stm32f103/unomode3.png deleted file mode 100644 index 1538b8538750313be7be1f1a7493797ebae924e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51210 zcmeEug;!MH_x3Oh9nwe-EiEk|A>AUBD z5Qtd8TtY%cPC^2zVsC3|Ze;=jz4YBqaZ-zWR?|6vIhzLNzVGOAGB^wTu*ud`R%Yh= zyg|joqhVsog7QI!QAKePma$JSicgw$Jd9^=<~%q&#@-#I37e%mq`Re89h+@?QiA*| zx2`T5GTT6|7Z9Yo`OIJXdf67VGC+_8u)P@M)fNTf6~WkDy@{`#6R>Vr)3MlLJ+o zwrrjy6ke8%VVu&)vT@E}5ZU~9@ul-L%W(`PQl}CLa{VWr@0A`!te)7}pFCQ32IZSj z%x*nt#(yY&R@d0*`9vp}BzMxg^x(_Om?ncJgja0u@yN}0mVe?rr~0u)_mu<6zAO6h z?54k=@y$*0!6j9P%P}XP453$IZrhJ=ULh;z z4_%6Zf^$ew?XfWgMeh!eb3AOB9c4o;@qrojzjC6IF|av3BLThgy7GSPCg#S;;=g}3 z|N7b!B>O%qwZ!{ik`}afiV2$hKL0w{^P9Z`Xf53t6C3qxTSC;^FI!O2CjwT#`^1G9 z4T?zMgFfiP;zQX2q7?%XwIDwL@h?af>*AmyKKV99@5>X7v@eF64^qm+2=@{Agb>++ z<(kvagW2X|3B~&1Bd&sM(V{;Hq4cA?kIK+O?uwZ3nc)G55yuf##2@?xWEimfhz=Tx zqZG{9Mzn~G<|8Q)OI;VuB}?&x`aKyJ_+3Clkd+vAmdZWqIHGQ3!Z+O#RarzTnlEv9 zD3h_+g2p6-GFt}|2MN~@NC_e!Sdkq;3_*E*rhY4aM1Bbo8X;r;V?oE@ZTu;!wYzI- zYvgOHYg230Yu9VzgJFX^SuQz`b4oM4J6l?P3{eg9jkF9;jp>YLT3&v++ottpqP4B< zeJeqmT4!ZD=I7qFqV}yXsqHguZ;XbF&L7V1D14h{rwyex(sRei;$-{x@Ln44+gn|CTstYGzz!&;lYgDK$%$U>30o$_z>F`NsOI`f~Y{2iixXzm*T~ zPWu>V@n$1jCweLb7VI8(9v2wZ;hX1U>c8TjkT{mkm*Jdre2P9mSkL078CY_exs+Xz z)sy8ReG-u#F_$V5(G=#D;+y^`h&u4QNUP9YYDMG~w0Z=xKuVI&3Z^}%KB zW%;G=rPHM?L>8h3p+QQ9Xdsy*9YOGsgpf}BwftEF>;nS*l>?9hX8l?GS0!Ib5lD(l zkxFSunoAu?y_NEiY!0yt69|qERthr?=?M)A<_|5E9hAE(|6cA;fm{Jy7N($~z%Gxg zP$1VXSEb+?zY<-Y$R3j(^Ev)WTu7XG%w()dOjQC~Tv}{v!qe!mXv>)CShJX#7>-!) zET6*6_c+D7THgz4K4iZ&3Rnck5)?!zN{dLPGlwvrv5c~KYM823tFo)6KcQB6^0Y2* zxX`|c`6FrOR6eYvBipo8qog`tIjf{JJ@;AImm|$JyBNk!8y1{TTX2`V_O6vz)@@!n}PpZcr_!miOoU#GshQt zRmSdjeCpgyj465&{-kv1U0JGKs$B+Jo8%DP=NBymt!nK&laAjo#}#{6N36P2+hztE zS}x;}A_8)y0@_g&{By&W^?Q_9L<&KL8ill$=9^lZW_((F$$XQ171e6h3DxS=EY9T4 zBF=ZVo2C_}JE!jmEePFxKp@oMB>4a)B=YK^W2|$i3#k)>GoMq*D+8zR&S;M7_5m=9 zS_2o)?T#NS-^Ui67fXJme;3*LyzqTvXv=P^;K#f5v+l5=o{_>nGFMA?Vps3o@B3(b z>nHTPyeGv+vj=aF74}k2%nncXcFS;yJ2EMBmAWh(ajLaVPJ(5t-mPv25Ja;f8UYL#65S zcue_;NOZ~TDL&lQB&hKubgMeuP;O9tZGJfpsq*jkZ?&8nwqO&k&uEek`Cb(#UglUqUp88eeFHvx0w9UgPDM6`!}W^s#%S zys{Ge*Q)+)n6iWLk8{0r6$6_&nv(E?O{a-4-9MK$Q*SFWUQ??t^>(P_Y zPxCw4^2Eo+At&@FhQ!CmrNvFhov1^ZW0}WTs+dzge*Gw3XrS4nF+S4<&4nyGFS*6LJG)OB&}TGw9nZ!#Vn`@Y_n@{JE{K9SG;D|GMZ0;IOv zug4clcQ`mXW?dyN8P@v-YJ6?^=O&wVT}w~APW@(rs-qgHY`u+6)hZP$Q_I2HAzA`j zM>L=<$JO&#l8b?ZT zpG6(}o!r3&V;^7do*7@HjMwx@M72ij{G1<;nu!|ocD@?MEA0z=CsBjRpW{&Fgaj(xEi9BQlPBNz&D z^r5^D>1e^!0$V;0TBKN2AUaJn^4)BsXrq$-BzG#;E4L`OA-5ujz{FU38nD0W#H_9j@W~G$f5A zVRtjQZ0^T!cX8HnFLOF^7gNjP45JcDVrOHNbu0F=c5U^hw$5}lbc=`6fQb{x6W9|5 zis*`li)@PAiiC?ctq834t#h zbBnKtafrcqs}S9jz~Wb!W*MInryDsPR`2f-eBp!ApVNo`*&)a*oj4*fV?2=Gug1?M zBI?bZuGIm}F8(f;?tw1b{*2!Fj%H>thRk~l94hqp>0dE?WqHY##B?h8N+DQTR^gs} z{-d>s`@WyTKivt%%aim8_6hcrP5Qw#+YX~E&{0eS`i$kt zy>%87<_Kovdo1@l@3}C0YvQWzJvCRGR55w#q*|=uSt|X(G)v<>U#T(x#_C88>opcu zgjxiylA@AHpJnnuL{&suKXE@K2^|T`R_4~n(yY=p(nr$u9d9~5cTjYQD*aF@c^969m$Z>W zl+?uM_f8;rmUEhqnClMrPPJHtO3l~uq>A@dl{G~bGu3$2p_Lmo9c5z`?B!l&trknx zBNhiE8k2k@$GH@KX@#?h^|T&H7d#gNDDEi4KmckiL*L2TiNxstw&rO)cXCCfL&!lW zMux)so=+_A3L`8VH(mJO1NPT-Q9e;QLAZl=M>h(YfFj?G$i2iJ&8^)-$)mNwv%%vv z>gys;($~tKRj+$IYpz~gm0!+X99(o>3?Sb}@rQ&%hLPP-j*(-K1(1ZXJ20xzY_LD0 za^5k=4De6(pTiKw;6|?}b0)GO@ZtbVCQ0&0W=kc@@JSg;O-fct;Y$n2oV2NQoVHCZr(5Qm$K$w`=f4{f{|< zz__HingXtZ<$~s6t6}$%@9UZ)iQIAA8(el=!rY7%kn;VCCNo{rlNG3atOK9Jk-cu| zh(T0iQ}TzH@wmtDsM4DCGM^0U$?D(LJ*|`dkYAjX^`OA@LtEwh6Xc7C88XIP7bP=mOd;hFC{G{l8FHg^?gmTb@g>tr{kt6v+hDmDW)g~ugfG#b4uTqR%C}|vcN1iLzdsJ z&f?9wxaYgax;GsO9`zqH9rFqY2={rN7tYt;Y;zZzJw~oY=|Gzp># zZ;`f_&dTx4VHt?XxDyo;HB0t^Y#yAQ`M&tBfIMj#7P`q46OPmdV71B z2dW3``qca1_A~ZTH6MDN?ZxjE4k5h@SdmI-j~(|fU3x~v?#ABeZG33@qquiEXh&;4 zzKPK**$_p;Va(J9pnto-Kj*kfyDGp~=ATj%X3g)8A3tXCOYpf}mR z2faWNS@#tS2b7J${9xdY3V0(76Jb^=5)`?JNYvu>2u1uJU$kV*XA^^kXYY`%yD@fS zlVaOqXQutbEI%gImA44KioTHJ1oSE!~BS8i0MK?Wcc7dS`t~&T|USKvP{d-_p;rK zUH)*_@YwL5;qBqA;X#T;iXDm}icv`#I6qM7C2_KeI0wQ%vwqq7qSyBD%cWny+xA#` zzuXj)M8bZH7Was%h$9R#wiF^=OkMnGE+M3PQV+Td&*LcaALJj&amgddsRX(NMjy}$ zP`zSzcw%R6-)>*^%JX~P(%6#nkDov0zCYSc+Iz8oc<_34dBtggZ82@ZZ$ISVYmm7t*KPn`XI?P?qgi_*p%J;-=$9d&YW( zi^PLO5}*_Dj#MvZ^rK}&P$;?VLDtoH?$+ary=o!nsl^#*65OdH7lT^@TQLxk_ z)6~@$lJby6k&uyNeDvWNadu%Q*@x*uk37ag;+*lE6NP6QqSDPWH;KMQkBT0ZQr}m* z-(WFe>u>u0MchlC7va`LHmNobZNy(@o7vC47>gVJ)_WMZPNtSx!(Yg&%e{L4gvo)!(;Tei-k;3CZ8(4vH*?_^QIpIShak53+VUkdMi^$N^ zPD4_|TtnUOT;H|7@6bYM@Mu5ry zW3odS7V0p1ypiKN<63`O4Y`D%sC{FEt=Ja}#XKD1E)xymV}hFVyyFyj=*AGhO;2sY zr2c@H+lfs{q?m3SsxQ>Yju>nBZYWtUbv;HP327j-*FBysDJ{M+Jty^P+5z|Y!i9k6XTkB`dvCHX%OBd^jv*QdHv?0D6i*_GC$=ZZ9Xm41HzU5+-Jv&!zIsq5+| zN-&D~ohH6_yhpqhyk`7VB9(3rzI~Zio!H-u>B%Y3C>#68ms;&po!coNMK;Yey)-p0 zgee3QniO;pdJIdg&r6qmSg_5ofxTm}KD52QWwPG4F1+oqo#M%SacCfF;{E!jpS#Db z74ZwAIuO|6`dLayOFRxb3+$18CG$mELk3IcBI7``^e*k)F!JfU{8Uu$a8hc8|{o(qh6Oo-n(Il_CH~G6|+xX)jKAMCs9}<4TD=)9w z_ypV4UOi|@{-$$4e9RHQ8Mpb4Y>h023?+p!C8L_P+O(RtI%8XQyK>8ZXKu=Pg5_NP zlGlmKTGZlZw`J$~(wz^YbDrEcd>;7@56<=1J$7P#JlVYCONG_B)mg>3`?mb)#>krt zI?)QR@7MAo5~5+ELKpgBXBGVjXD)M(FyZ{AGMZ?fZzEh)O%{ zfZ8H)Jq>F1LYzeP;2!3-d39>`rJI|uQ}1`ywY_|Lrey3DSc#K?JyxyrCS>qO>!;pz z2MhMApO^dndeTr5h3>GsP+kTJ-2tIG;^JNQfld)X&&ku$CEJlfe_No)wCS7loSPxZLQf2U)UO%u)A8n0!D*C4_yU;kJcuRhEP{)D;ozvS7Dl8 zBLsoZ@UJ;&pudJVS_;!>DXBmuZ0${;yzD&e_i04Xp-|{U`xmBys*=+GnhyL;nC7LU z<10Z94i^^}b{B4TTYEDOP5}V{j{963TwH9x2sQ^d8%IM|HX8@pe}w#7j--i$vAy{# zM{`>nC|s_gk*$-XFbxfSq5u5+gVV&-{J$&NIQ&a3KtT@p6An)H`yBs~4NQFq|5i}N z+||TNOVZrh#Kr+wLxhuy^ZvtM6aIMg-zEQNs`h`U@^kY1@67*s@~@c>Ip7-nk4FE{ z_3K-JFA?;I9RJ~71bzCIYy@Bqa&yVYYQS$W+%|yafVK$e-ao(LpYL<42%67X1-x8p5Px zY#PGnst63|G0CBWsrTQlCmzl@_3L}=*futQ_}Euxw$qsIGSHvsGJMi>+UIR>b_W3r zLB)ZJ`GEfO!S_3OhY1$QxORH`2?F>rIFy~(_rGKRH3=#%HbjVmF?8KREvL!50-lN>egC@Hdpdo~k(3A^r&x7aUp=d>8A{|LF9O ztjslgls_TT03dNWN#Fc|Q*3A%`%j3H07x1m9>{;-{riJYb`Qm$5QA}49HrV`qW(cM zf>ff=|I+@C7#!-%wb0-poIkY+Wq0{QA+f*21C0MA{;$UayXWsw^Y^I1f&M+?|6Z=Z zJ^A-?{TtQ%4JV<0!$}~3{~O2uO`w3}?r#G1H*-Y=Lgc?Cga3QA8qP-xA4IR#M>xHA z{iqZllyKwyR!Q--1MggIc#B>b%@j~1wTSs6hfJN@7Ft3Hffn)q@snfYMPt{o=zi;P=E!Ea~4W zF8sJEjr0p5?|B6Ncrvb8+l`L^x{d}@Fu^xCy{-!U4 z6o?_Qf)k)Bfa26?YC-Mi!P*^P`~-+;AGxDZvJ|&wCQBh_9h_uru};% zG-ERw=ccn%#EWz(N0W*^+!z@Qv0?snu#*vWnlR7f+({$0fDE3SC-YxGg`hqRZ%LWc zlNw*K+@0~h=law&C29^f>p-EyFIt(Dy@}IcjrK69rN7zs;iB&K^YN})V2VV`#RVp- zcO2j~JNI_;_+4~|j!tfNmp*V_?{j#acGz97XLtkM*5Zzmr7P;7(%3>l#lExY z{;RN?%fodJ?~})(r`1#!mOwSnHKt`X!~1&UXmh+&`SR)jcYdEZ;71}VPB7u=KGt=j z_f^e@Gw17ruoM1cd6ICDZw;zilN+JF?W3)0yCYlq_+8jQwL{~_)_(5dIfbDror!Y@ zpx@sp5j1vAAsXaB!{ZbMAR_S<$r0aKbqw<(i+AD!$x`T0nP$w zAABAm<?a<`9-V*ho4>awJh=KBa{LXT z{zjeumtyE0&&!QbVj;8Zes9nHj%}|qMyjU0RVL9NyXvvF4zgVrJpx{5^BKYs2Wg^S zqUNj>IM7#!zT>6On$O#*JYQ|mMI9zkNmO$pfNKaJoDFcy%}*O(pwNmvj}cq$n>BFs zJn6Sgp{yfyz6o&e9wEulc%ffTec zU4!=b{8$r6kks357(U604OO9zmH+-$#=;FSsRZn+1PDm;9SOReXT3cn@tOOUyXBeM)o&Y$0~6`yCeG<)xN zjTGEmw%$QWpNqMb)L#JzPX@lCNdUD4>PMu0zrnWwiYPE^9_$1L0I9;ahrhvp#Seg( z#j{J-0+3o&BL5CQ1xSEx@cfN`07Zv=Za(VY93>SnM%q!$1tL(WpuA_5^Sg4mfLvVX z6p?JenQ))-bN@DV3#goIf2$ss0OV2%dbR#m<7hz!rXs)4#W__4nhcb`84BcE1sI{K zNrQ2>3J`3Ge)GGjP+0*pvl&+1^R-342Wv84EWI^d8Bp^>UKMJ?BOuF1CKsjoUnfBT z!|OuGk_tHafa1*Z*OdfQR~5IwNCA9TwO6@VQE7!EKX1_0OY?^5P( ziB|_!SMScC-G#f73*>O~H(Q7;umNA!fX?;~ki2%@o@Cr8+}S0gYCb-@0L`}i{ohyIrx+`EjsXR8^_?pNnWh2EE4kJJ0FYedh7 zYDs>2J-7Wii*GLizJN5;Sr#|ezzb>5V|`AJ4b1iD&7{T~_d_1^9mPsvj^6jrE<_l@ zTY|iX6h-x>)Xz;|L-J5v9mW}!8}&CWoxpD)4K*k7o97}du%Gdd+ssQ6S&i}osehHv z?lLaWKKFbvH*?hC481Sal2Xsdw6m@AtPnp5P^D2*XZ%Ea$f@)-jj}`I3tS0a%&avF zvC6gw2vi80vrS?SZawL$?ug|ql}f3D=HO3+shJU8u;>*Se1sDIMUxX1&TmQ$@2=a2559lSH%7r=Jpc;#^!hil&ISJ2%Ht40i~arU>qbI)n1yEYd&~M_#Co zQL0ar&ryt0v{boDRrp?#IFiBT$TmA6h+RK)&zM{e*om=4Dm6>VvWF?h%Dm@*l zzwAOPODRt-Mcsf1bwcuGc85~Z^YFEa68-&%&tOyt-7e6;lHVLFUcL#$@WkC zJ!2$okHdOHH39f7Y9G z(h~@YT<^&|?U%Qn@>it{5Q8#7bZTtamZqu{i>C3cJ<1ix_+2lX)#Gsu! zH!@^|aLE8CkZ9ucY4{+a==}RUX$nR~*$6hnyI+D!?%z|DRz-t4O6>?3*&K$~fg!PC z&ka^P16I$Tu&HX|+S0Zwe8-U`Ksc}6vrmi|P}C1ke3q{iiuUkk0JTO*^OvKqw1eQlNITP6%)&w9njPekb^m$vuTg_PfDy^$0>r({2>vBS?v(Y^ zw`CNdLLGSt%}d_8fl>9}*@8j;mj3UBe1qZ0F_RXlp93GX@fyVc{p3GrvZ;Lr39&Tg z1H^EFWoYQOZp%PG^_K@_v8bgIAo~sjkmM`AqyC`|6ca#TsPY~Ycm&7;;c4Gi7zB30 z5nKC+NcllLlN1;{I!MFuhnP%v_!I6WOw@0ZpsYd$t5nE;fc{$`sv>~qJ~NkirU)?j zXm82tH)7!miqQj4;!*9$!PK~7Yv^cn?f*;tKNQFVXqXWKXK_$d00T@>r&FasEY8 z^kZP943r%x4hcZb*Fn|$e*kX5dC6zj-KPBsU@e>R{?A;y6&ecujk{OvwctMnL;V2y zxYisMZ7>0O9j{hD-nMx(1ps_|6s(XxEo=FlTRhU$(HW;g~Qqt^9}`)$?4 zbO2N5j#f+%3IW2(9MA~g{LAP5ZF}E1fED?75}b@pfUw0)G7IF}EUyDrjK>x=k^%!R zM&BZ*hI^YGJSBjfp`SVXax}nDI@>3jx6L3+10bYxj}T;x1(czgmCpS`nMc6-ct2P_ zCR+heyN;=+9exJp?iT&onBGL+j;7o`EH zHk4T+1;EgFopGbPw@uUL4 zzM*>(hp88URqUU9`hyOfU^ossEhYkRJ0K(U-KRhJfZ{L!%iK3tC4zLrcL8FM#Geb{ z0DK34VrZZ^aCtcLKYVYQ1_AY(GO$OTom0_#KLUf*1HyX$6!Q_ls~!=K4^<%p)|{%f zBf71#81x?S0yom**VxGI|L_IeWQQ8()L$~pO2_QnD_kRhtlEgduN zOT|XiD@6R*WDX%U?N$?rzD2m7_B6J!X;(}mp5<&ytyxr}aJgTx&N)&$npBpVwOCE# z=6}F{Zd*%0EUxL5^S$HO;TY`%Htf(_w6?SS$iHG*7Nx5gBa9=9;(LG5T2Pj50Nuaj z#~JG$Z#4yomrfxE1K9BMj+~hgglV+F)~Zl_jkU$R!n@^->%+8F;as0M`4#r6lW07k z(Uf4ml`&G=cnD{WqsJ%CL|5HpT!14&FyGwA#-p~GqTSH9X{h>k`_j@Iv7;&M{w3i& zyWz>^Lf|S#@D^5Lw#3@Lt=Np~nS&t*q+A{vo}|#gHtTK?QK!AVl)%u1i%ORvCcMXY zHpVy(20)&($MDurfQny_NfQHSUU`@5x(~#PQLI9f#aTNmETv@l)3#FLO1^2FFCZeU zCRffL0$ztcH@2zT(Szr(nVzFa)A%}N&N$-?;zE2R5}&xKup&-5oYzxa%( z`5Y3952y-&&UG!+z;h@(sfws;o8FkTLxv0k4y#+mBHOE!awS)RlEq?9sqoUXZXGWq zWf1s3jZV4|jUTg3X6w}GND@7J?^pE6%51&zoN~BG`yke>5v8QwnDNYH7*b)mTH=@6 z8anN9huHd=uo2n2!%lvw3#ZQ42dwO2Y{LdqtTP4)`q^)bYG+oO&L&7Wz}2)WCBN*n z@+hDrgW-l%7i(TFZy?zq{BcYrj%6ZmBx-flkQuJ z)sDh0l^}O&c(BRTE0LKDx53n6NIgxw5xb|}w9evzd_zPO$FRm*=pLUnALA&cf604y z_D4s+ZYj1;kRfhUT615C?^)g>9=P)@HbK|kbG>m^y}aeMLSo;|(Ve9qQ!y0*#p((3 zI_EA_I>)KpH`5xXy{Q^}QNp!Tp+aAkb<-IS`bRo`F7gJ#$uHE9-zpc^F{&n}L{dE{|{SJ$DYGs$5{i(Yjvx#N-65voAYy927slnPg z&EOzSNKCV$fe==tj{AwTMy+A=i$zGCJEdJs!=O~ds0LoMWJ5&8<6%`=GTYH~drp3~ zV}?m=AQtf8pmzFzAMK!)8c^bQC&TqeSNx#a&|U8@M5DaU-!8<3c{xnAWd=pXt#g~j@m@yk%*Ba*xLRHzDeJ*m zFQ3_}UM7Skq`IJK+hq~XGQ>gBG>85^-@F7i?O12{XAa>`i$yrJ@0o5SFee)bY)#- zL=*Mt!Y(F)iQz}A4k7%A{kWW07#r{YbZomi?Z@W4!-yeDQC(1K^RoB8@&UTOyW#;I z+hhuRagF8{a7%3N@kL%A&bi_`EUjg|81L$s`2y@nDH4aOOV&1h_;sYX+y0ib+ApPKvR^KF(8N+?rNFz3#r6)j?YNGK=6cn3{ISa1 z=ILX~1l&8AJQoQDudUC{FZlb8W39)c{Vs%)6UQ&|QU{m&PWoj|y7cc*F>{+OOCMN` zoT;rh{G^^^wdxG_*+z90LO2doC?pLSbQ+Wh>Pd>C1OI*C3`bNiZ~Gq~yer_&J93NKsJOB4aeD8^pr@6EV(wiuU0 zyU;K_j%%gTUz>k=ebB1QFl~61;Ybw!tZJ9wKqP-K_uY>72Hn~GbRBQ=O0t82zbd_xlO>(kEHKaF&|q(jUx2}{_2p7EsIJq26p)i8r&fv+I2^?)lj zrpLIp;5sz76c>=W^@SkYr{4S~6aouw+AlsYd-j-^ zJwyd|oiqIQ9b>i1+I(uJRA()H7~Pz=Jm$!v=QF23%O;*U)fSOBUa>ca?Y<<{8&N~G zWFXX>MCRO3g;{>r#k$v1-(G=nu(PU|+Mu*;+VzaKxN5Isx^gOsr@rVq^GJG4KKTSs z^_eYg4sep_s0NgrhQC+FWv!yE$-q-05P! z*SGo3sag#x36+7Bg^b;Xzan-Jr#(iAA&*!@pg(MOzWcJ4j%%phB@$~bt@ zQLSM8vV7*@$C}s2qX(uQE&VlJ^42x?9#(zC)psvH>581Tb`G>E@As85DW^4nRMI|| zVlUR7;MX@3_0G~ensVw`3(#ewdwlGzLgYYcqr&VKz}`3VMaHLUwc17?szEg0l^{o$ zGDy>=VR0d#+X>YkFj;YL40$}7tFg_*-k5=Kk6q18k0u%Bp`Ep5@I1>NpO=W7Wkk`0 z(_qNvhtamS36mp~;``#7Ml%UTp+tP;FGfXRQytoCQ$~I{CK2%-wH-Hm<5Bywk9Pzg z>o-Vy-5hvSct;XBbWwXeWH@h=umyazv;SL1UtbB*imrU*oL4fNtXpN-tJt6Gd>$Z{(K5*fq2`cI&*o2n%`~3~)ubHG~WID`P#l!gzF!UcO zPTEwAqzyeqAv94Rl51yFIwz3yB+XWOdy`H_JohOq?snor6jy9j^yvG;&{p@Rk6AYTt8uxWc2Kq6naJ<`nhJNn6 zs`hl7cCKT9(Y!cDbIs`7$hgsp7qw6ns3?t56*RgVN+=X(sozad%TgF0-)LG!D&Ih# zCeRkL98;`&@fDeC{lvDnEWx2NwjCqAH80h+NvF3p-N&X7_0E*8f$;7)qc zlI)=-NI%y34tCe_q&6M{eo#2Yls%zEub(w)R_qnV$wa{F6IF+(c`s}}83dO~|v@~Cu1bOtJdX?2{U z+ljQL9H+9MogenBzW6Had5L}Y)3WAJy5HzHXFpP%)=??#_=BF{3)(Y>{eir2+GF>; zm&_&x-y6&yAWS0+hE6!azSQoKo*%ywST7if@N}q7dP=$FQBzd?GDz$=Pi}1y?YXZW zWtid|8HbS#t6prkJP?St8y&XI&b+nJ4i~wmqWE=@2Es4WYN%s-YmSB=Q1S>8Rn^6? z1#A$bewWBBOCcjR|FJ?5UxfRXteeAS+DfGqvCfkfwldJE=6oadh}os}*iS)=3}Tb4 zvqT3D^@zcv)3DVrX9J#sQ|Io?JGoL}Gqg>!;K^V@AS&3Mb2LZV#H|-OJ)@nxKGrws zK4j_`z#Nn)(nI+cE|&u-#QqB%kD{YlJ4V%s=?rT0ldrF z=em*&&w!Zc__2<~YDA5B8PmG+MAN6K&)?eLdvJFgo$&DpY4UZ9Ml@KMK z6(7c#Kvs>I8DG)tm^Mq#k6t)NR$9QFCrG3DnB->UqGN?^%7&rUrK!skB#wh)jtc|s zpDCb}+jbDq_jD(Mn6swrTH(v6buW;pZR*+fj&cRp%Tx0wD*))_spmpm$!u@lXE_6@ z5Zhc*3i5QUjo&B~2NwIYD`|Y5j|YMlQ;DW87^@)TXs+YFSGAnkbSJ?o0+yFhQk*N- zexI=2>LZ<_(%A(+$wjxx{ui?GkP@^!^Ur4qF|ELb3TqK&Y64>KmT81f{Q5eZI&CE* z9qIJ^kz^L(2Jc6|>`UIDyePw?MN^0=kXbwT+@P{wzbT2X@p6@MFDb9sDm&jQsK2>b zQLo#c6$)Q-mi>SzMGPC~88NTXY;ccgI2m!}ZrtBJLY6x)?Nd0H2#7XV~{mb$W+@R0RDZpz{ZvF(VdvFdi&uaK2e5eQi& zMm9|Kx8zd>b1fa#N%fPf=Pwl}UAGZ?tLK|ZxIc6)kc}lY=PB|8o$PpKu-5!=H=Rb; zKR1my7VZ_fIysqd?l}={=4ig!E3SXc@A&y*)}`T*hE2W6oY!1in9nxoWpRUeVpENg zW);7|!0Wx#Ew3FB9e+8D{>DtJrkT8B>#lM39_IwF!V~8xkARZ+RHmB3D(z9>l^VO2 zsSEiJ^kaNMC7w$R0tb^0ea_r6!|q-!OT#vwtGRm4reD0&JbOKyxS};)t^Z>z&6a06 z>anXl@(lmQft^AW*?Zl3w%#(Gn@KWuVXCY`jZh^IgGPRXwwb&m&EXPLV;jQ;bs?Zo z;LdKR$@C*?rF$DUFH9GQ^ELfk#~>5a$5`MNkA2pw6jKnwE5(cIU(yES5Fo5EA{HMH z>M#fDF;p0i57j$%G%BITE!8x#X}FB3o`Qtb zjkf9b1l6X{K4AvR64nYKRG$yvOa&Io!z%# zFWcPNE3m3R{fOa4xa;IK;lLDYLpf{pE_3--Y+5SrGa=0?qPMnLTj8mI`>X|A`m@j4 zwwGAgGz2y~)RW)*U~+d?H$NG5@1fUCTTRb-O6A0?JotXqf+Shwd>Mb8-<|4gy)?tb zFL&(ivYfJ4H#~=a!8IR}z~E2L#)t&OwB*OG$QJBF^#H1w!yT zql!|ml1@X_oaKv|VgevL8&hZyhh70W>h$4L*}wpxvcCIt(b8N9!9rHU`zUlexTKAr z88et3euH(#h}?wLIo6ZMhdAjuMjmq21;dp#%Lv_g!Moxp-fuyO$wfR6en=Wpbo>&I}2(+xjCYT(fG@9L4prZL-?Z1dEDcm_ zO4QCS?bzPntJ(-d14>Cm1d?mRuQj$7I~2_09s?PmLp+)ObA>Wa{;<68i!?U6 zq|%j(+8NlY8vK?ym_T`RShm1a2?CVp9+yb34PX9)_mt72HCM(joc&YoL{dtXtL648 zfS3NC>Y*Es14|7$Jh6_~jzI*QGd^D`p3+w6RT9dmoeCNx)EszUYoOh@2SB&W>EJ0# z^U)Cm0W}#;8s{_qJRKXDm7I1&-I$jFb+k0tunou**At#t0^}x`b^~S3czBt!fbT;V zoZMZbFIJxba-9>TNdVgwWvR}#`~sUVwKjZEG|?WBIQ$h(?uiCBtR=w+C_^q5SEXs9 zzK;P?o2m|76Y*ZQSuU$z(%W!RUj+C7r=hJdP+V?Ue8DKLnc5JO1$(jAfsw@`f%VWh zZ%SEAm;wYuerq`O`(!G@{QA}JSv&MBg#c>FeD50r)YdwE`&EQioJ90}kB3S-$1r;Q zew-|eWt~#-<&`y1w#tZqf{dz2#UoUG_a?&n+C5d$x)-*!hx%+e7}reF zR=s`l4OPwu=)RTk($t)5pbTWS+KNK%AszHvHK8~@pQ%wz(3 zBD_c@B?t&XAaUZpe|Pu(+Ze%N1G*f)Ua`>w+H36SeE)8t{mlF{lbJ{7H-*7-B)|GpJ6+-+#MviGT`$cl+W9&Y&ucz+gcHd%-_iIGJ!X z=spiHeLul_SW>a}f9ib=Sn9Iw6EQdo=r5vEFd_Zf7~cmbFMnUaf@A|=2q|>s1OI4% z0gWs6DFjGzFu)zY?+Vv#t)sO8#@;yz2lB%;%VX$2x{UYG31t9bc8BOr zw~6)Tfj3Xz@|V$%0m6*7DVb6J>qq~*cEAL034M%wFaKUNP@wc0KP)=Y4yd`GlWMlx0`7RCLA8^Uh^1tSW-~vdoo#g2OrPN@A zIe(~)3`e>E`54Ux$eG;dAG>Wsu@Rh4G>HZgxcW-1sfA)8%j*-9HJ zwT4c`K`-8t0TNFXB|g3_3Ey!ghn^NHcY8e?41n&kSBUXn@c_%Px{>MLws2+vTK+_PFc3xbA8{!F zuq#SBU;WWg2Loc1K<^a9T7XV=Ii2fm^$}1dC46x8hhF8Xp%MVz$t?Z_`?e4tv3$S@ z#M|Wzaqa={BNXzGMc#HM5abK|jTB_5ZXe(gsy+fV2I)3CP!$wF6~P5NX2?h2br^Ll zw*5cN{}Jdfs|#}j0gw`~rp1?zKbQgewg6ASIW)A84fp{@CEEYznV|-}KcF6h(@Bj3 zr!QJe74y#n3<5mCdp?2X`w1{qfKuH4pH6lLthDd8iw%wes0qbnLz4L8;09hYVJ8Lu zJ)QpL5wUPjtZT|yK?7_Pe?RDn{%voPB?owKt78==6shmoTjyl(p`YcL82Lf!uvm;> z|Mm~JA(dMAR^~_MWL~2Cugl1N8}1rro$vnGG;9cMz*Q`*E-0?4_JXN~6`}O2(^lX` zVqZ#vAJuWHk)pY%#m~wle~Mc(Rb>_y6K!8vi*MOKp)*CyV&N>2*OV$Aj3`^FN;F{rY@* zzWI}#wP&rFHEZUYxz>gtuKLNP}ctz`5n`5k!7^i=GDWC&RXdG{})+-E^-DS@=Ktb;?7=7un8b? z2q5xDy2vemiX8g4$iKV*k+*NIRh0i0Spqgi`*8TT3{R52lJpK@x&`3EKt(jH{Kb&j zsBm#;x#`P`iTTYbSvu-pBY~pf548qAejcqov-2rVia?c+V1wK_A8*&ibNp{#^3e|H zxX|Tft(_t{1faI5H`pc0Rg4T(MLe$Zp>=y>#2A3*?mcDzAFRGMTb+_vpP3UqPjDFd zoOSY zq-CJqtkVVmC0JJ1xt`nxq`OlvbS-!)=5e2gmw%$9JKDKq{N4JbOE)xv-Bo^b#2wOx zm1^HkSBe8*GXhtdf0wuIlbn4>k1XxW;N`uK(Z_|aDyo;dWw|UgzE`5 zb7WG9e?)yc&UCH*sWn~EuNfE`Coc*M$a~j!K=#|S0=XiI`-)PsnV2}qk$3e9>e@bw zDrFO;JD1nDxvSdSnXAacR&VaAJ7Z0$ZIgGilco<=`~pszz*x!(8HRVlf7ta`jHUBU z7_Hb%p07htTUq)RvbpUJ_^|~-FiOV<8+@qj8{!@ZDlXrG$GjKSY$__q2dgnNG`2Yc zW_A9@@#)?NPB_OiRz{eK;2w4W(EIFZINx6SBP-nIfstU+-G_AJzj5^wUyWxq+ycNw zvSlQ7u!em(jiMPe5nnY)A+6Tl3>q{=|t5Hu$@O`qAo!h7;AM&Qv!a9Fx#V=fg zZDRWDI(;XI_0}^Vj*BM1^Q#<0SxAaanqdQ6fhxE+?%kp~lm;#RSL+(e0jNf98PG%c z>U&>wFqBiYF1(;}zWt%I?=CrhrjQ2@ix5?qJiC5xlGC=t`@Gv$$v?a85!+!Q&nwVo zTz(z^#y8`XkhzKMH3Js{P&Zq0Lg&?0`&*dko=fDlUW@rHsfgNs444=?aA|^yzFMMo zB=0p#%8ma0#9gU^*5*=!TCGkQ5^W>WSqj3_%c`G*f@ZU>pxZ0$#`b;ZqjPKwg_Z%+#+uLQ&$)G+aj)zGEEX zeZqW|{Pe^9mTuutTt=h1sL5aQ3J?B?E5C%l0xBf8n^0b8jtrqR#AAcPf}U89NR8C? z_b7b{mr!~$+0V1Xzcyd5&u) zziYA%aLHa>961d8;pbi{*(#uuel>ZrwAPPCh0W3wotF9MT-`7ul?Nx(pd&P(H_Py- z=aS1Lx+pdPRljvvq#Lml+*WiI2kN?U7i8ZdiX8U%(Rd&kGz(qFz`r)SPSDoN{%HXH zX!G|TNarZr|N0)ay~8gdQ5vRsN@X4hva}jo&d?YC2qRQHF7-RC?Czq&7`vqCk4RrC zEnTUN^FZ_I05S;M)$k>mROAqC%WO|8EZS!++awOFbuB_dWl$j<2U~-dcBVO3!zY}+ z%wJu_&#)Ws*cnX#Adm6eczn+ z-*2+HI7+)Z;Dn@xp z(k=9j`ttbvn`QLNS}k{R@UPGpqngk|VC!!I+H#ga)5!3OiPl13+FVZ<^#z zw|jgt=2&6Bj`rlzqb>P=r^jbXRN_nTEd{HE6kiHhWMKlWtv+6K{N-YUyo-AH7C7J; zTOH``^6b5P97(vyCxOVsvU7WmE{1Wg%aW1!d{=N<)3bzD>VB;fBBm3(Eab0A!`7NY zPfYduhJPf?S_pz0;CeTp%k?I(nw`ShnV1~WJI2s}VTC%B2V=2BCl#WCYtvzgy8@nY zS&ucD#+t|f(_MSd@b~GSzb5>3k;Q}!Xi25=#Y)@&2s7fPM>7G@UbWo(Et<;n*@8q! zV{#R?0vvjVJ#sH9*nF&TShZ_%ozdZL_jiPGha#xhoCCF$t(Ou=Wbrs(EE)?ys-0v0 z8&B5<=0p?wM`d&Z{G209vpled+2N_Ki)Z8=8WIHePV8J?(u;;C3s`k?7J8R0U8>2wO7u%(I`L{snyI@#Y;diq7aS-|t!pJ^j`-2{TqTc4Sx*)TG<(X0y+;N>W(W-j)qBj4o^Q~?5 zP831RWzs*nN+J-thRs0W812%w(o^Vr@s1ppEY_m9!0b5|Co9dn-o%b zHR~Z1L>U!^Y?6(VmW~yTS!fgesug1Y-6y?&<$0jULwAY#$IpPR@O_{e&}9Xn%NIzA z@)M0`(0Q*^4e7q-Cf{xE-E$+rp)(#xkTUV%x>zwbc)bua!iv`3QJa??Osw>Jl;{v* z@<=8_BZ7xEYz(1pAA{T%S4A8yfBAc^Sd=pFi(t}fCW0we&S zjk~Mr5~GTd{9fd!i5I7dV_3oW+W{!S=aKC6xJ89YGg(Y)W&fw8-k2xzEk42LvFb%| zY9+LRe8}C49tjz3ae)N$1B9UqQ=6s}l{tQEV^Xt8^y87Vznw86at;ke+e!%(X<6@% z^U^&3wb9VO=aQI*m?GjaNDFhSvny6B z6{v*<^cWnuRZ7p!9x=U+uSeYX!NZG@%Y9_wE25;k>Pd1s(i<8&i2ct?GP^I_bEC-{ zjbe30TUfizKw+pu#sSqX1(`3BLedIUiRUK%VuBRy^O?ESj~|7Mb;ZY)Yc!X2zN17s z+|5b0;u(SGCSF>oJ396|HahgWoDL_9zU^TbEiyR;5ZlZF(OjJG-=9CLJg*KSxA4-n zwZ0XK?E5uZ2-H*?PKDvQJU@oird|cySfrX7ZgG@?dTaCjOHt?kYc5~x2q?T0I}K+G z?8zdeA52NuC1q}zAXISJNzB3k>|=7FX|2{w-f~ye&aCtDN`IIRKSIP;TE}y5y$alk z08uppMb7@?Rtp*FC2)2n7E{{c3?W4QV}mf~`+AwBB0wmSmFHmnJIjp!`d9~a1EuHdqG@$h!hCDD}~ln}hp*?X=J-&O$Gi?QW5Tic8pjz>`! z2k4s^@Mlke$P(CFg8@a4byVgZb;n2Q64=o(_YCP}7TYSCwakA(5g*MM3}6G z75c!@^e6w$%Ooo30~MV04E+y~ zP5<2;m9Id$A_6>_65bPg*&-`D`!_NcrXj}o_X_+A@Vd7MV06rpLdGc7dG)vk-KVBN zRw-tDww9ir&W8Mvo*tzuNsInuBOo)OXkcI{7-*J8y50P(p#LMpqf@_E_p4+F}L_tg*fW1{*N#{y7`iEa-c0hogd!(*{OmW~%-xjjHVag%hg1c0{S zV@)ixW=<)cX_ueYy21~{CxbITYIy(DfX%DgT=XK=>D;) zydUWcaudRz-9)F)VQBZ4|E1f1Egdf%qKqQlzx9X-7%V_K*zr$H^_~?ShaU3Kmv^8) zIxDuw{HLWnrek&D5l<(Z0FYR{fS4=&=Ym|L)00##t4c)EsardWO$>id=Dif~elKd! zXcoOr6P)tlcZB?Z#XX||Or`|N9IO7XdH>(P(zh$GHXz~D%&EmFN8nMUr)Z1vAC`9S zBw!fLUytiw;RGHn{bgSeaOmABQP817ihlIF0RCI<*Db6sHs_jdmR*8*qfWkFI^$(K zuF*0~k#mjV$}BnerxEk^1OS63oso=hmjou`Oywc|X@9(Q>SXWT*%N1O1CPF7`cq;5 zA9d{i9qJfw&jY%un8f4%B+LQi9$^0$5XCS^!0sg^+))2hV>70kyF`RFxRG8HI;p_% zXZ_%HD6py9-)D-ItpRVjMEc9|Uq{-%o!$bSTRiYjdtN zAW(3oQ7+qm8|PuBFCT!Nl7#snTtfF{PFqi8{@hfL=uE|P(yVMzba!(R@j32Kg9E|` z;Ao?8N$Ai^n*lPRi~qC#rvM4BciHMoBZ0|8Ey^sO`k(y|lw)Gg={)Uj0(_@BhFR>7 zT?Y{E01~3m?CH-w3-m|1Ev%0JIhiJU0ZyK#Qm9KWp#^F;{}Ye?d&PhY-2n-o)x2&0 zl1QI-U5Lw{lR0w?n2g&hgU1hgZAP>DBHy3;@6&6#LYS0@@rpLJdUpb!Pcox9eZh)u zn%PS&!_H@_7k{~{h>1J7U11U*KAQ0WAO;5AdnTs*fz_QnruEGES5kK@?93y<*Tq(E zMs>_`i`eyv%mJufFLzHa#?nnowfVfvl9!H4$Mva%Y5ONbR&RLzY5+J#gOFcDwRrfM zNBjWejzKJAc+2wTpsuB9M;ySy6a4%C5F{fa5G?E_>ZzP!#PDp^Ny%5fI~xU4C#Ufw zsdrxI`X*qL4`T0DSqgE}C#sJaTvu|t(ENBW)q0;cC^~IFTMnxu@2)e{=bcuET zBk^HQw(|Xr#!GX}CN%n)ly1A*ZoI_E3$;bJ<&1h!kLc?Nd~IPo64)bATNCijP@~Mx zQZ8B8^xxtQQ~wb8P1y1FSBPgW!WriQ2z0O|scez=;~Er%Tf88zj*6xt`z@`yH+TFEHYl$j8;?1!SEPpv3WC;j(9eWc^1M0XlSme z!(1jm^-ut+Lvly+f@{Mo#|6gWgioIUu57Y~f^&uV@8N!TqT~vQoMBVZ?S2s&$& z5t!(WKWWv#h@;v{1@-5j6aphIPIrzNoc*yL#FdfX-lDSkfVJ2{(PY7~S%i~g{!ol( z4S{*AFI1Z0^)1$13H}>=R<1j7x@~VaHAUcP+!nRuu>!Do821<4w2) zV*rTaBQtkx%V`XG08h~R%^Q_@!3i@*%ls_k`eNbEI6nI7na~wpTIKXBFY9~d9aG3X zUL??4#VpC6+qu#Bea%k-81Y1qOcnrTQ0S}o>Y+;912#ZB#|KYJuq{Vq55WCFqj|}>;T1p+bk=mfU`i>}1d$<2SuZA?msrE;EpHJ6L781bC`}d>PCL2Wj_h`ul zrNg78!+sir&sFbedr#-j*~~Z@CAM={G<%oMFu2@DdfnuCr(3P}!>9qlpT4&pe(MhD zYOd}hI7ZB4x5Ht*g6zEmnG%@2TRN^HgwPooI7ym z&F@m34ASL*!||eL93m~<`DhJbFf``1KWZH3ml{Q1ReZ$n!Zp+p*K|FNtI$joqJADMD$Eb`%TZf)UgQw<(8hD3Tjp zN|(ul-JH*~&N7Kz+6#M~Y>yD%>-G zRj&dpHdP@+KuMusiihuJ8DNJXV~V0wGpz?>gDyp8zxJvjStFZveWXvysRzOnh9iTu zwQZGen*w>oGK#+s?uxpINiiAOo(~XSGYn94-WLeZ*C9CDOyf$>^7q#8xS-a_71)o7oHySHbt|z3=Pkx2 z?4|J3O$iyF0oOY&E&8?CtqS{A+Dx&C{SLQK6*+PZ_9HNYhwqY&dR9(4V)U}$IkbN6 zf|5<9ZVq9YRNRDy*rrp-n+wUXdbp}~Jy`T^aQ^&HCAr-q|A3_`x0R#W`f1me8&-D8 zCVI^TT-l}+dFDk9BxU5f>S|buc9+&iv5U|)P?S8!h1Q``8qM-cu7;YV>0fooWZ5JKUPW9W9{U0MO|n| z?R~W}^QzX&E~XL!rdG%mHw8AmAvPG5yF!U?KzytVa&djAAzIrL46!~C2zk)uIQ2w9 zu|S`E+iFqA-%nsp(We@-Gf4K1_g#MvUdIzTxojcBTobBFQUu*}k7F0V<(sA52sa2m z?xSVp>M|o#a_W1mSF*JZkEbW+HT>+eYclw}Bb1FsXD6miC4 zgfJJ{w5P*Xj?C1N%%iFJOZ<5Q@n_L^+NOcb zUKjW5cqMaHyd+t~cs(lr7QW*!OI;*2$Z5N}gZ5^D}Kxi_|ChQL#}mxxKEHu9yax zRvJilMMw=Q)0$?!Mp?A)j**+J9-8U59N}2Ga~0f~#i0n-*RJ#DF`D1CdnD8=;p}{g zx<-S{zCD&yl|y=&3N>~R@V(JPTrRS>j#GqHw$-l6hqST7SKQTf=8G8ZmHdkDN-QY4 z`(;VyV?DawfBBO0blO#%uVNs4LXOKSyU-*V>htv}jI?+n84WNGg>833$2TNgf&yK{ za#@xoppGH9AkT)${7TW(q}{QY53?^V;T~SAy_r5WDgNfvlO`=u^LZwp z_?q}0Rw~UB_S~5-<%-Y3K=q zz6zR1U`}$RlD)jwtC1qB!K~T|P)yE1xV0LE6?6{NUqR!JjU79u6We!F<$z0Uc;=$q zwsmhWi=?+|GS)ZZJXgti@df?1{rgg$;J$9W!~2T{zZ5KToEA@of;a@{CCZnKI&#B} zOTS;u-$C(Y@#RA|0nb&&Q4rcAVpQgk9@fuLZbT6 zxNr%1E#U_%9`=muMR#zQ3p;!y5Qm_tt&h9zYt1G*Dfdb)#D5P*b|cn5rR?8xCE>|&1C4`-JDc(Kj&QZTsj{$6;3lvV!qOc^ zXTJVh%8E-_!Ll!!B-bO$zM`{Dw-DdF(NE>dmT54;-2+LzGai#}6C!b3hNL;}Axg~> z!QdXjBRA>DV&FG;6EacXQz%tS47Ku z&0m~d&YY{W&OSeCjZ^XuH$G`J8DH8xE9^Jed+*p}8e6CSK#lK#o2paZyv)JYM%$gy zMDq+JPWD*)mE=^*N-V8k^a0IkU;td#IP*$NTcmx3OL$Hy?|x2*`Rpy{y}p3fkgmZa zs4CbV^g(>tUrG~N%)OCMYt7<0;iWzDE}@QjeFNQKaS4uvq z+$@#*(zVo?g4E6RfN`zvZ^@}E@)v%7`rHpKe214p5yLNBxH}Igf9W!DzA1=#Ew>aO zVfZZ=Bq^fL#`bwVBKWJXtV&7UH{r|3-h0s3A}%|I*rD({gCQ{{(VA){OVCciZ0_BQ zX!uVj*VGM54r_dU^F>ivY$8LwAAbJ4RCJkJ&kvWduZ2{=+rKJ6Z_DBvuU8Q%Ff;4C zO9g!Xcu2jdxB_H80MpxGmqYH}N9VIJUhw!j=2_((b~W4an^CBO!OBHgbWKaIX`1K+ z?(*|WiiNOSt~n2yV{0T=AluQ+$9i>t3;ZJ^`Jh!(c>pfEIMni51*lZ|63@NRLWk#s z?}})mHD9BCWj&5pt+xHj9B7<01Gm)d2|4TDsBG~=@`llri^D$M(DDF7Tl$xw-D(2v z?HNTRq-7%U`}!4r?nc5irFPOvpHU&{eORZ7dImk^x5kdxGBGYQ#@zgVc|H6`pNClZ zf{!KsrqaPq-Q|~KhF$No(mVI_Vg8Q{jSH;J(;(mtyJd?^YOTc~-vU_mQbXHgf;Mt7 zK|8TOl9fdv&Qx>}=n}c> zYA%Ajft<4G`SN+BZHwUgeGdV`A*I^0sF!?eB7BRkK@HHAlnhYNaxi|2uv0v~gYUKH z+k$7!sBEg?D?%`|PN1(zisG+6DqI?z`0!k%Fk$ghvl#Wr7Yjv6{&|l)Rzg(ecEeH}cY^`&yu!;j;uasriYCabR-;JqpqAE50&cEUhU+eviH(+6M2ek{_8{r9m!b^}o&Q3a2|Xmn9c{K!x< zrs6G9C%H#o>zE$4-$9~rABL2hdYFF36N~Tupgnk8XyTx&5YiScQ0)ZOs&m@GJT;P? zP|i_!(N~eUmu8jC7Y}uN&hCk68*{i^y>`5GZdc8lrFIOT^YI8svktiZCcP`G;Uw^M z$^h^c>!%DgQvC6>2$IyXoI=S^wVKVj=zLUCy43n^C*sZR$w#4D9Zc zqD+>%7fMJ6>weExc1LS^9G(j&bzh0#-t_J*SM^10&6?r7^$Zb6bJM-{P)Ir@cIy(Q zg%NCw28H-TQ+c>Lvs7xb9}4rjh?uuFsMITu_@vv&9gH)7II$-yjPWj;T~8qI3`kUp zOSt2SD(g-n70S&fc`rAoNt3cpf{Kd;Z=tWLA3qlR%jeFJs$2ArJnIfK(ib!Ee~RDF zV^_t6B|3%I5cZXM3@_W7f-mRIG(y6JmlE=Dd1~{0^#O_>TlRC^o6gTA9P5iIyV7ng z$?xTF#&n6}%~1aNgRCpFCY5n|PXII|o79*W@xH1i&ICI*Sm`!Zc>ULb$ptoXqn_%Y z7FMoc1sc+)zPo+!al~MMoM0@ddrcSd!V~x7Y1!h<1otaH)t+}`btg|)`VCj`f?n=p z)FNKa#Zy6gxFi|J5V8h}&9-|1Mm{?00NbpC4R6Ds;0%u)MwG>OvY_8I|kM+E5{7d?l-??vqgmrV}}CErJ{qQYnf z=CV78_v^wdBSCVf3!snP&1m&BgPO=Yf*&VpCONNn_X`X!L>r06`pViVRK{SunvR`l zc=bJ)*<{&-mdWz5M^#EnYQr@G-5SuvnX?6q6K?bC50Q&35qsCG$Pf zr_cm^a>E_k)fklYl-VR)amV{dT6cm#;v)6ob+8%JU3{KG#jfZnF&x&wn9)`PV_kA%wAuy>}(1WmRTUFKRS2li4Dt2KgPRI8(wypY7@+4SgU zMt*BWzHDX+;%+ms^ZBF)izjgFkVuFeb0u;2h#=DltCMV>^SpU?wN+YpLZ8Ks#KN0C z!Od9p3DmQeg2P!-=`399kCDzR`#ympr=%t4bG>qjCf*!jFj0NNJH@unaLL|CesnH8 zOP{D^oWVkQY&s`HtU^k2TtiOoj>nj4`qTs(MqLRfsb`s{L^BcLK=WG zmTmzz16dT*b!0;xcaQ7uLb{L=r;ku9kxpu?dK8li{Dpa_>T>dnzTUQ7-elfPp3dW} z06$n+^r@Cvu6~vYEj~NJX~eJ*Kr50xdSl?vT(C`Jd(@B8fU6Y+TF@AEo??YM@A zHFXs&`w-iA@D9MM;#%ypMc!#8u8(^#V@?%v-@>b;!6N-qt`5t<7lxKd)3oHRffijt%$SnHy69&o z5%{lyvaH8Bj1!RVFgxGb+!5lNc{Y1!`;UQ({>hwedY8p=SCJplPj>37pl&&b7uY^~ znkj5C<~pUznQruUBw?tXr@NJad!cr{=tCg6};xP~b+_{y68Rtla9j~$eNxZJp zNzS^f<1EDjyiQ$wQLB=y%jPaemxMu&BvR+97Npc~nZx(GDKuc| z3Jhq693gQ;djKh`DsH7;It#cKDtj_W2}3wvM#-z2`Qjo1o8)kvj}hjwm2n!nMTX*z zD-mVil4?evG*S5I3k4_W5eh8DI*$Q4*CLdckf+l$cam0R2wTOeNRm@)#sqzZX?>kixfcbD& z|7VCEY6U?)+AE;#*mq>ZL-=yT7j=yG$Uu4floNIk&a;7yt11Gt%v?K7$?v@MqW#Nl zVa3Tic8n91`4pu3>TdV_w=)iE;{#A~nsw@tKzF@6%-F5^qRs4r7?z5zL4G;(gXRD= z78+(|0WTr{PxhY-#yh&K34i$j^J(zg=%cg*`s`)uur1An&h~ZJWdoq4NNQYXn4Os1 z+0CN!mG%nqkJ5H;Z(Zz*e79TPc0Gml3;qkAs;Kvrm%WvttH;{|qDO@HjdxNyH7;;; ze_~hkVoX&wfNNX@(0j)kJ$3HC}o!$2K?l^o$f z3}D%+UuRe$byUaiWkd?~hvmxLeYLkNz&*N%yCEf(CcL0JtPvdFst9b5h>2jsdpHOkt6(^suP}3;O2) z-iX`2lg!hQqu}IWaaT-M;_cwKsf!Inu(j|MVT`D`Wg;#W*K5`=B$D{@g@5SkTPnmp*#JK&bt8&Uf@$0 z?L}x!;s9+o=38d1`KM&n$LX^!HoZ?+sQvVf}ud~Ei(Am6NOj;uzEPnq>Ps0Tjw zKmJ5Xk=k~@%c?H@Ja?P{hehkfr|#hAB^uzgL02thppMw7Wh}#U-azr|X_AjJdcIzy zgA~7kOpuLw*zZB(j*cBISc%ulD`~EJ#g8}MZqAG^%3*s_2H4#WYl_kzv#Rih_qeizzVMu z1)vUf+z3&rT}_U|=Dvwqd%=>n`_$L84zbixuSHLz#O1AexYp^~vf7cMNNdW`g6&rKdp>2pn53=%(Xpcj z^iIQhD*JjPY4XR4RFVDZg>qGRl7$5Fynm}qcHXjihSR`dFnieLP3^i{*P-4Q-?8cq zrq_YZTF>QA8p(E+>z=q2%^OI^GhKZ&kOiq1Qoy{EfG`7iv(OwI+fFh1kGk(tQX%cSUKfQeG5nRxGC6%{1B? z_F0L2gIbVcOQ9dtYHkHFKnDEzlUCxpd%`^1Do}i&d0k^FGa0#95YjRB^n|B+vUcqP zqEparxK5j^cIy=k2$bFT>T2b#YPy!JI;Iua6Yp%VSSrMa!5_*B6RE&z0o z;VW#{y18)zL3P;^U1->6%^qI3n=K<1MGV0&y+D7N1F2di;-!HF=i7Q5O~`IeRN3E| zV@D5xD$C5uoz|c|(JNyb8#otwcQ^i}b}Gs#LP7|g*uR$})323&u)#VZZo#D7aL(0l z&F|vAx@#S8>UZSwXWbLO4Ivga4ckj|ld93F>=*D|v}z7~JQikds#oLrsrBvXXK&8b zC60)p`+*`_k|KL}6;m=T| zeMv>ErbX!FJ*=^Q%_K*UbWwTnp`VY~7=I?Jkl!r@2jcULps!$8}d*&nPLucvv<$Eb@qn@Devp0s|Em)zT2@F?8ix_4{OzUZ)bjjxHt9?2pR+`a@*FXVn*fI6iB*dBJa!G~X-gIpe zh+ej|Ut1#v?-iy`+)q716fSB+r(9Q%n|&DTqZYOJs8GWfFHA?KZ+7qZb7J^X7W&XV zHT<@+*$7Xkki>w2<2QCvB^+MQ!d zEsI`}%K`hRj&=9kQP0W_Wka}Kd8E0T@2jxizYZK(wCcPtIws87A7pTF1}vp}lAUd> zvQn|wg6^C$;)y}VIRU-trM4qD^+|ieUZL#(8&xB=5PrALh}LKP-7f4p4$JxF6YW9j zLgr&?Vj%6Y`=^cu2+$TI_*eLS3R~{xUlv}f%e>suR;In$+5B9wgVte(S5ziOBXwEl zXr#&8trUxlpP#LQg9RlE$L&tdwLSVP>=}hR*&s_)m>}KikRJuWH~_>V)Ki-j1wrRU({NpN0UrHg(P4wP(nPr zjo&~3;CzcB7d)d4Ogjf3N8`VaIe^jJ!>9AN?n*tDt$W1LS%FNt2_VQC-MHp;7$kc_ zc-%*9XO-%9XLFkBQZj3hqrFl(RBz|_CHzG7>RM*1Lt<63HNfK2s00-jL0=9{Cy5j6 zdjr{*ee{!*bJ~Y*rp*T2Ie;oio|;P1ujZ`Z3bBREoi;$8nn-}D|21? z_`@#N;S_!p@ZdfhGtZSF`$NF%@|~WFH6En7iO9rD5u2R&L3p0Ch~$#Pl%B?18H$Cq zh8*UUa?HigS|nrn2?q@qnUN$2w_E%TPmitu#=ey=$EC=Qfr_tNlO_pw`mK{T91`RT zYvL0s`uXtvQ*VppE)N@SCyJWeL)W=ZQuun1MK6dEOn8DNEA)~m#s^qHP9SQOZw zs#2CT;N85ODm~Fx-|6eZ->DjCDM!N~ryd{^KE?9Q4sFp4gI&%5XccD%la))*KbS|X zikqVikD*g^wpaeLZπD!?%Vg$fcWu`WEZ7N0PS=9Wnz9Fu1E;Zt;_^}i zbys!kxM$MbQtG=O{6fywY5Yh&*^T2b2)Y2`!U|8alX#rYi`0o45Qj_}rRD%VI-48n zQnt$Q7ot<3o`&Cs$Zv?tDb}-gk-;0Kj%G1L!_fI#)e|V2kgfO&3ayI5I%t% ztFs*fRpox1@|Cx&G{>fVgo#OStW+JV9ghdS4VTZe>_p84*XQ(6Pbz9(U-g2`%XSGgB8OZq7U z!L0j|a`$}--9IH4_St8f)3Iv7SKonq^4pa-Wqq8Y2~}?C3eN@2S0b$#47f~p%8874u zpu(|43u#>8yuT;r=?1rM^lAQHWzMAY00u#R+u+Ui)1qd(fPVYqp$DY{YV?b#V|aPI z8uAxzq-BU&*qnE*(%Z)DjCRz1Ir%aTRa|%1F}LRK)r{K<0|f$#7^8O>Xr!EMN3vQD z=O$?DxxFmz8}I>T_H3YMtkL+~!Fe+CN<(G+IFpQI1kCZv#N3u+AgYW7ZKjRiZ16VL zZ{plvBy?^3Aa=Y6!o2O`QW`nHwOLY$ff)xlOzsMysA7N1dUSO-!0955@2du5?(rY zRBdnrs&UF$vKk4Z$#Uhz3nkJU+GK1y@Uz>Wx(?zLiCt+Bq}(V`f=*WC}CN`Qd2L@X39b-k>U@%7DlN(%{lZ`t25Q% z13Ej2t0KcfTW!3ejC?z&JEhkGizU=O3<+<~moT23-$AIvuT;^`yIh=-?Cz@OoHA-;j31cgGGAmoWs}8wSd4dH|^l6)6xN%C3iz5v~x09;6IfnK!JUt6bqZy93L2K@`LqHRpVUBJJlI&suJBlNkB6 zoML4)X+>jDih)>^)%w&qyku`_L?B$WP`jwPyShWZUe#x=6E>KR;+CqjhfH&E-Vn=a zsb1v4ObPAk2p_5rgxq##>ZV&=-&flVD$$h z7Tgy5G7r**^yZVeE-?U8qb@Snp-^`Y?D~Vvs7ee5NBu zmuJB~8eGs1MNHsotVX(JK`_R46y#?h+C4Of>l2TD;-s8@_WjFfNO;L%3&|7cP%|U|3n~6Ytvo zn9LSmUI<+uflhs(=xV=jbqNNQ;4f%I+lJ;WP~gw1O2XW(Pr6i!?KcQd;-1cgVzVp| zg!ZZN_2fdgi0oY{)68xyY>3f*$u^m}+rV3BrPG6a3Y@>bm<+DA)r(%-;ZJXQCx>~a zs~u*EQ}Uv1X!sX|r~B_ycL=sS_UG4lBq`UsUozvcH#7#*?wr_y&wY^e&T!HGF@YQ3)H3Xa^%J#PHRH*qoVW{mrlvcRT&|a$FkNmi(^M?7u;SKr6i9iZM5--OhxHp zw;2|i*!Uch7@LSUMLQ$}0=}U%)@^I^%`Os)5UY#3JOb3=WTm>*pyuXQMSXaqGsQfX zI-I6RWqpy%X5|D~ah-K>sacto9T;6-e$q!C(QZFp(mHE7-CXB#`5d|>q<5)Oe(S?4 z6{ChAzwy6j+?BliJt97tf_+-2X?szJH`U9E5m>Ae^LA$b!x_DpYry-puQ!>oExd#)OoymEw`XI43#W6}-xyobG>j!T?A0h(@htTas{KDd|RR2j5)%Tqqp&olK9 zBcS!QXC*@Cv_)hpd-c|BeftK%jM=w7MgzL(jO=y`GaqrSq?~w-JTXHT&uX%>aXtJM zX!=u6>|CM8vDY>Azu3{Tmv1F$s?fDi3_1bo6(Jmne$^vg186}2wD<5iilIj4$~cgi ztLdPGaTHYA_1gxofwA@gYf~-J_-$>tf-3n|z}j#HEIV)UJJA2%KE1SJ_|e9s za19yV+8b{EK)+^hs1um6!9l*#(a)lm;mbp*y_;-vUrRCti@s3SUouC4?OEd8z81a0 zfETaQ)`l)SAanl%SL{so-e;~{z@X#NTYf?GZE&0cCr9sM)t{SumFk3MY#=8v=6d&Q5g0~#fzpSJma(JYQLtdI7w+ef{9wRn1+&Ggu9 z^Nod007LNVog$~(hZpll@5|k~);&RrsrCu0<@b^`zYBn2H*ecl9$?sgnFtKdKQG=( zvA3?PDYh*UnQ5a3+7=x@&u1&n@4cm+Z>K!XcpG z(7?b5VJz4S%)Hgw*+M6T0$!YYba@6$0-_>EG~mT8uM}3MzZ}4{_IQOjs`d?@z?3q% z=Q-yWodp-J8n1YVVs^uUE?``7b;NVN@dm1k-}FlrVKK;jcP6gbJ{BfsPK^>?mRw^L zml;GewywL`cCU|LcfkeIEj!){BDuQZz#SHmUC+b{e_PK2T9NU^%m?lx5W`q7;KeM@ z1#h4I0NU{Q_yGwOw-@*TH5oll3Srk+aG|upajQ3qw*#gCeH-}DV1~0;zzeG< zFK(HmI9$UK=-U0Kk=_{g|EZH(+iOU1Zc@O zZJ=y?{9a)Tkh7P4Kyeid#~W9mjrwb>R11Ky^?FNZI!cfGo;1TI6P4$yTvcD-oAKqq(sQ=68m&@o3ey9E>`r~-??qst9Z z0s~~MgC;Plmbx6WKy?nt-krKu*ZHm%@3!z>rJ Date: Sat, 11 Jul 2020 18:02:47 +0200 Subject: [PATCH 119/323] @jcallano added to contributors' list --- README.md | 2 +- src/PJON.h | 4 ++-- src/PJONDefines.h | 4 ++-- src/PJONLocal.h | 3 ++- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1afdba96b7..3db796ee1b 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Telecomunicación - [Universidad de Cantabria](https://web.unican.es/) (ES) ### Contribute Feel free to send a pull request sharing something you have made that could help, if you want to support this project you can also try to solve an [issue](https://github.com/gioblu/PJON/issues). Thanks to support, expertise, kindness and talent of the following contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: -[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj) and [callalilychen](https://github.com/callalilychen). +[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen) and [Julio Aguirre](https://github.com/jcallano). ### Compliant tools - [ModuleInterface](https://github.com/fredilarsen/ModuleInterface) - easy config and value sync between IoT modules by Fred Larsen diff --git a/src/PJON.h b/src/PJON.h index a71dbf9c8e..0fec7acbe7 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -28,8 +28,8 @@ have been strongly tested, enhanced and verified: pacproduct, elusive-code, Emanuele Iannone, Christian Pointner, Fabian Gärtner, Mauro Mombelli, Remo Kallio, hyndruide, sigmaeo, filogranaf, Maximiliano Duarte, Viktor Szépe, Shachar Limor, Andrei Volkau, maniekq, - DetAtHome, Michael Branson, chestwood96, Mattze96, Steven Bense - and Jack Anderson. + DetAtHome, Michael Branson, chestwood96, Mattze96, Steven Bense, + Jack Anderson, callalilychen and Julio Aguirre. Compatible tools: diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 78330b588e..abee7210a6 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -28,8 +28,8 @@ have been strongly tested, enhanced and verified: pacproduct, elusive-code, Emanuele Iannone, Christian Pointner, Fabian Gärtner, Mauro Mombelli, Remo Kallio, hyndruide, sigmaeo, filogranaf, Maximiliano Duarte, Viktor Szépe, Shachar Limor, Andrei Volkau, maniekq, - DetAtHome, Michael Branson, chestwood96, Mattze96, Steven Bense - and Jack Anderson. + DetAtHome, Michael Branson, chestwood96, Mattze96, Steven Bense, + Jack Anderson, callalilychen and Julio Aguirre. Compatible tools: diff --git a/src/PJONLocal.h b/src/PJONLocal.h index a21009821f..c79a752cdb 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -37,7 +37,8 @@ have been strongly tested, enhanced and verified: pacproduct, elusive-code, Emanuele Iannone, Christian Pointner, Fabian Gärtner, Mauro Mombelli, Remo Kallio, hyndruide, sigmaeo, filogranaf, Maximiliano Duarte, Viktor Szépe, Shachar Limor, Andrei Volkau, maniekq, - DetAtHome, Michael Branson, chestwood96, Mattze96 and Steven Bense. + DetAtHome, Michael Branson, chestwood96, Mattze96 and Steven Bense, + Jack Anderson, callalilychen and Julio Aguirre. Compatible tools: From bc7be77e8bcbf982a0284891b7e5aed511d293ba Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 Jul 2020 18:05:49 +0200 Subject: [PATCH 120/323] STM32F1 compatible pins added to SoftwareBitBang compatibility table --- src/strategies/SoftwareBitBang/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index 0c705320a7..b784eba700 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -30,7 +30,7 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above | ATmega2560 (Mega, Mega nano) | 16MHz | 3, 4, 7, 8, 9, 10, 12 | | ATmega1284P | 16MHz | 18, 19, 20, 21, 22, 23, A0, A1, A2, A3, A4, A5, A6, A7 | | SAMD (Arduino Zero) | 48MHz | D0, D1, D3, A0, A1 | -| STM32F1 | 72MHz | ? | +| STM32F1 | 72MHz | PB15, PB14, PB13, PB12, PB11, PB10, PB9, PB8, PB7, PB6, PB4, PB3, PA15, PA10 | | MK20DX256 (Teensy 3.1) | 96MHz | All pins | | ESP8266 (NodeMCU, AI-THINKER modules) | 80/160MHz | D1 or GPIO 5 | | ESP32 (Heltech WiFi LoRa) | 160MHz | 12, 25 | From c7c0f4da7236499475ea8abc34ec146d8c2cef05 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 Jul 2020 18:12:24 +0200 Subject: [PATCH 121/323] SoftwareBitBang README tables update --- src/strategies/SoftwareBitBang/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index b784eba700..5d8f5df1cd 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -24,7 +24,7 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above | ---------------- |------ | ---------------- | | ATtiny84/84A | 16MHz | 0, 1, 2, 3, 4 | | ATtiny85 (Digispark development board) | 16MHz | 1, 2 | -| ATmega88/168/328 (Duemilanove, Uno, Nano, Pro) | 16MHz | 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, A0, A1 | +| ATmega88/168/328 (Uno, Nano, Pro) | 16MHz | 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, A0, A1 | | ATmega328PB | 16MHz | 10 | | ATmega16u4/32u4 (Leonardo, Micro) | 16MHz | 2, 4, 8, 12 | | ATmega2560 (Mega, Mega nano) | 16MHz | 3, 4, 7, 8, 9, 10, 12 | @@ -41,9 +41,9 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above | Mode | Speed | Range | Supported MCUs | | ---- | ----- |------ | ---------------- | | `1` | 1.95kB/s 15625Bd | 2000m | ATtiny84/84A, ATtiny85, ATmega88/168/328, ATmega328PB, ATmega16u4/32u4, ATmega2560, ATmega1284P, SAMD, STM32F1, MK20DX256, ESP8266, ESP32 | -| `2` | 2.21kB/s 17696Bd | 1600m | ATtiny84/84A, ATtiny85, ATmega88/168/328, ATmega328PB, ATmega16u4/32u4, ATmega2560 | -| `3` | 2.94kB/s 23529Bd | 1200m | ATtiny84/84A, ATtiny85, ATmega88/168/328 | -| `4` | 3.40kB/s 27210Bd | 800m | ATtiny84/84A, ATtiny85, ATmega88/168/328 | +| `2` | 2.21kB/s 17696Bd | 1600m | ATtiny84/84A, ATtiny85, ATmega88/168/328, ATmega328PB, ATmega16u4/32u4, ATmega2560, STM32F1 | +| `3` | 2.94kB/s 23529Bd | 1200m | ATtiny84/84A, ATtiny85, ATmega88/168/328, STM32F1 | +| `4` | 3.40kB/s 27210Bd | 800m | ATtiny84/84A, ATtiny85, ATmega88/168/328, STM32F1 | When including and using the `SoftwareBitBang` strategy you have the complete access to the microcontroller. This happens because `SoftwareBitBang` runs a completely software-defined implementation, transforming a painful walk in a nice flight. From f2f816b6bc149d0ea61ed4b8181e1bf290ac14b1 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 Jul 2020 18:13:59 +0200 Subject: [PATCH 122/323] SoftwareBitBang README minor fix --- src/strategies/SoftwareBitBang/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index 5d8f5df1cd..5ff0145ac4 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -23,7 +23,7 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above | MCU | Clock | Supported pins | | ---------------- |------ | ---------------- | | ATtiny84/84A | 16MHz | 0, 1, 2, 3, 4 | -| ATtiny85 (Digispark development board) | 16MHz | 1, 2 | +| ATtiny85 | 16MHz | 1, 2 | | ATmega88/168/328 (Uno, Nano, Pro) | 16MHz | 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, A0, A1 | | ATmega328PB | 16MHz | 10 | | ATmega16u4/32u4 (Leonardo, Micro) | 16MHz | 2, 4, 8, 12 | From d18f6bd502fd1e936b800303027a81c84e0b2765 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 Jul 2020 18:14:54 +0200 Subject: [PATCH 123/323] SoftwareBitBang README minor fix --- src/strategies/SoftwareBitBang/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index 5ff0145ac4..da74e8fccf 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -32,7 +32,7 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above | SAMD (Arduino Zero) | 48MHz | D0, D1, D3, A0, A1 | | STM32F1 | 72MHz | PB15, PB14, PB13, PB12, PB11, PB10, PB9, PB8, PB7, PB6, PB4, PB3, PA15, PA10 | | MK20DX256 (Teensy 3.1) | 96MHz | All pins | -| ESP8266 (NodeMCU, AI-THINKER modules) | 80/160MHz | D1 or GPIO 5 | +| ESP8266 (NodeMCU, AI-THINKER) | 80/160MHz | D1 or GPIO 5 | | ESP32 (Heltech WiFi LoRa) | 160MHz | 12, 25 | ### Performance From 63927c9ea8943964fe3508ad7e4293d4d30db268 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 Jul 2020 18:17:56 +0200 Subject: [PATCH 124/323] SoftwareBitBang mode table update --- src/strategies/SoftwareBitBang/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index da74e8fccf..3923c1185c 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -40,10 +40,10 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above | Mode | Speed | Range | Supported MCUs | | ---- | ----- |------ | ---------------- | -| `1` | 1.95kB/s 15625Bd | 2000m | ATtiny84/84A, ATtiny85, ATmega88/168/328, ATmega328PB, ATmega16u4/32u4, ATmega2560, ATmega1284P, SAMD, STM32F1, MK20DX256, ESP8266, ESP32 | -| `2` | 2.21kB/s 17696Bd | 1600m | ATtiny84/84A, ATtiny85, ATmega88/168/328, ATmega328PB, ATmega16u4/32u4, ATmega2560, STM32F1 | -| `3` | 2.94kB/s 23529Bd | 1200m | ATtiny84/84A, ATtiny85, ATmega88/168/328, STM32F1 | -| `4` | 3.40kB/s 27210Bd | 800m | ATtiny84/84A, ATtiny85, ATmega88/168/328, STM32F1 | +| `1` | 1.95kB/s | 2000m | ATtiny84/84A/85, ATmega88/168/328/328PB/16u4/32u4/2560/1284P, SAMD, STM32F1, MK20DX256, ESP8266, ESP32 | +| `2` | 2.21kB/s | 1600m | ATtiny84/84A/85, ATmega88/168/328/328PB/16u4/32u4/2560, STM32F1 | +| `3` | 2.94kB/s | 1200m | ATtiny84/84A/85, ATmega88/168/328, STM32F1 | +| `4` | 3.40kB/s | 800m | ATtiny84/84A/85, ATmega88/168/328, STM32F1 | When including and using the `SoftwareBitBang` strategy you have the complete access to the microcontroller. This happens because `SoftwareBitBang` runs a completely software-defined implementation, transforming a painful walk in a nice flight. From 4c2347900c554f528d221ff90c55e924629daaba Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 Jul 2020 19:40:25 +0200 Subject: [PATCH 125/323] removed .DS_Store --- src/strategies/SoftwareBitBang/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/strategies/SoftwareBitBang/.DS_Store diff --git a/src/strategies/SoftwareBitBang/.DS_Store b/src/strategies/SoftwareBitBang/.DS_Store deleted file mode 100644 index 8bfb6584b4a58b8077f4e299d5e05de0da9abf22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK!A`?441F0p6mi)NE=c(V%07THl@CBWa)GTHAg#30*uCGzXYe&V#}?{TI7}cU zCR=h|n#4~1BE>O)Fxyr+FaeNJ1xLqhz7Uxg9mvQ=#>9|(Y!LB)7gR)-|GEVuc(Rn64l5`Le0oUU++YsGG7}teXWrWLM|6c)xqQ-v2-9 zruqdh?b9HdUSQsJ2AlzB;2;?Y8dY|3kkNTi&VV!U69(jdh*ZJCuv1J|2b)v^5ak(} zgng+c#3mXRhMgj3C_zn$Y8tG>2x`vpXzL2YPEpMftoR7FbFc~}q}}O1rsW8QqPNa~ zGqB6Rk$z4j|KEIH|L+?4mowlD925g#T+YiGL$cgD2u^Zsq~23SWL>BDX~IrQ#at_? c_>7u_<54=q!mv~12*n=)i3V?+fj?#71CR7P+5i9m From e97447f16431ebbb061ae51e582ea5699e2fdc7c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 15 Jul 2020 16:48:35 +0200 Subject: [PATCH 126/323] PJON specification acknowledgement remark fixed --- specification/PJON-protocol-specification-v4.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index cb099a630f..5bd8dc50cd 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -205,7 +205,7 @@ Medium access Transmission Response BITS: | 8 | 8 | 8 | 8 | 8 | 8 | |____|__________|________|______|________|______| ``` -The acknowledgment gives reception certainty only when a packet transmission occurs directly without the intermediation of routers or switches. When a packet needs to traverse a network the acknowledgment is generally sent by the nearest router or switch, although does not necessarily mean that the packet is received by its recipient. +The acknowledgment ensures reliable delivery only when a packet transmission occurs directly without the intermediation of routers or switches. When a packet needs to traverse a network the acknowledgment is transmitted by the nearest intermediary therefore it ensures only best-effort delivery. #### Local mode Depending on header's `MODE` bit packets can contain basic or extended support to identification. Local mode required by header's `MODE` bit low supports connectivity for up to 254 devices. In the graph below is represented the simplest local mode packet format sending `@` (decimal 64) to device `12`: From fd2c8712d5f13b7f22b4a0b70dc261cebd648790 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jul 2020 02:03:20 +0200 Subject: [PATCH 127/323] PJDL spec added acceptable deviation and acceptable sync duration --- .../specification/PJDL-specification-v4.1.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index d05b7ba3b2..462239bc03 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -51,14 +51,12 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above ### Communication modes The proposed communication modes are the result of years of testing and optimization and have been selected to be easily supported by limited microcontrollers. -| MODE | Data bit duration | Padding bit duration | Pad-data ratio | Bandwidth | Range | -| ---- | ----------------- | -------------------- | --------------- | ------------------ | ----- | -| 1 | 44 | 116 | 2.636 | 1.95kB/s - 15625Bd | 2000m | -| 2 | 40 | 92 | 2.300 | 2.21kB/s - 17696Bd | 1600m | -| 3 | 28 | 88 | 3.142 | 2.94kB/s - 23529Bd | 1200m | -| 4 | 26 | 60 | 2.307 | 3.40kB/s - 27210Bd | 800m | - -Durations are expressed in microseconds. +| Mode | Data bit | Padding bit | Acceptable padding bit | Acceptable deviation | Bandwidth | Range | +| ---- |--------- | ----------- | ---------------------- | -------------------- | ------------------ | ----- | +| 1 | 44µs | 116µs | > 56µs | +- 1µs | 1.95kB/s - 15625Bd | 2000m | +| 2 | 40µs | 92µs | > 56µs | +- 1µs | 2.21kB/s - 17696Bd | 1600m | +| 3 | 28µs | 88µs | > 30µs | +- 0.75µs | 2.94kB/s - 23529Bd | 1200m | +| 4 | 26µs | 60µs | > 30µs | +- 0.35µs | 3.40kB/s - 27210Bd | 800m | ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. @@ -113,7 +111,7 @@ Transmission end Response | || || | | 6 | |______||______||______| |_____| ``` -In order to avoid other devices to detect the medium free for use and disrupt an ongoing exchange, the sender cyclically transmits a short high bit (1/4 data bit duration) and consequently attempts to receive a response. The receiver must synchronize its response to the falling edge of the last short high bit, and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pulse. If the response is not transmitted or not received the transmitter continues to keep busy the medium up to the maximum acceptable time between transmission and response. +In order to avoid other devices to detect the medium free for use and disrupt an ongoing exchange, the sender cyclically transmits a short high bit (1/4 data bit duration) and consequently attempts to receive a response. The receiver must synchronize its response to the falling edge of the last short high bit, and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If the response is not transmitted or not received the transmitter continues to keep busy the medium up to the maximum acceptable time between transmission and response. ```cpp Transmission end Response ______ ______ ______ _ _ _ _ _ _ ____ _____ From 8c079257c59fbad9737bcab6d488b27a3bebda6d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jul 2020 03:16:06 +0200 Subject: [PATCH 128/323] PJDL specification mode table update --- .../specification/PJDL-specification-v4.1.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index 462239bc03..0782ca82d6 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -51,12 +51,12 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above ### Communication modes The proposed communication modes are the result of years of testing and optimization and have been selected to be easily supported by limited microcontrollers. -| Mode | Data bit | Padding bit | Acceptable padding bit | Acceptable deviation | Bandwidth | Range | -| ---- |--------- | ----------- | ---------------------- | -------------------- | ------------------ | ----- | -| 1 | 44µs | 116µs | > 56µs | +- 1µs | 1.95kB/s - 15625Bd | 2000m | -| 2 | 40µs | 92µs | > 56µs | +- 1µs | 2.21kB/s - 17696Bd | 1600m | -| 3 | 28µs | 88µs | > 30µs | +- 0.75µs | 2.94kB/s - 23529Bd | 1200m | -| 4 | 26µs | 60µs | > 30µs | +- 0.35µs | 3.40kB/s - 27210Bd | 800m | +| Mode | Data bit | Padding bit | Acceptable padding bit | Deviation | Bandwidth | Range | +| ---- | -------- | ----------- | ---------------------- | --------- | ------------------ | ----- | +| 1 | 44µs | 116µs | 56µs - 116µs | +- 1.00µs | 1.95kB/s - 15625Bd | 2000m | +| 2 | 40µs | 92µs | 56µs - 92µs | +- 1.00µs | 2.21kB/s - 17696Bd | 1600m | +| 3 | 28µs | 88µs | 30µs - 88µs | +- 0.75µs | 2.94kB/s - 23529Bd | 1200m | +| 4 | 26µs | 60µs | 30µs - 60µs | +- 0.35µs | 3.40kB/s - 27210Bd | 800m | ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. From feea441e61cb09f80f4b24b1f8dc35f87ccc6e1c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jul 2020 03:37:54 +0200 Subject: [PATCH 129/323] PJDL mode table minor fix --- .../specification/PJDL-specification-v4.1.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index 0782ca82d6..97ba69b5a4 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -53,10 +53,10 @@ The proposed communication modes are the result of years of testing and optimiza | Mode | Data bit | Padding bit | Acceptable padding bit | Deviation | Bandwidth | Range | | ---- | -------- | ----------- | ---------------------- | --------- | ------------------ | ----- | -| 1 | 44µs | 116µs | 56µs - 116µs | +- 1.00µs | 1.95kB/s - 15625Bd | 2000m | -| 2 | 40µs | 92µs | 56µs - 92µs | +- 1.00µs | 2.21kB/s - 17696Bd | 1600m | -| 3 | 28µs | 88µs | 30µs - 88µs | +- 0.75µs | 2.94kB/s - 23529Bd | 1200m | -| 4 | 26µs | 60µs | 30µs - 60µs | +- 0.35µs | 3.40kB/s - 27210Bd | 800m | +| 1 | 44µs | 116µs | from 56 to 116µs | +- 1.00µs | 1.95kB/s - 15625Bd | 2000m | +| 2 | 40µs | 92µs | from 56 to 92µs | +- 1.00µs | 2.21kB/s - 17696Bd | 1600m | +| 3 | 28µs | 88µs | from 30 to 88µs | +- 0.75µs | 2.94kB/s - 23529Bd | 1200m | +| 4 | 26µs | 60µs | from 30 to 60µs | +- 0.35µs | 3.40kB/s - 27210Bd | 800m | ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. From 82fed4c205a1f3eb3b9d6b9eabb7f9afbb9d6e71 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jul 2020 16:57:01 +0200 Subject: [PATCH 130/323] PJDL spec removed impl details added bit deviation --- .../specification/PJDL-specification-v4.1.md | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index 97ba69b5a4..6de790e322 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -29,6 +29,7 @@ Released into the public domain 29/12/2018 3.0 - Medium access control info, mode 4 03/07/2019 4.0 - Response initializer 10/03/2020 4.1 - Maximum range experimentally determined +17/07/2020 4.2 - Deviation added thanks to J. Aguirre and G. Sittig ``` PJDL (Padded Jittering Data Link) is an asynchronous serial data link for low-data-rate applications that supports both master-slave and multi-master communication over a common conductive medium. PJDL can be easily implemented on limited microcontrollers with low clock accuracy and can operate directly using a single input-output pin. @@ -51,12 +52,12 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above ### Communication modes The proposed communication modes are the result of years of testing and optimization and have been selected to be easily supported by limited microcontrollers. -| Mode | Data bit | Padding bit | Acceptable padding bit | Deviation | Bandwidth | Range | -| ---- | -------- | ----------- | ---------------------- | --------- | ------------------ | ----- | -| 1 | 44µs | 116µs | from 56 to 116µs | +- 1.00µs | 1.95kB/s - 15625Bd | 2000m | -| 2 | 40µs | 92µs | from 56 to 92µs | +- 1.00µs | 2.21kB/s - 17696Bd | 1600m | -| 3 | 28µs | 88µs | from 30 to 88µs | +- 0.75µs | 2.94kB/s - 23529Bd | 1200m | -| 4 | 26µs | 60µs | from 30 to 60µs | +- 0.35µs | 3.40kB/s - 27210Bd | 800m | +| Mode | Data bit | Padding bit | Bit deviation | Bandwidth | Range | +| ---- | -------- | ----------- | ------------- | ------------------ | ----- | +| 1 | 44µs | 116µs | +- 1.22µs | 1.95kB/s - 15625Bd | 2000m | +| 2 | 40µs | 92µs | +- 1.11µs | 2.21kB/s - 17696Bd | 1600m | +| 3 | 28µs | 88µs | +- 0.77µs | 2.94kB/s - 23529Bd | 1200m | +| 4 | 26µs | 60µs | +- 0.72µs | 3.40kB/s - 27210Bd | 800m | ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. @@ -65,7 +66,7 @@ PJDL specifies a variation of the carrier-sense, non-persistent random multiple Byte transmission is composed by 10 bits, the first two are called synchronization pad and are used to obtain sampling synchronization. The synchronization pad is composed by a high padding bit longer than data bits and a low data bit. The following 8 data bits contain information in LSB-first (least significant bit first) order. The reception technique is based on 3 steps: -1. Find a high bit which duration is equal to or acceptably shorter than a high padding bit +1. Find a high bit which matches a padding bit 2. Synchronize to its falling edge 3. Ensure it is followed by a low data bit @@ -75,13 +76,11 @@ If so reception starts, if not, interference, synchronization loss or simply abs ___________ ___________________________ | SYNC-PAD | DATA | |_______ |___ ___ _____ | -| | | | | | | | | | -| | 1 | 0 | 1 | 0 0 | 1 | 0 | 1 1 | 0 | -|__|____|___|___|_____|___|___|_____|___| - | -Minimum acceptable padding bit duration +| | | | | | | | | +| 1 | 0 | 1 | 0 0 | 1 | 0 | 1 1 | 0 | +|_______|___|___|_____|___|___|_____|___| ``` -The synchronization pad adds overhead although it includes synchronization along with the data and eliminates the need of a dedicated clock line. The minimum acceptable padding bit duration is the time in which a receiver initiating polling can correctly receive a byte. If the duration of the padding bit is shorter than the minimum acceptable duration the received signal is discarded. The minimum acceptable duration of the padding bit must be shorter than a padding bit duration; a large minimum acceptable duration reduces the chances of false positive's occurrences, a small minimum acceptable duration instead mitigates timing inaccuracies. The presence of the synchronization pad between each byte also ensures that a frame composed of a series of bytes with decimal value 0 can be transmitted safely without risk of collision. +The synchronization pad adds overhead although it includes synchronization along with the data and eliminates the need of a dedicated clock line. The presence of the synchronization pad between each byte also ensures that a frame composed of a series of bytes with decimal value 0 can be transmitted safely without risk of collision. ### Frame transmission Before a frame transmission the communication medium's state is analysed, if high communication is detected and collision is avoided, if low for a duration of one byte plus a small random time, frame transmission starts with an initializer composed by 3 consecutive synchronization pads followed by data bytes. The synchronization pad is used for both byte and frame initialization to reduce the implementation complexity. @@ -95,11 +94,7 @@ Before a frame transmission the communication medium's state is analysed, if hig |00000000| 1 |0| 1 |0| 1 |0| 1 |0|0000|11|00| 1 |0|00000|1|0|1| |________|___|_|___|_|___|_|___|_|____|__|__|___|_|_____|_|_|_| ``` -When a frame is received a low performance microcontroller with an inaccurate clock can correctly synchronize with transmitter during the frame initializer and consequently each byte is received. On receiver's side a frame reception starts if 3 synchronization pads are detected and if their duration is equal or higher than: - -`frame initializer duration - (padding bit duration - padding bit minimum acceptable duration)` - -To ensure 100% reliability the padding bit must be longer than data bits. Frame initialization is 100% reliable, false positives can only occur because of externally induced interference. The padding bit duration must not be an exact multiple of the duration of one data bit, for this reason a `padding bit / data bit` ratio or pad-data ratio of 1, 2, 3 or 4 must be avoided because one or multiple consecutive data bits may be erroneously interpreted as a padding bit. +When a frame is received a low performance microcontroller with an inaccurate clock can correctly synchronize with transmitter during the frame initializer and consequently each byte is received. On receiver's side a frame reception starts if 3 synchronization pads are detected. Frame initialization is 100% reliable, false positives can only occur because of externally induced interference. The padding bit duration of all modes was selected not be an exact multiple of the duration of one data bit because in this particular case one or multiple consecutive data bits may be erroneously interpreted as a padding bit. ### Synchronous response A frame transmission can be optionally followed by a synchronous response sent by its recipient. Between frame transmission and a synchronous response there is a variable time which duration is influenced by latency. From 7624255478afa13821a150a85d1f3060dd7dbb78 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jul 2020 22:24:17 +0200 Subject: [PATCH 131/323] PJDL v5.0 draft spec and implementation (breaking compatibility) --- .../SoftwareBitBang/SoftwareBitBang.h | 15 +++--- src/strategies/SoftwareBitBang/Timing.h | 49 ++++++++++++------- .../specification/PJDL-specification-v4.1.md | 22 ++++----- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index 415b1dc506..9696660f24 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -145,12 +145,9 @@ class SoftwareBitBang { uint16_t receive_response() { if(_output_pin != _input_pin && _output_pin != SWBB_NOT_ASSIGNED) PJON_IO_WRITE(_output_pin, LOW); - uint16_t response = SWBB_FAIL; + uint16_t response; uint32_t time = PJON_MICROS(); - while( - response == SWBB_FAIL && - (uint32_t)(PJON_MICROS() - SWBB_RESPONSE_TIMEOUT) <= time - ) { + while((uint32_t)(PJON_MICROS() - time) < _timeout) { PJON_IO_WRITE(_input_pin, LOW); if(sync()) response = receive_byte(); if(response == SWBB_FAIL) { @@ -158,7 +155,7 @@ class SoftwareBitBang { PJON_IO_WRITE(_output_pin, HIGH); PJON_DELAY_MICROSECONDS(SWBB_BIT_WIDTH / 4); PJON_IO_PULL_DOWN(_output_pin); - } + } else return response; } return response; }; @@ -253,6 +250,7 @@ class SoftwareBitBang { Send a frame: */ void send_frame(uint8_t *data, uint16_t length) { + _timeout = (length * SWBB_RESPONSE_OFFSET) + SWBB_LATENCY; PJON_IO_MODE(_output_pin, OUTPUT); pulse(3); // Send frame initializer for(uint16_t b = 0; b < length; b++) @@ -333,6 +331,7 @@ class SoftwareBitBang { }; private: - uint8_t _input_pin; - uint8_t _output_pin; + uint16_t _timeout; + uint8_t _input_pin; + uint8_t _output_pin; }; diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 6ac9240573..b4814ffc75 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -2,12 +2,14 @@ /* PJON SoftwareBitBang strategy Transmission Timing table Copyright 2010-2020, Giovanni Blu Mitolo All rights reserved. - Often timing in two different architectures do not match. Code execution + Often timing in two different machines do not match, code execution time can variate and time measurements can be not perfectly equal. - Arduino Duemilanove/UNO/Nano durations are used as master. - Consider that master durations defined below are shorter than specified - in the PJDL-specification-v2.1 to accomodate the input-output pin change - duration (4 microseconds) and effectively produce the specified durations. + Consider that durations defined below may differ from what is specified in + PJDL v4.1. This is done to accomodate machine's inner workings and + effectively produce the specified timing. + + Arduino Duemilanove/UNO/Nano is used as timing master, or the machine used + to test all new supported MCUs. Benchmarks can be executed using NetworkAnalysis and SpeedTest examples. @@ -47,9 +49,9 @@ #if F_CPU == 16000000L /* Working on pin: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, A0, A1 */ #define SWBB_BIT_WIDTH 24 - #define SWBB_BIT_SPACER 84 - #define SWBB_ACCEPTANCE 30 - #define SWBB_READ_DELAY 8 + #define SWBB_BIT_SPACER 84 + #define SWBB_ACCEPTANCE 30 + #define SWBB_READ_DELAY 8 #endif #endif #if SWBB_MODE == 4 @@ -58,7 +60,7 @@ #define SWBB_BIT_WIDTH 22 #define SWBB_BIT_SPACER 56 #define SWBB_ACCEPTANCE 30 - #define SWBB_READ_DELAY 9 + #define SWBB_READ_DELAY 7 #endif #endif #endif @@ -213,8 +215,9 @@ #endif /* STM32F1 ---------------------------------------------------------------- */ -/* Mod by @jcallano on 09-jul-2020 see dumps and pics folder for info*/ -// tested on PB15, PB14, PB13, PB12, PB11, PB10, PB9, PB8, PB7, PB6, PB4, PB3, PA15, PA10. 5v tolerant pins on bluepill. +/* Added by jcallano - 09-07-2020 + Working on pin: PB15, PB14, PB13, PB12, PB11, PB10, PB9, PB8, PB7, PB6, PB4, + PB3, PA15, PA10. 5v tolerant pins on bluepill */ #if defined(__STM32F1__) #if SWBB_MODE == 1 #if F_CPU == 72000000L @@ -264,6 +267,9 @@ #ifndef SWBB_READ_DELAY #define SWBB_READ_DELAY 4 #endif + #ifndef SWBB_LATENCY + #define SWBB_LATENCY 13 + #endif #endif #if SWBB_MODE == 2 #ifndef SWBB_BIT_WIDTH @@ -278,6 +284,9 @@ #ifndef SWBB_READ_DELAY #define SWBB_READ_DELAY 4 #endif + #ifndef SWBB_LATENCY + #define SWBB_LATENCY 10 + #endif #endif #if SWBB_MODE == 3 #ifndef SWBB_BIT_WIDTH @@ -292,6 +301,9 @@ #ifndef SWBB_READ_DELAY #define SWBB_READ_DELAY 8 #endif + #ifndef SWBB_LATENCY + #define SWBB_LATENCY 8 + #endif #endif #if SWBB_MODE == 4 #ifndef SWBB_BIT_WIDTH @@ -306,15 +318,18 @@ #ifndef SWBB_READ_DELAY #define SWBB_READ_DELAY 9 #endif + #ifndef SWBB_LATENCY + #define SWBB_LATENCY 5 + #endif #endif -/* Synchronous acknowledgement response timeout. (1.5 milliseconds default). - If (latency + CRC computation) > SWBB_RESPONSE_TIMEOUT synchronous - acknowledgement reliability could be affected or disrupted higher - SWBB_RESPONSE_TIMEOUT if necessary. */ +/* Synchronous acknowledgement response offset. + If (latency + CRC computation) > (SWBB_RESPONSE_OFFSET * length) + synchronous acknowledgement reliability could be affected or disrupted + set a higher SWBB_RESPONSE_OFFSET if necessary. */ -#ifndef SWBB_RESPONSE_TIMEOUT - #define SWBB_RESPONSE_TIMEOUT 1500 +#ifndef SWBB_RESPONSE_OFFSET + #define SWBB_RESPONSE_OFFSET 20 #endif /* Maximum initial delay in milliseconds: */ diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index 6de790e322..3cd777f0d2 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -13,13 +13,13 @@ --- -## PJDL v4.1 +## PJDL v5.0 ``` Invented by Giovanni Blu Mitolo Originally published: 10/04/2010 Latest revision: 10/03/2020 Related implementation: /src/strategies/SoftwareBitBang/ -Compliant versions: PJON v12.0 and following +Compliant versions: PJON v13.0 and following Released into the public domain 10/04/2010 0.1 - First experimental release @@ -28,8 +28,8 @@ Released into the public domain 24/09/2017 2.0 - Modes 1, 2, 3 29/12/2018 3.0 - Medium access control info, mode 4 03/07/2019 4.0 - Response initializer -10/03/2020 4.1 - Maximum range experimentally determined -17/07/2020 4.2 - Deviation added thanks to J. Aguirre and G. Sittig +10/03/2020 4.1 - Maximum range determined by Jack Anderson +17/07/2020 5.0 - Timeout by Julio Aguirre deviation by Gerhard Sittig ``` PJDL (Padded Jittering Data Link) is an asynchronous serial data link for low-data-rate applications that supports both master-slave and multi-master communication over a common conductive medium. PJDL can be easily implemented on limited microcontrollers with low clock accuracy and can operate directly using a single input-output pin. @@ -52,12 +52,12 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above ### Communication modes The proposed communication modes are the result of years of testing and optimization and have been selected to be easily supported by limited microcontrollers. -| Mode | Data bit | Padding bit | Bit deviation | Bandwidth | Range | -| ---- | -------- | ----------- | ------------- | ------------------ | ----- | -| 1 | 44µs | 116µs | +- 1.22µs | 1.95kB/s - 15625Bd | 2000m | -| 2 | 40µs | 92µs | +- 1.11µs | 2.21kB/s - 17696Bd | 1600m | -| 3 | 28µs | 88µs | +- 0.77µs | 2.94kB/s - 23529Bd | 1200m | -| 4 | 26µs | 60µs | +- 0.72µs | 3.40kB/s - 27210Bd | 800m | +| Mode | Data bit | Padding bit | Bit deviation | Timeout | Latency | Bandwidth | Range | +| ---- | -------- | ----------- | ------------- | --------- | ------- | ------------------ | ----- | +| 1 | 44µs | 116µs | +- 1.22µs | 20µs/byte | 13µs | 1.95kB/s - 15625Bd | 2000m | +| 2 | 40µs | 92µs | +- 1.11µs | 20µs/byte | 10µs | 2.21kB/s - 17696Bd | 1600m | +| 3 | 28µs | 88µs | +- 0.77µs | 20µs/byte | 8µs | 2.94kB/s - 23529Bd | 1200m | +| 4 | 26µs | 60µs | +- 0.72µs | 20µs/byte | 5µs | 3.40kB/s - 27210Bd | 800m | ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. @@ -115,4 +115,4 @@ Transmission end Response | || || | | | | | | | | | | | | | | 6 | |______||______||______|_| |_| |_| |_| |_| |_| |____|_____| ``` -The maximum time dedicated to potential response reception for a given application can be determined practically transmitting the longest supported frame with the farthest physical distance between the two devices. The highest interval between packet transmission and response measured plus a small margin is the correct timeout that should exclude response losses. Consider that the longer this timeout is, the more bandwidth is wasted if the transmission is not successful. +The maximum time dedicated to potential response reception is determined by the transmitter computing the timeout using the frame length and then adding the maximum expected latency. From 8016b0b7db85914435abb83c30f21841f3c3e66b Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 19 Jul 2020 03:01:29 +0200 Subject: [PATCH 132/323] PJDL longer keep-busy bits (breaking compatibility) --- .../SoftwareBitBang/SoftwareBitBang.h | 4 ++-- .../specification/PJDL-specification-v4.1.md | 24 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index 9696660f24..36a4715c0d 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -153,7 +153,7 @@ class SoftwareBitBang { if(response == SWBB_FAIL) { PJON_IO_MODE(_output_pin, OUTPUT); PJON_IO_WRITE(_output_pin, HIGH); - PJON_DELAY_MICROSECONDS(SWBB_BIT_WIDTH / 4); + PJON_DELAY_MICROSECONDS(SWBB_BIT_WIDTH / 2); PJON_IO_PULL_DOWN(_output_pin); } else return response; } @@ -226,7 +226,7 @@ class SoftwareBitBang { ); time = PJON_MICROS(); while( // If high Wait for low - ((uint32_t)(PJON_MICROS() - time) < (SWBB_BIT_WIDTH / 4)) && + ((uint32_t)(PJON_MICROS() - time) < (SWBB_BIT_WIDTH / 2)) && PJON_IO_READ(_input_pin) ); PJON_IO_MODE(_output_pin, OUTPUT); diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index 3cd777f0d2..446d32bc1d 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -17,7 +17,7 @@ ``` Invented by Giovanni Blu Mitolo Originally published: 10/04/2010 -Latest revision: 10/03/2020 +Latest revision: 19/07/2020 Related implementation: /src/strategies/SoftwareBitBang/ Compliant versions: PJON v13.0 and following Released into the public domain @@ -28,8 +28,8 @@ Released into the public domain 24/09/2017 2.0 - Modes 1, 2, 3 29/12/2018 3.0 - Medium access control info, mode 4 03/07/2019 4.0 - Response initializer -10/03/2020 4.1 - Maximum range determined by Jack Anderson -17/07/2020 5.0 - Timeout by Julio Aguirre deviation by Gerhard Sittig +10/03/2020 4.1 - Maximum range experimentally determined +17/07/2020 5.0 - Timeout and keep-busy signal fixed, deviation added ``` PJDL (Padded Jittering Data Link) is an asynchronous serial data link for low-data-rate applications that supports both master-slave and multi-master communication over a common conductive medium. PJDL can be easily implemented on limited microcontrollers with low clock accuracy and can operate directly using a single input-output pin. @@ -52,12 +52,12 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above ### Communication modes The proposed communication modes are the result of years of testing and optimization and have been selected to be easily supported by limited microcontrollers. -| Mode | Data bit | Padding bit | Bit deviation | Timeout | Latency | Bandwidth | Range | -| ---- | -------- | ----------- | ------------- | --------- | ------- | ------------------ | ----- | -| 1 | 44µs | 116µs | +- 1.22µs | 20µs/byte | 13µs | 1.95kB/s - 15625Bd | 2000m | -| 2 | 40µs | 92µs | +- 1.11µs | 20µs/byte | 10µs | 2.21kB/s - 17696Bd | 1600m | -| 3 | 28µs | 88µs | +- 0.77µs | 20µs/byte | 8µs | 2.94kB/s - 23529Bd | 1200m | -| 4 | 26µs | 60µs | +- 0.72µs | 20µs/byte | 5µs | 3.40kB/s - 27210Bd | 800m | +| Mode | Data bit | Padding bit | Max bit deviation | Timeout | Max latency | Bandwidth | Range | +| ---- | -------- | ----------- | ----------------- | --------- | ----------- | ------------------ | ----- | +| 1 | 44µs | 116µs | +- 1.22µs | 20µs/byte | 13µs | 1.95kB/s - 15625Bd | 2000m | +| 2 | 40µs | 92µs | +- 1.11µs | 20µs/byte | 10µs | 2.21kB/s - 17696Bd | 1600m | +| 3 | 28µs | 88µs | +- 0.77µs | 20µs/byte | 8µs | 2.94kB/s - 23529Bd | 1200m | +| 4 | 26µs | 60µs | +- 0.72µs | 20µs/byte | 5µs | 3.40kB/s - 27210Bd | 800m | ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. @@ -106,13 +106,13 @@ Transmission end Response | || || | | 6 | |______||______||______| |_____| ``` -In order to avoid other devices to detect the medium free for use and disrupt an ongoing exchange, the sender cyclically transmits a short high bit (1/4 data bit duration) and consequently attempts to receive a response. The receiver must synchronize its response to the falling edge of the last short high bit, and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If the response is not transmitted or not received the transmitter continues to keep busy the medium up to the maximum acceptable time between transmission and response. +In order to avoid other devices to detect the medium free for use and disrupt an ongoing exchange, the sender cyclically transmits a high 1/2 data bit and consequently attempts to receive a response. The receiver must synchronize to the falling edge of the last high bit and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If the response is not transmitted or not received the transmitter continues to keep busy the medium up to the response timeout. ```cpp -Transmission end Response +Transmission end Keep busy Response ______ ______ ______ _ _ _ _ _ _ ____ _____ | BYTE || BYTE || BYTE | | | | | | | | | | | | |SYNC| ACK | |------||------||------| | | | | | | | | | | | |----|-----| | || || | | | | | | | | | | | | | | 6 | |______||______||______|_| |_| |_| |_| |_| |_| |____|_____| ``` -The maximum time dedicated to potential response reception is determined by the transmitter computing the timeout using the frame length and then adding the maximum expected latency. +The response timeout is determined multiplying 20µs by the length of the frame and then adding the maximum expected latency. From 3f11b87a4db3f61bc15399b2bfd5ea4df5127926 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 19 Jul 2020 03:22:01 +0200 Subject: [PATCH 133/323] PJDL spec contributors added to manifest --- .../specification/PJDL-specification-v4.1.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index 446d32bc1d..cd854a570c 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -15,9 +15,9 @@ ## PJDL v5.0 ``` -Invented by Giovanni Blu Mitolo -Originally published: 10/04/2010 -Latest revision: 19/07/2020 +Invented by Giovanni Blu Mitolo with the support +of Fred Larsen, Julio Aguirre and Gerhard Sittig +Publication date: 10/04/2010 Latest revision: 19/07/2020 Related implementation: /src/strategies/SoftwareBitBang/ Compliant versions: PJON v13.0 and following Released into the public domain @@ -108,7 +108,7 @@ Transmission end Response ``` In order to avoid other devices to detect the medium free for use and disrupt an ongoing exchange, the sender cyclically transmits a high 1/2 data bit and consequently attempts to receive a response. The receiver must synchronize to the falling edge of the last high bit and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If the response is not transmitted or not received the transmitter continues to keep busy the medium up to the response timeout. ```cpp -Transmission end Keep busy Response +Transmission end Keep busy Response ______ ______ ______ _ _ _ _ _ _ ____ _____ | BYTE || BYTE || BYTE | | | | | | | | | | | | |SYNC| ACK | |------||------||------| | | | | | | | | | | | |----|-----| From 57d43d63027c0f17fea7f1443649706cfd2b2ee5 Mon Sep 17 00:00:00 2001 From: fredilarsen Date: Sun, 19 Jul 2020 22:04:09 +0200 Subject: [PATCH 134/323] Including Any.h in PJONSwitch.h Otherwise strategies/Any/Any.h would have to be included in user sketches using routing classes. --- src/PJONSwitch.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PJONSwitch.h b/src/PJONSwitch.h index 3e36f61c84..d098843dee 100644 --- a/src/PJONSwitch.h +++ b/src/PJONSwitch.h @@ -39,6 +39,7 @@ limitations under the License. */ #pragma once #include "PJONSimpleSwitch.h" +#include "strategies/Any/Any.h" class PJONAny : public PJON { public: From fe4c1bde4b2637b475d0cbf98f5f9d5fe13f7af2 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jul 2020 15:31:57 +0200 Subject: [PATCH 135/323] PJDL specification mode pad-data ratio fixed to be 2.5 (breaking compatibility) --- .../specification/PJDL-specification-v4.1.md | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index cd854a570c..5344bbb632 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -19,7 +19,7 @@ Invented by Giovanni Blu Mitolo with the support of Fred Larsen, Julio Aguirre and Gerhard Sittig Publication date: 10/04/2010 Latest revision: 19/07/2020 Related implementation: /src/strategies/SoftwareBitBang/ -Compliant versions: PJON v13.0 and following +Compatible versions: PJON v13.0 and following Released into the public domain 10/04/2010 0.1 - First experimental release @@ -50,14 +50,22 @@ ___|__________|________|___________|______/\/\/\__| IO PIN It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above to reduce externally induced interference. The longer is the length of the cable and the higher is the amount of induced interference, the lower should be the resistance of the pull-down resistor. Pins can be optionally protected against overload adding a current limiting resistor to each connected pin. The resistor value can be obtained solving the following equation `R = (operating voltage / pin max current drain)`, for example to obtain the current limiting resistor value for an Arduino Uno simply substitute its characteristics: `R = (5v / 0.030A) = 166.66Ω`. ### Communication modes -The proposed communication modes are the result of years of testing and optimization and have been selected to be easily supported by limited microcontrollers. - -| Mode | Data bit | Padding bit | Max bit deviation | Timeout | Max latency | Bandwidth | Range | -| ---- | -------- | ----------- | ----------------- | --------- | ----------- | ------------------ | ----- | -| 1 | 44µs | 116µs | +- 1.22µs | 20µs/byte | 13µs | 1.95kB/s - 15625Bd | 2000m | -| 2 | 40µs | 92µs | +- 1.11µs | 20µs/byte | 10µs | 2.21kB/s - 17696Bd | 1600m | -| 3 | 28µs | 88µs | +- 0.77µs | 20µs/byte | 8µs | 2.94kB/s - 23529Bd | 1200m | -| 4 | 26µs | 60µs | +- 0.72µs | 20µs/byte | 5µs | 3.40kB/s - 27210Bd | 800m | +The proposed communication modes are the result of years of testing and optimization and have been selected to be easily supported by limited microcontrollers: + +| Mode | Bandwidth | Range | Pad bit | Data bit | Keep busy bit | Latency | Timeout | +| ---- | ------------------ | ----- | ------- | -------- | ------------- | ------- | ------- | +| 1 | 1.97kB/s - 15808Bd | 2000m | 110µs | 44µs | 22µs | 13µs | 20µs/B | +| 2 | 2.21kB/s - 17696Bd | 1600m | 92µs | 40µs | 20µs | 10µs | 20µs/B | +| 3 | 3.10kB/s - 24844Bd | 1200m | 70µs | 28µs | 14µs | 8µs | 20µs/B | +| 4 | 3.34kB/s - 26755Bd | 800m | 65µs | 26µs | 13µs | 5µs | 20µs/B | + +The following table specifies the maximum acceptable deviation of each bit type: + +| Max data bit octet deviation | Max padding bit deviation | Keep busy bit deviation | +| ---------------------------- | ------------------------- | ----------------------- | +| +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | +- (data bit / 8) - 1 | + +When the ratio between padding bit and data bit is 2.5 there is no ambiguity even with an overall deviation of up to half a bit. ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. From 5a376ff7e0ba6c5df79c40a4bb7699b0bc8308b0 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jul 2020 17:12:37 +0200 Subject: [PATCH 136/323] PJDL spec minor fix --- .../specification/PJDL-specification-v4.1.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index 5344bbb632..b474a7edc8 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -61,24 +61,22 @@ The proposed communication modes are the result of years of testing and optimiza The following table specifies the maximum acceptable deviation of each bit type: -| Max data bit octet deviation | Max padding bit deviation | Keep busy bit deviation | -| ---------------------------- | ------------------------- | ----------------------- | -| +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | +- (data bit / 8) - 1 | - -When the ratio between padding bit and data bit is 2.5 there is no ambiguity even with an overall deviation of up to half a bit. +| Max data bit octet deviation | Max padding bit deviation | Max keep busy bit deviation | +| ---------------------------- | ------------------------- | --------------------------- | +| +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | +- 12.5% | ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. ### Byte transmission -Byte transmission is composed by 10 bits, the first two are called synchronization pad and are used to obtain sampling synchronization. The synchronization pad is composed by a high padding bit longer than data bits and a low data bit. The following 8 data bits contain information in LSB-first (least significant bit first) order. +Byte transmission is composed by 10 bits, the first two are called synchronization pad and are used to obtain sampling synchronization. The synchronization pad is composed by a high padding bit 2.5 times longer than data bits and a low data bit. The following 8 data bits contain information in LSB-first (least significant bit first) order. The reception technique is based on 3 steps: 1. Find a high bit which matches a padding bit 2. Synchronize to its falling edge 3. Ensure it is followed by a low data bit -If so reception starts, if not, interference, synchronization loss or simply absence of communication is detected. +If so reception starts, if not, interference, synchronization loss or simply absence of communication is detected. The high padding bit is 2.5 times longer than data bits because with this ratio ambiguity between padding bits and 2 or 3 consecutive data bits is avoided even with an overall deviation of up to +- (data bit / 4) - 1. ```cpp ___________ ___________________________ From ccab7a9d7513ce2e94a2012764779fcd610124c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jul 2020 01:41:46 +0200 Subject: [PATCH 137/323] PJDL specification response latency remark --- .../SoftwareBitBang/specification/PJDL-specification-v4.1.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md index b474a7edc8..a0cfe22df7 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md @@ -63,7 +63,7 @@ The following table specifies the maximum acceptable deviation of each bit type: | Max data bit octet deviation | Max padding bit deviation | Max keep busy bit deviation | | ---------------------------- | ------------------------- | --------------------------- | -| +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | +- 12.5% | +| +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | +- 10µs | ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. @@ -112,7 +112,7 @@ Transmission end Response | || || | | 6 | |______||______||______| |_____| ``` -In order to avoid other devices to detect the medium free for use and disrupt an ongoing exchange, the sender cyclically transmits a high 1/2 data bit and consequently attempts to receive a response. The receiver must synchronize to the falling edge of the last high bit and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If the response is not transmitted or not received the transmitter continues to keep busy the medium up to the response timeout. +In order to avoid other devices to detect the medium free for use and disrupt an ongoing exchange, the sender cyclically transmits a high 1/2 data bit and consequently attempts to receive a response for up to twice the maximum expected latency. The receiver must synchronize to the falling edge of the last high bit and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If the response is not transmitted or not received the transmitter continues to keep busy the medium up to the response timeout. ```cpp Transmission end Keep busy Response ______ ______ ______ _ _ _ _ _ _ ____ _____ From 731ffa231072c8e4b6ad8a8a8c801ed7911895b4 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jul 2020 01:55:51 +0200 Subject: [PATCH 138/323] PJDL specification v5.0 is out (breaking compatibility) --- ...ion-v4.1.md => PJDL-specification-v5.0.md} | 2 +- .../obsolete/PJDL-specification-v4.1.md | 126 ++++++++++++++++++ 2 files changed, 127 insertions(+), 1 deletion(-) rename src/strategies/SoftwareBitBang/specification/{PJDL-specification-v4.1.md => PJDL-specification-v5.0.md} (99%) create mode 100644 src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v4.1.md diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md similarity index 99% rename from src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md rename to src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index a0cfe22df7..b86fab3f02 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -17,7 +17,7 @@ ``` Invented by Giovanni Blu Mitolo with the support of Fred Larsen, Julio Aguirre and Gerhard Sittig -Publication date: 10/04/2010 Latest revision: 19/07/2020 +Publication date: 10/04/2010 Latest revision: 21/07/2020 Related implementation: /src/strategies/SoftwareBitBang/ Compatible versions: PJON v13.0 and following Released into the public domain diff --git a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v4.1.md b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v4.1.md new file mode 100644 index 0000000000..bf96684e95 --- /dev/null +++ b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v4.1.md @@ -0,0 +1,126 @@ + +### Specifications index + +#### Network layer +- [PJON (Padded Jittering Operative Network) v3.2](/specification/PJON-protocol-specification-v3.2.md) +- [Acknowledge specification v1.0](/specification/PJON-protocol-acknowledge-specification-v1.0.md) +- [Network services list](/specification/PJON-network-services-list.md) +#### Data link layer +- **[PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md)** +- [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) +- [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) +- [TSDL (Tardy Serial Data Link) v2.1](/src/strategies/ThroughSerial/specification/TSDL-specification-v2.1.md) +- [SFSP (Secure Frame Separation Protocol) v1.0](/specification/SFSP-frame-separation-specification-v1.0.md) + +--- + +## PJDL v4.1 +``` +Invented by Giovanni Blu Mitolo +Originally published: 10/04/2010 +Latest revision: 10/03/2020 +Related implementation: /src/strategies/SoftwareBitBang/ +Compliant versions: PJON v12.0 and following +Released into the public domain + +10/04/2010 0.1 - First experimental release +12/02/2017 1.0 - Frame initializer, response made safe +31/03/2017 1.1 - Physical layer info +24/09/2017 2.0 - Modes 1, 2, 3 +29/12/2018 3.0 - Medium access control info, mode 4 +03/07/2019 4.0 - Response initializer +10/03/2020 4.1 - Maximum range experimentally determined +``` +PJDL (Padded Jittering Data Link) is an asynchronous serial data link for low-data-rate applications that supports both master-slave and multi-master communication over a common conductive medium. PJDL can be easily implemented on limited microcontrollers with low clock accuracy and can operate directly using a single input-output pin. + +### Physical layer +The medium's maximum length is limited by the wiring resistance, by the voltage level used and by externally induced interference. The maximum length of the bus can reach between 800 and 2000 meters depending on the mode used. +```cpp +PJDL SINGLE WIRE BUS ______ + ______ ______ ______ ______ | | +| | | | | | | | |DEVICE| +|DEVICE| |DEVICE| |DEVICE| |DEVICE| |______| +|______| |______| |______| |______| | +___|__________|________|___________|______/\/\/\__| IO PIN + ___|__ __|___ ___|__ ___|__ | 110-180 Ω +| | | | | | | | | +|DEVICE| |DEVICE| |DEVICE| |DEVICE| |__/\/\/\__ GND +|______| |______| |______| |______| 8 kΩ - 5 MΩ +``` +It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above to reduce externally induced interference. The longer is the length of the cable and the higher is the amount of induced interference, the lower should be the resistance of the pull-down resistor. Pins can be optionally protected against overload adding a current limiting resistor to each connected pin. The resistor value can be obtained solving the following equation `R = (operating voltage / pin max current drain)`, for example to obtain the current limiting resistor value for an Arduino Uno simply substitute its characteristics: `R = (5v / 0.030A) = 166.66Ω`. + +### Communication modes +The proposed communication modes are the result of years of testing and optimization and have been selected to be easily supported by limited microcontrollers. + +| MODE | Data bit duration | Padding bit duration | Pad-data ratio | Bandwidth | Range | +| ---- | ----------------- | -------------------- | --------------- | ------------------ | ----- | +| 1 | 44 | 116 | 2.636 | 1.95kB/s - 15625Bd | 2000m | +| 2 | 40 | 92 | 2.300 | 2.21kB/s - 17696Bd | 1600m | +| 3 | 28 | 88 | 3.142 | 2.94kB/s - 23529Bd | 1200m | +| 4 | 26 | 60 | 2.307 | 3.40kB/s - 27210Bd | 800m | + +Durations are expressed in microseconds. + +### Medium access control +PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. + +### Byte transmission +Byte transmission is composed by 10 bits, the first two are called synchronization pad and are used to obtain sampling synchronization. The synchronization pad is composed by a high padding bit longer than data bits and a low data bit. The following 8 data bits contain information in LSB-first (least significant bit first) order. + +The reception technique is based on 3 steps: +1. Find a high bit which duration is equal to or acceptably shorter than a high padding bit +2. Synchronize to its falling edge +3. Ensure it is followed by a low data bit + +If so reception starts, if not, interference, synchronization loss or simply absence of communication is detected. + +```cpp + ___________ ___________________________ +| SYNC-PAD | DATA | +|_______ |___ ___ _____ | +| | | | | | | | | | +| | 1 | 0 | 1 | 0 0 | 1 | 0 | 1 1 | 0 | +|__|____|___|___|_____|___|___|_____|___| + | +Minimum acceptable padding bit duration +``` +The synchronization pad adds overhead although it includes synchronization along with the data and eliminates the need of a dedicated clock line. The minimum acceptable padding bit duration is the time in which a receiver initiating polling can correctly receive a byte. If the duration of the padding bit is shorter than the minimum acceptable duration the received signal is discarded. The minimum acceptable duration of the padding bit must be shorter than a padding bit duration; a large minimum acceptable duration reduces the chances of false positive's occurrences, a small minimum acceptable duration instead mitigates timing inaccuracies. The presence of the synchronization pad between each byte also ensures that a frame composed of a series of bytes with decimal value 0 can be transmitted safely without risk of collision. + +### Frame transmission +Before a frame transmission the communication medium's state is analysed, if high communication is detected and collision is avoided, if low for a duration of one byte plus a small random time, frame transmission starts with an initializer composed by 3 consecutive synchronization pads followed by data bytes. The synchronization pad is used for both byte and frame initialization to reduce the implementation complexity. +```cpp + ________ _________________ __________________________________ +|ANALYSIS| FRAME INIT | DATA 1-65535 bytes | +|________|_____ _____ _____|________________ _________________| +| |Sync |Sync |Sync |Sync | Byte |Sync | Byte | +| |___ |___ |___ |___ | __ |___ | _ _| +| | | | | | | | | | | | | | | | | | | +|00000000| 1 |0| 1 |0| 1 |0| 1 |0|0000|11|00| 1 |0|00000|1|0|1| +|________|___|_|___|_|___|_|___|_|____|__|__|___|_|_____|_|_|_| +``` +When a frame is received a low performance microcontroller with an inaccurate clock can correctly synchronize with transmitter during the frame initializer and consequently each byte is received. On receiver's side a frame reception starts if 3 synchronization pads are detected and if their duration is equal or higher than: + +`frame initializer duration - (padding bit duration - padding bit minimum acceptable duration)` + +To ensure 100% reliability the padding bit must be longer than data bits. Frame initialization is 100% reliable, false positives can only occur because of externally induced interference. The padding bit duration must not be an exact multiple of the duration of one data bit, for this reason a `padding bit / data bit` ratio or pad-data ratio of 1, 2, 3 or 4 must be avoided because one or multiple consecutive data bits may be erroneously interpreted as a padding bit. + +### Synchronous response +A frame transmission can be optionally followed by a synchronous response sent by its recipient. Between frame transmission and a synchronous response there is a variable time which duration is influenced by latency. +```cpp +Transmission end Response + ______ ______ ______ _____ +| BYTE || BYTE || BYTE | CRC COMPUTATION / LATENCY | ACK | +|------||------||------|---------------------------|-----| +| || || | | 6 | +|______||______||______| |_____| +``` +In order to avoid other devices to detect the medium free for use and disrupt an ongoing exchange, the sender cyclically transmits a short high bit (1/4 data bit duration) and consequently attempts to receive a response. The receiver must synchronize its response to the falling edge of the last short high bit, and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pulse. If the response is not transmitted or not received the transmitter continues to keep busy the medium up to the maximum acceptable time between transmission and response. +```cpp +Transmission end Response + ______ ______ ______ _ _ _ _ _ _ ____ _____ +| BYTE || BYTE || BYTE | | | | | | | | | | | | |SYNC| ACK | +|------||------||------| | | | | | | | | | | | |----|-----| +| || || | | | | | | | | | | | | | | 6 | +|______||______||______|_| |_| |_| |_| |_| |_| |____|_____| +``` +The maximum time dedicated to potential response reception for a given application can be determined practically transmitting the longest supported frame with the farthest physical distance between the two devices. The highest interval between packet transmission and response measured plus a small margin is the correct timeout that should exclude response losses. Consider that the longer this timeout is, the more bandwidth is wasted if the transmission is not successful. From 30cb6ef8ad555ac6f6102b4fafab8079116100d3 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jul 2020 02:04:49 +0200 Subject: [PATCH 139/323] PJDL specification removed outdated remark --- .../SoftwareBitBang/specification/PJDL-specification-v5.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index b86fab3f02..201490ee96 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -100,7 +100,7 @@ Before a frame transmission the communication medium's state is analysed, if hig |00000000| 1 |0| 1 |0| 1 |0| 1 |0|0000|11|00| 1 |0|00000|1|0|1| |________|___|_|___|_|___|_|___|_|____|__|__|___|_|_____|_|_|_| ``` -When a frame is received a low performance microcontroller with an inaccurate clock can correctly synchronize with transmitter during the frame initializer and consequently each byte is received. On receiver's side a frame reception starts if 3 synchronization pads are detected. Frame initialization is 100% reliable, false positives can only occur because of externally induced interference. The padding bit duration of all modes was selected not be an exact multiple of the duration of one data bit because in this particular case one or multiple consecutive data bits may be erroneously interpreted as a padding bit. +When a frame is received a low performance microcontroller with an inaccurate clock can correctly synchronize with transmitter during the frame initializer and consequently each byte is received. On receiver's side a frame reception starts if 3 synchronization pads are detected. Frame initialization is 100% reliable, false positives can only occur because of externally induced interference. ### Synchronous response A frame transmission can be optionally followed by a synchronous response sent by its recipient. Between frame transmission and a synchronous response there is a variable time which duration is influenced by latency. From 019a31f309d5399a4147644630f0033801844bfb Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jul 2020 02:11:50 +0200 Subject: [PATCH 140/323] PJDL v5.0 specification update docs and READMEs --- README.md | 4 ++-- documentation/configuration.md | 2 +- specification/PJON-network-services-list.md | 2 +- specification/PJON-protocol-specification-v4.0.md | 2 +- .../AnalogSampling/specification/PJDLS-specification-v2.0.md | 2 +- .../OverSampling/specification/PJDLR-specification-v3.0.md | 2 +- src/strategies/README.md | 2 +- src/strategies/SoftwareBitBang/README.md | 4 ++-- src/strategies/SoftwareBitBang/Timing.h | 2 +- .../SoftwareBitBang/specification/PJDL-specification-v5.0.md | 2 +- .../ThroughSerial/specification/TSDL-specification-v3.0.md | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 3db796ee1b..666738b44b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ PJON® (Padded Jittering Operative Network) is an arduino-compatible, multi-mast PJON is used in thousands of devices and its community has spread worldwide because of the following 5 key factors: - **New technology**: [PJON](specification/PJON-protocol-specification-v4.0.md) is an experimental network protocol stack crafted in 10 years of research and experimentation. It was originally developed as an open-source alternative to i2c and 1-Wire but during development its scope and features have been extended to cover use cases where IP is generally applied. PJON has been engineered to have a variable footprint (4.2-8.2 kB program memory) and overhead (5-35 bytes per packet) depending on its configuration. -- **Multi-media support**: PJON operates upon a wide range of protocols like TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485 and LoRa. The PJON network protocol stack specifies and implements also [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) that operates over a single wire of up to 2000m shared by up to 255 devices, [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) that operates with many ASK/FSK/OOK radio modules, and also [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) that operates wirelessly with light pulses using off-the-shelf LEDs and laser diodes. +- **Multi-media support**: PJON operates upon a wide range of protocols like TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485 and LoRa. The PJON network protocol stack specifies and implements also [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) that operates over a single wire of up to 2000m shared by up to 255 devices, [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) that operates with many ASK/FSK/OOK radio modules, and also [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) that operates wirelessly with light pulses using off-the-shelf LEDs and laser diodes. - **Increased reliability**: Many protocols massively applied worldwide expose dangerous vulnerabilities, have weak error detection algorithms and are not resilient to interference. PJON is based on years of analysis and study not to make the same mistakes present in most alternatives and provide with a simpler and more efficient solution. - **High flexibility**: PJON is totally software-defined and it is designed to be easily extensible. it builds out-of-the-box in all supported devices and operates transparently on top of any supported protocol or medium. - **Low cost**: Without any additional hardware needed to operate, minimal network wiring requirements and direct pin-to-pin or LED-to-LED communication, PJON is extremely energy efficient, cheap to be implemented and maintained. This implementation is kept updated and meticulously tested thanks to the strong commitment of its growing community of end users, testers and developers. @@ -26,7 +26,7 @@ PJON is used in thousands of devices and its community has spread worldwide beca ### Specifications - [PJON v4.0](specification/PJON-protocol-specification-v4.0.md) -- [PJDL v4.1](src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) +- [PJDL v5.0](src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) - [PJDLR v3.0](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS v2.0](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) - [TSDL v3.0](src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) diff --git a/documentation/configuration.md b/documentation/configuration.md index da0fd3e560..d8e6e454a8 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -59,7 +59,7 @@ The table below lists the strategies available: | [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | | [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | `#include ` | | [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | `#include ` | -| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | `#include ` | +| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) | `#include ` | | [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | `#include ` | | [ThroughSerial](/src/strategies/ThroughSerial) | Wire | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | `#include ` | diff --git a/specification/PJON-network-services-list.md b/specification/PJON-network-services-list.md index cc13b5c754..e1e09b4174 100644 --- a/specification/PJON-network-services-list.md +++ b/specification/PJON-network-services-list.md @@ -4,7 +4,7 @@ - [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - **[Network services list](/specification/PJON-network-services-list.md)** #### Data link layer -- [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) +- [PJDL (Padded Jittering Data Link) v5.0](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) - [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) - [TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index 5bd8dc50cd..6d50586e9e 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -4,7 +4,7 @@ - **[PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md)** - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer -- [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) +- [PJDL (Padded Jittering Data Link) v5.0](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) - [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) - [TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) diff --git a/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md b/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md index 2bbcac0b72..663257fb17 100644 --- a/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md +++ b/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md @@ -4,7 +4,7 @@ - [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer -- [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) +- [PJDL (Padded Jittering Data Link) v5.0](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) - [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - **[PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md)** - [TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) diff --git a/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md b/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md index 5b435c4daf..aac3f079a7 100644 --- a/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md +++ b/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md @@ -5,7 +5,7 @@ - [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer -- [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) +- [PJDL (Padded Jittering Data Link) v5.0](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) - **[PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md)** - [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) - [TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) diff --git a/src/strategies/README.md b/src/strategies/README.md index 5019f9fb76..413ec02fe5 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -16,7 +16,7 @@ The table below lists the strategies available: | [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | | [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | `#include ` | | [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | `#include ` | -| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) | `#include ` | +| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) | `#include ` | | [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | `#include ` | | [ThroughSerial](/src/strategies/ThroughSerial) | Wire | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | `#include ` | diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index 3923c1185c..4767b7c8bc 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -4,7 +4,7 @@ |--------|-----------|--------------------| | Wire | 1 or 2 | `#include `| -`SoftwareBitBang` is a software implementation of [PJDL (Padded Jittering Data Link)](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md). It supports simplex and half-duplex asynchronous serial communication for up to 254 devices over a single wire. The maximum length of the bus can reach between 800 and 2000 meters depending on the mode used. It is a valid alternative to 1-Wire because of its flexibility and reliability. Fault tolerance schemes can be easily implemented because communication pins can be configured at runtime. Take a look at the [video introduction](https://www.youtube.com/watch?v=GWlhKD5lz5w) for a brief showcase of its features. +`SoftwareBitBang` is a software implementation of [PJDL (Padded Jittering Data Link)](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md). It supports simplex and half-duplex asynchronous serial communication for up to 254 devices over a single wire. The maximum length of the bus can reach between 800 and 2000 meters depending on the mode used. It is a valid alternative to 1-Wire because of its flexibility and reliability. Fault tolerance schemes can be easily implemented because communication pins can be configured at runtime. Take a look at the [video introduction](https://www.youtube.com/watch?v=GWlhKD5lz5w) for a brief showcase of its features. ```cpp PJDL SINGLE WIRE BUS ______ ______ ______ ______ ______ | | @@ -51,7 +51,7 @@ Communication over a single wire enables quick and creative experimentation. The ![PJDL communication over 2000m twisted pair](images/PJDL-2000m-mode4-twistedpair-8.2k-pulldown-60-series.png) -The picture above shows a [PJDL](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) frame transmitted over a 800m twisted pair using mode `4` (test done by [Jack Anderson](https://github.com/jdaandersj)). Although bits are substantially deformed the exchange occurs nominally and performance is not affected. +The picture above shows a [PJDL](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) frame transmitted over a 800m twisted pair using mode `4` (test done by [Jack Anderson](https://github.com/jdaandersj)). Although bits are substantially deformed the exchange occurs nominally and performance is not affected. ### Configuration Before including the library it is possible to configure `SoftwareBitBang` using predefined constants: diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index b4814ffc75..a23e4e2052 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -5,7 +5,7 @@ Often timing in two different machines do not match, code execution time can variate and time measurements can be not perfectly equal. Consider that durations defined below may differ from what is specified in - PJDL v4.1. This is done to accomodate machine's inner workings and + PJDL v5.0. This is done to accomodate machine's inner workings and effectively produce the specified timing. Arduino Duemilanove/UNO/Nano is used as timing master, or the machine used diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index 201490ee96..8ec0f6464e 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -5,7 +5,7 @@ - [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer -- **[PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md)** +- **[PJDL (Padded Jittering Data Link) v5.0](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md)** - [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) - [TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) diff --git a/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md b/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md index f8a41f4c93..8b38ca2648 100644 --- a/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md +++ b/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md @@ -4,7 +4,7 @@ - [PJON (Padded Jittering Operative Network) v4.0](/specification/PJON-protocol-specification-v4.0.md) - [Network services list](/specification/PJON-network-services-list.md) #### Data link layer -- [PJDL (Padded Jittering Data Link) v4.1](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v4.1.md) +- [PJDL (Padded Jittering Data Link) v5.0](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) - [PJDLR (Padded Jittering Data Link over Radio) v3.0](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) - [PJDLS (Padded Jittering Data Link byte Stuffed) v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) - **[TSDL (Tardy Serial Data Link) v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md)** From e4bdef2c31a02efc63419639fdca5bb0bcfc4c64 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jul 2020 16:39:56 +0200 Subject: [PATCH 141/323] SoftwareBitBang comments and specification minor fix --- src/strategies/SoftwareBitBang/SoftwareBitBang.h | 2 +- .../SoftwareBitBang/specification/PJDL-specification-v5.0.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index 36a4715c0d..599b324d03 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -2,7 +2,7 @@ /* SoftwareBitBang 1 or 2 wires software-defined asynchronous serial data link layer used as a Strategy by PJON (included in version v3.0) - Compliant with PJDL (Padded Jittering Data Link) specification v4.1 + Compliant with PJDL (Padded Jittering Data Link) specification v5.0 ___________________________________________________________________________ Copyright 2010-2020 Giovanni Blu Mitolo gioscarab@gmail.com diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index 8ec0f6464e..fc64ba3761 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -73,7 +73,7 @@ Byte transmission is composed by 10 bits, the first two are called synchronizati The reception technique is based on 3 steps: 1. Find a high bit which matches a padding bit -2. Synchronize to its falling edge +2. Synchronize with its falling edge 3. Ensure it is followed by a low data bit If so reception starts, if not, interference, synchronization loss or simply absence of communication is detected. The high padding bit is 2.5 times longer than data bits because with this ratio ambiguity between padding bits and 2 or 3 consecutive data bits is avoided even with an overall deviation of up to +- (data bit / 4) - 1. From f91dc961495e9531d8618207efe7d5701ef5249e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jul 2020 16:41:09 +0200 Subject: [PATCH 142/323] Network/SoftwareBitBang/NetworkAnalysis compilation error fixed --- .../SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino index 6e1ef28848..e73e8c14e1 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino @@ -30,7 +30,6 @@ uint8_t content[] = "01234567890123456789"; // First 10 bytes left empty for bus void setup() { bus.strategy.set_pin(12); bus.begin(); - header = bus.config | PJON_CRC_BIT; // Force CRC32 Serial.begin(115200); Serial.println("PJON - Network analysis"); Serial.println("Starting a 1 second communication test.."); From 043d1711c7ade20ec4ae5678bfd65820b0ec6e2c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jul 2020 20:58:54 +0200 Subject: [PATCH 143/323] Strategies README broken links fix --- src/strategies/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategies/README.md b/src/strategies/README.md index 413ec02fe5..2a00f035f9 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -6,7 +6,7 @@ The table below lists the strategies available: | Strategy | Physical layer | Protocol | Inclusion | | ------------- | -------------- | -------- | --------- | -| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](../src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | `#include ` | +| [AnalogSampling](/src/strategies/AnalogSampling) | Light | [PJDLS](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) | `#include ` | | [Any](/src/strategies/Any) | Virtual inheritance | Any | `#include ` | | [DualUDP](/src/strategies/DualUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | | [ESPNOW](/src/strategies/ESPNOW) | WiFi | [ESPNOW](https://www.espressif.com/en/products/software/esp-now/overview) | `#include ` | @@ -15,10 +15,10 @@ The table below lists the strategies available: | [LocalFile](/src/strategies/LocalFile) | File system | None | `#include ` | | [LocalUDP](/src/strategies/LocalUDP) | Ethernet/WiFi | [UDP](https://tools.ietf.org/html/rfc768) | `#include ` | | [MQTTTranslate](/src/strategies/MQTTTranslate) | Ethernet/WiFi | [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf) | `#include ` | -| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](../src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | `#include ` | -| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](../src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) | `#include ` | +| [OverSampling](/src/strategies/OverSampling) | Radio | [PJDLR](/src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) | `#include ` | +| [SoftwareBitBang](/src/strategies/SoftwareBitBang) | Wire | [PJDL](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) | `#include ` | | [ThroughLoRa](/src/strategies/ThroughLoRa) | Radio | [LoRa](https://lora-alliance.org/sites/default/files/2018-07/lorawan1.0.3.pdf) | `#include ` | -| [ThroughSerial](/src/strategies/ThroughSerial) | Wire | [TSDL](../src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | `#include ` | +| [ThroughSerial](/src/strategies/ThroughSerial) | Wire | [TSDL](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) | `#include ` | ### How the strategy is implemented A `Strategy` is a class containing a set of methods used to physically send and receive data along with the required getters to handle retransmission and collision: From c5e650494673cb9eecef736b1ebcdb408c5e3c70 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jul 2020 20:59:34 +0200 Subject: [PATCH 144/323] Added Serial.flush() to PacketSeparationTest for more accurate results --- .../SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino index 2284f589ca..0aa6e5d06a 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest/Receiver/Receiver.ino @@ -56,6 +56,7 @@ void loop() { Serial.println(" __________________________________________________ "); Serial.println("[0% 50% 100%]"); Serial.print(" "); + Serial.flush(); test = 0, fail = 0, percent = 0; time = millis(); while(test < attempts) { @@ -64,6 +65,7 @@ void loop() { test++; if(!(test % (attempts / 50))) { Serial.print("-"); + Serial.flush(); percent++; } } From e206d6a4c9fbf7f6b8c34af65e111f37b7599a20 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jul 2020 21:03:51 +0200 Subject: [PATCH 145/323] SoftwareBitBang timing update (breaking compatibility) --- src/strategies/SoftwareBitBang/Timing.h | 36 +++++++++++-------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index a23e4e2052..240d269ed4 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -31,8 +31,8 @@ #if F_CPU == 16000000L /* Working on pin: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, A0, A1 */ #define SWBB_BIT_WIDTH 40 - #define SWBB_BIT_SPACER 112 - #define SWBB_ACCEPTANCE 56 + #define SWBB_BIT_SPACER 106 + #define SWBB_ACCEPTANCE 53 #define SWBB_READ_DELAY 4 #endif #endif @@ -91,8 +91,10 @@ /* ATmega16/32U4 - Arduino Leonardo/Micro --------------------------------- */ #if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) #if SWBB_MODE == 1 - /* Working on pin: 2, 4, 8, 12 - Fallback to default timing */ + /* Working on pin: 2, 4, 8, 12 */ + #define SWBB_BIT_WIDTH 40 + #define SWBB_BIT_SPACER 106 + #define SWBB_ACCEPTANCE 53 #define SWBB_READ_DELAY 8 #endif #if SWBB_MODE == 2 @@ -107,8 +109,8 @@ #if SWBB_MODE == 1 /* Working on pin: 3, 4, 7, 8, 9, 10, 12 */ #define SWBB_BIT_WIDTH 38 - #define SWBB_BIT_SPACER 110 - #define SWBB_ACCEPTANCE 62 + #define SWBB_BIT_SPACER 104 + #define SWBB_ACCEPTANCE 53 #define SWBB_READ_DELAY 11 #endif #if SWBB_MODE == 2 @@ -157,21 +159,13 @@ #if defined(ARDUINO_SAMD_ZERO) #if SWBB_MODE == 1 /* Added by Esben Soeltoft - 03/09/2016 - Updated by Giovanni Blu Mitolo - 31/05/2019 + Updated by Giovanni Blu Mitolo - 21/07/2020 Working on pin: D0, D1, D3, A0, A1 */ - #define SWBB_BIT_WIDTH 43 - #define SWBB_BIT_SPACER 115 - #define SWBB_ACCEPTANCE 40 + #define SWBB_BIT_WIDTH 43.5 + #define SWBB_BIT_SPACER 109.5 + #define SWBB_ACCEPTANCE 45 #define SWBB_READ_DELAY -4 #endif - #if SWBB_MODE == 3 - /* Added by Esben Soeltoft - 09/03/2016 - Speed: 48000Bd or 6.00kB/s */ - #define SWBB_BIT_WIDTH 12 - #define SWBB_BIT_SPACER 36 - #define SWBB_ACCEPTANCE 12 - #define SWBB_READ_DELAY 1 - #endif #endif /* NodeMCU, generic ESP8266 ----------------------------------------------- */ @@ -181,9 +175,9 @@ Added full support to MODE 1 (80 and 160MHz) - 12/06/2018 */ #if (F_CPU == 80000000L) || (F_CPU == 160000000L) /* Working on pin: D1 or GPIO 5 */ - #define SWBB_BIT_WIDTH 44 - #define SWBB_BIT_SPACER 112 - #define SWBB_ACCEPTANCE 56 + #define SWBB_BIT_WIDTH 43.5 + #define SWBB_BIT_SPACER 109.5 + #define SWBB_ACCEPTANCE 52 #define SWBB_READ_DELAY -6 #endif #endif From ee88945286b0baea9a5f3ec9a33820b16d34501b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jul 2020 13:39:07 +0200 Subject: [PATCH 146/323] SoftwareBitBang README minor fix' --- src/strategies/SoftwareBitBang/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index 4767b7c8bc..0e52cf406c 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -40,10 +40,10 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above | Mode | Speed | Range | Supported MCUs | | ---- | ----- |------ | ---------------- | -| `1` | 1.95kB/s | 2000m | ATtiny84/84A/85, ATmega88/168/328/328PB/16u4/32u4/2560/1284P, SAMD, STM32F1, MK20DX256, ESP8266, ESP32 | +| `1` | 1.97kB/s | 2000m | ATtiny84/84A/85, ATmega88/168/328/328PB/16u4/32u4/2560/1284P, SAMD, STM32F1, MK20DX256, ESP8266, ESP32 | | `2` | 2.21kB/s | 1600m | ATtiny84/84A/85, ATmega88/168/328/328PB/16u4/32u4/2560, STM32F1 | -| `3` | 2.94kB/s | 1200m | ATtiny84/84A/85, ATmega88/168/328, STM32F1 | -| `4` | 3.40kB/s | 800m | ATtiny84/84A/85, ATmega88/168/328, STM32F1 | +| `3` | 3.10kB/s | 1200m | ATtiny84/84A/85, ATmega88/168/328, STM32F1 | +| `4` | 3.34kB/s | 800m | ATtiny84/84A/85, ATmega88/168/328, STM32F1 | When including and using the `SoftwareBitBang` strategy you have the complete access to the microcontroller. This happens because `SoftwareBitBang` runs a completely software-defined implementation, transforming a painful walk in a nice flight. @@ -88,7 +88,7 @@ PJON application example made by the user [Michael Teeuw](http://michaelteeuw.nl ### Known issues - A 1-5 MΩ pull down resistor could be necessary to reduce interference, see [Mitigate interference](https://github.com/gioblu/PJON/wiki/Mitigate-interference). -- When using more than one instance of `SoftwareBitBang` in the same sketch always use pins connected to a different port group to avoid cross-talk. +- When using more than one instance of `SoftwareBitBang` in the same sketch use pins part of different port groups to avoid cross-talk. - During the execution of other tasks or delays a certain amount of packets could be potentially lost because transmitted out of the polling time of the receiver device. Thanks to the PJON packet handler after some retries the packet is received but a certain amount of bandwidth is wasted. If this situation occurs, try to reduce as much as possible the duration of other tasks and or use a longer polling time using `receive` and passing the requested amount of microseconds: `bus.receive(1000); // Poll for 1 millisecond`. - `SoftwareBitBang` strategy can have compatibility issues with codebases that are using interrupts, reliability or bandwidth loss can occur because of the interruptions made by third party software. From ea5b989fbc9d8f972e9bd28add07ee48fa307a13 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jul 2020 14:24:33 +0200 Subject: [PATCH 147/323] SoftwareBitBang REAMDE, added PJDL frame pic and safety remarks --- src/strategies/SoftwareBitBang/README.md | 5 ++++- .../images/PJDL-frame-oscilloscope.jpg | Bin 0 -> 47554 bytes 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 src/strategies/SoftwareBitBang/images/PJDL-frame-oscilloscope.jpg diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index 0e52cf406c..e9a804bf16 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -19,6 +19,9 @@ ___|__________|________|___________|______/\/\/\__| IO PIN ``` It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above to reduce externally induced interference. The longer is the length of the cable and the higher is the amount of induced interference, the lower should be the resistance of the pull-down resistor. Pins can be optionally protected against overload adding a current limiting resistor to each connected pin. The resistor value can be obtained solving the following equation `R = (operating voltage / pin max current drain)`, for example to obtain the current limiting resistor value for an Arduino Uno simply substitute its characteristics: `R = (5v / 0.030A) = 166.66Ω`. +![PJDL frame seen in the oscilloscope](images/PJDL-frame-oscilloscope.jpg) +The picture above shows how a short PJDL frame looks like when observed with an oscilloscope. + ### Compatibility | MCU | Clock | Supported pins | | ---------------- |------ | ---------------- | @@ -93,4 +96,4 @@ PJON application example made by the user [Michael Teeuw](http://michaelteeuw.nl - `SoftwareBitBang` strategy can have compatibility issues with codebases that are using interrupts, reliability or bandwidth loss can occur because of the interruptions made by third party software. ### Safety warning -In all cases, when installing or maintaining a PJON network, extreme care must be taken to avoid any danger. When a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus is installed each pin must be protected with a current limiting resistor as described above. If a common ground or power supply line is used its cable size and length must be carefully selected taking in consideration the overall application's power supply requirements and selected components' maximum rating. +In all cases, when installing or maintaining a PJON network, extreme care must be taken to avoid any danger. If devices are connected to AC power you are exposed to a high chance of being electrocuted if hardware is not installed carefully and properly. If you are not experienced enough ask the support of a skilled technician and consider that many countries prohibit uncertified installations. When a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus is installed [interference mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines must be followed. If a common ground or power supply line is used its cable size and length must be carefully selected taking in consideration the overall application's power supply requirements and selected components' maximum rating. The PJDL protocol and its reference implementation [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) are experimental, use them at your own risk. diff --git a/src/strategies/SoftwareBitBang/images/PJDL-frame-oscilloscope.jpg b/src/strategies/SoftwareBitBang/images/PJDL-frame-oscilloscope.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3a084cb11e9160687134ab211f0cbb6a6b3a48e9 GIT binary patch literal 47554 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


MB;fB|6&ByEk;!WY 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 Date: Wed, 22 Jul 2020 14:56:08 +0200 Subject: [PATCH 148/323] PJDL frame image too big --- src/strategies/SoftwareBitBang/README.md | 3 --- .../images/PJDL-frame-oscilloscope.jpg | Bin 47554 -> 0 bytes 2 files changed, 3 deletions(-) delete mode 100644 src/strategies/SoftwareBitBang/images/PJDL-frame-oscilloscope.jpg diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index e9a804bf16..36c61c1727 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -19,9 +19,6 @@ ___|__________|________|___________|______/\/\/\__| IO PIN ``` It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above to reduce externally induced interference. The longer is the length of the cable and the higher is the amount of induced interference, the lower should be the resistance of the pull-down resistor. Pins can be optionally protected against overload adding a current limiting resistor to each connected pin. The resistor value can be obtained solving the following equation `R = (operating voltage / pin max current drain)`, for example to obtain the current limiting resistor value for an Arduino Uno simply substitute its characteristics: `R = (5v / 0.030A) = 166.66Ω`. -![PJDL frame seen in the oscilloscope](images/PJDL-frame-oscilloscope.jpg) -The picture above shows how a short PJDL frame looks like when observed with an oscilloscope. - ### Compatibility | MCU | Clock | Supported pins | | ---------------- |------ | ---------------- | diff --git a/src/strategies/SoftwareBitBang/images/PJDL-frame-oscilloscope.jpg b/src/strategies/SoftwareBitBang/images/PJDL-frame-oscilloscope.jpg deleted file mode 100644 index 3a084cb11e9160687134ab211f0cbb6a6b3a48e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47554 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
MB;fB|6&ByEk;!WY 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 Date: Wed, 22 Jul 2020 18:51:55 +0200 Subject: [PATCH 149/323] SoftwareBitBang NetworkAnalysis example added success rate --- .../Local/SoftwareBitBang/NetworkAnalysis/README.md | 8 ++++---- .../NetworkAnalysis/Transmitter/Transmitter.ino | 10 ++-------- .../NetworkAnalysis/Transmitter/Transmitter.ino | 10 ++-------- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/README.md b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/README.md index ec62477834..eab3fc58f3 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/README.md +++ b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/README.md @@ -21,10 +21,10 @@ The test result can be evaluated thanks to the following terms: * `Mistakes` or how many errors detected with CRC * `Fail` or number of transmission failures occurred in the test window * `Busy` or how many times the channel is found busy -* `Accuracy` or ratio between correct packets and packets that contain mistakes +* `Delivery success rate` or ratio between packets sent successfully and transmission failures The result can be interpreted as follows: -- Many `Fail` and or `Mistakes` may mean that the maximum communication range between devices has been reached -- Many `Busy` and or `Mistakes` and or low `Bandwidth` may mean that interference is present, see [mitigate interference](https://github.com/gioblu/PJON/wiki/Mitigate-interference) -- Many `Fail` and or `Mistakes` and or low `Bandwidth` may indicate a bad timing configuration, if you are porting a new MCU/architecture to [SoftwareBitBang](/src/strategies/SoftwareBitBang) consider that a different timing configuration may be required because of system discrepancies. Try tweaking `SWBB_BIT_WIDTH`, `SWBB_BIT_SPACER`, `SWBB_READ_DELAY` and `SWBB_ACCEPTANCE` in [src/strategies/SoftwareBitBang/Timing.h](/src/strategies/SoftwareBitBang/Timing.h) +- If the success rate is low that may mean that the maximum range between devices has been reached +- If the channel is found many times `busy` and or the bandwidth is low, that may mean that interference is present, see [mitigate interference](https://github.com/gioblu/PJON/wiki/Mitigate-interference) +- A low success rate and or low bandwidth may indicate a bad timing configuration, if you are porting a new MCU/architecture to [SoftwareBitBang](/src/strategies/SoftwareBitBang) consider that a different timing configuration may be required because of system discrepancies. Try tweaking `SWBB_BIT_WIDTH`, `SWBB_BIT_SPACER`, `SWBB_READ_DELAY` and `SWBB_ACCEPTANCE` in [src/strategies/SoftwareBitBang/Timing.h](/src/strategies/SoftwareBitBang/Timing.h) - Low performance also after painstaking timing tweaks may indicate that the new MCU/architecture may not be fast enough to run SoftwareBitBang at the mode you are working with, try using a faster clock or optimize digital I/O perfomance or choosing a slower mode. diff --git a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino index 38a42a3be2..7e618724a2 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino @@ -14,7 +14,6 @@ #include float test; -float mistakes; int busy; int fail; @@ -44,8 +43,6 @@ void loop() { unsigned int response = bus.send_packet(44, content, 20); if(response == PJON_ACK) test++; - if(response == PJON_NAK) - mistakes++; if(response == PJON_BUSY) busy++; if(response == PJON_FAIL) @@ -65,21 +62,18 @@ void loop() { Serial.println("B/s"); Serial.print("Packets sent: "); Serial.println((unsigned int)test); - Serial.print("Mistakes (error found with CRC): "); - Serial.println((unsigned int)mistakes); Serial.print("Fail (no acknowledge from receiver): "); Serial.println(fail); Serial.print("Busy (Channel is busy or affected by interference): "); Serial.println(busy); - Serial.print("Accuracy: "); - Serial.print(100 - (100 / (test / mistakes))); + Serial.print("Delivery success rate: "); + Serial.print(100 - (100 / (test / fail))); Serial.println(" %"); Serial.println("---------------------"); // Avoid Serial interference during test flushing Serial.flush(); test = 0; - mistakes = 0; busy = 0; fail = 0; }; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino index e73e8c14e1..02b993f27b 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino @@ -14,7 +14,6 @@ #include float test; -float mistakes; int busy; int fail; @@ -50,8 +49,6 @@ void loop() { if(response == PJON_ACK) test++; - if(response == PJON_NAK) - mistakes++; if(response == PJON_BUSY) busy++; if(response == PJON_FAIL) @@ -72,21 +69,18 @@ void loop() { Serial.println("B/s"); Serial.print("Packets sent: "); Serial.println((unsigned int)test); - Serial.print("Mistakes (error found with CRC): "); - Serial.println((unsigned int)mistakes); Serial.print("Fail (no acknowledge from receiver): "); Serial.println(fail); Serial.print("Busy (Channel is busy or affected by interference): "); Serial.println(busy); - Serial.print("Accuracy: "); - Serial.print(100 - (100 / (test / mistakes))); + Serial.print("Delivery success rate: "); + Serial.print(100 - (100 / (test / fail))); Serial.println(" %"); Serial.println("---------------------"); // Avoid Serial interference during test flushing Serial.flush(); test = 0; - mistakes = 0; busy = 0; fail = 0; }; From c9120ded8ad8347f2bfd0de56beb811f3e4a57b1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jul 2020 18:54:03 +0200 Subject: [PATCH 150/323] SWBB ESP8266, ESP32, STM32F1 timing update to fit in spec --- src/strategies/SoftwareBitBang/Timing.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 240d269ed4..20dad5074a 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -173,13 +173,20 @@ #if SWBB_MODE == 1 /* Added by github user 240974a - 09/03/2016 Added full support to MODE 1 (80 and 160MHz) - 12/06/2018 */ - #if (F_CPU == 80000000L) || (F_CPU == 160000000L) + #if (F_CPU == 80000000L) /* Working on pin: D1 or GPIO 5 */ #define SWBB_BIT_WIDTH 43.5 #define SWBB_BIT_SPACER 109.5 #define SWBB_ACCEPTANCE 52 #define SWBB_READ_DELAY -6 #endif + #if (F_CPU == 160000000L) + /* Working on pin: D1 or GPIO 5 */ + #define SWBB_BIT_WIDTH 44 + #define SWBB_BIT_SPACER 110 + #define SWBB_ACCEPTANCE 52 + #define SWBB_READ_DELAY -6 + #endif #endif #endif @@ -189,7 +196,7 @@ /* Added full support to MODE 1 - 28/06/2018 Working on pin: 12 and 25 */ #define SWBB_BIT_WIDTH 44 - #define SWBB_BIT_SPACER 112 + #define SWBB_BIT_SPACER 110 #define SWBB_ACCEPTANCE 56 #define SWBB_READ_DELAY -2 #endif @@ -215,10 +222,10 @@ #if defined(__STM32F1__) #if SWBB_MODE == 1 #if F_CPU == 72000000L - #define SWBB_BIT_WIDTH 43 - #define SWBB_BIT_SPACER 115 - #define SWBB_ACCEPTANCE 60 - #define SWBB_READ_DELAY 3 + #define SWBB_BIT_WIDTH 43.5 + #define SWBB_BIT_SPACER 109.5 + #define SWBB_ACCEPTANCE 50 + #define SWBB_READ_DELAY -6 #endif #endif #if SWBB_MODE == 2 From 006aa8452088b748314809f654139267549c9bd6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jul 2020 19:01:11 +0200 Subject: [PATCH 151/323] SoftwareBitBang tests directory added --- .../tests/NetworkAnalysis-10s.md | 30 +++++++++++++++++++ .../tests/PacketSeparationTest.md | 19 ++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md create mode 100644 src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md new file mode 100644 index 0000000000..7edac1874b --- /dev/null +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -0,0 +1,30 @@ +## NetworkAnalysis +This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis) example for 10 seconds and averaging the obtained series of results. + +| TX | PIN | RX | PIN | RESULT | +|----------------|-----|----------------|-----|-----------------------------------------------------| +| UNO/Nano | 12 | UNO/Nano | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | +| Mega | 12 | UNO/Nano | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | +| Leonardo | 12 | UNO/Nano | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | +| Mega | 12 | Leonardo | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | +| Leonardo | 12 | Leonardo | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | +| Leonardo | 12 | Mega | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | +| Leonardo | 12 | SAMD21 | D0 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| UNO/Nano | 12 | Mega | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | +| UNO/Nano | 12 | Leonardo | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | +| UNO/Nano | 12 | ESP8266 160MHz | D1 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| ESP8266 80MHz | D1 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| ESP8266 160MHz | D1 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| ESP8266 80MHz | D1 | Mega | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| ESP8266 160MHz | D1 | Mega | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| SAMD21 | D0 | Mega | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| ESP32 | 12 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| UNO/Nano | PB9 | Bluepill | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| Bluepill | PB9 | Bluepill | PB9 | Bandwidth: 1860kB/s Packets/s: 62 Success: 100% | +| Bluepill | PB9 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.5% | +| SAMD21 | D0 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | +| UNO/Nano | 12 | ESP32 | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | +| Mega | 12 | ESP32 | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | +| UNO/Nano | 12 | ESP8266 80MHz | D1 | Bandwidth: 1620kB/s Packets/s: 57 Success: 98.28% | +| ESP32 | 12 | Leonardo | 12 | Bandwidth: 1620kB/s Packets/s: 55 Success: 91.00% | +| Leonardo | 12 | ESP32 | 12 | Bandwidth: 1620kB/s Packets/s: 55 Success: 91.00% | diff --git a/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md b/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md new file mode 100644 index 0000000000..193dca6fb4 --- /dev/null +++ b/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md @@ -0,0 +1,19 @@ +## PacketSeparationTest + +This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest) example for 10 seconds and averaging the obtained series of results. + +| TX |PIN | RX |PIN | RESULT | +|---------------------|----|------------------|----|-----------------------------------------------------| +| UNO/Nano | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 100% | +| UNO/Nano | 12 | Mega | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.999% | +| UNO/Nano | 12 | ESP32 | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | +| Mega | 12 | Leonardo | 12 | SWBB_ACCEPTANCE 53 Accuracy: 100% | +| Mega | 12 | ESP32 | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | +| Leonardo | 12 | Leonardo | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | +| Leonardo | 12 | ESP32 | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | +| Leonardo | 12 | Mega | 12 | SWBB_ACCEPTANCE 53 Accuracy: 100% | +| Leonardo | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.999% | +| Mega | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.999% | +| SAMD21 | D0 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.89% | +| SAMD21 | D0 | Mega | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.88% | +| ESP32 | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.87% | From 43e32b92f7e1663180aa674539de537542bc07d0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jul 2020 19:03:33 +0200 Subject: [PATCH 152/323] SoftwareBitBang minor fix --- src/strategies/SoftwareBitBang/Timing.h | 2 +- src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 20dad5074a..74c1487ebf 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -225,7 +225,7 @@ #define SWBB_BIT_WIDTH 43.5 #define SWBB_BIT_SPACER 109.5 #define SWBB_ACCEPTANCE 50 - #define SWBB_READ_DELAY -6 + #define SWBB_READ_DELAY -8 #endif #endif #if SWBB_MODE == 2 diff --git a/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md b/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md index 193dca6fb4..497b7d7aee 100644 --- a/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md +++ b/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md @@ -1,6 +1,6 @@ ## PacketSeparationTest -This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest) example for 10 seconds and averaging the obtained series of results. +This table was filled running the [PacketSeparationTest](../../../../examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest) example for 10 seconds and averaging the obtained series of results. | TX |PIN | RX |PIN | RESULT | |---------------------|----|------------------|----|-----------------------------------------------------| From 417a58b553c2ddff74331d134db48c5496b009f6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jul 2020 19:21:15 +0200 Subject: [PATCH 153/323] NetworkAnaysis test result table update --- .../tests/NetworkAnalysis-10s.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index 7edac1874b..259ff1572b 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -4,27 +4,27 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | TX | PIN | RX | PIN | RESULT | |----------------|-----|----------------|-----|-----------------------------------------------------| | UNO/Nano | 12 | UNO/Nano | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | -| Mega | 12 | UNO/Nano | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | -| Leonardo | 12 | UNO/Nano | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | -| Mega | 12 | Leonardo | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | -| Leonardo | 12 | Leonardo | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | -| Leonardo | 12 | Mega | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | -| Leonardo | 12 | SAMD21 | D0 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| UNO/Nano | 12 | Leonardo/Micro | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | | UNO/Nano | 12 | Mega | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | -| UNO/Nano | 12 | Leonardo | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | | UNO/Nano | 12 | ESP8266 160MHz | D1 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| UNO/Nano | PB9 | Bluepill | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| UNO/Nano | 12 | ESP32 | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | +| UNO/Nano | 12 | ESP8266 80MHz | D1 | Bandwidth: 1620kB/s Packets/s: 57 Success: 98.28% | +| Leonardo/Micro | 12 | UNO/Nano | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | +| Leonardo/Micro | 12 | Leonardo/Micro | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | +| Leonardo/Micro | 12 | Mega | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | +| Leonardo/Micro | 12 | SAMD21 | D0 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| Leonardo/Micro | 12 | ESP32 | 12 | Bandwidth: 1620kB/s Packets/s: 55 Success: 91.00% | +| Mega | 12 | UNO/Nano | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | +| Mega | 12 | Leonardo/Micro | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | +| Mega | 12 | ESP32 | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | | ESP8266 80MHz | D1 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | | ESP8266 160MHz | D1 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | | ESP8266 80MHz | D1 | Mega | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | | ESP8266 160MHz | D1 | Mega | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| SAMD21 | D0 | Mega | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | | ESP32 | 12 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| UNO/Nano | PB9 | Bluepill | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| Bluepill | PB9 | Bluepill | PB9 | Bandwidth: 1860kB/s Packets/s: 62 Success: 100% | -| Bluepill | PB9 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.5% | +| ESP32 | 12 | Leonardo/Micro | 12 | Bandwidth: 1620kB/s Packets/s: 55 Success: 91.00% | +| SAMD21 | D0 | Mega | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | | SAMD21 | D0 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | -| UNO/Nano | 12 | ESP32 | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | -| Mega | 12 | ESP32 | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | -| UNO/Nano | 12 | ESP8266 80MHz | D1 | Bandwidth: 1620kB/s Packets/s: 57 Success: 98.28% | -| ESP32 | 12 | Leonardo | 12 | Bandwidth: 1620kB/s Packets/s: 55 Success: 91.00% | -| Leonardo | 12 | ESP32 | 12 | Bandwidth: 1620kB/s Packets/s: 55 Success: 91.00% | +| Blue pill | PB9 | Blue pill | PB9 | Bandwidth: 1860kB/s Packets/s: 62 Success: 100% | +| Blue pill | PB9 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.5% | From 7ed683cd44282eafa8086b02484b57d48d245302 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jul 2020 19:46:21 +0200 Subject: [PATCH 154/323] SoftwareBitBang NetworkAnalysis test update --- .../SoftwareBitBang/tests/NetworkAnalysis-10s.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index 259ff1572b..374e90366d 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -7,17 +7,20 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | UNO/Nano | 12 | Leonardo/Micro | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | | UNO/Nano | 12 | Mega | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | | UNO/Nano | 12 | ESP8266 160MHz | D1 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| UNO/Nano | PB9 | Bluepill | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| UNO/Nano | 12 | ESP32 | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | | UNO/Nano | 12 | ESP8266 80MHz | D1 | Bandwidth: 1620kB/s Packets/s: 57 Success: 98.28% | +| UNO/Nano | 12 | ESP32 | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | +| UNO/Nano | PB9 | Bluepill | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | | Leonardo/Micro | 12 | UNO/Nano | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | | Leonardo/Micro | 12 | Leonardo/Micro | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | | Leonardo/Micro | 12 | Mega | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | -| Leonardo/Micro | 12 | SAMD21 | D0 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | | Leonardo/Micro | 12 | ESP32 | 12 | Bandwidth: 1620kB/s Packets/s: 55 Success: 91.00% | +| Leonardo/Micro | 12 | SAMD21 | D0 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | | Mega | 12 | UNO/Nano | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | | Mega | 12 | Leonardo/Micro | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | +| Mega | 12 | ESP8266 80MHz | D1 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | +| Mega | 12 | ESP8266 160MHz | D1 | Bandwidth: 1755kB/s Packets/s: 58.5 Success: 99.5% | | Mega | 12 | ESP32 | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | +| Mega | 12 | SAMD21 | D0 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | | ESP8266 80MHz | D1 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | | ESP8266 160MHz | D1 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | | ESP8266 80MHz | D1 | Mega | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | From 99ed36c668ac09b4e6c31f040efda69070ac9473 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jul 2020 19:49:47 +0200 Subject: [PATCH 155/323] SoftwareBitBang NetworkAnalysis test result update --- .../tests/NetworkAnalysis-10s.md | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index 374e90366d..fc1d910f01 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -1,33 +1,33 @@ ## NetworkAnalysis This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis) example for 10 seconds and averaging the obtained series of results. -| TX | PIN | RX | PIN | RESULT | -|----------------|-----|----------------|-----|-----------------------------------------------------| -| UNO/Nano | 12 | UNO/Nano | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | -| UNO/Nano | 12 | Leonardo/Micro | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | -| UNO/Nano | 12 | Mega | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | -| UNO/Nano | 12 | ESP8266 160MHz | D1 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| UNO/Nano | 12 | ESP8266 80MHz | D1 | Bandwidth: 1620kB/s Packets/s: 57 Success: 98.28% | -| UNO/Nano | 12 | ESP32 | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | -| UNO/Nano | PB9 | Bluepill | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| Leonardo/Micro | 12 | UNO/Nano | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | -| Leonardo/Micro | 12 | Leonardo/Micro | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | -| Leonardo/Micro | 12 | Mega | 12 | Bandwidth: 1740kB/s Packets/s: 58 Success: 100% | -| Leonardo/Micro | 12 | ESP32 | 12 | Bandwidth: 1620kB/s Packets/s: 55 Success: 91.00% | -| Leonardo/Micro | 12 | SAMD21 | D0 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| Mega | 12 | UNO/Nano | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | -| Mega | 12 | Leonardo/Micro | 12 | Bandwidth: 1725kB/s Packets/s: 57.5 Success: 100% | -| Mega | 12 | ESP8266 80MHz | D1 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| Mega | 12 | ESP8266 160MHz | D1 | Bandwidth: 1755kB/s Packets/s: 58.5 Success: 99.5% | -| Mega | 12 | ESP32 | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | -| Mega | 12 | SAMD21 | D0 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| ESP8266 80MHz | D1 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| ESP8266 160MHz | D1 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| ESP8266 80MHz | D1 | Mega | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| ESP8266 160MHz | D1 | Mega | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| ESP32 | 12 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| ESP32 | 12 | Leonardo/Micro | 12 | Bandwidth: 1620kB/s Packets/s: 55 Success: 91.00% | -| SAMD21 | D0 | Mega | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 100% | -| SAMD21 | D0 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.00% | -| Blue pill | PB9 | Blue pill | PB9 | Bandwidth: 1860kB/s Packets/s: 62 Success: 100% | -| Blue pill | PB9 | UNO/Nano | 12 | Bandwidth: 1770kB/s Packets/s: 59 Success: 99.5% | +| TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | +|----------------|-----|----------------|-----|-----------|-----------|--------------| +| UNO/Nano | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | +| UNO/Nano | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | +| UNO/Nano | 12 | Mega | 12 | 1740kB/s | 58 | 100% | +| UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | +| UNO/Nano | 12 | ESP8266 80MHz | D1 | 1620kB/s | 57 | 98.28% | +| UNO/Nano | 12 | ESP32 | 12 | 1770kB/s | 59 | 99.00% | +| UNO/Nano | PB9 | Bluepill | 12 | 1770kB/s | 59 | 100% | +| Leonardo/Micro | 12 | UNO/Nano | 12 | 1725kB/s | 57.5 | 100% | +| Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | +| Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | +| Leonardo/Micro | 12 | ESP32 | 12 | 1620kB/s | 55 | 91.00% | +| Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | +| Mega | 12 | UNO/Nano | 12 | 1725kB/s | 57.5 | 100% | +| Mega | 12 | Leonardo/Micro | 12 | 1725kB/s | 57.5 | 100% | +| Mega | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | +| Mega | 12 | ESP8266 160MHz | D1 | 1755kB/s | 58.5 | 99.5% | +| Mega | 12 | ESP32 | 12 | 1770kB/s | 59 | 99.00% | +| Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | +| ESP8266 80MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| ESP8266 160MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| ESP8266 80MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | +| ESP8266 160MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | +| ESP32 | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| ESP32 | 12 | Leonardo/Micro | 12 | 1620kB/s | 55 | 91.00% | +| SAMD21 | D0 | Mega | 12 | 1770kB/s | 59 | 100% | +| SAMD21 | D0 | UNO/Nano | 12 | 1770kB/s | 59 | 99.00% | +| Blue pill | PB9 | Blue pill | PB9 | 1860kB/s | 62 | 100% | +| Blue pill | PB9 | UNO/Nano | 12 | 1770kB/s | 59 | 99.5% | From c84836ea80d1a779ac325c38e6d2b531c8bf9266 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jul 2020 21:47:56 +0200 Subject: [PATCH 156/323] SoftwareBitBang NetworkAnalysis test results update --- .../SoftwareBitBang/tests/NetworkAnalysis-10s.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index fc1d910f01..e1f346f45b 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -9,7 +9,7 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1620kB/s | 57 | 98.28% | | UNO/Nano | 12 | ESP32 | 12 | 1770kB/s | 59 | 99.00% | -| UNO/Nano | PB9 | Bluepill | 12 | 1770kB/s | 59 | 100% | +| UNO/Nano | PB9 | Blue pill | 12 | 1770kB/s | 59 | 100% | | Leonardo/Micro | 12 | UNO/Nano | 12 | 1725kB/s | 57.5 | 100% | | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | @@ -25,9 +25,17 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | ESP8266 160MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | ESP8266 80MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | | ESP8266 160MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | +| ESP8266 80MHz | D1 | Blue pill | PB9 | 1764kB/s | 58.8 | 98% | +| ESP8266 160MHz | D1 | Blue pill | PB9 | 1764kB/s | 58.8 | 98% | | ESP32 | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | ESP32 | 12 | Leonardo/Micro | 12 | 1620kB/s | 55 | 91.00% | +| ESP32 | 12 | Blue pill | PB9 | 0kB/s | 0 | 0% | | SAMD21 | D0 | Mega | 12 | 1770kB/s | 59 | 100% | +| SAMD21 | D0 | Leonardo/Micro | 12 | 1590kB/s | 53 | 88.68% | | SAMD21 | D0 | UNO/Nano | 12 | 1770kB/s | 59 | 99.00% | +| SAMD21 | D0 | Blue pill | PB9 | 1800kB/s | 60 | 100% | | Blue pill | PB9 | Blue pill | PB9 | 1860kB/s | 62 | 100% | | Blue pill | PB9 | UNO/Nano | 12 | 1770kB/s | 59 | 99.5% | +| Blue pill | PB9 | SAMD | 12 | 1830kB/s | 61 | 100% | +| Blue pill | PB9 | ESP8266 | D1 | 0kB/s | 0 | 0% | +| Blue pill | PB9 | ESP32 | 12 | 0kB/s | 0 | 0% | From f7d61b5bca060e9f06ec4f5377b642f2537ce41c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jul 2020 03:02:44 +0200 Subject: [PATCH 157/323] SoftwareBitBang better timing for Duemilanove/UNO/Nano --- src/strategies/SoftwareBitBang/Timing.h | 2 +- .../SoftwareBitBang/tests/NetworkAnalysis-10s.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 74c1487ebf..1007a80e7e 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -33,7 +33,7 @@ #define SWBB_BIT_WIDTH 40 #define SWBB_BIT_SPACER 106 #define SWBB_ACCEPTANCE 53 - #define SWBB_READ_DELAY 4 + #define SWBB_READ_DELAY 3 #endif #endif #if SWBB_MODE == 2 diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index e1f346f45b..51e6618539 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -8,14 +8,14 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | UNO/Nano | 12 | Mega | 12 | 1740kB/s | 58 | 100% | | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1620kB/s | 57 | 98.28% | -| UNO/Nano | 12 | ESP32 | 12 | 1770kB/s | 59 | 99.00% | +| UNO/Nano | 12 | ESP32 | 12 | 1770kB/s | 59 | 99.80% | | UNO/Nano | PB9 | Blue pill | 12 | 1770kB/s | 59 | 100% | -| Leonardo/Micro | 12 | UNO/Nano | 12 | 1725kB/s | 57.5 | 100% | +| Leonardo/Micro | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | | Leonardo/Micro | 12 | ESP32 | 12 | 1620kB/s | 55 | 91.00% | | Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | -| Mega | 12 | UNO/Nano | 12 | 1725kB/s | 57.5 | 100% | +| Mega | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | | Mega | 12 | Leonardo/Micro | 12 | 1725kB/s | 57.5 | 100% | | Mega | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | | Mega | 12 | ESP8266 160MHz | D1 | 1755kB/s | 58.5 | 99.5% | @@ -32,7 +32,7 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | ESP32 | 12 | Blue pill | PB9 | 0kB/s | 0 | 0% | | SAMD21 | D0 | Mega | 12 | 1770kB/s | 59 | 100% | | SAMD21 | D0 | Leonardo/Micro | 12 | 1590kB/s | 53 | 88.68% | -| SAMD21 | D0 | UNO/Nano | 12 | 1770kB/s | 59 | 99.00% | +| SAMD21 | D0 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | SAMD21 | D0 | Blue pill | PB9 | 1800kB/s | 60 | 100% | | Blue pill | PB9 | Blue pill | PB9 | 1860kB/s | 62 | 100% | | Blue pill | PB9 | UNO/Nano | 12 | 1770kB/s | 59 | 99.5% | From b7bde5fd461559372870286333f8fdbdead93442 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jul 2020 15:48:19 +0200 Subject: [PATCH 158/323] Strategy frame_end method added (breaking compatibility) --- src/PJON.h | 20 ++++++++++++------- .../AnalogSampling/AnalogSampling.h | 7 +++++++ src/strategies/Any/Any.h | 7 +++++++ src/strategies/DualUDP/DualUDP.h | 6 ++++++ src/strategies/ESPNOW/ESPNOW.h | 7 +++++++ src/strategies/EthernetTCP/EthernetTCP.h | 7 +++++++ src/strategies/GlobalUDP/GlobalUDP.h | 7 +++++++ src/strategies/LocalFile/LocalFile.h | 4 ++++ src/strategies/LocalUDP/LocalUDP.h | 7 +++++++ src/strategies/MQTTTranslate/MQTTTranslate.h | 7 +++++++ src/strategies/OverSampling/OverSampling.h | 5 +++++ src/strategies/README.md | 4 ++++ src/strategies/ThroughLoRa/ThroughLora.h | 6 ++++++ src/strategies/ThroughSerial/ThroughSerial.h | 5 +++++ 14 files changed, 92 insertions(+), 7 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 0fec7acbe7..562eb3cc58 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -343,22 +343,29 @@ class PJON { } } + bool nak = false, ack = + (data[1] & PJON_ACK_REQ_BIT) && (data[0] != PJON_BROADCAST) && + (_mode != PJON_SIMPLEX) && !_router + ; + + strategy.frame_end(ack); + if( PJON_crc8::compute(data, 3 + extended_length) != data[3 + extended_length] - ) return PJON_NAK; + ) nak = true; if(data[1] & PJON_CRC_BIT) { if( !PJON_crc32::compare( PJON_crc32::compute(data, length - 4), data + (length - 4) ) - ) return PJON_NAK; + ) nak = true; } else if(PJON_crc8::compute(data, length - 1) != data[length - 1]) - return PJON_NAK; + nak = true; #if(PJON_INCLUDE_MAC) - if(mac && (length > 15) && !_router) + if(!nak && mac && (length > 15) && !_router) if(!PJONTools::id_equality(data + (overhead - 16), tx.mac, 6)) if(! PJONTools::id_equality( @@ -368,9 +375,8 @@ class PJON { ) return PJON_BUSY; #endif - if(data[1] & PJON_ACK_REQ_BIT && data[0] != PJON_BROADCAST) - if((_mode != PJON_SIMPLEX) && !_router) - strategy.send_response(PJON_ACK); + if(ack) strategy.send_response((nak) ? PJON_NAK : PJON_ACK); + if(nak) return PJON_NAK; parse(data, last_packet_info); diff --git a/src/strategies/AnalogSampling/AnalogSampling.h b/src/strategies/AnalogSampling/AnalogSampling.h index ecdf9359ab..2487d68809 100644 --- a/src/strategies/AnalogSampling/AnalogSampling.h +++ b/src/strategies/AnalogSampling/AnalogSampling.h @@ -157,6 +157,13 @@ class AnalogSampling { }; + /* Function called at the end of a frame reception: */ + + void frame_end(bool ack) { + (void)ack; // Avoid unused parameter warning + }; + + /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { diff --git a/src/strategies/Any/Any.h b/src/strategies/Any/Any.h index 9583024c93..764e63a26a 100644 --- a/src/strategies/Any/Any.h +++ b/src/strategies/Any/Any.h @@ -53,6 +53,13 @@ class Any { bool can_start() { return s->can_start(); } + /* Function called at the end of a frame reception: */ + + void frame_end(bool ack) { + (void)ack; // Avoid unused parameter warning + }; + + /* Returns the maximum number of attempts for each transmission: */ uint8_t get_max_attempts() { return s->get_max_attempts(); } diff --git a/src/strategies/DualUDP/DualUDP.h b/src/strategies/DualUDP/DualUDP.h index d5f00b1fc2..157a10e26b 100644 --- a/src/strategies/DualUDP/DualUDP.h +++ b/src/strategies/DualUDP/DualUDP.h @@ -245,6 +245,12 @@ class DualUDP { DUDP_MINIMUM_SEND_INTERVAL_MS); }; + /* Function called at the end of a frame reception: */ + + void frame_end(bool ack) { + (void)ack; // Avoid unused parameter warning + }; + /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { return DUDP_MAX_RETRIES; }; diff --git a/src/strategies/ESPNOW/ESPNOW.h b/src/strategies/ESPNOW/ESPNOW.h index d5696c5560..52b8567aa5 100644 --- a/src/strategies/ESPNOW/ESPNOW.h +++ b/src/strategies/ESPNOW/ESPNOW.h @@ -155,6 +155,13 @@ class ESPNOW { bool can_start() { return check_en(); }; + /* Function called at the end of a frame reception: */ + + void frame_end(bool ack) { + (void)ack; // Avoid unused parameter warning + }; + + /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { return 10; }; diff --git a/src/strategies/EthernetTCP/EthernetTCP.h b/src/strategies/EthernetTCP/EthernetTCP.h index 021d6f60d7..326d4c8288 100644 --- a/src/strategies/EthernetTCP/EthernetTCP.h +++ b/src/strategies/EthernetTCP/EthernetTCP.h @@ -98,6 +98,13 @@ class EthernetTCP { }; + /* Function called at the end of a frame reception: */ + + void frame_end(bool ack) { + (void)ack; // Avoid unused parameter warning + }; + + /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { diff --git a/src/strategies/GlobalUDP/GlobalUDP.h b/src/strategies/GlobalUDP/GlobalUDP.h index 9337a14b4b..a0c42faca1 100644 --- a/src/strategies/GlobalUDP/GlobalUDP.h +++ b/src/strategies/GlobalUDP/GlobalUDP.h @@ -149,6 +149,13 @@ class GlobalUDP { bool can_start() { return check_udp(); }; + + /* Function called at the end of a frame reception: */ + + void frame_end(bool ack) { + (void)ack; // Avoid unused parameter warning + }; + /* Returns the maximum number of attempts for each transmission: */ diff --git a/src/strategies/LocalFile/LocalFile.h b/src/strategies/LocalFile/LocalFile.h index 7a997e04ad..f51dbc2983 100644 --- a/src/strategies/LocalFile/LocalFile.h +++ b/src/strategies/LocalFile/LocalFile.h @@ -225,6 +225,10 @@ class LocalFile { return openContentFile(); }; + void frame_end(bool ack) { + (void)ack; // Avoid unused parameter warning + }; + void handle_collision() { PJON_DELAY(10); }; diff --git a/src/strategies/LocalUDP/LocalUDP.h b/src/strategies/LocalUDP/LocalUDP.h index 807f60f956..f21f6840cc 100644 --- a/src/strategies/LocalUDP/LocalUDP.h +++ b/src/strategies/LocalUDP/LocalUDP.h @@ -78,6 +78,13 @@ class LocalUDP { bool can_start() { return check_udp(); }; + /* Function called at the end of a frame reception: */ + + void frame_end(bool ack) { + (void)ack; // Avoid unused parameter warning + }; + + /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { return 10; }; diff --git a/src/strategies/MQTTTranslate/MQTTTranslate.h b/src/strategies/MQTTTranslate/MQTTTranslate.h index f82fb788fa..6b62663b57 100644 --- a/src/strategies/MQTTTranslate/MQTTTranslate.h +++ b/src/strategies/MQTTTranslate/MQTTTranslate.h @@ -343,6 +343,13 @@ class MQTTTranslate { bool can_start() { return mqttclient.connect(); }; + /* Function called at the end of a frame reception: */ + + void frame_end(bool ack) { + (void)ack; // Avoid unused parameter warning + }; + + /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { return 0; }; diff --git a/src/strategies/OverSampling/OverSampling.h b/src/strategies/OverSampling/OverSampling.h index ef2939e49f..4dbe51ef4d 100644 --- a/src/strategies/OverSampling/OverSampling.h +++ b/src/strategies/OverSampling/OverSampling.h @@ -92,6 +92,11 @@ class OverSampling { return true; }; + /* Function called at the end of a frame reception: */ + + void frame_end(bool ack) { + (void)ack; // Avoid unused parameter warning + }; /* Returns the maximum number of attempts for each transmission: */ diff --git a/src/strategies/README.md b/src/strategies/README.md index 2a00f035f9..43660b2b8b 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -38,6 +38,10 @@ bool can_start() ``` Returns `true` if the medium is free for use and `false` if the medium is busy. +```cpp +void frame_end(bool ack) +``` +It is called when the frame reception ends and it receives a boolean that signals if the acknowledgment is requested or not. ```cpp void handle_collision() ``` diff --git a/src/strategies/ThroughLoRa/ThroughLora.h b/src/strategies/ThroughLoRa/ThroughLora.h index b92e129472..bcc89078de 100644 --- a/src/strategies/ThroughLoRa/ThroughLora.h +++ b/src/strategies/ThroughLoRa/ThroughLora.h @@ -116,6 +116,12 @@ class ThroughLora { return true; }; + /* Function called at the end of a frame reception: */ + + void frame_end(bool ack) { + (void)ack; // Avoid unused parameter warning + }; + /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { diff --git a/src/strategies/ThroughSerial/ThroughSerial.h b/src/strategies/ThroughSerial/ThroughSerial.h index 27f4c8a1f6..e7455f8082 100644 --- a/src/strategies/ThroughSerial/ThroughSerial.h +++ b/src/strategies/ThroughSerial/ThroughSerial.h @@ -109,6 +109,11 @@ class ThroughSerial { return TS_RECEIVE_TIME; }; + /* Function called at the end of a frame reception: */ + + void frame_end(bool ack) { + (void)ack; // Avoid unused parameter warning + }; /* Handle a collision: */ From d010541b46ed46994dc8553c073a9a052a50c885 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jul 2020 16:22:12 +0200 Subject: [PATCH 159/323] PJDL spec update, bus is kept busy by receiver (breaking compatibility) --- .../SoftwareBitBang/SoftwareBitBang.h | 62 +++++++++++-------- src/strategies/SoftwareBitBang/Timing.h | 16 ++++- .../specification/PJDL-specification-v5.0.md | 40 ++++++------ 3 files changed, 68 insertions(+), 50 deletions(-) diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index 599b324d03..ed8db383c6 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -28,7 +28,8 @@ // Used to signal communication failure #define SWBB_FAIL 65535 - +// Used to signal acknowledgment +#define SWBB_ACK 6 // Used for pin handling #define SWBB_NOT_ASSIGNED 255 @@ -143,19 +144,27 @@ class SoftwareBitBang { bit and transmits PJON_ACK */ uint16_t receive_response() { - if(_output_pin != _input_pin && _output_pin != SWBB_NOT_ASSIGNED) - PJON_IO_WRITE(_output_pin, LOW); - uint16_t response; + uint16_t response = SWBB_FAIL; uint32_t time = PJON_MICROS(); - while((uint32_t)(PJON_MICROS() - time) < _timeout) { - PJON_IO_WRITE(_input_pin, LOW); + PJON_IO_PULL_DOWN(_input_pin); + while( // Wait for the receiver's high to arrive + ((uint32_t)(PJON_MICROS() - time) < (SWBB_LATENCY * 2)) && + !PJON_IO_READ(_input_pin) + ); + time = PJON_MICROS(); + while( // Wait for low + ((uint32_t)(PJON_MICROS() - time) < _timeout) && + PJON_IO_READ(_input_pin) + ); + if((uint32_t)(PJON_MICROS() - time) < _timeout) { + time = PJON_MICROS(); + while( // Wait for incoming sync + ( + (uint32_t)(PJON_MICROS() - time) < + (SWBB_BIT_WIDTH + SWBB_DEVIATION) + ) && !PJON_IO_READ(_input_pin) + ); if(sync()) response = receive_byte(); - if(response == SWBB_FAIL) { - PJON_IO_MODE(_output_pin, OUTPUT); - PJON_IO_WRITE(_output_pin, HIGH); - PJON_DELAY_MICROSECONDS(SWBB_BIT_WIDTH / 2); - PJON_IO_PULL_DOWN(_output_pin); - } else return response; } return response; }; @@ -182,6 +191,13 @@ class SoftwareBitBang { return 1; }; + /* Function called at the end of a frame reception: */ + + void frame_end(bool ack) { + if(!ack) return; + PJON_IO_MODE(_output_pin, OUTPUT); + PJON_IO_WRITE(_output_pin, HIGH); + }; /* Every byte is prepended with a synchronization pad made by 2 padding bits. The first is a longer than standard logic 1 followed @@ -218,21 +234,13 @@ class SoftwareBitBang { incoming bit and transmits its response */ void send_response(uint8_t response) { - PJON_IO_PULL_DOWN(_input_pin); - uint32_t time = PJON_MICROS(); - while( // If initially low Wait for the next high - ((uint32_t)(PJON_MICROS() - time) < SWBB_BIT_WIDTH) && - !PJON_IO_READ(_input_pin) - ); - time = PJON_MICROS(); - while( // If high Wait for low - ((uint32_t)(PJON_MICROS() - time) < (SWBB_BIT_WIDTH / 2)) && - PJON_IO_READ(_input_pin) - ); - PJON_IO_MODE(_output_pin, OUTPUT); - pulse(1); - send_byte(response); - PJON_IO_PULL_DOWN(_output_pin); + PJON_IO_WRITE(_output_pin, LOW); + PJON_DELAY_MICROSECONDS(SWBB_BIT_WIDTH); + if(response == SWBB_ACK) { + pulse(1); + send_byte(response); + PJON_IO_PULL_DOWN(_output_pin); + } }; diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 1007a80e7e..1a05b08029 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -58,7 +58,7 @@ #if F_CPU == 16000000L /* Working on pin: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, A0, A1 */ #define SWBB_BIT_WIDTH 22 - #define SWBB_BIT_SPACER 56 + #define SWBB_BIT_SPACER 61 #define SWBB_ACCEPTANCE 30 #define SWBB_READ_DELAY 7 #endif @@ -95,7 +95,7 @@ #define SWBB_BIT_WIDTH 40 #define SWBB_BIT_SPACER 106 #define SWBB_ACCEPTANCE 53 - #define SWBB_READ_DELAY 8 + #define SWBB_READ_DELAY 6 #endif #if SWBB_MODE == 2 /* Working on pin: 2, 4, 8, 12 @@ -271,6 +271,9 @@ #ifndef SWBB_LATENCY #define SWBB_LATENCY 13 #endif + #ifndef SWBB_DEVIATION + #define SWBB_DEVIATION 10 + #endif #endif #if SWBB_MODE == 2 #ifndef SWBB_BIT_WIDTH @@ -288,6 +291,9 @@ #ifndef SWBB_LATENCY #define SWBB_LATENCY 10 #endif + #ifndef SWBB_DEVIATION + #define SWBB_DEVIATION 9 + #endif #endif #if SWBB_MODE == 3 #ifndef SWBB_BIT_WIDTH @@ -305,6 +311,9 @@ #ifndef SWBB_LATENCY #define SWBB_LATENCY 8 #endif + #ifndef SWBB_DEVIATION + #define SWBB_DEVIATION 7 + #endif #endif #if SWBB_MODE == 4 #ifndef SWBB_BIT_WIDTH @@ -322,6 +331,9 @@ #ifndef SWBB_LATENCY #define SWBB_LATENCY 5 #endif + #ifndef SWBB_DEVIATION + #define SWBB_DEVIATION 7 + #endif #endif /* Synchronous acknowledgement response offset. diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index fc64ba3761..009bf35d56 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -16,8 +16,7 @@ ## PJDL v5.0 ``` Invented by Giovanni Blu Mitolo with the support -of Fred Larsen, Julio Aguirre and Gerhard Sittig -Publication date: 10/04/2010 Latest revision: 21/07/2020 +Publication date: 10/04/2010 Latest revision: 24/07/2020 Related implementation: /src/strategies/SoftwareBitBang/ Compatible versions: PJON v13.0 and following Released into the public domain @@ -29,7 +28,7 @@ Released into the public domain 29/12/2018 3.0 - Medium access control info, mode 4 03/07/2019 4.0 - Response initializer 10/03/2020 4.1 - Maximum range experimentally determined -17/07/2020 5.0 - Timeout and keep-busy signal fixed, deviation added +17/07/2020 5.0 - Bus is kept busy by the receiver, deviation added ``` PJDL (Padded Jittering Data Link) is an asynchronous serial data link for low-data-rate applications that supports both master-slave and multi-master communication over a common conductive medium. PJDL can be easily implemented on limited microcontrollers with low clock accuracy and can operate directly using a single input-output pin. @@ -52,18 +51,18 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above ### Communication modes The proposed communication modes are the result of years of testing and optimization and have been selected to be easily supported by limited microcontrollers: -| Mode | Bandwidth | Range | Pad bit | Data bit | Keep busy bit | Latency | Timeout | -| ---- | ------------------ | ----- | ------- | -------- | ------------- | ------- | ------- | -| 1 | 1.97kB/s - 15808Bd | 2000m | 110µs | 44µs | 22µs | 13µs | 20µs/B | -| 2 | 2.21kB/s - 17696Bd | 1600m | 92µs | 40µs | 20µs | 10µs | 20µs/B | -| 3 | 3.10kB/s - 24844Bd | 1200m | 70µs | 28µs | 14µs | 8µs | 20µs/B | -| 4 | 3.34kB/s - 26755Bd | 800m | 65µs | 26µs | 13µs | 5µs | 20µs/B | +| Mode | Bandwidth | Range | Pad bit | Data bit | Latency | +| ---- | ------------------ | ----- | ------- | -------- | ------- | +| 1 | 1.97kB/s - 15808Bd | 2000m | 110µs | 44µs | 13µs | +| 2 | 2.21kB/s - 17696Bd | 1600m | 92µs | 40µs | 10µs | +| 3 | 3.10kB/s - 24844Bd | 1200m | 70µs | 28µs | 8µs | +| 4 | 3.34kB/s - 26755Bd | 800m | 65µs | 26µs | 5µs | The following table specifies the maximum acceptable deviation of each bit type: -| Max data bit octet deviation | Max padding bit deviation | Max keep busy bit deviation | -| ---------------------------- | ------------------------- | --------------------------- | -| +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | +- 10µs | +| Max data bit octet deviation | Max padding bit deviation | +| ---------------------------- | ------------------------- | +| +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. @@ -105,20 +104,19 @@ When a frame is received a low performance microcontroller with an inaccurate cl ### Synchronous response A frame transmission can be optionally followed by a synchronous response sent by its recipient. Between frame transmission and a synchronous response there is a variable time which duration is influenced by latency. ```cpp -Transmission end Response +Transmission Response ______ ______ ______ _____ | BYTE || BYTE || BYTE | CRC COMPUTATION / LATENCY | ACK | |------||------||------|---------------------------|-----| | || || | | 6 | |______||______||______| |_____| ``` -In order to avoid other devices to detect the medium free for use and disrupt an ongoing exchange, the sender cyclically transmits a high 1/2 data bit and consequently attempts to receive a response for up to twice the maximum expected latency. The receiver must synchronize to the falling edge of the last high bit and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If the response is not transmitted or not received the transmitter continues to keep busy the medium up to the response timeout. +The receiver must drive the bus high as soon as the last byte of the frame is received and must continue to keep it high until the higher protocol layer has verified the frame's consistency. When that has occurred the receiver must transmit a low data bit, and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If the higher protocol layer detects an error the receiver must drive the bus low. ```cpp -Transmission end Keep busy Response - ______ ______ ______ _ _ _ _ _ _ ____ _____ -| BYTE || BYTE || BYTE | | | | | | | | | | | | |SYNC| ACK | -|------||------||------| | | | | | | | | | | | |----|-----| -| || || | | | | | | | | | | | | | | 6 | -|______||______||______|_| |_| |_| |_| |_| |_| |____|_____| +Transmission Latency Receiver keeps busy Response + ______ ______ x2 ____________________ ____ _____ +| BYTE || BYTE | | | |SYNC| ACK | +|------||------| | | |----|-----| +| || | | | | | 6 | +|______||______|_________| |_|____|_____| ``` -The response timeout is determined multiplying 20µs by the length of the frame and then adding the maximum expected latency. From 2a08ec728ca820b7fe748e2d41ae9f7de401410b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jul 2020 16:29:42 +0200 Subject: [PATCH 160/323] PJDL specification added missing contributors remark, minor fix --- .../SoftwareBitBang/specification/PJDL-specification-v5.0.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index 009bf35d56..6fac293f99 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -16,6 +16,7 @@ ## PJDL v5.0 ``` Invented by Giovanni Blu Mitolo with the support +of Fred Larsen, Julio Aguirre and Gerhard Sittig Publication date: 10/04/2010 Latest revision: 24/07/2020 Related implementation: /src/strategies/SoftwareBitBang/ Compatible versions: PJON v13.0 and following @@ -111,7 +112,7 @@ Transmission Response | || || | | 6 | |______||______||______| |_____| ``` -The receiver must drive the bus high as soon as the last byte of the frame is received and must continue to keep it high until the higher protocol layer has verified the frame's consistency. When that has occurred the receiver must transmit a low data bit, and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If the higher protocol layer detects an error the receiver must drive the bus low. +The receiver must drive the bus high as soon as the last byte of the frame is received and must continue to keep it high until it has verified the frame's consistency. When that has occurred the receiver must transmit a low data bit, and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If an error is detected the receiver must drive the bus low. ```cpp Transmission Latency Receiver keeps busy Response ______ ______ x2 ____________________ ____ _____ From 47258c996515486fceddaf5afc6977e5f159377b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jul 2020 22:13:29 +0200 Subject: [PATCH 161/323] SoftwareBitBang timing and tests update --- src/strategies/SoftwareBitBang/Timing.h | 2 +- .../tests/NetworkAnalysis-10s.md | 55 ++++++++++++------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 1a05b08029..81e6eabc7f 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -49,7 +49,7 @@ #if F_CPU == 16000000L /* Working on pin: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, A0, A1 */ #define SWBB_BIT_WIDTH 24 - #define SWBB_BIT_SPACER 84 + #define SWBB_BIT_SPACER 66 #define SWBB_ACCEPTANCE 30 #define SWBB_READ_DELAY 8 #endif diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index 51e6618539..b94d97a404 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -7,35 +7,50 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | UNO/Nano | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | | UNO/Nano | 12 | Mega | 12 | 1740kB/s | 58 | 100% | | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | -| UNO/Nano | 12 | ESP8266 80MHz | D1 | 1620kB/s | 57 | 98.28% | -| UNO/Nano | 12 | ESP32 | 12 | 1770kB/s | 59 | 99.80% | -| UNO/Nano | PB9 | Blue pill | 12 | 1770kB/s | 59 | 100% | +| UNO/Nano | 12 | ESP8266 80MHz | D1 | 1740kB/s | 58 | 98.28% | +| UNO/Nano | 12 | ESP32 40MHz | 12 | 1770kB/s | 59 | 100% | +| UNO/Nano | 12 | ESP32 80MHz | 12 | 1770kB/s | 59 | 100% | +| UNO/Nano | 12 | ESP32 40MHz | 25 | 1770kB/s | 59 | 100% | +| UNO/Nano | 12 | ESP32 80MHz | 25 | 1770kB/s | 59 | 100% | +| UNO/Nano | PB9 | Blue pill | 12 | | | | | Leonardo/Micro | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | -| Leonardo/Micro | 12 | ESP32 | 12 | 1620kB/s | 55 | 91.00% | +| Leonardo/Micro | 12 | ESP32 | 12 | 1560kB/s | 52 | 86.54% | | Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | | Mega | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | -| Mega | 12 | Leonardo/Micro | 12 | 1725kB/s | 57.5 | 100% | +| Mega | 12 | Leonardo/Micro | 12 | 1725kB/s | 58 | 100% | | Mega | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | -| Mega | 12 | ESP8266 160MHz | D1 | 1755kB/s | 58.5 | 99.5% | -| Mega | 12 | ESP32 | 12 | 1770kB/s | 59 | 99.00% | +| Mega | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | +| Mega | 12 | ESP32 40MHz | 12 | 1755kB/s | 58.5 | 99.5% | +| Mega | 12 | ESP32 80MHz | 12 | 1755kB/s | 58.5 | 99.5% | +| Mega | 12 | ESP32 40Hz | 25 | 1755kB/s | 58.5 | 99.5% | +| Mega | 12 | ESP32 80Hz | 25 | 1755kB/s | 58.5 | 99.5% | | Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | +| Mega | 12 | SAMD21 | D1 | 1770kB/s | 59 | 100% | | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | ESP8266 160MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| ESP8266 80MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | +| ESP8266 160MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | ESP8266 80MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | | ESP8266 160MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | -| ESP8266 80MHz | D1 | Blue pill | PB9 | 1764kB/s | 58.8 | 98% | -| ESP8266 160MHz | D1 | Blue pill | PB9 | 1764kB/s | 58.8 | 98% | -| ESP32 | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| ESP32 | 12 | Leonardo/Micro | 12 | 1620kB/s | 55 | 91.00% | -| ESP32 | 12 | Blue pill | PB9 | 0kB/s | 0 | 0% | -| SAMD21 | D0 | Mega | 12 | 1770kB/s | 59 | 100% | -| SAMD21 | D0 | Leonardo/Micro | 12 | 1590kB/s | 53 | 88.68% | +| ESP8266 80MHz | D1 | Blue pill | PB9 | | | | +| ESP8266 160MHz | D1 | Blue pill | PB9 | | | | +| ESP32 80MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| ESP32 40MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| ESP32 40MHz | 12 | Leonardo/Micro | 12 | 1777kB/s | 59 | 100% | +| ESP32 80MHz | 12 | Leonardo/Micro | 12 | 1777kB/s | 59 | 100% | +| ESP32 | 12 | Blue pill | PB9 | | | | +| SAMD21 | D0 | Mega | 12 | 1770kB/s | 58 | 98.28% | +| SAMD21 | D0 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | SAMD21 | D0 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| SAMD21 | D0 | Blue pill | PB9 | 1800kB/s | 60 | 100% | -| Blue pill | PB9 | Blue pill | PB9 | 1860kB/s | 62 | 100% | -| Blue pill | PB9 | UNO/Nano | 12 | 1770kB/s | 59 | 99.5% | -| Blue pill | PB9 | SAMD | 12 | 1830kB/s | 61 | 100% | -| Blue pill | PB9 | ESP8266 | D1 | 0kB/s | 0 | 0% | -| Blue pill | PB9 | ESP32 | 12 | 0kB/s | 0 | 0% | +| SAMD21 | D0 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | +| SAMD21 | D0 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | +| SAMD21 | D0 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | +| SAMD21 | D0 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | +| SAMD21 | D0 | Blue pill | PB9 | | | | +| Blue pill | PB9 | Blue pill | PB9 | | | | +| Blue pill | PB9 | UNO/Nano | 12 | | | | +| Blue pill | PB9 | SAMD | 12 | | | | +| Blue pill | PB9 | ESP8266 | D1 | | | | +| Blue pill | PB9 | ESP32 | 12 | | | | From 372b42a1553875c2e9318f7fc6303e6c01bed473 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jul 2020 22:29:18 +0200 Subject: [PATCH 162/323] send_packet returns PJON_FAIL if the response is not PJON_ACK --- src/PJON.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 562eb3cc58..dd657b0925 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -571,12 +571,7 @@ class PJON { !(payload[1] & PJON_ACK_REQ_BIT) || _mode == PJON_SIMPLEX ) return PJON_ACK; - uint16_t response = strategy.receive_response(); - if( - response == PJON_ACK || - response == PJON_FAIL - ) return response; - else return PJON_BUSY; + return (strategy.receive_response() == PJON_ACK) ? PJON_ACK : PJON_FAIL; }; /* Compose and transmit a packet passing its info as parameters: */ From 87563173cb6cf5267394fc3607f02919b4bb7348 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jul 2020 22:30:41 +0200 Subject: [PATCH 163/323] random_seed -> _random_seed (now private) --- src/PJON.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index dd657b0925..cabb2fe534 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -81,7 +81,6 @@ class PJON { uint8_t data[PJON_PACKET_MAX_LENGTH]; PJON_Packet_Info last_packet_info; PJON_Packet packets[PJON_MAX_PACKETS]; - uint8_t random_seed = A0; PJON_Endpoint tx; #if(PJON_INCLUDE_PACKET_ID) @@ -141,7 +140,7 @@ class PJON { /* Begin function to be called after initialization: */ void begin() { - PJON_RANDOM_SEED(PJON_ANALOG_READ(random_seed) + tx.id); + PJON_RANDOM_SEED(PJON_ANALOG_READ(_random_seed) + tx.id); strategy.begin(tx.id); #if(PJON_INCLUDE_PACKET_ID) _packet_id_seed = PJON_RANDOM(65535) + tx.id; @@ -790,7 +789,7 @@ class PJON { /* Set the analog pin used as a seed for random generation: */ void set_random_seed(uint8_t seed) { - random_seed = seed; + _random_seed = seed; }; /* Pass as a parameter a receiver function you previously defined in your @@ -921,6 +920,7 @@ class PJON { PJON_Error _error; bool _mode; uint16_t _packet_id_seed = 0; + uint8_t _random_seed = A0; PJON_Receiver _receiver; uint8_t _recursion = 0; bool _router = false; From c726c875d3275cddab38556dc05492f51eee4a40 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jul 2020 22:31:30 +0200 Subject: [PATCH 164/323] PJON.h minor fix --- src/PJON.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index cabb2fe534..15eeb2b593 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -305,9 +305,8 @@ class PJON { !PJON_INCLUDE_PORT && (data[1] & PJON_PORT_BIT) ) || ( (!PJON_INCLUDE_MAC && mac) || (mac && !(data[1] & PJON_CRC_BIT)) - ) + ) || (drop && !mac) ) return PJON_BUSY; - if(drop && !mac) return PJON_BUSY; extended_length = data[i] & PJON_EXT_LEN_BIT; overhead = packet_overhead(data[i]); } From 84b6e80eb9f9a3f4e395c613f25e6a24c35d606f Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 25 Jul 2020 21:09:13 +0200 Subject: [PATCH 165/323] mode column added to SoftwareBitBang tests --- .../tests/NetworkAnalysis-10s.md | 106 +++++++++--------- .../tests/PacketSeparationTest.md | 30 ++--- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index b94d97a404..3d7a29e82e 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -1,56 +1,56 @@ ## NetworkAnalysis This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis) example for 10 seconds and averaging the obtained series of results. -| TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | -|----------------|-----|----------------|-----|-----------|-----------|--------------| -| UNO/Nano | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | -| UNO/Nano | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | -| UNO/Nano | 12 | Mega | 12 | 1740kB/s | 58 | 100% | -| UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | -| UNO/Nano | 12 | ESP8266 80MHz | D1 | 1740kB/s | 58 | 98.28% | -| UNO/Nano | 12 | ESP32 40MHz | 12 | 1770kB/s | 59 | 100% | -| UNO/Nano | 12 | ESP32 80MHz | 12 | 1770kB/s | 59 | 100% | -| UNO/Nano | 12 | ESP32 40MHz | 25 | 1770kB/s | 59 | 100% | -| UNO/Nano | 12 | ESP32 80MHz | 25 | 1770kB/s | 59 | 100% | -| UNO/Nano | PB9 | Blue pill | 12 | | | | -| Leonardo/Micro | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | -| Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | -| Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | -| Leonardo/Micro | 12 | ESP32 | 12 | 1560kB/s | 52 | 86.54% | -| Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | -| Mega | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | -| Mega | 12 | Leonardo/Micro | 12 | 1725kB/s | 58 | 100% | -| Mega | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | -| Mega | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | -| Mega | 12 | ESP32 40MHz | 12 | 1755kB/s | 58.5 | 99.5% | -| Mega | 12 | ESP32 80MHz | 12 | 1755kB/s | 58.5 | 99.5% | -| Mega | 12 | ESP32 40Hz | 25 | 1755kB/s | 58.5 | 99.5% | -| Mega | 12 | ESP32 80Hz | 25 | 1755kB/s | 58.5 | 99.5% | -| Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | -| Mega | 12 | SAMD21 | D1 | 1770kB/s | 59 | 100% | -| ESP8266 80MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| ESP8266 160MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| ESP8266 80MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | -| ESP8266 160MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | -| ESP8266 80MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | -| ESP8266 160MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | -| ESP8266 80MHz | D1 | Blue pill | PB9 | | | | -| ESP8266 160MHz | D1 | Blue pill | PB9 | | | | -| ESP32 80MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| ESP32 40MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| ESP32 40MHz | 12 | Leonardo/Micro | 12 | 1777kB/s | 59 | 100% | -| ESP32 80MHz | 12 | Leonardo/Micro | 12 | 1777kB/s | 59 | 100% | -| ESP32 | 12 | Blue pill | PB9 | | | | -| SAMD21 | D0 | Mega | 12 | 1770kB/s | 58 | 98.28% | -| SAMD21 | D0 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | -| SAMD21 | D0 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| SAMD21 | D0 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | -| SAMD21 | D0 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | -| SAMD21 | D0 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | -| SAMD21 | D0 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | -| SAMD21 | D0 | Blue pill | PB9 | | | | -| Blue pill | PB9 | Blue pill | PB9 | | | | -| Blue pill | PB9 | UNO/Nano | 12 | | | | -| Blue pill | PB9 | SAMD | 12 | | | | -| Blue pill | PB9 | ESP8266 | D1 | | | | -| Blue pill | PB9 | ESP32 | 12 | | | | +| MODE | TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | +|------|----------------|-----|----------------|-----|-----------|-----------|--------------| +| 1 | UNO/Nano | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | +| 1 | UNO/Nano | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | +| 1 | UNO/Nano | 12 | Mega | 12 | 1740kB/s | 58 | 100% | +| 1 | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | +| 1 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1740kB/s | 58 | 98.28% | +| 1 | UNO/Nano | 12 | ESP32 40MHz | 12 | 1770kB/s | 59 | 100% | +| 1 | UNO/Nano | 12 | ESP32 80MHz | 12 | 1770kB/s | 59 | 100% | +| 1 | UNO/Nano | 12 | ESP32 40MHz | 25 | 1770kB/s | 59 | 100% | +| 1 | UNO/Nano | 12 | ESP32 80MHz | 25 | 1770kB/s | 59 | 100% | +| 1 | UNO/Nano | PB9 | Blue pill | 12 | | | | +| 1 | Leonardo/Micro | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | +| 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | +| 1 | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | +| 1 | Leonardo/Micro | 12 | ESP32 | 12 | 1560kB/s | 52 | 86.54% | +| 1 | Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | +| 1 | Mega | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | +| 1 | Mega | 12 | Leonardo/Micro | 12 | 1725kB/s | 58 | 100% | +| 1 | Mega | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | +| 1 | Mega | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | +| 1 | Mega | 12 | ESP32 40MHz | 12 | 1755kB/s | 58.5 | 99.5% | +| 1 | Mega | 12 | ESP32 80MHz | 12 | 1755kB/s | 58.5 | 99.5% | +| 1 | Mega | 12 | ESP32 40Hz | 25 | 1755kB/s | 58.5 | 99.5% | +| 1 | Mega | 12 | ESP32 80Hz | 25 | 1755kB/s | 58.5 | 99.5% | +| 1 | Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | +| 1 | Mega | 12 | SAMD21 | D1 | 1770kB/s | 59 | 100% | +| 1 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP8266 80MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP8266 160MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP8266 80MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP8266 160MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP8266 80MHz | D1 | Blue pill | PB9 | | | | +| 1 | ESP8266 160MHz | D1 | Blue pill | PB9 | | | | +| 1 | ESP32 80MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP32 40MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | 1777kB/s | 59 | 100% | +| 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | 1777kB/s | 59 | 100% | +| 1 | ESP32 | 12 | Blue pill | PB9 | | | | +| 1 | SAMD21 | D0 | Mega | 12 | 1770kB/s | 58 | 98.28% | +| 1 | SAMD21 | D0 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | +| 1 | SAMD21 | D0 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| 1 | SAMD21 | D0 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | +| 1 | SAMD21 | D0 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | +| 1 | SAMD21 | D0 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | +| 1 | SAMD21 | D0 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | +| 1 | SAMD21 | D0 | Blue pill | PB9 | | | | +| 1 | Blue pill | PB9 | Blue pill | PB9 | | | | +| 1 | Blue pill | PB9 | UNO/Nano | 12 | | | | +| 1 | Blue pill | PB9 | SAMD | 12 | | | | +| 1 | Blue pill | PB9 | ESP8266 | D1 | | | | +| 1 | Blue pill | PB9 | ESP32 | 12 | | | | diff --git a/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md b/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md index 497b7d7aee..722869fbc5 100644 --- a/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md +++ b/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md @@ -2,18 +2,18 @@ This table was filled running the [PacketSeparationTest](../../../../examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest) example for 10 seconds and averaging the obtained series of results. -| TX |PIN | RX |PIN | RESULT | -|---------------------|----|------------------|----|-----------------------------------------------------| -| UNO/Nano | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 100% | -| UNO/Nano | 12 | Mega | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.999% | -| UNO/Nano | 12 | ESP32 | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | -| Mega | 12 | Leonardo | 12 | SWBB_ACCEPTANCE 53 Accuracy: 100% | -| Mega | 12 | ESP32 | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | -| Leonardo | 12 | Leonardo | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | -| Leonardo | 12 | ESP32 | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | -| Leonardo | 12 | Mega | 12 | SWBB_ACCEPTANCE 53 Accuracy: 100% | -| Leonardo | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.999% | -| Mega | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.999% | -| SAMD21 | D0 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.89% | -| SAMD21 | D0 | Mega | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.88% | -| ESP32 | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.87% | +| MODE | TX |PIN | RX |PIN | RESULT | +|------|---------------------|----|------------------|----|-----------------------------------------------------| +| 1 | UNO/Nano | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 100% | +| 1 | UNO/Nano | 12 | Mega | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.999% | +| 1 | UNO/Nano | 12 | ESP32 | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | +| 1 | Mega | 12 | Leonardo | 12 | SWBB_ACCEPTANCE 53 Accuracy: 100% | +| 1 | Mega | 12 | ESP32 | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | +| 1 | Leonardo | 12 | Leonardo | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | +| 1 | Leonardo | 12 | ESP32 | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | +| 1 | Leonardo | 12 | Mega | 12 | SWBB_ACCEPTANCE 53 Accuracy: 100% | +| 1 | Leonardo | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.999% | +| 1 | Mega | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.999% | +| 1 | SAMD21 | D0 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.89% | +| 1 | SAMD21 | D0 | Mega | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.88% | +| 1 | ESP32 | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.87% | From 4fe9da20aeda1c504e21bea3efd7106a1718c393 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 25 Jul 2020 23:03:24 +0200 Subject: [PATCH 166/323] SoftwareBitBang bluepill tests and timing update added thanks to @jcallano --- src/strategies/SoftwareBitBang/Timing.h | 4 ++-- .../tests/NetworkAnalysis-10s.md | 21 ++++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 81e6eabc7f..824bd80318 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -224,8 +224,8 @@ #if F_CPU == 72000000L #define SWBB_BIT_WIDTH 43.5 #define SWBB_BIT_SPACER 109.5 - #define SWBB_ACCEPTANCE 50 - #define SWBB_READ_DELAY -8 + #define SWBB_ACCEPTANCE 75 + #define SWBB_READ_DELAY -6 #endif #endif #if SWBB_MODE == 2 diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index 3d7a29e82e..0c7713c9e1 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -12,7 +12,7 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | UNO/Nano | 12 | ESP32 80MHz | 12 | 1770kB/s | 59 | 100% | | 1 | UNO/Nano | 12 | ESP32 40MHz | 25 | 1770kB/s | 59 | 100% | | 1 | UNO/Nano | 12 | ESP32 80MHz | 25 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | PB9 | Blue pill | 12 | | | | +| 1 | UNO/Nano | PB9 | Blue pill | 12 | 1800kB/s | 60 | 100% | | 1 | Leonardo/Micro | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | | 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | | 1 | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | @@ -34,13 +34,13 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | ESP8266 160MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | 1 | ESP8266 80MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | | 1 | ESP8266 160MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 80MHz | D1 | Blue pill | PB9 | | | | -| 1 | ESP8266 160MHz | D1 | Blue pill | PB9 | | | | +| 1 | ESP8266 80MHz | D1 | Blue pill | PB9 | 1791kB/s | 61 | 97.9% | +| 1 | ESP8266 160MHz | D1 | Blue pill | PB9 | 1860kB/s | 59 | 100% | | 1 | ESP32 80MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | 1 | ESP32 40MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | 1777kB/s | 59 | 100% | | 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | 1777kB/s | 59 | 100% | -| 1 | ESP32 | 12 | Blue pill | PB9 | | | | +| 1 | ESP32 | 12 | Blue pill | PB9 | 1800kB/s | 60 | 100% | | 1 | SAMD21 | D0 | Mega | 12 | 1770kB/s | 58 | 98.28% | | 1 | SAMD21 | D0 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | 1 | SAMD21 | D0 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | @@ -48,9 +48,10 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | SAMD21 | D0 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | | 1 | SAMD21 | D0 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | | 1 | SAMD21 | D0 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | -| 1 | SAMD21 | D0 | Blue pill | PB9 | | | | -| 1 | Blue pill | PB9 | Blue pill | PB9 | | | | -| 1 | Blue pill | PB9 | UNO/Nano | 12 | | | | -| 1 | Blue pill | PB9 | SAMD | 12 | | | | -| 1 | Blue pill | PB9 | ESP8266 | D1 | | | | -| 1 | Blue pill | PB9 | ESP32 | 12 | | | | +| 1 | SAMD21 | D0 | Blue pill | PB9 | 1800kB/s | 60 | 100% | +| 1 | Blue pill | PB9 | Blue pill | PB9 | 1830kB/s | 62 | 100% | +| 1 | Blue pill | PB9 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| 1 | Blue pill | PB9 | SAMD | 12 | 1830kB/s | 61 | 100% | +| 1 | Blue pill | PB9 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 99% | +| 1 | Blue pill | PB9 | ESP8266 160MHz | D1 | 1800kB/s | 60 | 100% | +| 1 | Blue pill | PB9 | ESP32 | 12 | 1830kB/s | 61 | 100% | From 188ca3b03d3c560476cf83a904c60ebf3b178eaa Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 25 Jul 2020 23:14:04 +0200 Subject: [PATCH 167/323] SoftwareBitBang performance remarks updated with new values --- src/strategies/SoftwareBitBang/SoftwareBitBang.h | 6 +++--- src/strategies/SoftwareBitBang/Timing.h | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index ed8db383c6..88b7664d53 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -34,10 +34,10 @@ #define SWBB_NOT_ASSIGNED 255 /* Transmission speed modes (see Timing.h) - MODE 1: 1.95kB/s - 15625Bd + MODE 1: 1.97kB/s - 15808Bd MODE 2: 2.21kB/s - 17696Bd - MODE 3: 2.94kB/s - 23529Bd - MODE 4: 3.40kB/s - 27210Bd */ + MODE 3: 3.10kB/s - 24844Bd + MODE 4: 3.34kB/s - 26755Bd */ #include "Timing.h" // Recommended receive time for this strategy, in microseconds diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 824bd80318..d0f2068035 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -13,10 +13,10 @@ Benchmarks can be executed using NetworkAnalysis and SpeedTest examples. - MODE 1: 1.95kB/s - 15625Bd + MODE 1: 1.97kB/s - 15808Bd MODE 2: 2.21kB/s - 17696Bd - MODE 3: 2.97kB/s - 23529Bd - MODE 4: 3.40kB/s - 27210Bd + MODE 3: 3.10kB/s - 24844Bd + MODE 4: 3.34kB/s - 26755Bd Use the same pin number on all connected devices to achieve maximum timing efficiency, not all different pin combinations work nominally @@ -175,14 +175,14 @@ Added full support to MODE 1 (80 and 160MHz) - 12/06/2018 */ #if (F_CPU == 80000000L) /* Working on pin: D1 or GPIO 5 */ - #define SWBB_BIT_WIDTH 43.5 + #define SWBB_BIT_WIDTH 43.5 #define SWBB_BIT_SPACER 109.5 #define SWBB_ACCEPTANCE 52 #define SWBB_READ_DELAY -6 #endif #if (F_CPU == 160000000L) /* Working on pin: D1 or GPIO 5 */ - #define SWBB_BIT_WIDTH 44 + #define SWBB_BIT_WIDTH 44 #define SWBB_BIT_SPACER 110 #define SWBB_ACCEPTANCE 52 #define SWBB_READ_DELAY -6 From 698eceb82d961305dd5a1174f0d9f15f4065cd6d Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 25 Jul 2020 23:19:44 +0200 Subject: [PATCH 168/323] strategies README minor fix --- src/strategies/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/strategies/README.md b/src/strategies/README.md index 43660b2b8b..28e3f12b40 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -93,6 +93,7 @@ class YourStrategyName { uint32_t back_off(uint8_t attempts) { }; bool begin(uint8_t did) { }; bool can_start() { }; + void frame_end(bool ack) { }; uint8_t get_max_attempts() { }; uint16_t get_receive_time() { }; uint16_t receive_frame(uint8_t *data, uint16_t max_length) { }; From 709506fb9c485078e38969ca93aee92084affd2b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jul 2020 14:53:42 +0200 Subject: [PATCH 169/323] frame_end strategy method removed --- src/PJON.h | 20 +++++++------------ .../AnalogSampling/AnalogSampling.h | 7 ------- src/strategies/Any/Any.h | 9 +-------- src/strategies/DualUDP/DualUDP.h | 6 ------ src/strategies/ESPNOW/ESPNOW.h | 7 ------- src/strategies/EthernetTCP/EthernetTCP.h | 9 +-------- src/strategies/GlobalUDP/GlobalUDP.h | 7 ------- src/strategies/LocalFile/LocalFile.h | 4 ---- src/strategies/LocalUDP/LocalUDP.h | 7 ------- src/strategies/MQTTTranslate/MQTTTranslate.h | 7 ------- src/strategies/OverSampling/OverSampling.h | 6 ------ src/strategies/README.md | 5 ----- .../SoftwareBitBang/SoftwareBitBang.h | 7 ------- src/strategies/ThroughLoRa/ThroughLora.h | 6 ------ src/strategies/ThroughSerial/ThroughSerial.h | 8 +------- 15 files changed, 10 insertions(+), 105 deletions(-) diff --git a/src/PJON.h b/src/PJON.h index 15eeb2b593..01d6121062 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -341,29 +341,22 @@ class PJON { } } - bool nak = false, ack = - (data[1] & PJON_ACK_REQ_BIT) && (data[0] != PJON_BROADCAST) && - (_mode != PJON_SIMPLEX) && !_router - ; - - strategy.frame_end(ack); - if( PJON_crc8::compute(data, 3 + extended_length) != data[3 + extended_length] - ) nak = true; + ) return PJON_NAK; if(data[1] & PJON_CRC_BIT) { if( !PJON_crc32::compare( PJON_crc32::compute(data, length - 4), data + (length - 4) ) - ) nak = true; + ) return PJON_NAK; } else if(PJON_crc8::compute(data, length - 1) != data[length - 1]) - nak = true; + return PJON_NAK; #if(PJON_INCLUDE_MAC) - if(!nak && mac && (length > 15) && !_router) + if(mac && (length > 15) && !_router) if(!PJONTools::id_equality(data + (overhead - 16), tx.mac, 6)) if(! PJONTools::id_equality( @@ -373,8 +366,9 @@ class PJON { ) return PJON_BUSY; #endif - if(ack) strategy.send_response((nak) ? PJON_NAK : PJON_ACK); - if(nak) return PJON_NAK; + if(data[1] & PJON_ACK_REQ_BIT && data[0] != PJON_BROADCAST) + if((_mode != PJON_SIMPLEX) && !_router) + strategy.send_response(PJON_ACK); parse(data, last_packet_info); diff --git a/src/strategies/AnalogSampling/AnalogSampling.h b/src/strategies/AnalogSampling/AnalogSampling.h index 2487d68809..ecdf9359ab 100644 --- a/src/strategies/AnalogSampling/AnalogSampling.h +++ b/src/strategies/AnalogSampling/AnalogSampling.h @@ -157,13 +157,6 @@ class AnalogSampling { }; - /* Function called at the end of a frame reception: */ - - void frame_end(bool ack) { - (void)ack; // Avoid unused parameter warning - }; - - /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { diff --git a/src/strategies/Any/Any.h b/src/strategies/Any/Any.h index 764e63a26a..daa31afb2b 100644 --- a/src/strategies/Any/Any.h +++ b/src/strategies/Any/Any.h @@ -50,14 +50,7 @@ class Any { /* Check if the channel is free for transmission */ - bool can_start() { return s->can_start(); } - - - /* Function called at the end of a frame reception: */ - - void frame_end(bool ack) { - (void)ack; // Avoid unused parameter warning - }; + bool can_start() { return s->can_start(); }; /* Returns the maximum number of attempts for each transmission: */ diff --git a/src/strategies/DualUDP/DualUDP.h b/src/strategies/DualUDP/DualUDP.h index 157a10e26b..d5f00b1fc2 100644 --- a/src/strategies/DualUDP/DualUDP.h +++ b/src/strategies/DualUDP/DualUDP.h @@ -245,12 +245,6 @@ class DualUDP { DUDP_MINIMUM_SEND_INTERVAL_MS); }; - /* Function called at the end of a frame reception: */ - - void frame_end(bool ack) { - (void)ack; // Avoid unused parameter warning - }; - /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { return DUDP_MAX_RETRIES; }; diff --git a/src/strategies/ESPNOW/ESPNOW.h b/src/strategies/ESPNOW/ESPNOW.h index 52b8567aa5..d5696c5560 100644 --- a/src/strategies/ESPNOW/ESPNOW.h +++ b/src/strategies/ESPNOW/ESPNOW.h @@ -155,13 +155,6 @@ class ESPNOW { bool can_start() { return check_en(); }; - /* Function called at the end of a frame reception: */ - - void frame_end(bool ack) { - (void)ack; // Avoid unused parameter warning - }; - - /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { return 10; }; diff --git a/src/strategies/EthernetTCP/EthernetTCP.h b/src/strategies/EthernetTCP/EthernetTCP.h index 326d4c8288..e30bef86da 100644 --- a/src/strategies/EthernetTCP/EthernetTCP.h +++ b/src/strategies/EthernetTCP/EthernetTCP.h @@ -96,14 +96,7 @@ class EthernetTCP { bool can_start() { return link.device_id() != 0; }; - - - /* Function called at the end of a frame reception: */ - - void frame_end(bool ack) { - (void)ack; // Avoid unused parameter warning - }; - + /* Returns the maximum number of attempts for each transmission: */ diff --git a/src/strategies/GlobalUDP/GlobalUDP.h b/src/strategies/GlobalUDP/GlobalUDP.h index a0c42faca1..ac390dc045 100644 --- a/src/strategies/GlobalUDP/GlobalUDP.h +++ b/src/strategies/GlobalUDP/GlobalUDP.h @@ -148,14 +148,7 @@ class GlobalUDP { /* Check if the channel is free for transmission */ bool can_start() { return check_udp(); }; - - /* Function called at the end of a frame reception: */ - - void frame_end(bool ack) { - (void)ack; // Avoid unused parameter warning - }; - /* Returns the maximum number of attempts for each transmission: */ diff --git a/src/strategies/LocalFile/LocalFile.h b/src/strategies/LocalFile/LocalFile.h index f51dbc2983..7a997e04ad 100644 --- a/src/strategies/LocalFile/LocalFile.h +++ b/src/strategies/LocalFile/LocalFile.h @@ -225,10 +225,6 @@ class LocalFile { return openContentFile(); }; - void frame_end(bool ack) { - (void)ack; // Avoid unused parameter warning - }; - void handle_collision() { PJON_DELAY(10); }; diff --git a/src/strategies/LocalUDP/LocalUDP.h b/src/strategies/LocalUDP/LocalUDP.h index f21f6840cc..807f60f956 100644 --- a/src/strategies/LocalUDP/LocalUDP.h +++ b/src/strategies/LocalUDP/LocalUDP.h @@ -78,13 +78,6 @@ class LocalUDP { bool can_start() { return check_udp(); }; - /* Function called at the end of a frame reception: */ - - void frame_end(bool ack) { - (void)ack; // Avoid unused parameter warning - }; - - /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { return 10; }; diff --git a/src/strategies/MQTTTranslate/MQTTTranslate.h b/src/strategies/MQTTTranslate/MQTTTranslate.h index 6b62663b57..f82fb788fa 100644 --- a/src/strategies/MQTTTranslate/MQTTTranslate.h +++ b/src/strategies/MQTTTranslate/MQTTTranslate.h @@ -343,13 +343,6 @@ class MQTTTranslate { bool can_start() { return mqttclient.connect(); }; - /* Function called at the end of a frame reception: */ - - void frame_end(bool ack) { - (void)ack; // Avoid unused parameter warning - }; - - /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { return 0; }; diff --git a/src/strategies/OverSampling/OverSampling.h b/src/strategies/OverSampling/OverSampling.h index 4dbe51ef4d..0b67a8fc22 100644 --- a/src/strategies/OverSampling/OverSampling.h +++ b/src/strategies/OverSampling/OverSampling.h @@ -92,12 +92,6 @@ class OverSampling { return true; }; - /* Function called at the end of a frame reception: */ - - void frame_end(bool ack) { - (void)ack; // Avoid unused parameter warning - }; - /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { diff --git a/src/strategies/README.md b/src/strategies/README.md index 28e3f12b40..2a00f035f9 100644 --- a/src/strategies/README.md +++ b/src/strategies/README.md @@ -38,10 +38,6 @@ bool can_start() ``` Returns `true` if the medium is free for use and `false` if the medium is busy. -```cpp -void frame_end(bool ack) -``` -It is called when the frame reception ends and it receives a boolean that signals if the acknowledgment is requested or not. ```cpp void handle_collision() ``` @@ -93,7 +89,6 @@ class YourStrategyName { uint32_t back_off(uint8_t attempts) { }; bool begin(uint8_t did) { }; bool can_start() { }; - void frame_end(bool ack) { }; uint8_t get_max_attempts() { }; uint16_t get_receive_time() { }; uint16_t receive_frame(uint8_t *data, uint16_t max_length) { }; diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index 88b7664d53..c408e619d3 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -191,13 +191,6 @@ class SoftwareBitBang { return 1; }; - /* Function called at the end of a frame reception: */ - - void frame_end(bool ack) { - if(!ack) return; - PJON_IO_MODE(_output_pin, OUTPUT); - PJON_IO_WRITE(_output_pin, HIGH); - }; /* Every byte is prepended with a synchronization pad made by 2 padding bits. The first is a longer than standard logic 1 followed diff --git a/src/strategies/ThroughLoRa/ThroughLora.h b/src/strategies/ThroughLoRa/ThroughLora.h index bcc89078de..b92e129472 100644 --- a/src/strategies/ThroughLoRa/ThroughLora.h +++ b/src/strategies/ThroughLoRa/ThroughLora.h @@ -116,12 +116,6 @@ class ThroughLora { return true; }; - /* Function called at the end of a frame reception: */ - - void frame_end(bool ack) { - (void)ack; // Avoid unused parameter warning - }; - /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { diff --git a/src/strategies/ThroughSerial/ThroughSerial.h b/src/strategies/ThroughSerial/ThroughSerial.h index e7455f8082..2c18b2b716 100644 --- a/src/strategies/ThroughSerial/ThroughSerial.h +++ b/src/strategies/ThroughSerial/ThroughSerial.h @@ -108,13 +108,7 @@ class ThroughSerial { static uint16_t get_receive_time() { return TS_RECEIVE_TIME; }; - - /* Function called at the end of a frame reception: */ - - void frame_end(bool ack) { - (void)ack; // Avoid unused parameter warning - }; - + /* Handle a collision: */ void handle_collision() { From 79bc1d8b59be014ab604320500ba057621563e5e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jul 2020 14:58:57 +0200 Subject: [PATCH 170/323] PJDL v5.0 revert to response phase driven by tx --- .../SoftwareBitBang/SoftwareBitBang.h | 52 +++++++++---------- .../specification/PJDL-specification-v5.0.md | 39 +++++++------- 2 files changed, 45 insertions(+), 46 deletions(-) diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index c408e619d3..d79f5ad6f2 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -28,8 +28,6 @@ // Used to signal communication failure #define SWBB_FAIL 65535 -// Used to signal acknowledgment -#define SWBB_ACK 6 // Used for pin handling #define SWBB_NOT_ASSIGNED 255 @@ -144,27 +142,19 @@ class SoftwareBitBang { bit and transmits PJON_ACK */ uint16_t receive_response() { + if(_output_pin != _input_pin && _output_pin != SWBB_NOT_ASSIGNED) + PJON_IO_WRITE(_output_pin, LOW); uint16_t response = SWBB_FAIL; uint32_t time = PJON_MICROS(); - PJON_IO_PULL_DOWN(_input_pin); - while( // Wait for the receiver's high to arrive - ((uint32_t)(PJON_MICROS() - time) < (SWBB_LATENCY * 2)) && - !PJON_IO_READ(_input_pin) - ); - time = PJON_MICROS(); - while( // Wait for low - ((uint32_t)(PJON_MICROS() - time) < _timeout) && - PJON_IO_READ(_input_pin) - ); - if((uint32_t)(PJON_MICROS() - time) < _timeout) { - time = PJON_MICROS(); - while( // Wait for incoming sync - ( - (uint32_t)(PJON_MICROS() - time) < - (SWBB_BIT_WIDTH + SWBB_DEVIATION) - ) && !PJON_IO_READ(_input_pin) - ); + while((uint32_t)(PJON_MICROS() - time) < _timeout) { + PJON_IO_WRITE(_input_pin, LOW); if(sync()) response = receive_byte(); + if(response == SWBB_FAIL) { + PJON_IO_MODE(_output_pin, OUTPUT); + PJON_IO_WRITE(_output_pin, HIGH); + PJON_DELAY_MICROSECONDS(SWBB_BIT_WIDTH / 4); + PJON_IO_PULL_DOWN(_output_pin); + } else return response; } return response; }; @@ -227,13 +217,21 @@ class SoftwareBitBang { incoming bit and transmits its response */ void send_response(uint8_t response) { - PJON_IO_WRITE(_output_pin, LOW); - PJON_DELAY_MICROSECONDS(SWBB_BIT_WIDTH); - if(response == SWBB_ACK) { - pulse(1); - send_byte(response); - PJON_IO_PULL_DOWN(_output_pin); - } + PJON_IO_PULL_DOWN(_input_pin); + uint32_t time = PJON_MICROS(); + while( // If initially low Wait for the next high + ((uint32_t)(PJON_MICROS() - time) < SWBB_BIT_WIDTH) && + !PJON_IO_READ(_input_pin) + ); + time = PJON_MICROS(); + while( // If high Wait for low + ((uint32_t)(PJON_MICROS() - time) < (SWBB_BIT_WIDTH / 4)) && + PJON_IO_READ(_input_pin) + ); + PJON_IO_MODE(_output_pin, OUTPUT); + pulse(1); + send_byte(response); + PJON_IO_PULL_DOWN(_output_pin); }; diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index 6fac293f99..986a3b2bc8 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -52,18 +52,18 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above ### Communication modes The proposed communication modes are the result of years of testing and optimization and have been selected to be easily supported by limited microcontrollers: -| Mode | Bandwidth | Range | Pad bit | Data bit | Latency | -| ---- | ------------------ | ----- | ------- | -------- | ------- | -| 1 | 1.97kB/s - 15808Bd | 2000m | 110µs | 44µs | 13µs | -| 2 | 2.21kB/s - 17696Bd | 1600m | 92µs | 40µs | 10µs | -| 3 | 3.10kB/s - 24844Bd | 1200m | 70µs | 28µs | 8µs | -| 4 | 3.34kB/s - 26755Bd | 800m | 65µs | 26µs | 5µs | +| Mode | Bandwidth | Range | Pad bit | Data bit | Keep busy bit | Latency | Timeout | +| ---- | ------------------ | ----- | ------- | -------- | ------------- | ------- | ------- | +| 1 | 1.97kB/s - 15808Bd | 2000m | 110µs | 44µs | 11µs | 13µs | 20µs/B | +| 2 | 2.21kB/s - 17696Bd | 1600m | 92µs | 40µs | 10µs | 10µs | 20µs/B | +| 3 | 3.10kB/s - 24844Bd | 1200m | 70µs | 28µs | 7µs | 8µs | 20µs/B | +| 4 | 3.34kB/s - 26755Bd | 800m | 65µs | 26µs | 6.5µs | 5µs | 20µs/B | The following table specifies the maximum acceptable deviation of each bit type: -| Max data bit octet deviation | Max padding bit deviation | -| ---------------------------- | ------------------------- | -| +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | +| Max data bit octet deviation | Max padding bit deviation | Max keep busy bit deviation | +| ---------------------------- | ------------------------- | --------------------------- | +| +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | +- keep busy bit / 2 | ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. @@ -76,7 +76,7 @@ The reception technique is based on 3 steps: 2. Synchronize with its falling edge 3. Ensure it is followed by a low data bit -If so reception starts, if not, interference, synchronization loss or simply absence of communication is detected. The high padding bit is 2.5 times longer than data bits because with this ratio ambiguity between padding bits and 2 or 3 consecutive data bits is avoided even with an overall deviation of up to +- (data bit / 4) - 1. +If so reception starts, if not, interference, synchronization loss or simply absence of communication is detected. The high padding bit is 2.5 times longer than data bits because with this ratio ambiguity between padding bits and 2 or 3 consecutive data bits is avoided even with an overall deviation of up to +- (data bit / 4) - 1. The receiver must accept a synchronization pad also if it is prepended by a 0 of up to (data bit / 4) - 1 microseconds. ```cpp ___________ ___________________________ @@ -86,7 +86,7 @@ If so reception starts, if not, interference, synchronization loss or simply abs | 1 | 0 | 1 | 0 0 | 1 | 0 | 1 1 | 0 | |_______|___|___|_____|___|___|_____|___| ``` -The synchronization pad adds overhead although it includes synchronization along with the data and eliminates the need of a dedicated clock line. The presence of the synchronization pad between each byte also ensures that a frame composed of a series of bytes with decimal value 0 can be transmitted safely without risk of collision. +The synchronization pad adds overhead although it includes synchronization along with the data and eliminates the need of a dedicated clock line. The presence of the synchronization pad between each byte also ensures that a frame composed of a series of bytes with decimal value 0 can be transmitted safely without risk of collision. ### Frame transmission Before a frame transmission the communication medium's state is analysed, if high communication is detected and collision is avoided, if low for a duration of one byte plus a small random time, frame transmission starts with an initializer composed by 3 consecutive synchronization pads followed by data bytes. The synchronization pad is used for both byte and frame initialization to reduce the implementation complexity. @@ -105,19 +105,20 @@ When a frame is received a low performance microcontroller with an inaccurate cl ### Synchronous response A frame transmission can be optionally followed by a synchronous response sent by its recipient. Between frame transmission and a synchronous response there is a variable time which duration is influenced by latency. ```cpp -Transmission Response +Transmission end Response ______ ______ ______ _____ | BYTE || BYTE || BYTE | CRC COMPUTATION / LATENCY | ACK | |------||------||------|---------------------------|-----| | || || | | 6 | |______||______||______| |_____| ``` -The receiver must drive the bus high as soon as the last byte of the frame is received and must continue to keep it high until it has verified the frame's consistency. When that has occurred the receiver must transmit a low data bit, and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If an error is detected the receiver must drive the bus low. +In order to avoid other devices to detect the medium free for use and disrupt an ongoing exchange, the sender cyclically transmits a high 1/4 data bit and consequently attempts to receive a response for up to twice the maximum expected latency. The receiver must synchronize to the falling edge of the last high bit and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If the response is not transmitted or not received the transmitter continues to keep busy the medium up to the response timeout. ```cpp -Transmission Latency Receiver keeps busy Response - ______ ______ x2 ____________________ ____ _____ -| BYTE || BYTE | | | |SYNC| ACK | -|------||------| | | |----|-----| -| || | | | | | 6 | -|______||______|_________| |_|____|_____| +Transmission end Keep busy Response + ______ ______ ______ _ _ _ _ _ _ ____ _____ +| BYTE || BYTE || BYTE | | | | | | | | | | | | |SYNC| ACK | +|------||------||------| | | | | | | | | | | | |----|-----| +| || || | | | | | | | | | | | | | | 6 | +|______||______||______|_| |_| |_| |_| |_| |_| |____|_____| ``` +The response timeout is determined multiplying 20µs by the length of the frame and then adding the maximum expected latency. From 6a4e440c68b031276b51c6b8858ab5f552078bc0 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jul 2020 20:25:34 +0200 Subject: [PATCH 171/323] PJDL v5.0 keep busy pulse deviation update --- .../specification/PJDL-specification-v5.0.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index 986a3b2bc8..70f9e1ae3d 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -29,7 +29,7 @@ Released into the public domain 29/12/2018 3.0 - Medium access control info, mode 4 03/07/2019 4.0 - Response initializer 10/03/2020 4.1 - Maximum range experimentally determined -17/07/2020 5.0 - Bus is kept busy by the receiver, deviation added +17/07/2020 5.0 - Response timeout, deviation added ``` PJDL (Padded Jittering Data Link) is an asynchronous serial data link for low-data-rate applications that supports both master-slave and multi-master communication over a common conductive medium. PJDL can be easily implemented on limited microcontrollers with low clock accuracy and can operate directly using a single input-output pin. @@ -61,9 +61,9 @@ The proposed communication modes are the result of years of testing and optimiza The following table specifies the maximum acceptable deviation of each bit type: -| Max data bit octet deviation | Max padding bit deviation | Max keep busy bit deviation | +| Max data bit octet deviation | Max sync. pad deviation | Max keep busy bit deviation | | ---------------------------- | ------------------------- | --------------------------- | -| +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | +- keep busy bit / 2 | +| +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | + 10µs | ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. From ea52b3b7618777eb8e316eebfe604875e9856c13 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jul 2020 23:10:10 +0200 Subject: [PATCH 172/323] SoftwareBitBang NetworkAnalysis test results update --- .../tests/NetworkAnalysis-10s.md | 95 ++++++++++--------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index 0c7713c9e1..c8524b918a 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -4,54 +4,57 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | MODE | TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | |------|----------------|-----|----------------|-----|-----------|-----------|--------------| | 1 | UNO/Nano | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | +| 1 | UNO/Nano | 11 | UNO/Nano | 11 | 1710kB/s | 57 | 100% | +| 1 | UNO/Nano | 10 | UNO/Nano | 10 | 1710kB/s | 57 | 100% | | 1 | UNO/Nano | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | | 1 | UNO/Nano | 12 | Mega | 12 | 1740kB/s | 58 | 100% | | 1 | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1740kB/s | 58 | 98.28% | -| 1 | UNO/Nano | 12 | ESP32 40MHz | 12 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | ESP32 80MHz | 12 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | ESP32 40MHz | 25 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | ESP32 80MHz | 25 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | PB9 | Blue pill | 12 | 1800kB/s | 60 | 100% | -| 1 | Leonardo/Micro | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | -| 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | -| 1 | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | -| 1 | Leonardo/Micro | 12 | ESP32 | 12 | 1560kB/s | 52 | 86.54% | -| 1 | Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | +| 1 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | +| 1 | UNO/Nano | 12 | ESP32 40MHz | 12 | | | | +| 1 | UNO/Nano | 12 | ESP32 80MHz | 12 | | | | +| 1 | UNO/Nano | 12 | ESP32 40MHz | 25 | | | | +| 1 | UNO/Nano | 12 | ESP32 80MHz | 25 | | | | +| 1 | UNO/Nano | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | +| 1 | UNO/Nano | 12 | Blue pill | PB9 | | | | +| 1 | Leonardo/Micro | 12 | UNO/Nano | 12 | | | | +| 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | | | | +| 1 | Leonardo/Micro | 12 | Mega | 12 | | | | +| 1 | Leonardo/Micro | 12 | ESP32 | 12 | | | | +| 1 | Leonardo/Micro | 12 | SAMD21 | D0 | | | | | 1 | Mega | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | -| 1 | Mega | 12 | Leonardo/Micro | 12 | 1725kB/s | 58 | 100% | -| 1 | Mega | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | -| 1 | Mega | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | -| 1 | Mega | 12 | ESP32 40MHz | 12 | 1755kB/s | 58.5 | 99.5% | -| 1 | Mega | 12 | ESP32 80MHz | 12 | 1755kB/s | 58.5 | 99.5% | -| 1 | Mega | 12 | ESP32 40Hz | 25 | 1755kB/s | 58.5 | 99.5% | -| 1 | Mega | 12 | ESP32 80Hz | 25 | 1755kB/s | 58.5 | 99.5% | +| 1 | Mega | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | +| 1 | Mega | 12 | ESP8266 80MHz | D1 | | | | +| 1 | Mega | 12 | ESP8266 160MHz | D1 | | | | +| 1 | Mega | 12 | ESP32 40MHz | 12 | | | | +| 1 | Mega | 12 | ESP32 80MHz | 12 | | | | +| 1 | Mega | 12 | ESP32 40Hz | 25 | | | | +| 1 | Mega | 12 | ESP32 80Hz | 25 | | | | | 1 | Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | -| 1 | Mega | 12 | SAMD21 | D1 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 80MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 160MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 80MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 160MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 80MHz | D1 | Blue pill | PB9 | 1791kB/s | 61 | 97.9% | -| 1 | ESP8266 160MHz | D1 | Blue pill | PB9 | 1860kB/s | 59 | 100% | -| 1 | ESP32 80MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP32 40MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | 1777kB/s | 59 | 100% | -| 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | 1777kB/s | 59 | 100% | -| 1 | ESP32 | 12 | Blue pill | PB9 | 1800kB/s | 60 | 100% | -| 1 | SAMD21 | D0 | Mega | 12 | 1770kB/s | 58 | 98.28% | -| 1 | SAMD21 | D0 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | -| 1 | SAMD21 | D0 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| 1 | SAMD21 | D0 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | -| 1 | SAMD21 | D0 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | -| 1 | SAMD21 | D0 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | -| 1 | SAMD21 | D0 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | -| 1 | SAMD21 | D0 | Blue pill | PB9 | 1800kB/s | 60 | 100% | -| 1 | Blue pill | PB9 | Blue pill | PB9 | 1830kB/s | 62 | 100% | -| 1 | Blue pill | PB9 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| 1 | Blue pill | PB9 | SAMD | 12 | 1830kB/s | 61 | 100% | -| 1 | Blue pill | PB9 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 99% | -| 1 | Blue pill | PB9 | ESP8266 160MHz | D1 | 1800kB/s | 60 | 100% | -| 1 | Blue pill | PB9 | ESP32 | 12 | 1830kB/s | 61 | 100% | +| 1 | Mega | 12 | SAMD21 | D1 | | | | +| 1 | ESP8266 80MHz | D1 | UNO/Nano | 12 | | | | +| 1 | ESP8266 160MHz | D1 | UNO/Nano | 12 | | | | +| 1 | ESP8266 80MHz | D1 | Leonardo/Micro | 12 | | | | +| 1 | ESP8266 160MHz | D1 | Leonardo/Micro | 12 | | | | +| 1 | ESP8266 80MHz | D1 | Mega | 12 | | | | +| 1 | ESP8266 160MHz | D1 | Mega | 12 | | | | +| 1 | ESP8266 80MHz | D1 | Blue pill | PB9 | | | | +| 1 | ESP8266 160MHz | D1 | Blue pill | PB9 | | | | +| 1 | ESP32 80MHz | 12 | UNO/Nano | 12 | | | | +| 1 | ESP32 40MHz | 12 | UNO/Nano | 12 | | | | +| 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | | | | +| 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | | | | +| 1 | ESP32 | 12 | Blue pill | PB9 | | | | +| 1 | SAMD21 | D0 | Mega | 12 | | | | +| 1 | SAMD21 | D0 | Leonardo/Micro | 12 | | | | +| 1 | SAMD21 | D0 | UNO/Nano | 12 | | | | +| 1 | SAMD21 | D0 | ESP32 40MHz | 12 | | | | +| 1 | SAMD21 | D0 | ESP32 80MHz | 12 | | | | +| 1 | SAMD21 | D0 | ESP32 40MHz | 25 | | | | +| 1 | SAMD21 | D0 | ESP32 80MHz | 25 | | | | +| 1 | SAMD21 | D0 | Blue pill | PB9 | | | | +| 1 | Blue pill | PB9 | Blue pill | PB9 | | | | +| 1 | Blue pill | PB9 | UNO/Nano | 12 | | | | +| 1 | Blue pill | PB9 | SAMD | 12 | | | | +| 1 | Blue pill | PB9 | ESP8266 80MHz | D1 | | | | +| 1 | Blue pill | PB9 | ESP8266 160MHz | D1 | | | | +| 1 | Blue pill | PB9 | ESP32 | 12 | | | | From 768f1a7c01732c4ba57de8d052804c2bc17a26c5 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jul 2020 19:27:23 +0200 Subject: [PATCH 173/323] SoftwareBitBang NetworkAnalysis bluepill results by @jcallano --- .../tests/NetworkAnalysis-10s.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index c8524b918a..6f8f611703 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -15,7 +15,7 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | UNO/Nano | 12 | ESP32 40MHz | 25 | | | | | 1 | UNO/Nano | 12 | ESP32 80MHz | 25 | | | | | 1 | UNO/Nano | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | Blue pill | PB9 | | | | +| 1 | UNO/Nano | 12 | Blue pill | PB9 | 1770kB/s | 59 | 100% | | 1 | Leonardo/Micro | 12 | UNO/Nano | 12 | | | | | 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | | | | | 1 | Leonardo/Micro | 12 | Mega | 12 | | | | @@ -43,7 +43,7 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | ESP32 40MHz | 12 | UNO/Nano | 12 | | | | | 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | | | | | 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | | | | -| 1 | ESP32 | 12 | Blue pill | PB9 | | | | +| 1 | ESP32 | 12 | Blue pill | PB9 | 1800kB/s | 60 | 100% | | 1 | SAMD21 | D0 | Mega | 12 | | | | | 1 | SAMD21 | D0 | Leonardo/Micro | 12 | | | | | 1 | SAMD21 | D0 | UNO/Nano | 12 | | | | @@ -51,10 +51,10 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | SAMD21 | D0 | ESP32 80MHz | 12 | | | | | 1 | SAMD21 | D0 | ESP32 40MHz | 25 | | | | | 1 | SAMD21 | D0 | ESP32 80MHz | 25 | | | | -| 1 | SAMD21 | D0 | Blue pill | PB9 | | | | -| 1 | Blue pill | PB9 | Blue pill | PB9 | | | | -| 1 | Blue pill | PB9 | UNO/Nano | 12 | | | | -| 1 | Blue pill | PB9 | SAMD | 12 | | | | -| 1 | Blue pill | PB9 | ESP8266 80MHz | D1 | | | | -| 1 | Blue pill | PB9 | ESP8266 160MHz | D1 | | | | -| 1 | Blue pill | PB9 | ESP32 | 12 | | | | +| 1 | SAMD21 | D0 | Blue pill | PB9 | 1860kB/s | 61 | 100% | +| 1 | Blue pill | PB9 | Blue pill | PB9 | 1830kB/s | 61 | 100% | +| 1 | Blue pill | PB9 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | +| 1 | Blue pill | PB9 | SAMD | 12 | 1830kB/s | 61 | 100% | +| 1 | Blue pill | PB9 | ESP8266 80MHz | D1 | 1788kB/s | 60 | 99.33% | +| 1 | Blue pill | PB9 | ESP8266 160MHz | D1 | 1800kB/s | 60 | 100% | +| 1 | Blue pill | PB9 | ESP32 | 12 | 1830kB/s | 61 | 100% | From 79620aeaf36cad00204e8da72467595208e9df30 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jul 2020 00:24:10 +0200 Subject: [PATCH 174/323] SoftwareBitBang MODE 2 and 3 timing and tests added --- src/strategies/SoftwareBitBang/Timing.h | 16 +++---- .../tests/NetworkAnalysis-10s.md | 47 ++++++++++++------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index d0f2068035..8a99656912 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -230,18 +230,18 @@ #endif #if SWBB_MODE == 2 #if F_CPU == 72000000L - #define SWBB_BIT_WIDTH 39 - #define SWBB_BIT_SPACER 91 - #define SWBB_ACCEPTANCE 47 - #define SWBB_READ_DELAY 3 + #define SWBB_BIT_WIDTH 39.5 + #define SWBB_BIT_SPACER 91.5 + #define SWBB_ACCEPTANCE 53 + #define SWBB_READ_DELAY -8 #endif #endif #if SWBB_MODE == 3 #if F_CPU == 72000000L - #define SWBB_BIT_WIDTH 27 - #define SWBB_BIT_SPACER 87 - #define SWBB_ACCEPTANCE 45 - #define SWBB_READ_DELAY 2 + #define SWBB_BIT_WIDTH 27.5 + #define SWBB_BIT_SPACER 69.5 + #define SWBB_ACCEPTANCE 33 + #define SWBB_READ_DELAY -5 #endif #endif #if SWBB_MODE == 4 diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index 6f8f611703..9863d3eca2 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -10,25 +10,25 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | UNO/Nano | 12 | Mega | 12 | 1740kB/s | 58 | 100% | | 1 | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | | 1 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | ESP32 40MHz | 12 | | | | -| 1 | UNO/Nano | 12 | ESP32 80MHz | 12 | | | | -| 1 | UNO/Nano | 12 | ESP32 40MHz | 25 | | | | -| 1 | UNO/Nano | 12 | ESP32 80MHz | 25 | | | | +| 1 | UNO/Nano | 12 | ESP32 40MHz | 12 | 1770kB/s | 59 | 100% | +| 1 | UNO/Nano | 12 | ESP32 80MHz | 12 | 1770kB/s | 59 | 100% | +| 1 | UNO/Nano | 12 | ESP32 40MHz | 25 | 1770kB/s | 59 | 100% | +| 1 | UNO/Nano | 12 | ESP32 80MHz | 25 | 1770kB/s | 59 | 100% | | 1 | UNO/Nano | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | | 1 | UNO/Nano | 12 | Blue pill | PB9 | 1770kB/s | 59 | 100% | -| 1 | Leonardo/Micro | 12 | UNO/Nano | 12 | | | | +| 1 | Leonardo/Micro | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | | 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | | | | -| 1 | Leonardo/Micro | 12 | Mega | 12 | | | | +| 1 | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | | 1 | Leonardo/Micro | 12 | ESP32 | 12 | | | | | 1 | Leonardo/Micro | 12 | SAMD21 | D0 | | | | | 1 | Mega | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | | 1 | Mega | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | | 1 | Mega | 12 | ESP8266 80MHz | D1 | | | | | 1 | Mega | 12 | ESP8266 160MHz | D1 | | | | -| 1 | Mega | 12 | ESP32 40MHz | 12 | | | | -| 1 | Mega | 12 | ESP32 80MHz | 12 | | | | -| 1 | Mega | 12 | ESP32 40Hz | 25 | | | | -| 1 | Mega | 12 | ESP32 80Hz | 25 | | | | +| 1 | Mega | 12 | ESP32 40MHz | 12 | 1710kB/s | 57 | 96.49% | +| 1 | Mega | 12 | ESP32 80MHz | 12 | 1710kB/s | 57 | 96.49% | +| 1 | Mega | 12 | ESP32 40MHz | 25 | 1710kB/s | 57 | 96.49% | +| 1 | Mega | 12 | ESP32 80MHz | 25 | 1710kB/s | 57 | 96.49% | | 1 | Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | | 1 | Mega | 12 | SAMD21 | D1 | | | | | 1 | ESP8266 80MHz | D1 | UNO/Nano | 12 | | | | @@ -44,17 +44,28 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | | | | | 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | | | | | 1 | ESP32 | 12 | Blue pill | PB9 | 1800kB/s | 60 | 100% | -| 1 | SAMD21 | D0 | Mega | 12 | | | | -| 1 | SAMD21 | D0 | Leonardo/Micro | 12 | | | | -| 1 | SAMD21 | D0 | UNO/Nano | 12 | | | | -| 1 | SAMD21 | D0 | ESP32 40MHz | 12 | | | | -| 1 | SAMD21 | D0 | ESP32 80MHz | 12 | | | | -| 1 | SAMD21 | D0 | ESP32 40MHz | 25 | | | | -| 1 | SAMD21 | D0 | ESP32 80MHz | 25 | | | | +| 1 | SAMD21 | D0 | Mega | 12 | 1770kB/s | 59 | 100% | +| 1 | SAMD21 | D0 | Leonardo/Micro | 12 | 1710kB/s | 57 | 100% | +| 1 | SAMD21 | D0 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| 1 | SAMD21 | D0 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | +| 1 | SAMD21 | D0 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | +| 1 | SAMD21 | D0 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | +| 1 | SAMD21 | D0 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | | 1 | SAMD21 | D0 | Blue pill | PB9 | 1860kB/s | 61 | 100% | | 1 | Blue pill | PB9 | Blue pill | PB9 | 1830kB/s | 61 | 100% | | 1 | Blue pill | PB9 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | | 1 | Blue pill | PB9 | SAMD | 12 | 1830kB/s | 61 | 100% | | 1 | Blue pill | PB9 | ESP8266 80MHz | D1 | 1788kB/s | 60 | 99.33% | | 1 | Blue pill | PB9 | ESP8266 160MHz | D1 | 1800kB/s | 60 | 100% | -| 1 | Blue pill | PB9 | ESP32 | 12 | 1830kB/s | 61 | 100% | +| 2 | Blue pill | PB9 | Blue pill | PB9 | 2040kB/s | 68 | 100% | +| 2 | Blue pill | PB9 | UNO/Nano | 12 | 2010kB/s | 67 | 100% | +| 2 | Blue pill | PB9 | SAMD | 12 | 2040kB/s | 68 | 100% | +| 2 | UNO/Nano | 12 | Blue pill | PB9 | 1980kB/s | 66 | 100% | +| 2 | SAMD21 | D0 | Blue pill | PB9 | 2010kB/s | 67 | 100% | +| 2 | ESP32 | 12 | Blue pill | PB9 | 2070kB/s | 69 | 100% | +| 2 | Blue pill | PB9 | ESP8266 80MHz | D1 | 2019kB/s | 68 | 99.77% | +| 2 | Blue pill | PB9 | ESP8266 160MHz | D1 | 2070kB/s | 69 | 100% | +| 2 | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1938kB/s | 66 | 97.8% | +| 2 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1969kB/s | 66 | 98.93% | +| 2 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1980kB/s | 66 | 100% | +| 2 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 2010kB/s | 67 | 100% | From 1774d9115ef4b056d263e47800f9dd4fc2eb8d85 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jul 2020 01:32:10 +0200 Subject: [PATCH 175/323] SoftwareBitBang NetworkAnalysis additional test results added --- .../tests/NetworkAnalysis-10s.md | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index 9863d3eca2..96f4a6dd65 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -17,20 +17,21 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | UNO/Nano | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | | 1 | UNO/Nano | 12 | Blue pill | PB9 | 1770kB/s | 59 | 100% | | 1 | Leonardo/Micro | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | -| 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | | | | +| 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 99.92% | | 1 | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | -| 1 | Leonardo/Micro | 12 | ESP32 | 12 | | | | -| 1 | Leonardo/Micro | 12 | SAMD21 | D0 | | | | +| 1 | Leonardo/Micro | 12 | ESP32 40MHz | 12 | 1590kB/s | 53 | 88.68% | +| 1 | Leonardo/Micro | 12 | ESP32 80MHz | 12 | 1590kB/s | 53 | 88.68% | +| 1 | Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | | 1 | Mega | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | | 1 | Mega | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | -| 1 | Mega | 12 | ESP8266 80MHz | D1 | | | | -| 1 | Mega | 12 | ESP8266 160MHz | D1 | | | | +| 1 | Mega | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 99.9% | +| 1 | Mega | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 99.9% | | 1 | Mega | 12 | ESP32 40MHz | 12 | 1710kB/s | 57 | 96.49% | | 1 | Mega | 12 | ESP32 80MHz | 12 | 1710kB/s | 57 | 96.49% | | 1 | Mega | 12 | ESP32 40MHz | 25 | 1710kB/s | 57 | 96.49% | | 1 | Mega | 12 | ESP32 80MHz | 25 | 1710kB/s | 57 | 96.49% | | 1 | Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | -| 1 | Mega | 12 | SAMD21 | D1 | | | | +| 1 | Mega | 12 | SAMD21 | D1 | 1770kB/s | 59 | 100% | | 1 | ESP8266 80MHz | D1 | UNO/Nano | 12 | | | | | 1 | ESP8266 160MHz | D1 | UNO/Nano | 12 | | | | | 1 | ESP8266 80MHz | D1 | Leonardo/Micro | 12 | | | | @@ -69,3 +70,14 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 2 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1969kB/s | 66 | 98.93% | | 2 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1980kB/s | 66 | 100% | | 2 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 2010kB/s | 67 | 100% | +| 3 | Blue pill | PB9 | Blue pill | PB9 | 2850kB/s | 95 | 100% | +| 3 | Blue pill | PB9 | UNO/Nano | 12 | 2760kB/s | 92 | 100% | +| 3 | UNO/Nano | 12 | Blue pill | PB9 | 2730kB/s | 91 | 100% | +| 3 | Blue pill | PB9 | SAMD | 12 | 2820kB/s | 94 | 100% | +| 3 | SAMD21 | D0 | Blue pill | PB9 | 2781kB/s | 93 | 99.78% | +| 3 | Blue pill | PB9 | ESP8266 80MHz | D1 | 2649kB/s | 95 | 93% | +| 3 | Blue pill | PB9 | ESP8266 160MHz | D1 | 2803kB/s | 95 | 98.36% | +| 3 | ESP8266 80MHz | D1 | Blue pill | PB9 | 2802kB/s | 94 | 99.36% | +| 3 | ESP8266 160MHz | D1 | Blue pill | PB9 | 2880kB/s | 96 | 100% | +| 3 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 2673kB/s | 90 | 99% | +| 3 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 2788kB/s | 93 | 99.94% | From 8b6efee8c1aa33467d7a95b60322f6ccb75ee5d7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jul 2020 02:16:23 +0200 Subject: [PATCH 176/323] SoftwareBitBang timing removed unused constant --- src/strategies/SoftwareBitBang/Timing.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 8a99656912..f4bf1e6e03 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -271,9 +271,6 @@ #ifndef SWBB_LATENCY #define SWBB_LATENCY 13 #endif - #ifndef SWBB_DEVIATION - #define SWBB_DEVIATION 10 - #endif #endif #if SWBB_MODE == 2 #ifndef SWBB_BIT_WIDTH @@ -291,9 +288,6 @@ #ifndef SWBB_LATENCY #define SWBB_LATENCY 10 #endif - #ifndef SWBB_DEVIATION - #define SWBB_DEVIATION 9 - #endif #endif #if SWBB_MODE == 3 #ifndef SWBB_BIT_WIDTH @@ -311,9 +305,6 @@ #ifndef SWBB_LATENCY #define SWBB_LATENCY 8 #endif - #ifndef SWBB_DEVIATION - #define SWBB_DEVIATION 7 - #endif #endif #if SWBB_MODE == 4 #ifndef SWBB_BIT_WIDTH @@ -331,9 +322,6 @@ #ifndef SWBB_LATENCY #define SWBB_LATENCY 5 #endif - #ifndef SWBB_DEVIATION - #define SWBB_DEVIATION 7 - #endif #endif /* Synchronous acknowledgement response offset. From 69fb85ea1764a8fa264459a480c79e48d687dbb5 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jul 2020 02:17:04 +0200 Subject: [PATCH 177/323] SoftwareBitBang NetworkAnalysis test results added --- .../tests/NetworkAnalysis-10s.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index 96f4a6dd65..d9e1b3eef1 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -17,7 +17,7 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | UNO/Nano | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | | 1 | UNO/Nano | 12 | Blue pill | PB9 | 1770kB/s | 59 | 100% | | 1 | Leonardo/Micro | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | -| 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 99.92% | +| 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 99.998% | | 1 | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | | 1 | Leonardo/Micro | 12 | ESP32 40MHz | 12 | 1590kB/s | 53 | 88.68% | | 1 | Leonardo/Micro | 12 | ESP32 80MHz | 12 | 1590kB/s | 53 | 88.68% | @@ -32,18 +32,18 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | Mega | 12 | ESP32 80MHz | 25 | 1710kB/s | 57 | 96.49% | | 1 | Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | | 1 | Mega | 12 | SAMD21 | D1 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 80MHz | D1 | UNO/Nano | 12 | | | | -| 1 | ESP8266 160MHz | D1 | UNO/Nano | 12 | | | | -| 1 | ESP8266 80MHz | D1 | Leonardo/Micro | 12 | | | | -| 1 | ESP8266 160MHz | D1 | Leonardo/Micro | 12 | | | | -| 1 | ESP8266 80MHz | D1 | Mega | 12 | | | | -| 1 | ESP8266 160MHz | D1 | Mega | 12 | | | | +| 1 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP8266 80MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP8266 160MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP8266 80MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP8266 160MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | | 1 | ESP8266 80MHz | D1 | Blue pill | PB9 | | | | | 1 | ESP8266 160MHz | D1 | Blue pill | PB9 | | | | -| 1 | ESP32 80MHz | 12 | UNO/Nano | 12 | | | | -| 1 | ESP32 40MHz | 12 | UNO/Nano | 12 | | | | -| 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | | | | -| 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | | | | +| 1 | ESP32 80MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP32 40MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | +| 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | 1 | ESP32 | 12 | Blue pill | PB9 | 1800kB/s | 60 | 100% | | 1 | SAMD21 | D0 | Mega | 12 | 1770kB/s | 59 | 100% | | 1 | SAMD21 | D0 | Leonardo/Micro | 12 | 1710kB/s | 57 | 100% | From cbcea9589c29a8eab8f06060ec26059506b3b3ef Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jul 2020 03:00:52 +0200 Subject: [PATCH 178/323] SoftwareBitBang added SAMD21 MODE 2 support --- src/strategies/SoftwareBitBang/Timing.h | 8 ++++++++ .../SoftwareBitBang/tests/NetworkAnalysis-10s.md | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index f4bf1e6e03..3c750aff1f 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -166,6 +166,14 @@ #define SWBB_ACCEPTANCE 45 #define SWBB_READ_DELAY -4 #endif + /* Added by Giovanni Blu Mitolo 30/07/2020 + Tested on pin: D0 */ + #if SWBB_MODE == 2 + #define SWBB_BIT_WIDTH 39.5 + #define SWBB_BIT_SPACER 91.5 + #define SWBB_ACCEPTANCE 45 + #define SWBB_READ_DELAY -2 + #endif #endif /* NodeMCU, generic ESP8266 ----------------------------------------------- */ diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index d9e1b3eef1..9b7ff07983 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -1,6 +1,8 @@ ## NetworkAnalysis This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis) example for 10 seconds and averaging the obtained series of results. +### Mode 1 + | MODE | TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | |------|----------------|-----|----------------|-----|-----------|-----------|--------------| | 1 | UNO/Nano | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | @@ -58,10 +60,17 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | Blue pill | PB9 | SAMD | 12 | 1830kB/s | 61 | 100% | | 1 | Blue pill | PB9 | ESP8266 80MHz | D1 | 1788kB/s | 60 | 99.33% | | 1 | Blue pill | PB9 | ESP8266 160MHz | D1 | 1800kB/s | 60 | 100% | + +### Mode 2 + +| MODE | TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | +|------|----------------|-----|----------------|-----|-----------|-----------|--------------| | 2 | Blue pill | PB9 | Blue pill | PB9 | 2040kB/s | 68 | 100% | | 2 | Blue pill | PB9 | UNO/Nano | 12 | 2010kB/s | 67 | 100% | -| 2 | Blue pill | PB9 | SAMD | 12 | 2040kB/s | 68 | 100% | +| 2 | Blue pill | PB9 | SAMD | | | | | | 2 | UNO/Nano | 12 | Blue pill | PB9 | 1980kB/s | 66 | 100% | +| 2 | UNO/Nano | 12 | SAMD21 | D0 | 1980kB/s | 66 | 100% | +| 2 | SAMD21 | D0 | UNO/Nano | 12 | 1950kB/s | 65 | 100% | | 2 | SAMD21 | D0 | Blue pill | PB9 | 2010kB/s | 67 | 100% | | 2 | ESP32 | 12 | Blue pill | PB9 | 2070kB/s | 69 | 100% | | 2 | Blue pill | PB9 | ESP8266 80MHz | D1 | 2019kB/s | 68 | 99.77% | @@ -70,6 +79,11 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 2 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1969kB/s | 66 | 98.93% | | 2 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1980kB/s | 66 | 100% | | 2 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 2010kB/s | 67 | 100% | + +### Mode 3 + +| MODE | TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | +|------|----------------|-----|----------------|-----|-----------|-----------|--------------| | 3 | Blue pill | PB9 | Blue pill | PB9 | 2850kB/s | 95 | 100% | | 3 | Blue pill | PB9 | UNO/Nano | 12 | 2760kB/s | 92 | 100% | | 3 | UNO/Nano | 12 | Blue pill | PB9 | 2730kB/s | 91 | 100% | From 09339756c2a565bf26b44a020dbcad0b6356222c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jul 2020 15:24:57 +0200 Subject: [PATCH 179/323] SoftwareBitBang ATmega328PB timing update (https://github.com/gioblu/PJON/pull/330) @willie68 --- src/strategies/SoftwareBitBang/Timing.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 3c750aff1f..ec892dde18 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -71,7 +71,7 @@ #if F_CPU == 16000000L /* Working on pin: 10 */ #define SWBB_BIT_WIDTH 37 - #define SWBB_BIT_SPACER 110 + #define SWBB_BIT_SPACER 104 #define SWBB_ACCEPTANCE 56 #define SWBB_READ_DELAY 4 #endif From 421e32a82b565b258fcd726c4e972520c15dc818 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jul 2020 16:45:53 +0200 Subject: [PATCH 180/323] PJDL v5.0 medium access latency remark, sync pulse rising edge remark --- src/strategies/SoftwareBitBang/SoftwareBitBang.h | 12 ++++++++---- .../specification/PJDL-specification-v5.0.md | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index d79f5ad6f2..e3b7656920 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -69,6 +69,7 @@ class SoftwareBitBang { bool can_start() { PJON_IO_MODE(_input_pin, INPUT); + // Look for ongoing transmission for 1 padding bit + 9 data bits PJON_DELAY_MICROSECONDS(SWBB_BIT_SPACER / 2); if(PJON_IO_READ(_input_pin)) return false; PJON_DELAY_MICROSECONDS((SWBB_BIT_SPACER / 2)); @@ -80,6 +81,10 @@ class SoftwareBitBang { PJON_DELAY_MICROSECONDS(SWBB_BIT_WIDTH); } if(PJON_IO_READ(_input_pin)) return false; + // Delay for the maximum expected latency and then check again + PJON_DELAY_MICROSECONDS(SWBB_LATENCY); + if(PJON_IO_READ(_input_pin)) return false; + // Delay for a small random time and then check again PJON_DELAY_MICROSECONDS(PJON_RANDOM(SWBB_COLLISION_DELAY)); if(PJON_IO_READ(_input_pin)) return false; return true; @@ -173,8 +178,7 @@ class SoftwareBitBang { (uint32_t)(PJON_MICROS() - time) < (((SWBB_BIT_WIDTH * 3) + (SWBB_BIT_SPACER * 3)) - SWBB_ACCEPTANCE) ) return SWBB_FAIL; - } - // Receive incoming bytes + } // Receive one byte result = receive_byte(); if(result == SWBB_FAIL) return SWBB_FAIL; *data = result; @@ -227,7 +231,7 @@ class SoftwareBitBang { while( // If high Wait for low ((uint32_t)(PJON_MICROS() - time) < (SWBB_BIT_WIDTH / 4)) && PJON_IO_READ(_input_pin) - ); + ); // Transmit response prepended with a synchronization pad PJON_IO_MODE(_output_pin, OUTPUT); pulse(1); send_byte(response); @@ -253,7 +257,7 @@ class SoftwareBitBang { PJON_IO_MODE(_output_pin, OUTPUT); pulse(3); // Send frame initializer for(uint16_t b = 0; b < length; b++) - send_byte(data[b]); // Send data + send_byte(data[b]); // Send each byte PJON_IO_PULL_DOWN(_output_pin); }; diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index 70f9e1ae3d..4a9e485676 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -76,7 +76,7 @@ The reception technique is based on 3 steps: 2. Synchronize with its falling edge 3. Ensure it is followed by a low data bit -If so reception starts, if not, interference, synchronization loss or simply absence of communication is detected. The high padding bit is 2.5 times longer than data bits because with this ratio ambiguity between padding bits and 2 or 3 consecutive data bits is avoided even with an overall deviation of up to +- (data bit / 4) - 1. The receiver must accept a synchronization pad also if it is prepended by a 0 of up to (data bit / 4) - 1 microseconds. +If so reception starts, if not, interference, synchronization loss or simply absence of communication is detected. The high padding bit is 2.5 times longer than data bits because with this ratio ambiguity between padding bits and 2 or 3 consecutive data bits is avoided even with an overall deviation of up to +- (data bit / 4) - 1. A synchronization pad is acceptable if prepended by a 0 of up to (data bit / 4) - 1. ```cpp ___________ ___________________________ @@ -89,7 +89,7 @@ If so reception starts, if not, interference, synchronization loss or simply abs The synchronization pad adds overhead although it includes synchronization along with the data and eliminates the need of a dedicated clock line. The presence of the synchronization pad between each byte also ensures that a frame composed of a series of bytes with decimal value 0 can be transmitted safely without risk of collision. ### Frame transmission -Before a frame transmission the communication medium's state is analysed, if high communication is detected and collision is avoided, if low for a duration of one byte plus a small random time, frame transmission starts with an initializer composed by 3 consecutive synchronization pads followed by data bytes. The synchronization pad is used for both byte and frame initialization to reduce the implementation complexity. +Before a frame transmission the communication medium's state is analysed, if high communication is detected and collision is avoided, if low for a duration of one byte plus the latency and a small random time, frame transmission starts with an initializer composed by 3 consecutive synchronization pads followed by data bytes. The synchronization pad is used for both byte and frame initialization to reduce the implementation complexity. ```cpp ________ _________________ __________________________________ |ANALYSIS| FRAME INIT | DATA 1-65535 bytes | From 7d7f11de421d1f62ef00790f36e6126c0de05d07 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jul 2020 17:07:56 +0200 Subject: [PATCH 181/323] PJDL v5.0 frame length limit remark added --- .../specification/PJDL-specification-v5.0.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index 4a9e485676..f5472e9fe2 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -80,7 +80,7 @@ If so reception starts, if not, interference, synchronization loss or simply abs ```cpp ___________ ___________________________ -| SYNC-PAD | DATA | +| SYNC PAD | DATA | |_______ |___ ___ _____ | | | | | | | | | | | 1 | 0 | 1 | 0 0 | 1 | 0 | 1 1 | 0 | @@ -89,10 +89,10 @@ If so reception starts, if not, interference, synchronization loss or simply abs The synchronization pad adds overhead although it includes synchronization along with the data and eliminates the need of a dedicated clock line. The presence of the synchronization pad between each byte also ensures that a frame composed of a series of bytes with decimal value 0 can be transmitted safely without risk of collision. ### Frame transmission -Before a frame transmission the communication medium's state is analysed, if high communication is detected and collision is avoided, if low for a duration of one byte plus the latency and a small random time, frame transmission starts with an initializer composed by 3 consecutive synchronization pads followed by data bytes. The synchronization pad is used for both byte and frame initialization to reduce the implementation complexity. +Before a frame transmission the communication medium's state is analysed, if high communication is detected and collision is avoided, if low for a duration of one byte plus the latency and a small random time, frame transmission starts with an initializer composed by 3 consecutive synchronization pads followed by data bytes. The synchronization pad is used for both byte and frame initialization to reduce the implementation complexity. PJDL frames do not have an intrinsic length limit. ```cpp ________ _________________ __________________________________ -|ANALYSIS| FRAME INIT | DATA 1-65535 bytes | +|ANALYSIS| FRAME INIT | DATA BYTES | |________|_____ _____ _____|________________ _________________| | |Sync |Sync |Sync |Sync | Byte |Sync | Byte | | |___ |___ |___ |___ | __ |___ | _ _| @@ -114,7 +114,7 @@ Transmission end Response ``` In order to avoid other devices to detect the medium free for use and disrupt an ongoing exchange, the sender cyclically transmits a high 1/4 data bit and consequently attempts to receive a response for up to twice the maximum expected latency. The receiver must synchronize to the falling edge of the last high bit and, in order to avoid false positives in case of collision, must transmit its response prepended with an additional synchronization pad. If the response is not transmitted or not received the transmitter continues to keep busy the medium up to the response timeout. ```cpp -Transmission end Keep busy Response +Transmission end Bus is kept busy Response ______ ______ ______ _ _ _ _ _ _ ____ _____ | BYTE || BYTE || BYTE | | | | | | | | | | | | |SYNC| ACK | |------||------||------| | | | | | | | | | | | |----|-----| From ada9d0a1ec672ef0d0b77b169f760977f378fd4e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jul 2020 17:11:01 +0200 Subject: [PATCH 182/323] PJDL v5.0 added keep busy bit negative deviation --- .../specification/PJDL-specification-v5.0.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index f5472e9fe2..6f05b991bb 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -61,9 +61,12 @@ The proposed communication modes are the result of years of testing and optimiza The following table specifies the maximum acceptable deviation of each bit type: -| Max data bit octet deviation | Max sync. pad deviation | Max keep busy bit deviation | -| ---------------------------- | ------------------------- | --------------------------- | -| +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | + 10µs | +| Mode | Max data bit octet deviation | Max sync. pad deviation | Max keep busy bit deviation | +| ---- | ---------------------------- | ------------------------- | --------------------------- | +| 1 | +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | -5µs +10µs | +| 2 | +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | -5µs +10µs | +| 3 | +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | -3µs +10µs | +| 4 | +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | -3µs +10µs | ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. From 77473ff90b8d68e1b1f599aa52ef2b516eb1afdb Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 1 Aug 2020 01:25:15 +0200 Subject: [PATCH 183/323] PJON_IO_PULL_DOWN bug fixed Because of missing parentheses PJON_IO_PULL_DOWN was executing both PJON_IO_MODE and pinMode wasting more than 3 microseconds. --- src/interfaces/ARDUINO/PJON_IO.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/interfaces/ARDUINO/PJON_IO.h b/src/interfaces/ARDUINO/PJON_IO.h index 8071192531..ed1d4b7bd2 100644 --- a/src/interfaces/ARDUINO/PJON_IO.h +++ b/src/interfaces/ARDUINO/PJON_IO.h @@ -310,8 +310,9 @@ inform the reader of their definition as macros in the global scope. do { if(__builtin_constant_p(P)) { \ PJON_IO_WRITE(P, LOW); \ PJON_IO_MODE(P, INPUT); \ - } else \ + } else { \ digitalWrite(P, LOW); \ pinMode(P, INPUT); \ + } \ } while(0) #endif From b3d8e55e790a06a4e390a8ad00511a8c43be0e13 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 1 Aug 2020 01:58:30 +0200 Subject: [PATCH 184/323] SoftwareBitBang default timing update Default values reflect Arduino Duemilanove/UNO setup, are temporary and used not to affect compatible devices without dedicated timing. Default timing should be used only by devices that are not officially compatible and should reflect the durations specified in PJDL v5.0 Therefore dedicated timing should be present for each compatible device --- src/strategies/SoftwareBitBang/Timing.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index ec892dde18..f2761ca216 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -268,13 +268,13 @@ #define SWBB_BIT_WIDTH 40 #endif #ifndef SWBB_BIT_SPACER - #define SWBB_BIT_SPACER 112 + #define SWBB_BIT_SPACER 106 #endif #ifndef SWBB_ACCEPTANCE - #define SWBB_ACCEPTANCE 56 + #define SWBB_ACCEPTANCE 53 #endif #ifndef SWBB_READ_DELAY - #define SWBB_READ_DELAY 4 + #define SWBB_READ_DELAY 3 #endif #ifndef SWBB_LATENCY #define SWBB_LATENCY 13 @@ -302,10 +302,10 @@ #define SWBB_BIT_WIDTH 24 #endif #ifndef SWBB_BIT_SPACER - #define SWBB_BIT_SPACER 80 + #define SWBB_BIT_SPACER 66 #endif #ifndef SWBB_ACCEPTANCE - #define SWBB_ACCEPTANCE 40 + #define SWBB_ACCEPTANCE 30 #endif #ifndef SWBB_READ_DELAY #define SWBB_READ_DELAY 8 @@ -319,13 +319,13 @@ #define SWBB_BIT_WIDTH 22 #endif #ifndef SWBB_BIT_SPACER - #define SWBB_BIT_SPACER 56 + #define SWBB_BIT_SPACER 61 #endif #ifndef SWBB_ACCEPTANCE #define SWBB_ACCEPTANCE 30 #endif #ifndef SWBB_READ_DELAY - #define SWBB_READ_DELAY 9 + #define SWBB_READ_DELAY 7 #endif #ifndef SWBB_LATENCY #define SWBB_LATENCY 5 From 434243e8541ec5ea99f8439f10472df7799da1bd Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Sun, 16 Aug 2020 23:37:51 +0200 Subject: [PATCH 185/323] Added new academic study by @jdaandersj --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 666738b44b..877021b477 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ Researchers are active in many universities worldwide using PJON in different en - [Definition and Application of PJON-PLC for sensor networks](https://repositorio.unican.es/xmlui/bitstream/handle/10902/14012/408952.pdf?sequence=1) by Jorge Gómez Segurola, Ingeniería de Tecnologías de Telecomunicación - [Universidad de Cantabria](https://web.unican.es/) (ES) - [Biomimetic electronics](http://c.harl.ie/biomimetic.html) by Charlie Williams with scientific input from researchers Vítor Martins dos Santos, Diana Machado de Sousa and Sabine Vreeburg - Artist in Residency at [Wageningen University](https://www.wur.nl/en.htm) (NL) +- [LANC Video Camera Control](http://jda.tel/pdf/lanc_video_camera_control.pdf) by [Jack Anderson](https://github.com/jdaandersj) - Department of Computer Science [Loughborough University](https://www.lboro.ac.uk/departments/compsci/) (UK) ### Contribute Feel free to send a pull request sharing something you have made that could help, if you want to support this project you can also try to solve an [issue](https://github.com/gioblu/PJON/issues). Thanks to support, expertise, kindness and talent of the following contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: From 5f9dff45e34b93b1df0419c8487856ff8e5cf25b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 25 Aug 2020 18:12:20 +0200 Subject: [PATCH 186/323] @jdaandersj added to PJDL header --- .../SoftwareBitBang/specification/PJDL-specification-v5.0.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index 6f05b991bb..01eed86a60 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -15,8 +15,8 @@ ## PJDL v5.0 ``` -Invented by Giovanni Blu Mitolo with the support -of Fred Larsen, Julio Aguirre and Gerhard Sittig +Invented by Giovanni Blu Mitolo with the support of +Fred Larsen, Julio Aguirre, Gerhard Sittig and Jack Anderson Publication date: 10/04/2010 Latest revision: 24/07/2020 Related implementation: /src/strategies/SoftwareBitBang/ Compatible versions: PJON v13.0 and following From 4dfbf9df036a653630d8a8de510a1eeb670975d8 Mon Sep 17 00:00:00 2001 From: Nico Lastzka Date: Wed, 19 Feb 2020 11:33:46 +0100 Subject: [PATCH 187/323] zephyr: add support for the ThroughSerial strategy using the tty driver --- src/interfaces/PJON_Interfaces.h | 1 + src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 86 +++++++++++++++++++ zephyr/CMakeLists.txt | 1 + zephyr/Kconfig | 0 4 files changed, 88 insertions(+) create mode 100644 src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h create mode 100644 zephyr/CMakeLists.txt create mode 100644 zephyr/Kconfig diff --git a/src/interfaces/PJON_Interfaces.h b/src/interfaces/PJON_Interfaces.h index ab7bebcd76..4db6c7203b 100644 --- a/src/interfaces/PJON_Interfaces.h +++ b/src/interfaces/PJON_Interfaces.h @@ -5,3 +5,4 @@ #include "RPI/PJON_RPI_Interface.h" #include "WINX86/PJON_WINX86_Interface.h" #include "LINUX/PJON_LINUX_Interface.h" +#include "ZEPHYR/PJON_ZEPHYR_Interface.h" diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h new file mode 100644 index 0000000000..04725de0d6 --- /dev/null +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -0,0 +1,86 @@ +#if defined(ZEPHYR) + +#include +#include + +static int serial_get_char(struct tty_serial* tty) +{ + u8_t tmp; + tty_read(tty, &tmp, 1); + return tmp; +} + +// deal with randomness + +#ifndef PJON_RANDOM +#define PJON_RANDOM(randMax) (int)((1.0 + randMax) * rand() / ( RAND_MAX + 1.0 )) +#endif + +#ifndef PJON_RANDOM_SEED +#define PJON_RANDOM_SEED srand +#endif + +#ifndef A0 +#define A0 0 +#endif + +#ifndef PJON_ANALOG_READ +#define PJON_ANALOG_READ(P) 0 +#endif + +// delay and timing functions + +#ifndef PJON_DELAY +#define PJON_DELAY k_sleep +#endif + +#ifndef PJON_DELAY_MICROSECONDS +#define PJON_DELAY_MICROSECONDS k_usleep +#endif + +#ifndef PJON_MICROS +#define PJON_MICROS k_uptime_get +#endif + +// serial port handling + +#ifndef PJON_SERIAL_TYPE +#define PJON_SERIAL_TYPE struct tty_serial* +#endif + +#ifndef PJON_SERIAL_AVAILABLE +#define PJON_SERIAL_AVAILABLE(S) S != NULL and S->rx_get != S->rx_put +#endif + +#ifndef PJON_SERIAL_READ +#define PJON_SERIAL_READ(S) serial_get_char(S) +#endif + +#ifndef PJON_SERIAL_WRITE +#define PJON_SERIAL_WRITE(S, C) tty_write(S, &C, 1) +#endif + +#ifndef PJON_SERIAL_FLUSH +#define PJON_SERIAL_FLUSH(S) +#endif + +// io pin handling (for setting the rs485 txe pin) is not needed since we use the auto-direction +// feature of the rs485 transceiver + +#ifndef PJON_IO_WRITE +#define PJON_IO_WRITE(P, C) +#endif + +#ifndef PJON_IO_MODE +#define PJON_IO_MODE(P, C) +#endif + +#ifndef LOW +#define LOW 0 +#endif + +#ifndef HIGH +#define HIGH 1 +#endif + +#endif diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt new file mode 100644 index 0000000000..bff5b18b63 --- /dev/null +++ b/zephyr/CMakeLists.txt @@ -0,0 +1 @@ +zephyr_include_directories(../src) diff --git a/zephyr/Kconfig b/zephyr/Kconfig new file mode 100644 index 0000000000..e69de29bb2 From c6c48514b8d3e1f7f55d7c6740db7f1c210884de Mon Sep 17 00:00:00 2001 From: Nico Lastzka Date: Fri, 21 Feb 2020 08:19:00 +0100 Subject: [PATCH 188/323] pjon: fix returning number of microseconds --- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h index 04725de0d6..32356b9bfa 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -39,7 +39,7 @@ static int serial_get_char(struct tty_serial* tty) #endif #ifndef PJON_MICROS -#define PJON_MICROS k_uptime_get +#define PJON_MICROS 1000*k_uptime_get #endif // serial port handling From 94586cffbdf4f77156d7a261f308dbefe0e894ef Mon Sep 17 00:00:00 2001 From: Nico Lastzka Date: Mon, 16 Mar 2020 10:30:19 +0100 Subject: [PATCH 189/323] zephyr: implement flushing the serial device --- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h index 32356b9bfa..64101e87f1 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -10,6 +10,13 @@ static int serial_get_char(struct tty_serial* tty) return tmp; } +static void serial_flush(struct tty_serial* tty) +{ + while (not uart_irq_tx_complete(tty->uart_dev)) { + k_usleep(100); + } +} + // deal with randomness #ifndef PJON_RANDOM @@ -61,7 +68,7 @@ static int serial_get_char(struct tty_serial* tty) #endif #ifndef PJON_SERIAL_FLUSH -#define PJON_SERIAL_FLUSH(S) +#define PJON_SERIAL_FLUSH(S) serial_flush(S) #endif // io pin handling (for setting the rs485 txe pin) is not needed since we use the auto-direction From 9ac27f653dac83803efdb3fbcf57acef0dc00ab1 Mon Sep 17 00:00:00 2001 From: Nico Lastzka Date: Mon, 8 Jun 2020 08:12:36 +0200 Subject: [PATCH 190/323] zephyr: fix usage of tcphelper by not applying unknown socket options --- src/interfaces/LINUX/TCPHelper_POSIX.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/interfaces/LINUX/TCPHelper_POSIX.h b/src/interfaces/LINUX/TCPHelper_POSIX.h index dcf4506a15..bb7053a942 100644 --- a/src/interfaces/LINUX/TCPHelper_POSIX.h +++ b/src/interfaces/LINUX/TCPHelper_POSIX.h @@ -13,6 +13,7 @@ #define close(fd) closesocket(fd) #define ssize_t int #else +#include #include #include #include @@ -101,11 +102,14 @@ class TCPHelperClient { struct timeval read_timeout; read_timeout.tv_sec = 0; read_timeout.tv_usec = 2000000; +#ifndef ZEPHYR setsockopt(_fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&read_timeout, sizeof read_timeout); setsockopt(_fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&read_timeout, sizeof read_timeout); +#endif bool connected = ::connect(_fd, (struct sockaddr *) &_remote_addr,sizeof(_remote_addr)) == 0; if (connected) { +#ifndef ZEPHYR // Shorten timeouts for reading and writing struct timeval read_timeout; read_timeout.tv_sec = 0; @@ -113,7 +117,7 @@ class TCPHelperClient { setsockopt(_fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&read_timeout, sizeof read_timeout); read_timeout.tv_usec = 2000000; setsockopt(_fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&read_timeout, sizeof read_timeout); - +#endif // Disable Nagles algorith because we are sending small packets and waiting for reply set_nodelay(true); } @@ -189,13 +193,14 @@ class TCPHelperClient { #endif // Set timeouts for reading and writing +#ifndef ZEPHYR struct timeval read_timeout; read_timeout.tv_sec = 0; read_timeout.tv_usec = 1000; setsockopt(_fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&read_timeout, sizeof read_timeout); read_timeout.tv_usec = 2000000; setsockopt(_fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&read_timeout, sizeof read_timeout); - +#endif // Disable Nagles algorith because we are sending small packets and waiting for reply set_nodelay(true); @@ -233,7 +238,7 @@ class TCPHelperClient { int write(const uint8_t *buffer, int size) { if (_fd == -1) return -1; -#ifdef _WIN32 +#if defined(_WIN32) || defined(ZEPHYR) int w = ::send(_fd, (char*)buffer, size, 0); #else int w = ::send(_fd, (char*)buffer, size, MSG_NOSIGNAL); @@ -298,6 +303,7 @@ class TCPHelperServer { memset(&_remote_sender_addr, 0, len); int connected_fd = _fd == -1 ? -1 : ::accept(_fd, (struct sockaddr *) &_remote_sender_addr, &len); if (connected_fd != -1) { +#ifndef ZEPHYR // Shorten timeout for reading and writing struct timeval read_timeout; read_timeout.tv_sec = 0; @@ -305,7 +311,7 @@ class TCPHelperServer { setsockopt(connected_fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&read_timeout, sizeof read_timeout); read_timeout.tv_usec = 2000000; setsockopt(connected_fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&read_timeout, sizeof read_timeout); - +#endif // Disable Nagles algorith because we are sending small packets and waiting for reply int flag = 1; setsockopt(connected_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof flag); From a53121ffced3fd4057b6ab0adb05dbce8275d179 Mon Sep 17 00:00:00 2001 From: Nico Lastzka Date: Mon, 8 Jun 2020 08:14:04 +0200 Subject: [PATCH 191/323] zephyr: fix usage of udphelper by not applying unknown socket options --- src/interfaces/LINUX/UDPHelper_POSIX.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/interfaces/LINUX/UDPHelper_POSIX.h b/src/interfaces/LINUX/UDPHelper_POSIX.h index f6982cdedb..e6f8ed8bf7 100644 --- a/src/interfaces/LINUX/UDPHelper_POSIX.h +++ b/src/interfaces/LINUX/UDPHelper_POSIX.h @@ -10,6 +10,7 @@ #define close(fd) closesocket(fd) #define ssize_t int #else +#include #include #include #include @@ -18,6 +19,11 @@ #include #endif +#ifdef ZEPHYR +#include +#define INADDR_BROADCAST ((u32_t) 0xffffffff) +#endif + class UDPHelper { uint16_t _port; uint32_t _magic_header; @@ -69,7 +75,11 @@ class UDPHelper { read_timeout.tv_sec = 0; read_timeout.tv_usec = 1000; #endif +#ifdef ZEPHYR + fcntl(_fd, F_SETFL, O_NONBLOCK); +#else setsockopt(_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&read_timeout, sizeof read_timeout); +#endif // Bind to specific local port memset(&_localaddr, 0, sizeof(_localaddr)); @@ -88,12 +98,14 @@ class UDPHelper { _remote_receiver_addr.sin_port = htons(_port); _remote_receiver_addr.sin_addr.s_addr = INADDR_BROADCAST; +#ifndef ZEPHYR // Allow broadcasts int broadcast=1; if (setsockopt(_fd,SOL_SOCKET,SO_BROADCAST,(const char*)&broadcast,sizeof(broadcast))==-1) { //printf("INIT send setsockopt %s\n", strerror(errno)); return false; } +#endif return true; } From 0a193fe81e60462fa7bb58f1c6c564b3d19fcf3d Mon Sep 17 00:00:00 2001 From: Nico Lastzka Date: Mon, 8 Jun 2020 08:16:26 +0200 Subject: [PATCH 192/323] zehyr: remove serial flush implementation --- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h index 64101e87f1..32356b9bfa 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -10,13 +10,6 @@ static int serial_get_char(struct tty_serial* tty) return tmp; } -static void serial_flush(struct tty_serial* tty) -{ - while (not uart_irq_tx_complete(tty->uart_dev)) { - k_usleep(100); - } -} - // deal with randomness #ifndef PJON_RANDOM @@ -68,7 +61,7 @@ static void serial_flush(struct tty_serial* tty) #endif #ifndef PJON_SERIAL_FLUSH -#define PJON_SERIAL_FLUSH(S) serial_flush(S) +#define PJON_SERIAL_FLUSH(S) #endif // io pin handling (for setting the rs485 txe pin) is not needed since we use the auto-direction From 44a32349f23d1564a6421bb50a4625472c73eec8 Mon Sep 17 00:00:00 2001 From: Nico Lastzka Date: Mon, 8 Jun 2020 08:16:45 +0200 Subject: [PATCH 193/323] zephyr: define PJON_MILLIS --- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h index 32356b9bfa..ac76c0f8f3 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -38,6 +38,10 @@ static int serial_get_char(struct tty_serial* tty) #define PJON_DELAY_MICROSECONDS k_usleep #endif +#ifndef PJON_MILLIS +#define PJON_MILLIS k_uptime_get +#endif + #ifndef PJON_MICROS #define PJON_MICROS 1000*k_uptime_get #endif From 1f0388d05ae760fd6ba3a3d336cd1a66b818ce3c Mon Sep 17 00:00:00 2001 From: Nico Lastzka Date: Tue, 23 Jun 2020 10:47:42 +0200 Subject: [PATCH 194/323] zephyr: make sleep time unit explicit --- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h index ac76c0f8f3..5b372fbe05 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -31,7 +31,7 @@ static int serial_get_char(struct tty_serial* tty) // delay and timing functions #ifndef PJON_DELAY -#define PJON_DELAY k_sleep +#define PJON_DELAY k_msleep #endif #ifndef PJON_DELAY_MICROSECONDS From 1c48232033590bc0bf46382be64c06184b656ae0 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Wed, 1 Jul 2020 10:20:44 +0200 Subject: [PATCH 195/323] pjon: use uart api instead of tty_serial --- src/interfaces/LINUX/UDPHelper_POSIX.h | 8 +-- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 54 +++++++++++++++---- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/interfaces/LINUX/UDPHelper_POSIX.h b/src/interfaces/LINUX/UDPHelper_POSIX.h index e6f8ed8bf7..9314205029 100644 --- a/src/interfaces/LINUX/UDPHelper_POSIX.h +++ b/src/interfaces/LINUX/UDPHelper_POSIX.h @@ -13,10 +13,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #endif #ifdef ZEPHYR diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h index 5b372fbe05..ec83a8fca2 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -1,13 +1,49 @@ #if defined(ZEPHYR) #include +#include #include -static int serial_get_char(struct tty_serial* tty) +#include +#include +#include + +RING_BUF_DECLARE(ringbuffer_pjon, CONFIG_PJON_MTU); +static uint8_t tmp_buffer[40]; +static int serial_get_char(struct device* dev) +{ + size_t ret; + uint8_t b; + ret = ring_buf_get(&ringbuffer_pjon, &b, sizeof(b)); + return b; +} + +static bool serial_char_available(struct device* dev) +{ + bool b = ring_buf_is_empty(&ringbuffer_pjon); + return !b; +} + +static void uart_irq_callback(struct device *dev) +{ + uart_irq_update(dev); + + if (uart_irq_rx_ready(dev)) { + uint8_t tmp; + while (1) { + if (uart_fifo_read(dev, &tmp, 1) == 0) { + break; + } + ring_buf_put(&ringbuffer_pjon, &tmp, sizeof(tmp)); + } + } +} + + +static int serial_put_char(struct device* dev, uint8_t byte) { - u8_t tmp; - tty_read(tty, &tmp, 1); - return tmp; + uart_poll_out(dev,byte); + return 1; } // deal with randomness @@ -31,11 +67,11 @@ static int serial_get_char(struct tty_serial* tty) // delay and timing functions #ifndef PJON_DELAY -#define PJON_DELAY k_msleep +#define PJON_DELAY(x) (k_sleep(K_MSEC(x))) #endif #ifndef PJON_DELAY_MICROSECONDS -#define PJON_DELAY_MICROSECONDS k_usleep +#define PJON_DELAY_MICROSECONDS(x) (k_sleep(K_USEC(x))) #endif #ifndef PJON_MILLIS @@ -49,11 +85,11 @@ static int serial_get_char(struct tty_serial* tty) // serial port handling #ifndef PJON_SERIAL_TYPE -#define PJON_SERIAL_TYPE struct tty_serial* +#define PJON_SERIAL_TYPE struct device* #endif #ifndef PJON_SERIAL_AVAILABLE -#define PJON_SERIAL_AVAILABLE(S) S != NULL and S->rx_get != S->rx_put +#define PJON_SERIAL_AVAILABLE(S) serial_char_available(S) #endif #ifndef PJON_SERIAL_READ @@ -61,7 +97,7 @@ static int serial_get_char(struct tty_serial* tty) #endif #ifndef PJON_SERIAL_WRITE -#define PJON_SERIAL_WRITE(S, C) tty_write(S, &C, 1) +#define PJON_SERIAL_WRITE(S, C) serial_put_char(S, C) #endif #ifndef PJON_SERIAL_FLUSH From 54000ccf4e370a206c97a8c3cc7e65eb2b4a032d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 27 Aug 2020 18:50:58 +0200 Subject: [PATCH 196/323] PJDL specification deviation update The earlier setup was ambiguous --- .../SoftwareBitBang/specification/PJDL-specification-v5.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index 01eed86a60..dafd6eac63 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -61,7 +61,7 @@ The proposed communication modes are the result of years of testing and optimiza The following table specifies the maximum acceptable deviation of each bit type: -| Mode | Max data bit octet deviation | Max sync. pad deviation | Max keep busy bit deviation | +| Mode | Max data bit nonet deviation | Max padding bit deviation | Max keep busy bit deviation | | ---- | ---------------------------- | ------------------------- | --------------------------- | | 1 | +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | -5µs +10µs | | 2 | +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | -5µs +10µs | From 9b663128c0ecffb0813b99b50ff125661073138a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Aug 2020 01:32:40 +0200 Subject: [PATCH 197/323] SoftwareBitBang Arduino UNO/nano and Mega timing update To have SoftwareBitBang PJDL v5.0 compliance a slight tweak was required, Arduino UNO/nano and mega are affected by this change, all other devices will need to be tested and their timing tweaked if required --- src/strategies/SoftwareBitBang/Timing.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index f2761ca216..2dbf886d16 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -30,7 +30,7 @@ #if SWBB_MODE == 1 #if F_CPU == 16000000L /* Working on pin: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, A0, A1 */ - #define SWBB_BIT_WIDTH 40 + #define SWBB_BIT_WIDTH 39 #define SWBB_BIT_SPACER 106 #define SWBB_ACCEPTANCE 53 #define SWBB_READ_DELAY 3 @@ -108,7 +108,7 @@ #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #if SWBB_MODE == 1 /* Working on pin: 3, 4, 7, 8, 9, 10, 12 */ - #define SWBB_BIT_WIDTH 38 + #define SWBB_BIT_WIDTH 37 #define SWBB_BIT_SPACER 104 #define SWBB_ACCEPTANCE 53 #define SWBB_READ_DELAY 11 @@ -265,7 +265,7 @@ /* Avoid error if any previous defined ------------------------------------ */ #if SWBB_MODE == 1 #ifndef SWBB_BIT_WIDTH - #define SWBB_BIT_WIDTH 40 + #define SWBB_BIT_WIDTH 39 #endif #ifndef SWBB_BIT_SPACER #define SWBB_BIT_SPACER 106 From 976f46ac425a46e08a84f5805a173f4b445fc825 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 29 Aug 2020 05:42:30 +0200 Subject: [PATCH 198/323] SoftwareBitBang SAMD and Leonardo timing tweak and test results --- src/strategies/SoftwareBitBang/Timing.h | 8 +- .../tests/NetworkAnalysis-10s.md | 114 +++++++++--------- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 2dbf886d16..61bfe8dba7 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -92,8 +92,8 @@ #if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) #if SWBB_MODE == 1 /* Working on pin: 2, 4, 8, 12 */ - #define SWBB_BIT_WIDTH 40 - #define SWBB_BIT_SPACER 106 + #define SWBB_BIT_WIDTH 39 + #define SWBB_BIT_SPACER 102 #define SWBB_ACCEPTANCE 53 #define SWBB_READ_DELAY 6 #endif @@ -161,10 +161,10 @@ /* Added by Esben Soeltoft - 03/09/2016 Updated by Giovanni Blu Mitolo - 21/07/2020 Working on pin: D0, D1, D3, A0, A1 */ - #define SWBB_BIT_WIDTH 43.5 + #define SWBB_BIT_WIDTH 42 #define SWBB_BIT_SPACER 109.5 #define SWBB_ACCEPTANCE 45 - #define SWBB_READ_DELAY -4 + #define SWBB_READ_DELAY -2.5 #endif /* Added by Giovanni Blu Mitolo 30/07/2020 Tested on pin: D0 */ diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index 9b7ff07983..4e95101052 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -3,63 +3,63 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO ### Mode 1 -| MODE | TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | -|------|----------------|-----|----------------|-----|-----------|-----------|--------------| -| 1 | UNO/Nano | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | -| 1 | UNO/Nano | 11 | UNO/Nano | 11 | 1710kB/s | 57 | 100% | -| 1 | UNO/Nano | 10 | UNO/Nano | 10 | 1710kB/s | 57 | 100% | -| 1 | UNO/Nano | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | -| 1 | UNO/Nano | 12 | Mega | 12 | 1740kB/s | 58 | 100% | -| 1 | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | ESP32 40MHz | 12 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | ESP32 80MHz | 12 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | ESP32 40MHz | 25 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | ESP32 80MHz | 25 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | -| 1 | UNO/Nano | 12 | Blue pill | PB9 | 1770kB/s | 59 | 100% | -| 1 | Leonardo/Micro | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | -| 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 99.998% | -| 1 | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | -| 1 | Leonardo/Micro | 12 | ESP32 40MHz | 12 | 1590kB/s | 53 | 88.68% | -| 1 | Leonardo/Micro | 12 | ESP32 80MHz | 12 | 1590kB/s | 53 | 88.68% | -| 1 | Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | -| 1 | Mega | 12 | UNO/Nano | 12 | 1740kB/s | 58 | 100% | -| 1 | Mega | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | -| 1 | Mega | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 99.9% | -| 1 | Mega | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 99.9% | -| 1 | Mega | 12 | ESP32 40MHz | 12 | 1710kB/s | 57 | 96.49% | -| 1 | Mega | 12 | ESP32 80MHz | 12 | 1710kB/s | 57 | 96.49% | -| 1 | Mega | 12 | ESP32 40MHz | 25 | 1710kB/s | 57 | 96.49% | -| 1 | Mega | 12 | ESP32 80MHz | 25 | 1710kB/s | 57 | 96.49% | -| 1 | Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | -| 1 | Mega | 12 | SAMD21 | D1 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 80MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 160MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 80MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 160MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP8266 80MHz | D1 | Blue pill | PB9 | | | | -| 1 | ESP8266 160MHz | D1 | Blue pill | PB9 | | | | -| 1 | ESP32 80MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP32 40MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | -| 1 | ESP32 | 12 | Blue pill | PB9 | 1800kB/s | 60 | 100% | -| 1 | SAMD21 | D0 | Mega | 12 | 1770kB/s | 59 | 100% | -| 1 | SAMD21 | D0 | Leonardo/Micro | 12 | 1710kB/s | 57 | 100% | -| 1 | SAMD21 | D0 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | -| 1 | SAMD21 | D0 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | -| 1 | SAMD21 | D0 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | -| 1 | SAMD21 | D0 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | -| 1 | SAMD21 | D0 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | -| 1 | SAMD21 | D0 | Blue pill | PB9 | 1860kB/s | 61 | 100% | -| 1 | Blue pill | PB9 | Blue pill | PB9 | 1830kB/s | 61 | 100% | -| 1 | Blue pill | PB9 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | -| 1 | Blue pill | PB9 | SAMD | 12 | 1830kB/s | 61 | 100% | -| 1 | Blue pill | PB9 | ESP8266 80MHz | D1 | 1788kB/s | 60 | 99.33% | -| 1 | Blue pill | PB9 | ESP8266 160MHz | D1 | 1800kB/s | 60 | 100% | +| MODE | TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | Timing Compliance | +|------|----------------|-----|----------------|-----|-----------|-----------|--------------|-------------------| +| 1 # | UNO/Nano | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | complete | +| 1 # | UNO/Nano | 11 | UNO/Nano | 11 | 1740kB/s | 58 | 100% | complete | +| 1 # | UNO/Nano | 10 | UNO/Nano | 10 | 1710kB/s | 57 | 100% | none | +| 1 # | UNO/Nano | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | complete | +| 1 # | UNO/Nano | 12 | Mega | 12 | 1770kB/s | 59 | 100% | complete | +| 1 | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | complete | +| 1 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | complete | +| 1 | UNO/Nano | 12 | ESP32 40MHz | 12 | 1770kB/s | 59 | 100% | complete | +| 1 | UNO/Nano | 12 | ESP32 80MHz | 12 | 1770kB/s | 59 | 100% | complete | +| 1 | UNO/Nano | 12 | ESP32 40MHz | 25 | 1770kB/s | 59 | 100% | complete | +| 1 | UNO/Nano | 12 | ESP32 80MHz | 25 | 1770kB/s | 59 | 100% | complete | +| 1 # | UNO/Nano | 12 | SAMD21 | D0 | 1800kB/s | 60 | 100% | complete | +| 1 | UNO/Nano | 12 | Blue pill | PB9 | 1770kB/s | 59 | 100% | complete | +| 1 # | Leonardo/Micro | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | incomplete | +| 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 99.998% | incomplete | +| 1 | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | incomplete | +| 1 | Leonardo/Micro | 12 | ESP32 40MHz | 12 | 1590kB/s | 53 | 88.68% | incomplete | +| 1 | Leonardo/Micro | 12 | ESP32 80MHz | 12 | 1590kB/s | 53 | 88.68% | incomplete | +| 1 | Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | incomplete | +| 1 # | Mega | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | complete | +| 1 | Mega | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | complete | +| 1 | Mega | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 99.9% | complete | +| 1 | Mega | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 99.9% | complete | +| 1 | Mega | 12 | ESP32 40MHz | 12 | 1710kB/s | 57 | 96.49% | complete | +| 1 | Mega | 12 | ESP32 80MHz | 12 | 1710kB/s | 57 | 96.49% | complete | +| 1 | Mega | 12 | ESP32 40MHz | 25 | 1710kB/s | 57 | 96.49% | complete | +| 1 | Mega | 12 | ESP32 80MHz | 25 | 1710kB/s | 57 | 96.49% | complete | +| 1 | Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | complete | +| 1 | Mega | 12 | SAMD21 | D1 | 1770kB/s | 59 | 100% | complete | +| 1 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | +| 1 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | +| 1 | ESP8266 80MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | +| 1 | ESP8266 160MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | +| 1 | ESP8266 80MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | | +| 1 | ESP8266 160MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | | +| 1 | ESP8266 80MHz | D1 | Blue pill | PB9 | | | | | +| 1 | ESP8266 160MHz | D1 | Blue pill | PB9 | | | | | +| 1 | ESP32 80MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | +| 1 | ESP32 40MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | +| 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | +| 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | +| 1 | ESP32 | 12 | Blue pill | PB9 | 1800kB/s | 60 | 100% | | +| 1 # | SAMD21 | D0 | Mega | 12 | 1770kB/s | 59 | 100% | complete | +| 1 | SAMD21 | D0 | Leonardo/Micro | 12 | 1710kB/s | 57 | 100% | complete | +| 1 # | SAMD21 | D0 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | complete | +| 1 | SAMD21 | D0 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | complete | +| 1 | SAMD21 | D0 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | complete | +| 1 | SAMD21 | D0 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | complete | +| 1 | SAMD21 | D0 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | complete | +| 1 | SAMD21 | D0 | Blue pill | PB9 | 1860kB/s | 61 | 100% | complete | +| 1 | Blue pill | PB9 | Blue pill | PB9 | 1830kB/s | 61 | 100% | | +| 1 | Blue pill | PB9 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | | +| 1 | Blue pill | PB9 | SAMD | 12 | 1830kB/s | 61 | 100% | | +| 1 | Blue pill | PB9 | ESP8266 80MHz | D1 | 1788kB/s | 60 | 99.33% | | +| 1 | Blue pill | PB9 | ESP8266 160MHz | D1 | 1800kB/s | 60 | 100% | | ### Mode 2 From db86f9431500190f99033eeb64a207a1e3c321e3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 29 Aug 2020 05:49:21 +0200 Subject: [PATCH 199/323] SoftwareBitBang NetworkAnalysis test results column added --- .../tests/NetworkAnalysis-10s.md | 76 +++++++++---------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index 4e95101052..76b636f581 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -3,37 +3,37 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO ### Mode 1 -| MODE | TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | Timing Compliance | +| MODE | TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | Compliant timing | |------|----------------|-----|----------------|-----|-----------|-----------|--------------|-------------------| -| 1 # | UNO/Nano | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | complete | -| 1 # | UNO/Nano | 11 | UNO/Nano | 11 | 1740kB/s | 58 | 100% | complete | -| 1 # | UNO/Nano | 10 | UNO/Nano | 10 | 1710kB/s | 57 | 100% | none | -| 1 # | UNO/Nano | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | complete | -| 1 # | UNO/Nano | 12 | Mega | 12 | 1770kB/s | 59 | 100% | complete | -| 1 | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | complete | -| 1 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | complete | -| 1 | UNO/Nano | 12 | ESP32 40MHz | 12 | 1770kB/s | 59 | 100% | complete | -| 1 | UNO/Nano | 12 | ESP32 80MHz | 12 | 1770kB/s | 59 | 100% | complete | -| 1 | UNO/Nano | 12 | ESP32 40MHz | 25 | 1770kB/s | 59 | 100% | complete | -| 1 | UNO/Nano | 12 | ESP32 80MHz | 25 | 1770kB/s | 59 | 100% | complete | -| 1 # | UNO/Nano | 12 | SAMD21 | D0 | 1800kB/s | 60 | 100% | complete | -| 1 | UNO/Nano | 12 | Blue pill | PB9 | 1770kB/s | 59 | 100% | complete | -| 1 # | Leonardo/Micro | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | incomplete | -| 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 99.998% | incomplete | -| 1 | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | incomplete | -| 1 | Leonardo/Micro | 12 | ESP32 40MHz | 12 | 1590kB/s | 53 | 88.68% | incomplete | -| 1 | Leonardo/Micro | 12 | ESP32 80MHz | 12 | 1590kB/s | 53 | 88.68% | incomplete | -| 1 | Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | incomplete | -| 1 # | Mega | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | complete | -| 1 | Mega | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | complete | -| 1 | Mega | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 99.9% | complete | -| 1 | Mega | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 99.9% | complete | -| 1 | Mega | 12 | ESP32 40MHz | 12 | 1710kB/s | 57 | 96.49% | complete | -| 1 | Mega | 12 | ESP32 80MHz | 12 | 1710kB/s | 57 | 96.49% | complete | -| 1 | Mega | 12 | ESP32 40MHz | 25 | 1710kB/s | 57 | 96.49% | complete | -| 1 | Mega | 12 | ESP32 80MHz | 25 | 1710kB/s | 57 | 96.49% | complete | -| 1 | Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | complete | -| 1 | Mega | 12 | SAMD21 | D1 | 1770kB/s | 59 | 100% | complete | +| 1 # | UNO/Nano | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | yes | +| 1 # | UNO/Nano | 11 | UNO/Nano | 11 | 1740kB/s | 58 | 100% | yes | +| 1 # | UNO/Nano | 10 | UNO/Nano | 10 | 1710kB/s | 57 | 100% | no | +| 1 # | UNO/Nano | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | yes | +| 1 # | UNO/Nano | 12 | Mega | 12 | 1770kB/s | 59 | 100% | yes | +| 1 | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | yes | +| 1 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | yes | +| 1 | UNO/Nano | 12 | ESP32 40MHz | 12 | 1770kB/s | 59 | 100% | yes | +| 1 | UNO/Nano | 12 | ESP32 80MHz | 12 | 1770kB/s | 59 | 100% | yes | +| 1 | UNO/Nano | 12 | ESP32 40MHz | 25 | 1770kB/s | 59 | 100% | yes | +| 1 | UNO/Nano | 12 | ESP32 80MHz | 25 | 1770kB/s | 59 | 100% | yes | +| 1 # | UNO/Nano | 12 | SAMD21 | D0 | 1800kB/s | 60 | 100% | yes | +| 1 | UNO/Nano | 12 | Blue pill | PB9 | 1770kB/s | 59 | 100% | yes | +| 1 # | Leonardo/Micro | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | no | +| 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 99.998% | no | +| 1 | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | no | +| 1 | Leonardo/Micro | 12 | ESP32 40MHz | 12 | 1590kB/s | 53 | 88.68% | no | +| 1 | Leonardo/Micro | 12 | ESP32 80MHz | 12 | 1590kB/s | 53 | 88.68% | no | +| 1 | Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | no | +| 1 # | Mega | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | yes | +| 1 | Mega | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | yes | +| 1 | Mega | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 99.9% | yes | +| 1 | Mega | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 99.9% | yes | +| 1 | Mega | 12 | ESP32 40MHz | 12 | 1710kB/s | 57 | 96.49% | yes | +| 1 | Mega | 12 | ESP32 80MHz | 12 | 1710kB/s | 57 | 96.49% | yes | +| 1 | Mega | 12 | ESP32 40MHz | 25 | 1710kB/s | 57 | 96.49% | yes | +| 1 | Mega | 12 | ESP32 80MHz | 25 | 1710kB/s | 57 | 96.49% | yes | +| 1 | Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | yes | +| 1 | Mega | 12 | SAMD21 | D1 | 1770kB/s | 59 | 100% | yes | | 1 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | | 1 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | | 1 | ESP8266 80MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | @@ -47,14 +47,14 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | | 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | | 1 | ESP32 | 12 | Blue pill | PB9 | 1800kB/s | 60 | 100% | | -| 1 # | SAMD21 | D0 | Mega | 12 | 1770kB/s | 59 | 100% | complete | -| 1 | SAMD21 | D0 | Leonardo/Micro | 12 | 1710kB/s | 57 | 100% | complete | -| 1 # | SAMD21 | D0 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | complete | -| 1 | SAMD21 | D0 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | complete | -| 1 | SAMD21 | D0 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | complete | -| 1 | SAMD21 | D0 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | complete | -| 1 | SAMD21 | D0 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | complete | -| 1 | SAMD21 | D0 | Blue pill | PB9 | 1860kB/s | 61 | 100% | complete | +| 1 # | SAMD21 | D0 | Mega | 12 | 1770kB/s | 59 | 100% | yes | +| 1 | SAMD21 | D0 | Leonardo/Micro | 12 | 1710kB/s | 57 | 100% | yes | +| 1 # | SAMD21 | D0 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | yes | +| 1 | SAMD21 | D0 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | yes | +| 1 | SAMD21 | D0 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | yes | +| 1 | SAMD21 | D0 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | yes | +| 1 | SAMD21 | D0 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | yes | +| 1 | SAMD21 | D0 | Blue pill | PB9 | 1860kB/s | 61 | 100% | yes | | 1 | Blue pill | PB9 | Blue pill | PB9 | 1830kB/s | 61 | 100% | | | 1 | Blue pill | PB9 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | | | 1 | Blue pill | PB9 | SAMD | 12 | 1830kB/s | 61 | 100% | | From 57aa3df2cd861c877024f04c5356c8972c846b6f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Sep 2020 22:19:09 +0200 Subject: [PATCH 200/323] SoftwareBitBang Uno/Nano, ESP8266 and ESP32 timing update --- src/strategies/SoftwareBitBang/README.md | 1 - src/strategies/SoftwareBitBang/Timing.h | 18 ++++---- .../tests/NetworkAnalysis-10s.md | 42 ++++++++++--------- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index 36c61c1727..e5befaf033 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -59,7 +59,6 @@ Before including the library it is possible to configure `SoftwareBitBang` using | Constant | Purpose | Supported value | | ----------------------- |------------------------------------ | ------------------------------------------ | | `SWBB_MODE` | Data transmission mode | 1, 2, 3, 4 | -| `SWBB_RESPONSE_TIMEOUT` | Maximum response time-out | Duration in microseconds (1500 by default) | | `SWBB_BACK_OFF_DEGREE` | Maximum back-off exponential degree | Numeric value (4 by default) | | `SWBB_MAX_ATTEMPTS` | Maximum transmission attempts | Numeric value (20 by default) | diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 61bfe8dba7..8ec0243ef4 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -33,7 +33,7 @@ #define SWBB_BIT_WIDTH 39 #define SWBB_BIT_SPACER 106 #define SWBB_ACCEPTANCE 53 - #define SWBB_READ_DELAY 3 + #define SWBB_READ_DELAY 2 #endif #endif #if SWBB_MODE == 2 @@ -183,17 +183,17 @@ Added full support to MODE 1 (80 and 160MHz) - 12/06/2018 */ #if (F_CPU == 80000000L) /* Working on pin: D1 or GPIO 5 */ - #define SWBB_BIT_WIDTH 43.5 - #define SWBB_BIT_SPACER 109.5 + #define SWBB_BIT_WIDTH 42.5 + #define SWBB_BIT_SPACER 108.5 #define SWBB_ACCEPTANCE 52 - #define SWBB_READ_DELAY -6 + #define SWBB_READ_DELAY -3.5 #endif #if (F_CPU == 160000000L) /* Working on pin: D1 or GPIO 5 */ - #define SWBB_BIT_WIDTH 44 - #define SWBB_BIT_SPACER 110 + #define SWBB_BIT_WIDTH 43 + #define SWBB_BIT_SPACER 109 #define SWBB_ACCEPTANCE 52 - #define SWBB_READ_DELAY -6 + #define SWBB_READ_DELAY -7 #endif #endif #endif @@ -203,10 +203,10 @@ #if SWBB_MODE == 1 /* Added full support to MODE 1 - 28/06/2018 Working on pin: 12 and 25 */ - #define SWBB_BIT_WIDTH 44 + #define SWBB_BIT_WIDTH 43 #define SWBB_BIT_SPACER 110 #define SWBB_ACCEPTANCE 56 - #define SWBB_READ_DELAY -2 + #define SWBB_READ_DELAY -3 #endif #endif diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md index 76b636f581..06667b4022 100644 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md @@ -7,18 +7,18 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO |------|----------------|-----|----------------|-----|-----------|-----------|--------------|-------------------| | 1 # | UNO/Nano | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | yes | | 1 # | UNO/Nano | 11 | UNO/Nano | 11 | 1740kB/s | 58 | 100% | yes | -| 1 # | UNO/Nano | 10 | UNO/Nano | 10 | 1710kB/s | 57 | 100% | no | +| 1 | UNO/Nano | 10 | UNO/Nano | 10 | 1710kB/s | 57 | 100% | no | | 1 # | UNO/Nano | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | yes | | 1 # | UNO/Nano | 12 | Mega | 12 | 1770kB/s | 59 | 100% | yes | -| 1 | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 100% | yes | -| 1 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 100% | yes | -| 1 | UNO/Nano | 12 | ESP32 40MHz | 12 | 1770kB/s | 59 | 100% | yes | -| 1 | UNO/Nano | 12 | ESP32 80MHz | 12 | 1770kB/s | 59 | 100% | yes | -| 1 | UNO/Nano | 12 | ESP32 40MHz | 25 | 1770kB/s | 59 | 100% | yes | -| 1 | UNO/Nano | 12 | ESP32 80MHz | 25 | 1770kB/s | 59 | 100% | yes | +| 1 # | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1785kB/s | 59-60 | 99.66% | yes | +| 1 # | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1785kB/s | 59-60 | 99.66% | yes | +| 1 # | UNO/Nano | 12 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | yes | +| 1 # | UNO/Nano | 12 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | yes | +| 1 # | UNO/Nano | 12 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | yes | +| 1 # | UNO/Nano | 12 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | yes | | 1 # | UNO/Nano | 12 | SAMD21 | D0 | 1800kB/s | 60 | 100% | yes | | 1 | UNO/Nano | 12 | Blue pill | PB9 | 1770kB/s | 59 | 100% | yes | -| 1 # | Leonardo/Micro | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | no | +| 1 | Leonardo/Micro | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | no | | 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 99.998% | no | | 1 | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | no | | 1 | Leonardo/Micro | 12 | ESP32 40MHz | 12 | 1590kB/s | 53 | 88.68% | no | @@ -26,30 +26,32 @@ This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO | 1 | Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | no | | 1 # | Mega | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | yes | | 1 | Mega | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | yes | -| 1 | Mega | 12 | ESP8266 80MHz | D1 | 1770kB/s | 59 | 99.9% | yes | -| 1 | Mega | 12 | ESP8266 160MHz | D1 | 1770kB/s | 59 | 99.9% | yes | -| 1 | Mega | 12 | ESP32 40MHz | 12 | 1710kB/s | 57 | 96.49% | yes | -| 1 | Mega | 12 | ESP32 80MHz | 12 | 1710kB/s | 57 | 96.49% | yes | +| 1 # | Mega | 12 | ESP8266 80MHz | D1 | 1797kB/s | 59-60 | 99.9% | yes | +| 1 # | Mega | 12 | ESP8266 160MHz | D1 | 1797kB/s | 59-60 | 99.9% | yes | +| 1 # | Mega | 12 | ESP32 40MHz | 12 | 1710kB/s | 57-60 | 96.49% | yes | +| 1 # | Mega | 12 | ESP32 80MHz | 12 | 1710kB/s | 57-60 | 96.49% | yes | | 1 | Mega | 12 | ESP32 40MHz | 25 | 1710kB/s | 57 | 96.49% | yes | | 1 | Mega | 12 | ESP32 80MHz | 25 | 1710kB/s | 57 | 96.49% | yes | | 1 | Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | yes | | 1 | Mega | 12 | SAMD21 | D1 | 1770kB/s | 59 | 100% | yes | -| 1 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | -| 1 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | +| 1 # | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | yes | +| 1 # | ESP8266 160MHz | D1 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | yes | | 1 | ESP8266 80MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | | 1 | ESP8266 160MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | -| 1 | ESP8266 80MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | | -| 1 | ESP8266 160MHz | D1 | Mega | 12 | 1770kB/s | 59 | 100% | | +| 1 # | ESP8266 80MHz | D1 | Mega | 12 | 1800kB/s | 60 | 100% | yes | +| 1 # | ESP8266 160MHz | D1 | Mega | 12 | 1800kB/s | 60 | 100% | yes | | 1 | ESP8266 80MHz | D1 | Blue pill | PB9 | | | | | | 1 | ESP8266 160MHz | D1 | Blue pill | PB9 | | | | | -| 1 | ESP32 80MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | -| 1 | ESP32 40MHz | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | | +| 1 # | ESP32 80MHz | 12 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | yes | +| 1 # | ESP32 40MHz | 12 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | yes | +| 1 # | ESP32 40MHz | 12 | Mega | 12 | 1800kB/s | 60 | 100% | yes | +| 1 # | ESP32 80MHz | 12 | Mega | 12 | 1800kB/s | 60 | 100% | yes | | 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | | 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | | 1 | ESP32 | 12 | Blue pill | PB9 | 1800kB/s | 60 | 100% | | -| 1 # | SAMD21 | D0 | Mega | 12 | 1770kB/s | 59 | 100% | yes | +| 1 # | SAMD21 | D0 | Mega | 12 | 1800kB/s | 60 | 100% | yes | | 1 | SAMD21 | D0 | Leonardo/Micro | 12 | 1710kB/s | 57 | 100% | yes | -| 1 # | SAMD21 | D0 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | yes | +| 1 | SAMD21 | D0 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | yes | | 1 | SAMD21 | D0 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | yes | | 1 | SAMD21 | D0 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | yes | | 1 | SAMD21 | D0 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | yes | From de972c98ba14c54923c1e31616e7e5bae54bc90a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Sep 2020 21:35:59 +0200 Subject: [PATCH 201/323] PJDL v5.0 deviation update, SoftwareBitBang timing revert to 12.1 Deviation is now specified as asymmetric with a bias for the positive domain in all modes --- src/strategies/SoftwareBitBang/Timing.h | 117 +++++++++--------- .../specification/PJDL-specification-v5.0.md | 20 +-- 2 files changed, 72 insertions(+), 65 deletions(-) diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 8ec0243ef4..dc07e3ff8b 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -30,10 +30,10 @@ #if SWBB_MODE == 1 #if F_CPU == 16000000L /* Working on pin: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, A0, A1 */ - #define SWBB_BIT_WIDTH 39 - #define SWBB_BIT_SPACER 106 - #define SWBB_ACCEPTANCE 53 - #define SWBB_READ_DELAY 2 + #define SWBB_BIT_WIDTH 40 + #define SWBB_BIT_SPACER 112 + #define SWBB_ACCEPTANCE 56 + #define SWBB_READ_DELAY 4 #endif #endif #if SWBB_MODE == 2 @@ -71,7 +71,7 @@ #if F_CPU == 16000000L /* Working on pin: 10 */ #define SWBB_BIT_WIDTH 37 - #define SWBB_BIT_SPACER 104 + #define SWBB_BIT_SPACER 110 #define SWBB_ACCEPTANCE 56 #define SWBB_READ_DELAY 4 #endif @@ -91,15 +91,19 @@ /* ATmega16/32U4 - Arduino Leonardo/Micro --------------------------------- */ #if defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) #if SWBB_MODE == 1 - /* Working on pin: 2, 4, 8, 12 */ - #define SWBB_BIT_WIDTH 39 - #define SWBB_BIT_SPACER 102 - #define SWBB_ACCEPTANCE 53 - #define SWBB_READ_DELAY 6 + /* Working on pin: 2, 4, 8, 12 + Fallback to default timing */ + #define SWBB_BIT_WIDTH 40 + #define SWBB_BIT_SPACER 112 + #define SWBB_ACCEPTANCE 56 + #define SWBB_READ_DELAY 8 #endif #if SWBB_MODE == 2 /* Working on pin: 2, 4, 8, 12 Fallback to default timing */ + #define SWBB_BIT_WIDTH 36 + #define SWBB_BIT_SPACER 88 + #define SWBB_ACCEPTANCE 56 #define SWBB_READ_DELAY 12 #endif #endif @@ -108,9 +112,9 @@ #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #if SWBB_MODE == 1 /* Working on pin: 3, 4, 7, 8, 9, 10, 12 */ - #define SWBB_BIT_WIDTH 37 - #define SWBB_BIT_SPACER 104 - #define SWBB_ACCEPTANCE 53 + #define SWBB_BIT_WIDTH 38 + #define SWBB_BIT_SPACER 110 + #define SWBB_ACCEPTANCE 62 #define SWBB_READ_DELAY 11 #endif #if SWBB_MODE == 2 @@ -128,12 +132,20 @@ #if F_CPU == 16000000L /* Working on pin: 1, 2 Fallback to default */ + #define SWBB_BIT_WIDTH 40 + #define SWBB_BIT_SPACER 112 + #define SWBB_ACCEPTANCE 56 + #define SWBB_READ_DELAY 4 #endif #endif #if SWBB_MODE == 2 #if F_CPU == 16000000L /* Working on pin: 1, 2 Fallback to default */ + #define SWBB_BIT_WIDTH 36 + #define SWBB_BIT_SPACER 88 + #define SWBB_ACCEPTANCE 56 + #define SWBB_READ_DELAY 4 #endif #endif #endif @@ -145,12 +157,20 @@ #if F_CPU == 16000000L /* Working on pin: 0, 1, 2, 3, 4 Fallback to default */ + #define SWBB_BIT_WIDTH 40 + #define SWBB_BIT_SPACER 112 + #define SWBB_ACCEPTANCE 56 + #define SWBB_READ_DELAY 4 #endif #endif #if SWBB_MODE == 2 #if F_CPU == 16000000L /* Working on pin: 0, 1, 2, 3, 4 Fallback to default */ + #define SWBB_BIT_WIDTH 36 + #define SWBB_BIT_SPACER 88 + #define SWBB_ACCEPTANCE 56 + #define SWBB_READ_DELAY 4 #endif #endif #endif @@ -159,20 +179,12 @@ #if defined(ARDUINO_SAMD_ZERO) #if SWBB_MODE == 1 /* Added by Esben Soeltoft - 03/09/2016 - Updated by Giovanni Blu Mitolo - 21/07/2020 + Updated by Giovanni Blu Mitolo - 31/05/2019 Working on pin: D0, D1, D3, A0, A1 */ - #define SWBB_BIT_WIDTH 42 - #define SWBB_BIT_SPACER 109.5 - #define SWBB_ACCEPTANCE 45 - #define SWBB_READ_DELAY -2.5 - #endif - /* Added by Giovanni Blu Mitolo 30/07/2020 - Tested on pin: D0 */ - #if SWBB_MODE == 2 - #define SWBB_BIT_WIDTH 39.5 - #define SWBB_BIT_SPACER 91.5 - #define SWBB_ACCEPTANCE 45 - #define SWBB_READ_DELAY -2 + #define SWBB_BIT_WIDTH 43 + #define SWBB_BIT_SPACER 115 + #define SWBB_ACCEPTANCE 40 + #define SWBB_READ_DELAY -4 #endif #endif @@ -181,19 +193,12 @@ #if SWBB_MODE == 1 /* Added by github user 240974a - 09/03/2016 Added full support to MODE 1 (80 and 160MHz) - 12/06/2018 */ - #if (F_CPU == 80000000L) + #if (F_CPU == 80000000L) || (F_CPU == 160000000L) /* Working on pin: D1 or GPIO 5 */ - #define SWBB_BIT_WIDTH 42.5 - #define SWBB_BIT_SPACER 108.5 - #define SWBB_ACCEPTANCE 52 - #define SWBB_READ_DELAY -3.5 - #endif - #if (F_CPU == 160000000L) - /* Working on pin: D1 or GPIO 5 */ - #define SWBB_BIT_WIDTH 43 - #define SWBB_BIT_SPACER 109 - #define SWBB_ACCEPTANCE 52 - #define SWBB_READ_DELAY -7 + #define SWBB_BIT_WIDTH 44 + #define SWBB_BIT_SPACER 112 + #define SWBB_ACCEPTANCE 56 + #define SWBB_READ_DELAY -6 #endif #endif #endif @@ -203,10 +208,10 @@ #if SWBB_MODE == 1 /* Added full support to MODE 1 - 28/06/2018 Working on pin: 12 and 25 */ - #define SWBB_BIT_WIDTH 43 - #define SWBB_BIT_SPACER 110 + #define SWBB_BIT_WIDTH 44 + #define SWBB_BIT_SPACER 112 #define SWBB_ACCEPTANCE 56 - #define SWBB_READ_DELAY -3 + #define SWBB_READ_DELAY -2 #endif #endif @@ -223,25 +228,25 @@ #endif #endif + /* STM32F1 ---------------------------------------------------------------- */ -/* Added by jcallano - 09-07-2020 - Working on pin: PB15, PB14, PB13, PB12, PB11, PB10, PB9, PB8, PB7, PB6, PB4, - PB3, PA15, PA10. 5v tolerant pins on bluepill */ +/* Mod by @jcallano on 09-jul-2020 only tested on PB9 pin. */ + #if defined(__STM32F1__) #if SWBB_MODE == 1 #if F_CPU == 72000000L - #define SWBB_BIT_WIDTH 43.5 - #define SWBB_BIT_SPACER 109.5 - #define SWBB_ACCEPTANCE 75 - #define SWBB_READ_DELAY -6 + #define SWBB_BIT_WIDTH 43 + #define SWBB_BIT_SPACER 115 + #define SWBB_ACCEPTANCE 60 + #define SWBB_READ_DELAY 3 #endif #endif #if SWBB_MODE == 2 #if F_CPU == 72000000L - #define SWBB_BIT_WIDTH 39.5 - #define SWBB_BIT_SPACER 91.5 - #define SWBB_ACCEPTANCE 53 - #define SWBB_READ_DELAY -8 + #define SWBB_BIT_WIDTH 39 + #define SWBB_BIT_SPACER 91 + #define SWBB_ACCEPTANCE 47 + #define SWBB_READ_DELAY 3 #endif #endif #if SWBB_MODE == 3 @@ -265,16 +270,16 @@ /* Avoid error if any previous defined ------------------------------------ */ #if SWBB_MODE == 1 #ifndef SWBB_BIT_WIDTH - #define SWBB_BIT_WIDTH 39 + #define SWBB_BIT_WIDTH 40 #endif #ifndef SWBB_BIT_SPACER - #define SWBB_BIT_SPACER 106 + #define SWBB_BIT_SPACER 112 #endif #ifndef SWBB_ACCEPTANCE - #define SWBB_ACCEPTANCE 53 + #define SWBB_ACCEPTANCE 56 #endif #ifndef SWBB_READ_DELAY - #define SWBB_READ_DELAY 3 + #define SWBB_READ_DELAY 4 #endif #ifndef SWBB_LATENCY #define SWBB_LATENCY 13 diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index dafd6eac63..b188cd75d9 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -29,7 +29,7 @@ Released into the public domain 29/12/2018 3.0 - Medium access control info, mode 4 03/07/2019 4.0 - Response initializer 10/03/2020 4.1 - Maximum range experimentally determined -17/07/2020 5.0 - Response timeout, deviation added +17/07/2020 5.0 - Response timeout, tolerance added ``` PJDL (Padded Jittering Data Link) is an asynchronous serial data link for low-data-rate applications that supports both master-slave and multi-master communication over a common conductive medium. PJDL can be easily implemented on limited microcontrollers with low clock accuracy and can operate directly using a single input-output pin. @@ -59,14 +59,16 @@ The proposed communication modes are the result of years of testing and optimiza | 3 | 3.10kB/s - 24844Bd | 1200m | 70µs | 28µs | 7µs | 8µs | 20µs/B | | 4 | 3.34kB/s - 26755Bd | 800m | 65µs | 26µs | 6.5µs | 5µs | 20µs/B | -The following table specifies the maximum acceptable deviation of each bit type: +The following table specifies the exclusive acceptable tolerance of each bit type: -| Mode | Max data bit nonet deviation | Max padding bit deviation | Max keep busy bit deviation | -| ---- | ---------------------------- | ------------------------- | --------------------------- | -| 1 | +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | -5µs +10µs | -| 2 | +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | -5µs +10µs | -| 3 | +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | -3µs +10µs | -| 4 | +- (data bit / 4) - 1 | +- (data bit / 4) - 1 | -3µs +10µs | +| Mode | Data bit nonet tolerance | Padding bit tolerance | Max keep busy bit tolerance | +| ---- | -------------------------| --------------------- | ---------------------------- | +| 1 | -5us +17us | -5us +17us | -5µs +10µs | +| 2 | -4us +16us | -4us +16us | -5µs +10µs | +| 3 | -3us +11us | -3us +11us | -3µs +10µs | +| 4 | -3us +10us | -3us +10us | -3µs +10µs | + +Positive tolerance is higher to accept bit-banged signals that are generally longer than expected. ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. @@ -79,7 +81,7 @@ The reception technique is based on 3 steps: 2. Synchronize with its falling edge 3. Ensure it is followed by a low data bit -If so reception starts, if not, interference, synchronization loss or simply absence of communication is detected. The high padding bit is 2.5 times longer than data bits because with this ratio ambiguity between padding bits and 2 or 3 consecutive data bits is avoided even with an overall deviation of up to +- (data bit / 4) - 1. A synchronization pad is acceptable if prepended by a 0 of up to (data bit / 4) - 1. +If so reception starts, if not, interference, synchronization loss or simply absence of communication is detected. While receiving a sequence of bytes a synchronization pad is acceptable even if prepended by a 0 of up to (data bit / 4) - 1. ```cpp ___________ ___________________________ From cde07aba6ef799588f5e41fc2da9fd081f0b9937 Mon Sep 17 00:00:00 2001 From: der-schne <62093862+der-schne@users.noreply.github.com> Date: Wed, 9 Sep 2020 12:25:02 +0200 Subject: [PATCH 202/323] Update PJON_IO.h I use it on a Arduino Nano from China with the custem Bootloder and it runs. After the instalation of the MicroCore Bootloader i must edit this File tu Rum my Program agene. Sorry 4 the bad englisch. --- src/interfaces/ARDUINO/PJON_IO.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/interfaces/ARDUINO/PJON_IO.h b/src/interfaces/ARDUINO/PJON_IO.h index ed1d4b7bd2..a0c327509d 100644 --- a/src/interfaces/ARDUINO/PJON_IO.h +++ b/src/interfaces/ARDUINO/PJON_IO.h @@ -95,6 +95,7 @@ inform the reader of their definition as macros in the global scope. /* AVR ATmega88/168/328/328P - Arduino Duemilanove, Uno, Nano, Mini, Pro -- */ #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || \ + defined(__AVR_ATmega168P__)|| \ defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || \ defined(__AVR_ATmega328PB__) #define PJON_IO_PIN_TO_PORT_REG(P) \ From 260e1ee9c4e18cab2831492949503556895af246 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Wed, 1 Jul 2020 10:21:06 +0200 Subject: [PATCH 203/323] zephyr: add kconfig parameter --- zephyr/CMakeLists.txt | 7 +++++++ zephyr/Kconfig | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index bff5b18b63..23df8099c4 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -1 +1,8 @@ +if(CONFIG_PJON) + zephyr_include_directories(../src) +add_compile_definitions(ZEPHYR) +zephyr_compile_definitions(ZEPHYR) + + +endif() diff --git a/zephyr/Kconfig b/zephyr/Kconfig index e69de29bb2..8ad3fb5fc6 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -0,0 +1,33 @@ +menuconfig PJON + bool "PJON communication protocol" + help + Enable the PJON protocol + +if PJON +choice + prompt "PJON strategy" + +config PJON_STRATEGY_DUALUDP + select NETWORKING + select NET_IPV4 + select NET_UDP + select NET_SOCKETS + bool "PJON strategy DualUDP" + + +config PJON_STRATEGY_THROUGHSERIAL + bool "PJON strategy Through Serial" +endchoice + +config PJON_DEVICE_ID + int "PJON Device ID" + default 255 + help + PJON Device ID + +config PJON_MTU + int "PJON MTU" + default 1400 + help + Maximum size of SMP frames send and receive over PJON DualUDP, in bytes. +endif From d9f6d3955200e63344aeb40e52c39683863a841a Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Wed, 8 Jul 2020 10:49:53 +0200 Subject: [PATCH 204/323] zephyr: select RING_BUFFER --- zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 8ad3fb5fc6..d3118cf50c 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -17,6 +17,7 @@ config PJON_STRATEGY_DUALUDP config PJON_STRATEGY_THROUGHSERIAL bool "PJON strategy Through Serial" + select RING_BUFFER endchoice config PJON_DEVICE_ID From 1d990e22c1b73b03ed44203b4795414d32ad9fa8 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Tue, 4 Aug 2020 14:58:53 +0200 Subject: [PATCH 205/323] zephyr: add support for rs485 txe pin --- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 21 +++++++++++++++++-- zephyr/Kconfig | 7 +++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h index ec83a8fca2..cc02759434 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -1,9 +1,12 @@ #if defined(ZEPHYR) +#define OUTPUT GPIO_OUTPUT + #include #include #include +#include #include #include #include @@ -39,6 +42,7 @@ static void uart_irq_callback(struct device *dev) } } +static struct device* pin_dev = NULL; static int serial_put_char(struct device* dev, uint8_t byte) { @@ -46,6 +50,19 @@ static int serial_put_char(struct device* dev, uint8_t byte) return 1; } +static void digitalWrite(int pin, bool state) +{ + gpio_pin_set(pin_dev, pin, state); + +} +static void pinMode(int pin, int mode) +{ + pin_dev = device_get_binding(DT_LABEL(DT_NODELABEL(dir))); + + gpio_pin_configure(pin_dev, pin, mode); + +} + // deal with randomness #ifndef PJON_RANDOM @@ -108,11 +125,11 @@ static int serial_put_char(struct device* dev, uint8_t byte) // feature of the rs485 transceiver #ifndef PJON_IO_WRITE -#define PJON_IO_WRITE(P, C) +#define PJON_IO_WRITE digitalWrite #endif #ifndef PJON_IO_MODE -#define PJON_IO_MODE(P, C) +#define PJON_IO_MODE pinMode #endif #ifndef LOW diff --git a/zephyr/Kconfig b/zephyr/Kconfig index d3118cf50c..57da81d5e1 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -4,8 +4,7 @@ menuconfig PJON Enable the PJON protocol if PJON -choice - prompt "PJON strategy" +menu "PJON strategy" config PJON_STRATEGY_DUALUDP select NETWORKING @@ -16,9 +15,9 @@ config PJON_STRATEGY_DUALUDP config PJON_STRATEGY_THROUGHSERIAL - bool "PJON strategy Through Serial" select RING_BUFFER -endchoice + bool "PJON strategy Through Serial" +endmenu config PJON_DEVICE_ID int "PJON Device ID" From 82f3fab9a9d38110fbd84281df2855c56669bc1e Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Wed, 26 Aug 2020 10:51:49 +0200 Subject: [PATCH 206/323] zephyr: use a new alias for pjon_txe_pin --- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h index cc02759434..0cde7bfed0 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -10,6 +10,7 @@ #include #include #include +#include RING_BUF_DECLARE(ringbuffer_pjon, CONFIG_PJON_MTU); static uint8_t tmp_buffer[40]; @@ -57,7 +58,7 @@ static void digitalWrite(int pin, bool state) } static void pinMode(int pin, int mode) { - pin_dev = device_get_binding(DT_LABEL(DT_NODELABEL(dir))); + pin_dev = device_get_binding(DT_GPIO_LABEL(DT_ALIAS(pjon_txe_pin), gpios)); gpio_pin_configure(pin_dev, pin, mode); From e88c6afbb59a570a5297e92405f1a71c3a6a5ea4 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Wed, 26 Aug 2020 10:55:44 +0200 Subject: [PATCH 207/323] zephyr: implement a simple serial_flush function --- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h index 0cde7bfed0..f1635b2435 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -64,6 +64,11 @@ static void pinMode(int pin, int mode) } +static void serial_flush(struct device* dev) +{ + k_usleep(10); +} + // deal with randomness #ifndef PJON_RANDOM @@ -119,7 +124,7 @@ static void pinMode(int pin, int mode) #endif #ifndef PJON_SERIAL_FLUSH -#define PJON_SERIAL_FLUSH(S) +#define PJON_SERIAL_FLUSH(S) serial_flush(S) #endif // io pin handling (for setting the rs485 txe pin) is not needed since we use the auto-direction From de6bff8104f06bc163c1182b33de4948c5c4faba Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Tue, 1 Sep 2020 16:12:47 +0200 Subject: [PATCH 208/323] zephyr: add a cpp file for PJON_ZEPHYR_Interface --- .../ZEPHYR/PJON_ZEPHYR_Interface.cpp | 133 ++++++++++++++++++ src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 80 ++--------- zephyr/CMakeLists.txt | 4 +- 3 files changed, 151 insertions(+), 66 deletions(-) create mode 100644 src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp new file mode 100644 index 0000000000..79c372db80 --- /dev/null +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp @@ -0,0 +1,133 @@ +#include "PJON_ZEPHYR_Interface.h" +#include + +#include +#include +#include +#include + +#include +#include +#include + +static struct device* pin_dev = NULL;; +#include "logging/log.h" +LOG_MODULE_REGISTER(PJON_SMP, LOG_LEVEL_INF); + + +static std::map ringbuffers; + + +static struct ring_buf* _get_ring_buf(struct device* dev) +{ + auto search = ringbuffers.find(dev); + struct ring_buf* tmp = nullptr; + if ( search != ringbuffers.end() ) { + tmp = search->second; + } + return tmp; +} + +struct device* serial_open(const char* dt_label) +{ + struct device* uart = device_get_binding(dt_label); ///@todo multiple uarts for this layer --SA + struct uart_config cfg; + uart_config_get(uart,&cfg); + cfg.data_bits = UART_CFG_DATA_BITS_8; + cfg.stop_bits = UART_CFG_STOP_BITS_1; + uart_configure(uart,&cfg); + ///todo: how to do this in PJON interface + uart_irq_callback_set(uart, uart_irq_callback); + uart_irq_rx_enable(uart); + + uint8_t* buf = (uint8_t*) calloc(1,CONFIG_PJON_MTU); + struct ring_buf* r = (struct ring_buf*) calloc(1, sizeof(struct ring_buf)); + r->size = CONFIG_PJON_MTU, + r->buf.buf8 = buf; + + auto ret = ringbuffers.insert(std::make_pair(uart, r)); + + LOG_INF("Size: %d", ringbuffers.size()); + + if (ret.second != true) { + uart = nullptr; + } + + LOG_INF("UART: %p", uart); + return uart; +} +void print_ringbuffer() +{ + LOG_INF("Ringbuffer: %p, size: %d",&ringbuffers, ringbuffers.size()); +} + +void serial_close(const char* dt_label) +{ + LOG_INF("close"); + // free((ringbuffers.at(dt_label))->buf.buf8); +} + +int serial_get_char(struct device* dev) +{ + size_t ret; + uint8_t b; + struct ring_buf* r = _get_ring_buf(dev); + if(r) { + ret = ring_buf_get(r, &b, sizeof(b)); + } + return b; +} + +bool serial_char_available(struct device* dev) +{ + struct ring_buf* r = _get_ring_buf(dev); + bool b = false; + if (r) { + b = !ring_buf_is_empty(r); + } + return b; +} + +///todo: implement this for different uarts --SA +void uart_irq_callback(struct device *dev) +{ + uart_irq_update(dev); + + if (uart_irq_rx_ready(dev)) { + uint8_t tmp; + while (1) { + if (uart_fifo_read(dev, &tmp, 1) == 0) { + break; + } + struct ring_buf* r = _get_ring_buf(dev); + + if (r) { + ring_buf_put(r, &tmp, sizeof(tmp)); + } + } + } +} + +int serial_put_char(struct device* dev, uint8_t b) +{ + uart_poll_out(dev,b); + return 1; +} + +void digitalWrite(int pin, bool state) +{ + gpio_pin_set(pin_dev, pin, state); + +} +void pinMode(int pin, int mode) +{ + pin_dev = device_get_binding(DT_GPIO_LABEL(DT_ALIAS(pjon_txe_pin), gpios)); + + gpio_pin_configure(pin_dev, pin, mode); + +} + +void serial_flush(struct device* dev) +{ + k_usleep(10); +} diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h index f1635b2435..da5a0963db 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -1,73 +1,23 @@ +#pragma once + #if defined(ZEPHYR) #define OUTPUT GPIO_OUTPUT -#include -#include -#include - #include -#include -#include -#include -#include - -RING_BUF_DECLARE(ringbuffer_pjon, CONFIG_PJON_MTU); -static uint8_t tmp_buffer[40]; -static int serial_get_char(struct device* dev) -{ - size_t ret; - uint8_t b; - ret = ring_buf_get(&ringbuffer_pjon, &b, sizeof(b)); - return b; -} - -static bool serial_char_available(struct device* dev) -{ - bool b = ring_buf_is_empty(&ringbuffer_pjon); - return !b; -} - -static void uart_irq_callback(struct device *dev) -{ - uart_irq_update(dev); - - if (uart_irq_rx_ready(dev)) { - uint8_t tmp; - while (1) { - if (uart_fifo_read(dev, &tmp, 1) == 0) { - break; - } - ring_buf_put(&ringbuffer_pjon, &tmp, sizeof(tmp)); - } - } -} - -static struct device* pin_dev = NULL; - -static int serial_put_char(struct device* dev, uint8_t byte) -{ - uart_poll_out(dev,byte); - return 1; -} - -static void digitalWrite(int pin, bool state) -{ - gpio_pin_set(pin_dev, pin, state); - -} -static void pinMode(int pin, int mode) -{ - pin_dev = device_get_binding(DT_GPIO_LABEL(DT_ALIAS(pjon_txe_pin), gpios)); - - gpio_pin_configure(pin_dev, pin, mode); - -} - -static void serial_flush(struct device* dev) -{ - k_usleep(10); -} +#include +#include +#include + +int serial_get_char(struct device* dev); +bool serial_char_available(struct device* dev); +void uart_irq_callback(struct device *dev); +int serial_put_char(struct device* dev, uint8_t byte); +struct device* serial_open(const char* dt_label); +void serial_close(const char* dt_label); +void digitalWrite(int pin, bool state); +void pinMode(int pin, int mode); +void serial_flush(struct device* dev); // deal with randomness diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 23df8099c4..e6dade2f1d 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -4,5 +4,7 @@ zephyr_include_directories(../src) add_compile_definitions(ZEPHYR) zephyr_compile_definitions(ZEPHYR) - +if(CONFIG_PJON_STRATEGY_THROUGHSERIAL) +zephyr_sources(../src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp) +endif() endif() From d862b38255e77b16039282592f3e66d4db263ec5 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Tue, 1 Sep 2020 16:23:15 +0200 Subject: [PATCH 209/323] zephyr: update kconfig file set default pjon address to PJON_NOT_ASSIGNED; also select SERIAL and UART_INTERRUPT_DRIVEN config --- zephyr/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 57da81d5e1..9e9d7d3cc7 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -16,12 +16,14 @@ config PJON_STRATEGY_DUALUDP config PJON_STRATEGY_THROUGHSERIAL select RING_BUFFER + select SERIAL + select UART_INTERRUPT_DRIVEN bool "PJON strategy Through Serial" endmenu config PJON_DEVICE_ID int "PJON Device ID" - default 255 + default 0 help PJON Device ID From 517feca7238e929091d1590eff6421f08d10e404 Mon Sep 17 00:00:00 2001 From: Fred Larsen Date: Sat, 12 Sep 2020 20:29:39 +0200 Subject: [PATCH 210/323] Improved F() macro redefinition tolerance --- src/strategies/EthernetTCP/EthernetLink.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/strategies/EthernetTCP/EthernetLink.h b/src/strategies/EthernetTCP/EthernetLink.h index 237a07b52d..6e4c9934b6 100644 --- a/src/strategies/EthernetTCP/EthernetLink.h +++ b/src/strategies/EthernetTCP/EthernetLink.h @@ -129,7 +129,9 @@ #include "../../interfaces/ARDUINO/TCPHelper_ARDUINO.h" #else #include "../../interfaces/LINUX/TCPHelper_POSIX.h" - const char *F(const char *s) { return s; } + #ifndef F + #define F(x) (x) + #endif #define Serial DummyPrint struct DummyPrint { static void print(const char *s) { printf("%s", s); } From 9a75585803aae9943e2b22f108a7a6eefe9dd251 Mon Sep 17 00:00:00 2001 From: Fred Larsen Date: Sat, 12 Sep 2020 20:30:04 +0200 Subject: [PATCH 211/323] Added support for extended leading sync pad width --- .../SoftwareBitBang/SoftwareBitBang.h | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index e3b7656920..d1b3c57ea7 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -43,6 +43,13 @@ #define SWBB_RECEIVE_TIME 1000 #endif +// The width of the initial spacer of a packet, can be increased from +// 1 to for example 3 to allow more "blind time" in modules not being +// able to call receive continuously. +#ifndef SWBB_INITIAL_SPACER_MULTIPLIER + #define SWBB_INITIAL_SPACER_MULTIPLIER 1 +#endif + class SoftwareBitBang { public: /* Returns the delay related to the attempts passed as parameter: */ @@ -172,7 +179,7 @@ class SoftwareBitBang { if(max_length == PJON_PACKET_MAX_LENGTH) { uint32_t time = PJON_MICROS(); // Look for a frame initializer - if(!sync() || !sync() || !sync()) return SWBB_FAIL; + if(!sync_first() || !sync() || !sync()) return SWBB_FAIL; // Check its timing consistency if( (uint32_t)(PJON_MICROS() - time) < @@ -279,14 +286,14 @@ class SoftwareBitBang { not, interference, synchronization loss or simply absence of communication is detected at byte level: */ - bool sync() { + bool sync(uint32_t spacer) { PJON_IO_PULL_DOWN(_input_pin); if((_output_pin != _input_pin) && (_output_pin != SWBB_NOT_ASSIGNED)) PJON_IO_PULL_DOWN(_output_pin); uint32_t time = PJON_MICROS(); while( PJON_IO_READ(_input_pin) && - ((uint32_t)(PJON_MICROS() - time) <= SWBB_BIT_SPACER) + ((uint32_t)(PJON_MICROS() - time) <= spacer) ); time = PJON_MICROS() - time; if(time < SWBB_ACCEPTANCE) @@ -301,9 +308,30 @@ class SoftwareBitBang { return false; }; + bool sync() { + return sync(SWBB_BIT_SPACER); + } + + bool sync_first() { + // Allow a wider packet start sampling interval for devices + // that do other tasks and cannot sample very fast. + return sync(SWBB_BIT_SPACER * SWBB_INITIAL_SPACER_MULTIPLIER); + }; + /* Emit synchronization pulse: */ void pulse(uint8_t n) { + #if SWBB_INITIAL_SPACER_MULTIPLIER != 1 + if (n == 3) { + // Extra long first pad of packet initializer, to tolerate devices + // that have other tasks and cannot sample continuously. + PJON_IO_WRITE(_output_pin, HIGH); + PJON_DELAY_MICROSECONDS(SWBB_BIT_SPACER * SWBB_INITIAL_SPACER_MULTIPLIER); + PJON_IO_WRITE(_output_pin, LOW); + PJON_DELAY_MICROSECONDS(SWBB_BIT_WIDTH); + n--; + } + #endif while(n--) { PJON_IO_WRITE(_output_pin, HIGH); PJON_DELAY_MICROSECONDS(SWBB_BIT_SPACER); From 2ef40eab6a00ffc873b385ae5024fa3c1665f0e3 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Tue, 8 Sep 2020 13:35:10 +0200 Subject: [PATCH 212/323] zephyr: TS: increase flush time to ensure that the last byte is correct transmitted --- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp index 79c372db80..d43bb1378f 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp @@ -129,5 +129,5 @@ void pinMode(int pin, int mode) void serial_flush(struct device* dev) { - k_usleep(10); + k_usleep(1000); } From 6d8e44ff08ced30c0e013e9cc02778ca20937c96 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Fri, 11 Sep 2020 13:44:33 +0200 Subject: [PATCH 213/323] zephyr: TS: free allocated memory if serial is close --- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp index d43bb1378f..c26f7d3147 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp @@ -63,8 +63,9 @@ void print_ringbuffer() void serial_close(const char* dt_label) { - LOG_INF("close"); - // free((ringbuffers.at(dt_label))->buf.buf8); + struct ring_buf * r = _get_ring_buf(device_get_binding(dt_label)); + free(r->buf.buf8); + free(r); } int serial_get_char(struct device* dev) From b704041a63922d1afb82230a84ca20bbb4cb7568 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Fri, 11 Sep 2020 14:22:11 +0200 Subject: [PATCH 214/323] zephyr: run lsp-format on PJON_ZEPHYR_Interface.cpp --- .../ZEPHYR/PJON_ZEPHYR_Interface.cpp | 58 +++++++++---------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp index c26f7d3147..6e42e47365 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp @@ -1,29 +1,28 @@ #include "PJON_ZEPHYR_Interface.h" #include +#include #include #include #include -#include -#include #include +#include #include -static struct device* pin_dev = NULL;; +static struct device* pin_dev = NULL; + #include "logging/log.h" LOG_MODULE_REGISTER(PJON_SMP, LOG_LEVEL_INF); - static std::map ringbuffers; - static struct ring_buf* _get_ring_buf(struct device* dev) { auto search = ringbuffers.find(dev); struct ring_buf* tmp = nullptr; - if ( search != ringbuffers.end() ) { - tmp = search->second; + if (search != ringbuffers.end()) { + tmp = search->second; } return tmp; } @@ -32,16 +31,16 @@ struct device* serial_open(const char* dt_label) { struct device* uart = device_get_binding(dt_label); ///@todo multiple uarts for this layer --SA struct uart_config cfg; - uart_config_get(uart,&cfg); + uart_config_get(uart, &cfg); cfg.data_bits = UART_CFG_DATA_BITS_8; cfg.stop_bits = UART_CFG_STOP_BITS_1; - uart_configure(uart,&cfg); - ///todo: how to do this in PJON interface + uart_configure(uart, &cfg); + uart_irq_callback_set(uart, uart_irq_callback); uart_irq_rx_enable(uart); - uint8_t* buf = (uint8_t*) calloc(1,CONFIG_PJON_MTU); - struct ring_buf* r = (struct ring_buf*) calloc(1, sizeof(struct ring_buf)); + uint8_t* buf = (uint8_t*)calloc(1, CONFIG_PJON_MTU); + struct ring_buf* r = (struct ring_buf*)calloc(1, sizeof(struct ring_buf)); r->size = CONFIG_PJON_MTU, r->buf.buf8 = buf; @@ -63,17 +62,17 @@ void print_ringbuffer() void serial_close(const char* dt_label) { - struct ring_buf * r = _get_ring_buf(device_get_binding(dt_label)); + struct ring_buf* r = _get_ring_buf(device_get_binding(dt_label)); free(r->buf.buf8); free(r); } int serial_get_char(struct device* dev) { - size_t ret; + size_t ret; uint8_t b; struct ring_buf* r = _get_ring_buf(dev); - if(r) { + if (r) { ret = ring_buf_get(r, &b, sizeof(b)); } return b; @@ -84,48 +83,45 @@ bool serial_char_available(struct device* dev) struct ring_buf* r = _get_ring_buf(dev); bool b = false; if (r) { - b = !ring_buf_is_empty(r); + b = !ring_buf_is_empty(r); } return b; } -///todo: implement this for different uarts --SA -void uart_irq_callback(struct device *dev) +void uart_irq_callback(struct device* dev) { - uart_irq_update(dev); + uart_irq_update(dev); - if (uart_irq_rx_ready(dev)) { + if (uart_irq_rx_ready(dev)) { uint8_t tmp; - while (1) { - if (uart_fifo_read(dev, &tmp, 1) == 0) { - break; - } - struct ring_buf* r = _get_ring_buf(dev); + while (1) { + if (uart_fifo_read(dev, &tmp, 1) == 0) { + break; + } + struct ring_buf* r = _get_ring_buf(dev); - if (r) { + if (r) { ring_buf_put(r, &tmp, sizeof(tmp)); - } - } + } + } } } int serial_put_char(struct device* dev, uint8_t b) { - uart_poll_out(dev,b); + uart_poll_out(dev, b); return 1; } void digitalWrite(int pin, bool state) { gpio_pin_set(pin_dev, pin, state); - } void pinMode(int pin, int mode) { pin_dev = device_get_binding(DT_GPIO_LABEL(DT_ALIAS(pjon_txe_pin), gpios)); gpio_pin_configure(pin_dev, pin, mode); - } void serial_flush(struct device* dev) From deb0f15c1dda1bb0e11adaad3bf50dd56ae71ea7 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Fri, 11 Sep 2020 14:22:36 +0200 Subject: [PATCH 215/323] zephyr: remove not needed code --- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp index 6e42e47365..a8aa22bda5 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp @@ -46,19 +46,12 @@ struct device* serial_open(const char* dt_label) auto ret = ringbuffers.insert(std::make_pair(uart, r)); - LOG_INF("Size: %d", ringbuffers.size()); - if (ret.second != true) { uart = nullptr; } - LOG_INF("UART: %p", uart); return uart; } -void print_ringbuffer() -{ - LOG_INF("Ringbuffer: %p, size: %d",&ringbuffers, ringbuffers.size()); -} void serial_close(const char* dt_label) { From 0a2f512d61ca29c783d12991328deb05d575f0f0 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Fri, 11 Sep 2020 14:37:16 +0200 Subject: [PATCH 216/323] zephyr: use __ZEPHYR__ to select PJON Zephyr interfaces. This is defined in the Zephyr-OS --- src/interfaces/LINUX/TCPHelper_POSIX.h | 10 +++++----- src/interfaces/LINUX/UDPHelper_POSIX.h | 6 +++--- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 2 +- zephyr/CMakeLists.txt | 2 -- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/interfaces/LINUX/TCPHelper_POSIX.h b/src/interfaces/LINUX/TCPHelper_POSIX.h index bb7053a942..c83edeb26b 100644 --- a/src/interfaces/LINUX/TCPHelper_POSIX.h +++ b/src/interfaces/LINUX/TCPHelper_POSIX.h @@ -102,14 +102,14 @@ class TCPHelperClient { struct timeval read_timeout; read_timeout.tv_sec = 0; read_timeout.tv_usec = 2000000; -#ifndef ZEPHYR +#ifndef __ZEPHYR__ setsockopt(_fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&read_timeout, sizeof read_timeout); setsockopt(_fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&read_timeout, sizeof read_timeout); #endif bool connected = ::connect(_fd, (struct sockaddr *) &_remote_addr,sizeof(_remote_addr)) == 0; if (connected) { -#ifndef ZEPHYR +#ifndef __ZEPHYR__ // Shorten timeouts for reading and writing struct timeval read_timeout; read_timeout.tv_sec = 0; @@ -193,7 +193,7 @@ class TCPHelperClient { #endif // Set timeouts for reading and writing -#ifndef ZEPHYR +#ifndef __ZEPHYR__ struct timeval read_timeout; read_timeout.tv_sec = 0; read_timeout.tv_usec = 1000; @@ -238,7 +238,7 @@ class TCPHelperClient { int write(const uint8_t *buffer, int size) { if (_fd == -1) return -1; -#if defined(_WIN32) || defined(ZEPHYR) +#if defined(_WIN32) || defined(__ZEPHYR__) int w = ::send(_fd, (char*)buffer, size, 0); #else int w = ::send(_fd, (char*)buffer, size, MSG_NOSIGNAL); @@ -303,7 +303,7 @@ class TCPHelperServer { memset(&_remote_sender_addr, 0, len); int connected_fd = _fd == -1 ? -1 : ::accept(_fd, (struct sockaddr *) &_remote_sender_addr, &len); if (connected_fd != -1) { -#ifndef ZEPHYR +#ifndef __ZEPHYR__ // Shorten timeout for reading and writing struct timeval read_timeout; read_timeout.tv_sec = 0; diff --git a/src/interfaces/LINUX/UDPHelper_POSIX.h b/src/interfaces/LINUX/UDPHelper_POSIX.h index 9314205029..221b7a2fc6 100644 --- a/src/interfaces/LINUX/UDPHelper_POSIX.h +++ b/src/interfaces/LINUX/UDPHelper_POSIX.h @@ -19,7 +19,7 @@ #include #endif -#ifdef ZEPHYR +#ifdef __ZEPHYR__ #include #define INADDR_BROADCAST ((u32_t) 0xffffffff) #endif @@ -75,7 +75,7 @@ class UDPHelper { read_timeout.tv_sec = 0; read_timeout.tv_usec = 1000; #endif -#ifdef ZEPHYR +#ifdef __ZEPHYR__ fcntl(_fd, F_SETFL, O_NONBLOCK); #else setsockopt(_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&read_timeout, sizeof read_timeout); @@ -98,7 +98,7 @@ class UDPHelper { _remote_receiver_addr.sin_port = htons(_port); _remote_receiver_addr.sin_addr.s_addr = INADDR_BROADCAST; -#ifndef ZEPHYR +#ifndef __ZEPHYR__ // Allow broadcasts int broadcast=1; if (setsockopt(_fd,SOL_SOCKET,SO_BROADCAST,(const char*)&broadcast,sizeof(broadcast))==-1) { diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h index da5a0963db..81a23bb5fc 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -1,6 +1,6 @@ #pragma once -#if defined(ZEPHYR) +#if defined(__ZEPHYR__) #define OUTPUT GPIO_OUTPUT diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index e6dade2f1d..3158205712 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -1,8 +1,6 @@ if(CONFIG_PJON) zephyr_include_directories(../src) -add_compile_definitions(ZEPHYR) -zephyr_compile_definitions(ZEPHYR) if(CONFIG_PJON_STRATEGY_THROUGHSERIAL) zephyr_sources(../src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp) From 41a52aacce1a15b4e39eeedafd21acf5bcdd8782 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Mon, 14 Sep 2020 10:37:29 +0200 Subject: [PATCH 217/323] zephyr: add Konfig for TS --- zephyr/Kconfig | 117 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 9e9d7d3cc7..9cfeec1a1c 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -14,11 +14,83 @@ config PJON_STRATEGY_DUALUDP bool "PJON strategy DualUDP" -config PJON_STRATEGY_THROUGHSERIAL +menuconfig PJON_STRATEGY_THROUGHSERIAL select RING_BUFFER select SERIAL select UART_INTERRUPT_DRIVEN bool "PJON strategy Through Serial" + +if PJON_STRATEGY_THROUGHSERIAL + +config INITIAL_DELAY + int "INITIAL DELAY" + default 1000 + help + Maximum 1 second random initial delay + + +config COLLISION_DELAY + int "COLLISION DELAY" + default 32 + help + Maximum 32 microseconds random delay in case of collision + + +config RESONSE_TIME_OUT + int "RESONSE TIME OUT" + default 10000 + help + Set 10 milliseconds as the maximum timeframe between transmission and + synchronous acknowledgement response. This value is strictly related to the + maximum time needed by receiver to receive, compute and transmit a response. + Higher if necessary. + + +config TIME_IN + int "TIME IN" + default 100032 + help + Minum timeframe with channel free for use before transmission. + (Avoid disrupting synchronous acknowledgement exchange) + + +config BYTE_TIME_OUT + int "BYTE TIME OUT" + default 50000 + help + Set 50 milliseconds as the maximum timeframe for byte reception. + This value depends on the latency, baud rate and computation time. + Always set TS_BYTE_TIME_OUT > (byte transmission time + latency) + + +config MAX_ATTEMTS + int "MAX ATTEMTS" + default 20 + help + Maximum transmission attempts + + +config BACK_OFF_DEGREE + int "BACK OFF DEGREE" + default 4 + help + Back-off exponential degree + + +config RS485_DELAY + int "RS485 DELAY" + default 1 + help + Delay before enabling and disabling RS485 DE and or RE pin + + +config FLUSH_OFFSET + int "FLUSH OFFSET" + default 152 + help + Force blocking sending hack (adds a delay for each character sent). +endif + endmenu config PJON_DEVICE_ID @@ -32,4 +104,47 @@ config PJON_MTU default 1400 help Maximum size of SMP frames send and receive over PJON DualUDP, in bytes. + +config PJON_MAX_PACKETS + int "PJON MAX PACKETS" + default 5 + help + Packet buffer length, if full PJON_PACKETS_BUFFER_FULL error is thrown. + The packet buffer is preallocated, so its length strongly affects + memory consumption + +config PJON_PACKET_MAX_LENGTH + int "MAX PACKET LENGTH" + default 50 + help + Max packet length, higher if necessary. + The max packet length defines the length of packets pre-allocated buffers + so it strongly affects memory consumption. + +config PJON_INCLUDE_ASYNC_ACK + bool "INCLUDE ASYNC ACK" + default false + help + If set to false async ack feature is not included saving memory + (it saves around 1kB of memory) + +config PJON_INCLUDE_PACKET_ID + bool "INCLUDE PACKET ID" + default false + help + If set to false packet id feature is not included saving memory + (it saves around 1kB of memory) + +config PJON_MAX_RECENT_PACKET_IDS + int "MAX RECENT PACKET IDS" + default 10 + help + Maximum packet ids record kept in memory (to avoid duplicated exchanges) + +config APP_LINK_WITH_PJON + bool "Link 'app' with PJON" + default y + help + Add PJON configuration to the 'app' + endif From bc75b0851b8b3f0f2ca8a0b765845c38afcbb2ee Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Mon, 14 Sep 2020 10:37:54 +0200 Subject: [PATCH 218/323] zephyr: built PJON as a zepyhr library and add the TS configurations --- zephyr/CMakeLists.txt | 28 ++++++++++++++++++++++++++-- zephyr/Kconfig | 18 +++++++++--------- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 3158205712..edbfafa667 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -1,8 +1,32 @@ if(CONFIG_PJON) +zephyr_interface_library_named(PJON) +zephyr_library() + +zephyr_compile_definitions_ifdef(CONFIG_PJON_MAX_PACKETS PJON_MAX_PACKETS=CONFIG_PJON_MAX_PACKETS) +zephyr_compile_definitions_ifdef(CONFIG_PJON_PACKET_MAX_LENGTH PJON_PACKET_MAX_LENGTH=CONFIG_PJON_PACKET_MAX_LENGTH) + +target_include_directories(PJON INTERFACE ../src) + -zephyr_include_directories(../src) if(CONFIG_PJON_STRATEGY_THROUGHSERIAL) -zephyr_sources(../src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp) +target_compile_definitions(PJON INTERFACE +PJON_INCLUDE_TS +TS_INITIAL_DELAY=CONFIG_TS_INITIAL_DELAY +TS_COLLISION_DELAY=CONFIG_TS_COLLISION_DELAY +TS_RESONSE_TIME_OUT=CONFIG_TS_RESONSE_TIME_OUT +TS_TIME_IN=CONFIG_TS_TIME_IN +TS_BYTE_TIME_OUT=CONFIG_TS_BYTE_TIME_OUT +TS_MAX_ATTEMTS=CONFIG_TS_MAX_ATTEMTS +TS_BACK_OFF_DEGREE=CONFIG_TS_BACK_OFF_DEGREE +TS_RS485_DELAY=CONFIG_TS_RS485_DELAY +TS_FLUSH_OFFSET=CONFIG_TS_FLUSH_OFFSET) + +zephyr_library_sources(../src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp) + +zephyr_library_link_libraries(PJON) endif() + + +target_link_libraries(PJON INTERFACE zephyr_interface) endif() diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 9cfeec1a1c..4f3853102c 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -22,21 +22,21 @@ menuconfig PJON_STRATEGY_THROUGHSERIAL if PJON_STRATEGY_THROUGHSERIAL -config INITIAL_DELAY +config TS_INITIAL_DELAY int "INITIAL DELAY" default 1000 help Maximum 1 second random initial delay -config COLLISION_DELAY +config TS_COLLISION_DELAY int "COLLISION DELAY" default 32 help Maximum 32 microseconds random delay in case of collision -config RESONSE_TIME_OUT +config TS_RESONSE_TIME_OUT int "RESONSE TIME OUT" default 10000 help @@ -46,7 +46,7 @@ config RESONSE_TIME_OUT Higher if necessary. -config TIME_IN +config TS_TIME_IN int "TIME IN" default 100032 help @@ -54,7 +54,7 @@ config TIME_IN (Avoid disrupting synchronous acknowledgement exchange) -config BYTE_TIME_OUT +config TS_BYTE_TIME_OUT int "BYTE TIME OUT" default 50000 help @@ -63,28 +63,28 @@ config BYTE_TIME_OUT Always set TS_BYTE_TIME_OUT > (byte transmission time + latency) -config MAX_ATTEMTS +config TS_MAX_ATTEMTS int "MAX ATTEMTS" default 20 help Maximum transmission attempts -config BACK_OFF_DEGREE +config TS_BACK_OFF_DEGREE int "BACK OFF DEGREE" default 4 help Back-off exponential degree -config RS485_DELAY +config TS_RS485_DELAY int "RS485 DELAY" default 1 help Delay before enabling and disabling RS485 DE and or RE pin -config FLUSH_OFFSET +config TS_FLUSH_OFFSET int "FLUSH OFFSET" default 152 help From c457fbc410cbe202c7264063169bd621954a8a64 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Mon, 14 Sep 2020 10:56:05 +0200 Subject: [PATCH 219/323] zephyr: add Kconfig options for DualUDP --- zephyr/CMakeLists.txt | 12 +++++++++++ zephyr/Kconfig | 50 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index edbfafa667..ed4e3f6c69 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -27,6 +27,18 @@ zephyr_library_sources(../src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp) zephyr_library_link_libraries(PJON) endif() +if(CONFIG_PJON_STRATEGY_DUALUDP) + +target_compile_definitions(PJON INTERFACE +DUDP_RESPONSE_TIMEOUT=CONFIG_DUDP_RESPONSE_TIMEOUT +DUDP_MINIMUM_SEND_INTERVAL_MS=CONFIG_DUDP_MINIMUM_SEND_INTERVAL_MS +DUDP_BACKOFF=CONFIG_DUDP_BACKOFF +DUDP_MAX_RETRIES=CONFIG_DUDP_MAX_RETRIES +DUDP_MAX_REMOTE_NODES=CONFIG_DUDP_MAX_REMOTE_NODES +DUDP_MAX_FAILURES=CONFIG_DUDP_MAX_FAILURES) + +endif() + target_link_libraries(PJON INTERFACE zephyr_interface) endif() diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 4f3853102c..947301efa3 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -6,13 +6,61 @@ menuconfig PJON if PJON menu "PJON strategy" -config PJON_STRATEGY_DUALUDP +menuconfig PJON_STRATEGY_DUALUDP select NETWORKING select NET_IPV4 select NET_UDP select NET_SOCKETS bool "PJON strategy DualUDP" +if PJON_STRATEGY_DUALUDP + + + +config DUDP_RESPONSE_TIMEOUT + int "DUDP_RESPONSE_TIMEOUT" + default 50000 + help + Timeout waiting for an ACK. This can be increased if the latency is high + + +config DUDP_MINIMUM_SEND_INTERVAL_MS + int "DUDP_MINIMUM_SEND_INTERVAL_MS" + default 8 + help + Minimum time interval in ms between send attempts. Some devices go into + contention if sending too fast. This can be overridden in an interface + for a device type, or in user sketches. + +config DUDP_BACKOFF + int "DUDP_BACKOFF" + default 5 + help + Backoff function that can be overridden depending on network and devices + + +config DUDP_MAX_RETRIES + int "DUDP_MAX_RETRIES" + default 10 + help + Max number of retries + + +config DUDP_MAX_REMOTE_NODES + int "DUDP_MAX_REMOTE_NODES" + default 10 + help + The size of the node table + + +config DUDP_MAX_FAILURES + int "DUDP_MAX_FAILURES" + default 10 + help + Remove automatically registered nodes after this number of send failures + +endif + menuconfig PJON_STRATEGY_THROUGHSERIAL select RING_BUFFER From e1acc7cce826b973ceb84c9bb51509defbd37800 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Mon, 14 Sep 2020 12:19:45 +0200 Subject: [PATCH 220/323] zephyr: revert include path for zephyr posix support; the posix directory of zephyr is in include_path --- src/interfaces/LINUX/UDPHelper_POSIX.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/interfaces/LINUX/UDPHelper_POSIX.h b/src/interfaces/LINUX/UDPHelper_POSIX.h index 221b7a2fc6..64ee2a3c23 100644 --- a/src/interfaces/LINUX/UDPHelper_POSIX.h +++ b/src/interfaces/LINUX/UDPHelper_POSIX.h @@ -13,10 +13,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #endif #ifdef __ZEPHYR__ From 6f3901cb5974c15db7373ed37d89b4a418826db6 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Wed, 16 Sep 2020 13:18:43 +0200 Subject: [PATCH 221/323] zephyr: put the implementation of the zephyr uart into a header to have only header files --- src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h | 5 +++++ ...ZEPHYR_Interface.cpp => PJON_ZEPHYR_Interface.inl} | 11 ++++++++--- zephyr/CMakeLists.txt | 6 ------ 3 files changed, 13 insertions(+), 9 deletions(-) rename src/interfaces/ZEPHYR/{PJON_ZEPHYR_Interface.cpp => PJON_ZEPHYR_Interface.inl} (95%) diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h index 81a23bb5fc..bc3905a1c0 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.h @@ -19,6 +19,11 @@ void digitalWrite(int pin, bool state); void pinMode(int pin, int mode); void serial_flush(struct device* dev); +#if defined CONFIG_PJON_STRATEGY_THROUGHSERIAL +#ifndef PJON_ZEPHYR_SEPARATE_DEFINITION +#include "PJON_ZEPHYR_Interface.inl" +#endif +#endif // deal with randomness #ifndef PJON_RANDOM diff --git a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.inl similarity index 95% rename from src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp rename to src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.inl index a8aa22bda5..8158b77129 100644 --- a/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp +++ b/src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.inl @@ -1,3 +1,10 @@ +#ifndef ZEPHYR + #define ZEPHYR +#endif +#ifndef PJON_ZEPHYR_SEPARATE_DEFINITION + #define PJON_ZEPHYR_SEPARATE_DEFINITION +#endif + #include "PJON_ZEPHYR_Interface.h" #include @@ -12,9 +19,6 @@ static struct device* pin_dev = NULL; -#include "logging/log.h" -LOG_MODULE_REGISTER(PJON_SMP, LOG_LEVEL_INF); - static std::map ringbuffers; static struct ring_buf* _get_ring_buf(struct device* dev) @@ -110,6 +114,7 @@ void digitalWrite(int pin, bool state) { gpio_pin_set(pin_dev, pin, state); } + void pinMode(int pin, int mode) { pin_dev = device_get_binding(DT_GPIO_LABEL(DT_ALIAS(pjon_txe_pin), gpios)); diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index ed4e3f6c69..45a8d020c2 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -1,6 +1,5 @@ if(CONFIG_PJON) zephyr_interface_library_named(PJON) -zephyr_library() zephyr_compile_definitions_ifdef(CONFIG_PJON_MAX_PACKETS PJON_MAX_PACKETS=CONFIG_PJON_MAX_PACKETS) zephyr_compile_definitions_ifdef(CONFIG_PJON_PACKET_MAX_LENGTH PJON_PACKET_MAX_LENGTH=CONFIG_PJON_PACKET_MAX_LENGTH) @@ -21,10 +20,6 @@ TS_MAX_ATTEMTS=CONFIG_TS_MAX_ATTEMTS TS_BACK_OFF_DEGREE=CONFIG_TS_BACK_OFF_DEGREE TS_RS485_DELAY=CONFIG_TS_RS485_DELAY TS_FLUSH_OFFSET=CONFIG_TS_FLUSH_OFFSET) - -zephyr_library_sources(../src/interfaces/ZEPHYR/PJON_ZEPHYR_Interface.cpp) - -zephyr_library_link_libraries(PJON) endif() if(CONFIG_PJON_STRATEGY_DUALUDP) @@ -40,5 +35,4 @@ DUDP_MAX_FAILURES=CONFIG_DUDP_MAX_FAILURES) endif() -target_link_libraries(PJON INTERFACE zephyr_interface) endif() From 458ae33a82ca6a7b8a5555b2c657003aded67780 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Wed, 16 Sep 2020 13:20:03 +0200 Subject: [PATCH 222/323] zephyr: add missing PJON_INCLUDE_DUDP for DualUDP --- zephyr/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 45a8d020c2..9be65d9679 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -25,6 +25,7 @@ endif() if(CONFIG_PJON_STRATEGY_DUALUDP) target_compile_definitions(PJON INTERFACE +PJON_INCLUDE_DUDP DUDP_RESPONSE_TIMEOUT=CONFIG_DUDP_RESPONSE_TIMEOUT DUDP_MINIMUM_SEND_INTERVAL_MS=CONFIG_DUDP_MINIMUM_SEND_INTERVAL_MS DUDP_BACKOFF=CONFIG_DUDP_BACKOFF From 987412f21ff8597bbda29bcd7863379b7065417b Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Wed, 16 Sep 2020 13:20:21 +0200 Subject: [PATCH 223/323] zephyr: remove DUDP_BACKOFF from Kconfig, because it is a macro --- zephyr/CMakeLists.txt | 1 - zephyr/Kconfig | 7 ------- 2 files changed, 8 deletions(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 9be65d9679..44695abb21 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -28,7 +28,6 @@ target_compile_definitions(PJON INTERFACE PJON_INCLUDE_DUDP DUDP_RESPONSE_TIMEOUT=CONFIG_DUDP_RESPONSE_TIMEOUT DUDP_MINIMUM_SEND_INTERVAL_MS=CONFIG_DUDP_MINIMUM_SEND_INTERVAL_MS -DUDP_BACKOFF=CONFIG_DUDP_BACKOFF DUDP_MAX_RETRIES=CONFIG_DUDP_MAX_RETRIES DUDP_MAX_REMOTE_NODES=CONFIG_DUDP_MAX_REMOTE_NODES DUDP_MAX_FAILURES=CONFIG_DUDP_MAX_FAILURES) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 947301efa3..476e5c52b1 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -32,13 +32,6 @@ config DUDP_MINIMUM_SEND_INTERVAL_MS contention if sending too fast. This can be overridden in an interface for a device type, or in user sketches. -config DUDP_BACKOFF - int "DUDP_BACKOFF" - default 5 - help - Backoff function that can be overridden depending on network and devices - - config DUDP_MAX_RETRIES int "DUDP_MAX_RETRIES" default 10 From a2d8300d9eb7554eb495c374442e5aed3824f1c0 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Wed, 16 Sep 2020 13:20:52 +0200 Subject: [PATCH 224/323] strategy DualUDP: call interface API PJON_MILLIS instead of implementation millis --- src/strategies/DualUDP/DualUDP.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/DualUDP/DualUDP.h b/src/strategies/DualUDP/DualUDP.h index 8fcc345b08..c25d1963bb 100644 --- a/src/strategies/DualUDP/DualUDP.h +++ b/src/strategies/DualUDP/DualUDP.h @@ -356,7 +356,7 @@ class DualUDP { udp.send_frame(data, length, _remote_ip[pos], _remote_port[pos]); _send_attempts[pos]++; } - _last_out_time = millis(); + _last_out_time = PJON_MILLIS(); } }; From 9c76aff25615c017582e9fe721deea12132c86e6 Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Wed, 16 Sep 2020 14:00:42 +0200 Subject: [PATCH 225/323] zephyr: add a example for Zephyr using the DualUDP strategy --- .../ZEPHYR/local/DualUDP/PingPong/README.md | 20 +++ .../DualUDP/PingPong/Receiver/.west/config | 8 ++ .../Receiver/application/CMakeLists.txt | 10 ++ .../PingPong/Receiver/application/prj.conf | 27 ++++ .../Receiver/application/src/main.cpp | 117 ++++++++++++++++++ .../PingPong/Receiver/application/west.yml | 33 +++++ .../DualUDP/PingPong/Transmitter/.west/config | 8 ++ .../Transmitter/application/CMakeLists.txt | 10 ++ .../PingPong/Transmitter/application/prj.conf | 27 ++++ .../Transmitter/application/src/main.cpp | 116 +++++++++++++++++ .../PingPong/Transmitter/application/west.yml | 33 +++++ 11 files changed, 409 insertions(+) create mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/README.md create mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/Receiver/.west/config create mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/CMakeLists.txt create mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/prj.conf create mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/src/main.cpp create mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/west.yml create mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/.west/config create mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/CMakeLists.txt create mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/prj.conf create mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/src/main.cpp create mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/west.yml diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/README.md b/examples/ZEPHYR/local/DualUDP/PingPong/README.md new file mode 100644 index 0000000000..d7048cded0 --- /dev/null +++ b/examples/ZEPHYR/local/DualUDP/PingPong/README.md @@ -0,0 +1,20 @@ +# Zephyr PingPong example +This setup consists of a Transmitter and a Receiver. The Transmitter will regularly send a small packet to the Receiver, and the +Receiver will reply back every time. + + +This example is tested with the [nucleo_f429zi](https://docs.zephyrproject.org/latest/boards/arm/nucleo_f429zi/doc/index.html) board. +You need a command-line Zephyr development environment. Follow [this](https://docs.zephyrproject.org/latest/boards/arm/nucleo_f429zi/doc/index.html) +to install it. + +# Build the example +To build the *Receiver* or the *Transmitter* type the following commands in the shell: + +``` +#> cd Transmitter +#> west update +#> source zephyr/zephyr-env.sh +#> west build -b nucleo_f429zi application +#> west flash +``` + diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/.west/config b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/.west/config new file mode 100644 index 0000000000..26c158d6c5 --- /dev/null +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/.west/config @@ -0,0 +1,8 @@ +[manifest] +path = application + +[zephyr] +base = zephyr + +[build] +cmake-args = -DCMAKE_EXPORT_COMPILE_COMMANDS=ON diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/CMakeLists.txt b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/CMakeLists.txt new file mode 100644 index 0000000000..c590215810 --- /dev/null +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.13.1) + +include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) +project(zephyr-sample) + +file(GLOB app_sources src/*.c src/*.cpp) + +include_directories(src) + +target_sources(app PRIVATE ${app_sources} ${smp_srv_sources}) diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/prj.conf b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/prj.conf new file mode 100644 index 0000000000..d2b69a1f6a --- /dev/null +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/prj.conf @@ -0,0 +1,27 @@ +CONFIG_SERIAL=y +CONFIG_GPIO=y + +CONFIG_PJON=y +CONFIG_PJON_DEVICE_ID=44 +CONFIG_NET_L2_ETHERNET_MGMT=y + +CONFIG_CPLUSPLUS=y +CONFIG_STD_CPP17=y +CONFIG_LIB_CPLUSPLUS=y +CONFIG_NEWLIB_LIBC=y +CONFIG_NEWLIB_LIBC_NANO=y + +# CONFIG_TINYCRYPT=y +# CONFIG_LEGACY_DEVICETREE_MACROS=y + +#nucleo +CONFIG_POSIX_API=y + +CONFIG_NETWORKING=y +CONFIG_NET_MGMT=y +CONFIG_NET_IPV4=y +CONFIG_NET_SOCKETS=y +CONFIG_NET_UDP=y +CONFIG_NET_DHCPV4=y + +CONFIG_PJON_STRATEGY_DUALUDP=y diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/src/main.cpp b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/src/main.cpp new file mode 100644 index 0000000000..173b856a4f --- /dev/null +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/src/main.cpp @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include + +/* 1000 msec = 1 sec */ +#define SLEEP_TIME_MS 1000 + +/* The devicetree node identifier for the "led0" alias. */ +#define LED0_NODE DT_ALIAS(led0) + +#if DT_NODE_HAS_STATUS(LED0_NODE, okay) +#define LED0 DT_GPIO_LABEL(LED0_NODE, gpios) +#define PIN DT_GPIO_PIN(LED0_NODE, gpios) +#if DT_PHA_HAS_CELL(LED0_NODE, gpios, flags) +#define FLAGS DT_GPIO_FLAGS(LED0_NODE, gpios) +#endif +#else +/* A build error here means your board isn't set up to blink an LED. */ +#error "Unsupported board: led0 devicetree alias is not defined" +#define LED0 "" +#define PIN 0 +#endif + +#ifndef FLAGS +#define FLAGS 0 +#endif + +#include "PJON.h" + +PJON bus(CONFIG_PJON_DEVICE_ID); + +static int cnt = 0; +static struct net_mgmt_event_callback mgmt_cb; + +static void pjon_receive_cb(uint8_t* payload, uint16_t length, const PJON_Packet_Info& packet_info) +{ + if (payload[0] == 'P') { + cnt++; + bus.reply("P", 1); + } +} + + +void pjon_thread(void) +{ + bus.set_receiver(pjon_receive_cb); + bus.begin(); + + printk("PJON Bus started!\n"); + + while (true) { + bus.update(); + bus.receive(); + k_usleep(1); + } +} + +K_THREAD_DEFINE(router_thread, 1024, pjon_thread, NULL, NULL, NULL, 12, 0, 0); + +/* + * print a IP addresse assigned by DHCP + */ +static void handler(struct net_mgmt_event_callback* cb, u32_t mgmt_event, struct net_if* iface) +{ + printk("dhcp handler called!"); + + if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) { + return; + } + + for (int i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) { + char buf[NET_IPV4_ADDR_LEN]; + + if (iface->config.ip.ipv4->unicast[i].addr_type != NET_ADDR_DHCP) { + continue; + } + printk("Your address: %s\n", + net_addr_ntop(AF_INET, + &iface->config.ip.ipv4->unicast[i].address.in_addr, buf, sizeof(buf))); + } +} + +void main(void) +{ + printk("Hello World from Receiver: %s!\n", CONFIG_BOARD); + + struct device *dev; + bool led_is_on = true; + int ret; + + dev = device_get_binding(LED0); + if (dev == NULL) { + return; + } + + ret = gpio_pin_configure(dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS); + if (ret < 0) { + return; + } + + // starting dhcpv4 on iface and add handler to print the IP + struct net_if* iface; + net_mgmt_init_event_callback(&mgmt_cb, handler, NET_EVENT_IPV4_ADDR_ADD); + net_mgmt_add_event_callback(&mgmt_cb); + iface = net_if_get_default(); + net_dhcpv4_start(iface); + + while (1) { + gpio_pin_set(dev, PIN, (int)led_is_on); + led_is_on = !led_is_on; + k_msleep(SLEEP_TIME_MS); + printk("PING/s: %d\n", cnt); + cnt = 0; + } +} diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/west.yml b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/west.yml new file mode 100644 index 0000000000..71cbc1588f --- /dev/null +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/west.yml @@ -0,0 +1,33 @@ +manifest: + defaults: + remote: zephyr-upstream + + remotes: + - name: zephyr-upstream + url-base: https://github.com/zephyrproject-rtos + + projects: + - name: zephyr + path: zephyr + west-commands: scripts/west-commands.yml + remote: zephyr-upstream + revision: v2.3.0 + + # anything beyond this line is meant to define zephyr modules that use the default remote. + # please have a look into the zephyr/west.yml for available modules + - name: cmsis + path: modules/hal/cmsis + revision: 542b2296e6d515b265e25c6b7208e8fea3014f90 + + - name: tinycrypt + path: modules/crypto/tinycrypt + revision: 3e9a49d2672ec01435ffbf0d788db6d95ef28de0 + + - name: hal_stm32 + revision: d1bc80d021f4ebc31f6e8b36f14b738cc26c7b03 + path: modules/hal/stm32 + + - name: pjon + url: git@github.com:Cimex97/PJON.git + revision: feature/zephyr_support + path: modules/pjon diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/.west/config b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/.west/config new file mode 100644 index 0000000000..26c158d6c5 --- /dev/null +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/.west/config @@ -0,0 +1,8 @@ +[manifest] +path = application + +[zephyr] +base = zephyr + +[build] +cmake-args = -DCMAKE_EXPORT_COMPILE_COMMANDS=ON diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/CMakeLists.txt b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/CMakeLists.txt new file mode 100644 index 0000000000..c590215810 --- /dev/null +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.13.1) + +include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) +project(zephyr-sample) + +file(GLOB app_sources src/*.c src/*.cpp) + +include_directories(src) + +target_sources(app PRIVATE ${app_sources} ${smp_srv_sources}) diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/prj.conf b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/prj.conf new file mode 100644 index 0000000000..535e69249e --- /dev/null +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/prj.conf @@ -0,0 +1,27 @@ +CONFIG_SERIAL=y +CONFIG_GPIO=y + +CONFIG_PJON=y +CONFIG_PJON_DEVICE_ID=45 +CONFIG_NET_L2_ETHERNET_MGMT=y + +CONFIG_CPLUSPLUS=y +CONFIG_STD_CPP17=y +CONFIG_LIB_CPLUSPLUS=y +CONFIG_NEWLIB_LIBC=y +CONFIG_NEWLIB_LIBC_NANO=y + +# CONFIG_TINYCRYPT=y +# CONFIG_LEGACY_DEVICETREE_MACROS=y + +#nucleo +CONFIG_POSIX_API=y + +CONFIG_NETWORKING=y +CONFIG_NET_MGMT=y +CONFIG_NET_IPV4=y +CONFIG_NET_SOCKETS=y +CONFIG_NET_UDP=y +CONFIG_NET_DHCPV4=y + +CONFIG_PJON_STRATEGY_DUALUDP=y diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/src/main.cpp b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/src/main.cpp new file mode 100644 index 0000000000..6d9848e902 --- /dev/null +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/src/main.cpp @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include + +/* 1000 msec = 1 sec */ +#define SLEEP_TIME_MS 1000 + +/* The devicetree node identifier for the "led0" alias. */ +#define LED0_NODE DT_ALIAS(led0) + +#if DT_NODE_HAS_STATUS(LED0_NODE, okay) +#define LED0 DT_GPIO_LABEL(LED0_NODE, gpios) +#define PIN DT_GPIO_PIN(LED0_NODE, gpios) +#if DT_PHA_HAS_CELL(LED0_NODE, gpios, flags) +#define FLAGS DT_GPIO_FLAGS(LED0_NODE, gpios) +#endif +#else +/* A build error here means your board isn't set up to blink an LED. */ +#error "Unsupported board: led0 devicetree alias is not defined" +#define LED0 "" +#define PIN 0 +#endif + +#ifndef FLAGS +#define FLAGS 0 +#endif + +#include "PJON.h" + +PJON bus(CONFIG_PJON_DEVICE_ID); + +static int cnt = 0; +static struct net_mgmt_event_callback mgmt_cb; + +static void pjon_receive_cb(uint8_t* payload, uint16_t length, const PJON_Packet_Info& packet_info) +{ + if (payload[0] == 'P') cnt++; +} + + +void pjon_thread(void) +{ + bus.set_receiver(pjon_receive_cb); + + bus.begin(); + printk("PJON Bus started!\n"); + + bus.send_repeatedly(44, "P", 1, 20000); + + while (true) { + bus.update(); + bus.receive(); + k_usleep(10); + } +} + +K_THREAD_DEFINE(router_thread, 1024, pjon_thread, NULL, NULL, NULL, 12, 0, 0); + +/* + * print a IP addresse assigned by DHCP + */ +static void handler(struct net_mgmt_event_callback* cb, u32_t mgmt_event, struct net_if* iface) +{ + printk("dhcp handler called!"); + + if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) { + return; + } + + for (int i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) { + char buf[NET_IPV4_ADDR_LEN]; + + if (iface->config.ip.ipv4->unicast[i].addr_type != NET_ADDR_DHCP) { + continue; + } + printk("Your address: %s", + net_addr_ntop(AF_INET, + &iface->config.ip.ipv4->unicast[i].address.in_addr, buf, sizeof(buf))); + } +} + +void main(void) +{ + printk("Hello World from Transmitter: %s!\n", CONFIG_BOARD); + + struct device *dev; + bool led_is_on = true; + int ret; + + dev = device_get_binding(LED0); + if (dev == NULL) { + return; + } + + ret = gpio_pin_configure(dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS); + if (ret < 0) { + return; + } + + // starting dhcpv4 on iface and add handler to print the IP + struct net_if* iface; + net_mgmt_init_event_callback(&mgmt_cb, handler, NET_EVENT_IPV4_ADDR_ADD); + net_mgmt_add_event_callback(&mgmt_cb); + iface = net_if_get_default(); + net_dhcpv4_start(iface); + + while (1) { + gpio_pin_set(dev, PIN, (int)led_is_on); + led_is_on = !led_is_on; + k_msleep(SLEEP_TIME_MS); + printk("PONG/s: %d\n", cnt); + cnt = 0; + } +} diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/west.yml b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/west.yml new file mode 100644 index 0000000000..71cbc1588f --- /dev/null +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/west.yml @@ -0,0 +1,33 @@ +manifest: + defaults: + remote: zephyr-upstream + + remotes: + - name: zephyr-upstream + url-base: https://github.com/zephyrproject-rtos + + projects: + - name: zephyr + path: zephyr + west-commands: scripts/west-commands.yml + remote: zephyr-upstream + revision: v2.3.0 + + # anything beyond this line is meant to define zephyr modules that use the default remote. + # please have a look into the zephyr/west.yml for available modules + - name: cmsis + path: modules/hal/cmsis + revision: 542b2296e6d515b265e25c6b7208e8fea3014f90 + + - name: tinycrypt + path: modules/crypto/tinycrypt + revision: 3e9a49d2672ec01435ffbf0d788db6d95ef28de0 + + - name: hal_stm32 + revision: d1bc80d021f4ebc31f6e8b36f14b738cc26c7b03 + path: modules/hal/stm32 + + - name: pjon + url: git@github.com:Cimex97/PJON.git + revision: feature/zephyr_support + path: modules/pjon From 0a5bae8605621f0377e8fe773850075ab9ac64cc Mon Sep 17 00:00:00 2001 From: Stephan Alsleben Date: Wed, 16 Sep 2020 14:26:14 +0200 Subject: [PATCH 226/323] zephyr: move the sample in one directory that only one west update install all required libraries --- .../PingPong/{Receiver => }/.west/config | 2 +- .../ZEPHYR/local/DualUDP/PingPong/README.md | 6 ++-- .../Receiver/{application => }/CMakeLists.txt | 0 .../Receiver/{application => }/prj.conf | 0 .../Receiver/{application => }/src/main.cpp | 0 .../DualUDP/PingPong/Transmitter/.west/config | 8 ----- .../{application => }/CMakeLists.txt | 0 .../PingPong/Transmitter/application/west.yml | 33 ------------------- .../Transmitter/{application => }/prj.conf | 0 .../{application => }/src/main.cpp | 0 .../application => Transmitter}/west.yml | 0 11 files changed, 4 insertions(+), 45 deletions(-) rename examples/ZEPHYR/local/DualUDP/PingPong/{Receiver => }/.west/config (82%) rename examples/ZEPHYR/local/DualUDP/PingPong/Receiver/{application => }/CMakeLists.txt (100%) rename examples/ZEPHYR/local/DualUDP/PingPong/Receiver/{application => }/prj.conf (100%) rename examples/ZEPHYR/local/DualUDP/PingPong/Receiver/{application => }/src/main.cpp (100%) delete mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/.west/config rename examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/{application => }/CMakeLists.txt (100%) delete mode 100644 examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/west.yml rename examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/{application => }/prj.conf (100%) rename examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/{application => }/src/main.cpp (100%) rename examples/ZEPHYR/local/DualUDP/PingPong/{Receiver/application => Transmitter}/west.yml (100%) diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/.west/config b/examples/ZEPHYR/local/DualUDP/PingPong/.west/config similarity index 82% rename from examples/ZEPHYR/local/DualUDP/PingPong/Receiver/.west/config rename to examples/ZEPHYR/local/DualUDP/PingPong/.west/config index 26c158d6c5..c87176d59c 100644 --- a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/.west/config +++ b/examples/ZEPHYR/local/DualUDP/PingPong/.west/config @@ -1,5 +1,5 @@ [manifest] -path = application +path = Transmitter [zephyr] base = zephyr diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/README.md b/examples/ZEPHYR/local/DualUDP/PingPong/README.md index d7048cded0..54b5b655d5 100644 --- a/examples/ZEPHYR/local/DualUDP/PingPong/README.md +++ b/examples/ZEPHYR/local/DualUDP/PingPong/README.md @@ -11,10 +11,10 @@ to install it. To build the *Receiver* or the *Transmitter* type the following commands in the shell: ``` -#> cd Transmitter #> west update #> source zephyr/zephyr-env.sh -#> west build -b nucleo_f429zi application -#> west flash +#> west build -b nucleo_f429zi Transmitter -d build_transmitter +#> west build -b nucleo_f429zi Receiver -d build_receiver +#> west flash -d [build_receiver|build_transmitter] ``` diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/CMakeLists.txt b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/CMakeLists.txt similarity index 100% rename from examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/CMakeLists.txt rename to examples/ZEPHYR/local/DualUDP/PingPong/Receiver/CMakeLists.txt diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/prj.conf b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/prj.conf similarity index 100% rename from examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/prj.conf rename to examples/ZEPHYR/local/DualUDP/PingPong/Receiver/prj.conf diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/src/main.cpp b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/src/main.cpp similarity index 100% rename from examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/src/main.cpp rename to examples/ZEPHYR/local/DualUDP/PingPong/Receiver/src/main.cpp diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/.west/config b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/.west/config deleted file mode 100644 index 26c158d6c5..0000000000 --- a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/.west/config +++ /dev/null @@ -1,8 +0,0 @@ -[manifest] -path = application - -[zephyr] -base = zephyr - -[build] -cmake-args = -DCMAKE_EXPORT_COMPILE_COMMANDS=ON diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/CMakeLists.txt b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/CMakeLists.txt similarity index 100% rename from examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/CMakeLists.txt rename to examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/CMakeLists.txt diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/west.yml b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/west.yml deleted file mode 100644 index 71cbc1588f..0000000000 --- a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/west.yml +++ /dev/null @@ -1,33 +0,0 @@ -manifest: - defaults: - remote: zephyr-upstream - - remotes: - - name: zephyr-upstream - url-base: https://github.com/zephyrproject-rtos - - projects: - - name: zephyr - path: zephyr - west-commands: scripts/west-commands.yml - remote: zephyr-upstream - revision: v2.3.0 - - # anything beyond this line is meant to define zephyr modules that use the default remote. - # please have a look into the zephyr/west.yml for available modules - - name: cmsis - path: modules/hal/cmsis - revision: 542b2296e6d515b265e25c6b7208e8fea3014f90 - - - name: tinycrypt - path: modules/crypto/tinycrypt - revision: 3e9a49d2672ec01435ffbf0d788db6d95ef28de0 - - - name: hal_stm32 - revision: d1bc80d021f4ebc31f6e8b36f14b738cc26c7b03 - path: modules/hal/stm32 - - - name: pjon - url: git@github.com:Cimex97/PJON.git - revision: feature/zephyr_support - path: modules/pjon diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/prj.conf b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/prj.conf similarity index 100% rename from examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/prj.conf rename to examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/prj.conf diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/src/main.cpp b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/src/main.cpp similarity index 100% rename from examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/application/src/main.cpp rename to examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/src/main.cpp diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/west.yml b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/west.yml similarity index 100% rename from examples/ZEPHYR/local/DualUDP/PingPong/Receiver/application/west.yml rename to examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/west.yml From 50f3980edf52221f9cbe409fd9def86b72f84f21 Mon Sep 17 00:00:00 2001 From: Fred Larsen Date: Fri, 18 Sep 2020 20:42:14 +0200 Subject: [PATCH 227/323] Added upper limit to initial spacer multiplier Improves compatibility, so devices can use different multipliers and still talk together. --- src/strategies/SoftwareBitBang/SoftwareBitBang.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index d1b3c57ea7..28712faf6d 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -49,6 +49,10 @@ #ifndef SWBB_INITIAL_SPACER_MULTIPLIER #define SWBB_INITIAL_SPACER_MULTIPLIER 1 #endif +// An upper limit to the inital spacer multiplier +#ifndef SWBB_MAX_INITIAL_SPACER_MULTIPLIER + #define SWBB_MAX_INITIAL_SPACER_MULTIPLIER 100 +#endif class SoftwareBitBang { public: @@ -315,7 +319,7 @@ class SoftwareBitBang { bool sync_first() { // Allow a wider packet start sampling interval for devices // that do other tasks and cannot sample very fast. - return sync(SWBB_BIT_SPACER * SWBB_INITIAL_SPACER_MULTIPLIER); + return sync(SWBB_BIT_SPACER * SWBB_MAX_INITIAL_SPACER_MULTIPLIER); }; /* Emit synchronization pulse: */ From 9fafd07e13521c854f7b69f5698ec422b82545d3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 20 Sep 2020 15:07:36 +0200 Subject: [PATCH 228/323] ThroughSerial read failure handling and state machine optimization --- src/strategies/ThroughSerial/ThroughSerial.h | 20 +++++++++++-------- src/strategies/ThroughSerial/Timing.h | 21 +++++++++++--------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/strategies/ThroughSerial/ThroughSerial.h b/src/strategies/ThroughSerial/ThroughSerial.h index 2c18b2b716..59522c176f 100644 --- a/src/strategies/ThroughSerial/ThroughSerial.h +++ b/src/strategies/ThroughSerial/ThroughSerial.h @@ -96,6 +96,14 @@ class ThroughSerial { }; + /* Function called when a frame reception fails */ + + int16_t fail() { + state = TS_WAITING; + return (int16_t)TS_FAIL; + } + + /* Returns the maximum number of attempts for each transmission: */ static uint8_t get_max_attempts() { @@ -187,18 +195,14 @@ class ThroughSerial { case TS_RECEIVING: { while(PJON_SERIAL_AVAILABLE(serial)) { int16_t value = receive_byte(); - if(value == -1) return TS_FAIL; - if(value == TS_START) { - state = TS_WAITING; - return TS_FAIL; - } + if((value == TS_START) || (value == -1)) return fail(); if(value == TS_ESC) { if(!PJON_SERIAL_AVAILABLE(serial)) { state = TS_WAITING_ESCAPE; return TS_FAIL; } else { value = receive_byte(); - if(value == -1) return TS_FAIL; + if(value == -1) return fail(); value = value ^ TS_ESC; if( (value != TS_START) && @@ -236,7 +240,7 @@ class ThroughSerial { case TS_WAITING_ESCAPE: { if(PJON_SERIAL_AVAILABLE(serial)) { int16_t value = receive_byte(); - if(value == -1) return TS_FAIL; + if(value == -1) return fail(); value = value ^ TS_ESC; if( (value != TS_START) && @@ -256,7 +260,7 @@ class ThroughSerial { case TS_WAITING_END: { if(PJON_SERIAL_AVAILABLE(serial)) { int16_t value = receive_byte(); - if(value == -1) return TS_FAIL; + if(value == -1) return fail(); if(value == TS_END) { state = TS_DONE; return TS_FAIL; diff --git a/src/strategies/ThroughSerial/Timing.h b/src/strategies/ThroughSerial/Timing.h index dc7bb8a544..c7a1842ca9 100644 --- a/src/strategies/ThroughSerial/Timing.h +++ b/src/strategies/ThroughSerial/Timing.h @@ -30,21 +30,25 @@ #define TS_INITIAL_DELAY 1000 #endif -/* Maximum 32 microseconds random delay in case of collision */ +/* Maximum 64 microseconds random delay in case of collision */ #ifndef TS_COLLISION_DELAY #define TS_COLLISION_DELAY 64 #endif -/* Set 40 milliseconds as the maximum timeframe between transmission and +/* Set 45 milliseconds as the maximum timeframe between transmission and synchronous acknowledgement response. Its optimal configuration is strictly related to the maximum time needed by receiver to receive, compute - and transmit back a response. */ + and transmit back a response. Set TS_RESPONSE_TIME_OUT to 0 and do not use + the acknowledgement feature if the system operates in master-slave mode and + or applies the request-response scheme. */ #ifndef TS_RESPONSE_TIME_OUT - #define TS_RESPONSE_TIME_OUT 40000 + #define TS_RESPONSE_TIME_OUT 45000 #endif -/* Minum duration of channel free for use before transmission. - (Avoid disrupting synchronous acknowledgement exchange) */ +/* Minum duration of channel free for use before transmission, used to avoid + disrupting an ongoing acknowledgement exchange. Set TS_TIME_IN to 0 and do + not use the acknowledgement feature if the system operates in master-slave + mode and or applies the request-response scheme. */ #ifndef TS_TIME_IN #define TS_TIME_IN TS_RESPONSE_TIME_OUT + TS_COLLISION_DELAY #endif @@ -57,14 +61,13 @@ #define TS_READ_INTERVAL 100 #endif -/* Byte reception timeout */ +/* Byte reception timeout (Default 1 second) */ #ifndef TS_BYTE_TIME_OUT #define TS_BYTE_TIME_OUT 1000000 #endif /* Response length (the response is composed by the last TS_RESPONSE_LENGTH - bytes of the packet received). By default should be relatively safe if - used in master-slave mode. Setting TS_RESPONSE_LENGTH < 4 when using + bytes of the packet received). Setting TS_RESPONSE_LENGTH < 4 when using ThroughSerial in multi-master mode reduces reliability and leads to higher chances of detecting a false positive. */ #ifndef TS_RESPONSE_LENGTH From 548361c704b50e26f80a208a06cc67f7c11603ef Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 20 Sep 2020 16:06:23 +0200 Subject: [PATCH 229/323] ThroughSerial implementation simplified --- src/strategies/ThroughSerial/README.md | 8 +-- src/strategies/ThroughSerial/ThroughSerial.h | 76 +++++++------------- 2 files changed, 27 insertions(+), 57 deletions(-) diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index 7e5d5b2024..eea3e5fd54 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -22,7 +22,7 @@ Before including the library it is possible to configure `ThroughSerial` using p | ----------------------- |------------------------------------ | ------------------------------------------ | | `TS_READ_INTERVAL` | minimum interval between receptions | Duration in microseconds (100 by default) | | `TS_BYTE_TIME_OUT` | Maximum byte reception time-out | Duration in microseconds (1000000 by default) | -| `TS_RESPONSE_TIME_OUT` | Maximum response time-out | Duration in microseconds (40000 by default) | +| `TS_RESPONSE_TIME_OUT` | Maximum response time-out | Duration in microseconds (45000 by default) | | `TS_BACK_OFF_DEGREE` | Maximum back-off exponential degree | Numeric value (4 by default) | | `TS_MAX_ATTEMPTS` | Maximum transmission attempts | Numeric value (20 by default) | @@ -56,11 +56,7 @@ bus.strategy.set_RS485_rxe_pin(11); // Set RS485 transmission enable pin bus.strategy.set_RS485_txe_pin(12); ``` -See the [Blink](../../../examples/ARDUINO/Local/ThroughSerial/Blink) and [BlinkWithResponse](https://github.com/gioblu/PJON/tree/master/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse) examples. - -Examples for `ThroughSerial` can be easily modifed to work with `ThroughSerial`, if you need to interface devices using RS485 see the [RS485-Blink](../../../examples/ARDUINO/Local/ThroughSerial/RS485-Blink) example. - -HC-12 wireless module supports the synchronous acknowledgement, see [HC-12-Blink](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-Blink), [HC-12-SendAndReceive](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive) and [HC-12-LocalChat](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat) examples. +See the [Blink](../../../examples/ARDUINO/Local/ThroughSerial/Blink) and [BlinkWithResponse](https://github.com/gioblu/PJON/tree/master/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse) examples, if you need to interface devices using RS485 see the [RS485-Blink](../../../examples/ARDUINO/Local/ThroughSerial/RS485-Blink) example. HC-12 wireless module supports the synchronous acknowledgement, see [HC-12-Blink](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-Blink), [HC-12-SendAndReceive](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive) and [HC-12-LocalChat](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat) examples. All the other necessary information is present in the general [Documentation](/documentation). diff --git a/src/strategies/ThroughSerial/ThroughSerial.h b/src/strategies/ThroughSerial/ThroughSerial.h index 59522c176f..fa2d72f90c 100644 --- a/src/strategies/ThroughSerial/ThroughSerial.h +++ b/src/strategies/ThroughSerial/ThroughSerial.h @@ -98,9 +98,9 @@ class ThroughSerial { /* Function called when a frame reception fails */ - int16_t fail() { - state = TS_WAITING; - return (int16_t)TS_FAIL; + uint16_t fail(TS_state_t s) { + state = s; + return (uint16_t)TS_FAIL; } @@ -116,7 +116,8 @@ class ThroughSerial { static uint16_t get_receive_time() { return TS_RECEIVE_TIME; }; - + + /* Handle a collision: */ void handle_collision() { @@ -174,10 +175,7 @@ class ThroughSerial { (state == TS_WAITING_ESCAPE) ) && ((uint32_t)(PJON_MICROS() - _last_reception_time) > TS_BYTE_TIME_OUT) - ) { - state = TS_WAITING; - return TS_FAIL; - } + ) return fail(TS_WAITING); switch(state) { case TS_WAITING: { @@ -185,9 +183,8 @@ class ThroughSerial { int16_t value = receive_byte(); if(value == -1) return TS_FAIL; if(value == TS_START) { - state = TS_RECEIVING; position = 0; - return TS_FAIL; + return fail(TS_RECEIVING); } }; break; @@ -195,43 +192,29 @@ class ThroughSerial { case TS_RECEIVING: { while(PJON_SERIAL_AVAILABLE(serial)) { int16_t value = receive_byte(); - if((value == TS_START) || (value == -1)) return fail(); + if((value == TS_START) || (value == -1)) return fail(TS_WAITING); if(value == TS_ESC) { - if(!PJON_SERIAL_AVAILABLE(serial)) { - state = TS_WAITING_ESCAPE; - return TS_FAIL; - } else { + if(!PJON_SERIAL_AVAILABLE(serial)) + return fail(TS_WAITING_ESCAPE); + else { value = receive_byte(); - if(value == -1) return fail(); + if(value == -1) return fail(TS_WAITING); value = value ^ TS_ESC; if( (value != TS_START) && (value != TS_ESC) && (value != TS_END) - ) { - state = TS_WAITING; - return TS_FAIL; - } + ) return fail(TS_WAITING); buffer[position++] = (uint8_t)value; continue; } } - - if(max_length == 1) { - state = TS_WAITING_END; - return TS_FAIL; - } - - if(position + 1 >= PJON_PACKET_MAX_LENGTH) { - state = TS_WAITING; - return TS_FAIL; - } - - if(value == TS_END) { - state = TS_DONE; - return TS_FAIL; - } - + if(max_length == 1) + return fail(TS_WAITING_END); + if(position + 1 >= PJON_PACKET_MAX_LENGTH) + return fail(TS_WAITING); + if(value == TS_END) + return fail(TS_DONE); buffer[position++] = (uint8_t)value; } return TS_FAIL; @@ -240,19 +223,15 @@ class ThroughSerial { case TS_WAITING_ESCAPE: { if(PJON_SERIAL_AVAILABLE(serial)) { int16_t value = receive_byte(); - if(value == -1) return fail(); + if(value == -1) return fail(TS_WAITING); value = value ^ TS_ESC; if( (value != TS_START) && (value != TS_ESC) && (value != TS_END) - ) { - state = TS_WAITING; - return TS_FAIL; - } + ) return fail(TS_WAITING); buffer[position++] = (uint8_t)value; - state = TS_RECEIVING; - return TS_FAIL; + return fail(TS_RECEIVING); } break; } @@ -260,14 +239,9 @@ class ThroughSerial { case TS_WAITING_END: { if(PJON_SERIAL_AVAILABLE(serial)) { int16_t value = receive_byte(); - if(value == -1) return fail(); - if(value == TS_END) { - state = TS_DONE; - return TS_FAIL; - } else { - state = TS_WAITING; - return TS_FAIL; - } + if(value == -1) return fail(TS_WAITING); + if(value == TS_END) return fail(TS_DONE); + else return fail(TS_WAITING); } break; } From 7861efd398663cea4e589339d9bdf94cfd241378 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 20 Sep 2020 16:18:51 +0200 Subject: [PATCH 230/323] SoftwareBitBang removed outdated test results --- src/strategies/SoftwareBitBang/README.md | 2 +- src/strategies/SoftwareBitBang/Timing.h | 5 +- .../tests/NetworkAnalysis-10s.md | 99 ------------------- .../tests/PacketSeparationTest.md | 19 ---- 4 files changed, 4 insertions(+), 121 deletions(-) delete mode 100644 src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md delete mode 100644 src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index e5befaf033..b84beb7e7c 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -92,4 +92,4 @@ PJON application example made by the user [Michael Teeuw](http://michaelteeuw.nl - `SoftwareBitBang` strategy can have compatibility issues with codebases that are using interrupts, reliability or bandwidth loss can occur because of the interruptions made by third party software. ### Safety warning -In all cases, when installing or maintaining a PJON network, extreme care must be taken to avoid any danger. If devices are connected to AC power you are exposed to a high chance of being electrocuted if hardware is not installed carefully and properly. If you are not experienced enough ask the support of a skilled technician and consider that many countries prohibit uncertified installations. When a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus is installed [interference mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines must be followed. If a common ground or power supply line is used its cable size and length must be carefully selected taking in consideration the overall application's power supply requirements and selected components' maximum rating. The PJDL protocol and its reference implementation [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) are experimental, use them at your own risk. +In all cases, when installing or maintaining a PJON network, extreme care must be taken to avoid any danger. If devices are connected to AC power you are exposed to a high chance of being electrocuted if hardware is not installed carefully and properly. If you are not experienced enough ask the support of a skilled technician and consider that many countries prohibit uncertified installations. When a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus is installed [interference mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines must be followed. If a common ground or power supply line is used its cable size and length must be carefully selected taking in consideration the overall application's power supply requirements and selected components' maximum rating. PJDL and its reference implementation [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) are experimental, use them at your own risk. diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index dc07e3ff8b..25f54a3539 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -3,7 +3,7 @@ Copyright 2010-2020, Giovanni Blu Mitolo All rights reserved. Often timing in two different machines do not match, code execution - time can variate and time measurements can be not perfectly equal. + time can variate and time measurements are not perfectly equal. Consider that durations defined below may differ from what is specified in PJDL v5.0. This is done to accomodate machine's inner workings and effectively produce the specified timing. @@ -230,7 +230,8 @@ /* STM32F1 ---------------------------------------------------------------- */ -/* Mod by @jcallano on 09-jul-2020 only tested on PB9 pin. */ +/* @jcallano 09-jul-2020 tested with pin PB15, PB14, PB13, PB12, PB11, PB10, + PB9, PB8, PB7, PB6, PB4, PB3, PA15, PA10. 5v tolerant pins on bluepill */ #if defined(__STM32F1__) #if SWBB_MODE == 1 diff --git a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md b/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md deleted file mode 100644 index 06667b4022..0000000000 --- a/src/strategies/SoftwareBitBang/tests/NetworkAnalysis-10s.md +++ /dev/null @@ -1,99 +0,0 @@ -## NetworkAnalysis -This table was filled running the [NetworkAnalysis](../../../../examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis) example for 10 seconds and averaging the obtained series of results. - -### Mode 1 - -| MODE | TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | Compliant timing | -|------|----------------|-----|----------------|-----|-----------|-----------|--------------|-------------------| -| 1 # | UNO/Nano | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | yes | -| 1 # | UNO/Nano | 11 | UNO/Nano | 11 | 1740kB/s | 58 | 100% | yes | -| 1 | UNO/Nano | 10 | UNO/Nano | 10 | 1710kB/s | 57 | 100% | no | -| 1 # | UNO/Nano | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | yes | -| 1 # | UNO/Nano | 12 | Mega | 12 | 1770kB/s | 59 | 100% | yes | -| 1 # | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1785kB/s | 59-60 | 99.66% | yes | -| 1 # | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1785kB/s | 59-60 | 99.66% | yes | -| 1 # | UNO/Nano | 12 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | yes | -| 1 # | UNO/Nano | 12 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | yes | -| 1 # | UNO/Nano | 12 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | yes | -| 1 # | UNO/Nano | 12 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | yes | -| 1 # | UNO/Nano | 12 | SAMD21 | D0 | 1800kB/s | 60 | 100% | yes | -| 1 | UNO/Nano | 12 | Blue pill | PB9 | 1770kB/s | 59 | 100% | yes | -| 1 | Leonardo/Micro | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | no | -| 1 | Leonardo/Micro | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 99.998% | no | -| 1 | Leonardo/Micro | 12 | Mega | 12 | 1740kB/s | 58 | 100% | no | -| 1 | Leonardo/Micro | 12 | ESP32 40MHz | 12 | 1590kB/s | 53 | 88.68% | no | -| 1 | Leonardo/Micro | 12 | ESP32 80MHz | 12 | 1590kB/s | 53 | 88.68% | no | -| 1 | Leonardo/Micro | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | no | -| 1 # | Mega | 12 | UNO/Nano | 12 | 1770kB/s | 59 | 100% | yes | -| 1 | Mega | 12 | Leonardo/Micro | 12 | 1740kB/s | 58 | 100% | yes | -| 1 # | Mega | 12 | ESP8266 80MHz | D1 | 1797kB/s | 59-60 | 99.9% | yes | -| 1 # | Mega | 12 | ESP8266 160MHz | D1 | 1797kB/s | 59-60 | 99.9% | yes | -| 1 # | Mega | 12 | ESP32 40MHz | 12 | 1710kB/s | 57-60 | 96.49% | yes | -| 1 # | Mega | 12 | ESP32 80MHz | 12 | 1710kB/s | 57-60 | 96.49% | yes | -| 1 | Mega | 12 | ESP32 40MHz | 25 | 1710kB/s | 57 | 96.49% | yes | -| 1 | Mega | 12 | ESP32 80MHz | 25 | 1710kB/s | 57 | 96.49% | yes | -| 1 | Mega | 12 | SAMD21 | D0 | 1770kB/s | 59 | 100% | yes | -| 1 | Mega | 12 | SAMD21 | D1 | 1770kB/s | 59 | 100% | yes | -| 1 # | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | yes | -| 1 # | ESP8266 160MHz | D1 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | yes | -| 1 | ESP8266 80MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | -| 1 | ESP8266 160MHz | D1 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | -| 1 # | ESP8266 80MHz | D1 | Mega | 12 | 1800kB/s | 60 | 100% | yes | -| 1 # | ESP8266 160MHz | D1 | Mega | 12 | 1800kB/s | 60 | 100% | yes | -| 1 | ESP8266 80MHz | D1 | Blue pill | PB9 | | | | | -| 1 | ESP8266 160MHz | D1 | Blue pill | PB9 | | | | | -| 1 # | ESP32 80MHz | 12 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | yes | -| 1 # | ESP32 40MHz | 12 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | yes | -| 1 # | ESP32 40MHz | 12 | Mega | 12 | 1800kB/s | 60 | 100% | yes | -| 1 # | ESP32 80MHz | 12 | Mega | 12 | 1800kB/s | 60 | 100% | yes | -| 1 | ESP32 40MHz | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | -| 1 | ESP32 80MHz | 12 | Leonardo/Micro | 12 | 1770kB/s | 59 | 100% | | -| 1 | ESP32 | 12 | Blue pill | PB9 | 1800kB/s | 60 | 100% | | -| 1 # | SAMD21 | D0 | Mega | 12 | 1800kB/s | 60 | 100% | yes | -| 1 | SAMD21 | D0 | Leonardo/Micro | 12 | 1710kB/s | 57 | 100% | yes | -| 1 | SAMD21 | D0 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | yes | -| 1 | SAMD21 | D0 | ESP32 40MHz | 12 | 1800kB/s | 60 | 100% | yes | -| 1 | SAMD21 | D0 | ESP32 80MHz | 12 | 1800kB/s | 60 | 100% | yes | -| 1 | SAMD21 | D0 | ESP32 40MHz | 25 | 1800kB/s | 60 | 100% | yes | -| 1 | SAMD21 | D0 | ESP32 80MHz | 25 | 1800kB/s | 60 | 100% | yes | -| 1 | SAMD21 | D0 | Blue pill | PB9 | 1860kB/s | 61 | 100% | yes | -| 1 | Blue pill | PB9 | Blue pill | PB9 | 1830kB/s | 61 | 100% | | -| 1 | Blue pill | PB9 | UNO/Nano | 12 | 1800kB/s | 60 | 100% | | -| 1 | Blue pill | PB9 | SAMD | 12 | 1830kB/s | 61 | 100% | | -| 1 | Blue pill | PB9 | ESP8266 80MHz | D1 | 1788kB/s | 60 | 99.33% | | -| 1 | Blue pill | PB9 | ESP8266 160MHz | D1 | 1800kB/s | 60 | 100% | | - -### Mode 2 - -| MODE | TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | -|------|----------------|-----|----------------|-----|-----------|-----------|--------------| -| 2 | Blue pill | PB9 | Blue pill | PB9 | 2040kB/s | 68 | 100% | -| 2 | Blue pill | PB9 | UNO/Nano | 12 | 2010kB/s | 67 | 100% | -| 2 | Blue pill | PB9 | SAMD | | | | | -| 2 | UNO/Nano | 12 | Blue pill | PB9 | 1980kB/s | 66 | 100% | -| 2 | UNO/Nano | 12 | SAMD21 | D0 | 1980kB/s | 66 | 100% | -| 2 | SAMD21 | D0 | UNO/Nano | 12 | 1950kB/s | 65 | 100% | -| 2 | SAMD21 | D0 | Blue pill | PB9 | 2010kB/s | 67 | 100% | -| 2 | ESP32 | 12 | Blue pill | PB9 | 2070kB/s | 69 | 100% | -| 2 | Blue pill | PB9 | ESP8266 80MHz | D1 | 2019kB/s | 68 | 99.77% | -| 2 | Blue pill | PB9 | ESP8266 160MHz | D1 | 2070kB/s | 69 | 100% | -| 2 | UNO/Nano | 12 | ESP8266 160MHz | D1 | 1938kB/s | 66 | 97.8% | -| 2 | UNO/Nano | 12 | ESP8266 80MHz | D1 | 1969kB/s | 66 | 98.93% | -| 2 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 1980kB/s | 66 | 100% | -| 2 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 2010kB/s | 67 | 100% | - -### Mode 3 - -| MODE | TX | PIN | RX | PIN | Bandwidth | Packets/s | Success rate | -|------|----------------|-----|----------------|-----|-----------|-----------|--------------| -| 3 | Blue pill | PB9 | Blue pill | PB9 | 2850kB/s | 95 | 100% | -| 3 | Blue pill | PB9 | UNO/Nano | 12 | 2760kB/s | 92 | 100% | -| 3 | UNO/Nano | 12 | Blue pill | PB9 | 2730kB/s | 91 | 100% | -| 3 | Blue pill | PB9 | SAMD | 12 | 2820kB/s | 94 | 100% | -| 3 | SAMD21 | D0 | Blue pill | PB9 | 2781kB/s | 93 | 99.78% | -| 3 | Blue pill | PB9 | ESP8266 80MHz | D1 | 2649kB/s | 95 | 93% | -| 3 | Blue pill | PB9 | ESP8266 160MHz | D1 | 2803kB/s | 95 | 98.36% | -| 3 | ESP8266 80MHz | D1 | Blue pill | PB9 | 2802kB/s | 94 | 99.36% | -| 3 | ESP8266 160MHz | D1 | Blue pill | PB9 | 2880kB/s | 96 | 100% | -| 3 | ESP8266 80MHz | D1 | UNO/Nano | 12 | 2673kB/s | 90 | 99% | -| 3 | ESP8266 160MHz | D1 | UNO/Nano | 12 | 2788kB/s | 93 | 99.94% | diff --git a/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md b/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md deleted file mode 100644 index 722869fbc5..0000000000 --- a/src/strategies/SoftwareBitBang/tests/PacketSeparationTest.md +++ /dev/null @@ -1,19 +0,0 @@ -## PacketSeparationTest - -This table was filled running the [PacketSeparationTest](../../../../examples/ARDUINO/Local/SoftwareBitBang/PacketSeparationTest) example for 10 seconds and averaging the obtained series of results. - -| MODE | TX |PIN | RX |PIN | RESULT | -|------|---------------------|----|------------------|----|-----------------------------------------------------| -| 1 | UNO/Nano | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 100% | -| 1 | UNO/Nano | 12 | Mega | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.999% | -| 1 | UNO/Nano | 12 | ESP32 | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | -| 1 | Mega | 12 | Leonardo | 12 | SWBB_ACCEPTANCE 53 Accuracy: 100% | -| 1 | Mega | 12 | ESP32 | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | -| 1 | Leonardo | 12 | Leonardo | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | -| 1 | Leonardo | 12 | ESP32 | 12 | SWBB_ACCEPTANCE 56 Accuracy: 100% | -| 1 | Leonardo | 12 | Mega | 12 | SWBB_ACCEPTANCE 53 Accuracy: 100% | -| 1 | Leonardo | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.999% | -| 1 | Mega | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.999% | -| 1 | SAMD21 | D0 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.89% | -| 1 | SAMD21 | D0 | Mega | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.88% | -| 1 | ESP32 | 12 | UNO/Nano | 12 | SWBB_ACCEPTANCE 53 Accuracy: 99.87% | From 722b008560f656852f289d8ffaf099bc504ca388 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Sep 2020 20:54:45 +0200 Subject: [PATCH 231/323] PJDL v5.0 added preamble, SoftwareBitBang minor code-style fix (https://github.com/gioblu/PJON/pull/365) --- .../SoftwareBitBang/SoftwareBitBang.h | 23 +++------ src/strategies/SoftwareBitBang/Timing.h | 20 ++++++++ .../specification/PJDL-specification-v5.0.md | 50 +++++++++---------- 3 files changed, 51 insertions(+), 42 deletions(-) diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index 28712faf6d..34496997d0 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -43,17 +43,6 @@ #define SWBB_RECEIVE_TIME 1000 #endif -// The width of the initial spacer of a packet, can be increased from -// 1 to for example 3 to allow more "blind time" in modules not being -// able to call receive continuously. -#ifndef SWBB_INITIAL_SPACER_MULTIPLIER - #define SWBB_INITIAL_SPACER_MULTIPLIER 1 -#endif -// An upper limit to the inital spacer multiplier -#ifndef SWBB_MAX_INITIAL_SPACER_MULTIPLIER - #define SWBB_MAX_INITIAL_SPACER_MULTIPLIER 100 -#endif - class SoftwareBitBang { public: /* Returns the delay related to the attempts passed as parameter: */ @@ -183,7 +172,7 @@ class SoftwareBitBang { if(max_length == PJON_PACKET_MAX_LENGTH) { uint32_t time = PJON_MICROS(); // Look for a frame initializer - if(!sync_first() || !sync() || !sync()) return SWBB_FAIL; + if(!sync_preamble() || !sync() || !sync()) return SWBB_FAIL; // Check its timing consistency if( (uint32_t)(PJON_MICROS() - time) < @@ -316,21 +305,21 @@ class SoftwareBitBang { return sync(SWBB_BIT_SPACER); } - bool sync_first() { + bool sync_preamble() { // Allow a wider packet start sampling interval for devices // that do other tasks and cannot sample very fast. - return sync(SWBB_BIT_SPACER * SWBB_MAX_INITIAL_SPACER_MULTIPLIER); + return sync(SWBB_BIT_SPACER * SWBB_MAX_PREAMBLE); }; /* Emit synchronization pulse: */ void pulse(uint8_t n) { - #if SWBB_INITIAL_SPACER_MULTIPLIER != 1 + #if SWBB_PREAMBLE != 1 if (n == 3) { - // Extra long first pad of packet initializer, to tolerate devices + // Extra long first pad of packet initializer, to tolerate devices // that have other tasks and cannot sample continuously. PJON_IO_WRITE(_output_pin, HIGH); - PJON_DELAY_MICROSECONDS(SWBB_BIT_SPACER * SWBB_INITIAL_SPACER_MULTIPLIER); + PJON_DELAY_MICROSECONDS(SWBB_BIT_SPACER * SWBB_PREAMBLE); PJON_IO_WRITE(_output_pin, LOW); PJON_DELAY_MICROSECONDS(SWBB_BIT_WIDTH); n--; diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 25f54a3539..699b8f3e6f 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -338,6 +338,26 @@ #endif #endif + +/* The width of the preamble of a frame (by default set to 1 x SWBB_BIT_SPACER) + Maximum allowed value is 100 or a preamble 100 x SWBB_BIT_SPACER + This feature avoids retransmissions, in order to avoid devices loosing + frames while executing tasks a preamble can be transmitted to signal the + start of a frame. The preamble can be used when devices need to execute + long tasks. */ + +#ifndef SWBB_PREAMBLE + #define SWBB_PREAMBLE 1 +#endif + +/* The maximum width of the preamble (by default set to 1 x SWBB_BIT_SPACER) + Maximum allowed value is 100 or a preamble 100 x SWBB_BIT_SPACER + To have full interoperability set SWBB_MAX_PREAMBLE = 100 */ + +#ifndef SWBB_MAX_PREAMBLE + #define SWBB_MAX_PREAMBLE 100 +#endif + /* Synchronous acknowledgement response offset. If (latency + CRC computation) > (SWBB_RESPONSE_OFFSET * length) synchronous acknowledgement reliability could be affected or disrupted diff --git a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md index b188cd75d9..4c4be9e0b9 100644 --- a/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md +++ b/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md @@ -29,7 +29,7 @@ Released into the public domain 29/12/2018 3.0 - Medium access control info, mode 4 03/07/2019 4.0 - Response initializer 10/03/2020 4.1 - Maximum range experimentally determined -17/07/2020 5.0 - Response timeout, tolerance added +17/07/2020 5.0 - Timeout, tolerance and preamble added ``` PJDL (Padded Jittering Data Link) is an asynchronous serial data link for low-data-rate applications that supports both master-slave and multi-master communication over a common conductive medium. PJDL can be easily implemented on limited microcontrollers with low clock accuracy and can operate directly using a single input-output pin. @@ -52,23 +52,23 @@ It is suggested to add 8kΩ-5MΩ pull-down resistor as shown in the graph above ### Communication modes The proposed communication modes are the result of years of testing and optimization and have been selected to be easily supported by limited microcontrollers: -| Mode | Bandwidth | Range | Pad bit | Data bit | Keep busy bit | Latency | Timeout | -| ---- | ------------------ | ----- | ------- | -------- | ------------- | ------- | ------- | -| 1 | 1.97kB/s - 15808Bd | 2000m | 110µs | 44µs | 11µs | 13µs | 20µs/B | -| 2 | 2.21kB/s - 17696Bd | 1600m | 92µs | 40µs | 10µs | 10µs | 20µs/B | -| 3 | 3.10kB/s - 24844Bd | 1200m | 70µs | 28µs | 7µs | 8µs | 20µs/B | -| 4 | 3.34kB/s - 26755Bd | 800m | 65µs | 26µs | 6.5µs | 5µs | 20µs/B | +| Mode | Bandwidth | Range | Preamble bit | Pad bit | Data bit | Keep busy bit | Latency | Timeout | +| ---- | ------------------ | ----- | ------------ | ------- | -------- | ------------- | ------- | ------- | +| 1 | 1.97kB/s - 15808Bd | 2000m | 11000µs | 110µs | 44µs | 11µs | 13µs | 20µs/B | +| 2 | 2.21kB/s - 17696Bd | 1600m | 9200µs | 92µs | 40µs | 10µs | 10µs | 20µs/B | +| 3 | 3.10kB/s - 24844Bd | 1200m | 7000µs | 70µs | 28µs | 7µs | 8µs | 20µs/B | +| 4 | 3.34kB/s - 26755Bd | 800m | 6500µs | 65µs | 26µs | 6.5µs | 5µs | 20µs/B | The following table specifies the exclusive acceptable tolerance of each bit type: -| Mode | Data bit nonet tolerance | Padding bit tolerance | Max keep busy bit tolerance | -| ---- | -------------------------| --------------------- | ---------------------------- | -| 1 | -5us +17us | -5us +17us | -5µs +10µs | -| 2 | -4us +16us | -4us +16us | -5µs +10µs | -| 3 | -3us +11us | -3us +11us | -3µs +10µs | -| 4 | -3us +10us | -3us +10us | -3µs +10µs | +| Mode | Preamble bit | Padding bit | Data bit nonet | Keep busy bit | +| ---- | -------------- | ----------- | -------------- | ------------- | +| 1 | -11000us +0us | -5us +17us | -5us +17us | -5µs +10µs | +| 2 | -9200us +0us | -4us +16us | -4us +16us | -5µs +10µs | +| 3 | -7000us +0us | -3us +11us | -3us +11us | -3µs +10µs | +| 4 | -6500us +0us | -3us +10us | -3us +10us | -3µs +10µs | -Positive tolerance is higher to accept bit-banged signals that are generally longer than expected. +Padding bit, data bit and keep busy bit have higher positive tolerance to accept bit-banged signals that are generally longer than expected. ### Medium access control PJDL specifies a variation of the carrier-sense, non-persistent random multiple access method (non-persistent CSMA). Devices can detect an ongoing transmission for this reason collisions can only occur in multi-master mode when 2 or more devices start to transmit at the same time. When a collision occurs it can be detected by the receiver because of synchronization loss or by the transmitter if an active collision avoidance procedure is implemented. @@ -81,7 +81,7 @@ The reception technique is based on 3 steps: 2. Synchronize with its falling edge 3. Ensure it is followed by a low data bit -If so reception starts, if not, interference, synchronization loss or simply absence of communication is detected. While receiving a sequence of bytes a synchronization pad is acceptable even if prepended by a 0 of up to (data bit / 4) - 1. +If so reception starts, if not, interference, synchronization loss or simply absence of communication is detected. While receiving a sequence of bytes a synchronization pad is acceptable even if prepended by a 0 of up to the maximum positive data bit nonet tolerance. ```cpp ___________ ___________________________ @@ -94,18 +94,18 @@ If so reception starts, if not, interference, synchronization loss or simply abs The synchronization pad adds overhead although it includes synchronization along with the data and eliminates the need of a dedicated clock line. The presence of the synchronization pad between each byte also ensures that a frame composed of a series of bytes with decimal value 0 can be transmitted safely without risk of collision. ### Frame transmission -Before a frame transmission the communication medium's state is analysed, if high communication is detected and collision is avoided, if low for a duration of one byte plus the latency and a small random time, frame transmission starts with an initializer composed by 3 consecutive synchronization pads followed by data bytes. The synchronization pad is used for both byte and frame initialization to reduce the implementation complexity. PJDL frames do not have an intrinsic length limit. +Before a frame transmission the communication medium's state is analysed, if high communication is detected and collision is avoided, if low for a duration of one byte plus the latency and a small random time, frame transmission starts with a frame preamble and a frame initializer composed by 3 consecutive synchronization pads followed by data bytes. The synchronization pad is used for both byte and frame initialization to reduce the implementation complexity. PJDL frames do not have an intrinsic length limit. ```cpp - ________ _________________ __________________________________ -|ANALYSIS| FRAME INIT | DATA BYTES | -|________|_____ _____ _____|________________ _________________| -| |Sync |Sync |Sync |Sync | Byte |Sync | Byte | -| |___ |___ |___ |___ | __ |___ | _ _| -| | | | | | | | | | | | | | | | | | | -|00000000| 1 |0| 1 |0| 1 |0| 1 |0|0000|11|00| 1 |0|00000|1|0|1| -|________|___|_|___|_|___|_|___|_|____|__|__|___|_|_____|_|_|_| + ________ __________ _________________ ________________ +|ANALYSIS| PREAMBLE | FRAME INIT | DATA BYTES | +|________|__________|_____ _____ _____|________________| +| | |Sync |Sync |Sync |Sync | Byte | +| |__________|___ |___ |___ |___ | __ | +| | | | | | | | | | | | | | +|00000000| 1 | 1 |0| 1 |0| 1 |0| 1 |0|0000|11|00| +|________|__________|___|_|___|_|___|_|___|_|____|__|__| ``` -When a frame is received a low performance microcontroller with an inaccurate clock can correctly synchronize with transmitter during the frame initializer and consequently each byte is received. On receiver's side a frame reception starts if 3 synchronization pads are detected. Frame initialization is 100% reliable, false positives can only occur because of externally induced interference. +When a frame is received a low performance microcontroller with an inaccurate clock can correctly identify a preamble, synchronize with transmitter during the frame initializer and consequently each byte is received. Frame initialization is 100% reliable, false positives can only occur because of externally induced interference. If the implementation applies polling, the preamble can be used to reduce the chances of transmission failure when the receiver's polling frequency is too low to detect incoming frames. The preamble's maximum length is 100 times the length of a padding bit. ### Synchronous response A frame transmission can be optionally followed by a synchronous response sent by its recipient. Between frame transmission and a synchronous response there is a variable time which duration is influenced by latency. From 2f3dbf7f6e8c2908c7ab612c4e8c5b847fe7a73f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Sep 2020 21:12:09 +0200 Subject: [PATCH 232/323] SoftwareBitBang max preamble default config fix --- src/strategies/SoftwareBitBang/README.md | 12 +++++++----- src/strategies/SoftwareBitBang/SoftwareBitBang.h | 5 +---- src/strategies/SoftwareBitBang/Timing.h | 13 ++++++------- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index b84beb7e7c..e9a12a2303 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -56,11 +56,13 @@ The picture above shows a [PJDL](/src/strategies/SoftwareBitBang/specification/P ### Configuration Before including the library it is possible to configure `SoftwareBitBang` using predefined constants: -| Constant | Purpose | Supported value | -| ----------------------- |------------------------------------ | ------------------------------------------ | -| `SWBB_MODE` | Data transmission mode | 1, 2, 3, 4 | -| `SWBB_BACK_OFF_DEGREE` | Maximum back-off exponential degree | Numeric value (4 by default) | -| `SWBB_MAX_ATTEMPTS` | Maximum transmission attempts | Numeric value (20 by default) | +| Constant | Purpose | Supported value | +| ----------------------- |------------------------------------- | ------------------------------------------ | +| `SWBB_MODE` | Data transmission mode | 1, 2, 3, 4 | +| `SWBB_BACK_OFF_DEGREE` | Maximum back-off exponential degree | Numeric value (4 by default) | +| `SWBB_MAX_ATTEMPTS` | Maximum transmission attempts | Numeric value (20 by default) | +| `SWBB_PREAMBLE` | Length of the frame preamble | Numeric value (1 by default) max 100 | +| `SWBB_MAX_PREAMBLE` | Maximum length of the frame preamble | Numeric value (1 by default) max 100 | `SoftwareBitBang` supports the use of input and output pins because separated signals may be required if additional circuitry is used for amplification or noise filtering. It also works if pins are directly connected as a simple point-to-point null-modem or cross-over serial link. diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index 34496997d0..684f359386 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -306,8 +306,6 @@ class SoftwareBitBang { } bool sync_preamble() { - // Allow a wider packet start sampling interval for devices - // that do other tasks and cannot sample very fast. return sync(SWBB_BIT_SPACER * SWBB_MAX_PREAMBLE); }; @@ -316,8 +314,7 @@ class SoftwareBitBang { void pulse(uint8_t n) { #if SWBB_PREAMBLE != 1 if (n == 3) { - // Extra long first pad of packet initializer, to tolerate devices - // that have other tasks and cannot sample continuously. + // Transmit preamble PJON_IO_WRITE(_output_pin, HIGH); PJON_DELAY_MICROSECONDS(SWBB_BIT_SPACER * SWBB_PREAMBLE); PJON_IO_WRITE(_output_pin, LOW); diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 699b8f3e6f..1f7c73c4cf 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -340,22 +340,21 @@ /* The width of the preamble of a frame (by default set to 1 x SWBB_BIT_SPACER) - Maximum allowed value is 100 or a preamble 100 x SWBB_BIT_SPACER - This feature avoids retransmissions, in order to avoid devices loosing - frames while executing tasks a preamble can be transmitted to signal the - start of a frame. The preamble can be used when devices need to execute - long tasks. */ + Maximum allowed value is 100 or a preamble of 100 x SWBB_BIT_SPACER + When devices execute other tasks frames may be lost unheard. The preamble + can be used to avoid transmission failure. To avoid retransmissions the + preamble length should be slightly longer than the task's duration. */ #ifndef SWBB_PREAMBLE #define SWBB_PREAMBLE 1 #endif /* The maximum width of the preamble (by default set to 1 x SWBB_BIT_SPACER) - Maximum allowed value is 100 or a preamble 100 x SWBB_BIT_SPACER + Maximum allowed value is 100 or a preamble of 100 x SWBB_BIT_SPACER To have full interoperability set SWBB_MAX_PREAMBLE = 100 */ #ifndef SWBB_MAX_PREAMBLE - #define SWBB_MAX_PREAMBLE 100 + #define SWBB_MAX_PREAMBLE 1 #endif /* Synchronous acknowledgement response offset. From 34e683f1ca251915c73369559901741329074b4d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Sep 2020 22:16:11 +0200 Subject: [PATCH 233/323] PJON README simplified --- README.md | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/README.md b/README.md index 877021b477..3b1714e1a8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![PJON](http://www.gioblu.com/PJON/PJON-github-header-tiny.png) ## PJON 12.1 -PJON® (Padded Jittering Operative Network) is an arduino-compatible, multi-master, multi-media network protocol. It proposes a new Open Standard, it is designed as a framework and implements a totally software-defined network protocol stack that can be easily cross-compiled on many MCUs and architectures like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media and protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. +PJON® (Padded Jittering Operative Network) is an arduino-compatible, multi-master, multi-media network protocol. It proposes a new Open Standard, it is designed as a framework and implements a totally software-defined network protocol stack that can be easily cross-compiled on many MCUs and architectures like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media and protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). [![Get PJON bus id](https://img.shields.io/badge/get-PJON%20bus%20id-lightgrey.svg)](http://www.pjon.org/get-bus-id.php) [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) @@ -24,23 +24,6 @@ PJON is used in thousands of devices and its community has spread worldwide beca - Optional acknowledgement - Error handling -### Specifications -- [PJON v4.0](specification/PJON-protocol-specification-v4.0.md) -- [PJDL v5.0](src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) -- [PJDLR v3.0](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) -- [PJDLS v2.0](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) -- [TSDL v3.0](src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md) - -### Documentation -- [Addressing](/documentation/addressing.md) -- [Configuration](/documentation/configuration.md) -- [Data reception](/documentation/data-reception.md) -- [Data structures](/documentation/data-structures.md) -- [Data transmission](/documentation/data-transmission.md) -- [Error handling](/documentation/error-handling.md) -- [Routing](/documentation/routing.md) -- [IO setup](/documentation/io-setup.md) - ### Publications - [PJON protocol handbook](https://www.pjon-technologies.com/collections/frontpage/products/pjon-protocol-hand-book) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) - [PJON 12.0 big box](https://www.pjon-technologies.com/collections/frontpage/products/pjon-protocol-12-0-big-box) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) From b403841dd567481da234d6e946d6583ee1bf6c7f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Sep 2020 22:16:55 +0200 Subject: [PATCH 234/323] SoftwareBitBang README and comments minor fix --- src/strategies/SoftwareBitBang/README.md | 6 +++--- src/strategies/SoftwareBitBang/Timing.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index e9a12a2303..ca387512b7 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -61,8 +61,8 @@ Before including the library it is possible to configure `SoftwareBitBang` using | `SWBB_MODE` | Data transmission mode | 1, 2, 3, 4 | | `SWBB_BACK_OFF_DEGREE` | Maximum back-off exponential degree | Numeric value (4 by default) | | `SWBB_MAX_ATTEMPTS` | Maximum transmission attempts | Numeric value (20 by default) | -| `SWBB_PREAMBLE` | Length of the frame preamble | Numeric value (1 by default) max 100 | -| `SWBB_MAX_PREAMBLE` | Maximum length of the frame preamble | Numeric value (1 by default) max 100 | +| `SWBB_PREAMBLE` | Preamble Length | Numeric value (1 by default), max 100 | +| `SWBB_MAX_PREAMBLE` | Maximum preamble length | Numeric value (1 by default), max 100 | `SoftwareBitBang` supports the use of input and output pins because separated signals may be required if additional circuitry is used for amplification or noise filtering. It also works if pins are directly connected as a simple point-to-point null-modem or cross-over serial link. @@ -90,7 +90,7 @@ PJON application example made by the user [Michael Teeuw](http://michaelteeuw.nl ### Known issues - A 1-5 MΩ pull down resistor could be necessary to reduce interference, see [Mitigate interference](https://github.com/gioblu/PJON/wiki/Mitigate-interference). - When using more than one instance of `SoftwareBitBang` in the same sketch use pins part of different port groups to avoid cross-talk. -- During the execution of other tasks or delays a certain amount of packets could be potentially lost because transmitted out of the polling time of the receiver device. Thanks to the PJON packet handler after some retries the packet is received but a certain amount of bandwidth is wasted. If this situation occurs, try to reduce as much as possible the duration of other tasks and or use a longer polling time using `receive` and passing the requested amount of microseconds: `bus.receive(1000); // Poll for 1 millisecond`. +- During the execution of other tasks or delays a certain amount of packets could be potentially lost because transmitted out of the polling time of the receiver device. Thanks to the PJON packet handler after some retries the packet is received but a certain amount of bandwidth is wasted. If this situation occurs try to reduce the duration of other tasks and use a frame preamble setting `SWBB_MAX_PREAMBLE` and `SWBB_PREAMBLE` to a value between 1 and 100. The optimal preamble length is the maximum interval between each `bus.receive()` call divided by `SWBB_BIT_SPACER` - `SoftwareBitBang` strategy can have compatibility issues with codebases that are using interrupts, reliability or bandwidth loss can occur because of the interruptions made by third party software. ### Safety warning diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 1f7c73c4cf..ee369d7f18 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -339,7 +339,7 @@ #endif -/* The width of the preamble of a frame (by default set to 1 x SWBB_BIT_SPACER) +/* Frame preamble length (by default set to 1 x SWBB_BIT_SPACER) Maximum allowed value is 100 or a preamble of 100 x SWBB_BIT_SPACER When devices execute other tasks frames may be lost unheard. The preamble can be used to avoid transmission failure. To avoid retransmissions the @@ -349,7 +349,7 @@ #define SWBB_PREAMBLE 1 #endif -/* The maximum width of the preamble (by default set to 1 x SWBB_BIT_SPACER) +/* Maximum frame preamble length (by default set to 1 x SWBB_BIT_SPACER) Maximum allowed value is 100 or a preamble of 100 x SWBB_BIT_SPACER To have full interoperability set SWBB_MAX_PREAMBLE = 100 */ From 8f938ad8f7a4a37ea9694e3c5a03748da1b4eef6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Sep 2020 23:03:57 +0200 Subject: [PATCH 235/323] Outdated comments removed from SoftwareBitBang examples --- .../Any/MultiStrategyLink/Transmitter1/Transmitter1.ino | 8 -------- .../Any/MultiStrategyLink/Transmitter2/Transmitter2.ino | 8 -------- .../Transmitter/Transmitter.ino | 7 ------- .../ClassMemberCallback/Receiver/Receiver.ino | 6 ------ .../ClassMemberCallback/Transmitter/Transmitter.ino | 6 ------ .../SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino | 6 ------ .../NetworkAnalysis/Transmitter/Transmitter.ino | 6 ------ .../PJONLocal/NetworkAnalysis/Receiver/Receiver.ino | 6 ------ .../PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino | 6 ------ .../SoftwareBitBang/SendAndReceive/Device1/Device1.ino | 6 ------ .../SoftwareBitBang/SendAndReceive/Device2/Device2.ino | 6 ------ .../Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino | 6 ------ .../SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino | 6 ------ .../SoftwareBitBang/UsePacketId/Receiver/Receiver.ino | 6 ------ .../UsePacketId/Transmitter/Transmitter.ino | 6 ------ .../SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino | 7 ------- .../LongPacketCRC32/Transmitter/Transmitter.ino | 7 ------- .../SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino | 7 ------- .../NetworkAnalysis/Transmitter/Transmitter.ino | 6 ------ .../SoftwareBitBang/SpeedTest/Receiver/Receiver.ino | 7 ------- .../SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino | 6 ------ 21 files changed, 135 deletions(-) diff --git a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino index d5e8659a05..fa328f64dd 100644 --- a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino +++ b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter1/Transmitter1.ino @@ -5,14 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Acknowledge Latency maximum duration (1000 microseconds default). - Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to - receiver to compute the CRC and to respond with a synchronous acknowledgement - SWBB_RESPONSE_TIMEOUT can be reduced to higher communication speed if - devices are near and able to compute CRC fast enough. */ - -//#define SWBB_RESPONSE_TIMEOUT 1000 - #include diff --git a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino index 0ec5e22748..0ec637a37f 100644 --- a/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino +++ b/examples/ARDUINO/Local/Any/MultiStrategyLink/Transmitter2/Transmitter2.ino @@ -5,14 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Acknowledge Latency maximum duration (1000 microseconds default). - Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to - receiver to compute the CRC and to respond with a synchronous acknowledgement - SWBB_RESPONSE_TIMEOUT can be reduced to higher communication speed if - devices are near and able to compute CRC fast enough. */ - -//#define SWBB_RESPONSE_TIMEOUT 1000 - #include diff --git a/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Transmitter/Transmitter.ino index 70bd92094d..4f84e840de 100644 --- a/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/Any/StrategyLinkNetworkAnalysis/Transmitter/Transmitter.ino @@ -5,13 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Acknowledge Latency maximum duration (1000 microseconds default). - Can be necessary to higher SWBB_RESPONSE_TIMEOUT to leave enough time to - receiver to compute the CRC and to respond with a synchronous acknowledgement - SWBB_RESPONSE_TIMEOUT can be reduced to higher communication speed if - devices are near and able to compute CRC fast enough. */ -//#define SWBB_RESPONSE_TIMEOUT 1000 - #include float test; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino index c4db327eb4..894fb2868f 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Receiver/Receiver.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino index 0760e2890c..a2e6fb81fa 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/ClassMemberCallback/Transmitter/Transmitter.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino index 5688a76d74..fa29611400 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino index 7e618724a2..b0500cb7b7 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - #include float test; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino index 6b4104c333..94de9fabed 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - // Include only SoftwareBitBang #include // Include PJONLocal diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino index cc8c89293f..2b564dc0a0 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - #include // Include PJONLocal #include // Include only SoftwareBitBang diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino index 6a932df11b..7a6b4e7686 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device1/Device1.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino index 633762822a..806404c124 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SendAndReceive/Device2/Device2.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino index 403ec19aad..5429f5c6c0 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - #include float test; diff --git a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino index 0df80f7c80..b41ad29428 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - #include diff --git a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino index 3e0d682232..42d4cdaf54 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Receiver/Receiver.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - // Include packet id feature #define PJON_INCLUDE_PACKET_ID diff --git a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino index 9c24311664..2186748b43 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/UsePacketId/Transmitter/Transmitter.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - // Include packet id feature #define PJON_INCLUDE_PACKET_ID diff --git a/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino index 6fc1b99278..cf4e24f09f 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Receiver/Receiver.ino @@ -2,13 +2,6 @@ #define PJON_PACKET_MAX_LENGTH 325 // Make the buffer big enough #define PJON_MAX_PACKETS 2 // Reduce number of packets not to empty memory -/* Response timeout duration duration (1500 microseconds default). - SWBB_RESPONSE_TIMEOUT duration must be long enough for the receiver to have the - time to compute the CRC and to respond with a synchronous acknowledgement. - Below SWBB_RESPONSE_TIMEOUT is set to 4 milliseconds to give enough time to - the receiver to compute CRC32 of a 300 bytes string. */ -#define SWBB_RESPONSE_TIMEOUT 4000 - #include float test; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Transmitter/Transmitter.ino index d0885bfbb2..bbaa5f3396 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/LongPacketCRC32/Transmitter/Transmitter.ino @@ -2,13 +2,6 @@ #define PJON_PACKET_MAX_LENGTH 325 // Make the buffer big enough #define PJON_MAX_PACKETS 2 // Reduce number of packets not to empty memory -/* Response timeout duration duration (1500 microseconds default). - SWBB_RESPONSE_TIMEOUT duration must be long enough for the receiver to have the - time to compute the CRC and to respond with a synchronous acknowledgement. - Below SWBB_RESPONSE_TIMEOUT is set to 4 milliseconds to give enough time to - the receiver to compute CRC32 of a 300 bytes string. */ -#define SWBB_RESPONSE_TIMEOUT 4000 - #include // Bus id definition diff --git a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino index 30ecc2c15e..82f7c3cc8b 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Receiver/Receiver.ino @@ -5,13 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - - #include // Bus id definition diff --git a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino index 02b993f27b..f1502f61e8 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/NetworkAnalysis/Transmitter/Transmitter.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - #include float test; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino index c01826f7c0..c16c4b69ea 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Receiver/Receiver.ino @@ -5,13 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - - #include float test; diff --git a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino index 37d9d044db..479506b270 100644 --- a/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Network/SoftwareBitBang/SpeedTest/Transmitter/Transmitter.ino @@ -5,12 +5,6 @@ // #define SWBB_MODE 3 // 2.94kB/s - 23529Bd // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd -/* Response timeout (1500 microseconds default). - If the acknowledgement fails SWBB_RESPONSE_TIMEOUT may be too short - specially if long packets are sent or if devices are far from each other */ - -//#define SWBB_RESPONSE_TIMEOUT 1500 - #include // Bus id definition From 3ba0e66b5a2a31f834ac3439e4349025feb74fe4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Oct 2020 19:02:29 +0200 Subject: [PATCH 236/323] ZEPHYR config and examples modified to work with master (https://github.com/gioblu/PJON/pull/366) --- .../DualUDP/PingPong/Receiver/src/main.cpp | 4 +-- .../DualUDP/PingPong/Transmitter/src/main.cpp | 4 +-- .../DualUDP/PingPong/Transmitter/west.yml | 2 +- zephyr/CMakeLists.txt | 5 ++- zephyr/Kconfig | 32 +++++++++++++------ 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/src/main.cpp b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/src/main.cpp index 173b856a4f..8b71ac664b 100644 --- a/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/src/main.cpp +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Receiver/src/main.cpp @@ -27,9 +27,9 @@ #define FLAGS 0 #endif -#include "PJON.h" +#include "PJONDualUDP.h" -PJON bus(CONFIG_PJON_DEVICE_ID); +PJONDualUDP bus(CONFIG_PJON_DEVICE_ID); static int cnt = 0; static struct net_mgmt_event_callback mgmt_cb; diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/src/main.cpp b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/src/main.cpp index 6d9848e902..6cb9557601 100644 --- a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/src/main.cpp +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/src/main.cpp @@ -27,9 +27,9 @@ #define FLAGS 0 #endif -#include "PJON.h" +#include "PJONDualUDP.h" -PJON bus(CONFIG_PJON_DEVICE_ID); +PJONDualUDP bus(CONFIG_PJON_DEVICE_ID); static int cnt = 0; static struct net_mgmt_event_callback mgmt_cb; diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/west.yml b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/west.yml index 71cbc1588f..4710746f39 100644 --- a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/west.yml +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/west.yml @@ -28,6 +28,6 @@ manifest: path: modules/hal/stm32 - name: pjon - url: git@github.com:Cimex97/PJON.git + url: git@github.com:gioblu/PJON.git revision: feature/zephyr_support path: modules/pjon diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 44695abb21..08fc8940af 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -10,7 +10,6 @@ target_include_directories(PJON INTERFACE ../src) if(CONFIG_PJON_STRATEGY_THROUGHSERIAL) target_compile_definitions(PJON INTERFACE -PJON_INCLUDE_TS TS_INITIAL_DELAY=CONFIG_TS_INITIAL_DELAY TS_COLLISION_DELAY=CONFIG_TS_COLLISION_DELAY TS_RESONSE_TIME_OUT=CONFIG_TS_RESONSE_TIME_OUT @@ -19,13 +18,13 @@ TS_BYTE_TIME_OUT=CONFIG_TS_BYTE_TIME_OUT TS_MAX_ATTEMTS=CONFIG_TS_MAX_ATTEMTS TS_BACK_OFF_DEGREE=CONFIG_TS_BACK_OFF_DEGREE TS_RS485_DELAY=CONFIG_TS_RS485_DELAY -TS_FLUSH_OFFSET=CONFIG_TS_FLUSH_OFFSET) +TS_FLUSH_OFFSET=CONFIG_TS_FLUSH_OFFSET +TS_READ_INTERVAL=CONFIG_TS_READ_INTERVAL) endif() if(CONFIG_PJON_STRATEGY_DUALUDP) target_compile_definitions(PJON INTERFACE -PJON_INCLUDE_DUDP DUDP_RESPONSE_TIMEOUT=CONFIG_DUDP_RESPONSE_TIMEOUT DUDP_MINIMUM_SEND_INTERVAL_MS=CONFIG_DUDP_MINIMUM_SEND_INTERVAL_MS DUDP_MAX_RETRIES=CONFIG_DUDP_MAX_RETRIES diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 476e5c52b1..ae6ef38f31 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -130,6 +130,13 @@ config TS_FLUSH_OFFSET default 152 help Force blocking sending hack (adds a delay for each character sent). + +config TS_READ_INTERVAL + int "READ INTERVAL" + default 100 + help + Interval between each serial read call. + endif endmenu @@ -162,19 +169,12 @@ config PJON_PACKET_MAX_LENGTH The max packet length defines the length of packets pre-allocated buffers so it strongly affects memory consumption. -config PJON_INCLUDE_ASYNC_ACK - bool "INCLUDE ASYNC ACK" - default false - help - If set to false async ack feature is not included saving memory - (it saves around 1kB of memory) - config PJON_INCLUDE_PACKET_ID bool "INCLUDE PACKET ID" default false help - If set to false packet id feature is not included saving memory - (it saves around 1kB of memory) + If set to false packet id feature is not included and 300B of program + memory plus 80B of RAM are spared. config PJON_MAX_RECENT_PACKET_IDS int "MAX RECENT PACKET IDS" @@ -182,6 +182,20 @@ config PJON_MAX_RECENT_PACKET_IDS help Maximum packet ids record kept in memory (to avoid duplicated exchanges) +config PJON_INCLUDE_PORT + bool "INCLUDE PORT" + default false + help + If set to false port feature is not included and 100B of program memory + plus 2B of RAM are spared. + +config PJON_INCLUDE_MAC + bool "INCLUDE MAC" + default false + help + If set to false port feature is not included and 200B of program memory + plus 20B of RAM are spared. + config APP_LINK_WITH_PJON bool "Link 'app' with PJON" default y From 0e94bfef2cd92e3e62e603d4bfc0766663ef3822 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Oct 2020 19:19:31 +0200 Subject: [PATCH 237/323] @der-schne and @Cimex97 added to contributors' list --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b1714e1a8..9e260a4449 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Telecomunicación - [Universidad de Cantabria](https://web.unican.es/) (ES) ### Contribute Feel free to send a pull request sharing something you have made that could help, if you want to support this project you can also try to solve an [issue](https://github.com/gioblu/PJON/issues). Thanks to support, expertise, kindness and talent of the following contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: -[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen) and [Julio Aguirre](https://github.com/jcallano). +[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen), [Julio Aguirre](https://github.com/jcallano), [Cimex97](https://github.com/Cimex97) and [der-schne](https://github.com/der-schne). ### Compliant tools - [ModuleInterface](https://github.com/fredilarsen/ModuleInterface) - easy config and value sync between IoT modules by Fred Larsen From f94b05f1b0afe300f4c75e524cc966b8a4f4c249 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Oct 2020 00:10:29 +0200 Subject: [PATCH 238/323] PJON README updated os support --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e260a4449..f5c81bace4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![PJON](http://www.gioblu.com/PJON/PJON-github-header-tiny.png) ## PJON 12.1 -PJON® (Padded Jittering Operative Network) is an arduino-compatible, multi-master, multi-media network protocol. It proposes a new Open Standard, it is designed as a framework and implements a totally software-defined network protocol stack that can be easily cross-compiled on many MCUs and architectures like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media and protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). +PJON® (Padded Jittering Operative Network) is an arduino-compatible, multi-master, multi-media network protocol. It proposes a new Open Standard, it is designed as a framework and implements a totally software-defined network protocol stack that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media and protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). [![Get PJON bus id](https://img.shields.io/badge/get-PJON%20bus%20id-lightgrey.svg)](http://www.pjon.org/get-bus-id.php) [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) From 08f3c65109bbc6970acbec0ddd3652285e4f2341 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Oct 2020 00:27:39 +0200 Subject: [PATCH 239/323] AnalogSampling README minor fix --- src/strategies/AnalogSampling/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strategies/AnalogSampling/README.md b/src/strategies/AnalogSampling/README.md index 7ab0e11ef0..2d009f07e0 100644 --- a/src/strategies/AnalogSampling/README.md +++ b/src/strategies/AnalogSampling/README.md @@ -4,9 +4,9 @@ |--------|-----------|--------------------| | Light pulses over air or optic-fibre | 1 or 2 | `#include `| -`AnalogSampling` strategy or data link complies with [PJDLS v2.0](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md), it is designed to communicate data wirelessly using light impulses and its sampling technique is based on analog readings. This strategy is able to use a single LED for both photo-emission and photo-reception phases providing with wireless half-duplex connectivity between devices with a range of up to 5 meters. Most appliances have at least a useless energy consuming LED on board, right? +The `AnalogSampling` strategy is a software implementation of [PJDLS](/src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md), it is designed to communicate data wirelessly using light impulses and its sampling technique is based on analog readings. This strategy is able to use a single LED for both photo-emission and photo-reception phases providing with wireless half-duplex connectivity between devices with a range of up to 5 meters. Most appliances have at least a useless energy consuming LED on board, right? Thanks to this strategy that can be used for communication. -`AnalogSampling` can also be used with separate emitter and receiver pins enabling cheap long range wireless communication using standard photo-diodes, light-emitting diodes or laser diodes. The proposed circuit, technique and codebase were originally implemented in the far 2011, see the first [video documented experiment](https://www.youtube.com/watch?v=-Ul2j6ixbmE). Take a look at the [video introduction](https://www.youtube.com/watch?v=1BeGYMjg-DI) for a brief showcase of its features. +`AnalogSampling` can also be used with separate emitter and receiver pins enabling cheap long range wireless or optic-fibre communication using standard photo-diodes, light-emitting diodes or laser diodes. The proposed circuit, technique and codebase were originally implemented in 2011, see the first [video documented experiment](https://www.youtube.com/watch?v=-Ul2j6ixbmE). Take a look at the [video introduction](https://www.youtube.com/watch?v=1BeGYMjg-DI) for a brief showcase of its features. ### Compatibility | MCU | Clock | Supported pins | Supported modes | From 28a497536ef5849e1fdf714e6bde06dd30bc7335 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 Oct 2020 16:04:57 +0200 Subject: [PATCH 240/323] Examples inclusion and instantiation update --- .../SoftwareBitBangSurrogate/Surrogate/Surrogate.ino | 4 ++-- .../SWBB-MQTT-Gateway/Gateway/Gateway.ino | 3 ++- .../SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino | 8 ++++---- .../Local/LocalUDP/PingPong/Receiver/Receiver.cpp | 4 ++-- .../LocalUDP/PingPong/Transmitter/Transmitter.cpp | 4 ++-- .../ARDUINO/Local/VirtualBusRouter/Device1/Device1.ino | 4 ++-- .../ARDUINO/Local/VirtualBusRouter/Device2/Device2.ino | 4 ++-- .../LocalBusViaNATSwitch/LocalDevice/LocalDevice.ino | 10 +++++----- .../NetworkDevice/NetworkDevice.ino | 10 +++++----- .../routing/ARDUINO/Network/Switch/Device1/Device1.ino | 4 ++-- .../routing/ARDUINO/Network/Switch/Device2/Device2.ino | 4 ++-- .../Network/Switch/SimpleSwitch/SimpleSwitch.ino | 5 +++-- 12 files changed, 33 insertions(+), 31 deletions(-) diff --git a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino index 860939c536..70ffd04862 100644 --- a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino +++ b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino @@ -15,12 +15,12 @@ //#define ETCP_SINGLE_SOCKET_WITH_ACK #include +#include const uint8_t DEVICE_ID = 45; // SWBB Device ID for this device and the RemoteWorker - -PJON busA(DEVICE_ID); +PJONSoftwareBitBang busA(DEVICE_ID); PJONEthernetTCP busB(1); // Ethernet configuration for this device diff --git a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino index f85edbd01d..d28f9b3cd0 100644 --- a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino +++ b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino @@ -3,6 +3,7 @@ #define PJON_MAX_PACKETS 2 #include +#include // Ethernet configuration for this device byte mac[] = {0xDA, 0xCA, 0x7E, 0xEF, 0xFE, 0x5D}; @@ -10,7 +11,7 @@ uint8_t broker_ip[] = { 192, 168, 1, 71 }; #define PJON_GATEWAY_ID 254 -PJON bus(PJON_GATEWAY_ID); +PJONSoftwareBitBang bus(PJON_GATEWAY_ID); PJONMQTTTranslate mqtt; uint32_t cnt_to_mqtt = 0, cnt_from_mqtt = 0; diff --git a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino index 647f42873d..8eaf356b06 100644 --- a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino +++ b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/SomeDevice/SomeDevice.ino @@ -13,12 +13,11 @@ // pjon/device42/output/temperature as would have been the case with // the MIRROR_TRANSLATE mode. -#include +#include #define PJON_GATEWAY_ID 254 - -PJON bus(42); +PJONSoftwareBitBang bus(42); float temperature = 20.0; // "Measurement" float temperature_target = 20.0; // "Target" @@ -31,7 +30,8 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info strncpy(buf, (const char *)payload, len); buf[len -1] = 0; Serial.print("Received from broker: "); Serial.println(buf); - if (strncmp("temperature=", buf, 12)==0) temperature_target = atof(&buf[12]); + if(strncmp("temperature=", buf, 12) == 0) + temperature_target = atof(&buf[12]); } } diff --git a/examples/WINX86/Local/LocalUDP/PingPong/Receiver/Receiver.cpp b/examples/WINX86/Local/LocalUDP/PingPong/Receiver/Receiver.cpp index 3ba52e85ea..12e5c88436 100644 --- a/examples/WINX86/Local/LocalUDP/PingPong/Receiver/Receiver.cpp +++ b/examples/WINX86/Local/LocalUDP/PingPong/Receiver/Receiver.cpp @@ -1,7 +1,7 @@ -#include +#include -PJON bus(44); +PJONLocalUDP bus(44); uint32_t count = 0; diff --git a/examples/WINX86/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp b/examples/WINX86/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp index caa9c7ec4d..78a6eb10ce 100644 --- a/examples/WINX86/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/LocalUDP/PingPong/Transmitter/Transmitter.cpp @@ -1,7 +1,7 @@ -#include +#include -PJON bus(45); +PJONLocalUDP bus(45); uint32_t count = 0; diff --git a/examples/routing/ARDUINO/Local/VirtualBusRouter/Device1/Device1.ino b/examples/routing/ARDUINO/Local/VirtualBusRouter/Device1/Device1.ino index 1dcf6229af..e179779618 100644 --- a/examples/routing/ARDUINO/Local/VirtualBusRouter/Device1/Device1.ino +++ b/examples/routing/ARDUINO/Local/VirtualBusRouter/Device1/Device1.ino @@ -1,6 +1,6 @@ -#include +#include -PJON bus(100); +PJONSoftwareBitBang bus(100); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { if((char)payload[0] == 'B') { diff --git a/examples/routing/ARDUINO/Local/VirtualBusRouter/Device2/Device2.ino b/examples/routing/ARDUINO/Local/VirtualBusRouter/Device2/Device2.ino index d06e0a0e0f..b90d0769d0 100644 --- a/examples/routing/ARDUINO/Local/VirtualBusRouter/Device2/Device2.ino +++ b/examples/routing/ARDUINO/Local/VirtualBusRouter/Device2/Device2.ino @@ -1,6 +1,6 @@ -#include +#include -PJON bus(200); +PJONSoftwareBitBang bus(200); void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { /* Make use of the payload before sending something, the buffer where payload points to is diff --git a/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/LocalDevice/LocalDevice.ino b/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/LocalDevice/LocalDevice.ino index 4f383892db..6e6924753b 100644 --- a/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/LocalDevice/LocalDevice.ino +++ b/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/LocalDevice/LocalDevice.ino @@ -1,20 +1,20 @@ /* Route packets between a local bus and a network bus in both directions, using a switch that supports NAT (network address translation). - - A device on the local bus can send to a device on a network bus by + + A device on the local bus can send to a device on a network bus by specifying the bus id. If the switch has configured a public bus id (a NAT bus id) for this local bus, the remote devices can also reply. __________ ________ __________ | LOCAL | Pin 7 | NAT | Pin 12 | NETWORK | | DEVICE |_______________| SWITCH |_______________| DEVICE | - |__________| Local bus |________| Bus 0.0.0.2 |__________| + |__________| Local bus |________| Bus 0.0.0.2 |__________| (NAT 0.0.0.1) */ -#include +#include // PJON object for a local bus -PJON bus(44); +PJONSoftwareBitBang bus(44); void setup() { pinMode(LED_BUILTIN, OUTPUT); diff --git a/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NetworkDevice/NetworkDevice.ino b/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NetworkDevice/NetworkDevice.ino index 957b173137..7460e41382 100644 --- a/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NetworkDevice/NetworkDevice.ino +++ b/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NetworkDevice/NetworkDevice.ino @@ -1,23 +1,23 @@ /* Route packets between a local bus and a network bus in both directions, using a switch that supports NAT (network address translation). - - The local bus is assigned a public address 0.0.0.1 in the switch, and that + + The local bus is assigned a public address 0.0.0.1 in the switch, and that bus id can be used to reach devices within the local bus. __________ ________ __________ | LOCAL | Pin 7 | NAT | Pin 12 | NETWORK | | DEVICE |_______________| SWITCH |_______________| DEVICE | - |__________| Local bus |________| Bus 0.0.0.2 |__________| + |__________| Local bus |________| Bus 0.0.0.2 |__________| (NAT 0.0.0.1) */ -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 2}; uint8_t remote_bus_id[] = {0, 0, 0, 1}; // PJON object for a network bus -PJON bus(bus_id, 45); +PJONSoftwareBitBang bus(bus_id, 45); void setup() { pinMode(LED_BUILTIN, OUTPUT); diff --git a/examples/routing/ARDUINO/Network/Switch/Device1/Device1.ino b/examples/routing/ARDUINO/Network/Switch/Device1/Device1.ino index 7ff0ec3ee4..7cac7a0280 100644 --- a/examples/routing/ARDUINO/Network/Switch/Device1/Device1.ino +++ b/examples/routing/ARDUINO/Network/Switch/Device1/Device1.ino @@ -6,14 +6,14 @@ | DEVICE 1 |_______________| SWITCH |_______________| DEVICE 2 | |__________| Bus 0.0.0.1 |________| Bus 0.0.0.2 |__________| */ -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 1}; uint8_t remote_bus_id[] = {0, 0, 0, 2}; // PJON object -PJON bus(bus_id, 44); +PJONSoftwareBitBang bus(bus_id, 44); void setup() { pinMode(LED_BUILTIN, OUTPUT); diff --git a/examples/routing/ARDUINO/Network/Switch/Device2/Device2.ino b/examples/routing/ARDUINO/Network/Switch/Device2/Device2.ino index 7dad8823b2..715ecd0f27 100644 --- a/examples/routing/ARDUINO/Network/Switch/Device2/Device2.ino +++ b/examples/routing/ARDUINO/Network/Switch/Device2/Device2.ino @@ -6,14 +6,14 @@ | DEVICE 1 |_______________| SWITCH |_______________| DEVICE 2 | |__________| Bus 0.0.0.1 |________| Bus 0.0.0.2 |__________| */ -#include +#include // Bus id definition uint8_t bus_id[] = {0, 0, 0, 2}; uint8_t remote_bus_id[] = {0, 0, 0, 1}; // PJON object -PJON bus(bus_id, 45); +PJONSoftwareBitBang bus(bus_id, 45); void setup() { pinMode(LED_BUILTIN, OUTPUT); diff --git a/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino b/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino index 7b6bad2311..f8699cfb87 100644 --- a/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino +++ b/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino @@ -1,3 +1,4 @@ +#include #include /* Route packets between a collection of buses with the same @@ -10,8 +11,8 @@ | DEVICE 1 |_______________| SWITCH |_______________| DEVICE 2 | |__________| Bus 0.0.0.1 |________| Bus 0.0.0.2 |__________| */ -PJON bus1((const uint8_t[4]){0, 0, 0, 1}, PJON_NOT_ASSIGNED), - bus2((const uint8_t[4]){0, 0, 0, 2}, PJON_NOT_ASSIGNED); +PJONSoftwareBitBang bus1((const uint8_t[4]){0, 0, 0, 1}, PJON_NOT_ASSIGNED), + bus2((const uint8_t[4]){0, 0, 0, 2}, PJON_NOT_ASSIGNED); PJONSimpleSwitch router(bus1, bus2); From 940c929d26076edf92e7a7a15404ce57ff2b8406 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 Oct 2020 16:12:35 +0200 Subject: [PATCH 241/323] Zephyr config minor fix as suggested by @Cimex97 --- examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/west.yml | 2 +- zephyr/CMakeLists.txt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/west.yml b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/west.yml index 4710746f39..89ba81c591 100644 --- a/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/west.yml +++ b/examples/ZEPHYR/local/DualUDP/PingPong/Transmitter/west.yml @@ -29,5 +29,5 @@ manifest: - name: pjon url: git@github.com:gioblu/PJON.git - revision: feature/zephyr_support + revision: master path: modules/pjon diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 08fc8940af..85523173c2 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -3,6 +3,8 @@ zephyr_interface_library_named(PJON) zephyr_compile_definitions_ifdef(CONFIG_PJON_MAX_PACKETS PJON_MAX_PACKETS=CONFIG_PJON_MAX_PACKETS) zephyr_compile_definitions_ifdef(CONFIG_PJON_PACKET_MAX_LENGTH PJON_PACKET_MAX_LENGTH=CONFIG_PJON_PACKET_MAX_LENGTH) +zephyr_compile_definitions_ifdef(CONFIG_PJON_INCLUDE_PORT PJON_INCLUDE_PORT) +zephyr_compile_definitions_ifdef(CONFIG_PJON_INCLUDE_MAC PJON_INCLUDE_MAC) target_include_directories(PJON INTERFACE ../src) From 9e6345588f3273f62d1a3d2b36e896b12285bf8a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Oct 2020 21:23:23 +0200 Subject: [PATCH 242/323] Surrogate and routing examples update --- documentation/configuration.md | 8 +- documentation/data-reception.md | 2 +- documentation/io-setup.md | 6 +- .../Surrogate/Surrogate.ino | 26 ++---- .../SWBB-MQTT-Gateway/Gateway/Gateway.ino | 4 +- .../Surrogate/Surrogate.ino | 89 ++++++++----------- .../BlinkTest/Transmitter/Transmitter.cpp | 7 +- .../Transmitter/Transmitter.cpp | 7 +- 8 files changed, 55 insertions(+), 94 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index d8e6e454a8..3a72897869 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -120,7 +120,7 @@ The instance can be configured to include a 16 bits [packet identifier](/specifi // If packet duplication occurs, higher PJON_MAX_RECENT_PACKET_IDS #define PJON_MAX_RECENT_PACKET_IDS 10 // By default 10 - #include + #include ``` Use `set_packet_id` to enable the packet identification: ```cpp @@ -133,7 +133,7 @@ The instance can be configured to include a [network service identifier](/specif ```cpp // Include the port id feature #define PJON_INCLUDE_PORT - #include + #include ``` Use `include_port` to enable the network service identification: ```cpp @@ -147,11 +147,11 @@ The instance can be configured to include the [hardware identification](/specifi ```cpp // Include the port id feature #define PJON_INCLUDE_MAC - #include + #include // Device's MAC address uint8_t mac[6] = {0, 0, 0, 0, 0, 0}; - PJON bus(mac); + PJONSoftwareBitBang bus(mac); ``` Use `include_mac` to enable the network service identification by default: ```cpp diff --git a/documentation/data-reception.md b/documentation/data-reception.md index f9397c602b..81f0ace177 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -31,7 +31,7 @@ void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info Register the `receiver_function` as the receiver callback: ```cpp -PJON bus; +PJONSoftwareBitBang bus; bus.set_receiver(receiver_function); ``` diff --git a/documentation/io-setup.md b/documentation/io-setup.md index 38df4fbeb8..13db23c514 100644 --- a/documentation/io-setup.md +++ b/documentation/io-setup.md @@ -21,19 +21,19 @@ ## IO setup The physical layer configuration is handled by the [strategy](/src/strategies/README.md) entity, if you want to communicate bi-directionally on a single pin with [SoftwareBitBang](/src/strategies/SoftwareBitBang) or [AnalogSampling](/src/strategies/AnalogSampling) use: ```cpp - PJON bus; + PJONSoftwareBitBang bus; bus.strategy.set_pin(12); ``` With this setup it is possible to communicate in `PJON_HALF_DUPLEX` mode with up to 254 different devices on the same physical pin. If for some reason you need to keep separate the two lines, for example if using [OverSampling](/src/strategies/OverSampling) with separate radio transmitter and receiver modules, you can pass 2 separate pins: ```cpp - PJON bus; + PJONOverSampling bus; bus.strategy.set_pins(11, 12); ``` If you don't need bidirectional communication and you have only the transmitter on one side and the receiver on the other side you can use the `PJON_NOT_ASSIGNED` constant: ```cpp - PJON bus; + PJONOverSampling bus; // Operate in simplex mode bus.set_communication_mode(PJON_SIMPLEX); // Use only receiver pin diff --git a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino index 70ffd04862..f721404cf8 100644 --- a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino +++ b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino @@ -55,32 +55,16 @@ void setup() { void receiver_functionA(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { // Forward packet to RemoteWorker on bus B, preserving the original sender id - busB.send_from_id( - packet_info.tx.id, - packet_info.tx.bus_id, - DEVICE_ID, - PJONTools::localhost(), - (uint8_t *)payload, - length, - packet_info.header, - packet_info.id, - packet_info.port - ); -} + PJON_Packet_Info p = packet_info; + p.rx.id = DEVICE_ID; + busB.forward(p, (uint8_t *)payload, length); +}; void receiver_functionB(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { // All packets sent by the RemoteWorker is delivered to this device, when in the // single_initiate_direction listening mode. // Forward packet to specified target device on bus A - busA.send_packet_blocking( - packet_info.rx.id, - packet_info.rx.bus_id, - (uint8_t *)payload, - length, - packet_info.header, - packet_info.id, - packet_info.port - ); + busA.send_packet_blocking(packet_info, (uint8_t *)payload, length); } void loop() { diff --git a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino index d28f9b3cd0..dc6f556714 100644 --- a/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino +++ b/examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway/Gateway/Gateway.ino @@ -24,9 +24,7 @@ bool router = false; void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { const char *msg = (const char *)payload; // Forward to MQTT topic pjon/device45/output if from device 45 - mqtt.send_from_id(packet_info.tx.id, PJONTools::localhost(), - packet_info.rx.id, PJONTools::localhost(), - payload, length, packet_info.header, packet_info.id, packet_info.port); + mqtt.forward(packet_info, payload, length); cnt_to_mqtt++; }; diff --git a/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino b/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino index 713bcd0ca3..74725640d8 100644 --- a/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino +++ b/examples/ARDUINO/Local/ThroughSerial/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino @@ -10,50 +10,51 @@ #define PJON_PACKET_MAX_LENGTH 50 #define PJON_MAX_PACKETS 3 -//// Define one of these modes -//#define ETCP_SINGLE_DIRECTION -////#define ETCP_SINGLE_SOCKET_WITH_ACK +// Define one of these modes +// #define ETCP_SINGLE_DIRECTION +// #define ETCP_SINGLE_SOCKET_WITH_ACK +// #include #include +#include const uint8_t DEVICE_ID = 45; // SWBB Device ID for this device and the RemoteWorker -PJON busA(DEVICE_ID); -//PJON busB(1); +PJONSoftwareBitBang busA(DEVICE_ID); PJONThroughSerial busB(1); -//// Ethernet configuration for this device -//uint8_t gateway[] = { 192, 1, 1, 1 }; -//uint8_t subnet[] = { 255, 255, 255, 0 }; -//uint8_t mac[] = {0xDE, 0x5D, 0x4E, 0xEF, 0xAE, 0xED}; -//uint8_t ip[] = { 192, 1, 1, 144 }; +// PJONEthernetTCP busB(1); +// Ethernet configuration for this device +// uint8_t gateway[] = { 192, 1, 1, 1 }; +// uint8_t subnet[] = { 255, 255, 255, 0 }; +// uint8_t mac[] = {0xDE, 0x5D, 0x4E, 0xEF, 0xAE, 0xED}; +// uint8_t ip[] = { 192, 1, 1, 144 }; -//// Ethernet configuration for remote device -//const uint8_t remote_ip[] = { 192, 1, 1, 70 }; +// Ethernet configuration for remote device +// const uint8_t remote_ip[] = { 192, 1, 1, 70 }; void setup() { pinMode(13, OUTPUT); digitalWrite(13, LOW); // Initialize LED 13 to be off -// digitalWrite(13, HIGH); // Initialize LED 13 to be on - -// Serial.begin(115200); -// Serial.println("Welcome to Surrogate 1"); -// Ethernet.begin(mac, ip, gateway, gateway, subnet); + // digitalWrite(13, HIGH); // Initialize LED 13 to be on + // Serial.begin(115200); + // Serial.println("Welcome to Surrogate 1"); + // Ethernet.begin(mac, ip, gateway, gateway, subnet); Serial.begin(9600); busA.strategy.set_pin(7); busA.set_receiver(receiver_functionA); busA.begin(); -// busB.strategy.link.set_id(busB.device_id()); -// busB.strategy.link.add_node(DEVICE_ID, remote_ip); -// #ifdef ETCP_SINGLE_DIRECTION -// busB.strategy.link.single_initiate_direction(true); -// #elif ETCP_SINGLE_SOCKET_WITH_ACK -// busB.strategy.link.single_socket(true); -// #endif + // busB.strategy.link.set_id(busB.device_id());` + // busB.strategy.link.add_node(DEVICE_ID, remote_ip); + // #ifdef ETCP_SINGLE_DIRECTION + // busB.strategy.link.single_initiate_direction(true); + // #elif ETCP_SINGLE_SOCKET_WITH_ACK + // busB.strategy.link.single_socket(true); + // #endif` busB.strategy.set_serial(&Serial); busB.set_router(true); busB.set_receiver(receiver_functionB); @@ -62,17 +63,9 @@ void setup() { void receiver_functionA(uint8_t *payload, uint16_t length, const PJON_Packet_Info &packet_info) { // Forward packet to RemoteWorker on bus B, preserving the original sender id - busB.send_from_id( - packet_info.tx.id, - packet_info.tx.bus_id, - DEVICE_ID, - PJONTools::localhost(), - (uint8_t *)payload, - length, - packet_info.header, - packet_info.id, - packet_info.port - ); + PJON_Packet_Info p = packet_info; + p.rx.id = DEVICE_ID; + busB.forward(p, (uint8_t *)payload, length); digitalWrite(13, HIGH); } @@ -80,15 +73,7 @@ void receiver_functionB(uint8_t *payload, uint16_t length, const PJON_Packet_Inf // All packets sent by the RemoteWorker is delivered to this device, when in the // single_initiate_direction listening mode. // Forward packet to specified target device on bus A - busA.send_packet_blocking( - packet_info.rx.id, - packet_info.rx.bus_id, - (uint8_t *)payload, - length, - packet_info.header, - packet_info.id, - packet_info.port - ); + busA.send_packet_blocking(packet_info, payload, length); digitalWrite(13, LOW); } @@ -98,12 +83,12 @@ void loop() { busB.receive(1000); busA.update(); -// // Show the number of sockets created after startup -// // (Try disconnecting the Ethernet cable for a while to see it increase when reconnected.) -// static uint32_t last = millis(); -// if (millis() - last > 5000) { -// last = millis(); -// Serial.print(F("CONNECT COUNT: ")); -// Serial.println(busB.strategy.link.get_connection_count()); -// } + // // Show the number of sockets created after startup + // // (Try disconnecting the Ethernet cable for a while to see it increase when reconnected.) + // static uint32_t last = millis(); + // if (millis() - last > 5000) { + // last = millis(); + // Serial.print(F("CONNECT COUNT: ")); + // Serial.println(busB.strategy.link.get_connection_count()); + // } }; diff --git a/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp b/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp index cb00cdf27c..8905e58e19 100644 --- a/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/ThroughSerial/BlinkTest/Transmitter/Transmitter.cpp @@ -22,12 +22,9 @@ // Set the USB COM port used #define COM_PORT "COM9" -// Include only ThroughSerial - - -// Include PJON library +// Include PJON library with the ThroughSerial strategy #include - +// Instantiate PJON over ThroughSerial PJONThroughSerial bus(45); // Error handler called when something goes wrong diff --git a/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp index 9c77121938..126ae261b0 100644 --- a/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp +++ b/examples/WINX86/Local/ThroughSerial/BlinkWithResponse/Transmitter/Transmitter.cpp @@ -22,12 +22,9 @@ // Set the USB COM port used #define COM_PORT "COM9" -// Include only ThroughSerial - - -// Include PJON library +// Include PJON library with ThroughSerial #include - +// Instantiate PJON over ThroughSerial PJONThroughSerial bus(45); // The function called when data is received From 16ddb526a1c3afea513f6424d0a2b096e4c62429 Mon Sep 17 00:00:00 2001 From: Zbigniew Zasieczny Date: Thu, 15 Oct 2020 23:24:41 +0200 Subject: [PATCH 243/323] interface/linux: delayMicroseconds changed to use select to avoid CPU-bound load --- src/interfaces/LINUX/PJON_LINUX_Interface.h | 1 + src/interfaces/LINUX/PJON_LINUX_Interface.inl | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/interfaces/LINUX/PJON_LINUX_Interface.h b/src/interfaces/LINUX/PJON_LINUX_Interface.h index 3e41ecfb06..608e666f84 100644 --- a/src/interfaces/LINUX/PJON_LINUX_Interface.h +++ b/src/interfaces/LINUX/PJON_LINUX_Interface.h @@ -36,6 +36,7 @@ #include #include #include + #include #define OUTPUT 1 #define INPUT 0 diff --git a/src/interfaces/LINUX/PJON_LINUX_Interface.inl b/src/interfaces/LINUX/PJON_LINUX_Interface.inl index 7994b62dc4..bfd1449343 100644 --- a/src/interfaces/LINUX/PJON_LINUX_Interface.inl +++ b/src/interfaces/LINUX/PJON_LINUX_Interface.inl @@ -30,15 +30,17 @@ uint32_t millis() { }; void delayMicroseconds(uint32_t delay_value) { - auto begin_ts = std::chrono::high_resolution_clock::now(); - while(true) { - auto elapsed_usec = - std::chrono::duration_cast( - std::chrono::high_resolution_clock::now() - begin_ts - ).count(); - if(elapsed_usec >= delay_value) break; - std::this_thread::sleep_for(std::chrono::microseconds(50)); + struct timeval tv; + if (delay_value < 1000000){ + tv.tv_sec = 0; + tv.tv_usec = delay_value; } + else{ + tv.tv_sec = floor(delay_value / 1000000); + tv.tv_usec = delay_value - tv.tv_sec * 1000000; + } + + select(0, NULL, NULL, NULL, &tv); }; void delay(uint32_t delay_value_ms) { From 236120c4c8ec8549cd6a1263c65f65833467dcba Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Fri, 16 Oct 2020 12:46:31 +0200 Subject: [PATCH 244/323] LEDAR README minor fix --- devices/sensors/LEDAR/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/devices/sensors/LEDAR/README.md b/devices/sensors/LEDAR/README.md index 92f9bca418..04fc7bbec8 100644 --- a/devices/sensors/LEDAR/README.md +++ b/devices/sensors/LEDAR/README.md @@ -18,7 +18,7 @@ Many LEDARs can be connected to the same [SoftwareBitBang](/src/strategies/Softw Its detection method is based on two interesting characteristics of LEDs: - If hit by light, LEDs produce a tiny amount of electricity, thanks to the photo-electric effect -- LEDs used as detectors are generally more sensitive to the frequency they emit if used as emitters, making a couple of identical LEDs generally used for lighting, in two extremely efficient wireless transceivers that can be used for reflectometry or also for wireless communication using the [AnalogSampling](/src/strategies/AnalogSampling/README.md) strategy +- LEDs used as detectors are generally more sensitive to the frequency they emit if used as emitters, so a couple of identical LEDs generally used for lighting can be used successfully as wireless transceivers for reflectometry or optical wireless communication using the [AnalogSampling](/src/strategies/AnalogSampling/README.md) strategy Its sampling method is based on two different samples: - Background noise or ambient light sample `B` @@ -79,6 +79,6 @@ The case is made by two elements and it has been printed using a customized Prus Once crafted, ATtiny85 has to be flashed with the [LEDAR](software/LEDAR/LEDAR.ino) sketch using an ISP programmer, see [ATtiny85 interfacing](https://github.com/gioblu/PJON/wiki/ATtiny-interfacing) -LEDAR has been engineered with the strong feeling that, in the future, "smart houses" will not necessarily host a multitude of inefficient and convoluted embedded real-time operative systems, in whatever "thing", consuming a lot of power running Ethernet over WiFi and exposing vulnerabilities also out of the physical boundaries of houses. Otherwise, more probably, will host many dedicated microcontrollers connected to a wired, common, open-source, lightweight and less power consuming communication bus, unhackable without direct physical access to its wiring. +LEDAR has been engineered with the strong feeling that, in the future, "smart houses" will not necessarily host a multitude of inefficient embedded real-time operative systems in whatever "thing" while exposing vulnerabilities out of the physical boundaries of houses. Otherwise, more probably, will host many simple, less power-hungy microcontrollers, connected to a wired communication bus, unhackable without direct physical access to its wiring. LEDAR should be considered as a general "guideline" on how PJON compatible devices can be published and shared with other PJON users through the [devices](../../README.md) directory. Feel free to make a pull request proposing a new device you have engineered. From 2a3a1ca2fba5d687142be63f776cdcf68a23cb26 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 18 Oct 2020 11:10:12 +0200 Subject: [PATCH 245/323] new delayMicroseconds used instead of usleep in LINUX interface (https://github.com/gioblu/PJON/pull/368) --- src/interfaces/LINUX/PJON_LINUX_Interface.inl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/interfaces/LINUX/PJON_LINUX_Interface.inl b/src/interfaces/LINUX/PJON_LINUX_Interface.inl index b57629edf0..642d0d2d21 100644 --- a/src/interfaces/LINUX/PJON_LINUX_Interface.inl +++ b/src/interfaces/LINUX/PJON_LINUX_Interface.inl @@ -37,11 +37,11 @@ void delayMicroseconds(uint32_t delay_value) { tv.tv_sec = 0; tv.tv_usec = delay_value; } - else{ - tv.tv_sec = floor(delay_value / 1000000); + else{ + tv.tv_sec = floor(delay_value / 1000000); tv.tv_usec = delay_value - tv.tv_sec * 1000000; } - + select(0, NULL, NULL, NULL, &tv); }; @@ -92,7 +92,7 @@ int serialOpen(const char *device, const int baud) { r = ioctl(fd, TIOCMSET, &state); if(r) return -1; - usleep(10000); // Sleep for 10 milliseconds + delayMicroseconds(10000); // Sleep for 10 milliseconds return fd; }; From f4e492d19659abf8eb96efff69a3069aa3cb49ec Mon Sep 17 00:00:00 2001 From: Aaron N Date: Sun, 18 Oct 2020 23:43:17 +0100 Subject: [PATCH 246/323] Find correct MAC for ESPNOW Stop searching when usng nodeID of 255 and instead use the intended MAC recepient. --- src/strategies/ESPNOW/ESPNOW.h | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/strategies/ESPNOW/ESPNOW.h b/src/strategies/ESPNOW/ESPNOW.h index d5696c5560..09730f0f6a 100644 --- a/src/strategies/ESPNOW/ESPNOW.h +++ b/src/strategies/ESPNOW/ESPNOW.h @@ -61,9 +61,9 @@ class ESPNOW { return _espnow_initialised; }; - int16_t find_remote_node(uint8_t id) { + int16_t find_remote_node(uint8_t id, uint8_t* mac) { for(uint8_t i = 0; i < _remote_node_count; i++) - if(_remote_id[i] == id) + if((_remote_id[i] == id && id != 255) || memcmp(_remote_mac, mac, ESP_NOW_ETH_ALEN) == 0) return i; return -1; }; @@ -85,21 +85,14 @@ class ESPNOW { en.get_sender(sender_mac); // See if PJON id is already registered, add if not - int16_t pos = find_remote_node(sender_id); + int16_t pos = find_remote_node(sender_id, sender_mac); if(pos == -1) { ESP_LOGI("ESPNOW", "Autoregister new sender %d",sender_id); add_node(sender_id, sender_mac); } - else if(memcmp(_remote_mac[pos], sender_mac, ESP_NOW_ETH_ALEN) != 0) { + else if(memcmp(_remote_mac[pos], sender_mac, ESP_NOW_ETH_ALEN) == 0) { // == 0 is the same // Update mac of existing node - ESP_LOGI( - "ESPNOW", - "Update sender mac %d %d:%d:%d", - sender_id, - sender_mac[1], - sender_mac[2], - sender_mac[3] - ); + ESP_LOGI("ESPNOW","Update sender sender_id(%d) [%02X:%02X:%02X:%02X:%02X:%02X]", sender_id, sender_mac[0],sender_mac[1],sender_mac[2],sender_mac[3],sender_mac[4],sender_mac[5]); memcpy(_remote_mac[pos], sender_mac, ESP_NOW_ETH_ALEN); } } @@ -213,10 +206,12 @@ class ESPNOW { void send_frame(uint8_t *data, uint16_t length) { if(length > 0) { uint8_t id = data[0]; // Package always starts with a receiver id + PJON_Packet_Info packet_info; // use parser to get intended recipient MAC + PJONTools::parse_header(data, packet_info); if(id == 0) { // Broadcast, send to all receivers en.send_frame(data, length); } else { // To a specific receiver - int16_t pos = find_remote_node(id); + int16_t pos = find_remote_node(id, packet_info.rx.mac); if(pos != -1) en.send_frame(data, length, _remote_mac[pos]); else //Broadcast - any replies will get registered From 98836c502e7d81a83a142b030829823438fda10b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Oct 2020 02:26:25 +0200 Subject: [PATCH 247/323] @porkyneal added to contributors list (https://github.com/gioblu/PJON/pull/370) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f5c81bace4..7fc04e0eb9 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Telecomunicación - [Universidad de Cantabria](https://web.unican.es/) (ES) ### Contribute Feel free to send a pull request sharing something you have made that could help, if you want to support this project you can also try to solve an [issue](https://github.com/gioblu/PJON/issues). Thanks to support, expertise, kindness and talent of the following contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: -[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen), [Julio Aguirre](https://github.com/jcallano), [Cimex97](https://github.com/Cimex97) and [der-schne](https://github.com/der-schne). +[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen), [Julio Aguirre](https://github.com/jcallano), [Cimex97](https://github.com/Cimex97), [der-schne](https://github.com/der-schne) and [porkyneal](https://github.com/porkyneal). ### Compliant tools - [ModuleInterface](https://github.com/fredilarsen/ModuleInterface) - easy config and value sync between IoT modules by Fred Larsen From df4dfe4e955dec429d74a8115a7c65b4d66750fa Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Oct 2020 02:30:43 +0200 Subject: [PATCH 248/323] ESPNOW code-style minor fix (https://github.com/gioblu/PJON/pull/370) --- src/strategies/ESPNOW/ESPNOW.h | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/strategies/ESPNOW/ESPNOW.h b/src/strategies/ESPNOW/ESPNOW.h index 09730f0f6a..26ea5a51dc 100644 --- a/src/strategies/ESPNOW/ESPNOW.h +++ b/src/strategies/ESPNOW/ESPNOW.h @@ -63,8 +63,10 @@ class ESPNOW { int16_t find_remote_node(uint8_t id, uint8_t* mac) { for(uint8_t i = 0; i < _remote_node_count; i++) - if((_remote_id[i] == id && id != 255) || memcmp(_remote_mac, mac, ESP_NOW_ETH_ALEN) == 0) - return i; + if( + ((_remote_id[i] == id) && (id != 255)) || + (memcmp(_remote_mac, mac, ESP_NOW_ETH_ALEN) == 0) + ) return i; return -1; }; @@ -90,9 +92,19 @@ class ESPNOW { ESP_LOGI("ESPNOW", "Autoregister new sender %d",sender_id); add_node(sender_id, sender_mac); } - else if(memcmp(_remote_mac[pos], sender_mac, ESP_NOW_ETH_ALEN) == 0) { // == 0 is the same + else if(memcmp(_remote_mac[pos], sender_mac, ESP_NOW_ETH_ALEN) == 0) { // Update mac of existing node - ESP_LOGI("ESPNOW","Update sender sender_id(%d) [%02X:%02X:%02X:%02X:%02X:%02X]", sender_id, sender_mac[0],sender_mac[1],sender_mac[2],sender_mac[3],sender_mac[4],sender_mac[5]); + ESP_LOGI( + "ESPNOW", + "Update sender sender_id(%d) [%02X:%02X:%02X:%02X:%02X:%02X]", + sender_id, + sender_mac[0], + sender_mac[1], + sender_mac[2], + sender_mac[3], + sender_mac[4], + sender_mac[5] + ); memcpy(_remote_mac[pos], sender_mac, ESP_NOW_ETH_ALEN); } } From 9d458a11856b3c983fd4ae2b9a505c10441b2b41 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Oct 2020 02:33:49 +0200 Subject: [PATCH 249/323] ESPNOW use PJON_NOT_ASSIGNED instead of 255 (https://github.com/gioblu/PJON/pull/370) --- src/strategies/ESPNOW/ESPNOW.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/ESPNOW/ESPNOW.h b/src/strategies/ESPNOW/ESPNOW.h index 26ea5a51dc..432a1d4ec6 100644 --- a/src/strategies/ESPNOW/ESPNOW.h +++ b/src/strategies/ESPNOW/ESPNOW.h @@ -64,7 +64,7 @@ class ESPNOW { int16_t find_remote_node(uint8_t id, uint8_t* mac) { for(uint8_t i = 0; i < _remote_node_count; i++) if( - ((_remote_id[i] == id) && (id != 255)) || + ((_remote_id[i] == id) && (id != PJON_NOT_ASSIGNED)) || (memcmp(_remote_mac, mac, ESP_NOW_ETH_ALEN) == 0) ) return i; return -1; From e2db3c239160551236644a50eec90c38c1604bf2 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 25 Oct 2020 14:49:33 +0100 Subject: [PATCH 250/323] routing examples update --- .../Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino | 6 ++++-- .../routing/ARDUINO/Local/Tunneler/SwitchA/SwitchA.ino | 6 ++++-- .../routing/ARDUINO/Local/Tunneler/SwitchB/SwitchB.ino | 6 ++++-- .../VirtualBusRouter2/VirtualBusRouter2.ino | 4 +++- .../Network/LocalBusViaNATSwitch/NATSwitch/NATSwitch.ino | 7 ++++--- .../ARDUINO/Network/Router/DynamicRouter/DynamicRouter.ino | 1 + examples/routing/ARDUINO/Network/Router/Router/Router.ino | 1 + .../Network/Switch/BlinkingSwitch/BlinkingSwitch.ino | 1 + .../ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino | 2 +- examples/routing/ARDUINO/Network/Switch/Switch/Switch.ino | 1 + 10 files changed, 24 insertions(+), 11 deletions(-) diff --git a/examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino b/examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino index b0cfe6bbe4..2f61aadd4d 100644 --- a/examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino +++ b/examples/routing/ARDUINO/Local/Tunneler/BlinkingRGBSwitch/BlinkingRGBSwitch.ino @@ -1,12 +1,14 @@ /* Similar to the Switch but with a blinking RGB led indicating each packet that is forwarded with blue and green for each direction respectively, - plus errors in red. - + plus errors in red. + This demonstrates how the PJONInteractiveRouter class supports user hooks for error handling and to catch every packet being forwarded. */ #define PJON_MAX_PACKETS 3 #include +#include +#include // Ethernet configuration for this device, MAC must be unique! byte mac[] = {0xDE, 0x34, 0x4E, 0xEF, 0xFE, 0xE1}; diff --git a/examples/routing/ARDUINO/Local/Tunneler/SwitchA/SwitchA.ino b/examples/routing/ARDUINO/Local/Tunneler/SwitchA/SwitchA.ino index b2a620ee85..a46518956a 100644 --- a/examples/routing/ARDUINO/Local/Tunneler/SwitchA/SwitchA.ino +++ b/examples/routing/ARDUINO/Local/Tunneler/SwitchA/SwitchA.ino @@ -1,12 +1,14 @@ -/* Tunnel packets through another medium using one switch on each end. +/* Tunnel packets through another medium using one switch on each end. / For example, two SoftwareBitBang buses that are far from each other / can be joined transparently through a LAN/WAN using the DualUDP strategy -/ or the EthernetTCP strategy. +/ or the EthernetTCP strategy. / In this case, use a non-default UDP port to isolate the "tunnel" from / potential other DualUDP communication on the same network. */ #define PJON_MAX_PACKETS 3 #include +#include +#include // Ethernet configuration for this device, MAC must be unique! byte mac[] = {0xDE, 0x34, 0x4E, 0xEF, 0xFE, 0xE1}; diff --git a/examples/routing/ARDUINO/Local/Tunneler/SwitchB/SwitchB.ino b/examples/routing/ARDUINO/Local/Tunneler/SwitchB/SwitchB.ino index 8953959dd7..34960c685a 100644 --- a/examples/routing/ARDUINO/Local/Tunneler/SwitchB/SwitchB.ino +++ b/examples/routing/ARDUINO/Local/Tunneler/SwitchB/SwitchB.ino @@ -1,12 +1,14 @@ -/* Tunnel packets through another medium using one switch on each end. +/* Tunnel packets through another medium using one switch on each end. / For example, two SoftwareBitBang buses that are far from each other / can be joined transparently through a LAN/WAN using the DualUDP strategy -/ or the EthernetTCP strategy. +/ or the EthernetTCP strategy. / In this case, use a non-default UDP port to isolate the "tunnel" from / potential other DualUDP communication on the same network. */ #define PJON_MAX_PACKETS 3 #include +#include +#include // Ethernet configuration for this device, MAC must be unique! byte mac[] = {0xEE, 0x79, 0x4E, 0xEF, 0xFE, 0x6D}; diff --git a/examples/routing/ARDUINO/Local/VirtualBusRouter/VirtualBusRouter2/VirtualBusRouter2.ino b/examples/routing/ARDUINO/Local/VirtualBusRouter/VirtualBusRouter2/VirtualBusRouter2.ino index 80414477cb..b3115ab106 100644 --- a/examples/routing/ARDUINO/Local/VirtualBusRouter/VirtualBusRouter2/VirtualBusRouter2.ino +++ b/examples/routing/ARDUINO/Local/VirtualBusRouter/VirtualBusRouter2/VirtualBusRouter2.ino @@ -1,7 +1,9 @@ #include +#include +#include /* This sketch is routing between two local buses to form one larger local bus, - just like the VirtualBusRouter example, but it uses the class + just like the VirtualBusRouter example, but it uses the class PJONVirtualBusRouter2 which is specialized to using two buses to provide a simpler declaration. diff --git a/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NATSwitch/NATSwitch.ino b/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NATSwitch/NATSwitch.ino index 175b918862..9f61b10c58 100644 --- a/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NATSwitch/NATSwitch.ino +++ b/examples/routing/ARDUINO/Network/LocalBusViaNATSwitch/NATSwitch/NATSwitch.ino @@ -1,15 +1,16 @@ /* Route packets between a local bus and a network bus in both directions, using a switch that supports NAT (network address translation). - + The first bus is a local bus, but we still specify a bus id for it. - This will be the "public" bus id for the local bus, allowing it to + This will be the "public" bus id for the local bus, allowing it to be reached from the network bus through NAT (network address translation). __________ ________ __________ | LOCAL | Pin 7 | NAT | Pin 12 | NETWORK | | DEVICE |_______________| SWITCH |_______________| DEVICE | |__________| Local bus |________| Bus 0.0.0.2 |__________| */ -#include +#include +#include PJONSwitch2 router; diff --git a/examples/routing/ARDUINO/Network/Router/DynamicRouter/DynamicRouter.ino b/examples/routing/ARDUINO/Network/Router/DynamicRouter/DynamicRouter.ino index 5ad2eff384..788db715cc 100644 --- a/examples/routing/ARDUINO/Network/Router/DynamicRouter/DynamicRouter.ino +++ b/examples/routing/ARDUINO/Network/Router/DynamicRouter/DynamicRouter.ino @@ -1,4 +1,5 @@ #include +#include /* Route packets between a collection of buses with the same or if required different strategies or media. Packets are routed transparently using a diff --git a/examples/routing/ARDUINO/Network/Router/Router/Router.ino b/examples/routing/ARDUINO/Network/Router/Router/Router.ino index 4e77a5496c..f54c9026ba 100644 --- a/examples/routing/ARDUINO/Network/Router/Router/Router.ino +++ b/examples/routing/ARDUINO/Network/Router/Router/Router.ino @@ -1,4 +1,5 @@ #include +#include /* Route packets between a collection of buses with the same or if required different strategies or media. diff --git a/examples/routing/ARDUINO/Network/Switch/BlinkingSwitch/BlinkingSwitch.ino b/examples/routing/ARDUINO/Network/Switch/BlinkingSwitch/BlinkingSwitch.ino index 546ee4680e..27f9faccc3 100644 --- a/examples/routing/ARDUINO/Network/Switch/BlinkingSwitch/BlinkingSwitch.ino +++ b/examples/routing/ARDUINO/Network/Switch/BlinkingSwitch/BlinkingSwitch.ino @@ -10,6 +10,7 @@ */ #include +#include PJONInteractiveRouter2 router; diff --git a/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino b/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino index f8699cfb87..36592d9aa8 100644 --- a/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino +++ b/examples/routing/ARDUINO/Network/Switch/SimpleSwitch/SimpleSwitch.ino @@ -1,5 +1,5 @@ -#include #include +#include /* Route packets between a collection of buses with the same or different strategies or media. diff --git a/examples/routing/ARDUINO/Network/Switch/Switch/Switch.ino b/examples/routing/ARDUINO/Network/Switch/Switch/Switch.ino index 7983d87c1d..8a06cb52d1 100644 --- a/examples/routing/ARDUINO/Network/Switch/Switch/Switch.ino +++ b/examples/routing/ARDUINO/Network/Switch/Switch/Switch.ino @@ -1,4 +1,5 @@ #include +#include /* Route packets between a collection of buses with the same or different strategies or media. From 023ee5e353629c139b1b21629c1cea2490c1125f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Oct 2020 16:32:07 +0100 Subject: [PATCH 251/323] ESPNOW examples update, missing PJON_INCLUDE_MAC error added --- .../ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp | 3 ++- .../ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp | 3 +++ examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino | 3 +++ examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino | 2 ++ examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp | 3 +++ examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp | 3 +++ src/PJONESPNOW.h | 5 +++++ 7 files changed, 21 insertions(+), 1 deletion(-) diff --git a/examples/ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp b/examples/ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp index 1c144012ab..4af2455522 100644 --- a/examples/ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp +++ b/examples/ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp @@ -13,10 +13,11 @@ static wifi_country_t wifi_country = { #include "Arduino.h" +// Include PJON's MAC feature (required for ESPNOW operation) +#define PJON_INCLUDE_MAC #include - PJONESPNOW bus(44); uint32_t cnt = 0; diff --git a/examples/ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp b/examples/ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp index c8e30f06b7..fe44de9bdc 100644 --- a/examples/ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp +++ b/examples/ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp @@ -13,6 +13,9 @@ static wifi_country_t wifi_country = { #include "Arduino.h" +// Include PJON's MAC feature (required for ESPNOW operation) +#define PJON_INCLUDE_MAC + #include PJONESPNOW bus(45); diff --git a/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino b/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino index 753a7ca49a..6ba4eee4ea 100644 --- a/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino +++ b/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino @@ -13,6 +13,9 @@ static wifi_country_t wifi_country = { policy: WIFI_COUNTRY_POLICY_MANUAL }; +// Include PJON's MAC feature (required for ESPNOW operation) +#define PJON_INCLUDE_MAC + #include PJONESPNOW bus(44); diff --git a/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino b/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino index 3f91cce4c9..b3cf6a732a 100644 --- a/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino +++ b/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino @@ -14,6 +14,8 @@ static wifi_country_t wifi_country = { policy: WIFI_COUNTRY_POLICY_MANUAL }; +// Include PJON's MAC feature (required for ESPNOW operation) +#define PJON_INCLUDE_MAC #include diff --git a/examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp b/examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp index c6f020b7a8..e3d31d8552 100644 --- a/examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp +++ b/examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp @@ -15,6 +15,9 @@ static wifi_country_t wifi_country = { policy : WIFI_COUNTRY_POLICY_MANUAL }; +// Include PJON's MAC feature (required for ESPNOW operation) +#define PJON_INCLUDE_MAC + #include PJONESPNOW bus(44); diff --git a/examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp b/examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp index 4f253bc920..8e8750c4ec 100644 --- a/examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp +++ b/examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp @@ -14,6 +14,9 @@ static wifi_country_t wifi_country = { policy : WIFI_COUNTRY_POLICY_MANUAL }; +// Include PJON's MAC feature (required for ESPNOW operation) +#define PJON_INCLUDE_MAC + #include PJONESPNOW bus(45); diff --git a/src/PJONESPNOW.h b/src/PJONESPNOW.h index 5df99e8db4..a154ebf4f1 100644 --- a/src/PJONESPNOW.h +++ b/src/PJONESPNOW.h @@ -1,7 +1,12 @@ #pragma once +#ifndef PJON_INCLUDE_MAC + #error ESPNOW strategy requires the MAC feature, define PJON_INCLUDE_MAC. +#endif + #include "PJON.h" + #include "strategies/ESPNOW/ESPNOW.h" #define PJONESPNOW PJON From 636ffed945a39c8d6c6e5409ebcaf0071c50ccf5 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Oct 2020 18:21:39 +0100 Subject: [PATCH 252/323] PJONESPNOW.h defines PJON_INCLUDE_MAC (PJON's MAC is used in ESPNOW) --- .../ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp | 3 --- .../ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp | 3 --- examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino | 3 --- examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino | 3 --- examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp | 3 --- examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp | 3 --- src/PJONESPNOW.h | 5 ++++- 7 files changed, 4 insertions(+), 19 deletions(-) diff --git a/examples/ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp b/examples/ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp index 4af2455522..e239ced267 100644 --- a/examples/ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp +++ b/examples/ESP32/ESPNOW/PingPong-esp-idf/Receiver/main/main.cpp @@ -13,9 +13,6 @@ static wifi_country_t wifi_country = { #include "Arduino.h" -// Include PJON's MAC feature (required for ESPNOW operation) -#define PJON_INCLUDE_MAC - #include PJONESPNOW bus(44); diff --git a/examples/ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp b/examples/ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp index fe44de9bdc..c8e30f06b7 100644 --- a/examples/ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp +++ b/examples/ESP32/ESPNOW/PingPong-esp-idf/Transmitter/main/main.cpp @@ -13,9 +13,6 @@ static wifi_country_t wifi_country = { #include "Arduino.h" -// Include PJON's MAC feature (required for ESPNOW operation) -#define PJON_INCLUDE_MAC - #include PJONESPNOW bus(45); diff --git a/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino b/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino index 6ba4eee4ea..753a7ca49a 100644 --- a/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino +++ b/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device1/Device1.ino @@ -13,9 +13,6 @@ static wifi_country_t wifi_country = { policy: WIFI_COUNTRY_POLICY_MANUAL }; -// Include PJON's MAC feature (required for ESPNOW operation) -#define PJON_INCLUDE_MAC - #include PJONESPNOW bus(44); diff --git a/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino b/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino index b3cf6a732a..8c1e578e40 100644 --- a/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino +++ b/examples/ESP32/ESPNOW/PingPongArduinoIDE/Device2/Device2.ino @@ -14,9 +14,6 @@ static wifi_country_t wifi_country = { policy: WIFI_COUNTRY_POLICY_MANUAL }; -// Include PJON's MAC feature (required for ESPNOW operation) -#define PJON_INCLUDE_MAC - #include PJONESPNOW bus(45); diff --git a/examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp b/examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp index e3d31d8552..c6f020b7a8 100644 --- a/examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp +++ b/examples/ESP32/ESPNOW/PlatformIO/Device1/src/main.cpp @@ -15,9 +15,6 @@ static wifi_country_t wifi_country = { policy : WIFI_COUNTRY_POLICY_MANUAL }; -// Include PJON's MAC feature (required for ESPNOW operation) -#define PJON_INCLUDE_MAC - #include PJONESPNOW bus(44); diff --git a/examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp b/examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp index 8e8750c4ec..4f253bc920 100644 --- a/examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp +++ b/examples/ESP32/ESPNOW/PlatformIO/Device2/src/main.cpp @@ -14,9 +14,6 @@ static wifi_country_t wifi_country = { policy : WIFI_COUNTRY_POLICY_MANUAL }; -// Include PJON's MAC feature (required for ESPNOW operation) -#define PJON_INCLUDE_MAC - #include PJONESPNOW bus(45); diff --git a/src/PJONESPNOW.h b/src/PJONESPNOW.h index a154ebf4f1..44ac766b26 100644 --- a/src/PJONESPNOW.h +++ b/src/PJONESPNOW.h @@ -1,8 +1,11 @@ #pragma once +/* ESPNOW strategy actively uses the PJON's MAC address feature for this reason + it must be included. */ + #ifndef PJON_INCLUDE_MAC - #error ESPNOW strategy requires the MAC feature, define PJON_INCLUDE_MAC. + #define PJON_INCLUDE_MAC #endif #include "PJON.h" From e7eb73a4d150e1a0ab02e0207a4356cc7e919736 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 29 Oct 2020 19:30:31 +0100 Subject: [PATCH 253/323] 12.1 -> 13.0 in README and comments --- README.md | 2 +- src/PJON.h | 2 +- src/PJONDefines.h | 2 +- src/PJONDynamicRouter.h | 2 +- src/PJONInteractiveRouter.h | 2 +- src/PJONLocal.h | 2 +- src/PJONRouter.h | 2 +- src/PJONSimpleSwitch.h | 2 +- src/PJONSwitch.h | 2 +- src/PJONVirtualBusRouter.h | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 7fc04e0eb9..9f5eabd0a8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![PJON](http://www.gioblu.com/PJON/PJON-github-header-tiny.png) -## PJON 12.1 +## PJON 13.0 PJON® (Padded Jittering Operative Network) is an arduino-compatible, multi-master, multi-media network protocol. It proposes a new Open Standard, it is designed as a framework and implements a totally software-defined network protocol stack that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media and protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). [![Get PJON bus id](https://img.shields.io/badge/get-PJON%20bus%20id-lightgrey.svg)](http://www.pjon.org/get-bus-id.php) diff --git a/src/PJON.h b/src/PJON.h index 01d6121062..d5165e65af 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -1,7 +1,7 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 12.1 + |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ diff --git a/src/PJONDefines.h b/src/PJONDefines.h index abee7210a6..0447516192 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -1,7 +1,7 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 12.1 + |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ diff --git a/src/PJONDynamicRouter.h b/src/PJONDynamicRouter.h index c2d5c97017..f91fe83763 100644 --- a/src/PJONDynamicRouter.h +++ b/src/PJONDynamicRouter.h @@ -1,7 +1,7 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 12.1 + |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ diff --git a/src/PJONInteractiveRouter.h b/src/PJONInteractiveRouter.h index 7810cc5efb..d5743b1520 100644 --- a/src/PJONInteractiveRouter.h +++ b/src/PJONInteractiveRouter.h @@ -1,7 +1,7 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 12.1 + |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ diff --git a/src/PJONLocal.h b/src/PJONLocal.h index c79a752cdb..af7bfade97 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -1,7 +1,7 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 12.1 + |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ diff --git a/src/PJONRouter.h b/src/PJONRouter.h index ed45e6a819..b278681ec7 100644 --- a/src/PJONRouter.h +++ b/src/PJONRouter.h @@ -1,7 +1,7 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 12.1 + |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ diff --git a/src/PJONSimpleSwitch.h b/src/PJONSimpleSwitch.h index 06fc598b62..1c36c27a0f 100644 --- a/src/PJONSimpleSwitch.h +++ b/src/PJONSimpleSwitch.h @@ -1,7 +1,7 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 12.1 + |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ diff --git a/src/PJONSwitch.h b/src/PJONSwitch.h index d098843dee..038d724b78 100644 --- a/src/PJONSwitch.h +++ b/src/PJONSwitch.h @@ -1,7 +1,7 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 12.1 + |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ diff --git a/src/PJONVirtualBusRouter.h b/src/PJONVirtualBusRouter.h index 7afa6e6909..4e90a86032 100644 --- a/src/PJONVirtualBusRouter.h +++ b/src/PJONVirtualBusRouter.h @@ -1,7 +1,7 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 12.1 + |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ From b764adb5b41e062128d8169f51d48dc3b6b412e6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 29 Oct 2020 19:32:58 +0100 Subject: [PATCH 254/323] zephyr added to library.json frameworks --- library.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library.json b/library.json index e6791d69aa..a65238ec1e 100644 --- a/library.json +++ b/library.json @@ -26,7 +26,8 @@ ], "frameworks": [ "arduino", - "wiringpi" + "wiringpi", + "zephyr" ], "platforms": [ "atmelavr", From 57dd9788ab2c14a21db18ffaa89f9f7f6661af15 Mon Sep 17 00:00:00 2001 From: Tristan Date: Thu, 29 Oct 2020 18:35:51 +0000 Subject: [PATCH 255/323] Fix transposed digits --- src/strategies/MQTTTranslate/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/MQTTTranslate/README.md b/src/strategies/MQTTTranslate/README.md index 3fe3cdb6e7..85b0398630 100644 --- a/src/strategies/MQTTTranslate/README.md +++ b/src/strategies/MQTTTranslate/README.md @@ -10,7 +10,7 @@ MQTTTranslate uses the [ReconnectingMqttClient](https://github.com/fredilarsen/R 2. `MQTTT_MODE_BUS_JSON` mode sends JSON packets with to, from and data, delivered to a topic like `pjon/device45` (where `45` is a receiver device id). Each device subscribes to a topic with its own name and receives packets like `{to:45,from:44,data:"message text sent from device 44 to device 45"}`. -3. `MQTTT_MODE_MIRROR_TRANSLATE` mode does not not use JSON encapsulation of values, and publishes to its own topic, not the receiver's. It publishes to an "output" folder and subscribes to an "input" folder. An outgoing packet with payload `P=44.1,T=22.0` results in the topics `pjon/device44/output/temperature`, with a value `44.1` and `pjon/device44/output/pressure`, with a value `22.0`. Likewise, when receiving an update of `pjon/device44/input/setpoint`, with a value `45` results in a packet with payload `S=45`. This mode supports a translation table to allow short names to be used in packets while topic names are longer. For example `T` translated in `temperature`. If no translation table is populated, the same names will be used in the packets and the topics. The directory [examples/ESP8266/Local/MQTTTranslate/EnvironmentController](../../../examples/ESP8266/Local/MQTTTranslate/EnvironmentController) contains the ESP8266 example, to build it, just use the Arduino IDE. +3. `MQTTT_MODE_MIRROR_TRANSLATE` mode does not not use JSON encapsulation of values, and publishes to its own topic, not the receiver's. It publishes to an "output" folder and subscribes to an "input" folder. An outgoing packet with payload `P=44.1,T=22.0` results in the topics `pjon/device44/output/temperature`, with a value `22.0` and `pjon/device44/output/pressure`, with a value `44.1`. Likewise, when receiving an update of `pjon/device44/input/setpoint`, with a value `45` results in a packet with payload `S=45`. This mode supports a translation table to allow short names to be used in packets while topic names are longer. For example `T` translated in `temperature`. If no translation table is populated, the same names will be used in the packets and the topics. The directory [examples/ESP8266/Local/MQTTTranslate/EnvironmentController](../../../examples/ESP8266/Local/MQTTTranslate/EnvironmentController) contains the ESP8266 example, to build it, just use the Arduino IDE. 4. `MQTTT_MODE_MIRROR_DIRECT` mode works like `MQTTT_MODE_MIRROR_TRANSLATE`, but just passes the payload on without any translation, leaving the formatting to the user. It does not split packets into separate topics but transfers the packets as-is to one output topic and from one input topic `pjon/device44/output`, `pjon/device44/input`. The user sketch will have control of the format used, which can be plain text like `P=44.1,T=22.0` or a JSON text. The directory [examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway](../../../examples/ARDUINO/Local/MQTTTranslate/SWBB-MQTT-Gateway) contains the Arduino SWBB-MQTT-Gateway example, that showcases bidirectional, transparent data transmission between an MQTT client and a [SoftwareBitBang](../SoftwareBitBang/README.md) bus. To build it, just use the Arduino IDE. From 4e10062f39562234e10c9e659156b667a7a58840 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Nov 2020 15:03:20 +0100 Subject: [PATCH 256/323] ThroughSerial README fixed broken BlinkTest example link --- src/strategies/ThroughSerial/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index eea3e5fd54..074321d605 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -56,7 +56,7 @@ bus.strategy.set_RS485_rxe_pin(11); // Set RS485 transmission enable pin bus.strategy.set_RS485_txe_pin(12); ``` -See the [Blink](../../../examples/ARDUINO/Local/ThroughSerial/Blink) and [BlinkWithResponse](https://github.com/gioblu/PJON/tree/master/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse) examples, if you need to interface devices using RS485 see the [RS485-Blink](../../../examples/ARDUINO/Local/ThroughSerial/RS485-Blink) example. HC-12 wireless module supports the synchronous acknowledgement, see [HC-12-Blink](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-Blink), [HC-12-SendAndReceive](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive) and [HC-12-LocalChat](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat) examples. +See the [BlinkTest](../../../examples/ARDUINO/Local/ThroughSerial/BlinkTest) and [BlinkWithResponse](https://github.com/gioblu/PJON/tree/master/examples/ARDUINO/Local/ThroughSerial/BlinkWithResponse) examples, if you need to interface devices using RS485 see the [RS485-Blink](../../../examples/ARDUINO/Local/ThroughSerial/RS485-Blink) example. HC-12 wireless module supports the synchronous acknowledgement, see [HC-12-Blink](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-Blink), [HC-12-SendAndReceive](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-SendAndReceive) and [HC-12-LocalChat](../../../examples/ARDUINO/Local/ThroughSerial/HC-12-LocalChat) examples. All the other necessary information is present in the general [Documentation](/documentation). From c6f9cf93f960660260d2ec8f01e29846ced59c4c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Nov 2020 22:03:29 +0100 Subject: [PATCH 257/323] version update --- library.json | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index a65238ec1e..d0c2608610 100644 --- a/library.json +++ b/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/gioblu/PJON.git" }, - "version": "12.1", + "version": "13.0", "examples": [ "examples/*/*/*/*/*.ino", "examples/*/*/*/*/*.h", diff --git a/library.properties b/library.properties index f9763725ec..8da4f4de7d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=PJON -version=12.1 +version=13.0 author=Giovanni Blu Mitolo maintainer=Giovanni Blu Mitolo sentence=PJON is an open-source, multi-master, multi-media bus network protocol From c3add3b91388d0cf64279fdbfe733981eb93df40 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Sat, 14 Nov 2020 13:47:37 +0100 Subject: [PATCH 258/323] PJDL vs. 1-Wire added to SoftwareBitBang README --- src/strategies/SoftwareBitBang/README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index ca387512b7..0979285ed7 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -51,7 +51,14 @@ Communication over a single wire enables quick and creative experimentation. The ![PJDL communication over 2000m twisted pair](images/PJDL-2000m-mode4-twistedpair-8.2k-pulldown-60-series.png) -The picture above shows a [PJDL](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) frame transmitted over a 800m twisted pair using mode `4` (test done by [Jack Anderson](https://github.com/jdaandersj)). Although bits are substantially deformed the exchange occurs nominally and performance is not affected. +The picture above shows a [PJDL](/src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) frame transmitted over a 800m twisted pair using mode `4`. Although bits are substantially deformed the exchange occurs nominally and performance is not affected. This experiment was done and published by [Jack Anderson](https://github.com/jdaandersj) in [LANC Video Camera Control](http://jda.tel/pdf/lanc_video_camera_control.pdf) - Department of Computer Science [Loughborough University](https://www.lboro.ac.uk/departments/compsci/) (UK). + +### PJDL vs. 1-Wire + +| Protocol | Communication speed | Range | Communication mode | +| -------- | ------------------- | --------- | ---------------------- | +| PJDL | 1.97-3.34kB/s | 800-2000m | Simplex or half-duplex | +| 1-Wire | 2.03kB/s | 300m | Half-duplex | ### Configuration Before including the library it is possible to configure `SoftwareBitBang` using predefined constants: From 9df01506554ccb78d958e3f10b5e39aad2029205 Mon Sep 17 00:00:00 2001 From: Fred Larsen Date: Sun, 13 Dec 2020 22:54:58 +0100 Subject: [PATCH 259/323] Updated the MQTTTranslate strategy to use PJON_Packet_Info --- src/strategies/MQTTTranslate/MQTTTranslate.h | 27 ++++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/strategies/MQTTTranslate/MQTTTranslate.h b/src/strategies/MQTTTranslate/MQTTTranslate.h index f82fb788fa..58f2516f1e 100644 --- a/src/strategies/MQTTTranslate/MQTTTranslate.h +++ b/src/strategies/MQTTTranslate/MQTTTranslate.h @@ -126,7 +126,7 @@ class MQTTTranslate { bool last_send_success = false; uint16_t incoming_packet_size = 0; -// TODO: Eliminate extra buffer -- is the on in the MqttClient not enough? +// TODO: Eliminate extra buffer -- is the one in the MqttClient not enough? uint8_t packet_buffer[MQTTT_BUFFER_SIZE]; PJON_Packet_Info _packet_info; // Used for parsing incoming and outgoing packets @@ -160,6 +160,17 @@ class MQTTTranslate { } #endif + static PJON_Packet_Info fill_info(uint8_t sender_id, const uint8_t sender_bus_id[4], + uint8_t receiver_id, const uint8_t receiver_bus_id[4], uint8_t header) { + PJON_Packet_Info info; + info.tx.id = sender_id; + PJONTools::copy_id(info.tx.bus_id, sender_bus_id, 4); + info.rx.id = receiver_id; + PJONTools::copy_id(info.rx.bus_id, receiver_bus_id, 4); + info.header = header; + return info; + } + static void static_receiver(const char *topic, const uint8_t *payload, uint16_t len, void *callback_object) { if (callback_object) ((MQTTTranslate*)callback_object)->receiver(topic, payload, len); } @@ -212,8 +223,8 @@ class MQTTTranslate { // Package the data message into a PJON packet uint8_t h = header; if (sender_id != 0) header |= PJON_TX_INFO_BIT; - incoming_packet_size = PJONTools::compose_packet(sender_id, bus_id, receiver_id, - bus_id, packet_buffer, payload, len, h); + PJON_Packet_Info info = fill_info(sender_id, bus_id, receiver_id, bus_id, h); + incoming_packet_size = PJONTools::compose_packet(info, packet_buffer, payload, len); #endif #if (MQTTT_MODE == MQTTT_MODE_MIRROR_TRANSLATE || MQTTT_MODE == MQTTT_MODE_MIRROR_DIRECT) uint8_t receiver_id = my_id; @@ -246,16 +257,16 @@ class MQTTTranslate { value[l] = 0; // Null terminate String s = key; s += "="; s += value; // Package the key=value into a PJON packet - incoming_packet_size = PJONTools::compose_packet(receiver_id, bus_id, receiver_id, - bus_id, packet_buffer, s.c_str(), s.length()+1, header); + PJON_Packet_Info info = fill_info(receiver_id, bus_id, receiver_id, bus_id, header); + incoming_packet_size = PJONTools::compose_packet(info, packet_buffer, s.c_str(), s.length()+1); } } return; #endif #if (MQTTT_MODE == MQTTT_MODE_MIRROR_DIRECT) // Package the payload as it is, into a PJON packet - incoming_packet_size = PJONTools::compose_packet(receiver_id, bus_id, receiver_id, - bus_id, packet_buffer, payload, len, header); + PJON_Packet_Info info = fill_info(receiver_id, bus_id, receiver_id, bus_id, header); + incoming_packet_size = PJONTools::compose_packet(info, packet_buffer, payload, len); #endif } @@ -454,6 +465,7 @@ class MQTTTranslate { #if (MQTTT_MODE == MQTTT_MODE_BUS_JSON) // Must assume that payload is text, unless UUencoding/base64encoding // {"to": to_id, "from": from id, "data": "payload"} + uint8_t payload_len = length - overhead; p = (char *) packet_buffer; if (6+3+8+3+9+payload_len+2 >= MQTTT_BUFFER_SIZE) return; strcpy(p, "{\"to\":"); p += 6; @@ -461,7 +473,6 @@ class MQTTTranslate { strcpy(p, ",\"from\":"); p+= 8; p += mqttclient.uint8toa(_packet_info.tx.id, p); strcpy(p, ",\"data\":\""); p+= 9; - uint8_t payload_len = length - overhead; strncpy(p, (const char*)&data[overhead - crc_size], payload_len); p[payload_len] = 0; p += strlen(p); strcpy(p, "\"}"); p += 2; From 71353ef7cd074ae4b36b7815f2b7bd02955395ef Mon Sep 17 00:00:00 2001 From: Fred Larsen Date: Thu, 17 Dec 2020 18:51:56 +0100 Subject: [PATCH 260/323] Limited scope of some Windows-specific defines for LocalFile strategy Could casue conflicts in other headers included later --- src/strategies/LocalFile/FileLockFunctions.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/strategies/LocalFile/FileLockFunctions.h b/src/strategies/LocalFile/FileLockFunctions.h index ded81abf1b..c3791a9e43 100644 --- a/src/strategies/LocalFile/FileLockFunctions.h +++ b/src/strategies/LocalFile/FileLockFunctions.h @@ -233,5 +233,12 @@ int LockFileSection(const int iFileNo, // the fileno #undef W_OK #undef R_OK #undef X_OK +#undef access +#undef lseek +#undef locking +#undef open +#undef write +#undef read +#undef close #endif From c4d4a7fbcd2d3385042060ac483972327eb262b0 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Sat, 2 Jan 2021 17:49:02 +0100 Subject: [PATCH 261/323] added links of new publications --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f5eabd0a8..cf8fc7f051 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,9 @@ PJON is used in thousands of devices and its community has spread worldwide beca - Error handling ### Publications -- [PJON protocol handbook](https://www.pjon-technologies.com/collections/frontpage/products/pjon-protocol-hand-book) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) +- [PJON protocol handbook 13.0](https://www.pjon-technologies.com/collections/frontpage/products/the-pjon-protocol-handbook-v13) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) +- [PJON 13.0 big box](https://www.pjon-technologies.com/collections/frontpage/products/pjon-13-0-big-box) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) +- [PJON protocol handbook 12.0](https://www.pjon-technologies.com/collections/frontpage/products/pjon-protocol-hand-book) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) - [PJON 12.0 big box](https://www.pjon-technologies.com/collections/frontpage/products/pjon-protocol-12-0-big-box) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) ### Academic studies From 9813c7dac18d20c242e65f34f207e2da361f4632 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Jan 2021 15:15:21 +0100 Subject: [PATCH 262/323] copyright year update --- LICENSE.md | 2 +- .../obsolete/PJON-dynamic-addressing-specification-v0.1.md | 2 +- .../obsolete/PJON-protocol-acknowledge-specification-v0.1.md | 2 +- specification/obsolete/PJON-protocol-specification-v0.1.md | 2 +- specification/obsolete/PJON-protocol-specification-v0.2.md | 2 +- specification/obsolete/PJON-protocol-specification-v0.3.md | 2 +- specification/obsolete/PJON-protocol-specification-v1.0.md | 2 +- specification/obsolete/PJON-protocol-specification-v1.1.md | 2 +- src/PJON.h | 4 ++-- src/PJONDefines.h | 4 ++-- src/PJONDynamicRouter.h | 4 ++-- src/PJONInteractiveRouter.h | 4 ++-- src/PJONLocal.h | 4 ++-- src/PJONRouter.h | 4 ++-- src/PJONSimpleSwitch.h | 4 ++-- src/PJONSwitch.h | 4 ++-- src/PJONVirtualBusRouter.h | 4 ++-- src/strategies/AnalogSampling/AnalogSampling.h | 2 +- src/strategies/Any/Any.h | 2 +- src/strategies/Any/StrategyLink.h | 2 +- src/strategies/Any/StrategyLinkBase.h | 2 +- .../specification/obsolete/PJDLR-specification-v1.0.md | 2 +- .../specification/obsolete/PJDLR-specification-v1.1.md | 2 +- src/strategies/SoftwareBitBang/SoftwareBitBang.h | 2 +- src/strategies/SoftwareBitBang/Timing.h | 2 +- .../specification/obsolete/PJDL-specification-v1.0.md | 2 +- .../specification/obsolete/PJDL-specification-v1.1.md | 2 +- .../obsolete/padded-jittering-protocol-specification-v0.1.md | 2 +- 28 files changed, 37 insertions(+), 37 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 7c67cd6df8..ecdf65d4f6 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ All the software included in this project is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. All specifications, all related software implementations and documentation released as a part of this repository are and will always remain free for personal, educational, experimental and commercial purposes. -Giovanni Blu Mitolo (gioscarab@gmail.com) Copyright 2010-2020 +Giovanni Blu Mitolo (gioscarab@gmail.com) Copyright 2010-2021 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at diff --git a/specification/obsolete/PJON-dynamic-addressing-specification-v0.1.md b/specification/obsolete/PJON-dynamic-addressing-specification-v0.1.md index 201985edc1..92173dbd26 100644 --- a/specification/obsolete/PJON-dynamic-addressing-specification-v0.1.md +++ b/specification/obsolete/PJON-dynamic-addressing-specification-v0.1.md @@ -4,7 +4,7 @@ Milan, Italy - 02/10/2016 The PJON® dynamic addressing specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2020 All rights reserved +Copyright 2010-2021 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 5.2 and following diff --git a/specification/obsolete/PJON-protocol-acknowledge-specification-v0.1.md b/specification/obsolete/PJON-protocol-acknowledge-specification-v0.1.md index 614851a70b..6b212b7461 100644 --- a/specification/obsolete/PJON-protocol-acknowledge-specification-v0.1.md +++ b/specification/obsolete/PJON-protocol-acknowledge-specification-v0.1.md @@ -4,7 +4,7 @@ Milan, Italy - 17/10/2016 The PJON® protocol acknowledge specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2020 All rights reserved +Copyright 2010-2021 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 6.0 and following diff --git a/specification/obsolete/PJON-protocol-specification-v0.1.md b/specification/obsolete/PJON-protocol-specification-v0.1.md index dfe66d6db0..778bd57b76 100644 --- a/specification/obsolete/PJON-protocol-specification-v0.1.md +++ b/specification/obsolete/PJON-protocol-specification-v0.1.md @@ -3,7 +3,7 @@ /* Milan, Italy - 10/04/2010 The PJON® protocol specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2020 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved Related work: https://github.com/gioblu/PJON Compliant implementation versions: PJON 1.0-3.0-beta diff --git a/specification/obsolete/PJON-protocol-specification-v0.2.md b/specification/obsolete/PJON-protocol-specification-v0.2.md index b97e42ea8a..03e45e0756 100644 --- a/specification/obsolete/PJON-protocol-specification-v0.2.md +++ b/specification/obsolete/PJON-protocol-specification-v0.2.md @@ -3,7 +3,7 @@ /* Milan, Italy - 19/08/2015 The PJON® protocol specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2020 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 3.0-beta-3.0 diff --git a/specification/obsolete/PJON-protocol-specification-v0.3.md b/specification/obsolete/PJON-protocol-specification-v0.3.md index 44bb8e4a2b..6ee3c91ab1 100644 --- a/specification/obsolete/PJON-protocol-specification-v0.3.md +++ b/specification/obsolete/PJON-protocol-specification-v0.3.md @@ -3,7 +3,7 @@ /* Milan, Italy - 04/09/2016 The PJON® protocol specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2020 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 4.0-5.0 diff --git a/specification/obsolete/PJON-protocol-specification-v1.0.md b/specification/obsolete/PJON-protocol-specification-v1.0.md index a7dc10681b..88c3dd585b 100644 --- a/specification/obsolete/PJON-protocol-specification-v1.0.md +++ b/specification/obsolete/PJON-protocol-specification-v1.0.md @@ -3,7 +3,7 @@ /* Milan, Italy - 3/10/2016 The PJON® protocol layer specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2020 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 6.0 and following diff --git a/specification/obsolete/PJON-protocol-specification-v1.1.md b/specification/obsolete/PJON-protocol-specification-v1.1.md index 9637b57a2b..dda97df3b7 100644 --- a/specification/obsolete/PJON-protocol-specification-v1.1.md +++ b/specification/obsolete/PJON-protocol-specification-v1.1.md @@ -4,7 +4,7 @@ Milan, Italy - 28/03/2017 The PJON® protocol layer specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2020 All rights reserved +Copyright 2010-2021 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 6.0 and following diff --git a/src/PJON.h b/src/PJON.h index d5165e65af..c14842e934 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -43,7 +43,7 @@ Compatible tools: This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 0447516192..8310aa3bc2 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -43,7 +43,7 @@ Compatible tools: This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONDynamicRouter.h b/src/PJONDynamicRouter.h index f91fe83763..6112f44cc6 100644 --- a/src/PJONDynamicRouter.h +++ b/src/PJONDynamicRouter.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -22,7 +22,7 @@ dynamically based on observed packets from remote buses. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONInteractiveRouter.h b/src/PJONInteractiveRouter.h index d5743b1520..7c46578b0c 100644 --- a/src/PJONInteractiveRouter.h +++ b/src/PJONInteractiveRouter.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -32,7 +32,7 @@ receiver callback should be really fast. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONLocal.h b/src/PJONLocal.h index af7bfade97..18bd9f85ec 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -52,7 +52,7 @@ Compatible tools: This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONRouter.h b/src/PJONRouter.h index b278681ec7..320b3c1f50 100644 --- a/src/PJONRouter.h +++ b/src/PJONRouter.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -23,7 +23,7 @@ buses. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONSimpleSwitch.h b/src/PJONSimpleSwitch.h index 1c36c27a0f..db7f8cdea1 100644 --- a/src/PJONSimpleSwitch.h +++ b/src/PJONSimpleSwitch.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -38,7 +38,7 @@ enabling receivers on shared buses to reply back to the local bus. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONSwitch.h b/src/PJONSwitch.h index 038d724b78..6efcd0b74b 100644 --- a/src/PJONSwitch.h +++ b/src/PJONSwitch.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -22,7 +22,7 @@ between buses of different strategies using the Any strategy. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONVirtualBusRouter.h b/src/PJONVirtualBusRouter.h index 4e90a86032..4517df127e 100644 --- a/src/PJONVirtualBusRouter.h +++ b/src/PJONVirtualBusRouter.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.0 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -30,7 +30,7 @@ and reducing traffic. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2020 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/AnalogSampling/AnalogSampling.h b/src/strategies/AnalogSampling/AnalogSampling.h index ecdf9359ab..e440aff4c6 100644 --- a/src/strategies/AnalogSampling/AnalogSampling.h +++ b/src/strategies/AnalogSampling/AnalogSampling.h @@ -31,7 +31,7 @@ necessary to tweak timing constants in Timing.h. ___________________________________________________________________________ - Copyright 2010-2020 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2021 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/Any/Any.h b/src/strategies/Any/Any.h index daa31afb2b..42a67b5b9c 100644 --- a/src/strategies/Any/Any.h +++ b/src/strategies/Any/Any.h @@ -7,7 +7,7 @@ Proposed and developed by Fred Larsen ___________________________________________________________________________ - Copyright 2010-2020 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2021 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/Any/StrategyLink.h b/src/strategies/Any/StrategyLink.h index f8f761d41d..9f7683591c 100644 --- a/src/strategies/Any/StrategyLink.h +++ b/src/strategies/Any/StrategyLink.h @@ -4,7 +4,7 @@ Proposed and developed by Fred Larsen ___________________________________________________________________________ - Copyright 2010-2020 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2021 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/Any/StrategyLinkBase.h b/src/strategies/Any/StrategyLinkBase.h index e2871c5e60..138b372c66 100644 --- a/src/strategies/Any/StrategyLinkBase.h +++ b/src/strategies/Any/StrategyLinkBase.h @@ -4,7 +4,7 @@ Proposed and developed by Fred Larsen ___________________________________________________________________________ - Copyright 2010-2020 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2021 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.0.md b/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.0.md index 2e38d81dee..c9ade58622 100644 --- a/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.0.md +++ b/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.0.md @@ -3,7 +3,7 @@ /* Milan, Italy - 18/01/2017 PJDLR (Padded jittering data link) specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2020 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 7.0-7.1 diff --git a/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.1.md b/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.1.md index 77e2b7f69e..5d6440977b 100644 --- a/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.1.md +++ b/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.1.md @@ -4,7 +4,7 @@ Milan, Italy - 31/03/2017 PJDLR (Padded jittering data link) specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2020 All rights reserved +Copyright 2010-2021 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 8.0 and following diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index 684f359386..122e29efce 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -5,7 +5,7 @@ Compliant with PJDL (Padded Jittering Data Link) specification v5.0 ___________________________________________________________________________ - Copyright 2010-2020 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2021 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index ee369d7f18..9e9aa81daa 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -1,6 +1,6 @@ /* PJON SoftwareBitBang strategy Transmission Timing table - Copyright 2010-2020, Giovanni Blu Mitolo All rights reserved. + Copyright 2010-2021, Giovanni Blu Mitolo All rights reserved. Often timing in two different machines do not match, code execution time can variate and time measurements are not perfectly equal. diff --git a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.0.md b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.0.md index 86e772fcc1..6b78bfd847 100644 --- a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.0.md +++ b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.0.md @@ -3,7 +3,7 @@ /* Milan, Italy - 10/04/2010 PJDL (Padded jittering data link) specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2020 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 6.0-7.1 diff --git a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.1.md b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.1.md index 6c2e30ee95..309863f4f6 100644 --- a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.1.md +++ b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.1.md @@ -4,7 +4,7 @@ Milan, Italy - 31/03/2017 PJDL (Padded jittering data link) specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2020 All rights reserved +Copyright 2010-2021 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 8.0 and following diff --git a/src/strategies/SoftwareBitBang/specification/obsolete/padded-jittering-protocol-specification-v0.1.md b/src/strategies/SoftwareBitBang/specification/obsolete/padded-jittering-protocol-specification-v0.1.md index 0835c53311..5b178c9a3c 100644 --- a/src/strategies/SoftwareBitBang/specification/obsolete/padded-jittering-protocol-specification-v0.1.md +++ b/src/strategies/SoftwareBitBang/specification/obsolete/padded-jittering-protocol-specification-v0.1.md @@ -3,7 +3,7 @@ /* Milan, Italy - 10/04/2010 The Padded jittering data link layer specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2020 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 1.0-5.0 From fd5fa07cd538bd395a2ac92e28383f900039e030 Mon Sep 17 00:00:00 2001 From: Jack Anderson <19514724+jdaandersj@users.noreply.github.com> Date: Sun, 24 Jan 2021 21:00:18 +0000 Subject: [PATCH 263/323] add column to 1-wire comparison point out PJDL is multi-controller bus. (using [oshwa terminology](https://www.oshwa.org/a-resolution-to-redefine-spi-signal-names/)) --- src/strategies/SoftwareBitBang/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index 0979285ed7..312cd900f9 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -55,10 +55,10 @@ The picture above shows a [PJDL](/src/strategies/SoftwareBitBang/specification/P ### PJDL vs. 1-Wire -| Protocol | Communication speed | Range | Communication mode | -| -------- | ------------------- | --------- | ---------------------- | -| PJDL | 1.97-3.34kB/s | 800-2000m | Simplex or half-duplex | -| 1-Wire | 2.03kB/s | 300m | Half-duplex | +| Protocol | Communication speed | Range | Communication mode | Bus Control | +| -------- | ------------------- | --------- | ---------------------- | -------------------------- | +| PJDL | 1.97-3.34kB/s | 800-2000m | Simplex or half-duplex | Multi-controller | +| 1-Wire | 2.03kB/s | 300m | Half-duplex | Controller-peripheral only | ### Configuration Before including the library it is possible to configure `SoftwareBitBang` using predefined constants: From 77e968e5956e548eb1ae3003b015788613924a7c Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 30 Jan 2021 19:41:01 +0100 Subject: [PATCH 264/323] data-transmission additional info about functions added --- documentation/data-transmission.md | 41 +++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index b0b38be9ca..c3b4e7418e 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -27,12 +27,17 @@ The `begin` method must be called before starting communication, the lack of thi ``` ### `send_packet` + +| Buffered | Blocking | Attempts | +| -------- | -------- | -------- | +| No | Yes | 1 | + The simplest way to send data is to use `send_packet`, this method composes the packet and tries to send it once. Consider that if the bus is busy or interference is present the transmission may not be attempted. The method returns the result of its operation. The first parameter is the device id of the recipient of type `uint8_t`, the second is the payload of type `const void *` and the third is the length of type `uint16_t`. This call implies a single attempt and has no guarantee of success, but logs the result of the attempted transmission: ```cpp // Send to device id 10 the string "Hi!" bus.send_packet(10, "Hi!", 3); ``` -The payload length is boring to be added in each call but is there to prevent buffer overflow. If sending arbitrary values `NULL` terminator strategy based on `strlen` is not safe to detect the end of a string. The `send` method can receive other 3 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id and including the port `8002`. + The `send_packet` method can receive 3 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion) and a port of type `uint16_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id and including the port `8002`. ```cpp // All optional parameters available bus.send_packet( @@ -62,7 +67,7 @@ bus.send_packet(1, &record, sizeof(record)); - `PJON_BUSY` (666) if bus is busy - `PJON_FAIL` (65535) if transmission failed -The `send_packet` result, of type `uint16_t`, can be used to determine if the transmission occurred successfully or not: +The `send_packet` return value, of type `uint16_t`, can be used to determine if the transmission occurred successfully or not: ```cpp uint16_t result = bus.send_packet(10, "All is ok?!", 11); @@ -85,13 +90,18 @@ bus.send_packet(info, "Ciao!", 5); ``` ### `send_packet_blocking` + +| Buffered | Blocking | Attempts | +| -------- | -------- | ----------------------------- | +| No | Yes | `strategy.get_max_attempts()` | + Use `send_packet_blocking` if it is necessary to try until the packet is effectively received by the recipient or a maximum amount of retries is reached. Consider that the method may block the operation of the program for up to 4 seconds in case of transmission failure. ```cpp // Send to device id 10 the string "Hi!" bus.send_packet_blocking(10, "Hi!", 3); ``` -The `send_packet_blocking` method can receive other 4 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion), a port of type `uint16_t` and a timeout of type `uint32_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id, including the port `8002` and passing a maximum timeout of 1 second: +The `send_packet_blocking` method can receive 4 optional parameters, the header of type `uint8_t`, a packet id of type `uint16_t` (pass 0 if you want to avoid the packet id inclusion), a port of type `uint16_t` and a timeout of type `uint32_t`. In the example below a packet containing the payload "Hello" is sent to device id 10 using the actual instance's header configuration, without including the packet id, including the port `8002` and passing a maximum timeout of 1 second: ```cpp // All optional parameters available bus.send_packet_blocking( @@ -121,7 +131,7 @@ bus.send_packet_blocking(1, &record, sizeof(record)); - `PJON_BUSY` (666) if bus is busy - `PJON_FAIL` (65535) if transmission failed -The `send_packet_blocking` result, of type `uint16_t`, can be used to determine if the transmission occurred successfully or not: +The `send_packet_blocking` return value, of type `uint16_t`, can be used to determine if the transmission occurred successfully or not: ```cpp uint16_t result = bus.send_packet_blocking(10, "All is ok?!", 11); @@ -140,7 +150,11 @@ bus.send_packet_blocking(info, "Ciao!", 5); ### `send` -When using the `send` method, PJON operates using its internal buffer, although a little more memory is required. The first thing to do and never forget is to call the `update` method once per loop cycle: +| Buffered | Blocking | Attempts | +| -------- | -------- | ----------------------------- | +| Yes | No | `strategy.get_max_attempts()` | + +When using the `send` method, PJON operates using its internal buffer, although a little more memory is required, this call is non-blocking and automatically handles back-off. The first thing to do and never forget is to call the `update` method once per loop cycle: ```cpp bus.update(); ``` @@ -193,7 +207,12 @@ bus.send(info, "Ciao!", 5); ``` ### `send_repeatedly` -The `send_repeatedly` method can be used when it is required to schedule a repeated sending with a given interval. The first parameter is the device id of the recipient of type `uint8_t` then follows the payload of type `const void *`, its length of type `uint16_t` and the interval of type `uint32_t`: + +| Buffered | Blocking | Attempts | +| -------- | -------- | ----------------------------- | +| Yes | No | `strategy.get_max_attempts()` | + +The `send_repeatedly` method can be used when it is required to schedule a repeated transmission. The first parameter is the device id of the recipient of type `uint8_t` then follows the payload of type `const void *`, its length of type `uint16_t` and the interval of type `uint32_t`: ```cpp // Local sending example uint16_t one_second_test = @@ -242,6 +261,11 @@ bus.send_repeatedly(info, "Ciao!", 5, 1000000); // Send "Ciao!" every second ``` ### `reply` + +| Buffered | Blocking | Attempts | +| -------- | -------- | ----------------------------- | +| Yes | No | `strategy.get_max_attempts()` | + The `reply` method can be called within the [receiver function](/documentation/data-reception.md#data-reception) to reply to a packet received previously: ```cpp bus.reply("All fine!", 9); @@ -264,6 +288,11 @@ bus.reply(&record, sizeof(record)); ``` ### `reply_blocking` + +| Buffered | Blocking | Attempts | +| -------- | -------- | ----------------------------- | +| No | Yes | `strategy.get_max_attempts()` | + The `reply_blocking` method can be called within the [receiver function](/documentation/data-reception.md#data-reception) to reply to a packet received previously: ```cpp bus.reply_blocking("All fine!", 9); From e107d760fac9770fcebf104dc01231fb846d5030 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 31 Jan 2021 01:04:30 +0100 Subject: [PATCH 265/323] PJONDefines.h PJON_MASTER_ID default added --- src/PJONDefines.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 8310aa3bc2..e268223acf 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -76,6 +76,11 @@ limitations under the License. */ #define PJON_NOT_ASSIGNED 255 #endif +/* Device id used by master */ +#ifndef PJON_MASTER_ID + #define PJON_MASTER_ID 254 +#endif + /* Internal constants: */ #define PJON_FAIL 65535 #define PJON_TO_BE_SENT 74 From 97f91f3f5b2e5aa3074da81e3b69ed04a9e679f1 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 31 Jan 2021 01:37:56 +0100 Subject: [PATCH 266/323] PJONLocal examples fixed strategy inclusion error --- .../SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino | 2 +- .../PJONLocal/BlinkTest/Transmitter/Transmitter.ino | 2 +- .../PJONLocal/NetworkAnalysis/Receiver/Receiver.ino | 2 +- .../PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino | 2 +- .../PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino | 2 +- .../PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino index 228184cb90..1ed39160e8 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Receiver/Receiver.ino @@ -3,7 +3,7 @@ #define PJON_PACKET_MAX_LENGTH 10 #include // Include PJONLocal -#include // Include only SoftwareBitBang +#include // Include only SoftwareBitBang PJONLocal bus(44); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Transmitter/Transmitter.ino index 71ca685500..b764612121 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/BlinkTest/Transmitter/Transmitter.ino @@ -2,7 +2,7 @@ #define PJON_PACKET_MAX_LENGTH 10 // Set maximum packet length #include // Include PJONLocal -#include // Include only SoftwareBitBang +#include // Include only SoftwareBitBang /* Create PJONLocal object: Class name instance name ( device id ) */ diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino index 94de9fabed..a73e0d83dd 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Receiver/Receiver.ino @@ -8,7 +8,7 @@ // Include only SoftwareBitBang #include // Include PJONLocal -#include // Include SoftwareBitBang +#include // Include only SoftwareBitBang PJONLocal bus(44); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino index 2b564dc0a0..d878ba29f0 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/NetworkAnalysis/Transmitter/Transmitter.ino @@ -6,7 +6,7 @@ // #define SWBB_MODE 4 // 3.40kB/s - 27210Bd #include // Include PJONLocal -#include // Include only SoftwareBitBang +#include // Include only SoftwareBitBang /* Create PJONLocal object: Class name instance name ( device id ) */ diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino index a5820a72c3..ea20b87e42 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Receiver/Receiver.ino @@ -3,7 +3,7 @@ is printed the record transmitted by the other device. */ #include // Include PJONLocal -#include // Include only SoftwareBitBang +#include // Include only SoftwareBitBang PJONLocal bus(44); diff --git a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino index 5ea76e0cad..a392e192ab 100644 --- a/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino +++ b/examples/ARDUINO/Local/SoftwareBitBang/PJONLocal/SendArbitraryDataType/Transmitter/Transmitter.ino @@ -2,7 +2,7 @@ This sketch contains the transmitter side. */ #include // Include PJONLocal -#include // Include only SoftwareBitBang +#include // Include only SoftwareBitBang /* Create PJONLocal object: Class name instance name ( device id ) */ From 3d887fdeda68f9929431827079e1e9da1d12ff9a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 31 Jan 2021 01:45:23 +0100 Subject: [PATCH 267/323] trademark property update --- README.md | 2 +- trademark/LICENSE.md | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index cf8fc7f051..084b3dbbe3 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Feel free to send a pull request sharing something you have made that could help - [PJON-gRPC](https://github.com/Halytskyi/PJON-gRPC) - gRPC server-client by Oleh Halytskyi ### License -All the software included in this project is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. [Licensed](https://github.com/gioblu/PJON/blob/master/LICENSE.md) under the Apache License, Version 2.0. PJON® and its brand are registered trademarks, property of Giovanni Blu Mitolo gioscarab@gmail.com +All the software included in this project is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. [Licensed](https://github.com/gioblu/PJON/blob/master/LICENSE.md) under the Apache License, Version 2.0. PJON® and its brand are registered trademarks, property of [PJON Technologies srl](https://www.pjon-technologies.com/) ### Safety warning When installing or maintaining a PJON network, extreme care must be taken to avoid any danger. If devices are connected to AC power you are exposed to a high chance of being electrocuted if hardware is not installed carefully and properly. If you are not experienced enough ask the support of a skilled technician and consider that many countries prohibit uncertified installations. When a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus is installed [interference mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines must be followed. When working with an [AnalogSampling](/src/strategies/AnalogSampling) LED or laser based setup safety glasses must be worn and transceivers must be operated cautiously to avoid potential eye injuries. Before any practical test or a hardware purchase for a wireless [OverSampling](/src/strategies/OverSampling), [ThroughSerial](/src/strategies/ThroughSerial) or [ThroughLoRa](/src/strategies/ThroughLoRa) radio setup, compliance with government requirements and regulations must be ensured. When connecting a local bus to the internet all devices must be considered potentially compromised, manipulated or remotely actuated against your will. It should be considered a good practice not to connect to the internet systems that may create a damage (fire, flood, data-leak) if hacked. diff --git a/trademark/LICENSE.md b/trademark/LICENSE.md index 84df7cc2e8..241faeec87 100644 --- a/trademark/LICENSE.md +++ b/trademark/LICENSE.md @@ -1,12 +1,9 @@ ![PJON](http://www.gioblu.com/PJON/PJON-github-header-tiny.png) -PJON® and its brand are registered trademarks, property of Giovanni Blu Mitolo gioscarab@gmail.com +PJON® and its brand are registered trademarks, property of [PJON Technologies srl](https://www.pjon-technologies.com/) Personal use of physical and or digital representations of PJON® and or its brand/icon are unlicensed and free. Commercial use of physical and or digital representations of PJON® and or its brand/icon trademark is subjected to prior application in order to be used. -The applicant may obtain a license of use concerning to physical and/or digital representation of PJON® and/or its brand/icon which can be used within physical and/or digital products of which is entitled to property, only if it deemed fully compliant with the latest official version of the PJON® Protocol layer specification (https://github.com/gioblu/PJON/blob/master/specification/) and fully interoperable with the other compatible systems, devices and implementations. +The applicant may obtain a license of use concerning to physical and/or digital representation of PJON® and/or its brand/icon which can be used within physical and/or digital products of which is entitled to property, only if it deemed fully compliant with the latest version of the PJON® Protocol layer specification (https://github.com/gioblu/PJON/blob/master/specification/) and fully interoperable with other compatible systems, devices and implementations. -To obtain a license for commercial use of digital and or physical representations of PJON® and or its brand/icon: - -1. Write a brief application containing a **product description**, **tool list** (hardware and software used), **interoperability assessment** (tested with other PJON compliant tools?), **functional tests** (It works? How?) and send it to gioscarab@gmail.com -2. Wait for response after application. If an application is considered unfitting, the applicant is informed and, if possible, supported to achieve full compliancy. +To obtain a license for commercial use of digital and or physical representations of PJON® and or its brand/icon write a brief application containing a **product description**, **tools list** (hardware and software used), **interoperability assessment** (tested with other PJON compliant tools?), **functional tests** (It works? How?) and send it to info@pjon-technologies.com From 14a33cf5a91573c1b13a29b7797df83351f74746 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 31 Jan 2021 15:13:48 +0100 Subject: [PATCH 268/323] ThroughSerial README updated info about communication modes --- src/strategies/ThroughSerial/README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index 074321d605..077ef32554 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -1,26 +1,24 @@ ## ThroughSerial -| Medium | Pins used | Inclusion | -|--------|-----------|--------------------| -| Wires | 2 | `#include `| +| Medium | Communication mode | Pins used | Inclusion | +|--------|--------------------|-----------|-----------| +| wires | master-slave, multi-master | 2 | `#include `| With `ThroughSerial` strategy, PJON can run through a software or hardware Serial port working out of the box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). It complies with [TSDL v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md). This strategy is based upon the obsolete blocking implementation although reception is now asynchronous and completely non-blocking. It is not required to call `bus.receive()` with any delay, just call it frequently to see if there are any packets that have been received. ### Why PJON over Serial? -Serial communication is fast and reliable but it is often useless without all the features PJON contains. `ThroughAsyncSerial` has been developed to enable PJON communication through a serial data link. Adding PJON on top of Serial it is possible to leverage of the PJON protocol layer features like acknowledge, addressing, multiplexing, packet handling, 8 or 32-bit CRC and traffic control. +Serial communication is fast and reliable but it is often useless without all the features PJON contains. `ThroughSerial` has been developed to enable PJON communication through a serial data link. Adding PJON on top of Serial it is possible to leverage of the PJON protocol layer features like acknowledge, addressing, multiplexing, packet handling, 8 or 32-bit CRC and traffic control. -`ThroughSerial` has been developed primarily to be used in master-slave mode. `ThroughSerial` in multi-master mode, being unable to detect or avoid collisions, operates using the slotted ALOHA medium access method. Of all contention based random multiple access methods, slotted ALOHA, which maximum data throughput is only 36.8% of the available bandwidth, is one of the least efficient and should not be applied in networks where many devices often need to arbitrarily transmit data. - -`ThroughSerial` performs well if used with ESP8266 and ESP32 where blocking procedures can strongly degrade functionality. The reception phase is entirely non-blocking. Sending and acknowledgement however are still blocking. +`ThroughSerial` implements a variation of CSMA (Carrier Sense Multiple Access). It is able to avoid collision with an ongoing frame transmission but cannot detect or avoid same-time collisions. The reception phase is entirely non-blocking although sending and acknowledgement are still blocking. ### Configuration Before including the library it is possible to configure `ThroughSerial` using predefined constants: | Constant | Purpose | Supported value | | ----------------------- |------------------------------------ | ------------------------------------------ | -| `TS_READ_INTERVAL` | minimum interval between receptions | Duration in microseconds (100 by default) | +| `TS_READ_INTERVAL` | Minimum interval between receptions | Duration in microseconds (100 by default) | | `TS_BYTE_TIME_OUT` | Maximum byte reception time-out | Duration in microseconds (1000000 by default) | | `TS_RESPONSE_TIME_OUT` | Maximum response time-out | Duration in microseconds (45000 by default) | | `TS_BACK_OFF_DEGREE` | Maximum back-off exponential degree | Numeric value (4 by default) | From 706d6a1319fa6e0f7247c1c10a1b5c59f15f65c1 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 31 Jan 2021 16:24:15 +0100 Subject: [PATCH 269/323] ThroughSerial README minor fix --- src/strategies/ThroughSerial/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/strategies/ThroughSerial/README.md b/src/strategies/ThroughSerial/README.md index 077ef32554..5092d17c32 100644 --- a/src/strategies/ThroughSerial/README.md +++ b/src/strategies/ThroughSerial/README.md @@ -1,8 +1,8 @@ ## ThroughSerial -| Medium | Communication mode | Pins used | Inclusion | -|--------|--------------------|-----------|-----------| -| wires | master-slave, multi-master | 2 | `#include `| +| Medium | Pins used | Inclusion | +|--------|-----------|--------------------| +| Wires | 2 | `#include `| With `ThroughSerial` strategy, PJON can run through a software or hardware Serial port working out of the box with many Arduino compatible serial transceivers, like RS485 or radio modules like HC-12 (HCMODU0054). It complies with [TSDL v3.0](/src/strategies/ThroughSerial/specification/TSDL-specification-v3.0.md). From 627eb10485d4b369eadb03d2387b15ee053b5041 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 1 Feb 2021 23:07:56 +0100 Subject: [PATCH 270/323] SoftwareBitBang Surrogate avoid polling for ETCP --- .../SoftwareBitBangSurrogate/Surrogate/Surrogate.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino index f721404cf8..20b35258f3 100644 --- a/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino +++ b/examples/ARDUINO/Local/EthernetTCP/SoftwareBitBangSurrogate/Surrogate/Surrogate.ino @@ -70,7 +70,7 @@ void receiver_functionB(uint8_t *payload, uint16_t length, const PJON_Packet_Inf void loop() { busA.receive(1000); busB.update(); - busB.receive(1000); + busB.receive(); busA.update(); // Show the number of sockets created after startup From 90a89619872dab9c4bd5d500ce6bb93f7ba32953 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 5 Mar 2021 15:22:57 +0100 Subject: [PATCH 271/323] SoftwareBitBang level conversion info added (https://github.com/gioblu/PJON/issues/386) --- src/strategies/SoftwareBitBang/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index 312cd900f9..803729c9b5 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -99,6 +99,7 @@ PJON application example made by the user [Michael Teeuw](http://michaelteeuw.nl - When using more than one instance of `SoftwareBitBang` in the same sketch use pins part of different port groups to avoid cross-talk. - During the execution of other tasks or delays a certain amount of packets could be potentially lost because transmitted out of the polling time of the receiver device. Thanks to the PJON packet handler after some retries the packet is received but a certain amount of bandwidth is wasted. If this situation occurs try to reduce the duration of other tasks and use a frame preamble setting `SWBB_MAX_PREAMBLE` and `SWBB_PREAMBLE` to a value between 1 and 100. The optimal preamble length is the maximum interval between each `bus.receive()` call divided by `SWBB_BIT_SPACER` - `SoftwareBitBang` strategy can have compatibility issues with codebases that are using interrupts, reliability or bandwidth loss can occur because of the interruptions made by third party software. +- If you need to connect devices that operate at different voltages, for example when connecting an Arduino UNOs to an ESP32, consider that voltage level converters available in the market are often not compatible with PJDL, you can try this [alternative approach](http://www.falstad.com/circuit/circuitjs.html?ctz=CQAgjCAMB0l3BWEA2AzNA7ATi8gHACxhaKTJYgaohIHUICmAtGGAFABu4WATCKgj7E+PDH0hQQBCemoT50BJxpg+AvglUhR4ydJqSFSgO5SCefoO0Jkl8WwAm12z0gWeN8D3fgAcqgI2AAduETcvd3CIeTZTD1t1ULsoWJU1KwJzZMhU4XAtePz7UwJkAiK0ipySsorMi1Z7EM0wiwQMFyjDNgBnSp1+8PkQADMAQwAbHoY2ACdnbXDCxIlCeF6kgbzXCwkIcamZ+bzGzaGpVzhUwp2z3evPU-qqh9tTwtV7+eenrJXweDreYtCog24SS5sAAeICYPBcYDerm0xCk2nKqA4qAAOj0HAwOABLADGDFxAEkAPLQmiEFHlDBgDAo5nlHjlBAcXH4omkinUmHECCoOkISAUEWs8BIADKAHVyQAVADCAAkAKIy3EAQQASurcQBVGXqgAiuMVlNxMvJAFlDQAZbWKg09SmGxUABQ9bCAA) proposed by [alastaira](https://github.com/alastaira) instead. It isn't truly converting voltage levels but it is much quicker and cheaper than designs based on transistors. ### Safety warning In all cases, when installing or maintaining a PJON network, extreme care must be taken to avoid any danger. If devices are connected to AC power you are exposed to a high chance of being electrocuted if hardware is not installed carefully and properly. If you are not experienced enough ask the support of a skilled technician and consider that many countries prohibit uncertified installations. When a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus is installed [interference mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines must be followed. If a common ground or power supply line is used its cable size and length must be carefully selected taking in consideration the overall application's power supply requirements and selected components' maximum rating. PJDL and its reference implementation [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) are experimental, use them at your own risk. From abe608c04b99cde653a73466fa16ea78a0cd9ba8 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 5 Mar 2021 15:43:26 +0100 Subject: [PATCH 272/323] random seed section added to configuration docs (https://github.com/gioblu/PJON/issues/387) --- documentation/configuration.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index 3a72897869..5f0683ee92 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -65,6 +65,13 @@ The table below lists the strategies available: Before using `ThroughLoRa` be sure to have [arduino-LoRa](https://github.com/sandeepmistry/arduino-LoRa) library available. Before using `ESPNOW` be sure to have installed the required tools as described [here](/src/strategies/ESPNOW/README.md). Before using `MQTTTranslate` be sure to have the [ReconnectingMqttClient](https://github.com/fredilarsen/ReconnectingMqttClient) library available. +### Random seed +When `begin` is called an analog pin is used to sample the seed for the random generator. By default PJON uses pin `A0` to sample the seed, if you need to use another pin call `set_random_seed` as shown below: +```cpp + bus.set_random_seed(A1); // A1 is used to sample the seed + bus.begin(); // Seed sampling occurs +``` + ### Network mode The network mode can be changed with `set_shared_network` during runtime, for example moving from [local](/specification/PJON-protocol-specification-v4.0.md#local-mode) to [shared](https://github.com/gioblu/PJON/blob/master/specification/PJON-protocol-specification-v4.0.md#shared-mode) mode: ```cpp @@ -72,7 +79,7 @@ The network mode can be changed with `set_shared_network` during runtime, for ex ``` ### Communication mode -The communication mode can be configured using the `set_communication_mode` passing `PJON_SIMPLEX` for simplex or mono-directional mode or `PJON_HALF_DUPLEX` for half-duplex or bidirectional mode: +The communication mode can be configured using `set_communication_mode` passing `PJON_SIMPLEX` for simplex or mono-directional mode or `PJON_HALF_DUPLEX` for half-duplex or bidirectional mode: ```cpp // Run in mono-directional PJON_SIMPLEX mode bus.set_communication_mode(PJON_SIMPLEX); From c56328dbae1ae167803c4bddf6d82adc085091ae Mon Sep 17 00:00:00 2001 From: Rainer Schoenberger Date: Sat, 13 Mar 2021 20:33:07 +0100 Subject: [PATCH 273/323] Inline LINUX_Interface functions and remove global vars This prevents linking errors if PJON is included in multiple compilation units. Also using the static singleton pattern is safer than global vars, especially with multiple compilation units. --- src/interfaces/LINUX/PJON_LINUX_Interface.inl | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/interfaces/LINUX/PJON_LINUX_Interface.inl b/src/interfaces/LINUX/PJON_LINUX_Interface.inl index 642d0d2d21..2b56040a3f 100644 --- a/src/interfaces/LINUX/PJON_LINUX_Interface.inl +++ b/src/interfaces/LINUX/PJON_LINUX_Interface.inl @@ -8,30 +8,39 @@ #include "PJON_LINUX_Interface.h" #include "/usr/include/asm-generic/termbits.h" #include "/usr/include/asm-generic/ioctls.h" - -auto start_ts = std::chrono::high_resolution_clock::now(); -auto start_ts_ms = std::chrono::high_resolution_clock::now(); - -uint32_t micros() { +#include + +inline auto& getMutableStartTime() +{ + static auto start_ts = std::chrono::high_resolution_clock::now(); + return start_ts; +} +inline auto getStartTime() +{ + static auto start_ts_ms = std::chrono::high_resolution_clock::now(); + return start_ts_ms; +} + +inline uint32_t micros() { auto elapsed_usec = std::chrono::duration_cast( - std::chrono::high_resolution_clock::now() - start_ts + std::chrono::high_resolution_clock::now() - getMutableStartTime() ).count(); if(elapsed_usec >= UINT32_MAX) { - start_ts = std::chrono::high_resolution_clock::now(); + getMutableStartTime() = std::chrono::high_resolution_clock::now(); return 0; } else return elapsed_usec; }; -uint32_t millis() { +inline uint32_t millis() { return (uint32_t) std::chrono::duration_cast( - std::chrono::high_resolution_clock::now() - start_ts_ms + std::chrono::high_resolution_clock::now() - getStartTime() ).count(); }; -void delayMicroseconds(uint32_t delay_value) { +inline void delayMicroseconds(uint32_t delay_value) { struct timeval tv; if (delay_value < 1000000){ tv.tv_sec = 0; @@ -45,13 +54,13 @@ void delayMicroseconds(uint32_t delay_value) { select(0, NULL, NULL, NULL, &tv); }; -void delay(uint32_t delay_value_ms) { +inline void delay(uint32_t delay_value_ms) { std::this_thread::sleep_for(std::chrono::milliseconds(delay_value_ms)); }; /* Open serial port ----------------------------------------------------- */ -int serialOpen(const char *device, const int baud) { +inline int serialOpen(const char *device, const int baud) { speed_t bd; int fd; @@ -98,7 +107,7 @@ int serialOpen(const char *device, const int baud) { /* Returns the number of bytes of data available to be read in the buffer */ -int serialDataAvailable(const int fd) { +inline int serialDataAvailable(const int fd) { int result = 0; ioctl(fd, FIONREAD, &result); return result; @@ -106,7 +115,7 @@ int serialDataAvailable(const int fd) { /* Reads a character from the serial buffer ------------------------------- */ -int serialGetCharacter(const int fd) { +inline int serialGetCharacter(const int fd) { uint8_t result; if(read(fd, &result, 1) != 1) return -1; return ((int)result) & 0xFF; From 73baf8e335ab28177dba559f411ea57ed995c99d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Apr 2021 12:51:01 +0200 Subject: [PATCH 274/323] @rainerschoe added to contributors (https://github.com/gioblu/PJON/issues/392) (https://github.com/gioblu/PJON/issues/388) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 084b3dbbe3..00a74364b0 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Telecomunicación - [Universidad de Cantabria](https://web.unican.es/) (ES) ### Contribute Feel free to send a pull request sharing something you have made that could help, if you want to support this project you can also try to solve an [issue](https://github.com/gioblu/PJON/issues). Thanks to support, expertise, kindness and talent of the following contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: -[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen), [Julio Aguirre](https://github.com/jcallano), [Cimex97](https://github.com/Cimex97), [der-schne](https://github.com/der-schne) and [porkyneal](https://github.com/porkyneal). +[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen), [Julio Aguirre](https://github.com/jcallano), [Cimex97](https://github.com/Cimex97), [der-schne](https://github.com/der-schne) and [porkyneal](https://github.com/porkyneal), [der-schne](https://github.com/der-schne) and [Rainer Schoenberger](https://github.com/rainerschoe). ### Compliant tools - [ModuleInterface](https://github.com/fredilarsen/ModuleInterface) - easy config and value sync between IoT modules by Fred Larsen From f6b1dbafac2447cbe7720cad270feadb6885cb3a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Apr 2021 12:53:38 +0200 Subject: [PATCH 275/323] Biomimetic electronics broken link fixed --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 00a74364b0..4c4d3183ab 100644 --- a/README.md +++ b/README.md @@ -34,13 +34,13 @@ PJON is used in thousands of devices and its community has spread worldwide beca Researchers are active in many universities worldwide using PJON in different environments. The following list contains all the known published academic studies about PJON: - [Definition and Application of PJON-PLC for sensor networks](https://repositorio.unican.es/xmlui/bitstream/handle/10902/14012/408952.pdf?sequence=1) by Jorge Gómez Segurola, Ingeniería de Tecnologías de Telecomunicación - [Universidad de Cantabria](https://web.unican.es/) (ES) -- [Biomimetic electronics](http://c.harl.ie/biomimetic.html) by Charlie Williams with scientific input from researchers Vítor Martins dos Santos, Diana Machado de Sousa and Sabine Vreeburg - Artist in Residency at [Wageningen University](https://www.wur.nl/en.htm) (NL) +- [Biomimetic electronics](https://charliewilliams.org/portfolio/biomimetic/) by Charlie Williams with scientific input from researchers Vítor Martins dos Santos, Diana Machado de Sousa and Sabine Vreeburg - Artist in Residency at [Wageningen University](https://www.wur.nl/en.htm) (NL) - [LANC Video Camera Control](http://jda.tel/pdf/lanc_video_camera_control.pdf) by [Jack Anderson](https://github.com/jdaandersj) - Department of Computer Science [Loughborough University](https://www.lboro.ac.uk/departments/compsci/) (UK) ### Contribute Feel free to send a pull request sharing something you have made that could help, if you want to support this project you can also try to solve an [issue](https://github.com/gioblu/PJON/issues). Thanks to support, expertise, kindness and talent of the following contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: -[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen), [Julio Aguirre](https://github.com/jcallano), [Cimex97](https://github.com/Cimex97), [der-schne](https://github.com/der-schne) and [porkyneal](https://github.com/porkyneal), [der-schne](https://github.com/der-schne) and [Rainer Schoenberger](https://github.com/rainerschoe). +[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen), [Julio Aguirre](https://github.com/jcallano), [Cimex97](https://github.com/Cimex97), [der-schne](https://github.com/der-schne), [porkyneal](https://github.com/porkyneal), [der-schne](https://github.com/der-schne) and [Rainer Schoenberger](https://github.com/rainerschoe). ### Compliant tools - [ModuleInterface](https://github.com/fredilarsen/ModuleInterface) - easy config and value sync between IoT modules by Fred Larsen From 1f0bf3303a53bb226a69809da0b28f32efe9289c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Apr 2021 13:25:21 +0200 Subject: [PATCH 276/323] documentation/data-transmission forward and forward_blocking added --- documentation/data-transmission.md | 42 ++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index c3b4e7418e..6fc6aa22db 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -313,3 +313,45 @@ record.v2 = analogRead(A2); // Reply with the record struct bus.reply_blocking(&record, sizeof(record)); ``` + +### `forward` + +| Buffered | Blocking | Attempts | +| -------- | -------- | ----------------------------- | +| Yes | No | `strategy.get_max_attempts()` | + +The `forward` method can retransmit a packet received previously to another device using its original sender's identification. It is useful to implement switching or routing features: +```cpp +void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &info) { + bus.forward(info, payload, length); + // Forward each packet is received +}; +``` + +Consider that `forward` dispatches a packet in the buffer like `send` or `send_repeatedly`. To use the return value of `forward` just save it in a variable of type `uint16_t`: +```cpp +uint16_t packet = bus.forward(info, payload, length); +if(packet == PJON_FAIL) Serial.print("Something went wrong"); +``` +The `forward` method accepts any type of data like `send` or `send_repeatedly`. + +### `forward_blocking` + +| Buffered | Blocking | Attempts | +| -------- | -------- | ----------------------------- | +| No | Yes | `strategy.get_max_attempts()` | + +The `forward_blocking` method can retransmit a packet received previously to another device using its original sender's identification. It is useful to implement switching or routing features: +```cpp +void receiver_function(uint8_t *payload, uint16_t length, const PJON_Packet_Info &info) { + bus.forward_blocking(info, payload, length); + // Forward each packet is received +}; +``` + +Consider that `forward_blocking` is a blocking procedure that in case of failure can last a considerable amount of time. The `forward_blocking` result, of type `uint16_t`, can be used to determine if the transmission occurred successfully or not: +```cpp +uint16_t result = bus.forward_blocking(info, payload, length); +if(result == PJON_ACK) Serial.println("Responded successfully!"); +``` +The `forward_blocking` method accepts any type of data like `send` or `send_repeatedly`. From efc00512e29aab0789875df4ae55df8ebfd25e78 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Apr 2021 13:29:14 +0200 Subject: [PATCH 277/323] documentation index update --- documentation/README.md | 2 +- documentation/addressing.md | 2 +- documentation/configuration.md | 2 +- documentation/data-reception.md | 2 +- documentation/data-structures.md | 2 +- documentation/data-transmission.md | 2 +- documentation/error-handling.md | 2 +- documentation/io-setup.md | 2 +- documentation/routing.md | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/documentation/README.md b/documentation/README.md index b2b33ff587..0ef24a499a 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -9,7 +9,7 @@ - [Data structures](/documentation/data-structures.md) - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`forward`](/documentation/data-transmission.md#forward) [`forward_blocking`](/documentation/data-transmission.md#forward_blocking) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) diff --git a/documentation/addressing.md b/documentation/addressing.md index 84c38c0628..33c6e4ad13 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -9,7 +9,7 @@ - [Data structures](/documentation/data-structures.md) - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`forward`](/documentation/data-transmission.md#forward) [`forward_blocking`](/documentation/data-transmission.md#forward_blocking) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) diff --git a/documentation/configuration.md b/documentation/configuration.md index 5f0683ee92..821a985184 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -9,7 +9,7 @@ - [Data structures](/documentation/data-structures.md) - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`forward`](/documentation/data-transmission.md#forward) [`forward_blocking`](/documentation/data-transmission.md#forward_blocking) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) diff --git a/documentation/data-reception.md b/documentation/data-reception.md index 81f0ace177..ab0c45e256 100644 --- a/documentation/data-reception.md +++ b/documentation/data-reception.md @@ -9,7 +9,7 @@ - [Data structures](/documentation/data-structures.md) - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`forward`](/documentation/data-transmission.md#forward) [`forward_blocking`](/documentation/data-transmission.md#forward_blocking) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) diff --git a/documentation/data-structures.md b/documentation/data-structures.md index e0bb80adf5..0d309bfc5e 100644 --- a/documentation/data-structures.md +++ b/documentation/data-structures.md @@ -9,7 +9,7 @@ - **[Data structures](/documentation/data-structures.md)** - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`forward`](/documentation/data-transmission.md#forward) [`forward_blocking`](/documentation/data-transmission.md#forward_blocking) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) diff --git a/documentation/data-transmission.md b/documentation/data-transmission.md index 6fc6aa22db..2c7cc76e5d 100644 --- a/documentation/data-transmission.md +++ b/documentation/data-transmission.md @@ -9,7 +9,7 @@ - [Data structures](/documentation/data-structures.md) - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - **[Data transmission](/documentation/data-transmission.md)** - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`forward`](/documentation/data-transmission.md#forward) [`forward_blocking`](/documentation/data-transmission.md#forward_blocking) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) diff --git a/documentation/error-handling.md b/documentation/error-handling.md index 72ec6bec4d..54e6d528b3 100644 --- a/documentation/error-handling.md +++ b/documentation/error-handling.md @@ -9,7 +9,7 @@ - [Data structures](/documentation/data-structures.md) - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`forward`](/documentation/data-transmission.md#forward) [`forward_blocking`](/documentation/data-transmission.md#forward_blocking) - **[Error handling](/documentation/error-handling.md)** - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) diff --git a/documentation/io-setup.md b/documentation/io-setup.md index 13db23c514..f4fe9f822b 100644 --- a/documentation/io-setup.md +++ b/documentation/io-setup.md @@ -9,7 +9,7 @@ - [Data structures](/documentation/data-structures.md) - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`forward`](/documentation/data-transmission.md#forward) [`forward_blocking`](/documentation/data-transmission.md#forward_blocking) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - [Routing](/documentation/routing.md) diff --git a/documentation/routing.md b/documentation/routing.md index 0fc40e2f49..e366af1186 100644 --- a/documentation/routing.md +++ b/documentation/routing.md @@ -9,7 +9,7 @@ - [Data structures](/documentation/data-structures.md) - [`PJON_Endpoint`](/documentation/data-structures.md#pjon_endpoint) [`PJON_Packet_Info`](/documentation/data-structures.md#pjon_packet_info) - [Data transmission](/documentation/data-transmission.md) - - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) + - [`begin`](/documentation/data-transmission.md#begin) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`send`](/documentation/data-transmission.md#send) [`send_packet`](/documentation/data-transmission.md#send_packet) [`send_packet_blocking`](/documentation/data-transmission.md#send_packet_blocking) [`send_repeatedly`](/documentation/data-transmission.md#send_repeatedly) [`reply`](/documentation/data-transmission.md#reply) [`reply_blocking`](/documentation/data-transmission.md#reply_blocking) [`forward`](/documentation/data-transmission.md#forward) [`forward_blocking`](/documentation/data-transmission.md#forward_blocking) - [Error handling](/documentation/error-handling.md) - [`set_error`](/documentation/error-handling.md#error-handling) - **[Routing](/documentation/routing.md)** From c7ad3269b904459cc6a4746ac474eb0a3fa6d8af Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 5 Apr 2021 13:59:15 +0200 Subject: [PATCH 278/323] PJONDefines.h avoid unsafe initialization (https://github.com/gioblu/PJON/issues/392) --- src/PJONDefines.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/PJONDefines.h b/src/PJONDefines.h index e268223acf..42ddc10fb6 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -394,7 +394,6 @@ struct PJONTools { /* Fills a PJON_Packet_Info struct with data parsing a packet: */ static void parse_header(const uint8_t *packet, PJON_Packet_Info &info) { - memset(&info, 0, sizeof info); uint8_t index = 0; info.rx.id = packet[index++]; bool extended_length = packet[index] & PJON_EXT_LEN_BIT; From f3611f40bdccf0950d474cbde18236582f61b852 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Apr 2021 13:26:39 +0200 Subject: [PATCH 279/323] README update --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4c4d3183ab..7bffe741ac 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ ![PJON](http://www.gioblu.com/PJON/PJON-github-header-tiny.png) ## PJON 13.0 -PJON® (Padded Jittering Operative Network) is an arduino-compatible, multi-master, multi-media network protocol. It proposes a new Open Standard, it is designed as a framework and implements a totally software-defined network protocol stack that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media and protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). +PJON® (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media network protocol. It proposes a new Open Standard, it is designed as a framework and implements a totally software-defined network protocol stack that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). [![Get PJON bus id](https://img.shields.io/badge/get-PJON%20bus%20id-lightgrey.svg)](http://www.pjon.org/get-bus-id.php) [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -PJON is used in thousands of devices and its community has spread worldwide because of the following 5 key factors: +### Why PJON? - **New technology**: [PJON](specification/PJON-protocol-specification-v4.0.md) is an experimental network protocol stack crafted in 10 years of research and experimentation. It was originally developed as an open-source alternative to i2c and 1-Wire but during development its scope and features have been extended to cover use cases where IP is generally applied. PJON has been engineered to have a variable footprint (4.2-8.2 kB program memory) and overhead (5-35 bytes per packet) depending on its configuration. - **Multi-media support**: PJON operates upon a wide range of protocols like TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485 and LoRa. The PJON network protocol stack specifies and implements also [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) that operates over a single wire of up to 2000m shared by up to 255 devices, [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) that operates with many ASK/FSK/OOK radio modules, and also [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) that operates wirelessly with light pulses using off-the-shelf LEDs and laser diodes. - **Increased reliability**: Many protocols massively applied worldwide expose dangerous vulnerabilities, have weak error detection algorithms and are not resilient to interference. PJON is based on years of analysis and study not to make the same mistakes present in most alternatives and provide with a simpler and more efficient solution. - **High flexibility**: PJON is totally software-defined and it is designed to be easily extensible. it builds out-of-the-box in all supported devices and operates transparently on top of any supported protocol or medium. -- **Low cost**: Without any additional hardware needed to operate, minimal network wiring requirements and direct pin-to-pin or LED-to-LED communication, PJON is extremely energy efficient, cheap to be implemented and maintained. This implementation is kept updated and meticulously tested thanks to the strong commitment of its growing community of end users, testers and developers. +- **Low cost**: With no additional hardware needed to operate, minimal network wiring requirements and direct pin-to-pin or LED-to-LED communication, PJON is extremely energy efficient, cheap to be implemented and maintained. This experimental reference implementation is kept updated thanks to the strong commitment of its growing community. ### Features - Cross-compilation support with the [interfaces](src/interfaces) system calls abstraction @@ -53,4 +53,4 @@ Feel free to send a pull request sharing something you have made that could help All the software included in this project is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. [Licensed](https://github.com/gioblu/PJON/blob/master/LICENSE.md) under the Apache License, Version 2.0. PJON® and its brand are registered trademarks, property of [PJON Technologies srl](https://www.pjon-technologies.com/) ### Safety warning -When installing or maintaining a PJON network, extreme care must be taken to avoid any danger. If devices are connected to AC power you are exposed to a high chance of being electrocuted if hardware is not installed carefully and properly. If you are not experienced enough ask the support of a skilled technician and consider that many countries prohibit uncertified installations. When a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus is installed [interference mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines must be followed. When working with an [AnalogSampling](/src/strategies/AnalogSampling) LED or laser based setup safety glasses must be worn and transceivers must be operated cautiously to avoid potential eye injuries. Before any practical test or a hardware purchase for a wireless [OverSampling](/src/strategies/OverSampling), [ThroughSerial](/src/strategies/ThroughSerial) or [ThroughLoRa](/src/strategies/ThroughLoRa) radio setup, compliance with government requirements and regulations must be ensured. When connecting a local bus to the internet all devices must be considered potentially compromised, manipulated or remotely actuated against your will. It should be considered a good practice not to connect to the internet systems that may create a damage (fire, flood, data-leak) if hacked. +When testing PJON, extreme care must be taken to avoid any danger. Consider that the implementation is experimental and may not behave as expected, use it at your own risk. When devices are connected to AC power you are exposed to a high chance of being electrocuted if hardware is not installed carefully and properly. If you are not experienced enough ask the support of a skilled technician and consider that many countries prohibit uncertified installations. When testing a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus [interference mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines must be followed. When experimenting with [AnalogSampling](/src/strategies/AnalogSampling) setup safety glasses must be worn and transceivers must be operated cautiously to avoid potential eye injuries. Before testing [OverSampling](/src/strategies/OverSampling), [ThroughSerial](/src/strategies/ThroughSerial) or [ThroughLoRa](/src/strategies/ThroughLoRa) radio communication, be sure the frequency, power and hardware used complies with local laws. When connecting a local bus to the internet all devices must be considered potentially compromised, manipulated or remotely actuated against your will. It should be considered a good practice not to connect to the internet systems that may create a damage (fire, flood, data-leak) if hacked. From 4dff0bc64069a551c9ca9edda140f603ceb7b1fd Mon Sep 17 00:00:00 2001 From: Rainer Date: Sun, 6 Feb 2022 13:37:02 +0100 Subject: [PATCH 280/323] fix undefined behavior when using ports #406 --- src/PJONDefines.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 42ddc10fb6..4cd9a96e55 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -395,6 +395,14 @@ struct PJONTools { static void parse_header(const uint8_t *packet, PJON_Packet_Info &info) { uint8_t index = 0; + + // replace passed in info with a fresh instance + // (initializing all values to their defaults) + // This is important, as we conditionally parse some info fields (e.g. Port) + // Those would then be left uninitialized or in an old state corresponding to + // the previous packet: + info = PJON_Packet_Info{}; + info.rx.id = packet[index++]; bool extended_length = packet[index] & PJON_EXT_LEN_BIT; info.header = packet[index++]; From 4f0aa5f7143553617167dcc9ac9500d5ee092b92 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 10 Feb 2022 22:04:33 +0100 Subject: [PATCH 281/323] removed comments --- src/PJONDefines.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 4cd9a96e55..ab60ac7ea3 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -395,12 +395,6 @@ struct PJONTools { static void parse_header(const uint8_t *packet, PJON_Packet_Info &info) { uint8_t index = 0; - - // replace passed in info with a fresh instance - // (initializing all values to their defaults) - // This is important, as we conditionally parse some info fields (e.g. Port) - // Those would then be left uninitialized or in an old state corresponding to - // the previous packet: info = PJON_Packet_Info{}; info.rx.id = packet[index++]; From 1fd1af544637267ea26dee83429b1415ca5c9bb2 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 10 Feb 2022 22:10:24 +0100 Subject: [PATCH 282/323] Added PjonHL, removed outdated stuff from README --- README.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/README.md b/README.md index 7bffe741ac..745bc269a4 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ - -![PJON](http://www.gioblu.com/PJON/PJON-github-header-tiny.png) ## PJON 13.0 PJON® (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media network protocol. It proposes a new Open Standard, it is designed as a framework and implements a totally software-defined network protocol stack that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). @@ -24,12 +22,6 @@ PJON® (Padded Jittering Operative Network) is an experimental, arduino-compatib - Optional acknowledgement - Error handling -### Publications -- [PJON protocol handbook 13.0](https://www.pjon-technologies.com/collections/frontpage/products/the-pjon-protocol-handbook-v13) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) -- [PJON 13.0 big box](https://www.pjon-technologies.com/collections/frontpage/products/pjon-13-0-big-box) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) -- [PJON protocol handbook 12.0](https://www.pjon-technologies.com/collections/frontpage/products/pjon-protocol-hand-book) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) -- [PJON 12.0 big box](https://www.pjon-technologies.com/collections/frontpage/products/pjon-protocol-12-0-big-box) by Giovanni Blu Mitolo - Distributed by [PJON Technologies srl](https://www.pjon-technologies.com) - ### Academic studies Researchers are active in many universities worldwide using PJON in different environments. The following list contains all the known published academic studies about PJON: - [Definition and Application of PJON-PLC for sensor networks](https://repositorio.unican.es/xmlui/bitstream/handle/10902/14012/408952.pdf?sequence=1) by Jorge Gómez Segurola, Ingeniería de Tecnologías de @@ -48,6 +40,7 @@ Feel free to send a pull request sharing something you have made that could help - [PJON-piper](https://github.com/Girgitt/PJON-piper) - command line wrapper by Zbigniew Zasieczny - [PJON-python](https://github.com/Girgitt/PJON-python) - python interface by Zbigniew Zasieczny - [PJON-gRPC](https://github.com/Halytskyi/PJON-gRPC) - gRPC server-client by Oleh Halytskyi +- [PjonHL](https://github.com/rainerschoe/PjonHL) - PjonHL is a highlevel wrapper around PJON ### License All the software included in this project is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. [Licensed](https://github.com/gioblu/PJON/blob/master/LICENSE.md) under the Apache License, Version 2.0. PJON® and its brand are registered trademarks, property of [PJON Technologies srl](https://www.pjon-technologies.com/) From 948e79df531fdc4627730f88fe9ee60e9cc85bd3 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 10 Feb 2022 22:12:18 +0100 Subject: [PATCH 283/323] obvious paragraph removed --- LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.md b/LICENSE.md index ecdf65d4f6..8093feae75 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -All the software included in this project is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. All specifications, all related software implementations and documentation released as a part of this repository are and will always remain free for personal, educational, experimental and commercial purposes. +All the software included in this project is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. Giovanni Blu Mitolo (gioscarab@gmail.com) Copyright 2010-2021 From 3dcdc32b75d3925721e38cdcab42d38f36ff5c3b Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 10 Feb 2022 22:15:48 +0100 Subject: [PATCH 284/323] Shorter initial description in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 745bc269a4..0f23cbfa6d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## PJON 13.0 -PJON® (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media network protocol. It proposes a new Open Standard, it is designed as a framework and implements a totally software-defined network protocol stack that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). +PJON® (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media, software-define network protocol that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). [![Get PJON bus id](https://img.shields.io/badge/get-PJON%20bus%20id-lightgrey.svg)](http://www.pjon.org/get-bus-id.php) [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) From cceb79f43e3a39895b742ea780a47f46a0715a30 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 10 Feb 2022 22:16:16 +0100 Subject: [PATCH 285/323] typo fixed in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0f23cbfa6d..2505491a06 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## PJON 13.0 -PJON® (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media, software-define network protocol that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). +PJON® (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media, software-defined network protocol that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). [![Get PJON bus id](https://img.shields.io/badge/get-PJON%20bus%20id-lightgrey.svg)](http://www.pjon.org/get-bus-id.php) [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) From 3634099d6a6c4de4dd6e56438d7521c1e3f3d15a Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 10 Feb 2022 22:31:00 +0100 Subject: [PATCH 286/323] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2505491a06..5a5d0ccacb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## PJON 13.0 +## PJON 13.1 PJON® (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media, software-defined network protocol that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). [![Get PJON bus id](https://img.shields.io/badge/get-PJON%20bus%20id-lightgrey.svg)](http://www.pjon.org/get-bus-id.php) From 2db76ac20be37072920ee2c533292465e07f60cf Mon Sep 17 00:00:00 2001 From: D O Date: Thu, 10 Feb 2022 22:39:04 +0100 Subject: [PATCH 287/323] version update, copyright update --- LICENSE.md | 2 +- library.json | 2 +- library.properties | 2 +- .../obsolete/PJON-dynamic-addressing-specification-v0.1.md | 2 +- .../PJON-protocol-acknowledge-specification-v0.1.md | 2 +- specification/obsolete/PJON-protocol-specification-v0.1.md | 2 +- specification/obsolete/PJON-protocol-specification-v0.2.md | 2 +- specification/obsolete/PJON-protocol-specification-v0.3.md | 2 +- specification/obsolete/PJON-protocol-specification-v1.0.md | 2 +- specification/obsolete/PJON-protocol-specification-v1.1.md | 2 +- src/PJON.h | 6 +++--- src/PJONDefines.h | 6 +++--- src/PJONDynamicRouter.h | 6 +++--- src/PJONInteractiveRouter.h | 6 +++--- src/PJONLocal.h | 6 +++--- src/PJONRouter.h | 6 +++--- src/PJONSimpleSwitch.h | 6 +++--- src/PJONSwitch.h | 6 +++--- src/PJONVirtualBusRouter.h | 6 +++--- src/strategies/AnalogSampling/AnalogSampling.h | 2 +- src/strategies/Any/Any.h | 2 +- src/strategies/Any/StrategyLink.h | 2 +- src/strategies/Any/StrategyLinkBase.h | 2 +- .../specification/obsolete/PJDLR-specification-v1.0.md | 2 +- .../specification/obsolete/PJDLR-specification-v1.1.md | 2 +- src/strategies/SoftwareBitBang/SoftwareBitBang.h | 2 +- src/strategies/SoftwareBitBang/Timing.h | 2 +- .../specification/obsolete/PJDL-specification-v1.0.md | 2 +- .../specification/obsolete/PJDL-specification-v1.1.md | 2 +- .../padded-jittering-protocol-specification-v0.1.md | 2 +- 30 files changed, 48 insertions(+), 48 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 8093feae75..f21ac818e2 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ All the software included in this project is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Giovanni Blu Mitolo (gioscarab@gmail.com) Copyright 2010-2021 +Giovanni Blu Mitolo (gioscarab@gmail.com) Copyright 2010-2022 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at diff --git a/library.json b/library.json index d0c2608610..d88a37f3dd 100644 --- a/library.json +++ b/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/gioblu/PJON.git" }, - "version": "13.0", + "version": "13.1", "examples": [ "examples/*/*/*/*/*.ino", "examples/*/*/*/*/*.h", diff --git a/library.properties b/library.properties index 8da4f4de7d..21be0ea8bd 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=PJON -version=13.0 +version=13.1 author=Giovanni Blu Mitolo maintainer=Giovanni Blu Mitolo sentence=PJON is an open-source, multi-master, multi-media bus network protocol diff --git a/specification/obsolete/PJON-dynamic-addressing-specification-v0.1.md b/specification/obsolete/PJON-dynamic-addressing-specification-v0.1.md index 92173dbd26..741d766652 100644 --- a/specification/obsolete/PJON-dynamic-addressing-specification-v0.1.md +++ b/specification/obsolete/PJON-dynamic-addressing-specification-v0.1.md @@ -4,7 +4,7 @@ Milan, Italy - 02/10/2016 The PJON® dynamic addressing specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2021 All rights reserved +Copyright 2010-2022 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 5.2 and following diff --git a/specification/obsolete/PJON-protocol-acknowledge-specification-v0.1.md b/specification/obsolete/PJON-protocol-acknowledge-specification-v0.1.md index 6b212b7461..a73d3832b8 100644 --- a/specification/obsolete/PJON-protocol-acknowledge-specification-v0.1.md +++ b/specification/obsolete/PJON-protocol-acknowledge-specification-v0.1.md @@ -4,7 +4,7 @@ Milan, Italy - 17/10/2016 The PJON® protocol acknowledge specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2021 All rights reserved +Copyright 2010-2022 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 6.0 and following diff --git a/specification/obsolete/PJON-protocol-specification-v0.1.md b/specification/obsolete/PJON-protocol-specification-v0.1.md index 778bd57b76..d80e3eb8c6 100644 --- a/specification/obsolete/PJON-protocol-specification-v0.1.md +++ b/specification/obsolete/PJON-protocol-specification-v0.1.md @@ -3,7 +3,7 @@ /* Milan, Italy - 10/04/2010 The PJON® protocol specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved Related work: https://github.com/gioblu/PJON Compliant implementation versions: PJON 1.0-3.0-beta diff --git a/specification/obsolete/PJON-protocol-specification-v0.2.md b/specification/obsolete/PJON-protocol-specification-v0.2.md index 03e45e0756..f11509b8d1 100644 --- a/specification/obsolete/PJON-protocol-specification-v0.2.md +++ b/specification/obsolete/PJON-protocol-specification-v0.2.md @@ -3,7 +3,7 @@ /* Milan, Italy - 19/08/2015 The PJON® protocol specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 3.0-beta-3.0 diff --git a/specification/obsolete/PJON-protocol-specification-v0.3.md b/specification/obsolete/PJON-protocol-specification-v0.3.md index 6ee3c91ab1..73b1d8c377 100644 --- a/specification/obsolete/PJON-protocol-specification-v0.3.md +++ b/specification/obsolete/PJON-protocol-specification-v0.3.md @@ -3,7 +3,7 @@ /* Milan, Italy - 04/09/2016 The PJON® protocol specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 4.0-5.0 diff --git a/specification/obsolete/PJON-protocol-specification-v1.0.md b/specification/obsolete/PJON-protocol-specification-v1.0.md index 88c3dd585b..87d5d6c272 100644 --- a/specification/obsolete/PJON-protocol-specification-v1.0.md +++ b/specification/obsolete/PJON-protocol-specification-v1.0.md @@ -3,7 +3,7 @@ /* Milan, Italy - 3/10/2016 The PJON® protocol layer specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 6.0 and following diff --git a/specification/obsolete/PJON-protocol-specification-v1.1.md b/specification/obsolete/PJON-protocol-specification-v1.1.md index dda97df3b7..3c7f8bdc89 100644 --- a/specification/obsolete/PJON-protocol-specification-v1.1.md +++ b/specification/obsolete/PJON-protocol-specification-v1.1.md @@ -4,7 +4,7 @@ Milan, Italy - 28/03/2017 The PJON® protocol layer specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2021 All rights reserved +Copyright 2010-2022 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 6.0 and following diff --git a/src/PJON.h b/src/PJON.h index c14842e934..820139674d 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -1,9 +1,9 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 13.0 + |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -43,7 +43,7 @@ Compatible tools: This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONDefines.h b/src/PJONDefines.h index ab60ac7ea3..1de7eb09bc 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -1,9 +1,9 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 13.0 + |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -43,7 +43,7 @@ Compatible tools: This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONDynamicRouter.h b/src/PJONDynamicRouter.h index 6112f44cc6..b5ee3e1420 100644 --- a/src/PJONDynamicRouter.h +++ b/src/PJONDynamicRouter.h @@ -1,9 +1,9 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 13.0 + |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -22,7 +22,7 @@ dynamically based on observed packets from remote buses. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONInteractiveRouter.h b/src/PJONInteractiveRouter.h index 7c46578b0c..f4828cc00f 100644 --- a/src/PJONInteractiveRouter.h +++ b/src/PJONInteractiveRouter.h @@ -1,9 +1,9 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 13.0 + |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -32,7 +32,7 @@ receiver callback should be really fast. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONLocal.h b/src/PJONLocal.h index 18bd9f85ec..9666dc3bd6 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -1,9 +1,9 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 13.0 + |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -52,7 +52,7 @@ Compatible tools: This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONRouter.h b/src/PJONRouter.h index 320b3c1f50..08375f9a78 100644 --- a/src/PJONRouter.h +++ b/src/PJONRouter.h @@ -1,9 +1,9 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 13.0 + |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -23,7 +23,7 @@ buses. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONSimpleSwitch.h b/src/PJONSimpleSwitch.h index db7f8cdea1..95aa4d4bad 100644 --- a/src/PJONSimpleSwitch.h +++ b/src/PJONSimpleSwitch.h @@ -1,9 +1,9 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 13.0 + |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -38,7 +38,7 @@ enabling receivers on shared buses to reply back to the local bus. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONSwitch.h b/src/PJONSwitch.h index 6efcd0b74b..6f22f71cda 100644 --- a/src/PJONSwitch.h +++ b/src/PJONSwitch.h @@ -1,9 +1,9 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 13.0 + |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -22,7 +22,7 @@ between buses of different strategies using the Any strategy. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONVirtualBusRouter.h b/src/PJONVirtualBusRouter.h index 4517df127e..2cb3f5d163 100644 --- a/src/PJONVirtualBusRouter.h +++ b/src/PJONVirtualBusRouter.h @@ -1,9 +1,9 @@ /*-O//\ __ __ |-gfo\ |__| | | | |\ | ® - |!y°o:\ | __| |__| | \| 13.0 + |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -30,7 +30,7 @@ and reducing traffic. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2021 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/AnalogSampling/AnalogSampling.h b/src/strategies/AnalogSampling/AnalogSampling.h index e440aff4c6..501502d5db 100644 --- a/src/strategies/AnalogSampling/AnalogSampling.h +++ b/src/strategies/AnalogSampling/AnalogSampling.h @@ -31,7 +31,7 @@ necessary to tweak timing constants in Timing.h. ___________________________________________________________________________ - Copyright 2010-2021 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2022 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/Any/Any.h b/src/strategies/Any/Any.h index 42a67b5b9c..94c8e04f16 100644 --- a/src/strategies/Any/Any.h +++ b/src/strategies/Any/Any.h @@ -7,7 +7,7 @@ Proposed and developed by Fred Larsen ___________________________________________________________________________ - Copyright 2010-2021 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2022 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/Any/StrategyLink.h b/src/strategies/Any/StrategyLink.h index 9f7683591c..3f140c0a76 100644 --- a/src/strategies/Any/StrategyLink.h +++ b/src/strategies/Any/StrategyLink.h @@ -4,7 +4,7 @@ Proposed and developed by Fred Larsen ___________________________________________________________________________ - Copyright 2010-2021 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2022 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/Any/StrategyLinkBase.h b/src/strategies/Any/StrategyLinkBase.h index 138b372c66..41cf5e3a4d 100644 --- a/src/strategies/Any/StrategyLinkBase.h +++ b/src/strategies/Any/StrategyLinkBase.h @@ -4,7 +4,7 @@ Proposed and developed by Fred Larsen ___________________________________________________________________________ - Copyright 2010-2021 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2022 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.0.md b/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.0.md index c9ade58622..fde7c4eea2 100644 --- a/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.0.md +++ b/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.0.md @@ -3,7 +3,7 @@ /* Milan, Italy - 18/01/2017 PJDLR (Padded jittering data link) specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 7.0-7.1 diff --git a/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.1.md b/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.1.md index 5d6440977b..07696c4db4 100644 --- a/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.1.md +++ b/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.1.md @@ -4,7 +4,7 @@ Milan, Italy - 31/03/2017 PJDLR (Padded jittering data link) specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2021 All rights reserved +Copyright 2010-2022 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 8.0 and following diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index 122e29efce..4347aa93c8 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -5,7 +5,7 @@ Compliant with PJDL (Padded Jittering Data Link) specification v5.0 ___________________________________________________________________________ - Copyright 2010-2021 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2022 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index 9e9aa81daa..f679601cce 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -1,6 +1,6 @@ /* PJON SoftwareBitBang strategy Transmission Timing table - Copyright 2010-2021, Giovanni Blu Mitolo All rights reserved. + Copyright 2010-2022, Giovanni Blu Mitolo All rights reserved. Often timing in two different machines do not match, code execution time can variate and time measurements are not perfectly equal. diff --git a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.0.md b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.0.md index 6b78bfd847..b893859c66 100644 --- a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.0.md +++ b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.0.md @@ -3,7 +3,7 @@ /* Milan, Italy - 10/04/2010 PJDL (Padded jittering data link) specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 6.0-7.1 diff --git a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.1.md b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.1.md index 309863f4f6..1711718a3e 100644 --- a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.1.md +++ b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.1.md @@ -4,7 +4,7 @@ Milan, Italy - 31/03/2017 PJDL (Padded jittering data link) specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2021 All rights reserved +Copyright 2010-2022 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 8.0 and following diff --git a/src/strategies/SoftwareBitBang/specification/obsolete/padded-jittering-protocol-specification-v0.1.md b/src/strategies/SoftwareBitBang/specification/obsolete/padded-jittering-protocol-specification-v0.1.md index 5b178c9a3c..5fb9abbbfb 100644 --- a/src/strategies/SoftwareBitBang/specification/obsolete/padded-jittering-protocol-specification-v0.1.md +++ b/src/strategies/SoftwareBitBang/specification/obsolete/padded-jittering-protocol-specification-v0.1.md @@ -3,7 +3,7 @@ /* Milan, Italy - 10/04/2010 The Padded jittering data link layer specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2021 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 1.0-5.0 From 1be4b1587014180da3393e88c2458bbd0e8e9d22 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Sat, 19 Feb 2022 23:55:59 +0100 Subject: [PATCH 288/323] fixed comments of header bits --- src/PJONDefines.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 1de7eb09bc..8658baec7e 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -97,26 +97,26 @@ limitations under the License. */ 1 - Shared network */ #define PJON_MODE_BIT 0B00000001 /* 0 - No info inclusion - 1 - Local: Sender device id included - Shared: Sender device id + Sender bus id */ + 1 - Local: Sender device id included (+8 bits) + Shared: Sender device id + bus id (+40 bits) */ #define PJON_TX_INFO_BIT 0B00000010 /* 0 - Synchronous acknowledgement disabled 1 - Synchronous acknowledgement enabled */ #define PJON_ACK_REQ_BIT 0B00000100 /* 0 - MAC address inclusion disabled - 1 - MAC address inclusion enabled (2x 48 bits) */ + 1 - MAC address inclusion enabled (+96 bits) */ #define PJON_MAC_BIT 0B00001000 -/* 0 - No port id contained - 1 - Port id contained (2 bytes integer) */ +/* 0 - Port id not included + 1 - Port id included (+16 bits) */ #define PJON_PORT_BIT 0B00010000 -/* 0 - CRC8 (1 byte) included at the end of the packet - 1 - CRC32 (4 bytes) included at the end of the packet */ +/* 0 - CRC8 (8 bits) included + 1 - CRC32 (32 bits) included */ #define PJON_CRC_BIT 0B00100000 -/* 0 - 1 byte long (max 255 bytes) - 1 - 2 bytes long (max 65535 bytes) */ +/* 0 - 8 bits length (max packet length 255 bytes) + 1 - 16 bits length (max packet length 65535 bytes) */ #define PJON_EXT_LEN_BIT 0B01000000 -/* 0 - Packet id not present - 1 - Packet id present */ +/* 0 - Packet id not included + 1 - Packet id included (+16 bits) */ #define PJON_PACKET_ID_BIT 0B10000000 /* Errors: */ From 5f790b3c05a63a0c2854a72ad66d9566e388ae56 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Mon, 25 Apr 2022 23:09:49 +0200 Subject: [PATCH 289/323] Missing encryption in ESPNOW activated (https://github.com/gioblu/PJON/issues/415) --- src/interfaces/ARDUINO/ESPNOWHelper.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/interfaces/ARDUINO/ESPNOWHelper.h b/src/interfaces/ARDUINO/ESPNOWHelper.h index ed25ce60cf..abec9d46ef 100644 --- a/src/interfaces/ARDUINO/ESPNOWHelper.h +++ b/src/interfaces/ARDUINO/ESPNOWHelper.h @@ -116,12 +116,11 @@ class ENHelper { memset(peer, 0, sizeof(esp_now_peer_info_t)); peer->channel = _channel; peer->ifidx = ESPNOW_WIFI_IF; - if(IS_BROADCAST_ADDR(mac_addr)) - peer->encrypt = false; - // else { - // peer->encrypt = true; - // memcpy(peer->lmk, _esp_pmk, 16); - // } + if(IS_BROADCAST_ADDR(mac_addr)) peer->encrypt = false; + else { + peer->encrypt = true; + memcpy(peer->lmk, _esp_pmk, 16); + } memcpy(peer->peer_addr, mac_addr, ESP_NOW_ETH_ALEN); ESP_ERROR_CHECK(esp_now_add_peer(peer)); free(peer); From ec9dc80d254605da06192b10be15f2e71bb7db39 Mon Sep 17 00:00:00 2001 From: alastaira Date: Fri, 4 Nov 2022 12:03:20 +0000 Subject: [PATCH 290/323] Update ESPNOWHelper.h Fixed broken wifi_interface_t enums that were introduced in breaking change in esp32 core v1.0.5 --- src/interfaces/ARDUINO/ESPNOWHelper.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/interfaces/ARDUINO/ESPNOWHelper.h b/src/interfaces/ARDUINO/ESPNOWHelper.h index abec9d46ef..0de94b85d8 100644 --- a/src/interfaces/ARDUINO/ESPNOWHelper.h +++ b/src/interfaces/ARDUINO/ESPNOWHelper.h @@ -29,10 +29,10 @@ static const char *TAG = "espnow"; It is configured in menuconfig. */ #if CONFIG_STATION_MODE #define ESPNOW_WIFI_MODE WIFI_MODE_STA - #define ESPNOW_WIFI_IF ESP_IF_WIFI_STA + #define ESPNOW_WIFI_IF WIFI_IF_STA #else #define ESPNOW_WIFI_MODE WIFI_MODE_AP - #define ESPNOW_WIFI_IF ESP_IF_WIFI_AP + #define ESPNOW_WIFI_IF WIFI_IF_AP #endif #define ESPNOW_MAX_PACKET 250 From 8b3480b70c2c544300be6733fb1190abd7844410 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 24 Nov 2022 18:32:42 +0100 Subject: [PATCH 291/323] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a5d0ccacb..92832d223f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ ## PJON 13.1 PJON® (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media, software-defined network protocol that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). -[![Get PJON bus id](https://img.shields.io/badge/get-PJON%20bus%20id-lightgrey.svg)](http://www.pjon.org/get-bus-id.php) +**I recently left the domain expire because I am too busy with work and I cannot maintain the website anymore. The domain is now property of someone else, I am not affiliated with them, furthermore the website does not contain any information about PJON. If you still want to check out the website's information you can use the wayback machine.** + [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ### Why PJON? From 5cdc62eb04dda41b3280a59c1acfa0bb2f4d9cea Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 24 Nov 2022 18:33:24 +0100 Subject: [PATCH 292/323] Update library.json --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index d88a37f3dd..5a39b04d06 100644 --- a/library.json +++ b/library.json @@ -1,7 +1,7 @@ { "name": "PJON", "description": "PJON is an open-source, multi-master, multi-media network protocol stack", - "homepage": "https://www.pjon.org", + "homepage": "", "keywords": "pjon, communication, bus, protocol, network, multimaster, iot, ethernet, wifi, tcp, udp, usb, rs232, rs485, ask, fsk, ook, pjdl, pjdlr, pjdls, lora, arduino, esp8266, esp32, teensy, attiny, windows, linux, apple, android", "license": "Apache-2.0", "authors": From 9999d34d36b7d8cc7160d865471b4f8f38261156 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 24 Nov 2022 18:40:48 +0100 Subject: [PATCH 293/323] Update addressing.md --- documentation/addressing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/addressing.md b/documentation/addressing.md index 33c6e4ad13..2433dc7be2 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -52,7 +52,7 @@ The device identifier of an object can be read after instantiation using `device ### Shared mode -if the medium used is private and not accessible from the outside world (wired network in home, business, industry) bus ids can be used arbitrarily without any risk of collision; if instead the network uses a shared medium, for example on unlicensed radio frequencies with [ThroughLoRa](/src/strategies/ThroughLoRa), it is strongly suggested to request a unique PJON bus id [here](http://www.pjon.org/get-bus-id.php) to avoid collisions. +if the medium used is private and not accessible from the outside world (wired network in home, business, industry) bus ids can be used arbitrarily without any risk of collision; if instead the network uses a shared medium, for example on unlicensed radio frequencies with [ThroughLoRa](/src/strategies/ThroughLoRa). Instantiation in shared mode: ```cpp From 0fd6ecf42fefc908eb7fd32a72c2187e31c6b521 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 24 Nov 2022 18:41:29 +0100 Subject: [PATCH 294/323] Update PJON-dynamic-addressing-specification-v3.0.md --- .../obsolete/PJON-dynamic-addressing-specification-v3.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/obsolete/PJON-dynamic-addressing-specification-v3.0.md b/specification/obsolete/PJON-dynamic-addressing-specification-v3.0.md index 826def1d1b..c8dd78d773 100644 --- a/specification/obsolete/PJON-dynamic-addressing-specification-v3.0.md +++ b/specification/obsolete/PJON-dynamic-addressing-specification-v3.0.md @@ -36,7 +36,7 @@ _______|________________|___________| BUS ID 0.0.0.1 | | 0.0.8.1.1 | | 0.0.8.121.1 | |_____________| |_____________| ``` -Regardless of the master or the network addresses used by the network layer, slaves remain uniquely identified by their own device address. In an isolated scenario device addresses can be generated and assigned as required. If the application is connected to a shared medium where collisions with other systems may occur, it is strongly suggested to request a unique device address here: [https://www.pjon.org/get-device-address.php](https://www.pjon.org/get-device-address.php). +Regardless of the master or the network addresses used by the network layer, slaves remain uniquely identified by their own device address. In an isolated scenario device addresses can be generated and assigned as required. If the application is connected to a shared medium where collisions with other systems may occur. #### Procedure All communication used to request and assign ids is transmitted using CRC32 on the `PJON_DYNAMIC_ADDRESSING_PORT` port (decimal 1). Masters routinely broadcast a `PJON_ID_DISCOVERY` (decimal 200) advertisement to let slaves be aware of their presence. From 428d463e2657d92bbac366bf38a948959572b994 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 24 Nov 2022 18:42:15 +0100 Subject: [PATCH 295/323] Update README.md --- examples/RPI/Local/ThroughSerial/BlinkWithResponse/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/RPI/Local/ThroughSerial/BlinkWithResponse/README.md b/examples/RPI/Local/ThroughSerial/BlinkWithResponse/README.md index 6aeef65c4e..39e00707a6 100644 --- a/examples/RPI/Local/ThroughSerial/BlinkWithResponse/README.md +++ b/examples/RPI/Local/ThroughSerial/BlinkWithResponse/README.md @@ -7,8 +7,6 @@ To correctly receive data on Raspberry Pi it may be necessary to disable the ser Connect the Serial GPIO TX and RX of your Raspberry Pi with an Arduino compatible device (crossing the channels) through a level shifter not to damage the 3v3 rpi serial port. -![image](http://www.pjon.org/assets/images/PJON-RPI-UNO-level-shifter.jpg) - To compile the program it is necessary to reach with the terminal the `PJON/examples/RPI/Local/ThroughSerial/BlinkWithResponse/` directory and type `make`. Once the program is compiled you should see a new file called `Transmitter`. Typing `sudo ./Transmitter` the program is executed and some logging info should appear. From 9fd6d0dedf58bfed58bd15a343b32943b6ab6716 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 24 Nov 2022 18:42:55 +0100 Subject: [PATCH 296/323] Update README.md --- examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/README.md b/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/README.md index 5b89811c35..c34e48ecae 100644 --- a/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/README.md +++ b/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/README.md @@ -4,8 +4,6 @@ If in your case it is missing, type `sudo apt-get install wiringPi` Connect the Serial GPIO TX and RX of your Raspberry Pi with an Arduino compatible device (crossing the channels) through a level shifter not to damage the 3v3 rpi serial port. -![image](http://www.pjon.org/assets/images/PJON-RPI-UNO-level-shifter.jpg) - To correctly receive data on Raspberry Pi it may be necessary to disable the serial console, accessing as root to `boot/cmdline.txt` and removing `console=ttyAMA0, 115200` or `console=serial0, 115200` if present. To compile the program it is necessary to reach with the terminal the `PJON/examples/RPI/Local/ThroughSerial/BlinkTestTransmitter/` directory and type `make`. Once the program is compiled you should see a new file called `Transmitter`. Typing `sudo ./Transmitter` the program is executed and some logging info should appear. From 519b5003cfccb4dd5b4fd089934962168d4a1188 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 24 Nov 2022 18:43:11 +0100 Subject: [PATCH 297/323] Update README.md --- examples/RPI/Local/ThroughSerial/BlinkTestReceiver/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/README.md b/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/README.md index d94d59f0b2..4cf08d3d9e 100644 --- a/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/README.md +++ b/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/README.md @@ -4,8 +4,6 @@ If in your case it is missing, type `sudo apt-get install wiringPi` Connect the Serial GPIO TX and RX of your Raspberry Pi with an Arduino compatible device (crossing the channels) through a level shifter not to damage the 3v3 rpi serial port. -![image](http://www.pjon.org/assets/images/PJON-RPI-UNO-level-shifter.jpg) - To correctly receive data on Raspberry Pi it may be necessary to disable the serial console, accessing as root to `boot/cmdline.txt` and removing `console=ttyAMA0, 115200` or `console=serial0, 115200` if present. To compile the program it is necessary to reach in the terminal the `PJON/examples/RPI/Local/ThroughSerial/BlinkTestReceiver/` directory and type `make`. Once the program is compiled you should see a new file called `Receiver`. Typing `sudo ./Receiver` the program is executed and some logging info should appear. From 856016c0d2f5dee55b7a2237c6413d284e59e2c9 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 24 Nov 2022 18:45:12 +0100 Subject: [PATCH 298/323] Update library.json --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index 5a39b04d06..ca7098ed7d 100644 --- a/library.json +++ b/library.json @@ -1,7 +1,7 @@ { "name": "PJON", "description": "PJON is an open-source, multi-master, multi-media network protocol stack", - "homepage": "", + "homepage": "https://github.com/gioblu/PJON", "keywords": "pjon, communication, bus, protocol, network, multimaster, iot, ethernet, wifi, tcp, udp, usb, rs232, rs485, ask, fsk, ook, pjdl, pjdlr, pjdls, lora, arduino, esp8266, esp32, teensy, attiny, windows, linux, apple, android", "license": "Apache-2.0", "authors": From 401951ac8b10b2cefe2dd07506fcb03abc3209a9 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 29 Dec 2022 16:26:28 +0100 Subject: [PATCH 299/323] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 92832d223f..ee5431825a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ ## PJON 13.1 PJON® (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media, software-defined network protocol that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). -**I recently left the domain expire because I am too busy with work and I cannot maintain the website anymore. The domain is now property of someone else, I am not affiliated with them, furthermore the website does not contain any information about PJON. If you still want to check out the website's information you can use the wayback machine.** - [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ### Why PJON? From f8649dcf3e0f092005c33a98d2f0307c8bfc29f4 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 29 Dec 2022 16:27:26 +0100 Subject: [PATCH 300/323] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ee5431825a..c7101c1f7d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## PJON 13.1 -PJON® (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media, software-defined network protocol that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). +PJON(Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media, software-defined network protocol that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) @@ -42,7 +42,7 @@ Feel free to send a pull request sharing something you have made that could help - [PjonHL](https://github.com/rainerschoe/PjonHL) - PjonHL is a highlevel wrapper around PJON ### License -All the software included in this project is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. [Licensed](https://github.com/gioblu/PJON/blob/master/LICENSE.md) under the Apache License, Version 2.0. PJON® and its brand are registered trademarks, property of [PJON Technologies srl](https://www.pjon-technologies.com/) +All the software included in this project is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. [Licensed](https://github.com/gioblu/PJON/blob/master/LICENSE.md) under the Apache License, Version 2.0. ### Safety warning When testing PJON, extreme care must be taken to avoid any danger. Consider that the implementation is experimental and may not behave as expected, use it at your own risk. When devices are connected to AC power you are exposed to a high chance of being electrocuted if hardware is not installed carefully and properly. If you are not experienced enough ask the support of a skilled technician and consider that many countries prohibit uncertified installations. When testing a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus [interference mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines must be followed. When experimenting with [AnalogSampling](/src/strategies/AnalogSampling) setup safety glasses must be worn and transceivers must be operated cautiously to avoid potential eye injuries. Before testing [OverSampling](/src/strategies/OverSampling), [ThroughSerial](/src/strategies/ThroughSerial) or [ThroughLoRa](/src/strategies/ThroughLoRa) radio communication, be sure the frequency, power and hardware used complies with local laws. When connecting a local bus to the internet all devices must be considered potentially compromised, manipulated or remotely actuated against your will. It should be considered a good practice not to connect to the internet systems that may create a damage (fire, flood, data-leak) if hacked. From 9945f3287e0dea3492d84959e8428af6598b8a8f Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Thu, 29 Dec 2022 16:27:54 +0100 Subject: [PATCH 301/323] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c7101c1f7d..3070668898 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## PJON 13.1 -PJON(Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media, software-defined network protocol that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). +PJON (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media, software-defined network protocol that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) From 1d5854eb6f3475848679c041cce527df454d7001 Mon Sep 17 00:00:00 2001 From: jgOhYeah Date: Fri, 3 Jan 2025 17:31:30 +1100 Subject: [PATCH 302/323] LoRa prepare_response sends correct values rather than zeros, added optional reply delay --- src/strategies/ThroughLoRa/ThroughLora.h | 5 ++++- src/strategies/ThroughLoRa/Timing.h | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/strategies/ThroughLoRa/ThroughLora.h b/src/strategies/ThroughLoRa/ThroughLora.h index b92e129472..1cccf9493e 100644 --- a/src/strategies/ThroughLoRa/ThroughLora.h +++ b/src/strategies/ThroughLoRa/ThroughLora.h @@ -172,7 +172,7 @@ class ThroughLora { *data = LoRa.read(); data++; } - prepare_response(data, frameSize); + prepare_response(data - frameSize, frameSize); return frameSize; } else return PJON_FAIL; }; @@ -188,6 +188,9 @@ class ThroughLora { void send_response(uint8_t response) { if(response == PJON_ACK) { start_tx(); +#if TL_RESPONSE_DELAY != 0 + PJON_DELAY(TL_RESPONSE_DELAY); +#endif for(uint8_t i = 0; i < TL_RESPONSE_LENGTH; i++) send_byte(_response[i]); end_tx(); diff --git a/src/strategies/ThroughLoRa/Timing.h b/src/strategies/ThroughLoRa/Timing.h index dfe933b339..061b131bf5 100644 --- a/src/strategies/ThroughLoRa/Timing.h +++ b/src/strategies/ThroughLoRa/Timing.h @@ -35,6 +35,12 @@ #define TL_RESPONSE_TIME_OUT 100000 #endif +/* Set an optional delay (in ms) before responding if the receiver is particularly + slow at swapping between transmit and receive modes. */ +#ifndef TL_RESPONSE_DELAY + #define TL_RESPONSE_DELAY 0 +#endif + /* Maximum transmission attempts (re-transmission not supported) */ #ifndef TL_MAX_ATTEMPTS #define TL_MAX_ATTEMPTS 5 From 73b4f4a5566f975be3cf21fd092fc647cbd7ffcf Mon Sep 17 00:00:00 2001 From: jgOhYeah Date: Tue, 7 Jan 2025 14:19:24 +1100 Subject: [PATCH 303/323] Adding acknowledgement to documentation --- src/strategies/ThroughLoRa/README.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/strategies/ThroughLoRa/README.md b/src/strategies/ThroughLoRa/README.md index 0db79c3497..fed6d39286 100644 --- a/src/strategies/ThroughLoRa/README.md +++ b/src/strategies/ThroughLoRa/README.md @@ -13,6 +13,7 @@ This strategy is a wrapper around [Arduino LoRa library](https://github.com/san - ATmega2560 16MHz (Arduino Mega) - ATmega16u4/32u4 16MHz (Arduino Leonardo) - STM32F103 ([Blue Pill](http://wiki.stm32duino.com/index.php?title=Blue_Pill)) +- ESP32-based boards ### Getting started 1. Pass the `ThroughLora` type as PJON template parameter to instantiate a PJON object ready to communicate through this Strategy. @@ -36,6 +37,9 @@ bus.strategy.setFrequency(868100000UL); //initialize 868 MHZ module | [HopeRF](http://www.hoperf.com/) | [RFM95W](http://www.hoperf.com/rf_transceiver/lora/RFM95W.html) / [RFM96W](http://www.hoperf.com/rf_transceiver/lora/RFM96W.html) / [RFM98W](http://www.hoperf.com/rf_transceiver/lora/RFM98W.html) | | [Modtronix](http://modtronix.com/) | [inAir4](http://modtronix.com/inair4.html) / [inAir9](http://modtronix.com/inair9.html) / [inAir9B](http://modtronix.com/inair9b.html) | | [Adafruit](https://www.adafruit.com/) | [Adafruit Feather 32u4 LoRa Radio (RFM9x)](https://learn.adafruit.com/adafruit-feather-32u4-radio-with-lora-radio-module/overview) | +| [Ai-Thinker](https://en.ai-thinker.com/index.html) | Ra01 / [Ra02](https://en.ai-thinker.com/pro_view-57.html) (SX1278 based) + +See the [Arduino LoRa readme](https://github.com/sandeepmistry/arduino-LoRa) for a more complete list of modules. ### Hardware connection | General Wiring | Arduino | @@ -51,11 +55,12 @@ bus.strategy.setFrequency(868100000UL); //initialize 868 MHZ module - `NSS`, `NRESET`, and `DIO0` pins can be changed by using `PJON.strategy.setPins(ss, reset, dio0)`. - `DIO0` pin is optional, it is only needed for receive callback mode. If `DIO0` pin is used, it **must** be interrupt capable via [`attachInterrupt(...)`](https://www.arduino.cc/en/Reference/AttachInterrupt). +- Some boards support custom pins for `SCK`, `MISO` and `MOSI` (ESP32 series for example). These can be set using `SPI.begin(sck, miso, mosi)` before calling `PJON.strategy.setFrequency(frequency)`. ### Usage Example Here are listed basic examples of a transmitter and receiver code. After you include the necessary code to initialize the Lora module you can use the normal PJON functions to handle data communication. -Keep in mind that to use the LoRa startegy you must download the [Arduino LoRa library](https://github.com/sandeepmistry/arduino-LoRa). +Keep in mind that to use the LoRa strategy you must download the [Arduino LoRa library](https://github.com/sandeepmistry/arduino-LoRa). More examples can be found in https://github.com/gioblu/PJON/tree/master/examples/ARDUINO/Local/ThroughLoRa @@ -217,5 +222,22 @@ byte b = bus.strategy.getRandom(); ``` Generate a random byte, based on the Wideband RSSI measurement. +### Acknowledgement +Acknowledgement allows the sendor to request that the receiver acknowledge reception of a message so that multiple transmission attempts can be made if required. Limits on the allowed transmission duty cycle in various parts of the world, power budgets, message importance and network throughput may affect whether acknowledgement is required for some or all messages. Acknowledgement can be enabled or disabled for the sender using: +```cpp +bus.set_acknowledge(true/false); +``` +Depending on the speed of the hardware on either end and the bandwidth and spreading factor configured, it may be necessary to increase the time the sender will wait for an acknowledgement before timing out. This can be set by defining `TL_RESPONSE_TIME_OUT` prior to including the header file. +```cpp +#define TL_RESPONSE_TIME_OUT 500000 // Timeout in us. Default is 100000 +#include +``` + +In some edge cases the sender may be significantly slower than the receiver at switching between transmit and receive modes. This could result in the receiver sending a response before the sender has a chance to listen for it. A delay can be added between receiving a packet and acknowledging it by defining `TL_RESPONSE_DELAY` prior to including the header file. Keep this as short as possible. +```cpp +#define TL_RESPONSE_DELAY 30 // Time delay between receiving a packet and sending a response in ms. Default is 0. +#define TL_RESPONSE_TIME_OUT 500000 // Timeout in us. Default is 100000 +#include +``` ### Safety warning In all cases, when installing or maintaining a PJON network, extreme care must be taken to avoid any danger. Before any practical test or hardware purchase for a wireless [ThroughLoRa](/src/strategies/ThroughLoRa) radio setup, compliance with government requirements and regulations must be ensured. From a3c4001cdda7958395e5c086dabd2569a5b7171c Mon Sep 17 00:00:00 2001 From: gioblu Date: Sun, 1 Jun 2025 22:19:14 +0200 Subject: [PATCH 304/323] minor docs and codestyle fix --- src/strategies/ThroughLoRa/README.md | 2 +- src/strategies/ThroughLoRa/ThroughLora.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategies/ThroughLoRa/README.md b/src/strategies/ThroughLoRa/README.md index fed6d39286..42ed4f1c9e 100644 --- a/src/strategies/ThroughLoRa/README.md +++ b/src/strategies/ThroughLoRa/README.md @@ -235,7 +235,7 @@ Depending on the speed of the hardware on either end and the bandwidth and sprea In some edge cases the sender may be significantly slower than the receiver at switching between transmit and receive modes. This could result in the receiver sending a response before the sender has a chance to listen for it. A delay can be added between receiving a packet and acknowledging it by defining `TL_RESPONSE_DELAY` prior to including the header file. Keep this as short as possible. ```cpp -#define TL_RESPONSE_DELAY 30 // Time delay between receiving a packet and sending a response in ms. Default is 0. +#define TL_RESPONSE_DELAY 30 // Delay between receiving a packet and sending a response in ms. (default 0) #define TL_RESPONSE_TIME_OUT 500000 // Timeout in us. Default is 100000 #include ``` diff --git a/src/strategies/ThroughLoRa/ThroughLora.h b/src/strategies/ThroughLoRa/ThroughLora.h index 1cccf9493e..7684f971c7 100644 --- a/src/strategies/ThroughLoRa/ThroughLora.h +++ b/src/strategies/ThroughLoRa/ThroughLora.h @@ -188,9 +188,9 @@ class ThroughLora { void send_response(uint8_t response) { if(response == PJON_ACK) { start_tx(); -#if TL_RESPONSE_DELAY != 0 - PJON_DELAY(TL_RESPONSE_DELAY); -#endif + #if TL_RESPONSE_DELAY != 0 + PJON_DELAY(TL_RESPONSE_DELAY); + #endif for(uint8_t i = 0; i < TL_RESPONSE_LENGTH; i++) send_byte(_response[i]); end_tx(); From 0fb7fa4d2686b1f4ee1fe72285800abe56b3c5da Mon Sep 17 00:00:00 2001 From: gioblu Date: Sun, 1 Jun 2025 22:27:17 +0200 Subject: [PATCH 305/323] PJON-protocol-specification-v4.0 minor fix (removed obsolete unacceptable header config) --- specification/PJON-protocol-specification-v4.0.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index 6d50586e9e..dc7cb2a945 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -161,12 +161,10 @@ HEADER BITMAP 8. `PACKET ID` bit informs if the packet contains (value 1) or not (value 0) a 16 bits [packet id](/specification/PJON-protocol-specification-v4.0.md#packet-identification) Unacceptable header configuration states for standard transmission: -* `----1-0-` or `ACK MODE` bit high, and `TX INFO` bit low (requires transmitter info) * `-10-----` or `EXT. LENGTH` bit high and `CRC` bit low (forced CRC32 for length > 15) Unacceptable header configuration states for a broadcast transmission: * `-----1--` or `ACK` bit high (acknowledgement not supported if broadcasting) -* `----1---` or `ACK MODE` bit high (acknowledgement not supported if broadcasting) `-` symbol means irrelevant bit value From b7a69a7f4abfa12bf0e7cc0f5a0835b20900f015 Mon Sep 17 00:00:00 2001 From: gioblu Date: Sun, 1 Jun 2025 22:29:11 +0200 Subject: [PATCH 306/323] jgOhYeah acknowledgement added --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3070668898..11c53d639c 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Telecomunicación - [Universidad de Cantabria](https://web.unican.es/) (ES) ### Contribute Feel free to send a pull request sharing something you have made that could help, if you want to support this project you can also try to solve an [issue](https://github.com/gioblu/PJON/issues). Thanks to support, expertise, kindness and talent of the following contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: -[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen), [Julio Aguirre](https://github.com/jcallano), [Cimex97](https://github.com/Cimex97), [der-schne](https://github.com/der-schne), [porkyneal](https://github.com/porkyneal), [der-schne](https://github.com/der-schne) and [Rainer Schoenberger](https://github.com/rainerschoe). +[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen), [Julio Aguirre](https://github.com/jcallano), [Cimex97](https://github.com/Cimex97), [der-schne](https://github.com/der-schne), [porkyneal](https://github.com/porkyneal), [der-schne](https://github.com/der-schne), [Rainer Schoenberger](https://github.com/rainerschoe) and [jgOhYeah](https://github.com/jgOhYeah). ### Compliant tools - [ModuleInterface](https://github.com/fredilarsen/ModuleInterface) - easy config and value sync between IoT modules by Fred Larsen From 7615fadd7790b6ef673c5622717072671d9efab2 Mon Sep 17 00:00:00 2001 From: gioblu Date: Sun, 1 Jun 2025 22:35:18 +0200 Subject: [PATCH 307/323] Added PJON_IO macros for Uno WiFi Rev 2, Nano Every by @kuchendieb --- README.md | 2 +- src/interfaces/ARDUINO/PJON_IO.h | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 11c53d639c..e08754e31a 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Telecomunicación - [Universidad de Cantabria](https://web.unican.es/) (ES) ### Contribute Feel free to send a pull request sharing something you have made that could help, if you want to support this project you can also try to solve an [issue](https://github.com/gioblu/PJON/issues). Thanks to support, expertise, kindness and talent of the following contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: -[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen), [Julio Aguirre](https://github.com/jcallano), [Cimex97](https://github.com/Cimex97), [der-schne](https://github.com/der-schne), [porkyneal](https://github.com/porkyneal), [der-schne](https://github.com/der-schne), [Rainer Schoenberger](https://github.com/rainerschoe) and [jgOhYeah](https://github.com/jgOhYeah). +[Fred Larsen](https://github.com/fredilarsen), [Zbigniew Zasieczny](https://github.com/girgitt), [Matheus Garbelini](https://github.com/Matheus-Garbelini), [sticilface](https://github.com/sticilface), [Felix Barbalet](https://github.com/xlfe), [Oleh Halitskiy](https://github.com/Halytskyi), [fotosettore](https://github.com/fotosettore), [fabpolli](https://github.com/fabpolli), [Adrian Sławiński](https://github.com/4ib3r), [Osman Selçuk Aktepe](https://github.com/osman-aktepe), [Jorgen-VikingGod](https://github.com/Jorgen-VikingGod), [drtrigon](https://github.com/drtrigon), [Endre Karlson](https://github.com/ekarlso), [Wilfried Klaas](https://github.com/willie68), [budaics](https://github.com/budaics), [ibantxo](https://github.com/ibantxo), [gonnavis](https://github.com/gonnavis), [maxidroms83](https://github.com/maxidroms83), [Evgeny Dontsov](https://github.com/dontsovcmc), [zcattacz](https://github.com/zcattacz), [Valerii Koval](https://github.com/valeros), [Ivan Kravets](https://github.com/ivankravets), [Esben Soeltoft](https://github.com/EsbenSoeltoft), [Alex Grishin](https://github.com/240974a), [Andrew Grande](https://github.com/aperepel), [Michael Teeww](https://github.com/MichMich), [Paolo Paolucci](https://github.com/PaoloP74), [per1234](https://github.com/per1234), [Santiago Castro](https://github.com/bryant1410), [pacproduct](https://github.com/pacproduct), [elusive-code](https://github.com/elusive-code), [Emanuele Iannone](https://github.com/eiannone), [Christian Pointner](https://github.com/equinox0815), [Fabian Gärtner](https://github.com/TeeTrizZz), [Mauro Mombelli](https://github.com/MauroMombelli), [Remo Kallio](https://github.com/shacal), [hyndruide](https://github.com/hyndruide), [sigmaeo](https://github.com/sigmaeo), [filogranaf](https://github.com/filogranaf), [Maximiliano Duarte](https://github.com/domonetic), [Viktor Szépe](https://github.com/szepeviktor), [Shachar Limor](), [Pantovich](), [Mauro Zancarlin](), [Franketto](), [jzobac](), [DanRoad](), [fcastrovilli](https://github.com/fcastrovilli), [Andrei Volkau](https://github.com/andrei-volkau), [maniekq](https://github.com/maniekq), [DetAtHome](https://github.com/DetAtHome), [Michael Branson](https://github.com/mxbranson), [chestwood96](https://github.com/chestwood96), [Mattze96](https://github.com/Mattze96), [Steven Bense](https://github.com/justoke), [Jack Anderson](https://github.com/jdaandersj), [callalilychen](https://github.com/callalilychen), [Julio Aguirre](https://github.com/jcallano), [Cimex97](https://github.com/Cimex97), [der-schne](https://github.com/der-schne), [porkyneal](https://github.com/porkyneal), [der-schne](https://github.com/der-schne), [Rainer Schoenberger](https://github.com/rainerschoe), [jgOhYeah](https://github.com/jgOhYeah) and [kuchendieb](https://github.com/kuchendieb). ### Compliant tools - [ModuleInterface](https://github.com/fredilarsen/ModuleInterface) - easy config and value sync between IoT modules by Fred Larsen diff --git a/src/interfaces/ARDUINO/PJON_IO.h b/src/interfaces/ARDUINO/PJON_IO.h index a0c327509d..5bfb5d5c2a 100644 --- a/src/interfaces/ARDUINO/PJON_IO.h +++ b/src/interfaces/ARDUINO/PJON_IO.h @@ -10,6 +10,7 @@ List of supported MCUs: - ATmega8/88/168/328/1280/1284P/2560 (Duemilanove, Uno, Nano, Mini, Pro, Mega) - ATmega16U4/32U4 (Leonardo, Micro) + - ATmega4809 (Nano every, Uno WiFi Rev 2) - ATtiny44/84/44A/84A Added by Wilfried Klaas - ATtiny45/85 (Trinket, Digispark) - SAMD21G18A (Arduino Zero) Added by Esben Soeltoft 03/09/2016 @@ -177,6 +178,25 @@ inform the reader of their definition as macros in the global scope. #endif #endif +// --- Arduino Uno WiFi Rev 2, Nano Every --- +#if defined(__AVR_ATmega4809__) + #define PJON_IO_PIN_TO_PORT_REG(P) \ + (((P) == 2 || (P) == 7 ) ? &VPORTA.OUT : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.OUT : \ + ((P) == 4) ? &VPORTC.OUT : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.OUT : \ + ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.OUT : &VPORTF.OUT) + #define PJON_IO_PIN_TO_DDR_REG(P) \ + (((P) == 2 || (P) == 7 ) ? &VPORTA.DIR : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.DIR : \ + ((P) == 4) ? &VPORTC.DIR : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.DIR : \ + ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.DIR : &VPORTF.DIR) + #define PJON_IO_PIN_TO_PIN_REG(P) \ + (((P) == 2 || (P) == 7 ) ? &VPORTA.IN : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.IN : \ + ((P) == 4) ? &VPORTC.IN : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.IN : \ + ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.IN : &VPORTF.IN) + #define PJON_IO_PIN_TO_BIT(P) \ + (((P) == 2 || (P) == 9 || (P) == 11 || (P) == 17) ? 0 : ((P) == 7 || (P) == 10 || (P) == 12 || (P) == 16) ? 1 : \ + ((P) == 5 || (P) == 13 || (P) == 15 || (P) == 18) ? 2 : ((P) == 9 || (P) == 14 || (P) == 19) ? 3 : \ + ((P) == 6 || (P) == 20) ? 4 : ((P) == 3 || (P) == 21) ? 5 : 6 ) +#endif /* SAMD21G18A - Arduino Zero ---------------------------------------------- */ #if defined(__SAMD21G18A__) || defined(ARDUINO_SAM_ZERO) // Arduino Zero pins From 31937fd67fffbc6ca5bd04cd2472e4e556a836ee Mon Sep 17 00:00:00 2001 From: gioblu Date: Fri, 7 Nov 2025 16:05:48 +0100 Subject: [PATCH 308/323] typos fixed in various README files --- documentation/addressing.md | 10 +++++----- documentation/configuration.md | 4 ++-- src/strategies/SoftwareBitBang/README.md | 2 +- src/strategies/ThroughLoRa/README.md | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/documentation/addressing.md b/documentation/addressing.md index 2433dc7be2..312a64392f 100644 --- a/documentation/addressing.md +++ b/documentation/addressing.md @@ -24,7 +24,7 @@ PJON objects can operate in local or shared mode. The PJON protocol v4.0 in [loc ### Local mode -The simples way to instantiate PJON in local mode is the following: +The simplest way to instantiate PJON in local mode is as follows: ```cpp PJONSoftwareBitBang bus; ``` @@ -52,7 +52,7 @@ The device identifier of an object can be read after instantiation using `device ### Shared mode -if the medium used is private and not accessible from the outside world (wired network in home, business, industry) bus ids can be used arbitrarily without any risk of collision; if instead the network uses a shared medium, for example on unlicensed radio frequencies with [ThroughLoRa](/src/strategies/ThroughLoRa). +if the medium used is private and not accessible from the outside world (wired network in home, business, industry), bus ids can be used arbitrarily without any risk of collision; if instead the network uses a shared medium, for example on unlicensed radio frequencies with [ThroughLoRa](/src/strategies/ThroughLoRa). Instantiation in shared mode: ```cpp @@ -68,7 +68,7 @@ Use `get_bus_id` to get a pointer to the bus id used by the instance: memcpy(bus_id, bus.get_bus_id(bus_id), 4); // Copy bus id in bus_id ``` -The bus id can set after initialisation using `set_bus_id`: +The bus id can be set after initialisation using `set_bus_id`: ```cpp uint8_t bus_id[4] = {0, 0, 0, 1}; bus.set_bus_id(bus_id); // Set bus id @@ -87,7 +87,7 @@ uint8_t mac[6] = {1, 2, 3, 4, 5, 6}; PJONSoftwareBitBang bus(mac); // Local mode, device id PJON_NOT_ASSIGNED ``` -This instantiation sets the MAC address, the device id set to `PJON_NOT_ASSIGNED` or 255 but can be changed afterwards as required. Packets containing a recipient's MAC address that is not equal to the one configured are discarded. PJON can operate in both local and shared mode while including MAC addresses. The feature can be disabled using `includ_mac`: +This instantiation sets the MAC address, the device id set to `PJON_NOT_ASSIGNED` or 255 but can be changed afterwards as required. Packets containing a recipient's MAC address that is not equal to the one configured are discarded. PJON can operate in both local and shared mode while including MAC addresses. The feature can be disabled using `include_mac`: ```cpp bus.include_mac(false); @@ -100,7 +100,7 @@ Use `get_mac` to get a pointer to the mac address used by the instance: memcpy(mac, bus.get_mac(mac), 6); // Copy mac in variable ``` -The mac address can set after initialisation using `set_mac`: +The mac address can be set after initialisation using `set_mac`: ```cpp uint8_t mac[6] = {0, 0, 0, 0, 0, 1}; bus.set_mac(mac); // Set mac diff --git a/documentation/configuration.md b/documentation/configuration.md index 821a985184..dab04a7431 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -22,7 +22,7 @@ PJON uses predefined constants, setters and getters to support features and constraints configuration. ### Buffers configuration -Before including the library it is possible to define the length of its buffers defining the `PJON_MAX_PACKETS` and `PJON_PACKET_MAX_LENGTH` constants: +Before including the library, it is possible to define the length of its buffers by defining the `PJON_MAX_PACKETS` and `PJON_PACKET_MAX_LENGTH` constants: ```cpp #define PJON_MAX_PACKETS 1 #define PJON_PACKET_MAX_LENGTH 20 @@ -36,7 +36,7 @@ Strategies are classes that abstract the physical transmission of data. `PJON` u #include PJONSoftwareBitBang bus; ``` -In the example above the PJON object is instantiated using the [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) strategy. It is possible to instantiate more than one PJON object using different strategies in the same program: +In the example above, the PJON object is instantiated using the [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) strategy. It is possible to instantiate more than one PJON object using different strategies in the same program: ```cpp #include #include diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index 803729c9b5..f4efd6b1c9 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -85,7 +85,7 @@ void setup() { bus.strategy.set_pins(11, 12); } ``` -After the PJON object is defined with its strategy it is possible to set the communication pin accessing to the strategy present in the PJON instance. All the other necessary information is present in the general [Documentation](/documentation). +After the PJON object is defined with its strategy, it is possible to set the communication pin by accessing the strategy present in the PJON instance. All the other necessary information is present in the general [Documentation](/documentation). ### Why not interrupts? In the Arduino environment the use of libraries is really extensive and often the end user is not able to go over collisions. Very often a library is using hardware resources of the microcontroller, colliding with other libraries. This happens because in general Arduino boards have limited hardware resources. Software-defined bit-banging, is a stable and reliable solution that leads to "more predictable" results than interrupt driven procedures coexisting on limited microcontrollers without the developer and the end user knowing about it. diff --git a/src/strategies/ThroughLoRa/README.md b/src/strategies/ThroughLoRa/README.md index 42ed4f1c9e..b3c4a0e4f6 100644 --- a/src/strategies/ThroughLoRa/README.md +++ b/src/strategies/ThroughLoRa/README.md @@ -223,7 +223,7 @@ byte b = bus.strategy.getRandom(); Generate a random byte, based on the Wideband RSSI measurement. ### Acknowledgement -Acknowledgement allows the sendor to request that the receiver acknowledge reception of a message so that multiple transmission attempts can be made if required. Limits on the allowed transmission duty cycle in various parts of the world, power budgets, message importance and network throughput may affect whether acknowledgement is required for some or all messages. Acknowledgement can be enabled or disabled for the sender using: +Acknowledgement allows the sender to request that the receiver acknowledge reception of a message so that multiple transmission attempts can be made if required. Limits on the allowed transmission duty cycle in various parts of the world, power budgets, message importance and network throughput may affect whether acknowledgement is required for some or all messages. Acknowledgement can be enabled or disabled for the sender using: ```cpp bus.set_acknowledge(true/false); ``` From 21053687f169c19da2aa041688cf76624f13c85b Mon Sep 17 00:00:00 2001 From: gioblu Date: Fri, 7 Nov 2025 16:06:17 +0100 Subject: [PATCH 309/323] fixed typos in TCPHelper_POSIX.h --- src/interfaces/LINUX/TCPHelper_POSIX.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/interfaces/LINUX/TCPHelper_POSIX.h b/src/interfaces/LINUX/TCPHelper_POSIX.h index c83edeb26b..4c4ad75e72 100644 --- a/src/interfaces/LINUX/TCPHelper_POSIX.h +++ b/src/interfaces/LINUX/TCPHelper_POSIX.h @@ -118,7 +118,7 @@ class TCPHelperClient { read_timeout.tv_usec = 2000000; setsockopt(_fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&read_timeout, sizeof read_timeout); #endif - // Disable Nagles algorith because we are sending small packets and waiting for reply + // Disable Nagles algorithm because we are sending small packets and waiting for reply set_nodelay(true); } return connected; @@ -201,7 +201,7 @@ class TCPHelperClient { read_timeout.tv_usec = 2000000; setsockopt(_fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&read_timeout, sizeof read_timeout); #endif - // Disable Nagles algorith because we are sending small packets and waiting for reply + // Disable Nagles algorithm because we are sending small packets and waiting for reply set_nodelay(true); return 1; @@ -312,7 +312,7 @@ class TCPHelperServer { read_timeout.tv_usec = 2000000; setsockopt(connected_fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&read_timeout, sizeof read_timeout); #endif - // Disable Nagles algorith because we are sending small packets and waiting for reply + // Disable Nagles algorithm because we are sending small packets and waiting for reply int flag = 1; setsockopt(connected_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof flag); } From 028abc836824c9642182ebd42b956ad0a050018d Mon Sep 17 00:00:00 2001 From: gioblu Date: Fri, 7 Nov 2025 16:06:40 +0100 Subject: [PATCH 310/323] fixed typos in zephyr config --- zephyr/CMakeLists.txt | 4 ++-- zephyr/Kconfig | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 85523173c2..ace991dd62 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -14,10 +14,10 @@ if(CONFIG_PJON_STRATEGY_THROUGHSERIAL) target_compile_definitions(PJON INTERFACE TS_INITIAL_DELAY=CONFIG_TS_INITIAL_DELAY TS_COLLISION_DELAY=CONFIG_TS_COLLISION_DELAY -TS_RESONSE_TIME_OUT=CONFIG_TS_RESONSE_TIME_OUT +TS_RESPONSE_TIME_OUT=CONFIG_TS_RESPONSE_TIME_OUT TS_TIME_IN=CONFIG_TS_TIME_IN TS_BYTE_TIME_OUT=CONFIG_TS_BYTE_TIME_OUT -TS_MAX_ATTEMTS=CONFIG_TS_MAX_ATTEMTS +TS_MAX_ATTEMPTS=CONFIG_TS_MAX_ATTEMPTS TS_BACK_OFF_DEGREE=CONFIG_TS_BACK_OFF_DEGREE TS_RS485_DELAY=CONFIG_TS_RS485_DELAY TS_FLUSH_OFFSET=CONFIG_TS_FLUSH_OFFSET diff --git a/zephyr/Kconfig b/zephyr/Kconfig index ae6ef38f31..c116bda56b 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -77,8 +77,8 @@ config TS_COLLISION_DELAY Maximum 32 microseconds random delay in case of collision -config TS_RESONSE_TIME_OUT - int "RESONSE TIME OUT" +config TS_RESPONSE_TIME_OUT + int "RESPONSE TIME OUT" default 10000 help Set 10 milliseconds as the maximum timeframe between transmission and @@ -104,8 +104,8 @@ config TS_BYTE_TIME_OUT Always set TS_BYTE_TIME_OUT > (byte transmission time + latency) -config TS_MAX_ATTEMTS - int "MAX ATTEMTS" +config TS_MAX_ATTEMPTS + int "MAX ATTEMPTS" default 20 help Maximum transmission attempts From 787379f5556292d93b7754b8347c13b3523280b6 Mon Sep 17 00:00:00 2001 From: gioblu Date: Fri, 7 Nov 2025 16:17:34 +0100 Subject: [PATCH 311/323] fixed bad english, typos, punctuation in README --- README.md | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index e08754e31a..72235961aa 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,35 @@ ## PJON 13.1 -PJON (Padded Jittering Operative Network) is an experimental, arduino-compatible, multi-master, multi-media, software-defined network protocol that can be easily cross-compiled on many microcontrollers and real-time operative systems like ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple and Android. PJON operates on a wide range of media, data links and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT and ESPNOW. For more information visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md) or the [wiki](https://github.com/gioblu/PJON/wiki). + +PJON (Padded Jittering Operative Network) is an experimental, Arduino-compatible, multi-master, multi-media, software-defined network protocol that can be easily cross-compiled for many microcontrollers and real-time operating systems such as ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple, and Android. PJON operates over a wide range of media, data links, and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT, and ESPNOW. For more information, visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md), or the [wiki](https://github.com/gioblu/PJON/wiki). [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ### Why PJON? -- **New technology**: [PJON](specification/PJON-protocol-specification-v4.0.md) is an experimental network protocol stack crafted in 10 years of research and experimentation. It was originally developed as an open-source alternative to i2c and 1-Wire but during development its scope and features have been extended to cover use cases where IP is generally applied. PJON has been engineered to have a variable footprint (4.2-8.2 kB program memory) and overhead (5-35 bytes per packet) depending on its configuration. -- **Multi-media support**: PJON operates upon a wide range of protocols like TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485 and LoRa. The PJON network protocol stack specifies and implements also [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) that operates over a single wire of up to 2000m shared by up to 255 devices, [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) that operates with many ASK/FSK/OOK radio modules, and also [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) that operates wirelessly with light pulses using off-the-shelf LEDs and laser diodes. -- **Increased reliability**: Many protocols massively applied worldwide expose dangerous vulnerabilities, have weak error detection algorithms and are not resilient to interference. PJON is based on years of analysis and study not to make the same mistakes present in most alternatives and provide with a simpler and more efficient solution. -- **High flexibility**: PJON is totally software-defined and it is designed to be easily extensible. it builds out-of-the-box in all supported devices and operates transparently on top of any supported protocol or medium. -- **Low cost**: With no additional hardware needed to operate, minimal network wiring requirements and direct pin-to-pin or LED-to-LED communication, PJON is extremely energy efficient, cheap to be implemented and maintained. This experimental reference implementation is kept updated thanks to the strong commitment of its growing community. +- **New technology**: [PJON](specification/PJON-protocol-specification-v4.0.md) is an experimental network protocol stack crafted through 10 years of research and experimentation. It was originally developed as an open-source alternative to i2c and 1-Wire, but during development, its scope and features were extended to cover use cases where IP is generally applied. PJON has been engineered to have a variable footprint (4.2–8.2 kB program memory) and overhead (5–35 bytes per packet) depending on its configuration. +- **Multi-media support**: PJON operates over a wide range of protocols including TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485, and LoRa. The PJON network protocol stack also specifies and implements: + - [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) that operates over a single wire of up to 2000m shared by up to 255 devices. + - [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) that operates with many ASK/FSK/OOK radio modules. + - [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) that operates wirelessly with light pulses using off-the-shelf LEDs and laser diodes. +- **Increased reliability**: Many widely applied protocols expose significant vulnerabilities, have weak error detection algorithms, and are not resilient to interference. PJON is based on years of analysis and study to avoid the mistakes present in most alternatives and provides a simpler and more efficient solution. +- **High flexibility**: PJON is fully software-defined and designed to be easily extensible. It builds out-of-the-box on all supported devices and operates transparently on top of any supported protocol or medium. +- **Low cost**: With no additional hardware needed to operate, minimal network wiring requirements, and direct pin-to-pin or LED-to-LED communication, PJON is extremely energy-efficient, inexpensive to implement, and maintain. This experimental reference implementation is kept up to date thanks to the strong commitment of its growing community. ### Features -- Cross-compilation support with the [interfaces](src/interfaces) system calls abstraction -- Multi-media support with the [strategies](src/strategies) data link layer abstraction -- Modular packet format that includes only the field used (overhead 5-35 bytes) -- Hot-swap support, no need of system reset or shut down when replacing or adding devices -- Flexible local (device id) and shared (bus id) network identification -- Safe error detection done with modern CRC8 and CRC32 polynomials -- Optional inclusion of MAC addresses -- Optional acknowledgement -- Error handling +- Cross-compilation support with the [interfaces](src/interfaces) system calls abstraction. +- Multi-media support with the [strategies](src/strategies) data link layer abstraction. +- Modular packet format that includes only the fields used (overhead 5–35 bytes). +- Hot-swap support—no need for a system reset or shutdown when replacing or adding devices. +- Flexible local (device ID) and shared (bus ID) network identification. +- Safe error detection using modern CRC8 and CRC32 polynomials. +- Optional inclusion of MAC addresses. +- Optional acknowledgement. +- Error handling. ### Academic studies -Researchers are active in many universities worldwide using PJON in different environments. The following list contains all the known published academic studies about PJON: -- [Definition and Application of PJON-PLC for sensor networks](https://repositorio.unican.es/xmlui/bitstream/handle/10902/14012/408952.pdf?sequence=1) by Jorge Gómez Segurola, Ingeniería de Tecnologías de -Telecomunicación - [Universidad de Cantabria](https://web.unican.es/) (ES) -- [Biomimetic electronics](https://charliewilliams.org/portfolio/biomimetic/) by Charlie Williams with scientific input from researchers Vítor Martins dos Santos, Diana Machado de Sousa and Sabine Vreeburg - Artist in Residency at [Wageningen University](https://www.wur.nl/en.htm) (NL) -- [LANC Video Camera Control](http://jda.tel/pdf/lanc_video_camera_control.pdf) by [Jack Anderson](https://github.com/jdaandersj) - Department of Computer Science [Loughborough University](https://www.lboro.ac.uk/departments/compsci/) (UK) +Researchers are active in many universities worldwide using PJON in different environments. The following list contains known published academic studies about PJON: +- [Definition and Application of PJON-PLC for sensor networks](https://repositorio.unican.es/xmlui/bitstream/handle/10902/14012/408952.pdf?sequence=1) by Jorge Gómez Segurola, Ingeniería de Tecnologías de Telecomunicación - [Universidad de Cantabria](https://web.unican.es/) (ES). +- [Biomimetic electronics](https://charliewilliams.org/portfolio/biomimetic/) by Charlie Williams with scientific input from researchers Vítor Martins dos Santos, Diana Machado de Sousa, and Sabine Vreeburg - Artist in Residency at [Wageningen University](https://www.wur.nl/en.htm) (NL). +- [LANC Video Camera Control](http://jda.tel/pdf/lanc_video_camera_control.pdf) by [Jack Anderson](https://github.com/jdaandersj) - Department of Computer Science [Loughborough University](https://www.lboro.ac.uk/departments/compsci/) (UK). ### Contribute Feel free to send a pull request sharing something you have made that could help, if you want to support this project you can also try to solve an [issue](https://github.com/gioblu/PJON/issues). Thanks to support, expertise, kindness and talent of the following contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: From 13c907f24ba633c03a7d898d6a4987c96f19e263 Mon Sep 17 00:00:00 2001 From: gioblu Date: Fri, 7 Nov 2025 16:40:21 +0100 Subject: [PATCH 312/323] safety warning update --- README.md | 2 +- SECURITY.md | 2 +- devices/sensors/LEDAR/README.md | 2 +- src/strategies/SoftwareBitBang/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 72235961aa..77c0d2ad66 100644 --- a/README.md +++ b/README.md @@ -48,4 +48,4 @@ Feel free to send a pull request sharing something you have made that could help All the software included in this project is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. [Licensed](https://github.com/gioblu/PJON/blob/master/LICENSE.md) under the Apache License, Version 2.0. ### Safety warning -When testing PJON, extreme care must be taken to avoid any danger. Consider that the implementation is experimental and may not behave as expected, use it at your own risk. When devices are connected to AC power you are exposed to a high chance of being electrocuted if hardware is not installed carefully and properly. If you are not experienced enough ask the support of a skilled technician and consider that many countries prohibit uncertified installations. When testing a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus [interference mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines must be followed. When experimenting with [AnalogSampling](/src/strategies/AnalogSampling) setup safety glasses must be worn and transceivers must be operated cautiously to avoid potential eye injuries. Before testing [OverSampling](/src/strategies/OverSampling), [ThroughSerial](/src/strategies/ThroughSerial) or [ThroughLoRa](/src/strategies/ThroughLoRa) radio communication, be sure the frequency, power and hardware used complies with local laws. When connecting a local bus to the internet all devices must be considered potentially compromised, manipulated or remotely actuated against your will. It should be considered a good practice not to connect to the internet systems that may create a damage (fire, flood, data-leak) if hacked. +When testing PJON, take extreme care to avoid any danger. The implementation is experimental and may not behave as expected; use it at your own risk. If devices are connected to AC power, you face a high risk of electrocution unless the hardware is installed carefully and correctly. If you lack sufficient experience, seek assistance from a qualified technician, and be aware that many countries prohibit uncertified installations. When testing a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus follow [interference-mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective-circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines. When experimenting with an AnalogSampling setup, wear safety glasses and operate transceivers cautiously to prevent eye injuries. Before testing [OverSampling](/src/strategies/OverSampling), [ThroughSerial](/src/strategies/ThroughSerial) or [ThroughLoRa](/src/strategies/ThroughLoRa) radio communication, ensure that the frequency, power, and hardware comply with local regulations. When connecting a local bus to the Internet, treat all devices as potentially compromised, manipulated, or remotely actuated against your will. As a best practice, avoid connecting to the internet systems that could cause damage (fire, flood, data leakage) if hacked. diff --git a/SECURITY.md b/SECURITY.md index 9054f1c040..c0823f531e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,7 +4,7 @@ PJON is still in experimental phase and it distributed "AS IS" without any warra The security of a system that uses PJON for communication mostly depends on the vulnerabilities exposed by the hardware and by the physical layer used. Consider that **only air-gapped wired local buses are undoubtely secure**. When connecting a local bus to the internet using [ESPNOW](/src/strategies/ESPNOW), [EthernetTCP](/src/strategies/EthernetTCP) or [LocalUDP](/src/strategies/LocalUDP), [GlobalUDP](/src/strategies/GlobalUDP) or [DualUDP](/src/strategies/DualUDP), all connected devices must be considered potentially compromised. It should be considered a good practice not to connect to the internet systems that may cause damage (fire, flood, data-leak) if hacked. ### Safety warning -When installing or maintaining a PJON network, extreme care must be taken to avoid any danger. If devices are connected to AC power you are exposed to a high chance of being electrocuted if hardware is not installed carefully and properly. If you are not experienced enough ask the support of a skilled technician and consider that many countries prohibit uncertified installations. When a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus is installed [interference mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines must be followed. When working with an [AnalogSampling](/src/strategies/AnalogSampling) LED or laser based setup safety glasses must be worn and transceivers must be operated cautiously to avoid potential eye injuries. Before any practical test or a hardware purchase for a wireless [OverSampling](/src/strategies/OverSampling), [ThroughSerial](/src/strategies/ThroughSerial) or [ThroughLoRa](/src/strategies/ThroughLoRa) radio setup, compliance with government requirements and regulations must be ensured. +When testing PJON, take extreme care to avoid any danger. The implementation is experimental and may not behave as expected; use it at your own risk. If devices are connected to AC power, you face a high risk of electrocution unless the hardware is installed carefully and correctly. If you lack sufficient experience, seek assistance from a qualified technician, and be aware that many countries prohibit uncertified installations. When testing a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus follow [interference-mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective-circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines. When experimenting with an AnalogSampling setup, wear safety glasses and operate transceivers cautiously to prevent eye injuries. Before testing [OverSampling](/src/strategies/OverSampling), [ThroughSerial](/src/strategies/ThroughSerial) or [ThroughLoRa](/src/strategies/ThroughLoRa) radio communication, ensure that the frequency, power, and hardware comply with local regulations. When connecting a local bus to the Internet, treat all devices as potentially compromised, manipulated, or remotely actuated against your will. As a best practice, avoid connecting to the internet systems that could cause damage (fire, flood, data leakage) if hacked. ### Reporting a Vulnerability If you discover a vulnerability in the specification or in the implementation please report it as soon as possible opening an [issue](https://github.com/gioblu/PJON/issues). If you have developed a fix, feel free to open a [pull request](https://github.com/gioblu/PJON/pulls). diff --git a/devices/sensors/LEDAR/README.md b/devices/sensors/LEDAR/README.md index 04fc7bbec8..ed0bbde058 100644 --- a/devices/sensors/LEDAR/README.md +++ b/devices/sensors/LEDAR/README.md @@ -79,6 +79,6 @@ The case is made by two elements and it has been printed using a customized Prus Once crafted, ATtiny85 has to be flashed with the [LEDAR](software/LEDAR/LEDAR.ino) sketch using an ISP programmer, see [ATtiny85 interfacing](https://github.com/gioblu/PJON/wiki/ATtiny-interfacing) -LEDAR has been engineered with the strong feeling that, in the future, "smart houses" will not necessarily host a multitude of inefficient embedded real-time operative systems in whatever "thing" while exposing vulnerabilities out of the physical boundaries of houses. Otherwise, more probably, will host many simple, less power-hungy microcontrollers, connected to a wired communication bus, unhackable without direct physical access to its wiring. +LEDAR has been engineered with the strong feeling that, in the future, "smart houses" will not necessarily host a multitude of inefficient embedded real-time operating systems in whatever "thing" while exposing vulnerabilities out of the physical boundaries of houses. Otherwise, more probably, will host many simple, less power-hungy microcontrollers, connected to a wired communication bus, unhackable without direct physical access to its wiring. LEDAR should be considered as a general "guideline" on how PJON compatible devices can be published and shared with other PJON users through the [devices](../../README.md) directory. Feel free to make a pull request proposing a new device you have engineered. diff --git a/src/strategies/SoftwareBitBang/README.md b/src/strategies/SoftwareBitBang/README.md index f4efd6b1c9..c675bfaba9 100644 --- a/src/strategies/SoftwareBitBang/README.md +++ b/src/strategies/SoftwareBitBang/README.md @@ -102,4 +102,4 @@ PJON application example made by the user [Michael Teeuw](http://michaelteeuw.nl - If you need to connect devices that operate at different voltages, for example when connecting an Arduino UNOs to an ESP32, consider that voltage level converters available in the market are often not compatible with PJDL, you can try this [alternative approach](http://www.falstad.com/circuit/circuitjs.html?ctz=CQAgjCAMB0l3BWEA2AzNA7ATi8gHACxhaKTJYgaohIHUICmAtGGAFABu4WATCKgj7E+PDH0hQQBCemoT50BJxpg+AvglUhR4ydJqSFSgO5SCefoO0Jkl8WwAm12z0gWeN8D3fgAcqgI2AAduETcvd3CIeTZTD1t1ULsoWJU1KwJzZMhU4XAtePz7UwJkAiK0ipySsorMi1Z7EM0wiwQMFyjDNgBnSp1+8PkQADMAQwAbHoY2ACdnbXDCxIlCeF6kgbzXCwkIcamZ+bzGzaGpVzhUwp2z3evPU-qqh9tTwtV7+eenrJXweDreYtCog24SS5sAAeICYPBcYDerm0xCk2nKqA4qAAOj0HAwOABLADGDFxAEkAPLQmiEFHlDBgDAo5nlHjlBAcXH4omkinUmHECCoOkISAUEWs8BIADKAHVyQAVADCAAkAKIy3EAQQASurcQBVGXqgAiuMVlNxMvJAFlDQAZbWKg09SmGxUABQ9bCAA) proposed by [alastaira](https://github.com/alastaira) instead. It isn't truly converting voltage levels but it is much quicker and cheaper than designs based on transistors. ### Safety warning -In all cases, when installing or maintaining a PJON network, extreme care must be taken to avoid any danger. If devices are connected to AC power you are exposed to a high chance of being electrocuted if hardware is not installed carefully and properly. If you are not experienced enough ask the support of a skilled technician and consider that many countries prohibit uncertified installations. When a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus is installed [interference mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines must be followed. If a common ground or power supply line is used its cable size and length must be carefully selected taking in consideration the overall application's power supply requirements and selected components' maximum rating. PJDL and its reference implementation [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) are experimental, use them at your own risk. +In all cases, when installing or maintaining a PJON network, extreme care must be taken to avoid any danger. If devices are connected to AC power, you face a high risk of electrocution unless the hardware is installed carefully and correctly. If you lack sufficient experience, seek assistance from a qualified technician, and be aware that many countries prohibit uncertified installations. When a [SoftwareBitBang](/src/strategies/SoftwareBitBang) bus is installed [interference-mitigation](https://github.com/gioblu/PJON/wiki/Mitigate-interference) and [protective-circuitry](https://github.com/gioblu/PJON/wiki/Protective-circuitry) guidelines must be followed. If a common ground or power supply line is used its cable size and length must be carefully selected taking in consideration the overall application's power supply requirements and selected components' maximum rating. PJDL and its reference implementation [SoftwareBitBang](/src/strategies/SoftwareBitBang/README.md) are experimental, use them at your own risk. From f6cc5053f90188b141498106d4b63f66566c8a2f Mon Sep 17 00:00:00 2001 From: gioblu Date: Fri, 7 Nov 2025 16:46:15 +0100 Subject: [PATCH 313/323] README multi-media support revert to list --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 77c0d2ad66..b82905a288 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,7 @@ PJON (Padded Jittering Operative Network) is an experimental, Arduino-compatible ### Why PJON? - **New technology**: [PJON](specification/PJON-protocol-specification-v4.0.md) is an experimental network protocol stack crafted through 10 years of research and experimentation. It was originally developed as an open-source alternative to i2c and 1-Wire, but during development, its scope and features were extended to cover use cases where IP is generally applied. PJON has been engineered to have a variable footprint (4.2–8.2 kB program memory) and overhead (5–35 bytes per packet) depending on its configuration. -- **Multi-media support**: PJON operates over a wide range of protocols including TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485, and LoRa. The PJON network protocol stack also specifies and implements: - - [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) that operates over a single wire of up to 2000m shared by up to 255 devices. - - [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) that operates with many ASK/FSK/OOK radio modules. - - [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) that operates wirelessly with light pulses using off-the-shelf LEDs and laser diodes. +- **Multi-media support**: PJON operates over a wide range of protocols including TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485, and LoRa. The PJON network protocol stack also specifies and implements [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) that operates over a single wire of up to 2000m shared by up to 255 devices, [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) that operates with many ASK/FSK/OOK radio modules and [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) that operates wirelessly with light pulses using off-the-shelf LEDs and laser diodes. - **Increased reliability**: Many widely applied protocols expose significant vulnerabilities, have weak error detection algorithms, and are not resilient to interference. PJON is based on years of analysis and study to avoid the mistakes present in most alternatives and provides a simpler and more efficient solution. - **High flexibility**: PJON is fully software-defined and designed to be easily extensible. It builds out-of-the-box on all supported devices and operates transparently on top of any supported protocol or medium. - **Low cost**: With no additional hardware needed to operate, minimal network wiring requirements, and direct pin-to-pin or LED-to-LED communication, PJON is extremely energy-efficient, inexpensive to implement, and maintain. This experimental reference implementation is kept up to date thanks to the strong commitment of its growing community. From d64b974727782cc912ddccf0f5b536462f590f5b Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Fri, 7 Nov 2025 17:02:53 +0100 Subject: [PATCH 314/323] README minor change --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b82905a288..28d1a6a083 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +PJON + ## PJON 13.1 PJON (Padded Jittering Operative Network) is an experimental, Arduino-compatible, multi-master, multi-media, software-defined network protocol that can be easily cross-compiled for many microcontrollers and real-time operating systems such as ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple, and Android. PJON operates over a wide range of media, data links, and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT, and ESPNOW. For more information, visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md), or the [wiki](https://github.com/gioblu/PJON/wiki). From a262588d74e3a9d2a1f8eedbb4a3a53acb419bf3 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Fri, 7 Nov 2025 17:18:44 +0100 Subject: [PATCH 315/323] Fix formatting of hot-swap support feature description --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 28d1a6a083..c85c4c2100 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ PJON (Padded Jittering Operative Network) is an experimental, Arduino-compatible - Cross-compilation support with the [interfaces](src/interfaces) system calls abstraction. - Multi-media support with the [strategies](src/strategies) data link layer abstraction. - Modular packet format that includes only the fields used (overhead 5–35 bytes). -- Hot-swap support—no need for a system reset or shutdown when replacing or adding devices. +- Hot-swap support, no need for a system reset or shutdown when replacing or adding devices. - Flexible local (device ID) and shared (bus ID) network identification. - Safe error detection using modern CRC8 and CRC32 polynomials. - Optional inclusion of MAC addresses. From 2bb20cee0d07b86ce0aad820e7244235392506c8 Mon Sep 17 00:00:00 2001 From: gioblu Date: Sat, 8 Nov 2025 17:37:18 +0100 Subject: [PATCH 316/323] Copyright update --- LICENSE.md | 2 +- .../obsolete/PJON-dynamic-addressing-specification-v0.1.md | 2 +- .../obsolete/PJON-protocol-acknowledge-specification-v0.1.md | 2 +- specification/obsolete/PJON-protocol-specification-v0.1.md | 2 +- specification/obsolete/PJON-protocol-specification-v0.2.md | 2 +- specification/obsolete/PJON-protocol-specification-v0.3.md | 2 +- specification/obsolete/PJON-protocol-specification-v1.0.md | 2 +- specification/obsolete/PJON-protocol-specification-v1.1.md | 2 +- src/PJON.h | 4 ++-- src/PJONDefines.h | 4 ++-- src/PJONDynamicRouter.h | 4 ++-- src/PJONInteractiveRouter.h | 4 ++-- src/PJONLocal.h | 4 ++-- src/PJONRouter.h | 4 ++-- src/PJONSimpleSwitch.h | 4 ++-- src/PJONSwitch.h | 4 ++-- src/PJONVirtualBusRouter.h | 4 ++-- src/strategies/AnalogSampling/AnalogSampling.h | 2 +- src/strategies/Any/Any.h | 2 +- src/strategies/Any/StrategyLink.h | 2 +- src/strategies/Any/StrategyLinkBase.h | 2 +- .../specification/obsolete/PJDLR-specification-v1.0.md | 2 +- .../specification/obsolete/PJDLR-specification-v1.1.md | 2 +- src/strategies/SoftwareBitBang/SoftwareBitBang.h | 2 +- src/strategies/SoftwareBitBang/Timing.h | 2 +- .../specification/obsolete/PJDL-specification-v1.0.md | 2 +- .../specification/obsolete/PJDL-specification-v1.1.md | 2 +- .../obsolete/padded-jittering-protocol-specification-v0.1.md | 2 +- 28 files changed, 37 insertions(+), 37 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index f21ac818e2..68d4263ced 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ All the software included in this project is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Giovanni Blu Mitolo (gioscarab@gmail.com) Copyright 2010-2022 +Giovanni Blu Mitolo (gioscarab@gmail.com) Copyright 2010-2025 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at diff --git a/specification/obsolete/PJON-dynamic-addressing-specification-v0.1.md b/specification/obsolete/PJON-dynamic-addressing-specification-v0.1.md index 741d766652..7a6b0c97e7 100644 --- a/specification/obsolete/PJON-dynamic-addressing-specification-v0.1.md +++ b/specification/obsolete/PJON-dynamic-addressing-specification-v0.1.md @@ -4,7 +4,7 @@ Milan, Italy - 02/10/2016 The PJON® dynamic addressing specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2022 All rights reserved +Copyright 2010-2025 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 5.2 and following diff --git a/specification/obsolete/PJON-protocol-acknowledge-specification-v0.1.md b/specification/obsolete/PJON-protocol-acknowledge-specification-v0.1.md index a73d3832b8..a438f9bda3 100644 --- a/specification/obsolete/PJON-protocol-acknowledge-specification-v0.1.md +++ b/specification/obsolete/PJON-protocol-acknowledge-specification-v0.1.md @@ -4,7 +4,7 @@ Milan, Italy - 17/10/2016 The PJON® protocol acknowledge specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2022 All rights reserved +Copyright 2010-2025 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 6.0 and following diff --git a/specification/obsolete/PJON-protocol-specification-v0.1.md b/specification/obsolete/PJON-protocol-specification-v0.1.md index d80e3eb8c6..b828db6af2 100644 --- a/specification/obsolete/PJON-protocol-specification-v0.1.md +++ b/specification/obsolete/PJON-protocol-specification-v0.1.md @@ -3,7 +3,7 @@ /* Milan, Italy - 10/04/2010 The PJON® protocol specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2025 All rights reserved Related work: https://github.com/gioblu/PJON Compliant implementation versions: PJON 1.0-3.0-beta diff --git a/specification/obsolete/PJON-protocol-specification-v0.2.md b/specification/obsolete/PJON-protocol-specification-v0.2.md index f11509b8d1..39da02befc 100644 --- a/specification/obsolete/PJON-protocol-specification-v0.2.md +++ b/specification/obsolete/PJON-protocol-specification-v0.2.md @@ -3,7 +3,7 @@ /* Milan, Italy - 19/08/2015 The PJON® protocol specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2025 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 3.0-beta-3.0 diff --git a/specification/obsolete/PJON-protocol-specification-v0.3.md b/specification/obsolete/PJON-protocol-specification-v0.3.md index 73b1d8c377..64fa9264bf 100644 --- a/specification/obsolete/PJON-protocol-specification-v0.3.md +++ b/specification/obsolete/PJON-protocol-specification-v0.3.md @@ -3,7 +3,7 @@ /* Milan, Italy - 04/09/2016 The PJON® protocol specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2025 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 4.0-5.0 diff --git a/specification/obsolete/PJON-protocol-specification-v1.0.md b/specification/obsolete/PJON-protocol-specification-v1.0.md index 87d5d6c272..9ef220e4ac 100644 --- a/specification/obsolete/PJON-protocol-specification-v1.0.md +++ b/specification/obsolete/PJON-protocol-specification-v1.0.md @@ -3,7 +3,7 @@ /* Milan, Italy - 3/10/2016 The PJON® protocol layer specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2025 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 6.0 and following diff --git a/specification/obsolete/PJON-protocol-specification-v1.1.md b/specification/obsolete/PJON-protocol-specification-v1.1.md index 3c7f8bdc89..b2fb6456b5 100644 --- a/specification/obsolete/PJON-protocol-specification-v1.1.md +++ b/specification/obsolete/PJON-protocol-specification-v1.1.md @@ -4,7 +4,7 @@ Milan, Italy - 28/03/2017 The PJON® protocol layer specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2022 All rights reserved +Copyright 2010-2025 All rights reserved Related work: https://github.com/gioblu/PJON/ Compliant implementation versions: PJON 6.0 and following diff --git a/src/PJON.h b/src/PJON.h index 820139674d..bfda7f90c4 100644 --- a/src/PJON.h +++ b/src/PJON.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -43,7 +43,7 @@ Compatible tools: This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONDefines.h b/src/PJONDefines.h index 8658baec7e..d393a25e3d 100644 --- a/src/PJONDefines.h +++ b/src/PJONDefines.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -43,7 +43,7 @@ Compatible tools: This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONDynamicRouter.h b/src/PJONDynamicRouter.h index b5ee3e1420..c2b89ef14d 100644 --- a/src/PJONDynamicRouter.h +++ b/src/PJONDynamicRouter.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -22,7 +22,7 @@ dynamically based on observed packets from remote buses. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONInteractiveRouter.h b/src/PJONInteractiveRouter.h index f4828cc00f..5bec67129a 100644 --- a/src/PJONInteractiveRouter.h +++ b/src/PJONInteractiveRouter.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -32,7 +32,7 @@ receiver callback should be really fast. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONLocal.h b/src/PJONLocal.h index 9666dc3bd6..3e68c9aae7 100644 --- a/src/PJONLocal.h +++ b/src/PJONLocal.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -52,7 +52,7 @@ Compatible tools: This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONRouter.h b/src/PJONRouter.h index 08375f9a78..70ece87c3e 100644 --- a/src/PJONRouter.h +++ b/src/PJONRouter.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -23,7 +23,7 @@ buses. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONSimpleSwitch.h b/src/PJONSimpleSwitch.h index 95aa4d4bad..9d663c0dff 100644 --- a/src/PJONSimpleSwitch.h +++ b/src/PJONSimpleSwitch.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -38,7 +38,7 @@ enabling receivers on shared buses to reply back to the local bus. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONSwitch.h b/src/PJONSwitch.h index 6f22f71cda..f47ae2ab13 100644 --- a/src/PJONSwitch.h +++ b/src/PJONSwitch.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -22,7 +22,7 @@ between buses of different strategies using the Any strategy. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/PJONVirtualBusRouter.h b/src/PJONVirtualBusRouter.h index 2cb3f5d163..023c53f8ba 100644 --- a/src/PJONVirtualBusRouter.h +++ b/src/PJONVirtualBusRouter.h @@ -3,7 +3,7 @@ |-gfo\ |__| | | | |\ | ® |!y°o:\ | __| |__| | \| 13.1 |y"s§+`\ multi-master, multi-media bus network protocol - /so+:-..`\ Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com + /so+:-..`\ Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com |+/:ngr-*.`\ |5/:%&-a3f.:;\ \+//u/+g%{osv,,\ @@ -30,7 +30,7 @@ and reducing traffic. This software is experimental and it is distributed "AS IS" without any warranty, use it at your own risk. -Copyright 2010-2022 by Giovanni Blu Mitolo gioscarab@gmail.com +Copyright 2010-2025 by Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/AnalogSampling/AnalogSampling.h b/src/strategies/AnalogSampling/AnalogSampling.h index 501502d5db..d831c88853 100644 --- a/src/strategies/AnalogSampling/AnalogSampling.h +++ b/src/strategies/AnalogSampling/AnalogSampling.h @@ -31,7 +31,7 @@ necessary to tweak timing constants in Timing.h. ___________________________________________________________________________ - Copyright 2010-2022 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2025 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/Any/Any.h b/src/strategies/Any/Any.h index 94c8e04f16..f0ce0f3444 100644 --- a/src/strategies/Any/Any.h +++ b/src/strategies/Any/Any.h @@ -7,7 +7,7 @@ Proposed and developed by Fred Larsen ___________________________________________________________________________ - Copyright 2010-2022 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2025 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/Any/StrategyLink.h b/src/strategies/Any/StrategyLink.h index 3f140c0a76..97866a2135 100644 --- a/src/strategies/Any/StrategyLink.h +++ b/src/strategies/Any/StrategyLink.h @@ -4,7 +4,7 @@ Proposed and developed by Fred Larsen ___________________________________________________________________________ - Copyright 2010-2022 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2025 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/Any/StrategyLinkBase.h b/src/strategies/Any/StrategyLinkBase.h index 41cf5e3a4d..4cd44cc315 100644 --- a/src/strategies/Any/StrategyLinkBase.h +++ b/src/strategies/Any/StrategyLinkBase.h @@ -4,7 +4,7 @@ Proposed and developed by Fred Larsen ___________________________________________________________________________ - Copyright 2010-2022 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2025 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.0.md b/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.0.md index fde7c4eea2..6cacb5cd04 100644 --- a/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.0.md +++ b/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.0.md @@ -3,7 +3,7 @@ /* Milan, Italy - 18/01/2017 PJDLR (Padded jittering data link) specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2025 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 7.0-7.1 diff --git a/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.1.md b/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.1.md index 07696c4db4..2a5dee8b05 100644 --- a/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.1.md +++ b/src/strategies/OverSampling/specification/obsolete/PJDLR-specification-v1.1.md @@ -4,7 +4,7 @@ Milan, Italy - 31/03/2017 PJDLR (Padded jittering data link) specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2022 All rights reserved +Copyright 2010-2025 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 8.0 and following diff --git a/src/strategies/SoftwareBitBang/SoftwareBitBang.h b/src/strategies/SoftwareBitBang/SoftwareBitBang.h index 4347aa93c8..948d771fcf 100644 --- a/src/strategies/SoftwareBitBang/SoftwareBitBang.h +++ b/src/strategies/SoftwareBitBang/SoftwareBitBang.h @@ -5,7 +5,7 @@ Compliant with PJDL (Padded Jittering Data Link) specification v5.0 ___________________________________________________________________________ - Copyright 2010-2022 Giovanni Blu Mitolo gioscarab@gmail.com + Copyright 2010-2025 Giovanni Blu Mitolo gioscarab@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/strategies/SoftwareBitBang/Timing.h b/src/strategies/SoftwareBitBang/Timing.h index f679601cce..c29b51f7d2 100644 --- a/src/strategies/SoftwareBitBang/Timing.h +++ b/src/strategies/SoftwareBitBang/Timing.h @@ -1,6 +1,6 @@ /* PJON SoftwareBitBang strategy Transmission Timing table - Copyright 2010-2022, Giovanni Blu Mitolo All rights reserved. + Copyright 2010-2025, Giovanni Blu Mitolo All rights reserved. Often timing in two different machines do not match, code execution time can variate and time measurements are not perfectly equal. diff --git a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.0.md b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.0.md index b893859c66..2dbf1d70e2 100644 --- a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.0.md +++ b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.0.md @@ -3,7 +3,7 @@ /* Milan, Italy - 10/04/2010 PJDL (Padded jittering data link) specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2025 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 6.0-7.1 diff --git a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.1.md b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.1.md index 1711718a3e..491fc99f6e 100644 --- a/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.1.md +++ b/src/strategies/SoftwareBitBang/specification/obsolete/PJDL-specification-v1.1.md @@ -4,7 +4,7 @@ Milan, Italy - 31/03/2017 PJDL (Padded jittering data link) specification is an invention and intellectual property of Giovanni Blu Mitolo -Copyright 2010-2022 All rights reserved +Copyright 2010-2025 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 8.0 and following diff --git a/src/strategies/SoftwareBitBang/specification/obsolete/padded-jittering-protocol-specification-v0.1.md b/src/strategies/SoftwareBitBang/specification/obsolete/padded-jittering-protocol-specification-v0.1.md index 5fb9abbbfb..3fefc26c75 100644 --- a/src/strategies/SoftwareBitBang/specification/obsolete/padded-jittering-protocol-specification-v0.1.md +++ b/src/strategies/SoftwareBitBang/specification/obsolete/padded-jittering-protocol-specification-v0.1.md @@ -3,7 +3,7 @@ /* Milan, Italy - 10/04/2010 The Padded jittering data link layer specification is an invention and intellectual property -of Giovanni Blu Mitolo - Copyright 2010-2022 All rights reserved +of Giovanni Blu Mitolo - Copyright 2010-2025 All rights reserved Related work: /src/strategies/SoftwareBitBang/ Compliant implementation versions: PJON 1.0-5.0 From 1fa4131c1de567c045e5ca35707431d6141b2d26 Mon Sep 17 00:00:00 2001 From: gioblu Date: Sat, 8 Nov 2025 17:58:55 +0100 Subject: [PATCH 317/323] added 50x50 PJON logo --- README.md | 2 +- trademark/assets/PJON-color-50x50.png | Bin 0 -> 17765 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 trademark/assets/PJON-color-50x50.png diff --git a/README.md b/README.md index c85c4c2100..53829b39ec 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -PJON +PJON ## PJON 13.1 diff --git a/trademark/assets/PJON-color-50x50.png b/trademark/assets/PJON-color-50x50.png new file mode 100644 index 0000000000000000000000000000000000000000..36d21106d9ac08b79b2bd630ba36383dfa1402c2 GIT binary patch literal 17765 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 Gqy7!*CE|1d literal 0 HcmV?d00001 From 0eec91117ec6313b65fed38be77fbae277c31a0d Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Mon, 10 Nov 2025 13:55:04 +0100 Subject: [PATCH 318/323] remark added to packet transmission section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit medium‑access, collision resolution, transmission and acknowledgement procedures and their timing are specified by the underlying layer. --- specification/PJON-protocol-specification-v4.0.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index dc7cb2a945..2464bbb409 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -203,7 +203,9 @@ Medium access Transmission Response BITS: | 8 | 8 | 8 | 8 | 8 | 8 | |____|__________|________|______|________|______| ``` -The acknowledgment ensures reliable delivery only when a packet transmission occurs directly without the intermediation of routers or switches. When a packet needs to traverse a network the acknowledgment is transmitted by the nearest intermediary therefore it ensures only best-effort delivery. +The acknowledgement ensures reliable delivery only when a packet transmission occurs directly without the intermediation of routers or switches. When a packet needs to traverse a network the acknowledegment is transmitted by the nearest intermediary therefore it ensures only best-effort delivery. + +The medium‑access, collision resolution, transmission and acknowledgement procedures are specified by the underlying layer, which also supplies the timing required for retransmissions. #### Local mode Depending on header's `MODE` bit packets can contain basic or extended support to identification. Local mode required by header's `MODE` bit low supports connectivity for up to 254 devices. In the graph below is represented the simplest local mode packet format sending `@` (decimal 64) to device `12`: From b6a6ebc4a53ea8fd41dc95fdf8d20a5b5dbfe30a Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Mon, 10 Nov 2025 13:58:44 +0100 Subject: [PATCH 319/323] minor formatting fix --- specification/PJON-protocol-specification-v4.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index 2464bbb409..fe064afb0a 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -205,7 +205,7 @@ Medium access Transmission Response ``` The acknowledgement ensures reliable delivery only when a packet transmission occurs directly without the intermediation of routers or switches. When a packet needs to traverse a network the acknowledegment is transmitted by the nearest intermediary therefore it ensures only best-effort delivery. -The medium‑access, collision resolution, transmission and acknowledgement procedures are specified by the underlying layer, which also supplies the timing required for retransmissions. +The medium access, collision resolution, transmission and acknowledgement procedures are specified by the underlying layer, which also supplies the timing required for retransmissions. #### Local mode Depending on header's `MODE` bit packets can contain basic or extended support to identification. Local mode required by header's `MODE` bit low supports connectivity for up to 254 devices. In the graph below is represented the simplest local mode packet format sending `@` (decimal 64) to device `12`: From 9188f0ea7d665b9cbc9f44d7415335b09b190a5d Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Mon, 10 Nov 2025 14:12:57 +0100 Subject: [PATCH 320/323] added retransmission remark to packet trasmissions ection Added maximum number of attempts to the transmission procedures description. --- specification/PJON-protocol-specification-v4.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index fe064afb0a..1be37fa1a9 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -205,7 +205,7 @@ Medium access Transmission Response ``` The acknowledgement ensures reliable delivery only when a packet transmission occurs directly without the intermediation of routers or switches. When a packet needs to traverse a network the acknowledegment is transmitted by the nearest intermediary therefore it ensures only best-effort delivery. -The medium access, collision resolution, transmission and acknowledgement procedures are specified by the underlying layer, which also supplies the timing required for retransmissions. +The medium access, collision resolution, transmission and acknowledgement procedures are specified by the underlying layer, which also supplies the timing required for retransmissions and the maximum number of attempts. #### Local mode Depending on header's `MODE` bit packets can contain basic or extended support to identification. Local mode required by header's `MODE` bit low supports connectivity for up to 254 devices. In the graph below is represented the simplest local mode packet format sending `@` (decimal 64) to device `12`: From ac1f8910461a05adeabd4774e90a98d3c71cd709 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Mon, 10 Nov 2025 14:14:13 +0100 Subject: [PATCH 321/323] Update PJON-protocol-specification-v4.0.md --- specification/PJON-protocol-specification-v4.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/PJON-protocol-specification-v4.0.md b/specification/PJON-protocol-specification-v4.0.md index 1be37fa1a9..74bf97c68f 100644 --- a/specification/PJON-protocol-specification-v4.0.md +++ b/specification/PJON-protocol-specification-v4.0.md @@ -205,7 +205,7 @@ Medium access Transmission Response ``` The acknowledgement ensures reliable delivery only when a packet transmission occurs directly without the intermediation of routers or switches. When a packet needs to traverse a network the acknowledegment is transmitted by the nearest intermediary therefore it ensures only best-effort delivery. -The medium access, collision resolution, transmission and acknowledgement procedures are specified by the underlying layer, which also supplies the timing required for retransmissions and the maximum number of attempts. +The medium access, collision resolution, transmission and acknowledgement procedures are specified by the underlying layer, which also supplies the maximum number of attempts and the timing required for retransmission. #### Local mode Depending on header's `MODE` bit packets can contain basic or extended support to identification. Local mode required by header's `MODE` bit low supports connectivity for up to 254 devices. In the graph below is represented the simplest local mode packet format sending `@` (decimal 64) to device `12`: From 57410762cbeac6bbc5e03b4288fa5c15191d75b6 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Fri, 21 Nov 2025 21:54:01 +0100 Subject: [PATCH 322/323] Simplify PJON description in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 53829b39ec..b90b0ff34f 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ ## PJON 13.1 -PJON (Padded Jittering Operative Network) is an experimental, Arduino-compatible, multi-master, multi-media, software-defined network protocol that can be easily cross-compiled for many microcontrollers and real-time operating systems such as ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple, and Android. PJON operates over a wide range of media, data links, and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT, and ESPNOW. For more information, visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md), or the [wiki](https://github.com/gioblu/PJON/wiki). +PJON (Padded Jittering Operative Network) is an experimental, multi-master, software-defined network protocol that can be easily cross-compiled for many microcontrollers and real-time operating systems such as ATtiny, ATmega, SAMD, ESP8266, ESP32, STM32, Teensy, Raspberry Pi, Zephyr, Linux, Windows x86, Apple, and Android. PJON operates over a wide range of media, data links, and existing protocols like PJDL, PJDLR, PJDLS, Serial, RS485, USB, ASK/FSK, LoRa, UDP, TCP, MQTT, and ESPNOW. For more information, visit the [documentation](documentation/README.md), the [specification](specification/PJON-protocol-specification-v4.0.md), or the [wiki](https://github.com/gioblu/PJON/wiki). [![Join the chat at https://gitter.im/gioblu/PJON](https://badges.gitter.im/gioblu/PJON.svg)](https://gitter.im/gioblu/PJON?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ### Why PJON? - **New technology**: [PJON](specification/PJON-protocol-specification-v4.0.md) is an experimental network protocol stack crafted through 10 years of research and experimentation. It was originally developed as an open-source alternative to i2c and 1-Wire, but during development, its scope and features were extended to cover use cases where IP is generally applied. PJON has been engineered to have a variable footprint (4.2–8.2 kB program memory) and overhead (5–35 bytes per packet) depending on its configuration. - **Multi-media support**: PJON operates over a wide range of protocols including TCP, UDP, MQTT, ESPNOW, USB, Serial, RS485, and LoRa. The PJON network protocol stack also specifies and implements [PJDL](src/strategies/SoftwareBitBang/specification/PJDL-specification-v5.0.md) that operates over a single wire of up to 2000m shared by up to 255 devices, [PJDLR](src/strategies/OverSampling/specification/PJDLR-specification-v3.0.md) that operates with many ASK/FSK/OOK radio modules and [PJDLS](src/strategies/AnalogSampling/specification/PJDLS-specification-v2.0.md) that operates wirelessly with light pulses using off-the-shelf LEDs and laser diodes. -- **Increased reliability**: Many widely applied protocols expose significant vulnerabilities, have weak error detection algorithms, and are not resilient to interference. PJON is based on years of analysis and study to avoid the mistakes present in most alternatives and provides a simpler and more efficient solution. +- **Increased reliability**: Many widely applied protocols expose significant vulnerabilities, have weak error detection algorithms, and are not resilient to interference. PJON is based on years of analysis and study to avoid the mistakes present in most alternatives and provide with a simpler and more efficient solution. - **High flexibility**: PJON is fully software-defined and designed to be easily extensible. It builds out-of-the-box on all supported devices and operates transparently on top of any supported protocol or medium. - **Low cost**: With no additional hardware needed to operate, minimal network wiring requirements, and direct pin-to-pin or LED-to-LED communication, PJON is extremely energy-efficient, inexpensive to implement, and maintain. This experimental reference implementation is kept up to date thanks to the strong commitment of its growing community. From 3f42e1827f851686d4ffd9143065c1d738744432 Mon Sep 17 00:00:00 2001 From: Giovanni Blu Mitolo Date: Fri, 21 Nov 2025 23:50:23 +0100 Subject: [PATCH 323/323] Add new academic study reference to README Added a new academic study on PJON hardware peripheral implementation. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b90b0ff34f..0708bc136c 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Researchers are active in many universities worldwide using PJON in different en - [Definition and Application of PJON-PLC for sensor networks](https://repositorio.unican.es/xmlui/bitstream/handle/10902/14012/408952.pdf?sequence=1) by Jorge Gómez Segurola, Ingeniería de Tecnologías de Telecomunicación - [Universidad de Cantabria](https://web.unican.es/) (ES). - [Biomimetic electronics](https://charliewilliams.org/portfolio/biomimetic/) by Charlie Williams with scientific input from researchers Vítor Martins dos Santos, Diana Machado de Sousa, and Sabine Vreeburg - Artist in Residency at [Wageningen University](https://www.wur.nl/en.htm) (NL). - [LANC Video Camera Control](http://jda.tel/pdf/lanc_video_camera_control.pdf) by [Jack Anderson](https://github.com/jdaandersj) - Department of Computer Science [Loughborough University](https://www.lboro.ac.uk/departments/compsci/) (UK). +- [Implementation of a PJON hardware peripheral for the Croc SoC](https://github.com/piussieber/pjon_on_croc) by [Pius Sieber](https://github.com/piussieber/) - [ETH Zurich](https://ethz.ch/) (CH) ### Contribute Feel free to send a pull request sharing something you have made that could help, if you want to support this project you can also try to solve an [issue](https://github.com/gioblu/PJON/issues). Thanks to support, expertise, kindness and talent of the following contributors, the protocol's documentation, specification and implementation have been strongly tested, enhanced and verified: