From 1f4182111b5c5bb6a1313855e9e5c84263c351c6 Mon Sep 17 00:00:00 2001 From: Joakim Larsson Edstrom Date: Tue, 6 Jun 2017 13:34:13 +0200 Subject: [PATCH 1/2] Added license --- src/mame/drivers/dbox.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mame/drivers/dbox.cpp b/src/mame/drivers/dbox.cpp index bb686cfb251..38f0092e7bd 100644 --- a/src/mame/drivers/dbox.cpp +++ b/src/mame/drivers/dbox.cpp @@ -1,3 +1,5 @@ +// license:BSD-3-Clause +// copyright-holders:Joakim Larsson Edstrom /* * The Dbox-1 CPU board. *__________________________________________________________________________________________________________ From 6e577c54653e7d1d53426166d7de23216d88699a Mon Sep 17 00:00:00 2001 From: Michael Zapf Date: Tue, 6 Jun 2017 16:21:51 +0200 Subject: [PATCH 2/2] ti99: Hexbus implementation; floppy HX5102 early WIP --- scripts/src/bus.lua | 6 +- src/devices/bus/ti99/hexbus/hexbus.cpp | 282 +++++++++++++++++++++ src/devices/bus/ti99/hexbus/hexbus.h | 141 +++++++++++ src/devices/bus/ti99/hexbus/hx5102.cpp | 28 ++ src/devices/bus/ti99/hexbus/hx5102.h | 34 +++ src/devices/bus/ti99/internal/998board.cpp | 12 +- src/devices/bus/ti99/internal/998board.h | 5 +- src/devices/bus/ti99/ti99defs.h | 1 + src/mame/drivers/ti99_8.cpp | 4 + 9 files changed, 509 insertions(+), 4 deletions(-) create mode 100644 src/devices/bus/ti99/hexbus/hexbus.cpp create mode 100644 src/devices/bus/ti99/hexbus/hexbus.h create mode 100644 src/devices/bus/ti99/hexbus/hx5102.cpp create mode 100644 src/devices/bus/ti99/hexbus/hx5102.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 49600891ed3..3f7e1d1a341 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2362,7 +2362,7 @@ 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 @@ -2392,6 +2392,10 @@ 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/src/devices/bus/ti99/hexbus/hexbus.cpp b/src/devices/bus/ti99/hexbus/hexbus.cpp new file mode 100644 index 00000000000..794d1d344d3 --- /dev/null +++ b/src/devices/bus/ti99/hexbus/hexbus.cpp @@ -0,0 +1,282 @@ +// 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 + ------------- + + Single device usage: + mame -hexbus + + Multiple device usage: + mame -hexbus chain -hexbus:chain:1 ... -hexbus:chain:4 + + 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. + + 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") + +// 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) +{ +} + +void hexbus_device::device_start() +{ +} + +void hexbus_device::device_config_complete() +{ + m_slave = static_cast(subdevices().first()); + if (m_slave != nullptr) + m_slave->set_hexbus(this); +} + +void hexbus_device::send() +{ + uint8_t sum = m_master->get_value(); + if (m_slave != nullptr) + { + sum &= m_slave->get_value(); + m_slave->receive(sum); + } + m_master->receive(sum); +} + +// ------------------------------------------------------------------------ + +hexbus_chain_device::hexbus_chain_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + hexbus_attached_device(mconfig, TI_HEXBUS_CHAIN, tag, owner, clock) +{ +} + +uint8_t hexbus_chain_device::get_value() +{ + uint8_t sum = 0xff; + + // Do the wired AND + for (device_t &child : subdevices()) + { + hexbus_slot_device* slot = downcast(&child); + sum &= slot->get_value(); + } + + return sum; +} + +void hexbus_chain_device::receive(uint8_t value) +{ + // Propagate + for (device_t &child : subdevices()) + { + hexbus_slot_device* slot = downcast(&child); + slot->receive(value); + } +} + +void hexbus_chain_device::device_start() +{ +} + +SLOT_INTERFACE_START( ti_hexbus_chain_slot ) +// SLOT_INTERFACE("hx5102", TI_HX5102) // not an option yet +SLOT_INTERFACE_END + +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 + +// ------------------------------------------------------------------------ + +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; + + return atoi(mytag+i+1); +} + +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) +{ +} + +/* Called from the Hexbus instance */ +int hexbus_slot_device::get_index() +{ + if (m_hexbdev == nullptr) return NOTCONN; + return get_index_from_tagname(); +} + +uint8_t hexbus_slot_device::get_value() +{ + return (m_hexbdev != nullptr)? m_hexbdev->get_value() : 0xff; +} + +void hexbus_slot_device::receive(uint8_t value) +{ + if (m_hexbdev != nullptr) + m_hexbdev->receive(value); +} + +void hexbus_slot_device::device_start() +{ +} + +void hexbus_slot_device::device_config_complete() +{ + m_hexbus = dynamic_cast(owner()); + m_hexbdev = downcast(subdevices().first()); +} + +// ------------------------------------------------------------------------ + +hexbus_attached_device::hexbus_attached_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_slot_card_interface(mconfig, *this) +{ +} + +void hexbus_attached_device::device_start() +{ +} + +void hexbus_attached_device::hexbus_send(uint8_t value) +{ + m_value = value; + m_hexbus->send(); +} + +} } } // 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_END + diff --git a/src/devices/bus/ti99/hexbus/hexbus.h b/src/devices/bus/ti99/hexbus/hexbus.h new file mode 100644 index 00000000000..c29a9813e37 --- /dev/null +++ b/src/devices/bus/ti99/hexbus/hexbus.h @@ -0,0 +1,141 @@ +// license:LGPL-2.1+ +// copyright-holders:Michael Zapf +/**************************************************************************** + + Hexbus peripheral bus + See hexbus.cpp for documentation + + Michael Zapf + June 2017 + + -hexbus:1 hx5102 -hexbus:2 ... + +*****************************************************************************/ + +#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 +{ + MAX_DEVICES = 4 +}; + +class hexbus_attached_device; +class hexbus_slot_device; + +class hexbus_device : public device_t, public device_slot_interface +{ + friend class hexbus_attached_device; + +public: + hexbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + void connect_master(hexbus_attached_device *masterdev) { m_master = masterdev; } + +protected: + void device_start() override; + void device_config_complete() override; + +private: + hexbus_attached_device *m_master; + hexbus_attached_device *m_slave; + + // Called from a slot, samples all values from the devices, and propagates + // the logical product to all connected devices + void send(); +}; + +/***************************************************************************** + The parent class for all Hexbus devices +******************************************************************************/ + +class hexbus_attached_device : public device_t, public device_slot_card_interface +{ + friend class hexbus_slot_device; + friend class hexbus_device; + +protected: + hexbus_attached_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + void device_start() override; + + 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; } + +private: + void set_hexbus(hexbus_device* hexbus) { m_hexbus = hexbus; } + + uint8_t m_value; + uint8_t m_busvalue; + hexbus_device *m_hexbus; // Link to the Hexbus +}; + +// ------------------------------------------------------------------------ + +class hexbus_chain_device : public hexbus_attached_device +{ +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; + +private: + void device_start() override; + void receive(uint8_t value) override; + uint8_t get_value() override; +}; + +// ------------------------------------------------------------------------ + +class hexbus_slot_device : public device_t, public device_slot_interface +{ + friend class hexbus_attached_device; + friend class hexbus_chain_device; + +public: + hexbus_slot_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); + + // Called from the hexbus + uint8_t get_value(); + +protected: + void device_start() override; + void device_config_complete() override; + + // Called from the Hexbus instance + int get_index(); + +private: + int get_index_from_tagname(); + + hexbus_attached_device* m_hexbdev; + hexbus_device* m_hexbus; +}; + + +#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) + +#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 new file mode 100644 index 00000000000..250c015b0d6 --- /dev/null +++ b/src/devices/bus/ti99/hexbus/hx5102.cpp @@ -0,0 +1,28 @@ +// 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_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_attached_device(mconfig, TI_HX5102, tag, owner, clock) +{ +} + +} } } // end namespace bus::ti99::hexbus + diff --git a/src/devices/bus/ti99/hexbus/hx5102.h b/src/devices/bus/ti99/hexbus/hx5102.h new file mode 100644 index 00000000000..1381ffd4c86 --- /dev/null +++ b/src/devices/bus/ti99/hexbus/hx5102.h @@ -0,0 +1,34 @@ +// 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_attached_device +{ +public: + hx5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + +} } } // 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 ea93c9b77cb..e8e47be74fb 100644 --- a/src/devices/bus/ti99/internal/998board.cpp +++ b/src/devices/bus/ti99/internal/998board.cpp @@ -2232,8 +2232,12 @@ enum SHSK = 0x01 }; -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), m_data(0), m_status(0), m_control(0), m_xmit(0) +oso_device::oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + bus::ti99::hexbus::hexbus_attached_device(mconfig, TI99_OSO, tag, owner, clock), + m_data(0), + m_status(0), + m_control(0), + m_xmit(0) { } @@ -2296,6 +2300,10 @@ void oso_device::device_start() { logerror("Starting\n"); m_status = m_xmit = m_control = m_data = 0; + + m_hexbus = downcast(machine().device(TI_HEXBUS_TAG)); + m_hexbus->connect_master(this); + save_item(NAME(m_data)); save_item(NAME(m_status)); save_item(NAME(m_control)); diff --git a/src/devices/bus/ti99/internal/998board.h b/src/devices/bus/ti99/internal/998board.h index ca1b7c1e5ba..240cb2c6951 100644 --- a/src/devices/bus/ti99/internal/998board.h +++ b/src/devices/bus/ti99/internal/998board.h @@ -20,6 +20,7 @@ #include "bus/ti99/ti99defs.h" #include "bus/ti99/gromport/gromport.h" +#include "bus/ti99/hexbus/hexbus.h" #include "bus/ti99/internal/ioport.h" #include "machine/ram.h" @@ -371,7 +372,7 @@ private: /* Custom chip: OSO */ -class oso_device : public device_t +class oso_device : public bus::ti99::hexbus::hexbus_attached_device { public: oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -384,6 +385,8 @@ private: 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 diff --git a/src/devices/bus/ti99/ti99defs.h b/src/devices/bus/ti99/ti99defs.h index 1f0d549e2bb..43f18796ce0 100644 --- a/src/devices/bus/ti99/ti99defs.h +++ b/src/devices/bus/ti99/ti99defs.h @@ -43,6 +43,7 @@ #define MAPPER_TAG "mapper" #define MAINBOARD8_TAG "mainboard8" #define SPEECHSYN_TAG "speech" +#define TI_HEXBUS_TAG "hexbus" #define ROM0_REG "rom0_region" #define ROM1_REG "rom1_region" diff --git a/src/mame/drivers/ti99_8.cpp b/src/mame/drivers/ti99_8.cpp index 8e74cf7b71e..adbb8f7e65c 100644 --- a/src/mame/drivers/ti99_8.cpp +++ b/src/mame/drivers/ti99_8.cpp @@ -183,6 +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/ti99/joyport/joyport.h" #include "bus/ti99/internal/ioport.h" @@ -763,6 +764,9 @@ static MACHINE_CONFIG_START( ti99_8 ) MCFG_IOPORT_EXTINT_HANDLER( WRITELINE(ti99_8_state, extint) ) MCFG_IOPORT_READY_HANDLER( DEVWRITELINE(MAINBOARD8_TAG, bus::ti99::internal::mainboard8_device, pbox_ready) ) + // Hexbus + MCFG_HEXBUS_ADD( TI_HEXBUS_TAG ) + // Sound hardware MCFG_SPEAKER_STANDARD_MONO("sound_out") MCFG_SOUND_ADD(TISOUNDCHIP_TAG, SN76496, 3579545) /* 3.579545 MHz */