summaryrefslogtreecommitdiff
path: root/firmware/drivers/fat.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/fat.c')
-rw-r--r--firmware/drivers/fat.c99
1 files changed, 54 insertions, 45 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index e319669e97..578397cbe6 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -1001,70 +1001,79 @@ static void fat_time(unsigned short* date,
#else
/* non-RTC version returns an increment from the supplied time, or a
* fixed standard time/date if no time given as input */
+
+/* Macros to convert a 2-digit string to a decimal constant.
+ (YEAR), MONTH and DAY are set by the date command, which outputs
+ DAY as 00..31 and MONTH as 01..12. The leading zero would lead to
+ misinterpretation as an octal constant. */
+#define S100(x) 1 ## x
+#define C2DIG2DEC(x) (S100(x)-100)
+/* The actual build date, as FAT date constant */
+#define BUILD_DATE_FAT (((YEAR - 1980) << 9) \
+ | (C2DIG2DEC(MONTH) << 5) \
+ | C2DIG2DEC(DAY))
+
+ bool date_forced = false;
bool next_day = false;
+ unsigned time2 = 0; /* double time, for CRTTIME with 1s precision */
+ if (date && *date < BUILD_DATE_FAT)
+ {
+ *date = BUILD_DATE_FAT;
+ date_forced = true;
+ }
+
if (time)
{
- if (0 == *time)
+ time2 = *time << 1;
+ if (time2 == 0 || date_forced)
{
- /* set to 00:15:00 */
- *time = (15 << 5);
+ time2 = (11 < 6) | 11; /* set to 00:11:11 */
}
else
{
- unsigned short mins = (*time >> 5) & 0x003F;
- unsigned short hours = (*time >> 11) & 0x001F;
- if ((mins += 10) >= 60)
- {
- mins = 0;
- hours++;
- }
- if ((++hours) >= 24)
+ unsigned mins = (time2 >> 6) & 0x3f;
+ unsigned hours = (time2 >> 12) & 0x1f;
+
+ mins = 11 * ((mins/11) + 1); /* advance to next multiple of 11 */
+ if (mins > 59)
{
- hours = hours - 24;
- next_day = true;
+ mins = 11; /* 00 would be a bad marker */
+ if (++hours > 23)
+ {
+ hours = 0;
+ next_day = true;
+ }
}
- *time = (hours << 11) | (mins << 5);
+ time2 = (hours << 12) | (mins << 6) | mins; /* secs = mins */
}
+ *time = time2 >> 1;
}
+
+ if (tenth)
+ *tenth = (time2 & 1) * 100;
- if (date)
+ if (date && next_day)
{
- if (0 == *date)
- {
-/* Macros to convert a 2-digit string to a decimal constant.
- (YEAR), MONTH and DAY are set by the date command, which outputs
- DAY as 00..31 and MONTH as 01..12. The leading zero would lead to
- misinterpretation as an octal constant. */
-#define S100(x) 1 ## x
-#define C2DIG2DEC(x) (S100(x)-100)
- /* set to build date */
- *date = ((YEAR - 1980) << 9) | (C2DIG2DEC(MONTH) << 5)
- | C2DIG2DEC(DAY);
- }
- else
+ static const unsigned char daysinmonth[] =
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ unsigned day = *date & 0x1f;
+ unsigned month = (*date >> 5) & 0x0f;
+ unsigned year = (*date >> 9) & 0x7f;
+
+ /* simplification: ignore leap years */
+ if (++day > daysinmonth[month-1])
{
- unsigned short day = *date & 0x001F;
- unsigned short month = (*date >> 5) & 0x000F;
- unsigned short year = (*date >> 9) & 0x007F;
- if (next_day)
+ day = 1;
+ if (++month > 12)
{
- /* do a very simple day increment - never go above 28 days */
- if (++day > 28)
- {
- day = 1;
- if (++month > 12)
- {
- month = 1;
- year++;
- }
- }
- *date = (year << 9) | (month << 5) | day;
+ month = 1;
+ year++;
}
}
+ *date = (year << 9) | (month << 5) | day;
}
- if (tenth)
- *tenth = 0;
+
#endif /* CONFIG_RTC */
}