feat(audio): API capture micro RX hal_i2s
Ajoute hal_i2s_capture_begin/read_frame/end : scratch PSRAM, downmix L+R->mono, energie RMS. Sonde app_main valide le canal.
This commit is contained in:
@@ -9,6 +9,9 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2s_std.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define TAG "hal_i2s"
|
||||
|
||||
@@ -18,6 +21,10 @@
|
||||
static i2s_chan_handle_t s_spk_handle = NULL;
|
||||
static i2s_chan_handle_t s_mic_handle = NULL;
|
||||
|
||||
#define HAL_I2S_CAP_FRAME_SAMPLES 320
|
||||
#define HAL_I2S_CAP_IN_BYTES (HAL_I2S_CAP_FRAME_SAMPLES * 2 * (int)sizeof(int16_t))
|
||||
static int16_t *s_rx_scratch = NULL;
|
||||
|
||||
void hal_audio_pa_set(bool enable)
|
||||
{
|
||||
gpio_set_level(PLIP_PA_ENABLE, enable ? 1 : 0);
|
||||
@@ -95,3 +102,44 @@ esp_err_t hal_i2s_init(void)
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t hal_i2s_capture_begin(void)
|
||||
{
|
||||
if (!s_mic_handle) {
|
||||
ESP_LOGE(TAG, "capture_begin: pas de canal RX");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (s_rx_scratch) return ESP_OK; /* idempotent */
|
||||
s_rx_scratch = heap_caps_malloc(HAL_I2S_CAP_IN_BYTES, MALLOC_CAP_SPIRAM);
|
||||
if (!s_rx_scratch) s_rx_scratch = malloc(HAL_I2S_CAP_IN_BYTES);
|
||||
if (!s_rx_scratch) return ESP_ERR_NO_MEM;
|
||||
ESP_LOGI(TAG, "capture_begin: pret (full-duplex, TX actif)");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int hal_i2s_capture_read_frame(int16_t *mono_out, int n_samples, int64_t *rms_sq_out)
|
||||
{
|
||||
if (!s_rx_scratch || !s_mic_handle) return -1;
|
||||
size_t bytes_read = 0;
|
||||
esp_err_t ret = i2s_channel_read(s_mic_handle, s_rx_scratch,
|
||||
HAL_I2S_CAP_IN_BYTES, &bytes_read,
|
||||
pdMS_TO_TICKS(100));
|
||||
if (ret != ESP_OK || bytes_read == 0) return 0; /* timeout */
|
||||
int n = (int)(bytes_read / (2 * sizeof(int16_t)));
|
||||
if (n > n_samples) n = n_samples;
|
||||
int64_t rms_sq = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
int32_t l = s_rx_scratch[i * 2];
|
||||
int32_t r = s_rx_scratch[i * 2 + 1];
|
||||
int16_t mono = (int16_t)((l + r) / 2);
|
||||
mono_out[i] = mono;
|
||||
rms_sq += (int64_t)mono * mono;
|
||||
}
|
||||
if (rms_sq_out) *rms_sq_out = (n > 0) ? rms_sq / n : 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
void hal_i2s_capture_end(void)
|
||||
{
|
||||
if (s_rx_scratch) { free(s_rx_scratch); s_rx_scratch = NULL; }
|
||||
}
|
||||
|
||||
@@ -21,6 +21,12 @@ i2s_chan_handle_t hal_i2s_mic_handle(void);
|
||||
/* Enable/disable the speaker power amplifier (GPIO21, active HIGH). */
|
||||
void hal_audio_pa_set(bool enable);
|
||||
|
||||
/* Microphone capture (RX). capture_begin allocates a scratch buffer; read_frame
|
||||
* reads one 20 ms frame, downmixes L+R to mono, and reports mean energy. */
|
||||
esp_err_t hal_i2s_capture_begin(void);
|
||||
int hal_i2s_capture_read_frame(int16_t *mono_out, int n_samples, int64_t *rms_sq_out);
|
||||
void hal_i2s_capture_end(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+10
-5
@@ -17,14 +17,19 @@ void app_main(void)
|
||||
* avec la tache tone (i2s_channel_write qui tourne en parallele). */
|
||||
ESP_ERROR_CHECK(slic_init());
|
||||
audio_router_init();
|
||||
audio_router_dialtone_start();
|
||||
ESP_LOGI(TAG, "tonalite de numerotation demarree (combine decroche pour ecouter)");
|
||||
/* Sonde temporaire de polarite hook (a retirer en Task 6). */
|
||||
/* Sonde RMS micro (valide chemin LIN2/RIN2) — a retirer en Task 6. */
|
||||
ESP_ERROR_CHECK(hal_i2s_capture_begin());
|
||||
int16_t cap[320];
|
||||
for (int i = 0; i < 20; i++) {
|
||||
ESP_LOGI(TAG, "HOOK sonde: offhook=%d (niveau brut SHK)", (int)slic_is_offhook());
|
||||
int64_t rms_sq = 0;
|
||||
int got = hal_i2s_capture_read_frame(cap, 320, &rms_sq);
|
||||
ESP_LOGI(TAG, "MIC sonde: offhook=%d frame=%d rms_sq=%lld",
|
||||
(int)slic_is_offhook(), got, (long long)rms_sq);
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
}
|
||||
ESP_LOGI(TAG, "boot OK — Phase 3 Task 1 SLIC KS0835");
|
||||
audio_router_dialtone_start();
|
||||
ESP_LOGI(TAG, "tonalite de numerotation demarree (combine decroche pour ecouter)");
|
||||
ESP_LOGI(TAG, "boot OK — Phase 3 Task 2 capture micro hal_i2s");
|
||||
while (true) {
|
||||
ESP_LOGI(TAG, "heartbeat");
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
|
||||
Reference in New Issue
Block a user