Support library for the ESP8266 Wireless Terminal. Can also be used for communicating with any VT100-compatible terminal.

espterm.hpp

Committer:
MightyPork
Date:
2017-03-19
Revision:
4:294e8f53ebcd
Parent:
3:1114012184bf
Child:
5:7379bd37f3e2

File content as of revision 4:294e8f53ebcd:

#ifndef ESPTERM_H
#define ESPTERM_H
#include "mbed.h"

/*
 * ESP8266 Wireless Terminal interfacing library
 * ---------------------------------------------
 *
 * Tested with ESP firmware v0.5.4
 *
 * This library provides simplified 
 */
 
// Max nr of CSI parameters
#define CSI_N_MAX 3
#define OSC_BUF_LEN 16

/**
 * ESP8266 Wireless Terminal interface
 *
 * Can also be used for sending ANSI sequences to a regular serial terminal
 */
class ESPTerm
{
    /** 
     * Status flag set by the rx handler when device responds with "device OK".
     * Cleared before sending Device Status Request.
     */
    bool device_ok;
    
    
    /** Serial comm used to talk to the ESP */
    Serial* ser;
    
    
    /** Internal init func, called from constructor */
    void init(Serial* ser);
    
    
    /** Internal rxchar handler with parser */
    void ser_rx_char(void);
    
    // ---- Ragel parser variables ----
    int cs;

    // The CSI code is built here
    char csi_leading;      //!< Leading char, 0 if none
    int  csi_ni;           //!< Number of the active digit
    int  csi_n[CSI_N_MAX]; //!< Param digits
    char csi_char;         //!< CSI action char (end)

    char osc_buff[OSC_BUF_LEN];
    int osc_i;
    
    // Ragel parser funcs
    void ansi_parser(const char *newdata, size_t len);
    void apars_handle_plainchar(char c);
    void apars_handle_csi(char lead, const int* nums, char keychar);
    void apars_handle_osc(const char *c);
    void apars_handle_badseq(void);
    
    
public:    
    
    /** 
     * ANSI colors supported by the ESP Terminal
     */
    enum Color {
        BLACK = 0, RED, GREEN, YELLOW, BLUE, PURPLE, CYAN, GRAY_LT,
        GRAY, RED_LT, GREEN_LT, YELLOW_LT, BLUE_LT, PURPLE_LT, CYAN_LT, WHITE,
        
        // aliases    
        RED_DK=1, GREEN_DK=2, YELLOW_DK=3, BLUE_DK=4, PURPLE_DK=5, CYAN_DK=6, SILVER=7,
    };
    
    
    /**
     * Argument for screen or line clear commands
     */
    enum ClearMode {
        CLEAR_TO_CURSOR = 0,
        CLEAR_FROM_CURSOR = 1,        
        CLEAR_ALL = 2,
    };
    
    
    enum CtlKey {
        KEY_LEFT=0, KEY_RIGHT, KEY_UP, KEY_DOWN
    };
    
    
    /** Fired when user taps the screen at the given coords */
    void (*on_mouse_click)(int row, int col);
    
    
    /** Fired when the user presses one of the blue buttons (index is 1 thru 5) */
    void (*on_button)(int index);
    
    
    /** Fired on rx of the "ESP reset notification" byte */
    void (*on_esp_reset)(void);
    
    
    /** Fired on each received plain character */
    void (*on_char_rx)(char c);
    
    
    /** Fired on each key press (keyboard arrows etc) */
    void (*on_key_press)(CtlKey key);
    
    
    /** Handle generic OSC command (may be used in the future) */
    void (*on_osc_rx)(const char *str);
    

    /**
     * @brief Create a terminal instance from already initialized serial port
     *
     * Example:
     * Serial ser(PA_2, PA_3, 115200); // eg. for STM32F042
     * ESPTerm term(&ser);
     */
    ESPTerm(Serial *s);
    

    /**
     * @brief Create a terminal instance with given params
     */
    ESPTerm(PinName txPin, PinName rxPin, int baud=115200);
    

    /**
     * @brief Create a terminal instance with given params & 115200 baud
     */
    //ESPTerm(PinName txPin, PinName rxPin);
    
    
    /**
     * @brief Create with Serial at (PA_2, PA_3, 115200)
     */
    ESPTerm(void);
    
    
    // ----- Printing -----
    
    
    /** 
     * @brief printf() over the Serial
     *
     * Use for raw strings without formatting, or with custom escape sequences.
     */
    int printf(const char *fmt, ...);
    
    
    /** 
     * @brief Alias for printf()
     */
    int print(const char *fmt, ...);
    
    
    /** 
     * @brief Print with no args
     */
    int puts(const char *str) 
    {    
        return ser->puts(str);
    }
    
    
    /** 
     * @brief Print a single char
     */
    void putc(const char c) 
    {
        ser->putc(c);    
    }
    
    
    /** 
     * printf() over the Serial, followed by a newline (\\r\\n)
     *
     * Use for raw strings without formatting, or with custom escape sequences.
     * Especially useful for log messages, automatically terminating the line.
     */
    int println(const char *fmt, ...);    
    
    
    // ----- Colors -----
    
    
    /** 
     * @brief Set foreground text color
     * @param c - color
     */    
    void fg(Color c);
    
    
    /** 
     * @brief Set background text color
     * @param c - color
     */ 
    void bg(Color c);
    
    
    /** 
     * @brief Set both text colors
     * @param fg - foregorund color
     * @param bg - background color
     */ 
    void colors(Color fg, Color bg)
    {
        this->fg(fg);
        this->bg(bg);
    }
    
    
    /** 
     * @brief Send \\e[0m - reset all attributes
     */ 
    void reset_attribs(void);
    
    
    /** 
     * @brief Reset all attributes (alias)
     */ 
    void rst(void)
    {
        this->reset_attribs();
    }
    
    
    // ----- Cursor & clearing -----
    
    
    /**
     * @brief Move cursor to a given position
     *
     * Screen coordinates are 1-based, starting left-top,
     * growing down and right.
     *
     * @param y - row
     * @param x - column
     */     
    void go_to(int y, int x);
    
    
    /**
     * @brief Clear screen
     *
     * Replace part of the screen with spaces (ASCII 32) of the currently 
     * selected foregorund and background colors.
     *
     * @param mode - what to clear: part or all
     */
    void clear_screen(ClearMode mode);
    
    
    /**
     * @brief Clear in line
     *
     * Replace part of the current line with spaces (ASCII 32) of the 
     * currently selected foregorund and background colors.
     *
     * @param mode - what to clear: part or all
     */
    void clear_line(ClearMode mode);
    
    
    /**
     * @brief Clear the whole screen and move cursor to 1,1
     */
    void screen_reset(void);
    
    
    /**
     * @brief Set cursor visibility
     *
     * If hidden, there will be no blinking square on the screen,
     * but the cursor still works (ie. go_to works).
     *
     * Hiding the cursor is useful for ASCII-art GUIs (dialog boxes etc)
     */
    void show_cursor(bool yes);
    
    
    // ----- System cmds -----
    
    
    /**
     * @brief Perform a factory reset of the ESP Terminal
     *
     * This clears any saved WiFi config, restores the default AP name
     * and switches to AP mode. The module will reset itself.
     *
     * Expect some ASCII output from the module (and a burst of garbage
     * during the reset).
     */
    void factory_reset(void);


    /**
     * @brief Set screen size
     *
     * The total number of characters (rows*cols) is limited by the Terminal
     * firmware, at v0.5.2 that is 2000 characters (25x80)
     * 
     * @param rows - number of rows (screen height)
     * @param cols - number of columns (screen width)
     */
    void set_screen_size(int rows, int cols);
    
    
    /** 
     * Clear the Device OK flag 
     */
    void clear_status(void)
    {
        device_ok = false;    
    }
      
        
    /**
     * Query device status, clears "device_ok" and it'll be set by
     * the response message.
     *
     * To use the query function, call clear_status() first, and then poll 
     * query_status() with some delays in between.
     *
     * @return the status flag, from a previous query
     */
    bool query_status(void);
};


/** Convenience alias for using class enums etc */
typedef ESPTerm VT;

#endif /* ESPTERM_H */