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 
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, 0);
50  }
51  listener->signal(*this, time);
52  } else {
53  periodic = true;
54  }
55 }
56 
57 
59 {
60  if (!periodic) {
61  return status;
62  } else {
63  return ((time - referenceTime) % totalDur) < hiDur;
64  }
65 }
66 
68 {
69  return periodic;
70 }
71 
73 {
74  assert(periodic);
75  return totalDur;
76 }
77 
79 {
80  assert(periodic);
81  return hiDur;
82 }
83 
85 {
86  assert(begin <= end);
87  if (!periodic) {
88  return 0;
89  }
90  if (totalDur > EmuDuration::zero) {
91  int a = (begin < referenceTime) ?
92  0 :
93  (begin - referenceTime) / totalDur;
94  int b = (end - referenceTime) / totalDur;
95  return b - a;
96  } else {
97  return 0;
98  }
99 }
100 
101 
103 {
104  if (signalEdge != wanted) {
105  signalEdge = wanted;
106  if (periodic) {
107  if (signalEdge) {
108  EmuTime tmp(referenceTime);
109  while (tmp < time) {
110  tmp += totalDur;
111  }
112  if (listener) {
113  schedule(tmp);
114  }
115  } else {
116  unschedule();
117  }
118  }
119  }
120 }
121 
122 void ClockPin::unschedule()
123 {
124  removeSyncPoint();
125 }
126 
127 void ClockPin::schedule(EmuTime::param time)
128 {
129  assert(signalEdge && periodic && listener);
130  setSyncPoint(time);
131 }
132 
133 void ClockPin::executeUntil(EmuTime::param time, int /*userdata*/)
134 {
135  assert(signalEdge && periodic && listener);
136  listener->signalPosEdge(*this, time);
137  if (signalEdge && (totalDur > EmuDuration::zero)) {
138  schedule(time + totalDur);
139  }
140 }
141 
142 
143 template<typename Archive>
144 void ClockPin::serialize(Archive& ar, unsigned /*version*/)
145 {
146  ar.template serializeBase<Schedulable>(*this);
147  ar.serialize("totalDur", totalDur);
148  ar.serialize("hiDur", hiDur);
149  ar.serialize("referenceTime", referenceTime);
150  ar.serialize("periodic", periodic);
151  ar.serialize("status", status);
152  ar.serialize("signalEdge", signalEdge);
153 }
155 
156 } // namespace openmsx