summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/tlcs870/tlcs870.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/tlcs870/tlcs870.cpp')
-rw-r--r--src/devices/cpu/tlcs870/tlcs870.cpp177
1 files changed, 174 insertions, 3 deletions
diff --git a/src/devices/cpu/tlcs870/tlcs870.cpp b/src/devices/cpu/tlcs870/tlcs870.cpp
index e893cf69e0b..db201179719 100644
--- a/src/devices/cpu/tlcs870/tlcs870.cpp
+++ b/src/devices/cpu/tlcs870/tlcs870.cpp
@@ -22,7 +22,6 @@ DEFINE_DEVICE_TYPE(TMP87PH40AN, tmp87ph40an_device, "tmp87ph40an", "Toshiba TMP8
void tlcs870_device::tmp87ph40an_mem(address_map &map)
{
-#if 0
map(0x0000, 0x0000).rw(FUNC(tlcs870_device::port0_r), FUNC(tlcs870_device::port0_w));
map(0x0001, 0x0001).rw(FUNC(tlcs870_device::port1_r), FUNC(tlcs870_device::port1_w));
map(0x0002, 0x0002).rw(FUNC(tlcs870_device::port2_r), FUNC(tlcs870_device::port2_w));
@@ -37,6 +36,7 @@ void tlcs870_device::tmp87ph40an_mem(address_map &map)
map(0x000b, 0x000b).w(FUNC(tlcs870_device::p1cr_w)); // Port 1 I/O control
map(0x000c, 0x000c).w(FUNC(tlcs870_device::p6cr_w)); // Port 6 I/O control
map(0x000d, 0x000d).w(FUNC(tlcs870_device::p7cr_w)); // Port 7 I/O control
+#if 0
map(0x000e, 0x000e).rw(FUNC(tlcs870_device::adccr_r), FUNC(tlcs870_device::adccr_w)); // A/D converter control
map(0x000f, 0x000f).r(FUNC(tlcs870_device::adcdr_r)); // A/D converter result
@@ -107,6 +107,8 @@ tlcs870_device::tlcs870_device(const machine_config &mconfig, device_type optype
, m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0, program_map)
, m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0)
, m_intram(*this, "intram")
+ , m_port_in_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
+ , m_port_out_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
{
}
@@ -129,6 +131,147 @@ bool tlcs870_device::stream_arg(std::ostream &stream, uint32_t pc, const char *p
return false;
}
+// NOT using templates here because there are subtle differences in the port behavior (the ports are multi-purpose) that still need implementing
+READ8_MEMBER(tlcs870_device::port0_r)
+{
+ // need to use P0CR (0x000a) to control direction
+
+ if (m_read_input_port)
+ return m_port_in_cb[0]();
+ else
+ return m_port_out_latch[0];
+}
+
+READ8_MEMBER(tlcs870_device::port1_r)
+{
+ // need to use P1CR (0x000b) to control direction
+
+ if (m_read_input_port)
+ return m_port_in_cb[1]();
+ else
+ return m_port_out_latch[1];
+}
+
+READ8_MEMBER(tlcs870_device::port2_r) // 3-bit port
+{
+ if (m_read_input_port)
+ return m_port_in_cb[2]() | 0xf8;
+ else
+ return m_port_out_latch[2];
+}
+
+READ8_MEMBER(tlcs870_device::port3_r)
+{
+ if (m_read_input_port)
+ return m_port_in_cb[3]();
+ else
+ return m_port_out_latch[3];
+}
+
+READ8_MEMBER(tlcs870_device::port4_r)
+{
+ if (m_read_input_port)
+ return m_port_in_cb[4]();
+ else
+ return m_port_out_latch[4];
+}
+
+READ8_MEMBER(tlcs870_device::port5_r) // 5-bit port
+{
+ if (m_read_input_port)
+ return m_port_in_cb[5]() | 0xe0;
+ else
+ return m_port_out_latch[5];
+}
+
+READ8_MEMBER(tlcs870_device::port6_r) // doubles up as analog?
+{
+ // need to use P6CR (0x000c) to control direction
+
+ if (m_read_input_port)
+ return m_port_in_cb[6]();
+ else
+ return m_port_out_latch[6];
+}
+
+READ8_MEMBER(tlcs870_device::port7_r)
+{
+ // need to use P7CR (0x000d) to control direction
+
+ if (m_read_input_port)
+ return m_port_in_cb[7]();
+ else
+ return m_port_out_latch[7];
+}
+
+WRITE8_MEMBER(tlcs870_device::port0_w)
+{
+ m_port_out_latch[0] = data;
+ m_port_out_cb[0](data);
+}
+
+WRITE8_MEMBER(tlcs870_device::port1_w)
+{
+ m_port_out_latch[1] = data;
+ m_port_out_cb[1](data);
+}
+
+WRITE8_MEMBER(tlcs870_device::port2_w)
+{
+ m_port_out_latch[2] = data;
+ m_port_out_cb[2](data);
+}
+
+WRITE8_MEMBER(tlcs870_device::port3_w)
+{
+ m_port_out_latch[3] = data;
+ m_port_out_cb[3](data);
+}
+
+WRITE8_MEMBER(tlcs870_device::port4_w)
+{
+ m_port_out_latch[4] = data;
+ m_port_out_cb[4](data);
+}
+
+WRITE8_MEMBER(tlcs870_device::port5_w)
+{
+ m_port_out_latch[5] = data;
+ m_port_out_cb[5](data);
+}
+
+WRITE8_MEMBER(tlcs870_device::port6_w)
+{
+ m_port_out_latch[6] = data;
+ m_port_out_cb[6](data);
+}
+
+WRITE8_MEMBER(tlcs870_device::port7_w)
+{
+ m_port_out_latch[7] = data;
+ m_port_out_cb[7](data);
+}
+
+WRITE8_MEMBER(tlcs870_device::p0cr_w)
+{
+ m_port0_cr = data;
+}
+
+WRITE8_MEMBER(tlcs870_device::p1cr_w)
+{
+ m_port1_cr = data;
+}
+
+WRITE8_MEMBER(tlcs870_device::p6cr_w)
+{
+ m_port6_cr = data;
+}
+
+WRITE8_MEMBER(tlcs870_device::p7cr_w)
+{
+ m_port7_cr = data;
+}
+
void tlcs870_device::execute_set_input(int inputnum, int state)
{
#if 0
@@ -151,7 +294,7 @@ void tlcs870_device::execute_set_input(int inputnum, int state)
void tlcs870_device::execute_run()
{
- m_cycles = 1;
+
while (m_icount > 0)
{
@@ -161,10 +304,19 @@ void tlcs870_device::execute_run()
//check_interrupts();
m_addr = m_pc.d;
m_tmppc = m_addr; // used for jumps etc.
+ m_cycles = 0;
+ m_read_input_port = 1; // some operations force the output latches to read from the memory mapped ports, not input ports
decode();
m_pc.d = m_addr;
- m_icount -= m_cycles * 4; // 1 machine cycle = 4 clock cycles?
+ if (m_cycles)
+ {
+ m_icount -= m_cycles * 4; // 1 machine cycle = 4 clock cycles?
+ }
+ else
+ {
+ fatalerror("m_cycles == 0 after PC %04x\n", m_tmppc);
+ }
};
}
@@ -172,6 +324,20 @@ void tlcs870_device::device_reset()
{
m_pc.d = RM16(0xfffe);
m_RBS = 0;
+
+ m_port_out_latch[0] = 0x00;
+ m_port_out_latch[1] = 0x00;
+ m_port_out_latch[2] = 0xff;
+ m_port_out_latch[3] = 0xff;
+ m_port_out_latch[4] = 0xff;
+ m_port_out_latch[5] = 0xff;
+ m_port_out_latch[6] = 0x00;
+ m_port_out_latch[7] = 0x00;
+
+ m_port0_cr = 0xff;
+ m_port1_cr = 0xff;
+ m_port6_cr = 0xff;
+ m_port7_cr = 0xff;
}
void tlcs870_device::state_import(const device_state_entry &entry)
@@ -315,6 +481,11 @@ void tlcs870_device::device_start()
state_add(STATE_GENFLAGS, "GENFLAGS", m_F).formatstr("%8s").noshow();
set_icountptr(m_icount);
+
+ for (auto &cb : m_port_in_cb)
+ cb.resolve_safe(0xff);
+ for (auto &cb : m_port_out_cb)
+ cb.resolve_safe();
}