arduino_ci 0.1.21 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f16bbf16889f4244fd035daa6af2901f48652617
4
- data.tar.gz: f95a8a86712af293b2e48aa386031ae1a2872f36
3
+ metadata.gz: ec22bfa6969f75cdb38ffa4365c3d8f2f83f2185
4
+ data.tar.gz: 2380ce41fe0779e258471b28e9e94eee3c238369
5
5
  SHA512:
6
- metadata.gz: 379a7bee7c9c88ce6dcc0abffa990ca67c1a2e2c6b04a5521c4958fa29ba2b65672a1d21e8d1b523f8bc0a098d3cf8e9f9d9c9a97336248855d3890472511a81
7
- data.tar.gz: 491efe2046ef7414f7adf381c6bd9cf68d7b203c88f644a0a0cd836319611195b0338676a73db4bad3d210f6612071af8e976243f07a4fa17618afa5492d9a43
6
+ metadata.gz: 2c464279ef51852b51b22287960474da51a2818c9d41b8aadc181287636fa095effa8644f08320a62af7316a8540e9279ccf904c4936da619e82b7fb0011b21c
7
+ data.tar.gz: 7dfecd48948dfa8588e150841ee24c472480a20f10892c6098905fa35220bca26690708f827ec5b290d1564006f5a3c3019c7638eac27b9669311f6203f3973c
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- # ArduinoCI Ruby gem (`arduino_ci`) [![Gem Version](https://badge.fury.io/rb/arduino_ci.svg)](https://rubygems.org/gems/arduino_ci) [![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://www.rubydoc.info/gems/arduino_ci/0.1.21)
2
+ # ArduinoCI Ruby gem (`arduino_ci`) [![Gem Version](https://badge.fury.io/rb/arduino_ci.svg)](https://rubygems.org/gems/arduino_ci) [![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://www.rubydoc.info/gems/arduino_ci/0.2.0)
3
3
 
4
4
  You want to run tests on your Arduino library (bonus: without hardware present), but the IDE doesn't support that. Arduino CI provides that ability.
5
5
 
@@ -2,37 +2,45 @@
2
2
  #include "HardwareSerial.h"
3
3
  #include "SPI.h"
4
4
 
5
- GodmodeState godmode = GodmodeState();
6
-
7
5
  GodmodeState* GODMODE() {
8
- return &godmode;
6
+ return GodmodeState::getInstance();
7
+ }
8
+
9
+ GodmodeState* GodmodeState::instance = nullptr;
10
+
11
+ GodmodeState* GodmodeState::getInstance()
12
+ {
13
+ if (instance == nullptr)
14
+ {
15
+ instance = new GodmodeState();
16
+ for (int i = 0; i < MOCK_PINS_COUNT; ++i) {
17
+ instance->digitalPin[i].setMicrosRetriever(&GodmodeState::getMicros);
18
+ instance->analogPin[i].setMicrosRetriever(&GodmodeState::getMicros);
19
+ }
20
+ }
21
+
22
+ return instance;
9
23
  }
10
24
 
11
25
  unsigned long millis() {
12
- GodmodeState* godmode = GODMODE();
13
- return godmode->micros / 1000;
26
+ return GODMODE()->micros / 1000;
14
27
  }
15
28
 
16
29
  unsigned long micros() {
17
- GodmodeState* godmode = GODMODE();
18
- return godmode->micros;
30
+ return GODMODE()->micros;
19
31
  }
20
32
 
21
33
  void delay(unsigned long millis) {
22
- GodmodeState* godmode = GODMODE();
23
- godmode->micros += millis * 1000;
34
+ GODMODE()->micros += millis * 1000;
24
35
  }
25
36
 
26
37
  void delayMicroseconds(unsigned long micros) {
27
- GodmodeState* godmode = GODMODE();
28
- godmode->micros += micros;
38
+ GODMODE()->micros += micros;
29
39
  }
30
40
 
31
-
32
41
  void randomSeed(unsigned long seed)
33
42
  {
34
- GodmodeState* godmode = GODMODE();
35
- godmode->seed = seed;
43
+ GODMODE()->seed = seed;
36
44
  }
37
45
 
38
46
  long random(long vmax)
@@ -81,16 +89,16 @@ void detachInterrupt(uint8_t interrupt) {
81
89
 
82
90
  // Serial ports
83
91
  #if defined(HAVE_HWSERIAL0)
84
- HardwareSerial Serial(&godmode.serialPort[0].dataIn, &godmode.serialPort[0].dataOut, &godmode.serialPort[0].readDelayMicros);
92
+ HardwareSerial Serial(&GODMODE()->serialPort[0].dataIn, &GODMODE()->serialPort[0].dataOut, &GODMODE()->serialPort[0].readDelayMicros);
85
93
  #endif
86
94
  #if defined(HAVE_HWSERIAL1)
87
- HardwareSerial Serial1(&godmode.serialPort[1].dataIn, &godmode.serialPort[1].dataOut, &godmode.serialPort[1].readDelayMicros);
95
+ HardwareSerial Serial1(&GODMODE()->serialPort[1].dataIn, &GODMODE()->serialPort[1].dataOut, &GODMODE()->serialPort[1].readDelayMicros);
88
96
  #endif
89
97
  #if defined(HAVE_HWSERIAL2)
90
- HardwareSerial Serial2(&godmode.serialPort[2].dataIn, &godmode.serialPort[2].dataOut, &godmode.serialPort[2].readDelayMicros);
98
+ HardwareSerial Serial2(&GODMODE()->serialPort[2].dataIn, &GODMODE()->serialPort[2].dataOut, &GODMODE()->serialPort[2].readDelayMicros);
91
99
  #endif
92
100
  #if defined(HAVE_HWSERIAL3)
93
- HardwareSerial Serial3(&godmode.serialPort[3].dataIn, &godmode.serialPort[3].dataOut, &godmode.serialPort[3].readDelayMicros);
101
+ HardwareSerial Serial3(&GODMODE()->serialPort[3].dataIn, &GODMODE()->serialPort[3].dataOut, &GODMODE()->serialPort[3].readDelayMicros);
94
102
  #endif
95
103
 
96
104
  template <typename T>
@@ -100,4 +108,4 @@ inline std::ostream& operator << ( std::ostream& out, const PinHistory<T>& ph )
100
108
  }
101
109
 
102
110
  // defined in SPI.h
103
- SPIClass SPI = SPIClass(&godmode.spi.dataIn, &godmode.spi.dataOut);
111
+ SPIClass SPI = SPIClass(&GODMODE()->spi.dataIn, &GODMODE()->spi.dataOut);
@@ -16,7 +16,6 @@ void delayMicroseconds(unsigned long micros);
16
16
  unsigned long millis();
17
17
  unsigned long micros();
18
18
 
19
-
20
19
  #define MOCK_PINS_COUNT 256
21
20
 
22
21
  #if defined(UBRR3H)
@@ -32,16 +31,19 @@ unsigned long micros();
32
31
  #endif
33
32
 
34
33
  class GodmodeState {
35
- struct PortDef {
36
- String dataIn;
37
- String dataOut;
38
- unsigned long readDelayMicros;
39
- };
34
+ private:
35
+ struct PortDef {
36
+ String dataIn;
37
+ String dataOut;
38
+ unsigned long readDelayMicros;
39
+ };
40
+
41
+ struct InterruptDef {
42
+ bool attached;
43
+ uint8_t mode;
44
+ };
40
45
 
41
- struct InterruptDef {
42
- bool attached;
43
- uint8_t mode;
44
- };
46
+ static GodmodeState* instance;
45
47
 
46
48
  public:
47
49
  unsigned long micros;
@@ -98,8 +100,24 @@ class GodmodeState {
98
100
  return NUM_SERIAL_PORTS;
99
101
  }
100
102
 
101
- GodmodeState()
102
- {
103
+ // Using this for anything other than unit testing arduino_ci itself
104
+ // is unsupported at the moment
105
+ void overrideClockTruth(unsigned long (*getMicros)(void)) {
106
+ }
107
+
108
+ // singleton pattern
109
+ static GodmodeState* getInstance();
110
+
111
+ static unsigned long getMicros() {
112
+ return instance->micros;
113
+ }
114
+
115
+ // C++ 11, declare as public for better compiler error messages
116
+ GodmodeState(GodmodeState const&) = delete;
117
+ void operator=(GodmodeState const&) = delete;
118
+
119
+ private:
120
+ GodmodeState() {
103
121
  reset();
104
122
  }
105
123
  };
@@ -123,4 +141,3 @@ inline void noTone(uint8_t _pin) {}
123
141
 
124
142
 
125
143
  GodmodeState* GODMODE();
126
-
@@ -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;
@@ -1,3 +1,3 @@
1
1
  module ArduinoCI
2
- VERSION = "0.1.21".freeze
2
+ VERSION = "0.2.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arduino_ci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.21
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian Katz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-02-07 00:00:00.000000000 Z
11
+ date: 2019-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: os
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.0.1
61
+ version: 0.0.2
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.0.1
68
+ version: 0.0.2
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -129,6 +129,7 @@ files:
129
129
  - cpp/arduino/Godmode.cpp
130
130
  - cpp/arduino/Godmode.h
131
131
  - cpp/arduino/HardwareSerial.h
132
+ - cpp/arduino/MockEventQueue.h
132
133
  - cpp/arduino/PinHistory.h
133
134
  - cpp/arduino/Print.h
134
135
  - cpp/arduino/SPI.h
@@ -414,7 +415,6 @@ files:
414
415
  - cpp/arduino/binary.h
415
416
  - cpp/arduino/ci/DeviceUsingBytes.h
416
417
  - cpp/arduino/ci/ObservableDataStream.h
417
- - cpp/arduino/ci/Queue.h
418
418
  - cpp/arduino/ci/README.md
419
419
  - cpp/arduino/ci/Table.h
420
420
  - cpp/arduino/stdlib.cpp
@@ -1,73 +0,0 @@
1
- #pragma once
2
-
3
- template <typename T>
4
- class ArduinoCIQueue {
5
- private:
6
- struct Node {
7
- T data;
8
- Node* next;
9
- };
10
-
11
- Node* mFront;
12
- Node* mBack;
13
- unsigned long mSize;
14
- T mNil;
15
-
16
- void init() {
17
- mFront = mBack = NULL;
18
- mSize = 0;
19
- }
20
-
21
- public:
22
- ArduinoCIQueue(): mNil() { init(); }
23
-
24
- ArduinoCIQueue(const ArduinoCIQueue<T>& q) {
25
- init();
26
- for (Node* n = q.mFront; n; n = n->next) push(n->data);
27
- }
28
-
29
- inline unsigned long size() const { return mSize; }
30
-
31
- inline bool empty() const { return 0 == mSize; }
32
-
33
- T front() const { return empty() ? mNil : mFront->data; }
34
-
35
- T back() const { return empty() ? mNil : mBack->data; }
36
-
37
- bool push(const T& v)
38
- {
39
- Node *n = new Node;
40
- if (n == NULL) return false;
41
-
42
- n->data = v;
43
- n->next = NULL;
44
-
45
- if (mFront == NULL)
46
- {
47
- mFront = mBack = n;
48
- } else {
49
- mBack->next = n;
50
- mBack = n;
51
- }
52
-
53
- ++mSize;
54
- return true;
55
- }
56
-
57
- void pop() {
58
- if (empty()) return;
59
- if (mFront == mBack) {
60
- mFront = mBack = NULL;
61
- } else {
62
- Node* n = mFront;
63
- mFront = mFront->next;
64
- delete n;
65
- }
66
-
67
- --mSize;
68
- }
69
-
70
- void clear() { while (!empty()) pop(); }
71
-
72
- ~ArduinoCIQueue() { clear(); }
73
- };