FabGL
ESP32 Display Controller and Graphics Library
VGA/AnsiTerminal/AnsiTerminal.ino

Serial VT/ANSI Terminal

/*
Created by Fabrizio Di Vittorio (fdivitto2013@gmail.com) - <http://www.fabgl.com>
Copyright (c) 2019-2022 Fabrizio Di Vittorio.
All rights reserved.
* Please contact fdivitto2013@gmail.com if you need a commercial license.
* This library and related software is available under GPL v3.
FabGL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FabGL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FabGL. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Credits:
- Guido Lehwalder, https://github.com/guidol70 : using USB-serial Port for ANSI-Terminal (https://github.com/fdivitto/FabGL/issues/110)
*/
#include "fabgl.h"
fabgl::PS2Controller PS2Controller;
fabgl::Terminal Terminal;
// notes about GPIO 2 and 12
// - GPIO2: may cause problem on programming. GPIO2 must also be either left unconnected/floating, or driven Low, in order to enter the serial bootloader.
// In normal boot mode (GPIO0 high), GPIO2 is ignored.
// - GPIO12: should be avoided. It selects flash voltage. To use it disable GPIO12 detection setting efuses with:
// python espefuse.py --port /dev/cu.SLAB_USBtoUART set_flash_voltage 3.3V
// WARN!! Good for ESP32 with 3.3V voltage (ESP-WROOM-32). This will BRICK your ESP32 if the flash isn't 3.3V
// NOTE1: replace "/dev/cu.SLAB_USBtoUART" with your serial port
// NOTE2: espefuse.py is downloadable from https://github.com/espressif/esptool
// UART Pins for USB serial
#define UART_URX 3
#define UART_UTX 1
// UART Pins for normal serial Port
#define UART_SRX 34
#define UART_STX 2
// RTS/CTS hardware flow gpios
#define RTS 13
#define CTS 35
// settings reset control
/* for old WROOM-32 boards
#define RESET_PIN 12
#define RESET_PIN_ACTIVE 1 // 0 = reset when low, 1 = reset when high
#define USERESETPIN 1 // 1 = reset enabled
//*/
#define RESET_PIN 39
#define RESET_PIN_ACTIVE 0 // 0 = reset when low, 1 = reset when high
#define USERESETPIN 1 // 1 = reset enabled
#include "confdialog.h"
void setup()
{
#if FABGLIB_TERMINAL_DEBUG_REPORT
Serial.begin(115200); delay(500); Serial.write("\n\nReset\n\n"); // DEBUG ONLY
#endif
disableCore0WDT();
delay(100); // experienced crashes without this delay!
disableCore1WDT();
// more stack is required for the UI (used inside Terminal.onVirtualKey)
Terminal.keyboardReaderTaskStackSize = 3000;
Terminal.inputQueueSize = 2048; // 2048 good to pass vttest
preferences.begin("AnsiTerminal", false);
ConfDialogApp::checkVersion();
#if USERESETPIN
pinMode(RESET_PIN, INPUT);
if (digitalRead(RESET_PIN) == RESET_PIN_ACTIVE)
preferences.clear();
#endif
// because mouse is optional, don't re-try if it is not found (to speed-up boot)
// keyboard configured on port 0, and optionally mouse on port 1
PS2Controller.begin(PS2Preset::KeyboardPort0_MousePort1);
ConfDialogApp::setupDisplay();
ConfDialogApp::loadConfiguration();
#if FABGLIB_TERMINAL_DEBUG_REPORT
Terminal.setLogStream(Serial); // debug only
#endif
Terminal.clear();
Terminal.enableCursor(true);
if (ConfDialogApp::getBootInfo() == BOOTINFO_ENABLED) {
Terminal.write("* * FabGL - Serial Terminal * *\r\n");
Terminal.write("* * 2019-2022 by Fabrizio Di Vittorio - www.fabgl.com * *\r\n\n");
Terminal.printf("Version : %d.%d\r\n", TERMVERSION_MAJ, TERMVERSION_MIN);
Terminal.printf("Screen Size : %d x %d\r\n", DisplayController->getViewPortWidth(), DisplayController->getViewPortHeight());
Terminal.printf("Terminal Size : %d x %d\r\n", Terminal.getColumns(), Terminal.getRows());
Terminal.printf("Keyboard Layout : %s\r\n", PS2Controller.keyboard()->isKeyboardAvailable() ? SupportedLayouts::names()[ConfDialogApp::getKbdLayoutIndex()] : "No Keyboard");
//Terminal.printf("Mouse : %s\r\n", PS2Controller.mouse()->isMouseAvailable() ? "Yes" : "No");
Terminal.printf("Terminal Type : %s\r\n", SupportedTerminals::names()[(int)ConfDialogApp::getTermType()]);
//Terminal.printf("Free Memory : %d bytes\r\n", heap_caps_get_free_size(MALLOC_CAP_32BIT));
if (ConfDialogApp::getSerCtl() == SERCTL_ENABLED)
Terminal.printf("Serial Port : USB RX-Pin[%d] TX-Pin[%d]\r\n", UART_URX, UART_UTX);
else
Terminal.printf("Serial Port : Serial RX-Pin[%d] TX-Pin[%d]\r\n", UART_SRX, UART_STX);
Terminal.printf("Serial Parameters : %s\r\n", ConfDialogApp::getSerParamStr());
Terminal.write("\r\nPress F12 to change terminal configuration and CTRL-ALT-F12 to reset settings\r\n\n");
} else if (ConfDialogApp::getBootInfo() == BOOTINFO_TEMPDISABLED) {
preferences.putInt(PREF_BOOTINFO, BOOTINFO_ENABLED);
}
// onVirtualKey is triggered whenever a key is pressed or released
Terminal.onVirtualKeyItem = [&](VirtualKeyItem * vkItem) {
if (vkItem->vk == VirtualKey::VK_F12) {
if (vkItem->CTRL && (vkItem->LALT || vkItem->RALT)) {
Terminal.deactivate();
preferences.clear();
// show reboot dialog
auto rebootApp = new RebootDialogApp;
rebootApp->run(DisplayController);
} else if (!vkItem->CTRL && !vkItem->LALT && !vkItem->RALT && !vkItem->down) {
// releasing F12 key to open configuration dialog
Terminal.deactivate();
PS2Controller.mouse()->emptyQueue(); // avoid previous mouse movements to be showed on UI
auto dlgApp = new ConfDialogApp;
dlgApp->run(DisplayController);
auto progToInstall = dlgApp->progToInstall;
delete dlgApp;
Terminal.activate();
// it has been requested to install a demo program?
if (progToInstall > -1)
installProgram(progToInstall);
vkItem->vk = VirtualKey::VK_NONE;
}
}
};
// onUserSequence is triggered whenever a User Sequence has been received (ESC + '_#' ... '$'), where '...' is sent here
Terminal.onUserSequence = [&](char const * seq) {
// 'R': change resolution (for example: ESC + "_#R512x384x64$")
for (int i = 0; i < RESOLUTIONS_COUNT; ++i)
if (strcmp(RESOLUTIONS_CMDSTR[i], seq) == 0) {
// found resolution string
preferences.putInt(PREF_TEMPRESOLUTION, i);
if (ConfDialogApp::getBootInfo() == BOOTINFO_ENABLED)
preferences.putInt(PREF_BOOTINFO, BOOTINFO_TEMPDISABLED);
ESP.restart();
}
};
}
void loop()
{
// the job is done using UART interrupts
vTaskDelete(NULL);
}
int getViewPortHeight()
Determines vertical size of the viewport.
int getViewPortWidth()
Determines horizontal size of the viewport.
Represents the base abstract class for bitmapped display controllers.
bool isKeyboardAvailable()
Checks if keyboard has been detected and correctly initialized.
Definition: keyboard.h:165
void emptyVirtualKeyQueue()
Empties the virtual keys queue.
Definition: keyboard.cpp:722
void emptyQueue()
Empties the mouse status and events queue.
Definition: mouse.cpp:386
static void quickCheckHardware()
Disable re-try when a mouse is not found.
Definition: mouse.h:373
static Mouse * mouse()
Returns the instance of Mouse object automatically created by PS2Controller.
static Keyboard * keyboard()
Returns the instance of Keyboard object automatically created by PS2Controller.
static void begin(gpio_num_t port0_clkGPIO, gpio_num_t port0_datGPIO, gpio_num_t port1_clkGPIO=GPIO_UNUSED, gpio_num_t port1_datGPIO=GPIO_UNUSED)
Initializes PS2 device controller.
The PS2 device controller class.
Definition: ps2controller.h:82
int getRows()
Returns the number of lines.
Definition: terminal.h:1217
void clear(bool moveCursor=true)
Clears the screen.
Definition: terminal.cpp:1010
void setLogStream(Stream &stream)
Sets the stream where to output debugging logs.
Definition: terminal.h:1134
int getColumns()
Returns the number of columns.
Definition: terminal.h:1210
static int keyboardReaderTaskStackSize
Stack size of the task that reads keys from keyboard and send ANSI/VT codes to output stream in Termi...
Definition: terminal.h:1528
size_t write(const uint8_t *buffer, size_t size)
Sends specified number of codes to the display.
Definition: terminal.cpp:1958
void deactivate()
Deactivates this terminal.
Definition: terminal.cpp:290
Keyboard * keyboard()
Gets associated keyboard object.
Definition: terminal.h:1365
static int inputQueueSize
Number of characters the terminal can "write" without pause (increase if you have loss of characters ...
Definition: terminal.h:1510
void activate(TerminalTransition transition=TerminalTransition::None)
Activates this terminal for input and output.
Definition: terminal.cpp:215
void enableCursor(bool value)
Enables or disables cursor.
Definition: terminal.cpp:1115
Delegate< VirtualKeyItem * > onVirtualKeyItem
Delegate called whenever a new virtual key is received from keyboard, including shift states.
Definition: terminal.h:1486
bool begin(BaseDisplayController *displayController, int maxColumns=-1, int maxRows=-1, Keyboard *keyboard=nullptr)
Initializes the terminal.
Definition: terminal.cpp:323
Delegate< char const * > onUserSequence
Delegate called whenever a new user sequence has been received.
Definition: terminal.h:1496
An ANSI-VT100 compatible display terminal.
Definition: terminal.h:953
This file is the all in one include file. Application can just include this file to use FabGL library...
@ VK_F12
Definition: fabutils.h:1277
@ VK_NONE
Definition: fabutils.h:1098