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       Button.h
35  *
36  *  @brief      Button driver
37  *
38  *  @anchor ti_drivers_Button_Synopsis
39  *  # Synopsis #
40  *
41  *  @code
42  *  #include <ti/drivers/apps/Button.h>
43  *
44  *  int main(void)
45  *  {
46  *      Button_Params params;
47  *      Button_Handle handle;
48  *
49  *      Button_Params_init(&params);
50  *
51  *      handle = Button_open(CONFIG_BUTTON0, buttonCallbackFxn, &params);
52  *
53  *      ...
54  *  }
55  *
56  *  void buttonCallbackFxn(Button_Handle handle, Button_EventMask events)
57  *  {
58  *      if (events & Button_EV_CLICK)
59  *      {
60  *          // Received a click, handle app condition 0 etc
61  *          handleAppCond(0);
62  *      }
63  *      if (events & Button_EV_LONGCLICKED)
64  *      {
65  *          // Long press, handle app condition 1 etc
66  *          handleAppCond(1);
67  *      }
68  *      ...
69  *  }
70  *  @endcode
71  *
72  *  @anchor ti_drivers_Button_Examples
73  *  ## Examples #
74  *
75  *  * @ref ti_drivers_Button_Examples_config "Generic Configuration"
76  *
77  *  ## Overview #
78  *
79  *  The Button driver simplifies interfacing push buttons. For example, push
80  *  buttons on LaunchPads, BoosterPacks, or custom boards may easily be managed
81  *  via the Button API. A given button instance may subscribe to one or several
82  *  #Button_Events. When a subscribed event occurs, the user will receive a
83  *  callback with the handle of the button and the event(s) that occured.
84  *
85  *  ## User requirements #
86  *  Buttons use the @ref GPIO.h interface for interfacing with hardware, so a
87  *  #GPIO_PinConfig array must exist and contain a config for the button pin.
88  *  The user must statically allocate a #Button_Config array called
89  *  Button_config. Each physical button should map to an index in
90  *  Button_config.
91  *
92  *  ## Defining #Button_Config, #Button_Object and #Button_HWAttrs #
93  *  Each structure must be defined by the application. The following
94  *  example is for a MSP432 in which two buttons are setup.
95  *  The following declarations are placed in "ti_drivers_config.h"
96  *  and "ti_drivers_config.c" respectively. How the GPIO configs are defined
97  *  are detailed in the next example.
98  *
99  *  @anchor ti_drivers_Button_Examples_config
100  *
101  *  "ti_drivers_config.h"
102  *  @code
103  *  #define CONFIG_BUTTON_0     0  //Button number 1
104  *  #define CONFIG_BUTTON_1     1  //Button number 2
105  *  @endcode
106  *
107  *  "ti_drivers_config.c"
108  *  @code
109  *  #include <Button.h>
110  *
111  *  Button_Object Button_object[2];
112  *
113  *  const  Button_HWAttrs Button_hwAttrs[2] = {
114  *      {
115  *          .gpioIndex = CONFIG_S1,
116  *      },
117  *      {
118  *          .gpioIndex = CONFIG_S2,
119  *      }
120  *  };
121  *
122  *  const Button_Config Button_config[2] = {
123  *      {
124  *          .hwAttrs = &Button_hwAttrs[0],
125  *          .object =  &Button_object[0],
126  *      },
127  *      {
128  *          .hwAttrs = &Button_hwAttrs[1],
129  *          .object =  &Button_object[1],
130  *      },
131  *  };
132  *  @endcode
133  *
134  *  ##Setting up GPIO configurations #
135  *
136  *  The following example is for a MSP432.
137  *  We are showing interfacing of two push buttons.  Each need a GPIO pin. The
138  *  following definitions are in "ti_drivers_config.h" and
139  *  "ti_drivers_config.c" respectively. This example uses GPIO pins 1.1 and
140  *  1.4. The other GPIO configuration structures must exist, see @ref GPIO.h.
141  *
142  *  "ti_drivers_config.h"
143  *  @code
144  *  #define CONFIG_S1       0
145  *  #define CONFIG_S2       1
146  *  @endcode
147  *
148  *  "ti_drivers_config.c"
149  *  @code
150  *  #include <gpio.h>
151  *  GPIO_PinConfig gpioPinConfigs[] = {
152  *      GPIOMSP432_P1_1 | GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING,
153  *      GPIOMSP432_P1_4 | GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING,
154  *  }
155  *
156  *  @endcode
157  ******************************************************************************
158  */
159 #ifndef ti_drivers_Button__include
160 #define ti_drivers_Button__include
161 
162 #include <stdint.h>
163 #include <stdbool.h>
164 
165 /* Driver Header files */
166 #include <ti/drivers/GPIO.h>
167 #include <ti/drivers/dpl/ClockP.h>
168 
169 #ifdef __cplusplus
170 extern "C" {
171 #endif
172 
173 /* Number of user defined Button configurations */
174 extern const uint_least8_t Button_count;
175 
176 /*!
177  *  @brief    Button configuration
178  *
179  *  Each #Button_Config represents a single physical button. It contains
180  *  pointers to the button's #Button_HWAttrs and #Button_Object. The user must
181  *  statically allocate all of these structures.
182  */
183 typedef struct Button_Config
184 {
185     /*! Pointer to a #Button_Object struct */
186     void *object;
187 
188     /*! Pointer to a #Button_HWAttrs structure */
189     void const *hwAttrs;
190 }Button_Config;
191 
192 /*!
193  *  @brief    A handle that is returned from a Button_open() call.
194  *
195  *  User will use this handle to interact with a given button instance.
196  */
197 typedef struct Button_Config* Button_Handle;
198 
199 /*!
200  *  @brief    Button State
201  *  @private
202  *
203  * This enumeration describes whether the button is pressed or released etc.
204  * This is for internal state machine handling.
205  */
206 typedef enum Button_State
207 {
208     /*! Edge detected, debouncing */
209     Button_PRESSING                     = 1,
210     /*! Press verified, not detecting longpress */
211     Button_PRESSED                      = 2,
212     /*! Press verified, waiting for longpress timeout. */
213     Button_LONGPRESSING                 = 3,
214     /*! Longpress verified, waiting for neg-edge */
215     Button_LONGPRESSED                  = 4,
216     /*! Neg-edge received, debouncing */
217     Button_RELEASING                    = 5,
218     /*! Neg-edge received after long-press, debouncing. */
219     Button_RELEASING_LONG               = 6,
220     /*! Button release verified. */
221     Button_RELEASED                     = 7,
222     /*! EDGE detected doublepress */
223     Button_DBLPRESS_DETECTION           = 8,
224     /*! EDGE detected doublepress */
225     Button_DBLPRESSING                  = 9,
226     /*! DOUBLE PRESS verified, waiting for neg edge */
227     Button_DBLPRESSED                   = 10,
228     /*! DOUBLE PRESS verified, waiting for neg edge k*/
229     Button_RELEASING_DBLPRESSED         = 11
230 } Button_State;
231 
232 /*!
233  *  @brief Button event flags
234  *
235  *  The event flags can be used by the user to subscribe to specific kinds of
236  *  button actions and by the driver to signal which event caused a callback.
237  */
238 typedef enum Button_Events
239 {
240     /*! Button pressed down, may or may not subsequently have been released */
241     Button_EV_PRESSED        = 0x01,
242     /*! Button held down for more than tLongpress (ms) */
243     Button_EV_LONGPRESSED    = 0x02,
244     /*! Button released after press or longpress */
245     Button_EV_RELEASED       = 0x04,
246     /*! Button was pressed and released, but was not a long press */
247     Button_EV_CLICKED        = 0x08,
248     /*!
249      * Button was pressed and released, and held for longer than
250      * longPressDuration (ms)
251      */
252     Button_EV_LONGCLICKED    = 0x10,
253     /*! Button was pressed when double click detection was active */
254     Button_EV_DOUBLECLICKED  = 0x20,
255 } Button_Events;
256 
257 /*! @brief Event subscription and notification mask type */
258 typedef uint8_t Button_EventMask;
259 
260 /*!
261  *  @brief    A handler to receive button callbacks.
262  */
263 typedef void (*Button_Callback)(Button_Handle buttonHandle,
264                                 Button_EventMask buttonEvents);
265 
266 /*!
267  *  @brief    Button Pull settings
268  *
269  * This enumeration defines whether the GPIO connected to the button
270  * is PULL UP or PULL DOWN
271  */
272 typedef enum Button_Pull
273 {
274     /* NOTE: DO NOT change the values of DOWN/UP from (0,1) */
275     Button_PULL_DOWN   = 0,     /*!< Button is PULLED DOWN. */
276     Button_PULL_UP     = 1,     /*!< Button is PULLED UP. */
277     Button_PULL_NOTSET = 2      /*!< Button pull not set */
278 } Button_Pull;
279 
280 /*!
281  *  @brief    Hardware specific settings for a button
282  *
283  *  This structure should be defined and provided by the application.
284  *  The index provided should correspond to a gpio pin in a #GPIO_PinConfig
285  *  array. This gpio pin should be the pin connected to the button and must
286  *  be configured as #GPIO_CFG_INPUT and #GPIO_CFG_IN_INT_FALLING.
287  */
288 typedef struct Button_HWAttrs
289 {
290     uint_least8_t gpioIndex;    /*!< GPIO configuration index. */
291 } Button_HWAttrs;
292 
293 /*!
294  *  @brief  Button State Variables
295  *  @private
296  *
297  *  Each button instance needs set of variables to monitor its state.
298  *  We group these variables under the structure Button_State.
299  *
300  *  @sa     Button_Params_init()
301  */
302 typedef struct Button_StateVariables
303 {
304     /*! Button state */
305     Button_State   state;
306     /*! Button pressed start time in milliseconds(ms) */
307     uint32_t       pressedStartTime;
308     /*! Button pressed duration (ms) */
309     uint32_t       lastPressedDuration;
310 }Button_StateVariables;
311 
312 /*!
313  *  @brief    Internal to Button module. Members should not be accessed
314  *            by the application.
315  */
316 typedef struct Button_Object
317 {
318     /*! Handle to clock used for timing */
319     ClockP_Handle          clockHandle;
320 
321     /*! State variables for handling the debounce state machine */
322     Button_StateVariables  buttonStateVariables;
323 
324     /*! Event subscription mask for the button */
325     Button_EventMask       buttonEventMask;
326 
327     /*! Callback function for the button */
328     Button_Callback        buttonCallback;
329 
330     /*! Debounce duration for the button in milliseconds(ms) */
331     uint32_t               debounceDuration;
332 
333     /*! Long press duration is milliseconds(ms) */
334     uint32_t               longPressDuration;
335 
336     /*! Double press detection timeout is milliseconds(ms) */
337     uint32_t               doublePressDetectiontimeout;
338 
339     /*! Button pull(stored after reading from GPIO module) */
340     Button_Pull            buttonPull;
341 } Button_Object;
342 
343 /*!
344  *  @brief  Button Parameters
345  *
346  *  Button parameters are used with the Button_open() call. Default values for
347  *  these parameters are set using Button_Params_init().
348  *
349  *  @sa     Button_Params_init()
350  */
351 typedef struct Button_Params
352 {
353     /*! Debounce duration for the button in milliseconds(ms) */
354     uint32_t        debounceDuration;
355 
356     /*! Long press duration is milliseconds(ms) */
357     uint32_t        longPressDuration;
358 
359     /*! Double press detection timeout is milliseconds(ms) */
360     uint32_t        doublePressDetectiontimeout;
361 
362     /*! Event subscription mask for the button */
363     Button_EventMask    buttonEventMask;
364 } Button_Params;
365 
366 /*!
367  *  @brief  Function to close a Button specified by the #Button_Handle
368  *
369  *  @pre        Button_open() had to be called first.
370  *
371  *  @param[in]  handle    A #Button_Handle returned from Button_open() call
372  *
373  *  @return     True on success or false upon failure.
374  */
375 extern bool Button_close(Button_Handle handle);
376 
377 /*!
378  *  @brief  Function to initialize Button driver.
379  */
380 extern void Button_init();
381 
382 /*!
383  *  @brief  Function to open a given Button
384  *
385  *  Function to open a button instance corresponding to a #Button_Config in the
386  *  Button_config array. The GPIO configurations must exist prior to calling
387  *  this function. The #Button_Params may be used to specify runtime parameters.
388  *
389  *  @pre       Button_init() has to be called first
390  *
391  *  @param[in] buttonIndex    Logical button number indexed into
392  *                            the Button_config table
393  *
394  *  @param[in] buttonCallback A #Button_Callback that is called when a desired
395  *                            event occurs.
396  *
397  *  @param[in] *params        A pointer to #Button_Params structure. If NULL,
398  *                            it will use default values.
399  *
400  *  @return  A #Button_Handle on success, or a NULL on failure.
401  *
402  *  @sa      Button_init()
403  *  @sa      Button_Params_init()
404  *  @sa      Button_close()
405  */
406 extern Button_Handle Button_open(uint_least8_t buttonIndex,
407                                  Button_Callback buttonCallback,
408                                  Button_Params *params);
409 
410 /*!
411  *  @brief  Function to initialize a #Button_Params struct to its defaults
412  *
413  *  @param[in] params   A pointer to a #Button_Params structure that will be
414  *                      initialized.
415  *
416  *  Default values
417  *  ------------------------------------------------------------------
418  *  parameter        | value        | description              | unit
419  *  -----------------|--------------|--------------------------|------------
420  *  debounceDuration | 10           | debounce duration        | ms
421  *  longPressDuration| 2000         | long press duration      | ms
422  *  buttonEventMask  | 0xFF         | subscribed to all events | NA
423  */
424 extern void Button_Params_init(Button_Params *params);
425 
426 /*!
427  *  @brief  Function to return the lastPressedDuration (valid only for short
428  *          press, long press)
429  *
430  *  The API returns last pressed duration and it is valid only for shortpress,
431  *  longpress. If this API is called after receiving an event click or long
432  *  click then the API returns the press duration which is time delta between
433  *  the press and release of the button.
434  *  @note This API call is only valid after a click or long click and not after
435  *  a double click.
436  *
437  *  @param[in] handle   Pointer to the #Button_Handle of the desired button.
438  *
439  *  @return    time duration in milliseconds.
440  *
441  */
442 extern uint32_t Button_getLastPressedDuration(Button_Handle handle);
443 
444 /*!
445  *  @brief     Function to set callback function for the button instance
446  *
447  *  @param[in] handle           A #Button_Handle returned from Button_open()
448  *
449  *  @param[in] buttonCallback   button callback function
450  *
451  */
452 extern void Button_setCallback(Button_Handle handle,
453                                Button_Callback buttonCallback);
454 
455 /*!
456  *  @brief  This is the GPIO interrupt callback function which is called on a
457  *          button press or release. This is internally used by button module.
458  *
459  *  This function is internally used by button module for receiving the GPIO
460  *  interrupt callbacks. This is exposed to the application for wake up cases.
461  *  In some of the MCUs, when in LPDS(Low power deep sleep) the GPIO interrupt
462  *  is consumed for wake up, and in order to make the button module work the
463  *  the application has to call this API with the index of the GPIO pin which
464  *  actually was the reason for the wake up.
465  *
466  *  @param[in]  index   Index of the GPIO for which the button press has to be
467  *                      detected. This is an index in #GPIO_PinConfig array.
468  */
469 void Button_gpioCallbackFxn(uint_least8_t index);
470 
471 #ifdef __cplusplus
472 }
473 #endif
474 
475 #endif /* ti_drivers_Button__include */
476