mirror of
https://github.com/markqvist/RNode_Firmware.git
synced 2026-04-27 14:30:33 +00:00
Add SPM1423 PDM microphone driver, fix speaker I2S port
Microphone on I2S_NUM_0 (PDM hardware constraint), speaker moved to I2S_NUM_1. Both init at boot, shut down before deep sleep. Mic provides raw audio read and RMS level measurement. Boot beep disabled (speaker confirmed working).
This commit is contained in:
parent
8dd50ac901
commit
c31b1908a7
3 changed files with 88 additions and 4 deletions
82
Microphone.h
Normal file
82
Microphone.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
// SPM1423 PDM Microphone Driver — Minimal audio input for T-Watch Ultra
|
||||
// PDM input on I2S_NUM_0 (hardware constraint for PDM on ESP32-S3)
|
||||
|
||||
#ifndef MICROPHONE_H
|
||||
#define MICROPHONE_H
|
||||
|
||||
#if BOARD_MODEL == BOARD_TWATCH_ULT
|
||||
|
||||
#include "driver/i2s.h"
|
||||
|
||||
#define MIC_CLK_PIN 17 // PDM clock (WS pin in I2S terms)
|
||||
#define MIC_DAT_PIN 18 // PDM data input
|
||||
#define MIC_I2S_PORT I2S_NUM_0 // PDM only works on I2S0
|
||||
#define MIC_SAMPLE_RATE 16000 // 16kHz max for PDM mic
|
||||
#define MIC_BUF_SIZE 1024
|
||||
|
||||
static bool mic_ready = false;
|
||||
|
||||
bool mic_init() {
|
||||
i2s_config_t i2s_config = {};
|
||||
i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM);
|
||||
i2s_config.sample_rate = MIC_SAMPLE_RATE;
|
||||
i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
|
||||
i2s_config.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT;
|
||||
i2s_config.communication_format = I2S_COMM_FORMAT_STAND_PCM_SHORT;
|
||||
i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1;
|
||||
i2s_config.dma_buf_count = 6;
|
||||
i2s_config.dma_buf_len = 512;
|
||||
i2s_config.use_apll = true;
|
||||
|
||||
i2s_pin_config_t pin_config = {};
|
||||
pin_config.bck_io_num = I2S_PIN_NO_CHANGE;
|
||||
pin_config.ws_io_num = MIC_CLK_PIN;
|
||||
pin_config.data_out_num = I2S_PIN_NO_CHANGE;
|
||||
pin_config.data_in_num = MIC_DAT_PIN;
|
||||
pin_config.mck_io_num = I2S_PIN_NO_CHANGE;
|
||||
|
||||
if (i2s_driver_install(MIC_I2S_PORT, &i2s_config, 0, NULL) != ESP_OK) {
|
||||
return false;
|
||||
}
|
||||
if (i2s_set_pin(MIC_I2S_PORT, &pin_config) != ESP_OK) {
|
||||
i2s_driver_uninstall(MIC_I2S_PORT);
|
||||
return false;
|
||||
}
|
||||
|
||||
mic_ready = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void mic_end() {
|
||||
if (mic_ready) {
|
||||
i2s_driver_uninstall(MIC_I2S_PORT);
|
||||
mic_ready = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Read raw audio samples into buffer. Returns bytes read.
|
||||
size_t mic_read(int16_t *buf, size_t samples) {
|
||||
if (!mic_ready) return 0;
|
||||
size_t bytes_read = 0;
|
||||
i2s_read(MIC_I2S_PORT, buf, samples * sizeof(int16_t), &bytes_read, portMAX_DELAY);
|
||||
return bytes_read / sizeof(int16_t);
|
||||
}
|
||||
|
||||
// Get current audio level (RMS of a short sample). Returns 0-32767.
|
||||
uint16_t mic_level() {
|
||||
if (!mic_ready) return 0;
|
||||
|
||||
int16_t buf[256];
|
||||
size_t samples = mic_read(buf, 256);
|
||||
if (samples == 0) return 0;
|
||||
|
||||
uint64_t sum_sq = 0;
|
||||
for (size_t i = 0; i < samples; i++) {
|
||||
int32_t s = buf[i];
|
||||
sum_sq += s * s;
|
||||
}
|
||||
return (uint16_t)sqrt((double)sum_sq / samples);
|
||||
}
|
||||
|
||||
#endif // BOARD_MODEL == BOARD_TWATCH_ULT
|
||||
#endif // MICROPHONE_H
|
||||
|
|
@ -29,8 +29,9 @@
|
|||
SensorBHI260AP *bhi260 = NULL;
|
||||
bool bhi260_ready = false;
|
||||
|
||||
// MAX98357A I2S speaker
|
||||
// MAX98357A I2S speaker + SPM1423 PDM microphone
|
||||
#include "Speaker.h"
|
||||
#include "Microphone.h"
|
||||
|
||||
// CST9217 capacitive touch panel
|
||||
#include <touch/TouchDrvCST92xx.h>
|
||||
|
|
@ -307,9 +308,9 @@ void setup() {
|
|||
attachInterrupt(TP_INT, touch_isr, FALLING);
|
||||
}
|
||||
|
||||
// Init speaker (BLDO2 already enabled by PMU init)
|
||||
// Init speaker (BLDO2 already enabled by PMU init) and microphone
|
||||
speaker_init();
|
||||
if (speaker_ready) speaker_beep(); // Boot audio feedback
|
||||
mic_init();
|
||||
|
||||
// BHI260AP init deferred — firmware upload takes ~10s at 1MHz I2C
|
||||
// and blocks serial communication during boot. Will be initialized
|
||||
|
|
@ -2078,6 +2079,7 @@ void twatch_enter_deep_sleep(bool beacon_timer) {
|
|||
}
|
||||
|
||||
// 1. Shut down audio and display before closing buses
|
||||
mic_end();
|
||||
speaker_end();
|
||||
#if HAS_DISPLAY
|
||||
co5300_sleep();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
#define SPK_BCLK I2S_BCLK
|
||||
#define SPK_WCLK I2S_WCLK
|
||||
#define SPK_DOUT I2S_DOUT
|
||||
#define SPK_I2S_PORT I2S_NUM_0
|
||||
#define SPK_I2S_PORT I2S_NUM_1 // I2S_NUM_0 reserved for PDM microphone
|
||||
#define SPK_SAMPLE_RATE 16000
|
||||
#define SPK_TONE_BUF_SIZE 512
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue