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.

Dependents:   RedButton

Committer:
huliyang
Date:
Fri Apr 24 07:58:22 2015 +0000
Revision:
4:55b287904199
Parent:
3:a789d816b3a2
Child:
5:26cc18306d95
Pulsator::step(): floating-point subtleties.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
huliyang 1:bcddb9898625 1 /* Copyright (c) 2015 Liyang HU, MIT License
huliyang 1:bcddb9898625 2 *
huliyang 1:bcddb9898625 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
huliyang 1:bcddb9898625 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
huliyang 1:bcddb9898625 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
huliyang 1:bcddb9898625 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
huliyang 1:bcddb9898625 7 * furnished to do so, subject to the following conditions:
huliyang 1:bcddb9898625 8 *
huliyang 1:bcddb9898625 9 * The above copyright notice and this permission notice shall be included in all copies or
huliyang 1:bcddb9898625 10 * substantial portions of the Software.
huliyang 1:bcddb9898625 11 *
huliyang 1:bcddb9898625 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
huliyang 1:bcddb9898625 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
huliyang 1:bcddb9898625 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
huliyang 1:bcddb9898625 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
huliyang 1:bcddb9898625 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
huliyang 1:bcddb9898625 17 */
huliyang 1:bcddb9898625 18
huliyang 0:dda7f6f55dc1 19 #include <math.h>
huliyang 0:dda7f6f55dc1 20 #include <mbed.h>
huliyang 0:dda7f6f55dc1 21
huliyang 0:dda7f6f55dc1 22 #include <Pulsator.h>
huliyang 0:dda7f6f55dc1 23
huliyang 0:dda7f6f55dc1 24 #ifndef M_PI
huliyang 0:dda7f6f55dc1 25 # define M_PI 3.14159265358979323846
huliyang 0:dda7f6f55dc1 26 #endif
huliyang 0:dda7f6f55dc1 27
huliyang 0:dda7f6f55dc1 28 #ifndef M_PI_2
huliyang 0:dda7f6f55dc1 29 # define M_PI_2 1.57079632679489661923
huliyang 0:dda7f6f55dc1 30 #endif
huliyang 0:dda7f6f55dc1 31
huliyang 1:bcddb9898625 32 /*! \class Pulsator
huliyang 1:bcddb9898625 33 * \brief Pulsate an LED using hardware \a PwmOut and \a Ticker.
huliyang 1:bcddb9898625 34 * \code
huliyang 1:bcddb9898625 35 #include <mbed.h>
huliyang 1:bcddb9898625 36 #include <Pulsator.h>
huliyang 1:bcddb9898625 37
huliyang 1:bcddb9898625 38 Pulsator led(LED1, 2.0, false);
huliyang 1:bcddb9898625 39
huliyang 1:bcddb9898625 40 int main(void) {
huliyang 1:bcddb9898625 41 led = true;
huliyang 1:bcddb9898625 42 while(1) wait(1);
huliyang 1:bcddb9898625 43 }
huliyang 1:bcddb9898625 44 * \endcode
huliyang 1:bcddb9898625 45 * \see \a PwmOut, \a Ticker
huliyang 1:bcddb9898625 46 */
huliyang 1:bcddb9898625 47
huliyang 0:dda7f6f55dc1 48 void Pulsator::step(void)
huliyang 0:dda7f6f55dc1 49 {
huliyang 0:dda7f6f55dc1 50 // sinf(phase_2)^2 == (1 - cosf(phase)) / 2
huliyang 0:dda7f6f55dc1 51 float s = sinf(phase_2);
huliyang 0:dda7f6f55dc1 52 float level = powf(s * s, gamma);
huliyang 0:dda7f6f55dc1 53 out = active_high ? level : 1.0 - level;
huliyang 0:dda7f6f55dc1 54 phase_2 += M_PI_2 / (float)(levels - 1);
huliyang 0:dda7f6f55dc1 55 if(phase_2 >= M_PI)
huliyang 4:55b287904199 56 phase_2 -= M_PI;
huliyang 0:dda7f6f55dc1 57 }
huliyang 0:dda7f6f55dc1 58
huliyang 0:dda7f6f55dc1 59 void Pulsator::enable(void)
huliyang 0:dda7f6f55dc1 60 {
huliyang 0:dda7f6f55dc1 61 out.period(1.0 / 1024.0);
huliyang 0:dda7f6f55dc1 62 phase_2 = 0.0;
huliyang 0:dda7f6f55dc1 63 step();
huliyang 3:a789d816b3a2 64 ticker.attach(this, &Pulsator::step, 0.5 * period / (float)(levels - 1));
huliyang 0:dda7f6f55dc1 65 }
huliyang 0:dda7f6f55dc1 66
huliyang 0:dda7f6f55dc1 67 void Pulsator::disable(void)
huliyang 0:dda7f6f55dc1 68 {
huliyang 0:dda7f6f55dc1 69 ticker.detach();
huliyang 0:dda7f6f55dc1 70 out = active_high ? 0.0 : 1.0;
huliyang 0:dda7f6f55dc1 71 }
huliyang 0:dda7f6f55dc1 72
huliyang 1:bcddb9898625 73 /*! Create a \a Pulsator object.
huliyang 2:e351afc2a3a8 74 * \param pin Pin to pulsate. Note that some platforms can only
huliyang 2:e351afc2a3a8 75 * drive certain pins with the hardware PWM.
huliyang 1:bcddb9898625 76 * \param period Duration of each cycle, in seconds.
huliyang 2:e351afc2a3a8 77 * \param active_high Should the output pin be active high (\a true),
huliyang 2:e351afc2a3a8 78 * or active low (\a false)?
huliyang 1:bcddb9898625 79 * \param gamma Gamma correction for the output LED.
huliyang 1:bcddb9898625 80 * \param levels Number of distinct brightness levels: a minimum of 2.
huliyang 1:bcddb9898625 81 */
huliyang 0:dda7f6f55dc1 82 Pulsator::Pulsator(PinName pin, float period, bool active_high, float gamma, int levels)
huliyang 0:dda7f6f55dc1 83 : out(pin), period(period), active_high(active_high), gamma(gamma), levels(levels)
huliyang 0:dda7f6f55dc1 84 {
huliyang 0:dda7f6f55dc1 85 disable();
huliyang 0:dda7f6f55dc1 86 }
huliyang 0:dda7f6f55dc1 87
huliyang 1:bcddb9898625 88 /*! Enable or disable the output.
huliyang 2:e351afc2a3a8 89 * \param state Pulsate the output?
huliyang 2:e351afc2a3a8 90 * \note Passing \a false deactivates the output completely, rather than
huliyang 2:e351afc2a3a8 91 * keeping the LED brightness at the point where this is called.
huliyang 2:e351afc2a3a8 92 * Conversely, \a true starts pulsating from the inactive state.
huliyang 1:bcddb9898625 93 */
huliyang 0:dda7f6f55dc1 94 Pulsator& Pulsator::operator=(bool state)
huliyang 0:dda7f6f55dc1 95 {
huliyang 0:dda7f6f55dc1 96 state ? enable() : disable();
huliyang 0:dda7f6f55dc1 97 return *this;
huliyang 0:dda7f6f55dc1 98 }