@@ -36,6 +36,7 @@ typedef union {
36
36
SPIClass SPI;
37
37
38
38
SPIClass::SPIClass () {
39
+ useHwCs = false ;
39
40
}
40
41
41
42
void SPIClass::begin () {
@@ -54,9 +55,26 @@ void SPIClass::end() {
54
55
pinMode (SCK, INPUT);
55
56
pinMode (MISO, INPUT);
56
57
pinMode (MOSI, INPUT);
58
+ if (useHwCs) {
59
+ pinMode (SS, INPUT);
60
+ }
61
+ }
62
+
63
+ void SPIClass::setHwCs (bool use) {
64
+ if (use) {
65
+ pinMode (SS, SPECIAL); // /< GPIO15
66
+ SPI1U |= (SPIUCSSETUP | SPIUCSHOLD);
67
+ } else {
68
+ if (useHwCs) {
69
+ pinMode (SS, INPUT);
70
+ SPI1U &= ~(SPIUCSSETUP | SPIUCSHOLD);
71
+ }
72
+ }
73
+ useHwCs = use;
57
74
}
58
75
59
76
void SPIClass::beginTransaction (SPISettings settings) {
77
+ while (SPI1CMD & SPIBUSY) {}
60
78
setFrequency (settings._clock );
61
79
setBitOrder (settings._bitOrder );
62
80
setDataMode (settings._dataMode );
@@ -198,13 +216,19 @@ void SPIClass::setClockDivider(uint32_t clockDiv) {
198
216
SPI1CLK = clockDiv;
199
217
}
200
218
219
+ inline void SPIClass::setDataBits (uint16_t bits) {
220
+ const uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO));
221
+ bits--;
222
+ SPI1U1 = ((SPI1U1 & mask) | ((bits << SPILMOSI) | (bits << SPILMISO)));
223
+ }
224
+
201
225
uint8_t SPIClass::transfer (uint8_t data) {
202
- while (SPI1CMD & SPIBUSY)
203
- ;
226
+ while (SPI1CMD & SPIBUSY) {}
227
+ // reset to 8Bit mode
228
+ setDataBits (8 );
204
229
SPI1W0 = data;
205
230
SPI1CMD |= SPIBUSY;
206
- while (SPI1CMD & SPIBUSY)
207
- ;
231
+ while (SPI1CMD & SPIBUSY) {}
208
232
return (uint8_t ) (SPI1W0 & 0xff );
209
233
}
210
234
@@ -230,3 +254,177 @@ uint16_t SPIClass::transfer16(uint16_t data) {
230
254
return out.val ;
231
255
}
232
256
257
+ void SPIClass::write (uint8_t data) {
258
+ while (SPI1CMD & SPIBUSY) {}
259
+ // reset to 8Bit mode
260
+ setDataBits (8 );
261
+ SPI1W0 = data;
262
+ SPI1CMD |= SPIBUSY;
263
+ while (SPI1CMD & SPIBUSY) {}
264
+ }
265
+
266
+ void SPIClass::write16 (uint16_t data) {
267
+ write16 (data, !(SPI1C & (SPICWBO | SPICRBO)));
268
+ }
269
+
270
+ void SPIClass::write16 (uint16_t data, bool msb) {
271
+ while (SPI1CMD & SPIBUSY) {}
272
+ // Set to 16Bits transfer
273
+ setDataBits (16 );
274
+ if (msb) {
275
+ // MSBFIRST Byte first
276
+ SPI1W0 = (data >> 8 ) | (data << 8 );
277
+ SPI1CMD |= SPIBUSY;
278
+ } else {
279
+ // LSBFIRST Byte first
280
+ SPI1W0 = data;
281
+ SPI1CMD |= SPIBUSY;
282
+ }
283
+ while (SPI1CMD & SPIBUSY) {}
284
+ }
285
+
286
+ void SPIClass::write32 (uint32_t data) {
287
+ write32 (data, !(SPI1C & (SPICWBO | SPICRBO)));
288
+ }
289
+
290
+ void SPIClass::write32 (uint32_t data, bool msb) {
291
+ while (SPI1CMD & SPIBUSY) {}
292
+ // Set to 32Bits transfer
293
+ setDataBits (32 );
294
+ if (msb) {
295
+ union {
296
+ uint32_t l;
297
+ uint8_t b[4 ];
298
+ } data_;
299
+ data_.l = data;
300
+ // MSBFIRST Byte first
301
+ SPI1W0 = (data_.b [3 ] | (data_.b [2 ] << 8 ) | (data_.b [1 ] << 16 ) | (data_.b [0 ] << 24 ));
302
+ SPI1CMD |= SPIBUSY;
303
+ } else {
304
+ // LSBFIRST Byte first
305
+ SPI1W0 = data;
306
+ SPI1CMD |= SPIBUSY;
307
+ }
308
+ while (SPI1CMD & SPIBUSY) {}
309
+ }
310
+
311
+ void SPIClass::writeBytes (uint8_t * data, uint32_t size) {
312
+ while (size) {
313
+ if (size > 64 ) {
314
+ writeBytes_ (data, 64 );
315
+ size -= 64 ;
316
+ data += 64 ;
317
+ } else {
318
+ writeBytes_ (data, size);
319
+ size = 0 ;
320
+ }
321
+ }
322
+ }
323
+
324
+ void SPIClass::writeBytes_ (uint8_t * data, uint8_t size) {
325
+ while (SPI1CMD & SPIBUSY) {}
326
+ // Set Bits to transfer
327
+ setDataBits (size * 8 );
328
+
329
+ volatile uint32_t * fifoPtr = &SPI1W0;
330
+ uint32_t * dataPtr = (uint32_t *) data;
331
+ uint8_t dataSize = ((size + 3 ) / 4 );
332
+
333
+ while (dataSize--) {
334
+ *fifoPtr = *dataPtr;
335
+ dataPtr++;
336
+ fifoPtr++;
337
+ }
338
+
339
+ SPI1CMD |= SPIBUSY;
340
+ while (SPI1CMD & SPIBUSY) {}
341
+ }
342
+
343
+ void SPIClass::writePattern (uint8_t * data, uint8_t size, uint32_t repeat) {
344
+ if (size > 64 ) return ; // max Hardware FIFO
345
+
346
+ uint32_t byte = (size * repeat);
347
+ uint8_t r = (64 / size);
348
+
349
+ while (byte) {
350
+ if (byte > 64 ) {
351
+ writePattern_ (data, size, r);
352
+ byte -= 64 ;
353
+ } else {
354
+ writePattern_ (data, size, (byte / size));
355
+ byte = 0 ;
356
+ }
357
+ }
358
+ }
359
+
360
+ void SPIClass::writePattern_ (uint8_t * data, uint8_t size, uint8_t repeat) {
361
+ uint8_t bytes = (size * repeat);
362
+ uint8_t buffer[64 ];
363
+ uint8_t * bufferPtr = &buffer[0 ];
364
+ uint8_t * dataPtr;
365
+ uint8_t dataSize = bytes;
366
+ for (uint8_t i = 0 ; i < repeat; i++) {
367
+ dataSize = size;
368
+ dataPtr = data;
369
+ while (dataSize--) {
370
+ *bufferPtr = *dataPtr;
371
+ dataPtr++;
372
+ bufferPtr++;
373
+ }
374
+ }
375
+
376
+ writeBytes (&buffer[0 ], bytes);
377
+ }
378
+
379
+ void SPIClass::transferBytes (uint8_t * out, uint8_t * in, uint32_t size) {
380
+ while (size) {
381
+ if (size > 64 ) {
382
+ transferBytes_ (out, in, 64 );
383
+ size -= 64 ;
384
+ if (out) out += 64 ;
385
+ if (in) in += 64 ;
386
+ } else {
387
+ transferBytes_ (out, in, size);
388
+ size = 0 ;
389
+ }
390
+ }
391
+ }
392
+
393
+ void SPIClass::transferBytes_ (uint8_t * out, uint8_t * in, uint8_t size) {
394
+ while (SPI1CMD & SPIBUSY) {}
395
+ // Set in/out Bits to transfer
396
+
397
+ setDataBits (size * 8 );
398
+
399
+ volatile uint32_t * fifoPtr = &SPI1W0;
400
+ uint8_t dataSize = ((size + 3 ) / 4 );
401
+
402
+ if (out) {
403
+ uint32_t * dataPtr = (uint32_t *) out;
404
+ while (dataSize--) {
405
+ *fifoPtr = *dataPtr;
406
+ dataPtr++;
407
+ fifoPtr++;
408
+ }
409
+ } else {
410
+ // no out data only read fill with dummy data!
411
+ while (dataSize--) {
412
+ *fifoPtr = 0xFFFFFFFF ;
413
+ fifoPtr++;
414
+ }
415
+ }
416
+
417
+ SPI1CMD |= SPIBUSY;
418
+ while (SPI1CMD & SPIBUSY) {}
419
+
420
+ if (in) {
421
+ volatile uint8_t * fifoPtr8 = (volatile uint8_t *) &SPI1W0;
422
+ dataSize = size;
423
+ while (dataSize--) {
424
+ *in = *fifoPtr8;
425
+ in++;
426
+ fifoPtr8++;
427
+ }
428
+ }
429
+ }
430
+
0 commit comments