Repository for import to local machine

Dependencies:   DMBasicGUI DMSupport

DebugCommandsPageHandler.cpp

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

File content as of revision 8:26e49e6955bd:

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

// main.cpp
void SpecialDebugPrint(char *stuffToPrint, GuiConst_INT16S X, GuiConst_INT16S Y);

/*
    Draws the default background bitmap, i.e. *without* the Ellutia logo.
    Defined in main.cpp
*/
void DrawBackgroundBitmap(void);


/*                      
    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 nudge and damp parameters, etc, nor will we show 
    more than one easyGUI page to the user at the same time).
*/
DebugCommandsPageHandler * DebugCommandsPageHandler::theDebugCommandsPageHandlerInstance = NULL;


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

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


// Singleton class - private constructor
DebugCommandsPageHandler::DebugCommandsPageHandler(USBDeviceConnected* newUsbDevice, USBHostGC* newUsbHostGC)
{
    usbDevice = newUsbDevice;
    usbHostGC = newUsbHostGC;
    
    // Set this true immediately after executing a GC command.
    // If the user types another char, clear the command first.
    commandJustExecuted = false; 
}


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

/*
    As the name implies, sends a command to the GC and displays the response.
    Expects the command to be in the easyGUI variable "GuiVar_debugCommandTx",
    and places the response in the easyGUI variable "GuiVar_debugCommandRx".
    It is up to the caller to (re)display the Debug Commands easyGUI page
    to show the updated values.
    
    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 DebugCommandsPageHandler::SendCommandToGCAndDisplayResponse(void)
{
    char command[20];
    char response[20];
    
    strcpy(command, GuiVar_debugCommandTx);
    
    bool expect4Chars = ((command[0] == 'C') || (command[0] == 'S'));
    // Else expect 8 chars (or "EPKT")
    
#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

    // There always seems to be garbage at the end of the response
    if(expect4Chars || (response[0] == 'E')) { // If 'E', assume "EPKT"
        response[4] = '\0';
    } else {
        response[8] = '\0';
    }
    
//#define DEBUG_PRINT_HERE
#ifdef DEBUG_PRINT_HERE
    char dbg[100];
    sprintf(dbg, "DCPH cmd \"%s\", response \"%s\"", command, response);
    SpecialDebugPrint(dbg, 10, 275);
#endif // DEBUG_PRINT_HERE

    strcpy(GuiVar_debugCommandRx, response);
    
    commandJustExecuted = true;
}


/*
    Tells the caller whether or not the specified touch index is on the Debug Commands page,
    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 DebugCommandsPageHandler::TouchAreaIsOnDebugCommandsPage(int touchAreaIndex)
{
    if((touchAreaIndex >= MIN_DEBUG_COMMANDS_TOUCHINDEX) && (touchAreaIndex <= MAX_DEBUG_COMMANDS_TOUCHINDEX)) {
        return true;
    }

    // 'else'
    return false;
}


/*
    Returns the character that matches the specified touch area index.
    This should be one of the character keys on the easyGUI DebugCommandsPage.
    If not, defaults to '0'.
    
    Args: the touch area index
    
    Returns the corresponding character if there is one, '0' if not
*/
char DebugCommandsPageHandler::GetCharCodeForTouchAreaIndex(int touchAreaIndex)
{
    if((touchAreaIndex >= DEBUG_COMMANDS_0) && (touchAreaIndex <= DEBUG_COMMANDS_9)) {
        return (touchAreaIndex - DEBUG_COMMANDS_0 + '0');
    }
    
    // else...
    if((touchAreaIndex >= DEBUG_COMMANDS_A) && (touchAreaIndex <= DEBUG_COMMANDS_Z)) {
        return (touchAreaIndex - DEBUG_COMMANDS_A + 'A');
    }

    // else...
    return '0';    
}


/*
    If the specified touch area represents a key or field on the easyGUI Debug Commands page,
    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 GC/Debug Commands  page, and so the caller
    must deal with it some other way).
*/
bool DebugCommandsPageHandler::DealWithTouch(int touchAreaIndex)
{
    if(touchAreaIndex == DEBUG_COMMANDS_SEND) {
        
        // Clear response first, so user sees something happen
        GuiVar_debugCommandRx[0] = '\0';
        DisplayEasyGUIPage();

        SendCommandToGCAndDisplayResponse();
        DisplayEasyGUIPage();

        return true;
    }

    // If a character, append it to GuiVar_debugCommandTx, unless that is already at MAX_COMMAND_LENGTH
    if((touchAreaIndex >= MIN_DEBUG_COMMANDS_CHAR) && (touchAreaIndex <= MAX_DEBUG_COMMANDS_CHAR)) {

        // If we have just executed a command, start a new one as soon as the user types another character,
        // but not if he types Delete or Clear (since he is in effect editing the previous command)
        if(commandJustExecuted) {
            GuiVar_debugCommandTx[0] = '\0'; // Clear the command we have just executed
            
            commandJustExecuted = false; // So we know to append subsequent characters to this one
        }

        int len = strlen(GuiVar_debugCommandTx);
        if(len < MAX_COMMAND_LENGTH) {
            // Append the new character to the command
            GuiVar_debugCommandTx[len] = GetCharCodeForTouchAreaIndex(touchAreaIndex);
            GuiVar_debugCommandTx[len + 1] = '\0';

            DisplayEasyGUIPage();
        }
        return true;
    }
    
    // If DEBUG_COMMANDS_DELETE, delete the last character in GuiVar_debugCommandTx, unless it already has zero characters
    if((touchAreaIndex == DEBUG_COMMANDS_DELETE)) {
        int len = strlen(GuiVar_debugCommandTx);
        if(len > 0) {
            // Delete the last character in the command
            GuiVar_debugCommandTx[len - 1] = '\0';

            DisplayEasyGUIPage();
            
            commandJustExecuted = false; // User has (in effect) edited this command - do not start a new one if he types another character
        }
        return true;
    }
    
    // If DEBUG_COMMANDS_CLEAR, clear the command by setting GuiVar_debugCommandTx to an empty string
    if((touchAreaIndex == DEBUG_COMMANDS_CLEAR)) {
        GuiVar_debugCommandTx[0] = '\0';
        DisplayEasyGUIPage();
            
        commandJustExecuted = false; // User has (in effect) edited this command - do not start a new one if he types another character
        return true;
    }

    // 'else'...
    
    return false;
}


/*
    (Re)display the easyGUI 'DebugCommandsPage' - e.g. after we have updated 
    the command to be sent, and want to display the new value to the user.
    
    No arguments, no return code
*/
void DebugCommandsPageHandler::DisplayEasyGUIPage(void)
{
    DrawBackgroundBitmap();

    GuiLib_ShowScreen(GuiStruct_DebugCommandsPage_Def, GuiLib_NO_CURSOR, GuiLib_RESET_AUTO_REDRAW);
    
    GuiLib_Refresh();    

    GetGCStatusLoop *getGCStatusLoop = GetGCStatusLoop::GetInstance();
    if(getGCStatusLoop != NULL) {
        getGCStatusLoop->SetCurrentPage(GuiStruct_DebugCommandsPage_Def);
    }
}