195 lines
4.5 KiB
C
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
|
|
|
|
|