diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/CHANGELOG.md b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/CHANGELOG.md
new file mode 100644
index 0000000..4331410
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/CHANGELOG.md
@@ -0,0 +1,7 @@
+# Project change log
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/)
+and this project adheres to [Semantic Versioning](http://semver.org/).
+
+## [1.0.0] 2018-10-15
+Initial version
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/LICENSE b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/LICENSE
new file mode 100644
index 0000000..0a04128
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/LICENSE
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/README.md b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/README.md
new file mode 100644
index 0000000..b56c332
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/README.md
@@ -0,0 +1,160 @@
+# MessagePack
+
+MessagePack is a library for AVR, SAMD, ESP8266 and ESP32 platforms to pack/unpack values into a compact, self-explanatory binary message.
+
+[![version](https://img.shields.io/badge/version-1.0.0-brightgreen.svg)](CHANGELOG.md)
+[![travis](https://travis-ci.org/xoseperez/messagepack.svg?branch=master)](https://travis-ci.org/xoseperez/messagepack)
+[![codacy](https://img.shields.io/codacy/grade/54c6bf3a367745509677e28dfbe1e0d1/master.svg)](https://www.codacy.com/app/xoseperez/messagepack/dashboard)
+[![license](https://img.shields.io/github/license/xoseperez/MessagePack.svg)](LICENSE)
+
+[![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=xose%2eperez%40gmail%2ecom&lc=US&no_note=0¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHostedGuest)
+[![twitter](https://img.shields.io/twitter/follow/xoseperez.svg?style=social)](https://twitter.com/intent/follow?screen_name=xoseperez)
+
+## Features
+
+The main features of the MessagePack library are:
+
+* Compact yet self-explanatory message format
+* Targeted to wireless communication
+* Support for boolean, short, integer, long, and float numbers and c-strings.
+
+## Usage
+
+Check the examples folder for working examples of the library.
+
+### Packing
+
+```
+
+#include "MessagePack.h"
+
+void send(unsigned char * data, unsigned char length) {
+ // ...
+}
+
+void setup() {
+
+ MessagePack * message = new MessagePack();
+
+ // Add some values, for instance temperature, humidity and pressure
+ message->addFloat(25.4);
+ message->addShort(67);
+ message->addFloat(1013.45);
+
+ // Send message
+ send(message->pack(), message->length());
+
+}
+
+loop() {}
+
+```
+
+### Unpacking
+
+```
+
+#include "MessagePack.h"
+
+void parse(unsigned char * data, unsigned char length) {
+
+ MessagePack * message = new MessagePack();
+
+ // Load the data
+ message->unpack(data, length);
+
+ // Number of elements
+ unsigned char count = message->count();
+ Serial.print("Number of values: ");
+ Serial.println(count);
+
+ // Walk elements (only for integer numbers, see example for full functionality)
+ char buffer[32];
+ for (unsigned char i=0; itype(i);
+ if (MESSAGE_PACK_BOOLEAN == type) {
+ snprintf(buffer, sizeof(buffer), "Value #%d is a BOOLEAN: %d\n", i, message->getBoolean(i) ? 1 : 0);
+ } else if (MESSAGE_PACK_SHORT == type) {
+ snprintf(buffer, sizeof(buffer), "Value #%d is a SHORT: %u\n", i, message->getShort(i));
+ } else if (MESSAGE_PACK_INTEGER == type) {
+ snprintf(buffer, sizeof(buffer), "Value #%d is an INTEGER: %u\n", i, message->getInteger(i));
+ } else if (MESSAGE_PACK_LONG == type) {
+ snprintf(buffer, sizeof(buffer), "Value #%d is a LONG: %lu\n", i, message->getLong(i));
+ }
+ Serial.print(buffer);
+ }
+
+}
+
+setup() {}
+
+loop() {
+
+ if (Serial.available()) {
+
+ // ...
+
+ // send the message to the parser routine
+ parse(data, length);
+
+ }
+
+}
+
+```
+
+## Format
+
+This library works under the following assumptions:
+
+* Data is in little-endian format (least significant byte, is at the lowest address)
+* Integers have a length of 8, 16 or 32 bits (for SHORT, INTEGER and LONG types)
+* Floats are represented in IEEE 754 single-precision format, and have a length of 32 bits
+* Booleans are represented in a byte (1 = true, 0 = false)
+* Strings are ended by the NULL char (0x00)
+
+Data is binary packed with this format:
+
+* First byte: number of values packed in the string
+* N bytes with the information about the data type of each packed value. Each byte have information about 2 packed values, one for each nibble. Data types are coded in this way:
+ * 0b0000: Null
+ * 0b0001: Boolean
+ * 0b0010: Short
+ * 0b0011: Integer
+ * 0b0100: Long
+ * 0b0101: Float
+ * 0b0110: String
+* N bytes of data
+
+```
+The pack string (without spaces) for 17 (short), true (boolean), nil and 452 (integer) are:
+
+03 21 30 11 01 C401
+
+03 is the number of packed values, in this case 3
+21 is the type of the first and second packed values: short and boolean
+30 is the type of the third and fourth packed values: integer and null
+11 is integer 17 (0x11) in hexadecimal 1-byte integer (a.k.a. short)
+01 is boolean true
+C401 is integer 452 (0x01C4) in 2-bytes little-endian
+
+Total length is 7 bytes. Take note that the nil value is only present in the header and has not representation in the data.
+
+```
+
+## License
+
+Copyright (C) 2018 by Xose Pérez
+
+The MessagePack library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+The MessagePack library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the MessagePack library. If not, see .
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/pack/pack.ino b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/pack/pack.ino
new file mode 100644
index 0000000..72e1b54
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/pack/pack.ino
@@ -0,0 +1,53 @@
+/*
+
+MessagePack - Packing example
+
+Copyright (C) 2018 by Xose Pérez
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program. If not, see .
+
+*/
+
+#include "MessagePack.h"
+
+void setup() {
+
+ // Init serial communications
+ Serial.begin(115200);
+ while (!Serial);
+ Serial.println();
+ Serial.println("MessagePack Library - Packing example");
+ Serial.println();
+
+ // Create a message pack object, defaults to 100 bytes of memory
+ MessagePack * message = new MessagePack();
+
+ // Add some values, for instance temperature, humidity and pressure
+ message->addFloat(25.4);
+ message->addShort(67);
+ message->addFloat(1013.45);
+
+ // Now dump message to serial
+ char buffer[6];
+ Serial.print("Packed message: { ");
+ for (unsigned char i=0; ilength(); i++) {
+ if (i>0) Serial.print(", ");
+ snprintf(buffer, sizeof(buffer), "0x%02X", message->pack()[i]);
+ Serial.print(buffer);
+ }
+ Serial.println(" }");
+
+}
+
+void loop() {}
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/pack/platformio.ini b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/pack/platformio.ini
new file mode 100644
index 0000000..dd428de
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/pack/platformio.ini
@@ -0,0 +1,9 @@
+[platformio]
+src_dir = .
+lib_extra_dirs = ../..
+env_default = leonardo
+
+[env:leonardo]
+platform = atmelavr
+board = leonardo
+framework = arduino
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/unpack/platformio.ini b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/unpack/platformio.ini
new file mode 100644
index 0000000..dd428de
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/unpack/platformio.ini
@@ -0,0 +1,9 @@
+[platformio]
+src_dir = .
+lib_extra_dirs = ../..
+env_default = leonardo
+
+[env:leonardo]
+platform = atmelavr
+board = leonardo
+framework = arduino
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/unpack/unpack.ino b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/unpack/unpack.ino
new file mode 100644
index 0000000..a27c72a
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/unpack/unpack.ino
@@ -0,0 +1,94 @@
+/*
+
+MessagePack - Unpacking example
+
+Copyright (C) 2018 by Xose Pérez
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program. If not, see .
+
+*/
+
+#include "MessagePack.h"
+
+char * snfloat(char * buffer, uint8_t len, uint8_t decimals, float value) {
+
+ bool negative = value < 0;
+
+ uint32_t mul = 1;
+ for (uint8_t i=0; iunpack(data, sizeof(data));
+
+ // Number of elements
+ unsigned char count = message->count();
+ Serial.print("Number of values: ");
+ Serial.println(count);
+
+ // Walk elements
+ char buffer[32];
+ for (unsigned char i=0; itype(i);
+ if (MESSAGE_PACK_BOOLEAN == type) {
+ snprintf(buffer, sizeof(buffer), "Value #%d is a BOOLEAN: %d\n", i, message->getBoolean(i) ? 1 : 0);
+ } else if (MESSAGE_PACK_SHORT == type) {
+ snprintf(buffer, sizeof(buffer), "Value #%d is a SHORT: %u\n", i, message->getShort(i));
+ } else if (MESSAGE_PACK_INTEGER == type) {
+ snprintf(buffer, sizeof(buffer), "Value #%d is an INTEGER: %u\n", i, message->getInteger(i));
+ } else if (MESSAGE_PACK_LONG == type) {
+ snprintf(buffer, sizeof(buffer), "Value #%d is a LONG: %lu\n", i, message->getLong(i));
+ } else if (MESSAGE_PACK_FLOAT == type) {
+ char number[10];
+ snfloat(number, sizeof(number), 2, message->getFloat(i));
+ snprintf(buffer, sizeof(buffer), "Value #%d is a FLOAT: %s\n", i, number);
+ } else if (MESSAGE_PACK_TEXT == type) {
+ unsigned char size = message->getTextLength(i);
+ char text[size+1];
+ snprintf(buffer, sizeof(buffer), "Value #%d is a TEXT: %s\n", i, message->getText(i, text));
+ } else {
+ snprintf(buffer, sizeof(buffer), "Value #%d is UNKNOWN\n", i);
+ }
+ Serial.print(buffer);
+ }
+
+
+}
+
+void loop() {}
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/keywords.txt b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/keywords.txt
new file mode 100644
index 0000000..bc25c15
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/keywords.txt
@@ -0,0 +1,53 @@
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+#######################################
+# Classes (KEYWORD1)
+#######################################
+
+MessagePack KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+addNull KEYWORDS2
+addBoolean KEYWORDS2
+addShort KEYWORDS2
+addInteger KEYWORDS2
+addLong KEYWORDS2
+addFloat KEYWORDS2
+addText KEYWORDS2
+
+getBoolean KEYWORDS2
+getShort KEYWORDS2
+getInteger KEYWORDS2
+getLong KEYWORDS2
+getFloat KEYWORDS2
+getTextLength KEYWORDS2
+getText KEYWORDS2
+
+count KEYWORDS2
+type KEYWORDS2
+length KEYWORDS2
+pack KEYWORDS2
+unpack KEYWORDS2
+
+#######################################
+# Instances (KEYWORD2)
+#######################################
+
+#######################################
+# Constants (LITERAL1)
+#######################################
+
+MESSAGE_PACK_NULL LITERAL1
+MESSAGE_PACK_BOOLEAN LITERAL1
+MESSAGE_PACK_SHORT LITERAL1
+MESSAGE_PACK_INTEGER LITERAL1
+MESSAGE_PACK_LONG LITERAL1
+MESSAGE_PACK_FLOAT LITERAL1
+MESSAGE_PACK_TEXT LITERAL1
+MESSAGE_PACK_MAX LITERAL1
+MESSAGE_PACK_ERROR LITERAL1
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/library.json b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/library.json
new file mode 100644
index 0000000..b5e3d59
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/library.json
@@ -0,0 +1,23 @@
+{
+ "name": "MessagePack",
+ "keywords": "message,packing,binary,transmission",
+ "description": "Library to pack/unpack values into a compact, self-explanatory binary message",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/xoseperez/messagepack.git"
+ },
+ "version": "1.0.0",
+ "license": "LGPL-3.0",
+ "exclude": "tests",
+ "frameworks": "arduino",
+ "platforms": ["atmelavr", "atmelsam", "espressif8266", "espressif32"],
+ "authors": {
+ "name": "Xose Perez",
+ "email": "xose.perez@gmail.com",
+ "url": "http://tinkerman.cat",
+ "maintainer": true
+ },
+ "examples": [
+ "examples/*/*.ino"
+ ]
+}
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/library.properties b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/library.properties
new file mode 100644
index 0000000..43ba4d1
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/library.properties
@@ -0,0 +1,10 @@
+name=MessagePack
+version=1.0.0
+author=Xose Pérez
+maintainer=Xose Pérez
+sentence=Library to pack/unpack values into a compact, self-explanatory binary message
+paragraph=
+category=Communication
+url=https://github.com/xoseperez/messagepack.git
+architectures=avr,samd,esp8266,esp32
+includes=MessagePack.h
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/pre-commit b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/pre-commit
new file mode 100644
index 0000000..b17ad39
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/pre-commit
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+"""
+
+Referencing current branch in github README.md [1]
+This pre-commit hook [2] updates the README.md file's
+Travis badge with the current branch. Based on [4].
+
+[1] http://stackoverflow.com/questions/18673694/referencing-current-branch-in-github-readme-md
+[2] http://www.git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
+[3] https://docs.travis-ci.com/user/status-images/
+[4] https://gist.github.com/dandye/dfe0870a6a1151c89ed9
+
+Copy this file to .git/hooks/
+
+"""
+
+import os
+import sys
+import re
+
+from subprocess import call, check_output
+try:
+ from urllib.parse import urlparse
+except ImportError:
+ from urlparse import urlparse
+
+from fileinput import FileInput
+# https://github.com/python/cpython/commit/6cb7b659#diff-78790b53ff259619377058acd4f74672
+if sys.version_info[0] < 3:
+ class FileInputCtx(FileInput):
+ def __enter__(self):
+ return self
+
+ def __exit__(self, type, value, traceback):
+ self.close()
+
+ FileInput = FileInputCtx
+
+
+def run(cmd, cwd=None):
+ out = check_output(cmd, cwd=cwd)
+ out = out.decode("latin1").strip()
+
+ return out
+
+
+def git_parse_remote(cwd=None, remote="origin"):
+ remote_url = run([
+ "git", "config", "--local",
+ "--get", "remote.{}.url".format(remote)], cwd)
+
+ if remote_url.startswith("git"):
+ _, _, repo = remote_url.partition(":")
+ elif remote_url.startswith("https"):
+ parsed = urlparse(remote_url)
+ repo = parsed.path[1:]
+
+ path = repo.replace(".git", "")
+ return path.split("/")
+
+
+def git_branch(cwd=None):
+ return run(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd)
+
+
+def get_version(base, version_h="library.properties"):
+ version = "unknown"
+
+ path = os.path.join(base, version_h)
+ with open(path, "r") as version_f:
+ for line in version_f:
+ if line.startswith("version="):
+ version = line.replace("version=", "").strip()
+ break
+
+ return version
+
+TEMPLATES = {
+ "![travis]": "[![travis](https://travis-ci.org/{USER}/{REPO}.svg?branch={BRANCH})]" \
+ "(https://travis-ci.org/{USER}/{REPO})\n",
+ "![version]": "[![version](https://img.shields.io/badge/version-{VERSION}-brightgreen.svg)](CHANGELOG.md)\n",
+ "![branch]": "[![branch](https://img.shields.io/badge/branch-{BRANCH}-orange.svg)]" \
+ "(https://github.org/{USER}/{REPO}/tree/{BRANCH}/)\n",
+ "![codacy]": "[![codacy](https://img.shields.io/codacy/grade/{CODACY}/{BRANCH}.svg)]" \
+ "(https://www.codacy.com/app/{USER}/{REPO}/dashboard)\n"
+}
+
+README = "README.md"
+
+if __name__ == "__main__":
+ base = os.getcwd()
+
+ user, repo = git_parse_remote()
+ fmt = {
+ "USER": user,
+ "REPO": repo,
+ "BRANCH": git_branch(),
+ "VERSION": get_version(base),
+ "CODACY": "54c6bf3a367745509677e28dfbe1e0d1"
+ }
+ templates = [
+ (k, tmpl.format(**fmt))
+ for k, tmpl in TEMPLATES.items()
+ ]
+
+ def fmt_line(line):
+ for match, tmpl in templates:
+ if match in line:
+ return tmpl
+
+ return line
+
+ path = os.path.join(base, README)
+
+ with FileInput(path, inplace=True) as readme:
+ for line in readme:
+ sys.stdout.write(fmt_line(line))
+
+ sys.exit(call(["git", "add", README]))
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/src/MessagePack.cpp b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/src/MessagePack.cpp
new file mode 100644
index 0000000..a867c2f
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/src/MessagePack.cpp
@@ -0,0 +1,4 @@
+#include
+#include "MessagePack.h"
+
+unsigned char MESSAGE_PACK_LEN[] = {0, 1, 1, 2, 4, 4, 0};
\ No newline at end of file
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/src/MessagePack.h b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/src/MessagePack.h
new file mode 100644
index 0000000..67ec4df
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/src/MessagePack.h
@@ -0,0 +1,271 @@
+/*
+
+Message pack
+
+Message binary packing/unpacking library
+
+Copyright (C) 2018 by Xose Pérez
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program. If not, see .
+
+*/
+
+#ifndef MESSAGE_PACK_H
+#define MESSAGE_PACK_H
+
+
+#ifdef LUA_COMPATIBILITY_MODE
+
+enum {
+
+ MESSAGE_PACK_FLOAT,
+ MESSAGE_PACK_LONG,
+ MESSAGE_PACK_NULL,
+ MESSAGE_PACK_BOOLEAN,
+ MESSAGE_PACK_TEXT,
+ MESSAGE_PACK_SHORT,
+ MESSAGE_PACK_INTEGER,
+
+ MESSAGE_PACK_MAX,
+ MESSAGE_PACK_ERROR = 0x0F
+
+};
+
+unsigned char MESSAGE_PACK_LEN[] = {4, 4, 0, 1, 0, 1, 2};
+
+#else
+
+enum {
+
+ MESSAGE_PACK_NULL,
+ MESSAGE_PACK_BOOLEAN,
+ MESSAGE_PACK_SHORT,
+ MESSAGE_PACK_INTEGER,
+ MESSAGE_PACK_LONG,
+ MESSAGE_PACK_FLOAT,
+ MESSAGE_PACK_TEXT,
+
+ MESSAGE_PACK_MAX,
+ MESSAGE_PACK_ERROR = 0x0F
+
+};
+
+//unsigned char MESSAGE_PACK_LEN[] = {0, 1, 1, 2, 4, 4, 0};
+extern unsigned char MESSAGE_PACK_LEN[];
+#endif
+
+
+class MessagePack {
+
+ public:
+
+
+ MessagePack(unsigned char buffer_size = 100) : _buffer_size(buffer_size) {
+ _buffer = (unsigned char *) malloc(_buffer_size);
+ if (_buffer) _buffer[0] = 0;
+ }
+
+ ~MessagePack() {
+ if (_buffer) free(_buffer);
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool addNull() {
+ return _addVoid(MESSAGE_PACK_NULL, NULL, 0);
+ }
+
+ bool addBoolean(bool value) {
+ unsigned char tmp = value ? 1 : 0;
+ return _addVoid(MESSAGE_PACK_BOOLEAN, (void *) &tmp, 1);
+ }
+
+ bool addShort(unsigned char value) {
+ return _addVoid(MESSAGE_PACK_SHORT, (void *) &value, 1);
+ }
+
+ bool addInteger(unsigned int value) {
+ return _addVoid(MESSAGE_PACK_INTEGER, (void *) &value, 2);
+ }
+
+ bool addLong(unsigned long value) {
+ return _addVoid(MESSAGE_PACK_LONG, (void *) &value, 4);
+ }
+
+ bool addFloat(float value) {
+ return _addVoid(MESSAGE_PACK_FLOAT, (void *) &value, 4);
+ }
+
+ bool addText(const char * value) {
+ return _addVoid(MESSAGE_PACK_TEXT, (void *) value, strlen(value) + 1);
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool getBoolean(unsigned char index) {
+ unsigned char value = 0;
+ _getVoid(index, MESSAGE_PACK_BOOLEAN, &value);
+ return value == 1;
+ }
+
+ unsigned char getShort(unsigned char index) {
+ unsigned char value = 0;
+ _getVoid(index, MESSAGE_PACK_SHORT, &value);
+ return value;
+ }
+
+ unsigned int getInteger(unsigned char index) {
+ unsigned int value = 0;
+ _getVoid(index, MESSAGE_PACK_INTEGER, &value);
+ return value;
+ }
+
+ unsigned long getLong(unsigned char index) {
+ unsigned long value = 0;
+ _getVoid(index, MESSAGE_PACK_LONG, &value);
+ return value;
+ }
+
+ float getFloat(unsigned char index) {
+ float value = 0;
+ _getVoid(index, MESSAGE_PACK_FLOAT, &value);
+ return value;
+ }
+
+ unsigned char getTextLength(unsigned char index) {
+ if (MESSAGE_PACK_TEXT != _type(index)) return 0;
+ unsigned char start = _getPosition(index);
+ unsigned char position = start;
+ while (0x00 != _buffer[position]) ++position;
+ return position - start;
+ }
+
+ char * getText(unsigned char index, char * text) {
+ if (MESSAGE_PACK_TEXT != _type(index)) return 0;
+ unsigned char position = _getPosition(index);
+ unsigned char len = getTextLength(index);
+ memcpy(text, &_buffer[position], len+1);
+ return text;
+ }
+
+ // ---------------------------------------------------------------------
+
+ unsigned char count() {
+ return _buffer[0];
+ }
+
+ unsigned char type(unsigned char index) {
+ if (!_buffer) return MESSAGE_PACK_ERROR;
+ if (index >= count()) return MESSAGE_PACK_ERROR;
+ return _type(index);
+ }
+
+ unsigned char length() {
+ return _length;
+ }
+
+ void pack(unsigned char * buffer) {
+ memcpy(buffer, _buffer, _length);
+ }
+
+ unsigned char * pack() {
+ return _buffer;
+ }
+
+ bool unpack(unsigned char * buffer, unsigned char len) {
+ if (len > _buffer_size) return false;
+ memcpy(_buffer, buffer, len);
+ _length = len;
+ return true;
+ }
+
+ private:
+
+ bool _addVoid(unsigned char type, void * data, unsigned char len) {
+
+ if (!_buffer) return false;
+ if (_buffer_size - _length < len) return false;
+
+ memcpy(&_buffer[_length], data, len);
+ _length += len;
+
+ // Check if we have to move everything forward 1 byte
+ if (0 == count() % 2) {
+ unsigned char start = count() / 2 + 1;
+ for (unsigned char i=_length; i > start; i--) {
+ _buffer[i] = _buffer[i-1];
+ }
+ _buffer[start] = 0;
+ _length++;
+ }
+
+ // Save the type in the header
+ _setType(count(), type);
+
+ // Increment counter
+ _buffer[0] = count() + 1;
+
+ return true;
+
+ }
+
+ bool _getVoid(unsigned char index, unsigned char type, void * data) {
+ if (type != _type(index)) return false;
+ unsigned char position = _getPosition(index);
+ memcpy(data, &_buffer[position], MESSAGE_PACK_LEN[type]);
+ return true;
+ }
+
+ unsigned char _getHeaderLength() {
+ return ( count() + 1 ) / 2 + 1;
+ }
+
+ unsigned char _getPosition(unsigned char index) {
+ unsigned char position = _getHeaderLength();
+ for (unsigned char i=0; i>= 4;
+ }
+ return byte & 0x0F;
+ }
+
+ void _setType(unsigned char index, unsigned char type) {
+ unsigned char byte = _buffer[index / 2 + 1];
+ type = type & 0x0F;
+ if (0 == index % 2) {
+ type <<= 4;
+ }
+ _buffer[index / 2 + 1] = byte | type;
+ }
+
+ unsigned char * _buffer;
+ unsigned char _buffer_size = 0;
+ unsigned char _length = 1;
+
+};
+
+#endif // MESSAGE_PACK_H
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/tests/UnitTest.ino b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/tests/UnitTest.ino
new file mode 100644
index 0000000..4c6aad1
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/tests/UnitTest.ino
@@ -0,0 +1,252 @@
+/*
+
+Message pack
+
+Unit test suite
+This test suite uses Aunit unit testing framework (https://github.com/bxparks/AUnit)
+
+Copyright (C) 2018 by Xose Pérez
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program. If not, see .
+
+*/
+
+
+#include "MessagePack.h"
+#include "AUnit.h"
+using namespace aunit;
+
+//#define DEBUG
+
+// -----------------------------------------------------------------------------
+// Test class
+// -----------------------------------------------------------------------------
+
+class CustomTest: public TestOnce {
+
+ protected:
+
+ virtual void setup() override {
+ message = new MessagePack();
+ }
+
+ virtual void teardown() override {
+ delete message;
+ }
+
+ virtual void compare(size_t len, unsigned char * expected) {
+
+ size_t buffer_len = message->length();
+ unsigned char buffer[buffer_len];
+ message->pack(buffer);
+
+ #ifdef DEBUG
+ char b[4];
+ for (uint8_t i=0; icount(), 0);
+ assertEqual(message->length(), 1);
+}
+
+// -----------------------------------------------------------------------------
+
+testF(CustomTest, test_pack_null) {
+ message->addNull();
+ assertEqual(message->count(), 1);
+ uint8_t expected[] = {1, MESSAGE_PACK_NULL << 4};
+ compare(sizeof(expected), expected);
+ assertEqual(message->type(0), MESSAGE_PACK_NULL);
+}
+
+testF(CustomTest, test_pack_boolean) {
+ message->addBoolean(true);
+ assertEqual(message->count(), 1);
+ uint8_t expected[] = {1, MESSAGE_PACK_BOOLEAN << 4, 0x01};
+ compare(sizeof(expected), expected);
+ assertEqual(message->type(0), MESSAGE_PACK_BOOLEAN);
+ assertEqual(message->getBoolean(0), (bool) true);
+}
+
+testF(CustomTest, test_pack_short) {
+ message->addShort(0x3F);
+ assertEqual(message->count(), 1);
+ uint8_t expected[] = {1, MESSAGE_PACK_SHORT << 4, 0x3F};
+ compare(sizeof(expected), expected);
+ assertEqual(message->type(0), MESSAGE_PACK_SHORT);
+ assertEqual(message->getShort(0), (unsigned char) 0x03F);
+}
+
+testF(CustomTest, test_pack_integer) {
+ message->addInteger(0x45A0);
+ assertEqual(message->count(), 1);
+ uint8_t expected[] = {1, MESSAGE_PACK_INTEGER << 4, 0xA0, 0x45};
+ compare(sizeof(expected), expected);
+ assertEqual(message->type(0), MESSAGE_PACK_INTEGER);
+ assertEqual(message->getInteger(0), (unsigned int) 0x45A0);
+}
+
+testF(CustomTest, test_pack_long) {
+ message->addLong(0x45A0FF);
+ assertEqual(message->count(), 1);
+ uint8_t expected[] = {1, MESSAGE_PACK_LONG << 4, 0xFF, 0xA0, 0x45, 0x00};
+ compare(sizeof(expected), expected);
+ assertEqual(message->type(0), MESSAGE_PACK_LONG);
+ assertEqual(message->getLong(0), (unsigned long) 0x45A0FF);
+}
+
+testF(CustomTest, test_pack_float) {
+ message->addFloat(3.1415926);
+ assertEqual(message->count(), 1);
+ uint8_t expected[] = {1, MESSAGE_PACK_FLOAT << 4, 0xDA, 0x0F, 0x49, 0x40};
+ compare(sizeof(expected), expected);
+ assertEqual(message->type(0), MESSAGE_PACK_FLOAT);
+ assertEqual(message->getFloat(0), (float) 3.1415926);
+}
+
+testF(CustomTest, test_pack_text) {
+ message->addText("HOLA");
+ assertEqual(message->count(), 1);
+ uint8_t expected[] = {1, MESSAGE_PACK_TEXT << 4, 'H', 'O', 'L', 'A', 0x00};
+ compare(sizeof(expected), expected);
+ assertEqual(message->type(0), MESSAGE_PACK_TEXT);
+ assertEqual(message->getTextLength(0), 4);
+ char buffer[5];
+ assertEqual(message->getText(0, buffer), "HOLA");
+}
+
+// -----------------------------------------------------------------------------
+
+testF(CustomTest, test_pack_short_long) {
+ message->addShort(0x2E);
+ message->addLong(0x45A0FF);
+ assertEqual(message->count(), 2);
+ uint8_t expected[] = {2, MESSAGE_PACK_SHORT << 4 | MESSAGE_PACK_LONG, 0x2E, 0xFF, 0xA0, 0x45, 0x00};
+ compare(sizeof(expected), expected);
+ assertEqual(message->type(0), MESSAGE_PACK_SHORT);
+ assertEqual(message->type(1), MESSAGE_PACK_LONG);
+}
+
+testF(CustomTest, test_pack_long_boolean_long) {
+ message->addLong(1);
+ message->addBoolean(true);
+ message->addLong(4);
+ assertEqual(message->count(), 3);
+ uint8_t expected[] = {3, MESSAGE_PACK_LONG << 4 | MESSAGE_PACK_BOOLEAN, MESSAGE_PACK_LONG << 4, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00};
+ compare(sizeof(expected), expected);
+ assertEqual(message->type(0), MESSAGE_PACK_LONG);
+ assertEqual(message->type(1), MESSAGE_PACK_BOOLEAN);
+ assertEqual(message->type(2), MESSAGE_PACK_LONG);
+}
+
+testF(CustomTest, test_pack_short_integer_long) {
+ message->addShort(0x2E);
+ message->addInteger(0x34AB);
+ message->addLong(0x45A0FF);
+ assertEqual(message->count(), 3);
+ uint8_t expected[] = {3, MESSAGE_PACK_SHORT << 4 | MESSAGE_PACK_INTEGER, MESSAGE_PACK_LONG << 4, 0x2E, 0xAB, 0x34, 0xFF, 0xA0, 0x45, 0x00};
+ compare(sizeof(expected), expected);
+ assertEqual(message->type(0), MESSAGE_PACK_SHORT);
+ assertEqual(message->type(1), MESSAGE_PACK_INTEGER);
+ assertEqual(message->type(2), MESSAGE_PACK_LONG);
+}
+
+testF(CustomTest, test_pack_short_text_long) {
+ message->addShort(0x2E);
+ message->addText("HOLA");
+ message->addLong(0x45A0FF);
+ assertEqual(message->count(), 3);
+ uint8_t expected[] = {3, MESSAGE_PACK_SHORT << 4 | MESSAGE_PACK_TEXT, MESSAGE_PACK_LONG << 4, 0x2E, 'H', 'O', 'L', 'A', 0x00, 0xFF, 0xA0, 0x45, 0x00};
+ compare(sizeof(expected), expected);
+ assertEqual(message->type(0), MESSAGE_PACK_SHORT);
+ assertEqual(message->type(1), MESSAGE_PACK_TEXT);
+ assertEqual(message->type(2), MESSAGE_PACK_LONG);
+}
+
+// -----------------------------------------------------------------------------
+
+testF(CustomTest, test_unpack_text) {
+ unsigned char data[] = {1, MESSAGE_PACK_TEXT << 4, 'H', 'O', 'L', 'A', 0x00};
+ assertTrue(message->unpack(data, sizeof(data)));
+ assertEqual(message->count(), 1);
+ assertEqual(message->type(0), MESSAGE_PACK_TEXT);
+ assertEqual(message->getTextLength(0), 4);
+ char buffer[5];
+ assertEqual(message->getText(0, buffer), "HOLA");
+}
+
+testF(CustomTest, test_unpack_short_float_long) {
+ unsigned char data[] = {3, MESSAGE_PACK_SHORT << 4 | MESSAGE_PACK_FLOAT, MESSAGE_PACK_LONG << 4, 0x2E, 0xDA, 0x0F, 0x49, 0x40, 0xFF, 0xA0, 0x45, 0x00};
+ assertTrue(message->unpack(data, sizeof(data)));
+ assertEqual(message->count(), 3);
+ assertEqual(message->type(0), MESSAGE_PACK_SHORT);
+ assertEqual(message->type(1), MESSAGE_PACK_FLOAT);
+ assertEqual(message->type(2), MESSAGE_PACK_LONG);
+ assertEqual(message->getShort(0), (unsigned char) 0x2E);
+ assertEqual(message->getFloat(1), (float) 3.1415926);
+ assertEqual(message->getLong(2), (unsigned long) 0x45A0FF);
+}
+
+testF(CustomTest, test_unpack_long_boolean_long) {
+ unsigned char data[] = {3, MESSAGE_PACK_LONG << 4 | MESSAGE_PACK_BOOLEAN, MESSAGE_PACK_LONG << 4, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00};
+ assertTrue(message->unpack(data, sizeof(data)));
+ assertEqual(message->count(), 3);
+ assertEqual(message->type(0), MESSAGE_PACK_LONG);
+ assertEqual(message->type(1), MESSAGE_PACK_BOOLEAN);
+ assertEqual(message->type(2), MESSAGE_PACK_LONG);
+ assertEqual(message->getLong(0), (unsigned long) 1);
+ assertEqual(message->getBoolean(1), (bool) true);
+ assertEqual(message->getLong(2), (unsigned long) 4);
+}
+
+// -----------------------------------------------------------------------------
+// Main
+// -----------------------------------------------------------------------------
+
+void setup() {
+
+ Serial.begin(115200);
+ while (!Serial);
+
+ Printer::setPrinter(&Serial);
+ #ifdef DEBUG
+ //TestRunner::setVerbosity(Verbosity::kAll);
+ #endif
+
+}
+
+void loop() {
+ TestRunner::run();
+}
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/tests/platformio.ini b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/tests/platformio.ini
new file mode 100644
index 0000000..56df861
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/tests/platformio.ini
@@ -0,0 +1,18 @@
+[platformio]
+src_dir = .
+lib_extra_dirs = ..
+env_default = leonardo
+
+[env:leonardo]
+platform = atmelavr
+board = leonardo
+framework = arduino
+lib_deps =
+ https://github.com/bxparks/AUnit
+
+[env:esp8266]
+platform = espressif8266
+board = esp12e
+framework = arduino
+lib_deps =
+ https://github.com/bxparks/AUnit
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/platformio.ini b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/platformio.ini
index 5d33b76..b0c8dd9 100644
--- a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/platformio.ini
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/platformio.ini
@@ -22,7 +22,8 @@ board_upload.flash_size = 2MB
;board_upload.flash_size = 4MB
board_build.filesystem = littlefs
-upload_speed = 115200
+;upload_speed = 115200
+upload_speed = 921600
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
monitor_rts = 0
@@ -37,14 +38,16 @@ lib_ldf_mode = deep+
; paulstoffregen/Time
; https://github.com/spacehuhn/SimpleList
; https://github.com/spacehuhn/SimpleMap
+; https://github.com/xoseperez/messagepack.git
build_flags =
- -D ARDUINO_USB_MODE=1
- -D ARDUINO_USB_CDC_ON_BOOT=1
+; -D ARDUINO_USB_MODE=1
+; -D ARDUINO_USB_CDC_ON_BOOT=1
-D CONFIG_ARDUHAL_LOG_COLORS=1
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_WARNING
+ -D ENABLE_MESSAGEPACK=0
build_type = debug
debug_tool = esp-builtin
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/ESP32C3Temperature.cpp b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/ESP32C3Temperature.cpp
new file mode 100644
index 0000000..363bf7e
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/ESP32C3Temperature.cpp
@@ -0,0 +1,44 @@
+/* Temperature Sensor Example
+ This example code is in the Public Domain (or CC0 licensed, at your option.)
+ Unless required by applicable law or agreed to in writing, this
+ software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ CONDITIONS OF ANY KIND, either express or implied.
+*/
+#include
+
+/* Note: ESP32 don't support temperature sensor */
+#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
+#include "driver/temp_sensor.h"
+
+/**
+ * @brief readTempSensor()
+ *
+ * @return float, tempSensor data, -10~80°C
+ */
+float readTempSensor()
+{
+ float tsens_out;
+ temp_sensor_read_celsius(&tsens_out);
+
+ return tsens_out;
+}
+
+void setupTempSensor()
+{
+ // Initialize touch pad peripheral, it will start a timer to run a filter
+ log_v("Initializing Temperature sensor");
+ float tsens_out;
+ temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT();
+ temp_sensor_get_config(&temp_sensor);
+ //log_v("default dac %d, clk_div %d", temp_sensor.dac_offset, temp_sensor.clk_div);
+ temp_sensor.dac_offset = TSENS_DAC_DEFAULT; // DEFAULT: range:-10℃ ~ 80℃, error < 1℃.
+ temp_sensor_set_config(temp_sensor);
+ temp_sensor_start();
+ log_i("Temperature sensor(-10℃ ~ 80℃) started...");
+
+}
+
+
+#else
+#error TempSensor N/A
+#endif
\ No newline at end of file
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/_QEspNowSyncMsgPack.cpp b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/_QEspNowSyncMsgPack.cpp
new file mode 100644
index 0000000..1c23bea
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/_QEspNowSyncMsgPack.cpp
@@ -0,0 +1,382 @@
+/**
+ * @file _QEspNowSync.cpp
+ * @author jimmy.su
+ * @brief QEspNow LED Sync
+ * Dependancy library:QuickEspNow, SimpleMap, Esp32Ticker
+ * @version 0.1
+ * @date 2023-01-06
+ *
+ * @copyright Copyright (c) 2023
+ *
+ */
+#include
+#include
+#include
+#include "QuickEspNow.h"
+//PeerListClass myPeers;
+
+//#define LED_ON 0
+//#define LED_OFF 1
+#define DEST_ADDR ESPNOW_BROADCAST_ADDRESS
+
+#include "myEspNow.h" //struct && enum
+espnow_struct EspNow;
+
+bool isEspNowRXed=false;
+
+uint64_t myMac, macLeader;
+//Preferences
+#include
+uint8_t _pinBlink=0;
+bool _pinBlinkOn=0;
+Preferences myPref;
+
+
+//-----------------------------------------------------------------------------
+#include
+Ticker tickBlinkLED;
+Ticker tickOffLED;
+void offLED()
+{
+ digitalWrite(_pinBlink, !_pinBlinkOn); //OFF LED
+}
+void blinkLED()
+{
+ digitalWrite(_pinBlink, _pinBlinkOn); //toggle LED
+ tickOffLED.once_ms(100, offLED); //Off LED 100ms later
+ }
+
+bool isUnicastSent = false;
+uint32_t utimeDataSent; //micros starting sent
+/**
+ * @brief EspNow dataSentCB
+ *
+ * @param address
+ * @param status
+ */
+void dataSentCB (uint8_t* address, uint8_t status ) {
+ if (ESP_NOW_SEND_SUCCESS==status) {
+ isUnicastSent = true;
+ utimeDataSent = micros()-utimeDataSent;
+ Serial.printf ("Unicast to *%02X%02X:%luus!\n", address[4], address[5], utimeDataSent);
+ }
+ else
+ Serial.printf ("Unicast to *%02X%02X:FAIL!\n", address[4], address[5]);
+}
+/**----------------------------------------------------------------------------
+ * @brief EspNow dataReceivedCB
+ *
+ * @param address
+ * @param data
+ * @param len
+ * @param rssi
+ * @param broadcast
+ */
+void dataReceivedCB (uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast) {
+ if (len<=0) return;
+ switch (*data) {
+ case myEspNowMsgType::HELLO:
+ case myEspNowMsgType::ECHO_REQ:
+ case myEspNowMsgType::ECHO_ACK:
+ memcpy(&EspNow, data, len);
+ EspNow.rssi = rssi;
+ {
+ uint32_t uOUI= address[0]<<16 | address[1]<<8 | address[2];
+ uint32_t uID = address[3]<<16 | address[4]<<8 | address[5];
+ EspNow.macAddr64 = ((uint64_t)uOUI) << 24 | uID; //convert OUI|ID into uint64_t
+ }
+ //Serial.printf("RX peer:%llX time:%lu\n", EspNow.macAddr64, EspNow.ums);
+ break;
+ case myEspNowMsgType::MSGPACK:
+ EspNow.msgType = myEspNowMsgType::MSGPACK; //copy msgType to EspNow
+ EspNow.rssi = rssi; //copy rssi to EspNow
+ _myMessagePack.unpack(data+1, len-1); //unpack msg data
+ if (0) {
+ Serial.print("Rx msgPack:");
+ for (int i=0;iaddLong(myMac >> 32);
+ EspMsgPack->addLong(myMac & 0xFFFFFF);
+ EspMsgPack->addLong(millis());
+ EspMsgPack->addFloat(readTempSensor());
+
+ uint8_t uSize = EspMsgPack->length()+1;
+ uint8_t aESP[uSize];
+ aESP[0]=myEspNowMsgType::MSGPACK;
+ memcpy(aESP+1, EspMsgPack->pack(), EspMsgPack->length());
+ //for (int i=0;i>>>>>>>>>> myEspNowMsgPack sent!\n");
+ }
+ else {
+ Serial.printf (">>>>>>>>>> myEspNowMsgPack NOT sent\n");
+ }
+
+}
+void broadcastEspNowHello()
+{
+ espnow_struct myData;
+ myData.msgType = myEspNowMsgType::HELLO;
+ myData.macAddr64 = myMac;
+ //myData.frames = counter++;
+ myData.ums = millis();
+ if (0==quickEspNow.send (DEST_ADDR, (uint8_t*)&myData, sizeof(espnow_struct)) ) {
+ //Serial.printf ("[%lu]>>>", millis());
+ //Serial.printf("ID:%0X Millis:%lu\n", myData.id, myData.ums);
+ macLeader = _myNodesTime->getKey(_myNodesTime->size()-1);
+ if (myData.macAddr64 == macLeader) { //Leader do 1000ms blink by himself
+ uint32_t iums = myData.ums%1000;
+ tickBlinkLED.once_ms(1002-iums, blinkLED); //Scheduling for next blink, with 2ms RTTI adjustment
+ }
+ else {
+ //Team member following blink upon ESPNOW RX
+ }
+ //Update nodes time
+ if (!_myNodesTime->has(myData.macAddr64)) { //New member
+ _myNodesAlive->put(myData.macAddr64, 0); //Add 0 to nodesAlive
+ _myNodesRSSI->put(myData.macAddr64, 0); //Add 0 to nodesRSSI
+ _myNodesTime->put(myData.macAddr64, myData.ums);
+ Serial.printf("<%0llX> Added!\n", myData.macAddr64);
+ //printNodesOld();
+ //printNodes();
+ }
+ else { //Old member
+ _myNodesTime->put(myData.macAddr64, myData.ums);
+ //Update RSSI for myself
+ _myNodesRSSI->put(myData.macAddr64, 0); //No talk to myself!
+ }
+ }
+ else {
+ Serial.printf (">>>>>>>>>> Message NOT sent\n");
+ }
+}
+void unicastEspNowEchoReq(uint64_t mac)
+{
+ espnow_struct myData;
+ myData.msgType = myEspNowMsgType::ECHO_REQ;
+ myData.macAddr64 = myMac;
+ myData.ums = micros();
+ quickEspNow.onDataSent(dataSentCB);
+ //convert uint64 to mac array
+ uint8_t mArray[6];
+ mArray[0]=(mac>>40)&0x00FF;
+ mArray[1]=(mac>>32)&0x00FF;
+ mArray[2]=(mac>>24)&0x00FF;
+ mArray[3]=(mac>>16)&0x00FF;
+ mArray[4]=(mac>>8) &0x00FF;
+ mArray[5]=mac &0x00FF;
+
+ utimeDataSent= micros();
+ if (0==quickEspNow.send (mArray, (uint8_t*)&myData, sizeof(espnow_struct)) ) {
+ //Serial.printf ("[%lu]>>>", millis());
+ //Serial.printf("ID:%0X Millis:%lu\n", myData.id, myData.ms);
+ //Serial.printf(">>> ECHO_REQ sent!\n");
+ }
+ else {
+ Serial.printf(">>> ECHO_REQ NOT sent!\n");
+ }
+}
+void sendEspNowEchoAck()
+{
+ espnow_struct myData;
+ myData.msgType = myEspNowMsgType::ECHO_ACK;
+ myData.macAddr64 = EspNow.macAddr64;
+ myData.ums = EspNow.ums;
+ if (0==quickEspNow.send (DEST_ADDR, (uint8_t*)&myData, sizeof(espnow_struct)) ) {
+ //Serial.printf ("[%lu]>>>", millis());
+ //Serial.printf("ID:%0X Millis:%lu\n", myData.id, myData.ms);
+ //Serial.printf(">>> ECHO_ACK sent!\n");
+ }
+ else {
+ Serial.printf(">>> ECHO_ACK NOT sent!\n");
+ }
+}
+Ticker tickSendHello;
+void espSendHelloCB()
+{
+ quickEspNow.onDataSent(NULL);
+ broadcastEspNowHello();
+}
+
+
+
+//=============================================================================
+void setup () {
+ //pinMode(_pinBlink, OUTPUT);
+
+ #if (ARDUINO_USB_CDC_ON_BOOT)
+ log_w("USB_CDC_ON_BOOT enabled!");
+ if (isUSBCDC()) {
+ if (!Serial) {Serial.begin(115200); delay(300);}
+ // Workaround for when USB CDC is unplugged #7583
+ Serial.setTxTimeoutMs(0); // <<<====== solves USBCDC issue of delay
+ }
+ #else
+ log_w("USB_CDC_ON_BOOT disabled!");
+ if (!Serial) {Serial.begin(115200); delay(300);}
+ #endif
+
+ printESP32info();
+
+ //Save pinBlink to NVS::my-app
+ //----------------------------
+ //myPref.begin("my-app", false); //ReadWrite mode
+ //_pinBlink = 3;
+ //_pinBlinkOn=1;
+ //myPref.putChar("pinBlink", _pinBlink); //reset pinBlink
+ //myPref.putChar("pinBlinkOn", _pinBlinkOn);
+
+ //Read pinBlink from NVS::my-app
+ //------------------------------
+ myPref.begin("my-app", true); //ReadOnly mode
+ _pinBlink=myPref.getChar("pinBlink", 0);
+ _pinBlinkOn=myPref.getChar("pinBlinkOn", 0);
+
+ Serial.printf("NVS pinBlink:%d\n", _pinBlink);
+ Serial.printf("NVS pinBlinkOn:%d\n", _pinBlinkOn);
+
+ myPref.end();
+ pinMode(_pinBlink, OUTPUT); //reset pinBlink as OUTPUT
+
+ WiFi.mode(WIFI_MODE_STA);
+ /* Config LR Mode
+ For LR-enabled AP of ESP32, it is incompatible with traditional 802.11 mode, because the beacon is sent in LR mode.
+ For LR-enabled station of ESP32 whose mode is NOT LR-only mode, it is compatible with traditional 802.11 mode.
+ If both station and AP are ESP32 devices and both of them have enabled LR mode, the negotiated mode supports LR.*/
+ esp_wifi_set_protocol( WIFI_IF_STA, WIFI_PROTOCOL_LR ); //11B/11G/11N/LR
+ //
+ WiFi.disconnect(false);
+ //quickEspNow.onDataSent(dataSentCB);
+ quickEspNow.onDataRcvd(dataReceivedCB);
+ quickEspNow.begin(1); // If you are not connected to WiFi, channel should be specified
+ tickSendHello.attach_ms(1000, espSendHelloCB); //Send HELLO every 1000ms
+
+ //myId=getESP32ChipID24(); //get my ID
+ //myMac = ESP.getEfuseMac();
+ //Serial.printf("EfuseMAC:%012X", myMac);
+ uint8_t mac[6];
+ WiFi.macAddress(mac);
+ Serial.printf("WiFiMAC:" MACSTR "\n", MAC2STR(mac));
+ uint32_t uOui = mac[0]<<16 | mac[1]<<8 | mac[2];
+ uint32_t uId = mac[3]<<16 | mac[4]<<8 | mac[5];
+ myMac = ((uint64_t)uOui)<<24 | uId;
+ macLeader = myMac;
+ //Serial.printf("uOui Id:%X:%X", uOui, uId);
+ Serial.printf("My MAC address:%llX\n", myMac);
+
+
+ setupNodesMap();
+ _myNodesAlive->clear();
+ _myNodesTime->put(myMac, millis());
+ printNodesAlive();
+ //=====================================
+
+}
+
+uint32_t lastStatusMs=0;
+uint8_t counter=0;
+void loop () {
+ //print Nodes & check KeepAlive every 3seconds
+ if ((millis()-lastStatusMs)>=3000) {
+ lastStatusMs = millis(); //update lastStatus counter
+ //printNodesOld();
+ //printNodesAlive();
+ //Check KeepAlive, drop node when timeDiff<1000ms
+ for (int i=0;i<_myNodesTime->size();i++) {
+ uint64_t mac=_myNodesTime->getKey(i); //get key
+ uint32_t timeOld = _myNodesAlive->getData(_myNodesAlive->getIndex(mac)); //find key/value in alive nodes
+ uint32_t timeNew = _myNodesTime->getData(i);
+ uint32_t timeDiff= timeNew - timeOld;
+
+ _myNodesAlive->put(mac, timeNew); //update NodesAlive w/ new time
+ //Serial.printf(" %0llX:%lu", mac, timeDiff);
+ if (timeDiff<1000){
+ _myNodesTime->remove(_myNodesTime->getIndex(mac));
+ _myNodesAlive->remove(_myNodesAlive->getIndex(mac));
+ _myNodesRSSI->remove(_myNodesRSSI->getIndex(mac));
+ Serial.printf("<%0llX> Dropped!\n", mac);
+ }
+ }
+ printNodesRSSI();
+ //printNodes();
+ //Serial.println();
+ //sendEspNowEchoReq(); //request a HELLO ECHO!
+ #if (ENABLE_MESSAGEPACK)
+ sendEspNowMsgPack();
+ #endif
+ #if (ENABLE_UNICAST)
+ //unicast to members in myNodes
+ if (counter <_myNodesTime->size()) {
+ uint64_t mac = _myNodesTime->getKey(counter);
+ if (mac != myMac)
+ unicastEspNowEchoReq(mac);
+ counter++;
+ }
+ else counter=0;
+ #endif
+ }
+ if (isEspNowRXed) { //Got EspNow RX data?
+ isEspNowRXed=false;
+ switch (EspNow.msgType) {
+ case myEspNowMsgType::HELLO:
+ //idLeader is the last one in _myNodesTime
+ macLeader = _myNodesTime->getKey(_myNodesTime->size()-1);
+ if (EspNow.macAddr64 == macLeader) { //Leader's HELLO
+ tickBlinkLED.once_ms(1000-(EspNow.ums%1000), blinkLED); //Scheduling for next blink and try to sync w/ Leader
+ }
+ if (!_myNodesTime->has(EspNow.macAddr64)) { //New memeber
+ _myNodesAlive->put(EspNow.macAddr64, 0); //Add 0 to nodesAlive
+ _myNodesRSSI->put(EspNow.macAddr64, 0); //Add 0 to nodesRSSI
+ _myNodesTime->put(EspNow.macAddr64, EspNow.ums);
+ Serial.printf("<%0llX> Added!\n", EspNow.macAddr64);
+ //printNodesOld();
+ //printNodes();
+ }
+ else { //Old member
+ _myNodesTime->put(EspNow.macAddr64, EspNow.ums);
+ //Average RSSI for node
+ int8_t rssiOld = _myNodesRSSI->getData(_myNodesRSSI->getIndex(EspNow.macAddr64));
+ //Serial.printf("<%0llX>RSSI:%d/%d\n", EspNow.macAddr64, rssiOld, EspNow.rssi);
+ _myNodesRSSI->put(EspNow.macAddr64, (EspNow.rssi/2 + rssiOld/2));
+ }
+ break;
+ case myEspNowMsgType::ECHO_REQ:
+ //sendEspNowEchoAck(); //Ack the REQ, send back HELLO
+ //break;
+ case myEspNowMsgType::ECHO_ACK: //Echo acked! calculate RTTI
+ if (myMac == EspNow.macAddr64) {
+ uint32_t uRTTI = micros() - EspNow.ums;
+ Serial.printf("!!! ECHO RTTI=%luus from:%llX (%d)dBm\n", uRTTI, EspNow.macAddr64, EspNow.rssi);
+ //Serial.printf(" From mac:%02x:%02x:%02x:%02x:%02x:%02x\n", MAC2STR(EspNow.mac));
+ }
+ break;
+ case myEspNowMsgType::MSGPACK:
+ parseMessagePack(_myMessagePack.pack());
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myEspNow.h b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myEspNow.h
index 71b8671..58093c2 100644
--- a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myEspNow.h
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myEspNow.h
@@ -5,22 +5,27 @@
#define LED0 0
+#include
+extern MessagePack _myMessagePack;
+
enum myEspNowMsgType {
HELLO =0x10, // ID+frames+millis
- SYNC_REQ =0x80, // Request to sync
- SYNC_ACK,
+ ECHO_REQ, // HELLO ECHO request, send HELLO packets back!
+ ECHO_ACK, // HELLO ECHO ackowledge
+ MSGPACK =0x80, // MsgPack Data
+
Reserved // Reserved
};
struct espnow_struct {
uint8_t msgType; //msgType: 0x10:time-report, 0x18:echo time-report
- uint32_t id;
- uint16_t frames;
- uint32_t ms;
+ uint64_t macAddr64;
+ //uint16_t frames;
+ uint32_t ums;
int8_t rssi;
};
-
+extern bool isUSBCDC();
extern uint32_t getESP32ChipID24();
extern void neopixelRGB(uint8_t r, uint8_t g, uint8_t b);
extern void neopixelSetupBlink(int msBlink);
@@ -29,14 +34,21 @@ extern void printESP32info();
//extern SimpleList* listID;
//extern void printListID();
//extern void setupListID();
-
-extern SimpleMap *_myNodes, *_myNodesOld;
+
+extern uint64_t myMac;
+extern SimpleMap *_myNodesTime, *_myNodesAlive;
+extern SimpleMap *_myNodesRSSI;
extern void setupNodesMap();
-extern void printNodes();
+extern void printNodesTime();
extern void printNodesOld();
-
+extern void printNodesAlive();
+extern void printNodesRSSI();
//WiFi Promiscuous Sniff
//extern void setupWiFiSniffer();
+extern float readTempSensor();
+extern void setupTempSensor();
+
+extern void parseMessagePack(unsigned char * data);
#endif
\ No newline at end of file
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myMessagePack.cpp b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myMessagePack.cpp
new file mode 100644
index 0000000..667c860
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myMessagePack.cpp
@@ -0,0 +1,39 @@
+
+#include
+#include
+
+MessagePack _myMessagePack; //MessagePack for rx
+
+void parseMessagePack(unsigned char * data) {
+ //MessagePack * message = new MessagePack();
+ Serial.print("myMessagePack:");
+ for (int i=0;i<_myMessagePack.length();i++) {
+ Serial.printf(" %02X", _myMessagePack.pack()[i]);
+ }
+ Serial.println();
+ // Load the data
+ //message->unpack(data, message->length());
+ // Number of elements
+ unsigned char count = _myMessagePack.count();
+ //Serial.print("Number of values: ");
+ //Serial.println(count);
+ // Walk elements
+ Serial.print("(");
+ char buffer[32];
+ for (unsigned char i=0; i
#include
-SimpleMap *_myNodes, *_myNodesOld;
+SimpleMap *_myNodesTime, *_myNodesAlive;
+SimpleMap *_myNodesRSSI;
+#include "myEspNow.h"
void setupNodesMap()
{
- _myNodes = new SimpleMap([](uint32_t &a, uint32_t &b) ->int {
+ _myNodesTime = new SimpleMap([](uint64_t &a, uint64_t &b) ->int {
if (a == b) return 0; // a and b are equal
else if (a > b) return 1; // a is bigger than b
else return -1; // a is smaller than b
});
- _myNodesOld = new SimpleMap([](uint32_t &a, uint32_t &b) ->int {
+ _myNodesAlive = new SimpleMap([](uint64_t &a, uint64_t &b) ->int {
if (a == b) return 0; // a and b are equal
else if (a > b) return 1; // a is bigger than b
else return -1; // a is smaller than b
});
+ _myNodesRSSI = new SimpleMap([](uint64_t &a, uint64_t &b) ->int {
+ if (a == b) return 0; // a and b are equal
+ else if (a > b) return 1; // a is bigger than b
+ else return -1; // a is smaller than b
+ });
}
-void printNodes()
+void printNodesTime()
{
- Serial.printf("[%lu]===>[", millis());
- for (int i=0;i<_myNodes->size();i++) {
- Serial.printf(" %0X:%lu",_myNodes->getKey(i), _myNodes->getData(i));
+ Serial.printf("[%lu]===>%d[", millis(), _myNodesTime->size());
+ for (int i=0;i<_myNodesTime->size();i++) {
+ Serial.printf(" %0llX:%lu",_myNodesTime->getKey(i), _myNodesTime->getData(i)/1000);
}
- Serial.printf("]<===\n");
+ int32_t imsLeader= _myNodesTime->getData(_myNodesTime->size()-1)%1000;
+ Serial.println("]<===");
+ //Serial.printf("]<=== %03lu(%03lu)\n", imsLeader, 1000-imsLeader);
}
void printNodesOld()
{
- Serial.printf("--->(");
- for (int i=0;i<_myNodesOld->size();i++) {
- Serial.printf(" %0X:%lu",_myNodesOld->getKey(i), _myNodesOld->getData(i));
+ Serial.printf("[%lu]--->%d(", millis(), _myNodesAlive->size());
+ for (int i=0;i<_myNodesAlive->size();i++) {
+ Serial.printf(" %0llX:%lu",_myNodesAlive->getKey(i), _myNodesAlive->getData(i)/1000);
}
Serial.printf(")<---\n");
-}
\ No newline at end of file
+}
+
+/**
+ * @brief print Nodes && KeepAlive time
+ *
+ */
+void printNodesAlive()
+{
+ Serial.printf("[%lu]>>>%d[", millis(), _myNodesTime->size());
+ for (int i=0;i<_myNodesTime->size();i++) { //print macId:alive seconds
+ uint64_t mac = _myNodesTime->getKey(i);
+ char cMark = '*';
+ if (mac == myMac) cMark='#';
+ Serial.printf(" %c%04llX:%3lu", cMark, mac&0x00FFFF, (_myNodesTime->getData(i)-_myNodesAlive->getData(i))/1000);
+ }
+ int32_t imsLeader= _myNodesTime->getData(_myNodesTime->size()-1)%1000;
+ Serial.printf("]<<< %03lu(%03lu)ms\n", imsLeader, 1000-imsLeader); //blink millis
+}
+
+void printNodesRSSI()
+{
+ Serial.printf("[%lu]\t>>>%d[", millis(), _myNodesTime->size());
+ for (int i=0;i<_myNodesRSSI->size();i++) { //print macId:alive seconds
+ uint64_t mac = _myNodesRSSI->getKey(i);
+ char cMark = '*';
+ if (mac == myMac) cMark='#';
+ Serial.printf(" %c%04llX:%03d", cMark, mac&0x00FFFF, (mac==myMac)? 0:_myNodesRSSI->getData(i));
+ }
+ int32_t imsLeader= _myNodesTime->getData(_myNodesTime->size()-1)%1000;
+ Serial.printf("]<<< \tSync:%03lu(%03lu)ms\n", imsLeader, 1000-imsLeader); //blink millis
+}
diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/utilCDC.cpp b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/utilCDC.cpp
new file mode 100644
index 0000000..69554e2
--- /dev/null
+++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/utilCDC.cpp
@@ -0,0 +1,18 @@
+#include
+#include
+
+bool isUSBCDC()
+ {
+ uint32_t regSOF1= *((volatile uint32_t *) USB_SERIAL_JTAG_FRAM_NUM_REG);
+ delay(5);
+ uint32_t regSOF2= *((volatile uint32_t *) USB_SERIAL_JTAG_FRAM_NUM_REG);
+ Serial.printf("USB SOF 3ms diff:%02d\n", regSOF2-regSOF1);
+
+ bool isUSBCDCconnected = ((regSOF2-regSOF1)>0) ? true:false;
+ if (isUSBCDCconnected)
+ log_d("USBCDC Connected!");
+ else
+ log_w("USBCDC NOT Connected!");
+
+ return isUSBCDCconnected;
+ }