The tcDspSpi class is used to provide a consistent method to access devices via an instance of the MityDSP SPI. Although tcDspSpi may be used directly by applications, it is usually used by higher-level classes to provide access to a specific device.
The tcDspSpi class provides a FIFO which can be used to read and/or write to the SPI. Serialization of access to multiple devices or to the same device across multiple threads must be provided by the application. The class provides interrupts when various transmit FIFO levels are reached (Empty, 1/4, 1/2, and 3/4 full).
The application may register a routine to be run in ISR context to provide specific functionality for each FIFO interrupt.
An instance of the tcDspSpi class is created by specifying the firmware base address of the core and the interrupt level used. This core supports specifying a level of gnAutoLevel, which automatically installs a vectored interrupt.
This is a simple example of tcDspSpi creation and usage:
{ SEM_handle MyClass::myFifoAlmostEmpty; tcDspSpi *MyClass::mySpi; static void MyClass::myIsrCallback(tcDspSpi *apSpi) { SEM_post(myFifoAlmostEmpty); return; } void MyClass::doSomething(void) { int i; unsigned int my_base_addr = 0xB0000200; tcDspSpi::tuFifoData FifoData; tcDspSpi::tuFifoData IncomingData[64]; LCK_Handle myLock = LCK_create(NULL); // initialize semaphore myFifoAlmostEmpty = SEM_create(0, NULL); // create access to the SPI (utilize locks since no ISR access) mySpi = new tcDspSpi((void *)my_base_addr, gnAutoLevel, myLock); // Set up FIFO width, clock edges, and whether the clock should // be gated... mySpi->SetFifoWidth(tcDspSpi::ee32Bit); mySpi->SetTxClockEdge(tcDspSpi::eeFalling); mySpi->SetRxClockEdge(tcDspSpi::eeFalling); mySpi->SetClockGateWithSync(true); // register callback when TX is 1/4 full mySpi->RegisterTxFIFOHandler(eeOneQ, myIsrCallback); // enable TX 1/4 full interrupt mySpi->SetTxFIFOInterruptLevel(eeOneQ, true); // load TX FIFO with "data" for (i=0; i<mySpi->GetTxFIFODepth(); i++) { FifoData.mnLword = i; if (mySpi->WriteData(&FifoData, 1) != 1) break; } // do something for a long time... while (true) { // do something application-specific : : // wait for ISR to trigger 1/4 full semaphore SEM_pend(myFifoAlmostEmpty, SYS_FOREVER); // reload FIFO for (i=0; i<mySpi->GetTxFIFODepth(); i++) { FifoData.ms32Bit.mnFifoData = i; if (mySpi->WriteData(&FifoData, 1) != 1) break; } // do something application-specific : : // reset SPI to 8-bit width mySpi->SetFifoWidth(tcDspSpi::ee32Bit); // Pre-load data (will be placed on the transmit data line when // data is being clocked in)... for (i=0; i<64; i++) IncomingData[i].ms8Bit.mnFifoData = 0xFF; // read data from SPI bytes = mySpi->ReadData(IncomingData, 64); // do something with the data : : } } }