From 328e1a52caf96f7d0354f84972601c518291d4c0 Mon Sep 17 00:00:00 2001 From: pschatzmann Date: Fri, 3 Oct 2025 16:48:36 +0200 Subject: [PATCH 1/6] Clean Wrapper implementations for SPI, I2C and GPIO --- ArduinoCore-Linux/cores/arduino/Arduino.cpp | 165 +++---- ArduinoCore-Linux/cores/arduino/Ethernet.h | 7 +- ArduinoCore-Linux/cores/arduino/FileStream.h | 166 ++++---- .../cores/arduino/GPIOWrapper.cpp | 93 ++++ ArduinoCore-Linux/cores/arduino/GPIOWrapper.h | 81 ++++ ArduinoCore-Linux/cores/arduino/Hardware.h | 23 - .../cores/arduino/HardwareGPIO.cpp | 87 ---- .../cores/arduino/HardwareGPIO.h | 38 +- .../cores/arduino/HardwareI2CEx.cpp | 80 ---- .../cores/arduino/HardwareI2CEx.h | 25 -- .../cores/arduino/HardwareSPI.cpp | 82 ---- .../cores/arduino/HardwareService.h | 401 +++++++++--------- .../cores/arduino/HardwareSetupRemote.h | 69 ++- .../cores/arduino/I2CWrapper.cpp | 119 ++++++ ArduinoCore-Linux/cores/arduino/I2CWrapper.h | 85 ++++ ArduinoCore-Linux/cores/arduino/Main.cpp | 7 +- ArduinoCore-Linux/cores/arduino/RemoteGPIO.h | 26 ++ ArduinoCore-Linux/cores/arduino/RemoteI2C.h | 33 +- ArduinoCore-Linux/cores/arduino/RemoteSPI.h | 32 +- .../cores/arduino/RemoteSerial.h | 252 ++++++----- .../cores/arduino/RingBufferExt.h | 182 ++++---- ArduinoCore-Linux/cores/arduino/SPI.h | 2 + .../cores/arduino/SPIWrapper.cpp | 90 ++++ ArduinoCore-Linux/cores/arduino/SPIWrapper.h | 79 ++++ ArduinoCore-Linux/cores/arduino/Serial.h | 137 +++--- ArduinoCore-Linux/cores/arduino/Sources.h | 54 +++ ArduinoCore-Linux/cores/arduino/StdioDevice.h | 219 +++++----- .../cores/arduino/Unsupported.cpp | 20 +- ArduinoCore-Linux/cores/arduino/WMath.cpp | 2 +- ArduinoCore-Linux/cores/arduino/WiFi.h | 18 +- .../cores/arduino/WiFiUdpStream.h | 159 +++---- ArduinoCore-Linux/cores/arduino/Wire.h | 5 +- .../cores/rasperry_pi/HardwareGPIO_RPI.cpp | 1 - .../cores/rasperry_pi/HardwareI2C_RPI.h | 1 - .../cores/rasperry_pi/HardwareSetupRPI.h | 51 ++- CMakeLists.txt | 5 + docs/html/_hardware_i2_c_ex_8h_source.html | 12 +- docs/html/_remote_i2_c_8h_source.html | 6 +- docs/html/_remote_serial_8h_source.html | 6 +- docs/html/annotated.html | 4 +- docs/html/classarduino_1_1_hardware_i2_c.html | 2 +- ...sarduino_1_1_hardware_i2_c_ex-members.html | 32 +- .../classarduino_1_1_hardware_i2_c_ex.html | 38 +- docs/html/classarduino_1_1_print.html | 2 +- .../classarduino_1_1_remote_i2_c-members.html | 4 +- docs/html/classarduino_1_1_remote_i2_c.html | 24 +- ...rduino_1_1_remote_serial_impl-members.html | 40 +- .../classarduino_1_1_remote_serial_impl.html | 26 +- docs/html/classarduino_1_1_stream.html | 2 +- docs/html/classes.html | 4 +- .../dir_2ba506666022b9e33e4ecc950aca3a7c.html | 2 +- docs/html/files.html | 2 +- docs/html/hierarchy.html | 4 +- docs/html/namespacearduino.html | 4 +- docs/html/namespaces.html | 4 +- docs/html/search/all_10.js | 2 +- docs/html/search/all_8.js | 2 +- docs/html/search/classes_6.js | 2 +- docs/html/search/classes_b.js | 2 +- examples/CMakeLists.txt | 5 +- .../{remote-api => }/blink/CMakeLists.txt | 0 examples/{raspberry-pi => }/blink/blink.ino | 2 + examples/{remote-api => }/i2c/CMakeLists.txt | 0 examples/{remote-api => }/i2c/i2c.ino | 1 - examples/jupyter/01-Setup.ipynb | 2 +- examples/jupyter/05-Serial.ipynb | 4 +- examples/raspberry-pi/CMakeLists.txt | 3 - examples/raspberry-pi/blink/CMakeLists.txt | 11 - examples/raspberry-pi/i2c/CMakeLists.txt | 11 - examples/raspberry-pi/i2c/i2c.ino | 35 -- examples/raspberry-pi/spi/CMakeLists.txt | 11 - examples/raspberry-pi/spi/spi.ino | 33 -- examples/remote-api/CMakeLists.txt | 4 - examples/remote-api/blink/blink.ino | 20 - examples/{remote-api => }/spi/CMakeLists.txt | 0 examples/{remote-api => }/spi/spi.ino | 1 - 76 files changed, 1720 insertions(+), 1545 deletions(-) create mode 100644 ArduinoCore-Linux/cores/arduino/GPIOWrapper.cpp create mode 100644 ArduinoCore-Linux/cores/arduino/GPIOWrapper.h delete mode 100644 ArduinoCore-Linux/cores/arduino/Hardware.h delete mode 100644 ArduinoCore-Linux/cores/arduino/HardwareGPIO.cpp delete mode 100644 ArduinoCore-Linux/cores/arduino/HardwareI2CEx.cpp delete mode 100644 ArduinoCore-Linux/cores/arduino/HardwareI2CEx.h delete mode 100644 ArduinoCore-Linux/cores/arduino/HardwareSPI.cpp create mode 100644 ArduinoCore-Linux/cores/arduino/I2CWrapper.cpp create mode 100644 ArduinoCore-Linux/cores/arduino/I2CWrapper.h create mode 100644 ArduinoCore-Linux/cores/arduino/SPI.h create mode 100644 ArduinoCore-Linux/cores/arduino/SPIWrapper.cpp create mode 100644 ArduinoCore-Linux/cores/arduino/SPIWrapper.h create mode 100644 ArduinoCore-Linux/cores/arduino/Sources.h rename examples/{remote-api => }/blink/CMakeLists.txt (100%) rename examples/{raspberry-pi => }/blink/blink.ino (91%) rename examples/{remote-api => }/i2c/CMakeLists.txt (100%) rename examples/{remote-api => }/i2c/i2c.ino (92%) delete mode 100644 examples/raspberry-pi/blink/CMakeLists.txt delete mode 100644 examples/raspberry-pi/i2c/CMakeLists.txt delete mode 100644 examples/raspberry-pi/i2c/i2c.ino delete mode 100644 examples/raspberry-pi/spi/CMakeLists.txt delete mode 100644 examples/raspberry-pi/spi/spi.ino delete mode 100644 examples/remote-api/CMakeLists.txt delete mode 100644 examples/remote-api/blink/blink.ino rename examples/{remote-api => }/spi/CMakeLists.txt (100%) rename examples/{remote-api => }/spi/spi.ino (92%) diff --git a/ArduinoCore-Linux/cores/arduino/Arduino.cpp b/ArduinoCore-Linux/cores/arduino/Arduino.cpp index 98ca9a3..a4a8d5f 100644 --- a/ArduinoCore-Linux/cores/arduino/Arduino.cpp +++ b/ArduinoCore-Linux/cores/arduino/Arduino.cpp @@ -1,150 +1,113 @@ +#include "Arduino.h" + +#include + +#include #include -#include #include -#include #include -#include -#include "Arduino.h" + +#include "GPIOWrapper.h" +#include "HardwareGPIO.h" +#include "RemoteSerial.h" #include "api/Common.h" -#include "api/Stream.h" #include "api/PluggableUSB.h" -#include "RemoteSerial.h" -#include "Hardware.h" +#include "api/Stream.h" #if !defined(SKIP_HARDWARE_SETUP) -# include "HardwareSetupRemote.h" +#include "HardwareSetupRemote.h" #endif #if !defined(SKIP_HARDWARE_WIFI) -# include "WiFi.h" -# include "WiFiClient.h" +#include "WiFi.h" +#include "WiFiClient.h" #endif #if defined(USE_RPI) -# include "HardwareGPIO_RPI.h" -# include "HardwareI2C_RPI.h" +#include "HardwareGPIO_RPI.h" +#include "HardwareI2C_RPI.h" #endif -#include "api/PluggableUSB.h" -#include "api/deprecated-avr-comp/avr/dtostrf.h" #include "ArduinoLogger.h" -#include "StdioDevice.h" #include "Serial.h" +#include "StdioDevice.h" +#include "api/PluggableUSB.h" +#include "api/deprecated-avr-comp/avr/dtostrf.h" namespace arduino { #if !defined(SKIP_HARDWARE_WIFI) -WifiMock WiFi; // So that we can use the WiFi +WifiMock WiFi; // So that we can use the WiFi #endif +// static PluggableUSB_ obj; +PluggableUSB_::PluggableUSB_() {} -//static PluggableUSB_ obj; -PluggableUSB_::PluggableUSB_(){} +} // namespace arduino -} - - // sleep ms milliseconds -void delay(unsigned long ms){ - std::this_thread::sleep_for(std::chrono::milliseconds(ms)); +void delay(unsigned long ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); } // sleep us milliseconds -void delayMicroseconds(unsigned int us){ - std::this_thread::sleep_for(std::chrono::microseconds(us)); +void delayMicroseconds(unsigned int us) { + std::this_thread::sleep_for(std::chrono::microseconds(us)); } // double to string conversion -> we can use sprintf which is complete in linux -char *dtostrf(double val, signed char width, unsigned char prec, char *sout){ - sprintf(sout,"%*.*lf",width,prec, val); - return sout; +char* dtostrf(double val, signed char width, unsigned char prec, char* sout) { + sprintf(sout, "%*.*lf", width, prec, val); + return sout; } // Returns the number of milliseconds passed since epich unsigned long millis() { - static uint64_t start = 0; - using namespace std::chrono; - // Get current time with precision of milliseconds - auto now = time_point_cast(system_clock::now()); - // sys_milliseconds is type time_point - using sys_milliseconds = decltype(now); - // Convert time_point to signed integral type - auto result = now.time_since_epoch().count(); - if (start == 0) { - start = result; - } - return result - start; - + static uint64_t start = 0; + using namespace std::chrono; + // Get current time with precision of milliseconds + auto now = time_point_cast(system_clock::now()); + // sys_milliseconds is type time_point + using sys_milliseconds = decltype(now); + // Convert time_point to signed integral type + auto result = now.time_since_epoch().count(); + if (start == 0) { + start = result; + } + return result - start; } // Returns the micros of milliseconds passed since epich -unsigned long micros(void){ - using namespace std::chrono; - // Get current time with precision of milliseconds - auto now = time_point_cast(system_clock::now()); - // sys_milliseconds is type time_point - using sys_milliseconds = decltype(now); - // Convert time_point to signed integral type - return now.time_since_epoch().count(); +unsigned long micros(void) { + using namespace std::chrono; + // Get current time with precision of milliseconds + auto now = time_point_cast(system_clock::now()); + // sys_milliseconds is type time_point + using sys_milliseconds = decltype(now); + // Convert time_point to signed integral type + return now.time_since_epoch().count(); } -void pinMode(pin_size_t pinNumber, PinMode pinMode){ - if (Hardware.gpio != nullptr) { - Hardware.gpio->pinMode(pinNumber,pinMode); - } +void pinMode(pin_size_t pinNumber, PinMode pinMode) { + GPIO.pinMode(pinNumber, pinMode); } void digitalWrite(pin_size_t pinNumber, PinStatus status) { - if (Hardware.gpio != nullptr) { - Hardware.gpio->digitalWrite(pinNumber,status); - } + GPIO.digitalWrite(pinNumber, status); } PinStatus digitalRead(pin_size_t pinNumber) { - if (Hardware.gpio != nullptr) { - return Hardware.gpio->digitalRead(pinNumber); - } else { - return HIGH; //sumulate input pullup - } -} -int analogRead(pin_size_t pinNumber){ - if (Hardware.gpio != nullptr) { - return Hardware.gpio->analogRead(pinNumber); - } else { - return 0; - } - -} -void analogReference(uint8_t mode){ - if (Hardware.gpio != nullptr) { - Hardware.gpio->analogReference(mode); - } + return GPIO.digitalRead(pinNumber); } +int analogRead(pin_size_t pinNumber) { return GPIO.analogRead(pinNumber); } +void analogReference(uint8_t mode) { GPIO.analogReference(mode); } void analogWrite(pin_size_t pinNumber, int value) { - if (Hardware.gpio != nullptr) { - Hardware.gpio->analogWrite(pinNumber,value); - } + GPIO.analogWrite(pinNumber, value); } void tone(uint8_t pinNumber, unsigned int frequency, unsigned long duration) { - if (Hardware.gpio != nullptr) { - Hardware.gpio->tone(pinNumber,frequency,duration); - } -} -void noTone(uint8_t pinNumber) { - if (Hardware.gpio != nullptr) { - Hardware.gpio->noTone(pinNumber); - } + GPIO.tone(pinNumber, frequency, duration); } -unsigned long pulseIn(uint8_t pinNumber, uint8_t state, unsigned long timeout){ - if (Hardware.gpio != nullptr) { - return Hardware.gpio->pulseIn(pinNumber, state, timeout); - } else { - return 0; - } +void noTone(uint8_t pinNumber) { GPIO.noTone(pinNumber); } +unsigned long pulseIn(uint8_t pinNumber, uint8_t state, unsigned long timeout) { + return GPIO.pulseIn(pinNumber, state, timeout); } -unsigned long pulseInLong(uint8_t pinNumber, uint8_t state, unsigned long timeout){ - if (Hardware.gpio != nullptr) { - return Hardware.gpio->pulseInLong(pinNumber, state, timeout); - } else { - return 0; - } +unsigned long pulseInLong(uint8_t pinNumber, uint8_t state, + unsigned long timeout) { + return GPIO.pulseInLong(pinNumber, state, timeout); } -void yield(){ -} - - +void yield() {} diff --git a/ArduinoCore-Linux/cores/arduino/Ethernet.h b/ArduinoCore-Linux/cores/arduino/Ethernet.h index 675adf1..b8eab54 100644 --- a/ArduinoCore-Linux/cores/arduino/Ethernet.h +++ b/ArduinoCore-Linux/cores/arduino/Ethernet.h @@ -6,11 +6,11 @@ #include // for close #include "ArduinoLogger.h" +#include "RingBufferExt.h" +#include "SocketImpl.h" #include "api/Client.h" #include "api/Common.h" #include "api/IPAddress.h" -#include "RingBufferExt.h" -#include "SocketImpl.h" namespace arduino { @@ -120,7 +120,6 @@ class EthernetClient : public Client { return connect(str.c_str(), port); } - // opens a connection virtual int connect(const char* address, uint16_t port) override { Logger.info(WIFICLIENT, "connect"); @@ -213,7 +212,7 @@ class EthernetClient : public Client { return result; } - virtual size_t readBytes(char* buffer, size_t len) { + virtual size_t readBytes(char* buffer, size_t len) { return read((uint8_t*)buffer, len); } diff --git a/ArduinoCore-Linux/cores/arduino/FileStream.h b/ArduinoCore-Linux/cores/arduino/FileStream.h index c2dbd2a..e782297 100644 --- a/ArduinoCore-Linux/cores/arduino/FileStream.h +++ b/ArduinoCore-Linux/cores/arduino/FileStream.h @@ -1,107 +1,95 @@ #pragma once -#include #include +#include + #include "Stream.h" namespace arduino { /** - * @brief We use the SerialDef class to be able to provide Serail, Serial1 and Serial2 outside of the - * Arduino environment; + * @brief We use the FileStream class to be able to provide Serail, Serial1 and + * Serial2 outside of the Arduino environment; */ class FileStream : public Stream { - public: - - FileStream(const char* outDevice="/dev/stdout", const char* inDevice="/dev/stdin"){ - open(outDevice, inDevice); - } - - ~FileStream(){ - in.close(); - out.close(); - } - - void open(const char* outDevice, const char* inDevice){ - if (outDevice!=nullptr) - out.open(outDevice,std::ios::out); - if (inDevice!=nullptr) - in.open(inDevice,std::ios::in); - } - - virtual void begin(int speed){ - // nothing to be done - } - - virtual void print(const char* str){ - out << str; - out.flush(); - } - - virtual void println(const char* str=""){ - out << str << "\n"; - out.flush(); - } - - virtual void print(int str){ - out << str; - out.flush(); - } - - virtual void println(int str){ - out << str << "\n"; - out.flush(); - } - - virtual void flush() { - out.flush(); - } - - virtual void write(const char* str, int len) { - out.write(str, len); - } - - virtual void write(uint8_t* str, int len) { - out.write((const char*)str, len); - } - - virtual size_t write(int32_t value){ - out.put(value); - return 1; - } - - virtual size_t write(uint8_t value){ - out.put(value); - return 1; - } - - virtual int available() { - return in.rdbuf()->in_avail(); - }; - - virtual int read() { - return in.get(); - } - - virtual int peek() { - return in.peek(); - } - - protected: - std::fstream out; - std::fstream in; + public: + FileStream(const char* outDevice = "/dev/stdout", + const char* inDevice = "/dev/stdin") { + open(outDevice, inDevice); + } + + ~FileStream() { + in.close(); + out.close(); + } + + void open(const char* outDevice, const char* inDevice) { + if (outDevice != nullptr) out.open(outDevice, std::ios::out); + if (inDevice != nullptr) in.open(inDevice, std::ios::in); + } + + virtual void begin(int speed) { + // nothing to be done + } + + virtual void print(const char* str) { + out << str; + out.flush(); + } + + virtual void println(const char* str = "") { + out << str << "\n"; + out.flush(); + } + + virtual void print(int str) { + out << str; + out.flush(); + } + + virtual void println(int str) { + out << str << "\n"; + out.flush(); + } + + virtual void flush() { out.flush(); } + + virtual void write(const char* str, int len) { out.write(str, len); } + + virtual void write(uint8_t* str, int len) { + out.write((const char*)str, len); + } + + virtual size_t write(int32_t value) { + out.put(value); + return 1; + } + + virtual size_t write(uint8_t value) { + out.put(value); + return 1; + } + + virtual int available() { return in.rdbuf()->in_avail(); }; + + virtual int read() { return in.get(); } + + virtual int peek() { return in.peek(); } + + protected: + std::fstream out; + std::fstream in; }; /** * @brief Global Serial1 instance for secondary serial communication. * - * This object provides access to the /dev/ttyACM0 device, typically used for USB serial or secondary UART on Linux systems. - * Use this instance in your sketches to perform serial communication, similar to the standard Arduino Serial1 object. - * Example: - * Serial1.begin(9600); - * Serial1.println("Hello from Serial1"); + * This object provides access to the /dev/ttyACM0 device, typically used for + * USB serial or secondary UART on Linux systems. Use this instance in your + * sketches to perform serial communication, similar to the standard Arduino + * Serial1 object. Example: Serial1.begin(9600); Serial1.println("Hello from + * Serial1"); */ static FileStream Serial1("/dev/ttyACM0"); - -} +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/GPIOWrapper.cpp b/ArduinoCore-Linux/cores/arduino/GPIOWrapper.cpp new file mode 100644 index 0000000..56f2d3e --- /dev/null +++ b/ArduinoCore-Linux/cores/arduino/GPIOWrapper.cpp @@ -0,0 +1,93 @@ +#include "GPIOWrapper.h" + +#include "HardwareGPIO.h" +#include "HardwareService.h" + +/** + * We support different implementations for the GPIO + */ + +namespace arduino { + +void GPIOWrapper::pinMode(pin_size_t pinNumber, PinMode pinMode) { + HardwareGPIO* gpio = getGPIO(); + if (gpio != nullptr) { + gpio->pinMode(pinNumber, pinMode); + } +} + +void GPIOWrapper::digitalWrite(pin_size_t pinNumber, PinStatus status) { + HardwareGPIO* gpio = getGPIO(); + if (gpio != nullptr) { + gpio->digitalWrite(pinNumber, status); + } +} + +PinStatus GPIOWrapper::digitalRead(pin_size_t pinNumber) { + HardwareGPIO* gpio = getGPIO(); + if (gpio != nullptr) { + return gpio->digitalRead(pinNumber); + } else { + return LOW; + } +} + +int GPIOWrapper::analogRead(pin_size_t pinNumber) { + HardwareGPIO* gpio = getGPIO(); + if (gpio != nullptr) { + return gpio->analogRead(pinNumber); + } else { + return 0; + } +} + +void GPIOWrapper::analogReference(uint8_t mode) { + HardwareGPIO* gpio = getGPIO(); + if (gpio != nullptr) { + gpio->analogReference(mode); + } +} + +void GPIOWrapper::analogWrite(pin_size_t pinNumber, int value) { + HardwareGPIO* gpio = getGPIO(); + if (gpio != nullptr) { + gpio->analogWrite(pinNumber, value); + } +} + +void GPIOWrapper::tone(uint8_t _pin, unsigned int frequency, + unsigned long duration) { + HardwareGPIO* gpio = getGPIO(); + if (gpio != nullptr) { + gpio->tone(_pin, frequency, duration); + } +} + +void GPIOWrapper::noTone(uint8_t _pin) { + HardwareGPIO* gpio = getGPIO(); + if (gpio != nullptr) { + gpio->noTone(_pin); + } +} + +unsigned long GPIOWrapper::pulseIn(uint8_t pin, uint8_t state, + unsigned long timeout) { + HardwareGPIO* gpio = getGPIO(); + if (gpio != nullptr) { + return gpio->pulseIn(pin, state, timeout); + } else { + return 0; + } +} + +unsigned long GPIOWrapper::pulseInLong(uint8_t pin, uint8_t state, + unsigned long timeout) { + HardwareGPIO* gpio = getGPIO(); + if (gpio != nullptr) { + return gpio->pulseInLong(pin, state, timeout); + } else { + return 0; + } +} + +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/GPIOWrapper.h b/ArduinoCore-Linux/cores/arduino/GPIOWrapper.h new file mode 100644 index 0000000..a4f9b9b --- /dev/null +++ b/ArduinoCore-Linux/cores/arduino/GPIOWrapper.h @@ -0,0 +1,81 @@ +#pragma once +#include "HardwareGPIO.h" +#include "HardwareService.h" +#include "Sources.h" + +namespace arduino { + +/** + * @brief GPIO wrapper class that provides flexible hardware abstraction + * + * GPIOWrapper is a concrete implementation of the HardwareGPIO interface that + * supports multiple delegation patterns for GPIO operations. It can delegate + * operations to: + * - An injected HardwareGPIO implementation + * - A GPIOSource provider that supplies the GPIO implementation + * - A default fallback implementation + * + * This class implements the complete GPIO interface including: + * - Digital I/O operations (pinMode, digitalWrite, digitalRead) + * - Analog I/O operations (analogRead, analogWrite, analogReference) + * - PWM and tone generation (analogWrite, tone, noTone) + * - Pulse measurement and timing functions (pulseIn, pulseInLong) + * - Pin mode configuration for input, output, and special modes + * + * The wrapper automatically handles null safety and provides appropriate + * default return values when no underlying GPIO implementation is available. It + * supports all standard Arduino GPIO operations with hardware abstraction. + * + * A global `GPIO` instance is automatically provided for system-wide GPIO + * access. + * + * @see HardwareGPIO + * @see GPIOSource + */ +class GPIOWrapper : public HardwareGPIO { + public: + GPIOWrapper() = default; + GPIOWrapper(GPIOSource& source) { setSource(&source); } + GPIOWrapper(HardwareGPIO& gpio) { setGPIO(&gpio); } + ~GPIOWrapper() = default; + void pinMode(pin_size_t pinNumber, PinMode pinMode); + void digitalWrite(pin_size_t pinNumber, PinStatus status); + PinStatus digitalRead(pin_size_t pinNumber); + int analogRead(pin_size_t pinNumber); + void analogReference(uint8_t mode); + void analogWrite(pin_size_t pinNumber, int value); + void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); + void noTone(uint8_t _pin); + unsigned long pulseIn(uint8_t pin, uint8_t state, + unsigned long timeout = 1000000L); + unsigned long pulseInLong(uint8_t pin, uint8_t state, + unsigned long timeout = 1000000L); + + /// defines the gpio implementation: use nullptr to reset. + void setGPIO(HardwareGPIO* gpio) { + p_gpio = gpio; + p_source = nullptr; + } + /// alternatively defines a class that provides the GPIO implementation + void setSource(GPIOSource* source) { + p_source = source; + p_gpio = nullptr; + } + + protected: + HardwareGPIO* p_gpio = nullptr; + GPIOSource* p_source = nullptr; + + HardwareGPIO* getGPIO() { + HardwareGPIO* result = p_gpio; + if (result == nullptr && p_source != nullptr) { + result = p_source->getGPIO(); + } + return result; + } +}; + +/// Global GPIO instance used by Arduino API functions and direct access +static GPIOWrapper GPIO; + +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/Hardware.h b/ArduinoCore-Linux/cores/arduino/Hardware.h deleted file mode 100644 index 5fa2f38..0000000 --- a/ArduinoCore-Linux/cores/arduino/Hardware.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -namespace arduino { - -// forware declarations for references -class HardwareI2C; -class HardwareSPI; -class HardwareGPIO; - -/** - * Class which is used to represent the actual implementation which is used to - * drive the specific interface - **/ -struct HardwareImpl { - HardwareImpl() = default; - HardwareGPIO* gpio = nullptr; - HardwareI2C* i2c = nullptr; - HardwareSPI* spi = nullptr; -}; - -static HardwareImpl Hardware; - -} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/HardwareGPIO.cpp b/ArduinoCore-Linux/cores/arduino/HardwareGPIO.cpp deleted file mode 100644 index 828a202..0000000 --- a/ArduinoCore-Linux/cores/arduino/HardwareGPIO.cpp +++ /dev/null @@ -1,87 +0,0 @@ - -#include "api/Common.h" -#include "Hardware.h" -#include "HardwareGPIO.h" -#include "HardwareService.h" - -/** - * We support different implementations for GPIO. These are the implementations for the public - * methods defined by Common.h - **/ -namespace arduino { - -void pinMode(pin_size_t pinNumber, PinMode pinMode){ - if (Hardware.gpio != nullptr) { - Hardware.gpio->pinMode(pinNumber,pinMode); - } -} - -void digitalWrite(pin_size_t pinNumber, PinStatus status){ - if (Hardware.gpio != nullptr) { - Hardware.gpio->digitalWrite(pinNumber, status); - } -} - -PinStatus digitalRead(pin_size_t pinNumber){ - if (Hardware.gpio != nullptr) { - return Hardware.gpio->digitalRead(pinNumber); - } else { - return HIGH; // return high, simulate weak pullup - } -} - -int analogRead(pin_size_t pinNumber){ - if (Hardware.gpio != nullptr) { - return Hardware.gpio->analogRead(pinNumber); - } else { - return 0; - } -} - -void analogReference(uint8_t mode){ - if (Hardware.gpio != nullptr) { - Hardware.gpio->analogReference(mode); - } -} - -void analogWrite(pin_size_t pinNumber, int value){ - if (Hardware.gpio != nullptr) { - Hardware.gpio->analogWrite(pinNumber, value); - } -} - - -// Generates a square wave of the specified frequency (and 50% duty cycle) on a pin -void tone(uint8_t pinNumber, unsigned int frequency, unsigned long duration = 0){ - if (Hardware.gpio != nullptr) { - Hardware.gpio->tone(pinNumber, frequency, duration); - } -} - -// Stops the generation of a square wave triggered by tone() -void noTone(uint8_t pinNumber){ - if (Hardware.gpio != nullptr) { - Hardware.gpio->noTone(pinNumber); - } -} - -/// Reads a pulse (either HIGH or LOW) on a pin -unsigned long pulseIn(uint8_t pinNumber, uint8_t state, unsigned long timeout = 1000000L){ - if (Hardware.gpio != nullptr) { - return Hardware.gpio->pulseIn(pinNumber, state, timeout); - } else { - return 0; - } -} - -/// Reads a pulse (either HIGH or LOW) on a pin -unsigned long pulseInLong(uint8_t pinNumber, uint8_t state, unsigned long timeout = 1000000L){ - if (Hardware.gpio != nullptr) { - return Hardware.gpio->pulseInLong(pinNumber, state, timeout); - } else { - return 0; - } -} - - -} diff --git a/ArduinoCore-Linux/cores/arduino/HardwareGPIO.h b/ArduinoCore-Linux/cores/arduino/HardwareGPIO.h index 9893f85..02a39c5 100644 --- a/ArduinoCore-Linux/cores/arduino/HardwareGPIO.h +++ b/ArduinoCore-Linux/cores/arduino/HardwareGPIO.h @@ -1,29 +1,27 @@ #pragma once -#include "api/Common.h" +#include "api/Common.h" namespace arduino { - + /** - * Base class for GPIO functions + * Abstract base class for GPIO functions **/ class HardwareGPIO { - public: - HardwareGPIO(){}; - virtual ~HardwareGPIO(){}; - virtual void pinMode(pin_size_t pinNumber, PinMode pinMode){}; - virtual void digitalWrite(pin_size_t pinNumber, PinStatus status){}; - virtual PinStatus digitalRead(pin_size_t pinNumber){return LOW;}; - virtual int analogRead(pin_size_t pinNumber){return -1;}; - virtual void analogReference(uint8_t mode){}; - virtual void analogWrite(pin_size_t pinNumber, int value){}; - virtual void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0){}; - virtual void noTone(uint8_t _pin){}; - virtual unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L) {return -1;}; - virtual unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L) {return -1;}; - -}; + public: + HardwareGPIO() = default; + virtual ~HardwareGPIO() = default; + virtual void pinMode(pin_size_t pinNumber, PinMode pinMode) = 0; + virtual void digitalWrite(pin_size_t pinNumber, PinStatus status) = 0; + virtual PinStatus digitalRead(pin_size_t pinNumber) = 0; + virtual int analogRead(pin_size_t pinNumber) = 0; + virtual void analogReference(uint8_t mode) = 0; + virtual void analogWrite(pin_size_t pinNumber, int value) = 0; + virtual void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0) = 0; + virtual void noTone(uint8_t _pin) = 0; + virtual unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L) = 0; + virtual unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L) = 0; +}; -} - +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/HardwareI2CEx.cpp b/ArduinoCore-Linux/cores/arduino/HardwareI2CEx.cpp deleted file mode 100644 index a1a393c..0000000 --- a/ArduinoCore-Linux/cores/arduino/HardwareI2CEx.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "Hardware.h" -#include "HardwareI2CEx.h" -#include "HardwareService.h" -/** - * We suppport different implementations for the I2C - **/ - -namespace arduino { - - -void HardwareI2CEx::begin() { - if (Hardware.i2c != nullptr) { - Hardware.i2c->begin(); - } -} - -void HardwareI2CEx::begin(uint8_t address) { - if (Hardware.i2c != nullptr) { - Hardware.i2c->begin(address); - } -} - -void HardwareI2CEx::end(){ - if (Hardware.i2c != nullptr) { - Hardware.i2c->end(); - } -} - -void HardwareI2CEx::setClock(uint32_t freq){ - if (Hardware.i2c != nullptr) { - Hardware.i2c->setClock(freq); - } -} - -void HardwareI2CEx::beginTransmission(uint8_t address){ - if (Hardware.i2c != nullptr) { - Hardware.i2c->beginTransmission(address); - } -} - -uint8_t HardwareI2CEx::endTransmission(bool stopBit){ - if (Hardware.i2c != nullptr) { - return Hardware.i2c->endTransmission(stopBit); - } else { - return 0; - } -} - -uint8_t HardwareI2CEx::endTransmission(void){ - if (Hardware.i2c != nullptr) { - return Hardware.i2c->endTransmission(); - } else { - return 0; - } -} - -size_t HardwareI2CEx::requestFrom(uint8_t address, size_t len, bool stopBit){ - if (Hardware.i2c != nullptr) { - return Hardware.i2c->requestFrom(address,len,stopBit); - } else { - return 0; - } -} - -size_t HardwareI2CEx::requestFrom(uint8_t address, size_t len){ - if (Hardware.i2c != nullptr) { - return Hardware.i2c->requestFrom(address,len); - } else { - return 0; - } -} - - -void HardwareI2CEx::onReceive(void(*)(int)){ -} - -void HardwareI2CEx::onRequest(void(*)(void)){ -} - -} \ No newline at end of file diff --git a/ArduinoCore-Linux/cores/arduino/HardwareI2CEx.h b/ArduinoCore-Linux/cores/arduino/HardwareI2CEx.h deleted file mode 100644 index d77a62d..0000000 --- a/ArduinoCore-Linux/cores/arduino/HardwareI2CEx.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "api/HardwareI2C.h" - -namespace arduino { - -class HardwareI2CEx : public HardwareI2C { - public: - HardwareI2CEx(){} - virtual ~HardwareI2CEx(){}; - virtual void begin(); - virtual void begin(uint8_t address); - virtual void end(); - virtual void setClock(uint32_t freq); - virtual void beginTransmission(uint8_t address); - virtual uint8_t endTransmission(bool stopBit); - virtual uint8_t endTransmission(void); - virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit); - virtual size_t requestFrom(uint8_t address, size_t len); - virtual void onReceive(void(*)(int)) = 0; - virtual void onRequest(void(*)(void)) = 0; -}; - -} - diff --git a/ArduinoCore-Linux/cores/arduino/HardwareSPI.cpp b/ArduinoCore-Linux/cores/arduino/HardwareSPI.cpp deleted file mode 100644 index 57da951..0000000 --- a/ArduinoCore-Linux/cores/arduino/HardwareSPI.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "api/HardwareSPI.h" -#include "HardwareService.h" -#include "Hardware.h" -/** - * We suppport different implementations for the SPI - * - **/ - -namespace arduino { - -uint8_t HardwareSPI::transfer(uint8_t data) { - if (Hardware.spi != nullptr) { - return Hardware.spi->transfer(data); - } else { - return 0; - } -} - -uint16_t HardwareSPI::transfer16(uint16_t data) { - if (Hardware.spi != nullptr) { - return Hardware.spi->transfer16(data); - } else { - return 0; - } -} - -void HardwareSPI::transfer(void *data, size_t count) { - if (Hardware.spi != nullptr) { - Hardware.spi->transfer(data, count); - } -} - -void HardwareSPI::usingInterrupt(int interruptNumber) { - if (Hardware.spi != nullptr) { - Hardware.spi->usingInterrupt(interruptNumber); - } -} - -void HardwareSPI::notUsingInterrupt(int interruptNumber){ - if (Hardware.spi != nullptr) { - Hardware.spi->notUsingInterrupt(interruptNumber); - } -} - -void HardwareSPI::beginTransaction(SPISettings settings){ - if (Hardware.spi != nullptr) { - Hardware.spi->beginTransaction(settings); - } -} - -void HardwareSPI::endTransaction(void){ - if (Hardware.spi != nullptr) { - Hardware.spi->endTransaction(); - } -} - -void HardwareSPI::attachInterrupt() { - if (Hardware.spi != nullptr) { - Hardware.spi->attachInterrupt(); - } -} - -void HardwareSPI::detachInterrupt(){ - if (Hardware.spi != nullptr) { - Hardware.spi->detachInterrupt(); - } -} - -void HardwareSPI::begin() { - if (Hardware.spi != nullptr) { - Hardware.spi->begin(); - } -} - -void HardwareSPI::end() { - if (Hardware.spi != nullptr) { - Hardware.spi->end(); - } -} - - -} \ No newline at end of file diff --git a/ArduinoCore-Linux/cores/arduino/HardwareService.h b/ArduinoCore-Linux/cores/arduino/HardwareService.h index be3c6e4..c037d75 100644 --- a/ArduinoCore-Linux/cores/arduino/HardwareService.h +++ b/ArduinoCore-Linux/cores/arduino/HardwareService.h @@ -11,213 +11,208 @@ namespace arduino { **/ enum HWCalls { - I2cBegin0, - I2cBegin1, - I2cEnd, - I2cSetClock, - I2cBeginTransmission, - I2cEndTransmission1, - I2cEndTransmission, - I2cRequestFrom3, - I2cRequestFrom2, - I2cOnReceive, - I2cOnRequest, - I2cWrite, - I2cAvailable, - I2cRead, - I2cPeek, - SpiTransfer, - SpiTransfer8, - SpiTransfer16, - SpiUsingInterrupt, - SpiNotUsingInterrupt, - SpiBeginTransaction, - SpiEndTransaction, - SpiAttachInterrupt, - SpiDetachInterrupt, - SpiBegin, - SpiEnd, - GpioPinMode, - GpioDigitalWrite, - GpioDigitalRead, - GpioAnalogRead, - GpioAnalogReference, - GpioAnalogWrite, - GpioTone, - GpioNoTone, - GpioPulseIn, - GpioPulseInLong, - SerialBegin, - SerialEnd, - SerialWrite, - SerialRead, - SerialAvailable, - SerialPeek, - SerialFlush, - I2sSetup, - I2sBegin3, - I2sBegin2, - I2sEnd, - I2sAvailable, - I2sRead, - I2sPeek, - I2sFlush, - I2sWrite, - I2sAvailableForWrite, - I2sSetBufferSize + I2cBegin0, + I2cBegin1, + I2cEnd, + I2cSetClock, + I2cBeginTransmission, + I2cEndTransmission1, + I2cEndTransmission, + I2cRequestFrom3, + I2cRequestFrom2, + I2cOnReceive, + I2cOnRequest, + I2cWrite, + I2cAvailable, + I2cRead, + I2cPeek, + SpiTransfer, + SpiTransfer8, + SpiTransfer16, + SpiUsingInterrupt, + SpiNotUsingInterrupt, + SpiBeginTransaction, + SpiEndTransaction, + SpiAttachInterrupt, + SpiDetachInterrupt, + SpiBegin, + SpiEnd, + GpioPinMode, + GpioDigitalWrite, + GpioDigitalRead, + GpioAnalogRead, + GpioAnalogReference, + GpioAnalogWrite, + GpioTone, + GpioNoTone, + GpioPulseIn, + GpioPulseInLong, + SerialBegin, + SerialEnd, + SerialWrite, + SerialRead, + SerialAvailable, + SerialPeek, + SerialFlush, + I2sSetup, + I2sBegin3, + I2sBegin2, + I2sEnd, + I2sAvailable, + I2sRead, + I2sPeek, + I2sFlush, + I2sWrite, + I2sAvailableForWrite, + I2sSetBufferSize }; /** - * Stream over which we tunnel the SPI, I2C, I2S and GPIO messages. Since most embedded divices - * are little endian we communicate in little endian! - * + * Stream over which we tunnel the SPI, I2C, I2S and GPIO messages. Since most + * embedded divices are little endian we communicate in little endian! **/ - -class HardwareService { - - public: - HardwareService(){ - } - - HardwareService(void *str){ - setStream((Stream*)str); - } - - void setStream(Stream *str){ - io = str; - } - - void send(HWCalls call){ - uint16_t val = (uint16_t) call; - io->write((uint8_t*)&val,sizeof(uint16_t)); - } - - void send(uint8_t data){ - io->write((uint8_t*)&data,sizeof(data)); - } - - void send(uint16_t dataIn){ - uint16_t data = swap_uint16(dataIn); - io->write((uint8_t*)&data,sizeof(data)); - } - - void send(uint32_t dataIn){ - uint32_t data = swap_uint32(dataIn); - io->write((uint8_t*)&data,sizeof(data)); - } - - void send(uint64_t dataIn){ - uint32_t data = swap_uint64(dataIn); - io->write((uint8_t*)&data,sizeof(data)); - } - - void send(int32_t dataIn){ - int32_t data = swap_int32(dataIn); - io->write((uint8_t*)&data,sizeof(data)); - - } - void send(int64_t dataIn){ - int32_t data = swap_int64(dataIn); - io->write((uint8_t*)&data,sizeof(data)); - } - - void send(bool data){ - io->write((uint8_t*)&data,sizeof(data)); - } - - void send(void *data, size_t len){ - io->write((uint8_t*)data, len); - } - - void flush() { - io->flush(); - } - - uint16_t receive16(){ - uint16_t result; - io->readBytes((char*)&result, sizeof(uint16_t)); - return swap_uint16(result); - } - - uint32_t receive32(){ - uint16_t result; - io->readBytes((char*)&result, sizeof(uint32_t)); - return swap_uint32(result); - } - - uint64_t receive64(){ - uint16_t result; - io->readBytes((char*)&result, sizeof(uint64_t)); - return swap_uint64(result); - } - - uint8_t receive8(){ - uint8_t result; - io->readBytes((char*)&result, sizeof(uint8_t)); - return result; - } - - uint16_t receive(void* data, int len){ - return io->readBytes((char*)data,len); - } - - protected: - Stream *io; - bool isLittleEndian = !is_big_endian(); - - // check if the system is big endian - bool is_big_endian(void){ - union { - uint32_t i; - char c[4]; - } bint = {0x01020304}; - - return bint.c[0] == 1; - } - - - //! Byte swap unsigned short - uint16_t swap_uint16( uint16_t val ) { - if (isLittleEndian) return val; - return (val << 8) | (val >> 8 ); - } - - //! Byte swap short - int16_t swap_int16( int16_t val ) { - if (isLittleEndian) return val; - return (val << 8) | ((val >> 8) & 0xFF); - } - - //! Byte swap unsigned int - uint32_t swap_uint32( uint32_t val ){ - if (isLittleEndian) return val; - val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF ); - return (val << 16) | (val >> 16); - } - //! Byte swap int - int32_t swap_int32( int32_t val ){ - if (isLittleEndian) return val; - val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF ); - return (val << 16) | ((val >> 16) & 0xFFFF); - } - - int64_t swap_int64( int64_t val ){ - if (isLittleEndian) return val; - val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL ); - val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL ); - return (val << 32) | ((val >> 32) & 0xFFFFFFFFULL); - } - - uint64_t swap_uint64( uint64_t val ){ - if (isLittleEndian) return val; - val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL ); - val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL ); - return (val << 32) | (val >> 32); - } - +class HardwareService { + public: + HardwareService() {} + + void setStream(Stream* str) { io = str; } + + void send(HWCalls call) { + uint16_t val = (uint16_t)call; + io->write((uint8_t*)&val, sizeof(uint16_t)); + } + + void send(uint8_t data) { io->write((uint8_t*)&data, sizeof(data)); } + + void send(uint16_t dataIn) { + uint16_t data = swap_uint16(dataIn); + io->write((uint8_t*)&data, sizeof(data)); + } + + void send(uint32_t dataIn) { + uint32_t data = swap_uint32(dataIn); + io->write((uint8_t*)&data, sizeof(data)); + } + + void send(uint64_t dataIn) { + uint32_t data = swap_uint64(dataIn); + io->write((uint8_t*)&data, sizeof(data)); + } + + void send(int32_t dataIn) { + int32_t data = swap_int32(dataIn); + io->write((uint8_t*)&data, sizeof(data)); + } + void send(int64_t dataIn) { + int32_t data = swap_int64(dataIn); + io->write((uint8_t*)&data, sizeof(data)); + } + + void send(bool data) { io->write((uint8_t*)&data, sizeof(data)); } + + void send(void* data, size_t len) { io->write((uint8_t*)data, len); } + + void flush() { io->flush(); } + + uint16_t receive16() { + uint16_t result; + blockingRead((char*)&result, sizeof(uint16_t)); + return swap_uint16(result); + } + + uint32_t receive32() { + uint32_t result; + blockingRead((char*)&result, sizeof(uint32_t)); + return swap_uint32(result); + } + + uint64_t receive64() { + uint64_t result; + blockingRead((char*)&result, sizeof(uint64_t)); + return swap_uint64(result); + } + + uint8_t receive8() { + uint8_t result; + blockingRead((char*)&result, sizeof(uint8_t)); + return result; + } + + uint16_t receive(void* data, int len) { + return blockingRead((char*)data, len); + } + + operator boolean() { return io != nullptr; } + + protected: + Stream* io = nullptr; + bool isLittleEndian = !is_big_endian(); + int timeout_ms = 1000; + + uint16_t blockingRead(void* data, int len, int timeout = 1000) { + int offset = 0; + long start = millis(); + while (offset < len && (millis() - start) < timeout) { + int n = io->readBytes((char*)data + offset, len - offset); + offset += n; + } + return offset; + } + + // check if the system is big endian + bool is_big_endian(void) { + union { + uint32_t i; + char c[4]; + } bint = {0x01020304}; + + return bint.c[0] == 1; + } + + //! Byte swap unsigned short + uint16_t swap_uint16(uint16_t val) { + if (isLittleEndian) return val; + return (val << 8) | (val >> 8); + } + + //! Byte swap short + int16_t swap_int16(int16_t val) { + if (isLittleEndian) return val; + return (val << 8) | ((val >> 8) & 0xFF); + } + + //! Byte swap unsigned int + uint32_t swap_uint32(uint32_t val) { + if (isLittleEndian) return val; + val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF); + return (val << 16) | (val >> 16); + } + + //! Byte swap int + int32_t swap_int32(int32_t val) { + if (isLittleEndian) return val; + val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF); + return (val << 16) | ((val >> 16) & 0xFFFF); + } + + int64_t swap_int64(int64_t val) { + if (isLittleEndian) return val; + val = ((val << 8) & 0xFF00FF00FF00FF00ULL) | + ((val >> 8) & 0x00FF00FF00FF00FFULL); + val = ((val << 16) & 0xFFFF0000FFFF0000ULL) | + ((val >> 16) & 0x0000FFFF0000FFFFULL); + return (val << 32) | ((val >> 32) & 0xFFFFFFFFULL); + } + + uint64_t swap_uint64(uint64_t val) { + if (isLittleEndian) return val; + val = ((val << 8) & 0xFF00FF00FF00FF00ULL) | + ((val >> 8) & 0x00FF00FF00FF00FFULL); + val = ((val << 16) & 0xFFFF0000FFFF0000ULL) | + ((val >> 16) & 0x0000FFFF0000FFFFULL); + return (val << 32) | (val >> 32); + } }; -} - - +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/HardwareSetupRemote.h b/ArduinoCore-Linux/cores/arduino/HardwareSetupRemote.h index 7d3c11b..3d1788d 100644 --- a/ArduinoCore-Linux/cores/arduino/HardwareSetupRemote.h +++ b/ArduinoCore-Linux/cores/arduino/HardwareSetupRemote.h @@ -3,68 +3,63 @@ #include #include "ArduinoLogger.h" -#include "Hardware.h" +#include "GPIOWrapper.h" +#include "I2CWrapper.h" #include "RemoteGPIO.h" #include "RemoteI2C.h" #include "RemoteSPI.h" +#include "SPIWrapper.h" #include "WiFiUdpStream.h" namespace arduino { -#if !defined(SKIP_HARDWARE_SETUP) && !defined(USE_RPI) -static RemoteI2C Wire; -static RemoteSPI SPI; -#endif /** * Class which is used to configure the actual Hardware APIs */ -class HardwareSetupRemoteClass { +class HardwareSetupRemoteClass : public I2CSource, + public SPISource, + public GPIOSource { public: /// default constructor: you need to call begin() afterwards HardwareSetupRemoteClass() = default; /// HardwareSetup uses the indicated stream - HardwareSetupRemoteClass(Stream& stream) { - begin(&stream, false); - } + HardwareSetupRemoteClass(Stream& stream) { begin(&stream, false); } - /// HardwareSetup that uses udp - HardwareSetupRemoteClass(int port) { - this->port = port; - } + /// HardwareSetup that uses udp + HardwareSetupRemoteClass(int port) { this->port = port; } /// assigns the different protocols to the stream - void begin(Stream* s, bool doHandShake = true) { + bool begin(Stream* s, bool asDefault = true, bool doHandShake = true) { p_stream = s; - Hardware.i2c = &i2c; - Hardware.spi = &spi; - Hardware.gpio = &gpio; - i2c.setStream(s); spi.setStream(s); gpio.setStream(s); - #if !defined(SKIP_HARDWARE_SETUP) && !defined(USE_RPI) // setup global objects - SPI = spi; - Wire = i2c; - #endif + if (asDefault) { + SPI.setSPI(&spi); + Wire.setI2C(&i2c); + GPIO.setGPIO(&gpio); + } if (doHandShake) { handShake(s); } + return i2c && spi && gpio; } /// start with udp on the indicatd port - void begin(int port){ + void begin(int port, bool asDefault) { this->port = port; - begin(); + begin(asDefault); } /// start with the default udp stream. - void begin() { + void begin(bool asDefault = true) { + is_default_objects_active = asDefault; if (p_stream == nullptr) { default_stream.begin(port); handShake(&default_stream); @@ -73,32 +68,35 @@ class HardwareSetupRemoteClass { default_stream.setTarget(ip, remote_port); default_stream.write((const uint8_t*)"OK", 2); default_stream.flush(); - begin(&default_stream, false); + begin(&default_stream, asDefault, false); } else { - begin(p_stream, true); + begin(p_stream, asDefault, true); } } void end() { + if (is_default_objects_active) { + GPIO.setGPIO(nullptr); + SPI.setSPI(nullptr); + Wire.setI2C(nullptr); + } if (p_stream == &default_stream) { default_stream.stop(); } - Hardware.i2c = nullptr; - Hardware.spi = nullptr; - Hardware.gpio = nullptr; } - auto& get_gpio() { return gpio; } - auto& get_i2c() { return i2c; } - auto& get_spi() { return spi; } + HardwareGPIO* getGPIO() { return &gpio; } + HardwareI2C* getI2C() { return &i2c; } + HardwareSPI* getSPI() { return &spi; } protected: WiFiUDPStream default_stream; - Stream *p_stream = nullptr; + Stream* p_stream = nullptr; RemoteI2C i2c; RemoteSPI spi; RemoteGPIO gpio; int port; + bool is_default_objects_active = false; void handShake(Stream* s) { while (true) { @@ -125,6 +123,7 @@ class HardwareSetupRemoteClass { }; #if !defined(SKIP_HARDWARE_SETUP) -static HardwareSetupRemoteClass HardwareSetupRemote{7000}; +static HardwareSetupRemoteClass Remote{7000}; #endif + } // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/I2CWrapper.cpp b/ArduinoCore-Linux/cores/arduino/I2CWrapper.cpp new file mode 100644 index 0000000..dfb07a4 --- /dev/null +++ b/ArduinoCore-Linux/cores/arduino/I2CWrapper.cpp @@ -0,0 +1,119 @@ +#include "I2CWrapper.h" +/** + * We suppport different implementations for the I2C + **/ + +namespace arduino { + +void I2CWrapper::begin() { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + i2c->begin(); + } +} + +void I2CWrapper::begin(uint8_t address) { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + i2c->begin(address); + } +} + +void I2CWrapper::end() { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + i2c->end(); + } +} + +void I2CWrapper::setClock(uint32_t freq) { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + i2c->setClock(freq); + } +} + +void I2CWrapper::beginTransmission(uint8_t address) { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + i2c->beginTransmission(address); + } +} + +uint8_t I2CWrapper::endTransmission(bool stopBit) { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + return i2c->endTransmission(stopBit); + } else { + return 0; + } +} + +uint8_t I2CWrapper::endTransmission(void) { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + return i2c->endTransmission(); + } else { + return 0; + } +} + +size_t I2CWrapper::requestFrom(uint8_t address, size_t len, bool stopBit) { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + return i2c->requestFrom(address, len, stopBit); + } else { + return 0; + } +} + +size_t I2CWrapper::requestFrom(uint8_t address, size_t len) { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + return i2c->requestFrom(address, len); + } else { + return 0; + } +} + +void I2CWrapper::onReceive(void (*)(int)) {} + +void I2CWrapper::onRequest(void (*)(void)) {} + +size_t I2CWrapper::write(uint8_t data) { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + return i2c->write(data); + } else { + return 0; + } +} + +int I2CWrapper::available() { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + return i2c->available(); + } else { + return 0; + } +} + +int I2CWrapper::read() { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + return i2c->read(); + } else { + return -1; + } +} + +int I2CWrapper::peek() { + HardwareI2C* i2c = getI2C(); + if (i2c != nullptr) { + return i2c->peek(); + } else { + return -1; + } +} + +} // namespace arduino \ No newline at end of file diff --git a/ArduinoCore-Linux/cores/arduino/I2CWrapper.h b/ArduinoCore-Linux/cores/arduino/I2CWrapper.h new file mode 100644 index 0000000..2f0057b --- /dev/null +++ b/ArduinoCore-Linux/cores/arduino/I2CWrapper.h @@ -0,0 +1,85 @@ +#pragma once + +#include "Sources.h" +#include "api/HardwareI2C.h" + +namespace arduino { + +/** + * @brief I2C wrapper class that provides flexible hardware abstraction + * + * I2CWrapper is a concrete implementation of the HardwareI2C interface that + * supports multiple delegation patterns for I2C communication. It can delegate + * operations to: + * - An injected HardwareI2C implementation + * - An I2CSource provider that supplies the I2C implementation + * - A default fallback implementation + * + * This class implements the complete I2C interface including: + * - Master/slave mode initialization and control + * - Data transmission and reception methods + * - Stream-like read/write operations with buffering + * - Callback registration for slave mode operations + * - Clock frequency configuration + * + * The wrapper automatically handles null safety and provides appropriate + * default return values when no underlying I2C implementation is available. + * + * A global `Wire` instance is automatically provided for Arduino compatibility. + * + * @see HardwareI2C + * @see I2CSource + */ +class I2CWrapper : public HardwareI2C { + public: + I2CWrapper() = default; + I2CWrapper(I2CSource& source) { setSource(&source); } + I2CWrapper(HardwareI2C& i2c) { setI2C(&i2c); } + ~I2CWrapper() = default; + void begin(); + void begin(uint8_t address); + void end(); + void setClock(uint32_t freq); + void beginTransmission(uint8_t address); + uint8_t endTransmission(bool stopBit); + uint8_t endTransmission(void); + size_t requestFrom(uint8_t address, size_t len, bool stopBit); + size_t requestFrom(uint8_t address, size_t len); + void onReceive(void (*)(int)); + void onRequest(void (*)(void)); + size_t write(uint8_t); + int available(); + int read(); + int peek(); + + /// defines the i2c implementation: use nullptr to reset. + void setI2C(HardwareI2C* i2c) { + p_i2c = i2c; + p_source = nullptr; + } + /// alternatively defines a class that provides the I2C implementation + void setSource(I2CSource* source) { + p_source = source; + p_i2c = nullptr; + } + + protected: + HardwareI2C* p_i2c = nullptr; + I2CSource* p_source = nullptr; + + HardwareI2C* getI2C() { + HardwareI2C* result = p_i2c; + if (result == nullptr) { + result = p_source->getI2C(); + } + return result; + } +}; + +/// Global Wire instance used by Arduino API functions and direct access +static I2CWrapper Wire; + +/// Type alias for Arduino compatibility - TwoWire refers to I2CWrapper +using TwoWire = I2CWrapper; + +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/Main.cpp b/ArduinoCore-Linux/cores/arduino/Main.cpp index d17f27a..cd58115 100644 --- a/ArduinoCore-Linux/cores/arduino/Main.cpp +++ b/ArduinoCore-Linux/cores/arduino/Main.cpp @@ -11,11 +11,12 @@ __attribute__((weak)) void loop() {} void hardwareSetup(){ #if !defined(SKIP_HARDWARE_SETUP) -# if defined(USE_REMOTE) - HardwareSetupRemote.begin(); -# endif # if (defined(USE_RPI)) RPI.begin(); +# else +# if defined(USE_REMOTE) + Remote.begin(); +# endif # endif #endif } diff --git a/ArduinoCore-Linux/cores/arduino/RemoteGPIO.h b/ArduinoCore-Linux/cores/arduino/RemoteGPIO.h index d4ab0e4..2736622 100644 --- a/ArduinoCore-Linux/cores/arduino/RemoteGPIO.h +++ b/ArduinoCore-Linux/cores/arduino/RemoteGPIO.h @@ -5,6 +5,30 @@ namespace arduino { +/** + * @brief Remote GPIO implementation that operates over a communication stream + * + * RemoteGPIO provides GPIO functionality by forwarding all operations to a remote + * GPIO controller via a communication stream (serial, network, etc.). This enables + * GPIO operations to be performed on remote hardware while maintaining the standard + * HardwareGPIO interface. + * + * Key features: + * - Complete HardwareGPIO interface implementation + * - Stream-based remote communication protocol + * - Digital I/O operations (pinMode, digitalWrite, digitalRead) + * - Analog I/O operations (analogRead, analogWrite, analogReference) + * - PWM and tone generation (analogWrite, tone, noTone) + * - Pulse measurement and timing functions (pulseIn, pulseInLong) + * - Real-time bidirectional communication with remote GPIO hardware + * + * The class uses HardwareService for protocol handling and can work with any + * Stream implementation (Serial, TCP, etc.) for remote connectivity. + * + * @see HardwareGPIO + * @see HardwareService + * @see Stream + */ class RemoteGPIO : public HardwareGPIO { public: RemoteGPIO() = default; @@ -87,6 +111,8 @@ class RemoteGPIO : public HardwareGPIO { return service.receive64(); } + operator boolean() { return service; } + protected: HardwareService service; }; diff --git a/ArduinoCore-Linux/cores/arduino/RemoteI2C.h b/ArduinoCore-Linux/cores/arduino/RemoteI2C.h index 35ff842..e5f3830 100644 --- a/ArduinoCore-Linux/cores/arduino/RemoteI2C.h +++ b/ArduinoCore-Linux/cores/arduino/RemoteI2C.h @@ -1,14 +1,33 @@ #pragma once - -#include "HardwareI2CEx.h" +#include "Stream.h" +#include "api/HardwareI2C.h" #include "HardwareService.h" namespace arduino { -// forware declaration of stream -class Stream; - -class RemoteI2C : public HardwareI2CEx { +/** + * @brief Remote I2C implementation that operates over a communication stream + * + * RemoteI2C provides I2C functionality by forwarding all operations to a remote + * I2C controller via a communication stream (serial, network, etc.). This enables + * I2C operations to be performed on remote hardware while maintaining the standard + * HardwareI2C interface. + * + * Key features: + * - Complete HardwareI2C interface implementation + * - Stream-based remote communication protocol + * - Automatic command serialization and response handling + * - Support for all I2C operations (master/slave, read/write, transactions) + * - Real-time bidirectional communication with remote I2C hardware + * + * The class uses HardwareService for protocol handling and can work with any + * Stream implementation (Serial, TCP, etc.) for remote connectivity. + * + * @see HardwareI2C + * @see HardwareService + * @see Stream + */ +class RemoteI2C : public HardwareI2C { public: RemoteI2C() = default; RemoteI2C(Stream* stream) { service.setStream(static_cast(stream)); } @@ -94,6 +113,8 @@ class RemoteI2C : public HardwareI2CEx { return service.receive16(); } + operator boolean() { return service; } + protected: HardwareService service; }; diff --git a/ArduinoCore-Linux/cores/arduino/RemoteSPI.h b/ArduinoCore-Linux/cores/arduino/RemoteSPI.h index b1279bf..1cdd77c 100644 --- a/ArduinoCore-Linux/cores/arduino/RemoteSPI.h +++ b/ArduinoCore-Linux/cores/arduino/RemoteSPI.h @@ -2,14 +2,32 @@ #include "api/HardwareSPI.h" -/** - * We virtualize the hardware and send the requests and replys over - * a stream. - * - **/ - namespace arduino { +/** + * @brief Remote SPI implementation that operates over a communication stream + * + * RemoteSPI provides SPI functionality by forwarding all operations to a remote + * SPI controller via a communication stream (serial, network, etc.). This enables + * SPI operations to be performed on remote hardware while maintaining the standard + * HardwareSPI interface. + * + * Key features: + * - Complete HardwareSPI interface implementation + * - Stream-based remote communication protocol + * - Support for all SPI transfer modes (8-bit, 16-bit, buffer transfers) + * - Transaction management with SPISettings support + * - Interrupt handling and configuration + * - Real-time bidirectional communication with remote SPI hardware + * + * The class uses HardwareService for protocol handling and can work with any + * Stream implementation (Serial, TCP, etc.) for remote connectivity. + * + * @see HardwareSPI + * @see HardwareService + * @see SPISettings + * @see Stream + */ class RemoteSPI : public HardwareSPI { public: RemoteSPI() = default; @@ -86,6 +104,8 @@ class RemoteSPI : public HardwareSPI { service.flush(); } + operator boolean() { return service; } + protected: HardwareService service; }; diff --git a/ArduinoCore-Linux/cores/arduino/RemoteSerial.h b/ArduinoCore-Linux/cores/arduino/RemoteSerial.h index 7b37cc7..d710507 100644 --- a/ArduinoCore-Linux/cores/arduino/RemoteSerial.h +++ b/ArduinoCore-Linux/cores/arduino/RemoteSerial.h @@ -1,139 +1,157 @@ #pragma once -#include "api/Stream.h" #include "HardwareService.h" #include "RingBufferExt.h" +#include "api/Stream.h" namespace arduino { /** - * RemoteSerialImpl shim that privodes access to a Stream on a - * remote device. Only Single character operations are buffered. + * @brief Remote Serial implementation that operates over a communication stream * - **/ - -class RemoteSerialImpl : public Stream { - public: - RemoteSerialImpl(Stream &stream, uint8_t no){ - this->no = no; - service = new HardwareService(&stream); - } - - virtual void begin(unsigned long baudrate) { - service->send(SerialBegin); - service->send(no); - service->send((uint64_t)baudrate); - service->flush(); - } + * RemoteSerialClass provides Serial/UART functionality by forwarding all operations + * to a remote Serial controller via a communication stream. This enables Serial + * communication to be performed on remote hardware while maintaining the standard + * Stream interface with buffering capabilities. + * + * Key features: + * - Complete Stream interface implementation + * - Stream-based remote communication protocol + * - Bidirectional buffering for read and write operations + * - Support for multiple serial ports via port numbering + * - Standard Serial operations (begin, end, baud rate configuration) + * - Optimized buffering for single character and bulk operations + * - Real-time bidirectional communication with remote Serial hardware + * + * The class uses HardwareService for protocol handling and maintains separate + * read and write buffers for efficient data transfer. It can work with any + * Stream implementation (Serial, TCP, etc.) for remote connectivity. + * + * @see Stream + * @see HardwareService + * @see RingBufferExt + */ +class RemoteSerialClass : public Stream { + public: + RemoteSerialClass(Stream& stream, uint8_t no) { + this->no = no; + this->service.setStream(&stream); + } - virtual void begin(unsigned long baudrate, uint16_t config) { - service->send(SerialBegin); - service->send(no); - service->send((uint64_t)baudrate); - service->flush(); - } + virtual void begin(unsigned long baudrate) { + service.send(SerialBegin); + service.send(no); + service.send((uint64_t)baudrate); + service.flush(); + } + + virtual void begin(unsigned long baudrate, uint16_t config) { + service.send(SerialBegin); + service.send(no); + service.send((uint64_t)baudrate); + service.flush(); + } + + virtual void end() { + service.send(SerialEnd); + service.send(no); + service.flush(); + } - virtual void end() { - service->send(SerialEnd); - service->send(no); - service->flush(); + virtual int available() { + if (read_buffer.available() > 0) { + return read_buffer.available(); } - - virtual int available(){ - if (read_buffer.available()>0){ - return read_buffer.available(); - } - // otherwise we get it from the remote system - service->send(SerialAvailable); - service->send(no); - service->flush(); - return service->receive16(); + // otherwise we get it from the remote system + service.send(SerialAvailable); + service.send(no); + service.flush(); + return service.receive16(); + } + + virtual int read() { + if (read_buffer.available() == 0) { + uint8_t buffer[max_buffer_len]; + int len = readBytes(buffer, max_buffer_len); + read_buffer.write(buffer, len); } - - virtual int read(){ - if (read_buffer.available()==0){ - uint8_t buffer[max_buffer_len]; - int len = readBytes(buffer, max_buffer_len); - read_buffer.write(buffer,len); - } - if (read_buffer.available()==0){ - return -1; - } - return read_buffer.read(); + if (read_buffer.available() == 0) { + return -1; } - - virtual size_t readBytes(uint8_t *buffer, size_t length){ - if (read_buffer.available()>0){ - return read_buffer.read(buffer, length); - } - service->send(SerialRead); - service->send(no); - service->send((uint64_t)length); - service->flush(); - int len = service->receive(buffer, length); - return len; + return read_buffer.read(); + } + + virtual size_t readBytes(uint8_t* buffer, size_t length) { + if (read_buffer.available() > 0) { + return read_buffer.read(buffer, length); } + service.send(SerialRead); + service.send(no); + service.send((uint64_t)length); + service.flush(); + int len = service.receive(buffer, length); + return len; + } - virtual int peek(){ - if (read_buffer.available()>0){ - return read_buffer.peek(); - } - service->send(SerialPeek); - service->flush(); - return service->receive16(); + virtual int peek() { + if (read_buffer.available() > 0) { + return read_buffer.peek(); } - - virtual size_t write(uint8_t c){ - if (write_buffer.availableToWrite()==0){ - flush(); - } - return write_buffer.write(c); + service.send(SerialPeek); + service.flush(); + return service.receive16(); + } + + virtual size_t write(uint8_t c) { + if (write_buffer.availableToWrite() == 0) { + flush(); } - - virtual size_t write(uint8_t *str, size_t len){ - flush(); - service->send(SerialWrite); - service->send(no); - service->send((uint64_t)len); - service->send(str, len); - service->flush(); - return service->receive16(); + return write_buffer.write(c); + } + + virtual size_t write(uint8_t* str, size_t len) { + flush(); + service.send(SerialWrite); + service.send(no); + service.send((uint64_t)len); + service.send(str, len); + service.flush(); + return service.receive16(); + } + + void flush() { +#if defined(_MSC_VER) + int available; + while ((available = write_buffer.available()) > 0) { + uint8_t buffer[max_buffer_len]; + write_buffer.read(buffer, min(available, max_buffer_len)); + write(buffer, min(available, max_buffer_len)); } - - void flush() { - #if defined(_MSC_VER) - int available; - while((available = write_buffer.available()) > 0){ - uint8_t buffer[max_buffer_len]; - write_buffer.read(buffer, min(available, max_buffer_len)); - write(buffer, min(available, max_buffer_len)); - } - #else - int available = write_buffer.available(); - if (available>0){ - uint8_t buffer[available]; - write_buffer.read(buffer, available); - write(buffer, available); - } - #endif - service->send(SerialFlush); - service->send(no); - service->flush(); +#else + int available = write_buffer.available(); + if (available > 0) { + uint8_t buffer[available]; + write_buffer.read(buffer, available); + write(buffer, available); } +#endif + service.send(SerialFlush); + service.send(no); + service.flush(); + } + + operator boolean() { return service; } - - protected: - HardwareService *service; - uint8_t no; - #if defined(_MSC_VER) - static constexpr int max_buffer_len = 512; // MSVC does not support VLA - #else - int max_buffer_len = 512; - #endif - RingBufferExt write_buffer; - RingBufferExt read_buffer; - + protected: + HardwareService service; + uint8_t no; +#if defined(_MSC_VER) + static constexpr int max_buffer_len = 512; // MSVC does not support VLA +#else + int max_buffer_len = 512; +#endif + RingBufferExt write_buffer; + RingBufferExt read_buffer; }; - - -} + +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/RingBufferExt.h b/ArduinoCore-Linux/cores/arduino/RingBufferExt.h index 19316f6..643012e 100644 --- a/ArduinoCore-Linux/cores/arduino/RingBufferExt.h +++ b/ArduinoCore-Linux/cores/arduino/RingBufferExt.h @@ -4,108 +4,96 @@ #include "stdint.h" #include "vector" - namespace arduino { /** - * @brief Implementation of a Simple Circular Buffer. Instead of comparing the position of the read - * and write pointer in order to figure out if we still have characters available or space left to - * write we keep track of the actual length which is easier to follow. This class was implemented to - * support the reading and writing of arrays. + * @brief Implementation of a Simple Circular Buffer. Instead of comparing the + * position of the read and write pointer in order to figure out if we still + * have characters available or space left to write we keep track of the actual + * length which is easier to follow. This class was implemented to support the + * reading and writing of arrays. */ class RingBufferExt { - public: - RingBufferExt(int size=1024){ - max_len = size; - buffer.resize(size); - } - - - // available to read - int available() { - return actual_len; - } - - int availableToWrite() { - return max_len - actual_len; - } - - // reads a single character and makes it availble on the buffer - int read() { - int result = peek(); - if (result>-1){ - actual_read_pos++; - actual_len--; - } - // wrap to the start - if (actual_read_pos>=max_len){ - actual_read_pos = 0; - } - return result; - } - - int read(char *str, int len){ - return read((uint8_t *)str, len); - } - - int read(uint8_t *str, int len){ - for (int j=0;j0){ - result = buffer[actual_read_pos]; - } - return result; - }; - - size_t write(uint8_t ch) { - int result = 0; - if (actual_len=max_len) { - actual_write_pos = 0; - } - } - return result; - } - - size_t write(char *str, int len) { - return write((uint8_t *)str,len); - } - - size_t write(uint8_t *str, int len) { - for (int j=0;j buffer; - int max_len; - int actual_len = 0; - int actual_read_pos = 0; - int actual_write_pos = 0; - + public: + RingBufferExt(int size = 1024) { + max_len = size; + buffer.resize(size); + } + + // available to read + int available() { return actual_len; } + + int availableToWrite() { return max_len - actual_len; } + + // reads a single character and makes it availble on the buffer + int read() { + int result = peek(); + if (result > -1) { + actual_read_pos++; + actual_len--; + } + // wrap to the start + if (actual_read_pos >= max_len) { + actual_read_pos = 0; + } + return result; + } + + int read(char* str, int len) { return read((uint8_t*)str, len); } + + int read(uint8_t* str, int len) { + for (int j = 0; j < len; j++) { + int current = read(); + if (current <= 0) { + return j; + } + str[j] = current; + } + return len; + } + + // peeks the actual character + int peek() { + int result = -1; + if (actual_len > 0) { + result = buffer[actual_read_pos]; + } + return result; + }; + + size_t write(uint8_t ch) { + int result = 0; + if (actual_len < max_len) { + result = 1; + buffer[actual_write_pos] = ch; + actual_write_pos++; + actual_len++; + if (actual_write_pos >= max_len) { + actual_write_pos = 0; + } + } + return result; + } + + size_t write(char* str, int len) { return write((uint8_t*)str, len); } + + size_t write(uint8_t* str, int len) { + for (int j = 0; j < len; j++) { + int result = write(str[j]); + if (result == 0) { + return j; + } + } + return len; + } + + protected: + std::vector buffer; + int max_len; + int actual_len = 0; + int actual_read_pos = 0; + int actual_write_pos = 0; }; -} - +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/SPI.h b/ArduinoCore-Linux/cores/arduino/SPI.h new file mode 100644 index 0000000..ff2132b --- /dev/null +++ b/ArduinoCore-Linux/cores/arduino/SPI.h @@ -0,0 +1,2 @@ +#pragma once +#include "SPIWrapper.h" \ No newline at end of file diff --git a/ArduinoCore-Linux/cores/arduino/SPIWrapper.cpp b/ArduinoCore-Linux/cores/arduino/SPIWrapper.cpp new file mode 100644 index 0000000..442338a --- /dev/null +++ b/ArduinoCore-Linux/cores/arduino/SPIWrapper.cpp @@ -0,0 +1,90 @@ +#include "SPIWrapper.h" +/** + * We suppport different implementations for the SPI + * + **/ + +namespace arduino { + +uint8_t SPIWrapper::transfer(uint8_t data) { + HardwareSPI* spi = getSPI(); + if (spi != nullptr) { + return spi->transfer(data); + } else { + return 0; + } +} + +uint16_t SPIWrapper::transfer16(uint16_t data) { + HardwareSPI* spi = getSPI(); + if (spi != nullptr) { + return spi->transfer16(data); + } else { + return 0; + } +} + +void SPIWrapper::transfer(void* data, size_t count) { + HardwareSPI* spi = getSPI(); + if (spi != nullptr) { + spi->transfer(data, count); + } +} + +void SPIWrapper::usingInterrupt(int interruptNumber) { + HardwareSPI* spi = getSPI(); + if (spi != nullptr) { + spi->usingInterrupt(interruptNumber); + } +} + +void SPIWrapper::notUsingInterrupt(int interruptNumber) { + HardwareSPI* spi = getSPI(); + if (spi != nullptr) { + spi->notUsingInterrupt(interruptNumber); + } +} + +void SPIWrapper::beginTransaction(SPISettings settings) { + HardwareSPI* spi = getSPI(); + if (spi != nullptr) { + spi->beginTransaction(settings); + } +} + +void SPIWrapper::endTransaction(void) { + HardwareSPI* spi = getSPI(); + if (spi != nullptr) { + spi->endTransaction(); + } +} + +void SPIWrapper::attachInterrupt() { + HardwareSPI* spi = getSPI(); + if (spi != nullptr) { + spi->attachInterrupt(); + } +} + +void SPIWrapper::detachInterrupt() { + HardwareSPI* spi = getSPI(); + if (spi != nullptr) { + spi->detachInterrupt(); + } +} + +void SPIWrapper::begin() { + HardwareSPI* spi = getSPI(); + if (spi != nullptr) { + spi->begin(); + } +} + +void SPIWrapper::end() { + HardwareSPI* spi = getSPI(); + if (spi != nullptr) { + spi->end(); + } +} + +} // namespace arduino \ No newline at end of file diff --git a/ArduinoCore-Linux/cores/arduino/SPIWrapper.h b/ArduinoCore-Linux/cores/arduino/SPIWrapper.h new file mode 100644 index 0000000..0564640 --- /dev/null +++ b/ArduinoCore-Linux/cores/arduino/SPIWrapper.h @@ -0,0 +1,79 @@ +#pragma once +#include "Sources.h" +#include "api/HardwareSPI.h" + +namespace arduino { + +/** + * @brief SPI wrapper class that provides flexible hardware abstraction + * + * SPIWrapper is a concrete implementation of the HardwareSPI interface that + * supports multiple delegation patterns for SPI communication. It can delegate + * operations to: + * - An injected HardwareSPI implementation + * - An SPISource provider that supplies the SPI implementation + * - A default fallback implementation + * + * This class implements the complete SPI interface including: + * - Bus initialization and termination (begin/end) + * - Data transfer operations (8-bit, 16-bit, and buffer transfers) + * - Transaction management with settings control + * - Interrupt handling and configuration + * - Clock, data order, and mode configuration via SPISettings + * + * The wrapper automatically handles null safety and provides appropriate + * default return values when no underlying SPI implementation is available. It + * supports both polling and interrupt-driven SPI operations. + * + * A global `SPI` instance is automatically provided for Arduino compatibility. + * + * @see HardwareSPI + * @see SPISource + * @see SPISettings + */ +class SPIWrapper : public HardwareSPI { + public: + SPIWrapper() = default; + SPIWrapper(SPISource& source) { setSource(&source); } + SPIWrapper(HardwareSPI& spi) { setSPI(&spi); } + ~SPIWrapper() = default; + void begin(); + void end(); + uint8_t transfer(uint8_t data); + uint16_t transfer16(uint16_t data); + void transfer(void* data, size_t count); + void usingInterrupt(int interruptNumber); + void notUsingInterrupt(int interruptNumber); + void beginTransaction(SPISettings settings); + void endTransaction(void); + void attachInterrupt(); + void detachInterrupt(); + + /// defines the spi implementation: use nullptr to reset. + void setSPI(HardwareSPI* spi) { + p_spi = spi; + p_source = nullptr; + } + /// alternatively defines a class that provides the SPI implementation + void setSource(SPISource* source) { + p_source = source; + p_spi = nullptr; + } + + protected: + HardwareSPI* p_spi = nullptr; + SPISource* p_source = nullptr; + + HardwareSPI* getSPI() { + HardwareSPI* result = p_spi; + if (result == nullptr) { + result = p_source->getSPI(); + } + return result; + } +}; + +/// Global SPI instance used by Arduino API and direct access +static SPIWrapper SPI; + +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/Serial.h b/ArduinoCore-Linux/cores/arduino/Serial.h index 35be4d7..9eb85cb 100644 --- a/ArduinoCore-Linux/cores/arduino/Serial.h +++ b/ArduinoCore-Linux/cores/arduino/Serial.h @@ -2,8 +2,8 @@ #if USE_SERIALLIB -#include "serialib.h" #include "HardwareSerial.h" +#include "serialib.h" namespace arduino { @@ -13,81 +13,68 @@ namespace arduino { */ class SerialImpl : public HardwareSerial { - public: - SerialImpl(const char* device = "/dev/ttyACM0"){ - this->device = device; - } - - virtual void begin(unsigned long baudrate) { - open(baudrate); - } - - virtual void begin(unsigned long baudrate, uint16_t config) { - open(baudrate); - } - - virtual void end() { - is_open = false; - serial.closeDevice(); - } - - virtual int available(void) { - return serial.available(); - }; - - virtual int peek(void) { - if (peek_char==-1){ - peek_char = read(); - } - return peek_char; - } - - virtual int read(void) { - int result = -1; - if (peek_char!=-1){ - result = peek_char; - peek_char = -1; - } else { - char c; - result = serial.readChar(&c, timeout); - } - return result; - }; - - virtual void flush(void) { - }; - - virtual size_t write(uint8_t c) { - return serial.writeChar(c); - } - - virtual operator bool(){ - return is_open; - } - - // sets maximum milliseconds to wait for stream data, default is 1 second - void setTimeout(unsigned long timeout){ - this->timeout = timeout; - HardwareSerial::setTimeout(timeout); - } - - protected: - const char* device; - serialib serial; - bool is_open = false; - int peek_char = -1; - long timeout = 1000; - - virtual void open(unsigned long baudrate) { - if (!serial.openDevice(device, baudrate)){ - Logger.error("SerialImpl","could not open",device); - } - is_open=true; - } + public: + SerialImpl(const char* device = "/dev/ttyACM0") { this->device = device; } + + virtual void begin(unsigned long baudrate) { open(baudrate); } + + virtual void begin(unsigned long baudrate, uint16_t config) { + open(baudrate); + } + + virtual void end() { + is_open = false; + serial.closeDevice(); + } + + virtual int available(void) { return serial.available(); }; + + virtual int peek(void) { + if (peek_char == -1) { + peek_char = read(); + } + return peek_char; + } + virtual int read(void) { + int result = -1; + if (peek_char != -1) { + result = peek_char; + peek_char = -1; + } else { + char c; + result = serial.readChar(&c, timeout); + } + return result; + }; + + virtual void flush(void) {}; + + virtual size_t write(uint8_t c) { return serial.writeChar(c); } + + virtual operator bool() { return is_open; } + + // sets maximum milliseconds to wait for stream data, default is 1 second + void setTimeout(unsigned long timeout) { + this->timeout = timeout; + HardwareSerial::setTimeout(timeout); + } + + protected: + const char* device; + serialib serial; + bool is_open = false; + int peek_char = -1; + long timeout = 1000; + + virtual void open(unsigned long baudrate) { + if (!serial.openDevice(device, baudrate)) { + Logger.error("SerialImpl", "could not open", device); + } + is_open = true; + } }; - - -} // namespace + +} // namespace arduino #endif \ No newline at end of file diff --git a/ArduinoCore-Linux/cores/arduino/Sources.h b/ArduinoCore-Linux/cores/arduino/Sources.h new file mode 100644 index 0000000..099e611 --- /dev/null +++ b/ArduinoCore-Linux/cores/arduino/Sources.h @@ -0,0 +1,54 @@ +#pragma once +#include "api/HardwareI2C.h" +#include "api/HardwareSPI.h" +#include "HardwareGPIO.h" + +namespace arduino { + +/** + * @brief Abstract interface for providing I2C hardware implementations + * + * I2CSource defines a factory interface for supplying HardwareI2C implementations. + * This abstraction allows wrapper classes to obtain I2C hardware instances from + * various sources without coupling to specific hardware providers. + * + * @see HardwareI2C + * @see I2CWrapper + */ +class I2CSource { + public: + virtual HardwareI2C* getI2C() = 0; +}; + +/** + * @brief Abstract interface for providing SPI hardware implementations + * + * SPISource defines a factory interface for supplying HardwareSPI implementations. + * This abstraction allows wrapper classes to obtain SPI hardware instances from + * various sources without coupling to specific hardware providers. + * + * @see HardwareSPI + * @see SPIWrapper + */ +class SPISource { + public: + virtual HardwareSPI* getSPI() = 0; +}; + +/** + * @brief Abstract interface for providing GPIO hardware implementations + * + * GPIOSource defines a factory interface for supplying HardwareGPIO implementations. + * This abstraction allows wrapper classes to obtain GPIO hardware instances from + * various sources without coupling to specific hardware providers. + * + * @see HardwareGPIO + * @see GPIOWrapper + */ +class GPIOSource { + public: + virtual HardwareGPIO* getGPIO() = 0; +}; + + +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/StdioDevice.h b/ArduinoCore-Linux/cores/arduino/StdioDevice.h index d70b571..aa5f043 100644 --- a/ArduinoCore-Linux/cores/arduino/StdioDevice.h +++ b/ArduinoCore-Linux/cores/arduino/StdioDevice.h @@ -2,131 +2,116 @@ #include #include -#include "Stream.h" + #include "Printable.h" +#include "Stream.h" namespace arduino { /** - * @brief We use the SerialDef class to be able to provide Serail, Serial1 and Serial2 outside of the - * Arduino environment; - * + * @brief We use the SerialDef class to be able to provide Serail, Serial1 and + * Serial2 outside of the Arduino environment; + * */ class StdioDevice : public Stream { - public: - - StdioDevice(bool autoFlush=true){ - auto_flush = autoFlush; - } - - ~StdioDevice(){ - } - - operator bool() const { return true; } // For classic while(!Serial) { ... } pattern for USB ready wait - - virtual void begin(int speed){ - // nothing to be done - } - - virtual size_t print(const char* str){ - std::cout << str; - if (auto_flush) flush(); - return strlen(str); - } - - virtual size_t println(const char* str=""){ - std::cout << str << "\n"; - if (auto_flush) flush(); - return strlen(str) + 1; - } - - virtual size_t print(int val, int radix = DEC){ - size_t result = Stream::print(val, radix); - if (auto_flush) flush(); - return result; - } - - virtual size_t println(int val, int radix = DEC){ - size_t result = Stream::println(val, radix); - if (auto_flush) flush(); - return result; - } - - virtual size_t println(String &str){ - return println(str.c_str()); - } - - virtual size_t print(String &str){ - return print(str.c_str()); - } - - - virtual size_t println(Printable &p){ - size_t result = p.printTo(*this); - std::cout << "\n"; - if (auto_flush) flush(); - return result + 1; - } - - virtual size_t print(Printable &p){ - auto result = p.printTo(*this); - if (auto_flush) flush(); - return result; - } - - void flush() override { - std::cout.flush(); - } - - virtual size_t write(const char* str, size_t len) { - std::cout.write(str, len); - if (auto_flush) flush(); - return len; - } - - virtual size_t write(uint8_t* str, size_t len) { - std::cout.write((const char*)str, len); - if (auto_flush) flush(); - return len; - - } - size_t write(const uint8_t* str, size_t len) override { - std::cout.write((const char*)str, len); - if (auto_flush) flush(); - return len; - } - - virtual size_t write(int32_t value){ - std::cout.put(value); - if (auto_flush) flush(); - return 1; - } - - size_t write(uint8_t value) override { - std::cout.put(value); - if (auto_flush) flush(); - return 1; - } - - int available() override { - return std::cin.rdbuf()->in_avail(); - }; - - int read() override { - return std::cin.get(); - } - - int peek() override { - return std::cin.peek(); - } - - protected: - bool auto_flush = true; - + public: + StdioDevice(bool autoFlush = true) { auto_flush = autoFlush; } + + ~StdioDevice() {} + + operator bool() const { + return true; + } // For classic while(!Serial) { ... } pattern for USB ready wait + + virtual void begin(int speed) { + // nothing to be done + } + + virtual size_t print(const char* str) { + std::cout << str; + if (auto_flush) flush(); + return strlen(str); + } + + virtual size_t println(const char* str = "") { + std::cout << str << "\n"; + if (auto_flush) flush(); + return strlen(str) + 1; + } + + virtual size_t print(int val, int radix = DEC) { + size_t result = Stream::print(val, radix); + if (auto_flush) flush(); + return result; + } + + virtual size_t println(int val, int radix = DEC) { + size_t result = Stream::println(val, radix); + if (auto_flush) flush(); + return result; + } + + virtual size_t println(String& str) { return println(str.c_str()); } + + virtual size_t print(String& str) { return print(str.c_str()); } + + virtual size_t println(Printable& p) { + size_t result = p.printTo(*this); + std::cout << "\n"; + if (auto_flush) flush(); + return result + 1; + } + + virtual size_t print(Printable& p) { + auto result = p.printTo(*this); + if (auto_flush) flush(); + return result; + } + + void flush() override { std::cout.flush(); } + + virtual size_t write(const char* str, size_t len) { + std::cout.write(str, len); + if (auto_flush) flush(); + return len; + } + + virtual size_t write(uint8_t* str, size_t len) { + std::cout.write((const char*)str, len); + if (auto_flush) flush(); + return len; + } + size_t write(const uint8_t* str, size_t len) override { + std::cout.write((const char*)str, len); + if (auto_flush) flush(); + return len; + } + + virtual size_t write(int32_t value) { + std::cout.put(value); + if (auto_flush) flush(); + return 1; + } + + size_t write(uint8_t value) override { + std::cout.put(value); + if (auto_flush) flush(); + return 1; + } + + int available() override { return std::cin.rdbuf()->in_avail(); }; + + int read() override { return std::cin.get(); } + + int peek() override { return std::cin.peek(); } + protected: + bool auto_flush = true; }; -static StdioDevice Serial; - -} +static StdioDevice Serial; +#ifndef USE_RPI +static StdioDevice Serial2; +#endif +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/Unsupported.cpp b/ArduinoCore-Linux/cores/arduino/Unsupported.cpp index 7ef414b..54b5611 100644 --- a/ArduinoCore-Linux/cores/arduino/Unsupported.cpp +++ b/ArduinoCore-Linux/cores/arduino/Unsupported.cpp @@ -1,19 +1,19 @@ -#include "api/Common.h" #include "ArduinoLogger.h" +#include "api/Common.h" -void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode){ - arduino::Logger.error("attachInterrupt","not supported"); +void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, + PinStatus mode) { + arduino::Logger.error("attachInterrupt", "not supported"); } -void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, PinStatus mode, void* param){ - arduino::Logger.error("attachInterruptParam","not supported"); +void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, + PinStatus mode, void* param) { + arduino::Logger.error("attachInterruptParam", "not supported"); } -void detachInterrupt(pin_size_t interruptNumber){ - arduino::Logger.error("detachInterrupt","not supported"); +void detachInterrupt(pin_size_t interruptNumber) { + arduino::Logger.error("detachInterrupt", "not supported"); } // to compile pluggable usb -void* epBuffer(unsigned int n){ - return nullptr; -} \ No newline at end of file +void* epBuffer(unsigned int n) { return nullptr; } \ No newline at end of file diff --git a/ArduinoCore-Linux/cores/arduino/WMath.cpp b/ArduinoCore-Linux/cores/arduino/WMath.cpp index a993f1f..3116b60 100644 --- a/ArduinoCore-Linux/cores/arduino/WMath.cpp +++ b/ArduinoCore-Linux/cores/arduino/WMath.cpp @@ -1,7 +1,7 @@ // WMath.cpp #include "api/Common.h" extern "C" { - #include +#include } long random(long howbig) { diff --git a/ArduinoCore-Linux/cores/arduino/WiFi.h b/ArduinoCore-Linux/cores/arduino/WiFi.h index 0985961..07ba329 100644 --- a/ArduinoCore-Linux/cores/arduino/WiFi.h +++ b/ArduinoCore-Linux/cores/arduino/WiFi.h @@ -13,38 +13,36 @@ namespace arduino { -enum wifi_ps_type_t { WIFI_PS_NONE, WIFI_PS_MIN_MODEM, WIFI_PS_MAX_MODEM}; +enum wifi_ps_type_t { WIFI_PS_NONE, WIFI_PS_MIN_MODEM, WIFI_PS_MAX_MODEM }; class WifiMock { -public: - virtual void begin(const char *name, const char *pwd) { + public: + virtual void begin(const char* name, const char* pwd) { // nothing to be done } // we assume the network to be available on a desktop or host machine wl_status_t status() { return WL_CONNECTED; } - IPAddress &localIP() { + IPAddress& localIP() { SocketImpl sock; adress.fromString(sock.getIPAddress()); return adress; } - void setSleep(bool){} + void setSleep(bool) {} void setSleep(wifi_ps_type_t) {} - int macAddress() { - return mac; - } + int macAddress() { return mac; } void setClientInsecure() {} -protected: + protected: IPAddress adress; int mac = 0; }; extern WifiMock WiFi; -} // namespace arduino +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/WiFiUdpStream.h b/ArduinoCore-Linux/cores/arduino/WiFiUdpStream.h index 58e186e..c467f05 100644 --- a/ArduinoCore-Linux/cores/arduino/WiFiUdpStream.h +++ b/ArduinoCore-Linux/cores/arduino/WiFiUdpStream.h @@ -1,87 +1,100 @@ #pragma once #include -#include + +#include + +#include "ArduinoLogger.h" +#include "WiFiUDP.h" #include "api/ArduinoAPI.h" #include "api/IPAddress.h" -#include "WiFiUDP.h" -#include "ArduinoLogger.h" namespace arduino { /** - * Single Target UDP Stream which sends the data on flush + * @brief UDP Stream implementation for single-target communication + * + * WiFiUDPStream extends WiFiUDP to provide a stream-like interface for UDP + * communication with a single target endpoint. It automatically manages packet + * boundaries and provides buffered read/write operations suitable for streaming + * protocols over UDP. + * + * Key features: + * - Stream-based UDP communication with automatic packet management + * - Single target endpoint configuration (IP address and port) + * - Automatic target discovery from incoming packets when target unknown + * - Buffered operations with flush-triggered packet transmission + * - Thread-safe operations for concurrent access + * - Integration with WiFiUDP for underlying network operations + * + * The class maintains an internal target address and automatically begins/ends + * UDP packets as needed. Data is sent when flush() is called, making it suitable + * for protocols that require message boundaries or batch transmission. + * + * @see WiFiUDP + * @see IPAddress + * @see Stream */ - class WiFiUDPStream : public WiFiUDP { - public: - // unknown target -> we wait for a hallo until we get one - WiFiUDPStream() = default; - - // known target - WiFiUDPStream(IPAddress targetAdress, int port){ - setTarget(targetAdress,port); - } - - void flush() { - WiFiUDP::flush(); - endPacket(); - if (!targetDefined()){ - target_adress = remoteIP(); - } - beginPacket(target_adress, port); - } - - void stop(){ - if (active){ - endPacket(); - WiFiUDP::stop(); - active = false; - } - } - - bool targetDefined() { - return ((uint32_t)target_adress)!=0; - } - - void setTarget(IPAddress targetAdress, int port){ - this->target_adress = targetAdress; - this->port = port; - beginPacket(targetAdress, port); - } - - size_t readBytes(uint8_t* values, size_t len){ - if (this->available()==0){ - // we need to receive the next packet - this->parsePacket(); - Logger.debug("parsePacket"); - } else { - Logger.debug("no parsePacket()"); - } - size_t result = read(values, len); - - char msg[50]; - sprintf(msg, "->len %ld",result); - Logger.debug(msg); - - - return result; - } - - bool isActive() { - return active; - } - - protected: - bool active = false; - IPAddress target_adress{0,0,0,0}; - int port = 0; - -}; - -// Define a global function which will be used to start a thread - -} // namespace arduino + public: + // unknown target -> we wait for a hallo until we get one + WiFiUDPStream() = default; + + // known target + WiFiUDPStream(IPAddress targetAdress, int port) { + setTarget(targetAdress, port); + } + void flush() { + WiFiUDP::flush(); + endPacket(); + if (!targetDefined()) { + target_adress = remoteIP(); + } + beginPacket(target_adress, port); + } + + void stop() { + if (active) { + endPacket(); + WiFiUDP::stop(); + active = false; + } + } + + bool targetDefined() { return ((uint32_t)target_adress) != 0; } + + void setTarget(IPAddress targetAdress, int port) { + this->target_adress = targetAdress; + this->port = port; + beginPacket(targetAdress, port); + } + + size_t readBytes(uint8_t* values, size_t len) { + if (this->available() == 0) { + // we need to receive the next packet + this->parsePacket(); + Logger.debug("parsePacket"); + } else { + Logger.debug("no parsePacket()"); + } + size_t result = read(values, len); + + char msg[50]; + sprintf(msg, "->len %ld", result); + Logger.debug(msg); + + return result; + } + + bool isActive() { return active; } + + protected: + bool active = false; + IPAddress target_adress{0, 0, 0, 0}; + int port = 0; +}; +// Define a global function which will be used to start a thread +} // namespace arduino diff --git a/ArduinoCore-Linux/cores/arduino/Wire.h b/ArduinoCore-Linux/cores/arduino/Wire.h index b965802..89a310e 100644 --- a/ArduinoCore-Linux/cores/arduino/Wire.h +++ b/ArduinoCore-Linux/cores/arduino/Wire.h @@ -1,5 +1,2 @@ #pragma once -#include "HardwareSetup.h" -#if defined(USE_RPI) -# include "HardwareSetupRPI.h" -#endif +#include "I2CWrapper.h" diff --git a/ArduinoCore-Linux/cores/rasperry_pi/HardwareGPIO_RPI.cpp b/ArduinoCore-Linux/cores/rasperry_pi/HardwareGPIO_RPI.cpp index 876a381..ab79914 100644 --- a/ArduinoCore-Linux/cores/rasperry_pi/HardwareGPIO_RPI.cpp +++ b/ArduinoCore-Linux/cores/rasperry_pi/HardwareGPIO_RPI.cpp @@ -4,7 +4,6 @@ #include // sudo apt-get install libgpiod-dev #include #include "HardwareGPIO_RPI.h" -#include "Hardware.h" #include "ArduinoLogger.h" namespace arduino { diff --git a/ArduinoCore-Linux/cores/rasperry_pi/HardwareI2C_RPI.h b/ArduinoCore-Linux/cores/rasperry_pi/HardwareI2C_RPI.h index 9120f38..10b516c 100644 --- a/ArduinoCore-Linux/cores/rasperry_pi/HardwareI2C_RPI.h +++ b/ArduinoCore-Linux/cores/rasperry_pi/HardwareI2C_RPI.h @@ -4,7 +4,6 @@ #include // for O_RDWR #include // for open(), close(), etc. #include -#include "Hardware.h" #include "HardwareI2C.h" #include "ArduinoLogger.h" diff --git a/ArduinoCore-Linux/cores/rasperry_pi/HardwareSetupRPI.h b/ArduinoCore-Linux/cores/rasperry_pi/HardwareSetupRPI.h index a275e82..d8a0db1 100644 --- a/ArduinoCore-Linux/cores/rasperry_pi/HardwareSetupRPI.h +++ b/ArduinoCore-Linux/cores/rasperry_pi/HardwareSetupRPI.h @@ -1,22 +1,18 @@ #pragma once #if defined(USE_RPI) && !defined(SKIP_HARDWARE_SETUP) -#include "Hardware.h" // for Hardware; +#include "FileStream.h" #include "HardwareGPIO_RPI.h" #include "HardwareI2C_RPI.h" #include "HardwareSPI_RPI.h" -#include "FileStream.h" namespace arduino { -static HardwareI2C_RPI Wire; -static HardwareSPI_RPI SPI;; - /** * @class HardwareSetupRPI * @brief Sets up hardware interfaces for Raspberry Pi (GPIO, I2C, SPI). */ -class HardwareSetupRPI { +class HardwareSetupRPI public I2CSource, public SPISource, public GPIOSource { public: /** * @brief Constructor. Initializes hardware interfaces. @@ -31,18 +27,20 @@ class HardwareSetupRPI { /** * @brief Initializes hardware pointers to Raspberry Pi interfaces. */ - bool begin() { + bool begin(bool asDefault = true) { Logger.info("Using Raspberry Pi hardware interfaces"); + is_default_objects_active = asDefault; gpio.begin(); i2c.begin(); spi.begin(); - // setup hardware pointers - Hardware.gpio = &gpio; - Hardware.i2c = &i2c; - Hardware.spi = &spi; - // setup global instances - Wire = HardwareSetupRPI::get_i2c(); - SPI = HardwareSetupRPI::get_spi(); + + // define the global hardware interfaces + if (asDefault) { + GPIO.setGPIO(&gpio); + SPI.setSPI(&spi); + Wire.setI2C(&i2c); + } + return gpio && i2c && spi; } @@ -50,22 +48,22 @@ class HardwareSetupRPI { * @brief Resets hardware pointers to nullptr. */ void end() { - Hardware.gpio = nullptr; - Hardware.i2c = nullptr; - Hardware.spi = nullptr; + if (is_default_objects_active) { + GPIO.setGPIO(nullptr); + SPI.setSPI(nullptr); + Wire.setI2C(nullptr); + } } - HardwareGPIO_RPI& get_gpio() { return gpio; } - HardwareI2C_RPI& get_i2c() { return i2c; } - HardwareSPI_RPI& get_spi() { return spi; } + HardwareGPIO_RPI* getGPIO() { return &gpio; } + HardwareI2C_RPI* getI2C() { return &i2c; } + HardwareSPI_RPI* getSPI() { return &spi; } protected: - /** GPIO interface for Raspberry Pi */ HardwareGPIO_RPI gpio; - /** I2C interface for Raspberry Pi */ HardwareI2C_RPI i2c; - /** SPI interface for Raspberry Pi */ HardwareSPI_RPI spi; + bool is_default_objects_active = false; }; /** @@ -79,15 +77,14 @@ static HardwareSetupRPI RPI; /** * @brief Second hardware serial port for Raspberry Pi. * - * Serial2 provides access to the Raspberry Pi's primary UART device (usually /dev/serial0). - * This can be used for serial communication with external devices, similar to Serial1/Serial2 on Arduino boards. - * Example usage: + * Serial2 provides access to the Raspberry Pi's primary UART device (usually + * /dev/serial0). This can be used for serial communication with external + * devices, similar to Serial1/Serial2 on Arduino boards. Example usage: * Serial2.begin(9600); * Serial2.println("Hello from Serial2"); */ static FileStream Serial2("/dev/serial0"); - } // namespace arduino #endif \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index fe69c7d..182b921 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ project(arduino_emulator VERSION 0.1 DESCRIPTION "Arduino Emulator for Linux" LA # Https takes quite some time and is not always neede option(USE_HTTPS "Https Support" OFF) option(USE_RPI "Raspberry Pi Support" OFF) +option(USE_REMOTE "Remote API Support" ON) option(BUILD_SHARED_LIBS "Build with shared libraries" ON) # Https support: Build with wolfssl @@ -62,6 +63,10 @@ if (USE_RPI) target_compile_options(arduino_emulator PUBLIC -DUSE_RPI) endif(USE_RPI) +if (USE_REMOTE) + target_compile_options(arduino_emulator PUBLIC -DUSE_REMOTE) +endif(USE_REMOTE) + if(USE_HTTPS) # Add external libraries target_link_libraries(arduino_emulator wolfssl) diff --git a/docs/html/_hardware_i2_c_ex_8h_source.html b/docs/html/_hardware_i2_c_ex_8h_source.html index d13df3d..b2dd89c 100644 --- a/docs/html/_hardware_i2_c_ex_8h_source.html +++ b/docs/html/_hardware_i2_c_ex_8h_source.html @@ -5,7 +5,7 @@ -arduino-emulator: ArduinoCore-Linux/cores/arduino/HardwareI2CEx.h Source File +arduino-emulator: ArduinoCore-Linux/cores/arduino/I2CWrapper.h Source File @@ -78,7 +78,7 @@
-
HardwareI2CEx.h
+
I2CWrapper.h
1#pragma once
@@ -88,10 +88,10 @@
5namespace arduino {
6
-
7class HardwareI2CEx : public HardwareI2C {
+
7class I2CWrapper : public HardwareI2C {
8 public:
- -
10 virtual ~HardwareI2CEx(){};
+
9 I2CWrapper(){}
+
10 virtual ~I2CWrapper(){};
11 virtual void begin();
12 virtual void begin(uint8_t address);
13 virtual void end();
@@ -109,7 +109,7 @@
24}
25
Definition DMAPool.h:103
-
Definition HardwareI2CEx.h:7
+
Definition I2CWrapper.h:7
Definition HardwareI2C.h:28
We provide the WiFi class to simulate the Arduino WIFI. In in Linux we can expect that networking is ...
Definition CanMsg.cpp:31
diff --git a/docs/html/_remote_i2_c_8h_source.html b/docs/html/_remote_i2_c_8h_source.html index 6e5c587..812f748 100644 --- a/docs/html/_remote_i2_c_8h_source.html +++ b/docs/html/_remote_i2_c_8h_source.html @@ -83,7 +83,7 @@
1#pragma once
2
-
3#include "HardwareI2CEx.h"
+
3#include "I2CWrapper.h"
4#include "HardwareService.h"
5
6namespace arduino {
@@ -92,7 +92,7 @@
9class Stream;
10
-
11class RemoteI2C : public HardwareI2CEx {
+
11class RemoteI2C : public I2CWrapper {
12 public:
13 RemoteI2C() = default;
14 RemoteI2C(Stream* stream) { service.setStream(static_cast<Stream*>(stream)); }
@@ -185,7 +185,7 @@
100
101} // namespace arduino
Definition DMAPool.h:103
-
Definition HardwareI2CEx.h:7
+
Definition I2CWrapper.h:7
Definition HardwareService.h:76
Definition RemoteI2C.h:11
Definition Stream.h:51
diff --git a/docs/html/_remote_serial_8h_source.html b/docs/html/_remote_serial_8h_source.html index d4cb7d7..65b5507 100644 --- a/docs/html/_remote_serial_8h_source.html +++ b/docs/html/_remote_serial_8h_source.html @@ -90,9 +90,9 @@
7namespace arduino {
8
-
15class RemoteSerialImpl : public Stream {
+
15class RemoteSerialClass : public Stream {
16 public:
- +
18 this->no = no;
19 service = new HardwareService(&stream);
20 }
@@ -218,7 +218,7 @@
139}
Definition DMAPool.h:103
Definition HardwareService.h:76
-
Definition RemoteSerial.h:15
+
Definition RemoteSerial.h:15
Implementation of a Simple Circular Buffer. Instead of comparing the position of the read and write p...
Definition RingBufferExt.h:17
Definition Stream.h:51
We provide the WiFi class to simulate the Arduino WIFI. In in Linux we can expect that networking is ...
Definition CanMsg.cpp:31
diff --git a/docs/html/annotated.html b/docs/html/annotated.html index fbc2ccc..6e57cfe 100644 --- a/docs/html/annotated.html +++ b/docs/html/annotated.html @@ -93,7 +93,7 @@  CHardwareGPIO_RPIGPIO hardware abstraction for Raspberry Pi in the Arduino emulator  CHardwareI2C  CHardwareI2C_RPIImplementation of I2C communication for Raspberry Pi using Linux I2C device interface - CHardwareI2CEx + CI2CWrapper  CHardwareImpl  CHardwareSerial  CHardwareService @@ -110,7 +110,7 @@  CRemoteGPIO  CRemoteI2C  CRemoteI2S - CRemoteSerialImpl + CRemoteSerialClass  CRemoteSPI  CRingBufferExtImplementation of a Simple Circular Buffer. Instead of comparing the position of the read and write pointer in order to figure out if we still have characters available or space left to write we keep track of the actual length which is easier to follow. This class was implemented to support the reading and writing of arrays  CRingBufferN diff --git a/docs/html/classarduino_1_1_hardware_i2_c.html b/docs/html/classarduino_1_1_hardware_i2_c.html index a319091..b4b9bb8 100644 --- a/docs/html/classarduino_1_1_hardware_i2_c.html +++ b/docs/html/classarduino_1_1_hardware_i2_c.html @@ -87,7 +87,7 @@ arduino::Stream arduino::Print -arduino::HardwareI2CEx +arduino::I2CWrapper arduino::HardwareI2C_RPI arduino::RemoteI2C diff --git a/docs/html/classarduino_1_1_hardware_i2_c_ex-members.html b/docs/html/classarduino_1_1_hardware_i2_c_ex-members.html index 9a59c94..b7cd688 100644 --- a/docs/html/classarduino_1_1_hardware_i2_c_ex-members.html +++ b/docs/html/classarduino_1_1_hardware_i2_c_ex-members.html @@ -69,27 +69,27 @@
-
arduino::HardwareI2CEx Member List
+
arduino::I2CWrapper Member List
-

This is the complete list of members for arduino::HardwareI2CEx, including all inherited members.

+

This is the complete list of members for arduino::I2CWrapper, including all inherited members.

- - - + + + - - - + + + @@ -103,9 +103,9 @@ - - - + + + @@ -147,9 +147,9 @@ - - - + + + @@ -159,7 +159,7 @@ - +
_startMillis (defined in arduino::Stream)arduino::Streamprotected
_timeout (defined in arduino::Stream)arduino::Streamprotected
available()=0 (defined in arduino::Stream)arduino::Streampure virtual
availableForWrite() (defined in arduino::Print)arduino::Printinlinevirtual
begin() (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExvirtual
begin(uint8_t address) (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExvirtual
beginTransmission(uint8_t address) (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExvirtual
begin() (defined in arduino::I2CWrapper)arduino::I2CWrappervirtual
begin(uint8_t address) (defined in arduino::I2CWrapper)arduino::I2CWrappervirtual
beginTransmission(uint8_t address) (defined in arduino::I2CWrapper)arduino::I2CWrappervirtual
clearWriteError() (defined in arduino::Print)arduino::Printinline
end() (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExvirtual
endTransmission(bool stopBit) (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExvirtual
endTransmission(void) (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExvirtual
end() (defined in arduino::I2CWrapper)arduino::I2CWrappervirtual
endTransmission(bool stopBit) (defined in arduino::I2CWrapper)arduino::I2CWrappervirtual
endTransmission(void) (defined in arduino::I2CWrapper)arduino::I2CWrappervirtual
find(const char *target) (defined in arduino::Stream)arduino::Stream
find(const uint8_t *target) (defined in arduino::Stream)arduino::Streaminline
find(const char *target, size_t length) (defined in arduino::Stream)arduino::Stream
flush() (defined in arduino::Print)arduino::Printinlinevirtual
getTimeout(void) (defined in arduino::Stream)arduino::Streaminline
getWriteError() (defined in arduino::Print)arduino::Printinline
HardwareI2CEx() (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExinline
onReceive(void(*)(int))=0 (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExpure virtual
onRequest(void(*)(void))=0 (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExpure virtual
I2CWrapper() (defined in arduino::I2CWrapper)arduino::I2CWrapperinline
onReceive(void(*)(int))=0 (defined in arduino::I2CWrapper)arduino::I2CWrapperpure virtual
onRequest(void(*)(void))=0 (defined in arduino::I2CWrapper)arduino::I2CWrapperpure virtual
parseFloat(LookaheadMode lookahead=SKIP_ALL, char ignore=NO_IGNORE_CHAR) (defined in arduino::Stream)arduino::Stream
parseFloat(char ignore) (defined in arduino::Stream)arduino::Streaminlineprotected
parseInt(LookaheadMode lookahead=SKIP_ALL, char ignore=NO_IGNORE_CHAR) (defined in arduino::Stream)arduino::Stream
readBytesUntil(char terminator, uint8_t *buffer, size_t length) (defined in arduino::Stream)arduino::Streaminline
readString() (defined in arduino::Stream)arduino::Stream
readStringUntil(char terminator) (defined in arduino::Stream)arduino::Stream
requestFrom(uint8_t address, size_t len, bool stopBit) (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExvirtual
requestFrom(uint8_t address, size_t len) (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExvirtual
setClock(uint32_t freq) (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExvirtual
requestFrom(uint8_t address, size_t len, bool stopBit) (defined in arduino::I2CWrapper)arduino::I2CWrappervirtual
requestFrom(uint8_t address, size_t len) (defined in arduino::I2CWrapper)arduino::I2CWrappervirtual
setClock(uint32_t freq) (defined in arduino::I2CWrapper)arduino::I2CWrappervirtual
setTimeout(unsigned long timeout) (defined in arduino::Stream)arduino::Stream
setWriteError(int err=1) (defined in arduino::Print)arduino::Printinlineprotected
Stream() (defined in arduino::Stream)arduino::Streaminline
write(const char *str) (defined in arduino::Print)arduino::Printinline
write(const uint8_t *buffer, size_t size) (defined in arduino::Print)arduino::Printvirtual
write(const char *buffer, size_t size) (defined in arduino::Print)arduino::Printinline
~HardwareI2CEx() (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExinlinevirtual
~I2CWrapper() (defined in arduino::I2CWrapper)arduino::I2CWrapperinlinevirtual
-
arduino::HardwareI2CEx Class Referenceabstract
+
arduino::I2CWrapper Class Referenceabstract
-Inheritance diagram for arduino::HardwareI2CEx:
+Inheritance diagram for arduino::I2CWrapper:
- - + + arduino::HardwareI2C arduino::Stream arduino::Print @@ -334,7 +334,7 @@

- + @@ -361,7 +361,7 @@

void arduino::HardwareI2CEx::begin void arduino::I2CWrapper::begin ( )
- + @@ -389,7 +389,7 @@

void arduino::HardwareI2CEx::begin void arduino::I2CWrapper::begin ( uint8_t  address)
- + @@ -417,7 +417,7 @@

void arduino::HardwareI2CEx::beginTransmission void arduino::I2CWrapper::beginTransmission ( uint8_t  address)
- + @@ -444,7 +444,7 @@

void arduino::HardwareI2CEx::end void arduino::I2CWrapper::end ( )
- + @@ -472,7 +472,7 @@

uint8_t arduino::HardwareI2CEx::endTransmission uint8_t arduino::I2CWrapper::endTransmission ( bool  stopBit)
- + @@ -500,7 +500,7 @@

uint8_t arduino::HardwareI2CEx::endTransmission uint8_t arduino::I2CWrapper::endTransmission ( void  )
- + @@ -528,7 +528,7 @@

void arduino::HardwareI2CEx::onReceive void arduino::I2CWrapper::onReceive ( void(*)(int )
- + @@ -556,7 +556,7 @@

void arduino::HardwareI2CEx::onRequest void arduino::I2CWrapper::onRequest ( void(*)(void )
- + @@ -594,7 +594,7 @@

size_t arduino::HardwareI2CEx::requestFrom size_t arduino::I2CWrapper::requestFrom ( uint8_t  address,
- + @@ -638,7 +638,7 @@

size_t arduino::HardwareI2CEx::requestFrom size_t arduino::I2CWrapper::requestFrom ( uint8_t  address,
- + @@ -657,8 +657,8 @@

HardwareI2CEx.h -
  • ArduinoCore-Linux/cores/arduino/HardwareI2CEx.cpp
  • +
  • ArduinoCore-Linux/cores/arduino/I2CWrapper.h
  • +
  • ArduinoCore-Linux/cores/arduino/I2CWrapper.cpp
  • diff --git a/docs/html/classarduino_1_1_print.html b/docs/html/classarduino_1_1_print.html index 94c9779..8d7cec1 100644 --- a/docs/html/classarduino_1_1_print.html +++ b/docs/html/classarduino_1_1_print.html @@ -94,7 +94,7 @@ arduino::FileStream arduino::HardwareI2C arduino::HardwareSerial -arduino::RemoteSerialImpl +arduino::RemoteSerialClass arduino::StdioDevice arduino::UDP arduino::UDP diff --git a/docs/html/classarduino_1_1_remote_i2_c-members.html b/docs/html/classarduino_1_1_remote_i2_c-members.html index 627e205..ebb4fe5 100644 --- a/docs/html/classarduino_1_1_remote_i2_c-members.html +++ b/docs/html/classarduino_1_1_remote_i2_c-members.html @@ -103,7 +103,7 @@

    - + @@ -163,7 +163,7 @@ - +
    void arduino::HardwareI2CEx::setClock void arduino::I2CWrapper::setClock ( uint32_t  freq)
    flush() (defined in arduino::Print)arduino::Printinlinevirtual
    getTimeout(void) (defined in arduino::Stream)arduino::Streaminline
    getWriteError() (defined in arduino::Print)arduino::Printinline
    HardwareI2CEx() (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExinline
    I2CWrapper() (defined in arduino::I2CWrapper)arduino::I2CWrapperinline
    onReceive(void(*)(int)) (defined in arduino::RemoteI2C)arduino::RemoteI2Cinlinevirtual
    onRequest(void(*)(void)) (defined in arduino::RemoteI2C)arduino::RemoteI2Cinlinevirtual
    parseFloat(LookaheadMode lookahead=SKIP_ALL, char ignore=NO_IGNORE_CHAR) (defined in arduino::Stream)arduino::Stream
    write(const char *str) (defined in arduino::Print)arduino::Printinline
    write(const uint8_t *buffer, size_t size) (defined in arduino::Print)arduino::Printvirtual
    write(const char *buffer, size_t size) (defined in arduino::Print)arduino::Printinline
    ~HardwareI2CEx() (defined in arduino::HardwareI2CEx)arduino::HardwareI2CExinlinevirtual
    ~I2CWrapper() (defined in arduino::I2CWrapper)arduino::I2CWrapperinlinevirtual

    @@ -412,7 +412,7 @@

    -

    Reimplemented from arduino::HardwareI2CEx.

    +

    Reimplemented from arduino::I2CWrapper.

    @@ -440,7 +440,7 @@

    -

    Reimplemented from arduino::HardwareI2CEx.

    +

    Reimplemented from arduino::I2CWrapper.

    @@ -467,7 +467,7 @@

    -

    Reimplemented from arduino::HardwareI2CEx.

    +

    Reimplemented from arduino::I2CWrapper.

    @@ -495,7 +495,7 @@

    -

    Reimplemented from arduino::HardwareI2CEx.

    +

    Reimplemented from arduino::I2CWrapper.

    @@ -523,7 +523,7 @@

    -

    Reimplemented from arduino::HardwareI2CEx.

    +

    Reimplemented from arduino::I2CWrapper.

    @@ -551,7 +551,7 @@

    -

    Implements arduino::HardwareI2CEx.

    +

    Implements arduino::I2CWrapper.

    @@ -579,7 +579,7 @@

    -

    Implements arduino::HardwareI2CEx.

    +

    Implements arduino::I2CWrapper.

    @@ -673,7 +673,7 @@

    -

    Reimplemented from arduino::HardwareI2CEx.

    +

    Reimplemented from arduino::I2CWrapper.

    @@ -717,7 +717,7 @@

    -

    Reimplemented from arduino::HardwareI2CEx.

    +

    Reimplemented from arduino::I2CWrapper.

    @@ -745,7 +745,7 @@

    -

    Reimplemented from arduino::HardwareI2CEx.

    +

    Reimplemented from arduino::I2CWrapper.

    diff --git a/docs/html/classarduino_1_1_remote_serial_impl-members.html b/docs/html/classarduino_1_1_remote_serial_impl-members.html index bdbe280..ae0ee3c 100644 --- a/docs/html/classarduino_1_1_remote_serial_impl-members.html +++ b/docs/html/classarduino_1_1_remote_serial_impl-members.html @@ -69,24 +69,24 @@
    -
    arduino::RemoteSerialImpl Member List
    +
    arduino::RemoteSerialClass Member List
    -

    This is the complete list of members for arduino::RemoteSerialImpl, including all inherited members.

    +

    This is the complete list of members for arduino::RemoteSerialClass, including all inherited members.

    - + - - + + - + @@ -97,17 +97,17 @@ - + - - - + + + - + @@ -137,27 +137,27 @@ - - - + + + - - + + - - + + - +
    _startMillis (defined in arduino::Stream)arduino::Streamprotected
    _timeout (defined in arduino::Stream)arduino::Streamprotected
    available() (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplinlinevirtual
    available() (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassinlinevirtual
    availableForWrite() (defined in arduino::Print)arduino::Printinlinevirtual
    begin(unsigned long baudrate) (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplinlinevirtual
    begin(unsigned long baudrate, uint16_t config) (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplinlinevirtual
    begin(unsigned long baudrate) (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassinlinevirtual
    begin(unsigned long baudrate, uint16_t config) (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassinlinevirtual
    clearWriteError() (defined in arduino::Print)arduino::Printinline
    end() (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplinlinevirtual
    end() (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassinlinevirtual
    find(const char *target) (defined in arduino::Stream)arduino::Stream
    find(const uint8_t *target) (defined in arduino::Stream)arduino::Streaminline
    find(const char *target, size_t length) (defined in arduino::Stream)arduino::Stream
    findUntil(const uint8_t *target, const char *terminator) (defined in arduino::Stream)arduino::Streaminline
    findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen) (defined in arduino::Stream)arduino::Stream
    findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) (defined in arduino::Stream)arduino::Streaminline
    flush() (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplinlinevirtual
    flush() (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassinlinevirtual
    getTimeout(void) (defined in arduino::Stream)arduino::Streaminline
    getWriteError() (defined in arduino::Print)arduino::Printinline
    max_buffer_len (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplprotectedstatic
    max_buffer_len (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplprotected
    no (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplprotected
    max_buffer_len (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassprotectedstatic
    max_buffer_len (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassprotected
    no (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassprotected
    parseFloat(LookaheadMode lookahead=SKIP_ALL, char ignore=NO_IGNORE_CHAR) (defined in arduino::Stream)arduino::Stream
    parseFloat(char ignore) (defined in arduino::Stream)arduino::Streaminlineprotected
    parseInt(LookaheadMode lookahead=SKIP_ALL, char ignore=NO_IGNORE_CHAR) (defined in arduino::Stream)arduino::Stream
    parseInt(char ignore) (defined in arduino::Stream)arduino::Streaminlineprotected
    peek() (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplinlinevirtual
    peek() (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassinlinevirtual
    peekNextDigit(LookaheadMode lookahead, bool detectDecimal) (defined in arduino::Stream)arduino::Streamprotected
    Print() (defined in arduino::Print)arduino::Printinline
    print(const __FlashStringHelper *) (defined in arduino::Print)arduino::Print
    println(double, int=2) (defined in arduino::Print)arduino::Print
    println(const Printable &) (defined in arduino::Print)arduino::Print
    println(void) (defined in arduino::Print)arduino::Print
    read() (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplinlinevirtual
    read_buffer (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplprotected
    readBytes(uint8_t *buffer, size_t length) (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplinlinevirtual
    read() (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassinlinevirtual
    read_buffer (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassprotected
    readBytes(uint8_t *buffer, size_t length) (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassinlinevirtual
    readBytes(char *buffer, size_t length) (defined in arduino::Stream)arduino::Stream
    readBytesUntil(char terminator, char *buffer, size_t length) (defined in arduino::Stream)arduino::Stream
    readBytesUntil(char terminator, uint8_t *buffer, size_t length) (defined in arduino::Stream)arduino::Streaminline
    readString() (defined in arduino::Stream)arduino::Stream
    readStringUntil(char terminator) (defined in arduino::Stream)arduino::Stream
    RemoteSerialImpl(Stream &stream, uint8_t no) (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplinline
    service (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplprotected
    RemoteSerialClass(Stream &stream, uint8_t no) (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassinline
    service (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassprotected
    setTimeout(unsigned long timeout) (defined in arduino::Stream)arduino::Stream
    setWriteError(int err=1) (defined in arduino::Print)arduino::Printinlineprotected
    Stream() (defined in arduino::Stream)arduino::Streaminline
    timedPeek() (defined in arduino::Stream)arduino::Streamprotected
    timedRead() (defined in arduino::Stream)arduino::Streamprotected
    write(uint8_t c) (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplinlinevirtual
    write(uint8_t *str, size_t len) (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplinlinevirtual
    write(uint8_t c) (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassinlinevirtual
    write(uint8_t *str, size_t len) (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassinlinevirtual
    write(const char *str) (defined in arduino::Print)arduino::Printinline
    write(const uint8_t *buffer, size_t size) (defined in arduino::Print)arduino::Printvirtual
    write(const char *buffer, size_t size) (defined in arduino::Print)arduino::Printinline
    write_buffer (defined in arduino::RemoteSerialImpl)arduino::RemoteSerialImplprotected
    write_buffer (defined in arduino::RemoteSerialClass)arduino::RemoteSerialClassprotected