mirror of
https://github.com/esphome/esphome.git
synced 2026-10-22 05:46:12 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05e8b431ef | ||
|
|
bdc0b23e84 |
@@ -11,7 +11,52 @@ ESPHOME_LOG_TAG(TAG, "apds9960");
|
||||
this->mark_failed(LOG_STR("Setting up APDS9960 registers failed")); \
|
||||
return; \
|
||||
}
|
||||
#define APDS9960_WRITE_BYTE(reg, value) APDS9960_ERROR_CHECK(this->write_byte(reg, value));
|
||||
|
||||
static constexpr i2c::I2CRegValue APDS9960_TIMING[] PROGMEM = {
|
||||
// ATime (ADC integration time, 2.78ms increments, 0x81) -> 0xDB (103ms)
|
||||
{0x81, 0xDB},
|
||||
// WTime (Wait time, 0x83) -> 0xF6 (27ms)
|
||||
{0x83, 0xF6},
|
||||
// PPulse (0x8E) -> 0x87 (16us, 8 pulses)
|
||||
{0x8E, 0x87},
|
||||
// POffset UR (0x9D) -> 0 (no offset)
|
||||
{0x9D, 0x00},
|
||||
// POffset DL (0x9E) -> 0 (no offset)
|
||||
{0x9E, 0x00},
|
||||
// Config 1 (0x8D) -> 0x60 (no wtime factor)
|
||||
{0x8D, 0x60},
|
||||
};
|
||||
|
||||
static constexpr i2c::I2CRegValue APDS9960_INTERRUPT_GESTURE[] PROGMEM = {
|
||||
// Pers (0x8C) -> 0x11 (2 consecutive proximity or ALS for interrupt)
|
||||
{0x8C, 0x11},
|
||||
// Config 2 (0x90) -> 0x01 (no saturation interrupts or LED boost)
|
||||
{0x90, 0x01},
|
||||
// Config 3 (0x9F) -> 0x00 (enable all photodiodes, no SAI)
|
||||
{0x9F, 0x00},
|
||||
// GPenTh (0xA0, gesture enter threshold) -> 0x28 (also 0x32)
|
||||
{0xA0, 0x28},
|
||||
// GPexTh (0xA1, gesture exit threshold) -> 0x1E
|
||||
{0xA1, 0x1E},
|
||||
// GConf 1 (0xA2, gesture config 1) -> 0x40 (4 gesture events for interrupt (GFIFO 3), 1 for exit)
|
||||
{0xA2, 0x40},
|
||||
};
|
||||
|
||||
static constexpr i2c::I2CRegValue APDS9960_GESTURE_OFFSETS[] PROGMEM = {
|
||||
// GOffsetU (0xA4) -> 0x00 (no offset)
|
||||
{0xA4, 0x00},
|
||||
// GOffsetD (0xA5) -> 0x00 (no offset)
|
||||
{0xA5, 0x00},
|
||||
// GOffsetL (0xA7) -> 0x00 (no offset)
|
||||
{0xA7, 0x00},
|
||||
// GOffsetR (0xA9) -> 0x00 (no offset)
|
||||
{0xA9, 0x00},
|
||||
// GPulse (0xA6) -> 0xC9 (32 µs, 10 pulses)
|
||||
{0xA6, 0xC9},
|
||||
// GConf 3 (0xAA, gesture config 3) -> 0x00 (all photodiodes active during gesture, all gesture dimensions enabled)
|
||||
// 0x00 -> all dimensions, 0x01 -> up down, 0x02 -> left right
|
||||
{0xAA, 0x00},
|
||||
};
|
||||
|
||||
void APDS9960::setup() {
|
||||
uint8_t id;
|
||||
@@ -25,83 +70,27 @@ void APDS9960::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
// ATime (ADC integration time, 2.78ms increments, 0x81) -> 0xDB (103ms)
|
||||
APDS9960_WRITE_BYTE(0x81, 0xDB);
|
||||
// WTime (Wait time, 0x83) -> 0xF6 (27ms)
|
||||
APDS9960_WRITE_BYTE(0x83, 0xF6);
|
||||
// PPulse (0x8E) -> 0x87 (16us, 8 pulses)
|
||||
APDS9960_WRITE_BYTE(0x8E, 0x87);
|
||||
// POffset UR (0x9D) -> 0 (no offset)
|
||||
APDS9960_WRITE_BYTE(0x9D, 0x00);
|
||||
// POffset DL (0x9E) -> 0 (no offset)
|
||||
APDS9960_WRITE_BYTE(0x9E, 0x00);
|
||||
// Config 1 (0x8D) -> 0x60 (no wtime factor)
|
||||
APDS9960_WRITE_BYTE(0x8D, 0x60);
|
||||
APDS9960_ERROR_CHECK(this->write_registers(APDS9960_TIMING));
|
||||
|
||||
// Control (0x8F) ->
|
||||
uint8_t val = 0;
|
||||
APDS9960_ERROR_CHECK(this->read_byte(0x8F, &val));
|
||||
val &= 0b00111111;
|
||||
// led drive, 0 -> 100mA, 1 -> 50mA, 2 -> 25mA, 3 -> 12.5mA
|
||||
val |= (this->led_drive_ & 0b11) << 6;
|
||||
// Control (0x8F): led drive (0 -> 100mA, 1 -> 50mA, 2 -> 25mA, 3 -> 12.5mA),
|
||||
// proximity gain (0 -> 1x, 1 -> 2X, 2 -> 4X, 3 -> 8X), ambient light gain (0 -> 1x, 1 -> 4x, 2 -> 16x, 3 -> 64x)
|
||||
APDS9960_ERROR_CHECK(this->update_register(
|
||||
0x8F, 0b11001111,
|
||||
(this->led_drive_ & 0b11) << 6 | (this->proximity_gain_ & 0b11) << 2 | (this->ambient_gain_ & 0b11)));
|
||||
|
||||
val &= 0b11110011;
|
||||
// proximity gain, 0 -> 1x, 1 -> 2X, 2 -> 4X, 3 -> 8X
|
||||
val |= (this->proximity_gain_ & 0b11) << 2;
|
||||
APDS9960_ERROR_CHECK(this->write_registers(APDS9960_INTERRUPT_GESTURE));
|
||||
|
||||
val &= 0b11111100;
|
||||
// ambient light gain, 0 -> 1x, 1 -> 4x, 2 -> 16x, 3 -> 64x
|
||||
val |= (this->ambient_gain_ & 0b11) << 0;
|
||||
APDS9960_WRITE_BYTE(0x8F, val);
|
||||
// GConf 2 (0xA3): gesture gain (0 -> 1x, 1 -> 2x, 2 -> 4x, 3 -> 8x),
|
||||
// gesture led drive (0 -> 100mA, 1 -> 50mA, 2 -> 25mA, 3 -> 12.5mA), gesture wait time
|
||||
// (0 -> 0ms, 1 -> 2.8ms, 2 -> 5.6ms, 3 -> 8.4ms, 4 -> 14.0ms, 5 -> 22.4 ms, 6 -> 30.8ms, 7 -> 39.2 ms)
|
||||
APDS9960_ERROR_CHECK(this->update_register(
|
||||
0xA3, 0b01111111,
|
||||
(this->gesture_gain_ & 0b11) << 5 | (this->gesture_led_drive_ & 0b11) << 3 | (this->gesture_wait_time_ & 0b111)));
|
||||
|
||||
// Pers (0x8C) -> 0x11 (2 consecutive proximity or ALS for interrupt)
|
||||
APDS9960_WRITE_BYTE(0x8C, 0x11);
|
||||
// Config 2 (0x90) -> 0x01 (no saturation interrupts or LED boost)
|
||||
APDS9960_WRITE_BYTE(0x90, 0x01);
|
||||
// Config 3 (0x9F) -> 0x00 (enable all photodiodes, no SAI)
|
||||
APDS9960_WRITE_BYTE(0x9F, 0x00);
|
||||
// GPenTh (0xA0, gesture enter threshold) -> 0x28 (also 0x32)
|
||||
APDS9960_WRITE_BYTE(0xA0, 0x28);
|
||||
// GPexTh (0xA1, gesture exit threshold) -> 0x1E
|
||||
APDS9960_WRITE_BYTE(0xA1, 0x1E);
|
||||
|
||||
// GConf 1 (0xA2, gesture config 1) -> 0x40 (4 gesture events for interrupt (GFIFO 3), 1 for exit)
|
||||
APDS9960_WRITE_BYTE(0xA2, 0x40);
|
||||
|
||||
// GConf 2 (0xA3, gesture config 2) ->
|
||||
APDS9960_ERROR_CHECK(this->read_byte(0xA3, &val));
|
||||
val &= 0b10011111;
|
||||
// gesture gain, 0 -> 1x, 1 -> 2x, 2 -> 4x, 3 -> 8x
|
||||
val |= (this->gesture_gain_ & 0b11) << 5;
|
||||
|
||||
val &= 0b11100111;
|
||||
// gesture led drive, 0 -> 100mA, 1 -> 50mA, 2 -> 25mA, 3 -> 12.5mA
|
||||
val |= (this->gesture_led_drive_ & 0b11) << 3;
|
||||
|
||||
val &= 0b11111000;
|
||||
// gesture wait time
|
||||
// 0 -> 0ms, 1 -> 2.8ms, 2 -> 5.6ms, 3 -> 8.4ms
|
||||
// 4 -> 14.0ms, 5 -> 22.4 ms, 6 -> 30.8ms, 7 -> 39.2 ms
|
||||
val |= (this->gesture_wait_time_ & 0b111) << 0;
|
||||
APDS9960_WRITE_BYTE(0xA3, val);
|
||||
|
||||
// GOffsetU (0xA4) -> 0x00 (no offset)
|
||||
APDS9960_WRITE_BYTE(0xA4, 0x00);
|
||||
// GOffsetD (0xA5) -> 0x00 (no offset)
|
||||
APDS9960_WRITE_BYTE(0xA5, 0x00);
|
||||
// GOffsetL (0xA7) -> 0x00 (no offset)
|
||||
APDS9960_WRITE_BYTE(0xA7, 0x00);
|
||||
// GOffsetR (0xA9) -> 0x00 (no offset)
|
||||
APDS9960_WRITE_BYTE(0xA9, 0x00);
|
||||
// GPulse (0xA6) -> 0xC9 (32 µs, 10 pulses)
|
||||
APDS9960_WRITE_BYTE(0xA6, 0xC9);
|
||||
|
||||
// GConf 3 (0xAA, gesture config 3) -> 0x00 (all photodiodes active during gesture, all gesture dimensions enabled)
|
||||
// 0x00 -> all dimensions, 0x01 -> up down, 0x02 -> left right
|
||||
APDS9960_WRITE_BYTE(0xAA, 0x00);
|
||||
APDS9960_ERROR_CHECK(this->write_registers(APDS9960_GESTURE_OFFSETS));
|
||||
|
||||
// Enable (0x80) ->
|
||||
val = 0;
|
||||
uint8_t val = 0;
|
||||
val |= (0b1) << 0; // power on
|
||||
val |= (this->is_color_enabled_() & 0b1) << 1;
|
||||
val |= (this->is_proximity_enabled_() & 0b1) << 2;
|
||||
@@ -109,7 +98,7 @@ void APDS9960::setup() {
|
||||
val |= 0b0 << 4; // color interrupt disabled
|
||||
val |= 0b0 << 5; // proximity interrupt disabled
|
||||
val |= (this->is_gesture_enabled_() & 0b1) << 6; // proximity is required for gestures
|
||||
APDS9960_WRITE_BYTE(0x80, val);
|
||||
APDS9960_ERROR_CHECK(this->write_byte(0x80, val));
|
||||
}
|
||||
bool APDS9960::is_color_enabled_() const {
|
||||
#ifdef USE_SENSOR
|
||||
|
||||
@@ -20,6 +20,23 @@ ESPHOME_LOG_TAG(TAG, "es8311");
|
||||
return false; \
|
||||
}
|
||||
|
||||
static constexpr i2c::I2CRegValue ES8311_POWER_UP[] PROGMEM = {
|
||||
// Power up analog circuitry
|
||||
{ES8311_REG0D_SYSTEM, 0x01},
|
||||
// Enable analog PGA, enable ADC modulator
|
||||
{ES8311_REG0E_SYSTEM, 0x02},
|
||||
// Power up DAC
|
||||
{ES8311_REG12_SYSTEM, 0x00},
|
||||
// Enable output to HP drive
|
||||
{ES8311_REG13_SYSTEM, 0x10},
|
||||
// ADC Equalizer bypass, cancel DC offset in digital domain
|
||||
{ES8311_REG1C_ADC, 0x6A},
|
||||
// Bypass DAC equalizer
|
||||
{ES8311_REG37_DAC, 0x08},
|
||||
// Power On
|
||||
{ES8311_REG00_RESET, 0x80},
|
||||
};
|
||||
|
||||
void ES8311::setup() {
|
||||
// Reset
|
||||
ES8311_ERROR_FAILED(this->write_byte(ES8311_REG00_RESET, 0x1F));
|
||||
@@ -32,20 +49,7 @@ void ES8311::setup() {
|
||||
// Set initial volume
|
||||
this->set_volume(0.75); // 0.75 = 0xBF = 0dB
|
||||
|
||||
// Power up analog circuitry
|
||||
ES8311_ERROR_FAILED(this->write_byte(ES8311_REG0D_SYSTEM, 0x01));
|
||||
// Enable analog PGA, enable ADC modulator
|
||||
ES8311_ERROR_FAILED(this->write_byte(ES8311_REG0E_SYSTEM, 0x02));
|
||||
// Power up DAC
|
||||
ES8311_ERROR_FAILED(this->write_byte(ES8311_REG12_SYSTEM, 0x00));
|
||||
// Enable output to HP drive
|
||||
ES8311_ERROR_FAILED(this->write_byte(ES8311_REG13_SYSTEM, 0x10));
|
||||
// ADC Equalizer bypass, cancel DC offset in digital domain
|
||||
ES8311_ERROR_FAILED(this->write_byte(ES8311_REG1C_ADC, 0x6A));
|
||||
// Bypass DAC equalizer
|
||||
ES8311_ERROR_FAILED(this->write_byte(ES8311_REG37_DAC, 0x08));
|
||||
// Power On
|
||||
ES8311_ERROR_FAILED(this->write_byte(ES8311_REG00_RESET, 0x80));
|
||||
ES8311_ERROR_FAILED(this->write_registers(ES8311_POWER_UP));
|
||||
}
|
||||
|
||||
void ES8311::dump_config() {
|
||||
|
||||
@@ -173,25 +173,11 @@ float ES8388::volume() {
|
||||
}
|
||||
|
||||
bool ES8388::set_mute_state_(bool mute_state) {
|
||||
uint8_t value = 0;
|
||||
|
||||
this->is_muted_ = mute_state;
|
||||
|
||||
ES8388_ERROR_CHECK(this->read_byte(ES8388_DACCONTROL3, &value));
|
||||
ESP_LOGV(TAG, "Read ES8388_DACCONTROL3: 0x%02X", value);
|
||||
|
||||
// Only toggle the DACMute bit; the other bits of this register hold unrelated
|
||||
// DAC settings that must be preserved. Previously muting overwrote the whole
|
||||
// register with 0x3C and unmuting never cleared the bit, so once muted the DAC
|
||||
// could not be unmuted again.
|
||||
if (mute_state) {
|
||||
value |= ES8388_DACCONTROL3_DAC_MUTE;
|
||||
} else {
|
||||
value &= ~ES8388_DACCONTROL3_DAC_MUTE;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Setting ES8388_DACCONTROL3 to 0x%02X (muted: %s)", value, YESNO(mute_state));
|
||||
return this->write_byte(ES8388_DACCONTROL3, value);
|
||||
// Only toggle the DACMute bit; the other bits of this register hold unrelated DAC settings
|
||||
return this->update_register(ES8388_DACCONTROL3, ES8388_DACCONTROL3_DAC_MUTE,
|
||||
mute_state ? ES8388_DACCONTROL3_DAC_MUTE : 0);
|
||||
}
|
||||
|
||||
// Set dac power output
|
||||
|
||||
@@ -286,9 +286,7 @@ bool FUSB302B::reset_pd_() {
|
||||
}
|
||||
|
||||
bool FUSB302B::enable_auto_crc_() {
|
||||
uint8_t switches1 = 0;
|
||||
return this->read_byte(FUSB_SWITCHES1, &switches1) &&
|
||||
this->write_byte(FUSB_SWITCHES1, switches1 | FUSB_SWITCHES1_AUTO_CRC);
|
||||
return this->update_register(FUSB_SWITCHES1, FUSB_SWITCHES1_AUTO_CRC, FUSB_SWITCHES1_AUTO_CRC);
|
||||
}
|
||||
|
||||
void FUSB302B::handle_interrupt_() {
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace esphome::tas58xx {
|
||||
|
||||
// Remainder of the startup sequence from TI PurePath Console, run after the reset. Register 0x00 selects the page.
|
||||
// Registers 0x46, 0x7D, 0x7E and page 1 register 0x51 are not documented in the datasheet.
|
||||
static const uint8_t STARTUP_SEQUENCE[][2] PROGMEM = {
|
||||
static constexpr i2c::I2CRegValue STARTUP_SEQUENCE[] PROGMEM = {
|
||||
{0x03, 0x00}, // DEVICE_CTRL_2: deep sleep
|
||||
{0x46, 0x01},
|
||||
{0x03, 0x02}, // DEVICE_CTRL_2: Hi-Z
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace esphome::tas58xx {
|
||||
// Remainder of the startup sequence, run after the reset in TAS58xx::init_(). Register 0x00 selects the page.
|
||||
// Based on the TI PurePath Console (PPC) export for "TAS5825M 2-Band DRC&AGL 2.0 96k".
|
||||
// Registers 0x46, 0x7D, 0x7E, page 1 register 0x51 and page 2 registers 0x1D, 0x19 are not documented in datasheet.
|
||||
static const uint8_t STARTUP_SEQUENCE[][2] PROGMEM = {
|
||||
static constexpr i2c::I2CRegValue STARTUP_SEQUENCE[] PROGMEM = {
|
||||
{0x03, 0x00}, // DEVICE_CTRL_2: deep sleep, the state the PPC sequence starts from
|
||||
{0x7D, 0x11},
|
||||
{0x7E, 0xFF},
|
||||
|
||||
@@ -91,12 +91,9 @@ bool TAS58xx::init_() {
|
||||
}
|
||||
delay(RESET_SETTLE_MS);
|
||||
|
||||
for (uint8_t i = 0; i < this->model_->startup_sequence_length; i++) {
|
||||
const uint8_t *entry = this->model_->startup_sequence[i];
|
||||
if (!this->write_byte(progmem_read_byte(&entry[0]), progmem_read_byte(&entry[1]))) {
|
||||
ESP_LOGE(TAG, "I2C write failed during init");
|
||||
return false;
|
||||
}
|
||||
if (!this->write_registers(this->model_->startup_sequence, this->model_->startup_sequence_length)) {
|
||||
ESP_LOGE(TAG, "I2C write failed during init");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setters are public, so keep the value inside the register range
|
||||
|
||||
@@ -70,7 +70,7 @@ static constexpr uint8_t NO_BIT = 0xFF;
|
||||
struct ModelInfo {
|
||||
const LogString *(*name)();
|
||||
/// Remainder of the startup sequence, run after the reset, as {register, value} pairs in PROGMEM
|
||||
const uint8_t (*startup_sequence)[2];
|
||||
const i2c::I2CRegValue *startup_sequence;
|
||||
uint8_t startup_sequence_length;
|
||||
/// Location of the four 9.23 fixed point input mixer coefficients: LEFT_TO_LEFT, RIGHT_TO_LEFT, LEFT_TO_RIGHT,
|
||||
/// RIGHT_TO_RIGHT
|
||||
|
||||
Reference in New Issue
Block a user