1 /*
2  * Copyright (c) 2016-2019, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*!*****************************************************************************
34  *  @file       LED.h
35  *
36  *  @brief      LED driver
37  *
38  *  The LED driver is provided for easy access to common LED functionality.
39  *  All functionality can be replicated using the GPIO.h and PWM.h APIs.
40  *
41  *  @anchor ti_drivers_LED_Synopsis
42  *  # Synopsis #
43  *
44  *  @code
45  *  #include <ti/drivers/apps/LED.h>
46  *
47  *  LED_Handle handle;
48  *  LED_Params ledParams;
49  *
50  *  // Assume our LED is configured to be a PWM LED
51  *  LED_Params_init(&ledParams);
52  *  ledHandle = LED_open(CONFIG_LED0, &ledParams);
53  *
54  *  // Turn on, set brightness, and blink
55  *  LED_setOn(handle, 80);
56  *  LED_startBlinking(handle, 500, LED_BLINK_FOREVER);
57  *
58  *  LED_setOff(handle);
59  *  LED_close(handle);
60  *
61  *  @endcode
62  *
63  *  @anchor ti_drivers_LED_Examples
64  *  ## Examples #
65  *
66  *  * @ref ti_drivers_LED_Examples_config_array "Generic Configuration"
67  *  * @ref ti_drivers_LED_Examples_gpio_config "GPIO Configuration"
68  *  * @ref ti_drivers_LED_Examples_pwm_led "PWM Mode"
69  *
70  *  # Operation #
71  *  LED driver simplifies using an LED (may be GPIO or PWM controlled)
72  *  available on board and supports following operations -
73  *
74  *      1. To Turn ON/OFF
75  *      2. Blink with requested delay, stop when requested
76  *      3. Vary brightness (can only be done to a PWM controlled LED)
77  *      4. Toggle
78  *
79  *  There are also APIs to open and close an LED handle and also one to get
80  *  current state of a LED. User can request to set a LED into particular state
81  *  while opening itself i.e. to start blink as part of LED_open() call.
82  *
83  *  LED_init() must be called before using LED_open().
84  *
85  *  ## Defining #LED_Config, #LED_Object and #LED_HWAttrs #
86  *  To use the LED driver, an application has to indicate how many LEDs it
87  *  wants to operate, of what type (PWM or GPIO controlled), and which GPIO or
88  *  PWM to index for each LED.
89  *
90  *  Each structure must be defined by the application. The following
91  *  example is for an MSP432P401R platform in which four LEDs are available
92  *  on board.
93  *  The following declarations are placed in "ti_drivers_config.c".
94  *  How the gpio indices are defined is detailed in the next section.
95  *
96  *  ### LED_config structures #
97  *  @anchor ti_drivers_LED_Examples_config_array
98  *  "ti_drivers_config.c"
99  *  @code
100  *  #include <ti/drivers/apps/LED.h>
101  *
102  *  LED_Object LED_object[4];
103  *
104  *  const LED_HWAttrs LED_hwAttrs[4] = {
105  *          {
106  *              .index = CONFIG_LED1,
107  *              .type  = LED_GPIO_CONTROLLED
108  *          },
109  *          {
110  *              .index = CONFIG_LED_RED,
111  *              .type  = LED_GPIO_CONTROLLED
112  *          },
113  *          {
114  *              .index = CONFIG_NA_GPIO_PWMLED,
115  *              .type  = LED_PWM_CONTROLLED
116  *          },
117  *          {
118  *              .index = CONFIG_NA_GPIO_PWMLED,
119  *              .type  = LED_PWM_CONTROLLED
120  *          }
121  *  };
122  *
123  *  const LED_Config LED_config[] = {
124  *      {
125  *          .object =  &LED_object[0],
126  *          .hwAttrs = &LED_hwAttrs[0],
127  *      },
128  *      {
129  *          .object =  &LED_object[1],
130  *          .hwAttrs = &LED_hwAttrs[1],
131  *      },
132  *      {
133  *          .object =  &LED_object[2],
134  *          .hwAttrs = &LED_hwAttrs[2],
135  *      },
136  *      {
137  *          .object =  &LED_object[3],
138  *          .hwAttrs = &LED_hwAttrs[3],
139  *      }
140  *  };
141  *
142  *  uint32_t LED_count = 4;
143  *
144  *  @endcode
145  *
146  *  ##Setting up a GPIO controlled LED #
147  *  The following code snippet shows how a GPIO pin controlling an LED is
148  *  configured. The index the user provides to LED_open() corresponds to an
149  *  entry in the #GPIO_PinConfig array which will source the LED. It is the
150  *  user's responsibility to ensure that the pin is configured properly in the
151  *  pin array. Typically this means configuring the pin as an output.
152  *
153  *  ### GPIO controlled LED #
154  *  @anchor ti_drivers_LED_Examples_gpio_config
155  *
156  *  The following definitions are in
157  *  "ti_drivers_config.h" and "ti_drivers_config.c" respectively. This
158  *  example uses GPIO pins 1.0 and 2.0 which control LED1 and RED LED on
159  *  LaunchPad respectively. In addition to the structures shown below, the
160  *  other GPIO configuration data must exist. See @ref GPIO.h.
161  *
162  *  "ti_drivers_config.h"
163  *  @code
164  *  #define CONFIG_LED1         0
165  *  #define CONFIG_LED_RED      1
166  *  @endcode
167  *
168  *  "ti_drivers_config.c"
169  *  @code
170  *  #include <ti/drivers/GPIO.h>
171  *  GPIO_PinConfig gpioPinConfigs[] = {
172  *      GPIOMSP432_P1_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
173  *      GPIOMSP432_P2_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
174  *  }
175  *
176  *  @endcode
177  *
178  *  ## Configuring a PWM controlled LED #
179  *  The LED driver allows for an LED to be driven by the PWM driver. This allows
180  *  the user to set a brightness level in addition to the other LED features.
181  *  The user must specify in the #LED_HWAttrs of each #LED_Config entry which
182  *  #PWM_Config the LED instance is allowed to use. LED instances cannot share
183  *  a PWM instance.
184  *
185  *  The user may specify the period of the PWM signal in the #LED_Params passed
186  *  to LED_open(). This is not to be confused with #LED_Params.blinkPeriod
187  *  which specifies the default blink period.
188  *
189  *  ### Opening a PWM LED #
190  *  @anchor ti_drivers_LED_Examples_pwm_led
191  *
192  *  We will borrow the 3rd LED_config entry from the
193  *  @ref ti_drivers_LED_Examples_config_array
194  *
195  *  In "ti_drivers_config.h"
196  *  @code
197  *  #define CONFIG_LED0     0
198  *  @endcode
199  *
200  *  In application code:
201  *  @code
202  *  #include <ti/drivers/apps/LED.h>
203  *
204  *  LED_Handle LEDHandle;
205  *  LED_Params ledParams;
206  *
207  *  LED_Params_init(&ledParams);
208  *  ledParams.pwmPeriod = 100; // 0.1 ms period
209  *  ledParams.blinkPeriod = 500; // LED will toggle twice a second
210  *  ledParams.setState = LED_STATE_BLINKING; // Start LED blink on open
211  *  ledHandle = LED_open(CONFIG_LED0, &ledParams); // Open the first LED_Config
212  *
213  *  // Turn on at half brightness level
214  *  LED_setOn(ledHandle, 50);
215  *  @endcode
216  *
217  *******************************************************************************
218  */
219 
220 
221 #ifndef ti_drivers_LED__include
222 #define ti_drivers_LED__include
223 
224 #include <stdint.h>
225 #include <stdbool.h>
226 
227 /* Driver Header files */
228 #include <ti/drivers/GPIO.h>
229 #include <ti/drivers/PWM.h>
230 #include <ti/drivers/dpl/ClockP.h>
231 
232 #ifdef __cplusplus
233 extern "C" {
234 #endif
235 
236 #define LED_BRIGHTNESS_MAX      100U  /* Max brightness in % is 100%*/
237 #define LED_BRIGHTNESS_MIN      0U    /* Max brightness in % is 0%*/
238 
239 #define LED_ON                  1U
240 #define LED_OFF                 0U
241 
242 #define LED_BLINK_FOREVER       0xFFFF
243 
244 /* Number of user defined LED configurations */
245 extern const uint_least8_t LED_count;
246 
247 /*!
248 *  @brief    LED types based on control source
249 *
250 *  A LED can be controlled by GPIO or PWM. Only a PWM controlled LED can
251 *  be operated to show brightness variation. An unopened instance will be of
252 *  type #LED_NONE.
253 */
254 typedef enum {
255     LED_NONE = 0,
256     LED_GPIO_CONTROLLED,
257     LED_PWM_CONTROLLED
258 } LED_Type;
259 
260 /*!
261 *  @brief    LED State
262 *
263 *  A LED can be in OFF, ON or BLINKING state
264 *
265 *  State of particular LED may be tied with a warning/alert in system
266 *  which a thread/task may want to know.
267 */
268 typedef enum {
269     LED_STATE_OFF =  0,
270     LED_STATE_ON,
271     LED_STATE_BLINKING
272 } LED_State;
273 
274 /*!
275  *  @brief    LED configuration
276  *
277  *  The LED_Config structure contains a set of pointers used to characterize
278  *  the LED driver implementation.
279  *
280  *  This structure needs to be defined and provided by the application and will
281  *  be NULL terminated.
282  */
283 typedef struct {
284     /*! Pointer to drivers internal data state object */
285     void        *object;
286     /*! Pointer to a driver specific hardware attributes structure */
287     void const  *hwAttrs;
288 } LED_Config;
289 
290 /*!
291  *  @brief    A handle that is returned from a LED_open() call.
292  */
293 typedef LED_Config* LED_Handle;
294 
295 /*!
296  *  @brief    Hardware specific settings for a LED module.
297  *
298  *  This structure should be defined and provided by the application. The
299  *  index should be correspond to the desired pin in either the PWM or GPIO
300  *  config tables depending on the requested #LED_Type.
301  */
302 typedef struct {
303     uint_least8_t index; /*!< Index into GPIO or PWM config array */
304     LED_Type      type; /*<! GPIO (binary) or PWM (dimmable) control */
305 } LED_HWAttrs;
306 
307 /*!
308  *  @brief    LED Object structure
309  *
310 *  The application must not access any member variables of this structure!
311  */
312 typedef struct {
313     uint32_t        pwmPeriod;    /*!< pwmPeriod(us) of controlling PWM */
314     PWM_Handle      pwmHandle;    /*!< Used for PWM calls if PWM type LED */
315     ClockP_Handle   clockHandle;  /*!< Handle to clock used for blinking */
316     ClockP_Struct   clock;        /*!< Clock internal data */
317     LED_State       state;        /*!< Current State of LED */
318     LED_State       rawState;     /*!< rawState maintains actual state On or Off
319                                        while blinking which is super state */
320     LED_Type        ledType;      /*!< may be either GPIO or PWM controlled */
321     uint8_t         brightness;   /*!< Varying min-max(0-100%) for PWM LED) */
322     uint_least8_t   gpioIndex;    /*!< Index into #GPIO_PinConfig array */
323     uint16_t        togglePeriod; /*!< Toggleperiod(ms), 0 for non-blinking LED
324                                        This is half of blinkPeriod: two toggles
325                                        is one blink */
326     uint16_t        blinkCount;   /*!< Blinkcount, 0 for non-blinking LED */
327 } LED_Object;
328 
329 /*!
330  *  @brief  LED Parameters
331  *
332  *  LED parameters are used with the LED_open() call. Default values for
333  *  these parameters are set using LED_Params_init(). It contains brightness
334  *  field which will be used to control brightness of a LED and also blink
335  *  period if user wants to set LED in blinking mode.
336  *
337  *  @sa     LED_Params_init()
338  */
339 typedef struct {
340     uint32_t    pwmPeriod;      /*!< pwmPeriod(us) of controlling PWM */
341     uint16_t    blinkPeriod;    /*!< param to set blink period (in ms) */
342     uint8_t     brightness;     /*!< may vary from 0-100% for PWM LED */
343     LED_State   setState;       /*!< request to set a LED state(eg blinking) */
344 } LED_Params;
345 
346 /*!
347  *  @brief  Function to close a LED specified by the LED handle
348  *
349  *  This call will destruct associated clock, turn off LED, and close the PWM
350  *  instance if applicable.
351  *
352  *  @pre    LED_open() had to be called first.
353  *
354  *  @param  ledHandle    A #LED_Handle returned from LED_open()
355  *
356  */
357 extern void LED_close(LED_Handle ledHandle);
358 
359 /*!
360  *  @brief  Function to get LED state.
361  *
362  *  This function may be useful in scenarios if a LED state(ON/OFF/BLINKING) is
363  *  tied with some system warning/alerts
364  *
365  *  @param  ledHandle    A #LED_Handle returned from LED_open()
366  *
367  *  @return  The LED State
368  */
369 extern LED_State LED_getState(LED_Handle ledHandle);
370 
371 /*!
372  *  @brief  Function to initialize LED driver.
373  *
374  *  This function will initialize the LED driver.
375  */
376 extern void LED_init();
377 
378 /*!
379  *  @brief  Function to open an instance of LED
380  *
381  *  Function to open an LED instance in the LED_config array. The GPIO or PWM
382  *  configuartions must already exist before this function is called. The
383  *  #LED_Params input can be used to specify the run time options of the LED
384  *  instance.
385  *
386  *  @pre    LED_init() has to be called first
387  *
388  *  @param  index          Index into the LED_config array specifying the
389  *                         #LED_Config that is to be used to open the LED.
390  *
391  *  @param  *params        A pointer to #LED_Params structure. If NULL, it
392  *                         will use default values.
393  *
394  *  @return  A LED_Handle on success, or a NULL on failure.
395  *
396  *  @sa      LED_init()
397  *  @sa      LED_Params_init()
398  *  @sa      LED_close()
399  */
400 LED_Handle LED_open(uint_least8_t index, LED_Params *params);
401 
402 /*!
403  *  @brief  Function to initialize a #LED_Params struct to its defaults
404  *
405  *  @param  params      A pointer to #LED_Params structure for
406  *                      initialization.
407  *
408  *  The default parameters are:
409  *  - LED initially off
410  *  - Blink period of zero
411  *  - Max brightness (for PWM LED only)
412  *  - PWM period of 1 ms (for PWM LED only)
413  */
414 extern void LED_Params_init(LED_Params *params);
415 
416 /*!
417  *  @brief  Function to set brightness level of a LED
418  *
419  *  Ignores brightness settings if LED is not PWM controlled. Fails if
420  *  requested brightness is above 100%.
421  *
422  *  @param  ledHandle    A #LED_Handle
423  *
424  *  @param  level        Brightness level in terms of percentage (0-100)
425  *
426  *  @return true on success or false upon failure.
427  */
428 extern bool LED_setBrightnessLevel(LED_Handle ledHandle, uint8_t level);
429 
430 /*!
431  *  @brief  Function to turn off an LED
432  *
433  *  @param  ledHandle    An #LED_Handle
434  *
435  *  @return true on success or false upon failure.
436  */
437 extern bool LED_setOff(LED_Handle ledHandle);
438 
439 /*!
440  *  @brief  Function to turn on an LED
441  *
442  *  @param  ledHandle    An #LED_Handle
443  *
444  *  @param  brightness   Brightness level in terms of percentage 0-100%.
445  *                       Is ignored for non PWM LEDs.
446  *
447  *  @return true on success or false upon failure.
448  */
449 extern bool LED_setOn(LED_Handle ledHandle, uint8_t brightness);
450 
451 /*!
452  *  @brief  Function to start an LED blinking
453  *
454  *  @param  ledHandle    An #LED_Handle
455  *
456  *  @param  blinkPeriod  Value in ms which determines how often the LED
457  *                       blinks. A value of 1000 will cause the LED to
458  *                       blink once a second. The maximum value is ~65 seconds
459  *                       or 0xFFFF ms.
460  *
461  *  @param  blinkCount   If not set to #LED_BLINK_FOREVER, the LED will blink
462  *                       the specified number of times and then will turn off.
463  *                       A value of zero will stop the LED blinking. Maximum
464  *                       number of blinks is 0x7FFF or 32,767 blinks. An input
465  *                       exceeding this value will be truncated to 0x7FFF.
466  */
467 extern void LED_startBlinking(LED_Handle ledHandle,
468                               uint16_t blinkPeriod,
469                               uint16_t blinkCount);
470 
471 /*!
472  *  @brief  Function to stop an LED blinking
473  *
474  *  @param  ledHandle    An #LED_Handle
475  *
476  */
477 extern void LED_stopBlinking(LED_Handle ledHandle);
478 
479 /*!
480  *  @brief  Function to toggle an LED
481  *
482  *  @param  ledHandle    An #LED_Handle
483  *
484  */
485 extern void LED_toggle(LED_Handle ledHandle);
486 
487 /*!
488  *  @brief  Specify binary state of an LED
489  *
490  *  @param  ledHandle    An #LED_Handle
491  *
492  *  @param  value        TRUE for on, FALSE for off
493  *
494  */
495 extern void LED_write(LED_Handle ledHandle, bool value);
496 
497 #ifdef __cplusplus
498 }
499 #endif
500 
501 #endif /* ti_drivers_LED__include */
502