m6801: add standby pin

This commit is contained in:
hap 2023-11-10 19:55:56 +01:00
parent 9a1fbb83e3
commit 98bc034070
8 changed files with 61 additions and 32 deletions

View File

@ -22,10 +22,13 @@ System dependencies: uint16_t must be 16 bit unsigned int
TODO:
- verify invalid opcodes for the different CPU types
- add 6802 nvram (only in case VCC STANDBY is connected to battery)
- cleanups (difficult to do maintenance work right now)
- improve 6801 and derivatives:
* make internal I/O map really internal
* RAM control register (eg. nvram)
* add internal nvram where applicable
* improve RAM control register
* improve STBY pin? RES pin (reset) should be ineffective while STBY is low
* IS3 interrupt for 6801 port 3 handshake (already implemented for 6301Y)
* finish 6301Y port 6 handshake, share implementation with p3csr?
* 6301Y sci_trcsr2_r/w
@ -487,8 +490,6 @@ void m6800_cpu_device::enter_interrupt(const char *message,uint16_t irq_vector)
/* check the IRQ lines for pending interrupts */
void m6800_cpu_device::check_irq_lines()
{
// TODO: IS3 interrupt
if (m_nmi_pending)
{
if (m_wai_state & M6800_SLP)

View File

@ -80,7 +80,7 @@ protected:
uint8_t m_wai_state; /* WAI opcode state (or sleep opcode state) */
uint8_t m_nmi_state; /* NMI line state */
uint8_t m_nmi_pending; /* NMI pending */
uint8_t m_irq_state[4]; /* IRQ line state [IRQ1,TIN,SC1,IS] */
uint8_t m_irq_state[3]; /* IRQ line state [IRQ1,TIN,IS3] */
/* Memory spaces */
memory_access<16, 0, 0, ENDIANNESS_BIG>::cache m_cprogram, m_copcodes;

View File

@ -319,6 +319,7 @@ m6801_cpu_device::m6801_cpu_device(const machine_config &mconfig, device_type ty
, m_out_port_func(*this)
, m_out_sc2_func(*this)
, m_out_sertx_func(*this)
, m_standby_func(*this)
, m_sclk_divider(8)
{
}
@ -451,7 +452,7 @@ void hd6301y_cpu_device::m6800_check_irq2()
{
if ((m_p6csr & 0xc0) == 0xc0)
{
standard_irq_callback(M6801_IS_LINE, m_pc.w.l);
standard_irq_callback(M6801_IS3_LINE, m_pc.w.l);
TAKE_ISI;
}
else
@ -950,8 +951,20 @@ void m6801_cpu_device::execute_set_input(int irqline, int state)
{
switch (irqline)
{
case M6801_SC1_LINE:
if (!m_sc1_state && (CLEAR_LINE != state))
case M6801_STBY_LINE:
if (!m_standby && state != CLEAR_LINE)
{
// clock stops, MCU goes into reset state, all pins except XTAL and STBY go high impedance
m_standby = true;
suspend(SUSPEND_REASON_CLOCK, true);
m_standby_func(1);
// once in standby, it can only recover from it after a reset
}
break;
case M6801_IS3_LINE:
if (!m_is3_state && state != CLEAR_LINE)
{
if (!m_port3_latched && (m_p3csr & M6801_P3CSR_LE))
{
@ -968,7 +981,7 @@ void m6801_cpu_device::execute_set_input(int irqline, int state)
LOGPORT("Not latching Port 3 Data:%s%s", m_port3_latched ? " already latched" : "", (m_p3csr & M6801_P3CSR_LE) ? "" : " LE clear");
}
}
m_sc1_state = ASSERT_LINE == state;
m_is3_state = state;
break;
case M6801_TIN_LINE:
@ -976,7 +989,7 @@ void m6801_cpu_device::execute_set_input(int irqline, int state)
{
m_irq_state[M6801_TIN_LINE] = state;
//edge = (state == CLEAR_LINE ) ? 2 : 0;
if (((m_tcsr&TCSR_IEDG) ^ (state==CLEAR_LINE ? TCSR_IEDG : 0)) == 0)
if (((m_tcsr & TCSR_IEDG) ^ (state == CLEAR_LINE ? TCSR_IEDG : 0)) == 0)
return;
/* active edge in */
m_tcsr |= TCSR_ICF;
@ -996,15 +1009,15 @@ void hd6301y_cpu_device::execute_set_input(int irqline, int state)
{
switch (irqline)
{
case M6801_IS_LINE:
case M6801_IS3_LINE:
// interrupt at falling edge
if (!state && m_irq_state[M6801_IS_LINE])
if (!state && m_irq_state[M6801_IS3_LINE])
{
m_p6csr |= 0x80; // IS flag
m_pending_isf_clear = false;
}
m_irq_state[M6801_IS_LINE] = state;
m_irq_state[M6801_IS3_LINE] = state;
break;
default:
@ -1051,10 +1064,11 @@ void m6801_cpu_device::device_start()
m_ext_serclock = 0;
m_use_ext_serclock = false;
m_standby = false;
m_latch09 = 0;
m_is3_state = 0;
m_timer_over.d = 0;
m_timer_next = 0;
m_sc1_state = 0;
save_item(NAME(m_port_ddr));
save_item(NAME(m_port_data));
@ -1087,10 +1101,11 @@ void m6801_cpu_device::device_start()
save_item(NAME(m_ext_serclock));
save_item(NAME(m_use_ext_serclock));
save_item(NAME(m_standby));
save_item(NAME(m_latch09));
save_item(NAME(m_is3_state));
save_item(NAME(m_timer_over.d));
save_item(NAME(m_timer_next));
save_item(NAME(m_sc1_state));
}
void hd6301x_cpu_device::device_start()
@ -1134,8 +1149,10 @@ void m6801_cpu_device::device_reset()
{
m6800_cpu_device::device_reset();
m_standby = false;
m_standby_func(0);
m_irq_state[M6801_TIN_LINE] = 0;
m_sc1_state = 0;
m_is3_state = 0;
m_port_ddr[0] = 0x00;
m_port_ddr[1] = 0x00;
@ -1487,7 +1504,7 @@ uint8_t hd6301y_cpu_device::p5_data_r()
if (m_portx_ddr[0] == 0xff)
return m_portx_data[0];
else
return ((m_in_portx_func[0]() | ((m_irq_state[M6801_IS_LINE]) ? 0x10 : 0)) & (m_portx_ddr[0] ^ 0xff)) | (m_portx_data[0] & m_portx_ddr[0]);
return ((m_in_portx_func[0]() | ((m_irq_state[M6801_IS3_LINE]) ? 0x10 : 0)) & (m_portx_ddr[0] ^ 0xff)) | (m_portx_data[0] & m_portx_ddr[0]);
}
void hd6301y_cpu_device::p5_data_w(uint8_t data)
@ -1950,6 +1967,15 @@ void m6801_cpu_device::rcr_w(uint8_t data)
m_ram_ctrl = data;
}
void hd6301y_cpu_device::rcr_w(uint8_t data)
{
m6801_cpu_device::rcr_w(data);
// software standby mode
if (~data & 0x20)
execute_set_input(M6801_STBY_LINE, ASSERT_LINE);
}
uint8_t m6801_cpu_device::ff_r()
{
return 0xff;

View File

@ -12,9 +12,9 @@
enum
{
M6801_IRQ_LINE = M6800_IRQ_LINE,
M6801_TIN_LINE, // P20/Tin Input Capture line (edge sense). Active edge is selectable by internal reg.
M6801_SC1_LINE,
M6801_IS_LINE // IS3(6801) or ISF(6301Y)
M6801_TIN_LINE, // P20/TIN Input Capture line (edge sense). Active edge is selectable by internal reg.
M6801_IS3_LINE, // SC1/IOS/IS3 (P54/IS on HD6301Y)
M6801_STBY_LINE // STBY pin, or internal standby
};
enum
@ -57,6 +57,7 @@ public:
auto out_sc2_cb() { return m_out_sc2_func.bind(); }
auto out_ser_tx_cb() { return m_out_sertx_func.bind(); }
auto standby_cb() { return m_standby_func.bind(); } // notifier (not an output pin)
void m6801_io(address_map &map); // FIXME: privatize this
@ -72,7 +73,8 @@ protected:
// device_execute_interface implementation
virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override { return (clocks + 4 - 1) / 4; }
virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const noexcept override { return (cycles * 4); }
virtual uint32_t execute_input_lines() const noexcept override { return 5; }
virtual uint32_t execute_input_lines() const noexcept override { return 6; }
virtual bool execute_input_edge_triggered(int inputnum) const noexcept override { return m6800_cpu_device::execute_input_edge_triggered(inputnum) || inputnum == M6801_STBY_LINE; }
virtual void execute_set_input(int inputnum, int state) override;
// device_disasm_interface implementation
@ -115,7 +117,7 @@ protected:
void sci_tdr_w(uint8_t data);
uint8_t rcr_r();
void rcr_w(uint8_t data);
virtual void rcr_w(uint8_t data);
uint8_t ff_r();
void m6803_mem(address_map &map);
@ -125,6 +127,7 @@ protected:
devcb_write_line m_out_sc2_func;
devcb_write_line m_out_sertx_func;
devcb_write_line m_standby_func;
int m_sclk_divider;
@ -147,15 +150,13 @@ protected:
int m_rxbits, m_txbits, m_txstate, m_trcsr_read_tdre, m_trcsr_read_orfe, m_trcsr_read_rdrf, m_tx, m_ext_serclock;
bool m_use_ext_serclock;
int m_latch09;
bool m_standby;
uint8_t m_latch09;
int m_is3_state;
PAIR m_timer_over;
emu_timer *m_sci_timer;
/* point of next timer event */
uint32_t m_timer_next;
int m_sc1_state;
uint32_t m_timer_next; /* point of next timer event */
static const uint8_t cycles_6803[256];
static const uint8_t cycles_63701[256];
@ -375,6 +376,7 @@ protected:
virtual void p6_data_w(uint8_t data) override;
uint8_t p6_csr_r();
void p6_csr_w(uint8_t data);
virtual void rcr_w(uint8_t data) override;
virtual void m6800_check_irq2() override;
void clear_pending_isf();

View File

@ -943,8 +943,8 @@ void adam_state::os3_w(int state)
//logerror("Master 6801 read from %04x data %02x\n", m_ba, m_data_out);
m_netcpu->set_input_line(M6801_SC1_LINE, ASSERT_LINE);
m_netcpu->set_input_line(M6801_SC1_LINE, CLEAR_LINE);
m_netcpu->set_input_line(M6801_IS3_LINE, ASSERT_LINE);
m_netcpu->set_input_line(M6801_IS3_LINE, CLEAR_LINE);
}
}
}

View File

@ -385,7 +385,7 @@ void leo_state::leonardo(machine_config &config)
m_maincpu->out_p6_cb().set(FUNC(leo_state::p6_w));
INPUT_MERGER_ANY_LOW(config, m_stb);
m_stb->output_handler().set_inputline(m_maincpu, M6801_IS_LINE);
m_stb->output_handler().set_inputline(m_maincpu, M6801_IS3_LINE);
config.set_maximum_quantum(attotime::from_hz(6000));

View File

@ -372,7 +372,7 @@ void ren_state::ren(machine_config &config)
m_maincpu->out_p6_cb().set(FUNC(ren_state::p6_w));
INPUT_MERGER_ANY_LOW(config, m_stb);
m_stb->output_handler().set_inputline(m_maincpu, M6801_IS_LINE);
m_stb->output_handler().set_inputline(m_maincpu, M6801_IS3_LINE);
config.set_maximum_quantum(attotime::from_hz(6000));

View File

@ -960,7 +960,7 @@ void ddragon_state::ddragon(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &ddragon_state::ddragon_map);
TIMER(config, "scantimer").configure_scanline(FUNC(ddragon_state::ddragon_scanline), "screen", 0, 1);
hd63701y0_cpu_device &subcpu(HD63701Y0(config, m_subcpu, MAIN_CLOCK / 2)); /* HD63701YOP, 6 MHz / 4 internally */
hd63701y0_cpu_device &subcpu(HD63701Y0(config, m_subcpu, MAIN_CLOCK / 2)); /* HD63701Y0P, 6 MHz / 4 internally */
subcpu.set_addrmap(AS_PROGRAM, &ddragon_state::sub_map);
subcpu.out_p6_cb().set(FUNC(ddragon_state::sub_port6_w));