-
Notifications
You must be signed in to change notification settings - Fork 1k
/
Copy pathSPI.h
191 lines (164 loc) · 5.27 KB
/
SPI.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
* Copyright (c) 2010 by Cristian Maglie <c.maglie@arduino.cc>
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
* SPI Master library for arduino.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#ifndef _SPI_H_INCLUDED
#define _SPI_H_INCLUDED
#include "Arduino.h"
#include <stdio.h>
extern "C" {
#include "utility/spi_com.h"
}
// SPI_HAS_TRANSACTION means SPI has
// - beginTransaction()
// - endTransaction()
// - usingInterrupt()
// - SPISetting(clock, bitOrder, dataMode)
#define SPI_HAS_TRANSACTION 1
// Compatibility with sketches designed for AVR @ 16 MHz could not
// be ensured as SPI frequency depends of system clock configuration.
// user have to use appropriate divider for the SPI clock
// This function should not be used in new project.
// Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
#define SPI_CLOCK_DIV2 2
#define SPI_CLOCK_DIV4 4
#define SPI_CLOCK_DIV8 8
#define SPI_CLOCK_DIV16 16
#define SPI_CLOCK_DIV32 32
#define SPI_CLOCK_DIV64 64
#define SPI_CLOCK_DIV128 128
#define SPI_TRANSMITRECEIVE false
#define SPI_TRANSMITONLY true
class SPISettings {
public:
constexpr SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode)
: clockFreq(clock),
bitOrder(bitOrder),
dataMode((SPIMode)dataMode)
{ }
constexpr SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode)
: clockFreq(clock),
bitOrder(bitOrder),
dataMode(dataMode)
{ }
constexpr SPISettings()
: clockFreq(SPI_SPEED_CLOCK_DEFAULT),
bitOrder(MSBFIRST),
dataMode(SPI_MODE0)
{ }
bool operator==(const SPISettings &rhs) const
{
if ((this->clockFreq == rhs.clockFreq) &&
(this->bitOrder == rhs.bitOrder) &&
(this->dataMode == rhs.dataMode)) {
return true;
}
return false;
}
bool operator!=(const SPISettings &rhs) const
{
return !(*this == rhs);
}
private:
uint32_t clockFreq; //specifies the spi bus maximum clock speed
BitOrder bitOrder; //bit order (MSBFirst or LSBFirst)
SPIMode dataMode; //one of the data mode
friend class SPIClass;
};
class SPIClass {
public:
SPIClass();
SPIClass(uint32_t mosi, uint32_t miso, uint32_t sclk, uint32_t ssel = PNUM_NOT_DEFINED);
// setMISO/MOSI/SCLK/SSEL have to be called before begin()
void setMISO(uint32_t miso)
{
_spi.pin_miso = digitalPinToPinName(miso);
};
void setMOSI(uint32_t mosi)
{
_spi.pin_mosi = digitalPinToPinName(mosi);
};
void setSCLK(uint32_t sclk)
{
_spi.pin_sclk = digitalPinToPinName(sclk);
};
void setSSEL(uint32_t ssel)
{
_spi.pin_ssel = digitalPinToPinName(ssel);
};
void setMISO(PinName miso)
{
_spi.pin_miso = (miso);
};
void setMOSI(PinName mosi)
{
_spi.pin_mosi = (mosi);
};
void setSCLK(PinName sclk)
{
_spi.pin_sclk = (sclk);
};
void setSSEL(PinName ssel)
{
_spi.pin_ssel = (ssel);
};
void begin(void);
void end(void);
/* This function should be used to configure the SPI instance in case you
* don't use default parameters.
*/
void beginTransaction(SPISettings settings);
void endTransaction(void);
/* Transfer functions: must be called after initialization of the SPI
* instance with begin() or beginTransaction().
*/
uint8_t transfer(uint8_t data, bool skipReceive = SPI_TRANSMITRECEIVE);
uint16_t transfer16(uint16_t data, bool skipReceive = SPI_TRANSMITRECEIVE);
uint16_t transfer16_obsoleted(uint16_t data, bool skipReceive = SPI_TRANSMITRECEIVE);
void transfer(void *buf, size_t count, bool skipReceive = SPI_TRANSMITRECEIVE);
/* Expand SPI API
* https://github.com/arduino/ArduinoCore-API/discussions/189
*/
void transfer(const void *tx_buf, void *rx_buf, size_t count);
/* These methods are deprecated and kept for compatibility.
* Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
*/
void setBitOrder(BitOrder);
void setDataMode(uint8_t);
void setDataMode(SPIMode);
void setClockDivider(uint8_t);
// Not implemented functions. Kept for compatibility.
void usingInterrupt(int interruptNumber);
void notUsingInterrupt(int interruptNumber);
void attachInterrupt(void);
void detachInterrupt(void);
// Could be used to mix Arduino API and STM32Cube HAL API (ex: DMA). Use at your own risk.
SPI_HandleTypeDef *getHandle(void)
{
return &(_spi.handle);
}
protected:
// spi instance
spi_t _spi;
private:
/* Current SPISettings */
SPISettings _spiSettings = SPISettings();
};
extern SPIClass SPI;
#if defined(SUBGHZSPI_BASE)
class SUBGHZSPIClass : public SPIClass {
public:
SUBGHZSPIClass(): SPIClass{NC, NC, NC, NC}
{
_spi.spi = SUBGHZSPI;
}
void enableDebugPins(uint32_t mosi = DEBUG_SUBGHZSPI_MOSI, uint32_t miso = DEBUG_SUBGHZSPI_MISO, uint32_t sclk = DEBUG_SUBGHZSPI_SCLK, uint32_t ssel = DEBUG_SUBGHZSPI_SS);
};
#endif
#endif /* _SPI_H_INCLUDED */