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