159 lines
3.8 KiB
C++
159 lines
3.8 KiB
C++
// license:BSD-3-Clause
|
|
// copyright-holders:hap
|
|
/*
|
|
|
|
TMS1000 family - TMS0270
|
|
|
|
*/
|
|
|
|
#include "emu.h"
|
|
#include "tms0270.h"
|
|
|
|
// TMS0270 is a TMS0980 with earrings and a new hat. The new changes look like a quick afterthought, almost hacky
|
|
// - RAM, ROM, and main instructions PLAs is the same as TMS0980
|
|
// - 64-term microinstructions PLA between the RAM and ROM, similar to TMS0980,
|
|
// plus optional separate lines for custom opcode handling
|
|
// - 48-term output PLA above the RAM (rotate opla 90 degrees)
|
|
DEFINE_DEVICE_TYPE(TMS0270, tms0270_cpu_device, "tms0270", "Texas Instruments TMS0270") // 40-pin DIP, 16 O pins, 8+ R pins (some R pins are internally hooked up to support more I/O)
|
|
// newer TMS0270 chips (eg. Speak & Math) have 42 pins
|
|
|
|
// TMS0260 is same or similar?
|
|
|
|
|
|
// device definitions
|
|
tms0270_cpu_device::tms0270_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
|
: tms0980_cpu_device(mconfig, TMS0270, tag, owner, clock, 16 /* o pins */, 16 /* r pins */, 7 /* pc bits */, 9 /* byte width */, 4 /* x width */, 11 /* prg width */, address_map_constructor(FUNC(tms0270_cpu_device::program_11bit_9), this), 8 /* data width */, address_map_constructor(FUNC(tms0270_cpu_device::data_144x4), this))
|
|
{
|
|
}
|
|
|
|
|
|
// machine configs
|
|
void tms0270_cpu_device::device_add_mconfig(machine_config &config)
|
|
{
|
|
// main opcodes PLA, microinstructions PLA, output PLA
|
|
PLA(config, "ipla", 9, 22, 24).set_format(pla_device::FMT::BERKELEY);
|
|
PLA(config, "mpla", 6, 22, 64).set_format(pla_device::FMT::BERKELEY);
|
|
PLA(config, "opla", 6, 16, 48).set_format(pla_device::FMT::BERKELEY);
|
|
}
|
|
|
|
|
|
// device_start/reset
|
|
void tms0270_cpu_device::device_start()
|
|
{
|
|
// common init
|
|
tms1k_base_device::device_start();
|
|
|
|
// zerofill
|
|
m_r_prev = 0;
|
|
m_chipsel = 0;
|
|
m_ctl_dir = 0;
|
|
m_ctl_out = 0;
|
|
m_pdc = -1; // !
|
|
|
|
m_o_latch_low = 0;
|
|
m_o_latch = 0;
|
|
m_o_latch_prev = 0;
|
|
|
|
// register for savestates
|
|
save_item(NAME(m_r_prev));
|
|
save_item(NAME(m_chipsel));
|
|
save_item(NAME(m_ctl_dir));
|
|
save_item(NAME(m_ctl_out));
|
|
save_item(NAME(m_pdc));
|
|
|
|
save_item(NAME(m_o_latch_low));
|
|
save_item(NAME(m_o_latch));
|
|
save_item(NAME(m_o_latch_prev));
|
|
}
|
|
|
|
void tms0270_cpu_device::device_reset()
|
|
{
|
|
// common reset
|
|
tms0980_cpu_device::device_reset();
|
|
|
|
m_o_latch_low = 0;
|
|
m_o_latch = 0;
|
|
m_o_latch_prev = 0;
|
|
}
|
|
|
|
|
|
// i/o handling
|
|
void tms0270_cpu_device::dynamic_output()
|
|
{
|
|
// R12: chip select (off=display via OPLA, on=TMS5100 via ACC/CKB)
|
|
m_chipsel = BIT(m_r, 12);
|
|
|
|
if (m_chipsel)
|
|
{
|
|
// R11: TMS5100 CTL port direction (0=read from TMS5100, 1=write to TMS5100)
|
|
m_ctl_dir = BIT(m_r, 11);
|
|
|
|
// ACC via SEG G,B,C,D: TMS5100 CTL pins
|
|
if (m_ctl_dir && m_ctl_out != m_a)
|
|
{
|
|
m_ctl_out = m_a;
|
|
m_write_ctl(m_ctl_out);
|
|
}
|
|
|
|
// R10 via SEG E: TMS5100 PDC pin
|
|
int pdc = BIT(m_r, 10);
|
|
if (m_pdc != pdc)
|
|
{
|
|
m_pdc = pdc;
|
|
m_write_pdc(m_pdc);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// standard O-output
|
|
if (m_o_latch != m_o_latch_prev)
|
|
{
|
|
write_o_output(m_o_latch);
|
|
m_o_latch_prev = m_o_latch;
|
|
}
|
|
}
|
|
|
|
// standard R-output
|
|
if (m_r != m_r_prev)
|
|
{
|
|
m_write_r(m_r & m_r_mask);
|
|
m_r_prev = m_r;
|
|
}
|
|
}
|
|
|
|
u8 tms0270_cpu_device::read_k_input()
|
|
{
|
|
// external: TMS5100 CTL port via SEG G,B,C,D
|
|
if (m_chipsel)
|
|
return (m_ctl_dir) ? m_ctl_out : m_read_ctl() & 0xf;
|
|
|
|
// standard K-input otherwise
|
|
u8 k = m_read_k() & 0x1f;
|
|
return (k & 0x10) ? 0xf : k; // the TMS0270 KF line asserts all K-inputs
|
|
}
|
|
|
|
|
|
// opcode deviations
|
|
void tms0270_cpu_device::op_setr()
|
|
{
|
|
// same as default, but handle write to output in dynamic_output
|
|
m_r = m_r | (1 << m_y);
|
|
}
|
|
|
|
void tms0270_cpu_device::op_rstr()
|
|
{
|
|
// same as default, but handle write to output in dynamic_output
|
|
m_r = m_r & ~(1 << m_y);
|
|
}
|
|
|
|
void tms0270_cpu_device::op_tdo()
|
|
{
|
|
// TDO: transfer data out
|
|
if (m_status)
|
|
m_o_latch_low = m_a;
|
|
else
|
|
m_o_latch = m_o_latch_low | (m_a << 4 & 0x30);
|
|
|
|
// write to output is done in dynamic_output
|
|
}
|