Repository for import to local machine

Dependencies:   DMBasicGUI DMSupport

ColumnDHManualCalibrationPageHandler.cpp

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

File content as of revision 8:26e49e6955bd:

#include "ColumnDHManualCalibrationPageHandler.h"
#include "EasyGUITouchAreaIndices.h"
#include "GetGCStatusLoop.h"
#include "NumericKeypadPageHandler.h"
#include "USBHostGCUtilities.h"

/*                      
    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 values for the same calibration parameters, etc, and nor will we show 
    more than one easyGUI 'ColumnDHManualCalibrationPage' to the user at the same time).
*/
ColumnDHManualCalibrationPageHandler * ColumnDHManualCalibrationPageHandler::theColumnDHManualCalibrationPageHandlerInstance = NULL;


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

/*
    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
*/
ColumnDHManualCalibrationPageHandler * ColumnDHManualCalibrationPageHandler::GetInstance(void)
{
    return theColumnDHManualCalibrationPageHandlerInstance;
}


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


    variablesForTouchArea[0].touchAreaIndex                    = COLUMN_DH_MANUAL_CALIB_EDIT_TEMP1;
    variablesForTouchArea[0].easyGUIVariablePtr                = GuiVar_columnDHManualCalibTemp1;
    variablesForTouchArea[0].maxValue                          = 999;
    variablesForTouchArea[0].placesOfDecimals                  = 1;
    strcpy(variablesForTouchArea[0].variableTitle, "Temp Point 1");

    variablesForTouchArea[1].touchAreaIndex                    = COLUMN_DH_MANUAL_CALIB_EDIT_TEMP2;
    variablesForTouchArea[1].easyGUIVariablePtr                = GuiVar_columnDHManualCalibTemp2;
    variablesForTouchArea[1].maxValue                          = 999;
    variablesForTouchArea[1].placesOfDecimals                  = 1;
    strcpy(variablesForTouchArea[1].variableTitle, "Temp Point 2");

    variablesForTouchArea[2].touchAreaIndex                    = COLUMN_DH_MANUAL_CALIB_EDIT_TEMP3;
    variablesForTouchArea[2].easyGUIVariablePtr                = GuiVar_columnDHManualCalibTemp3;
    variablesForTouchArea[2].maxValue                          = 999;
    variablesForTouchArea[2].placesOfDecimals                  = 1;
    strcpy(variablesForTouchArea[2].variableTitle, "Temp Point 3");

    variablesForTouchArea[3].touchAreaIndex                    = COLUMN_DH_MANUAL_CALIB_EDIT_RES1;
    variablesForTouchArea[3].easyGUIVariablePtr                = GuiVar_columnDHManualCalibRes1;
    variablesForTouchArea[3].maxValue                          = 99;
    variablesForTouchArea[3].placesOfDecimals                  = 2;
    strcpy(variablesForTouchArea[3].variableTitle, "Res Point 1");

    variablesForTouchArea[4].touchAreaIndex                    = COLUMN_DH_MANUAL_CALIB_EDIT_RES2;
    variablesForTouchArea[4].easyGUIVariablePtr                = GuiVar_columnDHManualCalibRes2;
    variablesForTouchArea[4].maxValue                          = 99;
    variablesForTouchArea[4].placesOfDecimals                  = 2;
    strcpy(variablesForTouchArea[4].variableTitle, "Res Point 2");

    variablesForTouchArea[5].touchAreaIndex                    = COLUMN_DH_MANUAL_CALIB_EDIT_RES3;
    variablesForTouchArea[5].easyGUIVariablePtr                = GuiVar_columnDHManualCalibRes3;
    variablesForTouchArea[5].maxValue                          = 99;
    variablesForTouchArea[5].placesOfDecimals                  = 2;
    strcpy(variablesForTouchArea[5].variableTitle, "Res Point 3");
}

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


/*
    Tells the caller whether or not the specified touch index is on the easyGUI 'ColumnDHAutoCalibrationPage',
    and therefore needs to be handled by this class.
    
    Args: the touch area index in question
    
    Return code: true if the touch area is 'one of ours', false if not
*/
bool ColumnDHManualCalibrationPageHandler::TouchAreaIsOnCalibrationPage(int touchAreaIndex)
{
    if((touchAreaIndex >= MIN_COLUMN_DH_MANUAL_CALIB_TOUCHINDEX) && (touchAreaIndex <= MAX_COLUMN_DH_MANUAL_CALIB_TOUCHINDEX)) {
        return true;
    }
    
    // 'else'
    return false;
}


/*
    If the specified touch area represents a key or field on the easyGUI 'ColumnDHManualCalibrationPage',
    this function performs whatever action is appropriate for it. Provided so that the caller
    can (in effect) say "if this is one of yours, deal with it", without needing to know 
    anything about what this class does, or how it handles the touch areas on that easyGUI page.

    Args: the touch area index in question
    
    Returns true if it dealt with the touch area (so the caller need not do anything else 
    with the value), or false if it did not deal with the touch area (implying that it 
    was not a touch area on the easyGUI 'Directly Heated Column Manual CalibrationPage', and so the caller
    must deal with it some other way).
*/
bool ColumnDHManualCalibrationPageHandler::DealWithTouch(int touchAreaIndex)
{
    bool dealtWithTouch = false; // so far...
    
    // Has the user selected a field to edit - 
    // if so, we will have an entry in our 'variablesForTouchArea' array that corresponds with this touch area
    int indexOfValueToEdit = GetIndexOfValueToEditForTouchArea(touchAreaIndex);
    if(indexOfValueToEdit  != -1) {        
        // User has selected a field to edit
        NumericKeypadPageHandler* numericKeypadPageHandler = NumericKeypadPageHandler::GetInstance(usbDevice, usbHostGC);
        if(numericKeypadPageHandler != NULL) {
            numericKeypadPageHandler->StartEditing(variablesForTouchArea[indexOfValueToEdit].easyGUIVariablePtr,
                                                   variablesForTouchArea[indexOfValueToEdit].placesOfDecimals);
            numericKeypadPageHandler->SetEasyGUIVariableToEdit(variablesForTouchArea[indexOfValueToEdit].easyGUIVariablePtr);
            numericKeypadPageHandler->SetEasyGUICallingPage(GuiStruct_ColumnDHManualCalibrationPage_Def);
            numericKeypadPageHandler->SetEditVariableRange(0, variablesForTouchArea[indexOfValueToEdit].maxValue);
            numericKeypadPageHandler->SetEditVariableName(variablesForTouchArea[indexOfValueToEdit].variableTitle);
            numericKeypadPageHandler->DisplayEasyGUIPage();
        }

        dealtWithTouch = true;
    } 
        
    if(!dealtWithTouch) {
        switch(touchAreaIndex) {
            case COLUMN_DH_MANUAL_CALIB_SET:
                SetCurrentCalibrationInGC();
                dealtWithTouch = true;
                break;
    
            case COLUMN_DH_MANUAL_CALIB_GET:
                GetCurrentCalibrationFromGC();
                dealtWithTouch = true;
                break;
    
            default: // Not recognised - do nothing
                break;
        }
    }
        
    return dealtWithTouch;
}


/*
    Caller is telling us it is about to display the easyGUI 'ColumnDHManualCalibrationPage',
    and that we should do whatever we have to do to get it ready,
    before the caller displays it.
    
    No arguments, no return code
*/
void ColumnDHManualCalibrationPageHandler::DisplayingEasyGUIPage(bool updateEasyGUIVariables)
{
    if(updateEasyGUIVariables) {
        GetCurrentCalibrationFromGC();
    }
}


/*
    Gets the current calibration temperature and resistance values from the GC,
    and copies them into the relevant easyGUI variables for display to the user.
    
    No arguments, no return code
*/
void ColumnDHManualCalibrationPageHandler::GetCurrentCalibrationFromGC(void)
{
    GetColumnTemperaturePointFromGC(1, GuiVar_columnDHManualCalibTemp1);
    GetColumnResistancePointFromGC(1, GuiVar_columnDHManualCalibRes1);

    GetColumnTemperaturePointFromGC(2, GuiVar_columnDHManualCalibTemp2);
    GetColumnResistancePointFromGC(2, GuiVar_columnDHManualCalibRes2);

    GetColumnTemperaturePointFromGC(3, GuiVar_columnDHManualCalibTemp3);
    GetColumnResistancePointFromGC(3, GuiVar_columnDHManualCalibRes3);
}


/*
    Sets the calibration temperature and resistance values in the GC,
    to match the values we are currently displayin to the user.
    
    No arguments, no return code
*/
void ColumnDHManualCalibrationPageHandler::SetCurrentCalibrationInGC(void)
{
    SetColumnTemperaturePointInGC(1, GuiVar_columnDHManualCalibTemp1);
    SetColumnResistancePointInGC(1, GuiVar_columnDHManualCalibRes1);

    SetColumnTemperaturePointInGC(2, GuiVar_columnDHManualCalibTemp2);
    SetColumnResistancePointInGC(2, GuiVar_columnDHManualCalibRes2);

    SetColumnTemperaturePointInGC(3, GuiVar_columnDHManualCalibTemp3);
    SetColumnResistancePointInGC(3, GuiVar_columnDHManualCalibRes3);
}


/*
    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 ColumnDHManualCalibrationPageHandler::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);
//#define DEBUG_PRINT_HERE
#ifdef DEBUG_PRINT_HERE
    char dbg[100];
    sprintf(dbg, "SCTGC cmd \"%s\", response \"%s\"", command, response);
    SpecialDebugPrint(dbg, 10, 275);
#endif // DEBUG_PRINT_HERE
#endif // USE_GC_UTILS 
}


/*
    Sends a command to the GC for which we expect a response of "DACK" if successful,
    "DNAK" or "EPKT" if failure.
    
    Args: a pointer to the command in question, as a null terminated string
    
    Returns true if the GC responded with "DACK", false for anything else
*/
bool ColumnDHManualCalibrationPageHandler::SendCommandToGCWithDACKResponse(char *cmd)
{
#define USE_GC_UTILS // Testing new class
#ifdef USE_GC_UTILS
    return USBHostGCUtilities::SendCommandToGCWithDACKResponse(usbDevice, usbHostGC, cmd);
#else
    char response[50];
    SendCommandToGCAndGetResponse(cmd, response);
    // We expect a response like this: "DACK" for success, "DNAK" for failure, "EPKT" for error
    
    return (response[1] == 'A');
#endif // USE_GC_UTILS 
}


/*
    There are three temperature points included in the manual calibration of the DH column.
    This function gets the value for the specified point, and copies it
    into the specified easyGUI variable (to be displayed on the easyGUI ColumnDHManualCalibration page).
    
    Args:   the number of the point to be displayed (1, 2 or 3)
            a pointer to the corresponding easyGUI variable
            
    Returns true if successful, false if not.
*/
bool ColumnDHManualCalibrationPageHandler::GetColumnTemperaturePointFromGC(int pointNumber, GuiConst_TEXT* easyGUIVariable)
{
    char cmd[50];
    char response[50];
    
    if((pointNumber < 1) || (pointNumber > 3)) {
        return false;
    }
    
    sprintf(cmd, "GCT%d", pointNumber);
    
    SendCommandToGCAndGetResponse(cmd, response);

    if(response[0] != 'D') return false;    
    if(response[1] != 'C') return false;    
    if(response[2] != 'T') return false;    
    if(response[3] != cmd[3]) return false;    
    
    // Response is in units of 1/10 degree C - 
    // and we don't want leading zeroes
    int index = 0;
    bool wantZeroes = false;
    if(response[4] != '0') {
        easyGUIVariable[index++] = response[4];
        wantZeroes = true;
    }
    if((response[5] != '0') || wantZeroes) {
        easyGUIVariable[index++] = response[5];
    }
    easyGUIVariable[index++] = response[6];
    easyGUIVariable[index++] = '.';
    easyGUIVariable[index++] = response[7];
    easyGUIVariable[index] = '\0';
    
    return true;
}


/*
    There are three temperature points included in the manual calibration of the DH column.
    This function sets the value for the specified point in the GC from our internal variable,
    whose value matches the one displayed to the user in the relevant easyGUI variable.
    
    Args:   the number of the point to be displayed (1, 2 or 3)
            
    Returns true if successful, false if not.
*/
bool ColumnDHManualCalibrationPageHandler::SetColumnTemperaturePointInGC(int pointNumber, GuiConst_TEXT* easyGUIVariable)
{
    char cmd[50];
    
    if((pointNumber < 1) || (pointNumber > 3)) {
        return false;
    }
    
    // temperature is passed to the GC in units of 0.1 degree C
    float temp;
    sscanf(easyGUIVariable, "%f", &temp);
    int gcTemp = (int)(temp * 10.0f);
    
    // In the command, the temperature value must have 4 digits, padded if necessary with leading zeroes
    sprintf(cmd, "SCT%d%.4d", pointNumber, gcTemp); 
    
    return SendCommandToGCWithDACKResponse(cmd);
}


/*
    There are three resistance points included in the manual calibration of the DH column.
    This function gets the value for the specified point, and copies it
    into the specified easyGUI variable (to be displayed on the easyGUI ColumnDHManualCalibration page).
    
    Args:   the number of the point to be displayed (1, 2 or 3)
            a pointer to the corresponding easyGUI variable
            
    Returns true if successful, false if not.
*/
bool ColumnDHManualCalibrationPageHandler::GetColumnResistancePointFromGC(int pointNumber, GuiConst_TEXT* easyGUIVariable)
{
    char cmd[50];
    char response[50];
    
    if((pointNumber < 1) || (pointNumber > 3)) {
        return false;
    }
    
    sprintf(cmd, "GCR%d", pointNumber);
    
    SendCommandToGCAndGetResponse(cmd, response);

    if(response[0] != 'D') return false;    
    if(response[1] != 'C') return false;    
    if(response[2] != 'R') return false;    
    if(response[3] != cmd[3]) return false;    
    
    // Response is in units of 1/100 ohm - 
    // and we don't want leading zeroes
    int index = 0;
    if(response[4] != '0') easyGUIVariable[index++] = response[4];
    easyGUIVariable[index++] = response[5];
    easyGUIVariable[index++] = '.';
    easyGUIVariable[index++] = response[6];
    easyGUIVariable[index++] = response[7];
    easyGUIVariable[index] = '\0';
    
    return true;
}


/*
    There are three resistance points included in the manual calibration of the DH column.
    This function sets the value for the specified point in the GC from our internal variable,
    whose value matches the one displayed to the user in the relevant easyGUI variable.
    
    Args:   the number of the point to be displayed (1, 2 or 3)
            
    Returns true if successful, false if not.
*/
bool ColumnDHManualCalibrationPageHandler::SetColumnResistancePointInGC(int pointNumber, GuiConst_TEXT* easyGUIVariable)
{
    char cmd[50];
    
    if((pointNumber < 1) || (pointNumber > 3)) {
        return false;
    }
    
    // Resistance is passed to the GC in units of 0.01 ohm
    float res;
    sscanf(easyGUIVariable, "%f", &res);
    int gcRes = (int)(res * 100.0f);
    
    // In the command, the resistance value must have 4 digits, padded if necessary with leading zeroes
    sprintf(cmd, "SCR%d%.4d", pointNumber, gcRes);
    
    return SendCommandToGCWithDACKResponse(cmd);
}


/*
    (Re)display the easyGUI 'ColumnDHManualCalibrationPage' -
    e.g. after the caller has updated one or more of the easyGUI variables
    included in the page, and wants to display the new value to the user.
    
    No arguments, no return code
*/
void ColumnDHManualCalibrationPageHandler::UpdateEasyGUIPage(void)
{
    GetGCStatusLoop *getGCStatusLoop = GetGCStatusLoop::GetInstance();
    
    if(getGCStatusLoop != NULL) {
        // The Gas Calibration page has a status rectangle for the gas - 
        // GetGCStatusLoop can display this, we cannot
        getGCStatusLoop->ForceUpdateOfColumnDHManualCalibrationPage();
    }
}


/*
    Tells the caller if the specified touch area corresponds to a value the user can edit
    on the easyGUI 'ColumnDHManualCalibrationPage', and if so, which one.
    
    Args: the touch area index in question
    
    Returns the index of the corresponding entry in our 'variablesForTouchArea' array,
    or -1 if there is no such entry. It is up to the caller to check for -1
                                     **************************************
*/
int ColumnDHManualCalibrationPageHandler::GetIndexOfValueToEditForTouchArea(int touchAreaIndex)
{
    for (int index = 0; index < COUNT_OF_VARIABLES_FOR_TOUCH_AREAS; ++index) {
        if(variablesForTouchArea[index].touchAreaIndex == touchAreaIndex) {
            return index;
        }
    }
    
    // 'else' no Column DH Manual Calibration value corresponds to the specified touch area
    return -1;
}