From d0508c6543e1b482f10ca71e872a53a98b2caa16 Mon Sep 17 00:00:00 2001 From: angoosh Date: Fri, 15 Sep 2023 00:42:41 +0200 Subject: [PATCH] added arduino software for the lsd --- Software/SGA_LSD/SGA_LSD.ino | 237 +++++++++++++++++++ Software/SGA_LSD/data/stargate-alteran30.vlw | Bin 0 -> 18895 bytes 2 files changed, 237 insertions(+) create mode 100644 Software/SGA_LSD/SGA_LSD.ino create mode 100644 Software/SGA_LSD/data/stargate-alteran30.vlw diff --git a/Software/SGA_LSD/SGA_LSD.ino b/Software/SGA_LSD/SGA_LSD.ino new file mode 100644 index 0000000..9450c65 --- /dev/null +++ b/Software/SGA_LSD/SGA_LSD.ino @@ -0,0 +1,237 @@ +#include // Hardware-specific library +#include +#include +#include +#include +#include "Wire.h" + +// TFT resolution +#define TFT_DISPLAY_RESOLUTION_X 320 +#define TFT_DISPLAY_RESOLUTION_Y 480 +#define CENTRE_Y TFT_DISPLAY_RESOLUTION_Y/2 + +// TFT SPI +#define TFT_LED 33 // TFT backlight pin +#define TFT_LED_PWM 100 // dutyCycle 0-255 last minimum was 15 + +#define ALTERAN "stargate-alteran30" + +#define TFT_GREY 0x7BEF +#define TFT_BG_COLOR 0xDA3E +#define TFT_POLY 0xC85D + +#define BATTERY_ADC 34 // Battery voltage mesurement +#define deviderRatio 1.7693877551 // Voltage devider ratio on ADC pin 1MOhm + 1.3MOhm + + +ESP32AnalogRead adc; +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library with default width and height + +void draw_background(){ + uint8_t hexagon_size = 14; //length of horizontal line in px + int hex_pos_y = 12; + for(int c = 0; c < 20; c++){ + for(int r = 0; r < 8; r++){ + int offset = r * hexagon_size * 3; + tft.drawLine(offset, (hex_pos_y - 12), (hexagon_size / 2) + offset, hex_pos_y, TFT_BG_COLOR); + tft.drawLine(offset, (hex_pos_y + 12), (hexagon_size / 2) + offset, hex_pos_y, TFT_BG_COLOR); + tft.drawLine(offset + (hexagon_size / 2), hex_pos_y, hexagon_size + offset + (hexagon_size / 2), hex_pos_y, TFT_BG_COLOR); + tft.drawLine(hexagon_size + offset + (hexagon_size / 2), hex_pos_y, (hexagon_size * 2) + offset, (hex_pos_y - 12), TFT_BG_COLOR); + tft.drawLine(hexagon_size + offset + (hexagon_size / 2), hex_pos_y, (hexagon_size * 2) + offset, (hex_pos_y + 12), TFT_BG_COLOR); + tft.drawLine((hexagon_size * 2) + offset, (hex_pos_y - 12), (hexagon_size * 3) + offset, (hex_pos_y - 12), TFT_BG_COLOR); + } + hex_pos_y += 24; + } +} + +void draw_life_sign(int x, int y, int create){ + if(create){ + tft.fillCircle(x, y, 7, TFT_CYAN); + tft.drawCircle(x, y, 10, TFT_WHITE); + } + else{ + tft.fillCircle(x, y, 7, TFT_BLACK); + tft.drawCircle(x, y, 10, TFT_BLACK); + } +} + +int Battery_Get_Percent(float voltage){ + float map[21] = {4.2,4.15,4.11,4.08,4.02,3.98,3.95,3.91,3.87,3.85,3.84,3.82,3.8,3.79,3.77,3.75,3.73,3.71,3.69,3.61,3.27}; + + for(int i = 0; i < 21; i++){ + if(voltage > map[i]){ + if(i == 0){ + return 100; + } + else{ + float delta = map[i - 1] - map[i]; + float voltage_step = delta / 5.0; + float voltages[6] = {map[i], map[i] + voltage_step, map[i] + voltage_step * 2.0, map[i] + voltage_step * 3.0, map[i] + voltage_step * 4.0, map[i - 1]}; + int smallest_index = 0; + + for(int j = 0; j < 6; j++){ + if(voltage > voltages[j]){ + smallest_index = j; + } + else{ + break; + } + } + + return 100 - i*5 + smallest_index; + } + } + else; + } + return 0; +} + +void battery_status(uint8_t state){ + int rect_size = 9; + + float voltage = adc.readVoltage() * deviderRatio; + int percent = Battery_Get_Percent(voltage); + int bars = (percent / 10) + 0.5; + + int polygon_points[12][2] = { + {TFT_DISPLAY_RESOLUTION_X - 40, TFT_DISPLAY_RESOLUTION_Y / 2}, + {TFT_DISPLAY_RESOLUTION_X - 40, TFT_DISPLAY_RESOLUTION_Y - 70}, + {TFT_DISPLAY_RESOLUTION_X - 80, TFT_DISPLAY_RESOLUTION_Y - 70}, + {TFT_DISPLAY_RESOLUTION_X - 95, TFT_DISPLAY_RESOLUTION_Y - 55}, + {TFT_DISPLAY_RESOLUTION_X - 140, TFT_DISPLAY_RESOLUTION_Y - 55}, + {TFT_DISPLAY_RESOLUTION_X - 155, TFT_DISPLAY_RESOLUTION_Y - 70}, + {TFT_DISPLAY_RESOLUTION_X - 180, TFT_DISPLAY_RESOLUTION_Y - 70}, + {TFT_DISPLAY_RESOLUTION_X - 180, TFT_DISPLAY_RESOLUTION_Y - 30}, + {TFT_DISPLAY_RESOLUTION_X - 165, TFT_DISPLAY_RESOLUTION_Y - 15}, + {TFT_DISPLAY_RESOLUTION_X - 60, TFT_DISPLAY_RESOLUTION_Y - 15}, + {TFT_DISPLAY_RESOLUTION_X - 10, TFT_DISPLAY_RESOLUTION_Y - 65}, + {TFT_DISPLAY_RESOLUTION_X - 10, TFT_DISPLAY_RESOLUTION_Y / 2 + 20} + }; + if(state == 0){ + tft.fillTriangle(polygon_points[0][0], polygon_points[0][1], polygon_points[1][0], polygon_points[1][1], polygon_points[11][0], polygon_points[11][1], TFT_POLY); + tft.fillTriangle(polygon_points[11][0], polygon_points[11][1], polygon_points[10][0], polygon_points[10][1], polygon_points[1][0], polygon_points[1][1], TFT_POLY); + tft.fillTriangle(polygon_points[10][0], polygon_points[10][1], polygon_points[1][0], polygon_points[1][1], polygon_points[9][0], polygon_points[9][1], TFT_POLY); + tft.fillTriangle(polygon_points[2][0], polygon_points[2][1], polygon_points[1][0], polygon_points[1][1], polygon_points[9][0], polygon_points[9][1], TFT_POLY); + tft.fillTriangle(polygon_points[2][0], polygon_points[2][1], polygon_points[3][0], polygon_points[3][1], polygon_points[9][0], polygon_points[9][1], TFT_POLY); + tft.fillTriangle(polygon_points[3][0], polygon_points[3][1], polygon_points[9][0], polygon_points[9][1], polygon_points[8][0], polygon_points[8][1], TFT_POLY); + tft.fillTriangle(polygon_points[4][0], polygon_points[4][1], polygon_points[3][0], polygon_points[3][1], polygon_points[8][0], polygon_points[8][1], TFT_POLY); + tft.fillTriangle(polygon_points[4][0], polygon_points[4][1], polygon_points[5][0], polygon_points[5][1], polygon_points[8][0], polygon_points[8][1], TFT_POLY); + tft.fillTriangle(polygon_points[5][0], polygon_points[5][1], polygon_points[7][0], polygon_points[7][1], polygon_points[8][0], polygon_points[8][1], TFT_POLY); + tft.fillTriangle(polygon_points[5][0], polygon_points[5][1], polygon_points[7][0], polygon_points[7][1], polygon_points[6][0], polygon_points[6][1], TFT_POLY); + } + int bars_empty = 10 - bars; + + tft.fillRect(TFT_DISPLAY_RESOLUTION_X - 35, ((TFT_DISPLAY_RESOLUTION_Y / 2 + 25)), 20, 140, TFT_POLY); + for(int i = 0; i < 10; i++){ + if(bars_empty == 0){ + tft.fillRect(TFT_DISPLAY_RESOLUTION_X - 35, ((TFT_DISPLAY_RESOLUTION_Y / 2 + 25) + (i * rect_size * 1.5)), 20, rect_size, TFT_WHITE); + } + else{ + tft.drawRect(TFT_DISPLAY_RESOLUTION_X - 35, ((TFT_DISPLAY_RESOLUTION_Y / 2 + 25) + (i * rect_size * 1.5)), 20, rect_size, TFT_WHITE); + bars_empty --; + } + } + if(state == 0){ + for(int i = 0; i < 12; i++){ + if(i < 11){ + tft.drawLine(polygon_points[i][0], polygon_points[i][1], polygon_points[i+1][0], polygon_points[i+1][1], TFT_CYAN); + } + else{ + tft.drawLine(polygon_points[i][0], polygon_points[i][1], polygon_points[0][0], polygon_points[0][1], TFT_CYAN); + } + } + + tft.loadFont(ALTERAN); + tft.setCursor(TFT_DISPLAY_RESOLUTION_X - 155, TFT_DISPLAY_RESOLUTION_Y - 48); + tft.setTextColor(TFT_WHITE,TFT_BLACK); + tft.print("BATTERY"); + } +} + +void draw_cosmetic_graphics(){ + int n_o_diamonds = 2; + int points[n_o_diamonds][4][2] = { + {{120,430},{90,430},{70,450},{100,450}}, + {{80,430},{50,430},{30,450},{60,450}}, + }; + + + for(int s = 0; s < n_o_diamonds; s++){ + tft.fillTriangle(points[s][0][0], points[s][0][1], points[s][1][0], points[s][1][1], points[s][2][0], points[s][2][1], TFT_POLY); + tft.fillTriangle(points[s][0][0], points[s][0][1], points[s][2][0], points[s][2][1], points[s][3][0], points[s][3][1], TFT_POLY); + for(int i = 0; i < 4; i++){ + if(i < 3){ + tft.drawLine(points[s][i][0], points[s][i][1], points[s][i+1][0], points[s][i+1][1], TFT_CYAN); + } + else{ + tft.drawLine(points[s][i][0], points[s][i][1], points[s][0][0], points[s][0][1], TFT_CYAN); + } + } + } +} + +void setup() { + Serial.begin(115200); + // put your setup code here, to run once: + Wire.begin(); + adc.attach(BATTERY_ADC); + + ledcSetup(1, 5000, 8); // ledChannel, freq, resolution + ledcAttachPin(TFT_LED, 1); // ledPin, ledChannel + ledcWrite(1, TFT_LED_PWM); // dutyCycle 0-255 + + // Setup the LCD + tft.init(); + tft.setRotation(2); + tft.fillScreen(TFT_BLACK); + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nSPIFFS available!"); + + // ESP32 will crash if any of the fonts are missing + bool font_missing = false; + if (SPIFFS.exists("/stargate-alteran30.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\r\nFont missing in SPIFFS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\r\nFonts found OK."); + + draw_background(); + draw_cosmetic_graphics(); + + battery_status(0); + + tft.setTextColor(TFT_WHITE,TFT_BLACK); + tft.loadFont(ALTERAN); // Must load the font first + +/* for(int i = 0; i < 30; i++){ + draw_life_sign(120 + i*3, 200 + i*5, 1); + tft.setCursor(20, 20); // Set cursor at top left of screen + tft.println("WHOAREYOU"); // println moves cursor down for a new line + delay(500); + draw_life_sign(120 + i*3, 200 + i*5, 0); + draw_background(); + }*/ + tft.setCursor(20, 60); + tft.print("uptime"); +} + +int uptime = 0; +void loop() { + // put your main code here, to run repeatedly: + tft.setCursor(120, 60); + tft.setTextColor(TFT_WHITE,TFT_BLACK); + tft.print(uptime); + delay(1000); + tft.setCursor(120, 60); + tft.setTextColor(TFT_BLACK,TFT_BLACK); + tft.print(uptime); + uptime ++; + battery_status(1); +} diff --git a/Software/SGA_LSD/data/stargate-alteran30.vlw b/Software/SGA_LSD/data/stargate-alteran30.vlw new file mode 100644 index 0000000000000000000000000000000000000000..b5af8710922e2fc568bd98ba1db1a72d624c2664 GIT binary patch literal 18895 zcmeHN&5{&F5N@~_p#ffrFoM`KCqNVoA`DSPK~RAKS8t=PtFW%PEckPp2jDUGfD!W& zdf^rJ&TBvnUv_0r)<{=wS7x!>yL3f#SF&GcR_0fk)zwo}RrO(2Rd3-sj*Hsy*=+V4 z{YhN!;3Dh@t_Fu#ox(-fo4EduomQ}S73_?Hy{BOBE7(~DJEveDDA)zYh?k?dVqQL0 zuum9keX3xWl<_`O^gdUx%L;Zy!MF-QpQ_V^nO;b zUli<)g571TEw9%Uy&6#?mO2EE*m#*V||`qRo`E zrClTh#+CXIRJYOz4Q%kBtbqZ#N??Q9L1Cj4W$A~UG_ZQwJ|TE$w{k;wqzh`UG8h+K zWu$$@2E_q~IUJ9aU}WF1k%*(rpS!X#nGZKIinr^xO7vQxIc^q3hiG&sQY-3NWY;Ld zoqq${#Lh=vAUtpSJH%l1PV}jM|8125W75q@*@ddi{rtixy;BZAM z-7A72F8%XN5xU%?0@hqE>KPj&cl@G1HdrW~1fcm@Fq(EvMTG*KPUaT-_CqUkD^nfK`W}cv)XXT-uOiGg#nvM+^2``p zq!uR3R$mLcOi+FYa+zq46l%Rd9GzB{g~(r>Mn0LMQDC(ZVcoMY`kPWeHkXc4Ps{ly)3&Hy&`lfaN=%S5VK3 z#uIOWJTha#Ng827xW@MLR5x?w4nx#J!xU|;WRLiAK0LKo%!~g z9DZdk$rzF~;KXnmIG+KT8Go5<2NPwx+SB1Qu%;GV@GP}Sm`Xy2)4-72vOqMIUrFf? zr-31n(jV=#H7R){jFE=Zz&Qt=EmqN;xo1}oUGc>h5t6K>PK|%%wGmx9t@)Y61JMFu z^dVA%F&wlEr-6ZTBnzjAe9*~+uWFX<+=L>}&F| zKao^6ibNC};T)!a^+Ak0GsYIFAtq;qb8RwL`5h=7P6OL#A)idqD6@i#y?m*R2guIh wG*I71^3?d&rgEo&)v=qK