Brett Wilson
/
Si4735
Si4735 Radio Library
Si4735.cpp@0:42c032fc907a, 2011-10-12 (annotated)
- Committer:
- bwilson30
- Date:
- Wed Oct 12 17:01:38 2011 +0000
- Revision:
- 0:42c032fc907a
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
bwilson30 | 0:42c032fc907a | 1 | /* mbed Si4735 Library |
bwilson30 | 0:42c032fc907a | 2 | * Brett Wilson and Brett Berry |
bwilson30 | 0:42c032fc907a | 3 | * Georgia Tech ECE 4180 |
bwilson30 | 0:42c032fc907a | 4 | * Note: this code has only been tested for FM. |
bwilson30 | 0:42c032fc907a | 5 | * Ported from ... |
bwilson30 | 0:42c032fc907a | 6 | |
bwilson30 | 0:42c032fc907a | 7 | * Arduino Si4735 Library |
bwilson30 | 0:42c032fc907a | 8 | * Written by Ryan Owens for SparkFun Electronics |
bwilson30 | 0:42c032fc907a | 9 | * 5/17/11 |
bwilson30 | 0:42c032fc907a | 10 | * |
bwilson30 | 0:42c032fc907a | 11 | * This library is for use with the SparkFun Si4735 Shield |
bwilson30 | 0:42c032fc907a | 12 | * Released under the 'Buy Me a Beer' license |
bwilson30 | 0:42c032fc907a | 13 | * (If we ever meet, you buy me a beer) |
bwilson30 | 0:42c032fc907a | 14 | * |
bwilson30 | 0:42c032fc907a | 15 | * See the header file for better function documentation. |
bwilson30 | 0:42c032fc907a | 16 | * |
bwilson30 | 0:42c032fc907a | 17 | * See the example sketches to learn how to use the library in your code. |
bwilson30 | 0:42c032fc907a | 18 | */ |
bwilson30 | 0:42c032fc907a | 19 | |
bwilson30 | 0:42c032fc907a | 20 | #include "Si4735.h" |
bwilson30 | 0:42c032fc907a | 21 | #include "mbed.h" |
bwilson30 | 0:42c032fc907a | 22 | |
bwilson30 | 0:42c032fc907a | 23 | //This is just a constructor. |
bwilson30 | 0:42c032fc907a | 24 | Si4735::Si4735(PinName sda, PinName scl, PinName RST_) : |
bwilson30 | 0:42c032fc907a | 25 | _RST_(RST_) { |
bwilson30 | 0:42c032fc907a | 26 | i2c_ = new I2C(sda, scl); |
bwilson30 | 0:42c032fc907a | 27 | i2c_->frequency(100000); |
bwilson30 | 0:42c032fc907a | 28 | } |
bwilson30 | 0:42c032fc907a | 29 | |
bwilson30 | 0:42c032fc907a | 30 | |
bwilson30 | 0:42c032fc907a | 31 | void Si4735::begin(char mode){ |
bwilson30 | 0:42c032fc907a | 32 | _mode = mode; |
bwilson30 | 0:42c032fc907a | 33 | //Set the initial volume level. |
bwilson30 | 0:42c032fc907a | 34 | _currentVolume=63; |
bwilson30 | 0:42c032fc907a | 35 | |
bwilson30 | 0:42c032fc907a | 36 | // Reset the Si4735 |
bwilson30 | 0:42c032fc907a | 37 | _RST_ = 0; |
bwilson30 | 0:42c032fc907a | 38 | wait(.2); |
bwilson30 | 0:42c032fc907a | 39 | _RST_ = 1; |
bwilson30 | 0:42c032fc907a | 40 | wait(.2); |
bwilson30 | 0:42c032fc907a | 41 | |
bwilson30 | 0:42c032fc907a | 42 | |
bwilson30 | 0:42c032fc907a | 43 | //Send the POWER_UP command |
bwilson30 | 0:42c032fc907a | 44 | switch(_mode){ |
bwilson30 | 0:42c032fc907a | 45 | case FM: |
bwilson30 | 0:42c032fc907a | 46 | sprintf(command, "%c%c%c", 0x01, 0x10, 0x05); |
bwilson30 | 0:42c032fc907a | 47 | break; |
bwilson30 | 0:42c032fc907a | 48 | case AM: |
bwilson30 | 0:42c032fc907a | 49 | case SW: |
bwilson30 | 0:42c032fc907a | 50 | case LW: |
bwilson30 | 0:42c032fc907a | 51 | sprintf(command, "%c%c%c", 0x01, 0x11, 0x05); |
bwilson30 | 0:42c032fc907a | 52 | break; |
bwilson30 | 0:42c032fc907a | 53 | default: |
bwilson30 | 0:42c032fc907a | 54 | return; |
bwilson30 | 0:42c032fc907a | 55 | } |
bwilson30 | 0:42c032fc907a | 56 | sendCommand(command, 3); |
bwilson30 | 0:42c032fc907a | 57 | wait(.2); |
bwilson30 | 0:42c032fc907a | 58 | |
bwilson30 | 0:42c032fc907a | 59 | // Set the RCLK to 32768Hz |
bwilson30 | 0:42c032fc907a | 60 | sprintf(command, "%c%c%c%c%c%c", 0x12, 0x00, 0x02, 0x01, 0x80, 0x00); |
bwilson30 | 0:42c032fc907a | 61 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 62 | wait(.2); |
bwilson30 | 0:42c032fc907a | 63 | |
bwilson30 | 0:42c032fc907a | 64 | // Set default frequency to 99.7 MHz FM |
bwilson30 | 0:42c032fc907a | 65 | sprintf(command, "%c%c%c%c", 0x20, 0x00, 0x26, 0xF2); |
bwilson30 | 0:42c032fc907a | 66 | sendCommand(command, 4); |
bwilson30 | 0:42c032fc907a | 67 | wait(.2); |
bwilson30 | 0:42c032fc907a | 68 | |
bwilson30 | 0:42c032fc907a | 69 | //Set the volume to the current value. |
bwilson30 | 0:42c032fc907a | 70 | sprintf(command, "%c%c%c%c%c%c", 0x12, 0x00, 0x40, 0x00, 0x00, _currentVolume); |
bwilson30 | 0:42c032fc907a | 71 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 72 | wait(.2); |
bwilson30 | 0:42c032fc907a | 73 | |
bwilson30 | 0:42c032fc907a | 74 | //Disable Mute |
bwilson30 | 0:42c032fc907a | 75 | sprintf(command, "%c%c%c%c%c%c", 0x12, 0x00, 0x40, 0x01, 0x00, 0x00); |
bwilson30 | 0:42c032fc907a | 76 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 77 | wait(.2); |
bwilson30 | 0:42c032fc907a | 78 | |
bwilson30 | 0:42c032fc907a | 79 | //Set the seek band for the desired mode (AM and FM can use default values) |
bwilson30 | 0:42c032fc907a | 80 | switch(_mode){ |
bwilson30 | 0:42c032fc907a | 81 | case SW: |
bwilson30 | 0:42c032fc907a | 82 | //Set the lower band limit for Short Wave Radio to 2300 kHz |
bwilson30 | 0:42c032fc907a | 83 | sprintf(command, "%c%c%c%c%c%c", 0x12, 0x00, 0x34, 0x00, 0x08, 0xFC); |
bwilson30 | 0:42c032fc907a | 84 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 85 | wait(.001); |
bwilson30 | 0:42c032fc907a | 86 | //Set the upper band limit for Short Wave Radio to 23000kHz |
bwilson30 | 0:42c032fc907a | 87 | sprintf(command, "%c%c%c%c%c%c", 0x12, 0x00, 0x34, 0x01, 0x59, 0xD8); |
bwilson30 | 0:42c032fc907a | 88 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 89 | wait(.001); |
bwilson30 | 0:42c032fc907a | 90 | break; |
bwilson30 | 0:42c032fc907a | 91 | case LW: |
bwilson30 | 0:42c032fc907a | 92 | //Set the lower band limit for Long Wave Radio to 152 kHz |
bwilson30 | 0:42c032fc907a | 93 | sprintf(command, "%c%c%c%c%c%c", 0x12, 0x00, 0x34, 0x00, 0x00, 0x99); |
bwilson30 | 0:42c032fc907a | 94 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 95 | wait(.001); |
bwilson30 | 0:42c032fc907a | 96 | //Set the upper band limit for Long Wave Radio to 279 kHz |
bwilson30 | 0:42c032fc907a | 97 | sprintf(command, "%c%c%c%c%c%c", 0x12, 0x00, 0x34, 0x01, 0x01, 0x17); |
bwilson30 | 0:42c032fc907a | 98 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 99 | wait(.001); |
bwilson30 | 0:42c032fc907a | 100 | break; |
bwilson30 | 0:42c032fc907a | 101 | default: |
bwilson30 | 0:42c032fc907a | 102 | break; |
bwilson30 | 0:42c032fc907a | 103 | } |
bwilson30 | 0:42c032fc907a | 104 | |
bwilson30 | 0:42c032fc907a | 105 | } |
bwilson30 | 0:42c032fc907a | 106 | |
bwilson30 | 0:42c032fc907a | 107 | /* |
bwilson30 | 0:42c032fc907a | 108 | * Description: Tunes the Si4735 to a frequency |
bwilson30 | 0:42c032fc907a | 109 | * |
bwilson30 | 0:42c032fc907a | 110 | * Params: int frequency - The desired frequency in kHz |
bwilson30 | 0:42c032fc907a | 111 | * |
bwilson30 | 0:42c032fc907a | 112 | * Returns: True if tune was successful |
bwilson30 | 0:42c032fc907a | 113 | * False if tune was unsuccessful |
bwilson30 | 0:42c032fc907a | 114 | */ |
bwilson30 | 0:42c032fc907a | 115 | bool Si4735::tuneFrequency(int frequency){ |
bwilson30 | 0:42c032fc907a | 116 | //Split the desired frequency into two character for use in the |
bwilson30 | 0:42c032fc907a | 117 | //set frequency command. |
bwilson30 | 0:42c032fc907a | 118 | char highByte = frequency >> 8; |
bwilson30 | 0:42c032fc907a | 119 | char lowByte = frequency & 0x00FF; |
bwilson30 | 0:42c032fc907a | 120 | |
bwilson30 | 0:42c032fc907a | 121 | //Depending on the current mode, set the new frequency. |
bwilson30 | 0:42c032fc907a | 122 | switch(_mode){ |
bwilson30 | 0:42c032fc907a | 123 | case FM: |
bwilson30 | 0:42c032fc907a | 124 | sprintf(command, "%c%c%c%c", 0x20, 0x00, highByte, lowByte); |
bwilson30 | 0:42c032fc907a | 125 | break; |
bwilson30 | 0:42c032fc907a | 126 | case AM: |
bwilson30 | 0:42c032fc907a | 127 | case SW: |
bwilson30 | 0:42c032fc907a | 128 | case LW: |
bwilson30 | 0:42c032fc907a | 129 | sprintf(command, "%c%c%c%c", 0x40, 0x00, highByte, lowByte); |
bwilson30 | 0:42c032fc907a | 130 | break; |
bwilson30 | 0:42c032fc907a | 131 | default: |
bwilson30 | 0:42c032fc907a | 132 | break; |
bwilson30 | 0:42c032fc907a | 133 | } |
bwilson30 | 0:42c032fc907a | 134 | sendCommand(command, 4); |
bwilson30 | 0:42c032fc907a | 135 | wait(.1); |
bwilson30 | 0:42c032fc907a | 136 | |
bwilson30 | 0:42c032fc907a | 137 | return true; |
bwilson30 | 0:42c032fc907a | 138 | } |
bwilson30 | 0:42c032fc907a | 139 | |
bwilson30 | 0:42c032fc907a | 140 | //This function does not work unless you bypass the buffer chip! |
bwilson30 | 0:42c032fc907a | 141 | int Si4735::getFrequency(void){ |
bwilson30 | 0:42c032fc907a | 142 | char data[8]; |
bwilson30 | 0:42c032fc907a | 143 | int freq = 0; |
bwilson30 | 0:42c032fc907a | 144 | // FM only |
bwilson30 | 0:42c032fc907a | 145 | i2c_->start(); |
bwilson30 | 0:42c032fc907a | 146 | i2c_->write(address_write); |
bwilson30 | 0:42c032fc907a | 147 | i2c_->write(0x22); |
bwilson30 | 0:42c032fc907a | 148 | i2c_->write(0x00); |
bwilson30 | 0:42c032fc907a | 149 | i2c_->stop(); |
bwilson30 | 0:42c032fc907a | 150 | i2c_->start(); |
bwilson30 | 0:42c032fc907a | 151 | i2c_->write(address_read); |
bwilson30 | 0:42c032fc907a | 152 | for (int i=0; i<8; i++) |
bwilson30 | 0:42c032fc907a | 153 | data[i] = i2c_->read(1); |
bwilson30 | 0:42c032fc907a | 154 | //i2c_->read(address_read, data, 8, false); |
bwilson30 | 0:42c032fc907a | 155 | i2c_->stop(); |
bwilson30 | 0:42c032fc907a | 156 | freq = data[2]; |
bwilson30 | 0:42c032fc907a | 157 | freq = (freq << 8) | data[3]; |
bwilson30 | 0:42c032fc907a | 158 | return freq; |
bwilson30 | 0:42c032fc907a | 159 | } |
bwilson30 | 0:42c032fc907a | 160 | |
bwilson30 | 0:42c032fc907a | 161 | bool Si4735::seekUp(void){ |
bwilson30 | 0:42c032fc907a | 162 | //Use the current mode selection to seek up. |
bwilson30 | 0:42c032fc907a | 163 | switch(_mode){ |
bwilson30 | 0:42c032fc907a | 164 | case FM: |
bwilson30 | 0:42c032fc907a | 165 | sprintf(command, "%c%c", 0x21, 0x0C); |
bwilson30 | 0:42c032fc907a | 166 | sendCommand(command, 2); |
bwilson30 | 0:42c032fc907a | 167 | break; |
bwilson30 | 0:42c032fc907a | 168 | case AM: |
bwilson30 | 0:42c032fc907a | 169 | case SW: |
bwilson30 | 0:42c032fc907a | 170 | case LW: |
bwilson30 | 0:42c032fc907a | 171 | sprintf(command, "%c%c%c%c%c%c", 0x41, 0x0C, 0x00, 0x00, 0x00, 0x00); |
bwilson30 | 0:42c032fc907a | 172 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 173 | break; |
bwilson30 | 0:42c032fc907a | 174 | default: |
bwilson30 | 0:42c032fc907a | 175 | break; |
bwilson30 | 0:42c032fc907a | 176 | } |
bwilson30 | 0:42c032fc907a | 177 | wait(.001); |
bwilson30 | 0:42c032fc907a | 178 | return true; |
bwilson30 | 0:42c032fc907a | 179 | } |
bwilson30 | 0:42c032fc907a | 180 | |
bwilson30 | 0:42c032fc907a | 181 | bool Si4735::seekDown(void){ |
bwilson30 | 0:42c032fc907a | 182 | //Use the current mode selection to seek down. |
bwilson30 | 0:42c032fc907a | 183 | switch(_mode){ |
bwilson30 | 0:42c032fc907a | 184 | case FM: |
bwilson30 | 0:42c032fc907a | 185 | sprintf(command, "%c%c", 0x21, 0x04); |
bwilson30 | 0:42c032fc907a | 186 | sendCommand(command, 2); |
bwilson30 | 0:42c032fc907a | 187 | break; |
bwilson30 | 0:42c032fc907a | 188 | case AM: |
bwilson30 | 0:42c032fc907a | 189 | case SW: |
bwilson30 | 0:42c032fc907a | 190 | case LW: |
bwilson30 | 0:42c032fc907a | 191 | sprintf(command, "%c%c%c%c%c%c", 0x41, 0x04, 0x00, 0x00, 0x00, 0x00); |
bwilson30 | 0:42c032fc907a | 192 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 193 | break; |
bwilson30 | 0:42c032fc907a | 194 | default: |
bwilson30 | 0:42c032fc907a | 195 | break; |
bwilson30 | 0:42c032fc907a | 196 | } |
bwilson30 | 0:42c032fc907a | 197 | wait(.001); |
bwilson30 | 0:42c032fc907a | 198 | return true; |
bwilson30 | 0:42c032fc907a | 199 | } |
bwilson30 | 0:42c032fc907a | 200 | |
bwilson30 | 0:42c032fc907a | 201 | void Si4735::volumeUp(void){ |
bwilson30 | 0:42c032fc907a | 202 | //If we're not at the maximum volume yet, increase the volume |
bwilson30 | 0:42c032fc907a | 203 | if(_currentVolume < 63){ |
bwilson30 | 0:42c032fc907a | 204 | _currentVolume+=1; |
bwilson30 | 0:42c032fc907a | 205 | //Set the volume to the current value. |
bwilson30 | 0:42c032fc907a | 206 | sprintf(command, "%c%c%c%c%c%c", 0x12, 0x00, 0x40, 0x00, 0x00, _currentVolume); |
bwilson30 | 0:42c032fc907a | 207 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 208 | wait(.01); |
bwilson30 | 0:42c032fc907a | 209 | } |
bwilson30 | 0:42c032fc907a | 210 | } |
bwilson30 | 0:42c032fc907a | 211 | |
bwilson30 | 0:42c032fc907a | 212 | void Si4735::volumeDown(void){ |
bwilson30 | 0:42c032fc907a | 213 | //If we're not at the maximum volume yet, increase the volume |
bwilson30 | 0:42c032fc907a | 214 | if(_currentVolume > 0){ |
bwilson30 | 0:42c032fc907a | 215 | _currentVolume-=1; |
bwilson30 | 0:42c032fc907a | 216 | //Set the volume to the current value. |
bwilson30 | 0:42c032fc907a | 217 | sprintf(command, "%c%c%c%c%c%c", 0x12, 0x00, 0x40, 0x00, 0x00, _currentVolume); |
bwilson30 | 0:42c032fc907a | 218 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 219 | wait(.01); |
bwilson30 | 0:42c032fc907a | 220 | } |
bwilson30 | 0:42c032fc907a | 221 | } |
bwilson30 | 0:42c032fc907a | 222 | |
bwilson30 | 0:42c032fc907a | 223 | void Si4735::mute(void){ |
bwilson30 | 0:42c032fc907a | 224 | //Disable Mute |
bwilson30 | 0:42c032fc907a | 225 | sprintf(command, "%c%c%c%c%c%c", 0x12, 0x00, 0x40, 0x01, 0x00, 0x03); |
bwilson30 | 0:42c032fc907a | 226 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 227 | wait(.001); |
bwilson30 | 0:42c032fc907a | 228 | } |
bwilson30 | 0:42c032fc907a | 229 | |
bwilson30 | 0:42c032fc907a | 230 | void Si4735::unmute(void){ |
bwilson30 | 0:42c032fc907a | 231 | //Disable Mute |
bwilson30 | 0:42c032fc907a | 232 | sprintf(command, "%c%c%c%c%c%c", 0x12, 0x00, 0x40, 0x01, 0x00, 0x00); |
bwilson30 | 0:42c032fc907a | 233 | sendCommand(command, 6); |
bwilson30 | 0:42c032fc907a | 234 | wait(.001); |
bwilson30 | 0:42c032fc907a | 235 | } |
bwilson30 | 0:42c032fc907a | 236 | |
bwilson30 | 0:42c032fc907a | 237 | /*char Si4735::getStatus(void){ |
bwilson30 | 0:42c032fc907a | 238 | char response; |
bwilson30 | 0:42c032fc907a | 239 | bool ack1, ack2; |
bwilson30 | 0:42c032fc907a | 240 | i2c_->start(); |
bwilson30 | 0:42c032fc907a | 241 | ack1 = i2c_->write(address_); //Send i2c address and wait for ack (true) to proceed |
bwilson30 | 0:42c032fc907a | 242 | response = spi_->write(0xA0); //read a single byte |
bwilson30 | 0:42c032fc907a | 243 | _cs_ = 1; |
bwilson30 | 0:42c032fc907a | 244 | wait(.001); |
bwilson30 | 0:42c032fc907a | 245 | return response; |
bwilson30 | 0:42c032fc907a | 246 | }*/ |
bwilson30 | 0:42c032fc907a | 247 | /*void Si4735::getResponse(char * response){ |
bwilson30 | 0:42c032fc907a | 248 | |
bwilson30 | 0:42c032fc907a | 249 | }*/ |
bwilson30 | 0:42c032fc907a | 250 | |
bwilson30 | 0:42c032fc907a | 251 | void Si4735::end(void){ |
bwilson30 | 0:42c032fc907a | 252 | sprintf(command, "%c", 0x11); |
bwilson30 | 0:42c032fc907a | 253 | sendCommand(command, 1); |
bwilson30 | 0:42c032fc907a | 254 | wait(.001); |
bwilson30 | 0:42c032fc907a | 255 | } |
bwilson30 | 0:42c032fc907a | 256 | |
bwilson30 | 0:42c032fc907a | 257 | /******************************************* |
bwilson30 | 0:42c032fc907a | 258 | * |
bwilson30 | 0:42c032fc907a | 259 | * Private Functions |
bwilson30 | 0:42c032fc907a | 260 | * |
bwilson30 | 0:42c032fc907a | 261 | *******************************************/ |
bwilson30 | 0:42c032fc907a | 262 | |
bwilson30 | 0:42c032fc907a | 263 | void Si4735::sendCommand(char * command, int length){ |
bwilson30 | 0:42c032fc907a | 264 | //ack = i2c_->write(address_write, command, length, false); |
bwilson30 | 0:42c032fc907a | 265 | i2c_->start(); |
bwilson30 | 0:42c032fc907a | 266 | bool ack = i2c_->write(address_write); |
bwilson30 | 0:42c032fc907a | 267 | for(int i=0; i<length; i++) |
bwilson30 | 0:42c032fc907a | 268 | ack = i2c_->write(command[i]); |
bwilson30 | 0:42c032fc907a | 269 | char CTS = i2c_->read(1); |
bwilson30 | 0:42c032fc907a | 270 | i2c_->stop(); |
bwilson30 | 0:42c032fc907a | 271 | } |