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