Designed by:

Vassilis Serasidis on 5 September 2015

If you like my project please consider a donation for supporting my website www.serasidis.gr

Published on:

17 September 2015

Programming language:

C++

IDE:

mbed

Target MCU:

WIZwiki-W7500 board

Extra used hardware:

VS1053 MP3 decoder

WIZwiki-W7500

The WIZwiki-W7500 Cortex-M0 platform board.

Introduction

On 31 August 2015 I got the new WIZnet platform board, the WIZwiki-W7500 that is based on a Cortex-M0 cpu at 48MHz with 128 kBytes of flash memory and 48 kBytes of RAM shared with the hardwired TCP/IP core. The RAM amount used by the TCP/IP core can be upto 32 kBytes leaving the rest 16 kBytes to the user (32 + 16 = 48 kBytes of RAM). The W7500 is a 3.3V device but according to the WIZnet the board's I/O pins are 5V tolerate. Moreover, the board has the same pinout with the Arduino UNO. Combining this board with a VS1053 mp3 decoder board you can build a very nice Icecast Internet streams player (WebRadio player) that can plays internet audio streams upto 320 kbits/second (320 kbps). Of course the limited RAM on W7500 receiver side (16 kBytes) is not enough to cover big data delays between your internet connection gateway (your ADSL router) and the Icecast server.  

 

The circuit

The circuit is very simple and combines only two boards. The WIZwiki-W7500 (W7500 for short) and the VS1053 mp3 decoder module. The W7500 board makes a connection to the Icecast server, requests the audio data stream and sends the received data to the the VS1053 module for decoding. The VS1053 module, receives the data stream from the W7500 and auto-recognize the audio data format. It recognizes if the data stream is midi or wav or mp3 or aac file format and decodes it. The user can listen to the music stream over the VS1053 audio jack that leads the head phones. The circuit is powered with 5V DC from the USB port of the W7500 board. The W7500 ethernet connector is connected to the ADSL router or to any ethernet device that can provide Internet connection (router, hub, switch).  The connection diagram is based on a real boards photo for being recognized from any person that wants to build the circuit but he doesn`t have any experience in electronic circuit schematic diagrams. Just connect the two end points accross every colored line by following the picture 1 connection digram.

Highslide JS

Picture 1. The connections between the WIZwiki-W7500 and VS1053 boards (Click to enlarge).

 

The circuit does not contain any LCD screen for hardware simplicity. Instead of printing the information on LCD, the WebRadio station information is printed on the USB_Serial port that provides the W7500 board. Just connect the W7500 USB port to your computer, install the drivers and open your favorite Serial Terminal. In my case, I used the Termite v3.1 with settings 115200 bps.

 

Highslide JS   Highslide JS   Highslide JS

WebRadio Station information from the Icecast servers.

 

The source code

The source code has been written in mbed online compiler and the programming language is used is C++. There are many comments on the source code to help you understand the meaning of almost every line of the source code.

The mbed has a VS1053 library that was written by Kaoru Onoe and has been modified from me (Vassilis Serasidis) for supporting the W7500 board and adding a patch [ modeSwitch() function] for some LC-Technology VS1053 board that have some chip pins disconnected. Without that patch there is no sound out of these VS1053 modules.

The Ethernet library (WIZnetInterface) is provided by WIZnet and can be found in mbed libraries. To that library you have to change the default settings of 8 Sockets, 2 kBytes Transmitter and 2 kBytes receiver buffer for each socket. The settings we want are: Only one socket with 16 kBytes transmitter and 16 kBytes receiver buffer. These settings can be changed by editing the file:

WIZnetInterface/arch/int/W7500x_toe.cpp

    Before

164
165
166
167
168
169
170
	/*
	 * set RX and TX buffer size
	 * for (int socket = 0; socket < MAX_SOCK_NUM; socket++) {
	 * 	sreg<uint8_t>(socket, Sn_RXBUF_SIZE, 2);
	 * 	sreg<uint8_t>(socket, Sn_TXBUF_SIZE, 2);
	 * }
	 */
                                        

    After

164
165
166
167
168
169
170
171
172
173
174
175
176
	/*
	 * set RX and TX buffer size
	 * for (int socket = 0; socket < MAX_SOCK_NUM; socket++) {
	 * 	sreg<uint8_t>(socket, Sn_RXBUF_SIZE, 2);
	 * 	sreg<uint8_t>(socket, Sn_TXBUF_SIZE, 2);
	 * }
	 */
	 
	 /**
	  * Use only one socket with 16 kBytes of RAM for Tx and 16 kBytes of RAM for Rx 
	  */
	 sreg<uint8_t>(0, Sn_RXBUF_SIZE, 16); //Vassilis Serasidis
	 sreg<uint8_t>(0, Sn_TXBUF_SIZE, 16); //Vassilis Serasidis
                                                                                

     

    The main.cpp file is the following

    main.cpp

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/**
 *     WebRadio player 2  (Icecast music streams player)
 *
 *     Listen to your favorite WebRadio music stations up to 320 kbps !
 *
 *     Used components: VS1053 MP3 decoder and WIZ-wiki-W7500 ARM Cortex-M0 board
 *
 *     5 September 2015 by Vassilis Serasidis
 *   
 *     Home: http://www.serasidis.gr
 *     email: avrsite@yahoo.gr
 *
 *     Edit the file "W7500x_toe.cpp" and add the following lines:
 *     
 *       **
 *       * Use only one socket with 16 kBytes of RAM for Tx and 16 kBytes of RAM for Rx 
 *       *
 *       sreg<uint8_t>(0, Sn_RXBUF_SIZE, 16); //Vassilis Serasidis
 *       sreg<uint8_t>(0, Sn_TXBUF_SIZE, 16); //Vassilis Serasidis
 *
 *     -= NOTE =-
 *     This project is provided as-is without any waranty, under the GNU General Public License v3 
 *     ( http://www.gnu.org/licenses/gpl-3.0.en.html )
 * 
 */

#include "mbed.h"
#include "VS1053.h"
#include "EthernetInterface.h"

#define BUFFER_LENGTH    1024
#define BUFFER_LENGTH2     32
#define MAX_RADIO_STATIONS 18 // 18 pre-defined webradio station. You can increase the number if you want.

VS1053 player(D11, D12, D13, D10, D9, D8, D7); // mosi, miso, sck, cs, dcs, dreq, rst
               
char ramBuffer[BUFFER_LENGTH];
int radioStationNumber = 0; //Initial webradio station

Serial com(USBTX, USBRX); //Create a Serial Port instance.

typedef struct station {
    char const * rAddress;
    unsigned int port;
} STATION;

/**
 * 18 pre-defined webradio stations. 
 * You can increase the number of the stations because there is plenty of memory bytes.
 * Syntax: {"WebRadio_station_address", port_number}
 */
const STATION stations[MAX_RADIO_STATIONS] = { 
    {"ks386954.kimsufi.com", 8248},    // <01> La Grosse Radio Metal - Hard Heavy - From Paris ::  48 kbps :: aacp
    {"205.164.62.15",10032},           // <02> 1.FM - GAIA                                     ::  64-kbps :: aacp
    {"205.164.36.153",80},             // <03> BOM PSYTRANCE (1.FM TM)                         ::  64-kbps :: aacp
    {"topfm-st1.kbcnet.rs",80},        // <04> TOP FM Beograd 106,8                            ::  64-kpbs :: mpeg
    {"80.86.82.101",8130},             // <05> Cosmoradio 95.1 - Thessaloniki - Greece         :: 128 kbps :: mpeg
    {"s10.voscast.com",9940},          // <06> Zoo Radio 90.8 Greece                           :: 128 kbps :: mpeg
    {"radio.onweb.gr",8078},           // <07> 1055 ROCK - THESSALONIKI - GREECE               :: 128 kbps :: mpeg
    {"149.255.59.162", 8030},          // <08> ORIGINUK.NET DRUM AND BASS AND OLDSKOOL         :: 128 kbps :: mpeg
    {"uk3.internet-radio.com", 8060},  // <09> Champion 5768 FM - Non Stop Hits From All Eras  :: 128 kbps :: mpeg
    {"46.41.129.195", 8000},           // <10> Trance1.FM                                      :: 128 kbps :: mpeg
    {"uk3.internet-radio.com", 10523}, // <11> Tonik Radio Ireland                             :: 192 kbps :: mpeg
    {"95.141.24.4", 80},               // <12> #MUSIK.CLUB (DANCE) - WWW.RAUTEMUSIK.FM         :: 192 kbps :: mpeg
    {"193.34.51.33", 80},              // <13> WackenRadio.com - Metal Rock Alternative        :: 192 kbps :: mpeg
    {"uk4.internet-radio.com",15938},  // <14> GoHamRadio - Trance Dance Progressive Chillout  :: 256 kbps :: mpeg
    {"206.190.152.194", 8000},         // <15> PARTY VIBE RADIO: Reggae   Roots   Dancehall    :: 256 kbps :: mpeg
    {"213.251.157.145", 8016},         // <16> Audiophile Baroque Clasic Music                 :: 320 kbps :: mpeg
    {"83.137.145.141", 14280},         // <17> Nautic Radio - Beats 'n Breaks - drum and bass  :: 320 kbps :: mpeg
    {"50.7.173.162", 8014}             // <18> Audiophile Jazz                                 :: 320 kbps :: mpeg
};


/*************************************
 *
 *************************************/
int main() {
    
    int i,m;
    
    DigitalIn dreq(D8); //Set DREQ pin as input (D8).
    DigitalIn sw1(D5);  //Next webradio station selection button (D5).
    DigitalIn sw2(D6);  //Previous webradio station selection button (D6).
    
    com.baud(115200);   //Set the Serial port baud rate to 115200 bits/second
    
    com.printf("---------------------------------------\n");
    com.printf("\n          WebRadio player\n");
    com.printf("(c) 05 Sept 2015 by Vassilis Serasidis\n");
    com.printf("      Home: http://www.serasidis.gr\n");
    com.printf("---------------------------------------\n");
    uint8_t mac_addr[6] = {0x00, 0x08, 0xDC, 0x00, 0x01, 0x02}; //Ethernet MAC address
    EthernetInterface eth; 
    com.printf("Getting IP address...\n");
    eth.init(mac_addr); //Use DHCP to get the IP from the ADSL router (from the DHCP server).
    eth.connect();
    printf("Local IP Address: %s\r\n", eth.getIPAddress()); //Print the local IP address.
    TCPSocketConnection client; //Create a client.
    
    player.hardwareReset(); //Do a reset to the VS1053 board.
    player.clockUp();       //Set the VS1053 at faster SPI speed.
    player.modeSwitch();    //Patch the VS1053 board to play MP3 files (very important!).
    player.setVolume(44);   //Set the VS1053 volume. Value 0 is MAX volume, 255 is mute.
    
    while(1){
        com.printf("\n----------------------------------------------\n");
        com.printf("Connecting to [%s] ...\n",stations[radioStationNumber].rAddress);
        
        /* Connect to the Icecast server defined by 'radioStationNumber' variable (1-18) */
        client.connect(stations[radioStationNumber].rAddress, stations[radioStationNumber].port);
        
        /* Check if the client was connected to the server */
        if(client.is_connected()){
            com.printf("Connected!\n\n");    
        }else{
            //com.printf("Is NOT connected. Please try again.\n");
            for(;;); //Stay here for ever.
        }
        
        client.send("GET / HTTP/1.1\r\n",16); //Send the Header to the Server.
        client.send("\r\n",2);
        wait(0.5);
    
        com.printf("Reading Icecast radiostation information...\n");
        /* Read the Icecast server information (station name, bit rate and more)*/
        client.receive(ramBuffer, BUFFER_LENGTH); //Store the received data to the RAM buffer.
        com.printf("Done!\n\n");
        
        com.printf("<%d> ",radioStationNumber + 1); //Print the station number (1-18)
        
        /**
         * From the 1024 received bytes extract only the WebRadio station information.
         * The information data ends with the bytes \r\n\r\n
         * In other words, ends with the four hexadecimal bytes [0x0d 0x0a 0x0d 0x0a] . 
         */
        for(i=0;i<(BUFFER_LENGTH - 4);i++){ 
          if((ramBuffer[i] == 0x0d)&&(ramBuffer[i+1] == 0x0a)&&(ramBuffer[i+2] == 0x0d)&&(ramBuffer[i+3] == 0x0a))
            break; //If you found the end-sequence then break the <for> loop.
          else
            com.putc(ramBuffer[i]);
        }
        com.printf("\n");
        
        
        /* Do that loop forever */  
    
        m = 1;
        
        while(m > 0){ 
            client.receive(ramBuffer, BUFFER_LENGTH2);        
            while(!dreq);
            if(sw1){ //If the NEXT button is pressed,
                if(radioStationNumber < MAX_RADIO_STATIONS - 1 )
                    radioStationNumber++; //select the NEXT webradio station. 
                else
                    radioStationNumber = 0;
                m = 0; //Exit from this loop.
            }
            
            if(sw2){ //If the PREVIOUS button is pressed,
                if(radioStationNumber > 0)
                    radioStationNumber--; //select the PREVIOUS webradio station. 
                else
                    radioStationNumber = MAX_RADIO_STATIONS - 1;
                m = 0; //Exit from this loop. 
            }
            player.sendDataBlock(ramBuffer, BUFFER_LENGTH2);    // and pass the data to the VS1053 MP3 decoder module.
        }
          
    }
}

 

My WebRadio player 2 demonstration

 

Created and published by Vassilis Serasidis on 17 September 2015