notif sonore et fin (1ere version)
This commit is contained in:
parent
434ede2480
commit
b7552e15ce
@ -10,12 +10,10 @@
|
||||
#include "bsp/esp-bsp.h"
|
||||
|
||||
/* Buffer for reading/writing to I2S driver. Same length as SPIFFS buffer and I2S buffer, for optimal read/write performance.
|
||||
Recording audio data path:
|
||||
I2S peripheral -> I2S buffer (DMA) -> App buffer (RAM) -> SPIFFS buffer -> External SPI Flash.
|
||||
Vice versa for playback. */
|
||||
External SPI Flash -> SPIFFS buffer -> App buffer (RAM) -> I2S buffer (DMA) -> I2S peripheral.
|
||||
*/
|
||||
#define BUFFER_SIZE (1024)
|
||||
#define SAMPLE_RATE (16000) // For recording
|
||||
#define DEFAULT_VOLUME (25)
|
||||
#define DEFAULT_VOLUME (50)
|
||||
|
||||
/* Globals */
|
||||
static const char *TAG = "audio";
|
||||
@ -35,22 +33,130 @@ typedef struct __attribute__((packed))
|
||||
uint8_t data[];
|
||||
} dumb_wav_header_t;
|
||||
|
||||
typedef struct {
|
||||
FILE *f;
|
||||
uint32_t data_offset;
|
||||
uint32_t data_size;
|
||||
} wav_ctx_t;
|
||||
#define AUDIO_CHUNK_SIZE 4096
|
||||
|
||||
bool wav_open(wav_ctx_t *ctx, const char *path)
|
||||
{
|
||||
ctx->f = fopen(path, "rb");
|
||||
if (!ctx->f) return false;
|
||||
|
||||
/* Skip RIFF header */
|
||||
fseek(ctx->f, 12, SEEK_SET);
|
||||
|
||||
uint32_t chunk_id, chunk_size;
|
||||
|
||||
while (fread(&chunk_id, 4, 1, ctx->f))
|
||||
{
|
||||
fread(&chunk_size, 4, 1, ctx->f);
|
||||
|
||||
if (chunk_id == 0x61746164) { // "data"
|
||||
ctx->data_offset = ftell(ctx->f);
|
||||
ctx->data_size = chunk_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
fseek(ctx->f, chunk_size, SEEK_CUR);
|
||||
}
|
||||
|
||||
fclose(ctx->f);
|
||||
return false;
|
||||
}
|
||||
void rewind_wav(wav_ctx_t *ctx)
|
||||
{
|
||||
fseek(ctx->f, ctx->data_offset, SEEK_SET);
|
||||
}
|
||||
#define AUDIO_CHUNK_SIZE 4096
|
||||
static void audio_task(void *arg)
|
||||
{
|
||||
ESP_LOGI(TAG,"Audio task");
|
||||
|
||||
esp_codec_dev_handle_t spk_codec_dev = bsp_audio_codec_speaker_init();
|
||||
assert(spk_codec_dev);
|
||||
|
||||
esp_codec_dev_set_out_vol(spk_codec_dev, DEFAULT_VOLUME);
|
||||
esp_codec_dev_set_out_mute(spk_codec_dev, false); // 🔑 CRITIQUE
|
||||
|
||||
const char *play_filename = "/littlefs/sounds/mixkit-clear-announce-tones-2861.wav";
|
||||
|
||||
uint8_t *wav_bytes = malloc(BUFFER_SIZE);
|
||||
assert(wav_bytes != NULL);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* ⏸️ Attend PLAY */
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
bool stop_requested = false;
|
||||
|
||||
while (!stop_requested) {
|
||||
ESP_LOGI(TAG,"On joue !");
|
||||
|
||||
FILE *play_file = fopen(play_filename, "rb");
|
||||
if (!play_file) {
|
||||
ESP_LOGE(TAG,"File not found");
|
||||
break;
|
||||
}
|
||||
|
||||
dumb_wav_header_t wav_header;
|
||||
if (fread(&wav_header, 1, sizeof(wav_header), play_file) != sizeof(wav_header)) {
|
||||
ESP_LOGE(TAG,"Header read failed");
|
||||
fclose(play_file);
|
||||
break;
|
||||
}
|
||||
|
||||
esp_codec_dev_sample_info_t fs = {
|
||||
.sample_rate = wav_header.sample_rate,
|
||||
.channel = wav_header.num_channels,
|
||||
.bits_per_sample = wav_header.bits_per_sample,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_codec_dev_open(spk_codec_dev, &fs));
|
||||
|
||||
uint32_t bytes_sent = 0;
|
||||
while (bytes_sent < wav_header.data_size) {
|
||||
size_t bytes_read = fread(wav_bytes, 1, BUFFER_SIZE, play_file);
|
||||
if (bytes_read == 0) break;
|
||||
|
||||
esp_codec_dev_write(spk_codec_dev, wav_bytes, bytes_read);
|
||||
bytes_sent += bytes_read;
|
||||
|
||||
vTaskDelay(1); // watchdog + scheduler
|
||||
}
|
||||
|
||||
esp_codec_dev_close(spk_codec_dev);
|
||||
fclose(play_file);
|
||||
|
||||
ESP_LOGI(TAG,"Fin du fichier");
|
||||
|
||||
if (ulTaskNotifyTake(pdTRUE, 0) > 0) {
|
||||
stop_requested = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(wav_bytes);
|
||||
}
|
||||
static void audio_task__(void *arg)
|
||||
{
|
||||
ESP_LOGE(TAG,"Audio task");
|
||||
esp_codec_dev_handle_t spk_codec_dev = bsp_audio_codec_speaker_init();
|
||||
assert(spk_codec_dev);
|
||||
esp_codec_dev_set_out_vol(spk_codec_dev, DEFAULT_VOLUME);
|
||||
|
||||
/* Pointer to a file that is going to be played */
|
||||
const char music_filename[] = "/littlefs/sounds/imperial_march.wav";
|
||||
const char music_filename[] = "/littlefs/sounds/mixkit-clear-announce-tones-2861.wav";
|
||||
const char *play_filename = music_filename;
|
||||
|
||||
while (1) {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
int16_t *wav_bytes = malloc(BUFFER_SIZE);
|
||||
assert(wav_bytes != NULL);
|
||||
|
||||
bool stop_requested = false;
|
||||
|
||||
while (!stop_requested){
|
||||
ESP_LOGE(TAG,"On joue !");
|
||||
/* Open WAV file */
|
||||
ESP_LOGI(TAG, "Playing file %s", play_filename);
|
||||
FILE *play_file = fopen(play_filename, "rb");
|
||||
@ -65,10 +171,10 @@ static void audio_task(void *arg)
|
||||
ESP_LOGW(TAG, "Error in reading file");
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "Number of channels: %" PRIu16 "", wav_header.num_channels);
|
||||
ESP_LOGI(TAG, "Bits per sample: %" PRIu16 "", wav_header.bits_per_sample);
|
||||
ESP_LOGI(TAG, "Sample rate: %" PRIu32 "", wav_header.sample_rate);
|
||||
ESP_LOGI(TAG, "Data size: %" PRIu32 "", wav_header.data_size);
|
||||
//ESP_LOGI(TAG, "Number of channels: %" PRIu16 "", wav_header.num_channels);
|
||||
//ESP_LOGI(TAG, "Bits per sample: %" PRIu16 "", wav_header.bits_per_sample);
|
||||
//ESP_LOGI(TAG, "Sample rate: %" PRIu32 "", wav_header.sample_rate);
|
||||
//ESP_LOGI(TAG, "Data size: %" PRIu32 "", wav_header.data_size);
|
||||
|
||||
esp_codec_dev_sample_info_t fs = {
|
||||
.sample_rate = wav_header.sample_rate,
|
||||
@ -83,11 +189,22 @@ static void audio_task(void *arg)
|
||||
size_t bytes_read_from_spiffs = fread(wav_bytes, 1, BUFFER_SIZE, play_file);
|
||||
esp_codec_dev_write(spk_codec_dev, wav_bytes, bytes_read_from_spiffs);
|
||||
bytes_send_to_i2s += bytes_read_from_spiffs;
|
||||
|
||||
/* ⭐ LIGNE CRITIQUE ⭐ */
|
||||
vTaskDelay(1); // laisse respirer IDLE + watchdog
|
||||
}
|
||||
ESP_LOGE(TAG,"On a fini le fichier");
|
||||
|
||||
fclose(play_file);
|
||||
free(wav_bytes);
|
||||
esp_codec_dev_close(spk_codec_dev);
|
||||
if(ulTaskNotifyTake(pdTRUE, 0)>0){
|
||||
stop_requested=true;
|
||||
break;
|
||||
};
|
||||
|
||||
}
|
||||
free(wav_bytes);
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
void playSound(void)
|
||||
@ -98,5 +215,10 @@ void playSound(void)
|
||||
}
|
||||
xTaskNotifyGive(audio_task_handle);
|
||||
}
|
||||
void stopSound(void){
|
||||
if (audio_task_handle) {
|
||||
xTaskNotifyGive(audio_task_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,2 +1,4 @@
|
||||
|
||||
void playSound(void);
|
||||
|
||||
void stopSound(void);
|
||||
|
||||
Binary file not shown.
@ -248,6 +248,8 @@ static void event_handler(lv_event_t *e)
|
||||
static lv_indev_t *keyboard;
|
||||
#endif
|
||||
|
||||
struct tm timeinfo;
|
||||
|
||||
void init_display_ihm(){
|
||||
|
||||
#if CONFIG_IDF_TARGET_LINUX
|
||||
@ -291,7 +293,6 @@ void init_display_ihm(){
|
||||
mainState.display_init=true;
|
||||
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
|
||||
@ -1306,73 +1307,22 @@ static void time_observer_cb(lv_observer_t *observer, lv_subject_t *subject)
|
||||
{
|
||||
LV_UNUSED(observer);
|
||||
|
||||
//ESP_LOGE(TAG,"################### On passe dans le cb time");
|
||||
lv_obj_t *parent = observer->target;
|
||||
struct tm *timeStruct=lv_subject_get_pointer(subject);
|
||||
|
||||
lv_obj_t *dateTimeObj = lv_observer_get_target_obj(observer);
|
||||
datetime_ctx_t *ctx = lv_obj_get_user_data(dateTimeObj);
|
||||
if (!ctx){
|
||||
ESP_LOGE(TAG,"################### Contexte non positionné");
|
||||
return;
|
||||
}
|
||||
lv_obj_t *hour = lv_obj_get_child_by_name(parent, "hour");
|
||||
lv_obj_t *minute = lv_obj_get_child_by_name(parent, "minute");
|
||||
|
||||
struct tm *t = (struct tm *)lv_subject_get_pointer(subject);
|
||||
if (!t){
|
||||
ESP_LOGE(TAG,"################### Pas de struct tm");
|
||||
return;
|
||||
}
|
||||
//ESP_LOGE(TAG,"################################# %d %d %d %02d:%02d", t->tm_wday, t->tm_mday, t->tm_mon, t->tm_hour, t->tm_min);
|
||||
int h = timeStruct->tm_hour;
|
||||
int m = timeStruct->tm_min;
|
||||
|
||||
char buf[4];
|
||||
bool refresh_date = false;
|
||||
bool refresh_time = false;
|
||||
char buf[3];
|
||||
|
||||
// ---- DATE ----
|
||||
if (t->tm_mday != ctx->last_day) {
|
||||
ctx->last_day = t->tm_mday;
|
||||
u8_to_2digits(buf, t->tm_mday);
|
||||
buf[2] = '/';
|
||||
buf[3] = '\0';
|
||||
//ESP_LOGE(TAG,"Jour %s",buf);
|
||||
lv_span_set_text(ctx->date_day, buf);
|
||||
refresh_date = true;
|
||||
}
|
||||
|
||||
if ((t->tm_mon + 1) != ctx->last_month) {
|
||||
ctx->last_month = t->tm_mon + 1;
|
||||
u8_to_2digits(buf, ctx->last_month);
|
||||
//ESP_LOGE(TAG,"Mois %s",buf);
|
||||
lv_span_set_text(ctx->date_month, buf);
|
||||
refresh_date = true;
|
||||
}
|
||||
|
||||
if (true || refresh_date) {
|
||||
lv_spangroup_refresh(ctx->date_group);
|
||||
}
|
||||
|
||||
// ---- TIME ----
|
||||
if (t->tm_hour != ctx->last_hour) {
|
||||
ctx->last_hour = t->tm_hour;
|
||||
u8_to_2digits(buf, t->tm_hour);
|
||||
//ESP_LOGE(TAG,"Heure %s",buf);
|
||||
lv_span_set_text(ctx->time_hour, buf);
|
||||
refresh_time = true;
|
||||
}
|
||||
|
||||
if (t->tm_min != ctx->last_min) {
|
||||
ctx->last_min = t->tm_min;
|
||||
buf[0] = ':';
|
||||
buf[1] = '0' + (t->tm_min / 10);
|
||||
buf[2] = '0' + (t->tm_min % 10);
|
||||
buf[3] = '\0';
|
||||
//ESP_LOGE(TAG,"Minutes %s",buf);
|
||||
lv_span_set_text(ctx->time_min, buf);
|
||||
refresh_time = true;
|
||||
}
|
||||
|
||||
if (refresh_time) {
|
||||
lv_spangroup_refresh(ctx->time_group);
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%02d", h);
|
||||
lv_label_set_text(hour, buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%02d", m);
|
||||
lv_label_set_text(minute, buf);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@ -1587,10 +1537,41 @@ void messageCardContent(lv_obj_t *cont_messages)
|
||||
lv_obj_set_width(txtMinuteur, LV_PCT(100));
|
||||
}
|
||||
|
||||
|
||||
lv_obj_t *btnStopNotif;
|
||||
static void minuteur_event_handler(lv_event_t *e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
// lv_obj_t *obj = (lv_obj_t *)lv_event_get_target(e);
|
||||
char *evtData = (char *)lv_event_get_user_data(e);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case LV_EVENT_CLICKED:
|
||||
send_event(EVT_FIN_MACHINE_STOP_NOTIF,NULL);
|
||||
lv_obj_delete(btnStopNotif);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void draw_minuteur(char *txt){
|
||||
lv_label_set_text(txtMinuteur, txt);
|
||||
}
|
||||
|
||||
void draw_minuteurStop(char *txt){
|
||||
lv_obj_t *ctr = lv_obj_get_parent(txtMinuteur);
|
||||
btnStopNotif = lv_btn_create(ctr);
|
||||
lv_obj_add_event_cb(btnStopNotif, minuteur_event_handler, LV_EVENT_ALL, NULL);
|
||||
lv_obj_t * label=lv_label_create(btnStopNotif);
|
||||
lv_label_set_text(label, "Stop !");
|
||||
lv_obj_center(label);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void backCb(lv_event_t * e)
|
||||
{
|
||||
@ -1718,6 +1699,7 @@ void messageCardContent(lv_obj_t *cont_messages)
|
||||
}
|
||||
void minuteurCb(lv_obj_t *base_obj)
|
||||
{
|
||||
send_event(EVT_FIN_MACHINE_STOP_NOTIF,NULL);
|
||||
drawMinuteur(base_obj);
|
||||
}
|
||||
void voletsCb(lv_obj_t *base_obj)
|
||||
@ -1820,22 +1802,45 @@ void messageCardContent(lv_obj_t *cont_messages)
|
||||
lv_span_set_text(month, "--");
|
||||
lv_style_set_text_font(lv_span_get_style(month), &super_malibu_80);
|
||||
|
||||
lv_obj_t *time = lv_spangroup_create(date_and_time);
|
||||
lv_obj_set_name(time, "time");
|
||||
lv_obj_set_id(time, "time");
|
||||
// lv_obj_add_style(time, &txtstyle, 0);
|
||||
lv_span_t *hourSpan = lv_spangroup_add_span(time);
|
||||
lv_span_set_text(hourSpan, "--");
|
||||
lv_style_set_text_font(lv_span_get_style(hourSpan), &super_malibu_80);
|
||||
lv_span_t *minute = lv_spangroup_add_span(time);
|
||||
lv_span_set_text(minute, ":--");
|
||||
lv_style_set_text_color(lv_span_get_style(minute), base);
|
||||
lv_style_set_line_color(lv_span_get_style(minute), accent);
|
||||
lv_style_set_text_font(lv_span_get_style(minute), &super_malibu_80);
|
||||
//lv_subject_add_observer_obj(&c->th, theme_observer_accent_span_cb, time, minute);
|
||||
datetime_ctx_init(date_and_time);
|
||||
lv_subject_add_observer_obj(&timeSubj, time_observer_cb, date_and_time, NULL);
|
||||
lv_obj_t *objTime = lv_obj_create(date_and_time);
|
||||
lv_obj_set_size(objTime, 250, LV_SIZE_CONTENT);
|
||||
lv_obj_clear_flag(objTime, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_set_style_bg_opa(objTime, LV_OPA_TRANSP, 0);
|
||||
lv_obj_set_style_border_width(objTime, 0, 0);
|
||||
|
||||
// Layout flex horizontal
|
||||
lv_obj_set_flex_flow(objTime, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_flex_align(
|
||||
objTime,
|
||||
LV_FLEX_ALIGN_SPACE_BETWEEN, // répartit les enfants
|
||||
LV_FLEX_ALIGN_CENTER, // align vertical
|
||||
LV_FLEX_ALIGN_CENTER
|
||||
);
|
||||
|
||||
// --- HEURES ---
|
||||
lv_obj_t *hour_lbl = lv_label_create(objTime);
|
||||
lv_obj_set_name(hour_lbl, "hour");
|
||||
lv_obj_set_style_text_font(hour_lbl, &super_malibu_80, 0);
|
||||
lv_obj_set_style_text_color(hour_lbl, lv_color_white(), 0);
|
||||
lv_label_set_text(hour_lbl, "--");
|
||||
|
||||
// --- DEUX-POINTS ---
|
||||
lv_obj_t *colon_lbl = lv_label_create(objTime);
|
||||
lv_obj_set_name(colon_lbl, "colon");
|
||||
lv_obj_set_style_text_font(colon_lbl, &super_malibu_80, 0);
|
||||
lv_obj_set_style_text_color(colon_lbl, base, 0);
|
||||
lv_label_set_text(colon_lbl, ":");
|
||||
|
||||
// --- MINUTES ---
|
||||
lv_obj_t *minute_lbl = lv_label_create(objTime);
|
||||
lv_obj_set_name(minute_lbl, "minute");
|
||||
lv_obj_set_style_text_font(minute_lbl, &super_malibu_80, 0);
|
||||
lv_obj_set_style_text_color(minute_lbl, lv_color_white(), 0);
|
||||
lv_label_set_text(minute_lbl, "--");
|
||||
|
||||
// Init datetime
|
||||
//datetime_ctx_init(date_and_time);
|
||||
lv_subject_add_observer_obj(&timeSubj, time_observer_cb, objTime, NULL);
|
||||
|
||||
lv_obj_t * subContent = lv_obj_create(info_area);
|
||||
lv_obj_set_flex_flow(subContent, LV_FLEX_FLOW_COLUMN);
|
||||
|
||||
@ -103,6 +103,11 @@ void traiteEvt(void *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
case IHM_EVT_MACHINE_TERMINEE:
|
||||
{
|
||||
draw_minuteurStop();
|
||||
}
|
||||
|
||||
case IHM_EVT_HAUTEUR_CUVE:
|
||||
{
|
||||
float hauteur = *(float *)evt->pvData;
|
||||
|
||||
@ -26,6 +26,7 @@ void drawHome();
|
||||
void draw_time(struct tm *dateHeure);
|
||||
void draw_tempExt(char *tempHumid);
|
||||
void draw_minuteur(char *txt);
|
||||
void draw_minuteurStop();
|
||||
void draw_temp(char *tempHumid);
|
||||
|
||||
void draw_meteo(meteo_event_payload_t *meteo);
|
||||
|
||||
@ -42,6 +42,7 @@ const char * domo_event_to_str(domo_events evt)
|
||||
case EVT_TEMP_EXT: return "TEMP_EXT";
|
||||
case EVT_TEMP_INT: return "TEMP_INT";
|
||||
case EVT_FIN_MACHINE: return "FIN_MACHINE";
|
||||
case EVT_FIN_MACHINE_STOP_NOTIF: return "FIN_MACHINE_STOP_NOTIF";
|
||||
default: return "EVT_UNKNOWN";
|
||||
}
|
||||
}
|
||||
@ -212,6 +213,16 @@ void send_event(domo_events evt, void* pDatas) {
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
playSound();
|
||||
#endif
|
||||
ihmEvt->eEventType = IHM_EVT_MACHINE_TERMINEE;
|
||||
ihmEvt->pvData = NULL;
|
||||
ihmEvt->bNeedToFreeData = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case EVT_FIN_MACHINE_STOP_NOTIF:{
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
stopSound();
|
||||
#endif
|
||||
free(ihmEvt); // rien à envoyer à l'IHM
|
||||
ihmEvt = NULL;
|
||||
break;
|
||||
|
||||
@ -15,7 +15,8 @@ typedef enum eIHMEvent_t{
|
||||
IHM_EVT_ETAT_MACHINE,
|
||||
IHM_EVT_HAUTEUR_CUVE,
|
||||
IHM_EVT_METEO_RECUE,
|
||||
IHM_EVT_TEMP_RECUE
|
||||
IHM_EVT_TEMP_RECUE,
|
||||
IHM_EVT_MACHINE_TERMINEE
|
||||
} eIHMEvent_t;
|
||||
|
||||
typedef struct IHM_EVENT
|
||||
@ -35,7 +36,8 @@ typedef enum domo_events{
|
||||
EVT_METEO_RECUE,
|
||||
EVT_TEMP_EXT,
|
||||
EVT_TEMP_INT,
|
||||
EVT_FIN_MACHINE
|
||||
EVT_FIN_MACHINE,
|
||||
EVT_FIN_MACHINE_STOP_NOTIF
|
||||
} domo_events;
|
||||
void startEvtManager();
|
||||
QueueHandle_t getIHMQueueHandle();
|
||||
|
||||
Binary file not shown.
BIN
main/medias/sounds/mixkit-clear-announce-tones-2861.wav
Normal file
BIN
main/medias/sounds/mixkit-clear-announce-tones-2861.wav
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user