Control Surface master
MIDI Control Surface library for Arduino
ExtendedIOElement.hpp
Go to the documentation of this file.
1/* ✔ */
2
3#pragma once
4
6AH_DIAGNOSTIC_WERROR() // Enable errors on warnings
7
8#include "ExtendedInputOutput.hpp"
11
13
63class ExtendedIOElement : public UpdatableCRTP<ExtendedIOElement> {
64 protected:
72
77
82
83 public:
100 virtual void pinMode(pin_t pin, PinMode_t mode) {
101 pinModeBuffered(pin, mode);
102 updateBufferedOutputs();
103 }
104
111 virtual void pinModeBuffered(pin_t pin, PinMode_t mode) = 0;
112
121 virtual void digitalWrite(pin_t pin, PinStatus_t state) {
122 digitalWriteBuffered(pin, state);
123 updateBufferedOutputs();
124 }
125
132 virtual void digitalWriteBuffered(pin_t pin, PinStatus_t state) = 0;
133
142 updateBufferedInputs();
143 return digitalReadBuffered(pin);
144 }
145
152
161 virtual void analogWrite(pin_t pin, analog_t val) {
162 analogWriteBuffered(pin, val);
163 updateBufferedOutputs();
164 }
165
172 virtual void analogWriteBuffered(pin_t pin, analog_t val) = 0;
173
181 virtual analog_t analogRead(pin_t pin) {
182 updateBufferedInputs();
183 return analogReadBuffered(pin);
184 }
185
192
196 virtual void begin() = 0;
197
201 static void beginAll();
202
206 virtual void updateBufferedOutputs() = 0;
207
212 static void updateAllBufferedOutputs();
213
217 virtual void updateBufferedInputs() = 0;
218
223 static void updateAllBufferedInputs();
224
232 pin_t pin(pin_t pin) const;
233
242 pin_t operator[](pin_t pin) const;
243
249 pin_t getLength() const;
250
255 pin_t getEnd() const;
256
261 pin_t getStart() const;
262
267
268 private:
271 const pin_t end;
272 static pin_t offset;
273};
274
275namespace ExtIO {
276
278 explicit CachedExtIOPin(pin_t pin)
279 : element(pin == NO_PIN || isNativePin(pin) ? nullptr
280 : getIOElementOfPin(pin)),
281 elementPin(element ? pin - element->getStart() : pin) {}
282
283 template <class FRet, class... FArgs, class Fallback>
284 FRet __attribute__((always_inline))
285 apply(FRet (ExtendedIOElement::*func)(pin_t, FArgs...), Fallback &&fallback,
286 FArgs... args) {
287 if (element != nullptr)
288 return (element->*func)(elementPin, args...);
289 else if (elementPin != NO_PIN)
290 return fallback(arduino_pin_cast(elementPin), args...);
291 else
292 return static_cast<FRet>(0);
293 }
294
297};
298
301inline void pinMode(CachedExtIOPin pin, PinMode_t mode) {
302 pin.apply(
304 [](ArduinoPin_t p, PinMode_t m) { ::pinMode(p, m); }, mode);
305}
309 pin.apply(
311 [](ArduinoPin_t p, PinStatus_t v) { ::digitalWrite(p, v); }, val);
312}
316 return pin.apply(&ExtendedIOElement::digitalRead, //
317 [](ArduinoPin_t p) { return ::digitalRead(p); });
318}
319
323 return pin.apply(&ExtendedIOElement::analogRead, //
324 [](ArduinoPin_t p) { return ::analogRead(p); });
325}
328inline void analogWrite(CachedExtIOPin pin, analog_t val) {
329#ifndef ESP32
330 pin.apply(
332 [](ArduinoPin_t p, analog_t v) { ::analogWrite(p, v); }, val);
333#else
334 pin.apply(
336 [](ArduinoPin_t, analog_t) {}, val);
337#endif
338}
341inline void analogWrite(CachedExtIOPin pin, int val) {
342 return analogWrite(pin, static_cast<analog_t>(val));
343}
344
346inline void shiftOut(CachedExtIOPin dataPin, CachedExtIOPin clockPin,
347 BitOrder_t bitOrder, uint8_t val) {
348 if (dataPin.elementPin == NO_PIN || clockPin.elementPin == NO_PIN)
349 return;
350 // Native version
351 if (dataPin.element == nullptr && clockPin.element == nullptr) {
353 arduino_pin_cast(clockPin.elementPin), bitOrder, val);
354 }
355 // ExtIO version
356 else if (dataPin.element != nullptr && clockPin.element != nullptr) {
357 const auto dataEl = dataPin.element;
358 const auto dataPinN = dataPin.elementPin;
359 const auto clockEl = clockPin.element;
360 const auto clockPinN = clockPin.elementPin;
361 for (uint8_t i = 0; i < 8; i++) {
362 uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
363 dataEl->digitalWrite(dataPinN, (val & mask) ? HIGH : LOW);
364 clockEl->digitalWrite(clockPinN, HIGH);
365 clockEl->digitalWrite(clockPinN, LOW);
366 }
367 }
368 // Mixed version (slow)
369 else {
370 for (uint8_t i = 0; i < 8; i++) {
371 uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
372 digitalWrite(dataPin, (val & mask) ? HIGH : LOW);
373 digitalWrite(clockPin, HIGH);
374 digitalWrite(clockPin, LOW);
375 }
376 }
377}
378
382 pin.apply(
384 [](ArduinoPin_t p, PinMode_t m) { ::pinMode(p, m); }, mode);
385}
389 pin.apply(
391 [](ArduinoPin_t p, PinStatus_t v) { ::digitalWrite(p, v); }, val);
392}
396 return pin.apply(&ExtendedIOElement::digitalReadBuffered, //
397 [](ArduinoPin_t p) { return ::digitalRead(p); });
398}
399
403 return pin.apply(&ExtendedIOElement::analogReadBuffered, //
404 [](ArduinoPin_t p) { return ::analogRead(p); });
405}
409#ifndef ESP32
410 pin.apply(
412 [](ArduinoPin_t p, analog_t v) { ::analogWrite(p, v); }, val);
413#else
414 pin.apply(
416 [](ArduinoPin_t, analog_t) {}, val);
417#endif
418}
421inline void analogWriteBuffered(CachedExtIOPin pin, int val) {
422 return analogWrite(pin, static_cast<analog_t>(val));
423}
424} // namespace ExtIO
425
426using ExtIO::CachedExtIOPin;
427
429
#define END_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
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
#define AH_DIAGNOSTIC_POP()
Definition: Warnings.hpp:36
#define AH_DIAGNOSTIC_WERROR()
Definition: Warnings.hpp:35
An abstract base class for Extended Input/Output elements.
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.
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.
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.
virtual void analogWrite(pin_t pin, analog_t val)
Write an analog (or PWM) value to the given pin.
ExtendedIOElement & operator=(ExtendedIOElement &&)=delete
Move assignment.
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.
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:32
A class for doubly linked lists.
Definition: LinkedList.hpp:25
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.
ExtendedIOElement * getIOElementOfPin(pin_t pin)
Find the IO element of a given extended IO pin number.
bool isNativePin(pin_t pin)
Check if the given pin number is a real Arduino pin number, and not an ExtIO pin number.
void shiftOut(CachedExtIOPin dataPin, CachedExtIOPin clockPin, BitOrder_t bitOrder, uint8_t val)
An ExtIO version of the Arduino function.
void digitalWrite(CachedExtIOPin pin, PinStatus_t val)
An ExtIO version of the Arduino function.
void digitalWriteBuffered(CachedExtIOPin pin, PinStatus_t val)
A buffered ExtIO version of the Arduino function.
analog_t analogReadBuffered(CachedExtIOPin pin)
A buffered ExtIO version of the Arduino function.
analog_t analogRead(CachedExtIOPin pin)
An ExtIO version of the Arduino function.
void analogWriteBuffered(CachedExtIOPin pin, int val)
A buffered ExtIO version of the Arduino function.
void pinMode(CachedExtIOPin pin, PinMode_t mode)
An ExtIO version of the Arduino function.
PinStatus_t digitalRead(CachedExtIOPin pin)
An ExtIO version of the Arduino function.
void analogWrite(CachedExtIOPin pin, int val)
An ExtIO version of the Arduino function.
void pinModeBuffered(CachedExtIOPin pin, PinMode_t mode)
A buffered ExtIO version of the Arduino function.
PinStatus_t digitalReadBuffered(CachedExtIOPin pin)
A buffered ExtIO version of the Arduino function.
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.
ArduinoPin_t arduino_pin_cast(T t)
uint16_t pin_t
The type for Arduino pins (and ExtendedIOElement pins).