Repository for import to local machine

Dependencies:   DMBasicGUI DMSupport

ColumnDHPSUDACPageHandler.cpp

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

File content as of revision 8:26e49e6955bd:

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


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

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


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


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


/*
    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 ColumnDHPSUDACPageHandler::TouchAreaIsOnPSUDACPage(int touchAreaIndex)
{
    if((touchAreaIndex >= MIN_COLUMN_DH_PSU_DAC_TOUCHINDEX) && (touchAreaIndex <= MAX_COLUMN_DH_PSU_DAC_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 ColumnDHPSUDACPageHandler::DealWithTouch(int touchAreaIndex)
{
    bool dealtWithTouch = false; // so far...

    switch(touchAreaIndex) {
        case COLUMN_DH_PSU_DAC_EDIT_DAC_VALUE: { // Restrict the scope of 'numericKeypadPageHandler' to this case - 
                                                 // avoid compiler warning "Transfer of control bypasses initialization"
            NumericKeypadPageHandler* numericKeypadPageHandler = NumericKeypadPageHandler::GetInstance(usbDevice, usbHostGC);
            if(numericKeypadPageHandler != NULL) {
                numericKeypadPageHandler->StartEditing(GuiVar_columnDHPSUDACSetValue);
                numericKeypadPageHandler->SetEasyGUIVariableToEdit(GuiVar_columnDHPSUDACSetValue);
                numericKeypadPageHandler->SetEasyGUICallingPage(GuiStruct_PSU_DAC_Page_Def);
                numericKeypadPageHandler->SetEditVariableRange(0, 4095);
                numericKeypadPageHandler->SetEditVariableName("PSU DAC Value");
                numericKeypadPageHandler->DisplayEasyGUIPage();
            }
            dealtWithTouch = true;
            break;
        } // See above

        case COLUMN_DH_PSU_DAC_SET_DAC_VALUE:
            SetCurrentPSUDACValueInGC();
            GetCurrentPSUDACValueFromGC();
            UpdateEasyGUIPage();
            dealtWithTouch = true;
            break;

        case COLUMN_DH_PSU_DAC_GET_DAC_VALUE:
            GetCurrentPSUDACValueFromGC();
            UpdateEasyGUIPage();
            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 ColumnDHPSUDACPageHandler::DisplayingEasyGUIPage(bool updateEasyGUIVariables)
{
    if(updateEasyGUIVariables) {
        GetCurrentPSUDACValueFromGC();
    }
}


/*
    Gets the current PSU DAC value from the GC, and copies them 
    into the relevant easyGUI variables for display to the user -
    these are the 'raw' DAC value, and the power expressed 
    as a percentage of the maximum
    
    No arguments, no return code
*/
bool ColumnDHPSUDACPageHandler::GetCurrentPSUDACValueFromGC(void)
{
    char response[50];
    
    SendCommandToGCAndGetResponse("QDAC", response);
    
    //  We expect a response of the form "DDAnnnnn",
    // where "nnnnn" is the current DAC value.
    // Note that it is five digits, not four.
    if((response[0] == 'D') &&
       (response[1] == 'D') &&
       (response[2] == 'A')) {
           
        // 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 dacValue;
        sscanf(&response[3], "%d", &dacValue);
        sprintf(GuiVar_columnDHPSUDACGetValue, "%d", dacValue);
        
        // Need to display power to 2 places of decimals (since that is what the VB6 app does)
        float temp = (float)dacValue;
        float dacPower = (temp * temp * 100.0f) / 16769025.0f; // 16769025 is 4095 squared
        sprintf(GuiVar_columnDHPSUDACPower, "%.2f", dacPower);
    
        return true;
    }
    
    // 'else'
    return false;
}


/*
    Sets the PSU DAC value in the GC, to match the value 
    we are currently displaying to the user.
    
    No arguments, no return code
*/
bool ColumnDHPSUDACPageHandler::SetCurrentPSUDACValueInGC(void)
{
    char buffer[50];
    
    // In the command, the PSU DAC value must have 4 digits, padded if necessary with leading zeroes
    int calib;
    sscanf(GuiVar_columnDHPSUDACSetValue, "%d", &calib);
    sprintf(buffer, "SDAC%.4d", calib); 
    
    return SendCommandToGCWithDACKResponse(buffer);
}


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


/*
    (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 ColumnDHPSUDACPageHandler::UpdateEasyGUIPage(void)
{
    GetGCStatusLoop *getGCStatusLoop = GetGCStatusLoop::GetInstance();
    
    if(getGCStatusLoop != NULL) {
        getGCStatusLoop->ForceUpdateOfColumnDHPSUDACPage();
    }
}