Mike Moore / mmSPI_RTOS

Dependents:   RTOS_project RTOS_project_fork_01 RTOS_project_fork_02

Committer:
gatedClock
Date:
Tue Sep 17 20:40:03 2013 +0000
Revision:
0:7b8e6b90c874
update.

Who changed what in which revision?

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