3 * Copyright (c) 2019 Google LLC.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 #include "ButtonHandler.h"
22 #include "AppConfig.h"
25 #include "gpiointerrupt.h"
26 #include "hal-config-board.h"
28 typedef struct ButtonArray
30 GPIO_Port_TypeDef port;
34 static const ButtonArray_t sButtonArray[BSP_BUTTON_COUNT] = BSP_BUTTON_INIT; // GPIO info for the 2 WDTK buttons.
35 TimerHandle_t buttonTimers[BSP_BUTTON_COUNT]; // FreeRTOS timers used for debouncing
36 // buttons. Array to hold handles to
37 // the created timers.
39 void ButtonHandler::Init(void)
43 // Create FreeRTOS sw timers for debouncing buttons.
44 for (uint8_t i = 0; i < BSP_BUTTON_COUNT; i++)
46 buttonTimers[i] = xTimerCreate("BtnTmr", // Just a text name, not used by the RTOS kernel
47 APP_BUTTON_DEBOUNCE_PERIOD_MS, // timer period
48 false, // no timer reload (==one-shot)
49 (void *) (int) i, // init timer id = button index
50 TimerCallback // timer callback handler (all buttons use
51 // the same timer cn function)
56 void ButtonHandler::GpioInit(void)
58 // Set up button GPIOs to input with pullups.
59 for (uint8_t i = 0; i < BSP_BUTTON_COUNT; i++)
61 GPIO_PinModeSet(sButtonArray[i].port, sButtonArray[i].pin, gpioModeInputPull, 1);
63 // Set up interrupt based callback function - trigger on both edges.
65 GPIOINT_CallbackRegister(sButtonArray[0].pin, Button0Isr);
66 GPIOINT_CallbackRegister(sButtonArray[1].pin, Button1Isr);
67 GPIO_IntConfig(sButtonArray[0].port, sButtonArray[0].pin, true, true, true);
68 GPIO_IntConfig(sButtonArray[1].port, sButtonArray[1].pin, true, true, true);
70 // Change GPIO interrupt priority (FreeRTOS asserts unless this is done here!)
71 NVIC_SetPriority(GPIO_EVEN_IRQn, 5);
72 NVIC_SetPriority(GPIO_ODD_IRQn, 5);
75 void ButtonHandler::Button0Isr(uint8_t pin)
80 if (pin == sButtonArray[btnIdx].pin)
82 EventHelper(btnIdx, true); // true== 'isr context'
86 void ButtonHandler::Button1Isr(uint8_t pin)
91 if (pin == sButtonArray[btnIdx].pin)
93 EventHelper(btnIdx, true); // true== 'isr context'
97 void ButtonHandler::EventHelper(uint8_t btnIdx, bool isrContext)
99 // May be called from Interrupt context so keep it short!
101 if (btnIdx < BSP_BUTTON_COUNT)
103 // Get buton gpio pin state.
104 bool gpioPinPressed = !GPIO_PinInGet(sButtonArray[btnIdx].port, sButtonArray[btnIdx].pin);
108 portBASE_TYPE taskWoken = pdFALSE; // For FreeRTOS timer (below).
110 // Start/restart the button debounce timer (Note ISR version of FreeRTOS
112 xTimerStartFromISR(buttonTimers[btnIdx], &taskWoken);
114 if (taskWoken != pdFALSE)
121 // Called by debounce timer expiry (this indicates that button gpio
123 // Note- NOT in isr context at this point.
125 // Notify AppTask of button state change.
126 GetAppTask().ButtonEventHandler(btnIdx, (gpioPinPressed) ? APP_BUTTON_PRESSED : APP_BUTTON_RELEASED);
131 void ButtonHandler::TimerCallback(TimerHandle_t xTimer)
133 // Get the button index of the expired timer and call button event helper.
137 timerId = (uint32_t) pvTimerGetTimerID(xTimer);
138 if (timerId < BSP_BUTTON_COUNT)
140 uint8_t btnIdx = timerId;
141 EventHelper(btnIdx, false); // false== 'not from isr context'