Go Down

Topic: RDA5807SP FM Radio Receiver - i2C (Read 8135 times) previous topic - next topic

KC8OZA

It sounds like learning about this OR'ing operation is going to be useful to me.  Where can I learn more about how this works?


KC8OZA

Ok so after reviewing the binary math stuff, I think I get it.   SO let me ask you this.... I probably want to read the register, store the result, perform a binary OR against the data, adding the bits I want to change, and then push the whole string back out , correct?   There's nothing that's going to let me just send selected bits over I2C is there?  Just making sure, but I think I need to be sending the whole byte(s).

Josh

Grumpy_Mike

Quote
there's nothing that's going to let me just send selected bits over I2C is there?

Correct
Quote
I think I need to be sending the whole byte(s)

Yes.
Quote
I probably want to read the register, store the result, perform a binary OR against the data, adding the bits I want to change, and then push the whole string back out , correct?

Normally you would not read them, you would have variables set up in the processor modify the bits and write them out. You would only read them when you want to do something with the read bits that the radio can change.

Nick Gammon


So for example, lets say I want to write the register at 0x05, and set bits 0-3 as the value 1 (forget the other bits, they're not important yet), I'm doing whats shown below.   But its not working. When I read it back, its not how I set it.  What am I doing wrong?


Is it working yet? I'm guessing not.

Now that I read the datasheet you linked to, I have to say it is one of the more confusing documents I have read.

After staring at it for a while I think they are saying that the device address is in fact the register. So, for example, say we want to set some bits in register 2:

Code: [Select]
15: DHIZ (1)
14: DMUTE (1)
13: MONO (0)
12: BASS (1)
11: RESERVED (0)
10: CLK32 (0)
8-7: RESERVED (0)
6-4: CLK_MODE (0)
1: SOFT RESET (0)
0: ENABLE (1)


So lets turn them into bits with the example values above:

Code: [Select]
0b1101000000000010
 |      |       |
 15     8       0


So we may as well split them up ourselves:
Code: [Select]

byte highCommand = 0b11010000;
byte lowCommand  = 0b00000010;


If I'm right, we now need to send to register (address) 2 on the device:

Code: [Select]

Wire.beginTransmission (2);
Wire.write (highCommand);
Wire.write (lowCommand);
Wire.endTransmission ();


And to get them back:

Code: [Select]
if (Wire.requestFrom (2, 2) != 2)  // read from register 2, for 2 bytes
 {
 // error
 return;
 }

byte readHigh = Wire.read ();
byte readLow = Wire.read ();


Try that and see. Also try my I2C scanner on this page:

http://www.gammon.com.au/i2c

If my theory is correct you will see it reporting that addresses 2, 3, 4, 5, 0x0A, 0x0B are on the bus.
 
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

KC8OZA

#20
Apr 30, 2012, 02:39 am Last Edit: Apr 30, 2012, 02:42 am by KC8OZA Reason: 1
I am so totally banging my head against the wall on this.   I've learned quite a bit (I think) from the comments thus far, I think I get the jist of what is supposed to be happening here..... but its not happening that way.

For example:
I'm structuring two bytes

Code: [Select]

byte val_hi = 0x88;  // 10001000
byte val_lo = 0xA8;  // 10101000


I send them

Code: [Select]

Wire.beginTransmission(device_address);
Wire.write(5);
Wire.write(val_hi); // hi byte
Wire.write(val_lo); // lo byte  
Wire.endTransmission();


And when I read them back

Code: [Select]

void getVolume(){
Wire.beginTransmission(device_address);
Wire.write(5);
Wire.endTransmission();
Wire.requestFrom(device_address, 2);
Wire.endTransmission();

while (Wire.available() < 2);
 
byte byte1 = Wire.read();
byte byte2 = Wire.read();

// 10001000 10101111


Serial.print("The currnet volume setting is: ");
Serial.print(byte1, BIN);
Serial.print(":");
Serial.println(byte2, BIN);


I get this

The currnet volume setting is: 1110:11100000  (Leading zeroes supressed, I assume).

So WTF.   I set a value, I read it, and I get something totally different back.  

Complete current code for reference... Some garbage still in there of course

Code: [Select]


#include <Wire.h>

int device_address = 96;
int seekPin = 12;
int seekPinState = 0;

void setup(){
pinMode (seekPin,INPUT); 
 
Wire.begin();
Serial.begin(9600);

getVolume();
maxVolume();
getVolume();


}


void loop(){

Serial.print("Device addres is: ");
Serial.println(device_address);

seekPinState = digitalRead(seekPin);

if (seekPinState == 1) {
  Serial.println("High!");

  }

getVolume();
delay(5000);

}


void maxVolume(){
Serial.println("Setting Volume");
Wire.beginTransmission(device_address);
Wire.write(5);
byte val_hi = 0x88;  // 10001000
byte val_lo = 0xA8;  // 10101000
Wire.write(val_hi); // hi byte
Wire.write(val_lo); // lo byte 
Wire.endTransmission();

}

void getVolume(){
Wire.beginTransmission(device_address);
Wire.write(5);
Wire.endTransmission();
Wire.requestFrom(device_address, 2);
Wire.endTransmission();

while (Wire.available() < 2);
 
byte byte1 = Wire.read();
byte byte2 = Wire.read();

// 10001000 10101111


Serial.print("The currnet volume setting is: ");
Serial.print(byte1, BIN);
Serial.print(":");
Serial.println(byte2, BIN);
}



Nick Gammon

Quote
So WTF.   I set a value, I read it, and I get something totally different back.  


What do you get back?




Did you run the port scanner?




Code: [Select]
Wire.beginTransmission(device_address);
Wire.write(5);
Wire.endTransmission();
Wire.requestFrom(device_address, 2);
Wire.endTransmission();

while (Wire.available() < 2);


That Wire.available() line is still there. <sigh>




Wire.endTransmission() returns zero on a good send. If you don't get that, you may as well stop right there.

Code: [Select]
Wire.beginTransmission(device_address);
Wire.write(5);
if (Wire.endTransmission() != 0)
 {
 // error message
 return;
 }





Wire.requestFrom returns the number of bytes it got. If you don't get 2 you may as well stop. As I said before.

Code: [Select]
if (Wire.requestFrom(device_address, 2) != 2)
 {
 // error message
 return;
 }





Tell you what. You implement my earlier suggestions, like the scanner, testing for the number of bytes returned, etc. Then we can talk.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

KC8OZA

Running the scanner produces the following ( I used a similar script when I was getting started, thats how I was able to get the device address to begin with...... I have no idea why 3 devices are showing up, this is a single device).

Code: [Select]

I2C scanner. Scanning ...
Found address: 16 (0x10)
Found address: 17 (0x11)
Found address: 96 (0x60)
Done.
Found 3 device(s).


As far as the while loop goes - I haven't noticed anything 'breaking' regardless of how that was set, so I haven't really focused there yet. 

As far as the values go.... I try and set this

byte val_hi = 0x88;  // 10001000
byte val_lo = 0xA8;  // 10101000

but I get this back

The currnet volume setting is: 1110:11100000  (Leading zeroes supressed, I assume).

So sent vs rcvd

TX - 1000100010101000
RX - 0000111011100000




Somehow I missed your error handling comments from before - I'm going to try those now, they look useful.


KC8OZA

I also added in the error handling stuff - I'm not getting errors either way, so I believe that we're getting a return of 0 indicating success, and I also believe we're getting 2 bytes back, as we should.

Something you said earlier has me a bit confused

Code: [Select]


After staring at it for a while I think they are saying that the device address is in fact the register. So, for example, say we want to set some bits in register 2:



Yes there are multiple registers.  of Primary interest to me is Register 2, 3,4,5,10, and 11.   But I believe it's using a standard i2c style address (we see 3 devices in a bus scan).

Nick Gammon

OK, well see this:

http://forums.parallax.com/showthread.php?131976-FM-Receiver-Module-documentation

Try address 0x10 and failing that 0x11.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

KC8OZA

When I try 16 (0x10) I get  00000001 00111111.    I get the same result after a 'set'
When I try 17 (0x11) I get  11111111 11111111.    I get the same result after a 'set'.

This is what clued me in initially that I should use the third address.

So I've clearly picked an oddball piece of hardware, ehh? :) lol

What I wish I could do is really 'see' the bitstream as I run the routine.  See what crosses the bus, and see what comes back.  I guess I just don't trust it until I prove it. But that's just me ranting about not believing what I'm seeing :)


Nick Gammon

The return of all ones suggests no response to me. Are you testing the return codes?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

I would be tempted to do a "read" of all possible 256 registers. After all that shouldn't hurt them, and you would find which ones seem to have reasonable data in them.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

KC8OZA

Yep I added some serial debug to tell me if things fail...Take a look, maybe my error handling has an error :)

Current state of code:

Code: [Select]

#include <Wire.h>

int device_address = 17;
int seekPin = 12;
int seekPinState = 0;

void setup(){
pinMode (seekPin,INPUT); 
 
Wire.begin();
Serial.begin(9600);

getVolume();
maxVolume();
getVolume();


}


void loop(){

Serial.print("Device addres is: ");
Serial.println(device_address);

seekPinState = digitalRead(seekPin);

if (seekPinState == 1) {
  Serial.println("High!");

  }

getVolume();
delay(5000);

}


void maxVolume(){
Serial.println("Setting Volume");
Wire.beginTransmission(device_address);
Wire.write(5);
byte val_hi = 0x88;  // 10001000
byte val_lo = 0xA8;  // 10101000
Wire.write(val_hi); // hi byte
Wire.write(val_lo); // lo byte 
Wire.endTransmission();
if (Wire.endTransmission() != 0)
  {
  Serial.println("Error on TX"); // error message
  return;
  }
}

void getVolume(){
Wire.beginTransmission(device_address);
Wire.write(5);
Wire.endTransmission();
Wire.requestFrom(device_address, 2);
Wire.endTransmission();
if (Wire.requestFrom(device_address, 2) != 2)
  {
  Serial.println("Error in RX"); //error message
  return;
  }
 
byte byte1 = Wire.read();
byte byte2 = Wire.read();

Serial.print("The currnet volume setting is: ");
Serial.print(byte1, BIN);
Serial.print(":");
Serial.println(byte2, BIN);
}

Nick Gammon

Code: [Select]
Wire.endTransmission();
if (Wire.endTransmission() != 0)


?

No, just the one endTransmission. Get rid of the first one.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Go Up