Skip to content

Commit ca7b32d

Browse files
committed
Fix SPI
1 parent f25e3da commit ca7b32d

File tree

2 files changed

+60
-29
lines changed

2 files changed

+60
-29
lines changed

Diff for: libraries/SPI/SPI.cpp

+5-27
Original file line numberDiff line numberDiff line change
@@ -26,29 +26,7 @@
2626
#define SPI_IMODE_EXTINT 1
2727
#define SPI_IMODE_GLOBAL 2
2828

29-
//const SPISettings DEFAULT_SPI_SETTINGS = SPISettings();
30-
31-
static inline SercomDataOrder getBitOrder(SPISettings& settings) {
32-
return (settings.getBitOrder() == MSBFIRST ? MSB_FIRST : LSB_FIRST);
33-
}
34-
35-
static inline SercomSpiClockMode getDataMode(SPISettings& settings) {
36-
switch (settings.getDataMode())
37-
{
38-
case SPI_MODE0:
39-
return SERCOM_SPI_MODE_0; break;
40-
case SPI_MODE1:
41-
return SERCOM_SPI_MODE_1; break;
42-
case SPI_MODE2:
43-
return SERCOM_SPI_MODE_2; break;
44-
case SPI_MODE3:
45-
return SERCOM_SPI_MODE_3; break;
46-
default:
47-
return SERCOM_SPI_MODE_0; break;
48-
}
49-
}
50-
51-
SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, SercomSpiTXPad PadTx, SercomRXPad PadRx)
29+
SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, SercomSpiTXPad PadTx, SercomRXPad PadRx) : settings(SPISettings(0, MSBFIRST, SPI_MODE0))
5230
{
5331
initialized = false;
5432
assert(p_sercom != NULL);
@@ -86,14 +64,14 @@ void SPIClass::init()
8664
initialized = true;
8765
}
8866

89-
void SPIClass::config(SPISettings settings)
67+
void SPIClass::config(SPISettingsSAMD settings)
9068
{
9169
if (this->settings != settings) {
9270
this->settings = settings;
9371
_p_sercom->disableSPI();
9472

95-
_p_sercom->initSPI(_padTx, _padRx, SPI_CHAR_SIZE_8_BITS, getBitOrder(settings));
96-
_p_sercom->initSPIClock(getDataMode(settings), settings.getClockFreq());
73+
_p_sercom->initSPI(_padTx, _padRx, SPI_CHAR_SIZE_8_BITS, settings.bitOrder);
74+
_p_sercom->initSPIClock(settings.dataMode, settings.clockFreq);
9775

9876
_p_sercom->enableSPI();
9977
}
@@ -155,7 +133,7 @@ void SPIClass::notUsingInterrupt(int interruptNumber)
155133
interrupts();
156134
}
157135

158-
void SPIClass::beginTransaction(SPISettings settings)
136+
void SPIClass::beginTransaction(SPISettingsSAMD settings)
159137
{
160138
if (interruptMode != SPI_IMODE_NONE)
161139
{

Diff for: libraries/SPI/SPI.h

+55-2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,53 @@
4646
#define SPI_MIN_CLOCK_DIVIDER (uint8_t)(1 + ((F_CPU - 1) / 12000000))
4747
#endif
4848

49+
class SPISettingsSAMD : public arduino::SPISettings {
50+
public:
51+
SPISettingsSAMD(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) {
52+
if (__builtin_constant_p(clock)) {
53+
init_AlwaysInline(clock, bitOrder, dataMode);
54+
} else {
55+
init_MightInline(clock, bitOrder, dataMode);
56+
}
57+
}
58+
59+
// Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first.
60+
SPISettingsSAMD() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); }
61+
62+
SPISettingsSAMD(SPISettings& x) { SPISettingsSAMD(x.getClockFreq(), x.getBitOrder(), x.getDataMode()); }
63+
64+
private:
65+
void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) {
66+
init_AlwaysInline(clock, bitOrder, dataMode);
67+
}
68+
69+
void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) {
70+
this->clockFreq = (clock >= (F_CPU / SPI_MIN_CLOCK_DIVIDER) ? F_CPU / SPI_MIN_CLOCK_DIVIDER : clock);
71+
72+
this->bitOrder = (bitOrder == MSBFIRST ? MSB_FIRST : LSB_FIRST);
73+
74+
switch (dataMode)
75+
{
76+
case SPI_MODE0:
77+
this->dataMode = SERCOM_SPI_MODE_0; break;
78+
case SPI_MODE1:
79+
this->dataMode = SERCOM_SPI_MODE_1; break;
80+
case SPI_MODE2:
81+
this->dataMode = SERCOM_SPI_MODE_2; break;
82+
case SPI_MODE3:
83+
this->dataMode = SERCOM_SPI_MODE_3; break;
84+
default:
85+
this->dataMode = SERCOM_SPI_MODE_0; break;
86+
}
87+
}
88+
89+
uint32_t clockFreq;
90+
SercomSpiClockMode dataMode;
91+
SercomDataOrder bitOrder;
92+
93+
friend class SPIClassSAMD;
94+
};
95+
4996
class SPIClassSAMD : public arduino::HardwareSPI {
5097
public:
5198
SPIClassSAMD(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, SercomSpiTXPad, SercomRXPad);
@@ -57,7 +104,10 @@ class SPIClassSAMD : public arduino::HardwareSPI {
57104
// Transaction Functions
58105
void usingInterrupt(int interruptNumber);
59106
void notUsingInterrupt(int interruptNumber);
60-
void beginTransaction(SPISettings settings);
107+
void beginTransaction(SPISettingsSAMD settings);
108+
void beginTransaction(SPISettings settings) {
109+
beginTransaction(SPISettingsSAMD(settings));
110+
}
61111
void endTransaction(void);
62112

63113
// SPI Configuration methods
@@ -73,7 +123,10 @@ class SPIClassSAMD : public arduino::HardwareSPI {
73123

74124
private:
75125
void init();
76-
void config(SPISettings settings);
126+
void config(SPISettingsSAMD settings);
127+
void config(SPISettings settings) {
128+
config(SPISettingsSAMD(settings));
129+
}
77130

78131
SERCOM *_p_sercom;
79132
uint8_t _uc_pinMiso;

0 commit comments

Comments
 (0)