INTELLEC 4: implement front-panel PROM programmer

This commit is contained in:
Vas Crabb 2017-07-12 19:58:33 +10:00
parent 4b6e1f2a0c
commit 95906048ab
7 changed files with 581 additions and 3 deletions

View File

@ -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",

View File

@ -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);

View File

@ -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);

View File

@ -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>

View File

@ -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>

View File

@ -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");
}
}
}

203
src/mame/machine/imm6_76.h Normal file
View File

@ -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.6 pullups.
DATA OUT ENABLE has an onboard 5.6 pullup. Driving it low disables DO
outputs.
DATA IN + TRUE (if jumpered in) has a 5.6 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.6 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 27 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