arduino_ci 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +32 -24
- data/REFERENCE.md +91 -11
- data/cpp/arduino/Arduino.h +0 -5
- data/cpp/arduino/ArduinoDefines.h +3 -0
- data/cpp/arduino/Godmode.h +63 -6
- data/cpp/arduino/Wire.h +37 -13
- data/cpp/unittest/ArduinoUnitTests.h +32 -0
- data/cpp/unittest/Assertion.h +54 -26
- data/cpp/unittest/Compare.h +58 -51
- data/exe/arduino_ci.rb +186 -76
- data/lib/arduino_ci/arduino_backend.rb +18 -2
- data/lib/arduino_ci/ci_config.rb +5 -2
- data/lib/arduino_ci/host.rb +1 -1
- data/lib/arduino_ci/library_properties.rb +6 -1
- data/lib/arduino_ci/version.rb +1 -1
- data/misc/default.yml +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95cc7dc7ab0591e45ffe7c1a9cdf31f64b21a8cf794a12ea83a4190af20e7488
|
4
|
+
data.tar.gz: 6e20b49ad3b015445c79511e9795fddbf205f01e20eb8c413e7ff342f4b240f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f40e840a35f788a4e02e0e332b5e7669198214419d9361abf10cc03558028bc691bb16379143b95c258dd2527fb8b03924d3cfb240c3af6b2fac526966b30274
|
7
|
+
data.tar.gz: bf8dc24b59f479ad858b75450a546ebd5e7bee694e33c8b443d2fa89576fe40fb09dede3c17353b7ca6c9c7dcda921aa7bb3f156c3beb98fd62cc99123c03119
|
data/README.md
CHANGED
@@ -1,17 +1,24 @@
|
|
1
1
|
|
2
2
|
# ArduinoCI Ruby gem (`arduino_ci`)
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/arduino_ci.svg)](https://rubygems.org/gems/arduino_ci)
|
4
|
-
[![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://www.rubydoc.info/gems/arduino_ci/1.
|
4
|
+
[![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://www.rubydoc.info/gems/arduino_ci/1.2.0)
|
5
5
|
[![Gitter](https://badges.gitter.im/Arduino-CI/arduino_ci.svg)](https://gitter.im/Arduino-CI/arduino_ci?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
6
|
+
[![GitHub Marketplace](https://img.shields.io/badge/Get_it-on_Marketplace-informational.svg)](https://github.com/marketplace/actions/arduino_ci)
|
6
7
|
|
7
|
-
|
8
|
+
Arduino CI was created to enable better collaboration among Arduino library maintainers and contributors, by enabling automated code checks to be performed as part of a pull request process.
|
8
9
|
|
9
|
-
|
10
|
+
* enables running unit tests against the library **without hardware present**
|
11
|
+
* provides a system of mocks that allow fine-grained control over the hardare inputs, including the system's clock
|
12
|
+
* verifies compilation of any example sketches included in the library
|
13
|
+
* can test a wide range of arduino boards with different hardware options available
|
14
|
+
* compares entries in `library.properties` to the contents of the library and reports mismatches
|
15
|
+
* can be run both locally and as part of CI (GitHub Actions, TravisCI, Appveyor, etc.)
|
16
|
+
* runs on multiple platforms -- any platform that supports the Arduino IDE
|
17
|
+
* provides detailed analysis of segfaults in compilers that support such debugging features
|
10
18
|
|
11
|
-
|
12
|
-
|
13
|
-
`arduino_ci` is a cross-platform build/test system, consisting of a Ruby gem and a series of C++ mocks. It enables tests to be run both locally and as part of a CI service like GitHub Actions, TravisCI, Appveyor, etc. Any OS that can run the Arduino IDE can run `arduino_ci`.
|
19
|
+
> Note: for running tests in response to [GitHub events](https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/github-event-types), an [Arduino CI GitHub Action](https://github.com/marketplace/actions/arduino_ci) is available for your convenience. This method of running `arduino_ci` is driven by Docker, which may also serve your local testing needs (as it does not require a ruby environment to be installed).
|
14
20
|
|
21
|
+
Arduino CI works on multiple platforms, which should enable your CI system of choice to leverage it for testing.
|
15
22
|
|
16
23
|
Platform | CI Status
|
17
24
|
---------|:---------
|
@@ -20,30 +27,22 @@ Linux | [![Linux Build Status](https://github.com/Arduino-CI/arduino_ci/workf
|
|
20
27
|
Windows | [![Windows Build status](https://github.com/Arduino-CI/arduino_ci/workflows/windows/badge.svg)](https://github.com/Arduino-CI/arduino_ci/actions?workflow=windows)
|
21
28
|
|
22
29
|
|
23
|
-
##
|
30
|
+
## Quick Start
|
24
31
|
|
25
|
-
|
26
|
-
|-----------------------------------------------------------------------------|:--:|:---------------:|:--------:|:-------------:|:-------:|:---:|:-----:|:--------|
|
27
|
-
|[ArduinoCI](https://github.com/Arduino-CI/arduino_ci) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |Free (Apache-2.0)|
|
28
|
-
|[ArduinoUnit](https://github.com/mmurdoch/arduinounit) | ❌ | ❌ | ⚠️ Hardware-based|❌ | ✅ | ✅ | ✅ |Free (MIT)|
|
29
|
-
|[Adafruit `ci-arduino`](https://github.com/adafruit/ci-arduino)| ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |Free (MIT)|
|
30
|
-
|[PlatformIO](https://platformio.org) | ✅ | ✅ | ⚠️ Paid only | ❌ | ✅ | ✅ | ✅ |⚠️ EULA|
|
31
|
-
|Official [Arduino IDE](https://www.arduino.cc/en/main/software) | ❌ | ⚠️ Manually | ❌ |N/A 😉| ✅ | ✅ | ✅ |Free (GPLv2)|
|
32
|
+
### You Need Your Arduino Library
|
32
33
|
|
34
|
+
For a fairly minimal practical example of a unit-testable library repo that you can copy from, see [the `Arduino-CI/Blink` repository](https://github.com/Arduino-CI/Blink).
|
33
35
|
|
34
|
-
|
36
|
+
> Note: The `SampleProjects` directory you see within _this_ repo contains tests for validing the `arduino_ci` framework itself, and due to that coupling will not be helpful to duplicate. That said, the [SampleProjects/TestSomething](SampleProjects/TestSomething) project contains [test files](SampleProjects/TestSomething/test/) (each named after the type of feature being tested) that may be illustrative of testing strategy and capabilities _on an individual basis_.
|
35
37
|
|
36
|
-
|
38
|
+
Arduino expects all libraries to be in a specific `Arduino/libraries` directory on your system. If your library is elsewhere, `arduino_ci` will _automatically_ create a symbolic link in the `libraries` directory that points to the directory of the project being tested. This simplifieds working with project dependencies, but **it can have unintended consequences on Windows systems**.
|
37
39
|
|
38
|
-
|
40
|
+
> If you use a Windows system **it is recommended that you only run `arduino_ci` from project directories that are already inside the `libraries` directory** because [in some cases deleting a folder that contains a symbolic link to another folder can cause the _entire linked folder_ to be removed instead of just the link itself](https://superuser.com/a/306618).
|
39
41
|
|
40
|
-
> Arduino expects all libraries to be in a specific `Arduino/libraries` directory on your system. If your library is elsewhere, `arduino_ci` will _automatically_ create a symbolic link in the `libraries` directory that points to the directory of the project being tested. This simplifieds working with project dependencies, but **it can have unintended consequences on Windows systems** because [in some cases deleting a folder that contains a symbolic link to another folder can cause the _entire linked folder_ to be removed instead of just the link itself](https://superuser.com/a/306618).
|
41
|
-
>
|
42
|
-
> If you use a Windows system **it is recommended that you only run `arduino_ci` from project directories that are already inside the `libraries` directory**
|
43
42
|
|
44
43
|
### You Need Ruby and Bundler
|
45
44
|
|
46
|
-
You'll need Ruby version 2.
|
45
|
+
You'll need Ruby version 2.5 or higher, and to `gem install bundler` if it's not already there.
|
47
46
|
|
48
47
|
|
49
48
|
### You Need A Compiler (`g++`)
|
@@ -52,7 +51,14 @@ For unit testing, you will need a compiler; [g++](https://gcc.gnu.org/) is prefe
|
|
52
51
|
|
53
52
|
* **Linux**: `gcc`/`g++` is likely pre-installed.
|
54
53
|
* **OSX**: `g++` is an alias for `clang`, which is provided by Xcode and the developer tools. You are free to `brew install gcc` as well; this is also tested and working.
|
55
|
-
* **Windows**: you will need Cygwin, and the `mingw-gcc-g++` package.
|
54
|
+
* **Windows**: you will need Cygwin, and the `mingw-gcc-g++` package.
|
55
|
+
|
56
|
+
|
57
|
+
### You _May_ Need `python`
|
58
|
+
|
59
|
+
ESP32 and ESP8266 boards have [a dependency on `python` that they don't install themselves](https://github.com/Arduino-CI/arduino_ci/issues/235#issuecomment-739629243). If you intend to test on these platforms (which are included in the default list of platforms to test against), you will need to make `python` (and possibly `pyserial`) available in the test environment.
|
60
|
+
|
61
|
+
Alternately, you might configure `arduino_ci` to simply not test against these. Consult the reference for those details.
|
56
62
|
|
57
63
|
|
58
64
|
### Changes to Your Repo
|
@@ -61,9 +67,11 @@ Add a file called `Gemfile` (no extension) to your Arduino project:
|
|
61
67
|
|
62
68
|
```ruby
|
63
69
|
source 'https://rubygems.org'
|
64
|
-
gem 'arduino_ci'
|
70
|
+
gem 'arduino_ci' '~> 1.1'
|
65
71
|
```
|
66
72
|
|
73
|
+
At the time of this writing, `1.1` is the latest version available, and the `~>` syntax will allow your system to update it to the latest `1.x.x` version. The list of all available versions can be found on [rubygems.org](https://rubygems.org/gems/arduino_ci) if you prefer to explicitly pin a higher version.
|
74
|
+
|
67
75
|
It would also make sense to add the following to your `.gitignore`, or copy [the `.gitignore` used by this project](.gitignore):
|
68
76
|
|
69
77
|
```
|
@@ -184,7 +192,7 @@ test_script:
|
|
184
192
|
|
185
193
|
## Known Problems
|
186
194
|
|
187
|
-
* The Arduino library is not fully mocked
|
195
|
+
* The Arduino library is not fully mocked, nor is `avr-libc`.
|
188
196
|
* I don't have preprocessor defines for all the Arduino board flavors
|
189
197
|
* https://github.com/Arduino-CI/arduino_ci/issues
|
190
198
|
|
data/REFERENCE.md
CHANGED
@@ -29,6 +29,11 @@ This completely skips the compilation tests (of library examples) portion of the
|
|
29
29
|
This completely skips the compilation tests (of library examples) portion of the CI script. It does not skip the compilation of unit tests.
|
30
30
|
|
31
31
|
|
32
|
+
### `--skip-library-properties` option
|
33
|
+
|
34
|
+
This completely skips validation of entries in `library.properties`.
|
35
|
+
|
36
|
+
|
32
37
|
### `--testfile-select` option
|
33
38
|
|
34
39
|
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`.
|
@@ -39,6 +44,16 @@ This allows a file (or glob) pattern to be executed in your tests directory, cre
|
|
39
44
|
This allows a file (or glob) pattern to be executed in your tests directory, creating a blacklist of files to skip. E.g. `--testfile-reject=test_animal_*.cpp` would match `test_animal_cat.cpp` and `test_animal_dog.cpp` (skipping those) and test only `test_plant_rose.cpp`, `test_plant_daisy.cpp`, etc.
|
40
45
|
|
41
46
|
|
47
|
+
### `CUSTOM_INIT_SCRIPT` environment variable
|
48
|
+
|
49
|
+
If set, testing will execute (using `/bin/sh`) the script referred to by this variable -- relative to the current working directory. This enables use cases like the GitHub action to install custom library versions (i.e. a version of a library that is different than what the library manager would automatically install by name) prior to CI test runs.
|
50
|
+
|
51
|
+
|
52
|
+
### `USE_SUBDIR` environment variable
|
53
|
+
|
54
|
+
If set, testing will be conducted in this subdirectory (relative to the working directory). This is for monorepos or other layouts where the library directory and project root directory are different.
|
55
|
+
|
56
|
+
|
42
57
|
### `EXPECT_UNITTESTS` environment variable
|
43
58
|
|
44
59
|
If set, testing will fail if no unit test files are detected (or if the directory does not exist). This is to avoid communicating a passing status in cases where a commit may have accidentally moved or deleted the test files.
|
@@ -49,6 +64,11 @@ If set, testing will fail if no unit test files are detected (or if the director
|
|
49
64
|
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.
|
50
65
|
|
51
66
|
|
67
|
+
### `SKIP_LIBRARY_PROPERTIES` environment variable
|
68
|
+
|
69
|
+
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".
|
70
|
+
|
71
|
+
|
52
72
|
## Indirectly Overriding Build Behavior (medium term use), and Advanced Options
|
53
73
|
|
54
74
|
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:
|
@@ -74,6 +94,8 @@ packages:
|
|
74
94
|
|
75
95
|
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.
|
76
96
|
|
97
|
+
> 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`.
|
98
|
+
|
77
99
|
```yaml
|
78
100
|
platforms:
|
79
101
|
# our custom definition of the "bogo" platform
|
@@ -107,7 +129,9 @@ platforms:
|
|
107
129
|
### Control How Examples Are Compiled
|
108
130
|
|
109
131
|
Put a file `.arduino-ci.yml` in each example directory where you require a different configuration than default.
|
110
|
-
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.
|
132
|
+
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.
|
133
|
+
|
134
|
+
> 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.
|
111
135
|
|
112
136
|
```yaml
|
113
137
|
compile:
|
@@ -198,15 +222,27 @@ This test defines one `unittest` (a macro provided by `ArduinoUnitTests.h`), cal
|
|
198
222
|
|
199
223
|
The following assertion functions are available in unit tests.
|
200
224
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
225
|
+
```c++
|
226
|
+
assertEqual(expected, actual); // a == b
|
227
|
+
assertNotEqual(unwanted, actual); // a != b
|
228
|
+
assertComparativeEquivalent(expected, actual); // abs(a - b) == 0 or (!(a > b) && !(a < b))
|
229
|
+
assertComparativeNotEquivalent(unwanted, actual); // abs(a - b) > 0 or ((a > b) || (a < b))
|
230
|
+
assertLess(upperBound, actual); // a < b
|
231
|
+
assertMore(lowerBound, actual); // a > b
|
232
|
+
assertLessOrEqual(upperBound, actual); // a <= b
|
233
|
+
assertMoreOrEqual(lowerBound, actual); // a >= b
|
234
|
+
assertTrue(actual);
|
235
|
+
assertFalse(actual);
|
236
|
+
assertNull(actual);
|
237
|
+
|
238
|
+
// special cases for floats
|
239
|
+
assertEqualFloat(expected, actual, epsilon); // fabs(a - b) <= epsilon
|
240
|
+
assertNotEqualFloat(unwanted, actual, epsilon); // fabs(a - b) >= epsilon
|
241
|
+
assertInfinity(actual); // isinf(a)
|
242
|
+
assertNotInfinity(actual); // !isinf(a)
|
243
|
+
assertNAN(arg); // isnan(a)
|
244
|
+
assertNotNAN(arg); // !isnan(a)
|
245
|
+
```
|
210
246
|
|
211
247
|
These functions will report the result of the test to the console, and the testing will continue if they fail.
|
212
248
|
|
@@ -327,7 +363,7 @@ unittest(pin_history)
|
|
327
363
|
// we expect 6 values in that queue (5 that we set plus one
|
328
364
|
// initial value), which we'll hard-code here for convenience.
|
329
365
|
// (we'll actually assert those 6 values in the next block)
|
330
|
-
assertEqual(6, state->digitalPin[1].queueSize));
|
366
|
+
assertEqual(6, state->digitalPin[1].queueSize());
|
331
367
|
bool expected[6] = {LOW, HIGH, LOW, LOW, HIGH, HIGH};
|
332
368
|
bool actual[6];
|
333
369
|
|
@@ -634,3 +670,47 @@ unittest(eeprom)
|
|
634
670
|
assertEqual(10, a);
|
635
671
|
}
|
636
672
|
```
|
673
|
+
|
674
|
+
|
675
|
+
### Wire
|
676
|
+
|
677
|
+
This library allows communication with I2C / TWI devices.
|
678
|
+
|
679
|
+
The interface the library has been fully mocked, with the addition of several functions for debugging
|
680
|
+
|
681
|
+
* `Wire.resetMocks()`: Initializes all mocks, and for test repeatability should be called at the top of any unit tests that use Wire.
|
682
|
+
* `Wire.didBegin()`: returns whether `Wire.begin()` was called at any point
|
683
|
+
* `Wire.getMosi(address)`: returns a pointer to a `deque` that represents the history of data sent to `address`
|
684
|
+
* `Wire.getMiso(address)`: returns a pointer to a `deque` that defines what the master will read from `address` (i.e. for you to supply)
|
685
|
+
|
686
|
+
```c++
|
687
|
+
unittest(wire_basics) {
|
688
|
+
// ensure known starting state
|
689
|
+
Wire.resetMocks();
|
690
|
+
|
691
|
+
// in case you need to check that your library is properly calling .begin()
|
692
|
+
assertFalse(Wire.didBegin());
|
693
|
+
Wire.begin();
|
694
|
+
assertTrue(Wire.didBegin());
|
695
|
+
|
696
|
+
// pick a random device. master write buffer should be empty
|
697
|
+
const uint8_t randomSlaveAddr = 14;
|
698
|
+
deque<uint8_t>* mosi = Wire.getMosi(randomSlaveAddr);
|
699
|
+
assertEqual(0, mosi->size());
|
700
|
+
|
701
|
+
// write some random data to random device
|
702
|
+
const uint8_t randomData[] = { 0x07, 0x0E };
|
703
|
+
Wire.beginTransmission(randomSlaveAddr);
|
704
|
+
Wire.write(randomData[0]);
|
705
|
+
Wire.write(randomData[1]);
|
706
|
+
Wire.endTransmission();
|
707
|
+
|
708
|
+
// check master write buffer values
|
709
|
+
assertEqual(2, mosi->size());
|
710
|
+
assertEqual(randomData[0], mosi->front());
|
711
|
+
mosi->pop_front();
|
712
|
+
assertEqual(randomData[1], mosi->front());
|
713
|
+
mosi->pop_front();
|
714
|
+
assertEqual(0, mosi->size());
|
715
|
+
}
|
716
|
+
```
|
data/cpp/arduino/Arduino.h
CHANGED
@@ -36,9 +36,6 @@ typedef uint8_t byte;
|
|
36
36
|
#define highByte(w) ((uint8_t) ((w) >> 8))
|
37
37
|
#define lowByte(w) ((uint8_t) ((w) & 0xff))
|
38
38
|
|
39
|
-
// Arduino defines this
|
40
|
-
#define _NOP() do { 0; } while (0)
|
41
|
-
|
42
39
|
// might as well use that NO-op macro for these, while unit testing
|
43
40
|
// you need interrupts? interrupt yourself
|
44
41
|
#define yield() _NOP()
|
@@ -70,5 +67,3 @@ inline unsigned int makeWord(unsigned int w) { return w; }
|
|
70
67
|
inline unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }
|
71
68
|
|
72
69
|
#define word(...) makeWord(__VA_ARGS__)
|
73
|
-
|
74
|
-
|
@@ -92,3 +92,6 @@
|
|
92
92
|
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
93
93
|
#define LED_BUILTIN 13
|
94
94
|
#endif
|
95
|
+
|
96
|
+
// Arduino defines this
|
97
|
+
#define _NOP() do { 0; } while (0)
|
data/cpp/arduino/Godmode.h
CHANGED
@@ -160,21 +160,78 @@ class GodmodeState {
|
|
160
160
|
};
|
161
161
|
|
162
162
|
// io pins
|
163
|
-
|
164
|
-
|
163
|
+
inline void pinMode(uint8_t pin, uint8_t mode) { _NOP(); }
|
164
|
+
inline void analogReference(uint8_t mode) { _NOP(); }
|
165
165
|
|
166
166
|
void digitalWrite(uint8_t, uint8_t);
|
167
167
|
int digitalRead(uint8_t);
|
168
168
|
int analogRead(uint8_t);
|
169
169
|
void analogWrite(uint8_t, int);
|
170
|
-
|
171
|
-
|
170
|
+
inline void analogReadResolution(uint8_t bits) { _NOP(); }
|
171
|
+
inline void analogWriteResolution(uint8_t bits) { _NOP(); }
|
172
172
|
void attachInterrupt(uint8_t interrupt, void ISR(void), uint8_t mode);
|
173
173
|
void detachInterrupt(uint8_t interrupt);
|
174
174
|
|
175
175
|
// 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
|
+
}
|
178
235
|
|
179
236
|
// These definitions allow the following to compile (see issue #193):
|
180
237
|
// https://github.com/arduino-libraries/Ethernet/blob/master/src/utility/w5100.h:341
|
data/cpp/arduino/Wire.h
CHANGED
@@ -54,19 +54,52 @@ struct wireData_t {
|
|
54
54
|
class TwoWire : public ObservableDataStream {
|
55
55
|
private:
|
56
56
|
bool _didBegin = false;
|
57
|
-
wireData_t
|
58
|
-
wireData_t
|
57
|
+
wireData_t* in = nullptr; // pointer to current slave for writing
|
58
|
+
wireData_t* out = nullptr; // pointer to current slave for reading
|
59
59
|
wireData_t slaves[SLAVE_COUNT];
|
60
60
|
|
61
61
|
public:
|
62
|
-
|
63
|
-
|
62
|
+
|
63
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
64
|
+
// testing methods
|
65
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
66
|
+
|
67
|
+
// initialize all the mocks
|
68
|
+
void resetMocks() {
|
69
|
+
_didBegin = false;
|
70
|
+
in = nullptr; // pointer to current slave for writing
|
71
|
+
out = nullptr; // pointer to current slave for reading
|
64
72
|
for (int i = 0; i < SLAVE_COUNT; ++i) {
|
65
73
|
slaves[i].misoSize = 0;
|
66
74
|
slaves[i].mosiSize = 0;
|
75
|
+
slaves[i].misoBuffer.clear();
|
76
|
+
slaves[i].mosiBuffer.clear();
|
67
77
|
}
|
68
78
|
}
|
69
79
|
|
80
|
+
// to verify that Wire.begin() was called at some point
|
81
|
+
bool didBegin() { return _didBegin; }
|
82
|
+
|
83
|
+
// to access the MISO buffer, which allows you to mock what the master will read in a request
|
84
|
+
deque<uint8_t>* getMiso(uint8_t address) {
|
85
|
+
return &slaves[address].misoBuffer;
|
86
|
+
}
|
87
|
+
|
88
|
+
// to access the MOSI buffer, which records what the master sends during a write
|
89
|
+
deque<uint8_t>* getMosi(uint8_t address) {
|
90
|
+
return &slaves[address].mosiBuffer;
|
91
|
+
}
|
92
|
+
|
93
|
+
|
94
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
95
|
+
// mock implementation
|
96
|
+
//////////////////////////////////////////////////////////////////////////////////////////////
|
97
|
+
|
98
|
+
// constructor initializes internal data
|
99
|
+
TwoWire() {
|
100
|
+
resetMocks();
|
101
|
+
}
|
102
|
+
|
70
103
|
// https://www.arduino.cc/en/Reference/WireBegin
|
71
104
|
// Initiate the Wire library and join the I2C bus as a master or slave. This
|
72
105
|
// should normally be called only once.
|
@@ -220,15 +253,6 @@ public:
|
|
220
253
|
// We don't (yet) support the slave role in the mock
|
221
254
|
void onRequest(void (*callback)(void)) { assert(false); }
|
222
255
|
|
223
|
-
// testing methods
|
224
|
-
bool didBegin() { return _didBegin; }
|
225
|
-
|
226
|
-
deque<uint8_t> *getMiso(uint8_t address) {
|
227
|
-
return &slaves[address].misoBuffer;
|
228
|
-
}
|
229
|
-
deque<uint8_t> *getMosi(uint8_t address) {
|
230
|
-
return &slaves[address].mosiBuffer;
|
231
|
-
}
|
232
256
|
};
|
233
257
|
|
234
258
|
extern TwoWire Wire;
|