Skip to content

Instantly share code, notes, and snippets.

@vishnumaiea
Last active November 12, 2017 13:55
Show Gist options
  • Save vishnumaiea/47c9fe7f820c723de6a0d2c6872d1db2 to your computer and use it in GitHub Desktop.
Save vishnumaiea/47c9fe7f820c723de6a0d2c6872d1db2 to your computer and use it in GitHub Desktop.
//========================================================================//
// //
// ILI9481 3.2" 320 x 480 TFT LCD Driver for ESP32 //
// //
// Author : Vishnu M Aiea //
// GitHub : https://github.com/vishnumaiea //
// License : GNU GPL v3 //
// Date Created : IST 04:07:07 PM, 30-10-2017, Monday //
// Last Modified : 07:24:42 PM, 12-11-2017, Sunday //
// File Version : 4 //
// //
//========================================================================//
#include <pgmspace.h>
// #include <esp_clk.h>
#define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; } //swaps two 16 bit values
//========================================================================//
//font specific declarations
// #include "Montserrat_Medium21x20.h"
#include "Poppins_Medium34x36.h"
class fontClass {
public:
const char * fontArray;
int fontWidth; //width of each char (don't worry; char widths are still variable)
int fontHeight; //font height
int charByteLength; //count of bytes for each char
int verticalByteCount; //no. of vertical bytes needed for a char
char startChar; //first char in font
char endChar; //last char in font
int charCount; //total char count in font
fontClass (const char * a, int w, int h, int c, int v, char s, char e, int n) {
fontArray = a;
fontWidth = w;
fontHeight = h;
charByteLength = c;
verticalByteCount = v;
startChar = s;
endChar = e;
charCount = n;
}
};
// fontClass * Montserrat_Medium21x20; //create a pointer so that can be initialized later
fontClass * Poppins_Medium34x36;
// Montserrat_Medium21x20.fontArray = someArray;
// Montserrat_Medium21x20.fontWidth = 21;
// Montserrat_Medium21x20.fontHeight = 20;
// Montserrat_Medium21x20.charByteLength = 64;
// Montserrat_Medium21x20.verticalByteCount = 3;
// Montserrat_Medium21x20.startChar = 33;
// Montserrat_Medium21x20.endChar = 126;
// Montserrat_Medium21x20.charCount = 93;
//========================================================================//
//define the pins for 8-bit parallel drive
#define CS_PIN 26
#define RST_PIN 12
#define DC_PIN 14
#define WR_PIN 27
#define PD0 15 //parallel data pins
#define PD1 2
#define PD2 0
#define PD3 4
#define PD4 16
#define PD5 17
#define PD6 21
#define PD7 22
//========================================================================//
//display specific parameters
static const int Width = 320; //constants
static const int Height = 480;
int _width = Width; //becasue we can change these later if needed
int _height = Height; //eg in setRotation()
//========================================================================//
//function declarations
void writeData (uint8_t);
void writeCommand (uint8_t);
void initializeDisplay (void);
void startDisplay (void);
void writeData16 (uint16_t);
void writeData8 (uint8_t);
void displayOn (void);
void displayOff (void);
void setAddrWindow (int, int, int, int);
void drawPixel (int, int, uint16_t);
void fillScreen (uint16_t);
void fillRectangle (int, int, int, int, uint16_t);
void drawHorizontalLine (int, int, int, uint16_t);
void drawVerticalLine (int, int, int, uint16_t);
void setRotation (int);
void invertDisplay (bool);
void openWindow (int, int, int, int);
void windowData (uint16_t);
void windowData (uint16_t*, int);
//========================================================================//
//setup function runs once
void setup() {
//font initializations
// Montserrat_Medium21x20 = new fontClass ( Montserrat_Medium21x20_fontArray,
// Montserrat_Medium21x20_fontWidth,
// Montserrat_Medium21x20_fontHeight,
// Montserrat_Medium21x20_charByteLength,
// Montserrat_Medium21x20_verticalByteCount,
// Montserrat_Medium21x20_startChar,
// Montserrat_Medium21x20_endChar,
// Montserrat_Medium21x20_charCount );
Poppins_Medium34x36 = new fontClass ( Poppins_Medium34x36_fontArray,
Poppins_Medium34x36_fontWidth,
Poppins_Medium34x36_fontHeight,
Poppins_Medium34x36_charByteLength,
Poppins_Medium34x36_verticalByteCount,
Poppins_Medium34x36_startChar,
Poppins_Medium34x36_endChar,
Poppins_Medium34x36_charCount );
Serial.begin(115200);
Serial.print("CPU Clock = ");
Serial.println(ESP.getCpuFreqMHz());
Serial.println("Initializing...");
Serial.println();
pinMode(CS_PIN, OUTPUT); //set all pins as outputs
pinMode(RST_PIN, OUTPUT);
pinMode(DC_PIN, OUTPUT);
pinMode(WR_PIN, OUTPUT);
pinMode(PD0, OUTPUT);
pinMode(PD1, OUTPUT);
pinMode(PD2, OUTPUT);
pinMode(PD3, OUTPUT);
pinMode(PD4, OUTPUT);
pinMode(PD5, OUTPUT);
pinMode(PD6, OUTPUT);
pinMode(PD7, OUTPUT);
initializeDisplay();
setRotation(1);
delay(1);
setAddrWindow(0, 0, _width, _height);
fillScreen(65535);
}
//========================================================================//
//infinite loop
int color = 0;
void loop() {
//drawHorizontalLine(50, 300, 470, 10);
//drawVerticalLine(50, 50, 350, 10);
// drawLine(10, 20, 300, 255, 21); //x0, y0, x1, y1, color
// drawCircle(200, 200, 100, 20);
// fillCircle(200, 200, 100, 5000);
// drawRoundRectangle(100, 100, 100, 100, 10, 500);
// fillRoundRectangle(100, 100, 100, 100, 10, 6500);
// fillRectangle(100, 100, 100, 100, 4000);
// drawRectangle(100, 100, 100, 100, 200);
// delay(200);
// Serial.println("Working..");
// Serial.print("CPU Clock = ");
// Serial.println(ESP.getCpuFreqMHz());
// if(color >= 65535) color = 0;
//
// //displayOff();
// setAddrWindow(0, 0, _width, _height);
// for(int i=0; i<320; i++) {
// for(int j=0; j<480; j++) {
// writeData16(color);
// }
// }
// color++;
// delay(1);
// fillScreen(65535);
// delay(1000);
// fillScreen(0);
// delay(1000);
// for(int i=33; i<127; i++) {
// drawChar(100, 100, i, 0, 65535, Poppins_Medium34x36);
// delay(500);
// fillScreen(65535);
// }
printText("VISHNU M AIEA", 100, 100, 0, 65535, Poppins_Medium34x36);
delay(10);
// String S = "VISHNU";
// char stringBuffer[S.length()+1];
// Serial.println(S.length()+1);
// S.toCharArray(stringBuffer, S.length()+1);
// Serial.println(stringBuffer);
}
//========================================================================//
//initializes the display with proper reset sequence
void initializeDisplay() {
digitalWrite(DC_PIN, HIGH); //DC high
digitalWrite(CS_PIN, HIGH); //CS high
digitalWrite(WR_PIN, HIGH); //WR high
digitalWrite(RST_PIN, HIGH); //RST high
delay(100);
digitalWrite(RST_PIN, LOW); //RST low
delay(100);
digitalWrite(RST_PIN, HIGH); //RST high
delay(100);
digitalWrite(CS_PIN, LOW); //CS low
startDisplay();
Serial.println("LCD Initialized.");
}
//========================================================================//
//starts the display with required configurations
void startDisplay() {
writeCommand(0x11); //exit sleep mode
delay(80);
writeCommand(0xD0); //power setting
writeData8(0x07);
writeData8(0x42);
writeData8(0x18);
writeCommand(0xD1); //VCOM control
writeData8(0x00);
writeData8(0x07);
writeData8(0x10);
writeCommand(0xD2); //power setting for normal mode
writeData8(0x01);
writeData8(0x02); //Fosc setting
writeCommand(0xC0); //panel driving setting - 5 parameters
writeData8(0x10); //REV=1, SM=0, GS=0 - grayscale inversion enabled : will invert colors
//writeData8(0x00); //REV=0, SM=0, GS=0 - no color inversion
writeData8(0x3B); //NL[5] - max lines
writeData8(0x00); //SCN - scanning start position
writeData8(0x02); //NDL (non-display area o/p level), PTS[3]
//writeData8(0x11); //PTG=1 (interval scan), ISC[3]=0001 (3 frames)
// writeData8(0x1F); //PTG=1 (interval scan), ISC[3]=1111 (31 frames)
writeData8(0x01); //PTG=0 (normal scan), ISC[3]=0002 (3 frames)
writeCommand(0xC5); //frame rate and inversion control - 1 parameter
//writeData8(0x03); //72FPS (default) - this had backlight flickering
writeData8(0x00); //125 FPS (max) - this has no flickering
writeCommand(0xB3); //frame memeory access and interface setting
writeData8(0x0); //extra data is ignored
writeData8(0x0); //all defaults
writeData8(0x0);
writeData8(0x0);
writeCommand(0x35); //tearing compensation
writeData8(0x0);
writeCommand(0xC1); //display timing for normal mode
writeData8(0x10); //BC=0 (frame inversion waveform)
writeData8(0x10); //line period is 16 clocks
writeData8(0x22); //front and back porch lines = 2
writeCommand(0xC8); //gamma setting
writeData8(0x00);
writeData8(0x32);
writeData8(0x36);
writeData8(0x45);
writeData8(0x06);
writeData8(0x16);
writeData8(0x37);
writeData8(0x75);
writeData8(0x77);
writeData8(0x54);
writeData8(0x0C);
writeData8(0x00);
writeCommand(0x36); //set address mode - 1 parameter
writeData8(0x0A); //BGR, horizontal flip
writeCommand(0x13); //eneter normal mode - no param
writeCommand(0x3A); //set pixel format - 1 parameter
writeData8(0x55); //16-bit per pixel
//writeData(0x66); //18-bit per pixel
setAddrWindow(0, 0, _width, _height);
//writeCommand(0x2A); //set column address
//writeData8(0x00);
//writeData8(0x00);
//writeData8(0x01);
//writeData8(0x3F);
//writeCommand(0x2B); //set page address
//writeData8(0x00);
//writeData8(0x00);
//writeData8(0x01);
//writeData8(0xDF);
delay(120);
writeCommand(0x29); //set display on
}
//========================================================================//
//writes 8 bit data
void writeData (uint8_t inputData) {
digitalWrite(CS_PIN, LOW); //CS low
digitalWrite(RST_PIN, HIGH); //RST high
digitalWrite(DC_PIN, HIGH); //DC high
digitalWrite(WR_PIN, HIGH); //WR high
writeToPins(inputData);
}
//========================================================================//
//writes 8 bit command
void writeCommand (uint8_t inputCommand) {
digitalWrite(CS_PIN, LOW); //CS low
digitalWrite(RST_PIN, HIGH); //RST high
digitalWrite(DC_PIN, LOW); //DC low
digitalWrite(WR_PIN, HIGH); //WR high
writeToPins(inputCommand);
digitalWrite(DC_PIN, HIGH); //high
}
//========================================================================//
//writes 16 bit data to the 8-bit bus
void writeData16 (uint16_t inputData) {
digitalWrite(DC_PIN, HIGH); //DC high
uint8_t highByte = (uint8_t) ((unsigned int)(inputData >> 8) & 0x00FF); //write the high byte (big endian)
writeToPins(highByte);
uint8_t lowByte = (uint8_t) inputData & 0x00FF; //writes the low byte
writeToPins(lowByte);
}
//========================================================================//
//writes 8-bit data to 8-bit bus
void writeData8 (uint8_t inputData) {
digitalWrite(DC_PIN, HIGH); //DC high
writeToPins(inputData);
}
//========================================================================//
//writes 8-bit data to individual pins
//LSB is ANDed with 1, and writes HIGH is the ouput is 1, LOW otherwise
//then the data is shifted right to do this for all 8 bits
void writeToPins (uint8_t inputData) {
digitalWrite (PD0, (((inputData & 0x01) == 1) ? HIGH : LOW)); //no need to shift here
digitalWrite (PD1, ((((unsigned int)(inputData >> 1) & 0x01) == 1) ? HIGH : LOW)); //AND the 2nd bit
digitalWrite (PD2, ((((unsigned int)(inputData >> 2) & 0x01) == 1) ? HIGH : LOW));
digitalWrite (PD3, ((((unsigned int)(inputData >> 3) & 0x01) == 1) ? HIGH : LOW));
digitalWrite (PD4, ((((unsigned int)(inputData >> 4) & 0x01) == 1) ? HIGH : LOW));
digitalWrite (PD5, ((((unsigned int)(inputData >> 5) & 0x01) == 1) ? HIGH : LOW));
digitalWrite (PD6, ((((unsigned int)(inputData >> 6) & 0x01) == 1) ? HIGH : LOW));
digitalWrite (PD7, ((((unsigned int)(inputData >> 7) & 0x01) == 1) ? HIGH : LOW));
digitalWrite (WR_PIN, LOW); //WR low
digitalWrite (WR_PIN, HIGH); //WR high
}
//========================================================================//
void displayOn () {
writeCommand (0x29); //set display on
}
//========================================================================//
void displayOff () {
writeCommand (0x28); //set display off
}
//========================================================================//
//sets the number of pixels (or a rectangular window) data to be written to
void setAddrWindow(int x0, int y0, int x1, int y1) {
x1 = (x1 >= _width) ? _width -1 : x1;
y1 = (y1 >= _height) ? _height -1 : y1;
writeCommand(0x2A); //set col address - 4 param
writeData16(x0);
writeData16(x1);
writeCommand(0x2B); //set page address - 4 param
writeData16(y0);
writeData16(y1);
writeCommand(0x2C); //write memory start
//writeCommand(0x3C); //write memory continue
}
//========================================================================//
//sets a single pixel to a color
void drawPixel(int x, int y, uint16_t color) {
if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
setAddrWindow(x,y,x,y);
writeData16(color);
}
//========================================================================//
//fills the entire screen with a color
void fillScreen(uint16_t color) {
//fillRectangle(0, 0, _width, _height, color);
setAddrWindow(0, 0, _width, _height);
for(int i=0; i<_height; i++) {
for(int j=0; j<_width; j++) {
writeData16(color);
}
}
}
//========================================================================//
//fast drawing of horizontal line
void drawHorizontalLine(int x, int y, int w, uint16_t color) {
// Rudimentary clipping
if((x >= _width) || (y >= _height))
return;
if((x+w-1) >= _width)
w = _width-x;
setAddrWindow(x, y, x+w-1, y);
while (w--) {
writeData16(color);
}
}
//========================================================================//
//fast drawing of vertical line
void drawVerticalLine(int x, int y, int h, uint16_t color) {
if((x >= _width) || (y >= _height))
return;
if((y+h-1) >= _height)
h = _height-y;
setAddrWindow(x, y, x, y+h-1);
while (h--) {
writeData16(color);
}
}
//========================================================================//
void setRotation(int m) {
writeCommand (0x36); //set address mode
int rotation = m % 4; // can't be higher than 3
switch (rotation) {
case 0:
writeData8(0x0A);
_width = Width;
_height = Height;
break;
case 1:
writeData8(0x28);
_width = Height;
_height = Width;
break;
case 2:
writeData8(0x09);
_width = Width;
_height = Height;
break;
case 3:
writeData8(0x2B);
_width = Height;
_height = Width;
break;
}
}
//========================================================================//
void invertDisplay(boolean i) {
writeCommand(i ? 0x21 : 0x20);
}
//========================================================================//
void openWindow(int x0, int y0, int x1, int y1) {
setAddrWindow(x0, y0, x0 + x1 - 1, y0 + y1 - 1);
}
//========================================================================//
//writes a single 16b data to the data lines
void windowData(uint16_t c) {
writeData16(c);
}
//========================================================================//
//writes an array of data to the data lines
void windowData(uint16_t *c, int len) {
for (uint32_t i = 0; i < len; i++) {
writeData16(c[i]);
}
}
//========================================================================//
//bressenham's line algorithm
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) {
int16_t steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
_swap_int16_t(x0, y0);
_swap_int16_t(x1, y1);
}
if (x0 > x1) {
_swap_int16_t(x0, x1);
_swap_int16_t(y0, y1);
}
int16_t dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int16_t err = dx / 2;
int16_t ystep;
if (y0 < y1) {
ystep = 1;
} else {
ystep = -1;
}
for (; x0<=x1; x0++) {
if (steep) {
drawPixel(y0, x0, color);
} else {
drawPixel(x0, y0, color);
}
err -= dy;
if (err < 0) {
y0 += ystep;
err += dx;
}
}
}
//========================================================================//
// Draw a rectangle
void drawRectangle(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
drawHorizontalLine(x, y, w, color);
drawHorizontalLine(x, y+h-1, w, color);
drawVerticalLine(x, y, h, color);
drawVerticalLine(x+w-1, y, h, color);
}
//========================================================================//
//fills a rectanglar area os display with a color
void fillRectangle(int x, int y, int w, int h, uint16_t color) { //fillRectangle(0, 0, 480, 320, 6500);
if((x >= _width) || (y >= _height))
return;
if((x + w - 1) >= _width)
w = _width - x;
if((y + h - 1) >= _height)
h = _height - y;
setAddrWindow(x, y, x+w-1, y+h-1);
for(y=h*2; y>0; y--) {
for(x=w; x>0; x--) {
writeData16(color);
}
}
}
//========================================================================//
// Draw a circle outline
void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color) {
int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
int16_t x = 0;
int16_t y = r;
drawPixel(x0 , y0+r, color);
drawPixel(x0 , y0-r, color);
drawPixel(x0+r, y0 , color);
drawPixel(x0-r, y0 , color);
while (x<y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
drawPixel(x0 + x, y0 + y, color);
drawPixel(x0 - x, y0 + y, color);
drawPixel(x0 + x, y0 - y, color);
drawPixel(x0 - x, y0 - y, color);
drawPixel(x0 + y, y0 + x, color);
drawPixel(x0 - y, y0 + x, color);
drawPixel(x0 + y, y0 - x, color);
drawPixel(x0 - y, y0 - x, color);
}
}
//========================================================================//
void drawCircleHelper( int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color) {
int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
int16_t x = 0;
int16_t y = r;
while (x<y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if (cornername & 0x4) {
drawPixel(x0 + x, y0 + y, color);
drawPixel(x0 + y, y0 + x, color);
}
if (cornername & 0x2) {
drawPixel(x0 + x, y0 - y, color);
drawPixel(x0 + y, y0 - x, color);
}
if (cornername & 0x8) {
drawPixel(x0 - y, y0 + x, color);
drawPixel(x0 - x, y0 + y, color);
}
if (cornername & 0x1) {
drawPixel(x0 - y, y0 - x, color);
drawPixel(x0 - x, y0 - y, color);
}
}
}
//========================================================================//
void fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color) {
drawVerticalLine(x0, y0-r, 2*r+1, color);
fillCircleHelper(x0, y0, r, 3, 0, color);
}
//========================================================================//
// Used to do circles and roundrects
void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color) {
int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
int16_t x = 0;
int16_t y = r;
while (x<y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if (cornername & 0x1) {
drawVerticalLine(x0+x, y0-y, 2*y+1+delta, color);
drawVerticalLine(x0+y, y0-x, 2*x+1+delta, color);
}
if (cornername & 0x2) {
drawVerticalLine(x0-x, y0-y, 2*y+1+delta, color);
drawVerticalLine(x0-y, y0-x, 2*x+1+delta, color);
}
}
}
//========================================================================//
// Draw a rounded rectangle
void drawRoundRectangle(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color) {
// smarter version
drawHorizontalLine(x+r , y , w-2*r, color); // Top
drawHorizontalLine(x+r , y+h-1, w-2*r, color); // Bottom
drawVerticalLine(x , y+r , h-2*r, color); // Left
drawVerticalLine(x+w-1, y+r , h-2*r, color); // Right
// draw four corners
drawCircleHelper(x+r , y+r , r, 1, color);
drawCircleHelper(x+w-r-1, y+r , r, 2, color);
drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
drawCircleHelper(x+r , y+h-r-1, r, 8, color);
}
//========================================================================//
// Fill a rounded rectangle
void fillRoundRectangle(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color) {
// smarter version
fillRectangle(x+r, y, w-2*r, h, color);
// draw four corners
fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color);
}
//========================================================================//
// Draw a triangle
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) {
drawLine(x0, y0, x1, y1, color);
drawLine(x1, y1, x2, y2, color);
drawLine(x2, y2, x0, y0, color);
}
//========================================================================//
// Fill a triangle
void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) {
int16_t a, b, y, last;
// Sort coordinates by Y order (y2 >= y1 >= y0)
if (y0 > y1) {
_swap_int16_t(y0, y1); _swap_int16_t(x0, x1);
}
if (y1 > y2) {
_swap_int16_t(y2, y1); _swap_int16_t(x2, x1);
}
if (y0 > y1) {
_swap_int16_t(y0, y1); _swap_int16_t(x0, x1);
}
if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
a = b = x0;
if(x1 < a) a = x1;
else if(x1 > b) b = x1;
if(x2 < a) a = x2;
else if(x2 > b) b = x2;
drawHorizontalLine(a, y0, b-a+1, color);
return;
}
int16_t
dx01 = x1 - x0,
dy01 = y1 - y0,
dx02 = x2 - x0,
dy02 = y2 - y0,
dx12 = x2 - x1,
dy12 = y2 - y1;
int32_t
sa = 0,
sb = 0;
// For upper part of triangle, find scanline crossings for segments
// 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
// is included here (and second loop will be skipped, avoiding a /0
// error there), otherwise scanline y1 is skipped here and handled
// in the second loop...which also avoids a /0 error here if y0=y1
// (flat-topped triangle).
if(y1 == y2) last = y1; // Include y1 scanline
else last = y1-1; // Skip it
for(y=y0; y<=last; y++) {
a = x0 + sa / dy01;
b = x0 + sb / dy02;
sa += dx01;
sb += dx02;
/* longhand:
a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
*/
if(a > b) _swap_int16_t(a,b);
drawHorizontalLine(a, y, b-a+1, color);
}
// For lower part of triangle, find scanline crossings for segments
// 0-2 and 1-2. This loop is skipped if y1=y2.
sa = dx12 * (y - y1);
sb = dx02 * (y - y0);
for(; y<=y2; y++) {
a = x1 + sa / dy12;
b = x0 + sb / dy02;
sa += dx12;
sb += dx02;
/* longhand:
a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
*/
if(a > b) _swap_int16_t(a,b);
drawHorizontalLine(a, y, b-a+1, color);
}
}
//========================================================================//
//draws a single char to the display
void drawChar(char letter, int16_t x, int16_t y, uint16_t color, uint16_t bg, fontClass* selectedFont) {
// for(int i=0; i < selectedFont->fontHeight; i++) {
// drawHorizontalLine(x, y+i, selectedFont->fontWidth, bg); //clear the bg with bg color
// }
Serial.print("Drawing char : ");
Serial.println(letter);
char verticalBytes [selectedFont->verticalByteCount]; //for vertical bytes
for(int i=0; i < (selectedFont->fontArray[((letter - selectedFont->startChar) * selectedFont->charByteLength)]); i++) { //finds start of each set of vertical bytes
for(int k=1; k <= selectedFont->verticalByteCount; k++) {
verticalBytes [k-1] = selectedFont->fontArray[((letter - selectedFont->startChar) * selectedFont->charByteLength) + k + (i * selectedFont->verticalByteCount)]; //copy the set of vertical bytes
}
for(int j=0; j < selectedFont->verticalByteCount; j++) { //iterates though each set of vertical bytes
if(verticalBytes[j] != 0) { //don't display if a byte is zero
for(int m=0; m < 8; m++) { //iterates though each pixel of a byte
if((((unsigned int)(verticalBytes[j] >> m)) & 0x1) == 0x1) //check if a bit is 1
drawPixel(x+i, y + m+ (8*j), color); //if a bit is 1, then draw pixel with color
else drawPixel(x+i, y + m+ (8*j), bg); //draw pixel with bg if otherwise
// delay(100);
}
}
}
}
}
//========================================================================//
void printText(String S, int16_t x, int16_t y, uint16_t color, uint16_t bg, fontClass* selectedFont) {
char stringBuffer[S.length()+1];
S.toCharArray(stringBuffer, S.length()+1); //create a char array
for(int i=0; i < S.length(); i++) {
if(((stringBuffer[i] < selectedFont->startChar) || (stringBuffer[i] > selectedFont->endChar)) && (stringBuffer[i] != 32)) { //check for char validity
Serial.print("Illegal character found : ");
Serial.print((int)stringBuffer[i]);
Serial.print(" at ");
Serial.println(i);
Serial.println("String Length : " + S.length());
return;
}
}
int cumulatedLength = 0;
for(int i=0; i < S.length(); i++) {
if(i==0) {
if(stringBuffer[i] == 32) { //if the char is a space
cumulatedLength += 10; //width for space char
Serial.println("Writing space..");
}
else {
Serial.print("Writing first char : ");
Serial.println(stringBuffer[i]);
drawChar(stringBuffer[i], x, y, color, bg, selectedFont);
cumulatedLength += selectedFont->fontArray[((stringBuffer[i] - selectedFont->startChar) * selectedFont->charByteLength)] + 2;
}
}
else {
if(stringBuffer[i] == 32) { //if the char is a space
Serial.println("Writing space..");
cumulatedLength += 10; //width for space char
}
else {
Serial.print("Writing char : ");
Serial.println(stringBuffer[i]);
drawChar(stringBuffer[i], (x + cumulatedLength), y, color, bg, selectedFont);
cumulatedLength += selectedFont->fontArray[((stringBuffer[i] - selectedFont->startChar) * selectedFont->charByteLength)] + 2;
}
}
}
}
//========================================================================//
@pranavpp2112
Copy link

Wow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment