// // FILE: KT0803.cpp // AUTHOR: Rob Tillaart // VERSION: 0.3.1 // PURPOSE: Arduino Library for KT0803 and KT0803K FM transmitter. // URL: https://github.com/RobTillaart/KT0803 #include "src/KT0803.h" // REGISTERS on page 7 datasheet KT0803::KT0803(TwoWire * wire) { _address = 0x3E; _wire = wire; } bool KT0803::begin(float freq, bool mute) { if (! isConnected()) return false; if (! setMute(mute)) return false; return setFrequency(freq); } bool KT0803::isConnected() { _wire->beginTransmission(_address); return (_wire->endTransmission() == 0); } /////////////////////////////////////////////////////////// // // FREQUENCY // bool KT0803::setFrequency(float MHz) { if ((MHz < 70) || (MHz > 108)) return false; // steps 50 KHz although KT0803 will truncate to 100 KHz. return setChannel(round(MHz * 20)); } // MHz float KT0803::getFrequency() { return getChannel() * 0.05; } // steps of 50 KHz. bool KT0803::setChannel(uint16_t channel) { if ((channel < 1400) || (channel > 2160)) return false; // need to split over 3 registers // register 2 part skipped (always 0) for KT0803 uint16_t ch = channel >> 1; uint8_t register0 = ch & 0xFF; // CHSEL[8:1] if (writeData(0x00, register0) == false) return false; ch >>= 8; uint8_t register1 = readData(0x01); register1 &= 0xF8; // CHSEL[11:9] register1 |= (ch & 0x07); // CHSEL[11:9] return writeData(0x01, register1); } uint16_t KT0803::getChannel() { uint16_t channel = readData(0x01) & 0x07; channel <<= 8; channel |= readData(0x00); channel <<= 1; return channel; } /////////////////////////////////////////////////////////// // // GAIN // bool KT0803::setPGA(uint8_t pga) { if (pga > 7) return false; uint8_t data = readData(0x01); data &= 0xC7; // keep other bits data |= (pga << 3); return writeData(0x01, data); } uint8_t KT0803::getPGA() { return (readData(0x01) >> 3) & 0x07; } bool KT0803::setRFGain(uint8_t rfgain) { if (rfgain > 15) return false; // bits 0 and 1 uint8_t data = readData(0x01) & 0x3F; data |= (rfgain & 0x03) << 6; writeData(0x01, data); // bit 2 data = readData(0x13) & 0x7F; data |= (rfgain & 0x04) << 5; writeData(0x13, data); // bit 3 data = readData(0x02) & 0xBF; data |= (rfgain & 0x08) << 3; writeData(0x02, data); return true; } uint8_t KT0803::getRFgain() { uint8_t data = readData(0x01) >> 6; // bit 0, 1 data |= ((readData(0x13) & 0x80) >> 5); // bit 2 data |= ((readData(0x02) & 0x40) >> 3); // bit 3 return data; } bool KT0803::setPHTCNST(bool on) { uint8_t data = readData(0x02); // is the bit already OK if ((on == true) && (data & 0x01) == 0x01) return true; if ((on == false) && (data & 0x01) == 0x00) return true; // otherwise flip the bit data = data ^ 0x01; return writeData(0x02, data); } /////////////////////////////////////////////////////////// // // MISC // bool KT0803::getPHTCNST() { return (readData(0x02) & 0x01) > 0; } bool KT0803::setPilotToneAdjust(uint8_t mode) { if (mode > 1) return false; uint8_t data = readData(0x02); // is the bit already OK if ((mode == 1) && (data & 0x04) == 0x04) return true; if ((mode == 0) && (data & 0x04) == 0x00) return true; // otherwise flip the bit data = data ^ 0x04; return writeData(0x02, data); } uint8_t KT0803::getPilotToneAdjust() { return (readData(0x02) & 0x04) > 0; } /////////////////////////////////////////////////////////// // // MUTE // bool KT0803::setMute(bool mute) { uint8_t data = readData(0x02); // is the bit already OK if ((mute == true) && (data & 0x08) == 0x08) return true; if ((mute == false) && (data & 0x08) == 0x00) return true; // otherwise flip the bit data = data ^ 0x08; return writeData(0x02, data); } bool KT0803::getMute() { return (readData(0x02) & 0x08) > 0; } /////////////////////////////////////////////////////////////////////// // // PROTECTED // bool KT0803::writeData(uint8_t reg, uint8_t data) { _wire->beginTransmission(_address); _wire->write(reg); _wire->write(data); return (_wire->endTransmission() == 0); } int KT0803::readData(uint8_t reg) { _wire->beginTransmission(_address); _wire->write(reg); _wire->endTransmission(false); // explicit no STOP fig 3 page 4 if (_wire->requestFrom(_address, (uint8_t) 1) == 1) { uint8_t data = _wire->read(); return data; } return -1; } ///////////////////////////////////////////////////////////////////////////// // // DERIVED CLASS KT0803K // KT0803K::KT0803K(TwoWire * wire) : KT0803(wire) { } bool KT0803K::setChannel(uint16_t channel) { if ((channel < 1400) || (channel > 2160)) return false; // need to split over 3 registers uint16_t ch = channel; uint8_t register2 = readData(0x02) & 0x7F; register2 |= (channel & 0x01) << 7; // CHSEL[0] if (writeData(0x02, register2) == false) return false; ch >>= 1; uint8_t register0 = ch & 0xFF; // CHSEL[8:1] if (writeData(0x00, register0) == false) return false; ch >>= 8; uint8_t register1 = readData(0x01); register1 &= 0xF8; // CHSEL[11:9] register1 |= (ch & 0x07); // CHSEL[11:9] return writeData(0x01, register1); } uint16_t KT0803K::getChannel() { uint16_t channel = readData(0x01) & 0x07; channel <<= 8; channel |= readData(0x00); channel <<= 1; channel |= (readData(0x02) >> 7); return channel; } /////////////////////////////////////////////////////////// // // KT0803K SPECIFIC // bool KT0803K::setMono() { uint8_t register4 = readData(0x04); if (register4 & (1 << 6)) { register4 &= ~(1 << 6); return writeData(0x04, register4); } return true; } bool KT0803K::setStereo() { uint8_t register4 = readData(0x04); if ((register4 & (1 << 6)) == 0) { register4 |= (1 << 6); return writeData(0x04, register4); } return true; } bool KT0803K::isStereo() { uint8_t register4 = readData(0x04); return (register4 & (1 << 6)); } bool KT0803K::setBass(uint8_t bass) // 0..3 = 0, 5, 11, 17 dB { if (bass > 3) return false; uint8_t register4 = readData(0x04); register4 &= ~0x03; // mask off bits register4 |= bass; return writeData(0x04, register4); } uint8_t KT0803K::getBass() { uint8_t register4 = readData(0x04); return register4 & 0x03; } bool KT0803K::powerOK() { uint8_t register0F = readData(0x0F); return (register0F & (1 << 4)) > 0; } bool KT0803K::silenceDetected() { uint8_t register0F = readData(0x0F); return (register0F & (1 << 2)) > 0; } ///////////////////////////////////////////////////////////////////////////// // // DERIVED CLASS KT0803L // KT0803L::KT0803L(TwoWire * wire) : KT0803K(wire) { } ///////////////////////////////////////////////////////////////////////////// // // DERIVED CLASS KT0803M // KT0803M::KT0803M(TwoWire * wire) : KT0803K(wire) { } // -- END OF FILE --