Repository for import to local machine

Dependencies:   DMBasicGUI DMSupport

DetectorIgnitionHandler.cpp

Committer:
jmitc91516
Date:
2017-07-31
Revision:
8:26e49e6955bd
Parent:
1:a5258871b33d

File content as of revision 8:26e49e6955bd:

#include "DetectorIgnitionHandler.h"
#include "EasyGUITouchAreaIndices.h"
#include "GetGCStatusLoop.h"
#include "USBHostGCUtilities.h"

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define DRAW_TEXT_ON_IGNITE_BUTTON
//#define PERFORM_FULL_IGNITION_SEQUENCE // not #define'd currently - we display the ignition state on the Detector page anyway

/*
    Passed three 8-bit colour components - red, green and blue.
    Returns the corresponding 16-bit colour value (5 bits for red, 6 bits for green, 5 bits for blue).
    
    Defined in main.cpp
*/
extern GuiConst_INTCOLOR SixteenBitColorValue(GuiConst_INT8U red, GuiConst_INT8U green, GuiConst_INT8U blue);


/*                      
    Note that this class is a singleton - we do not need or want there to be more than one instance of it
    (we do not want multiple ignition attempts going on simultaneously, and nor will we show 
    more than one easyGUI Detector page to the user at the same time).
*/
DetectorIgnitionHandler * DetectorIgnitionHandler::theDetectorIgnitionHandlerInstance = NULL;

/*
    Tell the world whether or not we are currently trying to ignite the detector
*/
bool DetectorIgnitionHandler::igniting = false;

/*
    Singleton class - return the one and only instance, first creating it if necessary.
*/
DetectorIgnitionHandler * DetectorIgnitionHandler::GetInstance(USBDeviceConnected* newUsbDevice, USBHostGC* newUsbHostGC)
{
    if (theDetectorIgnitionHandlerInstance == NULL) {
        theDetectorIgnitionHandlerInstance = new DetectorIgnitionHandler(newUsbDevice, newUsbHostGC);
    }
    
    return theDetectorIgnitionHandlerInstance;
}

/*
    Overriden version of the above, that does not take any arguments and does not create the instance 
    if it does not already exist.
    
    Provided for callers that do not have the 'usbDevice' and'usbHostGC' pointers, and just want access 
    to the instance if it exists
*/
DetectorIgnitionHandler * DetectorIgnitionHandler::GetInstance(void)
{
    return theDetectorIgnitionHandlerInstance;
}


// Singleton class - private constructor
DetectorIgnitionHandler::DetectorIgnitionHandler(USBDeviceConnected* newUsbDevice, USBHostGC* newUsbHostGC)
{
    usbDevice = newUsbDevice;
    usbHostGC = newUsbHostGC;
}

// Private destructor also
DetectorIgnitionHandler::~DetectorIgnitionHandler()
{
}


/*
    Tells the caller whether or not the specified touch area is the one this class handles
    
    Args: the index of the touch area in question
    
    Returns true if this class handles that touch area, false if not
*/
bool DetectorIgnitionHandler::TouchAreaIsDetectorIgniteButton(int touchAreaIndex)
{
    return (touchAreaIndex == DETECTOR_IGNITE_BUTTON);
}


/*
    If the touch area is the detector ignite button, deals with it and returns true.
    Else returns false.
    
    Args: the index of the touch area in question
    
    Returns: true if it dealt with the touch area, false if not
*/
bool DetectorIgnitionHandler::DealWithTouch(int touchAreaIndex)
{
    if (touchAreaIndex == DETECTOR_IGNITE_BUTTON) {
        
        // Ignore button press if we are already igniting
        if(!igniting) {
            PerformIgnitionSequence();
        }
        
        return true;
    }
    
    // 'else' ...
    return false;
}


/*
    The FID and FPD detectors require to be ignited before use. The sequence is: 
    
        send "CIGN" to the GC
        
        then poll every 1 second (say) with "QIGN"
    
    This will return "DIGN0002" while trying to ignite, then "DIGN0003" if lit or "DIGN0001" if failed to light. 
    
    We indicate the status by displaying text on top of the ignite button.
*/
void DetectorIgnitionHandler::PerformIgnitionSequence(void)
{
    if(TellGCToIgniteDetector()) {
        
#ifdef PERFORM_FULL_IGNITION_SEQUENCE
        igniting = true;
        
#ifdef DRAW_TEXT_ON_IGNITE_BUTTON
        DrawIgnitionLightingText();
#endif
            
        Thread::wait(1000); // 1 second
    
        IgnitionState ignitionState = GetDetectorIgnitionState();
            
        while(ignitionState == LIGHTING) {
            
            Thread::wait(1000); // 1 second
            
            ignitionState = GetDetectorIgnitionState();
        }
        
#ifdef DRAW_TEXT_ON_IGNITE_BUTTON
        if(ignitionState == LIT) {
            DrawIgnitionLitText();
        } else {
            // Assume not lit
            DrawIgnitionNotLitText();
        }
#endif
        
        igniting = false;
#endif // PERFORM_FULL_IGNITION_SEQUENCE

    }
}


/*
    As the name implies, sends a command to the GC and returns the response.
    
    Args: pointer to a buffer containing the command, as a null-terminated string
          pointer to a buffer to contain the response, as a null-terminated string
          
    No return code (it is up to the caller to examine the response to see whether 
    the command succeeded or failed)
*/
void DetectorIgnitionHandler::SendCommandToGCAndGetResponse(char* command, char* response)
{
#define USE_GC_UTILS // Testing new class
#ifdef USE_GC_UTILS
    USBHostGCUtilities::SendCommandToGCAndGetResponse(usbDevice, usbHostGC, command, response);
#else
    while(usbHostGC->ExecutingSetDeviceReport()) {}

    usbHostGC->SetDeviceReport(usbDevice, command, response);
#endif // USE_GC_UTILS
}


/*
    Tells the GC to ignite, i.e. sends it a "CIGN" command
    
    Returns true if the GC responded with "DACK", false for anything else
*/
bool DetectorIgnitionHandler::TellGCToIgniteDetector(void)
{
    char response[50];
    SendCommandToGCAndGetResponse("CIGN", response);
    // We expect a response like this: "DACK" for success, "DNAK" for failure, "EPKT" for error
    
    return (response[1] == 'A');
}


/*
    Gets the detector ignition state (not lit, igniting, lit), and returns it 
    as a value in the IgnitionState enumeration.
    
    Args: none
          
    Returns: the ignition state (not lit, lighting, lit);
*/
IgnitionState DetectorIgnitionHandler::GetDetectorIgnitionState(void)
{
    char response[50];
    SendCommandToGCAndGetResponse("QIGN", response);

    // We expect a response like this: "DIGN0001" for "not lit", 
    // "DIGN0002" for "igniting", "DIGN0003" for "lit"
    
    // Check for "EPKT" first
    if(response[0] == 'E') {
        return NOT_LIT;
    }
    
    // 'else'...
    switch (response[7]) {
        case '2': 
            return LIGHTING;
        case '3': 
            return LIT;
        default:
            return NOT_LIT;
    }
}


/*
    Draws the specified text on top of the Ignite button - i.e. at the bottom of the display, 
    in the centre, in the specified colour.
    
    Args: boolean, true to display the text, false to erase it
          pointer to the (null-terminated) text
          the foregound (i.e. text) colour
          the background colour
    
    No return code.
*/
void DetectorIgnitionHandler::DrawTextOnIgniteButton(char* text, GuiConst_INTCOLOR foreColor, GuiConst_INTCOLOR backColor)
{
    const GuiConst_INT16U fontNo = GuiFont_Helv20Bold;
    
    const GuiConst_INT16S X = 400; // Centre of display
    const GuiConst_INT16S Y = 450; // Over the Ignite button
    
    GuiLib_DrawStr(
        X,                      //GuiConst_INT16S X,
        Y,                      //GuiConst_INT16S Y,
        fontNo,                 //GuiConst_INT16U FontNo,
        text,                   //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,
        foreColor,              //GuiConst_INTCOLOR ForeColor,
        backColor               //GuiConst_INTCOLOR BackColor
    ); 
}

/*
    Draws "Lighting" on top of the ignite button, in yellow
    
    No arguments, no return code
*/
void DetectorIgnitionHandler::DrawIgnitionLightingText(void)
{
    DrawTextOnIgniteButton("Lighting", SixteenBitColorValue(236, 219, 0), SixteenBitColorValue(0, 0, 0));
}

/*
    Draws "Lit" on top of the ignite button, in green
    
    No arguments, no return code
*/
void DetectorIgnitionHandler::DrawIgnitionLitText(void)
{
    DrawTextOnIgniteButton("Lit", SixteenBitColorValue(0, 236, 5), SixteenBitColorValue(0, 0, 0));
}

/*
    Draws "Not Lit" on top of the ignite button, in red
    
    No arguments, no return code
*/
void DetectorIgnitionHandler::DrawIgnitionNotLitText(void)
{
    DrawTextOnIgniteButton("Not Lit", SixteenBitColorValue(255, 0, 0), SixteenBitColorValue(0, 0, 0));
}