arduino_ci 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ };
@@ -40,7 +40,11 @@
40
40
 
41
41
  class SPISettings {
42
42
  public:
43
- SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode){};
43
+ uint8_t bitOrder;
44
+
45
+ SPISettings(uint32_t clock, uint8_t bitOrder = MSBFIRST, uint8_t dataMode = SPI_MODE0) {
46
+ this->bitOrder = bitOrder;
47
+ };
44
48
  SPISettings(){};
45
49
  };
46
50
 
@@ -68,6 +72,7 @@ public:
68
72
  // and configure the correct settings.
69
73
  void beginTransaction(SPISettings settings)
70
74
  {
75
+ this->bitOrder = settings.bitOrder;
71
76
  #ifdef SPI_TRANSACTION_MISMATCH_LED
72
77
  if (inTransactionFlag) {
73
78
  pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
@@ -94,10 +99,12 @@ public:
94
99
  uint16_t transfer16(uint16_t data) {
95
100
  union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out;
96
101
  in.val = data;
97
- if (!(SPCR & (1 << DORD))) {
102
+ if (bitOrder == MSBFIRST) {
98
103
  out.msb = transfer(in.msb);
99
104
  out.lsb = transfer(in.lsb);
100
- } else {
105
+ }
106
+ else
107
+ {
101
108
  out.lsb = transfer(in.lsb);
102
109
  out.msb = transfer(in.msb);
103
110
  }
@@ -143,6 +150,7 @@ private:
143
150
  #endif
144
151
 
145
152
  bool isStarted = false;
153
+ uint8_t bitOrder;
146
154
  String* dataIn;
147
155
  String* dataOut;
148
156
  };
@@ -0,0 +1,5 @@
1
+ #pragma once
2
+
3
+ #include <Stream.h>
4
+
5
+ class Server : public Print {};
@@ -0,0 +1,27 @@
1
+ #pragma once
2
+
3
+ #include <IPAddress.h>
4
+ #include <Stream.h>
5
+
6
+ class UDP : public Stream {
7
+ protected:
8
+ uint8_t *rawIPAddress(IPAddress &addr) { return addr.raw_address(); };
9
+
10
+ public:
11
+ UDP() {
12
+ // The Stream mock defines a String buffer but never puts anyting in it!
13
+ if (!mGodmodeDataIn) {
14
+ mGodmodeDataIn = new String;
15
+ }
16
+ }
17
+ ~UDP() {
18
+ if (mGodmodeDataIn) {
19
+ delete mGodmodeDataIn;
20
+ mGodmodeDataIn = nullptr;
21
+ }
22
+ }
23
+ virtual size_t write(uint8_t value) {
24
+ mGodmodeDataIn->concat(value);
25
+ return 1;
26
+ }
27
+ };
@@ -1,138 +1,234 @@
1
+ /*
2
+ * The Wire Library (https://www.arduino.cc/en/Reference/Wire)
3
+ * allows you to communicate with I2C/TWI devices. The general
4
+ * TWI protocol supports one "master" device and many "slave"
5
+ * devices that share the same two wires (SDA and SCL for data
6
+ * and clock respectively).
7
+ *
8
+ * You initialize the library by calling begin() as a master or
9
+ * begin(myAddress) as a slave (with an int from 8-127). In the
10
+ * initial mock implementation we support only the master role.
11
+ *
12
+ * To send bytes from a master to a slave, start with
13
+ * beginTransmission(slaveAddress), then use write(byte) to
14
+ * enqueue data, and finish with endTransmission().
15
+ *
16
+ * When a master wants to read, it starts with a call to
17
+ * requestFrom(slaveAddress, quantity) which blocks until the
18
+ * request finishes. The return value is either 0 (if the slave
19
+ * does not respond) or the number of bytes requested (which
20
+ * might be more than the number sent since reading is simply
21
+ * looking at a pin value at each clock tick).
22
+ *
23
+ * A master can write to or read from two or more slaves in
24
+ * quick succession (say, during one loop() function), so our
25
+ * mock needs to support preloading data to be read from multiple
26
+ * slaves and archive data sent to multiple slaves.
27
+ *
28
+ * In the mock, this is handled by having an array of wireData_t
29
+ * structures, each of which contains a deque for input and a
30
+ * deque for output. You can preload data to be read and you can
31
+ * look at a log of data that has been written.
32
+ */
1
33
 
2
34
  #pragma once
3
35
 
4
36
  #include <inttypes.h>
5
37
  #include "Stream.h"
38
+ #include <cassert>
39
+ #include <deque>
40
+ using std::deque;
41
+
42
+ const size_t SLAVE_COUNT = 128;
43
+ const size_t BUFFER_LENGTH = 32;
44
+
45
+ struct wireData_t {
46
+ uint8_t misoSize; // bytes remaining for this read
47
+ uint8_t mosiSize; // bytes included in this write
48
+ deque<uint8_t> misoBuffer; // master in, slave out
49
+ deque<uint8_t> mosiBuffer; // master out, slave in
50
+ };
51
+
52
+ // Some inspiration taken from
53
+ // https://github.com/arduino/ArduinoCore-megaavr/blob/d2a81093ba66d22dbda14c30d146c231c5910734/libraries/Wire/src/Wire.cpp
54
+ class TwoWire : public ObservableDataStream {
55
+ private:
56
+ bool _didBegin = false;
57
+ wireData_t *in = nullptr; // pointer to current slave for writing
58
+ wireData_t *out = nullptr; // pointer to current slave for reading
59
+ wireData_t slaves[SLAVE_COUNT];
6
60
 
7
- class TwoWire : public ObservableDataStream
8
- {
9
61
  public:
62
+ // constructor initializes internal data
10
63
  TwoWire() {
64
+ for (int i = 0; i < SLAVE_COUNT; ++i) {
65
+ slaves[i].misoSize = 0;
66
+ slaves[i].mosiSize = 0;
67
+ }
11
68
  }
12
69
 
13
70
  // https://www.arduino.cc/en/Reference/WireBegin
14
- // Initiate the Wire library and join the I2C bus as a master or slave. This should normally be called only once.
15
- void begin() {
16
- isMaster = true;
17
- }
18
- void begin(int address) {
19
- i2cAddress = address;
20
- isMaster = false;
21
- }
71
+ // Initiate the Wire library and join the I2C bus as a master or slave. This
72
+ // should normally be called only once.
73
+ void begin() { begin(0); }
22
74
  void begin(uint8_t address) {
23
- begin((int)address);
24
- }
25
- void end() {
26
- // TODO: implement
75
+ assert(address == 0);
76
+ _didBegin = true;
27
77
  }
78
+ void begin(int address) { begin((uint8_t)address); }
79
+ // NOTE: end() is not part of the published API so we ignore it
80
+ void end() {}
28
81
 
29
82
  // https://www.arduino.cc/en/Reference/WireSetClock
30
- // This function modifies the clock frequency for I2C communication. I2C slave devices have no minimum working
31
- // clock frequency, however 100KHz is usually the baseline.
32
- void setClock(uint32_t) {
33
- // TODO: implement?
34
- }
83
+ // This function modifies the clock frequency for I2C communication. I2C slave
84
+ // devices have no minimum working clock frequency, however 100KHz is usually
85
+ // the baseline.
86
+ // Since the mock does not actually write pins we ignore this.
87
+ void setClock(uint32_t clock) {}
35
88
 
36
89
  // https://www.arduino.cc/en/Reference/WireBeginTransmission
37
- // Begin a transmission to the I2C slave device with the given address. Subsequently, queue bytes for
38
- // transmission with the write() function and transmit them by calling endTransmission().
39
- void beginTransmission(int address) {
40
- // TODO: implement
41
- }
90
+ // Begin a transmission to the I2C slave device with the given address.
91
+ // Subsequently, queue bytes for transmission with the write() function and
92
+ // transmit them by calling endTransmission().
93
+ // For the mock we update our output to the proper destination.
42
94
  void beginTransmission(uint8_t address) {
43
- beginTransmission((int)address);
95
+ assert(_didBegin);
96
+ assert(address > 0 && address < SLAVE_COUNT);
97
+ assert(out == nullptr);
98
+ out = &slaves[address];
99
+ out->mosiSize = 0;
44
100
  }
101
+ void beginTransmission(int address) { beginTransmission((uint8_t)address); }
45
102
 
46
103
  // https://www.arduino.cc/en/Reference/WireEndTransmission
47
- // Ends a transmission to a slave device that was begun by beginTransmission() and transmits the bytes that were
48
- // queued by write().
49
- uint8_t endTransmission(uint8_t sendStop) {
50
- // TODO: implement
104
+ // Ends a transmission to a slave device that was begun by beginTransmission()
105
+ // and transmits the bytes that were queued by write().
106
+ // In the mock we just leave the bytes there in the buffer
107
+ // to be read by the testing API and we ignore the sendStop.
108
+ uint8_t endTransmission(bool sendStop) {
109
+ assert(_didBegin);
110
+ assert(out);
111
+ out = nullptr;
51
112
  return 0; // success
52
113
  }
53
- uint8_t endTransmission(void) {
54
- return endTransmission((uint8_t)true);
55
- }
114
+ uint8_t endTransmission(void) { return endTransmission(true); }
56
115
 
57
116
  // https://www.arduino.cc/en/Reference/WireRequestFrom
58
- // Used by the master to request bytes from a slave device. The bytes may then be retrieved with the
59
- // available() and read() functions.
60
- uint8_t requestFrom(int address, int quantity, int stop) {
61
- // TODO: implement
62
- return 0; // number of bytes returned from the slave device
117
+ // Used by the master to request bytes from a slave device. The bytes may then
118
+ // be retrieved with the available() and read() functions.
119
+ uint8_t requestFrom(uint8_t address, uint8_t quantity, uint32_t _iaddress, uint8_t _isize, uint8_t stop) {
120
+ assert(_didBegin);
121
+ assert(address > 0 && address < SLAVE_COUNT);
122
+ assert(quantity <= BUFFER_LENGTH);
123
+ in = &slaves[address];
124
+ // do we have enough data in the input buffer
125
+ if (quantity <= (in->misoBuffer).size()) { // enough data
126
+ in->misoSize = quantity;
127
+ return quantity;
128
+ } else { // not enough data
129
+ in->misoSize = 0;
130
+ in = nullptr;
131
+ return 0;
132
+ }
63
133
  }
64
- uint8_t requestFrom(int address, int quantity) {
65
- int stop = true;
66
- return requestFrom(address, quantity, stop);
134
+
135
+ uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t stop) {
136
+ return requestFrom((uint8_t)address, (uint8_t)quantity, (uint32_t)0, (uint8_t)0, (uint8_t)stop);
67
137
  }
138
+
68
139
  uint8_t requestFrom(uint8_t address, uint8_t quantity) {
69
- return requestFrom((int)address, (int)quantity);
140
+ return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
70
141
  }
71
- uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t stop) {
72
- return requestFrom((int)address, (int)quantity, (int)stop);
142
+
143
+ uint8_t requestFrom(int address, int quantity) {
144
+ return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
73
145
  }
74
- uint8_t requestFrom(uint8_t, uint8_t, uint32_t, uint8_t, uint8_t) {
75
- // TODO: implement
76
- return 0;
146
+ uint8_t requestFrom(int address, int quantity, int stop) {
147
+ return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)stop);
77
148
  }
78
149
 
79
150
  // https://www.arduino.cc/en/Reference/WireWrite
80
- // Writes data from a slave device in response to a request from a master, or queues bytes for transmission from a
81
- // master to slave device (in-between calls to beginTransmission() and endTransmission()).
151
+ // Writes data from a slave device in response to a request from a master, or
152
+ // queues bytes for transmission from a master to slave device (in-between
153
+ // calls to beginTransmission() and endTransmission()).
82
154
  size_t write(uint8_t value) {
83
- // TODO: implement
84
- return 0; // number of bytes written
155
+ assert(out);
156
+ assert(++(out->mosiSize) <= BUFFER_LENGTH);
157
+ (out->mosiBuffer).push_back(value);
158
+ return 1; // number of bytes written
159
+ }
160
+ size_t write(const char *str) {
161
+ return str == NULL ? 0 : write((const uint8_t *)str, String(str).length());
85
162
  }
86
- size_t write(const char *str) { return str == NULL ? 0 : write((const uint8_t *)str, String(str).length()); }
87
163
  size_t write(const uint8_t *buffer, size_t size) {
88
164
  size_t n;
89
- for (n = 0; size && write(*buffer++) && ++n; --size);
165
+ for (n = 0; size && write(*buffer++) && ++n; --size)
166
+ ;
90
167
  return n;
91
168
  }
92
- size_t write(const char *buffer, size_t size) { return write((const uint8_t *)buffer, size); }
169
+ size_t write(const char *buffer, size_t size) {
170
+ return write((const uint8_t *)buffer, size);
171
+ }
93
172
  size_t write(unsigned long n) { return write((uint8_t)n); }
94
173
  size_t write(long n) { return write((uint8_t)n); }
95
174
  size_t write(unsigned int n) { return write((uint8_t)n); }
96
175
  size_t write(int n) { return write((uint8_t)n); }
97
176
 
98
177
  // https://www.arduino.cc/en/Reference/WireAvailable
99
- // Returns the number of bytes available for retrieval with read(). This should be called on a master device after a
100
- // call to requestFrom() or on a slave inside the onReceive() handler.
178
+ // Returns the number of bytes available for retrieval with read(). This
179
+ // should be called on a master device after a call to requestFrom() or on a
180
+ // slave inside the onReceive() handler.
101
181
  int available(void) {
102
- // TODO: implement
103
- return 0; // number of bytes available for reading
182
+ assert(in);
183
+ return in->misoSize;
104
184
  }
105
185
 
106
186
  // https://www.arduino.cc/en/Reference/WireRead
107
- // Reads a byte that was transmitted from a slave device to a master after a call to requestFrom() or was transmitted
108
- // from a master to a slave. read() inherits from the Stream utility class.
109
- int read(void) {
110
- // TODO: implement
111
- return '\0'; // The next byte received
187
+ // Reads a byte that was transmitted from a slave device to a master after a
188
+ // call to requestFrom() or was transmitted from a master to a slave. read()
189
+ // inherits from the Stream utility class.
190
+ // In the mock we simply return the next byte from the input buffer.
191
+ uint8_t read(void) {
192
+ uint8_t value = peek();
193
+ --in->misoSize;
194
+ in->misoBuffer.pop_front();
195
+ return value; // The next byte received
112
196
  }
113
- int peek(void) {
114
- // TODO: implement
115
- return 0;
197
+
198
+ // part of the Stream API
199
+ uint8_t peek(void) {
200
+ assert(in);
201
+ assert(0 < in->misoSize);
202
+ return in->misoBuffer.front(); // The next byte received
116
203
  }
204
+
205
+ // part of the Stream API
117
206
  void flush(void) {
118
- // TODO: implement
207
+ // NOTE: commented out in the megaavr repository
208
+ // data already at the (mock) destination
119
209
  }
120
210
 
121
211
  // https://www.arduino.cc/en/Reference/WireOnReceive
122
- // Registers a function to be called when a slave device receives a transmission from a master.
123
- void onReceive( void (*callback)(int) ) {
124
- // TODO: implement
125
- }
212
+ // Registers a function to be called when a slave device receives a
213
+ // transmission from a master.
214
+ // We don't (yet) support the slave role in the mock
215
+ void onReceive(void (*callback)(int)) { assert(false); }
126
216
 
127
217
  // https://www.arduino.cc/en/Reference/WireOnRequest
128
- // Register a function to be called when a master requests data from this slave device.
129
- void onRequest( void (*callback)(void) ) {
130
- // TODO: implement
131
- }
218
+ // Register a function to be called when a master requests data from this
219
+ // slave device.
220
+ // We don't (yet) support the slave role in the mock
221
+ void onRequest(void (*callback)(void)) { assert(false); }
132
222
 
133
- private:
134
- int i2cAddress;
135
- bool isMaster = false;
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
+ }
136
232
  };
137
233
 
138
234
  extern TwoWire Wire;
@@ -96,7 +96,16 @@
96
96
  #ifndef _AVR_IO_H_
97
97
  #define _AVR_IO_H_
98
98
 
99
- #define _SFR_IO8(io_addr) (io_addr) // this macro is all we need from the sfr file
99
+ #include <stdint.h>
100
+
101
+ // hardware mocks
102
+ // this set of macros is all we need from the sfr file
103
+ extern volatile uint8_t __ARDUINO_CI_SFR_MOCK[1024];
104
+ #define _SFR_IO8(io_addr) (*(volatile uint8_t *)(__ARDUINO_CI_SFR_MOCK + io_addr))
105
+ #define _SFR_IO16(io_addr) (*(volatile uint16_t *)(__ARDUINO_CI_SFR_MOCK + io_addr))
106
+ #define _SFR_MEM8(io_addr) (*(volatile uint8_t *)(__ARDUINO_CI_SFR_MOCK + io_addr))
107
+ #define _SFR_MEM16(io_addr) (*(volatile uint16_t *)(__ARDUINO_CI_SFR_MOCK + io_addr))
108
+ #define _SFR_MEM32(io_addr) (*(volatile uint32_t *)(__ARDUINO_CI_SFR_MOCK + io_addr))
100
109
 
101
110
  #if defined (__AVR_AT94K__)
102
111
  # include "ioat94k.h"