arduino_ci 0.2.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +49 -20
- data/REFERENCE.md +636 -0
- data/cpp/arduino/Arduino.h +1 -1
- data/cpp/arduino/AvrMath.h +117 -17
- data/cpp/arduino/Client.h +27 -0
- data/cpp/arduino/EEPROM.h +64 -0
- data/cpp/arduino/Godmode.cpp +11 -0
- data/cpp/arduino/Godmode.h +58 -9
- data/cpp/arduino/HardwareSerial.h +9 -28
- data/cpp/arduino/IPAddress.h +59 -0
- data/cpp/arduino/Print.h +9 -12
- data/cpp/arduino/Printable.h +8 -0
- data/cpp/arduino/SPI.h +11 -3
- data/cpp/arduino/Server.h +5 -0
- data/cpp/arduino/Udp.h +27 -0
- data/cpp/arduino/Wire.h +234 -0
- data/cpp/arduino/avr/io.h +10 -1
- data/cpp/arduino/avr/pgmspace.h +76 -46
- data/cpp/arduino/ci/StreamTape.h +36 -0
- data/cpp/unittest/OstreamHelpers.h +4 -0
- data/exe/arduino_ci.rb +427 -0
- data/exe/arduino_ci_remote.rb +2 -385
- data/exe/arduino_library_location.rb +2 -2
- data/exe/ensure_arduino_installation.rb +7 -1
- data/lib/arduino_ci.rb +1 -0
- data/lib/arduino_ci/arduino_backend.rb +222 -0
- data/lib/arduino_ci/arduino_downloader.rb +43 -73
- data/lib/arduino_ci/arduino_downloader_linux.rb +17 -55
- data/lib/arduino_ci/arduino_downloader_osx.rb +21 -33
- data/lib/arduino_ci/arduino_downloader_windows.rb +11 -53
- data/lib/arduino_ci/arduino_installation.rb +18 -80
- data/lib/arduino_ci/ci_config.rb +15 -9
- data/lib/arduino_ci/cpp_library.rb +266 -48
- data/lib/arduino_ci/host.rb +59 -4
- data/lib/arduino_ci/library_properties.rb +96 -0
- data/lib/arduino_ci/version.rb +1 -1
- data/misc/default.yml +55 -4
- metadata +21 -87
- data/cpp/arduino/Arduino.h.orig +0 -143
- data/exe/libasan.rb +0 -29
- data/lib/arduino_ci/arduino_cmd.rb +0 -328
- data/lib/arduino_ci/arduino_cmd_linux.rb +0 -17
- data/lib/arduino_ci/arduino_cmd_linux_builder.rb +0 -19
- data/lib/arduino_ci/arduino_cmd_osx.rb +0 -17
- data/lib/arduino_ci/arduino_cmd_windows.rb +0 -17
@@ -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);
|
data/cpp/arduino/Print.h
CHANGED
@@ -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
|
-
|
29
|
-
|
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;
|
data/cpp/arduino/SPI.h
CHANGED
@@ -40,7 +40,11 @@
|
|
40
40
|
|
41
41
|
class SPISettings {
|
42
42
|
public:
|
43
|
-
|
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 (
|
102
|
+
if (bitOrder == MSBFIRST) {
|
98
103
|
out.msb = transfer(in.msb);
|
99
104
|
out.lsb = transfer(in.lsb);
|
100
|
-
}
|
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
|
};
|
data/cpp/arduino/Udp.h
ADDED
@@ -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
|
+
};
|
data/cpp/arduino/Wire.h
ADDED
@@ -0,0 +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
|
+
*/
|
33
|
+
|
34
|
+
#pragma once
|
35
|
+
|
36
|
+
#include <inttypes.h>
|
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];
|
60
|
+
|
61
|
+
public:
|
62
|
+
// constructor initializes internal data
|
63
|
+
TwoWire() {
|
64
|
+
for (int i = 0; i < SLAVE_COUNT; ++i) {
|
65
|
+
slaves[i].misoSize = 0;
|
66
|
+
slaves[i].mosiSize = 0;
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
// https://www.arduino.cc/en/Reference/WireBegin
|
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); }
|
74
|
+
void begin(uint8_t address) {
|
75
|
+
assert(address == 0);
|
76
|
+
_didBegin = true;
|
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() {}
|
81
|
+
|
82
|
+
// https://www.arduino.cc/en/Reference/WireSetClock
|
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) {}
|
88
|
+
|
89
|
+
// https://www.arduino.cc/en/Reference/WireBeginTransmission
|
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.
|
94
|
+
void beginTransmission(uint8_t address) {
|
95
|
+
assert(_didBegin);
|
96
|
+
assert(address > 0 && address < SLAVE_COUNT);
|
97
|
+
assert(out == nullptr);
|
98
|
+
out = &slaves[address];
|
99
|
+
out->mosiSize = 0;
|
100
|
+
}
|
101
|
+
void beginTransmission(int address) { beginTransmission((uint8_t)address); }
|
102
|
+
|
103
|
+
// https://www.arduino.cc/en/Reference/WireEndTransmission
|
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;
|
112
|
+
return 0; // success
|
113
|
+
}
|
114
|
+
uint8_t endTransmission(void) { return endTransmission(true); }
|
115
|
+
|
116
|
+
// https://www.arduino.cc/en/Reference/WireRequestFrom
|
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
|
+
}
|
133
|
+
}
|
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);
|
137
|
+
}
|
138
|
+
|
139
|
+
uint8_t requestFrom(uint8_t address, uint8_t quantity) {
|
140
|
+
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
|
141
|
+
}
|
142
|
+
|
143
|
+
uint8_t requestFrom(int address, int quantity) {
|
144
|
+
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
|
145
|
+
}
|
146
|
+
uint8_t requestFrom(int address, int quantity, int stop) {
|
147
|
+
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)stop);
|
148
|
+
}
|
149
|
+
|
150
|
+
// https://www.arduino.cc/en/Reference/WireWrite
|
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()).
|
154
|
+
size_t write(uint8_t value) {
|
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());
|
162
|
+
}
|
163
|
+
size_t write(const uint8_t *buffer, size_t size) {
|
164
|
+
size_t n;
|
165
|
+
for (n = 0; size && write(*buffer++) && ++n; --size)
|
166
|
+
;
|
167
|
+
return n;
|
168
|
+
}
|
169
|
+
size_t write(const char *buffer, size_t size) {
|
170
|
+
return write((const uint8_t *)buffer, size);
|
171
|
+
}
|
172
|
+
size_t write(unsigned long n) { return write((uint8_t)n); }
|
173
|
+
size_t write(long n) { return write((uint8_t)n); }
|
174
|
+
size_t write(unsigned int n) { return write((uint8_t)n); }
|
175
|
+
size_t write(int n) { return write((uint8_t)n); }
|
176
|
+
|
177
|
+
// https://www.arduino.cc/en/Reference/WireAvailable
|
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.
|
181
|
+
int available(void) {
|
182
|
+
assert(in);
|
183
|
+
return in->misoSize;
|
184
|
+
}
|
185
|
+
|
186
|
+
// https://www.arduino.cc/en/Reference/WireRead
|
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
|
196
|
+
}
|
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
|
203
|
+
}
|
204
|
+
|
205
|
+
// part of the Stream API
|
206
|
+
void flush(void) {
|
207
|
+
// NOTE: commented out in the megaavr repository
|
208
|
+
// data already at the (mock) destination
|
209
|
+
}
|
210
|
+
|
211
|
+
// https://www.arduino.cc/en/Reference/WireOnReceive
|
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); }
|
216
|
+
|
217
|
+
// https://www.arduino.cc/en/Reference/WireOnRequest
|
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); }
|
222
|
+
|
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
|
+
};
|
233
|
+
|
234
|
+
extern TwoWire Wire;
|
data/cpp/arduino/avr/io.h
CHANGED
@@ -96,7 +96,16 @@
|
|
96
96
|
#ifndef _AVR_IO_H_
|
97
97
|
#define _AVR_IO_H_
|
98
98
|
|
99
|
-
#
|
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"
|
data/cpp/arduino/avr/pgmspace.h
CHANGED
@@ -14,8 +14,10 @@ out = externs.map {|l| l.split("(")[0].split(" ")[-1].gsub("*", "") }.uniq
|
|
14
14
|
out.each { |l| puts d(l) }
|
15
15
|
*/
|
16
16
|
|
17
|
-
#include <avr/io.h>
|
18
17
|
#include <string.h>
|
18
|
+
#include <stdio.h>
|
19
|
+
#include <stdint.h>
|
20
|
+
#include <stdarg.h>
|
19
21
|
|
20
22
|
#define PROGMEM
|
21
23
|
|
@@ -27,6 +29,11 @@ out.each { |l| puts d(l) }
|
|
27
29
|
#define PGM_VOID_P const void *
|
28
30
|
#endif
|
29
31
|
|
32
|
+
// These are normally 32-bit, but here use (u)intptr_t to ensure a pointer can
|
33
|
+
// always be safely cast to these types.
|
34
|
+
typedef intptr_t int_farptr_t;
|
35
|
+
typedef uintptr_t uint_farptr_t;
|
36
|
+
|
30
37
|
// everything's a no-op
|
31
38
|
#define PSTR(s) ((const char *)(s))
|
32
39
|
|
@@ -34,13 +41,13 @@ out.each { |l| puts d(l) }
|
|
34
41
|
#define pgm_read_word_near(address_short) (* (const uint16_t *) (address_short) )
|
35
42
|
#define pgm_read_dword_near(address_short) (* (const uint32_t *) (address_short) )
|
36
43
|
#define pgm_read_float_near(address_short) (* (const float *) (address_short) )
|
37
|
-
#define pgm_read_ptr_near(address_short) (* (const void
|
44
|
+
#define pgm_read_ptr_near(address_short) (* (const void **) (address_short) )
|
38
45
|
|
39
46
|
#define pgm_read_byte_far(address_long) (* (const uint8_t *) (address_long) )
|
40
47
|
#define pgm_read_word_far(address_long) (* (const uint16_t *) (address_long) )
|
41
48
|
#define pgm_read_dword_far(address_long) (* (const uint32_t *) (address_long) )
|
42
49
|
#define pgm_read_float_far(address_long) (* (const float *) (address_long) )
|
43
|
-
#define pgm_read_ptr_far(address_long) (* (const void
|
50
|
+
#define pgm_read_ptr_far(address_long) (* (const void **) (address_long) )
|
44
51
|
|
45
52
|
#define pgm_read_byte(address_short) pgm_read_byte_near(address_short)
|
46
53
|
#define pgm_read_word(address_short) pgm_read_word_near(address_short)
|
@@ -50,46 +57,69 @@ out.each { |l| puts d(l) }
|
|
50
57
|
|
51
58
|
#define pgm_get_far_address(var) ( (uint_farptr_t) (&(var)) )
|
52
59
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
60
|
+
inline const void * memchr_P(const void *s, int val, size_t len) { return memchr(s, val, len); }
|
61
|
+
inline int memcmp_P(const void *s1, const void *s2, size_t len) { return memcmp(s1, s2, len); }
|
62
|
+
inline void *memcpy_P(void *dest, const void *src, size_t n) { return memcpy(dest, src, n); }
|
63
|
+
inline char *strcat_P(char *dest, const char *src) { return strcat(dest, src); }
|
64
|
+
inline const char *strchr_P(const char *s, int val) { return strchr(s, val); }
|
65
|
+
inline int strcmp_P(const char *s1, const char *s2) { return strcmp(s1, s2); }
|
66
|
+
inline char *strcpy_P(char *dest, const char *src) { return strcpy(dest, src); }
|
67
|
+
inline size_t strcspn_P(const char *s, const char *reject) { return strcspn(s, reject); }
|
68
|
+
// strlcat and strlcpy are AVR-specific and not entirely trivial to reimplement using strncat it seems
|
69
|
+
//inline size_t strlcat_P(char *dst, const char *src, size_t siz) { return strlcat(dst, src, siz); }
|
70
|
+
//inline size_t strlcpy_P(char *dst, const char *src, size_t siz) { return strlcpy(dst, src, siz); }
|
71
|
+
//inline size_t strlcat_PF(char *dst, uint_farptr_t src, size_t n) { return strlcat(dst, (const char*)src, n); }
|
72
|
+
//inline size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz) { return strlcpy(dst, (const char*)src, siz); }
|
73
|
+
inline int strncmp_P(const char *s1, const char *s2, size_t n) { return strncmp(s1, s2, n); }
|
74
|
+
inline char *strncat_P(char *dest, const char *src, size_t len) { return strncat(dest, src, len); }
|
75
|
+
inline char *strncpy_P(char *dest, const char *src, size_t n) { return strncpy(dest, src, n); }
|
76
|
+
inline char *strpbrk_P(const char *s, const char *accept) { return (char*)strpbrk(s, accept); }
|
77
|
+
inline const char *strrchr_P(const char *s, int val) { return strrchr(s, val); }
|
78
|
+
inline size_t strspn_P(const char *s, const char *accept) { return strspn(s, accept); }
|
79
|
+
inline char *strstr_P(const char *s1, const char *s2) { return (char*)strstr(s1, s2); }
|
80
|
+
inline char *strtok_P(char *s, const char * delim) { return strtok(s, delim); }
|
81
|
+
inline size_t strlen_PF(uint_farptr_t s) { return strlen((char*)s); }
|
82
|
+
inline void *memcpy_PF(void *dest, uint_farptr_t src, size_t n) { return memcpy(dest, (const char*)src, n); }
|
83
|
+
inline char *strcpy_PF(char *dst, uint_farptr_t src) { return strcpy(dst, (const char*)src); }
|
84
|
+
inline char *strncpy_PF(char *dst, uint_farptr_t src, size_t n) { return strncpy(dst, (const char*)src, n); }
|
85
|
+
inline char *strcat_PF(char *dst, uint_farptr_t src) { return strcat(dst, (const char*)src); }
|
86
|
+
inline char *strncat_PF(char *dst, uint_farptr_t src, size_t n) { return strncat(dst, (const char*)src, n); }
|
87
|
+
inline int strcmp_PF(const char *s1, uint_farptr_t s2) { return strcmp(s1, (const char*)s2); }
|
88
|
+
inline int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) { return strncmp(s1, (const char*)s2, n); }
|
89
|
+
inline char *strstr_PF(const char *s1, uint_farptr_t s2) { return (char*)strstr(s1, (const char*)s2); }
|
90
|
+
inline int memcmp_PF(const void *s1, uint_farptr_t s2, size_t len) { return memcmp(s1, (const char*)s2, len); }
|
91
|
+
inline size_t strlen_P(const char *src) { return strlen(src); }
|
92
|
+
|
93
|
+
// TODO: These functions cannot be found on the CYGWIN test build for
|
94
|
+
// some reason, so disable them for now. Most of these are less common
|
95
|
+
// and/or GNU-specific addons anyway
|
96
|
+
//inline void *memccpy_P(void *dest, const void *src, int val, size_t len) { return memccpy(dest, src, val, len); }
|
97
|
+
//inline void *memmem_P(const void *s1, size_t len1, const void *s2, size_t len2) { return memmem(s1, len1, s2, len2); }
|
98
|
+
//inline const void *memrchr_P(const void *src, int val, size_t len) { return memrchr(src, val, len); }
|
99
|
+
//inline const char *strchrnul_P(const char *s, int c) { return strchrnul(s, c); }
|
100
|
+
//inline int strcasecmp_P(const char *s1, const char *s2) { return strcasecmp(s1, s2); }
|
101
|
+
//inline char *strcasestr_P(const char *s1, const char *s2) { return (char*)strcasestr(s1, s2); }
|
102
|
+
//inline int strncasecmp_P(const char *s1, const char *s2, size_t n) { return strncasecmp(s1, s2, n); }
|
103
|
+
//inline char *strsep_P(char **sp, const char *delim) { return strsep(sp, delim); }
|
104
|
+
//inline char *strtok_r_P(char *string, const char *delim, char **last) { return strtok_r(string, delim, last); }
|
105
|
+
//inline int strcasecmp_PF(const char *s1, uint_farptr_t s2) { return strcasecmp(s1, (const char*)s2); }
|
106
|
+
//inline int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) { return strncasecmp(s1, (const char*)s2, n); }
|
107
|
+
//inline size_t strnlen_P(uint_farptr_t s, size_t len) { return strnlen((char*)s, len); }
|
108
|
+
|
109
|
+
// These are normally defined by stdio.h on AVR, but we cannot override that
|
110
|
+
// include file (at least not without no longer being able to include the
|
111
|
+
// original as well), so just define these here. It seems likely that any
|
112
|
+
// sketch that uses these progmem-stdio functions will also include pgmspace.h
|
113
|
+
inline int vfprintf_P(FILE *stream, const char *__fmt, va_list __ap) { return vfprintf(stream, __fmt, __ap); }
|
114
|
+
inline int printf_P(const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vprintf(__fmt, args); va_end(args); }
|
115
|
+
inline int sprintf_P(char *s, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return sprintf(s, __fmt, args); va_end(args); }
|
116
|
+
inline int snprintf_P(char *s, size_t __n, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vsnprintf(s, __n, __fmt, args); va_end(args); }
|
117
|
+
inline int vsprintf_P(char *s, const char *__fmt, va_list ap) { return vsprintf(s, __fmt, ap); }
|
118
|
+
inline int vsnprintf_P(char *s, size_t __n, const char *__fmt, va_list ap) { return vsnprintf(s, __n, __fmt, ap); }
|
119
|
+
inline int fprintf_P(FILE *stream, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vfprintf(stream, __fmt, args); va_end(args); }
|
120
|
+
inline int fputs_P(const char *str, FILE *__stream) { return fputs(str, __stream); }
|
121
|
+
inline int puts_P(const char *str) { return puts(str); }
|
122
|
+
inline int vfscanf_P(FILE *stream, const char *__fmt, va_list __ap) { return vfscanf(stream, __fmt, __ap); }
|
123
|
+
inline int fscanf_P(FILE *stream, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vfscanf(stream, __fmt, args); va_end(args); }
|
124
|
+
inline int scanf_P(const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vscanf(__fmt, args); va_end(args); }
|
125
|
+
inline int sscanf_P(const char *buf, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vsscanf(buf, __fmt, args); va_end(args); }
|