From 7d980227979c30aac9eb527f15c5b893aebea5c6 Mon Sep 17 00:00:00 2001 From: Michael Zapf Date: Mon, 10 Jul 2017 17:48:08 +0200 Subject: ti99: Moved Hexbus one level up --- scripts/src/bus.lua | 18 +- scripts/target/mame/mess.lua | 1 + src/devices/bus/hexbus/hexbus.cpp | 309 +++++++++++++++++++++++++++++ src/devices/bus/hexbus/hexbus.h | 123 ++++++++++++ src/devices/bus/hexbus/hx5102.cpp | 35 ++++ src/devices/bus/hexbus/hx5102.h | 35 ++++ src/devices/bus/ti99/hexbus/hexbus.cpp | 306 ---------------------------- src/devices/bus/ti99/hexbus/hexbus.h | 124 ------------ src/devices/bus/ti99/hexbus/hx5102.cpp | 35 ---- src/devices/bus/ti99/hexbus/hx5102.h | 35 ---- src/devices/bus/ti99/internal/998board.cpp | 48 ++++- src/devices/bus/ti99/internal/998board.h | 12 +- src/mame/drivers/ti99_8.cpp | 2 +- 13 files changed, 568 insertions(+), 515 deletions(-) create mode 100644 src/devices/bus/hexbus/hexbus.cpp create mode 100644 src/devices/bus/hexbus/hexbus.h create mode 100644 src/devices/bus/hexbus/hx5102.cpp create mode 100644 src/devices/bus/hexbus/hx5102.h delete mode 100644 src/devices/bus/ti99/hexbus/hexbus.cpp delete mode 100644 src/devices/bus/ti99/hexbus/hexbus.h delete mode 100644 src/devices/bus/ti99/hexbus/hx5102.cpp delete mode 100644 src/devices/bus/ti99/hexbus/hx5102.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index b4eb4f52400..1991a06ab3a 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -767,6 +767,19 @@ if (BUSES["GENERIC"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/bus/hexbus/hexbus.h,BUSES["HEXBUS"] = true +--------------------------------------------------- + +if (BUSES["HEXBUS"]~=null) then + files { + MAME_DIR .. "src/devices/bus/hexbus/hexbus.cpp", + MAME_DIR .. "src/devices/bus/hexbus/hexbus.h", + MAME_DIR .. "src/devices/bus/hexbus/hx5102.cpp", + MAME_DIR .. "src/devices/bus/hexbus/hx5102.h", + } +end --------------------------------------------------- -- @@ -2388,7 +2401,6 @@ end --@src/devices/bus/ti99/joyport/joyport.h,BUSES["TI99"] = true --@src/devices/bus/ti99/peb/peribox.h,BUSES["TI99"] = true --@src/devices/bus/ti99/internal/genboard.h,BUSES["TI99"] = true ---@src/devices/bus/ti99/hexbus/hexbus.h,BUSES["TI99"] = true --------------------------------------------------- if (BUSES["TI99"]~=null) then @@ -2418,10 +2430,6 @@ if (BUSES["TI99"]~=null) then MAME_DIR .. "src/devices/bus/ti99/gromport/multiconn.h", MAME_DIR .. "src/devices/bus/ti99/gromport/singleconn.cpp", MAME_DIR .. "src/devices/bus/ti99/gromport/singleconn.h", - MAME_DIR .. "src/devices/bus/ti99/hexbus/hexbus.cpp", - MAME_DIR .. "src/devices/bus/ti99/hexbus/hexbus.h", - MAME_DIR .. "src/devices/bus/ti99/hexbus/hx5102.cpp", - MAME_DIR .. "src/devices/bus/ti99/hexbus/hx5102.h", MAME_DIR .. "src/devices/bus/ti99/joyport/handset.cpp", MAME_DIR .. "src/devices/bus/ti99/joyport/handset.h", MAME_DIR .. "src/devices/bus/ti99/joyport/joyport.cpp", diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 6b4b0c9f62d..60aa06fa3c3 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -662,6 +662,7 @@ BUSES["GAMEBOY"] = true BUSES["GAMEGEAR"] = true BUSES["GBA"] = true BUSES["GENERIC"] = true +BUSES["HEXBUS"] = true BUSES["HPHIL"] = true BUSES["HPDIO"] = true BUSES["IEEE488"] = true diff --git a/src/devices/bus/hexbus/hexbus.cpp b/src/devices/bus/hexbus/hexbus.cpp new file mode 100644 index 00000000000..d369f61f88b --- /dev/null +++ b/src/devices/bus/hexbus/hexbus.cpp @@ -0,0 +1,309 @@ +// license:BSD-3-Clause +// copyright-holders:Michael Zapf +/**************************************************************************** + + =========== Hexbus peripheral bus =========== + + The Hexbus is a 4-bit peripheral bus with master/slave coordination. Bytes + are written over the bus in two passes. Hexbus was the designated standard + peripheral bus for TI computers before TI left the home computer market. + + The Hexbus was also named IPB = Intelligent Peripheral Bus [1] + + Existing devices are floppy drive, RS232 serial adapter, and + a "Wafertape" drive (kind of tape streamer) + + Hexbus connector (console) + +---+---+---+---+ + | 4 | 3 | 2 | 1 | 4 = L; 3 = BAV*; 2 = ADB1; 1 = ADB0 + +---+---+---+---+ + | 8 | 7 | 6 | 5 | 8 = ADB3; 7 = ADB2; 6 = nc; 5 = HSK* + +---+---+---+---+ + + ADBx = Hexbus data bit X (x=0..3) + HSK* = Handshake + BAV* = Bus available (0=yes) + + Theory of operation + ------------------- + The bus connects all devices in a daisy chain. The lines are inactive high + and pulled down by any device that sets them to 0. + + HSK* is a synchronization line for transmitting single bytes. + BAV* is a synchronization line for complete request-response pairs + + Before a byte can be sent, the sender must check the BAV* line. When it is + inactive (1), it pulls it down, and then starts transmitting. The line + is raised again when the response has been fully received. + + For transmitting a byte, the HSK* line must first be pulled down by the + sender. Then, the lower nibble is transmitted first, and the sender + releases the HSK* line. Every receiver that has completely received the + nibble and is ready for the next one releases the HSK* line. The sender + must check the HSK* line until it goes high again (which means that the + slowest receiver has got the nibble). This is repeated for the high nibble. + + When the BAV* signal is asserted (0), the HSK* line must not be high for + more than 20 ms, or a bus timeout occurs. + + The device address is transmitted as part of the request header. All + devices with a non-matching device code must ignore the rest of the + message until BAV* goes inactive (1) again. + + If there is no matching device, HSK* will remain 1 after the end of the + master's request, and after 20ms, a timeout will occur. Declaring a timeout + is a matter of the devices, not of the bus. + + Message format + -------------- + + +-------------+-------------+-------------+-------------+ + | Device Code | Command code| LogUnitNum | RecNum LSB | + +-------------+-------------+-------------+-------------+ + | RecNum MSB | Buflen LSB | Buflen MSB | DataLen LSB | + +-------------+-------------+-------------+-------------+ + | DataLen MSB | | + +-------------+ | + | Data ... (not padded) | + | | + | | + +-------------+-------------+-------------+-------------+ + + Device codes + ------------ + + 0 - all devices (but none will respond, forcing a timeout) + 1-8 - Tape mass storage + 10-17 - Printer / plotter + 20-27 - RS-232 interface + 30-37 - TV interface (color) + 40-47 - TV interface (B/W) + 50-57 - Centronics interface + 60-67 - Calculator in slave mode + 70-77 - Modem + 80-87 - GPIB interface (?) + 90-97 - Bar code reader + 100-107 - Floppy disk drive + + Usage in MAME + ------------- + + mame -hexbus + + Usually the device offers an own hexbus socket, so we can chain devices: + + mame -hexbus -hexbus::hexbus ... + + 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_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_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. + + By default, instances of "hexbus_chained_device" own an outbound + hexbus slot as a subdevice; this may be overwritten by subclasses. + + References + ---------- + + [1] Intelligent Peripheral Bus: Structure, Timing, and Protocol Specification + Texas Instruments Inc., Consumer Products Group, Calculator Division, + 7/3/82, Revision 2.8 + + Michael Zapf + June 2017 + +*****************************************************************************/ +#include "emu.h" +#include "hexbus.h" + +// Devices +#include "hx5102.h" + +// Hexbus instance +DEFINE_DEVICE_TYPE_NS(HEXBUS, bus::hexbus, hexbus_device, "hexbus", "Hexbus") + +namespace bus { namespace hexbus { + +hexbus_device::hexbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, HEXBUS, tag, owner, clock), + device_slot_interface(mconfig, *this), + m_next_dev(nullptr) +{ +} + +void hexbus_device::device_start() +{ + m_next_dev = dynamic_cast(get_card_device()); +} + +/* + 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) +{ + 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); + } +} + +/* + 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) +{ + // Default is: all lines pulled up + uint8_t value = 0xff; + + if (dir == INBOUND) + value = m_chain_element->bus_read(INBOUND); + else + { + // Is there another Hexbus device? + if (m_next_dev != nullptr) + value = m_next_dev->bus_read(OUTBOUND); + } + return value; +} + +// ------------------------------------------------------------------------ + +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_hexbus_interface(mconfig, *this) +{ + m_hexbus_inbound = dynamic_cast(owner); + m_myvalue = 0xff; +} + +void hexbus_chained_device::device_start() +{ + m_hexbus_outbound = static_cast(subdevice("hexbus")); + + // Establish callback for inbound propagations + m_hexbus_outbound->set_chain_element(this); +} + +/* + 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) +{ + m_myvalue = data; + + uint8_t inbound_value = 0xff; + uint8_t outbound_value = 0xff; + + // 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); + + 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; + + // If it changed, propagate to both directions. + if (newvalue != m_current_bus_value) + { + hexbus_value_changed(newvalue); + m_current_bus_value = newvalue; + + if (m_hexbus_inbound != nullptr) + m_hexbus_inbound->write(INBOUND, m_current_bus_value); + + if (m_hexbus_outbound != nullptr) + m_hexbus_outbound->write(OUTBOUND, m_current_bus_value); + } +} + +/* + Called from the Hexbus user, that is, the device that subclasses + hexbus_chained_device, like the HX5102 +*/ +uint8_t hexbus_chained_device::hexbus_read() +{ + return m_current_bus_value; +} + +/* + Called from another hexbus device on the bus +*/ +uint8_t hexbus_chained_device::bus_read(int dir) +{ + uint8_t tmpvalue = 0xff; + hexbus_device* hexbuscont = (dir == INBOUND)? m_hexbus_inbound : m_hexbus_outbound; + + if (hexbuscont != nullptr) + tmpvalue = hexbuscont->read(dir); + + return m_myvalue & tmpvalue; +} + +/* + Called from another hexbus device on the bus +*/ +void hexbus_chained_device::bus_write(int dir, uint8_t data) +{ + hexbus_device* hexbuscont = (dir == INBOUND)? m_hexbus_inbound : m_hexbus_outbound; + + // Notify device + if (data != m_current_bus_value) + hexbus_value_changed(data); + + m_current_bus_value = data; + + // 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::hexbus + +SLOT_INTERFACE_START( hexbus_conn ) + SLOT_INTERFACE("hx5102", HX5102) +SLOT_INTERFACE_END + diff --git a/src/devices/bus/hexbus/hexbus.h b/src/devices/bus/hexbus/hexbus.h new file mode 100644 index 00000000000..3c3280cca91 --- /dev/null +++ b/src/devices/bus/hexbus/hexbus.h @@ -0,0 +1,123 @@ +// license:BSD-3-Clause +// copyright-holders:Michael Zapf +/**************************************************************************** + + Hexbus peripheral bus + See hexbus.cpp for documentation + + Michael Zapf + June 2017 + +*****************************************************************************/ + +#ifndef MAME_BUS_HEXBUS_HEXBUS_H +#define MAME_BUS_HEXBUS_HEXBUS_H + +#pragma once + +namespace bus { namespace hexbus { + +enum +{ + INBOUND = 0, + OUTBOUND = 1 +}; + +class hexbus_device; +class hexbus_chained_device; + +/******************************************************************** + Interface for a device that connects to the Hexbus +********************************************************************/ + +class device_hexbus_interface : public device_slot_card_interface +{ +public: + virtual uint8_t bus_read(int dir) =0; + virtual void bus_write(int dir, uint8_t data) =0; + +protected: + device_hexbus_interface(const machine_config &mconfig, device_t &device) : + device_slot_card_interface(mconfig, device) { } +}; + +/******************************************************************** + 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_hexbus_interface +{ + friend class hexbus_device; + +public: + 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: + virtual void device_add_mconfig(machine_config &config) override; + + void set_outbound_hexbus(hexbus_device *outbound) { m_hexbus_outbound = outbound; } + + // Link to the inbound Hexbus (if not null, see Oso chip) + hexbus_device *m_hexbus_inbound; + + // 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; + + // 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) { }; + + uint8_t m_myvalue; +}; + +// ------------------------------------------------------------------------ + +/******************************************************************** + Connector to the Hexbus, offers a slot for Hexbus-chained devices +********************************************************************/ + +class hexbus_device : public device_t, public device_slot_interface +{ +public: + hexbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // Used to establish the reverse link (inbound) + void set_chain_element(hexbus_chained_device* chain) { m_chain_element = chain; } + + // Read and write operations on the bus + uint8_t read(int dir); + void write(int dir, uint8_t data); + +protected: + void device_start() override; + device_hexbus_interface *m_next_dev; + +private: + // 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, HEXBUS, 0) \ + MCFG_DEVICE_SLOT_INTERFACE( hexbus_conn, nullptr, false) + +} } // end namespace bus::hexbus + +SLOT_INTERFACE_EXTERN( hexbus_conn ); + +DECLARE_DEVICE_TYPE_NS(HEXBUS, bus::hexbus, hexbus_device) + +#endif // MAME_BUS_HEXBUS_HEXBUS_H diff --git a/src/devices/bus/hexbus/hx5102.cpp b/src/devices/bus/hexbus/hx5102.cpp new file mode 100644 index 00000000000..71fe674506f --- /dev/null +++ b/src/devices/bus/hexbus/hx5102.cpp @@ -0,0 +1,35 @@ +// license:BSD-3-Clause +// copyright-holders:Michael Zapf +/**************************************************************************** + + Hexbus floppy disk drive + HX5102 + + Work in progress + + Michael Zapf + June 2017 + +*****************************************************************************/ + +#include "emu.h" +#include "hx5102.h" + +#define TRACE_HEXBUS 0 + +DEFINE_DEVICE_TYPE_NS(HX5102, bus::hexbus, hx5102_device, "hx5102", "TI Hexbus Floppy") + +namespace bus { namespace hexbus { + +hx5102_device::hx5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock): + hexbus_chained_device(mconfig, HX5102, tag, owner, clock) +{ +} + +void hx5102_device::hexbus_value_changed(uint8_t data) +{ + if (TRACE_HEXBUS) logerror("Hexbus value changed to %02x\n", data); +} + +} } // end namespace bus::hexbus + diff --git a/src/devices/bus/hexbus/hx5102.h b/src/devices/bus/hexbus/hx5102.h new file mode 100644 index 00000000000..fdb0c198f8d --- /dev/null +++ b/src/devices/bus/hexbus/hx5102.h @@ -0,0 +1,35 @@ +// license:BSD-3-Clause +// copyright-holders:Michael Zapf +/**************************************************************************** + + Hexbus floppy disk drive + HX5102 + + See hx5102.cpp for documentation + + Michael Zapf + June 2017 + +*****************************************************************************/ + +#ifndef MAME_BUS_HEXBUS_HX5102_H +#define MAME_BUS_HEXBUS_HX5102_H + +#pragma once + +#include "hexbus.h" + +namespace bus { namespace hexbus { + +class hx5102_device : public hexbus_chained_device +{ +public: + hx5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + void hexbus_value_changed(uint8_t data) override; +}; + +} } // end namespace bus::hexbus + +DECLARE_DEVICE_TYPE_NS(HX5102, bus::hexbus, hx5102_device) + +#endif // MAME_BUS_HEXBUS_HX5102_H diff --git a/src/devices/bus/ti99/hexbus/hexbus.cpp b/src/devices/bus/ti99/hexbus/hexbus.cpp deleted file mode 100644 index d8c315057c7..00000000000 --- a/src/devices/bus/ti99/hexbus/hexbus.cpp +++ /dev/null @@ -1,306 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:Michael Zapf -/**************************************************************************** - - =========== Hexbus peripheral bus =========== - - The Hexbus is a 4-bit peripheral bus with master/slave coordination. Bytes - are written over the bus in two passes. Hexbus was the designated standard - peripheral bus for TI computers before TI left the home computer market. - - The Hexbus was also named IPB = Intelligent Peripheral Bus [1] - - Existing devices are floppy drive, RS232 serial adapter, and - a "Wafertape" drive (kind of tape streamer) - - Hexbus connector (console) - +---+---+---+---+ - | 4 | 3 | 2 | 1 | 4 = L; 3 = BAV*; 2 = ADB1; 1 = ADB0 - +---+---+---+---+ - | 8 | 7 | 6 | 5 | 8 = ADB3; 7 = ADB2; 6 = nc; 5 = HSK* - +---+---+---+---+ - - ADBx = Hexbus data bit X (x=0..3) - HSK* = Handshake - BAV* = Bus available (0=yes) - - Theory of operation - ------------------- - The bus connects all devices in a daisy chain. The lines are inactive high - and pulled down by any device that sets them to 0. - - HSK* is a synchronization line for transmitting single bytes. - BAV* is a synchronization line for complete request-response pairs - - Before a byte can be sent, the sender must check the BAV* line. When it is - inactive (1), it pulls it down, and then starts transmitting. The line - is raised again when the response has been fully received. - - For transmitting a byte, the HSK* line must first be pulled down by the - sender. Then, the lower nibble is transmitted first, and the sender - releases the HSK* line. Every receiver that has completely received the - nibble and is ready for the next one releases the HSK* line. The sender - must check the HSK* line until it goes high again (which means that the - slowest receiver has got the nibble). This is repeated for the high nibble. - - When the BAV* signal is asserted (0), the HSK* line must not be high for - more than 20 ms, or a bus timeout occurs. - - The device address is transmitted as part of the request header. All - devices with a non-matching device code must ignore the rest of the - message until BAV* goes inactive (1) again. - - If there is no matching device, HSK* will remain 1 after the end of the - master's request, and after 20ms, a timeout will occur. Declaring a timeout - is a matter of the devices, not of the bus. - - Message format - -------------- - - +-------------+-------------+-------------+-------------+ - | Device Code | Command code| LogUnitNum | RecNum LSB | - +-------------+-------------+-------------+-------------+ - | RecNum MSB | Buflen LSB | Buflen MSB | DataLen LSB | - +-------------+-------------+-------------+-------------+ - | DataLen MSB | | - +-------------+ | - | Data ... (not padded) | - | | - | | - +-------------+-------------+-------------+-------------+ - - Device codes - ------------ - - 0 - all devices (but none will respond, forcing a timeout) - 1-8 - Tape mass storage - 10-17 - Printer / plotter - 20-27 - RS-232 interface - 30-37 - TV interface (color) - 40-47 - TV interface (B/W) - 50-57 - Centronics interface - 60-67 - Calculator in slave mode - 70-77 - Modem - 80-87 - GPIB interface (?) - 90-97 - Bar code reader - 100-107 - Floppy disk drive - - Usage in MAME - ------------- - - mame -hexbus - - Usually the device offers an own hexbus socket, so we can chain devices: - - mame -hexbus -hexbus::hexbus ... - - 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 - ---------- - - [1] Intelligent Peripheral Bus: Structure, Timing, and Protocol Specification - Texas Instruments Inc., Consumer Products Group, Calculator Division, - 7/3/82, Revision 2.8 - - Michael Zapf - June 2017 - -*****************************************************************************/ -#include "emu.h" -#include "hexbus.h" - -// Devices -#include "hx5102.h" - -// Hexbus instance -DEFINE_DEVICE_TYPE_NS(TI_HEXBUS, bus::ti99::hexbus, hexbus_device, "ti_hexbus", "Hexbus") - -namespace bus { namespace ti99 { namespace hexbus { - -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_next_dev(nullptr) -{ -} - -void hexbus_device::device_start() -{ - m_next_dev = dynamic_cast(get_card_device()); -} - -/* - 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) -{ - 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); - } -} - -/* - 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) -{ - // Default is: all lines pulled up - uint8_t value = 0xff; - - if (dir == INBOUND) - value = m_chain_element->bus_read(INBOUND); - else - { - // Is there another Hexbus device? - if (m_next_dev != nullptr) - value = m_next_dev->bus_read(OUTBOUND); - } - return value; -} - -// ------------------------------------------------------------------------ - -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(owner); - m_myvalue = 0xff; -} - -void hexbus_chained_device::device_start() -{ - m_hexbus_outbound = static_cast(subdevice("hexbus")); - - // Establish callback for inbound propagations - m_hexbus_outbound->set_chain_element(this); -} - -/* - 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) -{ - m_myvalue = data; - - uint8_t inbound_value = 0xff; - uint8_t outbound_value = 0xff; - - // 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); - - 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; - - // If it changed, propagate to both directions. - if (newvalue != m_current_bus_value) - { - hexbus_value_changed(newvalue); - m_current_bus_value = newvalue; - - if (m_hexbus_inbound != nullptr) - m_hexbus_inbound->write(INBOUND, m_current_bus_value); - - if (m_hexbus_outbound != nullptr) - m_hexbus_outbound->write(OUTBOUND, m_current_bus_value); - } -} - -/* - Called from the Hexbus user, that is, the device that subclasses - hexbus_chained_device, like the HX5102 -*/ -uint8_t hexbus_chained_device::hexbus_read() -{ - return m_current_bus_value; -} - -/* - Called from another hexbus device on the bus -*/ -uint8_t hexbus_chained_device::bus_read(int dir) -{ - uint8_t tmpvalue = 0xff; - hexbus_device* hexbuscont = (dir == INBOUND)? m_hexbus_inbound : m_hexbus_outbound; - - if (hexbuscont != nullptr) - tmpvalue = hexbuscont->read(dir); - - return m_myvalue & tmpvalue; -} - -/* - Called from another hexbus device on the bus -*/ -void hexbus_chained_device::bus_write(int dir, uint8_t data) -{ - hexbus_device* hexbuscont = (dir == INBOUND)? m_hexbus_inbound : m_hexbus_outbound; - - // Notify device - if (data != m_current_bus_value) - hexbus_value_changed(data); - - m_current_bus_value = data; - - // 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) -SLOT_INTERFACE_END - diff --git a/src/devices/bus/ti99/hexbus/hexbus.h b/src/devices/bus/ti99/hexbus/hexbus.h deleted file mode 100644 index 5c9f62274c2..00000000000 --- a/src/devices/bus/ti99/hexbus/hexbus.h +++ /dev/null @@ -1,124 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:Michael Zapf -/**************************************************************************** - - Hexbus peripheral bus - See hexbus.cpp for documentation - - Michael Zapf - June 2017 - -*****************************************************************************/ - -#ifndef MAME_BUS_TI99_HEXBUS_HEXBUS_H -#define MAME_BUS_TI99_HEXBUS_HEXBUS_H - -#pragma once - -#include "bus/ti99/ti99defs.h" - -namespace bus { namespace ti99 { namespace hexbus { - -enum -{ - INBOUND = 0, - OUTBOUND = 1 -}; - -class hexbus_device; -class hexbus_chained_device; - -/******************************************************************** - Interface for a device that connects to the Hexbus -********************************************************************/ - -class device_ti_hexbus_interface : public device_slot_card_interface -{ -public: - virtual uint8_t bus_read(int dir) =0; - virtual void bus_write(int dir, uint8_t data) =0; - -protected: - device_ti_hexbus_interface(const machine_config &mconfig, device_t &device) : - device_slot_card_interface(mconfig, device) { } -}; - -/******************************************************************** - 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 hexbus_device; - -public: - 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: - virtual void device_add_mconfig(machine_config &config) override; - - // Link to the inbound Hexbus (if not null, see Oso chip) - hexbus_device *m_hexbus_inbound; - - // 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; - - // 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: - uint8_t m_myvalue; -}; - -// ------------------------------------------------------------------------ - -/******************************************************************** - Connector to the Hexbus, offers a slot for Hexbus-chained devices -********************************************************************/ - -class hexbus_device : public device_t, public device_slot_interface -{ -public: - hexbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // Used to establish the reverse link (inbound) - void set_chain_element(hexbus_chained_device* chain) { m_chain_element = chain; } - - // Read and write operations on the bus - uint8_t read(int dir); - void write(int dir, uint8_t data); - -protected: - void device_start() override; - device_ti_hexbus_interface *m_next_dev; - -private: - // 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) - -} } } // end namespace bus::ti99::hexbus - -SLOT_INTERFACE_EXTERN( ti_hexbus_conn ); - -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 deleted file mode 100644 index e1bfb5fcbfa..00000000000 --- a/src/devices/bus/ti99/hexbus/hx5102.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:Michael Zapf -/**************************************************************************** - - Hexbus floppy disk drive - HX5102 - - Work in progress - - Michael Zapf - June 2017 - -*****************************************************************************/ - -#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): - hexbus_chained_device(mconfig, TI_HX5102, tag, owner, clock) -{ -} - -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 deleted file mode 100644 index c384305a9fd..00000000000 --- a/src/devices/bus/ti99/hexbus/hx5102.h +++ /dev/null @@ -1,35 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:Michael Zapf -/**************************************************************************** - - Hexbus floppy disk drive - HX5102 - - See hx5102.cpp for documentation - - Michael Zapf - June 2017 - -*****************************************************************************/ - -#ifndef MAME_BUS_TI99_HEXBUS_HX5102_H -#define MAME_BUS_TI99_HEXBUS_HX5102_H - -#pragma once - -#include "hexbus.h" - -namespace bus { namespace ti99 { namespace hexbus { - -class hx5102_device : public hexbus_chained_device -{ -public: - hx5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - void hexbus_value_changed(uint8_t data) override; -}; - -} } } // end namespace bus::ti99::hexbus - -DECLARE_DEVICE_TYPE_NS(TI_HX5102, bus::ti99::hexbus, hx5102_device) - -#endif // MAME_BUS_TI99_HEXBUS_HX5102_H diff --git a/src/devices/bus/ti99/internal/998board.cpp b/src/devices/bus/ti99/internal/998board.cpp index a89353051e9..f6eaf940e4d 100644 --- a/src/devices/bus/ti99/internal/998board.cpp +++ b/src/devices/bus/ti99/internal/998board.cpp @@ -426,6 +426,9 @@ WRITE_LINE_MEMBER( mainboard8_device::clock_in ) m_mofetta->skdrcs_in(m_amigo->skdrcs_out()); + // Clock to Oso + m_oso->clock_in(state); + int gromclk = m_mofetta->gromclk_out(); if (gromclk != m_gromclk) // when it changed, propagate to the GROMs @@ -2227,12 +2230,27 @@ enum SHSK = 0x01 }; +/* Control register bits */ +enum +{ + WIEN = 0x80, + RIEN = 0x40, + BAVIAEN = 0x20, + BAVAIEN = 0x10, + BAVC = 0x08, + WEN = 0x04, + REN = 0x02, + CR7 = 0x01 +}; + oso_device::oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - bus::ti99::hexbus::hexbus_chained_device(mconfig, TI99_OSO, tag, owner, clock), + bus::hexbus::hexbus_chained_device(mconfig, TI99_OSO, tag, owner, clock), m_data(0), - m_status(0), + m_status(0xff), m_control(0), - m_xmit(0) + m_xmit(0), + m_clkcount(0), + m_xmit_send(0) { m_hexbus_inbound = nullptr; m_hexbus_outbound = nullptr; @@ -2277,9 +2295,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_xmit_send = 2; m_status |= HSKWT; break; case 1: @@ -2299,13 +2315,31 @@ void oso_device::hexbus_value_changed(uint8_t data) if (TRACE_OSO) logerror("Hexbus value changed to %02x\n", data); } +/* + Phi3 incoming clock pulse +*/ +WRITE_LINE_MEMBER( oso_device::clock_in ) +{ + if (state==ASSERT_LINE) m_clkcount++; + if (m_clkcount > 30 && ((m_control & WEN)!=0) && (m_xmit_send > 0)) + { + if (TRACE_OSO) logerror("Write nibble %d\n", 3-m_xmit_send); + hexbus_write(((m_xmit & 0x0c)<<4) | (m_xmit & 0x03)); + m_xmit >>= 4; + m_clkcount = 0; + m_xmit_send--; + } +} + void oso_device::device_start() { logerror("Starting\n"); m_status = m_xmit = m_control = m_data = 0; - m_hexbus_outbound = dynamic_cast(machine().device(TI_HEXBUS_TAG)); + m_hexbus_outbound = dynamic_cast(machine().device(TI_HEXBUS_TAG)); + // Establish callback for inbound propagations + m_hexbus_outbound->set_chain_element(this); // Establish callback m_hexbus_outbound->set_chain_element(this); diff --git a/src/devices/bus/ti99/internal/998board.h b/src/devices/bus/ti99/internal/998board.h index a0d09062a54..bde035d7d73 100644 --- a/src/devices/bus/ti99/internal/998board.h +++ b/src/devices/bus/ti99/internal/998board.h @@ -20,7 +20,7 @@ #include "bus/ti99/ti99defs.h" #include "bus/ti99/gromport/gromport.h" -#include "bus/ti99/hexbus/hexbus.h" +#include "bus/hexbus/hexbus.h" #include "bus/ti99/internal/ioport.h" #include "machine/ram.h" @@ -422,21 +422,29 @@ private: /* Custom chip: OSO */ -class oso_device : public bus::ti99::hexbus::hexbus_chained_device +class oso_device : public bus::hexbus::hexbus_chained_device { public: oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); DECLARE_READ8_MEMBER( read ); DECLARE_WRITE8_MEMBER( write ); void device_start() override; + // Don't add a hexbus connector; we use the one from the driver instance + virtual void device_add_mconfig(machine_config &config) override { }; void hexbus_value_changed(uint8_t data) override; + WRITE_LINE_MEMBER( clock_in ); + private: uint8_t m_data; uint8_t m_status; uint8_t m_control; uint8_t m_xmit; + + int m_clkcount; + + int m_xmit_send; }; class mainboard8_device : public device_t diff --git a/src/mame/drivers/ti99_8.cpp b/src/mame/drivers/ti99_8.cpp index 71d00d8947f..7f84f2ca701 100644 --- a/src/mame/drivers/ti99_8.cpp +++ b/src/mame/drivers/ti99_8.cpp @@ -183,7 +183,7 @@ Known Issues (MZ, 2010-11-07) #include "bus/ti99/internal/998board.h" #include "bus/ti99/gromport/gromport.h" -#include "bus/ti99/hexbus/hexbus.h" +#include "bus/hexbus/hexbus.h" #include "bus/ti99/joyport/joyport.h" #include "bus/ti99/internal/ioport.h" -- cgit v1.2.3