diff --git a/README.md b/README.md index d8ce1e5d..f0fc0bef 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ ESP32 Based GPS Navigator (LVGL - LovyanGFX). |:-:|:-:|:-:| | Add Waypoint | Add Waypoint (landscape) | Waypoint List | -|||||| +|||||| |:-:|:-:|:-:|:-:|:-:| | Settings | Compass Calibration | Touch Calibration | Map Settings | Device Settings | @@ -84,8 +84,6 @@ If the board has a BOOT button (GPIO0) it is possible to use power saving functi To do this, simply include the following Build Flag in the required env in platformio.ini ```-DPOWER_SAVE```
-```-DARDUINO_RUNNING_CORE=1```
-```-DARDUINO_EVENT_RUNNING_CORE=1```
> [!IMPORTANT] > Currently, this project can run on any board with an ESP32S3 and at least a 320x480 TFT screen. The idea is to support all existing boards on the market that I can get to work, so if you don't want to use the specific IceNav board, please feel free to create an issue, and I will look into providing support. @@ -107,10 +105,10 @@ To do this, simply include the following Build Flag in the required env in platf |:------------|:--------------|:-----------------------------------|:-------------------------------------------------------| | | 🔋 Batt. Monitor | ```-DADC1``` or ```-DADC2```
```-DBATT_PIN=ADCn_CHANNEL_x``` | | | AT6558D | 🛰️ GPS | ```-DAT6558D_GPS``` | | -| HMC5883L | 🧭 Compass | ```-DHMC5883L``` | ```dfrobot/DFRobot_QMC5883@^1.0.0``` | -| QMC5883 | 🧭 Compass | ```-DQMC5883``` | ```dfrobot/DFRobot_QMC5883@^1.0.0``` | -| MPU9250 | 🧭 IMU (Compass) | ```-DIMU_MPU9250``` | ```bolderflight/Bolder Flight Systems MPU9250@^1.0.2```| -| BME280 | 🌡️ Temp
☁️ Pres
💧 Hum | ```-DBME280``` | ```adafruit/Adafruit Unified Sensor@^1.1.14```
```adafruit/Adafruit BusIO@^1.16.1```
```adafruit/Adafruit BME280 Library@^2.2.4```| +| HMC5883L | 🧭 Compass | ```-DHMC5883L``` | ```dfrobot/DFRobot_QMC5883@1.0.0``` | +| QMC5883 | 🧭 Compass | ```-DQMC5883``` | ```dfrobot/DFRobot_QMC5883@1.0.0``` | +| MPU9250 | 🧭 IMU (Compass) | ```-DIMU_MPU9250``` | ```bolderflight/Bolder Flight Systems MPU9250@1.0.2```| +| BME280 | 🌡️ Temp
☁️ Pres
💧 Hum | ```-DBME280``` | ```adafruit/Adafruit Unified Sensor@1.1.14```
```adafruit/Adafruit BusIO@1.16.2```
```adafruit/Adafruit BME280 Library@2.2.4```| [^1]: For ELECROW board UART port is shared with USB connection, GPS pinout are mapped to IO19 and IO40 (Analog and Digital Port). If CLI isn't used is possible to attach GPS module to UART port but for upload the firmware (change pinout at **hal.hpp**), the module should be disconnected. [^2]: See **hal.hpp** for pinouts configuration @@ -210,6 +208,8 @@ Please follow the instructions provided by [OSM_Extract](https://github.com/ares > pio run --target uploadfs > ``` +> [!TIP] +> Optional, firmware upgrade is possible from SD Card, please see [PR #259](https://github.com/jgauchia/IceNav-v3/pull/259) for detailed instructions > [!TIP] > Optional, for map debugging with specific coordinates, or when you are in indoors, you are able to set the defaults coordinates, on two ways: @@ -248,7 +248,7 @@ outnmea: toggle GPS NMEA output (or Ctrl+C to stop) poweroff: perform a ESP32 deep sleep reboot: perform a ESP32 reboot scshot: screenshot to SD or sending a PC -settings: device settings +setdstzone: set DST (Daylight Saving Time zone: NONE, EU or USA) waypoint: waypoint utilities webfile: enable/disable Web file server wipe: wipe preferences to factory default @@ -270,6 +270,7 @@ Some extra details: VmaxBatt custom VminBatt custom tempOffs custom + defGMT custom ``` **kset KEYNAME**: Set user custom settings: @@ -300,8 +301,6 @@ nc -l -p 8123 > screenshot.png Additionally, you can download the screenshot with webfile server. -**settings**: Device settings type `settings` for detailed options. - **waypoint**: type `waypoint` for detailed options. Additionally, this waypoint command can send the waypoint over WiFi using the following syntax (replace IP with your PC IP): @@ -338,7 +337,7 @@ To access the Web File Server, simply use any browser and go to the following ad - [X] Vector maps - [ ] Google Maps navigation style - [x] Optimize code -- [ ] Fix bugs! +- [X] Fix bugs! - [X] Web file server @@ -362,10 +361,11 @@ To access the Web File Server, simply use any browser and go to the following ad * OSM to binary vectorial maps [OSM_Extract](https://github.com/aresta/OSM_Extract) thanks to [@aresta](https://github.com/aresta) * Preferences Library [Easy Preferences](https://github.com/hpsaturn/easy-preferences) thanks to [@hpsaturn](https://github.com/hpsaturn) * Wifi CLI manager [esp32-wifi-cli](https://github.com/hpsaturn/esp32-wifi-cli) thanks to [@hpsaturn](https://github.com/hpsaturn) -* Web file server based in [@smford](https://github.com/smford) [esp32-asyncwebserver-fileupload-example ](https://github.com/smford/esp32-asyncwebserver-fileupload-example) +* Web file server based in [@smford](https://github.com/smford) [esp32-asyncwebserver-fileupload-example](https://github.com/smford/esp32-asyncwebserver-fileupload-example) +* Solar sunset and sunrise [SolarCalculator](https://github.com/jpb10/SolarCalculator) thanks to [@jpb10](https://github.com/jpb10) --- Map data is available thanks to the great OpenStreetMap project and contributors. The map data is available under the Open Database License. -© OpenStreetMap contributors +[© OpenStreetMap contributors](https://www.openstreetmap.org/copyright) diff --git a/boards/elecrow-esp32-s3-n16r8v-terminal.json b/boards/elecrow-esp32-s3-n16r8v-terminal.json index 730b6480..1bdd7ad9 100644 --- a/boards/elecrow-esp32-s3-n16r8v-terminal.json +++ b/boards/elecrow-esp32-s3-n16r8v-terminal.json @@ -8,9 +8,7 @@ "core": "esp32", "extra_flags": [ "-DBOARD_HAS_PSRAM", - "-DARDUINO_USB_MODE=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_USB_MODE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/icenav-esp32-s3.json b/boards/icenav-esp32-s3.json index ef141a4a..19728ee6 100644 --- a/boards/icenav-esp32-s3.json +++ b/boards/icenav-esp32-s3.json @@ -11,8 +11,6 @@ "-DBOARD_HAS_PSRAM", "-DARDUINO_USB_MODE=1", "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1", "-DPOWER_SAVE", "-DADC2", "-DBATT_PIN=ADC2_CHANNEL_6", diff --git a/data/sunrise.bin b/data/sunrise.bin new file mode 100644 index 00000000..6a70faa7 Binary files /dev/null and b/data/sunrise.bin differ diff --git a/data/sunset.bin b/data/sunset.bin new file mode 100644 index 00000000..7985c285 Binary files /dev/null and b/data/sunset.bin differ diff --git a/images/dev/compass.jpg b/images/dev/compass.jpg index 1bc9290d..952c33af 100644 Binary files a/images/dev/compass.jpg and b/images/dev/compass.jpg differ diff --git a/images/dev/devicesettings.jpg b/images/dev/devicesettings.jpg deleted file mode 100644 index 8547b0db..00000000 Binary files a/images/dev/devicesettings.jpg and /dev/null differ diff --git a/images/dev/devicesettings.png b/images/dev/devicesettings.png new file mode 100644 index 00000000..1d59e155 Binary files /dev/null and b/images/dev/devicesettings.png differ diff --git a/include/hal.hpp b/include/hal.hpp index 551f118b..d96d0f30 100644 --- a/include/hal.hpp +++ b/include/hal.hpp @@ -2,8 +2,8 @@ * @file hal.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Boards Pin definitions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef HAL_HPP diff --git a/lib/battery/battery.cpp b/lib/battery/battery.cpp index 80ae3446..fc9baecd 100644 --- a/lib/battery/battery.cpp +++ b/lib/battery/battery.cpp @@ -2,80 +2,78 @@ * @file battery.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Battery monitor definition and functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "battery.hpp" -/** - * @brief Battery values - * - */ -uint8_t battLevel = 0; -uint8_t battLevelOld = 0; -float batteryMax = 4.2; // maximum voltage of battery -float batteryMin = 3.6; // minimum voltage of battery before shutdown +Battery::Battery() {} /** * @brief Configure ADC Channel for battery reading * */ -void initADC() +void Battery::initADC() { - // When VDD_A is 3.3V: - // 0dB attenuation (ADC_ATTEN_DB_0) gives full-scale voltage 1.1V - // 2.5dB attenuation (ADC_ATTEN_DB_2_5) gives full-scale voltage 1.5V - // 6dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2V - // 12dB attenuation (ADC_ATTEN_DB_12) gives full-scale voltage 3.9V - - #ifdef ADC1 +#ifdef ADC1 adc1_config_width(ADC_WIDTH_BIT_12); - adc1_config_channel_atten(BATT_PIN, ADC_ATTEN_DB_12); - #endif + adc1_config_channel_atten(BATT_PIN, ADC_ATTEN_DB_12); +#endif - #ifdef ADC2 +#ifdef ADC2 adc2_config_channel_atten(BATT_PIN, ADC_ATTEN_DB_12); - #endif +#endif +} + +/** + * @brief Set battery voltage levels + * + * @param maxVoltage -> Full Charge voltage + * @param minVoltage -> Min Charge voltage + */ +void Battery::setBatteryLevels(float maxVoltage, float minVoltage) +{ + batteryMax = maxVoltage; + batteryMin = minVoltage; } /** - * @brief Read battery charge and return % + * @brief Read battery charge and return %. * * @return float -> % Charge */ -float batteryRead() +float Battery::readBattery() { - long sum = 0; // sum of samples taken - float voltage = 0.0; // calculated voltage - float output = 0.0; // output value - for (int i = 0; i < 100; i++) - { + long sum = 0; // Sum of samples taken + float voltage = 0.0; // Calculated voltage + float output = 0.0; // Output value + + for (int i = 0; i < 100; i++) + { + #ifdef ADC1 + sum += static_cast(adc1_get_raw(BATT_PIN)); + #endif + + #ifdef ADC2 + int readRaw; + esp_err_t r = adc2_get_raw(BATT_PIN, ADC_WIDTH_BIT_12, &readRaw); + if (r == ESP_OK) + sum += static_cast(readRaw); + #endif - #ifdef ADC1 - sum += (long)adc1_get_raw(BATT_PIN); - #endif + delayMicroseconds(150); + } - #ifdef ADC2 - int readRaw; - esp_err_t r = adc2_get_raw(BATT_PIN, ADC_WIDTH_BIT_12, &readRaw); - if (r == ESP_OK) - sum += (long)readRaw; - #endif + voltage = sum / 100.0; + // Custom board has a divider circuit + constexpr float R1 = 100000.0; // Resistance of R1 (100K) + constexpr float R2 = 100000.0; // Resistance of R2 (100K) + voltage = (voltage * V_REF) / 4096.0; + voltage = voltage / (R2 / (R1 + R2)); + voltage = roundf(voltage * 100) / 100; - delayMicroseconds(150); - } - voltage = sum / (float)100; - // custom board has a divider circuit - float R1 = 100000.0; // resistance of R1 (100K) - float R2 = 100000.0; // resistance of R2 (100K) - voltage = (voltage * V_REF) / 4096.0; - voltage = voltage / (R2 / (R1 + R2)); - voltage = roundf(voltage * 100) / 100; - output = ((voltage - batteryMin) / (batteryMax - batteryMin)) * 100; - if (output <= 160) - return output; - else - return 0.0f; + output = ((voltage - batteryMin) / (batteryMax - batteryMin)) * 100; + return (output <= 160) ? output : 0.0f; } diff --git a/lib/battery/battery.hpp b/lib/battery/battery.hpp index b85ed78d..70f729db 100644 --- a/lib/battery/battery.hpp +++ b/lib/battery/battery.hpp @@ -2,8 +2,8 @@ * @file battery.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Battery monitor definition and functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef BATTERY_HPP @@ -13,16 +13,19 @@ #include #include -static esp_adc_cal_characteristics_t characteristics; -#define V_REF 3.9 // ADC reference voltage +class Battery +{ +private: + float batteryMax; + float batteryMin; + static constexpr float V_REF = 3.9; // ADC reference voltage -extern float batteryMax; // 4.2; // maximum voltage of battery -extern float batteryMin; // 3.6; // minimum voltage of battery before shutdown +public: + Battery(); -extern uint8_t battLevel; -extern uint8_t battLevelOld; - -void initADC(); -float batteryRead(); + void initADC(); + void setBatteryLevels(float maxVoltage, float minVoltage); + float readBattery(); +}; #endif diff --git a/lib/bme/bme.cpp b/lib/bme/bme.cpp index 59e72dad..e85c31ac 100644 --- a/lib/bme/bme.cpp +++ b/lib/bme/bme.cpp @@ -2,8 +2,8 @@ * @file bme.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief BME280 Sensor functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "bme.hpp" diff --git a/lib/bme/bme.hpp b/lib/bme/bme.hpp index d9b23178..b7e404b8 100644 --- a/lib/bme/bme.hpp +++ b/lib/bme/bme.hpp @@ -2,8 +2,8 @@ * @file bme.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief BME280 Sensor functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef BME_HPP diff --git a/lib/cli/cli.cpp b/lib/cli/cli.cpp index 6d836280..860f0e35 100644 --- a/lib/cli/cli.cpp +++ b/lib/cli/cli.cpp @@ -3,7 +3,7 @@ * @author @Hpsaturn * @brief Network CLI and custom internal commands * @version Using https://github.com/hpsaturn/esp32-wifi-cli.git - * @date 2024-11 + * @date 2024-12 */ #ifndef DISABLE_CLI @@ -22,15 +22,27 @@ const char logo[] = "" ; +extern Power power; + +/** + * @brief Reboot ESP + */ void wcli_reboot(char *args, Stream *response) { ESP.restart(); } -void wcli_poweroff(char *args, Stream *response) { - deviceSuspend(); +/** + * @brief ESP Deep Sleep/shutdown + */ +void wcli_poweroff(char *args, Stream *response) +{ + power.deviceShutdown(); } +/** + * @brief Display device info + */ void wcli_info(char *args, Stream *response) { setlocale(LC_NUMERIC, ""); @@ -62,6 +74,9 @@ void wcli_info(char *args, Stream *response) response->printf("GPS Rx GPIO:\t: %i\r\n",GPS_RX); } +/** + * @brief Clear user settings + */ void wcli_swipe(char *args, Stream *response) { Pair operands = wcli.parseCommand(args); @@ -72,11 +87,17 @@ void wcli_swipe(char *args, Stream *response) response->println("done"); } +/** + * @brief Clear CLI console + */ void wcli_clear(char *args, Stream *response) { wcli.shell->clear(); } +/** + * @brief Take a screenshot + */ void wcli_scshot(char *args, Stream *response) { Pair operands = wcli.parseCommand(args); @@ -143,6 +164,9 @@ void wcli_kset(char *args, Stream *response) } } +/** + * @brief Waypoint list, download or delete + */ void wcli_waypoint(char *args, Stream *response) { Pair operands = wcli.parseCommand(args); @@ -267,53 +291,19 @@ void wcli_waypoint(char *args, Stream *response) } } -void wcli_settings(char *args, Stream *response) +/** + * @brief Output NMEA sentences in CLI + */ +void wcli_outnmea (char *args, Stream *response) { - Pair operands = wcli.parseCommand(args); - String commands = operands.first(); - String value = operands.second(); - int8_t gpio = -1; - - if (commands.isEmpty()) - { - response->println(""); - response->println(F( "\033[1;31m----\033[1;32m Available commands \033[1;31m----\033[0;37m\r\n" )); - response->println(F( "\033[1;32msetgpstx:\t\033[0;37mset GPS Tx GPIO")); - response->println(F( "\033[1;32msetgpsrx:\t\033[0;37mset GPS Rx GPIO")); - } - else if (commands.equals("setgpstx")) - { - if(value.isEmpty()) - response->println(F("Tx GPIO missing, use: setgpstx \033[1;32mGPIO\033[0;37m")); - else - { - gpio = value.toInt(); - saveGpsGpio(gpio, -1); - response->println(""); - response->printf("GPS \033[1;31mTx GPIO\033[0;37m set to: \033[1;32m%i\033[0;37m\r\n",gpio); - response->println("Please reboot device"); - } - } - else if (commands.equals("setgpsrx")) - { - if(value.isEmpty()) - response->println(F("Rx GPIO missing, use: setgpsrx \033[1;32mGPIO\033[0;37m")); - else - { - gpio = value.toInt(); - saveGpsGpio(-1, gpio); - response->println(""); - response->printf("GPS \033[1;31mRx GPIO\033[0;37m set to: \033[1;32m%i\033[0;37m\r\n",gpio); - response->println("Please reboot device"); - } - } -} - -void wcli_outnmea (char *args, Stream *response){ nmea_output_enable = !nmea_output_enable; } -void wcli_abort_handler () { +/** + * @brief Cancel NMEA Output + */ +void wcli_abort_handler () +{ if (nmea_output_enable) { nmea_output_enable = false; delay(100); @@ -321,6 +311,9 @@ void wcli_abort_handler () { } } +/** + * @brief Webfile server enable/disable option + */ void wcli_webfile(char *args, Stream *response) { Pair operands = wcli.parseCommand(args); @@ -347,6 +340,25 @@ void wcli_webfile(char *args, Stream *response) } } +/** + * @brief Set DST (daylight saving time) zone EU or USA + */ +void wcli_setdst(char *args, Stream *response) +{ + Pair operands = wcli.parseCommand(args); + String commands = operands.first(); + if (commands.isEmpty()) + response->println(F("missing parameter use: setdstzone \033[1;32mNONE/EU/USA\033[0;37m")); + else + { + commands.toUpperCase(); + if(commands.equals("NONE") || commands.equals("EU") || commands.equals("USA") ) + cfg.saveAuto("defDST",commands); + else + response->println(F("wrong parameter use: \033[1;32mNONE/EU/USA\033[0;37m")); + } +} + void initRemoteShell() { #ifndef DISABLE_CLI_TELNET @@ -354,7 +366,8 @@ void initRemoteShell() #endif } -void initShell(){ +void initShell() +{ wcli.shell->attachLogo(logo); wcli.setSilentMode(true); // Main Commands: @@ -365,11 +378,11 @@ void initShell(){ wcli.add("clear", &wcli_clear, "\t\tclear shell"); wcli.add("scshot", &wcli_scshot, "\tscreenshot to SD or sending a PC"); wcli.add("waypoint", &wcli_waypoint, "\twaypoint utilities"); - wcli.add("settings", &wcli_settings, "\tdevice settings"); wcli.add("webfile", &wcli_webfile, "\tenable/disable Web file server"); wcli.add("klist", &wcli_klist, "\t\tlist of user preferences. ('all' param show all)"); wcli.add("kset", &wcli_kset, "\t\tset an user extra preference"); wcli.add("outnmea", &wcli_outnmea, "\ttoggle GPS NMEA output (or Ctrl+C to stop)"); + wcli.add("setdstzone", &wcli_setdst, "\tset DST (Daylight Saving Time zone: NONE, EU or USA)"); wcli.shell->overrideAbortKey(&wcli_abort_handler); wcli.begin("IceNav"); } diff --git a/lib/cli/cli.hpp b/lib/cli/cli.hpp index 88d87a2c..6dcf0586 100644 --- a/lib/cli/cli.hpp +++ b/lib/cli/cli.hpp @@ -3,7 +3,7 @@ * @author @Hpsaturn * @brief Network CLI and custom internal commands * @version Using https://github.com/hpsaturn/esp32-wifi-cli.git - * @date 2024-11 + * @date 2024-12 */ #ifndef CLI_HPP diff --git a/lib/cli/utils.h b/lib/cli/utils.h index 4e327594..4fb9b613 100644 --- a/lib/cli/utils.h +++ b/lib/cli/utils.h @@ -2,8 +2,8 @@ * @file utils.h * @author @Hpsaturn * @brief Network CLI and custom internal commands - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef UTILS_H diff --git a/lib/compass/compass.cpp b/lib/compass/compass.cpp index 73c55089..8ab3893d 100644 --- a/lib/compass/compass.cpp +++ b/lib/compass/compass.cpp @@ -2,8 +2,8 @@ * @file compass.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Compass definition and functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "compass.hpp" diff --git a/lib/compass/compass.hpp b/lib/compass/compass.hpp index cf08bc33..2a747622 100644 --- a/lib/compass/compass.hpp +++ b/lib/compass/compass.hpp @@ -2,8 +2,8 @@ * @file compass.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Compass definition and functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef COMPASS_HPP diff --git a/lib/gps/gps.cpp b/lib/gps/gps.cpp index 60c2284f..e7bdf80c 100644 --- a/lib/gps/gps.cpp +++ b/lib/gps/gps.cpp @@ -2,8 +2,8 @@ * @file gps.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief GPS definition and functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "gps.hpp" @@ -138,8 +138,15 @@ void getGPSData() // Time and Date if (fix.valid.time && fix.valid.date) { - adjustTime( fix.dateTime ); + adjustTime( fix.dateTime ); localTime = fix.dateTime; + if (calcSun) + { + // Calculate Sunrise and Sunset only one time when date & time was valid + calculateSun(); + log_v("Get date, time, Sunrise and Sunset"); + calcSun = false; + } } // Altitude @@ -151,8 +158,9 @@ void getGPSData() gpsData.speed = (uint16_t)fix.speed_kph(); // Latitude and Longitude - gpsData.latitude = getLat(); - gpsData.longitude = getLon(); + if (fix.valid.location) + gpsData.latitude = getLat(); + gpsData.longitude = getLon(); // Heading if (fix.valid.heading) diff --git a/lib/gps/gps.hpp b/lib/gps/gps.hpp index 88959c7c..aa03bdb7 100644 --- a/lib/gps/gps.hpp +++ b/lib/gps/gps.hpp @@ -2,8 +2,8 @@ * @file gps.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief GPS definition and functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef GPS_HPP @@ -74,10 +74,15 @@ struct GPSDATA float pdop; float vdop; uint8_t satInView; + char sunriseHour[6]; + char sunsetHour[6]; }; extern GPSDATA gpsData; +static bool calcSun = true; +void calculateSun(); + void initGPS(); double getLat(); double getLon(); diff --git a/lib/gps/timezone.hpp b/lib/gps/timezone.hpp index 99d2d21e..95951e66 100644 --- a/lib/gps/timezone.hpp +++ b/lib/gps/timezone.hpp @@ -2,48 +2,30 @@ * @file timezone.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Time zone adjust - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef TIMEZONE_HPP #define TIMEZONE_HPP -// Set these values to the offset of your timezone from GMT +extern int32_t defGMT; // Default GMT offset +extern String defDST; // Default DST zone +extern bool calculateDST; // Calculate DST flag -static const int32_t zone_hours = 1L; -static const int32_t zone_minutes = 0L; // usually zero -static const NeoGPS::clock_t zone_offset = - zone_hours * NeoGPS::SECONDS_PER_HOUR + - zone_minutes * NeoGPS::SECONDS_PER_MINUTE; +// Calculate DST changeover times once per reset and year! +static NeoGPS::time_t changeover; +static NeoGPS::clock_t springForward, fallBack; - -// Uncomment one DST changeover rule, or define your own: - -//#define USA_DST -#define EU_DST - -#if defined(USA_DST) - static const uint8_t springMonth = 3; - static const uint8_t springDate = 14; // latest 2nd Sunday - static const uint8_t springHour = 2; - static const uint8_t fallMonth = 11; - static const uint8_t fallDate = 7; // latest 1st Sunday - static const uint8_t fallHour = 2; - #define CALCULATE_DST - -#elif defined(EU_DST) - static const uint8_t springMonth = 3; - static const uint8_t springDate = 31; // latest last Sunday - static const uint8_t springHour = 2; - static const uint8_t fallMonth = 10; - static const uint8_t fallDate = 31; // latest last Sunday - static const uint8_t fallHour = 1; - #define CALCULATE_DST -#endif +static uint8_t springMonth = 0; +static uint8_t springDate = 0; // latest last Sunday +static uint8_t springHour = 0; +static uint8_t fallMonth = 0; +static uint8_t fallDate = 0; // latest last Sunday +static uint8_t fallHour = 0; /** - * @brief Update notify bar event + * @brief Adjust Time (GMT and DST) * * @param dt -> GPS Time */ @@ -51,12 +33,34 @@ static void adjustTime( NeoGPS::time_t & dt ) { NeoGPS::clock_t seconds = dt; // convert date/time structure to seconds - #ifdef CALCULATE_DST - // Calculate DST changeover times once per reset and year! - static NeoGPS::time_t changeover; - static NeoGPS::clock_t springForward, fallBack; + // Set these values to the offset of your timezone from GMT + static const int32_t zone_minutes = 0L; // usually zero + static const NeoGPS::clock_t zone_offset = (int32_t)defGMT * NeoGPS::SECONDS_PER_HOUR + + zone_minutes * NeoGPS::SECONDS_PER_MINUTE; + + if (calculateDST) + { + if (defDST.equals("USA")) + { + springMonth = 3; + springDate = 14; // latest 2nd Sunday + springHour = 2; + fallMonth = 11; + fallDate = 7; // latest 1st Sunday + fallHour = 2; + } + if (defDST.equals("EU")) + { + springMonth = 3; + springDate = 31; // latest last Sunday + springHour = 2; + fallMonth = 10; + fallDate = 31; // latest last Sunday + fallHour = 1; + } - if ((springForward == 0) || (changeover.year != dt.year)) { + if ((springForward == 0) || (changeover.year != dt.year)) + { // Calculate the spring changeover time (seconds) changeover.year = dt.year; @@ -79,18 +83,41 @@ static void adjustTime( NeoGPS::time_t & dt ) changeover.date -= (changeover.day - NeoGPS::time_t::SUNDAY); fallBack = (NeoGPS::clock_t) changeover; } - #endif + } // First, offset from UTC to the local timezone seconds += zone_offset; - #ifdef CALCULATE_DST + if (calculateDST) + { // Then add an hour if DST is in effect if ((springForward <= seconds) && (seconds < fallBack)) seconds += NeoGPS::SECONDS_PER_HOUR; - #endif + } dt = seconds; // convert seconds back to a date/time structure } + +/** + * @brief convert hour to HH:MM rounded + * + * @param h -> hour + * @param str -> HH:MM text format + */ +static char * hoursToString(double h, char *str) +{ + int m = int(round(h * 60)); + int hr = (m / 60) % 24; + int mn = m % 60; + + str[0] = (hr / 10) % 10 + '0'; + str[1] = (hr % 10) + '0'; + str[2] = ':'; + str[3] = (mn / 10) % 10 + '0'; + str[4] = (mn % 10) + '0'; + str[5] = '\0'; + return str; +} + #endif \ No newline at end of file diff --git a/lib/gpx/src/addWaypoint.cpp b/lib/gpx/src/addWaypoint.cpp index 2b05770a..4bd29f64 100644 --- a/lib/gpx/src/addWaypoint.cpp +++ b/lib/gpx/src/addWaypoint.cpp @@ -2,13 +2,13 @@ * @file addWaypoint.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Add Waypoint functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "addWaypoint.hpp" -extern const int SD_CS; +extern const uint8_t SD_CS; wayPoint addWpt = {0, 0, 0, (char *)"", (char *)"", (char *)"", (char *)"", (char *)"", (char *)"", 0, 0, 0, 0}; wayPoint loadWpt = {0, 0, 0, (char *)"", (char *)"", (char *)"", (char *)"", (char *)"", (char *)"", 0, 0, 0, 0}; diff --git a/lib/gpx/src/addWaypoint.hpp b/lib/gpx/src/addWaypoint.hpp index 809571b0..c97ffdc8 100644 --- a/lib/gpx/src/addWaypoint.hpp +++ b/lib/gpx/src/addWaypoint.hpp @@ -2,19 +2,15 @@ * @file addWaypoint.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Add Waypoint functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef ADDWAYPOINT_HPP #define ADDWAYPOINT_HPP -#include "globalGpxDef.h" #include "SD.h" -#include "FS.h" -#include "tft.hpp" -#include "storage.hpp" -#include "lvgl.h" +#include "globalGpxDef.h" extern wayPoint addWpt; diff --git a/lib/gpx/src/deleteWaypoint.cpp b/lib/gpx/src/deleteWaypoint.cpp index e453453a..b93ebd5d 100644 --- a/lib/gpx/src/deleteWaypoint.cpp +++ b/lib/gpx/src/deleteWaypoint.cpp @@ -2,8 +2,8 @@ * @file deleteWaypoint.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Delete Waypoint functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "deleteWaypoint.hpp" diff --git a/lib/gpx/src/deleteWaypoint.hpp b/lib/gpx/src/deleteWaypoint.hpp index d21ad13e..49b73b59 100644 --- a/lib/gpx/src/deleteWaypoint.hpp +++ b/lib/gpx/src/deleteWaypoint.hpp @@ -2,18 +2,14 @@ * @file deleteWaypoint.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Delete Waypoint functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef DELETEWAYPOINT_HPP #define DELETEWAYPOINT_HPP #include "SD.h" -#include "FS.h" -#include "tft.hpp" -#include "storage.hpp" -#include "globalGuiDef.h" #include "globalGpxDef.h" void deleteWaypointName(char * wpt); diff --git a/lib/gpx/src/editWaypoint.cpp b/lib/gpx/src/editWaypoint.cpp index e3651712..8802c56f 100644 --- a/lib/gpx/src/editWaypoint.cpp +++ b/lib/gpx/src/editWaypoint.cpp @@ -2,8 +2,8 @@ * @file editWaypoint.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Edit Waypoint functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "editWaypoint.hpp" diff --git a/lib/gpx/src/editWaypoint.hpp b/lib/gpx/src/editWaypoint.hpp index fe4026e0..939833c6 100644 --- a/lib/gpx/src/editWaypoint.hpp +++ b/lib/gpx/src/editWaypoint.hpp @@ -2,18 +2,14 @@ * @file editWaypoint.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Edit Waypoint functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef EDITWAYPOINT_HPP #define EDITWAYPOINT_HPP #include "SD.h" -#include "FS.h" -#include "tft.hpp" -#include "storage.hpp" -#include "globalGuiDef.h" #include "globalGpxDef.h" void editWaypointName(char* oldName, char *newName); diff --git a/lib/gpx/src/globalGpxDef.h b/lib/gpx/src/globalGpxDef.h index 04741142..2dc545ec 100644 --- a/lib/gpx/src/globalGpxDef.h +++ b/lib/gpx/src/globalGpxDef.h @@ -2,8 +2,8 @@ * @file globalGpxDef.h * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Global GPX Variables - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ diff --git a/lib/gpx/src/loadWaypoint.cpp b/lib/gpx/src/loadWaypoint.cpp index 2a8b4802..c14ae479 100644 --- a/lib/gpx/src/loadWaypoint.cpp +++ b/lib/gpx/src/loadWaypoint.cpp @@ -2,8 +2,8 @@ * @file loadWaypoint.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Load Waypoint functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "loadWaypoint.hpp" diff --git a/lib/gpx/src/loadWaypoint.hpp b/lib/gpx/src/loadWaypoint.hpp index 678dcf69..182ee6d6 100644 --- a/lib/gpx/src/loadWaypoint.hpp +++ b/lib/gpx/src/loadWaypoint.hpp @@ -2,18 +2,13 @@ * @file loadWaypoint.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Load Waypoint functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef LOADWAYPOINT_HPP #define LOADWAYPOINT_HPP -#include "SD.h" -#include "FS.h" -#include "tft.hpp" -#include "storage.hpp" -#include "globalGuiDef.h" #include "globalGpxDef.h" extern wayPoint loadWpt; diff --git a/lib/gui/src/buttonBar.cpp b/lib/gui/src/buttonBar.cpp index 4c22c2b1..26552b77 100644 --- a/lib/gui/src/buttonBar.cpp +++ b/lib/gui/src/buttonBar.cpp @@ -2,15 +2,11 @@ * @file buttonBar.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Button Bar - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "buttonBar.hpp" -#include "waypointScr.hpp" -#include "waypointListScr.hpp" -#include "display/lv_display.h" -#include "globalGuiDef.h" bool isWaypointOpt = false; bool isTrackOpt = false; @@ -59,7 +55,6 @@ void buttonBarEvent(lv_event_t *event) if (strcmp(option,"waypoint") == 0) { log_v("Waypoint"); - // isMainScreen = false; isWaypointOpt = true; isTrackOpt = false; if (!isOptionLoaded) diff --git a/lib/gui/src/buttonBar.hpp b/lib/gui/src/buttonBar.hpp index 04ed9a60..5ff40902 100644 --- a/lib/gui/src/buttonBar.hpp +++ b/lib/gui/src/buttonBar.hpp @@ -2,8 +2,8 @@ * @file buttonBar.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Button Bar - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef BUTTONBAR_HPP @@ -11,6 +11,8 @@ #include "globalGuiDef.h" #include "mainScr.hpp" +#include "waypointScr.hpp" +#include "waypointListScr.hpp" static const char *waypointIconFile PROGMEM = "/wpt.bin"; // Waypoint icon static const char *trackIconFile PROGMEM = "/track.bin"; // Track icon diff --git a/lib/gui/src/deviceSettingsScr.cpp b/lib/gui/src/deviceSettingsScr.cpp index 52f428e2..970aae4a 100644 --- a/lib/gui/src/deviceSettingsScr.cpp +++ b/lib/gui/src/deviceSettingsScr.cpp @@ -2,12 +2,11 @@ * @file deviceSettingsScr.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Device Settings Screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "deviceSettingsScr.hpp" -#include "globalGuiDef.h" lv_obj_t *deviceSettingsScreen; // Device Settings Screen @@ -16,7 +15,7 @@ lv_obj_t *deviceSettingsScreen; // Device Settings Screen * * @param event */ -void deviceSettingsEvent(lv_event_t *event) +static void deviceSettingsEvent(lv_event_t *event) { lv_obj_t *obj = (lv_obj_t*)lv_event_get_target(event); char *option = (char *)lv_event_get_user_data(event); @@ -38,7 +37,12 @@ void deviceSettingsEvent(lv_event_t *event) } } -void lv_brightness_cb(lv_event_t *e) +/** + * @brief Brightness callback + * + * @param e + */ +static void brightnessEvent(lv_event_t *e) { lv_obj_t *obj =(lv_obj_t*) lv_event_get_target(e); defBright = lv_slider_get_value(obj); @@ -46,17 +50,32 @@ void lv_brightness_cb(lv_event_t *e) tft.setBrightness(defBright); } -// void lv_background_opa_cb(lv_event_t *e) -// { -// lv_obj_t *obj =(lv_obj_t*) lv_event_get_target(e); -// uint8_t val = lv_slider_get_value(obj); -// std::vector::iterator it; -// for (it = sub_section.begin(); it != sub_section.end(); it++) { -// lv_obj_set_style_bg_opa(*it, val, LV_PART_MAIN); -// } -// } - -static lv_obj_t *create_text(lv_obj_t *parent, const char *icon, const char *txt) +/** + * @brief Upgrade firmware event + * + * @param event + */ +static void upgradeEvent(lv_event_t *event) +{ + createMsgUpgrade(); + lv_screen_load(msgUpgrade); + if (!checkFileUpgrade()) + { + lv_label_set_text_static(msgUprgdText, LV_SYMBOL_WARNING " No Firmware found!"); + } + else + { + lv_label_set_text_static(msgUprgdText, LV_SYMBOL_WARNING " Firmware found!"); + lv_obj_clear_flag(btnMsgUpgrade,LV_OBJ_FLAG_HIDDEN); + lv_obj_clear_flag(contMeter,LV_OBJ_FLAG_HIDDEN); + } +} + +/** + * @brief Create brightness text + * + */ +static lv_obj_t *createBrightText(lv_obj_t *parent, const char *icon, const char *txt) { lv_obj_t *obj = lv_menu_cont_create(parent); @@ -83,10 +102,14 @@ static lv_obj_t *create_text(lv_obj_t *parent, const char *icon, const char *txt return obj; } -static lv_obj_t *create_slider(lv_obj_t *parent, const char *icon, const char *txt, int32_t min, int32_t max, +/** + * @brief Create brightness slider + * + */ +static lv_obj_t *createBrightSlider(lv_obj_t *parent, const char *icon, const char *txt, int32_t min, int32_t max, int32_t val, lv_event_cb_t cb, lv_event_code_t filter) { - lv_obj_t *obj = create_text(parent, icon, txt); + lv_obj_t *obj = createBrightText(parent, icon, txt); lv_obj_t *slider = lv_slider_create(obj); lv_obj_set_width(slider,TFT_WIDTH - 80); @@ -154,9 +177,20 @@ void createDeviceSettingsScr() lv_obj_align_to(dropdown, list, LV_ALIGN_OUT_RIGHT_MID, 0, 0); lv_obj_add_event_cb(dropdown, deviceSettingsEvent, LV_EVENT_VALUE_CHANGED, (char*)"rate"); - create_slider(deviceSettingsOptions, LV_SYMBOL_SETTINGS, "Brightness", 5, 255, defBright, lv_brightness_cb, LV_EVENT_VALUE_CHANGED); + // Upgrade button + list = lv_list_add_btn(deviceSettingsOptions, NULL, NULL); + btn = lv_btn_create(list); + lv_obj_set_size(btn, TFT_WIDTH - 45, 40 * scale); + label = lv_label_create(btn); + lv_obj_set_style_text_font(label, fontLarge, 0); + lv_label_set_text_static(label, "Firmware Upgrade"); + lv_obj_center(label); + lv_obj_add_event_cb(btn, upgradeEvent, LV_EVENT_CLICKED, NULL); + + // Brightness Slider + createBrightSlider(deviceSettingsOptions, LV_SYMBOL_SETTINGS, "Brightness", 5, 255, defBright, brightnessEvent, LV_EVENT_VALUE_CHANGED); - // Back button + // Back button btn = lv_btn_create(deviceSettingsScreen); lv_obj_set_size(btn, TFT_WIDTH - 30, 40 * scale); label = lv_label_create(btn); diff --git a/lib/gui/src/deviceSettingsScr.hpp b/lib/gui/src/deviceSettingsScr.hpp index 5ce3c2d6..e7a2b15e 100644 --- a/lib/gui/src/deviceSettingsScr.hpp +++ b/lib/gui/src/deviceSettingsScr.hpp @@ -2,21 +2,23 @@ * @file deviceSettingsScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Device Settings Screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef DEVICESETTINGSCR_HPP #define DEVICESETTINGSCR_HPP #include "globalGuiDef.h" -#include "gps.hpp" -#include "settings.hpp" +#include "upgradeScr.hpp" #include "lvglSetup.hpp" +#include "firmUpgrade.hpp" static lv_obj_t *deviceSettingsOptions; static void deviceSettingsEvent(lv_event_t *event); +static void brightnessEvent(lv_event_t *e); +static void upgradeEvent(lv_event_t *event); void createDeviceSettingsScr(); #endif diff --git a/lib/gui/src/globalGuiDef.h b/lib/gui/src/globalGuiDef.h index 23d977f9..6ee0d2b7 100644 --- a/lib/gui/src/globalGuiDef.h +++ b/lib/gui/src/globalGuiDef.h @@ -1,8 +1,8 @@ /** * @file globalGuiDef.h * @brief Global GUI Variables - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef GLOBALGUIDEF_H @@ -89,14 +89,9 @@ static bool getPngSize(const char* filename, uint16_t *width, uint16_t *height) return false; } - byte table[32]; + uint8_t table[32]; - // for (int i = 0; file.available() && i < 32; i++) - // { - // table[i] = file.read(); - // } - - fread(table, sizeof(byte), 32, file); + fread(table, sizeof(uint8_t), 32, file); *width=table[16]*256*256*256+table[17]*256*256+table[18]*256+table[19]; *height=table[20]*256*256*256+table[21]*256*256+table[22]*256+table[23]; diff --git a/lib/gui/src/mainScr.cpp b/lib/gui/src/mainScr.cpp index 4ebfda2f..8a8dc58a 100644 --- a/lib/gui/src/mainScr.cpp +++ b/lib/gui/src/mainScr.cpp @@ -2,21 +2,11 @@ * @file mainScr.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Main Screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "mainScr.hpp" -#include "buttonBar.hpp" -#include "core/lv_obj.h" -#include "core/lv_obj_pos.h" -#include "globalGuiDef.h" -#include "globalMapsDef.h" -#include "settings.hpp" -#include "tft.hpp" - -extern const int SD_CS; -extern const uint8_t TFT_SPI_CS; bool isMainScreen = false; // Flag to indicate main screen is selected bool isScrolled = true; // Flag to indicate when tileview was scrolled @@ -27,12 +17,12 @@ uint8_t wptAction = WPT_NONE; // Current Waypoint Action int wptPosX, wptPosY = 0; // Waypoint position on map #ifdef LARGE_SCREEN - int toolBarOffset = 100; - int toolBarSpace = 60; + uint8_t toolBarOffset = 100; + uint8_t toolBarSpace = 60; #endif #ifndef LARGE_SCREEN - int toolBarOffset = 80; - int toolBarSpace = 50; + uint8_t toolBarOffset = 80; + uint8_t toolBarSpace = 50; #endif lv_obj_t *tilesScreen; @@ -59,10 +49,8 @@ void updateCompassScr(lv_event_t * event) lv_obj_t *obj = (lv_obj_t *)lv_event_get_current_target(event); if (obj==compassHeading) { - //#ifdef ENABLE_COMPASS lv_label_set_text_fmt(compassHeading, "%5d\xC2\xB0", heading); lv_img_set_angle(compassImg, -(heading * 10)); - //#endif } if (obj==latitude) lv_label_set_text_fmt(latitude, "%s", latFormatString(gpsData.latitude)); @@ -72,6 +60,10 @@ void updateCompassScr(lv_event_t * event) lv_label_set_text_fmt(obj, "%4d m.", gpsData.altitude); if (obj==speedLabel) lv_label_set_text_fmt(obj, "%3d Km/h", gpsData.speed); + if (obj==sunriseLabel) + lv_label_set_text_static(obj, gpsData.sunriseHour); + if (obj==sunsetLabel) + lv_label_set_text_static(obj, gpsData.sunsetHour); } /** @@ -86,11 +78,6 @@ void getActTile(lv_event_t *event) isScrolled = true; redrawMap = true; - if (activeTile == SATTRACK) - { - // createSatSprite(spriteSat); - // createConstelSprite(constelSprite); - } if (activeTile == MAP) { createMapScrSprites(); @@ -175,6 +162,8 @@ void updateMainScreen(lv_timer_t *t) lv_obj_send_event(longitude, LV_EVENT_VALUE_CHANGED, NULL); lv_obj_send_event(altitude, LV_EVENT_VALUE_CHANGED, NULL); lv_obj_send_event(speedLabel, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_send_event(sunriseLabel, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_send_event(sunsetLabel, LV_EVENT_VALUE_CHANGED, NULL); break; case MAP: @@ -206,7 +195,6 @@ void updateMainScreen(lv_timer_t *t) */ void gestureEvent(lv_event_t *event) { - lv_obj_t *screen = (lv_obj_t *)lv_event_get_current_target(event); lv_dir_t dir = lv_indev_get_gesture_dir(lv_indev_get_act()); if (activeTile == MAP && isMainScreen) { @@ -240,9 +228,7 @@ void updateMap(lv_event_t *event) viewPort.setCenter(point); getMapBlocks(viewPort.bbox, memCache); - - // deleteMapScrSprites(); - // createMapScrSprites(); + generateVectorMap(viewPort, memCache, mapTempSprite); isPosMoved = false; @@ -419,9 +405,7 @@ void updateNavEvent(lv_event_t *event) if (wptDistance == 0) { lv_img_set_src(arrowNav, &navfinish); - //#ifdef ENABLE_COMPASS lv_img_set_angle(arrowNav, 0); - //#endif } else { @@ -470,6 +454,8 @@ void createMainScr() altitudeWidget(compassTile); // Speed widget speedWidget(compassTile); + // Sunrise/Sunset widget + sunWidget(compassTile); // Compass Tile Events lv_obj_add_event_cb(compassHeading, updateCompassScr, LV_EVENT_VALUE_CHANGED, NULL); @@ -477,6 +463,8 @@ void createMainScr() lv_obj_add_event_cb(longitude, updateCompassScr, LV_EVENT_VALUE_CHANGED, NULL); lv_obj_add_event_cb(altitude, updateCompassScr, LV_EVENT_VALUE_CHANGED, NULL); lv_obj_add_event_cb(speedLabel, updateCompassScr, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_add_event_cb(sunriseLabel, updateCompassScr, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_add_event_cb(sunsetLabel, updateCompassScr, LV_EVENT_VALUE_CHANGED, NULL); // Map Tile Toolbar btnFullScreen = lv_btn_create(mapTile); diff --git a/lib/gui/src/mainScr.hpp b/lib/gui/src/mainScr.hpp index b97532fe..0b401472 100644 --- a/lib/gui/src/mainScr.hpp +++ b/lib/gui/src/mainScr.hpp @@ -2,21 +2,17 @@ * @file mainScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Main Screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef MAINSCR_HPP #define MAINSCR_HPP #include "globalGuiDef.h" -#include "lvglFuncs.hpp" -#include "misc/lv_color.h" -#include "notifyBar.hpp" #include "buttonBar.hpp" #include "renderMaps.hpp" #include "vectorMaps.hpp" -#include "addWaypoint.hpp" #include "loadWaypoint.hpp" #include "deleteWaypoint.hpp" #include "editWaypoint.hpp" @@ -24,7 +20,7 @@ #include "navScr.hpp" #include "satInfoScr.hpp" -static lv_timer_t *mainTimer; // Main Screen Timer +extern lv_timer_t *mainTimer; // Main Screen Timer #define UPDATE_MAINSCR_PERIOD 30 // Main Screen update time extern bool isMainScreen; // Flag to indicate main screen is selected @@ -57,13 +53,14 @@ extern lv_obj_t *satTrackTile; extern lv_obj_t *btnFullScreen; extern lv_obj_t *btnZoomIn; extern lv_obj_t *btnZoomOut; -extern int toolBarOffset; -extern int toolBarSpace; +extern uint8_t toolBarOffset; +extern uint8_t toolBarSpace; void updateCompassScr(lv_event_t * event); void deleteMapScrSprites(); void createMapScrSprites(); +void displayMap(uint16_t tileSize); void getActTile(lv_event_t *event); void scrollTile(lv_event_t *event); diff --git a/lib/gui/src/mapSettingsScr.cpp b/lib/gui/src/mapSettingsScr.cpp index d0e52f66..e646df29 100644 --- a/lib/gui/src/mapSettingsScr.cpp +++ b/lib/gui/src/mapSettingsScr.cpp @@ -2,13 +2,11 @@ * @file mapSettingsScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Map Settings screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "mapSettingsScr.hpp" -#include "core/lv_obj.h" -#include "settings.hpp" lv_obj_t *mapSettingsScreen; // Map Settings Screen diff --git a/lib/gui/src/mapSettingsScr.hpp b/lib/gui/src/mapSettingsScr.hpp index 2572245d..7cf4e78a 100644 --- a/lib/gui/src/mapSettingsScr.hpp +++ b/lib/gui/src/mapSettingsScr.hpp @@ -2,15 +2,14 @@ * @file mapSettingsScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Map Settings screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef MAPSETTINGSCR_HPP #define MAPSETTINGSCR_HPP #include "globalGuiDef.h" -#include "settings.hpp" #include "lvglFuncs.hpp" #include "vectorMaps.hpp" #include "renderMaps.hpp" diff --git a/lib/gui/src/navScr.cpp b/lib/gui/src/navScr.cpp index ab96fc07..58537641 100644 --- a/lib/gui/src/navScr.cpp +++ b/lib/gui/src/navScr.cpp @@ -2,8 +2,8 @@ * @file navScr.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Navigation screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "navScr.hpp" diff --git a/lib/gui/src/navScr.hpp b/lib/gui/src/navScr.hpp index a8bdd982..efbfb179 100644 --- a/lib/gui/src/navScr.hpp +++ b/lib/gui/src/navScr.hpp @@ -2,14 +2,13 @@ * @file navScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Navigation screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef NAVSCR_HPP #define NAVSCR_HPP -#include "lvgl.h" #include "globalGuiDef.h" #include "navup.c" diff --git a/lib/gui/src/notifyBar.cpp b/lib/gui/src/notifyBar.cpp index 056d6cfc..408bf0b1 100644 --- a/lib/gui/src/notifyBar.cpp +++ b/lib/gui/src/notifyBar.cpp @@ -2,18 +2,19 @@ * @file notifyBar.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Notify Bar Screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "notifyBar.hpp" -#include "font/lv_symbol_def.h" -#include "misc/lv_event.h" lv_obj_t *mainScreen; lv_obj_t *notifyBarIcons; lv_obj_t *notifyBarHour; +Storage storage; +Battery battery; + /** * @brief Update notify bar event * @@ -34,7 +35,7 @@ void updateNotifyBar(lv_event_t *event) if (obj == gpsCount) lv_label_set_text_fmt(obj, LV_SYMBOL_GPS "%2d", gpsData.satellites); - if (obj == battery) + if (obj == battIcon) { if (battLevel <= 160 && battLevel > 140) lv_label_set_text_static(obj, " " LV_SYMBOL_CHARGE); @@ -115,10 +116,10 @@ void updateNotifyBarTimer(lv_timer_t *t) } #endif - battLevel = batteryRead(); + battLevel = battery.readBattery(); if (battLevel != battLevelOld) { - lv_obj_send_event(battery, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_send_event(battIcon, LV_EVENT_VALUE_CHANGED, NULL); battLevelOld = battLevel; } } @@ -151,8 +152,6 @@ void createNotifyBar() lv_obj_add_style(notifyBarIcons, &styleBar, LV_PART_MAIN); lv_obj_add_style(notifyBarHour, &styleBar, LV_PART_MAIN); - lv_obj_t *label; - gpsTime = lv_label_create(notifyBarHour); lv_obj_set_style_text_font(gpsTime, fontLarge, 0); lv_label_set_text_fmt(gpsTime, timeFormat, 0, 0, 0); @@ -168,7 +167,7 @@ void createNotifyBar() lv_obj_add_event_cb(temp, updateNotifyBar, LV_EVENT_VALUE_CHANGED, NULL); #endif - if (isSdLoaded) + if (storage.getSdLoaded()) { sdCard = lv_label_create(notifyBarIcons); lv_label_set_text_static(sdCard, LV_SYMBOL_SD_CARD); @@ -188,9 +187,9 @@ void createNotifyBar() lv_label_set_text_static(gpsFixMode, "----"); lv_obj_add_event_cb(gpsFixMode, updateNotifyBar, LV_EVENT_VALUE_CHANGED, NULL); - battery = lv_label_create(notifyBarIcons); - lv_label_set_text_static(battery, LV_SYMBOL_BATTERY_EMPTY); - lv_obj_add_event_cb(battery, updateNotifyBar, LV_EVENT_VALUE_CHANGED, NULL); + battIcon = lv_label_create(notifyBarIcons); + lv_label_set_text_static(battIcon, LV_SYMBOL_BATTERY_EMPTY); + lv_obj_add_event_cb(battIcon, updateNotifyBar, LV_EVENT_VALUE_CHANGED, NULL); lv_timer_t *timerNotifyBar = lv_timer_create(updateNotifyBarTimer, UPDATE_NOTIFY_PERIOD, NULL); lv_timer_ready(timerNotifyBar); diff --git a/lib/gui/src/notifyBar.hpp b/lib/gui/src/notifyBar.hpp index fdf5c311..6243b975 100644 --- a/lib/gui/src/notifyBar.hpp +++ b/lib/gui/src/notifyBar.hpp @@ -2,17 +2,18 @@ * @file notifyBar.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Notify Bar Screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef NOTIFYBAR_HPP #define NOTIFYBAR_HPP -#include #include "globalGuiDef.h" #include "tasks.hpp" #include "storage.hpp" +#include "battery.hpp" +#include "settings.hpp" /** * @brief Notify Bar screen objects @@ -22,11 +23,14 @@ static lv_obj_t *gpsTime; // Time static lv_obj_t *gpsCount; // Satellite count static lv_obj_t *gpsFix; // Satellite fix static lv_obj_t *gpsFixMode; // Satellite fix mode -static lv_obj_t *battery; // Battery level +static lv_obj_t *battIcon; // Battery level static lv_obj_t *sdCard; // SD card icon static lv_obj_t *temp; // Temperature static lv_obj_t *wifi; // Wifi +static float battLevel = 0; +static float battLevelOld = 0; + #define UPDATE_NOTIFY_PERIOD 1000 // Notify Bar update time /** diff --git a/lib/gui/src/satInfoScr.cpp b/lib/gui/src/satInfoScr.cpp index b543e37a..cff1159e 100644 --- a/lib/gui/src/satInfoScr.cpp +++ b/lib/gui/src/satInfoScr.cpp @@ -2,8 +2,8 @@ * @file satInfoScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Satellite info screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "satInfoScr.hpp" @@ -35,7 +35,6 @@ void drawTextOnLayer(const char * text, lv_layer_t * layer, lv_point_t * p, lv_a lv_draw_rect_dsc_t draw_rect_dsc; lv_draw_rect_dsc_init(&draw_rect_dsc); - //draw_rect_dsc.bg_color = lv_color_black(); draw_rect_dsc.bg_opa = LV_OPA_TRANSP; draw_rect_dsc.radius = 0; draw_rect_dsc.bg_image_symbol_font = font; diff --git a/lib/gui/src/satInfoScr.hpp b/lib/gui/src/satInfoScr.hpp index 659ece63..be90d78e 100644 --- a/lib/gui/src/satInfoScr.hpp +++ b/lib/gui/src/satInfoScr.hpp @@ -2,14 +2,13 @@ * @file satInfoScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Satellite info screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef SATINFOSCR_HPP #define SATINFOSCR_HPP -#include "lvgl.h" #include "globalGuiDef.h" #include "gps.hpp" diff --git a/lib/gui/src/searchSatScr.cpp b/lib/gui/src/searchSatScr.cpp index 44fee130..baba24d8 100644 --- a/lib/gui/src/searchSatScr.cpp +++ b/lib/gui/src/searchSatScr.cpp @@ -2,8 +2,8 @@ * @file searchSatScr.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - GPS satellite search screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "searchSatScr.hpp" @@ -11,6 +11,8 @@ static unsigned long millisActual = 0; static bool skipSearch = false; bool isSearchingSat = true; +extern uint8_t activeTile; +lv_timer_t *mainTimer; // Main Screen Timer /** * @brief Button events @@ -26,9 +28,9 @@ void buttonEvent(lv_event_t *event) } if (strcmp(option,"settings") == 0) { - //isMainScreen = false; lv_screen_load(settingsScreen); } + lv_timer_resume(mainTimer); } /** @@ -43,6 +45,7 @@ void searchGPS(lv_timer_t *searchTimer) while (millis() < millisActual + 500) ; lv_timer_del(searchTimer); + lv_timer_resume(mainTimer); isSearchingSat = false; loadMainScreen(); } @@ -52,6 +55,8 @@ void searchGPS(lv_timer_t *searchTimer) lv_timer_del(searchTimer); isSearchingSat = false; zoom = defaultZoom; + activeTile = 3; + lv_tileview_set_tile_by_index(tilesScreen, 3, 0, LV_ANIM_OFF); loadMainScreen(); } } @@ -64,6 +69,7 @@ void createSearchSatScr() { searchTimer = lv_timer_create(searchGPS, 100, NULL); lv_timer_ready(searchTimer); + lv_timer_pause(mainTimer); searchSatScreen = lv_obj_create(NULL); diff --git a/lib/gui/src/searchSatScr.hpp b/lib/gui/src/searchSatScr.hpp index d2929e64..93b98a47 100644 --- a/lib/gui/src/searchSatScr.hpp +++ b/lib/gui/src/searchSatScr.hpp @@ -2,14 +2,13 @@ * @file searchSatScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - GPS satellite search screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef SEARCHSATSCR_HPP #define SEARCHSATSCR_HPP -#include #include "gps.hpp" #include "globalGuiDef.h" diff --git a/lib/gui/src/settingsScr.cpp b/lib/gui/src/settingsScr.cpp index 3b351691..fd38ced0 100644 --- a/lib/gui/src/settingsScr.cpp +++ b/lib/gui/src/settingsScr.cpp @@ -2,12 +2,11 @@ * @file settingsScr.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Settings Screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "settingsScr.hpp" -#include "globalGuiDef.h" bool needReboot = false; @@ -19,7 +18,10 @@ bool needReboot = false; static void back(lv_event_t *event) { if (isSearchingSat) + { + lv_timer_pause(mainTimer); lv_screen_load(searchSatScreen); + } else loadMainScreen(); } diff --git a/lib/gui/src/settingsScr.hpp b/lib/gui/src/settingsScr.hpp index cf7f32e7..e02f9d43 100644 --- a/lib/gui/src/settingsScr.hpp +++ b/lib/gui/src/settingsScr.hpp @@ -2,8 +2,8 @@ * @file settingsScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Settings Screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef SETTINGSSCR_HPP @@ -11,9 +11,7 @@ #include "globalGuiDef.h" #include "mainScr.hpp" -#include "compass.hpp" #include "searchSatScr.hpp" -#include "settings.hpp" void loadMainScreen(); diff --git a/lib/gui/src/splashScr.cpp b/lib/gui/src/splashScr.cpp index 136cea6b..98557039 100644 --- a/lib/gui/src/splashScr.cpp +++ b/lib/gui/src/splashScr.cpp @@ -2,8 +2,8 @@ * @file splashScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Splash screen - NOT LVGL - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "splashScr.hpp" @@ -25,9 +25,15 @@ void splashScreen() getPngSize(logoFile,&pngWidth,&pngHeight); tft.drawPngFile(logoFile, (tft.width() / 2) - (pngWidth/2), (tft.height() / 2) - pngHeight); + + tft.setTextSize(1); + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + tft.drawCenterString("Map data from OpenStreetMap.",tft.width() >> 1, TFT_HEIGHT - 120 ); + tft.drawCenterString("(c) OpenStreetMap",tft.width() >> 1, TFT_HEIGHT - 110 ); + tft.drawCenterString("(c) OpenStreetMap contributors",tft.width() >> 1, TFT_HEIGHT - 100 ); char statusString[50] = ""; - tft.setTextSize(1); tft.setTextColor(TFT_YELLOW, TFT_BLACK); memset(&statusString[0], 0, sizeof(statusString)); @@ -63,6 +69,10 @@ void splashScreen() ; } + millisActual = millis(); + while (millis() < millisActual + 100) + ; + for (uint8_t fadeOut = maxBrightness; fadeOut > 0; fadeOut--) { tft.setBrightness(fadeOut); diff --git a/lib/gui/src/splashScr.hpp b/lib/gui/src/splashScr.hpp index 3d272514..298d60e5 100644 --- a/lib/gui/src/splashScr.hpp +++ b/lib/gui/src/splashScr.hpp @@ -2,14 +2,13 @@ * @file splashScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Splash screen - NOT LVGL - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef SPLASHSCR_HPP #define SPLASHSCR_HPP -#include "tft.hpp" #include "globalGuiDef.h" #include "settings.hpp" diff --git a/lib/gui/src/upgradeScr.cpp b/lib/gui/src/upgradeScr.cpp new file mode 100644 index 00000000..76c8e509 --- /dev/null +++ b/lib/gui/src/upgradeScr.cpp @@ -0,0 +1,89 @@ +/** + * @file upgradeScr.cpp + * @author Jordi Gauchía (jgauchia@gmx.es) + * @brief LVGL Firmware upgrade messages + * @version 0.1.9 + * @date 2024-12 + */ + + #include "upgradeScr.hpp" + + lv_obj_t *msgUpgrade; + lv_obj_t *msgUprgdText; + lv_obj_t *btnMsgBack; + lv_obj_t *btnMsgUpgrade; + lv_obj_t *contMeter; + +/** + * @brief Upgrade Back Message Event + * + */ +void msgBackEvent(lv_event_t *event) +{ + lv_screen_load(deviceSettingsScreen); +} + +/** + * @brief Upgrade Message Event + * + */ +void msgUpgrdEvent(lv_event_t *event) +{ + log_v("Upgrade firmware"); + lv_obj_add_flag(btnMsgBack,LV_OBJ_FLAG_HIDDEN); + lv_obj_add_flag(btnMsgUpgrade, LV_OBJ_FLAG_HIDDEN); + onUpgrdStart(); + onUpgrdEnd(); +} + + +/** + * @brief Create Upgrade Message + * + */ +void createMsgUpgrade() +{ + msgUpgrade = lv_obj_create(NULL); + lv_obj_t *msgBox = lv_msgbox_create(msgUpgrade); + lv_msgbox_add_title(msgBox, "Firmware Upgrade"); + lv_obj_t *content = lv_msgbox_get_content(msgBox); + lv_obj_set_flex_flow(content, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(content, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + lv_obj_set_height(msgBox,200); + + lv_obj_t *contText = lv_obj_create(content); + lv_obj_set_size(contText, lv_pct(100), LV_SIZE_CONTENT); + lv_obj_set_flex_flow(contText, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(contText, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER); + lv_obj_clear_flag(contText,LV_OBJ_FLAG_SCROLLABLE); + lv_obj_set_style_border_color(contText,lv_color_black(),0); + + msgUprgdText = lv_label_create(contText); + lv_label_set_text_static(msgUprgdText,""); + lv_obj_set_style_text_font(msgUprgdText, fontLarge, 0); + + contMeter = lv_obj_create(content); + lv_obj_set_size(contMeter, lv_pct(100), LV_SIZE_CONTENT); + lv_obj_set_flex_flow(contMeter, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(contMeter, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER); + lv_obj_clear_flag(contMeter,LV_OBJ_FLAG_SCROLLABLE); + lv_obj_set_style_border_color(contMeter,lv_color_black(),0); + lv_obj_add_flag(contMeter,LV_OBJ_FLAG_HIDDEN); + + static uint32_t objectColor = 0x303030; + static lv_style_t styleBtn; + lv_style_init(&styleBtn); + lv_style_set_bg_color(&styleBtn, lv_color_hex(objectColor)); + lv_style_set_border_color(&styleBtn, lv_color_hex(objectColor)); + + btnMsgBack = lv_msgbox_add_footer_button(msgBox, "Back"); + lv_obj_add_event_cb(btnMsgBack, msgBackEvent, LV_EVENT_CLICKED, NULL); + lv_obj_set_style_text_font(btnMsgBack, fontLarge, 0); + lv_obj_add_style(btnMsgBack, &styleBtn, 0); + + btnMsgUpgrade = lv_msgbox_add_footer_button(msgBox, "UPGRADE"); + lv_obj_add_event_cb(btnMsgUpgrade, msgUpgrdEvent, LV_EVENT_CLICKED, NULL); + lv_obj_set_style_text_font(btnMsgUpgrade, fontLarge, 0); + lv_obj_add_style(btnMsgUpgrade, &styleBtn, 0); + lv_obj_add_flag(btnMsgUpgrade,LV_OBJ_FLAG_HIDDEN); +} \ No newline at end of file diff --git a/lib/gui/src/upgradeScr.hpp b/lib/gui/src/upgradeScr.hpp new file mode 100644 index 00000000..3fef0e70 --- /dev/null +++ b/lib/gui/src/upgradeScr.hpp @@ -0,0 +1,26 @@ +/** + * @file upgradeScr.hpp + * @author Jordi Gauchía (jgauchia@gmx.es) + * @brief LVGL Firmware upgrade messages + * @version 0.1.9 + * @date 2024-12 + */ + +#ifndef UPGRADESCR_HPP +#define UPGRADESCR_HPP + +#include "lvgl.h" +#include "firmUpgrade.hpp" +#include "globalGuiDef.h" + +extern lv_obj_t *msgUpgrade; +extern lv_obj_t *msgUprgdText; +extern lv_obj_t *btnMsgBack; +extern lv_obj_t *btnMsgUpgrade; +extern lv_obj_t *contMeter; + +void msgBackEvent(lv_event_t *event); +void msgUpgrdEvent(lv_event_t *event); +void createMsgUpgrade(); + +#endif \ No newline at end of file diff --git a/lib/gui/src/waypointListScr.cpp b/lib/gui/src/waypointListScr.cpp index 22a00c9d..2c495408 100644 --- a/lib/gui/src/waypointListScr.cpp +++ b/lib/gui/src/waypointListScr.cpp @@ -2,8 +2,8 @@ * @file waypointListScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Waypoint list screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "waypointListScr.hpp" @@ -56,6 +56,8 @@ void waypointListEvent(lv_event_t * event) else lv_obj_add_flag(navTile,LV_OBJ_FLAG_HIDDEN); + isPosMoved = true; + loadMainScreen(); break; case WPT_EDIT: diff --git a/lib/gui/src/waypointListScr.hpp b/lib/gui/src/waypointListScr.hpp index c312e8a6..f24fbcc8 100644 --- a/lib/gui/src/waypointListScr.hpp +++ b/lib/gui/src/waypointListScr.hpp @@ -2,18 +2,14 @@ * @file waypointListScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Waypoint list screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef WAYPOINTLISTSCR_HPP #define WAYPOINTLISTSCR_HPP -#include "globalGuiDef.h" -#include "globalGpxDef.h" #include "mainScr.hpp" -#include "storage.hpp" -#include void loadMainScreen(); void updateWaypointPos(); diff --git a/lib/gui/src/waypointScr.cpp b/lib/gui/src/waypointScr.cpp index 23d73094..d9ecaad0 100644 --- a/lib/gui/src/waypointScr.cpp +++ b/lib/gui/src/waypointScr.cpp @@ -2,16 +2,11 @@ * @file waypointScr.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Waypoint Screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "waypointScr.hpp" -#include "core/lv_obj_pos.h" -#include "display/lv_display.h" -#include "globalGuiDef.h" -#include "tft.hpp" -#include "addWaypoint.hpp" lv_obj_t *waypointScreen; // Add Waypoint Screen lv_obj_t *waypointName; @@ -55,8 +50,6 @@ static void waypointScreenEvent(lv_event_t *event) editWaypointName(loadWpt.name, newName); } break; - // default: - // break; } isMainScreen = true; @@ -106,8 +99,6 @@ static void waypointScreenEvent(lv_event_t *event) editWaypointName(loadWpt.name, newName); } break; - // default: - // break; } isMainScreen = true; @@ -155,6 +146,46 @@ static void rotateScreen(lv_event_t *event) lv_refr_now(display); } +/** + * @brief Waypoint Name event + * + * @param event + */ +static void waypointNameEvent(lv_event_t *event) +{ + lv_event_code_t code = lv_event_get_code(event); + if(code == LV_EVENT_CLICKED) + { + switch (wptAction) + { + case WPT_ADD: + addWpt.name = (char *)lv_textarea_get_text(waypointName); + + if ( strcmp(addWpt.name,"") != 0) + { + openGpxFile(wptFile); + vTaskDelay(100); + addWaypointToFile(wptFile,addWpt); + } + break; + case WPT_EDIT: + char *newName = (char *)lv_textarea_get_text(waypointName); + + if ( strcmp(loadWpt.name, newName) != 0) + { + editWaypointName(loadWpt.name, newName); + } + break; + } + + isMainScreen = true; + redrawMap = true; + wptAction = WPT_NONE; + lv_refr_now(display); + loadMainScreen(); + } +} + /** * @brief Update current waypoint postion to add * @@ -202,7 +233,6 @@ void createWaypointScreen() #ifdef TDECK_ESP32S3 lv_group_add_obj(scrGroup, waypointName); lv_group_focus_obj(waypointName); - //lv_group_add_obj(scrGroup, waypointScreen); #endif #ifndef TDECK_ESP32S3 @@ -216,18 +246,22 @@ void createWaypointScreen() lv_obj_align(rotateScreenBtn, LV_ALIGN_TOP_RIGHT, -10, 5); lv_obj_add_flag(rotateScreenBtn, LV_OBJ_FLAG_CLICKABLE); lv_obj_add_event_cb(rotateScreenBtn, rotateScreen, LV_EVENT_CLICKED, NULL); + lv_obj_set_size(rotateScreenBtn, 40, 35); lv_obj_t *rotateScreenLbl = lv_label_create(rotateScreenBtn); lv_label_set_text(rotateScreenLbl, LV_SYMBOL_LOOP); lv_obj_center(rotateScreenLbl); #endif - lv_obj_t* label; - label = lv_label_create(waypointScreen); - lv_obj_set_style_text_font(label, fontOptions, 0); - lv_label_set_text_static(label, "Waypoint Name:"); - lv_obj_center(label); - lv_obj_align(label,LV_ALIGN_TOP_LEFT,10,10); + lv_obj_t* labelWpt; + labelWpt = lv_label_create(waypointScreen); + lv_obj_set_style_text_font(labelWpt, fontOptions, 0); + lv_label_set_text_static(labelWpt, LV_SYMBOL_LEFT " Waypoint Name:"); + lv_obj_center(labelWpt); + lv_obj_align(labelWpt,LV_ALIGN_TOP_LEFT,10,10); + lv_obj_add_flag(labelWpt, LV_OBJ_FLAG_CLICKABLE); + lv_obj_add_event_cb(labelWpt, waypointNameEvent, LV_EVENT_ALL, NULL); + lv_obj_t* label; label = lv_label_create(waypointScreen); lv_obj_set_style_text_font(label, fontOptions, 0); lv_label_set_text_static(label, "Lat:"); diff --git a/lib/gui/src/waypointScr.hpp b/lib/gui/src/waypointScr.hpp index 18db45c6..166350cc 100644 --- a/lib/gui/src/waypointScr.hpp +++ b/lib/gui/src/waypointScr.hpp @@ -2,14 +2,14 @@ * @file waypointScr.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Add Waypoint Screen - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef waypointScr_HPP #define waypointScr_HPP -#include "globalGuiDef.h" +#include "addWaypoint.hpp" #include "mainScr.hpp" extern lv_obj_t *waypointName; @@ -19,6 +19,7 @@ void loadMainScreen(); static void waypointScreenEvent(lv_event_t *event); static void rotateScreen(lv_event_t *event); +static void waypointNameEvent(lv_event_t *event); void updateWaypointPos(); void createWaypointScreen(); diff --git a/lib/gui/src/widgets.cpp b/lib/gui/src/widgets.cpp index 12934720..16fd2c89 100644 --- a/lib/gui/src/widgets.cpp +++ b/lib/gui/src/widgets.cpp @@ -2,8 +2,8 @@ * @file widgets.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Widgets - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "widgets.hpp" @@ -14,6 +14,8 @@ lv_obj_t *latitude; lv_obj_t *longitude; lv_obj_t *altitude; lv_obj_t *speedLabel; +lv_obj_t *sunriseLabel; +lv_obj_t *sunsetLabel; /** * @brief Edit Screen Event (drag widgets) @@ -211,4 +213,41 @@ void speedWidget(_lv_obj_t *screen) lv_obj_add_event_cb(obj, editWidget, LV_EVENT_LONG_PRESSED, NULL); lv_obj_add_event_cb(obj, dragWidget, LV_EVENT_PRESSING, (char *)"Speed_"); lv_obj_add_event_cb(obj, unselectWidget, LV_EVENT_RELEASED, (char *)"Speed_"); +} + +/** + * @brief Sunrise/Sunset widget + * + * @param screen + */ +void sunWidget(_lv_obj_t *screen) +{ + lv_obj_t *obj = lv_obj_create(screen); + lv_obj_set_size(obj, 70 * scale, 60 * scale); + lv_obj_set_pos(obj, sunPosX, sunPosY); + lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); + + sunriseLabel = lv_label_create(obj); + lv_obj_align(sunriseLabel, LV_ALIGN_TOP_RIGHT, 16, -2); + lv_label_set_text_static(sunriseLabel, ""); + sunsetLabel = lv_label_create(obj); + lv_obj_align(sunsetLabel,LV_ALIGN_BOTTOM_RIGHT, 16, 10); + lv_label_set_text_static(sunsetLabel, ""); + + lv_obj_t *img; + img = lv_img_create(obj); + lv_img_set_src(img, sunriseIconFile); + lv_img_set_zoom(img,iconScale); + lv_obj_update_layout(img); + lv_obj_align(img, LV_ALIGN_TOP_LEFT, -10, -10); + img = lv_img_create(obj); + lv_img_set_src(img, sunsetIconFile); + lv_img_set_zoom(img,iconScale); + lv_obj_update_layout(img); + lv_obj_align(img, LV_ALIGN_BOTTOM_LEFT, -10, 10); + + objUnselect(obj); + lv_obj_add_event_cb(obj, editWidget, LV_EVENT_LONG_PRESSED, NULL); + lv_obj_add_event_cb(obj, dragWidget, LV_EVENT_PRESSING, (char *)"Sun_"); + lv_obj_add_event_cb(obj, unselectWidget, LV_EVENT_RELEASED, (char *)"Sun_"); } \ No newline at end of file diff --git a/lib/gui/src/widgets.hpp b/lib/gui/src/widgets.hpp index f02c241d..1319a2a8 100644 --- a/lib/gui/src/widgets.hpp +++ b/lib/gui/src/widgets.hpp @@ -2,15 +2,13 @@ * @file widgets.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL - Widgets - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef WIDGETS_HPP #define WIDGETS_HPP -#include "lvgl.h" -#include "globalGuiDef.h" #include "globalMapsDef.h" #include "lvglFuncs.hpp" #include "gpsMath.hpp" @@ -26,6 +24,8 @@ extern lv_obj_t *compassHeading; extern lv_obj_t *compassImg; extern lv_obj_t *altitude; extern lv_obj_t *speedLabel; +extern lv_obj_t *sunriseLabel; +extern lv_obj_t *sunsetLabel; void editWidget(lv_event_t *event); void dragWidget(lv_event_t *event); @@ -36,14 +36,17 @@ static bool canMoveWidget = false; static lv_coord_t newX = 0; static lv_coord_t newY = 0; -static const char *arrowIconFile PROGMEM = "/arrow.bin"; // Compass Arrow Icon -static const char *positionIconFile PROGMEM = "/pin.bin"; // Position Icon -static const char *altitudeIconFile PROGMEM = "/altit.bin"; // Altitude Icon -static const char *speedIconFile PROGMEM = "/speed.bin"; // Speed Icon +static const char *arrowIconFile PROGMEM = "/arrow.bin"; // Compass Arrow Icon +static const char *positionIconFile PROGMEM = "/pin.bin"; // Position Icon +static const char *altitudeIconFile PROGMEM = "/altit.bin"; // Altitude Icon +static const char *speedIconFile PROGMEM = "/speed.bin"; // Speed Icon +static const char *sunriseIconFile PROGMEM = "/sunrise.bin"; // Sunrise Icon +static const char *sunsetIconFile PROGMEM = "/sunset.bin"; // Sunset Icon void positionWidget(_lv_obj_t *screen); void compassWidget(_lv_obj_t *screen); void altitudeWidget(_lv_obj_t *screen); void speedWidget(_lv_obj_t *screen); +void sunWidget(_lv_obj_t *screen); #endif \ No newline at end of file diff --git a/lib/lvgl/lv_conf.h b/lib/lvgl/lv_conf.h index 84b997c7..a7cf51cd 100644 --- a/lib/lvgl/lv_conf.h +++ b/lib/lvgl/lv_conf.h @@ -369,7 +369,7 @@ /** Default number of image header cache entries. The cache is used to store the headers of images * The main logic is like `LV_CACHE_DEF_SIZE` but for image headers. */ -#define LV_IMAGE_HEADER_CACHE_DEF_CNT 10 +#define LV_IMAGE_HEADER_CACHE_DEF_CNT 15 /** Number of stops allowed per gradient. Increase this to allow more stops. * This adds (sizeof(lv_color_t) + 1) bytes per additional stop. */ diff --git a/lib/lvgl/src/lvglFuncs.cpp b/lib/lvgl/src/lvglFuncs.cpp index c98b40e2..ce08fea9 100644 --- a/lib/lvgl/src/lvglFuncs.cpp +++ b/lib/lvgl/src/lvglFuncs.cpp @@ -2,8 +2,8 @@ * @file lvglFuncs.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL custom functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "lvglFuncs.hpp" diff --git a/lib/lvgl/src/lvglFuncs.hpp b/lib/lvgl/src/lvglFuncs.hpp index 73f29959..3edf2803 100644 --- a/lib/lvgl/src/lvglFuncs.hpp +++ b/lib/lvgl/src/lvglFuncs.hpp @@ -2,16 +2,13 @@ * @file lvglFuncs.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL custom functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef LVGLFUNCS_HPP #define LVGLFUNCS_HPP -#include -#include "tft.hpp" -#include "lvgl.h" #include "globalGuiDef.h" void objHideCursor(_lv_obj_t *obj); diff --git a/lib/lvgl/src/lvglSetup.cpp b/lib/lvgl/src/lvglSetup.cpp index b5b623de..2cb234ac 100644 --- a/lib/lvgl/src/lvglSetup.cpp +++ b/lib/lvgl/src/lvglSetup.cpp @@ -2,15 +2,11 @@ * @file lvglSetup.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL Screen implementation - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ -#include "lvgl_private.h" #include "lvglSetup.hpp" -#include "waypointScr.hpp" -#include "waypointListScr.hpp" -#include "globalGuiDef.h" ViewPort viewPort; // Vector map viewport MemCache memCache; // Vector map Memory Cache @@ -26,6 +22,8 @@ lv_group_t *scrGroup; // Screen group lv_group_t *keyGroup; // GPIO group lv_obj_t *powerMsg; // Power Message +Power power; + /** * @brief LVGL display update * @@ -61,7 +59,7 @@ void IRAM_ATTR touchRead(lv_indev_t *indev_driver, lv_indev_data_t *data) } else if (lv_display_get_rotation(display) == LV_DISPLAY_ROTATION_270) { - data->point.x = 320 - touchY; + data->point.x = TFT_WIDTH - touchY; data->point.y = touchX; } data->state = LV_INDEV_STATE_PRESSED; @@ -137,7 +135,6 @@ void IRAM_ATTR gpioRead(lv_indev_t *indev_driver, lv_indev_data_t *data) */ void gpioLongEvent(lv_event_t *event) { - lv_event_code_t code = lv_event_get_code(event); log_v("Shuting down device"); powerMsg = lv_msgbox_create(lv_scr_act()); lv_obj_set_width(powerMsg,TFT_WIDTH); @@ -149,7 +146,7 @@ void gpioLongEvent(lv_event_t *event) lv_obj_invalidate(powerMsg); lv_refr_now(display); vTaskDelay(2000); - deviceShutdown(); + power.deviceShutdown(); } /** @@ -158,7 +155,6 @@ void gpioLongEvent(lv_event_t *event) */ void gpioClickEvent(lv_event_t *event) { - lv_event_code_t code = lv_event_get_code(event); lv_indev_reset_long_press(lv_indev_active()); lv_indev_reset(NULL,lv_scr_act()); log_v("Entering sleep mode"); @@ -172,7 +168,7 @@ void gpioClickEvent(lv_event_t *event) lv_obj_invalidate(powerMsg); lv_refr_now(display); vTaskDelay(2000); - deviceSuspend(); + power.deviceSuspend(); } /** @@ -350,6 +346,7 @@ void initLVGL() void loadMainScreen() { isMainScreen = true; + isScrolled = true; isSearchingSat = false; wptAction = WPT_NONE; lv_screen_load(mainScreen); diff --git a/lib/lvgl/src/lvglSetup.hpp b/lib/lvgl/src/lvglSetup.hpp index c0588183..32d3d341 100644 --- a/lib/lvgl/src/lvglSetup.hpp +++ b/lib/lvgl/src/lvglSetup.hpp @@ -2,35 +2,24 @@ * @file lvglSetup.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LVGL Screen implementation - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef LVGLSETUP_HPP #define LVGLSETUP_HPP -#include - -#include "esp_attr.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#ifdef TDECK_ESP32S3 - #include "Wire.h" -#endif - #define LV_TICK_PERIOD_MS 5 -#include "globalGuiDef.h" +#include "lvgl_private.h" +// #ifdef TDECK_ESP32S3 +// #include "Wire.h" +// #endif #include "splashScr.hpp" -#include "searchSatScr.hpp" #include "notifyBar.hpp" -#include "widgets.hpp" -#include "mainScr.hpp" -#include "buttonBar.hpp" #include "settingsScr.hpp" #include "deviceSettingsScr.hpp" #include "mapSettingsScr.hpp" -#include "waypointScr.hpp" /** * @brief Default display driver definition diff --git a/lib/maps/src/globalMapsDef.h b/lib/maps/src/globalMapsDef.h index 18151ba6..baaee1f4 100644 --- a/lib/maps/src/globalMapsDef.h +++ b/lib/maps/src/globalMapsDef.h @@ -1,8 +1,8 @@ /** * @file globalMapsDef.h * @brief Global Maps Variables - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef GLOBALMAPSDEF_H @@ -133,5 +133,11 @@ struct tileBounds */ extern tileBounds totalBounds; +/** + * @brief Waypoint destination latitude and longitude + * + */ +extern double destLat; +extern double destLon; #endif diff --git a/lib/maps/src/mapsDrawFunc.h b/lib/maps/src/mapsDrawFunc.h index 0f2709bb..0db1ed15 100644 --- a/lib/maps/src/mapsDrawFunc.h +++ b/lib/maps/src/mapsDrawFunc.h @@ -1,8 +1,8 @@ /** * @file mapsDrawFunc.h * @brief Extra Draw functions for maps - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef MAPSDRAWFUNC_H @@ -94,8 +94,8 @@ static void drawMapWidgets() mapHeight = MAP_HEIGHT; - int toolBarOffset = 0; - int toolBarSpace = 0; + uint8_t toolBarOffset = 0; + uint8_t toolBarSpace = 0; #ifdef LARGE_SCREEN toolBarOffset = 100; toolBarSpace = 60; @@ -183,7 +183,10 @@ static void displayMap(uint16_t tileSize) } if (tileSize == VECTOR_TILE_SIZE) + { + mapTempSprite.pushImage(wptPosX-8, wptPosY-8, 16 ,16 ,(uint16_t*)waypoint, TFT_BLACK); mapTempSprite.setPivot(tileSize , tileSize ); + } mapTempSprite.pushRotated(&mapSprite, 360 - mapHeading, TFT_TRANSPARENT); //mapTempSprite.pushRotated(&mapSprite, 0, TFT_TRANSPARENT); diff --git a/lib/maps/src/renderMaps.cpp b/lib/maps/src/renderMaps.cpp index c71dadc1..8a4c1168 100644 --- a/lib/maps/src/renderMaps.cpp +++ b/lib/maps/src/renderMaps.cpp @@ -2,14 +2,11 @@ * @file renderMaps.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Render maps draw functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "renderMaps.hpp" -#include "mapsDrawFunc.h" - -extern const int SD_CS; MapTile oldMapTile = {(char*)"", 0, 0, 0}; // Old Map tile coordinates and zoom MapTile currentMapTile = {(char*)"", 0, 0, 0}; // Current Map tile coordinates and zoom @@ -20,8 +17,6 @@ bool isMapFound = false; tileBounds totalBounds = { 90.0, -90.0, 180.0, -180.0}; - - /** * @brief Tile size for position calculation * @@ -172,9 +167,6 @@ void generateRenderMap() if (strcmp(currentMapTile.file, oldMapTile.file) != 0 || currentMapTile.zoom != oldMapTile.zoom || currentMapTile.tilex != oldMapTile.tilex || currentMapTile.tiley != oldMapTile.tiley) { - // deleteMapScrSprites(); - // createMapScrSprites(); - isMapFound = mapTempSprite.drawPngFile(SD, currentMapTile.file, tileSize, tileSize); if (!isMapFound) diff --git a/lib/maps/src/renderMaps.hpp b/lib/maps/src/renderMaps.hpp index 0355c7c0..d61a9be0 100644 --- a/lib/maps/src/renderMaps.hpp +++ b/lib/maps/src/renderMaps.hpp @@ -2,18 +2,14 @@ * @file renderMaps.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Render maps draw functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef RENDERMAPS_HPP #define RENDERMAPS_HPP -#include -#include "tft.hpp" -#include "compass.hpp" #include "settings.hpp" -#include "globalMapsDef.h" #include "mapsDrawFunc.h" /** @@ -34,9 +30,6 @@ extern MapTile oldMapTile; // Old Map tile coordinates and zoom extern MapTile currentMapTile; // Current Map tile coordinates and zoom extern MapTile roundMapTile; // Boundaries Map tiles -extern double destLat; -extern double destLon; - uint32_t lon2tilex(double f_lon, uint8_t zoom); uint32_t lat2tiley(double f_lat, uint8_t zoom); double tilex2lon(uint32_t tileX, uint8_t zoom); @@ -45,8 +38,6 @@ tileBounds getTileBounds(uint32_t tileX, uint32_t tileY, uint8_t zoom); bool isCoordInBounds(double lat, double lon, tileBounds bound); void coords2map(double lat, double lon, tileBounds bound, int *pixelX, int *pixelY); MapTile getMapTile(double lon, double lat, uint8_t zoomLevel, int16_t offsetX, int16_t offsetY); -void drawMapWidgets(); void generateRenderMap(); -void initSD(); #endif diff --git a/lib/maps/src/vectorMaps.cpp b/lib/maps/src/vectorMaps.cpp index a162658c..230ef737 100644 --- a/lib/maps/src/vectorMaps.cpp +++ b/lib/maps/src/vectorMaps.cpp @@ -2,8 +2,8 @@ * @file vectorMaps.cpp * @author @aresta - https://github.com/aresta/ESP32_GPS * @brief Vector maps draw functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "vectorMaps.hpp" @@ -66,7 +66,6 @@ void getPosition(double lat, double lon) Coord pos; pos.lat = lat; pos.lng = lon; - if (abs(pos.lat - prevLat) > 0.00005 && abs(pos.lng - prevLng) > 0.00005) { point.x = lon2x(pos.lng); @@ -204,7 +203,6 @@ BBox parseBbox(String str) MapBlock *readMapBlock(String fileName) { log_d("readMapBlock: %s", fileName.c_str()); - char c; char str[30]; MapBlock *mblock = new MapBlock(); fs::File file_ = SD.open(fileName + ".fmp"); @@ -236,7 +234,6 @@ MapBlock *readMapBlock(String fileName) uint32_t totalPoints = 0; Polygon polygon; Point16 p; - int16_t maxVectorZoom;// = 4; while (count > 0) { // log_d("line: %i", line); @@ -573,6 +570,26 @@ void generateVectorMap(ViewPort &viewPort, MemCache &memCache, TFT_eSprite &map) // TILE_WIDTH / 2, TILE_HEIGHT / 2 - 6, // RED); log_d("Draw done! %i", millis()); + + MapBlock *firstBlock = memCache.blocks.front(); + delete firstBlock; + memCache.blocks.erase(memCache.blocks.begin()); + + totalBounds.lat_min = mercatorY2lat(viewPort.bbox.min.y); + totalBounds.lat_max = mercatorY2lat(viewPort.bbox.max.y); + totalBounds.lon_min = mercatorX2lon(viewPort.bbox.min.x); + totalBounds.lon_max = mercatorX2lon(viewPort.bbox.max.x); + + log_i("Total Bounds: Lat Min: %f, Lat Max: %f, Lon Min: %f, Lon Max: %f", + totalBounds.lat_min, totalBounds.lat_max, totalBounds.lon_min, totalBounds.lon_max); + + if(isCoordInBounds(destLat,destLon,totalBounds)) + coords2map(destLat, destLon, totalBounds, &wptPosX, &wptPosY); + else + { + wptPosX = -1; + wptPosY = -1; + } } else { diff --git a/lib/maps/src/vectorMaps.hpp b/lib/maps/src/vectorMaps.hpp index bbef50d4..ff507ed1 100644 --- a/lib/maps/src/vectorMaps.hpp +++ b/lib/maps/src/vectorMaps.hpp @@ -2,24 +2,18 @@ * @file vectorMaps.hpp * @author @aresta - https://github.com/aresta/ESP32_GPS * @brief Vector maps draw functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef VECTORMAPS_HPP #define VECTORMAPS_HPP -#include -#include #include -#include -#include #include -#include -#include #include #include "globalMapsDef.h" -#include "tft.hpp" +#include "renderMaps.hpp" #include "gpsMath.hpp" #include "settings.hpp" @@ -61,6 +55,8 @@ const int32_t MAPFOLDER_MASK = pow(2, MAPFOLDER_SIZE_BITS) - 1; // ...00001111 static double lat2y(double lat) { return log(tan(DEG2RAD(lat) / 2 + M_PI / 4)) * EARTH_RADIUS; } static double lon2x(double lon) { return DEG2RAD(lon) * EARTH_RADIUS; } +static double mercatorX2lon(double x) { return (x / EARTH_RADIUS) * (180.0 / M_PI); } +static double mercatorY2lat(double y) { return (atan(sinh(y / EARTH_RADIUS))) * (180.0 / M_PI); } /** * @brief Point in 16 bits projected coordinates (x,y) @@ -187,7 +183,7 @@ struct MemBlocks }; /** - * @brief Point in geografic (lat,lon) coordinates and other gps data + * @brief Point in geographic (lat,lon) coordinates and other gps data * */ struct Coord diff --git a/lib/panel/ICENAV_BOARD.hpp b/lib/panel/ICENAV_BOARD.hpp index a70a8a04..6e4e2ac4 100644 --- a/lib/panel/ICENAV_BOARD.hpp +++ b/lib/panel/ICENAV_BOARD.hpp @@ -2,8 +2,8 @@ * @file ICENAV_BOARD.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LOVYANGFX TFT driver for IceNaV board - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef ICENAV_BOARD_HPP diff --git a/lib/panel/ILI9341_XPT2046_SPI.hpp b/lib/panel/ILI9341_XPT2046_SPI.hpp index 43d3c2c0..a810e5b2 100644 --- a/lib/panel/ILI9341_XPT2046_SPI.hpp +++ b/lib/panel/ILI9341_XPT2046_SPI.hpp @@ -2,8 +2,8 @@ // * @file ILI9341_XPT2046_SPI.hpp // * @author Jordi Gauchía (jgauchia@gmx.es) // * @brief LOVYANGFX TFT driver for ILI9341 SPI With XPT2046 Touch controller -// * @version 0.1.8 -// * @date 2024-11 +// * @version 0.1.9 +// * @date 2024-12 // */ #ifndef ILI9341_XPT2046_SPI_HPP diff --git a/lib/panel/ILI9488_FT5x06_16B.hpp b/lib/panel/ILI9488_FT5x06_16B.hpp index 03d17c0e..60f08979 100644 --- a/lib/panel/ILI9488_FT5x06_16B.hpp +++ b/lib/panel/ILI9488_FT5x06_16B.hpp @@ -2,8 +2,8 @@ * @file ILI9488_FT5x06_16B.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LOVYANGFX TFT driver for ILI9488 16 Bits parallel With FT5x06 Touch controller - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef ILI9488_FT5x06_16B_HPP diff --git a/lib/panel/ILI9488_FT5x06_SPI.hpp b/lib/panel/ILI9488_FT5x06_SPI.hpp index 0828819d..c1ec522a 100644 --- a/lib/panel/ILI9488_FT5x06_SPI.hpp +++ b/lib/panel/ILI9488_FT5x06_SPI.hpp @@ -2,8 +2,8 @@ * @file ILI9488_XPT2046_SPI.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LOVYANGFX TFT driver for ILI9488 SPI With XPT2046 Touch controller - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef ILI9488_XPT2046_SPI_HPP diff --git a/lib/panel/ILI9488_NOTOUCH_8B.hpp b/lib/panel/ILI9488_NOTOUCH_8B.hpp index 8dc3efc8..e9d4edff 100644 --- a/lib/panel/ILI9488_NOTOUCH_8B.hpp +++ b/lib/panel/ILI9488_NOTOUCH_8B.hpp @@ -2,8 +2,8 @@ * @file ILI9488_NOTOUCH_8B.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LOVYANGFX TFT driver for ILI9488 8 Bits parallel Without Touch controller - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef ILI9488_NOTOUCH_8B_HPP diff --git a/lib/panel/ILI9488_XPT2046_SPI.hpp b/lib/panel/ILI9488_XPT2046_SPI.hpp index 5535bba2..f7b90152 100644 --- a/lib/panel/ILI9488_XPT2046_SPI.hpp +++ b/lib/panel/ILI9488_XPT2046_SPI.hpp @@ -2,8 +2,8 @@ * @file ILI9488_XPT2046_SPI.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief LOVYANGFX TFT driver for ILI9488 SPI With XPT2046 Touch controller - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef ILI9488_XPT2046_SPI_HPP diff --git a/lib/panel/LILYGO_TDECK.hpp b/lib/panel/LILYGO_TDECK.hpp index effad505..0428757b 100644 --- a/lib/panel/LILYGO_TDECK.hpp +++ b/lib/panel/LILYGO_TDECK.hpp @@ -2,8 +2,8 @@ * @file LILYGO_TDECK.hpp * @author Jordi Gauchía (jgauchia@gmx.es) and Antonio Vanegas @Hpsturn * @brief LOVYANGFX TFT driver for ST7789 SPI With GT911 Touch controller - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef LILYGO_TDECK_HPP diff --git a/lib/power/power.cpp b/lib/power/power.cpp index 6641aac6..26b09aaf 100644 --- a/lib/power/power.cpp +++ b/lib/power/power.cpp @@ -2,28 +2,44 @@ * @file power.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief ESP32 Power Management functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "power.hpp" extern const uint8_t BOARD_BOOT_PIN; +Power::Power() +{ + #ifdef DISABLE_RADIO + WiFi.disconnect(true); + WiFi.mode(WIFI_OFF); + btStop(); + esp_wifi_stop(); + esp_bt_controller_disable(); + #endif +} + /** * @brief Deep Sleep Mode * */ -void powerDeepSleep() +void Power::powerDeepSleep() { esp_bluedroid_disable(); esp_bt_controller_disable(); esp_wifi_stop(); esp_deep_sleep_disable_rom_logging(); delay(10); - // If you need other peripherals to maintain power, please set the IO port to hold - // gpio_hold_en((gpio_num_t)BOARD_POWERON); - // gpio_deep_sleep_hold_en(); + + #ifdef ICENAV_BOARD + // If you need other peripherals to maintain power, please set the IO port to hold + gpio_hold_en((gpio_num_t)TFT_BL); + gpio_hold_en((gpio_num_t)BOARD_BOOT_PIN); + gpio_deep_sleep_hold_en(); + #endif + esp_sleep_enable_ext1_wakeup(1ull << BOARD_BOOT_PIN, ESP_EXT1_WAKEUP_ANY_LOW); esp_deep_sleep_start(); } @@ -33,7 +49,7 @@ void powerDeepSleep() * * @param millis */ -void powerLightSleepTimer(int millis) +void Power::powerLightSleepTimer(int millis) { esp_sleep_enable_timer_wakeup(millis * 1000); esp_err_t rtc_gpio_hold_en(gpio_num_t GPIO_NUM_5); @@ -44,16 +60,27 @@ void powerLightSleepTimer(int millis) * @brief Sleep Mode * */ -void powerLightSleep() +void Power::powerLightSleep() { esp_sleep_enable_ext1_wakeup(1ull << BOARD_BOOT_PIN, ESP_EXT1_WAKEUP_ANY_LOW); esp_light_sleep_start(); } +/** + * @brief Power off peripherals devices + */ +void Power::powerOffPeripherals() +{ + tftOff(); + tft.fillScreen(TFT_BLACK); + SPI.end(); + Wire.end(); +} + /** * @brief Core light suspend and TFT off */ -void deviceSuspend() +void Power::deviceSuspend() { int brightness = tft.getBrightness(); lv_msgbox_close(powerMsg); @@ -70,34 +97,27 @@ void deviceSuspend() /** * @brief Power off peripherals and deep sleep + * */ -void deviceShutdown() +void Power::deviceShutdown() { powerOffPeripherals(); powerDeepSleep(); } -/** - * @brief Power off peripherals devices - */ -void powerOffPeripherals() -{ - tftOff(); - SPI.end(); - Wire.end(); -} -/** - * @brief On Mode - * - */ -void powerOn() -{ -#ifdef DISABLE_RADIO - WiFi.disconnect(true); - WiFi.mode(WIFI_OFF); - btStop(); - esp_wifi_stop(); - esp_bt_controller_disable(); -#endif -} + +// /** +// * @brief On Mode +// * +// */ +// void powerOn() +// { +// #ifdef DISABLE_RADIO +// WiFi.disconnect(true); +// WiFi.mode(WIFI_OFF); +// btStop(); +// esp_wifi_stop(); +// esp_bt_controller_disable(); +// #endif +// } diff --git a/lib/power/power.hpp b/lib/power/power.hpp index 6ad300aa..caf37a18 100644 --- a/lib/power/power.hpp +++ b/lib/power/power.hpp @@ -2,8 +2,8 @@ * @file power.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief ESP32 Power Management functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef POWER_HPP @@ -19,12 +19,20 @@ #include "lvgl.h" #include "globalGuiDef.h" -void powerDeepSeep(); -void powerLightSleepTimer(int millis); -void powerLightSleep(); -void powerOffPeripherals(); -void deviceSuspend(); -void deviceShutdown(); -void powerOn(); +class Power +{ +private: + void powerDeepSleep(); + void powerLightSleepTimer(int millis); + void powerLightSleep(); + void powerOffPeripherals(); + +public: + Power(); + + void deviceSuspend(); + void deviceShutdown(); +}; + #endif \ No newline at end of file diff --git a/lib/preferences/preferences-keys.h b/lib/preferences/preferences-keys.h index 88d13d00..3ad63447 100644 --- a/lib/preferences/preferences-keys.h +++ b/lib/preferences/preferences-keys.h @@ -13,12 +13,15 @@ X(KALTITUDE_Y, "Altitude_Y", INT) \ X(KSPEED_X, "Speed_X", INT) \ X(KSPEED_Y, "Speed_Y", INT) \ + X(KSUN_X, "Sun_X", INT) \ + X(KSUN_Y, "Sun_Y", INT) \ X(KCOMP_OFFSET_X, "C_offset_x", FLOAT) \ X(KCOMP_OFFSET_Y, "C_offset_y", FLOAT) \ X(KCOMP_ROT, "Compass_rot", BOOL) \ X(KGPS_SPEED, "GPS_speed", SHORT) \ X(KGPS_RATE, "GPS_rate", SHORT) \ X(KWEB_FILE, "Web_file", BOOL) \ + X(KDST_ZONE, "defDST", STRING) \ X(KUSER, "-----", UNKNOWN) \ X(KDEF_ZOOM, "defZoom", UINT) \ X(KGPS_TX, "gpsTX", UINT) \ @@ -29,4 +32,5 @@ X(KVMAX_BATT, "VmaxBatt", FLOAT) \ X(KVMIN_BATT, "VminBatt", FLOAT) \ X(KTEMP_OFFS, "tempOffs", INT) \ + X(KGMT_OFFS, "defGMT", INT) \ X(KCOUNT, "KCOUNT", UNKNOWN) diff --git a/lib/settings/settings.cpp b/lib/settings/settings.cpp index 142625b7..9abb2ad2 100644 --- a/lib/settings/settings.cpp +++ b/lib/settings/settings.cpp @@ -2,8 +2,8 @@ * @file settings.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Settings functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "settings.hpp" @@ -31,6 +31,7 @@ uint8_t zoom = 0; // Actual Zoom Level bool isMapRotation = true; // Map Compass Rotation uint8_t defaultZoom = 0; // Default Zoom Value uint8_t defBright = 255; // Default Brightness +int32_t defGMT = 1; // Default GMT offset bool showMapCompass = true; // Compass in map screen bool isCompassRot = true; // Compass rotation in map screen bool showMapSpeed = true; // Speed in map screen @@ -47,9 +48,14 @@ uint16_t altitudePosX = 0; // Altitude widget position X uint16_t altitudePosY = 0; // Altitude widget position Y uint16_t speedPosX = 0; // Speed widget position X uint16_t speedPosY = 0; // Speed widget position Y +uint16_t sunPosX = 0; // Sunrise/sunset position X +uint16_t sunPosY = 0; // Sunrise/sunset position Y bool enableWeb = true; // Enable/disable web file server bool showToolBar = false; // Show Map Toolbar int8_t tempOffset = 0; // BME Temperature offset +extern Battery battery; +String defDST = "NONE"; // default DST zone +bool calculateDST = false; // Calculate DST flag // float batteryMax = 0.0; // 4.2; // maximum voltage of battery // float batteryMin = 0.0; // 3.6; // minimum voltage of battery before shutdown @@ -79,8 +85,11 @@ void loadPreferences() altitudePosY = cfg.getInt(PKEYS::KALTITUDE_Y, TFT_HEIGHT - 170); speedPosX = cfg.getInt(PKEYS::KSPEED_X, 1); speedPosY = cfg.getInt(PKEYS::KSPEED_Y, TFT_HEIGHT - 130); + sunPosX = cfg.getInt(PKEYS::KSUN_X, 170); + sunPosY = cfg.getInt(PKEYS::KSUN_Y, TFT_HEIGHT - 170 ); isVectorMap = cfg.getBool(PKEYS::KMAP_VECTOR, false); defBright = cfg.getUInt(PKEYS::KDEF_BRIGT, 254); + defGMT = cfg.getInt(PKEYS::KGMT_OFFS, 1); if (isVectorMap) { minZoom = 1; @@ -110,19 +119,17 @@ void loadPreferences() altitudePosY = cfg.isKey(CONFKEYS::KALTITUDE_Y) ? cfg.getInt(CONFKEYS::KALTITUDE_Y, altitudePosY) : 57; speedPosX = cfg.isKey(CONFKEYS::KSPEED_X) ? cfg.getInt(CONFKEYS::KSPEED_X, speedPosX) : 3; speedPosY = cfg.isKey(CONFKEYS::KSPEED_Y) ? cfg.getInt(CONFKEYS::KSPEED_Y, speedPosY) : 94; + sunPosX = cfg.isKey(CONFKEYS::KSUN_X) ? cfg.getInt(CONFKEYS::KSPEED_X, speedPosX) : 3; + sunPosY = cfg.isKey(CONFKEYS::KSUN_Y) ? cfg.getInt(CONFKEYS::KSPEED_Y, speedPosY) : 110; #endif - batteryMax = cfg.getFloat(PKEYS::KVMAX_BATT,4.2); - batteryMin = cfg.getFloat(PKEYS::KVMIN_BATT,3.6); + battery.setBatteryLevels(cfg.getFloat(PKEYS::KVMAX_BATT,4.2),cfg.getFloat(PKEYS::KVMIN_BATT,3.6)); - // compassPosX = 60; - // compassPosY = 82; - // coordPosX = 66; - // coordPosY = 29; - // altitudePosX = 8; - // altitudePosY = 293; - // speedPosX = 1; - // speedPosY = 337; + defDST = cfg.getString(PKEYS::KDST_ZONE, "EU"); + if (defDST.equals("NONE")) + calculateDST = false; + else + calculateDST = true; printSettings(); } diff --git a/lib/settings/settings.hpp b/lib/settings/settings.hpp index 40df22e1..8501c63f 100644 --- a/lib/settings/settings.hpp +++ b/lib/settings/settings.hpp @@ -2,8 +2,8 @@ * @file settings.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Settings functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef SETTINGS_HPP @@ -21,8 +21,6 @@ extern uint8_t defZoomRender; // Default Zoom Level for render map extern uint8_t defZoomVector; // Default Zoom Level for vector map extern uint8_t zoom; // Actual Zoom Level extern uint8_t defBright; // Default brightness -extern float batteryMax; // 4.2; // maximum voltage of battery -extern float batteryMin; // 3.6; // minimum voltage of battery before shutdown extern bool isMapRotation; // Map Compass Rotation extern uint8_t defaultZoom; // Default Zoom Value @@ -43,8 +41,12 @@ extern uint16_t altitudePosX; // Altitude widget position X extern uint16_t altitudePosY; // Altitude widget position Y extern uint16_t speedPosX; // Speed widget position X extern uint16_t speedPosY; // Speed widget position Y +extern uint16_t sunPosX; // Sunrise/sunset position X +extern uint16_t sunPosY; // Sunrise/sunset position Y extern bool enableWeb; // Enable/disable web file server extern int8_t tempOffset; // BME Temperature offset +extern String defDST; // default DST zone +extern bool calculateDST; // Calculate DST flag void loadPreferences(); void saveMapRotation(bool zoomRotation); diff --git a/lib/storage/storage.cpp b/lib/storage/storage.cpp index 5530f5ab..d784369b 100644 --- a/lib/storage/storage.cpp +++ b/lib/storage/storage.cpp @@ -2,82 +2,90 @@ * @file storage.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Storage definition and functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "storage.hpp" -#include "esp_err.h" -#include "esp_spiffs.h" -bool isSdLoaded = false; -extern const int SD_CS; -extern const int SD_MISO; -extern const int SD_MOSI; -extern const int SD_CLK; -extern const int BOARD_TFT_CS; -extern const int RADIO_CS_PIN; +// Pin definitions (should be configurable if needed) +extern const uint8_t SD_CS; +extern const uint8_t SD_MISO; +extern const uint8_t SD_MOSI; +extern const uint8_t SD_CLK; + +Storage::Storage() : isSdLoaded(false) {} + /** * @brief SD Card init * */ -void initSD() +void Storage::initSD() { - bool SDInitOk = false; - pinMode(SD_CS,OUTPUT); - digitalWrite(SD_CS,LOW); + pinMode(SD_CS, OUTPUT); + digitalWrite(SD_CS, LOW); - SPI.begin(SD_CLK, SD_MISO, SD_MOSI); - SDInitOk = SD.begin(SD_CS, SPI, sdFreq); - - if (!SDInitOk) - { - log_e("SD Card Mount Failed"); - return; - } - else - { - log_v("SD Card Mounted"); - isSdLoaded = true; - } - } + SPI.begin(SD_CLK, SD_MISO, SD_MOSI); + + if (!SD.begin(SD_CS, SPI, sdFreq)) + { + log_e("SD Card Mount Failed"); + isSdLoaded = false; + } + else + { + log_v("SD Card Mounted"); + isSdLoaded = true; + } +} /** - * @brief SPIFFS Init + * @brief SPIFFS initialization * + * @return esp_err_t Error code for SPIFFS setup */ -esp_err_t initSPIFFS() +esp_err_t Storage::initSPIFFS() { - log_i("Initializing SPIFFS"); + log_i("Initializing SPIFFS"); - esp_vfs_spiffs_conf_t conf = { - .base_path = "/spiffs", - .partition_label = NULL, - .max_files = 5, - .format_if_mount_failed = false - }; + esp_vfs_spiffs_conf_t conf = + { + .base_path = "/spiffs", + .partition_label = NULL, + .max_files = 5, + .format_if_mount_failed = false + }; - esp_err_t ret = esp_vfs_spiffs_register(&conf); + esp_err_t ret = esp_vfs_spiffs_register(&conf); - if (ret !=ESP_OK) - { - if (ret == ESP_FAIL) - log_e("Failed to mount or format filesystem"); - else if (ret == ESP_ERR_NOT_FOUND) - log_e("Failed to find SPIFFS partition"); + if (ret != ESP_OK) + { + if (ret == ESP_FAIL) + log_e("Failed to mount or format filesystem"); + else if (ret == ESP_ERR_NOT_FOUND) + log_e("Failed to find SPIFFS partition"); + else + log_e("Failed to initialize SPIFFS (%s)", esp_err_to_name(ret)); + return ESP_FAIL; + } + + size_t total = 0, used = 0; + ret = esp_spiffs_info(NULL, &total, &used); + if (ret != ESP_OK) + log_e("Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret)); else - log_e("Failed to initialize SPIFFS (%s)",esp_err_to_name(ret)); - return ESP_FAIL; - } + log_i("Partition size: total: %d used: %d", total, used); - size_t total = 0, used = 0; - ret = esp_spiffs_info(NULL, &total, &used); - if (ret!= ESP_OK) - log_e("Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret)); - else - log_i("Partition size: total: %d used: %d", total, used); - - return ESP_OK; + return ESP_OK; } +/** + * @brief Get SD status + * + * @return true if SD card is loaded, false otherwise + */ +bool Storage::getSdLoaded() const +{ + return isSdLoaded; +} diff --git a/lib/storage/storage.hpp b/lib/storage/storage.hpp index 166ba4d6..01d688b6 100644 --- a/lib/storage/storage.hpp +++ b/lib/storage/storage.hpp @@ -2,23 +2,29 @@ * @file storage.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Storage definition and functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef STORAGE_HPP #define STORAGE_HPP #include "esp_spiffs.h" +#include "esp_err.h" #include -#include -#include -static uint32_t sdFreq = 40000000; +class Storage +{ +private: + bool isSdLoaded; + static const uint32_t sdFreq = 40000000; -extern bool isSdLoaded; +public: + Storage(); -void initSD(); -esp_err_t initSPIFFS(); + void initSD(); + esp_err_t initSPIFFS(); + bool getSdLoaded() const; +}; #endif diff --git a/lib/tasks/tasks.cpp b/lib/tasks/tasks.cpp index 8ecf3e8b..95643cee 100644 --- a/lib/tasks/tasks.cpp +++ b/lib/tasks/tasks.cpp @@ -2,13 +2,11 @@ * @file tasks.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Core Tasks functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "tasks.hpp" -#include "Arduino.h" -#include "freertos/FreeRTOS.h" TaskHandle_t LVGLTaskHandler; xSemaphoreHandle gpsMutex; diff --git a/lib/tasks/tasks.hpp b/lib/tasks/tasks.hpp index 2351aeac..25c4648e 100644 --- a/lib/tasks/tasks.hpp +++ b/lib/tasks/tasks.hpp @@ -2,8 +2,8 @@ * @file tasks.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Core Tasks functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef TASKS_HPP @@ -24,6 +24,10 @@ void gpsTask(void *pvParameters); void initGpsTask(); -void initCLITask(); + +#ifndef DISABLE_CLI + void cliTask(void *param); + void initCLITask(); +#endif #endif diff --git a/lib/tft/tft.cpp b/lib/tft/tft.cpp index b01896fa..0e85f065 100644 --- a/lib/tft/tft.cpp +++ b/lib/tft/tft.cpp @@ -2,8 +2,8 @@ * @file tft.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief TFT definition and functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "tft.hpp" @@ -14,12 +14,6 @@ uint16_t TFT_WIDTH = 0; uint16_t TFT_HEIGHT = 0; bool waitScreenRefresh = false; -#ifdef TDECK_ESP32S3 - extern const uint8_t TFT_SPI_BL; -#endif - - - /** * @brief Turn on TFT Sleep Mode for ILI9488 * diff --git a/lib/tft/tft.hpp b/lib/tft/tft.hpp index 9b9ab578..97600ec7 100644 --- a/lib/tft/tft.hpp +++ b/lib/tft/tft.hpp @@ -2,8 +2,8 @@ * @file tft.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief TFT definition and functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef TFT_HPP diff --git a/lib/upgrade/src/firmUpgrade.cpp b/lib/upgrade/src/firmUpgrade.cpp new file mode 100644 index 00000000..1a96d9d7 --- /dev/null +++ b/lib/upgrade/src/firmUpgrade.cpp @@ -0,0 +1,98 @@ +/** + * @file firmUpgrade.cpp + * @author Jordi Gauchía (jgauchia@gmx.es) + * @brief Firmware upgrade from SD functions + * @version 0.1.9 + * @date 2024-12 + */ + + #include "firmUpgrade.hpp" + +/** + * @brief Check if firmware file exist + * + * @return true/false + */ +bool checkFileUpgrade() +{ +if (SD.exists(upgrdFile)) + return true; +else + return false; +} + +/** + * @brief Firmware upgrade start callback + * + */ +void onUpgrdStart() +{ + log_v("Try to upgrade firmware..."); + File firmware = SD.open(upgrdFile); + Update.onProgress(onUpgrdProcess); + Update.begin(firmware.size(), U_FLASH); + Update.writeStream(firmware); + if (Update.end()) + { + log_v("Upgrade finished!"); + } + else + { + log_e("Upgrade error!"); + lv_label_set_text_static(msgUprgdText, LV_SYMBOL_WARNING " Upgrade error!"); + lv_obj_clear_flag(btnMsgBack,LV_OBJ_FLAG_HIDDEN); + lv_obj_add_flag(contMeter,LV_OBJ_FLAG_HIDDEN); + } + firmware.close(); +} + +/** + * @brief Draw progress bar + * + * @param x -> X Position + * @param y -> Y Position + * @param w -> Bar width + * @param h -> Bar height + * @param percent -> Percent to show + * @param frameColor -> Bar frame color + * @param barColor -> Bar color + */ +void drawProgressBar(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t percent, uint16_t frameColor, uint16_t barColor) +{ + if (percent == 0) + tft.fillRoundRect(x, y, w, h, 3, TFT_BLACK); + uint8_t margin = 2; + uint16_t barHeight = h - 2 * margin; + uint16_t barWidth = w - 2 * margin; + tft.drawRoundRect(x, y, w, h, 3, frameColor); + tft.fillRect(x + margin, y + margin, barWidth * percent / 100.0, barHeight, barColor); +} + +/** + * @brief Firmware upgrade process callback + * + * @param currSize -> Current size from file + * @param totalSize -> Total size from file + */ +void onUpgrdProcess(size_t currSize, size_t totalSize) +{ + float progress = (currSize * 100) / totalSize; + log_v("Firmware Upgrade process %d ...", (int)progress); + char strProgress[30]; + sprintf(strProgress,"Upgrading... %d%%",(int)progress); + tft.drawCenterString(strProgress, tft.width() >> 1, (tft.height() >> 1)+25, &fonts::FreeSans9pt7b); + drawProgressBar(40,tft.height() >> 1,TFT_WIDTH - 80,20,(int)progress,TFT_WHITE,TFT_BLUE); + if ((int)progress == 100) + tft.drawCenterString("Upgrade complete", tft.width() >> 1, (tft.height() >> 1)+25, &fonts::FreeSans9pt7b); +} + +/** + * @brief Firmware upgrade end callback + * + */ +void onUpgrdEnd() +{ + delay(500); + log_i("Rebooting ESP32: "); + ESP.restart(); +} \ No newline at end of file diff --git a/lib/upgrade/src/firmUpgrade.hpp b/lib/upgrade/src/firmUpgrade.hpp new file mode 100644 index 00000000..8c7a5d7c --- /dev/null +++ b/lib/upgrade/src/firmUpgrade.hpp @@ -0,0 +1,26 @@ +/** + * @file firmUpgrade.hpp + * @author Jordi Gauchía (jgauchia@gmx.es) + * @brief Firmware upgrade from SD functions + * @version 0.1.9 + * @date 2024-12 + */ + +#ifndef FIRMUPGRADE_HPP +#define FIRMUPGRADE_HPP + +#include +#include "tft.hpp" +#include "lvgl.h" +#include "upgradeScr.hpp" +#include "SD.h" + +static const char *upgrdFile PROGMEM = "/firmware.bin"; // Firmware upgrade file + +bool checkFileUpgrade(); +void onUpgrdStart(); +void drawProgressBar(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t percent, uint16_t frameColor, uint16_t barColor); +void onUpgrdProcess(size_t currSize, size_t totalSize); +void onUpgrdEnd(); + +#endif \ No newline at end of file diff --git a/lib/utils/src/gpsMath.cpp b/lib/utils/src/gpsMath.cpp index d4a3248c..2c371fa3 100644 --- a/lib/utils/src/gpsMath.cpp +++ b/lib/utils/src/gpsMath.cpp @@ -2,8 +2,8 @@ * @file gpsMath.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Math and various functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "gpsMath.hpp" diff --git a/lib/utils/src/gpsMath.hpp b/lib/utils/src/gpsMath.hpp index a87d9eda..6766f231 100644 --- a/lib/utils/src/gpsMath.hpp +++ b/lib/utils/src/gpsMath.hpp @@ -2,8 +2,8 @@ * @file gpsMath.hpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Math and various functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #ifndef GPSMATH_HPP diff --git a/lib/webfile/src/webpage.h b/lib/webfile/src/webpage.h index 373c703e..0fc0fefa 100644 --- a/lib/webfile/src/webpage.h +++ b/lib/webfile/src/webpage.h @@ -2,8 +2,8 @@ * @file webpage.h * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Web file server page - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ @@ -93,6 +93,8 @@ const char index_html[] PROGMEM = R"rawliteral( background-color: black; border: 1px solid #aaaaaa; text-align: center; + overflow-y: auto; + overflow-x: hidden; } @@ -100,11 +102,11 @@ const char index_html[] PROGMEM = R"rawliteral( - + @@ -122,7 +124,7 @@ const char index_html[] PROGMEM = R"rawliteral(

diff --git a/lib/webfile/src/webserver.h b/lib/webfile/src/webserver.h index 11d88d56..58d99c79 100644 --- a/lib/webfile/src/webserver.h +++ b/lib/webfile/src/webserver.h @@ -2,8 +2,8 @@ * @file webserver.h * @author Jordi Gauchía (jgauchia@gmx.es) * @brief Web file server functions - * @version 0.1.8 - * @date 2024-11 + * @version 0.1.9 + * @date 2024-12 */ #include "SPIFFS.h" @@ -19,6 +19,10 @@ String oldDir; String newDir; String currentDir; + +String createDir; +uint8_t nextSlash = 0; + bool updateList = true; const int FILES_PER_PAGE = 10; @@ -237,7 +241,6 @@ String listFiles(bool ishtml, int page = 0) { String returnText = ""; - int fileIndex = 0; int startIdx = page * FILES_PER_PAGE; int endIdx = startIdx + FILES_PER_PAGE; @@ -263,7 +266,9 @@ String listFiles(bool ishtml, int page = 0) if (entry.isDirectory) { returnText += " " + entry.name + ""; - returnText += "dir"; + returnText += "dir"; + returnText += ""; + returnText += ""; } else { @@ -286,12 +291,18 @@ String listFiles(bool ishtml, int page = 0) returnText += ""; if (page > 0) + { + returnText += ""; returnText += ""; + } - returnText += " Page " + String(page + 1) + " "; + returnText += " Page " + String(page + 1) + "/" + String((fileCache.size() / 10)+1) + " "; if (fileCache.size() > endIdx) + { returnText += ""; + returnText += ""; + } returnText += "

"; } @@ -299,6 +310,37 @@ String listFiles(bool ishtml, int page = 0) return returnText; } +/** + * @brief Create directories if needed for upload + * + * @param filepath -> Full file path + * @return true/false if successful + */ +bool createDirectories(String filepath) +{ + uint8_t lastSlash = 0; + while (true) + { + nextSlash = filepath.indexOf('/', lastSlash + 1); + String dir = filepath.substring(0, nextSlash); + + if (!SD.exists(oldDir + "/" + dir)) + { + if (!SD.mkdir(oldDir + "/" + dir)) + { + log_e("Directory %s creation error", dir.c_str()); + return false; + } + log_v("Directory %s created",dir.c_str()); + } + if (nextSlash == 255) break; + lastSlash = nextSlash; + + esp_task_wdt_reset(); + } + return true; +} + /** * @brief Upload file handle * @@ -311,12 +353,26 @@ String listFiles(bool ishtml, int page = 0) void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { waitScreenRefresh = true; - + uint8_t lastSlashIndex = filename.lastIndexOf("/"); + + if (lastSlashIndex != 255) + { + String path = filename.substring(0, lastSlashIndex); + if (createDir != path) + { + log_v("%s",path.c_str()); + if (!createDirectories(path)) + log_e("Directory creation error"); + createDir = path; + } + } + if (!index) { request->client()->setRxTimeout(15000); request->_tempFile = SD.open(oldDir + "/" + filename, "w"); } + if (len) request->_tempFile.write(data, len); @@ -350,16 +406,86 @@ void sendSpiffsImage(const char *imageFile,AsyncWebServerRequest *request) } /** - * @brief Configure Web Server + * @brief Delete directory recursive * + * @param dirPath -> directory path + * @return true/false if successful */ -void configureWebServer() +bool deleteDirRecursive(const char *dirPath) { + String basePath = dirPath; - // if (!MDNS.begin(hostname)) - // log_e("nDNS init error"); + log_v("Processing directory: %s", basePath.c_str()); - // log_i("mDNS initialized"); + File dir = SD.open(basePath.c_str()); + if (!dir || !dir.isDirectory()) + { + log_e("Error: %s isn't a directory or can't open", basePath.c_str()); + return false; + } + + while (true) + { + File entry = dir.openNextFile(); + if (!entry) + { + break; + } + + if (!basePath.endsWith("/")) + { + basePath += "/"; + } + + String entryPath = basePath + entry.name(); + + if (entry.isDirectory()) + { + + log_v("Found subdirectory: %s", entryPath.c_str()); + if (!deleteDirRecursive(entryPath.c_str())) + { + entry.close(); + return false; + } + } + else + { + log_v("Found file: %s", entryPath.c_str()); + if (!SD.remove(entryPath.c_str())) + { + log_e("Error deleting file: %s", entryPath.c_str()); + entry.close(); + return false; + } + log_v("Deleted file: %s", entryPath.c_str()); + } + entry.close(); + } + + dir.close(); + + if (basePath.endsWith("/")) + { + basePath = dirPath; + } + + if (!SD.rmdir(basePath.c_str())) + { + log_e("Error deleting directory: %s", basePath.c_str()); + return false; + } + + log_v("Deleted directory: %s", basePath.c_str()); + return true; +} + +/** + * @brief Configure Web Server + * + */ +void configureWebServer() +{ server.onNotFound(webNotFound); server.onFileUpload(handleUpload); @@ -431,7 +557,7 @@ void configureWebServer() logMessage = "Client:" + request->client()->remoteIP().toString() + " " + request->url() + "?name=" + String(fileName) + "&action=" + String(fileAction); - String path = oldDir + String(fileName); + String path = oldDir + "/" + String(fileName); log_i("%s",path.c_str()); if (!SD.exists(path)) @@ -446,6 +572,13 @@ void configureWebServer() logMessage += " downloaded"; request->send(SD, path, "application/octet-stream"); } + else if (strcmp(fileAction, "deldir") == 0) + { + logMessage += " deleted"; + deleteDirRecursive(path.c_str()); + request->send(200, "text/plain", "Deleted Folder: " + String(fileName)); + updateList = true; + } else if (strcmp(fileAction, "delete") == 0) { logMessage += " deleted"; @@ -484,7 +617,7 @@ void configureWebServer() if (oldDir == "") oldDir = "/"; currentDir = ""; - request->send(200, "text/plain", "Directory changed successfully"); + request->send(200, "text/plain", "Path:" + oldDir ); } else { @@ -499,7 +632,7 @@ void configureWebServer() else oldDir = newDir; currentDir = ""; - request->send(200, "text/plain", "Directory changed successfully"); + request->send(200, "text/plain", "Path:" + oldDir); } cacheDirectoryContent(oldDir); diff --git a/platformio.ini b/platformio.ini index 7587d769..871edbaa 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,10 +13,10 @@ description = ESP32 GPS Navigator default_envs = ICENAV_BOARD [common] -platform = espressif32 +platform = espressif32@6.9.0 framework = arduino -version = 0.1.8 -revision = 82 +version = 0.1.9 +revision = 83 monitor_speed = 115200 ;monitor_rts = 0 ;monitor_dtr = 0 @@ -34,20 +34,21 @@ build_flags = -D SHELLMINATOR_BUFF_DIM=70 -D SHELLMINATOR_LOGO_COLOR=BLUE -D COMMANDER_MAX_COMMAND_SIZE=70 - -D WCLI_MAX_CMDS=14 # set n+1 of defined commands for CLI + -D WCLI_MAX_CMDS=13 # set n+1 of defined commands for CLI ; -D DISABLE_CLI_TELNET=1 # disable remote access via telnet. It needs CLI ; -D DISABLE_CLI=1 # removed CLI module. Config via Bluetooth only lib_deps = ; slashdevin/NeoGPS@4.2.9 https://github.com/jgauchia/NeoGPS.git#43c4766 - lvgl/lvgl@9.2.0 - lovyan03/LovyanGFX@1.1.16 + lvgl/lvgl@9.2.2 + lovyan03/LovyanGFX@1.2.0 bblanchon/StreamUtils@1.9.0 - hpsaturn/EasyPreferences@0.1.2 - hpsaturn/ESP32 Wifi CLI@0.3.2 + hpsaturn/EasyPreferences@0.1.3 + hpsaturn/ESP32 Wifi CLI@0.3.3 kubafilinger/AsyncTCP@1.1.1 - esphome/ESPAsyncWebServer-esphome@2.1.0 + esphome/ESPAsyncWebServer-esphome@3.3.0 + jpb10/SolarCalculator@2.0.1 [esp32_common] extends = common @@ -58,7 +59,7 @@ board = icenav-esp32-s3 lib_deps = ${common.lib_deps} adafruit/Adafruit Unified Sensor@1.1.14 - adafruit/Adafruit BusIO@1.16.1 + adafruit/Adafruit BusIO@1.16.2 adafruit/Adafruit BME280 Library@2.2.4 dfrobot/DFRobot_QMC5883@1.0.0 build_flags = @@ -83,7 +84,7 @@ board = elecrow-esp32-s3-n16r8v-terminal lib_deps = ${common.lib_deps} ; adafruit/Adafruit Unified Sensor@1.1.14 -; adafruit/Adafruit BusIO@1.16.1 +; adafruit/Adafruit BusIO@1.16.2 ; adafruit/Adafruit BME280 Library@2.2.4 ; dfrobot/DFRobot_QMC5883@1.0.0 build_flags = @@ -122,7 +123,7 @@ board_build.partitions = default_16MB.csv lib_deps = ${common.lib_deps} ; adafruit/Adafruit Unified Sensor@1.1.14 -; adafruit/Adafruit BusIO@1.16.1 +; adafruit/Adafruit BusIO@1.16.2 ; adafruit/Adafruit BME280 Library@2.2.4 ; dfrobot/DFRobot_QMC5883@1.0.0 build_flags = @@ -143,7 +144,7 @@ board_build.partitions = default_16MB.csv lib_deps = ${common.lib_deps} ; adafruit/Adafruit Unified Sensor@1.1.14 -; adafruit/Adafruit BusIO@1.16.1 +; adafruit/Adafruit BusIO@1.16.2 ; adafruit/Adafruit BME280 Library@2.2.4 ; dfrobot/DFRobot_QMC5883@1.0.0 build_flags = diff --git a/src/main.cpp b/src/main.cpp index eeaff483..af90edef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,8 +2,8 @@ * @file main.cpp * @author Jordi Gauchía (jgauchia@gmx.es) * @brief ESP32 GPS Navigation main code - * @version 0.1.8 - * @date 2024-08 + * @version 0.1.9 + * @date 2024-12 */ #include @@ -16,6 +16,7 @@ #include #include #include +#include // Hardware includes #include "hal.hpp" @@ -45,10 +46,35 @@ extern xSemaphoreHandle gpsMutex; #include "webserver.h" #include "battery.hpp" #include "power.hpp" + +extern Storage storage; +extern Battery battery; +extern Power power; + +/** + * @brief Sunrise and Sunset + * + */ +static double transit, sunrise, sunset; + #include "settings.hpp" #include "lvglSetup.hpp" #include "tasks.hpp" +/** + * @brief Calculate Sunrise and Sunset + * Must be a global function + * + */ +void calculateSun() +{ + calcSunriseSunset(2000 + localTime.year, localTime.month, localTime.date, + gpsData.latitude, gpsData.longitude, + transit, sunrise, sunset); + hoursToString(sunrise + defGMT, gpsData.sunriseHour); + hoursToString(sunset + defGMT, gpsData.sunsetHour); +} + /** * @brief Setup * @@ -59,7 +85,12 @@ void setup() // Force GPIO0 to internal PullUP during boot (avoid LVGL key read) #ifdef POWER_SAVE - pinMode(BOARD_BOOT_PIN,INPUT_PULLUP); + pinMode(BOARD_BOOT_PIN,INPUT_PULLUP); + #ifdef ICENAV_BOARD + gpio_hold_dis((gpio_num_t)TFT_BL); + gpio_hold_dis((gpio_num_t)BOARD_BOOT_PIN); + gpio_deep_sleep_hold_dis(); + #endif #endif #ifdef ARDUINO_USB_CDC_ON_BOOT @@ -91,36 +122,20 @@ void setup() initCompass(); #endif - powerOn(); - initSD(); - initSPIFFS(); + // powerOn(); + storage.initSD(); + storage.initSPIFFS(); + battery.initADC(); initTFT(); loadPreferences(); initGPS(); initLVGL(); - initADC(); - - // Reserve PSRAM for buffer map - mapTempSprite.deleteSprite(); - mapTempSprite.createSprite(TILE_WIDTH, TILE_HEIGHT); - // Preload Map - if (isVectorMap) - { - } - else - { - // Get init Latitude and Longitude - gpsData.latitude = getLat(); - gpsData.longitude = getLon(); - tileSize = RENDER_TILE_SIZE; - generateRenderMap(); - } - - splashScreen(); - initGpsTask(); + // Get init Latitude and Longitude + gpsData.latitude = getLat(); + gpsData.longitude = getLon(); - lv_screen_load(searchSatScreen); + initGpsTask(); #ifndef DISABLE_CLI initCLI(); @@ -143,6 +158,32 @@ void setup() if(WiFi.getMode() == WIFI_OFF) ESP_ERROR_CHECK(esp_event_loop_create_default()); + + // Reserve PSRAM for buffer map + mapTempSprite.deleteSprite(); + mapTempSprite.createSprite(TILE_WIDTH, TILE_HEIGHT); + + // Preload Map + if (isVectorMap) + { + getPosition(gpsData.latitude, gpsData.longitude); + tileSize = VECTOR_TILE_SIZE; + viewPort.setCenter(point); + + getMapBlocks(viewPort.bbox, memCache); + + generateVectorMap(viewPort, memCache, mapTempSprite); + + isPosMoved = false; + } + else + { + tileSize = RENDER_TILE_SIZE; + generateRenderMap(); + } + + splashScreen(); + lv_screen_load(searchSatScreen); } /**