#include "TFT_eSPI.h" #include "ChronoBLE.h" #include "ChronoReading.h" #include #include "Display.h" #include "ChronoReadingManager.h" #include "ChronoWebServer.h" #include "FileManager.h" //testing mode variables static bool testMode=false; static long testModeLastAdd=0; //general variables static char currentTime[64]; //chronograph setup static bool chronoStateConnected=false; static ChronoBLE chronoBLE; static ChronoWebServer webServer; void speedCallback(int fps){ addReading(fps); } void addReading(int fps){ ChronoReadingManager& chronoReadings = ChronoReadingManager::getInstance(); //add reading to manager chronoReadings.addReading(fps); //update display Display::updateEntireDisplay(); if (chronoReadings.getShotCount() % 10 == 0){ // Get filesystem information unsigned int totalBytes = LittleFS.totalBytes(); unsigned int usedBytes = LittleFS.usedBytes(); unsigned int freeBytes = totalBytes - usedBytes; Serial.printf("\t(%u) Available Disk / Memory: %u / %u\n", chronoReadings.getShotCount(), freeBytes, ESP.getFreeHeap()); } } void toggleTestMode(){ if (testMode){ Serial.println("disabling test mode...."); testMode=false; } else { Serial.println("enabling test mode...."); testMode=true; } } void setup() { Serial.begin(115200); Serial.println("starting......"); //initialize the file manager FileManager& files = FileManager::getInstance(); files.init(); //initialize web portal webServer.init(); webServer.setTestModeCallback(toggleTestMode); //initialize display Display::init(); //initialize gun and projectile profile ChronoReadingManager& chronoReadings = ChronoReadingManager::getInstance(); chronoReadings.initializeProfiles(); //Display::updateProfile(chronoReadings.getProfile()); //initialize bluetooth chronoBLE.init(); chronoBLE.setSpeedCallback(speedCallback); } void setDateTime(){ // Example: Set time to January 1, 2025, 12:00:00 struct tm t; t.tm_year = 2025 - 1900; // Year - 1900 t.tm_mon = 7; // Month (0-11, where 0 = Jan) t.tm_mday = 4; // Day of the month (1-31) t.tm_hour = 14; // Hour (0-23) t.tm_min = 56; // Minute (0-59) t.tm_sec = 0; // Second (0-59) t.tm_isdst = -1; // Is DST on? 1 = yes, 0 = no, -1 = unknown time_t epoch_time = mktime(&t); struct timeval tv; tv.tv_sec = epoch_time; tv.tv_usec = 0; settimeofday(&tv, NULL); // Verify the set time time_t now; char strftime_buf[64]; struct tm timeinfo; time(&now); localtime_r(&now, &timeinfo); strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); } void updateTime(){ time_t now; char strftime_buf[64]; struct tm timeinfo; time(&now); const char* TZ_EST = "EST5EDT,M3.2.0/2,M11.1.0/2"; setenv("TZ", TZ_EST, 1); tzset(); localtime_r(&now, &timeinfo); strftime(strftime_buf, sizeof(strftime_buf), "%R", &timeinfo); if (strcmp(currentTime, strftime_buf) != 0) { strcpy(currentTime, strftime_buf); Display::updateTime(strftime_buf); Display::refreshDisplay(); } } void checkBLE(){ if (chronoBLE.isIdle()){ if (chronoStateConnected){ chronoStateConnected=false; Display::showChronographDisconnected(); Display::refreshDisplay(); } chronoBLE.startScan(); } else if (chronoBLE.isConnected()){ //update display if (!chronoStateConnected){ chronoStateConnected=true; Display::showChronographConnected(); Display::refreshDisplay(); } } else if (chronoBLE.foundDevice()){ chronoBLE.connectToDevice(); } } void loop() { //process BLE connection checkBLE(); //process web server webServer.process(); //update time updateTime(); ////////////////////////////////////////////////////// //run testmode commands if in test mode if (testMode){ if (testModeLastAdd==0){Display::showChronographConnected();} if (millis()>(testModeLastAdd+5000)){ long randomNumber = random(890, 920); addReading(randomNumber); testModeLastAdd=millis(); } } ////////////////////////////////////////////////////// //update display Display::refreshDisplay(); delay(2); }