forked from tjCFeng/ClassA20
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRTC.pas
157 lines (126 loc) · 3.5 KB
/
RTC.pas
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
(*
说明:全志A20的RTC底层操作封装类。单例。
TRTC类,可对寄存器直接操作,并实现了一些功能的简化。
作者:tjCFeng
更新日期:2014.12.06
*)
unit RTC;
{$mode objfpc}{$H+}
interface
uses SysUtils, A20;
type
TWeek = (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday);
TYMDHNSW = packed record //not TDateTime;
Year: Byte;
Month: Byte;
Day: Byte;
Hour: Byte;
Minute: Byte;
Second: Byte;
Week: TWeek;
end;
TRTC = class
private
class var FInstance: TRTC;
class function GetInstance: TRTC; static;
public
class procedure Release;
class property Instance: TRTC read GetInstance;
private
FRTC_BASE: ^LongWord;
procedure SetDT(Value: TYMDHNSW);
function GetDT: TYMDHNSW;
constructor Create;
destructor Destroy; override;
protected
FLOSC_CTRL: ^LongWord;
FRTC_DATE: ^LongWord;
FRTC_TIME: ^LongWord;
//Alarm Reg ...
public
property DateTime: TYMDHNSW read GetDT write SetDT;
end;
implementation
const
RTC_BASE = $01C20D00;
class function TRTC.GetInstance: TRTC;
begin
if FInstance = nil then FInstance:= TRTC.Create;
Result:= FInstance;
end;
class procedure TRTC.Release;
begin
FreeAndNil(FInstance);
end;
constructor TRTC.Create;
var Base: LongWord;
begin
inherited Create;
FRTC_BASE:= TA20.Instance.GetMMap(RTC_BASE);
Base:= LongWord(FRTC_BASE) + TA20.Instance.BaseOffset(RTC_BASE);
FLOSC_CTRL:= Pointer(Base + $00);
FRTC_DATE:= Pointer(Base + $04);
FRTC_TIME:= Pointer(Base + $08);
FLOSC_CTRL^:= FLOSC_CTRL^ and not ($1 shl 14);
FLOSC_CTRL^:= FLOSC_CTRL^ or ($1 shl 15) or $16AA0000;
FLOSC_CTRL^:= FLOSC_CTRL^ or $8; //($3 shl 2) or ($1 shl 0);
end;
destructor TRTC.Destroy;
begin
TA20.Instance.FreeMMap(FRTC_BASE);
inherited Destroy;
end;
procedure TRTC.SetDT(Value: TYMDHNSW);
var Leap: Byte; YMDFlag, HMSFlag: LongWord;
begin
with Value do
begin
if not (Year in [0..100]) then raise Exception.Create('Year must in [0..100]');
if not (Month in [1..12]) then raise Exception.Create('Month Error!');
if not (Day in [1..31]) then raise Exception.Create('Day Error!');
if not (Hour in [0..23]) then raise Exception.Create('Hour Error!');
if not (Minute in [0..59]) then raise Exception.Create('Minute Error!');
if not (Second in [0..59]) then raise Exception.Create('Second Error!');
end;
if IsLeapYear(Value.Year) then Leap:= 1 else Leap:= 0;
YMDFlag:= ($1 shl 7);
HMSFlag:= ($1 shl 8);
with Value do
begin
FRTC_DATE^:= 0;
while (FLOSC_CTRL^ and YMDFlag) <> 0 do Sleep(100);
FRTC_DATE^:= FRTC_DATE^ or (Leap shl 24) or (Year shl 16) or (Month shl 8) or (Day shl 0);
while (FLOSC_CTRL^ and YMDFlag) <> 0 do Sleep(100);
FRTC_TIME^:= 0;
while (FLOSC_CTRL^ and HMSFlag) <> 0 do Sleep(100);
FRTC_TIME^:= FRTC_TIME^ or (Ord(Week) shl 29) or (Hour shl 16) or (Minute shl 8) or (Second shl 0);
end;
end;
function TRTC.GetDT: TYMDHNSW;
var YMD, HMS: LongWord;
begin
YMD:= FRTC_DATE^;
HMS:= FRTC_TIME^;
with Result do
begin
Year:= (YMD shr 16) and $FF;
Month:= (YMD shr 8) and $F;
Day:= YMD and $1F;
Hour:= (HMS shr 16) and $1F;
Minute:= (HMS shr 8) and $3F;
Second:= HMS and $3F;
case (HMS shr 29) and $7 of
0: Week:= Monday;
1: Week:= Tuesday;
2: Week:= Wednesday;
3: Week:= Thursday;
4: Week:= Friday;
5: Week:= Saturday;
6: Week:= Sunday;
end;
end;
end;
finalization
TRTC.Instance.Release;
end.