SN74HC595 support for inverted & restore modes without relay pulsing

This commit is contained in:
Greg Gibeling 2024-01-22 17:14:47 -08:00
parent c35a21773e
commit 9373ebe353
2 changed files with 39 additions and 12 deletions

View File

@ -48,31 +48,53 @@ void SN74HC595Component::digital_write_(uint16_t pin, bool value) {
return; return;
} }
if (value) { if (value) {
this->output_bytes_[pin / 8] |= (1 << (pin % 8)); this->value_bytes_[pin / 8] |= (1 << (pin % 8));
} else { } else {
this->output_bytes_[pin / 8] &= ~(1 << (pin % 8)); this->value_bytes_[pin / 8] &= ~(1 << (pin % 8));
} }
this->write_gpio(); this->write_gpio();
} }
void SN74HC595Component::set_inverted_(uint16_t pin, bool inverted) {
if (pin >= this->sr_count_ * 8) {
ESP_LOGE(TAG, "Pin %u is out of range! Maximum pin number with %u chips in series is %u", pin, this->sr_count_,
(this->sr_count_ * 8) - 1);
return;
}
if (inverted) {
this->inverted_bytes_[pin / 8] |= (1 << (pin % 8));
} else {
this->inverted_bytes_[pin / 8] &= ~(1 << (pin % 8));
}
}
void SN74HC595GPIOComponent::write_gpio() { void SN74HC595GPIOComponent::write_gpio() {
for (auto byte = this->output_bytes_.rbegin(); byte != this->output_bytes_.rend(); byte++) { auto value = this->value_bytes_.rbegin();
auto inverted = this->inverted_bytes_.rbegin();
while (value != this->value_bytes_.rend() && inverted != this->inverted_bytes_.rend()) {
for (int8_t i = 7; i >= 0; i--) { for (int8_t i = 7; i >= 0; i--) {
bool bit = (*byte >> i) & 1; bool value_bit = (*value >> i) & 1;
this->data_pin_->digital_write(bit); bool value_inverted = (*inverted >> i) & 1;
this->data_pin_->digital_write(value_bit != value_inverted);
this->clock_pin_->digital_write(true); this->clock_pin_->digital_write(true);
this->clock_pin_->digital_write(false); this->clock_pin_->digital_write(false);
} }
value++;
inverted++;
} }
SN74HC595Component::write_gpio(); SN74HC595Component::write_gpio();
} }
#ifdef USE_SPI #ifdef USE_SPI
void SN74HC595SPIComponent::write_gpio() { void SN74HC595SPIComponent::write_gpio() {
for (auto byte = this->output_bytes_.rbegin(); byte != this->output_bytes_.rend(); byte++) { auto value = this->value_bytes_.rbegin();
auto inverted = this->inverted_bytes_.rbegin();
while (value != this->value_bytes_.rend() && inverted != this->inverted_bytes_.rend()) {
this->enable(); this->enable();
this->transfer_byte(*byte); this->transfer_byte((*byte) ^ (*inverted));
this->disable(); this->disable();
value++;
inverted++;
} }
SN74HC595Component::write_gpio(); SN74HC595Component::write_gpio();
} }
@ -92,7 +114,10 @@ void SN74HC595Component::write_gpio() {
float SN74HC595Component::get_setup_priority() const { return setup_priority::IO; } float SN74HC595Component::get_setup_priority() const { return setup_priority::IO; }
void SN74HC595GPIOPin::digital_write(bool value) { void SN74HC595GPIOPin::digital_write(bool value) {
this->parent_->digital_write_(this->pin_, value != this->inverted_); this->parent_->digital_write_(this->pin_, value);
}
void SN74HC595GPIOPin::set_inverted(bool inverted) {
this->parent_->set_inverted_(this->pin_, inverted);
} }
std::string SN74HC595GPIOPin::dump_summary() const { return str_snprintf("%u via SN74HC595", 18, pin_); } std::string SN74HC595GPIOPin::dump_summary() const { return str_snprintf("%u via SN74HC595", 18, pin_); }

View File

@ -29,12 +29,14 @@ class SN74HC595Component : public Component {
} }
void set_sr_count(uint8_t count) { void set_sr_count(uint8_t count) {
this->sr_count_ = count; this->sr_count_ = count;
this->output_bytes_.resize(count); this->value_bytes_.resize(count);
this->inverted_bytes_.resize(count);
} }
protected: protected:
friend class SN74HC595GPIOPin; friend class SN74HC595GPIOPin;
void digital_write_(uint16_t pin, bool value); void digital_write_(uint16_t pin, bool value);
void set_inverted_(uint16_t pin, bool inverted);
virtual void write_gpio(); virtual void write_gpio();
void pre_setup_(); void pre_setup_();
@ -44,7 +46,8 @@ class SN74HC595Component : public Component {
GPIOPin *oe_pin_; GPIOPin *oe_pin_;
uint8_t sr_count_; uint8_t sr_count_;
bool have_oe_pin_{false}; bool have_oe_pin_{false};
std::vector<uint8_t> output_bytes_; std::vector<uint8_t> value_bytes_;
std::vector<uint8_t> inverted_bytes_;
}; };
/// Helper class to expose a SC74HC595 pin as an internal output GPIO pin. /// Helper class to expose a SC74HC595 pin as an internal output GPIO pin.
@ -57,11 +60,10 @@ class SN74HC595GPIOPin : public GPIOPin, public Parented<SN74HC595Component> {
std::string dump_summary() const override; std::string dump_summary() const override;
void set_pin(uint16_t pin) { pin_ = pin; } void set_pin(uint16_t pin) { pin_ = pin; }
void set_inverted(bool inverted) { inverted_ = inverted; } void set_inverted(bool inverted);
protected: protected:
uint16_t pin_; uint16_t pin_;
bool inverted_;
}; };
class SN74HC595GPIOComponent : public SN74HC595Component { class SN74HC595GPIOComponent : public SN74HC595Component {