154 lines
4.1 KiB
Arduino
154 lines
4.1 KiB
Arduino
|
/**
|
||
|
* 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.
|
||
|
*/
|
||
|
|
||
|
#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;
|
||
|
|
||
|
#define FONT_SCALE 2
|
||
|
|
||
|
uint16_t make_bw_color(uint16_t color) {
|
||
|
return (color >> 8) | (color & 0xFF);
|
||
|
}
|
||
|
|
||
|
struct tintty_display ili9341_display = {
|
||
|
display.vw,//ILI9341_WIDTH,
|
||
|
display.vh,//(ILI9341_HEIGHT - KEYBOARD_HEIGHT),
|
||
|
display.vw / display.font_w,//ILI9341_WIDTH / TINTTY_CHAR_WIDTH,
|
||
|
display.vh / display.font_h,//(ILI9341_HEIGHT - KEYBOARD_HEIGHT) / TINTTY_CHAR_HEIGHT,
|
||
|
|
||
|
[=](int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
|
||
|
//tft.fillRect(x, y, w, h, color);
|
||
|
//display.fill_rect(x*FONT_SCALE + display.ow, (y*FONT_SCALE + display.oh, w*FONT_SCALE, h*FONT_SCALE, make_bw_color(color));
|
||
|
},
|
||
|
|
||
|
[=](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]));
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
[=](int16_t col, int16_t row, uint16_t fg_color, uint16_t bg_color, char character){
|
||
|
display.print_character(col, row - scrolled, make_bw_color(fg_color), make_bw_color(bg_color), character);
|
||
|
},
|
||
|
|
||
|
[=](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, '_');
|
||
|
},
|
||
|
|
||
|
[=](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;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
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
|
||
|
SerialTty.begin(9600, SERIAL_8N1, 18, 19, false, 100);
|
||
|
|
||
|
// LK201 keyboard connected to pins 16 and 17
|
||
|
SerialKbd.begin(4800);
|
||
|
|
||
|
display.setup();
|
||
|
//uint16_t tftID = tft.readID();
|
||
|
//tft.begin(tftID);
|
||
|
|
||
|
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
|
||
|
tintty_idle(&ili9341_display);
|
||
|
input_idle();
|
||
|
}
|
||
|
},
|
||
|
[=](){
|
||
|
while(true) {
|
||
|
// process at least one idle loop first to allow input to happen
|
||
|
tintty_idle(&ili9341_display);
|
||
|
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); },
|
||
|
&ili9341_display
|
||
|
);
|
||
|
}
|
||
|
|
||
|
void loop() {
|
||
|
}
|