From 27c8b4f2da8f9f995886ff4b74916805ea9346b3 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 6 Oct 2021 10:16:48 +0200 Subject: [PATCH 01/37] Removing Wire/Serial abstractions since Arduino_ThreadsafeIO will be used for that. --- src/Arduino_Threads.h | 4 +- src/Serial.cpp | 3 - src/SerialDispatcher.h | 199 ----------------------------------------- src/Wire.cpp | 11 --- src/Wire.h | 178 ------------------------------------ 5 files changed, 1 insertion(+), 394 deletions(-) delete mode 100644 src/Serial.cpp delete mode 100644 src/SerialDispatcher.h delete mode 100644 src/Wire.cpp delete mode 100644 src/Wire.h diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index f176365..2684e3e 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -1,6 +1,7 @@ #ifndef ARDUINO_THREADS_H_ #define ARDUINO_THREADS_H_ +#include #include #define SOURCE(name, type) \ @@ -305,7 +306,4 @@ private: \ }; \ CONCAT(tabname,Class) tabname; -#include "Wire.h" -#include "SerialDispatcher.h" - #endif /* ARDUINO_THREADS_H_ */ diff --git a/src/Serial.cpp b/src/Serial.cpp deleted file mode 100644 index 9553c59..0000000 --- a/src/Serial.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "SerialDispatcher.h" - -SerialClassDispatcher Serial(SerialUSB); \ No newline at end of file diff --git a/src/SerialDispatcher.h b/src/SerialDispatcher.h deleted file mode 100644 index 43acedf..0000000 --- a/src/SerialDispatcher.h +++ /dev/null @@ -1,199 +0,0 @@ -#ifndef __SERIAL_DISPATCHER_H__ -#define __SERIAL_DISPATCHER_H__ - -#include "Arduino.h" -#undef Serial -#include "api/RingBuffer.h" - -struct _sinkBuffers { - osThreadId_t id; - bool reader; - bool raw; - rtos::Semaphore* sem; - RingBuffer rxBuffer; - RingBuffer txBuffer; -}; - -#define READ_READY_UNBLOCK (1 << 1) - -class SerialClassDispatcher : public HardwareSerial { - public: - SerialClassDispatcher(HardwareSerial& _serial) : serial(_serial) { - - } - void begin(unsigned long baudrate) { - if (!begun) { - serial.begin(baudrate); - begun = true; - printer.start(mbed::callback(this, &SerialClassDispatcher::timedPrint)); - } - sinkBuffers[users].id = rtos::ThisThread::get_id(); - sinkBuffers[users].sem = new rtos::Semaphore(1); - sinkBuffers[users].raw = false; - users++; - } - - void begin(unsigned long baudrate, uint16_t config) { - if (!begun) { - serial.begin(baudrate, config); - begun = true; - } - sinkBuffers[users].id = rtos::ThisThread::get_id(); - sinkBuffers[users].sem = new rtos::Semaphore(1); - sinkBuffers[users].raw = false; - users++; - } - - using Print::write; // pull in write(str) and write(buf, size) from Print - - operator bool() { - return serial; - } - - void tags(bool enable = true) { - print_tags = enable; - } - - void end() { - if (users == 0) { - serial.end(); - } else { - users--; - } - } - - size_t write(uint8_t data) { - findSemaphore(rtos::ThisThread::get_id())->acquire(); - findThreadTxBuffer(rtos::ThisThread::get_id()).store_char(data); - findSemaphore(rtos::ThisThread::get_id())->release(); - unlock_print.set(READ_READY_UNBLOCK); - } - - size_t write(const uint8_t* data, size_t len) { - findSemaphore(rtos::ThisThread::get_id())->acquire(); - for (int i=0; irelease(); - unlock_print.set(READ_READY_UNBLOCK); - } - - void flushReadBuffer() { - while (serial.available()) { - int c = serial.read(); - for (int i = 0; i < users; i++) { - if (sinkBuffers[i].reader) { - sinkBuffers[i].rxBuffer.store_char(c); - } - } - } - } - - int read() { - *isReader(rtos::ThisThread::get_id()) = true; - flushReadBuffer(); - return findThreadRxBuffer(rtos::ThisThread::get_id()).read_char(); - } - - int peek() { - *isReader(rtos::ThisThread::get_id()) = true; - flushReadBuffer(); - return findThreadRxBuffer(rtos::ThisThread::get_id()).peek(); - } - - void raw(bool _raw = true) { - *isRaw(rtos::ThisThread::get_id()) = _raw; - } - - void flush() { - serial.flush(); - } - - int available() { - *isReader(rtos::ThisThread::get_id()) = true; - flushReadBuffer(); - return findThreadRxBuffer(rtos::ThisThread::get_id()).available(); - } - - private: - - void timedPrint() { - while (1) { - unlock_print.wait_any(READ_READY_UNBLOCK, osWaitForever, true); - for (int i = 0; i < users; i++) { - sinkBuffers[i].sem->acquire(); - // Implementation "leak", should be changed at RingBuffer API level - int c = sinkBuffers[i].txBuffer._iHead == 0 ? - sinkBuffers[i].txBuffer._aucBuffer[sizeof(sinkBuffers[i].txBuffer._aucBuffer) -1] : - sinkBuffers[i].txBuffer._aucBuffer[sinkBuffers[i].txBuffer._iHead - 1]; - if ((!sinkBuffers[i].raw && (c == '\n' /*|| c == '\r' */|| c == '\0')) || - sinkBuffers[i].raw || !sinkBuffers[i].txBuffer.availableForStore()) { - if (sinkBuffers[i].txBuffer.available() && print_tags) { - serial.print("["); - serial.print(i); - serial.print("] "); - } - while (sinkBuffers[i].txBuffer.available()) { - serial.write(sinkBuffers[i].txBuffer.read_char()); - } - } - sinkBuffers[i].sem->release(); - } - } - } - - bool* isReader(osThreadId_t id) { - for (int i = 0; i < 10; i++) { - if (id == sinkBuffers[i].id) { - return &sinkBuffers[i].reader; - } - } - } - - bool* isRaw(osThreadId_t id) { - for (int i = 0; i < 10; i++) { - if (id == sinkBuffers[i].id) { - return &sinkBuffers[i].raw; - } - } - } - - rtos::Semaphore* findSemaphore(osThreadId_t id) { - for (int i = 0; i < 10; i++) { - if (id == sinkBuffers[i].id) { - return sinkBuffers[i].sem; - } - } - } - - RingBuffer& findThreadTxBuffer(osThreadId_t id) { - for (int i = 0; i < 10; i++) { - if (id == sinkBuffers[i].id) { - return sinkBuffers[i].txBuffer; - } - } - } - - RingBuffer& findThreadRxBuffer(osThreadId_t id) { - for (int i = 0; i < 10; i++) { - if (id == sinkBuffers[i].id) { - return sinkBuffers[i].rxBuffer; - } - } - } - - private: - HardwareSerial& serial; - int users = 0; - bool begun = false; - int currentClock = 400000; - struct _sinkBuffers sinkBuffers[10]; - osThreadId_t currentThread; - rtos::Thread printer; - rtos::EventFlags unlock_print; - bool print_tags = false; -}; - -extern SerialClassDispatcher Serial; - -#endif \ No newline at end of file diff --git a/src/Wire.cpp b/src/Wire.cpp deleted file mode 100644 index aed2f05..0000000 --- a/src/Wire.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "Wire.h" -#define Wire WireReal -#define Wire1 WireReal1 -#include "../Wire/Wire.cpp" -#undef Wire -#undef Wire1 - -WireClassDispatcher Wire(WireReal); -WireClassDispatcher Wire1(WireReal1); -//WireClassDispatcher Wire(WireReal); -//WireClassDispatcher Wire1(Wire1Real); \ No newline at end of file diff --git a/src/Wire.h b/src/Wire.h deleted file mode 100644 index 2827d64..0000000 --- a/src/Wire.h +++ /dev/null @@ -1,178 +0,0 @@ -#ifndef __WIRE_WRAPPER_H__ -#define __WIRE_WRAPPER_H__ - -#include "Portenta_System.h" // just a trick to allow including the real Wire.h -#define Wire WireReal -#define Wire1 WireReal1 -#include "../Wire/Wire.h" -#undef Wire -#undef Wire1 -#include "api/RingBuffer.h" - -struct requiredClocks { - osThreadId_t id; - int clock; - RingBuffer rxBuffer; - bool transaction; -}; - -class WireClassDispatcher : public HardwareI2C { - public: - WireClassDispatcher(HardwareI2C& _wire) : wire(_wire) { - sem = new rtos::Semaphore(1); - } - void begin() { - sem->acquire(); - if (!begun) { - wire.begin(); - begun = true; - } - idClock[users].id = rtos::ThisThread::get_id(); - idClock[users].clock = currentClock; - users++; - sem->release(); - } - void begin(uint8_t) { - /*doNothing*/ - } - void onReceive(void (*)(int)) { - /*doNothing*/ - } - void onRequest(void (*)()) { - /*doNothing*/ - } - - void end() { - if (users == 0) { - wire.end(); - } else { - users--; - } - } - - void setClock(uint32_t freq) { - // must be called on a per-thread basis - if (freq != currentClock) { - wire.setClock(freq); - currentClock = freq; - *findThreadClock(rtos::ThisThread::get_id()) = currentClock; - } - } - - void beginTransmission(uint8_t address) { - //lock to caller thread until endTransmission(true) is called - sem->acquire(); - int freq = *findThreadClock(rtos::ThisThread::get_id()); - if (freq != currentClock) { - setClock(freq); - } - currentThread = rtos::ThisThread::get_id(); - wire.beginTransmission(address); - } - - uint8_t endTransmission(bool stopBit) { - uint8_t res = wire.endTransmission(stopBit); - if (stopBit) { - sem->release(); - *transactionInProgress(rtos::ThisThread::get_id()) = false; - } else { - *transactionInProgress(rtos::ThisThread::get_id()) = true; - } - return res; - } - - uint8_t endTransmission(void) { - return endTransmission(true); - } - - size_t requestFrom(uint8_t address, size_t len, bool stopBit) { - if (!*transactionInProgress(rtos::ThisThread::get_id())) { - sem->acquire(); - } - uint8_t ret = wire.requestFrom(address, len, stopBit); - if (ret > 0) { - while (wire.available()) { - findThreadRxBuffer(rtos::ThisThread::get_id()).store_char(wire.read()); - } - } - if (stopBit) { - *transactionInProgress(rtos::ThisThread::get_id()) = false; - sem->release(); - } else { - *transactionInProgress(rtos::ThisThread::get_id()) = true; - } - return ret; - } - - size_t requestFrom(uint8_t address, size_t len) { - return requestFrom(address, len, true); - } - - size_t write(uint8_t data) { - if (currentThread != rtos::ThisThread::get_id()) { - return 0; - } - return wire.write(data); - } - - size_t write(const uint8_t* data, int len) { - if (currentThread != rtos::ThisThread::get_id()) { - return 0; - } - return wire.write(data, len); - } - - int read() { - return findThreadRxBuffer(rtos::ThisThread::get_id()).read_char(); - } - - int peek() { - return findThreadRxBuffer(rtos::ThisThread::get_id()).peek(); - } - - void flush() { - } - - int available() { - return findThreadRxBuffer(rtos::ThisThread::get_id()).available(); - } - - private: - int* findThreadClock(osThreadId_t id) { - for (int i = 0; i < 10; i++) { - if (id == idClock[i].id) { - return &idClock[i].clock; - } - } - } - bool* transactionInProgress(osThreadId_t id) { - for (int i = 0; i < 10; i++) { - if (id == idClock[i].id) { - return &idClock[i].transaction; - } - } - } - RingBuffer& findThreadRxBuffer(osThreadId_t id) { - for (int i = 0; i < 10; i++) { - if (id == idClock[i].id) { - return idClock[i].rxBuffer; - } - } - } - - private: - HardwareI2C& wire; - int users = 0; - bool begun = false; - rtos::Semaphore* sem; - int currentClock = 400000; - struct requiredClocks idClock[10]; - osThreadId_t currentThread; -}; - -extern WireClassDispatcher Wire; -extern WireClassDispatcher Wire1; - -#define TwoWire WireClassDispatcher - -#endif \ No newline at end of file From a65ed03479dd75a7f2c67e31f01f083a07487c59 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 6 Oct 2021 10:54:46 +0200 Subject: [PATCH 02/37] Deleting super-fluous/confusing example code. --- examples/Enqueue_test/Enqueue.inot | 13 -- examples/Enqueue_test/Enqueue_test.ino | 15 --- examples/Enqueue_test/SharedVariables.h | 1 - examples/Leds/Leds.ino | 13 -- examples/Leds/SharedVariables.h | 1 - examples/Leds/ledblue.inot | 10 -- .../Nano33BLEMegaSketch/Accelerometer.inot | 50 -------- examples/Nano33BLEMegaSketch/Gesture.inot | 84 ------------- examples/Nano33BLEMegaSketch/Humidity.inot | 45 ------- .../Nano33BLEMegaSketch.ino | 14 --- .../Nano33BLEMegaSketch/SharedVariables.h | 1 - examples/SharedResources/SharedResources.ino | 35 ------ examples/SharedResources/SharedVariables.h | 12 -- examples/SharedResources/ecc_reader.inot | 15 --- examples/SharedResources/pf_reader.inot | 21 ---- examples/SharedResources/scanner.inot | 14 --- examples/SharedResources/temp_reader.inot | 11 -- .../Accelerometer.inot | 58 --------- .../GetRandom.inot | 18 --- .../SerialReader.inot | 14 --- .../SharedResourcesVariousLibraries.ino | 31 ----- .../SharedVariables.h | 12 -- .../TempReader.inot | 115 ------------------ examples/i2c_concurrent/SharedVariables.h | 12 -- examples/i2c_concurrent/ecc_reader.inot | 15 --- examples/i2c_concurrent/i2c_concurrent.ino | 57 --------- examples/i2c_concurrent/pf_reader.inot | 23 ---- examples/i2c_concurrent/scanner.inot | 14 --- examples/i2c_concurrent/temp_reader.inot | 11 -- .../i2c_concurrent/temp_reader_complete.inot | 27 ---- 30 files changed, 762 deletions(-) delete mode 100644 examples/Enqueue_test/Enqueue.inot delete mode 100644 examples/Enqueue_test/Enqueue_test.ino delete mode 100644 examples/Enqueue_test/SharedVariables.h delete mode 100644 examples/Leds/Leds.ino delete mode 100644 examples/Leds/SharedVariables.h delete mode 100644 examples/Leds/ledblue.inot delete mode 100644 examples/Nano33BLEMegaSketch/Accelerometer.inot delete mode 100644 examples/Nano33BLEMegaSketch/Gesture.inot delete mode 100644 examples/Nano33BLEMegaSketch/Humidity.inot delete mode 100644 examples/Nano33BLEMegaSketch/Nano33BLEMegaSketch.ino delete mode 100644 examples/Nano33BLEMegaSketch/SharedVariables.h delete mode 100644 examples/SharedResources/SharedResources.ino delete mode 100644 examples/SharedResources/SharedVariables.h delete mode 100644 examples/SharedResources/ecc_reader.inot delete mode 100644 examples/SharedResources/pf_reader.inot delete mode 100644 examples/SharedResources/scanner.inot delete mode 100644 examples/SharedResources/temp_reader.inot delete mode 100644 examples/SharedResourcesVariousLibraries/Accelerometer.inot delete mode 100644 examples/SharedResourcesVariousLibraries/GetRandom.inot delete mode 100644 examples/SharedResourcesVariousLibraries/SerialReader.inot delete mode 100644 examples/SharedResourcesVariousLibraries/SharedResourcesVariousLibraries.ino delete mode 100644 examples/SharedResourcesVariousLibraries/SharedVariables.h delete mode 100644 examples/SharedResourcesVariousLibraries/TempReader.inot delete mode 100644 examples/i2c_concurrent/SharedVariables.h delete mode 100644 examples/i2c_concurrent/ecc_reader.inot delete mode 100644 examples/i2c_concurrent/i2c_concurrent.ino delete mode 100644 examples/i2c_concurrent/pf_reader.inot delete mode 100644 examples/i2c_concurrent/scanner.inot delete mode 100644 examples/i2c_concurrent/temp_reader.inot delete mode 100644 examples/i2c_concurrent/temp_reader_complete.inot diff --git a/examples/Enqueue_test/Enqueue.inot b/examples/Enqueue_test/Enqueue.inot deleted file mode 100644 index f7cfaf4..0000000 --- a/examples/Enqueue_test/Enqueue.inot +++ /dev/null @@ -1,13 +0,0 @@ -void setup() { - // put your setup code here, to run once: - -} - -int i = 0; - -void loop() { - // Continuously pump counter - delay(100); - i++; - counter = i; -} diff --git a/examples/Enqueue_test/Enqueue_test.ino b/examples/Enqueue_test/Enqueue_test.ino deleted file mode 100644 index c0f3b1d..0000000 --- a/examples/Enqueue_test/Enqueue_test.ino +++ /dev/null @@ -1,15 +0,0 @@ -void setup() { - // put your setup code here, to run once: - Serial.begin(115200); - while (!Serial) {} - Enqueue.start(); - Serial.println("start"); -} - -void loop() { - // put your main code here, to run repeatedly: - delay(1000); - for (int i = 0; i < 10; i++) { - Serial.println(counter); - } -} diff --git a/examples/Enqueue_test/SharedVariables.h b/examples/Enqueue_test/SharedVariables.h deleted file mode 100644 index 51ea60e..0000000 --- a/examples/Enqueue_test/SharedVariables.h +++ /dev/null @@ -1 +0,0 @@ -Shared counter; diff --git a/examples/Leds/Leds.ino b/examples/Leds/Leds.ino deleted file mode 100644 index fc6e1fc..0000000 --- a/examples/Leds/Leds.ino +++ /dev/null @@ -1,13 +0,0 @@ -void setup() { - // put your setup code here, to run once: - pinMode(LEDR, OUTPUT); - ledblue.start(); -} - -void loop() { - // put your main code here, to run repeatedly: - digitalWrite(LEDR, HIGH); - delay(1000); - digitalWrite(LEDR, LOW); - delay(1000); -} diff --git a/examples/Leds/SharedVariables.h b/examples/Leds/SharedVariables.h deleted file mode 100644 index 8b13789..0000000 --- a/examples/Leds/SharedVariables.h +++ /dev/null @@ -1 +0,0 @@ - diff --git a/examples/Leds/ledblue.inot b/examples/Leds/ledblue.inot deleted file mode 100644 index 7329782..0000000 --- a/examples/Leds/ledblue.inot +++ /dev/null @@ -1,10 +0,0 @@ -void setup() { - pinMode(LEDB, OUTPUT); -} - -void loop() { - digitalWrite(LEDB, HIGH); - delay(80); - digitalWrite(LEDB, LOW); - delay(100); -} diff --git a/examples/Nano33BLEMegaSketch/Accelerometer.inot b/examples/Nano33BLEMegaSketch/Accelerometer.inot deleted file mode 100644 index 97b28ab..0000000 --- a/examples/Nano33BLEMegaSketch/Accelerometer.inot +++ /dev/null @@ -1,50 +0,0 @@ -/* - Arduino LSM9DS1 - Simple Accelerometer - - This example reads the acceleration values from the LSM9DS1 - sensor and continuously prints them to the Serial Monitor - or Serial Plotter. - - The circuit: - - Arduino Nano 33 BLE Sense - - created 10 Jul 2019 - by Riccardo Rizzo - - This example code is in the public domain. -*/ - -#include - -void setup() { - Serial.begin(9600); - while (!Serial); - Serial.println("Started"); - - if (!IMU.begin()) { - Serial.println("Failed to initialize IMU!"); - while (1); - } - - Serial.print("Accelerometer sample rate = "); - Serial.print(IMU.accelerationSampleRate()); - Serial.println(" Hz"); - Serial.println(); - Serial.println("Acceleration in G's"); - Serial.println("X\tY\tZ"); -} - -void loop() { - float x, y, z; - - if (IMU.accelerationAvailable()) { - IMU.readAcceleration(x, y, z); - - Serial.print(x); - Serial.print('\t'); - Serial.print(y); - Serial.print('\t'); - Serial.println(z); - } - delay(100); -} diff --git a/examples/Nano33BLEMegaSketch/Gesture.inot b/examples/Nano33BLEMegaSketch/Gesture.inot deleted file mode 100644 index 8ece3c5..0000000 --- a/examples/Nano33BLEMegaSketch/Gesture.inot +++ /dev/null @@ -1,84 +0,0 @@ -/* - APDS9960 - All sensor data from APDS9960 - - This example reads all data from the on-board APDS9960 sensor of the - Nano 33 BLE Sense: - - color RGB (red, green, blue) - - proximity - - gesture - and prints updates to the Serial Monitor every 100 ms. - - The circuit: - - Arduino Nano 33 BLE Sense - - This example code is in the public domain. -*/ - -#include - -void setup() { - Serial.begin(9600); - while (!Serial); // Wait for serial monitor to open - - if (!APDS.begin()) { - Serial.println("Error initializing APDS9960 sensor."); - while (true); // Stop forever - } -} - -int proximity = 0; -int r = 0, g = 0, b = 0; -unsigned long lastUpdate = 0; - -void loop() { - - // Check if a proximity reading is available. - if (APDS.proximityAvailable()) { - proximity = APDS.readProximity(); - } - - // check if a gesture reading is available - if (APDS.gestureAvailable()) { - int gesture = APDS.readGesture(); - switch (gesture) { - case GESTURE_UP: - Serial.println("Detected UP gesture"); - break; - - case GESTURE_DOWN: - Serial.println("Detected DOWN gesture"); - break; - - case GESTURE_LEFT: - Serial.println("Detected LEFT gesture"); - break; - - case GESTURE_RIGHT: - Serial.println("Detected RIGHT gesture"); - break; - - default: - // ignore - break; - } - } - - // check if a color reading is available - if (APDS.colorAvailable()) { - APDS.readColor(r, g, b); - } - - // Print updates every 100ms - if (millis() - lastUpdate > 100) { - lastUpdate = millis(); - Serial.print("PR="); - Serial.print(proximity); - Serial.print(" rgb="); - Serial.print(r); - Serial.print(","); - Serial.print(g); - Serial.print(","); - Serial.println(b); - } - delay(320); -} diff --git a/examples/Nano33BLEMegaSketch/Humidity.inot b/examples/Nano33BLEMegaSketch/Humidity.inot deleted file mode 100644 index 890adf5..0000000 --- a/examples/Nano33BLEMegaSketch/Humidity.inot +++ /dev/null @@ -1,45 +0,0 @@ -/* - HTS221 - Read Sensors - - This example reads data from the on-board HTS221 sensor of the - Nano 33 BLE Sense and prints the temperature and humidity sensor - values to the Serial Monitor once a second. - - The circuit: - - Arduino Nano 33 BLE Sense - - This example code is in the public domain. -*/ - -#include - -void setup() { - Serial.begin(9600); - while (!Serial); - - if (!HTS.begin()) { - Serial.println("Failed to initialize humidity temperature sensor!"); - while (1); - } -} - -void loop() { - // read all the sensor values - float temperature = HTS.readTemperature(); - float humidity = HTS.readHumidity(); - - // print each of the sensor values - Serial.print("Temperature = "); - Serial.print(temperature); - Serial.println(" °C"); - - Serial.print("Humidity = "); - Serial.print(humidity); - Serial.println(" %"); - - // print an empty line - Serial.println(); - - // wait 1 second to print again - delay(1000); -} diff --git a/examples/Nano33BLEMegaSketch/Nano33BLEMegaSketch.ino b/examples/Nano33BLEMegaSketch/Nano33BLEMegaSketch.ino deleted file mode 100644 index 538e170..0000000 --- a/examples/Nano33BLEMegaSketch/Nano33BLEMegaSketch.ino +++ /dev/null @@ -1,14 +0,0 @@ -void setup() { - // put your setup code here, to run once: - Serial.begin(115200); - while (!Serial); - Serial.tags(); - Humidity.start(); - Gesture.start(); - Accelerometer.start(); -} - -void loop() { - // put your main code here, to run repeatedly: - -} diff --git a/examples/Nano33BLEMegaSketch/SharedVariables.h b/examples/Nano33BLEMegaSketch/SharedVariables.h deleted file mode 100644 index 8b13789..0000000 --- a/examples/Nano33BLEMegaSketch/SharedVariables.h +++ /dev/null @@ -1 +0,0 @@ - diff --git a/examples/SharedResources/SharedResources.ino b/examples/SharedResources/SharedResources.ino deleted file mode 100644 index 94dbbae..0000000 --- a/examples/SharedResources/SharedResources.ino +++ /dev/null @@ -1,35 +0,0 @@ -void setup() { - Serial.begin(115200); - while (!Serial); - - // Insert tags before Serial transmission to distinguish - // the thread that originated them - Serial.tags(true); - - temp_reader.start(); - pf_reader.start(); - scanner.start(); - ecc_reader.start(); -} - -void loop() { - //Serial.println(temperature); // blocks until new data is available - //Serial.println(temperature.peek()); // returns immediately the last known value - - struct i2cScanResults results = scanResults; - for (int i = 0; i < 128; i++) { - if (results.address[i] == true) { - Serial.println("0x" + String(i, HEX)); - } - } - - if (Serial.available()) { - Serial.println("Got something"); - while (Serial.available()) { - Serial.write(Serial.read()); - } - } - - Serial.println("PF1550 ID: " + String(pf1550_id, HEX)); - Serial.println("ECC608 ID: " + String(ecc608_id, HEX)); -} diff --git a/examples/SharedResources/SharedVariables.h b/examples/SharedResources/SharedVariables.h deleted file mode 100644 index 51b8363..0000000 --- a/examples/SharedResources/SharedVariables.h +++ /dev/null @@ -1,12 +0,0 @@ -// The preprocessor should enforce that all variables belonging here are declared Shared -// There's no risk to spill other variables around since they are all private members of the automatic class - -struct i2cScanResults { - uint8_t address[128]; -}; - -Shared temperature; - -Shared scanResults; -Shared pf1550_id; -Shared ecc608_id; diff --git a/examples/SharedResources/ecc_reader.inot b/examples/SharedResources/ecc_reader.inot deleted file mode 100644 index 4ec4317..0000000 --- a/examples/SharedResources/ecc_reader.inot +++ /dev/null @@ -1,15 +0,0 @@ -void setup() { - Wire.begin(); - Wire.setClock(100000); -} - -void loop() { - Wire.beginTransmission(0x60); - Wire.write((uint8_t)0x0); - Wire.endTransmission(false); - int res = Wire.requestFrom(0x60, 1); - delay(random() % 5); - if (res == 1) { - ecc608_id = Wire.read(); - } -} diff --git a/examples/SharedResources/pf_reader.inot b/examples/SharedResources/pf_reader.inot deleted file mode 100644 index f69c8b0..0000000 --- a/examples/SharedResources/pf_reader.inot +++ /dev/null @@ -1,21 +0,0 @@ -void setup() { - Serial.begin(115200); - Wire.begin(); - Wire.setClock(400000); -} - -void loop() { - Wire.beginTransmission(0x8); - Wire.write((uint8_t)0x0); - Wire.endTransmission(false); - Wire.requestFrom(0x8, 1); - delay(random() % 60); - pf1550_id = Wire.read(); - - if (Serial.available()) { - Serial.println("Got something"); - while (Serial.available()) { - Serial.write(Serial.read()); - } - } -} diff --git a/examples/SharedResources/scanner.inot b/examples/SharedResources/scanner.inot deleted file mode 100644 index 27b50aa..0000000 --- a/examples/SharedResources/scanner.inot +++ /dev/null @@ -1,14 +0,0 @@ -void setup() { - Wire.begin(); - Wire.setClock(100000); -} - -void loop() { - struct i2cScanResults results = {}; - for (int i = 0; i < 128; i++) { - Wire.beginTransmission (i); - results.address[i] = (Wire.endTransmission () == 0); - } - scanResults = results; - delay(random() % 1000); -} diff --git a/examples/SharedResources/temp_reader.inot b/examples/SharedResources/temp_reader.inot deleted file mode 100644 index 1d5aac9..0000000 --- a/examples/SharedResources/temp_reader.inot +++ /dev/null @@ -1,11 +0,0 @@ -// cannot include anything since we are going to be wrapped in a class -// the preprocessor should move the includes in another file - -void setup() { - //initialize -} - -void loop() { - temperature = random() * 1.0f; - delay(random() % 1000); -} diff --git a/examples/SharedResourcesVariousLibraries/Accelerometer.inot b/examples/SharedResourcesVariousLibraries/Accelerometer.inot deleted file mode 100644 index e0192e2..0000000 --- a/examples/SharedResourcesVariousLibraries/Accelerometer.inot +++ /dev/null @@ -1,58 +0,0 @@ -/* - Arduino LSM9DS1 - Simple Accelerometer - - This example reads the acceleration values from the LSM9DS1 - sensor and continuously prints them to the Serial Monitor - or Serial Plotter. - - The circuit: - - Arduino Nano 33 BLE Sense - - created 10 Jul 2019 - by Riccardo Rizzo - - This example code is in the public domain. -*/ - -#include - -LSM9DS1Class myIMU = LSM9DS1Class(Wire1); -// Note: classic -// LSM9DS1Class myIMU(Wire1); -// cannot be used here since it becomes a private member of the class. -// The compilation would fail with "error: 'Wire1' is not a type" (whatever this means) -// This only happen when we reinstantiate a singleton because we want to change something in its constructor - -void setup() { - Serial.begin(9600); - while (!Serial); - Serial.println("Started"); - - if (!myIMU.begin()) { - Serial.println("Failed to initialize IMU!"); - while (1) { - delay(1000); - } - } - - Serial.print("Accelerometer sample rate = "); - Serial.print(myIMU.accelerationSampleRate()); - Serial.println(" Hz"); - Serial.println(); - Serial.println("Acceleration in G's"); - Serial.println("X\tY\tZ"); -} - -void loop() { - float x, y, z; - - if (myIMU.accelerationAvailable()) { - myIMU.readAcceleration(x, y, z); - - Serial.print(x); - Serial.print('\t'); - Serial.print(y); - Serial.print('\t'); - Serial.println(z); - } -} diff --git a/examples/SharedResourcesVariousLibraries/GetRandom.inot b/examples/SharedResourcesVariousLibraries/GetRandom.inot deleted file mode 100644 index 421577c..0000000 --- a/examples/SharedResourcesVariousLibraries/GetRandom.inot +++ /dev/null @@ -1,18 +0,0 @@ -#include "ArduinoECCX08.h" - -void setup() { - int ret = ECCX08.begin(); - if (!ret) { - Serial.println("ECCX08 could not start"); - } -} - -int _randomNumber; - -void loop() { - randomNumber = ECCX08.random(65535); - // ATTENTION: if we write `delay(randomNumber % 60);` - // the call becomes blocking and it only gets read in the same thread - // so we have full starvation (two consumers) - delay(randomNumber.latest() % 60); -} diff --git a/examples/SharedResourcesVariousLibraries/SerialReader.inot b/examples/SharedResourcesVariousLibraries/SerialReader.inot deleted file mode 100644 index d13e7db..0000000 --- a/examples/SharedResourcesVariousLibraries/SerialReader.inot +++ /dev/null @@ -1,14 +0,0 @@ -#include "Wire.h" - -void setup() { - Serial.begin(115200); -} - -void loop() { - if (Serial.available()) { - Serial.println("Got something"); - while (Serial.available()) { - Serial.write(Serial.read()); - } - } -} diff --git a/examples/SharedResourcesVariousLibraries/SharedResourcesVariousLibraries.ino b/examples/SharedResourcesVariousLibraries/SharedResourcesVariousLibraries.ino deleted file mode 100644 index 339dd60..0000000 --- a/examples/SharedResourcesVariousLibraries/SharedResourcesVariousLibraries.ino +++ /dev/null @@ -1,31 +0,0 @@ -void setup() { - Serial.begin(115200); - while (!Serial); - - // Insert tags before Serial transmission to distinguish - // the thread that originated them - Serial.tags(true); - - // By declaring a serial "raw" we ask the dispatcher to flush - // every N milliseconds without waiting for EOL (for this thread only) - //Serial.raw(); - - TempReader.start(); - SerialReader.start(); - GetRandom.start(); - Accelerometer.start(); -} - -void loop() { - //Serial.println(temperature); // blocks until new data is available - Serial.println(temperature.peek()); // returns immediately the last known value - - if (Serial.available()) { - Serial.println("Got something"); - while (Serial.available()) { - Serial.write(Serial.read()); - } - } - - Serial.println("ECC608 random number: " + String(randomNumber)); -} diff --git a/examples/SharedResourcesVariousLibraries/SharedVariables.h b/examples/SharedResourcesVariousLibraries/SharedVariables.h deleted file mode 100644 index ca037c5..0000000 --- a/examples/SharedResourcesVariousLibraries/SharedVariables.h +++ /dev/null @@ -1,12 +0,0 @@ -// The preprocessor should enforce that all variables belonging here are declared Shared -// There's no risk to spill other variables around since they are all private members of the automatic class - -struct i2cScanResults { - uint8_t address[128]; -}; - -Shared temperature; - -Shared scanResults; -Shared pf1550_id; -Shared randomNumber; diff --git a/examples/SharedResourcesVariousLibraries/TempReader.inot b/examples/SharedResourcesVariousLibraries/TempReader.inot deleted file mode 100644 index ad21d03..0000000 --- a/examples/SharedResourcesVariousLibraries/TempReader.inot +++ /dev/null @@ -1,115 +0,0 @@ -#include - -// OneWire DS18S20, DS18B20, DS1822 Temperature Example -// -// http://www.pjrc.com/teensy/td_libs_OneWire.html -// -// The DallasTemperature library can do all this work for you! -// https://github.com/milesburton/Arduino-Temperature-Control-Library - -OneWire ds = OneWire(10); // on pin 10 (a 4.7K resistor is necessary) -// See note on Accelerometer.inot - -void setup(void) { - Serial.begin(9600); -} - -void loop(void) { - byte i; - byte present = 0; - byte type_s; - byte data[12]; - byte addr[8]; - float celsius, fahrenheit; - - if ( !ds.search(addr)) { - Serial.println("No more addresses."); - Serial.println(); - ds.reset_search(); - delay(250); - return; - } - - Serial.print("ROM ="); - for( i = 0; i < 8; i++) { - Serial.write(' '); - Serial.print(addr[i], HEX); - } - - if (OneWire::crc8(addr, 7) != addr[7]) { - Serial.println("CRC is not valid!"); - return; - } - Serial.println(); - - // the first ROM byte indicates which chip - switch (addr[0]) { - case 0x10: - Serial.println(" Chip = DS18S20"); // or old DS1820 - type_s = 1; - break; - case 0x28: - Serial.println(" Chip = DS18B20"); - type_s = 0; - break; - case 0x22: - Serial.println(" Chip = DS1822"); - type_s = 0; - break; - default: - Serial.println("Device is not a DS18x20 family device."); - return; - } - - ds.reset(); - ds.select(addr); - ds.write(0x44, 1); // start conversion, with parasite power on at the end - - delay(1000); // maybe 750ms is enough, maybe not - // we might do a ds.depower() here, but the reset will take care of it. - - present = ds.reset(); - ds.select(addr); - ds.write(0xBE); // Read Scratchpad - - Serial.print(" Data = "); - Serial.print(present, HEX); - Serial.print(" "); - for ( i = 0; i < 9; i++) { // we need 9 bytes - data[i] = ds.read(); - Serial.print(data[i], HEX); - Serial.print(" "); - } - Serial.print(" CRC="); - Serial.print(OneWire::crc8(data, 8), HEX); - Serial.println(); - - // Convert the data to actual temperature - // because the result is a 16 bit signed integer, it should - // be stored to an "int16_t" type, which is always 16 bits - // even when compiled on a 32 bit processor. - int16_t raw = (data[1] << 8) | data[0]; - if (type_s) { - raw = raw << 3; // 9 bit resolution default - if (data[7] == 0x10) { - // "count remain" gives full 12 bit resolution - raw = (raw & 0xFFF0) + 12 - data[6]; - } - } else { - byte cfg = (data[4] & 0x60); - // at lower res, the low bits are undefined, so let's zero them - if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms - else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms - else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms - //// default is 12 bit resolution, 750 ms conversion time - } - celsius = (float)raw / 16.0; - fahrenheit = celsius * 1.8 + 32.0; - Serial.print(" Temperature = "); - Serial.print(celsius); - Serial.print(" Celsius, "); - Serial.print(fahrenheit); - Serial.println(" Fahrenheit"); - - temperature = celsius; -} diff --git a/examples/i2c_concurrent/SharedVariables.h b/examples/i2c_concurrent/SharedVariables.h deleted file mode 100644 index 51b8363..0000000 --- a/examples/i2c_concurrent/SharedVariables.h +++ /dev/null @@ -1,12 +0,0 @@ -// The preprocessor should enforce that all variables belonging here are declared Shared -// There's no risk to spill other variables around since they are all private members of the automatic class - -struct i2cScanResults { - uint8_t address[128]; -}; - -Shared temperature; - -Shared scanResults; -Shared pf1550_id; -Shared ecc608_id; diff --git a/examples/i2c_concurrent/ecc_reader.inot b/examples/i2c_concurrent/ecc_reader.inot deleted file mode 100644 index 4ec4317..0000000 --- a/examples/i2c_concurrent/ecc_reader.inot +++ /dev/null @@ -1,15 +0,0 @@ -void setup() { - Wire.begin(); - Wire.setClock(100000); -} - -void loop() { - Wire.beginTransmission(0x60); - Wire.write((uint8_t)0x0); - Wire.endTransmission(false); - int res = Wire.requestFrom(0x60, 1); - delay(random() % 5); - if (res == 1) { - ecc608_id = Wire.read(); - } -} diff --git a/examples/i2c_concurrent/i2c_concurrent.ino b/examples/i2c_concurrent/i2c_concurrent.ino deleted file mode 100644 index 9e19675..0000000 --- a/examples/i2c_concurrent/i2c_concurrent.ino +++ /dev/null @@ -1,57 +0,0 @@ -#include "Wire.h" -#include "SerialDispatcher.h" - -/* this part should be autogenerated */ -/* -THD_ENTER(temp_reader) -#include "temp_reader.h" -THD_DONE(temp_reader) - -// A singleton called temp_reader_obj is automatically created but the user can still -// instantiate another with -// temp_reader_class myObj; - -THD_ENTER(pf_reader) -#include "pf_reader.h" -THD_DONE(pf_reader) - -THD_ENTER(ecc_reader) -#include "ecc_reader.h" -THD_DONE(ecc_reader) - -THD_ENTER(scanner) -#include "scanner.h" -THD_DONE(scanner) -*/ - -void setup() { - Serial.begin(115200); - while (!Serial); - Serial.tags(true); - temp_reader.start(); - pf_reader.start(); - scanner.start(); - ecc_reader.start(); -} - -void loop() { - //Serial.println(temperature); // blocks until new data is available - //Serial.println(temperature.peek()); // returns immediately the last known value - - struct i2cScanResults results = scanResults; - for (int i = 0; i < 128; i++) { - if (results.address[i] == true) { - Serial.println("0x" + String(i, HEX)); - } - } - - if (Serial.available()) { - Serial.println("Got something"); - while (Serial.available()) { - Serial.write(Serial.read()); - } - } - - Serial.println("PF1550 ID: " + String(pf1550_id, HEX)); - Serial.println("ECC608 ID: " + String(ecc608_id, HEX)); -} diff --git a/examples/i2c_concurrent/pf_reader.inot b/examples/i2c_concurrent/pf_reader.inot deleted file mode 100644 index 4a8ad80..0000000 --- a/examples/i2c_concurrent/pf_reader.inot +++ /dev/null @@ -1,23 +0,0 @@ -void setup() { - Serial.begin(115200); - Wire.begin(); - Wire.setClock(400000); -} - -void loop() { - Wire.beginTransmission(0x8); - Wire.write((uint8_t)0x0); - Wire.endTransmission(false); - Wire.requestFrom(0x8, 1); - delay(random() % 60); - pf1550_id = Wire.read(); - - Serial.println("I'm pfreader"); - - if (Serial.available()) { - Serial.println("Got something"); - while (Serial.available()) { - Serial.write(Serial.read()); - } - } -} diff --git a/examples/i2c_concurrent/scanner.inot b/examples/i2c_concurrent/scanner.inot deleted file mode 100644 index 27b50aa..0000000 --- a/examples/i2c_concurrent/scanner.inot +++ /dev/null @@ -1,14 +0,0 @@ -void setup() { - Wire.begin(); - Wire.setClock(100000); -} - -void loop() { - struct i2cScanResults results = {}; - for (int i = 0; i < 128; i++) { - Wire.beginTransmission (i); - results.address[i] = (Wire.endTransmission () == 0); - } - scanResults = results; - delay(random() % 1000); -} diff --git a/examples/i2c_concurrent/temp_reader.inot b/examples/i2c_concurrent/temp_reader.inot deleted file mode 100644 index 1d5aac9..0000000 --- a/examples/i2c_concurrent/temp_reader.inot +++ /dev/null @@ -1,11 +0,0 @@ -// cannot include anything since we are going to be wrapped in a class -// the preprocessor should move the includes in another file - -void setup() { - //initialize -} - -void loop() { - temperature = random() * 1.0f; - delay(random() % 1000); -} diff --git a/examples/i2c_concurrent/temp_reader_complete.inot b/examples/i2c_concurrent/temp_reader_complete.inot deleted file mode 100644 index bcf05e4..0000000 --- a/examples/i2c_concurrent/temp_reader_complete.inot +++ /dev/null @@ -1,27 +0,0 @@ -class temp_reader_class { - - Shared temperature; - void setup() { - //initialize - } - - void loop() { - temperature = random() * 1.0f; - delay(1000); - } - - void temp_reader_execute() { - setup(); - while (1) { - loop(); - } - } - - rtos::Thread t; - public: - void start() { - t.start(mbed::callback(this, &temp_reader_class::temp_reader_execute)); - } -}; - -temp_reader_class temp_reader_obj; From 044bb8f521f1e89b1da0793fa45fa961545f58c6 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 6 Oct 2021 10:55:23 +0200 Subject: [PATCH 03/37] Providing simple example of shared variable usage. --- examples/Shared/Consumer.inot | 7 +++++++ examples/Shared/Producer.inot | 10 ++++++++++ examples/Shared/Shared.ino | 11 +++++++++++ examples/Shared/SharedVariables.h | 1 + 4 files changed, 29 insertions(+) create mode 100644 examples/Shared/Consumer.inot create mode 100644 examples/Shared/Producer.inot create mode 100644 examples/Shared/Shared.ino create mode 100644 examples/Shared/SharedVariables.h diff --git a/examples/Shared/Consumer.inot b/examples/Shared/Consumer.inot new file mode 100644 index 0000000..9d2d190 --- /dev/null +++ b/examples/Shared/Consumer.inot @@ -0,0 +1,7 @@ +void setup() { + +} + +void loop() { + Serial.println(counter); +} diff --git a/examples/Shared/Producer.inot b/examples/Shared/Producer.inot new file mode 100644 index 0000000..8932873 --- /dev/null +++ b/examples/Shared/Producer.inot @@ -0,0 +1,10 @@ +void setup() { + +} + +void loop() { + static int i = 0; + counter = i; + i++; + delay(100); +} diff --git a/examples/Shared/Shared.ino b/examples/Shared/Shared.ino new file mode 100644 index 0000000..8820b15 --- /dev/null +++ b/examples/Shared/Shared.ino @@ -0,0 +1,11 @@ +void setup() { + Serial.begin(115200); + while (!Serial) { } + + Producer.start(); + Consumer.start(); +} + +void loop() { + rtos::ThisThread::yield(); +} diff --git a/examples/Shared/SharedVariables.h b/examples/Shared/SharedVariables.h new file mode 100644 index 0000000..51ea60e --- /dev/null +++ b/examples/Shared/SharedVariables.h @@ -0,0 +1 @@ +Shared counter; From 900d8d780970ef248e54b2d756ae720bdf4db92c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 6 Oct 2021 10:59:19 +0200 Subject: [PATCH 04/37] Rename Shared to Demo_Shared --- examples/{Shared => Demo_Shared}/Consumer.inot | 0 examples/{Shared/Shared.ino => Demo_Shared/Demo_Shared.ino} | 0 examples/{Shared => Demo_Shared}/Producer.inot | 0 examples/{Shared => Demo_Shared}/SharedVariables.h | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename examples/{Shared => Demo_Shared}/Consumer.inot (100%) rename examples/{Shared/Shared.ino => Demo_Shared/Demo_Shared.ino} (100%) rename examples/{Shared => Demo_Shared}/Producer.inot (100%) rename examples/{Shared => Demo_Shared}/SharedVariables.h (100%) diff --git a/examples/Shared/Consumer.inot b/examples/Demo_Shared/Consumer.inot similarity index 100% rename from examples/Shared/Consumer.inot rename to examples/Demo_Shared/Consumer.inot diff --git a/examples/Shared/Shared.ino b/examples/Demo_Shared/Demo_Shared.ino similarity index 100% rename from examples/Shared/Shared.ino rename to examples/Demo_Shared/Demo_Shared.ino diff --git a/examples/Shared/Producer.inot b/examples/Demo_Shared/Producer.inot similarity index 100% rename from examples/Shared/Producer.inot rename to examples/Demo_Shared/Producer.inot diff --git a/examples/Shared/SharedVariables.h b/examples/Demo_Shared/SharedVariables.h similarity index 100% rename from examples/Shared/SharedVariables.h rename to examples/Demo_Shared/SharedVariables.h From dd5ee85b08101385ab8d28fe939575e6feb2c338 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Wed, 6 Oct 2021 10:59:38 +0200 Subject: [PATCH 05/37] Replace Blocks demo with Demo_Source_Sink --- examples/Blocks/Blocks.ino | 22 ------------------- examples/Blocks/data_reader.inot | 12 ---------- examples/Blocks/data_writer.inot | 21 ------------------ .../Demo_Source_Sink/Demo_Source_Sink.ino | 15 +++++++++++++ .../SharedVariables.h | 0 examples/Demo_Source_Sink/Sink_Thread.inot | 21 ++++++++++++++++++ examples/Demo_Source_Sink/Source_Thread.inot | 15 +++++++++++++ 7 files changed, 51 insertions(+), 55 deletions(-) delete mode 100644 examples/Blocks/Blocks.ino delete mode 100644 examples/Blocks/data_reader.inot delete mode 100644 examples/Blocks/data_writer.inot create mode 100644 examples/Demo_Source_Sink/Demo_Source_Sink.ino rename examples/{Blocks => Demo_Source_Sink}/SharedVariables.h (100%) create mode 100644 examples/Demo_Source_Sink/Sink_Thread.inot create mode 100644 examples/Demo_Source_Sink/Source_Thread.inot diff --git a/examples/Blocks/Blocks.ino b/examples/Blocks/Blocks.ino deleted file mode 100644 index 85efc0b..0000000 --- a/examples/Blocks/Blocks.ino +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This examples demonstrates the SOURCE/SINK abstraction. - * Each thread may have any number of SOURCES and SINKS that can be connected - * together using the "connectTo" method. - */ - -void setup() { - data_reader.out.connectTo(data_writer.in); - data_reader.start(); - data_writer.start(); - - // put your setup code here, to run once: - pinMode(LEDR, OUTPUT); -} - -void loop() { - // put your main code here, to run repeatedly: - digitalWrite(LEDR, HIGH); - delay(1000); - digitalWrite(LEDR, LOW); - delay(1000); -} diff --git a/examples/Blocks/data_reader.inot b/examples/Blocks/data_reader.inot deleted file mode 100644 index 6bd9708..0000000 --- a/examples/Blocks/data_reader.inot +++ /dev/null @@ -1,12 +0,0 @@ - -/* The output SOURCE, it sends 'int' */ -SOURCE(out, int) - -void setup() { -} - -// a '1' is sent every 100 ms -void loop() { - out.send(1); - delay(100); -} diff --git a/examples/Blocks/data_writer.inot b/examples/Blocks/data_writer.inot deleted file mode 100644 index d3e0e70..0000000 --- a/examples/Blocks/data_writer.inot +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * An 'int' SINK with a size of '0'. This kind of SINK has no buffer so the reading thread - * will block until the writing thread has written something, or vice versa. - */ -SINK(in, int, 0) - -void setup() { - pinMode(LEDB, OUTPUT); -} - -void loop() { - // Read an 'int' from the SINK and discard it. Since there is basically no delay in the loop - // this call will surely block until something comes from the connected SOURCE. In this case - // the pace is dictated by the SOURCE that sends data every 100 ms. - in.read(); - digitalWrite(LEDB, HIGH); - - in.read(); - digitalWrite(LEDB, LOW); -} diff --git a/examples/Demo_Source_Sink/Demo_Source_Sink.ino b/examples/Demo_Source_Sink/Demo_Source_Sink.ino new file mode 100644 index 0000000..d3007b3 --- /dev/null +++ b/examples/Demo_Source_Sink/Demo_Source_Sink.ino @@ -0,0 +1,15 @@ +/* + * This examples demonstrates the SOURCE/SINK abstraction. + * Each thread may have any number of SOURCES and SINKS that can be connected + * together using the "connectTo" method. + */ + +void setup() { + Source_Thread.led.connectTo(Sink_Thread.led); + Sink_Thread.start(); + Source_Thread.start(); +} + +void loop() { + rtos::ThisThread::yield(); +} diff --git a/examples/Blocks/SharedVariables.h b/examples/Demo_Source_Sink/SharedVariables.h similarity index 100% rename from examples/Blocks/SharedVariables.h rename to examples/Demo_Source_Sink/SharedVariables.h diff --git a/examples/Demo_Source_Sink/Sink_Thread.inot b/examples/Demo_Source_Sink/Sink_Thread.inot new file mode 100644 index 0000000..0bc87c6 --- /dev/null +++ b/examples/Demo_Source_Sink/Sink_Thread.inot @@ -0,0 +1,21 @@ + +/* + * An 'bool' SINK with a size of '0'. This kind of SINK has no buffer so the reading thread + * will block until the writing thread has written something, or vice versa. + */ +SINK(led, bool, 0) + +void setup() +{ + pinMode(LED_BUILTIN, OUTPUT); +} + +void loop() +{ + /* Read a 'bool' from the SINK and discard it. Since there is basically no delay in the loop + * this call will surely block until something comes from the connected SOURCE. In this case + * the pace is dictated by the SOURCE that sends data every 100 ms. + */ + bool led_on = led.read(); + digitalWrite(LED_BUILTIN, led_on); +} diff --git a/examples/Demo_Source_Sink/Source_Thread.inot b/examples/Demo_Source_Sink/Source_Thread.inot new file mode 100644 index 0000000..302a2c8 --- /dev/null +++ b/examples/Demo_Source_Sink/Source_Thread.inot @@ -0,0 +1,15 @@ +/* The output SOURCE, it sends 'bool' values. */ +SOURCE(led, bool) + +void setup() +{ + +} + +void loop() +{ + led.send(true); + delay(100); + led.send(false); + delay(100); +} From 9cb1c58b09d4cf69026bef20c5cf8eca36d596db Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 06:38:33 +0200 Subject: [PATCH 06/37] Extract implementation of 'Sink' into a separate file. --- src/Arduino_Threads.h | 134 ++++++------------------------------------ src/Sink.hpp | 131 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 117 deletions(-) create mode 100644 src/Sink.hpp diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 2684e3e..03856f1 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -1,9 +1,19 @@ #ifndef ARDUINO_THREADS_H_ #define ARDUINO_THREADS_H_ +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + #include #include +#include "Sink.hpp" + +/************************************************************************************** + * DEFINE + **************************************************************************************/ + #define SOURCE(name, type) \ public: \ Source name; \ @@ -23,128 +33,18 @@ public: \ // This is called "C++11 uniform init" (using "{}" instead of "()" without "="... yikes!) // https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++-dos-and-donts.md -// Forward declaration of Sink and Source +/************************************************************************************** + * FORWARD DECLARATION + **************************************************************************************/ + template class Sink; template class Source; -template -class Sink -{ - private: - rtos::Mutex dataMutex; - rtos::ConditionVariable dataAvailable; - rtos::ConditionVariable slotAvailable; - T latest; - Sink *next; - const int size; - int first, last; - bool full; - T *queue; - - public: - Sink(int s) : - dataAvailable(dataMutex), - slotAvailable(dataMutex), - size(s), - queue((size > 0) ? new T[size] : nullptr), - first(0), last(0), full(false) - {}; - - ~Sink() { - if (queue != nullptr) { delete queue; } - } - - - //protected: TODO - void connectTo(Sink &sink) - { - if (next == nullptr) { - next = &sink; - } else { - next->connectTo(sink); - } - } - - T read() - { - // Non-blocking shared variable - if (size == -1) { - dataMutex.lock(); - T res = latest; - dataMutex.unlock(); - return res; - } - - // Blocking shared variable - if (size == 0) { - dataMutex.lock(); - while (!full) { - dataAvailable.wait(); - } - T res = latest; - full = false; - slotAvailable.notify_all(); - dataMutex.unlock(); - return res; - } - - // Blocking queue - dataMutex.lock(); - while (first == last && !full) { - dataAvailable.wait(); - } - T res = queue[first++]; - first %= size; - if (full) { - full = false; - slotAvailable.notify_one(); - } - dataMutex.unlock(); - return res; - } - - //protected: TODO - void inject(const T &value) - { - dataMutex.lock(); - - // Non-blocking shared variable - if (size == -1) { - latest = value; - } - - // Blocking shared variable - else if (size == 0) { - while (full) { - slotAvailable.wait(); - } - latest = value; - full = true; - dataAvailable.notify_one(); - slotAvailable.wait(); - } - - // Blocking queue - else { - while (full) { - slotAvailable.wait(); - } - if (first == last) { - dataAvailable.notify_one(); - } - queue[last++] = value; - last %= size; - if (first == last) { - full = true; - } - } - dataMutex.unlock(); - - if (next) next->inject(value); - } -}; +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ template class Source diff --git a/src/Sink.hpp b/src/Sink.hpp new file mode 100644 index 0000000..97b3604 --- /dev/null +++ b/src/Sink.hpp @@ -0,0 +1,131 @@ +#ifndef ARDUINO_THREADS_SINK_HPP_ +#define ARDUINO_THREADS_SINK_HPP_ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +template +class Sink +{ + private: + rtos::Mutex dataMutex; + rtos::ConditionVariable dataAvailable; + rtos::ConditionVariable slotAvailable; + T latest; + Sink *next; + const int size; + int first, last; + bool full; + T *queue; + + public: + Sink(int s) : + dataAvailable(dataMutex), + slotAvailable(dataMutex), + size(s), + queue((size > 0) ? new T[size] : nullptr), + first(0), last(0), full(false) + {}; + + ~Sink() { + if (queue != nullptr) { delete queue; } + } + + + //protected: TODO + void connectTo(Sink &sink) + { + if (next == nullptr) { + next = &sink; + } else { + next->connectTo(sink); + } + } + + T read() + { + // Non-blocking shared variable + if (size == -1) { + dataMutex.lock(); + T res = latest; + dataMutex.unlock(); + return res; + } + + // Blocking shared variable + if (size == 0) { + dataMutex.lock(); + while (!full) { + dataAvailable.wait(); + } + T res = latest; + full = false; + slotAvailable.notify_all(); + dataMutex.unlock(); + return res; + } + + // Blocking queue + dataMutex.lock(); + while (first == last && !full) { + dataAvailable.wait(); + } + T res = queue[first++]; + first %= size; + if (full) { + full = false; + slotAvailable.notify_one(); + } + dataMutex.unlock(); + return res; + } + + //protected: TODO + void inject(const T &value) + { + dataMutex.lock(); + + // Non-blocking shared variable + if (size == -1) { + latest = value; + } + + // Blocking shared variable + else if (size == 0) { + while (full) { + slotAvailable.wait(); + } + latest = value; + full = true; + dataAvailable.notify_one(); + slotAvailable.wait(); + } + + // Blocking queue + else { + while (full) { + slotAvailable.wait(); + } + if (first == last) { + dataAvailable.notify_one(); + } + queue[last++] = value; + last %= size; + if (first == last) { + full = true; + } + } + dataMutex.unlock(); + + if (next) next->inject(value); + } +}; + +#endif /* ARDUINO_THREADS_SINK_HPP_ */ From a0d01a32564832e539b07158d5d80cce355b0b1a Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 06:41:16 +0200 Subject: [PATCH 07/37] Extract implementation of 'Source' into a separate file. --- src/Arduino_Threads.h | 32 +------------------------------- src/Source.hpp | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 31 deletions(-) create mode 100644 src/Source.hpp diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 03856f1..837ffa4 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -9,6 +9,7 @@ #include #include "Sink.hpp" +#include "Source.hpp" /************************************************************************************** * DEFINE @@ -33,41 +34,10 @@ public: \ // This is called "C++11 uniform init" (using "{}" instead of "()" without "="... yikes!) // https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++-dos-and-donts.md -/************************************************************************************** - * FORWARD DECLARATION - **************************************************************************************/ - -template -class Sink; -template -class Source; - /************************************************************************************** * CLASS DECLARATION **************************************************************************************/ -template -class Source -{ - public: - Source() {}; - - void connectTo(Sink &sink) { - if (destination == nullptr) { - destination = &sink; - } else { - destination->connectTo(sink); - } - } - - void send(const T &value) { - if (destination) destination->inject(value); - } - - private: - Sink *destination; -}; - template class Shared // template definition { diff --git a/src/Source.hpp b/src/Source.hpp new file mode 100644 index 0000000..e3b91ed --- /dev/null +++ b/src/Source.hpp @@ -0,0 +1,37 @@ +#ifndef ARDUINO_THREADS_SOURCE_HPP_ +#define ARDUINO_THREADS_SOURCE_HPP_ + +/************************************************************************************** + * FORWARD DECLARATION + **************************************************************************************/ + +template +class Sink; + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +template +class Source +{ + public: + Source() {}; + + void connectTo(Sink &sink) { + if (destination == nullptr) { + destination = &sink; + } else { + destination->connectTo(sink); + } + } + + void send(const T &value) { + if (destination) destination->inject(value); + } + + private: + Sink *destination; +}; + +#endif /* ARDUINO_THREADS_SOURCE_HPP_ */ From 30e238480b22e293113c8b7ae91e967107d81a23 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 06:44:10 +0200 Subject: [PATCH 08/37] Extract implementation of 'Shared' into a separate file. --- src/Arduino_Threads.h | 49 +--------------------------------- src/Shared.hpp | 62 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 48 deletions(-) create mode 100644 src/Shared.hpp diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 837ffa4..f2baa39 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -6,10 +6,10 @@ **************************************************************************************/ #include -#include #include "Sink.hpp" #include "Source.hpp" +#include "Shared.hpp" /************************************************************************************** * DEFINE @@ -38,53 +38,6 @@ public: \ * CLASS DECLARATION **************************************************************************************/ -template -class Shared // template definition -{ - public: - Shared() { - } - operator T() { - osEvent evt = queue.get(); - if (evt.status == osEventMessage) { - /* Obtain the oldest inserted element from the queue. */ - T * val_ptr = reinterpret_cast(evt.value.p); - /* Copy the content of T stored in the memory pool since we'll have to free the memory pool afterwards. */ - T const tmp_val = *val_ptr; - /* Free the allocated memory in the memory pool. */ - memory_pool.free(val_ptr); - /* Return obtained value from queue. */ - return tmp_val; - } - return val; - } - T& operator= (const T& other) { - if (queue.full()) { - // invokes operator T() to discard oldest element and free its memory - T discard = *this; - } - val = other; - /* Allocate memory in the memory pool. */ - T * val_ptr = memory_pool.alloc(); - /* Copy the content of 'other' into the freshly allocated message. */ - *val_ptr = other; - /* Insert into queue. */ - queue.put(val_ptr); - return (*val_ptr); - } - T& peek() { - return val; - } - T& latest() { - return peek(); - } - private: - - T val; - rtos::MemoryPool memory_pool; - rtos::Queue queue; -}; - #define CONCAT2(x,y) x##y #define CONCAT(x,y) CONCAT2(x,y) diff --git a/src/Shared.hpp b/src/Shared.hpp new file mode 100644 index 0000000..e2e07b0 --- /dev/null +++ b/src/Shared.hpp @@ -0,0 +1,62 @@ +#ifndef ARDUINO_THREADS_SHARED_HPP_ +#define ARDUINO_THREADS_SHARED_HPP_ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include +#include + +/************************************************************************************** + * CLASS DECLARATION + **************************************************************************************/ + +template +class Shared // template definition +{ + public: + Shared() { + } + operator T() { + osEvent evt = queue.get(); + if (evt.status == osEventMessage) { + /* Obtain the oldest inserted element from the queue. */ + T * val_ptr = reinterpret_cast(evt.value.p); + /* Copy the content of T stored in the memory pool since we'll have to free the memory pool afterwards. */ + T const tmp_val = *val_ptr; + /* Free the allocated memory in the memory pool. */ + memory_pool.free(val_ptr); + /* Return obtained value from queue. */ + return tmp_val; + } + return val; + } + T& operator= (const T& other) { + if (queue.full()) { + // invokes operator T() to discard oldest element and free its memory + T discard = *this; + } + val = other; + /* Allocate memory in the memory pool. */ + T * val_ptr = memory_pool.alloc(); + /* Copy the content of 'other' into the freshly allocated message. */ + *val_ptr = other; + /* Insert into queue. */ + queue.put(val_ptr); + return (*val_ptr); + } + T& peek() { + return val; + } + T& latest() { + return peek(); + } + private: + + T val; + rtos::MemoryPool memory_pool; + rtos::Queue queue; +}; + +#endif /* ARDUINO_THREADS_SHARED_HPP_ */ From 68d0a8aa9a1eff2cdb56c51a2e3deb8671d9fd13 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 07:18:59 +0200 Subject: [PATCH 09/37] Extract static member definition into dedicated cpp file. --- src/Arduino_Threads.cpp | 11 +++++++++++ src/Arduino_Threads.h | 3 --- 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/Arduino_Threads.cpp diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp new file mode 100644 index 0000000..c0ece69 --- /dev/null +++ b/src/Arduino_Threads.cpp @@ -0,0 +1,11 @@ +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include "Arduino_Threads.h" + +/************************************************************************************** + * STATIC MEMBER DECLARATION + **************************************************************************************/ + +rtos::EventFlags ArduinoThreads::globalEvents; diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index f2baa39..1efb3cb 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -46,7 +46,6 @@ public: \ #define _macroToString(sequence) #sequence - class ArduinoThreads { private: static rtos::EventFlags globalEvents; @@ -118,8 +117,6 @@ class ArduinoThreads { } }; -rtos::EventFlags ArduinoThreads::globalEvents; - #define THD_ENTER(tabname) class CONCAT(tabname, Class) : public ArduinoThreads { \ public: \ CONCAT(tabname, Class)() { _tabname = _macroToString(tabname); } \ From 619fa4b0b5351f25666849549254ab7ee746d630 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 07:22:13 +0200 Subject: [PATCH 10/37] Prefix member variables with '_' --- src/Arduino_Threads.cpp | 2 +- src/Arduino_Threads.h | 40 ++++++++++++++++++++-------------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index c0ece69..3a43462 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -8,4 +8,4 @@ * STATIC MEMBER DECLARATION **************************************************************************************/ -rtos::EventFlags ArduinoThreads::globalEvents; +rtos::EventFlags ArduinoThreads::_global_events; diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 1efb3cb..ad21329 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -48,22 +48,22 @@ public: \ class ArduinoThreads { private: - static rtos::EventFlags globalEvents; - uint32_t startFlags; - uint32_t stopFlags; - uint32_t loopDelay; + static rtos::EventFlags _global_events; + uint32_t _start_flags; + uint32_t _stop_flags; + uint32_t _loop_delay; virtual void setup(void) {}; virtual void loop(void) {}; void execute() { setup(); - // if startFlags have been passed then wait until all the flags are set + // if _start_flags have been passed then wait until all the flags are set // before starting the loop. this is used to synchronize loops from multiple // sketches. - if (startFlags != 0) { - globalEvents.wait_all(startFlags); + if (_start_flags != 0) { + _global_events.wait_all(_start_flags); } - // if stopFlags have been passed stop when all the flags are set + // if _stop_flags have been passed stop when all the flags are set // otherwise loop forever while ( 1 ) { loop(); @@ -71,18 +71,18 @@ class ArduinoThreads { // note that if two groups of sketches stop on common flags // the first group will clear them so the second group may never // exit - if (stopFlags!=0) { - if ((globalEvents.get()&stopFlags)!=stopFlags) { - globalEvents.clear(stopFlags); + if (_stop_flags!=0) { + if ((_global_events.get()&_stop_flags)!=_stop_flags) { + _global_events.clear(_stop_flags); return; } - if ((rtos::ThisThread::flags_get()&stopFlags)!=stopFlags) { - rtos::ThisThread::flags_clear(stopFlags); + if ((rtos::ThisThread::flags_get()&_stop_flags)!=_stop_flags) { + rtos::ThisThread::flags_clear(_stop_flags); return; } } // sleep for the time we've been asked to insert between loops - rtos::ThisThread::sleep_for(loopDelay); + rtos::ThisThread::sleep_for(_loop_delay); } } rtos::Thread *t; @@ -92,10 +92,10 @@ class ArduinoThreads { public: // start this sketch - void start(int stacksize = 4096, uint32_t startFlags=0, uint32_t stopFlags=0) { - this->startFlags = startFlags; - this->stopFlags = stopFlags; - loopDelay=0; + void start(int stacksize = 4096, uint32_t _start_flags=0, uint32_t _stop_flags=0) { + this->_start_flags = _start_flags; + this->_stop_flags = _stop_flags; + _loop_delay=0; t = new rtos::Thread(osPriorityNormal, stacksize, nullptr, _tabname); t->start(mbed::callback(this, &ArduinoThreads::execute)); } @@ -105,7 +105,7 @@ class ArduinoThreads { } // send an event to all sketches at the same time static void broadcastEvent(uint32_t event) { - globalEvents.set(event); + _global_events.set(event); } // send an event only to this sketch void sendEvent(uint32_t event) { @@ -113,7 +113,7 @@ class ArduinoThreads { } // set the rate at which loop function will be called void setLoopDelay(uint32_t delay) { - loopDelay = delay; + _loop_delay = delay; } }; From c5627506b4ce03f674b7d4b65c10d223bbc00d72 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 07:26:06 +0200 Subject: [PATCH 11/37] Extract private member function 'execute' into cpp file. --- src/Arduino_Threads.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ src/Arduino_Threads.h | 32 +--------------------------- 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index 3a43462..9db2da7 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -9,3 +9,49 @@ **************************************************************************************/ rtos::EventFlags ArduinoThreads::_global_events; + +/************************************************************************************** + * PRIVATE MEMBER FUNCTIONS + **************************************************************************************/ + +void ArduinoThreads::execute() +{ + setup(); + /* If _start_flags have been passed then wait until all the flags are set + * before starting the loop. this is used to synchronize loops from multiple + * sketches. + */ + if (_start_flags != 0) + _global_events.wait_all(_start_flags); + + /* if _stop_flags have been passed stop when all the flags are set + * otherwise loop forever + */ + for (;;) + { + loop(); + /* On exit clear the flags that have forced us to stop. + * note that if two groups of sketches stop on common flags + * the first group will clear them so the second group may never + * exit. + */ + if (_stop_flags!=0) + { + if ((_global_events.get() & _stop_flags) != _stop_flags) + { + _global_events.clear(_stop_flags); + return; + } + + if ((rtos::ThisThread::flags_get() & _stop_flags) != _stop_flags) + { + rtos::ThisThread::flags_clear(_stop_flags); + return; + } + } + + /* Sleep for the time we've been asked to insert between loops. + */ + rtos::ThisThread::sleep_for(_loop_delay); + } +} diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index ad21329..f8c668e 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -54,37 +54,7 @@ class ArduinoThreads { uint32_t _loop_delay; virtual void setup(void) {}; virtual void loop(void) {}; - void execute() { - setup(); - // if _start_flags have been passed then wait until all the flags are set - // before starting the loop. this is used to synchronize loops from multiple - // sketches. - if (_start_flags != 0) { - _global_events.wait_all(_start_flags); - } - - // if _stop_flags have been passed stop when all the flags are set - // otherwise loop forever - while ( 1 ) { - loop(); - // on exit clear the flags that have forced us to stop. - // note that if two groups of sketches stop on common flags - // the first group will clear them so the second group may never - // exit - if (_stop_flags!=0) { - if ((_global_events.get()&_stop_flags)!=_stop_flags) { - _global_events.clear(_stop_flags); - return; - } - if ((rtos::ThisThread::flags_get()&_stop_flags)!=_stop_flags) { - rtos::ThisThread::flags_clear(_stop_flags); - return; - } - } - // sleep for the time we've been asked to insert between loops - rtos::ThisThread::sleep_for(_loop_delay); - } - } + void execute(); rtos::Thread *t; protected: From dae21a6b79cd9f0259579fd97e0d2313d8cc85bc Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 08:51:50 +0200 Subject: [PATCH 12/37] Extract public Arduino_Threads member function implementation into cpp file. --- src/Arduino_Threads.cpp | 33 +++++++++++++++++++++++++++++++++ src/Arduino_Threads.h | 36 +++++++++++------------------------- 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index 9db2da7..1af5bb3 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -10,6 +10,39 @@ rtos::EventFlags ArduinoThreads::_global_events; +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +void ArduinoThreads::start(int const stack_size, uint32_t const start_flags, uint32_t const stop_flags) +{ + _start_flags = start_flags; + _stop_flags = stop_flags; + _loop_delay = 0; + t = new rtos::Thread(osPriorityNormal, stack_size, nullptr, _tabname); + t->start(mbed::callback(this, &ArduinoThreads::execute)); +} + +void ArduinoThreads::terminate() +{ + t->terminate(); +} + +void ArduinoThreads::sendEvent(uint32_t const event) +{ + t->flags_set(event); +} + +void ArduinoThreads::setLoopDelay(uint32_t const delay) +{ + _loop_delay = delay; +} + +void ArduinoThreads::broadcastEvent(uint32_t const event) +{ + _global_events.set(event); +} + /************************************************************************************** * PRIVATE MEMBER FUNCTIONS **************************************************************************************/ diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index f8c668e..8ac523b 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -46,7 +46,8 @@ public: \ #define _macroToString(sequence) #sequence -class ArduinoThreads { +class ArduinoThreads +{ private: static rtos::EventFlags _global_events; uint32_t _start_flags; @@ -58,33 +59,18 @@ class ArduinoThreads { rtos::Thread *t; protected: + char* _tabname; public: - // start this sketch - void start(int stacksize = 4096, uint32_t _start_flags=0, uint32_t _stop_flags=0) { - this->_start_flags = _start_flags; - this->_stop_flags = _stop_flags; - _loop_delay=0; - t = new rtos::Thread(osPriorityNormal, stacksize, nullptr, _tabname); - t->start(mbed::callback(this, &ArduinoThreads::execute)); - } - // kill this sketch - void terminate() { - t->terminate(); - } - // send an event to all sketches at the same time - static void broadcastEvent(uint32_t event) { - _global_events.set(event); - } - // send an event only to this sketch - void sendEvent(uint32_t event) { - t->flags_set(event); - } - // set the rate at which loop function will be called - void setLoopDelay(uint32_t delay) { - _loop_delay = delay; - } + + void start(int const stack_size = 4096, uint32_t const start_flags = 0, uint32_t const stop_flags = 0); + void terminate(); + void setLoopDelay(uint32_t const delay); + void sendEvent(uint32_t const event); + + static void broadcastEvent(uint32_t event); + }; #define THD_ENTER(tabname) class CONCAT(tabname, Class) : public ArduinoThreads { \ From 37301304cd20ddfd3e66bdd07e7bab38d282d950 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 08:54:49 +0200 Subject: [PATCH 13/37] Rearrange function definition for better overview. --- src/Arduino_Threads.h | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 8ac523b..8b62b2c 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -48,29 +48,32 @@ public: \ class ArduinoThreads { - private: - static rtos::EventFlags _global_events; - uint32_t _start_flags; - uint32_t _stop_flags; - uint32_t _loop_delay; - virtual void setup(void) {}; - virtual void loop(void) {}; - void execute(); - rtos::Thread *t; +public: - protected: + void start (int const stack_size = 4096, uint32_t const start_flags = 0, uint32_t const stop_flags = 0); + void terminate (); + void setLoopDelay(uint32_t const delay); + void sendEvent (uint32_t const event); - char* _tabname; + static void broadcastEvent(uint32_t event); - public: - void start(int const stack_size = 4096, uint32_t const start_flags = 0, uint32_t const stop_flags = 0); - void terminate(); - void setLoopDelay(uint32_t const delay); - void sendEvent(uint32_t const event); +protected: - static void broadcastEvent(uint32_t event); + char * _tabname; + +private: + + static rtos::EventFlags _global_events; + rtos::Thread *t; + uint32_t _start_flags, _stop_flags; + uint32_t _loop_delay; + + virtual void setup(void) {}; + virtual void loop(void) {}; + + void execute(); }; #define THD_ENTER(tabname) class CONCAT(tabname, Class) : public ArduinoThreads { \ From c0583ed4feb6bde4832ad3bceefeaac608cdb30d Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 08:57:59 +0200 Subject: [PATCH 14/37] Turn setup/loop into pure virtual functions, thereby turning ArduinoThreads into an abstract class, preventing accidential instantiation. --- src/Arduino_Threads.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 8b62b2c..51b35bb 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -62,6 +62,8 @@ class ArduinoThreads char * _tabname; + virtual void setup() = 0; + virtual void loop () = 0; private: @@ -70,9 +72,6 @@ class ArduinoThreads uint32_t _start_flags, _stop_flags; uint32_t _loop_delay; - virtual void setup(void) {}; - virtual void loop(void) {}; - void execute(); }; From 60670405c417726193209e68213f87423685965b Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 08:59:28 +0200 Subject: [PATCH 15/37] A class with virtual functions needs a virtual destructor. --- src/Arduino_Threads.cpp | 9 +++++++++ src/Arduino_Threads.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index 1af5bb3..a20e3a4 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -10,6 +10,15 @@ rtos::EventFlags ArduinoThreads::_global_events; +/************************************************************************************** + * CTOR/DTOR + **************************************************************************************/ + +ArduinoThreads::~ArduinoThreads() +{ + terminate(); +} + /************************************************************************************** * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 51b35bb..4d11cd0 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -50,6 +50,9 @@ class ArduinoThreads { public: + virtual ~ArduinoThreads(); + + void start (int const stack_size = 4096, uint32_t const start_flags = 0, uint32_t const stop_flags = 0); void terminate (); void setLoopDelay(uint32_t const delay); From 207b4fc5645f44e34804373546c6b68631fd358f Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 09:01:21 +0200 Subject: [PATCH 16/37] When terminating a thread, wait for the thread to join before deallocating the class. --- src/Arduino_Threads.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index a20e3a4..2731546 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -35,6 +35,7 @@ void ArduinoThreads::start(int const stack_size, uint32_t const start_flags, uin void ArduinoThreads::terminate() { t->terminate(); + t->join(); } void ArduinoThreads::sendEvent(uint32_t const event) From ce77408b4d04f0bea86254e6d6eca07537c99c3a Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 09:02:19 +0200 Subject: [PATCH 17/37] Rename 'execute' to 'threadFunc' --- src/Arduino_Threads.cpp | 4 ++-- src/Arduino_Threads.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index 2731546..8221a53 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -29,7 +29,7 @@ void ArduinoThreads::start(int const stack_size, uint32_t const start_flags, uin _stop_flags = stop_flags; _loop_delay = 0; t = new rtos::Thread(osPriorityNormal, stack_size, nullptr, _tabname); - t->start(mbed::callback(this, &ArduinoThreads::execute)); + t->start(mbed::callback(this, &ArduinoThreads::threadFunc)); } void ArduinoThreads::terminate() @@ -57,7 +57,7 @@ void ArduinoThreads::broadcastEvent(uint32_t const event) * PRIVATE MEMBER FUNCTIONS **************************************************************************************/ -void ArduinoThreads::execute() +void ArduinoThreads::threadFunc() { setup(); /* If _start_flags have been passed then wait until all the flags are set diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 4d11cd0..36960b4 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -75,7 +75,7 @@ class ArduinoThreads uint32_t _start_flags, _stop_flags; uint32_t _loop_delay; - void execute(); + void threadFunc(); }; #define THD_ENTER(tabname) class CONCAT(tabname, Class) : public ArduinoThreads { \ From 2d9ef0fd9b80b618345bd84917c58d173e177ad6 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 09:06:36 +0200 Subject: [PATCH 18/37] Providing a default ctor for initializing member variables. --- src/Arduino_Threads.cpp | 9 ++++++++- src/Arduino_Threads.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index 8221a53..cfe7361 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -14,6 +14,14 @@ rtos::EventFlags ArduinoThreads::_global_events; * CTOR/DTOR **************************************************************************************/ +ArduinoThreads::ArduinoThreads() +: _start_flags{0} +, _stop_flags{0} +, _loop_delay{0} +{ + +} + ArduinoThreads::~ArduinoThreads() { terminate(); @@ -27,7 +35,6 @@ void ArduinoThreads::start(int const stack_size, uint32_t const start_flags, uin { _start_flags = start_flags; _stop_flags = stop_flags; - _loop_delay = 0; t = new rtos::Thread(osPriorityNormal, stack_size, nullptr, _tabname); t->start(mbed::callback(this, &ArduinoThreads::threadFunc)); } diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 36960b4..97e1d40 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -50,6 +50,7 @@ class ArduinoThreads { public: + ArduinoThreads(); virtual ~ArduinoThreads(); From 661f97cec0c6aaa1ff8a45740f5d5214ba377a74 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 09:07:57 +0200 Subject: [PATCH 19/37] Renaming rtos::Thread pointer 't' to '_thread' --- src/Arduino_Threads.cpp | 10 +++++----- src/Arduino_Threads.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index cfe7361..0d8eb4d 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -35,19 +35,19 @@ void ArduinoThreads::start(int const stack_size, uint32_t const start_flags, uin { _start_flags = start_flags; _stop_flags = stop_flags; - t = new rtos::Thread(osPriorityNormal, stack_size, nullptr, _tabname); - t->start(mbed::callback(this, &ArduinoThreads::threadFunc)); + _thread = new rtos::Thread(osPriorityNormal, stack_size, nullptr, _tabname); + _thread->start(mbed::callback(this, &ArduinoThreads::threadFunc)); } void ArduinoThreads::terminate() { - t->terminate(); - t->join(); + _thread->terminate(); + _thread->join(); } void ArduinoThreads::sendEvent(uint32_t const event) { - t->flags_set(event); + _thread->flags_set(event); } void ArduinoThreads::setLoopDelay(uint32_t const delay) diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 97e1d40..e633fa7 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -72,7 +72,7 @@ class ArduinoThreads private: static rtos::EventFlags _global_events; - rtos::Thread *t; + rtos::Thread * _thread; uint32_t _start_flags, _stop_flags; uint32_t _loop_delay; From 99bc3c6f0f328280d2731d21a0f9738eb71eb140 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 7 Oct 2021 09:12:46 +0200 Subject: [PATCH 20/37] Replace (leaky) manual memory handling with a smart pointer. --- src/Arduino_Threads.cpp | 2 +- src/Arduino_Threads.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index 0d8eb4d..acef655 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -35,7 +35,7 @@ void ArduinoThreads::start(int const stack_size, uint32_t const start_flags, uin { _start_flags = start_flags; _stop_flags = stop_flags; - _thread = new rtos::Thread(osPriorityNormal, stack_size, nullptr, _tabname); + _thread.reset(new rtos::Thread(osPriorityNormal, stack_size, nullptr, _tabname)); _thread->start(mbed::callback(this, &ArduinoThreads::threadFunc)); } diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index e633fa7..7f07f4b 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -6,6 +6,7 @@ **************************************************************************************/ #include +#include #include "Sink.hpp" #include "Source.hpp" @@ -72,7 +73,7 @@ class ArduinoThreads private: static rtos::EventFlags _global_events; - rtos::Thread * _thread; + mbed::SharedPtr _thread; uint32_t _start_flags, _stop_flags; uint32_t _loop_delay; From 58f451c67c7e89d5e08b70f7316b63cfb5d4ecee Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 8 Oct 2021 10:12:55 +0200 Subject: [PATCH 21/37] Cast loop delay to expected type by rtos::ThisThread::sleep_for() --- src/Arduino_Threads.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index acef655..b01ec29 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -102,6 +102,6 @@ void ArduinoThreads::threadFunc() /* Sleep for the time we've been asked to insert between loops. */ - rtos::ThisThread::sleep_for(_loop_delay); + rtos::ThisThread::sleep_for(rtos::Kernel::Clock::duration_u32(_loop_delay)); } } From 9e44f59be6bc5f803e73b5b0b2983b7b51ce9a67 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 8 Oct 2021 10:14:47 +0200 Subject: [PATCH 22/37] Rename _loop_delay to _loop_delay_ms for better clarity on the unit of the parameter. --- src/Arduino_Threads.cpp | 6 +++--- src/Arduino_Threads.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index b01ec29..5343b1d 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -17,7 +17,7 @@ rtos::EventFlags ArduinoThreads::_global_events; ArduinoThreads::ArduinoThreads() : _start_flags{0} , _stop_flags{0} -, _loop_delay{0} +, _loop_delay_ms{0} { } @@ -52,7 +52,7 @@ void ArduinoThreads::sendEvent(uint32_t const event) void ArduinoThreads::setLoopDelay(uint32_t const delay) { - _loop_delay = delay; + _loop_delay_ms = delay; } void ArduinoThreads::broadcastEvent(uint32_t const event) @@ -102,6 +102,6 @@ void ArduinoThreads::threadFunc() /* Sleep for the time we've been asked to insert between loops. */ - rtos::ThisThread::sleep_for(rtos::Kernel::Clock::duration_u32(_loop_delay)); + rtos::ThisThread::sleep_for(rtos::Kernel::Clock::duration_u32(_loop_delay_ms)); } } diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 7f07f4b..bfd08c5 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -75,7 +75,7 @@ class ArduinoThreads static rtos::EventFlags _global_events; mbed::SharedPtr _thread; uint32_t _start_flags, _stop_flags; - uint32_t _loop_delay; + uint32_t _loop_delay_ms; void threadFunc(); }; From e58455326a88d17bae3cd454471e1804fedde48e Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 11 Oct 2021 08:41:02 +0200 Subject: [PATCH 23/37] Replace rtos::Queue/MemoryPool with rtos::Mail which contains both in one class. --- src/Shared.hpp | 53 +++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/src/Shared.hpp b/src/Shared.hpp index e2e07b0..504b7b3 100644 --- a/src/Shared.hpp +++ b/src/Shared.hpp @@ -13,50 +13,59 @@ **************************************************************************************/ template -class Shared // template definition +class Shared { public: Shared() { } - operator T() { - osEvent evt = queue.get(); - if (evt.status == osEventMessage) { - /* Obtain the oldest inserted element from the queue. */ - T * val_ptr = reinterpret_cast(evt.value.p); + + operator T() + { + T * val_ptr = _mailbox.try_get_for(rtos::Kernel::wait_for_u32_forever); + if (val_ptr) + { /* Copy the content of T stored in the memory pool since we'll have to free the memory pool afterwards. */ T const tmp_val = *val_ptr; /* Free the allocated memory in the memory pool. */ - memory_pool.free(val_ptr); - /* Return obtained value from queue. */ + _mailbox.free(val_ptr); + /* Return obtained value from _mailbox. */ return tmp_val; } return val; } - T& operator= (const T& other) { - if (queue.full()) { - // invokes operator T() to discard oldest element and free its memory - T discard = *this; - } + + void operator = (T const & other) + { + if (_mailbox.full()) + T discard = *this; /* Invokes operator T() to discard oldest element and free its memory. */ + val = other; - /* Allocate memory in the memory pool. */ - T * val_ptr = memory_pool.alloc(); - /* Copy the content of 'other' into the freshly allocated message. */ - *val_ptr = other; - /* Insert into queue. */ - queue.put(val_ptr); - return (*val_ptr); + + /* Try and allocate memory for the new entry in rtos::Mail. */ + T * val_ptr = _mailbox.try_alloc(); + if (val_ptr) + { + /* Copy the content of 'other' into the freshly allocated message. */ + *val_ptr = other; + /* Copy the content of 'other' into the peek value. */ + val = other; + /* Insert value into mailbox. */ + _mailbox.put(val_ptr); + } } + T& peek() { return val; } + T& latest() { return peek(); } + private: T val; - rtos::MemoryPool memory_pool; - rtos::Queue queue; + rtos::Mail _mailbox; }; #endif /* ARDUINO_THREADS_SHARED_HPP_ */ From 83a748d4bab32f87656b1ec102bc0733ddf2e954 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 11 Oct 2021 08:47:00 +0200 Subject: [PATCH 24/37] Separate implementation and definition. --- src/Shared.hpp | 69 +++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/Shared.hpp b/src/Shared.hpp index 504b7b3..f3e82eb 100644 --- a/src/Shared.hpp +++ b/src/Shared.hpp @@ -19,40 +19,8 @@ class Shared Shared() { } - operator T() - { - T * val_ptr = _mailbox.try_get_for(rtos::Kernel::wait_for_u32_forever); - if (val_ptr) - { - /* Copy the content of T stored in the memory pool since we'll have to free the memory pool afterwards. */ - T const tmp_val = *val_ptr; - /* Free the allocated memory in the memory pool. */ - _mailbox.free(val_ptr); - /* Return obtained value from _mailbox. */ - return tmp_val; - } - return val; - } - - void operator = (T const & other) - { - if (_mailbox.full()) - T discard = *this; /* Invokes operator T() to discard oldest element and free its memory. */ - - val = other; - - /* Try and allocate memory for the new entry in rtos::Mail. */ - T * val_ptr = _mailbox.try_alloc(); - if (val_ptr) - { - /* Copy the content of 'other' into the freshly allocated message. */ - *val_ptr = other; - /* Copy the content of 'other' into the peek value. */ - val = other; - /* Insert value into mailbox. */ - _mailbox.put(val_ptr); - } - } + operator T(); + void operator = (T const & other); T& peek() { return val; @@ -68,4 +36,37 @@ class Shared rtos::Mail _mailbox; }; +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +template +Shared::operator T() +{ + T * val_ptr = _mailbox.try_get_for(rtos::Kernel::wait_for_u32_forever); + if (val_ptr) + { + T const tmp_val = *val_ptr; + _mailbox.free(val_ptr); + return tmp_val; + } + return val; +} + +template +void Shared::operator = (T const & other) +{ + if (_mailbox.full()) + T discard = *this; + + val = other; + + T * val_ptr = _mailbox.try_alloc(); + if (val_ptr) + { + *val_ptr = other; + _mailbox.put(val_ptr); + } +} + #endif /* ARDUINO_THREADS_SHARED_HPP_ */ From 048d823a1932940239eb014fe02f6d2a15d5ea6a Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 11 Oct 2021 08:48:50 +0200 Subject: [PATCH 25/37] Make actions during discarding of old data better visible in the code. --- src/Shared.hpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Shared.hpp b/src/Shared.hpp index f3e82eb..d40a9dd 100644 --- a/src/Shared.hpp +++ b/src/Shared.hpp @@ -56,8 +56,15 @@ Shared::operator T() template void Shared::operator = (T const & other) { + /* If the mailbox is full we are discarding the + * oldest element and then push the new one into + * the queue. + **/ if (_mailbox.full()) - T discard = *this; + { + T * val_ptr = _mailbox.try_get_for(rtos::Kernel::wait_for_u32_forever); + _mailbox.free(val_ptr); + } val = other; From 6b25c8c20790c8ab3225867a67c978c17a474122 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 11 Oct 2021 08:50:17 +0200 Subject: [PATCH 26/37] Prefix private member variable 'val' with a '_' --- src/Shared.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Shared.hpp b/src/Shared.hpp index d40a9dd..d7c8fb2 100644 --- a/src/Shared.hpp +++ b/src/Shared.hpp @@ -23,7 +23,7 @@ class Shared void operator = (T const & other); T& peek() { - return val; + return _val; } T& latest() { @@ -32,7 +32,7 @@ class Shared private: - T val; + T _val; rtos::Mail _mailbox; }; @@ -50,7 +50,7 @@ Shared::operator T() _mailbox.free(val_ptr); return tmp_val; } - return val; + return _val; } template @@ -66,7 +66,7 @@ void Shared::operator = (T const & other) _mailbox.free(val_ptr); } - val = other; + _val = other; T * val_ptr = _mailbox.try_alloc(); if (val_ptr) From fae2eb1b2faee295ae6994cf1e3121d8b084b785 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 11 Oct 2021 08:51:26 +0200 Subject: [PATCH 27/37] Reformat for better optical consistency. --- src/Shared.hpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/Shared.hpp b/src/Shared.hpp index d7c8fb2..66ba49c 100644 --- a/src/Shared.hpp +++ b/src/Shared.hpp @@ -6,7 +6,6 @@ **************************************************************************************/ #include -#include /************************************************************************************** * CLASS DECLARATION @@ -15,25 +14,19 @@ template class Shared { - public: - Shared() { - } +public: - operator T(); - void operator = (T const & other); + operator T(); + void operator = (T const & other); - T& peek() { - return _val; - } + T & peek() { return _val; } + T & latest() { return peek(); } - T& latest() { - return peek(); - } - private: +private: - T _val; - rtos::Mail _mailbox; + T _val; + rtos::Mail _mailbox; }; /************************************************************************************** From 3e4f2ad6c0c5881926e059347a1137413a3a80f4 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 11 Oct 2021 08:51:58 +0200 Subject: [PATCH 28/37] Drop method 'latest' since its indistinguishable from 'peek' --- src/Shared.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Shared.hpp b/src/Shared.hpp index 66ba49c..85417d9 100644 --- a/src/Shared.hpp +++ b/src/Shared.hpp @@ -20,7 +20,6 @@ class Shared void operator = (T const & other); T & peek() { return _val; } - T & latest() { return peek(); } private: From 3b838915cee3cc4e1d49b0404ef1bfed4834a82f Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 11 Oct 2021 08:54:14 +0200 Subject: [PATCH 29/37] Changing return signature of 'peek' to prevent unauthorized manipulation of '_val' --- src/Shared.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Shared.hpp b/src/Shared.hpp index 85417d9..18b634c 100644 --- a/src/Shared.hpp +++ b/src/Shared.hpp @@ -18,8 +18,7 @@ class Shared operator T(); void operator = (T const & other); - - T & peek() { return _val; } + inline T peek() const { return _val; } private: From 7450577a18a4de2473dd470866b5223938aecb25 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 11 Oct 2021 08:55:34 +0200 Subject: [PATCH 30/37] Adding license file. --- src/Arduino_Threads.cpp | 18 ++++++++++++++++++ src/Arduino_Threads.h | 18 ++++++++++++++++++ src/Shared.hpp | 18 ++++++++++++++++++ src/Sink.hpp | 18 ++++++++++++++++++ src/Source.hpp | 18 ++++++++++++++++++ 5 files changed, 90 insertions(+) diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index 5343b1d..732f3fb 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -1,3 +1,21 @@ +/* + * This file is part of the Arduino_ThreadsafeIO library. + * Copyright (c) 2021 Arduino SA. + * + * This 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 2.1 of the License, or (at your option) any later version. + * This 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + /************************************************************************************** * INCLUDE **************************************************************************************/ diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index bfd08c5..2c46671 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -1,3 +1,21 @@ +/* + * This file is part of the Arduino_ThreadsafeIO library. + * Copyright (c) 2021 Arduino SA. + * + * This 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 2.1 of the License, or (at your option) any later version. + * This 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #ifndef ARDUINO_THREADS_H_ #define ARDUINO_THREADS_H_ diff --git a/src/Shared.hpp b/src/Shared.hpp index 18b634c..0eaf00e 100644 --- a/src/Shared.hpp +++ b/src/Shared.hpp @@ -1,3 +1,21 @@ +/* + * This file is part of the Arduino_ThreadsafeIO library. + * Copyright (c) 2021 Arduino SA. + * + * This 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 2.1 of the License, or (at your option) any later version. + * This 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #ifndef ARDUINO_THREADS_SHARED_HPP_ #define ARDUINO_THREADS_SHARED_HPP_ diff --git a/src/Sink.hpp b/src/Sink.hpp index 97b3604..09ae1de 100644 --- a/src/Sink.hpp +++ b/src/Sink.hpp @@ -1,3 +1,21 @@ +/* + * This file is part of the Arduino_ThreadsafeIO library. + * Copyright (c) 2021 Arduino SA. + * + * This 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 2.1 of the License, or (at your option) any later version. + * This 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #ifndef ARDUINO_THREADS_SINK_HPP_ #define ARDUINO_THREADS_SINK_HPP_ diff --git a/src/Source.hpp b/src/Source.hpp index e3b91ed..6b77098 100644 --- a/src/Source.hpp +++ b/src/Source.hpp @@ -1,3 +1,21 @@ +/* + * This file is part of the Arduino_ThreadsafeIO library. + * Copyright (c) 2021 Arduino SA. + * + * This 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 2.1 of the License, or (at your option) any later version. + * This 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #ifndef ARDUINO_THREADS_SOURCE_HPP_ #define ARDUINO_THREADS_SOURCE_HPP_ From 911f10c7291c3004a5a57de968d4ce1b8ba5a309 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 11 Oct 2021 08:57:21 +0200 Subject: [PATCH 31/37] Rename ArduinoThreads to Arduino_Threads to be consistent with library name. --- .github/workflows/compile-examples.yml | 2 +- src/Arduino_Threads.cpp | 20 ++++++++++---------- src/Arduino_Threads.h | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index e526286..4c600c8 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -32,7 +32,7 @@ jobs: env: # libraries to install for all boards UNIVERSAL_LIBRARIES: | - # Install the ArduinoThreads library from the repository + # Install the Arduino_Threads library from the repository - source-path: ./ - name: Arduino_LSM9DS1 - name: Arduino_APDS9960 diff --git a/src/Arduino_Threads.cpp b/src/Arduino_Threads.cpp index 732f3fb..444ded5 100644 --- a/src/Arduino_Threads.cpp +++ b/src/Arduino_Threads.cpp @@ -26,13 +26,13 @@ * STATIC MEMBER DECLARATION **************************************************************************************/ -rtos::EventFlags ArduinoThreads::_global_events; +rtos::EventFlags Arduino_Threads::_global_events; /************************************************************************************** * CTOR/DTOR **************************************************************************************/ -ArduinoThreads::ArduinoThreads() +Arduino_Threads::Arduino_Threads() : _start_flags{0} , _stop_flags{0} , _loop_delay_ms{0} @@ -40,7 +40,7 @@ ArduinoThreads::ArduinoThreads() } -ArduinoThreads::~ArduinoThreads() +Arduino_Threads::~Arduino_Threads() { terminate(); } @@ -49,31 +49,31 @@ ArduinoThreads::~ArduinoThreads() * PUBLIC MEMBER FUNCTIONS **************************************************************************************/ -void ArduinoThreads::start(int const stack_size, uint32_t const start_flags, uint32_t const stop_flags) +void Arduino_Threads::start(int const stack_size, uint32_t const start_flags, uint32_t const stop_flags) { _start_flags = start_flags; _stop_flags = stop_flags; _thread.reset(new rtos::Thread(osPriorityNormal, stack_size, nullptr, _tabname)); - _thread->start(mbed::callback(this, &ArduinoThreads::threadFunc)); + _thread->start(mbed::callback(this, &Arduino_Threads::threadFunc)); } -void ArduinoThreads::terminate() +void Arduino_Threads::terminate() { _thread->terminate(); _thread->join(); } -void ArduinoThreads::sendEvent(uint32_t const event) +void Arduino_Threads::sendEvent(uint32_t const event) { _thread->flags_set(event); } -void ArduinoThreads::setLoopDelay(uint32_t const delay) +void Arduino_Threads::setLoopDelay(uint32_t const delay) { _loop_delay_ms = delay; } -void ArduinoThreads::broadcastEvent(uint32_t const event) +void Arduino_Threads::broadcastEvent(uint32_t const event) { _global_events.set(event); } @@ -82,7 +82,7 @@ void ArduinoThreads::broadcastEvent(uint32_t const event) * PRIVATE MEMBER FUNCTIONS **************************************************************************************/ -void ArduinoThreads::threadFunc() +void Arduino_Threads::threadFunc() { setup(); /* If _start_flags have been passed then wait until all the flags are set diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 2c46671..2fcd6e0 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -65,12 +65,12 @@ public: \ #define _macroToString(sequence) #sequence -class ArduinoThreads +class Arduino_Threads { public: - ArduinoThreads(); - virtual ~ArduinoThreads(); + Arduino_Threads(); + virtual ~Arduino_Threads(); void start (int const stack_size = 4096, uint32_t const start_flags = 0, uint32_t const stop_flags = 0); @@ -98,7 +98,7 @@ class ArduinoThreads void threadFunc(); }; -#define THD_ENTER(tabname) class CONCAT(tabname, Class) : public ArduinoThreads { \ +#define THD_ENTER(tabname) class CONCAT(tabname, Class) : public Arduino_Threads { \ public: \ CONCAT(tabname, Class)() { _tabname = _macroToString(tabname); } \ private: \ From 904ee61a65346b28995cf1d672d749decaa72d69 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 11 Oct 2021 09:06:29 +0200 Subject: [PATCH 32/37] Adding missing mbed based platforms, eliminating no longer needed library for CI build. --- .github/workflows/compile-examples.yml | 33 +++++++++++++------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 4c600c8..45efc0f 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -26,7 +26,7 @@ env: jobs: compile-test: - name: compile for ${{ matrix.fqbn }} + name: ${{ matrix.board.fqbn }} runs-on: ubuntu-latest env: @@ -34,11 +34,6 @@ jobs: UNIVERSAL_LIBRARIES: | # Install the Arduino_Threads library from the repository - source-path: ./ - - name: Arduino_LSM9DS1 - - name: Arduino_APDS9960 - - name: ArduinoECCX08 - - name: Arduino_HTS221 - - name: OneWire # sketch paths to compile (recursive) for all boards UNIVERSAL_SKETCH_PATHS: | - examples @@ -49,10 +44,19 @@ jobs: fail-fast: false matrix: - fqbn: - - "arduino:mbed:nano33ble" - # - "arduino:mbed:envie_m4" - - "arduino:mbed:envie_m7" + board: + - fqbn: arduino:mbed_nano:nano33ble + platforms: | + - name: arduino:mbed_nano + - fqbn: arduino:mbed_nano:nanorp2040connect + platforms: | + - name: arduino:mbed_nano + - fqbn: arduino:mbed_portenta:envie_m4 + platforms: | + - name: arduino:mbed_portenta + - fqbn: arduino:mbed_portenta:envie_m7 + platforms: | + - name: arduino:mbed_portenta steps: - name: Checkout @@ -83,15 +87,10 @@ jobs: uses: arduino/compile-sketches@v1 with: cli-version: 'arduino_threads' - fqbn: ${{ matrix.fqbn }} + fqbn: ${{ matrix.board.fqbn }} libraries: | ${{ env.UNIVERSAL_LIBRARIES }} - platforms: | - # Use Board Manager to install the latest release of Arduino mbed Boards to get the toolchain - - name: "arduino:mbed" - # Overwrite the Board Manager installation with the local platform - - source-path: "extras/ArduinoCore-mbed" - name: "arduino:mbed" + platforms: ${{ matrix.board.platforms }} sketch-paths: | ${{ env.UNIVERSAL_SKETCH_PATHS }} enable-deltas-report: 'true' From 318d7ff3da38f9e73c1cf0eaaf2c17f3a612e734 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 12 Oct 2021 07:23:42 +0200 Subject: [PATCH 33/37] Using constant for defining queue size. --- src/Shared.hpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Shared.hpp b/src/Shared.hpp index 0eaf00e..8b35cc9 100644 --- a/src/Shared.hpp +++ b/src/Shared.hpp @@ -25,11 +25,17 @@ #include +/************************************************************************************** + * CONSTANT + **************************************************************************************/ + +static size_t constexpr SHARED_QUEUE_SIZE = 16; + /************************************************************************************** * CLASS DECLARATION **************************************************************************************/ -template +template class Shared { public: @@ -43,6 +49,7 @@ class Shared T _val; rtos::Mail _mailbox; + }; /************************************************************************************** From 7bfd8006c9b4349cee532ac387b32e3e29220ecc Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 12 Oct 2021 08:32:48 +0200 Subject: [PATCH 34/37] A big rework of the source/sink system. --- .../Consumer.inot | 0 .../Demo_Shared_Counter.ino} | 6 +- .../Producer.inot | 0 .../SharedVariables.h | 0 .../Demo_Source_Sink_Counter/Consumer.inot | 11 ++ .../Demo_Source_Sink_Counter.ino | 16 ++ .../Demo_Source_Sink_Counter/Producer.inot | 13 ++ .../SharedVariables.h | 0 .../Demo_Source_Sink_LED.ino} | 0 .../Demo_Source_Sink_LED/SharedVariables.h | 0 .../Sink_Thread.inot | 2 +- .../Source_Thread.inot | 6 +- src/Arduino_Threads.h | 4 +- src/Sink.hpp | 186 +++++++----------- src/Source.hpp | 56 ++++-- 15 files changed, 159 insertions(+), 141 deletions(-) rename examples/{Demo_Shared => Demo_Shared_Counter}/Consumer.inot (100%) rename examples/{Demo_Shared/Demo_Shared.ino => Demo_Shared_Counter/Demo_Shared_Counter.ino} (80%) rename examples/{Demo_Shared => Demo_Shared_Counter}/Producer.inot (100%) rename examples/{Demo_Shared => Demo_Shared_Counter}/SharedVariables.h (100%) create mode 100644 examples/Demo_Source_Sink_Counter/Consumer.inot create mode 100644 examples/Demo_Source_Sink_Counter/Demo_Source_Sink_Counter.ino create mode 100644 examples/Demo_Source_Sink_Counter/Producer.inot rename examples/{Demo_Source_Sink => Demo_Source_Sink_Counter}/SharedVariables.h (100%) rename examples/{Demo_Source_Sink/Demo_Source_Sink.ino => Demo_Source_Sink_LED/Demo_Source_Sink_LED.ino} (100%) create mode 100644 examples/Demo_Source_Sink_LED/SharedVariables.h rename examples/{Demo_Source_Sink => Demo_Source_Sink_LED}/Sink_Thread.inot (96%) rename examples/{Demo_Source_Sink => Demo_Source_Sink_LED}/Source_Thread.inot (66%) diff --git a/examples/Demo_Shared/Consumer.inot b/examples/Demo_Shared_Counter/Consumer.inot similarity index 100% rename from examples/Demo_Shared/Consumer.inot rename to examples/Demo_Shared_Counter/Consumer.inot diff --git a/examples/Demo_Shared/Demo_Shared.ino b/examples/Demo_Shared_Counter/Demo_Shared_Counter.ino similarity index 80% rename from examples/Demo_Shared/Demo_Shared.ino rename to examples/Demo_Shared_Counter/Demo_Shared_Counter.ino index 8820b15..aa71781 100644 --- a/examples/Demo_Shared/Demo_Shared.ino +++ b/examples/Demo_Shared_Counter/Demo_Shared_Counter.ino @@ -1,4 +1,5 @@ -void setup() { +void setup() +{ Serial.begin(115200); while (!Serial) { } @@ -6,6 +7,7 @@ void setup() { Consumer.start(); } -void loop() { +void loop() +{ rtos::ThisThread::yield(); } diff --git a/examples/Demo_Shared/Producer.inot b/examples/Demo_Shared_Counter/Producer.inot similarity index 100% rename from examples/Demo_Shared/Producer.inot rename to examples/Demo_Shared_Counter/Producer.inot diff --git a/examples/Demo_Shared/SharedVariables.h b/examples/Demo_Shared_Counter/SharedVariables.h similarity index 100% rename from examples/Demo_Shared/SharedVariables.h rename to examples/Demo_Shared_Counter/SharedVariables.h diff --git a/examples/Demo_Source_Sink_Counter/Consumer.inot b/examples/Demo_Source_Sink_Counter/Consumer.inot new file mode 100644 index 0000000..d892c67 --- /dev/null +++ b/examples/Demo_Source_Sink_Counter/Consumer.inot @@ -0,0 +1,11 @@ +SINK(counter, int); + +void setup() +{ + +} + +void loop() +{ + Serial.println(counter.read()); +} diff --git a/examples/Demo_Source_Sink_Counter/Demo_Source_Sink_Counter.ino b/examples/Demo_Source_Sink_Counter/Demo_Source_Sink_Counter.ino new file mode 100644 index 0000000..6ce05a6 --- /dev/null +++ b/examples/Demo_Source_Sink_Counter/Demo_Source_Sink_Counter.ino @@ -0,0 +1,16 @@ +/* + * This examples demonstrates the SOURCE/SINK abstraction. + * Each thread may have any number of SOURCES and SINKS that can be connected + * together using the "connectTo" method. + */ + +void setup() +{ + Producer.counter.connectTo(Consumer.counter); + Producer.start(); + Consumer.start(); +} + +void loop() { + rtos::ThisThread::yield(); +} diff --git a/examples/Demo_Source_Sink_Counter/Producer.inot b/examples/Demo_Source_Sink_Counter/Producer.inot new file mode 100644 index 0000000..fe0a250 --- /dev/null +++ b/examples/Demo_Source_Sink_Counter/Producer.inot @@ -0,0 +1,13 @@ +SOURCE(counter, int); + +void setup() +{ + +} + +void loop() +{ + static int i = 0; + counter.write(i); + i++; +} diff --git a/examples/Demo_Source_Sink/SharedVariables.h b/examples/Demo_Source_Sink_Counter/SharedVariables.h similarity index 100% rename from examples/Demo_Source_Sink/SharedVariables.h rename to examples/Demo_Source_Sink_Counter/SharedVariables.h diff --git a/examples/Demo_Source_Sink/Demo_Source_Sink.ino b/examples/Demo_Source_Sink_LED/Demo_Source_Sink_LED.ino similarity index 100% rename from examples/Demo_Source_Sink/Demo_Source_Sink.ino rename to examples/Demo_Source_Sink_LED/Demo_Source_Sink_LED.ino diff --git a/examples/Demo_Source_Sink_LED/SharedVariables.h b/examples/Demo_Source_Sink_LED/SharedVariables.h new file mode 100644 index 0000000..e69de29 diff --git a/examples/Demo_Source_Sink/Sink_Thread.inot b/examples/Demo_Source_Sink_LED/Sink_Thread.inot similarity index 96% rename from examples/Demo_Source_Sink/Sink_Thread.inot rename to examples/Demo_Source_Sink_LED/Sink_Thread.inot index 0bc87c6..51f9031 100644 --- a/examples/Demo_Source_Sink/Sink_Thread.inot +++ b/examples/Demo_Source_Sink_LED/Sink_Thread.inot @@ -3,7 +3,7 @@ * An 'bool' SINK with a size of '0'. This kind of SINK has no buffer so the reading thread * will block until the writing thread has written something, or vice versa. */ -SINK(led, bool, 0) +SINK(led, bool); void setup() { diff --git a/examples/Demo_Source_Sink/Source_Thread.inot b/examples/Demo_Source_Sink_LED/Source_Thread.inot similarity index 66% rename from examples/Demo_Source_Sink/Source_Thread.inot rename to examples/Demo_Source_Sink_LED/Source_Thread.inot index 302a2c8..1bf7fca 100644 --- a/examples/Demo_Source_Sink/Source_Thread.inot +++ b/examples/Demo_Source_Sink_LED/Source_Thread.inot @@ -1,5 +1,5 @@ /* The output SOURCE, it sends 'bool' values. */ -SOURCE(led, bool) +SOURCE(led, bool); void setup() { @@ -8,8 +8,8 @@ void setup() void loop() { - led.send(true); + led.write(true); delay(100); - led.send(false); + led.write(false); delay(100); } diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 2fcd6e0..428cdd1 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -39,9 +39,9 @@ public: \ Source name; \ private: -#define SINK(name, type, size) \ +#define SINK(name, type) \ public: \ - Sink name{size}; \ + SinkBlocking name; \ private: // we need to call the Sink(int size) non-default constructor using size as parameter. // This is done by writing diff --git a/src/Sink.hpp b/src/Sink.hpp index 09ae1de..d52ef65 100644 --- a/src/Sink.hpp +++ b/src/Sink.hpp @@ -29,121 +29,79 @@ * CLASS DECLARATION **************************************************************************************/ -template -class Sink +template +class SinkBase { - private: - rtos::Mutex dataMutex; - rtos::ConditionVariable dataAvailable; - rtos::ConditionVariable slotAvailable; - T latest; - Sink *next; - const int size; - int first, last; - bool full; - T *queue; - - public: - Sink(int s) : - dataAvailable(dataMutex), - slotAvailable(dataMutex), - size(s), - queue((size > 0) ? new T[size] : nullptr), - first(0), last(0), full(false) - {}; - - ~Sink() { - if (queue != nullptr) { delete queue; } - } - - - //protected: TODO - void connectTo(Sink &sink) - { - if (next == nullptr) { - next = &sink; - } else { - next->connectTo(sink); - } - } - - T read() - { - // Non-blocking shared variable - if (size == -1) { - dataMutex.lock(); - T res = latest; - dataMutex.unlock(); - return res; - } - - // Blocking shared variable - if (size == 0) { - dataMutex.lock(); - while (!full) { - dataAvailable.wait(); - } - T res = latest; - full = false; - slotAvailable.notify_all(); - dataMutex.unlock(); - return res; - } - - // Blocking queue - dataMutex.lock(); - while (first == last && !full) { - dataAvailable.wait(); - } - T res = queue[first++]; - first %= size; - if (full) { - full = false; - slotAvailable.notify_one(); - } - dataMutex.unlock(); - return res; - } - - //protected: TODO - void inject(const T &value) - { - dataMutex.lock(); - - // Non-blocking shared variable - if (size == -1) { - latest = value; - } - - // Blocking shared variable - else if (size == 0) { - while (full) { - slotAvailable.wait(); - } - latest = value; - full = true; - dataAvailable.notify_one(); - slotAvailable.wait(); - } - - // Blocking queue - else { - while (full) { - slotAvailable.wait(); - } - if (first == last) { - dataAvailable.notify_one(); - } - queue[last++] = value; - last %= size; - if (first == last) { - full = true; - } - } - dataMutex.unlock(); - - if (next) next->inject(value); - } +public: + + virtual ~SinkBase() { } + + virtual T read() = 0; + virtual void inject(T const & value) = 0; +}; + +template +class SinkNonBlocking : public SinkBase +{ + /* TODO - Do we really need this? */ }; +template +class SinkBlocking : public SinkBase +{ +public: + + SinkBlocking(); + virtual ~SinkBlocking() { } + + virtual T read() override; + virtual void inject(T const & value) override; + + +private: + + T _data; + bool _is_data_available; + rtos::Mutex _mutex; + rtos::ConditionVariable _cond_data_available; + rtos::ConditionVariable _cond_slot_available; + +}; + +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS - SinkBlocking + **************************************************************************************/ + +template +SinkBlocking::SinkBlocking() +: _is_data_available{false} +, _cond_data_available(_mutex) +, _cond_slot_available(_mutex) +{ } + +template +T SinkBlocking::read() +{ + _mutex.lock(); + while (!_is_data_available) + _cond_data_available.wait(); + T const d = _data; + _is_data_available = false; + _cond_slot_available.notify_all(); + _mutex.unlock(); + return d; +} + +template +void SinkBlocking::inject(T const & value) +{ + _mutex.lock(); + while (_is_data_available) + _cond_slot_available.wait(); + _data = value; + _is_data_available = true; + _cond_data_available.notify_all(); + _mutex.unlock(); +} + #endif /* ARDUINO_THREADS_SINK_HPP_ */ diff --git a/src/Source.hpp b/src/Source.hpp index 6b77098..0a3893c 100644 --- a/src/Source.hpp +++ b/src/Source.hpp @@ -19,37 +19,55 @@ #ifndef ARDUINO_THREADS_SOURCE_HPP_ #define ARDUINO_THREADS_SOURCE_HPP_ +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include +#include + /************************************************************************************** * FORWARD DECLARATION **************************************************************************************/ template -class Sink; +class SinkBase; /************************************************************************************** * CLASS DECLARATION **************************************************************************************/ -template +template class Source { - public: - Source() {}; - - void connectTo(Sink &sink) { - if (destination == nullptr) { - destination = &sink; - } else { - destination->connectTo(sink); - } - } - - void send(const T &value) { - if (destination) destination->inject(value); - } - - private: - Sink *destination; +public: + + void connectTo(SinkBase & sink); + void write(T const & value); + +private: + std::list *> _sink_list; }; +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS + **************************************************************************************/ + +template +void Source::connectTo(SinkBase & sink) +{ + _sink_list.push_back(&sink); +} + +template +void Source::write(T const & value) +{ + std::for_each(std::begin(_sink_list), + std::end (_sink_list), + [value](SinkBase * sink) + { + sink->inject(value); + }); +} + #endif /* ARDUINO_THREADS_SOURCE_HPP_ */ From 63553a81516fbc364c6247bbbb523e74c76e5175 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 12 Oct 2021 08:36:48 +0200 Subject: [PATCH 35/37] Provide a macro for instantiation of a Shared variable. --- examples/Demo_Shared_Counter/SharedVariables.h | 2 +- src/Arduino_Threads.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/Demo_Shared_Counter/SharedVariables.h b/examples/Demo_Shared_Counter/SharedVariables.h index 51ea60e..5891a84 100644 --- a/examples/Demo_Shared_Counter/SharedVariables.h +++ b/examples/Demo_Shared_Counter/SharedVariables.h @@ -1 +1 @@ -Shared counter; +SHARED(counter, int); diff --git a/src/Arduino_Threads.h b/src/Arduino_Threads.h index 428cdd1..ca9250f 100644 --- a/src/Arduino_Threads.h +++ b/src/Arduino_Threads.h @@ -53,6 +53,9 @@ public: \ // This is called "C++11 uniform init" (using "{}" instead of "()" without "="... yikes!) // https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++-dos-and-donts.md +#define SHARED(name, type) \ + Shared name; + /************************************************************************************** * CLASS DECLARATION **************************************************************************************/ From 4863888348c30f24f3aea3807e2f58c967074db8 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 12 Oct 2021 08:39:30 +0200 Subject: [PATCH 36/37] Implement non-blocking Sink. --- src/Sink.hpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Sink.hpp b/src/Sink.hpp index d52ef65..593601f 100644 --- a/src/Sink.hpp +++ b/src/Sink.hpp @@ -43,7 +43,29 @@ class SinkBase template class SinkNonBlocking : public SinkBase { - /* TODO - Do we really need this? */ +public: + + SinkNonBlocking(); + virtual ~SinkNonBlocking() { } + + virtual T read() override + { + _mutex.lock(); + return _data; + _mutex.unlock(); + } + virtual void inject(T const & value) override + { + _mutex.lock(); + _data = value; + _mutex.unlock(); + } + +private: + + T _data; + rtos::Mutex _mutex; + }; template From de2a0d477f7a98820d9ee4ac01736b7c6677bb5e Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 12 Oct 2021 08:42:05 +0200 Subject: [PATCH 37/37] Extract implemention of SinkNonBlocking member functions. --- src/Sink.hpp | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/Sink.hpp b/src/Sink.hpp index 593601f..40179a2 100644 --- a/src/Sink.hpp +++ b/src/Sink.hpp @@ -45,21 +45,12 @@ class SinkNonBlocking : public SinkBase { public: - SinkNonBlocking(); + SinkNonBlocking() { } virtual ~SinkNonBlocking() { } - virtual T read() override - { - _mutex.lock(); - return _data; - _mutex.unlock(); - } - virtual void inject(T const & value) override - { - _mutex.lock(); - _data = value; - _mutex.unlock(); - } + virtual T read() override; + virtual void inject(T const & value) override; + private: @@ -90,6 +81,26 @@ class SinkBlocking : public SinkBase }; +/************************************************************************************** + * PUBLIC MEMBER FUNCTIONS - SinkNonBlocking + **************************************************************************************/ + +template +T SinkNonBlocking::read() +{ + _mutex.lock(); + return _data; + _mutex.unlock(); +} + +template +void SinkNonBlocking::inject(T const & value) +{ + _mutex.lock(); + _data = value; + _mutex.unlock(); +} + /************************************************************************************** * PUBLIC MEMBER FUNCTIONS - SinkBlocking **************************************************************************************/