libsidplayfp  2.12.0
interrupt.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2020 Leandro Nini <drfiemost@users.sourceforge.net>
5  * Copyright 2007-2010 Antti Lankila
6  * Copyright 2000 Simon White
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef INTERRUPT_H
24 #define INTERRUPT_H
25 
26 #include "Event.h"
27 #include "EventScheduler.h"
28 #include "EventCallback.h"
29 
30 #include <stdint.h>
31 
32 #include "sidcxx11.h"
33 
34 namespace libsidplayfp
35 {
36 
37 class MOS652X;
38 
44 {
45 public:
46  enum
47  {
51  INTERRUPT_ALARM = 1 << 2,
52  INTERRUPT_SP = 1 << 3,
53  INTERRUPT_FLAG = 1 << 4,
54  INTERRUPT_REQUEST = 1 << 7
55  };
56 
57 private:
59  MOS652X &parent;
60 
61 protected:
64 
66  event_clock_t last_clear = 0;
67  event_clock_t last_set = 0;
68 
70  uint8_t icr = 0;
71 
73  uint8_t idr = 0;
74 
75  uint8_t idrTemp = 0;
76 
78  bool scheduled = false;
79 
81  bool asserted = false;
82 
83 private:
84  EventCallback<InterruptSource> interruptEvent;
85 
86  EventCallback<InterruptSource> updateIdrEvent;
87 
89 
90  EventCallback<InterruptSource> clearIrqEvent;
91 
92 protected:
93  inline bool interruptTriggered() const { return idr & INTERRUPT_REQUEST; }
94 
95  inline bool interruptMasked(uint8_t interruptMask) const
96  {
97  return ((interruptMask != INTERRUPT_NONE) ? interruptMask : idr) & icr;
98  }
99 
100  virtual void triggerInterrupt() =0;
101 
105  inline bool ack0() const { return eventScheduler.getTime(EVENT_CLOCK_PHI2) == (last_clear+1); }
106  inline bool write0() const { return eventScheduler.getTime(EVENT_CLOCK_PHI2) == (last_set+1); }
107 
111  void interrupt();
112 
113  void updateIdr();
114 
115  void setIrq();
116 
117  void clearIrq();
118 
119 protected:
126  InterruptSource(EventScheduler &scheduler, MOS652X &parent) :
127  parent(parent),
128  eventScheduler(scheduler),
129  interruptEvent("CIA Interrupt", *this, &InterruptSource::interrupt),
130  updateIdrEvent("CIA update ICR", *this, &InterruptSource::updateIdr),
131  setIrqEvent("CIA set IRQ", *this, &InterruptSource::setIrq),
132  clearIrqEvent("CIA clear IRQ", *this, &InterruptSource::clearIrq)
133  {}
134 
138  void schedule(int delay)
139  {
140  if (!scheduled)
141  {
142  eventScheduler.schedule(interruptEvent, delay, EVENT_CLOCK_PHI1);
143  scheduled = true;
144  }
145  }
146 
147  void scheduleIrq()
148  {
149  eventScheduler.schedule(setIrqEvent, 1, EVENT_CLOCK_PHI1);
150  }
151 
152  bool isTriggered(uint8_t interruptMask);
153 
154 public:
155  virtual ~InterruptSource() = default;
156 
162  virtual void trigger(uint8_t interruptMask) =0;
163 
169  virtual uint8_t clear();
170 
175  virtual void reset()
176  {
177  last_clear = 0;
178  last_set = 0;
179 
180  icr = 0;
181  idr = 0;
182 
183  eventScheduler.cancel(updateIdrEvent);
184  eventScheduler.cancel(setIrqEvent);
185  eventScheduler.cancel(clearIrqEvent);
186  eventScheduler.cancel(interruptEvent);
187  scheduled = false;
188 
189  asserted = false;
190  }
191 
197  void set(uint8_t interruptMask);
198 };
199 
200 }
201 
202 #endif // INTERRUPT_H
Definition: EventCallback.h:36
Definition: EventScheduler.h:62
event_clock_t getTime(event_phase_t phase) const
Definition: EventScheduler.h:158
void cancel(Event &event)
Definition: EventScheduler.cpp:35
Definition: interrupt.h:44
uint8_t idr
Interrupt data register.
Definition: interrupt.h:73
EventScheduler & eventScheduler
Event scheduler.
Definition: interrupt.h:63
event_clock_t last_clear
Clock when clear was called last.
Definition: interrupt.h:66
InterruptSource(EventScheduler &scheduler, MOS652X &parent)
Definition: interrupt.h:126
bool asserted
is the irq pin asserted?
Definition: interrupt.h:81
void set(uint8_t interruptMask)
Definition: interrupt.cpp:93
@ INTERRUPT_NONE
no interrupt
Definition: interrupt.h:48
@ INTERRUPT_REQUEST
control bit
Definition: interrupt.h:54
@ INTERRUPT_SP
serial port
Definition: interrupt.h:52
@ INTERRUPT_UNDERFLOW_B
underflow Timer B
Definition: interrupt.h:50
@ INTERRUPT_FLAG
external flag
Definition: interrupt.h:53
@ INTERRUPT_ALARM
alarm clock
Definition: interrupt.h:51
@ INTERRUPT_UNDERFLOW_A
underflow Timer A
Definition: interrupt.h:49
bool ack0() const
Definition: interrupt.h:105
bool scheduled
Have we already scheduled CIA->CPU interrupt transition?
Definition: interrupt.h:78
uint8_t icr
Interrupt control register.
Definition: interrupt.h:70
virtual void reset()
Definition: interrupt.h:175
void schedule(int delay)
Definition: interrupt.h:138
virtual void trigger(uint8_t interruptMask)=0
virtual uint8_t clear()
Definition: interrupt.cpp:110
void interrupt()
Definition: interrupt.cpp:30
Definition: mos652x.h:154