mirror of
https://github.com/holub/mame
synced 2025-04-26 02:07:14 +03:00
pit8253: Counters are now subdevices
This commit is contained in:
parent
6d854de3e5
commit
6228bbe942
File diff suppressed because it is too large
Load Diff
@ -35,46 +35,111 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#define MCFG_PIT8253_CLK0(_clk) \
|
#define MCFG_PIT8253_CLK0(_clk) \
|
||||||
downcast<pit8253_device &>(*device).set_clk0(_clk);
|
downcast<pit8253_device &>(*device).set_clk<0>(_clk);
|
||||||
|
|
||||||
#define MCFG_PIT8253_CLK1(_clk) \
|
#define MCFG_PIT8253_CLK1(_clk) \
|
||||||
downcast<pit8253_device &>(*device).set_clk1(_clk);
|
downcast<pit8253_device &>(*device).set_clk<1>(_clk);
|
||||||
|
|
||||||
#define MCFG_PIT8253_CLK2(_clk) \
|
#define MCFG_PIT8253_CLK2(_clk) \
|
||||||
downcast<pit8253_device &>(*device).set_clk2(_clk);
|
downcast<pit8253_device &>(*device).set_clk<2>(_clk);
|
||||||
|
|
||||||
#define MCFG_PIT8253_OUT0_HANDLER(_devcb) \
|
#define MCFG_PIT8253_OUT0_HANDLER(_devcb) \
|
||||||
devcb = &downcast<pit8253_device &>(*device).set_out0_handler(DEVCB_##_devcb);
|
devcb = &downcast<pit8253_device &>(*device).set_out_handler<0>(DEVCB_##_devcb);
|
||||||
|
|
||||||
#define MCFG_PIT8253_OUT1_HANDLER(_devcb) \
|
#define MCFG_PIT8253_OUT1_HANDLER(_devcb) \
|
||||||
devcb = &downcast<pit8253_device &>(*device).set_out1_handler(DEVCB_##_devcb);
|
devcb = &downcast<pit8253_device &>(*device).set_out_handler<1>(DEVCB_##_devcb);
|
||||||
|
|
||||||
#define MCFG_PIT8253_OUT2_HANDLER(_devcb) \
|
#define MCFG_PIT8253_OUT2_HANDLER(_devcb) \
|
||||||
devcb = &downcast<pit8253_device &>(*device).set_out2_handler(DEVCB_##_devcb);
|
devcb = &downcast<pit8253_device &>(*device).set_out_handler<2>(DEVCB_##_devcb);
|
||||||
|
|
||||||
|
|
||||||
|
enum class pit_type
|
||||||
|
{
|
||||||
|
I8254,
|
||||||
|
I8253,
|
||||||
|
FE2010
|
||||||
|
};
|
||||||
|
|
||||||
|
class pit_counter_device : public device_t
|
||||||
|
{
|
||||||
|
friend class pit8253_device;
|
||||||
|
friend class pit8254_device;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// construction/destruction
|
||||||
|
pit_counter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// device-level overrides
|
||||||
|
virtual void device_start() override;
|
||||||
|
virtual void device_reset() override;
|
||||||
|
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline uint32_t adjusted_count() const;
|
||||||
|
void decrease_counter_value(int64_t cycles);
|
||||||
|
void load_counter_value();
|
||||||
|
void set_output(int output);
|
||||||
|
void simulate2(int64_t elapsed_cycles);
|
||||||
|
void simulate(int64_t elapsed_cycles);
|
||||||
|
void update();
|
||||||
|
uint16_t masked_value() const;
|
||||||
|
uint8_t read();
|
||||||
|
void load_count(uint16_t newcount);
|
||||||
|
void readback(int command);
|
||||||
|
void control_w(uint8_t data);
|
||||||
|
void count_w(uint8_t data);
|
||||||
|
void gate_w(int state);
|
||||||
|
void set_clock_signal(int state);
|
||||||
|
void set_clockin(double new_clockin);
|
||||||
|
|
||||||
|
// internal state
|
||||||
|
int m_index; // index number of the timer
|
||||||
|
double m_clockin; // input clock frequency in Hz
|
||||||
|
int m_clock_signal; // clock signal when clockin is 0
|
||||||
|
|
||||||
|
attotime m_last_updated; // time when last updated
|
||||||
|
|
||||||
|
emu_timer *m_updatetimer; // MAME timer to process updates
|
||||||
|
|
||||||
|
uint16_t m_value; // current counter value ("CE" in Intel docs)
|
||||||
|
uint16_t m_latch; // latched counter value ("OL" in Intel docs)
|
||||||
|
uint16_t m_count; // new counter value ("CR" in Intel docs)
|
||||||
|
uint8_t m_control; // 6-bit control byte
|
||||||
|
uint8_t m_status; // status byte - 8254 only
|
||||||
|
uint8_t m_lowcount; // LSB of new counter value for 16-bit writes
|
||||||
|
bool m_rmsb; // true = Next read is MSB of 16-bit value
|
||||||
|
bool m_wmsb; // true = Next write is MSB of 16-bit value
|
||||||
|
int m_output; // 0 = low, 1 = high
|
||||||
|
|
||||||
|
int m_gate; // gate input (0 = low, 1 = high)
|
||||||
|
int m_latched_count; // number of bytes of count latched
|
||||||
|
int m_latched_status; // 1 = status latched (8254 only)
|
||||||
|
int m_null_count; // 1 = mode control or count written, 0 = count loaded
|
||||||
|
int m_phase; // see phase definition tables in simulate2(), below
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_DEVICE_TYPE(PIT_COUNTER, pit_counter_device)
|
||||||
|
|
||||||
class pit8253_device : public device_t
|
class pit8253_device : public device_t
|
||||||
{
|
{
|
||||||
|
friend class pit_counter_device;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// construction/destruction
|
||||||
pit8253_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
pit8253_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||||
|
|
||||||
// configuration helpers
|
// configuration helpers
|
||||||
void set_clk0(double clk0) { m_clk0 = clk0; }
|
template <unsigned N> void set_clk(double clk) { m_clk[N] = clk; }
|
||||||
void set_clk1(double clk1) { m_clk1 = clk1; }
|
template <unsigned N> void set_clk(const XTAL &xtal) { set_clk<N>(xtal.dvalue()); }
|
||||||
void set_clk2(double clk2) { m_clk2 = clk2; }
|
template <unsigned N, class Object> devcb_base &set_out_handler(Object &&cb) { return m_out_handler[N].set_callback(std::forward<Object>(cb)); }
|
||||||
void set_clk0(const XTAL &xtal) { set_clk0(xtal.dvalue()); }
|
|
||||||
void set_clk1(const XTAL &xtal) { set_clk1(xtal.dvalue()); }
|
|
||||||
void set_clk2(const XTAL &xtal) { set_clk2(xtal.dvalue()); }
|
|
||||||
template <class Object> devcb_base &set_out0_handler(Object &&cb) { return m_out0_handler.set_callback(std::forward<Object>(cb)); }
|
|
||||||
template <class Object> devcb_base &set_out1_handler(Object &&cb) { return m_out1_handler.set_callback(std::forward<Object>(cb)); }
|
|
||||||
template <class Object> devcb_base &set_out2_handler(Object &&cb) { return m_out2_handler.set_callback(std::forward<Object>(cb)); }
|
|
||||||
|
|
||||||
DECLARE_READ8_MEMBER(read);
|
DECLARE_READ8_MEMBER(read);
|
||||||
DECLARE_WRITE8_MEMBER(write);
|
DECLARE_WRITE8_MEMBER(write);
|
||||||
|
|
||||||
WRITE_LINE_MEMBER(write_gate0);
|
WRITE_LINE_MEMBER(write_gate0) { m_counter[0]->gate_w(state); }
|
||||||
WRITE_LINE_MEMBER(write_gate1);
|
WRITE_LINE_MEMBER(write_gate1) { m_counter[1]->gate_w(state); }
|
||||||
WRITE_LINE_MEMBER(write_gate2);
|
WRITE_LINE_MEMBER(write_gate2) { m_counter[2]->gate_w(state); }
|
||||||
|
|
||||||
/* In the 8253/8254 the CLKx input lines can be attached to a regular clock
|
/* In the 8253/8254 the CLKx input lines can be attached to a regular clock
|
||||||
signal. Another option is to use the output from one timer as the input
|
signal. Another option is to use the output from one timer as the input
|
||||||
@ -86,87 +151,28 @@ public:
|
|||||||
to 0 with pit8253_set_clockin and call pit8253_clkX_w to change
|
to 0 with pit8253_set_clockin and call pit8253_clkX_w to change
|
||||||
the state of the input CLKx signal.
|
the state of the input CLKx signal.
|
||||||
*/
|
*/
|
||||||
WRITE_LINE_MEMBER(write_clk0);
|
WRITE_LINE_MEMBER(write_clk0) { m_counter[0]->set_clock_signal(state); }
|
||||||
WRITE_LINE_MEMBER(write_clk1);
|
WRITE_LINE_MEMBER(write_clk1) { m_counter[1]->set_clock_signal(state); }
|
||||||
WRITE_LINE_MEMBER(write_clk2);
|
WRITE_LINE_MEMBER(write_clk2) { m_counter[2]->set_clock_signal(state); }
|
||||||
|
|
||||||
void set_clockin(int timer, double new_clockin);
|
void set_clockin(int timer, double new_clockin) { m_counter[timer]->set_clockin(new_clockin); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
pit8253_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int chip_type);
|
pit8253_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, pit_type chip_type);
|
||||||
|
|
||||||
// device-level overrides
|
// device-level overrides
|
||||||
|
virtual void device_add_mconfig(machine_config &config) override;
|
||||||
|
virtual void device_resolve_objects() override;
|
||||||
virtual void device_start() override;
|
virtual void device_start() override;
|
||||||
virtual void device_reset() override;
|
|
||||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
|
||||||
|
|
||||||
// internal state
|
|
||||||
struct pit8253_timer
|
|
||||||
{
|
|
||||||
int index; /* index number of the timer */
|
|
||||||
double clockin; /* input clock frequency in Hz */
|
|
||||||
int clock; /* clock signal when clockin is 0 */
|
|
||||||
|
|
||||||
attotime last_updated; /* time when last updated */
|
|
||||||
|
|
||||||
emu_timer *updatetimer; /* MAME timer to process updates */
|
|
||||||
|
|
||||||
uint16_t value; /* current counter value ("CE" in Intel docs) */
|
|
||||||
uint16_t latch; /* latched counter value ("OL" in Intel docs) */
|
|
||||||
uint16_t count; /* new counter value ("CR" in Intel docs) */
|
|
||||||
uint8_t control; /* 6-bit control byte */
|
|
||||||
uint8_t status; /* status byte - 8254 only */
|
|
||||||
uint8_t lowcount; /* LSB of new counter value for 16-bit writes */
|
|
||||||
int rmsb; /* 1 = Next read is MSB of 16-bit value */
|
|
||||||
int wmsb; /* 1 = Next write is MSB of 16-bit value */
|
|
||||||
int output; /* 0 = low, 1 = high */
|
|
||||||
|
|
||||||
int gate; /* gate input (0 = low, 1 = high) */
|
|
||||||
int latched_count; /* number of bytes of count latched */
|
|
||||||
int latched_status; /* 1 = status latched (8254 only) */
|
|
||||||
int null_count; /* 1 = mode control or count written, 0 = count loaded */
|
|
||||||
int phase; /* see phase definition tables in simulate2(), below */
|
|
||||||
};
|
|
||||||
|
|
||||||
void readback(pit8253_timer *timer, int command);
|
|
||||||
virtual void readback_command(uint8_t data);
|
virtual void readback_command(uint8_t data);
|
||||||
pit8253_timer *get_timer(int which);
|
|
||||||
|
|
||||||
enum
|
double m_clk[3];
|
||||||
{
|
devcb_write_line m_out_handler[3];
|
||||||
I8254,
|
|
||||||
I8253,
|
|
||||||
FE2010
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
required_device_array<pit_counter_device, 3> m_counter;
|
||||||
double m_clk0;
|
|
||||||
double m_clk1;
|
|
||||||
double m_clk2;
|
|
||||||
devcb_write_line m_out0_handler;
|
|
||||||
devcb_write_line m_out1_handler;
|
|
||||||
devcb_write_line m_out2_handler;
|
|
||||||
|
|
||||||
enum
|
pit_type m_type;
|
||||||
{
|
|
||||||
PIT8253_MAX_TIMER = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
pit8253_timer m_timers[PIT8253_MAX_TIMER];
|
|
||||||
|
|
||||||
inline uint32_t adjusted_count(int bcd, uint16_t val);
|
|
||||||
void decrease_counter_value(pit8253_timer *timer, int64_t cycles);
|
|
||||||
void load_counter_value(pit8253_timer *timer);
|
|
||||||
void set_output(pit8253_timer *timer, int output);
|
|
||||||
void simulate2(pit8253_timer *timer, int64_t elapsed_cycles);
|
|
||||||
void simulate(pit8253_timer *timer, int64_t elapsed_cycles);
|
|
||||||
void update(pit8253_timer *timer);
|
|
||||||
uint16_t masked_value(pit8253_timer *timer);
|
|
||||||
void load_count(pit8253_timer *timer, uint16_t newcount);
|
|
||||||
void gate_w(int gate, int state);
|
|
||||||
void set_clock_signal(int timerno, int state);
|
|
||||||
|
|
||||||
int m_type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_DEVICE_TYPE(PIT8253, pit8253_device)
|
DECLARE_DEVICE_TYPE(PIT8253, pit8253_device)
|
||||||
|
Loading…
Reference in New Issue
Block a user