|
| 1 | +# DJ Controller |
| 2 | + |
| 3 | +A standalone two-deck DJ controller running on the STM32U5, written in Rust. |
| 4 | + |
| 5 | +:::info |
| 6 | + |
| 7 | +**Author**: Stefan Răileanu \ |
| 8 | +**GitHub Project Link**: [link_to_github](https://github.com/UPB-PMRust-Students/acs-project-2026-raylaj23) |
| 9 | + |
| 10 | +::: |
| 11 | + |
| 12 | +## Description |
| 13 | + |
| 14 | +A fully standalone two-deck DJ controller built on the STM32U5 |
| 15 | +microcontroller, written in Rust using the Embassy async embedded framework. |
| 16 | +The board reads WAV audio files from an SD card and allows real-time mixing |
| 17 | +between two decks. |
| 18 | + |
| 19 | +Each deck has its own jog wheel (a rotary encoder with a disc on top), three |
| 20 | +EQ knobs (bass, mid, high), a low and high-pass filter, a volume knob, and |
| 21 | +dedicated buttons for Play/Pause, Cue, Loop, Sync, and Headphone Cue Select. |
| 22 | +Two shared controls: a crossfader and a headphone volume knob. Each deck has |
| 23 | +its own display showing track name, position, BPM and the loop, or the SD card |
| 24 | +file list when in browse mode. |
| 25 | + |
| 26 | +Audio leaves the STM32U5 through its **internal DAC**: the main mix goes out via a 3.5mm |
| 27 | +AUX jack into a **Marshall Middleton** speaker (using its built-in 50W amplifier), and the |
| 28 | +cued deck is routed through a **TPA6132 headphone amplifier** to the headphone output. |
| 29 | + |
| 30 | +## Motivation |
| 31 | + |
| 32 | +I'm a techno enthusiast and wanted a project that combines the technical |
| 33 | +skills I'm learning with a hobby I already love. |
| 34 | + |
| 35 | +## Architecture |
| 36 | + |
| 37 | +The system is organized around four main architectural components: an **Input |
| 38 | +Handler** that aggregates all user controls, an **Audio Engine** that |
| 39 | +streams, processes, and mixes audio in real time, a **Display Driver** that |
| 40 | +renders per-deck UI, and an **Output Stage** that splits the final audio into |
| 41 | +a main mix and a separate cue channel. |
| 42 | + |
| 43 | +* **Input Handler** — reads rotary encoders via GPIO interrupts, |
| 44 | +potentiometers via ADC + DMA, and buttons via GPIO. Maintains a per-deck |
| 45 | +state machine that distinguishes jog-wheel pitch-bend (rotate only), |
| 46 | +scrubbing (press + rotate), and mode switching (short press toggles between |
| 47 | +play and browse). |
| 48 | + |
| 49 | +* **Audio Engine** — streams two WAV files from the SD card simultaneously over SPI |
| 50 | ++ DMA. Each deck runs an independent DSP chain (3-band EQ + LPF + HPF as biquad |
| 51 | +filters), then pitch/seek/loop/sync logic adjusts the read pointer or sample rate, |
| 52 | +and a final mixer applies per-deck volume and the crossfader before pushing samples |
| 53 | +to the STM32U5's internal DAC. |
| 54 | + |
| 55 | +* **Display Driver** — receives playback state from the Audio Engine and UI |
| 56 | +navigation events from the Input Handler. In play mode it renders track name, |
| 57 | +position, BPM, and loop/sync state. In browse mode it renders a scrollable list of |
| 58 | +WAV files from the SD card. |
| 59 | + |
| 60 | +* **Output Stage** — the STM32U5's internal DAC produces two analog channels: the main |
| 61 | +mix is sent over a 3.5mm AUX jack into a Marshall Middleton speaker (which has its own |
| 62 | +built-in 50W amplifier), and the cue channel is sent through a TPA6132 headphone |
| 63 | +amplifier to the headphones (used by the DJ to prepare the next transition). |
| 64 | + |
| 65 | + |
| 66 | + |
| 67 | +## Log |
| 68 | + |
| 69 | +### Week 21 - 27 April |
| 70 | +* Completed the documentation and ordered the hardware parts |
| 71 | + |
| 72 | +### Week 28 April - 4 May |
| 73 | +* Connected all the parts to stm |
| 74 | + |
| 75 | +### Week 5 - 11 May |
| 76 | + |
| 77 | +### Week 12 - 18 May |
| 78 | + |
| 79 | +### Week 19 - 25 May |
| 80 | + |
| 81 | +## Hardware |
| 82 | + |
| 83 | +The controller is built around the **STM32U5 Nucleo board**, which handles SD streaming, |
| 84 | +DSP, display output, and input reading concurrently using Embassy's async runtime. Two WAV |
| 85 | +streams are read from a microSD card over SPI with DMA so the CPU stays free for DSP. |
| 86 | +Audio is generated by the **STM32U5's internal DAC** — no external DAC chip is used. The |
| 87 | +main mix leaves the board through a **3.5mm AUX jack** and feeds a **Marshall Middleton** |
| 88 | +speaker, which provides its own built-in 50W amplifier. The cue channel goes through a |
| 89 | +**TPA6132 headphone amplifier** to the headphones (carrying only the cued deck). |
| 90 | + |
| 91 | +Each deck has a rotary encoder with a 3D-printed disc as a jog wheel, six potentiometers |
| 92 | +(Bass / Mid / High EQ, LPF, HPF, Volume), and five push buttons (Play/Pause, Cue, Loop, |
| 93 | +Sync, Headphone Cue Select). Shared controls are a crossfader and a headphone volume knob. |
| 94 | +Two **ILI9341 2.4" TFT displays** (one per deck) connect over SPI and show playback state |
| 95 | +in play mode and the file list in browse mode. |
| 96 | + |
| 97 | +### Schematics |
| 98 | + |
| 99 | + |
| 100 | + |
| 101 | +### Bill of Materials |
| 102 | + |
| 103 | +| Device | Usage | Price | |
| 104 | +|--------|--------|-------| |
| 105 | +| [STM32U5 Nucleo Board](https://www.st.com/en/evaluation-tools/nucleo-u575zi-q.html) | Main microcontroller | — | |
| 106 | +| [TDA1308 Headphone Amplifier](https://www.emag.ro/amplificator-audio-stereo-pentru-casti-cu-tda1308-dc-3-6v-emg232/pd/DPSG9VYBM/?ref=fav_pd-title) | Headphone output | 24 RON | |
| 107 | +| [3.5mm Stereo Audio Jack (female) x2](https://ardushop.ro/en/electronics/2021-cjmcu-trrs-35mm-stereo-jack-module-6427854030856.html) | AUX output to speaker/headphone | 1.97 RON | |
| 108 | +| Marshall Middleton | Main speaker output via built-in 50W amplifier (AUX in) | — | |
| 109 | +| [Rotary Encoders ×2](https://ardushop.ro/en/electronics/1271-encoder-module-6427854018274.html) | Jog wheels — pitch-bend, scrubbing, browse | 10 RON | |
| 110 | +| [Potentiometers 10kΩ ×11](https://ardushop.ro/en/discrete-components/280-374-liniar-potentiometer-10k-50k-100k-6427854002952.html#/156-valoare_rezistenta-10k) | EQ Bass/Mid/High ×6, LPF ×2, HPF ×2, Headphone Vol ×1 | 1.31 x11 RON | |
| 111 | +| [Linear potentiometers x3](https://www.optimusdigital.ro/ro/componente-electronice-potentiometre/2420-modul-poteniometru-liniar.html)| Volume x 2, Crossfader x1 | 20 x3 RON| |
| 112 | +| [Push Buttons (×10)](https://ardushop.ro/en/buttons--switches/713-push-button-small-trough-hole-6427854009050.html) | Play/Pause ×2, Cue ×2, Loop ×2, Sync ×2, Headphone Cue Select ×2| 0.83 x10 RON | |
| 113 | +| [ILI9341 2.4" TFT Display (x2)](https://ardushop.ro/en/displays-and-leds/2534-lcd-tft-display-240x320-24-inch-il9341-touch-sd-6427854038630.html) | Per-deck display: track info, BPM, position, file list and SD module | 67 RON | |
| 114 | +| Micro sd card | storing the music | 40 RON | |
| 115 | +| [resistors](https://ardushop.ro/en/discrete-components/1444-set-rezistente-1-4w-600buc-30-valori-10r-1m-6427854021199.html), [capacitors](https://ardushop.ro/en/discrete-components/1299-set-electrolytic-capacitors-120pcs-12-values-022uf-470uf-6427854018779.html), [wires](https://ardushop.ro/en/wires-and-connectors/5-10-x-dupont-cables-male-male-10cm-6427854025869.html), [breadboard](https://ardushop.ro/en/electronics/2297-breadboard-830-points-mb-102-6427854012265.html), [leds](https://ardushop.ro/en/leds/293-468-5mm-led.html#/172-color-orange) | Debouncing, decoupling, wiring | 92 RON | |
| 116 | +| | | Total: 330 RON | |
| 117 | + |
| 118 | +## Software |
| 119 | + |
| 120 | +| Library | Description | Usage | |
| 121 | +|---------|-------------|-------| |
| 122 | +| [embassy-rs](https://github.com/embassy-rs/embassy) | Async embedded framework for Rust | Main async runtime on STM32U5; drives SPI, internal DAC, ADC, and DMA peripherals concurrently | |
| 123 | +| [embedded-sdmmc](https://github.com/rust-embedded-community/embedded-sdmmc-rs) | SD card FAT filesystem driver | Reads WAV and `.cue` metadata files from the SD card | |
| 124 | +| [ili9341](https://crates.io/crates/ili9341) | ILI9341 TFT display driver | Drives the two per-deck displays over SPI | |
| 125 | +| [embedded-graphics](https://github.com/embedded-graphics/embedded-graphics) | 2D graphics library | Renders track info, BPM, loop/sync state, and the browse-mode file list | |
| 126 | +| [micromath](https://github.com/tarcieri/micromath) | Lightweight math for embedded | Biquad filter coefficient calculations for EQ, LPF, and HPF | |
| 127 | + |
| 128 | +## Links |
| 129 | + |
| 130 | +1. [STM32U5 Reference Manual](https://www.st.com/resource/en/reference_manual/rm0456-stm32u5-series-armbased-32bit-mcus-stmicroelectronics.pdf) |
| 131 | +2. [Embassy — Async Embedded Rust](https://embassy.dev/) |
| 132 | +3. [Numark Mixtrack Platinum FX — reference DJ controller](https://www.numark.com/product/mixtrack-platinum-fx) |
| 133 | +4. [WAV file format specification](http://soundfile.sapp.org/doc/WaveFormat/) |
| 134 | +5. [Cookbook formulae for audio EQ biquad filter coefficients (Robert Bristow-Johnson)](https://www.w3.org/TR/audio-eq-cookbook/) |
0 commit comments