You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
7.3 KiB
263 lines
7.3 KiB
/*
|
|
* Copyright (c) 2019, Erich Styger
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "platform.h"
|
|
#if PL_CONFIG_USE_BUTTONS
|
|
#include "buttons.h"
|
|
#include "McuButton.h"
|
|
#include "McuRTOS.h"
|
|
#include "McuDebounce.h"
|
|
#include "McuRTT.h"
|
|
#include "fsl_port.h" /* for KBI and pull up selection */
|
|
#include "Event.h"
|
|
|
|
/* Buttons */
|
|
/* User button SW2: PTA14 */
|
|
#define PINS_SW2_GPIO GPIOA
|
|
#define PINS_SW2_PORT PORTA
|
|
#define PINS_SW2_PIN 14U
|
|
|
|
static McuBtn_Handle_t btnSW2;
|
|
|
|
bool BTN_SW2ButtonIsPressed(void) {
|
|
return McuBtn_IsOn(btnSW2);
|
|
}
|
|
|
|
static uint32_t GetButtons(void) {
|
|
uint32_t val = 0;
|
|
|
|
if (McuBtn_IsOn(btnSW2)) {
|
|
val |= BTN_SW2;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
static void OnDebounceEvent(McuDbnc_EventKinds event, uint32_t buttons);
|
|
|
|
#define TIMER_PERIOD_MS 20 /* frequency of timer */
|
|
static McuDbnc_Desc_t data =
|
|
{
|
|
.state = MCUDBMC_STATE_IDLE,
|
|
.timerPeriodMs = TIMER_PERIOD_MS,
|
|
.timer = NULL,
|
|
.debounceTimeMs = 100,
|
|
.repeatTimeMs = 300,
|
|
.longKeyTimeMs = 1000,
|
|
.getButtons = GetButtons,
|
|
.onDebounceEvent = OnDebounceEvent,
|
|
};
|
|
|
|
static void OnDebounceEvent(McuDbnc_EventKinds event, uint32_t buttons) {
|
|
switch(event) {
|
|
case MCUDBNC_EVENT_PRESSED:
|
|
SEGGER_printf("pressed: %d\r\n", buttons);
|
|
EVNT_SetEvent(EVNT_SW1_PRESSED);
|
|
break;
|
|
|
|
case MCUDBNC_EVENT_PRESSED_REPEAT:
|
|
SEGGER_printf("repeat: %d\r\n", buttons);
|
|
EVNT_SetEvent(EVNT_SW1_PRESSED_REPEAT);
|
|
break;
|
|
|
|
case MCUDBNC_EVENT_LONG_PRESSED:
|
|
SEGGER_printf("long pressed: %d\r\n", buttons);
|
|
EVNT_SetEvent(EVNT_SW1_LPRESSED);
|
|
|
|
#if PL_CONFIG_USE_GUI_KEY_NAV
|
|
if (buttons&BTN_UP) {
|
|
LV_ButtonEvent(LV_BTN_MASK_UP, LV_MASK_PRESSED_LONG);
|
|
}
|
|
if (buttons&BTN_DOWN) {
|
|
LV_ButtonEvent(LV_BTN_MASK_DOWN, LV_MASK_PRESSED_LONG);
|
|
}
|
|
if (buttons&BTN_LEFT) {
|
|
LV_ButtonEvent(LV_BTN_MASK_LEFT, LV_MASK_PRESSED_LONG);
|
|
}
|
|
if (buttons&BTN_RIGHT) {
|
|
LV_ButtonEvent(LV_BTN_MASK_RIGHT, LV_MASK_PRESSED_LONG);
|
|
}
|
|
if (buttons&BTN_CENTER) {
|
|
LV_ButtonEvent(LV_BTN_MASK_CENTER, LV_MASK_PRESSED_LONG);
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case MCUDBNC_EVENT_LONG_PRESSED_REPEAT:
|
|
SEGGER_printf("long repeat: %d\r\n", buttons);
|
|
EVNT_SetEvent(EVNT_SW1_LPRESSED_REPEAT);
|
|
break;
|
|
|
|
case MCUDBNC_EVENT_RELEASED:
|
|
SEGGER_printf("released: %d\r\n", buttons);
|
|
EVNT_SetEvent(EVNT_SW1_RELEASED);
|
|
|
|
#if PL_CONFIG_USE_RASPY_UART
|
|
RASPYU_OnJoystickEvent(0);
|
|
#endif
|
|
#if PL_CONFIG_USE_GUI_KEY_NAV
|
|
if (buttons&BTN_UP) {
|
|
LV_ButtonEvent(LV_BTN_MASK_UP, LV_MASK_RELEASED);
|
|
}
|
|
if (buttons&BTN_DOWN) {
|
|
LV_ButtonEvent(LV_BTN_MASK_DOWN, LV_MASK_RELEASED);
|
|
}
|
|
if (buttons&BTN_LEFT) {
|
|
LV_ButtonEvent(LV_BTN_MASK_LEFT, LV_MASK_RELEASED);
|
|
}
|
|
if (buttons&BTN_RIGHT) {
|
|
LV_ButtonEvent(LV_BTN_MASK_RIGHT, LV_MASK_RELEASED);
|
|
}
|
|
if (buttons&BTN_CENTER) {
|
|
LV_ButtonEvent(LV_BTN_MASK_CENTER, LV_MASK_RELEASED);
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
case MCUDBNC_EVENT_END:
|
|
(void)xTimerStop(data.timer, pdMS_TO_TICKS(100)); /* stop timer */
|
|
SEGGER_printf("end: %d\r\n", buttons);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if McuLib_CONFIG_SDK_USE_FREERTOS
|
|
static void vTimerCallbackDebounce(TimerHandle_t pxTimer) {
|
|
/* called with TIMER_PERIOD_MS during debouncing */
|
|
(void)pxTimer; /* not used */
|
|
McuDbnc_Process(&data);
|
|
}
|
|
|
|
static void StartDebounce(uint32_t buttons, bool fromISR) {
|
|
BaseType_t res;
|
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
|
|
if (data.state==MCUDBMC_STATE_IDLE) {
|
|
data.scanValue = buttons;
|
|
data.state = MCUDBMC_STATE_START;
|
|
McuDbnc_Process(&data);
|
|
if (fromISR) {
|
|
res = xTimerStartFromISR(data.timer, &xHigherPriorityTaskWoken);
|
|
} else {
|
|
res = xTimerStart(data.timer, pdMS_TO_TICKS(100));
|
|
}
|
|
#ifdef NDEBUG
|
|
(void)res; /* avoid compiler warning about unused variable */
|
|
#endif
|
|
assert(res==pdPASS);
|
|
if (fromISR) {
|
|
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if !PL_CONFIG_USE_KBI
|
|
#if McuLib_CONFIG_SDK_USE_FREERTOS
|
|
static void PollButtons(void) {
|
|
if (McuBtn_IsOn(btnSW2)) {
|
|
StartDebounce(BTN_SW2, false);
|
|
}
|
|
}
|
|
|
|
static void BtnTask(void *pv) {
|
|
for(;;) {
|
|
PollButtons();
|
|
vTaskDelay(pdMS_TO_TICKS(50));
|
|
}
|
|
}
|
|
#endif
|
|
#else
|
|
void PORTA_IRQHandler(void) { /* SW2 is on PORTA (PINS_SW2_PORT) */
|
|
uint32_t flags;
|
|
|
|
flags = GPIO_PortGetInterruptFlags(PINS_SW2_GPIO);
|
|
if (flags&(1U<<PINS_SW2_PIN)) {
|
|
GPIO_PortClearInterruptFlags(PINS_SW2_GPIO, 1U<<PINS_SW2_PIN);
|
|
StartDebounce(BTN_SW2, true);
|
|
}
|
|
__DSB();
|
|
}
|
|
#endif
|
|
|
|
/* because SDK 2.3.0 does not provide this: */
|
|
static inline port_pin_config_t PORT_GetPinConfig(PORT_Type *base, uint32_t pin) {
|
|
uint32_t addr = (uint32_t)&base->PCR[pin];
|
|
return *(port_pin_config_t *)(addr);
|
|
}
|
|
|
|
void BTN_EnablePullup(void) {
|
|
/* V2 has no pull-up on the board, need to turn on internal pull-up */
|
|
McuBtn_EnablePullResistor(btnSW2);
|
|
}
|
|
|
|
void BTN_Init(void) {
|
|
McuBtn_Config_t btnConfig;
|
|
|
|
McuBtn_GetDefaultConfig(&btnConfig);
|
|
btnConfig.isLowActive = true;
|
|
|
|
btnConfig.hw.gpio = PINS_SW2_GPIO;
|
|
btnConfig.hw.port = PINS_SW2_PORT;
|
|
btnConfig.hw.pin = PINS_SW2_PIN;
|
|
btnSW2 = McuBtn_InitButton(&btnConfig);
|
|
#if PL_IS_INTRO_ZUMO_K22_V2
|
|
/* has no pull-ups on the board, need to turn on internal pull-ups */
|
|
port_pin_config_t portConfig;
|
|
|
|
portConfig = PORT_GetPinConfig(PINS_SW2_PORT, PINS_SW2_PIN); /* get current config */
|
|
portConfig.pullSelect = kPORT_PullUp;
|
|
PORT_SetPinConfig(PINS_SW2_PORT, PINS_SW2_PIN, &portConfig);
|
|
#endif
|
|
#if !PL_LOCAL_CONFIG_USE_RESET_PIN
|
|
/* SW1: enable and turn on pull-up resistor for PTA14 (push button) */
|
|
// PORT_PDD_SetPinPullSelect(PORTA_BASE_PTR, 14, PORT_PDD_PULL_UP);
|
|
// PORT_PDD_SetPinPullEnable(PORTA_BASE_PTR, 14, PORT_PDD_PULL_ENABLE);
|
|
/* this is not implemented yet for the SDK: need to disable reset functionality and enable pull-ups */
|
|
#endif
|
|
#if PL_CONFIG_USE_KBI
|
|
PORT_SetPinInterruptConfig(PINS_SW2_PORT, PINS_SW2_PIN, kPORT_InterruptFallingEdge);
|
|
/* SW2 is on Port A */
|
|
NVIC_SetPriority(PORTA_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
|
EnableIRQ(PORTA_IRQn);
|
|
#elif McuLib_CONFIG_SDK_USE_FREERTOS /* use task for button polling */
|
|
if (xTaskCreate(
|
|
BtnTask, /* pointer to the task */
|
|
"Btn", /* task name for kernel awareness debugging */
|
|
500/sizeof(StackType_t), /* task stack size */
|
|
(void*)NULL, /* optional task startup argument */
|
|
tskIDLE_PRIORITY+4, /* initial priority */
|
|
(TaskHandle_t*)NULL /* optional task handle to create */
|
|
) != pdPASS)
|
|
{
|
|
for(;;){} /* error! probably out of memory */
|
|
}
|
|
#endif
|
|
#if McuLib_CONFIG_SDK_USE_FREERTOS
|
|
data.timer = xTimerCreate(
|
|
"tmrDbnc", /* name */
|
|
pdMS_TO_TICKS(TIMER_PERIOD_MS), /* period/time */
|
|
pdTRUE, /* auto reload */
|
|
(void*)2, /* timer ID */
|
|
vTimerCallbackDebounce); /* callback */
|
|
if (data.timer==NULL) {
|
|
for(;;); /* failure! */
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void BTN_Deinit(void) {
|
|
#if PL_CONFIG_USE_KBI
|
|
#if TINYK22_HAT_VERSION==3
|
|
DisableIRQ(PORTB_IRQn); /* all buttons are on Port B */
|
|
#elif TINYK22_HAT_VERSION==4 || TINYK22_HAT_VERSION==5
|
|
DisableIRQ(PORTA_IRQn); /* left and right are on Port A */
|
|
DisableIRQ(PORTB_IRQn); /* up, down, push are on Port B */
|
|
#endif
|
|
#endif
|
|
btnSW2 = McuBtn_DeinitButton(btnSW2);
|
|
}
|
|
#endif /* PL_CONFIG_USE_BUTTONS */
|
|
|