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

Committer:
gatedClock
Date:
Sun Aug 25 20:12:32 2013 +0000
Revision:
31:ea7b25e494b5
Parent:
30:331c7c7d8bc1
Child:
32:5a5d9525c6c4
this is working with python 'run'.

Who changed what in which revision?

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