summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/hmcs400
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2024-11-06 00:00:04 +0100
committer hap <happppp@users.noreply.github.com>2024-11-06 00:00:17 +0100
commit9778738aa62ed559fd5cff016aa3d7734f004687 (patch)
tree72a16f9efbfae8e5e9140c075ad97958add103d4 /src/devices/cpu/hmcs400
parent397ec2cb40efd19e71f6133505d0c6c8b6e6cd0c (diff)
hmcs400: add hmcs412/414/424
Diffstat (limited to 'src/devices/cpu/hmcs400')
-rw-r--r--src/devices/cpu/hmcs400/hmcs400.cpp115
-rw-r--r--src/devices/cpu/hmcs400/hmcs400.h158
2 files changed, 229 insertions, 44 deletions
diff --git a/src/devices/cpu/hmcs400/hmcs400.cpp b/src/devices/cpu/hmcs400/hmcs400.cpp
index 45e99697a6a..114335cf3b5 100644
--- a/src/devices/cpu/hmcs400/hmcs400.cpp
+++ b/src/devices/cpu/hmcs400/hmcs400.cpp
@@ -14,8 +14,6 @@ removed (interrupt flags are via memory-mapped I/O).
TODO:
- add serial interface
-- current I/O ports are hardcoded for HMS402/4/8, which will need to be changed
- when other MCU types are added
- do the LAW/LWA opcodes not work on early revisions of HMCS400? the 1988 user
manual warns that the W register is write-only, and that there is no efficient
way to save this register when using interrupts
@@ -37,10 +35,11 @@ TODO:
// CL = low-power
// AC = high-speed
-// HMCS408, HMCS414, HMCS424 have a mask option for the system clock divider
+// HMCS408, HMCS41x, HMCS42x have a mask option for the system clock divider
+// HMCS41x don't have timer A or serial interface, HMCS41x and HMCS42x have less I/O pins
// rev 2 apparently added LAW/LWA opcodes?
-// HMCS402C/CL/AC, 64 pins DP-64S or FP-64, 2Kx10 ROM, 160x4 RAM
+// HMCS402C/CL/AC, DP-64S or FP-64, 2Kx10 ROM, 160x4 RAM
DEFINE_DEVICE_TYPE(HD614022, hd614022_device, "hd614022", "Hitachi HD614022") // C, rev 2
DEFINE_DEVICE_TYPE(HD614023, hd614023_device, "hd614023", "Hitachi HD614023") // C, rev 1
DEFINE_DEVICE_TYPE(HD614025, hd614025_device, "hd614025", "Hitachi HD614025") // CL, rev 2
@@ -48,7 +47,7 @@ DEFINE_DEVICE_TYPE(HD614026, hd614026_device, "hd614026", "Hitachi HD614026") //
DEFINE_DEVICE_TYPE(HD614028, hd614028_device, "hd614028", "Hitachi HD614028") // AC, rev 2
DEFINE_DEVICE_TYPE(HD614029, hd614029_device, "hd614029", "Hitachi HD614029") // AC, rev 1
-// HMCS404C/CL/AC, 64 pins DP-64S or FP-64, 4Kx10 ROM, 256x4 RAM
+// HMCS404C/CL/AC, DP-64S or FP-64, 4Kx10 ROM, 256x4 RAM
DEFINE_DEVICE_TYPE(HD614042, hd614042_device, "hd614042", "Hitachi HD614042") // C, rev 2
DEFINE_DEVICE_TYPE(HD614043, hd614043_device, "hd614043", "Hitachi HD614043") // C, rev 1
DEFINE_DEVICE_TYPE(HD614045, hd614045_device, "hd614045", "Hitachi HD614045") // CL, rev 2
@@ -56,7 +55,7 @@ DEFINE_DEVICE_TYPE(HD614046, hd614046_device, "hd614046", "Hitachi HD614046") //
DEFINE_DEVICE_TYPE(HD614048, hd614048_device, "hd614048", "Hitachi HD614048") // AC, rev 2
DEFINE_DEVICE_TYPE(HD614049, hd614049_device, "hd614049", "Hitachi HD614049") // AC, rev 1
-// HMCS408C/CL/AC, 64 pins DP-64S or FP-64, 8Kx10 ROM, 512x4 RAM
+// HMCS408C/CL/AC, DP-64S or FP-64, 8Kx10 ROM, 512x4 RAM
DEFINE_DEVICE_TYPE(HD614080, hd614080_device, "hd614080", "Hitachi HD614080") // C, rev 2
DEFINE_DEVICE_TYPE(HD614081, hd614081_device, "hd614081", "Hitachi HD614081") // C, rev 1
DEFINE_DEVICE_TYPE(HD614085, hd614085_device, "hd614085", "Hitachi HD614085") // CL, rev 2
@@ -64,6 +63,21 @@ DEFINE_DEVICE_TYPE(HD614086, hd614086_device, "hd614086", "Hitachi HD614086") //
DEFINE_DEVICE_TYPE(HD614088, hd614088_device, "hd614088", "Hitachi HD614088") // AC, rev 2
DEFINE_DEVICE_TYPE(HD614089, hd614089_device, "hd614089", "Hitachi HD614089") // AC, rev 1
+// HMCS412C/CL/AC, DP-42/DP-42S or FP-44A, 2Kx10 ROM, 160x4 RAM
+DEFINE_DEVICE_TYPE(HD614120, hd614120_device, "hd614120", "Hitachi HD614120") // C
+DEFINE_DEVICE_TYPE(HD614125, hd614125_device, "hd614125", "Hitachi HD614125") // CL
+DEFINE_DEVICE_TYPE(HD614128, hd614128_device, "hd614128", "Hitachi HD614128") // AC
+
+// HMCS414C/CL/AC, DP-42/DP-42S or FP-44A, 4Kx10 ROM, 160x4 RAM
+DEFINE_DEVICE_TYPE(HD614140, hd614140_device, "hd614140", "Hitachi HD614140") // C
+DEFINE_DEVICE_TYPE(HD614145, hd614145_device, "hd614145", "Hitachi HD614145") // CL
+DEFINE_DEVICE_TYPE(HD614148, hd614148_device, "hd614148", "Hitachi HD614148") // AC
+
+// HMCS424C/CL/AC, DP-42/DP-42S or FP-44A, 4Kx10 ROM, 256x4 RAM
+DEFINE_DEVICE_TYPE(HD404240, hd404240_device, "hd404240", "Hitachi HD404240") // C
+DEFINE_DEVICE_TYPE(HD40L4240, hd40l4240_device, "hd40l4240", "Hitachi HD40L4240") // CL
+DEFINE_DEVICE_TYPE(HD40A4240, hd40a4240_device, "hd40a4240", "Hitachi HD40A4240") // AC
+
//-------------------------------------------------
// constructor
@@ -168,6 +182,57 @@ hd614089_device::hd614089_device(const machine_config &mconfig, const char *tag,
{ }
+hmcs41x_cpu_device::hmcs41x_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 rom_size, u32 ram_size) :
+ hmcs400_cpu_device(mconfig, type, tag, owner, clock, rom_size, ram_size)
+{
+ m_has_div = true;
+}
+
+hmcs412_cpu_device::hmcs412_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ hmcs41x_cpu_device(mconfig, type, tag, owner, clock, 0x800, 96)
+{ }
+
+hd614120_device::hd614120_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs412_cpu_device(mconfig, HD614120, tag, owner, clock)
+{ }
+hd614125_device::hd614125_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs412_cpu_device(mconfig, HD614125, tag, owner, clock)
+{ }
+hd614128_device::hd614128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs412_cpu_device(mconfig, HD614128, tag, owner, clock)
+{ }
+
+
+hmcs414_cpu_device::hmcs414_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ hmcs41x_cpu_device(mconfig, type, tag, owner, clock, 0x1000, 96)
+{ }
+
+hd614140_device::hd614140_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs414_cpu_device(mconfig, HD614140, tag, owner, clock)
+{ }
+hd614145_device::hd614145_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs414_cpu_device(mconfig, HD614145, tag, owner, clock)
+{ }
+hd614148_device::hd614148_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs414_cpu_device(mconfig, HD614148, tag, owner, clock)
+{ }
+
+
+hmcs424_cpu_device::hmcs424_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ hmcs41x_cpu_device(mconfig, type, tag, owner, clock, 0x1000, 192)
+{ }
+
+hd404240_device::hd404240_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs424_cpu_device(mconfig, HD404240, tag, owner, clock)
+{ }
+hd40l4240_device::hd40l4240_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs424_cpu_device(mconfig, HD40L4240, tag, owner, clock)
+{ }
+hd40a4240_device::hd40a4240_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs424_cpu_device(mconfig, HD40A4240, tag, owner, clock)
+{ }
+
+
//-------------------------------------------------
// initialization
//-------------------------------------------------
@@ -199,11 +264,13 @@ void hmcs400_cpu_device::device_start()
memset(m_r, 0, sizeof(m_r));
memset(m_r_mask, 0, sizeof(m_r_mask));
+ m_r_dir = 0;
m_d = 0;
m_d_mask = 0;
m_int_line[0] = m_int_line[1] = 1;
m_irq_flags = 0;
+ m_irq_mask = 0x33ff;
m_pmr = 0;
m_prescaler = 0;
m_timer_mode[0] = m_timer_mode[1] = 0;
@@ -233,6 +300,7 @@ void hmcs400_cpu_device::device_start()
save_item(NAME(m_r));
save_item(NAME(m_r_mask));
+ save_item(NAME(m_r_dir));
save_item(NAME(m_d));
save_item(NAME(m_d_mask));
@@ -268,6 +336,15 @@ void hmcs400_cpu_device::device_start()
set_icountptr(m_icount);
}
+void hmcs41x_cpu_device::device_start()
+{
+ hmcs400_cpu_device::device_start();
+
+ // no timer A or serial interface
+ m_irq_mask = 0x033f;
+ m_data->unmap_readwrite(0x005, 0x008);
+}
+
void hmcs400_cpu_device::device_reset()
{
m_pc = 0;
@@ -428,6 +505,9 @@ void hmcs400_cpu_device::reset_io()
m_d_mask = m_d = 0x000f;
m_write_d(m_d_mask);
+ // R0 and R6-R8 are write-only, R9 and RA are read-only
+ m_r_dir = 0x16affe;
+
for (int i = 0; i < 11; i++)
{
// R0-R2 and RA are high-voltage
@@ -438,13 +518,20 @@ void hmcs400_cpu_device::reset_io()
}
}
+void hmcs41x_cpu_device::reset_io()
+{
+ // does not have R5-R9
+ hmcs400_cpu_device::reset_io();
+ m_r_dir &= ~0xffc00;
+}
+
u8 hmcs400_cpu_device::read_r(u8 index)
{
// reads from write-only or non-existent ports are invalid
- const bool write_only = (index == 0 || (index >= 6 && index <= 8));
- if (write_only || index > 10)
+ const u8 dir = m_r_dir >> (index * 2) & 3;
+ if (~dir & 1)
{
- logerror("read from %s port R%X @ $%04X\n", write_only ? "output" : "unknown", index, m_prev_pc);
+ logerror("read from %s port R%X @ $%04X\n", (dir & 2) ? "output" : "unknown", index, m_prev_pc);
return 0xf;
}
@@ -479,7 +566,7 @@ void hmcs400_cpu_device::write_r(u8 index, u8 data)
data &= 0xf;
// ignore writes to read-only or non-existent ports
- if (index > 8)
+ if (~m_r_dir >> (index * 2) & 2)
return;
if (m_write_r[index].isunset())
@@ -550,7 +637,7 @@ bool hmcs400_cpu_device::access_mode(u8 mem_mask, bool bit_mode)
return true;
}
- if (err)
+ if (err || mem_mask == 0)
logerror("invalid access to I/O register @ $%04X\n", m_prev_pc);
return false;
@@ -559,7 +646,7 @@ bool hmcs400_cpu_device::access_mode(u8 mem_mask, bool bit_mode)
u8 hmcs400_cpu_device::irq_control_r(offs_t offset, u8 mem_mask)
{
// mask out unused bits (RSP is write-only)
- const u16 unused = 0xcc02;
+ const u16 unused = ~m_irq_mask | 2;
u16 data = m_irq_flags | unused;
if (!machine().side_effects_disabled())
@@ -585,7 +672,7 @@ void hmcs400_cpu_device::irq_control_w(offs_t offset, u8 data, u8 mem_mask)
u16 mask = mem_mask << (offset * 4);
// ignore writes to unused bits
- if (mask & 0xcc00)
+ if (mask & ~m_irq_mask)
return;
// ignore writing 1 to flags that can only be cleared
@@ -633,7 +720,7 @@ void hmcs400_cpu_device::take_interrupt(int irq)
void hmcs400_cpu_device::check_interrupts()
{
// irq priority is in the same order as the irq control flags
- u16 irq = m_irq_flags >> 2;
+ u16 irq = (m_irq_flags & m_irq_mask) >> 2;
for (int i = 0; i < 7; i++)
{
diff --git a/src/devices/cpu/hmcs400/hmcs400.h b/src/devices/cpu/hmcs400/hmcs400.h
index cea24878743..4f97c082539 100644
--- a/src/devices/cpu/hmcs400/hmcs400.h
+++ b/src/devices/cpu/hmcs400/hmcs400.h
@@ -21,31 +21,31 @@ enum
};
-// pinout reference
+// pinout reference (see datasheets for other pinouts)
/*
- _________________
- D11 1 |* | 64 D10
- D12 2 | | 63 D9
- D13 3 | | 62 D8
- D14 4 | | 61 D7
- D15 5 | | 60 D6
- R00 6 | | 59 D5
- R01 7 | | 58 D4
- R02 8 | | 57 D3
- R03 9 | | 56 D2
- R10 10 | | 55 D1
- R11 11 | | 54 D0
- R12 12 | | 53 GND
- R13 13 | | 52 OSC2
- R20 14 | HD61402x | 51 OSC1
- R21 15 | HD61404x | 50 _TEST
- R22 16 | HD61408x | 49 RESET
- R23 17 | | 48 R93
- RA0 18 | DP-64S | 47 R92
- RA1/Vdisp 19 | DC-64S | 46 R91
- R30 20 | | 45 R90
- R31 21 | | 44 R83
+ _________________ _________________
+ D11 1 |* | 64 D10 D12 1 |* | 64 D11
+ D12 2 | | 63 D9 D13 2 | | 63 D10
+ D13 3 | | 62 D8 D14 3 | | 62 D9
+ D14 4 | | 61 D7 RA1/Vdisp 4 | | 61 D8
+ D15 5 | | 60 D6 R00 5 | | 60 D7
+ R00 6 | | 59 D5 R01 6 | | 59 D6
+ R01 7 | | 58 D4 R02 7 | | 58 D5
+ R02 8 | | 57 D3 R03 8 | HD61412x | 57 D4
+ R03 9 | | 56 D2 R10 9 | HD61414x | 56 D3
+ R10 10 | | 55 D1 R11 10 | HD40x4240 | 55 D2
+ R11 11 | | 54 D0 R12 11 | | 54 D1
+ R12 12 | | 53 GND R13 12 | DP-42 | 53 D0
+ R13 13 | | 52 OSC2 R20 13 | DP-42S | 52 GND
+ R20 14 | HD61402x | 51 OSC1 R21 14 | | 51 OSC2
+ R21 15 | HD61404x | 50 _TEST R22 15 | | 50 OSC1
+ R22 16 | HD61408x | 49 RESET R23 16 | | 49 _TEST
+ R23 17 | | 48 R93 R30 17 | | 48 RESET
+ RA0 18 | DP-64S | 47 R92 R31 18 | | 47 R43
+ RA1/Vdisp 19 | DC-64S | 46 R91 R32/_INT0 19 | | 46 R42/SO
+ R30 20 | | 45 R90 R33/_INT1 20 | | 45 R41/SI
+ R31 21 | | 44 R83 Vcc 21 |_________________| 44 R40/_SCK
R32/_INT0 22 | | 43 R82
R33/_INT1 23 | | 42 R81
R50 24 | | 41 R80
@@ -58,8 +58,6 @@ enum
R63 31 | | 34 R41/SI
Vcc 32 |_________________| 33 R40/_SCK
- (see datasheets for FP-64 pinouts)
-
*/
@@ -78,7 +76,7 @@ public:
auto read_d() { return m_read_d.bind(); }
auto write_d() { return m_write_d.bind(); }
- // system clock divider mask option (only for HMCS408, HMCS414, HMCS424)
+ // system clock divider mask option (only for HMCS408, HMCS41x, HMCS42x)
// valid options: 4, 8, 16, default to 8
auto &set_divider(u8 div) { assert(m_has_div); m_divider = div; return *this; }
@@ -156,13 +154,15 @@ protected:
bool m_standby; // standby mode (SBY opcode)
bool m_stop; // stop mode (STOP opcode)
- u8 m_r[11]; // R outputs state
- u8 m_r_mask[11];
+ u8 m_r[11]; // R pins output state
+ u8 m_r_mask[11]; // R pins voltage mask
+ u32 m_r_dir; // R pins I/O direction (bit 0=R, bit 1=W)
u16 m_d; // D pins state
- u16 m_d_mask;
+ u16 m_d_mask; // D pins voltage mask
u8 m_int_line[2]; // INT0/INT1 pin state
u16 m_irq_flags; // interrupt control bits
+ u16 m_irq_mask; // valid irq flags bits
u8 m_pmr; // port mode register
u16 m_prescaler; // 11-bit clock prescaler
u8 m_timer_mode[2]; // TMA/TMB: timer mode registers
@@ -184,7 +184,7 @@ protected:
void pop_stack();
void push_stack();
- void reset_io();
+ virtual void reset_io();
u8 read_r(u8 index);
void write_r(u8 index, u8 data);
int read_d(u8 index);
@@ -435,6 +435,92 @@ public:
};
+class hmcs41x_cpu_device : public hmcs400_cpu_device
+{
+protected:
+ hmcs41x_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 rom_size, u32 ram_size);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void reset_io() override;
+};
+
+class hmcs412_cpu_device : public hmcs41x_cpu_device
+{
+protected:
+ hmcs412_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+};
+
+class hd614120_device : public hmcs412_cpu_device
+{
+public:
+ hd614120_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class hd614125_device : public hmcs412_cpu_device
+{
+public:
+ hd614125_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class hd614128_device : public hmcs412_cpu_device
+{
+public:
+ hd614128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+
+class hmcs414_cpu_device : public hmcs41x_cpu_device
+{
+protected:
+ hmcs414_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+};
+
+class hd614140_device : public hmcs414_cpu_device
+{
+public:
+ hd614140_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class hd614145_device : public hmcs414_cpu_device
+{
+public:
+ hd614145_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class hd614148_device : public hmcs414_cpu_device
+{
+public:
+ hd614148_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+
+class hmcs424_cpu_device : public hmcs41x_cpu_device
+{
+protected:
+ hmcs424_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD { hmcs400_cpu_device::device_start(); }
+};
+
+class hd404240_device : public hmcs424_cpu_device
+{
+public:
+ hd404240_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class hd40l4240_device : public hmcs424_cpu_device
+{
+public:
+ hd40l4240_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class hd40a4240_device : public hmcs424_cpu_device
+{
+public:
+ hd40a4240_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+
DECLARE_DEVICE_TYPE(HD614022, hd614022_device)
DECLARE_DEVICE_TYPE(HD614023, hd614023_device)
DECLARE_DEVICE_TYPE(HD614025, hd614025_device)
@@ -456,4 +542,16 @@ DECLARE_DEVICE_TYPE(HD614086, hd614086_device)
DECLARE_DEVICE_TYPE(HD614088, hd614088_device)
DECLARE_DEVICE_TYPE(HD614089, hd614089_device)
+DECLARE_DEVICE_TYPE(HD614120, hd614120_device)
+DECLARE_DEVICE_TYPE(HD614125, hd614125_device)
+DECLARE_DEVICE_TYPE(HD614128, hd614128_device)
+
+DECLARE_DEVICE_TYPE(HD614140, hd614140_device)
+DECLARE_DEVICE_TYPE(HD614145, hd614145_device)
+DECLARE_DEVICE_TYPE(HD614148, hd614148_device)
+
+DECLARE_DEVICE_TYPE(HD404240, hd404240_device)
+DECLARE_DEVICE_TYPE(HD40A4240, hd40a4240_device)
+DECLARE_DEVICE_TYPE(HD40L4240, hd40l4240_device)
+
#endif // MAME_CPU_HMCS400_HMCS400_H