arduino_ci 0.1.20 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -19
  3. data/REFERENCE.md +625 -0
  4. data/cpp/arduino/Arduino.h +1 -2
  5. data/cpp/arduino/AvrMath.h +117 -17
  6. data/cpp/arduino/Client.h +26 -0
  7. data/cpp/arduino/EEPROM.h +64 -0
  8. data/cpp/arduino/Godmode.cpp +38 -19
  9. data/cpp/arduino/Godmode.h +88 -22
  10. data/cpp/arduino/HardwareSerial.h +9 -28
  11. data/cpp/arduino/IPAddress.h +59 -0
  12. data/cpp/arduino/MockEventQueue.h +86 -0
  13. data/cpp/arduino/PinHistory.h +64 -24
  14. data/cpp/arduino/Print.h +9 -12
  15. data/cpp/arduino/Printable.h +8 -0
  16. data/cpp/arduino/SPI.h +11 -3
  17. data/cpp/arduino/Server.h +5 -0
  18. data/cpp/arduino/Udp.h +27 -0
  19. data/cpp/arduino/Wire.h +234 -0
  20. data/cpp/arduino/avr/io.h +10 -1
  21. data/cpp/arduino/avr/pgmspace.h +76 -46
  22. data/cpp/arduino/ci/StreamTape.h +36 -0
  23. data/cpp/unittest/ArduinoUnitTests.h +1 -0
  24. data/cpp/unittest/Compare.h +91 -897
  25. data/cpp/unittest/OstreamHelpers.h +9 -0
  26. data/exe/arduino_ci.rb +401 -0
  27. data/exe/arduino_ci_remote.rb +2 -385
  28. data/lib/arduino_ci.rb +1 -0
  29. data/lib/arduino_ci/arduino_cmd.rb +13 -9
  30. data/lib/arduino_ci/arduino_downloader.rb +5 -4
  31. data/lib/arduino_ci/arduino_installation.rb +5 -5
  32. data/lib/arduino_ci/ci_config.rb +12 -0
  33. data/lib/arduino_ci/cpp_library.rb +152 -25
  34. data/lib/arduino_ci/installed_cpp_library.rb +0 -0
  35. data/lib/arduino_ci/library_properties.rb +86 -0
  36. data/lib/arduino_ci/version.rb +1 -1
  37. data/misc/default.yml +50 -3
  38. metadata +23 -13
  39. data/cpp/arduino/Arduino.h.orig +0 -143
  40. data/cpp/arduino/Nullptr.h +0 -7
  41. data/cpp/arduino/ci/Queue.h +0 -73
  42. data/exe/libasan.rb +0 -29
@@ -1,7 +1,7 @@
1
1
  #pragma once
2
2
 
3
3
  //#include <inttypes.h>
4
- #include "Stream.h"
4
+ #include "ci/StreamTape.h"
5
5
 
6
6
  // definitions neeeded for Serial.begin's config arg
7
7
  #define SERIAL_5N1 0x00
@@ -29,53 +29,34 @@
29
29
  #define SERIAL_7O2 0x3C
30
30
  #define SERIAL_8O2 0x3E
31
31
 
32
- class HardwareSerial : public Stream, public ObservableDataStream
32
+ class HardwareSerial : public StreamTape
33
33
  {
34
- protected:
35
- String* mGodmodeDataOut;
36
-
37
34
  public:
38
- HardwareSerial(String* dataIn, String* dataOut, unsigned long* delay): Stream(), ObservableDataStream() {
39
- mGodmodeDataIn = dataIn;
40
- mGodmodeDataOut = dataOut;
41
- mGodmodeMicrosDelay = delay;
42
- }
35
+ HardwareSerial(String* dataIn, String* dataOut, unsigned long* delay): StreamTape(dataIn, dataOut, delay) {}
36
+
43
37
  void begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
44
38
  void begin(unsigned long baud, uint8_t config) {
45
39
  *mGodmodeMicrosDelay = 1000000 / baud;
46
40
  }
47
41
  void end() {}
48
42
 
49
- // virtual int available(void);
50
- // virtual int peek(void);
51
- // virtual int read(void);
52
- // virtual int availableForWrite(void);
53
- // virtual void flush(void);
54
- virtual size_t write(uint8_t aChar) {
55
- mGodmodeDataOut->append(String((char)aChar));
56
- advertiseByte((unsigned char)aChar);
57
- return 1;
58
- }
59
-
60
- // https://stackoverflow.com/a/4271276
61
- using Print::write; // pull in write(str) and write(buf, size) from Print
43
+ // support "if (Serial1) {}" sorts of things
62
44
  operator bool() { return true; }
63
-
64
45
  };
65
46
 
66
- #if defined(UBRRH) || defined(UBRR0H)
47
+ #if NUM_SERIAL_PORTS >= 1
67
48
  extern HardwareSerial Serial;
68
49
  #define HAVE_HWSERIAL0
69
50
  #endif
70
- #if defined(UBRR1H)
51
+ #if NUM_SERIAL_PORTS >= 2
71
52
  extern HardwareSerial Serial1;
72
53
  #define HAVE_HWSERIAL1
73
54
  #endif
74
- #if defined(UBRR2H)
55
+ #if NUM_SERIAL_PORTS >= 3
75
56
  extern HardwareSerial Serial2;
76
57
  #define HAVE_HWSERIAL2
77
58
  #endif
78
- #if defined(UBRR3H)
59
+ #if NUM_SERIAL_PORTS >= 4
79
60
  extern HardwareSerial Serial3;
80
61
  #define HAVE_HWSERIAL3
81
62
  #endif
@@ -0,0 +1,59 @@
1
+ #pragma once
2
+
3
+ #include <stdint.h>
4
+
5
+ class IPAddress {
6
+ private:
7
+ union {
8
+ uint8_t bytes[4];
9
+ uint32_t dword;
10
+ operator uint8_t *() const { return (uint8_t *)bytes; }
11
+ } _address;
12
+
13
+ public:
14
+ // Constructors
15
+ IPAddress() : IPAddress(0, 0, 0, 0) {}
16
+ IPAddress(uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4) {
17
+ _address.bytes[0] = octet1;
18
+ _address.bytes[1] = octet2;
19
+ _address.bytes[2] = octet3;
20
+ _address.bytes[3] = octet4;
21
+ }
22
+ IPAddress(uint32_t dword) { _address.dword = dword; }
23
+ IPAddress(const uint8_t bytes[]) {
24
+ _address.bytes[0] = bytes[0];
25
+ _address.bytes[1] = bytes[1];
26
+ _address.bytes[2] = bytes[2];
27
+ _address.bytes[3] = bytes[3];
28
+ }
29
+ IPAddress(unsigned long dword) { _address.dword = (uint32_t)dword; }
30
+
31
+ // Accessors
32
+ uint32_t asWord() const { return _address.dword; }
33
+ uint8_t *raw_address() { return _address.bytes; }
34
+
35
+ // Comparisons
36
+ bool operator==(const IPAddress &rhs) const {
37
+ return _address.dword == rhs.asWord();
38
+ }
39
+
40
+ bool operator!=(const IPAddress &rhs) const {
41
+ return _address.dword != rhs.asWord();
42
+ }
43
+
44
+ // Indexing
45
+ uint8_t operator[](int index) const { return _address.bytes[index]; }
46
+ uint8_t &operator[](int index) { return _address.bytes[index]; }
47
+
48
+ // Conversions
49
+ operator uint32_t() const { return _address.dword; };
50
+
51
+ friend class EthernetClass;
52
+ friend class UDP;
53
+ friend class Client;
54
+ friend class Server;
55
+ friend class DhcpClass;
56
+ friend class DNSClient;
57
+ };
58
+
59
+ const IPAddress INADDR_NONE(0, 0, 0, 0);
@@ -0,0 +1,86 @@
1
+ #pragma once
2
+
3
+ template <typename T>
4
+ class MockEventQueue {
5
+ public:
6
+ struct Event {
7
+ T data;
8
+ unsigned long micros;
9
+
10
+ Event() : data(T()), micros(0) {}
11
+ Event(const T &d, unsigned long const t) : data(d), micros(t) { }
12
+ };
13
+
14
+ private:
15
+ struct Node {
16
+ Event event;
17
+ Node* next;
18
+
19
+ Node(const Event &e, Node* n) : event(e), next(n) { }
20
+ };
21
+
22
+ Node* mFront;
23
+ Node* mBack;
24
+ unsigned long mSize;
25
+ T mNil;
26
+ unsigned long (*mGetMicros)(void);
27
+
28
+ void init(unsigned long (*getMicros)(void)) {
29
+ mFront = mBack = nullptr;
30
+ mSize = 0;
31
+ mGetMicros = getMicros;
32
+ }
33
+
34
+ public:
35
+ MockEventQueue(unsigned long (*getMicros)(void)): mNil() { init(getMicros); }
36
+ MockEventQueue(): mNil() { init(nullptr); }
37
+
38
+ MockEventQueue(const MockEventQueue<T>& q) {
39
+ init(q.mGetMicros);
40
+ for (Node* n = q.mFront; n; n = n->next) push(n->event);
41
+ }
42
+
43
+ void setMicrosRetriever(unsigned long (*getMicros)(void)) { mGetMicros = getMicros; }
44
+
45
+ inline unsigned long size() const { return mSize; }
46
+ inline bool empty() const { return 0 == mSize; }
47
+ inline Event front() const { return empty() ? Event(mNil, 0) : mFront->event; }
48
+ inline Event back() const { return empty() ? Event(mNil, 0) : mBack->event; }
49
+ inline T frontData() const { return front().data; }
50
+ inline T backData() const { return back().data; }
51
+ inline unsigned long frontTime() const { return front().micros; }
52
+ inline unsigned long backTime() const { return back().micros; }
53
+
54
+
55
+ // fully formed event
56
+ bool push(const Event& e) {
57
+ Node *n = new Node(e, nullptr);
58
+ if (n == nullptr) return false;
59
+ mBack = (mFront == nullptr ? mFront : mBack->next) = n;
60
+ return ++mSize;
61
+ }
62
+
63
+ // fully specfied event
64
+ bool push(const T& v, unsigned long const time) {
65
+ Event e = {v, time};
66
+ return push(e);
67
+ }
68
+
69
+ // event needing timestamp
70
+ bool push(const T& v) {
71
+ unsigned long micros = mGetMicros == nullptr ? 0 : mGetMicros();
72
+ return push(v, micros);
73
+ }
74
+
75
+ void pop() {
76
+ if (empty()) return;
77
+ Node* n = mFront;
78
+ mFront = mFront->next;
79
+ delete n;
80
+ if (--mSize == 0) mBack = nullptr;
81
+ }
82
+
83
+ void clear() { while (!empty()) pop(); }
84
+
85
+ ~MockEventQueue() { clear(); }
86
+ };
@@ -1,5 +1,5 @@
1
1
  #pragma once
2
- #include "ci/Queue.h"
2
+ #include "MockEventQueue.h"
3
3
  #include "ci/ObservableDataStream.h"
4
4
  #include "WString.h"
5
5
 
@@ -7,8 +7,8 @@
7
7
  template <typename T>
8
8
  class PinHistory : public ObservableDataStream {
9
9
  private:
10
- ArduinoCIQueue<T> qIn;
11
- ArduinoCIQueue<T> qOut;
10
+ MockEventQueue<T> qIn;
11
+ MockEventQueue<T> qOut;
12
12
 
13
13
  void clear() {
14
14
  qOut.clear();
@@ -16,14 +16,14 @@ class PinHistory : public ObservableDataStream {
16
16
  }
17
17
 
18
18
  // enqueue ascii bits
19
- void a2q(ArduinoCIQueue<T> &q, String input, bool bigEndian, bool advertise) {
19
+ void a2q(MockEventQueue<T> &q, String input, bool bigEndian, bool advertise) {
20
20
  // 8 chars at a time, form up
21
21
  for (int j = 0; j < input.length(); ++j) {
22
22
  for (int i = 0; i < 8; ++i) {
23
23
  int shift = bigEndian ? 7 - i : i;
24
24
  unsigned char mask = (0x01 << shift);
25
25
  q.push(mask & input[j]);
26
- if (advertise) advertiseBit(q.back()); // not valid for all possible types but whatever
26
+ if (advertise) advertiseBit(q.backData()); // not valid for all possible types but whatever
27
27
  }
28
28
  }
29
29
  }
@@ -31,10 +31,10 @@ class PinHistory : public ObservableDataStream {
31
31
 
32
32
  // convert a queue to a string as if it was serial bits
33
33
  // start from offset, consider endianness
34
- String q2a(const ArduinoCIQueue<T> &q, unsigned int offset, bool bigEndian) const {
34
+ String q2a(const MockEventQueue<T> &q, unsigned int offset, bool bigEndian) const {
35
35
  String ret = "";
36
36
 
37
- ArduinoCIQueue<T> q2(q);
37
+ MockEventQueue<T> q2(q);
38
38
 
39
39
  while (offset) {
40
40
  q2.pop();
@@ -48,7 +48,7 @@ class PinHistory : public ObservableDataStream {
48
48
  unsigned char acc = 0x00;
49
49
  for (int i = 0; i < 8; ++i) {
50
50
  int shift = bigEndian ? 7 - i : i;
51
- T val = q2.front();
51
+ T val = q2.frontData();
52
52
  unsigned char bit = val ? 0x1 : 0x0;
53
53
  acc |= (bit << shift);
54
54
  q2.pop();
@@ -59,15 +59,25 @@ class PinHistory : public ObservableDataStream {
59
59
  return ret;
60
60
  }
61
61
 
62
+ void init() {
63
+ asciiEncodingOffsetIn = 0; // default is sensible
64
+ asciiEncodingOffsetOut = 1; // default is sensible
65
+ }
66
+
62
67
  public:
63
68
  unsigned int asciiEncodingOffsetIn;
64
69
  unsigned int asciiEncodingOffsetOut;
65
70
 
71
+ PinHistory(unsigned long (*getMicros)(void)) : ObservableDataStream(), qOut(getMicros) {
72
+ init();
73
+ }
74
+
66
75
  PinHistory() : ObservableDataStream() {
67
- asciiEncodingOffsetIn = 0; // default is sensible
68
- asciiEncodingOffsetOut = 1; // default is sensible
76
+ init();
69
77
  }
70
78
 
79
+ void setMicrosRetriever(unsigned long (*getMicros)(void)) { qOut.setMicrosRetriever(getMicros); }
80
+
71
81
  void reset(T val) {
72
82
  clear();
73
83
  qOut.push(val);
@@ -79,8 +89,8 @@ class PinHistory : public ObservableDataStream {
79
89
 
80
90
  // This returns the "value" of the pin in a raw sense
81
91
  operator T() const {
82
- if (!qIn.empty()) return qIn.front();
83
- return qOut.back();
92
+ if (!qIn.empty()) return qIn.frontData();
93
+ return qOut.backData();
84
94
  }
85
95
 
86
96
  // this sets the value of the pin authoritatively
@@ -89,8 +99,8 @@ class PinHistory : public ObservableDataStream {
89
99
  T operator=(const T& i) {
90
100
  qIn.clear();
91
101
  qOut.push(i);
92
- advertiseBit(qOut.back()); // not valid for all possible types but whatever
93
- return qOut.back();
102
+ advertiseBit(qOut.backData()); // not valid for all possible types but whatever
103
+ return qOut.backData();
94
104
  }
95
105
 
96
106
  // This returns the "value" of the pin according to the queued values
@@ -98,14 +108,14 @@ class PinHistory : public ObservableDataStream {
98
108
  // then take the latest output.
99
109
  T retrieve() {
100
110
  if (!qIn.empty()) {
101
- T hack_required_by_travis_ci = qIn.front();
111
+ T hack_required_by_travis_ci = qIn.frontData();
102
112
  qIn.pop();
103
113
  qOut.push(hack_required_by_travis_ci);
104
114
  }
105
- return qOut.back();
115
+ return qOut.backData();
106
116
  }
107
117
 
108
- // enqueue a set of elements
118
+ // enqueue a set of data elements
109
119
  void fromArray(T const * const arr, unsigned int length) {
110
120
  for (int i = 0; i < length; ++i) qIn.push(arr[i]);
111
121
  }
@@ -124,18 +134,48 @@ class PinHistory : public ObservableDataStream {
124
134
  // start from offset, consider endianness
125
135
  String incomingToAscii(bool bigEndian) const { return incomingToAscii(asciiEncodingOffsetIn, bigEndian); }
126
136
 
127
- // convert the pin history to a string as if it was Serial comms
137
+ // convert the pin history data to a string as if it was Serial comms
128
138
  // start from offset, consider endianness
129
139
  String toAscii(unsigned int offset, bool bigEndian) const { return q2a(qOut, offset, bigEndian); }
130
140
 
131
- // convert the pin history to a string as if it was Serial comms
141
+ // convert the pin history data to a string as if it was Serial comms
132
142
  // start from offset, consider endianness
133
143
  String toAscii(bool bigEndian) const { return toAscii(asciiEncodingOffsetOut, bigEndian); }
134
144
 
135
- // copy elements to an array, up to a given length
145
+ // copy data elements to an array, up to a given length
136
146
  // return the number of elements moved
137
147
  int toArray (T* arr, unsigned int length) const {
138
- ArduinoCIQueue<T> q2(qOut);
148
+ MockEventQueue<T> q2(qOut); // preserve const by copying
149
+
150
+ int ret = 0;
151
+ for (int i = 0; i < length && q2.size(); ++i) {
152
+ arr[i] = q2.frontData();
153
+ q2.pop();
154
+ ++ret;
155
+ }
156
+ return ret;
157
+ }
158
+
159
+ // copy pin history timing to an array, up to a given length.
160
+ // note that this records times between calls to the pin, not between transitions
161
+ // return the number of elements moved
162
+ int toTimestampArray(unsigned long* arr, unsigned int length) const {
163
+ MockEventQueue<T> q2(qOut); // preserve const by copying
164
+
165
+ int ret = 0;
166
+ for (int i = 0; i < length && q2.size(); ++i) {
167
+ arr[i] = q2.frontTime();
168
+ q2.pop();
169
+ ++ret;
170
+ }
171
+ return ret;
172
+ }
173
+
174
+ // copy pin history timing to an array, up to a given length.
175
+ // note that this records times between calls to the pin, not between transitions
176
+ // return the number of elements moved
177
+ int toEventArray(typename MockEventQueue<T>::Event* arr, unsigned int length) const {
178
+ MockEventQueue<T> q2(qOut); // preserve const by copying
139
179
 
140
180
  int ret = 0;
141
181
  for (int i = 0; i < length && q2.size(); ++i) {
@@ -146,12 +186,12 @@ class PinHistory : public ObservableDataStream {
146
186
  return ret;
147
187
  }
148
188
 
149
- // see if the array matches the elements in the queue
189
+ // see if the array matches the data of the elements in the queue
150
190
  bool hasElements (T const * const arr, unsigned int length) const {
151
191
  int i;
152
- ArduinoCIQueue<T> q2(qOut);
192
+ MockEventQueue<T> q2(qOut); // preserve const by copying
153
193
  for (i = 0; i < length && q2.size(); ++i) {
154
- if (q2.front() != arr[i]) return false;
194
+ if (q2.frontData() != arr[i]) return false;
155
195
  q2.pop();
156
196
  }
157
197
  return i == length;
@@ -2,6 +2,8 @@
2
2
 
3
3
  #include <stdio.h>
4
4
  #include <avr/pgmspace.h>
5
+
6
+ #include "Printable.h"
5
7
  #include "WString.h"
6
8
 
7
9
  #define DEC 10
@@ -12,22 +14,17 @@
12
14
  #endif
13
15
  #define BIN 2
14
16
 
15
- class Print;
16
-
17
- class Printable
18
- {
19
- public:
20
- virtual size_t printTo(Print& p) const = 0;
21
- };
22
-
23
17
  class Print
24
18
  {
19
+ private:
20
+ int write_error;
21
+ protected:
22
+ void setWriteError(int err = 1) { write_error = err; }
25
23
  public:
26
- Print() {}
24
+ Print() : write_error(0) {}
27
25
 
28
- // Arduino's version of this is richer but until I see an actual error case I'm not sure how to mock
29
- int getWriteError() { return 0; }
30
- void clearWriteError() { }
26
+ int getWriteError() { return write_error; }
27
+ void clearWriteError() { setWriteError(0); }
31
28
  virtual int availableForWrite() { return 0; }
32
29
 
33
30
  virtual size_t write(uint8_t) = 0;
@@ -0,0 +1,8 @@
1
+ #pragma once
2
+
3
+ class Print;
4
+
5
+ class Printable {
6
+ public:
7
+ virtual size_t printTo(Print &p) const = 0;
8
+ };