Files
Pico-GB/lib/FatFs_SPI/src/rtc.c
T
2025-08-16 23:06:15 +02:00

117 lines
3.7 KiB
C

/* rtc.c
Copyright 2021 Carl John Kugler III
Licensed under the Apache License, Version 2.0 (the License); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
*/
#include <stdio.h>
#include <time.h>
//
#include "hardware/rtc.h"
#include "pico/stdio.h"
#include "pico/stdlib.h"
#include "pico/util/datetime.h"
//
#include "ff.h"
#include "util.h" // calculate_checksum
//
#include "rtc.h"
static time_t epochtime;
// Make an attempt to save a recent time stamp across reset:
typedef struct rtc_save {
uint32_t signature;
datetime_t datetime;
uint32_t checksum; // last, not included in checksum
} rtc_save_t;
static rtc_save_t rtc_save __attribute__((section(".uninitialized_data")));
static void update_epochtime() {
bool rc = rtc_get_datetime(&rtc_save.datetime);
if (rc) {
rtc_save.signature = 0xBABEBABE;
struct tm timeinfo = {
.tm_sec = rtc_save.datetime
.sec, /* Seconds. [0-60] (1 leap second) */
.tm_min = rtc_save.datetime.min, /* Minutes. [0-59] */
.tm_hour = rtc_save.datetime.hour, /* Hours. [0-23] */
.tm_mday = rtc_save.datetime.day, /* Day. [1-31] */
.tm_mon = rtc_save.datetime.month - 1, /* Month. [0-11] */
.tm_year = rtc_save.datetime.year - 1900, /* Year - 1900. */
.tm_wday = 0, /* Day of week. [0-6] */
.tm_yday = 0, /* Days in year.[0-365] */
.tm_isdst = -1 /* DST. [-1/0/1]*/
};
rtc_save.checksum = calculate_checksum((uint32_t *)&rtc_save,
offsetof(rtc_save_t, checksum));
epochtime = mktime(&timeinfo);
rtc_save.datetime.dotw = timeinfo.tm_wday;
// configASSERT(-1 != epochtime);
}
}
time_t time(time_t *pxTime) {
update_epochtime();
if (pxTime) {
*pxTime = epochtime;
}
return epochtime;
}
void time_init() {
rtc_init();
datetime_t t = {0, 0, 0, 0, 0, 0, 0};
rtc_get_datetime(&t);
if (!t.year && rtc_save.datetime.year) {
uint32_t xor_checksum = calculate_checksum(
(uint32_t *)&rtc_save, offsetof(rtc_save_t, checksum));
if (rtc_save.signature == 0xBABEBABE &&
rtc_save.checksum == xor_checksum) {
// Set rtc
rtc_set_datetime(&rtc_save.datetime);
}
}
}
// Called by FatFs:
DWORD get_fattime(void) {
datetime_t t = {0, 0, 0, 0, 0, 0, 0};
bool rc = rtc_get_datetime(&t);
if (!rc) return 0;
DWORD fattime = 0;
// bit31:25
// Year origin from the 1980 (0..127, e.g. 37 for 2017)
uint8_t yr = t.year - 1980;
fattime |= (0b01111111 & yr) << 25;
// bit24:21
// Month (1..12)
uint8_t mo = t.month;
fattime |= (0b00001111 & mo) << 21;
// bit20:16
// Day of the month (1..31)
uint8_t da = t.day;
fattime |= (0b00011111 & da) << 16;
// bit15:11
// Hour (0..23)
uint8_t hr = t.hour;
fattime |= (0b00011111 & hr) << 11;
// bit10:5
// Minute (0..59)
uint8_t mi = t.min;
fattime |= (0b00111111 & mi) << 5;
// bit4:0
// Second / 2 (0..29, e.g. 25 for 50)
uint8_t sd = t.sec / 2;
fattime |= (0b00011111 & sd);
return fattime;
}