Line data Source code
1 : #include "ExtendedInputOutput.hpp"
2 : #include "ExtendedIOElement.hpp"
3 : #include <AH/Error/Error.hpp>
4 :
5 : BEGIN_AH_NAMESPACE
6 :
7 : namespace ExtIO {
8 :
9 : template <class T>
10 90 : static bool inRange(T target, T start, T end) {
11 90 : return target >= start && target < end;
12 : }
13 :
14 80 : ExtendedIOElement *getIOElementOfPinOrNull(pin_t pin) {
15 92 : for (auto &el : ExtendedIOElement::getAll())
16 91 : if (pin < el.getStart())
17 1 : break;
18 90 : else if (inRange(pin, el.getStart(), el.getEnd()))
19 78 : return ⪙
20 2 : return nullptr;
21 : }
22 :
23 80 : ExtendedIOElement *getIOElementOfPin(pin_t pin) {
24 80 : auto *el = getIOElementOfPinOrNull(pin);
25 80 : if (el == nullptr)
26 2 : FATAL_ERROR(
27 : F("The given pin does not correspond to an Extended IO element."),
28 : 0x8888);
29 78 : return el;
30 : }
31 :
32 : template <class T>
33 16 : ArduinoPin_t arduino_pin_cast(T t) {
34 16 : return static_cast<ArduinoPin_t>(t);
35 : }
36 :
37 71 : void pinMode(pin_t pin, PinMode_t mode) {
38 71 : if (pin == NO_PIN)
39 : return; // LCOV_EXCL_LINE
40 70 : else if (isNativePin(pin)) {
41 64 : ::pinMode(pin, mode);
42 : } else {
43 6 : auto el = getIOElementOfPin(pin);
44 6 : el->pinMode(pin - el->getStart(), mode);
45 : }
46 : }
47 1 : void pinMode(int pin, PinMode_t mode) {
48 1 : ::pinMode(arduino_pin_cast(pin), mode);
49 1 : }
50 :
51 129 : void digitalWrite(pin_t pin, PinStatus_t val) {
52 129 : if (pin == NO_PIN)
53 : return; // LCOV_EXCL_LINE
54 128 : else if (isNativePin(pin)) {
55 107 : ::digitalWrite(pin, val);
56 : } else {
57 21 : auto el = getIOElementOfPin(pin);
58 21 : el->digitalWrite(pin - el->getStart(), val);
59 : }
60 : }
61 1 : void digitalWrite(int pin, PinStatus_t val) {
62 1 : ::digitalWrite(arduino_pin_cast(pin), val);
63 1 : }
64 :
65 99 : PinStatus_t digitalRead(pin_t pin) {
66 99 : if (pin == NO_PIN)
67 : return LOW; // LCOV_EXCL_LINE
68 98 : else if (isNativePin(pin)) {
69 89 : return ::digitalRead(pin);
70 : } else {
71 9 : auto el = getIOElementOfPin(pin);
72 7 : return el->digitalRead(pin - el->getStart());
73 : }
74 : }
75 1 : PinStatus_t digitalRead(int pin) {
76 1 : return ::digitalRead(arduino_pin_cast(pin));
77 : }
78 :
79 61 : analog_t analogRead(pin_t pin) {
80 61 : if (pin == NO_PIN)
81 : return 0; // LCOV_EXCL_LINE
82 60 : else if (isNativePin(pin)) {
83 45 : return ::analogRead(pin);
84 : } else {
85 15 : auto el = getIOElementOfPin(pin);
86 15 : return el->analogRead(pin - el->getStart());
87 : }
88 : }
89 1 : analog_t analogRead(int pin) { return ::analogRead(arduino_pin_cast(pin)); }
90 :
91 8 : void analogWrite(pin_t pin, analog_t val) {
92 8 : if (pin == NO_PIN)
93 : return; // LCOV_EXCL_LINE
94 7 : else if (isNativePin(pin)) {
95 : #ifndef ESP32
96 2 : ::analogWrite(pin, val);
97 : #endif
98 : } else {
99 5 : auto el = getIOElementOfPin(pin);
100 5 : el->analogWrite(pin - el->getStart(), val);
101 : }
102 : }
103 5 : void analogWrite(pin_t pin, int val) { analogWrite(pin, (analog_t)val); }
104 : #ifndef ESP32
105 1 : void analogWrite(int pin, analog_t val) {
106 1 : ::analogWrite(arduino_pin_cast(pin), val);
107 1 : }
108 1 : void analogWrite(int pin, int val) {
109 1 : ::analogWrite(arduino_pin_cast(pin), val);
110 1 : }
111 : #endif
112 :
113 3 : void pinModeBuffered(pin_t pin, PinMode_t mode) {
114 3 : if (pin == NO_PIN)
115 : return; // LCOV_EXCL_LINE
116 3 : else if (isNativePin(pin)) {
117 1 : ::pinMode(pin, mode);
118 : } else {
119 2 : auto el = getIOElementOfPin(pin);
120 2 : el->pinModeBuffered(pin - el->getStart(), mode);
121 : }
122 : }
123 :
124 2 : void digitalWriteBuffered(pin_t pin, PinStatus_t val) {
125 2 : if (pin == NO_PIN)
126 : return; // LCOV_EXCL_LINE
127 2 : else if (isNativePin(pin)) {
128 1 : ::digitalWrite(pin, val);
129 : } else {
130 1 : auto el = getIOElementOfPin(pin);
131 1 : el->digitalWriteBuffered(pin - el->getStart(), val);
132 : }
133 : }
134 :
135 3 : PinStatus_t digitalReadBuffered(pin_t pin) {
136 3 : if (pin == NO_PIN)
137 : return LOW; // LCOV_EXCL_LINE
138 3 : else if (isNativePin(pin)) {
139 1 : return ::digitalRead(pin);
140 : } else {
141 2 : auto el = getIOElementOfPin(pin);
142 2 : return el->digitalReadBuffered(pin - el->getStart());
143 : }
144 : }
145 :
146 3 : analog_t analogReadBuffered(pin_t pin) {
147 3 : if (pin == NO_PIN)
148 : return 0; // LCOV_EXCL_LINE
149 3 : else if (isNativePin(pin)) {
150 1 : return ::analogRead(pin);
151 : } else {
152 2 : auto el = getIOElementOfPin(pin);
153 2 : return el->analogReadBuffered(pin - el->getStart());
154 : }
155 : return 0;
156 : }
157 :
158 4 : void analogWriteBuffered(pin_t pin, analog_t val) {
159 4 : if (pin == NO_PIN)
160 : return; // LCOV_EXCL_LINE
161 4 : else if (isNativePin(pin)) {
162 : #ifndef ESP32
163 2 : ::analogWrite(pin, val);
164 : #endif
165 : } else {
166 2 : auto el = getIOElementOfPin(pin);
167 2 : el->analogWriteBuffered(pin - el->getStart(), val);
168 : }
169 : }
170 2 : void analogWriteBuffered(pin_t pin, int val) {
171 2 : analogWriteBuffered(pin, (analog_t)val);
172 2 : }
173 :
174 6 : void shiftOut(pin_t dataPin, pin_t clockPin, BitOrder_t bitOrder, uint8_t val) {
175 6 : if (dataPin == NO_PIN || clockPin == NO_PIN)
176 1 : return;
177 : // Native version
178 5 : if (isNativePin(dataPin) && isNativePin(clockPin)) {
179 1 : ::shiftOut((int)dataPin, (int)clockPin, bitOrder, val);
180 : }
181 : // ExtIO version
182 4 : else if (!isNativePin(dataPin) && !isNativePin(clockPin)) {
183 2 : auto dataEl = getIOElementOfPin(dataPin);
184 2 : auto dataPinN = dataPin - dataEl->getStart();
185 2 : auto clockEl = getIOElementOfPin(clockPin);
186 2 : auto clockPinN = clockPin - clockEl->getStart();
187 18 : for (uint8_t i = 0; i < 8; i++) {
188 16 : uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
189 16 : dataEl->digitalWrite(dataPinN, (val & mask) ? HIGH : LOW);
190 16 : clockEl->digitalWrite(clockPinN, HIGH);
191 16 : clockEl->digitalWrite(clockPinN, LOW);
192 : }
193 : }
194 : // Mixed version (slow)
195 : else {
196 18 : for (uint8_t i = 0; i < 8; i++) {
197 16 : uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
198 16 : digitalWrite(dataPin, (val & mask) ? HIGH : LOW);
199 16 : digitalWrite(clockPin, HIGH);
200 16 : digitalWrite(clockPin, LOW);
201 : }
202 : }
203 : }
204 1 : void shiftOut(int dataPin, int clockPin, BitOrder_t bitOrder, uint8_t val) {
205 1 : ::shiftOut(arduino_pin_cast(dataPin), arduino_pin_cast(clockPin), bitOrder,
206 : val);
207 1 : }
208 :
209 : #if UINT16_MAX != UINT_MAX
210 1 : void pinMode(unsigned int pin, PinMode_t mode) {
211 1 : ::pinMode(arduino_pin_cast(pin), mode);
212 1 : }
213 1 : void digitalWrite(unsigned int pin, PinStatus_t val) {
214 1 : ::digitalWrite(arduino_pin_cast(pin), val);
215 1 : }
216 1 : PinStatus_t digitalRead(unsigned int pin) {
217 1 : return ::digitalRead(arduino_pin_cast(pin));
218 : }
219 1 : analog_t analogRead(unsigned int pin) {
220 1 : return ::analogRead(arduino_pin_cast(pin));
221 : }
222 : #ifndef ESP32
223 1 : void analogWrite(unsigned int pin, analog_t val) {
224 1 : ::analogWrite(arduino_pin_cast(pin), val);
225 1 : }
226 1 : void analogWrite(unsigned int pin, int val) {
227 1 : ::analogWrite(arduino_pin_cast(pin), val);
228 1 : }
229 : #endif
230 1 : void shiftOut(unsigned int dataPin, unsigned int clockPin, BitOrder_t bitOrder,
231 : uint8_t val) {
232 1 : ::shiftOut(arduino_pin_cast(dataPin), arduino_pin_cast(clockPin), bitOrder,
233 : val);
234 1 : }
235 : #endif
236 :
237 : } // namespace ExtIO
238 :
239 : END_AH_NAMESPACE
|