Library for Silicon Labs Si47xx AM/FM receiver. I tested Si4730 and Si4735.

Committer:
matsujirushi
Date:
Sun Sep 06 05:39:04 2015 +0000
Revision:
3:4873fd430c38
Parent:
2:d0de9c9c66a8
Add setProperty().

Who changed what in which revision?

UserRevisionLine numberNew contents of line
matsujirushi 0:0672d41196db 1 #include "MjSi47xx.h"
matsujirushi 0:0672d41196db 2
matsujirushi 0:0672d41196db 3 MjSi47xx::MjSi47xx(I2C* i2c, uint8_t address, DigitalOut* rst_n)
matsujirushi 0:0672d41196db 4 {
matsujirushi 0:0672d41196db 5 this->i2c = i2c;
matsujirushi 0:0672d41196db 6 this->address = address;
matsujirushi 0:0672d41196db 7 this->rst_n = rst_n;
matsujirushi 1:c2a5efba43bc 8
matsujirushi 1:c2a5efba43bc 9 reset();
matsujirushi 0:0672d41196db 10 }
matsujirushi 0:0672d41196db 11
matsujirushi 0:0672d41196db 12 void MjSi47xx::reset()
matsujirushi 0:0672d41196db 13 {
matsujirushi 0:0672d41196db 14 *rst_n = 0;
matsujirushi 0:0672d41196db 15 }
matsujirushi 0:0672d41196db 16
matsujirushi 1:c2a5efba43bc 17 bool MjSi47xx::powerUp(FunctionType func)
matsujirushi 0:0672d41196db 18 {
matsujirushi 1:c2a5efba43bc 19 switch (func) {
matsujirushi 1:c2a5efba43bc 20 case FUNCTION_FM:
matsujirushi 1:c2a5efba43bc 21 case FUNCTION_AM:
matsujirushi 1:c2a5efba43bc 22 break;
matsujirushi 1:c2a5efba43bc 23 default:
matsujirushi 1:c2a5efba43bc 24 return false;
matsujirushi 1:c2a5efba43bc 25 }
matsujirushi 1:c2a5efba43bc 26
matsujirushi 0:0672d41196db 27 if (!*rst_n) {
matsujirushi 0:0672d41196db 28 wait_us(250);
matsujirushi 0:0672d41196db 29 *rst_n = 1;
matsujirushi 0:0672d41196db 30 wait_us(1);
matsujirushi 0:0672d41196db 31 }
matsujirushi 0:0672d41196db 32
matsujirushi 1:c2a5efba43bc 33 uint8_t arg[2];
matsujirushi 1:c2a5efba43bc 34 switch (func) {
matsujirushi 1:c2a5efba43bc 35 case FUNCTION_FM:
matsujirushi 1:c2a5efba43bc 36 arg[0] = 0x10; // FM Receive
matsujirushi 1:c2a5efba43bc 37 arg[1] = 0x05; // Analog Out
matsujirushi 1:c2a5efba43bc 38 break;
matsujirushi 1:c2a5efba43bc 39 case FUNCTION_AM:
matsujirushi 1:c2a5efba43bc 40 arg[0] = 0x11; // AM/SW/LW Receive
matsujirushi 1:c2a5efba43bc 41 arg[1] = 0x05; // Analog Out
matsujirushi 1:c2a5efba43bc 42 break;
matsujirushi 1:c2a5efba43bc 43 }
matsujirushi 2:d0de9c9c66a8 44
matsujirushi 1:c2a5efba43bc 45 writeCmd(0x01, arg, sizeof (arg)); // POWER_UP
matsujirushi 2:d0de9c9c66a8 46 uint8_t status;
matsujirushi 2:d0de9c9c66a8 47 readRes(&status);
matsujirushi 1:c2a5efba43bc 48
matsujirushi 1:c2a5efba43bc 49 return true;
matsujirushi 0:0672d41196db 50 }
matsujirushi 0:0672d41196db 51
matsujirushi 3:4873fd430c38 52 bool MjSi47xx::setProperty(PropertyType property, uint16_t value)
matsujirushi 3:4873fd430c38 53 {
matsujirushi 3:4873fd430c38 54 const uint8_t arg[] = { 0x00, property / 0x100, property % 0x100, value / 0x100, value % 0x100, };
matsujirushi 3:4873fd430c38 55
matsujirushi 3:4873fd430c38 56 writeCmd(0x12, arg, sizeof (arg)); // SET_PROPERTY
matsujirushi 3:4873fd430c38 57 uint8_t status;
matsujirushi 3:4873fd430c38 58 readRes(&status);
matsujirushi 3:4873fd430c38 59
matsujirushi 3:4873fd430c38 60 return true;
matsujirushi 3:4873fd430c38 61 }
matsujirushi 3:4873fd430c38 62
matsujirushi 1:c2a5efba43bc 63 bool MjSi47xx::getIntStatus(bool* stcInt)
matsujirushi 0:0672d41196db 64 {
matsujirushi 1:c2a5efba43bc 65 if (stcInt == NULL) return false;
matsujirushi 1:c2a5efba43bc 66
matsujirushi 0:0672d41196db 67 writeCmd(0x14); // GET_INT_STATUS
matsujirushi 0:0672d41196db 68 uint8_t status;
matsujirushi 2:d0de9c9c66a8 69 readRes(&status);
matsujirushi 0:0672d41196db 70
matsujirushi 0:0672d41196db 71 if (stcInt != NULL) *stcInt = status & 0x01 ? true : false;
matsujirushi 1:c2a5efba43bc 72
matsujirushi 1:c2a5efba43bc 73 return true;
matsujirushi 0:0672d41196db 74 }
matsujirushi 0:0672d41196db 75
matsujirushi 1:c2a5efba43bc 76 bool MjSi47xx::fmTuneFrequency(float frequency)
matsujirushi 0:0672d41196db 77 {
matsujirushi 1:c2a5efba43bc 78 if (frequency < 64.0f || 108.0f < frequency) return false;
matsujirushi 1:c2a5efba43bc 79
matsujirushi 0:0672d41196db 80 int freqInt = (int)(frequency * 100.0f);
matsujirushi 0:0672d41196db 81 const uint8_t arg[] = { 0x00, freqInt / 0x100, freqInt % 0x100, 0x00, };
matsujirushi 2:d0de9c9c66a8 82
matsujirushi 0:0672d41196db 83 writeCmd(0x20, arg, sizeof (arg)); // FM_TUNE_FREQ
matsujirushi 2:d0de9c9c66a8 84 uint8_t status;
matsujirushi 2:d0de9c9c66a8 85 readRes(&status);
matsujirushi 1:c2a5efba43bc 86
matsujirushi 1:c2a5efba43bc 87 return true;
matsujirushi 0:0672d41196db 88 }
matsujirushi 0:0672d41196db 89
matsujirushi 1:c2a5efba43bc 90 bool MjSi47xx::fmTuneStatus(float* frequency, uint8_t* rssi, uint8_t* snr, uint8_t* multipath)
matsujirushi 0:0672d41196db 91 {
matsujirushi 2:d0de9c9c66a8 92 const uint8_t arg[] = { 0x01, };
matsujirushi 0:0672d41196db 93
matsujirushi 0:0672d41196db 94 writeCmd(0x22, arg, sizeof (arg)); // FM_TUNE_STATUS
matsujirushi 0:0672d41196db 95 uint8_t status;
matsujirushi 0:0672d41196db 96 uint8_t resp[7];
matsujirushi 0:0672d41196db 97 readRes(&status, resp, sizeof (resp));
matsujirushi 0:0672d41196db 98
matsujirushi 0:0672d41196db 99 if (frequency != NULL) *frequency = (float)((int)resp[1] * 0x100 + (int)resp[2]) / 100.0f;
matsujirushi 0:0672d41196db 100 if (rssi != NULL) *rssi = resp[3];
matsujirushi 0:0672d41196db 101 if (snr != NULL) *snr = resp[4];
matsujirushi 0:0672d41196db 102 if (multipath != NULL) *multipath = resp[5];
matsujirushi 1:c2a5efba43bc 103
matsujirushi 1:c2a5efba43bc 104 return true;
matsujirushi 1:c2a5efba43bc 105 }
matsujirushi 1:c2a5efba43bc 106
matsujirushi 1:c2a5efba43bc 107 bool MjSi47xx::amTuneFrequency(float frequency)
matsujirushi 1:c2a5efba43bc 108 {
matsujirushi 1:c2a5efba43bc 109 if (frequency < 149.0f || 23000.0f < frequency) return false;
matsujirushi 1:c2a5efba43bc 110
matsujirushi 1:c2a5efba43bc 111 int freqInt = (int)frequency;
matsujirushi 1:c2a5efba43bc 112 const uint8_t arg[] = { 0x00, freqInt / 0x100, freqInt % 0x100, 0x00, 0x00, };
matsujirushi 2:d0de9c9c66a8 113
matsujirushi 1:c2a5efba43bc 114 writeCmd(0x40, arg, sizeof (arg)); // AM_TUNE_FREQ
matsujirushi 2:d0de9c9c66a8 115 uint8_t status;
matsujirushi 2:d0de9c9c66a8 116 readRes(&status);
matsujirushi 1:c2a5efba43bc 117
matsujirushi 1:c2a5efba43bc 118 return true;
matsujirushi 1:c2a5efba43bc 119 }
matsujirushi 1:c2a5efba43bc 120
matsujirushi 1:c2a5efba43bc 121 bool MjSi47xx::amTuneStatus(float* frequency, uint8_t* rssi, uint8_t* snr)
matsujirushi 1:c2a5efba43bc 122 {
matsujirushi 1:c2a5efba43bc 123 const uint8_t arg[] = { 0x01, };
matsujirushi 1:c2a5efba43bc 124 writeCmd(0x42, arg, sizeof (arg)); // AM_TUNE_STATUS
matsujirushi 1:c2a5efba43bc 125 uint8_t status;
matsujirushi 1:c2a5efba43bc 126 uint8_t resp[7];
matsujirushi 1:c2a5efba43bc 127 readRes(&status, resp, sizeof (resp));
matsujirushi 1:c2a5efba43bc 128
matsujirushi 1:c2a5efba43bc 129 if (frequency != NULL) *frequency = (float)((int)resp[1] * 0x100 + (int)resp[2]);
matsujirushi 1:c2a5efba43bc 130 if (rssi != NULL) *rssi = resp[3];
matsujirushi 1:c2a5efba43bc 131 if (snr != NULL) *snr = resp[4];
matsujirushi 1:c2a5efba43bc 132
matsujirushi 1:c2a5efba43bc 133 return true;
matsujirushi 0:0672d41196db 134 }
matsujirushi 0:0672d41196db 135
matsujirushi 0:0672d41196db 136 void MjSi47xx::writeCmd(uint8_t cmd, const uint8_t* argv, size_t argc)
matsujirushi 0:0672d41196db 137 {
matsujirushi 0:0672d41196db 138 i2c->start();
matsujirushi 0:0672d41196db 139 i2c->write(address);
matsujirushi 0:0672d41196db 140 i2c->write(cmd);
matsujirushi 0:0672d41196db 141 while (argc--) {
matsujirushi 0:0672d41196db 142 i2c->write(*argv++);
matsujirushi 0:0672d41196db 143 }
matsujirushi 0:0672d41196db 144 i2c->stop();
matsujirushi 0:0672d41196db 145 }
matsujirushi 0:0672d41196db 146
matsujirushi 0:0672d41196db 147 void MjSi47xx::readRes(uint8_t* status, uint8_t *resv, size_t resc)
matsujirushi 0:0672d41196db 148 {
matsujirushi 2:d0de9c9c66a8 149 // Wait for CTS. (command has been accepted.)
matsujirushi 2:d0de9c9c66a8 150 do {
matsujirushi 2:d0de9c9c66a8 151 i2c->start();
matsujirushi 2:d0de9c9c66a8 152 i2c->write(address | 1);
matsujirushi 2:d0de9c9c66a8 153 *status = i2c->read(0);
matsujirushi 2:d0de9c9c66a8 154 i2c->stop();
matsujirushi 2:d0de9c9c66a8 155 } while (!(*status & 0x80));
matsujirushi 2:d0de9c9c66a8 156
matsujirushi 2:d0de9c9c66a8 157 // ERR?
matsujirushi 2:d0de9c9c66a8 158 if (*status & 0x40) {
matsujirushi 2:d0de9c9c66a8 159 if (resv != NULL && resc >= 1) {
matsujirushi 2:d0de9c9c66a8 160 memset(resv, 0, resc);
matsujirushi 2:d0de9c9c66a8 161 }
matsujirushi 2:d0de9c9c66a8 162 return;
matsujirushi 2:d0de9c9c66a8 163 }
matsujirushi 2:d0de9c9c66a8 164
matsujirushi 2:d0de9c9c66a8 165 // Receive response.
matsujirushi 0:0672d41196db 166 i2c->start();
matsujirushi 0:0672d41196db 167 i2c->write(address | 1);
matsujirushi 0:0672d41196db 168 *status = i2c->read(resc >= 1 ? 1 : 0);
matsujirushi 0:0672d41196db 169 while (resc--) {
matsujirushi 0:0672d41196db 170 *resv++ = i2c->read(resc >= 1 ? 1 : 0);
matsujirushi 0:0672d41196db 171 }
matsujirushi 0:0672d41196db 172 i2c->stop();
matsujirushi 0:0672d41196db 173 }
matsujirushi 0:0672d41196db 174
matsujirushi 3:4873fd430c38 175