Stereo DSP Amplifier
Table
| Function | GPIO | Net | Direction | Notes |
|---|---|---|---|---|
| I2S BCLK | 4 | I2S_BCLK | Output | 3.072 MHz for 48 kHz × 64 BCLK. |
| I2S LRCLK | 5 | I2S_LRCLK | Output | 48 kHz. |
| ADC DOUT | 6 | ADC_DOUT | Input | PCM1863 DOUT through 33Ω. |
| Amp SDIN | 7 | AMP_SDIN | Output | TAS5825M SDIN through 33Ω. |
| I2C SDA | 8 | I2C_SDA | Bidirectional | Shared PCM1863/TAS5825M bus. |
| I2C SCL | 9 | I2C_SCL | Output | 400 kHz target. |
| Amp FAULT | 10 | AMP_FAULT | Input | From TAS5825M GPIO0. |
| Amp PDN | 11 | AMP_PDN | Output | Pulled low in hardware; drive high only after init. |
| Amp warn/mute | 12 | AMP_WARN_OR_MUTE | Input/Output | From/to TAS5825M GPIO1 depending register config. |
| BOOT | 0 | ESP_BOOT | Input | BOOT switch/header. |
| RESET | EN | ESP_EN_RESET | Input | Reset switch/header/test point. |
| UART0 TX | 43 | ESP_TXD0 | Output | Debug header J6. |
| UART0 RX | 44 | ESP_RXD0 | Input | Debug header J6. |
platformio.iniIni
[env:esp32-s3-devkitc-1] platform = espressif32 board = esp32-s3-devkitc-1 framework = arduino monitor_speed = 115200 build_flags = -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 lib_deps =
src/main.cppCpp
#include <Arduino.h> #include <Wire.h> #include <WiFi.h> #include "driver/i2s_std.h" // Pin definitions from schematic static constexpr int PIN_I2S_BCLK = 4; static constexpr int PIN_I2S_LRCLK = 5; static constexpr int PIN_ADC_DOUT = 6; static constexpr int PIN_AMP_SDIN = 7; static constexpr int PIN_I2C_SDA = 8; static constexpr int PIN_I2C_SCL = 9; static constexpr int PIN_AMP_FAULT = 10; static constexpr int PIN_AMP_PDN = 11; static constexpr int PIN_AMP_WARN = 12; static constexpr uint32_t AUDIO_SAMPLE_RATE = 48000; static constexpr size_t AUDIO_FRAMES_PER_BLOCK = 64; static constexpr uint8_t PCM1863_ADDR = 0x4A; // verify AD strap/register map before production static constexpr uint8_t TAS5825M_ADDR = 0x4C; // ADR0 typical; verify with TI address table const char* WIFI_SSID = "YOUR_SSID"; const char* WIFI_PASSWORD = "YOUR_PASSWORD"; i2s_chan_handle_t i2s_tx = nullptr; i2s_chan_handle_t i2s_rx = nullptr; struct StereoFrame32 { int32_t left; int32_t right; }; bool i2cWrite8(uint8_t addr, uint8_t reg, uint8_t value) { Wire.beginTransmission(addr); Wire.write(reg); Wire.write(value); return Wire.endTransmission() == 0; } void initWiFi() { WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); Serial.print("WiFi connecting"); for (int i = 0; i < 20 && WiFi.status() != WL_CONNECTED; ++i) { delay(250); Serial.print('.'); } Serial.println(); if (WiFi.status() == WL_CONNECTED) { Serial.printf("WiFi connected: %s\n", WiFi.localIP().toString().c_str()); } else { Serial.println("WiFi not connected; continuing local audio path."); } } void initControlPins() { pinMode(PIN_AMP_PDN, OUTPUT); digitalWrite(PIN_AMP_PDN, LOW); // hold TAS5825M powered down until configured pinMode(PIN_AMP_FAULT, INPUT_PULLUP); pinMode(PIN_AMP_WARN, INPUT_PULLUP); } void initI2C() { Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL, 400000); } void initPCM1863() { // Minimal placeholder register writes; verify final register map/settings from TI PPC3 or datasheet. // MD0 is strapped low for I2C mode; ESP32 supplies BCLK/LRCLK as I2S master. i2cWrite8(PCM1863_ADDR, 0x00, 0xFE); // software reset register write per datasheet delay(5); // TODO: configure VINL1/VINR1 single-ended inputs, 24-bit I2S, slave PLL from BCLK/LRCLK. } void initTAS5825M() { digitalWrite(PIN_AMP_PDN, LOW); delay(10); // TODO: add TI TAS5825M register sequence generated from PPC3 for desired DSP/limiter/EQ. // Keep amp muted until clocks and configuration are valid. digitalWrite(PIN_AMP_PDN, HIGH); delay(10); } void initI2S() { i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); esp_err_t err = i2s_new_channel(&chan_cfg, &i2s_tx, &i2s_rx); if (err != ESP_OK) { Serial.printf("i2s_new_channel failed: %d\n", err); return; } i2s_std_config_t std_cfg = {}; std_cfg.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(AUDIO_SAMPLE_RATE); std_cfg.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_STEREO); std_cfg.gpio_cfg.mclk = I2S_GPIO_UNUSED; std_cfg.gpio_cfg.bclk = static_cast<gpio_num_t>(PIN_I2S_BCLK); std_cfg.gpio_cfg.ws = static_cast<gpio_num_t>(PIN_I2S_LRCLK); std_cfg.gpio_cfg.dout = static_cast<gpio_num_t>(PIN_AMP_SDIN); std_cfg.gpio_cfg.din = static_cast<gpio_num_t>(PIN_ADC_DOUT); std_cfg.gpio_cfg.invert_flags.mclk_inv = false; std_cfg.gpio_cfg.invert_flags.bclk_inv = false; std_cfg.gpio_cfg.invert_flags.ws_inv = false; err = i2s_channel_init_std_mode(i2s_tx, &std_cfg); if (err != ESP_OK) Serial.printf("i2s tx init failed: %d\n", err); err = i2s_channel_init_std_mode(i2s_rx, &std_cfg); if (err != ESP_OK) Serial.printf("i2s rx init failed: %d\n", err); i2s_channel_enable(i2s_rx); i2s_channel_enable(i2s_tx); } void processAudioBlock(StereoFrame32* frames, size_t count) { // Permanent DSP path placeholder: gain/mute/limiter/EQ/delay code goes here. static float gain = 0.5f; for (size_t i = 0; i < count; ++i) { int64_t l = static_cast<int64_t>(frames[i].left * gain); int64_t r = static_cast<int64_t>(frames[i].right * gain); frames[i].left = constrain(l, INT32_MIN, INT32_MAX); frames[i].right = constrain(r, INT32_MIN, INT32_MAX); } } void setup() { Serial.begin(115200); delay(500); Serial.println("Stereo DSP amplifier firmware starting"); initControlPins(); initI2C(); initPCM1863(); initI2S(); initTAS5825M(); initWiFi(); } void loop() { static StereoFrame32 audio[AUDIO_FRAMES_PER_BLOCK]; size_t bytes_read = 0; size_t bytes_written = 0; if (digitalRead(PIN_AMP_FAULT) == LOW) { Serial.println("TAS5825M FAULT asserted; muting amp"); digitalWrite(PIN_AMP_PDN, LOW); delay(100); return; } esp_err_t err = i2s_channel_read(i2s_rx, audio, sizeof(audio), &bytes_read, 20); if (err == ESP_OK && bytes_read > 0) { size_t frames = bytes_read / sizeof(StereoFrame32); processAudioBlock(audio, frames); i2s_channel_write(i2s_tx, audio, frames * sizeof(StereoFrame32), &bytes_written, 20); } if (WiFi.status() != WL_CONNECTED) { // Keep audio running even if Wi-Fi is unavailable; reconnect opportunistically later. } }
pio runpio run -t uploadpio device monitorPlatform & Toolchain
Pin Mapping
`platformio.ini`
Complete Starter Source — `src/main.cpp`
Build & Flash
Open Firmware Items