ESPHome 2025.8.0b1
Loading...
Searching...
No Matches
spi.cpp
Go to the documentation of this file.
1#include "spi.h"
2#include "esphome/core/log.h"
4
5namespace esphome {
6namespace spi {
7
8const char *const TAG = "spi";
9
10SPIDelegate *const SPIDelegate::NULL_DELEGATE = // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
11 new SPIDelegateDummy();
12// https://bugs.llvm.org/show_bug.cgi?id=48040
13
14bool SPIDelegate::is_ready() { return true; }
15
16GPIOPin *const NullPin::NULL_PIN = new NullPin(); // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
17
19 GPIOPin *cs_pin, bool release_device, bool write_only) {
20 if (this->devices_.count(device) != 0) {
21 ESP_LOGE(TAG, "Device already registered");
22 return this->devices_[device];
23 }
24 SPIDelegate *delegate =
25 this->spi_bus_->get_delegate(data_rate, bit_order, mode, cs_pin, release_device, write_only); // NOLINT
26 this->devices_[device] = delegate;
27 return delegate;
28}
29
31 if (this->devices_.count(device) == 0) {
32 esph_log_e(TAG, "Device not registered");
33 return;
34 }
35 delete this->devices_[device]; // NOLINT
36 this->devices_.erase(device);
37}
38
40 if (this->sdo_pin_ == nullptr)
42 if (this->sdi_pin_ == nullptr)
44 if (this->clk_pin_ == nullptr) {
45 ESP_LOGE(TAG, "No clock pin");
46 this->mark_failed();
47 return;
48 }
49
50 if (this->using_hw_) {
51 this->spi_bus_ =
52 SPIComponent::get_bus(this->interface_, this->clk_pin_, this->sdo_pin_, this->sdi_pin_, this->data_pins_);
53 if (this->spi_bus_ == nullptr) {
54 ESP_LOGE(TAG, "Unable to allocate SPI interface");
55 this->mark_failed();
56 }
57 } else {
58 this->spi_bus_ = new SPIBus(this->clk_pin_, this->sdo_pin_, this->sdi_pin_); // NOLINT
59 this->clk_pin_->setup();
60 this->clk_pin_->digital_write(true);
61 this->sdo_pin_->setup();
62 this->sdi_pin_->setup();
63 }
64}
65
67 ESP_LOGCONFIG(TAG, "SPI bus:");
68 LOG_PIN(" CLK Pin: ", this->clk_pin_)
69 LOG_PIN(" SDI Pin: ", this->sdi_pin_)
70 LOG_PIN(" SDO Pin: ", this->sdo_pin_)
71 for (size_t i = 0; i != this->data_pins_.size(); i++) {
72 ESP_LOGCONFIG(TAG, " Data pin %u: GPIO%d", i, this->data_pins_[i]);
73 }
74 if (this->spi_bus_->is_hw()) {
75 ESP_LOGCONFIG(TAG, " Using HW SPI: %s", this->interface_name_);
76 } else {
77 ESP_LOGCONFIG(TAG, " Using software SPI");
78 }
79}
80
81void SPIDelegateDummy::begin_transaction() { ESP_LOGE(TAG, "SPIDevice not initialised - did you call spi_setup()?"); }
82
83uint8_t SPIDelegateBitBash::transfer(uint8_t data) { return this->transfer_(data, 8); }
84
85void SPIDelegateBitBash::write(uint16_t data, size_t num_bits) { this->transfer_(data, num_bits); }
86
87uint16_t SPIDelegateBitBash::transfer_(uint16_t data, size_t num_bits) {
88 // Clock starts out at idle level
90 uint16_t out_data = 0;
91
92 for (uint8_t i = 0; i != num_bits; i++) {
93 uint8_t shift;
95 shift = num_bits - 1 - i;
96 } else {
97 shift = i;
98 }
99
101 // sampling on leading edge
102 this->sdo_pin_->digital_write(data & (1 << shift));
103 this->cycle_clock_();
104 out_data |= uint16_t(this->sdi_pin_->digital_read()) << shift;
106 this->cycle_clock_();
108 } else {
109 // sampling on trailing edge
110 this->cycle_clock_();
112 this->sdo_pin_->digital_write(data & (1 << shift));
113 this->cycle_clock_();
114 out_data |= uint16_t(this->sdi_pin_->digital_read()) << shift;
116 }
117 }
118 App.feed_wdt();
119 return out_data;
120}
121
122} // namespace spi
123} // namespace esphome
BedjetMode mode
BedJet operating mode.
void feed_wdt(uint32_t time=0)
virtual void mark_failed()
Mark this component as failed.
virtual void setup()=0
virtual void digital_write(bool value)=0
virtual bool digital_read()=0
A pin to replace those that don't exist.
Definition spi.h:109
static GPIOPin *const NULL_PIN
Definition spi.h:130
virtual bool is_hw()
Definition spi.h:325
virtual SPIDelegate * get_delegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin, bool release_device, bool write_only)
Definition spi.h:320
Base class for SPIDevice, un-templated.
Definition spi.h:387
void setup() override
Definition spi.cpp:39
void unregister_device(SPIClient *device)
Definition spi.cpp:30
static SPIBus * get_bus(SPIInterface interface, GPIOPin *clk, GPIOPin *sdo, GPIOPin *sdi, const std::vector< uint8_t > &data_pins)
std::map< SPIClient *, SPIDelegate * > devices_
Definition spi.h:376
void dump_config() override
Definition spi.cpp:66
SPIInterface interface_
Definition spi.h:372
SPIDelegate * register_device(SPIClient *device, SPIMode mode, SPIBitOrder bit_order, uint32_t data_rate, GPIOPin *cs_pin, bool release_device, bool write_only)
Definition spi.cpp:18
const char * interface_name_
Definition spi.h:374
std::vector< uint8_t > data_pins_
Definition spi.h:370
uint8_t transfer(uint8_t data) override
Definition spi.cpp:83
SPIClockPolarity clock_polarity_
Definition spi.h:303
void write(uint16_t data, size_t num_bits) override
Definition spi.cpp:85
SPIClockPhase clock_phase_
Definition spi.h:304
uint16_t transfer_(uint16_t data, size_t num_bits)
Definition spi.cpp:87
A dummy SPIDelegate that complains if it's used.
Definition spi.h:266
void begin_transaction() override
Definition spi.cpp:81
virtual bool is_ready()
Definition spi.cpp:14
SPIBitOrder bit_order_
Definition spi.h:255
static SPIDelegate *const NULL_DELEGATE
Definition spi.h:259
SPIMode
Modes mapping to clock phase and polarity.
Definition spi.h:80
const char *const TAG
Definition spi.cpp:8
SPIBitOrder
The bit-order for SPI devices. This defines how the data read from and written to the device is inter...
Definition spi.h:42
@ BIT_ORDER_MSB_FIRST
The most significant bit is transmitted/received first.
Definition spi.h:46
@ CLOCK_PHASE_LEADING
The data is sampled on a leading clock edge. (CPHA=0)
Definition spi.h:70
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
Application App
Global storage of Application pointer - only one Application can exist.