Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
SparkFun-Si4703.cpp
00001 #include "mbed.h" 00002 #include "SparkFun-Si4703.h" 00003 00004 Si4703_Breakout::Si4703_Breakout(PinName sdioPin, PinName sclkPin, PinName resetPin, Serial *pc) 00005 { 00006 _resetPin = resetPin; 00007 _sdioPin = sdioPin; 00008 _sclkPin = sclkPin; 00009 00010 this->pc = pc; 00011 } 00012 00013 void Si4703_Breakout::powerOn() 00014 { 00015 si4703_init(); 00016 } 00017 00018 void Si4703_Breakout::powerOff() 00019 { 00020 // a Minimal Power-Down Sequence - According To SI AN230 (rev. 0.9), p.13 - Table 4 00021 00022 readRegisters(); 00023 si4703_registers[POWERCFG] &= ~(1<<DMUTE); // 'Enable Mute' 00024 updateRegisters(); 00025 00026 readRegisters(); 00027 si4703_registers[POWERCFG] |= (1<<ENABLE); // 'Enable IC' 00028 updateRegisters(); 00029 00030 readRegisters(); 00031 si4703_registers[POWERCFG] |= (1<<DISABLE); // & 'Disable IC' 00032 updateRegisters(); 00033 00034 // Notice : This Does NOT Perform a Reset of The IC. 00035 } 00036 00037 void Si4703_Breakout::setChannel(int channel) 00038 { 00039 uint8_t ack; 00040 //Freq(MHz) = 0.1 (in Europe) * Channel + 87.5MHz 00041 //97.3 = 0.1 * Chan + 87.5 00042 //9.8 / 0.1 = 98 00043 int newChannel = channel * 10; //973 * 10 = 9730 00044 newChannel -= 8750; //9730 - 8750 = 980 00045 newChannel /= 10; //980 / 10 = 98 00046 00047 //These steps come from AN230 page 20 rev 0.5 00048 readRegisters(); 00049 si4703_registers[CHANNEL] &= 0xFE00; //Clear out the channel bits 00050 si4703_registers[CHANNEL] |= newChannel; //Mask in the new channel 00051 si4703_registers[CHANNEL] |= (1<<TUNE); //Set the TUNE bit to start 00052 updateRegisters(); 00053 00054 wait_ms(60); //Wait 60ms - you can use or skip this delay 00055 00056 //Poll to see if STC is set 00057 while(1) { 00058 ack = readRegisters(); 00059 wait_ms(1); // Just In Case... 00060 if (( (si4703_registers[STATUSRSSI] & (1<<STC)) != 0) || (ack != SUCCESS)) break; //Tuning complete! (or FAILED) 00061 } 00062 00063 readRegisters(); 00064 si4703_registers[CHANNEL] &= ~(1<<TUNE); //Clear the tune after a tune has completed 00065 updateRegisters(); 00066 00067 //Wait for the si4703 to clear the STC as well 00068 while(1) { 00069 ack = readRegisters(); 00070 wait_ms(1); // Just In Case... 00071 if (( (si4703_registers[STATUSRSSI] & (1<<STC)) == 0) || (ack != SUCCESS)) break; //Tuning complete! (or FAILED) 00072 } 00073 } 00074 00075 int Si4703_Breakout::seekUp() 00076 { 00077 return seek(SEEK_UP); 00078 } 00079 00080 int Si4703_Breakout::seekDown() 00081 { 00082 return seek(SEEK_DOWN); 00083 } 00084 00085 void Si4703_Breakout::setVolume(int volume) 00086 { 00087 readRegisters(); //Read the current register set 00088 if(volume < 0) volume = 0; 00089 if (volume > 15) volume = 15; 00090 si4703_registers[SYSCONFIG2] &= 0xFFF0; //Clear volume bits 00091 si4703_registers[SYSCONFIG2] |= volume; //Set new volume 00092 updateRegisters(); //Update 00093 } 00094 00095 uint8_t Si4703_Breakout::getVolume() 00096 { 00097 readRegisters(); //Read the current register set 00098 00099 return (si4703_registers[SYSCONFIG2] & 0x000F); 00100 } 00101 00102 /* 00103 void Si4703_Breakout::readRDS(char* buffer, long timeout) 00104 { 00105 long endTime = millis() + timeout; 00106 boolean completed[] = {false, false, false, false}; 00107 int completedCount = 0; 00108 while(completedCount < 4 && millis() < endTime) { 00109 readRegisters(); 00110 if(si4703_registers[STATUSRSSI] & (1<<RDSR)){ 00111 // ls 2 bits of B determine the 4 letter pairs 00112 // once we have a full set return 00113 // if you get nothing after 20 readings return with empty string 00114 uint16_t b = si4703_registers[RDSB]; 00115 int index = b & 0x03; 00116 if (! completed[index] && b < 500) 00117 { 00118 completed[index] = true; 00119 completedCount ++; 00120 char Dh = (si4703_registers[RDSD] & 0xFF00) >> 8; 00121 char Dl = (si4703_registers[RDSD] & 0x00FF); 00122 buffer[index * 2] = Dh; 00123 buffer[index * 2 +1] = Dl; 00124 // Serial.print(si4703_registers[RDSD]); Serial.print(" "); 00125 // Serial.print(index);Serial.print(" "); 00126 // Serial.write(Dh); 00127 // Serial.write(Dl); 00128 // Serial.println(); 00129 } 00130 delay(40); //Wait for the RDS bit to clear 00131 } 00132 else { 00133 delay(30); //From AN230, using the polling method 40ms should be sufficient amount of time between checks 00134 } 00135 } 00136 if (millis() >= endTime) { 00137 buffer[0] ='\0'; 00138 return; 00139 } 00140 00141 buffer[8] = '\0'; 00142 } 00143 */ 00144 00145 00146 00147 //To get the Si4703 inito 2-wire mode, SEN needs to be high and SDIO needs to be low after a reset 00148 //The breakout board has SEN pulled high, but also has SDIO pulled high. Therefore, after a normal power up 00149 //The Si4703 will be in an unknown state. RST must be controlled 00150 void Si4703_Breakout::si4703_init() 00151 { 00152 _reset_ = new DigitalOut(_resetPin); 00153 _sdio_ = new DigitalOut(_sdioPin); 00154 00155 _sdio_->write(0); //A low SDIO indicates a 2-wire interface 00156 _reset_->write(0); //Put Si4703 into reset 00157 wait_ms(1); //Some delays while we allow pins to settle 00158 _reset_->write(1); //Bring Si4703 out of reset with SDIO set to low and SEN pulled high with on-board resistor 00159 wait_ms(1); //Allow Si4703 to come out of reset 00160 00161 //Now that the unit is reset and I2C inteface mode, we need to begin I2C 00162 i2c_ = new I2C(_sdioPin, _sclkPin); 00163 i2c_->frequency(100000); 00164 /// 00165 00166 readRegisters(); //Read the current register set 00167 si4703_registers[0x07] = 0x8100; //Enable the oscillator, from AN230 page 9, rev 0.61 (works) 00168 updateRegisters(); //Update 00169 00170 wait_ms(500); //Wait for clock to settle - from AN230 page 9 00171 00172 readRegisters(); //Read the current register set 00173 si4703_registers[POWERCFG] = 0x4001; //Enable the IC 00174 // si4703_registers[POWERCFG] |= (1<<SMUTE) | (1<<DMUTE); //Disable Mute, disable softmute 00175 si4703_registers[SYSCONFIG1] |= (1<<RDS); //Enable RDS 00176 00177 si4703_registers[SYSCONFIG1] |= (1<<DE); //50μS Europe setup 00178 si4703_registers[SYSCONFIG2] |= (1<<SPACE0); //100kHz channel spacing for Europe 00179 00180 si4703_registers[SYSCONFIG2] &= 0xFFF0; //Clear volume bits 00181 si4703_registers[SYSCONFIG2] |= 0x0001; //Set volume to lowest 00182 00183 // SI AN230 page 40 - Table 23 ('Good Quality Stations Only' Settings) 00184 si4703_registers[SYSCONFIG2] |= (0xC<<SEEKTH); 00185 si4703_registers[SYSCONFIG3] |= (0x7<<SKSNR); 00186 si4703_registers[SYSCONFIG3] |= (0xF<<SKCNT); 00187 /// 00188 updateRegisters(); //Update 00189 00190 wait_ms(110); //Max powerup time, from datasheet page 13 00191 00192 } 00193 00194 //Read the entire register control set from 0x00 to 0x0F 00195 uint8_t Si4703_Breakout::readRegisters(){ 00196 00197 //Si4703 begins reading from register upper register of 0x0A and reads to 0x0F, then loops to 0x00. 00198 // Wire.requestFrom(SI4703, 32); //We want to read the entire register set from 0x0A to 0x09 = 32 uint8_ts. 00199 char data[32]; 00200 uint8_t ack = i2c_->read(SI4703, data, 32); //Read in these 32 uint8_ts 00201 00202 if (ack != 0) { //We have a problem! 00203 return(FAIL); 00204 } 00205 00206 //Remember, register 0x0A comes in first so we have to shuffle the array around a bit 00207 for (int y=0; y<6; y++) 00208 { 00209 si4703_registers[0x0A+y] = 0; 00210 si4703_registers[0x0A+y] = data[(y*2)+1]; 00211 si4703_registers[0x0A+y] |= (data[(y*2)] << 8); 00212 } 00213 00214 for (int y=0; y<10; y++) 00215 { 00216 si4703_registers[y] = 0; 00217 si4703_registers[y] = data[(12)+(y*2)+1]; 00218 si4703_registers[y] |= (data[(12)+(y*2)] << 8); 00219 } 00220 //We're done! 00221 /// 00222 return(SUCCESS); 00223 } 00224 00225 //Write the current 9 control registers (0x02 to 0x07) to the Si4703 00226 //It's a little weird, you don't write an I2C address 00227 //The Si4703 assumes you are writing to 0x02 first, then increments 00228 uint8_t Si4703_Breakout::updateRegisters() { 00229 00230 char data[12]; 00231 00232 //First we send the 0x02 to 0x07 control registers 00233 //In general, we should not write to registers 0x08 and 0x09 00234 for(int regSpot = 0x02 ; regSpot < 0x08 ; regSpot++) { 00235 data[(regSpot-2)*2] = si4703_registers[regSpot] >> 8; 00236 data[((regSpot-2)*2)+1] = si4703_registers[regSpot] & 0x00FF; 00237 } 00238 00239 uint8_t ack = i2c_->write(SI4703, data, 12); // a write command automatically begins with register 0x02 so no need to send a write-to address 00240 00241 if(ack != 0) { //We have a problem! 00242 return(FAIL); 00243 } 00244 00245 return(SUCCESS); 00246 } 00247 00248 //Returns The Value of a Register 00249 uint16_t Si4703_Breakout::getRegister(uint8_t regNum) 00250 { 00251 readRegisters(); 00252 return si4703_registers[regNum]; 00253 // No Error Status Checking 00254 } 00255 00256 //Seeks out the next available station 00257 //Returns the freq if it made it 00258 //Returns zero if failed 00259 int Si4703_Breakout::seek(bool seekDirection){ 00260 uint8_t ack; 00261 readRegisters(); 00262 //Set seek mode wrap bit 00263 si4703_registers[POWERCFG] |= (1<<SKMODE); //Disallow wrap - if you disallow wrap, you may want to tune to 87.5 first 00264 //si4703_registers[POWERCFG] &= ~(1<<SKMODE); //Allow wrap 00265 if(seekDirection == SEEK_DOWN) si4703_registers[POWERCFG] &= ~(1<<SEEKUP); //Seek down is the default upon reset 00266 else si4703_registers[POWERCFG] |= 1<<SEEKUP; //Set the bit to seek up 00267 00268 si4703_registers[POWERCFG] |= (1<<SEEK); //Start seek 00269 updateRegisters(); //Seeking will now start 00270 00271 //Poll to see if STC is set 00272 while(1) { 00273 ack = readRegisters(); 00274 wait_ms(1); // Just In Case... 00275 if (((si4703_registers[STATUSRSSI] & (1<<STC)) != 0) || (ack != SUCCESS)) break; //Tuning complete! (or FAILED) 00276 } 00277 00278 readRegisters(); 00279 int valueSFBL = si4703_registers[STATUSRSSI] & (1<<SFBL); //Store the value of SFBL 00280 si4703_registers[POWERCFG] &= ~(1<<SEEK); //Clear the seek bit after seek has completed 00281 updateRegisters(); 00282 00283 //Wait for the si4703 to clear the STC as well 00284 while(1) { 00285 ack = readRegisters(); 00286 wait_ms(1); // Just In Case... 00287 if (((si4703_registers[STATUSRSSI] & (1<<STC)) == 0) || (ack != SUCCESS)) break; //Tuning complete! (or FAILED) 00288 } 00289 00290 if(valueSFBL) { //The bit was set indicating we hit a band limit or failed to find a station 00291 return(0); 00292 } 00293 return getChannel(); 00294 } 00295 00296 //Reads the current channel from READCHAN 00297 //Returns a number like 973 for 97.3MHz 00298 int Si4703_Breakout::getChannel() { 00299 readRegisters(); 00300 int channel = (si4703_registers[READCHAN] & 0x03FF); //Mask out everything but the lower 10 bits 00301 //Freq(MHz) = 0.100(in Europe) * Channel + 87.5MHz 00302 //X = 0.1 * Chan + 87.5 00303 channel += 875; //98 + 875 = 973 ( for 97.3 MHz ) 00304 return(channel); 00305 } 00306 00307 void Si4703_Breakout::printRegs() { 00308 readRegisters(); 00309 for (int x=0; x<16; x++) { pc->printf("Reg# 0x%X = 0x%X\r\n",x,si4703_registers[x]); wait_ms(1); } 00310 }
Generated on Mon Jul 18 2022 14:28:39 by
1.7.2