summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/machine.lua12
-rw-r--r--src/devices/machine/acorn_vidc.cpp340
-rw-r--r--src/devices/machine/acorn_vidc.h129
-rw-r--r--src/devices/machine/arm_iomd.cpp767
-rw-r--r--src/devices/machine/arm_iomd.h211
-rw-r--r--src/mame/drivers/riscpc.cpp933
-rw-r--r--src/mame/drivers/ssfindo.cpp521
7 files changed, 1607 insertions, 1306 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index e9a58631883..7d1eaef0e7b 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -82,7 +82,6 @@ if (MACHINES["ACORN_VIDC"]~=null) then
}
end
-
---------------------------------------------------
--
--@src/devices/machine/akiko.h,MACHINES["AKIKO"] = true
@@ -95,6 +94,17 @@ if (MACHINES["AKIKO"]~=null) then
}
end
+--------------------------------------------------
+--
+--@src/devices/machine/arm_iomd.h,MACHINES["ARM_IOMD"] = true
+--------------------------------------------------
+
+if (MACHINES["ARM_IOMD"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/machine/arm_iomd.cpp",
+ MAME_DIR .. "src/devices/machine/arm_iomd.h",
+ }
+end
---------------------------------------------------
--
diff --git a/src/devices/machine/acorn_vidc.cpp b/src/devices/machine/acorn_vidc.cpp
index 4ad88d5d4df..94ddfb8b3c8 100644
--- a/src/devices/machine/acorn_vidc.cpp
+++ b/src/devices/machine/acorn_vidc.cpp
@@ -30,6 +30,7 @@
// device type definition
DEFINE_DEVICE_TYPE(ACORN_VIDC10, acorn_vidc10_device, "acorn_vidc10", "Acorn VIDC10")
DEFINE_DEVICE_TYPE(ACORN_VIDC10_LCD, acorn_vidc10_lcd_device, "acorn_vidc10_lcd", "Acorn VIDC10 with LCD monitor")
+DEFINE_DEVICE_TYPE(ARM_VIDC20, arm_vidc20_device, "arm_vidc20", "ARM VIDC20")
//**************************************************************************
@@ -51,25 +52,23 @@ void acorn_vidc10_device::regs_map(address_map &map)
}
-acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, tag, owner, clock)
, device_memory_interface(mconfig, *this)
, device_palette_interface(mconfig, *this)
, device_video_interface(mconfig, *this)
- , m_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, 0, address_map_constructor(FUNC(acorn_vidc10_device::regs_map), this))
+ , m_bpp_mode(0)
+ , m_crtc_interlace(0)
+ , m_sound_frequency_latch(0)
+ , m_sound_mode(false)
+ , m_dac(*this, "dac%u", 0)
, m_lspeaker(*this, "lspeaker")
, m_rspeaker(*this, "rspeaker")
- , m_dac(*this, "dac%u", 0)
, m_vblank_cb(*this)
, m_sound_drq_cb(*this)
, m_pixel_clock(0)
- , m_bpp_mode(0)
- , m_crtc_interlace(0)
, m_cursor_enable(false)
- , m_sound_frequency_latch(0)
, m_sound_frequency_test_bit(false)
- , m_sound_mode(false)
-
{
std::fill(std::begin(m_crtc_regs), std::end(m_crtc_regs), 0);
std::fill(std::begin(m_stereo_image), std::end(m_stereo_image), 0);
@@ -78,12 +77,21 @@ acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, device_t
acorn_vidc10_device::acorn_vidc10_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: acorn_vidc10_device(mconfig, ACORN_VIDC10, tag, owner, clock)
{
+ m_space_config = address_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, 0, address_map_constructor(FUNC(acorn_vidc10_device::regs_map), this));
+ m_pal_4bpp_base = 0x100;
+ m_pal_cursor_base = 0x10;
+ m_pal_border_base = 0x110;
}
-acorn_vidc10_lcd_device::acorn_vidc10_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+acorn_vidc10_lcd_device::acorn_vidc10_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: acorn_vidc10_device(mconfig, ACORN_VIDC10_LCD, tag, owner, clock)
{
+ m_space_config = address_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, 0, address_map_constructor(FUNC(acorn_vidc10_lcd_device::regs_map), this));
+ // TODO: confirm being identical to raster version
+ m_pal_4bpp_base = 0x100;
+ m_pal_cursor_base = 0x10;
+ m_pal_border_base = 0x110;
}
device_memory_interface::space_config_vector acorn_vidc10_device::memory_space_config() const
@@ -118,7 +126,7 @@ void acorn_vidc10_lcd_device::device_add_mconfig(machine_config &config)
// TODO: verify !Configure with automatic type detection, there must be an ID telling this is a LCD machine.
}
-uint32_t acorn_vidc10_device::palette_entries() const
+u32 acorn_vidc10_device::palette_entries() const
{
return 0x100+0x10+4; // 8bpp + 1/2/4bpp + 2bpp for cursor
}
@@ -160,8 +168,9 @@ void acorn_vidc10_device::device_start()
save_item(NAME(m_sound_frequency_test_bit));
save_item(NAME(m_cursor_enable));
save_pointer(NAME(m_crtc_regs), CRTC_VCER+1);
- m_data_vram = auto_alloc_array_clear(machine(), u8, m_data_vram_size);
- m_cursor_vram = auto_alloc_array_clear(machine(), u8, m_cursor_vram_size);
+ save_pointer(NAME(m_crtc_raw_horz), 2);
+ m_data_vram = make_unique_clear<u8[]>(m_data_vram_size);
+ m_cursor_vram = make_unique_clear<u8[]>(m_cursor_vram_size);
save_pointer(NAME(m_data_vram), m_data_vram_size);
save_pointer(NAME(m_cursor_vram), m_cursor_vram_size);
save_pointer(NAME(m_stereo_image), m_sound_max_channels);
@@ -174,8 +183,8 @@ void acorn_vidc10_device::device_start()
// TODO: manual mentions a format difference between VIDC10 revisions
for (int rawval = 0; rawval < 256; rawval++)
{
- uint8_t chord = rawval >> 5;
- uint8_t point = (rawval & 0x1e) >> 1;
+ u8 chord = rawval >> 5;
+ u8 point = (rawval & 0x1e) >> 1;
bool sign = rawval & 1;
int16_t result = ((16+point)<<chord)-16;
@@ -184,6 +193,8 @@ void acorn_vidc10_device::device_start()
m_ulaw_lookup[rawval] = result*8;
}
+
+ // saved for debugging purposes
save_pointer(NAME(m_ulaw_lookup), 256);
}
@@ -195,8 +206,6 @@ void acorn_vidc10_device::device_start()
void acorn_vidc10_device::device_reset()
{
m_cursor_enable = false;
- memset(m_data_vram, 0, m_data_vram_size);
- memset(m_cursor_vram, 0, m_cursor_vram_size);
memset(m_stereo_image, 4, m_sound_max_channels);
for (int ch=0;ch<m_sound_max_channels;ch++)
refresh_stereo_image(ch);
@@ -232,9 +241,15 @@ inline void acorn_vidc10_device::screen_vblank_line_update()
m_video_timer->adjust((vline > 2) ? screen().time_until_pos(vline) : attotime::never);
}
-void acorn_vidc10_device::screen_dynamic_res_change()
+u32 acorn_vidc10_device::get_pixel_clock()
{
const int32_t pixel_rate[4] = { 8000000, 12000000, 16000000, 24000000};
+ return pixel_rate[m_pixel_clock];
+}
+
+inline void acorn_vidc10_device::screen_dynamic_res_change()
+{
+ const u32 pixel_clock = get_pixel_clock();
// sanity checks
if (m_crtc_regs[CRTC_HCR] <= 1 || m_crtc_regs[CRTC_VCR] <= 1)
@@ -267,7 +282,7 @@ void acorn_vidc10_device::screen_dynamic_res_change()
m_vidc_vblank_time);
#endif
- attoseconds_t const refresh = HZ_TO_ATTOSECONDS(pixel_rate[m_pixel_clock]) * m_crtc_regs[CRTC_HCR] * m_crtc_regs[CRTC_VCR];
+ attoseconds_t const refresh = HZ_TO_ATTOSECONDS(pixel_clock) * m_crtc_regs[CRTC_HCR] * m_crtc_regs[CRTC_VCR];
screen().configure(m_crtc_regs[CRTC_HCR], m_crtc_regs[CRTC_VCR] * (m_crtc_interlace+1), visarea, refresh);
}
@@ -279,13 +294,13 @@ void acorn_vidc10_device::screen_dynamic_res_change()
WRITE32_MEMBER( acorn_vidc10_device::write )
{
// TODO: check against mem_mask not 32-bit wide
- uint8_t reg = data >> 24;
- uint32_t val = data & 0xffffff;
-
+ u8 reg = data >> 24;
+ u32 val = data & 0xffffff;
+
this->space(AS_IO).write_dword(reg, val);
}
-inline void acorn_vidc10_device::update_4bpp_palette(uint16_t index, uint32_t paldata)
+inline void acorn_vidc10_device::update_4bpp_palette(u16 index, u32 paldata)
{
int r,g,b;
@@ -331,20 +346,34 @@ WRITE32_MEMBER( acorn_vidc10_device::control_w )
//m_test_mode = (data & 0xc100) != 0xc100;
//todo: vga/svga modes sets 0x1000?
+ m_crtc_regs[CRTC_HDSR] = convert_crtc_hdisplay(0);
+ m_crtc_regs[CRTC_HDER] = convert_crtc_hdisplay(1);
screen_vblank_line_update();
screen_dynamic_res_change();
}
+inline u32 acorn_vidc10_device::convert_crtc_hdisplay(u8 index)
+{
+ const u8 x_step[4] = { 19, 11, 7, 5 };
+ return (m_crtc_raw_horz[index]*2)+x_step[m_bpp_mode];
+}
+
WRITE32_MEMBER( acorn_vidc10_device::crtc_w )
{
switch(offset)
{
- case CRTC_HCR: m_crtc_regs[CRTC_HCR] = ((data >> 14)<<1)+2; break;
-// case CRTC_HSWR: m_crtc_regs[CRTC_HSWR] = (data >> 14)+1; break;
- case CRTC_HBSR: m_crtc_regs[CRTC_HBSR] = ((data >> 14)<<1)+1; break;
- case CRTC_HDSR: m_crtc_regs[CRTC_HDSR] = (data >> 14); break;
- case CRTC_HDER: m_crtc_regs[CRTC_HDER] = (data >> 14); break;
- case CRTC_HBER: m_crtc_regs[CRTC_HBER] = ((data >> 14)<<1)+1; break;
+ case CRTC_HCR: m_crtc_regs[CRTC_HCR] = ((data >> 14)<<1)+2; break;
+// case CRTC_HSWR: m_crtc_regs[CRTC_HSWR] = (data >> 14)+1; break;
+ case CRTC_HBSR: m_crtc_regs[CRTC_HBSR] = ((data >> 14)<<1)+1; break;
+ case CRTC_HDSR:
+ m_crtc_raw_horz[0] = (data >> 14);
+ m_crtc_regs[CRTC_HDSR] = convert_crtc_hdisplay(0);
+ break;
+ case CRTC_HDER:
+ m_crtc_raw_horz[1] = (data >> 14);
+ m_crtc_regs[CRTC_HDER] = convert_crtc_hdisplay(1);
+ break;
+ case CRTC_HBER: m_crtc_regs[CRTC_HBER] = ((data >> 14)<<1)+1; break;
case CRTC_HCSR: m_crtc_regs[CRTC_HCSR] = ((data >> 13) & 0x7ff) + 6; return;
// case CRTC_HIR: // ...
@@ -370,7 +399,7 @@ WRITE32_MEMBER( acorn_vidc10_device::crtc_w )
screen_dynamic_res_change();
}
-inline void acorn_vidc10_device::refresh_stereo_image(uint8_t channel)
+inline void acorn_vidc10_device::refresh_stereo_image(u8 channel)
{
/*
-111 full right
@@ -393,7 +422,7 @@ inline void acorn_vidc10_device::refresh_stereo_image(uint8_t channel)
WRITE32_MEMBER( acorn_vidc10_device::stereo_image_w )
{
- uint8_t channel = (offset + 7) & 0x7;
+ u8 channel = (offset + 7) & 0x7;
m_stereo_image[channel] = data & 0x7;
refresh_stereo_image(channel);
}
@@ -410,8 +439,8 @@ WRITE32_MEMBER( acorn_vidc10_device::sound_frequency_w )
// MEMC comms
//**************************************************************************
-void acorn_vidc10_device::write_dac(uint8_t channel, uint8_t data)
-{
+void acorn_vidc10_device::write_dac(u8 channel, u8 data)
+{
int16_t res;
res = m_ulaw_lookup[data];
m_dac[channel & 7]->write(res);
@@ -424,7 +453,7 @@ void acorn_vidc10_device::refresh_sound_frequency()
{
// TODO: Range is between 3 and 256 usecs
double sndhz = 1e6 / ((m_sound_frequency_latch & 0xff) + 2);
- sndhz /= 8.0;
+ sndhz /= m_sound_internal_divider;
m_sound_timer->adjust(attotime::zero, 0, attotime::from_hz(sndhz));
//printf("VIDC: audio DMA start, sound freq %d, sndhz = %f\n", (m_crtc_regs[0xc0] & 0xff)-2, sndhz);
}
@@ -436,9 +465,9 @@ void acorn_vidc10_device::refresh_sound_frequency()
// Screen Update / VBlank / HBlank
//**************************************************************************
-void acorn_vidc10_device::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 *vram, uint8_t bpp, int xstart, int ystart, int xsize, int ysize, bool is_cursor)
+void acorn_vidc10_device::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 *vram, u8 bpp, int xstart, int ystart, int xsize, int ysize, bool is_cursor)
{
- const u16 pen_base = (bpp == 3 ? 0 : 0x100) + (is_cursor == true ? 0x10 : 0);
+ const u16 pen_base = (bpp == 3 ? 0 : m_pal_4bpp_base) + (is_cursor == true ? m_pal_cursor_base : 0);
const u16 pen_masks[4] = { 1, 3, 0xf, 0xff };
const u16 pen_mask = pen_masks[bpp];
const u16 xchar_size = 1 << (3 - bpp);
@@ -476,14 +505,13 @@ u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm
int xstart,ystart,xend,yend;
int xsize,ysize;
int calc_dxs = 0,calc_dxe = 0;
- const uint8_t x_step[4] = { 19, 11, 7, 5 };
/* border color */
- bitmap.fill(pen(0x110), cliprect);
+ bitmap.fill(pen(m_pal_border_base), cliprect);
/* define X display area through BPP mode register */
- calc_dxs = (m_crtc_regs[CRTC_HDSR]*2)+x_step[m_bpp_mode & 3];
- calc_dxe = (m_crtc_regs[CRTC_HDER]*2)+x_step[m_bpp_mode & 3];
+ calc_dxs = m_crtc_regs[CRTC_HDSR];
+ calc_dxe = m_crtc_regs[CRTC_HDER];
/* now calculate display clip rectangle start/end areas */
xstart = (calc_dxs)-m_crtc_regs[CRTC_HBSR];
@@ -501,7 +529,7 @@ u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm
if (xsize <= 0 || ysize <= 0)
return 0;
- draw(bitmap, cliprect, m_data_vram, m_bpp_mode, xstart, ystart, xsize, ysize, false);
+ draw(bitmap, cliprect, m_data_vram.get(), m_bpp_mode, xstart, ystart, xsize, ysize, false);
if (m_cursor_enable == true)
{
xstart = m_crtc_regs[CRTC_HCSR] - m_crtc_regs[CRTC_HBSR];
@@ -509,7 +537,7 @@ u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm
xsize = 32;
ysize = m_crtc_regs[CRTC_VCER] - m_crtc_regs[CRTC_VCSR];
if (ysize > 0)
- draw(bitmap, cliprect, m_cursor_vram, 1, xstart, ystart, xsize, ysize, true);
+ draw(bitmap, cliprect, m_cursor_vram.get(), 1, xstart, ystart, xsize, ysize, true);
}
return 0;
@@ -518,6 +546,232 @@ u32 acorn_vidc10_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm
READ_LINE_MEMBER(acorn_vidc10_device::flyback_r )
{
int vert_pos = screen().vpos();
- bool flyback = (vert_pos <= m_crtc_regs[CRTC_VDSR] || vert_pos >= m_crtc_regs[CRTC_VDER]);
- return flyback;
+ if (vert_pos <= m_crtc_regs[CRTC_VDSR] * (m_crtc_interlace+1))
+ return true;
+
+ if (vert_pos >= m_crtc_regs[CRTC_VDER] * (m_crtc_interlace+1))
+ return true;
+
+ return false;
+}
+
+// VIDC20
+
+void arm_vidc20_device::regs_map(address_map &map)
+{
+ map(0x00, 0x0f).w(FUNC(arm_vidc20_device::vidc20_pal_data_display_w));
+ map(0x10, 0x1f).w(FUNC(arm_vidc20_device::vidc20_pal_data_index_w));
+ map(0x40, 0x7f).w(FUNC(arm_vidc20_device::vidc20_pal_data_cursor_w));
+ map(0x80, 0x9f).w(FUNC(arm_vidc20_device::vidc20_crtc_w));
+ map(0xb0, 0xb0).w(FUNC(arm_vidc20_device::vidc20_sound_frequency_w));
+ map(0xb1, 0xb1).w(FUNC(arm_vidc20_device::vidc20_sound_control_w));
+ map(0xd0, 0xdf).w(FUNC(arm_vidc20_device::fsynreg_w));
+ map(0xe0, 0xef).w(FUNC(arm_vidc20_device::vidc20_control_w));
+}
+
+arm_vidc20_device::arm_vidc20_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : acorn_vidc10_device(mconfig, ARM_VIDC20, tag, owner, clock)
+{
+ m_space_config = address_space_config("regs_space", ENDIANNESS_LITTLE, 32, 8, -2, address_map_constructor(FUNC(arm_vidc20_device::regs_map), this));
+ m_pal_4bpp_base = 0x000;
+ m_pal_cursor_base = 0x100;
+ m_pal_border_base = 0x100;
+}
+
+
+void arm_vidc20_device::device_add_mconfig(machine_config &config)
+{
+ acorn_vidc10_device::device_add_mconfig(config);
+ // ...
+ // TODO: for simplicity we may as well add separate DACs for 32-bit mode
}
+
+void arm_vidc20_device::device_config_complete()
+{
+ if (!has_screen())
+ return;
+
+ if (!screen().refresh_attoseconds())
+ screen().set_raw(clock() * 2 / 3, 1024,0,735, 624/2,0,292); // RiscOS 3 default screen settings
+
+ if (!screen().has_screen_update())
+ screen().set_screen_update(*this, FUNC(arm_vidc20_device::screen_update));
+}
+
+u32 arm_vidc20_device::palette_entries() const
+{
+ return 0x100+4; // 8bpp + 2bpp for cursor
+}
+
+void arm_vidc20_device::device_start()
+{
+ acorn_vidc10_device::device_start();
+
+ save_item(NAME(m_vco_r_modulo));
+ save_item(NAME(m_vco_v_modulo));
+ save_item(NAME(m_pal_data_index));
+ save_item(NAME(m_dac_serial_mode));
+ save_item(NAME(m_pixel_source));
+ save_item(NAME(m_pixel_rate));
+}
+
+void arm_vidc20_device::device_reset()
+{
+ acorn_vidc10_device::device_reset();
+
+ // TODO: sensible defaults
+ m_vco_r_modulo = 1;
+ m_vco_v_modulo = 1;
+}
+
+void arm_vidc20_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ acorn_vidc10_device::device_timer(timer, id, param, ptr);
+}
+
+inline void arm_vidc20_device::update_8bpp_palette(u16 index, u32 paldata)
+{
+ int r,g,b;
+
+ // TODO: ext hookup, supremacy plus other stuff according to the manual
+// ext = (paldata & 0x0f000000) >> 24;
+ b = (paldata & 0x00ff0000) >> 16;
+ g = (paldata & 0x0000ff00) >> 8;
+ r = (paldata & 0x000000ff) >> 0;
+
+ set_pen_color(index, r, g, b );
+ screen().update_partial(screen().vpos());
+}
+
+WRITE32_MEMBER(arm_vidc20_device::vidc20_pal_data_display_w)
+{
+ u8 ext_data = offset & 0xf;
+ update_8bpp_palette(m_pal_data_index, (ext_data<<24) | data);
+ m_pal_data_index ++;
+ m_pal_data_index &= 0xff;
+}
+
+WRITE32_MEMBER( arm_vidc20_device::vidc20_pal_data_index_w )
+{
+ m_pal_data_index = data & 0xff;
+}
+
+WRITE32_MEMBER( arm_vidc20_device::vidc20_pal_data_cursor_w )
+{
+ u8 ext_data = offset & 0xf;
+ u8 cursor_pal_index = (offset >> 4) & 3;
+ update_8bpp_palette(m_pal_cursor_base + cursor_pal_index, (ext_data<<24) | data);
+}
+
+u32 arm_vidc20_device::get_pixel_clock()
+{
+ // RCLK source: passes thru a r-modulus and a phase frequency (PCOMP), the full story is interesting if you're into maths.
+ // TODO: for now we just multiply source clock by 2, enough for ssfindo.cpp games.
+ //printf("%d %02x %02x %d %d\n",this->clock(), 1 << m_pixel_rate, m_pixel_source, m_vco_v_modulo, m_vco_r_modulo);
+ if (m_pixel_source == 2) // RCLK
+ return (this->clock() << 1) >> m_pixel_rate;
+
+ // VCLK source is just an external connection
+ // TODO: get clock from outside world, understand how the modulos are really used,
+ // understand if SW do some VCO testing before setting CRTC params,
+ // if there isn't a monitor ID mechanism that copes with this
+ if (m_pixel_source == 0) // VCLK
+ return (25175000);
+
+ throw emu_fatalerror("%s unhandled pixel source %02x selected",this->tag(), m_pixel_source);
+}
+
+WRITE32_MEMBER(arm_vidc20_device::vidc20_crtc_w)
+{
+ if (offset & 0x8)
+ throw emu_fatalerror("%s accessing CRTC test register %02x, please call the ambulance",this->tag(),offset+0x80);
+
+ const u8 crtc_offset = (offset & 0x7) | ((offset & 0x10) >> 1);
+
+ switch(crtc_offset)
+ {
+ case CRTC_HCR: m_crtc_regs[CRTC_HCR] = (data&0x7ffc) + 8; break;
+ case CRTC_HSWR: m_crtc_regs[CRTC_HSWR] = (data&0x7ffe) + 8; break;
+ case CRTC_HBSR: m_crtc_regs[CRTC_HBSR] = (data&0x7ffe) + 12; break;
+ case CRTC_HDSR: m_crtc_regs[CRTC_HDSR] = (data&0x7ffe) + 18; break;
+ case CRTC_HDER: m_crtc_regs[CRTC_HDER] = (data&0x7ffe) + 18; break;
+ case CRTC_HBER: m_crtc_regs[CRTC_HBER] = (data&0x7ffe) + 12; break;
+ case CRTC_HCSR: m_crtc_regs[CRTC_HCSR] = (data&0x7fff) + 17; return;
+// case CRTC_HIR:
+ case CRTC_VCR: m_crtc_regs[CRTC_VCR] = (data&0x3fff) + 2; break;
+ case CRTC_VSWR: m_crtc_regs[CRTC_VSWR] = (data&0x3fff) + 1; break;
+ case CRTC_VBSR: m_crtc_regs[CRTC_VBSR] = (data&0x3fff) + 1; break;
+ case CRTC_VDSR: m_crtc_regs[CRTC_VDSR] = (data&0x3fff) + 1; break;
+ case CRTC_VDER:
+ m_crtc_regs[CRTC_VDER] = (data&0x3fff) + 1;
+ screen_vblank_line_update();
+ break;
+ case CRTC_VBER: m_crtc_regs[CRTC_VBER] = (data&0x3fff) + 1; break;
+ // TODO: bits 15-14 specific for duplex LCD mode
+ case CRTC_VCSR:
+ m_crtc_regs[CRTC_VCSR] = (data&0x3fff) + 1;
+ return;
+ case CRTC_VCER: m_crtc_regs[CRTC_VCER] = (data&0x3fff) + 1; return;
+ }
+
+ screen_dynamic_res_change();
+}
+
+WRITE32_MEMBER( arm_vidc20_device::fsynreg_w )
+{
+ m_vco_r_modulo = data & 0x3f;
+ m_vco_v_modulo = (data >> 8) & 0x3f;
+ // bits 15-14 and 7-6 are test bits
+
+ screen_dynamic_res_change();
+}
+
+WRITE32_MEMBER( arm_vidc20_device::vidc20_control_w )
+{
+ // ---- --00: VCLK
+ // ---- --01: HCLK
+ // ---- --10: RCLK ("recommended" 24 MHz)
+ // ---- --11: undefined, prolly same as RCLK
+ m_pixel_source = data & 3;
+ m_pixel_rate = (data & 0x1c) >> 2;
+ // (data & 0x700) >> 8 FIFO load
+ // BIT(data, 13) enables Duplex LCD mode
+ // BIT(data, 14) power down
+ // (data & 0xf0000) >> 16 test mode
+ m_bpp_mode = (data & 0xe0) >> 5;
+ m_crtc_interlace = BIT(data, 12);
+
+ screen_vblank_line_update();
+ screen_dynamic_res_change();
+}
+
+WRITE32_MEMBER( arm_vidc20_device::vidc20_sound_control_w )
+{
+ // TODO: VIDC10 mode, ext clock bit 0
+ m_dac_serial_mode = BIT(data, 1);
+}
+
+WRITE32_MEMBER( arm_vidc20_device::vidc20_sound_frequency_w )
+{
+ m_sound_frequency_latch = data & 0xff;
+ if (m_sound_mode == true)
+ refresh_sound_frequency();
+}
+
+void arm_vidc20_device::write_dac32(u8 channel, u16 data)
+{
+ m_dac[channel & 1]->write(data);
+}
+
+bool arm_vidc20_device::get_dac_mode()
+{
+ return m_dac_serial_mode;
+}
+
+u32 arm_vidc20_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ // TODO: support for true color modes
+ return acorn_vidc10_device::screen_update(screen, bitmap, cliprect);
+}
+
+
diff --git a/src/devices/machine/acorn_vidc.h b/src/devices/machine/acorn_vidc.h
index 83a9bcbc000..bfa09402ea4 100644
--- a/src/devices/machine/acorn_vidc.h
+++ b/src/devices/machine/acorn_vidc.h
@@ -34,7 +34,7 @@ class acorn_vidc10_device : public device_t,
{
public:
// construction/destruction
- acorn_vidc10_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ acorn_vidc10_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// I/O operations
DECLARE_WRITE32_MEMBER( write );
@@ -42,36 +42,60 @@ public:
auto vblank() { return m_vblank_cb.bind(); }
auto sound_drq() { return m_sound_drq_cb.bind(); }
// MEMC comms
- void write_vram(uint32_t offset, uint8_t data) { m_data_vram[offset & (m_data_vram_mask)] = data; }
- void write_cram(uint32_t offset, uint8_t data) { m_cursor_vram[offset & (m_cursor_vram_mask)] = data; }
- void write_dac(uint8_t channel, uint8_t data);
- void clear_dac(uint8_t channel) { m_dac[channel & 7]->write(0); }
+ void write_vram(u32 offset, u8 data) { m_data_vram[offset & (m_data_vram_mask)] = data; }
+ void write_cram(u32 offset, u8 data) { m_cursor_vram[offset & (m_cursor_vram_mask)] = data; }
+ void write_dac(u8 channel, u8 data);
+ void clear_dac(u8 channel) { m_dac[channel & 7]->write(0); }
void update_sound_mode(bool state) { m_sound_mode = state; refresh_sound_frequency(); }
void set_cursor_enable(bool state) { m_cursor_enable = state; }
- uint32_t get_cursor_size() { return (m_crtc_regs[CRTC_VCER] - m_crtc_regs[CRTC_VCSR]) * (32/4); }
-
+ u32 get_cursor_size() { return (m_crtc_regs[CRTC_VCER] - m_crtc_regs[CRTC_VCSR]) * (32/4); }
+
protected:
acorn_vidc10_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
// device-level overrides
//virtual void device_validity_check(validity_checker &valid) const override;
virtual void device_add_mconfig(machine_config &config) override;
- virtual uint32_t palette_entries() const override;
+ virtual u32 palette_entries() const override;
virtual void device_config_complete() override;
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
virtual space_config_vector memory_space_config() const override;
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ virtual u32 get_pixel_clock();
-private:
- const address_space_config m_space_config;
-
+ address_space_config m_space_config;
void regs_map(address_map &map);
+ enum {
+ CRTC_HCR = 0, CRTC_HSWR, CRTC_HBSR, CRTC_HDSR, CRTC_HDER, CRTC_HBER, CRTC_HCSR, CRTC_HIR,
+ CRTC_VCR, CRTC_VSWR, CRTC_VBSR, CRTC_VDSR, CRTC_VDER, CRTC_VBER, CRTC_VCSR, CRTC_VCER
+ };
+ u32 m_crtc_regs[16];
+ enum {
+ TIMER_VIDEO = 1,
+ TIMER_SOUND = 2
+ };
+
+ inline void screen_vblank_line_update();
+ inline void screen_dynamic_res_change();
+ void refresh_sound_frequency();
+
+ u16 m_pal_4bpp_base;
+ u16 m_pal_cursor_base;
+ u16 m_pal_border_base;
+ const double m_sound_internal_divider = 8.0;
+
+ u8 m_bpp_mode, m_crtc_interlace;
+ u8 m_sound_frequency_latch;
+ bool m_sound_mode;
+
+ required_device_array<dac_16bit_r2r_twos_complement_device, 8> m_dac;
+
+private:
required_device<speaker_device> m_lspeaker;
required_device<speaker_device> m_rspeaker;
- required_device_array<dac_16bit_r2r_twos_complement_device, 8> m_dac;
devcb_write_line m_vblank_cb;
devcb_write_line m_sound_drq_cb;
@@ -81,51 +105,38 @@ private:
DECLARE_WRITE32_MEMBER( crtc_w );
DECLARE_WRITE32_MEMBER( sound_frequency_w );
DECLARE_WRITE32_MEMBER( control_w );
-
- uint8_t m_pixel_clock, m_bpp_mode, m_crtc_interlace;
+
+ u8 m_pixel_clock;
+ bool m_cursor_enable;
//bool m_flyback;
- enum {
- TIMER_VIDEO = 1,
- TIMER_SOUND = 2
- };
emu_timer *m_video_timer;
emu_timer *m_sound_timer;
-
- inline void screen_vblank_line_update();
- void screen_dynamic_res_change();
-
- enum {
- CRTC_HCR = 0, CRTC_HSWR, CRTC_HBSR, CRTC_HDSR, CRTC_HDER, CRTC_HBER, CRTC_HCSR, CRTC_HIR,
- CRTC_VCR, CRTC_VSWR, CRTC_VBSR, CRTC_VDSR, CRTC_VDER, CRTC_VBER, CRTC_VCSR, CRTC_VCER
- };
- uint32_t m_crtc_regs[16];
- u8 *m_data_vram;
- u8 *m_cursor_vram;
+
+ std::unique_ptr<u8[]> m_data_vram;
+ std::unique_ptr<u8[]> m_cursor_vram;
// TODO: correct data vram size
const u32 m_data_vram_mask = 0x1fffff;
const u32 m_cursor_vram_mask = 0x7fff;
const u32 m_data_vram_size = m_data_vram_mask+1;
const u32 m_cursor_vram_size = m_cursor_vram_mask+1;
- bool m_cursor_enable;
- void draw(bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 *vram, uint8_t bpp, int xstart, int ystart, int xsize, int ysize, bool is_cursor);
- inline void update_4bpp_palette(uint16_t index, uint32_t paldata);
+ void draw(bitmap_rgb32 &bitmap, const rectangle &cliprect, u8 *vram, u8 bpp, int xstart, int ystart, int xsize, int ysize, bool is_cursor);
+ inline void update_4bpp_palette(u16 index, u32 paldata);
+ u32 m_crtc_raw_horz[2];
+ inline u32 convert_crtc_hdisplay(u8 index);
- u8 m_sound_frequency_latch;
- bool m_sound_frequency_test_bit;
- bool m_sound_mode;
+ bool m_sound_frequency_test_bit;
u8 m_stereo_image[8];
const float m_sound_input_gain = 0.05f;
const int m_sound_max_channels = 8;
int16_t m_ulaw_lookup[256];
- void refresh_sound_frequency();
- inline void refresh_stereo_image(uint8_t channel);
+ inline void refresh_stereo_image(u8 channel);
};
class acorn_vidc10_lcd_device : public acorn_vidc10_device
{
public:
// construction/destruction
- acorn_vidc10_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ acorn_vidc10_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
virtual void device_add_mconfig(machine_config &config) override;
};
@@ -134,6 +145,48 @@ protected:
DECLARE_DEVICE_TYPE(ACORN_VIDC10, acorn_vidc10_device)
DECLARE_DEVICE_TYPE(ACORN_VIDC10_LCD, acorn_vidc10_lcd_device)
+class arm_vidc20_device : public acorn_vidc10_device
+{
+public:
+ // construction/destruction
+ arm_vidc20_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ void write_dac32(u8 channel, u16 data);
+ bool get_dac_mode();
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ void regs_map(address_map &map);
+ virtual u32 palette_entries() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_config_complete() override;
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ virtual u32 get_pixel_clock() override;
+
+ const double m_sound_internal_divider = 1.0;
+
+private:
+ DECLARE_WRITE32_MEMBER( vidc20_pal_data_display_w );
+ DECLARE_WRITE32_MEMBER( vidc20_pal_data_index_w );
+ DECLARE_WRITE32_MEMBER( vidc20_pal_data_cursor_w );
+ DECLARE_WRITE32_MEMBER( vidc20_crtc_w );
+ DECLARE_WRITE32_MEMBER( vidc20_control_w );
+ DECLARE_WRITE32_MEMBER( vidc20_sound_frequency_w );
+ DECLARE_WRITE32_MEMBER( vidc20_sound_control_w );
+ DECLARE_WRITE32_MEMBER( fsynreg_w );
+
+ u8 m_pal_data_index;
+ inline void update_8bpp_palette(u16 index, u32 paldata);
+ bool m_dac_serial_mode;
+ u8 m_pixel_source;
+ u8 m_pixel_rate;
+ u8 m_vco_r_modulo;
+ u8 m_vco_v_modulo;
+};
+
+DECLARE_DEVICE_TYPE(ARM_VIDC20, arm_vidc20_device)
//**************************************************************************
diff --git a/src/devices/machine/arm_iomd.cpp b/src/devices/machine/arm_iomd.cpp
new file mode 100644
index 00000000000..7cfa8d488f6
--- /dev/null
+++ b/src/devices/machine/arm_iomd.cpp
@@ -0,0 +1,767 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+ ARM IOMD device emulation
+
+ ARM7 SoC or stand-alone device, upgraded version(s) of the IOC found in Acorn Archimedes.
+
+ TODO:
+ - IOCR / IOLINES hookups can be further improved, also DDR bits needs verifying;
+ - word-boundary accesses for 8-bit ports;
+ - split into different types, add quick notes about where they diverges do in this header;
+ - keyboard/mouse interface hookup is wrong for PS/2 and unimplemented for quadrature.
+ I guess we can use connectors over a custom handling, with a terminal mock for testing it
+ without the overhead of everything else.
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "arm_iomd.h"
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(ARM_IOMD, arm_iomd_device, "arm_iomd", "ARM IOMD controller")
+// TODO: ssfindo.cpp actually uses a Cirrus Logic 7500FE, is it rebadged?
+DEFINE_DEVICE_TYPE(ARM7500FE_IOMD, arm7500fe_iomd_device, "arm_7500FE_SoC", "ARM 7500FE SoC")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arm_iomd_device - constructor
+//-------------------------------------------------
+
+void arm_iomd_device::base_map(address_map &map)
+{
+ // I/O
+ map(0x000, 0x003).rw(FUNC(arm_iomd_device::iocr_r), FUNC(arm_iomd_device::iocr_w));
+ map(0x004, 0x007).rw(FUNC(arm_iomd_device::kbddat_r), FUNC(arm_iomd_device::kbddat_w));
+ map(0x008, 0x00b).rw(FUNC(arm_iomd_device::kbdcr_r), FUNC(arm_iomd_device::kbdcr_w));
+
+ // interrupt A/B/fiq + master clock controls
+ map(0x010, 0x013).r(FUNC(arm_iomd_device::irqst_r<IRQA>));
+ map(0x014, 0x017).rw(FUNC(arm_iomd_device::irqrq_r<IRQA>), FUNC(arm_iomd_device::irqrq_w<IRQA>));
+ map(0x018, 0x01b).rw(FUNC(arm_iomd_device::irqmsk_r<IRQA>), FUNC(arm_iomd_device::irqmsk_w<IRQA>));
+
+ map(0x020, 0x023).r(FUNC(arm_iomd_device::irqst_r<IRQB>));
+ map(0x024, 0x027).rw(FUNC(arm_iomd_device::irqrq_r<IRQB>), FUNC(arm_iomd_device::irqrq_w<IRQB>));
+ map(0x028, 0x02b).rw(FUNC(arm_iomd_device::irqmsk_r<IRQB>), FUNC(arm_iomd_device::irqmsk_w<IRQB>));
+
+// map(0x030, 0x033).r(FUNC(arm_iomd_device::fiqst_r));
+// map(0x034, 0x037).rw(FUNC(arm_iomd_device::fiqrq_r), FUNC(arm_iomd_device::fiqrq_w));
+// map(0x038, 0x03b).rw(FUNC(arm_iomd_device::fiqmsk_r), FUNC(arm_iomd_device::fiqmsk_w));
+
+ // timers
+ map(0x040, 0x043).rw(FUNC(arm_iomd_device::tNlow_r<0>), FUNC(arm_iomd_device::tNlow_w<0>));
+ map(0x044, 0x047).rw(FUNC(arm_iomd_device::tNhigh_r<0>), FUNC(arm_iomd_device::tNhigh_w<0>));
+ map(0x048, 0x04b).w(FUNC(arm_iomd_device::tNgo_w<0>));
+ map(0x04c, 0x04f).w(FUNC(arm_iomd_device::tNlatch_w<0>));
+
+ map(0x050, 0x053).rw(FUNC(arm_iomd_device::tNlow_r<1>), FUNC(arm_iomd_device::tNlow_w<1>));
+ map(0x054, 0x057).rw(FUNC(arm_iomd_device::tNhigh_r<1>), FUNC(arm_iomd_device::tNhigh_w<1>));
+ map(0x058, 0x05b).w(FUNC(arm_iomd_device::tNgo_w<1>));
+ map(0x05c, 0x05f).w(FUNC(arm_iomd_device::tNlatch_w<1>));
+ // ROM control
+// map(0x080, 0x083).rw(FUNC(arm_iomd_device::romcr_r<0>), FUNC(arm_iomd_device::romcr_w<0>));
+// map(0x084, 0x087).rw(FUNC(arm_iomd_device::romcr_r<1>), FUNC(arm_iomd_device::romcr_w<1>));
+// map(0x08c, 0x08f).rw(FUNC(arm_iomd_device::refcr_r), FUNC(arm_iomd_device::refcr_w));
+
+ // device identifiers
+ map(0x094, 0x097).r(FUNC(arm_iomd_device::id_r<0>));
+ map(0x098, 0x09b).r(FUNC(arm_iomd_device::id_r<1>));
+ map(0x09c, 0x09f).r(FUNC(arm_iomd_device::version_r));
+ // mouse
+// map(0x0a0, 0x0a3) // ...
+
+ // I/O control
+// map(0x0c4, 0x0c7).rw(FUNC(arm_iomd_device::iotcr_r), FUNC(arm_iomd_device::iotcr_w));
+// map(0x0c8, 0x0cb).rw(FUNC(arm_iomd_device::ectcr_r), FUNC(arm_iomd_device::ectcr_w));
+ // sound DMA
+ // TODO: IOMD actually have a sd1* register, rework this
+ map(0x180, 0x183).rw(FUNC(arm_iomd_device::sdcur_r<0>), FUNC(arm_iomd_device::sdcur_w<0>));
+ map(0x184, 0x187).rw(FUNC(arm_iomd_device::sdend_r<0>), FUNC(arm_iomd_device::sdend_w<0>));
+ map(0x188, 0x18b).rw(FUNC(arm_iomd_device::sdcur_r<1>), FUNC(arm_iomd_device::sdcur_w<1>));
+ map(0x18c, 0x18f).rw(FUNC(arm_iomd_device::sdend_r<1>), FUNC(arm_iomd_device::sdend_w<1>));
+ map(0x190, 0x193).rw(FUNC(arm_iomd_device::sdcr_r), FUNC(arm_iomd_device::sdcr_w));
+ map(0x194, 0x197).r(FUNC(arm_iomd_device::sdst_r));
+
+ // video DMA
+// map(0x1c0, 0x1c3).rw(FUNC(arm_iomd_device::curscur_r), FUNC(arm_iomd_device::curscur_w));
+ map(0x1c4, 0x1c7).rw(FUNC(arm_iomd_device::cursinit_r), FUNC(arm_iomd_device::cursinit_w));
+
+// map(0x1d0, 0x1d3).rw(FUNC(arm_iomd_device::vidcura_r), FUNC(arm_iomd_device::vidcura_w));
+ map(0x1d4, 0x1d7).rw(FUNC(arm_iomd_device::vidend_r), FUNC(arm_iomd_device::vidend_w));
+// map(0x1d8, 0x1db).rw(FUNC(arm_iomd_device::vidstart_r), FUNC(arm_iomd_device::vidstart_w));
+ map(0x1dc, 0x1df).rw(FUNC(arm_iomd_device::vidinita_r), FUNC(arm_iomd_device::vidinita_w));
+ map(0x1e0, 0x1e3).rw(FUNC(arm_iomd_device::vidcr_r), FUNC(arm_iomd_device::vidcr_w));
+
+ // interrupt DMA
+ map(0x1f0, 0x1f3).r(FUNC(arm_iomd_device::irqst_r<IRQDMA>));
+ map(0x1f4, 0x1f7).rw(FUNC(arm_iomd_device::irqrq_r<IRQDMA>), FUNC(arm_iomd_device::irqrq_w<IRQDMA>));
+ map(0x1f8, 0x1fb).rw(FUNC(arm_iomd_device::irqmsk_r<IRQDMA>), FUNC(arm_iomd_device::irqmsk_w<IRQDMA>));
+
+// TODO: iomd2 has extra regs in 0x200-0x3ff area, others NOPs / mirrors?
+}
+
+void arm_iomd_device::map(address_map &map)
+{
+ arm_iomd_device::base_map(map);
+// map(0x088, 0x08b).rw(FUNC(arm_iomd_device::dramcr_r), FUNC(arm_iomd_device::dramcr_w));
+ // VRAM control
+// map(0x08c, 0x08f).rw(FUNC(arm_iomd_device::vrefcr_r), FUNC(arm_iomd_device::vrefcr_w));
+ // flyback line size
+// map(0x090, 0x093).rw(FUNC(arm_iomd_device::fsize_r), FUNC(arm_iomd_device::fsize_w));
+ // quadrature mouse control
+// map(0x0a0, 0x0a3).rw(FUNC(arm_iomd_device::mousex_r), FUNC(arm_iomd_device::mousex_w));
+// map(0x0a4, 0x0a7).rw(FUNC(arm_iomd_device::mousey_r), FUNC(arm_iomd_device::mousey_w));
+ // DACK timing control
+// map(0x0c0, 0x0c3).rw(FUNC(arm_iomd_device::dmatcr_r), FUNC(arm_iomd_device::dmatcr_w));
+ // DMA external control
+// map(0x0cc, 0x0cf).rw(FUNC(arm_iomd_device::dmaext_r), FUNC(arm_iomd_device::dmaext_w));
+ // I/O DMA, similar structure as sound DMA
+// map(0x100, 0x11f) ch 0
+// map(0x120, 0x13f) ch 1
+// map(0x140, 0x15f) ch 2
+// map(0x160, 0x17f) ch 3
+ // sound DMA
+// map(0x1a0, 0x1bf) ch 1
+
+}
+
+arm_iomd_device::arm_iomd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , m_host_cpu(*this, finder_base::DUMMY_TAG)
+ , m_vidc(*this, finder_base::DUMMY_TAG)
+ , m_kbdc(*this, finder_base::DUMMY_TAG)
+ , m_iocr_read_od_cb{{*this}, {*this}}
+ , m_iocr_write_od_cb{{*this}, {*this}}
+ , m_iocr_read_id_cb(*this)
+ , m_iocr_write_id_cb(*this)
+{
+}
+
+arm_iomd_device::arm_iomd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : arm_iomd_device(mconfig, ARM_IOMD, tag, owner, clock)
+{
+ m_id = 0xd4e7;
+ m_version = 0;
+}
+
+void arm7500fe_iomd_device::map(address_map &map)
+{
+ arm_iomd_device::base_map(map);
+
+ map(0x00c, 0x00f).rw(FUNC(arm7500fe_iomd_device::iolines_r), FUNC(arm7500fe_iomd_device::iolines_w));
+ // master clock controls
+// map(0x01c, 0x01f).rw(FUNC(arm7500fe_iomd_device::susmode_r), FUNC(arm7500fe_iomd_device::susmode_w));
+// map(0x02c, 0x02f).w(FUNC(arm7500fe_iomd_device::stopmode_w));
+ map(0x03c, 0x03f).rw(FUNC(arm7500fe_iomd_device::clkctl_r), FUNC(arm7500fe_iomd_device::clkctl_w));
+ // interrupt C/D
+ map(0x060, 0x063).r(FUNC(arm7500fe_iomd_device::irqst_r<IRQC>));
+ map(0x064, 0x067).rw(FUNC(arm7500fe_iomd_device::irqrq_r<IRQC>), FUNC(arm7500fe_iomd_device::irqrq_w<IRQC>));
+ map(0x068, 0x06b).rw(FUNC(arm7500fe_iomd_device::irqmsk_r<IRQC>), FUNC(arm7500fe_iomd_device::irqmsk_w<IRQC>));
+// map(0x06c, 0x06f).rw(FUNC(arm7500fe_iomd_device::vidmux_r), FUNC(arm7500fe_iomd_device::vidmux_w));
+ map(0x070, 0x073).r(FUNC(arm7500fe_iomd_device::irqst_r<IRQD>));
+ map(0x074, 0x077).rw(FUNC(arm7500fe_iomd_device::irqrq_r<IRQD>), FUNC(arm7500fe_iomd_device::irqrq_w<IRQD>));
+ map(0x078, 0x07b).rw(FUNC(arm7500fe_iomd_device::irqmsk_r<IRQD>), FUNC(arm7500fe_iomd_device::irqmsk_w<IRQD>));
+
+ // PS/2 mouse
+// map(0x0a8, 0x0ab).rw(FUNC(arm7500fe_iomd_device::msedat_r), FUNC(arm7500fe_iomd_device::msedat_w));
+ map(0x0ac, 0x0af).rw(FUNC(arm7500fe_iomd_device::msecr_r), FUNC(arm7500fe_iomd_device::msecr_w));
+ // I/O control
+// map(0x0cc, 0x0cf).rw(FUNC(arm7500fe_iomd_device::astcr_r), FUNC(arm7500fe_iomd_device::astcr_w));
+ // RAM control
+// map(0x0d0, 0x0d3).rw(FUNC(arm7500fe_iomd_device::dramctl_r), FUNC(arm7500fe_iomd_device::dramctl_w));
+// map(0x0d4, 0x0d7).rw(FUNC(arm7500fe_iomd_device::selfref_r), FUNC(arm7500fe_iomd_device::selfref_w));
+ // A/D converter
+// map(0x0e0, 0x0e3).rw(FUNC(arm7500fe_iomd_device::atodicr_r), FUNC(arm7500fe_iomd_device::atodicr_w));
+// map(0x0e4, 0x0e7).r(FUNC(arm7500fe_iomd_device::atodsr_r));
+// map(0x0e8, 0x0eb).rw(FUNC(arm7500fe_iomd_device::atodcc_r), FUNC(arm7500fe_iomd_device::atodcc_w));
+// map(0x0ec, 0x0ef).r(FUNC(arm7500fe_iomd_device::atodcnt_r<0>));
+// map(0x0f0, 0x0f3).r(FUNC(arm7500fe_iomd_device::atodcnt_r<1>));
+// map(0x0f4, 0x0f7).r(FUNC(arm7500fe_iomd_device::atodcnt_r<2>));
+// map(0x0f8, 0x0fb).r(FUNC(arm7500fe_iomd_device::atodcnt_r<3>));
+ // video DMA
+// map(0x1c8, 0x1cb).rw(FUNC(arm7500fe_iomd_device::vidcurb_r), FUNC(arm7500fe_iomd_device::vidcurb_w));
+// map(0x1e8, 0x1eb).rw(FUNC(arm7500fe_iomd_device::vidinitb_r), FUNC(arm7500fe_iomd_device::vidinitb_w));
+
+}
+
+arm7500fe_iomd_device::arm7500fe_iomd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arm_iomd_device(mconfig, ARM7500FE_IOMD, tag, owner, clock)
+ , m_iolines_read_cb(*this)
+ , m_iolines_write_cb(*this)
+{
+ m_id = 0xaa7c;
+ m_version = 0;
+}
+
+// vanilla ARM7500 m_id = 0x5b98; m_version = 0;
+// IOMD2 m_id = 0xd5e8; m_version = 1;
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific machine
+// configuration addiitons
+//-------------------------------------------------
+
+void arm_iomd_device::device_add_mconfig(machine_config &config)
+{
+ //DEVICE(config, ...);
+ //TODO: keyboard and mouse interfaces at very least, also they differs by device type
+}
+
+void arm7500fe_iomd_device::device_add_mconfig(machine_config &config)
+{
+ //DEVICE(config, ...);
+ //TODO: above plus new sub-devices
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arm_iomd_device::device_start()
+{
+ for (devcb_read_line &cb : m_iocr_read_od_cb)
+ cb.resolve_safe(1);
+
+ for (devcb_write_line &cb : m_iocr_write_od_cb)
+ cb.resolve_safe();
+
+ m_iocr_read_id_cb.resolve_safe(1);
+ m_iocr_write_id_cb.resolve_safe();
+
+ save_item(NAME(m_iocr_ddr));
+ save_item(NAME(m_video_enable));
+ save_item(NAME(m_vidinita));
+ save_item(NAME(m_vidend));
+ save_item(NAME(m_vidlast));
+ save_item(NAME(m_videqual));
+ save_item(NAME(m_cursor_enable));
+ save_item(NAME(m_cursinit));
+ save_pointer(NAME(m_irq_mask), IRQ_SOURCES_SIZE);
+ save_pointer(NAME(m_irq_status), IRQ_SOURCES_SIZE);
+
+ m_host_space = &m_host_cpu->space(AS_PROGRAM);
+
+ m_timer[0] = timer_alloc(T0_TIMER);
+ m_timer[1] = timer_alloc(T1_TIMER);
+ save_pointer(NAME(m_timer_in), timer_ch_size);
+ save_pointer(NAME(m_timer_out), timer_ch_size);
+ save_pointer(NAME(m_timer_counter), timer_ch_size);
+ save_pointer(NAME(m_timer_readinc), timer_ch_size);
+
+ save_item(NAME(m_sndcur));
+ save_item(NAME(m_sndend));
+ save_item(NAME(m_sound_dma_on));
+ save_item(NAME(m_sndcur_buffer));
+ save_item(NAME(m_snd_overrun));
+ save_item(NAME(m_snd_int));
+
+ save_pointer(NAME(m_sndcur_reg), sounddma_ch_size);
+ save_pointer(NAME(m_sndend_reg), sounddma_ch_size);
+ save_pointer(NAME(m_sndstop_reg), sounddma_ch_size);
+ save_pointer(NAME(m_sndlast_reg), sounddma_ch_size);
+ save_pointer(NAME(m_sndbuffer_ok), sounddma_ch_size);
+
+ // TODO: jumps to EASI space at $0c0016xx for RiscPC if POR is on?
+}
+
+void arm7500fe_iomd_device::device_start()
+{
+ arm_iomd_device::device_start();
+
+ m_iolines_read_cb.resolve_safe(0xff);
+ m_iolines_write_cb.resolve_safe();
+ save_item(NAME(m_iolines_ddr));
+
+ save_item(NAME(m_cpuclk_divider));
+ save_item(NAME(m_memclk_divider));
+ save_item(NAME(m_ioclk_divider));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arm_iomd_device::device_reset()
+{
+ int i;
+ m_iocr_ddr = 0x0b;
+ m_video_enable = false;
+ // TODO: defaults for these
+ m_vidinita = 0;
+ m_vidend = 0;
+
+ for (i=0; i<IRQ_SOURCES_SIZE; i++)
+ {
+ m_irq_status[i] = 0;
+ m_irq_mask[i] = 0;
+ }
+
+ for (i=0; i<timer_ch_size; i++)
+ m_timer[i]->adjust(attotime::never);
+
+ m_sound_dma_on = false;
+ for (i=0; i<sounddma_ch_size; i++)
+ m_sndbuffer_ok[i] = false;
+
+ // ...
+}
+
+void arm7500fe_iomd_device::device_reset()
+{
+ arm_iomd_device::device_reset();
+
+ m_cpuclk_divider = m_ioclk_divider = m_memclk_divider = false;
+ refresh_host_cpu_clocks();
+
+ m_iolines_ddr = 0xff;
+}
+
+void arm_iomd_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch(id)
+ {
+ case T0_TIMER:
+ case T1_TIMER:
+ trigger_irq<IRQA>(id == T1_TIMER ? 0x40 : 0x20);
+ break;
+ }
+}
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+// TODO: nINT1
+READ32_MEMBER( arm_iomd_device::iocr_r )
+{
+ u8 res = 0;
+
+ res = m_iocr_read_id_cb() << 3;
+ res|= m_iocr_read_od_cb[1]() << 1;
+ res|= m_iocr_read_od_cb[0]() << 0;
+
+ return (m_vidc->flyback_r() << 7) | 0x34 | (res & m_iocr_ddr);
+}
+
+WRITE32_MEMBER( arm_iomd_device::iocr_w )
+{
+ m_iocr_ddr = (data & 0x0b);
+ m_iocr_write_id_cb(BIT(m_iocr_ddr,3));
+ m_iocr_write_od_cb[1](BIT(m_iocr_ddr,1));
+ m_iocr_write_od_cb[0](BIT(m_iocr_ddr,0));
+}
+
+READ32_MEMBER( arm_iomd_device::kbddat_r )
+{
+ if (m_kbdc.found())
+ return m_kbdc->data_r();
+
+ logerror("%s attempted to read kbddat with no controller\n", this->tag());
+ return 0xff;
+}
+
+READ32_MEMBER( arm_iomd_device::kbdcr_r )
+{
+ if (m_kbdc.found())
+ return m_kbdc->status_r();
+
+ logerror("%s attempted to read kbdcr with no controller\n", this->tag());
+ return 0xff;
+}
+
+WRITE32_MEMBER( arm_iomd_device::kbddat_w )
+{
+ if (m_kbdc.found())
+ {
+ m_kbdc->data_w(data & 0xff);
+ return;
+ }
+
+ logerror("%s attempted to write %02x on kbddat with no controller\n", this->tag(),data & 0xff);
+}
+
+WRITE32_MEMBER( arm_iomd_device::kbdcr_w )
+{
+ if (m_kbdc.found())
+ {
+ m_kbdc->command_w(data & 0xff);
+ return;
+ }
+
+ logerror("%s attempted to write %02x on kbdcr with no controller\n", this->tag(),data & 0xff);
+}
+
+READ32_MEMBER( arm7500fe_iomd_device::msecr_r )
+{
+ // a7000p wants a TX empty otherwise it outright refuses to boot.
+ return 0x80;
+}
+
+WRITE32_MEMBER( arm7500fe_iomd_device::msecr_w )
+{
+ // ...
+}
+
+READ32_MEMBER( arm7500fe_iomd_device::iolines_r )
+{
+ return m_iolines_read_cb() & m_iolines_ddr;
+}
+
+WRITE32_MEMBER( arm7500fe_iomd_device::iolines_w )
+{
+ m_iolines_ddr = data;
+ m_iolines_write_cb(m_iolines_ddr);
+}
+
+// irqA is special since it has a force (7) and ignore (1) bits
+inline u8 arm_iomd_device::update_irqa_type(u8 data)
+{
+ return (data & 0xfd) | 0x80;
+}
+
+// interrupts
+
+inline void arm_iomd_device::flush_irq(unsigned Which)
+{
+ if (m_irq_status[Which] & m_irq_mask[Which])
+ m_host_cpu->pulse_input_line(ARM7_IRQ_LINE, m_host_cpu->minimum_quantum_time());
+}
+
+template <unsigned Which> inline void arm_iomd_device::trigger_irq(u8 irq_type)
+{
+ m_irq_status[Which] |= irq_type;
+ flush_irq(Which);
+}
+
+template <unsigned Which> READ32_MEMBER( arm_iomd_device::irqst_r )
+{
+ return m_irq_status[Which];
+}
+
+template <unsigned Which> READ32_MEMBER( arm_iomd_device::irqrq_r )
+{
+ return m_irq_status[Which] & m_irq_mask[Which];
+}
+
+template <unsigned Which> READ32_MEMBER( arm_iomd_device::irqmsk_r )
+{
+ return m_irq_mask[Which];
+}
+
+template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::irqrq_w )
+{
+ u8 res = m_irq_status[Which] & ~data;
+ if (Which == IRQA)
+ res = update_irqa_type(res);
+ m_irq_status[Which] = res;
+ flush_irq(Which);
+}
+
+template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::irqmsk_w )
+{
+ m_irq_mask[Which] = data & 0xff;
+ flush_irq(Which);
+}
+
+// master clock control
+inline void arm7500fe_iomd_device::refresh_host_cpu_clocks()
+{
+ m_host_cpu->set_unscaled_clock(this->clock() >> (m_cpuclk_divider == false));
+}
+
+READ32_MEMBER( arm7500fe_iomd_device::clkctl_r )
+{
+ return (m_cpuclk_divider << 2) | (m_memclk_divider << 1) | (m_ioclk_divider);
+}
+
+WRITE32_MEMBER( arm7500fe_iomd_device::clkctl_w )
+{
+ m_cpuclk_divider = BIT(data, 2);
+ m_memclk_divider = BIT(data, 1);
+ m_ioclk_divider = BIT(data, 0);
+ refresh_host_cpu_clocks();
+}
+
+// timers
+inline void arm_iomd_device::trigger_timer(unsigned Which)
+{
+ int timer_count = m_timer_counter[Which];
+ // TODO: it's actually a 2 MHz timer
+ int val = timer_count / 2;
+
+ if(val==0)
+ m_timer[Which]->adjust(attotime::never);
+ else
+ m_timer[Which]->adjust(attotime::from_usec(val), 0, attotime::from_usec(val));
+}
+
+// TODO: live updates aren't really supported here
+template <unsigned Which> READ32_MEMBER( arm_iomd_device::tNlow_r )
+{
+ return m_timer_out[Which] & 0xff;
+}
+
+template <unsigned Which> READ32_MEMBER( arm_iomd_device::tNhigh_r )
+{
+ return (m_timer_out[Which] >> 8) & 0xff;
+}
+
+template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::tNlow_w )
+{
+ m_timer_in[Which] = (m_timer_in[Which] & 0xff00) | (data & 0xff);
+}
+
+template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::tNhigh_w )
+{
+ m_timer_in[Which] = (m_timer_in[Which] & 0x00ff) | ((data & 0xff) << 8);
+}
+
+template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::tNgo_w )
+{
+ m_timer_counter[Which] = m_timer_in[Which];
+ trigger_timer(Which);
+}
+
+template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::tNlatch_w )
+{
+ m_timer_readinc[Which] ^=1;
+ m_timer_out[Which] = m_timer_counter[Which];
+ if(m_timer_readinc[Which])
+ {
+ m_timer_counter[Which]--;
+ if(m_timer_counter[Which] < 0)
+ m_timer_counter[Which] += m_timer_in[Which];
+ }
+}
+
+// device identifiers
+template <unsigned Nibble> READ32_MEMBER( arm_iomd_device::id_r )
+{
+ return (m_id >> (Nibble*8)) & 0xff;
+}
+
+READ32_MEMBER( arm_iomd_device::version_r )
+{
+ return m_version;
+}
+
+DECLARE_READ32_MEMBER( version_r );
+
+// sound DMA
+
+template <unsigned Which> READ32_MEMBER( arm_iomd_device::sdcur_r ) { return m_sndcur_reg[Which]; }
+template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::sdcur_w ) { COMBINE_DATA(&m_sndcur_reg[Which]); }
+template <unsigned Which> READ32_MEMBER( arm_iomd_device::sdend_r )
+{
+ return (m_sndstop_reg[Which] << 31) | (m_sndlast_reg[Which] << 30) | (m_sndend_reg[Which] & 0x00fffff0);
+}
+
+template <unsigned Which> WRITE32_MEMBER( arm_iomd_device::sdend_w )
+{
+ COMBINE_DATA(&m_sndend_reg[Which]);
+ m_sndend_reg[Which] &= 0x00fffff0;
+ m_sndstop_reg[Which] = BIT(data, 31);
+ m_sndlast_reg[Which] = BIT(data, 30);
+}
+
+READ32_MEMBER( arm_iomd_device::sdcr_r )
+{
+ return (m_sound_dma_on << 5) | dmaid_size;
+}
+
+WRITE32_MEMBER( arm_iomd_device::sdcr_w )
+{
+ m_sound_dma_on = BIT(data, 5);
+
+ m_vidc->update_sound_mode(m_sound_dma_on);
+ if (m_sound_dma_on)
+ {
+ m_sndcur_buffer = 0;
+ sounddma_swap_buffer();
+ }
+ else
+ {
+ // ...
+ }
+
+ // TODO: bit 7 resets sound DMA
+}
+
+READ32_MEMBER( arm_iomd_device::sdst_r )
+{
+ return (m_snd_overrun << 2) | (m_snd_int << 1) | m_sndcur_buffer;
+}
+
+// video DMA
+READ32_MEMBER( arm_iomd_device::cursinit_r )
+{
+ return m_cursinit;
+}
+
+WRITE32_MEMBER( arm_iomd_device::cursinit_w )
+{
+ COMBINE_DATA(&m_cursinit);
+ m_cursinit &= 0x1ffffff0;
+ m_cursor_enable = true;
+ m_vidc->set_cursor_enable(m_cursor_enable);
+}
+
+READ32_MEMBER( arm_iomd_device::vidcr_r )
+{
+ // bit 6: DRAM mode
+ // bits 4-0: qword transfer
+ return 0x40 | (m_video_enable << 5) | dmaid_size;
+}
+
+WRITE32_MEMBER( arm_iomd_device::vidcr_w )
+{
+ m_video_enable = BIT(data, 5);
+ if (m_video_enable == false)
+ {
+ m_cursor_enable = false;
+ m_vidc->set_cursor_enable(m_cursor_enable);
+ }
+
+ if (data & 0x80)
+ throw emu_fatalerror("%s VIDCR LCD dual panel mode enabled", this->tag());
+}
+
+READ32_MEMBER( arm_iomd_device::vidend_r )
+{
+ return (m_vidend & 0x00fffff0);
+}
+
+WRITE32_MEMBER( arm_iomd_device::vidend_w )
+{
+ COMBINE_DATA(&m_vidend);
+ m_vidend &= 0x00fffff0;
+}
+
+READ32_MEMBER( arm_iomd_device::vidinita_r )
+{
+ return (m_vidlast << 30) | (m_videqual << 29) | (m_vidinita & 0x1ffffff0);
+}
+
+WRITE32_MEMBER( arm_iomd_device::vidinita_w )
+{
+ COMBINE_DATA(&m_vidinita);
+ m_vidinita &= 0x1ffffff0;
+ m_vidlast = BIT(data, 30);
+ m_videqual = BIT(data, 29);
+}
+
+
+//**************************************************************************
+// IRQ/DRQ/Reset signals
+//**************************************************************************
+
+WRITE_LINE_MEMBER( arm_iomd_device::vblank_irq )
+{
+ if (!state)
+ return;
+
+ trigger_irq<IRQA>(0x08);
+ if (m_video_enable == true)
+ {
+ // TODO: much more complex, last/end regs, start regs and eventually LCD hooks
+ u32 src = m_vidinita;
+ u32 size = m_vidend;
+
+ // TODO: vidcur can be readback, support it once anything makes use of the 0x1d0 reg for obvious reasons
+ // (and using m_ prefix is intentional too)
+ for (u32 m_vidcur = 0; m_vidcur<size; m_vidcur++)
+ {
+ m_vidc->write_vram(m_vidcur, m_host_space->read_byte(src));
+ src++;
+ src &= 0x1fffffff;
+ }
+
+ if (m_cursor_enable == true)
+ {
+ src = m_cursinit;
+ size = m_vidc->get_cursor_size();
+
+ // TODO: same as above
+ for (u32 m_curscur = 0; m_curscur<size; m_curscur++)
+ {
+ m_vidc->write_cram(m_curscur, m_host_space->read_byte(src));
+ src++;
+ src &= 0x1fffffff;
+ }
+ }
+ }
+}
+
+inline void arm_iomd_device::sounddma_swap_buffer()
+{
+ m_sndcur = m_sndcur_reg[m_sndcur_buffer];
+ m_sndend = m_sndcur + (m_sndend_reg[m_sndcur_buffer] + 0x10);
+ m_sndbuffer_ok[m_sndcur_buffer] = true;
+
+ // TODO: actual condition for int
+ m_snd_overrun = false;
+ m_snd_int = false;
+}
+
+WRITE_LINE_MEMBER( arm_iomd_device::sound_drq )
+{
+ if (!state)
+ return;
+
+ if (m_vidc->get_dac_mode() == true)
+ {
+ for (int ch=0;ch<2;ch++)
+ m_vidc->write_dac32(ch, (m_host_space->read_word(m_sndcur + ch*2)));
+
+ m_sndcur += 4;
+
+ if (m_sndcur >= m_sndend)
+ {
+ // TODO: interrupt bit
+
+ m_vidc->update_sound_mode(m_sound_dma_on);
+ if (m_sound_dma_on)
+ {
+ m_sndbuffer_ok[m_sndcur_buffer] = false;
+ m_sndcur_buffer ^= 1;
+ m_snd_overrun = (m_sndbuffer_ok[m_sndcur_buffer] == false);
+ sounddma_swap_buffer();
+ }
+ else
+ {
+ // ...
+ }
+ }
+ }
+ else
+ {
+ // ...
+ }
+}
+
+WRITE_LINE_MEMBER( arm_iomd_device::keyboard_irq )
+{
+ printf("IRQ %d\n",state);
+ if (!state)
+ return;
+
+ trigger_irq<IRQB>(0x80);
+}
+
+WRITE_LINE_MEMBER( arm_iomd_device::keyboard_reset )
+{
+ printf("RST %d\n",state);
+}
+
+
diff --git a/src/devices/machine/arm_iomd.h b/src/devices/machine/arm_iomd.h
new file mode 100644
index 00000000000..c996a88b3dd
--- /dev/null
+++ b/src/devices/machine/arm_iomd.h
@@ -0,0 +1,211 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/***************************************************************************
+
+ ARM IOMD device emulation
+
+***************************************************************************/
+
+#ifndef MAME_MACHINE_ARM_IOMD_H
+#define MAME_MACHINE_ARM_IOMD_H
+
+#pragma once
+
+#include "cpu/arm7/arm7.h"
+#include "cpu/arm7/arm7core.h"
+#include "machine/acorn_vidc.h"
+#include "machine/at_keybc.h"
+#include "bus/pc_kbd/pc_kbdc.h"
+#include "bus/pc_kbd/keyboards.h"
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> arm_iomd_device
+
+class arm_iomd_device : public device_t
+{
+public:
+ // construction/destruction
+ arm_iomd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ arm_iomd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ template <unsigned N> auto iocr_read_od() { return m_iocr_read_od_cb[N].bind(); }
+ template <unsigned N> auto iocr_write_od() { return m_iocr_write_od_cb[N].bind(); }
+ auto iocr_read_id() { return m_iocr_read_id_cb.bind(); }
+ auto iocr_write_id() { return m_iocr_write_id_cb.bind(); }
+ // IRQA
+ DECLARE_WRITE_LINE_MEMBER( vblank_irq );
+ // IRQB
+ DECLARE_WRITE_LINE_MEMBER( keyboard_irq );
+ // DRQs
+ DECLARE_WRITE_LINE_MEMBER( sound_drq );
+ // Reset
+ DECLARE_WRITE_LINE_MEMBER( keyboard_reset );
+
+ // I/O operations
+ virtual void map(address_map &map);
+ template<class T> void set_host_cpu_tag(T &&tag) { m_host_cpu.set_tag(std::forward<T>(tag)); }
+ template<class T> void set_vidc_tag(T &&tag) { m_vidc.set_tag(std::forward<T>(tag)); }
+ template<class T> void set_kbdc_tag(T &&tag) { m_kbdc.set_tag(std::forward<T>(tag)); }
+
+protected:
+ // device-level overrides
+ //virtual void device_validity_check(validity_checker &valid) const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+ void base_map(address_map &map);
+ u16 m_id;
+ u8 m_version;
+
+ enum {
+ IRQA = 0,
+ IRQB,
+ IRQC,
+ IRQD,
+ IRQDMA,
+ IRQ_SOURCES_SIZE
+ };
+ template <unsigned Which> DECLARE_READ32_MEMBER( irqst_r );
+ template <unsigned Which> DECLARE_READ32_MEMBER( irqrq_r );
+ template <unsigned Which> DECLARE_WRITE32_MEMBER( irqrq_w );
+ template <unsigned Which> DECLARE_READ32_MEMBER( irqmsk_r );
+ template <unsigned Which> DECLARE_WRITE32_MEMBER( irqmsk_w );
+
+ // TODO: convert to ARM7 device instead, enums shouldn't be public
+ required_device<cpu_device> m_host_cpu;
+ required_device<arm_vidc20_device> m_vidc;
+ optional_device<ps2_keyboard_controller_device> m_kbdc;
+ address_space *m_host_space; /**< reference to the host cpu space for DMA ops */
+private:
+ u8 m_iocr_ddr;
+
+ devcb_read_line m_iocr_read_od_cb[2];
+ devcb_write_line m_iocr_write_od_cb[2];
+ devcb_read_line m_iocr_read_id_cb;
+ devcb_write_line m_iocr_write_id_cb;
+
+ DECLARE_READ32_MEMBER( iocr_r );
+ DECLARE_WRITE32_MEMBER( iocr_w );
+
+ DECLARE_READ32_MEMBER( kbddat_r );
+ DECLARE_WRITE32_MEMBER( kbddat_w );
+ DECLARE_READ32_MEMBER( kbdcr_r );
+ DECLARE_WRITE32_MEMBER( kbdcr_w );
+
+ u32 m_vidinita, m_vidend;
+ bool m_vidlast, m_videqual;
+ bool m_video_enable;
+ DECLARE_READ32_MEMBER( vidcr_r );
+ DECLARE_WRITE32_MEMBER( vidcr_w );
+ DECLARE_READ32_MEMBER( vidend_r );
+ DECLARE_WRITE32_MEMBER( vidend_w );
+ DECLARE_READ32_MEMBER( vidinita_r );
+ DECLARE_WRITE32_MEMBER( vidinita_w );
+ u32 m_cursinit;
+ bool m_cursor_enable;
+ DECLARE_READ32_MEMBER( cursinit_r );
+ DECLARE_WRITE32_MEMBER( cursinit_w );
+
+ static constexpr int sounddma_ch_size = 2;
+ u32 m_sndcur, m_sndend;
+ u32 m_sndcur_reg[sounddma_ch_size], m_sndend_reg[sounddma_ch_size];
+ bool m_sndstop_reg[sounddma_ch_size], m_sndlast_reg[sounddma_ch_size];
+ bool m_sndbuffer_ok[sounddma_ch_size];
+ bool m_sound_dma_on;
+ u8 m_sndcur_buffer;
+ bool m_snd_overrun, m_snd_int;
+ inline void sounddma_swap_buffer();
+ template <unsigned Which> DECLARE_READ32_MEMBER( sdcur_r );
+ template <unsigned Which> DECLARE_WRITE32_MEMBER( sdcur_w );
+ template <unsigned Which> DECLARE_READ32_MEMBER( sdend_r );
+ template <unsigned Which> DECLARE_WRITE32_MEMBER( sdend_w );
+ DECLARE_READ32_MEMBER( sdcr_r );
+ DECLARE_WRITE32_MEMBER( sdcr_w );
+ DECLARE_READ32_MEMBER( sdst_r );
+
+ u8 m_irq_status[IRQ_SOURCES_SIZE], m_irq_mask[IRQ_SOURCES_SIZE];
+ inline u8 update_irqa_type(u8 data);
+ inline void flush_irq(unsigned Which);
+ template <unsigned Which> inline void trigger_irq(u8 irq_type);
+
+ static constexpr int timer_ch_size = 2;
+ enum {
+ T0_TIMER = 1,
+ T1_TIMER
+ };
+ inline void trigger_timer(unsigned Which);
+ u16 m_timer_in[2];
+ u16 m_timer_out[2];
+ int m_timer_counter[2];
+ u8 m_timer_readinc[2];
+ emu_timer *m_timer[2];
+
+ template <unsigned Which> DECLARE_READ32_MEMBER( tNlow_r );
+ template <unsigned Which> DECLARE_READ32_MEMBER( tNhigh_r );
+ template <unsigned Which> DECLARE_WRITE32_MEMBER( tNlow_w );
+ template <unsigned Which> DECLARE_WRITE32_MEMBER( tNhigh_w );
+ template <unsigned Which> DECLARE_WRITE32_MEMBER( tNgo_w );
+ template <unsigned Which> DECLARE_WRITE32_MEMBER( tNlatch_w );
+
+ template <unsigned Nibble> DECLARE_READ32_MEMBER( id_r );
+ DECLARE_READ32_MEMBER( version_r );
+
+ // used in vidcr_r / sndcr_r, documentation hints this is a purged idea during chip development, to be checked out
+ static constexpr u8 dmaid_size = 0x10; // qword transfer
+// constexpr u8 dmaid_mask = 0x1f;
+};
+
+class arm7500fe_iomd_device : public arm_iomd_device
+{
+public:
+ // construction/destruction
+ arm7500fe_iomd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void map(address_map &map) override;
+ auto iolines_read() { return m_iolines_read_cb.bind(); }
+ auto iolines_write() { return m_iolines_write_cb.bind(); }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+private:
+ devcb_read8 m_iolines_read_cb;
+ devcb_write8 m_iolines_write_cb;
+
+ bool m_cpuclk_divider, m_memclk_divider, m_ioclk_divider;
+ inline void refresh_host_cpu_clocks();
+ DECLARE_READ32_MEMBER( clkctl_r );
+ DECLARE_WRITE32_MEMBER( clkctl_w );
+
+ u8 m_iolines_ddr;
+ DECLARE_READ32_MEMBER( iolines_r );
+ DECLARE_WRITE32_MEMBER( iolines_w );
+
+ DECLARE_READ32_MEMBER( msecr_r );
+ DECLARE_WRITE32_MEMBER( msecr_w );
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARM_IOMD, arm_iomd_device)
+DECLARE_DEVICE_TYPE(ARM7500FE_IOMD, arm7500fe_iomd_device)
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+
+#endif // MAME_MACHINE_ARM_IOMD_H
diff --git a/src/mame/drivers/riscpc.cpp b/src/mame/drivers/riscpc.cpp
index a5fb926105d..5208fec8e41 100644
--- a/src/mame/drivers/riscpc.cpp
+++ b/src/mame/drivers/riscpc.cpp
@@ -2,28 +2,25 @@
// copyright-holders:Angelo Salese
/***************************************************************************
- Acorn Archimedes 7000/7000+
+ Acorn RiscPC line of computers
- very preliminary driver by Angelo Salese,
+ preliminary driver by Angelo Salese,
based on work by Tomasz Slanina and Sarah Walker
TODO:
- - Move device implementations into specific files;
- - PS/2 keyboard doesn't work properly;
- - i2c device should actually be a pcf8583 RTC with i2c as slave
- (and indeed CMOS settings doesn't work);
- - Fix pendingUnd fatalerror from ARM7 core
- - Fix per-machine configurations;
-
- ???
- bp (0382827C) (second trigger)
- do R13 = SR13
+ - IOMD currently hardwired with ARM7500FE flavour for all machines, needs information about
+ which uses what;
+ - PS/2 keyboard doesn't work properly;
+ - Fix pendingUnd fatalerror from ARM7 core;
+ - Fix pendingAbtD fatalerror for RiscOS 4.xx;
****************************************************************************/
#include "emu.h"
#include "cpu/arm7/arm7.h"
#include "cpu/arm7/arm7core.h"
+#include "machine/acorn_vidc.h"
+#include "machine/arm_iomd.h"
#include "machine/i2cmem.h"
#include "machine/at_keybc.h"
#include "bus/pc_kbd/pc_kbdc.h"
@@ -37,12 +34,13 @@ class riscpc_state : public driver_device
{
public:
riscpc_state(const machine_config &mconfig, device_type type, const char *tag)
- : driver_device(mconfig, type, tag),
- m_maincpu(*this, "maincpu"),
- m_screen(*this, "screen"),
- m_palette(*this, "palette"),
- m_i2cmem(*this, "i2cmem"),
- m_kbdc(*this, "kbdc")
+ : driver_device(mconfig, type, tag)
+ , m_maincpu(*this, "maincpu")
+ , m_vidc(*this, "vidc")
+ , m_iomd(*this, "iomd")
+ , m_screen(*this, "screen")
+ , m_i2cmem(*this, "i2cmem")
+ , m_kbdc(*this, "kbdc")
{ }
void rpc700(machine_config &config);
@@ -56,791 +54,47 @@ private:
void base_config(machine_config &config);
required_device<cpu_device> m_maincpu;
+ required_device<arm_vidc20_device> m_vidc;
+ required_device<arm7500fe_iomd_device> m_iomd;
required_device<screen_device> m_screen;
- required_device<palette_device> m_palette;
required_device<i2cmem_device> m_i2cmem;
required_device<ps2_keyboard_controller_device> m_kbdc;
- std::unique_ptr<uint32_t[]> m_vram;
-
- DECLARE_READ32_MEMBER(a7000_iomd_r);
- DECLARE_WRITE32_MEMBER(a7000_iomd_w);
- DECLARE_WRITE32_MEMBER(a7000_vidc20_w);
- DECLARE_WRITE_LINE_MEMBER(keyboard_reset);
- DECLARE_WRITE_LINE_MEMBER(keyboard_interrupt);
-
- uint8_t m_vidc20_pal_index;
- uint16_t m_vidc20_horz_reg[0x10];
- uint16_t m_vidc20_vert_reg[0x10];
- uint8_t m_vidc20_bpp_mode;
- emu_timer *m_flyback_timer;
- uint16_t m_timer_in[2];
- uint16_t m_timer_out[2];
- int m_timer_counter[2];
- emu_timer *m_IOMD_timer[2];
- uint8_t m_IRQ_status_A, m_IRQ_status_B;
- uint8_t m_IRQ_mask_A, m_IRQ_mask_B;
- uint8_t m_IOMD_IO_ctrl;
- uint8_t m_IOMD_keyb_ctrl;
- uint16_t m_io_id;
- uint8_t m_viddma_status;
- uint32_t m_viddma_addr_init;
- uint32_t m_viddma_addr_start;
- uint32_t m_viddma_addr_end;
- uint8_t m_t0readinc;
- uint8_t m_t1readinc;
uint8_t m_i2c_clk;
- void fire_iomd_timer(int timer);
- void viddma_transfer_start();
- void vidc20_dynamic_screen_change();
- virtual void video_start() override;
+
virtual void machine_reset() override;
virtual void machine_start() override;
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- TIMER_CALLBACK_MEMBER(IOMD_timer0_callback);
- TIMER_CALLBACK_MEMBER(IOMD_timer1_callback);
- TIMER_CALLBACK_MEMBER(flyback_timer_callback);
- TIMER_CALLBACK_MEMBER(videodma_timer_callback);
-
void a7000_map(address_map &map);
void riscpc_map(address_map &map);
- void update_irq();
-};
-
-
-/*
- *
- * VIDC20 chip emulation
- *
- */
-
-void riscpc_state::video_start()
-{
- const uint32_t vram_size = 0x1000000/4;
- m_vram = std::make_unique<uint32_t[]>(vram_size);
- save_pointer(NAME(m_vram), vram_size);
-}
-
-
-static const char *const vidc20_regnames[] =
-{
- "Video Palette", // 0
- "Video Palette Address", // 1
- "RESERVED", // 2
- "LCD offset", // 3
- "Border Colour", // 4
- "Cursor Palette Logical Colour 1", // 5
- "Cursor Palette Logical Colour 2", // 6
- "Cursor Palette Logical Colour 3", // 7
- "Horizontal", // 8
- "Vertical", // 9
- "Stereo Image", // A
- "Sound", // B
- "External", // C
- "Frequency Synthesis", // D
- "Control", // E
- "Data Control" // F
-};
-
-#if 0
-static const char *const vidc20_horz_regnames[] =
-{
- "Horizontal Cycle", // 0x80 HCR
- "Horizontal Sync Width", // 0x81 HSWR
- "Horizontal Border Start", // 0x82 HBSR
- "Horizontal Display Start", // 0x83 HDSR
- "Horizontal Display End", // 0x84 HDER
- "Horizontal Border End", // 0x85 HBER
- "Horizontal Cursor Start", // 0x86 HCSR
- "Horizontal Interlace", // 0x87 HIR
- "Horizontal Counter TEST", // 0x88
- "Horizontal <UNDEFINED>", // 0x89
- "Horizontal <UNDEFINED>", // 0x8a
- "Horizontal <UNDEFINED>", // 0x8b
- "Horizontal All TEST", // 0x8c
- "Horizontal <UNDEFINED>", // 0x8d
- "Horizontal <UNDEFINED>", // 0x8e
- "Horizontal <UNDEFINED>" // 0x8f
-};
-#endif
-
-#define HCR 0
-#define HSWR 1
-#define HBSR 2
-#define HDSR 3
-#define HDER 4
-#define HBER 5
-#define HCSR 6
-#define HIR 7
-
-#if 0
-static const char *const vidc20_vert_regnames[] =
-{
- "Vertical Cycle", // 0x90 VCR
- "Vertical Sync Width", // 0x91 VSWR
- "Vertical Border Start", // 0x92 VBSR
- "Vertical Display Start", // 0x93 VDSR
- "Vertical Display End", // 0x94 VDER
- "Vertical Border End", // 0x95 VBER
- "Vertical Cursor Start", // 0x96 VCSR
- "Vertical Cursor End", // 0x97 VCER
- "Vertical Counter TEST", // 0x98
- "Horizontal <UNDEFINED>", // 0x99
- "Vertical Counter Increment TEST", // 0x9a
- "Horizontal <UNDEFINED>", // 0x9b
- "Vertical All TEST", // 0x9c
- "Horizontal <UNDEFINED>", // 0x9d
- "Horizontal <UNDEFINED>", // 0x9e
- "Horizontal <UNDEFINED>" // 0x9f
-};
-#endif
-
-#define VCR 0
-#define VSWR 1
-#define VBSR 2
-#define VDSR 3
-#define VDER 4
-#define VBER 5
-#define VCSR 6
-#define VCER 7
-
-void riscpc_state::vidc20_dynamic_screen_change()
-{
- /* sanity checks - first pass */
- /*
- total cycles + border start/end
- */
- if(m_vidc20_horz_reg[HCR] && m_vidc20_horz_reg[HBSR] && m_vidc20_horz_reg[HBER] &&
- m_vidc20_vert_reg[VCR] && m_vidc20_vert_reg[VBSR] && m_vidc20_vert_reg[VBER])
- {
- /* sanity checks - second pass */
- /*
- total cycles > border end > border start
- */
- if((m_vidc20_horz_reg[HCR] > m_vidc20_horz_reg[HBER]) &&
- (m_vidc20_horz_reg[HBER] > m_vidc20_horz_reg[HBSR]) &&
- (m_vidc20_vert_reg[VCR] > m_vidc20_vert_reg[VBER]) &&
- (m_vidc20_vert_reg[VBER] > m_vidc20_vert_reg[VBSR]))
- {
- /* finally ready to change the resolution */
- int hblank_period,vblank_period;
- rectangle visarea = m_screen->visible_area();
- hblank_period = (m_vidc20_horz_reg[HCR] & 0x3ffc);
- vblank_period = (m_vidc20_vert_reg[VCR] & 0x3fff);
- /* note that we use the border registers as the visible area */
- visarea.set(
- (m_vidc20_horz_reg[HBSR] & 0x3ffe),
- (m_vidc20_horz_reg[HBER] & 0x3ffe) - 1,
- (m_vidc20_vert_reg[VBSR] & 0x1fff),
- (m_vidc20_vert_reg[VBER] & 0x1fff) - 1);
-
- m_screen->configure(hblank_period, vblank_period, visarea, m_screen->frame_period().attoseconds() );
- logerror("VIDC20: successfully changed the screen to:\n Display Size = %d x %d\n Border Size %d x %d\n Cycle Period %d x %d\n",
- (m_vidc20_horz_reg[HDER]-m_vidc20_horz_reg[HDSR]),(m_vidc20_vert_reg[VDER]-m_vidc20_vert_reg[VDSR]),
- (m_vidc20_horz_reg[HBER]-m_vidc20_horz_reg[HBSR]),(m_vidc20_vert_reg[VBER]-m_vidc20_vert_reg[VBSR]),
- hblank_period,vblank_period);
- }
- }
-}
-
-WRITE32_MEMBER( riscpc_state::a7000_vidc20_w )
-{
- int r,g,b,cursor_index,horz_reg,vert_reg,reg = data >> 28;
-
- switch(reg)
- {
- case 0: // Video Palette
- r = (data & 0x0000ff) >> 0;
- g = (data & 0x00ff00) >> 8;
- b = (data & 0xff0000) >> 16;
-
- m_palette->set_pen_color(m_vidc20_pal_index & 0xff,r,g,b);
-
- /* auto-increment & wrap-around */
- m_vidc20_pal_index++;
- m_vidc20_pal_index &= 0xff;
- break;
-
- case 1: // Video Palette Address
-
- // according to RPCEmu, these mustn't be set
- if (data & 0x0fffff00)
- return;
-
- m_vidc20_pal_index = data & 0xff;
- break;
-
- case 4: // Border Color
- r = (data & 0x0000ff) >> 0;
- g = (data & 0x00ff00) >> 8;
- b = (data & 0xff0000) >> 16;
-
- m_palette->set_pen_color(0x100,r,g,b);
- break;
- case 5: // Cursor Palette Logical Colour n
- case 6:
- case 7:
- cursor_index = 0x100 + reg - 4; // 0x101,0x102 and 0x103 (plus 0x100 of above, 2bpp)
-
- r = (data & 0x0000ff) >> 0;
- g = (data & 0x00ff00) >> 8;
- b = (data & 0xff0000) >> 16;
-
- m_palette->set_pen_color(cursor_index,r,g,b);
- break;
- case 8: // Horizontal
- horz_reg = (data >> 24) & 0xf;
- m_vidc20_horz_reg[horz_reg] = data & 0x3fff;
- if(horz_reg == 0 || horz_reg == 2 || horz_reg == 5)
- vidc20_dynamic_screen_change();
-
- // logerror("VIDC20: %s Register write = %08x (%d)\n",vidc20_horz_regnames[horz_reg],val,val);
- break;
- case 9: // Vertical
- vert_reg = (data >> 24) & 0xf;
- m_vidc20_vert_reg[vert_reg] = data & 0x1fff;
- if(vert_reg == 0 || vert_reg == 2 || vert_reg == 5)
- vidc20_dynamic_screen_change();
-
- if(vert_reg == 4)
- {
- if(m_vidc20_vert_reg[VDER] != 0)
- m_flyback_timer->adjust(m_screen->time_until_pos(m_vidc20_vert_reg[VDER]));
- else
- m_flyback_timer->adjust(attotime::never);
- }
-
- // logerror("VIDC20: %s Register write = %08x (%d)\n",vidc20_vert_regnames[vert_reg],val,val);
-
- break;
- case 0x0e: // Control
- m_vidc20_bpp_mode = (data & 0xe0) >> 5;
- break;
- default: logerror("VIDC20: %s Register write = %08x\n",vidc20_regnames[reg],data & 0xfffffff);
- }
-}
-
-uint32_t riscpc_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- int x_size,y_size,x_start,y_start;
- int x,y,xi;
- uint32_t count;
-
- bitmap.fill(m_palette->pen(0x100), cliprect);
-
- x_size = (m_vidc20_horz_reg[HDER]-m_vidc20_horz_reg[HDSR]);
- y_size = (m_vidc20_vert_reg[VDER]-m_vidc20_vert_reg[VDSR]);
- x_start = m_vidc20_horz_reg[HDSR];
- y_start = m_vidc20_vert_reg[VDSR];
-
- /* check if display is enabled */
- if(x_size <= 0 || y_size <= 0)
- return 0;
-
-// popmessage("%d",m_vidc20_bpp_mode);
-
- count = 0;
-
- switch(m_vidc20_bpp_mode)
- {
- case 0: /* 1 bpp */
- {
- for(y=0;y<y_size;y++)
- {
- for(x=0;x<x_size;x+=32)
- {
- for(xi=0;xi<32;xi++)
- bitmap.pix32(y+y_start, x+xi+x_start) = m_palette->pen((m_vram[count]>>(xi))&1);
-
- count++;
- }
- }
- break;
- }
- case 2: /* 4 bpp */
- {
- for(y=0;y<y_size;y++)
- {
- for(x=0;x<x_size;x+=8)
- {
- for(xi=0;xi<8;xi++)
- bitmap.pix32(y+y_start, x+xi+x_start) = m_palette->pen((m_vram[count]>>(xi*4))&0xf);
-
- count++;
- }
- }
- break;
- }
- #if 0
- case 1: /* 2 bpp */
- {
- for(y=0;y<y_size;y++)
- {
- for(x=0;x<x_size;x+=4)
- {
- for(xi=0;xi<4;xi++)
- bitmap.pix32(y+y_start, x+xi+x_start) = m_palette->pen((vram[count]>>(xi*2))&3);
-
- count++;
- }
- }
- }
- break;
-
- case 3: /* 8 bpp */
- {
- for(y=0;y<y_size;y++)
- {
- for(x=0;x<x_size;x++)
- {
- bitmap.pix32(y+y_start, x+x_start) = m_palette->pen((vram[count])&0xff);
-
- count++;
- }
- }
- }
- break;
- case 4: /* 16 bpp */
- {
- for(y=0;y<y_size;y++)
- {
- for(x=0;x<x_size;x++)
- {
- int r,g,b,pen;
-
- pen = ((vram[count]<<8)|(vram[count+1]))&0xffff;
- r = (pen & 0x000f);
- g = (pen & 0x00f0) >> 4;
- b = (pen & 0x0f00) >> 8;
- r = (r << 4) | (r & 0xf);
- g = (g << 4) | (g & 0xf);
- b = (b << 4) | (b & 0xf);
-
- bitmap.pix32(y+y_start, x+x_start) = b | g << 8 | r << 16;
-
- count+=2;
- }
- }
- }
- break;
- case 6: /* 32 bpp */
- {
- for(y=0;y<y_size;y++)
- {
- for(x=0;x<x_size;x++)
- {
- int r,g,b,pen;
-
- pen = ((vram[count]<<24)|(vram[count+1]<<16)|(vram[count+2]<<8)|(vram[count+3]<<0));
- r = (pen & 0x0000ff);
- g = (pen & 0x00ff00) >> 8;
- b = (pen & 0xff0000) >> 16;
-
- bitmap.pix32(y+y_start, x+x_start) = b | g << 8 | r << 16;
-
- count+=4;
- }
- }
- }
- break;
- #endif
- default:
- fatalerror("VIDC20 %08x BPP mode not supported\n",m_vidc20_bpp_mode);
- break;
- }
-
- return 0;
-}
-
-/*
-*
-* IOMD / ARM7500 / ARM7500FE chip emulation
-*
-*/
-
-/* TODO: some of these registers are actually ARM7500 specific */
-static const char *const iomd_regnames[] =
-{
- "I/O Control", // 0x000 IOCR
- "Keyboard Data", // 0x004 KBDDAT
- "Keyboard Control", // 0x008 KBDCR
- "General Purpose I/O Lines", // 0x00c IOLINES
- "IRQA Status", // 0x010 IRQSTA
- "IRQA Request/clear", // 0x014 IRQRQA
- "IRQA Mask", // 0x018 IRQMSKA
- "Enter SUSPEND Mode", // 0x01c SUSMODE
- "IRQB Status", // 0x020 IRQSTB
- "IRQB Request/clear", // 0x024 IRQRQB
- "IRQB Mask", // 0x028 IRQMSKB
- "Enter STOP Mode", // 0x02c STOPMODE
- "FIQ Status", // 0x030 FIQST
- "FIQ Request/clear", // 0x034 FIQRQ
- "FIQ Mask", // 0x038 FIQMSK
- "Clock divider control", // 0x03c CLKCTL
- "Timer 0 Low Bits", // 0x040 T0LOW
- "Timer 0 High Bits", // 0x044 T0HIGH
- "Timer 0 Go Command", // 0x048 T0GO
- "Timer 0 Latch Command", // 0x04c T0LATCH
- "Timer 1 Low Bits", // 0x050 T1LOW
- "Timer 1 High Bits", // 0x054 T1HIGH
- "Timer 1 Go Command", // 0x058 T1GO
- "Timer 1 Latch Command", // 0x05c T1LATCH
- "IRQC Status", // 0x060 IRQSTC
- "IRQC Request/clear", // 0x064 IRQRQC
- "IRQC Mask", // 0x068 IRQMSKC
- "LCD and IIS Control Bits", // 0x06c VIDIMUX
- "IRQD Status", // 0x070 IRQSTD
- "IRQD Request/clear", // 0x074 IRQRQD
- "IRQD Mask", // 0x078 IRQMSKD
- "<RESERVED>", // 0x07c
- "ROM Control Bank 0", // 0x080 ROMCR0
- "ROM Control Bank 1", // 0x084 ROMCR1
- "DRAM Control (IOMD)", // 0x088 DRAMCR
- "VRAM and Refresh Control", // 0x08c VREFCR
- "Flyback Line Size", // 0x090 FSIZE
- "Chip ID no. Low Byte", // 0x094 ID0
- "Chip ID no. High Byte", // 0x098 ID1
- "Chip Version Number", // 0x09c VERSION
- "Mouse X Position", // 0x0a0 MOUSEX
- "Mouse Y Position", // 0x0a4 MOUSEY
- "Mouse Data", // 0x0a8 MSEDAT
- "Mouse Control", // 0x0ac MSECR
- "<RESERVED>", // 0x0b0
- "<RESERVED>", // 0x0b4
- "<RESERVED>", // 0x0b8
- "<RESERVED>", // 0x0bc
- "DACK Timing Control", // 0x0c0 DMATCR
- "I/O Timing Control", // 0x0c4 IOTCR
- "Expansion Card Timing", // 0x0c8 ECTCR
- "DMA External Control", // 0x0cc DMAEXT (IOMD) / ASTCR (ARM7500)
- "DRAM Width Control", // 0x0d0 DRAMWID
- "Force CAS/RAS Lines Low", // 0x0d4 SELFREF
- "<RESERVED>", // 0x0d8
- "<RESERVED>", // 0x0dc
- "A to D IRQ Control", // 0x0e0 ATODICR
- "A to D IRQ Status", // 0x0e4 ATODCC
- "A to D IRQ Converter Control", // 0x0e8 ATODICR
- "A to D IRQ Counter 1", // 0x0ec ATODCNT1
- "A to D IRQ Counter 2", // 0x0f0 ATODCNT2
- "A to D IRQ Counter 3", // 0x0f4 ATODCNT3
- "A to D IRQ Counter 4", // 0x0f8 ATODCNT4
- "<RESERVED>", // 0x0fc
- "I/O DMA 0 CurA", // 0x100 IO0CURA
- "I/O DMA 0 EndA", // 0x104 IO0ENDA
- "I/O DMA 0 CurB", // 0x108 IO0CURB
- "I/O DMA 0 EndB", // 0x10c IO0ENDB
- "I/O DMA 0 Control", // 0x110 IO0CR
- "I/O DMA 0 Status", // 0x114 IO0ST
- "<RESERVED>", // 0x118
- "<RESERVED>", // 0x11c
- "I/O DMA 1 CurA", // 0x120 IO1CURA
- "I/O DMA 1 EndA", // 0x124 IO1ENDA
- "I/O DMA 1 CurB", // 0x128 IO1CURB
- "I/O DMA 1 EndB", // 0x12c IO1ENDB
- "I/O DMA 1 Control", // 0x130 IO1CR
- "I/O DMA 1 Status", // 0x134 IO1ST
- "<RESERVED>", // 0x138
- "<RESERVED>", // 0x13c
- "I/O DMA 2 CurA", // 0x140 IO2CURA
- "I/O DMA 2 EndA", // 0x144 IO2ENDA
- "I/O DMA 2 CurB", // 0x148 IO2CURB
- "I/O DMA 2 EndB", // 0x14c IO2ENDB
- "I/O DMA 2 Control", // 0x150 IO2CR
- "I/O DMA 2 Status", // 0x154 IO2ST
- "<RESERVED>", // 0x158
- "<RESERVED>", // 0x15c
- "I/O DMA 3 CurA", // 0x160 IO3CURA
- "I/O DMA 3 EndA", // 0x164 IO3ENDA
- "I/O DMA 3 CurB", // 0x168 IO3CURB
- "I/O DMA 3 EndB", // 0x16c IO3ENDB
- "I/O DMA 3 Control", // 0x170 IO3CR
- "I/O DMA 3 Status", // 0x174 IO3ST
- "<RESERVED>", // 0x178
- "<RESERVED>", // 0x17c
- "Sound DMA 0 CurA", // 0x180 SD0CURA
- "Sound DMA 0 EndA", // 0x184 SD0ENDA
- "Sound DMA 0 CurB", // 0x188 SD0CURB
- "Sound DMA 0 EndB", // 0x18c SD0ENDB
- "Sound DMA 0 Control", // 0x190 SD0CR
- "Sound DMA 0 Status", // 0x194 SD0ST
- "<RESERVED>", // 0x198
- "<RESERVED>", // 0x19c
- "Sound DMA 1 CurA", // 0x1a0 SD1CURA
- "Sound DMA 1 EndA", // 0x1a4 SD1ENDA
- "Sound DMA 1 CurB", // 0x1a8 SD1CURB
- "Sound DMA 1 EndB", // 0x1ac SD1ENDB
- "Sound DMA 1 Control", // 0x1b0 SD1CR
- "Sound DMA 1 Status", // 0x1b4 SD1ST
- "<RESERVED>", // 0x1b8
- "<RESERVED>", // 0x1bc
- "Cursor DMA Current", // 0x1c0 CURSCUR
- "Cursor DMA Init", // 0x1c4 CURSINIT
- "Duplex LCD Current B", // 0x1c8 VIDCURB
- "<RESERVED>", // 0x1cc
- "Video DMA Current", // 0x1d0 VIDCUR
- "Video DMA End", // 0x1d4 VIDEND
- "Video DMA Start", // 0x1d8 VIDSTART
- "Video DMA Init", // 0x1dc VIDINIT
- "Video DMA Control", // 0x1e0 VIDCR
- "<RESERVED>", // 0x1e4
- "Duplex LCD Init B", // 0x1e8 VIDINITB
- "<RESERVED>", // 0x1ec
- "DMA IRQ Status", // 0x1f0 DMAST
- "DMA IRQ Request", // 0x1f4 DMARQ
- "DMA IRQ Mask", // 0x1f8 DMAMSK
- "<RESERVED>" // 0x1fc
+
+ bool m_i2cmem_clock;
+ DECLARE_READ_LINE_MEMBER(iocr_od0_r);
+ DECLARE_READ_LINE_MEMBER(iocr_od1_r);
+ DECLARE_WRITE_LINE_MEMBER(iocr_od0_w);
+ DECLARE_WRITE_LINE_MEMBER(iocr_od1_w);
};
-#define IOMD_IOCR 0x000/4
-#define IOMD_KBDDAT 0x004/4
-#define IOMD_KBDCR 0x008/4
-
-#define IOMD_IRQSTA 0x010/4
-#define IOMD_IRQRQA 0x014/4
-#define IOMD_IRQMSKA 0x018/4
-
-#define IOMD_IRQSTB 0x020/4
-#define IOMD_IRQRQB 0x024/4
-#define IOMD_IRQMSKB 0x028/4
-
-#define IOMD_T0LOW 0x040/4
-#define IOMD_T0HIGH 0x044/4
-#define IOMD_T0GO 0x048/4
-#define IOMD_T0LATCH 0x04c/4
-
-#define IOMD_T1LOW 0x050/4
-#define IOMD_T1HIGH 0x054/4
-#define IOMD_T1GO 0x058/4
-#define IOMD_T1LATCH 0x05c/4
-
-#define IOMD_ID0 0x094/4
-#define IOMD_ID1 0x098/4
-#define IOMD_VERSION 0x09c/4
-
-#define IOMD_VIDCUR 0x1d0/4
-#define IOMD_VIDEND 0x1d4/4
-#define IOMD_VIDSTART 0x1d8/4
-#define IOMD_VIDINIT 0x1dc/4
-#define IOMD_VIDCR 0x1e0/4
-
-#define IOMD_DMARQ 0x1f4/4
-
-void riscpc_state::update_irq()
-{
- if (m_IRQ_status_A & m_IRQ_mask_A)
- m_maincpu->pulse_input_line(ARM7_IRQ_LINE, m_maincpu->minimum_quantum_time());
- if (m_IRQ_status_B & m_IRQ_mask_B)
- m_maincpu->pulse_input_line(ARM7_IRQ_LINE, m_maincpu->minimum_quantum_time());
-}
-
-void riscpc_state::fire_iomd_timer(int timer)
+READ_LINE_MEMBER(riscpc_state::iocr_od1_r)
{
- int timer_count = m_timer_counter[timer];
- int val = timer_count / 2; // correct?
-
- if(val==0)
- m_IOMD_timer[timer]->adjust(attotime::never);
- else
- m_IOMD_timer[timer]->adjust(attotime::from_usec(val), 0, attotime::from_usec(val));
+ // TODO: presuming same as Acorn Archimedes, where i2c clock can be readback
+ return (m_i2cmem_clock == true) ? 1 : 0;
}
-TIMER_CALLBACK_MEMBER(riscpc_state::IOMD_timer0_callback)
+READ_LINE_MEMBER(riscpc_state::iocr_od0_r)
{
- m_IRQ_status_A|=0x20;
- update_irq();
-}
-
-TIMER_CALLBACK_MEMBER(riscpc_state::IOMD_timer1_callback)
-{
- m_IRQ_status_A|=0x40;
- update_irq();
-}
-
-TIMER_CALLBACK_MEMBER(riscpc_state::flyback_timer_callback)
-{
- m_IRQ_status_A|=0x08;
- update_irq();
-
- // for convenience lets just implement the video DMA transfer here
- // the actual transfer probably works per scanline once enabled.
- if(m_viddma_status & 0x20)
- viddma_transfer_start();
-
- m_flyback_timer->adjust(m_screen->time_until_pos(m_vidc20_vert_reg[VDER]));
+ return (m_i2cmem->read_sda() ? 1 : 0); //eeprom read
}
-void riscpc_state::viddma_transfer_start()
+WRITE_LINE_MEMBER(riscpc_state::iocr_od0_w)
{
- address_space &mem = m_maincpu->space(AS_PROGRAM);
- uint32_t src = m_viddma_addr_init;
- uint32_t dst = 0;
- uint32_t size = m_viddma_addr_end;
- uint32_t dma_index;
-
- /* TODO: this should actually be a qword transfer */
- for(dma_index = 0;dma_index < size;dma_index+=4)
- {
- m_vram[dst] = mem.read_dword(src);
-
- src+=4;
- // TODO: honor boundary
- dst++;
- }
-}
-
-READ32_MEMBER( riscpc_state::a7000_iomd_r )
-{
-// if(offset != IOMD_KBDCR)
-// logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4);
-
-
- switch(offset)
- {
- case IOMD_IOCR:
- {
- uint8_t flyback;
- int vert_pos;
-
- vert_pos = m_screen->vpos();
- flyback = (vert_pos <= m_vidc20_vert_reg[VDSR] || vert_pos >= m_vidc20_vert_reg[VDER]) ? 0x80 : 0x00;
-
- return flyback | (m_IOMD_IO_ctrl & 0x7c) | 0x34 | (m_i2c_clk << 1) | (m_i2cmem->read_sda() ? 1 : 0);
- }
- case IOMD_KBDDAT: return m_kbdc->data_r();
- case IOMD_KBDCR: return m_kbdc->status_r();
-
- /*
- 1--- ---- always high (force)
- -x-- ---- Timer 1
- --x- ---- Timer 0
- ---x ---- Power On Reset
- ---- x--- Flyback
- ---- -x-- nINT1
- ---- --0- always low
- ---- ---x INT2
- */
- case IOMD_IRQSTA: return (m_IRQ_status_A & 0x7d) | 0x80;
- case IOMD_IRQRQA: return (m_IRQ_status_A & m_IRQ_mask_A);
- case IOMD_IRQMSKA: return m_IRQ_mask_A;
-
- case IOMD_IRQSTB: return m_IRQ_status_B;
- case IOMD_IRQRQB: return (m_IRQ_status_B & m_IRQ_mask_B);
- case IOMD_IRQMSKB: return m_IRQ_mask_B;
-
- case IOMD_T0LOW: return m_timer_out[0] & 0xff;
- case IOMD_T0HIGH: return (m_timer_out[0] >> 8) & 0xff;
-
- case IOMD_T1LOW: return m_timer_out[1] & 0xff;
- case IOMD_T1HIGH: return (m_timer_out[1] >> 8) & 0xff;
-
- case IOMD_ID0: return m_io_id & 0xff; // IOMD ID low
- case IOMD_ID1: return (m_io_id >> 8) & 0xff; // IOMD ID high
- case IOMD_VERSION: return 0;
-
- case IOMD_VIDEND: return m_viddma_addr_end & 0x00fffff8; //bits 31:24 undefined
- case IOMD_VIDSTART: return m_viddma_addr_start & 0x1ffffff8; //bits 31, 30, 29 undefined
- case IOMD_VIDINIT: return m_viddma_addr_init & 0x1ffffff8;
- case IOMD_VIDCR: return (m_viddma_status & 0xa0) | 0x50; //bit 6 = DRAM mode, bit 4 = QWORD transfer
-
- default: logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4); break;
- }
-
- return 0;
+ m_i2cmem->write_sda(state == true ? 1 : 0);
}
-WRITE32_MEMBER( riscpc_state::a7000_iomd_w )
+WRITE_LINE_MEMBER(riscpc_state::iocr_od1_w)
{
-// logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data);
-
- switch(offset)
- {
- case IOMD_IOCR:
- m_IOMD_IO_ctrl = data & 0x7c;
- m_i2cmem->write_sda(data & 0x01);
- m_i2c_clk = (data & 2) >> 1;
- m_i2cmem->write_scl(m_i2c_clk);
- break;
-
- case IOMD_KBDDAT: m_kbdc->data_w(data); break;
- case IOMD_KBDCR: m_kbdc->command_w(data);
- //m_IRQ_status_B |= 0x40;
- //machine().debug_break();
- //update_irq();
- break;
-
- case IOMD_IRQRQA:
- m_IRQ_status_A &= ~data;
- m_IRQ_status_A |= 0x80;
- update_irq();
- break;
-
- case IOMD_IRQMSKA:
- m_IRQ_mask_A = data;
- update_irq();
- break;
-
- case IOMD_IRQRQB:
- m_IRQ_status_B &= ~data;
- update_irq();
- break;
-
- case IOMD_IRQMSKB:
- m_IRQ_mask_B = data;
- update_irq();
- break;
-
- case IOMD_T0LOW: m_timer_in[0] = (m_timer_in[0] & 0xff00) | (data & 0xff); break;
- case IOMD_T0HIGH: m_timer_in[0] = (m_timer_in[0] & 0x00ff) | ((data & 0xff) << 8); break;
- case IOMD_T0GO:
- m_timer_counter[0] = m_timer_in[0];
- fire_iomd_timer(0);
- break;
- case IOMD_T0LATCH:
- {
- m_t0readinc^=1;
- m_timer_out[0] = m_timer_counter[0];
- if(m_t0readinc)
- {
- m_timer_counter[0]--;
- if(m_timer_counter[0] < 0)
- m_timer_counter[0]+= m_timer_in[0];
- }
- }
- break;
-
- case IOMD_T1LOW: m_timer_in[1] = (m_timer_in[1] & 0xff00) | (data & 0xff); break;
- case IOMD_T1HIGH: m_timer_in[1] = (m_timer_in[1] & 0x00ff) | ((data & 0xff) << 8); break;
- case IOMD_T1GO:
- m_timer_counter[1] = m_timer_in[1];
- fire_iomd_timer(1);
- break;
- case IOMD_T1LATCH:
- {
- m_t1readinc^=1;
- m_timer_out[1] = m_timer_counter[1];
- if(m_t1readinc)
- {
- m_timer_counter[1]--;
- if(m_timer_counter[1] < 0)
- m_timer_counter[1]+= m_timer_in[1];
- }
- }
- break;
-
- case IOMD_VIDEND: m_viddma_addr_end = data & 0x00fffff8; //bits 31:24 unused
- break;
- case IOMD_VIDSTART: m_viddma_addr_start = data & 0x1ffffff8; //bits 31, 30, 29 unused
- break;
- case IOMD_VIDINIT: m_viddma_addr_init = data & 0x1ffffff8;
- break;
- case IOMD_VIDCR:
- m_viddma_status = data & 0xa0; if(data & 0x20) { viddma_transfer_start(); }
- break;
-
-
- default: logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data);
- }
+ m_i2cmem_clock = state;
+ m_i2cmem->write_scl(state == true ? 1 : 0);
}
void riscpc_state::a7000_map(address_map &map)
@@ -850,16 +104,17 @@ void riscpc_state::a7000_map(address_map &map)
//
// map(0x02000000, 0x027fffff).mirror(0x00800000).ram(); // VRAM, not installed on A7000 models
// I/O 03000000 - 033fffff
-// map(0x03010000, 0x03011fff) //Super IO
-// map(0x03012000, 0x03029fff) //FDC
-// map(0x0302b000, 0x0302bfff) //Network podule
-// map(0x03040000, 0x0304ffff) //podule space 0,1,2,3
-// map(0x03070000, 0x0307ffff) //podule space 4,5,6,7
- map(0x03200000, 0x032001ff).rw(FUNC(riscpc_state::a7000_iomd_r), FUNC(riscpc_state::a7000_iomd_w)); //IOMD Registers //mirrored at 0x03000000-0x1ff?
+// AM_RANGE(0x03010000, 0x03011fff) //Super IO
+// AM_RANGE(0x03012000, 0x03029fff) //FDC
+// AM_RANGE(0x0302b000, 0x0302bfff) //Network podule
+// AM_RANGE(0x03040000, 0x0304ffff) //podule space 0,1,2,3
+// AM_RANGE(0x03070000, 0x0307ffff) //podule space 4,5,6,7
+ map(0x03200000, 0x032001ff).m(m_iomd, FUNC(arm7500fe_iomd_device::map));
map(0x03310000, 0x03310003).portr("MOUSE");
- map(0x03400000, 0x037fffff).w(FUNC(riscpc_state::a7000_vidc20_w));
-// map(0x08000000, 0x08ffffff).mirror(0x07000000); //EASI space
+ map(0x03400000, 0x037fffff).w(m_vidc, FUNC(arm_vidc20_device::write));
+// AM_RANGE(0x08000000, 0x08ffffff) AM_MIRROR(0x07000000) //EASI space
+
map(0x10000000, 0x13ffffff).ram(); //SIMM 0 bank 0
map(0x14000000, 0x17ffffff).ram(); //SIMM 0 bank 1
// map(0x18000000, 0x18ffffff).mirror(0x03000000).ram(); //SIMM 1 bank 0
@@ -898,44 +153,14 @@ INPUT_PORTS_END
void riscpc_state::machine_start()
{
- m_IOMD_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(riscpc_state::IOMD_timer0_callback),this));
- m_IOMD_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(riscpc_state::IOMD_timer1_callback),this));
- m_flyback_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(riscpc_state::flyback_timer_callback),this));
-
- m_io_id = 0xd4e7;
+ // ...
}
void riscpc_state::machine_reset()
{
- m_IOMD_IO_ctrl = 0x08 | 0x34; //bit 0,1 and 3 set high on reset plus 2,4,5 always high
- // TODO: jumps to EASI space at $0c0016xx with this on!?
-// m_IRQ_status_A = 0x10; // set POR bit ON
- m_IRQ_mask_A = 0x00;
-
- m_IOMD_keyb_ctrl = 0x00;
- m_IOMD_timer[0]->adjust(attotime::never);
- m_IOMD_timer[1]->adjust(attotime::never);
- m_flyback_timer->adjust(attotime::never);
}
-WRITE_LINE_MEMBER(riscpc_state::keyboard_reset)
-{
- printf("RST %d\n",state);
-}
-
-WRITE_LINE_MEMBER(riscpc_state::keyboard_interrupt)
-{
- printf("IRQ %d\n",state);
- if (!state)
- return;
-
-// machine().debug_break();
- m_IRQ_status_B|=0x80;
- update_irq();
-}
-
-
void riscpc_state::base_config(machine_config &config)
{
I2C_24C02(config, m_i2cmem);
@@ -958,67 +183,95 @@ void riscpc_state::base_config(machine_config &config)
// aux.set_pc_kbdc_slot(&aux_con);
PS2_KEYBOARD_CONTROLLER(config, m_kbdc, 12_MHz_XTAL);
- m_kbdc->hot_res().set(FUNC(riscpc_state::keyboard_reset));
+ m_kbdc->hot_res().set(m_iomd, FUNC(arm_iomd_device::keyboard_reset));
m_kbdc->kbd_clk().set(kbd_con, FUNC(pc_kbdc_device::clock_write_from_mb));
m_kbdc->kbd_data().set(kbd_con, FUNC(pc_kbdc_device::data_write_from_mb));
- m_kbdc->kbd_irq().set(FUNC(riscpc_state::keyboard_interrupt));
+ m_kbdc->kbd_irq().set(m_iomd, FUNC(arm_iomd_device::keyboard_irq));
// m_kbdc->aux_clk().set(aux_con, FUNC(pc_kbdc_device::clock_write_from_mb));
// m_kbdc->aux_data().set(aux_con, FUNC(pc_kbdc_device::data_write_from_mb));
// m_kbdc->aux_irq().set(FUNC(riscpc_state::keyboard_interrupt));
/* video hardware */
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
- m_screen->set_refresh_hz(60);
- m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
- m_screen->set_size(1900, 1080); //max available size
- m_screen->set_visarea(0, 1900-1, 0, 1080-1);
- m_screen->set_screen_update(FUNC(riscpc_state::screen_update));
- PALETTE(config, m_palette).set_entries(0x200);
+
+ ARM_VIDC20(config, m_vidc, 24_MHz_XTAL);
+ m_vidc->set_screen("screen");
+ m_vidc->vblank().set(m_iomd, FUNC(arm_iomd_device::vblank_irq));
+ m_vidc->sound_drq().set(m_iomd, FUNC(arm_iomd_device::sound_drq));
+
+ m_iomd->set_host_cpu_tag(m_maincpu);
+ m_iomd->set_vidc_tag(m_vidc);
+ m_iomd->set_kbdc_tag(m_kbdc);
+ m_iomd->iocr_read_od<0>().set(FUNC(riscpc_state::iocr_od0_r));
+ m_iomd->iocr_read_od<1>().set(FUNC(riscpc_state::iocr_od1_r));
+ m_iomd->iocr_write_od<0>().set(FUNC(riscpc_state::iocr_od0_w));
+ m_iomd->iocr_write_od<1>().set(FUNC(riscpc_state::iocr_od1_w));
}
void riscpc_state::rpc600(machine_config &config)
{
- /* Basic machine hardware */
- ARM7(config, m_maincpu, 60_MHz_XTAL/2); // ARM610
+ constexpr XTAL cpuxtal(60_MHz_XTAL/2);
+
+ ARM7(config, m_maincpu, cpuxtal); // really ARM610
m_maincpu->set_addrmap(AS_PROGRAM, &riscpc_state::riscpc_map);
+
+ ARM7500FE_IOMD(config, m_iomd, cpuxtal);
base_config(config);
}
void riscpc_state::rpc700(machine_config &config)
{
- /* Basic machine hardware */
- ARM710A(config, m_maincpu, 80_MHz_XTAL/2); // ARM710
+ constexpr XTAL cpuxtal(80_MHz_XTAL/2);
+ ARM710A(config, m_maincpu, cpuxtal);
m_maincpu->set_addrmap(AS_PROGRAM, &riscpc_state::riscpc_map);
+
+ ARM7500FE_IOMD(config, m_iomd, cpuxtal);
base_config(config);
}
void riscpc_state::a7000(machine_config &config)
{
- /* Basic machine hardware */
- ARM7(config, m_maincpu, XTAL(32'000'000)); // ARM7500
+ constexpr XTAL cpuxtal(32'000'000);
+
+ ARM7500(config, m_maincpu, cpuxtal);
m_maincpu->set_addrmap(AS_PROGRAM, &riscpc_state::a7000_map);
+
+ ARM7500FE_IOMD(config, m_iomd, cpuxtal);
base_config(config);
}
void riscpc_state::a7000p(machine_config &config)
{
- a7000(config);
- m_maincpu->set_clock(XTAL(48'000'000)); // ARM7500FE
+ constexpr XTAL cpuxtal(48'000'000);
+
+ ARM7500(config, m_maincpu, cpuxtal); // really ARM7500FE
+ m_maincpu->set_addrmap(AS_PROGRAM, &riscpc_state::a7000_map);
+
+ ARM7500FE_IOMD(config, m_iomd, cpuxtal);
+ base_config(config);
}
void riscpc_state::sarpc(machine_config &config)
{
- /* Basic machine hardware */
- SA1110(config, m_maincpu, 202000000); // StrongARM
+ // TODO: ranges from 160 to 233 MHz
+ constexpr XTAL cpuxtal(200'000'000);
+
+ SA1110(config, m_maincpu, cpuxtal); // StrongARM
m_maincpu->set_addrmap(AS_PROGRAM, &riscpc_state::riscpc_map);
+
+ ARM7500FE_IOMD(config, m_iomd, cpuxtal);
base_config(config);
}
void riscpc_state::sarpc_j233(machine_config &config)
{
- /* Basic machine hardware */
- SA1110(config, m_maincpu, 233000000); // StrongARM
+ // TODO: 233 MHz, unsupported by xtal module
+ constexpr XTAL cpuxtal(200'000'000);
+
+ SA1110(config, m_maincpu, cpuxtal); // StrongARM
m_maincpu->set_addrmap(AS_PROGRAM, &riscpc_state::riscpc_map);
+
+ ARM7500FE_IOMD(config, m_iomd, cpuxtal);
base_config(config);
}
diff --git a/src/mame/drivers/ssfindo.cpp b/src/mame/drivers/ssfindo.cpp
index 4bc633cb729..26a14c43de2 100644
--- a/src/mame/drivers/ssfindo.cpp
+++ b/src/mame/drivers/ssfindo.cpp
@@ -12,7 +12,7 @@
Tomasz Slanina analog[at]op.pl
TODO:
- - move PS7500 stuff to machine/ps7500.c
+ - Correct IOMD type (CL-PS7500 -> ARM7500FE?)
- 24c01 eeprom (IOLINES)
- timing
- unknown reads/writes
@@ -128,136 +128,48 @@ Notes:
#include "cpu/arm7/arm7.h"
#include "cpu/arm7/arm7core.h"
#include "machine/i2cmem.h"
+#include "machine/acorn_vidc.h"
+#include "machine/arm_iomd.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
-enum
-{
- IOCR=0,
- KBDDAT,
- KBDCR,
- IOLINES,
- IRQSTA,
- IRQRQA,
- IRQMSKA,
- SUSMODE,
- IRQSTB,
- IRQRQB,
- IRQMSKB,
- STOPMODE,
- FIQST,
- FIQRQ,
- FIQMSK,
- CLKCTL,
- T0low,
- T0high,
- T0GO,
- T0LAT,
- T1low,
- T1high,
- T1GO,
- T1LAT,
- IRQSTC,
- IRQRQC,
- IRQMSKC,
- VIDMUX,
- IRQSTD,
- IRQRQD,
- IRQMSKD,
-
- ROMCR0=32,
- ROMCR1,
-
- REFCR=35,
-
- ID0=37,
- ID1,
- VERSION,
-
- MSEDAT=42,
- MSECR,
-
- IOTCR=49,
- ECTCR,
- ASTCR,
- DRAMCR,
- SELREF,
-
- ATODICR=56,
- ATODSR,
- ATODCC,
- ATODCNT1,
- ATODCNT2,
- ATODCNT3,
- ATODCNT4,
-
- SD0CURA=96,
- SD0ENDA,
- SD0CURB,
- SD0ENDB,
- SD0CR,
- SD0ST,
-
- CURSCUR=112,
- CURSINIT,
- VIDCURB,
-
- VIDCURA=116,
- VIDEND,
- VIDSTART,
- VIDINITA,
- VIDCR,
-
- VIDINITB=122,
-
- DMAST=124,
- DMARQ,
- DMASK,
- MAXIO=128
-};
-
-
class ssfindo_state : public driver_device
{
public:
ssfindo_state(const machine_config &mconfig, device_type type, const char *tag)
- : driver_device(mconfig, type, tag),
- m_maincpu(*this, "maincpu"),
- m_palette(*this, "palette"),
- m_i2cmem(*this, "i2cmem"),
- m_vram(*this, "vram"),
- m_flashrom(*this, "flash"),
- m_io_ps7500(*this, "PS7500") { }
+ : driver_device(mconfig, type, tag)
+ , m_maincpu(*this, "maincpu")
+ , m_vidc(*this, "vidc")
+ , m_iomd(*this, "iomd")
+ , m_i2cmem(*this, "i2cmem")
+ , m_flashrom(*this, "flash")
+ { }
void ssfindo(machine_config &config);
void ppcar(machine_config &config);
- void tetfight(machine_config &config);
void init_ssfindo();
void init_ppcar();
- void init_tetfight();
-private:
+protected:
required_device<cpu_device> m_maincpu;
- required_device<palette_device> m_palette;
+ required_device<arm_vidc20_device> m_vidc;
+ required_device<arm7500fe_iomd_device> m_iomd;
optional_device<i2cmem_device> m_i2cmem;
-
- required_shared_ptr<uint32_t> m_vram;
-
required_region_ptr<uint16_t> m_flashrom;
+
+ void init_common();
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
- required_ioport m_io_ps7500;
+ typedef void (ssfindo_state::*speedup_func)();
+ speedup_func m_speedup;
- // driver init configuration
uint32_t m_flashType;
- int m_iocr_hack;
- // common
- uint32_t m_PS7500_IO[MAXIO];
- uint32_t m_PS7500_FIFO[256];
- emu_timer *m_PS7500timer0;
- emu_timer *m_PS7500timer1;
+ bool m_i2cmem_clock;
+private:
// ssfindo and ppcar
uint32_t m_flashAdr;
@@ -265,11 +177,6 @@ private:
uint32_t m_adrLatch;
uint32_t m_flashN;
- // common
- DECLARE_WRITE32_MEMBER(FIFO_w);
- DECLARE_READ32_MEMBER(PS7500_IO_r);
- DECLARE_WRITE32_MEMBER(PS7500_IO_w);
-
// ssfindo and ppcar
DECLARE_READ32_MEMBER(io_r);
DECLARE_WRITE32_MEMBER(io_w);
@@ -282,125 +189,94 @@ private:
// ppcar
DECLARE_READ32_MEMBER(randomized_r);
- // tetfight
- DECLARE_READ32_MEMBER(tetfight_unk_r);
- DECLARE_WRITE32_MEMBER(tetfight_unk_w);
-
- void init_common();
- virtual void machine_reset() override;
-
- uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
-
- INTERRUPT_GEN_MEMBER(interrupt);
- TIMER_CALLBACK_MEMBER(PS7500_Timer0_callback);
- TIMER_CALLBACK_MEMBER(PS7500_Timer1_callback);
-
- typedef void (ssfindo_state::*speedup_func)();
- speedup_func m_speedup;
-
- void PS7500_startTimer0();
- void PS7500_startTimer1();
- void PS7500_reset();
void ssfindo_speedups();
void ppcar_speedups();
void ppcar_map(address_map &map);
void ssfindo_map(address_map &map);
- void tetfight_map(address_map &map);
+
+ DECLARE_READ8_MEMBER(iolines_r);
+ DECLARE_WRITE8_MEMBER(iolines_w);
+ bool m_flash_bank_select;
};
-
-uint32_t ssfindo_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+class tetfight_state : public ssfindo_state
{
- int s,x,y;
+public:
+ tetfight_state(const machine_config &mconfig, device_type type, const char *tag)
+ : ssfindo_state(mconfig, type, tag)
+ {}
- if( m_PS7500_IO[VIDCR]&0x20) //video DMA enabled
- {
- s=( (m_PS7500_IO[VIDINITA]&0x1fffffff)-0x10000000)/4;
-
- if(s>=0 && s<(0x10000000/4))
- {
- for(y=0;y<256;y++)
- for(x=0;x<320;x+=4)
- {
- bitmap.pix16(y, x+0) = m_vram[s]&0xff;
- bitmap.pix16(y, x+1) = (m_vram[s]>>8)&0xff;
- bitmap.pix16(y, x+2) = (m_vram[s]>>16)&0xff;
- bitmap.pix16(y, x+3) = (m_vram[s]>>24)&0xff;
- s++;
- }
- }
- }
+ void init_tetfight();
+ void tetfight(machine_config &config);
- return 0;
-}
+protected:
-WRITE32_MEMBER(ssfindo_state::FIFO_w)
-{
- m_PS7500_FIFO[data>>28]=data;
+private:
+ bool m_i2cdata_hack;
- if(!(data>>28))
- {
- m_palette->set_pen_color(m_PS7500_FIFO[1]&0xff, data&0xff,(data>>8)&0xff,(data>>16)&0xff);
- m_PS7500_FIFO[1]++; //autoinc
- }
-}
-TIMER_CALLBACK_MEMBER(ssfindo_state::PS7500_Timer0_callback)
+ void tetfight_map(address_map &map);
+
+ DECLARE_READ_LINE_MEMBER(iocr_od0_r);
+ DECLARE_READ_LINE_MEMBER(iocr_od1_r);
+ DECLARE_WRITE_LINE_MEMBER(iocr_od0_w);
+ DECLARE_WRITE_LINE_MEMBER(iocr_od1_w);
+ DECLARE_READ32_MEMBER(tetfight_unk_r);
+ DECLARE_WRITE32_MEMBER(tetfight_unk_w);
+};
+
+//TODO: eeprom 24c01 & 24c02
+// TODO: untangle, kill hacks
+READ8_MEMBER(ssfindo_state::iolines_r)
{
- m_PS7500_IO[IRQSTA]|=0x20;
- if(m_PS7500_IO[IRQMSKA]&0x20)
- {
- m_maincpu->pulse_input_line(ARM7_IRQ_LINE, m_maincpu->minimum_quantum_time());
- }
+ if(m_flashType == 1)
+ return 0;
+ else
+ return machine().rand();
}
-void ssfindo_state::PS7500_startTimer0()
+WRITE8_MEMBER(ssfindo_state::iolines_w)
{
- int val=((m_PS7500_IO[T0low]&0xff)|((m_PS7500_IO[T0high]&0xff)<<8))>>1;
+ if(data&0xc0)
+ m_adrLatch=0;
- if(val==0)
- m_PS7500timer0->adjust(attotime::never);
- else
- m_PS7500timer0->adjust(attotime::from_usec(val ), 0, attotime::from_usec(val ));
+ if(m_maincpu->pc() == 0xbac0 && m_flashType == 1)
+ m_flashN=data&1;
+
+ m_flash_bank_select = BIT(data, 0);
}
-TIMER_CALLBACK_MEMBER(ssfindo_state::PS7500_Timer1_callback)
+// inverted compared to riscpc.cpp
+// TODO: simplify hookup over i2cmem having AND 1 on state for a writeline (?)
+READ_LINE_MEMBER(tetfight_state::iocr_od1_r)
{
- m_PS7500_IO[IRQSTA]|=0x40;
- if(m_PS7500_IO[IRQMSKA]&0x40)
- {
- m_maincpu->pulse_input_line(ARM7_IRQ_LINE, m_maincpu->minimum_quantum_time());
- }
+ // TODO: completely get rid of this speedup fn or move anywhere else
+ //if (m_speedup) (this->*m_speedup)();
+ return (m_i2cmem->read_sda() ? 1 : 0); //eeprom read
}
-void ssfindo_state::PS7500_startTimer1()
+READ_LINE_MEMBER(tetfight_state::iocr_od0_r)
{
- int val=((m_PS7500_IO[T1low]&0xff)|((m_PS7500_IO[T1high]&0xff)<<8))>>1;
- if(val==0)
- m_PS7500timer1->adjust(attotime::never);
- else
- m_PS7500timer1->adjust(attotime::from_usec(val ), 0, attotime::from_usec(val ));
+ return (m_i2cmem_clock == true ? 1 : 0); //eeprom read
}
-INTERRUPT_GEN_MEMBER(ssfindo_state::interrupt)
+WRITE_LINE_MEMBER(tetfight_state::iocr_od1_w)
{
- m_PS7500_IO[IRQSTA]|=0x08;
- if(m_PS7500_IO[IRQMSKA]&0x08)
- {
- device.execute().pulse_input_line(ARM7_IRQ_LINE, device.execute().minimum_quantum_time());
- }
+ // TODO: i2c cares about the order of this!?
+ // tetfight reaches PC=0x106c if initialization has success
+ // rpc700 doesn't like above and go into supervisor mode even with a valid NVRAM
+ // both wants clock first then data, not sure where the issue actually is
+ m_i2cdata_hack = state == true;
+ //m_i2cmem->write_sda(state == true ? 1 : 0);
}
-void ssfindo_state::PS7500_reset()
+WRITE_LINE_MEMBER(tetfight_state::iocr_od0_w)
{
- m_PS7500_IO[IOCR] = 0x3f;
- m_PS7500_IO[VIDCR] = 0;
-
- m_PS7500timer0->adjust( attotime::never);
- m_PS7500timer1->adjust( attotime::never);
+ m_i2cmem_clock = state;
+ m_i2cmem->write_scl(state == true ? 1 : 0);
+ m_i2cmem->write_sda(m_i2cdata_hack == true ? 1 : 0);
}
-
void ssfindo_state::ssfindo_speedups()
{
if (m_maincpu->pc()==0x2d6c8) // ssfindo
@@ -417,138 +293,15 @@ void ssfindo_state::ppcar_speedups()
m_maincpu->spin_until_time(attotime::from_usec(20));
}
-
-READ32_MEMBER(ssfindo_state::PS7500_IO_r)
-{
- switch(offset)
- {
- case MSECR:
- return machine().rand();
-
- case IOLINES: //TODO: eeprom 24c01
-#if 0
- osd_printf_debug("IOLINESR %i @%x\n", offset, m_maincpu->pc());
-#endif
-
- if(m_flashType == 1)
- return 0;
- else
- return machine().rand();
-
- case IRQSTA:
- return (m_PS7500_IO[offset] & (~2)) | 0x80;
-
- case IRQRQA:
- return (m_PS7500_IO[IRQSTA] & m_PS7500_IO[IRQMSKA]) | 0x80;
-
- case IOCR: //TODO: nINT1, OD[n] p.81
- if (m_speedup) (this->*m_speedup)();
-
- if( m_iocr_hack)
- {
- return (m_io_ps7500->read() & 0x80) | 0x34 | (m_i2cmem->read_sda() ? 0x03 : 0x00); //eeprom read
- }
-
- return (m_io_ps7500->read() & 0x80) | 0x37;
-
- case VIDCR:
- return (m_PS7500_IO[offset] | 0x50) & 0xfffffff0;
-
- case T1low:
- case T0low:
- case T1high:
- case T0high:
- case IRQMSKA:
- case VIDEND:
- case VIDSTART:
- case VIDINITA: //TODO: bits 29 ("equal") and 30 (last bit) p.105
-
- return m_PS7500_IO[offset];
-
-
- }
- return machine().rand();//m_PS7500_IO[offset];
-}
-
-WRITE32_MEMBER(ssfindo_state::PS7500_IO_w)
-{
- uint32_t temp=m_PS7500_IO[offset];
-
- COMBINE_DATA(&temp);
-
- switch(offset)
- {
- case IOLINES: //TODO: eeprom 24c01
- m_PS7500_IO[offset]=data;
- if(data&0xc0)
- m_adrLatch=0;
-
- if(m_maincpu->pc() == 0xbac0 && m_flashType == 1)
- {
- m_flashN=data&1;
- }
-
-#if 0
- logerror("IOLINESW %i = %x @%x\n",offset,data,m_maincpu->pc());
-#endif
- break;
-
- case IRQRQA:
- m_PS7500_IO[IRQSTA]&=~temp;
- break;
-
- case IRQMSKA:
- m_PS7500_IO[IRQMSKA]=(temp&(~2))|0x80;
- break;
-
- case T1GO:
- PS7500_startTimer1();
- break;
-
- case T0GO:
- PS7500_startTimer0();
- break;
-
- case VIDEND:
- case VIDSTART:
- COMBINE_DATA(&m_PS7500_IO[offset]);
- m_PS7500_IO[offset]&=0xfffffff0; // qword align
- break;
-
- case IOCR:
- //popmessage("IOLINESW %i = %x @%x\n",offset,data,m_maincpu->pc());
- COMBINE_DATA(&m_PS7500_IO[offset]);
- // TODO: correct hook-up
- m_i2cmem->write_scl((data & 0x01) ? 1 : 0);
- m_i2cmem->write_sda((data & 0x02) ? 1 : 0);
- break;
-
- case REFCR:
- case DRAMCR:
- case SD0CR:
- case ROMCR0:
- case VIDMUX:
- case CLKCTL:
- case T1low:
- case T0low:
- case T1high:
- case T0high:
- case VIDCR:
- case VIDINITA: //TODO: bit 30 (last bit) p.105
- COMBINE_DATA(&m_PS7500_IO[offset]);
- break;
- }
-}
-
READ32_MEMBER(ssfindo_state::io_r)
{
int adr=m_flashAdr*0x200+(m_flashOffset);
-
switch(m_flashType)
{
case 0:
- if(m_PS7500_IO[IOLINES]&1) //bit 0 of IOLINES = flash select ( 5/6 or 3/2 )
+ //bit 0 of IOLINES = flash select ( 5/6 or 3/2 )
+ if (m_flash_bank_select)
adr+=0x400000;
break;
@@ -609,7 +362,7 @@ READ32_MEMBER(ssfindo_state::randomized_r)
void ssfindo_state::ssfindo_map(address_map &map)
{
map(0x00000000, 0x000fffff).rom();
- map(0x03200000, 0x032001ff).rw(FUNC(ssfindo_state::PS7500_IO_r), FUNC(ssfindo_state::PS7500_IO_w));
+ map(0x03200000, 0x032001ff).m(m_iomd, FUNC(arm7500fe_iomd_device::map));
map(0x03012e60, 0x03012e67).noprw();
map(0x03012fe0, 0x03012fe3).w(FUNC(ssfindo_state::debug_w));
map(0x03012ff0, 0x03012ff3).noprw();
@@ -621,14 +374,14 @@ void ssfindo_state::ssfindo_map(address_map &map)
map(0x03243000, 0x03243003).portr("DSW").nopw();
map(0x0324f000, 0x0324f003).r(FUNC(ssfindo_state::SIMPLEIO_r));
map(0x03245000, 0x03245003).nopw(); /* sound ? */
- map(0x03400000, 0x03400003).w(FUNC(ssfindo_state::FIFO_w));
- map(0x10000000, 0x11ffffff).ram().share("vram");
+ map(0x03400000, 0x037fffff).w(m_vidc, FUNC(arm_vidc20_device::write));
+ map(0x10000000, 0x11ffffff).ram();
}
void ssfindo_state::ppcar_map(address_map &map)
{
map(0x00000000, 0x000fffff).rom();
- map(0x03200000, 0x032001ff).rw(FUNC(ssfindo_state::PS7500_IO_r), FUNC(ssfindo_state::PS7500_IO_w));
+ map(0x03200000, 0x032001ff).m(m_iomd, FUNC(arm7500fe_iomd_device::map));
map(0x03012b00, 0x03012bff).r(FUNC(ssfindo_state::randomized_r)).nopw();
map(0x03012e60, 0x03012e67).nopw();
map(0x03012ff8, 0x03012ffb).portr("IN0").nopw();
@@ -636,43 +389,52 @@ void ssfindo_state::ppcar_map(address_map &map)
map(0x03340000, 0x03340007).nopw();
map(0x03341000, 0x0334101f).nopw();
map(0x033c0000, 0x033c0003).r(FUNC(ssfindo_state::io_r)).w(FUNC(ssfindo_state::io_w));
- map(0x03400000, 0x03400003).w(FUNC(ssfindo_state::FIFO_w));
+ map(0x03400000, 0x037fffff).w(m_vidc, FUNC(arm_vidc20_device::write));
map(0x08000000, 0x08ffffff).ram();
- map(0x10000000, 0x10ffffff).ram().share("vram");
+ map(0x10000000, 0x10ffffff).ram();
}
-READ32_MEMBER(ssfindo_state::tetfight_unk_r)
+READ32_MEMBER(tetfight_state::tetfight_unk_r)
{
//sound status ?
return machine().rand();
}
-WRITE32_MEMBER(ssfindo_state::tetfight_unk_w)
+WRITE32_MEMBER(tetfight_state::tetfight_unk_w)
{
//sound latch ?
}
-void ssfindo_state::tetfight_map(address_map &map)
+void tetfight_state::tetfight_map(address_map &map)
{
map(0x00000000, 0x001fffff).rom();
- map(0x03200000, 0x032001ff).rw(FUNC(ssfindo_state::PS7500_IO_r), FUNC(ssfindo_state::PS7500_IO_w));
- map(0x03400000, 0x03400003).w(FUNC(ssfindo_state::FIFO_w));
+ map(0x03200000, 0x032001ff).m(m_iomd, FUNC(arm7500fe_iomd_device::map));
map(0x03240000, 0x03240003).portr("IN0");
map(0x03240004, 0x03240007).portr("IN1");
map(0x03240008, 0x0324000b).portr("DSW2");
- map(0x03240020, 0x03240023).rw(FUNC(ssfindo_state::tetfight_unk_r), FUNC(ssfindo_state::tetfight_unk_w));
- map(0x10000000, 0x14ffffff).ram().share("vram");
+ map(0x03240020, 0x03240023).rw(FUNC(tetfight_state::tetfight_unk_r), FUNC(tetfight_state::tetfight_unk_w));
+ map(0x03400000, 0x037fffff).w(m_vidc, FUNC(arm_vidc20_device::write));
+ map(0x10000000, 0x14ffffff).ram();
+}
+
+void ssfindo_state::machine_start()
+{
+ // TODO: convert to exact flash device
+ save_item(NAME(m_flashAdr));
+ save_item(NAME(m_flashOffset));
+ save_item(NAME(m_adrLatch));
+ save_item(NAME(m_flashN));
+ save_item(NAME(m_i2cmem_clock));
+ save_item(NAME(m_flash_bank_select));
}
void ssfindo_state::machine_reset()
{
- PS7500_reset();
+ // ...
}
static INPUT_PORTS_START( ssfindo )
- PORT_START("PS7500")
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")
-
+ // TODO: incomplete structs
PORT_START("IN0")
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNUSED ) // IPT_START2 ??
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
@@ -698,31 +460,28 @@ static INPUT_PORTS_START( ssfindo )
PORT_DIPNAME( 0x02, 0x02, DEF_STR( Free_Play ) )
PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
- PORT_DIPNAME( 0x80, 0x80, DEF_STR( Service_Mode ) )
- PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x04, 0x04, "DSW 2" )
PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x08, 0x08, "DSW 3" )
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
- PORT_DIPNAME( 0x10, 0x010, "DSW 4" )
+ PORT_DIPNAME( 0x10, 0x10, "DSW 4" )
PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x20, 0x20, "DSW 5" )
PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
- PORT_DIPNAME( 0x40, 0x040, "DSW 6" )
+ PORT_DIPNAME( 0x40, 0x40, "DSW 6" )
PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Service_Mode ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
INPUT_PORTS_END
static INPUT_PORTS_START( ppcar )
- PORT_START("PS7500")
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")
-
PORT_START("IN0")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_COIN1 )
@@ -737,9 +496,6 @@ static INPUT_PORTS_START( ppcar )
INPUT_PORTS_END
static INPUT_PORTS_START( tetfight )
- PORT_START("PS7500")
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")
-
PORT_START("IN0")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
@@ -798,42 +554,46 @@ INPUT_PORTS_END
void ssfindo_state::ssfindo(machine_config &config)
{
- /* basic machine hardware */
- ARM7(config, m_maincpu, 54000000); // guess...
+ ARM7(config, m_maincpu, 54000000);
m_maincpu->set_addrmap(AS_PROGRAM, &ssfindo_state::ssfindo_map);
- m_maincpu->set_vblank_int("screen", FUNC(ssfindo_state::interrupt));
I2C_24C01(config, m_i2cmem);
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_refresh_hz(60);
- screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
- screen.set_size(320, 256);
- screen.set_visarea(0, 319, 0, 239);
- screen.set_screen_update(FUNC(ssfindo_state::screen_update));
- screen.set_palette(m_palette);
-
- PALETTE(config, m_palette).set_entries(256);
+ SCREEN(config, "screen", SCREEN_TYPE_RASTER);
+
+ ARM_VIDC20(config, m_vidc, 24_MHz_XTAL);
+ m_vidc->set_screen("screen");
+ m_vidc->vblank().set(m_iomd, FUNC(arm_iomd_device::vblank_irq));
+ m_vidc->sound_drq().set(m_iomd, FUNC(arm_iomd_device::sound_drq));
+
+ ARM7500FE_IOMD(config, m_iomd, 54000000);
+ m_iomd->set_host_cpu_tag(m_maincpu);
+ m_iomd->set_vidc_tag(m_vidc);
+ m_iomd->iolines_read().set(FUNC(ssfindo_state::iolines_r));
+ m_iomd->iolines_write().set(FUNC(ssfindo_state::iolines_w));
}
void ssfindo_state::ppcar(machine_config &config)
{
ssfindo(config);
- /* basic machine hardware */
m_maincpu->set_addrmap(AS_PROGRAM, &ssfindo_state::ppcar_map);
config.device_remove("i2cmem");
}
-void ssfindo_state::tetfight(machine_config &config)
+void tetfight_state::tetfight(machine_config &config)
{
ppcar(config);
- /* basic machine hardware */
- m_maincpu->set_addrmap(AS_PROGRAM, &ssfindo_state::tetfight_map);
+ m_maincpu->set_addrmap(AS_PROGRAM, &tetfight_state::tetfight_map);
I2C_24C02(config, m_i2cmem);
+
+ m_iomd->iocr_read_od<0>().set(FUNC(tetfight_state::iocr_od0_r));
+ m_iomd->iocr_read_od<1>().set(FUNC(tetfight_state::iocr_od1_r));
+ m_iomd->iocr_write_od<0>().set(FUNC(tetfight_state::iocr_od0_w));
+ m_iomd->iocr_write_od<1>().set(FUNC(tetfight_state::iocr_od1_w));
}
ROM_START( ssfindo )
@@ -909,11 +669,11 @@ ROM_END
void ssfindo_state::init_common()
{
m_speedup = nullptr;
- m_PS7500timer0 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ssfindo_state::PS7500_Timer0_callback),this));
- m_PS7500timer1 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ssfindo_state::PS7500_Timer1_callback),this));
+ //m_PS7500timer0 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ssfindo_state::PS7500_Timer0_callback),this));
+ //m_PS7500timer1 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ssfindo_state::PS7500_Timer1_callback),this));
- save_item(NAME(m_PS7500_IO));
- save_item(NAME(m_PS7500_FIFO));
+ //save_item(NAME(m_PS7500_IO));
+ //save_item(NAME(m_PS7500_FIFO));
}
void ssfindo_state::init_ssfindo()
@@ -921,12 +681,6 @@ void ssfindo_state::init_ssfindo()
init_common();
m_flashType = 0;
m_speedup = &ssfindo_state::ssfindo_speedups;
- m_iocr_hack = 0;
-
- save_item(NAME(m_flashAdr));
- save_item(NAME(m_flashOffset));
- save_item(NAME(m_adrLatch));
- save_item(NAME(m_flashN));
}
void ssfindo_state::init_ppcar()
@@ -936,13 +690,12 @@ void ssfindo_state::init_ppcar()
m_speedup = &ssfindo_state::ppcar_speedups;
}
-void ssfindo_state::init_tetfight()
+void tetfight_state::init_tetfight()
{
init_common();
m_flashType = 0;
- m_iocr_hack = 1;
}
GAME( 1999, ssfindo, 0, ssfindo, ssfindo, ssfindo_state, init_ssfindo, ROT0, "Icarus", "See See Find Out", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
GAME( 1999, ppcar, 0, ppcar, ppcar, ssfindo_state, init_ppcar, ROT0, "Icarus", "Pang Pang Car", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
-GAME( 2001, tetfight,0, tetfight, tetfight, ssfindo_state, init_tetfight, ROT0, "Sego", "Tetris Fighters", MACHINE_NO_SOUND | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
+GAME( 2001, tetfight,0, tetfight, tetfight, tetfight_state, init_tetfight, ROT0, "Sego", "Tetris Fighters", MACHINE_NO_SOUND | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )