RDA5807M FM Radio library with RDS.
Dependents: RDA5807M-FM-Radio EFM32 RDA5807M RDS Radio
Example program here:
https://developer.mbed.org/users/star297/code/RDA5807M-FM-Radio/
Diff: RDA5807M.cpp
- Revision:
- 1:2c8a64e71afd
- Parent:
- 0:527aa96336ac
- Child:
- 3:bdd691977de4
--- a/RDA5807M.cpp Tue Mar 31 22:26:32 2015 +0000 +++ b/RDA5807M.cpp Sat Apr 11 22:53:22 2015 +0000 @@ -1,13 +1,11 @@ #include "RDA5807M.h" -int volume; - unsigned int RDA5807M_WriteRegDef[6] ={0xC004,0x0000,0x0100,0x84D4,0x4000,0x0000}; // initial data - -RDA5807M::RDA5807M(PinName sda, PinName scl, int addr) : i2c(sda, scl), addr(addr) +RDA5807M::RDA5807M(PinName sda, PinName scl) : i2c(sda, scl) { + i2c.frequency(400000); Init(); } @@ -21,13 +19,11 @@ int i,x = 0; for(i=0; i<12; i=i+2){ buf[i] = RDA5807M_WriteReg[x] >> 8; - x++; - } + x++;} x = 0; for(i=1; i<13; i=i+2){ buf[i] = RDA5807M_WriteReg[x] & 0xFF; - x++; - } + x++;} i2c.write(0x20, buf, 14); } @@ -35,24 +31,29 @@ int i; for(i=0; i<6; i++){ RDA5807M_WriteReg[i] = RDA5807M_WriteRegDef[i]; + WriteAll(); } } void RDA5807M::PowerOn(){ - RDA5807M_WriteReg[1] = RDA5807M_WriteReg[1] | 0x0010; + RDA5807M_WriteReg[1] = RDA5807M_WriteReg[1] | RDA_TUNE_ON; RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] | RDA_POWER; - WriteAll(); + WriteAll(); power=1; RDA5807M_WriteReg[1] = RDA5807M_WriteReg[1] & 0xFFEF; //Disable tune after PowerOn operation } void RDA5807M::PowerOff(){ RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] ^ RDA_POWER; - WriteAll(); + WriteAll();power=0; } void RDA5807M::Reset(){ Init(); PowerOn(); + RDSinit(); + RDS(); + Volume(InitialVolume); + Frequency(DefaultFreq); // set default start frequency. } void RDA5807M::Volume(int vol){ @@ -63,15 +64,18 @@ vol = 0; } RDA5807M_WriteReg[3] = (RDA5807M_WriteReg[3] & 0xFFF0)| vol; // Set New Volume + volume=vol; WriteAll(); } void RDA5807M::BassBoost(){ if ((RDA5807M_WriteReg[0] & 0x1000)==0){ RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] | RDA_BASS_ON; + bass=1; } else{ RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] & RDA_BASS_OFF; + bass=0; } WriteAll(); } @@ -79,9 +83,11 @@ void RDA5807M::Mono(){ if ((RDA5807M_WriteReg[0] & 0x2000)==0){ RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] | RDA_MONO_ON; + mono=1; } else{ RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] & RDA_MONO_OFF; + mono=0; } WriteAll(); } @@ -89,9 +95,11 @@ void RDA5807M::Mute(){ if ((RDA5807M_WriteReg[0] & 0x8000)==0){ RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] | 0x8000; + mute=0; } else{ RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] & 0x7FFF; + mute=1; } WriteAll(); } @@ -99,9 +107,11 @@ void RDA5807M::Softmute(){ if ((RDA5807M_WriteReg[2] & 0x0200)==0){ RDA5807M_WriteReg[2] = RDA5807M_WriteReg[2] | 0x0200; + softmute=1; } else{ RDA5807M_WriteReg[2] = RDA5807M_WriteReg[2] & 0xFDFF; + softmute=0; } WriteAll(); } @@ -109,9 +119,23 @@ void RDA5807M::SoftBlend(){ if ((RDA5807M_WriteReg[6] & 0x0001)==0){ RDA5807M_WriteReg[6] = RDA5807M_WriteReg[6] | 0x0001; + softblend=1; } else{ RDA5807M_WriteReg[6] = RDA5807M_WriteReg[6] & 0xFFFE; + softblend=0; + } + WriteAll(); +} + +void RDA5807M::AFC(){ + if ((RDA5807M_WriteReg[2] & 0x0100)==0){ + RDA5807M_WriteReg[2] = RDA5807M_WriteReg[2] | 0x0100; + afc=1; + } + else{ + RDA5807M_WriteReg[2] = RDA5807M_WriteReg[2] & 0xFEFE; + afc=0; } WriteAll(); } @@ -130,9 +154,9 @@ void RDA5807M::Frequency(float Freq){ int Channel; - Channel = (Freq-StartingFreq)/0.1; + Channel = ((Freq-StartingFreq)/0.1)+0.05; Channel = Channel & 0x03FF; - RDA5807M_WriteReg[1] = Channel*64 +0x10; // Channel + TUNE-Bit + Band=00(87-108) + Space=00(100kHz) + RDA5807M_WriteReg[1] = Channel*64 + 0x10; // Channel + TUNE-Bit + Band=00(87-108) + Space=00(100kHz) WriteAll(); RDA5807M_WriteReg[1] = RDA5807M_WriteReg[1] & RDA_TUNE_OFF; } @@ -140,9 +164,11 @@ void RDA5807M::RDS(){ if ((RDA5807M_WriteReg[0] & RDA_RDS_ON)==0){ RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] | RDA_RDS_ON; + rds=1; } else{ RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] & RDA_RDS_OFF; + rds=0; } WriteAll(); } @@ -154,6 +180,10 @@ for(i=0; i<6; i++){ RDA5807M_ReadReg[i] = ((rcv[i *2] << 8) | rcv [(i*2) +1] ); } + block1 = RDA5807M_ReadReg[2]; + block2 = RDA5807M_ReadReg[3]; + block3 = RDA5807M_ReadReg[4]; + block4 = RDA5807M_ReadReg[5]; rdsready = RDA5807M_ReadReg[0] & 0x8000; //if rdsready != 0 rds data are ready tuneok = RDA5807M_ReadReg[0] & 0x4000; //if tuneok != 0 seek/tune completed @@ -171,3 +201,140 @@ } +void RDA5807M::RDSinit() { + strcpy(PSName1, " "); + strcpy(PSName2, PSName1); + strcpy(StationName, " "); + memset(RDSText, '\0', sizeof(RDSText)); + lastTextIDX = 0; +} + +void RDA5807M::processData() +{ + char c1, c2; + int idx; // index of rdsText + int mins; // RDS time in minutes + int offset; // RDS time offset and sign + Read(); + if (block1==0) { + // reset all the RDS info. + RDSinit(); + // Send out empty data + if (sendServiceName) sendServiceName(StationName); + if (sendText) sendText(""); + return; + } + + // analyzing Block 2 + rdsGroupType = 0x0A | ((block2 & 0xF000) >> 8) | ((block2 & 0x0800) >> 11); + rdsTP = (block2 & 0x0400); + rdsPTY = (block2 & 0x0400); + + switch (rdsGroupType) { + case 0x0A: + case 0x0B: + // The data received is part of the Service Station Name + + idx = 2 * (block2 & 0x0003); + // new data is 2 chars from block 4 + c1 = block4 >> 8; + c2 = block4 & 0x00FF; + // check that the data was received successfully twice + // before publishing the station name + if ((PSName1[idx] == c1) && (PSName1[idx + 1] == c2)) { + // retrieved the text a second time: store to _PSName2 + PSName2[idx] = c1; + PSName2[idx + 1] = c2; + PSName2[8] = '\0'; + if ((idx == 6) && strcmp(PSName1, PSName2) == 0) { + if (strcmp(PSName2, StationName) != 0) { + // publish station name + if(strlen(PSName2)<9){strcpy(StationName, PSName2);} + if (sendServiceName) + sendServiceName(StationName); + } + } + } + if ((PSName1[idx] != c1) || (PSName1[idx + 1] != c2)) { + PSName1[idx] = c1; + PSName1[idx + 1] = c2; + PSName1[8] = '\0'; + } + break; + + case 0x2A: + // RDS text + // if(rdsblockerror > 1){memset(RDSText, '\0', sizeof(RDSText));lastTextIDX = 0;} + // The data received is part of the RDS Text. + textAB = (block2 & 0x0010); + idx = 4 * (block2 & 0x000F); + + if (idx < lastTextIDX) { + // the existing text might be complete because the index is starting at the beginning again. + // now send it to the possible listener. + if (sendText) + sendText(RDSText); + } + lastTextIDX = idx; + + if (textAB != lasttextAB) { + // when this bit is toggled the whole buffer should be cleared. + lasttextAB = textAB; + } + // new data is 2 chars from block 3 + RDSText[idx] = (block3 >> 8); idx++; + RDSText[idx] = (block3 & 0x00FF); idx++; + + // new data is 2 chars from block 4 + RDSText[idx] = (block4 >> 8); idx++; + RDSText[idx] = (block4 & 0x00FF); idx++; + + break; + + case 0x4A: + // Clock time and date + offset = (block4) & 0x3F; // 6 bits + mins = (block4 >> 6) & 0x3F; // 6 bits + mins += 60 * (((block3 & 0x0001) << 4) | ((block4 >> 12) & 0x0F)); + + // adjust offset + if (offset & 0x20) { + mins -= 30 * (offset & 0x1F); + } + else { + mins += 30 * (offset & 0x1F); + } + +// Serial.print(" >>"); Serial.print(mins/60); Serial.print(':'); Serial.println(mins % 60); + + //if ((sendTime) && (mins != _lastRDSMinutes)) { + CTtime = mins; + // sendTime(mins / 60, mins % 60); + // } + break; + + case 0x6A: + // IH + break; + + case 0x8A: + // TMC + break; + + case 0xAA: + // TMC + break; + + case 0xCA: + // TMC + break; + + case 0xEA: + // IH + break; + + default: + // Serial.print("RDS_GRP:"); Serial.println(rdsGroupType, HEX); + break; + } +}