Yay…after all this being too busy, too lazy, or any number of other excuses, one more project finally off my stack. The “mYpod”* is a small CompactFlash-based mp3 player I built from leftover spare parts from a bottom-secret government project, free samples and a standalone mp3 decoder chip.
(Click thumbnails for larger image)
- Supports CompactFlash media up to 2GBytes officially (FAT16 file system limitation); 4GBytes if you “relax” (i.e. violate) the FAT16 specification a little by setting a 64KB cluster size (Win2k/XP will allow this, but Win98 and below will bitch loudly and not read the card)
- Actual, real, full FAT16 implementation – handles fragmented files, deleted files, etc. (You’d be amazed how many card-based music players, and even some digital cameras, do not fit this description, or at least not reliably)
- Playback of mp3s with bitrates all the way up to the maximum mp3 bitrate of 320KByte/sec
- Display title and artist from ID3 tag if present (display filename if no ID3 present), and elapsed time
- Saves the currently-playing song when powered off – picks up where it left off
- Song selection: next, previous, “skip 10”, pause and menus (e.g. restart card from the beginning)
- Buttons light up at night like a glow-in-the-dark Bomb Pop
- Line-in and line-out from stereo available on front panel (anything plugged into line-in is switched in instead of mp3 player)
One evening a year or two ago, GJM and I were about to head home from work and talking about part of an environmental monitoring system we were developing at the time. This was a handheld data-retreival unit that queried the environmental loggers in-the-field and recorded their wireless data to a CompactFlash card. I remember jokingly saying, “Hey… we have a memory card, A/D, processor, LCD and buttons…how many extra parts do you think it would take to turn this into a music player?” Next thing I know we’ve got a couple beers cracked and are laying out a quick-n-dirty mp3 player board in an unused corner of a layout set to go out that night.
Packaging this quick ‘n dirty design as a truly portable device would have been non-trivial (and, I got a Creative Nomad as a gift sometime between the start and end of this project); it would be much easier to package it into a car-stereo size enclosure. My car already came with this plastic tray (officially for holding papers, garage door clickers, etc.) bolted into the spare bay where an auxiliary radio component would go (or the bottom half of those huge, double-height stock radios), so I took it out, drilled some holes and screwed the board and extra parts directly into it.
Most of the parts were leftover lab spares, such as the PIC microcontrollers (scrapped from the Real Project because of a silicon defect in the revision we had; they can act unreliably above 4MHz and therefore can’t be used in production gear), the membrane keypad and the LCD. The only major extras needed were the STA013 mp3 decoder ($12) and a stereo DAC (free sample from Cypress Semiconductor)** to convert the decompressed digital (PCM) audio from the STA013 to real sound.
Guts during assembly. The large tall chip toward the front, hiding behind the too-fast oscillator (more on this in a bit) is the mp3 decoder, the square 64-pin bitch-to-solder in back is the PIC. (Click for larger image)
For the front panel, I grabbed a piece of Lexan left over from building the terrarium and of course, cut a bunch of holes in it. I started off with the usual score-and-break method of cutting the Lexan, but when it came to inner cuts (e.g. the rectangular holes for the CF card and LCD) consulted my dis-is-how-we-do-it-in-da-ghetto handbook, laid a hot soldering iron against the back of my X-Acto knife blade and pressed it into the piece. Like a hot knife through buttah! Using a straight edge as a guide, this provided straight, clean cuts, which were touched up a bit with a small hand file. Round holes were cut by making a pilot hole with a small drill bit, working up to larger and larger drills until the desired size was reached. The Lexan has a tendency to grab the drill bit and suck it in (depending on the intricacies of classical physics, this either yanks your drill out of your hands and into the piece, or yanks the piece out of whatever’s holding it, potentially snapping it), so don’t go diving immediately in with the large bits.
The keypad features an adhesive backing and insertable overlay for the button graphics – being the perfectionist that I am, I doodled some arrows and symbols on a piece of paper and slid it in. Since the front panel is clear, and surprisingly, the buttons themselves are translucent, it was easy to stick a few colored LEDs on a piece of Veroboard behind them, angled and distanced so that they cast a tight circle of light on the entirety of only one button each. I was originally going to have this turn on automatically when the headlights were turned on, but couldn’t find such a signal on the radio’s wiring harness. The LCD unfortunately comes without any backlighting, and no way in hell to add any since it’s mounted flush against a very opaque PCB full of traces. A metal guard ring completely surrounds the glass; if removed, the glass ceases displaying anything and falls out (the metal band presses it tight against a zebra strip that connects it to the board).
The button panel, without sexy backlighting. You can see how much effort I spent on it! ;) (click for larger image)
Software / Featuritis:
A couple features are missing, either because they were accidental, or too much of a pain to implement. The most notable is fast-forward. The firmware is already handling FAT16 fragmentation transparently in the background; all the decoder requires is bits, as fast as you can stuff them in. Mp3 files are made up of many small time segments called frames, which often incestuously share bits with previous frames, so you can’t just play the file at 10x by dropping 9 out of every 10 frames. All you get from this is a bunch of blips and pops… fast-forwarding an mp3 turns out to be non-trivial, so it is not implemented here. The other non-implemented “feature” is Chipmunk Mode. The mp3 decoder runs off of a very precise master clock, typically around 14MHz. Following this (internal to the decoder) is a Phase-Locked Loop system of clock multipliers/dividers that can be software adjusted to provide a correct timebase from a wide variety of input clocks. While I was testing, I got the sensation that everything from my player sounded a little “sharp”. Indeed, a side-by-side comparison between the early mYpod and WinAmp confirmed that the same 3.5-minute song finished almost 10 seconds faster on mYpod. Turns out I had the PLL set for a slower master clock than I used, so it was playing back too fast. I discovered the PLL settings are very, very adjustable; you could make all your favorite artists sound like demons or chipmunks. Unfortunately, this is not exactly a “fast-forward” feature (by the time you speed it up enough to be a decent FF, it’s too high and whiny to be intelligible – besides, the micro can’t pump data out that fast anyway), so I set the correct speed and didn’t leave provisions for messing with it via the front panel.
For the firmware – that was actually the most annoying part of this project, a lot of assembly coding. The FAT16 stuff was actually written already for the most part, as part of the actual work project (otherwise, I’d release the code here). All the fiddly bits (buttons and menu system, LCD scroller, play timer, hunting for ID3 tags, position-saving hack to an already crufty file handler, etc.), and getting them to play nice with one another (e.g. does the play timer stop when playback is paused? What’s the easiest way to restore the song title/info on the LCD after it’s been overwritten with a menu?), still had to be done though. The PIC programmer supplies and requires 5V to program, but the mp3 decoder chip can only handle 3.3V. The solution to this was to load the Jolt serial-port bootloader onto the PIC before soldering the decoder in (and hope I never introduced something in my code that overwrote the bootloader). Sending new firmware over the serial port, the PIC can self-program at 3.3V.
Last but not least, this beast had to be connected to the headunit somehow. Pioneer decided that all good headunits should have line-ins, but ensconce them in this proprietary 11-pin “IP-BUS”*** connector (with differential inputs, no less). Bah. Luckily, breakaway pin headers plus heat shrink equal reasonable facsimile of funny plug, and the differential inputs work fine by just dumping single-ended signal into one side and grounding the other.
So yeah… it sounds good! Now I just need to put the TrashAmp back together (strip away the melty bits, etc.) for that phat window-rattling bass, yo.
* my brother calls it my mpthriller – then again, he’s got some shizzle on his nizzle.
** I only sampled it because I couldn’t get it from Digikey or any other decent distributor. Ohh, that was a mistake. Samples came at a cost of about 6 months of horny Cypress rep calling me about how the chip’s working out for me, when he can come over and show off the full product line, and how soon I’ll be ready for those 10,000 units…
*** as in like, Intellectual Property Bus? As in, if any competitors try to reverse-engineer our funny plug and make something compatable, there will be hell (or IP lawyers) to pay? All right, maybe it stands for “Interconnected Peripherals” or something.