// license:BSD-3-Clause // copyright-holders:Krzysztof Strzecha, Nathan Woods /*************************************************************************** machine/dai.c Functions to emulate general aspects of DAI (RAM, ROM, interrupts, I/O ports) Krzysztof Strzecha Nathan Woods ***************************************************************************/ #include "emu.h" #include "includes/dai.h" #define DEBUG_DAI_PORTS 0 #define LOG_DAI_PORT_R(_port, _data, _comment) do { if (DEBUG_DAI_PORTS) logerror ("DAI port read : %04x, Data: %02x (%s)\n", _port, _data, _comment); } while (0) #define LOG_DAI_PORT_W(_port, _data, _comment) do { if (DEBUG_DAI_PORTS) logerror ("DAI port write: %04x, Data: %02x (%s)\n", _port, _data, _comment); } while (0) void dai_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { switch (id) { case TIMER_BOOTSTRAP: m_maincpu->set_pc(0xc000); break; case TIMER_TMS5501: m_tms5501->xi7_w((ioport("IN8")->read() & 0x04) ? 1:0); timer_set(attotime::from_hz(100), TIMER_TMS5501); break; default: throw emu_fatalerror("Unknown id in dai_state::device_timer"); } } /* Discrete I/O devices */ /* Memory */ WRITE8_MEMBER(dai_state::dai_stack_interrupt_circuit_w) { m_tms5501->sens_w(1); m_tms5501->sens_w(0); } void dai_state::dai_update_memory(int dai_rom_bank) { membank("bank2")->set_entry(dai_rom_bank); } READ8_MEMBER(dai_state::dai_keyboard_r) { uint8_t data = 0x00; static const char *const keynames[] = { "IN0", "IN1", "IN2", "IN3", "IN4", "IN5", "IN6", "IN7" }; for (int i = 0; i < 8; i++) { if (m_keyboard_scan_mask & (1 << i)) data |= ioport(keynames[i])->read(); } return data; } WRITE8_MEMBER(dai_state::dai_keyboard_w) { m_keyboard_scan_mask = data; } IRQ_CALLBACK_MEMBER(dai_state::int_ack) { return m_tms5501->get_vector(); } void dai_state::machine_start() { membank("bank2")->configure_entries(0, 4, memregion("maincpu")->base() + 0x010000, 0x1000); timer_set(attotime::zero, TIMER_BOOTSTRAP); timer_set(attotime::from_hz(100), TIMER_TMS5501); memset(m_ram->pointer(), 0, m_ram->size()); } void dai_state::machine_reset() { membank("bank1")->set_base(m_ram->pointer()); } /*************************************************************************** Discrete Devices IO FD00 POR1: IN bit 0 - bit 1 - bit 2 PIPGE: Page signal bit 3 PIDTR: Serial output ready bit 4 PIBU1: Button on paddle 1 (1 = closed) bit 5 PIBU1: Button on paddle 2 (1 = closed) bit 6 PIRPI: Random data bit 7 PICAI: Cassette input data FD01 PDLST: IN Single pulse used to trigger paddle timer circuit FD04 POR1: OUT bit 0-3 Volume oscillator channel 0 bit 4-7 Volume oscillator channel 1 FD05 POR1: OUT bit 0-3 Volume oscillator channel 2 bit 4-7 Volume random noise generator FD06 POR0: OUT bit 0 POCAS: Cassette data output bit 1-2 PDLMSK: Paddle select bit 3 PDPNA: Paddle enable bit 4 POCM1: Cassette 1 motor control (0 = run) bit 5 POCM2: Cassette 2 motor control (0 = run) bit 6-7 ROM bank switching ***************************************************************************/ READ8_MEMBER(dai_state::dai_io_discrete_devices_r) { uint8_t data = 0x00; switch(offset & 0x000f) { case 0x00: data = ioport("IN8")->read(); data |= 0x08; // serial ready if (machine().rand()&0x01) data |= 0x40; // random number generator if (m_cassette->input() > 0.01) data |= 0x80; // tape input break; default: data = 0xff; LOG_DAI_PORT_R (offset, data, "discrete devices - unmapped"); break; } return data; } WRITE8_MEMBER(dai_state::dai_io_discrete_devices_w) { switch(offset & 0x000f) { case 0x04: m_sound->set_volume(space, offset, data); LOG_DAI_PORT_W (offset, data&0x0f, "discrete devices - osc. 0 volume"); LOG_DAI_PORT_W (offset, (data&0xf0)>>4, "discrete devices - osc. 1 volume"); break; case 0x05: m_sound->set_volume(space, offset, data); LOG_DAI_PORT_W (offset, data&0x0f, "discrete devices - osc. 2 volume"); LOG_DAI_PORT_W (offset, (data&0xf0)>>4, "discrete devices - noise volume"); break; case 0x06: m_paddle_select = (data&0x06)>>2; m_paddle_enable = (data&0x08)>>3; m_cassette_motor[0] = (data&0x10)>>4; m_cassette_motor[1] = (data&0x20)>>5; m_cassette->change_state(m_cassette_motor[0]?CASSETTE_MOTOR_DISABLED:CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR); m_cassette->output((data & 0x01) ? -1.0 : 1.0); dai_update_memory ((data&0xc0)>>6); LOG_DAI_PORT_W (offset, (data&0x06)>>2, "discrete devices - paddle select"); LOG_DAI_PORT_W (offset, (data&0x08)>>3, "discrete devices - paddle enable"); LOG_DAI_PORT_W (offset, (data&0x10)>>4, "discrete devices - cassette motor 1"); LOG_DAI_PORT_W (offset, (data&0x20)>>5, "discrete devices - cassette motor 2"); LOG_DAI_PORT_W (offset, (data&0xc0)>>6, "discrete devices - ROM bank"); break; default: LOG_DAI_PORT_W (offset, data, "discrete devices - unmapped"); break; } } /*************************************************************************** PIT8253 Offset need to be shifted by 1 to right, because the PIT is connected to A1 and A2 ***************************************************************************/ READ8_MEMBER(dai_state::dai_pit_r) { return m_pit->read((offset >> 1) & 3); } WRITE8_MEMBER(dai_state::dai_pit_w) { m_pit->write((offset >> 1) & 3, data); } /*************************************************************************** AMD 9911 mathematical coprocesor ***************************************************************************/ READ8_MEMBER(dai_state::dai_amd9511_r) { /* optional and no present at this moment */ return 0xff; } WRITE8_MEMBER(dai_state::dai_amd9511_w) { logerror ("Writing to AMD9511 math chip, %04x, %02x\n", offset, data); }