Repository for import to local machine

Dependencies:   DMBasicGUI DMSupport

ColumnDHSensorCalibrationPageHandler.cpp

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

File content as of revision 8:26e49e6955bd:

#include "ColumnDHSensorCalibrationPageHandler.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 'ColumnDHSensorCalibrationPage' to the user at the same time).
*/
ColumnDHSensorCalibrationPageHandler * ColumnDHSensorCalibrationPageHandler::theColumnDHSensorCalibrationPageHandlerInstance = NULL;


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

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


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

    variablesForTouchArea[0].touchAreaIndex        = COLUMN_DH_SENSOR_CALIB_EDIT_VOLTAGE_GAIN;
    variablesForTouchArea[0].easyGUIVariablePtr    = GuiVar_columnDHSensorCalibVoltageGain;
    variablesForTouchArea[0].maxValue              = 9999;
    variablesForTouchArea[0].minValue              = 0;
    variablesForTouchArea[0].canBeNegative         = false;
    strcpy(variablesForTouchArea[0].variableTitle, "Voltage Gain");

    variablesForTouchArea[1].touchAreaIndex        = COLUMN_DH_SENSOR_CALIB_EDIT_VOLTAGE_OFFSET;
    variablesForTouchArea[1].easyGUIVariablePtr    = GuiVar_columnDHSensorCalibVoltageOffset;
    variablesForTouchArea[1].maxValue              = 50;
    variablesForTouchArea[1].minValue              = -50;
    variablesForTouchArea[1].canBeNegative         = true;
    strcpy(variablesForTouchArea[1].variableTitle, "Voltage Offset");

    variablesForTouchArea[2].touchAreaIndex        = COLUMN_DH_SENSOR_CALIB_EDIT_CURRENT_GAIN;
    variablesForTouchArea[2].easyGUIVariablePtr    = GuiVar_columnDHSensorCalibCurrentGain;
    variablesForTouchArea[2].maxValue              = 9999;
    variablesForTouchArea[2].minValue              = 0;
    variablesForTouchArea[2].canBeNegative         = false;
    strcpy(variablesForTouchArea[2].variableTitle, "Current Gain");

    variablesForTouchArea[3].touchAreaIndex        = COLUMN_DH_SENSOR_CALIB_EDIT_CURRENT_OFFSET;
    variablesForTouchArea[3].easyGUIVariablePtr    = GuiVar_columnDHSensorCalibCurrentOffset;
    variablesForTouchArea[3].maxValue              = 50;
    variablesForTouchArea[3].minValue              = -50;
    variablesForTouchArea[3].canBeNegative         = true;
    strcpy(variablesForTouchArea[3].variableTitle, "Current Offset");
}

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


/*
    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 ColumnDHSensorCalibrationPageHandler::TouchAreaIsOnCalibrationPage(int touchAreaIndex)
{
    if((touchAreaIndex >= MIN_COLUMN_DH_SENSOR_CALIB_TOUCHINDEX) && (touchAreaIndex <= MAX_COLUMN_DH_SENSOR_CALIB_TOUCHINDEX)) {
        return true;
    }
    
    // 'else'
    return false;
}


/*
    If the specified touch area represents a key or field on the easyGUI 'ColumnDHSensorCalibrationPage',
    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 Sensor Calibration Page', and so the caller
    must deal with it some other way).
*/
bool ColumnDHSensorCalibrationPageHandler::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, 0, 
                                                   variablesForTouchArea[indexOfValueToEdit].canBeNegative);
            numericKeypadPageHandler->SetEasyGUIVariableToEdit(variablesForTouchArea[indexOfValueToEdit].easyGUIVariablePtr);
            numericKeypadPageHandler->SetEasyGUICallingPage(GuiStruct_ColumnDHSensorCalibration_Def);
            numericKeypadPageHandler->SetEditVariableRange(variablesForTouchArea[indexOfValueToEdit].minValue, variablesForTouchArea[indexOfValueToEdit].maxValue);
            numericKeypadPageHandler->SetEditVariableName(variablesForTouchArea[indexOfValueToEdit].variableTitle);
            numericKeypadPageHandler->DisplayEasyGUIPage();
        }

        dealtWithTouch = true;
    } 
    
    if(!dealtWithTouch) {
        switch(touchAreaIndex) {
            case COLUMN_DH_SENSOR_CALIB_SET:
                SetCurrentCalibrationInGC();
                dealtWithTouch = true;
                break;
    
            case COLUMN_DH_SENSOR_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 'ColumnDHSensorCalibrationPage',
    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 ColumnDHSensorCalibrationPageHandler::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 ColumnDHSensorCalibrationPageHandler::GetCurrentCalibrationFromGC(void)
{
    GetGainCalibrationFromGC("GVSR", GuiVar_columnDHSensorCalibVoltageGain);
    
    GetOffsetCalibrationFromGC("GVSO", GuiVar_columnDHSensorCalibVoltageOffset);
    
    GetGainCalibrationFromGC("GCSR", GuiVar_columnDHSensorCalibCurrentGain);
    
    GetOffsetCalibrationFromGC("GCSO", GuiVar_columnDHSensorCalibCurrentOffset);
}


/*
    Sets the calibration temperature and resistance values in the GC,
    to match the values we are currently displaying to the user.
    
    No arguments, no return code
*/
void ColumnDHSensorCalibrationPageHandler::SetCurrentCalibrationInGC(void)
{
    SetGainCalibrationInGC("SVSR", GuiVar_columnDHSensorCalibVoltageGain);
    SetOffsetCalibrationInGC("SVSO", GuiVar_columnDHSensorCalibVoltageOffset);
    SetGainCalibrationInGC("SCSR", GuiVar_columnDHSensorCalibCurrentGain);
    SetOffsetCalibrationInGC("SCSO", GuiVar_columnDHSensorCalibCurrentOffset);
}


/*
    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 ColumnDHSensorCalibrationPageHandler::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 ColumnDHSensorCalibrationPageHandler::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
}


/*
    The commands to get the Current and Voltage Sensor Gain Calibration values are very similar,
    including the format of their data values. This function gets the value using the specified command,
    and copies the value into the specified easyGUI variable.
    
    It is up to the caller to display the updated easyGUI variable to the user.
    
    Returns true if successful, false if not.
*/
bool ColumnDHSensorCalibrationPageHandler::GetGainCalibrationFromGC(char *cmd, GuiConst_TEXT* easyGUIVariable)
{
    char response[50];
    
    SendCommandToGCAndGetResponse(cmd, response);
    if((response[0] == 'D') &&
       (response[1] == cmd[1]) &&
       (response[2] == cmd[2]) &&
       (response[3] == cmd[3])) {
           
        // The response data is simply a value from 0 to 9999,
        // - but we don't want leading zeroes
        response[8]= '\0'; // This appears to be necessary 
        int calib;
        sscanf(&response[4], "%d", &calib);
        sprintf(easyGUIVariable, "%d", calib);
        
        return true;
    }
    
    // 'else' 
    return false;
}


/*
    The commands to get the Current and Voltage Sensor Offset Calibration values are very similar,
    including the format of their data values. This function gets the value using the specified command,
    and copies the value into the specified easyGUI variable.
    
    It is up to the caller to display the updated easyGUI variable to the user.
    
    Returns true if successful, false if not.
*/
bool ColumnDHSensorCalibrationPageHandler::GetOffsetCalibrationFromGC(char *cmd, GuiConst_TEXT* easyGUIVariable)
{
    char response[50];
    
    SendCommandToGCAndGetResponse(cmd, response);
    if((response[0] == 'D') &&
       (response[1] == cmd[1]) &&
       (response[2] == cmd[2]) &&
       (response[3] == cmd[3])) {
           
        // The response data is a value from 0 to 100,
        // which corresponds to user values from -50 to +50 -
        // so we subtract 50 before displaying the value to the user
        
        int temp;
        sscanf(&response[4], "%d", &temp);
        temp -= 50;
        sprintf(easyGUIVariable, "%d", temp);
        
        return true;
    }
    
    // 'else' 
    return false;
}



/*
    The commands to set the Current and Voltage Sensor Gain Calibration values are very similar,
    including the format of their data values. This function sets the value in the GC 
    using the specified command, and obtaining the value from the specified easyGUI variable.
    
    Returns true if successful, false if not.
*/
bool ColumnDHSensorCalibrationPageHandler::SetGainCalibrationInGC(char *cmd, GuiConst_TEXT* easyGUIVariable)
{
    char buffer[50];
    
    // In the command, the gain calibration value must have 4 digits, padded if necessary with leading zeroes
    int calib;
    sscanf(easyGUIVariable, "%d", &calib);
    sprintf(buffer, "%s%.4d", cmd, calib); 
    
    return SendCommandToGCWithDACKResponse(buffer);
}


/*
    The commands to set the Current and Voltage Sensor Offset Calibration values are very similar,
    including the format of their data values. This function sets the value in the GC 
    using the specified command, and obtaining the value from the specified easyGUI variable.
    
    Returns true if successful, false if not.
*/
bool ColumnDHSensorCalibrationPageHandler::SetOffsetCalibrationInGC(char *cmd, GuiConst_TEXT* easyGUIVariable)
{
    char buffer[50];
    
    // The offset values we display to the user are in the range -50 to +50. 
    // However, the range we send to the GC is 0 to 100 -
    // so we must add 50 before sending the value to the GC.
    // Also, the value we send must have 4 digits, padded if necessary with leading zeroes
    int temp;
    sscanf(easyGUIVariable, "%d", &temp);
    temp += 50;
    sprintf(buffer, "%s%.4d", cmd, temp); 
    
    return SendCommandToGCWithDACKResponse(buffer);
}


/*
    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 ColumnDHSensorCalibrationPageHandler::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 Sensor Calibration value corresponds to the specified touch area
    return -1;
}