Repository for import to local machine
Dependencies: DMBasicGUI DMSupport
main.cpp
- Committer:
- jmitc91516
- Date:
- 2016-01-13
- Revision:
- 0:47c880c1463d
- Child:
- 1:a5258871b33d
File content as of revision 0:47c880c1463d:
#include "mbed.h" #include "DMBoard.h" #include "lpc_swim.h" #include "lpc_swim_font.h" #include <string.h> #include "GuiLib.h" #include "GuiDisplay.h" #include "USBHostGC.h" #include "TouchListener.h" #include "TouchPanelPageSelector.h" #include "GCHeatControl.h" #include "GetGCStatusLoop.h" #include "GCComponentStatusColorArea.h" #include "EthernetTimerHandler.h" // ** Start of timeout code to guard against multiple presses of the Heat On/Off button ** // (which is in the same position as the Abort Run button) Timeout heatOnOffTimeout; bool heatOnOffAvailable = true; void MakeHeatOnOffAvailableAgain(void) { heatOnOffAvailable = true; } void StartHeatOnOffTimeout(void) { heatOnOffAvailable = false; heatOnOffTimeout.attach(&MakeHeatOnOffAvailableAgain, 1.0); // Wait 1.0 sec before accepting touches again on Heat On/Off button } // ** End of Heat On/Off timeout code ** // These are 'global' - TouchCallback function, as well as main(), needs to access them TouchPanelPageSelectors touchPanelPageSelectors; GCHeatControl* theGCHeatControl; TouchListener* mainTouchListener = NULL; GetGCStatusLoop* getGCStatusLoop = NULL; HomePageGCComponentStatusColorAreas homePageGCComponentStatusColorAreas; SingleGCComponentPageStatusColorAreas singleGCComponentPageStatusColorAreas; EthernetTimerHandler* theEthernetTimerHandler = NULL; GuiConst_INTCOLOR SixteenBitColorValue(GuiConst_INT8U red, GuiConst_INT8U green, GuiConst_INT8U blue) { // Make sure we don't have numeric overflow problems during the conversion GuiConst_INT32U red32 = red; GuiConst_INT32U green32 = green; GuiConst_INT32U blue32 = blue; GuiConst_INT32U rgb = (blue32 << 16) | (green32 << 8) | red32; return GuiLib_RgbToPixelColor(rgb); } void DebugPrint(char *stuffToPrint, GuiConst_INT16S X, GuiConst_INT16S Y) { char buff[200]; const GuiConst_INT16U fontNo = GuiFont_Helv1; GuiDisplay_Lock(); // (Attempt to) clear previous strings from display sprintf(buff, " "); GuiLib_DrawStr( X, //GuiConst_INT16S X, Y, //GuiConst_INT16S Y, fontNo, //GuiConst_INT16U FontNo, buff, //GuiConst_TEXT PrefixLocate *String, GuiLib_ALIGN_LEFT, //GuiConst_INT8U Alignment, GuiLib_PS_ON, //GuiConst_INT8U PsWriting, GuiLib_TRANSPARENT_OFF, //GuiConst_INT8U Transparent, GuiLib_UNDERLINE_OFF, //GuiConst_INT8U Underlining, 0, //GuiConst_INT16S BackBoxSizeX, 0, //GuiConst_INT16S BackBoxSizeY1, 0, //GuiConst_INT16S BackBoxSizeY2, GuiLib_BBP_NONE, //GuiConst_INT8U BackBorderPixels, SixteenBitColorValue(0, 0, 0xFF), //GuiConst_INTCOLOR ForeColor, SixteenBitColorValue(0, 0xFF, 0) //GuiConst_INTCOLOR BackColor ); GuiLib_DrawStr( X, //GuiConst_INT16S X, Y, //GuiConst_INT16S Y, fontNo, //GuiConst_INT16U FontNo, stuffToPrint, //GuiConst_TEXT PrefixLocate *String, GuiLib_ALIGN_LEFT, //GuiConst_INT8U Alignment, GuiLib_PS_ON, //GuiConst_INT8U PsWriting, GuiLib_TRANSPARENT_OFF, //GuiConst_INT8U Transparent, GuiLib_UNDERLINE_OFF, //GuiConst_INT8U Underlining, 0, //GuiConst_INT16S BackBoxSizeX, 0, //GuiConst_INT16S BackBoxSizeY1, 0, //GuiConst_INT16S BackBoxSizeY2, GuiLib_BBP_NONE, //GuiConst_INT8U BackBorderPixels, SixteenBitColorValue(0, 0, 0xFF), //GuiConst_INTCOLOR ForeColor, SixteenBitColorValue(0, 0xFF, 0) //GuiConst_INTCOLOR BackColor ); GuiLib_Refresh(); GuiDisplay_Unlock(); } void EasyGUIDebugPrint(char *stuffToPrint, short X, short Y) { #define DEBUG_HERE #ifdef DEBUG_HERE DebugPrint(stuffToPrint, (GuiConst_INT16S) X, (GuiConst_INT16S) Y); #undef DEBUG_HERE #endif } void DummyEasyGUIDebugPrint(char *stuffToPrint, short X, short Y) { //DebugPrint(stuffToPrint, (GuiConst_INT16S) X, (GuiConst_INT16S) Y); } int DummyDebugFunction(int i) { return i^2; } bool GCIsReadyToRun(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC) { while(usbHostGC->ExecutingSetDeviceReport()) {} char response[50]; // Ensure we always have valid chars in the positions we are interested in, // in case we get "DNAK" or "EPKT" back response[6] = '0'; response[7] = '0'; usbHostGC->SetDeviceReport(usbDevice, "QSTA", response); // We expect a response like "QSTA00nn", where "nn" is the status. // "33" means ready to run, anything else means "not ready" return ((response[6] == '3') && (response[7]== '3')); } void DrawRunButton(bool enabled) { // Black if enabled, grey if disabled GuiConst_INTCOLOR buttonColor = (enabled) ? 0 : SixteenBitColorValue(0x80, 0x80, 0x80); GuiConst_TEXT *buttonText = "Run"; // These are hard-coded to match the corresponding definitions in easyGUI // (I have not found a way of getting these values from easyGUI at run time) const GuiConst_INT16S textX1 = 400; const GuiConst_INT16S textY1 = 220; const GuiConst_INT16U textFont = GuiFont_Helv1; const GuiConst_INT16S boxX1 = 338; const GuiConst_INT16S boxY1 = 195; const GuiConst_INT16S boxX2 = 462; const GuiConst_INT16S boxY2 = 235; GuiLib_Box(boxX1, boxY1, boxX2, boxY2, buttonColor); GuiLib_DrawStr( textX1, //GuiConst_INT16S X, textY1, //GuiConst_INT16S Y, textFont, //GuiConst_INT16U FontNo, buttonText, //GuiConst_TEXT PrefixLocate *String, GuiLib_ALIGN_CENTER, //GuiConst_INT8U Alignment, GuiLib_PS_ON, //GuiConst_INT8U PsWriting, GuiLib_TRANSPARENT_ON, //GuiConst_INT8U Transparent, GuiLib_UNDERLINE_OFF, //GuiConst_INT8U Underlining, 0, //GuiConst_INT16S BackBoxSizeX, 0, //GuiConst_INT16S BackBoxSizeY1, 0, //GuiConst_INT16S BackBoxSizeY2, GuiLib_BBP_NONE, //GuiConst_INT8U BackBorderPixels, buttonColor, //GuiConst_INTCOLOR ForeColor, SixteenBitColorValue(0xFF, 0xFF, 0xFF) //GuiConst_INTCOLOR BackColor (should be ignored with GuiLib_TRANSPARENT_ON) ); } void DisplayEasyGuiStructure(int structureIndex, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC) { // If required, query the GC to find out if it is ready to run *before* clearing the display - // otherwise the display remains clear while we talk to the GC - causes noticeable flickering bool gcIsReadyToRun = false; if((structureIndex == GuiStruct_HomePage_1) && (usbDevice != NULL) && (usbHostGC != NULL)) { gcIsReadyToRun = GCIsReadyToRun(usbDevice, usbHostGC); } GuiLib_Clear(); // Note - we draw the status rectangles after GuiLib_Clear - otherwise we wouldn't see the rectangles at all - // and before GuiLib_ShowScreen - so text, etc, is drawn on top of the rectangles switch(structureIndex) { case GuiStruct_HomePage_1: homePageGCComponentStatusColorAreas.DisplayAll(); break; case GuiStruct_ColumnPage1_2: case GuiStruct_ColumnPage2_9: case GuiStruct_ColumnPage3_10: singleGCComponentPageStatusColorAreas.DisplayGCComponentStatus(COLUMN); break; case GuiStruct_InjectorPage1_3: singleGCComponentPageStatusColorAreas.DisplayGCComponentStatus(INJECTOR); break; case GuiStruct_DetectorPage1_4: singleGCComponentPageStatusColorAreas.DisplayGCComponentStatus(DETECTOR); break; case GuiStruct_GasPage1_6: singleGCComponentPageStatusColorAreas.DisplayGCComponentStatus(GAS); break; default: // Don't need to display status rectangle for this page break; } GuiLib_ShowScreen(structureIndex, GuiLib_NO_CURSOR, GuiLib_RESET_AUTO_REDRAW); // But draw the run button, if required, on top of the fixed part of the home page if(structureIndex == GuiStruct_HomePage_1) { DrawRunButton(gcIsReadyToRun); } GuiLib_Refresh(); #define DEBUG_HERE #ifdef DEBUG_HERE char dbg[100]; sprintf(dbg, "After GuiLib_Refresh main 1"); EasyGUIDebugPrint(dbg, 100, 100); #undef DEBUG_HERE #endif if(getGCStatusLoop != NULL) { getGCStatusLoop->SetCurrentPage(structureIndex); } } void DrawErrorMessage(char *msg) { const GuiConst_INT16U fontNo = GuiFont_Helv1; GuiLib_DrawStr( 90, //GuiConst_INT16S X, 240, //GuiConst_INT16S Y, fontNo, //GuiConst_INT16U FontNo, msg, //GuiConst_TEXT PrefixLocate *String, GuiLib_ALIGN_LEFT, //GuiConst_INT8U Alignment, GuiLib_PS_ON, //GuiConst_INT8U PsWriting, GuiLib_TRANSPARENT_OFF, //GuiConst_INT8U Transparent, GuiLib_UNDERLINE_OFF, //GuiConst_INT8U Underlining, 0, //GuiConst_INT16S BackBoxSizeX, 0, //GuiConst_INT16S BackBoxSizeY1, 0, //GuiConst_INT16S BackBoxSizeY2, GuiLib_BBP_NONE, //GuiConst_INT8U BackBorderPixels, SixteenBitColorValue(0, 0, 0xFF), //GuiConst_INTCOLOR ForeColor, SixteenBitColorValue(0, 0xFF, 0) //GuiConst_INTCOLOR BackColor ); } void UpdateHeatOnOffEasyGuiVariable(void) { // Note that the easyGUI variable is not the current status of the heat on the GC, // but the command to toggle its current state if(theGCHeatControl != NULL) { if(theGCHeatControl->IsHeatOn()) { strcpy(GuiVar_heatOnOffCommand, "Heat Off"); } else { strcpy(GuiVar_heatOnOffCommand, "Heat On"); } } } bool StartGCRun(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC) { while(usbHostGC->ExecutingSetDeviceReport()) {} char response[50]; usbHostGC->SetDeviceReport(usbDevice, "CRUN", response); // We expect a response like this: "DACK" for success, "DNAK" for failure #define DEBUG_HERE #ifdef DEBUG_HERE char dbg[100]; sprintf(dbg, "CRUN returned %s", response); EasyGUIDebugPrint(dbg, 100, 150); #endif #undef DEBUG_HERE return (response[1] == 'A'); } bool StopGCRun(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC) { while(usbHostGC->ExecutingSetDeviceReport()) {} char response[50]; // TODO: Find out which is the correct command here // char *cmd = "CSTP"; char *cmd = "CABT"; usbHostGC->SetDeviceReport(usbDevice, cmd, response); // We expect a response like this: "DACK" for success, "DNAK" for failure #define DEBUG_HERE #ifdef DEBUG_HERE char dbg[100]; sprintf(dbg, "%s returned %s", cmd, response); EasyGUIDebugPrint(dbg, 100, 150); #endif #undef DEBUG_HERE return (response[1] == 'A'); } bool ExitGCStandbyMode(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC) { while(usbHostGC->ExecutingSetDeviceReport()) {} char response[50]; usbHostGC->SetDeviceReport(usbDevice, "CDIS", response); // We expect a response like this: "DACK" for success, "DNAK" for failure char dbg[100]; sprintf(dbg, "CDIS returned %s", response); EasyGUIDebugPrint(dbg, 100, 150); if(getGCStatusLoop != NULL) { getGCStatusLoop->ExitedGCStandbyMode(); } return (response[1] == 'A'); } bool ClearGCErrors(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC) { while(usbHostGC->ExecutingSetDeviceReport()) {} char response[50]; usbHostGC->SetDeviceReport(usbDevice, "CCLR", response); // We expect a response like this: "DACK" for success, "DNAK" for failure char dbg[100]; sprintf(dbg, "CCLR returned %s", response); EasyGUIDebugPrint(dbg, 100, 150); return (response[1] == 'A'); } void TouchCallback(touch_coordinate_t touchCoords, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC, int tickCount, bool newTouch) { GuiConst_INT32S touchAreaIndex = GuiLib_TouchCheck((GuiConst_INT16S)touchCoords.x, (GuiConst_INT16S)touchCoords.y); if(touchAreaIndex >= 0) { bool dealtWithTouch = false; // page selector? TouchPanelPageSelector* touchPanelPageSelector = touchPanelPageSelectors.GetTouchPanelPageSelector(touchAreaIndex); if( touchPanelPageSelector != NULL) { // Do not keep switching pages if the user keeps 'touching' - // switch only if he 'lets go', then presses again if(newTouch) { if(touchAreaIndex == 200) { // Stop run - as well as displaying the home page, do this... StopGCRun(usbDevice, usbHostGC); } if(touchAreaIndex == 400) { // Take GC out of standby mode ExitGCStandbyMode(usbDevice, usbHostGC); } if(touchAreaIndex == 600) { // Take GC out of error state ClearGCErrors(usbDevice, usbHostGC); } DisplayEasyGuiStructure(touchPanelPageSelector->GetPageNumber(), usbDevice, usbHostGC); } dealtWithTouch = true; // The user touched a page selector, so we have still 'dealt' with this, // whether we had a 'new touch' or not if(touchAreaIndex == 200) { // Is in same place as Heat On/Off button StartHeatOnOffTimeout(); } } if(!dealtWithTouch) { if(touchAreaIndex == 100) { // Run button if(newTouch) { // As above - do not do this repeatedly - GC does not like it... if(GCIsReadyToRun(usbDevice, usbHostGC)) { // Start run - if this works, display the 'Run' page, else do nothing if(StartGCRun(usbDevice, usbHostGC)) { DisplayEasyGuiStructure(GuiStruct_RunningPage_7, usbDevice, usbHostGC); } else { DrawErrorMessage("*** Run failed to start ***"); // Give user time to read error, then erase it Thread::wait(2000); DisplayEasyGuiStructure(GuiStruct_HomePage_1, usbDevice, usbHostGC); } } // else GC is not ready to run (button should be greyed out) - ignore } dealtWithTouch = true; } } if(!dealtWithTouch) { if(touchAreaIndex == 300) { // Heat on/off button if(newTouch) { // As above - do not do this repeatedly - GC does not like it... if(heatOnOffAvailable) { if(theGCHeatControl != NULL) { if(theGCHeatControl->IsHeatOn()) { theGCHeatControl->TurnHeatOff(); } else { theGCHeatControl->TurnHeatOn(); } UpdateHeatOnOffEasyGuiVariable(); // Make GuiVar_heatOnOffCommand update visible on screen DisplayEasyGuiStructure(GuiStruct_HomePage_1, usbDevice, usbHostGC); StartHeatOnOffTimeout(); } } } // Whether we changed the heat or not, the user still 'touched' our area, // so no-one else should try and deal with this touch dealtWithTouch = true; } } } } void SetupUSBGCTouchListener(DMBoard* board, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC) { // Note that TouchListener is a singleton - we do not need or want there to be more than one instance of it // (there is only one board, and only one touch panel) mainTouchListener = TouchListener::GetInstance(board->touchPanel(), usbDevice, usbHostGC); if(mainTouchListener != NULL) { mainTouchListener->SetTouchCallbackFunction(&TouchCallback); // Not yet... // mainTouchListener->SetTouchReleasedCallbackFunction(&TouchReleasedCallback); // // mainTouchListener->SetTimerOneSecondCallbackFunction(&TimerOneSecondCallback); } } int main() { DMBoard::BoardError err; DMBoard* board = &DMBoard::instance(); RtosLog* log = board->logger(); Display* disp = board->display(); do { err = board->init(); if (err != DMBoard::Ok) { log->printf("Failed to initialize the board, got error %d\r\n", err); break; } log->printf("\n\nHello World!\n\n"); void* fb = disp->allocateFramebuffer(); if (fb == NULL) { log->printf("Failed to allocate memory for a frame buffer\r\n"); err = DMBoard::MemoryError; break; } // Display::DisplayError disperr = disp->powerUp(fb, Display::Resolution_24bit_rgb888); // Start display in default mode (16-bit) (24-bit uses too much memory) Display::DisplayError disperr = disp->powerUp(fb); if (disperr != Display::DisplayError_Ok) { log->printf("Failed to initialize the display, got error %d\r\n", disperr); break; } } while(false); if (err != DMBoard::Ok) { log->printf("\nTERMINATING\n"); wait_ms(2000); // allow RtosLog to flush messages mbed_die(); } // easyGUI stuff - note function calls require 'extern "C"' in relevant header // Need to set up heat on/off command easyGUI variable // before we display the home page for the first time - // but we do not have a heat control object at this point - // default to 'Heat On' strcpy(GuiVar_heatOnOffCommand, "Heat On"); GuiDisplay_Lock(); GuiLib_Init(); GuiLib_Refresh(); DisplayEasyGuiStructure(GuiStruct_HomePage_1, NULL, NULL); GuiLib_Refresh(); GuiDisplay_Unlock(); // Now the USB 'stuff' USBHost* usbHost = USBHost::getHostInst(); USBDeviceConnected* usbDevice; USBHostGC usbHostGC; usbDevice = NULL; DrawErrorMessage("Waiting for USB device..."); // Wait (indefinitely) for a USB device to be connected - // note that, if there is no USB device, we will hang at this point - // there is no timeout while(usbDevice == NULL) { for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; ++i) { usbDevice = usbHost->getDevice(i); if (usbDevice) { break; } } } DrawErrorMessage(" "); if(usbDevice != NULL) { USB_TYPE enumerateRetVal = usbHost->enumerate(usbDevice, &usbHostGC); if (usbHostGC.DeviceIsGC()) { if (usbHostGC.AttachGCDevice(usbDevice)) { DrawErrorMessage("Found GC device "); SetupUSBGCTouchListener(board, usbDevice, &usbHostGC); DrawErrorMessage("After call to SetupUSBGCTouchListener "); getGCStatusLoop = GetGCStatusLoop::GetInstance(usbDevice, &usbHostGC); DrawErrorMessage("After creation of GetGCStatusLoop instance "); theGCHeatControl = new GCHeatControl(usbDevice, &usbHostGC); UpdateHeatOnOffEasyGuiVariable(); DrawErrorMessage("After UpdateHeatOnOffEasyGuiVariable "); //theEthernetTimerHandler = EthernetTimerHandler::GetInstance(usbDevice, &usbHostGC); getGCStatusLoop->SetHomePageGCComponentStatusColorAreas(&homePageGCComponentStatusColorAreas); getGCStatusLoop->SetSingleGCComponentPageStatusColorAreas(&singleGCComponentPageStatusColorAreas); DrawErrorMessage("Point 1 "); getGCStatusLoop->SetupAllEasyGUIVariables(); DrawErrorMessage("Point 2 "); getGCStatusLoop->SetCurrentPage(GuiStruct_HomePage_1); DrawErrorMessage("Point 3 "); DisplayEasyGuiStructure(GuiStruct_HomePage_1, usbDevice, &usbHostGC); // Currently, this never returns - but it allows time for the TouchCallback function to be invoked //getGCStatusLoop->MainLoop(); getGCStatusLoop->MainLoopWithEthernet(); // Should never reach this code - but just in case... delete theGCHeatControl; } else { DrawErrorMessage("Failed to attach GC device to host "); } } else { DrawErrorMessage(" *** USB device found, is *not* a GC *** "); } } else { DrawErrorMessage(" *** No USB device found *** "); } while(true) {} }