diff options
Diffstat (limited to 'src/devices/bus/hexbus/hexbus.cpp')
-rw-r--r-- | src/devices/bus/hexbus/hexbus.cpp | 91 |
1 files changed, 80 insertions, 11 deletions
diff --git a/src/devices/bus/hexbus/hexbus.cpp b/src/devices/bus/hexbus/hexbus.cpp index 768910752a2..5fec624ab39 100644 --- a/src/devices/bus/hexbus/hexbus.cpp +++ b/src/devices/bus/hexbus/hexbus.cpp @@ -150,7 +150,8 @@ // Devices #include "hx5102.h" -#define LOG_WRITE (1U<<1) // Write operation +#define LOG_LINES (1U<<1) // Line changes +#define LOG_ENABLED (1U<<2) // Enabled #define VERBOSE ( LOG_GENERAL ) @@ -222,10 +223,11 @@ uint8_t hexbus_device::read(int dir) 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) + device_hexbus_interface(mconfig, *this), + m_enabled(false), + m_myvalue(0xff) { m_hexbus_inbound = dynamic_cast<hexbus_device *>(owner); - m_myvalue = 0xff; } void hexbus_chained_device::device_start() @@ -242,21 +244,31 @@ void hexbus_chained_device::device_start() */ void hexbus_chained_device::hexbus_write(uint8_t data) { + uint8_t oldvalue = m_myvalue; m_myvalue = data; + set_communication_enabled(true); uint8_t otherval = hexbus_get_levels(); - // LOGMASKED(LOG_WRITE, ".. otherval=%02x\n", otherval); - // What is the new bus level? // The data lines are not supposed to be set by multiple devices // We assume that sending data overrides all data line levels. // This is emulated by pulling the data lines to ones. uint8_t newvalue = (otherval | 0xc3) & m_myvalue; + if (hsk_line(oldvalue)==ASSERT_LINE && own_hsk_level()==CLEAR_LINE) + LOGMASKED(LOG_LINES, "Release HSK*\n"); + + bool hsk_changed = (hsk_line(newvalue) != hsk_line(m_current_bus_value)); + bool bav_changed = (bav_line(newvalue) != bav_line(m_current_bus_value)); + // If it changed (with respect to HSK* or BAV*), propagate to both directions. - if ((newvalue & (HEXBUS_LINE_HSK | HEXBUS_LINE_BAV)) != (m_current_bus_value & (HEXBUS_LINE_HSK | HEXBUS_LINE_BAV))) + if (hsk_changed || bav_changed) { - LOGMASKED(LOG_WRITE, "Trying to write %02x, actually: %02x (current=%02x)\n", data, newvalue, m_current_bus_value); + if (hsk_changed && own_hsk_level()==ASSERT_LINE) + LOGMASKED(LOG_LINES, "Pull down HSK*, send data=%x\n", data_lines(m_myvalue)); + + if (bav_changed) + LOGMASKED(LOG_LINES, "%s BAV*\n", (own_bav_level()==ASSERT_LINE)? "Pull down" : "Release"); m_current_bus_value = newvalue; @@ -265,9 +277,38 @@ void hexbus_chained_device::hexbus_write(uint8_t data) if (m_hexbus_outbound != nullptr) m_hexbus_outbound->write(OUTBOUND, m_current_bus_value); - } - else LOGMASKED(LOG_WRITE, "No change on hexbus\n"); +} + +/* + Assert or release the HSK* line. +*/ +void hexbus_chained_device::set_hsk_line(line_state level) +{ + if (level==ASSERT_LINE) + hexbus_write(m_myvalue & ~HEXBUS_LINE_HSK); + else + hexbus_write(m_myvalue | HEXBUS_LINE_HSK); +} + +/* + Assert or release the BAV* line. +*/ +void hexbus_chained_device::set_bav_line(line_state level) +{ + if (level==ASSERT_LINE) + hexbus_write(m_myvalue & ~HEXBUS_LINE_BAV); + else + hexbus_write(m_myvalue | HEXBUS_LINE_BAV); +} + +void hexbus_chained_device::set_data_latch(int value, int pos) +{ + const uint8_t hexbval[4] = { 0x01, 0x02, 0x40, 0x80 }; + if (value==0) + m_myvalue &= ~hexbval[pos]; + else + m_myvalue |= hexbval[pos]; } /* @@ -325,17 +366,45 @@ void hexbus_chained_device::bus_write(int dir, uint8_t data) uint8_t oldvalue = m_current_bus_value; m_current_bus_value = data; + // When disabled, just propagate, and then return + if (!m_enabled) return; + + bool hsk_changed = (hsk_line(data) != hsk_line(oldvalue)); + // Notify device // Caution: Calling hexbus_value_changed may cause further activities that change the bus again // Data changes alone shall not trigger the callback - if ((data & (HEXBUS_LINE_HSK | HEXBUS_LINE_BAV)) != (oldvalue & (HEXBUS_LINE_HSK | HEXBUS_LINE_BAV))) + if (hsk_changed || (bav_line(data) != bav_line(oldvalue))) { - LOGMASKED(LOG_WRITE, "Hexbus value changed: %02x -> %02x\n", oldvalue, data); + if (hsk_changed) + { + if (hsk_line(data)==ASSERT_LINE) LOGMASKED(LOG_LINES, "Sense HSK*=0, got data=%x\n", data_lines(data)); + else + { + LOGMASKED(LOG_LINES, "Sense HSK*=1\n"); + // According to [1], HSK* going high writes ones into the data latch + m_myvalue |= 0xc3; + } + } + else LOGMASKED(LOG_LINES, "Sense BAV*=%d\n", bav_line(data)==CLEAR_LINE? 1:0); + hexbus_value_changed(data); } } /* + Enable or disable this component. +*/ +void hexbus_chained_device::set_communication_enabled(bool set) +{ + if (m_enabled != set) + LOGMASKED(LOG_ENABLED, "Hexbus listen %s\n", set? "enabled" : "disabled"); + m_enabled = set; + + if (!m_enabled) m_myvalue = 0xff; +} + +/* Convenience function to calculate the bus value. Used by subclasses. */ uint8_t hexbus_chained_device::to_line_state(uint8_t data, bool bav, bool hsk) |