element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
    About the element14 Community
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      •  Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Personal Blogs
  • Community Hub
  • More
Personal Blogs
Legacy Personal Blogs Controlling the RDA5807SP FM Radio Receiver with the Raspberry Pi
  • Blog
  • Documents
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: packetgeek
  • Date Created: 19 Jan 2014 6:33 AM Date Created
  • Views 10447 views
  • Likes 3 likes
  • Comments 37 comments
  • raspberry
  • pi
  • fm
  • proof-of-concept
  • radio
Related
Recommended

Controlling the RDA5807SP FM Radio Receiver with the Raspberry Pi

packetgeek
packetgeek
19 Jan 2014

I received a handful of gift certificates for Christmas.  I used one to purchase a few breakout boards, one of them an RDS5807SP-based FM radio receiver (see Amazon.com: FM Radio Receiver Module -- Arduino Compatible: Everything Else).  Although it's designed to work with the Arduino, it is possible to get it working with the Raspberry Pi.  The very nice part is that it comes with an I2C-based control interface.

 

Before you purchase one, there's a few limitations (keep in mind I paid less than $2 for the thing).  In short, the Raspberry Pi provides power and control signals and DOES NOT receive the audio back.  Instead, the audio is output through the headphone jack. (I have "connect to USB sound card" on my to-do list.)

 

In any case, following are my notes on getting it up and running for the first time.  It only took a few hours (4?) in doing the research and

 

1) Parts list

 

  • One Raspberry Pi (with the usual power supply and network connections)
  • One Cobber interface (for connecting the GPIO header to the breadboard)
  • One breadboard (thanks to Drew Fustini!)
  • The aforementioned FM Radio Receiver Module
  • A handful of breadboard wires

 

2) Initially, I attempted to use just the I2C software (described here) that gets installed by running

 

    apt-get install i2c-tools

 

Sadly, I couldn't figure out how to control the receiver with just the i2cset and i2cget commands.  Note: If anyone else plays with this, please omit this step and tell me if installation is still needed.  (I seem to think that it is.)

 

3) Frustrated, I turned to Google.  After some reading, I noticed a few people indicating that the RDA5807xx chip is a clone of the TEA5767, so I went looking for anyone who'd hooked that to the Raspberry Pi.  This led me to Emmanuel Granatello's page on setting up the FM Radio Receiver on Raspberry Pi.   He didn't provide his code, so I kept looking.  I also ran across a number of videos showing the same thing, along with using WiringPi's gpio tool to set up the connection to the receiver.  Mixing all of that together in another search, I finally stumbled across "Raspberry Pi • View topic - I2C, wiringPi & tea5767", which does have the basic code needed to get the receiver working.  Just in case the page disappears, the working code is:

#include <wiringPi.h>

#include <wiringPiI2C.h>

#include <stdio.h>

#include <stdlib.h>

int main( int argc, char *argv[]) {

  printf ("RPi - tea5767 Philips FM Tuner v0.3 \n") ;

  unsigned char radio[5] = {0};

  int fd;

  int dID = 0x60; // i2c Channel the device is on

  unsigned char frequencyH = 0;

  unsigned char frequencyL = 0;

  unsigned int frequencyB;

  double frequency = strtod(argv[1],NULL);

  frequencyB=4*(frequency*1000000+225000)/32768; //calculating PLL word

  frequencyH=frequencyB>>8;

  frequencyL=frequencyB&0XFF;

  printf ("Frequency = "); printf("%f",frequency);

  printf("\n"); // data to be sent

  radio[0]=frequencyH; //FREQUENCY H

  radio[1]=frequencyL; //FREQUENCY L

  radio[2]=0xB0; //3 byte (0xB0): high side LO injection is on,.

  radio[3]=0x10; //4 byte (0x10) : Xtal is 32.768 kHz

  radio[4]=0x00; //5 byte0x00)

 

if((fd=wiringPiI2CSetup(dID))<0){

printf("error opening i2c channel\n\r");

}

write (fd, (unsigned int)radio, 5) ;

return 0;

}

Save the above as "radio.c" and compile it with "gcc -o radio radio.c -lwiringPi".  Credit for the above code goes to "halfluck" on the Raspberry Pi web site.

 

Note: the above code is very limited and doesn't exploit all of the controls available on the chipset.  I plan on expanding the above, once I get a better idea of what's involved.

 

4) Once you've done all of the above, the receiver is connected to the Raspberry Pi, and the Pi has booted, you can test the interface by running "i2cdetect -y 1".  The output should look something like:

  root@raspberrypi:~/work# i2cdetect -y 1
       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
  00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
  10: 10 11 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
  20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
  30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
  40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
  50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
  60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
  70: -- -- -- -- -- -- -- --  

Note: if you see only dashes in the above, the Pi is not "seeing" the receiver.  Check your connections.  (Initially, I had the Cobbler connected to the header backwards.)

 

If you see only "21 22" in the above, it means that your cable is likely connected properly.  You'll next want to run wiringPi's gpio tool and then the radio application.  I was able to hear a local radio station by running:

 

  gpio load i2c

  gpio i2cd

  ./radio 98.7

 

Note: the first line is required as it (supposedly) renumbers the headers and causes the i2c interface to reset.  The second line is optional.  I use it to "see" when the i2c interface is "online".  When "60" shows up in the output, it's okay to run the "radio" command.  The "98.7" in the above is the frequency (in MHz) of the local radio station.

 

That's about it.  The above code is halfluck's proof-of-concept.  I plan on doing horrible things to it (adding error detection and command line defaults, adding more controls, slapping a web front end on it, etc.), once I've dug into the chip specs and have figured out what the board will and won't support.  I'll eventually get back to editing this code.  Keep an eye out here.

 

Update (26 Dec 2014): The code for the various commands is attached. Updated notes to follow (they're a bit lengthy).

  • Sign in to reply
  • e14 Contributor
    e14 Contributor over 11 years ago

    Hello there and Merry Christmas!

    I'm not waiting but keep on following very careful your interesting posts and emails.

    Time is on our side :-)

    Happy new year with peace, health and love!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • packetgeek
    packetgeek over 11 years ago

    I now have working code for mute, unmute, and for searching upward/downward, as well as for tuning the radio and querying the frequency.  Once I'd relearned enough of bitwise operators and figured out the mute function, the other three (unmute, searchup, searchdn) were easy.  Will write up the notes and attach the code to a new blog post (can't attach codes to comments such as these).  de viant, you still waiting on me?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • packetgeek
    packetgeek over 11 years ago

    Proof of concept: status

     

    Following reads the registers in the chip, extracts the PLL word from the first two registers, and calculates the frequency to which the radio is tuned.  Save the following as "status.c".

     

    #include <wiringPi.h>

    #include <wiringPiI2C.h>

    #include <stdio.h>

    #include <stdlib.h>

     

    //compile with gcc -lwiringPi -o status status.c

    int main( int argc, char *argv[]) {

     

       unsigned char radio[5] = {0};

       int fd;

       int dID = 0x60; // i2c Channel the device is on

       double frequency = 0;

     

       //open access to the board, send error msg if fails

       if((fd=wiringPiI2CSetup(dID))<0){

          printf("error opening i2c channel\n\r");

       }

       read(fd,radio,5);

     

       frequency=((((radio[0]&0x3F)<<8)+radio[1])*32768/4-225000)/100000;

       frequency= ((int)(frequency*10+5)/100.0);

       printf ("Frequency = "); printf("%.1f\n",frequency);

     

      close(fd);

       return 0;

    }

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • packetgeek
    packetgeek over 11 years ago

    What I need to do with the above code is to figure out how to concatenate the PLL word and push it back through the frequency calculation, This will involve undoing the bitwise AND and the bitwise shift (occurs in the frequencyH and frequenceL lines).

     

    For anyone else that wants to experiment, the RDA5807SP chip appears to be a drop-in replacement for the TEA5767.  This is a good thing as most of the RDA5807SP documentation is in Chinese, while the docs for the TEA5767 are available in English.  To figure out which registers do what, visit the following link and search for the section entitled "I2C Registers".  Note that both chips have separate formats for writing and reading the registers.

     

      http://developer.mbed.org/users/edodm85/notebook/radio-fm-tea5767/

     

    The formula for calculating the PLL word (the one that I need to reverse) is at:

     

      https://www.electronicsblog.net//wp-content/uploads/pllcalculation.png

     

    I think the Arduino code at the following link will reverse the PLL word (needs conversion to wiringPi syntax and experimentation):

     

      https://www.electronicsblog.net/arduino-fm-receiver-with-tea5767/

     

    More detail on the tea5767 registers is available at:

     

      http://www.rockbox.org/wiki/pub/Main/DataSheets/application_note_tea5767-8.pdf

     

    If anyone's working on this breakout board, and is ahead of me code-wise, please share.  Otherwise, I'll keep playing with this.  It'll be slow going, as classes start up again soon, but I'll keep working on it as time becomes available.  The docs indicate that there's a version of the chip (RDA5807M?) that has a RDS function.  I'd love to have that working too.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • packetgeek
    packetgeek over 11 years ago

    It's cheesy but I have a working mute function (see the code below).  It's safe to leave out any line containing "mine" and/or the collection of commented out printf functions.  They're there for my experimentation.  Basically, I've added a second argument to the command line, so if you wanted to tune to 98.7 MHz, you'd use "radio 98.7 0" to tune to the station and "radio 98.7 1" to mute it.  This is horrible code as it's a poor work-around (follow the logic in the code and you'll see) and I'm having to relearn C programming after 20 years.  That said, it works (at least for 98.7 MHz).  I'll republish updates to the code here as I improve my coding skills.

     

    #include <wiringPi.h>

    #include <wiringPiI2C.h>

    #include <stdio.h>

    #include <stdlib.h>

     

    int main( int argc, char *argv[]) {

      printf ("RPi - RDA5807SP FM Tuner v0.1 \n") ;

      unsigned char radio[5] = {0};

      unsigned char mine[5] = {0};

      int fd;

      int dID = 0x60; // i2c Channel the device is on

      unsigned char frequencyH = 0;

      unsigned char frequencyL = 0;

      unsigned int frequencyB;

     

      //read the frequency from the command line

      double frequency = strtod(argv[1],NULL);

     

      //read from the command line if output should be muted?

      int muted = strtod(argv[2],NULL);

     

      //calculate the PLL word and split it between the first and second bytes

      frequencyB=4*(frequency*1000000+225000)/32768; //calculating PLL word

      frequencyH=frequencyB>>8;

      frequencyL=frequencyB&0XFF;

     

      printf ("Frequency = "); printf("%f",frequency);

      printf("\n"); // data to be sent

     

      if(muted==1){

            frequencyH=0x80;

      }

      radio[0]=frequencyH; //FREQUENCY H

      radio[1]=frequencyL; //FREQUENCY L

      radio[2]=0xB0; //3 byte (0xB0): high side LO injection is on,.

      radio[3]=0x10; //4 byte (0x10) : Xtal is 32.768 kHz

      radio[4]=0x00; //5 byte0x00)

     

      if((fd=wiringPiI2CSetup(dID))<0){

        printf("error opening i2c channel\n\r");

      }

     

      write (fd, (unsigned int)radio, 5) ;

     

      //read(fd,mine,5);

      //printf("r0 %u\n",radio[0]);

      //printf("m0 %u\n",mine[0]);

      //printf("r1 %u\n",radio[1]);

      //printf("m1 %u\n",mine[1]);

      //printf("r2 %u\n",radio[2]);

      //printf("m2 %u\n",mine[2]);

      //printf("r3 %u\n",radio[3]);

      //printf("m3 %u\n",mine[3]);

      //printf("r4 %u\n",radio[4]);

      //printf("m4 %u\n",mine[4]);

     

      close(fd);

      return 0;

    }

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
<>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2026 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube