Files

350 lines
6.8 KiB
C++
Raw Permalink Normal View History

2026-08-28 23:16:37 +08:00
//
// 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 --