diff options
author | Vas Crabb <vas@vastheman.com> | 2017-07-12 19:58:33 +1000 |
---|---|---|
committer | Vas Crabb <vas@vastheman.com> | 2017-07-12 19:58:33 +1000 |
commit | 95906048abf77103d831014ce5a2ef214d9e8971 (patch) | |
tree | 99451208e1eec0be3dd45de2edc6fbc580389cdc | |
parent | 4b6e1f2a0c68fa106b4959423265146d7984e35a (diff) |
INTELLEC 4: implement front-panel PROM programmer
-rw-r--r-- | scripts/target/mame/mess.lua | 2 | ||||
-rw-r--r-- | src/devices/bus/intellec4/intellec4.h | 6 | ||||
-rw-r--r-- | src/mame/drivers/intellec4.cpp | 109 | ||||
-rw-r--r-- | src/mame/layout/intlc44.lay | 30 | ||||
-rw-r--r-- | src/mame/layout/intlc440.lay | 30 | ||||
-rw-r--r-- | src/mame/machine/imm6_76.cpp | 204 | ||||
-rw-r--r-- | src/mame/machine/imm6_76.h | 203 |
7 files changed, 581 insertions, 3 deletions
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 60aa06fa3c3..395662a41da 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -2130,6 +2130,8 @@ files { MAME_DIR .. "src/mame/drivers/isbc.cpp", MAME_DIR .. "src/mame/drivers/isbc8010.cpp", MAME_DIR .. "src/mame/drivers/isbc8030.cpp", + MAME_DIR .. "src/mame/machine/imm6_76.cpp", + MAME_DIR .. "src/mame/machine/imm6_76.h", MAME_DIR .. "src/mame/machine/isbc_215g.cpp", MAME_DIR .. "src/mame/machine/isbc_215g.h", MAME_DIR .. "src/mame/machine/isbc_208.cpp", diff --git a/src/devices/bus/intellec4/intellec4.h b/src/devices/bus/intellec4/intellec4.h index 58900760300..61a77873d54 100644 --- a/src/devices/bus/intellec4/intellec4.h +++ b/src/devices/bus/intellec4/intellec4.h @@ -254,6 +254,12 @@ protected: // device_interface implementation void interface_pre_start() override; + address_space &rom_space() { return m_bus->m_rom_device->space(m_bus->m_rom_space); } + address_space &rom_ports_space() { return m_bus->m_rom_ports_device->space(m_bus->m_rom_ports_space); } + address_space &memory_space() { return m_bus->m_memory_device->space(m_bus->m_memory_space); } + address_space &status_space() { return m_bus->m_status_device->space(m_bus->m_status_space); } + address_space &ram_ports_space() { return m_bus->m_ram_ports_device->space(m_bus->m_ram_ports_space); } + private: void set_bus(univ_bus_device &bus); diff --git a/src/mame/drivers/intellec4.cpp b/src/mame/drivers/intellec4.cpp index affdac7d5c6..f4c0eee7b51 100644 --- a/src/mame/drivers/intellec4.cpp +++ b/src/mame/drivers/intellec4.cpp @@ -23,19 +23,29 @@ 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: * Default terminal serial settings - * 4702A programmer * Universal slot cards * Image device for paper tape reader? * 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" @@ -60,9 +70,15 @@ public: 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); @@ -84,6 +100,8 @@ public: 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) @@ -94,11 +112,13 @@ protected: , 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") { } @@ -134,7 +154,10 @@ private: BIT_SW_INCR, BIT_SW_LOAD, BIT_SW_CMA_ENABLE, - BIT_SW_CMA_WRITE + BIT_SW_CMA_WRITE, + + BIT_SW_PRGM_PWR = 0, + BIT_SW_DATA_OUT_ENABLE }; TIMER_CALLBACK_MEMBER(reset_expired); @@ -151,10 +174,12 @@ private: 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; emu_timer *m_reset_timer = nullptr; @@ -162,6 +187,9 @@ private: 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 }; @@ -207,7 +235,10 @@ ADDRESS_MAP_START(intellec4_rom_port_banks, mcs40_cpu_device_base::AS_ROM_PORTS, ADDRESS_MAP_UNMAP_LOW // 0x0000...0x07ff MON - AM_RANGE(0x0000, 0x000f) AM_MIRROR(0x1f00) AM_READ(rom0_in) + AM_RANGE(0x0000, 0x000f) AM_MIRROR(0x1f00) AM_READWRITE(rom0_in, rom0_out) + AM_RANGE(0x0010, 0x001f) AM_MIRROR(0x1f00) AM_WRITE(rom1_out) + AM_RANGE(0x0020, 0x002f) AM_MIRROR(0x1f00) AM_READWRITE(rom2_in, rom2_out) + AM_RANGE(0x0030, 0x003f) AM_MIRROR(0x1f00) AM_READWRITE(rom3_in, rom3_out) AM_RANGE(0x00e0, 0x00ef) AM_MIRROR(0x1f00) AM_READWRITE(rome_in, rome_out) AM_RANGE(0x00f0, 0x00ff) AM_MIRROR(0x1f00) AM_READWRITE(romf_in, romf_out) @@ -273,6 +304,8 @@ MACHINE_CONFIG_START(intellec4) MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(14) MCFG_ADDRESS_MAP_BANK_STRIDE(0x1000) + MCFG_DEVICE_ADD("promprg", INTEL_IMM6_76, 0) + MCFG_RS232_PORT_ADD("tty", default_rs232_devices, "terminal") MCFG_DEVICE_ADD("bus", INTELLEC4_UNIV_BUS, 518000. / 7) @@ -339,6 +372,12 @@ INPUT_PORTS_START(intellec4) 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, nullptr) + PORT_CONFNAME( 0x0002, 0x0002, "PROM PROGRAMMER DATA OUT ENABLE" ) PORT_CHANGED_MEMBER(DEVICE_SELF, intellec4_state, sw_do_enable, nullptr) + PORT_CONFSETTING( 0x0000, DEF_STR(Off) ) + PORT_CONFSETTING( 0x0002, DEF_STR(On) ) INPUT_PORTS_END @@ -464,6 +503,18 @@ READ8_MEMBER(intellec4_state::rom0_in) return m_tty->rxd_r() ? 0x00U : 0x01U; } +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 @@ -476,6 +527,34 @@ READ8_MEMBER(intellec4_state::romf_in) 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 @@ -498,6 +577,10 @@ 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)); } @@ -628,6 +711,16 @@ INPUT_CHANGED_MEMBER(intellec4_state::sw_cma_write) 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 @@ -641,6 +734,9 @@ void intellec4_state::driver_start() 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)); @@ -705,6 +801,13 @@ void intellec4_state::driver_reset() 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); diff --git a/src/mame/layout/intlc44.lay b/src/mame/layout/intlc44.lay index 1bc1f7d3853..ffbf6e5f005 100644 --- a/src/mame/layout/intlc44.lay +++ b/src/mame/layout/intlc44.lay @@ -74,6 +74,9 @@ Intel INTELLEC® 4/MOD 40 layout <element name="label_ram"><text string="RAM"><color red="1.0" green="1.0" blue="1.0" /></text></element> <element name="label_prom"><text string="PROM"><color red="1.0" green="1.0" blue="1.0" /></text></element> + <element name="label_prgm"><text string="PRGM"><color red="1.0" green="1.0" blue="1.0" /></text></element> + <element name="label_pwr"><text string="PWR"><color red="1.0" green="1.0" blue="1.0" /></text></element> + <element name="label_passes"><text string="PASSES"><color red="1.0" green="1.0" blue="1.0" /></text></element> <element name="label_run"><text string="RUN"><color red="1.0" green="1.0" blue="1.0" /></text></element> @@ -114,6 +117,13 @@ Intel INTELLEC® 4/MOD 40 layout <text string="LAST RAM/ROM POINTER" align="1"><color red="1.0" green="1.0" blue="1.0" /></text> </element> + <element name="label_on"> + <text string="ON" align="1"><color red="1.0" green="1.0" blue="1.0" /></text> + </element> + <element name="label_off"> + <text string="OFF" align="1"><color red="1.0" green="1.0" blue="1.0" /></text> + </element> + <element name="label_enable"> <text string="ENABLE" align="2"><color red="1.0" green="1.0" blue="1.0" /></text> </element> @@ -244,6 +254,12 @@ Intel INTELLEC® 4/MOD 40 layout <cpanel element="label_ram"><bounds left="604" top="230" right="629" bottom="237" /></cpanel> <cpanel element="label_prom"><bounds left="635" top="230" right="660" bottom="237" /></cpanel> + <cpanel element="label_prgm"><bounds left="728" top="214" right="753" bottom="221" /></cpanel> + <cpanel element="label_prom"><bounds left="728" top="222" right="753" bottom="229" /></cpanel> + <cpanel element="label_pwr"><bounds left="728" top="230" right="753" bottom="237" /></cpanel> + <cpanel element="label_on"><bounds left="758" top="239" right="814" bottom="246" /></cpanel> + <cpanel element="label_off"><bounds left="758" top="279" right="814" bottom="287" /></cpanel> + <cpanel element="label_pass_counter"><bounds left="72" top="296" right="194" bottom="304" /></cpanel> <cpanel element="label_passes"><bounds left="74" top="304" right="192" bottom="311" /></cpanel> <cpanel element="label_3"><bounds left="74" top="312" right="99" bottom="319" /></cpanel> @@ -467,6 +483,10 @@ Intel INTELLEC® 4/MOD 40 layout <bounds left="635" top="240" right="660" bottom="286" /> </cpanel> + <cpanel element="switch" inputtag="PROM" inputmask="0x0001"> + <bounds left="728" top="240" right="753" bottom="286" /> + </cpanel> + <cpanel element="switch" inputtag="PASSES" inputmask="0x08"> <bounds left="74" top="322" right="99" bottom="368" /> </cpanel> @@ -614,6 +634,12 @@ Intel INTELLEC® 4/MOD 40 layout <cpanel element="label_ram"><bounds left="604" top="230" right="629" bottom="237" /></cpanel> <cpanel element="label_prom"><bounds left="635" top="230" right="660" bottom="237" /></cpanel> + <cpanel element="label_prgm"><bounds left="728" top="214" right="753" bottom="221" /></cpanel> + <cpanel element="label_prom"><bounds left="728" top="222" right="753" bottom="229" /></cpanel> + <cpanel element="label_pwr"><bounds left="728" top="230" right="753" bottom="237" /></cpanel> + <cpanel element="label_on"><bounds left="758" top="239" right="814" bottom="246" /></cpanel> + <cpanel element="label_off"><bounds left="758" top="279" right="814" bottom="287" /></cpanel> + <cpanel element="label_pass_counter"><bounds left="72" top="296" right="194" bottom="304" /></cpanel> <cpanel element="label_passes"><bounds left="74" top="304" right="192" bottom="311" /></cpanel> <cpanel element="label_3"><bounds left="74" top="312" right="99" bottom="319" /></cpanel> @@ -837,6 +863,10 @@ Intel INTELLEC® 4/MOD 40 layout <bounds left="635" top="240" right="660" bottom="286" /> </cpanel> + <cpanel element="switch" inputtag="PROM" inputmask="0x0001"> + <bounds left="728" top="240" right="753" bottom="286" /> + </cpanel> + <cpanel element="switch" inputtag="PASSES" inputmask="0x08"> <bounds left="74" top="322" right="99" bottom="368" /> </cpanel> diff --git a/src/mame/layout/intlc440.lay b/src/mame/layout/intlc440.lay index 27627e335d0..bf11a718128 100644 --- a/src/mame/layout/intlc440.lay +++ b/src/mame/layout/intlc440.lay @@ -73,6 +73,9 @@ Intel INTELLEC® 4/MOD 40 layout <element name="label_ram"><text string="RAM"><color red="1.0" green="1.0" blue="1.0" /></text></element> <element name="label_prom"><text string="PROM"><color red="1.0" green="1.0" blue="1.0" /></text></element> + <element name="label_prgm"><text string="PRGM"><color red="1.0" green="1.0" blue="1.0" /></text></element> + <element name="label_pwr"><text string="PWR"><color red="1.0" green="1.0" blue="1.0" /></text></element> + <element name="label_passes"><text string="PASSES"><color red="1.0" green="1.0" blue="1.0" /></text></element> <element name="label_run"><text string="RUN"><color red="1.0" green="1.0" blue="1.0" /></text></element> @@ -113,6 +116,13 @@ Intel INTELLEC® 4/MOD 40 layout <text string="LAST RAM/ROM POINTER" align="1"><color red="1.0" green="1.0" blue="1.0" /></text> </element> + <element name="label_on"> + <text string="ON" align="1"><color red="1.0" green="1.0" blue="1.0" /></text> + </element> + <element name="label_off"> + <text string="OFF" align="1"><color red="1.0" green="1.0" blue="1.0" /></text> + </element> + <element name="label_enable"> <text string="ENABLE" align="2"><color red="1.0" green="1.0" blue="1.0" /></text> </element> @@ -240,6 +250,12 @@ Intel INTELLEC® 4/MOD 40 layout <cpanel element="label_ram"><bounds left="604" top="230" right="629" bottom="237" /></cpanel> <cpanel element="label_prom"><bounds left="635" top="230" right="660" bottom="237" /></cpanel> + <cpanel element="label_prgm"><bounds left="728" top="214" right="753" bottom="221" /></cpanel> + <cpanel element="label_prom"><bounds left="728" top="222" right="753" bottom="229" /></cpanel> + <cpanel element="label_pwr"><bounds left="728" top="230" right="753" bottom="237" /></cpanel> + <cpanel element="label_on"><bounds left="758" top="239" right="814" bottom="246" /></cpanel> + <cpanel element="label_off"><bounds left="758" top="279" right="814" bottom="287" /></cpanel> + <cpanel element="label_pass_counter"><bounds left="72" top="296" right="194" bottom="304" /></cpanel> <cpanel element="label_passes"><bounds left="74" top="304" right="192" bottom="311" /></cpanel> <cpanel element="label_3"><bounds left="74" top="312" right="99" bottom="319" /></cpanel> @@ -462,6 +478,10 @@ Intel INTELLEC® 4/MOD 40 layout <bounds left="635" top="240" right="660" bottom="286" /> </cpanel> + <cpanel element="switch" inputtag="PROM" inputmask="0x0001"> + <bounds left="728" top="240" right="753" bottom="286" /> + </cpanel> + <cpanel element="switch" inputtag="PASSES" inputmask="0x08"> <bounds left="74" top="322" right="99" bottom="368" /> </cpanel> @@ -609,6 +629,12 @@ Intel INTELLEC® 4/MOD 40 layout <cpanel element="label_ram"><bounds left="604" top="230" right="629" bottom="237" /></cpanel> <cpanel element="label_prom"><bounds left="635" top="230" right="660" bottom="237" /></cpanel> + <cpanel element="label_prgm"><bounds left="728" top="214" right="753" bottom="221" /></cpanel> + <cpanel element="label_prom"><bounds left="728" top="222" right="753" bottom="229" /></cpanel> + <cpanel element="label_pwr"><bounds left="728" top="230" right="753" bottom="237" /></cpanel> + <cpanel element="label_on"><bounds left="758" top="239" right="814" bottom="246" /></cpanel> + <cpanel element="label_off"><bounds left="758" top="279" right="814" bottom="287" /></cpanel> + <cpanel element="label_pass_counter"><bounds left="72" top="296" right="194" bottom="304" /></cpanel> <cpanel element="label_passes"><bounds left="74" top="304" right="192" bottom="311" /></cpanel> <cpanel element="label_3"><bounds left="74" top="312" right="99" bottom="319" /></cpanel> @@ -831,6 +857,10 @@ Intel INTELLEC® 4/MOD 40 layout <bounds left="635" top="240" right="660" bottom="286" /> </cpanel> + <cpanel element="switch" inputtag="PROM" inputmask="0x0001"> + <bounds left="728" top="240" right="753" bottom="286" /> + </cpanel> + <cpanel element="switch" inputtag="PASSES" inputmask="0x08"> <bounds left="74" top="322" right="99" bottom="368" /> </cpanel> diff --git a/src/mame/machine/imm6_76.cpp b/src/mame/machine/imm6_76.cpp new file mode 100644 index 00000000000..b30a1c5e9da --- /dev/null +++ b/src/mame/machine/imm6_76.cpp @@ -0,0 +1,204 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +#include "emu.h" +#include "imm6_76.h" + +#include <algorithm> + + +DEFINE_DEVICE_TYPE(INTEL_IMM6_76, intel_imm6_76_device, "imm6_76", "Intel imm6-76 PROM programmer") + + +intel_imm6_76_device::intel_imm6_76_device( + machine_config const &mconfig, + char const *tag, + device_t *owner, + uint32_t clock) + : device_t(mconfig, INTEL_IMM6_76, tag, owner, clock) + , device_image_interface(mconfig, *this) + , m_cycle_tmr(nullptr), m_cycle_a_tmr(nullptr), m_prg_tmr(nullptr) + , m_di(0U), m_a(0U) + , m_do_enable(true), m_di_pos(true), m_do_pos(true) + , m_r_w(false), m_r_w_a(false) + , m_prgm_pwr(false) + , m_cycle(false), m_cycle_a(false), m_prg(false) +{ + std::fill(std::begin(m_data), std::end(m_data), 0U); +} + + +void intel_imm6_76_device::device_start() +{ + m_cycle_tmr = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(intel_imm6_76_device::cycle_expired), this)); + m_cycle_a_tmr = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(intel_imm6_76_device::cycle_a_expired), this)); + m_prg_tmr = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(intel_imm6_76_device::prg_expired), this)); + + save_item(NAME(m_data)); + save_item(NAME(m_di)); + save_item(NAME(m_a)); + save_item(NAME(m_do_enable)); + save_item(NAME(m_di_pos)); + save_item(NAME(m_do_pos)); + save_item(NAME(m_r_w)); + save_item(NAME(m_r_w_a)); + save_item(NAME(m_prgm_pwr)); + save_item(NAME(m_cycle)); + save_item(NAME(m_cycle_a)); + save_item(NAME(m_prg)); +} + + +image_init_result intel_imm6_76_device::call_load() +{ + if (length() != ARRAY_LENGTH(m_data)) + return image_init_result::FAIL; + else if (fread(m_data, ARRAY_LENGTH(m_data)) != ARRAY_LENGTH(m_data)) + return image_init_result::FAIL; + else + return image_init_result::PASS; +} + +image_init_result intel_imm6_76_device::call_create(int format_type, util::option_resolution *format_options) +{ + std::fill(std::begin(m_data), std::end(m_data), 0U); + if (fwrite(m_data, ARRAY_LENGTH(m_data)) != ARRAY_LENGTH(m_data)) + return image_init_result::FAIL; + else + return image_init_result::PASS; +} + +void intel_imm6_76_device::call_unload() +{ + if (!is_readonly()) + { + fseek(0, SEEK_SET); + fwrite(m_data, ARRAY_LENGTH(m_data)); + } + std::fill(std::begin(m_data), std::end(m_data), 0U); +} + + +void intel_imm6_76_device::di_w(u8 data) +{ + if (data != m_di) + { + if (m_prg) + logerror("data inputs changed during write - PROM damage likely (%02X -> %02X)\n", m_di, data); + m_di = data; + } +} + +void intel_imm6_76_device::a_w(u8 data) +{ + if (data != m_a) + { + if (m_prg) + logerror("address changed during write - PROM damage likely (%02X -> %02X)\n", m_a, data); + m_a = data; + } +} + +u8 intel_imm6_76_device::do_r() const +{ + if (!m_do_enable) + { + return 0xffU; + } + else + { + u8 const data(!m_prg ? m_data[m_a] : m_di_pos ? ~m_di : m_di); + return m_do_pos ? ~data : data; + } +} + +DECLARE_WRITE_LINE_MEMBER(intel_imm6_76_device::data_out_enable) +{ + m_do_enable = bool(state); +} + +DECLARE_WRITE_LINE_MEMBER(intel_imm6_76_device::data_in_positive) +{ + if (bool(state) != m_di_pos) + { + if (m_prg) + logerror("input polarity changed during write - PROM damage likely (%c -> %c)\n", m_di_pos ? '+' : '-', bool(state) ? '+' : '-'); + m_di_pos = bool(state); + } +} + +DECLARE_WRITE_LINE_MEMBER(intel_imm6_76_device::data_out_positive) +{ + m_do_pos = !bool(state); +} + +WRITE_LINE_MEMBER(intel_imm6_76_device::r_w) +{ + if (!m_r_w && !bool(state) && !m_cycle) + { + // half 9602 with Rx = 20kΩ, Cx = 22µF, 1N914 across capacitor + // wired to prevent re-triggering + m_cycle_tmr->adjust(attotime::from_msec(150)); + trigger_prg(); + m_cycle = true; + } + m_r_w = !bool(state); +} + +WRITE_LINE_MEMBER(intel_imm6_76_device::r_w_a) +{ + if (!m_r_w_a && !bool(state) && !m_cycle_a) + { + // half 9602 with Rx = 20kΩ, Cx = 2.2µF, 1N914 across capacitor + // wired to prevent re-triggering + m_cycle_a_tmr->adjust(attotime::from_msec(15)); + trigger_prg(); + m_cycle_a = true; + } + m_r_w_a = !bool(state); +} + +WRITE_LINE_MEMBER(intel_imm6_76_device::prgm_prom_pwr) +{ + if (!bool(state) != m_prgm_pwr) + { + if (m_prg) + logerror("programming power %s during write - PROM damage likely\n", bool(state) ? "disabled" : "enabled"); + m_prgm_pwr = !bool(state); + } +} + + +TIMER_CALLBACK_MEMBER(intel_imm6_76_device::cycle_expired) +{ + m_cycle = false; +} + +TIMER_CALLBACK_MEMBER(intel_imm6_76_device::cycle_a_expired) +{ + m_cycle_a = false; +} + +TIMER_CALLBACK_MEMBER(intel_imm6_76_device::prg_expired) +{ + m_prg = false; +} + + +void intel_imm6_76_device::trigger_prg() +{ + if (!m_cycle && !m_cycle_a) + { + // half 9602 with Rx = 4.7kΩ + 20kΩ trimpot, Cx = 1.0µF + m_prg_tmr->adjust(attotime::from_usec(3250)); + if (!m_prg) + { + if (m_prgm_pwr && is_loaded()) + m_data[m_a] |= m_di_pos ? ~m_di : m_di; // PROM can't be erased electronically + m_prg = true; + } + else + { + logerror("write re-triggered - PROM damage likely\n"); + } + } +} diff --git a/src/mame/machine/imm6_76.h b/src/mame/machine/imm6_76.h new file mode 100644 index 00000000000..cd21f72c024 --- /dev/null +++ b/src/mame/machine/imm6_76.h @@ -0,0 +1,203 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/* +Intel imm6-76 PROM programmer + +Simple programmer for 1602/1702 and 1602A/1702A 256x8 static PMOS +UVEPROMs (1602/1602A have a metal lid preventing erasure but are +otherwise identical to 1702/1702A). Used in the INTELLEC® 4 and +INTELLEC® 8 development systems. + +P1 universal edge connector (only used for power) + + 1 2 + GND 3 4 GND + 5 6 + 7 8 + 9 10 + 11 12 + 13 14 + 15 16 + 17 18 + 19 20 + 21 22 + 23 24 + 25 26 + 27 28 + 29 30 + 31 32 + 33 34 + 35 36 + 37 38 + 39 40 + 41 42 + -10V 43 44 -10V + 45 46 + 47 48 + 49 50 + 51 52 + 53 54 + 55 56 + 57 58 + 59 60 + 61 62 + 63 64 + 65 66 + 67 68 + 69 70 + 71 72 + 73 74 + 75 76 + 77 78 + 79 80 + 81 82 + 83 84 + 85 86 + 87 88 + 89 90 + 91 92 + 93 94 + 95 96 + 97 98 + +5V 99 100 +5V + + +J1 40-pin IDC connector (data/control) + + DI1 1 2 A0 + DI2 3 4 A1 + DI3 5 6 A2 + DI4 7 8 A3 + DI5 9 10 A4 + DI6 11 12 A5 + DI7 13 14 A6 + DI8 15 16 A7 + DO1 17 18 + DO2 19 20 + DO3 21 22 + DO4 23 24 DATA OUT ENABLE + DO5 25 26 DATA IN + TRUE + DO6 27 28 /DATA OUT + TRUE + DO7 29 30 R/W (1702) + DO8 31 32 R/W A (1702A) + GND 33 34 GND + GND 35 36 GND + GND 37 38 GND + GND 39 40 GND + + +J2 40-pin IDC connector (to PROM socket) + + D1 1 2 A0 + D2 3 4 A1 + D3 5 6 A2 + D4 7 8 A3 + D5 9 10 A4 + D6 11 11 A5 + D7 13 12 A6 + D8 15 16 A7 + GND 17 18 GND + Vccs 19 20 Vccs + Vdd 21 22 Vdd + Vgg 23 24 /CS + Vbb 25 26 PRGM + 27 28 + 29 30 + 31 32 + GND 33 34 GND + 35 36 + 37 38 + 39 40 + + +J3 Six-pin connector on flying leads + + 50V AC 1 2 + 50V AC 3 4 +80V DC +/PRGM PROM PWR 5 6 GND + + +DO are open-collector TTL outputs with 5.6kΩ pullups. + +DATA OUT ENABLE has an onboard 5.6kΩ pullup. Driving it low disables DO +outputs. + +DATA IN + TRUE (if jumpered in) has a 5.6kΩ pullup and is XORed with the +DI inputs. It should be pulled low in systems that use negative logic. +It is not jumpered in when used with INTELLEC 4 or INTELLEC 8 systems. + +/DATA OUT + TRUE (if jumpered in) has a 5.6kΩ and is XORed with the PROM +data outputs. It should be pulled low in systems that use positive +logic. It is not jumpered in when used with INTELLEC 4 or INTELLEC 8 +systems, the line is tied low with an onboard jumper. + +/PRGM PROM PWR has a 27kΩ pullup to +80V DC and must be pulled low (to +GND) for programming voltage to be applied to the PROM. + +When pulled low, R/W initiates a 2% programming duty cycle for writing +to a 1602 or 1702 PROM (150 millisecond cycle time). + +When pulled low, RW A initiates a 20% programming duty cycle for writing +to a 1602A or 1702A PROM (15 millisecond cycle time). +*/ +#ifndef MAME_MACHINE_IMM6_76_H +#define MAME_MACHINE_IMM6_76_H + +#pragma once + + +class intel_imm6_76_device : public device_t, public device_image_interface +{ +public: + intel_imm6_76_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock); + + // device_image_interface implementation + virtual image_init_result call_load() override; + virtual image_init_result call_create(int format_type, util::option_resolution *format_options) override; + virtual void call_unload() override; + + // device_image_interface static info + virtual iodevice_t image_type() const override { return IO_ROM; } + virtual bool is_readable() const override { return true; } + virtual bool is_writeable() const override { return true; } + virtual bool is_creatable() const override { return true; } + virtual bool must_be_loaded() const override { return false; } + virtual bool is_reset_on_load() const override { return false; } + virtual char const *file_extensions() const override { return "rom,bin"; } + virtual char const *custom_instance_name() const override { return "promimage"; } + virtual char const *custom_brief_instance_name() const override { return "prom"; } + + void di_w(u8 data); + void a_w(u8 data); + u8 do_r() const; + DECLARE_WRITE_LINE_MEMBER(data_out_enable); // 1 = asserted + DECLARE_WRITE_LINE_MEMBER(data_in_positive); // 1 = asserted + DECLARE_WRITE_LINE_MEMBER(data_out_positive); // 0 = asserted + DECLARE_WRITE_LINE_MEMBER(r_w); // 1 = read, 0 = write + DECLARE_WRITE_LINE_MEMBER(r_w_a); // 1 = read, 0 = write + DECLARE_WRITE_LINE_MEMBER(prgm_prom_pwr); // 0 = asserted + +protected: + // device_t implementation + virtual void device_start() override; + +private: + TIMER_CALLBACK_MEMBER(cycle_expired); + TIMER_CALLBACK_MEMBER(cycle_a_expired); + TIMER_CALLBACK_MEMBER(prg_expired); + + void trigger_prg(); + + emu_timer *m_cycle_tmr, *m_cycle_a_tmr, *m_prg_tmr; + + u8 m_data[256]; + u8 m_di, m_a; + bool m_do_enable, m_di_pos, m_do_pos; + bool m_r_w, m_r_w_a; + bool m_prgm_pwr; + bool m_cycle, m_cycle_a, m_prg; +}; + +DECLARE_DEVICE_TYPE(INTEL_IMM6_76, intel_imm6_76_device) + +#endif // MAME_MACHINE_IMM6_76_H |