Stereo DSP Amplifier


Created 4 project docs

Design Notes — Stereo DSP Amplifier

View Document

Complete schematic and BOM draft created for the requested signal chain. PCB placement and routing were intentionally not performed.

Firmware Starter — ESP32-S3-WROOM-1-N16R8

View Document

MCU module: ESP32-S3-WROOM-1-N16R8 Framework: Arduino-ESP32 3.x under PlatformIO

Board Bring-Up Plan — Stereo DSP Amplifier

View Document

Current-limited bench supply capable of 18 V. Multimeter, oscilloscope, audio source, 4 Ω dummy loads/speakers, UART/USB-serial adapter if u...

Regulatory FCC/CE Notes — Stereo DSP Amplifier

View Document

Draft design-stage notes. This board includes an ESP32-S3-WROOM-1-N16R8 Wi-Fi/BLE module, so wireless regulatory integration requirements ap...
Implemented the complete schematic and BOM draft for the stereo DSP amplifier, without PCB placement or routing. Electrical ERC is clean; the remaining BOM/manufacturing issue is that generic passives, inductors, test points, and attenuation headers still need final orderable MPN/package selections before manufacturing.
Created/updated project files:
Open items:
  • Select final MPNs/packages for generic resistors, capacitors, inductors, test points, and jumper headers.
  • Verify the PCM1863DBT footprint pitch against TI’s DBT TSSOP-30 land pattern before layout.
  • Add final TI register configurations for PCM1863 and TAS5825M firmware.
Suggested next steps:
  1. Finalize passive/inductor/test-point MPNs to make the BOM manufacturing-ready.
  2. Review the schematic visually for signal-flow readability.
  3. Set the 150 mm × 150 mm four-layer board, stackup, and placement constraints.
  4. Start PCB placement only after you approve the schematic.
Finalize BOM and placement
Finalize passive MPNs
Verify PCM1863 footprint
Arrange schematic readability
Start PCB placement
Explain remaining risks

Firmware Starter — ESP32-S3-WROOM-1-N16R8
Platform & Toolchain
  • MCU module: ESP32-S3-WROOM-1-N16R8
  • Framework: Arduino-ESP32 3.x under PlatformIO
  • Purpose: bring up I2C configuration, I2S audio passthrough/DSP placeholder, Wi-Fi control scaffold, TAS5825M FAULT/PDN handling.
Pin Mapping

Table


FunctionGPIONetDirectionNotes
I2S BCLK4I2S_BCLKOutput3.072 MHz for 48 kHz × 64 BCLK.
I2S LRCLK5I2S_LRCLKOutput48 kHz.
ADC DOUT6ADC_DOUTInputPCM1863 DOUT through 33Ω.
Amp SDIN7AMP_SDINOutputTAS5825M SDIN through 33Ω.
I2C SDA8I2C_SDABidirectionalShared PCM1863/TAS5825M bus.
I2C SCL9I2C_SCLOutput400 kHz target.
Amp FAULT10AMP_FAULTInputFrom TAS5825M GPIO0.
Amp PDN11AMP_PDNOutputPulled low in hardware; drive high only after init.
Amp warn/mute12AMP_WARN_OR_MUTEInput/OutputFrom/to TAS5825M GPIO1 depending register config.
BOOT0ESP_BOOTInputBOOT switch/header.
RESETENESP_EN_RESETInputReset switch/header/test point.
UART0 TX43ESP_TXD0OutputDebug header J6.
UART0 RX44ESP_RXD0InputDebug header J6.
platformio.ini

Ini


[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 =
Complete Starter Source — src/main.cpp

Cpp


#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.
  }
}
Build & Flash
  1. Hold BOOT (SW2), tap RESET (SW1), then release BOOT to enter bootloader if needed.
  2. Build: pio run
  3. Flash: pio run -t upload
  4. Monitor: pio device monitor
Open Firmware Items
  • Replace placeholder PCM1863/TAS5825M register writes with final TI register sequences.
  • Add real biquad EQ, high-pass, delay, gain/mute, limiter, and preset storage.
  • Confirm I2C addresses after measuring/reading actual devices on the assembled board.
  • Platform & Toolchain

  • Pin Mapping

  • `platformio.ini`

  • Complete Starter Source — `src/main.cpp`

  • Build & Flash

  • Open Firmware Items