164 lines
3.3 KiB
C
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);
|
|
}
|