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 "mcs51.h"
#include "mcs51dasm.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 CONSTANTS
@ -223,6 +227,22 @@ enum
V_PFI = 0x02b /* Power Failure Interrupt */ 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(I8031, i8031_device, "i8031", "Intel 8031")
DEFINE_DEVICE_TYPE(I8032, i8032_device, "i8032", "Intel 8032") 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_scratchpad(*this, "scratchpad")
, m_port_in_cb(*this) , m_port_in_cb(*this)
, m_port_out_cb(*this) , m_port_out_cb(*this)
, m_serial_tx_cb(*this)
, m_serial_rx_cb(*this)
, m_rtemp(0) , m_rtemp(0)
{ {
m_ds5002fp.mcon = 0; m_ds5002fp.mcon = 0;
@ -797,7 +815,7 @@ void mcs51_cpu_device::clear_current_irq()
m_cur_irq_prio = 0; m_cur_irq_prio = 0;
else else
m_cur_irq_prio = -1; 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); } 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)); 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) void mcs51_cpu_device::transmit_receive(int source)
{ {
int mode = (GET_SM0<<1) | GET_SM1; int mode = (GET_SM0<<1) | GET_SM1;
if (source == 1) /* timer1 */ 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) { 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: case 0:
m_uart.rx_clk += (source == 0) ? 16 : 0; /* clock / 12 */ if (source == 0)
m_uart.tx_clk += (source == 0) ? 16 : 0; /* clock / 12 */ {
break; // 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 //8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2
case 1: case 1:
case 3: 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 */ m_uart.tx_clk += (source == 0) ? (GET_SMOD ? 6 : 3) : 0; /* clock / 12 */
break; break;
} }
/* transmit ? */
// transmit
if (m_uart.tx_clk >= 16) if (m_uart.tx_clk >= 16)
{ {
m_uart.tx_clk &= 0x0f; 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; m_uart.rx_clk &= 0x0f;
if (m_uart.delay_cycles>0)
if (GET_REN)
{ {
m_uart.delay_cycles--; // directly read RXD input
if (m_uart.delay_cycles == 0) bool const data = BIT(m_port_in_cb[3](), 0);
switch (m_uart.rxbit)
{ {
int data = 0; case SIO_IDLE:
//Call our callball function to retrieve the data if (data)
data = m_serial_rx_cb(0, 0xff); m_uart.rxbit = SIO_START_LE;
LOG(("RX Deliver %d\n", data)); break;
SET_SBUF(data); case SIO_START_LE: // start bit leading edge
//Flag the IRQ if (!data)
SET_RI(1); {
SET_RB8(1); // HACK force 2nd stop bit 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 */ /* Check and update status of serial port */
void mcs51_cpu_device::update_serial(int cycles) 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 /* Skip the interrupt request if currently processing interrupt
* and the new request does not have a higher priority * 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)) 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; return;
} }
@ -1853,7 +1967,7 @@ void mcs51_cpu_device::check_irqs()
m_cur_irq_prio = priority_request; m_cur_irq_prio = priority_request;
m_irq_active |= (1 << 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! //Clear any interrupt flags that should be cleared since we're servicing the irq!
switch(int_vec) { 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"); fatalerror("mcs51: Trying to set T2EX_LINE on a non I8052 type cpu.\n");
break; 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 */ /* Power Fail Interrupt */
case DS5002FP_PFI_LINE: case DS5002FP_PFI_LINE:
if (m_features & FEATURE_DS5002FP) 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_P1: m_port_out_cb[1](data); break;
case ADDR_P2: m_port_out_cb[2](data); break; case ADDR_P2: m_port_out_cb[2](data); break;
case ADDR_P3: m_port_out_cb[3](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_PSW: SET_PARITY(); break;
case ADDR_ACC: SET_PARITY(); break; case ADDR_ACC: SET_PARITY(); break;
case ADDR_IP: update_irq_prio(data, 0); 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_B:
case ADDR_SP: case ADDR_SP:
case ADDR_DPL: case ADDR_DPL:
@ -2117,10 +2225,18 @@ void mcs51_cpu_device::sfr_write(size_t offset, uint8_t data)
case ADDR_TL1: case ADDR_TL1:
case ADDR_TH0: case ADDR_TH0:
case ADDR_TH1: case ADDR_TH1:
break;
case ADDR_SCON: 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; break;
default: 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 */ /* no write in this case according to manual */
return; return;
} }
@ -2162,7 +2278,7 @@ uint8_t mcs51_cpu_device::sfr_read(size_t offset)
return m_data.read_byte((size_t) offset | 0x100); return m_data.read_byte((size_t) offset | 0x100);
/* Illegal or non-implemented sfr */ /* Illegal or non-implemented sfr */
default: 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 */ /* according to the manual, the read may return random bits */
return 0xff; return 0xff;
} }
@ -2177,8 +2293,6 @@ void mcs51_cpu_device::device_start()
m_port_in_cb.resolve_all_safe(0xff); m_port_in_cb.resolve_all_safe(0xff);
m_port_out_cb.resolve_all_safe(); m_port_out_cb.resolve_all_safe();
m_serial_rx_cb.resolve_safe(0);
m_serial_tx_cb.resolve_safe();
/* Save states */ /* Save states */
save_item(NAME(m_ppc)); 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.rnr_delay) );
save_item(NAME(m_ds5002fp.range) ); save_item(NAME(m_ds5002fp.range) );
save_item(NAME(m_uart.data_out)); 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.smod_div));
save_item(NAME(m_uart.rx_clk)); save_item(NAME(m_uart.rx_clk));
save_item(NAME(m_uart.tx_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_PC, "PC", m_pc).formatstr("%04X");
state_add( MCS51_SP, "SP", SP).formatstr("%02X"); 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_out = 0;
m_uart.data_in = 0;
m_uart.rx_clk = 0; m_uart.rx_clk = 0;
m_uart.tx_clk = 0; m_uart.tx_clk = 0;
m_uart.bits_to_send = 0; m_uart.txbit = SIO_IDLE;
m_uart.delay_cycles = 0; m_uart.rxbit = SIO_IDLE;
m_uart.smod_div = 0; m_uart.smod_div = 0;
m_recalc_parity = 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_LOGW(a, d) LOG("write to " # a " register at 0x%04x, data=%x\n", PC, d)
#define DS5_LOGR(a, d) LOG(("ds5002fp '%s': read from " # a " register at 0x%04x\n", tag(), PC)) #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) 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)) if ((data == 0xaa) && (m_ds5002fp.ta_window == 0))
{ {
m_ds5002fp.ta_window = 6; /* 4*12 + 2*12 */ 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; break;
case ADDR_MCON: data = ds5002fp_protected(ADDR_MCON, data, 0x0f, 0xf7); DS5_LOGW(MCON, data); 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_INT0_LINE = 0, /* P3.2: External Interrupt 0 */
MCS51_INT1_LINE, /* P3.3: External Interrupt 1 */ 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_T1_LINE, /* P3.5: Timer 1 External Input */
MCS51_T2_LINE, /* P1.0: Timer 2 External Input */ MCS51_T2_LINE, /* P1.0: Timer 2 External Input */
MCS51_T2EX_LINE, /* P1.1: Timer 2 Capture Reload Trigger */ 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_in_cb() { return m_port_in_cb[N].bind(); }
template <unsigned N> auto port_out_cb() { return m_port_out_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 program_internal(address_map &map);
void data_internal(address_map &map); void data_internal(address_map &map);
@ -132,12 +129,14 @@ protected:
struct mcs51_uart struct mcs51_uart
{ {
uint8_t data_out; //Data to send out 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 smod_div; /* signal divided by 2^SMOD */
int rx_clk; /* rx clock */ int rx_clk; /* rx clock */
int tx_clk; /* tx clock */ int tx_clk; /* tx clock */
uint8_t delay_cycles; //Gross Hack;
} m_uart; /* internal uart */ } m_uart; /* internal uart */
/* Internal Ram */ /* Internal Ram */
@ -148,6 +147,8 @@ protected:
virtual void sfr_write(size_t offset, uint8_t data); virtual void sfr_write(size_t offset, uint8_t data);
virtual uint8_t sfr_read(size_t offset); virtual uint8_t sfr_read(size_t offset);
void transmit(bool state);
/* Memory spaces */ /* Memory spaces */
memory_access<16, 0, 0, ENDIANNESS_LITTLE>::cache m_program; memory_access<16, 0, 0, ENDIANNESS_LITTLE>::cache m_program;
memory_access< 9, 0, 0, ENDIANNESS_LITTLE>::specific m_data; memory_access< 9, 0, 0, ENDIANNESS_LITTLE>::specific m_data;
@ -156,10 +157,6 @@ protected:
devcb_read8::array<4> m_port_in_cb; devcb_read8::array<4> m_port_in_cb;
devcb_write8::array<4> m_port_out_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 */ /* DS5002FP */
struct { struct {
uint8_t previous_ta; /* Previous Timed Access value */ uint8_t previous_ta; /* Previous Timed Access value */
@ -197,9 +194,7 @@ protected:
void update_timer_t1(int cycles); void update_timer_t1(int cycles);
void update_timer_t2(int cycles); void update_timer_t2(int cycles);
void update_timers(int cycles); void update_timers(int cycles);
void serial_transmit(uint8_t data); void update_serial(int source);
void serial_receive();
void update_serial(int cycles);
void update_irq_prio(uint8_t ipl, uint8_t iph); void update_irq_prio(uint8_t ipl, uint8_t iph);
void execute_op(uint8_t op); void execute_op(uint8_t op);
void check_irqs(); void check_irqs();

View File

@ -978,5 +978,5 @@ OPHANDLER( xrl_a_r )
//illegal opcodes //illegal opcodes
OPHANDLER( illegal ) 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) 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_t(mconfig, ARCHIMEDES_KEYBOARD, tag, owner, clock)
, device_serial_interface(mconfig, *this)
, m_mcu(*this, "mcu") , m_mcu(*this, "mcu")
, m_kout(*this) , m_kout(*this)
, m_keyboard(*this, "ROW.%u", 0U) , m_keyboard(*this, "ROW.%u", 0U)
@ -250,10 +249,6 @@ void archimedes_keyboard_device::device_resolve_objects()
void archimedes_keyboard_device::device_start() 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); m_mouse_timer = timer_alloc(FUNC(archimedes_keyboard_device::update_mouse), this);
save_item(NAME(m_mouse_x)); 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_yref));
save_item(NAME(m_mouse_ydir)); save_item(NAME(m_mouse_ydir));
save_item(NAME(m_mux)); 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_yref = 1;
m_mouse_ydir = 1; m_mouse_ydir = 1;
m_mux = 0; m_mux = 0;
m_kin = false;
transmit_register_reset();
receive_register_reset();
m_mouse_timer->adjust(attotime::from_hz(1000 * 4), 0, attotime::from_hz(1000 * 4)); 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<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<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<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<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->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 ); 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) TIMER_CALLBACK_MEMBER(archimedes_keyboard_device::update_mouse)
{ {
// Mouse quadrature signals // Mouse quadrature signals
@ -418,10 +394,12 @@ TIMER_CALLBACK_MEMBER(archimedes_keyboard_device::update_mouse)
void archimedes_keyboard_device::leds_w(uint8_t data) void archimedes_keyboard_device::leds_w(uint8_t data)
{ {
// Keyboard LEDs // Keyboard LEDs
// --- --x- TXD
// --- -x-- Caps Lock // --- -x-- Caps Lock
// --- x--- Scroll Lock // --- x--- Scroll Lock
// --x ---- Num Lock // --x ---- Num Lock
m_kout(BIT(data, 1));
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
m_leds[i] = BIT(data, 2 + 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); 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()) m_kin = state;
transmit_register_setup(data);
} }

View File

@ -13,15 +13,13 @@
#include "cpu/mcs51/mcs51.h" #include "cpu/mcs51/mcs51.h"
#include "diserial.h"
//************************************************************************** //**************************************************************************
// TYPE DEFINITIONS // TYPE DEFINITIONS
//************************************************************************** //**************************************************************************
// ======================> archimedes_keyboard_device // ======================> archimedes_keyboard_device
class archimedes_keyboard_device : public device_t, public device_serial_interface class archimedes_keyboard_device : public device_t
{ {
public: public:
// construction/destruction // construction/destruction
@ -29,7 +27,7 @@ public:
auto kout() { return m_kout.bind(); } auto kout() { return m_kout.bind(); }
DECLARE_WRITE_LINE_MEMBER(kin_w) { rx_w(state); } DECLARE_WRITE_LINE_MEMBER(kin_w);
protected: protected:
// device-level overrides // device-level overrides
@ -42,15 +40,9 @@ protected:
virtual void device_add_mconfig(machine_config &config) override; virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const 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); TIMER_CALLBACK_MEMBER(update_mouse);
private: private:
void tx_w(uint8_t data);
uint8_t mouse_r(); uint8_t mouse_r();
void leds_w(uint8_t data); void leds_w(uint8_t data);
@ -70,6 +62,7 @@ private:
int16_t m_mouse_x; int16_t m_mouse_x;
int16_t m_mouse_y; int16_t m_mouse_y;
uint8_t m_mux; 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_p1_cb(*this),
m_out_p2_cb(*this), m_out_p2_cb(*this),
m_out_p3_cb(*this), m_out_p3_cb(*this),
//m_serial_w_cb(*this),
m_stream(nullptr), m_stream(nullptr),
m_cpu(*this, "cpu") 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_out_cb<2>().set(FUNC(qs1000_device::p2_w));
m_cpu->port_in_cb<3>().set(FUNC(qs1000_device::p3_r)); 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->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_p2_cb.resolve_safe();
m_out_p3_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)); save_item(NAME(m_wave_regs));
for (int i = 0; i < QS1000_CHANNELS; i++) 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 // 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 // device_reset - device-specific reset
//------------------------------------------------- //-------------------------------------------------

View File

@ -40,11 +40,9 @@ public:
auto p1_out() { return m_out_p1_cb.bind(); } auto p1_out() { return m_out_p1_cb.bind(); }
auto p2_out() { return m_out_p2_cb.bind(); } auto p2_out() { return m_out_p2_cb.bind(); }
auto p3_out() { return m_out_p3_cb.bind(); } auto p3_out() { return m_out_p3_cb.bind(); }
//auto serial_w() { return m_serial_w_cb.bind(); }
// external // external
i8052_device &cpu() const { return *m_cpu; } i8052_device &cpu() const { return *m_cpu; }
void serial_in(uint8_t data);
void set_irq(int state); void set_irq(int state);
void wave_w(offs_t offset, uint8_t data); void wave_w(offs_t offset, uint8_t data);
@ -101,14 +99,11 @@ private:
devcb_write8 m_out_p2_cb; devcb_write8 m_out_p2_cb;
devcb_write8 m_out_p3_cb; devcb_write8 m_out_p3_cb;
//devcb_write8 m_serial_w_cb;
// Internal state // Internal state
sound_stream * m_stream; sound_stream * m_stream;
required_device<i8052_device> m_cpu; required_device<i8052_device> m_cpu;
// Wavetable engine // Wavetable engine
uint8_t m_serial_data_in;
uint8_t m_wave_regs[18]; uint8_t m_wave_regs[18];
struct qs1000_channel struct qs1000_channel
@ -129,8 +124,6 @@ private:
}; };
qs1000_channel m_channels[QS1000_CHANNELS]; 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); data &= ~(0xff<<m_df_word_length);
m_rcv_byte_received = data; m_rcv_byte_received = data;
LOGMASKED(LOG_RX, "Receive data 0x%02x\n", m_rcv_byte_received);
if(m_df_parity == PARITY_NONE) if(m_df_parity == PARITY_NONE)
return; 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; 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) 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 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()); 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++; m_tra_bit_count_transmitted++;

View File

@ -133,6 +133,7 @@ Notes:
#include "machine/arm_iomd.h" #include "machine/arm_iomd.h"
#include "machine/i2cmem.h" #include "machine/i2cmem.h"
#include "sound/qs1000.h" #include "sound/qs1000.h"
#include "diserial.h"
#include "emupal.h" #include "emupal.h"
#include "screen.h" #include "screen.h"
#include "speaker.h" #include "speaker.h"
@ -140,11 +141,12 @@ Notes:
namespace { namespace {
class ssfindo_state : public driver_device class ssfindo_state : public driver_device, public device_serial_interface
{ {
public: public:
ssfindo_state(const machine_config &mconfig, device_type type, const char *tag) ssfindo_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag) : driver_device(mconfig, type, tag)
, device_serial_interface(mconfig, *this)
, m_maincpu(*this, "maincpu") , m_maincpu(*this, "maincpu")
, m_vidc(*this, "vidc") , m_vidc(*this, "vidc")
, m_iomd(*this, "iomd") , m_iomd(*this, "iomd")
@ -178,6 +180,7 @@ protected:
bool m_i2cmem_clock = false; bool m_i2cmem_clock = false;
virtual void tra_callback() override;
void sound_w(uint8_t data); void sound_w(uint8_t data);
private: private:
@ -209,6 +212,8 @@ private:
uint8_t iolines_r(); uint8_t iolines_r();
void iolines_w(uint8_t data); void iolines_w(uint8_t data);
bool m_flash_bank_select = false; bool m_flash_bank_select = false;
bool m_txd = true;
}; };
class tetfight_state : public ssfindo_state class tetfight_state : public ssfindo_state
@ -371,7 +376,7 @@ uint32_t ssfindo_state::randomized_r()
void ssfindo_state::sound_w(uint8_t data) 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 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_flashN));
save_item(NAME(m_i2cmem_clock)); save_item(NAME(m_i2cmem_clock));
save_item(NAME(m_flash_bank_select)); 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() 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 ) 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_device &qs1000(QS1000(config, "qs1000", 24_MHz_XTAL));
qs1000.set_external_rom(true); qs1000.set_external_rom(true);
// qs1000.p1_out().set(FUNC()); // TODO: writes something here // 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(0, "lspeaker", 0.25);
qs1000.add_route(1, "rspeaker", 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); void eolith_vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t eolith_vram_r(offs_t offset); uint16_t eolith_vram_r(offs_t offset);
void sound_p1_w(uint8_t data); void sound_p1_w(uint8_t data);
void sound_p3_w(uint8_t data);
uint8_t qs1000_p1_r(); uint8_t qs1000_p1_r();
void qs1000_p1_w(uint8_t data); 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); 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; int m_coin_counter_bit = 0;
std::unique_ptr<uint16_t[]> m_vram; std::unique_ptr<uint16_t[]> m_vram;
int m_buffer = 0; 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); 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); return m_sound_txd;
machine().scheduler().perfect_quantum(attotime::from_usec(250));
} }
@ -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_PROGRAM, &eolith_state::sound_prg_map);
m_soundcpu->set_addrmap(AS_IO, &eolith_state::sound_io_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->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") EEPROM_93C66_8BIT(config, "eeprom")
.erase_time(attotime::from_usec(250)) .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->set_external_rom(true);
m_qs1000->p1_in().set(FUNC(eolith_state::qs1000_p1_r)); m_qs1000->p1_in().set(FUNC(eolith_state::qs1000_p1_r));
m_qs1000->p1_out().set(FUNC(eolith_state::qs1000_p1_w)); 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(0, "lspeaker", 1.0);
m_qs1000->add_route(1, "rspeaker", 1.0); m_qs1000->add_route(1, "rspeaker", 1.0);
} }

View File

@ -200,7 +200,6 @@ protected:
u8 m_mcu_p1; u8 m_mcu_p1;
u8 m_mcu_p2; u8 m_mcu_p2;
u8 m_mcu_p3; u8 m_mcu_p3;
u8 m_mcu_uart;
u8 m_ppi_pa; u8 m_ppi_pa;
u8 m_ppi_pb; u8 m_ppi_pb;
@ -223,7 +222,6 @@ void rtpc_state::machine_start()
m_mcu_p1 = 0; m_mcu_p1 = 0;
m_mcu_p2 = 0; m_mcu_p2 = 0;
m_mcu_p3 = 0; m_mcu_p3 = 0;
m_mcu_uart = 0;
m_ppi_pa = 0; m_ppi_pa = 0;
m_ppi_pb = 0; m_ppi_pb = 0;
@ -375,6 +373,15 @@ void rtpc_state::mcu_port3_w(u8 data)
// 6 o kbd data out // 6 o kbd data out
// 7 o kbd clock 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->data_write_from_mb(BIT(data, 6));
m_kbd_con->clock_write_from_mb(BIT(data, 7)); 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_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_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->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)); 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 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 Once the system starts, all input must be in uppercase. Read the manual
to discover the special features of this Basic. 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 "emu.h"
#include "cpu/mcs51/mcs51.h" #include "cpu/mcs51/mcs51.h"
#include "machine/i8255.h" #include "machine/i8255.h"
#include "machine/terminal.h" #include "bus/rs232/terminal.h"
#include "bus/rs232/rs232.h"
#include "sound/spkrdev.h" #include "sound/spkrdev.h"
#include "speaker.h" #include "speaker.h"
@ -49,7 +39,7 @@ public:
basic52_state(const machine_config &mconfig, device_type type, const char *tag) basic52_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag) : driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu") , m_maincpu(*this, "maincpu")
, m_terminal(*this, "terminal") , m_serial(*this, "serial")
, m_speaker(*this, "speaker") , m_speaker(*this, "speaker")
{ } { }
@ -58,15 +48,15 @@ public:
private: private:
void machine_start() override; void machine_start() override;
void kbd_put(u8 data);
void port1_w(u8 data); void port1_w(u8 data);
uint8_t unk_r(); uint8_t port3_r();
uint8_t from_term(); void port3_w(u8 data);
void rx_w(int state);
void io_map(address_map &map); void io_map(address_map &map);
void mem_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<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; required_device<speaker_sound_device> m_speaker;
}; };
@ -82,9 +72,6 @@ void basic52_state::io_map(address_map &map)
map.unmap_value_high(); map.unmap_value_high();
map(0x0000, 0x7fff).ram(); map(0x0000, 0x7fff).ram();
// 8000-9FFF is reserved for a plug-in EPROM containing BASIC programs. // 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 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 INPUT_PORTS_END
uint8_t basic52_state::from_term() uint8_t basic52_state::port3_r()
{ {
return m_term_data; return m_port3;
}
uint8_t basic52_state::unk_r()
{
return m_term_data; // won't boot without this
} }
void basic52_state::port1_w(u8 data) 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)); m_speaker->level_w(BIT(data, 2));
} }
void basic52_state::port3_w(u8 data)
void basic52_state::kbd_put(u8 data)
{ {
m_maincpu->set_input_line(MCS51_RX_LINE, ASSERT_LINE); // preserve RXD
m_maincpu->set_input_line(MCS51_RX_LINE, CLEAR_LINE); m_port3 = (m_port3 & 1) | (data & ~1);
m_term_data = data;
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() 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) 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_PROGRAM, &basic52_state::mem_map);
m_maincpu->set_addrmap(AS_IO, &basic52_state::io_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_out_cb<1>().set(FUNC(basic52_state::port1_w));
m_maincpu->port_in_cb<3>().set(FUNC(basic52_state::unk_r)); m_maincpu->port_out_cb<3>().set(FUNC(basic52_state::port3_w));
m_maincpu->serial_tx_cb().set(m_terminal, FUNC(generic_terminal_device::write)); m_maincpu->port_in_cb<3>().set(FUNC(basic52_state::port3_r));
m_maincpu->serial_rx_cb().set(FUNC(basic52_state::from_term));
/* video hardware */ RS232_PORT(config, m_serial, serial_devices, "terminal");
GENERIC_TERMINAL(config, m_terminal, 0); m_serial->rxd_handler().set(FUNC(basic52_state::rx_w));
m_terminal->set_keyboard_callback(FUNC(basic52_state::kbd_put));
I8255(config, "ppi8255", 0); I8255(config, "ppi8255", 0);
@ -150,9 +143,8 @@ void basic52_state::basic52(machine_config &config)
I8052(config.replace(), m_maincpu, XTAL(11'059'200)); I8052(config.replace(), m_maincpu, XTAL(11'059'200));
m_maincpu->set_addrmap(AS_PROGRAM, &basic52_state::mem_map); m_maincpu->set_addrmap(AS_PROGRAM, &basic52_state::mem_map);
m_maincpu->set_addrmap(AS_IO, &basic52_state::io_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->port_out_cb<3>().set(FUNC(basic52_state::port3_w));
m_maincpu->serial_tx_cb().set(m_terminal, FUNC(generic_terminal_device::write)); m_maincpu->port_in_cb<3>().set(FUNC(basic52_state::port3_r));
m_maincpu->serial_rx_cb().set(FUNC(basic52_state::from_term));
} }
/* ROM definition */ /* ROM definition */

View File

@ -117,10 +117,6 @@ private:
void unk_ffa9_w(uint8_t data); void unk_ffa9_w(uint8_t data);
void tx(uint8_t data);
uint8_t rx();
uint8_t port0_r(); uint8_t port0_r();
void port0_w(u8 data); void port0_w(u8 data);
uint8_t port1_r(); uint8_t port1_r();
@ -520,28 +516,9 @@ uint32_t leapfrog_iquest_state::screen_update(screen_device &screen, bitmap_rgb3
return 0; 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? // doesn't help?
WRITE_LINE_MEMBER(leapfrog_iquest_state::rx_line_hack) 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) if (0)
{ {
// HACK: force past the wait loop if we're treating ff80 - ffff as RAM // 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 I8032(config, m_maincpu, 96000000/10); // unknown clock
m_maincpu->set_addrmap(AS_PROGRAM, &leapfrog_iquest_state::prog_map); m_maincpu->set_addrmap(AS_PROGRAM, &leapfrog_iquest_state::prog_map);
m_maincpu->set_addrmap(AS_IO, &leapfrog_iquest_state::ext_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_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_out_cb<0>().set(FUNC(leapfrog_iquest_state::port0_w));
m_maincpu->port_in_cb<1>().set(FUNC(leapfrog_iquest_state::port1_r)); 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); void write_odd(uint16_t data);
uint16_t read_odd(); uint16_t read_odd();
void vsync_int_ctrl(uint16_t data); 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(); uint8_t b_read();
void b_writ(uint8_t data); void b_writ(uint8_t data);
void strobe_w(uint8_t data); void strobe_w(uint8_t data);
@ -243,14 +241,13 @@ private:
uint8_t kbd_r(); uint8_t kbd_r();
uint32_t screen_update_maygayv1(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_maygayv1(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER(screen_vblank_maygayv1); DECLARE_WRITE_LINE_MEMBER(screen_vblank_maygayv1);
void data_from_i8031(uint8_t data); uint8_t sound_p1_r();
uint8_t data_to_i8031(); 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_irq_handler);
DECLARE_WRITE_LINE_MEMBER(duart_txa); DECLARE_WRITE_LINE_MEMBER(duart_txa);
void main_map(address_map &map); 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); void cpu_space_map(address_map &map);
required_device<cpu_device> m_maincpu; required_device<cpu_device> m_maincpu;
@ -273,7 +270,6 @@ private:
int m_vsync_latch_preset = 0; int m_vsync_latch_preset = 0;
uint8_t m_p1 = 0; uint8_t m_p1 = 0;
uint8_t m_p3 = 0; uint8_t m_p3 = 0;
int m_d68681_val = 0;
i82716_t m_i82716; i82716_t m_i82716;
output_finder<8 * 256> m_lamp; 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) if (!BIT(m_p3, 4))
{ return (ioport("REEL")->read()); // Reels???
case 1: else
{ return m_p1;
if ( !BIT(m_p3, 4) )
return (ioport("REEL")->read()); // Reels???
else
return 0;
}
case 3: return m_upd7759->busy_r() ? 0 : 0x08;
}
return 0;
} }
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) m_upd7759->port_w(data);//?
{
// 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;
}
} }
uint8_t maygayv1_state::sound_p3_r()
void maygayv1_state::sound_prg(address_map &map)
{ {
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) m_duart68681->rx_a_w(BIT(data, 1));
{ m_upd7759->reset_w(BIT(data, 2));
map(0x00, 0xff).rw(FUNC(maygayv1_state::mcu_r), FUNC(maygayv1_state::mcu_w)); 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) WRITE_LINE_MEMBER(maygayv1_state::duart_txa)
{ {
m_d68681_val = state; if (state)
m_soundcpu->set_input_line(MCS51_RX_LINE, ASSERT_LINE); // ? m_p3 |= 1;
} else
m_p3 &= ~1;
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);
} }
uint8_t maygayv1_state::b_read() 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); m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &maygayv1_state::cpu_space_map);
I8052(config, m_soundcpu, SOUND_CLOCK); I8052(config, m_soundcpu, SOUND_CLOCK);
m_soundcpu->set_addrmap(AS_PROGRAM, &maygayv1_state::sound_prg); m_soundcpu->port_in_cb<1>().set(FUNC(maygayv1_state::sound_p1_r));
m_soundcpu->set_addrmap(AS_DATA, &maygayv1_state::sound_data); m_soundcpu->port_out_cb<1>().set(FUNC(maygayv1_state::sound_p1_w));
m_soundcpu->set_addrmap(AS_IO, &maygayv1_state::sound_io); m_soundcpu->port_in_cb<3>().set(FUNC(maygayv1_state::sound_p3_r));
m_soundcpu->serial_tx_cb().set(FUNC(maygayv1_state::data_from_i8031)); m_soundcpu->port_out_cb<3>().set(FUNC(maygayv1_state::sound_p3_w));
m_soundcpu->serial_rx_cb().set(FUNC(maygayv1_state::data_to_i8031));
/* U25 ST 2 9148 EF68B21P */ /* U25 ST 2 9148 EF68B21P */
pia6821_device &pia(PIA6821(config, "pia", 0)); 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_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_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->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); MC68681(config, m_duart, 3.6864_MHz_XTAL);
m_duart->irq_cb().set(FUNC(micro3d_state::duart_irq_handler)); m_duart->irq_cb().set(FUNC(micro3d_state::duart_irq_handler));

View File

@ -177,8 +177,6 @@ private:
INTERRUPT_GEN_MEMBER(micro3d_vblank); INTERRUPT_GEN_MEMBER(micro3d_vblank);
TIMER_CALLBACK_MEMBER(mac_done_callback); TIMER_CALLBACK_MEMBER(mac_done_callback);
void micro3d_upd7759_w(uint8_t data); 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); DECLARE_WRITE_LINE_MEMBER(duart_irq_handler);
uint8_t duart_input_r(); uint8_t duart_input_r();
void duart_output_w(uint8_t data); 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) WRITE_LINE_MEMBER(micro3d_state::duart_txb)
{ {
m_m68681_tx0 = state; if (state)
m_audiocpu->set_input_line(MCS51_RX_LINE, ASSERT_LINE); m_sound_port_latch[3] |= 1;
// TODO: next line should be behind a timer callback which lasts one audiocpu clock cycle else
m_audiocpu->set_input_line(MCS51_RX_LINE, CLEAR_LINE); m_sound_port_latch[3] &= ~1;
}
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);
} }
/* /*
@ -463,8 +453,10 @@ void micro3d_state::micro3d_sound_p1_w(uint8_t data)
void micro3d_state::micro3d_sound_p3_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->set_rom_bank(BIT(data, 2));
m_upd7759->reset_w(!BIT(data, 4)); m_upd7759->reset_w(!BIT(data, 4));
} }

View File

@ -45,7 +45,7 @@ private:
virtual void machine_start() override; virtual void machine_start() override;
virtual void machine_reset() override; virtual void machine_reset() override;
void ctrl_w(uint8_t data); 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 led_strobe_w(uint8_t data);
void lcd_latch_w(uint8_t data); void lcd_latch_w(uint8_t data);
void lcd_control_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[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[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_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) void piggypas_state::ctrl_w(uint8_t data)
@ -83,9 +85,15 @@ void piggypas_state::ctrl_w(uint8_t data)
m_ctrl = 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) 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->set_addrmap(AS_IO, &piggypas_state::piggypas_io);
m_maincpu->port_out_cb<1>().set(FUNC(piggypas_state::led_strobe_w)); m_maincpu->port_out_cb<1>().set(FUNC(piggypas_state::led_strobe_w));
m_maincpu->port_in_cb<3>().set_ioport("IN2"); 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)); // m_maincpu->set_vblank_int("screen", FUNC(piggypas_state::irq0_line_hold));
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // DS1220AD NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // DS1220AD
@ -235,7 +243,6 @@ void piggypas_state::fidlstix(machine_config &config)
piggypas(config); piggypas(config);
m_maincpu->set_addrmap(AS_IO, &piggypas_state::fidlstix_io); 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_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<1>().set(FUNC(piggypas_state::lcd_latch_w));
m_maincpu->port_out_cb<3>().set(FUNC(piggypas_state::lcd_control_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() 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)); save_item(NAME(m_boot_press));
m_boot_timer = timer_alloc(FUNC(quizard_state::boot_press_tick), this); 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() void quizard_state::machine_reset()
{ {
cdi_state::machine_reset(); cdi_state::machine_reset();
m_mcu_rx_from_cpu = 0x00;
m_mcu_initial_byte = true;
m_boot_press = false; m_boot_press = false;
m_boot_timer->adjust(attotime::from_seconds(13), 1); 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) void quizard_state::mcu_rx_from_cpu(uint8_t data)
{ {
LOGMASKED(LOG_UART, "MCU receiving %02x from CPU\n", 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; transmit_register_setup(data);
m_mcu->set_input_line(MCS51_RX_LINE, ASSERT_LINE);
m_mcu->set_input_line(MCS51_RX_LINE, CLEAR_LINE);
} }
uint8_t quizard_state::mcu_p0_r() 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() uint8_t quizard_state::mcu_p3_r()
{ {
LOGMASKED(LOG_QUIZARD_READS, "%s: MCU Port 3 Read (%02x)\n", machine().describe_context(), 0x04); LOGMASKED(LOG_QUIZARD_READS, "%s: MCU Port 3 Read (%02x)\n", machine().describe_context(), m_mcu_p3);
return 0x04; return m_mcu_p3;
} }
void quizard_state::mcu_p0_w(uint8_t data) 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) void quizard_state::mcu_p3_w(uint8_t data)
{ {
LOGMASKED(LOG_QUIZARD_WRITES, "%s: MCU Port 3 Write (%02x)\n", machine().describe_context(), 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)); 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 * * 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_rtsn_callback().set(FUNC(quizard_state::mcu_rtsn_from_cpu));
m_maincpu->uart_tx_callback().set(FUNC(quizard_state::mcu_rx_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<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<1>().set(FUNC(quizard_state::mcu_p1_r));
m_mcu->port_in_cb<2>().set(FUNC(quizard_state::mcu_p2_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<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<2>().set(FUNC(quizard_state::mcu_p2_w));
m_mcu->port_out_cb<3>().set(FUNC(quizard_state::mcu_p3_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)); 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 * * Rom Load *
*************************/ *************************/

View File

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

View File

@ -156,6 +156,8 @@ private:
uint8_t port1_r(); uint8_t port1_r();
uint8_t port3_r(); uint8_t port3_r();
void serial_rxd(int state);
void dev_ctrl_reg_w(offs_t offset, uint8_t data); void dev_ctrl_reg_w(offs_t offset, uint8_t data);
uint8_t dev_keyb_ser_r(offs_t offset); 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) ); 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() 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)); m_modem->set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(m_modem));
RS232_PORT(config, m_serport, default_rs232_devices, nullptr); 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)); m_serport->set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(m_serport));
lineconnected = 0; 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_in_cb<1>().set(FUNC(mephisto_state::ay8910_read));
soundcpu.port_out_cb<1>().set(FUNC(mephisto_state::ay8910_write)); soundcpu.port_out_cb<1>().set(FUNC(mephisto_state::ay8910_write));
soundcpu.port_out_cb<3>().set(FUNC(mephisto_state::t0_t1_w)); soundcpu.port_out_cb<3>().set(FUNC(mephisto_state::t0_t1_w));
soundcpu.serial_rx_cb().set_constant(0); // from MUART
/* Sound */ /* Sound */
genpin_audio(config); genpin_audio(config);

View File

@ -10,8 +10,6 @@
#include "video/scn2674.h" #include "video/scn2674.h"
#include "emupal.h" #include "emupal.h"
#include "diserial.h"
class pcdx_video_device : public device_t, public device_gfx_interface class pcdx_video_device : public device_t, public device_gfx_interface
{ {
@ -78,12 +76,12 @@ private:
SCN2674_DRAW_CHARACTER_MEMBER(display_pixels); SCN2674_DRAW_CHARACTER_MEMBER(display_pixels);
}; };
class pcx_video_device : public pcdx_video_device, class pcx_video_device : public pcdx_video_device
public device_serial_interface
{ {
public: public:
pcx_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); pcx_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto txd_handler() { return m_txd_handler.bind(); } auto txd_handler() { return m_txd_handler.bind(); }
void rx_w(int state);
virtual void map(address_map &map) override; virtual void map(address_map &map) override;
uint8_t term_r(offs_t offset); uint8_t term_r(offs_t offset);
@ -103,18 +101,15 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override; virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override; virtual void device_add_mconfig(machine_config &config) override;
void tra_callback() override;
void rcv_complete() override;
private: private:
required_device<scn2672_device> m_crtc; required_device<scn2672_device> m_crtc;
required_region_ptr<uint8_t> m_charrom; required_region_ptr<uint8_t> m_charrom;
devcb_write_line m_txd_handler; 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(); uint8_t p3_r();
void tx_callback(uint8_t data); void p3_w(uint8_t data);
SCN2672_DRAW_CHARACTER_MEMBER(display_pixels); 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) : 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), pcdx_video_device(mconfig, PCX_VIDEO, tag, owner, clock),
device_serial_interface(mconfig, *this),
m_crtc(*this, "crtc"), m_crtc(*this, "crtc"),
m_charrom(*this, "char"), m_charrom(*this, "char"),
m_txd_handler(*this) 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_PROGRAM, &pcx_video_device::pcx_vid_map);
gfx.set_addrmap(AS_IO, &pcx_video_device::pcx_vid_io); gfx.set_addrmap(AS_IO, &pcx_video_device::pcx_vid_io);
gfx.port_out_cb<1>().set(FUNC(pcx_video_device::p1_w)); gfx.port_out_cb<1>().set(FUNC(pcx_video_device::p1_w));
gfx.serial_tx_cb().set(FUNC(pcx_video_device::tx_callback)); gfx.port_in_cb<3>().set(FUNC(pcx_video_device::p3_r));
gfx.serial_rx_cb().set(FUNC(pcx_video_device::rx_callback)); gfx.port_out_cb<3>().set(FUNC(pcx_video_device::p3_w));
// video hardware // video hardware
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); 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_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(); m_txd_handler.resolve_safe();
set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1);
set_rate(600);
decode_gfx(gfx_pcx); decode_gfx(gfx_pcx);
} }
@ -432,8 +428,6 @@ void pcx_video_device::device_reset()
{ {
m_term_key = 0; m_term_key = 0;
m_term_stat = 0; m_term_stat = 0;
transmit_register_reset();
receive_register_reset();
m_txd_handler(1); 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)); 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() m_txd_handler(BIT(data, 1));
{
receive_register_extract();
m_mcu->set_input_line(MCS51_RX_LINE, ASSERT_LINE);
m_mcu->set_input_line(MCS51_RX_LINE, CLEAR_LINE);
} }

View File

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

View File

@ -52,7 +52,6 @@ private:
void scan_load_w(u8 data); void scan_load_w(u8 data);
u8 scan_shift_r(); u8 scan_shift_r();
void lcd_control_w(u8 data); 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 prog_map(address_map &map);
void ext_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_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<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->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_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
screen.set_refresh_hz(50); screen.set_refresh_hz(50);

View File

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

View File

@ -44,7 +44,6 @@ Notes:
TODO: TODO:
- rewrite the mcs51.c serial I/O to replace this horrible, horrible hack
- dip switches - 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_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<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_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->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 // sound hardware
SPEAKER(config, "mono").front_center(); 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) : 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_t(mconfig, WANGPC_KEYBOARD, tag, owner, clock),
device_serial_interface(mconfig, *this),
m_maincpu(*this, I8051_TAG), m_maincpu(*this, I8051_TAG),
m_y(*this, "Y%u", 0), m_y(*this, "Y%u", 0),
m_txd_handler(*this), m_txd_handler(*this),
@ -389,11 +386,6 @@ void wangpc_keyboard_device::device_start()
m_txd_handler.resolve_safe(); m_txd_handler.resolve_safe();
m_leds.resolve(); 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_keylatch));
save_item(NAME(m_rxd)); save_item(NAME(m_rxd));
} }
@ -405,63 +397,10 @@ void wangpc_keyboard_device::device_start()
void wangpc_keyboard_device::device_reset() void wangpc_keyboard_device::device_reset()
{ {
receive_register_reset();
transmit_register_reset();
m_txd_handler(1); 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 - // write_rxd -
//------------------------------------------------- //-------------------------------------------------
@ -469,32 +408,6 @@ void wangpc_keyboard_device::rcv_complete()
WRITE_LINE_MEMBER(wangpc_keyboard_device::write_rxd) WRITE_LINE_MEMBER(wangpc_keyboard_device::write_rxd)
{ {
m_rxd = state; 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 - // kb_p3_w -
//------------------------------------------------- //-------------------------------------------------
@ -587,4 +510,5 @@ void wangpc_keyboard_device::kb_p3_w(uint8_t data)
*/ */
//if (LOG) logerror("P3 %02x\n", 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 "sound/sn76496.h"
#include "diserial.h"
//************************************************************************** //**************************************************************************
// TYPE DEFINITIONS // TYPE DEFINITIONS
@ -24,7 +22,7 @@
// ======================> wangpc_keyboard_device // ======================> wangpc_keyboard_device
class wangpc_keyboard_device : public device_t, public device_serial_interface class wangpc_keyboard_device : public device_t
{ {
public: public:
// construction/destruction // construction/destruction
@ -46,12 +44,6 @@ protected:
virtual void device_add_mconfig(machine_config &config) override; virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const 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: private:
required_device<i8051_device> m_maincpu; required_device<i8051_device> m_maincpu;
required_ioport_array<16> m_y; required_ioport_array<16> m_y;
@ -61,12 +53,10 @@ private:
uint8_t m_keylatch; uint8_t m_keylatch;
int m_rxd; int m_rxd;
uint8_t mcs51_rx_callback();
void mcs51_tx_callback(uint8_t data);
uint8_t kb_p1_r(); uint8_t kb_p1_r();
void kb_p1_w(uint8_t data); void kb_p1_w(uint8_t data);
void kb_p2_w(uint8_t data); void kb_p2_w(uint8_t data);
uint8_t kb_p3_r();
void kb_p3_w(uint8_t data); void kb_p3_w(uint8_t data);
}; };