summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/upd7810/upd7810.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/upd7810/upd7810.cpp')
-rw-r--r--src/devices/cpu/upd7810/upd7810.cpp177
1 files changed, 110 insertions, 67 deletions
diff --git a/src/devices/cpu/upd7810/upd7810.cpp b/src/devices/cpu/upd7810/upd7810.cpp
index 6fb869fc7f0..b96ac0a8e7b 100644
--- a/src/devices/cpu/upd7810/upd7810.cpp
+++ b/src/devices/cpu/upd7810/upd7810.cpp
@@ -376,6 +376,8 @@ STOP 01001000 10111011 12 stop
DEFINE_DEVICE_TYPE(UPD7810, upd7810_device, "upd7810", "NEC uPD7810")
DEFINE_DEVICE_TYPE(UPD78C10, upd78c10_device, "upd78c10", "NEC uPD78C10")
+DEFINE_DEVICE_TYPE(UPD7811, upd7811_device, "upd7811", "NEC uPD7811")
+DEFINE_DEVICE_TYPE(UPD78C11, upd78c11_device, "upd78c11", "NEC uPD78C11")
DEFINE_DEVICE_TYPE(UPD7807, upd7807_device, "upd7807", "NEC uPD7807")
DEFINE_DEVICE_TYPE(UPD7801, upd7801_device, "upd7801", "NEC uPD7801")
DEFINE_DEVICE_TYPE(UPD78C05, upd78c05_device, "upd78c05", "NEC uPD78C05")
@@ -389,7 +391,8 @@ void upd7810_device::upd_internal_128_ram_map(address_map &map)
void upd7810_device::upd_internal_256_ram_map(address_map &map)
{
- map(0xff00, 0xffff).ram();
+ map(0xff00, 0xffff).view(m_ram_view);
+ m_ram_view[0](0xff00, 0xffff).ram();
}
void upd7810_device::upd_internal_4096_rom_128_ram_map(address_map &map)
@@ -401,7 +404,8 @@ void upd7810_device::upd_internal_4096_rom_128_ram_map(address_map &map)
void upd7810_device::upd_internal_4096_rom_256_ram_map(address_map &map)
{
map(0x0000, 0x0fff).rom();
- map(0xff00, 0xffff).ram();
+ map(0xff00, 0xffff).view(m_ram_view);
+ m_ram_view[0](0xff00, 0xffff).ram();
}
upd7810_device::upd7810_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_map)
@@ -410,20 +414,21 @@ upd7810_device::upd7810_device(const machine_config &mconfig, device_type type,
, m_co0_func(*this)
, m_co1_func(*this)
, m_txd_func(*this)
- , m_rxd_func(*this)
- , m_an_func(*this)
- , m_pa_in_cb(*this)
- , m_pb_in_cb(*this)
- , m_pc_in_cb(*this)
- , m_pd_in_cb(*this)
- , m_pf_in_cb(*this)
+ , m_rxd_func(*this, 1)
+ , m_an_func(*this, 0)
+ , m_pa_in_cb(*this, 0xff)
+ , m_pb_in_cb(*this, 0xff)
+ , m_pc_in_cb(*this, 0xff)
+ , m_pd_in_cb(*this, 0xff)
+ , m_pf_in_cb(*this, 0xff)
, m_pa_out_cb(*this)
, m_pb_out_cb(*this)
, m_pc_out_cb(*this)
, m_pd_out_cb(*this)
, m_pf_out_cb(*this)
- , m_pt_in_cb(*this)
+ , m_pt_in_cb(*this, 0) // TODO: uPD7807 only
, m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0, internal_map)
+ , m_ram_view(*this, "ram_view")
, m_pa_pullups(0xff)
, m_pb_pullups(0xff)
, m_pc_pullups(0xff)
@@ -459,6 +464,16 @@ upd78c10_device::upd78c10_device(const machine_config &mconfig, const char *tag,
{
}
+upd7811_device::upd7811_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : upd7810_device(mconfig, UPD7811, tag, owner, clock, address_map_constructor(FUNC(upd7811_device::upd_internal_4096_rom_256_ram_map), this))
+{
+}
+
+upd78c11_device::upd78c11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : upd78c10_device(mconfig, UPD78C11, tag, owner, clock, address_map_constructor(FUNC(upd78c11_device::upd_internal_4096_rom_256_ram_map), this))
+{
+}
+
void upd7807_device::configure_ops()
{
m_opXX = s_opXX_7807;
@@ -585,23 +600,30 @@ void upd7810_device::pf_w(uint8_t data, uint8_t mem_mask)
COMBINE_DATA(&m_pf_in);
}
+void upd7810_device::sck_w(int state)
+{
+ if ((SMH & 0x03) == 0x03 && state != SCK)
+ update_sio(1);
+ SCK = state;
+}
+
uint8_t upd7810_device::RP(offs_t port)
{
uint8_t data = 0xff;
switch (port)
{
case UPD7810_PORTA:
- if (m_ma && !m_pa_in_cb.isnull()) // NS20031301 no need to read if the port is set as output
+ if (m_ma && !m_pa_in_cb.isunset()) // NS20031301 no need to read if the port is set as output
m_pa_in = m_pa_in_cb(0, m_ma);
data = (m_pa_in & m_ma) | (m_pa_out & ~m_ma);
break;
case UPD7810_PORTB:
- if (m_mb && !m_pb_in_cb.isnull()) // NS20031301 no need to read if the port is set as output
+ if (m_mb && !m_pb_in_cb.isunset()) // NS20031301 no need to read if the port is set as output
m_pb_in = m_pb_in_cb(0, m_mb);
data = (m_pb_in & m_mb) | (m_pb_out & ~m_mb);
break;
case UPD7810_PORTC:
- if (m_mc && !m_pc_in_cb.isnull()) // NS20031301 no need to read if the port is set as output
+ if (m_mc && !m_pc_in_cb.isunset()) // NS20031301 no need to read if the port is set as output
m_pc_in = m_pc_in_cb(0, m_mc);
data = (m_pc_in & m_mc) | (m_pc_out & ~m_mc);
if (m_mcc & 0x01) /* PC0 = TxD output */
@@ -622,7 +644,7 @@ uint8_t upd7810_device::RP(offs_t port)
data = (data & ~0x80) | (m_co1 & 1 ? 0x80 : 0x00);
break;
case UPD7810_PORTD:
- if (!m_pd_in_cb.isnull())
+ if (!m_pd_in_cb.isunset())
m_pd_in = m_pd_in_cb();
switch (m_mm & 0x07)
{
@@ -638,7 +660,7 @@ uint8_t upd7810_device::RP(offs_t port)
}
break;
case UPD7810_PORTF:
- if (m_mf && !m_pf_in_cb.isnull())
+ if (m_mf && !m_pf_in_cb.isunset())
m_pf_in = m_pf_in_cb(0, m_mf);
switch (m_mm & 0x06)
{
@@ -835,7 +857,7 @@ void upd7810_device::upd7810_take_irq()
{
/* acknowledge external IRQ */
if (irqline)
- standard_irq_callback(irqline);
+ standard_irq_callback(irqline, PC);
SP--;
WM( SP, PSW );
SP--;
@@ -896,7 +918,7 @@ void upd7801_device::upd7810_take_irq()
{
/* acknowledge external IRQ */
if (irqline)
- standard_irq_callback(irqline);
+ standard_irq_callback(irqline, PC);
SP--;
WM( SP, PSW );
SP--;
@@ -911,7 +933,9 @@ void upd7801_device::upd7810_take_irq()
void upd7810_device::upd7810_to_output_change(int state)
{
- TO = state & 1;
+ if ((SMH & 0x03) == 0x00 && state != TO)
+ update_sio(1);
+ TO = state;
m_to_func(TO);
if (m_mcc & 0x10)
@@ -1113,6 +1137,7 @@ void upd7810_device::upd7810_sio_input()
case 0x48: /* 7bits, no parity, 1 stop bit */
case 0x68: /* 7bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
m_rxs >>= 16 - 9;
+ m_rxs |= ~0U << 9;
RXB = (m_rxs >> 1) & 0x7f;
if ((1 << 8) != (m_rxs & (1 | (1 << 8))))
IRR |= INTER; /* framing error */
@@ -1120,12 +1145,14 @@ void upd7810_device::upd7810_sio_input()
case 0x4c: /* 8bits, no parity, 1 stop bit */
case 0x6c: /* 8bits, no parity, 1 stop bit (parity select = 1 but parity is off) */
m_rxs >>= 16 - 10;
+ m_rxs |= ~0U << 10;
RXB = (m_rxs >> 1) & 0xff;
if ((1 << 9) != (m_rxs & (1 | (1 << 9))))
IRR |= INTER; /* framing error */
break;
case 0x58: /* 7bits, odd parity, 1 stop bit */
m_rxs >>= 16 - 10;
+ m_rxs |= ~0U << 10;
RXB = (m_rxs >> 1) & 0x7f;
if ((1 << 9) != (m_rxs & (1 | (1 << 9))))
IRR |= INTER; /* framing error */
@@ -1134,6 +1161,7 @@ void upd7810_device::upd7810_sio_input()
break;
case 0x5c: /* 8bits, odd parity, 1 stop bit */
m_rxs >>= 16 - 11;
+ m_rxs |= ~0U << 11;
RXB = (m_rxs >> 1) & 0xff;
if ((1 << 10) != (m_rxs & (1 | (1 << 10))))
IRR |= INTER; /* framing error */
@@ -1142,6 +1170,7 @@ void upd7810_device::upd7810_sio_input()
break;
case 0x78: /* 7bits, even parity, 1 stop bit */
m_rxs >>= 16 - 10;
+ m_rxs |= ~0U << 10;
RXB = (m_rxs >> 1) & 0x7f;
if ((1 << 9) != (m_rxs & (1 | (1 << 9))))
IRR |= INTER; /* framing error */
@@ -1150,6 +1179,7 @@ void upd7810_device::upd7810_sio_input()
break;
case 0x7c: /* 8bits, even parity, 1 stop bit */
m_rxs >>= 16 - 11;
+ m_rxs |= ~0U << 11;
RXB = (m_rxs >> 1) & 0xff;
if ((1 << 10) != (m_rxs & (1 | (1 << 10))))
IRR |= INTER; /* framing error */
@@ -1159,6 +1189,7 @@ void upd7810_device::upd7810_sio_input()
case 0xc8: /* 7bits, no parity, 2 stop bits */
case 0xe8: /* 7bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
m_rxs >>= 16 - 10;
+ m_rxs |= ~0U << 10;
RXB = (m_rxs >> 1) & 0x7f;
if ((3 << 9) != (m_rxs & (1 | (3 << 9))))
IRR |= INTER; /* framing error */
@@ -1168,6 +1199,7 @@ void upd7810_device::upd7810_sio_input()
case 0xcc: /* 8bits, no parity, 2 stop bits */
case 0xec: /* 8bits, no parity, 2 stop bits (parity select = 1 but parity is off) */
m_rxs >>= 16 - 11;
+ m_rxs |= ~0U << 11;
RXB = (m_rxs >> 1) & 0xff;
if ((3 << 10) != (m_rxs & (1 | (3 << 10))))
IRR |= INTER; /* framing error */
@@ -1176,6 +1208,7 @@ void upd7810_device::upd7810_sio_input()
break;
case 0xd8: /* 7bits, odd parity, 2 stop bits */
m_rxs >>= 16 - 11;
+ m_rxs |= ~0U << 11;
RXB = (m_rxs >> 1) & 0x7f;
if ((3 << 10) != (m_rxs & (1 | (3 << 10))))
IRR |= INTER; /* framing error */
@@ -1184,6 +1217,7 @@ void upd7810_device::upd7810_sio_input()
break;
case 0xdc: /* 8bits, odd parity, 2 stop bits */
m_rxs >>= 16 - 12;
+ m_rxs |= ~0U << 12;
RXB = (m_rxs >> 1) & 0xff;
if ((3 << 11) != (m_rxs & (1 | (3 << 11))))
IRR |= INTER; /* framing error */
@@ -1192,6 +1226,7 @@ void upd7810_device::upd7810_sio_input()
break;
case 0xf8: /* 7bits, even parity, 2 stop bits */
m_rxs >>= 16 - 11;
+ m_rxs |= ~0U << 11;
RXB = (m_rxs >> 1) & 0x7f;
if ((3 << 10) != (m_rxs & (1 | (3 << 10))))
IRR |= INTER; /* framing error */
@@ -1200,6 +1235,7 @@ void upd7810_device::upd7810_sio_input()
break;
case 0xfc: /* 8bits, even parity, 2 stop bits */
m_rxs >>= 16 - 12;
+ m_rxs |= ~0U << 12;
RXB = (m_rxs >> 1) & 0xff;
if ((3 << 11) != (m_rxs & (1 | (3 << 11))))
IRR |= INTER; /* framing error */
@@ -1211,6 +1247,7 @@ void upd7810_device::upd7810_sio_input()
else
{
m_rxs >>= 16 - 8;
+ m_rxs |= ~0U << 8;
RXB = m_rxs;
// m_rxcnt = 8;
}
@@ -1270,6 +1307,8 @@ void upd7810_device::upd7810_sio_input()
m_rxcnt = 12;
break;
}
+
+ m_rxcnt--; // reduce by one since we already received the start bit at this point
}
else
/* TSK bit set ? */
@@ -1335,6 +1374,25 @@ void upd7810_device::upd7810_handle_timer1(int cycles, int clkdiv)
}
}
+void upd7810_device::update_sio(int cycles)
+{
+ const int divider[] = { 2, 384 / 3, 24 / 3, 2 };
+ const int prescale[] = { 1, 1, 16, 64 };
+ const int interval = divider[SMH & 0x03] * prescale[SML & 0x03];
+
+ OVCS += cycles;
+
+ while (OVCS >= interval / 2)
+ {
+ OVCS -= (interval / 2);
+
+ if (0 == (EDGES ^= 1))
+ upd7810_sio_input(); // rising edge
+ else
+ upd7810_sio_output(); // falling edge
+ }
+}
+
void upd7810_device::handle_timers(int cycles)
{
/**** TIMER 0 ****/
@@ -1443,32 +1501,10 @@ void upd7810_device::handle_timers(int cycles)
}
/**** SIO ****/
- switch (SMH & 0x03)
+ // we only handle "internal clock" serial mode here
+ if (((SMH & 0x03) == 0x01) || ((SMH & 0x03) == 0x02))
{
- case 0x00: /* interval timer F/F */
- break;
- case 0x01: /* internal clock divided by 384 */
- OVCS += cycles;
- while (OVCS >= 384/3)
- {
- OVCS -= 384/3;
- if (0 == (EDGES ^= 1))
- upd7810_sio_input();
- else
- upd7810_sio_output();
- }
- break;
- case 0x02: /* internal clock divided by 24 */
- OVCS += cycles;
- while (OVCS >= 24/3)
- {
- OVCS -= 24/3;
- if (0 == (EDGES ^= 1))
- upd7810_sio_input();
- else
- upd7810_sio_output();
- }
- break;
+ update_sio(cycles);
}
/**** ADC ****/
@@ -1579,27 +1615,6 @@ void upd7810_device::base_device_start()
space(AS_PROGRAM).specific(m_program);
space(AS_PROGRAM).cache(m_opcodes);
- m_to_func.resolve_safe();
- m_co0_func.resolve_safe();
- m_co1_func.resolve_safe();
- m_txd_func.resolve_safe();
- m_rxd_func.resolve_safe(1);
- m_an_func.resolve_all_safe(0);
-
- m_pa_in_cb.resolve();
- m_pb_in_cb.resolve();
- m_pc_in_cb.resolve();
- m_pd_in_cb.resolve();
- m_pf_in_cb.resolve();
-
- m_pa_out_cb.resolve_safe();
- m_pb_out_cb.resolve_safe();
- m_pc_out_cb.resolve_safe();
- m_pd_out_cb.resolve_safe();
- m_pf_out_cb.resolve_safe();
-
- m_pt_in_cb.resolve_safe(0); // TODO: uPD7807 only
-
configure_ops();
save_item(NAME(m_ppc.w.l));
@@ -1696,6 +1711,9 @@ void upd7810_device::device_start()
{
base_device_start();
+ MM = 8;
+ m_ram_view.select(0);
+
state_add( UPD7810_PC, "PC", m_pc.w.l).formatstr("%04X");
state_add( UPD7810_SP, "SP", m_sp.w.l).formatstr("%04X");
state_add( UPD7810_PSW, "PSW", m_psw).formatstr("%02X");
@@ -1756,6 +1774,31 @@ void upd7810_device::device_start()
state_add( STATE_GENFLAGS, "GENFLAGS", m_psw ).formatstr("%17s").noshow();
}
+void upd7801_device::device_start()
+{
+ base_device_start();
+
+ state_add( UPD7810_PC, "PC", m_pc.w.l).formatstr("%04X");
+ state_add( UPD7810_SP, "SP", m_sp.w.l).formatstr("%04X");
+ state_add( UPD7810_PSW, "PSW", m_psw).formatstr("%02X");
+ state_add( UPD7810_A, "A", m_va.b.l).formatstr("%02X");
+ state_add( UPD7810_V, "V", m_va.b.h).formatstr("%02X");
+ state_add( UPD7810_EA, "EA", m_ea.w.l).formatstr("%04X");
+ state_add( UPD7810_BC, "BC", m_bc.w.l).formatstr("%04X");
+ state_add( UPD7810_DE, "DE", m_de.w.l).formatstr("%04X");
+ state_add( UPD7810_HL, "HL", m_hl.w.l).formatstr("%04X");
+ state_add( UPD7810_CNT0, "CNT0", m_cnt.b.l).formatstr("%02X");
+ state_add( UPD7810_CNT1, "CNT1", m_cnt.b.h).formatstr("%02X");
+ state_add( UPD7810_TM0, "TM0", m_tm.b.l).formatstr("%02X");
+ state_add( UPD7810_TM1, "TM1", m_tm.b.h).formatstr("%02X");
+ state_add( UPD7810_MB, "MB", m_mb).formatstr("%02X");
+ state_add( UPD7810_MKL, "MKL", m_mkl).formatstr("%02X");
+
+ state_add( STATE_GENPC, "GENPC", m_pc.w.l ).formatstr("%04X").noshow();
+ state_add( STATE_GENPCBASE, "CURPC", m_ppc.w.l ).formatstr("%04X").noshow();
+ state_add( STATE_GENFLAGS, "GENFLAGS", m_psw ).formatstr("%17s").noshow();
+}
+
void upd78c05_device::device_start()
{
base_device_start();
@@ -1828,9 +1871,9 @@ void upd7810_device::device_reset()
m_etm.d = 0;
MA = 0xff;
MB = 0xff;
- m_mcc = 0;
+ MCC = 0;
MC = 0xff;
- m_mm = 0;
+ MM &= 8;
MF = 0xff;
m_mt = 0;
TMM = 0xff;
@@ -1876,7 +1919,7 @@ void upd7810_device::device_reset()
m_int2 = 1; // physical (inverted) INT2 line state
m_txs = 0;
- m_rxs = 0;
+ m_rxs = ~0;
m_txcnt = 0;
m_rxcnt = 0;
m_txbuf = 0;