Skip to content

Commit 9057371

Browse files
authored
Merge pull request #40 from bxparks/develop
merge v1.1.0 into master
2 parents f7c09fa + 26ac365 commit 9057371

File tree

12 files changed

+824
-53
lines changed

12 files changed

+824
-53
lines changed

CHANGELOG.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,36 @@
11
# Changelog
22

33
* Unreleased
4-
* 1.0 (2021-09-30)
4+
* 1.1.0 (2021-12-09)
5+
* Add optional `DEPS` variable containing header files that the `*.ino`
6+
depends on.
7+
* **Potential Breaking** Change `Print::println()` to print just a `\n`
8+
instead of `\r\n`.
9+
* This is more compatible on Unix where the line terminator is a single
10+
`\n`
11+
* This allows the text output of Arduino programs to be redirected to
12+
a file or piped to another Unix program with the correct line
13+
termination character.
14+
* This change may break some programs (usually unit tests) which print
15+
to a
16+
[PrintStr](https://github.com/bxparks/AceCommon/tree/develop/src/print_str)
17+
object (from my [AceCommon](https://github.com/bxparks/AceCommon)
18+
library), and then expect `\r\n` instead of `\n`.
19+
* Add `pgm_read_XXX_near()` and `pgm_read_XXX_far()` macros which
20+
simply delegate to the `pgm_read_XXX()` macros.
21+
* Add `clockCyclesPerMicrosecond()`, `clockCyclesToMicroseconds(a)`,
22+
and `microsecondsToClockCycles(a)` macros. Set a fake `F_CPU` to 16MHz
23+
on Unix machines.
24+
* Add `bitRead()`, `bitSet()`, `bitClear()`, `bitWrite()` macros. Add
25+
`bitToggle()` macro as well, which seems to be defined only on the
26+
Arduino AVR core.
27+
* Add `min()`, `max()`, `abs()`, etc. I don't normally use these Arduino
28+
macros in my libraries, but many other 3rd party libraries do. To compile
29+
those libraries under EpoxyDuino, we have to define them.
30+
* Add a minimal mock implementation of
31+
[FastLED](https://github.com/FastLED/FastLED) sufficient for my personal
32+
project.
33+
* 1.0.0 (2021-09-30)
534
* Add `epoxy_argc` and `epoxy_argv` as extern global variables which
635
are set to the `argc` and `argv` parameters passed into the global
736
`main()`.

EpoxyDuino.mk

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
# EpoxyDuino.mk.)
3030
# * OBJS
3131
# * Additional object (*.o) files needed by the binary
32+
# * DEPS
33+
# * Additional source (*.h, *.cpp) files required by the final executable.
34+
# * These are additional source files which should trigger a recompile
35+
# when they are modified.
3236
# * GENERATED
3337
# * A list of files which are generated by a script, and therefore can be
3438
# deleted by 'make clean'
@@ -177,7 +181,7 @@ $(APP_NAME).out: $(OBJS)
177181
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
178182

179183
# We need to add a rule to treat .ino file as just a normal .cpp.
180-
$(APP_NAME).o: $(APP_NAME).ino
184+
$(APP_NAME).o: $(APP_NAME).ino $(DEPS)
181185
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -x c++ -c $<
182186

183187
%.o: %.cpp

README.md

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,21 @@ produces an executable with a `.out` extension, for example, `SampleTest.out`.
2323
The `Serial` port object sends the output to the `STDOUT` and reads from the
2424
`STDIN` of the Unix host environment. Most other hardware dependent
2525
features (e.g. I2C, SPI, GPIO) are stubbed out (defined but don't do anything)
26-
to allow the Arduino programs to compile. This may be sufficient for a CI
27-
pipeline. For actual application development, I have started to build a set of
26+
to allow the Arduino programs to compile. Mock versions of various libraries are
27+
also provided:
28+
29+
* `<Wire.h>`: mock I2C library
30+
* `<SPI.h>`: mock SPI library
31+
* [EpoxyMockDigitalWriteFast](libraries/EpoxyMockDigitalWriteFast): mock
32+
version of the `digitalWriteFast` libraries
33+
* [EpoxyMockTimerOne](libraries/EpoxyMockTimerOne): mock version of the
34+
TimerOne (https://github.com/PaulStoffregen/TimerOne) library
35+
* [EpoxyMockFastLED](libraries/EpoxyMockFastLED/): mock version of the
36+
FastLED (https://github.com/FastLED/FastLED) library
37+
38+
These mock libraries may be sufficient for a CI pipeline.
39+
40+
For actual application development, I have started to build a set of
2841
libraries within EpoxyDuino which emulate the versions that run the actual
2942
hardware:
3043

@@ -55,7 +68,7 @@ The disadvantages are:
5568
environments (e.g. 16-bit `int` versus 32-bit `int`, or 32-bit `long` versus
5669
64-bit `long`).
5770

58-
**Version**: 1.0 (2021-09-30)
71+
**Version**: 1.1.0 (2021-12-09)
5972

6073
**Changelog**: See [CHANGELOG.md](CHANGELOG.md)
6174

@@ -74,6 +87,7 @@ The disadvantages are:
7487
* [Alternate C++ Compiler](#AlternateCompiler)
7588
* [Generated Source Code](#GeneratedSourceCode)
7689
* [Additional Clean Up](#AdditionalCleanUp)
90+
* [Additional Dependencies](#AdditionalDependencies)
7791
* [Alternate Arduino Core](#AlternateArduinoCore)
7892
* [PlatformIO](#PlatformIO)
7993
* [Command Line Flags and Arguments](#CommandLineFlagsAndArguments)
@@ -488,6 +502,19 @@ more_clean:
488502
rm -f epoxyeepromdata
489503
```
490504

505+
<a name="AdditionalDependencies"></a>
506+
### Additional Dependencies
507+
508+
Sometimes the `*.ino` file depend on additional header files within the same
509+
directory. When these header files are modified, the `*.ino` file must be
510+
recompiled. These additional header files can be listed in the `DEPS` variable:
511+
512+
```
513+
DEPS := header1.h header2.h
514+
...
515+
include {path/to/EpoxyDuino.mk}
516+
```
517+
491518
<a name="AlternateArduinoCore"></a>
492519
### Alternate Arduino Core
493520

@@ -606,7 +633,8 @@ A more advanced example can be seen in
606633
<a name="ArduinoFunctions"></a>
607634
### Arduino Functions
608635

609-
The following functions and features of the Arduino framework are implemented:
636+
The following is an incomplete list of Arduino functions and features
637+
which are implemented:
610638

611639
* `Arduino.h`
612640
* `setup()`, `loop()`
@@ -615,6 +643,12 @@ The following functions and features of the Arduino framework are implemented:
615643
* `digitalWrite()`, `digitalRead()`, `pinMode()` (empty stubs)
616644
* `analogRead()`, `analogWrite()` (empty stubs)
617645
* `pulseIn()`, `pulseInLong()`, `shiftIn()`, `shiftOut()` (empty stubs)
646+
* `min()`, `max()`, `abs()`, `round()`, etc
647+
* `bit()`, `bitRead()`, `bitSet()`, `bitClear()`, `bitWrite()`
648+
* `random()`, `randomSeed()`, `map()`
649+
* `makeWord()`
650+
* `F_CPU`, `clockCyclesPerMicrosecond(), `clockCyclesToMicroseconds(),
651+
`microsecondsToClockCycles()`
618652
* `HIGH`, `LOW`, `INPUT`, `OUTPUT`, `INPUT_PULLUP`
619653
* I2C and SPI pins: `SS`, `MOSI`, `MISO`, `SCK`, `SDA`, `SCL`
620654
* typedefs: `boolean`, `byte`, `word`
@@ -644,14 +678,13 @@ The following functions and features of the Arduino framework are implemented:
644678
* `Wire.h` (stub implementation)
645679
* `SPI.h` (stub implementation)
646680

647-
See
648-
[Arduino.h](https://github.com/bxparks/EpoxyDuino/blob/develop/cores/epoxy/Arduino.h)
681+
See [Arduino.h](cores/epoxy/Arduino.h)
649682
for the latest list. Most of the header files included by this `Arduino.h`
650683
file were copied and modified from the [arduino:avr
651684
core](https://github.com/arduino/ArduinoCore-avr/tree/master/cores/arduino),
652-
versions 1.8.2 (if I recall) or 1.8.3. A number of tweaks have been made to
653-
support slight variations in the API of other platforms, particularly the
654-
ESP8266 and ESP32 cores.
685+
v1.8.2 or v1.8.3. A number of tweaks have been made to support slight variations
686+
in the API of other platforms, particularly the ESP8266 v2.7.4 and ESP32 v1.0.6
687+
cores.
655688

656689
The `Print.printf()` function is an extension to the `Print` class that is
657690
provided by many Arduino-compatible microcontrollers (but not the AVR
@@ -729,7 +762,7 @@ These 3 types are described in more detail below.
729762
### Inherently Compatible Libraries
730763

731764
Almost all libraries that I write will be inherently compatible with EpoxyDuino
732-
because EpoxyDuino is what I use to my libraries.
765+
because EpoxyDuino is what I use to develop and test my libraries.
733766

734767
* AUnit (https://github.com/bxparks/AUnit)
735768
* AceButton (https://github.com/bxparks/AceButton)
@@ -802,6 +835,8 @@ intended. This limitation may be sufficient for Continous Integration purposes.
802835
* [EpoxyMockTimerOne](libraries/EpoxyMockTimerOne)
803836
* A simple mock of the TimerOne (https://github.com/PaulStoffregen/TimerOne)
804837
library.
838+
* [EpoxyMockFastLED](libraries/EpoxyMockFastLED/)
839+
* Mock version of the FastLED (https://github.com/FastLED/FastLED) library.
805840
* EspMock (https://github.com/hsaturn/EspMock)
806841
* This is a separate project that provides various mocks for functions and
807842
libraries included with the ESP8266 and the ESP32 processors.
@@ -811,7 +846,7 @@ intended. This limitation may be sufficient for Continous Integration purposes.
811846
<a name="SystemRequirements"></a>
812847
## System Requirements
813848

814-
This library has been tested on:
849+
This library has Tier 1 support on:
815850

816851
* Ubuntu 18.04
817852
* g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
@@ -822,6 +857,9 @@ This library has been tested on:
822857
* g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0
823858
* clang++ version 10.0.0-4ubuntu1
824859
* GNU Make 4.2.1
860+
861+
The following environments are Tier 2 because I do not test them often enough:
862+
825863
* Raspbian GNU/Linux 10 (buster)
826864
* On Raspberry Pi Model 3B
827865
* g++ (Raspbian 8.3.0-6+rpi1) 8.3.0
@@ -853,14 +891,14 @@ None that I am aware of.
853891
<a name="FeedbackAndSupport"></a>
854892
## Feedback and Support
855893

856-
If you have any questions, comments and other support questions about how to
857-
use this library, please use the
858-
[GitHub Discussions](https://github.com/bxparks/EpoxyDuino/discussions)
859-
for this project. If you have bug reports or feature requests, please file a
860-
ticket in [GitHub Issues](https://github.com/bxparks/EpoxyDuino/issues).
861-
I'd love to hear about how this software and its documentation can be improved.
862-
I can't promise that I will incorporate everything, but I will give your ideas
863-
serious consideration.
894+
If you have any questions, comments, or feature requests for this library,
895+
please use the [GitHub
896+
Discussions](https://github.com/bxparks/EpoxyDuino/discussions) for this
897+
project. If you have bug reports, please file a ticket in [GitHub
898+
Issues](https://github.com/bxparks/EpoxyDuino/issues). Feature requests should
899+
go into Discussions first because they often have alternative solutions which
900+
are useful to remain visible, instead of disappearing from the default view of
901+
the Issue tracker after the ticket is closed.
864902

865903
Please refrain from emailing me directly unless the content is sensitive. The
866904
problem with email is that I cannot reference the email conversation when other
@@ -875,5 +913,5 @@ people ask similar questions later.
875913
* Add `delayMicroSeconds()`, `WCharacter.h`, and stub implementations of
876914
`IPAddress.h`, `SPI.h`, by Erik Tideman (@ramboerik), see
877915
[PR #18](https://github.com/bxparks/EpoxyDuino/pull/18).
878-
* Add `memcpy_P()` and `vsnprintf_P()` by @pmp-p,
916+
* Add `memcpy_P()` and `vsnprintf_P()` by @pmp-p,
879917
[PR #28](https://github.com/bxparks/EpoxyDuino/pull/28).

cores/epoxy/Arduino.h

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
#define EPOXY_DUINO_EPOXY_ARDUINO_H
1515

1616
// xx.yy.zz => xxyyzz (without leading 0)
17-
#define EPOXY_DUINO_VERSION 10000
18-
#define EPOXY_DUINO_VERSION_STRING "1.0.0"
17+
#define EPOXY_DUINO_VERSION 10100
18+
#define EPOXY_DUINO_VERSION_STRING "1.1.0"
1919

20+
#include <algorithm> // min(), max()
21+
#include <cmath> // abs()
2022
#include <stdlib.h>
2123
#include <stdint.h>
2224
#include <stdbool.h>
@@ -144,10 +146,36 @@
144146
#define NOT_AN_INTERRUPT -1
145147
#define NOT_ON_TIMER 0
146148

149+
// Arduino defines min(), max(), abs(), and round() using c-preprocessor macros
150+
// in the global namespace. But this breaks the EpoxyFS library, which depends
151+
// on 3rd party Unix libraries, which in turn assume that these are functions
152+
// that can be overloaded. For EpoxyDuino, instead of macros, let's use the
153+
// versions defined by <algorithm> and <cmath> in the std:: namespace and lift
154+
// them into the global namespace.
155+
//
156+
// #define min(a,b) ((a)<(b)?(a):(b))
157+
// #define max(a,b) ((a)>(b)?(a):(b))
158+
// #define abs(x) ((x)>0?(x):-(x))
159+
// #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
160+
using std::min;
161+
using std::max;
162+
using std::abs;
163+
using std::round;
164+
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
165+
#define radians(deg) ((deg)*DEG_TO_RAD)
166+
#define degrees(rad) ((rad)*RAD_TO_DEG)
167+
#define sq(x) ((x)*(x))
168+
147169
// Stub implementations
148170
#define interrupts()
149171
#define noInterrupts()
150172

173+
// Fake the CPU clock to 16MHz on Linxu or MacOS.
174+
#define F_CPU 16000000
175+
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
176+
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
177+
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
178+
151179
#define bit(b) (1UL << (b))
152180
#if defined(EPOXY_CORE_ESP8266)
153181
#define _BV(b) (1UL << (b))
@@ -156,6 +184,13 @@
156184
#define lowByte(w) ((uint8_t) ((w) & 0xff))
157185
#define highByte(w) ((uint8_t) ((w) >> 8))
158186

187+
// bitToggle() is defined only on Arduino AVR as far as I can tell.
188+
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
189+
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
190+
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
191+
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
192+
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
193+
159194
extern "C" {
160195

161196
typedef bool boolean;

cores/epoxy/Print.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ size_t Print::print(const Printable& x)
129129

130130
size_t Print::println(void)
131131
{
132-
return write("\r\n");
132+
return write('\n');
133133
}
134134

135135
size_t Print::println(const String &s)

cores/epoxy/main.cpp

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,14 @@ static void disableRawMode() {
4545
if (inRawMode) {
4646
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1) {
4747
inRawMode = false; // prevent exit(1) from being called twice
48-
die("disableRawMode(): tcsetattr() failure");
48+
perror("disableRawMode(): tcsetattr() failure");
4949
}
5050
}
5151

5252
if (inNonBlockingMode) {
5353
if (fcntl(STDIN_FILENO, F_SETFL, orig_stdin_flags) == -1) {
54-
die("enableRawMode(): fcntl() failure");
54+
inNonBlockingMode = false; // prevent exit(1) from being called twice
55+
perror("enableRawMode(): fcntl() failure");
5556
}
5657
}
5758
}
@@ -105,28 +106,6 @@ static void enableRawMode() {
105106
inNonBlockingMode = true;
106107
}
107108

108-
static void handleControlC(int /*sig*/) {
109-
if (inRawMode) {
110-
// If this returns an error, don't call die() because it will call exit(),
111-
// which may call this again, causing an infinite recursion.
112-
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1) {
113-
perror("handleControlC(): tcsetattr() failure");
114-
}
115-
inRawMode = false;
116-
}
117-
118-
if (inNonBlockingMode) {
119-
// If this returns an error, don't call die() because it will call exit(),
120-
// which may call this again, causing an infinite recursion.
121-
if (fcntl(STDIN_FILENO, F_SETFL, orig_stdin_flags) == -1) {
122-
perror("handleControlC(): fcntl() failure");
123-
}
124-
inNonBlockingMode = false;
125-
}
126-
127-
exit(1);
128-
}
129-
130109
// -----------------------------------------------------------------------
131110
// Main loop. User code will provide setup() and loop().
132111
// -----------------------------------------------------------------------
@@ -141,7 +120,6 @@ int unixhostduino_main(int argc, char** argv) {
141120
epoxy_argc = argc;
142121
epoxy_argv = argv;
143122

144-
signal(SIGINT, handleControlC);
145123
atexit(disableRawMode);
146124
enableRawMode();
147125

cores/epoxy/pgmspace.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@
2727
#define pgm_read_float(p) (* (const float*) (p))
2828
#define pgm_read_ptr(p) (* (const void* const*) (p))
2929

30+
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
31+
#define pgm_read_word_near(addr) pgm_read_word(addr)
32+
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
33+
#define pgm_read_float_near(addr) pgm_read_float(addr)
34+
#define pgm_read_ptr_near(addr) pgm_read_ptr(addr)
35+
36+
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
37+
#define pgm_read_word_far(addr) pgm_read_word(addr)
38+
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
39+
#define pgm_read_float_far(addr) pgm_read_float(addr)
40+
#define pgm_read_ptr_far(addr) pgm_read_ptr(addr)
41+
3042
#define strlen_P strlen
3143
#define strcat_P strcat
3244
#define strcpy_P strcpy
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* MIT License
3+
* Copyright (c) 2013 FastLED
4+
* Copyright (c) 2021 Brian T. Park
5+
*/
6+
7+
#include "FastLED.h"
8+
9+
CFastLED FastLED;
10+
11+
const TProgmemRGBPalette16 PartyColors_p = {
12+
0x5500AB, 0x84007C, 0xB5004B, 0xE5001B,
13+
0xE81700, 0xB84700, 0xAB7700, 0xABAB00,
14+
0xAB5500, 0xDD2200, 0xF2000E, 0xC2003E,
15+
0x8F0071, 0x5F00A1, 0x2F00D0, 0x0007F9
16+
};

0 commit comments

Comments
 (0)