IPOD Mini
Greetings Everyone and Welcome Back.
Recently, there’s been a growing interest in going back to offline music players like the iPod and Zune. I wanted to build something similar but with a modern twist.
At the heart of this project is the Waveshare ESP32-P4 development board, which powers the entire device. I also designed the user interface from scratch, taking inspiration from the classic iPod Nano 6th Generation UI.
The device is primarily touchscreen-based, but instead of using a traditional physical click wheel, I created a software-based digital scroll wheel. It works similarly to the original iPod scroll wheel, allowing you to navigate through menus and control different functions.
The interface includes a Music section for playing songs, a Video section for video playback, and a Photos section for viewing images. I also added a dedicated Volume Control interface, allowing the scroll wheel to be used to increase or decrease the volume.
All of the media is stored on an SD card, which supports MP3, wav, flac, m4a, and several other common audio and video formats. The SD card can be accessed from the side of the enclosure through a dedicated opening, making it easy to add or replace media.
The goal of this project was to recreate the feel of a classic iPod while combining it with modern hardware and a touchscreen interface, and this article covers the complete build process of this project, let's get started.
Supplies
These were the materials used in this project
- Wavshare ESP32 P4 Dev board
- Speaker Module
- 3.7V LiPO Cell 800mAh
- SD Card with Legally downloaded music media (LOL)
- M2 screws
- 3D Printed parts
IPOD CLASSIC 6th GEN
The iPod Classic 6th Generation has always been one of those devices I wanted to own.
When I was younger, I never really had the opportunity to buy one. The iPods I came across were mostly cheap knockoffs, so the idea of owning a proper iPod Classic always felt a little out of reach. Even today, finding a good-condition original unit in India can be surprisingly expensive.
The 6th-generation iPod Classic was introduced by Apple in 2007, and it was a pretty impressive device for its time. It came with either 80 GB or 160 GB of storage, a 2.5-inch 320 × 240 color display, the iconic Click Wheel, and a battery rated for up to 30 hours of music playback on the 80 GB model and up to 40 hours on the 160 GB model.
The 160 GB version could hold up to 40,000 songs or 200 hours of video, which was pretty incredible for a pocket-sized device in 2007. It also supported formats such as MP3, AAC, Apple Lossless, WAV, and AIFF, along with video playback.
What I particularly like about the 6th generation is its design. It moved to an anodized aluminum front with a polished stainless-steel back, giving it that distinctive premium look, while retaining the Click Wheel that made navigating an iPod so satisfying.
Unfortunately, these devices are no longer produced, and finding one in good condition can be quite expensive. There is also a second option that I’ve been wanting to explore someday: flea markets and old electronics markets, where you can sometimes come across older iPods and other forgotten tech.
But for this project, instead of spending a significant amount of money hunting down an original, I decided to take a different route.
If I couldn't find the iPod I wanted, why not build one myself?
HARDWARE- ESP32-P4-WIFI6 4.3inch DEV BOARD
For the main hardware, or the Brain of this project, I chose the Waveshare ESP32-P4-WIFI6-Touch-LCD-4.3 development board.
I’ve actually used this same development board in one of my previous PIPBOY projects, so I was already familiar with the hardware and its capabilities. When I started working on this iPod project, it felt like a natural choice, especially because of the combination of processing power, display, and touch interface it offers.
One of the main reasons I chose this board was its built-in 4.3-inch 480 × 800 capacitive touchscreen. The size and resolution worked really well for the iPod-style interface I had in mind, while having the display and touch hardware integrated into the development board significantly simplified the overall design.
The other major reason was the ESP32-P4 itself. It features a dual-core RISC-V processor running at up to 400 MHz, along with dedicated multimedia hardware and a much more capable memory and peripheral system compared to the ESP32 boards I’ve worked with.
That extra processing power was particularly useful for this project because I wanted the iPod to handle a graphical user interface, animations, touchscreen interaction, audio playback, and even video playback.
The board also includes an ESP32-C6 wireless co-processor, providing Wi-Fi 6 and Bluetooth 5 capabilities, which gives the project plenty of room for additional functionality.
https://docs.waveshare.com/ESP32-P4-WIFI6-Touch-LCD-4.3
Another thing that made working with this board easier was the documentation. Waveshare provides a dedicated Wiki with hardware information, examples, and development resources. I relied on this documentation quite a bit during development, particularly while working with the display, touchscreen, SD card, audio, and other peripherals.
Since I had already worked with this board on my Pip-Boy project, I was also able to get up and running with the hardware relatively quickly for this build.
WAVSHARE SERVICE
Special thanks to Waveshare for providing the hardware used in this project. The ESP32 P4 4.3-inch Dev Board and supporting accessories were supplied as review units for testing and evaluation.
Waveshare is a leading global provider of electronic components, modules, and development tools used across robotics, IoT, automation, education, and many other fields. With a strong focus on quality, reliability, and continuous innovation, Waveshare has earned the trust of engineers, designers, hobbyists, and makers worldwide.
Their extensive product lineup, from displays and HATs to expansion boards and embedded modules, makes them a go-to choice for both professional builds and DIY projects.
SPEAKER & SD CARD ASSEMBLY
For audio output, I used the 4Ω mini speaker that came included with the Waveshare ESP32-P4 development kit. Connecting it was quite straightforward; the speaker has a JST connector, which plugs directly into the corresponding JST connector on the Waveshare development board.
For storing the music and other media, I used the SD card slot built into the development board.
Our iPod Mini supports a range of common media formats:
- Audio: .mp3, .wav, .flac, .m4a, and .aac, with ID3 metadata used for filename cleanup and better organization.
- Photos: .jpg, .jpeg, .png, and .bmp. Images are decoded on the fly using the LVGL TJPGD and LodePNG decoders.
- Videos: .mjpeg and .avi. Video frames are streamed directly into PSRAM for playback.
CODE & DEMO RUN
Here's the main code used in this project and it's a simple one; i have broken it down into small files.
System 'main.c'
Click Wheel 'ui_click_wheel.c'
Split Screen Menu 'ui_library.c'
Now Playing Screen 'ui_now_playing.c'
Main UI Orchestrator 'ui_main.c'
LAYOUT OF IPOD UI
Top Screen
- The status bar 28px displays play/pause status indicators and the current view title
- content viewpoint 372px houses the split menu; let 240px item list with blue gradient highlights right 240px live preview panel now playing cover art, scrub bar, fullscreen photo view or video canvas
Bottom Screen
- dedicated virtual iPod click wheel chassis with a 280px outer white disc and 96px inner silver select button
Virtual Click Wheel (Polar Mathematics)
Real iPod click wheels used capacitive rotary sensing rings. We simulate this on a standard capacitive touch screen using real-time polar coordinate mathematics.
the center of the virtual wheel is fixed at (x_c, y_c) = (240, 600). When a touch event is captured at a point (x, y), the firmware computes:
It will look & work like this:
Dual Core Execution Pipeline
to guarantee stutter-free 60 fps graphics alongside lossless audio decoding, the firmware leverages FreeRTOS dual-core task pinning:
Core 0 (UI & Display)
- runs the LVGL 9 display driver with triple partial rendering buffers.
- manages touchscreen input parsing and visual animations.
- synchronizes UI playback timers with thread-safe locks ('esp_lv_adapter_lock').
Core 1 (Audio Pipeline)
- high-priority RTOS task streaming MP/Wav/FLAC data from SDMMC.
- decodes audio chunks via 'minimp3_ex' directly into the DMA ring buffer feeding the ES8311 codec over I2S.
Media Scanner & Supported Formats
When inserted, the firmware recursively searches '/shcard' up to 4 directories deep and indexes media:
- Audio '.mp3' , '.wav' , '.flac' , '.m4a' , '.aac' . With ID3 Filename metadata cleanup
- Photos '.jpg' , '.jpeg' , '.png' , '.bmp' . Decoded on the fly via LVGL TJPGD and LodePNG decoders.
- Videos '.mjpeg' , '.avi' . Stremed frame by frame directly into PSRAM
Step-by-Step Ui Design
recreating the authentic iPod classic user experience required combining vintage design aesthetics with modern embedded GUI engineering. Here is exactly how we structured, styled, and rendered the user interface using LVGL 9.
Authentic Color Palette
To faithfully mirror the 6th/7th generation iPod Classic, we defined a strict design system with curated hex colors and typography tokens:
LVGL Widget Tree & Screen Hierarchy
instead of creating and destroying screens dynamically, all ui views are pre-allocated once in PSRAM during start and placed inside the top 480x400 viewpoint. View transitions happen instantaneously with zero heap fragmentation simply by toggling the 'LV_OBJ_FLAG_HIDDEN' flag
Crafting the 2-column split menu
the signature iPod split-screen layout divides the display into two 240px columns
- The left pane uses 'LV_FLEX_FLOW_COLUMN' to hold selectable rows; each row contains a label and a right-aligned chevron. When selected, 'set_row_selected()' applies a vertical linear gradient 'LV_GRAD_DIR_VER' from '#4FA5FF' down to '#0066FF' and turns the text crisp white
- Right pane Updates synchronously as the user scrolls; when highlighting "Music," it displays a music note icon with total song counts; when hovering over individual songs, it displays the track album art and artist metadata
Designing the "Now Playing" Screen 'ui_now_playing.c'
- Album Art Tile a 140x140 square with a 6px border radius and a subtle drop shadow 'LV_OPA_45' offset Y = 4 to give physical depth
- Circular Marquee Title: Long song titles automatically scroll horizontally without clipping using 'LV_LABEL_LONG_SCROLL_CIRCULAR'
- Scrubber Bar built using an 'lv_slider' with an accent blue indicator bar flanked by current and remaining time labels
Building the Fullscreen Photo & Video Viewer
- Photo Viewer 'photo_viewer.c' uses LVGL's streaming TJPGD decoder to render high resolution JPEGs directly from the SD card a translucent dark header bar '#1A1A1A' at 'LV_OPA_200' displays the photo index and slideshow status
- Video Screen 'ui_video_screen.c' directly draws decoded MJPEG video frames onto a 480x360 PSRAM canvas while displaying a sleek bottom control bar with a live scrub slider
Layering the Virtual Click wheel 'ui_click_wheel.c'
the virtual click wheel is rendered using concentric circular widgets:
- Outer Disc: a 280x280 circular container 'LV_RADIUS_CIRCLE' in pure white '#FFFFFF' with a soft 10px drop shadow
- Inner Center Button a 96x96 circular silver disc '#D6D6D8' entered within the outer wheel
- Quadrant Labels placed precisely at top 'MENU' , bottom 'PLAY PAUSE' , left 'PREV' and right 'NEXT' using Montserrat fonts and iconic symbols
- Touch Interceptor a single unified event callback attached to the root chassis listen to 'LV_EVENT_ALL' , running the polar mathematics engine to detect taps and rotary swirling.
Build and Flash
Install ESP-IDF 'V5.3' or newer:
Clone the Repository
Build & Flash
set the target to ESP2-P4 and compile:
Prepare MicroSD Card
- Format A MicroSD card as 'FAT32' or 'exFat'
- Create directories and copy your favourite media:
- Insert the card into the Waveshare ESP32-P3 board and reboot.
DESIGN
For the enclosure design, my first hurdle was the display itself.
The classic iPod has a very distinctive form factor, with a relatively small display and the iconic scroll wheel positioned underneath it. The overall design is also quite boxy, although the newer generations gradually became thinner compared to the older, chunkier models.
Since I wanted to loosely base my design on the iPod, I decided to keep the enclosure simple and boxy as well. However, the thickness had to be increased to accommodate the Waveshare ESP32-P4 development board along with the LiPo battery inside.
I designed the enclosure as two separate halves, a front enclosure and a back enclosure. Both halves are joined together using four M2 screws, with mounting points placed along the top and bottom.
On the bottom, the ESP32-P4 board has two USB Type-C ports, so I designed a dedicated recessed area around them. This gives enough clearance to plug in a USB-C cable as well as USB-C earphones without having the enclosure get in the way.
I also wanted the SD card to remain accessible without having to open the entire enclosure. To achieve this, I created an opening along the right side, aligned with the SD card slot on the development board. This allows the SD card to be inserted or removed directly from the outside.
And honestly, looking at the final design, it probably resembles a Nokia Lumia more than an iPod. But I actually really like how it turned out. It feels fresh while still retaining some of the simple, boxy character I wanted—and more importantly, every part of the design has a functional purpose.
ASSEMBLY
As mentioned in the design section, the main body of the iPod consists of two separate enclosure halves, the front enclosure and the back enclosure.
The display is essentially sandwiched between these two parts. It sits in the dedicated mounting area of the front enclosure, while the back enclosure has integrated support ribs that hold the display securely in position and prevent it from moving around inside the enclosure.
The back enclosure also houses the 3.7V LiPo battery and the slide power switch. I added a dedicated opening on the top face of the enclosure for the slide switch.
To join both enclosure halves together, I added mounting holes on the top and bottom faces. These mounting points allow the front and back sections to be secured using four M2 screws, keeping the entire assembly firmly together.
3D PRINTED PARTS
After finalizing the 3D model, I exported the enclosure as an STL mesh file and prepared it for 3D printing.
For the first prototype, I printed both enclosure parts using Red Hyper PLA. The print quality came out really well, but after assembling the parts, I noticed a couple of fitment issues. The overall design also had some unexpected Nokia Lumia vibes, so I decided to make a few changes before producing the final version.
I slightly modified the enclosure by removing around 0.1 mm of material from the inner lip. This gave the two enclosure halves a much tighter and cleaner fit when assembled.
For the final print, I used a special tri-color PLA+ filament that I had. The filament contains three colors—copper, purple, and brown—and the visible color of the enclosure changes depending on the viewing angle, giving the finished device a really interesting appearance.
Since this was a PLA+ filament, I sliced the model using the regular PLA+ profile rather than the high-speed printing profile.
The final print settings were
- Material: Tri-color PLA+
- Layer Height: 0.16 mm
- Infill: 25%
- Top Z Distance: 0.3 mm
- Supports: Tree supports
- Print Profile: Regular PLA+ profile
The combination of the fine layer height and the color-shifting filament gave the enclosure a clean finish while adding a unique look to the final device.
POWER SOURCE
For the power source, I’m using a 3.7V 800mAh LiPo cell.
The main reason I chose this particular LiPo was its compact size. One of my main goals with this project was to keep the iPod as thin and compact as possible, so using a cylindrical 18650 cell wasn’t really practical for this enclosure.
The slim form factor of the LiPo cell allowed me to fit the battery inside the enclosure while keeping the overall thickness of the device relatively low.
BATTERY SETUP
For the battery setup, we need two additional components along with the LiPo cell: a small slide switch and a 2-wire battery connector harness compatible with the battery connector on the Waveshare ESP32-P4 board.
First, connect the positive and negative wires of the harness to the corresponding positive and negative terminals of the LiPo battery.
For the power switch, we place the slide switch in series with the positive wire. Connect the battery’s positive terminal to one terminal of the slide switch, and then connect the other terminal of the switch to the red positive wire of the battery harness.
The negative terminal of the battery can be connected directly to the negative wire of the harness.
This gives us a simple ON/OFF power switch, allowing us to disconnect the battery power from the ESP32-P4 board whenever the device is not in use.
BACK ENCLOSURE ASSEMBLY
- The back enclosure assembly begins by securing the LiPo battery in its designated mounting area. First, apply a piece of double-sided tape to the battery mounting position and remove its protective backing.
- Next, carefully place the LiPo cell into position and press it down firmly to ensure good adhesion.
- Just above the battery, position the slide power switch in its dedicated opening. The switch is already designed to be a pressure fit, but since it is a moving component that will be operated frequently, I also used hot glue to secure it in place.
This prevents the switch from shifting or coming loose during repeated use while still allowing the switch itself to move freely for turning the device ON and OFF.
FRONT ENCLOSURE ASSEMBLY
- Next, place the Waveshare ESP32-P4 development board into its designated position inside the front enclosure.
- Once the board is properly aligned, use a small amount of hot glue to secure it in place. This keeps the board firmly seated inside the enclosure and prevents it from shifting during assembly and regular use.
FINAL ASSEMBLY
- For the final assembly, we first add a piece of double-sided tape to the designated speaker mounting area on the lower section of the back enclosure. Remove the protective backing and carefully place the speaker over the tape, making sure it is properly aligned and securely held in position.
- Next, connect the battery’s 2-pin JST connector to the corresponding battery connector on the Waveshare ESP32-P4 development board.
- Once all the internal components are connected and positioned correctly, bring the front and back enclosure halves together and carefully close the assembly.
- Finally, secure both halves permanently using four M2 screws—two from the top and two from the bottom of the enclosure.
and with that, the assembly process is completed.
RESULT
Here's the end result of this build, a fully functional DIY iPod Mini.
The music player can play common audio formats such as MP3, along with other supported audio files stored on the SD card. I also added a video playback mode, allowing the device to play video files such as MP4 and AVI. Along with music and videos, there is also a dedicated Photos section for storing and viewing images directly from the SD card.
For audio output, the device has a built-in speaker, and it gets surprisingly loud for something this compact. Since the ESP32-P4 board also provides USB connectivity, I can use USB Type-C headphones when I want a more private listening experience.
The 3.7V 800mAh LiPo battery gives me around one hour of backup, which I think is a reasonable compromise considering the compact size of the device, touchscreen, speaker, and relatively power-hungry multimedia features.
Overall, the project turned out pretty much the way I envisioned it—a compact offline media player with a custom iPod-inspired interface, digital scroll wheel, music, video and photo playback.
So yes, the DIY iPod Mini is a success!
OVERVIEW
Overall, I’m quite happy with how this project turned out. The hardware, enclosure, custom UI, digital scroll wheel, music playback, video playback, and photo viewer all work as intended, so there aren’t any major changes I feel are necessary.
The main thing I would like to improve is the battery life. At the moment, the 3.7V 800mAh LiPo gives me around one hour of runtime, so improving power efficiency or finding a better battery solution would be a priority for a future revision.
Another area I’d love to experiment with is the UI and software side. Since I’ve previously used this same hardware to build a Fallout-inspired Pip-Boy project with a completely custom Pip-Boy interface, I think a similar approach could work really well here. The iPod could have multiple selectable themes, such as a Fallout/Pip-Boy theme, a Cyberpunk-inspired interface, or even completely different custom UI designs.
And why stop there? Since the ESP32-P4 is capable of handling much more than just music playback, this device could potentially be turned into a small multimedia and gaming handheld. I could add some simple homebrew games or even experiment with Game Boy emulation. I’ve already worked with Game Boy emulation in one of my GBA projects, so bringing something similar to this device would be an interesting future upgrade.
For now, though, the core project is complete and working exactly as intended, and I’m really happy with the result.
All the details, Files, Code & wiring details are all attached in this article, so make sure to check them out.
Special thanks for reaching this far and i will be back with a new project real soon.
PEACE.