Paul Staron / RDA5807M

Dependents:   RDA5807M-FM-Radio EFM32 RDA5807M RDS Radio

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RDA5807M.cpp Source File

RDA5807M.cpp

00001 #include "RDA5807M.h"
00002 
00003 
00004 unsigned int RDA5807M_WriteRegDef[6] ={0xC004,0x0000,0x0100,0x84D4,0x4000,0x0000}; // initial data
00005 
00006 RDA5807M::RDA5807M(PinName sda, PinName scl) : i2c(sda, scl)
00007 {   
00008     i2c.frequency(400000);
00009     Init();
00010 }
00011 
00012 RDA5807M::~RDA5807M()
00013 {
00014 }
00015 
00016 void RDA5807M::WriteAll()
00017 { 
00018     char buf[30];  
00019     int i,x = 0;
00020     for(i=0; i<12; i=i+2){
00021         buf[i] = RDA5807M_WriteReg[x] >> 8;
00022         x++;}
00023     x = 0;
00024     for(i=1; i<13; i=i+2){
00025         buf[i] = RDA5807M_WriteReg[x] & 0xFF;
00026         x++;}
00027     i2c.write(0x20, buf, 14);
00028 }
00029 
00030 void RDA5807M::Init(){
00031     int i;
00032     for(i=0; i<6; i++){
00033         RDA5807M_WriteReg[i] = RDA5807M_WriteRegDef[i];
00034         WriteAll();
00035     }
00036 }
00037 
00038 void RDA5807M::PowerOn(){
00039     RDA5807M_WriteReg[1] = RDA5807M_WriteReg[1] | RDA_TUNE_ON;
00040     RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] | RDA_POWER;
00041     WriteAll(); power=1;
00042     RDA5807M_WriteReg[1] = RDA5807M_WriteReg[1] & 0xFFEF;   //Disable tune after PowerOn operation
00043 }
00044 
00045 void RDA5807M::PowerOff(){
00046     RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] ^ RDA_POWER;
00047     WriteAll();power=0;
00048 }
00049 
00050 void RDA5807M::Reset(){
00051     Init();
00052     PowerOn();
00053     RDSinit();
00054     RDS();
00055     Volume(InitialVolume);
00056     Frequency(DefaultFreq);  // set default start frequency.
00057 }
00058 
00059 void RDA5807M::Volume(int vol){
00060     if(vol > 15){
00061         vol = 15;
00062     }
00063     if(vol < 0){
00064         vol = 0;
00065     }
00066     RDA5807M_WriteReg[3] = (RDA5807M_WriteReg[3] & 0xFFF0)| vol;   // Set New Volume
00067     volume=vol;
00068     WriteAll();
00069 }
00070 
00071 void RDA5807M::BassBoost(){
00072     if ((RDA5807M_WriteReg[0] & 0x1000)==0){
00073         RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] | RDA_BASS_ON;
00074         bass=1;
00075     }
00076     else{
00077         RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] & RDA_BASS_OFF;
00078         bass=0;
00079     }
00080     WriteAll();
00081 }
00082 
00083 void RDA5807M::Mono(){
00084     if ((RDA5807M_WriteReg[0] & 0x2000)==0){
00085         RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] | RDA_MONO_ON;
00086         mono=1;
00087     }
00088     else{
00089         RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] & RDA_MONO_OFF;
00090         mono=0;
00091     }
00092     WriteAll();
00093 }
00094 
00095 void RDA5807M::Mute(){
00096     if ((RDA5807M_WriteReg[0] & 0x8000)==0){
00097         RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] | 0x8000;
00098         mute=0;
00099     }
00100     else{
00101         RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] & 0x7FFF;
00102         mute=1;
00103     }
00104     WriteAll();
00105 }
00106 
00107 void RDA5807M::Softmute(){
00108     if ((RDA5807M_WriteReg[2] & 0x0200)==0){
00109         RDA5807M_WriteReg[2] = RDA5807M_WriteReg[2] | 0x0200;
00110         softmute=1;
00111     }
00112     else{
00113         RDA5807M_WriteReg[2] = RDA5807M_WriteReg[2] & 0xFDFF;
00114         softmute=0;
00115     }
00116     WriteAll();
00117 }
00118 
00119 void RDA5807M::SoftBlend(){
00120     if ((RDA5807M_WriteReg[6] & 0x0001)==0){
00121         RDA5807M_WriteReg[6] = RDA5807M_WriteReg[6] | 0x0001;
00122         softblend=1;
00123     }
00124     else{
00125         RDA5807M_WriteReg[6] = RDA5807M_WriteReg[6] & 0xFFFE;
00126         softblend=0;
00127     }
00128     WriteAll();
00129 }
00130 
00131 void RDA5807M::AFC(){
00132     if ((RDA5807M_WriteReg[2] & 0x0100)==0){
00133         RDA5807M_WriteReg[2] = RDA5807M_WriteReg[2] | 0x0100;
00134         afc=1;
00135     }
00136     else{
00137         RDA5807M_WriteReg[2] = RDA5807M_WriteReg[2] & 0xFEFE;
00138         afc=0;
00139     }
00140     WriteAll();
00141 }
00142 
00143 void RDA5807M::SeekUp(){
00144     RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] | RDA_SEEK_UP;   // Set Seek Up
00145     WriteAll();
00146     RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] & RDA_SEEK_STOP;   // Disable Seek
00147 }
00148 
00149 void RDA5807M::SeekDown(){
00150     RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] | RDA_SEEK_DOWN;   // Set Seek Down
00151     WriteAll();
00152     RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] & RDA_SEEK_STOP;   // Disable Seek
00153 }
00154 
00155 void RDA5807M::Frequency(float Freq){
00156     int Channel;
00157     Channel = ((Freq-StartingFreq)/0.1)+0.05;
00158     Channel = Channel & 0x03FF;
00159     RDA5807M_WriteReg[1] = Channel*64 + 0x10;  // Channel + TUNE-Bit + Band=00(87-108) + Space=00(100kHz)
00160     WriteAll();
00161     RDA5807M_WriteReg[1] = RDA5807M_WriteReg[1] & RDA_TUNE_OFF;
00162 }
00163 
00164 void RDA5807M::RDS(){
00165     if ((RDA5807M_WriteReg[0] & RDA_RDS_ON)==0){
00166         RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] | RDA_RDS_ON;
00167         rds=1;
00168     }
00169     else{
00170         RDA5807M_WriteReg[0] = RDA5807M_WriteReg[0] & RDA_RDS_OFF;
00171         rds=0;
00172     }
00173     WriteAll();
00174 }
00175 
00176 void RDA5807M::Readregisters(){
00177    int i;
00178    char rcv[12];    
00179    i2c.read(0x20, rcv,12);   // read 12 bytes for reg 0x0A .. reg 0x0F 
00180         for(i=0; i<6; i++){
00181             RDA5807M_ReadReg[i] = ((rcv[i *2] << 8) | rcv [(i*2) +1] );
00182         }
00183     block1 = RDA5807M_ReadReg[2];
00184     block2 = RDA5807M_ReadReg[3];
00185     block3 = RDA5807M_ReadReg[4];
00186     block4 = RDA5807M_ReadReg[5];    
00187    
00188     rdsready = RDA5807M_ReadReg[0] & 0x8000;            //if rdsready != 0 rds data are ready
00189     tuneok = RDA5807M_ReadReg[0] & 0x4000;              //if tuneok != 0 seek/tune completed
00190     nochannel = RDA5807M_ReadReg[0] & 0x2000;           //if nochannel != 0 no channel found
00191     rdssynchro = RDA5807M_ReadReg[0] & 0x1000;          //if rdssynchro = 1000 rds decoder syncrhonized
00192     stereo = RDA5807M_ReadReg[0] & 0x0400;              //if stereo = 0 station is mono else stereo
00193     freq = (((RDA5807M_ReadReg[0] & 0x03FF) * 100) + 87000);    //return freq ex 102600KHz > 102.6MHz
00194     signal = RDA5807M_ReadReg[1] >> 10;                 //return signal strength rssi
00195     fmready = RDA5807M_ReadReg[1] & 0x0008;             //if fmready = 8 > fm is ready
00196     fmstation = RDA5807M_ReadReg[1] & 0x0100;           //if fmstation = 100 fm station is true
00197     rdsblockerror = RDA5807M_ReadReg[1] & 0x000C;       //check for rds blocks errors
00198                                                         //00= 0 errors,01= 1~2 errors requiring correction
00199                                                         //10= 3~5 errors requiring correction
00200                                                         //11= 6+ errors or error in checkword, correction not possible.
00201 }
00202 
00203 void RDA5807M::RDSinit() {
00204   strcpy(StationName, "        ");
00205   strcpy(PSName, "        ");
00206   strcpy(PSName1, "        ");
00207   strcpy(PSName2, "        ");
00208   memset(RDSText, '\0', sizeof(RDSText));
00209   memset(RDSTxt, '\0', sizeof(RDSTxt));
00210   lastTextIDX = 0;
00211   mins=0;
00212   sprintf(CTtime, "CT --:--");
00213 } 
00214 
00215 void RDA5807M::ProcessData()
00216 {
00217     Readregisters();        
00218     if (rdssynchro != 0x1000){  // reset all the RDS info.
00219         RDSinit();
00220         return;
00221     }   
00222   // analyzing Block 2
00223     rdsGroupType = 0x0A | ((block2 & 0xF000) >> 8) | ((block2 & 0x0800) >> 11);
00224     rdsTP = (block2 & 0x0400);
00225     rdsPTY = (block2 & 0x0400);
00226 
00227     switch (rdsGroupType) {
00228         case 0x0A:
00229         case 0x0B:
00230         // The data received is part of the Service Station Name  
00231             idx = 2 * (block2 & 0x0003);
00232             // new data is 2 chars from block 4
00233             c1 = block4 >> 8;
00234             c2 = block4 & 0x00FF;
00235         // check that the data was received successfully twice
00236         // before sending the station name
00237         if ((PSName1[idx] == c1) && (PSName1[idx + 1] == c2)) {
00238             // retrieve the text a second time: store to _PSName2
00239             PSName2[idx] = c1;
00240             PSName2[idx + 1] = c2;
00241             PSName2[8] = '\0';
00242             if (strcmp(PSName1, PSName2) == 0) {
00243                 // populate station name          
00244                 n=0;
00245                 for(i=0;i<(8);i++){ // remove non-printable error ASCCi characters               
00246                     if(PSName2[i] > 31 && PSName2[i] < 127){          
00247                         StationName[n] = PSName2[i];         
00248                         n++;
00249                     }                  
00250                 } 
00251             }
00252         }
00253         if ((PSName1[idx] != c1) || (PSName1[idx + 1] != c2)) {
00254             PSName1[idx] = c1;
00255             PSName1[idx + 1] = c2;
00256             PSName1[8] = '\0';
00257         } 
00258     break;
00259     
00260     case 0x2A:
00261         // RDS text
00262     textAB = (block2 & 0x0010);
00263     idx = 4 * (block2 & 0x000F);  
00264     if (idx < lastTextIDX) {
00265       // The existing text might be complete because the index is starting at the beginning again.
00266       // Populate RDS text array.
00267         n=0;       
00268         for(i=0;i<strlen(RDSTxt);i++){
00269             if(RDSTxt[i] > 31 && RDSTxt[i] < 127){    // remove any non printable error charcters      
00270                 RDSText[n] = RDSTxt[i];         
00271                 n++;
00272             }
00273         }
00274       }
00275     lastTextIDX = idx;
00276     if (textAB != lasttextAB) {
00277       // when this bit is toggled the whole buffer should be cleared.
00278       lasttextAB = textAB;
00279       memset(RDSTxt, 0, sizeof(RDSTxt));
00280       memset(RDSText, '\0', sizeof(RDSText));
00281     }    
00282     if(rdsblockerror < 4){     
00283         // new data is 2 chars from block 3
00284         RDSTxt[idx] = (block3 >> 8);     idx++;
00285         RDSTxt[idx] = (block3 & 0x00FF); idx++;
00286         // new data is 2 chars from block 4
00287         RDSTxt[idx] = (block4 >> 8); idx++;
00288         RDSTxt[idx] = (block4 & 0x00FF); idx++;
00289     }             
00290     break;
00291 
00292   case 0x4A:
00293     // Clock time and date
00294     if(rdsblockerror <3){ // allow limited RDS data errors as we have no correctioin code 
00295         offset = (block4) & 0x3F; // 6 bits
00296         mins = (block4 >> 6) & 0x3F; // 6 bits
00297         mins += 60 * (((block3 & 0x0001) << 4) | ((block4 >> 12) & 0x0F));
00298     }
00299     // adjust offset
00300     if (offset & 0x20) {
00301       mins -= 30 * (offset & 0x1F);
00302     }
00303     else {
00304       mins += 30 * (offset & 0x1F);
00305     }    
00306     if(mins == lastmins+1){ // get CT time twice before populating time
00307         minutes=mins;}
00308         lastmins=mins;    
00309     if(rdssynchro == 0x1000){
00310         if(minutes>0 && minutes<1500){sprintf(CTtime, "CT %2d:%02d",(minutes/60),(minutes%60));}
00311         }
00312         else{minutes=0;sprintf(CTtime, "CT --:--");} // CT time formatted string         
00313     break;
00314 
00315   case 0x6A: 
00316     // IH
00317     break;
00318 
00319   case 0x8A:
00320     // TMC
00321     break;
00322 
00323   case 0xAA:
00324     // TMC
00325     break;
00326 
00327   case 0xCA:
00328     // TMC
00329     break;
00330 
00331   case 0xEA:
00332     // IH
00333     break;
00334 
00335   default:
00336     
00337     break;
00338   }
00339 }
00340