summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/psion_asic5.cpp
diff options
context:
space:
mode:
author Nigel Barnes <ngbarnes@gmail.com>2023-03-25 12:23:20 +0000
committer Nigel Barnes <ngbarnes@gmail.com>2023-03-25 12:25:50 +0000
commit469c2906d96a0cec96ab5940d5890eb6c11f8ef9 (patch)
tree92b37eb90a284cc4d0a3971cccae024856d2581b /src/devices/machine/psion_asic5.cpp
parent2c3cbda8d043e7b7d017cde5f0666f04d33859a9 (diff)
New systems marked not working
------------------------------ Series 3a [Nigel Barnes, The Last Psion] Series 3c [Nigel Barnes, The Last Psion] Series 3mx [Nigel Barnes, The Last Psion] Siena [Nigel Barnes, The Last Psion] Workabout [Nigel Barnes, The Last Psion] Workabout mx [Nigel Barnes, The Last Psion] New clones marked not working ----------------------------- Pocket Book II [Nigel Barnes, The Last Psion] Series 3a (2M) [Nigel Barnes, The Last Psion] Series 3a (2M) (German) [Nigel Barnes, The Last Psion]
Diffstat (limited to 'src/devices/machine/psion_asic5.cpp')
-rw-r--r--src/devices/machine/psion_asic5.cpp225
1 files changed, 225 insertions, 0 deletions
diff --git a/src/devices/machine/psion_asic5.cpp b/src/devices/machine/psion_asic5.cpp
new file mode 100644
index 00000000000..8bd69f7e776
--- /dev/null
+++ b/src/devices/machine/psion_asic5.cpp
@@ -0,0 +1,225 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/******************************************************************************
+
+ Psion ASIC5
+
+ ASIC5 is a general purpose I/O chip with a built-in UART that can be set to
+ run in a number of different modes thereby simplifying the task of peripheral
+ design. For example, it is possible to set up ASIC5 to run as a Centronics
+ parallel port interface, an 8-bit parallel I/O port, a serial bar code
+ controller or a serial RS232 converter.
+
+ TODO:
+ - implement peripheral mode
+
+******************************************************************************/
+
+#include "emu.h"
+#include "psion_asic5.h"
+
+#define VERBOSE 0
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(PSION_ASIC5_PACK, psion_asic5_pack_device, "psion_asic5_pack", "Psion ASIC5 (Pack mode)")
+DEFINE_DEVICE_TYPE(PSION_ASIC5_PERIPHERAL, psion_asic5_peripheral_device, "psion_asic5_peripheral", "Psion ASIC5 (Peripheral mode)")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+psion_asic5_device::psion_asic5_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_in_a_handler(*this)
+ , m_in_b_handler(*this)
+ , m_out_a_handler(*this)
+ , m_out_b_handler(*this)
+ , m_out_c_handler(*this)
+ , m_out_d_handler(*this)
+{
+}
+
+psion_asic5_pack_device::psion_asic5_pack_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : psion_asic5_device(mconfig, PSION_ASIC5_PACK, tag, owner, clock)
+{
+}
+
+psion_asic5_peripheral_device::psion_asic5_peripheral_device(const machine_config &mconfig, const char * tag, device_t *owner, uint32_t clock)
+ : psion_asic5_device(mconfig, PSION_ASIC5_PERIPHERAL, tag, owner, clock)
+ , m_serial(*this, "serial")
+ //, m_irq4_callback(*this)
+ //, m_txd1_callback(*this)
+ //, m_dtr1_callback(*this)
+ //, m_rts1_callback(*this)
+{
+}
+
+
+void psion_asic5_peripheral_device::device_add_mconfig(machine_config &config)
+{
+ NS16550(config, m_serial, clock() / 13);
+ //m_serial->out_int_callback().set([this](int state) { m_irq4_callback(state); });
+ //m_serial->out_tx_callback().set([this](int state) { m_txd1_callback(state); });
+ //m_serial->out_dtr_callback().set([this](int state) { m_dtr1_callback(state); });
+ //m_serial->out_rts_callback().set([this](int state) { m_rts1_callback(state); });
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void psion_asic5_device::device_start()
+{
+ m_in_a_handler.resolve();
+ m_in_b_handler.resolve();
+ m_out_a_handler.resolve_safe();
+ m_out_b_handler.resolve_safe();
+ m_out_c_handler.resolve_safe();
+ m_out_d_handler.resolve_safe();
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void psion_asic5_device::device_reset()
+{
+ m_portb_ctrl = 0x00;
+ m_portb_counter = 0x00;
+}
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+void psion_asic5_device::data_w(uint16_t data)
+{
+ switch (data & 0x300)
+ {
+ case NULL_FRAME:
+ break;
+
+ case CONTROL_FRAME:
+ m_sibo_control = data & 0xff;
+
+ switch (m_sibo_control & 0xc0)
+ {
+ case 0x80: // SerialWrite
+ //if (m_sibo_control == 0x82) // write A3Setup
+ if (m_sibo_control == 0x93) // Multi Port D and C writes
+ m_port_dc_writes = 0;
+ break;
+ }
+ break;
+
+ case DATA_FRAME:
+ data &= 0xff;
+ switch (m_sibo_control & 0x0f)
+ {
+ case 0x00: // Port A write data
+ LOG("%s data_w: Port A write data %02x\n", machine().describe_context(), data);
+ m_out_a_handler(data);
+ break;
+
+ case 0x01: // Port B write data
+ LOG("%s data_w: Port B write data %02x\n", machine().describe_context(), data);
+ m_out_b_handler(data);
+ break;
+
+ case 0x02: // Port B control
+ LOG("%s data_w: Port B control %02x\n", machine().describe_context(), data);
+ m_portb_ctrl = data;
+ break;
+
+ case 0x03: // Port D and C write data
+ if (m_port_dc_writes)
+ {
+ 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);
+ m_portb_counter = 0x00;
+ m_out_b_handler(m_portb_counter);
+ }
+ m_port_dc_writes++;
+ break;
+
+ case 0x06: // Interrupt mask write
+ LOG("%s data_w: out int mask %02x\n", machine().describe_context(), data);
+ m_interrupt_mask = data;
+ break;
+
+ //case 0x07: // Control register
+ // m = data;
+ // break;
+
+ default:
+ LOG("%s data_w: unknown control %02x data %02x\n", machine().describe_context(), m_sibo_control, data);
+ break;
+ }
+ break;
+ }
+}
+
+
+uint8_t psion_asic5_device::data_r()
+{
+ uint8_t data = 0x00;
+
+ switch (m_sibo_control & 0xc0)
+ {
+ case 0x40: // SerialSelect
+ if (m_sibo_control == 0x42) // Asic5PackId
+ data = m_info_byte; // A3InfoByte
+ break;
+
+ case 0xc0: // SerialRead
+ switch (m_sibo_control & 0x0f)
+ {
+ case 0x00: // Port A read data
+ data = m_in_a_handler();
+ LOG("%s data_r: Port A read data %02x\n", machine().describe_context(), data);
+ if (m_sibo_control & 0x90) // Multi, increment Port B
+ {
+ m_portb_counter++;
+ m_out_b_handler(m_portb_counter);
+ }
+ break;
+
+ case 0x01: // Port B read data
+ data = m_in_b_handler();
+ LOG("%s data_r: Port B read data %02x\n", machine().describe_context(), data);
+ break;
+
+ case 0x02: // Port B counter
+ m_portb_counter++;
+ m_out_b_handler(m_portb_counter);
+ LOG("%s data_r: Port B counter %02x\n", machine().describe_context(), m_portb_counter);
+ break;
+
+ case 0x06: // Interrupt mask write
+ data = m_interrupt_mask;
+ LOG("%s data_r: in int mask %02x\n", machine().describe_context(), data);
+ break;
+
+ //case 0x07: // Control register
+ // m = data;
+ // break;
+
+ default:
+ LOG("%s data_r: unknown control %02x data %02x\n", machine().describe_context(), m_sibo_control, data);
+ break;
+ }
+ break;
+ }
+
+ return data;
+}