Repository for import to local machine

Dependencies:   DMBasicGUI DMSupport

GasCalibrationPageHandler.cpp

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

File content as of revision 8:26e49e6955bd:

#include "GasCalibrationPageHandler.h"
#include "EasyGUITouchAreaIndices.h"
#include "SettingsHandler.h"
#include "GetGCStatusLoop.h"
#include "NumericKeypadPageHandler.h"

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



/*
    Displays the specified easyGUI 'structure' (or page, to use a more easily understood term).
    Defined in main.cpp
*/
extern void DisplayEasyGuiStructure(int structureIndex, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC, bool updateEasyGUIVariables = true);


/*
    Converts three eight-bit colour values to the corresponding 16-bit RGB565 value.
    Defined in main.cpp
*/
GuiConst_INTCOLOR SixteenBitColorValue(GuiConst_INT8U red, GuiConst_INT8U green, GuiConst_INT8U blue); 

/*
    We distinguish the 'active' field - i.e. the one being edited by the user - 
    from the inactive fields, by its background colour
*/
#define EXPERIMENTING_WITH_COLORS
const GuiConst_INTCOLOR GasCalibrationPageHandler::inactiveFieldBackgroundColour = SixteenBitColorValue(192, 192, 192); // Grey
#ifdef EXPERIMENTING_WITH_COLORS
const GuiConst_INTCOLOR GasCalibrationPageHandler::activeFieldBackgroundColour   = SixteenBitColorValue(255, 255, 0); // Yellow
#else
const GuiConst_INTCOLOR GasCalibrationPageHandler::activeFieldBackgroundColour   = SixteenBitColorValue(255, 255, 255); // White
#endif // EXPERIMENTING_WITH_COLORS


/*                      
    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 carrier gas selection, etc, and nor will we show 
    more than one easyGUI 'GasCalibrationPage' to the user at the same time).
*/
GasCalibrationPageHandler * GasCalibrationPageHandler::theGasCalibrationPageHandlerInstance = NULL;


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

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

    variablesForTouchArea[0].touchAreaIndex                    = GAS_CALIB_DAC_1_VALUE_EDIT;
    variablesForTouchArea[0].easyGUIVariablePtr                = GuiVar_gasCalibDAC1;
    variablesForTouchArea[0].maxValue                          = 4095;
    variablesForTouchArea[0].easyGUIBackgroundColorVariablePtr = &GuiVar_gasCalibDAC1BackgroundColour;
    strcpy(variablesForTouchArea[0].variableName, "DAC value 1");

    variablesForTouchArea[1].touchAreaIndex                    = GAS_CALIB_FLOW_1_VALUE_EDIT;
    variablesForTouchArea[1].easyGUIVariablePtr                = GuiVar_gasCalibFlow1;
    variablesForTouchArea[1].maxValue                          = 500;
    variablesForTouchArea[1].easyGUIBackgroundColorVariablePtr = &GuiVar_gasCalibFlow1BackgroundColour;
    strcpy(variablesForTouchArea[1].variableName, "Flow value 1");

    variablesForTouchArea[2].touchAreaIndex                    = GAS_CALIB_DAC_2_VALUE_EDIT;
    variablesForTouchArea[2].easyGUIVariablePtr                = GuiVar_gasCalibDAC2;
    variablesForTouchArea[2].maxValue                          = 4095;
    variablesForTouchArea[2].easyGUIBackgroundColorVariablePtr = &GuiVar_gasCalibDAC2BackgroundColour;
    strcpy(variablesForTouchArea[2].variableName, "DAC value 2");

    variablesForTouchArea[3].touchAreaIndex                    = GAS_CALIB_FLOW_2_VALUE_EDIT;
    variablesForTouchArea[3].easyGUIVariablePtr                = GuiVar_gasCalibFlow2;
    variablesForTouchArea[3].maxValue                          = 500;
    variablesForTouchArea[3].easyGUIBackgroundColorVariablePtr = &GuiVar_gasCalibFlow2BackgroundColour;
    strcpy(variablesForTouchArea[3].variableName, "Flow value 2");

    variablesForTouchArea[4].touchAreaIndex                    = GAS_CALIB_DAC_3_VALUE_EDIT;
    variablesForTouchArea[4].easyGUIVariablePtr                = GuiVar_gasCalibDAC3;
    variablesForTouchArea[4].maxValue                          = 4095;
    variablesForTouchArea[4].easyGUIBackgroundColorVariablePtr = &GuiVar_gasCalibDAC3BackgroundColour;
    strcpy(variablesForTouchArea[4].variableName, "DAC value 3");

    variablesForTouchArea[5].touchAreaIndex                    = GAS_CALIB_FLOW_3_VALUE_EDIT;
    variablesForTouchArea[5].easyGUIVariablePtr                = GuiVar_gasCalibFlow3;
    variablesForTouchArea[5].maxValue                          = 500;
    variablesForTouchArea[5].easyGUIBackgroundColorVariablePtr = &GuiVar_gasCalibFlow3BackgroundColour;
    strcpy(variablesForTouchArea[5].variableName, "Flow value 3");

    variablesForTouchArea[6].touchAreaIndex                    = GAS_CALIB_DAC_4_VALUE_EDIT;
    variablesForTouchArea[6].easyGUIVariablePtr                = GuiVar_gasCalibDAC4;
    variablesForTouchArea[6].maxValue                          = 4095;
    variablesForTouchArea[6].easyGUIBackgroundColorVariablePtr = &GuiVar_gasCalibDAC4BackgroundColour;
    strcpy(variablesForTouchArea[6].variableName, "DAC value 4");

    variablesForTouchArea[7].touchAreaIndex                    = GAS_CALIB_FLOW_4_VALUE_EDIT;
    variablesForTouchArea[7].easyGUIVariablePtr                = GuiVar_gasCalibFlow4;
    variablesForTouchArea[7].maxValue                          = 500;
    variablesForTouchArea[7].easyGUIBackgroundColorVariablePtr = &GuiVar_gasCalibFlow4BackgroundColour;
    strcpy(variablesForTouchArea[7].variableName, "Flow value 4");

    variablesForTouchArea[8].touchAreaIndex                    = GAS_CALIB_DAC_5_VALUE_EDIT;
    variablesForTouchArea[8].easyGUIVariablePtr                = GuiVar_gasCalibDAC5;
    variablesForTouchArea[8].maxValue                          = 4095;
    variablesForTouchArea[8].easyGUIBackgroundColorVariablePtr = &GuiVar_gasCalibDAC5BackgroundColour;
    strcpy(variablesForTouchArea[8].variableName, "DAC value 5");

    variablesForTouchArea[9].touchAreaIndex                    = GAS_CALIB_FLOW_5_VALUE_EDIT;
    variablesForTouchArea[9].easyGUIVariablePtr                = GuiVar_gasCalibFlow5;
    variablesForTouchArea[9].maxValue                          = 500;
    variablesForTouchArea[9].easyGUIBackgroundColorVariablePtr = &GuiVar_gasCalibFlow5BackgroundColour;
    strcpy(variablesForTouchArea[9].variableName, "Flow value 5");

    variablesForTouchArea[10].touchAreaIndex                    = GAS_CALIB_DAC_6_VALUE_EDIT;
    variablesForTouchArea[10].easyGUIVariablePtr                = GuiVar_gasCalibDAC6;
    variablesForTouchArea[10].maxValue                          = 4095;
    variablesForTouchArea[10].easyGUIBackgroundColorVariablePtr = &GuiVar_gasCalibDAC6BackgroundColour;
    strcpy(variablesForTouchArea[10].variableName, "DAC value 6");

    variablesForTouchArea[11].touchAreaIndex                    = GAS_CALIB_FLOW_6_VALUE_EDIT;
    variablesForTouchArea[11].easyGUIVariablePtr                = GuiVar_gasCalibFlow6;
    variablesForTouchArea[11].maxValue                          = 500;
    variablesForTouchArea[11].easyGUIBackgroundColorVariablePtr = &GuiVar_gasCalibFlow6BackgroundColour;
    strcpy(variablesForTouchArea[11].variableName, "Flow value 6");
}
    
// Private destructor also
GasCalibrationPageHandler::~GasCalibrationPageHandler()
{
    //SaveCarrierGasSelectionToQSPISettings();
}


/*
    Tells the caller whether or not the specified touch index is on the easyGUI 'GasCalibrationPage',
    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 GasCalibrationPageHandler::TouchAreaIsOnCalibrationPage(int touchAreaIndex)
{
    if((touchAreaIndex >= MIN_GAS_CALIB_TOUCHINDEX) && (touchAreaIndex <= MAX_GAS_CALIB_TOUCHINDEX)) {
        return true;
    }
    
    // 'else'
    return false;
}


/*
    If the specified touch area represents a key or field on the easyGUI 'GasCalibrationPage',
    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 'Gas CalibrationPage', and so the caller
    must deal with it some other way).
*/
bool GasCalibrationPageHandler::DealWithTouch(int touchAreaIndex)
{
    bool dealtWithTouch = false;
    
    // 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
        indexOfValueCurrentlyBeingEdited = indexOfValueToEdit;
        NumericKeypadPageHandler* numericKeypadPageHandler = NumericKeypadPageHandler::GetInstance(usbDevice, usbHostGC);
        if(numericKeypadPageHandler != NULL) {
            numericKeypadPageHandler->StartEditing(variablesForTouchArea[indexOfValueCurrentlyBeingEdited].easyGUIVariablePtr);
            numericKeypadPageHandler->SetEasyGUIVariableToEdit(variablesForTouchArea[indexOfValueCurrentlyBeingEdited].easyGUIVariablePtr);
            numericKeypadPageHandler->SetEasyGUICallingPage(GuiStruct_GasCalibrationPage_Def);
            numericKeypadPageHandler->SetEditVariableRange(0, variablesForTouchArea[indexOfValueCurrentlyBeingEdited].maxValue);
            numericKeypadPageHandler->SetEditVariableName(variablesForTouchArea[indexOfValueCurrentlyBeingEdited].variableName);
            numericKeypadPageHandler->DisplayEasyGUIPage();
        }

        dealtWithTouch = true;
    } 
        
    if(!dealtWithTouch) {
        switch(touchAreaIndex) {
            case GAS_CALIB_HELIUM:
                if(GuiVar_gasCalibGasSelection != CARRIER_GAS_HELIUM) {
                    GuiVar_gasCalibGasSelection = CARRIER_GAS_HELIUM;
                    GetCurrentCalibrationFromGC();
                    SetAllFieldBackgroundColoursToInactive();
                    indexOfValueCurrentlyBeingEdited = -1; 
                    UpdateEasyGUIPage();
                    SaveCarrierGasSelectionToQSPISettings();
                }
                dealtWithTouch = true;
                break;
                
            case GAS_CALIB_HYDROGEN:
                if(GuiVar_gasCalibGasSelection != CARRIER_GAS_HYDROGEN) {
                    GuiVar_gasCalibGasSelection = CARRIER_GAS_HYDROGEN;
                    GetCurrentCalibrationFromGC();
                    SetAllFieldBackgroundColoursToInactive();
                    indexOfValueCurrentlyBeingEdited = -1; 
                    UpdateEasyGUIPage();
                    SaveCarrierGasSelectionToQSPISettings();
                }
                dealtWithTouch = true;
                break;
                
            case GAS_CALIB_NITROGEN:
                if(GuiVar_gasCalibGasSelection != CARRIER_GAS_NITROGEN) {
                    GuiVar_gasCalibGasSelection = CARRIER_GAS_NITROGEN;
                    GetCurrentCalibrationFromGC();
                    SetAllFieldBackgroundColoursToInactive();
                    indexOfValueCurrentlyBeingEdited = -1; 
                    UpdateEasyGUIPage();
                    SaveCarrierGasSelectionToQSPISettings();
                }
                dealtWithTouch = true;
                break;
                
            case GAS_CALIB_CANCEL_BUTTON:
                GetCurrentCalibrationFromGC();
                SetAllFieldBackgroundColoursToInactive();
                indexOfValueCurrentlyBeingEdited = -1;
                dealtWithTouch = true;
                UpdateEasyGUIPage();
                break;
                
            case GAS_CALIB_APPLY_BUTTON:
                SetCurrentCalibrationInGC();
                // Now deactivate all fields - shows user we have done something - 
                // also says "job done"
                SetAllFieldBackgroundColoursToInactive();
                indexOfValueCurrentlyBeingEdited = -1;
                dealtWithTouch = true;
                UpdateEasyGUIPage();
                break;
                                
            default:
                // Leave 'dealtWithTouch' set false
                break;
        }
    }
    
    return dealtWithTouch;
}


/*
    Caller is telling us it is about to display the easyGUI 'GasCalibrationPage',
    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 GasCalibrationPageHandler::DisplayingEasyGUIPage(bool updateEasyGUIVariables)
{
    ReadCarrierGasSelectionFromQSPISettings();
    
    if(updateEasyGUIVariables) {
        GetCurrentCalibrationFromGC();
    }
    
    SetAllFieldBackgroundColoursToInactive();
    
    indexOfValueCurrentlyBeingEdited = -1; 
}


/*
    Saves the current parameter values to QSPI settings,
    so they are maintained even when the user powers off
    
    No arguments, no return value
*/
void GasCalibrationPageHandler::SaveCarrierGasSelectionToQSPISettings(void)
{
    // Put values to QSPI settings, using SettingsHandler member functions

    SettingsHandler::PutIntegerValueToQSPISettings("CarrierGasSelection", GuiVar_gasCalibGasSelection);
}


/*
    Reads the current parameter values from QSPI settings,
    so they are maintained even when the user powers off
    
    No arguments, no return value
*/
void GasCalibrationPageHandler::ReadCarrierGasSelectionFromQSPISettings(void)
{
    // Get values from QSPI settings, using SettingsHandler member functions
    
    GuiVar_gasCalibGasSelection = SettingsHandler::GetIntegerValueFromQSPISettings("CarrierGasSelection", CARRIER_GAS_HELIUM);
}


/*
    Gets the current gas calibration DAC and flow values from the GC, 
    and puts them into the corresponding easyGUI variables
    
    No arguments, no return value
*/
void GasCalibrationPageHandler::GetCurrentCalibrationFromGC(void)
{
    GetCalibrationDACAndFlowValuesFromGC(GuiVar_gasCalibGasSelection, 1, GuiVar_gasCalibDAC1, GuiVar_gasCalibFlow1);
    GetCalibrationDACAndFlowValuesFromGC(GuiVar_gasCalibGasSelection, 2, GuiVar_gasCalibDAC2, GuiVar_gasCalibFlow2);
    GetCalibrationDACAndFlowValuesFromGC(GuiVar_gasCalibGasSelection, 3, GuiVar_gasCalibDAC3, GuiVar_gasCalibFlow3);
    GetCalibrationDACAndFlowValuesFromGC(GuiVar_gasCalibGasSelection, 4, GuiVar_gasCalibDAC4, GuiVar_gasCalibFlow4);
    GetCalibrationDACAndFlowValuesFromGC(GuiVar_gasCalibGasSelection, 5, GuiVar_gasCalibDAC5, GuiVar_gasCalibFlow5);
    GetCalibrationDACAndFlowValuesFromGC(GuiVar_gasCalibGasSelection, 6, GuiVar_gasCalibDAC6, GuiVar_gasCalibFlow6);
}

/*
    Sets the current gas calibration DAC and flow values in the GC, 
    getting the values from the corresponding easyGUI variables
    
    No arguments, no return value
*/
void GasCalibrationPageHandler::SetCurrentCalibrationInGC(void)
{
    SetCalibrationDACAndFlowValuesInGC(GuiVar_gasCalibGasSelection, 1, GuiVar_gasCalibDAC1, GuiVar_gasCalibFlow1);
    SetCalibrationDACAndFlowValuesInGC(GuiVar_gasCalibGasSelection, 2, GuiVar_gasCalibDAC2, GuiVar_gasCalibFlow2);
    SetCalibrationDACAndFlowValuesInGC(GuiVar_gasCalibGasSelection, 3, GuiVar_gasCalibDAC3, GuiVar_gasCalibFlow3);
    SetCalibrationDACAndFlowValuesInGC(GuiVar_gasCalibGasSelection, 4, GuiVar_gasCalibDAC4, GuiVar_gasCalibFlow4);
    SetCalibrationDACAndFlowValuesInGC(GuiVar_gasCalibGasSelection, 5, GuiVar_gasCalibDAC5, GuiVar_gasCalibFlow5);
    SetCalibrationDACAndFlowValuesInGC(GuiVar_gasCalibGasSelection, 6, GuiVar_gasCalibDAC6, GuiVar_gasCalibFlow6);
}


/*
    Gets the gas calibration DAC and flow values for the specified carrier gas
    and the specified index (1-6), and converts them to strings
    
    Arguments: carrier gas (integer - see enum in header file)
               index (1-6)
               buffer for DAC value
               buffer for flow value
               
    Returns true if OK, false if error
*/
bool GasCalibrationPageHandler::GetCalibrationDACAndFlowValuesFromGC(int carrierGasSelection, int valueIndex, char *bufferForDACValue, char *bufferForFlowValue)
{
    char cmd[8];
    char response[50];
    
    
    // DAC value first
    
    if(!ConstructGasCalibrationGCCommand(false, carrierGasSelection, valueIndex, true, cmd)) {
        return false;
    }
    
    while(usbHostGC->ExecutingSetDeviceReport()) {}

    usbHostGC->SetDeviceReport(usbDevice, cmd, response);
    // We expect a response like this: "DHEAnnnn", when nnnn is the DAC value,
    // or "EPKT" if something went wrong
    if(response[0] == 'E') {
        // Assume "EPKT"
        return false;
    }
    
    // 'else' - value received
    CopyCommandResponseToBufferWithoutLeadingZeroes(&response[4], bufferForDACValue);
    
    
    // Now the flow value
    
    if(!ConstructGasCalibrationGCCommand(false, carrierGasSelection, valueIndex, false, cmd)) {
        return false;
    }
        
    while(usbHostGC->ExecutingSetDeviceReport()) {}

    usbHostGC->SetDeviceReport(usbDevice, cmd, response);
    // We expect a response like this: "DHEGnnnn", when nnnn is the flow value,
    // or "EPKT" if something went wrong
    if(response[0] == 'E') {
        // Assume "EPKT"
        return false;
    }
    
    // 'else' - value received
    CopyCommandResponseToBufferWithoutLeadingZeroes(&response[4], bufferForFlowValue);
    
    return true;
}

/*
    Sets the gas calibration DAC and flow values for the specified carrier gas
    and the specified index (1-6) in the GC, using the string values passed to it
    
    Arguments: carrier gas (integer - see enum in header file)
               index (1-6)
               buffer containing the new DAC value as a string
               buffer containing the new flow value as a string
               
    Returns true if OK, false if error
*/
bool GasCalibrationPageHandler::SetCalibrationDACAndFlowValuesInGC(int carrierGasSelection, int valueIndex, char *bufferForDACValue, char *bufferForFlowValue)
{
    char cmd[8];
    char response[50];    
    
    // DAC value first
    
    if(!ConstructGasCalibrationGCCommand(true, carrierGasSelection, valueIndex, true, cmd)) {
        return false;
    }
    
    CopyBufferDigitsToCommand(cmd, bufferForDACValue);
    
    while(usbHostGC->ExecutingSetDeviceReport()) {}

    usbHostGC->SetDeviceReport(usbDevice, cmd, response);
    // We expect "DACK" as the response for success, "DNAK" or "EPKT" if something went wrong
    if(response[1] != 'A') {
        return false;
    }
    
    
    // Now the flow value
    
    if(!ConstructGasCalibrationGCCommand(true, carrierGasSelection, valueIndex, false, cmd)) {
        return false;
    }
        
    CopyBufferDigitsToCommand(cmd, bufferForFlowValue);

    while(usbHostGC->ExecutingSetDeviceReport()) {}

    usbHostGC->SetDeviceReport(usbDevice, cmd, response);
    // As before, we expect "DACK" as the response for success, "DNAK" or "EPKT" if something went wrong
    if(response[1] != 'A') {
        return false;
    }
    
    // 'else' success with both commands
    return true;
}


/*
    (Re)display the easyGUI 'GasCalibrationPage' -
    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 GasCalibrationPageHandler::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->ForceUpdateOfGasCalibrationPage();
    }
}


/*
    The gas calibration GC commands are all very similar. This function returns the required command,
    based on whether set or get is required, the carrier gas, DAC or Flow, and the index.
    
    Arguments: a boolean - true for set, false for get
               carrier gas (integer - see enum in header file)
               index (1-6)
               a boolean - true for the DAC command, false for the flow command
               pointer to a buffer to contain the command
               
    Returns true if the index was valid (1-6), false if not
*/    
bool GasCalibrationPageHandler::ConstructGasCalibrationGCCommand(bool wantSetCommand, int carrierGasSelection, int valueIndex, bool wantDACCommand, char *commandBuffer)
{
    if((valueIndex < 1) || (valueIndex > 6)) {
        return false;
    }
    
    commandBuffer[0] = wantSetCommand ? 'S' : 'G';
    
    switch (carrierGasSelection) {
        case CARRIER_GAS_HYDROGEN:
            commandBuffer[1] = 'H';
            commandBuffer[2] = '2';
            break;
        case CARRIER_GAS_NITROGEN:
            commandBuffer[1] = 'N';
            commandBuffer[2] = '2';
            break;
        default: // Assume helium
            commandBuffer[1] = 'H';
            commandBuffer[2] = 'E';
            break;
    }
    
    if(wantDACCommand) {
        switch(valueIndex) {
            case 1:
                commandBuffer[3] = 'A';
                break;
            case 2:
                commandBuffer[3] = 'B';
                break;
            case 3:
                commandBuffer[3] = 'C';
                break;
            case 4:
                commandBuffer[3] = 'D';
                break;
            case 5:
                commandBuffer[3] = 'E';
                break;
            default: // Assume 6
                commandBuffer[3] = 'F';
                break;
        }
    } else {
        // Flow command
        switch(valueIndex) {
            case 1:
                commandBuffer[3] = 'G';
                break;
            case 2:
                commandBuffer[3] = 'H';
                break;
            case 3:
                commandBuffer[3] = 'I';
                break;
            case 4:
                commandBuffer[3] = 'J';
                break;
            case 5:
                commandBuffer[3] = 'K';
                break;
            default: // Assume 6
                commandBuffer[3] = 'L';
                break;
        }
    }
    
    commandBuffer[4] = '\0';
    
    return true;
}


/*
    Sets the background colours of all 'editable' fields to the 'inactive' colour.
    
    No arguments, no return code
*/
void GasCalibrationPageHandler::SetAllFieldBackgroundColoursToInactive(void)
{
    GuiVar_gasCalibDAC1BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_gasCalibFlow1BackgroundColour = inactiveFieldBackgroundColour;

    GuiVar_gasCalibDAC2BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_gasCalibFlow2BackgroundColour = inactiveFieldBackgroundColour;

    GuiVar_gasCalibDAC3BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_gasCalibFlow3BackgroundColour = inactiveFieldBackgroundColour;

    GuiVar_gasCalibDAC4BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_gasCalibFlow4BackgroundColour = inactiveFieldBackgroundColour;

    GuiVar_gasCalibDAC5BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_gasCalibFlow5BackgroundColour = inactiveFieldBackgroundColour;

    GuiVar_gasCalibDAC6BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_gasCalibFlow6BackgroundColour = inactiveFieldBackgroundColour;
}


/*
    Tells the caller if the specified touch area corresponds to a value the user can edit
    on the easyGUI 'GasCalibrationPage', 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 GasCalibrationPageHandler::GetIndexOfValueToEditForTouchArea(int touchAreaIndex)
{
    for (int index = 0; index < COUNT_OF_VARIABLES_FOR_TOUCH_AREAS; ++index) {
        if(variablesForTouchArea[index].touchAreaIndex == touchAreaIndex) {
            return index;
        }
    }
    
    // 'else' no Gas Calibration value corresponds to the specified touch area
    return -1;
}


/*
    The response to a "Get DAC/Flow value n" command will always consist of four digits, 
    padded with leading zeroes if necessary. We want to display it to the user 
    without the leading zeroes, but - obviously - *with* any zeroes contained in the number itself,
    e.g. "0100" must be copied as "100", not "1". Note also that "0000" must be copied as "0" - 
    the destination string must not be left blank.
    
    Arguments: pointer to a character buffer containing the four-digit response [it is up to the caller to ensure this is valid]
               pointer to a character buffer to which we are to copy the response without leading zeroes
               
    No return value
*/
void GasCalibrationPageHandler::CopyCommandResponseToBufferWithoutLeadingZeroes(char *commandResponse, char *buffer)
{
    int bufferIndex = 0;
    bool wantZeroes = false;
    
    for (int responseIndex = 0; responseIndex < 4; ++responseIndex) {
        if(commandResponse[responseIndex] != '0') {
            buffer[bufferIndex++] = commandResponse[responseIndex];
            wantZeroes = true; // We have had a non-zero character, so we want zeroes from now on
        } else if (wantZeroes) {
            buffer[bufferIndex++] = commandResponse[responseIndex];
        }
    }
    
    if(bufferIndex == 0) {
        // Response *is* zero - copied no chars at all so far
        buffer[bufferIndex++] = '0';
    }
    
    buffer[bufferIndex] = '\0';
}


/*
    Gas calibration DAC and Flow values are stored in the easyGUI variables without leading zeroes,
    but we must always pass them to the GC as four-digit values, padded with leading zeroes if less than four digits.
    The four digits must be appended to the relevant GC 'Set' command, e.g. "SHEAnnnn".
    This function does that - takes the raw 1-4 digit string, and appends it to the command as a 4-digit string.
    
    Arguments: pointer to a buffer containing the command
               pointer to a buffer containing the raw (unpadded) value
               
    No return code
*/
void GasCalibrationPageHandler::CopyBufferDigitsToCommand(char *commandBuffer, char *digitsBuffer)
{
    int n = strlen(digitsBuffer);
    int commandBufferIndex = 4;
    int digitsBufferIndex = 0;
    
    while(n < 4) {
        commandBuffer[commandBufferIndex++] = '0';
        ++n;
    }
    
    while(digitsBuffer[digitsBufferIndex] != '\0') {
        commandBuffer[commandBufferIndex++] = digitsBuffer[digitsBufferIndex++];
    }
    
    commandBuffer[commandBufferIndex] = '\0';
}