Libraries/HardwareSPI/src/include/HSPI/Device.h
Go to the documentation of this file.
1 /****
2  * Device.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  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with this library.
16  * If not, see <https://www.gnu.org/licenses/>.
17  *
18  * @author: 11 December 2018 - mikee47 <mike@sillyhouse.net>
19  *
20  * SPI slave device management on hardware SPI bus (HSPI).
21  *
22  * Device specifies how bus will be used:
23  *
24  * - Bit order
25  * - Frequency
26  * - Data mode
27  * - Port selection: SPI1 is the regular HSPI pin connections, SPI0 uses overlapped mode
28  * - Chip select: Automatic (CS2) which is mandatory for SPI0, or manual
29  *
30  * Device classes may be defined to add specific functionality, such as mode switching.
31  ****/
32 
33 #pragma once
34 
35 #include "Controller.h"
36 
37 namespace HSPI
38 {
44 class Device
45 {
46 public:
48  {
49  }
50 
51  virtual ~Device()
52  {
53  end();
54  }
55 
62  bool begin(PinSet pinSet, uint8_t chipSelect, uint32_t clockSpeed)
63  {
64  return controller.startDevice(*this, pinSet, chipSelect, clockSpeed);
65  }
66 
67  void end()
68  {
69  controller.stopDevice(*this);
70  }
71 
76  bool isReady() const
77  {
78  return pinSet != PinSet::none;
79  }
80 
81  PinSet getPinSet() const
82  {
83  return pinSet;
84  }
85 
86  uint8_t getChipSelect() const
87  {
88  return chipSelect;
89  }
90 
91  uint32_t getSpeed() const
92  {
93  return speed;
94  }
95 
96  /*
97  * Byte ordering is consistent with processor, i.e. always LSB first, but bit ordering
98  * is variable.
99  */
100  void setBitOrder(BitOrder bitOrder)
101  {
102  if(this->bitOrder != bitOrder) {
103  this->bitOrder = bitOrder;
104  controller.configChanged(*this);
105  }
106  }
107 
108  BitOrder getBitOrder() const
109  {
110  return bitOrder;
111  }
112 
113  void setClockMode(ClockMode mode)
114  {
115  if(clockMode != mode) {
116  clockMode = mode;
117  controller.configChanged(*this);
118  }
119  }
120 
121  ClockMode getClockMode() const
122  {
123  return clockMode;
124  }
125 
129  virtual IoModes getSupportedIoModes() const = 0;
130 
135  bool isSupported(IoMode mode) const
136  {
137  return controller.getSupportedIoModes(*this)[mode];
138  }
139 
140  virtual bool setIoMode(IoMode mode)
141  {
142  if(ioMode != mode) {
143  ioMode = mode;
144  controller.configChanged(*this);
145  }
146  return true;
147  }
148 
149  IoMode getIoMode() const
150  {
151  return ioMode;
152  }
153 
154  size_t getBitsPerClock() const
155  {
156  switch(ioMode) {
157  case IoMode::SPI:
158  case IoMode::SPIHD:
159  return 1;
161  case IoMode::DIO:
162  case IoMode::SDI:
163  return 2;
164  case IoMode::QUAD:
165  case IoMode::QIO:
166  case IoMode::SQI:
167  return 4;
168  default:
169  return 1;
170  }
171  }
172 
173  void execute(Request& request)
174  {
175  request.device = this;
176  controller.execute(request);
177  }
178 
183  void onTransfer(Callback callback)
184  {
185  transferCallback = callback;
186  }
187 
188  void wait(Request& request)
189  {
190  if(request.busy) {
191  controller.wait(request);
192  }
193  }
194 
196 
197 protected:
198  friend Controller;
199 
200  void IRAM_ATTR transferStarting(Request& request)
201  {
202  if(transferCallback) {
203  transferCallback(request);
204  }
205  }
206 
207  bool IRAM_ATTR transferComplete(Request& request)
208  {
209  if(transferCallback && !transferCallback(request)) {
210  // Re-submit this request
211  return false;
212  }
213  if(request.callback && !request.callback(request)) {
214  return false;
215  }
216  // All done with this request
217  return true;
218  }
219 
220 private:
221  DeviceConfig config{};
222  PinSet pinSet{PinSet::none};
223  uint8_t chipSelect{255};
224  uint32_t speed{0};
225  BitOrder bitOrder{MSBFIRST};
226  ClockMode clockMode{};
227  IoMode ioMode{};
228  Callback transferCallback{nullptr};
229 };
230 
231 } // namespace HSPI
@ QIO
Four bits per clock for Address and Data, 1-bit for Command.
void configChanged(Device &dev)
Devices call this method to tell the Controller about configuration changes. Internally,...
virtual void execute(Request &request)
Definition: Common.h:34
@ SDI
Two bits per clock for Command, Address and Data.
bool begin(PinSet pinSet, uint8_t chipSelect, uint32_t clockSpeed)
Register device with controller and prepare for action.
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:122
IoMode getIoMode() const
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:209
bool(*)(Request &request) Callback
SPI completion callback routine.
Definition: HardwareSPI/src/include/HSPI/Request.h:63
void setBitOrder(BitOrder bitOrder)
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:160
Device * device
Target device for this request.
Definition: HardwareSPI/src/include/HSPI/Request.h:80
@ SPI
One bit per clock, MISO stage concurrent with MISO (full-duplex)
#define MSBFIRST
Definition: WConstants.h:63
virtual bool setIoMode(IoMode mode)
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:200
uint8_t getChipSelect() const
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:146
@ SQI
Four bits per clock for Command, Address and Data.
@ DUAL
Two bits per clock for Data, 1-bit for Command and Address.
uint32_t getSpeed() const
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:151
@ DIO
Two bits per clock for Address and Data, 1-bit for Command.
Callback callback
Completion routine.
Definition: HardwareSPI/src/include/HSPI/Request.h:93
void end()
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:127
IoModes getSupportedIoModes(const Device &dev) const
Determine which IO modes are supported for the given device.
Manages access to SPI hardware.
Definition: HardwareSPI/src/include/HSPI/Controller.h:71
void setClockMode(ClockMode mode)
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:173
uint8_t BitOrder
Definition: Common.h:103
bool isSupported(IoMode mode) const
Determine if the device/controller combination supports an IO mode Must be called after begin() as ot...
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:195
void wait(Request &request)
virtual void stopDevice(Device &dev)
Release CS for a device.
void onTransfer(Callback callback)
Set a callback to be invoked before a request is started, and when it has finished.
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:243
PinSet getPinSet() const
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:141
IoMode
Mode of data transfer.
Definition: Common.h:49
Defines an SPI Request Packet.
Definition: HardwareSPI/src/include/HSPI/Request.h:79
Manage a set of bit values using enumeration.
Definition: BitSet.h:44
PinSet
How SPI hardware pins are connected.
Definition: Common.h:108
void transferStarting(Request &request)
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:260
size_t getBitsPerClock() const
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:214
@ QUAD
Four bits per clock for Data, 1-bit for Command and Address.
bool transferComplete(Request &request)
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:267
bool isReady() const
Determine if the device is initialised.
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:136
void execute(Request &request)
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:233
ClockMode getClockMode() const
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:181
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.
Controller & controller
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:255
friend Controller
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:258
Device(Controller &controller)
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:107
void wait(Request &request)
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:248
ClockMode
SPI clock polarity (CPOL) and phase (CPHA)
Definition: Common.h:39
virtual ~Device()
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:111
@ none
Disabled.
@ SPIHD
One bit per clock, MISO stage follows MOSI (half-duplex)
virtual IoModes getSupportedIoModes() const =0
Return set of IO modes supported by a device implementation.
BitOrder getBitOrder() const
Definition: Libraries/HardwareSPI/src/include/HSPI/Device.h:168