mbed version of the Adafruit Si4713 library (FM transmitter)
Dependents: Adafruit_Si4173_Demo Radio_Transmitter_Working
Adafruit_Si4713.cpp
- Committer:
- JLarkin
- Date:
- 2017-01-24
- Revision:
- 0:6643c5542090
File content as of revision 0:6643c5542090:
/*************************************************** This is a library for the Si4713 FM Radio Transmitter with RDS Designed specifically to work with the Si4713 breakout in the adafruit shop ----> https://www.adafruit.com/products/1958 These transmitters use I2C to communicate, plus reset pin. 3 pins are required to interface Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried/Ladyada for Adafruit Industries. BSD license, all text above must be included in any redistribution ****************************************************/ /*************************************************** Modified to work with ARM mbed by John M. Larkin January 2017 ******************************************************/ #include "Adafruit_Si4713.h" float dt = 0.1; // An extra delay between I2C commands is essential int min(int a, int b) { return a > b ? a:b; } Adafruit_Si4713::Adafruit_Si4713(I2C i2c, PinName resetpin, uint8_t addr):_i2c(i2c),_rst(resetpin) { _i2caddr = addr; } bool Adafruit_Si4713::begin() { reset(); powerUp(); // check for Si4713 if (getRev() != 13) return false; return true; } void Adafruit_Si4713::reset() { _rst = 1; wait(dt); _rst = 0; wait(dt); _rst = 1; } ////////////////////////////////////////////////////// void Adafruit_Si4713::setProperty(uint16_t property, uint16_t value) { _i2ccommand[0] = SI4710_CMD_SET_PROPERTY; _i2ccommand[1] = 0; _i2ccommand[2] = property >> 8; _i2ccommand[3] = property & 0xFF; _i2ccommand[4] = value >> 8; _i2ccommand[5] = value & 0xFF; sendCommand(6); #ifdef SI4713_CMD_DEBUG printf("Set Prop 0x%x = %d\r\n", property,value); #endif } void Adafruit_Si4713::sendCommand(uint8_t len) { #ifdef SI4713_CMD_DEBUG printf("\r\n*** Command:"); for (uint8_t i = 0; i<len; i++) printf(" 0x%x",_i2ccommand[i]); printf("\r\n"); #endif _i2c.write(_i2caddr, _i2ccommand, len,true); wait(dt); // Wait for status CTS bit char status = 0; while (! (status & SI4710_STATUS_CTS)) { status = _i2c.read(0); #ifdef SI4713_CMD_DEBUG printf("status: %x\r\n", status); #endif } _i2c.stop(); wait(dt); } void Adafruit_Si4713::tuneFM(uint16_t freqKHz) { _i2ccommand[0] = SI4710_CMD_TX_TUNE_FREQ; _i2ccommand[1] = 0; _i2ccommand[2] = freqKHz >> 8; _i2ccommand[3] = freqKHz; sendCommand(4); while ((getStatus() & 0x81) != 0x81) { wait(0.01); } } void Adafruit_Si4713::setTXpower(uint8_t pwr, uint8_t antcap) { _i2ccommand[0] = SI4710_CMD_TX_TUNE_POWER; _i2ccommand[1] = 0; _i2ccommand[2] = 0; _i2ccommand[3] = pwr; _i2ccommand[4] = antcap; sendCommand(5); } void Adafruit_Si4713::readASQ(void) { _i2ccommand[0] = SI4710_CMD_TX_ASQ_STATUS; _i2ccommand[1] = 0x1; sendCommand(2); char rawBytes[5]; _i2c.read(_i2caddr, rawBytes, 5); currASQ = rawBytes[1]; currInLevel = rawBytes[4]; } void Adafruit_Si4713::readTuneStatus(void) { _i2ccommand[0] = SI4710_CMD_TX_TUNE_STATUS; _i2ccommand[1] = 0x1; // INTACK sendCommand(2); char rawBytes[8]; _i2c.read(_i2caddr, rawBytes, 8); currFreq = ((uint16_t)rawBytes[2] << 8) | (uint16_t)rawBytes[3]; currdBuV = rawBytes[5]; currAntCap = rawBytes[6]; currNoiseLevel = rawBytes[7]; } void Adafruit_Si4713::readTuneMeasure(uint16_t freq) { // check freq is multiple of 50khz if (freq % 5 != 0) { freq -= (freq % 5); } _i2ccommand[0] = SI4710_CMD_TX_TUNE_MEASURE; _i2ccommand[1] = 0; _i2ccommand[2] = freq >> 8; _i2ccommand[3] = freq; _i2ccommand[4] = 0; sendCommand(5); while (getStatus() != 0x81) wait(0.01); } void Adafruit_Si4713::beginRDS(uint16_t programID) { // 66.25KHz (default is 68.25) setProperty(SI4713_PROP_TX_AUDIO_DEVIATION, 6625); // 2KHz (default) setProperty(SI4713_PROP_TX_RDS_DEVIATION, 200); // RDS IRQ setProperty(SI4713_PROP_TX_RDS_INTERRUPT_SOURCE, 0x0001); // program identifier setProperty(SI4713_PROP_TX_RDS_PI, programID); // 50% mix (default) setProperty(SI4713_PROP_TX_RDS_PS_MIX, 0x03); // RDSD0 & RDSMS (default) setProperty(SI4713_PROP_TX_RDS_PS_MISC, 0x1808); // 3 repeats (default) setProperty(SI4713_PROP_TX_RDS_PS_REPEAT_COUNT, 3); setProperty(SI4713_PROP_TX_RDS_MESSAGE_COUNT, 1); setProperty(SI4713_PROP_TX_RDS_PS_AF, 0xE0E0); // no AF setProperty(SI4713_PROP_TX_RDS_FIFO_SIZE, 0); setProperty(SI4713_PROP_TX_COMPONENT_ENABLE, 0x0007); } void Adafruit_Si4713::setRDSstation(char *s) { uint8_t i, len = strlen(s); uint8_t slots = (len+3) / 4; for (uint8_t i=0; i<slots; i++) { memset(_i2ccommand, ' ', 6); // clear it with ' ' memcpy(_i2ccommand+2, s, min(4, strlen(s))); s+=4; _i2ccommand[6] = 0; //Serial.print("Set slot #"); Serial.print(i); //char *slot = (char *)( _i2ccommand+2); //Serial.print(" to '"); Serial.print(slot); Serial.println("'"); _i2ccommand[0] = SI4710_CMD_TX_RDS_PS; _i2ccommand[1] = i; // slot # sendCommand(6); } } void Adafruit_Si4713::setRDSbuffer(char *s) { uint8_t i, len = strlen(s); uint8_t slots = (len+3) / 4; char slot[5]; for (uint8_t i=0; i<slots; i++) { memset(_i2ccommand, ' ', 8); // clear it with ' ' memcpy(_i2ccommand+4, s, min(4, strlen(s))); s+=4; _i2ccommand[8] = 0; //Serial.print("Set buff #"); Serial.print(i); //char *slot = (char *)( _i2ccommand+4); //Serial.print(" to '"); Serial.print(slot); Serial.println("'"); _i2ccommand[0] = SI4710_CMD_TX_RDS_BUFF; if (i == 0) _i2ccommand[1] = 0x06; else _i2ccommand[1] = 0x04; _i2ccommand[2] = 0x20; _i2ccommand[3] = i; sendCommand(8); } /* // set time _i2ccommand[0] = SI4710_CMD_TX_RDS_BUFF; _i2ccommand[1] = 0x84; _i2ccommand[2] = 0x40; // RTC _i2ccommand[3] = 01; _i2ccommand[4] = 0xA7; _i2ccommand[5] = 0x0B; _i2ccommand[6] = 0x2D; _i2ccommand[7] = 0x6C; sendCommand(8); Wire.requestFrom((uint8_t)_i2caddr, (uint8_t)6); Wire.read(); // status Serial.print("FIFO overflow: 0x"); Serial.println(Wire.read(), HEX); Serial.print("Circ avail: "); Serial.println(Wire.read()); Serial.print("Circ used: "); Serial.println(Wire.read()); Serial.print("FIFO avail: "); Serial.println(Wire.read()); Serial.print("FIFO used: "); Serial.println(Wire.read()); */ // enable! //Serial.println("Enable RDS"); setProperty(SI4713_PROP_TX_COMPONENT_ENABLE, 0x0007); // stereo, pilot+rds /* // wait till ready while (getStatus() != 0x80) { Serial.println(getStatus(), HEX); delay(100); } delay(500); _i2ccommand[0] = SI4710_CMD_TX_RDS_BUFF; _i2ccommand[1] = 0x01; // clear RDSINT _i2ccommand[2] = 0x0; _i2ccommand[3] = 0x0; _i2ccommand[4] = 0x0; _i2ccommand[5] = 0x0; _i2ccommand[6] = 0x0; _i2ccommand[7] = 0x0; sendCommand(8); // get reply! Wire.requestFrom((uint8_t)_i2caddr, (uint8_t)6); for (uint8_t x=0; x<7; x++) { Wire.read(); } */ /* or you can read the status Wire.read(); // status Serial.print("FIFO overflow: 0x"); Serial.println(Wire.read(), HEX); Serial.print("Circ avail: "); Serial.println(Wire.read()); Serial.print("Circ used: "); Serial.println(Wire.read()); Serial.print("FIFO avail: "); Serial.println(Wire.read()); Serial.print("FIFO used: "); Serial.println(Wire.read()); */ } uint8_t Adafruit_Si4713::getStatus(void) { _i2c.start(); _i2c.write(_i2caddr); _i2c.write(SI4710_CMD_GET_INT_STATUS); _i2c.stop(); uint8_t status; _i2c.start(); _i2c.write(_i2caddr|0x01); status = _i2c.read(0); _i2c.stop(); return status; } void Adafruit_Si4713::powerUp(void) { _i2ccommand[0] = SI4710_CMD_POWER_UP; _i2ccommand[1] = 0x12; // CTS interrupt disabled // GPO2 output disabled // Boot normally // xtal oscillator ENabled // FM transmit _i2ccommand[2] = 0x50; // analog input mode sendCommand(3); // configuration! see page 254 setProperty(SI4713_PROP_REFCLK_FREQ, 32768); // crystal is 32.768 setProperty(SI4713_PROP_TX_PREEMPHASIS, 0); // 74uS pre-emph (USA std) setProperty(SI4713_PROP_TX_ACOMP_GAIN, 10); // max gain? setProperty(SI4713_PROP_TX_ACOMP_ENABLE, 0x02); // turn on limiter, but no dynamic ranging //setProperty(SI4713_PROP_TX_ACOMP_ENABLE, 0x0); // turn on limiter and AGC } uint8_t Adafruit_Si4713::getRev(void) { _i2ccommand[0] = SI4710_CMD_GET_REV; _i2ccommand[1] = 0; sendCommand(2); char rawBytes[9]; _i2c.read(_i2caddr, rawBytes, 9); uint8_t pn = rawBytes[1]; uint16_t fw = ((uint16_t)rawBytes[2] << 8) | (uint16_t)rawBytes[3]; uint16_t patch = ((uint16_t)rawBytes[4] << 8) | (uint16_t)rawBytes[5]; uint16_t cmp = ((uint16_t)rawBytes[6] << 8) | (uint16_t)rawBytes[7]; uint8_t chiprev = rawBytes[8]; printf("Part #Si47%d - %x\r\n", pn, fw); printf("Patch 0x%x\r\n", patch); printf("Chip rev %d\r\n", chiprev); return pn; } void Adafruit_Si4713::setGPIOctrl(uint8_t x) { // Serial.println("GPIO direction"); _i2ccommand[0] = SI4710_CMD_GPO_CTL; _i2ccommand[1] = x; sendCommand(2); } void Adafruit_Si4713::setGPIO(uint8_t x) { //Serial.println("GPIO set"); _i2ccommand[0] = SI4710_CMD_GPO_SET; _i2ccommand[1] = x; sendCommand(2); } /// /* void Adafruit_Si4713::rdstest() { _i2ccommand[0] = SI4710_CMD_TX_RDS_BUFF; _i2ccommand[1] = 0x02; _i2ccommand[2] = 0; _i2ccommand[3] = 0; _i2ccommand[4] = 0; _i2ccommand[5] = 0; _i2ccommand[6] = 0; _i2ccommand[7] = 0; sendCommand(8); Wire.requestFrom((uint8_t)_i2caddr, (uint8_t)6); Wire.read(); // status Serial.print("FIFO overflow: 0x"); Serial.println(Wire.read(), HEX); Serial.print("Circ avail: "); Serial.println(Wire.read()); Serial.print("Circ used: "); Serial.println(Wire.read()); Serial.print("FIFO avail: "); Serial.println(Wire.read()); Serial.print("FIFO used: "); Serial.println(Wire.read()); _i2ccommand[0] = SI4710_CMD_TX_RDS_BUFF; _i2ccommand[1] = 0x04; _i2ccommand[2] = 0x20; _i2ccommand[3] = 0x00; _i2ccommand[4] = 0x54; _i2ccommand[5] = 0x65; _i2ccommand[6] = 0x73; _i2ccommand[7] = 0x74; sendCommand(8); Wire.requestFrom((uint8_t)_i2caddr, (uint8_t)6); Wire.read(); // status Serial.print("FIFO overflow: 0x"); Serial.println(Wire.read(), HEX); Serial.print("Circ avail: "); Serial.println(Wire.read()); Serial.print("Circ used: "); Serial.println(Wire.read()); Serial.print("FIFO avail: "); Serial.println(Wire.read()); Serial.print("FIFO used: "); Serial.println(Wire.read()); _i2ccommand[0] = SI4710_CMD_TX_RDS_BUFF; _i2ccommand[1] = 0x04; _i2ccommand[2] = 0x20; _i2ccommand[3] = 0x01; _i2ccommand[4] = 0xD0; _i2ccommand[5] = 0x00; _i2ccommand[6] = 0x00; _i2ccommand[7] = 0x00; sendCommand(8); Wire.requestFrom((uint8_t)_i2caddr, (uint8_t)6); Wire.read(); // status Serial.print("FIFO overflow: 0x"); Serial.println(Wire.read(), HEX); Serial.print("Circ avail: "); Serial.println(Wire.read()); Serial.print("Circ used: "); Serial.println(Wire.read()); Serial.print("FIFO avail: "); Serial.println(Wire.read()); Serial.print("FIFO used: "); Serial.println(Wire.read()); } */