ESPHome 2025.7.1
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 ESP_LOGCONFIG(TAG, "Running setup");
41
42 if (this->sdo_pin_ == nullptr)
44 if (this->sdi_pin_ == nullptr)
46 if (this->clk_pin_ == nullptr) {
47 ESP_LOGE(TAG, "No clock pin");
48 this->mark_failed();
49 return;
50 }
51
52 if (this->using_hw_) {
53 this->spi_bus_ =
54 SPIComponent::get_bus(this->interface_, this->clk_pin_, this->sdo_pin_, this->sdi_pin_, this->data_pins_);
55 if (this->spi_bus_ == nullptr) {
56 ESP_LOGE(TAG, "Unable to allocate SPI interface");
57 this->mark_failed();
58 }
59 } else {
60 this->spi_bus_ = new SPIBus(this->clk_pin_, this->sdo_pin_, this->sdi_pin_); // NOLINT
61 this->clk_pin_->setup();
62 this->clk_pin_->digital_write(true);
63 this->sdo_pin_->setup();
64 this->sdi_pin_->setup();
65 }
66}
67
69 ESP_LOGCONFIG(TAG, "SPI bus:");
70 LOG_PIN(" CLK Pin: ", this->clk_pin_)
71 LOG_PIN(" SDI Pin: ", this->sdi_pin_)
72 LOG_PIN(" SDO Pin: ", this->sdo_pin_)
73 for (size_t i = 0; i != this->data_pins_.size(); i++) {
74 ESP_LOGCONFIG(TAG, " Data pin %u: GPIO%d", i, this->data_pins_[i]);
75 }
76 if (this->spi_bus_->is_hw()) {
77 ESP_LOGCONFIG(TAG, " Using HW SPI: %s", this->interface_name_);
78 } else {
79 ESP_LOGCONFIG(TAG, " Using software SPI");
80 }
81}
82
83void SPIDelegateDummy::begin_transaction() { ESP_LOGE(TAG, "SPIDevice not initialised - did you call spi_setup()?"); }
84
85uint8_t SPIDelegateBitBash::transfer(uint8_t data) { return this->transfer_(data, 8); }
86
87void SPIDelegateBitBash::write(uint16_t data, size_t num_bits) { this->transfer_(data, num_bits); }
88
89uint16_t SPIDelegateBitBash::transfer_(uint16_t data, size_t num_bits) {
90 // Clock starts out at idle level
92 uint16_t out_data = 0;
93
94 for (uint8_t i = 0; i != num_bits; i++) {
95 uint8_t shift;
97 shift = num_bits - 1 - i;
98 } else {
99 shift = i;
100 }
101
103 // sampling on leading edge
104 this->sdo_pin_->digital_write(data & (1 << shift));
105 this->cycle_clock_();
106 out_data |= uint16_t(this->sdi_pin_->digital_read()) << shift;
108 this->cycle_clock_();
110 } else {
111 // sampling on trailing edge
112 this->cycle_clock_();
114 this->sdo_pin_->digital_write(data & (1 << shift));
115 this->cycle_clock_();
116 out_data |= uint16_t(this->sdi_pin_->digital_read()) << shift;
118 }
119 }
120 App.feed_wdt();
121 return out_data;
122}
123
124} // namespace spi
125} // 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:68
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:85
SPIClockPolarity clock_polarity_
Definition spi.h:303
void write(uint16_t data, size_t num_bits) override
Definition spi.cpp:87
SPIClockPhase clock_phase_
Definition spi.h:304
uint16_t transfer_(uint16_t data, size_t num_bits)
Definition spi.cpp:89
A dummy SPIDelegate that complains if it's used.
Definition spi.h:266
void begin_transaction() override
Definition spi.cpp:83
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.