RTC.c
4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
Copyright (C) Dean Camera, 2019.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
#include "RTC.h"
#if defined(DUMMY_RTC)
/** Current dummy RTC time and date */
static volatile TimeDate_t DummyRTC_Count;
void RTC_Init(void)
{
DummyRTC_Count.Hour = 0;
DummyRTC_Count.Minute = 0;
DummyRTC_Count.Second = 0;
DummyRTC_Count.Day = 1;
DummyRTC_Count.Month = 1;
DummyRTC_Count.Year = 00;
}
void RTC_Tick500ms(void)
{
static bool HalfSecondElapsed = false;
HalfSecondElapsed = !HalfSecondElapsed;
if (HalfSecondElapsed == false)
return;
if (++DummyRTC_Count.Second < 60)
return;
DummyRTC_Count.Second = 0;
if (++DummyRTC_Count.Minute < 60)
return;
DummyRTC_Count.Minute = 0;
if (++DummyRTC_Count.Hour < 24)
return;
DummyRTC_Count.Hour = 0;
static const char MonthLength[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
uint8_t DaysInMonth = MonthLength[DummyRTC_Count.Month - 1];
/* Check if we need to account for a leap year */
if ((DummyRTC_Count.Month == 2) &&
((!(DummyRTC_Count.Year % 400)) || ((DummyRTC_Count.Year % 100) && !(DummyRTC_Count.Year % 4))))
{
DaysInMonth++;
}
if (++DummyRTC_Count.Day <= DaysInMonth)
return;
DummyRTC_Count.Day = 1;
if (++DummyRTC_Count.Month <= 12)
return;
DummyRTC_Count.Month = 1;
DummyRTC_Count.Year++;
}
bool RTC_SetTimeDate(const TimeDate_t* NewTimeDate)
{
GlobalInterruptDisable();
DummyRTC_Count = *NewTimeDate;
GlobalInterruptEnable();
return true;
}
bool RTC_GetTimeDate(TimeDate_t* const TimeDate)
{
GlobalInterruptDisable();
*TimeDate = DummyRTC_Count;
GlobalInterruptEnable();
return true;
}
#else
void RTC_Init(void)
{
/* Unused for a real external DS1307 RTC device */
}
void RTC_Tick500ms(void)
{
/* Unused for a real external DS1307 RTC device */
}
bool RTC_SetTimeDate(const TimeDate_t* NewTimeDate)
{
DS1307_DateTimeRegs_t NewRegValues;
const uint8_t WriteAddress = 0;
// Convert new time data to the DS1307's time register layout
NewRegValues.Byte1.Fields.TenSec = (NewTimeDate->Second / 10);
NewRegValues.Byte1.Fields.Sec = (NewTimeDate->Second % 10);
NewRegValues.Byte1.Fields.CH = false;
NewRegValues.Byte2.Fields.TenMin = (NewTimeDate->Minute / 10);
NewRegValues.Byte2.Fields.Min = (NewTimeDate->Minute % 10);
NewRegValues.Byte3.Fields.TenHour = (NewTimeDate->Hour / 10);
NewRegValues.Byte3.Fields.Hour = (NewTimeDate->Hour % 10);
NewRegValues.Byte3.Fields.TwelveHourMode = false;
// Convert new date data to the DS1307's date register layout
NewRegValues.Byte4.Fields.DayOfWeek = 0;
NewRegValues.Byte5.Fields.TenDay = (NewTimeDate->Day / 10);
NewRegValues.Byte5.Fields.Day = (NewTimeDate->Day % 10);
NewRegValues.Byte6.Fields.TenMonth = (NewTimeDate->Month / 10);
NewRegValues.Byte6.Fields.Month = (NewTimeDate->Month % 10);
NewRegValues.Byte7.Fields.TenYear = (NewTimeDate->Year / 10);
NewRegValues.Byte7.Fields.Year = (NewTimeDate->Year % 10);
// Write the new Time and Date into the DS1307
if (TWI_WritePacket(DS1307_ADDRESS, 10, &WriteAddress, sizeof(WriteAddress),
(uint8_t*)&NewRegValues, sizeof(DS1307_DateTimeRegs_t)) != TWI_ERROR_NoError)
{
return false;
}
return true;
}
bool RTC_GetTimeDate(TimeDate_t* const TimeDate)
{
DS1307_DateTimeRegs_t CurrentRegValues;
const uint8_t ReadAddress = 0;
// Read in the stored Time and Date from the DS1307
if (TWI_ReadPacket(DS1307_ADDRESS, 10, &ReadAddress, sizeof(ReadAddress),
(uint8_t*)&CurrentRegValues, sizeof(DS1307_DateTimeRegs_t)) != TWI_ERROR_NoError)
{
return false;
}
// Convert stored time value into decimal
TimeDate->Second = (CurrentRegValues.Byte1.Fields.TenSec * 10) + CurrentRegValues.Byte1.Fields.Sec;
TimeDate->Minute = (CurrentRegValues.Byte2.Fields.TenMin * 10) + CurrentRegValues.Byte2.Fields.Min;
TimeDate->Hour = (CurrentRegValues.Byte3.Fields.TenHour * 10) + CurrentRegValues.Byte3.Fields.Hour;
// Convert stored date value into decimal
TimeDate->Day = (CurrentRegValues.Byte5.Fields.TenDay * 10) + CurrentRegValues.Byte5.Fields.Day;
TimeDate->Month = (CurrentRegValues.Byte6.Fields.TenMonth * 10) + CurrentRegValues.Byte6.Fields.Month;
TimeDate->Year = (CurrentRegValues.Byte7.Fields.TenYear * 10) + CurrentRegValues.Byte7.Fields.Year;
return true;
}
#endif