Pia6821 improvements (#5254)

* 6821pia: fix method names in comments

* zwackery: Remove PIA port A z_mask setting.

This would only be relevant if the PIA was read while in output mode.
These are inputs, and only read in input mode, so z_mask is not relevant.

* thomson: move pia pullup resistors from z_mask to read handler.

* 6821pia: remove unused set_port_a_z_mask calls.

* dgn_beta: move pia pullup resistors from z_mask to read handler.

* mpu3: Don't invert the VFD power on reset line.

It doesn't go through an inverter. I believe this was done to work
around a bug in the PIA port A implementation.

* pia6821: remove m_port_a_z_mask variable.

* 6821pia: For port A reads, only use the DDR for reading pins unless.

Provide an override option when a device depends on slightly undefined
behavior of an external device driving the pins and changing the value
read.

One board seems to need this (coinmstr). I don't have the schematics,
but it seems it uses this to check its meter operation.
This commit is contained in:
Mike 2019-06-19 16:55:46 -07:00 committed by ajrhacker
parent 492a9e1b48
commit 2e0f4af6ee
14 changed files with 49 additions and 81 deletions

View File

@ -251,7 +251,7 @@ READ8_MEMBER(a2bus_mouse_device::mcu_port_a_r)
WRITE8_MEMBER(a2bus_mouse_device::mcu_port_a_w) WRITE8_MEMBER(a2bus_mouse_device::mcu_port_a_w)
{ {
m_pia->set_a_input(data, ~mem_mask); m_pia->set_a_input(data);
} }
READ8_MEMBER(a2bus_mouse_device::mcu_port_b_r) READ8_MEMBER(a2bus_mouse_device::mcu_port_b_r)

View File

@ -285,5 +285,5 @@ WRITE8_MEMBER(spectrum_opus_device::pia_out_b)
WRITE_LINE_MEMBER(spectrum_opus_device::busy_w) WRITE_LINE_MEMBER(spectrum_opus_device::busy_w)
{ {
m_pia->set_a_input(state << 6, 0xbf); m_pia->set_a_input(state << 6);
} }

View File

@ -136,7 +136,7 @@ void ss50_mpc_device::device_start()
WRITE_LINE_MEMBER(ss50_mpc_device::serial_input_w) WRITE_LINE_MEMBER(ss50_mpc_device::serial_input_w)
{ {
m_pia->set_a_input(state << 7, 0x7f); m_pia->set_a_input(state << 7);
m_loopback->in_w<0>(state); m_loopback->in_w<0>(state);
} }

View File

@ -52,7 +52,7 @@ pia6821_device::pia6821_device(const machine_config &mconfig, const char *tag, d
m_cb2_handler(*this), m_cb2_handler(*this),
m_irqa_handler(*this), m_irqa_handler(*this),
m_irqb_handler(*this), m_in_a(0), m_irqb_handler(*this), m_in_a(0),
m_in_ca1(0), m_in_ca2(0), m_out_a(0), m_out_ca2(0), m_port_a_z_mask(0), m_ddr_a(0), m_in_ca1(0), m_in_ca2(0), m_out_a(0), m_out_ca2(0), m_ddr_a(0),
m_ctl_a(0), m_irq_a1(0), m_irq_a2(0), m_ctl_a(0), m_irq_a1(0), m_irq_a2(0),
m_irq_a_state(0), m_in_b(0), m_irq_a_state(0), m_in_b(0),
m_in_cb1(0), m_in_cb2(0), m_out_b(0), m_out_cb2(0), m_last_out_cb2_z(0), m_ddr_b(0), m_in_cb1(0), m_in_cb2(0), m_out_b(0), m_out_cb2(0), m_last_out_cb2_z(0), m_ddr_b(0),
@ -90,7 +90,6 @@ void pia6821_device::device_start()
save_item(NAME(m_in_ca2)); save_item(NAME(m_in_ca2));
save_item(NAME(m_out_a)); save_item(NAME(m_out_a));
save_item(NAME(m_out_ca2)); save_item(NAME(m_out_ca2));
save_item(NAME(m_port_a_z_mask));
save_item(NAME(m_ddr_a)); save_item(NAME(m_ddr_a));
save_item(NAME(m_ctl_a)); save_item(NAME(m_ctl_a));
save_item(NAME(m_irq_a1)); save_item(NAME(m_irq_a1));
@ -137,7 +136,6 @@ void pia6821_device::device_reset()
m_in_ca2 = true; m_in_ca2 = true;
m_out_a = 0; m_out_a = 0;
m_out_ca2 = 0; m_out_ca2 = 0;
m_port_a_z_mask = 0;
m_ddr_a = 0; m_ddr_a = 0;
m_ctl_a = 0; m_ctl_a = 0;
m_irq_a1 = 0; m_irq_a1 = 0;
@ -226,8 +224,8 @@ uint8_t pia6821_device::get_in_a_value()
} }
else else
{ {
// mark all pins disconnected // assume pins are disconnected and simulate the internal pullups.
m_port_a_z_mask = 0xff; port_a_data = 0xff;
if (!m_logged_port_a_not_connected && (m_ddr_a != 0xff)) if (!m_logged_port_a_not_connected && (m_ddr_a != 0xff))
{ {
@ -237,12 +235,12 @@ uint8_t pia6821_device::get_in_a_value()
} }
} }
// - connected pins are always read // For port A, when the port is in output mode other devices can drive the
// - disconnected pins read the output buffer in output mode // pins too. If the device pulls the voltage on the lines enough,a read of
// - disconnected pins are HI in input mode // the output register will show the external device value on the driven pins.
ret = (~m_port_a_z_mask & port_a_data) | ret = (~m_ddr_a & port_a_data) // input pins
( m_port_a_z_mask & m_ddr_a & m_out_a) | | (m_ddr_a & m_out_a & ~m_a_input_overrides_output_mask) // normal output pins
( m_port_a_z_mask & ~m_ddr_a); | (m_ddr_a & port_a_data & m_a_input_overrides_output_mask); // overridden output pins
return ret; return ret;
} }
@ -888,14 +886,13 @@ void pia6821_device::write(offs_t offset, uint8_t data)
// set_a_input // set_a_input
//------------------------------------------------- //-------------------------------------------------
void pia6821_device::set_a_input(uint8_t data, uint8_t z_mask) void pia6821_device::set_a_input(uint8_t data)
{ {
assert_always(m_in_a_handler.isnull(), "pia6821_device::set_a_input() called when m_in_a_handler set"); assert_always(m_in_a_handler.isnull(), "pia6821_device::set_a_input() called when m_in_a_handler set");
LOG("Set PIA input port A = %02X\n", data); LOG("Set PIA input port A = %02X\n", data);
m_in_a = data; m_in_a = data;
m_port_a_z_mask = z_mask;
m_in_a_pushed = true; m_in_a_pushed = true;
} }
@ -906,7 +903,7 @@ void pia6821_device::set_a_input(uint8_t data, uint8_t z_mask)
void pia6821_device::write_porta(uint8_t data) void pia6821_device::write_porta(uint8_t data)
{ {
set_a_input(data, 0); set_a_input(data);
} }
@ -916,14 +913,11 @@ void pia6821_device::write_porta(uint8_t data)
void pia6821_device::write_porta_line(int line, bool state) void pia6821_device::write_porta_line(int line, bool state)
{ {
if (!m_in_a_pushed)
m_port_a_z_mask = 0xff;
uint8_t mask = 1 << line; uint8_t mask = 1 << line;
if (state) if (state)
set_a_input(m_in_a | mask, m_port_a_z_mask & ~mask); set_a_input(m_in_a | mask);
else else
set_a_input(m_in_a & ~mask, m_port_a_z_mask & ~mask); set_a_input(m_in_a & ~mask);
} }

View File

@ -5,13 +5,10 @@
Motorola 6821 PIA interface and emulation Motorola 6821 PIA interface and emulation
Notes: Notes:
* get_port_b_z_mask() gives the caller the bitmask that shows * port_b_z_mask() gives the caller the bitmask that shows
which bits are high-impedance when reading port B, and thus which bits are high-impedance when reading port B, and thus
neither 0 or 1. get_output_cb2_z() returns the same info neither 0 or 1. cb2_output_z() returns the same info
for the CB2 pin. for the CB2 pin.
* set_port_a_z_mask allows the input callback to indicate
which port A bits are disconnected. For these bits, the
read operation will return the output buffer's contents.
* The 'alt' interface functions are used when the A0 and A1 * The 'alt' interface functions are used when the A0 and A1
address bits are swapped. address bits are swapped.
* All 'int' data or return values are bool, and should be * All 'int' data or return values are bool, and should be
@ -61,13 +58,13 @@ public:
void write_alt(offs_t offset, uint8_t data) { write(((offset << 1) & 0x02) | ((offset >> 1) & 0x01), data); } void write_alt(offs_t offset, uint8_t data) { write(((offset << 1) & 0x02) | ((offset >> 1) & 0x01), data); }
uint8_t port_b_z_mask() const { return ~m_ddr_b; } // see first note in .c uint8_t port_b_z_mask() const { return ~m_ddr_b; } // see first note in .c
void set_port_a_z_mask(uint8_t data) { m_port_a_z_mask = data; }// see second note in .c
DECLARE_WRITE8_MEMBER( porta_w ) { write_porta(data); } DECLARE_WRITE8_MEMBER( porta_w ) { write_porta(data); }
void write_porta(uint8_t data); void write_porta(uint8_t data);
void write_porta_line(int line, bool state); void write_porta_line(int line, bool state);
void set_a_input(uint8_t data, uint8_t z_mask); void set_a_input(uint8_t data);
uint8_t a_output(); uint8_t a_output();
void set_port_a_input_overrides_output_mask(uint8_t mask) { m_a_input_overrides_output_mask = mask; }
DECLARE_WRITE_LINE_MEMBER( pa0_w ) { write_porta_line(0, state); } DECLARE_WRITE_LINE_MEMBER( pa0_w ) { write_porta_line(0, state); }
DECLARE_WRITE_LINE_MEMBER( pa1_w ) { write_porta_line(1, state); } DECLARE_WRITE_LINE_MEMBER( pa1_w ) { write_porta_line(1, state); }
@ -176,8 +173,8 @@ private:
uint8_t m_in_ca1; uint8_t m_in_ca1;
uint8_t m_in_ca2; uint8_t m_in_ca2;
uint8_t m_out_a; uint8_t m_out_a;
uint8_t m_a_input_overrides_output_mask;
uint8_t m_out_ca2; uint8_t m_out_ca2;
uint8_t m_port_a_z_mask;
uint8_t m_ddr_a; uint8_t m_ddr_a;
uint8_t m_ctl_a; uint8_t m_ctl_a;
uint8_t m_irq_a1; uint8_t m_irq_a1;

View File

@ -1254,7 +1254,6 @@ uint32_t coinmstr_state::screen_update_coinmstr(screen_device &screen, bitmap_rg
return 0; return 0;
} }
void coinmstr_state::coinmstr(machine_config &config) void coinmstr_state::coinmstr(machine_config &config)
{ {
Z80(config, m_maincpu, CPU_CLOCK); // 7 MHz. Z80(config, m_maincpu, CPU_CLOCK); // 7 MHz.
@ -1267,6 +1266,7 @@ void coinmstr_state::coinmstr(machine_config &config)
pia6821_device &pia1(PIA6821(config, "pia1", 0)); pia6821_device &pia1(PIA6821(config, "pia1", 0));
pia1.readpa_handler().set_ioport("PIA1.A"); pia1.readpa_handler().set_ioport("PIA1.A");
pia1.set_port_a_input_overrides_output_mask(0xff);
pia1.readpb_handler().set_ioport("PIA1.B"); pia1.readpb_handler().set_ioport("PIA1.B");
pia6821_device &pia2(PIA6821(config, "pia2", 0)); pia6821_device &pia2(PIA6821(config, "pia2", 0));

View File

@ -604,7 +604,7 @@ READ8_MEMBER(mpu3_state::pia_ic6_portb_r)
WRITE8_MEMBER(mpu3_state::pia_ic6_porta_w) WRITE8_MEMBER(mpu3_state::pia_ic6_porta_w)
{ {
LOG(("%s: IC6 PIA Port A Set to %2x (Alpha)\n", machine().describe_context(),data)); LOG(("%s: IC6 PIA Port A Set to %2x (Alpha)\n", machine().describe_context(),data));
m_vfd->por(!(data&0x08)); m_vfd->por((data & 0x08));
m_vfd->data((data & 0x20) >> 5); m_vfd->data((data & 0x20) >> 5);
m_vfd->sclk((data & 0x10) >>4); m_vfd->sclk((data & 0x10) >>4);
} }

View File

@ -441,10 +441,7 @@ WRITE_LINE_MEMBER(zwackery_state::pia0_irq_w)
READ8_MEMBER( zwackery_state::pia1_porta_r ) READ8_MEMBER( zwackery_state::pia1_porta_r )
{ {
uint8_t data = ioport("IN1")->read(); return ioport("IN1")->read();
m_pia1->set_port_a_z_mask(data);
return data;
} }
READ8_MEMBER( zwackery_state::pia1_portb_r ) READ8_MEMBER( zwackery_state::pia1_portb_r )
@ -457,10 +454,7 @@ READ8_MEMBER( zwackery_state::pia1_portb_r )
READ8_MEMBER( zwackery_state::pia2_porta_r ) READ8_MEMBER( zwackery_state::pia2_porta_r )
{ {
uint8_t data = ioport("IN3")->read(); return ioport("IN3")->read();
m_pia2->set_port_a_z_mask(data);
return data;
} }

View File

@ -159,7 +159,7 @@ protected:
ram_device &ram() { return *m_ram; } ram_device &ram() { return *m_ram; }
// miscellaneous // miscellaneous
virtual void update_keyboard_input(uint8_t value, uint8_t z); virtual void update_keyboard_input(uint8_t value);
virtual void cart_w(bool state); virtual void cart_w(bool state);
virtual void update_cart_base(uint8_t *cart_base) { }; virtual void update_cart_base(uint8_t *cart_base) { };

View File

@ -62,7 +62,7 @@ protected:
virtual bool irq_get_line(void) override; virtual bool irq_get_line(void) override;
// miscellaneous // miscellaneous
virtual void update_keyboard_input(uint8_t value, uint8_t z) override; virtual void update_keyboard_input(uint8_t value) override;
virtual void cart_w(bool line) override; virtual void cart_w(bool line) override;
private: private:

View File

@ -874,10 +874,8 @@ void coco_state::poll_joystick(bool *joyin, uint8_t *buttons)
void coco_state::poll_keyboard(void) void coco_state::poll_keyboard(void)
{ {
uint8_t pia0_pb = pia_0().b_output(); uint8_t pia0_pb = pia_0().b_output();
uint8_t pia0_pb_z = pia_0().port_b_z_mask();
uint8_t pia0_pa = 0x7F; uint8_t pia0_pa = 0x7F;
uint8_t pia0_pa_z = 0x7F;
/* poll the keyboard, and update PA6-PA0 accordingly*/ /* poll the keyboard, and update PA6-PA0 accordingly*/
for (unsigned i = 0; i < m_keyboard.size(); i++) for (unsigned i = 0; i < m_keyboard.size(); i++)
@ -887,10 +885,6 @@ void coco_state::poll_keyboard(void)
{ {
pia0_pa &= ~(0x01 << i); pia0_pa &= ~(0x01 << i);
} }
if ((value | pia0_pb_z) != 0xFF)
{
pia0_pa_z &= ~(0x01 << i);
}
} }
/* hires joystick */ /* hires joystick */
@ -906,10 +900,9 @@ void coco_state::poll_keyboard(void)
/* mask out the buttons */ /* mask out the buttons */
pia0_pa &= ~buttons; pia0_pa &= ~buttons;
pia0_pa_z &= ~buttons;
/* and write the result to PIA0 */ /* and write the result to PIA0 */
update_keyboard_input(pia0_pa, pia0_pa_z); update_keyboard_input(pia0_pa);
} }
@ -919,9 +912,9 @@ void coco_state::poll_keyboard(void)
// on the CoCo 3 controls a GIME input // on the CoCo 3 controls a GIME input
//------------------------------------------------- //-------------------------------------------------
void coco_state::update_keyboard_input(uint8_t value, uint8_t z) void coco_state::update_keyboard_input(uint8_t value)
{ {
pia_0().set_a_input(value, z); pia_0().set_a_input(value);
} }

View File

@ -112,9 +112,9 @@ bool coco3_state::irq_get_line(void)
// update_keyboard_input // update_keyboard_input
//------------------------------------------------- //-------------------------------------------------
void coco3_state::update_keyboard_input(uint8_t value, uint8_t z) void coco3_state::update_keyboard_input(uint8_t value)
{ {
coco_state::update_keyboard_input(value, z); coco_state::update_keyboard_input(value);
m_gime->set_il1(value == 0xFF); m_gime->set_il1(value == 0xFF);
} }

View File

@ -438,7 +438,8 @@ int dgn_beta_state::GetKeyRow(dgn_beta_state *state, int RowNo)
*/ */
READ8_MEMBER(dgn_beta_state::d_pia0_pa_r) READ8_MEMBER(dgn_beta_state::d_pia0_pa_r)
{ {
return 0; // The hardware has pullup resistors on port A.
return 0xff;
} }
WRITE8_MEMBER(dgn_beta_state::d_pia0_pa_w) WRITE8_MEMBER(dgn_beta_state::d_pia0_pa_w)
@ -558,7 +559,8 @@ WRITE_LINE_MEMBER(dgn_beta_state::d_pia0_irq_b)
READ8_MEMBER(dgn_beta_state::d_pia1_pa_r) READ8_MEMBER(dgn_beta_state::d_pia1_pa_r)
{ {
return 0; // The hardware has pullup resistors on port A.
return 0xff;
} }
WRITE8_MEMBER(dgn_beta_state::d_pia1_pa_w) WRITE8_MEMBER(dgn_beta_state::d_pia1_pa_w)
@ -657,7 +659,8 @@ WRITE_LINE_MEMBER(dgn_beta_state::d_pia1_irq_b)
*/ */
READ8_MEMBER(dgn_beta_state::d_pia2_pa_r) READ8_MEMBER(dgn_beta_state::d_pia2_pa_r)
{ {
return 0; // The hardware has pullup resistors on port A.
return 0xff;
} }
WRITE8_MEMBER(dgn_beta_state::d_pia2_pa_w) WRITE8_MEMBER(dgn_beta_state::d_pia2_pa_w)
@ -902,11 +905,6 @@ void dgn_beta_state::machine_reset()
memset(m_PageRegs, 0, sizeof(m_PageRegs)); /* Reset page registers to 0 */ memset(m_PageRegs, 0, sizeof(m_PageRegs)); /* Reset page registers to 0 */
SetDefaultTask(); SetDefaultTask();
/* Set pullups on all PIA port A, to match what hardware does */
m_pia_0->set_port_a_z_mask(0xFF);
m_pia_1->set_port_a_z_mask(0xFF);
m_pia_2->set_port_a_z_mask(0xFF);
m_d_pia1_pa_last = 0x00; m_d_pia1_pa_last = 0x00;
m_d_pia1_pb_last = 0x00; m_d_pia1_pb_last = 0x00;
m_RowShifter = 0x00; /* shift register to select row */ m_RowShifter = 0x00; /* shift register to select row */

View File

@ -1308,9 +1308,9 @@ WRITE8_MEMBER( thomson_state::mo5_sys_porta_out )
READ8_MEMBER( thomson_state::mo5_sys_porta_in ) READ8_MEMBER( thomson_state::mo5_sys_porta_in )
{ {
return return
(mo5_get_cassette() ? 0x80 : 0) | /* bit 7: cassette input */ ((m_io_lightpen_button->read() & 1) ? 0x20 : 0) | /* bit 5: lightpen button */
((m_io_lightpen_button->read() & 1) ? 0x20 : 0) (mo5_get_cassette() ? 0x80 : 0) | /* bit 7: cassette input */
/* bit 5: lightpen button */; 0x5f; /* other bits are unconnected and pulled hi internally */
} }
@ -1564,7 +1564,6 @@ MACHINE_RESET_MEMBER( thomson_state, mo5 )
/* subsystems */ /* subsystems */
thom_irq_reset(); thom_irq_reset();
m_pia_sys->set_port_a_z_mask(0x5f );
to7_game_reset(); to7_game_reset();
to7_floppy_reset(); to7_floppy_reset();
to7_modem_reset(); to7_modem_reset();
@ -2445,16 +2444,14 @@ void thomson_state::to9_kbd_init()
/* ------------ system PIA 6821 ------------ */ /* ------------ system PIA 6821 ------------ */
/* afaik, P2-P7 are not connected, so, the warning about undefined 0xf0 can be safely ignored */
READ8_MEMBER( thomson_state::to9_sys_porta_in ) READ8_MEMBER( thomson_state::to9_sys_porta_in )
{ {
uint8_t ktest = to9_kbd_ktest(); uint8_t ktest = to9_kbd_ktest();
LOG_KBD(( "to9_sys_porta_in: ktest=%i\n", ktest )); LOG_KBD(( "to9_sys_porta_in: ktest=%i\n", ktest ));
return ktest; // PB1-7 are not connected, and are pulled hi internally
return ktest | 0xfe;
} }
@ -2507,7 +2504,6 @@ MACHINE_RESET_MEMBER( thomson_state, to9 )
/* subsystems */ /* subsystems */
thom_irq_reset(); thom_irq_reset();
m_pia_sys->set_port_a_z_mask( 0xfe );
to7_game_reset(); to7_game_reset();
to9_floppy_reset(); to9_floppy_reset();
to9_kbd_reset(); to9_kbd_reset();
@ -3412,14 +3408,14 @@ WRITE8_MEMBER( thomson_state::to8_vreg_w )
/* ------------ system PIA 6821 ------------ */ /* ------------ system PIA 6821 ------------ */
READ8_MEMBER( thomson_state::to8_sys_porta_in ) READ8_MEMBER( thomson_state::to8_sys_porta_in )
{ {
int ktest = to8_kbd_ktest(); int ktest = to8_kbd_ktest();
LOG_KBD(( "$%04x %f: to8_sys_porta_in ktest=%i\n", m_maincpu->pc(), machine().time().as_double(), ktest )); LOG_KBD(( "$%04x %f: to8_sys_porta_in ktest=%i\n", m_maincpu->pc(), machine().time().as_double(), ktest ));
return ktest; // PB1-7 are not connected, and are pulled hi internally
return ktest | 0xfe;
} }
@ -3504,7 +3500,6 @@ MACHINE_RESET_MEMBER( thomson_state, to8 )
/* subsystems */ /* subsystems */
thom_irq_reset(); thom_irq_reset();
m_pia_sys->set_port_a_z_mask( 0xfe );
to7_game_reset(); to7_game_reset();
to8_floppy_reset(); to8_floppy_reset();
to8_kbd_reset(); to8_kbd_reset();
@ -3655,7 +3650,6 @@ MACHINE_RESET_MEMBER( thomson_state, to9p )
/* subsystems */ /* subsystems */
thom_irq_reset(); thom_irq_reset();
m_pia_sys->set_port_a_z_mask( 0xfe );
to7_game_reset(); to7_game_reset();
to8_floppy_reset(); to8_floppy_reset();
to9_kbd_reset(); to9_kbd_reset();
@ -4116,10 +4110,10 @@ void thomson_state::mo6_game_reset()
READ8_MEMBER( thomson_state::mo6_sys_porta_in ) READ8_MEMBER( thomson_state::mo6_sys_porta_in )
{ {
return return
(mo5_get_cassette() ? 0x80 : 0) | /* bit 7: cassette input */ ((m_io_lightpen_button->read() & 1) ? 2 : 0) | /* bit 1: lightpen button */
8 | /* bit 3: kbd-line float up to 1 */ 8 | /* bit 3: kbd-line float up to 1 */
((m_io_lightpen_button->read() & 1) ? 2 : 0); (mo5_get_cassette() ? 0x80 : 0) | /* bit 7: cassette input */
/* bit 1: lightpen button */; 0x75; /* other bits are unconnected and pulled hi internally */
} }
@ -4345,7 +4339,6 @@ MACHINE_RESET_MEMBER( thomson_state, mo6 )
/* subsystems */ /* subsystems */
thom_irq_reset(); thom_irq_reset();
m_pia_sys->set_port_a_z_mask( 0x75 );
mo6_game_reset(); mo6_game_reset();
to7_floppy_reset(); to7_floppy_reset();
to7_modem_reset(); to7_modem_reset();
@ -4568,7 +4561,6 @@ MACHINE_RESET_MEMBER( thomson_state, mo5nr )
/* subsystems */ /* subsystems */
thom_irq_reset(); thom_irq_reset();
m_pia_sys->set_port_a_z_mask( 0x65 );
mo5nr_game_reset(); mo5nr_game_reset();
to7_floppy_reset(); to7_floppy_reset();
to7_modem_reset(); to7_modem_reset();