summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Michael Zapf <Michael.Zapf@mizapf.de>2017-06-25 18:11:48 +0200
committer Michael Zapf <Michael.Zapf@mizapf.de>2017-06-25 18:12:34 +0200
commitc318e49ab277001120e667876f3b21da7539a047 (patch)
treef93767d761335006b8b9bb67a7870b280a2a37de
parentd80ae34c064b9e2e592235eaaaab07fbf6568dec (diff)
ti99: Changed Hexbus chaining
-rw-r--r--src/devices/bus/ti99/hexbus/hexbus.cpp236
-rw-r--r--src/devices/bus/ti99/hexbus/hexbus.h119
-rw-r--r--src/devices/bus/ti99/hexbus/hx5102.cpp8
-rw-r--r--src/devices/bus/ti99/hexbus/hx5102.h5
-rw-r--r--src/devices/bus/ti99/internal/998board.cpp17
-rw-r--r--src/devices/bus/ti99/internal/998board.h6
6 files changed, 206 insertions, 185 deletions
diff --git a/src/devices/bus/ti99/hexbus/hexbus.cpp b/src/devices/bus/ti99/hexbus/hexbus.cpp
index 92251f423b2..d8c315057c7 100644
--- a/src/devices/bus/ti99/hexbus/hexbus.cpp
+++ b/src/devices/bus/ti99/hexbus/hexbus.cpp
@@ -88,15 +88,42 @@
Usage in MAME
-------------
- Single device usage:
mame <driver> -hexbus <device>
- Multiple device usage:
- mame <driver> -hexbus chain -hexbus:chain:1 <device> ... -hexbus:chain:4 <device>
+ Usually the device offers an own hexbus socket, so we can chain devices:
- We currently assume a maximum length of 4 devices which can be increased
- if desired. The chain positions should be used starting from 1 with no
- gaps, but this is not enforced.
+ mame <driver> -hexbus <device1> -hexbus:<device1>:hexbus <device2> ...
+
+ The direction towards the console is named "inbound" in the implementation,
+ while the direction towards the end of the chain is named "outbound".
+
+ Implementation
+ --------------
+
+ All lines (ADB0-3, HSK*, BAV*) are pull-down outputs with open collectors,
+ and at the same time also inputs.
+
+ The challenge, compared to other daisy-chained buses, is that the Hexbus
+ is nondirectional. Writing on the bus is sensed by all devices in either
+ direction. Also, reading from the bus is the product of all active output
+ buffers. With no active device, the bus lines are pulled high.
+
+ Every Hexbus device has an interface "device_ti_hexbus_interface" which
+ allows it to plug into a preceding Hexbus socket.
+
+ Since the signal propagation is the same for all devices, there is a
+ parent class "hexbus_chained_device" that calculates the current levels
+ for all bus lines by fetching all values from the attached devices, ANDing
+ them, and propagating them again. This must be done in both directions.
+
+ Reading is simpler, because we assume that changes can only be done by
+ writing to the bus.
+
+ The "hexbus_chained_device" implements the "device_ti_hexbus_interface"
+ and holds references to up to two Hexbus instances, one for each direction.
+ The computer console will not offer an inbound Hexbus connection, only
+ an outbound one, and possibly there is some device that must be connected
+ at the end, without further outbound connections.
References
----------
@@ -118,163 +145,162 @@
// Hexbus instance
DEFINE_DEVICE_TYPE_NS(TI_HEXBUS, bus::ti99::hexbus, hexbus_device, "ti_hexbus", "Hexbus")
-// Hexbus daisy chain
-DEFINE_DEVICE_TYPE_NS(TI_HEXBUS_CHAIN, bus::ti99::hexbus, hexbus_chain_device, "ti_hexbus_chain", "Hexbus chain")
-
-// Single slot of the Hexbus
-DEFINE_DEVICE_TYPE_NS(TI_HEXBUS_SLOT, bus::ti99::hexbus, hexbus_slot_device, "ti_hexbus_slot", "Hexbus position")
-
namespace bus { namespace ti99 { namespace hexbus {
-enum
-{
- NOTCONN = -1
-};
-
hexbus_device::hexbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, TI_HEXBUS, tag, owner, clock),
device_slot_interface(mconfig, *this),
- m_master(nullptr),
- m_slave(nullptr)
+ m_next_dev(nullptr)
{
}
void hexbus_device::device_start()
{
+ m_next_dev = dynamic_cast<device_ti_hexbus_interface *>(get_card_device());
}
-void hexbus_device::device_config_complete()
+/*
+ Write to the hexbus. If the write operation comes from the plugged device,
+ this is an inbound write; otherwise, the write comes from the owner of the
+ hexbus connector, which means an outbound write.
+*/
+void hexbus_device::write(int dir, uint8_t data)
{
- m_slave = dynamic_cast<device_ti_hexbus_interface*>(subdevices().first());
- if (m_slave != nullptr)
- m_slave->set_hexbus(this);
+ if (dir == INBOUND)
+ m_chain_element->bus_write(INBOUND, data);
+ else
+ {
+ // Is there another Hexbus device?
+ if (m_next_dev != nullptr)
+ m_next_dev->bus_write(OUTBOUND, data);
+ }
}
-void hexbus_device::send()
+/*
+ Read from the hexbus. If the read operation comes from the plugged device,
+ this is an inbound read; otherwise, the read comes from the owner of the
+ hexbus connector, which means an outbound read.
+*/
+uint8_t hexbus_device::read(int dir)
{
- uint8_t sum = m_master->get_value();
- if (m_slave != nullptr)
+ // Default is: all lines pulled up
+ uint8_t value = 0xff;
+
+ if (dir == INBOUND)
+ value = m_chain_element->bus_read(INBOUND);
+ else
{
- sum &= m_slave->get_value();
- m_slave->receive(sum);
+ // Is there another Hexbus device?
+ if (m_next_dev != nullptr)
+ value = m_next_dev->bus_read(OUTBOUND);
}
- m_master->receive(sum);
+ return value;
}
// ------------------------------------------------------------------------
-hexbus_chain_device::hexbus_chain_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, TI_HEXBUS_CHAIN, tag, owner, clock),
+hexbus_chained_device::hexbus_chained_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock):
+ device_t(mconfig, type, tag, owner, clock),
device_ti_hexbus_interface(mconfig, *this)
{
+ m_hexbus_inbound = dynamic_cast<hexbus_device *>(owner);
+ m_myvalue = 0xff;
}
-uint8_t hexbus_chain_device::get_value()
+void hexbus_chained_device::device_start()
{
- uint8_t sum = 0xff;
+ m_hexbus_outbound = static_cast<hexbus_device*>(subdevice("hexbus"));
- // Do the wired AND
- for (device_t &child : subdevices())
- {
- hexbus_slot_device* slot = downcast<hexbus_slot_device *>(&child);
- sum &= slot->get_value();
- }
-
- return sum;
+ // Establish callback for inbound propagations
+ m_hexbus_outbound->set_chain_element(this);
}
-void hexbus_chain_device::receive(uint8_t value)
+/*
+ Called from the Hexbus user, that is, the device that subclasses
+ hexbus_chained_device, like the HX5102
+*/
+void hexbus_chained_device::hexbus_write(uint8_t data)
{
- // Propagate
- for (device_t &child : subdevices())
- {
- hexbus_slot_device* slot = downcast<hexbus_slot_device *>(&child);
- slot->receive(value);
- }
-}
+ m_myvalue = data;
-void hexbus_chain_device::device_start()
-{
-}
+ uint8_t inbound_value = 0xff;
+ uint8_t outbound_value = 0xff;
-SLOT_INTERFACE_START( ti_hexbus_chain_slot )
-// SLOT_INTERFACE("hx5102", TI_HX5102) // not an option yet
-SLOT_INTERFACE_END
+ // Determine the current bus level from the values of the
+ // other devices left and right from us
+ if (m_hexbus_inbound != nullptr)
+ inbound_value = m_hexbus_inbound->read(INBOUND);
-MACHINE_CONFIG_MEMBER( hexbus_chain_device::device_add_mconfig )
- MCFG_HEXBUS_SLOT_ADD( "1", ti_hexbus_chain_slot )
- MCFG_HEXBUS_SLOT_ADD( "2", ti_hexbus_chain_slot )
- MCFG_HEXBUS_SLOT_ADD( "3", ti_hexbus_chain_slot )
- MCFG_HEXBUS_SLOT_ADD( "4", ti_hexbus_chain_slot )
-MACHINE_CONFIG_END
+ if (m_hexbus_outbound != nullptr)
+ outbound_value = m_hexbus_outbound->read(OUTBOUND);
-// ------------------------------------------------------------------------
+ // What is the new bus level?
+ uint8_t newvalue = inbound_value & outbound_value & m_myvalue;
-int hexbus_slot_device::get_index_from_tagname()
-{
- const char *mytag = tag();
- int maxlen = strlen(mytag);
- int i;
- for (i=maxlen-1; i >=0; i--)
- if (mytag[i] < 48 || mytag[i] > 57) break;
+ // If it changed, propagate to both directions.
+ if (newvalue != m_current_bus_value)
+ {
+ hexbus_value_changed(newvalue);
+ m_current_bus_value = newvalue;
- return atoi(mytag+i+1);
-}
+ if (m_hexbus_inbound != nullptr)
+ m_hexbus_inbound->write(INBOUND, m_current_bus_value);
-hexbus_slot_device::hexbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, TI_HEXBUS_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_hexbdev(nullptr)
-{
+ if (m_hexbus_outbound != nullptr)
+ m_hexbus_outbound->write(OUTBOUND, m_current_bus_value);
+ }
}
-/* Called from the Hexbus instance */
-int hexbus_slot_device::get_index()
+/*
+ Called from the Hexbus user, that is, the device that subclasses
+ hexbus_chained_device, like the HX5102
+*/
+uint8_t hexbus_chained_device::hexbus_read()
{
- if (m_hexbdev == nullptr) return NOTCONN;
- return get_index_from_tagname();
+ return m_current_bus_value;
}
-uint8_t hexbus_slot_device::get_value()
+/*
+ Called from another hexbus device on the bus
+*/
+uint8_t hexbus_chained_device::bus_read(int dir)
{
- return (m_hexbdev != nullptr)? m_hexbdev->get_value() : 0xff;
-}
+ uint8_t tmpvalue = 0xff;
+ hexbus_device* hexbuscont = (dir == INBOUND)? m_hexbus_inbound : m_hexbus_outbound;
-void hexbus_slot_device::receive(uint8_t value)
-{
- if (m_hexbdev != nullptr)
- m_hexbdev->receive(value);
-}
+ if (hexbuscont != nullptr)
+ tmpvalue = hexbuscont->read(dir);
-void hexbus_slot_device::device_start()
-{
+ return m_myvalue & tmpvalue;
}
-void hexbus_slot_device::device_config_complete()
+/*
+ Called from another hexbus device on the bus
+*/
+void hexbus_chained_device::bus_write(int dir, uint8_t data)
{
- m_hexbus = dynamic_cast<hexbus_device*>(owner());
- m_hexbdev = dynamic_cast<device_ti_hexbus_interface *>(subdevices().first());
-}
+ hexbus_device* hexbuscont = (dir == INBOUND)? m_hexbus_inbound : m_hexbus_outbound;
-// ------------------------------------------------------------------------
+ // Notify device
+ if (data != m_current_bus_value)
+ hexbus_value_changed(data);
-void device_ti_hexbus_interface::interface_config_complete()
-{
- m_hexbus = dynamic_cast<hexbus_device*>(device().owner());
-}
+ m_current_bus_value = data;
-void device_ti_hexbus_interface::hexbus_send(uint8_t value)
-{
- m_value = value;
- m_hexbus->send();
+ // Propagate
+ if (hexbuscont != nullptr)
+ hexbuscont->write(dir, data);
}
+MACHINE_CONFIG_MEMBER( hexbus_chained_device::device_add_mconfig )
+ MCFG_HEXBUS_ADD("hexbus")
+MACHINE_CONFIG_END
+
// ------------------------------------------------------------------------
} } } // end namespace bus::ti99::hexbus
SLOT_INTERFACE_START( ti_hexbus_conn )
-// SLOT_INTERFACE("hx5102", TI_HX5102) // not an option yet
- SLOT_INTERFACE("chain", TI_HEXBUS_CHAIN)
+ SLOT_INTERFACE("hx5102", TI_HX5102)
SLOT_INTERFACE_END
diff --git a/src/devices/bus/ti99/hexbus/hexbus.h b/src/devices/bus/ti99/hexbus/hexbus.h
index 6718a79768f..5c9f62274c2 100644
--- a/src/devices/bus/ti99/hexbus/hexbus.h
+++ b/src/devices/bus/ti99/hexbus/hexbus.h
@@ -21,119 +21,104 @@ namespace bus { namespace ti99 { namespace hexbus {
enum
{
- MAX_DEVICES = 4
+ INBOUND = 0,
+ OUTBOUND = 1
};
class hexbus_device;
+class hexbus_chained_device;
/********************************************************************
- Common parent class of all devices attached to the hexbus port
+ Interface for a device that connects to the Hexbus
********************************************************************/
+
class device_ti_hexbus_interface : public device_slot_card_interface
{
- friend class hexbus_device;
- friend class hexbus_slot_device;
+public:
+ virtual uint8_t bus_read(int dir) =0;
+ virtual void bus_write(int dir, uint8_t data) =0;
protected:
- using device_slot_card_interface::device_slot_card_interface;
- void hexbus_send(uint8_t value);
- uint8_t hexbus_receive() { return m_busvalue; }
-
- virtual void receive(uint8_t value) { m_busvalue = value; }
- virtual uint8_t get_value() { return m_value; }
-
- virtual void interface_config_complete() override;
- hexbus_device *m_hexbus; // Link to the Hexbus
-
-private:
- void set_hexbus(hexbus_device* hexbus) { m_hexbus = hexbus; }
- uint8_t m_value;
- uint8_t m_busvalue;
+ device_ti_hexbus_interface(const machine_config &mconfig, device_t &device) :
+ device_slot_card_interface(mconfig, device) { }
};
-// ------------------------------------------------------------------------
-
-class hexbus_device : public device_t, public device_slot_interface
+/********************************************************************
+ Common parent class of all devices attached to the hexbus port
+ This class implements the signal propagation in both directions
+********************************************************************/
+class hexbus_chained_device : public device_t, public device_ti_hexbus_interface
{
- friend class device_ti_hexbus_interface;
+ friend class hexbus_device;
public:
- hexbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void connect_master(device_ti_hexbus_interface *masterdev) { m_master = masterdev; }
+ hexbus_chained_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ virtual void device_start() override;
protected:
- void device_start() override;
- void device_config_complete() override;
+ virtual void device_add_mconfig(machine_config &config) override;
-private:
- device_ti_hexbus_interface *m_master;
- device_ti_hexbus_interface *m_slave;
+ // Link to the inbound Hexbus (if not null, see Oso chip)
+ hexbus_device *m_hexbus_inbound;
- // Called from a slot, samples all values from the devices, and propagates
- // the logical product to all connected devices
- void send();
-};
+ // Link to the outbound Hexbus (if not null)
+ hexbus_device *m_hexbus_outbound;
+ // Common AND of all private values
+ uint8_t m_current_bus_value;
-// ------------------------------------------------------------------------
+ // From device_ti_hexbus_interface
+ virtual uint8_t bus_read(int dir) override;
+ virtual void bus_write(int dir, uint8_t data) override;
-class hexbus_chain_device : public device_t, public device_ti_hexbus_interface
-{
-public:
- hexbus_chain_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void device_add_mconfig(machine_config &config) override;
+ // Methods to be used from subclasses
+ void hexbus_write(uint8_t data);
+ uint8_t hexbus_read();
+
+ // For interrupts
+ virtual void hexbus_value_changed(uint8_t data) { };
private:
- void device_start() override;
- void receive(uint8_t value) override;
- uint8_t get_value() override;
+ uint8_t m_myvalue;
};
// ------------------------------------------------------------------------
-class hexbus_slot_device : public device_t, public device_slot_interface
-{
- friend class hexbus_attached_device;
- friend class hexbus_chain_device;
+/********************************************************************
+ Connector to the Hexbus, offers a slot for Hexbus-chained devices
+********************************************************************/
+class hexbus_device : public device_t, public device_slot_interface
+{
public:
- hexbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ hexbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // Called from the hexbus (direction to attached device)
- void receive(uint8_t value);
+ // Used to establish the reverse link (inbound)
+ void set_chain_element(hexbus_chained_device* chain) { m_chain_element = chain; }
- // Called from the hexbus
- uint8_t get_value();
+ // Read and write operations on the bus
+ uint8_t read(int dir);
+ void write(int dir, uint8_t data);
protected:
void device_start() override;
- void device_config_complete() override;
-
- // Called from the Hexbus instance
- int get_index();
+ device_ti_hexbus_interface *m_next_dev;
private:
- int get_index_from_tagname();
-
- device_ti_hexbus_interface* m_hexbdev;
- hexbus_device* m_hexbus;
+ // owner of this Hexbus socket; may be the owning component or another
+ // component in the device hierarchy (see TI-99/8 where it belongs to Oso,
+ // but the Hexbus is a subdevice of the driver itself)
+ hexbus_chained_device* m_chain_element;
};
-
#define MCFG_HEXBUS_ADD( _tag ) \
MCFG_DEVICE_ADD(_tag, TI_HEXBUS, 0) \
MCFG_DEVICE_SLOT_INTERFACE( ti_hexbus_conn, nullptr, false)
-#define MCFG_HEXBUS_SLOT_ADD(_tag, _slot_intf) \
- MCFG_DEVICE_ADD(_tag, TI_HEXBUS_SLOT, 0) \
- MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, nullptr, false)
-
} } } // end namespace bus::ti99::hexbus
SLOT_INTERFACE_EXTERN( ti_hexbus_conn );
-DECLARE_DEVICE_TYPE_NS(TI_HEXBUS, bus::ti99::hexbus, hexbus_device)
-DECLARE_DEVICE_TYPE_NS(TI_HEXBUS_CHAIN, bus::ti99::hexbus, hexbus_chain_device)
-DECLARE_DEVICE_TYPE_NS(TI_HEXBUS_SLOT, bus::ti99::hexbus, hexbus_slot_device)
+DECLARE_DEVICE_TYPE_NS(TI_HEXBUS, bus::ti99::hexbus, hexbus_device)
#endif // MAME_BUS_TI99_HEXBUS_HEXBUS_H
diff --git a/src/devices/bus/ti99/hexbus/hx5102.cpp b/src/devices/bus/ti99/hexbus/hx5102.cpp
index e95c31c8d1e..e1bfb5fcbfa 100644
--- a/src/devices/bus/ti99/hexbus/hx5102.cpp
+++ b/src/devices/bus/ti99/hexbus/hx5102.cpp
@@ -15,18 +15,20 @@
#include "emu.h"
#include "hx5102.h"
+#define TRACE_HEXBUS 0
+
DEFINE_DEVICE_TYPE_NS(TI_HX5102, bus::ti99::hexbus, hx5102_device, "ti_hx5102", "TI Hexbus Floppy")
namespace bus { namespace ti99 { namespace hexbus {
hx5102_device::hx5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
- device_t(mconfig, TI_HX5102, tag, owner, clock),
- device_ti_hexbus_interface(mconfig, *this)
+ hexbus_chained_device(mconfig, TI_HX5102, tag, owner, clock)
{
}
-void hx5102_device::device_start()
+void hx5102_device::hexbus_value_changed(uint8_t data)
{
+ if (TRACE_HEXBUS) logerror("Hexbus value changed to %02x\n", data);
}
} } } // end namespace bus::ti99::hexbus
diff --git a/src/devices/bus/ti99/hexbus/hx5102.h b/src/devices/bus/ti99/hexbus/hx5102.h
index 6eb2837ad1b..c384305a9fd 100644
--- a/src/devices/bus/ti99/hexbus/hx5102.h
+++ b/src/devices/bus/ti99/hexbus/hx5102.h
@@ -21,12 +21,11 @@
namespace bus { namespace ti99 { namespace hexbus {
-class hx5102_device : public device_t, public device_ti_hexbus_interface
+class hx5102_device : public hexbus_chained_device
{
public:
hx5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- void device_start() override;
+ void hexbus_value_changed(uint8_t data) override;
};
} } } // end namespace bus::ti99::hexbus
diff --git a/src/devices/bus/ti99/internal/998board.cpp b/src/devices/bus/ti99/internal/998board.cpp
index 28e01049671..a89353051e9 100644
--- a/src/devices/bus/ti99/internal/998board.cpp
+++ b/src/devices/bus/ti99/internal/998board.cpp
@@ -2228,13 +2228,14 @@ enum
};
oso_device::oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, TI99_OSO, tag, owner, clock),
- bus::ti99::hexbus::device_ti_hexbus_interface(mconfig, *this),
+ bus::ti99::hexbus::hexbus_chained_device(mconfig, TI99_OSO, tag, owner, clock),
m_data(0),
m_status(0),
m_control(0),
m_xmit(0)
{
+ m_hexbus_inbound = nullptr;
+ m_hexbus_outbound = nullptr;
}
READ8_MEMBER( oso_device::read )
@@ -2276,6 +2277,7 @@ WRITE8_MEMBER( oso_device::write )
// write 5FF8: write transmit register
if (TRACE_OSO) logerror("Write transmit register %02x\n", data);
m_xmit = data;
+ hexbus_write(data);
// We set the status register directly in order to prevent lock-ups
// until we have a complete Hexbus implementation
m_status |= HSKWT;
@@ -2292,13 +2294,20 @@ WRITE8_MEMBER( oso_device::write )
}
}
+void oso_device::hexbus_value_changed(uint8_t data)
+{
+ if (TRACE_OSO) logerror("Hexbus value changed to %02x\n", data);
+}
+
void oso_device::device_start()
{
logerror("Starting\n");
m_status = m_xmit = m_control = m_data = 0;
- m_hexbus = downcast<bus::ti99::hexbus::hexbus_device*>(machine().device(TI_HEXBUS_TAG));
- m_hexbus->connect_master(this);
+ m_hexbus_outbound = dynamic_cast<bus::ti99::hexbus::hexbus_device*>(machine().device(TI_HEXBUS_TAG));
+
+ // Establish callback
+ m_hexbus_outbound->set_chain_element(this);
save_item(NAME(m_data));
save_item(NAME(m_status));
diff --git a/src/devices/bus/ti99/internal/998board.h b/src/devices/bus/ti99/internal/998board.h
index 45b154a590b..a0d09062a54 100644
--- a/src/devices/bus/ti99/internal/998board.h
+++ b/src/devices/bus/ti99/internal/998board.h
@@ -422,7 +422,7 @@ private:
/*
Custom chip: OSO
*/
-class oso_device : public device_t, public bus::ti99::hexbus::device_ti_hexbus_interface
+class oso_device : public bus::ti99::hexbus::hexbus_chained_device
{
public:
oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -430,13 +430,13 @@ public:
DECLARE_WRITE8_MEMBER( write );
void device_start() override;
+ void hexbus_value_changed(uint8_t data) override;
+
private:
uint8_t m_data;
uint8_t m_status;
uint8_t m_control;
uint8_t m_xmit;
-
- bus::ti99::hexbus::hexbus_device* m_hexbus;
};
class mainboard8_device : public device_t