@@ -62,12 +62,12 @@ void SPIClass::init() {
6262#define interruptsStatus () __interruptsStatus()
6363static inline unsigned char __interruptsStatus (void ) __attribute__((always_inline, unused));
6464static inline unsigned char __interruptsStatus (void ) {
65- unsigned int primask, faultmask;
66- asm volatile (" mrs %0, primask" : " =r" (primask));
67- if (primask) return 0 ;
68- asm volatile (" mrs %0, faultmask" : " =r" (faultmask));
69- if (faultmask) return 0 ;
70- return 1 ;
65+ unsigned int primask, faultmask;
66+ asm volatile (" mrs %0, primask" : " =r" (primask));
67+ if (primask) return 0 ;
68+ asm volatile (" mrs %0, faultmask" : " =r" (faultmask));
69+ if (faultmask) return 0 ;
70+ return 1 ;
7171}
7272#endif
7373
@@ -182,18 +182,70 @@ byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) {
182182 d |= SPI_TDR_LASTXFER;
183183
184184 // SPI_Write(spi, _channel, _data);
185- while ((spi->SPI_SR & SPI_SR_TDRE) == 0 )
186- ;
187- spi->SPI_TDR = d;
188-
189- // return SPI_Read(spi);
190- while ((spi->SPI_SR & SPI_SR_RDRF) == 0 )
191- ;
192- d = spi->SPI_RDR ;
185+ while ((spi->SPI_SR & SPI_SR_TDRE) == 0 )
186+ ;
187+ spi->SPI_TDR = d;
188+
189+ // return SPI_Read(spi);
190+ while ((spi->SPI_SR & SPI_SR_RDRF) == 0 )
191+ ;
192+ d = spi->SPI_RDR ;
193193 // Reverse bit order
194194 if (bitOrder[ch] == LSBFIRST)
195195 d = __REV (__RBIT (d));
196- return d & 0xFF ;
196+ return d & 0xFF ;
197+ }
198+
199+ void SPIClass::transfer (byte _pin, void *_buf, size_t _count, SPITransferMode _mode) {
200+ if (_count == 0 )
201+ return ;
202+
203+ uint8_t *buffer = (uint8_t *)_buf;
204+ if (_count == 1 ) {
205+ *buffer = transfer (_pin, *buffer, _mode);
206+ return ;
207+ }
208+
209+ uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL (_pin);
210+ bool reverse = (bitOrder[ch] == LSBFIRST);
211+
212+ // Send the first byte
213+ uint32_t d = *buffer;
214+ if (reverse)
215+ d = __REV (__RBIT (d));
216+ while ((spi->SPI_SR & SPI_SR_TDRE) == 0 )
217+ ;
218+ spi->SPI_TDR = d | SPI_PCS (ch);
219+
220+ while (_count > 1 ) {
221+ // Prepare next byte
222+ d = *(buffer+1 );
223+ if (reverse)
224+ d = __REV (__RBIT (d));
225+ if (_count == 2 && _mode == SPI_LAST)
226+ d |= SPI_TDR_LASTXFER;
227+
228+ // Read transferred byte and send next one straight away
229+ while ((spi->SPI_SR & SPI_SR_RDRF) == 0 )
230+ ;
231+ uint8_t r = spi->SPI_RDR ;
232+ spi->SPI_TDR = d | SPI_PCS (ch);
233+
234+ // Save read byte
235+ if (reverse)
236+ r = __REV (__RBIT (r));
237+ *buffer = r;
238+ buffer++;
239+ _count--;
240+ }
241+
242+ // Receive the last transferred byte
243+ while ((spi->SPI_SR & SPI_SR_RDRF) == 0 )
244+ ;
245+ uint8_t r = spi->SPI_RDR ;
246+ if (reverse)
247+ r = __REV (__RBIT (r));
248+ *buffer = r;
197249}
198250
199251void SPIClass::attachInterrupt (void ) {
0 commit comments