203 lines
5.5 KiB
C
203 lines
5.5 KiB
C
#include "beacon.h"
|
|
|
|
#include "driver/gpio.h"
|
|
#include "driver/gptimer.h"
|
|
#include "esp_log.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "inttypes.h"
|
|
#include "led_strip.h"
|
|
#include "sdkconfig.h"
|
|
|
|
static const char *TAG = "beacon";
|
|
|
|
typedef struct
|
|
{
|
|
uint32_t count;
|
|
uint32_t alarm;
|
|
} TimerEvent;
|
|
|
|
typedef struct
|
|
{
|
|
led_strip_handle_t ledStrip;
|
|
uint32_t size;
|
|
} LedMatrix;
|
|
|
|
static LedMatrix ledMatrix = {.size = 64};
|
|
static QueueHandle_t timerEvtQueue = NULL;
|
|
gptimer_handle_t gpTimer = NULL;
|
|
|
|
bool IRAM_ATTR timerCallback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *userCtx)
|
|
{
|
|
TimerEvent evt = {.count = edata->count_value, .alarm = edata->alarm_value};
|
|
BaseType_t highTaskWakeup = pdFALSE;
|
|
xQueueSendFromISR(timerEvtQueue, &evt, &highTaskWakeup);
|
|
|
|
return (highTaskWakeup == pdTRUE);
|
|
}
|
|
|
|
void timerEventTask(void *arg)
|
|
{
|
|
TimerEvent evt;
|
|
while (true)
|
|
{
|
|
if (xQueueReceive(timerEvtQueue, &evt, portMAX_DELAY))
|
|
{
|
|
static bool level = false;
|
|
level = !level;
|
|
if (ledMatrix.ledStrip)
|
|
{
|
|
for (uint32_t i = 0; i < (ledMatrix.size / 2); i++)
|
|
{
|
|
led_strip_set_pixel(ledMatrix.ledStrip, i, 0, (level) ? 100 : 0, 0);
|
|
}
|
|
led_strip_refresh(ledMatrix.ledStrip);
|
|
}
|
|
ESP_LOGI(TAG, "Timer Event: count = %" PRIu32 ", alarm = %" PRIu32 ", GPIO now %s", evt.count, evt.alarm,
|
|
level ? "HIGH" : "LOW");
|
|
}
|
|
}
|
|
}
|
|
|
|
esp_err_t initWled(void)
|
|
{
|
|
led_strip_config_t stripConfig = {.strip_gpio_num = CONFIG_WLED_DIN_PIN,
|
|
.max_leds = ledMatrix.size,
|
|
.led_model = LED_MODEL_WS2812,
|
|
.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_RGB,
|
|
.flags = {
|
|
.invert_out = false,
|
|
}};
|
|
|
|
led_strip_rmt_config_t rmtConfig = {.clk_src = RMT_CLK_SRC_DEFAULT,
|
|
.resolution_hz = 0,
|
|
.mem_block_symbols = 0,
|
|
.flags = {
|
|
.with_dma = true,
|
|
}};
|
|
ESP_ERROR_CHECK(led_strip_new_rmt_device(&stripConfig, &rmtConfig, &ledMatrix.ledStrip));
|
|
|
|
const uint32_t value = 25;
|
|
for (uint32_t i = (ledMatrix.size / 2); i < ledMatrix.size; i++)
|
|
{
|
|
led_strip_set_pixel(ledMatrix.ledStrip, i, value, value, value);
|
|
}
|
|
led_strip_refresh(ledMatrix.ledStrip);
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t startBeacon(void)
|
|
{
|
|
if (gpTimer == NULL)
|
|
{
|
|
ESP_LOGE(TAG, "GPTimer not initialized");
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
esp_err_t ret = gptimer_start(gpTimer);
|
|
if (ret != ESP_OK)
|
|
{
|
|
ESP_LOGE(TAG, "Failed to start gptimer: %s", esp_err_to_name(ret));
|
|
}
|
|
else
|
|
{
|
|
ESP_LOGI(TAG, "GPTimer started.");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t stopBeacon(void)
|
|
{
|
|
if (gpTimer == NULL)
|
|
{
|
|
ESP_LOGE(TAG, "GPTimer not initialized");
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
esp_err_t ret = gptimer_stop(gpTimer);
|
|
if (ret != ESP_OK)
|
|
{
|
|
ESP_LOGE(TAG, "Failed to stop gptimer: %s", esp_err_to_name(ret));
|
|
}
|
|
else
|
|
{
|
|
ESP_LOGI(TAG, "GPTimer stopped.");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t initBeacon(void)
|
|
{
|
|
esp_err_t ret = ESP_OK;
|
|
timerEvtQueue = xQueueCreate(10, sizeof(TimerEvent));
|
|
if (timerEvtQueue == NULL)
|
|
{
|
|
ESP_LOGE(TAG, "Failed to create timer event queue");
|
|
ret = ESP_ERR_NO_MEM;
|
|
goto exit;
|
|
}
|
|
|
|
gptimer_config_t timerConfig = {
|
|
.clk_src = GPTIMER_CLK_SRC_DEFAULT, .direction = GPTIMER_COUNT_UP, .resolution_hz = 1000000};
|
|
ret = gptimer_new_timer(&timerConfig, &gpTimer);
|
|
if (ret != ESP_OK)
|
|
{
|
|
ESP_LOGE(TAG, "Failed to create new gptimer: %s", esp_err_to_name(ret));
|
|
goto cleanupQueue;
|
|
}
|
|
|
|
gptimer_event_callbacks_t callbacks = {.on_alarm = timerCallback};
|
|
ret = gptimer_register_event_callbacks(gpTimer, &callbacks, NULL);
|
|
if (ret != ESP_OK)
|
|
{
|
|
ESP_LOGE(TAG, "Failed to register timer callbacks: %s", esp_err_to_name(ret));
|
|
goto cleanupTimer;
|
|
}
|
|
|
|
ret = gptimer_enable(gpTimer);
|
|
if (ret != ESP_OK)
|
|
{
|
|
ESP_LOGE(TAG, "Failed to enable gptimer: %s", esp_err_to_name(ret));
|
|
goto cleanupTimer;
|
|
}
|
|
|
|
gptimer_alarm_config_t alarmConfig = {
|
|
.alarm_count = 2000000, .reload_count = 0, .flags.auto_reload_on_alarm = true};
|
|
ret = gptimer_set_alarm_action(gpTimer, &alarmConfig);
|
|
if (ret != ESP_OK)
|
|
{
|
|
ESP_LOGE(TAG, "Failed to set gptimer alarm action: %s", esp_err_to_name(ret));
|
|
goto cleanupEnabledTimer;
|
|
}
|
|
|
|
BaseType_t taskCreated = xTaskCreate(timerEventTask, "timer_event_task", 4096, NULL, 10, NULL);
|
|
if (taskCreated != pdPASS)
|
|
{
|
|
ESP_LOGE(TAG, "Failed to create timer event task");
|
|
ret = ESP_ERR_NO_MEM;
|
|
goto cleanupEnabledTimer;
|
|
}
|
|
|
|
ESP_LOGI(TAG, "Beacon module initialized.");
|
|
goto exit;
|
|
|
|
cleanupEnabledTimer:
|
|
if (gpTimer)
|
|
{
|
|
gptimer_disable(gpTimer);
|
|
}
|
|
cleanupTimer:
|
|
if (gpTimer)
|
|
{
|
|
gptimer_del_timer(gpTimer);
|
|
gpTimer = NULL;
|
|
}
|
|
cleanupQueue:
|
|
if (timerEvtQueue)
|
|
{
|
|
vQueueDelete(timerEvtQueue);
|
|
timerEvtQueue = NULL;
|
|
}
|
|
exit:
|
|
return ret;
|
|
}
|