Files

164 lines
3.3 KiB
C

#include <stdint.h>
#include <stdbool.h>
#include "esp_log.h"
#include "driver/ledc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#define PIN_BEEP 25
#define LEDC_TIMER LEDC_TIMER_0
#define LEDC_MODE LEDC_LOW_SPEED_MODE
#define LEDC_CHANNEL LEDC_CHANNEL_0
#define LEDC_DUTY_RES LEDC_TIMER_13_BIT
#define LEDC_DUTY 4095
static const char *TAG = "audio";
enum {
AUDIO_SHORT = 1,
AUDIO_ALARM,
AUDIO_CANCEL,
};
static QueueHandle_t s_q;
static TaskHandle_t s_task;
static bool s_inited;
static void tone_on(uint32_t hz)
{
ledc_set_freq(LEDC_MODE, LEDC_TIMER, hz);
ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, LEDC_DUTY);
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
}
static void tone_off(void)
{
ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, 0);
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
}
static bool drain_cancel(void)
{
int msg;
while (xQueueReceive(s_q, &msg, 0) == pdTRUE) {
if (msg == AUDIO_CANCEL) {
return true;
}
}
return false;
}
static void play_short(void)
{
tone_on(2000);
vTaskDelay(pdMS_TO_TICKS(100));
tone_off();
}
static void play_alarm(void)
{
for (int i = 0; i < 10; i++) {
if (drain_cancel()) {
tone_off();
return;
}
tone_on(2000);
TickType_t t0 = xTaskGetTickCount();
while ((xTaskGetTickCount() - t0) < pdMS_TO_TICKS(500)) {
if (drain_cancel()) {
tone_off();
return;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
tone_off();
t0 = xTaskGetTickCount();
while ((xTaskGetTickCount() - t0) < pdMS_TO_TICKS(250)) {
if (drain_cancel()) {
return;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
}
static void audio_task(void *arg)
{
(void)arg;
int msg;
for (;;) {
if (xQueueReceive(s_q, &msg, portMAX_DELAY) != pdTRUE) {
continue;
}
if (msg == AUDIO_SHORT) {
play_short();
} else if (msg == AUDIO_ALARM) {
play_alarm();
} else if (msg == AUDIO_CANCEL) {
tone_off();
}
}
}
static void post(int msg)
{
if (s_q == NULL) {
return;
}
xQueueSend(s_q, &msg, 0);
}
void autofilm_audio_task(void *arg)
{
audio_task(arg);
}
void hal_audio_init(void)
{
if (s_inited) {
return;
}
ledc_timer_config_t tcfg = {
.speed_mode = LEDC_MODE,
.duty_resolution = LEDC_DUTY_RES,
.timer_num = LEDC_TIMER,
.freq_hz = 2000,
.clk_cfg = LEDC_AUTO_CLK,
};
ledc_timer_config(&tcfg);
ledc_channel_config_t ccfg = {
.gpio_num = PIN_BEEP,
.speed_mode = LEDC_MODE,
.channel = LEDC_CHANNEL,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER,
.duty = 0,
.hpoint = 0,
};
ledc_channel_config(&ccfg);
tone_off();
s_q = xQueueCreate(8, sizeof(int));
if (s_task == NULL) {
xTaskCreate(audio_task, "audio", 3072, NULL, 2, &s_task);
}
s_inited = true;
ESP_LOGI(TAG, "init beep pin=%d LEDC", PIN_BEEP);
}
void hal_audio_beep_short(void)
{
post(AUDIO_SHORT);
}
void hal_audio_alarm_complete(void)
{
post(AUDIO_ALARM);
}
void hal_audio_alarm_cancel(void)
{
post(AUDIO_CANCEL);
}