What to do with the small cardboard box full of Raspberry Pi related junk, besides watch it sit slowly collecting dust? Surely it should be doing something interesting? Failing that it could be a wifi radio, I suppose.

Notes on how I converted a cardboard box full of bits into a cardboard box full of wifi radio.

It still collects dust.

Download the code

Photo set on Flickr



Cardboard Raspberry Pi internet radio front shot.





The hardware



Raspberry Pi model B

ST7565 LCD

2 Rotary encoders

4 digit, 7 segment display and a MAX72165124 driver

analogue panel meter

USB powered speakers

wifi dongle

cheap USB sound ‘card’ — on board audio conflicts with PWM GPIO

and a cardboard box









GPIO Pin Map

Attempt at a circuit diagram, coming soon.



All wired up



but will it fit into the box?



Needn’t have worried, it all rams in fine.





The software

Raspbian along with Gordon @ Drogon’s excellent Wiring Pi library.

A long time ago I almost learnt C, well enough to wangle a job as a C programmer (not very well). I don’t know Python at all and, like everyone else in the world, I think I can write PHP. It’s decided then everything will be bodged together in badly written C accompanied by even more badly written PHP.





Playing radio streams

I’m using mpd.

To set up, install (sudo apt-get you-know-the-rest) and edit the config file in /etc/mpd.conf

All we really need to change is the bind_to_address, set this to the RPi’s ip address. A little more fiddling is required to use the USB sound card, edit audio_output to use hw:1,0 instead of hw:0,0 in the config.

I created a playlist for every radio station I wanted to play. M3U playlists are stored in /var/lib/mpd/playlists At their most basic an M3U only needs to contain the URL of the the audio stream. For example XFM Manchester; URL http://ice-the.musicradio.com:80/XFMManchester pasted into an xfm_manchester.m3u in /var/lib/mpd/playlits

There’s a nice list of streaming radio stations here : http://www.listenlive.eu/uk.html

With a playlist created, restart mpd :

sudo service mpd restart

Now install an mpd client, funnily enough called mpc. With which we can :

mpc -h 192.168.0.66 load xfm_manchester.m3u mpc -h 192.168.0.66 play

192.168.0.66 is the IP address of my RPi.

Full list of commands : http://linux.die.net/man/1/mpc

To load another play list :

mpc -h 192.168.0.66 clear mpc -h 192.168.0.66 load radio4.m3u mpc -h 192.168.0.66 play



To stop playback :

mpc -h 192.168.0.66 stop



All well and good except I want to listen to the BBC and their streaming URLs are awkward. Here’s a nice solution by Tim of Codeified to grab BBC stream URLs and save as M3Us for mpd : http://www.codedefied.co.uk/2011/12/24/playing-bbc-radio-streams-with-mpd/





Do things when we turn the knobs

I’m using two 2 bit rotary encoders. Datasheets are here. This wasn’t as straight forward as I’d hoped. After much faffing I stumbled on this solution : http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html Cut… Paste.





The clock

Left over from another project, a 4 digit 7 segment display hooked up to a MAX7219 driver. I’ve gone into detail on how I bodged this in another post. It displays the current system time, updated over NTP.





Displaying the download rate

I thought it might be nice to show the current download rate on an old analogue volt meter. The original scale was scanned and altered in Photoshop before being printed and stuck to the reverse (It’s not totally ruined I can always flip it in future) of the plate. It’s connected to GPIO 18 which is set up as PWM_OUTPUT via Wiring Pi.

I parse /proc/net/dev/ every second pulling out wlan0’s bytes received, subtracting the previous value to get bytes that second then divide by 1000, er… multiply by 8 to get kbps (I think). I then make sure its less than 1000 (the maximum value on my scale) and divide by some magic number such that when sent to pin 18 it’s at to the correct position on my scale. Okay, it takes some fiddling but after all that it’s pretty accurate-ish.





Bitmaps on the ST7565

I rewrote (I say rewrote, cut, pasted, bashed head against keyboard until it compiled is more truthful) Adafruit’s Arduino tutorial here : https://github.com/adafruit/ST7565-LCD and I’m happily able to display text and bitmaps.

I cobbled together some 128 x 64 station logos :

and went about converting them to a format I can use with the ST7565 LCD.

The ST7565’s memory map is divided into 8 pages of 128 bytes each, laid out something like this (note weird page order, it isn’t as specified in the datasheet) :

ST7565 Memory Map

A 128×64 screen fits in 1K. Here’s a quick PHP (yay PHP!) script that takes a raw 1bpp image and converts to it to bytes suitable to dump to the ST765

// convert raw 1bit per pixel bitmap into code for lcd $bitmapwidth = 128; $bitmapheight = 64; $fp = fopen("logo.raw","r"); $buf = fread($fp,1024*10); for ($y=0;$y<($bitmapheight/8);$y++) { for ($x=0;$x<$bitmapwidth;$x++) { $code=0; for($dloop=0;$dloop<8;$dloop++) { if ( ord($buf[$x+(($y*8)+$dloop)*$bitmapwidth]) != 0 ) { $code += 1 << (7-$dloop); } } echo $code.", "; } }





Then I made it play Nyan Cat







Followed by Star Wars









Showing the currently playing song / artist

I intended to scrape html from the BBC station’s web sites for currently playing song title / artist, but I stumbled on some nice json feeds, the same feeds that the BBC use to update their own pages. 6 Music’s is here : http://polling.bbc.co.uk/radio/realtime/bbc_6music.json

Displaying current track info

A quick PHP script grabs the feed and parses title, artist and end time of the current song. I then store this locally for the main radio program to pull in. The fact that we know the end time of the song is helpful as it means we don’t have to constantly hammer the site in the hope that the song has changed if we know the song data we’ve already got is actually still playing.

The script :

#!/usr/bin/php5-cgi <?php $localfile = "/home/pi/wifiplayer/bbc6_now_playing.txt"; $currentinfo = file($localfile); $last_song_end_time = $currentinfo[0]; // no need to grab new info if last song is still playing... if (time() > $last_song_end_time ) { $songdata = file_get_contents("http://polling.bbc.co.uk/radio/realtime/bbc_6music.jsonp"); $end=0; // get song end time $pos1 = stripos($songdata, "end\":"); if ($pos1 !== false) { $endstart = $pos1 + 5; $endend = stripos(substr($songdata,$endstart), ","); if ($endend !== false) $end = substr($songdata,$endstart,$endend); } $artist=""; $title=""; // find artist $pos1 = stripos($songdata, "artist\":"); if ($pos1 !== false) { $artiststart = $pos1 + 9; $artistend = stripos(substr($songdata,$artiststart), "\","); if ($artistend !== false) $artist = substr($songdata,$artiststart,$artistend); } // find title $pos1 = stripos($songdata, "title\":"); if ($pos1 !== false) { $titlestart = $pos1 + 8; $titleend = stripos(substr($songdata,$titlestart), "\","); if ($titleend !== false) $title = substr($songdata,$titlestart,$titleend); } $fp = fopen($localfile, 'w'); fwrite($fp, $end."

".$artist."

".$title."

"); fclose($fp); } ?>





Finished, pride of place in the kitchen