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:
- 8:ddedf56b2eb0
- Parent:
- 7:7abc04b4c474
- Child:
- 9:b40252f5fee7
diff -r 7abc04b4c474 -r ddedf56b2eb0 Pulsator.cpp --- a/Pulsator.cpp Sun Apr 26 01:43:31 2015 +0000 +++ b/Pulsator.cpp Mon Apr 27 11:15:08 2015 +0000 @@ -16,19 +16,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include <algorithm> #include <math.h> #include <mbed.h> - #include <Pulsator.h> -#ifndef M_PI -# define M_PI 3.14159265358979323846 -#endif - -#ifndef M_PI_2 -# define M_PI_2 1.57079632679489661923 -#endif - /*! \class Pulsator * \brief Pulsate an LED using hardware \a PwmOut and \a Ticker. * \code @@ -55,9 +47,9 @@ void Pulsator::enable(void) { out.period(1.0f / 1024.0f); - phase_2 = 0.0f; + phase = 0.0f; + _enable = true; step(); - _enable = true; attach(this, &Pulsator::step, 0.5f * _period / (float)(_levels - 1)); } @@ -69,13 +61,14 @@ void Pulsator::step(void) { - // sinf(phase_2)^2 == (1 - cosf(phase)) / 2 - float s = sinf(phase_2); - float level = powf(s * s, _gamma); + float x = _fun(phase); + if(x < 0.0f) x = 0.0f; + if(x > 1.0f) x = 1.0f; + float level = powf(x, _gamma); out = _active_high ? level : 1.0f - level; - phase_2 += M_PI_2 / (float)(_levels - 1); - if(phase_2 >= M_PI) - phase_2 -= M_PI; + phase += 0.5f / (float)(_levels - 1); + if(phase >= 1.0f) + phase -= 1.0f; } //! Create a \a Pulsator attached to the specified \a pin. @@ -83,7 +76,7 @@ //! \note Some platforms can only drive certain pins with the hardware PWM. Pulsator::Pulsator(PinName pin) : out(pin) { - active_high(); disable(); gamma(); period(); levels(); + active_high(); disable(); fun(); gamma(); period(); levels(); } //! Enable or disable the output. @@ -113,6 +106,20 @@ return *this; } +#define TAU 6.2831853f +static float sinusoidal(float phase) { return 0.5f - 0.5f * cosf(TAU * phase); } + +//! Set the intensity function. +/* \param fp Pointer to a function returning an intensity + in the range [0,1]. Values outside will be clamped. */ +//! \param phase Input to \a fp, in the range [0, 1). +//! \note Pass \a NULL for the default sinusoidal function. +Pulsator& Pulsator::fun(float (*fp)(float phase)) +{ + _fun = fp ? fp : &sinusoidal; + return *this; +} + //! Set the gamma correction for the output LED. Pulsator& Pulsator::gamma(float power) {