Use the hardware PwmOut to pulsate an LED (or something else), with selectable active high/low, customisable intensity function, gamma correction, and number of brightness levels.
Diff: Pulsator.cpp
- Revision:
- 6:5eeb1acc1c50
- Parent:
- 5:26cc18306d95
- Child:
- 7:7abc04b4c474
diff -r 26cc18306d95 -r 5eeb1acc1c50 Pulsator.cpp --- a/Pulsator.cpp Fri Apr 24 21:26:05 2015 +0000 +++ b/Pulsator.cpp Sun Apr 26 01:39:38 2015 +0000 @@ -35,64 +35,62 @@ #include <mbed.h> #include <Pulsator.h> -Pulsator led(LED1, 2.0, false); +Pulsator led(LED1); int main(void) { - led = true; + led.period(2.0).gamma(1.8) = true; while(1) wait(1); } * \endcode * \see \a PwmOut, \a Ticker */ -void Pulsator::step(void) +void Pulsator::disable(void) { - // sinf(phase_2)^2 == (1 - cosf(phase)) / 2 - float s = sinf(phase_2); - float level = powf(s * s, gamma); - out = active_high ? level : 1.0 - level; - phase_2 += M_PI_2 / (float)(levels - 1); - if(phase_2 >= M_PI) - phase_2 -= M_PI; + _enable = false; + detach(); + out = _active_high ? 0.0 : 1.0; } void Pulsator::enable(void) { - _enable = true; out.period(1.0 / 1024.0); phase_2 = 0.0; step(); - ticker.attach(this, &Pulsator::step, 0.5 * period / (float)(levels - 1)); + _enable = true; + attach(this, &Pulsator::step, 0.5 * _period / (float)(_levels - 1)); } -void Pulsator::disable(void) +//! Bit of a hack to update _delay without re-attaching the handler. +void Pulsator::reload(void) { - _enable = false; - ticker.detach(); - out = active_high ? 0.0 : 1.0; + _delay = 1000000.0 * 0.5 * _period / (float)(_levels - 1); } -/*! Create a \a Pulsator object. - * \param pin Pin to pulsate. Note that some platforms can only - * drive certain pins with the hardware PWM. - * \param period Duration of each cycle, in seconds. - * \param active_high Should the output pin be active high (\a true), - * or active low (\a false)? - * \param gamma Gamma correction for the output LED. - * \param levels Number of distinct brightness levels: a minimum of 2. - */ -Pulsator::Pulsator(PinName pin, float period, bool active_high, float gamma, int levels) - : out(pin), period(period), active_high(active_high), gamma(gamma), levels(levels) +void Pulsator::step(void) { - disable(); + // sinf(phase_2)^2 == (1 - cosf(phase)) / 2 + float s = sinf(phase_2); + float level = powf(s * s, _gamma); + out = _active_high ? level : 1.0 - level; + phase_2 += M_PI_2 / (float)(_levels - 1); + if(phase_2 >= M_PI) + phase_2 -= M_PI; } -/*! Enable or disable the output. - * \param state Pulsate the output? - * \note Passing \a false deactivates the output completely, rather than - * keeping the LED brightness at the point where this is called. - * Conversely, \a true starts pulsating from the inactive state. - */ +//! Create a \a Pulsator attached to the specified \a pin. +//! \param pin Pin to pulsate. +//! \note Some platforms can only drive certain pins with the hardware PWM. +Pulsator::Pulsator(PinName pin) : out(pin) +{ + active_high(); disable(); gamma(); period(); levels(); +} + +//! Enable or disable the output. +/* \note Passing \a false deactivates the output completely, rather than + maintaining the LED brightness at the point when this is called. + Conversely, \a true starts pulsating from the inactive state. + Setting the curent state is a no-op. */ Pulsator& Pulsator::operator=(bool state) { if(state != _enable) @@ -100,7 +98,40 @@ return *this; } +//! Get the current state of the output. Pulsator::operator bool(void) { return _enable; } + +//! Should the output pin be active high (\a true), or active low (\a false)? +Pulsator& Pulsator::active_high(bool high) +{ + _active_high = high; + if(!_enable) + out = _active_high ? 0.0 : 1.0; + return *this; +} + +//! Set the gamma correction for the output LED. +Pulsator& Pulsator::gamma(float power) +{ + _gamma = power; + return *this; +} + +//! Set the number (>= 2) of distinct brightness levels. +Pulsator& Pulsator::levels(int number) +{ + _levels = number; + reload(); + return *this; +} + +//! Set the duration of each cycle, in seconds. +Pulsator& Pulsator::period(float seconds) +{ + _period = seconds; + reload(); + return *this; +}