A mbed Port of 'Sparkfun Si4703 Arduino Library'.
SparkFun-Si4703.cpp@1:3d2b66e5d09e, 2015-08-07 (annotated)
- Committer:
- mzcs
- Date:
- Fri Aug 07 04:30:15 2015 +0000
- Revision:
- 1:3d2b66e5d09e
- Parent:
- 0:1f830fa5c9b8
- Child:
- 2:558ef02f39d0
.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mzcs | 1:3d2b66e5d09e | 1 | #include "mbed.h" |
mzcs | 1:3d2b66e5d09e | 2 | #include "SparkFun-Si4703.h" |
mzcs | 0:1f830fa5c9b8 | 3 | |
mzcs | 0:1f830fa5c9b8 | 4 | Si4703_Breakout::Si4703_Breakout(PinName sdioPin, PinName sclkPin, PinName resetPin, Serial *pc) |
mzcs | 0:1f830fa5c9b8 | 5 | { |
mzcs | 0:1f830fa5c9b8 | 6 | _resetPin = resetPin; |
mzcs | 0:1f830fa5c9b8 | 7 | _sdioPin = sdioPin; |
mzcs | 0:1f830fa5c9b8 | 8 | _sclkPin = sclkPin; |
mzcs | 0:1f830fa5c9b8 | 9 | |
mzcs | 0:1f830fa5c9b8 | 10 | this->pc = pc; |
mzcs | 0:1f830fa5c9b8 | 11 | } |
mzcs | 0:1f830fa5c9b8 | 12 | |
mzcs | 0:1f830fa5c9b8 | 13 | void Si4703_Breakout::powerOn() |
mzcs | 0:1f830fa5c9b8 | 14 | { |
mzcs | 0:1f830fa5c9b8 | 15 | si4703_init(); |
mzcs | 0:1f830fa5c9b8 | 16 | } |
mzcs | 0:1f830fa5c9b8 | 17 | |
mzcs | 0:1f830fa5c9b8 | 18 | void Si4703_Breakout::powerOff() |
mzcs | 0:1f830fa5c9b8 | 19 | { |
mzcs | 0:1f830fa5c9b8 | 20 | // a Minimal Power-Down Sequence - According To SI AN230 (rev. 0.9), p.13 - Table 4 |
mzcs | 0:1f830fa5c9b8 | 21 | |
mzcs | 0:1f830fa5c9b8 | 22 | readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 23 | |
mzcs | 0:1f830fa5c9b8 | 24 | si4703_registers[POWERCFG] &= ~(1<<DMUTE); // 'Enable Mute' |
mzcs | 0:1f830fa5c9b8 | 25 | si4703_registers[POWERCFG] |= (1<<ENABLE); // 'Enable IC' |
mzcs | 0:1f830fa5c9b8 | 26 | si4703_registers[POWERCFG] |= (1<<DISABLE); // & 'Disable IC' |
mzcs | 0:1f830fa5c9b8 | 27 | // To Init. Power-Down Sequence |
mzcs | 0:1f830fa5c9b8 | 28 | |
mzcs | 0:1f830fa5c9b8 | 29 | updateRegisters(); |
mzcs | 0:1f830fa5c9b8 | 30 | // Notice : This Does NOT Perform a Reset of The IC. |
mzcs | 0:1f830fa5c9b8 | 31 | } |
mzcs | 0:1f830fa5c9b8 | 32 | |
mzcs | 0:1f830fa5c9b8 | 33 | void Si4703_Breakout::setChannel(int channel) |
mzcs | 0:1f830fa5c9b8 | 34 | { |
mzcs | 0:1f830fa5c9b8 | 35 | uint8_t ack; |
mzcs | 0:1f830fa5c9b8 | 36 | //Freq(MHz) = 0.1 (in Europe) * Channel + 87.5MHz |
mzcs | 0:1f830fa5c9b8 | 37 | //97.3 = 0.1 * Chan + 87.5 |
mzcs | 0:1f830fa5c9b8 | 38 | //9.8 / 0.1 = 98 |
mzcs | 0:1f830fa5c9b8 | 39 | int newChannel = channel * 10; //973 * 10 = 9730 |
mzcs | 0:1f830fa5c9b8 | 40 | newChannel -= 8750; //9730 - 8750 = 980 |
mzcs | 0:1f830fa5c9b8 | 41 | newChannel /= 10; //980 / 10 = 98 |
mzcs | 0:1f830fa5c9b8 | 42 | |
mzcs | 0:1f830fa5c9b8 | 43 | //These steps come from AN230 page 20 rev 0.5 |
mzcs | 0:1f830fa5c9b8 | 44 | readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 45 | si4703_registers[CHANNEL] &= 0xFE00; //Clear out the channel bits |
mzcs | 0:1f830fa5c9b8 | 46 | si4703_registers[CHANNEL] |= newChannel; //Mask in the new channel |
mzcs | 0:1f830fa5c9b8 | 47 | si4703_registers[CHANNEL] |= (1<<TUNE); //Set the TUNE bit to start |
mzcs | 0:1f830fa5c9b8 | 48 | updateRegisters(); |
mzcs | 0:1f830fa5c9b8 | 49 | |
mzcs | 0:1f830fa5c9b8 | 50 | wait_ms(60); //Wait 60ms - you can use or skip this delay |
mzcs | 0:1f830fa5c9b8 | 51 | |
mzcs | 0:1f830fa5c9b8 | 52 | //Poll to see if STC is set |
mzcs | 0:1f830fa5c9b8 | 53 | while(1) { |
mzcs | 0:1f830fa5c9b8 | 54 | ack = readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 55 | wait_ms(1); // Just In Case... |
mzcs | 0:1f830fa5c9b8 | 56 | if (( (si4703_registers[STATUSRSSI] & (1<<STC)) != 0) || (ack != SUCCESS)) break; //Tuning complete! (or FAILED) |
mzcs | 0:1f830fa5c9b8 | 57 | } |
mzcs | 0:1f830fa5c9b8 | 58 | |
mzcs | 0:1f830fa5c9b8 | 59 | readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 60 | si4703_registers[CHANNEL] &= ~(1<<TUNE); //Clear the tune after a tune has completed |
mzcs | 0:1f830fa5c9b8 | 61 | updateRegisters(); |
mzcs | 0:1f830fa5c9b8 | 62 | |
mzcs | 0:1f830fa5c9b8 | 63 | //Wait for the si4703 to clear the STC as well |
mzcs | 0:1f830fa5c9b8 | 64 | while(1) { |
mzcs | 0:1f830fa5c9b8 | 65 | ack = readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 66 | wait_ms(1); // Just In Case... |
mzcs | 0:1f830fa5c9b8 | 67 | if (( (si4703_registers[STATUSRSSI] & (1<<STC)) == 0) || (ack != SUCCESS)) break; //Tuning complete! (or FAILED) |
mzcs | 0:1f830fa5c9b8 | 68 | } |
mzcs | 0:1f830fa5c9b8 | 69 | } |
mzcs | 0:1f830fa5c9b8 | 70 | |
mzcs | 0:1f830fa5c9b8 | 71 | int Si4703_Breakout::seekUp() |
mzcs | 0:1f830fa5c9b8 | 72 | { |
mzcs | 0:1f830fa5c9b8 | 73 | return seek(SEEK_UP); |
mzcs | 0:1f830fa5c9b8 | 74 | } |
mzcs | 0:1f830fa5c9b8 | 75 | |
mzcs | 0:1f830fa5c9b8 | 76 | int Si4703_Breakout::seekDown() |
mzcs | 0:1f830fa5c9b8 | 77 | { |
mzcs | 0:1f830fa5c9b8 | 78 | return seek(SEEK_DOWN); |
mzcs | 0:1f830fa5c9b8 | 79 | } |
mzcs | 0:1f830fa5c9b8 | 80 | |
mzcs | 0:1f830fa5c9b8 | 81 | void Si4703_Breakout::setVolume(int volume) |
mzcs | 0:1f830fa5c9b8 | 82 | { |
mzcs | 0:1f830fa5c9b8 | 83 | readRegisters(); //Read the current register set |
mzcs | 0:1f830fa5c9b8 | 84 | if(volume < 0) volume = 0; |
mzcs | 0:1f830fa5c9b8 | 85 | if (volume > 15) volume = 15; |
mzcs | 0:1f830fa5c9b8 | 86 | si4703_registers[SYSCONFIG2] &= 0xFFF0; //Clear volume bits |
mzcs | 0:1f830fa5c9b8 | 87 | si4703_registers[SYSCONFIG2] |= volume; //Set new volume |
mzcs | 0:1f830fa5c9b8 | 88 | updateRegisters(); //Update |
mzcs | 0:1f830fa5c9b8 | 89 | } |
mzcs | 0:1f830fa5c9b8 | 90 | |
mzcs | 0:1f830fa5c9b8 | 91 | uint8_t Si4703_Breakout::getVolume() |
mzcs | 0:1f830fa5c9b8 | 92 | { |
mzcs | 0:1f830fa5c9b8 | 93 | readRegisters(); //Read the current register set |
mzcs | 0:1f830fa5c9b8 | 94 | |
mzcs | 0:1f830fa5c9b8 | 95 | return (si4703_registers[SYSCONFIG2] & 0x000F); |
mzcs | 0:1f830fa5c9b8 | 96 | } |
mzcs | 0:1f830fa5c9b8 | 97 | |
mzcs | 0:1f830fa5c9b8 | 98 | /* |
mzcs | 0:1f830fa5c9b8 | 99 | void Si4703_Breakout::readRDS(char* buffer, long timeout) |
mzcs | 0:1f830fa5c9b8 | 100 | { |
mzcs | 0:1f830fa5c9b8 | 101 | long endTime = millis() + timeout; |
mzcs | 0:1f830fa5c9b8 | 102 | boolean completed[] = {false, false, false, false}; |
mzcs | 0:1f830fa5c9b8 | 103 | int completedCount = 0; |
mzcs | 0:1f830fa5c9b8 | 104 | while(completedCount < 4 && millis() < endTime) { |
mzcs | 0:1f830fa5c9b8 | 105 | readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 106 | if(si4703_registers[STATUSRSSI] & (1<<RDSR)){ |
mzcs | 0:1f830fa5c9b8 | 107 | // ls 2 bits of B determine the 4 letter pairs |
mzcs | 0:1f830fa5c9b8 | 108 | // once we have a full set return |
mzcs | 0:1f830fa5c9b8 | 109 | // if you get nothing after 20 readings return with empty string |
mzcs | 0:1f830fa5c9b8 | 110 | uint16_t b = si4703_registers[RDSB]; |
mzcs | 0:1f830fa5c9b8 | 111 | int index = b & 0x03; |
mzcs | 0:1f830fa5c9b8 | 112 | if (! completed[index] && b < 500) |
mzcs | 0:1f830fa5c9b8 | 113 | { |
mzcs | 0:1f830fa5c9b8 | 114 | completed[index] = true; |
mzcs | 0:1f830fa5c9b8 | 115 | completedCount ++; |
mzcs | 0:1f830fa5c9b8 | 116 | char Dh = (si4703_registers[RDSD] & 0xFF00) >> 8; |
mzcs | 0:1f830fa5c9b8 | 117 | char Dl = (si4703_registers[RDSD] & 0x00FF); |
mzcs | 0:1f830fa5c9b8 | 118 | buffer[index * 2] = Dh; |
mzcs | 0:1f830fa5c9b8 | 119 | buffer[index * 2 +1] = Dl; |
mzcs | 0:1f830fa5c9b8 | 120 | // Serial.print(si4703_registers[RDSD]); Serial.print(" "); |
mzcs | 0:1f830fa5c9b8 | 121 | // Serial.print(index);Serial.print(" "); |
mzcs | 0:1f830fa5c9b8 | 122 | // Serial.write(Dh); |
mzcs | 0:1f830fa5c9b8 | 123 | // Serial.write(Dl); |
mzcs | 0:1f830fa5c9b8 | 124 | // Serial.println(); |
mzcs | 0:1f830fa5c9b8 | 125 | } |
mzcs | 0:1f830fa5c9b8 | 126 | delay(40); //Wait for the RDS bit to clear |
mzcs | 0:1f830fa5c9b8 | 127 | } |
mzcs | 0:1f830fa5c9b8 | 128 | else { |
mzcs | 0:1f830fa5c9b8 | 129 | delay(30); //From AN230, using the polling method 40ms should be sufficient amount of time between checks |
mzcs | 0:1f830fa5c9b8 | 130 | } |
mzcs | 0:1f830fa5c9b8 | 131 | } |
mzcs | 0:1f830fa5c9b8 | 132 | if (millis() >= endTime) { |
mzcs | 0:1f830fa5c9b8 | 133 | buffer[0] ='\0'; |
mzcs | 0:1f830fa5c9b8 | 134 | return; |
mzcs | 0:1f830fa5c9b8 | 135 | } |
mzcs | 0:1f830fa5c9b8 | 136 | |
mzcs | 0:1f830fa5c9b8 | 137 | buffer[8] = '\0'; |
mzcs | 0:1f830fa5c9b8 | 138 | } |
mzcs | 0:1f830fa5c9b8 | 139 | */ |
mzcs | 0:1f830fa5c9b8 | 140 | |
mzcs | 0:1f830fa5c9b8 | 141 | |
mzcs | 0:1f830fa5c9b8 | 142 | |
mzcs | 0:1f830fa5c9b8 | 143 | //To get the Si4703 inito 2-wire mode, SEN needs to be high and SDIO needs to be low after a reset |
mzcs | 0:1f830fa5c9b8 | 144 | //The breakout board has SEN pulled high, but also has SDIO pulled high. Therefore, after a normal power up |
mzcs | 0:1f830fa5c9b8 | 145 | //The Si4703 will be in an unknown state. RST must be controlled |
mzcs | 0:1f830fa5c9b8 | 146 | void Si4703_Breakout::si4703_init() |
mzcs | 0:1f830fa5c9b8 | 147 | { |
mzcs | 0:1f830fa5c9b8 | 148 | _reset_ = new DigitalOut(_resetPin); |
mzcs | 0:1f830fa5c9b8 | 149 | _sdio_ = new DigitalOut(_sdioPin); |
mzcs | 0:1f830fa5c9b8 | 150 | |
mzcs | 0:1f830fa5c9b8 | 151 | _sdio_->write(0); //A low SDIO indicates a 2-wire interface |
mzcs | 0:1f830fa5c9b8 | 152 | _reset_->write(0); //Put Si4703 into reset |
mzcs | 0:1f830fa5c9b8 | 153 | wait_ms(1); //Some delays while we allow pins to settle |
mzcs | 0:1f830fa5c9b8 | 154 | _reset_->write(1); //Bring Si4703 out of reset with SDIO set to low and SEN pulled high with on-board resistor |
mzcs | 0:1f830fa5c9b8 | 155 | wait_ms(1); //Allow Si4703 to come out of reset |
mzcs | 0:1f830fa5c9b8 | 156 | |
mzcs | 0:1f830fa5c9b8 | 157 | //Now that the unit is reset and I2C inteface mode, we need to begin I2C |
mzcs | 0:1f830fa5c9b8 | 158 | i2c_ = new I2C(_sdioPin, _sclkPin); |
mzcs | 0:1f830fa5c9b8 | 159 | i2c_->frequency(100000); |
mzcs | 0:1f830fa5c9b8 | 160 | /// |
mzcs | 0:1f830fa5c9b8 | 161 | |
mzcs | 0:1f830fa5c9b8 | 162 | readRegisters(); //Read the current register set |
mzcs | 0:1f830fa5c9b8 | 163 | si4703_registers[0x07] = 0x8100; //Enable the oscillator, from AN230 page 9, rev 0.61 (works) |
mzcs | 0:1f830fa5c9b8 | 164 | updateRegisters(); //Update |
mzcs | 0:1f830fa5c9b8 | 165 | |
mzcs | 0:1f830fa5c9b8 | 166 | wait_ms(500); //Wait for clock to settle - from AN230 page 9 |
mzcs | 0:1f830fa5c9b8 | 167 | |
mzcs | 0:1f830fa5c9b8 | 168 | readRegisters(); //Read the current register set |
mzcs | 0:1f830fa5c9b8 | 169 | si4703_registers[POWERCFG] = 0x4001; //Enable the IC |
mzcs | 0:1f830fa5c9b8 | 170 | // si4703_registers[POWERCFG] |= (1<<SMUTE) | (1<<DMUTE); //Disable Mute, disable softmute |
mzcs | 0:1f830fa5c9b8 | 171 | si4703_registers[SYSCONFIG1] |= (1<<RDS); //Enable RDS |
mzcs | 0:1f830fa5c9b8 | 172 | |
mzcs | 0:1f830fa5c9b8 | 173 | si4703_registers[SYSCONFIG1] |= (1<<DE); //50kHz Europe setup |
mzcs | 0:1f830fa5c9b8 | 174 | si4703_registers[SYSCONFIG2] |= (1<<SPACE0); //100kHz channel spacing for Europe |
mzcs | 0:1f830fa5c9b8 | 175 | |
mzcs | 0:1f830fa5c9b8 | 176 | si4703_registers[SYSCONFIG2] &= 0xFFF0; //Clear volume bits |
mzcs | 0:1f830fa5c9b8 | 177 | si4703_registers[SYSCONFIG2] |= 0x0001; //Set volume to lowest |
mzcs | 0:1f830fa5c9b8 | 178 | updateRegisters(); //Update |
mzcs | 0:1f830fa5c9b8 | 179 | |
mzcs | 0:1f830fa5c9b8 | 180 | wait_ms(110); //Max powerup time, from datasheet page 13 |
mzcs | 0:1f830fa5c9b8 | 181 | |
mzcs | 0:1f830fa5c9b8 | 182 | } |
mzcs | 0:1f830fa5c9b8 | 183 | |
mzcs | 0:1f830fa5c9b8 | 184 | //Read the entire register control set from 0x00 to 0x0F |
mzcs | 0:1f830fa5c9b8 | 185 | uint8_t Si4703_Breakout::readRegisters(){ |
mzcs | 0:1f830fa5c9b8 | 186 | |
mzcs | 0:1f830fa5c9b8 | 187 | //Si4703 begins reading from register upper register of 0x0A and reads to 0x0F, then loops to 0x00. |
mzcs | 0:1f830fa5c9b8 | 188 | // Wire.requestFrom(SI4703, 32); //We want to read the entire register set from 0x0A to 0x09 = 32 uint8_ts. |
mzcs | 0:1f830fa5c9b8 | 189 | char data[32]; |
mzcs | 0:1f830fa5c9b8 | 190 | uint8_t ack = i2c_->read(SI4703, data, 32); //Read in these 32 uint8_ts |
mzcs | 0:1f830fa5c9b8 | 191 | |
mzcs | 0:1f830fa5c9b8 | 192 | if (ack != 0) { //We have a problem! |
mzcs | 0:1f830fa5c9b8 | 193 | return(FAIL); |
mzcs | 0:1f830fa5c9b8 | 194 | } |
mzcs | 0:1f830fa5c9b8 | 195 | |
mzcs | 0:1f830fa5c9b8 | 196 | //Remember, register 0x0A comes in first so we have to shuffle the array around a bit |
mzcs | 0:1f830fa5c9b8 | 197 | for (int y=0; y<6; y++) |
mzcs | 0:1f830fa5c9b8 | 198 | { |
mzcs | 0:1f830fa5c9b8 | 199 | si4703_registers[0x0A+y] = 0; |
mzcs | 0:1f830fa5c9b8 | 200 | si4703_registers[0x0A+y] = data[(y*2)+1]; |
mzcs | 0:1f830fa5c9b8 | 201 | si4703_registers[0x0A+y] |= (data[(y*2)] << 8); |
mzcs | 0:1f830fa5c9b8 | 202 | } |
mzcs | 0:1f830fa5c9b8 | 203 | |
mzcs | 0:1f830fa5c9b8 | 204 | for (int y=0; y<10; y++) |
mzcs | 0:1f830fa5c9b8 | 205 | { |
mzcs | 0:1f830fa5c9b8 | 206 | si4703_registers[y] = 0; |
mzcs | 0:1f830fa5c9b8 | 207 | si4703_registers[y] = data[(12)+(y*2)+1]; |
mzcs | 0:1f830fa5c9b8 | 208 | si4703_registers[y] |= (data[(12)+(y*2)] << 8); |
mzcs | 0:1f830fa5c9b8 | 209 | } |
mzcs | 0:1f830fa5c9b8 | 210 | //We're done! |
mzcs | 0:1f830fa5c9b8 | 211 | /// |
mzcs | 0:1f830fa5c9b8 | 212 | return(SUCCESS); |
mzcs | 0:1f830fa5c9b8 | 213 | } |
mzcs | 0:1f830fa5c9b8 | 214 | |
mzcs | 0:1f830fa5c9b8 | 215 | //Write the current 9 control registers (0x02 to 0x07) to the Si4703 |
mzcs | 0:1f830fa5c9b8 | 216 | //It's a little weird, you don't write an I2C address |
mzcs | 0:1f830fa5c9b8 | 217 | //The Si4703 assumes you are writing to 0x02 first, then increments |
mzcs | 0:1f830fa5c9b8 | 218 | uint8_t Si4703_Breakout::updateRegisters() { |
mzcs | 0:1f830fa5c9b8 | 219 | |
mzcs | 0:1f830fa5c9b8 | 220 | char data[12]; |
mzcs | 0:1f830fa5c9b8 | 221 | |
mzcs | 0:1f830fa5c9b8 | 222 | //First we send the 0x02 to 0x07 control registers |
mzcs | 0:1f830fa5c9b8 | 223 | //In general, we should not write to registers 0x08 and 0x09 |
mzcs | 0:1f830fa5c9b8 | 224 | for(int regSpot = 0x02 ; regSpot < 0x08 ; regSpot++) { |
mzcs | 0:1f830fa5c9b8 | 225 | data[(regSpot-2)*2] = si4703_registers[regSpot] >> 8; |
mzcs | 0:1f830fa5c9b8 | 226 | data[((regSpot-2)*2)+1] = si4703_registers[regSpot] & 0x00FF; |
mzcs | 0:1f830fa5c9b8 | 227 | } |
mzcs | 0:1f830fa5c9b8 | 228 | |
mzcs | 0:1f830fa5c9b8 | 229 | 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 |
mzcs | 0:1f830fa5c9b8 | 230 | |
mzcs | 0:1f830fa5c9b8 | 231 | if(ack != 0) { //We have a problem! |
mzcs | 0:1f830fa5c9b8 | 232 | return(FAIL); |
mzcs | 0:1f830fa5c9b8 | 233 | } |
mzcs | 0:1f830fa5c9b8 | 234 | |
mzcs | 0:1f830fa5c9b8 | 235 | return(SUCCESS); |
mzcs | 0:1f830fa5c9b8 | 236 | } |
mzcs | 0:1f830fa5c9b8 | 237 | |
mzcs | 0:1f830fa5c9b8 | 238 | //Returns The Value of a Register |
mzcs | 0:1f830fa5c9b8 | 239 | uint16_t Si4703_Breakout::getRegister(uint8_t regNum) |
mzcs | 0:1f830fa5c9b8 | 240 | { |
mzcs | 0:1f830fa5c9b8 | 241 | readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 242 | return si4703_registers[regNum]; |
mzcs | 0:1f830fa5c9b8 | 243 | // No Error Status Checking |
mzcs | 0:1f830fa5c9b8 | 244 | } |
mzcs | 0:1f830fa5c9b8 | 245 | |
mzcs | 0:1f830fa5c9b8 | 246 | //Seeks out the next available station |
mzcs | 0:1f830fa5c9b8 | 247 | //Returns the freq if it made it |
mzcs | 0:1f830fa5c9b8 | 248 | //Returns zero if failed |
mzcs | 0:1f830fa5c9b8 | 249 | int Si4703_Breakout::seek(bool seekDirection){ |
mzcs | 0:1f830fa5c9b8 | 250 | uint8_t ack; |
mzcs | 0:1f830fa5c9b8 | 251 | readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 252 | //Set seek mode wrap bit |
mzcs | 0:1f830fa5c9b8 | 253 | si4703_registers[POWERCFG] |= (1<<SKMODE); //Allow wrap |
mzcs | 0:1f830fa5c9b8 | 254 | //si4703_registers[POWERCFG] &= ~(1<<SKMODE); //Disallow wrap - if you disallow wrap, you may want to tune to 87.5 first |
mzcs | 0:1f830fa5c9b8 | 255 | if(seekDirection == SEEK_DOWN) si4703_registers[POWERCFG] &= ~(1<<SEEKUP); //Seek down is the default upon reset |
mzcs | 0:1f830fa5c9b8 | 256 | else si4703_registers[POWERCFG] |= 1<<SEEKUP; //Set the bit to seek up |
mzcs | 0:1f830fa5c9b8 | 257 | |
mzcs | 0:1f830fa5c9b8 | 258 | si4703_registers[POWERCFG] |= (1<<SEEK); //Start seek |
mzcs | 0:1f830fa5c9b8 | 259 | updateRegisters(); //Seeking will now start |
mzcs | 0:1f830fa5c9b8 | 260 | |
mzcs | 0:1f830fa5c9b8 | 261 | //Poll to see if STC is set |
mzcs | 0:1f830fa5c9b8 | 262 | while(1) { |
mzcs | 0:1f830fa5c9b8 | 263 | ack = readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 264 | wait_ms(1); // Just In Case... |
mzcs | 0:1f830fa5c9b8 | 265 | if (((si4703_registers[STATUSRSSI] & (1<<STC)) != 0) || (ack != SUCCESS)) break; //Tuning complete! (or FAILED) |
mzcs | 0:1f830fa5c9b8 | 266 | } |
mzcs | 0:1f830fa5c9b8 | 267 | |
mzcs | 0:1f830fa5c9b8 | 268 | readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 269 | int valueSFBL = si4703_registers[STATUSRSSI] & (1<<SFBL); //Store the value of SFBL |
mzcs | 0:1f830fa5c9b8 | 270 | si4703_registers[POWERCFG] &= ~(1<<SEEK); //Clear the seek bit after seek has completed |
mzcs | 0:1f830fa5c9b8 | 271 | updateRegisters(); |
mzcs | 0:1f830fa5c9b8 | 272 | |
mzcs | 0:1f830fa5c9b8 | 273 | //Wait for the si4703 to clear the STC as well |
mzcs | 0:1f830fa5c9b8 | 274 | while(1) { |
mzcs | 0:1f830fa5c9b8 | 275 | ack = readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 276 | wait_ms(1); // Just In Case... |
mzcs | 0:1f830fa5c9b8 | 277 | if (((si4703_registers[STATUSRSSI] & (1<<STC)) == 0) || (ack != SUCCESS)) break; //Tuning complete! (or FAILED) |
mzcs | 0:1f830fa5c9b8 | 278 | } |
mzcs | 0:1f830fa5c9b8 | 279 | |
mzcs | 0:1f830fa5c9b8 | 280 | if(valueSFBL) { //The bit was set indicating we hit a band limit or failed to find a station |
mzcs | 0:1f830fa5c9b8 | 281 | return(0); |
mzcs | 0:1f830fa5c9b8 | 282 | } |
mzcs | 0:1f830fa5c9b8 | 283 | return getChannel(); |
mzcs | 0:1f830fa5c9b8 | 284 | } |
mzcs | 0:1f830fa5c9b8 | 285 | |
mzcs | 0:1f830fa5c9b8 | 286 | //Reads the current channel from READCHAN |
mzcs | 0:1f830fa5c9b8 | 287 | //Returns a number like 973 for 97.3MHz |
mzcs | 0:1f830fa5c9b8 | 288 | int Si4703_Breakout::getChannel() { |
mzcs | 0:1f830fa5c9b8 | 289 | readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 290 | int channel = (si4703_registers[READCHAN] & 0x03FF); //Mask out everything but the lower 10 bits |
mzcs | 0:1f830fa5c9b8 | 291 | //Freq(MHz) = 0.100(in Europe) * Channel + 87.5MHz |
mzcs | 0:1f830fa5c9b8 | 292 | //X = 0.1 * Chan + 87.5 |
mzcs | 0:1f830fa5c9b8 | 293 | channel += 875; //98 + 875 = 973 ( for 97.3 MHz ) |
mzcs | 0:1f830fa5c9b8 | 294 | return(channel); |
mzcs | 0:1f830fa5c9b8 | 295 | } |
mzcs | 0:1f830fa5c9b8 | 296 | |
mzcs | 0:1f830fa5c9b8 | 297 | void Si4703_Breakout::printRegs() { |
mzcs | 0:1f830fa5c9b8 | 298 | readRegisters(); |
mzcs | 0:1f830fa5c9b8 | 299 | for (int x=0; x<16; x++) { pc->printf("Reg# 0x%X = 0x%X\r\n",x,si4703_registers[x]); } |
mzcs | 0:1f830fa5c9b8 | 300 | } |