Control Surface  1.2.0
MIDI Control Surface library for Arduino
AnalogMultiplex.hpp
Go to the documentation of this file.
1 /* ✔ */
2 
3 #pragma once
4 
6 AH_DIAGNOSTIC_WERROR() // Enable errors on warnings
7 
8 #include "ExtendedInputOutput.hpp"
10 #include <AH/Containers/Array.hpp>
11 #include <stdlib.h>
12 
14 
27 template <uint8_t N>
29  public:
44  AnalogMultiplex(pin_t analogPin, const Array<pin_t, N> &addressPins,
45  pin_t enablePin = NO_PIN)
46  : analogPin(analogPin), addressPins(addressPins), enablePin(enablePin) {
47  }
48 
64  void pinMode(pin_t pin, PinMode_t mode) override;
65 
69  void pinModeBuffered(pin_t pin, PinMode_t mode) override;
70 
75  void digitalWrite(pin_t, PinStatus_t) override // LCOV_EXCL_LINE
76  __attribute__((deprecated)) {} // LCOV_EXCL_LINE
77 
81  void digitalWriteBuffered(pin_t, PinStatus_t) override // LCOV_EXCL_LINE
82  __attribute__((deprecated)) {} // LCOV_EXCL_LINE
83 
90  int digitalRead(pin_t pin) override;
91 
95  int digitalReadBuffered(pin_t pin) override;
96 
103  analog_t analogRead(pin_t pin) override;
104 
108  analog_t analogReadBuffered(pin_t pin) override;
109 
114  void analogWrite(pin_t, analog_t) override // LCOV_EXCL_LINE
115  __attribute__((deprecated)) {} // LCOV_EXCL_LINE
116 
120  void analogWriteBuffered(pin_t, analog_t) override // LCOV_EXCL_LINE
121  __attribute__((deprecated)) {} // LCOV_EXCL_LINE
122 
127  void begin() override;
128 
133  void updateBufferedOutputs() override {} // LCOV_EXCL_LINE
134 
139  void updateBufferedInputs() override {} // LCOV_EXCL_LINE
140 
141  private:
142  const pin_t analogPin;
143  const Array<pin_t, N> addressPins;
144  const pin_t enablePin;
145 
153  void setMuxAddress(uint8_t address);
154 
161  void prepareReading(uint8_t address);
162 
166  void afterReading();
167 
168  // The enable pin is active low.
169  constexpr static auto MUX_ENABLED = LOW;
170  constexpr static auto MUX_DISABLED = HIGH;
171 };
172 
179 using CD74HC4067 = AnalogMultiplex<4>;
180 
187 using CD74HC4051 = AnalogMultiplex<3>;
188 
189 // -------------------------------------------------------------------------- //
190 
191 template <uint8_t N>
192 void AnalogMultiplex<N>::pinMode(pin_t, PinMode_t mode) {
193  ExtIO::pinMode(analogPin, mode);
194 }
195 
196 template <uint8_t N>
197 void AnalogMultiplex<N>::pinModeBuffered(pin_t, PinMode_t mode) {
198  AnalogMultiplex<N>::pinMode(analogPin, mode);
199 }
200 
201 template <uint8_t N>
202 int AnalogMultiplex<N>::digitalRead(pin_t pin) {
203  prepareReading(pin);
204  int result = ExtIO::digitalRead(analogPin);
205  afterReading();
206  return result;
207 }
208 
209 template <uint8_t N>
210 int AnalogMultiplex<N>::digitalReadBuffered(pin_t pin) {
211  return AnalogMultiplex<N>::digitalRead(pin);
212 }
213 
214 template <uint8_t N>
215 analog_t AnalogMultiplex<N>::analogRead(pin_t pin) {
216  prepareReading(pin);
217  ExtIO::analogRead(analogPin); // Discard first reading
218  analog_t result = ExtIO::analogRead(analogPin);
219  afterReading();
220  return result;
221 }
222 
223 template <uint8_t N>
224 analog_t AnalogMultiplex<N>::analogReadBuffered(pin_t pin) {
225  return AnalogMultiplex<N>::analogRead(pin);
226 }
227 
228 template <uint8_t N>
229 void AnalogMultiplex<N>::begin() {
230  for (const pin_t &addressPin : addressPins)
231  ExtIO::pinMode(addressPin, OUTPUT);
232  if (enablePin != NO_PIN) {
233  ExtIO::pinMode(enablePin, OUTPUT);
234  ExtIO::digitalWrite(enablePin, MUX_DISABLED);
235  }
236 }
237 
238 template <uint8_t N>
239 void AnalogMultiplex<N>::setMuxAddress(uint8_t address) {
240  uint8_t mask = 1;
241  for (const pin_t &addressPin : addressPins) {
242  ExtIO::digitalWrite(addressPin, (address & mask) != 0 ? HIGH : LOW);
243  mask <<= 1;
244  }
245 #if !defined(__AVR__) && defined(ARDUINO)
246  delayMicroseconds(5);
247 #endif
248 }
249 
250 template <uint8_t N>
251 void AnalogMultiplex<N>::prepareReading(uint8_t address) {
252  setMuxAddress(address);
253  if (enablePin != NO_PIN)
254  ExtIO::digitalWrite(enablePin, MUX_ENABLED);
255 }
256 
257 template <uint8_t N>
258 void AnalogMultiplex<N>::afterReading() {
259  if (enablePin != NO_PIN)
260  ExtIO::digitalWrite(enablePin, MUX_DISABLED);
261 }
262 
263 END_AH_NAMESPACE
264 
265 AH_DIAGNOSTIC_POP()
Warnings.hpp
Array.hpp
AH::AnalogMultiplex
A class for reading multiplexed analog inputs.
Definition: AnalogMultiplex.hpp:28
StaticSizeExtendedIOElement.hpp
AH::StaticSizeExtendedIOElement
A class for ExtendedIOElements with a fixed size.
Definition: StaticSizeExtendedIOElement.hpp:19
AH_DIAGNOSTIC_WERROR
#define AH_DIAGNOSTIC_WERROR()
Definition: Warnings.hpp:35
BEGIN_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
Definition: AH/Settings/NamespaceSettings.hpp:9