Repository for import to local machine

Dependencies:   DMBasicGUI DMSupport

Committer:
jmitc91516
Date:
Mon Jul 31 15:37:57 2017 +0000
Revision:
8:26e49e6955bd
Parent:
1:a5258871b33d
Method ramp scrolling improved, and more bitmaps moved to QSPI memory

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jmitc91516 1:a5258871b33d 1 #include "EthernetHandler.h"
jmitc91516 1:a5258871b33d 2
jmitc91516 1:a5258871b33d 3 #define DO_USB_IN_THIS_THREAD // If #define'd, we do our own USB comms to the GC here in this thread.
jmitc91516 1:a5258871b33d 4 // If not, we signal the main thread to do it
jmitc91516 1:a5258871b33d 5
jmitc91516 1:a5258871b33d 6
jmitc91516 1:a5258871b33d 7 #define USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 8
jmitc91516 1:a5258871b33d 9 #ifdef USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 10
jmitc91516 1:a5258871b33d 11 #include "gpio_api.h"
jmitc91516 1:a5258871b33d 12 #include "wait_api.h"
jmitc91516 1:a5258871b33d 13 #include "toolchain.h"
jmitc91516 1:a5258871b33d 14 #include "mbed_interface.h"
jmitc91516 1:a5258871b33d 15
jmitc91516 1:a5258871b33d 16 // We turn on LED 1 when we have received, from the client, a command to send to the GC.
jmitc91516 1:a5258871b33d 17 // We turn it off when we send the response back to the client.
jmitc91516 1:a5258871b33d 18 static void SetLed1(bool turnLedOn)
jmitc91516 1:a5258871b33d 19 {
jmitc91516 1:a5258871b33d 20 gpio_t led_1; gpio_init_out(&led_1, LED1);
jmitc91516 1:a5258871b33d 21
jmitc91516 1:a5258871b33d 22 if(turnLedOn) {
jmitc91516 1:a5258871b33d 23 gpio_write(&led_1, 0); // zero appears to mean "turn LED 1 on"
jmitc91516 1:a5258871b33d 24 } else {
jmitc91516 1:a5258871b33d 25 gpio_write(&led_1, 1); // one appears to turn it off
jmitc91516 1:a5258871b33d 26 }
jmitc91516 1:a5258871b33d 27 }
jmitc91516 1:a5258871b33d 28
jmitc91516 1:a5258871b33d 29 #endif // USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 30
jmitc91516 1:a5258871b33d 31
jmitc91516 1:a5258871b33d 32 #include "GuiLib.h"
jmitc91516 1:a5258871b33d 33 /*
jmitc91516 1:a5258871b33d 34 Displays the specified text string at the specified location in the currently-displayed easyGUI page.
jmitc91516 1:a5258871b33d 35
jmitc91516 1:a5258871b33d 36 Defined in main.cpp - and omits the 'ALLOW_DEBUG_PRINTS' #define
jmitc91516 1:a5258871b33d 37 */
jmitc91516 1:a5258871b33d 38 extern void SpecialDebugPrint(char *stuffToPrint, GuiConst_INT16S X, GuiConst_INT16S Y);
jmitc91516 1:a5258871b33d 39
jmitc91516 1:a5258871b33d 40 /*
jmitc91516 1:a5258871b33d 41 Tells the caller whether or not a specified GC command represents the start of a method,
jmitc91516 1:a5258871b33d 42 and that therefore a new method is now being sent to the GC.
jmitc91516 1:a5258871b33d 43
jmitc91516 1:a5258871b33d 44 Params: pointer to a null-terminated string containing the command in question
jmitc91516 1:a5258871b33d 45
jmitc91516 1:a5258871b33d 46 Returns true if the command is one that occurs at the start of a method (and nowhere else),
jmitc91516 1:a5258871b33d 47 false if not.
jmitc91516 1:a5258871b33d 48
jmitc91516 1:a5258871b33d 49 Defined in main.cpp
jmitc91516 1:a5258871b33d 50 */
jmitc91516 1:a5258871b33d 51 bool IsStartOfMethodCommand(char *gcCommand);
jmitc91516 1:a5258871b33d 52
jmitc91516 1:a5258871b33d 53 /*
jmitc91516 1:a5258871b33d 54 Tells the caller whether or not a specified GC command represents the end of a method,
jmitc91516 1:a5258871b33d 55 and that therefore a new method has just been sent to the GC.
jmitc91516 1:a5258871b33d 56
jmitc91516 1:a5258871b33d 57 Params: pointer to a null-terminated string containing the command in question
jmitc91516 1:a5258871b33d 58
jmitc91516 1:a5258871b33d 59 Returns true if the command is one that occurs at the end of a method (and nowhere else),
jmitc91516 1:a5258871b33d 60 false if not.
jmitc91516 1:a5258871b33d 61
jmitc91516 1:a5258871b33d 62 Defined in main.cpp
jmitc91516 1:a5258871b33d 63 */
jmitc91516 1:a5258871b33d 64 bool IsEndOfMethodCommand(char *gcCommand);
jmitc91516 1:a5258871b33d 65
jmitc91516 1:a5258871b33d 66 /*
jmitc91516 1:a5258871b33d 67 Tells the caller whether or not a specified GC command is a control command,
jmitc91516 1:a5258871b33d 68 which received "DACK" in acknowledgement, and is therefore likely
jmitc91516 1:a5258871b33d 69 to have caused the GC to change its state.
jmitc91516 1:a5258871b33d 70
jmitc91516 1:a5258871b33d 71 Params: pointer to a null-terminated string containing the command in question
jmitc91516 1:a5258871b33d 72
jmitc91516 1:a5258871b33d 73 Returns true if the command is a control command and if it succeeded, false if not.
jmitc91516 1:a5258871b33d 74
jmitc91516 1:a5258871b33d 75 Defined in main.cpp
jmitc91516 1:a5258871b33d 76 */
jmitc91516 1:a5258871b33d 77 bool IsSuccessfulControlCommand(char *gcCommand, char *gcResponse);
jmitc91516 1:a5258871b33d 78
jmitc91516 1:a5258871b33d 79
jmitc91516 1:a5258871b33d 80 osThreadId EthernetHandler::mainThreadId = 0;
jmitc91516 1:a5258871b33d 81 bool EthernetHandler::mainThreadIdSet = false;
jmitc91516 1:a5258871b33d 82
jmitc91516 1:a5258871b33d 83 TCPSocketServer* EthernetHandler::ethernetServer = NULL;
jmitc91516 1:a5258871b33d 84
jmitc91516 1:a5258871b33d 85 USBDeviceConnected* EthernetHandler::usbDevice = NULL;
jmitc91516 1:a5258871b33d 86 USBHostGC* EthernetHandler::usbHostGC = NULL;
jmitc91516 1:a5258871b33d 87
jmitc91516 1:a5258871b33d 88 char EthernetHandler::gcCommand[20] = "";
jmitc91516 1:a5258871b33d 89 char EthernetHandler::gcResponse[20] = "";
jmitc91516 1:a5258871b33d 90
jmitc91516 1:a5258871b33d 91 Timer EthernetHandler::timer;
jmitc91516 1:a5258871b33d 92
jmitc91516 1:a5258871b33d 93 bool EthernetHandler::receivedGCCommand = false;
jmitc91516 1:a5258871b33d 94
jmitc91516 1:a5258871b33d 95 // This is the thread signal value we tell the main thread to use to tell us that it has received a response to the latest command.
jmitc91516 1:a5258871b33d 96 // We increment this each time we pass a new Ethernet command to the main thread, so that we know which command the response refers to.
jmitc91516 1:a5258871b33d 97 int EthernetHandler::responseReadyThreadSignalCode = GC_RESPONSE_READY;
jmitc91516 1:a5258871b33d 98
jmitc91516 1:a5258871b33d 99 // The maximum possible value for 'responseReadyThreadSignalCode' above - when it exceeds this value, we set it back to GC_RESPONSE_READY
jmitc91516 1:a5258871b33d 100 const int EthernetHandler::maxResponseReadyThreadSignalCode = GC_RESPONSE_READY + 1000;
jmitc91516 1:a5258871b33d 101
jmitc91516 1:a5258871b33d 102
jmitc91516 1:a5258871b33d 103 //#define CLIENT_SET_BLOCKING_FALSE
jmitc91516 1:a5258871b33d 104
jmitc91516 1:a5258871b33d 105
jmitc91516 1:a5258871b33d 106 bool EthernetHandler::GCCommandReceived(void)
jmitc91516 1:a5258871b33d 107 {
jmitc91516 1:a5258871b33d 108 #ifdef DO_USB_IN_THIS_THREAD
jmitc91516 1:a5258871b33d 109 return false; // We will deal with this ourselves
jmitc91516 1:a5258871b33d 110 #else
jmitc91516 1:a5258871b33d 111 return receivedGCCommand;
jmitc91516 1:a5258871b33d 112 #endif
jmitc91516 1:a5258871b33d 113 }
jmitc91516 1:a5258871b33d 114
jmitc91516 1:a5258871b33d 115
jmitc91516 1:a5258871b33d 116 /*
jmitc91516 1:a5258871b33d 117 Caller tells us the ID of the thread we are to signal
jmitc91516 1:a5258871b33d 118 when we have received a command (over the Ethernet link)
jmitc91516 1:a5258871b33d 119 to be sent to the GC.
jmitc91516 1:a5258871b33d 120 */
jmitc91516 1:a5258871b33d 121 void EthernetHandler::SetMainThreadId(osThreadId threadId)
jmitc91516 1:a5258871b33d 122 {
jmitc91516 1:a5258871b33d 123 mainThreadId = threadId;
jmitc91516 1:a5258871b33d 124
jmitc91516 1:a5258871b33d 125 mainThreadIdSet = true;
jmitc91516 1:a5258871b33d 126 }
jmitc91516 1:a5258871b33d 127
jmitc91516 1:a5258871b33d 128 /*
jmitc91516 1:a5258871b33d 129 Caller gives us a pointer to the Ethernet server
jmitc91516 1:a5258871b33d 130 we are to use.
jmitc91516 1:a5258871b33d 131 */
jmitc91516 1:a5258871b33d 132 void EthernetHandler::SetEthernetServer(TCPSocketServer* server)
jmitc91516 1:a5258871b33d 133 {
jmitc91516 1:a5258871b33d 134 ethernetServer = server;
jmitc91516 1:a5258871b33d 135 }
jmitc91516 1:a5258871b33d 136
jmitc91516 1:a5258871b33d 137 /*
jmitc91516 1:a5258871b33d 138 Caller gives us pointers for the USB link to the GC,
jmitc91516 1:a5258871b33d 139 to allow us to communicate with it ourselves
jmitc91516 1:a5258871b33d 140 */
jmitc91516 1:a5258871b33d 141 void EthernetHandler::SetUsbGC(USBDeviceConnected* newUsbDevice, USBHostGC* newUsbHostGC)
jmitc91516 1:a5258871b33d 142 {
jmitc91516 1:a5258871b33d 143 usbDevice = newUsbDevice;
jmitc91516 1:a5258871b33d 144 usbHostGC = newUsbHostGC;
jmitc91516 1:a5258871b33d 145 }
jmitc91516 1:a5258871b33d 146
jmitc91516 1:a5258871b33d 147
jmitc91516 1:a5258871b33d 148 /*
jmitc91516 1:a5258871b33d 149 Passes back to the caller, the command we have received over the Ethernet link
jmitc91516 1:a5258871b33d 150 to be sent to the GC (assume the caller is going to communicate with the GC).
jmitc91516 1:a5258871b33d 151
jmitc91516 1:a5258871b33d 152 Args: pointer to a buffer into which we will copy the command
jmitc91516 1:a5258871b33d 153 pointer to an integer into which we will place the value the caller
jmitc91516 1:a5258871b33d 154 must use to tell us that it has given us the response
jmitc91516 1:a5258871b33d 155 */
jmitc91516 1:a5258871b33d 156 void EthernetHandler::GetGCCommand(char *commandBuffer, int* responseThreadSignalCodeToUse)
jmitc91516 1:a5258871b33d 157 {
jmitc91516 1:a5258871b33d 158 strcpy(commandBuffer, gcCommand);
jmitc91516 1:a5258871b33d 159
jmitc91516 1:a5258871b33d 160 SetupNextResponseReadyThreadSignalCode();
jmitc91516 1:a5258871b33d 161
jmitc91516 1:a5258871b33d 162 *responseThreadSignalCodeToUse = responseReadyThreadSignalCode;
jmitc91516 1:a5258871b33d 163 }
jmitc91516 1:a5258871b33d 164
jmitc91516 1:a5258871b33d 165 /*
jmitc91516 1:a5258871b33d 166 Set 'responseReadyThreadSignalCode' to the next legal value
jmitc91516 1:a5258871b33d 167 */
jmitc91516 1:a5258871b33d 168 void EthernetHandler::SetupNextResponseReadyThreadSignalCode(void)
jmitc91516 1:a5258871b33d 169 {
jmitc91516 1:a5258871b33d 170 ++responseReadyThreadSignalCode;
jmitc91516 1:a5258871b33d 171
jmitc91516 1:a5258871b33d 172 if(responseReadyThreadSignalCode > maxResponseReadyThreadSignalCode) {
jmitc91516 1:a5258871b33d 173 responseReadyThreadSignalCode = GC_RESPONSE_READY;
jmitc91516 1:a5258871b33d 174 }
jmitc91516 1:a5258871b33d 175 }
jmitc91516 1:a5258871b33d 176
jmitc91516 1:a5258871b33d 177
jmitc91516 1:a5258871b33d 178 /*
jmitc91516 1:a5258871b33d 179 Function to allow the caller to pass to us,
jmitc91516 1:a5258871b33d 180 the response it got back from the GC.
jmitc91516 1:a5258871b33d 181 We copy it into our buffer, ready to be sent back
jmitc91516 1:a5258871b33d 182 to the Ethernet client.
jmitc91516 1:a5258871b33d 183
jmitc91516 1:a5258871b33d 184 Caller must set this *before* signaling GC_RESPONSE_READY
jmitc91516 1:a5258871b33d 185 *********************************************************
jmitc91516 1:a5258871b33d 186
jmitc91516 1:a5258871b33d 187 Args: pointer to a buffer containing the GC response
jmitc91516 1:a5258871b33d 188 */
jmitc91516 1:a5258871b33d 189 void EthernetHandler::SetGCResponse(char *response)
jmitc91516 1:a5258871b33d 190 {
jmitc91516 1:a5258871b33d 191 strcpy(gcResponse, response);
jmitc91516 1:a5258871b33d 192 }
jmitc91516 1:a5258871b33d 193
jmitc91516 1:a5258871b33d 194
jmitc91516 1:a5258871b33d 195 /*
jmitc91516 1:a5258871b33d 196 Sends a command (known as a 'report') to the GC, and returns the response.
jmitc91516 1:a5258871b33d 197
jmitc91516 1:a5258871b33d 198 Args: pointer to (null-terminated) command to use
jmitc91516 1:a5258871b33d 199 pointer to buffer to contain the (also null-terminated) response
jmitc91516 1:a5258871b33d 200
jmitc91516 1:a5258871b33d 201 No return code.
jmitc91516 1:a5258871b33d 202 */
jmitc91516 1:a5258871b33d 203 void EthernetHandler::SetGCDeviceReport(char *cmd, char *response)
jmitc91516 1:a5258871b33d 204 {
jmitc91516 1:a5258871b33d 205 if((usbHostGC != NULL) && (usbDevice != NULL)) {
jmitc91516 1:a5258871b33d 206
jmitc91516 1:a5258871b33d 207 //strcpy(response, "BEFORE"); // Debug
jmitc91516 1:a5258871b33d 208
jmitc91516 1:a5258871b33d 209 // Guard against simultaneous calls to usbHostGC->SetDeviceReport -
jmitc91516 1:a5258871b33d 210 // it is not re-entrant (and nor is the GC)
jmitc91516 1:a5258871b33d 211 while(usbHostGC->ExecutingSetDeviceReport()) {
jmitc91516 1:a5258871b33d 212 Thread::wait(1); // Give other threads a chance
jmitc91516 1:a5258871b33d 213 }
jmitc91516 1:a5258871b33d 214
jmitc91516 1:a5258871b33d 215 //strcpy(response, "AFTER 1"); // Debug
jmitc91516 1:a5258871b33d 216
jmitc91516 1:a5258871b33d 217 usbHostGC->SetDeviceReport(usbDevice, cmd, response);
jmitc91516 1:a5258871b33d 218
jmitc91516 1:a5258871b33d 219 //strcpy(response, "AFTER 2"); // Debug
jmitc91516 1:a5258871b33d 220 }
jmitc91516 1:a5258871b33d 221 }
jmitc91516 1:a5258871b33d 222
jmitc91516 1:a5258871b33d 223
jmitc91516 1:a5258871b33d 224 /*
jmitc91516 1:a5258871b33d 225 Handles the next Ethernet message from the specified client.
jmitc91516 1:a5258871b33d 226 Returns true if there was a message, false if not.
jmitc91516 1:a5258871b33d 227 */
jmitc91516 1:a5258871b33d 228 bool EthernetHandler::HandleEthernetMessage(TCPSocketConnection* client)
jmitc91516 1:a5258871b33d 229 {
jmitc91516 1:a5258871b33d 230 if(mainThreadIdSet) {
jmitc91516 1:a5258871b33d 231
jmitc91516 1:a5258871b33d 232 receivedGCCommand = false;
jmitc91516 1:a5258871b33d 233
jmitc91516 1:a5258871b33d 234 int n = client->receive(gcCommand, sizeof(gcCommand));
jmitc91516 1:a5258871b33d 235 if (n <= 0) return false;
jmitc91516 1:a5258871b33d 236
jmitc91516 1:a5258871b33d 237 gcCommand[n] = '\0';
jmitc91516 1:a5258871b33d 238
jmitc91516 1:a5258871b33d 239 timer.reset();
jmitc91516 1:a5258871b33d 240 timer.start();
jmitc91516 1:a5258871b33d 241
jmitc91516 1:a5258871b33d 242 //#define ALLOW_DEBUG_PRINTS_HERE
jmitc91516 1:a5258871b33d 243 #ifdef ALLOW_DEBUG_PRINTS_HERE
jmitc91516 1:a5258871b33d 244 char buff[300];
jmitc91516 1:a5258871b33d 245 sprintf(buff, "ETH - command received: \"%s\"", gcCommand);
jmitc91516 1:a5258871b33d 246 SpecialDebugPrint(buff, 50, 350);
jmitc91516 1:a5258871b33d 247 #endif // ALLOW_DEBUG_PRINTS_HERE
jmitc91516 1:a5258871b33d 248
jmitc91516 1:a5258871b33d 249 receivedGCCommand = true;
jmitc91516 1:a5258871b33d 250
jmitc91516 1:a5258871b33d 251 #ifdef USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 252 // Turn LED 1 on while we signal the main thread that we have a command, and while we wait for the main thread to respond
jmitc91516 1:a5258871b33d 253 // - or, if we are doing USB in this thread, while *we* send the command to the GC and wait for the GC to respond
jmitc91516 1:a5258871b33d 254 SetLed1(true);
jmitc91516 1:a5258871b33d 255 #endif // USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 256
jmitc91516 1:a5258871b33d 257
jmitc91516 1:a5258871b33d 258 #ifdef DO_USB_IN_THIS_THREAD
jmitc91516 1:a5258871b33d 259
jmitc91516 1:a5258871b33d 260 bool commandIdentified = false;
jmitc91516 1:a5258871b33d 261
jmitc91516 1:a5258871b33d 262 if(IsStartOfMethodCommand(gcCommand)) {
jmitc91516 1:a5258871b33d 263 commandIdentified = true;
jmitc91516 1:a5258871b33d 264 osSignalSet(mainThreadId, STARTED_DOWNLOADING_METHOD);
jmitc91516 1:a5258871b33d 265 }
jmitc91516 1:a5258871b33d 266
jmitc91516 1:a5258871b33d 267 SetGCDeviceReport(gcCommand, gcResponse);
jmitc91516 1:a5258871b33d 268
jmitc91516 1:a5258871b33d 269 if(!commandIdentified) {
jmitc91516 1:a5258871b33d 270 if(IsEndOfMethodCommand(gcCommand)) {
jmitc91516 1:a5258871b33d 271 commandIdentified = true;
jmitc91516 1:a5258871b33d 272 osSignalSet(mainThreadId, FINISHED_DOWNLOADING_METHOD);
jmitc91516 1:a5258871b33d 273 }
jmitc91516 1:a5258871b33d 274 }
jmitc91516 1:a5258871b33d 275
jmitc91516 1:a5258871b33d 276 if(!commandIdentified) {
jmitc91516 1:a5258871b33d 277 // Tell main thread if CRUN, CHON or CHOF were sent to the GC, and were successful -
jmitc91516 1:a5258871b33d 278 // i.e. acknowledged with DACK - so that it can update the display.
jmitc91516 1:a5258871b33d 279 // Also now CSTP and CABT
jmitc91516 1:a5258871b33d 280 if((gcResponse[0] == 'D') && (gcResponse[1] == 'A') && (gcResponse[2] == 'C') && (gcResponse[3] == 'K')) { /// i.e. "DACK"
jmitc91516 1:a5258871b33d 281 if(gcCommand[0] == 'C') { // Begins with 'C' - must be a command of some kind
jmitc91516 1:a5258871b33d 282 if((gcCommand[1] == 'R') && (gcCommand[2] == 'U') && (gcCommand[3] == 'N')) { // i.e. "CRUN"
jmitc91516 1:a5258871b33d 283 commandIdentified = true;
jmitc91516 1:a5258871b33d 284 osSignalSet(mainThreadId, CRUN_COMMAND_SENT);
jmitc91516 1:a5258871b33d 285 }
jmitc91516 1:a5258871b33d 286
jmitc91516 1:a5258871b33d 287 if(!commandIdentified) {
jmitc91516 1:a5258871b33d 288 if((gcCommand[1] == 'H') && (gcCommand[2] == 'O')) {
jmitc91516 1:a5258871b33d 289 if(gcCommand[3] == 'N') { // i.e. "CHON"
jmitc91516 1:a5258871b33d 290 commandIdentified = true;
jmitc91516 1:a5258871b33d 291 osSignalSet(mainThreadId, CHON_COMMAND_SENT);
jmitc91516 1:a5258871b33d 292 }
jmitc91516 1:a5258871b33d 293
jmitc91516 1:a5258871b33d 294 if(!commandIdentified) {
jmitc91516 1:a5258871b33d 295 if(gcCommand[3] == 'F') { // i.e. "CHOF"
jmitc91516 1:a5258871b33d 296 commandIdentified = true;
jmitc91516 1:a5258871b33d 297 osSignalSet(mainThreadId, CHOF_COMMAND_SENT);
jmitc91516 1:a5258871b33d 298 }
jmitc91516 1:a5258871b33d 299 }
jmitc91516 1:a5258871b33d 300 }
jmitc91516 1:a5258871b33d 301 }
jmitc91516 1:a5258871b33d 302
jmitc91516 1:a5258871b33d 303 if(!commandIdentified) {
jmitc91516 1:a5258871b33d 304 if(((gcCommand[1] == 'S') && (gcCommand[2] == 'T') && (gcCommand[3] == 'P')) // i.e. "CSTP"
jmitc91516 1:a5258871b33d 305 || ((gcCommand[1] == 'A') && (gcCommand[2] == 'B') && (gcCommand[3] == 'T'))) { // i.e. "CABT"
jmitc91516 1:a5258871b33d 306 commandIdentified = true;
jmitc91516 1:a5258871b33d 307 osSignalSet(mainThreadId, ABORT_RUN_COMMAND_SENT);
jmitc91516 1:a5258871b33d 308 }
jmitc91516 1:a5258871b33d 309 }
jmitc91516 1:a5258871b33d 310 }
jmitc91516 1:a5258871b33d 311 }
jmitc91516 1:a5258871b33d 312 }
jmitc91516 1:a5258871b33d 313 #else
jmitc91516 1:a5258871b33d 314 // Signal the main thread that we have a command to send to the GC
jmitc91516 1:a5258871b33d 315 osSignalSet(mainThreadId, GC_COMMAND_READY);
jmitc91516 1:a5258871b33d 316
jmitc91516 1:a5258871b33d 317 // Now wait for it to tell us it has 'got' the command - try and keep synchronised
jmitc91516 1:a5258871b33d 318 // (i.e. so that we do not get other commands before the main thread has dealt with this one,
jmitc91516 1:a5258871b33d 319 // and so that the commands and responses do not get out of step)
jmitc91516 1:a5258871b33d 320 Thread::signal_wait(GOT_GC_COMMAND);
jmitc91516 1:a5258871b33d 321
jmitc91516 1:a5258871b33d 322
jmitc91516 1:a5258871b33d 323 // Main thread must give us the response *now* - *before* signaling 'response ready' - see above
jmitc91516 1:a5258871b33d 324 // *********************************************************************************************
jmitc91516 1:a5258871b33d 325
jmitc91516 1:a5258871b33d 326 // We tell the main thread to use a different response code for each command,
jmitc91516 1:a5258871b33d 327 // to try and ensure that the commands and responses do not get out of step
jmitc91516 1:a5258871b33d 328
jmitc91516 1:a5258871b33d 329 // Wait forever - do not timeout (no point in continuing without a response)
jmitc91516 1:a5258871b33d 330 Thread::signal_wait(responseReadyThreadSignalCode);
jmitc91516 1:a5258871b33d 331
jmitc91516 1:a5258871b33d 332 // Main thread has put the response in 'gcResponse'
jmitc91516 1:a5258871b33d 333
jmitc91516 1:a5258871b33d 334 receivedGCCommand = false; // Ready for the next command
jmitc91516 1:a5258871b33d 335
jmitc91516 1:a5258871b33d 336 #endif // DO_USB_IN_THIS_THREAD
jmitc91516 1:a5258871b33d 337
jmitc91516 1:a5258871b33d 338
jmitc91516 1:a5258871b33d 339 #ifdef USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 340 // We have received the command response - turn LED 1 off
jmitc91516 1:a5258871b33d 341 SetLed1(false);
jmitc91516 1:a5258871b33d 342 #endif // USE_LED_FOR_DEBUGGING
jmitc91516 1:a5258871b33d 343
jmitc91516 1:a5258871b33d 344 // Pass the response back to the client
jmitc91516 1:a5258871b33d 345 client->send_all(gcResponse, strlen(gcResponse));
jmitc91516 1:a5258871b33d 346
jmitc91516 1:a5258871b33d 347 timer.stop();
jmitc91516 1:a5258871b33d 348
jmitc91516 1:a5258871b33d 349 #ifdef ALLOW_DEBUG_PRINTS_HERE
jmitc91516 1:a5258871b33d 350 sprintf(buff, "ETH - response sent: \"%s\"", gcResponse);
jmitc91516 1:a5258871b33d 351 SpecialDebugPrint(buff, 50, 380);
jmitc91516 1:a5258871b33d 352
jmitc91516 1:a5258871b33d 353 if((gcResponse[1] == gcCommand[1]) && (gcResponse[2] == gcCommand[2]) && (gcResponse[3] == gcCommand[3])) {
jmitc91516 1:a5258871b33d 354 SpecialDebugPrint("ETH - command and response match", 50, 400);
jmitc91516 1:a5258871b33d 355 } else {
jmitc91516 1:a5258871b33d 356 SpecialDebugPrint("ETH - command and response *** do not match ***", 50, 400);
jmitc91516 1:a5258871b33d 357 }
jmitc91516 1:a5258871b33d 358
jmitc91516 1:a5258871b33d 359 int read_ms = timer.read_ms();
jmitc91516 1:a5258871b33d 360 if(read_ms > 1000) { // We are interested only in suspiciously long response times (that may make Ellution time out)
jmitc91516 1:a5258871b33d 361 sprintf(buff, "ETH - time taken for %s: %d ms", gcCommand, read_ms);
jmitc91516 1:a5258871b33d 362 SpecialDebugPrint(buff, 50, 420);
jmitc91516 1:a5258871b33d 363 }
jmitc91516 1:a5258871b33d 364 #endif // ALLOW_DEBUG_PRINTS_HERE
jmitc91516 1:a5258871b33d 365
jmitc91516 1:a5258871b33d 366 //receivedGCCommand = false; // Ready for the next command
jmitc91516 1:a5258871b33d 367
jmitc91516 1:a5258871b33d 368 return true;
jmitc91516 1:a5258871b33d 369 }
jmitc91516 1:a5258871b33d 370
jmitc91516 1:a5258871b33d 371 // 'else'
jmitc91516 1:a5258871b33d 372 return false;
jmitc91516 1:a5258871b33d 373 }
jmitc91516 1:a5258871b33d 374
jmitc91516 1:a5258871b33d 375
jmitc91516 1:a5258871b33d 376 /*
jmitc91516 1:a5258871b33d 377 This is the infinite loop that handles Ethernet traffic on its own thread.
jmitc91516 1:a5258871b33d 378 Once started, it never exits.
jmitc91516 1:a5258871b33d 379 */
jmitc91516 1:a5258871b33d 380 void EthernetHandler::HandlerFunction(void const *argument)
jmitc91516 1:a5258871b33d 381 {
jmitc91516 1:a5258871b33d 382 if(mainThreadIdSet && (ethernetServer != NULL)) {
jmitc91516 1:a5258871b33d 383
jmitc91516 1:a5258871b33d 384 // We will now sit in this loop until the end of time, or this thread gets terminated, or the system powers off, whichever happens soonest...
jmitc91516 1:a5258871b33d 385 while(true) {
jmitc91516 1:a5258871b33d 386
jmitc91516 1:a5258871b33d 387 TCPSocketConnection client;
jmitc91516 1:a5258871b33d 388
jmitc91516 1:a5258871b33d 389 // Look for a client, but do not hang if there isn't one
jmitc91516 1:a5258871b33d 390 ethernetServer->set_blocking(false); // Timeout after (1.5)s
jmitc91516 1:a5258871b33d 391 bool clientFound = (ethernetServer->accept(client) == 0);
jmitc91516 1:a5258871b33d 392 if(clientFound) {
jmitc91516 1:a5258871b33d 393 #ifdef CLIENT_SET_BLOCKING_FALSE
jmitc91516 1:a5258871b33d 394 client.set_blocking(false); // Default timeout (1.5 sec)
jmitc91516 1:a5258871b33d 395 //client.set_blocking(false, 60000); // Timeout after 1 minute (comms somehow works better than with 1.5sec)
jmitc91516 1:a5258871b33d 396 #else
jmitc91516 1:a5258871b33d 397 // No - block this thread until we get a command - what else would we do?
jmitc91516 1:a5258871b33d 398 client.set_blocking(true);
jmitc91516 1:a5258871b33d 399 // But note that, on the face of it, set_blocking(true) means that we will never close the first client connection we open -
jmitc91516 1:a5258871b33d 400 // if the client goes away, we will just sit waiting forever (in HandleEthernetMessage) for the next command(?).
jmitc91516 1:a5258871b33d 401 // In this scenario, no subsequent client will be able to establish a connection.
jmitc91516 1:a5258871b33d 402 #endif // CLIENT_SET_BLOCKING_FALSE
jmitc91516 1:a5258871b33d 403
jmitc91516 1:a5258871b33d 404 while (true)
jmitc91516 1:a5258871b33d 405 {
jmitc91516 1:a5258871b33d 406 if(!HandleEthernetMessage(&client)) break;
jmitc91516 1:a5258871b33d 407 }
jmitc91516 1:a5258871b33d 408
jmitc91516 1:a5258871b33d 409 client.close();
jmitc91516 1:a5258871b33d 410 }
jmitc91516 1:a5258871b33d 411 }
jmitc91516 1:a5258871b33d 412 }
jmitc91516 1:a5258871b33d 413 }
jmitc91516 1:a5258871b33d 414
jmitc91516 1:a5258871b33d 415
jmitc91516 1:a5258871b33d 416
jmitc91516 1:a5258871b33d 417
jmitc91516 1:a5258871b33d 418