VirtualC64 v5.0 beta
Commodore 64 Emulator
Loading...
Searching...
No Matches
TOD.h
1// -----------------------------------------------------------------------------
2// This file is part of VirtualC64
3//
4// Copyright (C) Dirk W. Hoffmann. www.dirkwhoffmann.de
5// This FILE is dual-licensed. You are free to choose between:
6//
7// - The GNU General Public License v3 (or any later version)
8// - The Mozilla Public License v2
9//
10// SPDX-License-Identifier: GPL-3.0-or-later OR MPL-2.0
11// -----------------------------------------------------------------------------
12
13#pragma once
14
15#include "TODTypes.h"
16#include "SubComponent.h"
17
18namespace vc64 {
19
20/* Time of day clock (TOD). Each CIA contains a time of day clock, counting
21 * hours, minutes, seconds and tenths of a second. Furthermore, every TOD clock
22 * features an alarm mechanism. When the alarm time is reached, an interrupt
23 * is triggered.
24 */
25class TOD final : public SubComponent, public Inspectable<TODInfo> {
26
27 friend class CIA;
28
29 Descriptions descriptions = {{
30
31 .name = "TOD",
32 .description = "Time-of-day Clock"
33 }};
34
35private:
36
37 // Result of the latest inspection
38 mutable TODInfo info = { };
39
40 // Reference to the connected CIA
41 class CIA &cia;
42
43 // Time of day clock
44 TimeOfDay tod;
45
46 // Time of day clock latch
47 TimeOfDay latch;
48
49 // Alarm time
50 TimeOfDay alarm;
51
52 /* Indicates if the TOD registers are frozen. The CIA freezes the registers
53 * when the hours-part is read and reactivates them, when the 1/10th part
54 * is read. Although the values stay constant, the internal clock continues
55 * to advance. Hence, if the hours-part is read first, the clock won't
56 * change until all fragments have been read.
57 */
58 bool frozen;
59
60 /* Indicates if the TOD clock is halted. The CIA chip stops the TOD clock
61 * when the hours-part is written and restarts it, when the 1/10th part is
62 * written. This ensures that the clock doesn't start until the time is
63 * set completely.
64 */
65 bool stopped;
66
67 /* Indicates if tod time matches the alarm time. This value is read in
68 * checkIrq() for edge detection.
69 */
70 bool matching;
71
72 // Cycle where the tenth of a second counter needs to be incremented
73 Cycle nextTodTrigger;
74
75
76 //
77 // Methods
78 //
79
80public:
81
82 TOD(C64 &ref, CIA &cia);
83
84 TOD& operator= (const TOD& other) {
85
86 CLONE(tod.value)
87 CLONE(latch.value)
88 CLONE(alarm.value)
89 CLONE(frozen)
90 CLONE(stopped)
91 CLONE(matching)
92 CLONE(nextTodTrigger)
93
94 return *this;
95 }
96
97
98 //
99 // Methods from Serializable
100 //
101
102public:
103
104 template <class T>
105 void serialize(T& worker)
106 {
107 worker
108
109 << tod.value
110 << latch.value
111 << alarm.value
112 << frozen
113 << stopped
114 << matching
115 << nextTodTrigger;
116
117 } SERIALIZERS(serialize);
118
119
120 //
121 // Methods from CoreComponent
122 //
123
124public:
125
126 const Descriptions &getDescriptions() const override { return descriptions; }
127
128private:
129
130 void _dump(Category category, std::ostream& os) const override;
131 void _reset(bool hard) override;
132
133
134 //
135 // Methods from Inspectable
136 //
137
138public:
139
140 void cacheInfo(TODInfo &result) const override;
141
142
143 //
144 // Accessing
145 //
146
147 // Returns the hours digits of the time of day clock
148 u8 getTodHours() const { return (frozen ? latch.hour : tod.hour) & 0x9F; }
149
150 // Returns the minutes digits of the time of day clock
151 u8 getTodMinutes() const { return (frozen ? latch.min : tod.min) & 0x7F; }
152
153 // Returns the seconds digits of the time of day clock
154 u8 getTodSeconds() const { return (frozen ? latch.sec : tod.sec) & 0x7F; }
155
156 // Returns the tenth-of-a-second digits of the time of day clock
157 u8 getTodTenth() const { return (frozen ? latch.tenth : tod.tenth) & 0x0F; }
158
159 // Returns the hours digits of the alarm time
160 u8 getAlarmHours() const { return alarm.hour & 0x9F; }
161
162 // Returns the minutes digits of the alarm time
163 u8 getAlarmMinutes() const { return alarm.min & 0x7F; }
164
165 // Returns the seconds digits of the alarm time
166 u8 getAlarmSeconds() const { return alarm.sec & 0x7F; }
167
168 // Returns the tenth-of-a-second digits of the alarm time
169 u8 getAlarmTenth() const { return alarm.tenth & 0x0F; }
170
171 // Sets the hours digits of the time of day clock
172 void setTodHours(u8 value) { tod.hour = value & 0x9F; checkIrq(); }
173
174 // Sets the minutes digits of the time of day clock
175 void setTodMinutes(u8 value) { tod.min = value & 0x7F; checkIrq(); }
176
177 // Sets the seconds digits of the time of day clock
178 void setTodSeconds(u8 value) { tod.sec = value & 0x7F; checkIrq(); }
179
180 // Sets the tenth-of-a-second digits of the time of day clock
181 void setTodTenth(u8 value) { tod.tenth = value & 0x0F; checkIrq(); }
182
183 // Sets the hours digits of the alarm time
184 void setAlarmHours(u8 value) { alarm.hour = value & 0x9F; checkIrq(); }
185
186 // Sets the minutes digits of the alarm time
187 void setAlarmMinutes(u8 value) { alarm.min = value & 0x7F; checkIrq(); }
188
189 // Sets the seconds digits of the alarm time
190 void setAlarmSeconds(u8 value) { alarm.sec = value & 0x7F; checkIrq(); }
191
192 // Sets the tenth-of-a-second digits of the time of day clock
193 void setAlarmTenth(u8 value) { alarm.tenth = value & 0x0F; checkIrq(); }
194
195
196 //
197 // Emulating
198 //
199
200public:
201
202 // Increments the TOD clock if necessary (called after each scanline)
203 void increment();
204
205private:
206
207 // Freezes the time of day clock
208 void freeze() { if (!frozen) { latch.value = tod.value; frozen = true; } }
209
210 // Unfreezes the time of day clock
211 void defreeze() { frozen = false; }
212
213 // Stops the time of day clock
214 void stop() { stopped = true; }
215
216 // Starts the time of day clock
217 void cont();
218
219 // Updates variable 'matching'. A positive edge triggers an interrupt.
220 void checkIrq();
221};
222
223}
VirtualC64 project namespace.
Definition CmdQueue.cpp:16