Skip to content

Commit ac933c7

Browse files
author
fpr
committed
Fix SPI CS pin trouble if use CS pin other than Arduino digital pins
Signed-off-by: fpr <[email protected]>
1 parent d097a55 commit ac933c7

File tree

18 files changed

+260
-265
lines changed

18 files changed

+260
-265
lines changed

libraries/SPI/src/SPI.cpp

Lines changed: 127 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919
SPIClass SPI;
2020

21-
SPIClass::SPIClass() : g_active_id(-1)
21+
SPIClass::SPIClass() : _CSpin(-1)
2222
{
2323
_spi.pin_miso = digitalPinToPinName(MISO);
2424
_spi.pin_mosi = digitalPinToPinName(MOSI);
@@ -29,7 +29,7 @@ SPIClass::SPIClass() : g_active_id(-1)
2929
/* By default hardware SS pin is not used. To use hardware SS pin you should set
3030
ssel pin. Enable this pin disable software CS. See microcontroller documentation
3131
for the list of available SS pins. */
32-
SPIClass::SPIClass(uint8_t mosi, uint8_t miso, uint8_t sclk, uint8_t ssel) : g_active_id(-1)
32+
SPIClass::SPIClass(uint8_t mosi, uint8_t miso, uint8_t sclk, uint8_t ssel) : _CSpin(-1)
3333
{
3434
_spi.pin_miso = digitalPinToPinName(miso);
3535
_spi.pin_mosi = digitalPinToPinName(mosi);
@@ -45,22 +45,30 @@ SPIClass::SPIClass(uint8_t mosi, uint8_t miso, uint8_t sclk, uint8_t ssel) : g_a
4545
//begin using the default chip select
4646
void SPIClass::begin()
4747
{
48-
begin(BOARD_SPI_OWN_SS);
48+
begin(CS_PIN_CONTROLLED_BY_USER);
4949
}
5050

5151
//Begin with a chip select defined
5252
void SPIClass::begin(uint8_t _pin)
5353
{
54-
if(_pin > SPI_CHANNELS_NUM)
54+
uint8_t idx;
55+
56+
if(_pin > NUM_DIGITAL_PINS)
57+
return;
58+
59+
idx = pinIdx(_pin, ADD_NEW_PIN);
60+
if(idx == NB_SPI_SETTINGS)
5561
return;
5662

57-
if((_pin != BOARD_SPI_OWN_SS) && (_spi.pin_ssel == NC)) {
63+
if((_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) {
5864
pinMode(_pin, OUTPUT);
5965
digitalWrite(_pin, HIGH);
6066
}
6167

62-
spi_init(&_spi, spiSettings[_pin].clk, spiSettings[_pin].dMode, spiSettings[_pin].msb);
63-
g_active_id = _pin;
68+
spi_init(&_spi, spiSettings[idx].clk,
69+
spiSettings[idx].dMode,
70+
spiSettings[idx].msb);
71+
_CSpin = _pin;
6472
#if __has_include("WiFi.h")
6573
// Wait wifi shield initialization.
6674
// Should be better to do in SpiDrv::begin() of WiFi library but it seems
@@ -78,73 +86,98 @@ void SPIClass::usingInterrupt(uint8_t interruptNumber)
7886

7987
void SPIClass::beginTransaction(uint8_t _pin, SPISettings settings)
8088
{
81-
if(_pin > SPI_CHANNELS_NUM)
89+
uint8_t idx;
90+
91+
if(_pin > NUM_DIGITAL_PINS)
92+
return;
93+
94+
idx = pinIdx(_pin, ADD_NEW_PIN);
95+
if(idx == NB_SPI_SETTINGS) {
8296
return;
97+
}
8398

84-
spiSettings[_pin].clk = settings.clk;
85-
spiSettings[_pin].dMode = settings.dMode;
86-
spiSettings[_pin].bOrder = settings.bOrder;
87-
if(spiSettings[_pin].bOrder == MSBFIRST) {
88-
spiSettings[_pin].msb = MSBFIRST;
99+
spiSettings[idx].clk = settings.clk;
100+
spiSettings[idx].dMode = settings.dMode;
101+
spiSettings[idx].bOrder = settings.bOrder;
102+
if(spiSettings[idx].bOrder == MSBFIRST) {
103+
spiSettings[idx].msb = MSBFIRST;
89104
} else {
90-
spiSettings[_pin].msb = LSBFIRST;
105+
spiSettings[idx].msb = LSBFIRST;
91106
}
92107

93-
spi_init(&_spi, spiSettings[_pin].clk, spiSettings[_pin].dMode, spiSettings[_pin].msb);
94-
g_active_id = _pin;
95-
}
108+
if((_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) {
109+
pinMode(_pin, OUTPUT);
110+
digitalWrite(_pin, HIGH);
111+
}
96112

97-
void SPIClass::endTransaction(void)
98-
{
99-
g_active_id = -1;
113+
spi_init(&_spi, spiSettings[idx].clk,
114+
spiSettings[idx].dMode,
115+
spiSettings[idx].msb);
116+
_CSpin = _pin;
100117
}
101118

102-
void SPIClass::end(uint8_t _pin)
119+
void SPIClass::endTransaction(uint8_t _pin)
103120
{
104-
UNUSED(_pin);
105-
end();
121+
if(_pin > NUM_DIGITAL_PINS)
122+
return;
123+
124+
RemovePin(_pin);
125+
_CSpin = -1;
106126
}
107127

108128
void SPIClass::end()
109129
{
110130
spi_deinit(&_spi);
111-
g_active_id = -1;
131+
RemoveAllPin();
132+
_CSpin = -1;
112133
}
113134

114135
void SPIClass::setBitOrder(uint8_t _pin, BitOrder _bitOrder)
115136
{
116-
if(_pin > SPI_CHANNELS_NUM)
137+
if(_pin > NUM_DIGITAL_PINS)
138+
return;
139+
140+
uint8_t idx = pinIdx(_pin, GET_IDX);
141+
if(idx == NB_SPI_SETTINGS) {
117142
return;
143+
}
118144

119145
if(MSBFIRST == _bitOrder) {
120-
spiSettings[_pin].msb = MSBFIRST;
121-
spiSettings[_pin].bOrder = MSBFIRST;
146+
spiSettings[idx].msb = MSBFIRST;
147+
spiSettings[idx].bOrder = MSBFIRST;
122148
} else {
123-
spiSettings[_pin].msb = LSBFIRST;
124-
spiSettings[_pin].bOrder = LSBFIRST;
149+
spiSettings[idx].msb = LSBFIRST;
150+
spiSettings[idx].bOrder = LSBFIRST;
125151
}
126152

127-
spi_init(&_spi, spiSettings[_pin].clk, spiSettings[_pin].dMode, spiSettings[_pin].msb);
128-
g_active_id = _pin;
153+
spi_init(&_spi, spiSettings[idx].clk,
154+
spiSettings[idx].dMode,
155+
spiSettings[idx].msb);
129156
}
130157

131158
void SPIClass::setDataMode(uint8_t _pin, uint8_t _mode)
132159
{
133-
if(_pin > SPI_CHANNELS_NUM)
160+
if(_pin > NUM_DIGITAL_PINS)
161+
return;
162+
163+
uint8_t idx = pinIdx(_pin, GET_IDX);
164+
if(idx == NB_SPI_SETTINGS) {
134165
return;
166+
}
135167

136168
if(SPI_MODE0 == _mode) {
137-
spiSettings[_pin].dMode = SPI_MODE_0;
169+
spiSettings[idx].dMode = SPI_MODE_0;
138170
} else if(SPI_MODE1 == _mode) {
139-
spiSettings[_pin].dMode = SPI_MODE_1;
171+
spiSettings[idx].dMode = SPI_MODE_1;
140172
} else if(SPI_MODE2 == _mode) {
141-
spiSettings[_pin].dMode = SPI_MODE_2;
173+
spiSettings[idx].dMode = SPI_MODE_2;
142174
} else if(SPI_MODE3 == _mode) {
143-
spiSettings[_pin].dMode = SPI_MODE_3;
175+
spiSettings[idx].dMode = SPI_MODE_3;
144176
}
145177

146-
spi_init(&_spi, spiSettings[_pin].clk, spiSettings[_pin].dMode, spiSettings[_pin].msb);
147-
g_active_id = _pin;
178+
spi_init(&_spi, spiSettings[idx].clk,
179+
spiSettings[idx].dMode,
180+
spiSettings[idx].msb);
148181
}
149182

150183
/*
@@ -153,8 +186,13 @@ void SPIClass::setDataMode(uint8_t _pin, uint8_t _mode)
153186
*/
154187
void SPIClass::setClockDivider(uint8_t _pin, uint8_t _divider)
155188
{
156-
if(_pin > SPI_CHANNELS_NUM)
189+
if(_pin > NUM_DIGITAL_PINS)
190+
return;
191+
192+
uint8_t idx = pinIdx(_pin, GET_IDX);
193+
if(idx == NB_SPI_SETTINGS) {
157194
return;
195+
}
158196

159197
/* Get clk freq of the SPI instance */
160198
uint32_t spiClkFreq = spi_getClkFreq(&_spi);
@@ -167,39 +205,49 @@ void SPIClass::setClockDivider(uint8_t _pin, uint8_t _divider)
167205
case (SPI_CLOCK_DIV32) :
168206
case (SPI_CLOCK_DIV64) :
169207
case (SPI_CLOCK_DIV128) :
170-
spiSettings[_pin].clk = spiClkFreq/_divider;
208+
spiSettings[idx].clk = spiClkFreq/_divider;
171209
break;
172210
default:
173-
spiSettings[_pin].clk = SPI_SPEED_CLOCK_DEFAULT;
211+
spiSettings[idx].clk = SPI_SPEED_CLOCK_DEFAULT;
174212
break;
175213
}
176214

177-
spi_init(&_spi, spiSettings[_pin].clk, spiSettings[_pin].dMode, spiSettings[_pin].msb);
178-
g_active_id = _pin;
215+
spi_init(&_spi, spiSettings[idx].clk,
216+
spiSettings[idx].dMode,
217+
spiSettings[idx].msb);
179218
}
180219

181220

182-
//Transfer a message on the selected SPI. The _pin is the CS of the SPI that
183-
//identifies the SPI instance.
184-
//If the _mode is set to SPI_CONTINUE, keep the spi instance alive.
221+
/* Transfer a message on the selected SPI. The _pin is the CS.
222+
* The transfer function can reconfigure the SPI instance if the CS pin is
223+
* different from the previous one.
224+
* If the _mode is set to SPI_CONTINUE, keep the spi instance alive. That means
225+
* the CS pin is not reset. Be careful in case you use several CS pin.
226+
*/
185227
byte SPIClass::transfer(uint8_t _pin, uint8_t data, SPITransferMode _mode)
186228
{
187229
uint8_t rx_buffer = 0;
188230

189-
if (_pin > SPI_CHANNELS_NUM)
231+
if (_pin > NUM_DIGITAL_PINS)
190232
return rx_buffer;
191233

192-
if(_pin != g_active_id) {
193-
spi_init(&_spi, spiSettings[_pin].clk, spiSettings[_pin].dMode, spiSettings[_pin].msb);
194-
g_active_id = _pin;
234+
if(_pin != _CSpin) {
235+
uint8_t idx = pinIdx(_pin, GET_IDX);
236+
if(idx == NB_SPI_SETTINGS) {
237+
return rx_buffer;
238+
}
239+
spi_init(&_spi, spiSettings[idx].clk,
240+
spiSettings[idx].dMode,
241+
spiSettings[idx].msb);
242+
_CSpin = _pin;
195243
}
196244

197-
if((_pin != BOARD_SPI_OWN_SS) && (_spi.pin_ssel == NC))
245+
if((_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC))
198246
digitalWrite(_pin, LOW);
199247

200-
spi_transfer(&_spi, &data, &rx_buffer, sizeof(uint8_t), 10000);
248+
spi_transfer(&_spi, &data, &rx_buffer, sizeof(uint8_t), SPI_TRANSFER_TIMEOUT);
201249

202-
if((_pin != BOARD_SPI_OWN_SS) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC))
250+
if((_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC))
203251
digitalWrite(_pin, HIGH);
204252

205253
return rx_buffer;
@@ -210,25 +258,31 @@ uint16_t SPIClass::transfer16(uint8_t _pin, uint16_t data, SPITransferMode _mode
210258
uint16_t rx_buffer = 0;
211259
uint16_t tmp;
212260

213-
if (_pin > SPI_CHANNELS_NUM)
261+
if (_pin > NUM_DIGITAL_PINS)
214262
return rx_buffer;
215263

216264
if (spiSettings[_pin].msb) {
217265
tmp = ((data & 0xff00) >> 8) | ((data & 0xff) << 8);
218266
data = tmp;
219267
}
220268

221-
if(_pin != g_active_id) {
222-
spi_init(&_spi, spiSettings[_pin].clk, spiSettings[_pin].dMode, spiSettings[_pin].msb);
223-
g_active_id = _pin;
269+
if(_pin != _CSpin) {
270+
uint8_t idx = pinIdx(_pin, GET_IDX);
271+
if(idx == NB_SPI_SETTINGS) {
272+
return rx_buffer;
273+
}
274+
spi_init(&_spi, spiSettings[idx].clk,
275+
spiSettings[idx].dMode,
276+
spiSettings[idx].msb);
277+
_CSpin = _pin;
224278
}
225279

226-
if((_pin != BOARD_SPI_OWN_SS) && (_spi.pin_ssel == NC))
280+
if((_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC))
227281
digitalWrite(_pin, LOW);
228282

229-
spi_transfer(&_spi, (uint8_t *)&data, (uint8_t *)&rx_buffer, sizeof(uint16_t), 10000000);
283+
spi_transfer(&_spi, (uint8_t *)&data, (uint8_t *)&rx_buffer, sizeof(uint16_t), SPI_TRANSFER_TIMEOUT);
230284

231-
if((_pin != BOARD_SPI_OWN_SS) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC))
285+
if((_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC))
232286
digitalWrite(_pin, HIGH);
233287

234288
if (spiSettings[_pin].msb) {
@@ -241,20 +295,26 @@ uint16_t SPIClass::transfer16(uint8_t _pin, uint16_t data, SPITransferMode _mode
241295

242296
void SPIClass::transfer(uint8_t _pin, void *_buf, size_t _count, SPITransferMode _mode)
243297
{
244-
if ((_count == 0) || (_pin > SPI_CHANNELS_NUM))
298+
if ((_count == 0) || (_buf == NULL) || (_pin > NUM_DIGITAL_PINS))
245299
return;
246300

247-
if(_pin != g_active_id) {
248-
spi_init(&_spi, spiSettings[_pin].clk, spiSettings[_pin].dMode, spiSettings[_pin].msb);
249-
g_active_id = _pin;
301+
if(_pin != _CSpin) {
302+
uint8_t idx = pinIdx(_pin, GET_IDX);
303+
if(idx == NB_SPI_SETTINGS) {
304+
return;
305+
}
306+
spi_init(&_spi, spiSettings[idx].clk,
307+
spiSettings[idx].dMode,
308+
spiSettings[idx].msb);
309+
_CSpin = _pin;
250310
}
251311

252-
if((_pin != BOARD_SPI_OWN_SS) && (_spi.pin_ssel == NC))
312+
if((_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC))
253313
digitalWrite(_pin, LOW);
254314

255-
spi_transfer(&_spi, ((uint8_t*)_buf), ((uint8_t*)_buf), _count, 10000);
315+
spi_transfer(&_spi, ((uint8_t*)_buf), ((uint8_t*)_buf), _count, SPI_TRANSFER_TIMEOUT);
256316

257-
if((_pin != BOARD_SPI_OWN_SS) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC))
317+
if((_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC))
258318
digitalWrite(_pin, HIGH);
259319
}
260320

0 commit comments

Comments
 (0)