Skip to content

Commit

Permalink
Merge pull request #40 from bxparks/develop
Browse files Browse the repository at this point in the history
merge v1.1.0 into master
  • Loading branch information
bxparks authored Dec 9, 2021
2 parents f7c09fa + 26ac365 commit 9057371
Show file tree
Hide file tree
Showing 12 changed files with 824 additions and 53 deletions.
31 changes: 30 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
# Changelog

* Unreleased
* 1.0 (2021-09-30)
* 1.1.0 (2021-12-09)
* Add optional `DEPS` variable containing header files that the `*.ino`
depends on.
* **Potential Breaking** Change `Print::println()` to print just a `\n`
instead of `\r\n`.
* This is more compatible on Unix where the line terminator is a single
`\n`
* This allows the text output of Arduino programs to be redirected to
a file or piped to another Unix program with the correct line
termination character.
* This change may break some programs (usually unit tests) which print
to a
[PrintStr](https://github.com/bxparks/AceCommon/tree/develop/src/print_str)
object (from my [AceCommon](https://github.com/bxparks/AceCommon)
library), and then expect `\r\n` instead of `\n`.
* Add `pgm_read_XXX_near()` and `pgm_read_XXX_far()` macros which
simply delegate to the `pgm_read_XXX()` macros.
* Add `clockCyclesPerMicrosecond()`, `clockCyclesToMicroseconds(a)`,
and `microsecondsToClockCycles(a)` macros. Set a fake `F_CPU` to 16MHz
on Unix machines.
* Add `bitRead()`, `bitSet()`, `bitClear()`, `bitWrite()` macros. Add
`bitToggle()` macro as well, which seems to be defined only on the
Arduino AVR core.
* Add `min()`, `max()`, `abs()`, etc. I don't normally use these Arduino
macros in my libraries, but many other 3rd party libraries do. To compile
those libraries under EpoxyDuino, we have to define them.
* Add a minimal mock implementation of
[FastLED](https://github.com/FastLED/FastLED) sufficient for my personal
project.
* 1.0.0 (2021-09-30)
* Add `epoxy_argc` and `epoxy_argv` as extern global variables which
are set to the `argc` and `argv` parameters passed into the global
`main()`.
Expand Down
6 changes: 5 additions & 1 deletion EpoxyDuino.mk
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
# EpoxyDuino.mk.)
# * OBJS
# * Additional object (*.o) files needed by the binary
# * DEPS
# * Additional source (*.h, *.cpp) files required by the final executable.
# * These are additional source files which should trigger a recompile
# when they are modified.
# * GENERATED
# * A list of files which are generated by a script, and therefore can be
# deleted by 'make clean'
Expand Down Expand Up @@ -177,7 +181,7 @@ $(APP_NAME).out: $(OBJS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)

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

%.o: %.cpp
Expand Down
78 changes: 58 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,21 @@ produces an executable with a `.out` extension, for example, `SampleTest.out`.
The `Serial` port object sends the output to the `STDOUT` and reads from the
`STDIN` of the Unix host environment. Most other hardware dependent
features (e.g. I2C, SPI, GPIO) are stubbed out (defined but don't do anything)
to allow the Arduino programs to compile. This may be sufficient for a CI
pipeline. For actual application development, I have started to build a set of
to allow the Arduino programs to compile. Mock versions of various libraries are
also provided:

* `<Wire.h>`: mock I2C library
* `<SPI.h>`: mock SPI library
* [EpoxyMockDigitalWriteFast](libraries/EpoxyMockDigitalWriteFast): mock
version of the `digitalWriteFast` libraries
* [EpoxyMockTimerOne](libraries/EpoxyMockTimerOne): mock version of the
TimerOne (https://github.com/PaulStoffregen/TimerOne) library
* [EpoxyMockFastLED](libraries/EpoxyMockFastLED/): mock version of the
FastLED (https://github.com/FastLED/FastLED) library

These mock libraries may be sufficient for a CI pipeline.

For actual application development, I have started to build a set of
libraries within EpoxyDuino which emulate the versions that run the actual
hardware:

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

**Version**: 1.0 (2021-09-30)
**Version**: 1.1.0 (2021-12-09)

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

Expand All @@ -74,6 +87,7 @@ The disadvantages are:
* [Alternate C++ Compiler](#AlternateCompiler)
* [Generated Source Code](#GeneratedSourceCode)
* [Additional Clean Up](#AdditionalCleanUp)
* [Additional Dependencies](#AdditionalDependencies)
* [Alternate Arduino Core](#AlternateArduinoCore)
* [PlatformIO](#PlatformIO)
* [Command Line Flags and Arguments](#CommandLineFlagsAndArguments)
Expand Down Expand Up @@ -488,6 +502,19 @@ more_clean:
rm -f epoxyeepromdata
```

<a name="AdditionalDependencies"></a>
### Additional Dependencies

Sometimes the `*.ino` file depend on additional header files within the same
directory. When these header files are modified, the `*.ino` file must be
recompiled. These additional header files can be listed in the `DEPS` variable:

```
DEPS := header1.h header2.h
...
include {path/to/EpoxyDuino.mk}
```

<a name="AlternateArduinoCore"></a>
### Alternate Arduino Core

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

The following functions and features of the Arduino framework are implemented:
The following is an incomplete list of Arduino functions and features
which are implemented:

* `Arduino.h`
* `setup()`, `loop()`
Expand All @@ -615,6 +643,12 @@ The following functions and features of the Arduino framework are implemented:
* `digitalWrite()`, `digitalRead()`, `pinMode()` (empty stubs)
* `analogRead()`, `analogWrite()` (empty stubs)
* `pulseIn()`, `pulseInLong()`, `shiftIn()`, `shiftOut()` (empty stubs)
* `min()`, `max()`, `abs()`, `round()`, etc
* `bit()`, `bitRead()`, `bitSet()`, `bitClear()`, `bitWrite()`
* `random()`, `randomSeed()`, `map()`
* `makeWord()`
* `F_CPU`, `clockCyclesPerMicrosecond(), `clockCyclesToMicroseconds(),
`microsecondsToClockCycles()`
* `HIGH`, `LOW`, `INPUT`, `OUTPUT`, `INPUT_PULLUP`
* I2C and SPI pins: `SS`, `MOSI`, `MISO`, `SCK`, `SDA`, `SCL`
* typedefs: `boolean`, `byte`, `word`
Expand Down Expand Up @@ -644,14 +678,13 @@ The following functions and features of the Arduino framework are implemented:
* `Wire.h` (stub implementation)
* `SPI.h` (stub implementation)

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

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

Almost all libraries that I write will be inherently compatible with EpoxyDuino
because EpoxyDuino is what I use to my libraries.
because EpoxyDuino is what I use to develop and test my libraries.

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

This library has been tested on:
This library has Tier 1 support on:

* Ubuntu 18.04
* g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Expand All @@ -822,6 +857,9 @@ This library has been tested on:
* g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0
* clang++ version 10.0.0-4ubuntu1
* GNU Make 4.2.1

The following environments are Tier 2 because I do not test them often enough:

* Raspbian GNU/Linux 10 (buster)
* On Raspberry Pi Model 3B
* g++ (Raspbian 8.3.0-6+rpi1) 8.3.0
Expand Down Expand Up @@ -853,14 +891,14 @@ None that I am aware of.
<a name="FeedbackAndSupport"></a>
## Feedback and Support

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

Please refrain from emailing me directly unless the content is sensitive. The
problem with email is that I cannot reference the email conversation when other
Expand All @@ -875,5 +913,5 @@ people ask similar questions later.
* Add `delayMicroSeconds()`, `WCharacter.h`, and stub implementations of
`IPAddress.h`, `SPI.h`, by Erik Tideman (@ramboerik), see
[PR #18](https://github.com/bxparks/EpoxyDuino/pull/18).
* Add `memcpy_P()` and `vsnprintf_P()` by @pmp-p,
* Add `memcpy_P()` and `vsnprintf_P()` by @pmp-p,
[PR #28](https://github.com/bxparks/EpoxyDuino/pull/28).
39 changes: 37 additions & 2 deletions cores/epoxy/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
#define EPOXY_DUINO_EPOXY_ARDUINO_H

// xx.yy.zz => xxyyzz (without leading 0)
#define EPOXY_DUINO_VERSION 10000
#define EPOXY_DUINO_VERSION_STRING "1.0.0"
#define EPOXY_DUINO_VERSION 10100
#define EPOXY_DUINO_VERSION_STRING "1.1.0"

#include <algorithm> // min(), max()
#include <cmath> // abs()
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
Expand Down Expand Up @@ -144,10 +146,36 @@
#define NOT_AN_INTERRUPT -1
#define NOT_ON_TIMER 0

// Arduino defines min(), max(), abs(), and round() using c-preprocessor macros
// in the global namespace. But this breaks the EpoxyFS library, which depends
// on 3rd party Unix libraries, which in turn assume that these are functions
// that can be overloaded. For EpoxyDuino, instead of macros, let's use the
// versions defined by <algorithm> and <cmath> in the std:: namespace and lift
// them into the global namespace.
//
// #define min(a,b) ((a)<(b)?(a):(b))
// #define max(a,b) ((a)>(b)?(a):(b))
// #define abs(x) ((x)>0?(x):-(x))
// #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
using std::min;
using std::max;
using std::abs;
using std::round;
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))

// Stub implementations
#define interrupts()
#define noInterrupts()

// Fake the CPU clock to 16MHz on Linxu or MacOS.
#define F_CPU 16000000
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )

#define bit(b) (1UL << (b))
#if defined(EPOXY_CORE_ESP8266)
#define _BV(b) (1UL << (b))
Expand All @@ -156,6 +184,13 @@
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))

// bitToggle() is defined only on Arduino AVR as far as I can tell.
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))

extern "C" {

typedef bool boolean;
Expand Down
2 changes: 1 addition & 1 deletion cores/epoxy/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ size_t Print::print(const Printable& x)

size_t Print::println(void)
{
return write("\r\n");
return write('\n');
}

size_t Print::println(const String &s)
Expand Down
28 changes: 3 additions & 25 deletions cores/epoxy/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@ static void disableRawMode() {
if (inRawMode) {
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1) {
inRawMode = false; // prevent exit(1) from being called twice
die("disableRawMode(): tcsetattr() failure");
perror("disableRawMode(): tcsetattr() failure");
}
}

if (inNonBlockingMode) {
if (fcntl(STDIN_FILENO, F_SETFL, orig_stdin_flags) == -1) {
die("enableRawMode(): fcntl() failure");
inNonBlockingMode = false; // prevent exit(1) from being called twice
perror("enableRawMode(): fcntl() failure");
}
}
}
Expand Down Expand Up @@ -105,28 +106,6 @@ static void enableRawMode() {
inNonBlockingMode = true;
}

static void handleControlC(int /*sig*/) {
if (inRawMode) {
// If this returns an error, don't call die() because it will call exit(),
// which may call this again, causing an infinite recursion.
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1) {
perror("handleControlC(): tcsetattr() failure");
}
inRawMode = false;
}

if (inNonBlockingMode) {
// If this returns an error, don't call die() because it will call exit(),
// which may call this again, causing an infinite recursion.
if (fcntl(STDIN_FILENO, F_SETFL, orig_stdin_flags) == -1) {
perror("handleControlC(): fcntl() failure");
}
inNonBlockingMode = false;
}

exit(1);
}

// -----------------------------------------------------------------------
// Main loop. User code will provide setup() and loop().
// -----------------------------------------------------------------------
Expand All @@ -141,7 +120,6 @@ int unixhostduino_main(int argc, char** argv) {
epoxy_argc = argc;
epoxy_argv = argv;

signal(SIGINT, handleControlC);
atexit(disableRawMode);
enableRawMode();

Expand Down
12 changes: 12 additions & 0 deletions cores/epoxy/pgmspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@
#define pgm_read_float(p) (* (const float*) (p))
#define pgm_read_ptr(p) (* (const void* const*) (p))

#define pgm_read_byte_near(addr) pgm_read_byte(addr)
#define pgm_read_word_near(addr) pgm_read_word(addr)
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
#define pgm_read_float_near(addr) pgm_read_float(addr)
#define pgm_read_ptr_near(addr) pgm_read_ptr(addr)

#define pgm_read_byte_far(addr) pgm_read_byte(addr)
#define pgm_read_word_far(addr) pgm_read_word(addr)
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
#define pgm_read_float_far(addr) pgm_read_float(addr)
#define pgm_read_ptr_far(addr) pgm_read_ptr(addr)

#define strlen_P strlen
#define strcat_P strcat
#define strcpy_P strcpy
Expand Down
16 changes: 16 additions & 0 deletions libraries/EpoxyMockFastLED/FastLED.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* MIT License
* Copyright (c) 2013 FastLED
* Copyright (c) 2021 Brian T. Park
*/

#include "FastLED.h"

CFastLED FastLED;

const TProgmemRGBPalette16 PartyColors_p = {
0x5500AB, 0x84007C, 0xB5004B, 0xE5001B,
0xE81700, 0xB84700, 0xAB7700, 0xABAB00,
0xAB5500, 0xDD2200, 0xF2000E, 0xC2003E,
0x8F0071, 0x5F00A1, 0x2F00D0, 0x0007F9
};
Loading

0 comments on commit 9057371

Please sign in to comment.