From a1b60e00ae3b38d01361cf56c21ab87c0f913f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Wed, 21 Nov 2018 22:00:04 +0100 Subject: [PATCH 01/13] added proposal for I2C peer-to-peer communication (master/slave) examples --- .../Wire/examples/i2c-P2P-master/crc16.h | 209 +++++++++++++ .../i2c-P2P-master/i2c-P2P-master.ino | 271 +++++++++++++++++ .../examples/i2c-P2P-master/i2c-scanner.h | 43 +++ libraries/Wire/examples/i2c-P2P-slave/crc16.h | 209 +++++++++++++ .../examples/i2c-P2P-slave/i2c-P2P-slave.ino | 281 ++++++++++++++++++ 5 files changed, 1013 insertions(+) create mode 100644 libraries/Wire/examples/i2c-P2P-master/crc16.h create mode 100644 libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino create mode 100644 libraries/Wire/examples/i2c-P2P-master/i2c-scanner.h create mode 100644 libraries/Wire/examples/i2c-P2P-slave/crc16.h create mode 100644 libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino diff --git a/libraries/Wire/examples/i2c-P2P-master/crc16.h b/libraries/Wire/examples/i2c-P2P-master/crc16.h new file mode 100644 index 0000000000..1f2d724acf --- /dev/null +++ b/libraries/Wire/examples/i2c-P2P-master/crc16.h @@ -0,0 +1,209 @@ +//------------------------------------------------------------------------------------- +// CRC16 support class +// Based on various examples found on the web +// Copyright (C) 2014 Vincenzo Mennella (see license.txt) +// History +// 0.1.0 31/05/2014: First public code release +// 0.1.1 17/12/2014: Minor revision and commented code +// +// License +// "MIT Open Source Software License": +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in the +// Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//------------------------------------------------------------------------------------- +#ifndef CRC16_H +#define CRC16_H +#define LIBRARY_VERSION_CRC16_H "0.1.1" + +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +#elif defined(ARDUINO) +#include "WProgram.h" +#else +#include +#endif + +class Crc16 { +private: + //Crc parameters + uint16_t _msbMask; + uint16_t _mask; + uint16_t _xorIn; + uint16_t _xorOut; + uint16_t _polynomial; + uint8_t _reflectIn; + uint8_t _reflectOut; + //Crc value + uint16_t _crc; + uint8_t reflect(uint8_t data, uint8_t bits = 32); + +public: + inline Crc16() + { + //Default to XModem parameters + _reflectIn = false; + _reflectOut = false; + _polynomial = 0x1021; + _xorIn = 0x0000; + _xorOut = 0x0000; + _msbMask = 0x8000; + _mask = 0xFFFF; + _crc = _xorIn; + } + inline Crc16(uint8_t reflectIn, uint8_t reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask) + { + _reflectIn = reflectIn; + _reflectOut = reflectOut; + _polynomial = polynomial; + _xorIn = xorIn; + _xorOut = xorOut; + _msbMask = msbMask; + _mask = mask; + _crc = _xorIn; + } + inline void clearCrc(); + inline void updateCrc(uint8_t data); + inline uint16_t getCrc(); + inline unsigned int fastCrc(uint8_t data[], uint8_t start, uint16_t length, uint8_t reflectIn, uint8_t reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask); + inline unsigned int XModemCrc(uint8_t data[], uint8_t start, uint16_t length) + { + // XModem parameters: poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 + return fastCrc(data, start, length, false, false, 0x1021, 0x0000, 0x0000, 0x8000, 0xffff); + } +}; + +//--------------------------------------------------- +// Initialize crc calculation +//--------------------------------------------------- +void Crc16::clearCrc() +{ + _crc = _xorIn; +} +//--------------------------------------------------- +// Update crc with new data +//--------------------------------------------------- +void Crc16::updateCrc(uint8_t data) +{ + if (_reflectIn != 0) + data = (uint8_t) reflect(data, 8); + + int j = 0x80; + + while (j > 0) + { + uint16_t bit = (uint16_t)(_crc & _msbMask); + + _crc <<= 1; + + if ((data & j) != 0) + { + bit = (uint16_t)(bit ^ _msbMask); + } + + if (bit != 0) + { + _crc ^= _polynomial; + } + + j >>= 1; + } +} + +//--------------------------------------------------- +// Get final crc value +//--------------------------------------------------- +uint16_t Crc16::getCrc() +{ + if (_reflectOut != 0) + _crc = (unsigned int)((reflect(_crc) ^ _xorOut) & _mask); + + return _crc; +} + +//--------------------------------------------------- +// Calculate generic crc code on data array +// Examples of crc 16: +// Kermit: width=16 poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 +// Modbus: width=16 poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37 +// XModem: width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3 +// CCITT-False: width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 +//--------------------------------------------------- +unsigned int Crc16::fastCrc(uint8_t data[], uint8_t start, uint16_t length, uint8_t reflectIn, uint8_t reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask) +{ + unsigned int crc = xorIn; + + int j; + uint8_t c; + unsigned int bit; + + if (length == 0) return crc; + + for (int i = start; i < (start + length); i++) + { + c = data[i]; + + if (reflectIn != 0) + c = (uint8_t) reflect(c, 8); + + j = 0x80; + + while (j > 0) + { + bit = (unsigned int)(crc & msbMask); + crc <<= 1; + + if ((c & j) != 0) + { + bit = (unsigned int)(bit ^ msbMask); + } + + if (bit != 0) + { + crc ^= polynomial; + } + + j >>= 1; + } + } + + if (reflectOut != 0) + crc = (unsigned int)((reflect(crc) ^ xorOut) & mask); + + return crc; +} + +//------------------------------------------------------- +// Reflects bit in a uint8_t +//------------------------------------------------------- +uint8_t Crc16::reflect(uint8_t data, uint8_t bits) +{ + unsigned long reflection = 0x00000000; + // Reflect the data about the center bit. + for (uint8_t bit = 0; bit < bits; bit++) + { + // If the LSB bit is set, set the reflection of it. + if ((data & 0x01) != 0) + { + reflection |= (unsigned long)(1 << ((bits - 1) - bit)); + } + + data = (uint8_t)(data >> 1); + } + + return reflection; +} +#endif diff --git a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino new file mode 100644 index 0000000000..51fd40cf7a --- /dev/null +++ b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino @@ -0,0 +1,271 @@ +/* + * ESP8266 I2C master-slave communication, requires Arduno Core with I2C Slave Support (2.5.0+) + * + * Expects two ESP8266 devices with three pins connected: GND, SDA and SCL. This is master. + * Will send "MESA" messages to predefined slave address and then expect "PONG" response, + * or request to retransfer if message was misunderstood (e.g. CRC check failed). + * Message can be up to 26 bytes long (plus wrapper). + * + * 21-11-2018: initial drop by Matej Sychra (github.com/suculent) + */ + +#include + +#include "i2c-scanner.h" + +#define WIRE_SDA D1 +#define WIRE_SCL D2 + +#include "crc16.h" + +#define LED_PIN D4 + +const int16_t I2C_MASTER = 0x42; +const int16_t I2C_SLAVE = 0x08; + +int16_t slave_address = I2C_SLAVE; // may be overridden using scan() + +// Keep this structure in sync with the i2c-P2P-slave example. Should be in shared header. +struct MESSAGE_DATA { + uint8_t sequence; + uint16_t crc16; + uint8_t data[26]; + uint8_t terminator; +}; + +MESSAGE_DATA msgdata; +Crc16 crc; +bool expect_pong = false; +byte sequence = 0; +unsigned long next_ping = millis() + 1000; + +// analytics +uint16_t error_count = 0; +uint16_t byte_count = 0; + +// forward declarations +uint16_t calculateCRC16(uint8_t *data, size_t length); +void sendMessage(int seq, String msg); +MESSAGE_DATA encodeMessage(String bytes); +void receiveEvent(int howMany); +MESSAGE_DATA validateMessage(char* bytes_message); + +// + +// should be in shared header +uint16_t calculateCRC16(uint8_t *data, size_t length) { + crc.clearCrc(); + uint16_t value = (uint16_t)crc.XModemCrc(data,0,length); + Serial.print("crc = 0x"); Serial.println(value, HEX); + return value; +} + +// should be in shared header +MESSAGE_DATA encodeMessage(String bytes) { + + msgdata.terminator = '.'; + + int datasize = sizeof(msgdata.data); + Serial.print("\nEncoding data of size: "); + Serial.println(datasize); + + // Generate new data set for the struct + for (size_t i = 0; i < datasize; i++) { + if (bytes.length() >= i) { + msgdata.data[i] = bytes[i]; + } else { + msgdata.data[i] = '\0'; + } + Serial.print(msgdata.data[i]); + Serial.print(" "); + } + Serial.print('\n'); + msgdata.crc16 = calculateCRC16((uint8_t*) &msgdata.data[0], datasize); + //Serial.print("ENCODED Message CRC16: "); Serial.println(msgdata.crc16, HEX); + return msgdata; +} + +// should be in shared header +MESSAGE_DATA validateMessage(char* bytes_message) { + + MESSAGE_DATA tmp; + memcpy(&tmp, bytes_message, sizeof(tmp)); + + // Validate PROTOCOL terminator + if (tmp.terminator != '.') { + Serial.print("[ERROR] Terminator invalid: '"); + Serial.print(tmp.terminator); + Serial.println("'"); + return tmp; // should be nullptr // TODO: return error + } + + int datasize = sizeof(tmp.data); + Serial.print("Data of size: "); Serial.println(datasize); + + uint16_t data_crc = calculateCRC16((uint8_t*) &tmp.data[0], datasize); + + // Validate incoming data CRC against remote CRC + if (tmp.crc16 == data_crc) { + Serial.println("[OK] Data CRC valid."); + char inmsg[datasize]; + memcpy(inmsg, &tmp.data, datasize); + Serial.print("MASTER Incoming message: "); Serial.println(String(inmsg)); + } else { + Serial.print("CRC-A = 0x"); + Serial.println(tmp.crc16, HEX); + Serial.print("Incoming message CRC-B = 0x"); + Serial.println(data_crc, HEX); + Serial.print("tmp CRC16: "); + Serial.println(tmp.crc16, HEX); + Serial.println("[ERROR] Request retransfer exception."); + return tmp; + } + + // Validate sequence number + uint8_t remote_sequence = tmp.sequence; + if (remote_sequence < sequence - 1) { + Serial.print("[WARNING] TODO: Unexpected sequence number: "); + Serial.print(remote_sequence); + Serial.print(" while local is "); + Serial.println(sequence); // TODO: return error + } + + msgdata = tmp; // tmp is valid, assign to result address + + return tmp; + +} + +void sendMessage(int seq, String msg) { + + Serial.print("[MASTER] Sending message: "); + Serial.print(msg); + + if (msg.indexOf("MESA") == 0) { + expect_pong = true; + } else { + expect_pong = false; + } + + Wire.beginTransmission(I2C_SLAVE); // transmit to device 0x08 + //Sending Side + MESSAGE_DATA struct_data = encodeMessage(msg); + struct_data.sequence = seq; + char buf[sizeof(struct_data)]; + Serial.print(" of size "); + Serial.println(sizeof(struct_data)); + Serial.print("Encoding struct of size: "); Serial.println(sizeof(struct_data)); + memcpy(buf, &struct_data, sizeof(struct_data)); + for (int i = 0; i < sizeof(struct_data); i++) { + Wire.write(buf[i]); + Serial.print(buf[i]);Serial.print(" "); + } + Wire.endTransmission(); // stop transmitting + Serial.println(""); +} + +void receiveEvent(int howMany) { + + byte_count = byte_count + howMany; + + char incoming[howMany]; + incoming[howMany - 1] = '\0'; + int index = 0; + + digitalWrite(LED_PIN, LOW); + + // message duration may not exceed 100 ms (100 bytes, 3x buffer retransferred) + unsigned long rtimeout = millis() + 100; + while (millis() < rtimeout) { + // this must be fast, keep free from logging to serial here if possible + while (0 < Wire.available()) { // loop through all but the last + int c = Wire.read(); // receive byte as a character + if (index < howMany) { + incoming[index] = (char)c; // save the character + } + index++; + } + } + + Serial.println(); Serial.print("[MASTER] Received "); Serial.print(index); Serial.println(" bytes from SLAVE."); + //Serial.print("[MASTER] Local Sequence: "); Serial.println((int)sequence); + + MESSAGE_DATA message = validateMessage(incoming); + + char inmsg[sizeof(message.data)]; + memcpy(inmsg, &message.data, sizeof(message.data)); + if (inmsg[0] == 'R') { + String retransfer_command = String(inmsg); + retransfer_command.replace("R", ""); + int retransfer_offset = retransfer_command.toInt(); + Serial.println(sequence); + Serial.print("[MASTER] Retransfer request: "); + // dumb retransfer, only changes sequence number when expecting PONG + if (expect_pong) { + sequence = retransfer_offset + 1; + } else { + // debug only, WARNING! may loose important messages in production + sequence = retransfer_offset + 1; + } + Serial.println(sequence); + } else { + // Serial.print("[MASTER] Incoming message from SLAVE: "); Serial.println(String(inmsg)); + } + + String instring = String(inmsg); + if (instring.indexOf("PONG")) { + // alles kitz... + expect_pong = false; + } + + // Do something with the message... + + digitalWrite(LED_PIN, HIGH); +} + +void setup() { + + delay(2000); + + Wire.pins(WIRE_SDA, WIRE_SCL); + Wire.begin(I2C_MASTER); // join i2c bus (address optional for master) + Wire.onReceive(receiveEvent); + + Serial.begin(230400); // keep serial fast as possible for debug logging + while (!Serial); + pinMode(LED_PIN, OUTPUT); + digitalWrite(LED_PIN, HIGH); + + slave_address = scan(); // useful with master/slave devices only on the bus +} + +unsigned long second_timer = millis() + 1000; + +void loop() { + + if (millis() > second_timer) { + Serial.print("Errors/Bytes: "); + Serial.print(error_count); + Serial.print("/"); + Serial.print(byte_count); + Serial.println(" per second"); + error_count = 0; + byte_count = 0; + second_timer = millis() + 1000; + } + + if (millis() > next_ping) { + digitalWrite(LED_PIN, LOW); + next_ping = millis() + 200; + Serial.print("[MASTER] Sequence » "); + Serial.println(sequence); + digitalWrite(LED_PIN, HIGH); + sendMessage(sequence, "MESA"); + if (expect_pong) { + error_count++; + } + expect_pong = true; + sequence++; + } + +} diff --git a/libraries/Wire/examples/i2c-P2P-master/i2c-scanner.h b/libraries/Wire/examples/i2c-P2P-master/i2c-scanner.h new file mode 100644 index 0000000000..987e87b66e --- /dev/null +++ b/libraries/Wire/examples/i2c-P2P-master/i2c-scanner.h @@ -0,0 +1,43 @@ +/* ESP8266 I2C master-slave communication, requires i2c_slave by bjoham */ + +#include + +int scan(uint16_t) { + byte error, address; + int nDevices; + int aDevice = 0; + + Serial.println("Scanning..."); + + nDevices = 0; + for (address = 1; address < 127; address++) { + Wire.beginTransmission(address); + error = Wire.endTransmission(); + + if (error == 0) { + Serial.print("I2C device found at address 0x"); + if (address < 16) { + Serial.print("0"); + } + Serial.print(address, HEX); + Serial.println(" !"); + nDevices++; + aDevice = address; + + } else if (error == 4) { + Serial.print("Unknown error at address 0x"); + if (address < 16) { + Serial.print("0"); + } + Serial.println(address, HEX); + } + } + + if (nDevices == 0) { + Serial.println("No I2C devices found\n"); + } else { + Serial.println("Done.\n"); + } + + return aDevice; +} diff --git a/libraries/Wire/examples/i2c-P2P-slave/crc16.h b/libraries/Wire/examples/i2c-P2P-slave/crc16.h new file mode 100644 index 0000000000..1f2d724acf --- /dev/null +++ b/libraries/Wire/examples/i2c-P2P-slave/crc16.h @@ -0,0 +1,209 @@ +//------------------------------------------------------------------------------------- +// CRC16 support class +// Based on various examples found on the web +// Copyright (C) 2014 Vincenzo Mennella (see license.txt) +// History +// 0.1.0 31/05/2014: First public code release +// 0.1.1 17/12/2014: Minor revision and commented code +// +// License +// "MIT Open Source Software License": +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in the +// Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//------------------------------------------------------------------------------------- +#ifndef CRC16_H +#define CRC16_H +#define LIBRARY_VERSION_CRC16_H "0.1.1" + +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +#elif defined(ARDUINO) +#include "WProgram.h" +#else +#include +#endif + +class Crc16 { +private: + //Crc parameters + uint16_t _msbMask; + uint16_t _mask; + uint16_t _xorIn; + uint16_t _xorOut; + uint16_t _polynomial; + uint8_t _reflectIn; + uint8_t _reflectOut; + //Crc value + uint16_t _crc; + uint8_t reflect(uint8_t data, uint8_t bits = 32); + +public: + inline Crc16() + { + //Default to XModem parameters + _reflectIn = false; + _reflectOut = false; + _polynomial = 0x1021; + _xorIn = 0x0000; + _xorOut = 0x0000; + _msbMask = 0x8000; + _mask = 0xFFFF; + _crc = _xorIn; + } + inline Crc16(uint8_t reflectIn, uint8_t reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask) + { + _reflectIn = reflectIn; + _reflectOut = reflectOut; + _polynomial = polynomial; + _xorIn = xorIn; + _xorOut = xorOut; + _msbMask = msbMask; + _mask = mask; + _crc = _xorIn; + } + inline void clearCrc(); + inline void updateCrc(uint8_t data); + inline uint16_t getCrc(); + inline unsigned int fastCrc(uint8_t data[], uint8_t start, uint16_t length, uint8_t reflectIn, uint8_t reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask); + inline unsigned int XModemCrc(uint8_t data[], uint8_t start, uint16_t length) + { + // XModem parameters: poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 + return fastCrc(data, start, length, false, false, 0x1021, 0x0000, 0x0000, 0x8000, 0xffff); + } +}; + +//--------------------------------------------------- +// Initialize crc calculation +//--------------------------------------------------- +void Crc16::clearCrc() +{ + _crc = _xorIn; +} +//--------------------------------------------------- +// Update crc with new data +//--------------------------------------------------- +void Crc16::updateCrc(uint8_t data) +{ + if (_reflectIn != 0) + data = (uint8_t) reflect(data, 8); + + int j = 0x80; + + while (j > 0) + { + uint16_t bit = (uint16_t)(_crc & _msbMask); + + _crc <<= 1; + + if ((data & j) != 0) + { + bit = (uint16_t)(bit ^ _msbMask); + } + + if (bit != 0) + { + _crc ^= _polynomial; + } + + j >>= 1; + } +} + +//--------------------------------------------------- +// Get final crc value +//--------------------------------------------------- +uint16_t Crc16::getCrc() +{ + if (_reflectOut != 0) + _crc = (unsigned int)((reflect(_crc) ^ _xorOut) & _mask); + + return _crc; +} + +//--------------------------------------------------- +// Calculate generic crc code on data array +// Examples of crc 16: +// Kermit: width=16 poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 +// Modbus: width=16 poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37 +// XModem: width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3 +// CCITT-False: width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 +//--------------------------------------------------- +unsigned int Crc16::fastCrc(uint8_t data[], uint8_t start, uint16_t length, uint8_t reflectIn, uint8_t reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask) +{ + unsigned int crc = xorIn; + + int j; + uint8_t c; + unsigned int bit; + + if (length == 0) return crc; + + for (int i = start; i < (start + length); i++) + { + c = data[i]; + + if (reflectIn != 0) + c = (uint8_t) reflect(c, 8); + + j = 0x80; + + while (j > 0) + { + bit = (unsigned int)(crc & msbMask); + crc <<= 1; + + if ((c & j) != 0) + { + bit = (unsigned int)(bit ^ msbMask); + } + + if (bit != 0) + { + crc ^= polynomial; + } + + j >>= 1; + } + } + + if (reflectOut != 0) + crc = (unsigned int)((reflect(crc) ^ xorOut) & mask); + + return crc; +} + +//------------------------------------------------------- +// Reflects bit in a uint8_t +//------------------------------------------------------- +uint8_t Crc16::reflect(uint8_t data, uint8_t bits) +{ + unsigned long reflection = 0x00000000; + // Reflect the data about the center bit. + for (uint8_t bit = 0; bit < bits; bit++) + { + // If the LSB bit is set, set the reflection of it. + if ((data & 0x01) != 0) + { + reflection |= (unsigned long)(1 << ((bits - 1) - bit)); + } + + data = (uint8_t)(data >> 1); + } + + return reflection; +} +#endif diff --git a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino new file mode 100644 index 0000000000..c9fc879938 --- /dev/null +++ b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino @@ -0,0 +1,281 @@ +/* + * ESP8266 I2C master-slave communication, requires Arduno Core with I2C Slave Support (2.5.0+) + * + * Expects two ESP8266 devices with three pins connected: GND, SDA and SCL. This is slave. + * Will wait for "MESA" message and then respond with "PONG" message, + * or request retransfer if message was misunderstood (e.g. CRC check failed). + * Message can be up to 26 bytes long (plus wrapper). + * + * 21-11-2018: initial drop by Matej Sychra (github.com/suculent) + */ + +#include + +#include "crc16.h" + +#define SDA_PIN D1 +#define SCL_PIN D2 +#define LED_PIN D4 + +const uint16_t I2C_ADDRESS = 0x08; +const uint16_t I2C_MASTER = 0x42; +uint16_t local_address = I2C_ADDRESS; // slave + +// Keep this structure in sync with the i2c-P2P-master example. Should be in shared header. +struct MESSAGE_DATA { + uint8_t sequence; + uint16_t crc16; + uint8_t data[26]; + uint8_t terminator; +}; + +MESSAGE_DATA message; +MESSAGE_DATA msgdata; + +Crc16 crc; +byte seq = 0; + +// forward declarations +uint16_t calculateCRC16(uint8_t *data, size_t length); +void sendEvent(int a, String msg); +void sendMessage(int seq, String msg); +void receiveEvent(int howMany); +MESSAGE_DATA validateMessage(char* bytes_message); + +// + +// should be in shared header +uint16_t calculateCRC16(uint8_t *data, size_t length) { + crc.clearCrc(); + unsigned short value = crc.XModemCrc(data, 0, length); + Serial.print("crc = 0x"); Serial.println(value, HEX); + return (uint16_t)value; +} + +void setup() { + + // Enable internal pullup (there's always one from the master side) + //digitalWrite(SDA_PIN, HIGH); + //digitalWrite(SCL_PIN, HIGH); + + pinMode(LED_PIN, OUTPUT); + digitalWrite(LED_PIN, LOW); + + Wire.pins(SDA_PIN, SCL_PIN); + Wire.begin(I2C_ADDRESS); // address required for slave + + Serial.begin(230400); + //while (!Serial); if you want to wait for first messages + + delay(2000); + digitalWrite(LED_PIN, HIGH); + + Wire.onReceive(receiveEvent); + + Serial.print("I2C Slave started on address: 0x0"); + Serial.println(I2C_ADDRESS, HEX); +} + +// should be in shared header +MESSAGE_DATA encodeMessage(String bytes) { + + msgdata.terminator = '.'; + + int datasize = sizeof(msgdata.data); + Serial.print("Encoding data of size: "); + Serial.println(datasize); + + // Generate new data set for the struct + for (size_t i = 0; i < datasize; i++) { + if (bytes.length() >= i) { + msgdata.data[i] = bytes[i]; + } else { + msgdata.data[i] = '\0'; + } + Serial.print(msgdata.data[i]); + Serial.print(" "); + } + Serial.println(); + msgdata.crc16 = calculateCRC16((uint8_t*) &msgdata.data[0], datasize); + Serial.print("Outgoing Message CRC16: "); Serial.println(msgdata.crc16, HEX); + return msgdata; +} + +// should be in shared header +MESSAGE_DATA validateMessage(char* bytes_message) { + + MESSAGE_DATA tmp; + memcpy(&tmp, bytes_message, sizeof(tmp)); + + // Validate terminator + if (tmp.terminator == '.') { + Serial.println("[OK] Terminator valid."); + } else { + Serial.print("[ERROR] Terminator invalid: '"); + Serial.print(tmp.terminator); + Serial.println("'"); + return tmp; + } + + int datasize = sizeof(tmp.data); + if (datasize != 28) { + Serial.print("Data of size: "); Serial.println(datasize); + if (datasize > 28) { + datasize == 28; + } + } + + // Calculate data CRC + uint16_t data_crc = calculateCRC16((uint8_t*) &tmp.data[0], sizeof(datasize)); + + // should be only when CRC is good like commented below + char inmsg[datasize]; + memcpy(inmsg, &tmp.data, datasize); + + // Validate incoming data CRC against remote CRC + if (tmp.crc16 == data_crc) { + Serial.println("[OK] Data CRC valid."); + Serial.print("SLAVE Incoming message: "); Serial.println(String(inmsg)); + } else { + Serial.print("CRC-A = 0x"); + Serial.println(tmp.crc16, HEX); + Serial.print("CRC-B = 0x"); + Serial.println(data_crc, HEX); + Serial.print("tmp CRC16: "); + Serial.println(tmp.crc16, HEX); + Serial.print("SLAVE Incoming message: "); Serial.println(String(inmsg)); + Serial.println("[ERROR] TODO: Request retransfer exception."); + return tmp; + } + + // Validate sequence number ( should be already updated from byteParser ) + uint8_t remote_sequence = tmp.sequence; + if (remote_sequence != seq) { + Serial.println((char*)tmp.data); + } + + msgdata = tmp; // tmp is valid, assign to result address + + return msgdata; + +} + +void receiveEvent(int howMany) { + + Serial.print("Received "); Serial.print(howMany); Serial.println(" bytes..."); + char c; + char chars[howMany]; + chars[howMany - 1] = '\0'; + int index = 0; + + Serial.print("Local Sequence: "); Serial.println((int)seq); + digitalWrite(LED_PIN, LOW); + + bool requestRetransfer = false; + + unsigned long rtimeout = millis() + 200; // skip 100ms timeouts + while (millis() < rtimeout) { + while (0 < Wire.available()) { // loop through all but the last + //digitalWrite(LED_PIN, LOW); + c = Wire.read(); + chars[index] = c; + //Serial.print(index); Serial.print(" : "); Serial.println((int)c); + Serial.print((int)c); + Serial.print(" "); + + // Parses first byte for sequence number, contains recovery logic... + if (index == 0) { + + Serial.print("Remote Sequence: "); Serial.println((int)c); + + if ( c!= seq && ((c > seq - 4) || (c < seq + 4)) && c != seq + 1) { + Serial.print("[DIFF] Sequence offset [!]: "); + Serial.println(c - seq); + Serial.print("Re-assigning sequence number: "); + Serial.println(seq); + seq = c; + requestRetransfer = true; + + } else if (c != seq + 1) { + + Serial.print("[+DIFF] Local Sequence: "); + Serial.println(seq); + Serial.print("[+DIFF] Sequence offset [!]: "); + Serial.println(c - seq); + requestRetransfer = true; + } + + if (seq == 0) { + Serial.print("Assigning sequence 0: "); + Serial.println(seq); + seq = c; + + } else if (c != seq + 1) { + Serial.print("Re-assigning sequence number: "); + Serial.println(seq); + seq = c; + } + seq = c; + + } // if 0 + + digitalWrite(LED_PIN, HIGH); + index++; + } // while + } // while + + Serial.println(String(chars)); + + if (requestRetransfer) { + String event = String("R") + String(seq) + String('\0'); + sendMessage(seq, event); + } else { + + } + + int error = 0; + Serial.print("Decoding data of size: "); Serial.println(sizeof(chars)); + message = validateMessage(chars); // &error + + // TODO: Do something with the message. + char inmessage[5] = {0}; + memcpy(inmessage, (const char*)&message.data, 4); + String inmsg = String(inmessage); + if (inmsg.indexOf("MESA") == 0) { + String event = String("PONG"); + sendMessage(seq, event); + } + +} + +void sendMessage(int seq, String msg) { + Wire.beginTransmission(0x42); // transmit to device #8 + //Sending Side + MESSAGE_DATA struct_data = encodeMessage(msg); + struct_data.sequence = seq; + char b[sizeof(struct_data)]; + memcpy(b, &struct_data, sizeof(struct_data)); + Serial.print("Sending message of size "); Serial.print(sizeof(struct_data)); Serial.println(); + Serial.print("'"); + for (int i = 0; i < sizeof(struct_data); i++) { + Wire.write(b[i]); + Serial.print(b[i]); + } + Serial.println("' sent..."); + Wire.endTransmission(); // stop transmitting +} + +// wire_transmit +void sendEvent(int a, String msg) { + Serial.print("Sending "); + Serial.println(msg); + Wire.beginTransmission(0x42); // transmit to master + Wire.write(a); + Wire.write(";"); // sends five bytes + Wire.write(msg.c_str()); + Wire.endTransmission(); // stop transmitting +} + +void loop() { + // nothing here, slave receives data and sends reply in own callback +} From ace0b371973c4b2ec2ab0c2ea2f4dbc4e38d2d81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Wed, 21 Nov 2018 22:45:50 +0100 Subject: [PATCH 02/13] fixes with regards to Travis CI help --- .../i2c-P2P-master/i2c-P2P-master.ino | 93 +++++++++---------- .../examples/i2c-P2P-slave/i2c-P2P-slave.ino | 46 +++++---- 2 files changed, 68 insertions(+), 71 deletions(-) diff --git a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino index 51fd40cf7a..1032feffaf 100644 --- a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino +++ b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino @@ -1,28 +1,25 @@ -/* - * ESP8266 I2C master-slave communication, requires Arduno Core with I2C Slave Support (2.5.0+) - * +/* + * ESP8266 I2C master-slave communication, requires Arduno Core with I2C Slave Support (2.5.0+) + * * Expects two ESP8266 devices with three pins connected: GND, SDA and SCL. This is master. * Will send "MESA" messages to predefined slave address and then expect "PONG" response, * or request to retransfer if message was misunderstood (e.g. CRC check failed). * Message can be up to 26 bytes long (plus wrapper). - * + * * 21-11-2018: initial drop by Matej Sychra (github.com/suculent) */ #include +#include "crc16.h" #include "i2c-scanner.h" -#define WIRE_SDA D1 -#define WIRE_SCL D2 - -#include "crc16.h" - -#define LED_PIN D4 +#define WIRE_SDA 4 // D1 +#define WIRE_SCL 5 // D2 +#define LED_PIN 12 // D4 const int16_t I2C_MASTER = 0x42; const int16_t I2C_SLAVE = 0x08; - int16_t slave_address = I2C_SLAVE; // may be overridden using scan() // Keep this structure in sync with the i2c-P2P-slave example. Should be in shared header. @@ -34,9 +31,11 @@ struct MESSAGE_DATA { }; MESSAGE_DATA msgdata; + Crc16 crc; -bool expect_pong = false; byte sequence = 0; + +bool expect_pong = false; unsigned long next_ping = millis() + 1000; // analytics @@ -54,35 +53,35 @@ MESSAGE_DATA validateMessage(char* bytes_message); // should be in shared header uint16_t calculateCRC16(uint8_t *data, size_t length) { - crc.clearCrc(); + crc.clearCrc(); uint16_t value = (uint16_t)crc.XModemCrc(data,0,length); - Serial.print("crc = 0x"); Serial.println(value, HEX); + Serial.print("crc = 0x"); Serial.println(value, HEX); return value; } // should be in shared header MESSAGE_DATA encodeMessage(String bytes) { - - msgdata.terminator = '.'; - + + msgdata.terminator = '.'; + int datasize = sizeof(msgdata.data); Serial.print("\nEncoding data of size: "); Serial.println(datasize); - + // Generate new data set for the struct for (size_t i = 0; i < datasize; i++) { if (bytes.length() >= i) { - msgdata.data[i] = bytes[i]; + msgdata.data[i] = bytes[i]; } else { msgdata.data[i] = '\0'; } Serial.print(msgdata.data[i]); Serial.print(" "); - } + } Serial.print('\n'); msgdata.crc16 = calculateCRC16((uint8_t*) &msgdata.data[0], datasize); //Serial.print("ENCODED Message CRC16: "); Serial.println(msgdata.crc16, HEX); - return msgdata; + return msgdata; } // should be in shared header @@ -92,7 +91,7 @@ MESSAGE_DATA validateMessage(char* bytes_message) { memcpy(&tmp, bytes_message, sizeof(tmp)); // Validate PROTOCOL terminator - if (tmp.terminator != '.') { + if (tmp.terminator != '.') { Serial.print("[ERROR] Terminator invalid: '"); Serial.print(tmp.terminator); Serial.println("'"); @@ -100,16 +99,16 @@ MESSAGE_DATA validateMessage(char* bytes_message) { } int datasize = sizeof(tmp.data); - Serial.print("Data of size: "); Serial.println(datasize); + Serial.print("Data of size: "); Serial.println(datasize); uint16_t data_crc = calculateCRC16((uint8_t*) &tmp.data[0], datasize); // Validate incoming data CRC against remote CRC - if (tmp.crc16 == data_crc) { + if (tmp.crc16 == data_crc) { Serial.println("[OK] Data CRC valid."); char inmsg[datasize]; memcpy(inmsg, &tmp.data, datasize); - Serial.print("MASTER Incoming message: "); Serial.println(String(inmsg)); + Serial.print("MASTER Incoming message: "); Serial.println(String(inmsg)); } else { Serial.print("CRC-A = 0x"); Serial.println(tmp.crc16, HEX); @@ -120,7 +119,7 @@ MESSAGE_DATA validateMessage(char* bytes_message) { Serial.println("[ERROR] Request retransfer exception."); return tmp; } - + // Validate sequence number uint8_t remote_sequence = tmp.sequence; if (remote_sequence < sequence - 1) { @@ -137,16 +136,16 @@ MESSAGE_DATA validateMessage(char* bytes_message) { } void sendMessage(int seq, String msg) { - + Serial.print("[MASTER] Sending message: "); - Serial.print(msg); + Serial.print(msg); if (msg.indexOf("MESA") == 0) { expect_pong = true; } else { expect_pong = false; } - + Wire.beginTransmission(I2C_SLAVE); // transmit to device 0x08 //Sending Side MESSAGE_DATA struct_data = encodeMessage(msg); @@ -155,11 +154,11 @@ void sendMessage(int seq, String msg) { Serial.print(" of size "); Serial.println(sizeof(struct_data)); Serial.print("Encoding struct of size: "); Serial.println(sizeof(struct_data)); - memcpy(buf, &struct_data, sizeof(struct_data)); + memcpy(buf, &struct_data, sizeof(struct_data)); for (int i = 0; i < sizeof(struct_data); i++) { Wire.write(buf[i]); Serial.print(buf[i]);Serial.print(" "); - } + } Wire.endTransmission(); // stop transmitting Serial.println(""); } @@ -167,15 +166,15 @@ void sendMessage(int seq, String msg) { void receiveEvent(int howMany) { byte_count = byte_count + howMany; - + char incoming[howMany]; - incoming[howMany - 1] = '\0'; + incoming[howMany - 1] = '\0'; int index = 0; digitalWrite(LED_PIN, LOW); // message duration may not exceed 100 ms (100 bytes, 3x buffer retransferred) - unsigned long rtimeout = millis() + 100; + unsigned long rtimeout = millis() + 100; while (millis() < rtimeout) { // this must be fast, keep free from logging to serial here if possible while (0 < Wire.available()) { // loop through all but the last @@ -186,15 +185,15 @@ void receiveEvent(int howMany) { index++; } } - + Serial.println(); Serial.print("[MASTER] Received "); Serial.print(index); Serial.println(" bytes from SLAVE."); //Serial.print("[MASTER] Local Sequence: "); Serial.println((int)sequence); MESSAGE_DATA message = validateMessage(incoming); - + char inmsg[sizeof(message.data)]; memcpy(inmsg, &message.data, sizeof(message.data)); - if (inmsg[0] == 'R') { + if (inmsg[0] == 'R') { String retransfer_command = String(inmsg); retransfer_command.replace("R", ""); int retransfer_offset = retransfer_command.toInt(); @@ -207,8 +206,8 @@ void receiveEvent(int howMany) { // debug only, WARNING! may loose important messages in production sequence = retransfer_offset + 1; } - Serial.println(sequence); - } else { + Serial.println(sequence); + } else { // Serial.print("[MASTER] Incoming message from SLAVE: "); Serial.println(String(inmsg)); } @@ -231,10 +230,10 @@ void setup() { Wire.begin(I2C_MASTER); // join i2c bus (address optional for master) Wire.onReceive(receiveEvent); - Serial.begin(230400); // keep serial fast as possible for debug logging + Serial.begin(230400); // keep serial fast as possible for debug logging while (!Serial); pinMode(LED_PIN, OUTPUT); - digitalWrite(LED_PIN, HIGH); + digitalWrite(LED_PIN, HIGH); slave_address = scan(); // useful with master/slave devices only on the bus } @@ -250,22 +249,22 @@ void loop() { Serial.print(byte_count); Serial.println(" per second"); error_count = 0; - byte_count = 0; + byte_count = 0; second_timer = millis() + 1000; } - + if (millis() > next_ping) { digitalWrite(LED_PIN, LOW); - next_ping = millis() + 200; + next_ping = millis() + 200; Serial.print("[MASTER] Sequence » "); Serial.println(sequence); digitalWrite(LED_PIN, HIGH); - sendMessage(sequence, "MESA"); + sendMessage(sequence, "MESA"); if (expect_pong) { error_count++; } expect_pong = true; - sequence++; + sequence++; } - + } diff --git a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino index c9fc879938..6c1d185a51 100644 --- a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino +++ b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino @@ -1,21 +1,20 @@ -/* - * ESP8266 I2C master-slave communication, requires Arduno Core with I2C Slave Support (2.5.0+) - * +/* + * ESP8266 I2C master-slave communication, requires Arduno Core with I2C Slave Support (2.5.0+) + * * Expects two ESP8266 devices with three pins connected: GND, SDA and SCL. This is slave. - * Will wait for "MESA" message and then respond with "PONG" message, + * Will wait for "MESA" message and then respond with "PONG" message, * or request retransfer if message was misunderstood (e.g. CRC check failed). * Message can be up to 26 bytes long (plus wrapper). - * + * * 21-11-2018: initial drop by Matej Sychra (github.com/suculent) */ #include - #include "crc16.h" -#define SDA_PIN D1 -#define SCL_PIN D2 -#define LED_PIN D4 +#define SDA_PIN 4 // D1 +#define SCL_PIN 5 // D2 +#define LED_PIN 12 // D4 const uint16_t I2C_ADDRESS = 0x08; const uint16_t I2C_MASTER = 0x42; @@ -48,7 +47,7 @@ MESSAGE_DATA validateMessage(char* bytes_message); uint16_t calculateCRC16(uint8_t *data, size_t length) { crc.clearCrc(); unsigned short value = crc.XModemCrc(data, 0, length); - Serial.print("crc = 0x"); Serial.println(value, HEX); + Serial.print("crc = 0x"); Serial.println(value, HEX); return (uint16_t)value; } @@ -57,19 +56,19 @@ void setup() { // Enable internal pullup (there's always one from the master side) //digitalWrite(SDA_PIN, HIGH); //digitalWrite(SCL_PIN, HIGH); - + pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); Wire.pins(SDA_PIN, SCL_PIN); Wire.begin(I2C_ADDRESS); // address required for slave - + Serial.begin(230400); //while (!Serial); if you want to wait for first messages - + delay(2000); digitalWrite(LED_PIN, HIGH); - + Wire.onReceive(receiveEvent); Serial.print("I2C Slave started on address: 0x0"); @@ -78,13 +77,13 @@ void setup() { // should be in shared header MESSAGE_DATA encodeMessage(String bytes) { - + msgdata.terminator = '.'; - int datasize = sizeof(msgdata.data); + unsigned int datasize = sizeof(msgdata.data); Serial.print("Encoding data of size: "); Serial.println(datasize); - + // Generate new data set for the struct for (size_t i = 0; i < datasize; i++) { if (bytes.length() >= i) { @@ -94,7 +93,7 @@ MESSAGE_DATA encodeMessage(String bytes) { } Serial.print(msgdata.data[i]); Serial.print(" "); - } + } Serial.println(); msgdata.crc16 = calculateCRC16((uint8_t*) &msgdata.data[0], datasize); Serial.print("Outgoing Message CRC16: "); Serial.println(msgdata.crc16, HEX); @@ -121,7 +120,7 @@ MESSAGE_DATA validateMessage(char* bytes_message) { if (datasize != 28) { Serial.print("Data of size: "); Serial.println(datasize); if (datasize > 28) { - datasize == 28; + datasize = 28; } } @@ -129,12 +128,12 @@ MESSAGE_DATA validateMessage(char* bytes_message) { uint16_t data_crc = calculateCRC16((uint8_t*) &tmp.data[0], sizeof(datasize)); // should be only when CRC is good like commented below - char inmsg[datasize]; + char inmsg[datasize]; memcpy(inmsg, &tmp.data, datasize); - + // Validate incoming data CRC against remote CRC if (tmp.crc16 == data_crc) { - Serial.println("[OK] Data CRC valid."); + Serial.println("[OK] Data CRC valid."); Serial.print("SLAVE Incoming message: "); Serial.println(String(inmsg)); } else { Serial.print("CRC-A = 0x"); @@ -233,7 +232,6 @@ void receiveEvent(int howMany) { } - int error = 0; Serial.print("Decoding data of size: "); Serial.println(sizeof(chars)); message = validateMessage(chars); // &error @@ -257,7 +255,7 @@ void sendMessage(int seq, String msg) { memcpy(b, &struct_data, sizeof(struct_data)); Serial.print("Sending message of size "); Serial.print(sizeof(struct_data)); Serial.println(); Serial.print("'"); - for (int i = 0; i < sizeof(struct_data); i++) { + for (unsigned int i = 0; i < sizeof(struct_data); i++) { Wire.write(b[i]); Serial.print(b[i]); } From ba488f789e96294af1dbe97b3e4274dbbc8e3a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Wed, 21 Nov 2018 23:26:35 +0100 Subject: [PATCH 03/13] oh, the warnings. now the goes to default but address needs to be set anyway --- libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino | 2 +- libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino index 1032feffaf..d935f58966 100644 --- a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino +++ b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino @@ -226,7 +226,7 @@ void setup() { delay(2000); - Wire.pins(WIRE_SDA, WIRE_SCL); + // Wire.pins(WIRE_SDA, WIRE_SCL); // should set pins before address init Wire.begin(I2C_MASTER); // join i2c bus (address optional for master) Wire.onReceive(receiveEvent); diff --git a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino index 6c1d185a51..4d6ae64990 100644 --- a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino +++ b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino @@ -60,7 +60,7 @@ void setup() { pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); - Wire.pins(SDA_PIN, SCL_PIN); + // Wire.pins(WIRE_SDA, WIRE_SCL); // should set pins before address init Wire.begin(I2C_ADDRESS); // address required for slave Serial.begin(230400); From 716f3a0b3d448c772a486a5a235007fc8bfcab56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Wed, 21 Nov 2018 23:30:32 +0100 Subject: [PATCH 04/13] proposing new init method with pins and address, because pins() is deprecated and two begins are ambiguous --- libraries/Wire/Wire.cpp | 20 ++++++++++++++----- libraries/Wire/Wire.h | 4 ++-- .../i2c-P2P-master/i2c-P2P-master.ino | 3 +-- .../examples/i2c-P2P-slave/i2c-P2P-slave.ino | 3 +-- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index 7e86894991..f7e35d7f3b 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -69,6 +69,16 @@ void TwoWire::begin(int sda, int scl){ flush(); } +void TwoWire::begin(int sda, int scl, uint8_t address){ + default_sda_pin = sda; + default_scl_pin = scl; + twi_setAddress(address); + twi_init(sda, scl); + twi_attachSlaveTxEvent(onRequestService); + twi_attachSlaveRxEvent(onReceiveService); + flush(); +} + void TwoWire::pins(int sda, int scl){ default_sda_pin = sda; default_scl_pin = scl; @@ -224,17 +234,17 @@ void TwoWire::onReceiveService(uint8_t* inBytes, size_t numBytes) // if(rxBufferIndex < rxBufferLength){ // return; // } - + // copy twi rx buffer into local read buffer // this enables new reads to happen in parallel for (uint8_t i = 0; i < numBytes; ++i) { rxBuffer[i] = inBytes[i]; } - + // set rx iterator vars rxBufferIndex = 0; rxBufferLength = numBytes; - + // alert user program user_onReceive(numBytes); } @@ -245,12 +255,12 @@ void TwoWire::onRequestService(void) if (!user_onRequest) { return; } - + // reset tx buffer iterator vars // !!! this will kill any pending pre-master sendTo() activity txBufferIndex = 0; txBufferLength = 0; - + // alert user program user_onRequest(); } diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h index e697bcca07..a797a95960 100644 --- a/libraries/Wire/Wire.h +++ b/libraries/Wire/Wire.h @@ -51,6 +51,7 @@ class TwoWire : public Stream public: TwoWire(); void begin(int sda, int scl); + void begin(int sda, int scl, uint8_t address); void pins(int sda, int scl) __attribute__((deprecated)); // use begin(sda, scl) in new code void begin(); void begin(uint8_t); @@ -68,7 +69,7 @@ class TwoWire : public Stream uint8_t requestFrom(uint8_t, uint8_t, uint8_t); uint8_t requestFrom(int, int); uint8_t requestFrom(int, int, int); - + virtual size_t write(uint8_t); virtual size_t write(const uint8_t *, size_t); virtual int available(void); @@ -90,4 +91,3 @@ extern TwoWire Wire; #endif #endif - diff --git a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino index d935f58966..5abfd6e5bb 100644 --- a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino +++ b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino @@ -226,8 +226,7 @@ void setup() { delay(2000); - // Wire.pins(WIRE_SDA, WIRE_SCL); // should set pins before address init - Wire.begin(I2C_MASTER); // join i2c bus (address optional for master) + Wire.begin(WIRE_SDA, WIRE_SCL, I2C_MASTER); // join i2c bus (address optional for master) Wire.onReceive(receiveEvent); Serial.begin(230400); // keep serial fast as possible for debug logging diff --git a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino index 4d6ae64990..7657d785f3 100644 --- a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino +++ b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino @@ -60,8 +60,7 @@ void setup() { pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); - // Wire.pins(WIRE_SDA, WIRE_SCL); // should set pins before address init - Wire.begin(I2C_ADDRESS); // address required for slave + Wire.begin(SDA_PIN, SCL_PIN, I2C_ADDRESS); // address required for slave Serial.begin(230400); //while (!Serial); if you want to wait for first messages From 0473dbd9cdd49c21e954cb1cec21289da28ed048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Mon, 26 Nov 2018 12:28:55 +0100 Subject: [PATCH 05/13] type fixed in 3rd party code, removing I2C scanner (duplicate of another example) --- .../Wire/examples/i2c-P2P-master/crc16.h | 75 ++++++++++--------- .../examples/i2c-P2P-master/i2c-scanner.h | 43 ----------- libraries/Wire/examples/i2c-P2P-slave/crc16.h | 73 +++++++++--------- 3 files changed, 79 insertions(+), 112 deletions(-) delete mode 100644 libraries/Wire/examples/i2c-P2P-master/i2c-scanner.h diff --git a/libraries/Wire/examples/i2c-P2P-master/crc16.h b/libraries/Wire/examples/i2c-P2P-master/crc16.h index 1f2d724acf..f745dacb8b 100644 --- a/libraries/Wire/examples/i2c-P2P-master/crc16.h +++ b/libraries/Wire/examples/i2c-P2P-master/crc16.h @@ -5,6 +5,7 @@ // History // 0.1.0 31/05/2014: First public code release // 0.1.1 17/12/2014: Minor revision and commented code +// 0.1.2 24/11/2018: Minor code style fixes (by @devyte and @suculent) // // License // "MIT Open Source Software License": @@ -27,7 +28,7 @@ //------------------------------------------------------------------------------------- #ifndef CRC16_H #define CRC16_H -#define LIBRARY_VERSION_CRC16_H "0.1.1" +#define LIBRARY_VERSION_CRC16_H "0.1.2" #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" @@ -45,12 +46,12 @@ class Crc16 { uint16_t _xorIn; uint16_t _xorOut; uint16_t _polynomial; - uint8_t _reflectIn; - uint8_t _reflectOut; + bool _reflectIn; + bool _reflectOut; //Crc value uint16_t _crc; uint8_t reflect(uint8_t data, uint8_t bits = 32); - + public: inline Crc16() { @@ -64,7 +65,7 @@ class Crc16 { _mask = 0xFFFF; _crc = _xorIn; } - inline Crc16(uint8_t reflectIn, uint8_t reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask) + inline Crc16(bool reflectIn, bool reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask) { _reflectIn = reflectIn; _reflectOut = reflectOut; @@ -78,8 +79,8 @@ class Crc16 { inline void clearCrc(); inline void updateCrc(uint8_t data); inline uint16_t getCrc(); - inline unsigned int fastCrc(uint8_t data[], uint8_t start, uint16_t length, uint8_t reflectIn, uint8_t reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask); - inline unsigned int XModemCrc(uint8_t data[], uint8_t start, uint16_t length) + inline unsigned int fastCrc(const uint8_t *data, uint8_t start, uint16_t length, bool reflectIn, bool reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask); + inline unsigned int XModemCrc(const uint8_t *data, const uint8_t start, const uint16_t length) { // XModem parameters: poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 return fastCrc(data, start, length, false, false, 0x1021, 0x0000, 0x0000, 0x8000, 0xffff); @@ -98,27 +99,28 @@ void Crc16::clearCrc() //--------------------------------------------------- void Crc16::updateCrc(uint8_t data) { - if (_reflectIn != 0) + if (_reflectIn != 0) { data = (uint8_t) reflect(data, 8); - + } + int j = 0x80; - + while (j > 0) { uint16_t bit = (uint16_t)(_crc & _msbMask); - + _crc <<= 1; - + if ((data & j) != 0) { bit = (uint16_t)(bit ^ _msbMask); } - + if (bit != 0) { _crc ^= _polynomial; } - + j >>= 1; } } @@ -128,9 +130,10 @@ void Crc16::updateCrc(uint8_t data) //--------------------------------------------------- uint16_t Crc16::getCrc() { - if (_reflectOut != 0) + if (_reflectOut != 0) { _crc = (unsigned int)((reflect(_crc) ^ _xorOut) & _mask); - + } + return _crc; } @@ -142,47 +145,50 @@ uint16_t Crc16::getCrc() // XModem: width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3 // CCITT-False: width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 //--------------------------------------------------- -unsigned int Crc16::fastCrc(uint8_t data[], uint8_t start, uint16_t length, uint8_t reflectIn, uint8_t reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask) +unsigned int Crc16::fastCrc(const uint8_t *data, uint8_t start, uint16_t length, bool reflectIn, bool reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask) { unsigned int crc = xorIn; - + int j; uint8_t c; unsigned int bit; - - if (length == 0) return crc; - - for (int i = start; i < (start + length); i++) + + if (length == 0) { + return crc; + } + + for (int i = start; i < (start + length); ++i) { c = data[i]; - + if (reflectIn != 0) c = (uint8_t) reflect(c, 8); - + j = 0x80; - + while (j > 0) { bit = (unsigned int)(crc & msbMask); crc <<= 1; - + if ((c & j) != 0) { bit = (unsigned int)(bit ^ msbMask); } - + if (bit != 0) { crc ^= polynomial; } - + j >>= 1; } } - - if (reflectOut != 0) + + if (reflectOut != 0) { crc = (unsigned int)((reflect(crc) ^ xorOut) & mask); - + } + return crc; } @@ -196,14 +202,13 @@ uint8_t Crc16::reflect(uint8_t data, uint8_t bits) for (uint8_t bit = 0; bit < bits; bit++) { // If the LSB bit is set, set the reflection of it. - if ((data & 0x01) != 0) - { + if ((data & 0x01) != 0) { reflection |= (unsigned long)(1 << ((bits - 1) - bit)); } - + data = (uint8_t)(data >> 1); } - + return reflection; } #endif diff --git a/libraries/Wire/examples/i2c-P2P-master/i2c-scanner.h b/libraries/Wire/examples/i2c-P2P-master/i2c-scanner.h deleted file mode 100644 index 987e87b66e..0000000000 --- a/libraries/Wire/examples/i2c-P2P-master/i2c-scanner.h +++ /dev/null @@ -1,43 +0,0 @@ -/* ESP8266 I2C master-slave communication, requires i2c_slave by bjoham */ - -#include - -int scan(uint16_t) { - byte error, address; - int nDevices; - int aDevice = 0; - - Serial.println("Scanning..."); - - nDevices = 0; - for (address = 1; address < 127; address++) { - Wire.beginTransmission(address); - error = Wire.endTransmission(); - - if (error == 0) { - Serial.print("I2C device found at address 0x"); - if (address < 16) { - Serial.print("0"); - } - Serial.print(address, HEX); - Serial.println(" !"); - nDevices++; - aDevice = address; - - } else if (error == 4) { - Serial.print("Unknown error at address 0x"); - if (address < 16) { - Serial.print("0"); - } - Serial.println(address, HEX); - } - } - - if (nDevices == 0) { - Serial.println("No I2C devices found\n"); - } else { - Serial.println("Done.\n"); - } - - return aDevice; -} diff --git a/libraries/Wire/examples/i2c-P2P-slave/crc16.h b/libraries/Wire/examples/i2c-P2P-slave/crc16.h index 1f2d724acf..8e4c9115a2 100644 --- a/libraries/Wire/examples/i2c-P2P-slave/crc16.h +++ b/libraries/Wire/examples/i2c-P2P-slave/crc16.h @@ -5,6 +5,7 @@ // History // 0.1.0 31/05/2014: First public code release // 0.1.1 17/12/2014: Minor revision and commented code +// 0.1.2 24/11/2018: Minor code style fixes (by @devyte and @suculent) // // License // "MIT Open Source Software License": @@ -27,7 +28,7 @@ //------------------------------------------------------------------------------------- #ifndef CRC16_H #define CRC16_H -#define LIBRARY_VERSION_CRC16_H "0.1.1" +#define LIBRARY_VERSION_CRC16_H "0.1.2" #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" @@ -45,12 +46,12 @@ class Crc16 { uint16_t _xorIn; uint16_t _xorOut; uint16_t _polynomial; - uint8_t _reflectIn; - uint8_t _reflectOut; + bool _reflectIn; + bool _reflectOut; //Crc value uint16_t _crc; uint8_t reflect(uint8_t data, uint8_t bits = 32); - + public: inline Crc16() { @@ -64,7 +65,7 @@ class Crc16 { _mask = 0xFFFF; _crc = _xorIn; } - inline Crc16(uint8_t reflectIn, uint8_t reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask) + inline Crc16(bool reflectIn, bool reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask) { _reflectIn = reflectIn; _reflectOut = reflectOut; @@ -78,8 +79,8 @@ class Crc16 { inline void clearCrc(); inline void updateCrc(uint8_t data); inline uint16_t getCrc(); - inline unsigned int fastCrc(uint8_t data[], uint8_t start, uint16_t length, uint8_t reflectIn, uint8_t reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask); - inline unsigned int XModemCrc(uint8_t data[], uint8_t start, uint16_t length) + inline unsigned int fastCrc(const uint8_t *data, uint8_t start, uint16_t length, bool reflectIn, bool reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask); + inline unsigned int XModemCrc(const uint8_t *data, const uint8_t start, const uint16_t length) { // XModem parameters: poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 return fastCrc(data, start, length, false, false, 0x1021, 0x0000, 0x0000, 0x8000, 0xffff); @@ -98,27 +99,28 @@ void Crc16::clearCrc() //--------------------------------------------------- void Crc16::updateCrc(uint8_t data) { - if (_reflectIn != 0) + if (_reflectIn != 0) { data = (uint8_t) reflect(data, 8); - + } + int j = 0x80; - + while (j > 0) { uint16_t bit = (uint16_t)(_crc & _msbMask); - + _crc <<= 1; - + if ((data & j) != 0) { bit = (uint16_t)(bit ^ _msbMask); } - + if (bit != 0) { _crc ^= _polynomial; } - + j >>= 1; } } @@ -128,9 +130,10 @@ void Crc16::updateCrc(uint8_t data) //--------------------------------------------------- uint16_t Crc16::getCrc() { - if (_reflectOut != 0) + if (_reflectOut != 0) { _crc = (unsigned int)((reflect(_crc) ^ _xorOut) & _mask); - + } + return _crc; } @@ -142,47 +145,50 @@ uint16_t Crc16::getCrc() // XModem: width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3 // CCITT-False: width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 //--------------------------------------------------- -unsigned int Crc16::fastCrc(uint8_t data[], uint8_t start, uint16_t length, uint8_t reflectIn, uint8_t reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask) +unsigned int Crc16::fastCrc(const uint8_t *data, uint8_t start, uint16_t length, bool reflectIn, bool reflectOut, uint16_t polynomial, uint16_t xorIn, uint16_t xorOut, uint16_t msbMask, uint16_t mask) { unsigned int crc = xorIn; - + int j; uint8_t c; unsigned int bit; - - if (length == 0) return crc; - + + if (length == 0) { + return crc; + } + for (int i = start; i < (start + length); i++) { c = data[i]; - + if (reflectIn != 0) c = (uint8_t) reflect(c, 8); - + j = 0x80; - + while (j > 0) { bit = (unsigned int)(crc & msbMask); crc <<= 1; - + if ((c & j) != 0) { bit = (unsigned int)(bit ^ msbMask); } - + if (bit != 0) { crc ^= polynomial; } - + j >>= 1; } } - - if (reflectOut != 0) + + if (reflectOut != 0) { crc = (unsigned int)((reflect(crc) ^ xorOut) & mask); - + } + return crc; } @@ -196,14 +202,13 @@ uint8_t Crc16::reflect(uint8_t data, uint8_t bits) for (uint8_t bit = 0; bit < bits; bit++) { // If the LSB bit is set, set the reflection of it. - if ((data & 0x01) != 0) - { + if ((data & 0x01) != 0) { reflection |= (unsigned long)(1 << ((bits - 1) - bit)); } - + data = (uint8_t)(data >> 1); } - + return reflection; } #endif From d558bfe93d35d7e9928e4c437546881c217becca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Mon, 26 Nov 2018 12:30:43 +0100 Subject: [PATCH 06/13] type fix in onReceive callback --- libraries/Wire/Wire.cpp | 4 ++-- libraries/Wire/Wire.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index f7e35d7f3b..4124b44f1a 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -51,7 +51,7 @@ uint8_t TwoWire::txBufferLength = 0; uint8_t TwoWire::transmitting = 0; void (*TwoWire::user_onRequest)(void); -void (*TwoWire::user_onReceive)(int); +void (*TwoWire::user_onReceive)(size_t); static int default_sda_pin = SDA; static int default_scl_pin = SCL; @@ -265,7 +265,7 @@ void TwoWire::onRequestService(void) user_onRequest(); } -void TwoWire::onReceive( void (*function)(int) ) { +void TwoWire::onReceive( void (*function)(size_t) ) { user_onReceive = function; } diff --git a/libraries/Wire/Wire.h b/libraries/Wire/Wire.h index a797a95960..a1cae697c7 100644 --- a/libraries/Wire/Wire.h +++ b/libraries/Wire/Wire.h @@ -45,7 +45,7 @@ class TwoWire : public Stream static uint8_t transmitting; static void (*user_onRequest)(void); - static void (*user_onReceive)(int); + static void (*user_onReceive)(size_t); static void onRequestService(void); static void onReceiveService(uint8_t*, size_t); public: @@ -76,7 +76,7 @@ class TwoWire : public Stream virtual int read(void); virtual int peek(void); virtual void flush(void); - void onReceive( void (*)(int) ); + void onReceive( void (*)(size_t) ); void onRequest( void (*)(void) ); inline size_t write(unsigned long n) { return write((uint8_t)n); } From 21dfde20a2446935e36dffd695d10e951bc95424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Mon, 26 Nov 2018 12:31:31 +0100 Subject: [PATCH 07/13] implemented changes proposed by code review --- .../i2c-P2P-master/i2c-P2P-master.ino | 146 +++++++++--------- .../examples/i2c-P2P-slave/i2c-P2P-slave.ino | 71 ++++----- 2 files changed, 110 insertions(+), 107 deletions(-) diff --git a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino index 5abfd6e5bb..c766334f7a 100644 --- a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino +++ b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino @@ -12,42 +12,40 @@ #include #include "crc16.h" -#include "i2c-scanner.h" - -#define WIRE_SDA 4 // D1 -#define WIRE_SCL 5 // D2 +#define SDA_PIN 4 // D1 +#define SCL_PIN 5 // D2 #define LED_PIN 12 // D4 const int16_t I2C_MASTER = 0x42; const int16_t I2C_SLAVE = 0x08; -int16_t slave_address = I2C_SLAVE; // may be overridden using scan() +int16_t slave_address = I2C_SLAVE; // Keep this structure in sync with the i2c-P2P-slave example. Should be in shared header. -struct MESSAGE_DATA { +struct MessageData { uint8_t sequence; uint16_t crc16; uint8_t data[26]; uint8_t terminator; }; -MESSAGE_DATA msgdata; +MessageData msgdata; Crc16 crc; byte sequence = 0; -bool expect_pong = false; -unsigned long next_ping = millis() + 1000; +bool expectPong = false; +unsigned long nextPing = millis() + 1000; // analytics -uint16_t error_count = 0; -uint16_t byte_count = 0; +uint16_t errorCount = 0; +uint16_t byteCount = 0; // forward declarations -uint16_t calculateCRC16(uint8_t *data, size_t length); -void sendMessage(int seq, String msg); -MESSAGE_DATA encodeMessage(String bytes); -void receiveEvent(int howMany); -MESSAGE_DATA validateMessage(char* bytes_message); +uint16_t calculateCRC16(const uint8_t *data, size_t length); +void sendMessage(const int seq, const String &msg); +MessageData encodeMessage(const String &bytes); +void receiveEvent(const size_t howMany); +bool validateMessage(const char* bytes, MessageData &tmp); // @@ -55,12 +53,15 @@ MESSAGE_DATA validateMessage(char* bytes_message); uint16_t calculateCRC16(uint8_t *data, size_t length) { crc.clearCrc(); uint16_t value = (uint16_t)crc.XModemCrc(data,0,length); - Serial.print("crc = 0x"); Serial.println(value, HEX); + Serial.print("crc = 0x"); + Serial.println(value, HEX); return value; } // should be in shared header -MESSAGE_DATA encodeMessage(String bytes) { +MessageData encodeMessage(const String &instring) { + + MessageData msgdata; msgdata.terminator = '.'; @@ -69,9 +70,9 @@ MESSAGE_DATA encodeMessage(String bytes) { Serial.println(datasize); // Generate new data set for the struct - for (size_t i = 0; i < datasize; i++) { - if (bytes.length() >= i) { - msgdata.data[i] = bytes[i]; + for (size_t i = 0; i < datasize; ++i) { + if (instring.length() >= i) { + msgdata.data[i] = instring[i]; } else { msgdata.data[i] = '\0'; } @@ -80,26 +81,23 @@ MESSAGE_DATA encodeMessage(String bytes) { } Serial.print('\n'); msgdata.crc16 = calculateCRC16((uint8_t*) &msgdata.data[0], datasize); - //Serial.print("ENCODED Message CRC16: "); Serial.println(msgdata.crc16, HEX); return msgdata; } // should be in shared header -MESSAGE_DATA validateMessage(char* bytes_message) { - - MESSAGE_DATA tmp; - memcpy(&tmp, bytes_message, sizeof(tmp)); +bool validateMessage(const char* bytes, MessageData &tmp) { // Validate PROTOCOL terminator if (tmp.terminator != '.') { Serial.print("[ERROR] Terminator invalid: '"); Serial.print(tmp.terminator); Serial.println("'"); - return tmp; // should be nullptr // TODO: return error + return false; } int datasize = sizeof(tmp.data); - Serial.print("Data of size: "); Serial.println(datasize); + Serial.print("Data of size: "); + Serial.println(datasize); uint16_t data_crc = calculateCRC16((uint8_t*) &tmp.data[0], datasize); @@ -108,7 +106,8 @@ MESSAGE_DATA validateMessage(char* bytes_message) { Serial.println("[OK] Data CRC valid."); char inmsg[datasize]; memcpy(inmsg, &tmp.data, datasize); - Serial.print("MASTER Incoming message: "); Serial.println(String(inmsg)); + Serial.print("MASTER Incoming message: "); + Serial.println(String(inmsg)); } else { Serial.print("CRC-A = 0x"); Serial.println(tmp.crc16, HEX); @@ -117,7 +116,7 @@ MESSAGE_DATA validateMessage(char* bytes_message) { Serial.print("tmp CRC16: "); Serial.println(tmp.crc16, HEX); Serial.println("[ERROR] Request retransfer exception."); - return tmp; + return true; } // Validate sequence number @@ -129,43 +128,42 @@ MESSAGE_DATA validateMessage(char* bytes_message) { Serial.println(sequence); // TODO: return error } - msgdata = tmp; // tmp is valid, assign to result address - - return tmp; - + return true; } -void sendMessage(int seq, String msg) { +void sendMessage(const int seq, const String &msg) { Serial.print("[MASTER] Sending message: "); Serial.print(msg); if (msg.indexOf("MESA") == 0) { - expect_pong = true; + expectPong = true; } else { - expect_pong = false; + expectPong = false; } - Wire.beginTransmission(I2C_SLAVE); // transmit to device 0x08 + Wire.beginTransmission(I2C_SLAVE); //Sending Side - MESSAGE_DATA struct_data = encodeMessage(msg); + MessageData struct_data = encodeMessage(msg); struct_data.sequence = seq; char buf[sizeof(struct_data)]; Serial.print(" of size "); Serial.println(sizeof(struct_data)); - Serial.print("Encoding struct of size: "); Serial.println(sizeof(struct_data)); + Serial.print("Encoding struct of size: "); + Serial.println(sizeof(struct_data)); memcpy(buf, &struct_data, sizeof(struct_data)); - for (int i = 0; i < sizeof(struct_data); i++) { + for (int i = 0; i < sizeof(struct_data); ++i) { Wire.write(buf[i]); - Serial.print(buf[i]);Serial.print(" "); + Serial.print(buf[i]); + Serial.print(" "); } Wire.endTransmission(); // stop transmitting Serial.println(""); } -void receiveEvent(int howMany) { +void receiveEvent(const size_t howMany) { - byte_count = byte_count + howMany; + byteCount = byteCount + howMany; char incoming[howMany]; incoming[howMany - 1] = '\0'; @@ -173,23 +171,31 @@ void receiveEvent(int howMany) { digitalWrite(LED_PIN, LOW); - // message duration may not exceed 100 ms (100 bytes, 3x buffer retransferred) - unsigned long rtimeout = millis() + 100; - while (millis() < rtimeout) { + unsigned long interval = 100; + unsigned long currentMillis = millis(); + unsigned long previousMillis = millis(); + // message duration may not exceed 100 ms (100 bytes, 3x buffer retransferred) + if(currentMillis - previousMillis > interval) { + previousMillis = currentMillis; // this must be fast, keep free from logging to serial here if possible while (0 < Wire.available()) { // loop through all but the last int c = Wire.read(); // receive byte as a character if (index < howMany) { incoming[index] = (char)c; // save the character } - index++; + ++index; } } - Serial.println(); Serial.print("[MASTER] Received "); Serial.print(index); Serial.println(" bytes from SLAVE."); - //Serial.print("[MASTER] Local Sequence: "); Serial.println((int)sequence); + Serial.println(); + Serial.print("[MASTER] Received "); + Serial.print(index); + Serial.println(" bytes from SLAVE."); + Serial.println((int)sequence); + + MessageData message; - MESSAGE_DATA message = validateMessage(incoming); + bool success = validateMessage(incoming, message); char inmsg[sizeof(message.data)]; memcpy(inmsg, &message.data, sizeof(message.data)); @@ -200,25 +206,22 @@ void receiveEvent(int howMany) { Serial.println(sequence); Serial.print("[MASTER] Retransfer request: "); // dumb retransfer, only changes sequence number when expecting PONG - if (expect_pong) { + if (expectPong) { sequence = retransfer_offset + 1; } else { // debug only, WARNING! may loose important messages in production sequence = retransfer_offset + 1; } Serial.println(sequence); - } else { - // Serial.print("[MASTER] Incoming message from SLAVE: "); Serial.println(String(inmsg)); } String instring = String(inmsg); if (instring.indexOf("PONG")) { // alles kitz... - expect_pong = false; + expectPong = false; } // Do something with the message... - digitalWrite(LED_PIN, HIGH); } @@ -226,43 +229,42 @@ void setup() { delay(2000); - Wire.begin(WIRE_SDA, WIRE_SCL, I2C_MASTER); // join i2c bus (address optional for master) + Wire.pins(SDA_PIN, SCL_PIN); + Wire.begin(I2C_MASTER); + //Wire.begin(SDA_PIN, SCL_PIN, I2C_MASTER); // new syntax: join i2c bus (address optional for master) Wire.onReceive(receiveEvent); Serial.begin(230400); // keep serial fast as possible for debug logging while (!Serial); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); - - slave_address = scan(); // useful with master/slave devices only on the bus } -unsigned long second_timer = millis() + 1000; - +unsigned long secondTimer = millis() + 1000; void loop() { - if (millis() > second_timer) { + if (millis() > secondTimer) { Serial.print("Errors/Bytes: "); - Serial.print(error_count); + Serial.print(errorCount); Serial.print("/"); - Serial.print(byte_count); + Serial.print(byteCount); Serial.println(" per second"); - error_count = 0; - byte_count = 0; - second_timer = millis() + 1000; + errorCount = 0; + byteCount = 0; + secondTimer = millis() + 1000; } - if (millis() > next_ping) { + if (millis() > nextPing) { digitalWrite(LED_PIN, LOW); - next_ping = millis() + 200; + nextPing = millis() + 200; Serial.print("[MASTER] Sequence » "); Serial.println(sequence); digitalWrite(LED_PIN, HIGH); sendMessage(sequence, "MESA"); - if (expect_pong) { - error_count++; + if (expectPong) { + errorCount++; } - expect_pong = true; + expectPong = true; sequence++; } diff --git a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino index 7657d785f3..7c64ebf826 100644 --- a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino +++ b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino @@ -16,20 +16,19 @@ #define SCL_PIN 5 // D2 #define LED_PIN 12 // D4 -const uint16_t I2C_ADDRESS = 0x08; +const uint16_t I2C_SLAVE = 0x08; const uint16_t I2C_MASTER = 0x42; -uint16_t local_address = I2C_ADDRESS; // slave // Keep this structure in sync with the i2c-P2P-master example. Should be in shared header. -struct MESSAGE_DATA { +struct MessageData { uint8_t sequence; uint16_t crc16; uint8_t data[26]; uint8_t terminator; }; -MESSAGE_DATA message; -MESSAGE_DATA msgdata; +MessageData message; +MessageData msgdata; Crc16 crc; byte seq = 0; @@ -38,8 +37,8 @@ byte seq = 0; uint16_t calculateCRC16(uint8_t *data, size_t length); void sendEvent(int a, String msg); void sendMessage(int seq, String msg); -void receiveEvent(int howMany); -MESSAGE_DATA validateMessage(char* bytes_message); +void receiveEvent(const size_t howMany); +MessageData validateMessage(char* message_bytes); // @@ -53,6 +52,10 @@ uint16_t calculateCRC16(uint8_t *data, size_t length) { void setup() { + Serial.begin(230400); + while (!Serial); // if you want to wait for first messages + delay(2000); + // Enable internal pullup (there's always one from the master side) //digitalWrite(SDA_PIN, HIGH); //digitalWrite(SCL_PIN, HIGH); @@ -60,22 +63,22 @@ void setup() { pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); - Wire.begin(SDA_PIN, SCL_PIN, I2C_ADDRESS); // address required for slave - - Serial.begin(230400); - //while (!Serial); if you want to wait for first messages - - delay(2000); + Wire.pins(SDA_PIN, SCL_PIN); + Serial.println("I2C Slave begin..."); + Wire.begin(I2C_SLAVE); + //Wire.begin(SDA_PIN, SCL_PIN, I2C_SLAVE); // new syntax: join i2c bus (address required for slave) + digitalWrite(LED_PIN, HIGH); + Serial.println("I2C Slave attaching callback..."); Wire.onReceive(receiveEvent); Serial.print("I2C Slave started on address: 0x0"); - Serial.println(I2C_ADDRESS, HEX); + Serial.println(I2C_SLAVE, HEX); } // should be in shared header -MESSAGE_DATA encodeMessage(String bytes) { +MessageData encodeMessage(String bytes) { msgdata.terminator = '.'; @@ -84,7 +87,7 @@ MESSAGE_DATA encodeMessage(String bytes) { Serial.println(datasize); // Generate new data set for the struct - for (size_t i = 0; i < datasize; i++) { + for (size_t i = 0; i < datasize; ++i) { if (bytes.length() >= i) { msgdata.data[i] = bytes[i]; } else { @@ -100,10 +103,10 @@ MESSAGE_DATA encodeMessage(String bytes) { } // should be in shared header -MESSAGE_DATA validateMessage(char* bytes_message) { +MessageData validateMessage(char* message_bytes) { - MESSAGE_DATA tmp; - memcpy(&tmp, bytes_message, sizeof(tmp)); + MessageData tmp; + memcpy(&tmp, message_bytes, sizeof(tmp)); // Validate terminator if (tmp.terminator == '.') { @@ -158,7 +161,7 @@ MESSAGE_DATA validateMessage(char* bytes_message) { } -void receiveEvent(int howMany) { +void receiveEvent(const size_t howMany) { Serial.print("Received "); Serial.print(howMany); Serial.println(" bytes..."); char c; @@ -171,8 +174,8 @@ void receiveEvent(int howMany) { bool requestRetransfer = false; - unsigned long rtimeout = millis() + 200; // skip 100ms timeouts - while (millis() < rtimeout) { + unsigned long rtimeout = millis(); + while (millis() - rtimeout < 200) { // accept timeouts (may deprecate) while (0 < Wire.available()) { // loop through all but the last //digitalWrite(LED_PIN, LOW); c = Wire.read(); @@ -214,13 +217,12 @@ void receiveEvent(int howMany) { seq = c; } seq = c; - - } // if 0 + } digitalWrite(LED_PIN, HIGH); - index++; - } // while - } // while + ++index; + } + } Serial.println(String(chars)); @@ -234,7 +236,7 @@ void receiveEvent(int howMany) { Serial.print("Decoding data of size: "); Serial.println(sizeof(chars)); message = validateMessage(chars); // &error - // TODO: Do something with the message. + // Do something with the message. char inmessage[5] = {0}; memcpy(inmessage, (const char*)&message.data, 4); String inmsg = String(inmessage); @@ -246,15 +248,15 @@ void receiveEvent(int howMany) { } void sendMessage(int seq, String msg) { - Wire.beginTransmission(0x42); // transmit to device #8 - //Sending Side - MESSAGE_DATA struct_data = encodeMessage(msg); + Wire.beginTransmission(I2C_MASTER); // transmit to I2C device with our predefined master address + // Sending Side + MessageData struct_data = encodeMessage(msg); struct_data.sequence = seq; char b[sizeof(struct_data)]; memcpy(b, &struct_data, sizeof(struct_data)); Serial.print("Sending message of size "); Serial.print(sizeof(struct_data)); Serial.println(); Serial.print("'"); - for (unsigned int i = 0; i < sizeof(struct_data); i++) { + for (unsigned int i = 0; i < sizeof(struct_data); ++i) { Wire.write(b[i]); Serial.print(b[i]); } @@ -264,9 +266,8 @@ void sendMessage(int seq, String msg) { // wire_transmit void sendEvent(int a, String msg) { - Serial.print("Sending "); - Serial.println(msg); - Wire.beginTransmission(0x42); // transmit to master + Serial.print("Sending "); Serial.println(msg); + Wire.beginTransmission(I2C_MASTER); // transmit to master Wire.write(a); Wire.write(";"); // sends five bytes Wire.write(msg.c_str()); From 88de8da920167845fd096e1079dafd60f3736648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Mon, 26 Nov 2018 15:00:53 +0100 Subject: [PATCH 08/13] partial fixes after travis check; still missing merge of yesterday's work... --- .../i2c-P2P-master/i2c-P2P-master.ino | 44 ++++++++++--------- .../examples/i2c-P2P-slave/i2c-P2P-slave.ino | 29 +++++------- 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino index c766334f7a..ea68425042 100644 --- a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino +++ b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino @@ -65,7 +65,7 @@ MessageData encodeMessage(const String &instring) { msgdata.terminator = '.'; - int datasize = sizeof(msgdata.data); + size_t datasize = sizeof(msgdata.data); Serial.print("\nEncoding data of size: "); Serial.println(datasize); @@ -85,7 +85,10 @@ MessageData encodeMessage(const String &instring) { } // should be in shared header -bool validateMessage(const char* bytes, MessageData &tmp) { +bool validateMessage(char* message_bytes, MessageData &tmp) { + + MessageData tmp; + memcpy(&tmp, message_bytes, sizeof(tmp)); // Validate PROTOCOL terminator if (tmp.terminator != '.') { @@ -116,7 +119,7 @@ bool validateMessage(const char* bytes, MessageData &tmp) { Serial.print("tmp CRC16: "); Serial.println(tmp.crc16, HEX); Serial.println("[ERROR] Request retransfer exception."); - return true; + return false; } // Validate sequence number @@ -152,7 +155,7 @@ void sendMessage(const int seq, const String &msg) { Serial.print("Encoding struct of size: "); Serial.println(sizeof(struct_data)); memcpy(buf, &struct_data, sizeof(struct_data)); - for (int i = 0; i < sizeof(struct_data); ++i) { + for (unsigned int i = 0; i < sizeof(struct_data); ++i) { Wire.write(buf[i]); Serial.print(buf[i]); Serial.print(" "); @@ -167,7 +170,7 @@ void receiveEvent(const size_t howMany) { char incoming[howMany]; incoming[howMany - 1] = '\0'; - int index = 0; + unsigned int index = 0; digitalWrite(LED_PIN, LOW); @@ -229,9 +232,9 @@ void setup() { delay(2000); - Wire.pins(SDA_PIN, SCL_PIN); - Wire.begin(I2C_MASTER); - //Wire.begin(SDA_PIN, SCL_PIN, I2C_MASTER); // new syntax: join i2c bus (address optional for master) + //Wire.pins(SDA_PIN, SCL_PIN); + //Wire.begin(I2C_MASTER); + Wire.begin(SDA_PIN, SCL_PIN, I2C_MASTER); // new syntax: join i2c bus (address optional for master) Wire.onReceive(receiveEvent); Serial.begin(230400); // keep serial fast as possible for debug logging @@ -240,31 +243,32 @@ void setup() { digitalWrite(LED_PIN, HIGH); } -unsigned long secondTimer = millis() + 1000; +unsigned long second_timer = millis() + 1000; + void loop() { - if (millis() > secondTimer) { + if (millis() > second_timer) { Serial.print("Errors/Bytes: "); - Serial.print(errorCount); + Serial.print(error_count); Serial.print("/"); - Serial.print(byteCount); + Serial.print(byte_count); Serial.println(" per second"); - errorCount = 0; - byteCount = 0; - secondTimer = millis() + 1000; + error_count = 0; + byte_count = 0; + second_timer = millis() + 1000; } - if (millis() > nextPing) { + if (millis() > next_ping) { digitalWrite(LED_PIN, LOW); - nextPing = millis() + 200; + next_ping = millis() + 200; Serial.print("[MASTER] Sequence » "); Serial.println(sequence); digitalWrite(LED_PIN, HIGH); sendMessage(sequence, "MESA"); - if (expectPong) { - errorCount++; + if (expect_pong) { + error_count++; } - expectPong = true; + expect_pong = true; sequence++; } diff --git a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino index 7c64ebf826..e72a426be6 100644 --- a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino +++ b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino @@ -38,7 +38,7 @@ uint16_t calculateCRC16(uint8_t *data, size_t length); void sendEvent(int a, String msg); void sendMessage(int seq, String msg); void receiveEvent(const size_t howMany); -MessageData validateMessage(char* message_bytes); +MessageData validateMessage(char* bytes_message); // @@ -54,8 +54,7 @@ void setup() { Serial.begin(230400); while (!Serial); // if you want to wait for first messages - delay(2000); - + // Enable internal pullup (there's always one from the master side) //digitalWrite(SDA_PIN, HIGH); //digitalWrite(SCL_PIN, HIGH); @@ -63,14 +62,13 @@ void setup() { pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); - Wire.pins(SDA_PIN, SCL_PIN); - Serial.println("I2C Slave begin..."); - Wire.begin(I2C_SLAVE); - //Wire.begin(SDA_PIN, SCL_PIN, I2C_SLAVE); // new syntax: join i2c bus (address required for slave) - + //Wire.pins(SDA_PIN, SCL_PIN); + //Wire.begin(I2C_SLAVE); + Wire.begin(SDA_PIN, SCL_PIN, I2C_SLAVE); // new syntax: join i2c bus (address required for slave) + + delay(2000); digitalWrite(LED_PIN, HIGH); - Serial.println("I2C Slave attaching callback..."); Wire.onReceive(receiveEvent); Serial.print("I2C Slave started on address: 0x0"); @@ -103,10 +101,10 @@ MessageData encodeMessage(String bytes) { } // should be in shared header -MessageData validateMessage(char* message_bytes) { +bool validateMessage(const char* bytes, MessageData &tmp) { MessageData tmp; - memcpy(&tmp, message_bytes, sizeof(tmp)); + memcpy(&tmp, bytes_message, sizeof(tmp)); // Validate terminator if (tmp.terminator == '.') { @@ -145,8 +143,8 @@ MessageData validateMessage(char* message_bytes) { Serial.print("tmp CRC16: "); Serial.println(tmp.crc16, HEX); Serial.print("SLAVE Incoming message: "); Serial.println(String(inmsg)); - Serial.println("[ERROR] TODO: Request retransfer exception."); - return tmp; + Serial.println("[ERROR] Request retransfer exception."); + return false; } // Validate sequence number ( should be already updated from byteParser ) @@ -155,10 +153,7 @@ MessageData validateMessage(char* message_bytes) { Serial.println((char*)tmp.data); } - msgdata = tmp; // tmp is valid, assign to result address - - return msgdata; - + return true; } void receiveEvent(const size_t howMany) { From 983fc47d69030b8474c2884ee47be51d26f1257a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Sat, 8 Dec 2018 23:11:05 +0100 Subject: [PATCH 09/13] no message --- tools/sdk/lwip2/builder | 2 +- tools/sdk/ssl/bearssl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/sdk/lwip2/builder b/tools/sdk/lwip2/builder index c434c6fab1..80224f017d 160000 --- a/tools/sdk/lwip2/builder +++ b/tools/sdk/lwip2/builder @@ -1 +1 @@ -Subproject commit c434c6fab1cb7c670cd9a223e6667ec80a618d29 +Subproject commit 80224f017dd83d0d88dd82ccd5d896313c90a234 diff --git a/tools/sdk/ssl/bearssl b/tools/sdk/ssl/bearssl index 95c20d1efa..0e71e46987 160000 --- a/tools/sdk/ssl/bearssl +++ b/tools/sdk/ssl/bearssl @@ -1 +1 @@ -Subproject commit 95c20d1efacbe762019a64e35e90ebb1997eeb93 +Subproject commit 0e71e46987d863eb89112f15827b9f962acbab1b From 4faa7156a93875d0ab994c4e5eb852e9baf0781c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Sun, 9 Dec 2018 00:05:20 +0100 Subject: [PATCH 10/13] fixes after functional testing --- .../i2c-P2P-master/i2c-P2P-master.ino | 21 +++-- .../examples/i2c-P2P-slave/i2c-P2P-slave.ino | 79 ++++++++++--------- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino index ea68425042..3d1476a0a0 100644 --- a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino +++ b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino @@ -18,7 +18,7 @@ const int16_t I2C_MASTER = 0x42; const int16_t I2C_SLAVE = 0x08; -int16_t slave_address = I2C_SLAVE; +int16_t slave_address = I2C_SLAVE; // Keep this structure in sync with the i2c-P2P-slave example. Should be in shared header. struct MessageData { @@ -87,7 +87,6 @@ MessageData encodeMessage(const String &instring) { // should be in shared header bool validateMessage(char* message_bytes, MessageData &tmp) { - MessageData tmp; memcpy(&tmp, message_bytes, sizeof(tmp)); // Validate PROTOCOL terminator @@ -249,26 +248,26 @@ void loop() { if (millis() > second_timer) { Serial.print("Errors/Bytes: "); - Serial.print(error_count); + Serial.print(errorCount); Serial.print("/"); - Serial.print(byte_count); + Serial.print(byteCount); Serial.println(" per second"); - error_count = 0; - byte_count = 0; + errorCount = 0; + byteCount = 0; second_timer = millis() + 1000; } - if (millis() > next_ping) { + if (millis() > nextPing) { digitalWrite(LED_PIN, LOW); - next_ping = millis() + 200; + nextPing = millis() + 200; Serial.print("[MASTER] Sequence » "); Serial.println(sequence); digitalWrite(LED_PIN, HIGH); sendMessage(sequence, "MESA"); - if (expect_pong) { - error_count++; + if (expectPong) { + errorCount++; } - expect_pong = true; + expectPong = true; sequence++; } diff --git a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino index e72a426be6..44b5c24069 100644 --- a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino +++ b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino @@ -38,7 +38,7 @@ uint16_t calculateCRC16(uint8_t *data, size_t length); void sendEvent(int a, String msg); void sendMessage(int seq, String msg); void receiveEvent(const size_t howMany); -MessageData validateMessage(char* bytes_message); +bool validateMessage(const char* bytes, MessageData &tmp); // @@ -50,31 +50,6 @@ uint16_t calculateCRC16(uint8_t *data, size_t length) { return (uint16_t)value; } -void setup() { - - Serial.begin(230400); - while (!Serial); // if you want to wait for first messages - - // Enable internal pullup (there's always one from the master side) - //digitalWrite(SDA_PIN, HIGH); - //digitalWrite(SCL_PIN, HIGH); - - pinMode(LED_PIN, OUTPUT); - digitalWrite(LED_PIN, LOW); - - //Wire.pins(SDA_PIN, SCL_PIN); - //Wire.begin(I2C_SLAVE); - Wire.begin(SDA_PIN, SCL_PIN, I2C_SLAVE); // new syntax: join i2c bus (address required for slave) - - delay(2000); - digitalWrite(LED_PIN, HIGH); - - Wire.onReceive(receiveEvent); - - Serial.print("I2C Slave started on address: 0x0"); - Serial.println(I2C_SLAVE, HEX); -} - // should be in shared header MessageData encodeMessage(String bytes) { @@ -103,8 +78,7 @@ MessageData encodeMessage(String bytes) { // should be in shared header bool validateMessage(const char* bytes, MessageData &tmp) { - MessageData tmp; - memcpy(&tmp, bytes_message, sizeof(tmp)); + memcpy(&tmp, bytes, sizeof(tmp)); // Validate terminator if (tmp.terminator == '.') { @@ -113,7 +87,7 @@ bool validateMessage(const char* bytes, MessageData &tmp) { Serial.print("[ERROR] Terminator invalid: '"); Serial.print(tmp.terminator); Serial.println("'"); - return tmp; + return false; } int datasize = sizeof(tmp.data); @@ -227,17 +201,19 @@ void receiveEvent(const size_t howMany) { } else { } - + Serial.print("Decoding data of size: "); Serial.println(sizeof(chars)); - message = validateMessage(chars); // &error - - // Do something with the message. - char inmessage[5] = {0}; - memcpy(inmessage, (const char*)&message.data, 4); - String inmsg = String(inmessage); - if (inmsg.indexOf("MESA") == 0) { - String event = String("PONG"); - sendMessage(seq, event); + bool success = validateMessage(chars, message); + + if (success) { + // Do something with the message. + char inmessage[5] = {0}; + memcpy(inmessage, (const char*)&message.data, 4); + String inmsg = String(inmessage); + if (inmsg.indexOf("MESA") == 0) { + String event = String("PONG"); + sendMessage(seq, event); + } } } @@ -269,6 +245,31 @@ void sendEvent(int a, String msg) { Wire.endTransmission(); // stop transmitting } +void setup() { + + Serial.begin(230400); + while (!Serial); // if you want to wait for first messages + + // Enable internal pullup (there's always one from the master side) + //digitalWrite(SDA_PIN, HIGH); + //digitalWrite(SCL_PIN, HIGH); + + pinMode(LED_PIN, OUTPUT); + digitalWrite(LED_PIN, LOW); + + //Wire.pins(SDA_PIN, SCL_PIN); + //Wire.begin(I2C_SLAVE); + Wire.begin(SDA_PIN, SCL_PIN, I2C_SLAVE); // new syntax: join i2c bus (address required for slave) + + delay(2000); + digitalWrite(LED_PIN, HIGH); + + Wire.onReceive(receiveEvent); + + Serial.print("I2C Slave started on address: 0x0"); + Serial.println(I2C_SLAVE, HEX); +} + void loop() { // nothing here, slave receives data and sends reply in own callback } From fabca64db0ca8be2596ae213dbfa6c5a543d8f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Sun, 9 Dec 2018 00:25:19 +0100 Subject: [PATCH 11/13] minor style fixes --- .../i2c-P2P-master/i2c-P2P-master.ino | 24 +++++++-------- .../examples/i2c-P2P-slave/i2c-P2P-slave.ino | 30 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino index 3d1476a0a0..58dbdfd61d 100644 --- a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino +++ b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino @@ -1,13 +1,13 @@ /* - * ESP8266 I2C master-slave communication, requires Arduno Core with I2C Slave Support (2.5.0+) - * - * Expects two ESP8266 devices with three pins connected: GND, SDA and SCL. This is master. - * Will send "MESA" messages to predefined slave address and then expect "PONG" response, - * or request to retransfer if message was misunderstood (e.g. CRC check failed). - * Message can be up to 26 bytes long (plus wrapper). - * - * 21-11-2018: initial drop by Matej Sychra (github.com/suculent) - */ + ESP8266 I2C master-slave communication, requires Arduno Core with I2C Slave Support (2.5.0+) + + Expects two ESP8266 devices with three pins connected: GND, SDA and SCL. This is master. + Will send "MESA" messages to predefined slave address and then expect "PONG" response, + or request to retransfer if message was misunderstood (e.g. CRC check failed). + Message can be up to 26 bytes long (plus wrapper). + + 09-12-2018: initial drop by Matej Sychra (github.com/suculent) +*/ #include #include "crc16.h" @@ -52,7 +52,7 @@ bool validateMessage(const char* bytes, MessageData &tmp); // should be in shared header uint16_t calculateCRC16(uint8_t *data, size_t length) { crc.clearCrc(); - uint16_t value = (uint16_t)crc.XModemCrc(data,0,length); + uint16_t value = (uint16_t)crc.XModemCrc(data, 0, length); Serial.print("crc = 0x"); Serial.println(value, HEX); return value; @@ -176,8 +176,8 @@ void receiveEvent(const size_t howMany) { unsigned long interval = 100; unsigned long currentMillis = millis(); unsigned long previousMillis = millis(); - // message duration may not exceed 100 ms (100 bytes, 3x buffer retransferred) - if(currentMillis - previousMillis > interval) { + // message duration may not exceed 100 ms (100 bytes, 3x buffer retransferred) + if (currentMillis - previousMillis > interval) { previousMillis = currentMillis; // this must be fast, keep free from logging to serial here if possible while (0 < Wire.available()) { // loop through all but the last diff --git a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino index 44b5c24069..9cf0f0ae2b 100644 --- a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino +++ b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino @@ -1,13 +1,13 @@ /* - * ESP8266 I2C master-slave communication, requires Arduno Core with I2C Slave Support (2.5.0+) - * - * Expects two ESP8266 devices with three pins connected: GND, SDA and SCL. This is slave. - * Will wait for "MESA" message and then respond with "PONG" message, - * or request retransfer if message was misunderstood (e.g. CRC check failed). - * Message can be up to 26 bytes long (plus wrapper). - * - * 21-11-2018: initial drop by Matej Sychra (github.com/suculent) - */ + ESP8266 I2C master-slave communication, requires Arduno Core with I2C Slave Support (2.5.0+) + + Expects two ESP8266 devices with three pins connected: GND, SDA and SCL. This is slave. + Will wait for "MESA" message and then respond with "PONG" message, + or request retransfer if message was misunderstood (e.g. CRC check failed). + Message can be up to 26 bytes long (plus wrapper). + + 09-12-2018: initial drop by Matej Sychra (github.com/suculent) +*/ #include #include "crc16.h" @@ -156,9 +156,9 @@ void receiveEvent(const size_t howMany) { // Parses first byte for sequence number, contains recovery logic... if (index == 0) { - Serial.print("Remote Sequence: "); Serial.println((int)c); + Serial.print("Remote Sequence: "); Serial.println((int)c); - if ( c!= seq && ((c > seq - 4) || (c < seq + 4)) && c != seq + 1) { + if ( c != seq && ((c > seq - 4) || (c < seq + 4)) && c != seq + 1) { Serial.print("[DIFF] Sequence offset [!]: "); Serial.println(c - seq); Serial.print("Re-assigning sequence number: "); @@ -196,12 +196,12 @@ void receiveEvent(const size_t howMany) { Serial.println(String(chars)); if (requestRetransfer) { - String event = String("R") + String(seq) + String('\0'); - sendMessage(seq, event); - } else { + String event = String("R") + String(seq) + String('\0'); + sendMessage(seq, event); + } else { } - + Serial.print("Decoding data of size: "); Serial.println(sizeof(chars)); bool success = validateMessage(chars, message); From a8f7d63aa5f0bc712e6dba5fa778843178853956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Sun, 9 Dec 2018 11:38:34 +0100 Subject: [PATCH 12/13] style fix and unused variable fix --- libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino | 5 +++++ libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino index 58dbdfd61d..260b5999ce 100644 --- a/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino +++ b/libraries/Wire/examples/i2c-P2P-master/i2c-P2P-master.ino @@ -199,6 +199,11 @@ void receiveEvent(const size_t howMany) { bool success = validateMessage(incoming, message); + if (!success) { + Serial.println("I2C message failed to validate."); + return; + } + char inmsg[sizeof(message.data)]; memcpy(inmsg, &message.data, sizeof(message.data)); if (inmsg[0] == 'R') { diff --git a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino index 9cf0f0ae2b..0a5d5d8023 100644 --- a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino +++ b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino @@ -158,7 +158,7 @@ void receiveEvent(const size_t howMany) { Serial.print("Remote Sequence: "); Serial.println((int)c); - if ( c != seq && ((c > seq - 4) || (c < seq + 4)) && c != seq + 1) { + if (c != seq && ((c > seq - 4) || (c < seq + 4)) && c != seq + 1) { Serial.print("[DIFF] Sequence offset [!]: "); Serial.println(c - seq); Serial.print("Re-assigning sequence number: "); From 0272be2921f06c50ca689419dc5f539f59f1bbeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mate=CC=8Cj=20Sychra?= Date: Sun, 9 Dec 2018 12:12:35 +0100 Subject: [PATCH 13/13] style check fix --- libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino index 0a5d5d8023..d809f78d50 100644 --- a/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino +++ b/libraries/Wire/examples/i2c-P2P-slave/i2c-P2P-slave.ino @@ -158,7 +158,7 @@ void receiveEvent(const size_t howMany) { Serial.print("Remote Sequence: "); Serial.println((int)c); - if (c != seq && ((c > seq - 4) || (c < seq + 4)) && c != seq + 1) { + if (c != seq && ((c > seq - 4) || (c < seq + 4)) && c != seq + 1) { Serial.print("[DIFF] Sequence offset [!]: "); Serial.println(c - seq); Serial.print("Re-assigning sequence number: ");