Skip to main content
Version: FILS English

DIY Embedded Music Player

A hardware digital audio player built on STM32 using Rust and internal DAC audio processing.

info

Author: Marioara Alexandru
GitHub Project Link: https://github.com/UPB-PMRust-Students/fils-project-2026-StrumfoAlex

Description

This project implements a standalone, fully functional digital music player. It reads audio files from a MicroSD card and outputs sound using the microcontroller's internal DAC (Digital-to-Analog Converter) combined with an external PAM8403 analog amplifier. The system features a graphical interface on an OLED display and allows hardware control via a rotary encoder, IR remote, and tactile buttons.

Motivation

Music is an essential part of my daily life, and listening to it is a habit I enjoy every single day. This inspired me to build a digital music player from scratch, turning an everyday activity into a complex engineering challenge. From a technical standpoint, this project allows me to combine multiple communication protocols (SPI, I2C) and core microcontroller peripherals (Timers, DMA, DAC) into a single, cohesive product. Instead of using off-the-shelf "smart" modules that do the decoding automatically, I want the STM32 to handle the raw data stream and precisely output it through the internal DAC. This forces me to step out of my comfort zone and tackle real-time asynchronous data streaming using Rust's embassy framework.

Architecture

The system architecture is centralized around the STM32 microcontroller which handles data fetching, UI updates, and audio signal generation.

                    [POWER & DEBUGGING SECTION]

+-----------------------+ +--------------------------+
| Host PC | | Host PC |
| (USB Power 5V) | | (Serial Debugging) |
+-----------+-----------+ +------------+-------------+
| ^
| (5V & 3.3V) | [UART / USB]
v v
+----------------------------------------------------------------+
| |
| NUCLEO STM32U545RE-Q |
| (Main Microcontroller) |
| |
+-------+---------------+---------------+---------------+--------+
| | | |
[SPI] [I2C] [GPIO / EXTI] [DAC]
| | | |
v v v v
+---------------+ +-------------+ +-------------+ +--------------+
| | | | | | | |
| MicroSD Card | | 0.96" OLED | | Buttons & | | PAM8403 |
| Module | | Display | | Rotary Enc. | | Amplifier |
| | | | | | | |
+---------------+ +-------------+ +-------------+ +-------+------+
(Stores Audio) (UI/Visuals) (User Controls) |
| [Analog]
v
+--------------+
| |
| 52mm 4 Ohm |
| 5W Speaker |
+--------------+

The system architecture revolves around the STM32U545RE microcontroller:

  1. Input: Data is read asynchronously from the MicroSD card via SPI. User input is captured via a Rotary Encoder, an IR sensor (for remote control), and tactile buttons.
  2. Processing: The STM32 parses the WAV file format and feeds the raw PCM audio data into memory buffers.
  3. Output: The data is pushed via DMA to the internal DAC to generate an analog audio signal. This signal is then boosted by a PAM8403 amplifier to drive the speaker. The UI state (current song, volume) is updated on the I2C OLED display.

Log

  • Week 1 - 9: Finalized component list, established architecture using the internal DAC to avoid I2S complexity, and set up the documentation website.
  • Week 9 - 11: Assembling the hardware circuit. Initializing the code on the board and verifying the components. Making the KiCad schematics.
  • Week 11 - 14: Finishing the code and testing each function of the project. Making short ajustment in the hardware for a better performing. Finishing the documentation website.

Hardware

The core of the digital audio player is the STM32U545RE microcontroller, which handles file reading, user interface, and audio signal generation. Storage is managed via a MicroSD card module communicating over the SPI protocol, while visual feedback is provided by an SSD1306 OLED display connected via I2C. User input for navigating the playlist and controlling playback is handled through a rotary encoder.

For the audio output, the internal DAC of the STM32 generates an 8-bit PCM raw signal. Because this signal includes a DC offset of approximately 1.6V, a 10µF electrolytic capacitor is placed in series to act as an AC coupling filter, blocking the direct current and allowing only the audio waveform to pass. The filtered, AC-coupled signal is then routed directly into the PAM8403 Class-D audio amplifier for playback.

For the audio output, the internal DAC of the STM32 generates an 8-bit PCM raw signal. Because this signal includes a DC offset of approximately 1.6V, a 10µF electrolytic capacitor is placed in series to act as an AC coupling filter, blocking the direct current and allowing only the audio waveform to pass. Hardware

Schematics

Schematics

Bill of Materials

DeviceUsagePrice
STM32 Nucleo-U545REMain microcontroller (Brain)126 RON
PAM8403 AmplifierAmplifies the analog signal from the STM32 DAC~6 RON
4 Ohm SpeakerAudio output~8 RON
MicroSD Card ModuleSPI storage for music files~5 RON
0.96" OLED DisplayI2C UI Display~17 RON
IR Receiver & RemoteWireless user interface control~7 RON
Rotary Encoder & ButtonsPhysical user interface controls~15 RON

Software

The project is built entirely in Rust (no_std) utilizing the asynchronous Embassy framework.

LibraryDescriptionUsage
embassy-stm32Hardware Abstraction LayerControls peripherals (SPI, I2C, DAC, DMA, Timers, GPIO)
embassy-executorAsync Execution EnvironmentManages asynchronous tasks and threads
embassy-timeTime ManagementHandles delays and timing (e.g., Timer::after_millis)
embedded-sdmmcFAT32 File SystemReading WAV files from the SD Card
ssd1306Display DriverControlling the OLED screen
embedded-graphicsGraphics LibraryRenders text and UI elements on the display
defmtLogging FrameworkSends fast, low-overhead debug messages via USB
panic-probeDebugging UtilityCaptures and reports critical errors (panics)
infraredIR DecodingDecodes NEC protocol pulses from the remote control
  1. Rust Embassy Documentation
  2. Embedded Graphics
  3. Crates.io - Storage
  4. Reading .WAV files