From 9778738aa62ed559fd5cff016aa3d7734f004687 Mon Sep 17 00:00:00 2001 From: hap Date: Wed, 6 Nov 2024 00:00:04 +0100 Subject: hmcs400: add hmcs412/414/424 --- src/devices/cpu/hmcs400/hmcs400.cpp | 115 ++++++++++++++++++++++---- src/devices/cpu/hmcs400/hmcs400.h | 158 +++++++++++++++++++++++++++++------- 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 -- cgit v1.2.3