Introduction

featherlib is a set of tools for quickly building programs on the Adafruit Feather ecosystem without sacrificing readability and modularity. It’s the same sort of hardware abstraction layer (or HAL) that I find myself either copying over or reimplementing in new projects, so I decided to package it up as a PlatformIO library.

One of the examples that I use regularly is the program for setting the RTC in an Adalogger using the time from an Ultimate GPS wing:

// rtcgps is a small sketch that sets an Adalogger's RTC to the
// current GPS time. It uses a Feather M0, the Ultimate GPS
// Featherwing, and the Adalogger Featherwing.
#include <Arduino.h>
#include <RTClib.h>

#include <feather/feather.h>
#include <feather/scheduling.h>
#include <feather/wing/adalogger.h>
#include <feather/wing/gps.h>


#if defined(FEATHER_M0)
FeatherM0        board(INPUT, A1);
#elif defined(FEATHER_M4)
FeatherM4        board;
#else
#error Unknown board.
#endif


// The default GPS constructor uses Serial1 for the
// connection.
GPS              gps;

// NB: setting the Adalogger's CS pin to 0 disables the SD card,
// which isn't used in the sketch and therefore doesn't require an
// SD card to be inserted.
Adalogger        logger(0);


void
setup()
{
        // Start the serial port at 9600 baud but don't wait for a
        // serial connection to continue booting.
        board.setup(9600, false);

        // Registering wings allows them to be set up in one pass and
        // allows any update tasks to be started later on.
        registerWing(&gps);
        registerWing(&logger);

        if (!initialiseWings()) {
                // If a wing fails to initialise, a message will be
                // printed to serial.
                while (true) ;
        }

        // This starts a background thread that runs the update tasks
        // for the featherwings. For example, in this sketch, the GPS
        // needs to be updated in the background. Another scheduler
        // can be used that calls `runWings`, too.
        scheduleWingTasks();
}


void
loop()
{
        // rtcSet will be set to true when the GPS is used to set the
        // RTC.
        static bool        rtcSet = false;
        DateTime           dateTime;

        // when rtcSet is true, the program will stop.
        while (rtcSet) ;

        if (!gps.getDateTime(dateTime)) {
                return;
        }

        if (!logger.adjustRTC(dateTime)) {
                Serial.println("Failed to adjust the RTC.");
                return;
        }

        rtcSet = true;
        Serial.println("RTC is set; halting.");
}

I find this is relatively easy to read; organising the functionality under a wing is debatable (and arguably makes this not a true HAL) but it seems to be working out well for the projects I’ve been using it in.

Overhead

As a test, I’ve compiled a basic Arduino sketch for the Feather M0:

#include <Arduino.h>


void
setup()
{
        Serial.begin(9600);
        while (!Serial) ;
        Serial.println("boot OK");
}


void
loop()
{

}

Building this with PlatformIO shows the following sizes:

Building .pioenvs/adafruit_feather_m0/firmware.bin
Memory Usage -> http://bit.ly/pio-memory-usage
DATA:    [=         ]   8.0% (used 2620 bytes from 32768 bytes)
PROGRAM: [          ]   4.2% (used 10992 bytes from 262144 bytes)

and the equivalent using the featherlib library:

#include <Arduino.h>
#include <feather/feather.h>


FeatherM0        board;


void
setup()
{
        board.setup(9600, true);

        Serial.println("BOOT OK");
}


void
loop()
{

}

yields the following sizes:

Building .pioenvs/adafruit_feather_m0/firmware.bin
Memory Usage -> http://bit.ly/pio-memory-usage
DATA:    [=         ]   8.1% (used 2648 bytes from 32768 bytes)
PROGRAM: [=         ]   5.2% (used 13568 bytes from 262144 bytes)

The additional program space is taken up by the random number seeding. It’s worse in this case because a fair amount of additional setup is done, but once more peripherals are added, the tradeoff is generally useful to me.

As additional examples for the Feather M0:

Example Data (bytes) Program (bytes) Components (plus Feather)
calamity 3496 (10.7%) 24784 (9.5%) OLED
rtcgps 4844 (14.8%) 48576 (18.5%) Adalogger, GPS
loraspy 5216 (15.9%) 48336 (18.4%) Adalogger, OLED, RFM95, Trigger
lorabcn 3832 (11.7%) 35136 (13.8%) RFM95, Trigger