Files
microchip-application-bmd38…/btn.c
T

195 lines
4.5 KiB
C

#include "nrf_gpio.h"
#include "nrf_gpiote.h"
#include "nrfx_gpiote.h"
#include "nrf_log.h"
#include "elite_board.h"
#include "led_drv.h"
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#if (DEF_BTN_ENABLED)
#define TIME_DEBOUNCE pdMS_TO_TICKS(25)
#define TIME_CLICK_INTERVAL pdMS_TO_TICKS(200)
#define TIME_PRESS_LONG pdMS_TO_TICKS(1500)
//--------------------------------------------------------------------
static TaskHandle_t btn_task_handle = NULL;
static void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t xPin, nrf_gpiote_polarity_t ePolarity)
{
uint32_t pins = nrf_gpio_pin_read(SHUT_DOWN_PIN);
if (__get_IPSR() != 0)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(btn_task_handle, pins, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
else
{
xTaskNotify(btn_task_handle, xPin, eSetValueWithOverwrite);
}
}
static bool wait_pressed(TickType_t xTimeout)
{
uint32_t pins;
do {
if (!xTaskNotifyWait(0, 0, &pins, xTimeout))
{
return false;
}
do {
} while (xTaskNotifyWait(0, 0, &pins, TIME_DEBOUNCE));
} while (pins);
return true;
}
static bool wait_released(TickType_t xTimeout)
{
uint32_t pins;
do {
if (!xTaskNotifyWait(0, 0, &pins, xTimeout))
{
return false;
}
do {
} while (xTaskNotifyWait(0, 0, &pins, TIME_DEBOUNCE));
} while (!pins);
return true;
}
//--------------------------------------------------------------------
typedef enum
{
BTN_EVENT_SHORTx1,
BTN_EVENT_SHORTx2,
BTN_EVENT_SHORTx3,
BTN_EVENT_LONG,
} BtnEvent_t;
static BtnEvent_t btn_event(void)
{
while (1)
{
// drop previous/undefined clicks
while (wait_pressed(TIME_CLICK_INTERVAL))
{
wait_released(portMAX_DELAY);
}
// wait for clicks
wait_pressed(portMAX_DELAY);
if (!wait_released(TIME_PRESS_LONG))
{
return BTN_EVENT_LONG;
}
for (BtnEvent_t e = BTN_EVENT_SHORTx1; e < BTN_EVENT_LONG; e++)
{
if (!wait_pressed(TIME_CLICK_INTERVAL))
{
return e;
}
if (!wait_released(TIME_PRESS_LONG))
{
break;
}
}
}
}
static void btn_event_shortx1_cb(void)
{
NRF_LOG_INFO("BTN_EVENT_SHORTx1");
const struct led_color color[6] = { LED_RED, LED_ORANGE, LED_YELLOW, LED_GREEN, LED_BLUE, LED_PURPLE };
static int idx = 0;
led_set(color[idx++ % COUNTOF(color)]);
}
static void btn_event_shortx2_cb(void)
{
NRF_LOG_INFO("BTN_EVENT_SHORTx2");
for (int i = 0; i < 2; i++)
{
led_set(LED_OFF);
vTaskDelay(pdMS_TO_TICKS(250));
led_set(LED_BLUE);
vTaskDelay(pdMS_TO_TICKS(250));
}
led_set(LED_IDEL_DISCONNECT);
}
static void btn_event_shortx3_cb(void)
{
NRF_LOG_INFO("BTN_EVENT_SHORTx3");
for (int i = 0; i < 2; i++)
{
led_set(LED_OFF);
vTaskDelay(pdMS_TO_TICKS(250));
led_set(LED_CYAN);
vTaskDelay(pdMS_TO_TICKS(250));
led_set(LED_IDEL_DISCONNECT);
}
led_set(LED_IDEL_DISCONNECT);
}
static void btn_event_long(void)
{
NRF_LOG_INFO("BTN_EVENT_LONG");
led_set(LED_ORANGE);
if (!wait_released(TIME_PRESS_LONG))
{
led_set(LED_OFF);
elite_board_power_off();
}
led_set(LED_IDEL_DISCONNECT);
}
static void btn_task(void *pvArg)
{
for (;;)
{
switch (btn_event())
{
case BTN_EVENT_SHORTx1:
btn_event_shortx1_cb();
break;
case BTN_EVENT_SHORTx2:
btn_event_shortx2_cb();
break;
case BTN_EVENT_SHORTx3:
btn_event_shortx3_cb();
break;
case BTN_EVENT_LONG:
btn_event_long();
break;
}
}
}
void btn_init(void)
{
nrfx_gpiote_in_config_t config = {
.hi_accuracy = 1,
.is_watcher = 0,
.pull = NRF_GPIO_PIN_NOPULL,
.sense = NRF_GPIOTE_POLARITY_TOGGLE,
.skip_gpio_setup = 0
};
nrfx_gpiote_init();
nrfx_gpiote_in_init(SHUT_DOWN_PIN, &config, nrfx_gpiote_evt_handler);
nrfx_gpiote_in_event_enable(SHUT_DOWN_PIN, true);
xTaskCreate(btn_task, "btn", 256, NULL, 3, &btn_task_handle);
}
#endif // !SHUT_DOWN_PIN