USB Device Programming class project. This project allows a Python/Tk program running on a PC host to monitor/control a test-CPU programmed into an altera development board.

Dependencies:   C12832_lcd USBDevice mbed-rtos mbed mmSPI

Committer:
gatedClock
Date:
Sun Sep 01 02:29:14 2013 +0000
Revision:
2:08655e2bb776
Parent:
0:9a314675a67d
Child:
9:81726c95be74
add project code.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gatedClock 2:08655e2bb776 1 /*----------------------------------------------//------------------------------
gatedClock 2:08655e2bb776 2 student : m-moore
gatedClock 2:08655e2bb776 3 email : gated.clock@gmail.com
gatedClock 2:08655e2bb776 4 class : usb device drivers
gatedClock 2:08655e2bb776 5 directory : USB_device_project
gatedClock 2:08655e2bb776 6 file : main.cpp
gatedClock 2:08655e2bb776 7 date : september 3, 2013.
gatedClock 2:08655e2bb776 8 ----copyright-----------------------------------//------------------------------
gatedClock 2:08655e2bb776 9 licensed for personal and academic use.
gatedClock 2:08655e2bb776 10 commercial use must be approved by the account-holder of
gatedClock 2:08655e2bb776 11 gated.clock@gmail.com
gatedClock 2:08655e2bb776 12 ----description---------------------------------//------------------------------
gatedClock 2:08655e2bb776 13 overview:
gatedClock 2:08655e2bb776 14 program to provide round-trip communication between a python test-control
gatedClock 2:08655e2bb776 15 program running on a pc host, and a device-under-test CPU implemented on
gatedClock 2:08655e2bb776 16 an altera board. the pc-host communication is over USBSerial, and the
gatedClock 2:08655e2bb776 17 altera communication is over SPI.
gatedClock 2:08655e2bb776 18
gatedClock 2:08655e2bb776 19 features:
gatedClock 2:08655e2bb776 20 1. multi-threaded design, use of memory-pools to transfer data between threads.
gatedClock 2:08655e2bb776 21 2. use of USBDevice library for communication with PC host.
gatedClock 2:08655e2bb776 22 3. use of mmSPI custom library for communication with FPGA.
gatedClock 2:08655e2bb776 23 4. main thread provides USBSerial communication to/from host.
gatedClock 2:08655e2bb776 24 5. SPI processing thread provides SPI communication to/from DUT.
gatedClock 2:08655e2bb776 25 6. mmSPI library generates non-overlapping SPI and CPU clocks.
gatedClock 2:08655e2bb776 26 7. background diagnostic thread provides LCD & LED updates.
gatedClock 0:9a314675a67d 27
gatedClock 2:08655e2bb776 28 indicators: (led<3:0> = LED<1:4>)
gatedClock 2:08655e2bb776 29 1. LCD provides running counts for SPI and CPU clock cycles.
gatedClock 2:08655e2bb776 30 2. led0 indicates main thread processing.
gatedClock 2:08655e2bb776 31 3. led1 indicates SPI thread processing.
gatedClock 2:08655e2bb776 32 4. led2 indicates LCD thread processing.
gatedClock 2:08655e2bb776 33 5. led3 indicates reply-to-host underflow (should never turn on).
gatedClock 2:08655e2bb776 34
gatedClock 2:08655e2bb776 35 implementation:
gatedClock 2:08655e2bb776 36 1. main.processIncomingSerial(): accept incoming serial data from host,
gatedClock 2:08655e2bb776 37 and map it into tFromHost structures.
gatedClock 2:08655e2bb776 38 2. SPIprocessingThread: take the incoming data structures instances, and
gatedClock 2:08655e2bb776 39 feed their content into mmSPI commands.
gatedClock 2:08655e2bb776 40 3. mmSPI object: given commands/data passed from caller,
gatedClock 2:08655e2bb776 41 map them into SPI outgoing vectors and scan them into the FPGA.
gatedClock 2:08655e2bb776 42 4. mmSPI object: receive incoming SPI vectors from FPGA.
gatedClock 2:08655e2bb776 43 make FPGA payload data available to caller.
gatedClock 2:08655e2bb776 44 5. SPIprocessingThread: load tToHost structures with said FPGA payload data.
gatedClock 2:08655e2bb776 45 6. main.processOutgoingSerial(): transfer tToHost structure data into a
gatedClock 2:08655e2bb776 46 serial outgoing buffer, and block-transfer it to the host PC.
gatedClock 2:08655e2bb776 47
gatedClock 2:08655e2bb776 48 electrical:
gatedClock 2:08655e2bb776 49 1. four pins (and ground) attached to the zigbee header,
gatedClock 2:08655e2bb776 50 programmed as three SPI pins and the CPU clock.
gatedClock 2:08655e2bb776 51 2. each of the four signals over twisted-pair.
gatedClock 2:08655e2bb776 52 3. but some ribbon cable is used at the FPGA end.
gatedClock 2:08655e2bb776 53 4. best if only the mbed application board USB cable is attached
gatedClock 2:08655e2bb776 54 to the host; if the mbed CPU board USB cable is also attached to
gatedClock 2:08655e2bb776 55 the host, then the python program may attempt to use the wrong USB
gatedClock 2:08655e2bb776 56 connection.
gatedClock 2:08655e2bb776 57 5. no particular power sequence is needed for this system to work.
gatedClock 2:08655e2bb776 58
gatedClock 2:08655e2bb776 59
gatedClock 2:08655e2bb776 60 testing:
gatedClock 2:08655e2bb776 61 the python UI provides the main testing mechanism.
gatedClock 2:08655e2bb776 62
gatedClock 2:08655e2bb776 63 USB connect.
gatedClock 2:08655e2bb776 64 00. press 'CONNECT' button in UI. verify connection info in shell.
gatedClock 2:08655e2bb776 65
gatedClock 2:08655e2bb776 66 CPU register w/r
gatedClock 2:08655e2bb776 67 01. type values into {R0,R1,R2,R3,PC,IR} UI entry-forms.
gatedClock 2:08655e2bb776 68 02. press 'REG WRITE' UI button.
gatedClock 2:08655e2bb776 69 03. press 'REG READ' UI button.
gatedClock 2:08655e2bb776 70 04. verify that the read data is correct.
gatedClock 2:08655e2bb776 71
gatedClock 2:08655e2bb776 72 CPU main-memory w/r
gatedClock 2:08655e2bb776 73 05. type an address into 'mmADR' UI entry-form.
gatedClock 2:08655e2bb776 74 06. type data into 'mmVAL' UI entry-form.
gatedClock 2:08655e2bb776 75 07. press 'MM WRITE' UI button.
gatedClock 2:08655e2bb776 76 08. type a different address into 'mmADR' UI entry-form.
gatedClock 2:08655e2bb776 77 09. type different data into 'mmVAL' UI entry-form.
gatedClock 2:08655e2bb776 78 10. press 'MM WRITE' UI button.
gatedClock 2:08655e2bb776 79 11. type address from (05) into 'mmADR' UI entry-form.
gatedClock 2:08655e2bb776 80 12. press 'MM READ' UI button.
gatedClock 2:08655e2bb776 81 13. verify that the data from (06) is seen in the 'mmVAL' entry form.
gatedClock 2:08655e2bb776 82 14. type address from (08) into 'mmADR' UI entry-form.
gatedClock 2:08655e2bb776 83 15. press 'MM READ' UI button.
gatedClock 2:08655e2bb776 84 16. verify that the data from (09) is seen in the 'mmVAL' entry form.
gatedClock 2:08655e2bb776 85
gatedClock 2:08655e2bb776 86 CPU main-memory full load/dump.
gatedClock 2:08655e2bb776 87 17. press 'PROGRAM' in the UI. select a program file in the dialog-popup.
gatedClock 2:08655e2bb776 88 18. watch the load process in the shell text.
gatedClock 2:08655e2bb776 89 19. press 'DUMP in the UI. select a main-memory dump file in the diaglog-popup.
gatedClock 2:08655e2bb776 90 20. watch the dump process in the shell text.
gatedClock 2:08655e2bb776 91
gatedClock 2:08655e2bb776 92 CPU step function.
gatedClock 2:08655e2bb776 93 21. press 'STEP' in the UI repeatedly, watch the UI display the
gatedClock 2:08655e2bb776 94 CPU register states as the current program is executed one CPU clock
gatedClock 2:08655e2bb776 95 at a time.
gatedClock 2:08655e2bb776 96
gatedClock 2:08655e2bb776 97 CPU run function.
gatedClock 2:08655e2bb776 98 22. press 'RUN' in the UI. watch the current program run at high speed.
gatedClock 2:08655e2bb776 99 23. press 'SLOW' in the UI. watch the current program run at slow speed.
gatedClock 2:08655e2bb776 100 24. press 'STOP' in the UI. the program will stop execution.
gatedClock 2:08655e2bb776 101
gatedClock 2:08655e2bb776 102 CPU test function.
gatedClock 2:08655e2bb776 103 25. press 'TEST' in the UI. the program will load,execute,dump,compare.
gatedClock 2:08655e2bb776 104 26. tail -f testlog.txt to see test status.
gatedClock 2:08655e2bb776 105 27. the test will repeat until 'STOP TEST' is pressed.
gatedClock 2:08655e2bb776 106 28. long test performed by allowing this mode to continue.
gatedClock 2:08655e2bb776 107
gatedClock 2:08655e2bb776 108 UI exit function.
gatedClock 2:08655e2bb776 109 29. press 'EXIT' in the UI. it will exit.
gatedClock 2:08655e2bb776 110 -----includes-----------------------------------//----------------------------*/
gatedClock 2:08655e2bb776 111 #include "mbed.h" // general.
gatedClock 2:08655e2bb776 112 #include "USBSerial.h" // serial over USB.
gatedClock 2:08655e2bb776 113 #include "C12832_lcd.h" // LCD display.
gatedClock 2:08655e2bb776 114 #include "rtos.h" // RTOS.
gatedClock 2:08655e2bb776 115 #include "mmSPI.h" // SPI.
gatedClock 2:08655e2bb776 116 //---defines------------------------------------//------------------------------
gatedClock 2:08655e2bb776 117 #define LCD1 lcd.locate(0, 0); // LCD line 1.
gatedClock 2:08655e2bb776 118 #define LCD2 lcd.locate(0,11); // LCD line 2.
gatedClock 2:08655e2bb776 119 #define LCD3 lcd.locate(0,22); // LCD line 3.
gatedClock 2:08655e2bb776 120 #define LCD3 lcd.locate(0,22); // LCD line 3.
gatedClock 2:08655e2bb776 121 #define SPI_BYTES 8 // number of SPI bytes.
gatedClock 2:08655e2bb776 122 #define SPI_HZ 100000 // SPI frequency in Hz.
gatedClock 2:08655e2bb776 123 #define SER_BYTES 8 // serial in/out # of bytes.
gatedClock 2:08655e2bb776 124 #define SER_ALIGN 7 // '$' location in shift-register.
gatedClock 2:08655e2bb776 125 #define THREAD_0_WAIT 8 // multitasking wait mS.
gatedClock 2:08655e2bb776 126 #define THREAD_1_WAIT 2 // multitasking wait mS.
gatedClock 2:08655e2bb776 127 #define THREAD_2_WAIT 128 // multitasking wait mS.
gatedClock 2:08655e2bb776 128 #define HB_MODULO 64 // heartbeat slowdown factor.
gatedClock 2:08655e2bb776 129 #define POOL_LEN 16 // memory pool dimension.
gatedClock 2:08655e2bb776 130 #define HCMD_SETREG 1 // host command 'set register'.
gatedClock 2:08655e2bb776 131 #define HCMD_GETREG 2 // host command 'get register'.
gatedClock 2:08655e2bb776 132 #define HCMD_SETMM 3 // host command 'set main-memory.'
gatedClock 2:08655e2bb776 133 #define HCMD_GETMM 4 // host command 'get main-memory.'
gatedClock 2:08655e2bb776 134 #define HCMD_STEP 5 // host command 'step-CPU'.
gatedClock 2:08655e2bb776 135 #define HCMD_SETIR 6 // host command 'set-IR'.
gatedClock 2:08655e2bb776 136 #define CPU_REG_0 0 // CPU register 0.
gatedClock 2:08655e2bb776 137 #define CPU_REG_1 1 // CPU register 1.
gatedClock 2:08655e2bb776 138 #define CPU_REG_2 2 // CPU register 2.
gatedClock 2:08655e2bb776 139 #define CPU_REG_3 3 // CPU register 3.
gatedClock 2:08655e2bb776 140 #define CPU_REG_PC 4 // CPU Program Counter.
gatedClock 2:08655e2bb776 141 #define CPU_IR_H 5 // CPU IR high-byte.
gatedClock 2:08655e2bb776 142 #define CPU_IR_L 6 // CPU IR low-byte.
gatedClock 2:08655e2bb776 143 //--global_definitions--------------------------//------------------------------
gatedClock 2:08655e2bb776 144 struct tFromHost // command from host.
gatedClock 2:08655e2bb776 145 {
gatedClock 2:08655e2bb776 146 char cCommand; // command from host.
gatedClock 2:08655e2bb776 147 char cRegisterID; // which CPU register.
gatedClock 2:08655e2bb776 148 char cRegisterValue; // write this to CPU register.
gatedClock 2:08655e2bb776 149 char cIRValueH; // write this to IR.
gatedClock 2:08655e2bb776 150 char cIRValueL; // write this to IR.
gatedClock 2:08655e2bb776 151 char cMMaddress; // access this MM address.
gatedClock 2:08655e2bb776 152 char cMMdataH; // MM content high byte.
gatedClock 2:08655e2bb776 153 char cMMdataL; // MM content low byte.
gatedClock 2:08655e2bb776 154 };
gatedClock 2:08655e2bb776 155 MemoryPool<tFromHost, POOL_LEN> mPoolFromHost;
gatedClock 2:08655e2bb776 156 Queue <tFromHost, POOL_LEN> qFromHost;
gatedClock 2:08655e2bb776 157
gatedClock 2:08655e2bb776 158 //----
gatedClock 2:08655e2bb776 159
gatedClock 2:08655e2bb776 160 struct tToHost // reply to host.
gatedClock 2:08655e2bb776 161 {
gatedClock 2:08655e2bb776 162 char cCommand; // command executed.
gatedClock 2:08655e2bb776 163 char cRegisterID; // which CPU register read.
gatedClock 2:08655e2bb776 164 char cRegisterValue; // data from CPU register.
gatedClock 2:08655e2bb776 165 char cMMaddress; // which MM address read.
gatedClock 2:08655e2bb776 166 char cMMdataH; // MM content high byte.
gatedClock 2:08655e2bb776 167 char cMMdataL; // MM content low byte.
gatedClock 2:08655e2bb776 168 };
gatedClock 2:08655e2bb776 169 MemoryPool<tToHost, POOL_LEN> mPoolToHost;
gatedClock 2:08655e2bb776 170 Queue <tToHost, POOL_LEN> qToHost;
gatedClock 2:08655e2bb776 171 //--global_variables----------------------------//------------------------------
gatedClock 2:08655e2bb776 172 char gpcSerialFromHost[SER_BYTES]; // incoming serial buffer.
gatedClock 2:08655e2bb776 173 char gpcSerialToHost [SER_BYTES]; // outgoing serial buffer.
gatedClock 2:08655e2bb776 174 char gcNewCommand; // new command from host.
gatedClock 2:08655e2bb776 175 int gdRoundTrip; // +1 from host, -1 to host.
gatedClock 2:08655e2bb776 176 tToHost * gpToHost; // to-host structure.
gatedClock 2:08655e2bb776 177 osEvent gqToHostEvent; // incoming message event.
gatedClock 2:08655e2bb776 178 unsigned long gulSPIclkCount; // SPI clock count.
gatedClock 2:08655e2bb776 179 unsigned long gulCPUclkCount; // CPU clock count.
gatedClock 2:08655e2bb776 180 //--global_instances----------------------------//------------------------------
gatedClock 2:08655e2bb776 181 USBSerial serial; // serial over usb.
gatedClock 2:08655e2bb776 182 C12832_LCD lcd; // LCD display.
gatedClock 2:08655e2bb776 183 DigitalOut led0(LED4); // thread heartbeat.
gatedClock 2:08655e2bb776 184 DigitalOut led1(LED3); // thread heartbeat.
gatedClock 2:08655e2bb776 185 DigitalOut led2(LED2); // thread heartbeat.
gatedClock 2:08655e2bb776 186 DigitalOut led3(LED1); // SPI reply underflow warning.
gatedClock 2:08655e2bb776 187 //-------prototypes-----------------------------//------------------------------
gatedClock 2:08655e2bb776 188 int main(); // main.
gatedClock 2:08655e2bb776 189 void processIncomingSerial(); // process incoming host data.
gatedClock 2:08655e2bb776 190 void processOutgoingSerial(); // process outgoing data to host.
gatedClock 2:08655e2bb776 191 void SPIprocessingThread(void const *args); // SPI-side processing.
gatedClock 2:08655e2bb776 192 void diagnosticThread (void const *args); // LCD and LED notifications.
gatedClock 2:08655e2bb776 193 char ascii_nibble_to_binary(char cAscii); // ascii nibble -> binary.
gatedClock 2:08655e2bb776 194 char binary_to_ascii_nibble(char cBinary); // binary -> ascii nibble.
gatedClock 2:08655e2bb776 195 void clear_tFromHost(tFromHost *ptFromHost);// initialize structure.
gatedClock 2:08655e2bb776 196 void clear_tToHost (tToHost *ptToHost); // initialize structure.
gatedClock 2:08655e2bb776 197 //==============================================//==============================
gatedClock 2:08655e2bb776 198 int main(void) // USBSerial processing thread.
gatedClock 2:08655e2bb776 199 {
gatedClock 2:08655e2bb776 200 int dHeartbeat; // heartbeat counter.
gatedClock 2:08655e2bb776 201 int dLoop; // loop index.
gatedClock 2:08655e2bb776 202
gatedClock 2:08655e2bb776 203 gpToHost = NULL; // initialize global.
gatedClock 2:08655e2bb776 204 gcNewCommand = 0; // initialize global.
gatedClock 2:08655e2bb776 205 gdRoundTrip = 1024; // initialize global.
gatedClock 2:08655e2bb776 206 gulSPIclkCount = 0; // initialize global.
gatedClock 2:08655e2bb776 207 gulCPUclkCount = 0; // initialize global.
gatedClock 2:08655e2bb776 208 dHeartbeat = 0; // initialize local.
gatedClock 2:08655e2bb776 209 dLoop = 0; // initialize local.
gatedClock 2:08655e2bb776 210
gatedClock 2:08655e2bb776 211 // initialize serial-in shift-register.
gatedClock 2:08655e2bb776 212 for (dLoop = 0; dLoop < SER_BYTES; dLoop++) gpcSerialFromHost[dLoop] = 0;
gatedClock 2:08655e2bb776 213
gatedClock 2:08655e2bb776 214 // thread-out SPI-side processing.
gatedClock 2:08655e2bb776 215 Thread thread_1(SPIprocessingThread,NULL,osPriorityHigh,DEFAULT_STACK_SIZE,NULL);
gatedClock 2:08655e2bb776 216
gatedClock 2:08655e2bb776 217 // thread-out diagnostics.
gatedClock 2:08655e2bb776 218 Thread thread_2(diagnosticThread,NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL);
gatedClock 2:08655e2bb776 219
gatedClock 2:08655e2bb776 220 while(1) // main loop.
gatedClock 2:08655e2bb776 221 {
gatedClock 2:08655e2bb776 222 processIncomingSerial(); // process data in from host.
gatedClock 2:08655e2bb776 223 processOutgoingSerial(); // process data out to host.
gatedClock 2:08655e2bb776 224
gatedClock 2:08655e2bb776 225 dHeartbeat++; // thread heartbeat.
gatedClock 2:08655e2bb776 226 if (!(dHeartbeat % HB_MODULO)) led0 = !led0;
gatedClock 2:08655e2bb776 227 Thread::wait(THREAD_0_WAIT); // multitasking.
gatedClock 2:08655e2bb776 228 } // main loop.
gatedClock 2:08655e2bb776 229 } // main.
gatedClock 2:08655e2bb776 230 /*----------------------------------------------//----------------------------*/
gatedClock 2:08655e2bb776 231 /*
gatedClock 2:08655e2bb776 232 the python program running on the host is sending/receiving ascii characters
gatedClock 2:08655e2bb776 233 which represent command/data binary nibbles. the python program will send
gatedClock 2:08655e2bb776 234 the '$' character for command-string alignment. this function reads-in the
gatedClock 2:08655e2bb776 235 incoming serial stream when any serial data is available, into a shift-register,
gatedClock 2:08655e2bb776 236 and breaks upon detection of the '$' alignment character for python
gatedClock 2:08655e2bb776 237 command-processing. at that point the shift-register will look something like
gatedClock 2:08655e2bb776 238 [0] [1] [2] [3] [4] [5] [6] [7]
gatedClock 2:08655e2bb776 239 '1' '2' '3' '4' x x x '$' (means write 0x34 to CPU R2).
gatedClock 2:08655e2bb776 240
gatedClock 2:08655e2bb776 241
gatedClock 2:08655e2bb776 242 command-host register-number interpretation:
gatedClock 2:08655e2bb776 243 0 = CPU R0.
gatedClock 2:08655e2bb776 244 1 = CPU R1.
gatedClock 2:08655e2bb776 245 2 = CPU R2.
gatedClock 2:08655e2bb776 246 3 = CPU R3.
gatedClock 2:08655e2bb776 247 4 = CPU program-counter.
gatedClock 2:08655e2bb776 248 5 = CPU instruction-register high-byte.
gatedClock 2:08655e2bb776 249 6 = CPU instruction-register low-byte.
gatedClock 2:08655e2bb776 250
gatedClock 2:08655e2bb776 251 instruction-register write is specially implemented,
gatedClock 2:08655e2bb776 252 instruction-register read is implemented as two standard register-reads.
gatedClock 2:08655e2bb776 253
gatedClock 2:08655e2bb776 254 host-command shift-register interpretation:
gatedClock 2:08655e2bb776 255
gatedClock 2:08655e2bb776 256 gpcSerialFromHost[0] = command.
gatedClock 2:08655e2bb776 257 subsequent interpretation depends on the command.
gatedClock 2:08655e2bb776 258
gatedClock 2:08655e2bb776 259 ----
gatedClock 2:08655e2bb776 260 if command = HCMD_SETREG (write-CPU-register) or HCMD_GETREG (read-CPU-register):
gatedClock 2:08655e2bb776 261
gatedClock 2:08655e2bb776 262 gpcSerialFromHost[1] = register number (see above).
gatedClock 2:08655e2bb776 263 gpcSerialFromHost[2] = register content, high nibble.
gatedClock 2:08655e2bb776 264 gpcSerialFromHost[3] = register content, low nibble.
gatedClock 2:08655e2bb776 265 gpcSerialFromHost[4] = not used.
gatedClock 2:08655e2bb776 266 gpcSerialFromHost[5] = not used.
gatedClock 2:08655e2bb776 267 gpcSerialFromHost[6] = not used.
gatedClock 2:08655e2bb776 268
gatedClock 2:08655e2bb776 269 ----
gatedClock 2:08655e2bb776 270 if command = HCMD_SETIR (write-CPU-instruction-register):
gatedClock 2:08655e2bb776 271
gatedClock 2:08655e2bb776 272 gpcSerialFromHost[1] = IR register number, implied anyway.
gatedClock 2:08655e2bb776 273 gpcSerialFromHost[2] = IR write value high byte high nibble.
gatedClock 2:08655e2bb776 274 gpcSerialFromHost[3] = IR write value high byte low nibble.
gatedClock 2:08655e2bb776 275 gpcSerialFromHost[4] = IR write value low byte high nibble.
gatedClock 2:08655e2bb776 276 gpcSerialFromHost[5] = IR write value low byte low nibble.
gatedClock 2:08655e2bb776 277 gpcSerialFromHost[6] = not used.
gatedClock 2:08655e2bb776 278
gatedClock 2:08655e2bb776 279 ----
gatedClock 2:08655e2bb776 280 if command = HCMD_SETMM (write to CPU main-memory) or HCMD_GETMM (read from CPU main-memory):
gatedClock 2:08655e2bb776 281
gatedClock 2:08655e2bb776 282 gpcSerialFromHost[1] = MM address high nibble.
gatedClock 2:08655e2bb776 283 gpcSerialFromHost[2] = MM address low nibble.
gatedClock 2:08655e2bb776 284 gpcSerialFromHost[3] = MM content high byte high nibble.
gatedClock 2:08655e2bb776 285 gpcSerialFromHost[4] = MM content high byte low nibble.
gatedClock 2:08655e2bb776 286 gpcSerialFromHost[5] = MM content low byte high nibble.
gatedClock 2:08655e2bb776 287 gpcSerialFromHost[6] = MM content low byte low nibble.
gatedClock 2:08655e2bb776 288
gatedClock 2:08655e2bb776 289 the above also applies to function 'processOutgoingSerial'.
gatedClock 2:08655e2bb776 290 */
gatedClock 0:9a314675a67d 291
gatedClock 2:08655e2bb776 292 void processIncomingSerial(void) // process incoming serial data.
gatedClock 2:08655e2bb776 293 {
gatedClock 2:08655e2bb776 294 int dLoop; // loop index.
gatedClock 2:08655e2bb776 295 tFromHost * pFromHost; // from-host structure.
gatedClock 2:08655e2bb776 296
gatedClock 2:08655e2bb776 297 while(serial.available()) // while data from host is available.
gatedClock 2:08655e2bb776 298 {
gatedClock 2:08655e2bb776 299 // shift-in the serial stream.
gatedClock 2:08655e2bb776 300 for (dLoop = 0; dLoop < (SER_BYTES - 1); dLoop++)
gatedClock 2:08655e2bb776 301 gpcSerialFromHost[dLoop] = gpcSerialFromHost[dLoop + 1];
gatedClock 2:08655e2bb776 302 gpcSerialFromHost[SER_BYTES - 1] = serial._getc();
gatedClock 2:08655e2bb776 303
gatedClock 2:08655e2bb776 304 if (gpcSerialFromHost[SER_ALIGN] == '$')// data from host is aligned.
gatedClock 2:08655e2bb776 305 {
gatedClock 2:08655e2bb776 306 gcNewCommand = 1; // new host command just recognised.
gatedClock 2:08655e2bb776 307 break; // need to process aligned data.
gatedClock 2:08655e2bb776 308 } // data from host is aligned.
gatedClock 2:08655e2bb776 309 } // while data from host is available.
gatedClock 2:08655e2bb776 310
gatedClock 2:08655e2bb776 311 // even if more data awaits from the
gatedClock 2:08655e2bb776 312 // incoming serial stream, we now need
gatedClock 2:08655e2bb776 313 // to process the aligned data recognised
gatedClock 2:08655e2bb776 314 // as a command from the host.
gatedClock 2:08655e2bb776 315
gatedClock 2:08655e2bb776 316 if (gcNewCommand) // execute once per new command.
gatedClock 2:08655e2bb776 317 {
gatedClock 2:08655e2bb776 318 pFromHost = mPoolFromHost.alloc(); // allocate next pool entry.
gatedClock 2:08655e2bb776 319 if (!pFromHost) error("\n\r processIncomingSerial : FATAL malloc error for pFromHost. \n\r");
gatedClock 2:08655e2bb776 320 clear_tFromHost(pFromHost); // initialize structure.
gatedClock 2:08655e2bb776 321
gatedClock 2:08655e2bb776 322 // copy-in host message.
gatedClock 2:08655e2bb776 323 pFromHost->cCommand = ascii_nibble_to_binary(gpcSerialFromHost[0]);
gatedClock 2:08655e2bb776 324
gatedClock 2:08655e2bb776 325 // host requests register access.
gatedClock 2:08655e2bb776 326 if (pFromHost->cCommand == HCMD_SETREG || pFromHost->cCommand == HCMD_GETREG)
gatedClock 2:08655e2bb776 327 {
gatedClock 2:08655e2bb776 328 pFromHost->cRegisterID = ascii_nibble_to_binary(gpcSerialFromHost[1]);
gatedClock 2:08655e2bb776 329 pFromHost->cRegisterValue = ((ascii_nibble_to_binary(gpcSerialFromHost[2])) << 4) +
gatedClock 2:08655e2bb776 330 ascii_nibble_to_binary(gpcSerialFromHost[3]);
gatedClock 2:08655e2bb776 331 }
gatedClock 2:08655e2bb776 332
gatedClock 2:08655e2bb776 333
gatedClock 2:08655e2bb776 334 if (pFromHost->cCommand == HCMD_SETIR) // host requests IR write.
gatedClock 2:08655e2bb776 335 {
gatedClock 2:08655e2bb776 336 pFromHost->cIRValueH = ((ascii_nibble_to_binary(gpcSerialFromHost[2])) << 4) +
gatedClock 2:08655e2bb776 337 ascii_nibble_to_binary(gpcSerialFromHost[3]);
gatedClock 2:08655e2bb776 338 pFromHost->cIRValueL = ((ascii_nibble_to_binary(gpcSerialFromHost[4])) << 4) +
gatedClock 2:08655e2bb776 339 ascii_nibble_to_binary(gpcSerialFromHost[5]);
gatedClock 2:08655e2bb776 340 }
gatedClock 2:08655e2bb776 341
gatedClock 2:08655e2bb776 342
gatedClock 2:08655e2bb776 343 // host requests main-memory access.
gatedClock 2:08655e2bb776 344 if (pFromHost->cCommand == HCMD_SETMM || pFromHost->cCommand == HCMD_GETMM)
gatedClock 2:08655e2bb776 345 {
gatedClock 2:08655e2bb776 346 pFromHost->cMMaddress = ((ascii_nibble_to_binary(gpcSerialFromHost[1])) << 4) +
gatedClock 2:08655e2bb776 347 ascii_nibble_to_binary(gpcSerialFromHost[2]);
gatedClock 2:08655e2bb776 348 pFromHost->cMMdataH = ((ascii_nibble_to_binary(gpcSerialFromHost[3])) << 4) +
gatedClock 2:08655e2bb776 349 ascii_nibble_to_binary(gpcSerialFromHost[4]);
gatedClock 2:08655e2bb776 350 pFromHost->cMMdataL = ((ascii_nibble_to_binary(gpcSerialFromHost[5])) << 4) +
gatedClock 2:08655e2bb776 351 ascii_nibble_to_binary(gpcSerialFromHost[6]);
gatedClock 2:08655e2bb776 352 } // host requests main-memory access.
gatedClock 2:08655e2bb776 353
gatedClock 2:08655e2bb776 354 if (pFromHost->cCommand == HCMD_GETREG || pFromHost->cCommand == HCMD_GETMM)
gatedClock 2:08655e2bb776 355 gdRoundTrip++; // expected reply to host is pending.
gatedClock 2:08655e2bb776 356 qFromHost.put(pFromHost); // send out for processing.
gatedClock 2:08655e2bb776 357 gcNewCommand = 0; // don't execute until next new command.
gatedClock 2:08655e2bb776 358 } // execute once per new command.
gatedClock 2:08655e2bb776 359 Thread::wait(THREAD_0_WAIT); // multitasking.
gatedClock 2:08655e2bb776 360 } // processIncomingSerial
gatedClock 2:08655e2bb776 361 /*----------------------------------------------//----------------------------*/
gatedClock 2:08655e2bb776 362 void processOutgoingSerial(void) // prepare/transmit data to host.
gatedClock 2:08655e2bb776 363 {
gatedClock 2:08655e2bb776 364 int dLoop; // loop index.
gatedClock 2:08655e2bb776 365
gatedClock 2:08655e2bb776 366 gqToHostEvent = qToHost.get(1); // check for reply back to host.
gatedClock 2:08655e2bb776 367
gatedClock 2:08655e2bb776 368 // if new reply to host:
gatedClock 2:08655e2bb776 369 if (gqToHostEvent.status == osEventMessage)
gatedClock 2:08655e2bb776 370 {
gatedClock 2:08655e2bb776 371 // bring it in from the queue.
gatedClock 2:08655e2bb776 372 gpToHost = (tToHost *) gqToHostEvent.value.p;
gatedClock 2:08655e2bb776 373 if (!gpToHost) error("\n\r processOutgoingSerial : FATAL null gpToHost pointer. \n\r");
gatedClock 2:08655e2bb776 374
gatedClock 2:08655e2bb776 375 // clear outgoing buffer.
gatedClock 2:08655e2bb776 376 for (dLoop = 0; dLoop < SER_BYTES; dLoop++) gpcSerialToHost[dLoop] = 0;
gatedClock 2:08655e2bb776 377
gatedClock 2:08655e2bb776 378 // the commands from the host were
gatedClock 2:08655e2bb776 379 // looped-back into the to-host struct,
gatedClock 2:08655e2bb776 380 // make use of them here.
gatedClock 2:08655e2bb776 381
gatedClock 2:08655e2bb776 382 if (gpToHost->cCommand == HCMD_GETREG) // reading from a register.
gatedClock 2:08655e2bb776 383 {
gatedClock 2:08655e2bb776 384 gpcSerialToHost[0] = binary_to_ascii_nibble( gpToHost->cCommand);
gatedClock 2:08655e2bb776 385 gpcSerialToHost[1] = binary_to_ascii_nibble( gpToHost->cRegisterID);
gatedClock 2:08655e2bb776 386 gpcSerialToHost[2] = binary_to_ascii_nibble(((gpToHost->cRegisterValue) >> 4) & 0x0F);
gatedClock 2:08655e2bb776 387 gpcSerialToHost[3] = binary_to_ascii_nibble(((gpToHost->cRegisterValue) >> 0) & 0x0F);
gatedClock 2:08655e2bb776 388 gpcSerialToHost[4] = '\n'; // signals end of transfer.
gatedClock 2:08655e2bb776 389
gatedClock 2:08655e2bb776 390 // transmit to the host.
gatedClock 2:08655e2bb776 391 serial.writeBlock((uint8_t *) gpcSerialToHost, (uint16_t) SER_BYTES);
gatedClock 2:08655e2bb776 392 gdRoundTrip--; // expected reply sent to host.
gatedClock 2:08655e2bb776 393 }
gatedClock 2:08655e2bb776 394
gatedClock 2:08655e2bb776 395 if (gpToHost->cCommand == HCMD_GETMM) // reading from main-memory.
gatedClock 2:08655e2bb776 396 {
gatedClock 2:08655e2bb776 397 gpcSerialToHost[0] = binary_to_ascii_nibble( gpToHost->cCommand);
gatedClock 2:08655e2bb776 398 gpcSerialToHost[1] = binary_to_ascii_nibble(((gpToHost->cMMaddress) >> 4) & 0x0F);
gatedClock 2:08655e2bb776 399 gpcSerialToHost[2] = binary_to_ascii_nibble(((gpToHost->cMMaddress) >> 0) & 0x0F);
gatedClock 2:08655e2bb776 400 gpcSerialToHost[3] = binary_to_ascii_nibble(((gpToHost->cMMdataH ) >> 4) & 0x0F);
gatedClock 2:08655e2bb776 401 gpcSerialToHost[4] = binary_to_ascii_nibble(((gpToHost->cMMdataH ) >> 0) & 0x0F);
gatedClock 2:08655e2bb776 402 gpcSerialToHost[5] = binary_to_ascii_nibble(((gpToHost->cMMdataL ) >> 4) & 0x0F);
gatedClock 2:08655e2bb776 403 gpcSerialToHost[6] = binary_to_ascii_nibble(((gpToHost->cMMdataL ) >> 0) & 0x0F);
gatedClock 2:08655e2bb776 404 gpcSerialToHost[7] = '\n'; // signals end of transfer.
gatedClock 2:08655e2bb776 405
gatedClock 2:08655e2bb776 406 // transmit to the host.
gatedClock 2:08655e2bb776 407 serial.writeBlock((uint8_t *) gpcSerialToHost, (uint16_t) SER_BYTES);
gatedClock 2:08655e2bb776 408 gdRoundTrip--; // expected reply sent to host.
gatedClock 2:08655e2bb776 409 }
gatedClock 2:08655e2bb776 410 mPoolToHost.free(gpToHost); // done with this queue entry.
gatedClock 2:08655e2bb776 411 gpToHost = NULL; // clear pointer.
gatedClock 2:08655e2bb776 412 } // if new reply to host.
gatedClock 2:08655e2bb776 413 } // processOutgoingSerial.
gatedClock 2:08655e2bb776 414 /*----------------------------------------------//----------------------------*/
gatedClock 2:08655e2bb776 415 // the pcSendBuffer and pcReceiveBuffer arrays are not used by this function,
gatedClock 2:08655e2bb776 416 // but they are declared by this function, and their pointers are passed
gatedClock 2:08655e2bb776 417 // down to the mmSPI library for its use of them.
gatedClock 2:08655e2bb776 418 // note- the prefix 'pc' means 'pointer of type character', not 'personal computer'.
gatedClock 2:08655e2bb776 419
gatedClock 2:08655e2bb776 420 void SPIprocessingThread(void const *args) // process host-commands via SPI.
gatedClock 2:08655e2bb776 421 {
gatedClock 2:08655e2bb776 422 char pcSendBuffer [SPI_BYTES]; // SPI send buffer.
gatedClock 2:08655e2bb776 423 char pcReceiveBuffer[SPI_BYTES]; // SPI receive buffer.
gatedClock 2:08655e2bb776 424 int dHeartbeat; // heartbeat counter.
gatedClock 2:08655e2bb776 425 int dMemoryRead; // read main-memory into this.
gatedClock 2:08655e2bb776 426 int dLoop; // loop index.
gatedClock 2:08655e2bb776 427 osEvent qFromHostEvent; // incoming message event.
gatedClock 2:08655e2bb776 428 tFromHost * pFromHost; // message structure.
gatedClock 2:08655e2bb776 429 tToHost * gpToHost; // message structure.
gatedClock 2:08655e2bb776 430 mmSPI * pSPI; // SPI.
gatedClock 2:08655e2bb776 431
gatedClock 2:08655e2bb776 432 pFromHost = NULL; // NULL pointers.
gatedClock 2:08655e2bb776 433 gpToHost = NULL;
gatedClock 2:08655e2bb776 434 pSPI = NULL;
gatedClock 2:08655e2bb776 435 dHeartbeat = 0; // clear variables.
gatedClock 2:08655e2bb776 436 dMemoryRead = 0;
gatedClock 2:08655e2bb776 437 dLoop = 0;
gatedClock 2:08655e2bb776 438 // clear SPI vectors.
gatedClock 2:08655e2bb776 439 for (dLoop = 0; dLoop < SPI_BYTES; dLoop++) pcSendBuffer [dLoop] = 0;
gatedClock 2:08655e2bb776 440 for (dLoop = 0; dLoop < SPI_BYTES; dLoop++) pcReceiveBuffer[dLoop] = 0;
gatedClock 2:08655e2bb776 441
gatedClock 2:08655e2bb776 442 pSPI = new mmSPI; // SPI allocation.
gatedClock 2:08655e2bb776 443 if (!pSPI) error("\n\r SPIprocessingThread : FATAL malloc error for pSPI. \n\r");
gatedClock 2:08655e2bb776 444
gatedClock 2:08655e2bb776 445 pSPI->setSendBuffer (pcSendBuffer); // set SPI send buffer.
gatedClock 2:08655e2bb776 446 pSPI->setReceiveBuffer(pcReceiveBuffer); // set SPI receive buffer.
gatedClock 2:08655e2bb776 447 pSPI->setNumberOfBytes(SPI_BYTES); // set SPI number of bytes.
gatedClock 2:08655e2bb776 448 pSPI->setSPIfrequency (SPI_HZ); // set SPI clock frequency.
gatedClock 2:08655e2bb776 449
gatedClock 2:08655e2bb776 450 while(1) // thread loop.
gatedClock 2:08655e2bb776 451 {
gatedClock 2:08655e2bb776 452 qFromHostEvent = qFromHost.get(1); // check for incoming host command.
gatedClock 2:08655e2bb776 453
gatedClock 2:08655e2bb776 454 // if new host command:
gatedClock 2:08655e2bb776 455 if (qFromHostEvent.status == osEventMessage)
gatedClock 2:08655e2bb776 456 {
gatedClock 2:08655e2bb776 457 // bring it in from the queue.
gatedClock 2:08655e2bb776 458 pFromHost = (tFromHost *) qFromHostEvent.value.p;
gatedClock 2:08655e2bb776 459 if (!pFromHost) error("\n\r SPIprocessingThread : FATAL null pFromHost pointer. \n\r");
gatedClock 2:08655e2bb776 460
gatedClock 2:08655e2bb776 461 switch(pFromHost->cCommand) // host command decode.
gatedClock 2:08655e2bb776 462 {
gatedClock 2:08655e2bb776 463 case HCMD_SETREG : // set CPU register.
gatedClock 2:08655e2bb776 464 {
gatedClock 2:08655e2bb776 465 switch(pFromHost->cRegisterID) // which register to write to.
gatedClock 2:08655e2bb776 466 {
gatedClock 2:08655e2bb776 467 case CPU_REG_0 : {pSPI->write_register(CPU_REG_0 , pFromHost->cRegisterValue); break;}
gatedClock 2:08655e2bb776 468 case CPU_REG_1 : {pSPI->write_register(CPU_REG_1 , pFromHost->cRegisterValue); break;}
gatedClock 2:08655e2bb776 469 case CPU_REG_2 : {pSPI->write_register(CPU_REG_2 , pFromHost->cRegisterValue); break;}
gatedClock 2:08655e2bb776 470 case CPU_REG_3 : {pSPI->write_register(CPU_REG_3 , pFromHost->cRegisterValue); break;}
gatedClock 2:08655e2bb776 471 case CPU_REG_PC : {pSPI->write_register(CPU_REG_PC, pFromHost->cRegisterValue); break;}
gatedClock 2:08655e2bb776 472 default : {break;}
gatedClock 2:08655e2bb776 473 } // which register to write to.
gatedClock 2:08655e2bb776 474 break;
gatedClock 2:08655e2bb776 475 } // set CPU register.
gatedClock 2:08655e2bb776 476
gatedClock 2:08655e2bb776 477 case HCMD_SETIR: // set instruction register.
gatedClock 2:08655e2bb776 478 {
gatedClock 2:08655e2bb776 479 pSPI->write_IR(pFromHost->cIRValueH, pFromHost->cIRValueL);
gatedClock 2:08655e2bb776 480 break;
gatedClock 2:08655e2bb776 481 } // set instruction register.
gatedClock 2:08655e2bb776 482
gatedClock 2:08655e2bb776 483 case HCMD_GETREG : // get CPU register.
gatedClock 2:08655e2bb776 484 {
gatedClock 2:08655e2bb776 485 gpToHost = mPoolToHost.alloc(); // allocate next pool entry.
gatedClock 2:08655e2bb776 486 if (!gpToHost) error("\n\r SPIprocessingThread : FATAL malloc error for gpToHost. \n\r");
gatedClock 2:08655e2bb776 487 clear_tToHost(gpToHost); // initialize structure.
gatedClock 2:08655e2bb776 488
gatedClock 2:08655e2bb776 489 switch(pFromHost->cRegisterID) // which register to read from.
gatedClock 2:08655e2bb776 490 {
gatedClock 2:08655e2bb776 491 case CPU_REG_0 : {gpToHost->cRegisterValue = pSPI->read_register(CPU_REG_0 ); break;}
gatedClock 2:08655e2bb776 492 case CPU_REG_1 : {gpToHost->cRegisterValue = pSPI->read_register(CPU_REG_1 ); break;}
gatedClock 2:08655e2bb776 493 case CPU_REG_2 : {gpToHost->cRegisterValue = pSPI->read_register(CPU_REG_2 ); break;}
gatedClock 2:08655e2bb776 494 case CPU_REG_3 : {gpToHost->cRegisterValue = pSPI->read_register(CPU_REG_3 ); break;}
gatedClock 2:08655e2bb776 495 case CPU_REG_PC : {gpToHost->cRegisterValue = pSPI->read_register(CPU_REG_PC); break;}
gatedClock 2:08655e2bb776 496 case CPU_IR_H : {gpToHost->cRegisterValue = pSPI->read_register(CPU_IR_H ); break;}
gatedClock 2:08655e2bb776 497 case CPU_IR_L : {gpToHost->cRegisterValue = pSPI->read_register(CPU_IR_L ); break;}
gatedClock 2:08655e2bb776 498 default : {break;}
gatedClock 2:08655e2bb776 499 } // which register to read from.
gatedClock 2:08655e2bb776 500
gatedClock 2:08655e2bb776 501 // loop-back to host.
gatedClock 2:08655e2bb776 502 gpToHost->cCommand = pFromHost->cCommand;
gatedClock 2:08655e2bb776 503 gpToHost->cRegisterID = pFromHost->cRegisterID;
gatedClock 2:08655e2bb776 504
gatedClock 2:08655e2bb776 505 qToHost.put(gpToHost); // send up for processing.
gatedClock 2:08655e2bb776 506 break;
gatedClock 2:08655e2bb776 507 } // get CPU register.
gatedClock 2:08655e2bb776 508
gatedClock 2:08655e2bb776 509 case HCMD_SETMM : // do main-memory write.
gatedClock 2:08655e2bb776 510 {
gatedClock 2:08655e2bb776 511 pSPI->write_memory(pFromHost->cMMdataH, pFromHost->cMMdataL, pFromHost->cMMaddress);
gatedClock 2:08655e2bb776 512 break;
gatedClock 2:08655e2bb776 513 } // do main-memory write.
gatedClock 2:08655e2bb776 514
gatedClock 2:08655e2bb776 515 case HCMD_GETMM : // do main-memory read.
gatedClock 2:08655e2bb776 516 {
gatedClock 2:08655e2bb776 517 gpToHost = mPoolToHost.alloc(); // allocate next pool entry.
gatedClock 2:08655e2bb776 518 if (!gpToHost) error("\n\r SPIprocessingThread : FATAL malloc error for gpToHost. \n\r");
gatedClock 2:08655e2bb776 519 clear_tToHost(gpToHost); // initialize structure.
gatedClock 2:08655e2bb776 520
gatedClock 2:08655e2bb776 521 // read from CPU memory.
gatedClock 2:08655e2bb776 522 dMemoryRead = pSPI->read_memory(pFromHost->cMMaddress);
gatedClock 2:08655e2bb776 523 gpToHost->cMMdataH = (dMemoryRead >> 8) & 0xFF;
gatedClock 2:08655e2bb776 524 gpToHost->cMMdataL = (dMemoryRead >> 0) & 0xFF;
gatedClock 2:08655e2bb776 525
gatedClock 2:08655e2bb776 526 // loop-back to host.
gatedClock 2:08655e2bb776 527 gpToHost->cCommand = pFromHost->cCommand;
gatedClock 2:08655e2bb776 528 gpToHost->cMMaddress = pFromHost->cMMaddress;
gatedClock 2:08655e2bb776 529
gatedClock 2:08655e2bb776 530 qToHost.put(gpToHost); // send up for processing.
gatedClock 2:08655e2bb776 531 break;
gatedClock 2:08655e2bb776 532 } // do main-memory read.
gatedClock 2:08655e2bb776 533
gatedClock 2:08655e2bb776 534 case HCMD_STEP : // step the CPU.
gatedClock 2:08655e2bb776 535 {
gatedClock 2:08655e2bb776 536 pSPI->step();
gatedClock 2:08655e2bb776 537 break;
gatedClock 2:08655e2bb776 538 } // step the CPU.
gatedClock 2:08655e2bb776 539 default : break;
gatedClock 2:08655e2bb776 540 } // host command decode.
gatedClock 2:08655e2bb776 541 mPoolFromHost.free(pFromHost); // done with this queue entry.
gatedClock 2:08655e2bb776 542 pFromHost = NULL; // clear pointer.
gatedClock 2:08655e2bb776 543 } // if new host command.
gatedClock 2:08655e2bb776 544
gatedClock 2:08655e2bb776 545 gulSPIclkCount = pSPI->SPIClockCount(); // propagate to global variable.
gatedClock 2:08655e2bb776 546 gulCPUclkCount = pSPI->CPUClockCount(); // propagate to global variable.
gatedClock 2:08655e2bb776 547
gatedClock 2:08655e2bb776 548 // thread heartbeat.
gatedClock 2:08655e2bb776 549 dHeartbeat++; if (!(dHeartbeat % HB_MODULO)) led1 = !led1;
gatedClock 2:08655e2bb776 550 Thread::wait(THREAD_1_WAIT); // cooperative multitasking.
gatedClock 2:08655e2bb776 551 } // thread loop.
gatedClock 2:08655e2bb776 552 } // SPIprocessingThread.
gatedClock 2:08655e2bb776 553 /*----------------------------------------------//----------------------------*/
gatedClock 2:08655e2bb776 554 void diagnosticThread(void const *args) // LCD and LED notifications.
gatedClock 2:08655e2bb776 555 {
gatedClock 2:08655e2bb776 556 int dHeartbeat; // heartbeat counter.
gatedClock 2:08655e2bb776 557
gatedClock 2:08655e2bb776 558 dHeartbeat = 0; // initialize.
gatedClock 2:08655e2bb776 559 led3 = 0; // initialize.
gatedClock 2:08655e2bb776 560
gatedClock 2:08655e2bb776 561 while(1) // thread loop.
gatedClock 2:08655e2bb776 562 {
gatedClock 2:08655e2bb776 563 // if message round trip
gatedClock 2:08655e2bb776 564 // count not consistent.
gatedClock 2:08655e2bb776 565 if (gdRoundTrip > 1025 || gdRoundTrip < 1024) led3 = 1;
gatedClock 2:08655e2bb776 566
gatedClock 2:08655e2bb776 567 lcd.cls(); // clear LCD display.
gatedClock 2:08655e2bb776 568 LCD1; // lcd line 1.
gatedClock 2:08655e2bb776 569 lcd.printf(" USB DEV CLASS PROJECT");
gatedClock 2:08655e2bb776 570
gatedClock 2:08655e2bb776 571 LCD2; // lcd line 2.
gatedClock 2:08655e2bb776 572 lcd.printf(" %11lu = SPI clocks",gulSPIclkCount);
gatedClock 2:08655e2bb776 573
gatedClock 2:08655e2bb776 574 LCD3; // lcd line 3.
gatedClock 2:08655e2bb776 575 lcd.printf(" %11lu = CPU clocks",gulCPUclkCount);
gatedClock 2:08655e2bb776 576
gatedClock 2:08655e2bb776 577 dHeartbeat++; // thread heartbeat.
gatedClock 2:08655e2bb776 578 if (!(dHeartbeat % HB_MODULO)) led2 = !led2;
gatedClock 2:08655e2bb776 579 Thread::wait(THREAD_2_WAIT); // multitasking.
gatedClock 2:08655e2bb776 580 } // thread loop.
gatedClock 2:08655e2bb776 581 } // diagnosticThread.
gatedClock 2:08655e2bb776 582 /*----------------------------------------------//----------------------------*/
gatedClock 2:08655e2bb776 583 char ascii_nibble_to_binary(char cAscii) // ascii nibble -> binary.
gatedClock 2:08655e2bb776 584 {
gatedClock 2:08655e2bb776 585 char cBinary; // converted value.
gatedClock 2:08655e2bb776 586
gatedClock 2:08655e2bb776 587 switch(cAscii)
gatedClock 2:08655e2bb776 588 {
gatedClock 2:08655e2bb776 589 case 'F' : {cBinary = 15; break;}
gatedClock 2:08655e2bb776 590 case 'E' : {cBinary = 14; break;}
gatedClock 2:08655e2bb776 591 case 'D' : {cBinary = 13; break;}
gatedClock 2:08655e2bb776 592 case 'C' : {cBinary = 12; break;}
gatedClock 2:08655e2bb776 593 case 'B' : {cBinary = 11; break;}
gatedClock 2:08655e2bb776 594 case 'A' : {cBinary = 10; break;}
gatedClock 2:08655e2bb776 595 case 'f' : {cBinary = 15; break;}
gatedClock 2:08655e2bb776 596 case 'e' : {cBinary = 14; break;}
gatedClock 2:08655e2bb776 597 case 'd' : {cBinary = 13; break;}
gatedClock 2:08655e2bb776 598 case 'c' : {cBinary = 12; break;}
gatedClock 2:08655e2bb776 599 case 'b' : {cBinary = 11; break;}
gatedClock 2:08655e2bb776 600 case 'a' : {cBinary = 10; break;}
gatedClock 2:08655e2bb776 601 case '9' : {cBinary = 9; break;}
gatedClock 2:08655e2bb776 602 case '8' : {cBinary = 8; break;}
gatedClock 2:08655e2bb776 603 case '7' : {cBinary = 7; break;}
gatedClock 2:08655e2bb776 604 case '6' : {cBinary = 6; break;}
gatedClock 2:08655e2bb776 605 case '5' : {cBinary = 5; break;}
gatedClock 2:08655e2bb776 606 case '4' : {cBinary = 4; break;}
gatedClock 2:08655e2bb776 607 case '3' : {cBinary = 3; break;}
gatedClock 2:08655e2bb776 608 case '2' : {cBinary = 2; break;}
gatedClock 2:08655e2bb776 609 case '1' : {cBinary = 1; break;}
gatedClock 2:08655e2bb776 610 case '0' : {cBinary = 0; break;}
gatedClock 2:08655e2bb776 611 default : {cBinary = 0; break;}
gatedClock 2:08655e2bb776 612 } // switch(cAscii).
gatedClock 2:08655e2bb776 613 return(cBinary); // return the binary.
gatedClock 2:08655e2bb776 614 } // ascii_nibble_to_binary.
gatedClock 2:08655e2bb776 615 /*----------------------------------------------//----------------------------*/
gatedClock 2:08655e2bb776 616 char binary_to_ascii_nibble(char cBinary) // binary -> ascii nibble.
gatedClock 2:08655e2bb776 617 {
gatedClock 2:08655e2bb776 618 char cAscii; // converted value.
gatedClock 2:08655e2bb776 619
gatedClock 2:08655e2bb776 620 switch(cBinary)
gatedClock 2:08655e2bb776 621 {
gatedClock 2:08655e2bb776 622 case 15 : {cAscii = 'F'; break;}
gatedClock 2:08655e2bb776 623 case 14 : {cAscii = 'E'; break;}
gatedClock 2:08655e2bb776 624 case 13 : {cAscii = 'D'; break;}
gatedClock 2:08655e2bb776 625 case 12 : {cAscii = 'C'; break;}
gatedClock 2:08655e2bb776 626 case 11 : {cAscii = 'B'; break;}
gatedClock 2:08655e2bb776 627 case 10 : {cAscii = 'A'; break;}
gatedClock 2:08655e2bb776 628 case 9 : {cAscii = '9'; break;}
gatedClock 2:08655e2bb776 629 case 8 : {cAscii = '8'; break;}
gatedClock 2:08655e2bb776 630 case 7 : {cAscii = '7'; break;}
gatedClock 2:08655e2bb776 631 case 6 : {cAscii = '6'; break;}
gatedClock 2:08655e2bb776 632 case 5 : {cAscii = '5'; break;}
gatedClock 2:08655e2bb776 633 case 4 : {cAscii = '4'; break;}
gatedClock 2:08655e2bb776 634 case 3 : {cAscii = '3'; break;}
gatedClock 2:08655e2bb776 635 case 2 : {cAscii = '2'; break;}
gatedClock 2:08655e2bb776 636 case 1 : {cAscii = '1'; break;}
gatedClock 2:08655e2bb776 637 case 0 : {cAscii = '0'; break;}
gatedClock 2:08655e2bb776 638 default : {cAscii = '0'; break;}
gatedClock 2:08655e2bb776 639 } // switch(cBinary).
gatedClock 2:08655e2bb776 640 return(cAscii); // return the binary.
gatedClock 2:08655e2bb776 641 } // binary_to_ascii_nibble.
gatedClock 2:08655e2bb776 642 /*----------------------------------------------//----------------------------*/
gatedClock 2:08655e2bb776 643 void clear_tFromHost(tFromHost * ptFromHost)// clear structure.
gatedClock 2:08655e2bb776 644 {
gatedClock 2:08655e2bb776 645 ptFromHost->cCommand = 0x00;
gatedClock 2:08655e2bb776 646 ptFromHost->cRegisterID = 0x00;
gatedClock 2:08655e2bb776 647 ptFromHost->cRegisterValue = 0x00;
gatedClock 2:08655e2bb776 648 ptFromHost->cIRValueH = 0x00;
gatedClock 2:08655e2bb776 649 ptFromHost->cIRValueL = 0x00;
gatedClock 2:08655e2bb776 650 ptFromHost->cMMaddress = 0x00;
gatedClock 2:08655e2bb776 651 ptFromHost->cMMdataH = 0x00;
gatedClock 2:08655e2bb776 652 ptFromHost->cMMdataL = 0x00;
gatedClock 2:08655e2bb776 653 } // clear_tFromHost.
gatedClock 2:08655e2bb776 654 /*----------------------------------------------//----------------------------*/
gatedClock 2:08655e2bb776 655 void clear_tToHost(tToHost * ptToHost) // clear structure.
gatedClock 2:08655e2bb776 656 {
gatedClock 2:08655e2bb776 657 ptToHost->cCommand = 0x00;
gatedClock 2:08655e2bb776 658 ptToHost->cRegisterID = 0x00;
gatedClock 2:08655e2bb776 659 ptToHost->cRegisterValue = 0x00;
gatedClock 2:08655e2bb776 660 ptToHost->cMMaddress = 0x00;
gatedClock 2:08655e2bb776 661 ptToHost->cMMdataH = 0x00;
gatedClock 2:08655e2bb776 662 ptToHost->cMMdataL = 0x00;
gatedClock 2:08655e2bb776 663 } // clear_tToHost.
gatedClock 2:08655e2bb776 664 /*----------------------------------------------//----------------------------*/