Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Embedded_RTOS_Project
Fork of mmSPI by
mmSPI.cpp
- Committer:
- gatedClock
- Date:
- 2013-08-25
- Revision:
- 29:4ed71dfee7d8
- Parent:
- 27:fb63c8b70bc2
- Child:
- 30:331c7c7d8bc1
File content as of revision 29:4ed71dfee7d8:
/*----------------------------------------------//------------------------------
student : m-moore
class : external SPI interface
directory : mmSPI
file : mmSPI.cpp
------------------------------------------------//----------------------------*/
#include "mmSPI.h"
/*----------------------------------------------//------------------------------
------------------------------------------------//----------------------------*/
//==============================================//==============================
// consider resetting the fpga around here, because
// the micro may be wiggling these signals before here.
mmSPI::mmSPI() // constructor.
{
allocations(); // object allocations.
*pSCLK = 0; // initialize.
*pCPUclk = 0; // initialize.
}
//----------------------------------------------//------------------------------
mmSPI::~mmSPI() // destructor.
{
// deallocations.
if (pMOSI) {delete pMOSI; pMOSI = NULL;}
if (pMISO) {delete pMISO; pMISO = NULL;}
if (pSCLK) {delete pSCLK; pSCLK = NULL;}
if (pCPUclk) {delete pCPUclk; pCPUclk = NULL;}
}
//----------------------------------------------//------------------------------
void mmSPI::allocations(void) // object allocations.
{
pMOSI = new DigitalOut(mmSPI_MOSI); // SPI MOSI pin object.
if (!pMOSI) error("\n\r mmSPI::allocations : FATAL malloc error for pMOSI. \n\r");
pMISO = new DigitalOut(mmSPI_MISO); // SPI MISO pin object.
if (!pMISO) error("\n\r mmSPI::allocations : FATAL malloc error for pMISO. \n\r");
pSCLK = new DigitalOut(mmSPI_SCLK); // SPI SCLK pin object.
if (!pSCLK) error("\n\r mmSPI::allocations : FATAL malloc error for pSCLK. \n\r");
pCPUclk = new DigitalOut(mmCPU_CLK); // SPI SCLK pin object.
if (!pCPUclk) error("\n\r mmSPI::allocations : FATAL malloc error for pCPUclk. \n\r");
}
//----------------------------------------------//------------------------------
void mmSPI::setSPIfrequency(float fFreq) // set SPI clock frequency.
{
fSPIfreq = fFreq; // promote to object scope.
if (fSPIfreq < .05) // don't get near divide-by-zero.
error("\n\r mmSPI::setSPIfrequency : FATAL SPI frequency set too low. \n\r");
fSPIquarterP = (1 / fSPIfreq) / 4; // figure quarter-cycle period.
}
//----------------------------------------------//------------------------------
// obtain SPI send buffer pointer.
void mmSPI::setSendBuffer(char * pcSendBuffer)
{
pcSend = pcSendBuffer; // promote to object scope.
}
//----------------------------------------------//------------------------------
// obtain SPI receive buffer pointer.
void mmSPI::setReceiveBuffer(char * pcReceiveBuffer)
{
pcReceive = pcReceiveBuffer; // promote to object scope.
}
//----------------------------------------------//------------------------------
// obtain number of SPI bytes.
void mmSPI::setNumberOfBytes(int dNumberOfBytes)
{
dNumBytes = dNumberOfBytes; // promote to object scope.
}
//----------------------------------------------//------------------------------
// transceive a character array.
// MSB out/in first.
void mmSPI::transceive_vector(void)
{
int dClear;
int dIndex;
int dMosiByteIndex;
int dMosiBitIndex;
int dMisoByteIndex;
int dMisoBitIndex;
dIndex = (dNumBytes * 8) - 1;
dMosiByteIndex = dIndex / 8;
dMosiBitIndex = dIndex % 8;
for (dClear = 0; dClear < dNumBytes; dClear++) pcReceive[dClear] = 0;
*pCPUclk = 1; // pulse the CPU clock.
wait(fSPIquarterP);
wait(fSPIquarterP);
*pCPUclk = 0;
wait(fSPIquarterP);
wait(fSPIquarterP);
*pSCLK = 1; // pulse the SPI clock for parallel load.
wait(fSPIquarterP);
wait(fSPIquarterP);
*pSCLK = 0;
// pre-assert MOSI.
*pMOSI = ((pcSend[dMosiByteIndex]) >> dMosiBitIndex) & 1;
wait(fSPIquarterP);
wait(fSPIquarterP);
for (dIndex = (dNumBytes * 8) - 1; dIndex >= 0; dIndex--)
{
dMisoByteIndex = dIndex / 8;
dMisoBitIndex = dIndex % 8;
pcReceive[dMisoByteIndex] = pcReceive[dMisoByteIndex] | (*pMISO << dMisoBitIndex);
*pSCLK = 1;
wait(fSPIquarterP);
wait(fSPIquarterP);
*pSCLK = 0;
if (dIndex < 0) dIndex = 0;
dMosiByteIndex = (dIndex - 1) / 8;
dMosiBitIndex = (dIndex - 1) % 8;
*pMOSI = ((pcSend[dMosiByteIndex]) >> dMosiBitIndex) & 1;
wait(fSPIquarterP);
wait(fSPIquarterP);
}
}
//----------------------------------------------//------------------------------
// cRegister -> CPU_register
// 0 R0
// 1 R1
// 2 R2
// 3 R3
// 4 PC
// 5 <meta, don't do>
// 6 <nothing>
// 7 <nothing>
void mmSPI::write_register(char cRegister, char cValue)
{
int dLoop; // loop index.
clear_transmit_vector(); // clear transmit vector.
pcSend[7] = 0x02; // mbed sends a command.
// align into instruction word.
pcSend[1] = ((cRegister & 0x07) << 2) | 0xA0;
pcSend[0] = cValue & 0xFF; // immediate value to i.w.
transceive_vector(); // transmit command.
clear_transmit_vector(); // clear transmit vector.
}
//----------------------------------------------//------------------------------
// cRegister -> CPU_register
// 0 -> R0
// 1 -> R1
// 2 -> R2
// 3 -> R3
// 4 -> PC
// 5 -> IR-H
// 6 -> IR-L
// 7 -> <never-use>
// returns the content of
// a CPU register.
char mmSPI::read_register(char cRegister)
{
clear_transmit_vector(); // clear transmit vector.
pcSend[7] = 0x02; // suppress cpu operation.
transceive_vector(); // snap & scan-out reg contents.
return (pcReceive[6 - cRegister]); // return the particular reg value.
}
//----------------------------------------------//------------------------------
void mmSPI::write_memory(char cHData, char cLdata, char cAddress)
{
clear_transmit_vector(); // clear transmit vector.
write_register(0x03,cAddress); // R3 <- address.
write_register(0x02,cHData); // R2 <- high-data.
write_register(0x01,cLdata); // R1 <- low-data.
pcSend[7] = 0x02; // mbed sends command.
pcSend[1] = 0x02; // write-enable high.
pcSend[0] = 0x00; // remainder of instruction.
transceive_vector();
pcSend[7] = 0x02; // mbed sends command.
pcSend[1] = 0x00; // write-enable low.
pcSend[0] = 0x00; // remainder of instruction.
transceive_vector();
clear_transmit_vector(); // clear transmit vector.
}
//----------------------------------------------//------------------------------
// fetch a word from main memory.
unsigned int mmSPI::read_memory(char cAddress)
{
unsigned int udMemoryContent; // return variable.
char cHData; // returned data-high.
char cLData; // returned data-low.
clear_transmit_vector(); // clear transmit vector.
write_register(0x03,cAddress); // R3 <= address.
pcSend[7] = 0x02; // mbed sends command.
pcSend[1] = 0xC8; // R2 <- MM[R3]
pcSend[0] = 0x00;
transceive_vector(); // send command.
pcSend[7] = 0x02; // mbed sends command.
pcSend[1] = 0xC4; // R1 <- MM[R3]
pcSend[0] = 0x00;
transceive_vector(); // send command.
cHData = read_register(0x02); // obtain MM high-data-byte.
cLData = read_register(0x01); // obtain MM low-data-byte.
udMemoryContent = (cHData << 8) + cLData; // build the memory word.
clear_transmit_vector(); // clear transmit vector.
return udMemoryContent; // return the memory word.
}
//----------------------------------------------//------------------------------
void mmSPI::clear_transmit_vector(void) // fill transmit buffer with 0.
{
int dLoop;
for (dLoop = 0; dLoop < dNumBytes; dLoop++) pcSend[dLoop] = 0x00;
}
//----------------------------------------------//------------------------------
