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 204 : void pinMode(pin_t pin, PinMode_t mode) {
33 204 : if (pin == NO_PIN)
34 : return; // LCOV_EXCL_LINE
35 203 : else if (isNativePin(pin)) {
36 197 : ::pinMode(arduino_pin_cast(pin), mode);
37 : } else {
38 6 : auto el = getIOElementOfPin(pin);
39 6 : el->pinMode(pin - el->getStart(), mode);
40 : }
41 : }
42 :
43 203 : void digitalWrite(pin_t pin, PinStatus_t val) {
44 203 : if (pin == NO_PIN)
45 : return; // LCOV_EXCL_LINE
46 202 : else if (isNativePin(pin)) {
47 181 : ::digitalWrite(arduino_pin_cast(pin), val);
48 : } else {
49 21 : auto el = getIOElementOfPin(pin);
50 21 : el->digitalWrite(pin - el->getStart(), val);
51 : }
52 : }
53 :
54 303 : PinStatus_t digitalRead(pin_t pin) {
55 303 : if (pin == NO_PIN)
56 : return LOW; // LCOV_EXCL_LINE
57 302 : else if (isNativePin(pin)) {
58 293 : return ::digitalRead(arduino_pin_cast(pin));
59 : } else {
60 9 : auto el = getIOElementOfPin(pin);
61 7 : return el->digitalRead(pin - el->getStart());
62 : }
63 : }
64 :
65 85 : analog_t analogRead(pin_t pin) {
66 85 : if (pin == NO_PIN)
67 : return 0; // LCOV_EXCL_LINE
68 84 : else if (isNativePin(pin)) {
69 69 : return ::analogRead(arduino_pin_cast(pin));
70 : } else {
71 15 : auto el = getIOElementOfPin(pin);
72 15 : return el->analogRead(pin - el->getStart());
73 : }
74 : }
75 :
76 14 : void analogWrite(pin_t pin, analog_t val) {
77 14 : if (pin == NO_PIN)
78 : return; // LCOV_EXCL_LINE
79 13 : else if (isNativePin(pin)) {
80 : #ifndef ESP32
81 8 : ::analogWrite(arduino_pin_cast(pin), val);
82 : #endif
83 : } else {
84 5 : auto el = getIOElementOfPin(pin);
85 5 : el->analogWrite(pin - el->getStart(), val);
86 : }
87 : }
88 11 : void analogWrite(pin_t pin, int val) { analogWrite(pin, (analog_t)val); }
89 :
90 3 : void pinModeBuffered(pin_t pin, PinMode_t mode) {
91 3 : if (pin == NO_PIN)
92 : return; // LCOV_EXCL_LINE
93 3 : else if (isNativePin(pin)) {
94 1 : ::pinMode(arduino_pin_cast(pin), mode);
95 : } else {
96 2 : auto el = getIOElementOfPin(pin);
97 2 : el->pinModeBuffered(pin - el->getStart(), mode);
98 : }
99 : }
100 :
101 2 : void digitalWriteBuffered(pin_t pin, PinStatus_t val) {
102 2 : if (pin == NO_PIN)
103 : return; // LCOV_EXCL_LINE
104 2 : else if (isNativePin(pin)) {
105 1 : ::digitalWrite(arduino_pin_cast(pin), val);
106 : } else {
107 1 : auto el = getIOElementOfPin(pin);
108 1 : el->digitalWriteBuffered(pin - el->getStart(), val);
109 : }
110 : }
111 :
112 3 : PinStatus_t digitalReadBuffered(pin_t pin) {
113 3 : if (pin == NO_PIN)
114 : return LOW; // LCOV_EXCL_LINE
115 3 : else if (isNativePin(pin)) {
116 1 : return ::digitalRead(arduino_pin_cast(pin));
117 : } else {
118 2 : auto el = getIOElementOfPin(pin);
119 2 : return el->digitalReadBuffered(pin - el->getStart());
120 : }
121 : }
122 :
123 3 : analog_t analogReadBuffered(pin_t pin) {
124 3 : if (pin == NO_PIN)
125 : return 0; // LCOV_EXCL_LINE
126 3 : else if (isNativePin(pin)) {
127 1 : return ::analogRead(arduino_pin_cast(pin));
128 : } else {
129 2 : auto el = getIOElementOfPin(pin);
130 2 : return el->analogReadBuffered(pin - el->getStart());
131 : }
132 : return 0;
133 : }
134 :
135 4 : void analogWriteBuffered(pin_t pin, analog_t val) {
136 4 : if (pin == NO_PIN)
137 : return; // LCOV_EXCL_LINE
138 4 : else if (isNativePin(pin)) {
139 : #ifndef ESP32
140 2 : ::analogWrite(arduino_pin_cast(pin), val);
141 : #endif
142 : } else {
143 2 : auto el = getIOElementOfPin(pin);
144 2 : el->analogWriteBuffered(pin - el->getStart(), val);
145 : }
146 : }
147 2 : void analogWriteBuffered(pin_t pin, int val) {
148 2 : analogWriteBuffered(pin, (analog_t)val);
149 2 : }
150 :
151 6 : void shiftOut(pin_t dataPin, pin_t clockPin, BitOrder_t bitOrder, uint8_t val) {
152 6 : if (dataPin == NO_PIN || clockPin == NO_PIN)
153 1 : return;
154 : // Native version
155 5 : if (isNativePin(dataPin) && isNativePin(clockPin)) {
156 1 : ::shiftOut(arduino_pin_cast(dataPin), arduino_pin_cast(clockPin),
157 : bitOrder, val);
158 : }
159 : // ExtIO version
160 4 : else if (!isNativePin(dataPin) && !isNativePin(clockPin)) {
161 2 : auto dataEl = getIOElementOfPin(dataPin);
162 2 : auto dataPinN = dataPin - dataEl->getStart();
163 2 : auto clockEl = getIOElementOfPin(clockPin);
164 2 : auto clockPinN = clockPin - clockEl->getStart();
165 18 : for (uint8_t i = 0; i < 8; i++) {
166 16 : uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
167 16 : dataEl->digitalWrite(dataPinN, (val & mask) ? HIGH : LOW);
168 16 : clockEl->digitalWrite(clockPinN, HIGH);
169 16 : clockEl->digitalWrite(clockPinN, LOW);
170 : }
171 : }
172 : // Mixed version (slow)
173 : else {
174 18 : for (uint8_t i = 0; i < 8; i++) {
175 16 : uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
176 16 : digitalWrite(dataPin, (val & mask) ? HIGH : LOW);
177 16 : digitalWrite(clockPin, HIGH);
178 16 : digitalWrite(clockPin, LOW);
179 : }
180 : }
181 : }
182 :
183 : } // namespace ExtIO
184 :
185 : END_AH_NAMESPACE
|