#include <Arduino.h>
#include "SPI.h"
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#define ILI9341_VSCRDEF 0x33
#define ILI9341_VSCRSADD 0x37
int xp = 0;
int yp = 0;
uint16_t bg = ILI9341_BLACK;
uint16_t fg = ILI9341_WHITE;
int screenWd = 240;
int screenHt = 320;
int wrap = 0;
int bold = 0;
int sx = 1;
int sy = 1;
int horizontal = -1;
int scrollMode = 1;
#define WRAP_PIN 5
#define HORIZ_PIN 21
#define TFT_DC 2
#define TFT_CS 15
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// Uncomment below the font you find the most readable for you
// 7x8 bold - perfect for small term font
#include "font_b7x8.h"
const uint16_t *fontRects = font_b7x8_Rects;
const uint16_t *fontOffs = font_b7x8_CharOffs;
int charWd = 7;
int charHt = 10; // real 8
int charYoffs = 1;
// 7x8 - perfect for small terminal font
// #include "font_7x8.h"
// const uint16_t *fontRects = font_7x8_Rects;
// const uint16_t *fontOffs = font_7x8_CharOffs;
// int charWd = 7;
// int charHt = 10; // real 8
// int charYoffs = 1;
// 6x8
// #include "font_6x8.h"
// const uint16_t *fontRects = font_6x8_Rects;
// const uint16_t *fontOffs = font_6x8_CharOffs;
// int charWd = 6;
// int charHt = 9; // real 8
// int charYoffs = 1;
// nice 8x16 vga terminal font
// #include "font_term_8x16.h"
// const uint16_t *fontRects = wlcd_font_term_8x16_0_127_Rects;
// const uint16_t *fontOffs = wlcd_font_term_8x16_0_127_CharOffs;
// int charWd = 8;
// int charHt = 16;
// int charYoffs = 0;
// nice big for terminal
// #include "font_fxs_8x15.h"
// const uint16_t *fontRects = wlcd_font_fxs_8x15_16_127_Rects;
// const uint16_t *fontOffs = wlcd_font_fxs_8x15_16_127_CharOffs;
// int charWd = 8;
// int charHt = 15; // real 15
// int charYoffs = 0;
// my nice 10x16 term
// #include "font_term_10x16.h"
// const uint16_t *fontRects = font_term_10x16_Rects;
// const uint16_t *fontOffs = font_term_10x16_CharOffs;
// int charWd = 10;
// int charHt = 16;
// int charYoffs = 0;
void drawChar(int16_t x, int16_t y, unsigned char c,
uint16_t color, uint16_t bg, uint8_t sx, uint8_t sy)
{
if ((x >= screenWd) || // Clip right
(y >= screenHt) || // Clip bottom
((x + charWd * sx - 1) < 0) || // Clip left
((y + charHt * sy - 1) < 0)) // Clip top
return;
if (c > 127)
return;
uint16_t recIdx = fontOffs[c];
uint16_t recNum = fontOffs[c + 1] - recIdx;
if (bg && bg != color)
tft.fillRect(x, y, charWd * sx, charHt * sy, bg);
if (charWd <= 16 && charHt <= 16)
for (int i = 0; i < recNum; i++)
{
int v = fontRects[i + recIdx];
int xf = v & 0xf;
int yf = charYoffs + ((v & 0xf0) >> 4);
int wf = 1 + ((v & 0xf00) >> 8);
int hf = 1 + ((v & 0xf000) >> 12);
tft.fillRect(x + xf * sx, y + yf * sy, bold + wf * sx, hf * sy, color);
}
else
for (int i = 0; i < recNum; i++)
{
uint8_t *rects = (uint8_t *)fontRects;
int idx = (i + recIdx) * 3;
int xf = rects[idx + 0] & 0x3f;
int yf = rects[idx + 1] & 0x3f;
int wf = 1 + rects[idx + 2] & 0x3f;
int hf = 1 + (((rects[idx + 0] & 0xc0) >> 6) | ((rects[idx + 1] & 0xc0) >> 4) | ((rects[idx + 2] & 0xc0) >> 2));
tft.fillRect(x + xf * sx, y + yf * sy, bold + wf * sx, hf * sy, color);
}
}
void scroll()
{
xp = 0;
yp += charHt * sy;
if (yp + charHt > screenHt)
yp = 0;
tft.fillRect(0, yp, screenWd, charHt * sy, ILI9341_BLACK);
if (scrollMode)
tft.scrollTo(320 - yp - charHt * sy);
else
tft.scrollTo(0);
}
int escMode = 0;
int nVals = 0;
int vals[10] = {0};
void printChar(char c)
{
if (c == 0x1b)
{
escMode = 1;
return;
}
if (escMode == 1)
{
if (c == '[')
{
escMode = 2;
nVals = 0;
}
else
escMode = 0;
return;
}
if (escMode == 2)
{
if (isdigit(c))
vals[nVals] = vals[nVals] * 10 + (c - '0');
else if (c == ';')
nVals++;
else if (c == 'm')
{
escMode = 0;
nVals++;
for (int i = 0; i < nVals; i++)
{
int v = vals[i];
static const uint16_t colors[] = {
0x0000, // 0-black
0xf800, // 1-red
0x0780, // 2-green
0xfe00, // 3-yellow
0x001f, // 4-blue
0xf81f, // 5-magenta
0x07ff, // 6-cyan
0xffff // 7-white
};
if (v == 0)
{ // all attributes off
if (nVals == 1)
{
fg = ILI9341_WHITE;
bg = ILI9341_BLACK;
}
bold = 0;
}
else if (v == 1)
{ // all attributes off
bold = 1;
}
else if (v >= 30 && v < 38)
{ // fg colors
fg = colors[v - 30];
}
else if (v >= 40 && v < 48)
{
bg = colors[v - 40];
}
}
vals[0] = vals[1] = vals[2] = vals[3] = 0;
nVals = 0;
}
else
{
escMode = 0;
vals[0] = vals[1] = vals[2] = vals[3] = 0;
nVals = 0;
}
return;
}
if (c == 10)
{
scroll();
return;
}
if (c == 13)
{
xp = 0;
return;
}
if (c == 8)
{
if (xp > 0)
xp -= charWd * sx;
tft.fillRect(xp, yp, charWd * sx, charHt * sy, ILI9341_BLACK);
return;
}
if (xp < screenWd)
drawChar(xp, yp, c, fg, bg, sx, sy);
xp += charWd * sx;
if (xp >= screenWd && wrap)
scroll();
}
void printString(char *str)
{
while (*str)
printChar(*str++);
}
void checkButtons()
{
wrap = digitalRead(WRAP_PIN) ? 0 : 1;
int orient = digitalRead(HORIZ_PIN) ? 0 : 1;
if (orient != horizontal)
{
horizontal = orient;
scrollMode = horizontal ? 0 : 1;
tft.setRotation(horizontal ? 1 : 2);
screenWd = tft.width();
screenHt = tft.height();
}
}
void setup()
{
Serial.begin(115200);
pinMode(WRAP_PIN, INPUT_PULLUP);
pinMode(HORIZ_PIN, INPUT_PULLUP);
tft.begin();
//tft.setRotation(3);
tft.setScrollMargins(0, 0);
checkButtons();
tft.setCursor(0, 0);
tft.fillScreen(ILI9341_BLACK);
sx = 1;
sy = 2;
printString("\e[0;44m *** Terminal Init *** \e[0m\n");
sy = 1;
}
void loop(void)
{
checkButtons();
// while (Serial.available())
// printChar(Serial.read());
printString("hello world!\n");
delay(1000);
}