KT0803 FM Transmitter initial commit

This commit is contained in:
Gábor Poczkodi 2024-10-11 17:25:41 +02:00
parent 7e16cda949
commit 74ca4e04bb
8 changed files with 910 additions and 0 deletions

View file

@ -219,6 +219,7 @@ esphome/components/json/* @OttoWinter
esphome/components/kamstrup_kmp/* @cfeenstra1024
esphome/components/key_collector/* @ssieb
esphome/components/key_provider/* @ssieb
esphome/components/kt0803/* @gabest11
esphome/components/kuntze/* @ssieb
esphome/components/lcd_menu/* @numo68
esphome/components/ld2410/* @regevbr @sebcaps

View file

@ -0,0 +1,86 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import automation
from esphome.components import i2c, sensor, text_sensor, binary_sensor
from esphome.const import (
CONF_ID,
CONF_FREQUENCY,
DEVICE_CLASS_POWER,
DEVICE_CLASS_EMPTY,
)
CODEOWNERS = ["@gabest11"]
DEPENDENCIES = ["i2c"]
AUTO_LOAD = ["sensor", "text_sensor", "binary_sensor", "number", "switch", "select", "text"]
MULTI_CONF = True
UNIT_MEGA_HERTZ = "MHz"
UNIT_KILO_HERTZ = "KHz"
UNIT_MILLI_VOLT = "mV"
UNIT_MICRO_AMPERE = "mA"
UNIT_DECIBEL_MICRO_VOLT = "dBµV"
ICON_VOLUME_MUTE = "mdi:volume-mute"
ICON_EAR_HEARING = "mdi:ear-hearing"
ICON_RADIO_TOWER = "mdi:radio-tower"
ICON_SLEEP = "mdi:sleep"
ICON_SINE_WAVE = "mdi:sine-wave"
ICON_RESISTOR = "mdi:resistor"
ICON_FORMAT_TEXT = "mdi:format-text"
kt0803_ns = cg.esphome_ns.namespace("kt0803")
KT0803Component = kt0803_ns.class_(
"KT0803Component", cg.PollingComponent, i2c.I2CDevice
)
CONF_KT0803_ID = "kt0803_id"
CONF_CHIP_ID = "chip_id"
CONF_PW_OK = "pw_ok"
CONF_SLNCID = "slncid"
SetFrequencyAction = kt0803_ns.class_(
"SetFrequencyAction", automation.Action, cg.Parented.template(KT0803Component)
)
ChipId = kt0803_ns.enum("ChipId", True)
CHIP_ID = {
"KT0803": ChipId.KT0803,
"KT0803K": ChipId.KT0803K,
"KT0803M": ChipId.KT0803M,
"KT0803L": ChipId.KT0803L,
}
CONFIG_SCHEMA = (
cv.Schema(
{
cv.GenerateID(): cv.declare_id(KT0803Component),
cv.Required(CONF_CHIP_ID): cv.enum(CHIP_ID),
cv.Optional(CONF_FREQUENCY, default=87.50): cv.float_range(70, 108),
cv.Optional(CONF_PW_OK): binary_sensor.binary_sensor_schema(
device_class=DEVICE_CLASS_POWER,
icon=ICON_RADIO_TOWER,
),
cv.Optional(CONF_SLNCID): binary_sensor.binary_sensor_schema(
device_class=DEVICE_CLASS_EMPTY,
icon=ICON_VOLUME_MUTE,
),
}
)
.extend(cv.polling_component_schema("60s"))
.extend(i2c.i2c_device_schema(0x3E))
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
await i2c.register_i2c_device(var, config)
cg.add(var.set_chip_id(config.get(CONF_CHIP_ID)))
if conf_frequency := config.get(CONF_FREQUENCY):
cg.add(var.set_frequency(conf_frequency))
if conf_pw_ok := config.get(CONF_PW_OK):
s = await binary_sensor.new_binary_sensor(conf_pw_ok)
cg.add(var.set_pw_ok_binary_sensor(s))
if conf_slncid := config.get(CONF_SLNCID):
s = await binary_sensor.new_binary_sensor(conf_slncid)
cg.add(var.set_slncid_binary_sensor(s))

View file

@ -0,0 +1,283 @@
#include "kt0803.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include <cstdio>
#include <cmath>
namespace esphome {
namespace kt0803 {
// TODO: std::clamp isn't here yet
#define clamp(v, lo, hi) std::max(std::min(v, hi), lo)
static const char *const TAG = "kt0803";
KT0803Component::KT0803Component() {
this->chip_id_ = ChipId::KT0803L;
this->reset_ = false;
memset(&this->state_, 0, sizeof(this->state_));
// set datasheet defaults, except frequency to 87.5MHz
this->state_.REG_00 = 0x6B;
this->state_.REG_01 = 0xC3;
this->state_.REG_02 = 0x40;
this->state_.REG_04 = 0x04;
this->state_.REG_0E = 0x02;
this->state_.REG_10 = 0xA8;
this->state_.REG_12 = 0x80;
this->state_.REG_13 = 0x80;
this->state_.REG_15 = 0xE0;
this->state_.REG_26 = 0xA0;
}
bool KT0803Component::check_reg_(uint8_t addr) {
switch (addr) { // check KT0803 address range
case 0x00:
case 0x01:
case 0x02:
case 0x13:
return true;
}
if (this->chip_id_ != ChipId::KT0803) {
switch (addr) { // check KT0803K/M address range too
case 0x00:
case 0x01:
case 0x02:
case 0x04:
case 0x0B:
case 0x0E:
case 0x0F:
case 0x10:
case 0x12:
case 0x14:
case 0x16:
return true;
}
}
if (this->chip_id_ == ChipId::KT0803L) {
switch (addr) { // check KT0803L address range too
case 0x17:
case 0x1E:
case 0x26:
case 0x27:
return true;
}
}
return false;
}
void KT0803Component::write_reg_(uint8_t addr) {
if (addr >= sizeof(this->regs_) || !this->check_reg_(addr)) {
ESP_LOGE(TAG, "write_reg_(0x%02X) invalid register address", addr);
return;
}
if (addr == 0x13 && this->state_.PA_CTRL == 1) {
ESP_LOGW(TAG, "write_reg_(0x%02X) PA_CTRL = 1 can destroy the device", addr);
return; // TODO: remove this when everything tested and works
}
if (this->reset_) {
uint8_t value = this->regs_[addr];
ESP_LOGV(TAG, "write_reg_(0x%02X) = 0x%02X", addr, value);
this->write_byte(addr, value);
} else {
if (this->get_component_state() & COMPONENT_STATE_LOOP) {
ESP_LOGE(TAG, "write_reg_(0x%02X) device was not reset", addr);
}
}
}
bool KT0803Component::read_reg_(uint8_t addr) {
if (addr >= sizeof(this->regs_) || !this->check_reg_(addr)) {
ESP_LOGE(TAG, "write_reg_(0x%02X) invalid register address", addr);
return false;
}
uint8_t c;
if (i2c::ERROR_OK == this->read_register(addr, &c, 1, false)) {
this->regs_[addr] = c;
return true;
}
ESP_LOGE(TAG, "read_reg_(0x%02X) cannot read register", addr);
return false;
}
// overrides
void KT0803Component::setup() {
/*
for (size_t addr = 0; addr < 0x2F; addr++) {
uint8_t c;
if (i2c::ERROR_OK == this->read_register(addr, &c, 1, false)) {
ESP_LOGV(TAG, "setup register[%02X]: %02X", addr, c);
}
}
*/
this->reset_ = true;
for (size_t addr = 0; addr < sizeof(this->state_); addr++) {
if (addr != 0x0F && this->check_reg_(addr)) {
this->write_reg_(addr);
}
}
this->publish_pw_ok();
this->publish_slncid();
this->publish_frequency();
}
void KT0803Component::dump_config() {
ESP_LOGCONFIG(TAG, "KT0803:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, "failed!");
}
ESP_LOGCONFIG(TAG, " Chip: %s", this->get_chip_string().c_str());
ESP_LOGCONFIG(TAG, " Frequency: %.2f MHz", this->get_frequency());
// TODO: ...and everything else...
LOG_UPDATE_INTERVAL(this);
}
void KT0803Component::update() {
if (this->read_reg_(0x0F)) {
this->publish_pw_ok();
this->publish_slncid();
}
/*
for (size_t addr = 0; addr < 0x2F; addr++) {
uint8_t c;
if (i2c::ERROR_OK == this->read_register(addr, &c, 1, false)) {
ESP_LOGV(TAG, "update register[%02X]: %02X", addr, c);
}
}
*/
}
void KT0803Component::loop() {
}
// config
void KT0803Component::set_chip_id(ChipId value) {
this->chip_id_ = value;
}
ChipId KT0803Component::get_chip_id() {
return this->chip_id_;
}
std::string KT0803Component::get_chip_string() const {
switch (this->chip_id_) {
case ChipId::KT0803:
return "KT0803";
case ChipId::KT0803K:
return "KT0803K";
case ChipId::KT0803M:
return "KT0803M";
case ChipId::KT0803L:
return "KT0803L";
default:
return "Unknown";
}
}
void KT0803Component::set_frequency(float value) {
if (!(CHSEL_MIN <= value && value <= CHSEL_MAX)) {
ESP_LOGE(TAG, "set_frequency(%.2f) invalid (%.2f - %.2f)", value, CHSEL_MIN, CHSEL_MAX);
return;
}
uint16_t ch = (uint16_t) std::lround(value * 20);
this->state_.CHSEL2 = (uint8_t) ((ch >> 9) & 0x07);
this->state_.CHSEL1 = (uint8_t) ((ch >> 1) & 0xff);
this->state_.CHSEL0 = (uint8_t) ((ch >> 0) & 0x01);
this->write_reg_(0x00);
this->write_reg_(0x01);
this->write_reg_(0x02);
this->publish_frequency();
}
float KT0803Component::get_frequency() {
uint16_t ch = 0;
ch |= (uint16_t) this->state_.CHSEL2 << 9;
ch |= (uint16_t) this->state_.CHSEL1 << 1;
if (this->chip_id_ != ChipId::KT0803) {
ch |= (uint16_t) this->state_.CHSEL0 << 0;
}
return (float) ch / 20;
}
// publish
void KT0803Component::publish_pw_ok() { this->publish(this->pw_ok_binary_sensor_, this->state_.PW_OK == 1); }
void KT0803Component::publish_slncid() { this->publish(this->slncid_binary_sensor_, this->state_.SLNCID == 1); }
void KT0803Component::publish_frequency() { this->publish(this->frequency_number_, this->get_frequency()); }
void KT0803Component::publish(text_sensor::TextSensor *s, const std::string &state) {
if (s != nullptr) {
if (!s->has_state() || s->state != state) {
s->publish_state(state);
}
}
}
void KT0803Component::publish(binary_sensor::BinarySensor *s, bool state) {
if (s != nullptr) {
if (!s->has_state() || s->state != state) {
s->publish_state(state);
}
}
}
void KT0803Component::publish(sensor::Sensor *s, float state) {
if (s != nullptr) {
if (!s->has_state() || s->state != state) {
s->publish_state(state);
}
}
}
void KT0803Component::publish(number::Number *n, float state) {
if (n != nullptr) {
if (!n->has_state() || n->state != state) {
n->publish_state(state);
}
}
}
void KT0803Component::publish(switch_::Switch *s, bool state) {
if (s != nullptr) {
if (s->state != state) { // ?
s->publish_state(state);
}
}
}
void KT0803Component::publish(select::Select *s, size_t index) {
if (s != nullptr) {
if (auto state = s->at(index)) {
if (!s->has_state() || s->state != *state) {
s->publish_state(*state);
}
}
}
}
void KT0803Component::publish(text::Text *t, const std::string &state) {
if (t != nullptr) {
if (!t->has_state() || t->state != state) {
t->publish_state(state);
}
}
}
} // namespace kt0803
} // namespace esphome

View file

@ -0,0 +1,74 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/automation.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/text_sensor/text_sensor.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/number/number.h"
#include "esphome/components/switch/switch.h"
#include "esphome/components/select/select.h"
#include "esphome/components/text/text.h"
#include <string>
#include "kt0803defs.h"
namespace esphome {
namespace kt0803 {
#ifndef SUB_TEXT
#define SUB_TEXT(name) \
protected: \
text::Text *name##_text_{nullptr}; \
\
public: \
void set_##name##_text(text::Text *text) { this->name##_text_ = text; }
#endif
class KT0803Component : public PollingComponent, public i2c::I2CDevice {
ChipId chip_id_; // no way to detect it
bool reset_;
union {
struct KT0803State state_;
uint8_t regs_[sizeof(struct KT0803State)];
};
bool check_reg_(uint8_t addr);
void write_reg_(uint8_t addr);
bool read_reg_(uint8_t addr);
SUB_BINARY_SENSOR(pw_ok)
SUB_BINARY_SENSOR(slncid)
SUB_NUMBER(frequency)
void publish_pw_ok();
void publish_slncid();
void publish_frequency();
void publish(sensor::Sensor *s, float state);
void publish(binary_sensor::BinarySensor *s, bool state);
void publish(text_sensor::TextSensor *s, const std::string &state);
void publish(number::Number *n, float state);
void publish(switch_::Switch *s, bool state);
void publish(select::Select *s, size_t index);
void publish(text::Text *t, const std::string &state);
public:
KT0803Component();
// float get_setup_priority() const override { return setup_priority::HARDWARE; }
void setup() override;
void dump_config() override;
void update() override;
void loop() override;
void set_chip_id(ChipId value);
ChipId get_chip_id();
std::string get_chip_string() const;
void set_frequency(float value); // MHz
float get_frequency();
};
} // namespace kt0803
} // namespace esphome

View file

@ -0,0 +1,398 @@
#pragma once
namespace esphome {
namespace kt0803 {
static float CHSEL_MIN = 70.0f;
static float CHSEL_MAX = 108.0f;
static float PGA_MIN = -15;
static float PGA_MAX = 12;
static float RFGAIN_MIN = 95.5f;
static float RFGAIN_MAX = 108.0f;
enum class ChipId {
KT0803,
KT0803K,
KT0803M,
KT0803L,
};
enum class PreEmphasis {
PHTCNST_50US,
PHTCNST_75US,
LAST,
};
enum class PilotToneAmplitudeAdjustment {
PLTADJ_LOW,
PLTADJ_HIGH,
LAST,
};
enum class BassBoostControl {
BASS_DISABLED,
BASS_5DB,
BASS_11DB,
BASS_17DB,
LAST,
};
enum class AlcTimeSelection {
ALC_TIME_25US,
ALC_TIME_50US,
ALC_TIME_75US,
ALC_TIME_100US,
ALC_TIME_125US,
ALC_TIME_150US,
ALC_TIME_175US,
ALC_TIME_200US,
ALC_TIME_50MS,
ALC_TIME_100MS,
ALC_TIME_150MS,
ALC_TIME_200MS,
ALC_TIME_250MS,
ALC_TIME_300MS,
ALC_TIME_350MS,
ALC_TIME_40MS,
LAST,
};
enum class SilenceDetectionLowThreshold {
SLNCTHL_025MV,
SLNCTHL_050MV,
SLNCTHL_1MV,
SLNCTHL_2MV,
SLNCTHL_4MV,
SLNCTHL_8MV,
SLNCTHL_16MV,
SLNCTHL_32MV,
LAST,
};
enum class SilenceDetectionHighThreshold {
SLNCTHH_050MV,
SLNCTHH_1MV,
SLNCTHH_2MV,
SLNCTHH_4MV,
SLNCTHH_8MV,
SLNCTHH_16MV,
SLNCTHH_32MV,
SLNCTHH_64MV,
LAST,
};
enum class SilenceDetectionHighLevelCounterThreshold {
SLNCCNTHIGH_15,
SLNCCNTHIGH_31,
SLNCCNTHIGH_63,
SLNCCNTHIGH_127,
SLNCCNTHIGH_255,
SLNCCNTHIGH_511,
SLNCCNTHIGH_1023,
SLNCCNTHIGH_2047,
LAST,
};
enum class SilenceDetectionLowAndHighLevelDurationTime {
SLNCTIME_50MS,
SLNCTIME_100MS,
SLNCTIME_200MS,
SLNCTIME_400MS,
SLNCTIME_1S,
SLNCTIME_2S,
SLNCTIME_4S,
SLNCTIME_8S,
SLNCTIME_16S,
SLNCTIME_24S,
SLNCTIME_32S,
SLNCTIME_40S,
SLNCTIME_48S,
SLNCTIME_56S,
SLNCTIME_60S,
SLNCTIME_64S,
LAST,
};
enum class AlcCompressedGainSetting {
ALCCMPGAIN_N6DB,
ALCCMPGAIN_N9DB,
ALCCMPGAIN_N12DB,
ALCCMPGAIN_N15DB,
ALCCMPGAIN_6DB,
ALCCMPGAIN_3DB,
ALCCMPGAIN_0DB,
ALCCMPGAIN_N3DB,
LAST,
};
enum class SilenceLowCounter {
SLNCCNTLOW_1,
SLNCCNTLOW_2,
SLNCCNTLOW_4,
SLNCCNTLOW_8,
SLNCCNTLOW_16,
SLNCCNTLOW_32,
SLNCCNTLOW_64,
SLNCCNTLOW_128,
LAST,
};
enum class FrequencyDeviationAdjustment {
FDEV_75KHZ,
FDEV_112K5HZ,
FDEV_150KHZ,
FDEV_187K5HZ,
LAST,
};
enum class XtalSelection {
XTAL_SEL_32K768HZ,
XTAL_SEL_7M6HZ,
LAST,
};
enum class ReferenceClockSelection {
REF_CLK_32K768HZ,
REF_CLK_6M5HZ,
REF_CLK_7M6HZ,
REF_CLK_12MHZ,
REF_CLK_13MHZ,
REF_CLK_15M2HZ,
REF_CLK_19M2HZ,
REF_CLK_24MHZ,
REF_CLK_26MHZ,
LAST,
};
enum class AlcHighThresholdSelection {
ALCHIGHTH_50MS,
ALCHIGHTH_100MS,
ALCHIGHTH_150MS,
ALCHIGHTH_200MS,
ALCHIGHTH_1S,
ALCHIGHTH_5S,
ALCHIGHTH_10S,
ALCHIGHTH_15S,
LAST,
};
enum class AlcHoldTimeSelection {
ALCHOLD_06,
ALCHOLD_05,
ALCHOLD_04,
ALCHOLD_03,
ALCHOLD_02,
ALCHOLD_01,
ALCHOLD_005,
ALCHOLD_001,
LAST,
};
enum class AlcLowThreshold {
ALCLOWTH_025,
ALCLOWTH_020,
ALCLOWTH_015,
ALCLOWTH_010,
ALCLOWTH_005,
ALCLOWTH_003,
ALCLOWTH_002,
ALCLOWTH_001,
ALCLOWTH_0005,
ALCLOWTH_0001,
ALCLOWTH_00005,
ALCLOWTH_00001,
LAST,
};
// 0 = KT0803
// K = KT0803K or KT0803M (not datasheet for M, it should be mostly the same as K)
// L = KT0803L
struct KT0803State {
union {
uint8_t REG_00;
struct {
uint8_t CHSEL1 : 8; // 0 K L
};
};
union {
uint8_t REG_01;
struct {
uint8_t CHSEL2 : 3; // 0 K L
uint8_t PGA : 3; // 0 K L
uint8_t RFGAIN0 : 2; // 0 K L
};
};
union {
uint8_t REG_02;
struct {
uint8_t PHTCNST : 1; // 0 K L
uint8_t _02_1 : 1;
uint8_t PLTADJ : 1; // 0 K L
uint8_t MUTE : 1; // 0 K L
uint8_t _02_2 : 2;
uint8_t RFGAIN2 : 1; // 0 K L
uint8_t CHSEL0 : 1; // K L (no LSB on 0, step size is only 100KHz)
};
};
uint8_t REG_03;
union {
uint8_t REG_04;
struct {
uint8_t BASS : 2; // K L
uint8_t FDEV_K : 2; // K
uint8_t PGA_LSB : 2; // K L
uint8_t MONO : 1; // K L
uint8_t ALC_EN : 1; // L
};
};
uint8_t REG_05;
uint8_t REG_06;
uint8_t REG_07;
uint8_t REG_08;
uint8_t REG_09;
uint8_t REG_0A;
union {
uint8_t REG_0B;
struct {
uint8_t _0B_1 : 2;
uint8_t AUTO_PADN : 1; // L
uint8_t _0B_2 : 2;
uint8_t PDPA : 1; // K L
uint8_t _0B_3 : 1;
uint8_t Standby : 1; // L
};
};
union {
uint8_t REG_0C;
struct {
uint8_t ALC_ATTACK_TIME : 4; // L
uint8_t ALC_DECAY_TIME : 4; // L
};
};
union {
uint8_t REG_0E;
struct {
uint8_t _0E_1 : 1;
uint8_t PA_BIAS : 1; // K L
uint8_t _0E_2 : 6;
};
};
union {
uint8_t REG_0F;
struct {
uint8_t _0F_1 : 2;
uint8_t SLNCID : 1; // K L (ro)
uint8_t _0F_2 : 1;
uint8_t PW_OK : 1; // K L (ro)
uint8_t _0F_3 : 3;
};
};
union {
uint8_t REG_10;
struct {
uint8_t PGAMOD : 1; // K L
uint8_t _10_1 : 2;
uint8_t LMTLVL : 2; // K
uint8_t _10_2 : 4;
};
};
uint8_t REG_11;
union {
uint8_t REG_12;
struct {
uint8_t SW_MOD : 1; // K L
uint8_t SLNCTHH : 3; // K L
uint8_t SLNCTHL : 3; // K L
uint8_t SLNCDIS : 1; // K L
};
};
union {
uint8_t REG_13;
struct {
uint8_t _13_1 : 2;
uint8_t PA_CTRL : 1; // 0 K L
uint8_t _13_2 : 4;
uint8_t RFGAIN1 : 1; // 0 K L
};
};
union {
uint8_t REG_14;
struct {
uint8_t SLNCTIME_MSB : 1; // L
uint8_t _14_1 : 1;
uint8_t SLNCCNTHIGH : 3; // K L
uint8_t SLNCTIME : 3; // K L
};
};
union {
uint8_t REG_15;
struct {
uint8_t _15_1 : 5;
uint8_t ALCCMPGAIN : 3; // L
};
};
union {
uint8_t REG_16;
struct {
uint8_t SLNCCNTLOW : 3; // K L
uint8_t _16_1 : 5;
};
};
union {
uint8_t REG_17;
struct {
uint8_t _17_1 : 3;
uint8_t XTAL_SEL : 1; // L
uint8_t _17_2 : 1;
uint8_t AU_ENHANCE : 1; // L
uint8_t FDEV_L : 1; // L
uint8_t _17_3 : 1;
};
};
uint8_t REG_18;
uint8_t REG_19;
uint8_t REG_1A;
uint8_t REG_1B;
uint8_t REG_1C;
uint8_t REG_1D;
union {
uint8_t REG_1E;
struct {
uint8_t _1E_1 : 1;
uint8_t REF_CLK : 3; // L
uint8_t _1E_2 : 1;
uint8_t XTALD : 1; // L
uint8_t DCLK : 1; // L
uint8_t _1E_3 : 1;
};
};
uint8_t REG_1F;
uint8_t REG_20;
uint8_t REG_21;
uint8_t REG_22;
uint8_t REG_23;
uint8_t REG_24;
uint8_t REG_25;
union {
uint8_t REG_26;
struct {
uint8_t _26_1 : 1;
uint8_t ALCHIGHTH : 3; // L
uint8_t _26_2 : 1;
uint8_t ALCHOLD : 3; // L
};
};
union {
uint8_t REG_27;
struct {
uint8_t ALCLOWTH : 4; // L
uint8_t _27_1 : 4;
};
};
};
} // namespace kt0803
} // namespace esphome

View file

@ -0,0 +1,38 @@
import esphome.codegen as cg
from esphome.components import number
import esphome.config_validation as cv
from esphome.const import (
CONF_FREQUENCY,
DEVICE_CLASS_FREQUENCY,
ENTITY_CATEGORY_CONFIG,
)
from .. import (
CONF_KT0803_ID,
KT0803Component,
kt0803_ns,
UNIT_MEGA_HERTZ,
)
FrequencyNumber = kt0803_ns.class_("FrequencyNumber", number.Number)
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(CONF_KT0803_ID): cv.use_id(KT0803Component),
cv.Optional(CONF_FREQUENCY): number.number_schema(
FrequencyNumber,
unit_of_measurement=UNIT_MEGA_HERTZ,
device_class=DEVICE_CLASS_FREQUENCY,
entity_category=ENTITY_CATEGORY_CONFIG,
),
}
)
async def to_code(config):
kt0803_component = await cg.get_variable(config[CONF_KT0803_ID])
if frequency_config := config.get(CONF_FREQUENCY):
n = await number.new_number(
frequency_config, min_value=70, max_value=108, step=0.05
)
await cg.register_parented(n, config[CONF_KT0803_ID])
cg.add(kt0803_component.set_frequency_number(n))

View file

@ -0,0 +1,12 @@
#include "frequency_number.h"
namespace esphome {
namespace kt0803 {
void FrequencyNumber::control(float value) {
this->publish_state(value);
this->parent_->set_frequency(value);
}
} // namespace kt0803
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/number/number.h"
#include "../kt0803.h"
namespace esphome {
namespace kt0803 {
class FrequencyNumber : public number::Number, public Parented<KT0803Component> {
public:
FrequencyNumber() = default;
protected:
void control(float value) override;
};
} // namespace kt0803
} // namespace esphome