//#include <WProgram.h>
#include <SPI.h>
#include <DmaSpi.h>
/** Important
The sketch waits for user input through Serial (USB) before it starts the setup.
After any key was pressed, it should begin to work. It will ask for a second keypress later.
**/
class ActiveLowChipSelect1 : public AbstractChipSelect
{
public:
/** Configues a chip select pin for OUTPUT mode,
* manages the chip selection and a corresponding SPI transaction
*
* The chip select pin is asserted \e after the SPI settings are applied
* and deasserted before the SPI transaction ends.
* \param pin the CS pin to use
* \param settings which SPI settings to apply when the chip is selected
**/
ActiveLowChipSelect1(const unsigned int& pin, const SPISettings& settings)
: pin_(pin),
settings_(settings)
{
pinMode(pin, OUTPUT);
digitalWriteFast(pin, 1);
}
/** \brief begins an SPI transaction selects the chip (sets the pin to low) and
**/
void select() override
{
SPI1.beginTransaction(settings_);
digitalWriteFast(pin_, 0);
}
/** \brief deselects the chip (sets the pin to high) and ends the SPI transaction
**/
void deselect() override
{
digitalWriteFast(pin_, 1);
SPI1.endTransaction();
}
private:
const unsigned int pin_;
const SPISettings settings_;
};
class ActiveLowChipSelect2 : public AbstractChipSelect
{
public:
/** Configues a chip select pin for OUTPUT mode,
* manages the chip selection and a corresponding SPI transaction
*
* The chip select pin is asserted \e after the SPI settings are applied
* and deasserted before the SPI transaction ends.
* \param pin the CS pin to use
* \param settings which SPI settings to apply when the chip is selected
**/
ActiveLowChipSelect2(const unsigned int& pin, const SPISettings& settings)
: pin_(pin),
settings_(settings)
{
pinMode(pin, OUTPUT);
digitalWriteFast(pin, 1);
}
/** \brief begins an SPI transaction selects the chip (sets the pin to low) and
**/
void select() override
{
SPI2.beginTransaction(settings_);
digitalWriteFast(pin_, 0);
}
/** \brief deselects the chip (sets the pin to high) and ends the SPI transaction
**/
void deselect() override
{
digitalWriteFast(pin_, 1);
SPI2.endTransaction();
}
private:
const unsigned int pin_;
const SPISettings settings_;
};
/** Hardware setup:
plain Teensy 3.1 with DOUT (11) connected to DIN (12)
nothing else
**/
/** buffers to send from and to receive to **/
#define DMASIZE 100
uint8_t src[DMASIZE];
volatile uint8_t dest[DMASIZE];
volatile uint8_t dest1[DMASIZE];
volatile uint8_t dest2[DMASIZE];
/** Wait for and consume a keypress over USB **/
void waitForKeyPress()
{
Serial.println("\nPress a key to continue\n");
while(!Serial.available());
while(Serial.available())
{
Serial.read();
}
}
void dumpBuffer(const volatile uint8_t* buf, const char* prefix)
{
Serial.print(prefix);
for (size_t i = 0; i < DMASIZE; i++)
{
Serial.printf("0x%02x ", buf[i]);
}
Serial.print('\n');
}
/** Compare the buffers and print the destination contents if there's a mismatch **/
void compareBuffers(const uint8_t* src_, const uint8_t* dest_)
{
int n = memcmp((const void*)src_, (const void*)dest_, DMASIZE);
if (n == 0)
{
Serial.println("src and dest match");
}
else
{
Serial.println("src and dest don't match");
dumpBuffer(src_, " src: " );
dumpBuffer(dest_, "dest: ");
}
}
void setSrc()
{
for (size_t i = 0; i < DMASIZE; i++)
{
src[i] = i;
}
}
void clrDest(uint8_t* dest_)
{
memset((void*)dest_, 0x00, DMASIZE);
}
void setup()
{
waitForKeyPress();
Serial.println("Hi!");
/** Prepare source and destination **/
setSrc();
clrDest((uint8_t*)dest);
Serial.println("Buffers are prepared");Serial.flush();
/** set up SPI **/
SPISettings spiSettings(400000, MSBFIRST, SPI_MODE0);
// BUGBUG:: Probably should
SPI2.setMOSI(52);
SPI2.setMISO(51);
SPI2.begin();
SPI1.begin();
SPI.begin();
// transmit 10 bytes and measure time to get a feel of how long that takes
// Lets do for all three SPI busses
SPI.beginTransaction(spiSettings);
elapsedMicros us;
for (size_t i = 0; i < DMASIZE; i++)
{
dest[i] = SPI.transfer(src[i]);
}
uint32_t t = us;
Serial.print("SPI: Time for non-DMA transfer: ");Serial.print(t);Serial.println("us");
SPI.endTransaction();
compareBuffers(src, (const uint8_t*)dest);
//-------------------------------------------------------------
SPI1.beginTransaction(spiSettings);
for (size_t i = 0; i < DMASIZE; i++)
{
dest[i] = SPI1.transfer(src[i]);
}
Serial.print("SPI1: Time for non-DMA transfer: ");Serial.print(t);Serial.println("us");
SPI1.endTransaction();
compareBuffers(src, (const uint8_t*)dest);
//---------------------------------------------------------
SPI2.beginTransaction(spiSettings);
for (size_t i = 0; i < DMASIZE; i++)
{
dest[i] = SPI2.transfer(src[i]);
}
Serial.print("SPI2: Time for non-DMA transfer: ");Serial.print(t);Serial.println("us");
SPI1.endTransaction();
compareBuffers(src, (const uint8_t*)dest);
//---------------------------------------------------------
waitForKeyPress();
// Start up DMA on all three
DMASPI0.begin();
DMASPI0.start();
DMASPI1.begin();
DMASPI1.start();
DMASPI2.begin();
DMASPI2.start();
DmaSpi::Transfer trx(nullptr, 0, nullptr);
DmaSpi::Transfer trx1(nullptr, 0, nullptr);
DmaSpi::Transfer trx2(nullptr, 0, nullptr);
Serial.println("--------------------------------------------------");
Serial.println("Create CS objects");
ActiveLowChipSelect cs(2, SPISettings(1000000, MSBFIRST, SPI_MODE0));
ActiveLowChipSelect1 cs1(3, SPISettings(1000000, MSBFIRST, SPI_MODE0));
ActiveLowChipSelect2 cs2(4, SPISettings(1000000, MSBFIRST, SPI_MODE0));
Serial.println("Testing src -> dest, single transfer");
Serial.println("--------------------------------------------------");
Serial.println("SPI:");
trx = DmaSpi::Transfer(src, DMASIZE, dest, 0, &cs);
clrDest((uint8_t*)dest);
DMASPI0.registerTransfer(trx);
while(trx.busy())
{
}
Serial.println("Finished DMA transfer");
compareBuffers(src, (const uint8_t*)dest);
Serial.println("SPI1:");
trx = DmaSpi::Transfer(src, DMASIZE, dest, 0, &cs1);
clrDest((uint8_t*)dest);
DMASPI1.registerTransfer(trx);
while(trx.busy())
{
}
Serial.println("Finished DMA transfer");
compareBuffers(src, (const uint8_t*)dest);
Serial.println("SPI2:");
trx = DmaSpi::Transfer(src, DMASIZE, dest, 0, &cs2);
clrDest((uint8_t*)dest);
DMASPI2.registerTransfer(trx);
while(trx.busy())
{
}
Serial.println("Finished DMA transfer");
compareBuffers(src, (const uint8_t*)dest);
Serial.println("==================================================\n\n");
//==================================================================
// Try all three at same time
Serial.println("Testing all three SRC to DEST");
Serial.println("--------------------------------------------------");
trx = DmaSpi::Transfer(src, DMASIZE, dest, 0, &cs);
clrDest((uint8_t*)dest);
trx1 = DmaSpi::Transfer(src, DMASIZE, dest1, 0, &cs1);
clrDest((uint8_t*)dest1);
trx2 = DmaSpi::Transfer(src, DMASIZE, dest2, 0, &cs2);
clrDest((uint8_t*)dest2);
DMASPI0.registerTransfer(trx);
DMASPI1.registerTransfer(trx1);
DMASPI2.registerTransfer(trx2);
while(trx.busy() || trx1.busy() || trx2.busy())
{
}
Serial.println("Finished all three dma DMA transfer");
compareBuffers(src, (const uint8_t*)dest);
compareBuffers(src, (const uint8_t*)dest1);
compareBuffers(src, (const uint8_t*)dest2);
Serial.println("==================================================\n\n");
// Close down all three...
//=========================================
DmaSpi::Transfer(src, DMASIZE, dest, 0, &cs);
if (DMASPI0.stopped())
{
Serial.println("DMA SPI stopped.");
}
else
{
Serial.println("DMA SPI is still running");
}
DMASPI0.stop();
if (DMASPI0.stopped())
{
Serial.println("DMA SPI stopped.");
}
else
{
Serial.println("DMA SPI is still running");
}
//=========================================
DmaSpi::Transfer(src, DMASIZE, dest, 0, &cs);
if (DMASPI1.stopped())
{
Serial.println("DMA SPI1 stopped.");
}
else
{
Serial.println("DMA SPI1 is still running");
}
DMASPI1.stop();
if (DMASPI1.stopped())
{
Serial.println("DMA SPI1 stopped.");
}
else
{
Serial.println("DMA SPI1 is still running");
}
//=========================================
DmaSpi::Transfer(src, DMASIZE, dest, 0, &cs);
if (DMASPI2.stopped())
{
Serial.println("DMA SPI2 stopped.");
}
else
{
Serial.println("DMA SPI2 is still running");
}
DMASPI2.stop();
if (DMASPI2.stopped())
{
Serial.println("DMA SPI2 stopped.");
}
else
{
Serial.println("DMA SPI2 is still running");
}
//===================================
DMASPI0.end();
DMASPI1.end();
DMASPI2.end();
SPI.end();
SPI1.end();
SPI2.end();
pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
digitalWriteFast(LED_BUILTIN, true);
delay(500);
digitalWriteFast(LED_BUILTIN, false);
delay(500);
}