Advertisement
ripred

CompileTime.cpp

Dec 5th, 2023 (edited)
762
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.94 KB | None | 0 0
  1. /*
  2.  * CompileTime.cpp
  3.  *
  4.  * implementation file for the CompileTime library
  5.  *
  6.  * version 1.0 written June 2023 - Trent M. Wyatt
  7.  *
  8.  */
  9. #include "CompileTime.h"
  10.  
  11. #include <stdio.h>
  12. #include <stdint.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <stdbool.h>
  16. #include "EEPROM.h"
  17.  
  18. char const * const tmstr = __TIME__;
  19. char const * const dtstr = __DATE__;
  20.  
  21. // Function to check if a year is a leap year
  22. static bool isLeapYear(int year) {
  23.     if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
  24.         return true;  // Leap year
  25.     } else {
  26.         return false; // Not a leap year
  27.     }
  28. }
  29.  
  30. // Array of days in each month
  31. static int16_t daysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  32.  
  33. enum MagicNumbers : uint32_t {
  34.     secsPerMin    =   60UL,
  35.     minsPerHour   =   60UL,
  36.     secsPerHour   = 3600UL,
  37. };
  38.  
  39. static uint16_t const monthhash[12] = {
  40. // ascii added together
  41.     281,    // J+a+n = 74+97+110
  42.     269,    // F+e+b = 70+101+98
  43.     288,    // M+a+r = 77+97+114
  44.     291,    // A+p+r = 65+112+114
  45.     295,    // M+a+y = 77+97+121
  46.     301,    // J+u+n = 74+117+110
  47.     299,    // J+u+l = 74+117+108
  48.     285,    // A+u+g = 65+117+103
  49.     296,    // S+e+p = 83+101+112
  50.     294,    // O+c+t = 79+99+116
  51.     307,    // N+o+v = 78+111+118
  52.     268,    // D+e+c = 68+101+99
  53. };
  54.  
  55. namespace CompileTime {
  56.  
  57. // Global values used at runtime
  58. uint32_t startTime;
  59. volatile int16_t hour;
  60. volatile int16_t minute;
  61. volatile int16_t second;
  62. volatile int16_t year;
  63. volatile int16_t month;
  64. volatile int16_t day;
  65.  
  66. // The number of microseconds to calibrate the internal PLL
  67. // generated clock source to (if in use and adjusted):
  68. uint32_t uSecAdjust = 1000000UL;
  69.  
  70. void writeUInt32ToEEPROM(uint32_t value, int address) {
  71.     for (int i = 0; i < 4; ++i) {
  72.         EEPROM.write(address + i, (value >> (i * 8)) & 0xFF);
  73.     }
  74. }
  75.  
  76. uint32_t readUInt32FromEEPROM(int address) {
  77.     uint32_t value = 0;
  78.  
  79.     for (int i = 0; i < 4; ++i) {
  80.         value |= (uint32_t)(EEPROM.read(address + i)) << (i * 8);
  81.     }
  82.  
  83.     return value;
  84. }
  85.  
  86. uint32_t const eeprom_signature = 0xDEADBEEF;
  87.  
  88. int isEepromValid() {
  89.     return readUInt32FromEEPROM(0) == eeprom_signature;
  90. }
  91.  
  92. void writeEepromCalibrate(uint32_t cal_us) {
  93.     writeUInt32ToEEPROM(eeprom_signature, 0);
  94.     writeUInt32ToEEPROM(cal_us, sizeof(eeprom_signature));
  95. }
  96.  
  97. void setCompileTime(uint32_t const upload) {
  98.     // convert the digits from the ascii __TIME__ string into binary values:
  99.     char tm[9] {0};
  100.     strcpy(tm, tmstr);
  101.     uint16_t curHour   = ((uint32_t)(tm[0] - '0') * 10UL) + (uint32_t)(tm[1] - '0');
  102.     uint16_t curMinute = ((uint32_t)(tm[3] - '0') * 10UL) + (uint32_t)(tm[4] - '0');
  103.     uint16_t curSecond = ((uint32_t)(tm[6] - '0') * 10UL) + (uint32_t)(tm[7] - '0');
  104.  
  105.     char dt[12] {0};
  106.     strcpy(dt, dtstr);
  107.     uint16_t curYear = atoi(dt + 7);
  108.     uint16_t monthHash = dt[0] + dt[1] + dt[2];
  109.     uint8_t curMonth = -1;
  110.     for (uint8_t m = 0; m < 12; m++) {
  111.         if (monthHash == monthhash[m]) {
  112.             curMonth = m;
  113.             break;
  114.         }
  115.     }
  116.     char const * dayPtr = (' ' == dt[4]) ? dt + 5 : dt + 4;
  117.     volatile uint8_t curDay = atoi(dayPtr);
  118.  
  119.     // Adjust for the time it took to upload: (change time as needed)
  120.     curSecond += upload;
  121.     while (curSecond >= secsPerMin) {
  122.         curSecond -= secsPerMin;
  123.         if (++curMinute >= minsPerHour) {
  124.             curMinute -= minsPerHour;
  125.             if (++curHour >= 24UL) {
  126.                 curHour -= 24UL;
  127.             }
  128.         }
  129.     }
  130.  
  131.     hour   = curHour;
  132.     minute = curMinute;
  133.     second = curSecond;
  134.     year   = curYear;
  135.     month  = curMonth;
  136.     day    = curDay;
  137.  
  138.     // Set the starting time in seconds since midnight:
  139.     startTime = curHour * secsPerHour + curMinute * secsPerMin + curSecond;
  140.  
  141.     uint32_t const eeprom_signature = 0xDEADBEEF;
  142.     uint32_t const existing_signature = readUInt32FromEEPROM(0);
  143.     if (existing_signature == eeprom_signature) {
  144.         uSecAdjust = readUInt32FromEEPROM(sizeof(eeprom_signature));
  145.     }
  146. }
  147.  
  148. static int16_t last_hour = hour;
  149.  
  150. void updateTime(uint32_t const now) {
  151.     uint32_t now_secs = (now / uSecAdjust) + startTime;
  152.     int16_t curHour = now_secs / secsPerHour;
  153.     now_secs -= curHour * secsPerHour;
  154.     int16_t curMinute = now_secs / secsPerMin;
  155.     now_secs -= curMinute * secsPerMin;
  156.  
  157.     if (isLeapYear(year)) {
  158.         daysInMonth[1] = 29; // February
  159.     } else {
  160.         daysInMonth[1] = 28; // February
  161.     }
  162.  
  163.     if (last_hour != hour) {
  164.         if (last_hour == 23 && hour == 0) {
  165.             day++;
  166.             if (daysInMonth[month] == day) {
  167.                 day = 1;
  168.                 month++;
  169.                 if (month == 13) {
  170.                     month = 1;
  171.                     year++;
  172.                 }
  173.             }
  174.         }
  175.         last_hour = hour;
  176.     }
  177.  
  178.     hour = curHour;
  179.     minute = curMinute;
  180.     second = now_secs;
  181. }
  182.  
  183. } // namespace CompileTime
  184.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement