video-terminal-revival/video-terminal/video-terminal.ino

178 lines
4.8 KiB
Arduino
Raw Normal View History

2021-03-13 17:25:12 +00:00
/**
* Video Terminal
* VT100 emulated by ESP32 + TV display + LK201 keyboard
*
* TinTTY main sketch
* by Nick Matantsev 2017
*
* Original reference: VT100 emulation code written by Martin K. Schroeder
* and modified by Peter Scargill.
*/
2021-03-14 11:54:25 +00:00
#define SERIAL_KBD_BAUDRATE 4800 // hardcoded LK201 baud rate
#define SERIAL_KBD_RX_PIN 16 // hardcoded in Serial2
#define SERIAL_KBD_TX_PIN 17 // hardcoded in Serial2
#define SERIAL_TTY_BAUDRATE 9600 // configurable, depends on the TTY
#define SERIAL_TTY_CONFIG SERIAL_8N1 // configurable, depends on the TTY
#define SERIAL_TTY_RX_PIN 18 // configurable
#define SERIAL_TTY_TX_PIN 19 // configurable
2021-03-13 17:25:12 +00:00
#include <SPI.h>
#include <Adafruit_GFX.h>
#include "tintty.h"
#define SerialTty Serial1
#define SerialKbd Serial2
#include "Keyboard.h"
#include "Display.h"
Display display;
int16_t scrolled = 0;
uint16_t make_bw_color(uint16_t color) {
2021-03-13 23:08:55 +00:00
return ((color >> 8) | (color & 0xFF)) & 0xFF + 0xFF00;
2021-03-13 17:25:12 +00:00
}
2021-03-13 23:08:55 +00:00
#define FONT_W display.font_w
#define FONT_H display.font_h
struct tintty_display composite_display = {
display.vw, // width
display.vh, // height
display.vw / display.font_w, // chars horizontal
display.vh / display.font_h, // chars vertical
2021-03-13 17:25:12 +00:00
2021-03-13 23:08:55 +00:00
// fill rect
2021-03-13 17:25:12 +00:00
[=](int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
2021-03-13 23:08:55 +00:00
display.fill_rect(x*FONT_W + display.ow, y*FONT_H + display.oh, w*FONT_W, h*FONT_H, make_bw_color(color));
2021-03-13 17:25:12 +00:00
},
2021-03-13 23:08:55 +00:00
// draw pixels
2021-03-13 17:25:12 +00:00
[=](int16_t x, int16_t y, int16_t w, int16_t h, uint16_t *pixels){
//tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
//tft.pushColors(pixels, w * h, 1);
for (int px = 0; px < w; px++) {
for (int py = 0; py < h; py++) {
int i = py*w + px;
//display.pixel(x + display.ow + px, y + display.oh + py, pixels[i]);
//display.fill_rect(x*FONT_SCALE + display.ow + px*FONT_SCALE, y*FONT_SCALE + display.oh + py*FONT_SCALE, FONT_SCALE, FONT_SCALE, make_bw_color(pixels[i]));
}
}
},
2021-03-13 23:08:55 +00:00
// print character
2021-03-13 17:25:12 +00:00
[=](int16_t col, int16_t row, uint16_t fg_color, uint16_t bg_color, char character){
2021-03-13 23:08:55 +00:00
display.print_character(col, row - scrolled, make_bw_color(0), make_bw_color(0), ' ');
2021-03-13 17:25:12 +00:00
display.print_character(col, row - scrolled, make_bw_color(fg_color), make_bw_color(bg_color), character);
},
2021-03-13 23:08:55 +00:00
// print cursor
2021-03-13 17:25:12 +00:00
[=](int16_t col, int16_t row, uint16_t color){
display.fill_rect(col*display.font_w + display.ow, (row+1 - scrolled)*display.font_h-1 + display.oh, display.font_w, 1, make_bw_color(color));
//display.print_character(col, row, make_bw_color(color), 0, '_');
},
2021-03-13 23:08:55 +00:00
// scroll
2021-03-13 17:25:12 +00:00
[=](int16_t offset){
//tft.vertScroll(0, (ILI9341_HEIGHT - KEYBOARD_HEIGHT), offset);
int16_t rows = display.vh / display.font_h;
int16_t diff = (rows + offset - (scrolled % rows)) % rows;
display.scroll(diff*display.font_h);
scrolled += diff;
}
};
2021-03-13 23:08:55 +00:00
/**
* Keyboard callbacks.
*/
struct tintty_keyboard lk201_keyboard = {
[=]() {
Serial.print("<BELL RING> ");
SerialKbd.print((char)LK_RING_BELL);
}
};
2021-03-13 17:25:12 +00:00
void tty_keyboard_process()
{
// read keyboard and send it to the host
if (SerialKbd.available() > 0) {
int key = SerialKbd.read();
keyboard_handle_key(key);
}
}
// buffer to test various input sequences
char *test_buffer = "-- \e[1mTinTTY\e[m --\r\n";
uint8_t test_buffer_cursor = 0;
void input_init() {};
void input_idle() {};
void setup() {
// Debug port
Serial.begin(115200);
Serial.println("Running!");
// TTY host
2021-03-14 11:54:25 +00:00
SerialTty.begin(SERIAL_TTY_BAUDRATE, SERIAL_TTY_CONFIG, SERIAL_TTY_RX_PIN, SERIAL_TTY_TX_PIN, false, 100);
2021-03-13 17:25:12 +00:00
// LK201 keyboard connected to pins 16 and 17
2021-03-14 11:54:25 +00:00
SerialKbd.begin(SERIAL_KBD_BAUDRATE);
2021-03-13 17:25:12 +00:00
display.setup();
input_init();
tintty_run(
[=](){
// peek idle loop
while (true) {
// first peek from the test buffer
if (test_buffer[test_buffer_cursor]) {
return test_buffer[test_buffer_cursor];
}
tty_keyboard_process();
// fall back to normal blocking serial input
if (SerialTty.available() > 0) {
return (char)SerialTty.peek();
}
// idle logic only after peeks failed
2021-03-13 23:08:55 +00:00
tintty_idle(&composite_display);
2021-03-13 17:25:12 +00:00
input_idle();
}
},
[=](){
while(true) {
// process at least one idle loop first to allow input to happen
2021-03-13 23:08:55 +00:00
tintty_idle(&composite_display);
2021-03-13 17:25:12 +00:00
input_idle();
tty_keyboard_process();
// first read from the test buffer
if (test_buffer[test_buffer_cursor]) {
return test_buffer[test_buffer_cursor++];
}
// fall back to normal blocking serial input
if (SerialTty.available() > 0) {
return (char)SerialTty.read();
}
}
},
[=](char ch){ SerialTty.print(ch); },
2021-03-13 23:08:55 +00:00
&composite_display,
&lk201_keyboard
2021-03-13 17:25:12 +00:00
);
}
void loop() {
}