Skip to content

Commit

Permalink
Merge pull request #9 from bxparks/develop
Browse files Browse the repository at this point in the history
0.5.1 - Support SAMD21 boards
  • Loading branch information
bxparks authored Jul 24, 2019
2 parents 9b570ac + 885082a commit 8bc521e
Show file tree
Hide file tree
Showing 392 changed files with 2,900 additions and 1,449 deletions.
9 changes: 7 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# Changelog

* Unreleased
* 0.5 (2019-07-21, TB DB version 2019a, beta)
* 0.5.1 (2019-07-24, TZ DB version 2019a, beta)
* Add documentation about the ZoneManager into `USER_GUIDE.md`.
* Move `DateStrings` string pointers into PROGMEM, saving 42 bytes of RAM.
* Use `SERIAL_PORT_MONITOR` instead of `Serial` everywhere for portability
across different Arduino boards.
* Support SAMD21 boards except for EEPROM which SAMD21 does not support.
* 0.5 (2019-07-21, TZ DB version 2019a, beta)
* Remove over-engineered `SystemClockHeartbeatLoop` and
`SystemClockHeartbeatLoop` and replace with just a call to
`SystemClock::keepAlive()`.
Expand Down
89 changes: 54 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ be converted to another timezone. The library also provides a SystemClock that
can be synchronized from a more reliable external time source, such as an
[NTP](https://en.wikipedia.org/wiki/Network_Time_Protocol) server or a [DS3231
RTC](https://www.maximintegrated.com/en/products/analog/real-time-clocks/DS3231.html)
chip. This library is can be an alternative to the [Arduino
chip. This library can be an alternative to the [Arduino
Time](https://github.com/PaulStoffregen/Time) and [Arduino
Timezone](https://github.com/JChristensen/Timezone) libraries.

Expand Down Expand Up @@ -59,7 +59,7 @@ C++ namespaces:
* `ace_time::clock::NtpTimeProvider`
* `ace_time::clock::SystemClockSyncCoroutine`
* `ace_time::clock::SystemClockSyncLoop`
* internal helper classes (normally unused by app developers)
* internal helper classes (not normally used by app developers)
* `ace_time::basic::ZoneContext`
* `ace_time::basic::ZoneEra`
* `ace_time::basic::ZoneInfo`
Expand All @@ -83,28 +83,28 @@ individual (year, month, day, hour, minute, second) components, and the
The Epoch in AceTime is defined to be 2000-01-01T00:00:00Z, in contrast to the
Epoch in Unix which is 1970-01-01T00:00:00Z. Internally, the current time is
represented as "seconds from Epoch" stored as a 32-bit signed integer
(`acetime_t` aliased to `int32_t`). Internally, the smallest 32-bit signed
(`acetime_t` aliased to `int32_t`). The smallest 32-bit signed
integer (`-2^31`) is used to indicate an internal Error condition, so the
smallest valid `acetime_t` value is `-2^31+1`. The largest valid value is
`2^31-1`. Therefore, the range of dates that the `acetime_t` type can handle is
range of valid `acetime_t` value is `-2^31+1` to `2^31-1`.
Therefore, the range of dates that the `acetime_t` type can handle is
1931-12-13T20:45:53Z to 2068-01-19T03:14:07Z (inclusive). (In contrast, the
32-bit Unix `time_t` range is 1901-12-13T20:45:52Z to 2038-01-19T03:14:07Z).

The various date classes (`LocalDate`, `LocalDateTime`, `OffsetDateTime`,
`ZonedDateTime`) store the year component as a signed 8-bit integer offset from
the year 2000. The range of this integer is -128 to +127, but -128 is used to
indicate an internal Error condition, so the actual range is -127 to +127.
Therefore, these classes can represent dates from 1873-01-01T00:00:00 to
`ZonedDateTime`) store the year component internally as a signed 8-bit integer
offset from the year 2000. The range of this integer is -128 to +127, but -128
is used to indicate an internal Error condition, so the actual range is -127 to
+127. Therefore, these classes can represent dates from 1873-01-01T00:00:00 to
2127-12-31T23:59:59 (inclusive). Notice that these classes can represent all
dates that can be expressed by the `acetime_t` type, but the reverse is not
true. There are date objects that cannot be converted into a valid `acetime_t`
value. To be safe, users of this library should stay at least 1 day away from
the lower and upper limits of `acetime_t` (i.e. stay within the year 1932 to
2067, inclusive).
2067 inclusive).

The `ZonedDateTime` class works with the `TimeZone` class to provide access to
the TZ Database and allow conversions to other timezones using the
`ZonedDateTime::convertToTimeZone()` method.
The `ZonedDateTime` class works with the `TimeZone` class to implement the DST
transition rules defined by the TZ Database. It also allows conversions to other
timezones using the `ZonedDateTime::convertToTimeZone()` method.

The library provides 2 sets of zoneinfo files created from the IANA TZ Database:

Expand All @@ -117,20 +117,33 @@ The library provides 2 sets of zoneinfo files created from the IANA TZ Database:
the TZ Database (essentially the entire database) intended to be used with
the `ExtendedZoneProcessor` class.

These zoneinfo files have been validated to match the UTC offsets calculated
using the Python [pytz](https://pypi.org/project/pytz/) library from the year
2000 until 2037 (inclusive), and using the [Java 11
These zoneinfo files (and the `ZoneProcessor` classes which calculate the UTC
offsets and DST transitions) have been validated to match the UTC offsets
calculated using the Python [pytz](https://pypi.org/project/pytz/) library from
the year 2000 until 2037 (inclusive), and using the [Java 11
Time](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html)
library from year 2000 to 2049 (inclusive). Custom datasets with smaller or
larger range of years may be generated by developers using scripts provided in
this library (although this is not documented currently). The target application
may be compiled against the custom dataset instead of using `zonedb::` and
`zonedbx::` zone files provided in this library.

It is expected that an application using AceTime will use only a small subset of
these timezones at the same time (1 to 3 zones have been tested). The C++
compiler will include only the subset of zoneinfo files needed to support those
timezones, instead of compiling in the entire TZ database.
It is expected that most applications using AceTime will use only a small number
of timezones at the same time (1 to 3 zones have been extensively tested) and
that this set is known at compile-time. The C++ compiler will include only the
subset of zoneinfo files needed to support those timezones, instead of compiling
in the entire TZ Database. But on microcontrollers with enough memory, the
`ZoneManager` can be used to load the entire TZ Database into the app and
the `TimeZone` objects can be dynamically created as needed.

Each timezone in the TZ Database is identified by its fully qualified zone name
(e.g. `"America/Los_Angeles"`). On small microcontroller environments, these
strings can consume precious memory (e.g. 30 bytes for
`"America/Argentina/Buenos_Aires"`) and are not convenient to serialize over the
network or to save to EEPROM. Therefore, the AceTime library provides each
timezone with an alternative `zoneId` identifier of type `uint32_t` which is
guaranteed to be unique and stable. A `TimeZone` object can be saved as a
`zoneId` and then recreated using the `ZoneManager::createFromZoneId()` method.

The `ace_time::clock` classes collaborate together to implement the
SystemClock which can obtain its time from various sources, such as a DS3231 RTC
Expand All @@ -139,20 +152,22 @@ from accurate clock sources can be expensive, so the `SystemClock` uses the
built-in `millis()` function to provide fast access to a reasonably accurate
clock, but synchronizes to more accurate clocks periodically.

This library does not perform dynamic allocation of memory, in other words,
it does not call the `new` operator nor the `malloc()` function, and it does not
use the Arduino `String` class. Everything it needs is allocated statically at
initialization time.
This library does not perform dynamic allocation of memory so that it can be
used in small microcontroller environments. In other words, it does not call the
`new` operator nor the `malloc()` function, and it does not use the Arduino
`String` class. Everything it needs is allocated statically at initialization
time.

The zoneinfo files are stored in flash memory (using the `PROGMEM` compiler
directive) whenever possible so that they do not consume static RAM:
directive) if the microcontroller allows it (e.g. AVR, ESP8266) so that they do
not consume static RAM:

* 270 timezones supported by `BasicZoneProcessor`consume:
* 14 kB of flash on an 8-bit processor
* 21 kB of flash on a 32-bit processor
* 14 kB of flash on an 8-bit processor (AVR)
* 21 kB of flash on a 32-bit processor (ESP8266)
* 387 timezones supported by `ExtendedZoneProcessor` consume:
* 23 kB of flash on an 8-bit processor
* 37 kB of flash on a 32-bit processor
* 23 kB of flash on an 8-bit processor (AVR)
* 37 kB of flash on a 32-bit processor (ESP8266)

Normally a small application will use only a small number of timezones. The
AceTime library with one timezone using the `BasicZoneProcessor` and the
Expand Down Expand Up @@ -181,7 +196,7 @@ Conversion from an epochSeconds to date-time components including timezone
* 2.5 microseconds on an ESP32,
* 6 microseconds on a Teensy 3.2.

**Version**: 0.5 (2019-07-21, TZ DB version 2019a, beta)
**Version**: 0.5.1 (2019-07-24, TZ DB version 2019a, beta)

**Status**: Fully functional. Added `ZoneManager` for dynamic binding of
zoneName or zoneId to the TimeZone.
Expand Down Expand Up @@ -388,10 +403,12 @@ See the [AceTime User Guide](USER_GUIDE.md) for information on:
This library was developed and tested using:
* [Arduino IDE 1.8.9](https://www.arduino.cc/en/Main/Software)
* [Arduino AVR Core 1.6.23](https://github.com/arduino/ArduinoCore-avr)
* [SparkFun AVR Core 1.1.12](https://github.com/sparkfun/Arduino_Boards)
* [ESP8266 Arduino Core 2.5.2](https://github.com/esp8266/Arduino)
* [ESP32 Arduino Core 1.0.2](https://github.com/espressif/arduino-esp32)
* [Arduino AVR Boards 1.6.23](https://github.com/arduino/ArduinoCore-avr)
* [Arduino SAMD Boards 1.8.3](https://github.com/arduino/ArduinoCore-samd)
* [SparkFun AVR Boards 1.1.12](https://github.com/sparkfun/Arduino_Boards)
* [SparkFun SAMD Boards 1.6.2](https://github.com/sparkfun/Arduino_Boards)
* [ESP8266 Arduino 2.5.2](https://github.com/esp8266/Arduino)
* [ESP32 Arduino 1.0.2](https://github.com/espressif/arduino-esp32)
* [Teensydino 1.46](https://www.pjrc.com/teensy/td_download.html)
It should work with [PlatformIO](https://platformio.org/) but I have
Expand All @@ -404,12 +421,14 @@ library will work fine under MacOS and Windows, but I have not tested them.
### Hardware
The library is tested on the following hardware before each release:
The library is extensively tested on the following boards:
* Arduino Nano clone (16 MHz ATmega328P)
* SparkFun Pro Micro clone (16 MHz ATmega32U4)
* WeMos D1 Mini clone (ESP-12E module, 80 MHz ESP8266)
* ESP32 dev board (ESP-WROOM-32 module, 240 MHz dual core Tensilica LX6)
* SAMD21 M0 Mini (48 MHz ARM Cortex-M0+) (compatible with Arduino Zero) (See
notes in the [USER_GUIDE.md](USER_GUIDE.md) for some potential issues.)
I will occasionally test on the following hardware as a sanity check:
Expand Down
41 changes: 36 additions & 5 deletions USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

See the [README.md](README.md) for introductory background.

Version: 0.5 (2019-07-21, TZ DB version 2019a, beta)
Version: 0.5.1 (2019-07-24, TZ DB version 2019a, beta)

## Installation

Expand Down Expand Up @@ -1454,10 +1454,11 @@ static ExtendedZoneManager<2> zoneManager(kZoneRegistrySize, kZoneRegistry);
```

The `ACE_TIME_PROGMEM` macro is defined in
[flash.h](src/ace_time/common/flash.h) and indicates whether the ZoneInfo files
are stored in normal RAM or flash memory (i.e. `PROGMEM`). It must be used for
custom zoneRegistries because the `BasicZoneManager` and `ExtendedZoneManager`
expect to find them in static RAM or flash memory according to this macro.
[compat.h](src/ace_time/common/compat.h) and indicates whether the ZoneInfo
files are stored in normal RAM or flash memory (i.e. `PROGMEM`). It must be used
for custom zoneRegistries because the `BasicZoneManager` and
`ExtendedZoneManager` expect to find them in static RAM or flash memory
according to this macro.

See [CommandLineClock](examples/CommandLineClock/) for an example of how these
custom registries can be created and used.
Expand Down Expand Up @@ -2577,3 +2578,33 @@ did not think it would fit inside an Arduino controller.
is created with a `TimeZone` associated with `kZoneUS_Pacific`, the
`ZonedDateTime::printTo()` will print "[America/Los_Angeles]" not
"[US/Pacific]".
* Arduino Zero and SAMD21 Boards
* SAMD21 boards (which all identify themselves as `ARDUINO_SAMD_ZERO`) are
fully supported, but there are some tricky points.
* If you are using an original Arduino Zero and using the "Native USB Port",
you may encounter problems with nothing showing up on the Serial Monitor.
* The original Arduino Zero has [2 USB
ports](https://www.arduino.cc/en/Guide/ArduinoZero). The Programming
port is connected to `Serial` object and the Native port is connected
to `SerialUSB` object. You can select either the "Arduino/Genuino Zero
(Programming Port)" or the "Arduino/Genuino Zero (Native USB Port)" on
the Board Manager selector in the Arduino IDEA. Unfortunately, if you
select "(Native USB Port)", the `SERIAL_MONITOR_PORT` macro *should*
be defined to be `SerialUSB`, but it continues to point to `Serial`,
which means that nothing will show up on the Serial Monitor.
* You may be able to fix this by setting
`ACE_TIME_CLOBBER_SERIAL_PORT_MONITOR` to `1` in
`src/ace_time/common/compat.h`. (I do not test this option often, so
it may be broke.)
* If you are using a SAMD21 development or breakout board, or one of the
many clones called something like "Ardunio SAMD21 M0 Mini" (this is what I
have), I have found things working better using the SparkFun
Boards instead of the Arduino Zero board. Download "SparkFun SAMD Boards"
using the Board Manager by following the [SparkFun Boards
Installation](https://github.com/sparkfun/Arduino_Boards), then select the
board labeled "SparkFun SAMD Mini Breakout". These boards have only a
single USB connector, and the `SERIAL_PORT_MONITOR` will be properly
defined to be `SerialUSB`.
* The SAMD21 microcontroller does *not* provide any EEPROM. Therefore,
this feature is disabled in the apps under `examples` (e.g.
`CommandLineClock`, `OledClock`, and `WorldClock`) which use this feature.
2 changes: 1 addition & 1 deletion docs/doxygen.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ PROJECT_NAME = "AceTime"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = 0.5
PROJECT_NUMBER = 0.5.1

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
Loading

0 comments on commit 8bc521e

Please sign in to comment.