Skip to content

Commit 957db19

Browse files
committed
add ability to queue up pin values to be read
1 parent 8b3f194 commit 957db19

File tree

8 files changed

+286
-142
lines changed

8 files changed

+286
-142
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99
- Yaml files can have either `.yml` or `.yaml` extensions
1010
- Yaml files support select/reject critera for paths of unit tests for targeted testing
1111
- Pins now track history and can report it in Ascii (big- or little-endian) for digital sequences
12+
- Pins now accept an array (or string) of input bits for providing pin values across multiple reads
1213

1314
### Changed
1415
- Unit test executables print to STDERR just in case there are segfaults. Uh, just in case I ever write any.

README.md

Lines changed: 68 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,74 @@ unittest(example_godmode_stuff)
7070
}
7171
```
7272

73+
Of course, it's possible that your code might flip the bit more than once in a function. For that scenario, you may want to examine the history of a pin's commanded outputs:
74+
75+
```C++
76+
unittest(pin_history)
77+
{
78+
GodmodeState* state = GODMODE();
79+
int myPin = 3;
80+
state->reset(); // pin will start LOW
81+
digitalWrite(myPin, HIGH);
82+
digitalWrite(myPin, LOW);
83+
digitalWrite(myPin, LOW);
84+
digitalWrite(myPin, HIGH);
85+
digitalWrite(myPin, HIGH);
86+
87+
assertEqual(6, state->digitalPin[1].size());
88+
bool expected[6] = {LOW, HIGH, LOW, LOW, HIGH, HIGH};
89+
bool actual[6];
90+
91+
// move history queue into an array because at the moment, reading
92+
// the history is destructive -- it's a linked-list queue. this
93+
// means that if toArray or hasElements fails, the queue will be in
94+
// an unknown state and you should reset it before continuing with
95+
// other tests
96+
int numMoved = state->digitalPin[myPin].toArray(actual, 6);
97+
assertEqual(6, numMoved);
98+
99+
// verify each element
100+
for (int i = 0; i < 6; ++i) {
101+
assertEqual(expected[i], actual[i]);
102+
}
103+
```
104+
105+
Reading the pin more than once per function is also a possibility. In that case, we want to queue up a few values for the `digitalRead` or `analogRead` to find.
106+
107+
```C++
108+
unittest(pin_read_history)
109+
{
110+
GodmodeState* state = GODMODE();
111+
state->reset();
112+
113+
int future[6] = {33, 22, 55, 11, 44, 66};
114+
state->analogPin[1].fromArray(future, 6);
115+
delay(1); // swallow first entry
116+
for (int i = 0; i < 6; ++i)
117+
{
118+
assertEqual(future[i], analogRead(1));
119+
assertEqual(future[i], analogRead(1)); // reading twice in the same instant produces the same value
120+
delay(1); // advancing the instant produces the next value
121+
}
122+
123+
// for digital pins, we have the added possibility of specifying
124+
// a stream of input bytes encoded as ASCII
125+
bool bigEndian = true;
126+
state->digitalPin[1].fromAscii("Yo", bigEndian);
127+
128+
// digitial history as serial data, big-endian
129+
bool expectedBits[16] = {
130+
0, 1, 0, 1, 1, 0, 0, 1, // Y
131+
0, 1, 1, 0, 1, 1, 1, 1 // o
132+
};
133+
134+
for (int i = 0; i < 16; ++i) {
135+
assertEqual(expectedBits[i], digitalRead(1));
136+
delay(1);
137+
}
138+
}
139+
```
140+
73141
A more complicated example: working with serial port IO. Let's say I have the following function:
74142

75143
```C++
@@ -127,37 +195,8 @@ unittest(two_flips)
127195
}
128196
```
129197

130-
Of course, it's possible that your code might flip the bit more than once in a function. For that scenario, you may want to examine the history of a pin's commanded outputs:
131-
132-
```C++
133-
unittest(pin_history)
134-
{
135-
GodmodeState* state = GODMODE();
136-
int myPin = 3;
137-
state->reset(); // pin will start LOW
138-
digitalWrite(myPin, HIGH);
139-
digitalWrite(myPin, LOW);
140-
digitalWrite(myPin, LOW);
141-
digitalWrite(myPin, HIGH);
142-
digitalWrite(myPin, HIGH);
143-
144-
assertEqual(6, state->digitalPin[1].size());
145-
bool expected[6] = {LOW, HIGH, LOW, LOW, HIGH, HIGH};
146-
bool actual[6];
147198

148-
// move history queue into an array because at the moment, reading
149-
// the history is destructive -- it's a linked-list queue. this
150-
// means that if toArray or hasElements fails, the queue will be in
151-
// an unknown state and you should reset it before continuing with
152-
// other tests
153-
int numMoved = state->digitalPin[myPin].toArray(actual, 6);
154-
assertEqual(6, numMoved);
155199

156-
// verify each element
157-
for (int i = 0; i < 6; ++i) {
158-
assertEqual(expected[i], actual[i]);
159-
}
160-
```
161200

162201
Finally, there are some cases where you want to use a pin as a serial port. There are history functions for that too.
163202

SampleProjects/TestSomething/test/good-godmode.cpp

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ unittest(pins)
4545
pinMode(1, OUTPUT); // this is a no-op in unit tests. it's just here to prove compilation
4646
digitalWrite(1, HIGH);
4747
assertEqual(HIGH, state->digitalPin[1]);
48+
assertEqual(HIGH, digitalRead(1));
4849
digitalWrite(1, LOW);
4950
assertEqual(LOW, state->digitalPin[1]);
51+
assertEqual(LOW, digitalRead(1));
5052

5153
pinMode(1, INPUT);
5254
state->digitalPin[1] = HIGH;
@@ -65,25 +67,63 @@ unittest(pins)
6567
assertEqual(56, analogRead(1));
6668
}
6769

68-
unittest(pin_history)
70+
unittest(pin_read_history)
6971
{
7072
GodmodeState* state = GODMODE();
7173
state->reset();
7274

75+
int future[6] = {33, 22, 55, 11, 44, 66};
76+
state->analogPin[1].fromArray(future, 6);
77+
delay(1); // swallow first entry
78+
for (int i = 0; i < 6; ++i)
79+
{
80+
assertEqual(future[i], analogRead(1));
81+
assertEqual(future[i], analogRead(1)); // test same-instant read
82+
delay(1);
83+
}
84+
85+
// assert end of history works
86+
delay(1);
87+
assertEqual(future[5], analogRead(1));
88+
89+
state->digitalPin[1].fromAscii("Yo", true);
90+
// digitial history as serial data, big-endian
91+
bool binaryAscii[16] = {
92+
0, 1, 0, 1, 1, 0, 0, 1,
93+
0, 1, 1, 0, 1, 1, 1, 1
94+
};
95+
96+
for (int i = 0; i < 16; ++i) {
97+
assertEqual(binaryAscii[i], digitalRead(1));
98+
assertEqual(binaryAscii[i], digitalRead(1)); // test same-instant read
99+
delay(1);
100+
}
101+
}
102+
103+
unittest(pin_write_history)
104+
{
105+
GodmodeState *state = GODMODE();
106+
state->reset();
107+
int numMoved;
108+
73109
// history for digital pin
74110
digitalWrite(1, HIGH);
75111
digitalWrite(1, LOW);
76112
digitalWrite(1, LOW);
77113
digitalWrite(1, HIGH);
78114
digitalWrite(1, HIGH);
79115

80-
assertEqual(6, state->digitalPin[1].size());
116+
assertEqual(6, state->digitalPin[1].historySize());
81117
bool expectedD[6] = {LOW, HIGH, LOW, LOW, HIGH, HIGH};
82118
bool actualD[6];
83-
int numMoved = state->digitalPin[1].toArray(actualD, 6);
119+
numMoved = state->digitalPin[1].toArray(actualD, 6);
120+
assertEqual(6, numMoved);
121+
// assert non-destructive
122+
numMoved = state->digitalPin[1].toArray(actualD, 6);
84123
assertEqual(6, numMoved);
85124

86-
for (int i = 0; i < 6; ++i) {
125+
for (int i = 0; i < 6; ++i)
126+
{
87127
assertEqual(expectedD[i], actualD[i]);
88128
}
89129

@@ -94,34 +134,38 @@ unittest(pin_history)
94134
analogWrite(1, 44);
95135
analogWrite(1, 55);
96136

97-
assertEqual(6, state->analogPin[1].size());
137+
assertEqual(6, state->analogPin[1].historySize());
98138
int expectedA[6] = {0, 11, 22, 33, 44, 55};
99139
int actualA[6];
100140
numMoved = state->analogPin[1].toArray(actualA, 6);
101141
assertEqual(6, numMoved);
142+
// assert non-destructive
143+
numMoved = state->analogPin[1].toArray(actualA, 6);
144+
assertEqual(6, numMoved);
102145

103-
for (int i = 0; i < 6; ++i) {
146+
for (int i = 0; i < 6; ++i)
147+
{
104148
assertEqual(expectedA[i], actualA[i]);
105149
}
106150

107151
// digitial history as serial data, big-endian
108152
bool binaryAscii[24] = {
109-
0, 1, 0, 1, 1, 0, 0, 1,
110-
0, 1, 1, 0, 0, 1, 0, 1,
111-
0, 1, 1, 1, 0, 0, 1, 1
112-
};
153+
0, 1, 0, 1, 1, 0, 0, 1,
154+
0, 1, 1, 0, 0, 1, 0, 1,
155+
0, 1, 1, 1, 0, 0, 1, 1};
113156

114-
for (int i = 0; i < 24; digitalWrite(2, binaryAscii[i++]));
157+
for (int i = 0; i < 24; digitalWrite(2, binaryAscii[i++]))
158+
;
115159

116160
assertEqual("Yes", state->digitalPin[2].toAscii(1, true));
117161

118162
// digitial history as serial data, little-endian
119163
bool binaryAscii2[16] = {
120-
0, 1, 1, 1, 0, 0, 1, 0,
121-
1, 1, 1, 1, 0, 1, 1, 0
122-
};
164+
0, 1, 1, 1, 0, 0, 1, 0,
165+
1, 1, 1, 1, 0, 1, 1, 0};
123166

124-
for (int i = 0; i < 16; digitalWrite(3, binaryAscii2[i++]));
167+
for (int i = 0; i < 16; digitalWrite(3, binaryAscii2[i++]))
168+
;
125169

126170
assertEqual("No", state->digitalPin[3].toAscii(1, false));
127171

cpp/arduino/Arduino.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ void digitalWrite(unsigned char pin, unsigned char val) {
99

1010
int digitalRead(unsigned char pin) {
1111
GodmodeState* godmode = GODMODE();
12-
return godmode->digitalPin[pin];
12+
return godmode->digitalPin[pin].retrieve();
1313
}
1414

15-
int analogRead(unsigned char pin) {
15+
void analogWrite(unsigned char pin, int val) {
1616
GodmodeState* godmode = GODMODE();
17-
return godmode->analogPin[pin];
17+
godmode->analogPin[pin] = val;
1818
}
1919

20-
void analogWrite(unsigned char pin, int val) {
20+
int analogRead(unsigned char pin) {
2121
GodmodeState* godmode = GODMODE();
22-
godmode->analogPin[pin] = val;
22+
return godmode->analogPin[pin].retrieve();
2323
}

cpp/arduino/Godmode.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,8 @@ long random(long vmin, long vmax)
6060
HardwareSerial Serial3(&godmode.serialPort[3].dataIn, &godmode.serialPort[3].dataOut, &godmode.serialPort[3].readDelayMicros);
6161
#endif
6262

63+
template <typename T>
64+
inline std::ostream& operator << ( std::ostream& out, const PinHistory<T>& ph ) {
65+
out << ph;
66+
return out;
67+
}

0 commit comments

Comments
 (0)