ESPHome  2024.11.0
spi.cpp
Go to the documentation of this file.
1 #include "spi.h"
2 #include "esphome/core/log.h"
4 
5 namespace esphome {
6 namespace spi {
7 
8 const char *const TAG = "spi";
9 
10 bool SPIDelegate::is_ready() { return true; }
11 
12 GPIOPin *const NullPin::NULL_PIN = new NullPin(); // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
13 
15  GPIOPin *cs_pin) {
16  if (this->devices_.count(device) != 0) {
17  ESP_LOGE(TAG, "SPI device already registered");
18  return this->devices_[device];
19  }
20  SPIDelegate *delegate = this->spi_bus_->get_delegate(data_rate, bit_order, mode, cs_pin); // NOLINT
21  this->devices_[device] = delegate;
22  return delegate;
23 }
24 
26  if (this->devices_.count(device) == 0) {
27  esph_log_e(TAG, "SPI device not registered");
28  return;
29  }
30  delete this->devices_[device]; // NOLINT
31  this->devices_.erase(device);
32 }
33 
35  ESP_LOGD(TAG, "Setting up SPI bus...");
36 
37  if (this->sdo_pin_ == nullptr)
38  this->sdo_pin_ = NullPin::NULL_PIN;
39  if (this->sdi_pin_ == nullptr)
40  this->sdi_pin_ = NullPin::NULL_PIN;
41  if (this->clk_pin_ == nullptr) {
42  ESP_LOGE(TAG, "No clock pin for SPI");
43  this->mark_failed();
44  return;
45  }
46 
47  if (this->using_hw_) {
48  this->spi_bus_ =
49  SPIComponent::get_bus(this->interface_, this->clk_pin_, this->sdo_pin_, this->sdi_pin_, this->data_pins_);
50  if (this->spi_bus_ == nullptr) {
51  ESP_LOGE(TAG, "Unable to allocate SPI interface");
52  this->mark_failed();
53  }
54  } else {
55  this->spi_bus_ = new SPIBus(this->clk_pin_, this->sdo_pin_, this->sdi_pin_); // NOLINT
56  this->clk_pin_->setup();
57  this->clk_pin_->digital_write(true);
58  this->sdo_pin_->setup();
59  this->sdi_pin_->setup();
60  }
61 }
62 
64  ESP_LOGCONFIG(TAG, "SPI bus:");
65  LOG_PIN(" CLK Pin: ", this->clk_pin_)
66  LOG_PIN(" SDI Pin: ", this->sdi_pin_)
67  LOG_PIN(" SDO Pin: ", this->sdo_pin_)
68  for (size_t i = 0; i != this->data_pins_.size(); i++) {
69  ESP_LOGCONFIG(TAG, " Data pin %u: GPIO%d", i, this->data_pins_[i]);
70  }
71  if (this->spi_bus_->is_hw()) {
72  ESP_LOGCONFIG(TAG, " Using HW SPI: %s", this->interface_name_);
73  } else {
74  ESP_LOGCONFIG(TAG, " Using software SPI");
75  }
76 }
77 
78 uint8_t SPIDelegateBitBash::transfer(uint8_t data) { return this->transfer_(data, 8); }
79 
80 void SPIDelegateBitBash::write(uint16_t data, size_t num_bits) { this->transfer_(data, num_bits); }
81 
82 uint16_t SPIDelegateBitBash::transfer_(uint16_t data, size_t num_bits) {
83  // Clock starts out at idle level
84  this->clk_pin_->digital_write(clock_polarity_);
85  uint8_t out_data = 0;
86 
87  for (uint8_t i = 0; i != num_bits; i++) {
88  uint8_t shift;
90  shift = num_bits - 1 - i;
91  } else {
92  shift = i;
93  }
94 
95  if (clock_phase_ == CLOCK_PHASE_LEADING) {
96  // sampling on leading edge
97  this->sdo_pin_->digital_write(data & (1 << shift));
98  this->cycle_clock_();
99  out_data |= uint16_t(this->sdi_pin_->digital_read()) << shift;
100  this->clk_pin_->digital_write(!this->clock_polarity_);
101  this->cycle_clock_();
102  this->clk_pin_->digital_write(this->clock_polarity_);
103  } else {
104  // sampling on trailing edge
105  this->cycle_clock_();
106  this->clk_pin_->digital_write(!this->clock_polarity_);
107  this->sdo_pin_->digital_write(data & (1 << shift));
108  this->cycle_clock_();
109  out_data |= uint16_t(this->sdi_pin_->digital_read()) << shift;
110  this->clk_pin_->digital_write(this->clock_polarity_);
111  }
112  }
113  App.feed_wdt();
114  return out_data;
115 }
116 
117 } // namespace spi
118 } // namespace esphome
void unregister_device(SPIClient *device)
Definition: spi.cpp:25
The data is sampled on a leading clock edge. (CPHA=0)
Definition: spi.h:66
A pin to replace those that don&#39;t exist.
Definition: spi.h:105
SPIDelegate * register_device(SPIClient *device, SPIMode mode, SPIBitOrder bit_order, uint32_t data_rate, GPIOPin *cs_pin)
Definition: spi.cpp:14
The most significant bit is transmitted/received first.
Definition: spi.h:42
void write(uint16_t data, size_t num_bits) override
Definition: spi.cpp:80
uint16_t transfer_(uint16_t data, size_t num_bits)
Definition: spi.cpp:82
void dump_config() override
Definition: spi.cpp:63
uint8_t transfer(uint8_t data) override
Definition: spi.cpp:78
const char *const TAG
Definition: spi.cpp:8
BedjetMode mode
BedJet operating mode.
Definition: bedjet_codec.h:183
SPIMode
Modes mapping to clock phase and polarity.
Definition: spi.h:76
Application App
Global storage of Application pointer - only one Application can exist.
Base class for SPIDevice, un-templated.
Definition: spi.h:356
static SPIBus * get_bus(SPIInterface interface, GPIOPin *clk, GPIOPin *sdo, GPIOPin *sdi, const std::vector< uint8_t > &data_pins)
Definition: spi_arduino.cpp:88
void setup() override
Definition: spi.cpp:34
SPIBitOrder
The bit-order for SPI devices. This defines how the data read from and written to the device is inter...
Definition: spi.h:38
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
static GPIOPin *const NULL_PIN
Definition: spi.h:124
virtual bool is_ready()
Definition: spi.cpp:10
SPIBitOrder bit_order_
Definition: spi.h:247