commit 4149376f547cd6975c0fc2da0e4c9fa1d7fd565b Author: Vadim Date: Mon May 4 09:45:46 2026 +0300 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/include/README b/include/README new file mode 100644 index 0000000..49819c0 --- /dev/null +++ b/include/README @@ -0,0 +1,37 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the convention is to give header files names that end with `.h'. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..9379397 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into the executable file. + +The source code of each library should be placed in a separate directory +("lib/your_library_name/[Code]"). + +For example, see the structure of the following example libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +Example contents of `src/main.c` using Foo and Bar: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +The PlatformIO Library Dependency Finder will find automatically dependent +libraries by scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..91b2974 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,18 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32dev] +platform = espressif32 +board = esp32dev +monitor_speed = 115200 +framework = arduino +lib_deps = + bodmer/TFT_eSPI@^2.5.43 + mikalhart/TinyGPSPlus@^1.1.0 diff --git a/src/Free_Fonts.h b/src/Free_Fonts.h new file mode 100644 index 0000000..8ee278c --- /dev/null +++ b/src/Free_Fonts.h @@ -0,0 +1,377 @@ +// Attach this header file to your sketch to use the GFX Free Fonts. You can write +// sketches without it, but it makes referencing them easier. + +// This calls up ALL the fonts but they only get loaded if you actually +// use them in your sketch. +// +// No changes are needed to this header file unless new fonts are added to the +// library "Fonts/GFXFF" folder. +// +// To save a lot of typing long names, each font can easily be referenced in the +// sketch in three ways, either with: +// +// 1. Font file name with the & in front such as &FreeSansBoldOblique24pt7b +// an example being: +// +// tft.setFreeFont(&FreeSansBoldOblique24pt7b); +// +// 2. FF# where # is a number determined by looking at the list below +// an example being: +// +// tft.setFreeFont(FF32); +// +// 3. An abbreviation of the file name. Look at the list below to see +// the abbreviations used, for example: +// +// tft.setFreeFont(FSSBO24) +// +// Where the letters mean: +// F = Free font +// M = Mono +// SS = Sans Serif (double S to distinguish is form serif fonts) +// S = Serif +// B = Bold +// O = Oblique (letter O not zero) +// I = Italic +// # = point size, either 9, 12, 18 or 24 +// +// Setting the font to NULL will select the GLCD font: +// +// tft.setFreeFont(NULL); // Set font to GLCD + +#ifdef LOAD_GFXFF // Only include the fonts if LOAD_GFXFF is defined in User_Setup.h + +// Use these when printing or drawing text in GLCD and high rendering speed fonts +#define GFXFF 1 +#define GLCD 0 +#define FONT2 2 +#define FONT4 4 +#define FONT6 6 +#define FONT7 7 +#define FONT8 8 + +// Use the following when calling setFont() +// +// Reserved for GLCD font // FF0 +// + +#define TT1 &TomThumb + +#define FM9 &FreeMono9pt7b +#define FM12 &FreeMono12pt7b +#define FM18 &FreeMono18pt7b +#define FM24 &FreeMono24pt7b + +#define FMB9 &FreeMonoBold9pt7b +#define FMB12 &FreeMonoBold12pt7b +#define FMB18 &FreeMonoBold18pt7b +#define FMB24 &FreeMonoBold24pt7b + +#define FMO9 &FreeMonoOblique9pt7b +#define FMO12 &FreeMonoOblique12pt7b +#define FMO18 &FreeMonoOblique18pt7b +#define FMO24 &FreeMonoOblique24pt7b + +#define FMBO9 &FreeMonoBoldOblique9pt7b +#define FMBO12 &FreeMonoBoldOblique12pt7b +#define FMBO18 &FreeMonoBoldOblique18pt7b +#define FMBO24 &FreeMonoBoldOblique24pt7b + +#define FSS9 &FreeSans9pt7b +#define FSS12 &FreeSans12pt7b +#define FSS18 &FreeSans18pt7b +#define FSS24 &FreeSans24pt7b + +#define FSSB9 &FreeSansBold9pt7b +#define FSSB12 &FreeSansBold12pt7b +#define FSSB18 &FreeSansBold18pt7b +#define FSSB24 &FreeSansBold24pt7b + +#define FSSO9 &FreeSansOblique9pt7b +#define FSSO12 &FreeSansOblique12pt7b +#define FSSO18 &FreeSansOblique18pt7b +#define FSSO24 &FreeSansOblique24pt7b + +#define FSSBO9 &FreeSansBoldOblique9pt7b +#define FSSBO12 &FreeSansBoldOblique12pt7b +#define FSSBO18 &FreeSansBoldOblique18pt7b +#define FSSBO24 &FreeSansBoldOblique24pt7b + +#define FS9 &FreeSerif9pt7b +#define FS12 &FreeSerif12pt7b +#define FS18 &FreeSerif18pt7b +#define FS24 &FreeSerif24pt7b + +#define FSI9 &FreeSerifItalic9pt7b +#define FSI12 &FreeSerifItalic12pt7b +#define FSI19 &FreeSerifItalic18pt7b +#define FSI24 &FreeSerifItalic24pt7b + +#define FSB9 &FreeSerifBold9pt7b +#define FSB12 &FreeSerifBold12pt7b +#define FSB18 &FreeSerifBold18pt7b +#define FSB24 &FreeSerifBold24pt7b + +#define FSBI9 &FreeSerifBoldItalic9pt7b +#define FSBI12 &FreeSerifBoldItalic12pt7b +#define FSBI18 &FreeSerifBoldItalic18pt7b +#define FSBI24 &FreeSerifBoldItalic24pt7b + +#define FF0 NULL //ff0 reserved for GLCD +#define FF1 &FreeMono9pt7b +#define FF2 &FreeMono12pt7b +#define FF3 &FreeMono18pt7b +#define FF4 &FreeMono24pt7b + +#define FF5 &FreeMonoBold9pt7b +#define FF6 &FreeMonoBold12pt7b +#define FF7 &FreeMonoBold18pt7b +#define FF8 &FreeMonoBold24pt7b + +#define FF9 &FreeMonoOblique9pt7b +#define FF10 &FreeMonoOblique12pt7b +#define FF11 &FreeMonoOblique18pt7b +#define FF12 &FreeMonoOblique24pt7b + +#define FF13 &FreeMonoBoldOblique9pt7b +#define FF14 &FreeMonoBoldOblique12pt7b +#define FF15 &FreeMonoBoldOblique18pt7b +#define FF16 &FreeMonoBoldOblique24pt7b + +#define FF17 &FreeSans9pt7b +#define FF18 &FreeSans12pt7b +#define FF19 &FreeSans18pt7b +#define FF20 &FreeSans24pt7b + +#define FF21 &FreeSansBold9pt7b +#define FF22 &FreeSansBold12pt7b +#define FF23 &FreeSansBold18pt7b +#define FF24 &FreeSansBold24pt7b + +#define FF25 &FreeSansOblique9pt7b +#define FF26 &FreeSansOblique12pt7b +#define FF27 &FreeSansOblique18pt7b +#define FF28 &FreeSansOblique24pt7b + +#define FF29 &FreeSansBoldOblique9pt7b +#define FF30 &FreeSansBoldOblique12pt7b +#define FF31 &FreeSansBoldOblique18pt7b +#define FF32 &FreeSansBoldOblique24pt7b + +#define FF33 &FreeSerif9pt7b +#define FF34 &FreeSerif12pt7b +#define FF35 &FreeSerif18pt7b +#define FF36 &FreeSerif24pt7b + +#define FF37 &FreeSerifItalic9pt7b +#define FF38 &FreeSerifItalic12pt7b +#define FF39 &FreeSerifItalic18pt7b +#define FF40 &FreeSerifItalic24pt7b + +#define FF41 &FreeSerifBold9pt7b +#define FF42 &FreeSerifBold12pt7b +#define FF43 &FreeSerifBold18pt7b +#define FF44 &FreeSerifBold24pt7b + +#define FF45 &FreeSerifBoldItalic9pt7b +#define FF46 &FreeSerifBoldItalic12pt7b +#define FF47 &FreeSerifBoldItalic18pt7b +#define FF48 &FreeSerifBoldItalic24pt7b + +// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +// Now we define "s"tring versions for easy printing of the font name so: +// tft.println(sFF5); +// will print +// Mono bold 9 +// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +#define sFF0 "GLCD" +#define sTT1 "Tom Thumb" +#define sFF1 "Mono 9" +#define sFF2 "Mono 12" +#define sFF3 "Mono 18" +#define sFF4 "Mono 24" + +#define sFF5 "Mono bold 9" +#define sFF6 "Mono bold 12" +#define sFF7 "Mono bold 18" +#define sFF8 "Mono bold 24" + +#define sFF9 "Mono oblique 9" +#define sFF10 "Mono oblique 12" +#define sFF11 "Mono oblique 18" +#define sFF12 "Mono oblique 24" + +#define sFF13 "Mono bold oblique 9" +#define sFF14 "Mono bold oblique 12" +#define sFF15 "Mono bold oblique 18" +#define sFF16 "Mono bold obl. 24" // Full text line is too big for 480 pixel wide screen + +#define sFF17 "Sans 9" +#define sFF18 "Sans 12" +#define sFF19 "Sans 18" +#define sFF20 "Sans 24" + +#define sFF21 "Sans bold 9" +#define sFF22 "Sans bold 12" +#define sFF23 "Sans bold 18" +#define sFF24 "Sans bold 24" + +#define sFF25 "Sans oblique 9" +#define sFF26 "Sans oblique 12" +#define sFF27 "Sans oblique 18" +#define sFF28 "Sans oblique 24" + +#define sFF29 "Sans bold oblique 9" +#define sFF30 "Sans bold oblique 12" +#define sFF31 "Sans bold oblique 18" +#define sFF32 "Sans bold oblique 24" + +#define sFF33 "Serif 9" +#define sFF34 "Serif 12" +#define sFF35 "Serif 18" +#define sFF36 "Serif 24" + +#define sFF37 "Serif italic 9" +#define sFF38 "Serif italic 12" +#define sFF39 "Serif italic 18" +#define sFF40 "Serif italic 24" + +#define sFF41 "Serif bold 9" +#define sFF42 "Serif bold 12" +#define sFF43 "Serif bold 18" +#define sFF44 "Serif bold 24" + +#define sFF45 "Serif bold italic 9" +#define sFF46 "Serif bold italic 12" +#define sFF47 "Serif bold italic 18" +#define sFF48 "Serif bold italic 24" + +#else // LOAD_GFXFF not defined so setup defaults to prevent error messages + +// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +// Free fonts are not loaded in User_Setup.h so we must define all as font 1 +// to prevent compile error messages +// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +#define GFXFF 1 +#define GLCD 1 +#define FONT2 2 +#define FONT4 4 +#define FONT6 6 +#define FONT7 7 +#define FONT8 8 + +#define TT1 1 + +#define FF0 1 +#define FF1 1 +#define FF2 1 +#define FF3 1 +#define FF4 1 +#define FF5 1 +#define FF6 1 +#define FF7 1 +#define FF8 1 +#define FF9 1 +#define FF10 1 +#define FF11 1 +#define FF12 1 +#define FF13 1 +#define FF14 1 +#define FF15 1 +#define FF16 1 +#define FF17 1 +#define FF18 1 +#define FF19 1 +#define FF20 1 +#define FF21 1 +#define FF22 1 +#define FF23 1 +#define FF24 1 +#define FF25 1 +#define FF26 1 +#define FF27 1 +#define FF28 1 +#define FF29 1 +#define FF30 1 +#define FF31 1 +#define FF32 1 +#define FF33 1 +#define FF34 1 +#define FF35 1 +#define FF36 1 +#define FF37 1 +#define FF38 1 +#define FF39 1 +#define FF40 1 +#define FF41 1 +#define FF42 1 +#define FF43 1 +#define FF44 1 +#define FF45 1 +#define FF46 1 +#define FF47 1 +#define FF48 1 + +#define FM9 1 +#define FM12 1 +#define FM18 1 +#define FM24 1 + +#define FMB9 1 +#define FMB12 1 +#define FMB18 1 +#define FMB24 1 + +#define FMO9 1 +#define FMO12 1 +#define FMO18 1 +#define FMO24 1 + +#define FMBO9 1 +#define FMBO12 1 +#define FMBO18 1 +#define FMBO24 1 + +#define FSS9 1 +#define FSS12 1 +#define FSS18 1 +#define FSS24 1 + +#define FSSB9 1 +#define FSSB12 1 +#define FSSB18 1 +#define FSSB24 1 + +#define FSSO9 1 +#define FSSO12 1 +#define FSSO18 1 +#define FSSO24 1 + +#define FSSBO9 1 +#define FSSBO12 1 +#define FSSBO18 1 +#define FSSBO24 1 + +#define FS9 1 +#define FS12 1 +#define FS18 1 +#define FS24 1 + +#define FSI9 1 +#define FSI12 1 +#define FSI19 1 +#define FSI24 1 + +#define FSB9 1 +#define FSB12 1 +#define FSB18 1 +#define FSB24 1 + +#define FSBI9 1 +#define FSBI12 1 +#define FSBI18 1 +#define FSBI24 1 + +#endif // LOAD_GFXFF diff --git a/src/help.cpp b/src/help.cpp new file mode 100644 index 0000000..b1021ee --- /dev/null +++ b/src/help.cpp @@ -0,0 +1,15 @@ +void setup1(void) +{ + // tft.begin(); + // tft.setRotation(2); + // tft.fillScreen(TFT_BLACK); + // tft.setTextColor(TFT_WHITE, TFT_BLACK); + // tft.print("Hello, world! Foo bar!!!"); + // tft.setFreeFont(FM9); + // tft.drawString("test", 5, 20, GFXFF); + // tft.setTextFont(1); + // tft.setTextSize(2); + // tft.setTextColor(TFT_WHITE, TFT_BLACK); + // tft.setTextDatum(CC_DATUM); + // tft.drawString("Makerguides", TFT_HEIGHT / 2, TFT_WIDTH / 2); +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..9b62cdf --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,363 @@ +#include +#include +#include +#include +#include + +#include "Free_Fonts.h" + +#define RX2_PIN 16 +#define TX2_PIN 17 +#define GPS_BAUD 9600 +#define LED 2 + +#define KEY_X 3 // start X +#define KEY_Y 24 +#define KEY_W 76 // Key width +#define KEY_H 36 // Key height +#define KEY_SPACING_X 3 // X gap +#define KEY_SPACING_Y 3 // Y gap +#define KEY_TEXTSIZE 1 // Font size multiplier +#define BUTTON_X_DELTA 22 +#define NUM_KEYS 3 +#define QUEUE_SIZE 5 + +TFT_eSPI tft = TFT_eSPI(); +TinyGPSPlus gps; +HardwareSerial serialGPS(1); +TaskHandle_t taskBlinkHandle = NULL; // for task control: suspend / resume +TaskHandle_t taskGPSHandle = NULL; +TFT_eSPI_Button key[NUM_KEYS]; +SemaphoreHandle_t spiMutex; +QueueHandle_t gpsQueue = NULL; + +char label[] = "label"; +String btnLabel[] = {"GPS", "DATE", "LOC"}; + +// uint16_t calData[5] = { 293, 3474, 445, 3470, 0 }; +// uint16_t calData[5] = { 314, 3512, 424, 3489, 0 }; +// uint16_t calData[5] = { 233, 3558, 390, 3514, 0 }; +// uint16_t calData[5] = { 283, 3553, 416, 3514, 0 }; +// Initial Free Heap: 274996 bytes + +struct GpsData +{ + float lat; + float lng; + + uint8_t hour; + uint8_t minute; + uint8_t second; + + uint16_t year; + uint8_t month; + uint8_t day; + + uint32_t sat; + float speed; + float alt; + bool isValid; +}; + +// struct GPSData1 { +// float lat = 0.0f; +// float lon = 0.0f; +// float alt = 0.0f; +// uint8_t satellites = 0; +// float speed = 0.0f; +// float course = 0.0f; +// bool valid = false; +// }; +// packet.lat = gps.location.isValid() ? gps.location.lat() : 0.0f; + +void smartDelay(unsigned long ms); +void initDisplay(); +void displayGPSInfo(); +void drawButtons(); +void taskBlink(void *pvParameters); +void taskGPS(void *pvParameters); +void taskTFT(void *pvParameters); +void drawTitle(const char *title); + +//------------------------------------------------------------------------------------------ +void setup() +{ + Serial.begin(115200); + spiMutex = xSemaphoreCreateMutex(); + Serial.printf("Starting FreeRTOS: Memory Usage\nInitial Free Heap: %u bytes\n", xPortGetFreeHeapSize()); + + gpsQueue = xQueueCreate(QUEUE_SIZE, sizeof(GpsData)); + + xTaskCreatePinnedToCore(taskBlink, "taskBlink", 2000, NULL, 1, &taskBlinkHandle, 0); + xTaskCreatePinnedToCore(taskGPS, "taskGPS", 2000, NULL, 1, &taskGPSHandle, 0); + xTaskCreatePinnedToCore(taskTFT, "taskTFT", 2000, NULL, 1, NULL, 1); +} + +void loop() +{ + static uint32_t lastCheck = 0; + if (millis() - lastCheck > 5000) + { + Serial.printf("Free Heap: %u bytes\n", xPortGetFreeHeapSize()); + lastCheck = millis(); + } +} + +void taskGPS(void *pvParameters) +{ + serialGPS.begin(GPS_BAUD, SERIAL_8N1, RX2_PIN, TX2_PIN); + Serial.print("Task GPS running on core "); + Serial.println(xPortGetCoreID()); + + GpsData data; + + while (true) + { + while (serialGPS.available() > 0) + { + gps.encode(serialGPS.read()); + } + + if (gps.location.isUpdated()) + { + data.lat = gps.location.lat(); + data.lng = gps.location.lng(); + data.speed = gps.speed.kmph(); + data.alt = gps.altitude.meters(); + data.sat = gps.satellites.value(); + + Serial.printf("Lat: %.6f, Lon: %.6f\n", data.lat, data.lng); + Serial.printf("Speed: %.1f km/h\n", data.speed); + Serial.printf("Alt: %.1f m\n", data.alt); + Serial.printf("Satellites: %d\n", data.sat); + } + + if (gps.date.isUpdated() && gps.time.isUpdated()) + { + data.year = gps.date.year(); + data.month = gps.date.month(); + data.day = gps.date.day(); + data.hour = gps.time.hour(); + data.minute = gps.time.minute(); + data.second = gps.time.second(); + + Serial.printf("Date: %04d-%02d-%02d\n", data.year, data.month, data.day); + Serial.printf("Time: %02d:%02d:%02d\n", data.hour, data.minute, data.second); + } + + vTaskDelay(1000 / portTICK_PERIOD_MS); + // Serial.printf("TaskGPS Stack Free: %u bytes\n", uxTaskGetStackHighWaterMark(NULL)); + } +} + +void taskBlink(void *pvParameters) +{ + pinMode(LED, OUTPUT); + + for (;;) + { // Infinite loop + digitalWrite(LED, HIGH); + // Serial.println("BlinkTask: LED ON"); + vTaskDelay(1000 / portTICK_PERIOD_MS); // 1000ms + digitalWrite(LED, LOW); + // Serial.println("BlinkTask: LED OFF"); + vTaskDelay(1000 / portTICK_PERIOD_MS); + // Serial.print("Task Blink running on core "); + // Serial.println(xPortGetCoreID()); + // Serial.printf("TaskBlink Stack Free: %u bytes\n", uxTaskGetStackHighWaterMark(NULL)); + } +} + +void taskTFT(void *pvParameters) +{ + initDisplay(); + + drawTitle("Hello world!"); + + drawButtons(); + + for (;;) + { + // Serial.printf("taskTFT Stack Free: %u bytes\n", uxTaskGetStackHighWaterMark(NULL)); + vTaskDelay(2000 / portTICK_PERIOD_MS); + } +} + +void loop_1() +{ + if (gps.location.isUpdated()) + { + displayGPSInfo(); + } + + uint16_t t_x = 0, t_y = 0; // To store the touch coordinates + + // Get current touch state and coordinates + bool pressed = tft.getTouch(&t_x, &t_y); + if (pressed) + { + Serial.println("pressed"); + digitalWrite(LED, HIGH); + } + else + { + digitalWrite(LED, LOW); + } + + // Adjust press state of each key appropriately + for (uint8_t b = 0; b < NUM_KEYS; b++) + { + if (pressed && key[b].contains(t_x, t_y)) + { + key[b].press(true); + } + else + { + key[b].press(false); + } + } + + // Check if any key has changed state + for (uint8_t b = 0; b < NUM_KEYS; b++) + { + // If button was just pressed, redraw inverted button + if (key[b].justPressed()) + { + Serial.println("Button " + (String)b + " pressed"); + tft.setFreeFont(FF5); + key[b].drawButton(true, btnLabel[b]); + } + + // If button was just released, redraw normal color button + if (key[b].justReleased()) + { + Serial.println("Button " + (String)b + " released"); + tft.setFreeFont(FF5); + key[b].drawButton(false, btnLabel[b]); + } + } + + smartDelay(100); +} + +void drawButtons() +{ + for (int i = 0; i < NUM_KEYS; i++) + { + key[i].initButtonUL(&tft, + KEY_X + i * (KEY_W + KEY_SPACING_X), + KEY_Y, + KEY_W, + KEY_H, + TFT_LIGHTGREY, + TFT_DARKGREY, + TFT_WHITE, + label, + KEY_TEXTSIZE); + + key[i].setLabelDatum(0, 2, MC_DATUM); + key[i].drawButton(false, btnLabel[i]); + } +} + +void initDisplay() +{ + tft.init(); + tft.setRotation(2); + + uint16_t calData[5] = {283, 3553, 416, 3514, 0}; + tft.setTouch(calData); + +#ifndef TFT_BL + Serial.println("No TFT backlight pin defined"); +#else + pinMode(TFT_BL, OUTPUT); + digitalWrite(TFT_BL, HIGH); +#endif + + tft.fillScreen(TFT_BLACK); +} + +void drawTitle(const char *title) +{ + tft.setFreeFont(FF5); + tft.setTextColor(TFT_YELLOW, TFT_BLACK); + tft.drawString(title, 0, 0, GFXFF); +} + +void displayGPSInfo() +{ + Serial.print(F("Location: ")); + if (gps.location.isValid()) + { + Serial.print(gps.location.lat(), 6); + Serial.print(F(",")); + Serial.print(gps.location.lng(), 6); + } + else + { + Serial.print(F("INVALID")); + } + + Serial.print(F(" Date/Time: ")); + if (gps.date.isValid()) + { + Serial.print(gps.date.month()); + Serial.print(F("/")); + Serial.print(gps.date.day()); + Serial.print(F("/")); + Serial.print(gps.date.year()); + } + else + { + Serial.print(F("INVALID")); + } + + Serial.print(F(" ")); + if (gps.time.isValid()) + { + if (gps.time.hour() < 10) + Serial.print(F("0")); + Serial.print(gps.time.hour()); + Serial.print(F(":")); + if (gps.time.minute() < 10) + Serial.print(F("0")); + Serial.print(gps.time.minute()); + Serial.print(F(":")); + if (gps.time.second() < 10) + Serial.print(F("0")); + Serial.print(gps.time.second()); + Serial.print(F(".")); + if (gps.time.centisecond() < 10) + Serial.print(F("0")); + Serial.print(gps.time.centisecond()); + + String a = ""; + a += String(gps.time.hour()); + a += ":"; + a += String(gps.time.minute()); + a += ":"; + + a += String(gps.time.second()); + + tft.setFreeFont(FF30); + tft.setTextColor(TFT_CYAN, TFT_BLACK); + tft.drawString(a, 5, 100, GFXFF); + } + else + { + Serial.print(F("INVALID")); + } + + Serial.println(); +} + +void smartDelay(unsigned long ms) +{ + unsigned long start = millis(); + do + { + while (serialGPS.available()) + gps.encode(serialGPS.read()); + } while (millis() - start < ms); +} diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html