This commit is contained in:
@@ -18,6 +18,11 @@
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#define TAG "audio_router"
|
||||
|
||||
@@ -39,9 +44,11 @@ static volatile tone_mode_t s_mode = TONE_NONE;
|
||||
static volatile bool s_tone_idle = true;
|
||||
static TaskHandle_t s_task = NULL;
|
||||
|
||||
/* --- Gain numerique SCO (avec saturation) --- */
|
||||
#define SCO_PLAY_GAIN 4 /* downlink : PCM mobile -> ecouteur */
|
||||
#define SCO_MIC_GAIN 5 /* uplink : micro -> mobile */
|
||||
/* --- Gain numerique SCO (reglable a la volee, avec saturation) --- */
|
||||
static volatile int s_play_gain = 4; /* downlink : PCM mobile -> ecouteur */
|
||||
static volatile int s_mic_gain = 8; /* uplink : micro -> mobile (filtre) */
|
||||
static volatile bool s_mic_filter = true; /* passe-bande voix sur le micro */
|
||||
|
||||
static inline int16_t sat16(int32_t v)
|
||||
{
|
||||
if (v > 32767) return 32767;
|
||||
@@ -49,6 +56,47 @@ static inline int16_t sat16(int32_t v)
|
||||
return (int16_t)v;
|
||||
}
|
||||
|
||||
/* --- Biquad (RBJ) : passe-haut + passe-bas en serie sur le micro --- */
|
||||
typedef struct { float b0, b1, b2, a1, a2; float z1, z2; } biquad_t;
|
||||
static biquad_t s_hp, s_lp; /* HP 300 Hz, LP 3400 Hz @ 16 kHz */
|
||||
|
||||
static void biquad_set(biquad_t *f, float fc, float fs, float q, bool highpass)
|
||||
{
|
||||
float w0 = 2.0f * (float)M_PI * fc / fs;
|
||||
float c = cosf(w0), s = sinf(w0);
|
||||
float alpha = s / (2.0f * q);
|
||||
float a0;
|
||||
if (highpass) {
|
||||
f->b0 = (1.0f + c) / 2.0f; f->b1 = -(1.0f + c); f->b2 = (1.0f + c) / 2.0f;
|
||||
} else {
|
||||
f->b0 = (1.0f - c) / 2.0f; f->b1 = (1.0f - c); f->b2 = (1.0f - c) / 2.0f;
|
||||
}
|
||||
a0 = 1.0f + alpha;
|
||||
f->b0 /= a0; f->b1 /= a0; f->b2 /= a0;
|
||||
f->a1 = (-2.0f * c) / a0; f->a2 = (1.0f - alpha) / a0;
|
||||
f->z1 = f->z2 = 0.0f;
|
||||
}
|
||||
|
||||
static inline float biquad_run(biquad_t *f, float x) /* direct form II transposed */
|
||||
{
|
||||
float y = f->b0 * x + f->z1;
|
||||
f->z1 = f->b1 * x - f->a1 * y + f->z2;
|
||||
f->z2 = f->b2 * x - f->a2 * y;
|
||||
return y;
|
||||
}
|
||||
|
||||
static void mic_dsp_init(void)
|
||||
{
|
||||
biquad_set(&s_hp, 300.0f, 16000.0f, 0.707f, true);
|
||||
biquad_set(&s_lp, 3400.0f, 16000.0f, 0.707f, false);
|
||||
}
|
||||
|
||||
void audio_router_set_play_gain(int g) { if (g >= 0 && g <= 32) s_play_gain = g; }
|
||||
void audio_router_set_mic_gain(int g) { if (g >= 0 && g <= 32) s_mic_gain = g; }
|
||||
void audio_router_set_mic_filter(bool on) { s_mic_filter = on; }
|
||||
int audio_router_get_play_gain(void) { return s_play_gain; }
|
||||
int audio_router_get_mic_gain(void) { return s_mic_gain; }
|
||||
|
||||
/* --- Compteurs de diagnostic SCO (temporaires) --- */
|
||||
static volatile uint32_t s_dbg_in_bytes = 0; /* PCM recu du BT (feed_playback) */
|
||||
static volatile uint32_t s_dbg_cap = 0; /* frames micro capturees */
|
||||
@@ -96,7 +144,7 @@ static void tone_task(void *a)
|
||||
/* Frame complete : mono -> stereo (CVSD double pour 8k->16k) */
|
||||
int frames = 0;
|
||||
for (int i = 0; i < target && frames < FRAME; i++) {
|
||||
int16_t v = sat16((int32_t)sco_acc[i] * SCO_PLAY_GAIN);
|
||||
int16_t v = sat16((int32_t)sco_acc[i] * s_play_gain);
|
||||
buf[frames * 2] = v; buf[frames * 2 + 1] = v; frames++;
|
||||
if (!s_sco_msbc && frames < FRAME) {
|
||||
buf[frames * 2] = v; buf[frames * 2 + 1] = v; frames++;
|
||||
@@ -204,7 +252,15 @@ static void sco_mic_task(void *a)
|
||||
int n = hal_i2s_capture_read_frame(mono, FRAME, &e);
|
||||
if (n <= 0) { vTaskDelay(pdMS_TO_TICKS(5)); continue; }
|
||||
s_dbg_cap++;
|
||||
for (int i = 0; i < n; i++) mono[i] = sat16((int32_t)mono[i] * SCO_MIC_GAIN);
|
||||
/* Filtre passe-bande voix (HP 300 Hz + LP 3400 Hz) puis gain. */
|
||||
for (int i = 0; i < n; i++) {
|
||||
float x = (float)mono[i];
|
||||
if (s_mic_filter) {
|
||||
x = biquad_run(&s_hp, x);
|
||||
x = biquad_run(&s_lp, x);
|
||||
}
|
||||
mono[i] = sat16((int32_t)(x * (float)s_mic_gain));
|
||||
}
|
||||
if (s_sco_msbc) {
|
||||
/* 16 kHz direct : envoyer tel quel */
|
||||
xRingbufferSend(s_sco_cap_rb, mono, (size_t)(n * (int)sizeof(int16_t)), 0);
|
||||
@@ -223,6 +279,7 @@ static void sco_mic_task(void *a)
|
||||
void audio_router_sco_begin(bool msbc)
|
||||
{
|
||||
s_sco_msbc = msbc;
|
||||
mic_dsp_init(); /* (re)calcule les coeffs du filtre + reset l'etat */
|
||||
if (!s_sco_play_rb) s_sco_play_rb = xRingbufferCreate(SCO_RB_SIZE, RINGBUF_TYPE_BYTEBUF);
|
||||
if (!s_sco_cap_rb) s_sco_cap_rb = xRingbufferCreate(SCO_RB_SIZE, RINGBUF_TYPE_BYTEBUF);
|
||||
hal_i2s_capture_begin();
|
||||
|
||||
@@ -10,6 +10,13 @@ extern "C" {
|
||||
/* Create the tone task (idempotent). Call once after hal_i2s_init(). */
|
||||
void audio_router_init(void);
|
||||
|
||||
/* Gains SCO reglables a la volee (0..32) + filtre passe-bande voix sur le micro. */
|
||||
void audio_router_set_play_gain(int g); /* downlink : ecouteur */
|
||||
void audio_router_set_mic_gain(int g); /* uplink : micro -> mobile */
|
||||
void audio_router_set_mic_filter(bool on);
|
||||
int audio_router_get_play_gain(void);
|
||||
int audio_router_get_mic_gain(void);
|
||||
|
||||
/* Start a continuous 440 Hz dial tone (enables PA). */
|
||||
void audio_router_dialtone_start(void);
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "cli.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES audio_router
|
||||
)
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* cli.c — petit CLI serie (console UART0) pour regler les gains audio et le
|
||||
* filtre micro a la volee, sans recompiler. Coexiste avec les logs ESP_LOG.
|
||||
*/
|
||||
#include "cli.h"
|
||||
#include "audio_router.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TAG "cli"
|
||||
|
||||
static void handle(char *l)
|
||||
{
|
||||
if (strncmp(l, "gmic", 4) == 0) {
|
||||
audio_router_set_mic_gain(atoi(l + 4));
|
||||
ESP_LOGI(TAG, "gain micro = %d", audio_router_get_mic_gain());
|
||||
} else if (strncmp(l, "gspk", 4) == 0) {
|
||||
audio_router_set_play_gain(atoi(l + 4));
|
||||
ESP_LOGI(TAG, "gain ecouteur = %d", audio_router_get_play_gain());
|
||||
} else if (strncmp(l, "filt", 4) == 0) {
|
||||
int on = atoi(l + 4);
|
||||
audio_router_set_mic_filter(on != 0);
|
||||
ESP_LOGI(TAG, "filtre micro = %s", on ? "ON" : "OFF");
|
||||
} else if (strncmp(l, "status", 6) == 0) {
|
||||
ESP_LOGI(TAG, "gspk=%d gmic=%d",
|
||||
audio_router_get_play_gain(), audio_router_get_mic_gain());
|
||||
} else {
|
||||
ESP_LOGI(TAG, "cmds: gmic N | gspk N | filt 0/1 | status");
|
||||
}
|
||||
}
|
||||
|
||||
static void cli_task(void *a)
|
||||
{
|
||||
(void)a;
|
||||
char line[48];
|
||||
int pos = 0;
|
||||
ESP_LOGI(TAG, "CLI prete — gmic N / gspk N / filt 0/1 / status");
|
||||
for (;;) {
|
||||
int c = getchar();
|
||||
if (c == EOF) {
|
||||
vTaskDelay(pdMS_TO_TICKS(30));
|
||||
continue;
|
||||
}
|
||||
if (c == '\n' || c == '\r') {
|
||||
if (pos > 0) { line[pos] = '\0'; handle(line); pos = 0; }
|
||||
} else if (pos < (int)sizeof(line) - 1) {
|
||||
line[pos++] = (char)c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cli_start(void)
|
||||
{
|
||||
xTaskCreate(cli_task, "cli", 3072, NULL, 3, NULL);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Demarre un CLI serie (console UART) pour regler les gains/filtre a la volee :
|
||||
* gmic <0..32> gain micro (uplink)
|
||||
* gspk <0..32> gain ecouteur (downlink)
|
||||
* filt <0|1> filtre passe-bande voix sur le micro
|
||||
* status affiche les valeurs courantes
|
||||
*/
|
||||
void cli_start(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "app_main.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES nvs_flash config_store hal_es8388 hal_i2s audio_router slic_ks0835 dtmf dialer hook_monitor call_manager bt_hfp
|
||||
REQUIRES nvs_flash config_store hal_es8388 hal_i2s audio_router slic_ks0835 dtmf dialer hook_monitor call_manager bt_hfp cli
|
||||
)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "dialer.h"
|
||||
#include "call_manager.h"
|
||||
#include "bt_hfp.h"
|
||||
#include "cli.h"
|
||||
|
||||
static const char *TAG = "rtc_phone";
|
||||
|
||||
@@ -28,5 +29,6 @@ void app_main(void)
|
||||
/* Pile BT HFP-HF — NVS déjà initialisé par config_store_init().
|
||||
* call_manager_bt_event remplace le handler de log temporaire (Task 2). */
|
||||
ESP_ERROR_CHECK(bt_hfp_init(call_manager_bt_event));
|
||||
cli_start();
|
||||
ESP_LOGI(TAG, "call_manager + bt_hfp prets — appairer sur 'RTC_BL_PHONE'");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user