// **Project Link:** https://wokwi.com/projects/372034198045091841?gh=1
// Error message: Library not found: "TFT_eSPI@wokwi:e05dd5def8f952d3f56c5f0b6f6fcfffe80b6b01"
// #include "Adafruit_GFX.h"
#include "TFT_eSPI.h"
#include "Adafruit_ILI9341.h"
#include "SPI.h"
#include "Chewy_Regular_16.h"
#include "bitmap.h"
#define TFT_DC 2
#define TFT_CS 15
#define TFT_MOSI 23
#define TFT_SCLK 18
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite img= TFT_eSprite(&tft);
#define DEG2RAD 0.0174532925
#define background1 0x29CC
int lastCursor = 0;
int posCursor = 0;
#define ROT_A 25
#define ROT_B 26
#define ROT_SW 27
int crntCLK;
int lastCLK;
int SWstate = 0;
void drawSplashScreen(void)
{
img.fillSprite(TFT_WHITE);
Serial.println("splash screen!");
img.drawBitmap(125, 2, epd_bitmap_polytronLogo[0], 73, 112, TFT_WHITE, TFT_RED);
img.drawBitmap(135, 36, epd_bitmap_polytronText[0], 246, 32, TFT_WHITE, TFT_BLACK);
}
void drawPrev(uint8_t posX, uint8_t posY, uint8_t selected) {
if(selected)
{
// img.fillRect(posX, posY, 46, 37, TFT_BLACK);
// img.fillRect(posX+3, posY+3, 8, 31, TFT_ORANGE);
// img.fillTriangle(posX+26, posY+3, posX+26, posY+33, posX+11, posY+18, TFT_ORANGE);
// img.fillTriangle(posX+42, posY+3, posX+42, posY+33, posX+27, posY+18, TFT_ORANGE);
img.fillRect(posX, posY, 58, 33, TFT_BLACK);
img.fillRect(posX+11, posY+3, 6, 27, TFT_ORANGE);
img.fillTriangle(posX+30, posY+3, posX+30, posY+29, posX+17, posY+16, TFT_ORANGE);
img.fillTriangle(posX+44, posY+3, posX+44, posY+29, posX+31, posY+16, TFT_ORANGE);
// img.fillRect(posX+3, posY+3, 6, 25, TFT_RED);
// img.fillTriangle(posX+21, posY+3, posX+21, posY+27, posX+9, posY+15, TFT_RED);
// img.fillTriangle(posX+34, posY+3, posX+34, posY+27, posX+22, posY+15, TFT_RED);
// img.drawRect(posX, posY, 38, 31, TFT_RED);
Serial.println("prev Selected!");
}
else
{
// img.drawRect(posX, posY, 46, 37, TFT_BLACK);
// img.fillRect(posX+3, posY+3, 8, 31, TFT_ORANGE);
// img.fillTriangle(posX+26, posY+3, posX+26, posY+33, posX+11, posY+18, TFT_ORANGE);
// img.fillTriangle(posX+42, posY+3, posX+42, posY+33, posX+27, posY+18, TFT_ORANGE);
img.drawRect(posX, posY, 58, 33, TFT_BLACK);
img.fillRect(posX+11, posY+3, 6, 27, TFT_ORANGE);
img.fillTriangle(posX+30, posY+3, posX+30, posY+29, posX+17, posY+16, TFT_ORANGE);
img.fillTriangle(posX+44, posY+3, posX+44, posY+29, posX+31, posY+16, TFT_ORANGE);
// img.drawRect(posX+3, posY+3, 6, 25, TFT_ORANGE);
// img.drawTriangle(posX+21, posY+3, posX+21, posY+27, posX+9, posY+15, TFT_ORANGE);
// img.drawTriangle(posX+34, posY+3, posX+34, posY+27, posX+22, posY+15, TFT_ORANGE);
// img.drawRect(posX, posY, 38, 31, TFT_ORANGE);
Serial.println("prev unSelected!");
}
img.setTextSize(2);
img.setTextColor(TFT_BLACK);
// img.drawString("PREV", posX, posY+39);
img.drawString("PREV", posX+6, posY+39);
}
void drawPlayPause(uint8_t posX, uint8_t posY, uint8_t selected) {
if(selected)
{
// img.fillRect(posX+56, posY, 46, 37, TFT_BLACK);
// img.fillTriangle(posX+59, posY+3, posX+59, posY+33, posX+74, posY+18, TFT_ORANGE);
// img.fillRect(posX+79, posY+3, 8, 31, TFT_ORANGE);
// img.fillRect(posX+91, posY+3, 8, 31, TFT_ORANGE);
img.fillRect(posX+68, posY, 58, 33, TFT_BLACK);
img.fillTriangle(posX+81, posY+3, posX+81, posY+29, posX+94, posY+16, TFT_ORANGE);
img.fillRect(posX+98, posY+3, 6, 27, TFT_ORANGE);
img.fillRect(posX+107, posY+3, 6, 27, TFT_ORANGE);
// img.fillTriangle(posX+48, posY+3, posX+48, posY+27, posX+60, posY+15, TFT_RED);
// img.fillRect(posX+66, posY+3, 6, 25, TFT_RED);
// img.fillRect(posX+76, posY+3, 6, 25, TFT_RED);
// img.drawRect(posX+45, posY, 38, 31, TFT_RED);
Serial.println("playPause Selected!");
}
else
{
// img.drawRect(posX+56, posY, 46, 37, TFT_BLACK);
// img.fillTriangle(posX+59, posY+3, posX+59, posY+33, posX+74, posY+18, TFT_ORANGE);
// img.fillRect(posX+79, posY+3, 8, 31, TFT_ORANGE);
// img.fillRect(posX+91, posY+3, 8, 31, TFT_ORANGE);
img.drawRect(posX+68, posY, 58, 33, TFT_BLACK);
img.fillTriangle(posX+81, posY+3, posX+81, posY+29, posX+94, posY+16, TFT_ORANGE);
img.fillRect(posX+98, posY+3, 6, 27, TFT_ORANGE);
img.fillRect(posX+107, posY+3, 6, 27, TFT_ORANGE);
// img.drawTriangle(posX+48, posY+3, posX+48, posY+27, posX+60, posY+15, TFT_ORANGE);
// img.drawRect(posX+66, posY+3, 6, 25, TFT_ORANGE);
// img.drawRect(posX+76, posY+3, 6, 25, TFT_ORANGE);
// img.drawRect(posX+45, posY, 38, 31, TFT_ORANGE);
Serial.println("playPause unSelected!");
}
img.setTextSize(2);
img.setTextColor(TFT_BLACK);
// img.drawString("PLAY", posX+56, posY+39);
img.drawString("PLAY", posX+74, posY+39);
// img.drawString("PAUSE", posX+68, posY+39);
}
void drawNext(uint8_t posX, uint8_t posY, uint8_t selected) {
if(selected)
{
// img.fillRect(posX+112, posY, 46, 37, TFT_BLACK);
// img.fillTriangle(posX+115, posY+3, posX+115, posY+33, posX+130, posY+18, TFT_ORANGE);
// img.fillTriangle(posX+131, posY+3, posX+131, posY+33, posX+146, posY+18, TFT_ORANGE);
// img.fillRect(posX+147, posY+3, 8, 31, TFT_ORANGE);
img.fillRect(posX+136, posY, 58, 33, TFT_BLACK);
img.fillTriangle(posX+148, posY+3, posX+148, posY+29, posX+161, posY+16, TFT_ORANGE);
img.fillTriangle(posX+162, posY+3, posX+162, posY+29, posX+179, posY+16, TFT_ORANGE);
img.fillRect(posX+176, posY+3, 6, 27, TFT_ORANGE);
// img.fillTriangle(posX+95, posY+3, posX+95, posY+27, posX+107, posY+15, TFT_RED);
// img.fillTriangle(posX+108, posY+3, posX+108, posY+27, posX+120, posY+15, TFT_RED);
// img.fillRect(posX+121, posY+3, 6, 25, TFT_RED);
// img.drawRect(posX+92, posY, 38, 31, TFT_RED);
Serial.println("next Selected!");
}
else
{
// img.drawRect(posX+112, posY, 46, 37, TFT_BLACK);
// img.fillTriangle(posX+115, posY+3, posX+115, posY+33, posX+130, posY+18, TFT_ORANGE);
// img.fillTriangle(posX+131, posY+3, posX+131, posY+33, posX+146, posY+18, TFT_ORANGE);
// img.fillRect(posX+147, posY+3, 8, 31, TFT_ORANGE);
img.drawRect(posX+136, posY, 58, 33, TFT_BLACK);
img.fillTriangle(posX+148, posY+3, posX+148, posY+29, posX+161, posY+16, TFT_ORANGE);
img.fillTriangle(posX+162, posY+3, posX+162, posY+29, posX+179, posY+16, TFT_ORANGE);
img.fillRect(posX+176, posY+3, 6, 27, TFT_ORANGE);
// img.drawTriangle(posX+95, posY+3, posX+95, posY+27, posX+107, posY+15, TFT_ORANGE);
// img.drawTriangle(posX+108, posY+3, posX+108, posY+27, posX+120, posY+15, TFT_ORANGE);
// img.drawRect(posX+121, posY+3, 6, 25, TFT_ORANGE);
// img.drawRect(posX+92, posY, 38, 31, TFT_ORANGE);
Serial.println("next unSelected!");
}
img.setTextSize(2);
img.setTextColor(TFT_BLACK);
// img.drawString("NEXT", posX+112, posY+39);
img.drawString("NEXT", posX+142, posY+39);
}
void drawPlayControl(uint8_t posX, uint8_t posY, uint8_t selected)
{
switch(selected)
{
case 0:
drawPrev(posX, posY, 1);
drawPlayPause(posX, posY, 0);
drawNext(posX, posY, 0);
break;
case 1:
drawPrev(posX, posY, 0);
drawPlayPause(posX, posY, 1);
drawNext(posX, posY, 0);
break;
case 2:
drawPrev(posX, posY, 0);
drawPlayPause(posX, posY, 0);
drawNext(posX, posY, 1);
break;
}
}
// #########################################################################
// Draw a circular or elliptical arc with a defined thickness
// #########################################################################
// x,y == coords of centre of arc
// start_angle = 0 - 359
// seg_count = number of 6 degree segments to draw (60 => 360 degree arc)
// rx = x axis outer radius
// ry = y axis outer radius
// w = width (thickness) of arc in pixels
// colour = 16-bit colour value
// Note if rx and ry are the same then an arc of a circle is drawn
void fillArc(int x, int y, int start_angle, int seg_count, int rx, int ry, int w, unsigned int colour)
{
byte seg = 6; // Segments are 3 degrees wide = 120 segments for 360 degrees
byte inc = 6; // Draw segments every 3 degrees, increase to 6 for segmented ring
// Calculate first pair of coordinates for segment start
float sx = cos((start_angle - 90) * DEG2RAD);
float sy = sin((start_angle - 90) * DEG2RAD);
uint16_t x0 = sx * (rx - w) + x;
uint16_t y0 = sy * (ry - w) + y;
uint16_t x1 = sx * rx + x;
uint16_t y1 = sy * ry + y;
// Draw colour blocks every inc degrees
for (int i = start_angle; i < start_angle + seg * seg_count; i += inc) {
// Calculate pair of coordinates for segment end
float sx2 = cos((i + seg - 90) * DEG2RAD);
float sy2 = sin((i + seg - 90) * DEG2RAD);
int x2 = sx2 * (rx - w) + x;
int y2 = sy2 * (ry - w) + y;
int x3 = sx2 * rx + x;
int y3 = sy2 * ry + y;
img.fillTriangle(x0, y0, x1, y1, x2, y2, colour);
img.fillTriangle(x1, y1, x2, y2, x3, y3, colour);
// Copy segment end to segment start for next segment
x0 = x2;
y0 = y2;
x1 = x3;
y1 = y3;
}
}
void drawVolume(uint8_t vol, uint8_t posX, uint8_t posY)
{
char mVol[10];
sprintf(mVol, "%d", vol);
#if 0
// img.drawSmoothArc(posX+52, posY+30, 8, 6, 0, 180, TFT_BLACK, TFT_WHITE, true);
fillArc(posX+52, posY+30, 15, 24, 8, 7, 3, TFT_BLACK);
fillArc(posX+56, posY+30, 15, 24, 12, 14, 3, TFT_BLACK);
fillArc(posX+60, posY+30, 15, 24, 16, 21, 3, TFT_BLACK);
fillArc(posX+64, posY+30, 15, 24, 20, 28, 3, TFT_BLACK);
// fillArc(posX+68, posY+30, 15, 24, 24, 35, 3, TFT_BLACK);
img.fillTriangle(posX+45, posY, posX+45, posY+60, posX+15, posY+30, TFT_BLACK);
img.fillRoundRect(posX, posY+13, 36, 35, 5, TFT_BLACK);
img.setTextSize(3);
img.setTextColor(TFT_WHITE);
img.drawString(mVol, posX+6, posY+20);
#else
img.drawBitmap(posX, posY, epd_bitmap_allArray[0], 44, 72, TFT_WHITE, TFT_BLACK);
if(vol == 0)
{
img.drawBitmap(posX+49, posY, epd_bitmap_allArray[1], 44, 72, TFT_WHITE, TFT_BLACK);
}
else if(vol > 0 && vol < 11)
{
img.drawBitmap(posX+47, posY, epd_bitmap_allArray[2], 44, 72, TFT_WHITE, TFT_BLACK);
}
else if(vol > 10 && vol < 21)
{
img.drawBitmap(posX+47, posY, epd_bitmap_allArray[3], 44, 72, TFT_WHITE, TFT_BLACK);
}
else if(vol > 20 && vol < 31)
{
img.drawBitmap(posX+47, posY, epd_bitmap_allArray[4], 44, 72, TFT_WHITE, TFT_BLACK);
}
img.setCursor(posX+6, posY+26);
img.setTextColor(TFT_WHITE);
img.setTextSize(3);
img.println(mVol);
#endif
}
void drawBattery(uint8_t bat, uint8_t posX, uint8_t posY)
{
if(bat >= 0 && bat < 10)
{
img.drawBitmap(posX, posY, batt_allArray[1], 34, 20, TFT_WHITE, TFT_BLACK);
}
else if(bat >=10 && bat < 20)
{
img.drawBitmap(posX, posY, batt_allArray[2], 34, 20, TFT_WHITE, TFT_BLACK);
}
else if(bat >=20 && bat < 30)
{
img.drawBitmap(posX, posY, batt_allArray[3], 34, 20, TFT_WHITE, TFT_BLACK);
}
else if(bat >=30 && bat < 40)
{
img.drawBitmap(posX, posY, batt_allArray[4], 34, 20, TFT_WHITE, TFT_BLACK);
}
else if(bat >=40 && bat < 50)
{
img.drawBitmap(posX, posY, batt_allArray[5], 34, 20, TFT_WHITE, TFT_BLACK);
}
else if(bat >=50 && bat < 60)
{
img.drawBitmap(posX, posY, batt_allArray[6], 34, 20, TFT_WHITE, TFT_BLACK);
}
else if(bat >=60 && bat < 70)
{
img.drawBitmap(posX, posY, batt_allArray[7], 34, 20, TFT_WHITE, TFT_BLACK);
}
else if(bat >=70 && bat < 80)
{
img.drawBitmap(posX, posY, batt_allArray[8], 34, 20, TFT_WHITE, TFT_BLACK);
}
else if(bat >=80 && bat < 90)
{
img.drawBitmap(posX, posY, batt_allArray[9], 34, 20, TFT_WHITE, TFT_BLACK);
}
else if(bat >=90 && bat <= 100)
{
img.drawBitmap(posX, posY, batt_allArray[10], 34, 20, TFT_WHITE, TFT_BLACK);
}
else if(bat == 0xFF)
{
img.drawBitmap(posX, posY, batt_allArray[0], 34, 20, TFT_WHITE, TFT_BLACK);
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Hello, ESP32!");
pinMode(ROT_A, INPUT);
pinMode(ROT_B, INPUT);
pinMode(ROT_SW, INPUT_PULLUP);
lastCLK = digitalRead(ROT_A);
tft.init();
tft.writecommand(0x11);
tft.setRotation(1);
tft.fillScreen(background1);
img.createSprite(320, 170);
drawSplashScreen();
delay(3000);
img.fillSprite(TFT_WHITE);
// drawPlayControl(62, 116, posCursor);
// drawVolume(39, 125, 30);
drawBattery(posCursor, 180, 0);
// img.drawBitmap(0, 0, epd_bitmap_batere[0], 35, 20, TFT_WHITE, TFT_BLACK);
// img.drawBitmap(40, 0, epd_bitmap_battAll[0], 48, 26, TFT_WHITE, TFT_BLACK);
drawPlayControl(62, 116, 0);
drawVolume(39, 0, 30);
img.pushSprite(0, 0);
}
void readEncoder(void)
{
crntCLK = digitalRead(ROT_A);
SWstate = digitalRead(ROT_SW);
if(crntCLK != lastCLK)
{
lastCLK = crntCLK;
int dtValue = digitalRead(ROT_B);
if(crntCLK == LOW && dtValue == HIGH)
{
if(posCursor > 0) posCursor--;
Serial.print("Rotated clockwise ⏩ Pos:");
Serial.println(posCursor);
}
if(crntCLK == LOW && dtValue == LOW)
{
if(posCursor < 100) posCursor++;
Serial.print("Rotated counterclockwise ⏪ Pos:");
Serial.println(posCursor);
}
}
}
void loop() {
// put your main code here, to run repeatedly:
readEncoder();
if(lastCursor != posCursor)
{
img.fillSprite(TFT_WHITE);
// drawPlayControl(62, 116, posCursor);
// drawVolume(39, 125, 30);
drawPlayControl(62, 116, 0);
drawVolume(39, 0, 30);
drawBattery(posCursor, 180, 0);
lastCursor = posCursor;
img.pushSprite(0, 0);
}
}