Copyright Brian Starkey 2012-2014
Valid HTML 4.01 Transitional

Valid CSS!
iconThe Pidrive - A(nother) Raspberry-Pi music playermax, min, close
August 2014
Software ArchitectureSoftware Architecture

The system quite a few different software components, all built on linux (soft-float debian wheezy - yuck!). The heart of the music playback is mpd, a music player daemon which handles the music database and playback. There are 3 different mpd clients running - empcd which takes input from the front-panel buttons, client175 which gives a web interface, and my custom Pidrive client.

The other components of the system are the kernel drivers for pidrio and the LCD, and of course the firmware running on the Atmega itself. I've used mainline kernel frameworks where possible, however I did all this work before device-tree had really emerged (or atleast I was unaware of it) so it's all hard-coded into the R-Pi board file.

My userspace code is all written in Google go, mainly as a learning exercise.

The s4548 emulatorThe s4548 emulator

The LCD uses my s4548.ko kernel driver to expose a character device. I looked at fbdev, but I seem to remember monochrome bit-mapping wasn't well supported.

In userspace, I wrote a small go library which exposes the LCD's framebuffer as a paletted image which lets me use go's draw library to draw onto it.

I also wrote a little emulator which allows for testing on a platform without the s4548 hardware. It reads the contents of a file and treats it like the framebuffer for the LCD, drawing it using SDL. This way, a userspace application can open and mmap the file as though it were a character device, and act as if there is a s4548 available.


The Pidrio kernel module just exposes control of the LED drivers through the LED framework and the buttons through the input framework. Simple as that! It reads the state from the Atmega at regular intervals over i2c, and then marshalls the data to the right places. The power button is a special case - it causes orderly_poweroff() to be called to shutdown the system.

In userspace there isn't much to do as the frameworks take care of it. I've got a little go wrapper for the sysfs LEDs files, and either empcd or the pidrive app takes care of reading the input events

The Atmega firmware has quite a few jobs:

  • Generate PWM for the LEDs
  • Monitor button/input events
  • Generate square wave for voltage inverter
  • Reset the Pi to power it on when wanted
  • Babysit the S4548
That last point is interesting. The S4548 doesn't ACK i2c transactions and the R-Pi i2c driver doesn't (or didn't? might do now) support the protocol mangling quirk required to make that work. Instead, the Atmega listens for its own address and the S4548 address, and ACKs any S4548 transactions so that the LCD doesn't have to.

The "now playing" screenThe "now playing" screen
The LED control screenThe LED control screen

As I've mentioned, in userspace I use a lot of "off-the-shelf" software as there's little point in reinventing it. This consists of mpd and some existing clients. On top of that, I have my own client - "pidrive"

Pidrive is written in go, and uses the gompd library to talk to the mpd server. It has a bunch of UI components I wrote using the go image and draw librarys, which get painted to the LCD. There's labels with scrolling and wrapping, progress bars, sprites, lists. I have plans for more, but those are the bare minimum needed to get me started.

The pidrive application listens for events from input devices (i.e. keyboard), or from the mpd server so that it stays up to date with what's going on. It can control playback and that's about it at the moment. By using the s4548-emulator its possible to run the pidrive client on any computer, if you should want to. (great for testing).