pps41: add serial i/o

This commit is contained in:
hap 2021-03-09 18:06:04 +01:00
parent fa467244bf
commit efe9ac40f6
4 changed files with 71 additions and 9 deletions

View File

@ -42,6 +42,9 @@ public:
protected:
virtual void device_start() override;
virtual u32 execute_input_lines() const noexcept override { return 2; }
virtual void execute_set_input(int line, int state) override { if (line < 2) mm76_device::execute_set_input(line, state); }
// opcode handlers
virtual void op_ios() override;
virtual void op_i2c() override;

View File

@ -175,12 +175,14 @@ void mm76_device::op_xas()
u8 a = m_a;
m_a = m_s;
m_s = a;
m_write_sdo(BIT(m_s, 3));
}
void mm76_device::op_lsa()
{
// LSA: load S from A
m_s = m_a;
m_write_sdo(BIT(m_s, 3));
}
@ -413,7 +415,7 @@ void mm76_device::op_oa()
void mm76_device::op_ios()
{
// IOS: start serial I/O
op_todo();
m_sclock_count = 8;
}
void mm76_device::op_i1()

View File

@ -40,7 +40,6 @@ TODO:
flops with SOS/ROS opcodes
- allowed opcodes after TAB should be limited
- add MCU mask options, there's one for inverting interrupts
- add serial i/o
- add MM78LA
*/
@ -62,7 +61,9 @@ pps41_base_device::pps41_base_device(const machine_config &mconfig, device_type
m_read_d(*this),
m_write_d(*this),
m_read_r(*this),
m_write_r(*this)
m_write_r(*this),
m_write_sdo(*this),
m_write_ssc(*this)
{ }
@ -83,6 +84,8 @@ void pps41_base_device::device_start()
m_write_d.resolve_safe();
m_read_r.resolve_safe(0xff);
m_write_r.resolve_safe();
m_write_sdo.resolve_safe();
m_write_ssc.resolve_safe();
// init RAM with 0xf
for (int i = 0; i <= m_datamask; i++)
@ -108,16 +111,21 @@ void pps41_base_device::device_start()
m_prev_c = 0;
m_c_in = 0;
m_c_delay = false;
m_s = 0;
m_x = 0;
m_skip = false;
m_skip_count = 0;
m_s = 0;
m_sdi = 0;
m_sclock_in = 0;
m_sclock_count = 0;
m_ss_pending = false;
m_d_pins = 10;
m_d_mask = (1 << m_d_pins) - 1;
m_d_output = 0;
m_r_output = 0;
m_int_line[0] = m_int_line[1] = 1;
m_int_line[0] = m_int_line[1] = 0;
m_int_ff[0] = m_int_ff[1] = 0;
// register for savestates
@ -140,11 +148,16 @@ void pps41_base_device::device_start()
save_item(NAME(m_prev_c));
save_item(NAME(m_c_in));
save_item(NAME(m_c_delay));
save_item(NAME(m_s));
save_item(NAME(m_x));
save_item(NAME(m_skip));
save_item(NAME(m_skip_count));
save_item(NAME(m_s));
save_item(NAME(m_sdi));
save_item(NAME(m_sclock_in));
save_item(NAME(m_sclock_count));
save_item(NAME(m_ss_pending));
save_item(NAME(m_d_output));
save_item(NAME(m_r_output));
save_item(NAME(m_int_line));
@ -187,6 +200,11 @@ void pps41_base_device::device_reset()
// clear outputs
m_write_r(m_r_output = 0xff);
m_write_d(m_d_output = 0);
m_s = 0;
m_sclock_count = 0;
m_write_sdo(0);
m_write_ssc(0);
}
@ -214,6 +232,17 @@ void pps41_base_device::execute_set_input(int line, int state)
m_int_line[1] = state;
break;
case PPS41_INPUT_LINE_SDI:
m_sdi = state;
break;
case PPS41_INPUT_LINE_SSC:
// serial shift pending on falling edge
if (!state && m_sclock_in)
m_ss_pending = true;
m_sclock_in = state;
break;
default:
break;
}
@ -227,6 +256,21 @@ void pps41_base_device::execute_set_input(int line, int state)
void pps41_base_device::cycle()
{
m_icount--;
// clock serial i/o
m_ss_pending = m_ss_pending || bool(m_sclock_count & 1);
if (m_sclock_count)
{
m_sclock_count--;
m_write_ssc(m_sclock_count & 1);
}
if (m_ss_pending)
{
m_ss_pending = false;
m_s = (m_s << 1 | m_sdi) & 0xf;
m_write_sdo(BIT(m_s, 3));
}
}
void pps41_base_device::increment_pc()

View File

@ -16,7 +16,9 @@
enum
{
PPS41_INPUT_LINE_INT0 = 0,
PPS41_INPUT_LINE_INT1
PPS41_INPUT_LINE_INT1,
PPS41_INPUT_LINE_SDI, // serial data input
PPS41_INPUT_LINE_SSC // serial shift clock
};
@ -37,6 +39,10 @@ public:
auto read_r() { return m_read_r.bind(); }
auto write_r() { return m_write_r.bind(); }
// serial data/clock
auto write_sdo() { return m_write_sdo.bind(); }
auto write_ssc() { return m_write_ssc.bind(); }
protected:
// construction/destruction
pps41_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data);
@ -48,7 +54,7 @@ protected:
// device_execute_interface overrides
virtual u32 execute_min_cycles() const noexcept override { return 1; }
virtual u32 execute_max_cycles() const noexcept override { return 2; }
virtual u32 execute_input_lines() const noexcept override { return 2; }
virtual u32 execute_input_lines() const noexcept override { return 4; }
virtual void execute_set_input(int line, int state) override;
virtual void execute_run() override;
virtual void execute_one() = 0;
@ -78,6 +84,8 @@ protected:
devcb_write16 m_write_d;
devcb_read8 m_read_r;
devcb_write8 m_write_r;
devcb_write_line m_write_sdo;
devcb_write_line m_write_ssc;
// internal state, regs
u16 m_pc;
@ -100,11 +108,16 @@ protected:
int m_prev_c;
int m_c_in;
bool m_c_delay;
u8 m_s;
u8 m_x;
bool m_skip;
int m_skip_count;
u8 m_s;
int m_sdi;
int m_sclock_in;
int m_sclock_count;
bool m_ss_pending;
int m_d_pins;
u16 m_d_mask;
u16 m_d_output;