IoAbstraction
MockIoAbstraction.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry).
3  * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4  */
5 
6 #ifndef _MOCK_IO_ABSTRACTION_H_
7 #define _MOCK_IO_ABSTRACTION_H_
8 
15 #include <IoAbstraction.h>
16 
23  NO_ERROR = 0,
30 };
31 
42 private:
43  uint8_t pinModes[16];
44  uint16_t *readValues;
45  uint16_t *writeValues;
46  int runLoopCalls;
47  int numberOfCycles;
48 
50  MockIoError error;
51 
53  RawIntHandler intHandler;
55  uint8_t intPin;
57  uint8_t intMode;
58 
59 public:
60  MockedIoAbstraction(int numberOfCycles = 6) {
61  for(int i=0;i<16;i++) pinModes[i] = 0xff;
62  error = NO_ERROR;
63 
64  this->numberOfCycles = numberOfCycles;
65  readValues = new uint16_t[numberOfCycles];
66  writeValues = new uint16_t[numberOfCycles];
67 
68  resetIo();
69  }
70 
71  virtual ~MockedIoAbstraction() {
72  delete readValues;
73  delete writeValues;
74  }
75 
79  void resetIo() {
80  for(int i=0; i<numberOfCycles; i++) {
81  readValues[i] = 0;
82  writeValues[i] = 0;
83  }
84  runLoopCalls = 0;
85  }
86 
87 
88  void pinDirection(pinid_t pin, uint8_t mode) override {
89  checkPinInRange(pin);
90  pinModes[pin] = mode;
91  }
92 
93  void writeValue(pinid_t pin, uint8_t value) override {
94  checkPinInRange(pin);
95 
96  if(pinModes[pin] != OUTPUT) error = WRITE_NOT_OUTPUT;
97  bitWrite(writeValues[runLoopCalls], pin, value != 0);
98  }
99 
100  uint8_t readValue(pinid_t pin) override {
101  checkPinInRange(pin);
102  if(pinModes[pin] != INPUT && pinModes[pin] != INPUT_PULLUP) error = READ_NOT_INPUT;
103  return bitRead(readValues[runLoopCalls], pin);
104  }
105 
109  void attachInterrupt(pinid_t pin, RawIntHandler interruptHandler, uint8_t mode) override {
110  this->intHandler = interruptHandler;
111  this->intPin = pin;
112  this->intMode = mode;
113  }
114 
115  bool runLoop() override {
116  // copy over the last written values (as they are generally additive) and bump counter.
117  uint16_t currentWritten = writeValues[runLoopCalls];
118 
119  runLoopCalls++;
120  runLoopCalls = runLoopCalls % numberOfCycles; // dont exceed array
121 
122  writeValues[runLoopCalls] = currentWritten;
123  return true;
124  }
125 
126  void writePort(pinid_t pin, uint8_t portVal) override {
127 
128  checkPinInRange(pin);
129 
130  if(pin < 8) {
131  checkPinsAre(OUTPUT, 0, 7);
132  writeValues[runLoopCalls] = (writeValues[runLoopCalls] & 0xff00) | portVal;
133  }
134  else {
135  checkPinsAre(OUTPUT, 8, 15);
136  writeValues[runLoopCalls] = (writeValues[runLoopCalls] & 0x00ff) | (portVal << 8);
137  }
138  }
139 
140  virtual uint8_t readPort(pinid_t pin) {
141  checkPinInRange(pin);
142 
143  if(pin < 8) {
144  checkPinsAre(INPUT, 0, 7);
145  return readValues[runLoopCalls];
146  }
147  else {
148  checkPinsAre(INPUT, 8, 15);
149  return readValues[runLoopCalls] >> 8;
150  }
151  }
152 
154  int getNumberOfRunLoops() {return runLoopCalls;}
155 
157  uint16_t getWrittenValuesForRunLoop(int runLoop) { return writeValues[runLoop]; }
158 
160  void setValueForReading(int runLoopNo, uint16_t val) {readValues[runLoopNo] = val;}
161 
163  uint16_t getWrittenValue(int runLoopNo) {return writeValues[runLoopNo];}
164 
166  MockIoError getErrorMode() {return error;}
167 
169  void clearError() { error = NO_ERROR; }
170 
172  RawIntHandler getInterruptFunction() {return intHandler;}
173 
175  bool isIntRegisteredAs(uint8_t pin, uint8_t mode) {
176  return intPin == pin && intMode == mode && intHandler != NULL;
177  }
178 private:
179  void checkPinInRange(int pin) {
180  if(pin > 15) error = PIN_TOO_HIGH;
181  }
182  void checkPinsAre(uint8_t mode, uint8_t start, uint8_t end) {
183  for(int i = start; i < end; ++i) {
184  if(mode == OUTPUT) {
185  if(pinModes[i] != OUTPUT) error = WRITE_NOT_OUTPUT;
186  }
187  else if(mode == INPUT) {
188  if(pinModes[i] != INPUT && pinModes[i] != INPUT_PULLUP) error = READ_NOT_INPUT;
189  }
190  }
191  }
192 };
193 
205 private:
206  IoAbstractionRef delegate;
207  uint32_t writeVals;
208  int ports;
209 public:
210  LoggingIoAbstraction(IoAbstractionRef delegate, int ports) {
211  this->delegate = delegate;
212  this->ports = ports;
213  writeVals = 0;
214  }
215 
216  void pinDirection(pinid_t pin, uint8_t mode) override { delegate->pinDirection(pin, mode); }
217 
218  void writeValue(pinid_t pin, uint8_t value) override {
219  bitWrite(writeVals, pin, value);
220  delegate->writeValue(pin, value);
221  }
222  uint8_t readValue(pinid_t pin) override { return delegate->readValue(pin); }
223 
224  void attachInterrupt(pinid_t pin, RawIntHandler interruptHandler, uint8_t mode) override { delegate->attachInterrupt(pin, interruptHandler, mode); }
225 
226  void writePort(pinid_t pin, uint8_t portVal) override {
227  if(pin < 8) {
228  writeVals &= 0xffffff00L;
229  writeVals |= (uint32_t)portVal;
230  }
231  else if(pin < 16) {
232  writeVals &= 0xffff00ffL;
233  writeVals |= ((uint32_t)portVal<<8);
234  }
235  else if(pin < 24) {
236  writeVals &= 0xff00ffffL;
237  writeVals |= ((uint32_t)portVal<<16);
238  }
239  else {
240  writeVals &= 0x00ffffffL;
241  writeVals |= ((uint32_t)portVal<<24);
242  }
243  delegate->writePort(pin, portVal);
244  }
245  uint8_t readPort(pinid_t pin) override { return delegate->readPort(pin);}
246 
247  bool runLoop() override {
248  serlogF(SER_DEBUG, "Port write ");
249  uint32_t val = writeVals;
250  for(int i=0;i<ports;i++) {
251  printHexZeroPad(val);
252  val = val >> 8;
253  }
254  bool ret = delegate->runLoop();
255  serlogF(SER_DEBUG, "read ");
256  for(int i=0;i<ports;i++) {
257  printHexZeroPad(delegate->readPort(i * 8));
258  }
259  serlogF(SER_DEBUG, "EOL");
260  return ret;
261  }
262 
263  void printHexZeroPad(uint8_t val) {
264  serlog3(SER_DEBUG, hexchar(val / 16), hexchar(val % 16), ' ');
265  }
266 
267  char hexchar(uint8_t ch) {
268  return ch < 10 ? ch + '0' : (ch-10) + 'A';
269  }
270 };
271 
272 #endif // _MOCK_IO_ABSTRACTION_H_
Using basic IoFacilities allows one to abstract away the use of IoExpanders, such that the switching ...
MockIoError
Definition: MockIoAbstraction.h:21
@ READ_NOT_INPUT
Definition: MockIoAbstraction.h:27
@ PIN_TOO_HIGH
Definition: MockIoAbstraction.h:25
@ NO_ERROR
Definition: MockIoAbstraction.h:23
@ WRITE_NOT_OUTPUT
Definition: MockIoAbstraction.h:29
Definition: BasicIoAbstraction.h:38
virtual void pinDirection(pinid_t pin, uint8_t mode)
virtual void writePort(pinid_t pin, uint8_t portVal)
virtual uint8_t readValue(pinid_t pin)
virtual void writeValue(pinid_t pin, uint8_t value)
virtual void attachInterrupt(pinid_t pin, RawIntHandler interruptHandler, uint8_t mode)
virtual bool runLoop()
Definition: BasicIoAbstraction.h:147
virtual uint8_t readPort(pinid_t pin)
Definition: MockIoAbstraction.h:204
uint8_t readPort(pinid_t pin) override
Definition: MockIoAbstraction.h:245
void attachInterrupt(pinid_t pin, RawIntHandler interruptHandler, uint8_t mode) override
Definition: MockIoAbstraction.h:224
void writeValue(pinid_t pin, uint8_t value) override
Definition: MockIoAbstraction.h:218
bool runLoop() override
Definition: MockIoAbstraction.h:247
void pinDirection(pinid_t pin, uint8_t mode) override
Definition: MockIoAbstraction.h:216
uint8_t readValue(pinid_t pin) override
Definition: MockIoAbstraction.h:222
void writePort(pinid_t pin, uint8_t portVal) override
Definition: MockIoAbstraction.h:226
Definition: MockIoAbstraction.h:41
void pinDirection(pinid_t pin, uint8_t mode) override
Definition: MockIoAbstraction.h:88
MockIoError getErrorMode()
Definition: MockIoAbstraction.h:166
void writeValue(pinid_t pin, uint8_t value) override
Definition: MockIoAbstraction.h:93
virtual uint8_t readPort(pinid_t pin)
Definition: MockIoAbstraction.h:140
void attachInterrupt(pinid_t pin, RawIntHandler interruptHandler, uint8_t mode) override
Definition: MockIoAbstraction.h:109
bool isIntRegisteredAs(uint8_t pin, uint8_t mode)
Definition: MockIoAbstraction.h:175
uint16_t getWrittenValue(int runLoopNo)
Definition: MockIoAbstraction.h:163
uint8_t readValue(pinid_t pin) override
Definition: MockIoAbstraction.h:100
RawIntHandler getInterruptFunction()
Definition: MockIoAbstraction.h:172
bool runLoop() override
Definition: MockIoAbstraction.h:115
uint16_t getWrittenValuesForRunLoop(int runLoop)
Definition: MockIoAbstraction.h:157
void resetIo()
Definition: MockIoAbstraction.h:79
void setValueForReading(int runLoopNo, uint16_t val)
Definition: MockIoAbstraction.h:160
void clearError()
Definition: MockIoAbstraction.h:169
void writePort(pinid_t pin, uint8_t portVal) override
Definition: MockIoAbstraction.h:126
int getNumberOfRunLoops()
Definition: MockIoAbstraction.h:154