[allmost solved] How to use RDA5807

Hi, I have a RDA5807 FM-Module connected to the arduino. There is some example code to set the frequency - this works!

Now, the module has the ability to seek for another station (up and down). After long search, I found the datasheet! There is described (page 9ff), that the Register 02H, bit 8 enables seek and bit 9 controls the direction (up or down).

If I want to seek up, I know what to do in words: 1. Read the register 2. Set the bits 3. Write the register

With the example, I can not imagine what to do exactly. Hopefully one of you can tell me the instructions needed.

Here is how the frequency is set (from the exampe):

void setFrequency()
 {
   frequencyB = 4 * (frequency * 1000000 + 225000) / 32768;
   frequencyH = frequencyB >> 8;
   frequencyL = frequencyB & 0XFF;
   Wire.beginTransmission(0x60);
   Wire.write(frequencyH);
   Wire.write(frequencyL);
   Wire.write(0xB0);
   Wire.write(0x10);
   Wire.write((byte)0x00);
   Wire.endTransmission();
   delay(100);
 }

EDIT: Ideas for a solution can be found here

That example code is for I2C address 0x60. If that I2C address is used, the RDA5807 is in TEA5767 mode. So you should have a look for the TEA5767 datasheet, and TEA5767 arduino code.

For the full RDA5807, it should be used via I2C address 0x10 or 0x11. I could not find an Arduino library for that. Which would be nice, since the chip is better than the old TEA5767.

Here is an attempt: http://forum.arduino.cc/index.php?topic=173276.0

Thanks

It is not easy to understand. Well, referencing on some TEA5767 code:

#define TEA5767_MUTE_FULL        0x80

That defines bit 7.

unsigned char TEA5767_buffer[5]={0x00,0x00,0xB0,0x10,0x00};

That defines an array, representing all 5 DataBytes of the TEA5767.

TEA5767_buffer[0] |= TEA5767_MUTE_FULL;

That sets the “Mute-Bit” in the first DataByte

  for(byte i=0;i<data_size;i++)
    Wire.write(TEA5767_buffer[i]);

Finally, this writes all the DataBytes to the TEA5767.

Well, this makes sense and I have the understanding from datasheet to code.

In the datasheet (linked in the first post) of the RDA5807 is another notation that I do not fully understand. In the Register 02H, there is Bit 14 representing Muting (0 = Mute).

Datasheet says: “The I2C interface has a fixed start register address (0x02h for write transfer and 0x0Ah for read transfer), and an internal incremental address counter”.
Does this mean, that I can use the Buffer-Method above and the Register 02H correspond to the Array[0] (Array[1] is for the first 8 Bit, Array[0] for the second 8 Bit)? Because: “MCU programs registers from register 0x02h high byte, then register 0x02h low byte, then register 0x03h high byte, till the last register”?

Damn, it is easy if one no how to read… Hope I’m on the right way. Thanks for confirmation or some clarification.

I noticed that, and I'm also puzzled by it. Perhaps the fixed addresses are for some kind of faster and easier access, but for the Arduino it is not easier at all. Maybe I2C address 0x10 has those fixed register addresses, and maybe I2C address 0x11 can normally access the registers. But the datasheet does not provide enough information how to use that.

It is one of the most incomplete and unclear datasheets I have seen.

Hmpf!

So, I prepare an example for mute and try'n'error it.

Hi all

Well, there is some usefull code in the web!

First of all, most examples use the tea-compatibility mode of programming. This is not what I was looking for.

In this post here is a good testcode from Harald A. - but in german. Well find below the demo-code from him. Based on that, an implementation is very easy, especially with the shown mode with random access!!!

Also the website from http://arduino.vom-kuhberg.de shows a good project (follow the menu Projekte → RDA Radio). There you have more ideas to use the whole functionality - and with a command-line-interface! Well, only a few functions worked because the input was not recognised. The Code itself gives enogh ideas to do the own stuff.

Well, I had the idea to write a Library. But I think that my skills are not good enough to do it. If you have any question, write it down anyway

So, here the testcode:

#include <Wire.h>

 unsigned char freqH = 0, freqL = 0, c, i;
 unsigned int frequencyB, freq, freqB;
// double frequency = 0;

 
 void setup()
 {
   Wire.begin();

   freq = 892;                            // 89.2 MHz
   freqB = freq - 870;
   freqH = freqB>>2;
   freqL = (freqB&3)<<6;                  // Shift channel selection for matching register 0x03
   
   Serial.begin(9600);

   Wire.beginTransmission(0x11);          // Device address 0x11 (random access)
   Wire.write(0x02);                      // Register address 0x02
   Wire.write(0xC0); Wire.write(0x03);    // write 0xC002 into Reg.3 (soft reset, enable)
   Wire.endTransmission();                // stop condition
   delay(500);                            // wait 500ms

   Wire.beginTransmission(0x11);
   Wire.write(0x02);
   Wire.write(0xC0); Wire.write(0x0D);    // write 0xC00D (RDS on etc.) into 0x02
   Wire.endTransmission();
   delay(500);   
   
   Wire.beginTransmission(0x11);
   Wire.write(0x03);
   Wire.write(freqH);                     // write frequency into bits 15:6, set tune bit
   Wire.write(freqL + 0x10);
   Wire.endTransmission();
 }

 
// LOOP is optional for accessing RDS raw data, leave emoty if not required

 void loop()
 {
   Wire.beginTransmission(0x11);       // Device 0x11 for random access
   Wire.write(0x0C);                   // Adress 0x0C
   Wire.endTransmission(0);            // restart condition

   Wire.requestFrom(0x11, 8, 1);       // Retransmit device address with READ, followed by 8 bytes

   c = Wire.read();
   if (c <= 0x0F) Serial.print("0");   // print PI high byte
   Serial.print(c, HEX);

   c = Wire.read();
   if (c <= 0x0F) Serial.print("0");   // print PI low byte
   Serial.print(c, HEX);

   Serial.print(" ");

   c = Wire.read();
   if (c <= 0x0F) Serial.print("0");   // print block B (PTY, TP and GT) high byte
   Serial.print(c, HEX);

   c = Wire.read(); 
   if (c <= 0x0F) Serial.print("0");   // and low byte
   Serial.print(c, HEX);
   Serial.print(" ");

   Serial.write(Wire.read());          // print content of block C and D (4 bytes)
   Serial.write(Wire.read());
   Serial.write(Wire.read());
   Serial.write(Wire.read());

   Serial.print("\r\n");
   Wire.endTransmission();             // stop condition
 }

Thanks for sharing, I'm going to order one and use the random access via 0x11.

It is great for my application (radio in a toy farm of my daughter).

Be aware of the following: Wire.write(0xC0); Wire.write(0x03); // write 0xC002 into Reg.3 (soft reset, enable) The write of 0x03 sets the reset-bit.

If you don't need the RDS-Set-Part do a second write anyway to remove the reset-bit. If not, you will never hear anything. I think, that costs the have of one night...

Following some snipplets of my code.

// Mini-Setup
   RDA5807_05H_val = setBit(RDA5807_05H_val, RDA5807_INTMODE);
   RDA5807_05H_val = setBit(RDA5807_05H_val, RDA5807_SEEKTH);
   RDA5807_05H_val = setBit(RDA5807_05H_val, RDA5807_VOLUME);
   RDA5807_Write(RDA5807, RDA5807_05H, RDA5807_05H_val);

   RDA5807_02H_val = setBit(RDA5807_02H_val, RDA5807_DHIZ);
   RDA5807_02H_val = setBit(RDA5807_02H_val, RDA5807_DMUTE);
   RDA5807_02H_val = setBit(RDA5807_02H_val, RDA5807_NEWMETHOD);
   RDA5807_02H_val = setBit(RDA5807_02H_val, RDA5807_ENABLE);
   RDA5807_02H_val = setBit(RDA5807_02H_val, RDA5807_RESET);
   RDA5807_Write(RDA5807, RDA5807_02H, RDA5807_02H_val);
   RDA5807_02H_val = clrBit(RDA5807_02H_val, RDA5807_RESET);
   RDA5807_Write(RDA5807, RDA5807_02H, RDA5807_02H_val);

RDA5807_02H_val and ...05H_val are variables they store the desired register. To help me later, I set all Bits in their own line. But important on it, the last write removes the reset-bit.

The write-function is very easy:

  byte RDA5807_Write(byte bAdr, byte bReg, word wVal) {
    Wire.beginTransmission(bAdr);
    Wire.write(bReg);
    Wire.write(wVal >> 8); 
    Wire.write(wVal & 0xFF);
    return Wire.endTransmission();
    }

And if someone is interest of the setBit-function, here is an asortment of used mini-functions:

 word setBit(word wReg, word wBit) {
   wReg |= wBit; //set wBit in wReg
   return wReg;
   }

word clrBit(word wReg, word wBit) {
   wReg &= ~wBit; //clear wBit in wReg
   return wReg;
   }

word tglBit(word wReg, word wBit) {
   wReg ^= wBit; //toggle wBit in wReg
   return wReg;
   }

boolean chkBit(word wReg, word wBit) {
   if (wReg & wBit) return true; //true if wBit is set in wReg
   else return false;
   }

Oh, and some of the definition:

// Modul Setup
#define RDA5807            0x11                  // I2C-Address RDA Chip for random Access / 0x10; for sequential  Access / 0x60 for TEA5767like Access

// Bits in Register 02H
#define RDA5807_ENABLE     0x0001
#define RDA5807_RESET      0x0002
#define RDA5807_NEWMETHOD  0x0004
#define RDA5807_RDS        0x0008
#define RDA5807_CLK1       0x0010              
#define RDA5807_CLK2       0x0020
#define RDA5807_CLK3       0x0040
#define RDA5807_SKMODE     0x0080
#define RDA5807_SEEK       0x0100
#define RDA5807_SEEKUP     0x0200
#define RDA5807_RCLK-DI    0x0400
#define RDA5807_RCLK-NC    0x0800
#define RDA5807_BASS       0x1000
#define RDA5807_MONO       0x2000
#define RDA5807_DMUTE      0x4000
#define RDA5807_DHIZ       0x8000

// Bits in Register 05H
#define RDA5807_VOLUME      0x000F              //sets only half volume
#define RDA5807_RSVD2       0x0000
#define RDA5807_SEEKTH      0x0200
#define RDA5807_RSVD1       0x0000
#define RDA5807_INTMODE     0x8000


// Register Addresses
#define RDA5807_02H        0x02
#define RDA5807_03H        0x03
#define RDA5807_04H        0x04
#define RDA5807_05H        0x05
#define RDA5807_0AH        0x0A
#define RDA5807_0BH        0x0B
#define RDA5807_0CH        0x0C

Great, very interesting! I will follow this topic. I've just bought this module and I'm interested to get time info from RDS, for a simple table clock project.

Oops, I just ordered a RDA5807P, and the RDS is on the chip RDA5807M. So I'm ordering also that one.

nique: Hi all

Well, there is some usefull code in the web!

First of all, most examples use the tea-compatibility mode of programming. This is not what I was looking for.

In this post here is a good testcode from Harald A. - but in german. Well find below the demo-code from him. Based on that, an implementation is very easy, especially with the shown mode with random access!!!

Also the website from http://arduino.vom-kuhberg.de shows a good project (follow the menu Projekte --> RDA Radio). There you have more ideas to use the whole functionality - and with a command-line-interface! Well, only a few functions worked because the input was not recognised.

I let input working changing the line (587):

if (i_key == 13) {CLI_exec (); }

to

if (i_key == 10) {CLI_exec (); }

OK, I made some good steps forward. Now I can parse PS and CT (time and date) correctly. What it looks not working is "seek" function. When search starts, it doesn't stop and frequency goes to 118!

I have try RDA5807M and success using TEA5767 mode. But when I use the RDA5807 mode, it is not success. I can't hear anything. I want to set RDA5807 to be, stereo, frequency 76MHz, 32.768 KHz, no interrupt, max volume I write the register. 02h : 0xC0,0x00 03h : 0x00,0x04 04h : 0x00,0x00 05h : 0x88,0xAF

Then, I can't hear anything. I use TEA5767 code again and the sound appear.

Please let me know if there are any mistake with the data I write to the register

I am attempting to use the RDA5807 in RDA5807 MODE and NOT in TEA MODE, here is the code I have kludged together to test-develop with:

// Test and experimental code to work out the handling of the RDA5807 registers

// CODE BEGINS ////////////////////////////////////////////////
#include <Wire.h>

typedef union X
{
uint16_t wBuffer[16];
uint8_t bBuffer[32];
} x;

typedef union Y
{
uint8_t RbUFFER[6];
uint8_t rBuffer[12];
} y;

y buf;

boolean monoBit = false;
boolean bassBit = true;

uint8_t rr[2];

typedef union REGISTERS
{
uint8_t regs[32];
uint16_t REGS[16];
} registers;

x BUFFER;

void setup(void)
{
// pinMode(A4, INPUT_PULLUP);
// pinMode(A5, INPUT_PULLUP);
registers r;
Wire.begin();
Serial.begin(9600);
/*
Wire.beginTransmission(0x10);
Wire.write(0x00);
Wire.endTransmission();

loadBuffer();

Wire.requestFrom(0x10, 32);
for(int i = 0; i < 32; i++)
r.regs = Wire.read();

  • for(int j = 0; j < 32; j += 2)*

  • {*

  • Serial.print(r.regs[j], HEX);*

  • Serial.print("H ");*

  • Serial.print(r.regs[j + 1], HEX);*

  • Serial.println(‘H’);*

  • }*
    _*/ _

  • loadBuffer();*

  • Wire.requestFrom(0x11, 32);*

  • for(int i = 0; i < 32; i++)*
    _ r.regs = Wire.read();_

* for(int j = 0; j < 32; j += 2)*
* {*
* Serial.print(r.regs[j], HEX);*
* Serial.print("H ");*
* Serial.print(r.regs[j + 1], HEX);*
* Serial.println(‘H’);*
* }*
* }*

void loop()
* {*
* DEBUG();*
* delay(5000);*
* }*
/* The following is meant to initialize the 5807, and put it in a stable, useable state, and having it tuned to a station */
void loadBuffer(void)
* {*
* uint16_t t;*

_ t = ((20 * 1) + 87);
* BUFFER.bBuffer[0] = 0x00;*
* BUFFER.bBuffer[1] = 0x58;*
* BUFFER.bBuffer[2] = 0x00;*
* BUFFER.bBuffer[3] = 0x00;*
* BUFFER.bBuffer[4] = 0xb11010010;*
* BUFFER.bBuffer[5] = 0xb10000011;*
* BUFFER.wBuffer[3] = (t << 6);*
* BUFFER.bBuffer[7] | 0xb0001001;*
* BUFFER.bBuffer[8] = 0xb00000000;*
* BUFFER.bBuffer[9] = 0xb00000000;*
* BUFFER.bBuffer[10] = 0xb00001000;*
* BUFFER.bBuffer[11] = 0xb00001111;*
* BUFFER.bBuffer[12] = 0xb00000000;*
* BUFFER.bBuffer[13] = 0xb00000000;*
* BUFFER.bBuffer[14] = 0xb01000000;*
* BUFFER.bBuffer[15] = 0xb00000000;*
* Wire.beginTransmission(0x10);*
* for(int i = 0; i < 16; i += 2)*
* {*
Wire.write(BUFFER.bBuffer*);
Wire.write(BUFFER.bBuffer[i + 1]);
}
delay(100);
Serial.print("initialization returns: ");
Serial.println(Wire.endTransmission());*_

* }*

void DEBUG(void)
* {*
* int ctr = 0X0A;*

/* The following is intended to read the registers 0x0AH-0x0FH and tell me the relevant data */
* Serial.println(“DEBUG…”);*
* Wire.requestFrom(0x11, 12, 1);*
* for(int i = 0; i < 12; i++)*
* {*
_ buf.rBuffer = Wire.read();
* }*_

* for(int j = 0; j < 12; j += 2)*
* {*
* Serial.print("REGISTER ");*
* Serial.print(ctr++, HEX);*
* Serial.print(" = ");*
* if((buf.rBuffer[j] & 0b11110000) == 0x00)*
* Serial.print(‘0’);*
* Serial.print(buf.rBuffer[j], HEX);*
* Serial.print(’ ');*
* if((buf.rBuffer[j] & 0b00001111) == 0x00)*
* Serial.print(‘0’);*

* if((buf.rBuffer[j + 1] < 16) == 0x00)*
* Serial.print(‘0’);*
* Serial.print(buf.rBuffer[j + 1], HEX);*
* if((buf.rBuffer[j + 1] > 0x1F) == 0x00)*
* Serial.print(‘0’);*

* Serial.println("H ");*
* Serial.print("SIGNAL = ");*
* Serial.println((buf.RbUFFER[3] >> 1));*
* }*
* Serial.println(“END DEBUG…”);*
* Serial.println();*
* }*
// CODE ENDS
Perhaps grrus at handling hardware register, and with a much better understanding can remark and point out the errors I have.
The most confusing point I am at, when I real the registers at ADDR 0x11, they keep changing, as if the chip is scanning-etc.
And help, knowlege, advise, expertise, would be GREATLY appreciated – I am thinking I am NOT handling the writing/reading of these registers correctly.
Thanks, in advance!

Hi,

I am working with this FM chip, but I'm very confused when I'm reading datasheet. Maybe anyone knows, which new demodulation method is used (reg 0x02, bit 2)? What is difference between soft reset and reset?

Thanks for answers!

Hi

I know this is late, but the most complete libraries that I could find for these chips are here:

http://mathertel.de/Arduino/RadioLibrary.aspx

HTH

Regards

Chris