ESPHome 2025.5.0
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) {
20 if (this->devices_.count(device) != 0) {
21 ESP_LOGE(TAG, "SPI device already registered");
22 return this->devices_[device];
23 }
24 SPIDelegate *delegate = this->spi_bus_->get_delegate(data_rate, bit_order, mode, cs_pin); // NOLINT
25 this->devices_[device] = delegate;
26 return delegate;
27}
28
30 if (this->devices_.count(device) == 0) {
31 esph_log_e(TAG, "SPI device not registered");
32 return;
33 }
34 delete this->devices_[device]; // NOLINT
35 this->devices_.erase(device);
36}
37
39 ESP_LOGD(TAG, "Setting up SPI bus...");
40
41 if (this->sdo_pin_ == nullptr)
43 if (this->sdi_pin_ == nullptr)
45 if (this->clk_pin_ == nullptr) {
46 ESP_LOGE(TAG, "No clock pin for SPI");
47 this->mark_failed();
48 return;
49 }
50
51 if (this->using_hw_) {
52 this->spi_bus_ =
53 SPIComponent::get_bus(this->interface_, this->clk_pin_, this->sdo_pin_, this->sdi_pin_, this->data_pins_);
54 if (this->spi_bus_ == nullptr) {
55 ESP_LOGE(TAG, "Unable to allocate SPI interface");
56 this->mark_failed();
57 }
58 } else {
59 this->spi_bus_ = new SPIBus(this->clk_pin_, this->sdo_pin_, this->sdi_pin_); // NOLINT
60 this->clk_pin_->setup();
61 this->clk_pin_->digital_write(true);
62 this->sdo_pin_->setup();
63 this->sdi_pin_->setup();
64 }
65}
66
68 ESP_LOGCONFIG(TAG, "SPI bus:");
69 LOG_PIN(" CLK Pin: ", this->clk_pin_)
70 LOG_PIN(" SDI Pin: ", this->sdi_pin_)
71 LOG_PIN(" SDO Pin: ", this->sdo_pin_)
72 for (size_t i = 0; i != this->data_pins_.size(); i++) {
73 ESP_LOGCONFIG(TAG, " Data pin %u: GPIO%d", i, this->data_pins_[i]);
74 }
75 if (this->spi_bus_->is_hw()) {
76 ESP_LOGCONFIG(TAG, " Using HW SPI: %s", this->interface_name_);
77 } else {
78 ESP_LOGCONFIG(TAG, " Using software SPI");
79 }
80}
81
82void SPIDelegateDummy::begin_transaction() { ESP_LOGE(TAG, "SPIDevice not initialised - did you call spi_setup()?"); }
83
84uint8_t SPIDelegateBitBash::transfer(uint8_t data) { return this->transfer_(data, 8); }
85
86void SPIDelegateBitBash::write(uint16_t data, size_t num_bits) { this->transfer_(data, num_bits); }
87
88uint16_t SPIDelegateBitBash::transfer_(uint16_t data, size_t num_bits) {
89 // Clock starts out at idle level
91 uint16_t out_data = 0;
92
93 for (uint8_t i = 0; i != num_bits; i++) {
94 uint8_t shift;
96 shift = num_bits - 1 - i;
97 } else {
98 shift = i;
99 }
100
102 // sampling on leading edge
103 this->sdo_pin_->digital_write(data & (1 << shift));
104 this->cycle_clock_();
105 out_data |= uint16_t(this->sdi_pin_->digital_read()) << shift;
107 this->cycle_clock_();
109 } else {
110 // sampling on trailing edge
111 this->cycle_clock_();
113 this->sdo_pin_->digital_write(data & (1 << shift));
114 this->cycle_clock_();
115 out_data |= uint16_t(this->sdi_pin_->digital_read()) << shift;
117 }
118 }
119 App.feed_wdt();
120 return out_data;
121}
122
123} // namespace spi
124} // 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:324
virtual SPIDelegate * get_delegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin)
Definition spi.h:320
Base class for SPIDevice, un-templated.
Definition spi.h:386
void setup() override
Definition spi.cpp:38
void unregister_device(SPIClient *device)
Definition spi.cpp:29
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:375
SPIDelegate * register_device(SPIClient *device, SPIMode mode, SPIBitOrder bit_order, uint32_t data_rate, GPIOPin *cs_pin)
Definition spi.cpp:18
void dump_config() override
Definition spi.cpp:67
SPIInterface interface_
Definition spi.h:371
const char * interface_name_
Definition spi.h:373
std::vector< uint8_t > data_pins_
Definition spi.h:369
uint8_t transfer(uint8_t data) override
Definition spi.cpp:84
SPIClockPolarity clock_polarity_
Definition spi.h:303
void write(uint16_t data, size_t num_bits) override
Definition spi.cpp:86
SPIClockPhase clock_phase_
Definition spi.h:304
uint16_t transfer_(uint16_t data, size_t num_bits)
Definition spi.cpp:88
A dummy SPIDelegate that complains if it's used.
Definition spi.h:266
void begin_transaction() override
Definition spi.cpp:82
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.