SPI library used to communicate with an altera development board attached to four zigbee-header pins.

Committer:
gatedClock
Date:
Mon Aug 26 22:39:44 2013 +0000
Revision:
32:5a5d9525c6c4
Parent:
31:ea7b25e494b5
Child:
33:59e13ec04ea8
Child:
34:d5553509f31a
cleanup.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gatedClock 0:fb42c5acf810 1 /*----------------------------------------------//------------------------------
gatedClock 0:fb42c5acf810 2 student : m-moore
gatedClock 32:5a5d9525c6c4 3 email : gated.clock@gmail.com
gatedClock 32:5a5d9525c6c4 4 class : usb device drivers
gatedClock 0:fb42c5acf810 5 directory : mmSPI
gatedClock 0:fb42c5acf810 6 file : mmSPI.cpp
gatedClock 32:5a5d9525c6c4 7 date : september 3, 2013.
gatedClock 0:fb42c5acf810 8 ------------------------------------------------//----------------------------*/
gatedClock 0:fb42c5acf810 9 #include "mmSPI.h"
gatedClock 0:fb42c5acf810 10 /*----------------------------------------------//------------------------------
gatedClock 0:fb42c5acf810 11 ------------------------------------------------//----------------------------*/
gatedClock 0:fb42c5acf810 12 //==============================================//==============================
gatedClock 0:fb42c5acf810 13 mmSPI::mmSPI() // constructor.
gatedClock 0:fb42c5acf810 14 {
gatedClock 3:de99451ab3c0 15 allocations(); // object allocations.
gatedClock 15:d6cc57c4e23d 16
gatedClock 32:5a5d9525c6c4 17 *pSCLK = 0; // initialize.
gatedClock 32:5a5d9525c6c4 18 *pCPUclk = 0; // initialize.
gatedClock 32:5a5d9525c6c4 19 ulSPIclkCount = 0; // initialize.
gatedClock 32:5a5d9525c6c4 20 ulCPUclkCount = 0; // initialize.
gatedClock 32:5a5d9525c6c4 21 } // constructor.
gatedClock 0:fb42c5acf810 22 //----------------------------------------------//------------------------------
gatedClock 0:fb42c5acf810 23 mmSPI::~mmSPI() // destructor.
gatedClock 0:fb42c5acf810 24 {
gatedClock 8:e2d8bbc3e659 25 // deallocations.
gatedClock 8:e2d8bbc3e659 26 if (pMOSI) {delete pMOSI; pMOSI = NULL;}
gatedClock 8:e2d8bbc3e659 27 if (pMISO) {delete pMISO; pMISO = NULL;}
gatedClock 8:e2d8bbc3e659 28 if (pSCLK) {delete pSCLK; pSCLK = NULL;}
gatedClock 8:e2d8bbc3e659 29 if (pCPUclk) {delete pCPUclk; pCPUclk = NULL;}
gatedClock 32:5a5d9525c6c4 30 } // destructor.
gatedClock 3:de99451ab3c0 31 //----------------------------------------------//------------------------------
gatedClock 3:de99451ab3c0 32 void mmSPI::allocations(void) // object allocations.
gatedClock 3:de99451ab3c0 33 {
gatedClock 32:5a5d9525c6c4 34 pMOSI = new DigitalOut(mmSPI_MOSI); // SPI MOSI pin object.
gatedClock 3:de99451ab3c0 35 if (!pMOSI) error("\n\r mmSPI::allocations : FATAL malloc error for pMOSI. \n\r");
gatedClock 3:de99451ab3c0 36
gatedClock 32:5a5d9525c6c4 37 pMISO = new DigitalOut(mmSPI_MISO); // SPI MISO pin object.
gatedClock 3:de99451ab3c0 38 if (!pMISO) error("\n\r mmSPI::allocations : FATAL malloc error for pMISO. \n\r");
gatedClock 3:de99451ab3c0 39
gatedClock 32:5a5d9525c6c4 40 pSCLK = new DigitalOut(mmSPI_SCLK); // SPI SCLK pin object.
gatedClock 3:de99451ab3c0 41 if (!pSCLK) error("\n\r mmSPI::allocations : FATAL malloc error for pSCLK. \n\r");
gatedClock 8:e2d8bbc3e659 42
gatedClock 32:5a5d9525c6c4 43 pCPUclk = new DigitalOut(mmCPU_CLK); // SPI SCLK pin object.
gatedClock 8:e2d8bbc3e659 44 if (!pCPUclk) error("\n\r mmSPI::allocations : FATAL malloc error for pCPUclk. \n\r");
gatedClock 32:5a5d9525c6c4 45 } // allocations.
gatedClock 4:aa1fe8707bef 46 //----------------------------------------------//------------------------------
gatedClock 4:aa1fe8707bef 47 void mmSPI::setSPIfrequency(float fFreq) // set SPI clock frequency.
gatedClock 4:aa1fe8707bef 48 {
gatedClock 4:aa1fe8707bef 49 fSPIfreq = fFreq; // promote to object scope.
gatedClock 4:aa1fe8707bef 50 if (fSPIfreq < .05) // don't get near divide-by-zero.
gatedClock 4:aa1fe8707bef 51 error("\n\r mmSPI::setSPIfrequency : FATAL SPI frequency set too low. \n\r");
gatedClock 4:aa1fe8707bef 52 fSPIquarterP = (1 / fSPIfreq) / 4; // figure quarter-cycle period.
gatedClock 4:aa1fe8707bef 53 }
gatedClock 22:7524dee5c753 54 //----------------------------------------------//------------------------------
gatedClock 22:7524dee5c753 55 // obtain SPI send buffer pointer.
gatedClock 22:7524dee5c753 56 void mmSPI::setSendBuffer(char * pcSendBuffer)
gatedClock 22:7524dee5c753 57 {
gatedClock 22:7524dee5c753 58 pcSend = pcSendBuffer; // promote to object scope.
gatedClock 32:5a5d9525c6c4 59 } // setSendBuffer.
gatedClock 22:7524dee5c753 60 //----------------------------------------------//------------------------------
gatedClock 22:7524dee5c753 61 // obtain SPI receive buffer pointer.
gatedClock 22:7524dee5c753 62 void mmSPI::setReceiveBuffer(char * pcReceiveBuffer)
gatedClock 22:7524dee5c753 63 {
gatedClock 22:7524dee5c753 64 pcReceive = pcReceiveBuffer; // promote to object scope.
gatedClock 32:5a5d9525c6c4 65 } // setReceiveBuffer.
gatedClock 0:fb42c5acf810 66 //----------------------------------------------//------------------------------
gatedClock 22:7524dee5c753 67 // obtain number of SPI bytes.
gatedClock 22:7524dee5c753 68 void mmSPI::setNumberOfBytes(int dNumberOfBytes)
gatedClock 22:7524dee5c753 69 {
gatedClock 22:7524dee5c753 70 dNumBytes = dNumberOfBytes; // promote to object scope.
gatedClock 32:5a5d9525c6c4 71 } // setNumberOfBytes.
gatedClock 22:7524dee5c753 72 //----------------------------------------------//------------------------------
gatedClock 16:0e422fd263c6 73 // transceive a character array.
gatedClock 16:0e422fd263c6 74 // MSB out/in first.
gatedClock 31:ea7b25e494b5 75 // normal inputs: [1,1,1,0]
gatedClock 31:ea7b25e494b5 76 // CPUstep input : [0,0,1,1]
gatedClock 31:ea7b25e494b5 77 void mmSPI::transceive_vector(char cPreCPU, char cPreSPI, char cScan, char cPostCPU)
gatedClock 16:0e422fd263c6 78 {
gatedClock 16:0e422fd263c6 79 int dClear;
gatedClock 16:0e422fd263c6 80 int dIndex;
gatedClock 16:0e422fd263c6 81 int dMosiByteIndex;
gatedClock 16:0e422fd263c6 82 int dMosiBitIndex;
gatedClock 16:0e422fd263c6 83 int dMisoByteIndex;
gatedClock 16:0e422fd263c6 84 int dMisoBitIndex;
gatedClock 16:0e422fd263c6 85
gatedClock 16:0e422fd263c6 86 dIndex = (dNumBytes * 8) - 1;
gatedClock 31:ea7b25e494b5 87 dMosiByteIndex = dIndex / 8;
gatedClock 31:ea7b25e494b5 88 dMosiBitIndex = dIndex % 8;
gatedClock 16:0e422fd263c6 89
gatedClock 16:0e422fd263c6 90 for (dClear = 0; dClear < dNumBytes; dClear++) pcReceive[dClear] = 0;
gatedClock 16:0e422fd263c6 91
gatedClock 31:ea7b25e494b5 92 if (cPreCPU) // if pre-CPU clock.
gatedClock 31:ea7b25e494b5 93 {
gatedClock 31:ea7b25e494b5 94 *pCPUclk = 1; // pulse the CPU clock.
gatedClock 31:ea7b25e494b5 95 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 96 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 97 *pCPUclk = 0;
gatedClock 31:ea7b25e494b5 98 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 99 wait(fSPIquarterP);
gatedClock 32:5a5d9525c6c4 100 ulCPUclkCount++;
gatedClock 31:ea7b25e494b5 101 } // if pre-CPU clock.
gatedClock 16:0e422fd263c6 102
gatedClock 31:ea7b25e494b5 103 if (cPreSPI) // if pre-SPI pulse.
gatedClock 31:ea7b25e494b5 104 {
gatedClock 31:ea7b25e494b5 105 *pSCLK = 1; // pulse the SPI clock for parallel load.
gatedClock 31:ea7b25e494b5 106 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 107 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 108 *pSCLK = 0;
gatedClock 32:5a5d9525c6c4 109 ulSPIclkCount++;
gatedClock 31:ea7b25e494b5 110 } // if pre-SPI pulse.
gatedClock 31:ea7b25e494b5 111
gatedClock 31:ea7b25e494b5 112 if (cScan) // if cScan.
gatedClock 31:ea7b25e494b5 113 {
gatedClock 16:0e422fd263c6 114 // pre-assert MOSI.
gatedClock 31:ea7b25e494b5 115 *pMOSI = ((pcSend[dMosiByteIndex]) >> dMosiBitIndex) & 1;
gatedClock 31:ea7b25e494b5 116 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 117 wait(fSPIquarterP);
gatedClock 16:0e422fd263c6 118
gatedClock 16:0e422fd263c6 119
gatedClock 32:5a5d9525c6c4 120 // main SPI scan loop.
gatedClock 31:ea7b25e494b5 121 for (dIndex = (dNumBytes * 8) - 1; dIndex >= 0; dIndex--)
gatedClock 31:ea7b25e494b5 122 {
gatedClock 31:ea7b25e494b5 123 dMisoByteIndex = dIndex / 8;
gatedClock 31:ea7b25e494b5 124 dMisoBitIndex = dIndex % 8;
gatedClock 31:ea7b25e494b5 125 pcReceive[dMisoByteIndex] = pcReceive[dMisoByteIndex] | (*pMISO << dMisoBitIndex);
gatedClock 31:ea7b25e494b5 126 *pSCLK = 1;
gatedClock 31:ea7b25e494b5 127 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 128 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 129 *pSCLK = 0;
gatedClock 31:ea7b25e494b5 130 if (dIndex < 0) dIndex = 0;
gatedClock 31:ea7b25e494b5 131 dMosiByteIndex = (dIndex - 1) / 8;
gatedClock 31:ea7b25e494b5 132 dMosiBitIndex = (dIndex - 1) % 8;
gatedClock 31:ea7b25e494b5 133 *pMOSI = ((pcSend[dMosiByteIndex]) >> dMosiBitIndex) & 1;
gatedClock 31:ea7b25e494b5 134 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 135 wait(fSPIquarterP);
gatedClock 32:5a5d9525c6c4 136 ulSPIclkCount++;
gatedClock 32:5a5d9525c6c4 137 } // main SPI scan loop.
gatedClock 31:ea7b25e494b5 138 } // if cScan.
gatedClock 31:ea7b25e494b5 139
gatedClock 31:ea7b25e494b5 140 if (cPostCPU) // if post-CPU pulse.
gatedClock 16:0e422fd263c6 141 {
gatedClock 31:ea7b25e494b5 142 *pCPUclk = 1; // pulse the CPU clock.
gatedClock 31:ea7b25e494b5 143 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 144 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 145 *pCPUclk = 0;
gatedClock 31:ea7b25e494b5 146 wait(fSPIquarterP);
gatedClock 32:5a5d9525c6c4 147 wait(fSPIquarterP);
gatedClock 32:5a5d9525c6c4 148 ulCPUclkCount++;
gatedClock 31:ea7b25e494b5 149
gatedClock 31:ea7b25e494b5 150 *pSCLK = 1; // clear-out the SPI parallel-load enable.
gatedClock 16:0e422fd263c6 151 wait(fSPIquarterP);
gatedClock 16:0e422fd263c6 152 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 153 *pSCLK = 0;
gatedClock 32:5a5d9525c6c4 154 ulSPIclkCount++;
gatedClock 31:ea7b25e494b5 155 } // if post-CPU pulse.
gatedClock 32:5a5d9525c6c4 156 } // transceive_vector.
gatedClock 7:b3e8b537d5c2 157 //----------------------------------------------//------------------------------
gatedClock 26:26a8f31a31b8 158 // cRegister -> CPU_register
gatedClock 26:26a8f31a31b8 159 // 0 R0
gatedClock 26:26a8f31a31b8 160 // 1 R1
gatedClock 26:26a8f31a31b8 161 // 2 R2
gatedClock 26:26a8f31a31b8 162 // 3 R3
gatedClock 26:26a8f31a31b8 163 // 4 PC
gatedClock 26:26a8f31a31b8 164 // 5 <meta, don't do>
gatedClock 26:26a8f31a31b8 165 // 6 <nothing>
gatedClock 26:26a8f31a31b8 166 // 7 <nothing>
gatedClock 26:26a8f31a31b8 167
gatedClock 23:dbd89a56716d 168 void mmSPI::write_register(char cRegister, char cValue)
gatedClock 16:0e422fd263c6 169 {
gatedClock 18:4a29cad91540 170 int dLoop; // loop index.
gatedClock 18:4a29cad91540 171
gatedClock 24:d3b8c68f41f2 172 clear_transmit_vector(); // clear transmit vector.
gatedClock 18:4a29cad91540 173
gatedClock 18:4a29cad91540 174 pcSend[7] = 0x02; // mbed sends a command.
gatedClock 18:4a29cad91540 175
gatedClock 18:4a29cad91540 176 // align into instruction word.
gatedClock 16:0e422fd263c6 177 pcSend[1] = ((cRegister & 0x07) << 2) | 0xA0;
gatedClock 18:4a29cad91540 178 pcSend[0] = cValue & 0xFF; // immediate value to i.w.
gatedClock 17:b81c0c1f312f 179
gatedClock 31:ea7b25e494b5 180 transceive_vector(1,1,1,0); // transmit command.
gatedClock 18:4a29cad91540 181
gatedClock 24:d3b8c68f41f2 182 clear_transmit_vector(); // clear transmit vector.
gatedClock 32:5a5d9525c6c4 183 } // write_register.
gatedClock 17:b81c0c1f312f 184 //----------------------------------------------//------------------------------
gatedClock 26:26a8f31a31b8 185 // cRegister -> CPU_register
gatedClock 26:26a8f31a31b8 186 // 0 -> R0
gatedClock 26:26a8f31a31b8 187 // 1 -> R1
gatedClock 26:26a8f31a31b8 188 // 2 -> R2
gatedClock 26:26a8f31a31b8 189 // 3 -> R3
gatedClock 26:26a8f31a31b8 190 // 4 -> PC
gatedClock 26:26a8f31a31b8 191 // 5 -> IR-H
gatedClock 26:26a8f31a31b8 192 // 6 -> IR-L
gatedClock 26:26a8f31a31b8 193 // 7 -> <never-use>
gatedClock 17:b81c0c1f312f 194 // returns the content of
gatedClock 17:b81c0c1f312f 195 // a CPU register.
gatedClock 23:dbd89a56716d 196 char mmSPI::read_register(char cRegister)
gatedClock 17:b81c0c1f312f 197 {
gatedClock 24:d3b8c68f41f2 198 clear_transmit_vector(); // clear transmit vector.
gatedClock 29:4ed71dfee7d8 199
gatedClock 29:4ed71dfee7d8 200 pcSend[7] = 0x02; // suppress cpu operation.
gatedClock 29:4ed71dfee7d8 201
gatedClock 31:ea7b25e494b5 202 transceive_vector(1,1,1,0); // snap & scan-out reg contents.
gatedClock 17:b81c0c1f312f 203
gatedClock 19:c2b753533b93 204 return (pcReceive[6 - cRegister]); // return the particular reg value.
gatedClock 32:5a5d9525c6c4 205 } // read_register.
gatedClock 17:b81c0c1f312f 206 //----------------------------------------------//------------------------------
gatedClock 23:dbd89a56716d 207 void mmSPI::write_memory(char cHData, char cLdata, char cAddress)
gatedClock 18:4a29cad91540 208 {
gatedClock 24:d3b8c68f41f2 209 clear_transmit_vector(); // clear transmit vector.
gatedClock 24:d3b8c68f41f2 210
gatedClock 24:d3b8c68f41f2 211 write_register(0x03,cAddress); // R3 <- address.
gatedClock 24:d3b8c68f41f2 212 write_register(0x02,cHData); // R2 <- high-data.
gatedClock 24:d3b8c68f41f2 213 write_register(0x01,cLdata); // R1 <- low-data.
gatedClock 18:4a29cad91540 214
gatedClock 27:fb63c8b70bc2 215 pcSend[7] = 0x02; // mbed sends command.
gatedClock 27:fb63c8b70bc2 216 pcSend[1] = 0x02; // write-enable high.
gatedClock 27:fb63c8b70bc2 217 pcSend[0] = 0x00; // remainder of instruction.
gatedClock 31:ea7b25e494b5 218 transceive_vector(1,1,1,0);
gatedClock 18:4a29cad91540 219
gatedClock 27:fb63c8b70bc2 220 pcSend[7] = 0x02; // mbed sends command.
gatedClock 27:fb63c8b70bc2 221 pcSend[1] = 0x00; // write-enable low.
gatedClock 27:fb63c8b70bc2 222 pcSend[0] = 0x00; // remainder of instruction.
gatedClock 31:ea7b25e494b5 223 transceive_vector(1,1,1,0);
gatedClock 24:d3b8c68f41f2 224
gatedClock 24:d3b8c68f41f2 225 clear_transmit_vector(); // clear transmit vector.
gatedClock 32:5a5d9525c6c4 226 } // write_memory.
gatedClock 18:4a29cad91540 227 //----------------------------------------------//------------------------------
gatedClock 18:4a29cad91540 228 // fetch a word from main memory.
gatedClock 23:dbd89a56716d 229 unsigned int mmSPI::read_memory(char cAddress)
gatedClock 24:d3b8c68f41f2 230 {
gatedClock 18:4a29cad91540 231 unsigned int udMemoryContent; // return variable.
gatedClock 18:4a29cad91540 232 char cHData; // returned data-high.
gatedClock 18:4a29cad91540 233 char cLData; // returned data-low.
gatedClock 24:d3b8c68f41f2 234
gatedClock 24:d3b8c68f41f2 235 clear_transmit_vector(); // clear transmit vector.
gatedClock 21:e90dd0f8aaa1 236
gatedClock 24:d3b8c68f41f2 237 write_register(0x03,cAddress); // R3 <= address.
gatedClock 18:4a29cad91540 238
gatedClock 18:4a29cad91540 239 pcSend[7] = 0x02; // mbed sends command.
gatedClock 20:2d5cd38047ca 240 pcSend[1] = 0xC8; // R2 <- MM[R3]
gatedClock 18:4a29cad91540 241 pcSend[0] = 0x00;
gatedClock 31:ea7b25e494b5 242 transceive_vector(1,1,1,0); // send command.
gatedClock 18:4a29cad91540 243
gatedClock 18:4a29cad91540 244 pcSend[7] = 0x02; // mbed sends command.
gatedClock 20:2d5cd38047ca 245 pcSend[1] = 0xC4; // R1 <- MM[R3]
gatedClock 18:4a29cad91540 246 pcSend[0] = 0x00;
gatedClock 31:ea7b25e494b5 247 transceive_vector(1,1,1,0); // send command.
gatedClock 18:4a29cad91540 248
gatedClock 24:d3b8c68f41f2 249 cHData = read_register(0x02); // obtain MM high-data-byte.
gatedClock 24:d3b8c68f41f2 250 cLData = read_register(0x01); // obtain MM low-data-byte.
gatedClock 31:ea7b25e494b5 251
gatedClock 18:4a29cad91540 252 udMemoryContent = (cHData << 8) + cLData; // build the memory word.
gatedClock 24:d3b8c68f41f2 253
gatedClock 24:d3b8c68f41f2 254 clear_transmit_vector(); // clear transmit vector.
gatedClock 18:4a29cad91540 255
gatedClock 18:4a29cad91540 256 return udMemoryContent; // return the memory word.
gatedClock 32:5a5d9525c6c4 257 } // read_memory.
gatedClock 18:4a29cad91540 258 //----------------------------------------------//------------------------------
gatedClock 30:331c7c7d8bc1 259 void mmSPI::step(void) // step the CPU.
gatedClock 30:331c7c7d8bc1 260 {
gatedClock 31:ea7b25e494b5 261 clear_transmit_vector(); // clear transmit vector.
gatedClock 31:ea7b25e494b5 262 transceive_vector(0,0,1,0); // enable CPU mode.
gatedClock 31:ea7b25e494b5 263 transceive_vector(0,0,0,1); // advance CPU, clear shadow-load.
gatedClock 31:ea7b25e494b5 264 pcSend[7] = 0x02; // ready to disable CPU mode.
gatedClock 31:ea7b25e494b5 265 transceive_vector(0,0,1,0); // disable CPU mode.
gatedClock 32:5a5d9525c6c4 266 } // step.
gatedClock 30:331c7c7d8bc1 267 //----------------------------------------------//------------------------------
gatedClock 24:d3b8c68f41f2 268 void mmSPI::clear_transmit_vector(void) // fill transmit buffer with 0.
gatedClock 24:d3b8c68f41f2 269 {
gatedClock 24:d3b8c68f41f2 270 int dLoop;
gatedClock 24:d3b8c68f41f2 271 for (dLoop = 0; dLoop < dNumBytes; dLoop++) pcSend[dLoop] = 0x00;
gatedClock 32:5a5d9525c6c4 272 } // clear_transmit_vector.
gatedClock 32:5a5d9525c6c4 273 //----------------------------------------------//------------------------------
gatedClock 32:5a5d9525c6c4 274 // getters.
gatedClock 32:5a5d9525c6c4 275 unsigned long mmSPI::SPIClockCount() {return ulSPIclkCount;}
gatedClock 32:5a5d9525c6c4 276 unsigned long mmSPI::CPUClockCount() {return ulCPUclkCount;}
gatedClock 24:d3b8c68f41f2 277 //----------------------------------------------//------------------------------
gatedClock 17:b81c0c1f312f 278
gatedClock 17:b81c0c1f312f 279
gatedClock 5:b14dcaae260e 280
gatedClock 5:b14dcaae260e 281
gatedClock 5:b14dcaae260e 282
gatedClock 5:b14dcaae260e 283
gatedClock 5:b14dcaae260e 284
gatedClock 5:b14dcaae260e 285