listen serial input and react by callback registered.

Dependents:   Interference_Simple StrCommandHandler_Demo SerialInputReactionHandler_DEMO

Files at this revision

API Documentation at this revision

Comitter:
aktk
Date:
Tue Nov 12 01:10:29 2019 +0000
Child:
1:fd211f137803
Commit message:
First Implement;

Changed in this revision

SerialInputReactionHandler.cpp Show annotated file Show diff for this revision Revisions of this file
SerialInputReactionHandler.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialInputReactionHandler.cpp	Tue Nov 12 01:10:29 2019 +0000
@@ -0,0 +1,141 @@
+#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;
+    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));
+}
+
+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 (m_buffer_c == 0x1B /*ESC*/) {
+
+        //  If only 0x1B, ESC KEY should be Pressed, else some symbol sequence.
+        if (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();
+            }
+
+            m_buffer_s += m_buffer_c;
+            //  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*/:
+                break;
+
+        }
+    }
+    __enable_irq();
+}
+
+void SerialInputReactionHandler::discardBuffer()
+{
+    m_buffer_c = '\0';
+    m_buffer_s = "";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialInputReactionHandler.h	Tue Nov 12 01:10:29 2019 +0000
@@ -0,0 +1,59 @@
+#ifndef SERIAL_INPUT_REACTION_HANDLER_H
+#define SERIAL_INPUT_REACTION_HANDLER_H
+
+#include "mbed.h"
+#include <string>
+
+class SerialInputReactionHandler
+{
+public:
+    enum InputMode {KB_SINGLE_INPUT = 0, KB_TILL_ENTER, NUMBEROFMODES};
+    static char const * const ARROW_UP;
+    static char const * const ARROW_DOWN;
+    static char const * const ARROW_RIGHT;
+    static char const * const ARROW_LEFT;
+
+    SerialInputReactionHandler(
+        Callback<int (char const * const)> arg_callback_onCommand = &echoCommand
+    );
+    
+    void attach(Callback<int (char const * const)> arg_callback_onCommand);
+    void startReception(Serial * arg_serial_socket, InputMode arg_mode = KB_SINGLE_INPUT);
+    void quit();
+
+    void changeMode(InputMode arg_mode);
+
+private:
+    void commonProcedure();
+    void listenKBSingleInput();
+    void listenKBTillEnter();
+    void discardBuffer();
+
+    void (SerialInputReactionHandler::*funcIfInput[NUMBEROFMODES])();
+
+    /** Wrapper function that executes commonProcedure() and a function
+     *  listed in funcIfInput[]()
+     *
+     *  This function is supposed to be used as callback attached to such like
+     *  Serial.attach(), so that it is called evrey a key input thry keyboard
+     *  or a byte written thru communication with like PCs.
+     */
+    void sig_bind();
+
+    Callback<int (char const * const)> callback_onCommand;
+    static int echoCommand (char const * const);
+
+    Serial * m_serial_socket;
+
+    InputMode m_input_mode;
+    uint8_t m_buffer_c;
+    string  m_buffer_s;
+};
+
+inline int SerialInputReactionHandler::echoCommand (char const * const arg_str)
+{
+    printf("%s", arg_str);
+    return 0;
+}
+
+#endif