1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     timer.h
6 
7     Timer devices.
8 
9 ***************************************************************************/
10 #ifndef MAME_MACHINE_TIMER_H
11 #define MAME_MACHINE_TIMER_H
12 
13 #pragma once
14 
15 #include "screen.h"
16 
17 
18 //**************************************************************************
19 //  MACROS
20 //**************************************************************************
21 
22 // macros for a timer callback functions
23 #define TIMER_DEVICE_CALLBACK_MEMBER(name)  void name(timer_device &timer, void *ptr, s32 param)
24 
25 //**************************************************************************
26 //  TYPE DEFINITIONS
27 //**************************************************************************
28 
29 // ======================> timer_device
30 
31 class timer_device : public device_t
32 {
33 public:
34 	// a timer callbacks look like this
35 	typedef device_delegate<void (timer_device &, void *, s32)> expired_delegate;
36 
37 	// construction/destruction
38 	timer_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
39 
40 	// inline configuration helpers
configure_generic(T &&...args)41 	template <typename... T> void configure_generic(T &&... args)
42 	{
43 		m_type = TIMER_TYPE_GENERIC;
44 		m_callback.set(std::forward<T>(args)...);
45 	}
46 
configure_periodic(F && callback,const char * name,const attotime & period)47 	template <typename F> void configure_periodic(F &&callback, const char *name, const attotime &period)
48 	{
49 		m_type = TIMER_TYPE_PERIODIC;
50 		m_callback.set(std::forward<F>(callback), name);
51 		m_period = period;
52 	}
configure_periodic(T && target,F && callback,const char * name,const attotime & period)53 	template <typename T, typename F> void configure_periodic(T &&target, F &&callback, const char *name, const attotime &period)
54 	{
55 		m_type = TIMER_TYPE_PERIODIC;
56 		m_callback.set(std::forward<T>(target), std::forward<F>(callback), name);
57 		m_period = period;
58 	}
59 
configure_scanline(F && callback,const char * name,U && screen,int first_vpos,int increment)60 	template <typename F, typename U> void configure_scanline(F &&callback, const char *name, U &&screen, int first_vpos, int increment)
61 	{
62 		m_type = TIMER_TYPE_SCANLINE;
63 		m_callback.set(std::forward<F>(callback), name);
64 		m_screen.set_tag(std::forward<U>(screen));
65 		m_first_vpos = first_vpos;
66 		m_increment = increment;
67 	}
configure_scanline(T && target,F && callback,const char * name,U && screen,int first_vpos,int increment)68 	template <typename T, typename F, typename U> void configure_scanline(T &&target, F &&callback, const char *name, U &&screen, int first_vpos, int increment)
69 	{
70 		m_type = TIMER_TYPE_SCANLINE;
71 		m_callback.set(std::forward<T>(target), std::forward<F>(callback), name);
72 		m_screen.set_tag(std::forward<U>(screen));
73 		m_first_vpos = first_vpos;
74 		m_increment = increment;
75 	}
76 
set_callback(T &&...args)77 	template <typename... T> void set_callback(T &&... args) { m_callback.set(std::forward<T>(args)...); }
78 
set_start_delay(const attotime & delay)79 	void set_start_delay(const attotime &delay) { m_start_delay = delay; }
config_param(int param)80 	void config_param(int param) { m_param = param; }
81 
82 	// property getters
param()83 	int param() const { return m_timer->param(); }
ptr()84 	void *ptr() const { return m_ptr; }
enabled()85 	bool enabled() const { return m_timer->enabled(); }
86 
87 	// property setters
set_param(int param)88 	void set_param(int param) const { if(m_type != TIMER_TYPE_GENERIC) fatalerror("Cannot change parameter on a non-generic timer.\n"); m_timer->set_param(param); }
set_ptr(void * ptr)89 	void set_ptr(void *ptr) { m_ptr = ptr; }
90 	void enable(bool enable = true) const { m_timer->enable(enable); }
91 
92 	// adjustments
reset()93 	void reset() { adjust(attotime::never, 0, attotime::never); }
94 	void adjust(const attotime &duration, s32 param = 0, const attotime &period = attotime::never) const
95 	{
96 		if(m_type != TIMER_TYPE_GENERIC)
97 			fatalerror("Cannot adjust a non-generic timer.\n");
98 		m_timer->adjust(duration, param, period);
99 	}
100 
101 	// timing information
time_elapsed()102 	attotime time_elapsed() const { return m_timer->elapsed(); }
time_left()103 	attotime time_left() const { return m_timer->remaining(); }
start_time()104 	attotime start_time() const { return m_timer->start(); }
fire_time()105 	attotime fire_time() const { return m_timer->expire(); }
period()106 	attotime period() const { return m_timer ? m_timer->period() : m_period; }
107 
108 private:
109 	// device-level overrides
110 	virtual void device_validity_check(validity_checker &valid) const override;
111 	virtual void device_start() override;
112 	virtual void device_reset() override;
113 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
114 
115 	// timer types
116 	enum timer_type
117 	{
118 		TIMER_TYPE_PERIODIC,
119 		TIMER_TYPE_SCANLINE,
120 		TIMER_TYPE_GENERIC
121 	};
122 
123 	// configuration data
124 	timer_type              m_type;             // type of timer
125 	expired_delegate        m_callback;         // the timer's callback function
126 	void *                  m_ptr;              // the pointer parameter passed to the timer callback
127 
128 	// periodic timers only
129 	attotime                m_start_delay;      // delay before the timer fires for the first time
130 	attotime                m_period;           // period of repeated timer firings
131 	s32                     m_param;            // the integer parameter passed to the timer callback
132 
133 	// scanline timers only
134 	optional_device<screen_device> m_screen;    // pointer to the screen device
135 	u32                     m_first_vpos;       // the first vertical scanline position the timer fires on
136 	u32                     m_increment;        // the number of scanlines between firings
137 
138 	// internal state
139 	emu_timer *             m_timer;            // the backing timer
140 	bool                    m_first_time;       // indicates that the system is starting (scanline timers only)
141 };
142 
143 
144 
145 //**************************************************************************
146 //  GLOBAL VARIABLES
147 //**************************************************************************
148 
149 DECLARE_DEVICE_TYPE(TIMER, timer_device)
150 
151 
152 #endif // MAME_MACHINE_TIMER_H
153