1 /***************************************************************************
2                           event.h  -  Event scheduler (based on alarm
3                                       from Vice)
4                              -------------------
5     begin                : Wed May 9 2001
6     copyright            : (C) 2001 by Simon White
7     email                : s_a_white@email.com
8  ***************************************************************************/
9 
10 /***************************************************************************
11  *                                                                         *
12  *   This program is free software; you can redistribute it and/or modify  *
13  *   it under the terms of the GNU General Public License as published by  *
14  *   the Free Software Foundation; either version 2 of the License, or     *
15  *   (at your option) any later version.                                   *
16  *                                                                         *
17  ***************************************************************************/
18 
19 #ifndef _event_h_
20 #define _event_h_
21 
22 #include <stdio.h>
23 #include "sidtypes.h"
24 
25 typedef uint_fast32_t event_clock_t;
26 typedef enum {EVENT_CLOCK_PHI1 = 0, EVENT_CLOCK_PHI2 = 1} event_phase_t;
27 #define EVENT_CONTEXT_MAX_PENDING_EVENTS 0x100
28 
29 class SID_EXTERN Event
30 {
31     friend class EventScheduler;
32 
33 public:
34     const char * const m_name;
35     event_clock_t m_clk;
36 
37     /* This variable is set by the event context
38        when it is scheduled */
39     bool m_pending;
40 
41     /* Link to the next and previous events in the
42        list.  */
43     Event *m_next, *m_prev;
44 
45 public:
Event(const char * const name)46     Event(const char * const name)
47         : m_name(name),
48           m_pending(false) {}
49 
50     virtual void event (void) = 0;
pending()51     bool    pending () { return m_pending; }
52 };
53 
54 // Public Event Context
55 class EventContext
56 {
57 public:
58     virtual void cancel   (Event *event) = 0;
59     virtual void schedule (Event *event, event_clock_t cycles,
60                            event_phase_t phase) = 0;
61     virtual event_clock_t getTime (event_phase_t phase) const = 0;
62     virtual event_clock_t getTime (event_clock_t clock, event_phase_t phase) const = 0;
63     virtual event_phase_t phase () const = 0;
64 };
65 
66 // Private Event Context Object (The scheduler)
67 class EventScheduler: public EventContext, public Event
68 {
69 private:
70     event_clock_t m_absClk;
71     uint  m_events;
72 
73     class SID_EXTERN EventTimeWarp: public Event
74     {
75     private:
76         EventScheduler &m_scheduler;
77 
event(void)78         void event (void)
79         {
80             m_scheduler.event ();
81         }
82 
83     public:
EventTimeWarp(EventScheduler * context)84         EventTimeWarp (EventScheduler *context)
85         :Event("Time Warp"),
86          m_scheduler(*context)
87         {;}
88     } m_timeWarp;
89     friend class EventTimeWarp;
90 
91 private:
92     void event    (void);
dispatch(Event & e)93     void dispatch (Event &e)
94     {
95         cancelPending (e);
96         //printf ("Event \"%s\"\n", e.m_name);
97         e.event ();
98     }
99 
cancelPending(Event & event)100     void cancelPending (Event &event)
101     {
102         event.m_pending      = false;
103         event.m_prev->m_next = event.m_next;
104         event.m_next->m_prev = event.m_prev;
105         m_events--;
106     }
107 
108 public:
109     EventScheduler (const char * const name);
110     void cancel    (Event *event);
111     void reset     (void);
112     void schedule  (Event *event, event_clock_t cycles,
113                     event_phase_t phase);
114 
clock(void)115     void clock (void)
116     {
117 //        m_clk++;
118 //        while (m_events && (m_clk >= m_next->m_clk))
119 //            dispatch (*m_next);
120         m_clk = m_next->m_clk;
121         dispatch (*m_next);
122     }
123 
124     // Get time with respect to a specific clock phase
getTime(event_phase_t phase)125     event_clock_t getTime (event_phase_t phase) const
126     {   return (m_absClk + m_clk + (phase ^ 1)) >> 1; }
getTime(event_clock_t clock,event_phase_t phase)127     event_clock_t getTime (event_clock_t clock, event_phase_t phase) const
128     {   return ((getTime (phase) - clock) << 1) >> 1; } // 31 bit res.
phase()129     event_phase_t phase () const { return (event_phase_t) ((m_absClk + m_clk) & 1); }
130 };
131 
132 #endif // _event_h_
133