openMSX
ClockPin.cc
Go to the documentation of this file.
1#include "ClockPin.hh"
2#include "narrow.hh"
3#include "serialize.hh"
4#include <cassert>
5
6namespace openmsx {
7
9 : Schedulable(scheduler_), listener(listener_)
10{
11}
12
13void ClockPin::setState(bool newStatus, EmuTime::param time)
14{
15 periodic = false;
16 if (signalEdge) {
17 unschedule();
18 }
19 if (signalEdge && !status && newStatus) {
20 // pos edge
21 status = newStatus;
22 if (listener) {
23 listener->signalPosEdge(*this, time);
24 }
25 } else {
26 status = newStatus;
27 }
28 if (listener) {
29 listener->signal(*this, time);
30 }
31}
32
34 EmuDuration::param hi, EmuTime::param time)
35{
36 referenceTime = time;
37 totalDur = total;
38 hiDur = hi;
39
40 if (listener) {
41 if (periodic) {
42 unschedule();
43 }
44 periodic = true;
45 if (signalEdge) {
46 executeUntil(time);
47 }
48 listener->signal(*this, time);
49 } else {
50 periodic = true;
51 }
52}
53
54
55bool ClockPin::getState(EmuTime::param time) const
56{
57 if (!periodic) {
58 return status;
59 } else {
60 return ((time - referenceTime) % totalDur) < hiDur;
61 }
62}
63
65{
66 assert(periodic);
67 return totalDur;
68}
69
71{
72 assert(periodic);
73 return hiDur;
74}
75
76unsigned ClockPin::getTicksBetween(EmuTime::param begin, EmuTime::param end) const
77{
78 assert(begin <= end);
79 if (!periodic) {
80 return 0;
81 }
82 if (totalDur > EmuDuration::zero()) {
83 auto a = (begin < referenceTime)
84 ? 0
85 : (begin - referenceTime) / totalDur;
86 auto b = (end - referenceTime) / totalDur;
87 return b - a;
88 } else {
89 return 0;
90 }
91}
92
93
94void ClockPin::generateEdgeSignals(bool wanted, EmuTime::param time)
95{
96 if (signalEdge != wanted) {
97 signalEdge = wanted;
98 if (periodic) {
99 if (signalEdge) {
100 EmuTime tmp(referenceTime);
101 while (tmp < time) {
102 tmp += totalDur;
103 }
104 if (listener) {
105 schedule(tmp);
106 }
107 } else {
108 unschedule();
109 }
110 }
111 }
112}
113
114void ClockPin::unschedule()
115{
117}
118
119void ClockPin::schedule(EmuTime::param time)
120{
121 assert(signalEdge && periodic && listener);
122 setSyncPoint(time);
123}
124
125void ClockPin::executeUntil(EmuTime::param time)
126{
127 assert(signalEdge && periodic && listener);
128 listener->signalPosEdge(*this, time);
129 if (signalEdge && (totalDur > EmuDuration::zero())) {
130 schedule(time + totalDur);
131 }
132}
133
134
135template<typename Archive>
136void ClockPin::serialize(Archive& ar, unsigned /*version*/)
137{
138 ar.template serializeBase<Schedulable>(*this);
139 ar.serialize("totalDur", totalDur,
140 "hiDur", hiDur,
141 "referenceTime", referenceTime,
142 "periodic", periodic,
143 "status", status,
144 "signalEdge", signalEdge);
145}
147
148} // namespace openmsx
virtual void signal(ClockPin &pin, EmuTime::param time)=0
virtual void signalPosEdge(ClockPin &pin, EmuTime::param time)=0
ClockPin(Scheduler &scheduler, ClockPinListener *listener=nullptr)
Definition ClockPin.cc:8
unsigned getTicksBetween(EmuTime::param begin, EmuTime::param end) const
Definition ClockPin.cc:76
void generateEdgeSignals(bool wanted, EmuTime::param time)
Definition ClockPin.cc:94
void setState(bool status, EmuTime::param time)
Definition ClockPin.cc:13
void serialize(Archive &ar, unsigned version)
Definition ClockPin.cc:136
bool getState(EmuTime::param time) const
Definition ClockPin.cc:55
EmuDuration::param getHighDuration() const
Definition ClockPin.cc:70
void setPeriodicState(EmuDuration::param total, EmuDuration::param hi, EmuTime::param time)
Definition ClockPin.cc:33
EmuDuration::param getTotalDuration() const
Definition ClockPin.cc:64
static constexpr EmuDuration zero()
Every class that wants to get scheduled at some point must inherit from this class.
void setSyncPoint(EmuTime::param timestamp)
This file implemented 3 utility functions:
Definition Autofire.cc:11
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)