summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/psion_asic3.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/psion_asic3.cpp')
-rw-r--r--src/devices/machine/psion_asic3.cpp301
1 files changed, 301 insertions, 0 deletions
diff --git a/src/devices/machine/psion_asic3.cpp b/src/devices/machine/psion_asic3.cpp
new file mode 100644
index 00000000000..409c5246acd
--- /dev/null
+++ b/src/devices/machine/psion_asic3.cpp
@@ -0,0 +1,301 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/******************************************************************************
+
+ 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.
+
+ TODO:
+ - Battery status readings, maybe different analogue channel.
+
+******************************************************************************/
+
+#include "emu.h"
+#include "psion_asic3.h"
+
+#define VERBOSE 0
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+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, 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
+//-------------------------------------------------
+
+void psion_asic3_device::device_start()
+{
+ save_item(NAME(m_a3_control1));
+ save_item(NAME(m_a3_control2));
+ save_item(NAME(m_a3_control3));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void psion_asic3_device::device_reset()
+{
+ m_a3_control1 = 0x00;
+ m_a3_control2 = 0x00;
+ m_a3_control3 = 0x00;
+}
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+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;
+ break;
+
+ case DATA_FRAME:
+ data &= 0xff;
+ switch (m_sibo_control & 0x0f)
+ {
+ case 0x01: // A3Control1
+ // b0-b4 DtoaBits
+ // b5 Vcc3Enable LCD
+ // b6 Vcc4Enable Sound subsystem
+ // b7 Vcc5Enable SSDs
+ LOG("%s data_w: A3Control1 register %02x\n", machine().describe_context(), data);
+ m_a3_control1 = data;
+ break;
+
+ case 0x02: // A3Setup
+ LOG("%s data_w: A3Setup register %02x\n", machine().describe_context(), data);
+ break;
+
+ case 0x03: // A3Control2
+ // b0 Vee1Enable LCD
+ // b1 Vee2Enable Sound subsystem
+ // b2 VhEnable
+ // b3 Vee1SoftStart
+ // b4 Vee2SoftStart
+ // b5 VhSoftStart
+ // b6-b7 AnalogueMultiplex
+ LOG("%s data_w: A3Control2 register %02x\n", machine().describe_context(), data);
+ m_a3_control2 = data;
+ break;
+
+ case 0x07: // A3Control3
+ // 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: unknown control %02x data %02x\n", machine().describe_context(), m_sibo_control, data);
+ break;
+ }
+ }
+}
+
+uint8_t psion_psu_asic5_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: // A3Adc
+ {
+ // A3AdcLsbR
+ // b0-b6 OtherBits
+ // b7 InvertedBit
+ // A3AdcMsbR
+ // 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(data_in, 8, 4);
+ else
+ 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 ColdStart
+ // b1 PowerFail
+ data = 0x02; // PowerFail (required to initialise MC400/200/Word)
+ LOG("%s data_r: A3Status register %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;
+ }
+
+ 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; // PowerFail (required to initialise MC600)
+ 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;
+ }
+
+ return data;
+}