Skip to content

Commit f168ba3

Browse files
committed
Add shiftIn and shiftOut
1 parent b9aab4e commit f168ba3

File tree

3 files changed

+120
-2
lines changed

3 files changed

+120
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1515
- `assertNAN()` and `assertNotNAN()` for comparing floats to `NaN`
1616
- `assertion()`, `ReporterTAP.onAssert()`, and `testBehaviorExp` macro to handle simple expression evaluation (is true, is false, etc)
1717
- `Wire.resetMocks()` and documentation
18+
- `shiftIn()` and `shiftOut()`
1819

1920
### Changed
2021
- Rubocop expected syntax downgraded from ruby 2.6 to 2.5

SampleProjects/TestSomething/test/godmode.cpp

+60
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,66 @@ unittest(spi) {
222222
assertEqual("LMNOe", String(inBuf));
223223
}
224224

225+
unittest(shift_in) {
226+
227+
uint8_t dataPin = 2;
228+
uint8_t clockPin = 3;
229+
uint8_t input;
230+
bool actualClock[16];
231+
uint8_t originalSize;
232+
233+
// verify data
234+
state->reset();
235+
state->digitalPin[dataPin].fromAscii("|", true); // 0111 1100
236+
originalSize = state->digitalPin[clockPin].historySize();
237+
238+
input = shiftIn(dataPin, clockPin, MSBFIRST);
239+
assertEqual(0x7C, (uint)input); // 0111 1100
240+
assertEqual('|', input); // 0111 1100
241+
assertEqual((uint)'|', (uint)input); // 0111 1100
242+
243+
// now verify clock
244+
assertEqual(16, state->digitalPin[clockPin].historySize() - originalSize);
245+
int numMoved = state->digitalPin[clockPin].toArray(actualClock, 16);
246+
assertEqual(16, numMoved);
247+
for (int i = 0; i < 16; ++i) assertEqual(i % 2, actualClock[i]);
248+
249+
state->reset();
250+
state->digitalPin[dataPin].fromAscii("|", true); // 0111 1100
251+
input = shiftIn(dataPin, clockPin, LSBFIRST); // <- note the LSB/MSB flip
252+
assertEqual(0x3E, (uint)input); // 0011 1110
253+
assertEqual('>', input); // 0011 1110
254+
assertEqual((uint)'>', (uint)input); // 0011 1110
255+
256+
// test setting MSB
257+
state->reset();
258+
state->digitalPin[dataPin].fromAscii("U", true); // 0101 0101
259+
input = shiftIn(dataPin, clockPin, LSBFIRST); // <- note the LSB/MSB flip
260+
assertEqual(0xAA, (uint)input); // 1010 1010
261+
}
262+
263+
unittest(shift_out) {
264+
265+
uint8_t dataPin = 2;
266+
uint8_t clockPin = 3;
267+
uint8_t output;
268+
bool actualClock[16];
269+
uint8_t originalSize;
270+
271+
state->reset();
272+
originalSize = state->digitalPin[clockPin].historySize();
273+
shiftOut(dataPin, clockPin, MSBFIRST, '|');
274+
assertEqual("|", state->digitalPin[dataPin].toAscii(1, true));
275+
assertEqual(16, state->digitalPin[clockPin].historySize() - originalSize);
276+
int numMoved = state->digitalPin[clockPin].toArray(actualClock, 16);
277+
for (int i = 0; i < 16; ++i) assertEqual(i % 2, actualClock[i]);
278+
279+
state->reset();
280+
shiftOut(dataPin, clockPin, LSBFIRST, '|');
281+
assertEqual(">", state->digitalPin[dataPin].toAscii(1, true));
282+
283+
}
284+
225285

226286
#ifdef HAVE_HWSERIAL0
227287

cpp/arduino/Godmode.h

+59-2
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,65 @@ void attachInterrupt(uint8_t interrupt, void ISR(void), uint8_t mode);
173173
void detachInterrupt(uint8_t interrupt);
174174

175175
// TODO: issue #26 to track the commanded state here
176-
inline void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0) {}
177-
inline void noTone(uint8_t _pin) {}
176+
inline void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0) { throw "Not Yet Implemented"; }
177+
inline void noTone(uint8_t _pin) { throw "Not Yet Implemented"; }
178+
inline uint8_t pulseIn(uint8_t _pin, uint8_t _value, uint32_t _timeout) { throw "Not Yet Implemented"; }
179+
inline uint8_t pulseIn(uint8_t pin, uint8_t value) { return pulseIn(pin, value, (uint32_t) 1000000); }
180+
inline uint32_t pulseInLong(uint8_t _pin, uint8_t _value, uint32_t _timeout) { throw "Not Yet Implemented"; }
181+
inline uint32_t pulseInLong(uint8_t pin, uint8_t value) { return pulseInLong(pin, value, (uint32_t) 1000000); }
182+
183+
/**
184+
* Shifts in a byte of data one bit at a time.
185+
*
186+
* Starts from either the most (i.e. the leftmost) or least (rightmost)
187+
* significant bit. For each bit, the clock pin is pulled high, the next bit is
188+
* read from the data line, and then the clock pin is taken low.
189+
*
190+
* @param dataPin the pin on which to input each bit
191+
* @param clockPin the pin to toggle to signal a read from dataPin
192+
* @param bitOrder which order to shift in the bits; either MSBFIRST or LSBFIRST. B=Bit, not byte
193+
*
194+
* @return The value read
195+
*/
196+
inline uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, bool bitOrder) {
197+
bool mFirst = bitOrder == MSBFIRST;
198+
uint8_t ret = 0x00;
199+
for (uint8_t i = 0, mask = (bitOrder == MSBFIRST ? 0x80 : 0x01); i < 8; ++i) {
200+
digitalWrite(clockPin, HIGH);
201+
uint8_t setBit = mFirst ? 0x80 : 0x01;
202+
uint8_t val = (mFirst ? (setBit >> i) : (setBit << i));
203+
ret = ret | (digitalRead(dataPin) ? val : 0x00);
204+
digitalWrite(clockPin, LOW);
205+
}
206+
return ret;
207+
}
208+
209+
/**
210+
* Shifts out a byte of data one bit at a time.
211+
*
212+
* Starts from either the most (i.e. the leftmost) or least (rightmost)
213+
* significant bit. Each bit is written in turn to a data pin, after which a
214+
* clock pin is pulsed (taken high, then low) to indicate that the bit is
215+
* available.
216+
*
217+
* @param dataPin the pin on which to input each bit
218+
* @param clockPin the pin to toggle to signal a write from dataPin
219+
* @param bitOrder which order to shift in the bits; either MSBFIRST or LSBFIRST. B=Bit, not byte
220+
* @param value the data to shift out
221+
*
222+
* @return The value read
223+
*/
224+
inline void shiftOut(uint8_t dataPin, uint8_t clockPin, bool bitOrder, uint8_t value) {
225+
bool mFirst = bitOrder == MSBFIRST;
226+
uint8_t ret = 0x00;
227+
for (uint8_t i = 0, mask = (bitOrder == MSBFIRST ? 0x80 : 0x01); i < 8; ++i) {
228+
uint8_t setBit = mFirst ? 0x80 : 0x01;
229+
uint8_t val = (mFirst ? (setBit >> i) : (setBit << i));
230+
digitalWrite(dataPin, (value & val) ? HIGH : LOW);
231+
digitalWrite(clockPin, HIGH);
232+
digitalWrite(clockPin, LOW);
233+
}
234+
}
178235

179236
// These definitions allow the following to compile (see issue #193):
180237
// https://github.com/arduino-libraries/Ethernet/blob/master/src/utility/w5100.h:341

0 commit comments

Comments
 (0)