arduino_ci 0.3.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +125 -69
  3. data/REFERENCE.md +711 -0
  4. data/cpp/arduino/Arduino.h +1 -7
  5. data/cpp/arduino/ArduinoDefines.h +3 -0
  6. data/cpp/arduino/AvrMath.h +117 -17
  7. data/cpp/arduino/Client.h +27 -0
  8. data/cpp/arduino/EEPROM.h +64 -0
  9. data/cpp/arduino/Godmode.cpp +7 -0
  10. data/cpp/arduino/Godmode.h +121 -15
  11. data/cpp/arduino/HardwareSerial.h +4 -4
  12. data/cpp/arduino/IPAddress.h +59 -0
  13. data/cpp/arduino/Print.h +9 -12
  14. data/cpp/arduino/Printable.h +8 -0
  15. data/cpp/arduino/SPI.h +11 -3
  16. data/cpp/arduino/Server.h +5 -0
  17. data/cpp/arduino/Udp.h +27 -0
  18. data/cpp/arduino/Wire.h +197 -77
  19. data/cpp/arduino/avr/io.h +10 -1
  20. data/cpp/arduino/avr/pgmspace.h +76 -46
  21. data/cpp/unittest/ArduinoUnitTests.h +32 -0
  22. data/cpp/unittest/Assertion.h +54 -26
  23. data/cpp/unittest/Compare.h +58 -51
  24. data/cpp/unittest/OstreamHelpers.h +4 -0
  25. data/exe/arduino_ci.rb +538 -0
  26. data/exe/arduino_ci_remote.rb +2 -393
  27. data/exe/arduino_library_location.rb +2 -2
  28. data/exe/ensure_arduino_installation.rb +7 -1
  29. data/lib/arduino_ci.rb +1 -0
  30. data/lib/arduino_ci/arduino_backend.rb +238 -0
  31. data/lib/arduino_ci/arduino_downloader.rb +43 -73
  32. data/lib/arduino_ci/arduino_downloader_linux.rb +17 -55
  33. data/lib/arduino_ci/arduino_downloader_osx.rb +21 -33
  34. data/lib/arduino_ci/arduino_downloader_windows.rb +11 -53
  35. data/lib/arduino_ci/arduino_installation.rb +18 -80
  36. data/lib/arduino_ci/ci_config.rb +8 -11
  37. data/lib/arduino_ci/cpp_library.rb +250 -59
  38. data/lib/arduino_ci/host.rb +59 -4
  39. data/lib/arduino_ci/library_properties.rb +101 -0
  40. data/lib/arduino_ci/version.rb +1 -1
  41. data/misc/default.yml +57 -6
  42. metadata +19 -87
  43. data/cpp/arduino/Arduino.h.orig +0 -143
  44. data/exe/libasan.rb +0 -29
  45. data/lib/arduino_ci/arduino_cmd.rb +0 -332
  46. data/lib/arduino_ci/arduino_cmd_linux.rb +0 -17
  47. data/lib/arduino_ci/arduino_cmd_linux_builder.rb +0 -19
  48. data/lib/arduino_ci/arduino_cmd_osx.rb +0 -17
  49. data/lib/arduino_ci/arduino_cmd_windows.rb +0 -17
@@ -9,13 +9,12 @@ Where possible, variable names from the Arduino library are used to avoid confli
9
9
 
10
10
  #include "ArduinoDefines.h"
11
11
 
12
+ #include "IPAddress.h"
12
13
  #include "WCharacter.h"
13
14
  #include "WString.h"
14
15
  #include "Print.h"
15
16
  #include "Stream.h"
16
17
  #include "HardwareSerial.h"
17
- #include "SPI.h"
18
- #include "Wire.h"
19
18
 
20
19
  typedef bool boolean;
21
20
  typedef uint8_t byte;
@@ -37,9 +36,6 @@ typedef uint8_t byte;
37
36
  #define highByte(w) ((uint8_t) ((w) >> 8))
38
37
  #define lowByte(w) ((uint8_t) ((w) & 0xff))
39
38
 
40
- // Arduino defines this
41
- #define _NOP() do { 0; } while (0)
42
-
43
39
  // might as well use that NO-op macro for these, while unit testing
44
40
  // you need interrupts? interrupt yourself
45
41
  #define yield() _NOP()
@@ -71,5 +67,3 @@ inline unsigned int makeWord(unsigned int w) { return w; }
71
67
  inline unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }
72
68
 
73
69
  #define word(...) makeWord(__VA_ARGS__)
74
-
75
-
@@ -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)
@@ -1,26 +1,126 @@
1
1
  #pragma once
2
+ #include "ArduinoDefines.h"
2
3
  #include <math.h>
3
4
 
4
- #define constrain(x,l,h) ((x)<(l)?(l):((x)>(h)?(h):(x)))
5
- #define map(x,inMin,inMax,outMin,outMax) (((x)-(inMin))*((outMax)-(outMin))/((inMax)-(inMin))+outMin)
5
+ #ifdef __cplusplus
6
6
 
7
- #define sq(x) ((x)*(x))
7
+ template <class Amt, class Low, class High>
8
+ auto constrain(const Amt &amt, const Low &low, const High &high)
9
+ -> decltype(amt < low ? low : (amt > high ? high : amt)) {
10
+ return (amt < low ? low : (amt > high ? high : amt));
11
+ }
8
12
 
9
- #define radians(deg) ((deg)*DEG_TO_RAD)
10
- #define degrees(rad) ((rad)*RAD_TO_DEG)
13
+ template <class X, class InMin, class InMax, class OutMin, class OutMax>
14
+ auto map(const X &x, const InMin &inMin, const InMax &inMax,
15
+ const OutMin &outMin, const OutMax &outMax)
16
+ -> decltype((x - inMin) * (outMax - outMin) / (inMax - inMin) + outMin) {
17
+ return (x - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
18
+ }
11
19
 
12
- #ifdef abs
13
- #undef abs
14
- #endif
15
- #define abs(x) ((x)>0?(x):-(x))
20
+ template <class T> auto radians(const T &deg) -> decltype(deg * DEG_TO_RAD) {
21
+ return deg * DEG_TO_RAD;
22
+ }
16
23
 
17
- #ifdef max
18
- #undef max
19
- #endif
20
- #define max(a,b) ((a)>(b)?(a):(b))
24
+ template <class T> auto degrees(const T &rad) -> decltype(rad * RAD_TO_DEG) {
25
+ return rad * RAD_TO_DEG;
26
+ }
21
27
 
22
- #ifdef min
23
- #undef min
24
- #endif
25
- #define min(a,b) ((a)<(b)?(a):(b))
28
+ template <class T> auto sq(const T &x) -> decltype(x * x) { return x * x; }
29
+
30
+ template <class T> auto abs(const T &x) -> decltype(x > 0 ? x : -x) {
31
+ return x > 0 ? x : -x;
32
+ }
33
+
34
+ template <class T, class L>
35
+ auto min(const T &a, const L &b) -> decltype((b < a) ? b : a) {
36
+ return (b < a) ? b : a;
37
+ }
38
+
39
+ template <class T, class L>
40
+ auto max(const T &a, const L &b) -> decltype((b < a) ? b : a) {
41
+ return (a < b) ? b : a;
42
+ }
43
+
44
+ #else // __cplusplus
45
+
46
+ #ifdef constrain
47
+ #undef constrain
48
+ #endif
49
+ #define constrain(amt, low, high) \
50
+ ({ \
51
+ __typeof__(amt) _amt = (amt); \
52
+ __typeof__(low) _low = (low); \
53
+ __typeof__(high) _high = (high); \
54
+ (amt < low ? low : (amt > high ? high : amt)); \
55
+ })
26
56
 
57
+ #ifdef map
58
+ #undef map
59
+ #endif
60
+ #define map(x, inMin, inMax, outMin, outMax) \
61
+ ({ \
62
+ __typeof__(x) _x = (x); \
63
+ __typeof__(inMin) _inMin = (inMin); \
64
+ __typeof__(inMax) _inMax = (inMax); \
65
+ __typeof__(outMin) _outMin = (outMin); \
66
+ __typeof__(outMax) _outMax = (outMax); \
67
+ (_x - _inMin) * (_outMax - _outMin) / (_inMax - _inMin) + _outMin; \
68
+ })
69
+
70
+ #ifdef radians
71
+ #undef radians
72
+ #endif
73
+ #define radians(deg) \
74
+ ({ \
75
+ __typeof__(deg) _deg = (deg); \
76
+ _deg *DEG_TO_RAD; \
77
+ })
78
+
79
+ #ifdef degrees
80
+ #undef degrees
81
+ #endif
82
+ #define degrees(rad) \
83
+ ({ \
84
+ __typeof__(rad) _rad = (rad); \
85
+ _rad *RAD_TO_DEG; \
86
+ })
87
+
88
+ #ifdef sq
89
+ #undef sq
90
+ #endif
91
+ #define sq(x) \
92
+ ({ \
93
+ __typeof__(x) _x = (x); \
94
+ _x *_x; \
95
+ })
96
+
97
+ #ifdef abs
98
+ #undef abs
99
+ #endif
100
+ #define abs(x) \
101
+ ({ \
102
+ __typeof__(x) _x = (x); \
103
+ _x > 0 ? _x : -_x; \
104
+ })
105
+
106
+ #ifdef min
107
+ #undef min
108
+ #endif
109
+ #define min(a, b) \
110
+ ({ \
111
+ __typeof__(a) _a = (a); \
112
+ __typeof__(b) _b = (b); \
113
+ _a < _b ? _a : _b; \
114
+ })
115
+
116
+ #ifdef max
117
+ #undef max
118
+ #endif
119
+ #define max(a, b) \
120
+ ({ \
121
+ __typeof__(a) _a = (a); \
122
+ __typeof__(b) _b = (b); \
123
+ _a > _b ? _a : _b; \
124
+ })
125
+
126
+ #endif
@@ -0,0 +1,27 @@
1
+ #pragma once
2
+
3
+ #include <Stream.h>
4
+ #include <IPAddress.h>
5
+
6
+ class Client : public Stream {
7
+ public:
8
+ Client() {
9
+ // The Stream mock defines a String buffer but never puts anyting in it!
10
+ if (!mGodmodeDataIn) {
11
+ mGodmodeDataIn = new String;
12
+ }
13
+ }
14
+ ~Client() {
15
+ if (mGodmodeDataIn) {
16
+ delete mGodmodeDataIn;
17
+ mGodmodeDataIn = nullptr;
18
+ }
19
+ }
20
+ virtual size_t write(uint8_t value) {
21
+ mGodmodeDataIn->concat(value);
22
+ return 1;
23
+ }
24
+
25
+ protected:
26
+ uint8_t *rawIPAddress(IPAddress &addr) { return addr.raw_address(); }
27
+ };
@@ -0,0 +1,64 @@
1
+ #pragma once
2
+
3
+ #include <cassert>
4
+ #include <inttypes.h>
5
+ #include <Godmode.h>
6
+
7
+ // Does the current board have EEPROM?
8
+ #ifndef EEPROM_SIZE
9
+ // In lieu of an "EEPROM.h not found" error for unsupported boards
10
+ #error "EEPROM library not available for your board"
11
+ #endif
12
+
13
+ class EEPROMClass {
14
+ private:
15
+ GodmodeState* state;
16
+ public:
17
+ // constructor
18
+ EEPROMClass() {
19
+ state = GODMODE();
20
+ }
21
+ // array subscript operator
22
+ uint8_t &operator[](const int index) {
23
+ assert(index < EEPROM_SIZE);
24
+ return state->eeprom[index];
25
+ }
26
+
27
+ uint8_t read(const int index) {
28
+ assert(index < EEPROM_SIZE);
29
+ return state->eeprom[index];
30
+ }
31
+
32
+ void write(const int index, const uint8_t value) {
33
+ assert(index < EEPROM_SIZE);
34
+ state->eeprom[index] = value;
35
+ }
36
+
37
+ void update(const int index, const uint8_t value) {
38
+ assert(index < EEPROM_SIZE);
39
+ state->eeprom[index] = value;
40
+ }
41
+
42
+ uint16_t length() { return EEPROM_SIZE; }
43
+
44
+ // read any object
45
+ template <typename T> T &get(const int index, T &object) {
46
+ uint8_t *ptr = (uint8_t *)&object;
47
+ for (int i = 0; i < sizeof(T); ++i) {
48
+ *ptr++ = read(index + i);
49
+ }
50
+ return object;
51
+ }
52
+
53
+ // write any object
54
+ template <typename T> const T &put(const int index, T &object) {
55
+ const uint8_t *ptr = (const uint8_t *)&object;
56
+ for (int i = 0; i < sizeof(T); ++i) {
57
+ write(index + i, *ptr++);
58
+ }
59
+ return object;
60
+ }
61
+ };
62
+
63
+ // global available in Godmode.cpp
64
+ extern EEPROMClass EEPROM;
@@ -113,3 +113,10 @@ SPIClass SPI = SPIClass(&GODMODE()->spi.dataIn, &GODMODE()->spi.dataOut);
113
113
 
114
114
  // defined in Wire.h
115
115
  TwoWire Wire = TwoWire();
116
+
117
+ #if defined(EEPROM_SIZE)
118
+ #include <EEPROM.h>
119
+ EEPROMClass EEPROM;
120
+ #endif
121
+
122
+ volatile uint8_t __ARDUINO_CI_SFR_MOCK[1024];
@@ -1,6 +1,8 @@
1
1
  #pragma once
2
2
  #include "ArduinoDefines.h"
3
+ #if defined(__AVR__)
3
4
  #include <avr/io.h>
5
+ #endif
4
6
  #include "WString.h"
5
7
  #include "PinHistory.h"
6
8
 
@@ -18,16 +20,29 @@ unsigned long micros();
18
20
 
19
21
  #define MOCK_PINS_COUNT 256
20
22
 
21
- #if defined(UBRR3H)
22
- #define NUM_SERIAL_PORTS 4
23
- #elif defined(UBRR2H)
24
- #define NUM_SERIAL_PORTS 3
25
- #elif defined(UBRR1H)
26
- #define NUM_SERIAL_PORTS 2
27
- #elif defined(UBRRH) || defined(UBRR0H)
28
- #define NUM_SERIAL_PORTS 1
23
+ #if (!defined NUM_SERIAL_PORTS)
24
+ #if defined(UBRR3H)
25
+ #define NUM_SERIAL_PORTS 4
26
+ #elif defined(UBRR2H)
27
+ #define NUM_SERIAL_PORTS 3
28
+ #elif defined(UBRR1H)
29
+ #define NUM_SERIAL_PORTS 2
30
+ #elif defined(UBRRH) || defined(UBRR0H)
31
+ #define NUM_SERIAL_PORTS 1
32
+ #else
33
+ #define NUM_SERIAL_PORTS 0
34
+ #endif
35
+ #endif
36
+
37
+ // different EEPROM implementations have different macros that leak out
38
+ #if !defined(EEPROM_SIZE) && defined(E2END) && (E2END)
39
+ // public value indicates that feature is available
40
+ #define EEPROM_SIZE (E2END + 1)
41
+ // local array size
42
+ #define _EEPROM_SIZE EEPROM_SIZE
29
43
  #else
30
- #define NUM_SERIAL_PORTS 0
44
+ // feature is not available but we want to have the array so other code compiles
45
+ #define _EEPROM_SIZE (0)
31
46
  #endif
32
47
 
33
48
  class GodmodeState {
@@ -43,6 +58,8 @@ class GodmodeState {
43
58
  uint8_t mode;
44
59
  };
45
60
 
61
+ uint8_t mmapPorts[MOCK_PINS_COUNT];
62
+
46
63
  static GodmodeState* instance;
47
64
 
48
65
  public:
@@ -54,6 +71,7 @@ class GodmodeState {
54
71
  struct PortDef serialPort[NUM_SERIAL_PORTS];
55
72
  struct InterruptDef interrupt[MOCK_PINS_COUNT]; // not sure how to get actual number
56
73
  struct PortDef spi;
74
+ uint8_t eeprom[_EEPROM_SIZE];
57
75
 
58
76
  void resetPins() {
59
77
  for (int i = 0; i < MOCK_PINS_COUNT; ++i) {
@@ -87,12 +105,28 @@ class GodmodeState {
87
105
  spi.readDelayMicros = 0;
88
106
  }
89
107
 
108
+ void resetMmapPorts() {
109
+ for (int i = 0; i < MOCK_PINS_COUNT; ++i) {
110
+ mmapPorts[i] = 1;
111
+ }
112
+ }
113
+
114
+ void resetEEPROM() {
115
+ #if defined(EEPROM_SIZE)
116
+ for(int i = 0; i < EEPROM_SIZE; ++i) {
117
+ eeprom[i] = 255;
118
+ }
119
+ #endif
120
+ }
121
+
90
122
  void reset() {
91
123
  resetClock();
92
124
  resetPins();
93
125
  resetInterrupts();
94
126
  resetPorts();
95
127
  resetSPI();
128
+ resetMmapPorts();
129
+ resetEEPROM();
96
130
  seed = 1;
97
131
  }
98
132
 
@@ -112,6 +146,9 @@ class GodmodeState {
112
146
  return instance->micros;
113
147
  }
114
148
 
149
+ uint8_t* pMmapPort(uint8_t port) { return &mmapPorts[port]; }
150
+ uint8_t mmapPortValue(uint8_t port) { return mmapPorts[port]; }
151
+
115
152
  // C++ 11, declare as public for better compiler error messages
116
153
  GodmodeState(GodmodeState const&) = delete;
117
154
  void operator=(GodmodeState const&) = delete;
@@ -123,21 +160,90 @@ class GodmodeState {
123
160
  };
124
161
 
125
162
  // io pins
126
- #define pinMode(...) _NOP()
127
- #define analogReference(...) _NOP()
163
+ inline void pinMode(uint8_t pin, uint8_t mode) { _NOP(); }
164
+ inline void analogReference(uint8_t mode) { _NOP(); }
128
165
 
129
166
  void digitalWrite(uint8_t, uint8_t);
130
167
  int digitalRead(uint8_t);
131
168
  int analogRead(uint8_t);
132
169
  void analogWrite(uint8_t, int);
133
- #define analogReadResolution(...) _NOP()
134
- #define analogWriteResolution(...) _NOP()
170
+ inline void analogReadResolution(uint8_t bits) { _NOP(); }
171
+ inline void analogWriteResolution(uint8_t bits) { _NOP(); }
135
172
  void attachInterrupt(uint8_t interrupt, void ISR(void), uint8_t mode);
136
173
  void detachInterrupt(uint8_t interrupt);
137
174
 
138
175
  // TODO: issue #26 to track the commanded state here
139
- inline void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0) {}
140
- 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
+ }
235
+
236
+ // These definitions allow the following to compile (see issue #193):
237
+ // https://github.com/arduino-libraries/Ethernet/blob/master/src/utility/w5100.h:341
238
+ // we allow one byte per port which "wastes" 224 bytes, but makes the code easier
239
+ #if defined(__AVR__)
240
+ #define digitalPinToBitMask(pin) (1)
241
+ #define digitalPinToPort(pin) (pin)
242
+ #define portInputRegister(port) (GODMODE()->pMmapPort(port))
243
+ #define portOutputRegister(port) (GODMODE()->pMmapPort(port))
244
+ #else
245
+ // we don't (yet) support other boards
246
+ #endif
141
247
 
142
248
 
143
249
  GodmodeState* GODMODE();