Open FFBoard
Open source force feedback firmware
Loading...
Searching...
No Matches
SPI.cpp
Go to the documentation of this file.
1#include <algorithm>
2
3#include "SPI.h"
4#include "semaphore.hpp"
5#include "cppmain.h"
6#include "math.h"
7
8static bool operator==(const SPI_InitTypeDef& lhs, const SPI_InitTypeDef& rhs) {
9 return memcmp(&lhs,&rhs,sizeof(SPI_InitTypeDef)) == 0;
10}
11
12
13
14SPIPort::SPIPort(SPI_HandleTypeDef &hspi,const std::vector<OutputPin>& csPins,uint32_t baseclk,bool allowReconfigure)
15: hspi{hspi}{
16 this->current_device = nullptr;
17 this->allowReconfigure = allowReconfigure;
18 this->csPins = csPins;
19 this->freePins = csPins;
20 this->baseclk = baseclk;
21}
22
23// ----------------------------------
24//CS pins
26 auto it = std::find(freePins.begin(), freePins.end(), pin);
27 if(it != freePins.end()){
28 freePins.erase(it);
29 return true;
30 }
31 // Pin not found or not free
32 return false;
33}
34
35
36
38 // is in pins
39 if(std::find(csPins.begin(),csPins.end(), pin) != csPins.end()){
40 // is not in free pins
41 if(std::find(freePins.begin(),freePins.end(), pin) == freePins.end()){
42 freePins.push_back(pin);
43 return true;
44 }
45 }
46
47 // Pin not found
48 return false;
49}
50
52 return(std::find(freePins.begin(),freePins.end(), pin) != freePins.end());
53}
54
55std::vector<OutputPin>& SPIPort::getFreeCsPins(){
56
57 return freePins;
58}
59
60
61std::vector<OutputPin>& SPIPort::getCsPins(){
62 return csPins;
63}
64
66 if(idx < csPins.size()){
67 return &csPins[idx];
68 }
69 return nullptr;
70}
71
72void SPIPort::configurePort(SPI_InitTypeDef* config){
73 if(config == nullptr || hspi.Init == *config){
74 return; // No need to reconfigure
75 }
76 hspi.Init = *config;
77 HAL_SPI_Init(&hspi);
78}
79
80SPI_HandleTypeDef* SPIPort::getPortHandle(){
81 return &hspi;
82}
83
84// ----------------------------------
89void SPIPort::transmit_DMA(const uint8_t* buf,uint16_t size,SPIDevice* device){
90 device->beginSpiTransfer(this);
91 current_device = device; // Will call back this device
92 if(!takenExclusive && this->allowReconfigure){
93 this->configurePort(&device->getSpiConfig()->peripheral);
94 }
95 HAL_SPI_Transmit_DMA(&this->hspi,const_cast<uint8_t*>(buf),size);
96 // Request completes in tx complete callback
97}
98
103void SPIPort::transmitReceive_DMA(const uint8_t* txbuf,uint8_t* rxbuf,uint16_t size,SPIDevice* device){
104 device->beginSpiTransfer(this);
105 if(!takenExclusive && this->allowReconfigure){
106 this->configurePort(&device->getSpiConfig()->peripheral);
107 }
108 current_device = device; // Will call back this device
109 HAL_SPI_TransmitReceive_DMA(&this->hspi,const_cast<uint8_t*>(txbuf),rxbuf,size);
110 // Request completes in rxtx complete callback
111}
112
117void SPIPort::receive_DMA(uint8_t* buf,uint16_t size,SPIDevice* device){
118 device->beginSpiTransfer(this);
119 if(!takenExclusive && this->allowReconfigure){
120 this->configurePort(&device->getSpiConfig()->peripheral);
121 }
122 current_device = device;
123 HAL_SPI_Receive_DMA(&this->hspi,buf,size);
124 // Request completes in rx complete callback
125}
126
127
128void SPIPort::transmit_IT(const uint8_t* buf,uint16_t size,SPIDevice* device){
129 device->beginSpiTransfer(this);
130 current_device = device; // Will call back this device
131 if(!takenExclusive && this->allowReconfigure){
132 this->configurePort(&device->getSpiConfig()->peripheral);
133 }
134 HAL_SPI_Transmit_IT(&this->hspi,const_cast<uint8_t*>(buf),size);
135 // Request completes in tx complete callback
136}
137
138void SPIPort::transmitReceive_IT(const uint8_t* txbuf,uint8_t* rxbuf,uint16_t size,SPIDevice* device){
139 device->beginSpiTransfer(this);
140 if(!takenExclusive && this->allowReconfigure){
141 this->configurePort(&device->getSpiConfig()->peripheral);
142 }
143 current_device = device; // Will call back this device
144 HAL_SPI_TransmitReceive_IT(&this->hspi,const_cast<uint8_t*>(txbuf),rxbuf,size);
145 // Request completes in rxtx complete callback
146}
147
148void SPIPort::receive_IT(uint8_t* buf,uint16_t size,SPIDevice* device){
149 device->beginSpiTransfer(this);
150 if(!takenExclusive && this->allowReconfigure){
151 this->configurePort(&device->getSpiConfig()->peripheral);
152 }
153 current_device = device;
154 HAL_SPI_Receive_IT(&this->hspi,buf,size);
155 // Request completes in rx complete callback
156}
157
158void SPIPort::transmit(const uint8_t* buf,uint16_t size,SPIDevice* device,uint16_t timeout){
159 device->beginSpiTransfer(this);
160 if(!takenExclusive && this->allowReconfigure){
161 this->configurePort(&device->getSpiConfig()->peripheral);
162 }
163 HAL_SPI_Transmit(&this->hspi,const_cast<uint8_t*>(buf),size,timeout);
164 device->endSpiTransfer(this);
165}
166
167void SPIPort::receive(uint8_t* buf,uint16_t size,SPIDevice* device,int16_t timeout){
168 device->beginSpiTransfer(this);
169 if(!takenExclusive && this->allowReconfigure){
170 this->configurePort(&device->getSpiConfig()->peripheral);
171 }
172 HAL_SPI_Receive(&this->hspi,buf,size,timeout);
173 device->endSpiTransfer(this);
174}
175
176void SPIPort::transmitReceive(const uint8_t* txbuf,uint8_t* rxbuf,uint16_t size,SPIDevice* device,uint16_t timeout){
177 device->beginSpiTransfer(this);
178 if(!takenExclusive && this->allowReconfigure){
179 this->configurePort(&device->getSpiConfig()->peripheral);
180 }
181 HAL_SPI_TransmitReceive(&this->hspi,const_cast<uint8_t*>(txbuf),rxbuf,size,timeout);
182 device->endSpiTransfer(this);
183}
184// --------------------------------
185
187 bool isIsr = inIsr();
188
189 if(isIsr){
190 BaseType_t taskWoken = 0;
191 this->semaphore.TakeFromISR(&taskWoken);
192 portYIELD_FROM_ISR(taskWoken);
193 }else{
194 this->semaphore.Take();
195 }
196 isTakenFlag = true;
197}
198
200 bool isIsr = inIsr();
201 isTakenFlag = false;
202 if(isIsr){
203 BaseType_t taskWoken = 0;
204 this->semaphore.GiveFromISR(&taskWoken);
205 portYIELD_FROM_ISR(taskWoken);
206 }else{
207 this->semaphore.Give();
208 }
209
210}
211
213 return isTakenFlag;
214}
215
216void SPIPort::takeExclusive(bool exclusive){
217 takenExclusive = exclusive;
218}
219
221 return !takenExclusive && this->getCsPins().size() > 0;
222}
223
228 return this->baseclk;
229}
230
231// interrupt callbacks
232void SPIPort::SpiTxCplt(SPI_HandleTypeDef *hspi) {
233 if (current_device == nullptr) {
234 return;
235 }
236
237 if (hspi->Instance != this->hspi.Instance) {
238 return;
239 }
240 current_device->endSpiTransfer(this);
241 current_device->spiTxCompleted(this);
242
243 current_device = nullptr;
244
245}
246void SPIPort::SpiRxCplt(SPI_HandleTypeDef *hspi) {
247 if (current_device == nullptr) {
248 return;
249 }
250
251 if (hspi->Instance != this->hspi.Instance) {
252 return;
253 }
254 current_device->endSpiTransfer(this);
255 current_device->spiRxCompleted(this);
256
257 current_device = nullptr;
258}
259void SPIPort::SpiTxRxCplt(SPI_HandleTypeDef *hspi) {
260 if (current_device == nullptr) {
261 return;
262 }
263
264 if (hspi->Instance != this->hspi.Instance) {
265 return;
266 }
267 current_device->endSpiTransfer(this);
268 current_device->spiTxRxCompleted(this);
269
270 current_device = nullptr;
271}
272
273void SPIPort::SpiError(SPI_HandleTypeDef *hspi) {
274 if (current_device == nullptr) {
275 return;
276 }
277
278 if (hspi->Instance != this->hspi.Instance) {
279 return;
280 }
281 current_device->endSpiTransfer(this);
282 current_device->spiRequestError(this);
283
284 current_device = nullptr;
285}
286
291std::pair<uint32_t,float> SPIPort::getClosestPrescaler(float clock){
292 std::vector<std::pair<uint32_t,float>> distances;
293#if defined(SPI_BAUDRATEPRESCALER_2)
294 distances.push_back({SPI_BAUDRATEPRESCALER_2,(baseclk/2.0)});
295#endif
296#if defined(SPI_BAUDRATEPRESCALER_4)
297 distances.push_back({SPI_BAUDRATEPRESCALER_4,(baseclk/4.0)});
298#endif
299#if defined(SPI_BAUDRATEPRESCALER_8)
300 distances.push_back({SPI_BAUDRATEPRESCALER_8,(baseclk/8.0)});
301#endif
302#if defined(SPI_BAUDRATEPRESCALER_16)
303 distances.push_back({SPI_BAUDRATEPRESCALER_16,(baseclk/16.0)});
304#endif
305#if defined(SPI_BAUDRATEPRESCALER_32)
306 distances.push_back({SPI_BAUDRATEPRESCALER_32,(baseclk/32.0)});
307#endif
308#if defined(SPI_BAUDRATEPRESCALER_64)
309 distances.push_back({SPI_BAUDRATEPRESCALER_64,(baseclk/64.0)});
310#endif
311#if defined(SPI_BAUDRATEPRESCALER_128)
312 distances.push_back({SPI_BAUDRATEPRESCALER_128,(baseclk/128.0)});
313#endif
314#if defined(SPI_BAUDRATEPRESCALER_256)
315 distances.push_back({SPI_BAUDRATEPRESCALER_256,(baseclk/256.0)});
316#endif
317 // Calc distances
318 std::pair<uint32_t,float> bestVal = distances[0];
319 float bestDist = INFINITY;
320 for(auto& val : distances){
321 if(std::abs(clock-val.second) < bestDist){
322 bestDist = abs(clock-val.second);
323 bestVal = val;
324 }
325 }
326 return bestVal;
327}
328
333 this->spiConfig.cs = csPin;
334 spiPort.reserveCsPin(spiConfig.cs);
335}
337 spiPort.freeCsPin(spiConfig.cs);
338}
339
341 if(csPin == spiConfig.cs){
342 return true;
343 }
344 if(!spiPort.isPinFree(csPin)){
345 return false;
346 }
347
348 if(!spiPort.freeCsPin(spiConfig.cs)){
349 return false;
350 }
351 spiConfig.cs = csPin;
352 return spiPort.reserveCsPin(csPin);
353}
354
355/*
356 * Called before the spi transfer starts.
357 * Can be used to take the semaphore and set CS pins by default
358 */
363
364/*
365 * Called after a transfer is finished
366 * Gives a semaphore back and resets the CS pin
367 */
372
374 spiConfig.cs.write(!spiConfig.cspol);
375}
376
378 spiConfig.cs.write(spiConfig.cspol);
379}
static bool operator==(const SPI_InitTypeDef &lhs, const SPI_InitTypeDef &rhs)
Definition SPI.cpp:8
virtual bool updateCSPin(OutputPin &csPin)
Definition SPI.cpp:340
SPIPort & spiPort
Definition SPI.h:124
virtual void beginSpiTransfer(SPIPort *port)
Definition SPI.cpp:359
SPIDevice(SPIPort &port, OutputPin csPin)
Definition SPI.cpp:332
virtual ~SPIDevice()
Definition SPI.cpp:336
void assertChipSelect()
Definition SPI.cpp:373
virtual SPIConfig * getSpiConfig()
Definition SPI.h:120
void clearChipSelect()
Definition SPI.cpp:377
virtual void endSpiTransfer(SPIPort *port)
Definition SPI.cpp:368
SPIConfig spiConfig
Definition SPI.h:125
Definition SPI.h:43
void transmitReceive(const uint8_t *txbuf, uint8_t *rxbuf, uint16_t size, SPIDevice *device, uint16_t timeout)
Definition SPI.cpp:176
void transmit_IT(const uint8_t *buf, uint16_t size, SPIDevice *device)
Definition SPI.cpp:128
std::vector< OutputPin > & getCsPins()
Definition SPI.cpp:61
bool hasFreePins()
Definition SPI.cpp:220
SPIDevice * current_device
Definition SPI.h:89
SPI_HandleTypeDef & hspi
Definition SPI.h:88
bool isPinFree(OutputPin pin)
Definition SPI.cpp:51
void takeExclusive(bool exclusive)
Definition SPI.cpp:216
void takeSemaphore()
Definition SPI.cpp:186
bool reserveCsPin(OutputPin pin)
Definition SPI.cpp:25
std::pair< uint32_t, float > getClosestPrescaler(float clock)
Definition SPI.cpp:291
uint32_t getBaseClk()
Definition SPI.cpp:227
std::vector< OutputPin > & getFreeCsPins()
Definition SPI.cpp:55
std::vector< OutputPin > freePins
Definition SPI.h:91
SPI_HandleTypeDef * getPortHandle()
Definition SPI.cpp:80
void receive(uint8_t *buf, uint16_t size, SPIDevice *device, int16_t timeout)
Definition SPI.cpp:167
void transmitReceive_DMA(const uint8_t *txbuf, uint8_t *rxbuf, uint16_t size, SPIDevice *device)
Definition SPI.cpp:103
void SpiError(SPI_HandleTypeDef *hspi) override
Definition SPI.cpp:273
void SpiTxCplt(SPI_HandleTypeDef *hspi) override
Definition SPI.cpp:232
void transmit(const uint8_t *buf, uint16_t size, SPIDevice *device, uint16_t timeout)
Definition SPI.cpp:158
void receive_DMA(uint8_t *buf, uint16_t size, SPIDevice *device)
Definition SPI.cpp:117
bool isTaken()
Definition SPI.cpp:212
void transmitReceive_IT(const uint8_t *txbuf, uint8_t *rxbuf, uint16_t size, SPIDevice *device)
Definition SPI.cpp:138
bool takenExclusive
Definition SPI.h:96
void transmit_DMA(const uint8_t *buf, uint16_t size, SPIDevice *device)
Definition SPI.cpp:89
OutputPin * getCsPin(uint16_t idx)
Definition SPI.cpp:65
std::vector< OutputPin > csPins
Definition SPI.h:90
void SpiTxRxCplt(SPI_HandleTypeDef *hspi) override
Definition SPI.cpp:259
void configurePort(SPI_InitTypeDef *config)
Definition SPI.cpp:72
void giveSemaphore()
Definition SPI.cpp:199
void receive_IT(uint8_t *buf, uint16_t size, SPIDevice *device)
Definition SPI.cpp:148
bool freeCsPin(OutputPin pin)
Definition SPI.cpp:37
volatile bool isTakenFlag
Definition SPI.h:95
bool allowReconfigure
Definition SPI.h:94
void SpiRxCplt(SPI_HandleTypeDef *hspi) override
Definition SPI.cpp:246
cpp_freertos::BinarySemaphore semaphore
Definition SPI.h:93
SPIPort(SPI_HandleTypeDef &hspi, const std::vector< OutputPin > &csPins, uint32_t baseclk, bool allowReconfigure=true)
Definition SPI.cpp:14
uint32_t baseclk
Definition SPI.h:97
static bool inIsr()
Definition cppmain.h:41
SPI_InitTypeDef peripheral
Definition SPI.h:38