Library for Silicon Labs Si47xx AM/FM receiver. I tested Si4730 and Si4735.
MjSi47xx.cpp@3:4873fd430c38, 2015-09-06 (annotated)
- 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?
User | Revision | Line number | New 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 |