Control Surface main
MIDI Control Surface library for Arduino
Loading...
Searching...
No Matches
ExtendedIOElement.hpp
Go to the documentation of this file.
1/* ✔ */
2
3#pragma once
4
8
10
58class ExtendedIOElement : public UpdatableCRTP<ExtendedIOElement> {
59 protected:
67
72
77
78 public:
95 virtual void pinMode(pin_int_t pin, PinMode_t mode) {
96 pinModeBuffered(pin, mode);
98 }
99
106 virtual void pinModeBuffered(pin_int_t pin, PinMode_t mode) = 0;
107
116 virtual void digitalWrite(pin_int_t pin, PinStatus_t state) {
119 }
120
128
140
147
156 virtual void analogWrite(pin_int_t pin, analog_t val) {
159 }
160
168
180
187
191 virtual void begin() = 0;
192
196 static void beginAll();
197
201 virtual void updateBufferedOutputs() = 0;
202
207 static void updateAllBufferedOutputs();
208
212 virtual void updateBufferedInputs() = 0;
213
218 static void updateAllBufferedInputs();
219
227 pin_t pin(pin_int_t pin) const;
228
238
244 pin_int_t getLength() const;
245
250 pin_t getEnd() const;
251
256 pin_t getStart() const;
257
262
263 private:
266 const pin_t end;
267 static pin_t offset;
268};
269
270namespace ExtIO {
271
273 explicit CachedExtIOPin(pin_t pin)
274 : element(pin == NO_PIN || isNativePin(pin) ? nullptr
275 : getIOElementOfPin(pin)),
276 elementPin(element ? pin - element->getStart() : pin.pin) {}
277
278 template <class FRet, class... FArgs, class Fallback>
279 FRet __attribute__((always_inline))
280 apply(FRet (ExtendedIOElement::*func)(pin_int_t, FArgs...),
281 Fallback &&fallback, FArgs... args) {
282 if (element != nullptr)
283 return (element->*func)(elementPin, args...);
284 else if (elementPin != NO_PIN_INT)
285 return fallback(arduino_pin_cast(elementPin), args...);
286 else
287 return static_cast<FRet>(0);
288 }
289
292};
293
296inline void pinMode(CachedExtIOPin pin, PinMode_t mode) {
297 pin.apply(
299 [](ArduinoPin_t p, PinMode_t m) { ::pinMode(p, m); }, mode);
300}
301
304 pin.apply(
306 [](ArduinoPin_t p, PinStatus_t v) { ::digitalWrite(p, v); }, val);
307}
308
311 return pin.apply(&ExtendedIOElement::digitalRead, //
312 [](ArduinoPin_t p) { return ::digitalRead(p); });
313}
314
318 return pin.apply(&ExtendedIOElement::analogRead, //
319 [](ArduinoPin_t p) { return ::analogRead(p); });
320}
321
323inline void analogWrite(CachedExtIOPin pin, analog_t val) {
324#ifndef ESP32
325 pin.apply(
327 [](ArduinoPin_t p, analog_t v) { ::analogWrite(p, v); }, val);
328#else
329 pin.apply(
331 [](ArduinoPin_t, analog_t) {}, val);
332#endif
333}
334
336inline void analogWrite(CachedExtIOPin pin, int val) {
337 return analogWrite(pin, static_cast<analog_t>(val));
338}
339
341inline void shiftOut(CachedExtIOPin dataPin, CachedExtIOPin clockPin,
342 BitOrder_t bitOrder, uint8_t val) {
343 if (dataPin.elementPin == NO_PIN || clockPin.elementPin == NO_PIN)
344 return;
345 // Native version
346 if (dataPin.element == nullptr && clockPin.element == nullptr) {
348 arduino_pin_cast(clockPin.elementPin), bitOrder, val);
349 }
350 // ExtIO version
351 else if (dataPin.element != nullptr && clockPin.element != nullptr) {
352 const auto dataEl = dataPin.element;
353 const auto dataPinN = dataPin.elementPin;
354 const auto clockEl = clockPin.element;
355 const auto clockPinN = clockPin.elementPin;
356 for (uint8_t i = 0; i < 8; i++) {
357 uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
358 dataEl->digitalWrite(dataPinN, (val & mask) ? HIGH : LOW);
359 clockEl->digitalWrite(clockPinN, HIGH);
360 clockEl->digitalWrite(clockPinN, LOW);
361 }
362 }
363 // Mixed version (slow)
364 else {
365 for (uint8_t i = 0; i < 8; i++) {
366 uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
367 digitalWrite(dataPin, (val & mask) ? HIGH : LOW);
368 digitalWrite(clockPin, HIGH);
369 digitalWrite(clockPin, LOW);
370 }
371 }
372}
373
377 pin.apply(
379 [](ArduinoPin_t p, PinMode_t m) { ::pinMode(p, m); }, mode);
380}
381
384 pin.apply(
386 [](ArduinoPin_t p, PinStatus_t v) { ::digitalWrite(p, v); }, val);
387}
388
391 return pin.apply(&ExtendedIOElement::digitalReadBuffered, //
392 [](ArduinoPin_t p) { return ::digitalRead(p); });
393}
394
398 return pin.apply(&ExtendedIOElement::analogReadBuffered, //
399 [](ArduinoPin_t p) { return ::analogRead(p); });
400}
401
404#ifndef ESP32
405 pin.apply(
407 [](ArduinoPin_t p, analog_t v) { ::analogWrite(p, v); }, val);
408#else
409 pin.apply(
411 [](ArduinoPin_t, analog_t) {}, val);
412#endif
413}
414
416inline void analogWriteBuffered(CachedExtIOPin pin, int val) {
417 return analogWrite(pin, static_cast<analog_t>(val));
418}
419} // namespace ExtIO
420
421using ExtIO::CachedExtIOPin;
422
#define END_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
constexpr PinStatus_t LOW
uint8_t BitOrder_t
constexpr PinStatus_t HIGH
AH::function_traits< decltype(::digitalWrite)>::argument_t< 0 > ArduinoPin_t
AH::function_traits< decltype(::pinMode)>::argument_t< 1 > PinMode_t
AH::function_traits< decltype(::digitalWrite)>::argument_t< 1 > PinStatus_t
An abstract base class for Extended Input/Output elements.
virtual void digitalWriteBuffered(pin_int_t pin, PinStatus_t state)=0
Set the output of a given pin in the software buffer.
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 PinStatus_t digitalReadBuffered(pin_int_t pin)=0
Read the state of the given pin from the software buffer.
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.
virtual void digitalWrite(pin_int_t pin, PinStatus_t state)
Set the output of the given pin to the given state.
ExtendedIOElement(pin_int_t length)
Create an ExtendedIOElement with the given number of pins.
pin_int_t getLength() const
Get the number of pins this IO element has.
virtual void analogWriteBuffered(pin_int_t pin, analog_t val)=0
Write an analog (or PWM) value to the software buffer given pin.
virtual PinStatus_t digitalRead(pin_int_t pin)
Read the state of the given pin.
virtual void pinMode(pin_int_t pin, PinMode_t mode)
Set the mode of a given pin.
virtual void pinModeBuffered(pin_int_t pin, PinMode_t mode)=0
Set the mode of a given pin in the software buffer.
virtual void analogWrite(pin_int_t pin, analog_t val)
Write an analog (or PWM) value to the given pin.
virtual analog_t analogReadBuffered(pin_int_t pin)=0
Read the analog value of the given pin from the software buffer.
ExtendedIOElement & operator=(const ExtendedIOElement &)=delete
Copying not allowed.
virtual void begin()=0
Initialize the extended IO element.
static DoublyLinkedList< ExtendedIOElement > & getAll()
Get the list of all Extended IO elements.
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.
virtual analog_t analogRead(pin_int_t pin)
Read the analog value of the given pin.
static void beginAll()
Initialize all extended IO elements.
pin_t operator[](pin_int_t pin) const
Get the extended IO pin number of a given physical pin of this extended IO element.
pin_t pin(pin_int_t pin) const
Get the extended IO pin number of a given physical pin of this extended IO element.
static void updateAllBufferedInputs()
Read the physical state into the input buffers for all extended IO elements.
UpdatableCRTP() __attribute__((no_sanitize("undefined")))
Definition Updatable.hpp:50
A class for doubly linked lists.
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 ...
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.
constexpr pin_int_t NO_PIN_INT
constexpr ArduinoPin_t arduino_pin_cast(T t)
uint_fast16_t pin_int_t
Integer type used internally to store the index of (extended) GPIO pins.
Type for storing pin numbers of Extended Input/Output elements.