mirror of
https://github.com/esphome/esphome.git
synced 2024-12-20 16:18:49 +01:00
Add HW SPI support (#623)
* Add HW SPI support * Update spi.cpp * Lint * ESP32 Compile Fix
This commit is contained in:
parent
d2be58ba31
commit
75630a36f8
@ -8,20 +8,10 @@ namespace spi {
|
||||
|
||||
static const char *TAG = "spi";
|
||||
|
||||
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(CLOCK_POLARITY);
|
||||
|
||||
this->active_cs_ = cs;
|
||||
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() {
|
||||
if (this->hw_spi_ != nullptr) {
|
||||
this->hw_spi_->endTransaction();
|
||||
}
|
||||
ESP_LOGVV(TAG, "Disabling SPI Chip on pin %u...", this->active_cs_->get_pin());
|
||||
this->active_cs_->digital_write(true);
|
||||
this->active_cs_ = nullptr;
|
||||
@ -30,6 +20,53 @@ void SPIComponent::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up SPI bus...");
|
||||
this->clk_->setup();
|
||||
this->clk_->digital_write(true);
|
||||
|
||||
bool use_hw_spi = true;
|
||||
if (this->clk_->is_inverted())
|
||||
use_hw_spi = false;
|
||||
const bool has_miso = this->miso_ != nullptr;
|
||||
const bool has_mosi = this->mosi_ != nullptr;
|
||||
if (has_miso && this->miso_->is_inverted())
|
||||
use_hw_spi = false;
|
||||
if (has_mosi && this->mosi_->is_inverted())
|
||||
use_hw_spi = false;
|
||||
int8_t clk_pin = this->clk_->get_pin();
|
||||
int8_t miso_pin = has_miso ? this->miso_->get_pin() : -1;
|
||||
int8_t mosi_pin = has_mosi ? this->mosi_->get_pin() : -1;
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
if (clk_pin == 6 && miso_pin == 7 && mosi_pin == 8) {
|
||||
// pass
|
||||
} else if (clk_pin == 14 && miso_pin == 12 && mosi_pin == 13) {
|
||||
// pass
|
||||
} else {
|
||||
use_hw_spi = false;
|
||||
}
|
||||
|
||||
if (use_hw_spi) {
|
||||
this->hw_spi_ = &SPI;
|
||||
this->hw_spi_->pins(clk_pin, miso_pin, mosi_pin, 0);
|
||||
this->hw_spi_->begin();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
static uint8_t spi_bus_num = 0;
|
||||
if (spi_bus_num >= 2) {
|
||||
use_hw_spi = false;
|
||||
}
|
||||
|
||||
if (use_hw_spi) {
|
||||
if (spi_bus_num == 0) {
|
||||
this->hw_spi_ = &SPI;
|
||||
} else {
|
||||
this->hw_spi_ = new SPIClass(VSPI);
|
||||
}
|
||||
spi_bus_num++;
|
||||
this->hw_spi_->begin(clk_pin, miso_pin, mosi_pin);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (this->miso_ != nullptr) {
|
||||
this->miso_->setup();
|
||||
}
|
||||
@ -43,6 +80,7 @@ void SPIComponent::dump_config() {
|
||||
LOG_PIN(" CLK Pin: ", this->clk_);
|
||||
LOG_PIN(" MISO Pin: ", this->miso_);
|
||||
LOG_PIN(" MOSI Pin: ", this->mosi_);
|
||||
ESP_LOGCONFIG(TAG, " Using HW SPI: %s", YESNO(this->hw_spi_ != nullptr));
|
||||
}
|
||||
float SPIComponent::get_setup_priority() const { return setup_priority::BUS; }
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/esphal.h"
|
||||
#include <SPI.h>
|
||||
|
||||
namespace esphome {
|
||||
namespace spi {
|
||||
@ -67,11 +68,18 @@ class SPIComponent : public Component {
|
||||
void dump_config() override;
|
||||
|
||||
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE> uint8_t read_byte() {
|
||||
if (this->hw_spi_ != nullptr) {
|
||||
return this->hw_spi_->transfer(0x00);
|
||||
}
|
||||
return this->transfer_<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE, true, false>(0x00);
|
||||
}
|
||||
|
||||
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE>
|
||||
void read_array(uint8_t *data, size_t length) {
|
||||
if (this->hw_spi_ != nullptr) {
|
||||
this->hw_spi_->transfer(data, length);
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
data[i] = this->read_byte<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE>();
|
||||
}
|
||||
@ -79,11 +87,20 @@ class SPIComponent : public Component {
|
||||
|
||||
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE>
|
||||
void write_byte(uint8_t data) {
|
||||
if (this->hw_spi_ != nullptr) {
|
||||
this->hw_spi_->write(data);
|
||||
return;
|
||||
}
|
||||
this->transfer_<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE, false, true>(data);
|
||||
}
|
||||
|
||||
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE>
|
||||
void write_array(const uint8_t *data, size_t length) {
|
||||
if (this->hw_spi_ != nullptr) {
|
||||
auto *data_c = const_cast<uint8_t *>(data);
|
||||
this->hw_spi_->writeBytes(data_c, length);
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
this->write_byte<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE>(data[i]);
|
||||
}
|
||||
@ -91,17 +108,39 @@ class SPIComponent : public Component {
|
||||
|
||||
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE>
|
||||
uint8_t transfer_byte(uint8_t data) {
|
||||
if (this->hw_spi_ != nullptr) {
|
||||
return this->hw_spi_->transfer(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) {
|
||||
if (this->hw_spi_ != nullptr) {
|
||||
this->hw_spi_->transfer(data, length);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
template<SPIBitOrder BIT_ORDER, SPIClockPolarity CLOCK_POLARITY, SPIClockPhase CLOCK_PHASE, uint32_t DATA_RATE>
|
||||
void enable(GPIOPin *cs) {
|
||||
SPIComponent::debug_enable(cs->get_pin());
|
||||
|
||||
if (this->hw_spi_ != nullptr) {
|
||||
uint8_t data_mode = (uint8_t(CLOCK_POLARITY) << 1) | uint8_t(CLOCK_PHASE);
|
||||
SPISettings settings(DATA_RATE, BIT_ORDER, data_mode);
|
||||
this->hw_spi_->beginTransaction(settings);
|
||||
} else {
|
||||
this->clk_->digital_write(CLOCK_POLARITY);
|
||||
this->wait_cycle_ = uint32_t(F_CPU) / DATA_RATE / 2ULL;
|
||||
}
|
||||
|
||||
this->active_cs_ = cs;
|
||||
this->active_cs_->digital_write(false);
|
||||
}
|
||||
|
||||
void disable();
|
||||
|
||||
@ -121,6 +160,7 @@ class SPIComponent : public Component {
|
||||
GPIOPin *miso_{nullptr};
|
||||
GPIOPin *mosi_{nullptr};
|
||||
GPIOPin *active_cs_{nullptr};
|
||||
SPIClass *hw_spi_{nullptr};
|
||||
uint32_t wait_cycle_;
|
||||
};
|
||||
|
||||
@ -138,7 +178,7 @@ class SPIDevice {
|
||||
this->cs_->digital_write(true);
|
||||
}
|
||||
|
||||
void enable() { this->parent_->template enable<CLOCK_POLARITY>(this->cs_, uint32_t(F_CPU) / DATA_RATE / 2ULL); }
|
||||
void enable() { this->parent_->template enable<BIT_ORDER, CLOCK_POLARITY, CLOCK_PHASE, DATA_RATE>(this->cs_); }
|
||||
|
||||
void disable() { this->parent_->disable(); }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user