0.2.0 KT0803

This commit is contained in:
Rob Tillaart 2024-03-11 10:53:11 +01:00
parent 4fccafce21
commit a5207b4764
19 changed files with 624 additions and 101 deletions

View File

@ -1,4 +1,4 @@
# These are supported funding model platforms # These are supported funding model platforms
github: RobTillaart github: RobTillaart
custom: "https://www.paypal.me/robtillaart"

View File

@ -6,7 +6,7 @@ jobs:
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: arduino/arduino-lint-action@v1 - uses: arduino/arduino-lint-action@v1
with: with:
library-manager: update library-manager: update

View File

@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@v1
with: with:
ruby-version: 2.6 ruby-version: 2.6

View File

@ -10,7 +10,7 @@ jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: json-syntax-check - name: json-syntax-check
uses: limitusus/json-syntax-check@v1 uses: limitusus/json-syntax-check@v1
with: with:

View File

@ -6,5 +6,18 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/). and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.2.0] - 2024-03-09
- Fix #2 frequency to channel formula
- add derived **class KT0803K**
- add examples
- add parameter checks functions.
- add default frequency + mute to **begin()**
- update documentation
- update GitHub actions
- minor edits
----
## [0.1.0] - 2023-12-27 ## [0.1.0] - 2023-12-27
- initial version - initial version

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2023-2023 Rob Tillaart Copyright (c) 2023-2024 Rob Tillaart
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -12,10 +12,10 @@
# KT0803 # KT0803
Arduino Library for KT0803 FM transmitter. Arduino Library for KT0803 and KT0803K FM transmitter.
## Legal point of attention ### Legal point of attention
In different countries there are different laws with respect to using transmitting devices In different countries there are different laws with respect to using transmitting devices
and their range. and their range.
@ -25,26 +25,96 @@ device like the KT0803 in your projects, either hobby, commercial or otherwise.
## Description ## Description
This **experimental** library allows basic control of the KT0803 FM transmitter device. This **experimental** library allows basic control of the KT0803 and / or the KT0803K
It is written as I wanted to understand the possibilities and the interface of the device. FM transmitter device.
It is primary written to understand the possibilities and the interface of the device.
The library is not tested yet with hardware. (see future). The library is not tested by me with hardware yet. See future below.
There are some newer, more capable, follow up devices like model K, L and M however these There are some newer, more capable, follow up devices like model K, L and M.
are not supported (yet) although they probably will work as they seem backwards compatible. From these only the KT0803K is supported since 0.2.0.
The others are not supported (yet) although they might work as they seem backwards compatible.
#### Warning
#### Hardware
Read datasheet for details.
**Warning**
The KT0803 is an 3.3 Volt device and cannot be connected directly to 5V MCU's. The KT0803 is an 3.3 Volt device and cannot be connected directly to 5V MCU's.
```
+----------+
| KT0803 |
GND --| 1 16 |-- PA_OUT RF analog output
Crystal XI --| 2 15 |-- GND
Crystal XO --| 3 14 |-- SCL I2C Clock
3.3V IOVDD --| 4 13 |-- SCA I2C Data
GND --| 5 12 |-- GND
in left INL --| 6 11 |-- GND
in right INR --| 7 10 |-- RSTB Reset
enable SW --| 8 9 |-- GND
| |
+----------+
```
#### Frequency range
The frequency range stated on the front page of the datasheet ==> 70 MHz - 108 MHz.
The frequency range stated in table 2 ==> 76 MHz - 108 MHz.
So the datasheet is at least ambiguous on this point.
Also keep in mind that the
#### Differences
The KT0803K device has far more options, which are not implemented yet except one.
The resolution or step-size of the frequency.
| device | step-size | Notes |
|:---------:|:-----------:|:--------|
| KT0803 | 100 KHz | in code the math is done with 50 KHz
| KT0803K | 50 KHz |
Backwards compatible.
According to the datasheet code for the KT0803 should work for the KT0803K.
Code with the KT0803K class will probably not work on a KT0803.
#### Transmit frequency
The transmit frequency can be set with **setFrequency(MHz)** or by **setChannel(channel)**.
Note that the channel and frequency math of the KT0803 and the KT0803K is aligned
in this library. This allows exchange of channel data between device types.
Note that the KT0803 will internally round to use 100 KHz steps.
Some examples:
| Frequency | Channel | Notes |
|:------------:|:---------:|:-------:|
| 70.00 MHz | 1400 | channel = freq (Mhz) \* 20
| 70.05 MHz | 1401 | freq = channel \* 0.05
| 70.10 MHz | 1402 |
| 76.00 MHz | 1520 |
| 80.00 MHz | 1600 |
| 89.70 MHz | 1794 | default (see registers datasheet)
| 100.00 MHz | 2000 |
| 101.30 MHz | 2026 |
| 105.70 MHz | 2114 |
| 108.00 MHz | 2160 |
#### Related #### Related
- https://github.com/RobTillaart/KT0803 - https://github.com/RobTillaart/KT0803
- https://www.hackster.io/hesam-moshiri/stereo-digital-fm-transmitter-circuit-arduino-code-2dbd8d - https://www.hackster.io/hesam-moshiri/stereo-digital-fm-transmitter-circuit-arduino-code-2dbd8d
- https://www.hackster.io/hesam-moshiri/full-digital-fm-receiver-with-arduino-and-tea5767-52be37 - https://www.hackster.io/hesam-moshiri/full-digital-fm-receiver-with-arduino-and-tea5767-52be37
- https://www.hackerstore.nl/Artikel/388 - https://www.hackerstore.nl/Artikel/388
- https://en.wikipedia.org/wiki/FM_broadcasting
## Interface ## Interface
@ -53,85 +123,152 @@ The KT0803 is an 3.3 Volt device and cannot be connected directly to 5V MCU's.
#include "KT0803.h" #include "KT0803.h"
``` ```
`
#### Constructor #### Constructor
- **KT0803(uint8_t address, TwoWire \*wire = &Wire)** constructor, - **KT0803(TwoWire \*wire = &Wire)** constructor,
optional Wire interface. optional Wire interface.
- **bool begin()** initializes the library. - **KT0803K(TwoWire \*wire = &Wire)** constructor,
optional Wire interface.
- **bool begin(float freq = 90.0, bool mute = true)** initializes the library.
Furthermore it checks if the deviceAddress is available on the I2C bus. Furthermore it checks if the deviceAddress is available on the I2C bus.
Default it sets the frequency to 90 MHz and **mutes the signal**.
Returns true if deviceAddress is found on the bus, false otherwise. Returns true if deviceAddress is found on the bus, false otherwise.
- **bool isConnected()** test to see if deviceAddress is found on the I2C-bus. - **bool isConnected()** test to see if deviceAddress is found on the I2C-bus.
#### Frequency #### Frequency
- **bool setFrequency(float frequency)** converts the frequency to call **setChannel()** - **bool setFrequency(float MHz)** converts the frequency in MHz to
- **float getFrequency()** returns the current frequency, can be slightly different, call **setChannel(channel)**. The value of channel is rounded off depending
due to rounding math. on the resolution of the device.
The return value if derived from **getChannel()** Returns false if MHz is out of range or **setChannel()** fails.
- **bool setChannel(uint16_t channel)** sets the channel to broadcast on. - **float getFrequency()** returns the current frequency in MHz, can be slightly different
- **uint16_t getChannel()** returns the set channel. from the set value due to rounding math mentioned above.
The return value is derived from a call to **getChannel()**
- **bool setChannel(uint16_t channel)** writes the channel to broadcast on to the device.
This involves two or three writes to different device registers.
- **uint16_t getChannel()** reads the selected channel from the device and
returns it.
#### PGA, RFGain #### PGA
Read datasheet. Read Datasheet.
- **bool setPGA(uint8_t pga)** The KT0803K has a **PGA_LSB** (2 bits) setting, which allows setting the gain
- **uint8_t getPGA()** with single (1) dB steps. This is not yet implemented in the library.
| pga | gain | - **bool setPGA(uint8_t pga)** sets gain according to table below.
|:-----:|:-------:| Returns false if pga is out of range (0..7).
- **uint8_t getPGA()** returns 0..7, default 0.
| PGA | gain | notes |
|:-----:|:-------:|:-------:|
| 111 | 12dB | | 111 | 12dB |
| 110 | 8dB | | 110 | 8dB |
| 101 | 4dB | | 101 | 4dB |
| 100 | 0dB | | 100 | 0dB |
| 000 | 0dB | | 000 | 0dB | default
| 001 | -4dB | | 001 | -4dB |
| 010 | -8dB | | 010 | -8dB |
| 011 | -12dB | | 011 | -12dB |
- **bool setRFGain(uint8_t rfgain);
- **uint8_t getRFgain();
TODO RFGAIN table #### RFGain
Read Datasheet.
Note: the RFGain value (4 bits) is distributed over three registers.
PA_BIAS (register 0x05) is only supported in the KT0803K device.
It is not yet supported in the library.
- **bool setRFGain(uint8_t rfgain)** sets rfgain according to table below.
Returns false if rfgain is out of range (0..15).
- **uint8_t getRFgain()** returns 0..15, default 15.
| RFGAIN | RFout | PA_BIAS = 1 | notes |
|:--------:|:------------:|:------------:|:-------:|
| 0000 | 95.5 dBuV | - |
| 0001 | 96.5 dBuV | - |
| 0010 | 97.5 dBuV | - |
| 0011 | 98.2 dBuV | - |
| 0100 | 98.9 dBuV | - |
| 0101 | 100.0 dBuV | - |
| 0110 | 101.5 dBuV | - |
| 0111 | 102.8 dBuV | - |
| 1000 | 105.1 dBuV | 107.2 dBuV |
| 1001 | 105.6 dBuV | 108.0 dBuV |
| 1010 | 106.2 dBuV | 108.7 dBuV |
| 1011 | 106.5 dBuV | 109.5 dBuV |
| 1100 | 107.0 dBuV | 110.3 dBuV |
| 1101 | 107.4 dBuV | 111.0 dBuV |
| 1110 | 107.7 dBuV | 111.7 dBuV |
| 1111 | 108.0 dBuV | 112.5 dBuV | default
#### Region selection #### Region selection
Read datasheet. Read datasheet for details.
Note that not all frequencies are allowed in all regions / countries!
The first four are convenience wrappers for **setPHTCNST()** The first four are convenience wrappers for **setPHTCNST()**
If some region is missing please let me know the details and I can add
a wrapper for it.
- **void setEurope()** - **void setEurope()**
- **void setAustralia()** - **void setAustralia()**
- **void setUSA()** - **void setUSA()**
- **void setJapan()** - **void setJapan()**
- **bool setPHTCNST(bool on)** - **bool setPHTCNST(bool on)** See table below.
- **bool getPHTCNST()** - **bool getPHTCNST()** returns set value.
If some region is missing please let me know and I can add it. | PHTCNST | time | Region |
|:---------:|:-------:|:--------:|
| 0 | 75 μs | USA, Japan, (default)
| 1 | 50 μs | Europe, Australia
#### PilotToneAdjust #### PilotToneAdjust
Read datasheet. Read datasheet.
- **bool setPilotToneAdjust(uint8_t mode)** // HIGH = 1 LOW = 0 - **bool setPilotToneAdjust(uint8_t mode)** HIGH = 1 LOW = 0
- **uint8_t getPilotToneAdjust()** - **uint8_t getPilotToneAdjust()**
#### Mute #### Mute
- **bool setMute(bool mute)** enables or disables the transmitting. Default the device is not muted, but **begin()** will default mute it.
- **bool getMute()** returns the current state. See interface section above.
- **bool setMute(bool mute)** enables or disables the transmitting
by muting the signal.
- **bool getMute()** returns the current state of muting.
## Preference channels
The device and library do not implement the persistant store of user
selectable preferences (frequencies or channels).
This can be implemented by the user in EEPROM or another persistent medium.
Think of a class that holds an array of channels and optional descriptions.
A minimal hardcoded preset sketch is in the examples.
## Derived classes ## Derived classes
The KT0803K/L/M devices might work as they seem backwards compatible. Since 0.2.0 the KT0803K class is created, although minimally implemented.
The KT0803L might work as it seems backwards compatible. It has far more
registers in use than the KT0803/K.
At the moment there is no intention to implement this KT0803L version.
The KT0803M looks almost identical to the KT0803K (no new registers), so
a derived class is straightforward.
## Future ## Future
@ -139,39 +276,62 @@ The KT0803K/L/M devices might work as they seem backwards compatible.
#### Must #### Must
- improve documentation - improve documentation
- fill in gaps (TODO).
- buy hardware - buy hardware
- test and verify. - test and verify.
#### Should
- check validity/range parameters #### Should
- enums for parameters - readability?
- investigate support
- KT0803K, KT0803L, KT0803M (derived classes)
- at startup
- mute device
- set 'dummy' channel
- preset channel array in .h file (hardcoded)
#### Could #### Could
- RESET pin as optional parameter in constructor?
- SW pin (ON/OFF) as optional parameter in constructor?
- add functions for sw on/off,
- what is impact on settings?
- call begin () again? => default
- explain well doc.
- derived class KT0803M (== K check)
- improve error handling
- unit tests possible?
- extend settings upon request **bold** are interesting, see table
| device | setting | register | Notes |
|:---------:|:-------------:|:---------------:|:--------|
| KT0803 | PA_CTRL | 13, bit 2 | **WARNING in datasheet**
| | | | Should it be added in API?
| KT0803K | MONO/STEREO | 04, bit 6 | **idem**
| KT0803K | PGA_LSB | 04, bit 4+5 | gain fine tuning -> see PGA_MOD
| KT0803K | FDEV | 04, bit 2+3 | Frequency deviation adjustment
| KT0803K | BASS | 04, bit 0+1 | **Bass boost control**
| KT0803K | PDPA | 0B, bit 5 | Power Amplifier Power Down ?
| KT0803K | PA_BIAS | 0E, bit 1 | PA bias current enhancement.
| KT0803K | PW_OK (RO) | 0F, bit 4 | **Power OK indicator**
| KT0803K | SLNCID (RO) | 0F, bit 2 | 1 when Silence is detected
| KT0803K | LMTLVL | 10, bit 3+4 | **Internal audio limiter level control**
| KT0803K | PGAMOD | 10, bit 0 | PGA mode selection (use PGA_LSB/ not)
| KT0803K | SLNCDIS | 12, bit 7 | Silence detection disable
| KT0803K | SLNCTHL | 12, bit 4+5+6 | Silence detection low threshold
| KT0803K | SLNCTHH | 12, bit 1+2+3 | Silence detection high threshold
| KT0803K | SW_MOD | 12, bit 0 | **Switching channel mode selection**
| KT0803K | SLNCTIME | 14, bit 5+6+7 | silence detection time
| KT0803K | SLNCCNTHIGH | 14, bit 2+3+4 | silence detection count high
| KT0803K | SLNCCNTLOW | 15, bit 0+1+2 | silence detection count low
#### Wont (for now)
- investigate tea5767 FM receiver (Out of scope for this lib).
- implement KT0803L
- investigate efficiency of register access. - investigate efficiency of register access.
- caching all (allowed) registers in **begin()** 0.1.1 - caching all (allowed) registers in **begin()**
- 3 bytes for KT0803 - 3 bytes for KT0803
- 12 bytes for KT0803K - 12 bytes for KT0803K
- cache frequency. - cache frequency.
- only writing is needed. - only writing is needed.
- need hardware to test. - send binary data over FM?
- examples - preset frequency array in .h file (hardcoded)
- create frequency hopping device - enums for parameters - readability?
- preset channels (eeprom?)
- send binary data over FM?
- investigate tea5767 FM receiver
#### Wont
## Support ## Support

View File

@ -0,0 +1,33 @@
//
// FILE: KT0803K_minimal.ino
// AUTHOR: Rob Tillaart
// PURPOSE: minimal demo
// URL: https://github.com/RobTillaart/KT0803
#include "Arduino.h"
#include "Wire.h"
#include "KT0803.h"
KT0803K FM_SEND;
void setup()
{
Serial.begin(115200);
while(!Serial);
Wire.begin();
FM_SEND.begin();
FM_SEND.setChannel(2000); // * 0.05 100.00 MHz
FM_SEND.setMute(false);
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,50 @@
//
// FILE: KT0803K_minimal.ino
// AUTHOR: Rob Tillaart
// PURPOSE: minimal demo hardcoded presets
// URL: https://github.com/RobTillaart/KT0803
#include "Arduino.h"
#include "Wire.h"
#include "KT0803.h"
KT0803K FM_SEND;
// hardcoded presets adjust to your need.
// note: presets by channel would take half the memory
float preset[10] =
{
88.6, 91.3, 92.2, 96.0, 97.3,
98.8, 100.1, 100.3, 105.4, 107.6
};
void setup()
{
Serial.begin(115200);
while (!Serial);
Wire.begin();
FM_SEND.begin(preset[0], false);
}
void loop()
{
if (Serial.available())
{
char c = Serial.read();
if (c == 'm') FM_SEND.setMute(false);
if (c == 'M') FM_SEND.setMute(true);
// select preset 0..9
int p = c - '0'; // convert to digit
if ((0 <= p) && (p <= 9)) FM_SEND.setFrequency(preset[p]);
}
}
// -- END OF FILE --

View File

@ -0,0 +1,39 @@
//
// FILE: KT0803_setFrequency.ino
// AUTHOR: Rob Tillaart
// PURPOSE: minimal demo
// URL: https://github.com/RobTillaart/KT0803
#include "Arduino.h"
#include "Wire.h"
#include "KT0803.h"
KT0803K FM_SEND;
void setup()
{
Serial.begin(115200);
while(!Serial);
Wire.begin();
FM_SEND.begin();
FM_SEND.setFrequency(105.75);
FM_SEND.setMute(false);
Serial.print("Freq: ");
Serial.println(FM_SEND.getFrequency());
Serial.print("Channel: ");
Serial.println(FM_SEND.getChannel());
}
void loop()
{
}
// -- END OF FILE --

View File

@ -18,9 +18,11 @@ void setup()
Serial.begin(115200); Serial.begin(115200);
while(!Serial); while(!Serial);
FM_SEND.begin(); Wire.begin();
FM_SEND.setChannel(1000); FM_SEND.begin();
FM_SEND.setChannel(2000); // * 0.05 = 100.00 MHz
FM_SEND.setMute(false);
} }
void loop() void loop()
@ -29,4 +31,3 @@ void loop()
// -- END OF FILE -- // -- END OF FILE --

View File

@ -0,0 +1,38 @@
//
// FILE: KT0803_setFrequency.ino
// AUTHOR: Rob Tillaart
// PURPOSE: minimal demo
// URL: https://github.com/RobTillaart/KT0803
#include "Arduino.h"
#include "Wire.h"
#include "KT0803.h"
KT0803 FM_SEND;
void setup()
{
Serial.begin(115200);
while(!Serial);
Wire.begin();
FM_SEND.begin();
FM_SEND.setFrequency(105.75);
FM_SEND.setMute(false);
Serial.print("Freq: ");
Serial.println(FM_SEND.getFrequency());
Serial.print("Channel: ");
Serial.println(FM_SEND.getChannel());
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,37 @@
//
// FILE: KT0803_sweep_2_seconds.ino
// AUTHOR: Rob Tillaart
// PURPOSE: minimal demo
// URL: https://github.com/RobTillaart/KT0803
#include "Arduino.h"
#include "Wire.h"
#include "KT0803.h"
KT0803 FM_SEND;
void setup()
{
Serial.begin(115200);
while(!Serial);
Wire.begin();
FM_SEND.begin();
FM_SEND.setMute(false);
}
void loop()
{
// adjust to your local allowed frequencies
for (float freq = 88.0; freq <= 108.0; freq += 0.1)
{
FM_SEND.setFrequency(freq);
delay(2000);
}
}
// -- END OF FILE --

View File

@ -0,0 +1,69 @@
//
// FILE: KT0803_up_down.ino
// AUTHOR: Rob Tillaart
// PURPOSE: minimal demo
// URL: https://github.com/RobTillaart/KT0803
#include "Arduino.h"
#include "Wire.h"
#include "KT0803.h"
KT0803 FM_SEND;
// connect two buttons to GND
// adjust pins to your needs,
uint8_t UP_PIN = 6;
uint8_t DOWN_PIN = 7;
float freq = 100.0;
float newFreq = 100.0;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(UP_PIN, INPUT_PULLUP);
pinMode(DOWN_PIN, INPUT_PULLUP);
Wire.begin();
FM_SEND.begin(freq, false);
}
void loop()
{
// adjust frequency with up and down button.
uint8_t u = digitalRead(UP_PIN);
uint8_t d = digitalRead(DOWN_PIN);
if ((u == 0) && (d == 0))
{
newFreq = 100.0;
}
else if (u == 0)
{
newFreq += 0.1;
if (newFreq > 108.0) newFreq = 108.0;
}
else if (d == 0)
{
newFreq -= 0.1;
if (newFreq < 88.0) newFreq = 88.0;
}
if (newFreq != freq)
{
freq = newFreq;
FM_SEND.setFrequency(freq);
Serial.print("Freq: ");
Serial.print(FM_SEND.getFrequency());
Serial.print("\t");
Serial.println(FM_SEND.getChannel());
delay(100);
}
}
// -- END OF FILE --

View File

@ -3,10 +3,10 @@
# Data types (KEYWORD1) # Data types (KEYWORD1)
KT0803 KEYWORD1 KT0803 KEYWORD1
KT0803K KEYWORD1
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)
# Common
begin KEYWORD2 begin KEYWORD2
isConnected KEYWORD2 isConnected KEYWORD2

View File

@ -1,7 +1,7 @@
{ {
"name": "KT0803", "name": "KT0803",
"keywords": "Broadcast, KT0803K, KT0803L, KT0803M", "keywords": "Broadcast, KT0803K, KT0803L, KT0803M, FM",
"description": "Arduino library for the KT0803 FM transmitter.", "description": "Arduino library for the KT0803 and KT0803K FM transmitter.",
"authors": "authors":
[ [
{ {
@ -15,7 +15,7 @@
"type": "git", "type": "git",
"url": "https://github.com/RobTillaart/KT0803.git" "url": "https://github.com/RobTillaart/KT0803.git"
}, },
"version": "0.1.0", "version": "0.2.0",
"license": "MIT", "license": "MIT",
"frameworks": "*", "frameworks": "*",
"platforms": "*", "platforms": "*",

View File

@ -1,8 +1,8 @@
name=KT0803 name=KT0803
version=0.1.0 version=0.2.0
author=Rob Tillaart <rob.tillaart@gmail.com> author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com> maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for the KT0803 FM transmitter. sentence=Arduino library for the KT0803 and KT0803K FM transmitter.
paragraph=KT0803K, KT0803L, KT0803M paragraph=KT0803K, KT0803L, KT0803M
category=Communication category=Communication
url=https://github.com/RobTillaart/KT0803 url=https://github.com/RobTillaart/KT0803

View File

@ -1,8 +1,8 @@
// //
// FILE: KT0803.cpp // FILE: KT0803.cpp
// AUTHOR: Rob Tillaart // AUTHOR: Rob Tillaart
// VERSION: 0.1.0 // VERSION: 0.2.0
// PURPOSE: Arduino Library for KT0803 FM transmitter // PURPOSE: Arduino Library for KT0803 and KT0803K FM transmitter.
// URL: https://github.com/RobTillaart/KT0803 // URL: https://github.com/RobTillaart/KT0803
@ -19,9 +19,11 @@ KT0803::KT0803(TwoWire * wire)
} }
bool KT0803::begin() bool KT0803::begin(float freq, bool mute)
{ {
return isConnected(); if (! isConnected()) return false;
if (! setMute(mute)) return false;
return setFrequency(freq);
} }
@ -33,31 +35,37 @@ bool KT0803::isConnected()
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
//
// FREQUENCY
bool KT0803::setFrequency(float frequency) //
bool KT0803::setFrequency(float MHz)
{ {
return setChannel(round(frequency * 20)); if ((MHz < 70) || (MHz > 108)) return false;
// steps 50 KHz
return setChannel(round(MHz * 20));
} }
// MHz
float KT0803::getFrequency() float KT0803::getFrequency()
{ {
return getChannel() * 0.05; return getChannel() * 0.05;
} }
// steps of 50 KHz.
bool KT0803::setChannel(uint16_t channel) bool KT0803::setChannel(uint16_t channel)
{ {
if (writeData(0x00, channel & 0xFF) == false) return false; if ((channel < 1400) || (channel > 2160)) return false;
// need to split over 3 registers
uint8_t data = readData(0x01); // register 2 part skipped (always 0) for KT0803
data &= 0xF8; // keep other bits uint16_t ch = channel >> 1;
data |= (channel >> 8) & 0x07; // register 0
if (writeData(0x00, ch & 0xFF) == false) return false;
// register 1
uint8_t data = readData(0x01) & 0xF8; // keep other bits
data |= ((ch >> 8) & 0x07);
return writeData(0x01, data); return writeData(0x01, data);
// Reg02 CHSEL[0] = 0 ==> 100 KHz accuracy.
// Reg02 CHSEL[0] = 1 ==> 50 KHz accuracy. // TODO KT0803K derived class
} }
@ -70,8 +78,13 @@ uint16_t KT0803::getChannel()
} }
///////////////////////////////////////////////////////////
//
// GAIN
//
bool KT0803::setPGA(uint8_t pga) bool KT0803::setPGA(uint8_t pga)
{ {
if (pga > 7) return false;
uint8_t data = readData(0x01); uint8_t data = readData(0x01);
data &= 0xC7; // keep other bits data &= 0xC7; // keep other bits
data |= (pga << 3); data |= (pga << 3);
@ -87,6 +100,7 @@ uint8_t KT0803::getPGA()
bool KT0803::setRFGain(uint8_t rfgain) bool KT0803::setRFGain(uint8_t rfgain)
{ {
if (rfgain > 15) return false;
// bits 0 and 1 // bits 0 and 1
uint8_t data = readData(0x01) & 0x3F; uint8_t data = readData(0x01) & 0x3F;
data |= (rfgain & 0x03) << 6; data |= (rfgain & 0x03) << 6;
@ -99,13 +113,13 @@ bool KT0803::setRFGain(uint8_t rfgain)
data = readData(0x02) & 0xBF; data = readData(0x02) & 0xBF;
data |= (rfgain & 0x08) << 3; data |= (rfgain & 0x08) << 3;
writeData(0x02, data); writeData(0x02, data);
return true; // TODO add error handling. return true;
} }
uint8_t KT0803::getRFgain() uint8_t KT0803::getRFgain()
{ {
uint8_t data = readData(0x01) >> 6; // bit 0, 1 uint8_t data = readData(0x01) >> 6; // bit 0, 1
data |= ((readData(0x13) & 0x80) >> 5); // bit 2 data |= ((readData(0x13) & 0x80) >> 5); // bit 2
data |= ((readData(0x02) & 0x40) >> 3); // bit 3 data |= ((readData(0x02) & 0x40) >> 3); // bit 3
return data; return data;
@ -123,6 +137,11 @@ bool KT0803::setPHTCNST(bool on)
return writeData(0x02, data); return writeData(0x02, data);
} }
///////////////////////////////////////////////////////////
//
// MISC
//
bool KT0803::getPHTCNST() bool KT0803::getPHTCNST()
{ {
return (readData(0x02) & 0x01) > 0; return (readData(0x02) & 0x01) > 0;
@ -131,6 +150,7 @@ bool KT0803::getPHTCNST()
bool KT0803::setPilotToneAdjust(uint8_t mode) bool KT0803::setPilotToneAdjust(uint8_t mode)
{ {
if (mode > 1) return false;
uint8_t data = readData(0x02); uint8_t data = readData(0x02);
// is the bit already OK // is the bit already OK
if ((mode == 1) && (data & 0x04) == 0x04) return true; if ((mode == 1) && (data & 0x04) == 0x04) return true;
@ -147,6 +167,10 @@ uint8_t KT0803::getPilotToneAdjust()
} }
///////////////////////////////////////////////////////////
//
// MUTE
//
bool KT0803::setMute(bool mute) bool KT0803::setMute(bool mute)
{ {
uint8_t data = readData(0x02); uint8_t data = readData(0x02);
@ -165,8 +189,6 @@ bool KT0803::getMute()
} }
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
// PROTECTED // PROTECTED
@ -195,5 +217,51 @@ int KT0803::readData(uint8_t reg)
} }
/////////////////////////////////////////////////////////////////////////////
//
// DERIVED CLASSES
//
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;
// register 2
uint8_t data = readData(0x02) & 0x7F;
data |= (channel & 0x01) << 8;
if (writeData(0x02, data) == false) return false;
ch >>= 1;
// register 0
if (writeData(0x00, ch & 0xFF) == false) return false;
// register 1
ch >>= 8;
data = readData(0x01);
data &= 0xF8; // keep other bits
data |= ch & 0x07;
return writeData(0x01, data);
}
uint16_t KT0803K::getChannel()
{
uint16_t channel = readData(0x01) & 0x07;
channel <<= 8;
channel |= readData(0x00);
channel <<= 1;
channel |= (readData(0x02) >> 0x07);
return channel;
}
///////////////////////////////////////////////////////////
//
// OTHER
//
// -- END OF FILE -- // -- END OF FILE --

View File

@ -2,8 +2,8 @@
// //
// FILE: KT0803.h // FILE: KT0803.h
// AUTHOR: Rob Tillaart // AUTHOR: Rob Tillaart
// VERSION: 0.1.0 // VERSION: 0.2.0
// PURPOSE: Arduino Library for KT0803 FM transmitter // PURPOSE: Arduino Library for KT0803 and KT0803K FM transmitter
// URL: https://github.com/RobTillaart/KT0803 // URL: https://github.com/RobTillaart/KT0803
@ -11,7 +11,7 @@
#include "Wire.h" #include "Wire.h"
#define KT0803_LIB_VERSION (F("0.1.0")) #define KT0803_LIB_VERSION (F("0.2.0"))
class KT0803 class KT0803
@ -19,14 +19,14 @@ class KT0803
public: public:
KT0803(TwoWire * wire = &Wire); KT0803(TwoWire * wire = &Wire);
bool begin(); bool begin(float freq = 90.0, bool mute = true);
bool isConnected(); bool isConnected();
// FM FREQUENCY // FM FREQUENCY
bool setFrequency(float frequency); bool setFrequency(float MHz);
float getFrequency(); float getFrequency();
bool setChannel(uint16_t channel); bool setChannel(uint16_t channel);
uint16_t getChannel(); uint16_t getChannel();
@ -42,7 +42,7 @@ public:
// 011: -12dB // 011: -12dB
uint8_t getPGA(); uint8_t getPGA();
bool setRFGain(uint8_t rfgain); bool setRFGain(uint8_t rfgain); // 0-15
uint8_t getRFgain(); uint8_t getRFgain();
@ -63,7 +63,7 @@ public:
// MUTE software // MUTE software
bool setMute(bool mute); // true == muted bool setMute(bool mute); // true == muted
bool getMute(); // isMuted(). bool getMute(); // isMuted().
protected: protected:
@ -76,5 +76,20 @@ protected:
}; };
/////////////////////////////////////////////////////////////////////////////
//
// DERIVED CLASSES
//
class KT0803K : public KT0803
{
public:
KT0803K(TwoWire * wire = &Wire);
// CHANNEL
bool setChannel(uint16_t channel);
uint16_t getChannel();
};
// -- END OF FILE -- // -- END OF FILE --