This is an involuntary fork, created because the repository would not update mmSPI. SPI library used to communicate with an altera development board attached to four zigbee-header pins.

Dependents:   Embedded_RTOS_Project

Fork of mmSPI by Mike Moore

Committer:
gatedClock
Date:
Tue Sep 17 19:06:50 2013 +0000
Revision:
36:32cdc295f859
Parent:
35:6152c9709697
updates for RTOS class project.

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 36:32cdc295f859 4 class : embedded RTOS
gatedClock 35:6152c9709697 5 directory : USB_device_project/mmSPI
gatedClock 0:fb42c5acf810 6 file : mmSPI.cpp
gatedClock 36:32cdc295f859 7 date : september 19, 2013.
gatedClock 35:6152c9709697 8 ----copyright-----------------------------------//------------------------------
gatedClock 35:6152c9709697 9 licensed for personal and academic use.
gatedClock 36:32cdc295f859 10 commercial use of original code must be approved by the account-holder of
gatedClock 35:6152c9709697 11 gated.clock@gmail.com
gatedClock 35:6152c9709697 12 ----description---------------------------------//------------------------------
gatedClock 35:6152c9709697 13 this library provides the low-level SPI data and clock signaling
gatedClock 35:6152c9709697 14 for communication with the altera development board, via four i/o
gatedClock 35:6152c9709697 15 pins available on the mbed development board's zigbee header.
gatedClock 35:6152c9709697 16
gatedClock 35:6152c9709697 17 this library also provides higher-level calls to send/receive register
gatedClock 35:6152c9709697 18 and main-memory data to/from the CPU implemented in the altera.
gatedClock 35:6152c9709697 19
gatedClock 35:6152c9709697 20 the SPI clock and the CPU clock are both built by this library.
gatedClock 35:6152c9709697 21
gatedClock 35:6152c9709697 22 the SPI clock (*pSCLK) is generated with quarter-phase resolution,
gatedClock 35:6152c9709697 23 although at the moment, only half-phase resolution is being used.
gatedClock 35:6152c9709697 24
gatedClock 35:6152c9709697 25 within the FPGA, the SPI scan registers are called 'shadow registers'
gatedClock 35:6152c9709697 26 because they parallel load-to/store-from the CPU registers.
gatedClock 35:6152c9709697 27
gatedClock 35:6152c9709697 28 character vectors pcSend and pcReceive are used to scan-in and scan-out
gatedClock 35:6152c9709697 29 to/from the altera shadow registers. note that the prefix 'pc' means
gatedClock 35:6152c9709697 30 'pointer-of-type-character' and not 'personal-computer'.
gatedClock 35:6152c9709697 31
gatedClock 35:6152c9709697 32 the shadow registers in the altera are arranged as follows:
gatedClock 35:6152c9709697 33
gatedClock 35:6152c9709697 34 <-- MISO (altera-out to mbed-in)
gatedClock 35:6152c9709697 35 ^
gatedClock 35:6152c9709697 36 |
gatedClock 35:6152c9709697 37 scan_08 U14_spi_control = pcSend/pcReceive[7]
gatedClock 35:6152c9709697 38 scan_08 U08_shadowR0 = pcSend/pcReceive[6]
gatedClock 35:6152c9709697 39 scan_08 U09_shadowR1 = pcSend/pcReceive[5]
gatedClock 35:6152c9709697 40 scan_08 U10_shadowR2 = pcSend/pcReceive[4]
gatedClock 35:6152c9709697 41 scan_08 U11_shadowR3 = pcSend/pcReceive[3]
gatedClock 35:6152c9709697 42 scan_08 U12_shadowPC = pcSend/pcReceive[2]
gatedClock 35:6152c9709697 43 scan_16 U13_shadowIR = pcSend/pcReceive[1:0]
gatedClock 35:6152c9709697 44 ^
gatedClock 35:6152c9709697 45 |
gatedClock 35:6152c9709697 46 --> MOSI (altera-in from mbed-out)
gatedClock 35:6152c9709697 47
gatedClock 35:6152c9709697 48 when U14_spi_control<1> is high, the mbed takes over CPU operation.
gatedClock 35:6152c9709697 49 this means that the CPU instruction decoder decodes U13_shadowIR
gatedClock 35:6152c9709697 50 rather than the CPU's actual IR.
gatedClock 35:6152c9709697 51
gatedClock 35:6152c9709697 52 when U14_spi_control<2> is high, the mbed writes into the IR.
gatedClock 35:6152c9709697 53 this means that the CPU instruction decoder load-enable outputs
gatedClock 35:6152c9709697 54 are gated-off so that the mbed may write into the instrucition
gatedClock 35:6152c9709697 55 register without immediate consequence in the CPU. writing to
gatedClock 35:6152c9709697 56 the IR this way is more for the ability to show that it can be done,
gatedClock 35:6152c9709697 57 rather than any likely useful purpose.
gatedClock 35:6152c9709697 58
gatedClock 35:6152c9709697 59 debug/test:
gatedClock 35:6152c9709697 60 this library was debugged by using the altera FPGA logic analyzer
gatedClock 35:6152c9709697 61 known as 'signal tap'. the main program uses all of the memory and
gatedClock 35:6152c9709697 62 register access calls, which were used as an informal unit test.
gatedClock 35:6152c9709697 63 -----includes-----------------------------------//----------------------------*/
gatedClock 0:fb42c5acf810 64 #include "mmSPI.h"
gatedClock 0:fb42c5acf810 65 //==============================================//==============================
gatedClock 0:fb42c5acf810 66 mmSPI::mmSPI() // constructor.
gatedClock 0:fb42c5acf810 67 {
gatedClock 3:de99451ab3c0 68 allocations(); // object allocations.
gatedClock 15:d6cc57c4e23d 69
gatedClock 32:5a5d9525c6c4 70 *pSCLK = 0; // initialize.
gatedClock 32:5a5d9525c6c4 71 *pCPUclk = 0; // initialize.
gatedClock 32:5a5d9525c6c4 72 ulSPIclkCount = 0; // initialize.
gatedClock 32:5a5d9525c6c4 73 ulCPUclkCount = 0; // initialize.
gatedClock 32:5a5d9525c6c4 74 } // constructor.
gatedClock 0:fb42c5acf810 75 //----------------------------------------------//------------------------------
gatedClock 0:fb42c5acf810 76 mmSPI::~mmSPI() // destructor.
gatedClock 0:fb42c5acf810 77 {
gatedClock 8:e2d8bbc3e659 78 // deallocations.
gatedClock 8:e2d8bbc3e659 79 if (pMOSI) {delete pMOSI; pMOSI = NULL;}
gatedClock 8:e2d8bbc3e659 80 if (pMISO) {delete pMISO; pMISO = NULL;}
gatedClock 8:e2d8bbc3e659 81 if (pSCLK) {delete pSCLK; pSCLK = NULL;}
gatedClock 8:e2d8bbc3e659 82 if (pCPUclk) {delete pCPUclk; pCPUclk = NULL;}
gatedClock 32:5a5d9525c6c4 83 } // destructor.
gatedClock 3:de99451ab3c0 84 //----------------------------------------------//------------------------------
gatedClock 3:de99451ab3c0 85 void mmSPI::allocations(void) // object allocations.
gatedClock 3:de99451ab3c0 86 {
gatedClock 32:5a5d9525c6c4 87 pMOSI = new DigitalOut(mmSPI_MOSI); // SPI MOSI pin object.
gatedClock 3:de99451ab3c0 88 if (!pMOSI) error("\n\r mmSPI::allocations : FATAL malloc error for pMOSI. \n\r");
gatedClock 3:de99451ab3c0 89
gatedClock 32:5a5d9525c6c4 90 pMISO = new DigitalOut(mmSPI_MISO); // SPI MISO pin object.
gatedClock 3:de99451ab3c0 91 if (!pMISO) error("\n\r mmSPI::allocations : FATAL malloc error for pMISO. \n\r");
gatedClock 3:de99451ab3c0 92
gatedClock 32:5a5d9525c6c4 93 pSCLK = new DigitalOut(mmSPI_SCLK); // SPI SCLK pin object.
gatedClock 3:de99451ab3c0 94 if (!pSCLK) error("\n\r mmSPI::allocations : FATAL malloc error for pSCLK. \n\r");
gatedClock 8:e2d8bbc3e659 95
gatedClock 32:5a5d9525c6c4 96 pCPUclk = new DigitalOut(mmCPU_CLK); // SPI SCLK pin object.
gatedClock 8:e2d8bbc3e659 97 if (!pCPUclk) error("\n\r mmSPI::allocations : FATAL malloc error for pCPUclk. \n\r");
gatedClock 32:5a5d9525c6c4 98 } // allocations.
gatedClock 4:aa1fe8707bef 99 //----------------------------------------------//------------------------------
gatedClock 4:aa1fe8707bef 100 void mmSPI::setSPIfrequency(float fFreq) // set SPI clock frequency.
gatedClock 4:aa1fe8707bef 101 {
gatedClock 4:aa1fe8707bef 102 fSPIfreq = fFreq; // promote to object scope.
gatedClock 4:aa1fe8707bef 103 if (fSPIfreq < .05) // don't get near divide-by-zero.
gatedClock 4:aa1fe8707bef 104 error("\n\r mmSPI::setSPIfrequency : FATAL SPI frequency set too low. \n\r");
gatedClock 4:aa1fe8707bef 105 fSPIquarterP = (1 / fSPIfreq) / 4; // figure quarter-cycle period.
gatedClock 4:aa1fe8707bef 106 }
gatedClock 22:7524dee5c753 107 //----------------------------------------------//------------------------------
gatedClock 22:7524dee5c753 108 // obtain SPI send buffer pointer.
gatedClock 22:7524dee5c753 109 void mmSPI::setSendBuffer(char * pcSendBuffer)
gatedClock 22:7524dee5c753 110 {
gatedClock 22:7524dee5c753 111 pcSend = pcSendBuffer; // promote to object scope.
gatedClock 32:5a5d9525c6c4 112 } // setSendBuffer.
gatedClock 22:7524dee5c753 113 //----------------------------------------------//------------------------------
gatedClock 22:7524dee5c753 114 // obtain SPI receive buffer pointer.
gatedClock 22:7524dee5c753 115 void mmSPI::setReceiveBuffer(char * pcReceiveBuffer)
gatedClock 22:7524dee5c753 116 {
gatedClock 22:7524dee5c753 117 pcReceive = pcReceiveBuffer; // promote to object scope.
gatedClock 32:5a5d9525c6c4 118 } // setReceiveBuffer.
gatedClock 0:fb42c5acf810 119 //----------------------------------------------//------------------------------
gatedClock 22:7524dee5c753 120 // obtain number of SPI bytes.
gatedClock 22:7524dee5c753 121 void mmSPI::setNumberOfBytes(int dNumberOfBytes)
gatedClock 22:7524dee5c753 122 {
gatedClock 22:7524dee5c753 123 dNumBytes = dNumberOfBytes; // promote to object scope.
gatedClock 32:5a5d9525c6c4 124 } // setNumberOfBytes.
gatedClock 22:7524dee5c753 125 //----------------------------------------------//------------------------------
gatedClock 35:6152c9709697 126 /*
gatedClock 35:6152c9709697 127 this method has four 'components' which may be switched on/off by the caller:
gatedClock 35:6152c9709697 128 1. cPreCPU = 1 means cycle the altera CPU clock once.
gatedClock 35:6152c9709697 129 2. cPreSPI = 1 means cycle the SPI clock once.
gatedClock 35:6152c9709697 130 3. cScan = 1 means run a full SPI scan-in/scan-out cycle.
gatedClock 35:6152c9709697 131 4. cPostCPU = 1 means cycle the alter CPU clock once, then the SPI clock once.
gatedClock 35:6152c9709697 132
gatedClock 35:6152c9709697 133 in the altera, upon the falling edge of any CPU clock, a load-enable is
gatedClock 35:6152c9709697 134 asserted into the scan registers, such that at the next rising edge of
gatedClock 35:6152c9709697 135 the SPI clock, the scan registers perform a parallel-load of the CPU
gatedClock 35:6152c9709697 136 registers, so that that data can subsequently be scanned back into the mbed
gatedClock 35:6152c9709697 137 via a full SPI scan-in cycle. (this load-enable is turned-off upon the first
gatedClock 35:6152c9709697 138 falling edge of the subsequent SPI clock.)
gatedClock 35:6152c9709697 139 therefore, the regular input switches to this method are (1,1,1,0).
gatedClock 35:6152c9709697 140 this means that the altera CPU clock will cycle,
gatedClock 35:6152c9709697 141 and the result of that CPU operation will be parallel-loaded into the
gatedClock 35:6152c9709697 142 shadow registers for scan into the mbed on the subsequent full-scan cycle.
gatedClock 35:6152c9709697 143
gatedClock 35:6152c9709697 144 a finer level of sequencing these 'components' is needed by the 'step' method,
gatedClock 35:6152c9709697 145 which is why they are under four-input-parameter control.
gatedClock 35:6152c9709697 146 */
gatedClock 31:ea7b25e494b5 147 void mmSPI::transceive_vector(char cPreCPU, char cPreSPI, char cScan, char cPostCPU)
gatedClock 16:0e422fd263c6 148 {
gatedClock 35:6152c9709697 149 int dClear; // clear-loop index.
gatedClock 35:6152c9709697 150 int dIndex; // total scan index.
gatedClock 35:6152c9709697 151 int dMosiByteIndex; // SPI-MOSI byte index.
gatedClock 35:6152c9709697 152 int dMosiBitIndex; // SPI-MOSI bit index.
gatedClock 35:6152c9709697 153 int dMisoByteIndex; // SPI-MISO byte index.
gatedClock 35:6152c9709697 154 int dMisoBitIndex; // SPI-MISO bit index.
gatedClock 16:0e422fd263c6 155
gatedClock 35:6152c9709697 156 // initializations. these are needed.
gatedClock 35:6152c9709697 157 dIndex = (dNumBytes * 8) - 1; // calculate scan count.
gatedClock 35:6152c9709697 158 dMosiByteIndex = dIndex / 8; // calculate current byte index.
gatedClock 35:6152c9709697 159 dMosiBitIndex = dIndex % 8; // calculate current bit iindex.
gatedClock 16:0e422fd263c6 160
gatedClock 35:6152c9709697 161 // clear the SPI receive vector.
gatedClock 16:0e422fd263c6 162 for (dClear = 0; dClear < dNumBytes; dClear++) pcReceive[dClear] = 0;
gatedClock 35:6152c9709697 163 //---
gatedClock 31:ea7b25e494b5 164 if (cPreCPU) // if pre-CPU clock.
gatedClock 31:ea7b25e494b5 165 {
gatedClock 31:ea7b25e494b5 166 *pCPUclk = 1; // pulse the CPU clock.
gatedClock 31:ea7b25e494b5 167 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 168 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 169 *pCPUclk = 0;
gatedClock 31:ea7b25e494b5 170 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 171 wait(fSPIquarterP);
gatedClock 32:5a5d9525c6c4 172 ulCPUclkCount++;
gatedClock 31:ea7b25e494b5 173 } // if pre-CPU clock.
gatedClock 35:6152c9709697 174 //---
gatedClock 31:ea7b25e494b5 175 if (cPreSPI) // if pre-SPI pulse.
gatedClock 31:ea7b25e494b5 176 {
gatedClock 31:ea7b25e494b5 177 *pSCLK = 1; // pulse the SPI clock for parallel load.
gatedClock 31:ea7b25e494b5 178 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 179 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 180 *pSCLK = 0;
gatedClock 32:5a5d9525c6c4 181 ulSPIclkCount++;
gatedClock 31:ea7b25e494b5 182 } // if pre-SPI pulse.
gatedClock 35:6152c9709697 183 //---
gatedClock 31:ea7b25e494b5 184 if (cScan) // if cScan.
gatedClock 31:ea7b25e494b5 185 {
gatedClock 16:0e422fd263c6 186 // pre-assert MOSI.
gatedClock 31:ea7b25e494b5 187 *pMOSI = ((pcSend[dMosiByteIndex]) >> dMosiBitIndex) & 1;
gatedClock 31:ea7b25e494b5 188 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 189 wait(fSPIquarterP);
gatedClock 16:0e422fd263c6 190
gatedClock 16:0e422fd263c6 191
gatedClock 32:5a5d9525c6c4 192 // main SPI scan loop.
gatedClock 31:ea7b25e494b5 193 for (dIndex = (dNumBytes * 8) - 1; dIndex >= 0; dIndex--)
gatedClock 31:ea7b25e494b5 194 {
gatedClock 31:ea7b25e494b5 195 dMisoByteIndex = dIndex / 8;
gatedClock 31:ea7b25e494b5 196 dMisoBitIndex = dIndex % 8;
gatedClock 31:ea7b25e494b5 197 pcReceive[dMisoByteIndex] = pcReceive[dMisoByteIndex] | (*pMISO << dMisoBitIndex);
gatedClock 31:ea7b25e494b5 198 *pSCLK = 1;
gatedClock 31:ea7b25e494b5 199 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 200 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 201 *pSCLK = 0;
gatedClock 31:ea7b25e494b5 202 if (dIndex < 0) dIndex = 0;
gatedClock 31:ea7b25e494b5 203 dMosiByteIndex = (dIndex - 1) / 8;
gatedClock 31:ea7b25e494b5 204 dMosiBitIndex = (dIndex - 1) % 8;
gatedClock 31:ea7b25e494b5 205 *pMOSI = ((pcSend[dMosiByteIndex]) >> dMosiBitIndex) & 1;
gatedClock 31:ea7b25e494b5 206 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 207 wait(fSPIquarterP);
gatedClock 32:5a5d9525c6c4 208 ulSPIclkCount++;
gatedClock 32:5a5d9525c6c4 209 } // main SPI scan loop.
gatedClock 31:ea7b25e494b5 210 } // if cScan.
gatedClock 35:6152c9709697 211 //---
gatedClock 31:ea7b25e494b5 212 if (cPostCPU) // if post-CPU pulse.
gatedClock 16:0e422fd263c6 213 {
gatedClock 31:ea7b25e494b5 214 *pCPUclk = 1; // pulse the CPU clock.
gatedClock 31:ea7b25e494b5 215 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 216 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 217 *pCPUclk = 0;
gatedClock 31:ea7b25e494b5 218 wait(fSPIquarterP);
gatedClock 32:5a5d9525c6c4 219 wait(fSPIquarterP);
gatedClock 32:5a5d9525c6c4 220 ulCPUclkCount++;
gatedClock 31:ea7b25e494b5 221
gatedClock 31:ea7b25e494b5 222 *pSCLK = 1; // clear-out the SPI parallel-load enable.
gatedClock 16:0e422fd263c6 223 wait(fSPIquarterP);
gatedClock 16:0e422fd263c6 224 wait(fSPIquarterP);
gatedClock 31:ea7b25e494b5 225 *pSCLK = 0;
gatedClock 32:5a5d9525c6c4 226 ulSPIclkCount++;
gatedClock 31:ea7b25e494b5 227 } // if post-CPU pulse.
gatedClock 32:5a5d9525c6c4 228 } // transceive_vector.
gatedClock 7:b3e8b537d5c2 229 //----------------------------------------------//------------------------------
gatedClock 35:6152c9709697 230 /*
gatedClock 35:6152c9709697 231 cRegister -> CPU_register
gatedClock 35:6152c9709697 232 0 R0
gatedClock 35:6152c9709697 233 1 R1
gatedClock 35:6152c9709697 234 2 R2
gatedClock 35:6152c9709697 235 3 R3
gatedClock 35:6152c9709697 236 4 PC
gatedClock 35:6152c9709697 237 5 <use write_IR instead>
gatedClock 35:6152c9709697 238 6 <nothing>
gatedClock 35:6152c9709697 239 7 <nothing>
gatedClock 35:6152c9709697 240
gatedClock 35:6152c9709697 241 in order to write to a CPU register, pcSend[7] is set to 0x02,
gatedClock 35:6152c9709697 242 which informs the CPU instruction decoder to decode what we are
gatedClock 35:6152c9709697 243 here scanning into the shadow instruction-register, rather than
gatedClock 35:6152c9709697 244 the CPU instruction decoder decoding the regular instruction-register.
gatedClock 35:6152c9709697 245 here, we set-up pcSend to scan the instruction
gatedClock 35:6152c9709697 246 'load Rx with immediate data yy', and this is executed on the
gatedClock 35:6152c9709697 247 subsequent CPU clock.
gatedClock 35:6152c9709697 248
gatedClock 35:6152c9709697 249 said another way, this method writes a value into a CPU register
gatedClock 35:6152c9709697 250 by effectively taking over the CPU and doing a write-register-immediate.
gatedClock 35:6152c9709697 251 */
gatedClock 26:26a8f31a31b8 252
gatedClock 35:6152c9709697 253 // write to a CPU register.
gatedClock 23:dbd89a56716d 254 void mmSPI::write_register(char cRegister, char cValue)
gatedClock 16:0e422fd263c6 255 {
gatedClock 24:d3b8c68f41f2 256 clear_transmit_vector(); // clear transmit vector.
gatedClock 18:4a29cad91540 257
gatedClock 18:4a29cad91540 258 pcSend[7] = 0x02; // mbed sends a command.
gatedClock 18:4a29cad91540 259
gatedClock 18:4a29cad91540 260 // align into instruction word.
gatedClock 16:0e422fd263c6 261 pcSend[1] = ((cRegister & 0x07) << 2) | 0xA0;
gatedClock 18:4a29cad91540 262 pcSend[0] = cValue & 0xFF; // immediate value to i.w.
gatedClock 17:b81c0c1f312f 263
gatedClock 31:ea7b25e494b5 264 transceive_vector(1,1,1,0); // transmit command.
gatedClock 18:4a29cad91540 265
gatedClock 24:d3b8c68f41f2 266 clear_transmit_vector(); // clear transmit vector.
gatedClock 32:5a5d9525c6c4 267 } // write_register.
gatedClock 35:6152c9709697 268 //----------------------------------------------//------------------------------
gatedClock 35:6152c9709697 269 /*
gatedClock 35:6152c9709697 270 for writing to the instruction-register, this method is used.
gatedClock 35:6152c9709697 271 for reading from the instruction-register, the 'regular'
gatedClock 35:6152c9709697 272 read_register method is used, once for each of the two IR data bytes.
gatedClock 35:6152c9709697 273
gatedClock 35:6152c9709697 274 unlike method 'write_register', this method works by gating-off the
gatedClock 35:6152c9709697 275 outputs of the CPU instruction decoder, and having the instruction-register
gatedClock 35:6152c9709697 276 content loaded in from the shadow instruction-register.
gatedClock 35:6152c9709697 277 */
gatedClock 34:d5553509f31a 278 // write instruction register.
gatedClock 34:d5553509f31a 279 void mmSPI::write_IR(char cValueH, char cValueL)
gatedClock 34:d5553509f31a 280 {
gatedClock 34:d5553509f31a 281 clear_transmit_vector(); // clear transmit vector.
gatedClock 34:d5553509f31a 282
gatedClock 34:d5553509f31a 283 pcSend[7] = 0x06; // mbed sends a command.
gatedClock 34:d5553509f31a 284
gatedClock 34:d5553509f31a 285 pcSend[1] = (cValueH & 0xFF); // load IR shadow with new IR content.
gatedClock 34:d5553509f31a 286 pcSend[0] = (cValueL & 0xFF);
gatedClock 34:d5553509f31a 287
gatedClock 34:d5553509f31a 288 transceive_vector(1,1,1,0); // transmit command.
gatedClock 34:d5553509f31a 289
gatedClock 34:d5553509f31a 290 clear_transmit_vector(); // clear transmit vector.
gatedClock 34:d5553509f31a 291 } // write instruction register.
gatedClock 17:b81c0c1f312f 292 //----------------------------------------------//------------------------------
gatedClock 35:6152c9709697 293 /*
gatedClock 35:6152c9709697 294 cRegister -> CPU_register pcReceive
gatedClock 35:6152c9709697 295 0 -> R0 [6]
gatedClock 35:6152c9709697 296 1 -> R1 [5]
gatedClock 35:6152c9709697 297 2 -> R2 [4]
gatedClock 35:6152c9709697 298 3 -> R3 [3]
gatedClock 35:6152c9709697 299 4 -> PC [2]
gatedClock 35:6152c9709697 300 5 -> IR-H [1]
gatedClock 35:6152c9709697 301 6 -> IR-L [0]
gatedClock 35:6152c9709697 302 7 -> <never-use>
gatedClock 35:6152c9709697 303
gatedClock 35:6152c9709697 304 this method works by taking over the instruction decoder as described above,
gatedClock 35:6152c9709697 305 but not issuing any instruction, but the scan registers will parallel-load
gatedClock 35:6152c9709697 306 all of the CPU register data and scan them into pcReceive, where they are
gatedClock 35:6152c9709697 307 picked up below.
gatedClock 35:6152c9709697 308 */
gatedClock 35:6152c9709697 309
gatedClock 35:6152c9709697 310 char mmSPI::read_register(char cRegister) // return content of a CPU register.
gatedClock 17:b81c0c1f312f 311 {
gatedClock 24:d3b8c68f41f2 312 clear_transmit_vector(); // clear transmit vector.
gatedClock 29:4ed71dfee7d8 313
gatedClock 29:4ed71dfee7d8 314 pcSend[7] = 0x02; // suppress cpu operation.
gatedClock 29:4ed71dfee7d8 315
gatedClock 31:ea7b25e494b5 316 transceive_vector(1,1,1,0); // snap & scan-out reg contents.
gatedClock 17:b81c0c1f312f 317
gatedClock 19:c2b753533b93 318 return (pcReceive[6 - cRegister]); // return the particular reg value.
gatedClock 32:5a5d9525c6c4 319 } // read_register.
gatedClock 17:b81c0c1f312f 320 //----------------------------------------------//------------------------------
gatedClock 36:32cdc295f859 321 //----------------------------------------------//------------------------------
gatedClock 36:32cdc295f859 322 /*
gatedClock 36:32cdc295f859 323 since the Tk UI often wants to obtain the content of all of the CPU registers,
gatedClock 36:32cdc295f859 324 this method may be used to obtain all of them at once, speading up the UI
gatedClock 36:32cdc295f859 325 read cycle.
gatedClock 36:32cdc295f859 326
gatedClock 36:32cdc295f859 327 pRegisters[6] <- pcReceive[6] = R0
gatedClock 36:32cdc295f859 328 pRegisters[5] <- pcReceive[5] = R1
gatedClock 36:32cdc295f859 329 pRegisters[4] <- pcReceive[4] = R2
gatedClock 36:32cdc295f859 330 pRegisters[3] <- pcReceive[3] = R3
gatedClock 36:32cdc295f859 331 pRegisters[2] <- pcReceive[2] = PC
gatedClock 36:32cdc295f859 332 pRegisters[1] <- pcReceive[1] = IR-H
gatedClock 36:32cdc295f859 333 pRegisters[0] <- pcReceive[0] = IR-L
gatedClock 36:32cdc295f859 334 */
gatedClock 36:32cdc295f859 335
gatedClock 36:32cdc295f859 336 void mmSPI::read_all_registers(char * pcRegisters)
gatedClock 36:32cdc295f859 337 {
gatedClock 36:32cdc295f859 338 int dLoop; // loop index.
gatedClock 36:32cdc295f859 339
gatedClock 36:32cdc295f859 340 clear_transmit_vector(); // clear transmit vector.
gatedClock 36:32cdc295f859 341
gatedClock 36:32cdc295f859 342 pcSend[7] = 0x02; // suppress cpu operation.
gatedClock 36:32cdc295f859 343
gatedClock 36:32cdc295f859 344 transceive_vector(1,1,1,0); // snap & scan-out reg contents.
gatedClock 36:32cdc295f859 345
gatedClock 36:32cdc295f859 346 // propagate register data.
gatedClock 36:32cdc295f859 347 for (dLoop = 0; dLoop < 7; dLoop++) pcRegisters[dLoop] = pcReceive[dLoop];
gatedClock 36:32cdc295f859 348
gatedClock 36:32cdc295f859 349 } // read_all_registers.
gatedClock 36:32cdc295f859 350 //----------------------------------------------//------------------------------
gatedClock 35:6152c9709697 351 /*
gatedClock 35:6152c9709697 352 this method works by taking over the instruction decoder, and issuing
gatedClock 35:6152c9709697 353 the CPU commands which load the MM address/data into {R3,R2,R1}
gatedClock 35:6152c9709697 354 followed by issuing a write-pulse.
gatedClock 35:6152c9709697 355 */
gatedClock 35:6152c9709697 356 // write a word to main-memory.
gatedClock 23:dbd89a56716d 357 void mmSPI::write_memory(char cHData, char cLdata, char cAddress)
gatedClock 18:4a29cad91540 358 {
gatedClock 24:d3b8c68f41f2 359 clear_transmit_vector(); // clear transmit vector.
gatedClock 24:d3b8c68f41f2 360
gatedClock 24:d3b8c68f41f2 361 write_register(0x03,cAddress); // R3 <- address.
gatedClock 24:d3b8c68f41f2 362 write_register(0x02,cHData); // R2 <- high-data.
gatedClock 24:d3b8c68f41f2 363 write_register(0x01,cLdata); // R1 <- low-data.
gatedClock 18:4a29cad91540 364
gatedClock 27:fb63c8b70bc2 365 pcSend[7] = 0x02; // mbed sends command.
gatedClock 27:fb63c8b70bc2 366 pcSend[1] = 0x02; // write-enable high.
gatedClock 27:fb63c8b70bc2 367 pcSend[0] = 0x00; // remainder of instruction.
gatedClock 31:ea7b25e494b5 368 transceive_vector(1,1,1,0);
gatedClock 18:4a29cad91540 369
gatedClock 27:fb63c8b70bc2 370 pcSend[7] = 0x02; // mbed sends command.
gatedClock 27:fb63c8b70bc2 371 pcSend[1] = 0x00; // write-enable low.
gatedClock 27:fb63c8b70bc2 372 pcSend[0] = 0x00; // remainder of instruction.
gatedClock 31:ea7b25e494b5 373 transceive_vector(1,1,1,0);
gatedClock 24:d3b8c68f41f2 374
gatedClock 24:d3b8c68f41f2 375 clear_transmit_vector(); // clear transmit vector.
gatedClock 32:5a5d9525c6c4 376 } // write_memory.
gatedClock 18:4a29cad91540 377 //----------------------------------------------//------------------------------
gatedClock 35:6152c9709697 378 /*
gatedClock 35:6152c9709697 379 this command works by taking over the instruction decoder, loading
gatedClock 35:6152c9709697 380 R3 with the MM address, then issuing load-from-MM commands so that
gatedClock 35:6152c9709697 381 R2,R1 are loaded with MM[R3], and then reading the result from
gatedClock 35:6152c9709697 382 R1,R2.
gatedClock 35:6152c9709697 383 */
gatedClock 18:4a29cad91540 384 // fetch a word from main memory.
gatedClock 23:dbd89a56716d 385 unsigned int mmSPI::read_memory(char cAddress)
gatedClock 24:d3b8c68f41f2 386 {
gatedClock 18:4a29cad91540 387 unsigned int udMemoryContent; // return variable.
gatedClock 18:4a29cad91540 388 char cHData; // returned data-high.
gatedClock 18:4a29cad91540 389 char cLData; // returned data-low.
gatedClock 24:d3b8c68f41f2 390
gatedClock 24:d3b8c68f41f2 391 clear_transmit_vector(); // clear transmit vector.
gatedClock 21:e90dd0f8aaa1 392
gatedClock 24:d3b8c68f41f2 393 write_register(0x03,cAddress); // R3 <= address.
gatedClock 18:4a29cad91540 394
gatedClock 18:4a29cad91540 395 pcSend[7] = 0x02; // mbed sends command.
gatedClock 20:2d5cd38047ca 396 pcSend[1] = 0xC8; // R2 <- MM[R3]
gatedClock 18:4a29cad91540 397 pcSend[0] = 0x00;
gatedClock 31:ea7b25e494b5 398 transceive_vector(1,1,1,0); // send command.
gatedClock 18:4a29cad91540 399
gatedClock 18:4a29cad91540 400 pcSend[7] = 0x02; // mbed sends command.
gatedClock 20:2d5cd38047ca 401 pcSend[1] = 0xC4; // R1 <- MM[R3]
gatedClock 18:4a29cad91540 402 pcSend[0] = 0x00;
gatedClock 31:ea7b25e494b5 403 transceive_vector(1,1,1,0); // send command.
gatedClock 18:4a29cad91540 404
gatedClock 24:d3b8c68f41f2 405 cHData = read_register(0x02); // obtain MM high-data-byte.
gatedClock 24:d3b8c68f41f2 406 cLData = read_register(0x01); // obtain MM low-data-byte.
gatedClock 31:ea7b25e494b5 407
gatedClock 18:4a29cad91540 408 udMemoryContent = (cHData << 8) + cLData; // build the memory word.
gatedClock 24:d3b8c68f41f2 409
gatedClock 24:d3b8c68f41f2 410 clear_transmit_vector(); // clear transmit vector.
gatedClock 18:4a29cad91540 411
gatedClock 18:4a29cad91540 412 return udMemoryContent; // return the memory word.
gatedClock 32:5a5d9525c6c4 413 } // read_memory.
gatedClock 18:4a29cad91540 414 //----------------------------------------------//------------------------------
gatedClock 30:331c7c7d8bc1 415 void mmSPI::step(void) // step the CPU.
gatedClock 30:331c7c7d8bc1 416 {
gatedClock 31:ea7b25e494b5 417 clear_transmit_vector(); // clear transmit vector.
gatedClock 31:ea7b25e494b5 418 transceive_vector(0,0,1,0); // enable CPU mode.
gatedClock 31:ea7b25e494b5 419 transceive_vector(0,0,0,1); // advance CPU, clear shadow-load.
gatedClock 31:ea7b25e494b5 420 pcSend[7] = 0x02; // ready to disable CPU mode.
gatedClock 31:ea7b25e494b5 421 transceive_vector(0,0,1,0); // disable CPU mode.
gatedClock 32:5a5d9525c6c4 422 } // step.
gatedClock 30:331c7c7d8bc1 423 //----------------------------------------------//------------------------------
gatedClock 24:d3b8c68f41f2 424 void mmSPI::clear_transmit_vector(void) // fill transmit buffer with 0.
gatedClock 24:d3b8c68f41f2 425 {
gatedClock 24:d3b8c68f41f2 426 int dLoop;
gatedClock 24:d3b8c68f41f2 427 for (dLoop = 0; dLoop < dNumBytes; dLoop++) pcSend[dLoop] = 0x00;
gatedClock 32:5a5d9525c6c4 428 } // clear_transmit_vector.
gatedClock 32:5a5d9525c6c4 429 //----------------------------------------------//------------------------------
gatedClock 32:5a5d9525c6c4 430 // getters.
gatedClock 32:5a5d9525c6c4 431 unsigned long mmSPI::SPIClockCount() {return ulSPIclkCount;}
gatedClock 32:5a5d9525c6c4 432 unsigned long mmSPI::CPUClockCount() {return ulCPUclkCount;}
gatedClock 24:d3b8c68f41f2 433 //----------------------------------------------//------------------------------
gatedClock 17:b81c0c1f312f 434
gatedClock 17:b81c0c1f312f 435
gatedClock 5:b14dcaae260e 436
gatedClock 5:b14dcaae260e 437
gatedClock 5:b14dcaae260e 438
gatedClock 5:b14dcaae260e 439
gatedClock 5:b14dcaae260e 440
gatedClock 5:b14dcaae260e 441