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);
97 updateBufferedOutputs();
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) {
117 digitalWriteBuffered(pin, state);
118 updateBufferedOutputs();
119 }
120
127 virtual void digitalWriteBuffered(pin_int_t pin, PinStatus_t state) = 0;
128
137 updateBufferedInputs();
138 return digitalReadBuffered(pin);
139 }
140
147
156 virtual void analogWrite(pin_int_t pin, analog_t val) {
157 analogWriteBuffered(pin, val);
158 updateBufferedOutputs();
159 }
160
168
177 updateBufferedInputs();
178 return analogReadBuffered(pin);
179 }
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
237 pin_t operator[](pin_int_t pin) const;
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))
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(
298 &ExtendedIOElement::pinMode, //
299 [](ArduinoPin_t p, PinMode_t m) { ::pinMode(p, m); }, mode);
300}
304 pin.apply(
305 &ExtendedIOElement::digitalWrite, //
306 [](ArduinoPin_t p, PinStatus_t v) { ::digitalWrite(p, v); }, val);
307}
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}
324#ifndef ESP32
325 pin.apply(
326 &ExtendedIOElement::analogWrite, //
327 [](ArduinoPin_t p, analog_t v) { ::analogWrite(p, v); }, val);
328#else
329 pin.apply(
330 &ExtendedIOElement::analogWrite, //
331 [](ArduinoPin_t, analog_t) {}, val);
332#endif
333}
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) {
347 ::shiftOut(arduino_pin_cast(dataPin.elementPin),
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));
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(
378 &ExtendedIOElement::pinModeBuffered, //
379 [](ArduinoPin_t p, PinMode_t m) { ::pinMode(p, m); }, mode);
380}
384 pin.apply(
385 &ExtendedIOElement::digitalWriteBuffered, //
386 [](ArduinoPin_t p, PinStatus_t v) { ::digitalWrite(p, v); }, val);
387}
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}
404#ifndef ESP32
405 pin.apply(
406 &ExtendedIOElement::analogWriteBuffered, //
407 [](ArduinoPin_t p, analog_t v) { ::analogWrite(p, v); }, val);
408#else
409 pin.apply(
410 &ExtendedIOElement::analogWriteBuffered, //
411 [](ArduinoPin_t, analog_t) {}, val);
412#endif
413}
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
AH::function_traits< decltype(::digitalWrite)>::argument_t< 1 > PinStatus_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< 0 > ArduinoPin_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.
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.
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.
ExtendedIOElement & operator=(ExtendedIOElement &&)=delete
Move assignment.
virtual analog_t analogRead(pin_int_t pin)
Read the analog value of the given pin.
A class for serial-in/parallel-out shift registers, like the 74HC595 that are connected to the SPI bu...
void digitalWrite(pin_int_t pin, PinStatus_t val) override
Set the state of a given output 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.
uint16_t analog_t
The type returned from analogRead and similar functions.
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.