Add more efficient SPI implementation (#622)

* Add more efficient SPI implementation

* Lint

* Add 200KHZ

* Updates

* Fix write_byte

* Update from datasheet

* Shift clock

* Fix calculation
This commit is contained in:
Otto Winter 2019-06-07 14:25:57 +02:00 committed by GitHub
parent 88ccd60a08
commit 726b0e73d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 300 additions and 111 deletions

View file

@ -82,7 +82,5 @@ void MAX31855Sensor::read_data_() {
this->status_clear_warning();
}
bool MAX31855Sensor::is_device_msb_first() { return true; }
} // namespace max31855
} // namespace esphome

View file

@ -7,7 +7,10 @@
namespace esphome {
namespace max31855 {
class MAX31855Sensor : public sensor::Sensor, public PollingComponent, public spi::SPIDevice {
class MAX31855Sensor : public sensor::Sensor,
public PollingComponent,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW,
spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_4MHZ> {
public:
void setup() override;
void dump_config() override;
@ -16,8 +19,6 @@ class MAX31855Sensor : public sensor::Sensor, public PollingComponent, public sp
void update() override;
protected:
bool is_device_msb_first() override;
void read_data_();
};

View file

@ -48,7 +48,5 @@ void MAX6675Sensor::read_data_() {
this->status_clear_warning();
}
bool MAX6675Sensor::is_device_msb_first() { return true; }
} // namespace max6675
} // namespace esphome

View file

@ -7,7 +7,10 @@
namespace esphome {
namespace max6675 {
class MAX6675Sensor : public sensor::Sensor, public PollingComponent, public spi::SPIDevice {
class MAX6675Sensor : public sensor::Sensor,
public PollingComponent,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
spi::DATA_RATE_1KHZ> {
public:
void setup() override;
void dump_config() override;
@ -16,8 +19,6 @@ class MAX6675Sensor : public sensor::Sensor, public PollingComponent, public spi
void update() override;
protected:
bool is_device_msb_first() override;
void read_data_();
};

View file

@ -155,7 +155,6 @@ void MAX7219Component::send_to_all_(uint8_t a_register, uint8_t data) {
this->send_byte_(a_register, data);
this->disable();
}
bool MAX7219Component::is_device_msb_first() { return true; }
void MAX7219Component::update() {
for (uint8_t i = 0; i < this->num_chips_ * 8; i++)
this->buffer_[i] = 0;

View file

@ -16,7 +16,9 @@ class MAX7219Component;
using max7219_writer_t = std::function<void(MAX7219Component &)>;
class MAX7219Component : public PollingComponent, public spi::SPIDevice {
class MAX7219Component : public PollingComponent,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW,
spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_1MHZ> {
public:
void set_writer(max7219_writer_t &&writer);
@ -54,7 +56,6 @@ class MAX7219Component : public PollingComponent, public spi::SPIDevice {
protected:
void send_byte_(uint8_t a_register, uint8_t data);
void send_to_all_(uint8_t a_register, uint8_t data);
bool is_device_msb_first() override;
uint8_t intensity_{15}; /// Intensity of the display from 0 to 15 (most)
uint8_t num_chips_{1};

View file

@ -335,7 +335,6 @@ bool PN532::wait_ready_() {
return true;
}
bool PN532::is_device_msb_first() { return false; }
void PN532::dump_config() {
ESP_LOGCONFIG(TAG, "PN532:");
switch (this->error_code_) {

View file

@ -11,7 +11,9 @@ namespace pn532 {
class PN532BinarySensor;
class PN532Trigger;
class PN532 : public PollingComponent, public spi::SPIDevice {
class PN532 : public PollingComponent,
public spi::SPIDevice<spi::BIT_ORDER_LSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
spi::DATA_RATE_1MHZ> {
public:
void setup() override;
@ -26,8 +28,6 @@ class PN532 : public PollingComponent, public spi::SPIDevice {
void register_trigger(PN532Trigger *trig) { this->triggers_.push_back(trig); }
protected:
bool is_device_msb_first() override;
/// Write the full command given in data to the PN532
void pn532_write_command_(const std::vector<uint8_t> &data);
bool pn532_write_command_check_ack_(const std::vector<uint8_t> &data);

View file

@ -8,73 +8,19 @@ namespace spi {
static const char *TAG = "spi";
void ICACHE_RAM_ATTR HOT SPIComponent::write_byte(uint8_t data) {
uint8_t send_bits = data;
if (this->msb_first_)
send_bits = reverse_bits_8(data);
template<SPIClockPolarity CLOCK_POLARITY> void SPIComponent::enable(GPIOPin *cs, uint32_t wait_cycle) {
this->debug_enable(cs->get_pin());
this->wait_cycle_ = wait_cycle;
this->clk_->digital_write(true);
if (!this->high_speed_)
delayMicroseconds(5);
for (size_t i = 0; i < 8; i++) {
if (!this->high_speed_)
delayMicroseconds(5);
this->clk_->digital_write(false);
// sampling on leading edge
this->mosi_->digital_write(send_bits & (1 << i));
if (!this->high_speed_)
delayMicroseconds(5);
this->clk_->digital_write(true);
}
ESP_LOGVV(TAG, " Wrote 0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(data), data);
}
uint8_t ICACHE_RAM_ATTR HOT SPIComponent::read_byte() {
this->clk_->digital_write(true);
uint8_t data = 0;
for (size_t i = 0; i < 8; i++) {
if (!this->high_speed_)
delayMicroseconds(5);
data |= uint8_t(this->miso_->digital_read()) << i;
this->clk_->digital_write(false);
if (!this->high_speed_)
delayMicroseconds(5);
this->clk_->digital_write(true);
}
if (this->msb_first_) {
data = reverse_bits_8(data);
}
ESP_LOGVV(TAG, " Received 0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(data), data);
return data;
}
void ICACHE_RAM_ATTR HOT SPIComponent::read_array(uint8_t *data, size_t length) {
for (size_t i = 0; i < length; i++)
data[i] = this->read_byte();
}
void ICACHE_RAM_ATTR HOT SPIComponent::write_array(uint8_t *data, size_t length) {
for (size_t i = 0; i < length; i++) {
App.feed_wdt();
this->write_byte(data[i]);
}
}
void ICACHE_RAM_ATTR HOT SPIComponent::enable(GPIOPin *cs, bool msb_first, bool high_speed) {
ESP_LOGVV(TAG, "Enabling SPI Chip on pin %u...", cs->get_pin());
cs->digital_write(false);
this->clk_->digital_write(CLOCK_POLARITY);
this->active_cs_ = cs;
this->msb_first_ = msb_first;
this->high_speed_ = high_speed;
this->active_cs_->digital_write(false);
}
template void SPIComponent::enable<CLOCK_POLARITY_LOW>(GPIOPin *cs, uint32_t wait_cycle);
template void SPIComponent::enable<CLOCK_POLARITY_HIGH>(GPIOPin *cs, uint32_t wait_cycle);
void ICACHE_RAM_ATTR HOT SPIComponent::disable() {
ESP_LOGVV(TAG, "Disabling SPI Chip on pin %u...", this->active_cs_->get_pin());
this->active_cs_->digital_write(true);
@ -100,5 +46,150 @@ void SPIComponent::dump_config() {
}
float SPIComponent::get_setup_priority() const { return setup_priority::BUS; }
void SPIComponent::debug_tx(uint8_t value) {
ESP_LOGVV(TAG, " TX 0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(value), value);
}
void SPIComponent::debug_rx(uint8_t value) {
ESP_LOGVV(TAG, " RX 0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(value), value);
}
void SPIComponent::debug_enable(uint8_t pin) { ESP_LOGVV(TAG, "Enabling SPI Chip on pin %u...", pin); }
void SPIComponent::cycle_clock_(bool value) {
uint32_t start = ESP.getCycleCount();
while (start - ESP.getCycleCount() < this->wait_cycle_)
;
this->clk_->digital_write(value);
start += this->wait_cycle_;
while (start - ESP.getCycleCount() < this->wait_cycle_)
;
}
// NOLINTNEXTLINE
#pragma GCC optimize("unroll-loops")
// NOLINTNEXTLINE
#pragma GCC optimize("O2")
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE, bool READ, bool WRITE>
uint8_t HOT SPIComponent::transfer_(uint8_t data) {
// Clock starts out at idle level
this->clk_->digital_write(CLOCK_POLARITY);
uint8_t out_data = 0;
for (uint8_t i = 0; i < 8; i++) {
uint8_t shift;
if (BIT_ORDER == BIT_ORDER_MSB_FIRST)
shift = 7 - i;
else
shift = i;
if (CLOCK_PHASE == CLOCK_PHASE_LEADING) {
// sampling on leading edge
if (WRITE) {
this->mosi_->digital_write(data & (1 << shift));
}
// SAMPLE!
this->cycle_clock_(!CLOCK_POLARITY);
if (READ) {
out_data |= uint8_t(this->miso_->digital_read()) << shift;
}
this->cycle_clock_(CLOCK_POLARITY);
} else {
// sampling on trailing edge
this->cycle_clock_(!CLOCK_POLARITY);
if (WRITE) {
this->mosi_->digital_write(data & (1 << shift));
}
// SAMPLE!
this->cycle_clock_(CLOCK_POLARITY);
if (READ) {
out_data |= uint8_t(this->miso_->digital_read()) << shift;
}
}
}
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
if (WRITE) {
SPIComponent::debug_tx(data);
}
if (READ) {
SPIComponent::debug_rx(out_data);
}
#endif
App.feed_wdt();
return out_data;
}
// Generate with (py3):
//
// from itertools import product
// bit_orders = ['BIT_ORDER_LSB_FIRST', 'BIT_ORDER_MSB_FIRST']
// clock_pols = ['CLOCK_POLARITY_LOW', 'CLOCK_POLARITY_HIGH']
// clock_phases = ['CLOCK_PHASE_LEADING', 'CLOCK_PHASE_TRAILING']
// reads = [False, True]
// writes = [False, True]
// cpp_bool = {False: 'false', True: 'true'}
// for b, cpol, cph, r, w in product(bit_orders, clock_pols, clock_phases, reads, writes):
// if not r and not w:
// continue
// print(f"template uint8_t SPIComponent::transfer_<{b}, {cpol}, {cph}, {cpp_bool[r]}, {cpp_bool[w]}>(uint8_t
// data);")
template uint8_t SPIComponent::transfer_<BIT_ORDER_LSB_FIRST, CLOCK_POLARITY_LOW, CLOCK_PHASE_LEADING, false, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_LSB_FIRST, CLOCK_POLARITY_LOW, CLOCK_PHASE_LEADING, true, false>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_LSB_FIRST, CLOCK_POLARITY_LOW, CLOCK_PHASE_LEADING, true, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_LSB_FIRST, CLOCK_POLARITY_LOW, CLOCK_PHASE_TRAILING, false, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_LSB_FIRST, CLOCK_POLARITY_LOW, CLOCK_PHASE_TRAILING, true, false>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_LSB_FIRST, CLOCK_POLARITY_LOW, CLOCK_PHASE_TRAILING, true, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_LSB_FIRST, CLOCK_POLARITY_HIGH, CLOCK_PHASE_LEADING, false, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_LSB_FIRST, CLOCK_POLARITY_HIGH, CLOCK_PHASE_LEADING, true, false>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_LSB_FIRST, CLOCK_POLARITY_HIGH, CLOCK_PHASE_LEADING, true, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_LSB_FIRST, CLOCK_POLARITY_HIGH, CLOCK_PHASE_TRAILING, false, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_LSB_FIRST, CLOCK_POLARITY_HIGH, CLOCK_PHASE_TRAILING, true, false>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_LSB_FIRST, CLOCK_POLARITY_HIGH, CLOCK_PHASE_TRAILING, true, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_MSB_FIRST, CLOCK_POLARITY_LOW, CLOCK_PHASE_LEADING, false, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_MSB_FIRST, CLOCK_POLARITY_LOW, CLOCK_PHASE_LEADING, true, false>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_MSB_FIRST, CLOCK_POLARITY_LOW, CLOCK_PHASE_LEADING, true, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_MSB_FIRST, CLOCK_POLARITY_LOW, CLOCK_PHASE_TRAILING, false, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_MSB_FIRST, CLOCK_POLARITY_LOW, CLOCK_PHASE_TRAILING, true, false>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_MSB_FIRST, CLOCK_POLARITY_LOW, CLOCK_PHASE_TRAILING, true, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_MSB_FIRST, CLOCK_POLARITY_HIGH, CLOCK_PHASE_LEADING, false, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_MSB_FIRST, CLOCK_POLARITY_HIGH, CLOCK_PHASE_LEADING, true, false>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_MSB_FIRST, CLOCK_POLARITY_HIGH, CLOCK_PHASE_LEADING, true, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_MSB_FIRST, CLOCK_POLARITY_HIGH, CLOCK_PHASE_TRAILING, false, true>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_MSB_FIRST, CLOCK_POLARITY_HIGH, CLOCK_PHASE_TRAILING, true, false>(
uint8_t data);
template uint8_t SPIComponent::transfer_<BIT_ORDER_MSB_FIRST, CLOCK_POLARITY_HIGH, CLOCK_PHASE_TRAILING, true, true>(
uint8_t data);
} // namespace spi
} // namespace esphome

View file

@ -6,6 +6,56 @@
namespace esphome {
namespace spi {
/// The bit-order for SPI devices. This defines how the data read from and written to the device is interpreted.
enum SPIBitOrder {
/// The least significant bit is transmitted/received first.
BIT_ORDER_LSB_FIRST,
/// The most significant bit is transmitted/received first.
BIT_ORDER_MSB_FIRST,
};
/** The SPI clock signal polarity,
*
* This defines how the clock signal is used. Flipping this effectively inverts the clock signal.
*/
enum SPIClockPolarity {
/** The clock signal idles on LOW. (CPOL=0)
*
* A rising edge means a leading edge for the clock.
*/
CLOCK_POLARITY_LOW = false,
/** The clock signal idles on HIGH. (CPOL=1)
*
* A falling edge means a trailing edge for the clock.
*/
CLOCK_POLARITY_HIGH = true,
};
/** The SPI clock signal phase.
*
* This defines when the data signals are sampled. Most SPI devices use the LEADING clock phase.
*/
enum SPIClockPhase {
/// The data is sampled on a leading clock edge. (CPHA=0)
CLOCK_PHASE_LEADING,
/// The data is sampled on a trailing clock edge. (CPHA=1)
CLOCK_PHASE_TRAILING,
};
/** The SPI clock signal data rate. This defines for what duration the clock signal is HIGH/LOW.
* So effectively the rate of bytes can be calculated using
*
* effective_byte_rate = spi_data_rate / 16
*
* Implementations can use the pre-defined constants here, or use an integer in the template definition
* to manually use a specific data rate.
*/
enum SPIDataRate : uint32_t {
DATA_RATE_1KHZ = 1000,
DATA_RATE_200KHZ = 200000,
DATA_RATE_1MHZ = 1000000,
DATA_RATE_2MHZ = 2000000,
DATA_RATE_4MHZ = 4000000,
DATA_RATE_8MHZ = 8000000,
};
class SPIComponent : public Component {
public:
void set_clk(GPIOPin *clk) { clk_ = clk; }
@ -16,59 +66,117 @@ class SPIComponent : public Component {
void dump_config() override;
uint8_t read_byte();
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE> uint8_t read_byte() {
return this->transfer_<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE, true, false>(0x00);
}
void read_array(uint8_t *data, size_t length);
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE>
void read_array(uint8_t *data, size_t length) {
for (size_t i = 0; i < length; i++) {
data[i] = this->read_byte<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE>();
}
}
void write_byte(uint8_t data);
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE>
void write_byte(uint8_t data) {
this->transfer_<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE, false, true>(data);
}
void write_array(uint8_t *data, size_t length);
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE>
void write_array(const uint8_t *data, size_t length) {
for (size_t i = 0; i < length; i++) {
this->write_byte<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE>(data[i]);
}
}
void enable(GPIOPin *cs, bool msb_first, bool high_speed);
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE>
uint8_t transfer_byte(uint8_t data) {
return this->transfer_<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE, true, true>(data);
}
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE>
void transfer_array(uint8_t *data, size_t length) {
for (size_t i = 0; i < length; i++) {
data[i] = this->transfer_byte<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE>(data[i]);
}
}
template<SPIClockPolarity CLOCK_POLARITY> void enable(GPIOPin *cs, uint32_t wait_cycle);
void disable();
float get_setup_priority() const override;
protected:
inline void cycle_clock_(bool value);
static void debug_enable(uint8_t pin);
static void debug_tx(uint8_t value);
static void debug_rx(uint8_t value);
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE, bool READ, bool WRITE>
uint8_t transfer_(uint8_t data);
GPIOPin *clk_;
GPIOPin *miso_{nullptr};
GPIOPin *mosi_{nullptr};
GPIOPin *active_cs_{nullptr};
bool msb_first_{true};
bool high_speed_{false};
uint32_t wait_cycle_;
};
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE, SPIDataRate DATA_RATE>
class SPIDevice {
public:
SPIDevice() = default;
SPIDevice(SPIComponent *parent, GPIOPin *cs) : parent_(parent), cs_(cs) {}
void set_spi_parent(SPIComponent *parent) { this->parent_ = parent; }
void set_cs_pin(GPIOPin *cs) { this->cs_ = cs; }
void set_spi_parent(SPIComponent *parent) { parent_ = parent; }
void set_cs_pin(GPIOPin *cs) { cs_ = cs; }
void spi_setup() {
this->cs_->setup();
this->cs_->digital_write(true);
}
void enable() { this->parent_->enable(this->cs_, this->is_device_msb_first(), this->is_device_high_speed()); }
void enable() { this->parent_->template enable<CLOCK_POLARITY>(this->cs_, uint32_t(F_CPU) / DATA_RATE / 2ULL); }
void disable() { this->parent_->disable(); }
uint8_t read_byte() { return this->parent_->read_byte(); }
uint8_t read_byte() { return this->parent_->template read_byte<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE>(); }
void read_array(uint8_t *data, size_t length) { return this->parent_->read_array(data, length); }
void read_array(uint8_t *data, size_t length) {
return this->parent_->template read_array<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE>(data, length);
}
void write_byte(uint8_t data) { return this->parent_->write_byte(data); }
template<size_t N> std::array<uint8_t, N> read_array() {
std::array<uint8_t, N> data;
this->read_array(data.data(), N);
return data;
}
void write_array(uint8_t *data, size_t length) { this->parent_->write_array(data, length); }
void write_byte(uint8_t data) {
return this->parent_->template write_byte<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE>(data);
}
void write_array(const uint8_t *data, size_t length) {
this->parent_->template write_array<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE>(data, length);
}
template<size_t N> void write_array(const std::array<uint8_t, N> &data) { this->write_array(data.data(), N); }
void write_array(const std::vector<uint8_t> &data) { this->write_array(data.data(), data.size()); }
uint8_t transfer_byte(uint8_t data) {
return this->parent_->template transfer_byte<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE>(data);
}
void transfer_array(uint8_t *data, size_t length) {
this->parent_->template transfer_array<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE>(data, length);
}
template<size_t N> void transfer_array(std::array<uint8_t, N> &data) { this->transfer_array(data.data(), N); }
protected:
virtual bool is_device_msb_first() = 0;
virtual bool is_device_high_speed() { return false; }
SPIComponent *parent_{nullptr};
GPIOPin *cs_{nullptr};
};

View file

@ -7,7 +7,6 @@ namespace ssd1306_spi {
static const char *TAG = "ssd1306_spi";
bool SPISSD1306::is_device_msb_first() { return true; }
void SPISSD1306::setup() {
ESP_LOGCONFIG(TAG, "Setting up SPI SSD1306...");
this->spi_setup();
@ -52,7 +51,6 @@ void HOT SPISSD1306::write_display_data() {
this->disable();
}
}
bool SPISSD1306::is_device_high_speed() { return true; }
} // namespace ssd1306_spi
} // namespace esphome

View file

@ -7,7 +7,9 @@
namespace esphome {
namespace ssd1306_spi {
class SPISSD1306 : public ssd1306_base::SSD1306, public spi::SPIDevice {
class SPISSD1306 : public ssd1306_base::SSD1306,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_HIGH, spi::CLOCK_PHASE_TRAILING,
spi::DATA_RATE_8MHZ> {
public:
void set_dc_pin(GPIOPin *dc_pin) { dc_pin_ = dc_pin; }
@ -19,8 +21,6 @@ class SPISSD1306 : public ssd1306_base::SSD1306, public spi::SPIDevice {
void command(uint8_t value) override;
void write_display_data() override;
bool is_device_msb_first() override;
bool is_device_high_speed() override;
GPIOPin *dc_pin_;
};

View file

@ -42,7 +42,6 @@ void WaveshareEPaper::data(uint8_t value) {
this->write_byte(value);
this->end_data_();
}
bool WaveshareEPaper::is_device_msb_first() { return true; }
bool WaveshareEPaper::wait_until_idle_() {
if (this->busy_pin_ == nullptr) {
return true;
@ -81,7 +80,6 @@ void HOT WaveshareEPaper::draw_absolute_pixel_internal(int x, int y, int color)
this->buffer_[pos] &= ~(0x80 >> subpos);
}
uint32_t WaveshareEPaper::get_buffer_length_() { return this->get_width_internal() * this->get_height_internal() / 8u; }
bool WaveshareEPaper::is_device_high_speed() { return true; }
void WaveshareEPaper::start_command_() {
this->dc_pin_->digital_write(false);
this->enable();
@ -495,7 +493,6 @@ void HOT WaveshareEPaper4P2In::display() {
}
int WaveshareEPaper4P2In::get_width_internal() { return 400; }
int WaveshareEPaper4P2In::get_height_internal() { return 300; }
bool WaveshareEPaper4P2In::is_device_high_speed() { return false; }
void WaveshareEPaper4P2In::dump_config() {
LOG_DISPLAY("", "Waveshare E-Paper", this);
ESP_LOGCONFIG(TAG, " Model: 4.2in");

View file

@ -7,14 +7,16 @@
namespace esphome {
namespace waveshare_epaper {
class WaveshareEPaper : public PollingComponent, public spi::SPIDevice, public display::DisplayBuffer {
class WaveshareEPaper : public PollingComponent,
public display::DisplayBuffer,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW,
spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_2MHZ> {
public:
void set_dc_pin(GPIOPin *dc_pin) { dc_pin_ = dc_pin; }
float get_setup_priority() const override;
void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; }
void set_busy_pin(GPIOPin *busy) { this->busy_pin_ = busy; }
bool is_device_msb_first() override;
void command(uint8_t value);
void data(uint8_t value);
@ -51,8 +53,6 @@ class WaveshareEPaper : public PollingComponent, public spi::SPIDevice, public d
uint32_t get_buffer_length_();
bool is_device_high_speed() override;
void start_command_();
void end_command_();
void start_data_();
@ -166,8 +166,6 @@ class WaveshareEPaper4P2In : public WaveshareEPaper {
int get_width_internal() override;
int get_height_internal() override;
bool is_device_high_speed() override;
};
class WaveshareEPaper7P5In : public WaveshareEPaper {