From a5207b47644e8c198e8775eddd9d13c953623e3c Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Mon, 11 Mar 2024 10:53:11 +0100 Subject: [PATCH] 0.2.0 KT0803 --- libraries/KT0803/.github/FUNDING.yml | 2 +- .../KT0803/.github/workflows/arduino-lint.yml | 2 +- .../.github/workflows/arduino_test_runner.yml | 2 +- .../KT0803/.github/workflows/jsoncheck.yml | 2 +- libraries/KT0803/CHANGELOG.md | 13 + libraries/KT0803/LICENSE | 2 +- libraries/KT0803/README.md | 276 ++++++++++++++---- .../KT0803K_minimal/KT0803K_minimal.ino | 33 +++ .../KT0803K_presets/KT0803K_presets.ino | 50 ++++ .../KT0803K_setFrequency.ino | 39 +++ .../KT0803_minimal/KT0803_minimal.ino | 7 +- .../KT0803_setFrequency.ino | 38 +++ .../KT0803_sweep_2_seconds.ino | 37 +++ .../KT0803_up_down/KT0803_up_down.ino | 69 +++++ libraries/KT0803/keywords.txt | 2 +- libraries/KT0803/library.json | 6 +- libraries/KT0803/library.properties | 4 +- libraries/KT0803/src/KT0803.cpp | 108 +++++-- libraries/KT0803/src/KT0803.h | 33 ++- 19 files changed, 624 insertions(+), 101 deletions(-) create mode 100644 libraries/KT0803/examples/KT0803K_minimal/KT0803K_minimal.ino create mode 100644 libraries/KT0803/examples/KT0803K_presets/KT0803K_presets.ino create mode 100644 libraries/KT0803/examples/KT0803K_setFrequency/KT0803K_setFrequency.ino create mode 100644 libraries/KT0803/examples/KT0803_setFrequency/KT0803_setFrequency.ino create mode 100644 libraries/KT0803/examples/KT0803_sweep_2_seconds/KT0803_sweep_2_seconds.ino create mode 100644 libraries/KT0803/examples/KT0803_up_down/KT0803_up_down.ino diff --git a/libraries/KT0803/.github/FUNDING.yml b/libraries/KT0803/.github/FUNDING.yml index 90d9ab4c..554358c3 100644 --- a/libraries/KT0803/.github/FUNDING.yml +++ b/libraries/KT0803/.github/FUNDING.yml @@ -1,4 +1,4 @@ # These are supported funding model platforms github: RobTillaart - +custom: "https://www.paypal.me/robtillaart" diff --git a/libraries/KT0803/.github/workflows/arduino-lint.yml b/libraries/KT0803/.github/workflows/arduino-lint.yml index 8a26f14a..870a1769 100644 --- a/libraries/KT0803/.github/workflows/arduino-lint.yml +++ b/libraries/KT0803/.github/workflows/arduino-lint.yml @@ -6,7 +6,7 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: arduino/arduino-lint-action@v1 with: library-manager: update diff --git a/libraries/KT0803/.github/workflows/arduino_test_runner.yml b/libraries/KT0803/.github/workflows/arduino_test_runner.yml index fadfa904..5506eb6a 100644 --- a/libraries/KT0803/.github/workflows/arduino_test_runner.yml +++ b/libraries/KT0803/.github/workflows/arduino_test_runner.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: 2.6 diff --git a/libraries/KT0803/.github/workflows/jsoncheck.yml b/libraries/KT0803/.github/workflows/jsoncheck.yml index 37a11298..beb88295 100644 --- a/libraries/KT0803/.github/workflows/jsoncheck.yml +++ b/libraries/KT0803/.github/workflows/jsoncheck.yml @@ -10,7 +10,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: json-syntax-check uses: limitusus/json-syntax-check@v1 with: diff --git a/libraries/KT0803/CHANGELOG.md b/libraries/KT0803/CHANGELOG.md index c21f3700..06c21232 100644 --- a/libraries/KT0803/CHANGELOG.md +++ b/libraries/KT0803/CHANGELOG.md @@ -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/). +## [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 - initial version diff --git a/libraries/KT0803/LICENSE b/libraries/KT0803/LICENSE index 16ef1551..03053375 100644 --- a/libraries/KT0803/LICENSE +++ b/libraries/KT0803/LICENSE @@ -1,6 +1,6 @@ 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 of this software and associated documentation files (the "Software"), to deal diff --git a/libraries/KT0803/README.md b/libraries/KT0803/README.md index 52e32152..1751ef7b 100644 --- a/libraries/KT0803/README.md +++ b/libraries/KT0803/README.md @@ -12,10 +12,10 @@ # 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 and their range. @@ -25,26 +25,96 @@ device like the KT0803 in your projects, either hobby, commercial or otherwise. ## Description -This **experimental** library allows basic control of the KT0803 FM transmitter device. -It is written as I wanted to understand the possibilities and the interface of the device. +This **experimental** library allows basic control of the KT0803 and / or the KT0803K +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 -are not supported (yet) although they probably will work as they seem backwards compatible. +There are some newer, more capable, follow up devices like model K, L and M. +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. +``` + +----------+ + | 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 - 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/full-digital-fm-receiver-with-arduino-and-tea5767-52be37 - https://www.hackerstore.nl/Artikel/388 - +- https://en.wikipedia.org/wiki/FM_broadcasting ## 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" ``` -` #### Constructor -- **KT0803(uint8_t address, TwoWire \*wire = &Wire)** constructor, +- **KT0803(TwoWire \*wire = &Wire)** constructor, 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. +Default it sets the frequency to 90 MHz and **mutes the signal**. Returns true if deviceAddress is found on the bus, false otherwise. - **bool isConnected()** test to see if deviceAddress is found on the I2C-bus. #### Frequency -- **bool setFrequency(float frequency)** converts the frequency to call **setChannel()** -- **float getFrequency()** returns the current frequency, can be slightly different, -due to rounding math. -The return value if derived from **getChannel()** -- **bool setChannel(uint16_t channel)** sets the channel to broadcast on. -- **uint16_t getChannel()** returns the set channel. - - -#### PGA, RFGain +- **bool setFrequency(float MHz)** converts the frequency in MHz to +call **setChannel(channel)**. The value of channel is rounded off depending +on the resolution of the device. +Returns false if MHz is out of range or **setChannel()** fails. +- **float getFrequency()** returns the current frequency in MHz, can be slightly different +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. -Read datasheet. -- **bool setPGA(uint8_t pga)** -- **uint8_t getPGA()** +#### PGA -| pga | gain | -|:-----:|:-------:| +Read Datasheet. + +The KT0803K has a **PGA_LSB** (2 bits) setting, which allows setting the gain +with single (1) dB steps. This is not yet implemented in the library. + +- **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 | | 110 | 8dB | | 101 | 4dB | | 100 | 0dB | -| 000 | 0dB | +| 000 | 0dB | default | 001 | -4dB | | 010 | -8dB | | 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 -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()** +If some region is missing please let me know the details and I can add +a wrapper for it. - **void setEurope()** - **void setAustralia()** - **void setUSA()** - **void setJapan()** -- **bool setPHTCNST(bool on)** -- **bool getPHTCNST()** +- **bool setPHTCNST(bool on)** See table below. +- **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 Read datasheet. -- **bool setPilotToneAdjust(uint8_t mode)** // HIGH = 1 LOW = 0 +- **bool setPilotToneAdjust(uint8_t mode)** HIGH = 1 LOW = 0 - **uint8_t getPilotToneAdjust()** #### Mute -- **bool setMute(bool mute)** enables or disables the transmitting. -- **bool getMute()** returns the current state. +Default the device is not muted, but **begin()** will default mute it. +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 -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 @@ -139,39 +276,62 @@ The KT0803K/L/M devices might work as they seem backwards compatible. #### Must - improve documentation - - fill in gaps (TODO). - buy hardware - test and verify. -#### Should -- check validity/range parameters - - 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) +#### Should #### 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. - - caching all (allowed) registers in **begin()** 0.1.1 + - caching all (allowed) registers in **begin()** - 3 bytes for KT0803 - 12 bytes for KT0803K - cache frequency. - only writing is needed. -- need hardware to test. -- examples - - create frequency hopping device - - preset channels (eeprom?) - - send binary data over FM? -- investigate tea5767 FM receiver - - -#### Wont +- send binary data over FM? +- preset frequency array in .h file (hardcoded) +- enums for parameters - readability? ## Support diff --git a/libraries/KT0803/examples/KT0803K_minimal/KT0803K_minimal.ino b/libraries/KT0803/examples/KT0803K_minimal/KT0803K_minimal.ino new file mode 100644 index 00000000..2cbbd9d4 --- /dev/null +++ b/libraries/KT0803/examples/KT0803K_minimal/KT0803K_minimal.ino @@ -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 -- diff --git a/libraries/KT0803/examples/KT0803K_presets/KT0803K_presets.ino b/libraries/KT0803/examples/KT0803K_presets/KT0803K_presets.ino new file mode 100644 index 00000000..3efe7900 --- /dev/null +++ b/libraries/KT0803/examples/KT0803K_presets/KT0803K_presets.ino @@ -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 -- diff --git a/libraries/KT0803/examples/KT0803K_setFrequency/KT0803K_setFrequency.ino b/libraries/KT0803/examples/KT0803K_setFrequency/KT0803K_setFrequency.ino new file mode 100644 index 00000000..d382be7f --- /dev/null +++ b/libraries/KT0803/examples/KT0803K_setFrequency/KT0803K_setFrequency.ino @@ -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 -- diff --git a/libraries/KT0803/examples/KT0803_minimal/KT0803_minimal.ino b/libraries/KT0803/examples/KT0803_minimal/KT0803_minimal.ino index 811e01f6..9f1ec067 100644 --- a/libraries/KT0803/examples/KT0803_minimal/KT0803_minimal.ino +++ b/libraries/KT0803/examples/KT0803_minimal/KT0803_minimal.ino @@ -18,9 +18,11 @@ void setup() Serial.begin(115200); while(!Serial); + Wire.begin(); + FM_SEND.begin(); - - FM_SEND.setChannel(1000); + FM_SEND.setChannel(2000); // * 0.05 = 100.00 MHz + FM_SEND.setMute(false); } void loop() @@ -29,4 +31,3 @@ void loop() // -- END OF FILE -- - diff --git a/libraries/KT0803/examples/KT0803_setFrequency/KT0803_setFrequency.ino b/libraries/KT0803/examples/KT0803_setFrequency/KT0803_setFrequency.ino new file mode 100644 index 00000000..9d4f34e9 --- /dev/null +++ b/libraries/KT0803/examples/KT0803_setFrequency/KT0803_setFrequency.ino @@ -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 -- diff --git a/libraries/KT0803/examples/KT0803_sweep_2_seconds/KT0803_sweep_2_seconds.ino b/libraries/KT0803/examples/KT0803_sweep_2_seconds/KT0803_sweep_2_seconds.ino new file mode 100644 index 00000000..bdfe39b2 --- /dev/null +++ b/libraries/KT0803/examples/KT0803_sweep_2_seconds/KT0803_sweep_2_seconds.ino @@ -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 -- diff --git a/libraries/KT0803/examples/KT0803_up_down/KT0803_up_down.ino b/libraries/KT0803/examples/KT0803_up_down/KT0803_up_down.ino new file mode 100644 index 00000000..5433915b --- /dev/null +++ b/libraries/KT0803/examples/KT0803_up_down/KT0803_up_down.ino @@ -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 -- diff --git a/libraries/KT0803/keywords.txt b/libraries/KT0803/keywords.txt index d31ebda3..106c2319 100644 --- a/libraries/KT0803/keywords.txt +++ b/libraries/KT0803/keywords.txt @@ -3,10 +3,10 @@ # Data types (KEYWORD1) KT0803 KEYWORD1 +KT0803K KEYWORD1 # Methods and Functions (KEYWORD2) -# Common begin KEYWORD2 isConnected KEYWORD2 diff --git a/libraries/KT0803/library.json b/libraries/KT0803/library.json index 7a187618..c28b652e 100644 --- a/libraries/KT0803/library.json +++ b/libraries/KT0803/library.json @@ -1,7 +1,7 @@ { "name": "KT0803", - "keywords": "Broadcast, KT0803K, KT0803L, KT0803M", - "description": "Arduino library for the KT0803 FM transmitter.", + "keywords": "Broadcast, KT0803K, KT0803L, KT0803M, FM", + "description": "Arduino library for the KT0803 and KT0803K FM transmitter.", "authors": [ { @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/KT0803.git" }, - "version": "0.1.0", + "version": "0.2.0", "license": "MIT", "frameworks": "*", "platforms": "*", diff --git a/libraries/KT0803/library.properties b/libraries/KT0803/library.properties index 2236e268..be0976f0 100644 --- a/libraries/KT0803/library.properties +++ b/libraries/KT0803/library.properties @@ -1,8 +1,8 @@ name=KT0803 -version=0.1.0 +version=0.2.0 author=Rob Tillaart maintainer=Rob Tillaart -sentence=Arduino library for the KT0803 FM transmitter. +sentence=Arduino library for the KT0803 and KT0803K FM transmitter. paragraph=KT0803K, KT0803L, KT0803M category=Communication url=https://github.com/RobTillaart/KT0803 diff --git a/libraries/KT0803/src/KT0803.cpp b/libraries/KT0803/src/KT0803.cpp index bb96086d..900958ae 100644 --- a/libraries/KT0803/src/KT0803.cpp +++ b/libraries/KT0803/src/KT0803.cpp @@ -1,8 +1,8 @@ // // FILE: KT0803.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.0 -// PURPOSE: Arduino Library for KT0803 FM transmitter +// VERSION: 0.2.0 +// PURPOSE: Arduino Library for KT0803 and KT0803K FM transmitter. // 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() /////////////////////////////////////////////////////////// - - -bool KT0803::setFrequency(float frequency) +// +// 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() { return getChannel() * 0.05; } +// steps of 50 KHz. bool KT0803::setChannel(uint16_t channel) { - if (writeData(0x00, channel & 0xFF) == false) return false; - - uint8_t data = readData(0x01); - data &= 0xF8; // keep other bits - data |= (channel >> 8) & 0x07; + 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; + // 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); - - // 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) { + if (pga > 7) return false; uint8_t data = readData(0x01); data &= 0xC7; // keep other bits data |= (pga << 3); @@ -87,6 +100,7 @@ uint8_t KT0803::getPGA() 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; @@ -99,13 +113,13 @@ bool KT0803::setRFGain(uint8_t rfgain) data = readData(0x02) & 0xBF; data |= (rfgain & 0x08) << 3; writeData(0x02, data); - return true; // TODO add error handling. + return true; } 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(0x02) & 0x40) >> 3); // bit 3 return data; @@ -123,6 +137,11 @@ bool KT0803::setPHTCNST(bool on) return writeData(0x02, data); } + +/////////////////////////////////////////////////////////// +// +// MISC +// bool KT0803::getPHTCNST() { return (readData(0x02) & 0x01) > 0; @@ -131,6 +150,7 @@ bool KT0803::getPHTCNST() 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; @@ -147,6 +167,10 @@ uint8_t KT0803::getPilotToneAdjust() } +/////////////////////////////////////////////////////////// +// +// MUTE +// bool KT0803::setMute(bool mute) { uint8_t data = readData(0x02); @@ -165,8 +189,6 @@ bool KT0803::getMute() } - - /////////////////////////////////////////////////////////////////////// // // 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 -- diff --git a/libraries/KT0803/src/KT0803.h b/libraries/KT0803/src/KT0803.h index e92f95f5..ff1ee3a2 100644 --- a/libraries/KT0803/src/KT0803.h +++ b/libraries/KT0803/src/KT0803.h @@ -2,8 +2,8 @@ // // FILE: KT0803.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.0 -// PURPOSE: Arduino Library for KT0803 FM transmitter +// VERSION: 0.2.0 +// PURPOSE: Arduino Library for KT0803 and KT0803K FM transmitter // URL: https://github.com/RobTillaart/KT0803 @@ -11,7 +11,7 @@ #include "Wire.h" -#define KT0803_LIB_VERSION (F("0.1.0")) +#define KT0803_LIB_VERSION (F("0.2.0")) class KT0803 @@ -19,14 +19,14 @@ class KT0803 public: KT0803(TwoWire * wire = &Wire); - bool begin(); + bool begin(float freq = 90.0, bool mute = true); bool isConnected(); // FM FREQUENCY - bool setFrequency(float frequency); - float getFrequency(); - bool setChannel(uint16_t channel); + bool setFrequency(float MHz); + float getFrequency(); + bool setChannel(uint16_t channel); uint16_t getChannel(); @@ -42,7 +42,7 @@ public: // 011: -12dB uint8_t getPGA(); - bool setRFGain(uint8_t rfgain); + bool setRFGain(uint8_t rfgain); // 0-15 uint8_t getRFgain(); @@ -63,7 +63,7 @@ public: // MUTE software bool setMute(bool mute); // true == muted - bool getMute(); // isMuted(). + bool getMute(); // isMuted(). 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 --