mcs51: implement serial input/output as bit stream (#11190)

* fix [MT#05495](https://mametesters.org/view.php?id=5495)
This commit is contained in:
Patrick Mackinlay 2023-05-08 16:16:50 +07:00 committed by GitHub
parent 8dbba0b525
commit 743ac098e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 489 additions and 570 deletions

View File

@ -134,9 +134,13 @@
#include "mcs51.h"
#include "mcs51dasm.h"
#define VERBOSE 0
#define LOG_RX (1U << 1)
#define LOG_TX (1U << 2)
#define VERBOSE (0)
#include "logmacro.h"
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
/***************************************************************************
CONSTANTS
@ -223,6 +227,22 @@ enum
V_PFI = 0x02b /* Power Failure Interrupt */
};
enum serial_state : u8
{
SIO_IDLE,
SIO_START_LE,
SIO_START,
SIO_DATA0,
SIO_DATA1,
SIO_DATA2,
SIO_DATA3,
SIO_DATA4,
SIO_DATA5,
SIO_DATA6,
SIO_DATA7,
SIO_DATA8,
SIO_STOP,
};
DEFINE_DEVICE_TYPE(I8031, i8031_device, "i8031", "Intel 8031")
DEFINE_DEVICE_TYPE(I8032, i8032_device, "i8032", "Intel 8032")
@ -281,8 +301,6 @@ mcs51_cpu_device::mcs51_cpu_device(const machine_config &mconfig, device_type ty
, m_scratchpad(*this, "scratchpad")
, m_port_in_cb(*this)
, m_port_out_cb(*this)
, m_serial_tx_cb(*this)
, m_serial_rx_cb(*this)
, m_rtemp(0)
{
m_ds5002fp.mcon = 0;
@ -797,7 +815,7 @@ void mcs51_cpu_device::clear_current_irq()
m_cur_irq_prio = 0;
else
m_cur_irq_prio = -1;
LOG(("New: %d %02x\n", m_cur_irq_prio, m_irq_active));
LOG("New: %d %02x\n", m_cur_irq_prio, m_irq_active);
}
uint8_t mcs51_cpu_device::r_acc() { return SFR_A(ADDR_ACC); }
@ -997,19 +1015,65 @@ void mcs51_cpu_device::do_sub_flags(uint8_t a, uint8_t data, uint8_t c)
SET_OV((result1 < -128 || result1 > 127));
}
void mcs51_cpu_device::transmit(bool state)
{
if (BIT(SFR_A(ADDR_P3), 1) != state)
{
if (state)
SFR_A(ADDR_P3) |= 1U << 1;
else
SFR_A(ADDR_P3) &= ~(1U << 1);
m_port_out_cb[3](SFR_A(ADDR_P3));
}
}
void mcs51_cpu_device::transmit_receive(int source)
{
int mode = (GET_SM0<<1) | GET_SM1;
if (source == 1) /* timer1 */
m_uart.smod_div = (m_uart.smod_div + 1) & (2-GET_SMOD);
m_uart.smod_div = (m_uart.smod_div + 1) & (1-GET_SMOD);
switch(mode) {
//8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12
// 8 bit shifter - rate set by clock freq / 12
case 0:
m_uart.rx_clk += (source == 0) ? 16 : 0; /* clock / 12 */
m_uart.tx_clk += (source == 0) ? 16 : 0; /* clock / 12 */
break;
if (source == 0)
{
// TODO: mode 0 serial input is unemulated
// FIXME: output timing is highly simplified and incorrect
switch (m_uart.txbit)
{
case SIO_IDLE:
break;
case SIO_START:
SFR_A(ADDR_P3) |= 0x03;
m_port_out_cb[3](SFR_A(ADDR_P3));
m_uart.txbit = SIO_DATA0;
break;
case SIO_DATA0: case SIO_DATA1: case SIO_DATA2: case SIO_DATA3:
case SIO_DATA4: case SIO_DATA5: case SIO_DATA6: case SIO_DATA7:
SFR_A(ADDR_P3) &= ~0x03;
if (BIT(m_uart.data_out, m_uart.txbit - SIO_DATA0))
SFR_A(ADDR_P3) |= 1U << 0;
m_port_out_cb[3](SFR_A(ADDR_P3));
if (m_uart.txbit == SIO_DATA7)
{
SET_TI(1);
m_uart.txbit = SIO_STOP;
}
else
m_uart.txbit++;
break;
case SIO_STOP:
SFR_A(ADDR_P3) |= 0x03;
m_port_out_cb[3](SFR_A(ADDR_P3));
m_uart.txbit = SIO_IDLE;
break;
}
}
return;
//8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2
case 1:
case 3:
@ -1030,39 +1094,139 @@ void mcs51_cpu_device::transmit_receive(int source)
m_uart.tx_clk += (source == 0) ? (GET_SMOD ? 6 : 3) : 0; /* clock / 12 */
break;
}
/* transmit ? */
// transmit
if (m_uart.tx_clk >= 16)
{
m_uart.tx_clk &= 0x0f;
if(m_uart.bits_to_send)
{
m_uart.bits_to_send--;
if(m_uart.bits_to_send == 0) {
//Call the callback function
m_serial_tx_cb(0, m_uart.data_out, 0xff);
//Set Interrupt Flag
SET_TI(1);
}
}
switch (m_uart.txbit)
{
case SIO_IDLE:
transmit(1);
break;
case SIO_START:
LOGMASKED(LOG_TX, "tx start bit (%s)\n", machine().time().to_string());
transmit(0);
m_uart.txbit = SIO_DATA0;
break;
case SIO_DATA0: case SIO_DATA1: case SIO_DATA2: case SIO_DATA3:
case SIO_DATA4: case SIO_DATA5: case SIO_DATA6: case SIO_DATA7:
LOGMASKED(LOG_TX, "tx bit %d data %d (%s)\n", m_uart.txbit - SIO_DATA0, BIT(m_uart.data_out, m_uart.txbit - SIO_DATA0), machine().time().to_string());
transmit(BIT(m_uart.data_out, m_uart.txbit - SIO_DATA0));
// mode 1 has no data8/parity bit
if (mode == 1 && m_uart.txbit == SIO_DATA7)
m_uart.txbit = SIO_STOP;
else
m_uart.txbit++;
break;
case SIO_DATA8: // data8/parity bit
LOGMASKED(LOG_TX, "tx bit %d data %d (%s)\n", m_uart.txbit - SIO_DATA0, GET_TB8, machine().time().to_string());
transmit(GET_TB8);
m_uart.txbit = SIO_STOP;
break;
case SIO_STOP:
LOGMASKED(LOG_TX, "tx stop bit (%s)\n", machine().time().to_string());
transmit(1);
SET_TI(1);
m_uart.txbit = SIO_IDLE;
break;
}
}
/* receive */
if (m_uart.rx_clk >= 16)
// receive
if (m_uart.rx_clk >= 16 || m_uart.rxbit < SIO_START)
{
m_uart.rx_clk &= 0x0f;
if (m_uart.delay_cycles>0)
if (GET_REN)
{
m_uart.delay_cycles--;
if (m_uart.delay_cycles == 0)
// directly read RXD input
bool const data = BIT(m_port_in_cb[3](), 0);
switch (m_uart.rxbit)
{
int data = 0;
//Call our callball function to retrieve the data
data = m_serial_rx_cb(0, 0xff);
LOG(("RX Deliver %d\n", data));
SET_SBUF(data);
//Flag the IRQ
SET_RI(1);
SET_RB8(1); // HACK force 2nd stop bit
case SIO_IDLE:
if (data)
m_uart.rxbit = SIO_START_LE;
break;
case SIO_START_LE: // start bit leading edge
if (!data)
{
LOGMASKED(LOG_RX, "rx start leading edge (%s)\n", machine().time().to_string());
m_uart.rxbit = SIO_START;
m_uart.rx_clk = 8;
}
break;
case SIO_START:
if (!data)
{
LOGMASKED(LOG_RX, "rx start bit (%s)\n", machine().time().to_string());
m_uart.data_in = 0;
m_uart.rxbit = SIO_DATA0;
}
else
// false start bit
m_uart.rxbit = SIO_START_LE;
break;
case SIO_DATA0: case SIO_DATA1: case SIO_DATA2: case SIO_DATA3:
case SIO_DATA4: case SIO_DATA5: case SIO_DATA6: case SIO_DATA7:
LOGMASKED(LOG_RX, "rx bit %d data %d (%s)\n", m_uart.rxbit - SIO_DATA0, data, machine().time().to_string());
if (data)
m_uart.data_in |= 1U << (m_uart.rxbit - SIO_DATA0);
// mode 1 has no data8/parity bit
if (mode == 1 && m_uart.rxbit == SIO_DATA7)
m_uart.rxbit = SIO_STOP;
else
m_uart.rxbit++;
break;
case SIO_DATA8: // data8/parity bit
LOGMASKED(LOG_RX, "rx bit %d data %d (%s)\n", m_uart.rxbit - SIO_DATA0, data, machine().time().to_string());
m_uart.rxb8 = data;
m_uart.rxbit = SIO_STOP;
break;
case SIO_STOP:
if (!GET_RI)
{
switch (mode)
{
case 1:
LOGMASKED(LOG_RX, "rx byte 0x%02x stop %d (%s)\n", m_uart.data_in, data, machine().time().to_string());
SET_SBUF(m_uart.data_in);
if (!GET_SM2)
{
// RB8 contains stop bit
SET_RB8(data);
SET_RI(1);
}
else if (data)
// RI if valid stop bit
SET_RI(1);
break;
case 2:
case 3:
LOGMASKED(LOG_RX, "rx byte 0x%02x RB8 %d stop %d (%s)\n", m_uart.data_in, m_uart.rxb8, data, machine().time().to_string());
SET_SBUF(m_uart.data_in);
SET_RB8(m_uart.rxb8);
// no RI if SM2 && !RB8
if (!GET_SM2 || GET_RB8)
SET_RI(1);
break;
}
}
else
LOGMASKED(LOG_RX, "rx overrun discarding data 0x%02x\n", m_uart.data_in);
// next state depends on stop bit validity
if (data)
m_uart.rxbit = SIO_START_LE;
else
m_uart.rxbit = SIO_IDLE;
break;
}
}
}
@ -1325,56 +1489,6 @@ void mcs51_cpu_device::update_timers(int cycles)
}
}
//Set up to transmit data out of serial port
//NOTE: Enable Serial Port Interrupt bit is NOT required to send/receive data!
void mcs51_cpu_device::serial_transmit(uint8_t data)
{
int mode = (GET_SM0<<1) | GET_SM1;
//Flag that we're sending data
m_uart.data_out = data;
LOG(("serial_transmit: %x %x\n", mode, data));
switch(mode) {
//8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12
case 0:
m_uart.bits_to_send = 8+2;
break;
//8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2
case 1:
m_uart.bits_to_send = 8+2;
break;
//9 bit uart
case 2:
case 3:
m_uart.bits_to_send = 8+3;
break;
}
}
void mcs51_cpu_device::serial_receive()
{
int mode = (GET_SM0<<1) | GET_SM1;
if (GET_REN) {
switch(mode) {
//8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12
case 0:
m_uart.delay_cycles = 8+2;
break;
//8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2
case 1:
m_uart.delay_cycles = 8+2;
break;
//9 bit uart
case 2:
case 3:
m_uart.delay_cycles = 8+3;
break;
}
}
}
/* Check and update status of serial port */
void mcs51_cpu_device::update_serial(int cycles)
{
@ -1819,10 +1933,10 @@ void mcs51_cpu_device::check_irqs()
/* Skip the interrupt request if currently processing interrupt
* and the new request does not have a higher priority
*/
LOG(("Request: %d\n", priority_request));
LOG("Request: %d\n", priority_request);
if (m_irq_active && (priority_request <= m_cur_irq_prio))
{
LOG(("higher or equal priority irq (%u) in progress already, skipping ...\n", m_cur_irq_prio));
LOG("higher or equal priority irq (%u) in progress already, skipping ...\n", m_cur_irq_prio);
return;
}
@ -1853,7 +1967,7 @@ void mcs51_cpu_device::check_irqs()
m_cur_irq_prio = priority_request;
m_irq_active |= (1 << priority_request);
LOG(("Take: %d %02x\n", m_cur_irq_prio, m_irq_active));
LOG("Take: %d %02x\n", m_cur_irq_prio, m_irq_active);
//Clear any interrupt flags that should be cleared since we're servicing the irq!
switch(int_vec) {
@ -1994,14 +2108,6 @@ void mcs51_cpu_device::execute_set_input(int irqline, int state)
fatalerror("mcs51: Trying to set T2EX_LINE on a non I8052 type cpu.\n");
break;
case MCS51_RX_LINE: /* Serial Port Receive */
/* Is the enable flags for this interrupt set? */
if (state != CLEAR_LINE)
{
serial_receive();
}
break;
/* Power Fail Interrupt */
case DS5002FP_PFI_LINE:
if (m_features & FEATURE_DS5002FP)
@ -2099,12 +2205,14 @@ void mcs51_cpu_device::sfr_write(size_t offset, uint8_t data)
case ADDR_P1: m_port_out_cb[1](data); break;
case ADDR_P2: m_port_out_cb[2](data); break;
case ADDR_P3: m_port_out_cb[3](data); break;
case ADDR_SBUF: serial_transmit(data); break;
case ADDR_SBUF:
LOGMASKED(LOG_TX, "tx byte 0x%02x\n", data);
m_uart.data_out = data;
m_uart.txbit = SIO_START;
break;
case ADDR_PSW: SET_PARITY(); break;
case ADDR_ACC: SET_PARITY(); break;
case ADDR_IP: update_irq_prio(data, 0); break;
/* R_SBUF = data; //This register is used only for "Receiving data coming in!" */
case ADDR_B:
case ADDR_SP:
case ADDR_DPL:
@ -2117,10 +2225,18 @@ void mcs51_cpu_device::sfr_write(size_t offset, uint8_t data)
case ADDR_TL1:
case ADDR_TH0:
case ADDR_TH1:
break;
case ADDR_SCON:
if (!GET_REN && BIT(data, 4))
{
LOGMASKED(LOG_RX, "rx enabled SCON 0x%02x\n", data);
if (!BIT(data, 6, 2))
logerror("mode 0 serial input is not emulated\n");
m_uart.rxbit = SIO_IDLE;
}
break;
default:
LOG(("mcs51 '%s': attemping to write to an invalid/non-implemented SFR address: %x at 0x%04x, data=%x\n", tag(), (uint32_t)offset,PC,data));
LOG("attemping to write to an invalid/non-implemented SFR address: %x at 0x%04x, data=%x\n", (uint32_t)offset,PC,data);
/* no write in this case according to manual */
return;
}
@ -2162,7 +2278,7 @@ uint8_t mcs51_cpu_device::sfr_read(size_t offset)
return m_data.read_byte((size_t) offset | 0x100);
/* Illegal or non-implemented sfr */
default:
LOG(("mcs51 '%s': attemping to read an invalid/non-implemented SFR address: %x at 0x%04x\n", tag(), (uint32_t)offset,PC));
LOG("attemping to read an invalid/non-implemented SFR address: %x at 0x%04x\n", (uint32_t)offset,PC);
/* according to the manual, the read may return random bits */
return 0xff;
}
@ -2177,8 +2293,6 @@ void mcs51_cpu_device::device_start()
m_port_in_cb.resolve_all_safe(0xff);
m_port_out_cb.resolve_all_safe();
m_serial_rx_cb.resolve_safe(0);
m_serial_tx_cb.resolve_safe();
/* Save states */
save_item(NAME(m_ppc));
@ -2200,11 +2314,10 @@ void mcs51_cpu_device::device_start()
save_item(NAME(m_ds5002fp.rnr_delay) );
save_item(NAME(m_ds5002fp.range) );
save_item(NAME(m_uart.data_out));
save_item(NAME(m_uart.bits_to_send));
save_item(NAME(m_uart.data_in));
save_item(NAME(m_uart.smod_div));
save_item(NAME(m_uart.rx_clk));
save_item(NAME(m_uart.tx_clk));
save_item(NAME(m_uart.delay_cycles));
state_add( MCS51_PC, "PC", m_pc).formatstr("%04X");
state_add( MCS51_SP, "SP", SP).formatstr("%02X");
@ -2346,10 +2459,11 @@ void mcs51_cpu_device::device_reset()
}
m_uart.data_out = 0;
m_uart.data_in = 0;
m_uart.rx_clk = 0;
m_uart.tx_clk = 0;
m_uart.bits_to_send = 0;
m_uart.delay_cycles = 0;
m_uart.txbit = SIO_IDLE;
m_uart.rxbit = SIO_IDLE;
m_uart.smod_div = 0;
m_recalc_parity = 0;
@ -2441,8 +2555,8 @@ uint8_t i80c52_device::sfr_read(size_t offset)
****************************************************************************/
#define DS5_LOGW(a, d) LOG(("ds5002fp '%s': write to " # a " register at 0x%04x, data=%x\n", tag(), PC, d))
#define DS5_LOGR(a, d) LOG(("ds5002fp '%s': read from " # a " register at 0x%04x\n", tag(), PC))
#define DS5_LOGW(a, d) LOG("write to " # a " register at 0x%04x, data=%x\n", PC, d)
#define DS5_LOGR(a, d) LOG("read from " # a " register at 0x%04x\n", PC)
uint8_t mcs51_cpu_device::ds5002fp_protected(size_t offset, uint8_t data, uint8_t ta_mask, uint8_t mask)
{
@ -2467,7 +2581,7 @@ void ds5002fp_device::sfr_write(size_t offset, uint8_t data)
if ((data == 0xaa) && (m_ds5002fp.ta_window == 0))
{
m_ds5002fp.ta_window = 6; /* 4*12 + 2*12 */
LOG(("ds5002fp '%s': TA window initiated at 0x%04x\n", tag(), PC));
LOG("TA window initiated at 0x%04x\n", PC);
}
break;
case ADDR_MCON: data = ds5002fp_protected(ADDR_MCON, data, 0x0f, 0xf7); DS5_LOGW(MCON, data); break;

View File

@ -44,8 +44,7 @@ enum
{
MCS51_INT0_LINE = 0, /* P3.2: External Interrupt 0 */
MCS51_INT1_LINE, /* P3.3: External Interrupt 1 */
MCS51_RX_LINE, /* P3.0: Serial Port Receive Line */
MCS51_T0_LINE, /* P3,4: Timer 0 External Input */
MCS51_T0_LINE, /* P3.4: Timer 0 External Input */
MCS51_T1_LINE, /* P3.5: Timer 1 External Input */
MCS51_T2_LINE, /* P1.0: Timer 2 External Input */
MCS51_T2EX_LINE, /* P1.1: Timer 2 Capture Reload Trigger */
@ -64,8 +63,6 @@ public:
template <unsigned N> auto port_in_cb() { return m_port_in_cb[N].bind(); }
template <unsigned N> auto port_out_cb() { return m_port_out_cb[N].bind(); }
auto serial_rx_cb() { return m_serial_rx_cb.bind(); }
auto serial_tx_cb() { return m_serial_tx_cb.bind(); }
void program_internal(address_map &map);
void data_internal(address_map &map);
@ -132,12 +129,14 @@ protected:
struct mcs51_uart
{
uint8_t data_out; //Data to send out
uint8_t bits_to_send; //How many bits left to send when transmitting out the serial port
uint8_t data_in;
uint8_t txbit;
uint8_t rxbit;
bool rxb8;
int smod_div; /* signal divided by 2^SMOD */
int rx_clk; /* rx clock */
int tx_clk; /* tx clock */
uint8_t delay_cycles; //Gross Hack;
} m_uart; /* internal uart */
/* Internal Ram */
@ -148,6 +147,8 @@ protected:
virtual void sfr_write(size_t offset, uint8_t data);
virtual uint8_t sfr_read(size_t offset);
void transmit(bool state);
/* Memory spaces */
memory_access<16, 0, 0, ENDIANNESS_LITTLE>::cache m_program;
memory_access< 9, 0, 0, ENDIANNESS_LITTLE>::specific m_data;
@ -156,10 +157,6 @@ protected:
devcb_read8::array<4> m_port_in_cb;
devcb_write8::array<4> m_port_out_cb;
/* Serial Port TX/RX Callbacks */
devcb_write8 m_serial_tx_cb; //Call back function when sending data out of serial port
devcb_read8 m_serial_rx_cb; //Call back function to retrieve data when receiving serial port data
/* DS5002FP */
struct {
uint8_t previous_ta; /* Previous Timed Access value */
@ -197,9 +194,7 @@ protected:
void update_timer_t1(int cycles);
void update_timer_t2(int cycles);
void update_timers(int cycles);
void serial_transmit(uint8_t data);
void serial_receive();
void update_serial(int cycles);
void update_serial(int source);
void update_irq_prio(uint8_t ipl, uint8_t iph);
void execute_op(uint8_t op);
void check_irqs();

View File

@ -978,5 +978,5 @@ OPHANDLER( xrl_a_r )
//illegal opcodes
OPHANDLER( illegal )
{
LOG(("i8051 '%s': illegal opcode at 0x%03x: %02x\n", tag(), PC-1, r));
LOG("illegal opcode at 0x%03x: %02x\n", PC-1, r);
}

View File

@ -232,7 +232,6 @@ ioport_constructor archimedes_keyboard_device::device_input_ports() const
archimedes_keyboard_device::archimedes_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, ARCHIMEDES_KEYBOARD, tag, owner, clock)
, device_serial_interface(mconfig, *this)
, m_mcu(*this, "mcu")
, m_kout(*this)
, m_keyboard(*this, "ROW.%u", 0U)
@ -250,10 +249,6 @@ void archimedes_keyboard_device::device_resolve_objects()
void archimedes_keyboard_device::device_start()
{
// KART interface
set_data_frame(1, 8, PARITY_NONE, STOP_BITS_2);
set_rate(31250);
m_mouse_timer = timer_alloc(FUNC(archimedes_keyboard_device::update_mouse), this);
save_item(NAME(m_mouse_x));
@ -265,6 +260,7 @@ void archimedes_keyboard_device::device_start()
save_item(NAME(m_mouse_yref));
save_item(NAME(m_mouse_ydir));
save_item(NAME(m_mux));
save_item(NAME(m_kin));
}
//-------------------------------------------------
@ -282,9 +278,7 @@ void archimedes_keyboard_device::device_reset()
m_mouse_yref = 1;
m_mouse_ydir = 1;
m_mux = 0;
transmit_register_reset();
receive_register_reset();
m_kin = false;
m_mouse_timer->adjust(attotime::from_hz(1000 * 4), 0, attotime::from_hz(1000 * 4));
}
@ -299,11 +293,9 @@ void archimedes_keyboard_device::device_add_mconfig(machine_config &config)
m_mcu->port_in_cb<0>().set([this]() { return m_keyboard[m_mux]->read() & 0xff; });
m_mcu->port_in_cb<1>().set([this]() { return (m_keyboard[m_mux]->read() >> 8) & 0xff; });
m_mcu->port_in_cb<2>().set(FUNC(archimedes_keyboard_device::mouse_r));
m_mcu->port_in_cb<3>().set([this]() { return m_mouse[2]->read() & 0xff; });
m_mcu->port_in_cb<3>().set([this]() { return (m_mouse[2]->read() & 0xfe) | m_kin; });
m_mcu->port_out_cb<2>().set([this](uint8_t data) { m_mux = data & 0x0f; });
m_mcu->port_out_cb<3>().set(FUNC(archimedes_keyboard_device::leds_w));
m_mcu->serial_rx_cb().set([this]() { return get_received_char(); });
m_mcu->serial_tx_cb().set(FUNC(archimedes_keyboard_device::tx_w));
}
//-------------------------------------------------
@ -321,22 +313,6 @@ const tiny_rom_entry *archimedes_keyboard_device::device_rom_region() const
return ROM_NAME( archimedes_keyboard );
}
void archimedes_keyboard_device::tra_complete()
{
}
void archimedes_keyboard_device::rcv_complete()
{
receive_register_extract();
m_mcu->set_input_line(MCS51_RX_LINE, ASSERT_LINE);
m_mcu->set_input_line(MCS51_RX_LINE, CLEAR_LINE);
}
void archimedes_keyboard_device::tra_callback()
{
m_kout(transmit_register_get_data_bit());
}
TIMER_CALLBACK_MEMBER(archimedes_keyboard_device::update_mouse)
{
// Mouse quadrature signals
@ -418,10 +394,12 @@ TIMER_CALLBACK_MEMBER(archimedes_keyboard_device::update_mouse)
void archimedes_keyboard_device::leds_w(uint8_t data)
{
// Keyboard LEDs
// --- --x- TXD
// --- -x-- Caps Lock
// --- x--- Scroll Lock
// --x ---- Num Lock
m_kout(BIT(data, 1));
for (int i = 0; i < 3; i++)
m_leds[i] = BIT(data, 2 + i);
}
@ -431,8 +409,7 @@ uint8_t archimedes_keyboard_device::mouse_r()
return (m_mouse_xref << 4) | (m_mouse_xdir << 5) | (m_mouse_yref << 6) | (m_mouse_ydir << 7);
}
void archimedes_keyboard_device::tx_w(uint8_t data)
WRITE_LINE_MEMBER(archimedes_keyboard_device::kin_w)
{
if (is_transmit_register_empty())
transmit_register_setup(data);
m_kin = state;
}

View File

@ -13,15 +13,13 @@
#include "cpu/mcs51/mcs51.h"
#include "diserial.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> archimedes_keyboard_device
class archimedes_keyboard_device : public device_t, public device_serial_interface
class archimedes_keyboard_device : public device_t
{
public:
// construction/destruction
@ -29,7 +27,7 @@ public:
auto kout() { return m_kout.bind(); }
DECLARE_WRITE_LINE_MEMBER(kin_w) { rx_w(state); }
DECLARE_WRITE_LINE_MEMBER(kin_w);
protected:
// device-level overrides
@ -42,15 +40,9 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
// device_serial_interface overrides
virtual void tra_callback() override;
virtual void tra_complete() override;
virtual void rcv_complete() override;
TIMER_CALLBACK_MEMBER(update_mouse);
private:
void tx_w(uint8_t data);
uint8_t mouse_r();
void leds_w(uint8_t data);
@ -70,6 +62,7 @@ private:
int16_t m_mouse_x;
int16_t m_mouse_y;
uint8_t m_mux;
bool m_kin;
};

View File

@ -175,7 +175,6 @@ qs1000_device::qs1000_device(const machine_config &mconfig, const char *tag, dev
m_out_p1_cb(*this),
m_out_p2_cb(*this),
m_out_p3_cb(*this),
//m_serial_w_cb(*this),
m_stream(nullptr),
m_cpu(*this, "cpu")
{
@ -207,7 +206,6 @@ void qs1000_device::device_add_mconfig(machine_config &config)
m_cpu->port_out_cb<2>().set(FUNC(qs1000_device::p2_w));
m_cpu->port_in_cb<3>().set(FUNC(qs1000_device::p3_r));
m_cpu->port_out_cb<3>().set(FUNC(qs1000_device::p3_w));
m_cpu->serial_rx_cb().set(FUNC(qs1000_device::data_to_i8052));
}
@ -241,9 +239,6 @@ void qs1000_device::device_start()
m_out_p2_cb.resolve_safe();
m_out_p3_cb.resolve_safe();
//m_serial_w_cb.resolve_safe();
save_item(NAME(m_serial_data_in));
save_item(NAME(m_wave_regs));
for (int i = 0; i < QS1000_CHANNELS; i++)
@ -267,19 +262,6 @@ void qs1000_device::device_start()
}
//-------------------------------------------------
// serial_in - send data to the chip
//-------------------------------------------------
void qs1000_device::serial_in(uint8_t data)
{
m_serial_data_in = data;
// Signal to the CPU that data is available
m_cpu->set_input_line(MCS51_RX_LINE, ASSERT_LINE);
m_cpu->set_input_line(MCS51_RX_LINE, CLEAR_LINE);
}
//-------------------------------------------------
// set_irq - interrupt the internal CPU
//-------------------------------------------------
@ -290,16 +272,6 @@ void qs1000_device::set_irq(int state)
}
//-------------------------------------------------
// data_to_i8052 - called by the 8052 core to
// receive serial data
//-------------------------------------------------
uint8_t qs1000_device::data_to_i8052()
{
return m_serial_data_in;
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------

View File

@ -40,11 +40,9 @@ public:
auto p1_out() { return m_out_p1_cb.bind(); }
auto p2_out() { return m_out_p2_cb.bind(); }
auto p3_out() { return m_out_p3_cb.bind(); }
//auto serial_w() { return m_serial_w_cb.bind(); }
// external
i8052_device &cpu() const { return *m_cpu; }
void serial_in(uint8_t data);
void set_irq(int state);
void wave_w(offs_t offset, uint8_t data);
@ -101,14 +99,11 @@ private:
devcb_write8 m_out_p2_cb;
devcb_write8 m_out_p3_cb;
//devcb_write8 m_serial_w_cb;
// Internal state
sound_stream * m_stream;
required_device<i8052_device> m_cpu;
// Wavetable engine
uint8_t m_serial_data_in;
uint8_t m_wave_regs[18];
struct qs1000_channel
@ -129,8 +124,6 @@ private:
};
qs1000_channel m_channels[QS1000_CHANNELS];
uint8_t data_to_i8052();
};

View File

@ -311,6 +311,7 @@ void device_serial_interface::receive_register_extract()
data &= ~(0xff<<m_df_word_length);
m_rcv_byte_received = data;
LOGMASKED(LOG_RX, "Receive data 0x%02x\n", m_rcv_byte_received);
if(m_df_parity == PARITY_NONE)
return;
@ -436,7 +437,7 @@ u8 device_serial_interface::transmit_register_get_data_bit()
bit = (m_tra_register_data>>(m_tra_bit_count-1-m_tra_bit_count_transmitted))&1;
if (m_tra_bit_count_transmitted < m_df_start_bit_count)
LOGMASKED(LOG_TX, "Transmitting start bit as %d (%s)\n", m_tra_bit_count_transmitted, bit, device().machine().time().to_string());
LOGMASKED(LOG_TX, "Transmitting start bit %d as %d (%s)\n", m_tra_bit_count_transmitted, bit, device().machine().time().to_string());
else
LOGMASKED(LOG_TX, "Transmitting bit %d as %d (%s)\n", m_tra_bit_count_transmitted - m_df_start_bit_count, bit, device().machine().time().to_string());
m_tra_bit_count_transmitted++;

View File

@ -133,6 +133,7 @@ Notes:
#include "machine/arm_iomd.h"
#include "machine/i2cmem.h"
#include "sound/qs1000.h"
#include "diserial.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
@ -140,11 +141,12 @@ Notes:
namespace {
class ssfindo_state : public driver_device
class ssfindo_state : public driver_device, public device_serial_interface
{
public:
ssfindo_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, device_serial_interface(mconfig, *this)
, m_maincpu(*this, "maincpu")
, m_vidc(*this, "vidc")
, m_iomd(*this, "iomd")
@ -178,6 +180,7 @@ protected:
bool m_i2cmem_clock = false;
virtual void tra_callback() override;
void sound_w(uint8_t data);
private:
@ -209,6 +212,8 @@ private:
uint8_t iolines_r();
void iolines_w(uint8_t data);
bool m_flash_bank_select = false;
bool m_txd = true;
};
class tetfight_state : public ssfindo_state
@ -371,7 +376,7 @@ uint32_t ssfindo_state::randomized_r()
void ssfindo_state::sound_w(uint8_t data)
{
m_qs1000->serial_in(data);
transmit_register_setup(data);
m_maincpu->spin_until_time(attotime::from_usec(2000)); // give time to the QS1000 CPU to react. TODO: sync things correctly
}
@ -441,11 +446,23 @@ void ssfindo_state::machine_start()
save_item(NAME(m_flashN));
save_item(NAME(m_i2cmem_clock));
save_item(NAME(m_flash_bank_select));
set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1);
set_rate(31250);
}
void ssfindo_state::machine_reset()
{
// ...
receive_register_reset();
transmit_register_reset();
m_txd = true;
}
void ssfindo_state::tra_callback()
{
m_txd = transmit_register_get_data_bit();
}
static INPUT_PORTS_START( ssfindo )
@ -616,6 +633,7 @@ void ssfindo_state::ssfindo(machine_config &config)
qs1000_device &qs1000(QS1000(config, "qs1000", 24_MHz_XTAL));
qs1000.set_external_rom(true);
// qs1000.p1_out().set(FUNC()); // TODO: writes something here
qs1000.p3_in().set([this]() { return u8(0xfeU | m_txd); });
qs1000.add_route(0, "lspeaker", 0.25);
qs1000.add_route(1, "rspeaker", 0.25);
}

View File

@ -153,9 +153,10 @@ private:
void eolith_vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t eolith_vram_r(offs_t offset);
void sound_p1_w(uint8_t data);
void sound_p3_w(uint8_t data);
uint8_t qs1000_p1_r();
void qs1000_p1_w(uint8_t data);
void soundcpu_to_qs1000(uint8_t data);
uint8_t qs1000_p3_r();
uint32_t screen_update_eolith(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
@ -176,6 +177,7 @@ private:
int m_coin_counter_bit = 0;
std::unique_ptr<uint16_t[]> m_vram;
int m_buffer = 0;
uint8_t m_sound_txd = 0;
};
@ -315,6 +317,11 @@ void eolith_state::sound_p1_w(uint8_t data)
m_sndbank->set_entry(data & 0x0f);
}
void eolith_state::sound_p3_w(uint8_t data)
{
// Sound CPU -> QS1000 CPU serial link
m_sound_txd = BIT(data, 1);
}
/*************************************
*
@ -352,10 +359,9 @@ void eolith_state::qs1000_p1_w(uint8_t data)
*
*************************************/
void eolith_state::soundcpu_to_qs1000(uint8_t data)
uint8_t eolith_state::qs1000_p3_r()
{
m_qs1000->serial_in(data);
machine().scheduler().perfect_quantum(attotime::from_usec(250));
return m_sound_txd;
}
@ -693,7 +699,8 @@ void eolith_state::eolith45(machine_config &config)
m_soundcpu->set_addrmap(AS_PROGRAM, &eolith_state::sound_prg_map);
m_soundcpu->set_addrmap(AS_IO, &eolith_state::sound_io_map);
m_soundcpu->port_out_cb<1>().set(FUNC(eolith_state::sound_p1_w));
m_soundcpu->serial_tx_cb().set(FUNC(eolith_state::soundcpu_to_qs1000)); // Sound CPU -> QS1000 CPU serial link
m_soundcpu->port_out_cb<3>().set(FUNC(eolith_state::sound_p3_w));
config.set_perfect_quantum(m_soundcpu); // HACK: ensure serial sync between Sound CPU and QS1000
EEPROM_93C66_8BIT(config, "eeprom")
.erase_time(attotime::from_usec(250))
@ -724,6 +731,7 @@ void eolith_state::eolith45(machine_config &config)
m_qs1000->set_external_rom(true);
m_qs1000->p1_in().set(FUNC(eolith_state::qs1000_p1_r));
m_qs1000->p1_out().set(FUNC(eolith_state::qs1000_p1_w));
m_qs1000->p3_in().set(FUNC(eolith_state::qs1000_p3_r));
m_qs1000->add_route(0, "lspeaker", 1.0);
m_qs1000->add_route(1, "rspeaker", 1.0);
}

View File

@ -200,7 +200,6 @@ protected:
u8 m_mcu_p1;
u8 m_mcu_p2;
u8 m_mcu_p3;
u8 m_mcu_uart;
u8 m_ppi_pa;
u8 m_ppi_pb;
@ -223,7 +222,6 @@ void rtpc_state::machine_start()
m_mcu_p1 = 0;
m_mcu_p2 = 0;
m_mcu_p3 = 0;
m_mcu_uart = 0;
m_ppi_pa = 0;
m_ppi_pb = 0;
@ -375,6 +373,15 @@ void rtpc_state::mcu_port3_w(u8 data)
// 6 o kbd data out
// 7 o kbd clock out
// uart txd -> rxd wrap
if (BIT(m_kls_cmd, 5))
{
if (BIT(data, 1))
m_mcu_p3 |= 1;
else
m_mcu_p3 &= ~1;
}
m_kbd_con->data_write_from_mb(BIT(data, 6));
m_kbd_con->clock_write_from_mb(BIT(data, 7));
@ -578,18 +585,6 @@ void rtpc_state::common(machine_config &config)
m_mcu->port_out_cb<2>().set(FUNC(rtpc_state::mcu_port2_w));
m_mcu->port_in_cb<3>().set([this]() { return m_mcu_p3 | 0xce; });
m_mcu->port_out_cb<3>().set(FUNC(rtpc_state::mcu_port3_w));
m_mcu->serial_tx_cb().set(
[this](u8 data)
{
if (BIT(m_kls_cmd, 5))
{
m_mcu_uart = data;
m_mcu->set_input_line(MCS51_RX_LINE, 1);
}
else
LOGMASKED(LOG_KLS, "kls uart tx 0x%02x\n", data);
});
m_mcu->serial_rx_cb().set([this]() { return m_mcu_uart; });
TIMER(config, "mcu_timer").configure_periodic(FUNC(rtpc_state::mcu_timer), attotime::from_hz(32768));

View File

@ -14,17 +14,6 @@ BASIC-31 (and variants) as found on the below url, are homebrews.
https://web.archive.org/web/20110908004037/http://dsaprojects.110mb.com/electronics/8031-ah/8031-bas.html
The driver is working, however there are issues with the cpu serial code.
When started, you are supposed to press Space and the system works out
the baud rate and boots up.
However, the way the cpu is written, it actually passes bytes around, so
the auto-speed detection doesn't work as intended. Also the cpu interface
is horribly outdated and needs to be brought up to date.
The optional eprom presents the ability to bypass the auto-speed problems.
Once the system starts, all input must be in uppercase. Read the manual
to discover the special features of this Basic.
@ -36,7 +25,8 @@ Sound: BASIC-31 has sound, and BASIC-52 doesn't. The sound command is PWM.
#include "emu.h"
#include "cpu/mcs51/mcs51.h"
#include "machine/i8255.h"
#include "machine/terminal.h"
#include "bus/rs232/terminal.h"
#include "bus/rs232/rs232.h"
#include "sound/spkrdev.h"
#include "speaker.h"
@ -49,7 +39,7 @@ public:
basic52_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_terminal(*this, "terminal")
, m_serial(*this, "serial")
, m_speaker(*this, "speaker")
{ }
@ -58,15 +48,15 @@ public:
private:
void machine_start() override;
void kbd_put(u8 data);
void port1_w(u8 data);
uint8_t unk_r();
uint8_t from_term();
uint8_t port3_r();
void port3_w(u8 data);
void rx_w(int state);
void io_map(address_map &map);
void mem_map(address_map &map);
uint8_t m_term_data = 0U;
uint8_t m_port3 = 0U;
required_device<mcs51_cpu_device> m_maincpu;
required_device<generic_terminal_device> m_terminal;
required_device<rs232_port_device> m_serial;
required_device<speaker_sound_device> m_speaker;
};
@ -82,9 +72,6 @@ void basic52_state::io_map(address_map &map)
map.unmap_value_high();
map(0x0000, 0x7fff).ram();
// 8000-9FFF is reserved for a plug-in EPROM containing BASIC programs.
// We have used this to preset the baud rate and skip the unreliable auto-detect.
map(0x8000, 0x8000).lr8(NAME([] () { return 0x31; })); // we will be manually setting the baud rate
map(0x8001, 0x8002).lr8(NAME([] () { return 0xFE; })); // to the fastest possible
map(0xa000, 0xa003).rw("ppi8255", FUNC(i8255_device::read), FUNC(i8255_device::write)); // PPI-8255
}
@ -93,14 +80,9 @@ static INPUT_PORTS_START( basic52 )
INPUT_PORTS_END
uint8_t basic52_state::from_term()
uint8_t basic52_state::port3_r()
{
return m_term_data;
}
uint8_t basic52_state::unk_r()
{
return m_term_data; // won't boot without this
return m_port3;
}
void basic52_state::port1_w(u8 data)
@ -108,17 +90,30 @@ void basic52_state::port1_w(u8 data)
m_speaker->level_w(BIT(data, 2));
}
void basic52_state::kbd_put(u8 data)
void basic52_state::port3_w(u8 data)
{
m_maincpu->set_input_line(MCS51_RX_LINE, ASSERT_LINE);
m_maincpu->set_input_line(MCS51_RX_LINE, CLEAR_LINE);
m_term_data = data;
// preserve RXD
m_port3 = (m_port3 & 1) | (data & ~1);
m_serial->write_txd(BIT(data, 1));
}
void basic52_state::rx_w(int state)
{
if (state)
m_port3 |= 1;
else
m_port3 &= ~1;
}
void basic52_state::machine_start()
{
save_item(NAME(m_term_data));
save_item(NAME(m_port3));
}
static void serial_devices(device_slot_interface &device)
{
device.option_add("terminal", SERIAL_TERMINAL);
}
void basic52_state::basic31(machine_config &config)
@ -128,13 +123,11 @@ void basic52_state::basic31(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &basic52_state::mem_map);
m_maincpu->set_addrmap(AS_IO, &basic52_state::io_map);
m_maincpu->port_out_cb<1>().set(FUNC(basic52_state::port1_w));
m_maincpu->port_in_cb<3>().set(FUNC(basic52_state::unk_r));
m_maincpu->serial_tx_cb().set(m_terminal, FUNC(generic_terminal_device::write));
m_maincpu->serial_rx_cb().set(FUNC(basic52_state::from_term));
m_maincpu->port_out_cb<3>().set(FUNC(basic52_state::port3_w));
m_maincpu->port_in_cb<3>().set(FUNC(basic52_state::port3_r));
/* video hardware */
GENERIC_TERMINAL(config, m_terminal, 0);
m_terminal->set_keyboard_callback(FUNC(basic52_state::kbd_put));
RS232_PORT(config, m_serial, serial_devices, "terminal");
m_serial->rxd_handler().set(FUNC(basic52_state::rx_w));
I8255(config, "ppi8255", 0);
@ -150,9 +143,8 @@ void basic52_state::basic52(machine_config &config)
I8052(config.replace(), m_maincpu, XTAL(11'059'200));
m_maincpu->set_addrmap(AS_PROGRAM, &basic52_state::mem_map);
m_maincpu->set_addrmap(AS_IO, &basic52_state::io_map);
m_maincpu->port_in_cb<3>().set(FUNC(basic52_state::unk_r));
m_maincpu->serial_tx_cb().set(m_terminal, FUNC(generic_terminal_device::write));
m_maincpu->serial_rx_cb().set(FUNC(basic52_state::from_term));
m_maincpu->port_out_cb<3>().set(FUNC(basic52_state::port3_w));
m_maincpu->port_in_cb<3>().set(FUNC(basic52_state::port3_r));
}
/* ROM definition */

View File

@ -117,10 +117,6 @@ private:
void unk_ffa9_w(uint8_t data);
void tx(uint8_t data);
uint8_t rx();
uint8_t port0_r();
void port0_w(u8 data);
uint8_t port1_r();
@ -520,28 +516,9 @@ uint32_t leapfrog_iquest_state::screen_update(screen_device &screen, bitmap_rgb3
return 0;
}
// never triggered?
void leapfrog_iquest_state::tx(uint8_t data)
{
logerror("%s: transmitting %02x\n", machine().describe_context().c_str(), data);
}
// never triggered?
uint8_t leapfrog_iquest_state::rx()
{
logerror("%s: receiving\n", machine().describe_context().c_str());
return machine().rand();
}
// doesn't help?
WRITE_LINE_MEMBER(leapfrog_iquest_state::rx_line_hack)
{
/*
m_maincpu->set_input_line(MCS51_RX_LINE, ASSERT_LINE);
m_maincpu->set_input_line(MCS51_RX_LINE, CLEAR_LINE);
*/
if (0)
{
// HACK: force past the wait loop if we're treating ff80 - ffff as RAM
@ -605,8 +582,6 @@ void leapfrog_iquest_state::leapfrog_base(machine_config &config)
I8032(config, m_maincpu, 96000000/10); // unknown clock
m_maincpu->set_addrmap(AS_PROGRAM, &leapfrog_iquest_state::prog_map);
m_maincpu->set_addrmap(AS_IO, &leapfrog_iquest_state::ext_map);
m_maincpu->serial_tx_cb().set(FUNC(leapfrog_iquest_state::tx));
m_maincpu->serial_rx_cb().set(FUNC(leapfrog_iquest_state::rx));
m_maincpu->port_in_cb<0>().set(FUNC(leapfrog_iquest_state::port0_r));
m_maincpu->port_out_cb<0>().set(FUNC(leapfrog_iquest_state::port0_w));
m_maincpu->port_in_cb<1>().set(FUNC(leapfrog_iquest_state::port1_r));

View File

@ -234,8 +234,6 @@ private:
void write_odd(uint16_t data);
uint16_t read_odd();
void vsync_int_ctrl(uint16_t data);
uint8_t mcu_r(offs_t offset);
void mcu_w(offs_t offset, uint8_t data);
uint8_t b_read();
void b_writ(uint8_t data);
void strobe_w(uint8_t data);
@ -243,14 +241,13 @@ private:
uint8_t kbd_r();
uint32_t screen_update_maygayv1(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER(screen_vblank_maygayv1);
void data_from_i8031(uint8_t data);
uint8_t data_to_i8031();
uint8_t sound_p1_r();
void sound_p1_w(uint8_t data);
uint8_t sound_p3_r();
void sound_p3_w(uint8_t data);
DECLARE_WRITE_LINE_MEMBER(duart_irq_handler);
DECLARE_WRITE_LINE_MEMBER(duart_txa);
void main_map(address_map &map);
void sound_data(address_map &map);
void sound_io(address_map &map);
void sound_prg(address_map &map);
void cpu_space_map(address_map &map);
required_device<cpu_device> m_maincpu;
@ -273,7 +270,6 @@ private:
int m_vsync_latch_preset = 0;
uint8_t m_p1 = 0;
uint8_t m_p3 = 0;
int m_d68681_val = 0;
i82716_t m_i82716;
output_finder<8 * 256> m_lamp;
};
@ -616,59 +612,34 @@ void maygayv1_state::main_map(address_map &map)
*/
uint8_t maygayv1_state::mcu_r(offs_t offset)
uint8_t maygayv1_state::sound_p1_r()
{
switch (offset)
{
case 1:
{
if ( !BIT(m_p3, 4) )
return (ioport("REEL")->read()); // Reels???
else
return 0;
}
case 3: return m_upd7759->busy_r() ? 0 : 0x08;
}
return 0;
if (!BIT(m_p3, 4))
return (ioport("REEL")->read()); // Reels???
else
return m_p1;
}
void maygayv1_state::mcu_w(offs_t offset, uint8_t data)
void maygayv1_state::sound_p1_w(uint8_t data)
{
logerror("O %x D %x",offset,data);
m_p1 = data;
switch (offset)
{
// Bottom nibble = UPD
case 1:
m_p1 = data;
// m_upd7759->msg_w(data);//?
break;
case 3:
m_upd7759->reset_w (BIT(data, 2));
m_upd7759->start_w(BIT(data, 6));
// if ( !BIT(m_p3, 7) && BIT(data, 7) )
// P1 propagates to outputs
m_p3 = data;
break;
}
m_upd7759->port_w(data);//?
}
void maygayv1_state::sound_prg(address_map &map)
uint8_t maygayv1_state::sound_p3_r()
{
map(0x0000, 0xffff).rom();
return m_upd7759->busy_r() ? m_p3 : (m_p3 | 0x08);
}
void maygayv1_state::sound_data(address_map &map)
void maygayv1_state::sound_p3_w(uint8_t data)
{
}
// preserve RXD
m_p3 = (m_p3 & 1) | (m_p3 & ~1);
void maygayv1_state::sound_io(address_map &map)
{
map(0x00, 0xff).rw(FUNC(maygayv1_state::mcu_r), FUNC(maygayv1_state::mcu_w));
m_duart68681->rx_a_w(BIT(data, 1));
m_upd7759->reset_w(BIT(data, 2));
m_upd7759->start_w(BIT(data, 6));
}
@ -835,18 +806,10 @@ WRITE_LINE_MEMBER(maygayv1_state::duart_irq_handler)
WRITE_LINE_MEMBER(maygayv1_state::duart_txa)
{
m_d68681_val = state;
m_soundcpu->set_input_line(MCS51_RX_LINE, ASSERT_LINE); // ?
}
uint8_t maygayv1_state::data_to_i8031()
{
return m_d68681_val;
}
void maygayv1_state::data_from_i8031(uint8_t data)
{
m_duart68681->rx_a_w(data);
if (state)
m_p3 |= 1;
else
m_p3 &= ~1;
}
uint8_t maygayv1_state::b_read()
@ -886,11 +849,10 @@ void maygayv1_state::maygayv1(machine_config &config)
m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &maygayv1_state::cpu_space_map);
I8052(config, m_soundcpu, SOUND_CLOCK);
m_soundcpu->set_addrmap(AS_PROGRAM, &maygayv1_state::sound_prg);
m_soundcpu->set_addrmap(AS_DATA, &maygayv1_state::sound_data);
m_soundcpu->set_addrmap(AS_IO, &maygayv1_state::sound_io);
m_soundcpu->serial_tx_cb().set(FUNC(maygayv1_state::data_from_i8031));
m_soundcpu->serial_rx_cb().set(FUNC(maygayv1_state::data_to_i8031));
m_soundcpu->port_in_cb<1>().set(FUNC(maygayv1_state::sound_p1_r));
m_soundcpu->port_out_cb<1>().set(FUNC(maygayv1_state::sound_p1_w));
m_soundcpu->port_in_cb<3>().set(FUNC(maygayv1_state::sound_p3_r));
m_soundcpu->port_out_cb<3>().set(FUNC(maygayv1_state::sound_p3_w));
/* U25 ST 2 9148 EF68B21P */
pia6821_device &pia(PIA6821(config, "pia", 0));

View File

@ -334,8 +334,6 @@ void micro3d_state::micro3d(machine_config &config)
m_audiocpu->port_out_cb<1>().set(FUNC(micro3d_state::micro3d_sound_p1_w));
m_audiocpu->port_in_cb<3>().set(FUNC(micro3d_state::micro3d_sound_p3_r));
m_audiocpu->port_out_cb<3>().set(FUNC(micro3d_state::micro3d_sound_p3_w));
m_audiocpu->serial_tx_cb().set(FUNC(micro3d_state::data_from_i8031));
m_audiocpu->serial_rx_cb().set(FUNC(micro3d_state::data_to_i8031));
MC68681(config, m_duart, 3.6864_MHz_XTAL);
m_duart->irq_cb().set(FUNC(micro3d_state::duart_irq_handler));

View File

@ -177,8 +177,6 @@ private:
INTERRUPT_GEN_MEMBER(micro3d_vblank);
TIMER_CALLBACK_MEMBER(mac_done_callback);
void micro3d_upd7759_w(uint8_t data);
void data_from_i8031(uint8_t data);
uint8_t data_to_i8031();
DECLARE_WRITE_LINE_MEMBER(duart_irq_handler);
uint8_t duart_input_r();
void duart_output_w(uint8_t data);

View File

@ -39,20 +39,10 @@ WRITE_LINE_MEMBER(micro3d_state::duart_irq_handler)
WRITE_LINE_MEMBER(micro3d_state::duart_txb)
{
m_m68681_tx0 = state;
m_audiocpu->set_input_line(MCS51_RX_LINE, ASSERT_LINE);
// TODO: next line should be behind a timer callback which lasts one audiocpu clock cycle
m_audiocpu->set_input_line(MCS51_RX_LINE, CLEAR_LINE);
}
uint8_t micro3d_state::data_to_i8031()
{
return m_m68681_tx0;
}
void micro3d_state::data_from_i8031(uint8_t data)
{
m_duart->rx_b_w(data);
if (state)
m_sound_port_latch[3] |= 1;
else
m_sound_port_latch[3] &= ~1;
}
/*
@ -463,8 +453,10 @@ void micro3d_state::micro3d_sound_p1_w(uint8_t data)
void micro3d_state::micro3d_sound_p3_w(uint8_t data)
{
m_sound_port_latch[3] = data;
// preserve RXD input
m_sound_port_latch[3] = (m_sound_port_latch[3] & 1) | (data & ~1);
m_duart->rx_b_w(BIT(data, 1));
m_upd7759->set_rom_bank(BIT(data, 2));
m_upd7759->reset_w(!BIT(data, 4));
}

View File

@ -45,7 +45,7 @@ private:
virtual void machine_start() override;
virtual void machine_reset() override;
void ctrl_w(uint8_t data);
void mcs51_tx_callback(uint8_t data);
void port3_w(uint8_t data);
void led_strobe_w(uint8_t data);
void lcd_latch_w(uint8_t data);
void lcd_control_w(uint8_t data);
@ -71,6 +71,8 @@ void piggypas_state::output_digits()
m_digits[1] = bitswap<8>((m_digit_latch >> 8) & 0xff, 7,6,4,3,2,1,0,5) & 0x7f;
m_digits[2] = bitswap<8>((m_digit_latch >> 16) & 0xff, 7,6,4,3,2,1,0,5) & 0x7f;
m_digits[3] = bitswap<8>((m_digit_latch >> 24) & 0xff, 7,6,4,3,2,1,0,5) & 0x7f;
m_digit_latch = 0;
}
void piggypas_state::ctrl_w(uint8_t data)
@ -83,9 +85,15 @@ void piggypas_state::ctrl_w(uint8_t data)
m_ctrl = data;
}
void piggypas_state::mcs51_tx_callback(uint8_t data)
void piggypas_state::port3_w(uint8_t data)
{
m_digit_latch = (m_digit_latch >> 8) | (u32(data) << 24);
if (!BIT(data, 1))
{
m_digit_latch >>= 1;
if (BIT(data, 0))
m_digit_latch |= (1U << 31);
}
}
void piggypas_state::led_strobe_w(uint8_t data)
@ -197,7 +205,7 @@ void piggypas_state::piggypas(machine_config &config)
m_maincpu->set_addrmap(AS_IO, &piggypas_state::piggypas_io);
m_maincpu->port_out_cb<1>().set(FUNC(piggypas_state::led_strobe_w));
m_maincpu->port_in_cb<3>().set_ioport("IN2");
m_maincpu->serial_tx_cb().set(FUNC(piggypas_state::mcs51_tx_callback));
m_maincpu->port_out_cb<3>().set(FUNC(piggypas_state::port3_w));
// m_maincpu->set_vblank_int("screen", FUNC(piggypas_state::irq0_line_hold));
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // DS1220AD
@ -235,7 +243,6 @@ void piggypas_state::fidlstix(machine_config &config)
piggypas(config);
m_maincpu->set_addrmap(AS_IO, &piggypas_state::fidlstix_io);
m_maincpu->serial_tx_cb().set_nop();
m_maincpu->port_in_cb<1>().set(m_hd44780, FUNC(hd44780_device::db_r));
m_maincpu->port_out_cb<1>().set(FUNC(piggypas_state::lcd_latch_w));
m_maincpu->port_out_cb<3>().set(FUNC(piggypas_state::lcd_control_w));

View File

@ -195,21 +195,21 @@ void cdi_state::machine_reset()
void quizard_state::machine_start()
{
save_item(NAME(m_mcu_rx_from_cpu));
save_item(NAME(m_mcu_initial_byte));
save_item(NAME(m_boot_press));
m_boot_timer = timer_alloc(FUNC(quizard_state::boot_press_tick), this);
set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1);
set_rate(9600);
}
void quizard_state::machine_reset()
{
cdi_state::machine_reset();
m_mcu_rx_from_cpu = 0x00;
m_mcu_initial_byte = true;
m_boot_press = false;
m_boot_timer->adjust(attotime::from_seconds(13), 1);
m_mcu_p3 = 0x04;
}
@ -288,16 +288,8 @@ void quizard_state::mcu_rtsn_from_cpu(int state)
void quizard_state::mcu_rx_from_cpu(uint8_t data)
{
LOGMASKED(LOG_UART, "MCU receiving %02x from CPU\n", data);
if (m_mcu_initial_byte)
{
m_mcu_initial_byte = false;
return;
}
m_mcu_rx_from_cpu = data;
m_mcu->set_input_line(MCS51_RX_LINE, ASSERT_LINE);
m_mcu->set_input_line(MCS51_RX_LINE, CLEAR_LINE);
transmit_register_setup(data);
}
uint8_t quizard_state::mcu_p0_r()
@ -325,8 +317,8 @@ uint8_t quizard_state::mcu_p2_r()
uint8_t quizard_state::mcu_p3_r()
{
LOGMASKED(LOG_QUIZARD_READS, "%s: MCU Port 3 Read (%02x)\n", machine().describe_context(), 0x04);
return 0x04;
LOGMASKED(LOG_QUIZARD_READS, "%s: MCU Port 3 Read (%02x)\n", machine().describe_context(), m_mcu_p3);
return m_mcu_p3;
}
void quizard_state::mcu_p0_w(uint8_t data)
@ -347,22 +339,10 @@ void quizard_state::mcu_p2_w(uint8_t data)
void quizard_state::mcu_p3_w(uint8_t data)
{
LOGMASKED(LOG_QUIZARD_WRITES, "%s: MCU Port 3 Write (%02x)\n", machine().describe_context(), data);
rx_w(BIT(data, 1));
m_maincpu->uart_ctsn(BIT(data, 6));
}
void quizard_state::mcu_tx(uint8_t data)
{
LOGMASKED(LOG_QUIZARD_OTHER, "%s: MCU transmitting %02x\n", machine().describe_context(), data);
m_maincpu->uart_rx(data);
}
uint8_t quizard_state::mcu_rx()
{
uint8_t data = m_mcu_rx_from_cpu;
LOGMASKED(LOG_QUIZARD_OTHER, "%s: MCU receiving %02x\n", machine().describe_context(), data);
return data;
}
/*************************
* DVC cartridge *
*************************/
@ -601,7 +581,7 @@ void quizard_state::quizard(machine_config &config)
m_maincpu->uart_rtsn_callback().set(FUNC(quizard_state::mcu_rtsn_from_cpu));
m_maincpu->uart_tx_callback().set(FUNC(quizard_state::mcu_rx_from_cpu));
I8751(config, m_mcu, 8000000);
I8751(config, m_mcu, 11.0592_MHz_XTAL);
m_mcu->port_in_cb<0>().set(FUNC(quizard_state::mcu_p0_r));
m_mcu->port_in_cb<1>().set(FUNC(quizard_state::mcu_p1_r));
m_mcu->port_in_cb<2>().set(FUNC(quizard_state::mcu_p2_r));
@ -610,12 +590,27 @@ void quizard_state::quizard(machine_config &config)
m_mcu->port_out_cb<1>().set(FUNC(quizard_state::mcu_p1_w));
m_mcu->port_out_cb<2>().set(FUNC(quizard_state::mcu_p2_w));
m_mcu->port_out_cb<3>().set(FUNC(quizard_state::mcu_p3_w));
m_mcu->serial_tx_cb().set(FUNC(quizard_state::mcu_tx));
m_mcu->serial_rx_cb().set(FUNC(quizard_state::mcu_rx));
m_slave_hle->read_mousebtn().set(FUNC(quizard_state::mcu_button_press));
}
void quizard_state::tra_callback()
{
if (transmit_register_get_data_bit())
m_mcu_p3 |= 1;
else
m_mcu_p3 &= ~1;
}
void quizard_state::rcv_complete()
{
receive_register_extract();
const uint8_t data = get_received_char();
LOGMASKED(LOG_QUIZARD_OTHER, "%s: MCU transmitting %02x\n", machine().describe_context(), data);
m_maincpu->uart_rx(data);
}
/*************************
* Rom Load *
*************************/

View File

@ -11,6 +11,7 @@
#include "mcd212.h"
#include "cpu/mcs51/mcs51.h"
#include "cpu/m6805/m68hc05.h"
#include "diserial.h"
#include "screen.h"
/*----------- driver state -----------*/
@ -81,11 +82,12 @@ private:
required_device_array<dmadac_sound_device, 2> m_dmadac;
};
class quizard_state : public cdi_state
class quizard_state : public cdi_state, public device_serial_interface
{
public:
quizard_state(const machine_config &mconfig, device_type type, const char *tag)
: cdi_state(mconfig, type, tag)
, device_serial_interface(mconfig, *this)
, m_mcu(*this, "mcu")
, m_inputs(*this, "P%u", 0U)
{ }
@ -96,6 +98,9 @@ private:
virtual void machine_start() override;
virtual void machine_reset() override;
virtual void tra_callback() override;
virtual void rcv_complete() override;
TIMER_CALLBACK_MEMBER(boot_press_tick);
uint8_t mcu_p0_r();
@ -106,8 +111,6 @@ private:
void mcu_p1_w(uint8_t data);
void mcu_p2_w(uint8_t data);
void mcu_p3_w(uint8_t data);
void mcu_tx(uint8_t data);
uint8_t mcu_rx();
void mcu_rx_from_cpu(uint8_t data);
void mcu_rtsn_from_cpu(int state);
@ -117,10 +120,9 @@ private:
required_device<i8751_device> m_mcu;
required_ioport_array<3> m_inputs;
uint8_t m_mcu_rx_from_cpu = 0U;
bool m_mcu_initial_byte = false;
bool m_boot_press = false;
emu_timer *m_boot_timer = nullptr;
uint8_t m_mcu_p3 = 0x04;
};
// Quizard 2 language values:

View File

@ -156,6 +156,8 @@ private:
uint8_t port1_r();
uint8_t port3_r();
void serial_rxd(int state);
void dev_ctrl_reg_w(offs_t offset, uint8_t data);
uint8_t dev_keyb_ser_r(offs_t offset);
@ -243,9 +245,16 @@ void minitel_state::port3_w(uint8_t data)
m_serport->write_txd( !!(data & PORT_3_SER_TXD) );
port3 = data;
port3 = (port3 & PORT_3_SER_RXD) | (data & ~PORT_3_SER_RXD);
}
void minitel_state::serial_rxd(int state)
{
if (state)
port3 |= PORT_3_SER_RXD;
else
port3 &= ~PORT_3_SER_RXD;
}
void minitel_state::update_modem_state()
@ -532,7 +541,7 @@ void minitel_state::minitel2(machine_config &config)
m_modem->set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(m_modem));
RS232_PORT(config, m_serport, default_rs232_devices, nullptr);
m_serport->rxd_handler().set_inputline(m_maincpu, MCS51_RX_LINE);
m_serport->rxd_handler().set(FUNC(minitel_state::serial_rxd));
m_serport->set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(m_serport));
lineconnected = 0;

View File

@ -235,7 +235,6 @@ void mephisto_state::mephisto(machine_config &config)
soundcpu.port_in_cb<1>().set(FUNC(mephisto_state::ay8910_read));
soundcpu.port_out_cb<1>().set(FUNC(mephisto_state::ay8910_write));
soundcpu.port_out_cb<3>().set(FUNC(mephisto_state::t0_t1_w));
soundcpu.serial_rx_cb().set_constant(0); // from MUART
/* Sound */
genpin_audio(config);

View File

@ -10,8 +10,6 @@
#include "video/scn2674.h"
#include "emupal.h"
#include "diserial.h"
class pcdx_video_device : public device_t, public device_gfx_interface
{
@ -78,12 +76,12 @@ private:
SCN2674_DRAW_CHARACTER_MEMBER(display_pixels);
};
class pcx_video_device : public pcdx_video_device,
public device_serial_interface
class pcx_video_device : public pcdx_video_device
{
public:
pcx_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto txd_handler() { return m_txd_handler.bind(); }
void rx_w(int state);
virtual void map(address_map &map) override;
uint8_t term_r(offs_t offset);
@ -103,18 +101,15 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
void tra_callback() override;
void rcv_complete() override;
private:
required_device<scn2672_device> m_crtc;
required_region_ptr<uint8_t> m_charrom;
devcb_write_line m_txd_handler;
uint8_t m_term_key, m_term_char, m_term_stat, m_p1;
uint8_t m_term_key, m_term_char, m_term_stat, m_p1, m_p3;
uint8_t rx_callback();
void tx_callback(uint8_t data);
uint8_t p3_r();
void p3_w(uint8_t data);
SCN2672_DRAW_CHARACTER_MEMBER(display_pixels);
};

View File

@ -34,7 +34,6 @@ pcd_video_device::pcd_video_device(const machine_config &mconfig, const char *ta
pcx_video_device::pcx_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
pcdx_video_device(mconfig, PCX_VIDEO, tag, owner, clock),
device_serial_interface(mconfig, *this),
m_crtc(*this, "crtc"),
m_charrom(*this, "char"),
m_txd_handler(*this)
@ -152,8 +151,8 @@ void pcx_video_device::device_add_mconfig(machine_config &config)
gfx.set_addrmap(AS_PROGRAM, &pcx_video_device::pcx_vid_map);
gfx.set_addrmap(AS_IO, &pcx_video_device::pcx_vid_io);
gfx.port_out_cb<1>().set(FUNC(pcx_video_device::p1_w));
gfx.serial_tx_cb().set(FUNC(pcx_video_device::tx_callback));
gfx.serial_rx_cb().set(FUNC(pcx_video_device::rx_callback));
gfx.port_in_cb<3>().set(FUNC(pcx_video_device::p3_r));
gfx.port_out_cb<3>().set(FUNC(pcx_video_device::p3_w));
// video hardware
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
@ -422,9 +421,6 @@ void pcx_video_device::device_start()
m_maincpu->space(AS_IO).install_readwrite_handler(0xfb00, 0xfb01, read8smo_delegate(*this, FUNC(pcdx_video_device::detect_r)), write8smo_delegate(*this, FUNC(pcdx_video_device::detect_w)), 0x00ff);
m_txd_handler.resolve_safe();
set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1);
set_rate(600);
decode_gfx(gfx_pcx);
}
@ -432,8 +428,6 @@ void pcx_video_device::device_reset()
{
m_term_key = 0;
m_term_stat = 0;
transmit_register_reset();
receive_register_reset();
m_txd_handler(1);
}
@ -443,24 +437,23 @@ void pcx_video_device::map(address_map &map)
map(0x0, 0xf).rw(FUNC(pcx_video_device::term_r), FUNC(pcx_video_device::term_w));
}
uint8_t pcx_video_device::rx_callback()
void pcx_video_device::rx_w(int state)
{
return get_received_char();
if (state)
m_p3 |= 1;
else
m_p3 &= ~1;
}
void pcx_video_device::tx_callback(uint8_t data)
uint8_t pcx_video_device::p3_r()
{
transmit_register_setup(data);
return m_p3;
}
void pcx_video_device::tra_callback()
void pcx_video_device::p3_w(uint8_t data)
{
m_txd_handler(transmit_register_get_data_bit());
}
// preserve RXD
m_p3 = (m_p3 & 1) | (data & ~1);
void pcx_video_device::rcv_complete()
{
receive_register_extract();
m_mcu->set_input_line(MCS51_RX_LINE, ASSERT_LINE);
m_mcu->set_input_line(MCS51_RX_LINE, CLEAR_LINE);
m_txd_handler(BIT(data, 1));
}

View File

@ -64,7 +64,8 @@ Current status:
#include "emu.h"
#include "cpu/mcs51/mcs51.h"
#include "sound/tms5220.h"
#include "machine/terminal.h"
#include "bus/rs232/terminal.h"
#include "bus/rs232/rs232.h"
#include "speaker.h"
@ -76,7 +77,7 @@ public:
pes_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_terminal(*this, "terminal")
, m_serial(*this, "serial")
, m_speech(*this, "tms5220")
{ }
@ -84,34 +85,25 @@ public:
private:
u8 m_term_data = 0U;
u8 m_port3 = 0U;
virtual void machine_reset() override;
void port3_w(u8 data);
u8 port3_r();
void kbd_put(u8 data);
void rx_w(int state);
void io_map(address_map &map);
void prg_map(address_map &map);
required_device<i80c31_device> m_maincpu;
required_device<generic_terminal_device> m_terminal;
required_device<rs232_port_device> m_serial;
required_device<tms5220_device> m_speech;
};
/* Devices */
void pes_state::kbd_put(u8 data)
{
m_maincpu->set_input_line(MCS51_RX_LINE, ASSERT_LINE);
m_maincpu->set_input_line(MCS51_RX_LINE, CLEAR_LINE);
m_term_data = data;
}
/* Port Handlers */
void pes_state::port3_w(u8 data)
{
m_port3 = data;
// preserve RXD
m_port3 = (m_port3 & 0x01) | (data & ~0x01);
#if 0
logerror("port3 write: control data written: %02X; ", data);
logerror("RXD: %d; ", BIT(data,0));
@ -123,7 +115,7 @@ void pes_state::port3_w(u8 data)
logerror("WR: %d; ", BIT(data,6));
logerror("RD: %d;\n", BIT(data,7));
#endif
// todo: poke serial handler here somehow?
m_serial->write_txd(BIT(data, 1));
}
u8 pes_state::port3_r()
@ -136,6 +128,14 @@ u8 pes_state::port3_r()
return data;
}
void pes_state::rx_w(int state)
{
if (state)
m_port3 |= 1;
else
m_port3 &= ~1;
}
/* Reset */
void pes_state::machine_reset()
@ -171,6 +171,11 @@ INPUT_PORTS_END
Machine Drivers
******************************************************************************/
static void serial_devices(device_slot_interface &device)
{
device.option_add("terminal", SERIAL_TERMINAL);
}
void pes_state::pes(machine_config &config)
{
/* basic machine hardware */
@ -181,16 +186,14 @@ void pes_state::pes(machine_config &config)
m_maincpu->port_out_cb<1>().set(m_speech, FUNC(tms5220_device::data_w));
m_maincpu->port_in_cb<3>().set(FUNC(pes_state::port3_r));
m_maincpu->port_out_cb<3>().set(FUNC(pes_state::port3_w));
m_maincpu->serial_tx_cb().set(m_terminal, FUNC(generic_terminal_device::write));
m_maincpu->serial_rx_cb().set([this] () { return m_term_data; });
/* sound hardware */
SPEAKER(config, "mono").front_center();
TMS5220C(config, m_speech, 720000); /* 720Khz clock, 9khz sample-rate, adjustable with 10-turn trimpot */
m_speech->add_route(ALL_OUTPUTS, "mono", 1.0);
GENERIC_TERMINAL(config, m_terminal, 0);
m_terminal->set_keyboard_callback(FUNC(pes_state::kbd_put));
RS232_PORT(config, m_serial, serial_devices, "terminal");
m_serial->rxd_handler().set(FUNC(pes_state::rx_w));
}
/******************************************************************************

View File

@ -52,7 +52,6 @@ private:
void scan_load_w(u8 data);
u8 scan_shift_r();
void lcd_control_w(u8 data);
void serial_tx_w(u8 data) { logerror("Serial TX: %02X\n", data); }
void prog_map(address_map &map);
void ext_map(address_map &map);
@ -163,7 +162,6 @@ void sk101bl_state::sk101bl(machine_config &config)
m_maincpu->port_in_cb<1>().set(FUNC(sk101bl_state::p1_r));
m_maincpu->port_out_cb<1>().set(FUNC(sk101bl_state::p1_w));
m_maincpu->port_out_cb<3>().set("alarm", FUNC(speaker_sound_device::level_w)).bit(3);
m_maincpu->serial_tx_cb().set(FUNC(sk101bl_state::serial_tx_w));
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
screen.set_refresh_hz(50);

View File

@ -71,9 +71,11 @@ private:
u8 dma_r(offs_t offset);
u8 key_r(offs_t offset);
u8 port1_r();
u8 port3_r();
void store_w(u8 data);
void port1_w(u8 data);
void port3_w(u8 data);
void rx_w(int state);
I8275_DRAW_CHARACTER_MEMBER(crtc_update_row);
void io_map(address_map &map);
@ -94,6 +96,8 @@ private:
required_device<ttl7474_device> m_7474;
required_device<rs232_port_device> m_rs232;
required_device<centronics_device> m_centronics;
u8 m_port3;
};
void trs80dt1_state::machine_reset()
@ -103,6 +107,7 @@ void trs80dt1_state::machine_reset()
// line is active low in the real chip
m_nvram->recall(1);
m_nvram->recall(0);
m_port3 = 0;
}
u8 trs80dt1_state::dma_r(offs_t offset)
@ -158,6 +163,21 @@ void trs80dt1_state::port3_w(u8 data)
{
m_rs232->write_txd(BIT(data, 1));
m_buzzer->set_state(BIT(data, 4));
m_port3 = (m_port3 & 1) | (data & ~1);
}
u8 trs80dt1_state::port3_r()
{
return m_port3;
}
void trs80dt1_state::rx_w(int state)
{
if (state)
m_port3 |= 1;
else
m_port3 &= ~1;
}
void trs80dt1_state::prg_map(address_map &map)
@ -341,6 +361,7 @@ void trs80dt1_state::trs80dt1(machine_config &config)
m_maincpu->port_out_cb<1>().set(FUNC(trs80dt1_state::port1_w));
m_maincpu->port_in_cb<1>().set(FUNC(trs80dt1_state::port1_r));
m_maincpu->port_out_cb<3>().set(FUNC(trs80dt1_state::port3_w));
m_maincpu->port_in_cb<3>().set(FUNC(trs80dt1_state::port3_r));
/* video hardware */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
@ -373,7 +394,7 @@ void trs80dt1_state::trs80dt1(machine_config &config)
BEEP(config, m_buzzer, 2000).add_route(ALL_OUTPUTS, "mono", 0.50);
RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
m_rs232->rxd_handler().set_inputline("maincpu", MCS51_RX_LINE);
m_rs232->rxd_handler().set(FUNC(trs80dt1_state::rx_w));
/* printer */
CENTRONICS(config, m_centronics, centronics_devices, "printer");

View File

@ -44,7 +44,6 @@ Notes:
TODO:
- rewrite the mcs51.c serial I/O to replace this horrible, horrible hack
- dip switches
*/
@ -119,9 +118,8 @@ void wangpc_keyboard_device::device_add_mconfig(machine_config &config)
m_maincpu->port_in_cb<1>().set(FUNC(wangpc_keyboard_device::kb_p1_r));
m_maincpu->port_out_cb<1>().set(FUNC(wangpc_keyboard_device::kb_p1_w));
m_maincpu->port_out_cb<2>().set(FUNC(wangpc_keyboard_device::kb_p2_w));
m_maincpu->port_in_cb<3>().set(FUNC(wangpc_keyboard_device::kb_p3_r));
m_maincpu->port_out_cb<3>().set(FUNC(wangpc_keyboard_device::kb_p3_w));
m_maincpu->serial_tx_cb().set(FUNC(wangpc_keyboard_device::mcs51_tx_callback));
m_maincpu->serial_rx_cb().set(FUNC(wangpc_keyboard_device::mcs51_rx_callback));
// sound hardware
SPEAKER(config, "mono").front_center();
@ -369,7 +367,6 @@ ioport_constructor wangpc_keyboard_device::device_input_ports() const
wangpc_keyboard_device::wangpc_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, WANGPC_KEYBOARD, tag, owner, clock),
device_serial_interface(mconfig, *this),
m_maincpu(*this, I8051_TAG),
m_y(*this, "Y%u", 0),
m_txd_handler(*this),
@ -389,11 +386,6 @@ void wangpc_keyboard_device::device_start()
m_txd_handler.resolve_safe();
m_leds.resolve();
set_data_frame(1, 8, PARITY_NONE, STOP_BITS_2);
set_rcv_rate(62500);
set_tra_rate(62500);
save_item(NAME(m_keylatch));
save_item(NAME(m_rxd));
}
@ -405,63 +397,10 @@ void wangpc_keyboard_device::device_start()
void wangpc_keyboard_device::device_reset()
{
receive_register_reset();
transmit_register_reset();
m_txd_handler(1);
}
//-------------------------------------------------
// tra_callback -
//-------------------------------------------------
void wangpc_keyboard_device::tra_callback()
{
int bit = transmit_register_get_data_bit();
if (LOG) logerror("KB '%s' Transmit Bit %u\n", tag(), bit);
m_txd_handler(bit);
}
//-------------------------------------------------
// tra_complete -
//-------------------------------------------------
void wangpc_keyboard_device::tra_complete()
{
}
//-------------------------------------------------
// rcv_callback -
//-------------------------------------------------
void wangpc_keyboard_device::rcv_callback()
{
if (LOG) logerror("KB '%s' Receive Bit %u\n", tag(), m_rxd);
receive_register_update_bit(m_rxd);
}
//-------------------------------------------------
// rcv_complete -
//-------------------------------------------------
void wangpc_keyboard_device::rcv_complete()
{
receive_register_extract();
if (LOG) logerror("KB '%s' Receive Data %02x\n", tag(), get_received_char());
m_maincpu->set_input_line(MCS51_RX_LINE, ASSERT_LINE);
m_maincpu->set_input_line(MCS51_RX_LINE, CLEAR_LINE);
}
//-------------------------------------------------
// write_rxd -
//-------------------------------------------------
@ -469,32 +408,6 @@ void wangpc_keyboard_device::rcv_complete()
WRITE_LINE_MEMBER(wangpc_keyboard_device::write_rxd)
{
m_rxd = state;
device_serial_interface::rx_w(state);
}
//-------------------------------------------------
// mcs51_rx_callback -
//-------------------------------------------------
uint8_t wangpc_keyboard_device::mcs51_rx_callback()
{
if (LOG) logerror("KB '%s' CPU Receive Data %02x\n", tag(), get_received_char());
return get_received_char();
}
//-------------------------------------------------
// mcs51_tx_callback -
//-------------------------------------------------
void wangpc_keyboard_device::mcs51_tx_callback(uint8_t data)
{
if (LOG) logerror("KB '%s' CPU Transmit Data %02x\n", tag(), data);
transmit_register_setup(data);
}
@ -565,6 +478,16 @@ void wangpc_keyboard_device::kb_p2_w(uint8_t data)
}
//-------------------------------------------------
// kb_p3_r -
//-------------------------------------------------
uint8_t wangpc_keyboard_device::kb_p3_r()
{
return m_rxd;
}
//-------------------------------------------------
// kb_p3_w -
//-------------------------------------------------
@ -587,4 +510,5 @@ void wangpc_keyboard_device::kb_p3_w(uint8_t data)
*/
//if (LOG) logerror("P3 %02x\n", data);
m_txd_handler(BIT(data, 1));
}

View File

@ -15,8 +15,6 @@
#include "sound/sn76496.h"
#include "diserial.h"
//**************************************************************************
// TYPE DEFINITIONS
@ -24,7 +22,7 @@
// ======================> wangpc_keyboard_device
class wangpc_keyboard_device : public device_t, public device_serial_interface
class wangpc_keyboard_device : public device_t
{
public:
// construction/destruction
@ -46,12 +44,6 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
// device_serial_interface overrides
virtual void tra_callback() override;
virtual void tra_complete() override;
virtual void rcv_callback() override;
virtual void rcv_complete() override;
private:
required_device<i8051_device> m_maincpu;
required_ioport_array<16> m_y;
@ -61,12 +53,10 @@ private:
uint8_t m_keylatch;
int m_rxd;
uint8_t mcs51_rx_callback();
void mcs51_tx_callback(uint8_t data);
uint8_t kb_p1_r();
void kb_p1_w(uint8_t data);
void kb_p2_w(uint8_t data);
uint8_t kb_p3_r();
void kb_p3_w(uint8_t data);
};