embedded RTOS class project.

Dependencies:   C12832_lcd USBDevice mbed-rtos mbed mmSPI_RTOS watchdog_RTOS

Committer:
gatedClock
Date:
Tue Sep 17 20:45:34 2013 +0000
Revision:
3:1b3329242491
Parent:
2:4336e18b60fe
embedded RTOS class project.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gatedClock 0:8e898e1270d6 1 /*----------------------------------------------//------------------------------
gatedClock 0:8e898e1270d6 2 student : m-moore
gatedClock 0:8e898e1270d6 3 email : gated.clock@gmail.com
gatedClock 0:8e898e1270d6 4 class : embedded RTOS
gatedClock 1:a3df81701818 5 directory : RTOS_project
gatedClock 0:8e898e1270d6 6 file : main.cpp
gatedClock 0:8e898e1270d6 7 date : september 19, 2013.
gatedClock 0:8e898e1270d6 8 ----copyright-----------------------------------//------------------------------
gatedClock 0:8e898e1270d6 9 licensed for personal and academic use.
gatedClock 0:8e898e1270d6 10 commercial use of original code must be approved by the account-holder of
gatedClock 0:8e898e1270d6 11 gated.clock@gmail.com
gatedClock 0:8e898e1270d6 12 ----revision------------------------------------//------------------------------
gatedClock 0:8e898e1270d6 13 this is the embedded RTOS class revision.
gatedClock 0:8e898e1270d6 14 changes made since the USB device class release:
gatedClock 0:8e898e1270d6 15
gatedClock 0:8e898e1270d6 16 1. a 'read all registers' feature has been added, which speeds up
gatedClock 0:8e898e1270d6 17 CPU execution, since the UI obtains all of the register states after
gatedClock 0:8e898e1270d6 18 each CPU clock. originally, each register was individually read.
gatedClock 0:8e898e1270d6 19 now, all registers are read at once, if so requested by the python code.
gatedClock 0:8e898e1270d6 20
gatedClock 0:8e898e1270d6 21 2. some 'if' statements were changed to 'switch' statements (neatening).
gatedClock 0:8e898e1270d6 22
gatedClock 0:8e898e1270d6 23 3. added watchdog timers for the three threads. this via a meta-watchdog thread.
gatedClock 0:8e898e1270d6 24
gatedClock 0:8e898e1270d6 25 4. added #defined-based option to either boot on error detection
gatedClock 0:8e898e1270d6 26 (such as malloc fail) or use error(); function.
gatedClock 0:8e898e1270d6 27
gatedClock 0:8e898e1270d6 28 5. the LCD is updated only if a display value is changed - reduced power
gatedClock 0:8e898e1270d6 29 usage a little & reduces potential 'blinkieness'.
gatedClock 0:8e898e1270d6 30
gatedClock 0:8e898e1270d6 31 6. BOOT notification on LCD.
gatedClock 0:8e898e1270d6 32 ----description---------------------------------//------------------------------
gatedClock 0:8e898e1270d6 33 overview:
gatedClock 0:8e898e1270d6 34 program to provide round-trip communication between a python test-control
gatedClock 0:8e898e1270d6 35 program running on a pc host, and a device-under-test CPU implemented on
gatedClock 0:8e898e1270d6 36 an altera board. the pc-host communication is over USBSerial, and the
gatedClock 0:8e898e1270d6 37 altera communication is over SPI.
gatedClock 0:8e898e1270d6 38
gatedClock 0:8e898e1270d6 39 features:
gatedClock 0:8e898e1270d6 40 1. multi-threaded design, use of memory-pools to transfer data between threads.
gatedClock 0:8e898e1270d6 41 2. use of USBDevice library for communication with PC host.
gatedClock 1:a3df81701818 42 3. use of mmSPI_RTOS custom library for communication with FPGA.
gatedClock 0:8e898e1270d6 43 4. main thread provides USBSerial communication to/from host.
gatedClock 0:8e898e1270d6 44 5. SPI processing thread provides SPI communication to/from DUT.
gatedClock 1:a3df81701818 45 6. mmSPI_RTOS library generates non-overlapping SPI and CPU clocks.
gatedClock 0:8e898e1270d6 46 7. background diagnostic thread provides LCD & error updates.
gatedClock 0:8e898e1270d6 47 8. meta watchdog thread monitors itself & the other threads.
gatedClock 0:8e898e1270d6 48
gatedClock 0:8e898e1270d6 49 indicators: (led<3:0> = LED<1:4>)
gatedClock 0:8e898e1270d6 50 1. LCD provides running counts for SPI and CPU clock cycles.
gatedClock 0:8e898e1270d6 51 2. led0 indicates main thread processing.
gatedClock 0:8e898e1270d6 52 3. led1 indicates SPI thread processing.
gatedClock 0:8e898e1270d6 53 4. led2 indicates LCD thread processing.
gatedClock 0:8e898e1270d6 54 5. led3 indicates watchdog thread processing.
gatedClock 0:8e898e1270d6 55
gatedClock 0:8e898e1270d6 56 implementation:
gatedClock 0:8e898e1270d6 57 1. main.processIncomingSerial(): accept incoming serial data from host,
gatedClock 0:8e898e1270d6 58 and map it into tFromHost structures.
gatedClock 0:8e898e1270d6 59 2. SPIprocessingThread: take the incoming data structures instances, and
gatedClock 1:a3df81701818 60 feed their content into mmSPI_RTOS commands.
gatedClock 1:a3df81701818 61 3. mmSPI_RTOS object: given commands/data passed from caller,
gatedClock 0:8e898e1270d6 62 map them into SPI outgoing vectors and scan them into the FPGA.
gatedClock 1:a3df81701818 63 4. mmSPI_RTOS object: receive incoming SPI vectors from FPGA.
gatedClock 0:8e898e1270d6 64 make FPGA payload data available to caller.
gatedClock 0:8e898e1270d6 65 5. SPIprocessingThread: load tToHost structures with said FPGA payload data.
gatedClock 0:8e898e1270d6 66 6. main.processOutgoingSerial(): transfer tToHost structure data into a
gatedClock 0:8e898e1270d6 67 serial outgoing buffer, and block-transfer it to the host PC.
gatedClock 0:8e898e1270d6 68
gatedClock 0:8e898e1270d6 69 electrical:
gatedClock 0:8e898e1270d6 70 1. four pins (and ground) attached to the zigbee header,
gatedClock 0:8e898e1270d6 71 programmed as three SPI pins and the CPU clock.
gatedClock 0:8e898e1270d6 72 2. each of the four signals over twisted-pair.
gatedClock 0:8e898e1270d6 73 3. but some ribbon cable is used at the FPGA end.
gatedClock 0:8e898e1270d6 74 4. best if only the mbed application board USB cable is attached
gatedClock 0:8e898e1270d6 75 to the host; if the mbed CPU board USB cable is also attached to
gatedClock 0:8e898e1270d6 76 the host, then the python program may attempt to use the wrong USB
gatedClock 0:8e898e1270d6 77 connection.
gatedClock 0:8e898e1270d6 78 5. no particular power sequence is needed for this system to work.
gatedClock 0:8e898e1270d6 79
gatedClock 0:8e898e1270d6 80 timing critical path: serial processing. the python code needs
gatedClock 0:8e898e1270d6 81 a delay between serial access of 40mS conservatively.
gatedClock 0:8e898e1270d6 82
gatedClock 0:8e898e1270d6 83 testing:
gatedClock 0:8e898e1270d6 84 the python UI provides the main testing mechanism.
gatedClock 0:8e898e1270d6 85
gatedClock 0:8e898e1270d6 86 USB connect.
gatedClock 0:8e898e1270d6 87 00. press 'CONNECT' button in UI. verify connection info in shell.
gatedClock 0:8e898e1270d6 88
gatedClock 0:8e898e1270d6 89 CPU register w/r
gatedClock 0:8e898e1270d6 90 01. type values into {R0,R1,R2,R3,PC,IR} UI entry-forms.
gatedClock 0:8e898e1270d6 91 02. press 'REG WRITE' UI button.
gatedClock 0:8e898e1270d6 92 03. press 'REG READ' UI button.
gatedClock 0:8e898e1270d6 93 04. verify that the read data is correct.
gatedClock 0:8e898e1270d6 94
gatedClock 0:8e898e1270d6 95 CPU main-memory w/r
gatedClock 0:8e898e1270d6 96 05. type an address into 'mmADR' UI entry-form.
gatedClock 0:8e898e1270d6 97 06. type data into 'mmVAL' UI entry-form.
gatedClock 0:8e898e1270d6 98 07. press 'MM WRITE' UI button.
gatedClock 0:8e898e1270d6 99 08. type a different address into 'mmADR' UI entry-form.
gatedClock 0:8e898e1270d6 100 09. type different data into 'mmVAL' UI entry-form.
gatedClock 0:8e898e1270d6 101 10. press 'MM WRITE' UI button.
gatedClock 0:8e898e1270d6 102 11. type address from (05) into 'mmADR' UI entry-form.
gatedClock 0:8e898e1270d6 103 12. press 'MM READ' UI button.
gatedClock 0:8e898e1270d6 104 13. verify that the data from (06) is seen in the 'mmVAL' entry form.
gatedClock 0:8e898e1270d6 105 14. type address from (08) into 'mmADR' UI entry-form.
gatedClock 0:8e898e1270d6 106 15. press 'MM READ' UI button.
gatedClock 0:8e898e1270d6 107 16. verify that the data from (09) is seen in the 'mmVAL' entry form.
gatedClock 0:8e898e1270d6 108
gatedClock 0:8e898e1270d6 109 CPU main-memory full load/dump.
gatedClock 0:8e898e1270d6 110 17. press 'PROGRAM' in the UI. select a program file in the dialog-popup.
gatedClock 0:8e898e1270d6 111 18. watch the load process in the shell text.
gatedClock 0:8e898e1270d6 112 19. press 'DUMP in the UI. select a main-memory dump file in the diaglog-popup.
gatedClock 0:8e898e1270d6 113 20. watch the dump process in the shell text.
gatedClock 0:8e898e1270d6 114
gatedClock 0:8e898e1270d6 115 CPU step function.
gatedClock 0:8e898e1270d6 116 21. press 'STEP' in the UI repeatedly, watch the UI display the
gatedClock 0:8e898e1270d6 117 CPU register states as the current program is executed one CPU clock
gatedClock 0:8e898e1270d6 118 at a time.
gatedClock 0:8e898e1270d6 119
gatedClock 0:8e898e1270d6 120 CPU run function.
gatedClock 0:8e898e1270d6 121 22. press 'RUN' in the UI. watch the current program run at high speed.
gatedClock 0:8e898e1270d6 122 23. press 'SLOW' in the UI. watch the current program run at slow speed.
gatedClock 0:8e898e1270d6 123 24. press 'STOP' in the UI. the program will stop execution.
gatedClock 0:8e898e1270d6 124
gatedClock 0:8e898e1270d6 125 CPU test function.
gatedClock 0:8e898e1270d6 126 25. press 'TEST' in the UI. the program will load,execute,dump,compare.
gatedClock 0:8e898e1270d6 127 26. tail -f testlog.txt to see test status.
gatedClock 0:8e898e1270d6 128 27. the test will repeat until 'STOP TEST' is pressed.
gatedClock 0:8e898e1270d6 129 28. long test performed by allowing this mode to continue.
gatedClock 0:8e898e1270d6 130
gatedClock 0:8e898e1270d6 131 UI exit function.
gatedClock 0:8e898e1270d6 132 29. press 'EXIT' in the UI. it will exit.
gatedClock 0:8e898e1270d6 133 -----includes-----------------------------------//----------------------------*/
gatedClock 0:8e898e1270d6 134 #include "mbed.h" // general.
gatedClock 0:8e898e1270d6 135 #include "USBSerial.h" // serial over USB.
gatedClock 0:8e898e1270d6 136 #include "C12832_lcd.h" // LCD display.
gatedClock 0:8e898e1270d6 137 #include "rtos.h" // RTOS.
gatedClock 1:a3df81701818 138 #include "mmSPI_RTOS.h" // SPI.
gatedClock 2:4336e18b60fe 139 #include "watchdog_RTOS.h" // watchdog.
gatedClock 0:8e898e1270d6 140 //---defines------------------------------------//------------------------------
gatedClock 0:8e898e1270d6 141 #define LCD1 lcd.locate(0, 0); // LCD line 1.
gatedClock 0:8e898e1270d6 142 #define LCD2 lcd.locate(0,11); // LCD line 2.
gatedClock 0:8e898e1270d6 143 #define LCD3 lcd.locate(0,22); // LCD line 3.
gatedClock 0:8e898e1270d6 144 #define LCD3 lcd.locate(0,22); // LCD line 3.
gatedClock 0:8e898e1270d6 145 #define WATCHDOG_S 10 // watchdog timeout, in seconds.
gatedClock 0:8e898e1270d6 146 #define ERROR_BOOT 1 // 1 means boot rather than error().
gatedClock 0:8e898e1270d6 147 #define SPI_BYTES 8 // number of SPI bytes.
gatedClock 0:8e898e1270d6 148 #define SPI_HZ 100000 // SPI frequency in Hz.
gatedClock 0:8e898e1270d6 149 #define SER_BYTES 18 // serial in/out # of bytes.
gatedClock 0:8e898e1270d6 150 #define SER_ALIGN 7 // '$' location in shift-register.
gatedClock 0:8e898e1270d6 151 #define THREAD_0_WAIT 8 // multitasking wait mS.
gatedClock 0:8e898e1270d6 152 #define THREAD_1_WAIT 2 // multitasking wait mS.
gatedClock 0:8e898e1270d6 153 #define THREAD_2_WAIT 128 // multitasking wait mS.
gatedClock 0:8e898e1270d6 154 #define THREAD_3_WAIT 128 // multitasking wait mS.
gatedClock 0:8e898e1270d6 155 #define HB_MODULO 64 // heartbeat slowdown factor.
gatedClock 0:8e898e1270d6 156 #define POOL_LEN 16 // memory pool dimension.
gatedClock 0:8e898e1270d6 157 #define HCMD_SETREG 1 // host command 'set register'.
gatedClock 0:8e898e1270d6 158 #define HCMD_GETREG 2 // host command 'get register'.
gatedClock 0:8e898e1270d6 159 #define HCMD_SETMM 3 // host command 'set main-memory.'
gatedClock 0:8e898e1270d6 160 #define HCMD_GETMM 4 // host command 'get main-memory.'
gatedClock 0:8e898e1270d6 161 #define HCMD_STEP 5 // host command 'step-CPU'.
gatedClock 0:8e898e1270d6 162 #define HCMD_SETIR 6 // host command 'set-IR'.
gatedClock 0:8e898e1270d6 163 #define HCMD_GETALLREG 7 // host command 'get-all-registers'.
gatedClock 0:8e898e1270d6 164 #define CPU_REG_0 0 // CPU register 0.
gatedClock 0:8e898e1270d6 165 #define CPU_REG_1 1 // CPU register 1.
gatedClock 0:8e898e1270d6 166 #define CPU_REG_2 2 // CPU register 2.
gatedClock 0:8e898e1270d6 167 #define CPU_REG_3 3 // CPU register 3.
gatedClock 0:8e898e1270d6 168 #define CPU_REG_PC 4 // CPU Program Counter.
gatedClock 0:8e898e1270d6 169 #define CPU_IR_H 5 // CPU IR high-byte.
gatedClock 0:8e898e1270d6 170 #define CPU_IR_L 6 // CPU IR low-byte.
gatedClock 0:8e898e1270d6 171 //--externals-----------------------------------//------------------------------
gatedClock 0:8e898e1270d6 172 extern "C" void mbed_reset(); // processor reset.
gatedClock 0:8e898e1270d6 173 //--global_definitions--------------------------//------------------------------
gatedClock 0:8e898e1270d6 174 struct tFromHost // command from host.
gatedClock 0:8e898e1270d6 175 {
gatedClock 0:8e898e1270d6 176 char cCommand; // command from host.
gatedClock 0:8e898e1270d6 177 char cRegisterID; // which CPU register.
gatedClock 0:8e898e1270d6 178 char cRegisterValue; // write this to CPU register.
gatedClock 0:8e898e1270d6 179 char cIRValueH; // write this to IR.
gatedClock 0:8e898e1270d6 180 char cIRValueL; // write this to IR.
gatedClock 0:8e898e1270d6 181 char cMMaddress; // access this MM address.
gatedClock 0:8e898e1270d6 182 char cMMdataH; // MM content high byte.
gatedClock 0:8e898e1270d6 183 char cMMdataL; // MM content low byte.
gatedClock 0:8e898e1270d6 184 };
gatedClock 0:8e898e1270d6 185 MemoryPool<tFromHost, POOL_LEN> mPoolFromHost;
gatedClock 0:8e898e1270d6 186 Queue <tFromHost, POOL_LEN> qFromHost;
gatedClock 0:8e898e1270d6 187
gatedClock 0:8e898e1270d6 188 //----
gatedClock 0:8e898e1270d6 189
gatedClock 0:8e898e1270d6 190 struct tToHost // reply to host.
gatedClock 0:8e898e1270d6 191 {
gatedClock 0:8e898e1270d6 192 char cCommand; // command executed.
gatedClock 0:8e898e1270d6 193 char cRegisterID; // which CPU register read.
gatedClock 0:8e898e1270d6 194 char cRegisterValue; // data from CPU register.
gatedClock 0:8e898e1270d6 195 char cMMaddress; // which MM address read.
gatedClock 0:8e898e1270d6 196 char cMMdataH; // MM content high byte.
gatedClock 0:8e898e1270d6 197 char cMMdataL; // MM content low byte.
gatedClock 0:8e898e1270d6 198 char cReg0; // data from R0.
gatedClock 0:8e898e1270d6 199 char cReg1; // data from R1.
gatedClock 0:8e898e1270d6 200 char cReg2; // data from R2.
gatedClock 0:8e898e1270d6 201 char cReg3; // data from R3.
gatedClock 0:8e898e1270d6 202 char cPC; // data from program counter.
gatedClock 0:8e898e1270d6 203 char cIRH; // high byte from instruction register.
gatedClock 0:8e898e1270d6 204 char cIRL; // low byte from instruction register.
gatedClock 0:8e898e1270d6 205 };
gatedClock 0:8e898e1270d6 206 MemoryPool<tToHost, POOL_LEN> mPoolToHost;
gatedClock 0:8e898e1270d6 207 Queue <tToHost, POOL_LEN> qToHost;
gatedClock 0:8e898e1270d6 208
gatedClock 0:8e898e1270d6 209 Queue<int, POOL_LEN> queueWatchdogThread_0; // main thread watchdog notice.
gatedClock 0:8e898e1270d6 210 Queue<int, POOL_LEN> queueWatchdogThread_1; // thread 1 watchdog notice.
gatedClock 0:8e898e1270d6 211 Queue<int, POOL_LEN> queueWatchdogThread_2; // thread 2 watchdog notice.
gatedClock 0:8e898e1270d6 212 //--global_variables----------------------------//------------------------------
gatedClock 0:8e898e1270d6 213 char gpcSerialFromHost[SER_BYTES]; // incoming serial buffer.
gatedClock 0:8e898e1270d6 214 char gpcSerialToHost [SER_BYTES]; // outgoing serial buffer.
gatedClock 0:8e898e1270d6 215 char gcNewCommand; // new command from host.
gatedClock 0:8e898e1270d6 216 int gdRoundTrip; // +1 from host, -1 to host.
gatedClock 0:8e898e1270d6 217 tToHost * gpToHost; // to-host structure.
gatedClock 0:8e898e1270d6 218 osEvent gqToHostEvent; // incoming message event.
gatedClock 0:8e898e1270d6 219 unsigned long gulSPIclkCount; // SPI clock count.
gatedClock 0:8e898e1270d6 220 unsigned long gulCPUclkCount; // CPU clock count.
gatedClock 0:8e898e1270d6 221 //--global_instances----------------------------//------------------------------
gatedClock 0:8e898e1270d6 222 USBSerial serial; // serial over usb.
gatedClock 0:8e898e1270d6 223 C12832_LCD lcd; // LCD display.
gatedClock 0:8e898e1270d6 224 DigitalOut led0(LED4); // thread heartbeat.
gatedClock 0:8e898e1270d6 225 DigitalOut led1(LED3); // thread heartbeat.
gatedClock 0:8e898e1270d6 226 DigitalOut led2(LED2); // thread heartbeat.
gatedClock 0:8e898e1270d6 227 DigitalOut led3(LED1); // SPI reply underflow warning.
gatedClock 0:8e898e1270d6 228 //-------prototypes-----------------------------//------------------------------
gatedClock 0:8e898e1270d6 229 int main(); // main.
gatedClock 0:8e898e1270d6 230 void processIncomingSerial(); // process incoming host data.
gatedClock 0:8e898e1270d6 231 void processOutgoingSerial(); // process outgoing data to host.
gatedClock 0:8e898e1270d6 232 void SPIprocessingThread(void const *args); // SPI-side processing.
gatedClock 0:8e898e1270d6 233 void diagnosticThread (void const *args); // LCD and LED notifications.
gatedClock 0:8e898e1270d6 234 void watchdogThread (void const *args); // overall watchdog.
gatedClock 0:8e898e1270d6 235 char ascii_nibble_to_binary(char cAscii); // ascii nibble -> binary.
gatedClock 0:8e898e1270d6 236 char binary_to_ascii_nibble(char cBinary); // binary -> ascii nibble.
gatedClock 0:8e898e1270d6 237 void clear_tFromHost(tFromHost *ptFromHost);// initialize structure.
gatedClock 0:8e898e1270d6 238 void clear_tToHost (tToHost *ptToHost); // initialize structure.
gatedClock 0:8e898e1270d6 239 //==============================================//==============================
gatedClock 0:8e898e1270d6 240 int main(void) // USBSerial processing thread.
gatedClock 0:8e898e1270d6 241 {
gatedClock 0:8e898e1270d6 242 int dHeartbeat; // heartbeat counter.
gatedClock 0:8e898e1270d6 243 int dLoop; // loop index.
gatedClock 0:8e898e1270d6 244
gatedClock 0:8e898e1270d6 245 gpToHost = NULL; // initialize global.
gatedClock 0:8e898e1270d6 246 gcNewCommand = 0; // initialize global.
gatedClock 0:8e898e1270d6 247 gdRoundTrip = 1024; // initialize global.
gatedClock 0:8e898e1270d6 248 gulSPIclkCount = 0; // initialize global.
gatedClock 0:8e898e1270d6 249 gulCPUclkCount = 0; // initialize global.
gatedClock 0:8e898e1270d6 250 led0 = 0; // initialize global.
gatedClock 0:8e898e1270d6 251 led1 = 0; // initialize global.
gatedClock 0:8e898e1270d6 252 led2 = 0; // initialize global.
gatedClock 0:8e898e1270d6 253 led3 = 0; // initialize global.
gatedClock 0:8e898e1270d6 254 dHeartbeat = 0; // initialize local.
gatedClock 0:8e898e1270d6 255 dLoop = 0; // initialize local.
gatedClock 0:8e898e1270d6 256
gatedClock 0:8e898e1270d6 257 // BOOT notification.
gatedClock 0:8e898e1270d6 258 lcd.cls(); LCD2; lcd.printf(" BOOT"); wait(1.0);
gatedClock 0:8e898e1270d6 259
gatedClock 0:8e898e1270d6 260 // initialize serial-in shift-register.
gatedClock 0:8e898e1270d6 261 for (dLoop = 0; dLoop < SER_BYTES; dLoop++) gpcSerialFromHost[dLoop] = 0;
gatedClock 0:8e898e1270d6 262
gatedClock 0:8e898e1270d6 263 // thread-out SPI-side processing.
gatedClock 0:8e898e1270d6 264 Thread thread_1(SPIprocessingThread,NULL,osPriorityHigh,DEFAULT_STACK_SIZE,NULL);
gatedClock 0:8e898e1270d6 265
gatedClock 0:8e898e1270d6 266 // thread-out diagnostics.
gatedClock 0:8e898e1270d6 267 Thread thread_2(diagnosticThread, NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL);
gatedClock 0:8e898e1270d6 268
gatedClock 0:8e898e1270d6 269 // thread-out universal watchdog.
gatedClock 0:8e898e1270d6 270 Thread thread_3(watchdogThread, NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL);
gatedClock 0:8e898e1270d6 271
gatedClock 0:8e898e1270d6 272 while(1) // main loop.
gatedClock 0:8e898e1270d6 273 {
gatedClock 0:8e898e1270d6 274 processIncomingSerial(); // process data in from host.
gatedClock 0:8e898e1270d6 275 processOutgoingSerial(); // process data out to host.
gatedClock 0:8e898e1270d6 276
gatedClock 0:8e898e1270d6 277 dHeartbeat++; // thread heartbeat.
gatedClock 0:8e898e1270d6 278 if (!(dHeartbeat % HB_MODULO)) led0 = !led0;
gatedClock 0:8e898e1270d6 279 queueWatchdogThread_0.put((int *) 0,1); // adds 1mS to wait.
gatedClock 0:8e898e1270d6 280 Thread::wait(THREAD_0_WAIT - 1); // multitasking.
gatedClock 0:8e898e1270d6 281 } // main loop.
gatedClock 0:8e898e1270d6 282 } // main.
gatedClock 0:8e898e1270d6 283 /*----------------------------------------------//----------------------------*/
gatedClock 0:8e898e1270d6 284 /*
gatedClock 0:8e898e1270d6 285 the python program running on the host is sending/receiving ascii characters
gatedClock 0:8e898e1270d6 286 which represent command/data binary nibbles. the python program will send
gatedClock 0:8e898e1270d6 287 the '$' character for command-string alignment. this function reads-in the
gatedClock 0:8e898e1270d6 288 incoming serial stream when any serial data is available, into a shift-register,
gatedClock 0:8e898e1270d6 289 and breaks upon detection of the '$' alignment character for python
gatedClock 0:8e898e1270d6 290 command-processing. at that point the shift-register will look something like
gatedClock 0:8e898e1270d6 291 [0] [1] [2] [3] [4] [5] [6] [7]
gatedClock 0:8e898e1270d6 292 '1' '2' '3' '4' x x x '$' (means write 0x34 to CPU R2).
gatedClock 0:8e898e1270d6 293
gatedClock 0:8e898e1270d6 294
gatedClock 0:8e898e1270d6 295 command-host register-number interpretation:
gatedClock 0:8e898e1270d6 296 0 = CPU R0.
gatedClock 0:8e898e1270d6 297 1 = CPU R1.
gatedClock 0:8e898e1270d6 298 2 = CPU R2.
gatedClock 0:8e898e1270d6 299 3 = CPU R3.
gatedClock 0:8e898e1270d6 300 4 = CPU program-counter.
gatedClock 0:8e898e1270d6 301 5 = CPU instruction-register high-byte.
gatedClock 0:8e898e1270d6 302 6 = CPU instruction-register low-byte.
gatedClock 0:8e898e1270d6 303
gatedClock 0:8e898e1270d6 304 instruction-register write is specially implemented,
gatedClock 0:8e898e1270d6 305 instruction-register read is implemented as two standard register-reads.
gatedClock 0:8e898e1270d6 306
gatedClock 0:8e898e1270d6 307 host-command shift-register interpretation:
gatedClock 0:8e898e1270d6 308
gatedClock 0:8e898e1270d6 309 gpcSerialFromHost[0] = command.
gatedClock 0:8e898e1270d6 310 subsequent interpretation depends on the command.
gatedClock 0:8e898e1270d6 311
gatedClock 0:8e898e1270d6 312 ----
gatedClock 0:8e898e1270d6 313 if command = HCMD_SETREG (write-CPU-register) or HCMD_GETREG (read-CPU-register):
gatedClock 0:8e898e1270d6 314
gatedClock 0:8e898e1270d6 315 gpcSerialFromHost[1] = register number (see above).
gatedClock 0:8e898e1270d6 316 gpcSerialFromHost[2] = register content, high nibble.
gatedClock 0:8e898e1270d6 317 gpcSerialFromHost[3] = register content, low nibble.
gatedClock 0:8e898e1270d6 318 gpcSerialFromHost[4] = not used.
gatedClock 0:8e898e1270d6 319 gpcSerialFromHost[5] = not used.
gatedClock 0:8e898e1270d6 320 gpcSerialFromHost[6] = not used.
gatedClock 0:8e898e1270d6 321
gatedClock 0:8e898e1270d6 322 ----
gatedClock 0:8e898e1270d6 323 if command = HCMD_SETIR (write-CPU-instruction-register):
gatedClock 0:8e898e1270d6 324
gatedClock 0:8e898e1270d6 325 gpcSerialFromHost[1] = IR register number, implied anyway.
gatedClock 0:8e898e1270d6 326 gpcSerialFromHost[2] = IR write value high byte high nibble.
gatedClock 0:8e898e1270d6 327 gpcSerialFromHost[3] = IR write value high byte low nibble.
gatedClock 0:8e898e1270d6 328 gpcSerialFromHost[4] = IR write value low byte high nibble.
gatedClock 0:8e898e1270d6 329 gpcSerialFromHost[5] = IR write value low byte low nibble.
gatedClock 0:8e898e1270d6 330 gpcSerialFromHost[6] = not used.
gatedClock 0:8e898e1270d6 331
gatedClock 0:8e898e1270d6 332 ----
gatedClock 0:8e898e1270d6 333 if command = HCMD_SETMM (write to CPU main-memory) or HCMD_GETMM (read from CPU main-memory):
gatedClock 0:8e898e1270d6 334
gatedClock 0:8e898e1270d6 335 gpcSerialFromHost[1] = MM address high nibble.
gatedClock 0:8e898e1270d6 336 gpcSerialFromHost[2] = MM address low nibble.
gatedClock 0:8e898e1270d6 337 gpcSerialFromHost[3] = MM content high byte high nibble.
gatedClock 0:8e898e1270d6 338 gpcSerialFromHost[4] = MM content high byte low nibble.
gatedClock 0:8e898e1270d6 339 gpcSerialFromHost[5] = MM content low byte high nibble.
gatedClock 0:8e898e1270d6 340 gpcSerialFromHost[6] = MM content low byte low nibble.
gatedClock 0:8e898e1270d6 341
gatedClock 0:8e898e1270d6 342 the above also applies to function 'processOutgoingSerial'.
gatedClock 0:8e898e1270d6 343 */
gatedClock 0:8e898e1270d6 344
gatedClock 0:8e898e1270d6 345 void processIncomingSerial(void) // process incoming serial data.
gatedClock 0:8e898e1270d6 346 {
gatedClock 0:8e898e1270d6 347 int dLoop; // loop index.
gatedClock 0:8e898e1270d6 348 tFromHost * pFromHost; // from-host structure.
gatedClock 0:8e898e1270d6 349
gatedClock 0:8e898e1270d6 350 while(serial.available()) // while data from host is available.
gatedClock 0:8e898e1270d6 351 {
gatedClock 0:8e898e1270d6 352 // shift-in the serial stream.
gatedClock 0:8e898e1270d6 353 for (dLoop = 0; dLoop < (SER_BYTES - 1); dLoop++)
gatedClock 0:8e898e1270d6 354 gpcSerialFromHost[dLoop] = gpcSerialFromHost[dLoop + 1];
gatedClock 0:8e898e1270d6 355 gpcSerialFromHost[SER_BYTES - 1] = serial._getc();
gatedClock 0:8e898e1270d6 356
gatedClock 0:8e898e1270d6 357 if (gpcSerialFromHost[SER_ALIGN] == '$')// data from host is aligned.
gatedClock 0:8e898e1270d6 358 {
gatedClock 0:8e898e1270d6 359 gcNewCommand = 1; // new host command just recognised.
gatedClock 0:8e898e1270d6 360 break; // need to process aligned data.
gatedClock 0:8e898e1270d6 361 } // data from host is aligned.
gatedClock 0:8e898e1270d6 362 } // while data from host is available.
gatedClock 0:8e898e1270d6 363
gatedClock 0:8e898e1270d6 364 // even if more data awaits from the
gatedClock 0:8e898e1270d6 365 // incoming serial stream, we now need
gatedClock 0:8e898e1270d6 366 // to process the aligned data recognised
gatedClock 0:8e898e1270d6 367 // as a command from the host.
gatedClock 0:8e898e1270d6 368
gatedClock 0:8e898e1270d6 369 if (gcNewCommand) // execute once per new command.
gatedClock 0:8e898e1270d6 370 {
gatedClock 0:8e898e1270d6 371 pFromHost = mPoolFromHost.alloc(); // allocate next pool entry.
gatedClock 0:8e898e1270d6 372 if (!pFromHost) // failure detection.
gatedClock 0:8e898e1270d6 373 {
gatedClock 0:8e898e1270d6 374 if (ERROR_BOOT) mbed_reset(); else
gatedClock 0:8e898e1270d6 375 error("\n\r processIncomingSerial : FATAL malloc error for pFromHost. \n\r");
gatedClock 0:8e898e1270d6 376 }
gatedClock 0:8e898e1270d6 377
gatedClock 0:8e898e1270d6 378 clear_tFromHost(pFromHost); // initialize structure.
gatedClock 0:8e898e1270d6 379
gatedClock 0:8e898e1270d6 380 // copy-in host message.
gatedClock 0:8e898e1270d6 381 pFromHost->cCommand = ascii_nibble_to_binary(gpcSerialFromHost[0]);
gatedClock 0:8e898e1270d6 382
gatedClock 0:8e898e1270d6 383 //----
gatedClock 0:8e898e1270d6 384
gatedClock 0:8e898e1270d6 385 switch(pFromHost->cCommand) // command dependency.
gatedClock 0:8e898e1270d6 386 {
gatedClock 0:8e898e1270d6 387 case HCMD_SETREG : // host command 'set register'.
gatedClock 0:8e898e1270d6 388 {
gatedClock 0:8e898e1270d6 389 pFromHost->cRegisterID = ascii_nibble_to_binary(gpcSerialFromHost[1]);
gatedClock 0:8e898e1270d6 390 pFromHost->cRegisterValue = ((ascii_nibble_to_binary(gpcSerialFromHost[2])) << 4) +
gatedClock 0:8e898e1270d6 391 ascii_nibble_to_binary(gpcSerialFromHost[3]);
gatedClock 0:8e898e1270d6 392 break;
gatedClock 0:8e898e1270d6 393 } // host command 'set register'.
gatedClock 0:8e898e1270d6 394
gatedClock 0:8e898e1270d6 395 case HCMD_GETREG : // host command 'get register'.
gatedClock 0:8e898e1270d6 396 {
gatedClock 0:8e898e1270d6 397 pFromHost->cRegisterID = ascii_nibble_to_binary(gpcSerialFromHost[1]);
gatedClock 0:8e898e1270d6 398 pFromHost->cRegisterValue = ((ascii_nibble_to_binary(gpcSerialFromHost[2])) << 4) +
gatedClock 0:8e898e1270d6 399 ascii_nibble_to_binary(gpcSerialFromHost[3]);
gatedClock 0:8e898e1270d6 400 gdRoundTrip++; // expected reply to host is pending.
gatedClock 0:8e898e1270d6 401 break;
gatedClock 0:8e898e1270d6 402 } // host command 'get register'.
gatedClock 0:8e898e1270d6 403
gatedClock 0:8e898e1270d6 404 case HCMD_SETMM : // host command 'set main-memory.'
gatedClock 0:8e898e1270d6 405 {
gatedClock 0:8e898e1270d6 406 pFromHost->cMMaddress = ((ascii_nibble_to_binary(gpcSerialFromHost[1])) << 4) +
gatedClock 0:8e898e1270d6 407 ascii_nibble_to_binary(gpcSerialFromHost[2]);
gatedClock 0:8e898e1270d6 408 pFromHost->cMMdataH = ((ascii_nibble_to_binary(gpcSerialFromHost[3])) << 4) +
gatedClock 0:8e898e1270d6 409 ascii_nibble_to_binary(gpcSerialFromHost[4]);
gatedClock 0:8e898e1270d6 410 pFromHost->cMMdataL = ((ascii_nibble_to_binary(gpcSerialFromHost[5])) << 4) +
gatedClock 0:8e898e1270d6 411 ascii_nibble_to_binary(gpcSerialFromHost[6]);
gatedClock 0:8e898e1270d6 412 break;
gatedClock 0:8e898e1270d6 413 } // host command 'set main-memory.'
gatedClock 0:8e898e1270d6 414
gatedClock 0:8e898e1270d6 415 case HCMD_GETMM : // host command 'get main-memory.'
gatedClock 0:8e898e1270d6 416 {
gatedClock 0:8e898e1270d6 417 pFromHost->cMMaddress = ((ascii_nibble_to_binary(gpcSerialFromHost[1])) << 4) +
gatedClock 0:8e898e1270d6 418 ascii_nibble_to_binary(gpcSerialFromHost[2]);
gatedClock 0:8e898e1270d6 419 pFromHost->cMMdataH = ((ascii_nibble_to_binary(gpcSerialFromHost[3])) << 4) +
gatedClock 0:8e898e1270d6 420 ascii_nibble_to_binary(gpcSerialFromHost[4]);
gatedClock 0:8e898e1270d6 421 pFromHost->cMMdataL = ((ascii_nibble_to_binary(gpcSerialFromHost[5])) << 4) +
gatedClock 0:8e898e1270d6 422 ascii_nibble_to_binary(gpcSerialFromHost[6]);
gatedClock 0:8e898e1270d6 423
gatedClock 0:8e898e1270d6 424 gdRoundTrip++; // expected reply to host is pending.
gatedClock 0:8e898e1270d6 425 break;
gatedClock 0:8e898e1270d6 426 } // host command 'get main-memory.'
gatedClock 0:8e898e1270d6 427
gatedClock 0:8e898e1270d6 428 case HCMD_STEP : // host command 'step-CPU'.
gatedClock 0:8e898e1270d6 429 {
gatedClock 0:8e898e1270d6 430 break;
gatedClock 0:8e898e1270d6 431 } // host command 'step-CPU'.
gatedClock 0:8e898e1270d6 432
gatedClock 0:8e898e1270d6 433 case HCMD_SETIR : // host command 'set-IR'.
gatedClock 0:8e898e1270d6 434 {
gatedClock 0:8e898e1270d6 435 pFromHost->cIRValueH = ((ascii_nibble_to_binary(gpcSerialFromHost[2])) << 4) +
gatedClock 0:8e898e1270d6 436 ascii_nibble_to_binary(gpcSerialFromHost[3]);
gatedClock 0:8e898e1270d6 437 pFromHost->cIRValueL = ((ascii_nibble_to_binary(gpcSerialFromHost[4])) << 4) +
gatedClock 0:8e898e1270d6 438 ascii_nibble_to_binary(gpcSerialFromHost[5]);
gatedClock 0:8e898e1270d6 439 break;
gatedClock 0:8e898e1270d6 440 } // host command 'set-IR'.
gatedClock 0:8e898e1270d6 441
gatedClock 0:8e898e1270d6 442 case HCMD_GETALLREG : // host command 'get-all-registers'.
gatedClock 0:8e898e1270d6 443 {
gatedClock 0:8e898e1270d6 444 gdRoundTrip++; // expected reply to host is pending.
gatedClock 0:8e898e1270d6 445 break;
gatedClock 0:8e898e1270d6 446 } // host command 'get-all-registers'.
gatedClock 0:8e898e1270d6 447
gatedClock 0:8e898e1270d6 448 default : // default.
gatedClock 0:8e898e1270d6 449 {
gatedClock 0:8e898e1270d6 450 if (ERROR_BOOT) mbed_reset(); else
gatedClock 0:8e898e1270d6 451 error("\n\r processIncomingSerial : ERROR unrecognised command from host. \n\r");
gatedClock 0:8e898e1270d6 452 break;
gatedClock 0:8e898e1270d6 453 } // default.
gatedClock 0:8e898e1270d6 454 } // command dependency.
gatedClock 0:8e898e1270d6 455
gatedClock 0:8e898e1270d6 456 //----
gatedClock 0:8e898e1270d6 457
gatedClock 0:8e898e1270d6 458 qFromHost.put(pFromHost); // send out for processing.
gatedClock 0:8e898e1270d6 459 gcNewCommand = 0; // don't execute until next new command.
gatedClock 0:8e898e1270d6 460 } // execute once per new command.
gatedClock 0:8e898e1270d6 461 Thread::wait(THREAD_0_WAIT); // multitasking.
gatedClock 0:8e898e1270d6 462 } // processIncomingSerial
gatedClock 0:8e898e1270d6 463 /*----------------------------------------------//----------------------------*/
gatedClock 0:8e898e1270d6 464 void processOutgoingSerial(void) // prepare/transmit data to host.
gatedClock 0:8e898e1270d6 465 {
gatedClock 0:8e898e1270d6 466 int dLoop; // loop index.
gatedClock 0:8e898e1270d6 467
gatedClock 0:8e898e1270d6 468 gqToHostEvent = qToHost.get(1); // check for reply back to host.
gatedClock 0:8e898e1270d6 469
gatedClock 0:8e898e1270d6 470 // if new reply to host:
gatedClock 0:8e898e1270d6 471 if (gqToHostEvent.status == osEventMessage)
gatedClock 0:8e898e1270d6 472 {
gatedClock 0:8e898e1270d6 473 // bring it in from the queue.
gatedClock 0:8e898e1270d6 474 gpToHost = (tToHost *) gqToHostEvent.value.p;
gatedClock 0:8e898e1270d6 475 if (!gpToHost) // failure detection.
gatedClock 0:8e898e1270d6 476 {
gatedClock 0:8e898e1270d6 477 if (ERROR_BOOT) mbed_reset(); else
gatedClock 0:8e898e1270d6 478 error("\n\r processOutgoingSerial : FATAL NULL gpToHost pointer. \n\r");
gatedClock 0:8e898e1270d6 479 }
gatedClock 0:8e898e1270d6 480
gatedClock 0:8e898e1270d6 481 // clear outgoing buffer.
gatedClock 0:8e898e1270d6 482 for (dLoop = 0; dLoop < SER_BYTES; dLoop++) gpcSerialToHost[dLoop] = 0;
gatedClock 0:8e898e1270d6 483
gatedClock 0:8e898e1270d6 484 switch(gpToHost->cCommand) // the from-host command was looped to here.
gatedClock 0:8e898e1270d6 485 {
gatedClock 0:8e898e1270d6 486 case HCMD_SETREG : // host command 'set register'.
gatedClock 0:8e898e1270d6 487 {
gatedClock 0:8e898e1270d6 488 break;
gatedClock 0:8e898e1270d6 489 } // host command 'set register'.
gatedClock 0:8e898e1270d6 490
gatedClock 0:8e898e1270d6 491 case HCMD_GETREG : // host command 'get register'.
gatedClock 0:8e898e1270d6 492 {
gatedClock 0:8e898e1270d6 493 gpcSerialToHost[0] = binary_to_ascii_nibble( gpToHost->cCommand);
gatedClock 0:8e898e1270d6 494 gpcSerialToHost[1] = binary_to_ascii_nibble( gpToHost->cRegisterID);
gatedClock 0:8e898e1270d6 495 gpcSerialToHost[2] = binary_to_ascii_nibble(((gpToHost->cRegisterValue) >> 4) & 0x0F);
gatedClock 0:8e898e1270d6 496 gpcSerialToHost[3] = binary_to_ascii_nibble(((gpToHost->cRegisterValue) >> 0) & 0x0F);
gatedClock 0:8e898e1270d6 497 gpcSerialToHost[4] = '\n'; // signals end of transfer.
gatedClock 0:8e898e1270d6 498
gatedClock 0:8e898e1270d6 499 // transmit to the host.
gatedClock 0:8e898e1270d6 500 serial.writeBlock((uint8_t *) gpcSerialToHost, (uint16_t) SER_BYTES);
gatedClock 0:8e898e1270d6 501 gdRoundTrip--; // expected reply sent to host.
gatedClock 0:8e898e1270d6 502 break;
gatedClock 0:8e898e1270d6 503 } // host command 'get register'.
gatedClock 0:8e898e1270d6 504
gatedClock 0:8e898e1270d6 505 case HCMD_SETMM : // host command 'set main-memory.'
gatedClock 0:8e898e1270d6 506 {
gatedClock 0:8e898e1270d6 507 break;
gatedClock 0:8e898e1270d6 508 } // host command 'set main-memory.'
gatedClock 0:8e898e1270d6 509
gatedClock 0:8e898e1270d6 510 case HCMD_GETMM : // host command 'get main-memory.'
gatedClock 0:8e898e1270d6 511 {
gatedClock 0:8e898e1270d6 512 gpcSerialToHost[0] = binary_to_ascii_nibble( gpToHost->cCommand);
gatedClock 0:8e898e1270d6 513 gpcSerialToHost[1] = binary_to_ascii_nibble(((gpToHost->cMMaddress) >> 4) & 0x0F);
gatedClock 0:8e898e1270d6 514 gpcSerialToHost[2] = binary_to_ascii_nibble(((gpToHost->cMMaddress) >> 0) & 0x0F);
gatedClock 0:8e898e1270d6 515 gpcSerialToHost[3] = binary_to_ascii_nibble(((gpToHost->cMMdataH ) >> 4) & 0x0F);
gatedClock 0:8e898e1270d6 516 gpcSerialToHost[4] = binary_to_ascii_nibble(((gpToHost->cMMdataH ) >> 0) & 0x0F);
gatedClock 0:8e898e1270d6 517 gpcSerialToHost[5] = binary_to_ascii_nibble(((gpToHost->cMMdataL ) >> 4) & 0x0F);
gatedClock 0:8e898e1270d6 518 gpcSerialToHost[6] = binary_to_ascii_nibble(((gpToHost->cMMdataL ) >> 0) & 0x0F);
gatedClock 0:8e898e1270d6 519 gpcSerialToHost[7] = '\n'; // signals end of transfer.
gatedClock 0:8e898e1270d6 520
gatedClock 0:8e898e1270d6 521 // transmit to the host.
gatedClock 0:8e898e1270d6 522 serial.writeBlock((uint8_t *) gpcSerialToHost, (uint16_t) SER_BYTES);
gatedClock 0:8e898e1270d6 523 gdRoundTrip--; // expected reply sent to host.
gatedClock 0:8e898e1270d6 524 break;
gatedClock 0:8e898e1270d6 525 } // host command 'get main-memory.'
gatedClock 0:8e898e1270d6 526
gatedClock 0:8e898e1270d6 527 case HCMD_STEP : // host command 'step-CPU'.
gatedClock 0:8e898e1270d6 528 {
gatedClock 0:8e898e1270d6 529 break;
gatedClock 0:8e898e1270d6 530 } // host command 'step-CPU'.
gatedClock 0:8e898e1270d6 531
gatedClock 0:8e898e1270d6 532 case HCMD_SETIR : // host command 'set-IR'.
gatedClock 0:8e898e1270d6 533 {
gatedClock 0:8e898e1270d6 534 break;
gatedClock 0:8e898e1270d6 535 } // host command 'set-IR'.
gatedClock 0:8e898e1270d6 536
gatedClock 0:8e898e1270d6 537 case HCMD_GETALLREG : // host command 'get-all-registers'.
gatedClock 0:8e898e1270d6 538 {
gatedClock 0:8e898e1270d6 539 gpcSerialToHost[ 0] = binary_to_ascii_nibble( gpToHost->cCommand);
gatedClock 0:8e898e1270d6 540 gpcSerialToHost[ 1] = binary_to_ascii_nibble(((gpToHost->cReg0) >> 4) & 0x0F);
gatedClock 0:8e898e1270d6 541 gpcSerialToHost[ 2] = binary_to_ascii_nibble(((gpToHost->cReg0) >> 0) & 0x0F);
gatedClock 0:8e898e1270d6 542 gpcSerialToHost[ 3] = binary_to_ascii_nibble(((gpToHost->cReg1) >> 4) & 0x0F);
gatedClock 0:8e898e1270d6 543 gpcSerialToHost[ 4] = binary_to_ascii_nibble(((gpToHost->cReg1) >> 0) & 0x0F);
gatedClock 0:8e898e1270d6 544 gpcSerialToHost[ 5] = binary_to_ascii_nibble(((gpToHost->cReg2) >> 4) & 0x0F);
gatedClock 0:8e898e1270d6 545 gpcSerialToHost[ 6] = binary_to_ascii_nibble(((gpToHost->cReg2) >> 0) & 0x0F);
gatedClock 0:8e898e1270d6 546 gpcSerialToHost[ 7] = binary_to_ascii_nibble(((gpToHost->cReg3) >> 4) & 0x0F);
gatedClock 0:8e898e1270d6 547 gpcSerialToHost[ 8] = binary_to_ascii_nibble(((gpToHost->cReg3) >> 0) & 0x0F);
gatedClock 0:8e898e1270d6 548 gpcSerialToHost[ 9] = binary_to_ascii_nibble(((gpToHost->cPC) >> 4) & 0x0F);
gatedClock 0:8e898e1270d6 549 gpcSerialToHost[10] = binary_to_ascii_nibble(((gpToHost->cPC) >> 0) & 0x0F);
gatedClock 0:8e898e1270d6 550 gpcSerialToHost[11] = binary_to_ascii_nibble(((gpToHost->cIRH) >> 4) & 0x0F);
gatedClock 0:8e898e1270d6 551 gpcSerialToHost[12] = binary_to_ascii_nibble(((gpToHost->cIRH) >> 0) & 0x0F);
gatedClock 0:8e898e1270d6 552 gpcSerialToHost[13] = binary_to_ascii_nibble(((gpToHost->cIRL) >> 4) & 0x0F);
gatedClock 0:8e898e1270d6 553 gpcSerialToHost[14] = binary_to_ascii_nibble(((gpToHost->cIRL) >> 0) & 0x0F);
gatedClock 0:8e898e1270d6 554 gpcSerialToHost[15] = '\n'; // signals end of transfer.
gatedClock 0:8e898e1270d6 555
gatedClock 0:8e898e1270d6 556 // transmit to the host.
gatedClock 0:8e898e1270d6 557 serial.writeBlock((uint8_t *) gpcSerialToHost, (uint16_t) SER_BYTES);
gatedClock 0:8e898e1270d6 558 gdRoundTrip--; // expected reply sent to host.
gatedClock 0:8e898e1270d6 559 break;
gatedClock 0:8e898e1270d6 560 } // host command 'get-all-registers'.
gatedClock 0:8e898e1270d6 561
gatedClock 0:8e898e1270d6 562 default :
gatedClock 0:8e898e1270d6 563 {
gatedClock 0:8e898e1270d6 564 if (ERROR_BOOT) mbed_reset(); else
gatedClock 0:8e898e1270d6 565 error("\n\r processOutgoingSerial : ERROR unrecognised command from host. \n\r");
gatedClock 0:8e898e1270d6 566 break;
gatedClock 0:8e898e1270d6 567 } // default.
gatedClock 0:8e898e1270d6 568 } // switch(gpToHost->cCommand)
gatedClock 0:8e898e1270d6 569
gatedClock 0:8e898e1270d6 570 mPoolToHost.free(gpToHost); // done with this queue entry.
gatedClock 0:8e898e1270d6 571 gpToHost = NULL; // clear pointer.
gatedClock 0:8e898e1270d6 572 } // if new reply to host.
gatedClock 0:8e898e1270d6 573 } // processOutgoingSerial.
gatedClock 0:8e898e1270d6 574 /*----------------------------------------------//----------------------------*/
gatedClock 0:8e898e1270d6 575 // the pcSendBuffer and pcReceiveBuffer arrays are not used by this function,
gatedClock 0:8e898e1270d6 576 // but they are declared by this function, and their pointers are passed
gatedClock 1:a3df81701818 577 // down to the mmSPI_RTOS library for its use of them.
gatedClock 0:8e898e1270d6 578 // note- the prefix 'pc' means 'pointer of type character', not 'personal computer'.
gatedClock 0:8e898e1270d6 579
gatedClock 0:8e898e1270d6 580 void SPIprocessingThread(void const *args) // process host-commands via SPI.
gatedClock 0:8e898e1270d6 581 {
gatedClock 1:a3df81701818 582 char pcSendBuffer [SPI_BYTES]; // SPI send buffer.
gatedClock 1:a3df81701818 583 char pcReceiveBuffer[SPI_BYTES]; // SPI receive buffer.
gatedClock 1:a3df81701818 584 char pcRegisters [SPI_BYTES]; // fetch-all-registers vector.
gatedClock 1:a3df81701818 585 int dHeartbeat; // heartbeat counter.
gatedClock 1:a3df81701818 586 int dMemoryRead; // read main-memory into this.
gatedClock 1:a3df81701818 587 int dLoop; // loop index.
gatedClock 1:a3df81701818 588 osEvent qFromHostEvent; // incoming message event.
gatedClock 1:a3df81701818 589 tFromHost * pFromHost; // message structure.
gatedClock 1:a3df81701818 590 tToHost * gpToHost; // message structure.
gatedClock 1:a3df81701818 591 mmSPI_RTOS * pSPI; // SPI.
gatedClock 0:8e898e1270d6 592
gatedClock 0:8e898e1270d6 593 pFromHost = NULL; // NULL pointers.
gatedClock 0:8e898e1270d6 594 gpToHost = NULL;
gatedClock 0:8e898e1270d6 595 pSPI = NULL;
gatedClock 0:8e898e1270d6 596 dHeartbeat = 0; // clear variables.
gatedClock 0:8e898e1270d6 597 dMemoryRead = 0;
gatedClock 0:8e898e1270d6 598 dLoop = 0;
gatedClock 0:8e898e1270d6 599 // clear SPI vectors.
gatedClock 0:8e898e1270d6 600 for (dLoop = 0; dLoop < SPI_BYTES; dLoop++) pcSendBuffer [dLoop] = 0;
gatedClock 0:8e898e1270d6 601 for (dLoop = 0; dLoop < SPI_BYTES; dLoop++) pcReceiveBuffer[dLoop] = 0;
gatedClock 0:8e898e1270d6 602
gatedClock 1:a3df81701818 603 pSPI = new mmSPI_RTOS; // SPI allocation.
gatedClock 0:8e898e1270d6 604 if (!pSPI) // failure detection.
gatedClock 0:8e898e1270d6 605 {
gatedClock 0:8e898e1270d6 606 if (ERROR_BOOT) mbed_reset(); else
gatedClock 0:8e898e1270d6 607 error("\n\r SPIprocessingThread : FATAL new error for pSPI. \n\r");
gatedClock 0:8e898e1270d6 608 }
gatedClock 0:8e898e1270d6 609
gatedClock 0:8e898e1270d6 610 pSPI->setSendBuffer (pcSendBuffer); // set SPI send buffer.
gatedClock 0:8e898e1270d6 611 pSPI->setReceiveBuffer(pcReceiveBuffer); // set SPI receive buffer.
gatedClock 0:8e898e1270d6 612 pSPI->setNumberOfBytes(SPI_BYTES); // set SPI number of bytes.
gatedClock 0:8e898e1270d6 613 pSPI->setSPIfrequency (SPI_HZ); // set SPI clock frequency.
gatedClock 0:8e898e1270d6 614
gatedClock 0:8e898e1270d6 615 while(1) // thread loop.
gatedClock 0:8e898e1270d6 616 {
gatedClock 0:8e898e1270d6 617 qFromHostEvent = qFromHost.get(1); // check for incoming host command.
gatedClock 0:8e898e1270d6 618
gatedClock 0:8e898e1270d6 619 // if new host command:
gatedClock 0:8e898e1270d6 620 if (qFromHostEvent.status == osEventMessage)
gatedClock 0:8e898e1270d6 621 {
gatedClock 0:8e898e1270d6 622 // bring it in from the queue.
gatedClock 0:8e898e1270d6 623 pFromHost = (tFromHost *) qFromHostEvent.value.p;
gatedClock 0:8e898e1270d6 624 if (!pFromHost) // failure detection.
gatedClock 0:8e898e1270d6 625 {
gatedClock 0:8e898e1270d6 626 if (ERROR_BOOT) mbed_reset(); else
gatedClock 0:8e898e1270d6 627 error("\n\r SPIprocessingThread : FATAL NULL pFromHost pointer. \n\r");
gatedClock 0:8e898e1270d6 628 }
gatedClock 0:8e898e1270d6 629
gatedClock 0:8e898e1270d6 630 switch(pFromHost->cCommand) // host command decode.
gatedClock 0:8e898e1270d6 631 {
gatedClock 0:8e898e1270d6 632 case HCMD_SETREG : // set CPU register.
gatedClock 0:8e898e1270d6 633 {
gatedClock 0:8e898e1270d6 634 switch(pFromHost->cRegisterID) // which register to write to.
gatedClock 0:8e898e1270d6 635 {
gatedClock 0:8e898e1270d6 636 case CPU_REG_0 : {pSPI->write_register(CPU_REG_0 , pFromHost->cRegisterValue); break;}
gatedClock 0:8e898e1270d6 637 case CPU_REG_1 : {pSPI->write_register(CPU_REG_1 , pFromHost->cRegisterValue); break;}
gatedClock 0:8e898e1270d6 638 case CPU_REG_2 : {pSPI->write_register(CPU_REG_2 , pFromHost->cRegisterValue); break;}
gatedClock 0:8e898e1270d6 639 case CPU_REG_3 : {pSPI->write_register(CPU_REG_3 , pFromHost->cRegisterValue); break;}
gatedClock 0:8e898e1270d6 640 case CPU_REG_PC : {pSPI->write_register(CPU_REG_PC, pFromHost->cRegisterValue); break;}
gatedClock 0:8e898e1270d6 641 default : {break;}
gatedClock 0:8e898e1270d6 642 } // which register to write to.
gatedClock 0:8e898e1270d6 643 break;
gatedClock 0:8e898e1270d6 644 } // set CPU register.
gatedClock 0:8e898e1270d6 645
gatedClock 0:8e898e1270d6 646 case HCMD_SETIR: // set instruction register.
gatedClock 0:8e898e1270d6 647 {
gatedClock 0:8e898e1270d6 648 pSPI->write_IR(pFromHost->cIRValueH, pFromHost->cIRValueL);
gatedClock 0:8e898e1270d6 649 break;
gatedClock 0:8e898e1270d6 650 } // set instruction register.
gatedClock 0:8e898e1270d6 651
gatedClock 0:8e898e1270d6 652 case HCMD_GETREG : // get CPU register.
gatedClock 0:8e898e1270d6 653 {
gatedClock 0:8e898e1270d6 654 gpToHost = mPoolToHost.alloc(); // allocate next pool entry.
gatedClock 0:8e898e1270d6 655 if (!gpToHost) // failure detection.
gatedClock 0:8e898e1270d6 656 {
gatedClock 0:8e898e1270d6 657 if (ERROR_BOOT) mbed_reset(); else
gatedClock 0:8e898e1270d6 658 error("\n\r SPIprocessingThread : FATAL malloc error for gpToHost. \n\r");
gatedClock 0:8e898e1270d6 659 }
gatedClock 0:8e898e1270d6 660
gatedClock 0:8e898e1270d6 661 clear_tToHost(gpToHost); // initialize structure.
gatedClock 0:8e898e1270d6 662
gatedClock 0:8e898e1270d6 663 switch(pFromHost->cRegisterID) // which register to read from.
gatedClock 0:8e898e1270d6 664 {
gatedClock 0:8e898e1270d6 665 case CPU_REG_0 : {gpToHost->cRegisterValue = pSPI->read_register(CPU_REG_0 ); break;}
gatedClock 0:8e898e1270d6 666 case CPU_REG_1 : {gpToHost->cRegisterValue = pSPI->read_register(CPU_REG_1 ); break;}
gatedClock 0:8e898e1270d6 667 case CPU_REG_2 : {gpToHost->cRegisterValue = pSPI->read_register(CPU_REG_2 ); break;}
gatedClock 0:8e898e1270d6 668 case CPU_REG_3 : {gpToHost->cRegisterValue = pSPI->read_register(CPU_REG_3 ); break;}
gatedClock 0:8e898e1270d6 669 case CPU_REG_PC : {gpToHost->cRegisterValue = pSPI->read_register(CPU_REG_PC); break;}
gatedClock 0:8e898e1270d6 670 case CPU_IR_H : {gpToHost->cRegisterValue = pSPI->read_register(CPU_IR_H ); break;}
gatedClock 0:8e898e1270d6 671 case CPU_IR_L : {gpToHost->cRegisterValue = pSPI->read_register(CPU_IR_L ); break;}
gatedClock 0:8e898e1270d6 672 default : {break;}
gatedClock 0:8e898e1270d6 673 } // which register to read from.
gatedClock 0:8e898e1270d6 674
gatedClock 0:8e898e1270d6 675 // loop-back to host.
gatedClock 0:8e898e1270d6 676 gpToHost->cCommand = pFromHost->cCommand;
gatedClock 0:8e898e1270d6 677 gpToHost->cRegisterID = pFromHost->cRegisterID;
gatedClock 0:8e898e1270d6 678
gatedClock 0:8e898e1270d6 679 qToHost.put(gpToHost); // send up for processing.
gatedClock 0:8e898e1270d6 680 break;
gatedClock 0:8e898e1270d6 681 } // get CPU register.
gatedClock 0:8e898e1270d6 682
gatedClock 0:8e898e1270d6 683 case HCMD_GETALLREG : // get all CPU registers.
gatedClock 0:8e898e1270d6 684 {
gatedClock 0:8e898e1270d6 685 gpToHost = mPoolToHost.alloc(); // allocate next pool entry.
gatedClock 0:8e898e1270d6 686 if (!gpToHost) // failure detection.
gatedClock 0:8e898e1270d6 687 {
gatedClock 0:8e898e1270d6 688 if (ERROR_BOOT) mbed_reset(); else
gatedClock 0:8e898e1270d6 689 error("\n\r SPIprocessingThread : FATAL malloc error for gpToHost. \n\r");
gatedClock 0:8e898e1270d6 690 }
gatedClock 0:8e898e1270d6 691
gatedClock 0:8e898e1270d6 692 clear_tToHost(gpToHost); // initialize structure.
gatedClock 0:8e898e1270d6 693
gatedClock 0:8e898e1270d6 694 // tell SPI to return all reg content.
gatedClock 0:8e898e1270d6 695 pSPI->read_all_registers(pcRegisters);
gatedClock 0:8e898e1270d6 696
gatedClock 0:8e898e1270d6 697 gpToHost->cReg0 = pcRegisters[6]; // transfer to outgoing structure.
gatedClock 0:8e898e1270d6 698 gpToHost->cReg1 = pcRegisters[5];
gatedClock 0:8e898e1270d6 699 gpToHost->cReg2 = pcRegisters[4];
gatedClock 0:8e898e1270d6 700 gpToHost->cReg3 = pcRegisters[3];
gatedClock 0:8e898e1270d6 701 gpToHost->cPC = pcRegisters[2];
gatedClock 0:8e898e1270d6 702 gpToHost->cIRH = pcRegisters[1];
gatedClock 0:8e898e1270d6 703 gpToHost->cIRL = pcRegisters[0];
gatedClock 0:8e898e1270d6 704
gatedClock 0:8e898e1270d6 705 // loop-back to host.
gatedClock 0:8e898e1270d6 706 gpToHost->cCommand = pFromHost->cCommand;
gatedClock 0:8e898e1270d6 707 qToHost.put(gpToHost); // send up for processing.
gatedClock 0:8e898e1270d6 708
gatedClock 0:8e898e1270d6 709 break;
gatedClock 0:8e898e1270d6 710 } // get all CPU registers.
gatedClock 0:8e898e1270d6 711
gatedClock 0:8e898e1270d6 712 case HCMD_SETMM : // do main-memory write.
gatedClock 0:8e898e1270d6 713 {
gatedClock 0:8e898e1270d6 714 pSPI->write_memory(pFromHost->cMMdataH, pFromHost->cMMdataL, pFromHost->cMMaddress);
gatedClock 0:8e898e1270d6 715 break;
gatedClock 0:8e898e1270d6 716 } // do main-memory write.
gatedClock 0:8e898e1270d6 717
gatedClock 0:8e898e1270d6 718 case HCMD_GETMM : // do main-memory read.
gatedClock 0:8e898e1270d6 719 {
gatedClock 0:8e898e1270d6 720 gpToHost = mPoolToHost.alloc(); // allocate next pool entry.
gatedClock 0:8e898e1270d6 721 if (!gpToHost) // failure detection.
gatedClock 0:8e898e1270d6 722 {
gatedClock 0:8e898e1270d6 723 if (ERROR_BOOT) mbed_reset(); else
gatedClock 0:8e898e1270d6 724 error("\n\r SPIprocessingThread : FATAL malloc error for gpToHost. \n\r");
gatedClock 0:8e898e1270d6 725 }
gatedClock 0:8e898e1270d6 726
gatedClock 0:8e898e1270d6 727 clear_tToHost(gpToHost); // initialize structure.
gatedClock 0:8e898e1270d6 728
gatedClock 0:8e898e1270d6 729 // read from CPU memory.
gatedClock 0:8e898e1270d6 730 dMemoryRead = pSPI->read_memory(pFromHost->cMMaddress);
gatedClock 0:8e898e1270d6 731 gpToHost->cMMdataH = (dMemoryRead >> 8) & 0xFF;
gatedClock 0:8e898e1270d6 732 gpToHost->cMMdataL = (dMemoryRead >> 0) & 0xFF;
gatedClock 0:8e898e1270d6 733
gatedClock 0:8e898e1270d6 734 // loop-back to host.
gatedClock 0:8e898e1270d6 735 gpToHost->cCommand = pFromHost->cCommand;
gatedClock 0:8e898e1270d6 736 gpToHost->cMMaddress = pFromHost->cMMaddress;
gatedClock 0:8e898e1270d6 737
gatedClock 0:8e898e1270d6 738 qToHost.put(gpToHost); // send up for processing.
gatedClock 0:8e898e1270d6 739 break;
gatedClock 0:8e898e1270d6 740 } // do main-memory read.
gatedClock 0:8e898e1270d6 741
gatedClock 0:8e898e1270d6 742 case HCMD_STEP : // step the CPU.
gatedClock 0:8e898e1270d6 743 {
gatedClock 0:8e898e1270d6 744 pSPI->step();
gatedClock 0:8e898e1270d6 745 break;
gatedClock 0:8e898e1270d6 746 } // step the CPU.
gatedClock 0:8e898e1270d6 747 default : break;
gatedClock 0:8e898e1270d6 748 } // host command decode.
gatedClock 0:8e898e1270d6 749 mPoolFromHost.free(pFromHost); // done with this queue entry.
gatedClock 0:8e898e1270d6 750 pFromHost = NULL; // clear pointer.
gatedClock 0:8e898e1270d6 751 } // if new host command.
gatedClock 0:8e898e1270d6 752
gatedClock 0:8e898e1270d6 753 gulSPIclkCount = pSPI->SPIClockCount(); // propagate to global variable.
gatedClock 0:8e898e1270d6 754 gulCPUclkCount = pSPI->CPUClockCount(); // propagate to global variable.
gatedClock 0:8e898e1270d6 755
gatedClock 0:8e898e1270d6 756 // thread heartbeat.
gatedClock 0:8e898e1270d6 757 dHeartbeat++; if (!(dHeartbeat % HB_MODULO)) led1 = !led1;
gatedClock 0:8e898e1270d6 758 queueWatchdogThread_1.put((int *) 0,1); // adds 1mS to wait.
gatedClock 0:8e898e1270d6 759 Thread::wait(THREAD_1_WAIT - 1); // cooperative multitasking.
gatedClock 0:8e898e1270d6 760 } // thread loop.
gatedClock 0:8e898e1270d6 761 } // SPIprocessingThread.
gatedClock 0:8e898e1270d6 762 /*----------------------------------------------//----------------------------*/
gatedClock 0:8e898e1270d6 763 void diagnosticThread(void const *args) // LCD notification & error check.
gatedClock 0:8e898e1270d6 764 {
gatedClock 0:8e898e1270d6 765 // track previous values.
gatedClock 0:8e898e1270d6 766 static unsigned long ulLastSPIclkCount = 1;
gatedClock 0:8e898e1270d6 767 static unsigned long ulLastCPUclkCount = 1;
gatedClock 0:8e898e1270d6 768 int dHeartbeat; // heartbeat counter.
gatedClock 0:8e898e1270d6 769
gatedClock 0:8e898e1270d6 770 dHeartbeat = 0; // initialize.
gatedClock 0:8e898e1270d6 771
gatedClock 0:8e898e1270d6 772 while(1) // thread loop.
gatedClock 0:8e898e1270d6 773 {
gatedClock 0:8e898e1270d6 774 // if message round trip
gatedClock 0:8e898e1270d6 775 // count not consistent.
gatedClock 0:8e898e1270d6 776 if (gdRoundTrip > 1025 || gdRoundTrip < 1024)
gatedClock 0:8e898e1270d6 777 {
gatedClock 0:8e898e1270d6 778 if (ERROR_BOOT) mbed_reset(); else
gatedClock 0:8e898e1270d6 779 error("\n\r diagnosticThread : ERROR serial reply underflow. \n\r");
gatedClock 0:8e898e1270d6 780 }
gatedClock 0:8e898e1270d6 781
gatedClock 0:8e898e1270d6 782 // update LCD only if a display
gatedClock 0:8e898e1270d6 783 // value has changed. anti-blink,
gatedClock 0:8e898e1270d6 784 // save a bit of power.
gatedClock 0:8e898e1270d6 785 if (gulSPIclkCount != ulLastSPIclkCount ||
gatedClock 0:8e898e1270d6 786 gulCPUclkCount != ulLastCPUclkCount )
gatedClock 0:8e898e1270d6 787 {
gatedClock 0:8e898e1270d6 788 lcd.cls(); // clear LCD display.
gatedClock 0:8e898e1270d6 789 LCD1; // lcd line 1.
gatedClock 0:8e898e1270d6 790 lcd.printf(" RTOS CLASS PROJECT");
gatedClock 0:8e898e1270d6 791
gatedClock 0:8e898e1270d6 792 LCD2; // lcd line 2.
gatedClock 0:8e898e1270d6 793 lcd.printf(" %11lu = SPI clocks",gulSPIclkCount);
gatedClock 0:8e898e1270d6 794
gatedClock 0:8e898e1270d6 795 LCD3; // lcd line 3.
gatedClock 0:8e898e1270d6 796 lcd.printf(" %11lu = CPU clocks",gulCPUclkCount);
gatedClock 0:8e898e1270d6 797 }
gatedClock 0:8e898e1270d6 798
gatedClock 0:8e898e1270d6 799 ulLastSPIclkCount = gulSPIclkCount; // pipeline.
gatedClock 0:8e898e1270d6 800 ulLastCPUclkCount = gulCPUclkCount; // pipeline.
gatedClock 0:8e898e1270d6 801
gatedClock 0:8e898e1270d6 802 dHeartbeat++; // thread heartbeat.
gatedClock 0:8e898e1270d6 803 if (!(dHeartbeat % HB_MODULO)) led2 = !led2;
gatedClock 0:8e898e1270d6 804 queueWatchdogThread_2.put((int *) 0,1); // adds 1mS to wait.
gatedClock 0:8e898e1270d6 805 Thread::wait(THREAD_2_WAIT - 1); // multitasking.
gatedClock 0:8e898e1270d6 806 } // thread loop.
gatedClock 0:8e898e1270d6 807 } // diagnosticThread.
gatedClock 0:8e898e1270d6 808 /*----------------------------------------------//----------------------------*/
gatedClock 0:8e898e1270d6 809 // this is its own watchdog.
gatedClock 0:8e898e1270d6 810
gatedClock 0:8e898e1270d6 811 void watchdogThread(void const *args) // overall watchdog.
gatedClock 0:8e898e1270d6 812 {
gatedClock 2:4336e18b60fe 813 int dHeartbeat; // heartbeat counter.
gatedClock 2:4336e18b60fe 814 Watchdog_RTOS watchdog; // the one and only watchdog.
gatedClock 0:8e898e1270d6 815
gatedClock 0:8e898e1270d6 816 dHeartbeat = 0; // initialize.
gatedClock 0:8e898e1270d6 817
gatedClock 0:8e898e1270d6 818 watchdog.kick(WATCHDOG_S); // initialize watchdog.
gatedClock 0:8e898e1270d6 819
gatedClock 0:8e898e1270d6 820 while (1) // thread loop.
gatedClock 0:8e898e1270d6 821 {
gatedClock 0:8e898e1270d6 822 // all other threads report-in.
gatedClock 0:8e898e1270d6 823 // blocking wait on all of them.
gatedClock 1:a3df81701818 824 queueWatchdogThread_0.get(osWaitForever);
gatedClock 1:a3df81701818 825 queueWatchdogThread_1.get(osWaitForever);
gatedClock 1:a3df81701818 826 queueWatchdogThread_2.get(osWaitForever);
gatedClock 0:8e898e1270d6 827
gatedClock 0:8e898e1270d6 828 watchdog.kick(); // reset watchdog timer.
gatedClock 0:8e898e1270d6 829
gatedClock 0:8e898e1270d6 830 dHeartbeat++; // thread heartbeat.
gatedClock 0:8e898e1270d6 831 if (!(dHeartbeat % HB_MODULO)) led3 = !led3;
gatedClock 0:8e898e1270d6 832 Thread::wait(THREAD_3_WAIT); // multitasking.
gatedClock 0:8e898e1270d6 833 } // thread loop.
gatedClock 0:8e898e1270d6 834 }
gatedClock 0:8e898e1270d6 835 /*----------------------------------------------//----------------------------*/
gatedClock 0:8e898e1270d6 836 char ascii_nibble_to_binary(char cAscii) // ascii nibble -> binary.
gatedClock 0:8e898e1270d6 837 {
gatedClock 0:8e898e1270d6 838 char cBinary; // converted value.
gatedClock 0:8e898e1270d6 839
gatedClock 0:8e898e1270d6 840 switch(cAscii)
gatedClock 0:8e898e1270d6 841 {
gatedClock 0:8e898e1270d6 842 case 'F' : {cBinary = 15; break;}
gatedClock 0:8e898e1270d6 843 case 'E' : {cBinary = 14; break;}
gatedClock 0:8e898e1270d6 844 case 'D' : {cBinary = 13; break;}
gatedClock 0:8e898e1270d6 845 case 'C' : {cBinary = 12; break;}
gatedClock 0:8e898e1270d6 846 case 'B' : {cBinary = 11; break;}
gatedClock 0:8e898e1270d6 847 case 'A' : {cBinary = 10; break;}
gatedClock 0:8e898e1270d6 848 case 'f' : {cBinary = 15; break;}
gatedClock 0:8e898e1270d6 849 case 'e' : {cBinary = 14; break;}
gatedClock 0:8e898e1270d6 850 case 'd' : {cBinary = 13; break;}
gatedClock 0:8e898e1270d6 851 case 'c' : {cBinary = 12; break;}
gatedClock 0:8e898e1270d6 852 case 'b' : {cBinary = 11; break;}
gatedClock 0:8e898e1270d6 853 case 'a' : {cBinary = 10; break;}
gatedClock 0:8e898e1270d6 854 case '9' : {cBinary = 9; break;}
gatedClock 0:8e898e1270d6 855 case '8' : {cBinary = 8; break;}
gatedClock 0:8e898e1270d6 856 case '7' : {cBinary = 7; break;}
gatedClock 0:8e898e1270d6 857 case '6' : {cBinary = 6; break;}
gatedClock 0:8e898e1270d6 858 case '5' : {cBinary = 5; break;}
gatedClock 0:8e898e1270d6 859 case '4' : {cBinary = 4; break;}
gatedClock 0:8e898e1270d6 860 case '3' : {cBinary = 3; break;}
gatedClock 0:8e898e1270d6 861 case '2' : {cBinary = 2; break;}
gatedClock 0:8e898e1270d6 862 case '1' : {cBinary = 1; break;}
gatedClock 0:8e898e1270d6 863 case '0' : {cBinary = 0; break;}
gatedClock 0:8e898e1270d6 864 default : {cBinary = 0; break;}
gatedClock 0:8e898e1270d6 865 } // switch(cAscii).
gatedClock 0:8e898e1270d6 866 return(cBinary); // return the binary.
gatedClock 0:8e898e1270d6 867 } // ascii_nibble_to_binary.
gatedClock 0:8e898e1270d6 868 /*----------------------------------------------//----------------------------*/
gatedClock 0:8e898e1270d6 869 char binary_to_ascii_nibble(char cBinary) // binary -> ascii nibble.
gatedClock 0:8e898e1270d6 870 {
gatedClock 0:8e898e1270d6 871 char cAscii; // converted value.
gatedClock 0:8e898e1270d6 872
gatedClock 0:8e898e1270d6 873 switch(cBinary)
gatedClock 0:8e898e1270d6 874 {
gatedClock 0:8e898e1270d6 875 case 15 : {cAscii = 'F'; break;}
gatedClock 0:8e898e1270d6 876 case 14 : {cAscii = 'E'; break;}
gatedClock 0:8e898e1270d6 877 case 13 : {cAscii = 'D'; break;}
gatedClock 0:8e898e1270d6 878 case 12 : {cAscii = 'C'; break;}
gatedClock 0:8e898e1270d6 879 case 11 : {cAscii = 'B'; break;}
gatedClock 0:8e898e1270d6 880 case 10 : {cAscii = 'A'; break;}
gatedClock 0:8e898e1270d6 881 case 9 : {cAscii = '9'; break;}
gatedClock 0:8e898e1270d6 882 case 8 : {cAscii = '8'; break;}
gatedClock 0:8e898e1270d6 883 case 7 : {cAscii = '7'; break;}
gatedClock 0:8e898e1270d6 884 case 6 : {cAscii = '6'; break;}
gatedClock 0:8e898e1270d6 885 case 5 : {cAscii = '5'; break;}
gatedClock 0:8e898e1270d6 886 case 4 : {cAscii = '4'; break;}
gatedClock 0:8e898e1270d6 887 case 3 : {cAscii = '3'; break;}
gatedClock 0:8e898e1270d6 888 case 2 : {cAscii = '2'; break;}
gatedClock 0:8e898e1270d6 889 case 1 : {cAscii = '1'; break;}
gatedClock 0:8e898e1270d6 890 case 0 : {cAscii = '0'; break;}
gatedClock 0:8e898e1270d6 891 default : {cAscii = '0'; break;}
gatedClock 0:8e898e1270d6 892 } // switch(cBinary).
gatedClock 0:8e898e1270d6 893 return(cAscii); // return the binary.
gatedClock 0:8e898e1270d6 894 } // binary_to_ascii_nibble.
gatedClock 0:8e898e1270d6 895 /*----------------------------------------------//----------------------------*/
gatedClock 0:8e898e1270d6 896 void clear_tFromHost(tFromHost * ptFromHost)// clear structure.
gatedClock 0:8e898e1270d6 897 {
gatedClock 0:8e898e1270d6 898 ptFromHost->cCommand = 0x00;
gatedClock 0:8e898e1270d6 899 ptFromHost->cRegisterID = 0x00;
gatedClock 0:8e898e1270d6 900 ptFromHost->cRegisterValue = 0x00;
gatedClock 0:8e898e1270d6 901 ptFromHost->cIRValueH = 0x00;
gatedClock 0:8e898e1270d6 902 ptFromHost->cIRValueL = 0x00;
gatedClock 0:8e898e1270d6 903 ptFromHost->cMMaddress = 0x00;
gatedClock 0:8e898e1270d6 904 ptFromHost->cMMdataH = 0x00;
gatedClock 0:8e898e1270d6 905 ptFromHost->cMMdataL = 0x00;
gatedClock 0:8e898e1270d6 906 } // clear_tFromHost.
gatedClock 0:8e898e1270d6 907 /*----------------------------------------------//----------------------------*/
gatedClock 0:8e898e1270d6 908 void clear_tToHost(tToHost * ptToHost) // clear structure.
gatedClock 0:8e898e1270d6 909 {
gatedClock 0:8e898e1270d6 910 ptToHost->cCommand = 0x00;
gatedClock 0:8e898e1270d6 911 ptToHost->cRegisterID = 0x00;
gatedClock 0:8e898e1270d6 912 ptToHost->cRegisterValue = 0x00;
gatedClock 0:8e898e1270d6 913 ptToHost->cMMaddress = 0x00;
gatedClock 0:8e898e1270d6 914 ptToHost->cMMdataH = 0x00;
gatedClock 0:8e898e1270d6 915 ptToHost->cMMdataL = 0x00;
gatedClock 0:8e898e1270d6 916 } // clear_tToHost.
gatedClock 0:8e898e1270d6 917 /*----------------------------------------------//----------------------------*/