Arduino Helpers master
Utility library for Arduino
ExtendedIOElement.hpp
Go to the documentation of this file.
1/* ✔ */
2
3#pragma once
4
8
10
60class ExtendedIOElement : public UpdatableCRTP<ExtendedIOElement> {
61 protected:
69
74
79
80 public:
97 virtual void pinMode(pin_t pin, PinMode_t mode) {
98 pinModeBuffered(pin, mode);
100 }
101
108 virtual void pinModeBuffered(pin_t pin, PinMode_t mode) = 0;
109
118 virtual void digitalWrite(pin_t pin, PinStatus_t state) {
121 }
122
129 virtual void digitalWriteBuffered(pin_t pin, PinStatus_t state) = 0;
130
140 return digitalReadBuffered(pin);
141 }
142
149
158 virtual void analogWrite(pin_t pin, analog_t val) {
161 }
162
169 virtual void analogWriteBuffered(pin_t pin, analog_t val) = 0;
170
180 return analogReadBuffered(pin);
181 }
182
189
193 virtual void begin() = 0;
194
198 static void beginAll();
199
203 virtual void updateBufferedOutputs() = 0;
204
209 static void updateAllBufferedOutputs();
210
214 virtual void updateBufferedInputs() = 0;
215
220 static void updateAllBufferedInputs();
221
229 pin_t pin(pin_t pin) const;
230
239 pin_t operator[](pin_t pin) const;
240
246 pin_t getLength() const;
247
252 pin_t getEnd() const;
253
258 pin_t getStart() const;
259
264
265 private:
268 const pin_t end;
269 static pin_t offset;
270};
271
272namespace ExtIO {
273
275 explicit CachedExtIOPin(pin_t pin)
276 : element(pin == NO_PIN || isNativePin(pin) ? nullptr
277 : getIOElementOfPin(pin)),
278 elementPin(element ? pin - element->getStart() : pin) {}
279
280 template <class FRet, class... FArgs, class Fallback>
281 FRet __attribute__((always_inline))
282 apply(FRet (ExtendedIOElement::*func)(pin_t, FArgs...), Fallback &&fallback,
283 FArgs... args) {
284 if (element != nullptr)
285 return (element->*func)(elementPin, args...);
286 else if (elementPin != NO_PIN)
287 return fallback(arduino_pin_cast(elementPin), args...);
288 else
289 return static_cast<FRet>(0);
290 }
291
294};
295
298inline void pinMode(CachedExtIOPin pin, PinMode_t mode) {
299 pin.apply(
301 [](ArduinoPin_t p, PinMode_t m) { ::pinMode(p, m); }, mode);
302}
306 pin.apply(
308 [](ArduinoPin_t p, PinStatus_t v) { ::digitalWrite(p, v); }, val);
309}
313 return pin.apply(&ExtendedIOElement::digitalRead, //
314 [](ArduinoPin_t p) { return ::digitalRead(p); });
315}
316
320 return pin.apply(&ExtendedIOElement::analogRead, //
321 [](ArduinoPin_t p) { return ::analogRead(p); });
322}
325inline void analogWrite(CachedExtIOPin pin, analog_t val) {
326#ifndef ESP32
327 pin.apply(
329 [](ArduinoPin_t p, analog_t v) { ::analogWrite(p, v); }, val);
330#else
331 pin.apply(
333 [](ArduinoPin_t, analog_t) {}, val);
334#endif
335}
338inline void analogWrite(CachedExtIOPin pin, int val) {
339 return analogWrite(pin, static_cast<analog_t>(val));
340}
341
343inline void shiftOut(CachedExtIOPin dataPin, CachedExtIOPin clockPin,
344 BitOrder_t bitOrder, uint8_t val) {
345 if (dataPin.elementPin == NO_PIN || clockPin.elementPin == NO_PIN)
346 return;
347 // Native version
348 if (dataPin.element == nullptr && clockPin.element == nullptr) {
350 arduino_pin_cast(clockPin.elementPin), bitOrder, val);
351 }
352 // ExtIO version
353 else if (dataPin.element != nullptr && clockPin.element != nullptr) {
354 const auto dataEl = dataPin.element;
355 const auto dataPinN = dataPin.elementPin;
356 const auto clockEl = clockPin.element;
357 const auto clockPinN = clockPin.elementPin;
358 for (uint8_t i = 0; i < 8; i++) {
359 uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
360 dataEl->digitalWrite(dataPinN, (val & mask) ? HIGH : LOW);
361 clockEl->digitalWrite(clockPinN, HIGH);
362 clockEl->digitalWrite(clockPinN, LOW);
363 }
364 }
365 // Mixed version (slow)
366 else {
367 for (uint8_t i = 0; i < 8; i++) {
368 uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
369 digitalWrite(dataPin, (val & mask) ? HIGH : LOW);
370 digitalWrite(clockPin, HIGH);
371 digitalWrite(clockPin, LOW);
372 }
373 }
374}
375
379 pin.apply(
381 [](ArduinoPin_t p, PinMode_t m) { ::pinMode(p, m); }, mode);
382}
386 pin.apply(
388 [](ArduinoPin_t p, PinStatus_t v) { ::digitalWrite(p, v); }, val);
389}
393 return pin.apply(&ExtendedIOElement::digitalReadBuffered, //
394 [](ArduinoPin_t p) { return ::digitalRead(p); });
395}
396
400 return pin.apply(&ExtendedIOElement::analogReadBuffered, //
401 [](ArduinoPin_t p) { return ::analogRead(p); });
402}
406#ifndef ESP32
407 pin.apply(
409 [](ArduinoPin_t p, analog_t v) { ::analogWrite(p, v); }, val);
410#else
411 pin.apply(
413 [](ArduinoPin_t, analog_t) {}, val);
414#endif
415}
418inline void analogWriteBuffered(CachedExtIOPin pin, int val) {
419 return analogWrite(pin, static_cast<analog_t>(val));
420}
421} // namespace ExtIO
422
424
constexpr PinStatus_t LOW
AH::function_traits< decltype(::digitalWrite)>::argument_t< 0 > ArduinoPin_t
uint8_t BitOrder_t
constexpr PinStatus_t HIGH
AH::function_traits< decltype(::pinMode)>::argument_t< 1 > PinMode_t
AH::function_traits< decltype(::digitalWrite)>::argument_t< 1 > PinStatus_t
uint16_t analog_t
The type returned from analogRead and similar functions.
constexpr pin_t NO_PIN
A special pin number that indicates an unused or invalid pin.
uint16_t pin_t
The type for Arduino pins (and ExtendedIOElement pins).
#define END_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
An abstract base class for Extended Input/Output elements.
pin_t getStart() const
Get the smallest global extended IO pin number that belongs to this extended IO element.
ExtendedIOElement(ExtendedIOElement &&)=default
Move constructor.
virtual void updateBufferedInputs()=0
Read the physical state into the input buffers.
ExtendedIOElement(const ExtendedIOElement &)=delete
Copying not allowed.
virtual void updateBufferedOutputs()=0
Write the internal state to the physical outputs.
pin_t pin(pin_t pin) const
Get the extended IO pin number of a given physical pin of this extended IO element.
pin_t getLength() const
Get the number of pins this IO element has.
virtual void analogWriteBuffered(pin_t pin, analog_t val)=0
Write an analog (or PWM) value to the software buffer given pin.
virtual analog_t analogRead(pin_t pin)
Read the analog value of the given pin.
virtual PinStatus_t digitalReadBuffered(pin_t pin)=0
Read the state of the given pin from the software buffer.
pin_t operator[](pin_t pin) const
Get the extended IO pin number of a given physical pin of this extended IO element.
virtual void digitalWriteBuffered(pin_t pin, PinStatus_t state)=0
Set the output of a given pin in the software buffer.
virtual void pinMode(pin_t pin, PinMode_t mode)
Set the mode of a given pin.
ExtendedIOElement & operator=(const ExtendedIOElement &)=delete
Copying not allowed.
virtual void begin()=0
Initialize the extended IO element.
ExtendedIOElement(pin_t length)
Create an ExtendedIOElement with the given number of pins.
static DoublyLinkedList< ExtendedIOElement > & getAll()
Get the list of all Extended IO elements.
virtual void analogWrite(pin_t pin, analog_t val)
Write an analog (or PWM) value to the given pin.
static void updateAllBufferedOutputs()
Write the internal states to the physical outputs for all extended IO elements.
pin_t getEnd() const
Get the largest global extended IO pin number that belongs to this extended IO element.
ExtendedIOElement & operator=(ExtendedIOElement &&)=delete
Move assignment.
static void beginAll()
Initialize all extended IO elements.
virtual void digitalWrite(pin_t pin, PinStatus_t state)
Set the output of the given pin to the given state.
virtual void pinModeBuffered(pin_t pin, PinMode_t mode)=0
Set the mode of a given pin in the software buffer.
static void updateAllBufferedInputs()
Read the physical state into the input buffers for all extended IO elements.
virtual analog_t analogReadBuffered(pin_t pin)=0
Read the analog value of the given pin from the software buffer.
virtual PinStatus_t digitalRead(pin_t pin)
Read the state of the given pin.
A super class for object that have to be updated regularly.
Definition: Updatable.hpp:28
Array< decltype(F{}(U{})), N > apply(const Array< U, N > &src, F f)
Apply a function to all elements of the array and return a copy.
void analogWriteBuffered(pin_t pin, analog_t val)
A buffered ExtIO version of the Arduino function.
bool isNativePin(pin_t pin)
Check if the given pin number is a real Arduino pin number, and not an ExtIO pin number.
void pinModeBuffered(pin_t pin, PinMode_t mode)
A buffered ExtIO version of the Arduino function.
ExtendedIOElement * getIOElementOfPin(pin_t pin)
Find the IO element of a given extended IO pin number.
void digitalWriteBuffered(pin_t pin, PinStatus_t val)
A buffered ExtIO version of the Arduino function.
void analogWrite(pin_t pin, analog_t val)
An ExtIO version of the Arduino function.
void pinMode(pin_t pin, PinMode_t mode)
An ExtIO version of the Arduino function.
PinStatus_t digitalReadBuffered(pin_t pin)
A buffered ExtIO version of the Arduino function.
analog_t analogRead(pin_t pin)
An ExtIO version of the Arduino function.
analog_t analogReadBuffered(pin_t pin)
A buffered ExtIO version of the Arduino function.
PinStatus_t digitalRead(pin_t pin)
An ExtIO version of the Arduino function.
void shiftOut(pin_t dataPin, pin_t clockPin, BitOrder_t bitOrder, uint8_t val)
An ExtIO version of the Arduino function.
void digitalWrite(pin_t pin, PinStatus_t val)
An ExtIO version of the Arduino function.
A namespace with alternatives to the standard Arduino IO functions that can be used with extended IO ...
PinStatus_t digitalRead(CachedExtIOPin pin)
An ExtIO version of the Arduino function.
analog_t analogRead(CachedExtIOPin pin)
An ExtIO version of the Arduino function.
ArduinoPin_t arduino_pin_cast(T t)
ExtendedIOElement * element