listen serial input and react by callback registered.

Dependents:   Interference_Simple StrCommandHandler_Demo SerialInputReactionHandler_DEMO

SerialInputReactionHandler.cpp

Committer:
aktk
Date:
2019-11-12
Revision:
1:fd211f137803
Parent:
0:ec916055f0dd
Child:
2:4718a4eaf340

File content as of revision 1:fd211f137803:

#include "SerialInputReactionHandler.h"

char const * const SerialInputReactionHandler::ARROW_UP   = "\x1b\x5b\x41";
char const * const SerialInputReactionHandler::ARROW_DOWN = "\x1b\x5b\x42";
char const * const SerialInputReactionHandler::ARROW_RIGHT= "\x1b\x5b\x43";
char const * const SerialInputReactionHandler::ARROW_LEFT = "\x1b\x5b\x44";

SerialInputReactionHandler::SerialInputReactionHandler(
    Callback<int(char const * const)> arg_callback_onCommand
)
{
    funcIfInput[KB_SINGLE_INPUT] = &SerialInputReactionHandler::listenKBSingleInput;
    funcIfInput[KB_TILL_ENTER] = &SerialInputReactionHandler::listenKBTillEnter;
    callback_onCommand = arg_callback_onCommand;
}

void SerialInputReactionHandler::attach(
    Callback<int (char const * const)> arg_callback_onCommand
)
{
    callback_onCommand = arg_callback_onCommand;
}

void SerialInputReactionHandler::startReception(
    Serial * arg_serial_socket,
    InputMode arg_mode
)
{
    m_serial_socket = arg_serial_socket;
    m_input_mode = arg_mode;
    m_serial_socket->attach(callback(this, &SerialInputReactionHandler::sig_bind));
}

void SerialInputReactionHandler::quit()
{
    m_serial_socket->attach(NULL);
}

void SerialInputReactionHandler::commonProcedure()
{
}

void SerialInputReactionHandler::sig_bind()
{
    commonProcedure();
    (this->*funcIfInput[m_input_mode])();
}

void SerialInputReactionHandler::changeMode(InputMode arg_mode)
{
    discardBuffer();
    m_input_mode = arg_mode;
}

void SerialInputReactionHandler::listenKBSingleInput()
{
    m_buffer_c = m_serial_socket->getc();
    m_buffer_s = m_buffer_c;
    if(m_buffer_c != 0x1B && isArrowSymbol())
        callback_onCommand(m_buffer_s.c_str());
    m_serial_socket->printf("Single key board input: %c (%x)\n", m_buffer_c, m_buffer_c);
    discardBuffer();
}

bool isUpperCase (const char arg_c)
{
    return ('A' <= arg_c && arg_c <= 'Z');
}

bool isLowerCase (const char arg_c)
{
    return ('a' <= arg_c && arg_c <= 'z');
}

bool isSymbol (const char arg_c)
{
    return ((0x20 <= arg_c && arg_c <= 0x40)
            ||  (0x5B <= arg_c && arg_c <= 0x60)
            ||  (0x7B <= arg_c && arg_c <= 0x7E));
}

bool SerialInputReactionHandler::isArrowSymbol()
{
    //  If only 0x1B, ESC KEY should be Pressed, else some symbol sequence.
    if (m_buffer_c == 0x1B && m_serial_socket->readable()) {
        m_buffer_s = m_buffer_c;
        m_buffer_c = m_serial_socket->getc();

        //  If 0x5B follows, it coul be arrow key was pressed
        if (m_buffer_c == 0x5B && m_serial_socket->readable()) {
            m_buffer_s += m_buffer_c;
            m_buffer_c = m_serial_socket->getc();
        } else m_buffer_c = 0x1B;

        m_buffer_s += m_buffer_c;
    } else m_buffer_c = 0x1B;

    if (m_buffer_c == 0x1B) return false;
    else return true;
}


void SerialInputReactionHandler::listenKBTillEnter()
{
    __disable_irq();
    m_buffer_c = m_serial_socket->getc();

    if ( isUpperCase(m_buffer_c) || isLowerCase(m_buffer_c) || isSymbol( m_buffer_c)) {

        if(m_buffer_s.length() != 0 && m_buffer_s[0] != '\0')
            m_buffer_s += m_buffer_c;
        else
            m_buffer_s = m_buffer_c;
        m_serial_socket->putc(m_buffer_c);

    } else if ( m_buffer_c == '\n' || m_buffer_c == '\r') {

        callback_onCommand(m_buffer_s.c_str());
        m_serial_socket->putc(m_buffer_c);
        discardBuffer();

    } else if (isArrowSymbol()) {

        //  Arrows
        callback_onCommand(m_buffer_s.c_str());
        discardBuffer();

    } else {
        switch (m_buffer_c) {
            case 0x08 /*BS */:
            case 0x7F /*DEL*/:
                m_buffer_s.erase(m_buffer_s.end() - 1);
                //m_serial_socket->putc(0x7F);
                m_serial_socket->putc(0x08);
                m_serial_socket->putc(0x20);
                m_serial_socket->putc(0x08);
                break;
            case 0x1B /*ESC*/:
                discardBuffer();
                break;

        }
    }
    __enable_irq();
}