pit8253: Counters are now subdevices

This commit is contained in:
AJR 2018-03-03 13:46:36 -05:00
parent 6d854de3e5
commit 6228bbe942
2 changed files with 533 additions and 578 deletions

File diff suppressed because it is too large Load Diff

View File

@ -35,46 +35,111 @@
***************************************************************************/
#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) \
downcast<pit8253_device &>(*device).set_clk1(_clk);
downcast<pit8253_device &>(*device).set_clk<1>(_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) \
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) \
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) \
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
{
friend class pit_counter_device;
public:
// construction/destruction
pit8253_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// configuration helpers
void set_clk0(double clk0) { m_clk0 = clk0; }
void set_clk1(double clk1) { m_clk1 = clk1; }
void set_clk2(double clk2) { m_clk2 = clk2; }
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)); }
template <unsigned N> void set_clk(double clk) { m_clk[N] = clk; }
template <unsigned N> void set_clk(const XTAL &xtal) { set_clk<N>(xtal.dvalue()); }
template <unsigned N, class Object> devcb_base &set_out_handler(Object &&cb) { return m_out_handler[N].set_callback(std::forward<Object>(cb)); }
DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write);
WRITE_LINE_MEMBER(write_gate0);
WRITE_LINE_MEMBER(write_gate1);
WRITE_LINE_MEMBER(write_gate2);
WRITE_LINE_MEMBER(write_gate0) { m_counter[0]->gate_w(state); }
WRITE_LINE_MEMBER(write_gate1) { m_counter[1]->gate_w(state); }
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
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
the state of the input CLKx signal.
*/
WRITE_LINE_MEMBER(write_clk0);
WRITE_LINE_MEMBER(write_clk1);
WRITE_LINE_MEMBER(write_clk2);
WRITE_LINE_MEMBER(write_clk0) { m_counter[0]->set_clock_signal(state); }
WRITE_LINE_MEMBER(write_clk1) { m_counter[1]->set_clock_signal(state); }
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:
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
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_resolve_objects() 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);
pit8253_timer *get_timer(int which);
enum
{
I8254,
I8253,
FE2010
};
double m_clk[3];
devcb_write_line m_out_handler[3];
private:
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;
required_device_array<pit_counter_device, 3> m_counter;
enum
{
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;
pit_type m_type;
};
DECLARE_DEVICE_TYPE(PIT8253, pit8253_device)