summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/mips_rambo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/mips_rambo.cpp')
-rw-r--r--src/mame/machine/mips_rambo.cpp174
1 files changed, 174 insertions, 0 deletions
diff --git a/src/mame/machine/mips_rambo.cpp b/src/mame/machine/mips_rambo.cpp
new file mode 100644
index 00000000000..ce170ddfc01
--- /dev/null
+++ b/src/mame/machine/mips_rambo.cpp
@@ -0,0 +1,174 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * DMA/timer ASIC used in MIPS Pizazz architecture systems.
+ *
+ * Sources:
+ *
+ * https://github.com/NetBSD/src/blob/trunk/sys/arch/mipsco/obio/rambo.h
+ *
+ * TODO
+ * - interrupts
+ * - dma
+ * - timer
+ * - buzzer
+ */
+
+#include "emu.h"
+#include "mips_rambo.h"
+
+#define LOG_GENERAL (1U << 0)
+#define LOG_REG (1U << 1)
+
+//#define VERBOSE (LOG_GENERAL|LOG_REG)
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(MIPS_RAMBO, mips_rambo_device, "mips_rambo", "MIPS RAMBO")
+
+mips_rambo_device::mips_rambo_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MIPS_RAMBO, tag, owner, clock)
+ , m_ram(*this, finder_base::DUMMY_TAG)
+ , m_irq_out_cb(*this)
+ , m_parity_out_cb(*this)
+ , m_timer_out_cb(*this)
+ , m_buzzer_out_cb(*this)
+ , m_irq_out_state(0)
+ , m_buzzer_out_state(0)
+{
+}
+
+void mips_rambo_device::map(address_map &map)
+{
+ map(0x000, 0x003).rw(FUNC(mips_rambo_device::load_address_r<0>), FUNC(mips_rambo_device::load_address_w<0>));
+ map(0x100, 0x103).r(FUNC(mips_rambo_device::diag_r<0>));
+ map(0x202, 0x203).rw(FUNC(mips_rambo_device::fifo_r<0>), FUNC(mips_rambo_device::fifo_w<0>));
+ map(0x300, 0x303).rw(FUNC(mips_rambo_device::mode_r<0>), FUNC(mips_rambo_device::mode_w<0>));
+ map(0x402, 0x403).rw(FUNC(mips_rambo_device::block_count_r<0>), FUNC(mips_rambo_device::block_count_w<0>));
+ map(0x500, 0x503).r(FUNC(mips_rambo_device::current_address_r<0>));
+
+ map(0x600, 0x603).rw(FUNC(mips_rambo_device::load_address_r<1>), FUNC(mips_rambo_device::load_address_w<1>));
+ map(0x700, 0x703).r(FUNC(mips_rambo_device::diag_r<1>));
+ map(0x802, 0x803).rw(FUNC(mips_rambo_device::fifo_r<1>), FUNC(mips_rambo_device::fifo_w<1>));
+ map(0x900, 0x903).rw(FUNC(mips_rambo_device::mode_r<1>), FUNC(mips_rambo_device::mode_w<1>));
+ map(0xa02, 0xa03).rw(FUNC(mips_rambo_device::block_count_r<1>), FUNC(mips_rambo_device::block_count_w<1>));
+ map(0xb00, 0xb03).r(FUNC(mips_rambo_device::current_address_r<1>));
+
+ map(0xc00, 0xc03).rw(FUNC(mips_rambo_device::tcount_r), FUNC(mips_rambo_device::tcount_w));
+ map(0xd00, 0xd03).rw(FUNC(mips_rambo_device::tbreak_r), FUNC(mips_rambo_device::tbreak_w));
+ map(0xe00, 0xe03).r(FUNC(mips_rambo_device::error_r));
+ map(0xf00, 0xf03).rw(FUNC(mips_rambo_device::control_r), FUNC(mips_rambo_device::control_w));
+}
+
+void mips_rambo_device::device_start()
+{
+ m_irq_out_cb.resolve_safe();
+ m_parity_out_cb.resolve_safe();
+ m_timer_out_cb.resolve_safe();
+ m_buzzer_out_cb.resolve_safe();
+
+ m_buzzer_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mips_rambo_device::buzzer_toggle), this));
+
+}
+
+void mips_rambo_device::device_reset()
+{
+ // TODO: update interrupts
+
+ m_tcount = machine().time();
+}
+
+READ32_MEMBER(mips_rambo_device::tcount_r)
+{
+ return attotime_to_clocks(machine().time() - m_tcount);
+}
+
+WRITE32_MEMBER(mips_rambo_device::tcount_w)
+{
+ LOGMASKED(LOG_REG, "tcount_w 0x%08x (%s)\n", data, machine().describe_context());
+
+ m_tcount = machine().time();
+}
+
+WRITE32_MEMBER(mips_rambo_device::tbreak_w)
+{
+ LOGMASKED(LOG_REG, "tbreak_w 0x%08x (%s)\n", data, machine().describe_context());
+}
+
+WRITE32_MEMBER(mips_rambo_device::control_w)
+{
+ LOGMASKED(LOG_REG, "control_w 0x%08x (%s)\n", data, machine().describe_context());
+
+ // stop the buzzer
+ m_buzzer_timer->enable(false);
+ m_buzzer_out_state = 0;
+ m_buzzer_out_cb(m_buzzer_out_state);
+
+ // start the buzzer if requested
+ if (data & CONTROL_BUZZON)
+ {
+ attotime const period = attotime::from_ticks(1 << ((data & CONTROL_BUZZMASK) >> 4), 1524_Hz_XTAL);
+
+ m_buzzer_timer->adjust(period, 0, period);
+ }
+}
+
+template <unsigned Channel> WRITE32_MEMBER(mips_rambo_device::load_address_w)
+{
+ LOGMASKED(LOG_REG, "load_address_w<%d> 0x%08x (%s)\n", Channel, data, machine().describe_context());
+
+ COMBINE_DATA(&m_channel[Channel].load_address);
+}
+
+template <unsigned Channel> WRITE16_MEMBER(mips_rambo_device::fifo_w)
+{
+ LOGMASKED(LOG_REG, "fifo_w<%d> 0x%04x (%s)\n", Channel, data, machine().describe_context());
+}
+
+template <unsigned Channel> WRITE32_MEMBER(mips_rambo_device::mode_w)
+{
+ LOGMASKED(LOG_REG, "mode_w<%d> 0x%08x (%s)\n", Channel, data, machine().describe_context());
+
+ COMBINE_DATA(&m_channel[Channel].mode);
+}
+
+template <unsigned Channel> WRITE16_MEMBER(mips_rambo_device::block_count_w)
+{
+ LOGMASKED(LOG_REG, "block_count_w<%d> 0x%04x (%s)\n", Channel, data, machine().describe_context());
+
+ COMBINE_DATA(&m_channel[Channel].block_count);
+}
+
+TIMER_CALLBACK_MEMBER(mips_rambo_device::buzzer_toggle)
+{
+ m_buzzer_out_state = !m_buzzer_out_state;
+ m_buzzer_out_cb(m_buzzer_out_state);
+}
+
+u32 mips_rambo_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ // check if dma channel is configured
+ u32 const blocks_required = (screen.visible_area().height() * screen.visible_area().width()) >> 9;
+ if (!(m_channel[1].mode & MODE_CHANNEL_EN) || !(m_channel[1].mode & MODE_AUTO_RELOAD) || (m_channel[1].block_count != blocks_required))
+ return 1;
+
+ u32 address = m_channel[1].load_address;
+ for (int y = screen.visible_area().min_y; y <= screen.visible_area().max_y; y++)
+ for (int x = screen.visible_area().min_x; x <= screen.visible_area().max_x; x += 8)
+ {
+ u8 pixel_data = m_ram->read(BYTE4_XOR_BE(address));
+
+ bitmap.pix(y, x + 0) = BIT(pixel_data, 7) ? rgb_t::white() : rgb_t::black();
+ bitmap.pix(y, x + 1) = BIT(pixel_data, 6) ? rgb_t::white() : rgb_t::black();
+ bitmap.pix(y, x + 2) = BIT(pixel_data, 5) ? rgb_t::white() : rgb_t::black();
+ bitmap.pix(y, x + 3) = BIT(pixel_data, 4) ? rgb_t::white() : rgb_t::black();
+ bitmap.pix(y, x + 4) = BIT(pixel_data, 3) ? rgb_t::white() : rgb_t::black();
+ bitmap.pix(y, x + 5) = BIT(pixel_data, 2) ? rgb_t::white() : rgb_t::black();
+ bitmap.pix(y, x + 6) = BIT(pixel_data, 1) ? rgb_t::white() : rgb_t::black();
+ bitmap.pix(y, x + 7) = BIT(pixel_data, 0) ? rgb_t::white() : rgb_t::black();
+
+ address++;
+ }
+
+ return 0;
+}