From 5dcf902ea7f060045f1ce5666e92c94645cf749d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Corr=C3=AAa=20da=20Silva=20Sanches?= Date: Fri, 23 Aug 2024 18:15:04 -0300 Subject: [PATCH] Improvements to Technics KN5000 --- scripts/src/bus.lua | 15 + scripts/src/cpu.lua | 2 + src/devices/bus/technics/hdae5000.cpp | 125 + src/devices/bus/technics/hdae5000.h | 16 + src/devices/bus/technics/kn5000_extension.cpp | 41 + src/devices/bus/technics/kn5000_extension.h | 48 + src/devices/cpu/tlcs900/dasm900.cpp | 358 +-- src/devices/cpu/tlcs900/dasm900.h | 65 +- src/devices/cpu/tlcs900/tlcs900.h | 7 +- src/devices/cpu/tlcs900/tmp94c241.cpp | 2009 +++++++++++++++++ src/devices/cpu/tlcs900/tmp94c241.h | 282 +++ src/devices/cpu/tlcs900/tmp95c061.cpp | 49 +- src/devices/cpu/tlcs900/tmp95c061.h | 3 + src/devices/cpu/tlcs900/tmp95c063.cpp | 39 +- src/devices/cpu/tlcs900/tmp95c063.h | 3 + src/devices/cpu/tlcs900/tmp96c141.cpp | 26 + src/devices/cpu/tlcs900/tmp96c141.h | 3 + src/mame/mame.lst | 2 +- src/mame/matsushita/kn5000.cpp | 142 +- src/tools/unidasm.cpp | 4 + 20 files changed, 3017 insertions(+), 222 deletions(-) create mode 100644 src/devices/bus/technics/hdae5000.cpp create mode 100644 src/devices/bus/technics/hdae5000.h create mode 100644 src/devices/bus/technics/kn5000_extension.cpp create mode 100644 src/devices/bus/technics/kn5000_extension.h create mode 100644 src/devices/cpu/tlcs900/tmp94c241.cpp create mode 100644 src/devices/cpu/tlcs900/tmp94c241.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index dabbbd82731cc..786f35907fc59 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2599,6 +2599,21 @@ if (BUSES["SUPRACAN"]~=null) then end +--------------------------------------------------- +-- +--@src/devices/bus/technics/kn5000_extension.h,BUSES["TECHNICS"] = true +--------------------------------------------------- + +if (BUSES["TECHNICS"]~=null) then + files { + MAME_DIR .. "src/devices/bus/technics/kn5000_extension.cpp", + MAME_DIR .. "src/devices/bus/technics/kn5000_extension.h", + MAME_DIR .. "src/devices/bus/technics/hdae5000.cpp", + MAME_DIR .. "src/devices/bus/technics/hdae5000.h", + } +end + + --------------------------------------------------- -- --@src/devices/bus/tiki100/exp.h,BUSES["TIKI100"] = true diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index de0f2fe40d8f4..2ac4194f06ba4 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -2975,6 +2975,8 @@ if CPUS["TLCS900"] then MAME_DIR .. "src/devices/cpu/tlcs900/tlcs900.h", MAME_DIR .. "src/devices/cpu/tlcs900/900tbl.hxx", MAME_DIR .. "src/devices/cpu/tlcs900/900htbl.hxx", + MAME_DIR .. "src/devices/cpu/tlcs900/tmp94c241.cpp", + MAME_DIR .. "src/devices/cpu/tlcs900/tmp94c241.h", MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c061.cpp", MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c061.h", MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c063.cpp", diff --git a/src/devices/bus/technics/hdae5000.cpp b/src/devices/bus/technics/hdae5000.cpp new file mode 100644 index 0000000000000..f205eec26bcc6 --- /dev/null +++ b/src/devices/bus/technics/hdae5000.cpp @@ -0,0 +1,125 @@ +// license:BSD-3-Clause +// copyright-holders:Antoine Mine, Olivier Galibert, Felipe Sanches +// +// HD-AE5000, Hard Disk & Audio Extension for Technics KN5000 emulation +// +// The HD-AE5000 was an extension board for the Technics KN5000 musical keyboard. +// It provided a hard-disk, additional audio outputs and a serial port to interface +// with a computer to transfer files to/from the hard-drive. + +#include "emu.h" +#include "hdae5000.h" +#include "bus/ata/hdd.h" +#include "machine/i8255.h" + +namespace { + +class hdae5000_device : public device_t, public kn5000_extension_interface +{ +public: + static constexpr feature_type unemulated_features() { return feature::DISK | feature::SOUND; } + + hdae5000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void rom_map(address_map &map) override; + virtual void io_map(address_map &map) override; + +protected: + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + virtual void device_reset() override; + virtual const tiny_rom_entry *device_rom_region() const override; + +private: + uint8_t ata_r(offs_t offset); + void ata_w(offs_t offset, uint8_t data); + + required_device m_hdd; + required_device m_ppi; + required_memory_region m_rom; +}; + +hdae5000_device::hdae5000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, HDAE5000, tag, owner, clock) + , kn5000_extension_interface(mconfig, *this) + , m_hdd(*this, "hdd") + , m_ppi(*this, "ppi") + , m_rom(*this, "rom") +{ +} + +ROM_START(hdae5000) + ROM_REGION16_LE(0x80000, "rom" , 0) + ROM_DEFAULT_BIOS("v2.01i") + + ROM_SYSTEM_BIOS(0, "v1.10i", "Version 1.10i - July 6th, 1998") + ROMX_LOAD("hd-ae5000_v1_10i.ic4", 0x000000, 0x80000, CRC(7461374b) SHA1(6019f3c28b6277730418974dde4dc6893fced00e), ROM_BIOS(0)) + + ROM_SYSTEM_BIOS(1, "v1.15i", "Version 1.15i - October 13th, 1998") + ROMX_LOAD("hd-ae5000_v1_15i.ic4", 0x000000, 0x80000, CRC(e76d4b9f) SHA1(581fa58e2cd6fe381cfc312c73771d25ff2e662c), ROM_BIOS(1)) + + // Version 2.01i is described as having "additions like lyrics display etc." + ROM_SYSTEM_BIOS(2, "v2.01i", "Version 2.01i - January 15th, 1999") // installation file indicated "v2.0i" but signature inside the ROM is "v2.01i" + ROMX_LOAD("hd-ae5000_v2_01i.ic4", 0x000000, 0x80000, CRC(961e6dcd) SHA1(0160c17baa7b026771872126d8146038a19ef53b), ROM_BIOS(2)) +ROM_END + +void hdae5000_device::rom_map(address_map &map) +{ + map(0x00000, 0x7ffff).rom().region(m_rom, 0); +} + +uint8_t hdae5000_device::ata_r(offs_t offset) +{ + return 0; //TODO: FIXME! +} + +void hdae5000_device::ata_w(offs_t offset, uint8_t data) +{ +} + +/* +PPI pin 2 /CS = CN6 pin 59 PPIFCS +ATA pin 31 INTRQ = CN6 pin 58 HDINT + +*/ +void hdae5000_device::io_map(address_map &map) +{ + map(0x130000, 0x13001f).rw(FUNC(hdae5000_device::ata_r), FUNC(hdae5000_device::ata_w)); // ATA IDE at CN2 + map(0x160000, 0x160007).umask16(0x00ff).rw(m_ppi, FUNC(i8255_device::read), FUNC(i8255_device::write)); // parallel port interface (NEC uPD71055) IC9 +} + +const tiny_rom_entry *hdae5000_device::device_rom_region() const +{ + return ROM_NAME(hdae5000); +} + +void hdae5000_device::device_add_mconfig(machine_config &config) +{ + IDE_HARDDISK(config, m_hdd, 0); + + /* Optional Parallel Port */ + I8255(config, m_ppi); // actual chip is a NEC uPD71055 @ IC9 on the HD-AE5000 board + + // Port A: DB15 connector + + // m_ppi->in_pa_callback().set(FUNC(?_device::ppi_in_a)); + // m_ppi->out_pb_callback().set(FUNC(?_device::ppi_out_b)); + // m_ppi->in_pc_callback().set(FUNC(?_device::ppi_in_c)); + // m_ppi->out_pc_callback().set(FUNC(?_device::ppi_out_c)); + +// we may later add this, for the auxiliary audio output provided by this extension board: +// SPEAKER(config, "is it mono or stereo ?").front_center(); +} + +void hdae5000_device::device_start() +{ +// save_item(NAME(m_...)); +} + +void hdae5000_device::device_reset() +{ +} + +} // anonymous namespace + +DEFINE_DEVICE_TYPE_PRIVATE(HDAE5000, kn5000_extension_interface, hdae5000_device, "hdae5000", "HD-AE5000, Hard Disk & Audio Extension") diff --git a/src/devices/bus/technics/hdae5000.h b/src/devices/bus/technics/hdae5000.h new file mode 100644 index 0000000000000..05633a6519969 --- /dev/null +++ b/src/devices/bus/technics/hdae5000.h @@ -0,0 +1,16 @@ +// license:BSD-3-Clause +// copyright-holders:Antoine Mine, Olivier Galibert, Felipe Sanches +// +// HD-AE5000 emulation +// +#ifndef MAME_BUS_TECHNICS_HDAE5000_H +#define MAME_BUS_TECHNICS_HDAE5000_H + +#pragma once + +#include "kn5000_extension.h" + +// device type declaration +DECLARE_DEVICE_TYPE(HDAE5000, kn5000_extension_interface) + +#endif // MAME_BUS_TECHNICS_HDAE5000_H diff --git a/src/devices/bus/technics/kn5000_extension.cpp b/src/devices/bus/technics/kn5000_extension.cpp new file mode 100644 index 0000000000000..b7d3b6282cae5 --- /dev/null +++ b/src/devices/bus/technics/kn5000_extension.cpp @@ -0,0 +1,41 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert, Felipe Sanches + +// Generic Technics KN5000 extension slot + + +#include "emu.h" +#include "kn5000_extension.h" + +DEFINE_DEVICE_TYPE(KN5000_EXTENSION, kn5000_extension_device, "kn5000_extension", "Technics KN5000 extension port") + +kn5000_extension_device::kn5000_extension_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, KN5000_EXTENSION, tag, owner, clock), + device_single_card_slot_interface(mconfig, *this), + m_write_irq(*this) +{ +} + +void kn5000_extension_device::rom_map(address_space_installer &space, offs_t start, offs_t end) +{ + auto dev = get_card_device(); + if(dev) + space.install_device(start, end, *dev, &kn5000_extension_interface::rom_map); +} + +void kn5000_extension_device::io_map(address_space_installer &space, offs_t start, offs_t end) +{ + auto dev = get_card_device(); + if(dev) + space.install_device(start, end, *dev, &kn5000_extension_interface::io_map); +} + +void kn5000_extension_device::device_start() +{ +} + +kn5000_extension_interface::kn5000_extension_interface(const machine_config &mconfig, device_t &device) : + device_interface(device, "extension"), + m_ext(dynamic_cast(device.owner())) +{ +} diff --git a/src/devices/bus/technics/kn5000_extension.h b/src/devices/bus/technics/kn5000_extension.h new file mode 100644 index 0000000000000..8a3c63f8ec22b --- /dev/null +++ b/src/devices/bus/technics/kn5000_extension.h @@ -0,0 +1,48 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert, Felipe Sanches +// +// Generic Technics KN5000 extension slot + +#ifndef MAME_BUS_TECHNICS_KN5000_EXTENSION_H +#define MAME_BUS_TECHNICS_KN5000_EXTENSION_H + +#pragma once + +class kn5000_extension_device; + +class kn5000_extension_interface : public device_interface +{ +public: + kn5000_extension_interface(const machine_config &mconfig, device_t &device); + + virtual void rom_map(address_map &map) = 0; + virtual void io_map(address_map &map) = 0; + +//protected: +// DECLARE_WRITE_LINE_MEMBER(irq_w); + +private: + kn5000_extension_device *const m_ext; +}; + + +class kn5000_extension_device : public device_t, public device_single_card_slot_interface +{ + friend class kn5000_extension_interface; + +public: + kn5000_extension_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void rom_map(address_space_installer &space, offs_t start, offs_t end); + void io_map(address_space_installer &space, offs_t start, offs_t end); + auto irq_callback() { return m_write_irq.bind(); } + void irq_w(int state) { m_write_irq(state); } + +protected: + virtual void device_start() override; + devcb_write_line m_write_irq; +}; + +DECLARE_DEVICE_TYPE(KN5000_EXTENSION, kn5000_extension_device) + +#endif // MAME_BUS_TECHNICS_KN5000_EXTENSION_H diff --git a/src/devices/cpu/tlcs900/dasm900.cpp b/src/devices/cpu/tlcs900/dasm900.cpp index af78c98b8e565..516d4cbc8d441 100644 --- a/src/devices/cpu/tlcs900/dasm900.cpp +++ b/src/devices/cpu/tlcs900/dasm900.cpp @@ -9,6 +9,23 @@ Toshiba TLCS-900/H disassembly #include "emu.h" #include "dasm900.h" +tlcs900_disassembler::tlcs900_disassembler(std::pair const symbols[], std::size_t symbol_count) + : m_symbols(symbols), m_symbol_count(symbol_count) +{ +} + +template std::string tlcs900_disassembler::address(T offset, int size) const +{ + auto const symbol = std::lower_bound(m_symbols, + m_symbols + m_symbol_count, + offset, + [] (auto const &sym, u16 addr) { return sym.first < addr; }); + if ((m_symbol_count != (symbol - m_symbols)) && (symbol->first == offset)) + return symbol->second; + else + return util::string_format("0x%0*x", size, offset); +} + const char *const tlcs900_disassembler::s_mnemonic[] = { "adc", "add", "and", "andcf", "bit", "bs1b", @@ -1369,12 +1386,120 @@ const char *const tlcs900_disassembler::s_cond[16] = "F","LT","LE","ULE","PE/OV","M/MI","Z","C","T","GE","GT","UGT","PO/NOV","P/PL","NZ","NC" }; - u32 tlcs900_disassembler::opcode_alignment() const { return 1; } +void tlcs900_disassembler::decode_control_register_8(std::ostream &stream, uint8_t imm){ + switch( imm ) + { + case 0x22: util::stream_format(stream, " DMAM0"); break; + case 0x26: util::stream_format(stream, " DMAM1"); break; + case 0x2a: util::stream_format(stream, " DMAM2"); break; + case 0x2e: util::stream_format(stream, " DMAM3"); break; + default: + util::stream_format(stream, " unknown (encoding is 0x%02x)", imm); + break; + } +} + + +void tmp94c241_disassembler::decode_control_register_8(std::ostream &stream, uint8_t imm){ + switch( imm ) + { + case 0x42: util::stream_format(stream, " DMAM0"); break; + case 0x46: util::stream_format(stream, " DMAM1"); break; + case 0x4a: util::stream_format(stream, " DMAM2"); break; + case 0x4e: util::stream_format(stream, " DMAM3"); break; + case 0x52: util::stream_format(stream, " DMAM4"); break; + case 0x56: util::stream_format(stream, " DMAM5"); break; + case 0x5a: util::stream_format(stream, " DMAM6"); break; + case 0x5e: util::stream_format(stream, " DMAM7"); break; + default: + util::stream_format(stream, " unknown (encoding is 0x%02x)", imm); + break; + } +} + + +void tlcs900_disassembler::decode_control_register_16(std::ostream &stream, uint8_t imm){ + switch( imm ) + { + case 0x20: util::stream_format(stream, " DMAC0"); break; + case 0x24: util::stream_format(stream, " DMAC1"); break; + case 0x28: util::stream_format(stream, " DMAC2"); break; + case 0x2c: util::stream_format(stream, " DMAC3"); break; + case 0x7c: util::stream_format(stream, " NSP"); break; + default: + util::stream_format(stream, " unknown (encoding is 0x%02x)", imm); + break; + } +} + + +void tmp94c241_disassembler::decode_control_register_16(std::ostream &stream, uint8_t imm){ + switch( imm ) + { + case 0x40: util::stream_format(stream, " DMAC0"); break; + case 0x44: util::stream_format(stream, " DMAC1"); break; + case 0x48: util::stream_format(stream, " DMAC2"); break; + case 0x4c: util::stream_format(stream, " DMAC3"); break; + case 0x50: util::stream_format(stream, " DMAC4"); break; + case 0x54: util::stream_format(stream, " DMAC5"); break; + case 0x58: util::stream_format(stream, " DMAC6"); break; + case 0x5c: util::stream_format(stream, " DMAC7"); break; + default: + util::stream_format(stream, " unknown (encoding is 0x%02x)", imm); + break; + } +} + + +void tlcs900_disassembler::decode_control_register_32(std::ostream &stream, uint8_t imm){ + switch( imm ) + { + case 0x00: util::stream_format(stream, " DMAS0"); break; + case 0x04: util::stream_format(stream, " DMAS1"); break; + case 0x08: util::stream_format(stream, " DMAS2"); break; + case 0x0c: util::stream_format(stream, " DMAS3"); break; + case 0x10: util::stream_format(stream, " DMAD0"); break; + case 0x14: util::stream_format(stream, " DMAD1"); break; + case 0x18: util::stream_format(stream, " DMAD2"); break; + case 0x1c: util::stream_format(stream, " DMAD3"); break; + default: + util::stream_format(stream, " unknown (encoding is 0x%02x)", imm); + break; + } +} + + +void tmp94c241_disassembler::decode_control_register_32(std::ostream &stream, uint8_t imm){ + switch( imm ) + { + case 0x00: util::stream_format(stream, " DMAS0"); break; + case 0x04: util::stream_format(stream, " DMAS1"); break; + case 0x08: util::stream_format(stream, " DMAS2"); break; + case 0x0c: util::stream_format(stream, " DMAS3"); break; + case 0x10: util::stream_format(stream, " DMAS4"); break; + case 0x14: util::stream_format(stream, " DMAS5"); break; + case 0x18: util::stream_format(stream, " DMAS6"); break; + case 0x1c: util::stream_format(stream, " DMAS7"); break; + case 0x20: util::stream_format(stream, " DMAD0"); break; + case 0x24: util::stream_format(stream, " DMAD1"); break; + case 0x28: util::stream_format(stream, " DMAD2"); break; + case 0x2c: util::stream_format(stream, " DMAD3"); break; + case 0x30: util::stream_format(stream, " DMAD4"); break; + case 0x34: util::stream_format(stream, " DMAD5"); break; + case 0x38: util::stream_format(stream, " DMAD6"); break; + case 0x3c: util::stream_format(stream, " DMAD7"); break; + default: + util::stream_format(stream, " unknown (encoding is 0x%02x)", imm); + break; + } +} + + offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) { const tlcs900inst *dasm; @@ -1449,25 +1574,25 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case M_C0: switch( op & 0x07 ) { - case 0x00: /* 0xC0 */ + case 0x00: /* 0xc0 */ imm = opcodes.r8( pos++ ); - buf = string_format("0x%02x", imm); + buf = address( imm, 2 ); break; - case 0x01: /* 0xC1 */ + case 0x01: /* 0xc1 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); - buf = string_format("0x%04x", imm); + buf = address( imm, 4 ); break; - case 0x02: /* 0xC2 */ + case 0x02: /* 0xc2 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); imm = imm | (opcodes.r8( pos++ ) << 16); - buf = string_format("0x%06x", imm); + buf = address( imm, 6 ); break; - case 0x03: /* 0xC3 */ + case 0x03: /* 0xc3 */ imm = opcodes.r8( pos++ ); switch( imm & 0x03 ) { @@ -1511,12 +1636,12 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const } break; - case 0x04: /* 0xC4 */ + case 0x04: /* 0xc4 */ imm = opcodes.r8( pos++ ); buf = string_format("-%s", s_allreg32[imm]); break; - case 0x05: /* 0xC5 */ + case 0x05: /* 0xc5 */ imm = opcodes.r8( pos++ ); buf = string_format("%s+", s_allreg32[imm]); break; @@ -1526,7 +1651,7 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const break; case oC8: - if ( op & 0x08 ) + if( op & 0x08 ) { buf = string_format("%s", s_reg8[ op & 0x07 ]); } @@ -1542,25 +1667,25 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case M_D0: switch( op & 0x07 ) { - case 0x00: /* 0xD0 */ + case 0x00: /* 0xd0 */ imm = opcodes.r8( pos++ ); buf = string_format("0x%02x", imm); break; - case 0x01: /* 0xD1 */ + case 0x01: /* 0xd1 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); buf = string_format("0x%04x", imm); break; - case 0x02: /* 0xD2 */ + case 0x02: /* 0xd2 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); imm = imm | (opcodes.r8( pos++ ) << 16); buf = string_format("0x%06x", imm); break; - case 0x03: /* 0xD3 */ + case 0x03: /* 0xd3 */ imm = opcodes.r8( pos++ ); switch( imm & 0x03 ) { @@ -1604,12 +1729,12 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const } break; - case 0x04: /* 0xD4 */ + case 0x04: /* 0xd4 */ imm = opcodes.r8( pos++ ); buf = string_format("-%s", s_allreg32[imm]); break; - case 0x05: /* 0xD5 */ + case 0x05: /* 0xd5 */ imm = opcodes.r8( pos++ ); buf = string_format("%s+", s_allreg32[imm]); break; @@ -1619,7 +1744,7 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const break; case oD8: - if ( op & 0x08 ) + if( op & 0x08 ) { buf = string_format("%s", s_reg16[ op & 0x07 ]); } @@ -1636,25 +1761,25 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case M_E0: switch( op & 0x07 ) { - case 0x00: /* 0xE0 */ + case 0x00: /* 0xe0 */ imm = opcodes.r8( pos++ ); buf = string_format("0x%02x", imm); break; - case 0x01: /* 0xE1 */ + case 0x01: /* 0xe1 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); buf = string_format("0x%04x", imm); break; - case 0x02: /* 0xE2 */ + case 0x02: /* 0xe2 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); imm = imm | (opcodes.r8( pos++ ) << 16); buf = string_format("0x%06x", imm); break; - case 0x03: /* 0xE3 */ + case 0x03: /* 0xe3 */ imm = opcodes.r8( pos++ ); switch( imm & 0x03 ) { @@ -1698,12 +1823,12 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const } break; - case 0x04: /* 0xE4 */ + case 0x04: /* 0xe4 */ imm = opcodes.r8( pos++ ); buf = string_format("-%s", s_allreg32[imm]); break; - case 0x05: /* 0xE5 */ + case 0x05: /* 0xe5 */ imm = opcodes.r8( pos++ ); buf = string_format("%s+", s_allreg32[imm]); break; @@ -1713,7 +1838,7 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const break; case M_E8: - if ( op & 0x08 ) + if( op & 0x08 ) { buf = string_format("%s", s_reg32[ op & 0x07 ]); } @@ -1729,25 +1854,25 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case M_F0: switch( op & 0x07 ) { - case 0x00: /* 0xF0 */ + case 0x00: /* 0xf0 */ imm = opcodes.r8( pos++ ); - buf = string_format("0x%02x", imm); + buf = address( imm, 2 ); break; - case 0x01: /* 0xF1 */ + case 0x01: /* 0xf1 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); - buf = string_format("0x%04x", imm); + buf = address( imm, 4 ); break; - case 0x02: /* 0xF2 */ + case 0x02: /* 0xf2 */ imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); imm = imm | (opcodes.r8( pos++ ) << 16); - buf = string_format("0x%06x", imm); + buf = address( imm, 6 ); break; - case 0x03: /* 0xF3 */ + case 0x03: /* 0xf3 */ imm = opcodes.r8( pos++ ); switch( imm & 0x03 ) { @@ -1791,12 +1916,12 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const } break; - case 0x04: /* 0xF4 */ + case 0x04: /* 0xf4 */ imm = opcodes.r8( pos++ ); buf = string_format("-%s", s_allreg32[imm]); break; - case 0x05: /* 0xF5 */ + case 0x05: /* 0xf5 */ imm = opcodes.r8( pos++ ); buf = string_format("%s+", s_allreg32[imm]); break; @@ -1854,97 +1979,36 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case O_CC: util::stream_format(stream, " %s", s_cond[op & 0x0F]); - if ((op & 0x07) != 0 && dasm->mnemonic != M_SCC) + if( (op & 0x07) != 0 && dasm->mnemonic != M_SCC ) + { flags |= STEP_COND; + } break; case O_CR8: imm = opcodes.r8( pos++ ); - switch( imm ) - { - case 0x22: - util::stream_format(stream, " DMAM0"); - break; - case 0x26: - util::stream_format(stream, " DMAM1"); - break; - case 0x2a: - util::stream_format(stream, " DMAM2"); - break; - case 0x2e: - util::stream_format(stream, " DMAM3"); - break; - default: - util::stream_format(stream, " unknown"); - break; - } + decode_control_register_8(stream, imm); break; case O_CR16: imm = opcodes.r8( pos++ ); - switch( imm ) - { - case 0x20: - util::stream_format(stream, " DMAC0"); - break; - case 0x24: - util::stream_format(stream, " DMAC1"); - break; - case 0x28: - util::stream_format(stream, " DMAC2"); - break; - case 0x2c: - util::stream_format(stream, " DMAC3"); - break; - default: - util::stream_format(stream, " unknown"); - break; - } + decode_control_register_16(stream, imm); break; case O_CR32: imm = opcodes.r8( pos++ ); - switch( imm ) - { - case 0x00: - util::stream_format(stream, " DMAS0"); - break; - case 0x04: - util::stream_format(stream, " DMAS1"); - break; - case 0x08: - util::stream_format(stream, " DMAS2"); - break; - case 0x0c: - util::stream_format(stream, " DMAS3"); - break; - case 0x10: - util::stream_format(stream, " DMAD0"); - break; - case 0x14: - util::stream_format(stream, " DMAD1"); - break; - case 0x18: - util::stream_format(stream, " DMAD2"); - break; - case 0x1c: - util::stream_format(stream, " DMAD3"); - break; - default: - util::stream_format(stream, " unknown"); - break; - } + decode_control_register_32(stream, imm); break; case O_D8: imm = opcodes.r8( pos++ ); - util::stream_format(stream, " 0x%06x", ( pos + (int8_t)imm ) & 0xFFFFFF); + util::stream_format(stream, " 0x%06x", ( pos + (int8_t)imm ) & 0xffffff); break; case O_D16: imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); - util::stream_format(stream, " 0x%06x", ( pos + (int16_t)imm ) & 0xFFFFFF); + util::stream_format(stream, " 0x%06x", ( pos + (int16_t)imm ) & 0xffffff); break; case O_F: @@ -1997,13 +2061,13 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case O_M8: imm = opcodes.r8( pos++ ); - util::stream_format(stream, " (0x%02x)", imm); + util::stream_format(stream, " (%s)", address( imm, 2 )); break; case O_M16: imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); - util::stream_format(stream, " (0x%04x)", imm); + util::stream_format(stream, " (%s)", address( imm, 4 )); break; case O_R: @@ -2042,97 +2106,39 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case O_CC: util::stream_format(stream, ",%s", s_cond[op & 0x0F]); - if ((op & 0x07) != 0 && dasm->mnemonic != M_SCC) + if( (op & 0x07) != 0 && dasm->mnemonic != M_SCC ) + { flags |= STEP_COND; + } break; case O_CR8: imm = opcodes.r8( pos++ ); - switch( imm ) - { - case 0x22: - util::stream_format(stream, ",DMAM0"); - break; - case 0x26: - util::stream_format(stream, ",DMAM1"); - break; - case 0x2a: - util::stream_format(stream, ",DMAM2"); - break; - case 0x2e: - util::stream_format(stream, ",DMAM3"); - break; - default: - util::stream_format(stream, ",unknown"); - break; - } + util::stream_format(stream, ","); + decode_control_register_8(stream, imm); break; case O_CR16: imm = opcodes.r8( pos++ ); - switch( imm ) - { - case 0x20: - util::stream_format(stream, ",DMAC0"); - break; - case 0x24: - util::stream_format(stream, ",DMAC1"); - break; - case 0x28: - util::stream_format(stream, ",DMAC2"); - break; - case 0x2c: - util::stream_format(stream, ",DMAC3"); - break; - default: - util::stream_format(stream, ",unknown"); - break; - } + util::stream_format(stream, ","); + decode_control_register_16(stream, imm); break; case O_CR32: imm = opcodes.r8( pos++ ); - switch( imm ) - { - case 0x00: - util::stream_format(stream, ",DMAS0"); - break; - case 0x04: - util::stream_format(stream, ",DMAS1"); - break; - case 0x08: - util::stream_format(stream, ",DMAS2"); - break; - case 0x0c: - util::stream_format(stream, ",DMAS3"); - break; - case 0x10: - util::stream_format(stream, ",DMAD0"); - break; - case 0x14: - util::stream_format(stream, ",DMAD1"); - break; - case 0x18: - util::stream_format(stream, ",DMAD2"); - break; - case 0x1c: - util::stream_format(stream, ",DMAD3"); - break; - default: - util::stream_format(stream, ",unknown"); - break; - } + util::stream_format(stream, ","); + decode_control_register_32(stream, imm); break; case O_D8: imm = opcodes.r8( pos++ ); - util::stream_format(stream, ",0x%06x", ( pos + (int8_t)imm ) & 0xFFFFFF); + util::stream_format(stream, ",0x%06x", ( pos + (int8_t)imm ) & 0xffffff); break; case O_D16: imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); - util::stream_format(stream, ",0x%06x", ( pos + (int16_t)imm ) & 0xFFFFFF); + util::stream_format(stream, ",0x%06x", ( pos + (int16_t)imm ) & 0xffffff); break; case O_F: @@ -2185,13 +2191,13 @@ offs_t tlcs900_disassembler::disassemble(std::ostream &stream, offs_t pc, const case O_M8: imm = opcodes.r8( pos++ ); - util::stream_format(stream, ",(0x%02x)", imm); + util::stream_format(stream, " (%s)", address( imm, 2 )); break; case O_M16: imm = opcodes.r8( pos++ ); imm = imm | (opcodes.r8( pos++ ) << 8); - util::stream_format(stream, ",(0x%04x)", imm); + util::stream_format(stream, " (%s)", address( imm, 4 )); break; case O_R: diff --git a/src/devices/cpu/tlcs900/dasm900.h b/src/devices/cpu/tlcs900/dasm900.h index 8fb067a299a8b..51b0bafdfbe57 100644 --- a/src/devices/cpu/tlcs900/dasm900.h +++ b/src/devices/cpu/tlcs900/dasm900.h @@ -13,8 +13,15 @@ Toshiba TLCS-900/H disassembly class tlcs900_disassembler : public util::disasm_interface { +protected: + virtual void decode_control_register_8(std::ostream &stream, uint8_t imm); + virtual void decode_control_register_16(std::ostream &stream, uint8_t imm); + virtual void decode_control_register_32(std::ostream &stream, uint8_t imm); + public: - tlcs900_disassembler() = default; + tlcs900_disassembler(std::pair const symbols[], std::size_t symbol_count); + tlcs900_disassembler() : tlcs900_disassembler(nullptr, 0) {} + virtual ~tlcs900_disassembler() = default; virtual u32 opcode_alignment() const override; @@ -106,6 +113,62 @@ class tlcs900_disassembler : public util::disasm_interface static const char *const s_allreg32[256]; static const char *const s_cond[16]; + std::pair const *m_symbols; + std::size_t m_symbol_count; + + template std::string address(T offset, int size) const; +}; + + +class tmp94c241_disassembler : public tlcs900_disassembler +{ +public: + tmp94c241_disassembler() : tlcs900_disassembler() {}; + tmp94c241_disassembler(std::pair const symbols[], std::size_t symbol_count); + template tmp94c241_disassembler(std::pair const (&symbols)[N]) : tlcs900_disassembler(symbols, N) {} + + void decode_control_register_8(std::ostream &stream, uint8_t imm) override; + void decode_control_register_16(std::ostream &stream, uint8_t imm) override; + void decode_control_register_32(std::ostream &stream, uint8_t imm) override; + +private: + static const char *const s_sfr_names[]; +}; + + +class tmp95c061_disassembler : public tlcs900_disassembler +{ +public: + tmp95c061_disassembler() : tlcs900_disassembler() {}; + tmp95c061_disassembler(std::pair const symbols[], std::size_t symbol_count); + template tmp95c061_disassembler(std::pair const (&symbols)[N]) : tlcs900_disassembler(symbols, N) {} + +private: + static const char *const s_sfr_names[]; +}; + + +class tmp95c063_disassembler : public tlcs900_disassembler +{ +public: + tmp95c063_disassembler() : tlcs900_disassembler() {}; + tmp95c063_disassembler(std::pair const symbols[], std::size_t symbol_count); + template tmp95c063_disassembler(std::pair const (&symbols)[N]) : tlcs900_disassembler(symbols, N) {} + +private: + static const char *const s_sfr_names[]; +}; + + +class tmp96c141_disassembler : public tlcs900_disassembler +{ +public: + tmp96c141_disassembler() : tlcs900_disassembler() {}; + tmp96c141_disassembler(std::pair const symbols[], std::size_t symbol_count); + template tmp96c141_disassembler(std::pair const (&symbols)[N]) : tlcs900_disassembler(symbols, N) {} + +private: + static const char *const s_sfr_names[]; }; #endif diff --git a/src/devices/cpu/tlcs900/tlcs900.h b/src/devices/cpu/tlcs900/tlcs900.h index a3ce3d5fa6724..13b1d989e51ef 100644 --- a/src/devices/cpu/tlcs900/tlcs900.h +++ b/src/devices/cpu/tlcs900/tlcs900.h @@ -20,6 +20,9 @@ enum tlcs900_inputs TLCS900_INT6, TLCS900_INT7, TLCS900_INT8, + TLCS900_INT9, + TLCS900_INTA, + TLCS900_INTB, TLCS900_TIO, TLCS900_NUM_INPUTS }; @@ -102,8 +105,8 @@ class tlcs900_device : public cpu_device /* Internal timers, irqs, etc */ uint32_t m_timer_pre; - uint8_t m_timer[6]; - int m_timer_change[4]; + uint8_t m_timer[10]; + int m_timer_change[8]; bool m_prefetch_clear; uint8_t m_prefetch_index; uint8_t m_prefetch[4]; diff --git a/src/devices/cpu/tlcs900/tmp94c241.cpp b/src/devices/cpu/tlcs900/tmp94c241.cpp new file mode 100644 index 0000000000000..30a3eb64c23cd --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp94c241.cpp @@ -0,0 +1,2009 @@ +// license:BSD-3-Clause +// copyright-holders:AJR,Wilbert Pol,Felipe Sanches +/**************************************************************************** + + Toshiba TMP94C241 microcontroller + +****************************************************************************/ + +#include "emu.h" +#include "tmp94c241.h" +#include "dasm900.h" + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(TMP94C241, tmp94c241_device, "tmp94c241", "Toshiba TMP94C241") + +#define SFR_T01MOD m_tmod[0] +#define SFR_T23MOD m_tmod[1] +#define SFR_T4MOD m_tmod[2] +#define SFR_T6MOD m_tmod[3] +#define SFR_T8MOD m_tmod[4] +#define SFR_TAMOD m_tmod[5] +#define SFR_T8RUN m_t8run +#define SFR_T16RUN m_t16run +#define SFR_T02FFCR m_ffcr[0] +#define SFR_T4FFCR m_ffcr[1] +#define SFR_T6FFCR m_ffcr[2] +#define SFR_T8FFCR m_ffcr[3] +#define SFR_TAFFCR m_ffcr[4] +#define SFR_MSAR0 m_mem_start_reg[0] +#define SFR_MSAR1 m_mem_start_reg[1] +#define SFR_MSAR2 m_mem_start_reg[2] +#define SFR_MSAR3 m_mem_start_reg[3] +#define SFR_MSAR4 m_mem_start_reg[4] +#define SFR_MSAR5 m_mem_start_reg[5] +#define SFR_MAMR0 m_mem_start_mask[0] +#define SFR_MAMR1 m_mem_start_mask[1] +#define SFR_MAMR2 m_mem_start_mask[2] +#define SFR_MAMR3 m_mem_start_mask[3] +#define SFR_MAMR4 m_mem_start_mask[4] +#define SFR_MAMR5 m_mem_start_mask[5] + +#define TIMER_0_IS_RUNNING BIT(SFR_T8RUN, 0) +#define TIMER_1_IS_RUNNING BIT(SFR_T8RUN, 1) +#define TIMER_2_IS_RUNNING BIT(SFR_T8RUN, 2) +#define TIMER_3_IS_RUNNING BIT(SFR_T8RUN, 3) +#define TIMER_4_IS_RUNNING BIT(SFR_T16RUN, 0) +#define TIMER_6_IS_RUNNING BIT(SFR_T16RUN, 1) +#define TIMER_8_IS_RUNNING BIT(SFR_T16RUN, 2) +#define TIMER_A_IS_RUNNING BIT(SFR_T16RUN, 3) +#define PRESCALER_IS_ACTIVE BIT(SFR_T16RUN, 7) + +#define T0_INPUT_CLOCK ((SFR_T01MOD >> 0) & 0x03) +#define T1_INPUT_CLOCK ((SFR_T01MOD >> 2) & 0x03) +#define PWM1_INTERVAL_SELECTION ((SFR_T01MOD >> 4) & 0x03) +#define TO1_OPERATING_MODE ((SFR_T01MOD >> 6) & 0x03) +#define T2_INPUT_CLOCK ((SFR_T23MOD >> 0) & 0x03) +#define T3_INPUT_CLOCK ((SFR_T23MOD >> 2) & 0x03) +#define PWM2_INTERVAL_SELECTION ((SFR_T23MOD >> 4) & 0x03) +#define T23_OPERATING_MODE ((SFR_T23MOD >> 6) & 0x03) +#define T4_INPUT_CLOCK ((SFR_T4MOD >> 0) & 0x03) +#define UC4_CLEAR ((SFR_T4MOD >> 2) & 0x01) +#define T4_CAPTURE_TIMING ((SFR_T4MOD >> 3) & 0x03) +#define CAP4IN ((SFR_T4MOD >> 5) & 0x01) +#define T6_INPUT_CLOCK ((SFR_T6MOD >> 0) & 0x03) +#define T8_INPUT_CLOCK ((SFR_T8MOD >> 0) & 0x03) +#define TA_INPUT_CLOCK ((SFR_TAMOD >> 0) & 0x03) +#define EQ4T4 BIT(SFR_T4FFCR, 2) +#define EQ5T4 BIT(SFR_T4FFCR, 3) +#define EQ6T6 BIT(SFR_T6FFCR, 2) +#define EQ7T6 BIT(SFR_T6FFCR, 3) +#define EQ8T8 BIT(SFR_T8FFCR, 2) +#define EQ9T8 BIT(SFR_T8FFCR, 3) +#define EQATA BIT(SFR_TAFFCR, 2) +#define EQBTA BIT(SFR_TAFFCR, 3) + +// Field values for timer mode selection on TnMOD SFRs: +#define MODE_8BIT_TIMER 0 +#define MODE_16BIT_TIMER 1 +#define MODE_PPG 2 +#define MODE_PWM 3 + +#define UPCOUNTER_0 m_timer[0] +#define UPCOUNTER_1 m_timer[1] +#define UPCOUNTER_2 m_timer[2] +#define UPCOUNTER_3 m_timer[3] +#define UPCOUNTER_4 m_timer16[0] +#define UPCOUNTER_6 m_timer16[1] +#define UPCOUNTER_8 m_timer16[2] +#define UPCOUNTER_A m_timer16[3] +#define SFR_TREG0 m_t8_reg[0] +#define SFR_TREG1 m_t8_reg[1] +#define SFR_TREG2 m_t8_reg[2] +#define SFR_TREG3 m_t8_reg[3] +#define SFR_TREG4 m_t16_reg[0] +#define SFR_TREG5 m_t16_reg[1] +#define SFR_TREG6 m_t16_reg[2] +#define SFR_TREG7 m_t16_reg[3] +#define SFR_TREG8 m_t16_reg[4] +#define SFR_TREG9 m_t16_reg[5] +#define SFR_TREGA m_t16_reg[6] +#define SFR_TREGB m_t16_reg[7] +#define TIMER_CHANGE_0 m_timer_change[0] +#define TIMER_CHANGE_1 m_timer_change[1] +#define TIMER_CHANGE_2 m_timer_change[2] +#define TIMER_CHANGE_3 m_timer_change[3] +#define TIMER_CHANGE_4 m_timer_change[4] +#define TIMER_CHANGE_6 m_timer_change[5] +#define TIMER_CHANGE_8 m_timer_change[6] +#define TIMER_CHANGE_A m_timer_change[7] + +enum +{ + INTE45, + INTE67, + INTE89, + INTEAB, + INTET01, + INTET23, + INTET45, + INTET67, + INTET89, + INTETAB, + INTES0, + INTES1, + INTETC01, + INTETC23, + INTETC45, + INTETC67, + INTE0AD, + INTNMWDT +}; + +static const struct { + uint8_t reg; + uint8_t iff; + uint8_t vector; + uint8_t dma_start_vector; +} tmp94c241_irq_vector_map[] = +{ + { INTE0AD, 0x08, 0x28, 0x0a}, // INT0 Pin + { INTE45, 0x08, 0x2c, 0x0b}, // INT4 Pin + { INTE45, 0x80, 0x30, 0x0c}, // INT5 Pin + { INTE67, 0x08, 0x34, 0x0d}, // INT6 Pin + { INTE67, 0x80, 0x38, 0x0e}, // INT7 Pin + // 0x3c - reserved + { INTE89, 0x08, 0x40, 0x10}, // INT8 Pin + { INTE89, 0x80, 0x44, 0x11}, // INT9 Pin + { INTEAB, 0x08, 0x48, 0x12}, // INTA Pin + { INTEAB, 0x80, 0x4c, 0x13}, // INTB Pin + { INTET01, 0x08, 0x50, 0x14}, // INTT0: 8-bit timer (Timer 0) + { INTET01, 0x80, 0x54, 0x15}, // INTT1: 8-bit timer (Timer 1) + { INTET23, 0x08, 0x58, 0x16}, // INTT2: 8-bit timer (Timer 2) + { INTET23, 0x80, 0x5c, 0x17}, // INTT3: 8-bit timer (Timer 3) + { INTET45, 0x08, 0x60, 0x18}, // INTTR4: 16-bit timer (Treg 4) + { INTET45, 0x80, 0x64, 0x19}, // INTTR5: 16-bit timer (Treg 5) + { INTET67, 0x08, 0x68, 0x1a}, // INTTR6: 16-bit timer (Treg 6) + { INTET67, 0x80, 0x6c, 0x1b}, // INTTR7: 16-bit timer (Treg 7) + { INTET89, 0x08, 0x70, 0x1c}, // INTTR8: 16-bit timer (Treg 8) + { INTET89, 0x80, 0x74, 0x1d}, // INTTR9: 16-bit timer (Treg 9) + { INTETAB, 0x08, 0x78, 0x1e}, // INTTRA: 16-bit timer (Treg A) + { INTETAB, 0x80, 0x7c, 0x1f}, // INTTRB: 16-bit timer (Treg B) + { INTES0, 0x08, 0x80, 0x20}, // INTRX0: Serial receive 0 + { INTES0, 0x80, 0x84, 0x21}, // INTTX0: Serial send 0 + { INTES1, 0x08, 0x88, 0x22}, // INTRX1: Serial receive 1 + { INTES1, 0x80, 0x8c, 0x23}, // INTTX1: Serial send 1 + { INTE0AD, 0x80, 0x90, 0x24}, // INTAD: AD conversion completion + { INTETC01, 0x08, 0x94, 0x25}, // INTTC0: micro-DMA completion Ch.0 + { INTETC01, 0x80, 0x98, 0x26}, // INTTC1: micro-DMA completion Ch.1 + { INTETC23, 0x08, 0x9c, 0x27}, // INTTC2: micro-DMA completion Ch.2 + { INTETC23, 0x80, 0xa0, 0x28}, // INTTC3: micro-DMA completion Ch.3 + { INTETC45, 0x08, 0xa4, 0x29}, // INTTC4: micro-DMA completion Ch.4 + { INTETC45, 0x80, 0xa8, 0x2a}, // INTTC5: micro-DMA completion Ch.5 + { INTETC67, 0x08, 0xac, 0x2b}, // INTTC6: micro-DMA completion Ch.6 + { INTETC67, 0x80, 0xb0, 0x2c}, // INTTC7: micro-DMA completion Ch.7 + /* 0xb4 ... 0xfc (Reserved) */ +}; +static constexpr u8 NUM_MASKABLE_IRQS = sizeof(tmp94c241_irq_vector_map) / 4; + + +//************************************************************************** +// DEVICE CONSTRUCTION AND INITIALIZATION +//************************************************************************** + +//------------------------------------------------- +// tmp94c241_device - constructor +//------------------------------------------------- + +tmp94c241_device::tmp94c241_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + tlcs900h_device(mconfig, TMP94C241, tag, owner, clock), + m_an_read(*this, 0), + m_port_read(*this, 0), + m_port_write(*this), + m_port_latch{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + m_port_control{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + m_port_function{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + m_t8run(0), + m_t8_reg{ 0, 0, 0, 0, 0, 0, 0, 0 }, + m_tmod{ 0, 0, 0, 0, 0, 0 }, + m_ffcr{ 0, 0, 0, 0, 0 }, + m_trdc(0), + m_t16_reg{ 0, 0, 0, 0, 0, 0, 0, 0 }, + m_t16_cap{ 0, 0, 0, 0, 0, 0, 0, 0 }, + m_t16run(0), + m_timer16{ 0, 0, 0, 0 }, + m_watchdog_mode(0), + m_serial_control{ 0, 0 }, + m_serial_mode{ 0, 0 }, + m_baud_rate{ 0, 0 }, + m_od_enable(0), + m_ad_mode1(0), + m_ad_mode2(0), + m_ad_result{ 0, 0, 0, 0 }, + m_int_reg{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + m_iimc(0), + m_dma_vector{ 0, 0, 0, 0 }, + m_block_cs{ 0, 0, 0, 0 }, + m_external_cs(0), + m_mem_start_reg{ 0, 0, 0, 0 }, + m_mem_start_mask{ 0, 0, 0, 0 }, + m_dram_refresh{ 0, 0 }, + m_dram_access{ 0, 0 }, + m_da_drive(0) +{ +} + +//------------------------------------------------- +// device_config_complete - device-specific startup +//------------------------------------------------- + +void tmp94c241_device::device_config_complete() +{ + if (m_am8_16 == 0) + m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor(FUNC(tmp94c241_device::internal_mem), this)); + else + m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 8, 24, 0, address_map_constructor(FUNC(tmp94c241_device::internal_mem), this)); +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void tmp94c241_device::device_start() +{ + tlcs900h_device::device_start(); + + save_item(NAME(m_port_latch)); + save_item(NAME(m_port_control)); + save_item(NAME(m_port_function)); + save_item(NAME(m_t8run)); + save_item(NAME(m_t8_reg)); + save_item(NAME(m_tmod)); + save_item(NAME(m_trdc)); + save_item(NAME(m_t16_reg)); + save_item(NAME(m_t16_cap)); + save_item(NAME(m_ffcr)); + save_item(NAME(m_t16run)); + save_item(NAME(m_watchdog_mode)); + save_item(NAME(m_serial_control)); + save_item(NAME(m_serial_mode)); + save_item(NAME(m_baud_rate)); + save_item(NAME(m_od_enable)); + save_item(NAME(m_ad_mode1)); + save_item(NAME(m_ad_mode2)); + save_item(NAME(m_ad_result)); + save_item(NAME(m_int_reg)); + save_item(NAME(m_iimc)); + save_item(NAME(m_dma_vector)); + save_item(NAME(m_block_cs)); + save_item(NAME(m_external_cs)); + save_item(NAME(m_mem_start_reg)); + save_item(NAME(m_mem_start_mask)); + save_item(NAME(m_dram_refresh)); + save_item(NAME(m_dram_access)); + save_item(NAME(m_da_drive)); + + m_nmi_state = CLEAR_LINE; + for( int i = 0; i < TLCS900_NUM_INPUTS; i++ ) + { + m_level[i] = CLEAR_LINE; + } +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void tmp94c241_device::device_reset() +{ + tlcs900h_device::device_reset(); + + m_ad_cycles_left = 0; + m_timer_pre = 0; + TIMER_CHANGE_0 = 0; + TIMER_CHANGE_1 = 0; + TIMER_CHANGE_2 = 0; + TIMER_CHANGE_3 = 0; + TIMER_CHANGE_4 = 0; + TIMER_CHANGE_6 = 0; + TIMER_CHANGE_8 = 0; + TIMER_CHANGE_A = 0; + + m_port_latch[PORT_0] = 0x00; + m_port_latch[PORT_1] = 0x00; + m_port_latch[PORT_2] = 0x00; + m_port_latch[PORT_3] = 0x00; + m_port_latch[PORT_4] = 0x00; + m_port_latch[PORT_5] = 0x00; + m_port_latch[PORT_6] = 0x00; + m_port_latch[PORT_7] = 0x7f; + m_port_latch[PORT_8] = 0x3b; + m_port_latch[PORT_A] = 0x1f; + m_port_latch[PORT_B] = 0x1f; + m_port_latch[PORT_C] = 0x00; + m_port_latch[PORT_D] = 0x00; + m_port_latch[PORT_E] = 0x00; + m_port_latch[PORT_F] = 0x00; + m_port_latch[PORT_H] = 0x00; + m_port_latch[PORT_Z] = 0x00; + + m_port_function[PORT_0] = 0x01; + m_port_function[PORT_1] = 0x01; + m_port_function[PORT_2] = 0x01; + m_port_function[PORT_3] = 0x01; + m_port_function[PORT_4] = 0xff; + m_port_function[PORT_5] = 0xff; + m_port_function[PORT_6] = 0xff; + m_port_function[PORT_7] = 0x01; + m_port_function[PORT_8] = 0x00; + m_port_function[PORT_A] = 0x00; + m_port_function[PORT_B] = 0x00; + m_port_function[PORT_C] = 0x00; + m_port_function[PORT_D] = 0x00; + m_port_function[PORT_E] = 0x00; + m_port_function[PORT_F] = 0x00; + m_port_function[PORT_H] = 0x00; + m_port_function[PORT_Z] = 0x00; + + std::fill_n(&m_port_control[0], NUM_PORTS, 0x00); + m_t8run = 0x00; + m_trdc = 0x00; + std::fill_n(&m_tmod[0], 8, 0x00); + std::fill_n(&m_ffcr[0], 6, 0x00); + std::fill_n(&m_timer[0], 4, 0x00); + std::fill_n(&m_timer16[0], 4, 0x00); + m_watchdog_mode = 0x80; + for( int i = 0; i < 2; i++ ) + { + m_serial_control[i] &= 0x80; + m_serial_mode[i] &= 0x80; + m_baud_rate[i] = 0x00; + } + m_od_enable = 0x00; + m_ad_mode1 = 0x00; + m_ad_mode2 = 0x00; + std::fill_n(&m_int_reg[0], 18, 0x00); + m_iimc = 0x00; + std::fill_n(&m_dma_vector[0], 4, 0x00); + m_block_cs[0] = 0x0000; + m_block_cs[1] = 0x0000; + m_block_cs[2] = 0x1000; //FIXME! + m_block_cs[3] = 0x0000; + m_block_cs[4] = 0x0000; + m_block_cs[5] = 0x0000; + m_external_cs = 0x0000; + std::fill_n(&m_mem_start_reg[0], 6, 0xff); + std::fill_n(&m_mem_start_mask[0], 6, 0xff); + std::fill_n(&m_dram_refresh[0], 2, 0x00); + std::fill_n(&m_dram_access[0], 2, 0x80); + m_da_drive = 0x00; +} + +uint8_t tmp94c241_device::inte_r(offs_t offset) +{ + return m_int_reg[offset]; +} + +void tmp94c241_device::inte_w(offs_t offset, uint8_t data) +{ + if ( data & 0x80 ) + data = ( data & 0x7f ) | ( m_int_reg[offset] & 0x80 ); + if ( data & 0x08 ) + data = ( data & 0xf7 ) | ( m_int_reg[offset] & 0x08 ); + + m_int_reg[offset] = data; + m_check_irqs = 1; +} + +uint8_t tmp94c241_device::intnmwdt_r(offs_t offset) +{ + return m_int_reg[INTNMWDT]; +} + +void tmp94c241_device::intnmwdt_w(offs_t offset, uint8_t data) +{ + if ( data & 0x80 ) + data = ( data & 0x7f ) | ( m_int_reg[INTNMWDT] & 0x80 ); + if ( data & 0x08 ) + data = ( data & 0xf7 ) | ( m_int_reg[INTNMWDT] & 0x08 ); + + m_int_reg[INTNMWDT] = data; + m_check_irqs = 1; +} + +void tmp94c241_device::iimc_w(uint8_t data) +{ + m_iimc = data; + m_check_irqs = 1; +} + +void tmp94c241_device::intclr_w(uint8_t data) +{ + for( int i = 0; i < NUM_MASKABLE_IRQS; i++ ) + { + if ( data == tmp94c241_irq_vector_map[i].dma_start_vector ) + { + // clear interrupt request + m_int_reg[tmp94c241_irq_vector_map[i].reg] &= ~ tmp94c241_irq_vector_map[i].iff; + return; + } + } +} + +void tmp94c241_device::dmav_w(offs_t offset, uint8_t data) +{ + m_dma_vector[offset] = data; +} + +void tmp94c241_device::b0cs_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 0)) + m_block_cs[0] = (m_block_cs[0] & 0xff) | (data << 8); + else + m_block_cs[0] = (m_block_cs[0] & 0xff00) | data; +} + +void tmp94c241_device::b1cs_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 0)) + m_block_cs[1] = (m_block_cs[1] & 0xff) | (data << 8); + else + m_block_cs[1] = (m_block_cs[1] & 0xff00) | data; +} + +void tmp94c241_device::b2cs_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 0)) + m_block_cs[2] = (m_block_cs[2] & 0xff) | (data << 8); + else + m_block_cs[2] = (m_block_cs[2] & 0xff00) | data; +} + +void tmp94c241_device::b3cs_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 0)) + m_block_cs[3] = (m_block_cs[3] & 0xff) | (data << 8); + else + m_block_cs[3] = (m_block_cs[3] & 0xff00) | data; +} + +void tmp94c241_device::b4cs_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 0)) + m_block_cs[4] = (m_block_cs[4] & 0xff) | (data << 8); + else + m_block_cs[4] = (m_block_cs[4] & 0xff00) | data; +} + +void tmp94c241_device::b5cs_w(offs_t offset, uint8_t data) +{ + if (BIT(offset, 0)) + m_block_cs[5] = (m_block_cs[5] & 0xff) | (data << 8); + else + m_block_cs[5] = (m_block_cs[5] & 0xff00) | data; +} + +void tmp94c241_device::mamr0_w(offs_t offset, uint8_t data) +{ + SFR_MAMR0 = data; +} + +void tmp94c241_device::msar0_w(offs_t offset, uint8_t data) +{ + SFR_MSAR0 = data; +} + +uint8_t tmp94c241_device::mamr0_r() +{ + return SFR_MAMR0; +} + +uint8_t tmp94c241_device::msar0_r() +{ + return SFR_MSAR0; +} + +void tmp94c241_device::mamr1_w(offs_t offset, uint8_t data) +{ + SFR_MAMR1 = data; +} + +void tmp94c241_device::msar1_w(offs_t offset, uint8_t data) +{ + SFR_MSAR1 = data; +} + +uint8_t tmp94c241_device::mamr1_r() +{ + return SFR_MAMR1; +} + +uint8_t tmp94c241_device::msar1_r() +{ + return SFR_MSAR1; +} + +void tmp94c241_device::mamr2_w(offs_t offset, uint8_t data) +{ + SFR_MAMR2 = data; +} + +void tmp94c241_device::msar2_w(offs_t offset, uint8_t data) +{ + SFR_MSAR2 = data; +} + +uint8_t tmp94c241_device::mamr2_r() +{ + return SFR_MAMR2; +} + +uint8_t tmp94c241_device::msar2_r() +{ + return SFR_MSAR2; +} + +void tmp94c241_device::mamr3_w(offs_t offset, uint8_t data) +{ + SFR_MAMR3 = data; +} + +void tmp94c241_device::msar3_w(offs_t offset, uint8_t data) +{ + SFR_MSAR3 = data; +} + +uint8_t tmp94c241_device::mamr3_r() +{ + return SFR_MAMR3; +} + +uint8_t tmp94c241_device::msar3_r() +{ + return SFR_MSAR3; +} + +void tmp94c241_device::mamr4_w(offs_t offset, uint8_t data) +{ + SFR_MAMR4 = data; +} + +void tmp94c241_device::msar4_w(offs_t offset, uint8_t data) +{ + SFR_MSAR4 = data; +} + +uint8_t tmp94c241_device::mamr4_r() +{ + return SFR_MAMR4; +} + +uint8_t tmp94c241_device::msar4_r() +{ + return SFR_MSAR4; +} + +void tmp94c241_device::mamr5_w(offs_t offset, uint8_t data) +{ + SFR_MAMR5 = data; +} + +void tmp94c241_device::msar5_w(offs_t offset, uint8_t data) +{ + SFR_MSAR5 = data; +} + +uint8_t tmp94c241_device::mamr5_r() +{ + return SFR_MAMR5; +} + +uint8_t tmp94c241_device::msar5_r() +{ + return SFR_MSAR5; +} + +uint8_t tmp94c241_device::t8run_r() +{ + return SFR_T8RUN; +} + +void tmp94c241_device::t8run_w(uint8_t data) +{ + SFR_T8RUN = data; + + if ( !TIMER_0_IS_RUNNING ) + { + UPCOUNTER_0 = 0; + TIMER_CHANGE_0 = 0; + } + if ( !TIMER_1_IS_RUNNING ) + { + UPCOUNTER_1 = 0; + TIMER_CHANGE_1 = 0; + } + if ( !TIMER_2_IS_RUNNING ) + { + UPCOUNTER_2 = 0; + TIMER_CHANGE_2 = 0; + } + if ( !TIMER_3_IS_RUNNING ) + { + UPCOUNTER_3 = 0; + TIMER_CHANGE_3 = 0; + } +} + +void tmp94c241_device::treg01_w(offs_t offset, uint8_t data) +{ + + if (BIT(0, offset)) + SFR_TREG1 = data; + else + SFR_TREG0 = data; +} + +uint8_t tmp94c241_device::t01mod_r() +{ + return SFR_T01MOD; +} + +void tmp94c241_device::t01mod_w(uint8_t data) +{ + logerror("T01MOD = %02X\n", data); + SFR_T01MOD = data; +} + +uint8_t tmp94c241_device::t02ffcr_r() +{ + return SFR_T02FFCR; +} + +enum +{ + FF_INVERT, + FF_SET, + FF_CLEAR, + FF_DONTCARE +}; + +void tmp94c241_device::change_timer_flipflop(uint8_t flipflop, uint8_t operation) +{ + switch(operation) + { + case FF_INVERT: + switch( flipflop ) + { + case 0x1: if ((m_port_function[PORT_C] & 0x03) == 0x02) port_w(m_port_latch[PORT_C] ^ 0x01); break; + case 0x3: if ((m_port_function[PORT_C] & 0x03) == 0x02) port_w(m_port_latch[PORT_C] ^ 0x02); break; + case 0x4: if ((m_port_function[PORT_D] & 0x01) == 0x01) port_w(m_port_latch[PORT_D] ^ 0x01); break; + case 0x6: if ((m_port_function[PORT_D] & 0x10) == 0x10) port_w(m_port_latch[PORT_D] ^ 0x10); break; + case 0x7: if ((m_port_function[PORT_C] & 0x03) == 0x03) port_w(m_port_latch[PORT_C] ^ 0x01); break; + case 0x8: if ((m_port_function[PORT_E] & 0x01) == 0x01) port_w(m_port_latch[PORT_E] ^ 0x01); break; + case 0xa: if ((m_port_function[PORT_E] & 0x10) == 0x10) port_w(m_port_latch[PORT_E] ^ 0x10); break; + case 0xb: if ((m_port_function[PORT_C] & 0x03) == 0x03) port_w(m_port_latch[PORT_C] ^ 0x02); break; + } + break; + case FF_SET: + switch( flipflop ) + { + case 0x1: if ((m_port_function[PORT_C] & 0x03) == 0x02) port_w(m_port_latch[PORT_C] & 0x01); break; + case 0x3: if ((m_port_function[PORT_C] & 0x03) == 0x02) port_w(m_port_latch[PORT_C] & 0x02); break; + case 0x4: if ((m_port_function[PORT_D] & 0x01) == 0x01) port_w(m_port_latch[PORT_D] & 0x01); break; + case 0x6: if ((m_port_function[PORT_D] & 0x10) == 0x10) port_w(m_port_latch[PORT_D] & 0x10); break; + case 0x7: if ((m_port_function[PORT_C] & 0x03) == 0x03) port_w(m_port_latch[PORT_C] & 0x01); break; + case 0x8: if ((m_port_function[PORT_E] & 0x01) == 0x01) port_w(m_port_latch[PORT_E] & 0x01); break; + case 0xa: if ((m_port_function[PORT_E] & 0x10) == 0x10) port_w(m_port_latch[PORT_E] & 0x10); break; + case 0xb: if ((m_port_function[PORT_C] & 0x03) == 0x03) port_w(m_port_latch[PORT_C] & 0x02); break; + } + break; + case FF_CLEAR: + switch( flipflop ) + { + case 0x1: if ((m_port_function[PORT_C] & 0x03) == 0x02) port_w(m_port_latch[PORT_C] | ~0x01); break; + case 0x3: if ((m_port_function[PORT_C] & 0x03) == 0x02) port_w(m_port_latch[PORT_C] | ~0x02); break; + case 0x4: if ((m_port_function[PORT_D] & 0x01) == 0x01) port_w(m_port_latch[PORT_D] | ~0x01); break; + case 0x6: if ((m_port_function[PORT_D] & 0x10) == 0x10) port_w(m_port_latch[PORT_D] | ~0x10); break; + case 0x7: if ((m_port_function[PORT_C] & 0x03) == 0x03) port_w(m_port_latch[PORT_C] | ~0x01); break; + case 0x8: if ((m_port_function[PORT_E] & 0x01) == 0x01) port_w(m_port_latch[PORT_E] | ~0x01); break; + case 0xa: if ((m_port_function[PORT_E] & 0x10) == 0x10) port_w(m_port_latch[PORT_E] | ~0x10); break; + case 0xb: if ((m_port_function[PORT_C] & 0x03) == 0x03) port_w(m_port_latch[PORT_C] | ~0x02); break; + } + break; + } +} + +void tmp94c241_device::t02ffcr_w(uint8_t data) +{ + switch( data & 0x0c ) + { + case 0x00: + change_timer_flipflop( 1, FF_INVERT ); + break; + case 0x04: + change_timer_flipflop( 1, FF_SET ); + break; + case 0x08: + change_timer_flipflop( 1, FF_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + change_timer_flipflop( 3, FF_INVERT ); + break; + case 0x40: + change_timer_flipflop( 3, FF_SET ); + break; + case 0x80: + change_timer_flipflop( 3, FF_CLEAR ); + break; + } + + SFR_T02FFCR = data | 0xcc; +} + +void tmp94c241_device::treg23_w(offs_t offset, uint8_t data) +{ + + if (BIT(0, offset)) + SFR_TREG3 = data; + else + SFR_TREG2 = data; +} + +uint8_t tmp94c241_device::t23mod_r() +{ + return SFR_T23MOD; +} + +void tmp94c241_device::t23mod_w(uint8_t data) +{ + logerror("T23MOD = %02X\n", data); + + SFR_T23MOD = data; +} + +uint8_t tmp94c241_device::trdc_r() +{ + return m_trdc; +} + +void tmp94c241_device::trdc_w(uint8_t data) +{ + m_trdc = data; +} + +void tmp94c241_device::treg45_w(offs_t offset, uint16_t data) +{ + if (offset < 2) + SFR_TREG4 = data; + else + SFR_TREG5 = data; +} + +void tmp94c241_device::treg67_w(offs_t offset, uint16_t data) +{ + if (offset < 2) + SFR_TREG6 = data; + else + SFR_TREG7 = data; +} + +void tmp94c241_device::treg89_w(offs_t offset, uint16_t data) +{ + if (offset < 2) + SFR_TREG8 = data; + else + SFR_TREG9 = data; +} + +void tmp94c241_device::tregab_w(offs_t offset, uint16_t data) +{ + if (offset < 2) + SFR_TREGA = data; + else + SFR_TREGB = data; +} + +uint8_t tmp94c241_device::t4mod_r() +{ + return SFR_T4MOD; +} + +void tmp94c241_device::t4mod_w(uint8_t data) +{ + logerror("T4MOD = %02X\n", data); + SFR_T4MOD = data; +} + +uint8_t tmp94c241_device::t6mod_r() +{ + return SFR_T6MOD; +} + +void tmp94c241_device::t6mod_w(uint8_t data) +{ + logerror("T6MOD = %02X\n", data); + SFR_T6MOD = data; +} + +uint8_t tmp94c241_device::t8mod_r() +{ + return SFR_T8MOD; +} + +void tmp94c241_device::t8mod_w(uint8_t data) +{ + logerror("T8MOD = %02X\n", data); + SFR_T8MOD = data; +} + +uint8_t tmp94c241_device::tamod_r() +{ + return SFR_TAMOD; +} + +void tmp94c241_device::tamod_w(uint8_t data) +{ + logerror("TAMOD = %02X\n", data); + SFR_TAMOD = data; +} + + +uint8_t tmp94c241_device::t4ffcr_r() +{ + return SFR_T4FFCR; +} + +void tmp94c241_device::t4ffcr_w(uint8_t data) +{ + switch( data & 0x03 ) + { + case 0x00: + change_timer_flipflop( 4, FF_INVERT ); + break; + case 0x01: + change_timer_flipflop( 4, FF_SET ); + break; + case 0x02: + change_timer_flipflop( 4, FF_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + change_timer_flipflop( 5, FF_INVERT ); + break; + case 0x40: + change_timer_flipflop( 5, FF_SET ); + break; + case 0x80: + change_timer_flipflop( 5, FF_CLEAR ); + break; + } + + SFR_T4FFCR = data | 0xc3; +} + +uint8_t tmp94c241_device::t8ffcr_r() +{ + return SFR_T8FFCR; +} + +void tmp94c241_device::t8ffcr_w(uint8_t data) +{ + switch( data & 0x03 ) + { + case 0x00: + change_timer_flipflop( 8, FF_INVERT ); + break; + case 0x01: + change_timer_flipflop( 8, FF_SET ); + break; + case 0x02: + change_timer_flipflop( 8, FF_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + change_timer_flipflop( 9, FF_INVERT ); + break; + case 0x40: + change_timer_flipflop( 9, FF_SET ); + break; + case 0x80: + change_timer_flipflop( 9, FF_CLEAR ); + break; + } + + SFR_T8FFCR = data | 0xc3; +} + + +uint8_t tmp94c241_device::t6ffcr_r() +{ + return SFR_T6FFCR; +} + +void tmp94c241_device::t6ffcr_w(uint8_t data) +{ + switch( data & 0x03 ) + { + case 0x00: + change_timer_flipflop( 6, FF_INVERT ); + break; + case 0x01: + change_timer_flipflop( 6, FF_SET ); + break; + case 0x02: + change_timer_flipflop( 6, FF_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + change_timer_flipflop( 7, FF_INVERT ); + break; + case 0x40: + change_timer_flipflop( 7, FF_SET ); + break; + case 0x80: + change_timer_flipflop( 7, FF_CLEAR ); + break; + } + + SFR_T6FFCR = data | 0xc3; +} + +uint8_t tmp94c241_device::taffcr_r() +{ + return SFR_TAFFCR; +} + +void tmp94c241_device::taffcr_w(uint8_t data) +{ + switch( data & 0x03 ) + { + case 0x00: + change_timer_flipflop( 0xa, FF_INVERT ); + break; + case 0x01: + change_timer_flipflop( 0xa, FF_SET ); + break; + case 0x02: + change_timer_flipflop( 0xa, FF_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + change_timer_flipflop( 0xb, FF_INVERT ); + break; + case 0x40: + change_timer_flipflop( 0xb, FF_SET ); + break; + case 0x80: + change_timer_flipflop( 0xb, FF_CLEAR ); + break; + } + + SFR_TAFFCR = data | 0xc3; +} + +uint8_t tmp94c241_device::t16run_r() +{ + return SFR_T16RUN; +} + +void tmp94c241_device::t16run_w(uint8_t data) +{ + SFR_T16RUN = data; + + if ( !TIMER_4_IS_RUNNING ) + { + UPCOUNTER_4 = 0; + TIMER_CHANGE_4 = 0; + } + if ( !TIMER_6_IS_RUNNING ) + { + UPCOUNTER_6 = 0; + TIMER_CHANGE_6 = 0; + } + if ( !TIMER_8_IS_RUNNING ) + { + UPCOUNTER_8 = 0; + TIMER_CHANGE_8 = 0; + } + if ( !TIMER_A_IS_RUNNING ) + { + UPCOUNTER_A = 0; + TIMER_CHANGE_A = 0; + } +} + + +uint8_t tmp94c241_device::cap45_r(offs_t offset) +{ + if (BIT(offset, 0)) + return m_t16_cap[(offset >> 1) + 0] >> 8; + else + return m_t16_cap[(offset >> 1) + 0] & 0x00ff; +} + +uint8_t tmp94c241_device::cap67_r(offs_t offset) +{ + if (BIT(offset, 0)) + return m_t16_cap[(offset >> 1) + 2] >> 8; + else + return m_t16_cap[(offset >> 1) + 2] & 0x00ff; +} + +uint8_t tmp94c241_device::cap89_r(offs_t offset) +{ + if (BIT(offset, 0)) + return m_t16_cap[(offset >> 1) + 4] >> 8; + else + return m_t16_cap[(offset >> 1) + 4] & 0x00ff; +} + +uint8_t tmp94c241_device::capab_r(offs_t offset) +{ + if (BIT(offset, 0)) + return m_t16_cap[(offset >> 1) + 6] >> 8; + else + return m_t16_cap[(offset >> 1) + 6] & 0x00ff; +} + +uint8_t tmp94c241_device::wdmod_r() +{ + return m_watchdog_mode; +} + +void tmp94c241_device::wdmod_w(uint8_t data) +{ + m_watchdog_mode = data; +} + +void tmp94c241_device::wdcr_w(uint8_t data) +{ +} + + +uint8_t tmp94c241_device::sc0buf_r() +{ + return 0; +} + +void tmp94c241_device::sc0buf_w(uint8_t data) +{ + // Fake finish sending data + m_int_reg[INTES0] |= 0x80; + m_check_irqs = 1; +} + +uint8_t tmp94c241_device::sc0cr_r() +{ + uint8_t reg = m_serial_control[0]; + if (!machine().side_effects_disabled()) + m_serial_control[0] &= 0xe3; + return reg; +} + +void tmp94c241_device::sc0cr_w(uint8_t data) +{ + m_serial_control[0] = data; +} + +uint8_t tmp94c241_device::sc0mod_r() +{ + return m_serial_mode[0]; +} + +void tmp94c241_device::sc0mod_w(uint8_t data) +{ + m_serial_mode[0] = data; +} + +uint8_t tmp94c241_device::br0cr_r() +{ + return m_baud_rate[0]; +} + +void tmp94c241_device::br0cr_w(uint8_t data) +{ + m_baud_rate[0] = data; +} + +uint8_t tmp94c241_device::sc1buf_r() +{ + return 0; +} + +void tmp94c241_device::sc1buf_w(uint8_t data) +{ + // Fake finish sending data + m_int_reg[INTES1] |= 0x80; + m_check_irqs = 1; +} + +uint8_t tmp94c241_device::sc1cr_r() +{ + uint8_t reg = m_serial_control[1]; + if (!machine().side_effects_disabled()) + m_serial_control[1] &= 0xe3; + return reg; +} + +void tmp94c241_device::sc1cr_w(uint8_t data) +{ + m_serial_control[1] = data; +} + +uint8_t tmp94c241_device::sc1mod_r() +{ + return m_serial_mode[1]; +} + +void tmp94c241_device::sc1mod_w(uint8_t data) +{ + m_serial_mode[1] = data; +} + +uint8_t tmp94c241_device::br1cr_r() +{ + return m_baud_rate[1]; +} + +void tmp94c241_device::br1cr_w(uint8_t data) +{ + m_baud_rate[1] = data; +} + +uint8_t tmp94c241_device::ode_r() +{ + return m_od_enable; +} + +void tmp94c241_device::ode_w(uint8_t data) +{ + m_od_enable = data; +} + +uint8_t tmp94c241_device::admod1_r() +{ + return m_ad_mode1; +} + +void tmp94c241_device::admod1_w(uint8_t data) +{ + // Preserve read-only bits + data = ( m_ad_mode1 & 0xc0 ) | ( data & 0x34 ); + + // Check for A/D conversion start + if (data & 0x04) + { + data &= ~0x04; + data |= 0x40; + + switch ((m_ad_mode2 >> 4) & 3) + { + case 0: m_ad_cycles_left = 160; break; + case 1: m_ad_cycles_left = 320; break; + case 2: m_ad_cycles_left = 640; break; + case 3: m_ad_cycles_left = 1280; break; + } + } + + m_ad_mode1 = data; +} + +uint8_t tmp94c241_device::admod2_r() +{ + return m_ad_mode2; +} + +void tmp94c241_device::admod2_w(uint8_t data) +{ + m_ad_mode2 = data; +} + +uint8_t tmp94c241_device::adreg_r(offs_t offset) +{ + if (BIT(offset, 0)) + return m_ad_result[offset >> 1] >> 2; + else + return m_ad_result[offset >> 1] << 6 | 0x3f; +} + +uint8_t tmp94c241_device::dadrv_r() +{ + return m_da_drive; +} + +void tmp94c241_device::dadrv_w(uint8_t data) +{ + m_da_drive = data; +} + +void tmp94c241_device::dareg_w(offs_t offset, uint8_t data) +{ +} + +template +void tmp94c241_device::port_w(uint8_t data) +{ + m_port_latch[P] = data; + m_port_write[P](0, data, 0xff); +} + +template +uint8_t tmp94c241_device::port_r() +{ + return m_port_read[P](0); +} + +template +void tmp94c241_device::port_cr_w(uint8_t data) +{ + m_port_control[P] = data; +} + +template +void tmp94c241_device::port_fc_w(uint8_t data) +{ + m_port_function[P] = data; +} + +//************************************************************************** +// INTERNAL REGISTERS +//************************************************************************** + +//------------------------------------------------- +// internal_mem - memory map for internal RAM and +// I/O registers +//------------------------------------------------- + +void tmp94c241_device::internal_mem(address_map &map) +{ + map(0x000000, 0x000000).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x000002, 0x000002).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x000003, 0x000003).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x000004, 0x000004).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x000006, 0x000006).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x000007, 0x000007).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x000008, 0x000008).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x00000a, 0x00000a).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x00000b, 0x00000b).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x00000c, 0x00000c).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x00000e, 0x00000e).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x00000f, 0x00000f).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x000010, 0x000010).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x000012, 0x000012).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x000013, 0x000013).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x000014, 0x000014).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x000016, 0x000016).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x000017, 0x000017).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x000018, 0x000018).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x00001a, 0x00001a).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x00001b, 0x00001b).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x00001c, 0x00001c).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x00001e, 0x00001e).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x00001f, 0x00001f).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x000020, 0x000020).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x000022, 0x000022).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x000023, 0x000023).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x000028, 0x000028).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x00002b, 0x00002b).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x00002c, 0x00002c).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x00002f, 0x00002f).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x000030, 0x000030).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x000032, 0x000032).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x000033, 0x000033).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x000034, 0x000034).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x000036, 0x000036).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x000037, 0x000037).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x000038, 0x000038).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x00003a, 0x00003a).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x00003b, 0x00003b).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x00003c, 0x00003c).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x00003e, 0x00003e).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x00003f, 0x00003f).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x000040, 0x000040).r(FUNC(tmp94c241_device::port_r)); + map(0x000044, 0x000044).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x000046, 0x000046).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x000047, 0x000047).w(FUNC(tmp94c241_device::port_fc_w)); + map(0x000068, 0x000068).rw(FUNC(tmp94c241_device::port_r), FUNC(tmp94c241_device::port_w)); + map(0x00006a, 0x00006a).w(FUNC(tmp94c241_device::port_cr_w)); + map(0x000080, 0x000080).rw(FUNC(tmp94c241_device::t8run_r), FUNC(tmp94c241_device::t8run_w)); + map(0x000081, 0x000081).rw(FUNC(tmp94c241_device::trdc_r), FUNC(tmp94c241_device::trdc_w)); + map(0x000082, 0x000082).rw(FUNC(tmp94c241_device::t02ffcr_r), FUNC(tmp94c241_device::t02ffcr_w)); + map(0x000084, 0x000084).rw(FUNC(tmp94c241_device::t01mod_r), FUNC(tmp94c241_device::t01mod_w)); + map(0x000085, 0x000085).rw(FUNC(tmp94c241_device::t23mod_r), FUNC(tmp94c241_device::t23mod_w)); + map(0x000088, 0x000089).w(FUNC(tmp94c241_device::treg01_w)); + map(0x00008a, 0x00008b).w(FUNC(tmp94c241_device::treg23_w)); + map(0x000090, 0x000093).w(FUNC(tmp94c241_device::treg45_w)); + map(0x000094, 0x000097).r(FUNC(tmp94c241_device::cap45_r)); + map(0x000098, 0x000098).rw(FUNC(tmp94c241_device::t4mod_r), FUNC(tmp94c241_device::t4mod_w)); + map(0x000099, 0x000099).rw(FUNC(tmp94c241_device::t4ffcr_r), FUNC(tmp94c241_device::t4ffcr_w)); + map(0x00009e, 0x00009e).rw(FUNC(tmp94c241_device::t16run_r), FUNC(tmp94c241_device::t16run_w)); + map(0x0000a0, 0x0000a3).w(FUNC(tmp94c241_device::treg67_w)); + map(0x0000a4, 0x0000a7).r(FUNC(tmp94c241_device::cap67_r)); + map(0x0000a8, 0x0000a8).rw(FUNC(tmp94c241_device::t6mod_r), FUNC(tmp94c241_device::t6mod_w)); + map(0x0000a9, 0x0000a9).rw(FUNC(tmp94c241_device::t6ffcr_r), FUNC(tmp94c241_device::t6ffcr_w)); + map(0x0000b0, 0x0000b3).w(FUNC(tmp94c241_device::treg89_w)); + map(0x0000b4, 0x0000b7).r(FUNC(tmp94c241_device::cap89_r)); + map(0x0000b8, 0x0000b8).rw(FUNC(tmp94c241_device::t8mod_r), FUNC(tmp94c241_device::t8mod_w)); + map(0x0000b9, 0x0000b9).rw(FUNC(tmp94c241_device::t8ffcr_r), FUNC(tmp94c241_device::t8ffcr_w)); + map(0x0000c0, 0x0000c3).w(FUNC(tmp94c241_device::tregab_w)); + map(0x0000c4, 0x0000c7).r(FUNC(tmp94c241_device::capab_r)); + map(0x0000c8, 0x0000c8).rw(FUNC(tmp94c241_device::tamod_r), FUNC(tmp94c241_device::tamod_w)); + map(0x0000c9, 0x0000c9).rw(FUNC(tmp94c241_device::taffcr_r), FUNC(tmp94c241_device::taffcr_w)); + map(0x0000d0, 0x0000d0).rw(FUNC(tmp94c241_device::sc0buf_r), FUNC(tmp94c241_device::sc0buf_w)); + map(0x0000d1, 0x0000d1).rw(FUNC(tmp94c241_device::sc0cr_r), FUNC(tmp94c241_device::sc0cr_w)); + map(0x0000d2, 0x0000d2).rw(FUNC(tmp94c241_device::sc0mod_r), FUNC(tmp94c241_device::sc0mod_w)); + map(0x0000d3, 0x0000d3).rw(FUNC(tmp94c241_device::br0cr_r), FUNC(tmp94c241_device::br0cr_w)); + map(0x0000d4, 0x0000d4).rw(FUNC(tmp94c241_device::sc1buf_r), FUNC(tmp94c241_device::sc1buf_w)); + map(0x0000d5, 0x0000d5).rw(FUNC(tmp94c241_device::sc1cr_r), FUNC(tmp94c241_device::sc1cr_w)); + map(0x0000d6, 0x0000d6).rw(FUNC(tmp94c241_device::sc1mod_r), FUNC(tmp94c241_device::sc1mod_w)); + map(0x0000d7, 0x0000d7).rw(FUNC(tmp94c241_device::br1cr_r), FUNC(tmp94c241_device::br1cr_w)); + map(0x0000e0, 0x0000f0).rw(FUNC(tmp94c241_device::inte_r), FUNC(tmp94c241_device::inte_w)); + map(0x0000f6, 0x0000f6).w(FUNC(tmp94c241_device::iimc_w)); + map(0x0000f7, 0x0000f7).rw(FUNC(tmp94c241_device::intnmwdt_r), FUNC(tmp94c241_device::intnmwdt_w)); + map(0x0000f8, 0x0000f8).w(FUNC(tmp94c241_device::intclr_w)); + map(0x000100, 0x000103).w(FUNC(tmp94c241_device::dmav_w)); + map(0x000110, 0x000110).rw(FUNC(tmp94c241_device::wdmod_r), FUNC(tmp94c241_device::wdmod_w)); + map(0x000111, 0x000111).w(FUNC(tmp94c241_device::wdcr_w)); + map(0x000120, 0x000127).r(FUNC(tmp94c241_device::adreg_r)); + map(0x000128, 0x000128).rw(FUNC(tmp94c241_device::admod1_r), FUNC(tmp94c241_device::admod1_w)); + map(0x000129, 0x000129).rw(FUNC(tmp94c241_device::admod2_r), FUNC(tmp94c241_device::admod2_w)); + map(0x000130, 0x000131).w(FUNC(tmp94c241_device::dareg_w)); + map(0x000132, 0x000132).rw(FUNC(tmp94c241_device::dadrv_r), FUNC(tmp94c241_device::dadrv_w)); + map(0x000140, 0x000141).w(FUNC(tmp94c241_device::b0cs_w)); + map(0x000142, 0x000142).rw(FUNC(tmp94c241_device::mamr0_r), FUNC(tmp94c241_device::mamr0_w)); + map(0x000143, 0x000143).rw(FUNC(tmp94c241_device::msar0_r), FUNC(tmp94c241_device::msar0_w)); + map(0x000144, 0x000145).w(FUNC(tmp94c241_device::b1cs_w)); + map(0x000146, 0x000146).rw(FUNC(tmp94c241_device::mamr1_r), FUNC(tmp94c241_device::mamr1_w)); + map(0x000147, 0x000147).rw(FUNC(tmp94c241_device::msar1_r), FUNC(tmp94c241_device::msar1_w)); + map(0x000148, 0x000149).w(FUNC(tmp94c241_device::b2cs_w)); + map(0x00014a, 0x00014a).rw(FUNC(tmp94c241_device::mamr2_r), FUNC(tmp94c241_device::mamr2_w)); + map(0x00014b, 0x00014b).rw(FUNC(tmp94c241_device::msar2_r), FUNC(tmp94c241_device::msar2_w)); + map(0x00014c, 0x00014d).w(FUNC(tmp94c241_device::b3cs_w)); + map(0x00014e, 0x00014e).rw(FUNC(tmp94c241_device::mamr3_r), FUNC(tmp94c241_device::mamr3_w)); + map(0x00014f, 0x00014f).rw(FUNC(tmp94c241_device::msar3_r), FUNC(tmp94c241_device::msar3_w)); + map(0x000150, 0x000151).w(FUNC(tmp94c241_device::b4cs_w)); + map(0x000152, 0x000152).rw(FUNC(tmp94c241_device::mamr4_r), FUNC(tmp94c241_device::mamr4_w)); + map(0x000153, 0x000153).rw(FUNC(tmp94c241_device::msar4_r), FUNC(tmp94c241_device::msar4_w)); + map(0x000154, 0x000155).w(FUNC(tmp94c241_device::b5cs_w)); + map(0x000156, 0x000156).rw(FUNC(tmp94c241_device::mamr5_r), FUNC(tmp94c241_device::mamr5_w)); + map(0x000157, 0x000157).rw(FUNC(tmp94c241_device::msar5_r), FUNC(tmp94c241_device::msar5_w)); + map(0x000400, 0x000bff).ram(); +} + +//************************************************************************** +// EXECUTION CALLBACKS +//************************************************************************** + +//------------------------------------------------- +// tlcs900_check_hdma - +//------------------------------------------------- + +void tmp94c241_device::tlcs900_check_hdma() +{ +} + + +//------------------------------------------------- +// tlcs900_check_irqs - +//------------------------------------------------- + +void tmp94c241_device::tlcs900_check_irqs() +{ + int irq_vectors[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; + int level = 0; + int irq = -1; + int i; + + /* Check for NMI */ + if ( m_nmi_state == ASSERT_LINE ) + { + m_xssp.d -= 4; + WRMEML( m_xssp.d, m_pc.d ); + m_xssp.d -= 2; + WRMEMW( m_xssp.d, m_sr.w.l ); + m_pc.d = RDMEML( 0xffff00 + 0x20 ); + m_cycles += 18; + m_prefetch_clear = true; + m_halted = 0; + m_nmi_state = CLEAR_LINE; + return; + } + + /* Check regular irqs */ + // the smaller the vector value, the higher the priority + for( i = NUM_MASKABLE_IRQS - 1; i >= 0; i-- ) + { + if ( m_int_reg[tmp94c241_irq_vector_map[i].reg] & tmp94c241_irq_vector_map[i].iff ) + { + switch( tmp94c241_irq_vector_map[i].iff ) + { + case 0x80: + irq_vectors[ ( m_int_reg[ tmp94c241_irq_vector_map[i].reg ] >> 4 ) & 0x07 ] = i; + break; + case 0x08: + irq_vectors[ m_int_reg[ tmp94c241_irq_vector_map[i].reg ] & 0x07 ] = i; + break; + } + } + } + + /* Check highest allowed priority irq */ + for( i = std::max( 1, ( ( m_sr.b.h & 0x70 ) >> 4 ) ); i < 7; i++ ) + { + if ( irq_vectors[i] >= 0 ) + { + irq = irq_vectors[i]; + level = i + 1; + } + } + + /* Take irq */ + if ( irq >= 0 ) + { + uint8_t vector = tmp94c241_irq_vector_map[irq].vector; + + m_xssp.d -= 4; + WRMEML( m_xssp.d, m_pc.d ); + m_xssp.d -= 2; + WRMEMW( m_xssp.d, m_sr.w.l ); + + /* Mask off any lower priority interrupts */ + m_sr.b.h = ( m_sr.b.h & 0x8f ) | ( level << 4 ); + + m_pc.d = RDMEML( 0xffff00 + vector ); + + m_cycles += 18; + m_prefetch_clear = true; + + m_halted = 0; + + /* Clear taken IRQ */ + m_int_reg[ tmp94c241_irq_vector_map[irq].reg ] &= ~ tmp94c241_irq_vector_map[irq].iff; + } +} + + +//------------------------------------------------- +// tlcs900_handle_ad - +//------------------------------------------------- + +void tmp94c241_device::tlcs900_handle_ad() +{ +} + + +//------------------------------------------------- +// tlcs900_handle_timers - +//------------------------------------------------- + +void tmp94c241_device::tlcs900_handle_timers() +{ + uint32_t old_pre = m_timer_pre; + + if ( PRESCALER_IS_ACTIVE ) + m_timer_pre += m_cycles; + + /* Timer 0 */ + if ( TIMER_0_IS_RUNNING ) + { + switch( T0_INPUT_CLOCK ) + { + case 0: /* TIO */ + break; + case 1: /* T1 */ + TIMER_CHANGE_0 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 2: /* T4 */ + TIMER_CHANGE_0 += ( m_timer_pre >> 5 ) - ( old_pre >> 5 ); + break; + case 3: /* T16 */ + TIMER_CHANGE_0 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + } + + for( ; TIMER_CHANGE_0 > 0; TIMER_CHANGE_0-- ) + { + UPCOUNTER_0++; + if ( UPCOUNTER_0 == SFR_TREG0 ) + { + if ( TO1_OPERATING_MODE == MODE_8BIT_TIMER ) + TIMER_CHANGE_1++; + + if ( (m_ffcr[0] & 0x03) == 0b10 ) + change_timer_flipflop( 1, FF_INVERT ); + + /* In 16bit timer mode the timer should not be reset */ + if ( TO1_OPERATING_MODE != MODE_16BIT_TIMER ) + { + UPCOUNTER_0 = 0; + m_int_reg[INTET01] |= 0x08; + m_check_irqs = 1; + } + } + } + } + + /* Timer 1 */ + if ( TIMER_1_IS_RUNNING ) + { + switch( T1_INPUT_CLOCK ) + { + case 0x00: /* TO0TRG */ + break; + case 0x01: /* T1 */ + TIMER_CHANGE_1 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 0x02: /* T16 */ + TIMER_CHANGE_1 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + case 0x03: /* T256 */ + TIMER_CHANGE_1 += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); + break; + } + + for( ; TIMER_CHANGE_1 > 0; TIMER_CHANGE_1-- ) + { + UPCOUNTER_1 += 1; + if ( UPCOUNTER_1 == SFR_TREG1 ) + { + UPCOUNTER_1 = 0; + m_int_reg[INTET01] |= 0x80; + m_check_irqs = 1; + + if ( (m_ffcr[0] & 0x03) == 0b11 ) + change_timer_flipflop( 1, FF_INVERT ); + + /* In 16bit timer mode also reset timer 0 */ + if ( TO1_OPERATING_MODE == MODE_16BIT_TIMER ) + UPCOUNTER_1 = 0; + } + } + } + + /* Timer 2 */ + if ( TIMER_2_IS_RUNNING ) + { + switch( T2_INPUT_CLOCK ) + { + case 0: /* invalid */ + case 1: /* T1 */ + TIMER_CHANGE_2 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 2: /* T4 */ + TIMER_CHANGE_2 += ( m_timer_pre >> 5 ) - ( old_pre >> 5 ); + break; + case 3: /* T16 */ + TIMER_CHANGE_2 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + } + + for( ; TIMER_CHANGE_2 > 0; TIMER_CHANGE_2-- ) + { + UPCOUNTER_2++; + if ( UPCOUNTER_2 == SFR_TREG2 ) + { + if ( T23_OPERATING_MODE == MODE_8BIT_TIMER ) + TIMER_CHANGE_3++; + + if ( ((m_ffcr[0] & 0x30) >> 4) == 0b10 ) + change_timer_flipflop( 3, FF_INVERT ); + + /* In 16bit timer mode the timer should not be reset */ + if ( T23_OPERATING_MODE != MODE_16BIT_TIMER ) + { + UPCOUNTER_2 = 0; + m_int_reg[INTET23] |= 0x08; + m_check_irqs = 1; + } + } + } + } + + /* Timer 3 */ + if ( TIMER_3_IS_RUNNING ) + { + switch( T3_INPUT_CLOCK ) + { + case 0: /* TO2TRG */ + break; + case 1: /* T1 */ + TIMER_CHANGE_3 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 2: /* T16 */ + TIMER_CHANGE_3 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + case 3: /* T256 */ + TIMER_CHANGE_3 += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); + break; + } + + for( ; TIMER_CHANGE_3 > 0; TIMER_CHANGE_3-- ) + { + UPCOUNTER_3++; + if ( UPCOUNTER_3 == SFR_TREG3 ) + { + UPCOUNTER_3 = 0; + m_int_reg[INTET23] |= 0x80; + m_check_irqs = 1; + + if ( ((m_ffcr[0] & 0x30) >> 4) == 0b11 ) + change_timer_flipflop( 3, FF_INVERT ); + + /* In 16bit timer mode also reset timer 2 */ + if ( T23_OPERATING_MODE == MODE_16BIT_TIMER ) + UPCOUNTER_2 = 0; + } + } + } + + /* Timer 4 */ + if ( TIMER_4_IS_RUNNING ) + { + switch( T4_INPUT_CLOCK ) + { + case 0x00: /* TIA */ + // TODO: implement-me! + break; + case 0x01: /* T1 */ + TIMER_CHANGE_4 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 0x02: /* T4 */ + TIMER_CHANGE_4 += ( m_timer_pre >> 5 ) - ( old_pre >> 5 ); + break; + case 0x03: /* T16 */ + TIMER_CHANGE_4 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + } + + for( ; TIMER_CHANGE_4 > 0; TIMER_CHANGE_4-- ) + { + UPCOUNTER_4++; + if ( ((UPCOUNTER_4 == SFR_TREG5) && EQ5T4) || + ((UPCOUNTER_4 == SFR_TREG4) && EQ4T4) ) + { + change_timer_flipflop( 4, FF_INVERT ); + UPCOUNTER_4 = 0; + m_int_reg[INTET45] |= 0x08; + m_check_irqs = 1; + } + } + } + + + /* Timer 6 */ + if ( TIMER_6_IS_RUNNING ) + { + switch( T6_INPUT_CLOCK ) + { + case 0: /* TIA */ + // TODO: implement-me! + break; + case 1: /* T1 */ + TIMER_CHANGE_6 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 2: /* T4 */ + TIMER_CHANGE_6 += ( m_timer_pre >> 5 ) - ( old_pre >> 5 ); + break; + case 3: /* T16 */ + TIMER_CHANGE_6 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + } + + for( ; TIMER_CHANGE_6 > 0; TIMER_CHANGE_6-- ) + { + UPCOUNTER_6++; + if ( ((UPCOUNTER_6 == SFR_TREG7) && EQ7T6) || + ((UPCOUNTER_6 == SFR_TREG6) && EQ6T6) ) + { + change_timer_flipflop( 6, FF_INVERT ); + UPCOUNTER_6 = 0; + m_int_reg[INTET67] |= 0x08; + m_check_irqs = 1; + } + } + } + + + /* Timer 8 */ + if ( TIMER_8_IS_RUNNING ) + { + switch( T8_INPUT_CLOCK ) + { + case 0x00: /* TIA */ + // TODO: implement-me! + break; + case 0x01: /* T1 */ + TIMER_CHANGE_8 += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 0x02: /* T4 */ + TIMER_CHANGE_8 += ( m_timer_pre >> 5 ) - ( old_pre >> 5 ); + break; + case 0x03: /* T16 */ + TIMER_CHANGE_8 += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + } + + for( ; TIMER_CHANGE_8 > 0; TIMER_CHANGE_8-- ) + { + UPCOUNTER_8++; + if ( ((UPCOUNTER_8 == SFR_TREG9) && EQ9T8) || + ((UPCOUNTER_8 == SFR_TREG8) && EQ8T8) ) + { + change_timer_flipflop( 8, FF_INVERT ); + UPCOUNTER_8 = 0; + m_int_reg[INTET89] |= 0x08; + m_check_irqs = 1; + } + } + } + + + /* Timer A */ + if ( TIMER_A_IS_RUNNING ) + { + switch( TA_INPUT_CLOCK ) + { + case 0: /* TIA */ + // TODO: implement-me! + break; + case 1: /* T1 */ + TIMER_CHANGE_A += ( m_timer_pre >> 3 ) - ( old_pre >> 3 ); + break; + case 2: /* T4 */ + TIMER_CHANGE_A += ( m_timer_pre >> 5 ) - ( old_pre >> 5 ); + break; + case 3: /* T16 */ + TIMER_CHANGE_A += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + } + + for( ; TIMER_CHANGE_A > 0; TIMER_CHANGE_A-- ) + { + UPCOUNTER_A++; + if ( ((UPCOUNTER_A == SFR_TREGA) && EQATA) || + ((UPCOUNTER_A == SFR_TREGB) && EQBTA) ) + { + change_timer_flipflop( 0xa, FF_INVERT ); + UPCOUNTER_A = 0; + m_int_reg[INTETAB] |= 0x08; + m_check_irqs = 1; + } + } + } + + m_timer_pre &= 0xffffff; +} + + +//------------------------------------------------- +// execute_set_input - called when a synchronized +// input is changed +//------------------------------------------------- + +void tmp94c241_device::execute_set_input(int input, int level) +{ + switch( input ) + { + case INPUT_LINE_NMI: + case TLCS900_NMI: + if ( m_level[TLCS900_NMI] == CLEAR_LINE && level == ASSERT_LINE ) + { + m_nmi_state = level; + } + m_level[TLCS900_NMI] = level; + break; + + case TLCS900_INTWD: + break; + + case TLCS900_INT0: + /* Is INT0 functionality enabled? */ + if (m_iimc & 0x04) + { + if (m_iimc & 0x02) + { + /* Rising edge detect */ + if (m_level[TLCS900_INT0] == CLEAR_LINE && level == ASSERT_LINE) + { + /* Leave HALT state */ + m_halted = 0; + m_int_reg[INTE0AD] |= 0x08; + } + } + else + { + /* Level detect */ + if (level == ASSERT_LINE) + m_int_reg[INTE0AD] |= 0x08; + else + m_int_reg[INTE0AD] &= ~ 0x08; + } + } + m_level[TLCS900_INT0] = level; + break; + + case TLCS900_INT4: + if (m_level[TLCS900_INT4] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[INTE45] |= 0x08; + } + else if (m_level[TLCS900_INT4] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[INTE45] &= ~0x08; + } + m_level[TLCS900_INT4] = level; + break; + + case TLCS900_INT5: + if (m_level[TLCS900_INT5] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[INTE45] |= 0x80; + } + else if (m_level[TLCS900_INT5] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[INTE45] &= ~0x80; + } + m_level[TLCS900_INT5] = level; + break; + + case TLCS900_INT6: + if (m_level[TLCS900_INT6] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[INTE67] |= 0x08; + } + else if (m_level[TLCS900_INT6] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[INTE67] &= ~0x08; + } + m_level[TLCS900_INT3] = level; + break; + + case TLCS900_INT7: + if (m_level[TLCS900_INT7] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[INTE67] |= 0x80; + } + else if (m_level[TLCS900_INT7] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[INTE67] &= ~0x80; + } + m_level[TLCS900_INT7] = level; + break; + + case TLCS900_INT8: + if (m_level[TLCS900_INT8] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[INTE89] |= 0x08; + } + else if (m_level[TLCS900_INT8] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[INTE89] &= ~0x08; + } + m_level[TLCS900_INT8] = level; + break; + + case TLCS900_INT9: + if (m_level[TLCS900_INT9] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[INTE89] |= 0x80; + } + else if (m_level[TLCS900_INT9] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[INTE89] &= ~0x80; + } + m_level[TLCS900_INT9] = level; + break; + + case TLCS900_INTA: + if (m_level[TLCS900_INTA] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[INTEAB] |= 0x08; + } + else if (m_level[TLCS900_INTA] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[INTEAB] &= ~0x08; + } + m_level[TLCS900_INTA] = level; + break; + + case TLCS900_INTB: + if (m_level[TLCS900_INTB] == CLEAR_LINE && level == ASSERT_LINE) + { + m_int_reg[INTEAB] |= 0x80; + } + else if (m_level[TLCS900_INTB] == ASSERT_LINE && level == CLEAR_LINE) + { + m_int_reg[INTEAB] &= ~0x80; + } + m_level[TLCS900_INTB] = level; + break; + } + m_check_irqs = 1; +} + +std::pair const tmp94c241_syms[] = { + /* TLCS-900/H2 type 8 bit I/O: */ + { 0x00, "P0" }, { 0x02, "P0CR" }, { 0x03, "P0FC" }, + { 0x04, "P1" }, { 0x06, "P1CR" }, { 0x07, "P1FC" }, + { 0x08, "P2" }, { 0x0a, "P2CR" }, { 0x0b, "P2FC" }, + { 0x0c, "P3" }, { 0x0e, "P3CR" }, { 0x0f, "P3FC" }, + { 0x10, "P4" }, { 0x12, "P4CR" }, { 0x13, "P4FC" }, + { 0x14, "P5" }, { 0x16, "P5CR" }, { 0x17, "P5FC" }, + { 0x18, "P6" }, { 0x1a, "P6CR" }, { 0x1b, "P6FC" }, + { 0x1c, "P7" }, { 0x1e, "P7CR" }, { 0x1f, "P7FC" }, + { 0x20, "P8" }, { 0x22, "P8CR" }, { 0x23, "P8FC" }, + { 0x28, "PA" }, { 0x2b, "PAFC" }, + { 0x2c, "PB" }, { 0x2f, "PBFC" }, + { 0x30, "PC" }, { 0x32, "PCCR" }, { 0x33, "PCFC" }, + { 0x34, "PD" }, { 0x36, "PDCR" }, { 0x37, "PDFC" }, + { 0x38, "PE" }, { 0x3a, "PECR" }, { 0x3b, "PEFC" }, + { 0x3c, "PF" }, { 0x3e, "PFCR" }, { 0x3f, "PFFC" }, + { 0x40, "PG" }, + { 0x44, "PH" }, { 0x46, "PHCR" }, { 0x47, "PHFC" }, + { 0x68, "PZ" }, { 0x6a, "PZCR" }, + + /* TLCS-90 type I/O: */ + { 0x80, "T8RUN" }, { 0x81, "TRDC" }, { 0x82, "T02FFCR" }, + { 0x84, "T01MOD" }, { 0x85, "T23MOD" }, + { 0x88, "TREG0" }, { 0x89, "TREG1" }, { 0x8a, "TREG2" }, { 0x8b, "TREG3" }, + { 0x90, "TREG4L" }, { 0x91, "TREG4H" }, { 0x92, "TREG5L" }, { 0x93, "TREG5H" }, + { 0x94, "CAP4L" }, { 0x95, "CAP4H" }, { 0x96, "CAP5L" }, { 0x97, "CAP5H" }, + { 0x98, "T4MOD" }, { 0x99, "T4FFCR" }, { 0x9e, "T16RUN" }, { 0x9f, "T16CR" }, + { 0xa0, "TREG6L" }, { 0xa1, "TREG6H" }, { 0xa2, "TREG7L" }, { 0xa3, "TREG7H" }, + { 0xa4, "CAP6L" }, { 0xa5, "CAP6H" }, { 0xa6, "CAP7L" }, { 0xa7, "CAP7H" }, + { 0xa8, "T6MOD" }, { 0xa9, "T6FFCR" }, + { 0xb0, "TREG8L" }, { 0xb1, "TREG8H" }, { 0xb2, "TREG9L" }, { 0xb3, "TREG9H" }, + { 0xb4, "CAP8L" }, { 0xb5, "CAP8H" }, { 0xb6, "CAP9L" }, { 0xb7, "CAP9H" }, + { 0xb8, "T8MOD" }, { 0xb9, "T8FFCR" }, + { 0xc0, "TREGAL" }, { 0xc1, "TREGAH" }, { 0xc2, "TREGBL" }, { 0xc3, "TREGBH" }, + { 0xc4, "CAPAL" }, { 0xc5, "CAPAH" }, { 0xc6, "CAPBL" }, { 0xc7, "CAPBH" }, + { 0xc8, "TAMOD" }, { 0xc9, "TAFFCR" }, + { 0xd0, "SC0BUF" }, { 0xd1, "SC0CR" }, { 0xd2, "SC0MOD" }, { 0xd3, "BR0CR" }, + { 0xd4, "SC1BUF" }, { 0xd5, "SC1CR" }, { 0xd6, "SC1MOD" }, { 0xd7, "BR1CR" }, + + /* TLCS-900/H2 type 8 bit I/O: */ + { 0xe0, "INTE45" }, { 0xe1, "INTE67" }, { 0xe2, "INTE89" }, { 0xe3, "INTEAB" }, + { 0xe4, "INTET01" }, { 0xe5, "INTET23" }, { 0xe6, "INTET45" }, { 0xe7, "INTET67" }, + { 0xe8, "INTET89" }, { 0xe9, "INTETAB" }, { 0xea, "INTES0" }, { 0xeb, "INTES1" }, + { 0xec, "INTETC01" }, { 0xed, "INTETC23" }, + { 0xee, "INTETC45" }, { 0xef, "INTETC67" }, + { 0xf0, "INTE0AD" }, { 0xf6, "IIMC" }, { 0xf7, "INTNMWDT" }, { 0xf8, "INTCLR" }, + { 0x100, "DMA0V" }, { 0x101, "DMA1V" }, { 0x102, "DMA2V" }, { 0x103, "DMA3V" }, + { 0x104, "DMA4V" }, { 0x105, "DMA5V" }, { 0x106, "DMA6V" }, { 0x107, "DMA7V" }, + { 0x108, "DMAB" }, { 0x109, "DMAR" }, { 0x10a, "CLKMOD" }, + + /* TLCS-90 type I/O: */ + { 0x110, "WDMOD" }, { 0x111, "WDCR" }, + { 0x120, "ADREG04L" }, { 0x121, "ADREG04H" }, + { 0x122, "ADREG15L" }, { 0x123, "ADREG15H" }, + { 0x124, "ADREG26L" }, { 0x125, "ADREG26H" }, + { 0x126, "ADREG37L" }, { 0x127, "ADREG37H" }, + { 0x128, "ADMOD1" }, { 0x129, "ADMOD2" }, + { 0x130, "DAREG0" }, { 0x131, "DAREG1" }, + { 0x132, "DADRV" }, + + /* TLCS-900/H2 type 8 bit I/O: */ + { 0x140, "B0CSL" }, { 0x141, "B0CSH" }, { 0x142, "MAMR0" }, { 0x143, "MSAR0" }, + { 0x144, "B1CSL" }, { 0x145, "B1CSH" }, { 0x146, "MAMR1" }, { 0x147, "MSAR1" }, + { 0x148, "B2CSL" }, { 0x149, "B2CSH" }, { 0x14a, "MAMR2" }, { 0x14b, "MSAR2" }, + { 0x14c, "B3CSL" }, { 0x14d, "B3CSH" }, { 0x14e, "MAMR3" }, { 0x14f, "MSAR3" }, + { 0x150, "B4CSL" }, { 0x151, "B4CSH" }, { 0x152, "MAMR4" }, { 0x153, "MSAR4" }, + { 0x154, "B5CSL" }, { 0x155, "B5CSH" }, { 0x156, "MAMR5" }, { 0x157, "MSAR5" }, + { 0x160, "DRAM0CRL" }, { 0x161, "DRAM0CRH" }, + { 0x162, "DRAM1CRL" }, { 0x163, "DRAM1CRH" }, + { 0x164, "DRAM0REF" }, { 0x165, "DRAM1REF" }, + { 0x166, "PMEMCR" }, +}; + +std::unique_ptr tmp94c241_device::create_disassembler() +{ + return std::make_unique(tmp94c241_syms); +} + diff --git a/src/devices/cpu/tlcs900/tmp94c241.h b/src/devices/cpu/tlcs900/tmp94c241.h new file mode 100644 index 0000000000000..1fb5574cd780b --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp94c241.h @@ -0,0 +1,282 @@ +// license:BSD-3-Clause +// copyright-holders:AJR,Wilbert Pol,Felipe Sanches +/**************************************************************************** + + Toshiba TMP94C241 microcontroller + +****************************************************************************/ + +#ifndef MAME_CPU_TLCS900_TMP94C241_H +#define MAME_CPU_TLCS900_TMP94C241_H + +#pragma once + +#include "tlcs900.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> tmp94c241_device + +class tmp94c241_device : public tlcs900h_device +{ + static constexpr uint8_t PORT_0 = 0; // 8 bit I/O. Shared with d0-d7 + static constexpr uint8_t PORT_1 = 1; // 8 bit I/O. Shared with d8-d15 + static constexpr uint8_t PORT_2 = 2; // 8 bit I/O. Shared with d16-d23 + static constexpr uint8_t PORT_3 = 3; // 8 bit I/O. Shared with d24-d31 + static constexpr uint8_t PORT_4 = 4; // 8 bit I/O. Shared with a0-a7 + static constexpr uint8_t PORT_5 = 5; // 8 bit I/O. Shared with a8-a15 + static constexpr uint8_t PORT_6 = 6; // 8 bit I/O. Shared with a16-a23 + static constexpr uint8_t PORT_7 = 7; // 8 bit I/O. Shared with external memory & bus signals + static constexpr uint8_t PORT_8 = 8; // 7 bit I/O. Shared with chip-select signals + static constexpr uint8_t PORT_A = 9; // 5 bit I/O. Shared with external DRAM (channel 0) + static constexpr uint8_t PORT_B = 10; // 5 bit I/O. Shared with external DRAM (channel 1) + static constexpr uint8_t PORT_C = 11; // 2 bit I/O. Shared with outputs for 8-bit or 16-bit timers + static constexpr uint8_t PORT_D = 12; // 6 bit I/O. Shared with 16-bit timer I/O and interrupt input + static constexpr uint8_t PORT_E = 13; // 6 bit I/O. Shared with 8-bit or 16-bit timer output and interrupt input + static constexpr uint8_t PORT_F = 14; // 6 bit I/O. Shared with I/O functions of serial interface + static constexpr uint8_t PORT_G = 15; // 8 bit input-only. Shared with AD converter. + static constexpr uint8_t PORT_H = 16; // 5 bit I/O. Shared with /INT0 and micro DMA + static constexpr uint8_t PORT_Z = 17; // 8 bit I/O. + static constexpr uint8_t NUM_PORTS = 18; + +public: + // device type constructor + tmp94c241_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // configuration helpers + auto port0_read() { return m_port_read[PORT_0].bind(); } + auto port0_write() { return m_port_write[PORT_0].bind(); } + auto port1_read() { return m_port_read[PORT_1].bind(); } + auto port1_write() { return m_port_write[PORT_1].bind(); } + auto port2_read() { return m_port_read[PORT_2].bind(); } + auto port2_write() { return m_port_write[PORT_2].bind(); } + auto port3_read() { return m_port_read[PORT_3].bind(); } + auto port3_write() { return m_port_write[PORT_3].bind(); } + auto port4_read() { return m_port_read[PORT_4].bind(); } + auto port4_write() { return m_port_write[PORT_4].bind(); } + auto port5_read() { return m_port_read[PORT_5].bind(); } + auto port5_write() { return m_port_write[PORT_5].bind(); } + auto port6_read() { return m_port_read[PORT_6].bind(); } + auto port6_write() { return m_port_write[PORT_6].bind(); } + auto port7_read() { return m_port_read[PORT_7].bind(); } + auto port7_write() { return m_port_write[PORT_7].bind(); } + auto port8_read() { return m_port_read[PORT_8].bind(); } + auto port8_write() { return m_port_write[PORT_8].bind(); } + auto porta_read() { return m_port_read[PORT_A].bind(); } + auto porta_write() { return m_port_write[PORT_A].bind(); } + auto portb_read() { return m_port_read[PORT_B].bind(); } + auto portb_write() { return m_port_write[PORT_B].bind(); } + auto portc_read() { return m_port_read[PORT_C].bind(); } + auto portc_write() { return m_port_write[PORT_C].bind(); } + auto portd_read() { return m_port_read[PORT_D].bind(); } + auto portd_write() { return m_port_write[PORT_D].bind(); } + auto porte_read() { return m_port_read[PORT_E].bind(); } + auto porte_write() { return m_port_write[PORT_E].bind(); } + auto portf_read() { return m_port_read[PORT_F].bind(); } + auto portf_write() { return m_port_write[PORT_F].bind(); } + auto portg_read() { return m_port_read[PORT_G].bind(); } + auto porth_read() { return m_port_read[PORT_H].bind(); } + auto porth_write() { return m_port_write[PORT_H].bind(); } + auto portz_read() { return m_port_read[PORT_Z].bind(); } + auto portz_write() { return m_port_write[PORT_Z].bind(); } + +protected: + // device_t implementation + virtual void device_config_complete() override; + virtual void device_start() override; + virtual void device_reset() override; + + // device_execute_interface overrides + virtual void execute_set_input(int inputnum, int state) override; + + // tlcs900_device overrides + virtual void tlcs900_check_hdma() override; + virtual void tlcs900_check_irqs() override; + virtual void tlcs900_handle_ad() override; + virtual void tlcs900_handle_timers() override; + + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + +private: + void change_timer_flipflop(uint8_t flipflop, uint8_t operation); + template uint8_t port_r(); + template void port_w(uint8_t data); + template void port_cr_w(uint8_t data); + template void port_fc_w(uint8_t data); + uint8_t t8run_r(); + void t8run_w(uint8_t data); + void treg01_w(offs_t offset, uint8_t data); + void treg23_w(offs_t offset, uint8_t data); + uint8_t t01mod_r(); + void t01mod_w(uint8_t data); + uint8_t t02ffcr_r(); + void t02ffcr_w(uint8_t data); + uint8_t t23mod_r(); + void t23mod_w(uint8_t data); + uint8_t trdc_r(); + void trdc_w(uint8_t data); + uint8_t t4mod_r(); + uint8_t t6mod_r(); + uint8_t t8mod_r(); + uint8_t tamod_r(); + void t4mod_w(uint8_t data); + void t6mod_w(uint8_t data); + void t8mod_w(uint8_t data); + void tamod_w(uint8_t data); + uint8_t t4ffcr_r(); + void t4ffcr_w(uint8_t data); + uint8_t t8ffcr_r(); + void t8ffcr_w(uint8_t data); + uint8_t t6ffcr_r(); + void t6ffcr_w(uint8_t data); + uint8_t taffcr_r(); + void taffcr_w(uint8_t data); + void treg45_w(offs_t offset, uint16_t data); + void treg67_w(offs_t offset, uint16_t data); + void treg89_w(offs_t offset, uint16_t data); + void tregab_w(offs_t offset, uint16_t data); + uint8_t cap45_r(offs_t offset); + uint8_t cap67_r(offs_t offset); + uint8_t cap89_r(offs_t offset); + uint8_t capab_r(offs_t offset); + uint8_t t16run_r(); + void t16run_w(uint8_t data); + uint8_t wdmod_r(); + void wdmod_w(uint8_t data); + void wdcr_w(uint8_t data); + uint8_t sc0buf_r(); + void sc0buf_w(uint8_t data); + uint8_t sc0cr_r(); + void sc0cr_w(uint8_t data); + uint8_t sc0mod_r(); + void sc0mod_w(uint8_t data); + uint8_t br0cr_r(); + void br0cr_w(uint8_t data); + uint8_t sc1buf_r(); + void sc1buf_w(uint8_t data); + uint8_t sc1cr_r(); + void sc1cr_w(uint8_t data); + uint8_t sc1mod_r(); + void sc1mod_w(uint8_t data); + uint8_t br1cr_r(); + void br1cr_w(uint8_t data); + uint8_t ode_r(); + void ode_w(uint8_t data); + uint8_t admod1_r(); + void admod1_w(uint8_t data); + uint8_t admod2_r(); + void admod2_w(uint8_t data); + uint8_t adreg_r(offs_t offset); + uint8_t inte_r(offs_t offset); + void inte_w(offs_t offset, uint8_t data); + uint8_t intnmwdt_r(offs_t offset); + void intnmwdt_w(offs_t offset, uint8_t data); + void iimc_w(uint8_t data); + void intclr_w(uint8_t data); + void dmav_w(offs_t offset, uint8_t data); + void b0cs_w(offs_t offset, uint8_t data); + void b1cs_w(offs_t offset, uint8_t data); + void b2cs_w(offs_t offset, uint8_t data); + void b3cs_w(offs_t offset, uint8_t data); + void b4cs_w(offs_t offset, uint8_t data); + void b5cs_w(offs_t offset, uint8_t data); + uint8_t msar0_r(); + void msar0_w(offs_t offset, uint8_t data); + uint8_t mamr0_r(); + void mamr0_w(offs_t offset, uint8_t data); + uint8_t msar1_r(); + void msar1_w(offs_t offset, uint8_t data); + uint8_t mamr1_r(); + void mamr1_w(offs_t offset, uint8_t data); + uint8_t msar2_r(); + void msar2_w(offs_t offset, uint8_t data); + uint8_t mamr2_r(); + void mamr2_w(offs_t offset, uint8_t data); + uint8_t msar3_r(); + void msar3_w(offs_t offset, uint8_t data); + uint8_t mamr3_r(); + void mamr3_w(offs_t offset, uint8_t data); + uint8_t msar4_r(); + void msar4_w(offs_t offset, uint8_t data); + uint8_t mamr4_r(); + void mamr4_w(offs_t offset, uint8_t data); + uint8_t msar5_r(); + void msar5_w(offs_t offset, uint8_t data); + uint8_t mamr5_r(); + void mamr5_w(offs_t offset, uint8_t data); + uint8_t drefcr1_r(); + void drefcr1_w(uint8_t data); + uint8_t dmemcr1_r(); + void dmemcr1_w(uint8_t data); + uint8_t drefcr3_r(); + void drefcr3_w(uint8_t data); + uint8_t dmemcr3_r(); + void dmemcr3_w(uint8_t data); + uint8_t dadrv_r(); + void dadrv_w(uint8_t data); + void dareg_w(offs_t offset, uint8_t data); + + void internal_mem(address_map &map); + + // analogue inputs, sampled at 10 bits + devcb_read16::array<8> m_an_read; + + // I/O Ports + devcb_read8::array m_port_read; + devcb_write8::array m_port_write; + uint8_t m_port_latch[NUM_PORTS]; + uint8_t m_port_control[NUM_PORTS]; + uint8_t m_port_function[NUM_PORTS]; + + // Timer Control + uint8_t m_t8run; + uint8_t m_t8_reg[8]; + uint8_t m_tmod[8]; + uint8_t m_ffcr[5]; + uint8_t m_trdc; + uint16_t m_t16_reg[8]; + uint16_t m_t16_cap[8]; + uint8_t m_t16run; + uint16_t m_timer16[4]; + + // Watchdog Timer + uint8_t m_watchdog_mode; + + // Serial Channel + uint8_t m_serial_control[2]; + uint8_t m_serial_mode[2]; + uint8_t m_baud_rate[2]; + uint8_t m_od_enable; + + // A/D Converter Control + uint8_t m_ad_mode1; + uint8_t m_ad_mode2; + uint16_t m_ad_result[4]; + + // Interrupt Control + uint8_t m_int_reg[18]; + uint8_t m_iimc; + uint8_t m_dma_vector[4]; + + // Chip Select/Wait Control + uint16_t m_block_cs[6]; + uint8_t m_external_cs; + uint8_t m_mem_start_reg[6]; + uint8_t m_mem_start_mask[6]; + + // DRAM Control + uint8_t m_dram_refresh[2]; + uint8_t m_dram_access[2]; + + // D/A Converter Control + uint8_t m_da_drive; +}; + +// device type declaration +DECLARE_DEVICE_TYPE(TMP94C241, tmp94c241_device) + +#endif // MAME_CPU_TLCS900_TMP94C241_H diff --git a/src/devices/cpu/tlcs900/tmp95c061.cpp b/src/devices/cpu/tlcs900/tmp95c061.cpp index 55c591cc74542..b1ba398e58deb 100644 --- a/src/devices/cpu/tlcs900/tmp95c061.cpp +++ b/src/devices/cpu/tlcs900/tmp95c061.cpp @@ -8,6 +8,7 @@ Toshiba TMP95C061 emulation #include "emu.h" #include "tmp95c061.h" +#include "dasm900.h" DEFINE_DEVICE_TYPE(TMP95C061, tmp95c061_device, "tmp95c061", "Toshiba TMP95C061") @@ -229,6 +230,12 @@ void tmp95c061_device::device_start() save_item(NAME(m_mem_start_mask)); save_item(NAME(m_dram_refresh)); save_item(NAME(m_dram_access)); + + m_nmi_state = CLEAR_LINE; + for( int i = 0; i < TLCS900_NUM_INPUTS; i++ ) + { + m_level[i] = CLEAR_LINE; + } } void tmp95c061_device::device_reset() @@ -239,7 +246,6 @@ void tmp95c061_device::device_reset() m_to3 = 0; m_ad_cycles_left = 0; - m_nmi_state = CLEAR_LINE; m_timer_pre = 0; m_timer_change[0] = 0; m_timer_change[1] = 0; @@ -289,11 +295,6 @@ void tmp95c061_device::device_reset() std::fill_n(&m_mem_start_mask[0], 4, 0xff); m_dram_refresh = 0x00; m_dram_access = 0x80; - - for (int i = 0; i < TLCS900_NUM_INPUTS; i++) - { - m_level[i] = CLEAR_LINE; - } } enum @@ -614,7 +615,6 @@ void tmp95c061_device::tlcs900_handle_ad() } } - enum ff_change { FF_CLEAR, @@ -1352,3 +1352,38 @@ void tmp95c061_device::dmemcr_w(uint8_t data) { m_dram_access = data; } + +std::pair const tmp95c061_syms[] = { + { 0x01, "P1" }, { 0x04, "P1CR" }, { 0x06, "P2" }, { 0x09, "P2FC" }, + { 0x0d, "P5" }, { 0x10, "P5CR" }, { 0x11, "P5FC" }, { 0x12, "P6" }, + { 0x13, "P7" }, { 0x15, "P6FC" }, { 0x16, "P7CR" }, { 0x17, "P7FC" }, + { 0x18, "P8" }, { 0x19, "P9" }, { 0x1a, "P8CR" }, { 0x1b, "P8FC" }, + { 0x1e, "PA" }, { 0x1f, "PB" }, { 0x20, "TRUN" }, { 0x22, "TREG0" }, + { 0x23, "TREG1" }, { 0x24, "T01MOD" }, { 0x25, "TFFCR" }, { 0x26, "TREG2" }, + { 0x27, "TREG3" }, { 0x28, "T23MOD" }, { 0x29, "TRDC" }, { 0x2c, "PACR" }, + { 0x2d, "PAFC" }, { 0x2e, "PBCR" }, { 0x2f, "PBFC" }, { 0x30, "TREG4L" }, + { 0x31, "TREG4H" }, { 0x32, "TREG5L" }, { 0x33, "TREG5H" }, { 0x34, "CAP1L" }, + { 0x35, "CAP1H" }, { 0x36, "CAP2L" }, { 0x37, "CAP2H" }, { 0x38, "T4MOD" }, + { 0x39, "T4FFCR" }, { 0x3a, "T45CR" }, { 0x3c, "MSAR0" }, { 0x3d, "MAMR0" }, + { 0x3e, "MSAR1" }, { 0x3f, "MAMR1" }, { 0x40, "TREG6L" }, { 0x41, "TREG6H" }, + { 0x42, "TREG7L" }, { 0x43, "TREG7H" }, { 0x44, "CAP3L" }, { 0x45, "CAP3H" }, + { 0x46, "CAP4L" }, { 0x47, "CAP4H" }, { 0x48, "T5MOD" }, { 0x49, "T5FFCR" }, + { 0x4c, "PG0REG" }, { 0x4d, "PG1REG" }, { 0x4e, "PG01CR" }, { 0x50, "SC0BUF" }, + { 0x51, "SC0CR" }, { 0x52, "SC0MOD" }, { 0x53, "BR0CR" }, { 0x54, "SC1BUF" }, + { 0x55, "SC1CR" }, { 0x56, "SC1MOD" }, { 0x57, "BR1CR" }, { 0x58, "ODE" }, + { 0x5a, "DREFCR" }, { 0x5b, "DMEMCR" }, { 0x5c, "MSAR2" }, { 0x5d, "MAMR2" }, + { 0x5e, "MSAR3" }, { 0x5f, "MAMR3" }, { 0x60, "ADREG0L" }, { 0x61, "ADREG0H" }, + { 0x62, "ADREG1L" }, { 0x63, "ADREG1H" }, { 0x64, "ADREG2L" }, { 0x65, "ADREG2H" }, + { 0x66, "ADREG3L" }, { 0x67, "ADREG3H" }, { 0x68, "B0CS" }, { 0x69, "B1CS" }, + { 0x6a, "B2CS" }, { 0x6b, "B3CS" }, { 0x6c, "BEXCS" }, { 0x6d, "ADMOD" }, + { 0x6e, "WDMOD" }, { 0x6f, "WDCR" }, { 0x70, "INTE0AD" }, { 0x71, "INTE45" }, + { 0x72, "INTE67" }, { 0x73, "INTET10" }, { 0x74, "INTET32" }, { 0x75, "INTET54" }, + { 0x76, "INTET76" }, { 0x77, "INTES0" }, { 0x78, "INTES1" }, { 0x79, "INTETC01" }, + { 0x7a, "INTETC23" }, { 0x7b, "IIMC" }, { 0x7c, "DMA0V" }, { 0x7d, "DMA1V" }, + { 0x7e, "DMA2V" }, { 0x7f, "DMA3V" } +}; + +std::unique_ptr tmp95c061_device::create_disassembler() +{ + return std::make_unique(tmp95c061_syms); +} diff --git a/src/devices/cpu/tlcs900/tmp95c061.h b/src/devices/cpu/tlcs900/tmp95c061.h index 7b52057fa2d85..548e8827d5303 100644 --- a/src/devices/cpu/tlcs900/tmp95c061.h +++ b/src/devices/cpu/tlcs900/tmp95c061.h @@ -61,6 +61,9 @@ class tmp95c061_device : public tlcs900h_device int tlcs900_process_hdma( int channel ); void update_porta(); + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + private: template uint8_t port_r(); template void port_w(uint8_t data); diff --git a/src/devices/cpu/tlcs900/tmp95c063.cpp b/src/devices/cpu/tlcs900/tmp95c063.cpp index 6220434622858..0cada57f4808b 100644 --- a/src/devices/cpu/tlcs900/tmp95c063.cpp +++ b/src/devices/cpu/tlcs900/tmp95c063.cpp @@ -8,6 +8,7 @@ Toshiba TMP95C063 emulation #include "emu.h" #include "tmp95c063.h" +#include "dasm900.h" DEFINE_DEVICE_TYPE(TMP95C063, tmp95c063_device, "tmp95c063", "Toshiba TMP95C063") @@ -595,6 +596,12 @@ void tmp95c063_device::device_start() save_item(NAME(m_dram_refresh)); save_item(NAME(m_dram_access)); save_item(NAME(m_da_drive)); + + m_nmi_state = CLEAR_LINE; + for( int i = 0; i < TLCS900_NUM_INPUTS; i++ ) + { + m_level[i] = CLEAR_LINE; + } } void tmp95c063_device::device_reset() @@ -602,7 +609,6 @@ void tmp95c063_device::device_reset() tlcs900h_device::device_reset(); m_ad_cycles_left = 0; - m_nmi_state = CLEAR_LINE; m_timer_pre = 0; m_timer_change[0] = 0; m_timer_change[1] = 0; @@ -655,9 +661,6 @@ void tmp95c063_device::device_reset() std::fill_n(&m_dram_refresh[0], 2, 0x00); std::fill_n(&m_dram_access[0], 2, 0x80); m_da_drive = 0x00; - - for (int i = 0; i < TLCS900_NUM_INPUTS; i++) - m_level[i] = CLEAR_LINE; } uint8_t tmp95c063_device::t8run_r() @@ -1398,3 +1401,31 @@ void tmp95c063_device::execute_set_input(int input, int level) } m_check_irqs = 1; } + +std::pair const tmp95c063_syms[] = { + { 0x01, "P1" }, { 0x04, "P1CR" }, { 0x06, "P2" }, + { 0x09, "P2FC" }, { 0x0d, "P5" }, + { 0x10, "P5CR" }, { 0x11, "P5FC" }, { 0x12, "P6" }, { 0x13, "P7" }, { 0x15, "P6FC" }, { 0x16, "P7CR" }, { 0x17, "P7FC" }, + { 0x18, "P8" }, { 0x19, "P9" }, { 0x1a, "P8CR" }, { 0x1b, "P8FC" }, { 0x1c, "P9CR" }, { 0x1d, "P9FC" }, { 0x1e, "PA" }, { 0x1f, "PB" }, + { 0x20, "T8RUN" }, { 0x21, "TRDC" }, { 0x22, "TREG0" }, { 0x23, "TREG1" }, { 0x24, "T01MOD" }, { 0x25, "T02FFCR" }, { 0x26, "TREG2" }, { 0x27, "TREG3" }, + { 0x28, "T23MOD" }, { 0x29, "TREG4" }, { 0x2a, "TREG5" }, { 0x2b, "T45MOD" }, { 0x2c, "TA46FFCR" }, { 0x2d, "TREG6" }, { 0x2e, "TREG7" }, { 0x2f, "T67MOD" }, + { 0x30, "TREG8L" }, { 0x31, "TREG8H" }, { 0x32, "TREG9L" }, { 0x33, "TREG9H" }, { 0x34, "CAP1L" }, { 0x35, "CAP1H" }, { 0x36, "CAP2L" }, { 0x37, "CAP2H" }, + { 0x38, "T8MOD" }, { 0x39, "T8FFCR" }, { 0x3a, "T89CR" }, { 0x3b, "T16RUN" }, + { 0x40, "TREGAL" }, { 0x41, "TREGAH" }, { 0x42, "TREGBL" }, { 0x43, "TREGBH" }, { 0x44, "CAP3L" }, { 0x45, "CAP3H" }, { 0x46, "CAP4L" }, { 0x47, "CAP4H" }, + { 0x48, "T9MOD" }, { 0x49, "T9FFCR" }, { 0x4a, "DAREG0" }, { 0x4b, "DAREG1" }, { 0x4c, "PG0REG" }, { 0x4d, "PG1REG" }, { 0x4e, "PG01CR" }, { 0x4f, "DADRV" }, + { 0x50, "SC0BUF" }, { 0x51, "SC0CR" }, { 0x52, "SC0MOD" }, { 0x53, "BR0CR" }, { 0x54, "SC1BUF" }, { 0x55, "SC1CR" }, { 0x56, "SC1MOD" }, { 0x57, "BR1CR" }, + { 0x58, "ODE" }, { 0x5a, "DMA0V" }, { 0x5b, "DMA1V" }, { 0x5c, "DMA2V" }, { 0x5d, "DMA3V" }, { 0x5e, "ADMOD1" }, { 0x5f, "ADMOD2" }, + { 0x60, "ADREG04L" }, { 0x61, "ADREG04H" }, { 0x62, "ADREG15L" }, { 0x63, "ADREG15H" }, { 0x64, "ADREG26L" }, { 0x65, "ADREG26H" }, { 0x66, "ADREG37L" }, { 0x67, "ADREG37H" }, + { 0x6a, "SDMACR0" }, { 0x6b, "SDMACR1" }, { 0x6c, "SDMACR2" }, { 0x6d, "SDMACR3" }, { 0x6e, "WDMOD" }, { 0x6f, "WDCR" }, + { 0x70, "INTE_0AD" }, { 0x71, "INTE12" }, { 0x72, "INTE34" }, { 0x73, "INTE56" }, { 0x74, "INT78" }, { 0x75, "INTET01" }, { 0x76, "INTET32" }, { 0x77, "INTET45" }, + { 0x78, "INTET67" }, { 0x79, "INTET89" }, { 0x7a, "INTETAB" }, { 0x7b, "INTES0" }, { 0x7c, "INTES1" }, { 0x7d, "INTETC01" }, { 0x7e, "INTETC23" }, { 0x7f, "IIMC" }, + { 0x80, "PACR" }, { 0x81, "PAFC" }, { 0x82, "PBCR" }, { 0x83, "PBFC" }, { 0x84, "PC" }, { 0x85, "PD"}, + { 0x88, "PDCR" }, { 0x8a, "PE" }, { 0x8c, "PECR" }, { 0x8f, "BEXCS" }, + { 0x90, "B0CS" }, { 0x91, "B1CS" }, { 0x92, "B2CS" }, { 0x93, "B3CS" }, { 0x94, "MSAR0" }, { 0x95, "MAMR0" }, { 0x96, "MSAR1" }, { 0x97, "MAMR1" }, + { 0x98, "MSAR2" }, { 0x99, "MAMR2" }, { 0x9a, "MSAR3" }, { 0x9b, "MAMR3" }, { 0x9c, "DREFCR1" }, { 0x9d, "DMEMCR1" }, { 0x9e, "DREFCR3" }, { 0x9f, "DMEMCR3" } +}; + +std::unique_ptr tmp95c063_device::create_disassembler() +{ + return std::make_unique(tmp95c063_syms); +} diff --git a/src/devices/cpu/tlcs900/tmp95c063.h b/src/devices/cpu/tlcs900/tmp95c063.h index acbcfc10f3c18..e0df20e468fb8 100644 --- a/src/devices/cpu/tlcs900/tmp95c063.h +++ b/src/devices/cpu/tlcs900/tmp95c063.h @@ -67,6 +67,9 @@ class tmp95c063_device : public tlcs900h_device virtual void tlcs900_handle_ad() override; virtual void tlcs900_handle_timers() override; + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + private: template uint8_t port_r(); template void port_w(uint8_t data); diff --git a/src/devices/cpu/tlcs900/tmp96c141.cpp b/src/devices/cpu/tlcs900/tmp96c141.cpp index b5e64be8da3e5..e8a1a08e19d0a 100644 --- a/src/devices/cpu/tlcs900/tmp96c141.cpp +++ b/src/devices/cpu/tlcs900/tmp96c141.cpp @@ -12,6 +12,7 @@ #include "emu.h" #include "tmp96c141.h" +#include "dasm900.h" //************************************************************************** @@ -195,3 +196,28 @@ void tmp96c141_device::tlcs900_handle_timers() void tmp96c141_device::execute_set_input(int inputnum, int state) { } + +std::pair const tmp96c141_syms[] = { + { 0x00, "P0" }, { 0x01, "P1" }, { 0x02, "P0CR" }, + { 0x04, "P1CR" }, { 0x05, "P1FC" }, { 0x06, "P2" }, { 0x07, "P3" }, + { 0x08, "P2CR" }, { 0x09, "P2FC" }, { 0x0a, "P3CR" }, { 0x0b, "P3FC" }, { 0x0c, "P4" }, { 0x0d, "P5" }, { 0x0e, "P4CR" }, + { 0x10, "P4FC" }, { 0x12, "P6" }, { 0x13, "P7" }, { 0x14, "P6CR" }, { 0x15, "P7CR" }, { 0x16, "P6FC" }, { 0x17, "P7FC" }, + { 0x18, "P8" }, { 0x19, "P9" }, { 0x1a, "P8CR" }, { 0x1b, "P9CR" }, { 0x1c, "P8FC" }, { 0x1d, "P9FC" }, + { 0x20, "TRUN" }, { 0x22, "TREG0" }, { 0x23, "TREG1" }, { 0x24, "TMOD" }, { 0x25, "TFFCR" }, { 0x26, "TREG2" }, { 0x27, "TREG3" }, + { 0x28, "P0MOD" }, { 0x29, "P1MOD" }, { 0x2a, "PFFCR" }, + { 0x30, "TREG4L" }, { 0x31, "TREG4H" }, { 0x32, "TREG5L" }, { 0x33, "TREG5H" }, { 0x34, "CAP1L" }, { 0x35, "CAP1H" }, { 0x36, "CAP2L" }, { 0x37, "CAP2H" }, + { 0x38, "T4MOD" }, { 0x39, "T4FFCR" }, { 0x3a, "T45CR" }, + { 0x40, "TREG6L" }, { 0x41, "TREG6H" }, { 0x42, "TREG7L" }, { 0x43, "TREG7H" }, { 0x44, "CAP3L" }, { 0x45, "CAP3H" }, { 0x46, "CAP4L" }, { 0x47, "CAP4H" }, + { 0x48, "T5MOD" }, { 0x49, "T5FFCR" }, { 0x4c, "PG0REG" }, { 0x4d, "PG1REG" }, { 0x4e, "PG01CR" }, + { 0x50, "SC0BUF" }, { 0x51, "SC0CR" }, { 0x52, "SC0MOD" }, { 0x53, "BR0CR" }, { 0x54, "SC1BUF" }, { 0x55, "SC1CR" }, { 0x56, "SC1MOD" }, { 0x57, "BR1CR" }, + { 0x58, "ODE" }, { 0x5c, "WDMOD" }, { 0x5d, "WDCR" }, { 0x5e, "ADMOD" }, + { 0x60, "ADREG0L" }, { 0x61, "ADREG0H" }, { 0x62, "ADREG1L" }, { 0x63, "ADREG1H" }, { 0x64, "ADREG2L" }, { 0x65, "ADREG2H" }, { 0x66, "ADREG3L" }, { 0x67, "ADREG3H" }, + { 0x68, "B0CS" }, { 0x69, "B1CS" }, { 0x6a, "B2CS" }, + { 0x70, "INTE0AD" }, { 0x71, "INTE45" }, { 0x72, "INTE67" }, { 0x73, "INTET10" }, { 0x74, "INTEPW10" }, { 0x75, "INTET54" }, { 0x76, "INTET76" }, { 0x77, "INTES0" }, + { 0x78, "INTES1" }, { 0x7b, "IIMC" }, { 0x7c, "DMA0V" }, { 0x7d, "DMA1V" }, { 0x7e, "DMA2V" }, { 0x7f, "DMA3V"} +}; + +std::unique_ptr tmp96c141_device::create_disassembler() +{ + return std::make_unique(tmp96c141_syms); +} diff --git a/src/devices/cpu/tlcs900/tmp96c141.h b/src/devices/cpu/tlcs900/tmp96c141.h index 4710820f71ebd..b432a2631d2ed 100644 --- a/src/devices/cpu/tlcs900/tmp96c141.h +++ b/src/devices/cpu/tlcs900/tmp96c141.h @@ -88,6 +88,9 @@ class tmp96c141_device : public tlcs900_device virtual void tlcs900_handle_ad() override; virtual void tlcs900_handle_timers() override; + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + private: void internal_mem(address_map &map) ATTR_COLD; }; diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 2fc2e23aebe28..02b8d0a59af78 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -25212,7 +25212,7 @@ jr200 // jr200u // @source:matsushita/kn5000.cpp -kn5000 // (c) 199? Technics SX-KN5000 PCM Keyboard +kn5000 // (c) 1998 Technics SX KN-5000 PCM Keyboard @source:matsushita/myb3k.cpp myb3k // diff --git a/src/mame/matsushita/kn5000.cpp b/src/mame/matsushita/kn5000.cpp index 64023b65aaa24..9f4267357bc5a 100644 --- a/src/mame/matsushita/kn5000.cpp +++ b/src/mame/matsushita/kn5000.cpp @@ -7,7 +7,8 @@ ******************************************************************************/ #include "emu.h" -#include "cpu/tlcs900/tmp95c061.h" // TODO: tmp94c241.h +#include "bus/technics/hdae5000.h" +#include "cpu/tlcs900/tmp94c241.h" #include "imagedev/floppy.h" #include "machine/gen_latch.h" #include "machine/upd765.h" @@ -95,6 +96,9 @@ class kn5000_state : public driver_device , m_maincpu_latch(*this, "maincpu_latch") , m_subcpu_latch(*this, "subcpu_latch") , m_fdc(*this, "fdc") + , m_extension(*this, "extension") + , m_extension_view(*this, "extension_view") + , m_com_select(*this, "COM_SELECT") , m_CPL_SEG(*this, "CPL_SEG%u", 0U) , m_CPR_SEG(*this, "CPR_SEG%u", 0U) , m_checking_device_led_cn11(*this, "checking_device_led_cn11") @@ -109,11 +113,15 @@ class kn5000_state : public driver_device void kn5000(machine_config &config); private: - required_device m_maincpu; - required_device m_subcpu; + required_device m_maincpu; + required_device m_subcpu; required_device m_maincpu_latch; required_device m_subcpu_latch; required_device m_fdc; + required_device m_extension; + memory_view m_extension_view; + + required_ioport m_com_select; required_ioport_array<11> m_CPL_SEG; // buttons on "Control Panel Left" PCB required_ioport_array<11> m_CPR_SEG; // buttons on "Control Panel Right" PCB output_finder<> m_checking_device_led_cn11; @@ -135,6 +143,20 @@ class kn5000_state : public driver_device void subcpu_mem(address_map &map) ATTR_COLD; }; +/* +MSAR0: 0x1e MAMR0: 0x0f start: 0x1e0000 mask: 0x01ffff (128kB) SRAM @ IC21 +MSAR1: 0x10 MAMR1: 0x3f start: 0x100000 mask: 0x0fffff (1MByte) +MSAR2: 0xc0 MAMR2: 0x7f start: 0xc00000 mask: 0x3fffff (4MByte) table data ROM (also boot?) +MSAR3: 0x00 MAMR3: 0x1f start: 0x000000 mask: 0x0fffff (1MByte) DRAM ? +MSAR4: 0x80 MAMR4: 0xff start: 0x800000 mask: 0x7fffff (8MByte) +MSAR5: 0x00 MAMR5: 0xff start: 0x000000 mask: 0x7fffff (8MByte) + CS5: optional HSRAM at A22=0 A21=X A20=0 A19=0 (0x200000) (512k) + CS5: optional HSROM at A22=0 A21=X A20=0 A19=1 (0x280000) (512k) + CS5: custom data at A22=0 A21=X A20=1 (0x300000) (1MB) + CS5: rhythm data at A22=1 (0x400000) (4MB) +*/ + + void kn5000_state::maincpu_mem(address_map &map) { map(0x000000, 0x0fffff).ram(); // 1Mbyte = 2 * 4Mbit DRAMs @ IC9, IC10 (CS3) @@ -148,11 +170,17 @@ void kn5000_state::maincpu_mem(address_map &map) map(0x1703b0, 0x1703df).m("vga", FUNC(mn89304_vga_device::io_map)); // LCD controller @ IC206 map(0x1a0000, 0x1bffff).rw("vga", FUNC(mn89304_vga_device::mem_linear_r), FUNC(mn89304_vga_device::mem_linear_w)); map(0x1e0000, 0x1fffff).ram(); // 1Mbit SRAM @ IC21 (CS0) Note: I think this is the message "ERROR in back-up SRAM" - map(0x200000, 0x2fffff).noprw(); // Extension board goes here. + map(0x200000, 0x2fffff).view(m_extension_view); + m_extension_view[0](0x200000, 0x2fffff).noprw(); + m_extension_view[1](0x200000, 0x27ffff).ram(); // optional hsram: 2 * 256k bytes Static RAM @ IC5, IC6 (CS5) map(0x300000, 0x3fffff).rom().region("custom_data", 0); // 8MBit FLASH ROM @ IC19 (CS5) map(0x400000, 0x7fffff).rom().region("rhythm_data", 0); // 32MBit ROM @ IC14 (A22=1 and CS5) - //map(0x800000, 0x82ffff).rom().region("subprogram", 0); // not sure yet in which chip this is stored, but I suspect it should be IC19 - map(0x800000, 0x9fffff).mirror(0x200000).rom().region("table_data", 0); //2 * 8MBit ROMs @ IC1, IC3 (CS2) + //map(0x?00000, 0x?2ffff).rom().region("subprogram", 0); // FIXME: not sure yet in which chip this is stored, but I suspect it should be IC19 + + //map(0x800000, 0x9fffff).mask(0x1fffff).rom().region("program", 0); //2 * 8MBit FLASH ROMs @ IC4, IC6 + //map(0xe00000, 0xffffff).rom().region("table_data", 0); //2 * 8MBit ROMs @ IC1, IC3 (CS2) + + map(0x800000, 0x9fffff).rom().region("table_data", 0); //2 * 8MBit ROMs @ IC1, IC3 (CS2) map(0xe00000, 0xffffff).mask(0x1fffff).rom().region("program", 0); //2 * 8MBit FLASH ROMs @ IC4, IC6 } @@ -197,6 +225,37 @@ static INPUT_PORTS_START(kn5000) PORT_DIPSETTING( 0xb0, "PC2") PORT_DIPSETTING( 0x70, "Mac") + PORT_START("AREA") + PORT_DIPNAME(0x06, 0x06, "Area Selection") + PORT_DIPSETTING( 0x02, "Thailand, Indonesia, Iran, U.A.E., Panama, Argentina, Peru, Brazil") + PORT_DIPSETTING( 0x04, "USA, Mexico") + PORT_DIPSETTING( 0x06, "Other") + +/* + Actual full list of regions (but it is unclear if there's any + other hardware difference among them): + + PORT_DIPSETTING( 0x04, "(M): U.S.A.") + PORT_DIPSETTING( 0x06, "(MC): Canada") + PORT_DIPSETTING( 0x04, "(XM): Mexico") + PORT_DIPSETTING( 0x06, "(EN): Norway, Sweden, Denmark, Finland") + PORT_DIPSETTING( 0x06, "(EH): Holland, Belgium") + PORT_DIPSETTING( 0x06, "(EF): France, Italy") + PORT_DIPSETTING( 0x06, "(EZ): Germany") + PORT_DIPSETTING( 0x06, "(EW): Switzerland") + PORT_DIPSETTING( 0x06, "(EA): Austria") + PORT_DIPSETTING( 0x06, "(EP): Spain, Portugal, Greece, South Africa") + PORT_DIPSETTING( 0x06, "(EK): United Kingdom") + PORT_DIPSETTING( 0x06, "(XL): New Zealand") + PORT_DIPSETTING( 0x06, "(XR): Australia") + PORT_DIPSETTING( 0x06, "(XS): Malaysia") + PORT_DIPSETTING( 0x06, "(MD): Saudi Arabia, Hong Kong, Kuwait") + PORT_DIPSETTING( 0x06, "(XT): Taiwan") + PORT_DIPSETTING( 0x02, "(X): Thailand, Indonesia, Iran, U.A.E., Panama, Argentina, Peru, Brazil") + PORT_DIPSETTING( 0x06, "(XP): Philippines") + PORT_DIPSETTING( 0x06, "(XW): Singapore") +*/ + PORT_START("CPR_SEG0") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) @@ -589,6 +648,16 @@ void kn5000_state::machine_start() save_item(NAME(m_mstat)); save_item(NAME(m_sstat)); + if (m_extension) + { + m_extension->rom_map(m_extension_view[1], 0x280000, 0x2fffff); + m_extension_view.select(1); + } + else + { + m_extension_view.select(0); + } + m_checking_device_led_cn11.resolve(); m_checking_device_led_cn12.resolve(); m_CPL_LED.resolve(); @@ -604,7 +673,7 @@ void kn5000_state::machine_reset() void kn5000_state::kn5000(machine_config &config) { // Note: The CPU has an internal clock doubler - TMP95C061(config, m_maincpu, 2 * 8_MHz_XTAL); // actual cpu is TMP94C241F @ IC5 + TMP94C241(config, m_maincpu, 2 * 8_MHz_XTAL); // TMP94C241F @ IC5 // Address bus is set to 32 bits by the pins AM1=+5v and AM0=GND m_maincpu->set_addrmap(AS_PROGRAM, &kn5000_state::maincpu_mem); // Interrupt 4: FDCINT @@ -619,7 +688,7 @@ void kn5000_state::kn5000(machine_config &config) // MAINCPU PORT 7: // bit 5 (~BUSRQ pin): RY/~BY pin of maincpu ROMs - m_maincpu->port7_read().set([] { return (1 << 5); }); // checked at EF3735 (v10 ROM) + m_maincpu->port7_read().set_constant(1 << 5); // checked at EF3735 (v10 ROM) // MAINCPU PORT 8: @@ -636,14 +705,16 @@ void kn5000_state::kn5000(machine_config &config) // MAINCPU PORT C: // bit 0 (input) = "check terminal" switch // bit 1 (output) = "check terminal" LED - // TODO: m_maincpu->portc_read().set([this] { return ioport("CN11")->read(); }); - // TODO: m_maincpu->portc_write().set([this] (u8 data) { m_checking_device_led_cn11 = (BIT(data, 1) == 0); }); + m_maincpu->portc_read().set_ioport("CN11"); + m_maincpu->portc_write().set([this] (u8 data) { + m_checking_device_led_cn11 = (BIT(data, 1) == 0); + }); // MAINCPU PORT D: // bit 0 (output) = FDCRST // bit 6 (input) = FD.I/O - // TODO: m_maincpu->portd_write().set([this] (u8 data) { m_fdc->reset_w(BIT(data, 0)); }); + m_maincpu->portd_write().set(m_fdc, FUNC(upd72067_device::reset_w)).bit(0); // TODO: bit 6! @@ -651,7 +722,7 @@ void kn5000_state::kn5000(machine_config &config) // bit 0 (input) = +5v // bit 2 (input) = HDDRDY // bit 4 (?) = MICSNS - // TODO: m_maincpu->porte_read().set([] { return 1; }); //checked at EF05A6 (v10 ROM) + m_maincpu->porte_read().set_constant(1); //checked at EF05A6 (v10 ROM) // FIXME: Bit 0 should only be 1 if the // optional hard-drive extension board is disabled; @@ -670,10 +741,7 @@ void kn5000_state::kn5000(machine_config &config) // MAINCPU PORT H: - // bit 1 = TC1 Terminal count - microDMA - // TODO: m_maincpu->porth_read().set([] { return 2; }); // area/region detection: checked at EF083E (v10 ROM) - // FIXME: These are resistors on the pcb, but could be declared - // in the driver as a 2 bit DIP-Switch for area/region selection. + m_maincpu->porth_read().set_ioport("AREA"); // checked at EF083E (v10 ROM) // MAINCPU PORT Z: @@ -685,12 +753,12 @@ void kn5000_state::kn5000(machine_config &config) // bit 5 = (input) COM.PC1 // bit 6 = (input) COM.MAC // bit 7 = (input) COM.MIDI - // TODO: m_maincpu->portz_read().set([this] { - // TODO: return ioport("COM_SELECT")->read() | (m_sstat << 2); - // TODO: }); - // TODO: m_maincpu->portz_write().set([this] (u8 data) { - // TODO: m_mstat = data & 3; - // TODO: }); + m_maincpu->portz_read().set([this] { + return m_com_select->read() | (m_sstat << 2); + }); + m_maincpu->portz_write().set([this] (u8 data) { + m_mstat = data & 3; + }); // RX0/TX0 = MRXD/MTXD @@ -701,15 +769,18 @@ void kn5000_state::kn5000(machine_config &config) // AN1 = AFT // Note: The CPU has an internal clock doubler - TMP95C061(config, m_subcpu, 2*10_MHz_XTAL); // actual cpu is TMP94C241F @ IC27 + TMP94C241(config, m_subcpu, 2*10_MHz_XTAL); // TMP94C241F @ IC27 // Address bus is set to 8 bits by the pins AM1=GND and AM0=GND m_subcpu->set_addrmap(AS_PROGRAM, &kn5000_state::subcpu_mem); // SUBCPU PORT C: // bit 0 (input) = "check terminal" switch // bit 1 (output) = "check terminal" LED - // TODO: m_subcpu->portc_read().set([this] { return ioport("CN12")->read(); }); - // TODO: m_subcpu->portc_write().set([this] (u8 data) { m_checking_device_led_cn12 = (BIT(data, 1) == 0); }); + m_subcpu->portc_read().set_ioport("CN12"); + m_subcpu->portc_write().set([this] (u8 data) { + m_checking_device_led_cn12 = (BIT(data, 1) == 0); + }); + // SUBCPU PORT D: // bit 0 = (output) SSTAT0 @@ -717,12 +788,12 @@ void kn5000_state::kn5000(machine_config &config) // bit 2 = (input) MSTAT0 // bit 3 (not used) // bit 4 = (input) MSTAT1 - // TODO: m_subcpu->portd_read().set([this] { - // TODO: return (BIT(m_mstat, 0) << 2) | (BIT(m_mstat, 1) << 4); - // TODO: }); - // TODO: m_subcpu->portd_write().set([this] (u8 data) { - // TODO: m_sstat = data & 3; - // TODO: }); + m_subcpu->portd_read().set([this] { + return (BIT(m_mstat, 0) << 2) | (BIT(m_mstat, 1) << 4); + }); + m_subcpu->portd_write().set([this] (u8 data) { + m_sstat = data & 3; + }); GENERIC_LATCH_8(config, m_maincpu_latch); // @ IC23 @@ -744,6 +815,15 @@ void kn5000_state::kn5000(machine_config &config) FLOPPY_CONNECTOR(config, "fdc:0", kn5000_floppies, "35dd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true); + /* extension port */ + KN5000_EXTENSION(config, m_extension, 16_MHz_XTAL / 16); //FIXME: which clock signal should be passed to the extension port? + m_extension->irq_callback().set_inputline(m_maincpu, TLCS900_INT9); + m_extension->option_add("hdae5000", HDAE5000); + + /* sound hardware */ + //SPEAKER(config, "lspeaker").front_left(); + //SPEAKER(config, "rspeaker").front_right(); + /* video hardware */ // LCD Controller MN89304 @ IC206 24_MHz_XTAL screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD)); diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 4ccce7f1eeb68..79dc88267819a 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -645,6 +645,10 @@ static const dasm_table_entry dasm_table[] = { "tmp90c051", le, 0, []() -> util::disasm_interface * { return new tmp90c051_disassembler; } }, { "tmp90840", le, 0, []() -> util::disasm_interface * { return new tmp90840_disassembler; } }, { "tmp90844", le, 0, []() -> util::disasm_interface * { return new tmp90844_disassembler; } }, + { "tmp94c241", le, 0, []() -> util::disasm_interface * { return new tmp94c241_disassembler; } }, + { "tmp95c061", le, 0, []() -> util::disasm_interface * { return new tmp95c061_disassembler; } }, + { "tmp95c063", le, 0, []() -> util::disasm_interface * { return new tmp95c063_disassembler; } }, + { "tmp96c141", le, 0, []() -> util::disasm_interface * { return new tmp96c141_disassembler; } }, { "tms0980", be, 0, []() -> util::disasm_interface * { return new tms0980_disassembler; } }, { "tms1000", le, 0, []() -> util::disasm_interface * { return new tms1000_disassembler; } }, { "tms1100", le, 0, []() -> util::disasm_interface * { return new tms1100_disassembler; } },