@@ -183,6 +183,19 @@ void SPIClass::setBitOrder(BitOrder bitOrder)
183183 this ->begin ();
184184}
185185
186+ /* Victor Perez. Added to test changing datasize from 8 to 16 bit modes on the fly.
187+ * Input parameter should be SPI_CR1_DFF set to 0 or 1 on a 32bit word.
188+ *
189+ */
190+ void SPIClass::setDataSize (uint32 datasize)
191+ {
192+ uint32 cr1 = this ->spi_d ->regs ->CR1 ;
193+ datasize &= SPI_CR1_DFF;
194+ cr1 &= ~(SPI_CR1_DFF);
195+ cr1 |= datasize;
196+ this ->spi_d ->regs ->CR1 = cr1;
197+ }
198+
186199void SPIClass::setDataMode (uint8_t dataMode)
187200{
188201/* Notes. As far as I can tell, the AVR numbers for dataMode appear to match the numbers required by the STM32
@@ -297,6 +310,20 @@ void SPIClass::read(uint8 *buf, uint32 len) {
297310 }
298311}
299312
313+ void SPIClass::write (uint16 data) {
314+ // this->write(&data, 1);
315+
316+ /* Added for 16bit data Victor Perez. Roger Clark
317+ * Improved speed by just directly writing the single byte to the SPI data reg and wait for completion, * by taking the Tx code from transfer(byte)
318+ * The original method, of calling write(*data, length) .
319+ * This almost doubles the speed of this function.
320+ */
321+
322+ spi_tx_reg (this ->spi_d , data); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
323+ while (spi_is_tx_empty (this ->spi_d ) == 0 ); // "5. Wait until TXE=1 ..."
324+ while (spi_is_busy (this ->spi_d ) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
325+ }
326+
300327void SPIClass::write (uint8 byte) {
301328 // this->write(&byte, 1);
302329
@@ -329,35 +356,116 @@ uint8 SPIClass::transfer(uint8 byte) {
329356 while (spi_is_busy (this ->spi_d ) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
330357 return b;
331358}
332-
333- uint8 SPIClass::DMATransfer (uint8 *transmitBuf, uint8 *receiveBuf, uint32 length) {
359+ /* Roger Clark and Victor Perez, 2015
360+ * Performs a DMA SPI transfer with at least a receive buffer.
361+ * If a TX buffer is not provided, FF is sent over and over for the lenght of the transfer.
362+ * On exit TX buffer is not modified, and RX buffer cotains the received data.
363+ * Still in progress.
364+ */
365+ uint8 SPIClass::dmaTransfer (uint8 *transmitBuf, uint8 *receiveBuf, uint16 length) {
366+ if (length == 0 ) return 0 ;
334367 uint8 b;
335-
368+ if ( spi_is_rx_nonempty ( this -> spi_d ) == 1 ) b = spi_rx_reg ( this -> spi_d ); // Clear the RX buffer in case a byte is waiting on it.
336369 dma1_ch3_Active=true ;
337-
338370 dma_init (DMA1);
339-
340- dma_attach_interrupt (DMA1, DMA_CH2, &SPIClass::DMA1_CH3_Event);
341-
371+ dma_attach_interrupt (DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event);
372+
342373 // RX
343374 spi_rx_dma_enable (SPI1);
344375 dma_setup_transfer (DMA1, DMA_CH2, &SPI1->regs ->DR , DMA_SIZE_8BITS,
345- receiveBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_TRNS_CMPLT | DMA_TRNS_ERR ));// receive buffer DMA
376+ receiveBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_TRNS_CMPLT));// receive buffer DMA
346377 dma_set_num_transfers (DMA1, DMA_CH2, length);
347-
378+
348379 // TX
349- spi_tx_dma_enable (SPI1);
380+ spi_tx_dma_enable (SPI1);
381+ if (!transmitBuf) {
382+ static uint8_t ff = 0XFF ;
383+ transmitBuf = &ff;
384+ dma_setup_transfer (DMA1, DMA_CH3, &SPI1->regs ->DR , DMA_SIZE_8BITS,
385+ transmitBuf, DMA_SIZE_8BITS, (DMA_FROM_MEM | DMA_TRNS_CMPLT));// Transmit FF repeatedly
386+ }
387+ else {
350388 dma_setup_transfer (DMA1, DMA_CH3, &SPI1->regs ->DR , DMA_SIZE_8BITS,
351- transmitBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT));// Transmit buffer DMA
352- dma_set_num_transfers (DMA1, DMA_CH3, length);
353-
389+ transmitBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT));// Transmit buffer DMA
390+ }
391+ dma_set_num_transfers (DMA1, DMA_CH3, length);
392+
354393 dma_enable (DMA1, DMA_CH2);// enable receive
355394 dma_enable (DMA1, DMA_CH3);// enable transmit
356395
357- while (dma1_ch3_Active);
396+ // while (dma1_ch3_Active);
397+ // if (receiveBuf) {
398+ uint32_t m = millis ();
399+ while (dma1_ch3_Active) {
400+ if ((millis () - m) > 100 ) {
401+ dma1_ch3_Active = 0 ;
402+ b = 2 ;
403+ break ;
404+ }
405+ }
406+
407+ // }
408+ while (spi_is_tx_empty (this ->spi_d ) == 0 ); // "5. Wait until TXE=1 ..."
409+ while (spi_is_busy (this ->spi_d ) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
410+ dma_disable (DMA1, DMA_CH3);
411+ dma_disable (DMA1, DMA_CH2);
412+ spi_rx_dma_disable (SPI1);
413+ spi_tx_dma_disable (SPI1);
414+ return b;
415+ }
416+
417+ /* Roger Clark and Victor Perez, 2015
418+ * Performs a DMA SPI send using a TX buffer.
419+ * On exit TX buffer is not modified.
420+ * Still in progress.
421+ */
422+ uint8 SPIClass::dmaSend (uint8 *transmitBuf, uint16 length, bool minc) {
423+ if (length == 0 ) return 0 ;
424+ uint32 flags = ((DMA_MINC_MODE * minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT);
425+ uint8 b;
426+ dma1_ch3_Active=true ;
427+ dma_init (DMA1);
428+ dma_attach_interrupt (DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event);
429+
430+ // TX
431+ spi_tx_dma_enable (SPI1);
432+ dma_setup_transfer (DMA1, DMA_CH3, &SPI1->regs ->DR , DMA_SIZE_8BITS,
433+ transmitBuf, DMA_SIZE_8BITS, flags);// Transmit buffer DMA
434+ dma_set_num_transfers (DMA1, DMA_CH3, length);
435+ dma_enable (DMA1, DMA_CH3);// enable transmit
436+
437+ while (dma1_ch3_Active);
438+ while (spi_is_rx_nonempty (this ->spi_d ) == 0 ); // "4. Wait until RXNE=1 ..."
439+ b = spi_rx_reg (this ->spi_d ); // "... and read the last received data."
358440 while (spi_is_tx_empty (this ->spi_d ) == 0 ); // "5. Wait until TXE=1 ..."
359- while (spi_is_busy (this ->spi_d ) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
441+ while (spi_is_busy (this ->spi_d ) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
442+ dma_disable (DMA1, DMA_CH3);
443+ spi_tx_dma_disable (SPI1);
444+ return b;
445+ }
446+
447+ uint8 SPIClass::dmaSend (uint16 *transmitBuf, uint16 length, bool minc) {
448+ if (length == 0 ) return 0 ;
449+ uint32 flags = ((DMA_MINC_MODE * minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT);
450+ uint8 b;
451+ dma1_ch3_Active=true ;
452+ dma_init (DMA1);
453+ dma_attach_interrupt (DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event);
454+
455+ // TX
456+ spi_tx_dma_enable (SPI1);
457+ dma_setup_transfer (DMA1, DMA_CH3, &SPI1->regs ->DR , DMA_SIZE_16BITS,
458+ transmitBuf, DMA_SIZE_16BITS, flags);// Transmit buffer DMA
459+ dma_set_num_transfers (DMA1, DMA_CH3, length);
460+ dma_enable (DMA1, DMA_CH3);// enable transmit
360461
462+ while (dma1_ch3_Active);
463+ while (spi_is_rx_nonempty (this ->spi_d ) == 0 ); // "4. Wait until RXNE=1 ..."
464+ b = spi_rx_reg (this ->spi_d ); // "... and read the last received data."
465+ while (spi_is_tx_empty (this ->spi_d ) == 0 ); // "5. Wait until TXE=1 ..."
466+ while (spi_is_busy (this ->spi_d ) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
467+ dma_disable (DMA1, DMA_CH3);
468+ spi_tx_dma_disable (SPI1);
361469 return b;
362470}
363471
0 commit comments