summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/schedule.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/schedule.h')
-rw-r--r--src/emu/schedule.h190
1 files changed, 177 insertions, 13 deletions
diff --git a/src/emu/schedule.h b/src/emu/schedule.h
index 6e0aaccfdbf..ac0b9b5f36d 100644
--- a/src/emu/schedule.h
+++ b/src/emu/schedule.h
@@ -51,54 +51,218 @@
// MACROS
//**************************************************************************
+// this macro wraps a function 'x' and can be used to pass a function followed by its name
+#define FUNC(x) x, #x
+
+// this macro wraps a member function 'x' from class 'c' using a templatized stub of type 's'
+#define MFUNC(s,c,x) s##_stub<c, &c::x>, #c "::" #x
+
+
// these must be macros because we are included before the running_machine
#define cpuexec_describe_context(mach) (mach)->describe_context()
#define cpuexec_boost_interleave(mach, slice, dur) (mach)->scheduler().boost_interleave(slice, dur)
#define cpuexec_trigger(mach, trigid) (mach)->scheduler().trigger(trigid)
#define cpuexec_triggertime(mach, trigid, dur) (mach)->scheduler().trigger(trigid, dur)
+// macro for the RC time constant on a 74LS123 with C > 1000pF
+// R is in ohms, C is in farads
+#define TIME_OF_74LS123(r,c) (0.45 * (double)(r) * (double)(c))
+
+// macros for the RC time constant on a 555 timer IC
+// R is in ohms, C is in farads
+#define PERIOD_OF_555_MONOSTABLE_NSEC(r,c) ((attoseconds_t)(1100000000 * (double)(r) * (double)(c)))
+#define PERIOD_OF_555_ASTABLE_NSEC(r1,r2,c) ((attoseconds_t)( 693000000 * ((double)(r1) + 2.0 * (double)(r2)) * (double)(c)))
+#define PERIOD_OF_555_MONOSTABLE(r,c) attotime::from_nsec(PERIOD_OF_555_MONOSTABLE_NSEC(r,c))
+#define PERIOD_OF_555_ASTABLE(r1,r2,c) attotime::from_nsec(PERIOD_OF_555_ASTABLE_NSEC(r1,r2,c))
+
+#define TIMER_CALLBACK(name) void name(running_machine *machine, void *ptr, int param)
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
+// timer callbacks look like this
+typedef void (*timer_expired_func)(running_machine *machine, void *ptr, INT32 param);
+
+// stub for when the ptr parameter points to a class
+template<class T, void (T::*func)(running_machine &machine, INT32 param)>
+void timer_expired_stub(running_machine *machine, void *ptr, INT32 param)
+{
+ T *target = reinterpret_cast<T *>(ptr);
+ (target->*func)(*machine, param);
+}
+
+
+// ======================> emu_timer
+
+class emu_timer
+{
+ friend class device_scheduler;
+ friend class simple_list<emu_timer>;
+ friend class fixed_allocator<emu_timer>;
+
+ // construction/destruction
+ emu_timer();
+
+ // allocation and re-use
+ emu_timer &init(running_machine &machine, timer_expired_func callback, const char *name, void *ptr, bool temporary);
+ emu_timer &init(device_t &device, device_timer_id id, void *ptr, bool temporary);
+ emu_timer &release();
+
+public:
+ // getters
+ emu_timer *next() const { return m_next; }
+ running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
+ bool enabled() const { return m_enabled; }
+ int param() const { return m_param; }
+ void *ptr() const { return m_ptr; }
+
+ // setters
+ bool enable(bool enable = true);
+ void set_param(int param) { m_param = param; }
+ void set_ptr(void *ptr) { m_ptr = ptr; }
+
+ // control
+ void reset(attotime duration) { adjust(duration, m_param, m_period); }
+ void adjust(attotime duration, INT32 param = 0, attotime periodicity = attotime::never);
+
+ // timing queries
+ attotime elapsed() const;
+ attotime remaining() const;
+ attotime start() const { return m_start; }
+ attotime expire() const { return m_expire; }
+
+private:
+ // internal helpers
+ void register_save();
+ void schedule_next_period();
+
+ // internal state
+ running_machine * m_machine; // reference to the owning machine
+ emu_timer * m_next; // next timer in order in the list
+ emu_timer * m_prev; // previous timer in order in the list
+ timer_expired_func m_callback; // callback function
+ INT32 m_param; // integer parameter
+ void * m_ptr; // pointer parameter
+ const char * m_func; // string name of the callback function
+ bool m_enabled; // is the timer enabled?
+ bool m_temporary; // is the timer temporary?
+ attotime m_period; // the repeat frequency of the timer
+ attotime m_start; // time when the timer was started
+ attotime m_expire; // time when the timer will expire
+ device_t * m_device; // for device timers, a pointer to the device
+ device_timer_id m_id; // for device timers, the ID of the timer
+};
+
+
// ======================> device_scheduler
class device_scheduler
{
friend class device_execute_interface;
+ friend class emu_timer;
public:
+ // construction/destruction
device_scheduler(running_machine &machine);
~device_scheduler();
+ void register_for_save();
- void timeslice();
+ // getters
+ attotime time() const;
+ emu_timer *first_timer() const { return m_timer_list; }
+ device_execute_interface *currently_executing() const { return m_executing_device; }
+ bool can_save() const;
+ // execution
+ void timeslice();
+ void abort_timeslice();
void trigger(int trigid, attotime after = attotime::zero);
-
void boost_interleave(attotime timeslice_time, attotime boost_duration);
- void abort_timeslice();
+
+ // timers, specified by callback/name
+ emu_timer *timer_alloc(timer_expired_func callback, const char *name, void *ptr = NULL);
+ void timer_set(attotime duration, timer_expired_func callback, const char *name, int param = 0, void *ptr = NULL);
+ void timer_pulse(attotime period, timer_expired_func callback, const char *name, int param = 0, void *ptr = NULL);
+ void synchronize(timer_expired_func callback = NULL, const char *name = NULL, int param = 0, void *ptr = NULL) { timer_set(attotime::zero, callback, name, param, ptr); }
- device_execute_interface *currently_executing() const { return m_executing_device; }
-
- // for timer system only!
- attotime override_local_time(attotime default_time);
+ // timers, specified by device/id; generally devices should use the device_t methods instead
+ emu_timer *timer_alloc(device_t &device, device_timer_id id = 0, void *ptr = NULL);
+ void timer_set(attotime duration, device_t &device, device_timer_id id = 0, int param = 0, void *ptr = NULL);
// for emergencies only!
void eat_all_cycles();
private:
+ // callbacks
+ void timed_trigger(running_machine &machine, INT32 param);
+ void postload();
+
+ // scheduling helpers
void compute_perfect_interleave();
void rebuild_execute_list();
+ void add_scheduling_quantum(attotime quantum, attotime duration);
+
+ // timer helpers
+ emu_timer &timer_list_insert(emu_timer &timer);
+ emu_timer &timer_list_remove(emu_timer &timer);
+ void execute_timers();
+
+ // internal state
+ running_machine & m_machine; // reference to our machine
+ device_execute_interface * m_executing_device; // pointer to currently executing device
+ device_execute_interface * m_execute_list; // list of devices to be executed
+ attotime m_basetime; // global basetime; everything moves forward from here
+
+ // list of active timers
+ emu_timer * m_timer_list; // head of the active list
+ fixed_allocator<emu_timer> m_timer_allocator; // allocator for timers
- static TIMER_CALLBACK( static_timed_trigger );
+ // other internal states
+ emu_timer * m_callback_timer; // pointer to the current callback timer
+ bool m_callback_timer_modified; // true if the current callback timer was modified
+ attotime m_callback_timer_expire_time; // the original expiration time
- running_machine & m_machine; // reference to our owner
- bool m_quantum_set; // have we set the scheduling quantum yet?
- device_execute_interface * m_executing_device; // pointer to currently executing device
- device_execute_interface * m_execute_list; // list of devices to be executed
+ // scheduling quanta
+ class quantum_slot
+ {
+ friend class simple_list<quantum_slot>;
+
+ public:
+ quantum_slot *next() const { return m_next; }
+
+ quantum_slot * m_next;
+ attoseconds_t m_actual; // actual duration of the quantum
+ attoseconds_t m_requested; // duration of the requested quantum
+ attotime m_expire; // absolute expiration time of this quantum
+ };
+ simple_list<quantum_slot> m_quantum_list; // list of active quanta
+ fixed_allocator<quantum_slot> m_quantum_allocator; // allocator for quanta
+ attoseconds_t m_quantum_minimum; // duration of minimum quantum
};
-#endif /* __SCHEDULE_H__ */
+
+
+// temporary stuff
+attotime timer_get_time(running_machine *machine);
+
+inline void timer_adjust_oneshot(emu_timer *which, attotime duration, INT32 param) { which->adjust(duration, param); }
+inline void timer_adjust_periodic(emu_timer *which, attotime start_delay, INT32 param, attotime period) { which->adjust(start_delay, param, period); }
+
+inline void timer_reset(emu_timer *which, attotime duration) { which->reset(duration); }
+inline int timer_enable(emu_timer *which, int enable) { return which->enable(enable); }
+inline int timer_enabled(emu_timer *which) { return which->enabled(); }
+inline int timer_get_param(emu_timer *which) { return which->param(); }
+inline void timer_set_param(emu_timer *which, int param) { which->set_param(param); }
+inline void *timer_get_ptr(emu_timer *which) { return which->ptr(); }
+inline void timer_set_ptr(emu_timer *which, void *ptr) { which->set_ptr(ptr); }
+
+inline attotime timer_timeelapsed(emu_timer *which) { return which->elapsed(); }
+inline attotime timer_timeleft(emu_timer *which) { return which->remaining(); }
+inline attotime timer_starttime(emu_timer *which) { return which->start(); }
+inline attotime timer_firetime(emu_timer *which) { return which->expire(); }
+
+#endif // __SCHEDULE_H__ */