Skip to content

Finish 2020 milestone #256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jan 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## Note to `arduino_ci` users

In this project, we define a workflow for each target platform. **If you're looking for an example you can copy from, take only `linux.yaml`.**


### Long version

The reason that all platforms are tested in _this_ project is to ensure that, as a framework, `arduino_ci` will run properly on any developer's personal workstation (regardless of OS).

For testing an individual Arduino library in the context of GitHub, [Linux is the cheapest option](https://docs.github.com/en/free-pro-team@latest/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions) and produces results identical to the other OSes.
4 changes: 4 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ Layout/EmptyLinesAroundMethodBody:
Layout/EmptyLinesAroundModuleBody:
Enabled: false

# This can add clarity
Style/CommentedKeyword:
Enabled: false

# Configuration parameters: AllowForAlignment.
Layout/ExtraSpacing:
Enabled: false
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `assertNAN()` and `assertNotNAN()` for comparing floats to `NaN`
- `assertion()`, `ReporterTAP.onAssert()`, and `testBehaviorExp` macro to handle simple expression evaluation (is true, is false, etc)
- `Wire.resetMocks()` and documentation
- `shiftIn()` and `shiftOut()`
- `CIConfig.is_default` to detect when the default configuration is used
- `ArduinoBackend.boards_installed?` to detect whether a board family (or package, like `arduino:avr`) is installed
- `ArduinoBackend.library_available?` to detect whether the library manager knows of a library
- Sanity checks for `library.properties` `includes=` and `depends=` entries

### Changed
- Rubocop expected syntax downgraded from ruby 2.6 to 2.5
- `assertEqual()` and `assertNotEqual()` use actual `==` and `!=` -- they no longer require a type to be totally ordered just to do equality tests
- Evaluative assertions (is true/false/null/etc) now produce simpler error messages instead of masquerading as an operation (e.g. "== true")
- `LibraryProperties.to_h` now properly uses formatters and symbolic keys, in order to support a `.to_s`
- Architectures from `library.properties` are considered when iterating over unit test or examples compilation, as well as the configured platforms

### Deprecated

Expand All @@ -28,6 +35,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
- Warnings about directory name mismatches are now based on proper comparison of strings
- Now using the recommended "stable" URL for the `esp32` board family
- `esp8266:huzzah` options updated as per upstream
- Errors about `'_NOP' was not declared in this scope` (test added)
- `pinMode()` and `analogReference()` are now functions (no longer macros), because that conflicted with actual function names in the wild
- `analogReadResolution()` and `analogWriteResolution()` are also no longer macros

### Security

Expand Down
16 changes: 15 additions & 1 deletion REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ This completely skips the compilation tests (of library examples) portion of the
This completely skips the compilation tests (of library examples) portion of the CI script. It does not skip the compilation of unit tests.


### `--skip-library-properties` option

This completely skips validation of entries in `library.properties`.


### `--testfile-select` option

This allows a file (or glob) pattern to be executed in your tests directory, creating a whitelist of files to test. E.g. `--testfile-select=test_animal_*.cpp` would match `test_animal_cat.cpp` and `test_animal_dog.cpp` (testing only those) and not `test_plant_rose.cpp`.
Expand Down Expand Up @@ -59,6 +64,11 @@ If set, testing will fail if no unit test files are detected (or if the director
If set, testing will fail if no example sketches are detected. This is to avoid communicating a passing status in cases where a commit may have accidentally moved or deleted the examples.


### `SKIP_LIBRARY_PROPERTIES` environment variable

If set, testing will skip validating `library.properties` entries. This is to work around any possible bugs in `arduino_ci`'s interpretation of what is "correct".


## Indirectly Overriding Build Behavior (medium term use), and Advanced Options

For build behavior that you'd like to persist across commits (e.g. defining the set of platforms to test against, disabling a test that you expect to re-enable at some future point), a special configuration file called `.arduino-ci.yml` can be used. There are 3 places you can put them:
Expand All @@ -84,6 +94,8 @@ packages:

To define a platform called `bogo` that uses a board called `potato:salad:bogo` (based on the `potato:salad` family), set it up in the `plaforms:` section. Note that this will override any default configuration of `bogo` if it had existed in `arduino_ci`'s `misc/default.yml` file. If this board defines particular features in the compiler, you can set those here.

> Note that the platform names are arbitrary -- just keys in this yaml file and in the [`default.yml`](https://github.com/Arduino-CI/arduino_ci/blob/master/misc/default.yml) file included in this gem. That said, they are also case sensitive; defining the `bogo` platform will not let you refer to it as `Bogo` nor `BOGO`.

```yaml
platforms:
# our custom definition of the "bogo" platform
Expand Down Expand Up @@ -117,7 +129,9 @@ platforms:
### Control How Examples Are Compiled

Put a file `.arduino-ci.yml` in each example directory where you require a different configuration than default.
The `compile:` section controls the platforms on which the compilation will be attempted, as well as any external libraries that must be installed and included.
The `compile:` section controls the platforms on which the compilation will be attempted, as well as any external libraries that must be installed and included. This works by _overriding_ portions of the default configuration.

> Note that the platform names _must_ match (case-sensitive) the platform names in the underlying [`default.yml`](https://github.com/Arduino-CI/arduino_ci/blob/master/misc/default.yml), or else match platforms that you have defined yourself in your `.arduino-ci.yml` override.

```yaml
compile:
Expand Down
66 changes: 66 additions & 0 deletions SampleProjects/TestSomething/test/godmode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,72 @@ unittest(spi) {
assertEqual("LMNOe", String(inBuf));
}

unittest(shift_in) {

uint8_t dataPin = 2;
uint8_t clockPin = 3;
uint8_t input;
bool actualClock[16];
uint8_t originalSize;

// verify data
state->reset();
state->digitalPin[dataPin].fromAscii("|", true); // 0111 1100
originalSize = state->digitalPin[clockPin].historySize();

input = shiftIn(dataPin, clockPin, MSBFIRST);
assertEqual(0x7C, (uint)input); // 0111 1100
assertEqual('|', input); // 0111 1100
assertEqual((uint)'|', (uint)input); // 0111 1100

// now verify clock
assertEqual(16, state->digitalPin[clockPin].historySize() - originalSize);
int numMoved = state->digitalPin[clockPin].toArray(actualClock, 16);
assertEqual(16, numMoved);
for (int i = 0; i < 16; ++i) assertEqual(i % 2, actualClock[i]);

state->reset();
state->digitalPin[dataPin].fromAscii("|", true); // 0111 1100
input = shiftIn(dataPin, clockPin, LSBFIRST); // <- note the LSB/MSB flip
assertEqual(0x3E, (uint)input); // 0011 1110
assertEqual('>', input); // 0011 1110
assertEqual((uint)'>', (uint)input); // 0011 1110

// test setting MSB
state->reset();
state->digitalPin[dataPin].fromAscii("U", true); // 0101 0101
input = shiftIn(dataPin, clockPin, LSBFIRST); // <- note the LSB/MSB flip
assertEqual(0xAA, (uint)input); // 1010 1010
}

unittest(shift_out) {

uint8_t dataPin = 2;
uint8_t clockPin = 3;
uint8_t output;
bool actualClock[16];
uint8_t originalSize;

state->reset();
originalSize = state->digitalPin[clockPin].historySize();
shiftOut(dataPin, clockPin, MSBFIRST, '|');
assertEqual("|", state->digitalPin[dataPin].toAscii(1, true));
assertEqual(16, state->digitalPin[clockPin].historySize() - originalSize);
int numMoved = state->digitalPin[clockPin].toArray(actualClock, 16);
for (int i = 0; i < 16; ++i) assertEqual(i % 2, actualClock[i]);

state->reset();
shiftOut(dataPin, clockPin, LSBFIRST, '|');
assertEqual(">", state->digitalPin[dataPin].toAscii(1, true));

}

unittest(no_ops) {
pinMode(1, INPUT);
analogReference(3);
analogReadResolution(4);
analogWriteResolution(5);
}

#ifdef HAVE_HWSERIAL0

Expand Down
5 changes: 0 additions & 5 deletions cpp/arduino/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ typedef uint8_t byte;
#define highByte(w) ((uint8_t) ((w) >> 8))
#define lowByte(w) ((uint8_t) ((w) & 0xff))

// Arduino defines this
#define _NOP() do { 0; } while (0)

// might as well use that NO-op macro for these, while unit testing
// you need interrupts? interrupt yourself
#define yield() _NOP()
Expand Down Expand Up @@ -70,5 +67,3 @@ inline unsigned int makeWord(unsigned int w) { return w; }
inline unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }

#define word(...) makeWord(__VA_ARGS__)


3 changes: 3 additions & 0 deletions cpp/arduino/ArduinoDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,6 @@
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define LED_BUILTIN 13
#endif

// Arduino defines this
#define _NOP() do { 0; } while (0)
69 changes: 63 additions & 6 deletions cpp/arduino/Godmode.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,21 +160,78 @@ class GodmodeState {
};

// io pins
#define pinMode(...) _NOP()
#define analogReference(...) _NOP()
inline void pinMode(uint8_t pin, uint8_t mode) { _NOP(); }
inline void analogReference(uint8_t mode) { _NOP(); }

void digitalWrite(uint8_t, uint8_t);
int digitalRead(uint8_t);
int analogRead(uint8_t);
void analogWrite(uint8_t, int);
#define analogReadResolution(...) _NOP()
#define analogWriteResolution(...) _NOP()
inline void analogReadResolution(uint8_t bits) { _NOP(); }
inline void analogWriteResolution(uint8_t bits) { _NOP(); }
void attachInterrupt(uint8_t interrupt, void ISR(void), uint8_t mode);
void detachInterrupt(uint8_t interrupt);

// TODO: issue #26 to track the commanded state here
inline void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0) {}
inline void noTone(uint8_t _pin) {}
inline void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0) { throw "Not Yet Implemented"; }
inline void noTone(uint8_t _pin) { throw "Not Yet Implemented"; }
inline uint8_t pulseIn(uint8_t _pin, uint8_t _value, uint32_t _timeout) { throw "Not Yet Implemented"; }
inline uint8_t pulseIn(uint8_t pin, uint8_t value) { return pulseIn(pin, value, (uint32_t) 1000000); }
inline uint32_t pulseInLong(uint8_t _pin, uint8_t _value, uint32_t _timeout) { throw "Not Yet Implemented"; }
inline uint32_t pulseInLong(uint8_t pin, uint8_t value) { return pulseInLong(pin, value, (uint32_t) 1000000); }

/**
* Shifts in a byte of data one bit at a time.
*
* Starts from either the most (i.e. the leftmost) or least (rightmost)
* significant bit. For each bit, the clock pin is pulled high, the next bit is
* read from the data line, and then the clock pin is taken low.
*
* @param dataPin the pin on which to input each bit
* @param clockPin the pin to toggle to signal a read from dataPin
* @param bitOrder which order to shift in the bits; either MSBFIRST or LSBFIRST. B=Bit, not byte
*
* @return The value read
*/
inline uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, bool bitOrder) {
bool mFirst = bitOrder == MSBFIRST;
uint8_t ret = 0x00;
for (uint8_t i = 0, mask = (bitOrder == MSBFIRST ? 0x80 : 0x01); i < 8; ++i) {
digitalWrite(clockPin, HIGH);
uint8_t setBit = mFirst ? 0x80 : 0x01;
uint8_t val = (mFirst ? (setBit >> i) : (setBit << i));
ret = ret | (digitalRead(dataPin) ? val : 0x00);
digitalWrite(clockPin, LOW);
}
return ret;
}

/**
* Shifts out a byte of data one bit at a time.
*
* Starts from either the most (i.e. the leftmost) or least (rightmost)
* significant bit. Each bit is written in turn to a data pin, after which a
* clock pin is pulsed (taken high, then low) to indicate that the bit is
* available.
*
* @param dataPin the pin on which to input each bit
* @param clockPin the pin to toggle to signal a write from dataPin
* @param bitOrder which order to shift in the bits; either MSBFIRST or LSBFIRST. B=Bit, not byte
* @param value the data to shift out
*
* @return The value read
*/
inline void shiftOut(uint8_t dataPin, uint8_t clockPin, bool bitOrder, uint8_t value) {
bool mFirst = bitOrder == MSBFIRST;
uint8_t ret = 0x00;
for (uint8_t i = 0, mask = (bitOrder == MSBFIRST ? 0x80 : 0x01); i < 8; ++i) {
uint8_t setBit = mFirst ? 0x80 : 0x01;
uint8_t val = (mFirst ? (setBit >> i) : (setBit << i));
digitalWrite(dataPin, (value & val) ? HIGH : LOW);
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
}

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