fasdf gfaha / Terminal

Terminal.cpp

Committer:
UCSBRobotics
Date:
2012-08-07
Revision:
9:bb92a6ecb668
Parent:
6:4269b879a2af
Child:
10:ce5816cee1e4

File content as of revision 9:bb92a6ecb668:

#include "Terminal.h"
#include "mbed.h"
#include <cctype>
#include <cstring>



Terminal::Terminal(PinName tx, PinName rx, int baudrate) : serial(tx, rx)
{
    // These values need to be initialized
    numCommands = 0;
    runningCmd = NULL;
    
    // Set up the serial connection
    serial.baud(baudrate);
    serial.attach(this, &Terminal::receive, Serial::RxIrq);
    serial.printf("> ");
}



void Terminal::addCommand(const char* cmdString, CmdHandler* (*fpointer)(Terminal*, const char*) )
{
    // Check if there's room in the command array before adding a command
    if (numCommands < NUM_COMMANDS_MAX)
    {
        strncpy(cmdList[numCommands].cmdString, cmdString, INPUT_BUFFER_MAX);
        cmdList[numCommands].cmdString[INPUT_BUFFER_MAX - 1] = '\0'; // Make sure that the command string is null terminated
        cmdList[numCommands].stringLength = strlen(cmdList[numCommands].cmdString);
        cmdList[numCommands].fpointer = fpointer;
        numCommands++;
    }
    else
    {
        serial.printf("error: too many commands\n");
    }
}



void Terminal::terminateCmd()
{
    // Delete the running command's CmdHandler, if it exists
    if (runningCmd != NULL)
    {
        delete runningCmd;
        runningCmd = NULL;
    }
    
    serial.printf("\n> ");
    inputBuffer[0] = '\0'; // Clear the input buffer
}



void Terminal::write(const char* string)
{
    serial.printf("%s", string);
}



void Terminal::receive()
{
    char c = serial.getc();
    
    // Check if a command is currently running
    if (runningCmd == NULL) // No command is currently running
    {
        int len = strlen(inputBuffer);
        
        if (isprint(c)) // If c is a printable character
        {
            if (len < INPUT_BUFFER_MAX - 1)
            {
                // Add the new character to the input buffer and display it
                inputBuffer[len] = c;
                inputBuffer[len + 1] = '\0';
                serial.putc(c);
            }
        }
        else if (c == '\b' || c == 127) // Backspace or DEL
        {
            // Escape codes currently mess up the display of the current input
            if (len > 0)
            {
                inputBuffer[len - 1] = '\0';
                serial.printf("\b \b");
            }
        }
        else if (c == '\n') // Execute input command
        {
            serial.putc('\n');
            
            bool matchFound = false; // Initialize flag
            
            // Try to match the input string to a command
            for (int i = 0; i < NUM_COMMANDS_MAX; i++)
            {
                if (cmdList[i].stringLength && !strncmp(inputBuffer, cmdList[i].cmdString, cmdList[i].stringLength))
                {
                    // Match found, call the associated command
                    runningCmd = cmdList[i].fpointer(this, inputBuffer);
                    matchFound = true;
                    break;
                }
            }
            
            if (matchFound)
            {
                // If the command finishes immediately, it should return null instead of a pointer to a CmdHandler
                if (runningCmd == NULL)
                {
                    // Terminate the command here, because there is no CmdHandler to terminate it later
                    terminateCmd();
                }
            }
            else
            {
                // No match was found
                serial.printf("unrecognized command");
            }
        }
        // Control characters other than \n, \b, and 127 (DEL) are ignored
    }
    else // A command is running, so pass the character to the CmdHandler
    {
        runningCmd->sendChar(c);
    }
}