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

Committer:
gatedClock
Date:
Fri Aug 30 20:46:52 2013 +0000
Revision:
33:59e13ec04ea8
Parent:
32:5a5d9525c6c4
snapshot current state.

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 33:59e13ec04ea8 164 // 5 IR
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 33:59e13ec04ea8 174 switch(cRegister)
gatedClock 33:59e13ec04ea8 175 {
gatedClock 33:59e13ec04ea8 176 case 5 : {pcSend[7] = 0x02; break;} // write IR-L.
gatedClock 33:59e13ec04ea8 177 case 6 : {pcSend[7] = 0x0A; break;} // write IR-H.
gatedClock 33:59e13ec04ea8 178 default: {pcSend[7] = 0x02; break;} // other register writes.
gatedClock 33:59e13ec04ea8 179 }
gatedClock 33:59e13ec04ea8 180
gatedClock 18:4a29cad91540 181 // align into instruction word.
gatedClock 16:0e422fd263c6 182 pcSend[1] = ((cRegister & 0x07) << 2) | 0xA0;
gatedClock 18:4a29cad91540 183 pcSend[0] = cValue & 0xFF; // immediate value to i.w.
gatedClock 17:b81c0c1f312f 184
gatedClock 31:ea7b25e494b5 185 transceive_vector(1,1,1,0); // transmit command.
gatedClock 18:4a29cad91540 186
gatedClock 24:d3b8c68f41f2 187 clear_transmit_vector(); // clear transmit vector.
gatedClock 32:5a5d9525c6c4 188 } // write_register.
gatedClock 17:b81c0c1f312f 189 //----------------------------------------------//------------------------------
gatedClock 26:26a8f31a31b8 190 // cRegister -> CPU_register
gatedClock 26:26a8f31a31b8 191 // 0 -> R0
gatedClock 26:26a8f31a31b8 192 // 1 -> R1
gatedClock 26:26a8f31a31b8 193 // 2 -> R2
gatedClock 26:26a8f31a31b8 194 // 3 -> R3
gatedClock 26:26a8f31a31b8 195 // 4 -> PC
gatedClock 26:26a8f31a31b8 196 // 5 -> IR-H
gatedClock 26:26a8f31a31b8 197 // 6 -> IR-L
gatedClock 26:26a8f31a31b8 198 // 7 -> <never-use>
gatedClock 17:b81c0c1f312f 199 // returns the content of
gatedClock 17:b81c0c1f312f 200 // a CPU register.
gatedClock 23:dbd89a56716d 201 char mmSPI::read_register(char cRegister)
gatedClock 17:b81c0c1f312f 202 {
gatedClock 24:d3b8c68f41f2 203 clear_transmit_vector(); // clear transmit vector.
gatedClock 29:4ed71dfee7d8 204
gatedClock 29:4ed71dfee7d8 205 pcSend[7] = 0x02; // suppress cpu operation.
gatedClock 29:4ed71dfee7d8 206
gatedClock 31:ea7b25e494b5 207 transceive_vector(1,1,1,0); // snap & scan-out reg contents.
gatedClock 17:b81c0c1f312f 208
gatedClock 19:c2b753533b93 209 return (pcReceive[6 - cRegister]); // return the particular reg value.
gatedClock 32:5a5d9525c6c4 210 } // read_register.
gatedClock 17:b81c0c1f312f 211 //----------------------------------------------//------------------------------
gatedClock 23:dbd89a56716d 212 void mmSPI::write_memory(char cHData, char cLdata, char cAddress)
gatedClock 18:4a29cad91540 213 {
gatedClock 24:d3b8c68f41f2 214 clear_transmit_vector(); // clear transmit vector.
gatedClock 24:d3b8c68f41f2 215
gatedClock 24:d3b8c68f41f2 216 write_register(0x03,cAddress); // R3 <- address.
gatedClock 24:d3b8c68f41f2 217 write_register(0x02,cHData); // R2 <- high-data.
gatedClock 24:d3b8c68f41f2 218 write_register(0x01,cLdata); // R1 <- low-data.
gatedClock 18:4a29cad91540 219
gatedClock 27:fb63c8b70bc2 220 pcSend[7] = 0x02; // mbed sends command.
gatedClock 27:fb63c8b70bc2 221 pcSend[1] = 0x02; // write-enable high.
gatedClock 27:fb63c8b70bc2 222 pcSend[0] = 0x00; // remainder of instruction.
gatedClock 31:ea7b25e494b5 223 transceive_vector(1,1,1,0);
gatedClock 18:4a29cad91540 224
gatedClock 27:fb63c8b70bc2 225 pcSend[7] = 0x02; // mbed sends command.
gatedClock 27:fb63c8b70bc2 226 pcSend[1] = 0x00; // write-enable low.
gatedClock 27:fb63c8b70bc2 227 pcSend[0] = 0x00; // remainder of instruction.
gatedClock 31:ea7b25e494b5 228 transceive_vector(1,1,1,0);
gatedClock 24:d3b8c68f41f2 229
gatedClock 24:d3b8c68f41f2 230 clear_transmit_vector(); // clear transmit vector.
gatedClock 32:5a5d9525c6c4 231 } // write_memory.
gatedClock 18:4a29cad91540 232 //----------------------------------------------//------------------------------
gatedClock 18:4a29cad91540 233 // fetch a word from main memory.
gatedClock 23:dbd89a56716d 234 unsigned int mmSPI::read_memory(char cAddress)
gatedClock 24:d3b8c68f41f2 235 {
gatedClock 18:4a29cad91540 236 unsigned int udMemoryContent; // return variable.
gatedClock 18:4a29cad91540 237 char cHData; // returned data-high.
gatedClock 18:4a29cad91540 238 char cLData; // returned data-low.
gatedClock 24:d3b8c68f41f2 239
gatedClock 24:d3b8c68f41f2 240 clear_transmit_vector(); // clear transmit vector.
gatedClock 21:e90dd0f8aaa1 241
gatedClock 24:d3b8c68f41f2 242 write_register(0x03,cAddress); // R3 <= address.
gatedClock 18:4a29cad91540 243
gatedClock 18:4a29cad91540 244 pcSend[7] = 0x02; // mbed sends command.
gatedClock 20:2d5cd38047ca 245 pcSend[1] = 0xC8; // R2 <- 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 18:4a29cad91540 249 pcSend[7] = 0x02; // mbed sends command.
gatedClock 20:2d5cd38047ca 250 pcSend[1] = 0xC4; // R1 <- MM[R3]
gatedClock 18:4a29cad91540 251 pcSend[0] = 0x00;
gatedClock 31:ea7b25e494b5 252 transceive_vector(1,1,1,0); // send command.
gatedClock 18:4a29cad91540 253
gatedClock 24:d3b8c68f41f2 254 cHData = read_register(0x02); // obtain MM high-data-byte.
gatedClock 24:d3b8c68f41f2 255 cLData = read_register(0x01); // obtain MM low-data-byte.
gatedClock 31:ea7b25e494b5 256
gatedClock 18:4a29cad91540 257 udMemoryContent = (cHData << 8) + cLData; // build the memory word.
gatedClock 24:d3b8c68f41f2 258
gatedClock 24:d3b8c68f41f2 259 clear_transmit_vector(); // clear transmit vector.
gatedClock 18:4a29cad91540 260
gatedClock 18:4a29cad91540 261 return udMemoryContent; // return the memory word.
gatedClock 32:5a5d9525c6c4 262 } // read_memory.
gatedClock 18:4a29cad91540 263 //----------------------------------------------//------------------------------
gatedClock 30:331c7c7d8bc1 264 void mmSPI::step(void) // step the CPU.
gatedClock 30:331c7c7d8bc1 265 {
gatedClock 31:ea7b25e494b5 266 clear_transmit_vector(); // clear transmit vector.
gatedClock 31:ea7b25e494b5 267 transceive_vector(0,0,1,0); // enable CPU mode.
gatedClock 31:ea7b25e494b5 268 transceive_vector(0,0,0,1); // advance CPU, clear shadow-load.
gatedClock 31:ea7b25e494b5 269 pcSend[7] = 0x02; // ready to disable CPU mode.
gatedClock 31:ea7b25e494b5 270 transceive_vector(0,0,1,0); // disable CPU mode.
gatedClock 32:5a5d9525c6c4 271 } // step.
gatedClock 30:331c7c7d8bc1 272 //----------------------------------------------//------------------------------
gatedClock 24:d3b8c68f41f2 273 void mmSPI::clear_transmit_vector(void) // fill transmit buffer with 0.
gatedClock 24:d3b8c68f41f2 274 {
gatedClock 24:d3b8c68f41f2 275 int dLoop;
gatedClock 24:d3b8c68f41f2 276 for (dLoop = 0; dLoop < dNumBytes; dLoop++) pcSend[dLoop] = 0x00;
gatedClock 32:5a5d9525c6c4 277 } // clear_transmit_vector.
gatedClock 32:5a5d9525c6c4 278 //----------------------------------------------//------------------------------
gatedClock 32:5a5d9525c6c4 279 // getters.
gatedClock 32:5a5d9525c6c4 280 unsigned long mmSPI::SPIClockCount() {return ulSPIclkCount;}
gatedClock 32:5a5d9525c6c4 281 unsigned long mmSPI::CPUClockCount() {return ulCPUclkCount;}
gatedClock 24:d3b8c68f41f2 282 //----------------------------------------------//------------------------------
gatedClock 17:b81c0c1f312f 283
gatedClock 17:b81c0c1f312f 284
gatedClock 5:b14dcaae260e 285
gatedClock 5:b14dcaae260e 286
gatedClock 5:b14dcaae260e 287
gatedClock 5:b14dcaae260e 288
gatedClock 5:b14dcaae260e 289
gatedClock 5:b14dcaae260e 290