mirror of
https://github.com/holub/mame
synced 2025-04-19 15:11:37 +03:00
machine/psion_asic2.cpp: Added indexed control registers.
machine/psion_asic3.cpp: Re-implemented as two variants, ASIC3 and earlier ASIC5 based PSU devices. machine/psion_asic5.cpp: Implemented UART and interrupts. machine/psion_asic9.cpp: Added PCM sound I/O.
This commit is contained in:
parent
8f98573380
commit
1af93b7319
@ -120,8 +120,7 @@ TIMER_CALLBACK_MEMBER(psion_asic1_device::frc)
|
||||
switch (--m_frc_count)
|
||||
{
|
||||
case 0x0000:
|
||||
m_frc_ovl ^= 1;
|
||||
m_frcovl_cb(m_frc_ovl);
|
||||
m_frcovl_cb(m_frc_ovl ^= 1);
|
||||
|
||||
m_a1_interrupt_status |= 0x20; // FrcExpired
|
||||
update_interrupts();
|
||||
@ -281,7 +280,7 @@ uint16_t psion_asic1_device::io_r(offs_t offset, uint16_t mem_mask)
|
||||
break;
|
||||
|
||||
case 0x06: // A1InterruptStatus
|
||||
data = m_a1_interrupt_status;
|
||||
data = m_a1_interrupt_status & m_a1_interrupt_mask;
|
||||
LOG("%s io_r: A1InterruptStatus => %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
|
||||
|
@ -36,6 +36,8 @@ psion_asic2_device::psion_asic2_device(const machine_config &mconfig, const char
|
||||
, m_buzvol_cb(*this)
|
||||
, m_dr_cb(*this)
|
||||
, m_col_cb(*this, 0xff)
|
||||
, m_read_pd_cb(*this, 0x00)
|
||||
, m_write_pd_cb(*this)
|
||||
, m_data_r(*this, 0x00)
|
||||
, m_data_w(*this)
|
||||
{
|
||||
@ -47,10 +49,14 @@ psion_asic2_device::psion_asic2_device(const machine_config &mconfig, const char
|
||||
|
||||
void psion_asic2_device::device_start()
|
||||
{
|
||||
m_a2_status = 0x01;
|
||||
m_a2_status = 0x00;
|
||||
|
||||
m_busy_timer = timer_alloc(FUNC(psion_asic2_device::busy), this);
|
||||
|
||||
save_item(NAME(m_a2_index));
|
||||
save_item(NAME(m_a2_icontrol0));
|
||||
save_item(NAME(m_a2_icontrol1));
|
||||
save_item(NAME(m_a2_iddr));
|
||||
save_item(NAME(m_a2_control1));
|
||||
save_item(NAME(m_a2_control2));
|
||||
save_item(NAME(m_a2_control3));
|
||||
@ -66,12 +72,17 @@ void psion_asic2_device::device_start()
|
||||
|
||||
void psion_asic2_device::device_reset()
|
||||
{
|
||||
m_a2_index = 0x00;
|
||||
m_a2_icontrol0 = 0x00;
|
||||
m_a2_icontrol1 = 0x00;
|
||||
m_a2_iddr = 0x00;
|
||||
m_a2_control1 = 0x00;
|
||||
m_a2_control2 = 0x00;
|
||||
m_a2_control3 = 0x00;
|
||||
m_a2_serial_data = 0x00;
|
||||
m_a2_serial_control = 0x00;
|
||||
m_a2_interrupt_status = 0x00;
|
||||
m_a2_status = 0x00;
|
||||
m_a2_channel_control = 0x00;
|
||||
}
|
||||
|
||||
@ -86,6 +97,16 @@ void psion_asic2_device::on_clr_w(int state)
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
void psion_asic2_device::sds_int_w(int state)
|
||||
{
|
||||
if (state)
|
||||
m_a2_status |= 0x20; // A2Sdis
|
||||
else
|
||||
m_a2_status &= ~0x20;
|
||||
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
void psion_asic2_device::dnmi_w(int state)
|
||||
{
|
||||
if (state)
|
||||
@ -112,7 +133,7 @@ void psion_asic2_device::reset_w(int state)
|
||||
|
||||
void psion_asic2_device::update_interrupts()
|
||||
{
|
||||
int irq = m_a2_status & 0x01;
|
||||
int irq = m_a2_status & 0x21;
|
||||
int nmi = BIT(m_a2_interrupt_status, 0, 2) & BIT(m_a2_control3, 4, 2);
|
||||
|
||||
m_int_cb(irq ? ASSERT_LINE : CLEAR_LINE);
|
||||
@ -136,6 +157,32 @@ uint8_t psion_asic2_device::io_r(offs_t offset)
|
||||
|
||||
switch (offset & 7)
|
||||
{
|
||||
case 0x00: // A2Index - Index Register
|
||||
data = m_a2_index;
|
||||
LOG("%s io_r: A2Index => %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
|
||||
case 0x01: // A2Control - Indexed Control Register
|
||||
switch (m_a2_index)
|
||||
{
|
||||
case 0: // A2IControl0 - System Control Register 0
|
||||
data = m_a2_icontrol0;
|
||||
LOG("%s io_r: A2IControl0 => %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
case 1: // A2IControl1 - Serial Clock Control Register
|
||||
data = m_a2_icontrol1;
|
||||
LOG("%s io_r: A2IControl1 => %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
case 2: // A2IWrite - Port Output Data Register (Write only)
|
||||
LOG("%s io_r: A2IWrite => %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
case 3: // A2IDDR - Port Data Direction Register
|
||||
data = m_a2_iddr;
|
||||
LOG("%s io_r: A2IDDR => %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x02: // A2External - External status register
|
||||
switch (m_a2_control1 & 0x0f)
|
||||
{
|
||||
@ -161,6 +208,9 @@ uint8_t psion_asic2_device::io_r(offs_t offset)
|
||||
// b2 SlaveDataValid - Slave data valid, 1 if valid frame arrived
|
||||
// b3 SlaveDataControl - Slave control or data frame, 1 if control frame
|
||||
// b4 SlaveDataOverrun - Slave data overrun, 1 if overrun
|
||||
// b5 LowBatteryNMI - Low battery NMI, 1 if NMI occurred
|
||||
// b6 0
|
||||
// b7 0
|
||||
data = m_a2_interrupt_status;
|
||||
LOG("%s io_r: A2InterruptStatus => %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
@ -172,6 +222,8 @@ uint8_t psion_asic2_device::io_r(offs_t offset)
|
||||
// b3 SerialClockState - 1 if slave clock is high
|
||||
// b4 SerialBusy - 1 while data serial controller is busy
|
||||
// b5 A2Sdis - 1 if slave data signal is high
|
||||
// b6 Ext - 1 in Extended Mode, 0 in Compatible Mode
|
||||
// b7 RevId - 1 if Revision 4 part
|
||||
data = m_a2_status;
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
@ -189,7 +241,8 @@ uint8_t psion_asic2_device::io_r(offs_t offset)
|
||||
break;
|
||||
|
||||
case 0x06: // A2KeyData - Keyboard poll register
|
||||
data = m_col_cb(m_a2_control1 & 0x0f);
|
||||
// Extended mode read from Port I/O lines
|
||||
data = m_read_pd_cb();
|
||||
LOG("%s io_r: A2KeyData => %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
|
||||
@ -209,6 +262,45 @@ void psion_asic2_device::io_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
switch (offset & 7)
|
||||
{
|
||||
case 0x00: // A2Index - Index Register
|
||||
// b0-b1 INDEX0,1 - Register 1 Index
|
||||
LOG("%s io_w: A2Index <= %02x\n", machine().describe_context(), data);
|
||||
m_a2_index = data & 3;
|
||||
break;
|
||||
|
||||
case 0x01: // A2Control - Indexed Control Register
|
||||
switch (m_a2_index)
|
||||
{
|
||||
case 0: // A2IControl0 - System Control Register 0
|
||||
// b0-b1 CLKSEL0-1 - Crystal Divider Select (0,1 - 23.04MHz divider = 3, 2 - 15.36MHz divider = 2, 3 - 7.68MHz divider = 1)
|
||||
// b2 CHEN3 - Serial Channel 3 is enabled when this bit is set
|
||||
// b3 CHEN4 - Serial Channel 4 is enabled when this bit is set
|
||||
// b4 CHEN6 - Serial Channel 6 is enabled when this bit is set
|
||||
// b5 EXONOFF - EXON & SCKS witch-on is disabled when this bit is set
|
||||
// b6 INTSEL - Interrupt Source Select (0 - Frame received, 1 - SDIS direct)
|
||||
LOG("%s io_w: A2IControl0 => %02x\n", machine().describe_context(), data);
|
||||
m_a2_icontrol0 = data;
|
||||
break;
|
||||
case 1: // A2IControl1 - Serial Clock Control Register
|
||||
// b0 CKEN1 - Serial Channel 1 continuous clock is enabled when this bit is set
|
||||
// b1 CKEN2 - Serial Channel 2 continuous clock is enabled when this bit is set
|
||||
// b2 CKEN3 - Serial Channel 3 continuous clock is enabled when this bit is set
|
||||
// b3 CKEN4 - Serial Channel 4 continuous clock is enabled when this bit is set
|
||||
LOG("%s io_w: A2IControl1 => %02x\n", machine().describe_context(), data);
|
||||
m_a2_icontrol1 = data;
|
||||
break;
|
||||
case 2: // A2IWrite - Port Output Data Register
|
||||
LOG("%s io_w: A2IWrite => %02x\n", machine().describe_context(), data);
|
||||
m_write_pd_cb(data & m_a2_iddr);
|
||||
break;
|
||||
case 3: // A2IDDR - Port Data Direction Register
|
||||
// b0-b7 DO0-7 - 0 = PD* is and input, 1 = PD* is an output
|
||||
LOG("%s io_w: A2IDDR => %02x\n", machine().describe_context(), data);
|
||||
m_a2_iddr = data;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x02: // A2Control1 - Control register 1
|
||||
// b0-b3 KeyScan - Values 0-15 drive the keyboard poll columns
|
||||
// b4-b5 SerialClockRate - Sets the clock frequency for channels 1-4 and 7 as below:
|
||||
@ -217,7 +309,6 @@ void psion_asic2_device::io_w(offs_t offset, uint8_t data)
|
||||
// 3 = ClockRateFast 3.84 MHz
|
||||
LOG("%s io_w: A2Control1 <= %02x\n", machine().describe_context(), data);
|
||||
m_a2_control1 = data;
|
||||
//m_a2_external = m_col_cb(data & 0x0f);
|
||||
break;
|
||||
|
||||
case 0x03: // A2Control2 - Control register 2
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
auto buzvol_cb() { return m_buzvol_cb.bind(); }
|
||||
auto dr_cb() { return m_dr_cb.bind(); }
|
||||
auto col_cb() { return m_col_cb.bind(); }
|
||||
auto read_pd_cb() { return m_read_pd_cb.bind(); }
|
||||
auto write_pd_cb() { return m_write_pd_cb.bind(); }
|
||||
|
||||
template <unsigned N> auto data_r() { static_assert(N < 8); return m_data_r[N].bind(); }
|
||||
template <unsigned N> auto data_w() { static_assert(N < 8); return m_data_w[N].bind(); }
|
||||
@ -40,6 +42,7 @@ public:
|
||||
void io_w(offs_t offset, uint8_t data);
|
||||
|
||||
void on_clr_w(int state);
|
||||
void sds_int_w(int state);
|
||||
void dnmi_w(int state);
|
||||
void frcovl_w(int state);
|
||||
void reset_w(int state);
|
||||
@ -51,6 +54,10 @@ protected:
|
||||
private:
|
||||
void update_interrupts();
|
||||
|
||||
uint8_t m_a2_index;
|
||||
uint8_t m_a2_icontrol0;
|
||||
uint8_t m_a2_icontrol1;
|
||||
uint8_t m_a2_iddr;
|
||||
uint8_t m_a2_control1;
|
||||
uint8_t m_a2_control2;
|
||||
uint8_t m_a2_control3;
|
||||
@ -59,7 +66,6 @@ private:
|
||||
uint8_t m_a2_interrupt_status;
|
||||
uint8_t m_a2_status;
|
||||
uint8_t m_a2_channel_control;
|
||||
//uint8_t m_a2_external;
|
||||
|
||||
devcb_write_line m_int_cb;
|
||||
devcb_write_line m_nmi_cb;
|
||||
@ -68,6 +74,8 @@ private:
|
||||
devcb_write_line m_buzvol_cb;
|
||||
devcb_write_line m_dr_cb;
|
||||
devcb_read8 m_col_cb;
|
||||
devcb_read8 m_read_pd_cb;
|
||||
devcb_write8 m_write_pd_cb;
|
||||
|
||||
devcb_read8::array<8> m_data_r;
|
||||
devcb_write16::array<8> m_data_w;
|
||||
|
@ -2,7 +2,7 @@
|
||||
// copyright-holders:Nigel Barnes
|
||||
/******************************************************************************
|
||||
|
||||
Psion ASIC3
|
||||
Psion ASIC3/PS34
|
||||
|
||||
MC and HC power supplies are based on a full custom liner ASIC known as ASIC3.
|
||||
This custom chip is manufactured by Maxim and has the Maxim part number MAX616.
|
||||
@ -21,18 +21,28 @@
|
||||
#include "logmacro.h"
|
||||
|
||||
|
||||
DEFINE_DEVICE_TYPE(PSION_ASIC3, psion_asic3_device, "psion_asic3", "Psion ASIC3")
|
||||
DEFINE_DEVICE_TYPE(PSION_PSU_ASIC3, psion_psu_asic3_device, "psion_psu_asic3", "Psion PSU (ASIC3)")
|
||||
DEFINE_DEVICE_TYPE(PSION_PSU_ASIC5, psion_psu_asic5_device, "psion_psu_asic5", "Psion PSU (ASIC5)")
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
psion_asic3_device::psion_asic3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, PSION_ASIC3, tag, owner, clock)
|
||||
psion_asic3_device::psion_asic3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, m_adin_cb(*this, 0)
|
||||
{
|
||||
}
|
||||
|
||||
psion_psu_asic5_device::psion_psu_asic5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: psion_asic3_device(mconfig, PSION_PSU_ASIC5, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
psion_psu_asic3_device::psion_psu_asic3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: psion_asic3_device(mconfig, PSION_PSU_ASIC3, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
@ -40,7 +50,9 @@ psion_asic3_device::psion_asic3_device(const machine_config &mconfig, const char
|
||||
|
||||
void psion_asic3_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_a3_status));
|
||||
save_item(NAME(m_a3_control1));
|
||||
save_item(NAME(m_a3_control2));
|
||||
save_item(NAME(m_a3_control3));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -49,7 +61,9 @@ void psion_asic3_device::device_start()
|
||||
|
||||
void psion_asic3_device::device_reset()
|
||||
{
|
||||
m_a3_status = 0x00;
|
||||
m_a3_control1 = 0x00;
|
||||
m_a3_control2 = 0x00;
|
||||
m_a3_control3 = 0x00;
|
||||
}
|
||||
|
||||
|
||||
@ -57,21 +71,16 @@ void psion_asic3_device::device_reset()
|
||||
// READ/WRITE HANDLERS
|
||||
//**************************************************************************
|
||||
|
||||
void psion_asic3_device::data_w(uint16_t data)
|
||||
void psion_psu_asic5_device::data_w(uint16_t data)
|
||||
{
|
||||
switch (data & 0x300)
|
||||
{
|
||||
case NULL_FRAME:
|
||||
device_reset();
|
||||
break;
|
||||
|
||||
case CONTROL_FRAME:
|
||||
m_sibo_control = data & 0xff;
|
||||
|
||||
switch (m_sibo_control & 0xc0)
|
||||
{
|
||||
case 0x80: // SerialWrite
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_FRAME:
|
||||
@ -103,26 +112,23 @@ void psion_asic3_device::data_w(uint16_t data)
|
||||
m_a3_control2 = data;
|
||||
break;
|
||||
|
||||
case 0x04: // A3Dummy1
|
||||
LOG("%s data_w: A3Dummy1 register %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
|
||||
case 0x07: // A3Control3
|
||||
// b0 xDummy1
|
||||
// b0 0
|
||||
// b1 OffEnable
|
||||
// b2 AdcReadHighEnable
|
||||
// b3-b7 0
|
||||
LOG("%s data_w: A3Control3 register %02x\n", machine().describe_context(), data);
|
||||
m_a3_control3 = data;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG("%s data_w: Unhandled register %02x\n", machine().describe_context(), m_sibo_control & 0x0f);
|
||||
LOG("%s data_w: unknown control %02x data %02x\n", machine().describe_context(), m_sibo_control, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t psion_asic3_device::data_r()
|
||||
uint8_t psion_psu_asic5_device::data_r()
|
||||
{
|
||||
uint8_t data = 0x00;
|
||||
|
||||
@ -137,6 +143,7 @@ uint8_t psion_asic3_device::data_r()
|
||||
switch (m_sibo_control & 0x0f)
|
||||
{
|
||||
case 0x00: // A3Adc
|
||||
{
|
||||
// A3AdcLsbR
|
||||
// b0-b6 OtherBits
|
||||
// b7 InvertedBit
|
||||
@ -144,29 +151,148 @@ uint8_t psion_asic3_device::data_r()
|
||||
// b0-b3 AdcBits
|
||||
// b4 Overrange
|
||||
// b5 Polarity
|
||||
uint16_t data_in = 0;
|
||||
switch (BIT(m_a3_control2, 6, 2)) // AnalogueMultiplex
|
||||
{
|
||||
case 0: // AdcDigitizer
|
||||
data_in = m_adin_cb();
|
||||
break;
|
||||
case 1: // AdcVh
|
||||
break;
|
||||
case 2: // AdcMainBattery
|
||||
data_in = 0x7ff;
|
||||
break;
|
||||
case 3: // AdcLithiumBattery
|
||||
data_in = 0x7ff;
|
||||
break;
|
||||
}
|
||||
if (BIT(m_a3_control3, 2)) // AdcReadHighEnable
|
||||
data = BIT(m_adin_cb(), 8, 4);
|
||||
data = BIT(data_in, 8, 4);
|
||||
else
|
||||
data = (m_adin_cb() & 0xff) ^ 0x80;
|
||||
LOG("%s data_r: A3Adc register %02x\n", machine().describe_context(), data);
|
||||
data = (data_in & 0xff) ^ 0x80;
|
||||
LOG("%s data_r: A3Adc %d register %02x\n", machine().describe_context(), BIT(m_a3_control2, 6, 2), data);
|
||||
break;
|
||||
|
||||
}
|
||||
case 0x0d: // A3Status
|
||||
// b0-b2 Admsb
|
||||
// b3 Nc
|
||||
// b4 Penup
|
||||
// b5 Vhready
|
||||
// b6 ColdStart
|
||||
// b7 PowerFail
|
||||
|
||||
// b0 ColdStart
|
||||
// b1 PowerFail
|
||||
data = 0x40;
|
||||
data = 0x00; // ColdStart
|
||||
LOG("%s data_r: A3Status register %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG("%s data_r: Unhandled register %02x\n", machine().describe_context(), m_sibo_control & 0x0f);
|
||||
LOG("%s data_r: unknown control %02x data %02x\n", machine().describe_context(), m_sibo_control, data);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void psion_psu_asic3_device::data_w(uint16_t data)
|
||||
{
|
||||
switch (data & 0x300)
|
||||
{
|
||||
case NULL_FRAME:
|
||||
device_reset();
|
||||
break;
|
||||
|
||||
case CONTROL_FRAME:
|
||||
m_sibo_control = data & 0xff;
|
||||
break;
|
||||
|
||||
case DATA_FRAME:
|
||||
data &= 0xff;
|
||||
switch (m_sibo_control & 0x0f)
|
||||
{
|
||||
case 0x00: // PS34W_CONTROL
|
||||
// b0-b1 Vhpower
|
||||
// b2 Vh
|
||||
// b3 Vcc5
|
||||
// b4 Vee2
|
||||
// b5 Vcc4
|
||||
// b6 Vee1
|
||||
// b7 Vcc3
|
||||
LOG("%s data_w: PS34W_CONTROL %02x\n", machine().describe_context(), data);
|
||||
m_a3_control1 = data;
|
||||
break;
|
||||
|
||||
case 0x01: // PS34W_DTOA
|
||||
// b0-b4 Dac
|
||||
// b5-b6 Adcsel
|
||||
// b7 Ncc
|
||||
LOG("%s data_w: PS34W_DTOA %02x\n", machine().describe_context(), data);
|
||||
m_a3_control2 = data;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG("%s data_w: unknown control %02x data %02x\n", machine().describe_context(), m_sibo_control, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t psion_psu_asic3_device::data_r()
|
||||
{
|
||||
uint8_t data = 0x00;
|
||||
|
||||
switch (m_sibo_control & 0xc0)
|
||||
{
|
||||
case 0x40: // SerialSelect
|
||||
if (m_sibo_control == 0x43) // A3SelectId
|
||||
data = 0x80; // A3InfoByte
|
||||
break;
|
||||
|
||||
case 0xc0: // SerialRead
|
||||
switch (m_sibo_control & 0x0f)
|
||||
{
|
||||
case 0x00: // PS34R_ADC
|
||||
switch (BIT(m_a3_control2, 5, 2)) // Adcsel
|
||||
{
|
||||
case 0: // ADCSEL_ADCIN
|
||||
data = m_adin_cb() & 0xff;
|
||||
break;
|
||||
case 1: // ADCSEL_VIN
|
||||
data = 0xff;
|
||||
break;
|
||||
case 2: // ADCSEL_VH
|
||||
break;
|
||||
case 3: // ADCSEL_VBATT
|
||||
data = 0xff;
|
||||
break;
|
||||
}
|
||||
LOG("%s data_r: PS34R_ADC %d %02x\n", machine().describe_context(), BIT(m_a3_control2, 5, 2), data);
|
||||
break;
|
||||
|
||||
case 0x01: // PS34R_STATUS
|
||||
// b0-b2 Admsb
|
||||
// b3 Nc
|
||||
// b4 Penup
|
||||
// b5 Vhready
|
||||
// b6 ColdStart
|
||||
// b7 PowerFail
|
||||
switch (BIT(m_a3_control2, 5, 2)) // Adcsel
|
||||
{
|
||||
case 0: // ADCSEL_ADCIN
|
||||
data = BIT(m_adin_cb(), 8, 3);
|
||||
break;
|
||||
case 1: // ADCSEL_VIN
|
||||
data = 0x07;
|
||||
break;
|
||||
case 2: // ADCSEL_VH
|
||||
break;
|
||||
case 3: // ADCSEL_VBATT
|
||||
data = 0x07;
|
||||
break;
|
||||
}
|
||||
data |= 0x40; // ColdStart
|
||||
LOG("%s data_r: PS34R_STATUS %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG("%s data_r: unknown control %02x data %02x\n", machine().describe_context(), m_sibo_control, data);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -2,7 +2,7 @@
|
||||
// copyright-holders:Nigel Barnes
|
||||
/******************************************************************************
|
||||
|
||||
Psion ASIC3
|
||||
Psion ASIC3/PS34
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
@ -21,19 +21,18 @@
|
||||
class psion_asic3_device : public device_t
|
||||
{
|
||||
public:
|
||||
psion_asic3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
// callbacks
|
||||
auto adin_cb() { return m_adin_cb.bind(); }
|
||||
|
||||
void data_w(uint16_t data);
|
||||
uint8_t data_r();
|
||||
virtual void data_w(uint16_t data) { }
|
||||
virtual uint8_t data_r() { return 0x00; }
|
||||
|
||||
protected:
|
||||
psion_asic3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
static constexpr uint16_t NULL_FRAME = 0x000;
|
||||
static constexpr uint16_t CONTROL_FRAME = 0x100;
|
||||
static constexpr uint16_t DATA_FRAME = 0x200;
|
||||
@ -44,11 +43,37 @@ private:
|
||||
uint8_t m_a3_control1;
|
||||
uint8_t m_a3_control2;
|
||||
uint8_t m_a3_control3;
|
||||
uint8_t m_a3_status;
|
||||
};
|
||||
|
||||
|
||||
// ======================> psion_psu_asic5_device
|
||||
|
||||
class psion_psu_asic5_device : public psion_asic3_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
psion_psu_asic5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
virtual void data_w(uint16_t data) override;
|
||||
virtual uint8_t data_r() override;
|
||||
};
|
||||
|
||||
|
||||
// ======================> psion_psu_asic3_device
|
||||
|
||||
class psion_psu_asic3_device : public psion_asic3_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
psion_psu_asic3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
virtual void data_w(uint16_t data) override;
|
||||
virtual uint8_t data_r() override;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(PSION_ASIC3, psion_asic3_device)
|
||||
DECLARE_DEVICE_TYPE(PSION_PSU_ASIC3, psion_psu_asic3_device)
|
||||
DECLARE_DEVICE_TYPE(PSION_PSU_ASIC5, psion_psu_asic5_device)
|
||||
|
||||
#endif // MAME_MACHINE_PSION_ASIC3_H
|
||||
|
@ -82,6 +82,7 @@ void psion_asic4_device::data_w(uint16_t data)
|
||||
switch (data & 0x300)
|
||||
{
|
||||
case NULL_FRAME:
|
||||
device_reset();
|
||||
break;
|
||||
|
||||
case CONTROL_FRAME:
|
||||
|
@ -22,16 +22,13 @@
|
||||
Peripheral Mode Type
|
||||
0 x x 0 x x x x 1 RS232 port
|
||||
x x 0 x x x 1 x Centronics (Parallel) port
|
||||
x x 0 x x 1 x X ROM
|
||||
x x 0 x 1 x x X Magnetic Card Reader
|
||||
x x 0 x x 1 x x ROM
|
||||
x x 0 x 1 x x x Magnetic Card Reader
|
||||
x x 0 0 x x x x Barcode reader
|
||||
x x 0 1 x x x x USA modem
|
||||
x 1 0 x x x x x Modem
|
||||
1 x 0 x x x x x RS232 TTL
|
||||
|
||||
TODO:
|
||||
- implement UART
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
@ -55,11 +52,20 @@ psion_asic5_device::psion_asic5_device(const machine_config &mconfig, const char
|
||||
, m_mode(~uint8_t(0))
|
||||
, m_in_a_handler(*this, 0)
|
||||
, m_in_b_handler(*this, 0)
|
||||
, m_in_c_handler(*this, 0)
|
||||
, m_out_a_handler(*this)
|
||||
, m_out_b_handler(*this)
|
||||
, m_out_c_handler(*this)
|
||||
, m_out_d_handler(*this)
|
||||
, m_out_e_handler(*this)
|
||||
, m_out_cs_handler(*this)
|
||||
, m_int_handler(*this)
|
||||
, m_txd_handler(*this)
|
||||
, m_rts_handler(*this)
|
||||
, m_dtr_handler(*this)
|
||||
, m_rxd(0)
|
||||
, m_cts(0)
|
||||
, m_dsr(0)
|
||||
, m_dcd(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -84,8 +90,11 @@ void psion_asic5_device::device_start()
|
||||
save_item(NAME(m_port_b_counter));
|
||||
save_item(NAME(m_port_b_latch));
|
||||
save_item(NAME(m_port_b_mode));
|
||||
save_item(NAME(m_port_dc_writes));
|
||||
save_item(NAME(m_port_dc_select));
|
||||
save_item(NAME(m_int_mask));
|
||||
save_item(NAME(m_int_status));
|
||||
save_item(NAME(m_control));
|
||||
save_item(NAME(m_bdr));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -97,6 +106,50 @@ void psion_asic5_device::device_reset()
|
||||
m_port_b_counter = 0x00;
|
||||
m_port_b_latch = 0x00;
|
||||
m_port_b_mode = 0x00;
|
||||
m_port_dc_select = false;
|
||||
m_int_mask = 0x00;
|
||||
m_int_status = 0x02; // UART transmitter empty
|
||||
m_control = 0x00;
|
||||
m_bdr = 0xffff;
|
||||
|
||||
receive_register_reset();
|
||||
transmit_register_reset();
|
||||
}
|
||||
|
||||
|
||||
void psion_asic5_device::update_interrupts()
|
||||
{
|
||||
int irq = m_int_status & m_int_mask;
|
||||
|
||||
m_int_handler(irq ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
|
||||
void psion_asic5_device::rcv_callback()
|
||||
{
|
||||
if (BIT(m_port_b_mode, 0)) // UART enabled
|
||||
receive_register_update_bit(m_rxd);
|
||||
}
|
||||
|
||||
void psion_asic5_device::rcv_complete()
|
||||
{
|
||||
if (is_receive_framing_error() || is_receive_parity_error())
|
||||
m_int_status |= 0x04;
|
||||
|
||||
m_int_status |= 0x01;
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
void psion_asic5_device::tra_callback()
|
||||
{
|
||||
if (BIT(m_port_b_mode, 0)) // UART enabled
|
||||
m_txd_handler(transmit_register_get_data_bit());
|
||||
}
|
||||
|
||||
void psion_asic5_device::tra_complete()
|
||||
{
|
||||
m_int_status |= 0x02;
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
|
||||
@ -109,6 +162,7 @@ void psion_asic5_device::data_w(uint16_t data)
|
||||
switch (data & 0x300)
|
||||
{
|
||||
case NULL_FRAME:
|
||||
device_reset();
|
||||
break;
|
||||
|
||||
case CONTROL_FRAME:
|
||||
@ -118,7 +172,7 @@ void psion_asic5_device::data_w(uint16_t data)
|
||||
{
|
||||
case 0x80: // SerialWrite
|
||||
if (m_sibo_control == 0x93) // Multi Port D and C writes
|
||||
m_port_dc_writes = 0;
|
||||
m_port_dc_select = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -138,61 +192,110 @@ void psion_asic5_device::data_w(uint16_t data)
|
||||
|
||||
case 0x01: // Port B write data
|
||||
LOG("%s data_w: Port B write data %02x\n", machine().describe_context(), data);
|
||||
if (BIT(m_port_b_mode, 1, 2) == 1) // Latch mode
|
||||
if (BIT(m_port_b_mode, 1, 2) == 1 && !BIT(m_control, 3)) // Latch mode
|
||||
{
|
||||
m_out_b_handler(m_port_b_latch = data);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x02: // Port B control
|
||||
// b0 0 Memory mode, 1 Peripheral mode - enables UART
|
||||
// b1 Port B mode
|
||||
// b2 Port B mode
|
||||
// b3 0 Normal mode, 1 Test mode
|
||||
// b4 Not used
|
||||
// b5 Not used
|
||||
// b6 Not used
|
||||
// b7 Not used
|
||||
//
|
||||
// Port B mode
|
||||
// b2 b1 Mode
|
||||
// 0 0 Counter mode
|
||||
// 0 1 Latch mode
|
||||
// 1 0 Baud rate out on port B
|
||||
// 1 1 Test bus output on port B
|
||||
LOG("%s data_w: Port B mode %02x\n", machine().describe_context(), data);
|
||||
m_port_b_mode = data;
|
||||
break;
|
||||
|
||||
case 0x03: // Port D and C write data
|
||||
if (m_port_dc_writes)
|
||||
switch (BIT(m_port_b_mode, 0))
|
||||
{
|
||||
LOG("%s data_w: Port C write data %02x\n", machine().describe_context(), data);
|
||||
m_out_c_handler(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("%s data_w: Port D write data %02x\n", machine().describe_context(), data);
|
||||
m_out_d_handler(data);
|
||||
if (BIT(m_port_b_mode, 1, 2) == 0) // Counter mode
|
||||
case 0:
|
||||
if (m_port_dc_select)
|
||||
{
|
||||
m_out_b_handler(m_port_b_counter = 0);
|
||||
LOG("%s data_w: Port C write data %02x\n", machine().describe_context(), data);
|
||||
m_out_c_handler(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("%s data_w: Port D write data %02x\n", machine().describe_context(), data);
|
||||
m_out_d_handler(data);
|
||||
if (BIT(m_port_b_mode, 1, 2) == 0) // Counter mode
|
||||
{
|
||||
m_out_b_handler(m_port_b_counter = 0);
|
||||
}
|
||||
}
|
||||
m_port_dc_select = true;
|
||||
break;
|
||||
case 1: // UART enabled
|
||||
m_rts_handler(BIT(data, 1));
|
||||
m_dtr_handler(BIT(data, 2));
|
||||
break;
|
||||
}
|
||||
m_port_dc_writes++;
|
||||
break;
|
||||
|
||||
case 0x06: // Interrupt mask write
|
||||
// b0 UART - UART character received
|
||||
// b1 UART - UART transmitter empty
|
||||
// b2 UART - UART error or modem line status change
|
||||
// b3 PC7 - Barcode switch/general interrupt
|
||||
// b4 SR - Synchronous port1 character received
|
||||
// b5 SR - Synchronous port2 character received
|
||||
// b6 PC4 - Barcode data/general interrupt
|
||||
// b7 PA4 - Centronics busy low/general interrupt
|
||||
LOG("%s data_w: Interrupt mask write %02x\n", machine().describe_context(), data);
|
||||
m_int_mask = data;
|
||||
update_interrupts();
|
||||
break;
|
||||
|
||||
case 0x07: // Control register
|
||||
LOG("%s data_w: Control register %02x\n", machine().describe_context(), data);
|
||||
m_out_e_handler(data & 7);
|
||||
m_control = data;
|
||||
m_out_cs_handler(data & 7);
|
||||
break;
|
||||
|
||||
case 0x08: // UART Control register
|
||||
// b0 Generate break character
|
||||
// b1 Character length 1
|
||||
// b2 Character length 2
|
||||
// b3 Parity enabled if set
|
||||
// b4 Odd parity if, even if clear
|
||||
// b5 Set for two stop bits, clear for one
|
||||
// b6 Not used
|
||||
// b7 Not used
|
||||
LOG("%s data_w: UART Control register %02x\n", machine().describe_context(), data);
|
||||
set_data_frame(1, 5 + BIT(data, 1, 2), BIT(data, 3) ? (BIT(data, 4) ? PARITY_ODD : PARITY_EVEN) : PARITY_NONE, BIT(data, 5) ? STOP_BITS_2 : STOP_BITS_1);
|
||||
receive_register_reset();
|
||||
transmit_register_reset();
|
||||
break;
|
||||
|
||||
case 0x09: // UART Transmit holding register
|
||||
LOG("%s data_w: UART Transmit holding register %02x\n", machine().describe_context(), data);
|
||||
transmit_register_setup(data);
|
||||
m_int_status &= ~0x02;
|
||||
update_interrupts();
|
||||
break;
|
||||
|
||||
case 0x0a: // UART Baud rate LSB
|
||||
LOG("%s data_w: UART Baud rate LSB %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
|
||||
case 0x0b: // UART Baud rate MSB
|
||||
LOG("%s data_w: UART Baud rate MSB %02x\n", machine().describe_context(), data);
|
||||
case 0x0a:
|
||||
case 0x0b: // UART Baud rate
|
||||
switch (m_sibo_control & 1)
|
||||
{
|
||||
case 0: m_bdr = (m_bdr & 0xff00) | (data << 0); break; // LSB
|
||||
case 1: m_bdr = (m_bdr & 0x00ff) | (data << 8); break; // MSB
|
||||
}
|
||||
LOG("%s data_w: UART Baud rate divisor %04x, Baud rate %d\n", machine().describe_context(), m_bdr, clock() / 16 / (1 - m_bdr));
|
||||
set_rate(clock() / 16 / (1 - m_bdr));
|
||||
break;
|
||||
|
||||
case 0x0c: // Port 1 and 2 reset
|
||||
@ -258,16 +361,39 @@ uint8_t psion_asic5_device::data_r()
|
||||
LOG("%s data_r: Interrupt mask read %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
|
||||
case 0x07: // Interrupt status read
|
||||
data = m_int_status & m_int_mask;
|
||||
LOG("%s data_r: Interrupt status read %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
|
||||
case 0x08: // UART Status register
|
||||
data |= is_transmit_register_empty() ? 1 << 3 : 0;
|
||||
data |= is_receive_framing_error() ? 1 << 6 : 0;
|
||||
data |= is_receive_parity_error() ? 1 << 7 : 0;
|
||||
// b0 State of the CTS line (PA1)
|
||||
// b1 State of the DSR line (PA2)
|
||||
// b2 State of the DCD line (PA3)
|
||||
// b3 Transmitter buffer empty
|
||||
// b4 Transmitter busy
|
||||
// b5 Receive data waiting
|
||||
// b6 Overrun or framing error
|
||||
// b7 Parity error
|
||||
data |= m_cts << 0;
|
||||
data |= m_dsr << 1;
|
||||
data |= m_dcd << 2;
|
||||
data |= is_transmit_register_empty() ? 1 << 3 : 0;
|
||||
data |= !is_transmit_register_empty() ? 1 << 4 : 0;
|
||||
data |= is_receive_register_full() ? 1 << 5 : 0;
|
||||
data |= is_receive_framing_error() ? 1 << 6 : 0;
|
||||
data |= is_receive_parity_error() ? 1 << 7 : 0;
|
||||
LOG("%s data_r: UART Status register %02x\n", machine().describe_context(), data);
|
||||
m_int_status &= ~0x04;
|
||||
update_interrupts();
|
||||
break;
|
||||
|
||||
case 0x09: // UART Receive register
|
||||
receive_register_extract();
|
||||
data = get_received_char();
|
||||
LOG("%s data_r: UART Receive register %02x\n", machine().describe_context(), data);
|
||||
m_int_status &= ~0x01;
|
||||
update_interrupts();
|
||||
break;
|
||||
|
||||
case 0x0c: // Synchronous Port 1 read
|
||||
@ -275,10 +401,14 @@ uint8_t psion_asic5_device::data_r()
|
||||
break;
|
||||
|
||||
case 0x0d: // Barcode read data
|
||||
// 0 PC4 4 PB4
|
||||
// 1 PC7 5 PB5
|
||||
// 2 PB2 6 PB6
|
||||
// 3 PB3 7 PB7
|
||||
// b0 PC4
|
||||
// b1 PC7
|
||||
// b2 PB2
|
||||
// b3 PB3
|
||||
// b4 PB4
|
||||
// b5 PB5
|
||||
// b6 PB6
|
||||
// b7 PB7
|
||||
LOG("%s data_r: Barcode read data %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
|
||||
@ -295,3 +425,34 @@ uint8_t psion_asic5_device::data_r()
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void psion_asic5_device::write_rxd(int state)
|
||||
{
|
||||
m_rxd = state;
|
||||
device_serial_interface::rx_w(state);
|
||||
}
|
||||
|
||||
void psion_asic5_device::write_cts(int state)
|
||||
{
|
||||
if (m_cts != state)
|
||||
m_int_status |= 0x04;
|
||||
m_cts = state;
|
||||
update_interrupts();
|
||||
|
||||
}
|
||||
void psion_asic5_device::write_dsr(int state)
|
||||
{
|
||||
if (m_dsr != state)
|
||||
m_int_status |= 0x04;
|
||||
m_dsr = state;
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
void psion_asic5_device::write_dcd(int state)
|
||||
{
|
||||
if (m_dcd != state)
|
||||
m_int_status |= 0x04;
|
||||
m_dcd = state;
|
||||
update_interrupts();
|
||||
}
|
||||
|
@ -31,16 +31,30 @@ public:
|
||||
|
||||
psion_asic5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
static constexpr feature_type imperfect_features() { return feature::COMMS; }
|
||||
|
||||
void set_mode(pc6_state mode) { m_mode = mode; }
|
||||
|
||||
auto readpa_handler() { return m_in_a_handler.bind(); }
|
||||
auto readpb_handler() { return m_in_b_handler.bind(); }
|
||||
auto readpc_handler() { return m_in_c_handler.bind(); }
|
||||
|
||||
auto writepa_handler() { return m_out_a_handler.bind(); }
|
||||
auto writepb_handler() { return m_out_b_handler.bind(); }
|
||||
auto writepc_handler() { return m_out_c_handler.bind(); }
|
||||
auto writepd_handler() { return m_out_d_handler.bind(); }
|
||||
auto writepe_handler() { return m_out_e_handler.bind(); }
|
||||
auto writecs_handler() { return m_out_cs_handler.bind(); }
|
||||
|
||||
// UART handlers
|
||||
auto int_handler() { return m_int_handler.bind(); }
|
||||
auto txd_handler() { return m_txd_handler.bind(); }
|
||||
auto rts_handler() { return m_rts_handler.bind(); }
|
||||
auto dtr_handler() { return m_dtr_handler.bind(); }
|
||||
|
||||
void write_rxd(int state);
|
||||
void write_cts(int state);
|
||||
void write_dsr(int state);
|
||||
void write_dcd(int state);
|
||||
|
||||
void set_info_byte(uint8_t info) { m_info_byte = info; }
|
||||
|
||||
@ -53,26 +67,48 @@ protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_serial overrides
|
||||
virtual void rcv_callback() override;
|
||||
virtual void rcv_complete() override;
|
||||
virtual void tra_callback() override;
|
||||
virtual void tra_complete() override;
|
||||
|
||||
private:
|
||||
static constexpr uint16_t NULL_FRAME = 0x000;
|
||||
static constexpr uint16_t CONTROL_FRAME = 0x100;
|
||||
static constexpr uint16_t DATA_FRAME = 0x200;
|
||||
|
||||
void update_interrupts();
|
||||
|
||||
uint8_t m_mode;
|
||||
|
||||
devcb_read8 m_in_a_handler;
|
||||
devcb_read8 m_in_b_handler;
|
||||
devcb_read8 m_in_c_handler;
|
||||
devcb_write8 m_out_a_handler;
|
||||
devcb_write8 m_out_b_handler;
|
||||
devcb_write8 m_out_c_handler;
|
||||
devcb_write8 m_out_d_handler;
|
||||
devcb_write8 m_out_e_handler;
|
||||
devcb_write8 m_out_cs_handler;
|
||||
|
||||
devcb_write_line m_int_handler;
|
||||
devcb_write_line m_txd_handler;
|
||||
devcb_write_line m_rts_handler;
|
||||
devcb_write_line m_dtr_handler;
|
||||
|
||||
int m_rxd;
|
||||
int m_cts;
|
||||
int m_dsr;
|
||||
int m_dcd;
|
||||
|
||||
uint8_t m_port_b_counter;
|
||||
uint8_t m_port_b_latch;
|
||||
uint8_t m_port_b_mode;
|
||||
uint8_t m_port_dc_writes;
|
||||
bool m_port_dc_select;
|
||||
uint8_t m_int_mask;
|
||||
uint8_t m_int_status;
|
||||
uint8_t m_control;
|
||||
int16_t m_bdr;
|
||||
|
||||
uint8_t m_info_byte;
|
||||
uint8_t m_sibo_control;
|
||||
|
@ -13,7 +13,7 @@
|
||||
TODO:
|
||||
- improve RAM configuration for mx machines
|
||||
- set RTC timer
|
||||
- ASIC9MX implements V30MX, and likely the unknown Temic device found in 3c/Siena
|
||||
- ASIC9MX implements V30MX, and likely the Temic (Condor) device found in 3c/Siena
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
@ -50,10 +50,13 @@ psion_asic9_device::psion_asic9_device(const machine_config &mconfig, device_typ
|
||||
, m_frc2_timer(nullptr)
|
||||
, m_watchdog_timer(nullptr)
|
||||
, m_rtc_timer(nullptr)
|
||||
, m_snd_timer(nullptr)
|
||||
, m_buz_cb(*this)
|
||||
, m_col_cb(*this)
|
||||
, m_port_ab_r(*this, 0)
|
||||
, m_port_ab_w(*this)
|
||||
, m_pcm_in(*this, 0)
|
||||
, m_pcm_out(*this)
|
||||
, m_data_r(*this, 0x00)
|
||||
, m_data_w(*this)
|
||||
{
|
||||
@ -147,6 +150,7 @@ void psion_asic9_device::device_start()
|
||||
m_frc2_timer = timer_alloc(FUNC(psion_asic9_device::frc2), this);
|
||||
m_watchdog_timer = timer_alloc(FUNC(psion_asic9_device::watchdog), this);
|
||||
m_rtc_timer = timer_alloc(FUNC(psion_asic9_device::rtc), this);
|
||||
m_snd_timer = timer_alloc(FUNC(psion_asic9_device::snd), this);
|
||||
m_busy_timer = timer_alloc(FUNC(psion_asic9_device::busy), this);
|
||||
|
||||
m_a9_control = 0x00;
|
||||
@ -186,6 +190,7 @@ void psion_asic9_device::device_reset()
|
||||
m_frc2_timer->adjust(attotime::from_hz(512000), 0, attotime::from_hz(512000));
|
||||
m_watchdog_timer->adjust(attotime::from_hz(4), 0, attotime::from_hz(4));
|
||||
m_rtc_timer->adjust(attotime::from_hz(1), 0, attotime::from_hz(1));
|
||||
m_snd_timer->adjust(attotime::from_hz(8000), 0, attotime::from_hz(8000)); // unknown data rate
|
||||
|
||||
m_post = 0x00;
|
||||
|
||||
@ -196,6 +201,7 @@ void psion_asic9_device::device_reset()
|
||||
m_frc1_reload = 0;
|
||||
m_frc2_count = 0;
|
||||
m_frc2_reload = 0;
|
||||
m_buz_toggle = 0;
|
||||
m_watchdog_count = 0;
|
||||
m_a9_protection_mode = false;
|
||||
m_a9_protection_lower = 0x00;
|
||||
@ -208,9 +214,11 @@ void psion_asic9_device::device_reset()
|
||||
m_a9_psel_8000 = 0x00;
|
||||
m_a9_psel_9000 = 0x00;
|
||||
m_a9_control_extra = 0x00;
|
||||
m_rtc = time(nullptr) - 946684800;
|
||||
m_rtc = 0;
|
||||
|
||||
m_a9_status |= 0x0020; // A9MMainsPresent
|
||||
m_a9_status |= 0xe000; // A9MCold
|
||||
|
||||
m_a9_serial_control = 0x00;
|
||||
m_a9_channel_select = 0x00;
|
||||
}
|
||||
@ -227,6 +235,10 @@ TIMER_CALLBACK_MEMBER(psion_asic9_device::frc1)
|
||||
switch (--m_frc1_count)
|
||||
{
|
||||
case 0x0000:
|
||||
if (BIT(m_a9_control_extra, 5)) // A9MBuzzFromFrc1OrTog
|
||||
{
|
||||
m_buz_cb(m_buz_toggle ^= 1);
|
||||
}
|
||||
m_a9_interrupt_status |= 0x40; // A9MFrc1
|
||||
update_interrupts();
|
||||
break;
|
||||
@ -271,6 +283,41 @@ TIMER_CALLBACK_MEMBER(psion_asic9_device::rtc)
|
||||
m_rtc++;
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(psion_asic9_device::snd)
|
||||
{
|
||||
if (BIT(m_a9_control, 11)) // A9MSoundEnable
|
||||
{
|
||||
switch (BIT(m_a9_control_extra, 7)) // A9MSoundDir
|
||||
{
|
||||
case 0:
|
||||
if (!m_snd_fifo.full())
|
||||
m_snd_fifo.enqueue(m_pcm_in());
|
||||
if (m_snd_fifo.full())
|
||||
m_a9_status |= 0x0800;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (!m_snd_fifo.empty())
|
||||
m_pcm_out(m_snd_fifo.dequeue());
|
||||
if (!m_snd_fifo.full())
|
||||
m_a9_status &= ~0x0800;
|
||||
break;
|
||||
}
|
||||
m_a9_interrupt_status |= 0x01; // Sound
|
||||
update_interrupts();
|
||||
}
|
||||
}
|
||||
|
||||
void psion_asic9_device::sds_int_w(int state)
|
||||
{
|
||||
if (state)
|
||||
m_a9_interrupt_status |= 0x04; // A9MSlave
|
||||
else
|
||||
m_a9_interrupt_status &= ~0x04;
|
||||
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
void psion_asic9_device::eint0_w(int state)
|
||||
{
|
||||
if (state)
|
||||
@ -286,7 +333,7 @@ void psion_asic9_device::eint1_w(int state)
|
||||
if (state)
|
||||
m_a9_interrupt_status |= 0x10; // A9MExpIntA
|
||||
else
|
||||
m_a9_interrupt_status &= ~0x10;
|
||||
m_a9_interrupt_status &= ~0x10;
|
||||
|
||||
update_interrupts();
|
||||
}
|
||||
@ -549,8 +596,8 @@ uint16_t psion_asic9_device::io_r(offs_t offset, uint16_t mem_mask)
|
||||
case 0x06: // A9BInterruptStatus
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
data = m_a9_interrupt_status;
|
||||
LOG("%s io_r: A1InterruptStatus => %02x\n", machine().describe_context(), data);
|
||||
data = m_a9_interrupt_status & m_a9_interrupt_mask;
|
||||
LOG("%s io_r: A9InterruptStatus => %02x\n", machine().describe_context(), data);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -578,6 +625,9 @@ uint16_t psion_asic9_device::io_r(offs_t offset, uint16_t mem_mask)
|
||||
case 0x1a: // A9BSoundData
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
data = m_snd_fifo.dequeue();
|
||||
if (!m_snd_fifo.full())
|
||||
m_a9_status &= ~0x0800;
|
||||
LOG("%s io_r: A9BSoundData => %02x\n", machine().describe_context(), data);
|
||||
}
|
||||
break;
|
||||
@ -595,12 +645,12 @@ uint16_t psion_asic9_device::io_r(offs_t offset, uint16_t mem_mask)
|
||||
case 0x22: // A9WPortABDDR
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
data = m_a9_port_ab_ddr & 0x00ff;
|
||||
data |= m_a9_port_ab_ddr & 0x00ff;
|
||||
LOG("%s io_r: A9WPortADDR => %02x\n", machine().describe_context(), data);
|
||||
}
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
data = m_a9_port_ab_ddr & 0xff00;
|
||||
data |= m_a9_port_ab_ddr & 0xff00;
|
||||
LOG("%s io_r: A9WPortBDDR => %02x\n", machine().describe_context(), data >> 8);
|
||||
}
|
||||
break;
|
||||
@ -608,12 +658,12 @@ uint16_t psion_asic9_device::io_r(offs_t offset, uint16_t mem_mask)
|
||||
case 0x24: // A9WPortCDData
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
data = 0x00;
|
||||
data |= 0x00;
|
||||
LOG("%s io_r: A9WPortCData => %02x\n", machine().describe_context(), data);
|
||||
}
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
data = 0x00 << 8;
|
||||
data |= 0x00 << 8;
|
||||
LOG("%s io_r: A9WPortDData => %02x\n", machine().describe_context(), data >> 8);
|
||||
}
|
||||
break;
|
||||
@ -874,6 +924,9 @@ void psion_asic9_device::io_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
LOG("%s io_w: A9BSoundData <= %04x\n", machine().describe_context(), data);
|
||||
m_snd_fifo.enqueue(data & 0xff);
|
||||
if (m_snd_fifo.full())
|
||||
m_a9_status |= 0x0800;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -34,10 +34,14 @@ public:
|
||||
auto col_cb() { return m_col_cb.bind(); }
|
||||
auto port_ab_r() { return m_port_ab_r.bind(); }
|
||||
auto port_ab_w() { return m_port_ab_w.bind(); }
|
||||
auto pcm_in() { return m_pcm_in.bind(); }
|
||||
auto pcm_out() { return m_pcm_out.bind(); }
|
||||
|
||||
template <unsigned N> auto data_r() { static_assert(N < 8); return m_data_r[N].bind(); }
|
||||
template <unsigned N> auto data_w() { static_assert(N < 8); return m_data_w[N].bind(); }
|
||||
|
||||
address_space &io_space() const { return m_v30->space(AS_IO); }
|
||||
|
||||
uint16_t io_r(offs_t offset, uint16_t mem_mask);
|
||||
void io_w(offs_t offset, uint16_t data, uint16_t mem_mask);
|
||||
uint16_t mem_r(offs_t offset, uint16_t mem_mask);
|
||||
@ -47,6 +51,7 @@ public:
|
||||
|
||||
IRQ_CALLBACK_MEMBER(inta_cb);
|
||||
|
||||
void sds_int_w(int state);
|
||||
void eint0_w(int state);
|
||||
void eint1_w(int state);
|
||||
void eint2_w(int state);
|
||||
@ -85,12 +90,14 @@ private:
|
||||
emu_timer *m_frc2_timer;
|
||||
emu_timer *m_watchdog_timer;
|
||||
emu_timer *m_rtc_timer;
|
||||
emu_timer *m_snd_timer;
|
||||
|
||||
TIMER_CALLBACK_MEMBER(tick);
|
||||
TIMER_CALLBACK_MEMBER(frc1);
|
||||
TIMER_CALLBACK_MEMBER(frc2);
|
||||
TIMER_CALLBACK_MEMBER(watchdog);
|
||||
TIMER_CALLBACK_MEMBER(rtc);
|
||||
TIMER_CALLBACK_MEMBER(snd);
|
||||
|
||||
void update_interrupts();
|
||||
bool is_protected(offs_t offset);
|
||||
@ -111,11 +118,12 @@ private:
|
||||
uint16_t m_frc1_reload;
|
||||
uint16_t m_frc2_count;
|
||||
uint16_t m_frc2_reload;
|
||||
int m_buz_toggle;
|
||||
uint8_t m_watchdog_count;
|
||||
bool m_a9_protection_mode;
|
||||
uint32_t m_a9_protection_upper;
|
||||
uint32_t m_a9_protection_lower;
|
||||
uint8_t m_a9_port_ab_ddr;
|
||||
uint16_t m_a9_port_ab_ddr;
|
||||
uint8_t m_a9_port_c_ddr;
|
||||
uint8_t m_a9_port_d_ddr;
|
||||
uint8_t m_a9_psel_6000;
|
||||
@ -124,6 +132,7 @@ private:
|
||||
uint8_t m_a9_psel_9000;
|
||||
uint16_t m_a9_control_extra;
|
||||
uint32_t m_rtc;
|
||||
util::fifo<uint8_t, 16> m_snd_fifo;
|
||||
|
||||
uint8_t m_a9_serial_data;
|
||||
uint8_t m_a9_serial_control;
|
||||
@ -133,6 +142,8 @@ private:
|
||||
devcb_write8 m_col_cb;
|
||||
devcb_read16 m_port_ab_r;
|
||||
devcb_write16 m_port_ab_w;
|
||||
devcb_read8 m_pcm_in;
|
||||
devcb_write8 m_pcm_out;
|
||||
|
||||
devcb_read8::array<8> m_data_r;
|
||||
devcb_write16::array<8> m_data_w;
|
||||
|
Loading…
Reference in New Issue
Block a user