mirror of
https://github.com/holub/mame
synced 2025-04-24 17:30:55 +03:00
mc68901: Sweeping rewrite of USART emulation (no longer based on device_serial_interface), adding support for 16x clock prescaler and data transition synchronization, break generation and detection, internal loopback and synchronous mode.
harriet, x68k_kbd: Adjust serial clocks to match MFP-generated baud rates. indiana: Replace serial ASCII keyboard with AT-style keyboard (which only mostly works). Document some clocks and interrupts. tti: Terminal actually works now.
This commit is contained in:
parent
443e962caa
commit
dbcffd411f
@ -1,9 +1,12 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Curt Coder
|
||||
// copyright-holders:Curt Coder, AJR
|
||||
/**********************************************************************
|
||||
|
||||
Motorola MC68901 Multi Function Peripheral emulation
|
||||
|
||||
This chip was originally designed by Mostek (MK68901) as a 68000-
|
||||
oriented evolution of the Z80 STI.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
/*
|
||||
@ -34,12 +37,7 @@
|
||||
the GLUE is essentially invisible w.r.t IPL. The CPU and the
|
||||
MFP manage to add the delays all by themselves.
|
||||
|
||||
- divide serial clock by 16
|
||||
- synchronous mode
|
||||
- 1.5/2 stop bits
|
||||
- interrupt on receiver break end
|
||||
- interrupt on character boundaries during break transmission
|
||||
- loopback mode
|
||||
- RR & TR outputs
|
||||
|
||||
*/
|
||||
|
||||
@ -47,7 +45,11 @@
|
||||
#include "mc68901.h"
|
||||
#include "cpu/m68000/m68000.h"
|
||||
|
||||
//#define VERBOSE 1
|
||||
#define LOG_GENERAL (1 << 0U)
|
||||
#define LOG_RCV (1 << 1U)
|
||||
#define LOG_XMIT (1 << 2U)
|
||||
|
||||
//#define VERBOSE (LOG_GENERAL | LOG_RCV | LOG_XMIT)
|
||||
#include "logmacro.h"
|
||||
|
||||
|
||||
@ -196,6 +198,22 @@ inline void mc68901_device::take_interrupt(u16 mask)
|
||||
check_interrupts();
|
||||
}
|
||||
|
||||
inline void mc68901_device::tx_buffer_empty()
|
||||
{
|
||||
if (m_ier & IR_XMIT_BUFFER_EMPTY)
|
||||
{
|
||||
take_interrupt(IR_XMIT_BUFFER_EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
inline void mc68901_device::tx_error()
|
||||
{
|
||||
if (m_ier & IR_XMIT_ERROR)
|
||||
{
|
||||
take_interrupt(IR_XMIT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
inline void mc68901_device::rx_buffer_full()
|
||||
{
|
||||
if (m_ier & IR_RCV_BUFFER_FULL)
|
||||
@ -330,10 +348,7 @@ void mc68901_device::gpio_output()
|
||||
|
||||
mc68901_device::mc68901_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, MC68901, tag, owner, clock),
|
||||
device_serial_interface(mconfig, *this),
|
||||
m_timer_clock(0),
|
||||
m_rx_clock(0),
|
||||
m_tx_clock(0),
|
||||
m_out_irq_cb(*this),
|
||||
m_out_gpio_cb(*this),
|
||||
m_out_tao_cb(*this),
|
||||
@ -346,8 +361,28 @@ mc68901_device::mc68901_device(const machine_config &mconfig, const char *tag, d
|
||||
m_iack_chain_cb(*this),
|
||||
m_aer(0),
|
||||
m_ier(0),
|
||||
m_scr(0),
|
||||
m_scr_parity(false),
|
||||
m_transmit_buffer(0),
|
||||
m_receive_buffer(0),
|
||||
m_gpio_input(0),
|
||||
m_gpio_output(0xff)
|
||||
m_gpio_output(0xff),
|
||||
m_rframe(0),
|
||||
m_rclk(0),
|
||||
m_rbits(0),
|
||||
m_si_scan(0xff),
|
||||
m_next_rsr(0),
|
||||
m_rc(true),
|
||||
m_si(true),
|
||||
m_last_si(true),
|
||||
m_rparity(false),
|
||||
m_osr(0),
|
||||
m_tclk(0),
|
||||
m_tbits(0),
|
||||
m_tc(true),
|
||||
m_so(false),
|
||||
m_tparity(false),
|
||||
m_underrun(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -358,8 +393,6 @@ mc68901_device::mc68901_device(const machine_config &mconfig, const char *tag, d
|
||||
|
||||
void mc68901_device::device_start()
|
||||
{
|
||||
m_start_bit_hack_for_external_clocks = true;
|
||||
|
||||
/* resolve callbacks */
|
||||
m_out_irq_cb.resolve_safe();
|
||||
m_out_gpio_cb.resolve_safe();
|
||||
@ -378,16 +411,6 @@ void mc68901_device::device_start()
|
||||
m_timer[TIMER_C] = timer_alloc(TIMER_C);
|
||||
m_timer[TIMER_D] = timer_alloc(TIMER_D);
|
||||
|
||||
if (m_rx_clock > 0)
|
||||
{
|
||||
set_rcv_rate(m_rx_clock);
|
||||
}
|
||||
|
||||
if (m_tx_clock > 0)
|
||||
{
|
||||
set_tra_rate(m_tx_clock);
|
||||
}
|
||||
|
||||
/* register for state saving */
|
||||
save_item(NAME(m_gpip));
|
||||
save_item(NAME(m_aer));
|
||||
@ -405,17 +428,30 @@ void mc68901_device::device_start()
|
||||
save_item(NAME(m_to));
|
||||
save_item(NAME(m_ti));
|
||||
save_item(NAME(m_scr));
|
||||
save_item(NAME(m_scr_parity));
|
||||
save_item(NAME(m_ucr));
|
||||
save_item(NAME(m_rsr));
|
||||
save_item(NAME(m_tsr));
|
||||
save_item(NAME(m_transmit_buffer));
|
||||
save_item(NAME(m_transmit_pending));
|
||||
save_item(NAME(m_receive_buffer));
|
||||
save_item(NAME(m_overrun_pending));
|
||||
save_item(NAME(m_gpio_input));
|
||||
save_item(NAME(m_gpio_output));
|
||||
save_item(NAME(m_rsr_read));
|
||||
save_item(NAME(m_rframe));
|
||||
save_item(NAME(m_rclk));
|
||||
save_item(NAME(m_rbits));
|
||||
save_item(NAME(m_si_scan));
|
||||
save_item(NAME(m_next_rsr));
|
||||
save_item(NAME(m_rc));
|
||||
save_item(NAME(m_si));
|
||||
save_item(NAME(m_last_si));
|
||||
save_item(NAME(m_rparity));
|
||||
save_item(NAME(m_osr));
|
||||
save_item(NAME(m_tclk));
|
||||
save_item(NAME(m_tbits));
|
||||
save_item(NAME(m_tc));
|
||||
save_item(NAME(m_so));
|
||||
save_item(NAME(m_tparity));
|
||||
save_item(NAME(m_underrun));
|
||||
}
|
||||
|
||||
|
||||
@ -425,13 +461,16 @@ void mc68901_device::device_start()
|
||||
|
||||
void mc68901_device::device_reset()
|
||||
{
|
||||
m_tsr = 0;
|
||||
m_transmit_pending = false;
|
||||
m_overrun_pending = false;
|
||||
m_rsr = 0;
|
||||
m_tsr = TSR_BUFFER_EMPTY;
|
||||
m_underrun = false;
|
||||
m_rclk = 0;
|
||||
m_tclk = 0;
|
||||
|
||||
// Avoid read-before-write
|
||||
m_ipr = m_imr = 0;
|
||||
|
||||
m_rframe = 0x100;
|
||||
m_next_rsr = 0;
|
||||
|
||||
memset(m_tmc, 0, sizeof(m_tmc));
|
||||
@ -455,10 +494,8 @@ void mc68901_device::device_reset()
|
||||
write(REGISTER_TCDCR, 0);
|
||||
write(REGISTER_SCR, 0);
|
||||
write(REGISTER_UCR, 0);
|
||||
write(REGISTER_RSR, 0);
|
||||
|
||||
transmit_register_reset();
|
||||
receive_register_reset();
|
||||
set_so(true);
|
||||
}
|
||||
|
||||
|
||||
@ -474,84 +511,7 @@ void mc68901_device::device_timer(emu_timer &timer, device_timer_id id, int para
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// tra_callback -
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68901_device::tra_callback()
|
||||
{
|
||||
m_out_so_cb(transmit_register_get_data_bit());
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// tra_complete -
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68901_device::tra_complete()
|
||||
{
|
||||
if (m_tsr & TSR_XMIT_ENABLE)
|
||||
{
|
||||
if (m_transmit_pending)
|
||||
{
|
||||
transmit_register_setup(m_transmit_buffer);
|
||||
m_transmit_pending = false;
|
||||
m_tsr |= TSR_BUFFER_EMPTY;
|
||||
|
||||
if (m_ier & IR_XMIT_BUFFER_EMPTY)
|
||||
{
|
||||
take_interrupt(IR_XMIT_BUFFER_EMPTY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tsr |= TSR_UNDERRUN_ERROR;
|
||||
// TODO: transmit error?
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tsr |= TSR_END_OF_XMIT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// rcv_complete -
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68901_device::rcv_complete()
|
||||
{
|
||||
receive_register_extract();
|
||||
if (m_rsr & RSR_BUFFER_FULL)
|
||||
{
|
||||
m_overrun_pending = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_receive_buffer = get_received_char();
|
||||
m_rsr |= RSR_BUFFER_FULL;
|
||||
LOG("Received Character: %02x\n", m_receive_buffer);
|
||||
|
||||
if (is_receive_framing_error())
|
||||
m_rsr |= RSR_FRAME_ERROR;
|
||||
else
|
||||
m_rsr &= ~RSR_FRAME_ERROR;
|
||||
|
||||
if (is_receive_parity_error())
|
||||
m_rsr |= RSR_PARITY_ERROR;
|
||||
else
|
||||
m_rsr &= ~RSR_PARITY_ERROR;
|
||||
|
||||
if ((m_rsr & (RSR_FRAME_ERROR | RSR_PARITY_ERROR)) && (m_ier & IR_RCV_ERROR))
|
||||
rx_error();
|
||||
else
|
||||
rx_buffer_full();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// read -
|
||||
// read - read from one MFP register
|
||||
//-------------------------------------------------
|
||||
|
||||
u8 mc68901_device::read(offs_t offset)
|
||||
@ -595,7 +555,7 @@ u8 mc68901_device::read(offs_t offset)
|
||||
{
|
||||
/* clear UE bit (in reality, this won't be cleared until one full clock cycle of the transmitter has passed since the bit was set) */
|
||||
u8 tsr = m_tsr;
|
||||
if (!machine().side_effects_disabled())
|
||||
if (!machine().side_effects_disabled() && !m_underrun)
|
||||
m_tsr &= ~TSR_UNDERRUN_ERROR;
|
||||
return tsr;
|
||||
}
|
||||
@ -604,10 +564,15 @@ u8 mc68901_device::read(offs_t offset)
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
m_rsr &= ~RSR_BUFFER_FULL;
|
||||
if (m_overrun_pending)
|
||||
if (m_next_rsr != 0)
|
||||
{
|
||||
m_overrun_pending = false;
|
||||
m_rsr |= RSR_OVERRUN_ERROR;
|
||||
m_rsr |= m_next_rsr;
|
||||
m_next_rsr = 0;
|
||||
rx_error();
|
||||
}
|
||||
if ((m_rsr & RSR_BREAK) && BIT(m_rframe, 9))
|
||||
{
|
||||
m_rsr &= ~RSR_BREAK;
|
||||
rx_error();
|
||||
}
|
||||
}
|
||||
@ -620,7 +585,7 @@ u8 mc68901_device::read(offs_t offset)
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// write -
|
||||
// write - write to one MFP register
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68901_device::write(offs_t offset, u8 data)
|
||||
@ -917,6 +882,7 @@ void mc68901_device::write(offs_t offset, u8 data)
|
||||
LOG("MC68901 Sync Character : %x\n", data);
|
||||
|
||||
m_scr = data;
|
||||
m_scr_parity = BIT(population_count_32(data), 0);
|
||||
break;
|
||||
|
||||
case REGISTER_UCR:
|
||||
@ -931,60 +897,41 @@ void mc68901_device::write(offs_t offset, u8 data)
|
||||
case UCR_WORD_LENGTH_5: data_bit_count = 5; break;
|
||||
}
|
||||
|
||||
parity_t parity;
|
||||
|
||||
if (data & UCR_PARITY_ENABLED)
|
||||
{
|
||||
if (data & UCR_PARITY_EVEN)
|
||||
{
|
||||
LOG("MC68901 Parity : Even\n");
|
||||
|
||||
parity = PARITY_EVEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("MC68901 Parity : Odd\n");
|
||||
|
||||
parity = PARITY_ODD;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("MC68901 Parity : Disabled\n");
|
||||
|
||||
parity = PARITY_NONE;
|
||||
}
|
||||
|
||||
LOG("MC68901 Word Length : %u bits\n", data_bit_count);
|
||||
|
||||
|
||||
int start_bits;
|
||||
stop_bits_t stop_bits;
|
||||
|
||||
switch (data & 0x18)
|
||||
{
|
||||
case UCR_START_STOP_0_0:
|
||||
default:
|
||||
start_bits = 0;
|
||||
stop_bits = STOP_BITS_0;
|
||||
LOG("MC68901 Start Bits : 0, Stop Bits : 0, Format : synchronous\n");
|
||||
break;
|
||||
|
||||
case UCR_START_STOP_1_1:
|
||||
start_bits = 1;
|
||||
stop_bits = STOP_BITS_1;
|
||||
LOG("MC68901 Start Bits : 1, Stop Bits : 1, Format : asynchronous\n");
|
||||
break;
|
||||
|
||||
case UCR_START_STOP_1_15:
|
||||
start_bits = 1;
|
||||
stop_bits = STOP_BITS_1_5;
|
||||
LOG("MC68901 Start Bits : 1, Stop Bits : 1.5, Format : asynchronous\n");
|
||||
break;
|
||||
|
||||
case UCR_START_STOP_1_2:
|
||||
start_bits = 1;
|
||||
stop_bits = STOP_BITS_2;
|
||||
LOG("MC68901 Start Bits : 1, Stop Bits : 2, Format : asynchronous\n");
|
||||
break;
|
||||
}
|
||||
@ -998,9 +945,6 @@ void mc68901_device::write(offs_t offset, u8 data)
|
||||
LOG("MC68901 Rx/Tx Clock Divisor : 1\n");
|
||||
}
|
||||
|
||||
set_data_frame(start_bits, data_bit_count, parity, stop_bits);
|
||||
receive_register_reset();
|
||||
|
||||
m_ucr = data;
|
||||
}
|
||||
break;
|
||||
@ -1014,20 +958,32 @@ void mc68901_device::write(offs_t offset, u8 data)
|
||||
else
|
||||
{
|
||||
LOG("MC68901 Receiver Enabled\n");
|
||||
m_rsr |= RSR_RCV_ENABLE;
|
||||
|
||||
if (data & RSR_SYNC_STRIP_ENABLE)
|
||||
{
|
||||
LOG("MC68901 Sync Strip Enabled\n");
|
||||
m_rsr |= RSR_SYNC_STRIP_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("MC68901 Sync Strip Disabled\n");
|
||||
m_rsr &= ~RSR_SYNC_STRIP_ENABLE;
|
||||
}
|
||||
|
||||
if (data & RSR_FOUND_SEARCH)
|
||||
LOG("MC68901 Receiver Search Mode Enabled\n");
|
||||
|
||||
m_rsr = data & 0x0b;
|
||||
if ((m_ucr & UCR_START_STOP_1_2) == UCR_START_STOP_0_0)
|
||||
{
|
||||
if (data & RSR_FOUND_SEARCH)
|
||||
{
|
||||
LOG("MC68901 Receiver Search Mode Disabled\n");
|
||||
m_rsr |= RSR_FOUND_SEARCH;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("MC68901 Receiver Search Mode Disabled\n");
|
||||
m_rsr &= ~RSR_FOUND_SEARCH;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1036,12 +992,11 @@ void mc68901_device::write(offs_t offset, u8 data)
|
||||
|
||||
if ((data & TSR_XMIT_ENABLE) == 0)
|
||||
{
|
||||
LOG("MC68901 Transmitter Disabled\n");
|
||||
|
||||
m_tsr &= ~TSR_UNDERRUN_ERROR;
|
||||
m_underrun = false;
|
||||
|
||||
if (is_transmit_register_empty())
|
||||
m_tsr |= TSR_END_OF_XMIT;
|
||||
if (m_tbits == 0)
|
||||
set_so((m_tsr & TSR_OUTPUT_MASK) != TSR_OUTPUT_LOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1082,29 +1037,13 @@ void mc68901_device::write(offs_t offset, u8 data)
|
||||
}
|
||||
|
||||
m_tsr &= ~TSR_END_OF_XMIT;
|
||||
|
||||
if (m_transmit_pending && is_transmit_register_empty())
|
||||
{
|
||||
transmit_register_setup(m_transmit_buffer);
|
||||
m_transmit_pending = false;
|
||||
}
|
||||
if (!m_transmit_pending)
|
||||
m_tsr |= TSR_BUFFER_EMPTY;
|
||||
}
|
||||
break;
|
||||
|
||||
case REGISTER_UDR:
|
||||
LOG("MC68901 UDR %x\n", data);
|
||||
m_transmit_buffer = data;
|
||||
m_transmit_pending = true;
|
||||
m_tsr &= ~TSR_BUFFER_EMPTY;
|
||||
|
||||
if ((m_tsr & TSR_XMIT_ENABLE) && is_transmit_register_empty())
|
||||
{
|
||||
transmit_register_setup(m_transmit_buffer);
|
||||
m_transmit_pending = false;
|
||||
m_tsr |= TSR_BUFFER_EMPTY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1161,7 +1100,413 @@ WRITE_LINE_MEMBER( mc68901_device::tbi_w )
|
||||
timer_input(TIMER_B, state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(mc68901_device::write_rx)
|
||||
//**************************************************************************
|
||||
// USART
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// si_w - serial data input for receiver
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER(mc68901_device::si_w)
|
||||
{
|
||||
device_serial_interface::rx_w(state);
|
||||
m_si = state;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// rc_w - receiver clock input
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER(mc68901_device::rc_w)
|
||||
{
|
||||
if (state != m_rc)
|
||||
{
|
||||
// receiver active on rising edge
|
||||
m_rc = state;
|
||||
if (state && (m_rsr & RSR_RCV_ENABLE) && (m_tsr & TSR_OUTPUT_MASK) != TSR_OUTPUT_LOOP)
|
||||
rx_clock(m_si);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// tc_w - transmitter clock input
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER(mc68901_device::tc_w)
|
||||
{
|
||||
if (state != m_tc)
|
||||
{
|
||||
// transmitter active on falling edge
|
||||
m_tc = state;
|
||||
if (!state && ((m_tsr & TSR_XMIT_ENABLE) || !(m_tsr & TSR_END_OF_XMIT)))
|
||||
tx_clock();
|
||||
else if (state && (m_rsr & RSR_RCV_ENABLE) && (m_tsr & TSR_OUTPUT_MASK) == TSR_OUTPUT_LOOP)
|
||||
rx_clock(m_so);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_so - set serial output
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68901_device::set_so(bool state)
|
||||
{
|
||||
if (m_so != state)
|
||||
{
|
||||
m_so = state;
|
||||
m_out_so_cb(state);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// rx_frame_start - begin a new frame of received
|
||||
// data (following start bit for async mode)
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68901_device::rx_frame_start()
|
||||
{
|
||||
m_rframe = 0;
|
||||
m_rbits = (m_ucr & UCR_WORD_LENGTH_MASK) >> 5;
|
||||
m_rparity = (m_ucr & UCR_PARITY_EVEN) == UCR_PARITY_ODD;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// rx_sync_found - notify that a sync character
|
||||
// was found
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68901_device::rx_sync_found()
|
||||
{
|
||||
m_rsr |= RSR_FOUND_SEARCH;
|
||||
LOGMASKED(LOG_RCV, "USART sync character found (%02X)\n", m_scr);
|
||||
|
||||
// causes error interrupt, but does not fill receiver buffer
|
||||
rx_error();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// rx_async_frame_complete - finish receiving one
|
||||
// character in asynchronous mode
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68901_device::rx_async_frame_complete()
|
||||
{
|
||||
if (m_rsr & RSR_BUFFER_FULL)
|
||||
{
|
||||
LOGMASKED(LOG_RCV, "USART discarding received character %02X (%s)\n", m_rframe & 0xff, (m_rframe == 0 && !m_last_si) ? "break" : "overrun");
|
||||
m_next_rsr |= (m_rframe == 0 && !m_last_si) ? RSR_BREAK : RSR_OVERRUN_ERROR;
|
||||
}
|
||||
else if (m_rsr & RSR_OVERRUN_ERROR)
|
||||
{
|
||||
if (m_rframe == 0 && !m_last_si)
|
||||
m_rsr |= RSR_BREAK;
|
||||
}
|
||||
else
|
||||
{
|
||||
// load the receiver buffer
|
||||
m_receive_buffer = m_rframe & 0xff;
|
||||
m_rsr |= RSR_BUFFER_FULL;
|
||||
|
||||
// set error flags
|
||||
m_rsr &= ~(RSR_PARITY_ERROR | RSR_FRAME_ERROR | RSR_BREAK);
|
||||
if (m_rparity)
|
||||
m_rsr |= RSR_PARITY_ERROR;
|
||||
if (!m_last_si)
|
||||
m_rsr |= m_rframe == 0 ? RSR_BREAK : RSR_FRAME_ERROR;
|
||||
LOGMASKED(LOG_RCV, "USART received character: %02X (PE = %d, FE = %d, B = %d)\n", m_receive_buffer,
|
||||
m_rparity,
|
||||
!m_last_si && m_rframe != 0,
|
||||
!m_last_si && m_rframe == 0);
|
||||
|
||||
// set normal or error interrupt (if the latter is disabled, always use the former)
|
||||
if ((m_rparity || !m_last_si) && (m_ier & IR_RCV_ERROR))
|
||||
rx_error();
|
||||
else
|
||||
rx_buffer_full();
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// rx_sync_frame_complete - finish receiving one
|
||||
// character in synchronous mode (error flags are
|
||||
// different from asynchronous mode)
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68901_device::rx_sync_frame_complete()
|
||||
{
|
||||
// check if sync character matches
|
||||
bool match = (m_rframe & 0xff) == (m_scr & (0xff >> ((m_ucr & UCR_WORD_LENGTH_MASK) >> 5))) && !m_rparity;
|
||||
|
||||
// suppress sync characters if strip option set
|
||||
if (!match || !(m_rsr & RSR_SYNC_STRIP_ENABLE))
|
||||
{
|
||||
if (m_rsr & RSR_BUFFER_FULL)
|
||||
m_next_rsr |= RSR_OVERRUN_ERROR;
|
||||
else if (!(m_rsr & RSR_OVERRUN_ERROR))
|
||||
{
|
||||
// load the receiver buffer
|
||||
m_receive_buffer = m_rframe & 0xff;
|
||||
m_rsr |= RSR_BUFFER_FULL;
|
||||
|
||||
// set error flags
|
||||
m_rsr &= ~(RSR_FRAME_ERROR | RSR_PARITY_ERROR | RSR_MATCH);
|
||||
if (m_rparity)
|
||||
m_rsr |= RSR_PARITY_ERROR;
|
||||
if (match)
|
||||
m_rsr |= RSR_MATCH;
|
||||
LOGMASKED(LOG_RCV, "USART received character: %02X (PE = %d, sync %smatched)\n", m_receive_buffer,
|
||||
m_rparity,
|
||||
match ? "not " : "");
|
||||
|
||||
// set normal or error interrupt (if the latter is disabled, always use the former)
|
||||
if ((m_rparity || match) && (m_ier & IR_RCV_ERROR))
|
||||
rx_error();
|
||||
else
|
||||
rx_buffer_full();
|
||||
}
|
||||
}
|
||||
else
|
||||
LOGMASKED(LOG_RCV, "USART sync character stripped (%02X)\n", m_rframe & 0xff);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// rx_clock - process one active transition on
|
||||
// the receiver clock
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68901_device::rx_clock(bool si)
|
||||
{
|
||||
m_rclk++;
|
||||
if (m_rclk >= 244)
|
||||
m_rclk &= 15;
|
||||
m_si_scan = (m_si_scan >> 1) | (si ? 0x80 : 0);
|
||||
bool rclk_sync = (m_ucr & UCR_CLOCK_DIVIDE_16) == UCR_CLOCK_DIVIDE_1 || (m_rclk >= 4 && (m_si_scan & 0xe0) == (m_last_si ? 0 : 0xe0));
|
||||
bool sync_mode = (m_ucr & UCR_START_STOP_1_2) == UCR_START_STOP_0_0;
|
||||
if (rclk_sync)
|
||||
{
|
||||
LOGMASKED(LOG_RCV, "SI = %d (synchronized); RSR = %02X; rframe = %X; %d rbits, %d rclks\n", si, m_rsr, m_rframe, m_rbits, m_rclk);
|
||||
m_last_si = si;
|
||||
if (si && !sync_mode && !(m_rsr & RSR_CHAR_IN_PROGRESS))
|
||||
{
|
||||
m_rframe = 0x100;
|
||||
if (!(m_rsr & RSR_BUFFER_FULL) && (m_rsr & RSR_BREAK))
|
||||
{
|
||||
// valid 0 to 1 transition ends break condition
|
||||
m_rsr &= ~RSR_BREAK;
|
||||
rx_error();
|
||||
}
|
||||
}
|
||||
m_rclk = 0;
|
||||
}
|
||||
|
||||
if ((m_ucr & UCR_CLOCK_DIVIDE_16) == UCR_CLOCK_DIVIDE_1 || (m_rclk & 15) == 8)
|
||||
{
|
||||
if (sync_mode && !(m_rsr & RSR_FOUND_SEARCH))
|
||||
{
|
||||
// search mode: continuous comparison
|
||||
m_rframe = (m_rframe >> 1) | (m_last_si ? 0x100 : 0);
|
||||
if ((m_ucr & UCR_PARITY_ENABLED) && (m_ucr & UCR_WORD_LENGTH_MASK) == UCR_WORD_LENGTH_8)
|
||||
{
|
||||
// check calculated parity of 8-bit sync character
|
||||
if ((m_rframe & 0xff) == m_scr && m_last_si == ((m_ucr & UCR_PARITY_EVEN) ? m_scr_parity : !m_scr_parity))
|
||||
{
|
||||
rx_sync_found();
|
||||
rx_frame_start();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// parity, if any, must be included in SCR when words are less than 8 bits
|
||||
int frame_bits = ((m_ucr & UCR_PARITY_ENABLED) ? 9 : 8) - ((m_ucr & UCR_WORD_LENGTH_MASK) >> 5);
|
||||
if ((m_rframe >> (9 - frame_bits)) == (m_scr & ((1 << frame_bits) - 1)))
|
||||
{
|
||||
rx_sync_found();
|
||||
rx_frame_start();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sync_mode || (m_rsr & RSR_CHAR_IN_PROGRESS))
|
||||
{
|
||||
if (m_rbits > 8)
|
||||
{
|
||||
rx_async_frame_complete();
|
||||
m_rframe = m_last_si ? 0x100 : 0;
|
||||
m_rsr &= ~RSR_CHAR_IN_PROGRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGMASKED(LOG_RCV, "USART shifting in %d %s bit\n", m_last_si, m_rbits < 8 ? "data" : "parity");
|
||||
m_rframe = (m_rframe >> 1) | (m_last_si ? 0x100 : 0);
|
||||
if (m_last_si)
|
||||
m_rparity = !m_rparity;
|
||||
m_rbits++;
|
||||
|
||||
if (m_rbits == 8)
|
||||
{
|
||||
// adjust for fewer than 8 data bits
|
||||
m_rframe >>= (m_ucr & UCR_WORD_LENGTH_MASK) >> 5;
|
||||
|
||||
// adjust for no parity
|
||||
if (!(m_ucr & UCR_PARITY_ENABLED))
|
||||
{
|
||||
m_rframe >>= 1;
|
||||
m_rparity = false;
|
||||
m_rbits++;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_rbits > 8 && sync_mode)
|
||||
{
|
||||
rx_sync_frame_complete();
|
||||
|
||||
// one character follows another in sync mode
|
||||
rx_frame_start();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!m_last_si && BIT(m_rframe, 8))
|
||||
{
|
||||
// start bit valid
|
||||
LOGMASKED(LOG_RCV, "USART received start bit\n");
|
||||
m_rsr |= RSR_CHAR_IN_PROGRESS;
|
||||
rx_frame_start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// tx_frame_load - load one character into the
|
||||
// shift register for transmission
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68901_device::tx_frame_load(u8 data)
|
||||
{
|
||||
// set up output shift register
|
||||
m_osr = data;
|
||||
m_tbits = 9 - ((m_ucr & UCR_WORD_LENGTH_MASK) >> 5);
|
||||
m_tparity = (m_ucr & UCR_PARITY_EVEN) == UCR_PARITY_ODD;
|
||||
|
||||
// add start and stop bits for asynchronous mode
|
||||
if ((m_ucr & UCR_START_STOP_1_2) != UCR_START_STOP_0_0)
|
||||
{
|
||||
m_osr = (m_osr << 1) | (1 << m_tbits);
|
||||
m_tbits += 2;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// tx_clock - process one active edge on the
|
||||
// transmitter clock
|
||||
//-------------------------------------------------
|
||||
|
||||
void mc68901_device::tx_clock()
|
||||
{
|
||||
if (m_tclk != 0)
|
||||
{
|
||||
m_tclk--;
|
||||
return;
|
||||
}
|
||||
|
||||
m_underrun = false;
|
||||
|
||||
bool sync_mode = (m_ucr & UCR_START_STOP_1_2) == UCR_START_STOP_0_0;
|
||||
if (m_tbits == (sync_mode ? 2 : 3))
|
||||
{
|
||||
// inject the calculated parity or skip that bit
|
||||
if (m_ucr & UCR_PARITY_ENABLED)
|
||||
m_osr = (m_osr << 1) | m_tparity;
|
||||
else
|
||||
m_tbits--;
|
||||
}
|
||||
|
||||
bool send_break = !sync_mode && (m_tsr & TSR_BREAK);
|
||||
bool tbusy = false;
|
||||
if (m_tbits != 0)
|
||||
{
|
||||
m_tbits--;
|
||||
if (m_tbits != 0)
|
||||
tbusy = true;
|
||||
else if (!(m_tsr & TSR_XMIT_ENABLE))
|
||||
{
|
||||
LOGMASKED(LOG_XMIT, "USART transmitter disabled\n");
|
||||
|
||||
// transmitter is now effectively disabled
|
||||
m_tsr |= TSR_END_OF_XMIT;
|
||||
tx_error();
|
||||
|
||||
// automatic turnaround enables the receiver
|
||||
if (m_tsr & TSR_AUTO_TURNAROUND)
|
||||
m_rsr |= RSR_RCV_ENABLE;
|
||||
}
|
||||
else if ((m_tsr & TSR_BUFFER_EMPTY) && !(m_tsr & TSR_UNDERRUN_ERROR) && !send_break)
|
||||
{
|
||||
LOGMASKED(LOG_XMIT, "USART transmitter underrun\n");
|
||||
|
||||
// underrun error condition
|
||||
m_tsr |= TSR_UNDERRUN_ERROR;
|
||||
m_underrun = true;
|
||||
tx_error();
|
||||
}
|
||||
}
|
||||
|
||||
if (!tbusy && (m_tsr & TSR_XMIT_ENABLE))
|
||||
{
|
||||
// break inhibits reload
|
||||
if (!(m_tsr & TSR_BUFFER_EMPTY) && !send_break)
|
||||
{
|
||||
LOGMASKED(LOG_XMIT, "USART loading character (%02X)\n", m_transmit_buffer);
|
||||
|
||||
// empty buffer into shift register
|
||||
m_tsr |= TSR_BUFFER_EMPTY;
|
||||
tx_buffer_empty();
|
||||
tx_frame_load(m_transmit_buffer);
|
||||
tbusy = true;
|
||||
}
|
||||
else if (sync_mode)
|
||||
{
|
||||
LOGMASKED(LOG_XMIT, "USART loading sync character (%02X)\n", m_scr);
|
||||
|
||||
// transmit sync characters if nothing else is loaded
|
||||
tx_frame_load(m_scr);
|
||||
tbusy = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (tbusy)
|
||||
{
|
||||
LOGMASKED(LOG_XMIT, "USART shifting out %d %s bit\n", BIT(m_osr, 0),
|
||||
m_tbits == 1 && !sync_mode ? "stop" : m_tbits == (sync_mode ? 1 : 2) ? "parity" : "data or start");
|
||||
|
||||
// shift out one bit
|
||||
set_so(BIT(m_osr, 0));
|
||||
if (BIT(m_osr, 0))
|
||||
m_tparity = !m_tparity;
|
||||
m_osr >>= 1;
|
||||
|
||||
if (m_tbits == 1 && (m_ucr & UCR_START_STOP_1_2) >= UCR_START_STOP_1_15)
|
||||
{
|
||||
// 1½ or 2 stop bits selected
|
||||
if (m_ucr & UCR_CLOCK_DIVIDE_16)
|
||||
m_tclk = (m_ucr & UCR_START_STOP_1_2) == UCR_START_STOP_1_2 ? 31 : 23;
|
||||
else
|
||||
m_tclk = (m_ucr & UCR_START_STOP_1_2) == UCR_START_STOP_1_2 ? 1 : 0;
|
||||
}
|
||||
else if (m_ucr & UCR_CLOCK_DIVIDE_16)
|
||||
m_tclk = 15;
|
||||
}
|
||||
else if (!(m_tsr & TSR_XMIT_ENABLE))
|
||||
{
|
||||
// high/low output on SO (Hi-Z not supported)
|
||||
set_so((m_tsr & TSR_OUTPUT_MASK) != TSR_OUTPUT_LOW);
|
||||
}
|
||||
else if (send_break)
|
||||
{
|
||||
set_so(false);
|
||||
m_tbits = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// asynchronous marking condition
|
||||
set_so(true);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Curt Coder
|
||||
// copyright-holders:Curt Coder, AJR
|
||||
/**********************************************************************
|
||||
|
||||
Motorola MC68901 Multi Function Peripheral emulation
|
||||
@ -38,8 +38,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "diserial.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
@ -48,19 +46,14 @@
|
||||
|
||||
// ======================> mc68901_device
|
||||
|
||||
class mc68901_device : public device_t,
|
||||
public device_serial_interface
|
||||
class mc68901_device : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
mc68901_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
void set_timer_clock(int timer_clock) { m_timer_clock = timer_clock; }
|
||||
void set_rx_clock(int rx_clock) { m_rx_clock = rx_clock; }
|
||||
void set_tx_clock(int tx_clock) { m_tx_clock = tx_clock; }
|
||||
void set_timer_clock(const XTAL &xtal) { set_timer_clock(xtal.value()); }
|
||||
void set_rx_clock(const XTAL &xtal) { set_rx_clock(xtal.value()); }
|
||||
void set_tx_clock(const XTAL &xtal) { set_tx_clock(xtal.value()); }
|
||||
|
||||
auto out_irq_cb() { return m_out_irq_cb.bind(); }
|
||||
auto out_gpio_cb() { return m_out_gpio_cb.bind(); }
|
||||
@ -90,7 +83,9 @@ public:
|
||||
DECLARE_WRITE_LINE_MEMBER( tai_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( tbi_w );
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( write_rx );
|
||||
DECLARE_WRITE_LINE_MEMBER( si_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( rc_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( tc_w );
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
@ -98,13 +93,10 @@ protected:
|
||||
virtual void device_reset() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
// device_serial_interface overrides
|
||||
virtual void tra_callback() override;
|
||||
virtual void tra_complete() override;
|
||||
virtual void rcv_complete() override;
|
||||
|
||||
void check_interrupts();
|
||||
void take_interrupt(u16 mask);
|
||||
void tx_buffer_empty();
|
||||
void tx_error();
|
||||
void rx_buffer_full();
|
||||
void rx_error();
|
||||
void timer_count(int index);
|
||||
@ -112,6 +104,15 @@ protected:
|
||||
void gpio_input(int bit, int state);
|
||||
void gpio_output();
|
||||
|
||||
void set_so(bool state);
|
||||
void rx_frame_start();
|
||||
void rx_sync_found();
|
||||
void rx_async_frame_complete();
|
||||
void rx_sync_frame_complete();
|
||||
void rx_clock(bool si);
|
||||
void tx_frame_load(u8 data);
|
||||
void tx_clock();
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
@ -204,8 +205,6 @@ private:
|
||||
static const int PRESCALER[];
|
||||
|
||||
int m_timer_clock; /* timer clock */
|
||||
int m_rx_clock; /* serial receive clock */
|
||||
int m_tx_clock; /* serial transmit clock */
|
||||
|
||||
devcb_write_line m_out_irq_cb;
|
||||
|
||||
@ -239,13 +238,12 @@ private:
|
||||
u8 m_tdr[4]; // timer data registers
|
||||
|
||||
u8 m_scr; // synchronous character register
|
||||
bool m_scr_parity; // parity of sync character
|
||||
u8 m_ucr; // USART control register
|
||||
u8 m_tsr; // transmitter status register
|
||||
u8 m_rsr; // receiver status register
|
||||
u8 m_transmit_buffer; // USART data register
|
||||
bool m_transmit_pending;
|
||||
u8 m_receive_buffer;
|
||||
bool m_overrun_pending;
|
||||
u8 m_gpio_input;
|
||||
u8 m_gpio_output;
|
||||
|
||||
@ -254,9 +252,25 @@ private:
|
||||
int m_ti[4]; // timer in latch
|
||||
int m_to[4]; // timer out latch
|
||||
|
||||
// serial state
|
||||
// serial receiver state
|
||||
u16 m_rframe; // receiver frame shift register
|
||||
u8 m_rclk; // receiver clock counter
|
||||
u8 m_rbits; // receiver bit counter
|
||||
u8 m_si_scan; // receiver bitstream scan
|
||||
u8 m_next_rsr; // receiver status register latch
|
||||
int m_rsr_read; // receiver status register read flag
|
||||
bool m_rc; // receiver clock input
|
||||
bool m_si; // serial data input
|
||||
bool m_last_si; // synchronized serial data input
|
||||
bool m_rparity; // receiver data parity
|
||||
|
||||
// serial transmitter state
|
||||
u16 m_osr; // output shift register
|
||||
u8 m_tclk; // transmit clock counter
|
||||
u8 m_tbits; // transmit bit counter
|
||||
bool m_tc; // transmit clock input
|
||||
bool m_so; // serial data output
|
||||
bool m_tparity; // transmit data transmit
|
||||
bool m_underrun; // underrun preset time
|
||||
|
||||
// timers
|
||||
emu_timer *m_timer[4]; // counter timers
|
||||
|
@ -1780,11 +1780,6 @@ WRITE_LINE_MEMBER(st_state::write_acia_clock)
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER( st_state::mfp_tdo_w )
|
||||
{
|
||||
m_mfp->clock_w(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( st_state::fdc_drq_w )
|
||||
{
|
||||
if (state && (!(m_fdc_mode & DMA_MODE_ENABLED)) && (m_fdc_mode & DMA_MODE_FDC_HDC_ACK))
|
||||
@ -2019,14 +2014,13 @@ void st_state::common(machine_config &config)
|
||||
|
||||
MC68901(config, m_mfp, Y2/8);
|
||||
m_mfp->set_timer_clock(Y1);
|
||||
m_mfp->set_rx_clock(0);
|
||||
m_mfp->set_tx_clock(0);
|
||||
m_mfp->out_irq_cb().set_inputline(m_maincpu, M68K_IRQ_6);
|
||||
m_mfp->out_tdo_cb().set(FUNC(st_state::mfp_tdo_w));
|
||||
m_mfp->out_tdo_cb().set(m_mfp, FUNC(mc68901_device::tc_w));
|
||||
m_mfp->out_tdo_cb().append(m_mfp, FUNC(mc68901_device::rc_w));
|
||||
m_mfp->out_so_cb().set(m_rs232, FUNC(rs232_port_device::write_txd));
|
||||
|
||||
RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
|
||||
m_rs232->rxd_handler().set(m_mfp, FUNC(mc68901_device::write_rx));
|
||||
m_rs232->rxd_handler().set(m_mfp, FUNC(mc68901_device::si_w));
|
||||
m_rs232->dcd_handler().set(m_mfp, FUNC(mc68901_device::i1_w));
|
||||
m_rs232->cts_handler().set(m_mfp, FUNC(mc68901_device::i2_w));
|
||||
m_rs232->ri_handler().set(m_mfp, FUNC(mc68901_device::i6_w));
|
||||
@ -2224,10 +2218,9 @@ void stbook_state::stbook(machine_config &config)
|
||||
|
||||
MC68901(config, m_mfp, U517/8);
|
||||
m_mfp->set_timer_clock(Y1);
|
||||
m_mfp->set_rx_clock(0);
|
||||
m_mfp->set_tx_clock(0);
|
||||
m_mfp->out_irq_cb().set_inputline(M68000_TAG, M68K_IRQ_6);
|
||||
m_mfp->out_tdo_cb().set(FUNC(st_state::mfp_tdo_w));
|
||||
m_mfp->out_tdo_cb().set(m_mfp, FUNC(mc68901_device::tc_w));
|
||||
m_mfp->out_tdo_cb().append(m_mfp, FUNC(mc68901_device::rc_w));
|
||||
m_mfp->out_so_cb().set(RS232_TAG, FUNC(rs232_port_device::write_txd));
|
||||
|
||||
WD1772(config, m_fdc, U517/2);
|
||||
@ -2243,7 +2236,7 @@ void stbook_state::stbook(machine_config &config)
|
||||
m_centronics->set_output_latch(cent_data_out);
|
||||
|
||||
RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
|
||||
m_rs232->rxd_handler().set(m_mfp, FUNC(mc68901_device::write_rx));
|
||||
m_rs232->rxd_handler().set(m_mfp, FUNC(mc68901_device::si_w));
|
||||
m_rs232->dcd_handler().set(m_mfp, FUNC(mc68901_device::i1_w));
|
||||
m_rs232->cts_handler().set(m_mfp, FUNC(mc68901_device::i2_w));
|
||||
m_rs232->ri_handler().set(m_mfp, FUNC(mc68901_device::i6_w));
|
||||
|
@ -82,6 +82,17 @@ void harriet_state::machine_reset()
|
||||
}
|
||||
|
||||
|
||||
static const input_device_default terminal_defaults[] =
|
||||
{
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_19200 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_19200 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_STARTBITS", 0xff, RS232_STARTBITS_1 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
|
||||
{ nullptr, 0, 0 }
|
||||
};
|
||||
|
||||
void harriet_state::harriet(machine_config &config)
|
||||
{
|
||||
M68010(config, m_maincpu, 40_MHz_XTAL / 4); // MC68010FN10
|
||||
@ -91,11 +102,9 @@ void harriet_state::harriet(machine_config &config)
|
||||
|
||||
mc68901_device &mfp(MC68901(config, "mfp", 40_MHz_XTAL / 16));
|
||||
mfp.set_timer_clock(2.4576_MHz_XTAL);
|
||||
mfp.set_rx_clock(9600);
|
||||
mfp.set_tx_clock(9600);
|
||||
mfp.out_so_cb().set("rs232", FUNC(rs232_port_device::write_txd));
|
||||
//mfp.out_tco_cb().set("mfp", FUNC(mc68901_device::rc_w));
|
||||
//mfp.out_tdo_cb().set("mfp", FUNC(mc68901_device::tc_w));
|
||||
mfp.out_tco_cb().set("mfp", FUNC(mc68901_device::rc_w));
|
||||
mfp.out_tdo_cb().set("mfp", FUNC(mc68901_device::tc_w));
|
||||
|
||||
HD63450(config, "dmac", 40_MHz_XTAL / 4, "maincpu"); // MC68450R10 (or HD68450Y-10)
|
||||
|
||||
@ -103,8 +112,9 @@ void harriet_state::harriet(machine_config &config)
|
||||
NVRAM(config, "zpram", nvram_device::DEFAULT_ALL_0); // MK48Z02
|
||||
|
||||
rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "terminal"));
|
||||
rs232.rxd_handler().set("mfp", FUNC(mc68901_device::write_rx));
|
||||
rs232.rxd_handler().set("mfp", FUNC(mc68901_device::si_w));
|
||||
rs232.rxd_handler().append("mfp", FUNC(mc68901_device::tbi_w));
|
||||
rs232.set_option_device_input_defaults("terminal", terminal_defaults);
|
||||
|
||||
NSCSI_BUS(config, "scsia");
|
||||
NSCSI_CONNECTOR(config, "scsia:7").option_set("wdc", WD33C93A).clock(40_MHz_XTAL / 4);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Miodrag Milanovic
|
||||
// copyright-holders:Miodrag Milanovic, AJR
|
||||
/***************************************************************************
|
||||
|
||||
Indiana University 68030 board
|
||||
@ -15,7 +15,8 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "bus/rs232/keyboard.h"
|
||||
#include "bus/pc_kbd/keyboards.h"
|
||||
#include "bus/pc_kbd/pc_kbdc.h"
|
||||
#include "cpu/m68000/m68000.h"
|
||||
#include "bus/isa/com.h"
|
||||
#include "bus/isa/fdc.h"
|
||||
@ -24,17 +25,19 @@
|
||||
#include "bus/isa/isa_cards.h"
|
||||
#include "bus/isa/vga.h"
|
||||
#include "machine/mc68901.h"
|
||||
#include "sound/spkrdev.h"
|
||||
#include "speaker.h"
|
||||
|
||||
#define M68K_TAG "maincpu"
|
||||
#define ISABUS_TAG "isa"
|
||||
#define MFP_TAG "mfp"
|
||||
|
||||
class indiana_state : public driver_device
|
||||
{
|
||||
public:
|
||||
indiana_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag) ,
|
||||
m_maincpu(*this, M68K_TAG) { }
|
||||
m_maincpu(*this, "maincpu")
|
||||
{
|
||||
}
|
||||
|
||||
void indiana(machine_config &config);
|
||||
|
||||
@ -52,7 +55,7 @@ void indiana_state::indiana_mem(address_map &map)
|
||||
map.unmap_value_high();
|
||||
map(0x00000000, 0x0000ffff).mirror(0x7f800000).rom().region("user1", 0); // 64Kb of EPROM
|
||||
map(0x00100000, 0x00107fff).mirror(0x7f8f8000).ram(); // SRAM 32Kb of SRAM
|
||||
map(0x00200000, 0x002fffff).rw(MFP_TAG, FUNC(mc68901_device::read), FUNC(mc68901_device::write)).mirror(0x7f800000); // MFP
|
||||
map(0x00200000, 0x002fffff).rw("mfp", FUNC(mc68901_device::read), FUNC(mc68901_device::write)).mirror(0x7f800000); // MFP
|
||||
map(0x00400000, 0x004fffff).rw(ISABUS_TAG, FUNC(isa16_device::io16_swap_r), FUNC(isa16_device::io16_swap_w)).mirror(0x7f800000); // 16 bit PC IO
|
||||
map(0x00500000, 0x005fffff).rw(ISABUS_TAG, FUNC(isa16_device::mem16_swap_r), FUNC(isa16_device::mem16_swap_w)).mirror(0x7f800000); // 16 bit PC MEM
|
||||
map(0x00600000, 0x006fffff).rw(ISABUS_TAG, FUNC(isa16_device::io_r), FUNC(isa16_device::io_w)).mirror(0x7f800000); // 8 bit PC IO
|
||||
@ -86,38 +89,46 @@ void indiana_isa_cards(device_slot_interface &device)
|
||||
device.option_add("ide", ISA16_IDE);
|
||||
}
|
||||
|
||||
static DEVICE_INPUT_DEFAULTS_START( keyboard )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_1200 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_STARTBITS", 0xff, RS232_STARTBITS_1 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
|
||||
DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
|
||||
DEVICE_INPUT_DEFAULTS_END
|
||||
|
||||
void indiana_state::indiana(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
M68030(config, m_maincpu, XTAL(16'000'000));
|
||||
M68030(config, m_maincpu, 16_MHz_XTAL);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &indiana_state::indiana_mem);
|
||||
|
||||
// FIXME: determine ISA bus clock
|
||||
isa16_device &isa(ISA16(config, ISABUS_TAG, 0));
|
||||
isa16_device &isa(ISA16(config, ISABUS_TAG, 16_MHz_XTAL / 2)); // OSC = CLK = CLK8
|
||||
isa.set_custom_spaces();
|
||||
isa.irq3_callback().set_inputline(m_maincpu, M68K_IRQ_5);
|
||||
isa.irq4_callback().set_inputline(m_maincpu, M68K_IRQ_4);
|
||||
isa.irq5_callback().set_inputline(m_maincpu, M68K_IRQ_3);
|
||||
isa.irq6_callback().set_inputline(m_maincpu, M68K_IRQ_2);
|
||||
isa.irq7_callback().set_inputline(m_maincpu, M68K_IRQ_1);
|
||||
isa.irq2_callback().set("mfp", FUNC(mc68901_device::i7_w)); // IRQ9
|
||||
isa.irq10_callback().set("mfp", FUNC(mc68901_device::i6_w));
|
||||
isa.irq11_callback().set("mfp", FUNC(mc68901_device::i5_w));
|
||||
isa.irq12_callback().set("mfp", FUNC(mc68901_device::i4_w));
|
||||
isa.irq14_callback().set("mfp", FUNC(mc68901_device::i3_w));
|
||||
isa.irq15_callback().set("mfp", FUNC(mc68901_device::i2_w));
|
||||
|
||||
ISA16_SLOT(config, "isa1", 0, ISABUS_TAG, indiana_isa_cards, "vga", false);
|
||||
ISA16_SLOT(config, "isa2", 0, ISABUS_TAG, indiana_isa_cards, "fdc_at", false);
|
||||
ISA16_SLOT(config, "isa3", 0, ISABUS_TAG, indiana_isa_cards, "comat", false);
|
||||
ISA16_SLOT(config, "isa4", 0, ISABUS_TAG, indiana_isa_cards, "ide", false);
|
||||
|
||||
mc68901_device &mfp(MC68901(config, MFP_TAG, XTAL(16'000'000)/4));
|
||||
mfp.set_timer_clock(XTAL(16'000'000)/4);
|
||||
mfp.set_rx_clock(0);
|
||||
mfp.set_tx_clock(0);
|
||||
mfp.out_so_cb().set("keyboard", FUNC(rs232_port_device::write_txd));
|
||||
pc_kbdc_device &pc_kbdc(PC_KBDC(config, "pc_kbdc", 0));
|
||||
pc_kbdc.out_data_cb().set("mfp", FUNC(mc68901_device::i0_w));
|
||||
pc_kbdc.out_data_cb().append("mfp", FUNC(mc68901_device::si_w));
|
||||
pc_kbdc.out_clock_cb().set("mfp", FUNC(mc68901_device::i1_w));
|
||||
pc_kbdc.out_clock_cb().append("mfp", FUNC(mc68901_device::rc_w));
|
||||
|
||||
rs232_port_device &keyboard(RS232_PORT(config, "keyboard", default_rs232_devices, "keyboard"));
|
||||
keyboard.rxd_handler().set(MFP_TAG, FUNC(mc68901_device::write_rx));
|
||||
keyboard.set_option_device_input_defaults("keyboard", DEVICE_INPUT_DEFAULTS_NAME(keyboard));
|
||||
PC_KBDC_SLOT(config, "kbd", pc_at_keyboards, STR_KBD_IBM_PC_AT_84).set_pc_kbdc_slot(subdevice("pc_kbdc"));
|
||||
|
||||
mc68901_device &mfp(MC68901(config, "mfp", 16_MHz_XTAL / 4));
|
||||
mfp.set_timer_clock(16_MHz_XTAL / 16);
|
||||
mfp.out_irq_cb().set_inputline(m_maincpu, M68K_IRQ_6);
|
||||
mfp.out_tdo_cb().set("speaker", FUNC(speaker_sound_device::level_w));
|
||||
|
||||
SPEAKER(config, "mono").front_center();
|
||||
SPEAKER_SOUND(config, "speaker").add_route(ALL_OUTPUTS, "mono", 0.50);
|
||||
}
|
||||
|
||||
/* ROM definition */
|
||||
|
@ -346,11 +346,9 @@ void micro3d_state::micro3d(machine_config &config)
|
||||
|
||||
mc68901_device &mfp(MC68901(config, "mfp", 4000000));
|
||||
mfp.set_timer_clock(4000000);
|
||||
mfp.set_rx_clock(0);
|
||||
mfp.set_tx_clock(0);
|
||||
mfp.out_irq_cb().set_inputline("maincpu", M68K_IRQ_4);
|
||||
//mfp.out_tao_cb().set("mfp", FUNC(mc68901_device::rc_w));
|
||||
//mfp.out_tao_cb().append("mfp", FUNC(mc68901_device::tc_w));
|
||||
mfp.out_tao_cb().set("mfp", FUNC(mc68901_device::rc_w));
|
||||
mfp.out_tao_cb().append("mfp", FUNC(mc68901_device::tc_w));
|
||||
mfp.out_tco_cb().set("mfp", FUNC(mc68901_device::tbi_w));
|
||||
|
||||
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
|
||||
|
@ -157,9 +157,9 @@ void tti_state::tti(machine_config &config)
|
||||
m_maincpu->set_addrmap(m68008_device::AS_CPU_SPACE, &tti_state::fc7_map);
|
||||
|
||||
MC68901(config, m_mfp, 20_MHz_XTAL / 2); // guess
|
||||
m_mfp->set_timer_clock(20_MHz_XTAL / 2); // guess
|
||||
m_mfp->set_rx_clock(9600); // for testing (FIXME: actually 16x)
|
||||
m_mfp->set_tx_clock(9600); // for testing (FIXME: actually 16x)
|
||||
m_mfp->set_timer_clock(2'457'600); // guess
|
||||
m_mfp->out_tco_cb().set(m_mfp, FUNC(mc68901_device::rc_w));
|
||||
m_mfp->out_tdo_cb().set(m_mfp, FUNC(mc68901_device::tc_w));
|
||||
m_mfp->out_so_cb().set("rs232", FUNC(rs232_port_device::write_txd));
|
||||
m_mfp->out_irq_cb().set_inputline("maincpu", M68K_IRQ_2); // probably
|
||||
|
||||
@ -174,7 +174,7 @@ void tti_state::tti(machine_config &config)
|
||||
NSCSI_CONNECTOR(config, "scsibus:7", tti_scsi_devices, "asc", true).set_option_machine_config("asc", [this] (device_t *device) { asc_config(device); });
|
||||
|
||||
rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "terminal"));
|
||||
rs232.rxd_handler().set(m_mfp, FUNC(mc68901_device::write_rx));
|
||||
rs232.rxd_handler().set(m_mfp, FUNC(mc68901_device::si_w));
|
||||
|
||||
EEPROM_X24C44_16BIT(config, "novram").do_callback().set("mfp", FUNC(mc68901_device::i0_w));
|
||||
|
||||
|
@ -1630,14 +1630,13 @@ void x68k_state::x68000_base(machine_config &config)
|
||||
/* device hardware */
|
||||
MC68901(config, m_mfpdev, 16_MHz_XTAL / 4);
|
||||
m_mfpdev->set_timer_clock(16_MHz_XTAL / 4);
|
||||
m_mfpdev->set_rx_clock(0);
|
||||
m_mfpdev->set_tx_clock(0);
|
||||
m_mfpdev->out_irq_cb().set(FUNC(x68k_state::mfp_irq_callback));
|
||||
m_mfpdev->out_tbo_cb().set(m_mfpdev, FUNC(mc68901_device::clock_w));
|
||||
m_mfpdev->out_tbo_cb().set(m_mfpdev, FUNC(mc68901_device::tc_w));
|
||||
m_mfpdev->out_tbo_cb().append(m_mfpdev, FUNC(mc68901_device::rc_w));
|
||||
m_mfpdev->out_so_cb().set("keyboard", FUNC(rs232_port_device::write_txd));
|
||||
|
||||
rs232_port_device &keyboard(RS232_PORT(config, "keyboard", keyboard_devices, "x68k"));
|
||||
keyboard.rxd_handler().set(m_mfpdev, FUNC(mc68901_device::write_rx));
|
||||
keyboard.rxd_handler().set(m_mfpdev, FUNC(mc68901_device::si_w));
|
||||
|
||||
I8255A(config, m_ppi, 0);
|
||||
m_ppi->in_pa_callback().set(FUNC(x68k_state::ppi_port_a_r));
|
||||
|
@ -238,9 +238,6 @@ public:
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( ikbd_tx_w );
|
||||
|
||||
DECLARE_READ8_MEMBER( mfp_gpio_r );
|
||||
DECLARE_WRITE_LINE_MEMBER( mfp_tdo_w );
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( write_acia_clock );
|
||||
|
||||
void toggle_dma_fifo();
|
||||
|
@ -276,7 +276,7 @@ void x68k_keyboard_device::device_reset()
|
||||
buffered_rs232_device::device_reset();
|
||||
|
||||
set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1);
|
||||
set_rate(38'400); // TODO: Should be 2400 but MC68901 doesn't support divide by 16
|
||||
set_rate(2400);
|
||||
receive_register_reset();
|
||||
transmit_register_reset();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user