1 // license:BSD-3-Clause
2 // copyright-holders:Michael Zapf
3 /****************************************************************************
4
5 TMS9901 Programmable System Interface
6 See tms9901.c for documentation
7
8 Raphael Nabet
9 Michael Zapf
10
11 February 2012: Rewritten as class
12
13 *****************************************************************************/
14
15 #ifndef MAME_MACHINE_TMS9901_H
16 #define MAME_MACHINE_TMS9901_H
17
18
DECLARE_DEVICE_TYPE(TMS9901,tms9901_device)19 DECLARE_DEVICE_TYPE(TMS9901, tms9901_device)
20
21 /***************************************************************************
22 MACROS
23 ***************************************************************************/
24
25 /***************************************************************************
26 CLASS DEFINITION
27 ***************************************************************************/
28
29 class tms9901_device : public device_t
30 {
31 public:
32 // I/O pins
33 enum
34 {
35 INT1=1,
36 INT2,
37 INT3,
38 INT4,
39 INT5,
40 INT6,
41 INT7_P15,
42 INT8_P14,
43 INT9_P13,
44 INT10_P12,
45 INT11_P11,
46 INT12_P10,
47 INT13_P9,
48 INT14_P8,
49 INT15_P7,
50 P0,
51 P1,
52 P2,
53 P3,
54 P4,
55 P5,
56 P6
57 } pins;
58
59 tms9901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
60
61 void set_int_line(int pin_number, int state);
62
63 void rst1_line(int state);
64
65 // Synchronous clock input
66 void phi_line(int state);
67
68 uint8_t read(offs_t offset);
69 void write(offs_t offset, uint8_t data);
70
71 bool read_bit(int bit);
72 void write_bit(int bit, bool set);
73
74 auto p_out_cb(int n) { return m_write_p[n].bind(); }
75 auto read_cb() { return m_read_port.bind(); }
76 auto intreq_cb() { return m_interrupt.bind(); }
77
78 // Pins IC3...IC0
79 // When no interrupt is active, the IC lines are all set to 1
80 // The difference to /INT15 is that INTREQ is cleared.
81 int get_int_level() { return m_int_pending? m_int_level : 15; }
82
83 // Return PIO all outputs; ports configured as inputs return 1
84 // Used by si5500
85 uint16_t pio_outputs() const { return m_pio_output | ~m_pio_direction; }
86
87 void set_poll_int_lines(bool poll) { m_poll_lines = poll; }
88
89 private:
90 static constexpr device_timer_id DECREMENTER = 0;
91
92 virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
93 void soft_reset();
94
95 void device_start() override;
96 void device_stop() override;
97 void device_reset() override;
98
99 // Common method for device_reset and rst1_line
100 void do_reset();
101
102 // Common clock handling
103 void timer_clock_in(line_state clk);
104
105 // Direction and value of P pins
106 bool is_output(int p);
107 bool output_value(int p);
108 void set_and_latch_output(int p, bool val);
109 void set_bit(uint16_t& bitfield, int pos, bool val);
110
111 int m_int_level;
112 int m_last_level;
113
114 // State of the INT1-INT15 lines (must be inverted when queried)
115 // Note that the levels must also be delivered when reading the pins, which
116 // may require to latch the int levels on the caller's side.
117 uint16_t m_int_line;
118 uint16_t m_int_mask;
119 bool m_int_pending;
120 bool m_poll_lines;
121
122 // Find the interrupt with the lowest level (most important)
123 void prioritize_interrupts();
124
125 // Outgoing INTREQ* line
126 void signal_int();
127
128 // Sample the interrupt inputs.
129 void sample_interrupt_inputs();
130
131 // P15..P0; 1=output H, 0=output L
132 uint16_t m_pio_output;
133
134 // For P15..P0; 1=output, 0=input
135 // Once set to 1, a reset is necessary to return the pin to input
136 uint16_t m_pio_direction;
137
138 // =======================================================================
139
140 // TMS9901 clock mode
141 // false = interrupt mode (read interrupt state, write interrupt enable mask)
142 // true = clock mode (read/write clock interval)
143 bool m_clock_mode;
144
145 // Clock divider
146 int m_clockdiv;
147
148 // Clock has reached 0
149 bool m_timer_int_pending;
150
151 // Timer, used to emulate the decrementer register
152 emu_timer *m_decrementer;
153
154 // Clock interval, loaded in decrementer when it reaches 0.
155 uint16_t m_clock_register;
156
157 // Current decrementer value
158 uint16_t m_decrementer_value;
159
160 // when we go into timer mode, the decrementer is copied there to allow to read it reliably
161 uint16_t m_clock_read_register;
162
163 // =======================================================================
164
165 // Read callback.
166 devcb_read8 m_read_port;
167
168 // I/O lines, used for output. When used as inputs, the levels are delivered via the m_read_block
169 devcb_write_line::array<16> m_write_p;
170
171 // INTREQ pin
172 devcb_write_line m_interrupt;
173 };
174
175 #endif // MAME_MACHINE_TMS9901_H
176