config done

This commit is contained in:
Gábor Poczkodi 2024-10-16 17:38:00 +02:00
parent b695d1e804
commit 7bfbf72092
75 changed files with 2902 additions and 504 deletions

View file

@ -1,10 +1,11 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import automation, pins
from esphome.components import i2c, sensor, text_sensor
from esphome.components import i2c, sensor, binary_sensor, text_sensor
from esphome.const import (
CONF_ID,
CONF_FREQUENCY,
UNIT_DECIBEL,
UNIT_EMPTY,
DEVICE_CLASS_VOLTAGE,
STATE_CLASS_MEASUREMENT,
@ -22,6 +23,9 @@ UNIT_KILO_HERTZ = "kHz"
UNIT_MILLI_VOLT = "mV"
UNIT_MICRO_AMPERE = "mA"
UNIT_DECIBEL_MICRO_VOLT = "dBµV"
UNIT_PICO_FARAD = "pF"
UNIT_KILO_OHM = "kOhm"
UNIT_DECIBEL_FS = "dBfs"
ICON_VOLUME_MUTE = "mdi:volume-mute"
ICON_EAR_HEARING = "mdi:ear-hearing"
@ -38,59 +42,309 @@ Si4713Component = si4713_ns.class_(
CONF_SI4713_ID = "si4713_id"
CONF_RESET_PIN = "reset_pin"
CONF_FREQUENCY_DEVIATION = "frequency_deviation"
CONF_SECTION_TUNER = "tuner"
CONF_SECTION_ANALOG = "analog"
CONF_SECTION_DIGITAL = "digital"
CONF_SECTION_PILOT = "pilot"
CONF_SECTION_REFCLK = "refclk"
CONF_SECTION_COMPRESSOR = "compressor"
CONF_SECTION_LIMITER = "limiter"
CONF_SECTION_ASQ = "asq"
CONF_SECTION_RDS = "rds"
CONF_SECTION_OUTPUT = "output"
CONF_SECTION_SENSOR = "sensor"
# general config
CONF_OP_MODE = "op_mode"
CONF_MUTE = "mute"
CONF_MONO = "mono"
CONF_TX_ENABLE = "tx_enable"
CONF_TX_PILOT = "tx_pilot"
CONF_T1M_SEL = "t1m_sel"
CONF_PRIV_EN = "priv_en"
CONF_PRE_EMPHASIS = "pre_emphasis"
CONF_XTAL_SOURCE = "xtal_source"
CONF_XTAL_CURRENT = "xtal_current"
CONF_XTAL_FREQUENCY = "xtal_frequency"
CONF_INPUT_IMPEDANCE = "input_impedance"
CONF_INPUT_GAIN = "input_gain"
CONF_DIGITAL_GAIN = "digital_gain"
CONF_POWER_TARGET = "power_target"
CONF_RDS_ENABLE = "rds_enable"
CONF_RDS_FREQUENCY_DEVIATION = "rds_frequency_deviation"
CONF_RDS_STATION = "rds_station"
CONF_RDS_TEXT = "rds_text"
CONF_AUD_PK = "aud_pk"
CONF_FSM = "fsm"
# tuner
CONF_FREQUENCY = "frequency"
CONF_DEVIATION = "deviation"
CONF_POWER = "power"
CONF_ANTCAP = "antcap"
# analog
CONF_LEVEL = "level"
CONF_ATTENUATION = "attenuation"
# digital
CONF_SAMPLE_RATE = "sample_rate"
CONF_SAMPLE_BITS = "sample_bits"
CONF_CHANNELS = "channels"
CONF_MODE = "mode"
CONF_CLOCK_EDGE = "clock_edge"
# pilot
CONF_ENABLE = "enable"
CONF_FREQUENCY = "frequency"
CONF_DEVIATION = "deviation"
# refclk
CONF_FREQUENCY = "frequency"
CONF_SOURCE = "source"
CONF_PRESCALER = "prescaler"
# compressor
CONF_ENABLE = "enable"
CONF_THRESHOLD = "threshold"
CONF_ATTACK = "attack"
CONF_RELEASE = "release"
CONF_GAIN = "gain"
CONF_PRESET = "preset"
# limiter
CONF_ENABLE = "enable"
CONF_RELEASE_TIME = "release_time"
# asq
CONF_IALL = "iall"
CONF_IALH = "ialh"
CONF_OVERMOD = "overmod"
CONF_LEVEL_LOW = "level_low"
CONF_DURATION_LOW = "duration_low"
CONF_LEVEL_HIGH = "level_high"
CONF_DURATION_HIGH = "duration_high"
# rds
CONF_ENABLE = "enable"
CONF_DEVIATION = "deviation"
CONF_STATION = "station"
CONF_TEXT = "text"
# output
CONF_GPIO1="gpio1"
CONF_GPIO2="gpio2"
CONF_GPIO3="gpio3"
# sensor
CONF_CHIP_ID = "chip_id"
CONF_REG30 = "reg30"
CONF_READ_FREQUENCY = "frequency"
CONF_READ_POWER = "power"
CONF_READ_ANTCAP = "antcap"
CONF_READ_NOISE_LEVEL = "noise_level"
CONF_IALL = "iall"
CONF_IALH = "ialh"
CONF_OVERMOD = "overmod"
CONF_INLEVEL = "inlevel"
SetFrequencyAction = si4713_ns.class_(
"SetFrequencyAction", automation.Action, cg.Parented.template(Si4713Component)
)
#T1mSel = si4713_ns.enum("T1mSel", True)
#T1M_SEL = {
# "58s": T1mSel.T1M_SEL_58S,
# "59s": T1mSel.T1M_SEL_59S,
# "60s": T1mSel.T1M_SEL_60S,
# "Never": T1mSel.T1M_SEL_NEVER,
#}
MeasureFrequencyAction = si4713_ns.class_(
"MeasureFrequencyAction", automation.Action, cg.Parented.template(Si4713Component)
)
OpMode = si4713_ns.enum("OpMode", True)
OP_MODE = {
"Analog": OpMode.OPMODE_ANALOG,
"Digital": OpMode.OPMODE_Digital,
}
PreEmphasis = si4713_ns.enum("PreEmphasis", True)
PRE_EMPHASIS = {
"75us": PreEmphasis.FMPE_75US,
"50us": PreEmphasis.FMPE_50US,
"Disabled": PreEmphasis.FMPE_DISABLED,
}
LineAttenuation = si4713_ns.enum("LineAttenuation", True)
LINE_ATTENUATION = {
"396kOhm": LineAttenuation.LIATTEN_396KOHM,
"100kOhm": LineAttenuation.LIATTEN_100KOHM,
"74kOhm": LineAttenuation.LIATTEN_74KOHM,
"60kOhm": LineAttenuation.LIATTEN_60KOHM,
}
SampleBits = si4713_ns.enum("SampleBits", True)
SAMPLE_BITS = {
"16": SampleBits.ISIZE_16BITS,
"20": SampleBits.ISIZE_20BITS,
"24": SampleBits.ISIZE_24BITS,
"8": SampleBits.ISIZE_8BITS,
}
SampleChannels = si4713_ns.enum("SampleChannels", True)
SAMPLE_CHANNELS = {
"Stereo": SampleChannels.IMONO_STEREO,
"Mono": SampleChannels.IMONO_MONO,
}
DigitalMode = si4713_ns.enum("DigitalMode", True)
DIGITAL_MODE = {
"Default": DigitalMode.IMODE_DEFAULT,
"I2S": DigitalMode.IMODE_I2S,
"Left Justified": DigitalMode.IMODE_LEFT_JUSTIFIED,
"MSB at 1st": DigitalMode.IMODE_MSB_AT_1ST,
"MSB at 2nd": DigitalMode.IMODE_MSB_AT_2ND,
}
DigitalClockEdge = si4713_ns.enum("DigitalClockEdge", True)
DIGITAL_CLOCK_EDGE = {
"Rising": DigitalClockEdge.IFALL_DCLK_RISING_EDGE,
"Falling": DigitalClockEdge.IFALL_DCLK_FALLING_EDGE,
}
RefClkSource = si4713_ns.enum("RefClkSource", True)
REFCLK_SOURCE = {
"RCLK": RefClkSource.RCLKSEL_RCLK,
"DCLK": RefClkSource.RCLKSEL_DCLK,
}
AcompAttack = si4713_ns.enum("AcompAttack", True)
ACOMP_ATTACK = {
"0.5ms": AcompAttack.ATTACK_05MS,
"1.0ms": AcompAttack.ATTACK_10MS,
"1.5ms": AcompAttack.ATTACK_15MS,
"2.0ms": AcompAttack.ATTACK_20MS,
"2.5ms": AcompAttack.ATTACK_25MS,
"3.0ms": AcompAttack.ATTACK_30MS,
"3.5ms": AcompAttack.ATTACK_35MS,
"4.0ms": AcompAttack.ATTACK_40MS,
"4.5ms": AcompAttack.ATTACK_45MS,
"5.0ms": AcompAttack.ATTACK_50MS,
}
AcompRelease = si4713_ns.enum("AcompRelease", True)
ACOMP_RELEASE = {
"100ms": AcompRelease.RELEASE_100MS,
"200ms": AcompRelease.RELEASE_200MS,
"350ms": AcompRelease.RELEASE_350MS,
"525ms": AcompRelease.RELEASE_525MS,
"1000ms": AcompRelease.RELEASE_1000MS,
}
AcompPreset = si4713_ns.enum("AcompPreset", True)
ACOMP_PRESET = {
"Minimal": AcompPreset.ACOMP_MINIMAL,
"Aggressive": AcompPreset.ACOMP_AGGRESSIVE,
"Custom": AcompPreset.ACOMP_CUSTOM,
}
CONFIG_SCHEMA = (
cv.Schema(
{
cv.GenerateID(): cv.declare_id(Si4713Component),
cv.Required(CONF_RESET_PIN): pins.gpio_output_pin_schema,
cv.Optional(CONF_FREQUENCY, default=87.50): cv.float_range(76, 108),
cv.Optional(CONF_OP_MODE, default="Analog"): cv.enum(OP_MODE),
cv.Optional(CONF_MUTE, default=False): cv.boolean,
cv.Optional(CONF_MONO, default=False): cv.boolean,
# cv.Optional(CONF_T1M_SEL, default="60s"): cv.enum(T1M_SEL),
cv.Optional(CONF_RDS_ENABLE, default=False): cv.boolean,
cv.Optional(CONF_RDS_STATION): cv.string,
cv.Optional(CONF_RDS_TEXT): cv.string,
cv.Optional(CONF_PRE_EMPHASIS, default="75us"): cv.enum(PRE_EMPHASIS),
cv.Optional(CONF_SECTION_TUNER): cv.Schema(
{
cv.Optional(CONF_FREQUENCY, default=87.50): cv.float_range(76, 108), # MHz
cv.Optional(CONF_DEVIATION, default=68.25): cv.float_range(0, 90), # kHz
cv.Optional(CONF_POWER, default=115): cv.int_range(88, 115),
cv.Optional(CONF_ANTCAP, default=0): cv.int_range(0, 191),
}
),
cv.Optional(CONF_SECTION_ANALOG): cv.Schema(
{
cv.Optional(CONF_LEVEL, default=636): cv.int_range(0, 1023),
cv.Optional(CONF_ATTENUATION, default=636): cv.enum(LINE_ATTENUATION),
}
),
cv.Optional(CONF_SECTION_DIGITAL): cv.Schema(
{
cv.Optional(CONF_SAMPLE_RATE, default=44100): cv.int_range(32000, 48000), # Hz
cv.Optional(CONF_SAMPLE_BITS, default="16"): cv.enum(SAMPLE_BITS),
cv.Optional(CONF_CHANNELS, default="Stereo"): cv.enum(SAMPLE_CHANNELS),
cv.Optional(CONF_MODE, default="Default"): cv.enum(DIGITAL_MODE),
cv.Optional(CONF_CLOCK_EDGE, default="Rising"): cv.enum(DIGITAL_CLOCK_EDGE),
}
),
cv.Optional(CONF_SECTION_PILOT): cv.Schema(
{
cv.Optional(CONF_ENABLE, default="True"): cv.boolean,
cv.Optional(CONF_FREQUENCY, default=19): cv.float_range(0, 19), # kHz
cv.Optional(CONF_DEVIATION, default=6.75): cv.float_range(0, 90), # kHz
}
),
cv.Optional(CONF_SECTION_REFCLK): cv.Schema(
{
cv.Optional(CONF_FREQUENCY, default=32768): cv.int_range(31130, 34406), # Hz
cv.Optional(CONF_SOURCE, default="RCLK"): cv.enum(REFCLK_SOURCE),
cv.Optional(CONF_PRESCALER, default=1): cv.int_range(0, 4095),
}
),
cv.Optional(CONF_SECTION_COMPRESSOR): cv.Schema(
{
cv.Optional(CONF_ENABLE, default="False"): cv.boolean,
cv.Optional(CONF_THRESHOLD, default=-40): cv.int_range(-40, 0),
cv.Optional(CONF_ATTACK, default='0.5'): cv.enum(ACOMP_ATTACK),
cv.Optional(CONF_RELEASE, default="1000"): cv.enum(ACOMP_RELEASE),
cv.Optional(CONF_GAIN, default=15): cv.int_range(0, 20),
cv.Optional(CONF_PRESET, default="Custom"): cv.enum(ACOMP_PRESET),
}
),
cv.Optional(CONF_SECTION_LIMITER): cv.Schema(
{
cv.Optional(CONF_ENABLE, default="True"): cv.boolean,
cv.Optional(CONF_RELEASE_TIME, default=5): cv.float_range(0.25, 102.4),
}
),
cv.Optional(CONF_SECTION_ASQ): cv.Schema(
{
cv.Optional(CONF_IALL, default="False"): cv.boolean,
cv.Optional(CONF_IALH, default="False"): cv.boolean,
cv.Optional(CONF_OVERMOD, default="False"): cv.boolean,
cv.Optional(CONF_LEVEL_LOW, default=-50): cv.float_range(-70, 0),
cv.Optional(CONF_DURATION_LOW, default=10000): cv.int_range(0, 65535),
cv.Optional(CONF_LEVEL_HIGH, default=-20): cv.float_range(-70, 0),
cv.Optional(CONF_DURATION_HIGH, default=5000): cv.int_range(0, 65535),
}
),
cv.Optional(CONF_SECTION_RDS): cv.Schema(
{
cv.Optional(CONF_ENABLE, default=False): cv.boolean,
cv.Optional(CONF_DEVIATION, default=2.0): cv.float_range(0, 7.5), # kHz
cv.Optional(CONF_STATION): cv.string,
cv.Optional(CONF_TEXT): cv.string,
}
),
cv.Optional(CONF_SECTION_SENSOR): cv.Schema(
{
cv.Optional(CONF_CHIP_ID): text_sensor.text_sensor_schema(
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
icon=ICON_CHIP,
),
cv.Optional(CONF_READ_FREQUENCY): sensor.sensor_schema(
unit_of_measurement=UNIT_MEGA_HERTZ,
# entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
state_class=STATE_CLASS_MEASUREMENT,
accuracy_decimals=2,
# icon=ICON_,
),
cv.Optional(CONF_READ_POWER): sensor.sensor_schema(
unit_of_measurement=UNIT_DECIBEL_MICRO_VOLT,
# entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
state_class=STATE_CLASS_MEASUREMENT,
# icon=ICON_,
),
cv.Optional(CONF_READ_ANTCAP): sensor.sensor_schema(
unit_of_measurement=UNIT_PICO_FARAD,
# entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
state_class=STATE_CLASS_MEASUREMENT,
# icon=ICON_,
),
cv.Optional(CONF_READ_NOISE_LEVEL): sensor.sensor_schema(
unit_of_measurement=UNIT_DECIBEL_MICRO_VOLT,
# entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
# state_class=STATE_CLASS_MEASUREMENT,
# icon=ICON_,
),
cv.Optional(CONF_IALL): binary_sensor.binary_sensor_schema(
# entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
# icon=ICON_,
),
cv.Optional(CONF_IALH): binary_sensor.binary_sensor_schema(
# entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
# icon=ICON_,
),
cv.Optional(CONF_OVERMOD): binary_sensor.binary_sensor_schema(
# entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
# icon=ICON_,
),
cv.Optional(CONF_INLEVEL): sensor.sensor_schema(
unit_of_measurement=UNIT_DECIBEL_FS,
# entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
state_class=STATE_CLASS_MEASUREMENT,
# icon=ICON_,
),
}
),
}
)
.extend(cv.polling_component_schema("60s"))
@ -98,18 +352,43 @@ CONFIG_SCHEMA = (
)
FREQUENCY_SCHEMA = automation.maybe_simple_id(
{
cv.GenerateID(): cv.use_id(Si4713Component),
cv.Required(CONF_FREQUENCY): cv.templatable(cv.float_range(min = 76, max = 108)),
}
)
@automation.register_action("si4713.set_frequency", SetFrequencyAction, FREQUENCY_SCHEMA)
@automation.register_action("si4713.measure_frequency", MeasureFrequencyAction, FREQUENCY_SCHEMA)
async def tune_frequency_action_to_code(config, action_id, template_arg, args):
var = cg.new_Pvariable(action_id, template_arg)
await cg.register_parented(var, config[CONF_ID])
if frequency := config.get(CONF_FREQUENCY):
template_ = await cg.templatable(frequency, args, cg.float_)
cg.add(var.set_frequency(template_))
return var
async def set_var(config, id, setter):
if c := config.get(id):
cg.add(setter(c))
async def set_sensor(config, id, setter):
async def new_sensor(config, id, setter):
if c := config.get(id):
s = await sensor.new_sensor(c)
cg.add(setter(s))
async def set_text_sensor(config, id, setter):
async def new_binary_sensor(config, id, setter):
if c := config.get(id):
s = await binary_sensor.new_binary_sensor(c)
cg.add(setter(s))
async def new_text_sensor(config, id, setter):
if c := config.get(id):
s = await text_sensor.new_text_sensor(c)
cg.add(setter(s))
@ -121,11 +400,62 @@ async def to_code(config):
await i2c.register_i2c_device(var, config)
reset_pin = await cg.gpio_pin_expression(config[CONF_RESET_PIN])
cg.add(var.set_reset_pin(reset_pin))
await set_var(config, CONF_FREQUENCY, var.set_frequency)
await set_var(config, CONF_OP_MODE, var.set_op_mode)
await set_var(config, CONF_MUTE, var.set_mute)
await set_var(config, CONF_MONO, var.set_mono)
# await set_var(config, CONF_T1M_SEL, var.set_t1m_sel)
await set_var(config, CONF_RDS_ENABLE, var.set_rds_enable)
await set_var(config, CONF_RDS_STATION, var.set_rds_station)
await set_var(config, CONF_RDS_TEXT, var.set_rds_text)
await set_text_sensor(config, CONF_CHIP_ID, var.set_chip_id_text_sensor)
await set_var(config, CONF_PRE_EMPHASIS, var.set_pre_emphasis)
if tuner_config := config.get(CONF_SECTION_TUNER):
await set_var(tuner_config, CONF_FREQUENCY, var.set_frequency)
await set_var(tuner_config, CONF_DEVIATION, var.set_audio_deviation)
await set_var(tuner_config, CONF_POWER, var.set_power)
await set_var(tuner_config, CONF_ANTCAP, var.set_antcap)
if analog_config := config.get(CONF_SECTION_ANALOG):
await set_var(analog_config, CONF_LEVEL, var.set_analog_level)
await set_var(analog_config, CONF_ATTENUATION, var.set_analog_attenuation)
if digital_config := config.get(CONF_SECTION_DIGITAL):
await set_var(digital_config, CONF_SAMPLE_RATE, var.set_digital_sample_rate)
await set_var(digital_config, CONF_SAMPLE_BITS, var.set_digital_sample_bits)
await set_var(digital_config, CONF_CHANNELS, var.set_digital_channels)
await set_var(digital_config, CONF_MODE, var.set_digital_mode)
await set_var(digital_config, CONF_CLOCK_EDGE, var.set_digital_clock_edge)
if pilot_config := config.get(CONF_SECTION_PILOT):
await set_var(pilot_config, CONF_ENABLE, var.set_pilot_enable)
await set_var(pilot_config, CONF_FREQUENCY, var.set_pilot_frequency)
await set_var(pilot_config, CONF_DEVIATION, var.set_pilot_deviation)
if refclk_config := config.get(CONF_SECTION_REFCLK):
await set_var(refclk_config, CONF_FREQUENCY, var.set_refclk_frequency)
await set_var(refclk_config, CONF_SOURCE, var.set_refclk_source)
await set_var(refclk_config, CONF_PRESCALER, var.set_refclk_prescaler)
if compressor_config := config.get(CONF_SECTION_COMPRESSOR):
await set_var(compressor_config, CONF_ENABLE, var.set_acomp_enable)
await set_var(compressor_config, CONF_THRESHOLD, var.set_acomp_threshold)
await set_var(compressor_config, CONF_ATTACK, var.set_acomp_attack)
await set_var(compressor_config, CONF_RELEASE, var.set_acomp_release)
await set_var(compressor_config, CONF_GAIN, var.set_acomp_gain)
await set_var(compressor_config, CONF_PRESET, var.set_acomp_preset)
if limiter_config := config.get(CONF_SECTION_LIMITER):
await set_var(limiter_config, CONF_ENABLE, var.set_limiter_enable)
await set_var(limiter_config, CONF_RELEASE_TIME, var.set_limiter_release_time)
if asq_config := config.get(CONF_SECTION_ASQ):
await set_var(asq_config, CONF_IALL, var.set_asq_iall_enable)
await set_var(asq_config, CONF_IALH, var.set_asq_ialh_enable)
await set_var(asq_config, CONF_OVERMOD, var.set_asq_overmod_enable)
await set_var(asq_config, CONF_LEVEL_LOW, var.set_asq_level_low)
await set_var(asq_config, CONF_DURATION_LOW, var.set_asq_duration_low)
await set_var(asq_config, CONF_LEVEL_HIGH, var.set_asq_level_high)
await set_var(asq_config, CONF_DURATION_HIGH, var.set_asq_duration_high)
if rds_config := config.get(CONF_SECTION_RDS):
await set_var(rds_config, CONF_ENABLE, var.set_rds_enable)
await set_var(rds_config, CONF_DEVIATION, var.set_rds_deviation)
await set_var(rds_config, CONF_STATION, var.set_rds_station)
await set_var(rds_config, CONF_TEXT, var.set_rds_text)
if sensor_config := config.get(CONF_SECTION_SENSOR):
await new_text_sensor(sensor_config, CONF_CHIP_ID, var.set_chip_id_text_sensor)
await new_sensor(sensor_config, CONF_READ_FREQUENCY, var.set_read_frequency_sensor)
await new_sensor(sensor_config, CONF_READ_POWER, var.set_read_power_sensor)
await new_sensor(sensor_config, CONF_READ_ANTCAP, var.set_read_antcap_sensor)
await new_sensor(sensor_config, CONF_READ_NOISE_LEVEL, var.set_read_noise_level_sensor)
await new_binary_sensor(sensor_config, CONF_IALL, var.set_iall_binary_sensor)
await new_binary_sensor(sensor_config, CONF_IALH, var.set_ialh_binary_sensor)
await new_binary_sensor(sensor_config, CONF_OVERMOD, var.set_overmod_binary_sensor)
await new_sensor(sensor_config, CONF_INLEVEL, var.set_inlevel_sensor)

View file

@ -3,11 +3,15 @@ from esphome.components import number
import esphome.config_validation as cv
from esphome.const import (
CONF_FREQUENCY,
UNIT_PERCENT,
CONF_MODE,
UNIT_HERTZ,
UNIT_MILLISECOND,
UNIT_DECIBEL,
UNIT_EMPTY,
DEVICE_CLASS_FREQUENCY,
DEVICE_CLASS_CURRENT,
DEVICE_CLASS_VOLTAGE,
DEVICE_CLASS_SIGNAL_STRENGTH,
DEVICE_CLASS_DURATION,
DEVICE_CLASS_EMPTY,
ENTITY_CATEGORY_CONFIG,
)
@ -15,37 +19,245 @@ from .. import (
CONF_SI4713_ID,
Si4713Component,
si4713_ns,
# CONF_,
CONF_SECTION_TUNER,
CONF_SECTION_ANALOG,
CONF_SECTION_DIGITAL,
CONF_SECTION_PILOT,
CONF_SECTION_REFCLK,
CONF_SECTION_COMPRESSOR,
CONF_SECTION_LIMITER,
CONF_SECTION_ASQ,
CONF_SECTION_RDS,
CONF_FREQUENCY,
CONF_DEVIATION,
CONF_POWER,
CONF_ANTCAP,
CONF_LEVEL,
CONF_SAMPLE_RATE,
CONF_PRESCALER,
CONF_THRESHOLD,
CONF_GAIN,
CONF_RELEASE_TIME,
CONF_LEVEL_LOW,
CONF_DURATION_LOW,
CONF_LEVEL_HIGH,
CONF_DURATION_HIGH,
UNIT_MEGA_HERTZ,
UNIT_KILO_HERTZ,
UNIT_MICRO_AMPERE,
UNIT_MILLI_VOLT,
UNIT_DECIBEL_MICRO_VOLT,
UNIT_PICO_FARAD,
)
FrequencyNumber = si4713_ns.class_("FrequencyNumber", number.Number)
AudioDeviationNumber = si4713_ns.class_("AudioDeviationNumber", number.Number)
PowerNumber = si4713_ns.class_("PowerNumber", number.Number)
AntcapNumber = si4713_ns.class_("AntcapNumber", number.Number)
AnalogLevelNumber = si4713_ns.class_("AnalogLevelNumber", number.Number)
DigitalSampleRateNumber = si4713_ns.class_("DigitalSampleRateNumber", number.Number)
PilotFrequencyNumber = si4713_ns.class_("PilotFrequencyNumber", number.Number)
PilotDeviationNumber = si4713_ns.class_("PilotDeviationNumber", number.Number)
RefClkFrequencyNumber = si4713_ns.class_("RefClkFrequencyNumber", number.Number)
RefClkPrescalerNumber = si4713_ns.class_("RefClkPrescalerNumber", number.Number)
AcompThresholdNumber = si4713_ns.class_("AcompThresholdNumber", number.Number)
AcompGainNumber = si4713_ns.class_("AcompGainNumber", number.Number)
LimiterReleaseTimeNumber = si4713_ns.class_("LimiterReleaseTimeNumber", number.Number)
AsqLevelLowNumber = si4713_ns.class_("AsqLevelLowNumber", number.Number)
AsqDurationLowNumber = si4713_ns.class_("AsqDurationLowNumber", number.Number)
AsqLevelHighNumber = si4713_ns.class_("AsqLevelHighNumber", number.Number)
AsqDurationHighNumber = si4713_ns.class_("AsqDurationHighNumber", number.Number)
RdsDeviationNumber = si4713_ns.class_("RdsDeviationNumber", number.Number)
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(CONF_SI4713_ID): cv.use_id(Si4713Component),
cv.Optional(CONF_SECTION_TUNER): cv.Schema(
{
cv.Optional(CONF_FREQUENCY): number.number_schema(
FrequencyNumber,
unit_of_measurement=UNIT_MEGA_HERTZ,
device_class=DEVICE_CLASS_FREQUENCY,
entity_category=ENTITY_CATEGORY_CONFIG,
),
cv.Optional(CONF_DEVIATION): number.number_schema(
AudioDeviationNumber,
unit_of_measurement=UNIT_KILO_HERTZ,
device_class=DEVICE_CLASS_FREQUENCY,
entity_category=ENTITY_CATEGORY_CONFIG,
),
cv.Optional(CONF_POWER): number.number_schema(
PowerNumber,
unit_of_measurement=UNIT_DECIBEL_MICRO_VOLT,
device_class=DEVICE_CLASS_SIGNAL_STRENGTH,
entity_category=ENTITY_CATEGORY_CONFIG,
),
cv.Optional(CONF_ANTCAP): number.number_schema(
AntcapNumber,
unit_of_measurement=UNIT_PICO_FARAD,
device_class=DEVICE_CLASS_EMPTY,
entity_category=ENTITY_CATEGORY_CONFIG,
),
}
),
cv.Optional(CONF_SECTION_ANALOG): cv.Schema(
{
cv.Optional(CONF_LEVEL): number.number_schema(
AnalogLevelNumber,
unit_of_measurement=UNIT_MILLI_VOLT,
device_class=DEVICE_CLASS_VOLTAGE,
entity_category=ENTITY_CATEGORY_CONFIG,
),
},
),
cv.Optional(CONF_SECTION_DIGITAL): cv.Schema(
{
cv.Optional(CONF_SAMPLE_RATE): number.number_schema(
DigitalSampleRateNumber,
unit_of_measurement=UNIT_HERTZ,
device_class=DEVICE_CLASS_FREQUENCY,
entity_category=ENTITY_CATEGORY_CONFIG,
),
},
),
cv.Optional(CONF_SECTION_PILOT): cv.Schema(
{
cv.Optional(CONF_FREQUENCY): number.number_schema(
PilotFrequencyNumber,
unit_of_measurement=UNIT_KILO_HERTZ,
device_class=DEVICE_CLASS_FREQUENCY,
entity_category=ENTITY_CATEGORY_CONFIG,
),
cv.Optional(CONF_DEVIATION): number.number_schema(
PilotDeviationNumber,
unit_of_measurement=UNIT_KILO_HERTZ,
device_class=DEVICE_CLASS_FREQUENCY,
entity_category=ENTITY_CATEGORY_CONFIG,
),
},
),
cv.Optional(CONF_SECTION_REFCLK): cv.Schema(
{
cv.Optional(CONF_FREQUENCY): number.number_schema(
RefClkFrequencyNumber,
unit_of_measurement=UNIT_HERTZ,
device_class=DEVICE_CLASS_FREQUENCY,
entity_category=ENTITY_CATEGORY_CONFIG,
),
cv.Optional(CONF_PRESCALER): number.number_schema(
RefClkPrescalerNumber,
unit_of_measurement=UNIT_EMPTY,
device_class=DEVICE_CLASS_EMPTY,
entity_category=ENTITY_CATEGORY_CONFIG,
),
},
),
cv.Optional(CONF_SECTION_COMPRESSOR): cv.Schema(
{
cv.Optional(CONF_THRESHOLD): number.number_schema(
AcompThresholdNumber,
unit_of_measurement=UNIT_DECIBEL,
device_class=DEVICE_CLASS_SIGNAL_STRENGTH,
entity_category=ENTITY_CATEGORY_CONFIG,
),
cv.Optional(CONF_GAIN): number.number_schema(
AcompGainNumber,
unit_of_measurement=UNIT_DECIBEL,
device_class=DEVICE_CLASS_SIGNAL_STRENGTH,
entity_category=ENTITY_CATEGORY_CONFIG,
),
},
),
cv.Optional(CONF_SECTION_LIMITER): cv.Schema(
{
cv.Optional(CONF_RELEASE_TIME): number.number_schema(
LimiterReleaseTimeNumber,
unit_of_measurement=UNIT_MILLISECOND,
device_class=DEVICE_CLASS_DURATION,
entity_category=ENTITY_CATEGORY_CONFIG,
),
},
),
cv.Optional(CONF_SECTION_ASQ): cv.Schema(
{
cv.Optional(CONF_LEVEL_LOW): number.number_schema(
AsqLevelLowNumber,
unit_of_measurement=UNIT_DECIBEL,
device_class=DEVICE_CLASS_SIGNAL_STRENGTH,
entity_category=ENTITY_CATEGORY_CONFIG,
),
cv.Optional(CONF_DURATION_LOW): number.number_schema(
AsqDurationLowNumber,
unit_of_measurement=UNIT_MILLISECOND,
device_class=DEVICE_CLASS_DURATION,
entity_category=ENTITY_CATEGORY_CONFIG,
),
cv.Optional(CONF_LEVEL_HIGH): number.number_schema(
AsqLevelHighNumber,
unit_of_measurement=UNIT_DECIBEL,
device_class=DEVICE_CLASS_SIGNAL_STRENGTH,
entity_category=ENTITY_CATEGORY_CONFIG,
),
cv.Optional(CONF_DURATION_HIGH): number.number_schema(
AsqDurationHighNumber,
unit_of_measurement=UNIT_MILLISECOND,
device_class=DEVICE_CLASS_DURATION,
entity_category=ENTITY_CATEGORY_CONFIG,
),
}
),
cv.Optional(CONF_SECTION_RDS): cv.Schema(
{
cv.Optional(CONF_DEVIATION): number.number_schema(
RdsDeviationNumber,
unit_of_measurement=UNIT_KILO_HERTZ,
device_class=DEVICE_CLASS_FREQUENCY,
entity_category=ENTITY_CATEGORY_CONFIG,
),
},
),
}
)
async def new_number(config, id, setter, min_value, max_value, step, *args):
async def new_number(parent, config, id, setter, min_value, max_value, step, *args, **kwargs):
if c := config.get(id):
if CONF_MODE in kwargs:
if CONF_MODE not in c or c[CONF_MODE] == number.NumberMode.NUMBER_MODE_AUTO:
c[CONF_MODE] = kwargs.get(CONF_MODE)
n = await number.new_number(
c, *args, min_value=min_value, max_value=max_value, step=step
)
await cg.register_parented(n, config[CONF_SI4713_ID])
await cg.register_parented(n, parent)
cg.add(setter(n))
return n
async def to_code(config):
c = await cg.get_variable(config[CONF_SI4713_ID])
await new_number(config, CONF_FREQUENCY, c.set_frequency_number, 76, 108, 0.05)
parent = await cg.get_variable(config[CONF_SI4713_ID])
if tuner_config := config.get(CONF_SECTION_TUNER):
await new_number(parent, tuner_config, CONF_FREQUENCY, parent.set_frequency_number, 76, 108, 0.05)
await new_number(parent, tuner_config, CONF_DEVIATION, parent.set_audio_deviation_number, 0, 90, 0.01)
await new_number(parent, tuner_config, CONF_POWER, parent.set_power_number, 88, 120, 1, mode = number.NumberMode.NUMBER_MODE_SLIDER)
await new_number(parent, tuner_config, CONF_ANTCAP, parent.set_antcap_number, 0, 191, 1, mode = number.NumberMode.NUMBER_MODE_SLIDER)
if analog_config := config.get(CONF_SECTION_ANALOG):
await new_number(parent, analog_config, CONF_LEVEL, parent.set_analog_level_number, 0, 1023, 1, mode = number.NumberMode.NUMBER_MODE_SLIDER)
if digital_config := config.get(CONF_SECTION_DIGITAL):
await new_number(parent, digital_config, CONF_SAMPLE_RATE, parent.set_digital_sample_rate_number, 32000, 48000, 1)
if pilot_config := config.get(CONF_SECTION_PILOT):
await new_number(parent, pilot_config, CONF_FREQUENCY, parent.set_pilot_frequency_number, 0, 19, 0.001)
await new_number(parent, pilot_config, CONF_DEVIATION, parent.set_pilot_deviation_number, 0, 90, 0.001)
if refclk_config := config.get(CONF_SECTION_REFCLK):
await new_number(parent, refclk_config, CONF_FREQUENCY, parent.set_refclk_frequency_number, 31130, 34406, 1)
await new_number(parent, refclk_config, CONF_PRESCALER, parent.set_refclk_prescaler_number, 0, 4095, 1)
if compressor_config := config.get(CONF_SECTION_COMPRESSOR):
await new_number(parent, compressor_config, CONF_THRESHOLD, parent.set_acomp_threshold_number, -40, 0, 1)
await new_number(parent, compressor_config, CONF_GAIN, parent.set_acomp_gain_number, 0, 20, 1)
if limiter_config := config.get(CONF_SECTION_LIMITER):
await new_number(parent, limiter_config, CONF_RELEASE_TIME, parent.set_limiter_release_time_number, 0.25, 102.4, 0.01, mode = number.NumberMode.NUMBER_MODE_SLIDER)
if asq_config := config.get(CONF_SECTION_ASQ):
await new_number(parent, asq_config, CONF_LEVEL_LOW, parent.set_asq_level_low_number, -70, 0, 1)
await new_number(parent, asq_config, CONF_DURATION_LOW, parent.set_asq_duration_low_number, 0, 65535, 1)
await new_number(parent, asq_config, CONF_LEVEL_HIGH, parent.set_asq_level_high_number, -70, 0, 1)
await new_number(parent, asq_config, CONF_DURATION_HIGH, parent.set_asq_duration_high_number, 0, 65535, 1)
if rds_config := config.get(CONF_SECTION_RDS):
await new_number(parent, rds_config, CONF_DEVIATION, parent.set_rds_deviation_number, 0, 7.5, 0.01)

View file

@ -0,0 +1,12 @@
#include "acomp_gain_number.h"
namespace esphome {
namespace si4713 {
void AcompGainNumber::control(float value) {
this->publish_state(value);
this->parent_->set_acomp_gain(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "acomp_threshold_number.h"
namespace esphome {
namespace si4713 {
void AcompThresholdNumber::control(float value) {
this->publish_state(value);
this->parent_->set_acomp_threshold(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "analog_level_number.h"
namespace esphome {
namespace si4713 {
void AnalogLevelNumber::control(float value) {
this->publish_state(value);
this->parent_->set_analog_level(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "antcap_number.h"
namespace esphome {
namespace si4713 {
void AntcapNumber::control(float value) {
this->publish_state(value);
this->parent_->set_antcap(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "asq_duration_high_number.h"
namespace esphome {
namespace si4713 {
void AsqDurationHighNumber::control(float value) {
this->publish_state(value);
this->parent_->set_asq_duration_high(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "asq_duration_low_number.h"
namespace esphome {
namespace si4713 {
void AsqDurationLowNumber::control(float value) {
this->publish_state(value);
this->parent_->set_asq_duration_low(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "asq_level_high_number.h"
namespace esphome {
namespace si4713 {
void AsqLevelHighNumber::control(float value) {
this->publish_state(value);
this->parent_->set_asq_level_high(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "asq_level_low_number.h"
namespace esphome {
namespace si4713 {
void AsqLevelLowNumber::control(float value) {
this->publish_state(value);
this->parent_->set_asq_level_low(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "audio_deviation_number.h"
namespace esphome {
namespace si4713 {
void AudioDeviationNumber::control(float value) {
this->publish_state(value);
this->parent_->set_audio_deviation(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "digital_sample_rate_number.h"
namespace esphome {
namespace si4713 {
void DigitalSampleRateNumber::control(float value) {
this->publish_state(value);
this->parent_->set_digital_sample_rate(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "limiter_release_time_number.h"
namespace esphome {
namespace si4713 {
void LimiterReleaseTimeNumber::control(float value) {
this->publish_state(value);
this->parent_->set_limiter_release_time(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "pilot_deviation_number.h"
namespace esphome {
namespace si4713 {
void PilotDeviationNumber::control(float value) {
this->publish_state(value);
this->parent_->set_pilot_deviation(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "pilot_frequency_number.h"
namespace esphome {
namespace si4713 {
void PilotFrequencyNumber::control(float value) {
this->publish_state(value);
this->parent_->set_pilot_frequency(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "power_number.h"
namespace esphome {
namespace si4713 {
void PowerNumber::control(float value) {
this->publish_state(value);
this->parent_->set_power(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "rds_deviation_number.h"
namespace esphome {
namespace si4713 {
void RdsDeviationNumber::control(float value) {
this->publish_state(value);
this->parent_->set_rds_deviation(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "refclk_frequency_number.h"
namespace esphome {
namespace si4713 {
void RefClkFrequencyNumber::control(float value) {
this->publish_state(value);
this->parent_->set_refclk_frequency(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -0,0 +1,12 @@
#include "refclk_prescaler_number.h"
namespace esphome {
namespace si4713 {
void RefClkPrescalerNumber::control(float value) {
this->publish_state(value);
this->parent_->set_refclk_prescaler(value);
}
} // namespace si4713
} // namespace esphome

View file

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

View file

@ -12,7 +12,7 @@ void BinaryOutput::dump_config() {
ESP_LOGCONFIG(TAG, " Pin: %d", this->pin_);
}
void Si4713BinaryOutput::write_state(bool state) {
void BinaryOutput::write_state(bool state) {
this->parent_->set_gpio(this->pin_, state);
}

View file

@ -9,34 +9,140 @@ from .. import (
CONF_SI4713_ID,
Si4713Component,
si4713_ns,
CONF_,
ICON_SLEEP,
CONF_SECTION_ANALOG,
CONF_SECTION_DIGITAL,
CONF_SECTION_REFCLK,
CONF_SECTION_COMPRESSOR,
CONF_PRE_EMPHASIS,
CONF_ATTENUATION,
CONF_SAMPLE_BITS,
CONF_CHANNELS,
CONF_MODE,
CONF_CLOCK_EDGE,
CONF_SOURCE,
CONF_ATTACK,
CONF_RELEASE,
CONF_PRESET,
ICON_SINE_WAVE,
ICON_RESISTOR,
# T1M_SEL,
ICON_EAR_HEARING,
PRE_EMPHASIS,
LINE_ATTENUATION,
SAMPLE_BITS,
SAMPLE_CHANNELS,
DIGITAL_MODE,
DIGITAL_CLOCK_EDGE,
REFCLK_SOURCE,
ACOMP_ATTACK,
ACOMP_RELEASE,
ACOMP_PRESET,
)
#T1mSelSelect = si4713_ns.class_("T1mSelSelect", select.Select)
PreEmphasisSelect = si4713_ns.class_("PreEmphasisSelect", select.Select)
AnalogAttenuationSelect = si4713_ns.class_("AnalogAttenuationSelect", select.Select)
DigitalSampleBitsSelect = si4713_ns.class_("DigitalSampleBitsSelect", select.Select)
DigitalChannelsSelect = si4713_ns.class_("DigitalChannelsSelect", select.Select)
DigitalModeSelect = si4713_ns.class_("DigitalModeSelect", select.Select)
DigitalClockEdgeSelect = si4713_ns.class_("DigitalClockEdgeSelect", select.Select)
RefClkSourceSelect = si4713_ns.class_("RefClkSourceSelect", select.Select)
AcompAttackSelect = si4713_ns.class_("AcompAttackSelect", select.Select)
AcompReleaseSelect = si4713_ns.class_("AcompReleaseSelect", select.Select)
AcompPresetSelect = si4713_ns.class_("AcompPresetSelect", select.Select)
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(CONF_SI4713_ID): cv.use_id(Si4713Component),
# cv.Optional(CONF_T1M_SEL): select.select_schema(
# T1mSelSelect,
# entity_category=ENTITY_CATEGORY_CONFIG,
# icon=ICON_SLEEP,
# ),
cv.Optional(CONF_PRE_EMPHASIS): select.select_schema(
PreEmphasisSelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_SINE_WAVE,
),
cv.Optional(CONF_SECTION_ANALOG): cv.Schema(
{
cv.Optional(CONF_ATTENUATION): select.select_schema(
AnalogAttenuationSelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_RESISTOR,
),
}
),
cv.Optional(CONF_SECTION_DIGITAL): cv.Schema(
{
cv.Optional(CONF_SAMPLE_BITS): select.select_schema(
DigitalSampleBitsSelect,
entity_category=ENTITY_CATEGORY_CONFIG,
# icon=ICON_,
),
cv.Optional(CONF_CHANNELS): select.select_schema(
DigitalChannelsSelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_EAR_HEARING,
),
cv.Optional(CONF_MODE): select.select_schema(
DigitalModeSelect,
entity_category=ENTITY_CATEGORY_CONFIG,
# icon=ICON_,
),
cv.Optional(CONF_CLOCK_EDGE): select.select_schema(
DigitalClockEdgeSelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_PULSE,
),
}
),
cv.Optional(CONF_SECTION_REFCLK): cv.Schema(
{
cv.Optional(CONF_SOURCE): select.select_schema(
RefClkSourceSelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_PULSE,
),
}
),
cv.Optional(CONF_SECTION_COMPRESSOR): cv.Schema(
{
cv.Optional(CONF_ATTACK): select.select_schema(
AcompAttackSelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_SINE_WAVE,
),
cv.Optional(CONF_RELEASE): select.select_schema(
AcompReleaseSelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_SINE_WAVE,
),
cv.Optional(CONF_PRESET): select.select_schema(
AcompPresetSelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_SINE_WAVE,
),
}
),
}
)
async def new_select(config, id, setter, options):
async def new_select(parent, config, id, setter, options):
if c := config.get(id):
s = await select.new_select(c, options=list(options.keys()))
await cg.register_parented(s, config[CONF_SI4713_ID])
await cg.register_parented(s, parent)
cg.add(setter(s))
return s
async def to_code(config):
c = await cg.get_variable(config[CONF_SI4713_ID])
# await new_select(config, CONF_T1M_SEL, c.set_t1m_sel_select, T1M_SEL)
parent = await cg.get_variable(config[CONF_SI4713_ID])
await new_select(parent, config, CONF_PRE_EMPHASIS, parent.set_pre_emphasis_select, PRE_EMPHASIS)
if analog_config := config.get(CONF_SECTION_ANALOG):
await new_select(parent, analog_config, CONF_ATTENUATION, parent.set_analog_attenuation_select, LINE_ATTENUATION)
if digital_config := config.get(CONF_SECTION_DIGITAL):
await new_select(parent, digital_config, CONF_SAMPLE_BITS, parent.set_digital_sample_bits_select, SAMPLE_BITS)
await new_select(parent, digital_config, CONF_CHANNELS, parent.set_digital_channels_select, SAMPLE_CHANNELS)
await new_select(parent, digital_config, CONF_MODE, parent.set_digital_mode_select, DIGITAL_MODE)
await new_select(parent, digital_config, CONF_CLOCK_EDGE, parent.set_digital_clock_edge_select, DIGITAL_CLOCK_EDGE)
if refclk_config := config.get(CONF_SECTION_REFCLK):
await new_select(parent, refclk_config, CONF_SOURCE, parent.set_refclk_source_select, REFCLK_SOURCE)
if compressor_config := config.get(CONF_SECTION_COMPRESSOR):
await new_select(parent, compressor_config, CONF_ATTACK, parent.set_acomp_attack_select, ACOMP_ATTACK)
await new_select(parent, compressor_config, CONF_RELEASE, parent.set_acomp_release_select, ACOMP_RELEASE)
await new_select(parent, compressor_config, CONF_PRESET, parent.set_acomp_preset_select, ACOMP_PRESET)

View file

@ -0,0 +1,14 @@
#include "acomp_attack_select.h"
namespace esphome {
namespace si4713 {
void AcompAttackSelect::control(const std::string &value) {
this->publish_state(value);
if (auto index = this->active_index()) {
this->parent_->set_acomp_attack((AcompAttack) *index);
}
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/select/select.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class AcompAttackSelect : public select::Select, public Parented<Si4713Component> {
public:
AcompAttackSelect() = default;
protected:
void control(const std::string &value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,14 @@
#include "acomp_preset_select.h"
namespace esphome {
namespace si4713 {
void AcompPresetSelect::control(const std::string &value) {
this->publish_state(value);
if (auto index = this->active_index()) {
this->parent_->set_acomp_preset((AcompPreset) *index);
}
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/select/select.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class AcompPresetSelect : public select::Select, public Parented<Si4713Component> {
public:
AcompPresetSelect() = default;
protected:
void control(const std::string &value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,14 @@
#include "acomp_release_select.h"
namespace esphome {
namespace si4713 {
void AcompReleaseSelect::control(const std::string &value) {
this->publish_state(value);
if (auto index = this->active_index()) {
this->parent_->set_acomp_release((AcompRelease) *index);
}
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/select/select.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class AcompReleaseSelect : public select::Select, public Parented<Si4713Component> {
public:
AcompReleaseSelect() = default;
protected:
void control(const std::string &value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,14 @@
#include "analog_attenuation_select.h"
namespace esphome {
namespace si4713 {
void AnalogAttenuationSelect::control(const std::string &value) {
this->publish_state(value);
if (auto index = this->active_index()) {
this->parent_->set_analog_attenuation((LineAttenuation) *index);
}
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/select/select.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class AnalogAttenuationSelect : public select::Select, public Parented<Si4713Component> {
public:
AnalogAttenuationSelect() = default;
protected:
void control(const std::string &value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,14 @@
#include "digital_channels_select.h"
namespace esphome {
namespace si4713 {
void DigitalChannelsSelect::control(const std::string &value) {
this->publish_state(value);
if (auto index = this->active_index()) {
this->parent_->set_digital_channels((SampleChannels) *index);
}
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/select/select.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class DigitalChannelsSelect : public select::Select, public Parented<Si4713Component> {
public:
DigitalChannelsSelect() = default;
protected:
void control(const std::string &value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,14 @@
#include "digital_clock_edge_select.h"
namespace esphome {
namespace si4713 {
void DigitalClockEdgeSelect::control(const std::string &value) {
this->publish_state(value);
if (auto index = this->active_index()) {
this->parent_->set_digital_clock_edge((DigitalClockEdge) *index);
}
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/select/select.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class DigitalClockEdgeSelect : public select::Select, public Parented<Si4713Component> {
public:
DigitalClockEdgeSelect() = default;
protected:
void control(const std::string &value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,14 @@
#include "digital_mode_select.h"
namespace esphome {
namespace si4713 {
void DigitalModeSelect::control(const std::string &value) {
this->publish_state(value);
if (auto index = this->active_index()) {
this->parent_->set_digital_mode((DigitalMode) *index);
}
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/select/select.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class DigitalModeSelect : public select::Select, public Parented<Si4713Component> {
public:
DigitalModeSelect() = default;
protected:
void control(const std::string &value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,14 @@
#include "digital_sample_bits_select.h"
namespace esphome {
namespace si4713 {
void DigitalSampleBitsSelect::control(const std::string &value) {
this->publish_state(value);
if (auto index = this->active_index()) {
this->parent_->set_digital_sample_bits((SampleBits) *index);
}
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/select/select.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class DigitalSampleBitsSelect : public select::Select, public Parented<Si4713Component> {
public:
DigitalSampleBitsSelect() = default;
protected:
void control(const std::string &value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,14 @@
#include "pre_emphasis_select.h"
namespace esphome {
namespace si4713 {
void PreEmphasisSelect::control(const std::string &value) {
this->publish_state(value);
if (auto index = this->active_index()) {
this->parent_->set_pre_emphasis((PreEmphasis) *index);
}
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/select/select.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class PreEmphasisSelect : public select::Select, public Parented<Si4713Component> {
public:
PreEmphasisSelect() = default;
protected:
void control(const std::string &value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,14 @@
#include "refclk_source_select.h"
namespace esphome {
namespace si4713 {
void RefClkSourceSelect::control(const std::string &value) {
this->publish_state(value);
if (auto index = this->active_index()) {
this->parent_->set_refclk_source((RefClkSource) *index);
}
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/select/select.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class RefClkSourceSelect : public select::Select, public Parented<Si4713Component> {
public:
RefClkSourceSelect() = default;
protected:
void control(const std::string &value) override;
};
} // namespace si4713
} // namespace esphome

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,7 @@
#include "esphome/core/gpio.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/binary_sensor/binary_sensor.h"
#include "esphome/components/text_sensor/text_sensor.h"
#include "esphome/components/number/number.h"
#include "esphome/components/switch/switch.h"
@ -25,20 +26,75 @@ namespace si4713 {
void set_##name##_text(text::Text *text) { this->name##_text_ = text; }
#endif
#define SUB_NUMBER_EX(name) \
SUB_NUMBER(name) \
void publish_##name() { this->publish(this->name##_number_, (float) this->get_##name()); }
#define SUB_SWITCH_EX(name) \
SUB_SWITCH(name) \
void publish_##name() { this->publish_switch(this->name##_switch_, this->get_##name()); }
#define SUB_SELECT_EX(name) \
SUB_SELECT(name) \
void publish_##name() { this->publish_select(this->name##_select_, (size_t) this->get_##name()); }
#define SUB_TEXT_EX(name) \
SUB_TEXT(name) \
void publish_##name() { this->publish(this->name##_text_, this->get_##name()); }
#define SUB_SENSOR_EX(name) \
SUB_SENSOR(name) \
void publish_##name() { this->publish(this->name##_sensor_, (float) this->get_##name()); }
#define SUB_BINARY_SENSOR_EX(name) \
SUB_BINARY_SENSOR(name) \
void publish_##name() { this->publish(this->name##_binary_sensor_, this->get_##name()); }
#define SUB_TEXT_SENSOR_EX(name) \
SUB_TEXT_SENSOR(name) \
void publish_##name() { this->publish(this->name##_text_sensor_, this->get_##name()); }
class Si4713Component : public PollingComponent, public i2c::I2CDevice {
std::string chip_id_;
InternalGPIOPin *reset_pin_;
bool reset_;
bool gpio_[3];
/*
union {
struct Si4713State state_;
uint8_t regs_[sizeof(struct Si4713State)];
};
ResTxTuneStatus tune_status_;
ResTxAsqStatus asq_status_;
// config state
OpMode op_mode_;
uint16_t frequency_;
uint8_t power_;
uint8_t antcap_;
PropTxComponentEnable tx_component_enable_;
PropTxAudioDeviation tx_audio_deviation_;
PropTxPreEmphasis tx_pre_emphasis_;
PropTxPilotFrequency tx_pilot_frequency_;
PropTxPilotDeviation tx_pilot_deviation_;
PropTxLineInputLevel tx_line_input_level_;
PropTxLineInputMute tx_line_input_mute_;
PropDigitalInputFormat digital_input_format_;
PropDigitalInputSampleRate digital_input_sample_rate_;
PropRefClkFreq refclk_freq_;
PropRefClkPreScale refclk_prescale_;
PropTxAcompEnable tx_acomp_enable_;
PropTxAcompThreshold tx_acomp_threshold_;
PropTxAcompAttackTime tx_acomp_attack_time_;
PropTxAcompReleaseTime tx_acomp_release_time_;
AcompPreset tx_acomp_preset_;
PropTxAcompGain tx_acomp_gain_;
PropTxLimiterReleaseTime tx_limiter_releasee_time_;
PropTxAsqInterruptSource tx_asq_interrupt_source_;
PropTxAsqLevelLow tx_asq_level_low_;
PropTxAsqDurationLow tx_asq_duration_low_;
PropTxAsqLevelHigh tx_asq_level_high_;
PropTxAsqDurationHigh tx_asq_duration_high_;
PropTxRdsDeviation tx_rds_deviation_;
std::string rds_station_;
std::string rds_text_;
uint8_t gpio_[3];
void write_reg_(uint8_t addr);
bool read_reg_(uint8_t addr);
*/
bool send_cmd(const void *cmd, size_t cmd_size, void *res, size_t res_size);
template<typename CMD> bool send_cmd(const CMD &cmd) {
@ -64,42 +120,86 @@ class Si4713Component : public PollingComponent, public i2c::I2CDevice {
return false;
}
std::string rds_station_;
std::string rds_text_;
uint8_t rds_station_pos_;
uint8_t rds_text_pos_;
uint8_t rds_upd_;
void rds_update_(); // TODO
void rds_update_();
bool reset();
bool power_up();
bool power_down();
bool detect_chip_id();
bool tune_freq(uint16_t freq);
bool tune_power(uint8_t power, uint8_t antcap = 0);
bool stc_wait();
SUB_TEXT_SENSOR(chip_id)
// TODO: sensors TX_TUNE_STATUS / FREQ, RFuV, ANTCAP, NL
// TODO: sensors TX_ASQ_STATUS / OVERMOD, IALH, IALL, INLEVEL
SUB_NUMBER(frequency)
SUB_SWITCH(mute)
SUB_SWITCH(mono)
SUB_SWITCH(rds_enable)
SUB_TEXT(rds_station)
SUB_TEXT(rds_text)
SUB_SWITCH(gpio1)
SUB_SWITCH(gpio2)
SUB_SWITCH(gpio3)
template<class S, class T> void publish(S *s, T state);
// template specialization here is not supported by the compiler yet
void publish_switch(switch_::Switch *s, bool state);
void publish_select(select::Select *s, size_t index);
void publish_();
void publish_chip_id();
void publish_frequency();
void publish_mute();
void publish_mono();
void publish_rds_enable();
void publish_rds_station();
void publish_rds_text();
void publish_gpio(uint8_t pin);
void publish(sensor::Sensor *s, float 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);
// general config
SUB_SWITCH_EX(mute)
SUB_SWITCH_EX(mono)
SUB_SELECT_EX(pre_emphasis)
// tuner
SUB_NUMBER_EX(frequency)
SUB_NUMBER_EX(audio_deviation)
SUB_NUMBER_EX(power)
SUB_NUMBER_EX(antcap)
// analog
SUB_NUMBER_EX(analog_level)
SUB_SELECT_EX(analog_attenuation)
// digital
SUB_NUMBER_EX(digital_sample_rate)
SUB_SELECT_EX(digital_sample_bits)
SUB_SELECT_EX(digital_channels)
SUB_SELECT_EX(digital_mode)
SUB_SELECT_EX(digital_clock_edge)
// pilot
SUB_SWITCH_EX(pilot_enable)
SUB_NUMBER_EX(pilot_frequency)
SUB_NUMBER_EX(pilot_deviation)
// refclk
SUB_NUMBER_EX(refclk_frequency)
SUB_SELECT_EX(refclk_source)
SUB_NUMBER_EX(refclk_prescaler)
// compressor
SUB_SWITCH_EX(acomp_enable)
SUB_NUMBER_EX(acomp_threshold)
SUB_SELECT_EX(acomp_attack)
SUB_SELECT_EX(acomp_release)
SUB_NUMBER_EX(acomp_gain)
SUB_SELECT_EX(acomp_preset)
// limiter
SUB_SWITCH_EX(limiter_enable)
SUB_NUMBER_EX(limiter_release_time)
// asq
SUB_SWITCH_EX(asq_iall_enable)
SUB_SWITCH_EX(asq_ialh_enable)
SUB_SWITCH_EX(asq_overmod_enable)
SUB_NUMBER_EX(asq_level_low)
SUB_NUMBER_EX(asq_duration_low)
SUB_NUMBER_EX(asq_level_high)
SUB_NUMBER_EX(asq_duration_high)
// rds
SUB_SWITCH_EX(rds_enable)
SUB_NUMBER_EX(rds_deviation)
SUB_TEXT_EX(rds_station)
SUB_TEXT_EX(rds_text)
// output
SUB_SWITCH_EX(gpio1)
SUB_SWITCH_EX(gpio2)
SUB_SWITCH_EX(gpio3)
// sensors
SUB_TEXT_SENSOR_EX(chip_id)
SUB_SENSOR_EX(read_frequency)
SUB_SENSOR_EX(read_power)
SUB_SENSOR_EX(read_antcap)
SUB_SENSOR_EX(read_noise_level)
SUB_BINARY_SENSOR_EX(iall)
SUB_BINARY_SENSOR_EX(ialh)
SUB_BINARY_SENSOR_EX(overmod)
SUB_SENSOR_EX(inlevel)
void publish_gpio(uint8_t pin); // helper
public:
Si4713Component();
@ -110,27 +210,121 @@ class Si4713Component : public PollingComponent, public i2c::I2CDevice {
void update() override;
void loop() override;
bool reset();
bool power_up();
bool power_down();
bool detect_chip_id();
bool tune_freq(uint16_t freq);
bool tune_power(uint8_t power = 0, uint8_t antcap = 0);
bool tune_wait();
// non-mutable config (opmode could be)
void set_reset_pin(InternalGPIOPin *pin);
void set_frequency(float value);
float get_frequency();
void set_op_mode(OpMode value);
// config
void set_mute(bool value);
bool get_mute();
void set_mono(bool value);
bool get_mono();
void set_pre_emphasis(PreEmphasis value);
PreEmphasis get_pre_emphasis();
void set_frequency(float value);
float get_frequency();
void set_audio_deviation(float value);
float get_audio_deviation();
void set_power(int value);
int get_power();
void set_antcap(int value);
int get_antcap();
void set_analog_level(int value);
int get_analog_level();
void set_analog_attenuation(LineAttenuation value);
LineAttenuation get_analog_attenuation();
void set_digital_sample_rate(int value);
int get_digital_sample_rate();
void set_digital_sample_bits(SampleBits value);
SampleBits get_digital_sample_bits();
void set_digital_channels(SampleChannels value);
SampleChannels get_digital_channels();
void set_digital_mode(DigitalMode value);
DigitalMode get_digital_mode();
void set_digital_clock_edge(DigitalClockEdge value);
DigitalClockEdge get_digital_clock_edge();
void set_pilot_enable(bool value);
bool get_pilot_enable();
void set_pilot_frequency(float value);
float get_pilot_frequency();
void set_pilot_deviation(float value);
float get_pilot_deviation();
void set_refclk_frequency(int value);
int get_refclk_frequency();
void set_refclk_source(RefClkSource value);
RefClkSource get_refclk_source();
void set_refclk_prescaler(int value);
int get_refclk_prescaler();
void set_acomp_enable(bool value);
bool get_acomp_enable();
void set_acomp_threshold(int value);
int get_acomp_threshold();
void set_acomp_attack(AcompAttack value);
AcompAttack get_acomp_attack();
void set_acomp_release(AcompRelease value);
AcompRelease get_acomp_release();
void set_acomp_gain(int value);
int get_acomp_gain();
void set_acomp_preset(AcompPreset value);
AcompPreset get_acomp_preset();
void set_limiter_enable(bool value);
bool get_limiter_enable();
void set_limiter_release_time(float value);
float get_limiter_release_time();
void set_asq_iall_enable(bool value);
bool get_asq_iall_enable();
void set_asq_ialh_enable(bool value);
bool get_asq_ialh_enable();
void set_asq_overmod_enable(bool value);
bool get_asq_overmod_enable();
void set_asq_level_low(int value);
int get_asq_level_low();
void set_asq_duration_low(int value);
int get_asq_duration_low();
void set_asq_level_high(int value);
int get_asq_level_high();
void set_asq_duration_high(int value);
int get_asq_duration_high();
void set_rds_enable(bool value);
bool get_rds_enable();
void set_rds_deviation(float value);
float get_rds_deviation();
void set_rds_station(const std::string &value);
std::string get_rds_station();
void set_rds_text(const std::string &value);
void set_gpio(uint8_t pin, bool value);
bool get_gpio(uint8_t pin);
std::string get_rds_text();
void set_gpio(uint8_t pin, bool value); // helper
bool get_gpio(uint8_t pin); // helper
void set_gpio1(bool value);
bool get_gpio1();
void set_gpio2(bool value);
bool get_gpio2();
void set_gpio3(bool value);
bool get_gpio3();
// used by sensors
std::string get_chip_id();
float get_read_frequency();
float get_read_power();
float get_read_antcap();
float get_read_noise_level();
bool get_iall();
bool get_ialh();
bool get_overmod();
float get_inlevel();
// used by automation
void measure_freq(float value);
};
template<typename... Ts> class SetFrequencyAction : public Action<Ts...>, public Parented<Si4713Component> {
TEMPLATABLE_VALUE(float, frequency)
void play(Ts... x) override { this->parent_->set_frequency(this->frequency_.value(x...)); }
};
template<typename... Ts> class MeasureFrequencyAction : public Action<Ts...>, public Parented<Si4713Component> {
TEMPLATABLE_VALUE(float, frequency)
void play(Ts... x) override { this->parent_->measure_freq(this->frequency_.value(x...)); }
};
} // namespace si4713

View file

@ -5,11 +5,140 @@ namespace si4713 {
static const uint8_t SI4710_STATUS_CTS = 0x80;
static const float CH_FREQ_MIN = 76;
static const float CH_FREQ_MAX = 108;
static const float FREQ_MIN = 76;
static const float FREQ_MAX = 108;
static const int FREQ_RAW_MIN = 7600;
static const int FREQ_RAW_MAX = 10800;
static const int POWER_MIN = 88;
static const int POWER_MAX = 120;
static const int ANTCAP_MIN = 0;
static const int ANTCAP_MAX = 191;
static const int LILEVEL_MIN = 0;
static const int LILEVEL_MAX = 1023; // no max in the datasheet, only that it is 10 bits
static const int DISR_MIN = 32000;
static const int DISR_MAX = 48000;
static const float PILOT_FREQ_MIN = 0;
static const float PILOT_FREQ_MAX = 19;
static const int PILOT_FREQ_RAW_MIN = 0;
static const int PILOT_FREQ_RAW_MAX = 19000;
static const float TXADEV_MIN = 0;
static const float TXADEV_MAX = 90;
static const int TXADEV_RAW_MIN = 0;
static const int TXADEV_RAW_MAX = 9000;
static const float TXPDEV_MIN = 0;
static const float TXPDEV_MAX = 90;
static const int TXPDEV_RAW_MIN = 0;
static const int TXPDEV_RAW_MAX = 9000;
static const float TXRDEV_MIN = 0;
static const float TXRDEV_MAX = 7.5f;
static const int TXRDEV_RAW_MIN = 0;
static const int TXRDEV_RAW_MAX = 750;
static const int REFCLKF_MIN = 31130;
static const int REFCLKF_MAX = 34406;
static const int RCLKP_MIN = 1;
static const int RCLKP_MAX = 4095;
static const int ACOMP_THRESHOLD_MIN = -40;
static const int ACOMP_THRESHOLD_MAX = 0;
static const int ACOMP_GAIN_MIN = 0;
static const int ACOMP_GAIN_MAX = 20;
static const float ACOMP_ATTACK_MIN = 0.5f;
static const float ACOMP_ATTACK_MAX = 5.0f;
static const int ACOMP_ATTACK_RAW_MIN = 0;
static const int ACOMP_ATTACK_RAW_MAX = 9;
static const float LMITERTC_MIN = 0.25f;
static const float LMITERTC_MAX = 102.4f;
static const int LMITERTC_RAW_MIN = 5;
static const int LMITERTC_RAW_MAX = 2000;
static const int IALTH_MIN = -70;
static const int IALTH_MAX = 0;
static const int IALDUR_MIN = 0;
static const int IALDUR_MAX = 65535;
static const uint8_t RDS_STATION_MAX = 8;
static const uint8_t RDS_TEXT_MAX = 64;
static const uint8_t RDS_STATION_MAX = 8; // TODO
static const uint8_t RDS_TEXT_MAX = 64; // TODO
template<typename T> T GET_ENUM_LAST(T value) { return T::LAST; }
enum class OpMode {
OPMODE_ANALOG = 0b01010000, // 0x50
OPMODE_DIGITAL = 0b00001111, // 0x0F
LAST,
};
enum class PreEmphasis {
FMPE_75US, // USA
FMPE_50US, // EU
FMPE_DISABLED,
LAST,
};
enum class LineAttenuation {
LIATTEN_396KOHM,
LIATTEN_100KOHM,
LIATTEN_74KOHM,
LIATTEN_60KOHM,
LAST,
};
enum class SampleBits {
ISIZE_16BITS,
ISIZE_20BITS,
ISIZE_24BITS,
ISIZE_8BITS,
LAST,
};
enum class SampleChannels {
IMONO_STEREO,
IMONO_MONO,
LAST,
};
enum class DigitalMode {
IMODE_DEFAULT,
IMODE_I2S,
IMODE_LEFT_JUSTIFIED,
IMODE_MSB_AT_1ST,
IMODE_MSB_AT_2ND,
LAST,
};
enum class DigitalClockEdge {
IFALL_DCLK_RISING_EDGE,
IFALL_DCLK_FALLIBG_EDGE,
LAST,
};
enum class RefClkSource {
RCLKSEL_RCLK,
RCLKSEL_DCLK,
LAST,
};
enum class AcompAttack {
ATTACK_05MS,
ATTACK_10MS,
ATTACK_15MS,
ATTACK_20MS,
ATTACK_25MS,
ATTACK_30MS,
ATTACK_35MS,
ATTACK_40MS,
ATTACK_45MS,
ATTACK_50MS,
LAST,
};
enum class AcompRelease {
RELEASE_100MS,
RELEASE_200MS,
RELEASE_350MS,
RELEASE_525MS,
RELEASE_1000MS,
LAST,
};
enum class AcompPreset { ACOMP_MINIMAL, ACOMP_AGGRESSIVE, ACOMP_CUSTOM, LAST };
enum class CmdType : uint8_t {
POWER_UP = 0x01, // Power up device and mode selection.
@ -407,20 +536,17 @@ struct ResTxTuneMeasure : ResBase {};
struct CmdTxTuneStatus : CmdBase {
union {
uint8_t ARG[2];
uint8_t ARG[1];
struct {
// ARG1
uint8_t : 8; // zero
// ARG2
uint8_t INTACK : 1; // Seek/Tune Interrupt Clear.
uint8_t : 7;
};
};
CmdTxTuneStatus(uint8_t intack = 1) {
CmdTxTuneStatus(uint8_t intack) {
this->CMD = CmdType::TX_TUNE_STATUS;
this->ARG[0] = 0;
this->ARG[1] = 0;
this->INTACK = intack;
}
};
@ -449,20 +575,17 @@ struct ResTxTuneStatus : ResBase {
struct CmdTxAsqStatus : CmdBase {
union {
uint8_t ARG[2];
uint8_t ARG[1];
struct {
// ARG1
uint8_t : 8; // zero
// ARG2
uint8_t INTACK : 1; // Interrupt Acknowledge. Clears ASQINT, OVERMOD, IALDH, and IALDL
uint8_t : 7;
};
};
CmdTxAsqStatus(uint8_t intack = 1) {
CmdTxAsqStatus(uint8_t intack) {
this->CMD = CmdType::TX_ASQ_STATUS;
this->ARG[0] = 0;
this->ARG[1] = 0;
this->INTACK = intack;
}
};
@ -472,9 +595,9 @@ struct ResTxAsqStatus : ResBase {
uint8_t RESP[4];
struct {
// RESP1
uint8_t OVERMOD : 1; // Overmodulation Detection
uint8_t IALL : 1; // Overmodulation Detection
uint8_t IALH : 1; // Input Audio Level Threshold Detect High
uint8_t IALL : 1; // Input Audio Level Threshold Detect Low
uint8_t OVERMOD : 1; // Input Audio Level Threshold Detect Low
uint8_t : 5;
// RESP2
uint8_t : 8;
@ -673,13 +796,16 @@ struct PropDigitalInputFormat : PropBase {
};
};
PropDigitalInputFormat(uint16_t isize = 0, uint16_t imono = 0, uint16_t imode = 0, uint16_t ifall = 0) {
PropDigitalInputFormat(SampleBits isize = SampleBits::ISIZE_16BITS,
SampleChannels imono = SampleChannels::IMONO_STEREO,
DigitalMode imode = DigitalMode::IMODE_DEFAULT,
DigitalClockEdge ifall = DigitalClockEdge::IFALL_DCLK_RISING_EDGE) {
this->PROP = PropType::DIGITAL_INPUT_FORMAT;
this->PROPD = 0x0000;
this->ISIZE = isize;
this->IMONO = imono;
this->IMODE = imode;
this->IFALL = ifall;
this->ISIZE = (uint16_t) isize;
this->IMONO = (uint16_t) imono;
this->IMODE = (uint16_t) imode;
this->IFALL = (uint16_t) ifall;
}
};
@ -724,11 +850,11 @@ struct PropRefClkPreScale : PropBase {
};
};
PropRefClkPreScale(uint16_t rclkp = 1, uint16_t rclksel = 0) {
PropRefClkPreScale(uint16_t rclkp = 1, RefClkSource rclksel = RefClkSource::RCLKSEL_RCLK) {
this->PROP = PropType::REFCLK_PRESCALE;
this->PROPD = 0x0001;
this->RCLKP = rclkp;
this->RCLKSEL = rclksel;
this->RCLKSEL = (uint16_t) rclksel;
}
};
@ -805,11 +931,11 @@ struct PropTxLineInputLevel : PropBase {
};
};
PropTxLineInputLevel(uint16_t lilevel = 636, uint16_t liatten = 3) {
PropTxLineInputLevel(uint16_t lilevel = 636, LineAttenuation liatten = LineAttenuation::LIATTEN_60KOHM) {
this->PROP = PropType::TX_LINE_INPUT_LEVEL;
this->PROPD = 0x327C;
this->LILEVEL = lilevel;
this->LIATTEN = liatten;
this->LIATTEN = (uint16_t) liatten;
}
};
@ -840,10 +966,10 @@ struct PropTxPreEmphasis : PropBase {
};
};
PropTxPreEmphasis(uint16_t fmpe = 0) {
PropTxPreEmphasis(PreEmphasis fmpe = PreEmphasis::FMPE_75US) {
this->PROP = PropType::TX_PREEMPHASIS;
this->PROPD = 0x0000;
this->FMPE = fmpe;
this->FMPE = (uint16_t) fmpe;
}
};
@ -920,10 +1046,10 @@ struct PropTxAcompReleaseTime : PropBase {
};
};
PropTxAcompReleaseTime(uint16_t release = 4) {
PropTxAcompReleaseTime(AcompRelease release = AcompRelease::RELEASE_1000MS) {
this->PROP = PropType::TX_ACOMP_RELEASE_TIME;
this->PROPD = 0x0004;
this->RELEASE = release;
this->RELEASE = (uint16_t) release;
}
};
@ -978,8 +1104,8 @@ struct PropTxAsqLevelLow : PropBase {
union {
uint16_t PROPD;
struct {
uint16_t IALLTH : 8; // Input Audio Level Low Threshold (-70 to 0 dB)
uint16_t : 8;
int8_t IALLTH : 8; // Input Audio Level Low Threshold (-70 to 0 dB)
uint8_t : 8;
};
};
@ -1007,8 +1133,8 @@ struct PropTxAsqLevelHigh : PropBase {
union {
uint16_t PROPD;
struct {
uint16_t IALHTH : 8; // Input Audio Level High Threshold (-70 to 0 dB)
uint16_t : 8;
int8_t IALHTH : 8; // Input Audio Level High Threshold (-70 to 0 dB)
uint8_t : 8;
};
};

View file

@ -10,20 +10,36 @@ from .. import (
CONF_SI4713_ID,
Si4713Component,
si4713_ns,
CONF_SECTION_PILOT,
CONF_SECTION_COMPRESSOR,
CONF_SECTION_LIMITER,
CONF_SECTION_ASQ,
CONF_SECTION_RDS,
CONF_SECTION_OUTPUT,
CONF_MUTE,
CONF_MONO,
CONF_RDS_ENABLE,
CONF_ENABLE,
CONF_OVERMOD,
CONF_IALL,
CONF_IALH,
CONF_GPIO1,
CONF_GPIO2,
CONF_GPIO3,
ICON_SINE_WAVE,
ICON_VOLUME_MUTE,
ICON_EAR_HEARING,
ICON_FORMAT_TEXT,
)
CONF_GPIO1="gpio1"
CONF_GPIO2="gpio2"
CONF_GPIO3="gpio3"
MuteSwitch = si4713_ns.class_("MuteSwitch", switch.Switch)
MonoSwitch = si4713_ns.class_("MonoSwitch", switch.Switch)
PilotEnableSwitch = si4713_ns.class_("PilotEnableSwitch", switch.Switch)
AcompEnableSwitch = si4713_ns.class_("AcompEnableSwitch", switch.Switch)
LimiterEnableSwitch = si4713_ns.class_("LimiterEnableSwitch", switch.Switch)
AsqOvermodEnableSwitch = si4713_ns.class_("AsqOvermodEnableSwitch", switch.Switch)
AsqIallEnableSwitch = si4713_ns.class_("AsqIallEnableSwitch", switch.Switch)
AsqIalhEnableSwitch = si4713_ns.class_("AsqIalhEnableSwitch", switch.Switch)
RdsEnable = si4713_ns.class_("RdsEnable", switch.Switch)
RDSEnableSwitch = si4713_ns.class_("RDSEnableSwitch", switch.Switch)
GPIOSwitch = si4713_ns.class_("GPIOSwitch", switch.Switch)
@ -42,12 +58,70 @@ CONFIG_SCHEMA = cv.Schema(
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_EAR_HEARING,
),
cv.Optional(CONF_RDS_ENABLE): switch.switch_schema(
cv.Optional(CONF_SECTION_PILOT): cv.Schema(
{
cv.Optional(CONF_ENABLE): switch.switch_schema(
PilotEnableSwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_SINE_WAVE,
),
}
),
cv.Optional(CONF_SECTION_COMPRESSOR): cv.Schema(
{
cv.Optional(CONF_ENABLE): switch.switch_schema(
AcompEnableSwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_SINE_WAVE,
),
}
),
cv.Optional(CONF_SECTION_LIMITER): cv.Schema(
{
cv.Optional(CONF_ENABLE): switch.switch_schema(
LimiterEnableSwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_SINE_WAVE,
),
}
),
cv.Optional(CONF_SECTION_ASQ): cv.Schema(
{
cv.Optional(CONF_OVERMOD): switch.switch_schema(
AsqOvermodEnableSwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
# icon=ICON_,
),
cv.Optional(CONF_IALL): switch.switch_schema(
AsqIallEnableSwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
# icon=ICON_,
),
cv.Optional(CONF_IALH): switch.switch_schema(
AsqIalhEnableSwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
# icon=ICON_,
),
}
),
cv.Optional(CONF_SECTION_RDS): cv.Schema(
{
cv.Optional(CONF_ENABLE): switch.switch_schema(
RDSEnableSwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_FORMAT_TEXT,
),
}
),
cv.Optional(CONF_SECTION_OUTPUT): cv.Schema(
{
cv.Optional(CONF_GPIO1): switch.switch_schema(
GPIOSwitch,
device_class=DEVICE_CLASS_SWITCH,
@ -68,24 +142,38 @@ CONFIG_SCHEMA = cv.Schema(
),
}
)
}
)
async def new_switch(config, id, setter):
async def new_switch(parent, config, id, setter):
if c := config.get(id):
s = await switch.new_switch(c)
await cg.register_parented(s, config[CONF_SI4713_ID])
await cg.register_parented(s, parent)
cg.add(setter(s))
return s
async def to_code(config):
c = await cg.get_variable(config[CONF_SI4713_ID])
await new_switch(config, CONF_MUTE, c.set_mute_switch)
await new_switch(config, CONF_MONO, c.set_mono_switch)
await new_switch(config, CONF_RDS_ENABLE, c.set_rds_enable_switch)
s = await new_switch(config, CONF_GPIO1, c.set_gpio1_switch)
s.set_pin(1)
s = await new_switch(config, CONF_GPIO2, c.set_gpio2_switch)
s.set_pin(2)
s = await new_switch(config, CONF_GPIO3, c.set_gpio3_switch)
s.set_pin(3)
parent = await cg.get_variable(config[CONF_SI4713_ID])
await new_switch(parent, config, CONF_MUTE, parent.set_mute_switch)
await new_switch(parent, config, CONF_MONO, parent.set_mono_switch)
if pilot_config := config.get(CONF_SECTION_PILOT):
await new_switch(parent, pilot_config, CONF_ENABLE, parent.set_pilot_enable_switch)
if compressor_config := config.get(CONF_SECTION_COMPRESSOR):
await new_switch(parent, compressor_config, CONF_ENABLE, parent.set_acomp_enable_switch)
if limiter_config := config.get(CONF_SECTION_LIMITER):
await new_switch(parent, limiter_config, CONF_ENABLE, parent.set_limiter_enable_switch)
if asq_config := config.get(CONF_SECTION_ASQ):
await new_switch(parent, asq_config, CONF_IALL, parent.set_asq_iall_enable_switch)
await new_switch(parent, asq_config, CONF_IALH, parent.set_asq_ialh_enable_switch)
await new_switch(parent, asq_config, CONF_OVERMOD, parent.set_asq_overmod_enable_switch)
if rds_config := config.get(CONF_SECTION_RDS):
await new_switch(parent, rds_config, CONF_ENABLE, parent.set_rds_enable_switch)
if output_config := config.get(CONF_SECTION_OUTPUT):
gpio1 = await new_switch(parent, output_config, CONF_GPIO1, parent.set_gpio1_switch)
gpio2 = await new_switch(parent, output_config, CONF_GPIO2, parent.set_gpio2_switch)
gpio3 = await new_switch(parent, output_config, CONF_GPIO3, parent.set_gpio3_switch)
cg.add(gpio1.set_pin(1))
cg.add(gpio2.set_pin(2))
cg.add(gpio3.set_pin(3))

View file

@ -0,0 +1,12 @@
#include "acomp_enable_switch.h"
namespace esphome {
namespace si4713 {
void AcompEnableSwitch::write_state(bool value) {
this->publish_state(value);
this->parent_->set_acomp_enable(value);
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class AcompEnableSwitch : public switch_::Switch, public Parented<Si4713Component> {
public:
AcompEnableSwitch() = default;
protected:
void write_state(bool value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,12 @@
#include "asq_ialh_enable_switch.h"
namespace esphome {
namespace si4713 {
void AsqIalhEnableSwitch::write_state(bool value) {
this->publish_state(value);
this->parent_->set_asq_ialh_enable(value);
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class AsqIalhEnableSwitch : public switch_::Switch, public Parented<Si4713Component> {
public:
AsqIalhEnableSwitch() = default;
protected:
void write_state(bool value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,12 @@
#include "asq_iall_enable_switch.h"
namespace esphome {
namespace si4713 {
void AsqIallEnableSwitch::write_state(bool value) {
this->publish_state(value);
this->parent_->set_asq_iall_enable(value);
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class AsqIallEnableSwitch : public switch_::Switch, public Parented<Si4713Component> {
public:
AsqIallEnableSwitch() = default;
protected:
void write_state(bool value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,12 @@
#include "asq_overmod_enable_switch.h"
namespace esphome {
namespace si4713 {
void AsqOvermodEnableSwitch::write_state(bool value) {
this->publish_state(value);
this->parent_->set_asq_overmod_enable(value);
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class AsqOvermodEnableSwitch : public switch_::Switch, public Parented<Si4713Component> {
public:
AsqOvermodEnableSwitch() = default;
protected:
void write_state(bool value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,12 @@
#include "limiter_enable_switch.h"
namespace esphome {
namespace si4713 {
void LimiterEnableSwitch::write_state(bool value) {
this->publish_state(value);
this->parent_->set_limiter_enable(value);
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class LimiterEnableSwitch : public switch_::Switch, public Parented<Si4713Component> {
public:
LimiterEnableSwitch() = default;
protected:
void write_state(bool value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,12 @@
#include "pilot_enable_switch.h"
namespace esphome {
namespace si4713 {
void PilotEnableSwitch::write_state(bool value) {
this->publish_state(value);
this->parent_->set_pilot_enable(value);
}
} // namespace si4713
} // namespace esphome

View file

@ -0,0 +1,18 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../si4713.h"
namespace esphome {
namespace si4713 {
class PilotEnableSwitch : public switch_::Switch, public Parented<Si4713Component> {
public:
PilotEnableSwitch() = default;
protected:
void write_state(bool value) override;
};
} // namespace si4713
} // namespace esphome

View file

@ -18,8 +18,9 @@ from .. import (
CONF_SI4713_ID,
Si4713Component,
si4713_ns,
CONF_RDS_STATION,
CONF_RDS_TEXT,
CONF_SECTION_RDS,
CONF_STATION,
CONF_TEXT,
ICON_FORMAT_TEXT,
)
@ -123,32 +124,38 @@ async def new_text(
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(CONF_SI4713_ID): cv.use_id(Si4713Component),
cv.Optional(CONF_RDS_STATION): text_schema(
cv.Optional(CONF_SECTION_RDS): cv.Schema(
{
cv.Optional(CONF_STATION): text_schema(
RDSStationText,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_FORMAT_TEXT,
),
cv.Optional(CONF_RDS_TEXT): text_schema(
cv.Optional(CONF_TEXT): text_schema(
RDSTextText,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_FORMAT_TEXT,
),
}
),
}
)
async def new_text_simple(config, id, setter, min_length, max_length, *args):
async def new_text_simple(parent, config, id, setter, min_length, max_length, *args):
if c := config.get(id):
t = await new_text(c, *args, min_length=min_length, max_length=max_length)
await cg.register_parented(t, config[CONF_SI4713_ID])
await cg.register_parented(t, parent)
cg.add(setter(t))
return t
async def to_code(config):
c = await cg.get_variable(config[CONF_SI4713_ID])
parent = await cg.get_variable(config[CONF_SI4713_ID])
if rds_config := config.get(CONF_SECTION_RDS):
await new_text_simple(
config, CONF_RDS_STATION, c.set_rds_station_text, 0, si4713_ns.RDS_STATION_MAX
parent, rds_config, CONF_STATION, parent.set_rds_station_text, 0, si4713_ns.RDS_STATION_MAX
)
await new_text_simple(
config, CONF_RDS_TEXT, c.set_rds_text_text, 0, si4713_ns.RDS_TEXT_MAX
parent, rds_config, CONF_TEXT, parent.set_rds_text_text, 0, si4713_ns.RDS_TEXT_MAX
)