diff options
-rw-r--r-- | scripts/src/cpu.lua | 2 | ||||
-rw-r--r-- | src/devices/cpu/tlcs900/tlcs900.cpp | 2 | ||||
-rw-r--r-- | src/devices/cpu/tlcs900/tlcs900.h | 7 | ||||
-rw-r--r-- | src/devices/cpu/tlcs900/tmp94c241.cpp | 1332 | ||||
-rw-r--r-- | src/devices/cpu/tlcs900/tmp94c241.h | 279 | ||||
-rw-r--r-- | src/devices/cpu/tlcs900/tmp95c061.cpp | 67 | ||||
-rw-r--r-- | src/devices/cpu/tlcs900/tmp95c061.h | 3 | ||||
-rw-r--r-- | src/devices/cpu/tlcs900/tmp95c063.cpp | 65 | ||||
-rw-r--r-- | src/devices/cpu/tlcs900/tmp95c063.h | 3 | ||||
-rw-r--r-- | src/mame/matsushita/kn5000.cpp | 75 |
10 files changed, 1745 insertions, 90 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 99bb9efb18b..51d8e1b17b5 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -2982,6 +2982,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/cpu/tlcs900/tlcs900.cpp b/src/devices/cpu/tlcs900/tlcs900.cpp index 2b2c4653b3c..ac8bfaf78fc 100644 --- a/src/devices/cpu/tlcs900/tlcs900.cpp +++ b/src/devices/cpu/tlcs900/tlcs900.cpp @@ -138,7 +138,7 @@ void tlcs900_device::device_start() save_item( NAME(m_dmac) ); save_item( NAME(m_dmam) ); save_item( NAME(m_timer_pre) ); - save_item( NAME(m_timer) ); + save_item( NAME(m_timer_8) ); save_item( NAME(m_timer_change) ); save_item( NAME(m_level) ); save_item( NAME(m_check_irqs) ); diff --git a/src/devices/cpu/tlcs900/tlcs900.h b/src/devices/cpu/tlcs900/tlcs900.h index a3ce3d5fa67..36feca4e7b1 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 @@ protected: /* Internal timers, irqs, etc */ uint32_t m_timer_pre; - uint8_t m_timer[6]; - int m_timer_change[4]; + uint8_t m_timer_8[6]; + 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 00000000000..bf76eaa5897 --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp94c241.cpp @@ -0,0 +1,1332 @@ +// license:BSD-3-Clause +// copyright-holders:AJR,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") + +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_timer_flipflops{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + m_t8run(0), + m_t01mod(0), + m_t23mod(0), + m_t4mod(0), + m_t6mod(0), + m_t8mod(0), + m_tamod(0), + m_tffcr(0), + m_t4ffcr(0), + m_t6ffcr(0), + m_t8ffcr(0), + m_taffcr(0), + m_trdc(0), + m_t16run(0), + m_treg_8{ 0, 0, 0, 0 }, + m_treg_16{ 0, 0, 0, 0, 0, 0, 0, 0 }, + m_t16_cap{ 0, 0, 0, 0, 0, 0, 0, 0 }, + m_timer_16{ 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_msar{ 0, 0, 0, 0, 0, 0 }, + m_mamr{ 0, 0, 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)); +} + + +void tmp94c241_device::device_resolve_objects() +{ + m_nmi_state = CLEAR_LINE; + for (int i = 0; i < TLCS900_NUM_INPUTS; i++) + { + m_level[i] = CLEAR_LINE; + } +} + +//------------------------------------------------- +// 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_timer_flipflops)); + save_item(NAME(m_t8run)); + save_item(NAME(m_t01mod)); + save_item(NAME(m_t23mod)); + save_item(NAME(m_t4mod)); + save_item(NAME(m_t6mod)); + save_item(NAME(m_t8mod)); + save_item(NAME(m_tamod)); + save_item(NAME(m_trdc)); + save_item(NAME(m_treg_8)); + save_item(NAME(m_treg_16)); + save_item(NAME(m_t16_cap)); + save_item(NAME(m_tffcr)); + save_item(NAME(m_t4ffcr)); + save_item(NAME(m_t6ffcr)); + save_item(NAME(m_t8ffcr)); + save_item(NAME(m_taffcr)); + 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_msar)); + save_item(NAME(m_mamr)); + save_item(NAME(m_dram_refresh)); + save_item(NAME(m_dram_access)); + save_item(NAME(m_da_drive)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void tmp94c241_device::device_reset() +{ + tlcs900h_device::device_reset(); + + m_ad_cycles_left = 0; + m_timer_pre = 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); + std::fill_n(&m_timer_flipflops[0], 12, 0x00); + m_t8run = 0x00; + m_trdc = 0x00; + m_t01mod = 0x00; + m_t23mod = 0x00; + m_t4mod = 0x00; + m_t6mod = 0x00; + m_t8mod = 0x00; + m_tamod = 0x00; + m_tffcr = 0x00; + m_t4ffcr = 0x00; + m_t6ffcr = 0x00; + m_t8ffcr = 0x00; + m_taffcr = 0x00; + std::fill_n(&m_timer_change[0], 8, 0x00); + std::fill_n(&m_timer_8[0], 4, 0x00); + std::fill_n(&m_timer_16[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_msar[0], 6, 0xff); + std::fill_n(&m_mamr[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; +} + +template <uint8_t N> +void tmp94c241_device::bNcs_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_block_cs[N]); +} + +template <uint8_t N> +void tmp94c241_device::mamr_w(uint8_t data) +{ + m_mamr[N] = data; +} + +template <uint8_t N> +void tmp94c241_device::msar_w(uint8_t data) +{ + m_msar[N] = data; +} + +template <uint8_t N> +uint8_t tmp94c241_device::mamr_r() +{ + return m_mamr[N]; +} + +template <uint8_t N> +uint8_t tmp94c241_device::msar_r() +{ + return m_msar[N]; +} + +uint8_t tmp94c241_device::t8run_r() +{ + return m_t8run; +} + +void tmp94c241_device::t8run_w(uint8_t data) +{ + m_t8run = data; + for (int i = 0; i < 4; i++) + { + // These correspond to UP_COUNTER and TIMER_CHANGE for 8-bit timers 0, 1, 2 and 3 + if (!BIT(m_t8run, i)) // Timer isn't running + { + m_timer_8[i] = 0; + m_timer_change[i] = 0; + } + } +} + +uint8_t tmp94c241_device::t01mod_r() +{ + return m_t01mod; +} + +void tmp94c241_device::t01mod_w(uint8_t data) +{ + m_t01mod = data; +} + +uint8_t tmp94c241_device::tffcr_r() +{ + return m_tffcr; +} + +enum +{ + FF_INVERT, + FF_SET, + FF_CLEAR, + FF_DONTCARE +}; + +void tmp94c241_device::change_timer_flipflop(uint8_t flipflop, uint8_t operation) +{ + /* First we update the timer flip-flop */ + bool &ff_state = m_timer_flipflops[flipflop]; + + switch (operation) + { + case FF_INVERT: + ff_state = !ff_state; + break; + case FF_SET: + ff_state = true; + break; + case FF_CLEAR: + ff_state = false; + break; + default: + // invalid operation + return; + } + + /* The value of the flipflop is only exposed to a pin in certain modes of operation + determined by fields of the port function registers. + + So here we bail out if the flipflop is not routed to its corresponding port bit: + */ + switch (flipflop) + { + case 0x1: + if (!BIT(m_port_function[PORT_C], 0) || BIT(m_port_control[PORT_C], 0)) return; + break; + case 0x7: + if (!BIT(m_port_function[PORT_C], 0) || !BIT(m_port_control[PORT_C], 0)) return; + break; + case 0x3: + if (!BIT(m_port_function[PORT_C], 1) || BIT(m_port_control[PORT_C], 1)) return; + break; + case 0xb: + if (!BIT(m_port_function[PORT_C], 1) || !BIT(m_port_control[PORT_C], 1)) return; + break; + case 0x4: + if (!BIT(m_port_function[PORT_D], 0)) return; + break; + case 0x6: + if (!BIT(m_port_function[PORT_D], 4)) return; + break; + case 0x8: + if (!BIT(m_port_function[PORT_E], 0)) return; + break; + case 0xA: + if (!BIT(m_port_function[PORT_E], 4)) return; + break; + default: + // invalid flip flop + return; + } + + // And here we actually send the value to the corresponding pin + uint8_t new_port_value = 0; + switch (flipflop) + { + case 0x1: + case 0x7: + new_port_value = m_port_latch[PORT_C] & 0xfe; + if (ff_state) new_port_value |= 0x01; + port_w<PORT_C>(new_port_value); + break; + case 0x3: + case 0xb: + new_port_value = m_port_latch[PORT_C] & 0xfd; + if (ff_state) new_port_value |= 0x02; + port_w<PORT_C>(new_port_value); + break; + case 0x4: + new_port_value = m_port_latch[PORT_D] & 0xfe; + if (ff_state) new_port_value |= 0x01; + port_w<PORT_D>(new_port_value); + break; + case 0x6: + new_port_value = m_port_latch[PORT_D] & 0xef; + if (ff_state) new_port_value |= 0x10; + port_w<PORT_D>(new_port_value); + break; + case 0x8: + new_port_value = m_port_latch[PORT_E] & 0xfe; + if (ff_state) new_port_value |= 0x01; + port_w<PORT_E>(new_port_value); + break; + case 0xa: + new_port_value = m_port_latch[PORT_E] & 0xef; + if (ff_state) new_port_value |= 0x10; + port_w<PORT_E>(new_port_value); + break; + } +} + +void tmp94c241_device::tffcr_w(uint8_t data) +{ + change_timer_flipflop( 1, (data >> 2) & 3 ); + change_timer_flipflop( 3, (data >> 6) & 3 ); + m_tffcr = data | 0xcc; +} + +uint8_t tmp94c241_device::t23mod_r() +{ + return m_t23mod; +} + +void tmp94c241_device::t23mod_w(uint8_t data) +{ + m_t23mod = data; +} + +uint8_t tmp94c241_device::trdc_r() +{ + return m_trdc; +} + +void tmp94c241_device::trdc_w(uint8_t data) +{ + m_trdc = data; +} + +template <uint8_t Timer> +void tmp94c241_device::treg_8_w(uint8_t data) +{ + m_treg_8[Timer] = data; +} + +template <uint8_t Timer> +void tmp94c241_device::treg_16_w(uint16_t data) +{ + m_treg_16[Timer] = data; +} + +uint8_t tmp94c241_device::t4mod_r() +{ + return m_t4mod; +} + +void tmp94c241_device::t4mod_w(uint8_t data) +{ + m_t4mod = data; +} + +uint8_t tmp94c241_device::t6mod_r() +{ + return m_t6mod; +} + +void tmp94c241_device::t6mod_w(uint8_t data) +{ + m_t6mod = data; +} + +uint8_t tmp94c241_device::t8mod_r() +{ + return m_t8mod; +} + +void tmp94c241_device::t8mod_w(uint8_t data) +{ + m_t8mod = data; +} + +uint8_t tmp94c241_device::tamod_r() +{ + return m_tamod; +} + +void tmp94c241_device::tamod_w(uint8_t data) +{ + m_tamod = data; +} + +uint8_t tmp94c241_device::t4ffcr_r() +{ + return m_t4ffcr; +} + +void tmp94c241_device::t4ffcr_w(uint8_t data) +{ + change_timer_flipflop( 4, data & 3 ); + change_timer_flipflop( 5, (data >> 6) & 3 ); + m_t4ffcr = data | 0xc3; +} + +uint8_t tmp94c241_device::t6ffcr_r() +{ + return m_t6ffcr; +} + +void tmp94c241_device::t6ffcr_w(uint8_t data) +{ + change_timer_flipflop( 6, data & 3 ); + change_timer_flipflop( 7, (data >> 6) & 3 ); + m_t6ffcr = data | 0xc3; +} + +uint8_t tmp94c241_device::t8ffcr_r() +{ + return m_t8ffcr; +} + +void tmp94c241_device::t8ffcr_w(uint8_t data) +{ + change_timer_flipflop( 8, data & 3 ); + change_timer_flipflop( 9, (data >> 6) & 3 ); + m_t8ffcr = data | 0xc3; +} + +uint8_t tmp94c241_device::taffcr_r() +{ + return m_taffcr; +} + +void tmp94c241_device::taffcr_w(uint8_t data) +{ + change_timer_flipflop( 0xa, data & 3 ); + change_timer_flipflop( 0xb, (data >> 6) & 3 ); + m_taffcr = data | 0xc3; +} + +uint8_t tmp94c241_device::t16run_r() +{ + return m_t16run; +} + +void tmp94c241_device::t16run_w(uint8_t data) +{ + m_t16run = data; + for (int i = 0; i < 4; i++) + { + if (!BIT(m_t16run, i)) // Timer isn't running + { + // These correspond to UP_COUNTER and TIMER_CHANGE for 16-bit timers 4, 6, 8 and A + m_timer_16[i] = 0; + m_timer_change[4 + i] = 0; + } + } +} + +template <uint8_t Timer> +uint16_t tmp94c241_device::cap_r() +{ + return m_t16_cap[Timer]; +} + +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) +{ +} + +template <uint8_t Channel> +uint8_t tmp94c241_device::scNbuf_r() +{ + return 0; +} + +template <uint8_t Channel> +void tmp94c241_device::scNbuf_w(uint8_t data) +{ + // Fake finish sending data + m_int_reg[(Channel == 0) ? INTES0 : INTES1] |= 0x80; + m_check_irqs = 1; + logerror("sc%dbuf write: %02X\n", Channel, data); + //machine().debugger().debug_break(); +} + +template <uint8_t Channel> +uint8_t tmp94c241_device::scNcr_r() +{ + uint8_t reg = m_serial_control[Channel]; + if (!machine().side_effects_disabled()) + m_serial_control[Channel] &= 0xe3; + return reg; +} + +template <uint8_t Channel> +void tmp94c241_device::scNcr_w(uint8_t data) +{ + m_serial_control[Channel] = data; +} + +template <uint8_t Channel> +uint8_t tmp94c241_device::scNmod_r() +{ + return m_serial_mode[Channel]; +} + +template <uint8_t Channel> +void tmp94c241_device::scNmod_w(uint8_t data) +{ + m_serial_mode[Channel] = data; +} + +template <uint8_t Channel> +uint8_t tmp94c241_device::brNcr_r() +{ + return m_baud_rate[Channel]; +} + +template <uint8_t Channel> +void tmp94c241_device::brNcr_w(uint8_t data) +{ + m_baud_rate[Channel] = 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 <uint8_t P> +void tmp94c241_device::port_w(uint8_t data) +{ + m_port_latch[P] = data; + m_port_write[P](0, data, 0xff); +} + +template <uint8_t P> +uint8_t tmp94c241_device::port_r() +{ + return m_port_read[P](0); +} + +template <uint8_t P> +void tmp94c241_device::port_cr_w(uint8_t data) +{ + m_port_control[P] = data; +} + +template <uint8_t P> +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<PORT_0>), FUNC(tmp94c241_device::port_w<PORT_0>)); + map(0x000002, 0x000002).w(FUNC(tmp94c241_device::port_cr_w<PORT_0>)); + map(0x000003, 0x000003).w(FUNC(tmp94c241_device::port_fc_w<PORT_0>)); + map(0x000004, 0x000004).rw(FUNC(tmp94c241_device::port_r<PORT_1>), FUNC(tmp94c241_device::port_w<PORT_1>)); + map(0x000006, 0x000006).w(FUNC(tmp94c241_device::port_cr_w<PORT_1>)); + map(0x000007, 0x000007).w(FUNC(tmp94c241_device::port_fc_w<PORT_1>)); + map(0x000008, 0x000008).rw(FUNC(tmp94c241_device::port_r<PORT_2>), FUNC(tmp94c241_device::port_w<PORT_2>)); + map(0x00000a, 0x00000a).w(FUNC(tmp94c241_device::port_cr_w<PORT_2>)); + map(0x00000b, 0x00000b).w(FUNC(tmp94c241_device::port_fc_w<PORT_2>)); + map(0x00000c, 0x00000c).rw(FUNC(tmp94c241_device::port_r<PORT_3>), FUNC(tmp94c241_device::port_w<PORT_3>)); + map(0x00000e, 0x00000e).w(FUNC(tmp94c241_device::port_cr_w<PORT_3>)); + map(0x00000f, 0x00000f).w(FUNC(tmp94c241_device::port_fc_w<PORT_3>)); + map(0x000010, 0x000010).rw(FUNC(tmp94c241_device::port_r<PORT_4>), FUNC(tmp94c241_device::port_w<PORT_4>)); + map(0x000012, 0x000012).w(FUNC(tmp94c241_device::port_cr_w<PORT_4>)); + map(0x000013, 0x000013).w(FUNC(tmp94c241_device::port_fc_w<PORT_4>)); + map(0x000014, 0x000014).rw(FUNC(tmp94c241_device::port_r<PORT_5>), FUNC(tmp94c241_device::port_w<PORT_5>)); + map(0x000016, 0x000016).w(FUNC(tmp94c241_device::port_cr_w<PORT_5>)); + map(0x000017, 0x000017).w(FUNC(tmp94c241_device::port_fc_w<PORT_5>)); + map(0x000018, 0x000018).rw(FUNC(tmp94c241_device::port_r<PORT_6>), FUNC(tmp94c241_device::port_w<PORT_6>)); + map(0x00001a, 0x00001a).w(FUNC(tmp94c241_device::port_cr_w<PORT_6>)); + map(0x00001b, 0x00001b).w(FUNC(tmp94c241_device::port_fc_w<PORT_6>)); + map(0x00001c, 0x00001c).rw(FUNC(tmp94c241_device::port_r<PORT_7>), FUNC(tmp94c241_device::port_w<PORT_7>)); + map(0x00001e, 0x00001e).w(FUNC(tmp94c241_device::port_cr_w<PORT_7>)); + map(0x00001f, 0x00001f).w(FUNC(tmp94c241_device::port_fc_w<PORT_7>)); + map(0x000020, 0x000020).rw(FUNC(tmp94c241_device::port_r<PORT_8>), FUNC(tmp94c241_device::port_w<PORT_8>)); + map(0x000022, 0x000022).w(FUNC(tmp94c241_device::port_cr_w<PORT_8>)); + map(0x000023, 0x000023).w(FUNC(tmp94c241_device::port_fc_w<PORT_8>)); + map(0x000028, 0x000028).rw(FUNC(tmp94c241_device::port_r<PORT_A>), FUNC(tmp94c241_device::port_w<PORT_A>)); + map(0x00002b, 0x00002b).w(FUNC(tmp94c241_device::port_fc_w<PORT_A>)); + map(0x00002c, 0x00002c).rw(FUNC(tmp94c241_device::port_r<PORT_B>), FUNC(tmp94c241_device::port_w<PORT_B>)); + map(0x00002f, 0x00002f).w(FUNC(tmp94c241_device::port_fc_w<PORT_B>)); + map(0x000030, 0x000030).rw(FUNC(tmp94c241_device::port_r<PORT_C>), FUNC(tmp94c241_device::port_w<PORT_C>)); + map(0x000032, 0x000032).w(FUNC(tmp94c241_device::port_cr_w<PORT_C>)); + map(0x000033, 0x000033).w(FUNC(tmp94c241_device::port_fc_w<PORT_C>)); + map(0x000034, 0x000034).rw(FUNC(tmp94c241_device::port_r<PORT_D>), FUNC(tmp94c241_device::port_w<PORT_D>)); + map(0x000036, 0x000036).w(FUNC(tmp94c241_device::port_cr_w<PORT_D>)); + map(0x000037, 0x000037).w(FUNC(tmp94c241_device::port_fc_w<PORT_D>)); + map(0x000038, 0x000038).rw(FUNC(tmp94c241_device::port_r<PORT_E>), FUNC(tmp94c241_device::port_w<PORT_E>)); + map(0x00003a, 0x00003a).w(FUNC(tmp94c241_device::port_cr_w<PORT_E>)); + map(0x00003b, 0x00003b).w(FUNC(tmp94c241_device::port_fc_w<PORT_E>)); + map(0x00003c, 0x00003c).rw(FUNC(tmp94c241_device::port_r<PORT_F>), FUNC(tmp94c241_device::port_w<PORT_F>)); + map(0x00003e, 0x00003e).w(FUNC(tmp94c241_device::port_cr_w<PORT_F>)); + map(0x00003f, 0x00003f).w(FUNC(tmp94c241_device::port_fc_w<PORT_F>)); + map(0x000040, 0x000040).r(FUNC(tmp94c241_device::port_r<PORT_G>)); + map(0x000044, 0x000044).rw(FUNC(tmp94c241_device::port_r<PORT_H>), FUNC(tmp94c241_device::port_w<PORT_H>)); + map(0x000046, 0x000046).w(FUNC(tmp94c241_device::port_cr_w<PORT_H>)); + map(0x000047, 0x000047).w(FUNC(tmp94c241_device::port_fc_w<PORT_H>)); + map(0x000068, 0x000068).rw(FUNC(tmp94c241_device::port_r<PORT_Z>), FUNC(tmp94c241_device::port_w<PORT_Z>)); + map(0x00006a, 0x00006a).w(FUNC(tmp94c241_device::port_cr_w<PORT_Z>)); + 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::tffcr_r), FUNC(tmp94c241_device::tffcr_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, 0x000088).w(FUNC(tmp94c241_device::treg_8_w<TREG0>)); + map(0x000089, 0x000089).w(FUNC(tmp94c241_device::treg_8_w<TREG1>)); + map(0x00008a, 0x00008a).w(FUNC(tmp94c241_device::treg_8_w<TREG2>)); + map(0x00008b, 0x00008b).w(FUNC(tmp94c241_device::treg_8_w<TREG3>)); + map(0x000090, 0x000091).w(FUNC(tmp94c241_device::treg_16_w<TREG4>)); + map(0x000092, 0x000093).w(FUNC(tmp94c241_device::treg_16_w<TREG5>)); + map(0x000094, 0x000095).r(FUNC(tmp94c241_device::cap_r<CAP4>)); + map(0x000096, 0x000097).r(FUNC(tmp94c241_device::cap_r<CAP5>)); + 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, 0x0000a1).w(FUNC(tmp94c241_device::treg_16_w<TREG6>)); + map(0x0000a2, 0x0000a3).w(FUNC(tmp94c241_device::treg_16_w<TREG7>)); + map(0x0000a4, 0x0000a5).r(FUNC(tmp94c241_device::cap_r<CAP6>)); + map(0x0000a6, 0x0000a7).r(FUNC(tmp94c241_device::cap_r<CAP7>)); + 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, 0x0000b1).w(FUNC(tmp94c241_device::treg_16_w<TREG8>)); + map(0x0000b2, 0x0000b3).w(FUNC(tmp94c241_device::treg_16_w<TREG9>)); + map(0x0000b4, 0x0000b5).r(FUNC(tmp94c241_device::cap_r<CAP8>)); + map(0x0000b6, 0x0000b7).r(FUNC(tmp94c241_device::cap_r<CAP9>)); + 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, 0x0000c1).w(FUNC(tmp94c241_device::treg_16_w<TREGA>)); + map(0x0000c2, 0x0000c3).w(FUNC(tmp94c241_device::treg_16_w<TREGB>)); + map(0x0000c4, 0x0000c5).r(FUNC(tmp94c241_device::cap_r<CAPA>)); + map(0x0000c6, 0x0000c7).r(FUNC(tmp94c241_device::cap_r<CAPB>)); + 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::scNbuf_r<0>), FUNC(tmp94c241_device::scNbuf_w<0>)); + map(0x0000d1, 0x0000d1).rw(FUNC(tmp94c241_device::scNcr_r<0>), FUNC(tmp94c241_device::scNcr_w<0>)); + map(0x0000d2, 0x0000d2).rw(FUNC(tmp94c241_device::scNmod_r<0>), FUNC(tmp94c241_device::scNmod_w<0>)); + map(0x0000d3, 0x0000d3).rw(FUNC(tmp94c241_device::brNcr_r<0>), FUNC(tmp94c241_device::brNcr_w<0>)); + map(0x0000d4, 0x0000d4).rw(FUNC(tmp94c241_device::scNbuf_r<1>), FUNC(tmp94c241_device::scNbuf_w<1>)); + map(0x0000d5, 0x0000d5).rw(FUNC(tmp94c241_device::scNcr_r<1>), FUNC(tmp94c241_device::scNcr_w<1>)); + map(0x0000d6, 0x0000d6).rw(FUNC(tmp94c241_device::scNmod_r<1>), FUNC(tmp94c241_device::scNmod_w<1>)); + map(0x0000d7, 0x0000d7).rw(FUNC(tmp94c241_device::brNcr_r<1>), FUNC(tmp94c241_device::brNcr_w<1>)); + 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::bNcs_w<0>)); + map(0x000142, 0x000142).rw(FUNC(tmp94c241_device::mamr_r<0>), FUNC(tmp94c241_device::mamr_w<0>)); + map(0x000143, 0x000143).rw(FUNC(tmp94c241_device::msar_r<0>), FUNC(tmp94c241_device::msar_w<0>)); + map(0x000144, 0x000145).w(FUNC(tmp94c241_device::bNcs_w<1>)); + map(0x000146, 0x000146).rw(FUNC(tmp94c241_device::mamr_r<1>), FUNC(tmp94c241_device::mamr_w<1>)); + map(0x000147, 0x000147).rw(FUNC(tmp94c241_device::msar_r<1>), FUNC(tmp94c241_device::msar_w<1>)); + map(0x000148, 0x000149).w(FUNC(tmp94c241_device::bNcs_w<2>)); + map(0x00014a, 0x00014a).rw(FUNC(tmp94c241_device::mamr_r<2>), FUNC(tmp94c241_device::mamr_w<2>)); + map(0x00014b, 0x00014b).rw(FUNC(tmp94c241_device::msar_r<2>), FUNC(tmp94c241_device::msar_w<2>)); + map(0x00014c, 0x00014d).w(FUNC(tmp94c241_device::bNcs_w<3>)); + map(0x00014e, 0x00014e).rw(FUNC(tmp94c241_device::mamr_r<3>), FUNC(tmp94c241_device::mamr_w<3>)); + map(0x00014f, 0x00014f).rw(FUNC(tmp94c241_device::msar_r<3>), FUNC(tmp94c241_device::msar_w<3>)); + map(0x000150, 0x000151).w(FUNC(tmp94c241_device::bNcs_w<4>)); + map(0x000152, 0x000152).rw(FUNC(tmp94c241_device::mamr_r<4>), FUNC(tmp94c241_device::mamr_w<4>)); + map(0x000153, 0x000153).rw(FUNC(tmp94c241_device::msar_r<4>), FUNC(tmp94c241_device::msar_w<4>)); + map(0x000154, 0x000155).w(FUNC(tmp94c241_device::bNcs_w<5>)); + map(0x000156, 0x000156).rw(FUNC(tmp94c241_device::mamr_r<5>), FUNC(tmp94c241_device::mamr_w<5>)); + map(0x000157, 0x000157).rw(FUNC(tmp94c241_device::msar_r<5>), FUNC(tmp94c241_device::msar_w<5>)); + map(0x000400, 0x000bff).ram(); +} + +//************************************************************************** +// EXECUTION CALLBACKS +//************************************************************************** + +//------------------------------------------------- +// tlcs900_check_hdma - +//------------------------------------------------- + +void tmp94c241_device::tlcs900_check_hdma() +{ +} + + +//------------------------------------------------- +// tlcs900_check_irqs - +//------------------------------------------------- + +void tmp94c241_device::tlcs900_check_irqs() +{ + // 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. */ + int irq_vectors[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; + for (int 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 + int irq = -1; + int level = 0; + for (int 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 - +//------------------------------------------------- + +// Prescaler shift amounts corresponding to each possible timer input clock source: +static constexpr uint8_t T1 = 3; +static constexpr uint8_t T4 = 5; +static constexpr uint8_t T16 = 7; +static constexpr uint8_t T256 = 11; + +void tmp94c241_device::tlcs900_handle_timers() +{ + auto const update_timer_count = + [this, old_pre = m_timer_pre] ( + uint8_t timer_index, + uint8_t input_clk_select, + uint8_t s1, + uint8_t s2, + uint8_t s3) + { + switch (input_clk_select) + { + case 0: + /* Not yet implemented. + - For the 8 bit timers: TIO, TO0TRG, invalid and TO2TRG + - For all 16 bit timers: TIA + */ + break; + case 1: m_timer_change[timer_index] += ((m_timer_pre >> s1) - (old_pre >> s1)); break; + case 2: m_timer_change[timer_index] += ((m_timer_pre >> s2) - (old_pre >> s2)); break; + case 3: m_timer_change[timer_index] += ((m_timer_pre >> s3) - (old_pre >> s3)); break; + } + }; + + auto const timer_8bits = + [this] ( + uint8_t timer_index, + uint8_t timer_reg, + uint8_t interrupt, + uint8_t interrupt_mask, + uint8_t operating_mode, + bool invert) + { + for ( ; m_timer_change[timer_index] > 0; m_timer_change[timer_index]--) + { + m_timer_8[timer_index]++; + if (m_timer_8[timer_index] == m_treg_8[timer_reg]) + { + if (BIT(timer_index, 0) == 0) + { + if (operating_mode == 0) // mode == MODE_8BIT_TIMER + m_timer_change[timer_index | 1]++; + + // In 16-bit timer mode the timer should not be reset + if (operating_mode != 1) // mode != MODE_16BIT_TIMER + { + m_timer_8[timer_index] = 0; + m_int_reg[interrupt] |= interrupt_mask; + m_check_irqs = 1; + } + } + else + { + m_timer_8[timer_index] = 0; + m_int_reg[interrupt] |= interrupt_mask; + m_check_irqs = 1; + + // In 16-bit timer mode also reset its 8-bit counterpart (timer N-1) + if (operating_mode == 1) // mode == MODE_16BIT_TIMER + m_timer_8[timer_index & ~1] = 0; + } + + if (invert) + change_timer_flipflop(timer_index | 1, FF_INVERT); + } + } + }; + + auto const timer_16bits = + [this] ( + uint8_t timer_id, + uint8_t timer_reg_low, + uint8_t timer_reg_high, + uint8_t tffcr, + uint8_t interrupt) + { + /* + timer_id 4 => m_timer_16[0] m_timer_change[4] + timer_id 6 => m_timer_16[1] m_timer_change[5] + timer_id 8 => m_timer_16[2] m_timer_change[6] + timer_id A => m_timer_16[3] m_timer_change[7] + */ + uint8_t timer_index = (timer_id - 4)/2; + + for ( ; m_timer_change[timer_index + 4] > 0; m_timer_change[timer_index + 4]--) + { + m_timer_16[timer_index]++; + // TODO: also check for criteria of up counter matching CAPn registers + if (((m_timer_16[timer_index] == m_treg_16[timer_reg_high]) && BIT(tffcr, 3)) || + ((m_timer_16[timer_index] == m_treg_16[timer_reg_low]) && BIT(tffcr, 2)) ) + { + change_timer_flipflop(timer_id, FF_INVERT); + m_timer_16[timer_index] = 0; + m_int_reg[interrupt] |= 0x08; + m_check_irqs = 1; + } + } + }; + + if (BIT(m_t16run, 7)) // prescaler is active + m_timer_pre += m_cycles; + + if (BIT(m_t8run, 0)) // Timer 0 is running + { + update_timer_count(0, m_t01mod & 3, T1, T4, T16); + timer_8bits( + 0, TREG0, INTET01, 0x08, + (m_t01mod >> 6) & 3, // TO1_OPERATING_MODE + (m_tffcr & 3) == 2); // "FF1 Invert Enable" && "Invert by 8-bit timer 0" + } + + if (BIT(m_t8run, 1)) // Timer 1 is running + { + update_timer_count(1, (m_t01mod >> 2) & 3, T1, T16, T256); + timer_8bits( + 1, TREG1, INTET01, 0x80, + (m_t01mod >> 6) & 3, // TO1_OPERATING_MODE + (m_tffcr & 3) == 3); // "FF1 Invert Enable" && "Invert by 8-bit timer 1" + } + + if (BIT(m_t8run, 2)) // Timer 2 is running + { + update_timer_count(2, m_t23mod & 3, T1, T4, T16); + timer_8bits( + 2, TREG2, INTET23, 0x08, + (m_t23mod >> 6) & 3, // T23_OPERATING_MODE + ((m_tffcr >> 4) & 3) == 2); // "FF3 Invert Enable" && "Invert by 8-bit timer 2" + } + + if (BIT(m_t8run, 3)) // Timer 3 is running + { + update_timer_count(3, (m_t23mod >> 2) & 3, T1, T16, T256); + timer_8bits( + 3, TREG3, INTET23, 0x80, + (m_t23mod >> 6) & 3, // T23_OPERATING_MODE + ((m_tffcr >> 4) & 3) == 3); // "FF3 Invert Enable" && "Invert by 8-bit timer 3" + } + + if (BIT(m_t16run, 0)) // Timer 4 is running + { + update_timer_count(4, m_t4mod & 3, T1, T4, T16); + timer_16bits(4, TREG4, TREG5, m_t4ffcr, INTET45); + } + + if (BIT(m_t16run, 1)) // Timer 6 is running + { + update_timer_count(5, m_t6mod & 3, T1, T4, T16); + timer_16bits(6, TREG6, TREG7, m_t6ffcr, INTET67); + } + + if (BIT(m_t16run, 2)) // Timer 8 is running + { + update_timer_count(6, m_t8mod & 3, T1, T4, T16); + timer_16bits(8, TREG8, TREG9, m_t8ffcr, INTET89); + } + + if (BIT(m_t16run, 3)) // Timer A is running + { + update_timer_count(7, m_tamod & 3, T1, T4, T16); + timer_16bits(0xa, TREGA, TREGB, m_taffcr, INTETAB); + } + + m_timer_pre &= 0xffffff; +} + + +//------------------------------------------------- +// execute_set_input - called when a synchronized +// input is changed +//------------------------------------------------- + +void tmp94c241_device::execute_set_input(int input, int level) +{ + auto const update_int_reg = + [this, level, input] (uint8_t reg, uint8_t mask) + { + if (level != m_level[input]) + { + m_level[input] = level; + if (level == ASSERT_LINE) + m_int_reg[reg] |= mask; + else + m_int_reg[reg] &= ~mask; + } + }; + + switch (input) + { + case INPUT_LINE_NMI: + case TLCS900_NMI: + if (level != m_level[TLCS900_NMI]) + { + m_level[TLCS900_NMI] = level; + if (level == ASSERT_LINE) + m_nmi_state = ASSERT_LINE; + } + break; + + case TLCS900_INTWD: + break; + + case TLCS900_INT0: + if (m_iimc & 0x02) + { + // Rising edge detect + if (level != m_level[TLCS900_INT0] && level == ASSERT_LINE) + { + // Leave HALT state + m_halted = 0; + m_int_reg[INTE0AD] |= 0x08; + } + m_level[TLCS900_INT0] = level; + } + else + { + // Level detect + update_int_reg(INTE0AD, 0x08); + } + break; + + case TLCS900_INT4: update_int_reg(INTE45, 0x08); break; + case TLCS900_INT5: update_int_reg(INTE45, 0x80); break; + case TLCS900_INT6: update_int_reg(INTE67, 0x08); break; + case TLCS900_INT7: update_int_reg(INTE67, 0x80); break; + case TLCS900_INT8: update_int_reg(INTE89, 0x08); break; + case TLCS900_INT9: update_int_reg(INTE89, 0x80); break; + case TLCS900_INTA: update_int_reg(INTEAB, 0x08); break; + case TLCS900_INTB: update_int_reg(INTEAB, 0x80); break; + + default: + // invalid + return; + } + m_check_irqs = 1; +} + +std::unique_ptr<util::disasm_interface> tmp94c241_device::create_disassembler() +{ + return std::make_unique<tlcs900_disassembler>(); +} diff --git a/src/devices/cpu/tlcs900/tmp94c241.h b/src/devices/cpu/tlcs900/tmp94c241.h new file mode 100644 index 00000000000..bb83a748f73 --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp94c241.h @@ -0,0 +1,279 @@ +// license:BSD-3-Clause +// copyright-holders:AJR,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; + + static constexpr uint8_t TREG0 = 0; + static constexpr uint8_t TREG1 = 1; + static constexpr uint8_t TREG2 = 2; + static constexpr uint8_t TREG3 = 3; + static constexpr uint8_t TREG4 = 0; + static constexpr uint8_t TREG5 = 1; + static constexpr uint8_t TREG6 = 2; + static constexpr uint8_t TREG7 = 3; + static constexpr uint8_t TREG8 = 4; + static constexpr uint8_t TREG9 = 5; + static constexpr uint8_t TREGA = 6; + static constexpr uint8_t TREGB = 7; + + static constexpr uint8_t CAP4 = 0; + static constexpr uint8_t CAP5 = 1; + static constexpr uint8_t CAP6 = 2; + static constexpr uint8_t CAP7 = 3; + static constexpr uint8_t CAP8 = 4; + static constexpr uint8_t CAP9 = 5; + static constexpr uint8_t CAPA = 6; + static constexpr uint8_t CAPB = 7; + +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 ATTR_COLD; + virtual void device_resolve_objects() override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + // 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<util::disasm_interface> create_disassembler() override; + +private: + void change_timer_flipflop(uint8_t flipflop, uint8_t operation); + + // Ports + template <uint8_t P> uint8_t port_r(); + template <uint8_t P> void port_w(uint8_t data); + template <uint8_t P> void port_cr_w(uint8_t data); + template <uint8_t P> void port_fc_w(uint8_t data); + + // Special Function Registers + template <uint8_t N> void bNcs_w(offs_t offset, uint16_t data, uint16_t mem_mask); + template <uint8_t Timer> uint16_t cap_r(); + template <uint8_t N> uint8_t mamr_r(); + template <uint8_t N> void mamr_w(uint8_t data); + template <uint8_t N> uint8_t msar_r(); + template <uint8_t N> void msar_w(uint8_t data); + template <uint8_t Timer> void treg_8_w(uint8_t data); + template <uint8_t Timer> void treg_16_w(uint16_t data); + template <uint8_t Channel> uint8_t scNbuf_r(); + template <uint8_t Channel> void scNbuf_w(uint8_t data); + template <uint8_t Channel> uint8_t scNcr_r(); + template <uint8_t Channel> void scNcr_w(uint8_t data); + template <uint8_t Channel> uint8_t scNmod_r(); + template <uint8_t Channel> void scNmod_w(uint8_t data); + template <uint8_t Channel> uint8_t brNcr_r(); + template <uint8_t Channel> void brNcr_w(uint8_t data); + uint8_t t8run_r(); + void t8run_w(uint8_t data); + uint8_t t01mod_r(); + void t01mod_w(uint8_t data); + uint8_t tffcr_r(); + void tffcr_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); + 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 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); + 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<NUM_PORTS> m_port_read; + devcb_write8::array<NUM_PORTS> 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 + bool m_timer_flipflops[12]; + uint8_t m_t8run; + uint8_t m_t01mod; + uint8_t m_t23mod; + uint8_t m_t4mod; + uint8_t m_t6mod; + uint8_t m_t8mod; + uint8_t m_tamod; + uint8_t m_tffcr; + uint8_t m_t4ffcr; + uint8_t m_t6ffcr; + uint8_t m_t8ffcr; + uint8_t m_taffcr; + uint8_t m_trdc; + uint8_t m_t16run; + uint8_t m_treg_8[4]; // TREG0 - TREG3 + uint16_t m_treg_16[8]; //TREG4 - TREGB + uint16_t m_t16_cap[8]; //CAP4 - CAPB + uint16_t m_timer_16[4]; // UPCOUNTERA - UPCOUNTERB + + // 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_msar[6]; + uint8_t m_mamr[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 55c591cc745..e6dbf029ac8 100644 --- a/src/devices/cpu/tlcs900/tmp95c061.cpp +++ b/src/devices/cpu/tlcs900/tmp95c061.cpp @@ -191,6 +191,15 @@ void tmp95c061_device::device_config_complete() } +void tmp95c061_device::device_resolve_objects() +{ + m_nmi_state = CLEAR_LINE; + for( int i = 0; i < TLCS900_NUM_INPUTS; i++ ) + { + m_level[i] = CLEAR_LINE; + } +} + void tmp95c061_device::device_start() { @@ -239,7 +248,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 +297,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 @@ -492,11 +495,6 @@ void tmp95c061_device::tlcs900_check_hdma() void tmp95c061_device::tlcs900_check_irqs() { - int irq_vectors[9] = { -1, -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 ) { @@ -516,7 +514,8 @@ void tmp95c061_device::tlcs900_check_irqs() } /* Check regular irqs */ - for( i = 0; i < NUM_MASKABLE_IRQS; i++ ) + int irq_vectors[9] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 }; + for( int i = 0; i < NUM_MASKABLE_IRQS; i++ ) { if ( m_int_reg[tmp95c061_irq_vector_map[i].reg] & tmp95c061_irq_vector_map[i].iff ) { @@ -533,7 +532,9 @@ void tmp95c061_device::tlcs900_check_irqs() } /* Check highest allowed priority irq */ - for ( i = std::max( 1, ( ( m_sr.b.h & 0x70 ) >> 4 ) ); i < 7; i++ ) + int irq = -1; + int level = 0; + for ( int i = std::max( 1, ( ( m_sr.b.h & 0x70 ) >> 4 ) ); i < 7; i++ ) { if ( irq_vectors[i] >= 0 ) { @@ -690,8 +691,8 @@ void tmp95c061_device::tlcs900_handle_timers() for( ; m_timer_change[0] > 0; m_timer_change[0]-- ) { - m_timer[0] += 1; - if ( m_timer[0] == m_t8_reg[0] ) + m_timer_8[0] += 1; + if ( m_timer_8[0] == m_t8_reg[0] ) { if ( ( m_trun & 0x02 ) && ( m_t8_mode[0] & 0x0c ) == 0x00 ) { @@ -701,7 +702,7 @@ void tmp95c061_device::tlcs900_handle_timers() /* In 16bit timer mode the timer should not be reset */ if ( ( m_t8_mode[0] & 0xc0 ) != 0x40 ) { - m_timer[0] = 0; + m_timer_8[0] = 0; m_int_reg[INTET10] |= 0x08; } } @@ -728,10 +729,10 @@ void tmp95c061_device::tlcs900_handle_timers() for( ; m_timer_change[1] > 0; m_timer_change[1]-- ) { - m_timer[1] += 1; - if ( m_timer[1] == m_t8_reg[1] ) + m_timer_8[1] += 1; + if ( m_timer_8[1] == m_t8_reg[1] ) { - m_timer[1] = 0; + m_timer_8[1] = 0; m_int_reg[INTET10] |= 0x80; if ( m_t8_invert & 0x02 ) @@ -742,7 +743,7 @@ void tmp95c061_device::tlcs900_handle_timers() /* In 16bit timer mode also reset timer 0 */ if ( ( m_t8_mode[0] & 0xc0 ) == 0x40 ) { - m_timer[0] = 0; + m_timer_8[0] = 0; } } } @@ -767,8 +768,8 @@ void tmp95c061_device::tlcs900_handle_timers() for( ; m_timer_change[2] > 0; m_timer_change[2]-- ) { - m_timer[2] += 1; - if ( m_timer[2] == m_t8_reg[2] ) + m_timer_8[2] += 1; + if ( m_timer_8[2] == m_t8_reg[2] ) { if ( ( m_trun & 0x08 ) && ( m_t8_mode[1] & 0x0c ) == 0x00 ) { @@ -778,7 +779,7 @@ void tmp95c061_device::tlcs900_handle_timers() /* In 16bit timer mode the timer should not be reset */ if ( ( m_t8_mode[1] & 0xc0 ) != 0x40 ) { - m_timer[2] = 0; + m_timer_8[2] = 0; m_int_reg[INTET32] |= 0x08; } } @@ -805,10 +806,10 @@ void tmp95c061_device::tlcs900_handle_timers() for( ; m_timer_change[3] > 0; m_timer_change[3]-- ) { - m_timer[3] += 1; - if ( m_timer[3] == m_t8_reg[3] ) + m_timer_8[3] += 1; + if ( m_timer_8[3] == m_t8_reg[3] ) { - m_timer[3] = 0; + m_timer_8[3] = 0; m_int_reg[INTET32] |= 0x80; if ( m_t8_invert & 0x20 ) @@ -819,7 +820,7 @@ void tmp95c061_device::tlcs900_handle_timers() /* In 16bit timer mode also reset timer 2 */ if ( ( m_t8_mode[1] & 0xc0 ) == 0x40 ) { - m_timer[2] = 0; + m_timer_8[2] = 0; } } } @@ -916,28 +917,28 @@ void tmp95c061_device::trun_w(uint8_t data) { if ( ! ( data & 0x01 ) ) { - m_timer[0] = 0; + m_timer_8[0] = 0; m_timer_change[0] = 0; } if ( ! ( data & 0x02 ) ) { - m_timer[1] = 0; + m_timer_8[1] = 0; m_timer_change[1] = 0; } if ( ! ( data & 0x04 ) ) { - m_timer[2] = 0; + m_timer_8[2] = 0; m_timer_change[2] = 0; } if ( ! ( data & 0x08 ) ) { - m_timer[3] = 0; + m_timer_8[3] = 0; m_timer_change[3] = 0; } if ( ! ( data & 0x10 ) ) - m_timer[4] = 0; + m_timer_8[4] = 0; if ( ! ( data & 0x20 ) ) - m_timer[5] = 0; + m_timer_8[5] = 0; m_trun = data; } diff --git a/src/devices/cpu/tlcs900/tmp95c061.h b/src/devices/cpu/tlcs900/tmp95c061.h index 7b52057fa2d..031ba79f727 100644 --- a/src/devices/cpu/tlcs900/tmp95c061.h +++ b/src/devices/cpu/tlcs900/tmp95c061.h @@ -47,7 +47,8 @@ public: template <size_t Bit> auto an_read() { return m_an_read[Bit].bind(); } protected: - virtual void device_config_complete() override; + virtual void device_config_complete() override ATTR_COLD; + virtual void device_resolve_objects() override ATTR_COLD; virtual void device_start() override ATTR_COLD; virtual void device_reset() override ATTR_COLD; diff --git a/src/devices/cpu/tlcs900/tmp95c063.cpp b/src/devices/cpu/tlcs900/tmp95c063.cpp index 05b79834eb5..23f4025a411 100644 --- a/src/devices/cpu/tlcs900/tmp95c063.cpp +++ b/src/devices/cpu/tlcs900/tmp95c063.cpp @@ -271,8 +271,8 @@ void tmp95c063_device::tlcs900_handle_timers() for( ; m_timer_change[0] > 0; m_timer_change[0]-- ) { - m_timer[0] += 1; - if ( m_timer[0] == m_t8_reg[0] ) + m_timer_8[0] += 1; + if ( m_timer_8[0] == m_t8_reg[0] ) { if ( ( m_t8run & 0x02 ) && ( m_t8_mode[0] & 0x0c ) == 0x00 ) { @@ -282,7 +282,7 @@ void tmp95c063_device::tlcs900_handle_timers() /* In 16bit timer mode the timer should not be reset */ if ( ( m_t8_mode[0] & 0xc0 ) != 0x40 ) { - m_timer[0] = 0; + m_timer_8[0] = 0; m_int_reg[INTET01] |= 0x08; } } @@ -309,10 +309,10 @@ void tmp95c063_device::tlcs900_handle_timers() for( ; m_timer_change[1] > 0; m_timer_change[1]-- ) { - m_timer[1] += 1; - if ( m_timer[1] == m_t8_reg[1] ) + m_timer_8[1] += 1; + if ( m_timer_8[1] == m_t8_reg[1] ) { - m_timer[1] = 0; + m_timer_8[1] = 0; m_int_reg[INTET01] |= 0x80; if ( m_t8_invert[0] & 0x02 ) @@ -323,7 +323,7 @@ void tmp95c063_device::tlcs900_handle_timers() /* In 16bit timer mode also reset timer 0 */ if ( ( m_t8_mode[0] & 0xc0 ) == 0x40 ) { - m_timer[0] = 0; + m_timer_8[0] = 0; } } } @@ -348,8 +348,8 @@ void tmp95c063_device::tlcs900_handle_timers() for( ; m_timer_change[2] > 0; m_timer_change[2]-- ) { - m_timer[2] += 1; - if ( m_timer[2] == m_t8_reg[2] ) + m_timer_8[2] += 1; + if ( m_timer_8[2] == m_t8_reg[2] ) { if ( ( m_t8run & 0x08 ) && ( m_t8_mode[1] & 0x0c ) == 0x00 ) { @@ -359,7 +359,7 @@ void tmp95c063_device::tlcs900_handle_timers() /* In 16bit timer mode the timer should not be reset */ if ( ( m_t8_mode[1] & 0xc0 ) != 0x40 ) { - m_timer[2] = 0; + m_timer_8[2] = 0; m_int_reg[INTET23] |= 0x08; } } @@ -386,10 +386,10 @@ void tmp95c063_device::tlcs900_handle_timers() for( ; m_timer_change[3] > 0; m_timer_change[3]-- ) { - m_timer[3] += 1; - if ( m_timer[3] == m_t8_reg[3] ) + m_timer_8[3] += 1; + if ( m_timer_8[3] == m_t8_reg[3] ) { - m_timer[3] = 0; + m_timer_8[3] = 0; m_int_reg[INTET23] |= 0x80; if ( m_t8_invert[1] & 0x20 ) @@ -400,7 +400,7 @@ void tmp95c063_device::tlcs900_handle_timers() /* In 16bit timer mode also reset timer 2 */ if ( ( m_t8_mode[1] & 0xc0 ) == 0x40 ) { - m_timer[2] = 0; + m_timer_8[2] = 0; } } } @@ -416,11 +416,6 @@ void tmp95c063_device::tlcs900_check_hdma() void tmp95c063_device::tlcs900_check_irqs() { - int irq_vectors[9] = { -1, -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 ) { @@ -440,7 +435,8 @@ void tmp95c063_device::tlcs900_check_irqs() } /* Check regular irqs */ - for( i = 0; i < NUM_MASKABLE_IRQS; i++ ) + int irq_vectors[9] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 }; + for( int i = 0; i < NUM_MASKABLE_IRQS; i++ ) { if ( m_int_reg[tmp95c063_irq_vector_map[i].reg] & tmp95c063_irq_vector_map[i].iff ) { @@ -457,7 +453,9 @@ void tmp95c063_device::tlcs900_check_irqs() } /* Check highest allowed priority irq */ - for ( i = std::max( 1, ( ( m_sr.b.h & 0x70 ) >> 4 ) ); i < 7; i++ ) + int irq = -1; + int level = 0; + for ( int i = std::max( 1, ( ( m_sr.b.h & 0x70 ) >> 4 ) ); i < 7; i++ ) { if ( irq_vectors[i] >= 0 ) { @@ -557,6 +555,15 @@ void tmp95c063_device::tlcs900_handle_ad() } +void tmp95c063_device::device_resolve_objects() +{ + m_nmi_state = CLEAR_LINE; + for( int i = 0; i < TLCS900_NUM_INPUTS; i++ ) + { + m_level[i] = CLEAR_LINE; + } +} + void tmp95c063_device::device_start() { tlcs900h_device::device_start(); @@ -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() @@ -669,28 +672,28 @@ void tmp95c063_device::t8run_w(uint8_t data) { if ( ! ( data & 0x01 ) ) { - m_timer[0] = 0; + m_timer_8[0] = 0; m_timer_change[0] = 0; } if ( ! ( data & 0x02 ) ) { - m_timer[1] = 0; + m_timer_8[1] = 0; m_timer_change[1] = 0; } if ( ! ( data & 0x04 ) ) { - m_timer[2] = 0; + m_timer_8[2] = 0; m_timer_change[2] = 0; } if ( ! ( data & 0x08 ) ) { - m_timer[3] = 0; + m_timer_8[3] = 0; m_timer_change[3] = 0; } if ( ! ( data & 0x10 ) ) - m_timer[4] = 0; + m_timer_8[4] = 0; if ( ! ( data & 0x20 ) ) - m_timer[5] = 0; + m_timer_8[5] = 0; m_t8run = data; } diff --git a/src/devices/cpu/tlcs900/tmp95c063.h b/src/devices/cpu/tlcs900/tmp95c063.h index acbcfc10f3c..32033aad155 100644 --- a/src/devices/cpu/tlcs900/tmp95c063.h +++ b/src/devices/cpu/tlcs900/tmp95c063.h @@ -57,7 +57,8 @@ public: template <size_t Bit> auto an_read() { return m_an_read[Bit].bind(); } protected: - virtual void device_config_complete() override; + virtual void device_config_complete() override ATTR_COLD; + virtual void device_resolve_objects() override ATTR_COLD; virtual void device_start() override ATTR_COLD; virtual void device_reset() override ATTR_COLD; diff --git a/src/mame/matsushita/kn5000.cpp b/src/mame/matsushita/kn5000.cpp index 64023b65aaa..d6678bdad5b 100644 --- a/src/mame/matsushita/kn5000.cpp +++ b/src/mame/matsushita/kn5000.cpp @@ -7,7 +7,7 @@ ******************************************************************************/ #include "emu.h" -#include "cpu/tlcs900/tmp95c061.h" // TODO: tmp94c241.h +#include "cpu/tlcs900/tmp94c241.h" #include "imagedev/floppy.h" #include "machine/gen_latch.h" #include "machine/upd765.h" @@ -109,8 +109,8 @@ public: void kn5000(machine_config &config); private: - required_device<tmp95c061_device> m_maincpu; - required_device<tmp95c061_device> m_subcpu; + required_device<tmp94c241_device> m_maincpu; + required_device<tmp94c241_device> m_subcpu; required_device<generic_latch_8_device> m_maincpu_latch; required_device<generic_latch_8_device> m_subcpu_latch; required_device<upd72067_device> m_fdc; @@ -197,6 +197,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 ) @@ -604,7 +635,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 @@ -636,14 +667,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 +684,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 +703,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: @@ -701,15 +731,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 +750,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 |