Engine

A control structure that acts like the conductor of an orchestra, managing an ensemble of units. It handles their initialization, updates, and timing, ensuring that all components remain synchronized.

By default, all units are automatically added to the primary engine which can be accessed using the global object Plaquette. By using secondary engines you can organize and optimize your code, allowing for multi-tasking, grouping units, switching between ensembles of units, and save power by running engines at lower frequency.

Usage

To create and use an engine, simply declare it:

Engine myEngine;

To assign units to a specific engine, add it as the last parameter at construction:

Wave wave(1.0, 0.2, myEngine); // Use myEngine instead of the default

Each engine provides its own time measurements:

float sec = myEngine.seconds();        // Time since engine started, in seconds
uint32_t ms = myEngine.milliSeconds(); // Time in milliseconds
uint64_t us = myEngine.microSeconds(); // Time in microseconds

You will need to call the engine’s begin() function at initialization, and then its step() function at a regular pace.

Sample Rate

The Engine step() function computes timings and peforms background update operations on units. It is possible to set a specific (target) sample rate using sampleRate(rate) to reduce computation load for operations that do not need to be performed as fast as possible.

The engine’s step() function returns:

  • true if the step has been fully performed

  • false if it is still waiting for the next “tick”

As an example, if one sets a 100 Hz sample rate on engine myEngine by calling myEngine.sampleRate(100), the myEngine.step() function should return true about 100 times per second and false otherwise.

To fully support custom sample rates and avoid performing unnecessary operations on units, the step() function should be used as a guard condition in the main stepping loop.

void begin() {
  myEngine.sampleRate(100); // Target sample rate: 100 Hz.
}

void loop() {
  if (!myEngine.step()) // Guard condition.
    return; // Exit the loop.

  // The operations below will be performed at ~100 Hz.
  if (button)
    wave >> led;
  ...
}

For more in-depth explanations and examples please read Synchronizing Groups of Units with Secondary Engines.

Example

This example demonstrates the use of a secondary engine on an Arduino Uno or Nano using timer2 interrupt.

#include <Plaquette.h>

Engine timerEngine; // The secondary timer engine.

Metronome serialMetro(1.0); // Metronome (primary engine).

Metronome toggleMetro(0.25, timerEngine); // Metronome (timer engine).
DigitalOut led(LED_BUILTIN, timerEngine); // Built-in LED (timer engine).

// Primary engine begin().
void begin() {
  timerEngine.begin(); // Begin timer engine.
  timerSetup();        // Initialize timer interrupt timer2.
}

// Primary engine step().
void step() {
  if (serialMetro)
    println("step");
}

// Timer2 interrupt: will be called at 1kHz frequency.
ISR(TIMER2_COMPA_vect) {
  timerEngine.step(); // Step engine.

  if (toggleMetro) // Toggle LED on metro bang.
    led.toggle();
}

// Timer2 setup for 1kHz on AVR.
void timerSetup() {
  // Stop Timer2
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2  = 0;

  // Set compare match register for 1 kHz increments.
  // 16 MHz / (prescaler * 1000) - 1 = OCR2A
  // Try prescaler = 128 => OCR2A = (16e6 / (128 * 1000)) - 1 = ~124
  OCR2A = 124;

  TCCR2A |= (1 << WGM21); // CTC mode (Clear Timer on Compare Match).
  TCCR2B |= (1 << CS22) | (1 << CS20); // Set prescaler to 128.
  TIMSK2 |= (1 << OCIE2A); // Enable Timer2 compare interrupt.

  sei(); // Enable global interrupts.
}

Reference

class Engine

The main Plaquette static class containing all the units.

Public Functions

void preBegin(unsigned long baudrate = PLAQUETTE_SERIAL_BAUD_RATE)

Initializes all components (calls begin() on all of them).

void postBegin()

Performs additional tasks after the class to begin().

inline void preStep()

Updates all components (calls step() on all of them).

inline bool timeStep()

Performs additional tasks after the class to step().

Returns

true if the program should

inline void begin(unsigned long baudrate = PLAQUETTE_SERIAL_BAUD_RATE)

Function to be used within the PlaquetteLib context (needs to be called at top of setup() method).

inline bool step()

Function to be used within the PlaquetteLib context (needs to be called at top of loop() method).

inline void end()

Optional function to be used within the PlaquetteLib context.

No need to call it if the program is looping indefinitely. Call if the program stops at some point.

inline size_t nUnits()

Returns the current number of units.

float seconds(bool referenceTime = true) const

Returns time in seconds.

Optional parameter allows to ask for reference time (default) which will yield the same value through one iteration of step(), or “real” time which will return the current total running time.

Parameters

referenceTime – determines whether the function returns the reference time or the real time

Returns

the time in seconds

uint32_t milliSeconds(bool referenceTime = true) const

Returns time in milliseconds.

Optional parameter allows to ask for reference time (default) which will yield the same value through one iteration of step(), or “real” time which will return the current total running time.

Parameters

referenceTime – determines whether the function returns the reference time or the real time

Returns

the time in milliseconds

uint64_t microSeconds(bool referenceTime = true) const

Returns time in microseconds.

Optional parameter allows to ask for reference time (default) which will yield the same value through one iteration of step(), or “real” time which will return the current total running time.

Parameters

referenceTime – determines whether the function returns the reference time or the real time

Returns

the time in microseconds

inline unsigned long nSteps() const

Returns number of steps.

inline bool hasAutoSampleRate() const

Returns true iff the auto sample rate mode is enabled (default).

void autoSampleRate()

Enables auto sample rate mode (default).

void sampleRate(float sampleRate)

Sets sample rate to a fixed value, thus disabling auto sampling rate.

void samplePeriod(float samplePeriod)

Sets sample period to a fixed value, thus disabling auto sampling rate.

inline float sampleRate() const

Returns sample rate.

inline float samplePeriod() const

Returns sample period.

inline uint32_t deltaTimeMicroSeconds() const

Returns time between steps (in microseconds).

inline float deltaTimeSecondsTimesFixed32Max() const

Returns time between steps, expressed in fixed point propotion.

inline bool isPrimary() const

Returns true if this Engine is the main.

bool randomTrigger(float timeWindow)

Randomly triggers an event about once per time window, on average.

Call this function once in each step(). It will occasionally return true, with the frequency adjusted so that you get roughly one event for each timeWindow period, no matter how fast your loop is running.

Parameters

timeWindow – duration of the window (in seconds)

Returns

true when an event occurs during this sample

Public Static Functions

static Engine &primary()

Returns the main instance of Plaquette.

See Also