diff options
Diffstat (limited to 'src/mame/drivers/intellec4.cpp')
-rw-r--r-- | src/mame/drivers/intellec4.cpp | 1470 |
1 files changed, 0 insertions, 1470 deletions
diff --git a/src/mame/drivers/intellec4.cpp b/src/mame/drivers/intellec4.cpp deleted file mode 100644 index 8ea1f468107..00000000000 --- a/src/mame/drivers/intellec4.cpp +++ /dev/null @@ -1,1470 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Vas Crabb -/* - Intel INTELLEC® 4 - - The MOD 4 system has a 4004/4008/4009 chipset. It has front panel - switches for holding or pulsing the CPU's TEST line, and a CPU LED - driven by clock phase 2. - - The MOD 40 system has a 4040/4289 chipset. It replaces the TEST - switches with STOP and SINGLE STEP switches, and replaces the CPU LED - with a RUN LED that's lit when the CPU isn't acknowledging a STOP or - HALT condition. - - The MOD 4 and MOD 40 systems use the same monitor PROM. The monitor - program doesn't use any 4040-specific features, and the console RAM - readback feature avoids the need for the RPM instruction by latching - the data and reading it through the ROM port space. - - Strictly speaking, the INTELLEC® 4 and INTELLEC® 4/MOD 4 are different - machines. The former uses an earlier control board without support - for MOD 40 features; the latter uses the same control board as the - MOD 40 jumpered to provide TEST line control rather than 4040 STOP - and SINGLE STEP features. - - The MOD 40 repurposes the pins originally used for ROM 1 input port - lines to expose stop/interrupt request/acknowledge. It's pretty - obvious that the MOD 40 was designed as a minimal modification. A - set of X1 display LEDs would have been fantastic, as it would show the - contents of the accumulator with the 4040 CPU, while the X3 LEDs really - aren't very useful. However, since the 4004 just echoes M2 during X1, - the control board has no provision for latching data during this cycle - and would have required significant layout changes to cater for this. - - Set the terminal for 110 1/8/N/2 to talk to the monitor. - It only accepts uppercase letters, digits, comma, and carriage return. - Paper tape reader run/stop is sent to RTS on the serial port. - - TODO: - * Expose general-purpose I/O? - */ -#include "emu.h" - -#include "machine/imm6_76.h" - -#include "bus/intellec4/intellec4.h" -#include "bus/rs232/rs232.h" -#include "cpu/mcs40/mcs40.h" -#include "machine/bankdev.h" - -#include "intlc44.lh" -#include "intlc440.lh" - - -namespace { - -/*********************************************************************** - INTELLEC® 4 base driver -***********************************************************************/ - -class intellec4_state : public driver_device -{ -public: - void bus_cycle(mcs40_cpu_device_base::phase step, u8 sync, u8 data); - - DECLARE_READ8_MEMBER(pm_read); - DECLARE_WRITE8_MEMBER(pm_write); - - DECLARE_READ8_MEMBER(rom0_in); - DECLARE_READ8_MEMBER(rom2_in); - DECLARE_READ8_MEMBER(rom3_in); - DECLARE_READ8_MEMBER(rome_in); - DECLARE_READ8_MEMBER(romf_in); - - DECLARE_WRITE8_MEMBER(rom0_out); - DECLARE_WRITE8_MEMBER(rom1_out); - DECLARE_WRITE8_MEMBER(rom2_out); - DECLARE_WRITE8_MEMBER(rom3_out); - DECLARE_WRITE8_MEMBER(rome_out); - DECLARE_WRITE8_MEMBER(romf_out); - - DECLARE_WRITE8_MEMBER(ram0_out); - DECLARE_WRITE8_MEMBER(ram1_out); - - // universal slot outputs - DECLARE_WRITE_LINE_MEMBER(bus_reset_4002); - DECLARE_WRITE_LINE_MEMBER(bus_user_reset); - - // front panel switches - DECLARE_INPUT_CHANGED_MEMBER(sw_reset); - DECLARE_INPUT_CHANGED_MEMBER(sw_reset_mode); - template <unsigned N> DECLARE_INPUT_CHANGED_MEMBER(sw_prg_mode); - DECLARE_INPUT_CHANGED_MEMBER(sw_run); - DECLARE_INPUT_CHANGED_MEMBER(sw_next_inst); - DECLARE_INPUT_CHANGED_MEMBER(sw_decr); - DECLARE_INPUT_CHANGED_MEMBER(sw_incr); - DECLARE_INPUT_CHANGED_MEMBER(sw_load); - DECLARE_INPUT_CHANGED_MEMBER(sw_cma_enable); - DECLARE_INPUT_CHANGED_MEMBER(sw_cma_write); - DECLARE_INPUT_CHANGED_MEMBER(sw_prgm_pwr); - DECLARE_INPUT_CHANGED_MEMBER(sw_do_enable); - -protected: - intellec4_state(machine_config const &mconfig, device_type type, char const *tag) - : driver_device(mconfig, type, tag) - , m_cpu(*this, "maincpu") - , m_bus(*this, "bus") - , m_prg_ram(*this, "ram") - , m_sw_mode(*this, "MODE") - , m_program_banks(*this, "prgbank") - , m_rom_port_banks(*this, "rpbank") - , m_prom_programmer(*this, "promprg") - , m_tty(*this, "tty") - , m_memory(*this, "memory"), m_status(*this, "status") - , m_sw_control(*this, "CONTROL") - , m_sw_addr_data(*this, "ADDRDAT") - , m_sw_passes(*this, "PASSES") - , m_sw_prom_prgm(*this, "PROM") - , m_led_address(*this, "led_address_a%u_%u", 1U, 0U) - , m_led_instruction(*this, "led_instruction_m%u_%u", 1U, 0U) - , m_led_active_bank(*this, "led_active_bank_%u", 0U) - , m_led_execution(*this, "led_execution_x%u_%u", 2U, 0U) - , m_led_last_ptr(*this, "led_last_ptr_x%u_%u", 2U, 0U) - { - } - - virtual void driver_start() override; - virtual void driver_reset() override; - - void intellec4_program_banks(address_map &map); - void intellec4_rom_port_banks(address_map &map); - - void intellec4_rom(address_map &map); - void intellec4_ram_memory(address_map &map); - void intellec4_rom_ports(address_map &map); - void intellec4_ram_status(address_map &map); - void intellec4_ram_ports(address_map &map); - void intellec4_program_memory(address_map &map); - - void intellec4(machine_config &config); - - required_device<mcs40_cpu_device_base> m_cpu; - required_device<bus::intellec4::univ_bus_device> m_bus; - required_shared_ptr<u8> m_prg_ram; - required_ioport m_sw_mode; - -private: - enum - { - BANK_PRG_MON = 0, - BANK_PRG_PROM, - BANK_PRG_RAM, - BANK_PRG_NONE, - - BANK_IO_MON = 0, - BANK_IO_PROM, - BANK_IO_NEITHER, - - BIT_SW_RESET = 2, - BIT_SW_RESET_MODE, - BIT_SW_MON, - BIT_SW_RAM, - BIT_SW_PROM, - - BIT_SW_RUN = 0, - BIT_SW_NEXT_INST, - BIT_SW_DECR, - BIT_SW_INCR, - BIT_SW_LOAD, - BIT_SW_CMA_ENABLE, - BIT_SW_CMA_WRITE, - - BIT_SW_PRGM_PWR = 0, - BIT_SW_DATA_OUT_ENABLE - }; - - TIMER_CALLBACK_MEMBER(reset_expired); - - // LED update helpers - void display_address(u16 value, u16 mask); - void display_instruction(u8 value, u8 mask); - void display_active_bank(u8 value); - void display_execution(u8 value, u8 mask); - void display_pointer(u8 value, u8 mask); - - void trigger_reset(); - void check_4002_reset(); - void reset_panel(); - - required_device<address_map_bank_device> m_program_banks, m_rom_port_banks; - required_device<intel_imm6_76_device> m_prom_programmer; - required_device<rs232_port_device> m_tty; - - required_shared_ptr<u8> m_memory, m_status; - required_ioport m_sw_control, m_sw_addr_data, m_sw_passes; - required_ioport m_sw_prom_prgm; - output_finder<3, 4> m_led_address; - output_finder<2, 4> m_led_instruction; - output_finder<4> m_led_active_bank; - output_finder<2, 4> m_led_execution; - output_finder<2, 4> m_led_last_ptr; - - emu_timer *m_reset_timer = nullptr; - - // program memory access - u8 m_ram_page = 0U, m_ram_data = 0U; - bool m_ram_write = false; - - // PROM programmer - u8 m_prom_addr = 0U, m_prom_data = 0U; - - // control board state - bool m_cpu_reset = false; - bool m_ff_prg_mode[3] = { false, false, false }; - - // current state of signals from bus - bool m_bus_reset_4002 = false, m_bus_user_reset = false; - - // front panel state - u16 m_latched_addr = 0U, m_display_addr = 0U; - u8 m_display_instr = 0U, m_display_exec = 0U, m_display_ptr = 0U; - u8 m_pass_counter = 0U; - bool m_panel_reset = false; - bool m_next_inst = false, m_adr_cmp_latch = false, m_search_complete = false; - bool m_src = false, m_pointer_valid = false; - bool m_cma_enable = false, m_cma_write = false; - - // current state of front panel switches - bool m_sw_reset = false, m_sw_reset_mode = false; - bool m_sw_prg_mode[3] = { false, false, false }; - bool m_sw_run = false; -}; - - -/*---------------------------------- - Common front panel switches -----------------------------------*/ - -INPUT_PORTS_START(intellec4) - PORT_START("MODE") - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("RESET") PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_reset, 0) - PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("RESET MODE") PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_reset_mode, 0) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("MON") PORT_CODE(KEYCODE_1_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_prg_mode<0>, 0) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("RAM") PORT_CODE(KEYCODE_2_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_prg_mode<1>, 0) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("PROM") PORT_CODE(KEYCODE_3_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_prg_mode<2>, 0) - - PORT_START("CONTROL") - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("RUN") PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_run, 0) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("NEXT INST") PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_next_inst, 0) - PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("DECR") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_decr, 0) - PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("INCR") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_incr, 0) - PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("LOAD") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_load, 0) - PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("CMA ENABLE") PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_cma_enable, 0) - PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("CMA WRITE") PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_cma_write, 0) - - PORT_START("ADDRDAT") - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("ADDRESS/DATA 0") - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("ADDRESS/DATA 1") - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("ADDRESS/DATA 2") - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("ADDRESS/DATA 3") - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("ADDRESS/DATA 4") - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("ADDRESS/DATA 5") - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("ADDRESS/DATA 6") - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("ADDRESS/DATA 7") - PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("ADDRESS/DATA 8") - PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("ADDRESS/DATA 9") - PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("ADDRESS/DATA 10") - PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("ADDRESS/DATA 11") - - PORT_START("PASSES") - PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("PASSES 0") - PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("PASSES 1") - PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("PASSES 2") - PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("PASSES 3") - - PORT_START("PROM") - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("PRGM PROM PWR") PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_prgm_pwr, 0) - PORT_CONFNAME( 0x0002, 0x0002, "PROM PROGRAMMER DATA OUT ENABLE" ) PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_do_enable, 0) - PORT_CONFSETTING( 0x0000, DEF_STR(Off) ) - PORT_CONFSETTING( 0x0002, DEF_STR(On) ) -INPUT_PORTS_END - - -/*---------------------------------- - System bus cycle handler -----------------------------------*/ - -void intellec4_state::bus_cycle(mcs40_cpu_device_base::phase step, u8 sync, u8 data) -{ - switch (step) - { - case mcs40_cpu_device_base::phase::A1: - if (m_cma_enable) - { - display_address(m_latched_addr, 0x0fffU); - display_instruction(m_prg_ram[m_latched_addr], 0xffU); - } - else if (!m_search_complete) - { - display_address(u16(data), 0x000fU); - m_src = false; - } - if (m_cma_write) - { - m_prg_ram[m_latched_addr] = u8(~m_sw_addr_data->read() & 0x00ffU); - m_cma_write = false; - } - break; - case mcs40_cpu_device_base::phase::A2: - if (!m_search_complete && !m_cma_enable) - display_address(u16(data) << 4, 0x00f0U); - break; - case mcs40_cpu_device_base::phase::A3: - if (!m_search_complete && !m_cma_enable) - { - display_address(u16(data) << 8, 0x0f00U); - display_active_bank(~m_cpu->get_cm_ram()); - } - break; - case mcs40_cpu_device_base::phase::M1: - if (!m_search_complete && !m_cma_enable) - display_instruction(data << 4, 0xf0U); - break; - case mcs40_cpu_device_base::phase::M2: - if (!m_search_complete && !m_cma_enable) - display_instruction(data, 0x0fU); - break; - case mcs40_cpu_device_base::phase::X1: - // not connected to anything - break; - case mcs40_cpu_device_base::phase::X2: - if (!m_search_complete && !m_cma_enable) - { - display_execution(data << 4, 0xf0U); - m_src = BIT(~m_cpu->get_cm_rom(), 0); - if (m_src) - display_pointer(data << 4, 0xf0U); - } - break; - case mcs40_cpu_device_base::phase::X3: - if (m_search_complete != m_adr_cmp_latch) - machine().output().set_value("led_status_search", m_search_complete = m_adr_cmp_latch); - if (!m_search_complete && !m_cma_enable) - { - display_execution(data, 0x0fU); - if (m_src) - { - display_pointer(data, 0x0fU); - if (!m_panel_reset && !m_pointer_valid) - machine().output().set_value("led_status_ptr_valid", m_pointer_valid = true); - } - } - if (!m_panel_reset && !m_adr_cmp_latch) - m_adr_cmp_latch = (m_latched_addr == m_display_addr) && !((m_pass_counter ^ m_sw_passes->read()) & 0x0fU); - if (!m_search_complete && !m_panel_reset && !m_cma_enable && !m_sw_run && (m_latched_addr == m_display_addr)) - m_pass_counter = (m_pass_counter + 1U) & 0x0fU; - if (m_adr_cmp_latch && !m_next_inst && !m_search_complete) - machine().output().set_value("led_status_search", m_search_complete = true); - if (!m_cpu_reset && !m_cma_enable && !m_sw_run) - m_panel_reset = false; - break; - } -} - - -/*---------------------------------- - Program memory access handlers -----------------------------------*/ - -READ8_MEMBER(intellec4_state::pm_read) -{ - if (!machine().side_effects_disabled()) - { - // always causes data to be latched - u16 const addr((u16(m_ram_page) << 8) | ((offset >> 1) & 0x00ffU)); - m_ram_data = m_prg_ram[addr]; - } - - // the C outputs of the 4289 are always high for RPM/WPM so it's equivalent to romf_in - return m_ram_data & 0x0fU; -} - -WRITE8_MEMBER(intellec4_state::pm_write) -{ - // always causes data to be latched - u16 const addr((u16(m_ram_page) << 8) | ((offset >> 1) & 0x00ffU)); - m_ram_data = m_prg_ram[addr]; - if (m_ram_write) - { - bool const first(BIT(offset, 0)); - m_prg_ram[addr] = (m_ram_data & (first ? 0x0fU : 0xf0U)) | ((data & 0x0fU) << (first ? 4 : 0)); - } -} - - -/*---------------------------------- - I/O port handlers -----------------------------------*/ - -READ8_MEMBER(intellec4_state::rom0_in) -{ - // bit 0 of this port is ANDed with the TTY input - return m_tty->rxd_r() ? 0x0eU : 0x0fU; -} - -READ8_MEMBER(intellec4_state::rom2_in) -{ - // lower nybble of PROM programmer data - return m_prom_programmer->do_r() & 0x0fU; -} - -READ8_MEMBER(intellec4_state::rom3_in) -{ - // upper nybble of PROM programmer data - return (m_prom_programmer->do_r() >> 4) & 0x0fU; -} - -READ8_MEMBER(intellec4_state::rome_in) -{ - // upper nybble of RAM data latch - return (m_ram_data >> 4) & 0x0fU; -} - -READ8_MEMBER(intellec4_state::romf_in) -{ - // lower nybble of RAM data latch - return m_ram_data & 0x0fU; -} - -WRITE8_MEMBER(intellec4_state::rom0_out) -{ - // lower nybble of PROM programmer address - m_prom_addr = (m_prom_addr & 0xf0U) | (data & 0x0fU); - m_prom_programmer->a_w(m_prom_addr); -} - -WRITE8_MEMBER(intellec4_state::rom1_out) -{ - // upper nybble of PROM programmer address - m_prom_addr = (m_prom_addr & 0x0fU) | ((data << 4) & 0xf0U); - m_prom_programmer->a_w(m_prom_addr); -} - -WRITE8_MEMBER(intellec4_state::rom2_out) -{ - // lower nybble of PROM programmer data - m_prom_data = (m_prom_data & 0xf0U) | (data & 0x0fU); - m_prom_programmer->di_w(m_prom_data); -} - -WRITE8_MEMBER(intellec4_state::rom3_out) -{ - // upper nybble of PROM programmer data - m_prom_data = (m_prom_data & 0x0fU) | ((data << 4) & 0xf0U); - m_prom_programmer->di_w(m_prom_data); -} - -WRITE8_MEMBER(intellec4_state::rome_out) -{ - // bit 0 of this port enables program memory write - m_ram_write = BIT(data, 0); -} - -WRITE8_MEMBER(intellec4_state::romf_out) -{ - // sets the program memory page for read/write operations - m_ram_page = data & 0x0fU; -} - -WRITE8_MEMBER(intellec4_state::ram0_out) -{ - // bit 0 of this port controls the TTY current loop - m_tty->write_txd(BIT(data, 0)); -} - -WRITE8_MEMBER(intellec4_state::ram1_out) -{ - // bit 0 of this port controls the paper tape motor (0 = stop, 1 = run) - m_tty->write_rts(BIT(~data, 0)); - - // bits 1 and 2 of this port enable PROM write - m_prom_programmer->r_w_a(BIT(~data, 1)); - m_prom_programmer->r_w(BIT(~data, 2)); -} - - -/*---------------------------------- - Bus signal handlers -----------------------------------*/ - -WRITE_LINE_MEMBER(intellec4_state::bus_reset_4002) -{ - m_bus_reset_4002 = 0 == state; - check_4002_reset(); -} - -WRITE_LINE_MEMBER(intellec4_state::bus_user_reset) -{ - if (!state) - trigger_reset(); - m_bus_user_reset = 0 == state; -} - - -/*---------------------------------- - Front panel switch handlers -----------------------------------*/ - -INPUT_CHANGED_MEMBER(intellec4_state::sw_reset) -{ - if (!newval && oldval) - trigger_reset(); - m_sw_reset = !bool(newval); -} - -INPUT_CHANGED_MEMBER(intellec4_state::sw_reset_mode) -{ - m_sw_reset_mode = bool(newval); - if (m_cpu_reset) - { - m_bus->reset_4002_in(m_sw_reset_mode ? 0 : 1); - check_4002_reset(); - } -} - -template <unsigned N> INPUT_CHANGED_MEMBER(intellec4_state::sw_prg_mode) -{ - static constexpr char const *const mode_leds[3] = { "led_mode_mon", "led_mode_ram", "led_mode_prom" }; - static constexpr int prg_banks[3] = { BANK_PRG_MON, BANK_PRG_RAM, BANK_PRG_PROM }; - static constexpr int io_banks[3] = { BANK_IO_MON, BANK_IO_NEITHER, BANK_IO_PROM }; - - if (oldval && !newval) - { - if (((0U == N) || !m_sw_prg_mode[0]) && ((1U == N) || !m_sw_prg_mode[1]) && ((2U == N) || !m_sw_prg_mode[2])) - { - if (!m_ff_prg_mode[N]) - { - m_program_banks->set_bank(prg_banks[N]); - m_rom_port_banks->set_bank(io_banks[N]); - machine().output().set_value(mode_leds[N], m_ff_prg_mode[N] = true); - } - trigger_reset(); - } - else - { - m_program_banks->set_bank(BANK_PRG_NONE); - m_rom_port_banks->set_bank(BANK_IO_NEITHER); - } - if ((0U != N) && m_ff_prg_mode[0]) - machine().output().set_value(mode_leds[0], m_ff_prg_mode[0] = false); - if ((1U != N) && m_ff_prg_mode[1]) - machine().output().set_value(mode_leds[1], m_ff_prg_mode[1] = false); - if ((2U != N) && m_ff_prg_mode[2]) - machine().output().set_value(mode_leds[2], m_ff_prg_mode[2] = false); - } - m_sw_prg_mode[N] = !bool(newval); -} - -INPUT_CHANGED_MEMBER(intellec4_state::sw_run) -{ - m_sw_run = !bool(newval); - if (m_sw_run) - reset_panel(); -} - -INPUT_CHANGED_MEMBER(intellec4_state::sw_next_inst) -{ - m_next_inst = !bool(newval); -} - -INPUT_CHANGED_MEMBER(intellec4_state::sw_decr) -{ - // connected to a pulse generator circuit - if (newval && !oldval) - { - m_latched_addr = (m_latched_addr - 1U) & 0x0fffU; - reset_panel(); - } -} - -INPUT_CHANGED_MEMBER(intellec4_state::sw_incr) -{ - // connected to a pulse generator circuit - if (newval && !oldval) - { - m_latched_addr = (m_latched_addr + 1U) & 0x0fffU; - reset_panel(); - } -} - -INPUT_CHANGED_MEMBER(intellec4_state::sw_load) -{ - // connected to a pulse generator circuit - if (newval && !oldval) - { - m_latched_addr = ~m_sw_addr_data->read() & 0x0fffU; - reset_panel(); - } -} - -INPUT_CHANGED_MEMBER(intellec4_state::sw_cma_enable) -{ - m_cma_enable = bool(newval); - if (m_cma_enable) - reset_panel(); -} - -INPUT_CHANGED_MEMBER(intellec4_state::sw_cma_write) -{ - if (newval && !oldval) - m_cma_write = m_cma_enable; -} - -INPUT_CHANGED_MEMBER(intellec4_state::sw_prgm_pwr) -{ - m_prom_programmer->prgm_prom_pwr(newval); -} - -INPUT_CHANGED_MEMBER(intellec4_state::sw_do_enable) -{ - m_prom_programmer->data_out_enable(newval); -} - - -/*---------------------------------- - driver_device implementation -----------------------------------*/ - -void intellec4_state::driver_start() -{ - m_reset_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(intellec4_state::reset_expired), this)); - - m_led_address.resolve(); - m_led_instruction.resolve(); - m_led_active_bank.resolve(); - m_led_execution.resolve(); - m_led_last_ptr.resolve(); - - save_item(NAME(m_ram_page)); - save_item(NAME(m_ram_data)); - save_item(NAME(m_ram_write)); - - save_item(NAME(m_prom_addr)); - save_item(NAME(m_prom_data)); - - save_item(NAME(m_cpu_reset)); - save_item(NAME(m_ff_prg_mode)); - - save_item(NAME(m_bus_reset_4002)); - save_item(NAME(m_bus_user_reset)); - - save_item(NAME(m_latched_addr)); - save_item(NAME(m_display_addr)); - save_item(NAME(m_display_instr)); - save_item(NAME(m_display_exec)); - save_item(NAME(m_display_ptr)); - save_item(NAME(m_pass_counter)); - save_item(NAME(m_panel_reset)); - save_item(NAME(m_next_inst)); - save_item(NAME(m_adr_cmp_latch)); - save_item(NAME(m_search_complete)); - save_item(NAME(m_src)); - save_item(NAME(m_pointer_valid)); - save_item(NAME(m_cma_enable)); - save_item(NAME(m_cma_write)); - - save_item(NAME(m_sw_reset)); - save_item(NAME(m_sw_reset_mode)); - save_item(NAME(m_sw_prg_mode)); - save_item(NAME(m_sw_run)); - - m_ff_prg_mode[0] = true; - m_ff_prg_mode[1] = m_ff_prg_mode[2] = false; -}; - -void intellec4_state::driver_reset() -{ - // set stuff according to initial state of front panel - ioport_value const sw_mode(m_sw_mode->read()), sw_control(m_sw_control->read()); - m_sw_reset = BIT(~sw_mode, BIT_SW_RESET); - m_sw_reset_mode = BIT( sw_mode, BIT_SW_RESET_MODE); - m_sw_prg_mode[0] = BIT(~sw_mode, BIT_SW_MON); - m_sw_prg_mode[1] = BIT(~sw_mode, BIT_SW_RAM); - m_sw_prg_mode[2] = BIT(~sw_mode, BIT_SW_PROM); - m_sw_run = BIT(~sw_control, BIT_SW_RUN); - m_next_inst = BIT(~sw_control, BIT_SW_NEXT_INST); - m_cma_enable = BIT( sw_control, BIT_SW_CMA_ENABLE); - m_ff_prg_mode[0] = m_ff_prg_mode[0] && !m_sw_prg_mode[1] && !m_sw_prg_mode[2]; - m_ff_prg_mode[1] = m_ff_prg_mode[1] && !m_sw_prg_mode[0] && !m_sw_prg_mode[2]; - m_ff_prg_mode[2] = m_ff_prg_mode[2] && !m_sw_prg_mode[0] && !m_sw_prg_mode[1]; - m_panel_reset = m_panel_reset || m_cma_enable || m_sw_run; - if (m_panel_reset) - { - m_pass_counter = 0U; - m_adr_cmp_latch = false; - m_search_complete = m_search_complete && m_next_inst; - m_pointer_valid = false; - } - - // ensure we're consistent with the state of the bus - m_bus_reset_4002 = 0 == m_bus->reset_4002_out(); - m_bus_user_reset = 0 == m_bus->user_reset_out(); - - // ensure device inputs are all in the correct state - m_cpu->set_input_line(INPUT_LINE_RESET, m_cpu_reset ? ASSERT_LINE : CLEAR_LINE); - m_bus->cpu_reset_in(m_cpu_reset ? 0 : 1); - m_bus->reset_4002_in((m_cpu_reset && m_sw_reset_mode) ? 0 : 1); - - // set up the PROM programmer - ioport_value const sw_prom_prgm(m_sw_prom_prgm->read()); - m_prom_programmer->data_out_enable(BIT(sw_prom_prgm, BIT_SW_DATA_OUT_ENABLE)); - m_prom_programmer->data_in_positive(1); // not jumpered in, onboard pullup - m_prom_programmer->data_out_positive(0); // jumpered to ground - m_prom_programmer->prgm_prom_pwr(BIT(sw_prom_prgm, BIT_SW_PRGM_PWR)); - - // set front panel LEDs - machine().output().set_value("led_status_ptr_valid", m_pointer_valid); - machine().output().set_value("led_status_search", m_search_complete); - machine().output().set_value("led_mode_mon", m_ff_prg_mode[0]); - machine().output().set_value("led_mode_ram", m_ff_prg_mode[1]); - machine().output().set_value("led_mode_prom", m_ff_prg_mode[2]); -} - - -/*---------------------------------- - System address spaces -----------------------------------*/ - -void intellec4_state::intellec4_program_banks(address_map &map) -{ - map.unmap_value_low(); - - // 0x0000...0x0fff MON - map(0x0000, 0x03ff).rom().region("monitor", 0x0000); - - // 0x1000...0x1fff PROM - - // 0x1000...0x1fff RAM - map(0x2000, 0x2fff).readonly().share("ram"); - - // 0x3000...0x3fff unmapped in case someone presses two mode switches at once -} - -void intellec4_state::intellec4_rom_port_banks(address_map &map) -{ - map.unmap_value_high(); - - // 0x0000...0x07ff MON - map(0x0000, 0x000f).mirror(0x1f00).rw(FUNC(intellec4_state::rom0_in), FUNC(intellec4_state::rom0_out)); - map(0x0010, 0x001f).mirror(0x1f00).w(FUNC(intellec4_state::rom1_out)); - map(0x0020, 0x002f).mirror(0x1f00).rw(FUNC(intellec4_state::rom2_in), FUNC(intellec4_state::rom2_out)); - map(0x0030, 0x003f).mirror(0x1f00).rw(FUNC(intellec4_state::rom3_in), FUNC(intellec4_state::rom3_out)); - map(0x00e0, 0x00ef).mirror(0x1f00).rw(FUNC(intellec4_state::rome_in), FUNC(intellec4_state::rome_out)); - map(0x00f0, 0x00ff).mirror(0x1f00).rw(FUNC(intellec4_state::romf_in), FUNC(intellec4_state::romf_out)); - - // 0x0800...0x0fff PROM - - // 0x1000...0x17ff neither - - // 0x1800...0x1fff unused -} - - -/*--------------------------------- - CPU views of address spaces ----------------------------------*/ - -void intellec4_state::intellec4_rom(address_map &map) -{ - map.unmap_value_low(); - map(0x0000, 0x0fff).m(m_program_banks, FUNC(address_map_bank_device::amap8)); -} - -void intellec4_state::intellec4_ram_memory(address_map &map) -{ - map.unmap_value_low(); - map(0x0000, 0x00ff).ram().share("memory"); // 4 * 4002 -} - -void intellec4_state::intellec4_rom_ports(address_map &map) -{ - map.unmap_value_high(); - map(0x0000, 0x07ff).m("rpbank", FUNC(address_map_bank_device::amap8)); -} - -void intellec4_state::intellec4_ram_status(address_map &map) -{ - map.unmap_value_low(); - map(0x0000, 0x003f).ram().share("status"); // 4 * 4002 -} - -void intellec4_state::intellec4_ram_ports(address_map &map) -{ - map(0x00, 0x00).w(FUNC(intellec4_state::ram0_out)); - map(0x01, 0x01).w(FUNC(intellec4_state::ram1_out)); -} - -void intellec4_state::intellec4_program_memory(address_map &map) -{ - map.unmap_value_low(); - map(0x0000, 0x01ff).rw(FUNC(intellec4_state::pm_read), FUNC(intellec4_state::pm_write)); -} - - -/*---------------------------------- - Common machine configuration -----------------------------------*/ - -DEVICE_INPUT_DEFAULTS_START(tty) - DEVICE_INPUT_DEFAULTS("RS232_TXBAUD", 0x00ff, RS232_BAUD_110) - DEVICE_INPUT_DEFAULTS("RS232_RXBAUD", 0x00ff, RS232_BAUD_110) - DEVICE_INPUT_DEFAULTS("RS232_STARTBITS", 0x00ff, RS232_STARTBITS_1) - DEVICE_INPUT_DEFAULTS("RS232_DATABITS", 0x00ff, RS232_DATABITS_8) - DEVICE_INPUT_DEFAULTS("RS232_PARITY", 0x00ff, RS232_PARITY_NONE) - DEVICE_INPUT_DEFAULTS("RS232_STOPBITS", 0x00ff, RS232_STOPBITS_2) - DEVICE_INPUT_DEFAULTS("TERM_CONF", 0x01c0, 0x0000) - DEVICE_INPUT_DEFAULTS("FLOW_CONTROL", 0x0001, 0x0000) -DEVICE_INPUT_DEFAULTS_END - -void intellec4_state::intellec4(machine_config &config) -{ - ADDRESS_MAP_BANK(config, m_program_banks, 0); - m_program_banks->set_map(&intellec4_state::intellec4_program_banks); - m_program_banks->set_endianness(ENDIANNESS_LITTLE); - m_program_banks->set_data_width(8); - m_program_banks->set_addr_width(14); - m_program_banks->set_stride(0x1000); - - ADDRESS_MAP_BANK(config, m_rom_port_banks, 0); - m_rom_port_banks->set_map(&intellec4_state::intellec4_rom_port_banks); - m_rom_port_banks->set_endianness(ENDIANNESS_LITTLE); - m_rom_port_banks->set_data_width(8); - m_rom_port_banks->set_addr_width(14); - m_rom_port_banks->set_stride(0x1000); - - INTEL_IMM6_76(config, m_prom_programmer, 0); - - RS232_PORT(config, m_tty, default_rs232_devices, "terminal"); - m_tty->set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(tty)); - m_tty->set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(tty)); - - INTELLEC4_UNIV_BUS(config, m_bus, 518000. / 7); - m_bus->set_rom_space(m_program_banks, AS_PROGRAM); - m_bus->set_rom_ports_space(m_rom_port_banks, AS_PROGRAM); - m_bus->set_memory_space(m_cpu, mcs40_cpu_device_base::AS_RAM_MEMORY); - m_bus->set_status_space(m_cpu, mcs40_cpu_device_base::AS_RAM_STATUS); - m_bus->set_ram_ports_space(m_cpu, mcs40_cpu_device_base::AS_RAM_PORTS); - m_bus->reset_4002_out_cb().set(FUNC(intellec4_state::bus_reset_4002)); - m_bus->user_reset_out_cb().set(FUNC(intellec4_state::bus_user_reset)); - INTELLEC4_UNIV_SLOT(config, "j7", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, "imm4_90"); - INTELLEC4_UNIV_SLOT(config, "j8", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, "imm6_26"); - INTELLEC4_UNIV_SLOT(config, "j9", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, nullptr); - INTELLEC4_UNIV_SLOT(config, "j10", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, nullptr); - INTELLEC4_UNIV_SLOT(config, "j11", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, nullptr); - INTELLEC4_UNIV_SLOT(config, "j12", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, nullptr); - INTELLEC4_UNIV_SLOT(config, "j13", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, nullptr); - INTELLEC4_UNIV_SLOT(config, "j14", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, nullptr); - INTELLEC4_UNIV_SLOT(config, "j15", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, nullptr); - INTELLEC4_UNIV_SLOT(config, "j16", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, nullptr); - INTELLEC4_UNIV_SLOT(config, "j17", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, nullptr); - INTELLEC4_UNIV_SLOT(config, "j18", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, nullptr); - INTELLEC4_UNIV_SLOT(config, "j19", 5.185_MHz_XTAL / 7, m_bus, intellec4_univ_cards, nullptr); -} - - -/*---------------------------------- - Timer handlers -----------------------------------*/ - -TIMER_CALLBACK_MEMBER(intellec4_state::reset_expired) -{ - if (m_cpu_reset) - { - m_cpu_reset = false; - m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); - m_bus->cpu_reset_in(1); - if (m_sw_reset_mode) - { - m_bus->reset_4002_in(1); - check_4002_reset(); - } - } -} - - -/*---------------------------------- - LED update helpers -----------------------------------*/ - -void intellec4_state::display_address(u16 value, u16 mask) -{ - u16 const diff((value ^ m_display_addr) & mask); - m_display_addr ^= diff; - m_led_address[0][0] = BIT(m_display_addr, 0); - m_led_address[0][1] = BIT(m_display_addr, 1); - m_led_address[0][2] = BIT(m_display_addr, 2); - m_led_address[0][3] = BIT(m_display_addr, 3); - m_led_address[1][0] = BIT(m_display_addr, 4); - m_led_address[1][1] = BIT(m_display_addr, 5); - m_led_address[1][2] = BIT(m_display_addr, 6); - m_led_address[1][3] = BIT(m_display_addr, 7); - m_led_address[2][0] = BIT(m_display_addr, 8); - m_led_address[2][1] = BIT(m_display_addr, 9); - m_led_address[2][2] = BIT(m_display_addr, 10); - m_led_address[2][3] = BIT(m_display_addr, 11); -} - -void intellec4_state::display_instruction(u8 value, u8 mask) -{ - u16 const diff((value ^ m_display_instr) & mask); - m_display_instr ^= diff; - m_led_instruction[1][0] = BIT(m_display_instr, 0); - m_led_instruction[1][1] = BIT(m_display_instr, 1); - m_led_instruction[1][2] = BIT(m_display_instr, 2); - m_led_instruction[1][3] = BIT(m_display_instr, 3); - m_led_instruction[0][0] = BIT(m_display_instr, 4); - m_led_instruction[0][1] = BIT(m_display_instr, 5); - m_led_instruction[0][2] = BIT(m_display_instr, 6); - m_led_instruction[0][3] = BIT(m_display_instr, 7); -} - -void intellec4_state::display_active_bank(u8 value) -{ - m_led_active_bank[0] = BIT(value, 0); - m_led_active_bank[1] = BIT(value, 1); - m_led_active_bank[2] = BIT(value, 2); - m_led_active_bank[3] = BIT(value, 3); -} - -void intellec4_state::display_execution(u8 value, u8 mask) -{ - u16 const diff((value ^ m_display_exec) & mask); - m_display_exec ^= diff; - m_led_execution[1][0] = BIT(m_display_exec, 0); - m_led_execution[1][1] = BIT(m_display_exec, 1); - m_led_execution[1][2] = BIT(m_display_exec, 2); - m_led_execution[1][3] = BIT(m_display_exec, 3); - m_led_execution[0][0] = BIT(m_display_exec, 4); - m_led_execution[0][1] = BIT(m_display_exec, 5); - m_led_execution[0][2] = BIT(m_display_exec, 6); - m_led_execution[0][3] = BIT(m_display_exec, 7); -} - -void intellec4_state::display_pointer(u8 value, u8 mask) -{ - u16 const diff((value ^ m_display_ptr) & mask); - m_display_ptr ^= diff; - m_led_last_ptr[1][0] = BIT(m_display_ptr, 0); - m_led_last_ptr[1][1] = BIT(m_display_ptr, 1); - m_led_last_ptr[1][2] = BIT(m_display_ptr, 2); - m_led_last_ptr[1][3] = BIT(m_display_ptr, 3); - m_led_last_ptr[0][0] = BIT(m_display_ptr, 4); - m_led_last_ptr[0][1] = BIT(m_display_ptr, 5); - m_led_last_ptr[0][2] = BIT(m_display_ptr, 6); - m_led_last_ptr[0][3] = BIT(m_display_ptr, 7); -} - - -/*---------------------------------- - Internal helpers -----------------------------------*/ - -void intellec4_state::trigger_reset() -{ - // (re-)trigger the reset monostable - if (!m_sw_reset && !m_sw_prg_mode[0] && !m_sw_prg_mode[1] && !m_sw_prg_mode[2] && !m_bus_user_reset) - { - // 9602 with Rx = 27kΩ, Cx = 0.1µF - // K * Rx(kΩ) * Cx(pF) * (1 + (1 / Rx(kΩ))) = 0.34 * 27 * 100000 * (1 + (1 / 27)) = 952000ns - m_reset_timer->adjust(attotime::from_usec(952)); - if (!m_cpu_reset) - { - m_cpu_reset = true; - m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - m_bus->cpu_reset_in(0); - reset_panel(); - if (m_sw_reset_mode) - { - m_bus->reset_4002_in(0); - check_4002_reset(); - } - } - } -} - -void intellec4_state::check_4002_reset() -{ - // FIXME: this really takes multiple cycles to erase, and prevents writes while held - if ((m_cpu_reset && m_sw_reset_mode) || m_bus_reset_4002) - { - std::fill_n(&m_memory[0], m_memory.bytes(), 0U); - std::fill_n(&m_status[0], m_memory.bytes(), 0U); - } -} - -void intellec4_state::reset_panel() -{ - if (!m_panel_reset) - { - m_pass_counter = 0U; - m_panel_reset = true; - m_adr_cmp_latch = false; - if (m_search_complete && !m_next_inst) - machine().output().set_value("led_status_search", m_search_complete = false); - if (m_pointer_valid) - machine().output().set_value("led_status_ptr_valid", m_pointer_valid = false); - } -} - - - -/*********************************************************************** - MOD 4 driver -***********************************************************************/ - -class mod4_state : public intellec4_state -{ -public: - mod4_state(machine_config const &mconfig, device_type type, char const *tag) - : intellec4_state(mconfig, type, tag) - { - } - - // universal slot outputs - DECLARE_WRITE_LINE_MEMBER(bus_test); - - // front panel switches - DECLARE_INPUT_CHANGED_MEMBER(sw_hold); - DECLARE_INPUT_CHANGED_MEMBER(sw_one_shot); - - void mod4(machine_config &config); - -protected: - virtual void driver_start() override; - virtual void driver_reset() override; - -private: - enum - { - BIT_SW_HOLD = 0, - BIT_SW_ONE_SHOT - }; - - TIMER_CALLBACK_MEMBER(one_shot_expired); - - emu_timer *m_one_shot_timer = nullptr; - - // control board state - bool m_one_shot = false; - - // current state of signals from bus - bool m_bus_test = false; - - // current state of front panel switches - bool m_sw_hold = false; -}; - - -/*---------------------------------- - MOD 4-specific switches -----------------------------------*/ - -INPUT_PORTS_START(mod4) - PORT_INCLUDE(intellec4) - - PORT_MODIFY("MODE") - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("HOLD") PORT_CODE(KEYCODE_LEFT) PORT_CHANGED_MEMBER(DEVICE_SELF, mod4_state, sw_hold, 0) - PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("ONE SHOT") PORT_CODE(KEYCODE_RIGHT) PORT_CHANGED_MEMBER(DEVICE_SELF, mod4_state, sw_one_shot, 0) -INPUT_PORTS_END - - -/*---------------------------------- - Bus signal handlers -----------------------------------*/ - -WRITE_LINE_MEMBER(mod4_state::bus_test) -{ - if (!m_one_shot && !m_sw_hold) - m_cpu->set_input_line(I4004_TEST_LINE, state ? CLEAR_LINE : ASSERT_LINE); - m_bus_test = 0 == state; -} - - -/*---------------------------------- - Front panel switch handlers -----------------------------------*/ - -INPUT_CHANGED_MEMBER(mod4_state::sw_hold) -{ - // overridden by the one-shot monostable and the bus test signal - if (!m_one_shot) - { - if (!m_bus_test) - m_cpu->set_input_line(I4004_TEST_LINE, newval ? CLEAR_LINE : ASSERT_LINE); - m_bus->test_in(newval ? 1 : 0); - } - m_sw_hold = !bool(newval); -} - -INPUT_CHANGED_MEMBER(mod4_state::sw_one_shot) -{ - if (newval && !oldval) - { - // 9602 with Rx = 20kΩ, Cx = 0.005µF - // K * Rx(kΩ) * Cx(pF) * (1 + (1 / Rx(kΩ))) = 0.34 * 20 * 5000 * (1 + (1 / 20)) = 35700ns - m_one_shot_timer->adjust(attotime::from_nsec(35700)); - if (!m_one_shot) - { - m_one_shot = true; - if (!m_sw_hold) - { - m_bus->test_in(0); - if (!m_bus_test) - m_cpu->set_input_line(I4004_TEST_LINE, ASSERT_LINE); - } - } - } -} - - -/*---------------------------------- - MOD 4-specific configuration -----------------------------------*/ - -void mod4_state::mod4(machine_config &config) -{ - intellec4(config); - - i4004_cpu_device &cpu(I4004(config, m_cpu, 5.185_MHz_XTAL / 7)); - cpu.set_rom_map(&mod4_state::intellec4_rom); - cpu.set_ram_memory_map(&mod4_state::intellec4_ram_memory); - cpu.set_rom_ports_map(&mod4_state::intellec4_rom_ports); - cpu.set_ram_status_map(&mod4_state::intellec4_ram_status); - cpu.set_ram_ports_map(&mod4_state::intellec4_ram_ports); - cpu.set_program_memory_map(&mod4_state::intellec4_program_memory); - cpu.set_bus_cycle_cb(FUNC(mod4_state::bus_cycle)); - cpu.sync_cb().set(m_bus, FUNC(bus::intellec4::univ_bus_device::sync_in)); - - m_bus->test_out_cb().set(FUNC(mod4_state::bus_test)); - - config.set_default_layout(layout_intlc44); -} - - -/*---------------------------------- - driver_device implementation -----------------------------------*/ - -void mod4_state::driver_start() -{ - intellec4_state::driver_start(); - - m_one_shot_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mod4_state::one_shot_expired), this)); - - save_item(NAME(m_one_shot)); - - save_item(NAME(m_bus_test)); - - save_item(NAME(m_sw_hold)); - - m_one_shot = false; -} - -void mod4_state::driver_reset() -{ - intellec4_state::driver_reset(); - - // set stuff according to initial state of front panel - m_sw_hold = BIT(~m_sw_mode->read(), BIT_SW_HOLD); - - // ensure we're consistent with the state of the bus - m_bus_test = 0 == m_bus->test_out(); - - // ensure device inputs are all in the correct state - m_cpu->set_input_line(I4004_TEST_LINE, (m_one_shot || m_bus_test || m_sw_hold) ? ASSERT_LINE : CLEAR_LINE); - m_bus->test_in((m_one_shot || m_sw_hold) ? 0 : 1); - - // set front panel LEDs - machine().output().set_value("led_status_cpu", true); // actually driven by clock phase 2 - let's assume it's always running -} - - -/*---------------------------------- - Timer handlers -----------------------------------*/ - -TIMER_CALLBACK_MEMBER(mod4_state::one_shot_expired) -{ - m_one_shot = false; - if (!m_sw_hold) - { - m_bus->test_in(1); - if (!m_bus_test) - m_cpu->set_input_line(I4004_TEST_LINE, CLEAR_LINE); - } -} - - - -/*********************************************************************** - MOD 40 driver -***********************************************************************/ - -class mod40_state : public intellec4_state -{ -public: - mod40_state(machine_config const &mconfig, device_type type, char const *tag) - : intellec4_state(mconfig, type, tag) - , m_led_status_run(*this, "led_status_run") - { - } - - DECLARE_WRITE_LINE_MEMBER(stp_ack); - - // universal slot outputs - DECLARE_WRITE_LINE_MEMBER(bus_stop); - DECLARE_WRITE_LINE_MEMBER(bus_test); - - // front panel switches - DECLARE_INPUT_CHANGED_MEMBER(sw_stop); - DECLARE_INPUT_CHANGED_MEMBER(sw_single_step); - - void mod40(machine_config &config); - -protected: - virtual void driver_start() override; - virtual void driver_reset() override; - -private: - enum - { - BIT_SW_STOP = 0, - BIT_SW_SINGLE_STEP - }; - - TIMER_CALLBACK_MEMBER(single_step_expired); - - output_finder<> m_led_status_run; - - emu_timer *m_single_step_timer = nullptr; - - // control board state - bool m_stp_ack = false, m_single_step = false; - - // current state of signals from bus - bool m_bus_stop = false; - - // current state of front panel switches - bool m_sw_stop = false; -}; - - -/*---------------------------------- - MOD 40-specific switches -----------------------------------*/ - -INPUT_PORTS_START(mod40) - PORT_INCLUDE(intellec4) - - PORT_MODIFY("MODE") - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_NAME("STOP") PORT_CODE(KEYCODE_LEFT) PORT_CHANGED_MEMBER(DEVICE_SELF, mod40_state, sw_stop, 0) - PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("SINGLE STEP") PORT_CODE(KEYCODE_RIGHT) PORT_CHANGED_MEMBER(DEVICE_SELF, mod40_state, sw_single_step, 0) -INPUT_PORTS_END - - -/*---------------------------------- - CPU output handlers -----------------------------------*/ - -WRITE_LINE_MEMBER(mod40_state::stp_ack) -{ - // resets the single-step monostable - if (m_stp_ack && state) - { - m_single_step_timer->reset(); - m_single_step = false; - if (m_sw_stop) - { - m_bus->stop_in(0); - if (!m_bus_stop) - m_cpu->set_input_line(I4040_STP_LINE, ASSERT_LINE); - } - } - m_stp_ack = 0 == state; - m_led_status_run = !m_stp_ack; - m_bus->stop_acknowledge_in(state); -} - - -WRITE_LINE_MEMBER(mod40_state::bus_stop) -{ - // will not allow the CPU to step/run - if (m_single_step || !m_sw_stop) - m_cpu->set_input_line(I4040_STP_LINE, state ? CLEAR_LINE : ASSERT_LINE); - m_bus_stop = 0 == state; -} - - -/*---------------------------------- - Bus signal handlers -----------------------------------*/ - -WRITE_LINE_MEMBER(mod40_state::bus_test) -{ - m_cpu->set_input_line(I4040_TEST_LINE, state ? CLEAR_LINE : ASSERT_LINE); -} - - -/*---------------------------------- - Front panel switch handlers -----------------------------------*/ - -INPUT_CHANGED_MEMBER(mod40_state::sw_stop) -{ - // overridden by the single-step monostable and the bus stop signal - if (!m_single_step) - { - if (!m_bus_stop) - m_cpu->set_input_line(I4040_STP_LINE, newval ? CLEAR_LINE : ASSERT_LINE); - m_bus->stop_in(newval ? 1 : 0); - } - m_sw_stop = !bool(newval); -} - -INPUT_CHANGED_MEMBER(mod40_state::sw_single_step) -{ - // (re-)triggers the single-step monostable - if (m_stp_ack && newval && !oldval) - { - // 9602 with Rx = 20kΩ, Cx = 0.005µF - // K * Rx(kΩ) * Cx(pF) * (1 + (1 / Rx(kΩ))) = 0.34 * 20 * 5000 * (1 + (1 / 20)) = 35700ns - m_single_step_timer->adjust(attotime::from_nsec(35700)); - if (!m_single_step) - { - m_single_step = true; - if (m_sw_stop) - { - m_bus->stop_in(1); - if (!m_bus_stop) - m_cpu->set_input_line(I4040_STP_LINE, CLEAR_LINE); - } - } - } -} - - -/*---------------------------------- - MOD 40-specific configuration -----------------------------------*/ - -void mod40_state::mod40(machine_config &config) -{ - intellec4(config); - - i4040_cpu_device &cpu(I4040(config, m_cpu, 5.185_MHz_XTAL / 7)); - cpu.set_rom_map(&mod40_state::intellec4_rom); - cpu.set_ram_memory_map(&mod40_state::intellec4_ram_memory); - cpu.set_rom_ports_map(&mod40_state::intellec4_rom_ports); - cpu.set_ram_status_map(&mod40_state::intellec4_ram_status); - cpu.set_ram_ports_map(&mod40_state::intellec4_ram_ports); - cpu.set_program_memory_map(&mod40_state::intellec4_program_memory); - cpu.set_bus_cycle_cb(FUNC(mod40_state::bus_cycle)); - cpu.sync_cb().set(m_bus, FUNC(bus::intellec4::univ_bus_device::sync_in)); - cpu.stp_ack_cb().set(FUNC(mod40_state::stp_ack)); - - m_bus->stop_out_cb().set(FUNC(mod40_state::bus_stop)); - m_bus->test_out_cb().set(FUNC(mod40_state::bus_test)); - - config.set_default_layout(layout_intlc440); -} - - -/*---------------------------------- - driver_device implementation -----------------------------------*/ - -void mod40_state::driver_start() -{ - intellec4_state::driver_start(); - - m_led_status_run.resolve(); - - m_single_step_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mod40_state::single_step_expired), this)); - - save_item(NAME(m_stp_ack)); - save_item(NAME(m_single_step)); - - save_item(NAME(m_bus_stop)); - - save_item(NAME(m_sw_stop)); - - m_stp_ack = m_single_step = false; -} - -void mod40_state::driver_reset() -{ - intellec4_state::driver_reset(); - - // set stuff according to initial state of front panel - m_sw_stop = BIT(~m_sw_mode->read(), BIT_SW_STOP); - - // ensure we're consistent with the state of the bus - m_bus_stop = 0 == m_bus->stop_out(); - - // ensure device inputs are all in the correct state - m_cpu->set_input_line(I4040_TEST_LINE, m_bus->test_out() ? CLEAR_LINE : ASSERT_LINE); - m_cpu->set_input_line(I4040_STP_LINE, ((m_sw_stop && !m_single_step) || m_bus_stop) ? ASSERT_LINE : CLEAR_LINE); - m_bus->test_in(1); - m_bus->stop_in((m_sw_stop && !m_single_step) ? 0 : 1); - - // set front panel LEDs - m_led_status_run = !m_stp_ack; -} - - -/*---------------------------------- - Timer handlers -----------------------------------*/ - -TIMER_CALLBACK_MEMBER(mod40_state::single_step_expired) -{ - m_single_step = false; - if (m_sw_stop) - { - m_bus->stop_in(0); - if (!m_bus_stop) - m_cpu->set_input_line(I4040_STP_LINE, ASSERT_LINE); - } -} - - -/*********************************************************************** - ROM definitions -***********************************************************************/ - -ROM_START(intlc44) - ROM_REGION(0x0400, "monitor", 0) // 4 * 1702A - ROM_DEFAULT_BIOS("v2.1") - ROM_SYSTEM_BIOS(0, "v2.1", "MON 4 V2.1") - ROMX_LOAD("mon_4-000-v_2.1.a1", 0x0000, 0x0100, CRC(8d1f56ff) SHA1(96bc19be9be4e92195fad82d7a3cadb763ab6e3f), ROM_BIOS(0)) - ROMX_LOAD("mon_4-100-v_2.1.a2", 0x0100, 0x0100, CRC(66562a4f) SHA1(040749c45e95dfc39b3397d0c31c8b4c11f0a5fc), ROM_BIOS(0)) - ROMX_LOAD("mon_4-200-v_2.1.a3", 0x0200, 0x0100, CRC(fe039c68) SHA1(1801cfcc7514412865c0fdc7d1800fcf583a2d2a), ROM_BIOS(0)) - ROMX_LOAD("mon_4-300-v_2.1.a4", 0x0300, 0x0100, CRC(3724d5af) SHA1(b764b3bb3541fbda875f7a7655f46aa54b332631), ROM_BIOS(0)) -ROM_END - -ROM_START(intlc440) - ROM_REGION(0x0400, "monitor", 0) // 4 * 1702A - ROM_DEFAULT_BIOS("v2.1") - ROM_SYSTEM_BIOS(0, "v2.1", "MON 4 V2.1") - ROMX_LOAD("mon_4-000-v_2.1.a1", 0x0000, 0x0100, CRC(8d1f56ff) SHA1(96bc19be9be4e92195fad82d7a3cadb763ab6e3f), ROM_BIOS(0)) - ROMX_LOAD("mon_4-100-v_2.1.a2", 0x0100, 0x0100, CRC(66562a4f) SHA1(040749c45e95dfc39b3397d0c31c8b4c11f0a5fc), ROM_BIOS(0)) - ROMX_LOAD("mon_4-200-v_2.1.a3", 0x0200, 0x0100, CRC(fe039c68) SHA1(1801cfcc7514412865c0fdc7d1800fcf583a2d2a), ROM_BIOS(0)) - ROMX_LOAD("mon_4-300-v_2.1.a4", 0x0300, 0x0100, CRC(3724d5af) SHA1(b764b3bb3541fbda875f7a7655f46aa54b332631), ROM_BIOS(0)) - ROM_SYSTEM_BIOS(1, "v2.1_1200", "MON 4 V2.1 1200 Baud hack") - ROMX_LOAD("mon_4-000-v_2.1.a1", 0x0000, 0x0100, CRC(8d1f56ff) SHA1(96bc19be9be4e92195fad82d7a3cadb763ab6e3f), ROM_BIOS(1)) - ROMX_LOAD("i40_mon-1.a2", 0x0100, 0x0100, CRC(cd9fecd6) SHA1(9c4fb85118c881687fd4b324e5089df05d1e63d1), ROM_BIOS(1)) - ROMX_LOAD("i40_mon-2.a3", 0x0200, 0x0100, CRC(037de128) SHA1(3694636e1f4e23688b36ea9ee755a0c5888f4328), ROM_BIOS(1)) - ROMX_LOAD("1200_baud-i40_mon-f3.a4", 0x0300, 0x0100, CRC(f3198d79) SHA1(b7903073b69f487b6f78842c08694f12225d85f0), ROM_BIOS(1)) -ROM_END - -} // anonymous namespace - - -/*********************************************************************** - Machine definitions -***********************************************************************/ - -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP( 1973?, intlc44, 0, 0, mod4, mod4, mod4_state, empty_init, "Intel", "INTELLEC 4/MOD 4", MACHINE_NO_SOUND_HW | MACHINE_CLICKABLE_ARTWORK | MACHINE_SUPPORTS_SAVE ) -COMP( 1974?, intlc440, 0, 0, mod40, mod40, mod40_state, empty_init, "Intel", "INTELLEC 4/MOD 40", MACHINE_NO_SOUND_HW | MACHINE_CLICKABLE_ARTWORK | MACHINE_SUPPORTS_SAVE ) |