Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "TFT_eSPI.h"
- #include "U8g2_for_TFT_eSPI.h"
- #include <Preferences.h>
- #include "SPI.h"
- #include "SD.h"
- #include "FS.h"
- #include "Wire.h"
- #include <NMEAGPS.h>
- #include <GPSport.h>
- // ------- [ GPS ] -------
- NMEAGPS gps; // This parses the GPS characters
- gps_fix fix; // This holds on to the latest values
- int UTCOffset = 2;
- int headingLookupTable[8][2];
- const String markers[8] = {
- "S",
- "SE",
- "E",
- "NE",
- "N",
- "NW",
- "W",
- "SW"
- };
- enum GPSspeed { HZ_1,
- HZ_2,
- HZ_4,
- HZ_5,
- HZ_10 };
- const String GPScommands[5][2] = {
- { "$PCAS02,1000*2E", "1HZ" }, // 1HZ - 0
- { "$PCAS02,500*1A", "2HZ" }, // 2HZ - 1
- { "$PCAS02,250*18", "4HZ" }, // 4HZ - 2
- { "$PCAS02,200*1D", "5HZ" }, // 5HZ - 3
- { "$PCAS02,100*1E", "10HZ" } //10 HZ - 4
- };
- #define SAT_RADIUS 5
- #define OFFSET 180
- // ------- [ TEXT ] -------
- #define fontBig u8g2_font_fub49_tn // 61px
- #define fontMid u8g2_font_crox5tb_tf // 16px
- #define fontSml u8g2_font_helvR14_tr // 15px
- #define fontxSml u8g2_font_6x13_tf // ??px
- #define fontSpecial u8g2_font_gb24st_t_3 // 13px
- #define paddingL 5
- #define paddingR 10
- #define clearPaddingL 4
- #define clearPaddingR 5
- enum directions { LEFT, RIGHT, CENTER, CENTER_NO }; // CENTER_NO doesn't have 15px offset to account for sidebar
- // ------- [ IP5306 ] -------
- #define chargeCurrent 10 // 1050 mA charging current
- #define IP5306_REG_CHG_4 0x24
- #define IP5306_REG_READ_0 0x70
- #define IP5306_REG_READ_1 0x71
- #define IP5306_REG_READ_4 0x78
- // ------- [ BUTTONS ] -------
- TaskHandle_t handleButtons;
- int clicked = -1;
- unsigned long lastPressed = 0;
- // ------- [ SCREEN ] -------
- TFT_eSPI tft = TFT_eSPI();
- U8g2_for_TFT_eSPI u8f;
- TFT_eSprite spr = TFT_eSprite(&tft);
- bool refreshScreen = true;
- const int refreshRate = 100; // global refreshrate, ms
- int screenWidth, screenHeight;
- unsigned long lastRefresh;
- bool screenOn = true;
- byte mainScreenIndex = 0;
- const byte numScreens = 5;
- int pallete = 2;
- const int numPalletes = 7;
- // [0]UI, [1]ACCENT, [2]TEXT
- const uint16_t palletes[numPalletes][3] = {
- // UI ACCENT TEXT
- {TFT_DARKCYAN, TFT_GREEN, TFT_CYAN}, // OCEAN
- {TFT_BROWN, TFT_GOLD, TFT_WHITE}, // BEAR
- {TFT_LIGHTGREY, TFT_DARKGREY, TFT_LIGHTGREY}, // DARK
- {TFT_DARKGREY, TFT_DARKGREY, TFT_DARKGREY}, // DARKER
- {0x0260, 0x05E0, TFT_WHITE}, // <3
- {TFT_SKYBLUE, TFT_BLUE, TFT_NAVY}, // BLU
- {0x268E, 0x9EB4, TFT_WHITE} // MINT
- };
- const String palleteNames[numPalletes] = {
- "Ocean",
- "Bear",
- "Dark",
- "Darker",
- "<3",
- "Blu",
- "Mint"
- };
- const uint16_t barColors[6] = {
- TFT_DARKGREEN,
- TFT_GREEN,
- TFT_YELLOW,
- TFT_ORANGE,
- TFT_RED,
- };
- const int graphSize = 600;
- const int gRefreshRate = 100;
- bool runSettings = false;
- bool bootRdy = false;
- Preferences preferences;
- #include "settingsArray.h"
- // this is where core 0 stores all the GPS data
- struct GPS{
- int fixStatus;
- float lat;
- float lon;
- float alt;
- long latP;
- long lonP;
- long lonDMS;
- long latDMS;
- // int latErr;
- // int lonErr;
- // int altErr;
- float spd; // speed in km/h
- float spdS; // speed in m/s
- int velN;
- int velE;
- int velD;
- float hdg;
- int sats; // amount of TRACKED sats
- int totalSats; // amount of VISIBLE sats
- int SNR;
- String time;
- int timeSeconds; // keep seconds seperate to not break other stuff
- uint8_t GPSmonth;
- uint8_t GPSday;
- uint8_t GPSyear;
- uint8_t GPSdow; // day of week
- };
- GPS gpsData;
- const int32_t latOne = xxxxxxxxx;
- const int32_t lonOne = xxxxxxxxx;
- const int32_t latTwo = xxxxxxxxx;
- const int32_t lonTwo = xxxxxxxxx;
- NeoGPS::Location_t posOne(latOne, lonOne);
- NeoGPS::Location_t posTwo(latTwo, lonTwo );
- NeoGPS::Location_t liveMeassureLoc;
- int32_t liveMLat;
- int32_t liveMLon;
- bool canSleep = true;
- const String fixTypes[8] = {
- "NO FIX",
- "EST",
- "TIME ONLY",
- "STD",
- "DGPS",
- "RTK FLOAT",
- "RTK FIXED",
- "PPS"
- };
- const String monthNames[12] = {
- "Dec",
- "Jan",
- "Feb",
- "Mar",
- "Apr",
- "May",
- "Jun",
- "Jul",
- "Aug",
- "Sep",
- "Oct",
- "Nov"
- };
- // [x][0] - hour hand X
- // [x][1] - hour hand Y
- //
- // [x][2] - Minute hand X
- // [x][3] - minute hand Y
- //
- // [x][4] - marker START X
- // [x][5] - marker START Y
- //
- // [x][6] - marker STOP X
- // [x][7] - marker STOP Y
- int clockPositions[60][8];
- int clockCounterPositions[60][2];
- // length of analog clock hands, as radius of a circle
- #define hrRadius 75 // hour hand
- #define mnRadius 105 // minute hand
- #define scRadius 105 // seconds hand ( currently overriden to mnRadius )
- #define cnRadius 22 // hour hand other side
- void setup() {
- // first get screen orientation!
- preferences.begin("settings", false);
- landscape = preferences.getBool("screenOri", true);
- tft.init();
- u8f.begin(spr);
- u8f.setFont(u8g2_font_t0_22_me);
- tft.setTextWrap(false, false);
- tft.setRotation(landscape);
- screenHeight = tft.height();
- screenWidth = tft.width();
- spr.createSprite(screenWidth, screenHeight);
- drawText("GPS TRACKER", 20, CENTER_NO, palletes[pallete][3]);
- drawText("Booting..", 50, CENTER_NO, TFT_WHITE);
- spr.pushSprite(0, 0);
- Serial.begin(115200);
- drawText("Getting settings..", 80, LEFT, TFT_WHITE);
- spr.pushSprite(0, 0);
- getSettings();
- esp_sleep_enable_ext0_wakeup(GPIO_NUM_39, 0); //R button
- drawText("SD init..", 105, LEFT, TFT_WHITE);
- spr.pushSprite(0, 0);
- SPI.begin(14, 2, 15, 13);
- hasSD = SD.begin(13);
- (hasSD) ? Serial.println("SD opened!") : Serial.println("Issue with SD!");
- (hasSD) ? drawText("OK", 105, RIGHT, TFT_GREEN) : drawText("FAIL", 105, RIGHT, TFT_RED);
- spr.pushSprite(0, 0);
- pinMode(21, OUTPUT); // pinMode(TFT_BL OUTPUT);
- Wire.begin();
- //set battery charging current to 1000mA
- ip5306_set_bits(IP5306_REG_CHG_4, 0, 5, chargeCurrent);
- String current = String((ip5306_get_bits(IP5306_REG_CHG_4, 0, 5) * 100) + 50) + "mA";
- drawText("charging current:", 125, LEFT, TFT_WHITE);
- drawText(current, 125, RIGHT, TFT_WHITE);
- xTaskCreatePinnedToCore(
- checkButtons, /* Task function. */
- "Task1", /* name of task. */
- 10000, /* Stack size of task */
- NULL, /* parameter of the task */
- 1, /* priority of the task */
- &handleButtons, /* Task handle to keep track of created task */
- 0); /* pin task to core 0 */
- for (int i = 0; i < 8; i++) {
- headingLookupTable[i][0] = sin(radians((i * 45) + 90));
- headingLookupTable[i][1] = cos(radians((i * 45) + 90));
- }
- // calculate positions for analog clock and save them, to save resources
- for(int i = 0; i < 60; i++){
- // HOUR
- clockPositions[i][0] = sin(radians((i*6))) * hrRadius; // calculate hour hand X pos
- clockPositions[i][1] = -cos(radians((i*6))) * hrRadius; // calculate hour hand Y pos
- // MINUTE
- clockPositions[i][2] = sin(radians((i*6))) * mnRadius; // calculate min hand X pos
- clockPositions[i][3] = -cos(radians((i*6))) * mnRadius; // calculate min hand Y pos
- // COUNTER ( inverted )
- clockCounterPositions[i][0] = -sin(radians((i*6))) * cnRadius; // calculate counter hand X pos
- clockCounterPositions[i][1] = cos(radians((i*6))) * cnRadius; // calculate counter hand Y pos
- }
- for(int i = 0; i < 12; i++){
- // MARKERS START
- clockPositions[i][4] = -sin(radians((i*30))) * 117; // calculate min hand X pos
- clockPositions[i][5] = cos(radians((i*30))) * 117; // calculate min hand Y pos
- // MARKERS END
- clockPositions[i][6] = -sin(radians((i*30))) * 115; // calculate min hand X pos
- clockPositions[i][7] = cos(radians((i*30))) * 115; // calculate min hand Y pos
- }
- Serial.println("Core 1 RDY!");
- spr.pushSprite(0, 0);
- drawText("Core 1 RDY!", 145, LEFT, TFT_GREEN);
- while (!bootRdy) {
- delay(1);
- }
- drawText("Core 2 RDY!", 165, LEFT, TFT_GREEN);
- spr.pushSprite(0, 0);
- delay(1000);
- spr.fillSprite(TFT_BLACK);
- }
- void loop() {
- // show correct home screen
- if (clicked == 1 && screenOn) {
- if (mainScreenIndex + 1 < numScreens) {
- mainScreenIndex++;
- refreshScreen = true;
- }
- clicked = -1;
- }
- if (clicked == 3 && screenOn) {
- if (mainScreenIndex - 1 > -1) {
- mainScreenIndex--;
- refreshScreen = true;
- }
- clicked = -1;
- }
- if(!canSleep){
- lastPressed = millis();
- }
- // screen autosleep
- if (autoScreenOff && millis() - lastPressed > (screenTimer * 1000)) {
- screenOn = false;
- if(useAOD){
- setScreenBrightness(AODBrightness);
- AOD(false);
- }
- else{ setScreenBrightness(0); }
- }
- else if (!screenOn) {
- screenOn = true;
- setScreenBrightness(screenBrightness);
- refreshScreen = true;
- clicked = -1;
- }
- if (autoSleep && millis() - lastPressed > (sleepTimer * 1000)) {
- setScreenBrightness(0);
- esp_deep_sleep_start();
- }
- // enter settings menu
- if (clicked == 2 && screenOn) {
- clicked = -1;
- settings();
- }
- if (millis() - lastRefresh > refreshRate) {
- lastRefresh = millis();
- refreshScreen = true;
- }
- // refresh screen
- if (refreshScreen && screenOn) {
- refreshScreen = false;
- switch (mainScreenIndex) {
- case 0:
- homeScreen();
- break;
- case 1:
- drawGPSData();
- break;
- case 2:
- drawSatConstellation();
- break;
- case 3:
- drawBars();
- break;
- case numScreens-1: // graph screen is always last screen
- drawGraph();
- break;
- }
- }
- delay(1);
- }
- // --------------- UI - GPS ---------------
- void homeScreen(){
- tft.setRotation(landscape);
- spr.fillSprite(TFT_BLACK);
- canSleep = true;
- // drawStatusBar(String(gpsData.sats), "");
- u8f.setFont(fontMid);
- String dateString = gpsData.time + " " + String(gpsData.GPSday) + " " + monthNames[gpsData.GPSmonth];
- drawText(dateString, 25, CENTER_NO, palletes[pallete][2]);
- spr.drawFastHLine(0, 40, screenWidth, palletes[pallete][1]);
- drawBattery(15, 13, 10, 7);
- u8f.setFont(fontMid);
- if(usePrecision){
- drawText("lat: " + String(gpsData.latP), 90, CENTER_NO, palletes[pallete][2]);
- drawText("lon: " + String(gpsData.lonP), 110, CENTER_NO, palletes[pallete][2]);
- drawText("alt: " + String(gpsData.alt), 130, CENTER_NO, palletes[pallete][2]);
- }
- else if(useDMS){
- drawText("lat: " + String(gpsData.latDMS, 6), 90, CENTER_NO, palletes[pallete][2]);
- drawText("lon: " + String(gpsData.lonDMS, 6), 110, CENTER_NO, palletes[pallete][2]);
- drawText("alt: " + String(gpsData.alt), 130, CENTER_NO, palletes[pallete][2]);
- }
- else{
- drawText("lat: " + String(gpsData.lat, 6), 90, CENTER_NO, palletes[pallete][2]);
- drawText("lon: " + String(gpsData.lon, 6), 110, CENTER_NO, palletes[pallete][2]);
- drawText("alt: " + String(gpsData.alt), 130, CENTER_NO, palletes[pallete][2]);
- }
- if(gpsData.spd >= minCardinalSpeed){
- String spdText;
- if(useKmS){
- spdText = String(gpsData.spd) + "km/h - ";
- }
- else { spdText = String(gpsData.spdS) + "m/s - "; }
- spdText += String(gpsData.hdg, 0) + "°";
- drawText(spdText, 160, CENTER_NO, palletes[pallete][2]);
- }
- u8f.setFont(fontxSml);
- drawText(fixTypes[gpsData.fixStatus], 15, RIGHT, palletes[pallete][2]);
- if (gpsData.sats > 0) { drawText(String(gpsData.sats), 30, RIGHT, palletes[pallete][2]); }
- u8f.setFont(fontSml);
- if(gpsData.fixStatus > 2){
- if(liveMeassure){
- String liveDistance = String(fix.location.DistanceKm(liveMeassureLoc), 3) + "km, " + String(fix.location.BearingToDegrees(liveMeassureLoc), 0) + "°";
- drawText("Live Meassure: ", 220, CENTER_NO, palletes[pallete][2]);
- drawText(liveDistance, 240, CENTER_NO, palletes[pallete][2]);
- }
- else{
- String mikaDistance = String(fix.location.DistanceKm(mikaHome)) + "km from home";
- drawText(mikaDistance, 220, CENTER_NO, palletes[pallete][2]);
- String hestiaDistance = String(String(fix.location.DistanceKm(hestiaHome)));
- (fix.location.DistanceKm(hestiaHome) > 3 ) ? hestiaDistance += "km too far from her" : hestiaDistance += "km";
- drawText(hestiaDistance, 240, CENTER_NO, palletes[pallete][2]);
- }
- }
- else{
- drawText("Waiting for fix..", 220, CENTER_NO, palletes[pallete][2]);
- }
- spr.pushSprite(0, 0);
- }
- void drawGPSData() {
- tft.setRotation(landscape);
- canSleep = false;
- unsigned long lastUpdate, last;
- bool refresh = true;
- clicked = -1;
- if(gpsData.fixStatus < 3) {
- noFixScreen();
- return;
- }
- if (millis() - lastUpdate > 100) {
- lastUpdate = millis();
- refresh = false;
- spr.fillSprite(TFT_BLACK);
- drawStatusBar(String(gpsData.sats), "");
- // draw speed compenents cross
- // spr.drawWideLine((screenWidth/2)+15, 5, screenWidth/2)+15, 100, 5, palletes[pallete][2]);
- // u8f.setFont(fontMid);
- // if(landscape){
- // drawText(String(gpsData.velN) + "N", 50, CENTER, palletes[pallete][2]);
- // drawText(String(gpsData.velE) + "E", 70, CENTER, palletes[pallete][2]);
- // drawText(String(gpsData.velD) + "D", 90, CENTER, palletes[pallete][2]);
- // }
- // else{
- // drawText(String(gpsData.sats), 20, LEFT, palletes[pallete][2]);
- // drawText(String(gpsData.velN) + "N", 70, CENTER, palletes[pallete][2]);
- // drawText(String(gpsData.velE) + "E", 90, CENTER, palletes[pallete][2]);
- // drawText(String(gpsData.velD) + "D", 110, CENTER, palletes[pallete][2]);
- // }
- // drawHeadingCircle(gpsData.hdg, gpsData.spd);
- drawAltHeading(gpsData.hdg, gpsData.spd);
- spr.pushSprite(0, 0);
- }
- }
- void drawHeadingCircle(int heading, double speed) {
- tft.setRotation(landscape);
- int radius;
- (landscape) ? radius = 130 : radius = 100;
- int x;
- (landscape) ? x = (screenWidth/2)+15 : x = screenWidth/2;
- int y = 320 - (radius / 3);
- String cardinalString[3];
- drawText("^", (y - radius), CENTER, palletes[pallete][2]);
- spr.drawSmoothCircle(x, y, radius, palletes[pallete][0], TFT_BLACK);
- if(landscape){
- drawText(String(heading) + "°", y-57, CENTER, palletes[pallete][2]);
- (useKmS) ? drawText(String(speed) + "km/h", y-37, CENTER, palletes[pallete][2]) : drawText(String(speed) + "m/s", y-37, CENTER, palletes[pallete][2]);
- }
- else{
- drawText(String(heading) + "°", y, CENTER, palletes[pallete][2]);
- (useKmS) ? drawText(String(speed) + "km/h", screenHeight-10, CENTER, palletes[pallete][2]) : drawText(String(speed) + "m/s", screenHeight-10, CENTER, palletes[pallete][2]);
- }
- int textX;
- int textY;
- int w;
- uint16_t tColor;
- for (int i = 0; i < 8; i++) {
- if (i % 2) { // for 45, 135, 225, 315 deg
- u8f.setFont(fontSpecial);
- tColor = palletes[pallete][1];
- }
- else { //for 0, 90, 180, 270 deg
- u8f.setFont(fontMid);
- tColor = palletes[pallete][2];
- }
- w = u8f.getUTF8Width(markers[i].c_str());
- textX = sin(radians(heading + (i * 45))) * radius + x;
- textY = cos(radians(heading + (i * 45))) * radius + y;
- drawText(markers[i], textX - (w / 2), textY + 7, tColor);
- }
- }
- void drawAltHeading(int heading, double speed){
- tft.setRotation(landscape);
- int radius = (240/2)-8;
- int x = (screenWidth/2);
- int y = (screenHeight/2);
- (landscape) ? x += 15 : y += 15;
- int dotX = sin(radians(heading)) * radius + x;
- int dotY = -cos(radians(heading)) * radius + y;
- int armX = sin(radians(heading)) * (radius-10) + x;
- int armY = -cos(radians(heading)) * (radius-10) + y;
- int armCounterX = -sin(radians(heading)) * (radius-10) + x;
- int armCounterY = cos(radians(heading)) * (radius-10) + y;
- // spr.drawSmoothCircle(x, y, radius, palletes[pallete][0], TFT_BLACK);
- // spr.drawFastHLine(x-radius+5, y, (radius-5)*2, palletes[pallete][0]);
- // spr.drawFastVLine(x, y-radius+5, (radius-5)*2, palletes[pallete][0]);
- uint16_t tColor;
- byte w = 0;
- u8f.setFont(fontSpecial);
- for(int i = 0; i < 8; i++) {
- (i % 2) ? tColor = palletes[pallete][1] : tColor = palletes[pallete][2];
- w = u8f.getUTF8Width(markers[i].c_str());
- int textX = sin(radians(i * 45)) * radius + x;
- int textY = cos(radians(i * 45)) * radius + y;
- // if(i % 2 == 0) { spr.drawSmoothCircle(textX, textY, 10, tColor, TFT_BLACK); }
- drawText(markers[i], textX - (w / 2), textY + 7, tColor);
- }
- String headingS = String(heading);
- if(gpsData.spd >= minCardinalSpeed){
- spr.drawSpot(x, y, 5, palletes[pallete][0], TFT_BLACK);
- spr.drawWedgeLine(x, y, armCounterX, armCounterY, 5, 1, TFT_WHITE);
- spr.drawWedgeLine(x, y, armX, armY, 5, 1, TFT_RED);
- }
- else{
- spr.drawSpot(x, y, 5, TFT_BLACK, TFT_BLACK);
- spr.drawWedgeLine(x, y, armX, armY, 5, 1, TFT_DARKGREY);
- spr.drawWedgeLine(x, y, armCounterX, armCounterY, 5, 1, TFT_LIGHTGREY);
- }
- }
- void drawSatConstellation() {
- tft.setRotation(landscape);
- canSleep = true;
- if(gpsData.fixStatus < 3) { noFixScreen(); }
- else
- {
- // only here, for now
- bool drawMarkers = true;
- int outerRadius = 118;
- int circleX,circleY;
- if(landscape){
- circleX = 175; // add width of status bar
- circleY = 120;
- }
- else{
- circleX = 120;
- circleY = 195;
- }
- int totalCount;
- spr.fillSprite(TFT_BLACK);
- drawStatusBar(String(gpsData.sats), "");
- // draw main circles, one at 0deg, and one at 45deg altitude
- spr.drawSmoothCircle(circleX, circleY, outerRadius, palletes[pallete][0], TFT_BLACK);
- spr.drawSmoothCircle(circleX, circleY, outerRadius/2, palletes[pallete][0], TFT_BLACK);
- // tft.drawCircle(120, 200, 5, TFT_WHITE);
- // draw lines at 0, 45, 90, 135 etc degrees azimuth
- for (int i = 0; i < 8; i++) {
- int xPos = sin(radians((i * 45) + 90)) * outerRadius;
- int yPos = cos(radians((i * 45) + 90)) * outerRadius;
- spr.drawLine(circleX, circleY, xPos + circleX, yPos + circleY, palletes[pallete][1]);
- u8f.setFont(fontxSml);
- int markerIndex = i + 2;
- markerIndex %= 8;
- int w = u8f.getUTF8Width(markers[markerIndex].c_str());
- drawText(markers[markerIndex], xPos - (w / 2) + circleX, (yPos + 6) + circleY, palletes[pallete][2]);
- }
- // draw the positions of the sats
- for (int i = 0; i < gpsData.totalSats; i++) {
- int xPos = -sin(radians(gps.satellites[i].azimuth + 180)) * map(gps.satellites[i].elevation, 0, 90, outerRadius, 1);
- int yPos = cos(radians(gps.satellites[i].azimuth + 180)) * map(gps.satellites[i].elevation, 0, 90, outerRadius, 1);
- if(gps.satellites[i].tracked){
- int snr = gps.satellites[i].snr;
- spr.drawSpot(xPos + circleX, yPos + circleY, SAT_RADIUS, SNRToColor(snr));
- }
- else{ spr.drawSpot(xPos + circleX, yPos + circleY, SAT_RADIUS, TFT_DARKGREY); }
- String satMarker;
- satMarker = String(gps.satellites[i].id);
- int w = u8f.getUTF8Width(satMarker.c_str());
- int textY = yPos+(circleY-SAT_RADIUS)-2;
- int textX = xPos+circleX-(w/2);
- if(landscape && textY < 15){ textY = yPos+(circleY+SAT_RADIUS) + 15; }
- (gps.satellites[i].tracked) ? drawText(satMarker, textX, textY, palletes[pallete][2]) : drawText(satMarker, textX, textY, TFT_DARKGREY);
- }
- spr.pushSprite(0, 0);
- }
- }
- void drawBars(){
- tft.setRotation(1);
- canSleep = true;
- spr.fillSprite(TFT_BLACK);
- if(gpsData.fixStatus < 3) { noFixScreen(); }
- else
- {
- int numSatsHalf = gpsData.totalSats/2;
- bool odd = false;
- byte spacing = 10;
- byte barHeight = 100;
- byte startOffset;
- (landscape) ? startOffset = 32 : startOffset = 0;
- int screenWidthLocal = screenWidth;
- if(landscape){ screenWidthLocal -= 35; }
- screenWidthLocal -= startOffset;
- // set odd flag
- if((gpsData.sats) % 2){
- odd = true;
- }
- byte colorIndex;
- drawStatusBar(String(gpsData.sats), "");
- u8f.setFont(fontSml);
- int x, y, barWidth, topCnt, btmCnt;
- topCnt = numSatsHalf;
- if(odd){
- barWidth = (screenWidthLocal/(numSatsHalf+1))-spacing;
- btmCnt = numSatsHalf+1;
- }
- else{
- barWidth = (screenWidthLocal/numSatsHalf)-spacing;
- btmCnt = numSatsHalf;
- }
- for(int i = 0; i < topCnt; i++){
- (landscape) ? y = 20 : y = 50;
- if(!landscape){
- if(i > 0 && i < topCnt-2) { (odd) ? x = ((screenWidthLocal/(numSatsHalf+1))*i) + (spacing/2) + startOffset : x = ((screenWidthLocal/numSatsHalf)*i) + (spacing/2) + startOffset; }
- else { (odd) ? x = ((screenWidthLocal/(numSatsHalf+1))*i) + spacing + startOffset : x = ((screenWidthLocal/numSatsHalf)*i) + spacing + startOffset; }
- }
- else{ (odd) ? x = ((screenWidthLocal/(numSatsHalf+1))*i) + spacing + startOffset : x = ((screenWidthLocal/numSatsHalf)*i) + spacing + startOffset; }
- byte SNR = gps.satellites[i].snr;
- byte barFill = map(SNR, 0, 99, 0, barHeight-1);
- (SNR) ? spr.drawRect(x, y, barWidth, barHeight, SNRToColor(SNR)) : spr.drawRect(x, y, barWidth, barHeight, TFT_DARKGREY);
- // fillRect() starts at passed X/Y, and works downwards (!)
- // because of this, we first move the top left corner of the filled bar down to the amount it should be filled.
- // then, we set the height ( from the top left corner ) to what is left between the moved start, and the bottom of the bar
- spr.fillRect(x+1, y+(barHeight-barFill)-1, barWidth-2, barFill, SNRToColor(SNR));
- String text;
- byte textW;
- if(SNR){
- text = String(SNR);
- textW = u8f.getUTF8Width(text.c_str());
- drawText(text, x+(barWidth/2)-(textW/2), y+20, palletes[pallete][2]);
- }
- text = String(gps.satellites[i].id);
- textW = u8f.getUTF8Width(text.c_str());
- (gps.satellites[i].tracked) ? drawText(text, x+(barWidth/2)-(textW/2), y-2, palletes[pallete][2]) : drawText(text, x+(barWidth/2)-(textW/2), y-2, TFT_DARKGREY);
- }
- // draw bottom row of bars
- for(int i = 0; i < btmCnt; i++){
- (landscape) ? y = 140 : y = 170;
- // calculate X position for each bar
- if(!landscape){
- if(i > 0 && i < topCnt-2) { (odd) ? x = ((screenWidthLocal/(numSatsHalf+1))*i) + (spacing/2) + startOffset : x = ((screenWidthLocal/numSatsHalf)*i) + (spacing/2) + startOffset; }
- else { (odd) ? x = ((screenWidthLocal/(numSatsHalf+1))*i) + spacing + startOffset : x = ((screenWidthLocal/numSatsHalf)*i) + spacing + startOffset; }
- }
- else{ (odd) ? x = ((screenWidthLocal/(numSatsHalf+1))*i) + spacing + startOffset : x = ((screenWidthLocal/numSatsHalf)*i) + spacing + startOffset; }
- byte SNR = gps.satellites[i+numSatsHalf].snr;
- byte barFill = map(SNR, 0, 99, 0, barHeight-1);
- (SNR) ? spr.drawRect(x, y, barWidth, barHeight, SNRToColor(SNR)) : spr.drawRect(x, y, barWidth, barHeight, TFT_DARKGREY);
- // fillRect() starts at passed X/Y, and works downwards (!)
- // because of this, we first move the top left corner of the filled bar down to the amount it should be filled.
- // then, we set the height ( from the top left corner ) to what is left between the moved start, and the bottom of the bar
- spr.fillRect(x+1, y+(barHeight-barFill)-1, barWidth-2, barFill, SNRToColor(SNR));
- String text;
- byte textW;
- if(SNR){
- text = String(SNR);
- textW = u8f.getUTF8Width(text.c_str());
- drawText(text, x+(barWidth/2)-(textW/2), y+20, palletes[pallete][2]);
- }
- text = String(gps.satellites[i+numSatsHalf].id);
- textW = u8f.getUTF8Width(text.c_str());
- (gps.satellites[i+numSatsHalf].tracked) ? drawText(text, x+(barWidth/2)-(textW/2), y-2, palletes[pallete][2]) : drawText(text, x+(barWidth/2)-(textW/2), y-2, TFT_DARKGREY);
- }
- String avgSNRs = String(gpsData.SNR);
- // PRINT AVG SNR
- if(landscape){
- int avgBarFill = map(gpsData.SNR, 0, 99, 0, 239);
- spr.fillRect(301, (239-avgBarFill), 18, avgBarFill, SNRToColor(gpsData.SNR));
- spr.drawRect(300, 0, 20, 240, palletes[pallete][0]);
- drawText(avgSNRs, 320-(u8f.getUTF8Width(avgSNRs.c_str())), 20, SNRToColor(gpsData.SNR));
- }
- else{
- spr.drawRect(0, screenHeight-25, screenWidth, 25, palletes[pallete][0]);
- int avgBarFill = map(gpsData.SNR, 0, 99, 0, screenWidth-1);
- drawText(avgSNRs, screenHeight-25, CENTER, palletes[pallete][2]);
- spr.fillRect(1, screenHeight-24, avgBarFill, 23, SNRToColor(gpsData.SNR));
- }
- spr.pushSprite(0, 0);
- }
- }
- void drawGraph(){
- canSleep = false;
- float gData[graphSize];
- float datapointsMapped[graphSize];
- u8f.setFont(fontSml);
- for(int i = 0; i < graphSize; i++){
- gData[i] = -99;
- }
- bool refresh = true;
- bool drawnUI = false;
- bool emptyArray = false;
- unsigned long last;
- int x, y, xe, ye;
- static int dataIndex = 0;
- float minOld, maxOld;
- String dataMarker = "";
- String markerOld = "";
- while(clicked < 2){
- // switch data types
- if(clicked == 1){
- dataIndex++;
- if(dataIndex > 3){ dataIndex = 0; }
- emptyArray = true;
- clicked = -1;
- }
- if(emptyArray){
- emptyArray = false;
- for(int i = 0; i < graphSize; i++){
- gData[i] = -99;
- }
- }
- if(millis() - last > gRefreshRate){
- last = millis();
- spr.fillSprite(TFT_BLACK);
- // left shift new data into array
- for(int i = 0; i < graphSize-1; i++){
- gData[i] = gData[i+1];
- }
- switch (dataIndex){
- case 0:
- gData[graphSize-1] = gpsData.SNR;
- dataMarker = "SNR";
- break;
- case 1:
- gData[graphSize-1] = gpsData.sats;
- dataMarker = "Sats";
- break;
- case 2:
- gData[graphSize-1] = gpsData.spd;
- dataMarker = "SPD ";
- (useKmS) ? dataMarker += "(Km/h)" : dataMarker += "(m/s)";
- break;
- case 3:
- if(fix.valid.altitude){
- (useGeoidHeight) ? gData[graphSize-1] = fix.geoidHeight() : gData[graphSize-1] = fix.altitude();
- }
- else{ gData[graphSize-1] = 0; }
- dataMarker = "ALT (m)";
- break;
- default:
- gData[graphSize-1] = gpsData.SNR;
- dataMarker = "SNR";
- break;
- }
- float minVal = 10000.0;
- float maxVal = -10000.0;
- // draw scales
- spr.drawWideLine(30, 0, 30, screenHeight-28, 2, TFT_WHITE, TFT_BLACK);
- spr.drawWideLine(30, screenHeight-28, screenWidth, screenHeight-28, 2, TFT_WHITE, TFT_BLACK);
- // draw timescale on X axis and get min/max
- for(int i = 0; i < graphSize; i++){
- if(i % (graphSize/4) == 0){
- u8f.setFont(fontxSml);
- String marker = String(gRefreshRate*(graphSize - (i))/1000.0, 1) + "s";
- int markerW = u8f.getUTF8Width(marker.c_str());
- int tPos = 30 + map(i+1, 0, graphSize, 0, screenWidth-30);
- drawText(marker, tPos-(markerW/2), screenHeight-10, TFT_WHITE);
- spr.drawFastVLine(tPos, screenHeight-33, 10, TFT_WHITE);
- }
- if(gData[i] > -99){
- if(gData[i] < minVal) { minVal = gData[i]; }
- if(gData[i] > maxVal) { maxVal = gData[i]; }
- }
- }
- // prevent graph line from touching top/bottom by adding 5% of the graph range
- int paddingVal = ((maxVal - minVal)/100)*10;
- minVal -= paddingVal;
- maxVal += paddingVal;
- if(maxVal - minVal < 5){
- maxVal += 2.5;
- minVal -= 2.5;
- }
- byte dataMarkerWidth = u8f.getUTF8Width(dataMarker.c_str());
- drawText(dataMarker, 15, CENTER, TFT_WHITE);
- u8f.setFont(fontSpecial);
- drawText(String(minVal+paddingVal, 0), 0, screenHeight-28, TFT_WHITE);
- drawText(String(maxVal-paddingVal, 0), 0, 20, TFT_WHITE);
- u8f.setFont(fontMid);
- // transform values to coordinates on screen
- for(int i = 0; i < graphSize; i++){
- if(gData[i] == -99) { datapointsMapped[i] = -99; }
- else{ datapointsMapped[i] = mapF(gData[i], minVal, maxVal, screenHeight-31, 1); }
- }
- // draw lines on screen
- for(int i = 0; i < graphSize-1; i++){
- if(datapointsMapped[i] > -99 && datapointsMapped[i+1] > -99){
- x = map(i, 0, graphSize, 32, screenWidth);
- xe = map(i+1, 0, graphSize, 32, screenWidth);
- y = datapointsMapped[i];
- ye = datapointsMapped[i+1];
- spr.drawLine(xe, ye, x, y, palletes[pallete][1]);
- }
- }
- String text = String(gData[graphSize-1], 1);
- u8f.setFont(fontSml);
- int textW = u8f.getUTF8Width(text.c_str());
- if(datapointsMapped[graphSize-1] < 20){ drawText(text, screenWidth-textW, datapointsMapped[graphSize-1]+17, TFT_WHITE); }
- else { drawText(text, screenWidth-textW, datapointsMapped[graphSize-1]-3, TFT_WHITE); }
- delay(1); // WD
- spr.pushSprite(0, 0);
- }
- }
- }
- // --------------- UI - OTHER ---------------
- void noFixScreen(){
- spr.fillSprite(TFT_BLACK);
- drawStatusBar("", "");
- u8f.setFont(fontMid);
- drawText("Waiting for fix..", 70, CENTER, palletes[pallete][2]);
- u8f.setFont(fontSml);
- drawText("SI: " + String(mainScreenIndex), 20, RIGHT, TFT_WHITE);
- drawText(fixTypes[gpsData.fixStatus], 40, RIGHT, palletes[pallete][2]);
- spr.pushSprite(0, 0);
- }
- void AOD(bool forceRefresh){
- byte cPallete;
- (useAODPalette) ? cPallete = clockPallete : cPallete = pallete;
- if(altAOD){
- // draw analog clock
- spr.fillSprite(TFT_BLACK);
- byte s, m, h;
- String gpsTime = gpsData.time;
- m = gpsTime.substring(gpsTime.indexOf(":")+1).toInt();
- h = gpsTime.substring(0, gpsTime.indexOf(":")).toInt();
- s = gpsData.timeSeconds;
- h %= 12; // convert to 12hr time
- h *= 5;
- h += map(m, 0, 60, 0, 5); // this makes the hour hand move towards the next hour instead of sticking
- int x = screenWidth/2;
- int y = screenHeight/2;
- // draw seconds hand
- if(showSeconds) {
- spr.drawWideLine(x, y, clockPositions[s][2] + x, clockPositions[s][3] + y, 2, TFT_WHITE);
- // spr.drawWideLine(x, y, clockCounterPositions[s][0] + x, clockCounterPositions[s][1] + y, 2, TFT_WHITE);
- }
- // draw minute hand
- spr.drawWedgeLine(x, y, clockPositions[m][2] + x, clockPositions[m][3] + y, 2, 1, palletes[cPallete][1]);
- spr.drawWedgeLine(x, y, clockCounterPositions[m][0] + x, clockCounterPositions[m][1] + y, 2, 1, palletes[cPallete][1]);
- // draw markers
- for(int i = 0; i < 12; i++){
- spr.drawWideLine(clockPositions[i][4] + x, clockPositions[i][5] + y, clockPositions[i][6] + x, clockPositions[i][7] + y, 3, palletes[cPallete][0]);
- }
- // spr.drawSmoothCircle(x, y, 119, TFT_WHITE, TFT_BLACK);
- // draw center ring
- spr.drawSpot(x, y, 6, TFT_BLACK); // clear area
- //spr.drawSpot(x, y, 10, TFT_TRANSPARENT); // draw shadow
- spr.drawSpot(x, y, 7, palletes[cPallete][1]); // draw center
- // draw hour hand
- spr.drawWedgeLine(x, y, clockPositions[h][0] + x, clockPositions[h][1] + y, 3, 1, palletes[cPallete][1]);
- spr.drawWedgeLine(x, y, clockCounterPositions[h][0] + x, clockCounterPositions[h][1] + y, 3, 2, palletes[cPallete][1]);
- spr.drawSpot(x, y, 3, TFT_BLACK); // clear center
- if(showBattery) { drawBattery(x, y, 10, 5); }
- else{
- u8f.setFont(fontxSml);
- byte textLen;
- if(getCharging()){
- textLen = u8f.getUTF8Width("Charging");
- drawText("Charging", (screenWidth/2) - (textLen/2), y+17, TFT_WHITE);
- }
- }
- spr.pushSprite(0, 0);
- }
- else{
- // draw digital clock
- spr.fillSprite(TFT_BLACK);
- tft.setRotation(landscape);
- u8f.setFont(fontBig);
- setScreenBrightness(1);
- // draw time
- String timeWhole = gpsData.time;
- String time = timeWhole.substring(0, timeWhole.indexOf(":"));
- int len = u8f.getUTF8Width(time.c_str());
- drawText(time, (screenWidth/2)-(len/2), (screenHeight/2)-10, TFT_DARKGREY);
- time = timeWhole.substring(timeWhole.indexOf(":")+1);
- len = u8f.getUTF8Width(time.c_str());
- drawText(time, (screenWidth/2)-(len/2), (screenHeight/2)+60, TFT_DARKGREY);
- drawBattery(screenWidth/2, screenHeight/2, 100, 90);
- spr.pushSprite(0, 0);
- }
- }
- void drawBattery(int x, int y, int r, int ir){
- int bat = 0;
- bat = getBatLevel();
- int arcEnd;
- switch (bat){
- case 100:
- arcEnd = 180;
- break;
- case 75:
- arcEnd = 90;
- break;
- case 50:
- arcEnd = 0;
- break;
- case 25:
- arcEnd = 270;
- break;
- }
- spr.drawSmoothArc(x, y, r, ir, 180, 180, TFT_DARKGREY, TFT_BLACK);
- spr.drawSmoothArc(x, y, r, ir, 180, arcEnd, TFT_SILVER, TFT_BLACK);
- if(getCharging()){
- u8f.setFont(fontxSml);
- byte textLen = u8f.getUTF8Width("CHG");
- drawText("CHG", x - (textLen/2), y + r + 11, TFT_WHITE);
- }
- }
- void drawStatusBar(String itemTop, String itemBot) {
- tft.setRotation(landscape);
- u8f.setFont(fontSml);
- if(landscape){
- String wholeTime = gpsData.time;
- drawText(wholeTime.substring(0, wholeTime.indexOf(":")), (screenHeight/2)-10, LEFT, palletes[pallete][2]);
- drawText(wholeTime.substring(wholeTime.indexOf(":")+1), (screenHeight/2)+10, LEFT, palletes[pallete][2]);
- int textW;
- textW = u8f.getUTF8Width(itemTop.c_str());
- drawText(itemTop, (30/2)-(textW/2)-2, (screenHeight/4) + 7, palletes[pallete][2]);
- textW = u8f.getUTF8Width(itemBot.c_str());
- drawText(itemBot, (30/2)-(textW/2)-2, (screenHeight/4)*3 + 7, palletes[pallete][2]);
- u8f.setFont(fontxSml);
- if(hasSD){
- if (logGPS) {
- textW = u8f.getUTF8Width("GPS");
- drawText("GPS", (30/2)-(textW/2)-2, screenHeight-10, palletes[pallete][2]);
- }
- if(logSPD) {
- textW = u8f.getUTF8Width("SPD");
- drawText("SPD", (30/2)-(textW/2)-2, screenHeight-20, palletes[pallete][2]);
- }
- if(!logSPD && !logGPS){
- textW = u8f.getUTF8Width("SD");
- drawText("SD", (30/2)-(textW/2)-2, screenHeight-10, palletes[pallete][2]);
- }
- }
- drawBattery(15, 13, 10, 7);
- spr.fillRect(29, 0, 3, screenHeight, palletes[pallete][1]);
- }
- else{
- drawText(itemTop, 20, LEFT, palletes[pallete][2]);
- drawText(gpsData.time, 20, CENTER, palletes[pallete][2]);
- if(hasSD){
- u8f.setFont(fontxSml);
- int textW;
- if (logGPS) {
- textW = u8f.getUTF8Width("GPS");
- drawText("GPS", screenWidth-textW-2, 10, palletes[pallete][2]);
- }
- if(logSPD) {
- textW = u8f.getUTF8Width("SPD");
- drawText("SPD", screenWidth-textW-2, 20, palletes[pallete][2]);
- }
- if(!logSPD && !logGPS){
- textW = u8f.getUTF8Width("SD");
- drawText("SD", screenWidth-textW-2, 10, palletes[pallete][2]);
- }
- }
- int bat = getBatLevel();
- spr.drawRect(0, 25, 240, 5, palletes[pallete][1]);
- spr.fillRect(1, 26, map(bat, 0, 100, 1, 240), 4, palletes[pallete][0]);
- }
- }
- // --------------- SETTINGS - MENUS ---------------
- void settings() {
- tft.setRotation(landscape);
- byte cursor = 0;
- int oldCursorIndex = 1;
- int subSettingsIndex = 0;
- runSettings = true;
- bool forceRefresh = false;
- delay(200);
- while (runSettings) {
- cursor = handleCursorIndex(false, numSettings);
- switch (subSettingsIndex) {
- case 1:
- powerSettings();
- subSettingsIndex = 0;
- oldCursorIndex = -1; // force screen to update
- handleCursorIndex(true, numSettings);
- break;
- case 2:
- screenSettings();
- subSettingsIndex = 0;
- oldCursorIndex = -1; // force screen to update
- handleCursorIndex(true, numSettings);
- break;
- case 3:
- AODSettings();
- subSettingsIndex = 0;
- oldCursorIndex = -1;
- handleCursorIndex(true, numSettings);
- break;
- case 4:
- GPSSettings();
- subSettingsIndex = 0;
- handleCursorIndex(true, numSettings);
- break;
- case 5:
- loggingSettings();
- subSettingsIndex = 0;
- handleCursorIndex(true, numSettings);
- break;
- }
- // ENTER was clicked, check what to run
- if (clicked == 2) {
- Serial.println(settingsText[cursor]);
- if (settingsText[cursor].equals("Power settings")) {
- subSettingsIndex = 1;
- }
- else if(settingsText[cursor].equals("Screen settings")){
- subSettingsIndex = 2;
- }
- else if(settingsText[cursor].equals("AOD settings")){
- subSettingsIndex = 3;
- }
- else if (settingsText[cursor].equals("GPS settings")) {
- subSettingsIndex = 4;
- }
- else if(settingsText[cursor].equals("Deep sleep")) {
- setScreenBrightness(0);
- esp_deep_sleep_start();
- }
- else if (settingsText[cursor].equals("Pallete")) {
- pallete++;
- if (pallete > numPalletes - 1) {
- pallete = 0;
- }
- forceRefresh = true;
- }
- else if (settingsText[cursor].equals("Logging settings")) {
- subSettingsIndex = 5;
- }
- else if(settingsText[cursor].equals("Start live meassure")){
- if(gpsData.sats > 0){
- settingsText[6] = "Stop live meassure";
- liveMeassureLoc = fix.location;
- liveMeassure = true;
- forceRefresh = true;
- }
- }
- else if(settingsText[cursor].equals("Stop live meassure")){
- settingsText[6] = "Start live meassure";
- liveMeassure = false;
- forceRefresh = true;
- }
- else if (settingsText[cursor].equals("Exit")) {
- setSettings(); //save settings
- runSettings = false;
- handleCursorIndex(true, numSettings);
- clicked = -1;
- refreshScreen = true;
- }
- clicked = -1;
- }
- // only draw screen if something changed
- if (oldCursorIndex != cursor || forceRefresh) {
- spr.fillSprite(TFT_BLACK);
- oldCursorIndex = cursor;
- forceRefresh = false;
- drawSettingOptions(settingsPtr, numSettings, cursor);
- drawText(palleteNames[pallete], 120, RIGHT, TFT_WHITE);
- String chargingCurrent = String((ip5306_get_bits(IP5306_REG_CHG_4, 0, 5) * 100) + 50) + "mA";
- drawText("Charging current: " + chargingCurrent, screenHeight-5, LEFT, TFT_WHITE);
- spr.pushSprite(0, 0);
- }
- delay(1); // keep WD happy
- }
- }
- void powerSettings() {
- tft.setRotation(landscape);
- byte cursor = 0;
- byte oldCursor = 0;
- bool forceRefresh = true;
- bool ignoreButtons = false;
- delay(200);
- handleCursorIndex(true, numPowerSettings);
- while (runSettings) {
- if (!ignoreButtons) { cursor = handleCursorIndex(false, numPowerSettings); }
- if (clicked == 2 || ignoreButtons) {
- if (powerSettingsText[cursor].equals("Auto-sleep")) {
- autoSleep = !autoSleep;
- forceRefresh = true;
- clicked = -1;
- }
- else if (powerSettingsText[cursor].equals("Sleep timer")) {
- handleSettingNumbers(&ignoreButtons, &forceRefresh, &sleepTimer, 0, 1, 900000);
- }
- else if (powerSettingsText[cursor].equals("Screen timer")) {
- handleSettingNumbers(&ignoreButtons, &forceRefresh, &screenTimer, 0, 1, 900000);
- }
- else if (powerSettingsText[cursor].equals("Screen auto-off")) {
- autoScreenOff = !autoScreenOff;
- forceRefresh = true;
- clicked = -1;
- }
- else if (powerSettingsText[cursor].equals("Screen brightness")) {
- handleSettingNumbers(&ignoreButtons, &forceRefresh, &screenBrightness, 0, 1, 10);
- }
- else if (powerSettingsText[cursor].equals("Back")) {
- clicked = -1;
- return;
- }
- }
- if (cursor != oldCursor || forceRefresh) {
- oldCursor = cursor;
- forceRefresh = false;
- spr.fillSprite(TFT_BLACK);
- drawSettingOptions(powerArrayPtr, numPowerSettings, cursor);
- (autoSleep) ? drawText("ON", 20, RIGHT, TFT_GREEN) : drawText("OFF", 20, RIGHT, TFT_RED);
- drawText(String(sleepTimer) + "s", 40, RIGHT, TFT_WHITE);
- spr.pushSprite(0, 0);
- }
- delay(1);
- }
- }
- void screenSettings(){
- tft.setRotation(landscape);
- byte cursor = 0;
- byte oldCursor = 0;
- bool forceRefresh = true;
- bool ignoreButtons = false;
- delay(200);
- handleCursorIndex(true, numScreenSettings);
- while (runSettings) {
- if (!ignoreButtons) { cursor = handleCursorIndex(false, numScreenSettings); }
- if (clicked == 2 || ignoreButtons) {
- if (screenSettingsText[cursor].equals("Screen auto-off")) {
- autoScreenOff = !autoScreenOff;
- forceRefresh = true;
- clicked = -1;
- }
- else if(screenSettingsText[cursor].equals("Screen timer")) {
- handleSettingNumbers(&ignoreButtons, &forceRefresh, &screenTimer, 0, 1, 900000);
- }
- else if (screenSettingsText[cursor].equals("Screen brightness")) {
- handleSettingNumbers(&ignoreButtons, &forceRefresh, &screenBrightness, 0, 1, 10);
- }
- else if(screenSettingsText[cursor].equals("Screen orientation")){
- landscape = !landscape;
- forceRefresh = true;
- tft.setRotation(landscape);
- screenHeight = tft.height();
- screenWidth = tft.width();
- clicked = -1;
- // make new virtual canvas with correct dimensions
- spr.deleteSprite();
- spr.createSprite(screenWidth, screenHeight);
- }
- else if(screenSettingsText[cursor].equals("Use pallete for SNR")){
- SNRPallete = !SNRPallete;
- forceRefresh = true;
- clicked = -1;
- }
- else if(screenSettingsText[cursor].equals("Back")) {
- clicked = -1;
- return;
- }
- }
- if (cursor != oldCursor || forceRefresh) {
- oldCursor = cursor;
- forceRefresh = false;
- spr.fillSprite(TFT_BLACK);
- drawSettingOptions(screenArrayPtr, numScreenSettings, cursor);
- (autoScreenOff) ? drawText("ON", 20, RIGHT, TFT_GREEN) : drawText("OFF", 20, RIGHT, TFT_RED);
- drawText(String(screenTimer) + "s", 40, RIGHT, TFT_WHITE);
- drawText(String(screenBrightness), 60, RIGHT, TFT_WHITE);
- if(landscape){
- (landscape) ? drawText("Landscape", 80, RIGHT, TFT_WHITE) : drawText("Portrait", 80, RIGHT, TFT_WHITE);
- }
- else{
- (landscape) ? drawText("L", 80, RIGHT, TFT_WHITE) : drawText("P", 80, RIGHT, TFT_WHITE);
- }
- (SNRPallete) ? drawText("ON", 100, RIGHT, TFT_GREEN) : drawText("OFF", 100, RIGHT, TFT_RED);
- spr.pushSprite(0, 0);
- }
- delay(1);
- }
- }
- void AODSettings(){
- tft.setRotation(landscape);
- byte cursor = 0;
- byte oldCursor = 0;
- bool forceRefresh = true;
- bool ignoreButtons = false;
- delay(200);
- handleCursorIndex(true, numAODSettings);
- while(runSettings){
- if (!ignoreButtons) { cursor = handleCursorIndex(false, numAODSettings); }
- if (clicked == 2 || ignoreButtons) {
- if (AODSettingsText[cursor].equals("AOD")) {
- useAOD = !useAOD;
- forceRefresh = true;
- clicked = -1;
- }
- if(AODSettingsText[cursor].equals("Clock mode")){
- altAOD = !altAOD;
- forceRefresh = true;
- clicked = -1;
- }
- if(AODSettingsText[cursor].equals("Seconds hand")){
- showSeconds = !showSeconds;
- forceRefresh = true;
- clicked = -1;
- }
- if(AODSettingsText[cursor].equals("AOD brightness")){
- handleSettingNumbers(&ignoreButtons, &forceRefresh, &AODBrightness, 1, 1, 10);
- }
- if(AODSettingsText[cursor].equals("Battery icon")){
- showBattery = !showBattery;
- forceRefresh = true;
- clicked = -1;
- }
- if(AODSettingsText[cursor].equals("Seperate palette")){
- useAODPalette = !useAODPalette;
- forceRefresh = true;
- clicked = -1;
- }
- if(AODSettingsText[cursor].equals("AOD palette")){
- clockPallete++;
- if (clockPallete > numPalletes - 1) {
- clockPallete = 0;
- }
- forceRefresh = true;
- clicked = -1;
- }
- if(AODSettingsText[cursor].equals("Back")){
- clicked = -1;
- return;
- }
- }
- if (cursor != oldCursor || forceRefresh) {
- oldCursor = cursor;
- forceRefresh = false;
- spr.fillSprite(TFT_BLACK);
- drawSettingOptions(AODArrayPtr, numAODSettings, cursor);
- (useAOD) ? drawText("ON", 20, RIGHT, TFT_GREEN) : drawText("OFF", 20, RIGHT, TFT_RED);
- (altAOD) ? drawText("Analog", 40, RIGHT, TFT_WHITE) : drawText("Digital", 40, RIGHT, TFT_WHITE);
- (showSeconds) ? drawText("ON", 60, RIGHT, TFT_GREEN) : drawText("OFF", 60, RIGHT, TFT_RED);
- drawText(String(AODBrightness), 80, RIGHT, TFT_WHITE);
- (showBattery) ? drawText("ON", 100, RIGHT, TFT_GREEN) : drawText("OFF", 100, RIGHT, TFT_RED);
- (useAODPalette) ? drawText("ON", 120, RIGHT, TFT_GREEN) : drawText("OFF", 120, RIGHT, TFT_RED);
- drawText(palleteNames[clockPallete], 140, RIGHT, TFT_WHITE);
- spr.pushSprite(0, 0);
- }
- }
- }
- void GPSSettings() {
- tft.setRotation(landscape);
- byte cursor = 10;
- byte oldCursor = 1;
- bool forceRefresh = false;
- bool ignoreButtons = false;
- delay(200);
- cursor = handleCursorIndex(true, numGPSSettings);
- while (runSettings) {
- if (!ignoreButtons) { cursor = handleCursorIndex(false, numGPSSettings); }
- if (clicked == 2 || ignoreButtons) {
- if (GPSSettingsText[cursor].equals("Speed metric")) {
- clicked = -1;
- useKmS = !useKmS;
- forceRefresh = true;
- }
- if (GPSSettingsText[cursor].equals("UTC offset")) {
- handleSettingNumbers(&ignoreButtons, &forceRefresh, &UTCOffset, 0, 1, 14);
- }
- if (GPSSettingsText[cursor].equals("Minimum speed")) {
- handleSettingNumbers(&ignoreButtons, &forceRefresh, &minCardinalSpeed, 0, 1, 100);
- }
- if(GPSSettingsText[cursor].equals("Precision")){
- clicked = -1;
- usePrecision = !usePrecision;
- forceRefresh = true;
- }
- if (GPSSettingsText[cursor].equals("Back")) {
- clicked = -1;
- return;
- }
- }
- if (cursor != oldCursor || forceRefresh) {
- oldCursor = cursor;
- forceRefresh = false;
- spr.fillSprite(TFT_BLACK);
- drawSettingOptions(gpsArrayPtr, numGPSSettings, cursor);
- (useKmS) ? drawText("km/h", 20, RIGHT, TFT_WHITE) : drawText("m/s", 20, RIGHT, TFT_WHITE);
- (UTCOffset > 0) ? drawText("+" + String(UTCOffset), 40, RIGHT, TFT_WHITE) : drawText(String(UTCOffset), 40, RIGHT, TFT_WHITE);
- drawText(String(minCardinalSpeed) + "km/h", 60, RIGHT, TFT_WHITE);
- // (usePrecision) ? drawText("HIGH", 80, RIGHT, TFT_WHITE) : drawText("LOW", 80, RIGHT, TFT_WHITE);
- // (randomiseData) ? drawText("TRUE", 80, RIGHT, TFT_GREEN) : drawText("FALSE", 0, RIGHT, TFT_RED);
- spr.pushSprite(0, 0);
- }
- delay(1);
- }
- }
- void loggingSettings() {
- tft.setRotation(landscape);
- byte cursor = 10;
- byte oldCursor = 1;
- bool forceRefresh = false;
- bool ignoreButtons = false;
- delay(200);
- cursor = handleCursorIndex(true, numLoggingSettings);
- while (runSettings) {
- if (!ignoreButtons) { cursor = handleCursorIndex(false, numLoggingSettings); }
- if (clicked == 2 || ignoreButtons) {
- if (loggingSettingsText[cursor].equals("Log position")) {
- clicked = -1;
- logGPS = !logGPS;
- forceRefresh = true;
- if(logGPS) { logData("/GPSLog.txt", ""); } // if logging was enabled, insert a NL
- }
- if (loggingSettingsText[cursor].equals("Log speed")) {
- clicked = -1;
- logSPD = !logSPD;
- forceRefresh = true;
- if(logSPD) { logData("/SPDLog.txt", ""); } // if logging was enabled, insert a NL
- }
- if(loggingSettingsText[cursor].equals("Logging freq")) {
- handleSettingNumbers(&ignoreButtons, &forceRefresh, &logGPSfreq, 1, 1, 300);
- }
- if (loggingSettingsText[cursor].equals("Back")) {
- clicked = -1;
- return;
- }
- }
- if (cursor != oldCursor || forceRefresh) {
- oldCursor = cursor;
- forceRefresh = false;
- spr.fillSprite(TFT_BLACK);
- drawSettingOptions(loggingArrayPtr, numLoggingSettings, cursor);
- (logGPS) ? drawText("ON", 20, RIGHT, TFT_GREEN) : drawText("OFF", 20, RIGHT, TFT_RED);
- (logSPD) ? drawText("ON", 40, RIGHT, TFT_GREEN) : drawText("OFF", 40, RIGHT, TFT_RED);
- drawText(String(logGPSfreq) + "s", 60, RIGHT, TFT_WHITE);
- spr.pushSprite(0, 0);
- }
- }
- }
- // --------------- SETTINGS - HELPERS ---------------
- uint16_t SNRToColor(byte SNRIn){
- uint16_t color;
- if(!SNRPallete){
- if(SNRIn >= 50) { color = barColors[0]; }
- else if(SNRIn >= 30) { color = barColors[1]; }
- else if(SNRIn >= 20) { color = barColors[2]; }
- else if(SNRIn >= 10) { color = barColors[3]; }
- else { color = barColors[4]; }
- }
- else {
- if(SNRIn >= 30) { color = palletes[pallete][1]; }
- else { color = palletes[pallete][0]; }
- }
- return color;
- }
- void setSettings() {
- // save power settings
- preferences.putBool("sleep", autoSleep);
- preferences.putInt("sleepTime", sleepTimer);
- // save screen settings
- preferences.putBool("screenSleep", autoScreenOff);
- preferences.putInt("screenTime", screenTimer);
- preferences.putInt("screenPower", screenBrightness);
- preferences.putBool("screenOri", landscape);
- preferences.putBool("SNRCMode", SNRPallete);
- // save pallete settings
- preferences.putInt("currentPallete", pallete);
- // save GPS settings
- preferences.putBool("speedUnit", useKmS);
- preferences.putInt("timeOffset", UTCOffset);
- preferences.putInt("cardinalSpeed", minCardinalSpeed);
- preferences.putBool("prec", usePrecision);
- // save logging settings
- preferences.putBool("GPSLogging", logGPS);
- preferences.putBool("SPDLogging", logSPD);
- preferences.putInt("LogFreq", logGPSfreq);
- // save AOD settings
- preferences.putBool("AODEnabled", useAOD);
- preferences.putBool("clockMode", altAOD);
- preferences.putBool("secondsHand", showSeconds);
- preferences.putBool("batteryIcon", showBattery);
- preferences.putInt("AODBright", AODBrightness);
- preferences.putBool("useCustomPallete", useAODPalette);
- preferences.putInt("cPallete", clockPallete);
- }
- void getSettings() {
- // get power settings
- autoSleep = preferences.getBool("sleep", false);
- sleepTimer = preferences.getInt("sleepTime", 60);
- // get screen settings
- autoScreenOff = preferences.getBool("screenSleep", false);
- screenTimer = preferences.getInt("screenTime", 60);
- screenBrightness = preferences.getInt("screenPower", 10);
- landscape = preferences.getBool("screenOri", true);
- SNRPallete = preferences.getBool("SNRCMode", false);
- // get pallete settings
- pallete = preferences.getInt("currentPallete", 0);
- // get GPS settings
- useKmS = preferences.getBool("speedUnit", false);
- UTCOffset = preferences.getInt("timeOffset", 2);
- minCardinalSpeed = preferences.getInt("cardinalSpeed", 5);
- usePrecision = preferences.getBool("prec", false);
- // get logging settings
- logGPS = preferences.getBool("GPSLogging", false);
- logSPD = preferences.getBool("SPDLogging", false);
- logGPSfreq = preferences.getInt("logFreq", 10);
- // get AOD settings
- useAOD = preferences.getBool("AODEnabled", true);
- altAOD = preferences.getBool("clockMode", true);
- showSeconds = preferences.getBool("secondsHand", false);
- showBattery = preferences.getBool("batteryIcon", false);
- AODBrightness = preferences.getInt("AODBright", 1);
- useAODPalette = preferences.getBool("useCustomPallete", true);
- clockPallete = preferences.getInt("cPallete", 0);
- }
- void handleSettingNumbers(bool* ignoreButtonBool, bool* forceUpdateBool, int* longToChange, int minVal, int increment, unsigned long maxVal) {
- if (clicked == 2 && !*ignoreButtonBool) {
- *ignoreButtonBool = true;
- clicked = -1;
- }
- if (clicked == 1) {
- if (*longToChange - increment >= minVal) {
- *longToChange -= increment;
- *forceUpdateBool = true;
- }
- clicked = -1;
- }
- if (clicked == 2 && ignoreButtonBool) {
- *ignoreButtonBool = false;
- clicked = -1;
- }
- if (clicked == 3) {
- if (*longToChange + increment <= maxVal) {
- *longToChange += increment;
- clicked = -1;
- *forceUpdateBool = true;
- }
- }
- }
- void drawSettingOptions(const String* arrayPointer, int arrayLen, int cursor) {
- u8f.setFont(fontSpecial);
- for (int i = 0; i < arrayLen; i++) {
- if (cursor == i) {
- drawText(arrayPointer[i], (20 * i) + 20, LEFT, palletes[pallete][1]);
- spr.drawRect(0, (i*20)+4, screenWidth, 20, palletes[pallete][1]);
- }
- else {
- drawText(arrayPointer[i], (20 * i) + 20, LEFT, TFT_WHITE);
- }
- }
- }
- byte handleCursorIndex(bool resetIndex, byte maxSetting) {
- static byte cursorIndex = 0;
- if(landscape){ // invert button dir when in landscape mode
- switch (clicked) {
- case 1:
- if(cursorIndex < maxSetting - 1) { cursorIndex++; }
- clicked = -1;
- break;
- case 3:
- if(cursorIndex > 0) { cursorIndex--; }
- clicked = -1;
- break;
- }
- }
- else{
- switch (clicked) {
- case 1: // LEFT BUTTON
- if (cursorIndex > 0) { cursorIndex--; }
- clicked = -1;
- break;
- case 3: // RIGHT BUTTON
- if (cursorIndex < maxSetting - 1) { cursorIndex++; }
- clicked = -1;
- break;
- }
- }
- if (resetIndex) { cursorIndex = 0; }
- return cursorIndex;
- }
- // --------------- BUTTONS ------------------
- void checkButtons(void* pvParameters) {
- byte bLeft = 38;
- byte bCentre = 37;
- byte bRight = 39;
- pinMode(bLeft, INPUT);
- pinMode(bCentre, INPUT);
- pinMode(bRight, INPUT);
- bool pressedLeft = false;
- bool pressedCentre = false;
- bool pressedRight = false;
- gpsPort.begin(9600, SERIAL_8N1, 35, 33);
- while (gpsPort.available()) { delay(1); }
- gpsPort.println("$PCAS01,5*19");
- Serial.println("Command sent!");
- delay(200);
- gpsPort.flush();
- gpsPort.end();
- delay(1000);
- gpsPort.begin(115200, SERIAL_8N1, 35, 33);
- gpsPort.println("$PCAS02,100*1E");
- Serial.println("Core 0 RDY!");
- bootRdy = true;
- unsigned long lastLog;
- for (;;) {
- checkGPS();
- if (digitalRead(bLeft) && !pressedLeft) {
- pressedLeft = true;
- if(screenOn) { clicked = 1; }
- buttonTasks();
- } else if (!digitalRead(bLeft) && pressedLeft) {
- pressedLeft = false;
- }
- if (digitalRead(bCentre) && !pressedCentre) {
- pressedCentre = true;
- if(screenOn) { clicked = 2; }
- buttonTasks();
- } else if (!digitalRead(bCentre) && pressedCentre) {
- pressedCentre = false;
- }
- if (digitalRead(bRight) && !pressedRight) {
- pressedRight = true;
- if(screenOn) { clicked = 3; }
- buttonTasks();
- } else if (!digitalRead(bRight) && pressedRight) {
- pressedRight = false;
- }
- delay(1);
- }
- }
- // tasks that all 3 buttons need to run when pressed
- void buttonTasks() {
- lastPressed = millis();
- setScreenBrightness(screenBrightness);
- }
- void checkGPS() {
- static unsigned long lastLogging;
- while (gps.available( gpsPort )) {
- fix = gps.read();
- gpsData.fixStatus = fix.status;
- // populate struct with GPS data
- // lat/lon/alt
- if(fix.valid.location){
- gpsData.lat = fix.latitude();
- gpsData.lon = fix.longitude();
- gpsData.latP = fix.latitudeL();
- gpsData.lonP = fix.longitudeL();
- gpsData.latDMS = fix.latitudeDMS.degrees;
- gpsData.lonDMS = fix.longitudeDMS.degrees;
- }
- else{
- gpsData.lat = -1;
- gpsData.lon = -1;
- gpsData.lonP = -1;
- gpsData.latP = -1;
- gpsData.latDMS = -1;
- gpsData.lonDMS = -1;
- }
- (fix.valid.altitude) ? gpsData.alt = fix.altitude() : gpsData.alt = -1;
- // speed/hdg
- if(fix.valid.speed) {
- gpsData.spd = fix.speed_kph(); // km/h
- gpsData.spdS = fix.speed_kph() / 3.6; // m/s
- }
- else{
- gpsData.spd = -1;
- gpsData.spdS = -1;
- }
- (fix.valid.heading) ? gpsData.hdg = fix.heading() : gpsData.hdg = -1;
- // if(gpsData.spd > 0 && !useKmS){ gpsData.spd /= 3,6; }
- // if(fix.valid.velned){
- fix.calculateNorthAndEastVelocityFromSpeedAndHeading();
- if(useKmS){
- gpsData.velN = fix.velocity_north / 27,778;
- gpsData.velE = fix.velocity_east / 27,778;
- gpsData.velD = fix.velocity_down / 27,778;
- }
- else{
- gpsData.velN = fix.velocity_north / 100;
- gpsData.velE = fix.velocity_east / 100;
- gpsData.velD = fix.velocity_down / 100;
- }
- // }
- // else{
- // gpsData.velN = -1;
- // gpsData.velE = -1;
- // gpsData.velD = -1;
- // }
- // (fix.valid.lat_err) ? gpsData.latErr = fix.lat_err() : gpsData.latErr = -1;
- // (fix.valid.lon_err) ? gpsData.lonErr = fix.lon_err() : gpsData.lonErr = -1;
- // (fix.valid.alt_err) ? gpsData.altErr = fix.alt_err() : gpsData.altErr = -1;
- // update time
- if(fix.valid.time){
- // add UTC offset to date/time
- NeoGPS::clock_t seconds = fix.dateTime;
- seconds += (UTCOffset*3600);
- fix.dateTime = seconds;
- int GPShr = fix.dateTime.hours;
- //GPShr %= 24;
- String GPStimeTemp;
- if(GPShr < 10) { GPStimeTemp += "0"; } // add leading 0 if needed
- GPStimeTemp += String(GPShr) + ":";
- if(fix.dateTime.minutes < 10) { GPStimeTemp += "0"; }
- GPStimeTemp += String(fix.dateTime.minutes);
- gpsData.time = GPStimeTemp;
- gpsData.timeSeconds = fix.dateTime.seconds;
- }
- else { gpsData.time = "inv"; }
- if(fix.valid.date){
- gpsData.GPSmonth = fix.dateTime.month;
- gpsData.GPSday = fix.dateTime.date;
- gpsData.GPSyear = fix.dateTime.year;
- //gpsData.GPSdow = fix.dateTime.day;
- }
- else{
- gpsData.GPSmonth = -1;
- gpsData.GPSdow = -1;
- gpsData.GPSyear = -1;
- gpsData.GPSdow = -1;
- }
- // get ( tracked ) sat count
- if (fix.valid.satellites) {
- gpsData.totalSats = fix.satellites; // + 1; // seems to be an extra entry in last position of array?
- if(fix.satellites > 0){
- byte trackedNum = 0;
- for(int i = 0; i < fix.satellites; i++){
- if(gps.satellites[i].tracked) { trackedNum++; }
- }
- gpsData.sats = trackedNum;
- }
- }
- else {
- gpsData.sats = -1;
- gpsData.totalSats = -1;
- }
- // calculate avg SNR if fix available
- if(gpsData.sats > 0){
- byte inactive = 0;
- int tempAvgSNR = 0;
- for(int i = 0; i < gpsData.totalSats; i++){
- byte snr = gps.satellites[i].snr;
- (snr) ? tempAvgSNR += snr : inactive++;
- }
- if(gpsData.totalSats - inactive > 0){
- tempAvgSNR /= (gpsData.totalSats - inactive);
- gpsData.SNR = tempAvgSNR;
- }
- }
- else { gpsData.SNR = -1; }
- // log data if setting calls for it
- if(millis() - lastLogging > (logGPSfreq*1000)){
- lastLogging = millis();
- if(logGPS){
- String log;
- if (fix.valid.location) {
- log += "[" + String(fix.latitude(), 6) + "," + String(fix.longitude(), 6) + "],";
- }
- else{ log += "[NO VALID LOCATION],"; }
- if (fix.valid.altitude) {
- log += "[" + String(fix.altitude()) + "],";
- }
- else { log += "[NO VALID ALTITUDE],"; }
- if(fix.valid.time){
- log += "[" + gpsData.time + ":" + String(fix.dateTime.seconds) + "]";
- }
- else { log += "[NO VALID TIME]"; }
- logData("/GPSLog.txt", log);
- }
- if(logSPD){
- String log;
- if (fix.valid.speed) {
- log += "[" + String(fix.speed_kph()) + "],";
- }
- else { log += "[NO VALID SPEED],"; }
- if (fix.valid.heading) {
- log += "[" + String(fix.heading()) + "],";
- }
- else{ log += "[NO VALID HDG],"; }
- if(fix.valid.time){
- log += "[" + gpsData.time + ":" + String(fix.dateTime.seconds) + "]";
- }
- else { log += "[NO VALID TIME]"; }
- logData("/SPDLog.txt", log);
- }
- }
- }
- }
- // --------------- SD ------------------
- void logData(const char* path, String message) {
- if (!hasSD) { return; }
- File file = SD.open(path, FILE_APPEND);
- file.println(message);
- file.close();
- }
- // --------------- TEXT ------------------
- // only passes right x/y to function below
- void drawText(String text, int y, directions dir, uint16_t color) {
- u8f.setForegroundColor(color);
- int textW = u8f.getUTF8Width(text.c_str());
- switch (dir) {
- case LEFT:
- drawText(text, 0 + paddingL, y, color);
- break;
- case RIGHT:
- drawText(text, (screenWidth - textW) - paddingR, y, color);
- break;
- case CENTER: // TODO: make offset toggleable
- (landscape) ? drawText(text, (screenWidth / 2) + 15 - (textW / 2), y, color) : drawText(text, (screenWidth / 2) - textW / 2, y, color);
- break;
- case CENTER_NO:
- drawText(text, (screenWidth / 2) - (textW / 2), y, color);
- break;
- }
- }
- // draws the actual text
- void drawText(String text, int x, int y, uint16_t color) {
- u8f.setForegroundColor(color);
- u8f.setCursor(x, y);
- int textW = u8f.getUTF8Width(text.c_str());
- int textH = u8f.getFontAscent() - u8f.getFontDescent();
- //tft.fillRect(x - clearPaddingL, y - u8f.getFontAscent() - 1, textW + (clearPaddingR * 2), textH, TFT_BLACK);
- u8f.print(text);
- }
- // 0 - 10 ( 0 - 255)
- void setScreenBrightness(int brightness) {
- int bValue = map(brightness, 0, 10, 0, 255);
- if (brightness == 0) {
- tft.fillScreen(TFT_BLACK);
- analogWrite(TFT_BL, 0);
- } else {
- //ledcWrite(0, bValue);
- analogWrite(TFT_BL, bValue);
- }
- }
- // --------------- GPS ------------------
- void sendGPSCommand(GPSspeed spd) {
- while (Serial2.available()) { delay(1); } //wait for GPS to be silent
- Serial2.println(GPScommands[spd][0]); //send command
- Serial.println("Command sent: " + GPScommands[spd][0]);
- }
- // --------------- IP5306 ------------------
- void ip5306_set_bits(uint8_t reg, uint8_t index, uint8_t bits, uint8_t value) {
- uint8_t mask = (1 << bits) - 1;
- int v = ip5306_get_reg(reg);
- if (v < 0) {
- Serial.printf("ip5306_get_reg fail: 0x%02x\n", reg);
- return;
- }
- v &= ~(mask << index);
- v |= ((value & mask) << index);
- if (ip5306_set_reg(reg, v)) {
- Serial.printf("ip5306_set_bits fail: 0x%02x\n", reg);
- }
- }
- uint8_t ip5306_get_bits(uint8_t reg, uint8_t index, uint8_t bits) {
- int value = ip5306_get_reg(reg);
- if (value < 0) {
- Serial.printf("ip5306_get_bits fail: 0x%02x\n", reg);
- return 0;
- }
- return (value >> index) & ((1 << bits) - 1);
- }
- int ip5306_get_reg(uint8_t reg) {
- Wire.beginTransmission(0x75);
- Wire.write(reg);
- if (Wire.endTransmission(false) == 0 && Wire.requestFrom(0x75, 1)) {
- return Wire.read();
- }
- return -1;
- }
- int ip5306_set_reg(uint8_t reg, uint8_t value) {
- Wire.beginTransmission(0x75);
- Wire.write(reg);
- Wire.write(value);
- if (Wire.endTransmission(true) == 0) {
- return 0;
- }
- return -1;
- }
- // returns battery lvl in %
- byte getBatLevel() {
- static byte batLvl = 0;
- static unsigned long last = 0;
- // only check status once per 5s
- if(millis() - last > 5000){
- last = millis();
- uint8_t bytes = (~ip5306_get_bits(IP5306_REG_READ_4, 4, 4)) & 0x0F;
- batLvl = 0; // reset before next reading
- if (bytes & 0x01) { batLvl += 25; }
- if (bytes & 0x02) { batLvl += 25; }
- if (bytes & 0x04) { batLvl += 25; }
- if (bytes & 0x08) { batLvl += 25; }
- }
- return batLvl;
- }
- bool getCharging(){
- static bool charging = false;
- static unsigned long last = 0;
- // only check status once per 5s
- if(millis() - last > 5000){
- last = millis();
- // if we're powered from VCC ( plugged in ) and the battery isn't full, we're charging
- (ip5306_get_bits(IP5306_REG_READ_0, 3, 1) && !ip5306_get_bits(IP5306_REG_READ_1, 3, 1)) ? charging = true : charging = false;
- }
- return charging;
- }
- float mapF(float x, float in_min, float in_max, float out_min, float out_max){
- return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement