mirror of
https://github.com/holub/mame
synced 2025-04-25 09:50:04 +03:00
m6801: add input ports ddr override mask
This commit is contained in:
parent
1f53ff94c6
commit
249a6a793f
@ -434,6 +434,8 @@ m6801_cpu_device::m6801_cpu_device(const machine_config &mconfig, device_type ty
|
||||
, m_nvram_battery(true)
|
||||
, m_sclk_divider(8)
|
||||
{
|
||||
std::fill(std::begin(m_port_ddr_override), std::end(m_port_ddr_override), 0);
|
||||
|
||||
// disable nvram by default (set to true if MCU is battery-backed when in standby mode)
|
||||
nvram_enable_backup(false);
|
||||
}
|
||||
@ -498,6 +500,8 @@ hd6301x_cpu_device::hd6301x_cpu_device(const machine_config &mconfig, device_typ
|
||||
, m_in_portx_func(*this, 0xff)
|
||||
, m_out_portx_func(*this)
|
||||
{
|
||||
std::fill(std::begin(m_portx_ddr_override), std::end(m_portx_ddr_override), 0);
|
||||
|
||||
m_sclk_divider = 16;
|
||||
}
|
||||
|
||||
@ -1221,7 +1225,8 @@ void m6801_cpu_device::execute_set_input(int irqline, int state)
|
||||
if (!m_port3_latched && (m_p3csr & M6801_P3CSR_LE))
|
||||
{
|
||||
// latch input data to port 3
|
||||
m_port_data[2] = (m_in_port_func[2]() & (m_port_ddr[2] ^ 0xff)) | (m_port_data[2] & m_port_ddr[2]);
|
||||
u8 ddr = m_port_ddr[2] & ~m_port_ddr_override[2];
|
||||
m_port_data[2] = (m_in_port_func[2]() & ~ddr) | (m_port_data[2] & ddr);
|
||||
m_port3_latched = 1;
|
||||
LOGPORT("Latched Port 3 Data: %02x\n", m_port_data[2]);
|
||||
|
||||
@ -1322,6 +1327,7 @@ void m6801_cpu_device::device_start()
|
||||
save_item(NAME(m_nvram_battery));
|
||||
save_item(NAME(m_port_ddr));
|
||||
save_item(NAME(m_port_data));
|
||||
save_item(NAME(m_port_ddr_override));
|
||||
save_item(NAME(m_p3csr));
|
||||
save_item(NAME(m_tcsr));
|
||||
save_item(NAME(m_pending_tcsr));
|
||||
@ -1392,6 +1398,7 @@ void hd6301x_cpu_device::device_start()
|
||||
|
||||
save_item(NAME(m_portx_ddr));
|
||||
save_item(NAME(m_portx_data));
|
||||
save_item(NAME(m_portx_ddr_override));
|
||||
save_item(NAME(m_tcsr2));
|
||||
save_item(NAME(m_pending_tcsr2));
|
||||
save_item(NAME(m_output_compare[1].d));
|
||||
@ -1680,10 +1687,12 @@ void hd6301y_cpu_device::p1_ddr_1bit_w(u8 data)
|
||||
|
||||
u8 m6801_cpu_device::p1_data_r()
|
||||
{
|
||||
if (m_port_ddr[0] == 0xff)
|
||||
u8 ddr = m_port_ddr[0] & ~m_port_ddr_override[0];
|
||||
|
||||
if (ddr == 0xff)
|
||||
return m_port_data[0];
|
||||
else
|
||||
return (m_in_port_func[0]() & (m_port_ddr[0] ^ 0xff)) | (m_port_data[0] & m_port_ddr[0]);
|
||||
return (m_in_port_func[0]() & ~ddr) | (m_port_data[0] & ddr);
|
||||
}
|
||||
|
||||
void m6801_cpu_device::p1_data_w(u8 data)
|
||||
@ -1763,10 +1772,12 @@ void hd6301x_cpu_device::p2_ddr_2bit_w(u8 data)
|
||||
|
||||
u8 m6801_cpu_device::p2_data_r()
|
||||
{
|
||||
if (m_port_ddr[1] == 0xff)
|
||||
u8 ddr = m_port_ddr[1] & ~m_port_ddr_override[1];
|
||||
|
||||
if (ddr == 0xff)
|
||||
return m_port_data[1];
|
||||
else
|
||||
return (m_in_port_func[1]() & (m_port_ddr[1] ^ 0xff)) | (m_port_data[1] & m_port_ddr[1]);
|
||||
return (m_in_port_func[1]() & ~ddr) | (m_port_data[1] & ddr);
|
||||
}
|
||||
|
||||
void m6801_cpu_device::p2_data_w(u8 data)
|
||||
@ -1805,8 +1816,6 @@ void hd6301x_cpu_device::p3_ddr_1bit_w(u8 data)
|
||||
|
||||
u8 m6801_cpu_device::p3_data_r()
|
||||
{
|
||||
u8 data;
|
||||
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
if (m_pending_isf_clear)
|
||||
@ -1822,10 +1831,12 @@ u8 m6801_cpu_device::p3_data_r()
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_p3csr & M6801_P3CSR_LE) || (m_port_ddr[2] == 0xff))
|
||||
u8 data, ddr = m_port_ddr[2] & ~m_port_ddr_override[2];
|
||||
|
||||
if ((m_p3csr & M6801_P3CSR_LE) || (ddr == 0xff))
|
||||
data = m_port_data[2];
|
||||
else
|
||||
data = (m_in_port_func[2]() & (m_port_ddr[2] ^ 0xff)) | (m_port_data[2] & m_port_ddr[2]);
|
||||
data = (m_in_port_func[2]() & ~ddr) | (m_port_data[2] & ddr);
|
||||
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
@ -1836,6 +1847,7 @@ u8 m6801_cpu_device::p3_data_r()
|
||||
set_os3(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -1867,10 +1879,12 @@ void m6801_cpu_device::p3_data_w(u8 data)
|
||||
u8 hd6301x_cpu_device::p3_data_r()
|
||||
{
|
||||
// no handshaking protocol
|
||||
if (m_port_ddr[2] == 0xff)
|
||||
u8 ddr = m_port_ddr[2] & ~m_port_ddr_override[2];
|
||||
|
||||
if (ddr == 0xff)
|
||||
return m_port_data[2];
|
||||
else
|
||||
return (m_in_port_func[2]() & (m_port_ddr[2] ^ 0xff)) | (m_port_data[2] & m_port_ddr[2]);
|
||||
return (m_in_port_func[2]() & ~ddr) | (m_port_data[2] & ddr);
|
||||
}
|
||||
|
||||
void hd6301x_cpu_device::p3_data_w(u8 data)
|
||||
@ -1913,10 +1927,12 @@ void m6801_cpu_device::p4_ddr_w(u8 data)
|
||||
|
||||
u8 m6801_cpu_device::p4_data_r()
|
||||
{
|
||||
if (m_port_ddr[3] == 0xff)
|
||||
u8 ddr = m_port_ddr[3] & ~m_port_ddr_override[3];
|
||||
|
||||
if (ddr == 0xff)
|
||||
return m_port_data[3];
|
||||
else
|
||||
return (m_in_port_func[3]() & (m_port_ddr[3] ^ 0xff)) | (m_port_data[3] & m_port_ddr[3]);
|
||||
return (m_in_port_func[3]() & ~ddr) | (m_port_data[3] & ddr);
|
||||
}
|
||||
|
||||
void m6801_cpu_device::p4_data_w(u8 data)
|
||||
@ -1954,7 +1970,9 @@ u8 hd6301x_cpu_device::p5_data_r()
|
||||
|
||||
u8 hd6301y_cpu_device::p5_data_r()
|
||||
{
|
||||
if (m_portx_ddr[0] == 0xff)
|
||||
u8 ddr = m_portx_ddr[0] & ~m_portx_ddr_override[0];
|
||||
|
||||
if (ddr == 0xff)
|
||||
return m_portx_data[0];
|
||||
else
|
||||
{
|
||||
@ -1963,7 +1981,7 @@ u8 hd6301y_cpu_device::p5_data_r()
|
||||
if (m_irq_state[M6801_IS3_LINE])
|
||||
data |= 0x10;
|
||||
|
||||
return (data & (m_portx_ddr[0] ^ 0xff)) | (m_portx_data[0] & m_portx_ddr[0]);
|
||||
return (data & ~ddr) | (m_portx_data[0] & ddr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1989,10 +2007,12 @@ void hd6301x_cpu_device::p6_ddr_w(u8 data)
|
||||
|
||||
u8 hd6301x_cpu_device::p6_data_r()
|
||||
{
|
||||
if (m_portx_ddr[1] == 0xff)
|
||||
u8 ddr = m_portx_ddr[1] & ~m_portx_ddr_override[1];
|
||||
|
||||
if (ddr == 0xff)
|
||||
return m_portx_data[1];
|
||||
else
|
||||
return (m_in_portx_func[1]() & (m_portx_ddr[1] ^ 0xff)) | (m_portx_data[1] & m_portx_ddr[1]);
|
||||
return (m_in_portx_func[1]() & ~ddr) | (m_portx_data[1] & ddr);
|
||||
}
|
||||
|
||||
void hd6301x_cpu_device::p6_data_w(u8 data)
|
||||
|
@ -52,6 +52,12 @@ public:
|
||||
auto in_p4_cb() { return m_in_port_func[3].bind(); }
|
||||
auto out_p4_cb() { return m_out_port_func[3].bind(); }
|
||||
|
||||
// a connected device can pull the voltage enough to force pin(s) to input, overriding DDR
|
||||
void in_p1_override_mask(u8 mask) { m_port_ddr_override[0] = mask; }
|
||||
void in_p2_override_mask(u8 mask) { m_port_ddr_override[1] = mask; }
|
||||
void in_p3_override_mask(u8 mask) { m_port_ddr_override[2] = mask; }
|
||||
void in_p4_override_mask(u8 mask) { m_port_ddr_override[3] = mask; }
|
||||
|
||||
auto out_sc2_cb() { return m_out_sc2_func.bind(); }
|
||||
auto out_ser_tx_cb() { return m_out_sertx_func.bind(); }
|
||||
|
||||
@ -142,12 +148,13 @@ protected:
|
||||
int m_sclk_divider;
|
||||
|
||||
// internal registers
|
||||
u8 m_port_ddr[4];
|
||||
u8 m_port_data[4];
|
||||
u8 m_p3csr; // Port 3 Control/Status Register
|
||||
u8 m_tcsr; // Timer Control and Status Register
|
||||
u8 m_pending_tcsr; // pending IRQ flag for clear IRQflag process
|
||||
u8 m_ram_ctrl;
|
||||
u8 m_port_ddr[4];
|
||||
u8 m_port_data[4];
|
||||
u8 m_port_ddr_override[4];
|
||||
u8 m_p3csr; // Port 3 Control/Status Register
|
||||
u8 m_tcsr; // Timer Control and Status Register
|
||||
u8 m_pending_tcsr; // pending IRQ flag for clear IRQflag process
|
||||
u8 m_ram_ctrl;
|
||||
PAIR m_counter; // free running counter
|
||||
PAIR m_output_compare[3]; // output compare (MC6801U4 and HD6301X have more than one)
|
||||
u16 m_input_capture; // input capture
|
||||
@ -155,11 +162,11 @@ protected:
|
||||
int m_port3_latched;
|
||||
bool m_port2_written;
|
||||
|
||||
u8 m_trcsr, m_rmcr, m_rdr, m_tdr, m_rsr, m_tshr;
|
||||
u8 m_trcsr, m_rmcr, m_rdr, m_tdr, m_rsr, m_tshr;
|
||||
int m_rxbits, m_txbits, m_txstate, m_trcsr_read_tdre, m_trcsr_read_orfe, m_trcsr_read_rdrf, m_tx, m_ext_serclock;
|
||||
bool m_use_ext_serclock;
|
||||
|
||||
u8 m_latch09;
|
||||
u8 m_latch09;
|
||||
int m_is3_state;
|
||||
|
||||
PAIR m_timer_over;
|
||||
@ -339,6 +346,9 @@ public:
|
||||
auto out_p6_cb() { return m_out_portx_func[1].bind(); }
|
||||
auto out_p7_cb() { return m_out_portx_func[2].bind(); }
|
||||
|
||||
void in_p5_override_mask(u8 mask) { m_portx_ddr_override[0] = mask; }
|
||||
void in_p6_override_mask(u8 mask) { m_portx_ddr_override[1] = mask; }
|
||||
|
||||
protected:
|
||||
hd6301x_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal, int nvram_bytes);
|
||||
|
||||
@ -398,6 +408,7 @@ protected:
|
||||
|
||||
u8 m_portx_ddr[2];
|
||||
u8 m_portx_data[3];
|
||||
u8 m_portx_ddr_override[2];
|
||||
|
||||
u8 m_tcsr2;
|
||||
u8 m_pending_tcsr2;
|
||||
|
@ -1129,15 +1129,15 @@ void pic16c5x_device::state_string_export(const device_state_entry &entry, std::
|
||||
case STATE_GENFLAGS:
|
||||
str = string_format("%01x%c%c%c%c%c %c%c%c%03x",
|
||||
(m_STATUS & 0xe0) >> 5,
|
||||
m_STATUS & 0x10 ? '.':'O', // WDT Overflow
|
||||
m_STATUS & 0x08 ? 'P':'D', // Power/Down
|
||||
m_STATUS & 0x04 ? 'Z':'.', // Zero
|
||||
m_STATUS & 0x02 ? 'c':'b', // Nibble Carry/Borrow
|
||||
m_STATUS & 0x01 ? 'C':'B', // Carry/Borrow
|
||||
m_STATUS & 0x10 ? '.':'O', // WDT Overflow
|
||||
m_STATUS & 0x08 ? 'P':'D', // Power/Down
|
||||
m_STATUS & 0x04 ? 'Z':'.', // Zero
|
||||
m_STATUS & 0x02 ? 'c':'b', // Nibble Carry/Borrow
|
||||
m_STATUS & 0x01 ? 'C':'B', // Carry/Borrow
|
||||
|
||||
m_OPTION & 0x20 ? 'C':'T', // Counter/Timer
|
||||
m_OPTION & 0x10 ? 'N':'P', // Negative/Positive
|
||||
m_OPTION & 0x08 ? 'W':'T', // WatchDog/Timer
|
||||
m_OPTION & 0x20 ? 'C':'T', // Counter/Timer
|
||||
m_OPTION & 0x10 ? 'N':'P', // Negative/Positive
|
||||
m_OPTION & 0x08 ? 'W':'T', // WatchDog/Timer
|
||||
m_OPTION & 0x08 ? (1<<(m_OPTION&7)) : (2<<(m_OPTION&7)));
|
||||
break;
|
||||
}
|
||||
|
@ -15,18 +15,19 @@ Hardware notes:
|
||||
- piezo, 16+4 LEDs, 8*8 chessboard buttons
|
||||
|
||||
TODO:
|
||||
- It expects P63 input to be 0 even though that pin is set to output, otherwise
|
||||
the piezo is very slow. There's a workaround in p6_w. This is the 2nd time I
|
||||
saw a situation like this, perhaps external devices can override DDR?
|
||||
- is Novag Amigo the same ROM? MCU label is also "892A", but QFP, ROM serial M44
|
||||
|
||||
BTANB:
|
||||
- piezo sounds glitchy/fast (which is weird when compared against other Novag
|
||||
chesscomputers), verified with 2 videos
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "cpu/m6800/m6801.h"
|
||||
#include "machine/sensorboard.h"
|
||||
#include "sound/dac.h"
|
||||
#include "sound/spkrdev.h"
|
||||
#include "video/pwm.h"
|
||||
|
||||
#include "speaker.h"
|
||||
@ -66,7 +67,7 @@ private:
|
||||
required_device<sensorboard_device> m_board;
|
||||
required_device<pwm_display_device> m_led_pwm;
|
||||
required_device<pwm_display_device> m_lcd_pwm;
|
||||
required_device<dac_2bit_ones_complement_device> m_dac;
|
||||
required_device<speaker_sound_device> m_dac;
|
||||
required_ioport_array<2> m_inputs;
|
||||
output_finder<4, 16> m_out_lcd;
|
||||
output_finder<8> m_out_digit;
|
||||
@ -153,8 +154,7 @@ void mentor16_state::lcd_pwm_w(offs_t offset, u8 data)
|
||||
|
||||
void mentor16_state::update_lcd()
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
m_lcd_pwm->write_row(i, BIT(m_lcd_com, i + 4) ? ((m_lcd_com & 1) ? ~m_lcd_segs : m_lcd_segs) : 0);
|
||||
m_lcd_pwm->matrix(m_lcd_com >> 4, (m_lcd_com & 1) ? ~m_lcd_segs : m_lcd_segs);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
@ -214,14 +214,11 @@ u8 mentor16_state::p6_r()
|
||||
|
||||
void mentor16_state::p6_w(u8 data)
|
||||
{
|
||||
// P62,P63: speaker out
|
||||
m_dac->write(~data >> 2 & 3);
|
||||
// P62: speaker out (P63 too, but forced low)
|
||||
m_dac->level_w(BIT(~data, 2));
|
||||
|
||||
// P64-P66: led select
|
||||
m_led_pwm->write_my(~data >> 4 & 7);
|
||||
|
||||
// HACK: force DDR6 to be 0x74
|
||||
m_maincpu->space(AS_PROGRAM).write_byte(0x16, 0x74);
|
||||
}
|
||||
|
||||
|
||||
@ -274,6 +271,7 @@ void mentor16_state::mentor16(machine_config &config)
|
||||
m_maincpu->out_p4_cb().set(FUNC(mentor16_state::lcd_segs_w<1>));
|
||||
m_maincpu->in_p5_cb().set(FUNC(mentor16_state::p5_r));
|
||||
m_maincpu->in_p6_cb().set(FUNC(mentor16_state::p6_r));
|
||||
m_maincpu->in_p6_override_mask(0x08); // P23 forced low, slow piezo otherwise
|
||||
m_maincpu->out_p6_cb().set(FUNC(mentor16_state::p6_w));
|
||||
|
||||
SENSORBOARD(config, m_board).set_type(sensorboard_device::BUTTONS);
|
||||
@ -290,7 +288,7 @@ void mentor16_state::mentor16(machine_config &config)
|
||||
|
||||
// sound hardware
|
||||
SPEAKER(config, "speaker").front_center();
|
||||
DAC_2BIT_ONES_COMPLEMENT(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25);
|
||||
SPEAKER_SOUND(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.25);
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,8 +14,6 @@ NVRAM won't save properly.
|
||||
TODO:
|
||||
- dump/add other MCU revisions, SX8 for tmate/conquist is known to exist
|
||||
- verify if QFP SX5A has the same ROM contents as DIP SX5A
|
||||
- SX4A and SX5A read from port 2 bits 3 and 7 while DDR is 0xff, why does it work?
|
||||
I added a simple workaround for it in p2_w
|
||||
- what is t1850's official title? "1850 Deluxe Table Chess" is from the back of
|
||||
the computer. The manual can't make up its mind and says "1850 Chess Computer",
|
||||
"1850 Chess: 16 Level Program", or "1850 Sensory Chess Game". The box disagrees
|
||||
@ -125,7 +123,6 @@ protected:
|
||||
|
||||
template <int N> void leds1_w(u8 data);
|
||||
template <int N> void leds2_w(u8 data);
|
||||
void p2_w(u8 data);
|
||||
void p2l_w(u8 data);
|
||||
virtual void p3_w(u8 data);
|
||||
virtual u8 p5_r();
|
||||
@ -205,15 +202,6 @@ void turbo16k_state::leds2_w(u8 data)
|
||||
m_display->write_row(N + 3, ~data);
|
||||
}
|
||||
|
||||
void turbo16k_state::p2_w(u8 data)
|
||||
{
|
||||
// P24,P25: status leds
|
||||
leds2_w<0>(data);
|
||||
|
||||
// HACK: force DDR2 to be 0x77
|
||||
m_maincpu->space(AS_PROGRAM).write_byte(0x01, 0x77);
|
||||
}
|
||||
|
||||
void turbo16k_state::p3_w(u8 data)
|
||||
{
|
||||
// P30-P37: input mux
|
||||
@ -283,7 +271,8 @@ void turbo16k_state::lcd_enable(u8 enable)
|
||||
|
||||
void turbo16k_state::p2l_w(u8 data)
|
||||
{
|
||||
p2_w(data);
|
||||
// P24,P25: status leds
|
||||
leds2_w<0>(data);
|
||||
|
||||
// P20,P21: LCD clocks enabled
|
||||
lcd_enable(~data & 3);
|
||||
@ -425,7 +414,8 @@ void turbo16k_state::compan3(machine_config &config)
|
||||
m_maincpu->standby_cb().append([this](int state) { if (state) m_display->clear(); });
|
||||
m_maincpu->out_p1_cb().set(FUNC(turbo16k_state::leds1_w<0>));
|
||||
m_maincpu->in_p2_cb().set_ioport("FREQ");
|
||||
m_maincpu->out_p2_cb().set(FUNC(turbo16k_state::p2_w));
|
||||
m_maincpu->in_p2_override_mask(0x88); // SX4A and SX5A rely on this
|
||||
m_maincpu->out_p2_cb().set(FUNC(turbo16k_state::leds2_w<0>));
|
||||
m_maincpu->out_p3_cb().set(FUNC(turbo16k_state::p3_w));
|
||||
m_maincpu->out_p4_cb().set(FUNC(turbo16k_state::leds1_w<1>));
|
||||
m_maincpu->in_p5_cb().set(FUNC(turbo16k_state::p5_r));
|
||||
|
Loading…
Reference in New Issue
Block a user