1
0
mirror of https://github.com/esphome/esphome.git synced 2025-03-15 15:18:16 +00:00

added all options for breathe and blink

fixed var namings
This commit is contained in:
Michiel van Turnhout 2019-06-02 10:14:35 +02:00
parent e2937430a0
commit 4748c355d0
5 changed files with 104 additions and 91 deletions

View File

@ -8,8 +8,9 @@ CONF_ON_TIME = 'on_time'
CONF_OFF_TIME = 'off_time'
CONF_RISE_TIME = 'rise_time'
CONF_FALL_TIME = 'fall_time'
CONF_ON_INT = 'on_intemsity'
CONF_ON_INT = 'on_intensity'
CONF_OFF_INT = 'off_intensity'
CONF_FADING_MODE = 'fading_mode'
DEPENDENCIES = ['i2c']
MULTI_CONF = True
@ -23,6 +24,10 @@ SX1509_GPIO_MODES = {
'BREATHE_OUTPUT': SX1509GPIOMode.SX1509_BREATHE_OUTPUT,
'BLINK_OUTPUT': SX1509GPIOMode.SX1509_BLINK_OUTPUT
}
SX1509_FADING_MODES = {
'LINEAR': SX1509GPIOMode.SX1509_FADING_LINEAR,
'LOGARITHMIC': SX1509GPIOMode.SX1509_FADING_LOGARITHMIC
}
SX1509Component = sx1509_ns.class_('SX1509Component', cg.Component, i2c.I2CDevice)
SX1509GPIOPin = sx1509_ns.class_('SX1509GPIOPin', cg.GPIOPin)
@ -44,6 +49,7 @@ SX1509_OUTPUT_PIN_SCHEMA = cv.Schema({
cv.Required(CONF_NUMBER): cv.int_,
cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum(SX1509_GPIO_MODES, upper=True),
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
cv.Optional(CONF_FADING_MODE, default="LINEAR"): cv.enum(SX1509_FADING_MODES, upper=True),
cv.Optional(CONF_ON_TIME, default=500): cv.int_,
cv.Optional(CONF_OFF_TIME, default=500): cv.int_,
cv.Optional(CONF_RISE_TIME, default=500): cv.int_,
@ -65,6 +71,6 @@ def sx1509_pin_to_code(config):
if(config[CONF_MODE] == 'BREATHE_OUTPUT' or config[CONF_MODE] == 'BLINK_OUTPUT'):
yield SX1509GPIOPin.new(parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED],
config[CONF_ON_TIME], config[CONF_OFF_TIME],
config[CONF_RISE_TIME], config[CONF_FALL_TIME])
config[CONF_RISE_TIME], config[CONF_FALL_TIME],config[CONF_FADING_MODE])
else:
yield SX1509GPIOPin.new(parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED])

View File

@ -107,11 +107,11 @@ void SX1509Component::pin_mode(uint8_t pin, uint8_t mode) {
digital_write(pin, HIGH);
if (mode == ANALOG_OUTPUT) {
led_driver_init(pin);
setup_led_driver(pin);
}
}
void SX1509Component::led_driver_init(uint8_t pin, uint8_t freq, bool log) {
void SX1509Component::setup_led_driver(uint8_t pin, uint8_t freq, bool log) {
uint16_t temp_word;
uint8_t temp_byte;
@ -141,9 +141,9 @@ void SX1509Component::led_driver_init(uint8_t pin, uint8_t freq, bool log) {
temp_byte &= ~(1 << 3); // set linear mode bank A
}
if (_clkX == 0) // Make clckX non-zero
if (clk_x_ == 0) // Make clckX non-zero
{
_clkX = 2000000.0 / (1 << (1 - 1)); // Update private clock variable
clk_x_ = 2000000.0 / (1 << (1 - 1)); // Update private clock variable
uint8_t freq = (1 & 0x07) << 4; // freq should only be 3 bits from 6:4
temp_byte |= freq;
@ -159,7 +159,7 @@ void SX1509Component::led_driver_init(uint8_t pin, uint8_t freq, bool log) {
this->write_byte_16(REG_DATA_B, temp_word);
}
void SX1509Component::breathe(uint8_t pin, uint16_t t_on, uint16_t t_off,uint16_t t_rise,
void SX1509Component::setup_breathe(uint8_t pin, uint16_t t_on, uint16_t t_off,uint16_t t_rise,
uint16_t t_fall, uint8_t on_intensity, uint8_t off_intensity, bool log) {
off_intensity = constrain(off_intensity, 0, 7);
@ -174,93 +174,89 @@ void SX1509Component::breathe(uint8_t pin, uint16_t t_on, uint16_t t_off,uint16_
void SX1509Component::setup_blink(uint8_t pin, uint8_t t_on, uint8_t t_off, uint8_t on_intensity, uint8_t off_intensity,
uint8_t t_rise, uint8_t t_fall, bool log) {
led_driver_init(pin, log);
setup_led_driver(pin, log);
t_on &= 0x1F; // t_on should be a 5-bit value
t_off &= 0x1F; // t_off should be a 5-bit value
off_intensity &= 0x07;
// Write the time on
this->write_byte(REG_T_ON[pin], t_on);
this->write_byte(REG_OFF[pin], (t_off << 3) | off_intensity);
this->write_byte(REG_I_ON[pin], on_intensity);
t_rise &= 0x1F;
t_fall &= 0x1F;
if (REG_T_RISE[pin] != 0xFF)
this->write_byte(REG_T_RISE[pin], t_rise);
if (REG_T_FALL[pin] != 0xFF)
this->write_byte(REG_T_FALL[pin], t_fall);
}
void SX1509Component::clock(byte oscSource, byte oscPinFunction, byte oscFreqOut, byte oscDivider) {
oscSource = (oscSource & 0b11) << 5; // 2-bit value, bits 6:5
oscPinFunction = (oscPinFunction & 1) << 4; // 1-bit value bit 4
oscFreqOut = (oscFreqOut & 0b1111); // 4-bit value, bits 3:0
byte regClock = oscSource | oscPinFunction | oscFreqOut;
this->write_byte(REG_CLOCK, regClock);
void SX1509Component::clock(byte osc_source, byte osc_pin_function, byte osc_freq_out, byte osc_divider) {
osc_source = (osc_source & 0b11) << 5; // 2-bit value, bits 6:5
osc_pin_function = (osc_pin_function & 1) << 4; // 1-bit value bit 4
osc_freq_out = (osc_freq_out & 0b1111); // 4-bit value, bits 3:0
byte reg_clock = osc_source | osc_pin_function | osc_freq_out;
this->write_byte(REG_CLOCK, reg_clock);
oscDivider = constrain(oscDivider, 1, 7);
_clkX = 2000000.0 / (1 << (oscDivider - 1)); // Update private clock variable
oscDivider = (oscDivider & 0b111) << 4; // 3-bit value, bits 6:4
osc_divider = constrain(osc_divider, 1, 7);
clk_x_ = 2000000.0 / (1 << (osc_divider - 1)); // Update private clock variable
osc_divider = (osc_divider & 0b111) << 4; // 3-bit value, bits 6:4
uint8_t regMisc;
this->read_byte(REG_MISC, &regMisc);
regMisc &= ~(0b111 << 4);
regMisc |= oscDivider;
this->write_byte(REG_MISC, regMisc);
uint8_t reg_misc;
this->read_byte(REG_MISC, &reg_misc);
reg_misc &= ~(0b111 << 4);
reg_misc |= osc_divider;
this->write_byte(REG_MISC, reg_misc);
}
void SX1509Component::set_pin_value_(uint8_t pin, uint8_t iOn) {
ESP_LOGD(TAG, "set_pin_value_ for pin %d to %d", pin, iOn);
this->write_byte(REG_I_ON[pin], iOn);
void SX1509Component::set_pin_value_(uint8_t pin, uint8_t i_on) {
ESP_LOGD(TAG, "set_pin_value_ for pin %d to %d", pin, i_on);
this->write_byte(REG_I_ON[pin], i_on);
}
uint8_t SX1509Component::calculate_led_t_register(uint16_t ms) {
uint16_t regOn1, regOn2;
uint16_t reg_on_1, reg_on_2;
float timeOn1, timeOn2;
if (_clkX == 0)
if (clk_x_ == 0)
return 0;
regOn1 = (float) (ms / 1000.0) / (64.0 * 255.0 / (float) _clkX);
regOn2 = regOn1 / 8;
regOn1 = constrain(regOn1, 1, 15);
regOn2 = constrain(regOn2, 16, 31);
timeOn1 = 64.0 * regOn1 * 255.0 / _clkX * 1000.0;
timeOn2 = 512.0 * regOn2 * 255.0 / _clkX * 1000.0;
reg_on_1 = (float) (ms / 1000.0) / (64.0 * 255.0 / (float) clk_x_);
reg_on_2 = reg_on_1 / 8;
reg_on_1 = constrain(reg_on_1, 1, 15);
reg_on_2 = constrain(reg_on_2, 16, 31);
timeOn1 = 64.0 * reg_on_1 * 255.0 / clk_x_ * 1000.0;
timeOn2 = 512.0 * reg_on_2 * 255.0 / clk_x_ * 1000.0;
if (abs(timeOn1 - ms) < abs(timeOn2 - ms))
return regOn1;
return reg_on_1;
else
return regOn2;
return reg_on_2;
}
uint8_t SX1509Component::calculate_slope_register(uint16_t ms, uint8_t onIntensity, uint8_t offIntensity) {
uint16_t regSlope1, regSlope2;
float regTime1, regTime2;
if (_clkX == 0)
uint8_t SX1509Component::calculate_slope_register(uint16_t ms, uint8_t on_intensity, uint8_t off_intensity) {
uint16_t reg_slope_1, reg_slope_2;
float reg_time_1, reg_time_2;
if (clk_x_ == 0)
return 0;
float tFactor = ((float) onIntensity - (4.0 * (float) offIntensity)) * 255.0 / (float) _clkX;
float timeS = float(ms) / 1000.0;
regSlope1 = timeS / tFactor;
regSlope2 = regSlope1 / 16;
regSlope1 = constrain(regSlope1, 1, 15);
regSlope2 = constrain(regSlope2, 16, 31);
regTime1 = regSlope1 * tFactor * 1000.0;
regTime2 = 16 * regTime1;
if (abs(regTime1 - ms) < abs(regTime2 - ms))
return regSlope1;
float t_factor = ((float) on_intensity - (4.0 * (float) off_intensity)) * 255.0 / (float) clk_x_;
float time_s = float(ms) / 1000.0;
reg_slope_1 = time_s / t_factor;
reg_slope_2 = reg_slope_1 / 16;
reg_slope_1 = constrain(reg_slope_1, 1, 15);
reg_slope_2 = constrain(reg_slope_2, 16, 31);
reg_time_1 = reg_slope_1 * t_factor * 1000.0;
reg_time_2 = 16 * reg_time_1;
if (abs(reg_time_1 - ms) < abs(reg_time_2 - ms))
return reg_slope_1;
else
return regSlope2;
return reg_slope_2;
}
void SX1509Component::setup_keypad(uint8_t rows, uint8_t columns, uint16_t sleepTime, uint8_t scanTime,
void SX1509Component::setup_keypad(uint8_t rows, uint8_t columns, uint16_t sleep_time, uint8_t scan_time,
uint8_t debounce_time) {
uint16_t temp_word;
uint8_t temp_byte;
if (_clkX == 0)
if (clk_x_ == 0)
clock(INTERNAL_CLOCK_2MHZ);
this->read_byte_16(REG_DIR_B, &temp_word);
for (int i = 0; i < rows; i++)
@ -277,32 +273,32 @@ void SX1509Component::setup_keypad(uint8_t rows, uint8_t columns, uint16_t sleep
temp_byte |= (1 << i);
this->write_byte(REG_PULL_UP_B, temp_byte);
debounce_time = constrain(debounce_time, 1, 64);
scanTime = constrain(scanTime, 1, 128);
if (debounce_time >= scanTime) {
debounce_time = scanTime >> 1; // Force debounce_time to be less than scanTime
scan_time = constrain(scan_time, 1, 128);
if (debounce_time >= scan_time) {
debounce_time = scan_time >> 1; // Force debounce_time to be less than scan_time
}
debounce_keypad(debounce_time, rows, columns);
uint8_t scanTimeBits = 0;
uint8_t scan_time_bits = 0;
for (uint8_t i = 7; i > 0; i--) {
if (scanTime & (1 << i)) {
scanTimeBits = i;
if (scan_time & (1 << i)) {
scan_time_bits = i;
break;
}
}
uint8_t sleepTimeBits = 0;
if (sleepTime != 0) {
uint8_t sleep_time_bits = 0;
if (sleep_time != 0) {
for (uint8_t i = 7; i > 0; i--) {
if (sleepTime & ((unsigned int) 1 << (i + 6))) {
sleepTimeBits = i;
if (sleep_time & ((unsigned int) 1 << (i + 6))) {
sleep_time_bits = i;
break;
}
}
if (sleepTimeBits == 0)
sleepTimeBits = 1;
if (sleep_time_bits == 0)
sleep_time_bits = 1;
}
sleepTimeBits = (sleepTimeBits & 0b111) << 4;
scanTimeBits &= 0b111; // Scan time is bits 2:0
temp_byte = sleepTime | scanTimeBits;
sleep_time_bits = (sleep_time_bits & 0b111) << 4;
scan_time_bits &= 0b111; // Scan time is bits 2:0
temp_byte = sleep_time | scan_time_bits;
this->write_byte(REG_KEY_CONFIG_1, temp_byte);
rows = (rows - 1) & 0b111; // 0 = off, 0b001 = 2 rows, 0b111 = 8 rows, etc.
columns = (columns - 1) & 0b111; // 0b000 = 1 column, ob111 = 8 columns, etc.
@ -315,7 +311,7 @@ uint16_t SX1509Component::read_key_data() {
return (0xFFFF ^ key_data);
}
void SX1509Component::debounce_config(uint8_t configValue) {
void SX1509Component::debounce_config(uint8_t config_value) {
// First make sure clock is configured
uint8_t temp_byte;
this->read_byte(REG_MISC, &temp_byte);
@ -329,25 +325,25 @@ void SX1509Component::debounce_config(uint8_t configValue) {
this->write_byte(REG_CLOCK, temp_byte);
}
configValue &= 0b111; // 3-bit value
this->write_byte(REG_DEBOUNCE_CONFIG, configValue);
config_value &= 0b111; // 3-bit value
this->write_byte(REG_DEBOUNCE_CONFIG, config_value);
}
void SX1509Component::debounce_time(uint8_t time) {
if (_clkX == 0) // If clock hasn't been set up.
if (clk_x_ == 0) // If clock hasn't been set up.
clock(INTERNAL_CLOCK_2MHZ, 1); // Set clock to 2MHz.
uint8_t configValue = 0;
uint8_t config_value = 0;
for (int i = 7; i >= 0; i--) {
if (time & (1 << i)) {
configValue = i + 1;
config_value = i + 1;
break;
}
}
configValue = constrain(configValue, 0, 7);
config_value = constrain(config_value, 0, 7);
debounce_config(configValue);
debounce_config(config_value);
}
void SX1509Component::debounce_enable(uint8_t pin) {
@ -359,11 +355,11 @@ void SX1509Component::debounce_enable(uint8_t pin) {
void SX1509Component::debounce_pin(uint8_t pin) { debounce_enable(pin); }
void SX1509Component::debounce_keypad(uint8_t time, uint8_t numRows, uint8_t numCols) {
void SX1509Component::debounce_keypad(uint8_t time, uint8_t num_rows, uint8_t num_cols) {
debounce_time(time);
for (uint16_t i = 0; i < numRows; i++)
for (uint16_t i = 0; i < num_rows; i++)
debounce_pin(i);
for (uint16_t i = 0; i < (8 + numCols); i++)
for (uint16_t i = 0; i < (8 + num_cols); i++)
debounce_pin(i);
}

View File

@ -35,7 +35,7 @@ class SX1509Component : public Component, public i2c::I2CDevice {
void dump_config() override;
float get_setup_priority() const override { return setup_priority::HARDWARE; }
void pin_mode(uint8_t pin, uint8_t in_out);
void led_driver_init(uint8_t pin, uint8_t freq = 1, bool log = false);
void setup_led_driver(uint8_t pin, uint8_t freq = 1, bool log = false);
void clock(uint8_t osc_source = 2, uint8_t osc_divider = 1, uint8_t osc_pin_function = 0, uint8_t osc_freq_out = 0);
void digital_write(uint8_t pin, uint8_t high_low);
uint8_t digital_read(uint8_t pin);
@ -43,8 +43,8 @@ class SX1509Component : public Component, public i2c::I2CDevice {
void setup_blink(uint8_t pin, uint8_t t_on, uint8_t t_off, uint8_t on_intensity = 255, uint8_t off_intensity = 0,
uint8_t t_rise = 0, uint8_t t_fall = 0, bool log = false);
void blink(uint8_t pin, uint16_t tOn, uint16_t tOff, uint8_t on_intensity = 255, uint8_t off_intensity = 0);
void breathe(uint8_t pin, uint16_t tOn, uint16_t tOff, uint16_t rise, uint16_t fall,
//void init_blink(uint8_t pin, uint16_t t_on, uint16_t t_off, uint8_t on_intensity = 255, uint8_t off_intensity = 0);
void setup_breathe(uint8_t pin, uint16_t t_on, uint16_t t_off, uint16_t t_rise, uint16_t t_fall,
uint8_t on_intensity = 255, uint8_t off_intensity = 0, bool log = LINEAR);
uint8_t calculate_led_t_register(uint16_t ms);
uint8_t calculate_slope_register(uint16_t ms, uint8_t on_intensity, uint8_t off_intensity);
@ -65,7 +65,7 @@ class SX1509Component : public Component, public i2c::I2CDevice {
uint8_t pinOscillator_;
uint8_t pinReset_;
// variables:
u_long _clkX;
u_long clk_x_;
uint8_t frequency_ = 0;
bool update_{true};

View File

@ -8,22 +8,24 @@ namespace sx1509 {
static const char *TAG = "sx1509_gpio_pin";
SX1509GPIOPin::SX1509GPIOPin(SX1509Component *parent, uint8_t pin, uint8_t mode, bool inverted, uint16_t t_on,
uint16_t t_off, uint16_t t_rise, uint16_t t_fall)
uint16_t t_off, uint16_t t_rise, uint16_t t_fall, uint8_t fading_mode)
: GPIOPin(pin, mode, inverted), parent_(parent) {
t_on_ = t_on;
t_off_ = t_off;
t_rise_ = t_rise;
t_fall_ = t_fall;
fading_mode_ = fading_mode;
}
void SX1509GPIOPin::setup() {
ESP_LOGD(TAG, "setup pin %d", this->pin_);
this->pin_mode(this->mode_);
switch (this->mode_) {
case BREATHE_OUTPUT:
this->parent_->breathe(this->pin_, t_on_, t_off_, t_rise_, t_fall_);
this->parent_->setup_breathe(this->pin_, t_on_, t_off_, t_rise_, t_fall_);
break;
case BLINK_OUTPUT:
this->parent_->blink(this->pin_, t_on_, t_off_);
this->parent_->setup_blink(this->pin_, t_on_, t_off_);
break;
}
}

View File

@ -5,10 +5,13 @@
#define BREATHE_OUTPUT 0x04
#define BLINK_OUTPUT 0x05
#define LINEAR 0
#define LOGARITHMIC 1
namespace esphome {
namespace sx1509 {
/// Modes for SX1509 pins
/// PinModes for SX1509 pins
enum SX1509GPIOMode : uint8_t {
SX1509_INPUT = INPUT, // 0x00
SX1509_INPUT_PULLUP = INPUT_PULLUP, // 0x02
@ -16,13 +19,18 @@ enum SX1509GPIOMode : uint8_t {
SX1509_BREATHE_OUTPUT = BREATHE_OUTPUT, // 0x04
SX1509_BLINK_OUTPUT = BLINK_OUTPUT // 0x05
};
/// PinModes for SX1509 pins
enum SX1509FadingMode : uint8_t {
SX1509_FADING_LINEAR = LINEAR, // 0x00
SX1509_FADING_LOGARITHMIC = LOGARITHMIC // 0x01
};
class SX1509Component;
class SX1509GPIOPin : public GPIOPin {
public:
SX1509GPIOPin(SX1509Component *parent, uint8_t pin, uint8_t mode, bool inverted = false, uint16_t t_on = 500,
uint16_t t_off = 500, uint16_t t_rise = 250, uint16_t t_fall = 250);
uint16_t t_off = 500, uint16_t t_rise = 250, uint16_t t_fall = 250, uint8_t fading_mode = SX1509_FADING_LINEAR);
void setup() override;
void pin_mode(uint8_t mode) override;
bool digital_read() override;
@ -34,6 +42,7 @@ class SX1509GPIOPin : public GPIOPin {
uint16_t t_off_ = {0};
uint16_t t_rise_ = {0};
uint16_t t_fall_ = {0};
uint8_t fading_mode_ = {SX1509_FADING_LINEAR};
};
} // namespace sx1509