// license:BSD-3-Clause // copyright-holders:Michael Zapf /**************************************************************************** TMS9901 Programmable System Interface See tms9901.c for documentation Raphael Nabet Michael Zapf February 2012: Rewritten as class *****************************************************************************/ #ifndef MAME_MACHINE_TMS9901_H #define MAME_MACHINE_TMS9901_H DECLARE_DEVICE_TYPE(TMS9901, tms9901_device) /*************************************************************************** MACROS ***************************************************************************/ /*************************************************************************** CLASS DEFINITION ***************************************************************************/ class tms9901_device : public device_t { public: // I/O pins enum { INT1=1, INT2, INT3, INT4, INT5, INT6, INT7_P15, INT8_P14, INT9_P13, INT10_P12, INT11_P11, INT12_P10, INT13_P9, INT14_P8, INT15_P7, P0, P1, P2, P3, P4, P5, P6 } pins; tms9901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); void set_int_line(int pin_number, int state); DECLARE_WRITE_LINE_MEMBER( rst1_line ); // Synchronous clock input DECLARE_WRITE_LINE_MEMBER( phi_line ); DECLARE_READ8_MEMBER( read ); DECLARE_WRITE8_MEMBER( write ); auto p_out_cb(int n) { return m_write_p[n].bind(); } auto read_cb() { return m_read_port.bind(); } auto intreq_cb() { return m_interrupt.bind(); } // Pins IC3...IC0 // When no interrupt is active, the IC lines are all set to 1 // The difference to /INT15 is that INTREQ is cleared. int get_int_level() { return m_int_pending? m_int_level : 15; } // Return PIO all outputs; ports configured as inputs return 1 // Used by si5500 uint16_t pio_outputs() const { return m_pio_output | ~m_pio_direction; } void set_poll_int_lines(bool poll) { m_poll_lines = poll; } private: static constexpr device_timer_id DECREMENTER = 0; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; void soft_reset(); void device_start() override; void device_stop() override; void device_reset() override; // Common method for device_reset and rst1_line void do_reset(); // Common clock handling void timer_clock_in(line_state clk); // Direction and value of P pins bool is_output(int p); bool output_value(int p); void set_and_latch_output(int p, bool val); void set_bit(uint16_t& bitfield, int pos, bool val); int m_int_level; int m_last_level; // State of the INT1-INT15 lines (must be inverted when queried) // Note that the levels must also be delivered when reading the pins, which // may require to latch the int levels on the caller's side. uint16_t m_int_line; uint16_t m_int_mask; bool m_int_pending; bool m_poll_lines; // Find the interrupt with the lowest level (most important) void prioritize_interrupts(); // Outgoing INTREQ* line void signal_int(); // Sample the interrupt inputs. void sample_interrupt_inputs(); // P15..P0; 1=output H, 0=output L uint16_t m_pio_output; // For P15..P0; 1=output, 0=input // Once set to 1, a reset is necessary to return the pin to input uint16_t m_pio_direction; // ======================================================================= // TMS9901 clock mode // false = interrupt mode (read interrupt state, write interrupt enable mask) // true = clock mode (read/write clock interval) bool m_clock_mode; // Clock divider int m_clockdiv; // Clock has reached 0 bool m_timer_int_pending; // Timer, used to emulate the decrementer register emu_timer *m_decrementer; // Clock interval, loaded in decrementer when it reaches 0. uint16_t m_clock_register; // Current decrementer value uint16_t m_decrementer_value; // when we go into timer mode, the decrementer is copied there to allow to read it reliably uint16_t m_clock_read_register; // ======================================================================= // Read callback. devcb_read8 m_read_port; // I/O lines, used for output. When used as inputs, the levels are delivered via the m_read_block devcb_write_line m_write_p[16]; // INTREQ pin devcb_write_line m_interrupt; }; #endif // MAME_MACHINE_TMS9901_H