trunk/src/mess/drivers/votrpss.c
| r25404 | r25405 | |
| 53 | 53 | <kevtris> but that's everything you need |
| 54 | 54 | <LordNLptp> yeah |
| 55 | 55 | |
| 56 | | * (driver structure copied from vtech1.c) |
| 56 | |
| 57 | Things to be looked at: |
| 58 | - Serial doesn't work, so has been disabled. |
| 59 | - Bottom 3 dips must be off/serial/off, or else nothing works. |
| 60 | - No sound at all. |
| 61 | - volume and pitch should be controlled by ppi outputs |
| 62 | - pit to be hooked up |
| 63 | - bit 0 of portc is not connected according to text above, but it |
| 64 | completely changes the irq operation. |
| 65 | |
| 57 | 66 | ******************************************************************************/ |
| 58 | 67 | |
| 59 | 68 | /* Core includes */ |
| 60 | 69 | #include "emu.h" |
| 61 | 70 | #include "cpu/z80/z80.h" |
| 62 | | #include "votrpss.lh" |
| 71 | //#include "votrpss.lh" |
| 63 | 72 | |
| 64 | 73 | /* Components */ |
| 65 | | //#include "sound/ay8910.h" |
| 66 | | //#include "sound/votrax.h" |
| 67 | | //#include "machine/i8255.h" |
| 68 | | //#include "machine/pit8253.h" |
| 69 | | //#include "machine/i8251.h" |
| 74 | #include "sound/ay8910.h" |
| 75 | #include "sound/votrax.h" |
| 76 | #include "machine/i8255.h" |
| 77 | #include "machine/pit8253.h" |
| 78 | #include "machine/i8251.h" |
| 79 | #include "machine/serial.h" |
| 70 | 80 | |
| 71 | 81 | /* For testing */ |
| 72 | 82 | #include "machine/terminal.h" |
| r25404 | r25405 | |
| 76 | 86 | { |
| 77 | 87 | public: |
| 78 | 88 | votrpss_state(const machine_config &mconfig, device_type type, const char *tag) |
| 79 | | : driver_device(mconfig, type, tag), |
| 80 | | m_maincpu(*this, "maincpu"), |
| 81 | | m_terminal(*this, TERMINAL_TAG) |
| 89 | : driver_device(mconfig, type, tag) |
| 90 | , m_maincpu(*this, "maincpu") |
| 91 | , m_terminal(*this, TERMINAL_TAG) |
| 92 | , m_ppi(*this, "ppi") |
| 93 | , m_uart(*this, "uart") |
| 82 | 94 | { } |
| 83 | 95 | |
| 96 | DECLARE_WRITE8_MEMBER(kbd_put); |
| 97 | DECLARE_READ8_MEMBER(ppi_pa_r); |
| 98 | DECLARE_READ8_MEMBER(ppi_pb_r); |
| 99 | DECLARE_READ8_MEMBER(ppi_pc_r); |
| 100 | DECLARE_WRITE8_MEMBER(ppi_pa_w); |
| 101 | DECLARE_WRITE8_MEMBER(ppi_pb_w); |
| 102 | DECLARE_WRITE8_MEMBER(ppi_pc_w); |
| 103 | TIMER_DEVICE_CALLBACK_MEMBER(irq_timer); |
| 104 | TIMER_DEVICE_CALLBACK_MEMBER(serial_tick); |
| 105 | IRQ_CALLBACK_MEMBER(irq_ack); |
| 106 | private: |
| 107 | UINT8 m_term_data; |
| 108 | UINT8 m_porta; |
| 109 | UINT8 m_portb; |
| 110 | UINT8 m_portc; |
| 111 | virtual void machine_start(); |
| 84 | 112 | required_device<cpu_device> m_maincpu; |
| 85 | 113 | required_device<generic_terminal_device> m_terminal; |
| 86 | | DECLARE_READ8_MEMBER(votrpss_00_r); |
| 87 | | DECLARE_READ8_MEMBER(votrpss_02_r); |
| 88 | | DECLARE_READ8_MEMBER(votrpss_41_r); |
| 89 | | DECLARE_WRITE8_MEMBER( votrpss_kbd_put ); |
| 90 | | UINT8 m_term_data; |
| 91 | | UINT8 m_term_status; |
| 114 | required_device<i8255_device> m_ppi; |
| 115 | required_device<i8251_device> m_uart; |
| 92 | 116 | }; |
| 93 | 117 | |
| 94 | | READ8_MEMBER( votrpss_state::votrpss_02_r ) |
| 95 | | { |
| 96 | | return m_term_status; |
| 97 | | } |
| 98 | 118 | |
| 99 | | READ8_MEMBER( votrpss_state::votrpss_00_r ) |
| 100 | | { |
| 101 | | m_term_status = 0; |
| 102 | | return m_term_data; |
| 103 | | } |
| 104 | | |
| 105 | | READ8_MEMBER( votrpss_state::votrpss_41_r ) |
| 106 | | { |
| 107 | | return 1; |
| 108 | | } |
| 109 | | |
| 110 | | |
| 111 | 119 | /****************************************************************************** |
| 112 | 120 | Address Maps |
| 113 | 121 | ******************************************************************************/ |
| r25404 | r25405 | |
| 124 | 132 | |
| 125 | 133 | static ADDRESS_MAP_START(votrpss_io, AS_IO, 8, votrpss_state) |
| 126 | 134 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
| 127 | | AM_RANGE(0x00, 0x00) AM_READ(votrpss_00_r) |
| 128 | | AM_RANGE(0x01, 0x01) AM_DEVWRITE(TERMINAL_TAG, generic_terminal_device, write) |
| 129 | | AM_RANGE(0x02, 0x02) AM_READ(votrpss_02_r) |
| 130 | | AM_RANGE(0x41, 0x41) AM_READ(votrpss_41_r) |
| 131 | | //AM_RANGE(0x00, 0xff) AM_NOP /* temporary */ |
| 132 | | //AM_RANGE(0x00, 0x03) AM_READWRITE(8255ppi_r, 8255ppi_w) AM_MIRROR (0x3c) |
| 133 | | //AM_RANGE(0x40, 0x41) AM_READWRITE(i8251_r, i8251_w) AM_MIRROR (0x3e) |
| 134 | | //AM_RANGE(0x80, 0x83) AM_READWRITE(pit8253_r, pit8253_w) AM_MIRROR (0x3c) |
| 135 | | //AM_RANGE(0xc0, 0xc3) AM_DEVREADWRITE("ay1", ay8910_device, data_r, data_w) AM_MIRROR (0x3c) |
| 135 | AM_RANGE(0x00, 0x03) AM_MIRROR(0x3c) AM_DEVREADWRITE("ppi", i8255_device, read, write) |
| 136 | AM_RANGE(0x40, 0x40) AM_MIRROR(0x3e) AM_DEVREADWRITE("uart", i8251_device, data_r, data_w) |
| 137 | AM_RANGE(0x41, 0x41) AM_MIRROR(0x3e) AM_DEVREADWRITE("uart", i8251_device, status_r, control_w) |
| 138 | AM_RANGE(0x80, 0x83) AM_MIRROR(0x3c) AM_DEVREADWRITE("pit", pit8253_device, read, write) |
| 139 | AM_RANGE(0xc0, 0xc0) AM_MIRROR(0x3e) AM_DEVREADWRITE("ay", ay8910_device, data_r, address_w) |
| 140 | AM_RANGE(0xc1, 0xc1) AM_MIRROR(0x3e) AM_DEVREADWRITE("ay", ay8910_device, data_r, data_w) |
| 136 | 141 | ADDRESS_MAP_END |
| 137 | 142 | |
| 138 | 143 | |
| r25404 | r25405 | |
| 168 | 173 | PORT_DIPSETTING( 0x80, DEF_STR ( On ) ) |
| 169 | 174 | INPUT_PORTS_END |
| 170 | 175 | |
| 171 | | WRITE8_MEMBER( votrpss_state::votrpss_kbd_put ) |
| 176 | void votrpss_state::machine_start() |
| 172 | 177 | { |
| 178 | m_maincpu->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(votrpss_state::irq_ack),this)); |
| 179 | } |
| 180 | |
| 181 | TIMER_DEVICE_CALLBACK_MEMBER( votrpss_state::irq_timer ) |
| 182 | { |
| 183 | m_maincpu->set_input_line(0, ASSERT_LINE); |
| 184 | } |
| 185 | |
| 186 | IRQ_CALLBACK_MEMBER( votrpss_state::irq_ack ) |
| 187 | { |
| 188 | m_maincpu->set_input_line(0, CLEAR_LINE); |
| 189 | return 0x38; |
| 190 | } |
| 191 | |
| 192 | static const i8251_interface uart_intf = |
| 193 | { |
| 194 | //DEVCB_DEVICE_LINE_MEMBER("rs232", serial_port_device, rx), |
| 195 | //DEVCB_DEVICE_LINE_MEMBER("rs232", serial_port_device, tx), |
| 196 | //DEVCB_DEVICE_LINE_MEMBER("rs232", rs232_port_device, dsr_r), |
| 197 | //DEVCB_DEVICE_LINE_MEMBER("rs232", rs232_port_device, dtr_w), |
| 198 | //DEVCB_DEVICE_LINE_MEMBER("rs232", rs232_port_device, rts_w), |
| 199 | DEVCB_NULL, |
| 200 | DEVCB_NULL, |
| 201 | DEVCB_NULL, |
| 202 | DEVCB_NULL, |
| 203 | DEVCB_NULL, |
| 204 | DEVCB_NULL, |
| 205 | DEVCB_NULL, |
| 206 | DEVCB_NULL, |
| 207 | DEVCB_NULL |
| 208 | }; |
| 209 | |
| 210 | static const rs232_port_interface rs232_intf = |
| 211 | { |
| 212 | DEVCB_NULL, |
| 213 | DEVCB_NULL, |
| 214 | DEVCB_NULL, |
| 215 | DEVCB_NULL, |
| 216 | DEVCB_NULL |
| 217 | }; |
| 218 | |
| 219 | static const struct pit8253_interface pit_intf = |
| 220 | { |
| 221 | { |
| 222 | { |
| 223 | XTAL_8MHz, /* Timer 0: baud rate gen for 8251 */ |
| 224 | DEVCB_NULL, |
| 225 | DEVCB_NULL |
| 226 | }, { |
| 227 | XTAL_8MHz / 256, /* Timer 1: Pitch */ |
| 228 | DEVCB_NULL, |
| 229 | DEVCB_NULL |
| 230 | }, { |
| 231 | XTAL_8MHz / 4096, /* Timer 2: Volume */ |
| 232 | DEVCB_NULL, |
| 233 | DEVCB_NULL |
| 234 | } |
| 235 | } |
| 236 | }; |
| 237 | |
| 238 | READ8_MEMBER( votrpss_state::ppi_pa_r ) |
| 239 | { |
| 240 | UINT8 ret = m_term_data; |
| 241 | m_term_data = 0; |
| 242 | return ret; |
| 243 | } |
| 244 | |
| 245 | READ8_MEMBER( votrpss_state::ppi_pb_r ) |
| 246 | { |
| 247 | return m_portb; |
| 248 | } |
| 249 | |
| 250 | // Bit 0 controls what happens at interrupt time. See code around 518. |
| 251 | READ8_MEMBER( votrpss_state::ppi_pc_r ) |
| 252 | { |
| 253 | UINT8 data = 0; |
| 254 | |
| 255 | if (m_term_data) |
| 256 | { |
| 257 | m_ppi->pc4_w(0); // send a strobe pulse |
| 258 | data |= 0x20; |
| 259 | } |
| 260 | |
| 261 | return (m_portc & 0xdb) | data; |
| 262 | //return data; |
| 263 | } |
| 264 | |
| 265 | WRITE8_MEMBER( votrpss_state::ppi_pa_w ) |
| 266 | { |
| 267 | m_porta = data; |
| 268 | } |
| 269 | |
| 270 | WRITE8_MEMBER( votrpss_state::ppi_pb_w ) |
| 271 | { |
| 272 | m_portb = data; |
| 273 | m_terminal->write(space, offset, data&0x7f); |
| 274 | } |
| 275 | |
| 276 | WRITE8_MEMBER( votrpss_state::ppi_pc_w ) |
| 277 | { |
| 278 | m_portc = data; |
| 279 | } |
| 280 | |
| 281 | static I8255_INTERFACE( ppi_intf ) |
| 282 | { |
| 283 | DEVCB_DRIVER_MEMBER(votrpss_state, ppi_pa_r), // Port A read |
| 284 | DEVCB_DRIVER_MEMBER(votrpss_state, ppi_pa_w), // Port A write |
| 285 | DEVCB_DRIVER_MEMBER(votrpss_state, ppi_pb_r), // Port B read |
| 286 | DEVCB_DRIVER_MEMBER(votrpss_state, ppi_pb_w), // Port B write |
| 287 | DEVCB_DRIVER_MEMBER(votrpss_state, ppi_pc_r), // Port C read |
| 288 | DEVCB_DRIVER_MEMBER(votrpss_state, ppi_pc_w), // Port C write |
| 289 | }; |
| 290 | |
| 291 | static const ay8910_interface ay8910_intf = |
| 292 | { |
| 293 | AY8910_LEGACY_OUTPUT, // flags |
| 294 | AY8910_DEFAULT_LOADS, // channel load in ohms |
| 295 | DEVCB_NULL, // port A read |
| 296 | DEVCB_INPUT_PORT("DSW1"), // port B read |
| 297 | DEVCB_DEVICE_MEMBER("votrax", votrax_sc01_device, write), // port A write |
| 298 | DEVCB_NULL // port B write |
| 299 | }; |
| 300 | |
| 301 | static struct votrax_sc01_interface votrax_interface = |
| 302 | { |
| 303 | }; |
| 304 | |
| 305 | WRITE8_MEMBER( votrpss_state::kbd_put ) |
| 306 | { |
| 173 | 307 | m_term_data = data; |
| 174 | | m_term_status = 0x20; |
| 175 | 308 | } |
| 176 | 309 | |
| 177 | | static GENERIC_TERMINAL_INTERFACE( votrpss_terminal_intf ) |
| 310 | static GENERIC_TERMINAL_INTERFACE( terminal_intf ) |
| 178 | 311 | { |
| 179 | | DEVCB_DRIVER_MEMBER(votrpss_state, votrpss_kbd_put) |
| 312 | DEVCB_DRIVER_MEMBER(votrpss_state, kbd_put) |
| 180 | 313 | }; |
| 181 | 314 | |
| 315 | TIMER_DEVICE_CALLBACK_MEMBER( votrpss_state::serial_tick ) |
| 316 | { |
| 317 | m_uart->receive_clock(); |
| 318 | m_uart->transmit_clock(); |
| 319 | } |
| 320 | |
| 182 | 321 | /****************************************************************************** |
| 183 | 322 | Machine Drivers |
| 184 | 323 | ******************************************************************************/ |
| r25404 | r25405 | |
| 188 | 327 | MCFG_CPU_ADD("maincpu", Z80, XTAL_8MHz/2) /* 4.000 MHz, verified */ |
| 189 | 328 | MCFG_CPU_PROGRAM_MAP(votrpss_mem) |
| 190 | 329 | MCFG_CPU_IO_MAP(votrpss_io) |
| 191 | | //MCFG_QUANTUM_TIME(attotime::from_hz(60)) |
| 192 | 330 | |
| 193 | 331 | /* video hardware */ |
| 194 | 332 | //MCFG_DEFAULT_LAYOUT(layout_votrpss) |
| 195 | 333 | |
| 196 | 334 | /* sound hardware */ |
| 197 | | //MCFG_SPEAKER_STANDARD_MONO("mono") |
| 198 | | //MCFG_SOUND_ADD("ay1", AY8910, XTAL_8MHz/4) /* 2.000 MHz, verified */ |
| 199 | | //MCFG_SOUND_CONFIG(ay8910_config) |
| 200 | | //MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 201 | | //votrax goes here too |
| 335 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 336 | MCFG_SOUND_ADD("ay", AY8910, XTAL_8MHz/4) /* 2.000 MHz, verified */ |
| 337 | MCFG_SOUND_CONFIG(ay8910_intf) |
| 338 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 339 | MCFG_VOTRAX_SC01_ADD("votrax", 1700000, votrax_interface ) /* 1.70 MHz? needs verify */ |
| 340 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) |
| 202 | 341 | |
| 203 | | /* printer */ |
| 204 | | //MCFG_PRINTER_ADD("printer") |
| 342 | /* Devices */ |
| 343 | MCFG_GENERIC_TERMINAL_ADD(TERMINAL_TAG, terminal_intf) |
| 344 | MCFG_I8251_ADD("uart", uart_intf) |
| 345 | MCFG_PIT8253_ADD( "pit", pit_intf) |
| 346 | MCFG_I8255_ADD("ppi", ppi_intf) |
| 347 | MCFG_TIMER_DRIVER_ADD_PERIODIC("irq_timer", votrpss_state, irq_timer, attotime::from_msec(10)) |
| 205 | 348 | |
| 206 | | MCFG_GENERIC_TERMINAL_ADD(TERMINAL_TAG, votrpss_terminal_intf) |
| 349 | /* Serial components - comment out if not needed */ |
| 350 | //MCFG_TIMER_DRIVER_ADD_PERIODIC("serial", votrpss_state, serial_tick, attotime::from_hz(153600)) |
| 351 | //MCFG_RS232_PORT_ADD("rs232", rs232_intf, default_rs232_devices, "serial_terminal") |
| 207 | 352 | MACHINE_CONFIG_END |
| 208 | 353 | |
| 209 | 354 | |