summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/ti99/internal/998board.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/ti99/internal/998board.cpp')
-rw-r--r--src/devices/bus/ti99/internal/998board.cpp435
1 files changed, 262 insertions, 173 deletions
diff --git a/src/devices/bus/ti99/internal/998board.cpp b/src/devices/bus/ti99/internal/998board.cpp
index 486130d5ac9..9a4fc5cca8e 100644
--- a/src/devices/bus/ti99/internal/998board.cpp
+++ b/src/devices/bus/ti99/internal/998board.cpp
@@ -106,6 +106,26 @@
#include "emu.h"
#include "998board.h"
+#define LOG_DETAIL (1U<<1) // More detail
+#define LOG_CRU (1U<<2) // CRU logging
+#define LOG_ADDRESS (1U<<3) // Address bus
+#define LOG_MEM (1U<<4) // Memory access
+#define LOG_MAP (1U<<5) // Mapper
+#define LOG_READY (1U<<6) // READY line
+#define LOG_CLOCK (1U<<7) // CLKOUT
+#define LOG_MOFETTA (1U<<8) // Mofetta operation
+#define LOG_AMIGO (1U<<9) // Amigo operation
+#define LOG_OSO (1U<<10) // Oso operation
+#define LOG_HEXBUS (1U<<11) // Hexbus operation
+#define LOG_WS (1U<<12) // Wait states
+#define LOG_CPURY (1U<<13) // Combined ready line
+#define LOG_GROM (1U<<14) // GROM operation
+#define LOG_PUNMAP (1U<<15) // Unmapped physical addresss
+
+#define VERBOSE ( LOG_GENERAL )
+
+#include "logmacro.h"
+
DEFINE_DEVICE_TYPE_NS(TI99_MAINBOARD8, bus::ti99::internal, mainboard8_device, "ti998_mainboard", "TI-99/8 Mainboard")
DEFINE_DEVICE_TYPE_NS(TI99_VAQUERRO, bus::ti99::internal, vaquerro_device, "ti998_vaquerro", "TI-99/8 Logical Address Space Decoder")
DEFINE_DEVICE_TYPE_NS(TI99_MOFETTA, bus::ti99::internal, mofetta_device, "ti998_mofetta", "TI-99/8 Physical Address Space Decoder")
@@ -114,22 +134,6 @@ DEFINE_DEVICE_TYPE_NS(TI99_AMIGO, bus::ti99::internal, amigo_device, "ti998_amig
namespace bus { namespace ti99 { namespace internal {
-#define TRACE_CRU 0
-#define TRACE_ADDRESS 0
-#define TRACE_MAP 0
-#define TRACE_OSO 0
-#define TRACE_DECODE 0
-#define TRACE_READY 0
-#define TRACE_MEM 0
-#define TRACE_CLOCK 0
-#define TRACE_DETAIL 0
-#define TRACE_MOFETTA 0
-#define TRACE_AMIGO 0
-#define TRACE_WS 0
-#define TRACE_CPURY 0
-#define TRACE_GROM 0
-#define TRACE_PUNMAP 0
-
enum
{
SGMSEL = 1,
@@ -345,7 +349,7 @@ WRITE_LINE_MEMBER( mainboard8_device::dbin_in )
SETOFFSET_MEMBER( mainboard8_device::setoffset )
{
- if (TRACE_ADDRESS) logerror("set %s %04x\n", (m_dbin_level==ASSERT_LINE)? "R" : "W", offset);
+ LOGMASKED(LOG_ADDRESS, "set %s %04x\n", (m_dbin_level==ASSERT_LINE)? "R" : "W", offset);
// No data is waiting on the data bus
m_pending_write = false;
@@ -407,7 +411,7 @@ WRITE_LINE_MEMBER( mainboard8_device::holda_line )
*/
WRITE_LINE_MEMBER( mainboard8_device::clock_in )
{
- if (TRACE_CLOCK) logerror("CLKOUT = %d\n", state);
+ LOGMASKED(LOG_CLOCK, "CLKOUT = %d\n", state);
// Propagate to Vaquerro; may change GGRDY (trailing edge) and the GROM select lines
m_vaquerro->clock_in((line_state)state);
@@ -469,7 +473,7 @@ WRITE_LINE_MEMBER( mainboard8_device::clock_in )
if (m_A14_set) m_video->register_write(*m_space, 0, m_latched_data);
else m_video->vram_write(*m_space, 0, m_latched_data);
m_pending_write = false;
- if (TRACE_MEM) logerror("Write %04x (video) <- %02x\n", m_logical_address, m_latched_data);
+ LOGMASKED(LOG_MEM, "Write %04x (video) <- %02x\n", m_logical_address, m_latched_data);
cycle_end();
return;
}
@@ -486,14 +490,14 @@ WRITE_LINE_MEMBER( mainboard8_device::clock_in )
{
m_dram->pointer()[m_physical_address & 0xffff] = m_latched_data;
m_pending_write = false;
- if (TRACE_MEM) logerror("Write %04x (phys %06x, DRAM) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
+ LOGMASKED(LOG_MEM, "Write %04x (phys %06x, DRAM) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
}
if (m_mofetta->alccs_out()==ASSERT_LINE)
{
m_oso->write(*m_space, m_physical_address>>1, m_latched_data);
m_pending_write = false;
- if (TRACE_MEM) logerror("Write %04x (phys %06x, OSO) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
+ LOGMASKED(LOG_MEM, "Write %04x (phys %06x, OSO) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
}
if (m_mofetta->cmas_out()==ASSERT_LINE)
@@ -501,7 +505,7 @@ WRITE_LINE_MEMBER( mainboard8_device::clock_in )
m_gromport->romgq_line(ASSERT_LINE);
m_gromport->write(*m_space, m_physical_address & 0x3fff, m_latched_data);
m_pending_write = false;
- if (TRACE_MEM) logerror("Write %04x (phys %06x, cartridge) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
+ LOGMASKED(LOG_MEM, "Write %04x (phys %06x, cartridge) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
}
else
{
@@ -512,7 +516,7 @@ WRITE_LINE_MEMBER( mainboard8_device::clock_in )
{
m_ioport->write(*m_space, m_physical_address, m_latched_data);
m_pending_write = false;
- if (TRACE_MEM) logerror("Write %04x (phys %06x, PEB) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
+ LOGMASKED(LOG_MEM, "Write %04x (phys %06x, PEB) <- %02x\n", m_logical_address, m_physical_address, m_latched_data);
}
}
@@ -553,7 +557,7 @@ void mainboard8_device::select_groms()
for (int i=0; i < 3; i++)
m_p3grom[i]->set_lines(*m_space, lines, select & P3GSEL);
- // Write to the cartridge port. The GROMs on cartridges are accesses as system GROMs
+ // Write to the cartridge port. The GROMs on cartridges are accessed as system GROMs
if (select & SGMSEL) m_gromport->romgq_line(CLEAR_LINE);
m_gromport->set_gromlines(*m_space, lines, select & SGMSEL);
}
@@ -569,7 +573,7 @@ void mainboard8_device::select_groms()
{
m_sgrom[i]->write(*m_space, 0, m_latched_data);
}
- if (TRACE_MEM) logerror("Write GS <- %02x\n", m_latched_data);
+ LOGMASKED(LOG_MEM, "Write GS <- %02x\n", m_latched_data);
m_gromport->write(*m_space, 0, m_latched_data);
break;
@@ -578,7 +582,7 @@ void mainboard8_device::select_groms()
{
m_tsgrom[i]->write(*m_space, 0, m_latched_data);
}
- if (TRACE_MEM) logerror("Write GT <- %02x\n", m_latched_data);
+ LOGMASKED(LOG_MEM, "Write GT <- %02x\n", m_latched_data);
break;
case P8GSEL:
@@ -586,7 +590,7 @@ void mainboard8_device::select_groms()
{
m_p8grom[i]->write(*m_space, 0, m_latched_data);
}
- if (TRACE_MEM) logerror("Write G8 <- %02x\n", m_latched_data);
+ LOGMASKED(LOG_MEM, "Write G8 <- %02x\n", m_latched_data);
break;
case P3GSEL:
@@ -594,7 +598,7 @@ void mainboard8_device::select_groms()
{
m_p3grom[i]->write(*m_space, 0, m_latched_data);
}
- if (TRACE_MEM) logerror("Write G3 <- %02x\n", m_latched_data);
+ LOGMASKED(LOG_MEM, "Write G3 <- %02x\n", m_latched_data);
break;
default:
@@ -608,7 +612,7 @@ void mainboard8_device::set_paddress(int address)
{
// Keep this value as the current address
m_physical_address = (m_physical_address << 16) | address;
- if (TRACE_DETAIL) logerror("Setting physical address %06x\n", m_physical_address);
+ LOGMASKED(LOG_DETAIL, "Setting physical address %06x\n", m_physical_address);
m_mofetta->set_address(*m_space, address, m_dbin_level);
m_ioport->setaddress_dbin(*m_space, address, m_dbin_level);
@@ -616,7 +620,7 @@ void mainboard8_device::set_paddress(int address)
WRITE_LINE_MEMBER( mainboard8_device::msast_in )
{
- if (TRACE_DETAIL) logerror("msast = %d\n", state);
+ LOGMASKED(LOG_DETAIL, "msast = %d\n", state);
// Start physical space cycle on the trailing edge
if (state==CLEAR_LINE)
@@ -692,7 +696,7 @@ READ8_MEMBER( mainboard8_device::read )
m_sgrom[i]->readz(space, 0, &value);
}
m_gromport->readz(space, 0, &value);
- if (TRACE_GROM && !m_A14_set) logerror("GS>%04x\n", m_sgrom[0]->debug_get_address()-1);
+ if (!m_A14_set) LOGMASKED(LOG_GROM, "GS>%04x\n", m_sgrom[0]->debug_get_address()-1);
what = "system GROM";
goto readdone;
@@ -702,7 +706,7 @@ READ8_MEMBER( mainboard8_device::read )
{
m_tsgrom[i]->readz(space, 0, &value);
}
- if (TRACE_GROM && !m_A14_set) logerror("GT>%04x\n", m_tsgrom[0]->debug_get_address()-1);
+ if (!m_A14_set) LOGMASKED(LOG_GROM, "GT>%04x\n", m_tsgrom[0]->debug_get_address()-1);
what = "TTS GROM";
goto readdone;
@@ -712,7 +716,7 @@ READ8_MEMBER( mainboard8_device::read )
{
m_p8grom[i]->readz(space, 0, &value);
}
- if (TRACE_GROM && !m_A14_set) logerror("G8>%04x\n", m_p8grom[0]->debug_get_address()-1);
+ if (!m_A14_set) LOGMASKED(LOG_GROM, "G8>%04x\n", m_p8grom[0]->debug_get_address()-1);
what = "P8 GROM";
goto readdone;
@@ -722,7 +726,7 @@ READ8_MEMBER( mainboard8_device::read )
{
m_p3grom[i]->readz(space, 0, &value);
}
- if (TRACE_GROM && !m_A14_set) logerror("G3>%04x\n", m_p3grom[0]->debug_get_address()-1);
+ if (!m_A14_set) LOGMASKED(LOG_GROM, "G3>%04x\n", m_p3grom[0]->debug_get_address()-1);
what = "P3 GROM";
goto readdone;
default:
@@ -758,7 +762,7 @@ READ8_MEMBER( mainboard8_device::read )
if (m_mofetta->rom1al_out()==ASSERT_LINE) address |= 0x2000;
value = m_rom1[address];
- if (TRACE_MEM) logerror("Read %04x (ROM1@%04x) -> %02x\n", m_logical_address, address, value);
+ LOGMASKED(LOG_MEM, "Read %04x (ROM1@%04x) -> %02x\n", m_logical_address, address, value);
cycle_end();
return value;
}
@@ -792,7 +796,7 @@ READ8_MEMBER( mainboard8_device::read )
goto readdonephys;
}
- if (TRACE_PUNMAP) logerror("Read %04x (phys %06x, unmapped) ignored\n", m_logical_address, m_physical_address);
+ LOGMASKED(LOG_PUNMAP, "Read %04x (phys %06x, unmapped) ignored\n", m_logical_address, m_physical_address);
// Memory cycle ends
cycle_end();
@@ -801,12 +805,12 @@ READ8_MEMBER( mainboard8_device::read )
readdone:
- if (TRACE_MEM) logerror("Read %04x (%s) -> %02x\n", m_logical_address, what, value);
+ LOGMASKED(LOG_MEM, "Read %04x (%s) -> %02x\n", m_logical_address, what, value);
cycle_end();
return value;
readdonephys:
- if (TRACE_MEM) logerror("Read %04x (phys %06x, %s) -> %02x\n", m_logical_address, m_physical_address, what, value);
+ LOGMASKED(LOG_MEM, "Read %04x (phys %06x, %s) -> %02x\n", m_logical_address, m_physical_address, what, value);
cycle_end();
return value;
}
@@ -841,7 +845,7 @@ WRITE8_MEMBER( mainboard8_device::write )
// GROMs and video must wait to be selected
if (m_amigo->mapper_accessed())
{
- if (TRACE_MEM) logerror("Write %04x (mapper) <- %02x\n", m_logical_address, data);
+ LOGMASKED(LOG_MEM, "Write %04x (mapper) <- %02x\n", m_logical_address, data);
m_amigo->write(space, 0, data);
m_pending_write = false;
}
@@ -850,7 +854,7 @@ WRITE8_MEMBER( mainboard8_device::write )
// sound address lies within the SRAM area
if (m_vaquerro->sccs_out()==ASSERT_LINE)
{
- if (TRACE_MEM) logerror("Write %04x (sound) <- %02x\n", m_logical_address, data);
+ LOGMASKED(LOG_MEM, "Write %04x (sound) <- %02x\n", m_logical_address, data);
m_sound->write(space, 0, data); // Sound chip will lower READY after this access
m_pending_write = false;
}
@@ -859,7 +863,7 @@ WRITE8_MEMBER( mainboard8_device::write )
// SRAM
if (m_amigo->sramcs_out()==ASSERT_LINE)
{
- if (TRACE_MEM) logerror("Write %04x (SRAM) <- %02x\n", m_logical_address, data);
+ LOGMASKED(LOG_MEM, "Write %04x (SRAM) <- %02x\n", m_logical_address, data);
m_sram->pointer()[m_logical_address & 0x07ff] = data;
m_pending_write = false;
}
@@ -868,7 +872,7 @@ WRITE8_MEMBER( mainboard8_device::write )
// Speech
if (m_vaquerro->spwt_out()==ASSERT_LINE)
{
- if (TRACE_MEM) logerror("Write %04x (speech) <- %02x\n", m_logical_address, data);
+ LOGMASKED(LOG_MEM, "Write %04x (speech) <- %02x\n", m_logical_address, data);
m_speech->data_w(space, 0, data);
m_pending_write = false;
}
@@ -884,7 +888,7 @@ WRITE8_MEMBER( mainboard8_device::write )
*/
WRITE_LINE_MEMBER( mainboard8_device::crus_in )
{
- if (TRACE_CRU) logerror("%s CRUS\n", (state==1)? "Assert" : "Clear");
+ LOGMASKED(LOG_CRU, "%s CRUS\n", (state==1)? "Assert" : "Clear");
m_vaquerro->crus_in(state);
m_amigo->crus_in(state);
m_crus_debug = (line_state)state;
@@ -896,7 +900,7 @@ WRITE_LINE_MEMBER( mainboard8_device::crus_in )
*/
WRITE_LINE_MEMBER( mainboard8_device::ptgen_in )
{
- if (TRACE_CRU) logerror("%s PTGEN*\n", (state==0)? "Assert" : "Clear");
+ LOGMASKED(LOG_CRU, "%s PTGEN*\n", (state==0)? "Assert" : "Clear");
m_vaquerro->crusgl_in((state==0)? ASSERT_LINE : CLEAR_LINE);
}
@@ -1124,7 +1128,7 @@ SETADDRESS_DBIN_MEMBER( vaquerro_device::set_address )
// =================== TI (compatibility) mode ======================
if (m_crus == ASSERT_LINE)
{
- if (TRACE_DETAIL) logerror("Compatibility mode\n");
+ LOGMASKED(LOG_DETAIL, "Compatibility mode\n");
// SPRD (Speech read)
m_sprd = ((offbase==0x9000) && reading);
@@ -1147,7 +1151,7 @@ SETADDRESS_DBIN_MEMBER( vaquerro_device::set_address )
// ====================== Native mode ======================
else
{
- if (TRACE_DETAIL) logerror("Native mode\n");
+ LOGMASKED(LOG_DETAIL, "Native mode\n");
// SPRD (Speech read)
m_sprd = ((offbase==0xf820) && reading);
@@ -1176,7 +1180,7 @@ SETADDRESS_DBIN_MEMBER( vaquerro_device::set_address )
m_lasreq = (m_sprd || m_spwt || m_sccs || m_sromcs || m_grom_or_video);
- if (TRACE_DETAIL) logerror("sgfap=%d tsgfap=%d p8gfap=%d p3gfap=%d vfap=%d\n", sgfap, tsgfap, p8gfap, p3gfap, vfap);
+ LOGMASKED(LOG_DETAIL, "sgfap=%d tsgfap=%d p8gfap=%d p3gfap=%d vfap=%d\n", sgfap, tsgfap, p8gfap, p3gfap, vfap);
// Pass the selection to the wait state generators
// and pick up the current select line states
@@ -1195,7 +1199,7 @@ SETADDRESS_DBIN_MEMBER( vaquerro_device::set_address )
{
// We don't see the current selection now; only with next clock pulse.
m_mainboard->ggrdy_in(m_sry);
- if (TRACE_READY) logerror("GGRDY = %d\n", m_sry);
+ LOGMASKED(LOG_READY, "GGRDY = %d\n", m_sry);
}
}
@@ -1227,25 +1231,25 @@ READ_LINE_MEMBER( vaquerro_device::lascsq_out )
*/
WRITE_LINE_MEMBER( vaquerro_device::sgmry )
{
- if (TRACE_READY) logerror("Incoming SGMRY = %d\n", state);
+ LOGMASKED(LOG_READY, "Incoming SGMRY = %d\n", state);
m_sgmws.ready_in((line_state)state);
}
WRITE_LINE_MEMBER( vaquerro_device::tsgry )
{
- if (TRACE_READY) logerror("Incoming TSGRY = %d\n", state);
+ LOGMASKED(LOG_READY, "Incoming TSGRY = %d\n", state);
m_tsgws.ready_in((line_state)state);
}
WRITE_LINE_MEMBER( vaquerro_device::p8gry )
{
- if (TRACE_READY) logerror("Incoming 8GRY = %d\n", state);
+ LOGMASKED(LOG_READY, "Incoming 8GRY = %d\n", state);
m_p8gws.ready_in((line_state)state);
}
WRITE_LINE_MEMBER( vaquerro_device::p3gry )
{
- if (TRACE_READY) logerror("Incoming P3GRY = %d\n", state);
+ LOGMASKED(LOG_READY, "Incoming P3GRY = %d\n", state);
m_p3gws.ready_in((line_state)state);
}
@@ -1254,7 +1258,7 @@ WRITE_LINE_MEMBER( vaquerro_device::p3gry )
*/
READ_LINE_MEMBER( vaquerro_device::ggrdy_out )
{
- if (TRACE_READY) logerror("GGRDY out = %d\n", m_ggrdy);
+ LOGMASKED(LOG_READY, "GGRDY out = %d\n", m_ggrdy);
return m_ggrdy;
}
@@ -1335,7 +1339,7 @@ WRITE_LINE_MEMBER( vaquerro_device::clock_in )
if (level==CLEAR_LINE)
{
m_sry = m_sgmws.ready_out() || m_tsgws.ready_out() || m_p8gws.ready_out() || m_p3gws.ready_out() || m_vidws.ready_out();
- if (TRACE_WS) logerror("ready_out = (%d, %d, %d, %d, %d)\n", m_sgmws.ready_out(), m_tsgws.ready_out(), m_p8gws.ready_out(), m_p3gws.ready_out(),m_vidws.ready_out());
+ LOGMASKED(LOG_WS, "ready_out = (%d, %d, %d, %d, %d)\n", m_sgmws.ready_out(), m_tsgws.ready_out(), m_p8gws.ready_out(), m_p3gws.ready_out(),m_vidws.ready_out());
}
// If the output gate is closed, propagate ASSERT_LINE (pulled up)
@@ -1345,7 +1349,6 @@ WRITE_LINE_MEMBER( vaquerro_device::clock_in )
void vaquerro_device::device_start()
{
- logerror("Starting\n");
m_mainboard = downcast<mainboard8_device*>(owner());
m_sgmws.init(SGMSEL);
m_tsgws.init(TSGSEL);
@@ -1558,13 +1561,13 @@ SETADDRESS_DBIN_MEMBER( mofetta_device::set_address )
if (!m_gotfirstword)
{
// Store the first word and wait for clearing of MSAST
- if (TRACE_MOFETTA) logerror("Got the upper word of the address: %04x\n", offset);
+ LOGMASKED(LOG_MOFETTA, "Got the upper word of the address: %04x\n", offset);
m_address_latch = offset;
}
else
{
// Second part - now decode the address
- if (TRACE_MOFETTA) logerror("Got the lower word of the address: %04x\n", offset);
+ LOGMASKED(LOG_MOFETTA, "Got the lower word of the address: %04x\n", offset);
bool acs, tcs, rcs, acsx;
bool reading = (state==ASSERT_LINE);
@@ -1685,14 +1688,14 @@ WRITE8_MEMBER(mofetta_device::cruwrite)
{
// SWRST (Software reset)
// Value seems to be irrelevant
- if (TRACE_CRU) logerror("Doing a software reset by SBO 2702\n");
+ LOGMASKED(LOG_CRU, "Doing a software reset by SBO 2702\n");
m_mainboard->reset_console(ASSERT_LINE);
m_mainboard->reset_console(CLEAR_LINE);
}
else
{
m_txspg = (data!=0); // CRU>2700
- if (TRACE_CRU) logerror("Turning %s CRU>2700\n", m_txspg? "on" : "off");
+ LOGMASKED(LOG_CRU, "Turning %s CRU>2700\n", m_txspg? "on" : "off");
}
}
else
@@ -1700,7 +1703,7 @@ WRITE8_MEMBER(mofetta_device::cruwrite)
if ((offset & 0xff00)==0x1700)
{
m_alcpg = (data!=0); // CRU>1700
- if (TRACE_CRU) logerror("Turning %s CRU>1700\n", m_alcpg? "on" : "off");
+ LOGMASKED(LOG_CRU, "Turning %s CRU>1700\n", m_alcpg? "on" : "off");
}
}
}
@@ -1740,7 +1743,6 @@ WRITE_LINE_MEMBER( mofetta_device::skdrcs_in )
void mofetta_device::device_start()
{
- logerror("Starting\n");
m_mainboard = downcast<mainboard8_device*>(owner());
save_item(NAME(m_pmemen));
@@ -1873,13 +1875,13 @@ int amigo_device::get_physical_address_debug(offs_t offset)
*/
WRITE_LINE_MEMBER( amigo_device::srdy_in )
{
- if (TRACE_READY) logerror("Incoming SRDY = %d\n", state);
+ LOGMASKED(LOG_READY, "Incoming SRDY = %d\n", state);
m_srdy = (line_state)state;
// If the access is going to logical space, pass through the READY line
if (m_logical_space)
{
- if (TRACE_CPURY) logerror("Setting CPURY = %d (SRDY)\n", m_ready_out);
+ LOGMASKED(LOG_CPURY, "Setting CPURY = %d (SRDY)\n", m_ready_out);
m_ready_out = m_srdy;
}
}
@@ -1958,7 +1960,7 @@ SETOFFSET_MEMBER( amigo_device::set_address )
// Is the address not in the logical address space?
if (!m_logical_space)
{
- if (TRACE_AMIGO) logerror("Amigo decoding; %04x is a physical address.\n", offset);
+ LOGMASKED(LOG_AMIGO, "Amigo decoding; %04x is a physical address.\n", offset);
// Build the physical address
// The first three bits are the protection bits (Write, Execute, Read)
// Theoretically, the addition of the logical address could mess up those
@@ -1979,7 +1981,7 @@ SETOFFSET_MEMBER( amigo_device::set_address )
// Pull down READY
m_ready_out = CLEAR_LINE;
- if (TRACE_CPURY) logerror("Setting CPURY = %d (PAS)\n", m_ready_out);
+ LOGMASKED(LOG_CPURY, "Setting CPURY = %d (PAS)\n", m_ready_out);
}
else
{
@@ -1987,7 +1989,7 @@ SETOFFSET_MEMBER( amigo_device::set_address )
m_dram_accessed = false;
m_amstate = IDLE;
m_ready_out = m_srdy;
- if (TRACE_CPURY) logerror("Setting CPURY = %d (LAS)\n", m_ready_out);
+ LOGMASKED(LOG_CPURY, "Setting CPURY = %d (LAS)\n", m_ready_out);
}
}
@@ -2066,7 +2068,7 @@ void amigo_device::mapper_load()
if ((m_sram_address & 0x03)==0)
{
- if (TRACE_MAP) logerror("Loaded basereg %02d = %08x\n", m_basereg, m_mapvalue);
+ LOGMASKED(LOG_MAP, "Loaded basereg %02d = %08x\n", m_basereg, m_mapvalue);
m_base_register[m_basereg++] = m_mapvalue;
}
if (m_basereg == 16)
@@ -2089,7 +2091,7 @@ void amigo_device::mapper_save()
else
{
m_mapvalue = m_base_register[m_basereg];
- if (TRACE_MAP) logerror("Saving basereg %02d = %08x\n", m_basereg, m_mapvalue);
+ LOGMASKED(LOG_MAP, "Saving basereg %02d = %08x\n", m_basereg, m_mapvalue);
m_basereg++;
}
}
@@ -2131,13 +2133,12 @@ void amigo_device::mapper_access_debug(int data)
WRITE_LINE_MEMBER( amigo_device::holda_in )
{
- if (TRACE_MAP) logerror("HOLD acknowledged = %d\n", state);
+ LOGMASKED(LOG_MAP, "HOLD acknowledged = %d\n", state);
m_hold_acknowledged = (state==ASSERT_LINE);
}
void amigo_device::device_start()
{
- logerror("Starting\n");
m_mainboard = downcast<mainboard8_device*>(owner());
save_item(NAME(m_memen));
@@ -2210,67 +2211,28 @@ void amigo_device::device_reset()
| 8 | 7 | 6 | 5 | 8 = ADB3; 7 = ADB2; 6 = nc; 5 = HSK*
+---+---+---+---+
- TODO: This is just a preliminary implementation to satisfy the operating
- system. When completed we can hopefully emulate a Hexbus floppy and
- use it in Extended Basic II which refuses to work with the PEB cards.
- The Hexbus should then be designed as a slot device.
-
****************************************************************************/
-/* Status register bits */
-enum
-{
- HSKWT = 0x80,
- HSKRD = 0x40,
- BAVIAS = 0x20,
- BAVAIS = 0x10,
- SBAV = 0x08,
- WBUSY = 0x04,
- RBUSY = 0x02,
- SHSK = 0x01
-};
-
-/* Control register bits */
-enum
-{
- WIEN = 0x80,
- RIEN = 0x40,
- BAVIAEN = 0x20,
- BAVAIEN = 0x10,
- BAVC = 0x08,
- WEN = 0x04,
- REN = 0x02,
- CR7 = 0x01
-};
-
-/* Line */
-enum
-{
- LINE_HSK = 0x10,
- LINE_BAV = 0x04,
- LINE_BIT32 = 0xc0,
- LINE_BIT10 = 0x03
-};
-
oso_device::oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
bus::hexbus::hexbus_chained_device(mconfig, TI99_OSO, tag, owner, clock),
m_int(*this),
m_data(0),
m_status(0xff),
m_control(0),
- m_xmit(0), m_lasthxvalue(0x01),
- m_bav(false), m_sbav(false), m_sbavold(false), m_bavhold(false),
- m_hsk(false), m_shsk(false), m_shskold(false), m_hskhold(false),
+ m_xmit(0),
+ m_bav(false), m_sbav(false), m_sbavold(false), m_bavold(false),
+ m_hsk(false), m_hsklocal(false), m_shsk(false), m_hskold(false),
m_wq1(false), m_wq1old(false), m_wq2(false), m_wq2old(false),
- m_wnp(false), m_wbusyold(false), m_sendbyte(false),
+ m_wnp(false), m_wbusy(false), m_wbusyold(false), m_sendbyte(false),
m_wrset(false), m_counting(false), m_clkcount(0),
m_rq1(false), m_rq2(false), m_rq2old(false),
m_rnib(false), m_rnibcold(false),
m_rdset(false), m_rdsetold(false),
m_msns(false), m_lsns(false),
- m_rhsus(false)
+ m_rhsus(false), m_rbusy(false),
+ m_phi3(false),
+ m_oldvalue(0xff)
{
- (void)m_shskold;
m_hexbus_inbound = nullptr;
m_hexbus_outbound = nullptr;
}
@@ -2283,8 +2245,8 @@ READ8_MEMBER( oso_device::read )
{
case 0:
// read 5FF8: read data register
- if (TRACE_OSO) logerror("Read data register = %02x\n", value);
value = m_data;
+ LOGMASKED(LOG_OSO, "Read data register = %02x\n", value);
// Release the handshake
m_rhsus = false;
break;
@@ -2292,7 +2254,7 @@ READ8_MEMBER( oso_device::read )
// read 5FFA: read status register
value = m_status;
clear_int_status();
- if (TRACE_OSO) logerror("Read status %02x (HSKWT=%d,HSKRD=%d,BAVIAS=%d,BAVAIS=%d,SBAV=%d,WBUSY=%d,RBUSY=%d,SHSK=%d)\n", value,
+ LOGMASKED(LOG_OSO, "Read status %02x (HSKWT=%d,HSKRD=%d,BAVIAS=%d,BAVAIS=%d,SBAV=%d,WBUSY=%d,RBUSY=%d,SHSK=%d)\n", value,
(value&HSKWT)? 1:0, (value&HSKRD)? 1:0, (value&BAVIAS)? 1:0,
(value&BAVAIS)? 1:0, (value&SBAV)? 1:0, (value&WBUSY)? 1:0,
(value&RBUSY)? 1:0,(value&SHSK)? 1:0);
@@ -2300,12 +2262,12 @@ READ8_MEMBER( oso_device::read )
case 2:
// read 5FFC: read control register
value = m_control;
- if (TRACE_OSO) logerror("Read control register = %02x\n", value);
+ LOGMASKED(LOG_OSO, "Read control register = %02x\n", value);
break;
case 3:
// read 5FFE: read transmit register
value = m_xmit;
- if (TRACE_OSO) logerror("Read transmit register = %02x\n", value);
+ LOGMASKED(LOG_OSO, "Read transmit register = %02x\n", value);
break;
}
return value;
@@ -2318,7 +2280,7 @@ WRITE8_MEMBER( oso_device::write )
{
case 0:
// write 5FF8: write transmit register
- if (TRACE_OSO) logerror("Write transmit register %02x\n", data);
+ LOGMASKED(LOG_OSO, "Write transmit register %02x\n", data);
// trigger some actions in the write subsystem
m_sendbyte = true;
@@ -2332,10 +2294,11 @@ WRITE8_MEMBER( oso_device::write )
break;
case 1:
// write 5FFA: write control register
- if (TRACE_OSO) logerror("Write control register %02x (WIEN=%d, RIEN=%d, BAVIAEN=%d, BAVAIEN=%d, BAVC=%d, WEN=%d, REN=%d)\n",
+ LOGMASKED(LOG_OSO, "Write control register %02x (WIEN=%d, RIEN=%d, BAVIAEN=%d, BAVAIEN=%d, BAVC=%d, WEN=%d, REN=%d)\n",
data, (data & WIEN)? 1:0, (data & RIEN)? 1:0, (data&BAVIAEN)? 1:0, (data&BAVAIEN)? 1:0,
(data & BAVC)? 1:0, (data & WEN)? 1:0, (data & REN)? 1:0);
m_control = data;
+ m_bav = control_bit(BAVC);
// Reset some flipflops in the write/read timing section
if (!control_bit(WEN))
@@ -2346,10 +2309,11 @@ WRITE8_MEMBER( oso_device::write )
{
m_rq1 = m_rq2 = m_rdset = false;
}
+ update_hexbus();
break;
default:
// write 5FFC, 5FFE: undefined
- if (TRACE_OSO) logerror("Invalid write on %04x: %02x\n", (offset<<1) | 0x5ff0, data);
+ LOGMASKED(LOG_OSO, "Invalid write on %04x: %02x\n", (offset<<1) | 0x5ff0, data);
break;
}
}
@@ -2360,35 +2324,28 @@ void oso_device::clear_int_status()
m_int(CLEAR_LINE);
}
-void oso_device::hexbus_value_changed(uint8_t data)
-{
- if (TRACE_OSO) logerror("Hexbus value changed to %02x\n", data);
-
- m_bav = ((data & LINE_BAV)==0) | control_bit(BAVC);
-
- m_hsk = (data & LINE_HSK)==0;
- int nibble = ((data & LINE_BIT32)>>4) | (data & LINE_BIT10);
- if (m_msns)
- m_data = (m_data & 0x0f) | (nibble<<4);
- if (m_lsns)
- m_data = (m_data & 0xf0) | nibble;
-}
-
/*
Phi3 incoming clock pulse
*/
WRITE_LINE_MEMBER( oso_device::clock_in )
{
+ m_phi3 = state;
if (state==ASSERT_LINE)
{
// Control lines SHSK, SBAV
// When BAV/HSK is 0/1 for two rising edges of Phi3*, SBAV/SHSK goes to
// 0/1 at the following falling edge of Phi3*.
// Page 5
- m_sbav = m_bavhold && m_bav; // could mean "stable BAV"
- m_bavhold = m_bav;
- m_shsk = m_hskhold && m_hsk;
- m_hskhold = m_hsk;
+
+ // In reality, the HSK and BAV signals are checked for their minimum
+ // width (by waiting for two cycles of constant level), but due to
+ // problems with synchronous execution between different parts in the
+ // emulation, we accept the level change immediately.
+
+ m_sbav = m_bav; // could mean "stable BAV"
+ // if (control_bit(WEN)) logerror("hskhold=%d, hsk=%d\n", m_hskhold? 1:0, m_hsk? 1:0);
+
+ m_shsk = m_hsk;
set_status(SHSK, m_shsk);
set_status(SBAV, m_sbav);
@@ -2412,7 +2369,9 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
if (control_bit(WEN)) // Nothing happens without WEN
{
- if (TRACE_OSO) if (!m_wrset && m_sendbyte) logerror("Starting write process\n");
+ if (!m_wrset && m_sendbyte)
+ LOGMASKED(LOG_OSO, "Starting write process\n");
+
// Page 3: Write timing
// Note: First pass counts to 30, second to 31
bool cnt30 = ((m_clkcount & 0x1e) == 30);
@@ -2420,7 +2379,7 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
|| (cnt30 && !m_wq2 && m_wq1) || (m_shsk && m_wq2 && m_wq1);
bool jwq1 = cont && m_wq2;
- bool kwq1 = !((cont && !m_wq2) || (!cont && m_wq2 && m_wnp));
+ bool kwq1 = !(cont && !m_wq2) && !(!cont && m_wq2 && m_wnp);
bool jwq2 = cont;
bool kwq2 = !(m_wq1 && !cont);
@@ -2431,17 +2390,26 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
if (m_wq1 == true)
m_sendbyte = false;
- // logerror("sendbyte=%d, wq1=%d, wq2=%d, jwq1=%d, kwq1=%d, jwq2=%d, kwq2=%d, shsk=%d\n", m_sendbyte, m_wq1, m_wq2, jwq1, kwq1, jwq2, kwq2, m_shsk);
+ // logerror("sendbyte=%d, wq1=%d, wq2=%d, jwq1=%d, kwq1=%d, jwq2=%d, kwq2=%d\n", m_sendbyte, m_wq1, m_wq2, jwq1, kwq1, jwq2, kwq2);
+ // logerror("sendbyte=%d, wq1=%d, wq2=%d, m_shsk=%d\n", m_sendbyte, m_wq1, m_wq2, m_shsk);
// WBUSY is asserted on byte load, during phase 1, and phase 2.
- bool wbusy = m_sendbyte || m_wq1 || m_wq2;
+ m_wbusy = m_sendbyte || m_wq1 || m_wq2;
// Set status bits and raise interrupt (p. 4)
- set_status(WBUSY, wbusy);
+ set_status(WBUSY, m_wbusy);
// Raising edge of wbusy*
- if (m_wbusyold == true && wbusy == false)
+ // This is true when the two nibbles of the byte have been written and acknowledged
+ // by the receiver which has released HSK*
+ if (m_wbusyold == true && m_wbusy == false)
+ {
+ LOGMASKED(LOG_HEXBUS, "Setting HSKWT to true\n");
set_status(HSKWT, true);
- m_wbusyold = wbusy;
+ // Problem: By turning off the WBUSY signal, the transmit register goes inactive
+ // so the peripheral setting dominates again. However, the peripheral sender will not
+ // send its value again.
+ }
+ m_wbusyold = m_wbusy;
// Operate flipflops
// Write phases
@@ -2487,27 +2455,26 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
if (control_bit(REN))
{
- bool rbusy = m_rq1 || m_rq2;
- set_status(RBUSY, rbusy);
-
- // Flipflop resets
- if (!rbusy) m_rnib = false;
- if (m_rq2) m_rdset = false;
-
- bool rdsetin = !control_bit(WBUSY) && m_sbav && m_shsk;
+ bool rdsetin = !status_bit(WBUSY) && m_sbav && m_shsk;
bool next = (m_rdset && !m_rq2) || (m_shsk && m_rq2);
bool drq1 = (next && m_rq2) || (m_rq2 && m_rq1 && !m_rnib);
bool jrq2 = next && !m_rq1;
- bool krq2 = m_rq1 && !m_rnib;
- m_msns = m_rnib && !m_rq1 && m_rq2;
- m_lsns = !m_rnib && !m_rq1 && m_rq2;
+ bool krq2 = !m_rq1 || m_rnib;
bool rnibc = m_rq1;
+ //logerror("n=%d,d1=%d,j2=%d,k2=%d,rn=%d\n", next, drq1, jrq2, krq2, m_rnib);
// Next state
- if (!m_rdsetold && rdsetin) m_rdset = true; // raising edge
+ if (!m_rdsetold && rdsetin)
+ {
+ m_rdset = true; // raising edge
+ }
m_rdsetold = rdsetin;
+ // logerror("rdset=%d, rdsetin=%d\n", m_rdset, rdsetin);
+
+ // Set the RQ1 flipflop
m_rq1 = drq1;
+ // Set the RQ2 flipflop
if (jrq2)
{
if (!krq2) m_rq2 = !m_rq2;
@@ -2516,12 +2483,47 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
else
if (!krq2) m_rq2 = false;
- if (m_rnibcold == false && rnibc == true) m_rnib = !m_rnib; // raising edge
+ if (m_rq2) m_rdset = false;
+
+ // Set the rnib flipflop. This is in sequence to the RQ1 flipflop.
+ rnibc = m_rq1;
+ if (m_rnibcold == false && rnibc == true) // raising edge
+ m_rnib = !m_rnib;
+
m_rnibcold = rnibc;
+ // Debugging only
+ // next = (m_rdset && !m_rq2) || (m_shsk && m_rq2);
+ // drq1 = (next && m_rq2) || (m_rq2 && m_rq1 && !m_rnib);
+ // jrq2 = next && !m_rq1;
+ // krq2 = !m_rq1 || m_rnib;
+ // logerror("r=%d,n=%d,rn=%d,d1=%d,j2=%d,k2=%d,q1=%d,q2=%d\n", m_rdset, next, m_rnib, drq1, jrq2, krq2, m_rq1, m_rq2);
+
+ // Set RBUSY
+ bool rbusy = m_rq1 || m_rq2;
+
+ if (rbusy != m_rbusy)
+ LOGMASKED(LOG_HEXBUS, "RBUSY=%d\n",rbusy);
+
+ m_rbusy = rbusy;
+ set_status(RBUSY, rbusy);
+
+ // Flipflop resets
+ if (!rbusy) m_rnib = false;
+
+ bool msns = m_rnib && !m_rq1 && m_rq2;
+ bool lsns = !m_rnib && !m_rq1 && m_rq2;
+
+ // if (msns != m_msns) LOGMASKED(LOG_HEXBUS, "MSNS=%d\n", msns);
+ // if (lsns != m_lsns) LOGMASKED(LOG_HEXBUS, "LSNS=%d\n", lsns);
+
+ m_lsns = lsns;
+ m_msns = msns;
+
// Raising edge of RQ2*
if (m_rq2old == true && m_rq2 == false)
{
+ LOGMASKED(LOG_HEXBUS, "Byte available for reading\n");
set_status(HSKRD, true);
m_rhsus = true; // byte is available for reading
}
@@ -2534,11 +2536,14 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
// Handshake control
// Set HSK (Page 6, RHSUS*)
- bool hskwrite = !m_wq1 && m_wq2;
+ // This is very likely an error in the schematics. It does not make
+ // sense, and simulations show that the behaviour would be wrong.
+ // bool hskwrite = !m_wq1 && m_wq2;
+ bool hskwrite = (m_wq1 != m_wq2);
// We can simplify this to a single flag because the CPU read operation
// is atomic here (starts and immediately terminates)
- m_hsk = hskwrite || m_rhsus;
+ m_hsklocal = hskwrite || m_rhsus;
update_hexbus();
}
// Actions that occur for Phi3=0
@@ -2575,26 +2580,110 @@ WRITE_LINE_MEMBER( oso_device::clock_in )
}
}
+/*
+ Change the Hexbus line levels and propagate them towards the peripherals.
+*/
void oso_device::update_hexbus()
{
- uint8_t value = 0x00;
- uint8_t nibble = m_xmit;
+ bool changed = false;
+ if (m_hsklocal != m_hskold)
+ {
+ LOGMASKED(LOG_HEXBUS, "%s HSK*\n", m_hsklocal? "Pulling down" : "Releasing");
+ m_hskold = m_hsklocal;
+ changed = true;
+ }
+
+ if (m_bav != m_bavold)
+ {
+ LOGMASKED(LOG_HEXBUS, "%s BAV*\n", m_bav? "Pulling down" : "Releasing");
+ m_bavold = m_bav;
+ changed = true;
+ }
+
+ if (!changed) return;
+
+ // If wbusy==false, set the data output to 1111; since the Hexbus is
+ // a pull-down line bus, this means to inactivate the output
+ uint8_t nibble = m_wbusy? m_xmit : 0xff;
if (m_wnp) nibble >>= 4;
- value = ((m_xmit & 0x0c)<<4) | (m_xmit & 0x03);
- if (!m_hsk) value |= 0x10;
- if (!control_bit(BAVC)) value |= 0x04;
- if (value != m_lasthxvalue)
+ uint8_t value = to_line_state(nibble, control_bit(BAVC), m_hsklocal);
+
+ // if (m_oldvalue != value)
+ // LOGMASKED(LOG_OSO, "Set hexbus = %02x (BAV*=%d, HSK*=%d, data=%01x)\n", value, (value & 0x04)? 1:0, (value & 0x10)? 1:0, ((value>>4)&0x0c) | (value&0x03));
+
+ // As for Oso, we can be sure that hexbus_write does not trigger further
+ // activities from the peripherals that cause a call to hexbus_value_changed.
+ hexbus_write(value);
+
+ // Check how the bus has changed. This depends on the states of all
+ // connected peripherals
+ uint8_t value1 = hexbus_read();
+ // if (value1 != value) LOGMASKED(LOG_OSO, "actually: %02x (BAV*=%d, HSK*=%d, data=%01x)\n", value1, (value1 & 0x04)? 1:0, (value1 & 0x10)? 1:0, ((value1>>4)&0x0c) | (value1&0x03));
+
+ // Update the state of BAV and HSK
+ m_bav = ((value1 & bus::hexbus::HEXBUS_LINE_BAV)==0);
+ m_hsk = ((value1 & bus::hexbus::HEXBUS_LINE_HSK)==0);
+
+ // Sometimes, Oso does not have a chance to advance its state after the
+ // last byte was read. In that case, a change of rdsetin would not be
+ // sensed. We reset the flag right here and so pretend that the tick
+ // has happened.
+ if (m_hsk==false) m_rdsetold = false;
+
+ m_oldvalue = value1;
+}
+
+/*
+ Called when the value on the Hexbus has changed.
+*/
+void oso_device::hexbus_value_changed(uint8_t data)
+{
+// LOGMASKED(LOG_OSO, "Hexbus value changed to %02x\n", data);
+ bool bav = (data & bus::hexbus::HEXBUS_LINE_BAV)==0;
+ bool hsk = (data & bus::hexbus::HEXBUS_LINE_HSK)==0;
+
+ if ((bav != m_bav) || (hsk != m_hsk))
+ {
+ m_bav = bav | control_bit(BAVC);
+ m_hsk = hsk;
+
+ LOGMASKED(LOG_HEXBUS, "BAV*=%d, HSK*=%d\n", m_bav? 0:1, m_hsk? 0:1);
+ int nibble = ((data & bus::hexbus::HEXBUS_LINE_BIT32)>>4) | (data & bus::hexbus::HEXBUS_LINE_BIT10);
+
+ // The real devices are driven at a similar clock rate like the 99/8.
+ // The designers assumed that there is a clock tick of Oso between
+ // every clock tick of the peripheral device. This is not true for
+ // the emulation in MAME, however. For that reason, we trigger "fake"
+ // clock ticks on every change of the hexbus.
+ for (int fake=0; fake < 4; fake++)
+ {
+ if (m_msns)
+ {
+ m_data = (m_data & 0x0f) | (nibble<<4);
+ LOGMASKED(LOG_HEXBUS, "Data register = %02x\n", m_data);
+ }
+ if (m_lsns)
+ {
+ m_data = (m_data & 0xf0) | nibble;
+ LOGMASKED(LOG_HEXBUS, "Data register = %02x\n", m_data);
+ }
+
+ LOGMASKED(LOG_HEXBUS, "Fake tick %d\n", fake);
+ bool phi3 = m_phi3; // mind that clock_in swaps the state of m_phi3
+ clock_in(!phi3);
+ clock_in(phi3);
+ LOGMASKED(LOG_HEXBUS, "Fake tick %d end\n", fake);
+ }
+ }
+ else
{
- if (TRACE_OSO) logerror("Set hexbus = %02x (BAV*=%d, HSK*=%d, data=%01x)\n", value, (value & 0x04)? 1:0, (value & 0x10)? 1:0, ((value>>4)&0x0c) | (value&0x03));
- hexbus_write(value);
+ LOGMASKED(LOG_HEXBUS, "No change for BAV* and HSK*\n");
}
- m_lasthxvalue = value;
}
void oso_device::device_start()
{
- logerror("Starting\n");
m_status = m_xmit = m_control = m_data = 0;
m_int.resolve_safe();