Firmware for Radyjko 357 - a standalone, battery-driven device for playing probably the best independent, internet radio station in Poland: Radio 357
The device is basically a WiFi radio player. It is actually not limited only to "Radio 357", but I've built it with this particular radio station in mind and tested it only on this radio station. The device can easily play any Revma stream with a simple configuration change. The stream can be either MP3 or AAC. The device can connect via WiFi to a Revma host and parse the redirection instruction that Revma uses to direct the client to the actual audio stream.
I've built Radyjko 357 around Adafruit Feather M0 WiFi with ATWINC1500 and Adafruit Music Maker FeatherWing. These are not the cheapest components for building an internet radio player, but this is what I had lying around and since they are part of the same system (Adafruit Feather), they are perfectly compatible. The loudspeaker was part of a two-piece set from Tracer called Orlando 2.0 (shown below). It's a USB speaker set with an amplifier and volume control.
Other components include a LiPo 2500mAh battery, a LiPo charging module, a potentiometer for volume control, some resistors and a FeatherWing Doubler:
After connecting, the components looked like this:
Note the volume control thingy in the bottom, right corner of the photo above. It contains a simple amplifier that works quite well in this setup even though it was meant to work with 5V and gets only ~3.7V.
The housing of each speaker is mostly empty...
... so it can easily fit all components:
Since the Feather M0 and the Music Maker are both "Feathers", they share the same pinout. I've used the FeatherWing Doubler to connect the two boards and thus I did not have to solder any connections between them.
All I needed to do is to define the pins that M0 will use to control the Music Maker. There are also two pins used for reading the volume potentiometer and the battery voltage divider:
M0 Pin | Connected to |
---|---|
20 | VS1053 reset pin |
6 | VS1053 chip select pin |
10 | VS1053 data select pin |
9 | VS1053 data request interrupt pin |
5 | SD card chip select pin |
A5 | Volume pot. input |
A4 | Battery voltage input |
The whole software (firmware) for Radyjko 357 is in just one Arduino source file called radyjko-357.ino
.
The program requires four libraries (available in Arduino IDE):
- SPI
- WiFi101
- SD
- Adafruit_VS1053
There's also a header file (vs1053b-patches.h
) with firmware patches for VS1053b - the MP3 decoder. Applying those patches is crucial as without them, the Music Maker will not be able to play chunks of MP3 or AAC audio stream. You will find the call that applies the patches in the initAudioPlayer()
function.
Another piece of firmware that needs updating, for this whole contraption to work, is the ATWINC1500 WiFi module. The Arduino IDE contains a special tool for doing just that. The update procedure is a bit involved, but fortunately the folks at Adafruit did a good job at describing this process on this website.
The configuration for Radyjko 357 is stored on a microSD card. The card needs to be in FAT32 format so that it can be read using the standard SD library for Arduino. Besides that, there are no special requirements. The amount of data stored on the card is quite small:
- one configuration text file
- one small MP3 file with a jingle
The configuration file should be called config.txt
and, in its basic form, can contain only three parameters:
wifi-ssid
: SSID for your WiFi access pointwifi-password
: the password for the WiFi access pointstream-id
: Revma stream ID. For Radio 357 these are 'ye5kghkgcm0uv' for AAC format and 'an1ugyygzk8uv' for MP3
Thus, the file will look something like this (for playing AAC stream):
wifi-ssid=<your WiFi SSID>
wifi-password=<your WiFi password>
stream-id=ye5kghkgcm0uv
There's also an option to define a second access point like so:
wifi-ssid-1=<your WiFi #1 SSID>
wifi-password-1=<your WiFi #1 password>
wifi-ssid-2=<your WiFi #2 SSID>
wifi-password-2=<your WiFi #2 password>
stream-id=ye5kghkgcm0uv
Besides the configuration file, the SD card will also need to store two MP3 files: jingle.mp3
and alarm,mp3
. The former will be played by the player before it is ready to play the stream while the latter is used for notifying the user about the battery level. Both sound files are played during startup and they improve the perceived performance as the device does need a few seconds to connect to the WiFi access point, then to Revma host, parse the redirect response from Revma main server and then start playing the audio stream. Without the jingle, you would hear only silence for a few seconds and that could be a bit confusing - especially since the device has no screen or even blinking LEDs.
For battery level notification, te device plays three tones in quick succession when the battery is full, two when it is half full and one when it should be recharged.
Radyjko 357 has only one control - the volume knob at the top. It's a potentiometer with a switch so it can be used to turn the device on and off and set the volume.
After turning the device on, the firmware does the following sequence of operations:
- Initializes the SD card reader
- Reads the
config.txt
file - Initializes the VS1053b audio decoder chip
- Plays the battery level notification
- Initializes the ATWINC1500 WiFi module
- Connects to
stream.rcs.revma.com
to obtain the URL for the audio stream - Starts playing the jingle
The main loop does two things:
- Fetches the redirect instruction, parses it and opens the actual audio stream
- Reads a chunk of data from the audio stream and into a ring buffer and then reads another chunk from that buffer and into the VS1053b decoder.
The ring buffer is currently only 250kB long (constant AUDIO_BUFFER_SIZE
) so it does require a rather stable connection.
The Revma stream isn't infinite and after some time the connection is closed. The device is able to detect that and reconnect but it does so be restarting the whole streaming process and resetting the buffer. This creates a rather lengthy gap in the produced audio. It should be possible to restart the stream without clearing the buffer and thus reduce or eliminate the gap.