Repository for import to local machine
Dependencies: DMBasicGUI DMSupport
EthernetHandler.cpp@8:26e49e6955bd, 2017-07-31 (annotated)
- 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?
User | Revision | Line number | New 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 |