HardwareSPI/src/include/HSPI/Controller.h
Go to the documentation of this file.
1 /****
2  * Controller.h
3  *
4  * Copyright 2018 mikee47 <mike@sillyhouse.net>
5  *
6  * This file is part of the HardwareSPI Library
7  *
8  * This library is free software: you can redistribute it and/or modify it under the terms of the
9  * GNU General Public License as published by the Free Software Foundation, version 3 or later.
10  *
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this library.
17  * If not, see <https://www.gnu.org/licenses/>.
18  *
19  * @author: 11 December 2018 - mikee47 <mike@sillyhouse.net>
20  *
21  ****/
22 
23 #pragma once
24 
25 #include <cstdint>
26 #include <esp_attr.h>
27 #include "Request.h"
28 #include <bitset>
29 #include "Common.h"
30 #include <ControllerBase.h>
31 
32 namespace HSPI
33 {
34 class Device;
35 
36 static constexpr uint8_t SPI_PIN_NONE{0xff};
37 static constexpr uint8_t SPI_PIN_DEFAULT{0xfe};
38 
42 struct SpiPins {
43  uint8_t sck{SPI_PIN_DEFAULT};
46 };
47 
51 class Controller : public ControllerBase
52 {
53 public:
64  using SelectDevice = void (*)(uint8_t chipSelect, bool active);
65 
67  {
68  }
69 
70  Controller(SpiBus id, SpiPins pins) : ControllerBase(), busId(id), mPins(pins)
71  {
72  }
73 
74  virtual ~Controller()
75  {
76  end();
77  }
78 
79  /* @brief Initialize the HSPI controller
80  */
81  bool begin();
82 
86  void end();
87 
93  IoModes getSupportedIoModes(const Device& dev) const;
94 
102  {
103  selectDeviceCallback = callback;
104  }
105 
113  virtual bool startDevice(Device& dev, PinSet pinSet, uint8_t chipSelect, uint32_t clockSpeed);
114 
118  virtual void stopDevice(Device& dev);
119 
124  void configChanged(Device& dev);
125 
131  SpiBus getBusId() const
132  {
133  return busId;
134  }
135 
136 #ifdef HSPI_ENABLE_STATS
137  struct Stats {
138  uint32_t requestCount;
139  uint32_t transCount;
140  uint32_t waitCycles;
141  uint32_t tasksQueued;
142  uint32_t tasksCancelled;
143 
144  void clear() volatile
145  {
146  requestCount = 0;
147  transCount = 0;
148  waitCycles = 0;
149  tasksQueued = 0;
150  tasksCancelled = 0;
151  }
152  };
153  static volatile Stats stats;
154 #endif
155 
156  PinSet IRAM_ATTR getActivePinSet() const
157  {
158  return activePinSet;
159  }
160 
161  void wait(Request& request);
162 
168  bool loopback(bool enable);
169 
170  const SpiPins& pins{mPins};
171 
172 protected:
173  friend Device;
174 
175  virtual void execute(Request& request);
176 
180  void assignDefaultPins(const SpiPins& defPins)
181  {
182  if(pins.sck == SPI_PIN_DEFAULT) {
183  mPins.sck = defPins.sck;
184  }
185  if(pins.miso == SPI_PIN_DEFAULT) {
186  mPins.miso = defPins.miso;
187  }
188  if(pins.mosi == SPI_PIN_DEFAULT) {
189  mPins.mosi = defPins.mosi;
190  }
191  }
192 
193 private:
194 #if defined(ARCH_ESP32)
195  static void IRAM_ATTR pre_transfer_callback(spi_transaction_t* t);
196  static void IRAM_ATTR post_transfer_callback(spi_transaction_t* t);
197 #elif defined(ARCH_ESP8266) || defined(ARCH_HOST)
198  static void isr(Controller* spi);
199 #elif defined(ARCH_RP2040)
200  void configure_dma(volatile void* fifo_addr, uint8_t dreq_tx, uint8_t dreq_rx);
201  void release_dma();
202  void interruptHandler();
203  static void staticInterruptHandler();
204 #endif
205 
206  static void updateConfig(Device& dev);
207 
208  void queueTask();
209  void executeTask();
210  void startRequest();
211  void nextTransaction();
212  void transactionDone();
213 
214  SpiBus busId;
215  SpiPins mPins;
216  PinSet activePinSet{PinSet::none};
217  SelectDevice selectDeviceCallback{nullptr};
218 
219  // State of the current transaction in progress
220  struct Transaction {
221  Request* request;
222 #ifdef ARCH_RP2040
223  // RP2040 doesn't have a restriction on transaction size, so doesn't need to split requests
224 #else
225  uint32_t addr;
226  uint16_t outOffset;
227  uint16_t inOffset;
228  uint8_t inlen;
229  IoMode ioMode;
230 #endif
231  // Flags
232  uint8_t bitOrder : 1;
233  volatile uint8_t busy : 1;
234 #ifdef ARCH_ESP8266
235  uint8_t addrShift;
236  uint32_t addrCmdMask;
237 #endif
238  };
239  Transaction trans{};
240 };
241 
242 } // namespace HSPI
Manage a set of bit values using enumeration.
Definition: BitSet.h:45
Manages access to SPI hardware.
Definition: HardwareSPI/src/include/HSPI/Controller.h:52
Controller(SpiBus id, SpiPins pins)
Definition: HardwareSPI/src/include/HSPI/Controller.h:70
virtual void execute(Request &request)
PinSet getActivePinSet() const
Definition: HardwareSPI/src/include/HSPI/Controller.h:156
void onSelectDevice(SelectDevice callback)
Set interrupt callback to use for manual CS control (PinSet::manual) or if CS pin is multiplexed.
Definition: HardwareSPI/src/include/HSPI/Controller.h:101
void configChanged(Device &dev)
Devices call this method to tell the Controller about configuration changes. Internally,...
SpiBus getBusId() const
Get the active bus identifier.
Definition: HardwareSPI/src/include/HSPI/Controller.h:131
void(*)(uint8_t chipSelect, bool active) SelectDevice
Interrupt callback for custom Controllers.
Definition: HardwareSPI/src/include/HSPI/Controller.h:64
void assignDefaultPins(const SpiPins &defPins)
Assign any default pins.
Definition: HardwareSPI/src/include/HSPI/Controller.h:180
Controller(SpiBus id=SpiBus::DEFAULT)
Definition: HardwareSPI/src/include/HSPI/Controller.h:66
IoModes getSupportedIoModes(const Device &dev) const
Determine which IO modes are supported for the given device.
bool loopback(bool enable)
For testing, tie MISO <-> MOSI internally.
void end()
Disable HSPI controller.
virtual bool startDevice(Device &dev, PinSet pinSet, uint8_t chipSelect, uint32_t clockSpeed)
Assign a device to a CS# using a specific pin set. Only one device may be assigned to any CS.
void wait(Request &request)
const SpiPins & pins
Definition: HardwareSPI/src/include/HSPI/Controller.h:170
friend Device
Definition: HardwareSPI/src/include/HSPI/Controller.h:173
virtual void stopDevice(Device &dev)
Release CS for a device.
virtual ~Controller()
Definition: HardwareSPI/src/include/HSPI/Controller.h:74
Manages a specific SPI device instance attached to a controller.
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:45
SpiBus
Identifies bus selection.
Definition: Esp32/spi_arch.h:23
void enable(Handler &commandHandler, HardwareSerial &serial)
Definition: Common.h:35
IoMode
Mode of data transfer.
Definition: Common.h:49
PinSet
How SPI hardware pins are connected.
Definition: Common.h:108
@ none
Disabled.
static constexpr uint8_t SPI_PIN_DEFAULT
Definition: HardwareSPI/src/include/HSPI/Controller.h:37
static constexpr uint8_t SPI_PIN_NONE
Definition: HardwareSPI/src/include/HSPI/Controller.h:36
Defines an SPI Request Packet.
Definition: HardwareSPI/src/include/HSPI/Request.h:57
SPI pin connections.
Definition: HardwareSPI/src/include/HSPI/Controller.h:42
uint8_t sck
Definition: HardwareSPI/src/include/HSPI/Controller.h:43
uint8_t miso
Definition: HardwareSPI/src/include/HSPI/Controller.h:44
uint8_t mosi
Definition: HardwareSPI/src/include/HSPI/Controller.h:45