From a7738bb241d226ca218e05522026881225f84cd8 Mon Sep 17 00:00:00 2001 From: arbee Date: Wed, 19 Jun 2024 11:41:50 -0400 Subject: machine/mv_sonora.cpp: Sonora/Ardbeg use an external pixel clock (PDM does not). Also fixed monochrome mode. [R. Belmont] apple/omega.cpp: Add "Omega" programmable PLL chip to generate the pixel clock for LC III/LC 520/LC 550. [R. Belmont] --- src/devices/machine/mv_sonora.cpp | 37 +++++++--- src/devices/machine/mv_sonora.h | 6 +- src/mame/apple/maclc3.cpp | 12 ++++ src/mame/apple/omega.cpp | 141 ++++++++++++++++++++++++++++++++++++++ src/mame/apple/omega.h | 34 +++++++++ src/mame/apple/sonora.h | 2 + 6 files changed, 223 insertions(+), 9 deletions(-) create mode 100644 src/mame/apple/omega.cpp create mode 100644 src/mame/apple/omega.h diff --git a/src/devices/machine/mv_sonora.cpp b/src/devices/machine/mv_sonora.cpp index f51007d9e64..441285829fa 100644 --- a/src/devices/machine/mv_sonora.cpp +++ b/src/devices/machine/mv_sonora.cpp @@ -5,6 +5,11 @@ Mac video support, "Sonora" edition Supports 5 different modelines at up to 16bpp + The original Sonora ASIC and its follow-on Ardbeg require an + external pixel clock source, while the version used in the PDM + machines has an internal clock source that automatically is set + appropriately for the video mode. + *********************************************************************/ #include "emu.h" @@ -13,11 +18,11 @@ DEFINE_DEVICE_TYPE(MAC_VIDEO_SONORA, mac_video_sonora_device, "mv_sonora", "Mac Sonora video support") const mac_video_sonora_device::modeline mac_video_sonora_device::modelines[5] = { - { 0x02, "512x384 12\" RGB", 15667200, 640, 16, 32, 80, 407, 1, 3, 19, true }, - { 0x06, "640x480 13\" RGB", 31334400, 896, 80, 64, 112, 525, 3, 3, 39, true }, - { 0x01, "640x870 15\" Portrait", 57283200, 832, 32, 80, 80, 918, 3, 3, 42, false }, - { 0x09, "832x624 16\" RGB", 57283200, 1152, 32, 64, 224, 667, 1, 3, 39, false }, - { 0x0b, "640x480 VGA", 25175000, 800, 16, 96, 48, 525, 10, 2, 33, false }, + { 0x02, "512x384 12\" RGB", 15667200, 640, 16, 32, 80, 407, 1, 3, 19, true, false }, + { 0x06, "640x480 13\" RGB", 31334400, 896, 80, 64, 112, 525, 3, 3, 39, true, false }, + { 0x01, "640x870 15\" Portrait", 57283200, 832, 32, 80, 80, 918, 3, 3, 42, false, true }, + { 0x09, "832x624 16\" RGB", 57283200, 1152, 32, 64, 224, 667, 1, 3, 39, false, false }, + { 0x0b, "640x480 VGA", 25175000, 800, 16, 96, 48, 525, 10, 2, 33, false, false }, }; mac_video_sonora_device::mac_video_sonora_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : @@ -26,6 +31,7 @@ mac_video_sonora_device::mac_video_sonora_device(const machine_config &mconfig, m_palette(*this, "palette"), m_monitor_config(*this, "monitor"), m_screen_vblank(*this), + m_isPDM(false), m_is32bit(false) { } @@ -272,7 +278,11 @@ void mac_video_sonora_device::vctrl_w(offs_t offset, uint8_t data) if(m_modeline_id != -1 && m_modeline_id != prev_modeline) { const modeline &m = modelines[m_modeline_id]; rectangle visarea(0, m.htot - m.hfp - m.hs - m.hbp - 1, 0, m.vtot - m.vfp - m.vs - m.vbp - 1); - m_screen->configure(m.htot, m.vtot, visarea, attotime::from_ticks(m.htot*m.vtot, m.dotclock).as_attoseconds()); + if (m_isPDM) { + m_screen->configure(m.htot, m.vtot, visarea, attotime::from_ticks(m.htot*m.vtot, m.dotclock).as_attoseconds()); + } else { + m_screen->configure(m.htot, m.vtot, visarea, attotime::from_ticks(m.htot * m.vtot, m_extPixelClock).as_attoseconds()); + } } break; } @@ -305,7 +315,7 @@ uint8_t mac_video_sonora_device::dac_r(offs_t offset) return m_pal_control; default: - logerror("dac_r %x\n", offset); +// logerror("dac_r %x\n", offset); return 0; } } @@ -322,7 +332,18 @@ void mac_video_sonora_device::dac_w(offs_t offset, uint8_t data) switch(m_pal_idx) { case 0: m_palette->set_pen_red_level(m_pal_address, data); break; case 1: m_palette->set_pen_green_level(m_pal_address, data); break; - case 2: m_palette->set_pen_blue_level(m_pal_address, data); break; + case 2: + // monochrome monitors use the blue line as the video, so duplicate blue to all 3 primaries + if (modelines[m_modeline_id].monochrome) { + m_palette->set_pen_red_level(m_pal_address, data); + m_palette->set_pen_green_level(m_pal_address, data); + m_palette->set_pen_blue_level(m_pal_address, data); + } + else + { + m_palette->set_pen_blue_level(m_pal_address, data); + } + break; } m_pal_idx ++; if(m_pal_idx == 3) { diff --git a/src/devices/machine/mv_sonora.h b/src/devices/machine/mv_sonora.h index 127cd921edc..3761ae91033 100644 --- a/src/devices/machine/mv_sonora.h +++ b/src/devices/machine/mv_sonora.h @@ -33,6 +33,8 @@ public: void set_vram_base(const uint64_t *vram) { m_vram = vram; } void set_vram_offset(uint32_t offset) { m_vram_offset = offset; } void set_32bit() { m_is32bit = true; } + void set_PDM() { m_isPDM = true; } + void set_pixel_clock(uint32_t pclk) { m_extPixelClock = pclk; } protected: virtual void device_start() override; @@ -48,6 +50,7 @@ private: uint32_t htot, hfp, hs, hbp; uint32_t vtot, vfp, vs, vbp; bool supports_16bpp; + bool monochrome; }; static const modeline modelines[5]; @@ -58,10 +61,11 @@ private: devcb_write_line m_screen_vblank; const uint64_t *m_vram; - uint32_t m_vram_offset; + uint32_t m_vram_offset, m_extPixelClock; uint8_t m_mode, m_depth, m_monitor_id, m_vtest; uint8_t m_pal_address, m_pal_idx, m_pal_control, m_pal_colkey; int m_modeline_id; + bool m_isPDM; bool m_is32bit; uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); diff --git a/src/mame/apple/maclc3.cpp b/src/mame/apple/maclc3.cpp index c0fe497dc18..de6585f08ff 100644 --- a/src/mame/apple/maclc3.cpp +++ b/src/mame/apple/maclc3.cpp @@ -23,6 +23,7 @@ #include "macadb.h" #include "macscsi.h" #include "mactoolbox.h" +#include "omega.h" #include "sonora.h" #include "bus/nscsi/cd.h" @@ -57,6 +58,7 @@ public: m_ram(*this, RAM_TAG), m_sonora(*this, "sonora"), m_dfac(*this, "dfac"), + m_omega(*this, "omega"), m_scsibus1(*this, "scsi"), m_ncr5380(*this, "scsi:7:ncr5380"), m_scsihelp(*this, "scsihelp"), @@ -83,6 +85,7 @@ private: required_device m_ram; required_device m_sonora; optional_device m_dfac; + required_device m_omega; required_device m_scsibus1; required_device m_ncr5380; required_device m_scsihelp; @@ -298,6 +301,9 @@ void macvail_state::maclc3_base(machine_config &config) m_dfac->add_route(0, "lspeaker", 1.0); m_dfac->add_route(1, "rspeaker", 1.0); + APPLE_OMEGA(config, m_omega, 31.3344_MHz_XTAL); + m_omega->pclock_changed().set(m_sonora, FUNC(sonora_device::pixel_clock_w)); + SONORA(config, m_sonora, C15M); m_sonora->set_maincpu_tag("maincpu"); m_sonora->set_rom_tag("bootrom"); @@ -324,8 +330,11 @@ void macvail_state::maclc3(machine_config &config) m_egret->set_default_bios_tag("341s0851"); m_egret->reset_callback().set(FUNC(macvail_state::cuda_reset_w)); m_egret->dfac_scl_callback().set(m_dfac, FUNC(dfac_device::clock_write)); + m_egret->dfac_scl_callback().append(m_omega, FUNC(omega_device::clock_write)); m_egret->dfac_sda_callback().set(m_dfac, FUNC(dfac_device::data_write)); + m_egret->dfac_sda_callback().append(m_omega, FUNC(omega_device::data_write)); m_egret->dfac_latch_callback().set(m_dfac, FUNC(dfac_device::latch_write)); + m_egret->dfac_latch_callback().append(m_omega, FUNC(omega_device::latch_write)); m_egret->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_egret->via_clock_callback().set(m_sonora, FUNC(sonora_device::cb1_w)); m_egret->via_data_callback().set(m_sonora, FUNC(sonora_device::cb2_w)); @@ -356,6 +365,9 @@ void macvail_state::maclc520(machine_config &config) m_cuda->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_cuda->via_clock_callback().set(m_sonora, FUNC(sonora_device::cb1_w)); m_cuda->via_data_callback().set(m_sonora, FUNC(sonora_device::cb2_w)); + m_cuda->iic_scl_callback().set(m_omega, FUNC(omega_device::clock_write)); + m_cuda->iic_sda_callback().set(m_omega, FUNC(omega_device::data_write)); + m_cuda->dfac_latch_callback().set(m_omega, FUNC(omega_device::latch_write)); m_macadb->adb_data_callback().set(m_cuda, FUNC(cuda_device::set_adb_line)); config.set_perfect_quantum(m_maincpu); diff --git a/src/mame/apple/omega.cpp b/src/mame/apple/omega.cpp new file mode 100644 index 00000000000..72a633749d8 --- /dev/null +++ b/src/mame/apple/omega.cpp @@ -0,0 +1,141 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/*************************************************************************** + + omega.cpp - Apple PLL clock synthesizer, used with Sonora and Ardbeg + based machines to generate the system clock and video dot clock. + + Omega is intended to share the 3-wire clock/data/latch serial bus + with DFAC. On the rising edge of the latch, it takes note of the + next 16 bits. The first 7 are the N parameter, the next 7 bits are + the D parameter, and the final 2 are the P parameter. The actual + formula is identical to the Gazelle chip and the Sierra Semiconductor + SC11412. + + Pixel clock = (31.3344 MHz * (N / D)) / P; + + ________________________ + / 4 3 2 1 28 27 26 | + | * | + | 5 25 | + | 6 344S1060-A N 24 | + | 7 23 | + | 8 (C)1991 APPLE 22 | + | 9 21 | + | 10 20 | + | 11 19 | + |____12_13_14_15_16_17_18__| + + 1, 7, 13, 16, 19, 20 = DGND, digital ground + 2, 28 = AGND, analog ground + 3 = DOTFLTR, filter for the DOTCLK output + 4, 26 = AVDD, analog +5 volt supply (connected to VDD in LC 520) + 5 - OESYSCLK - 1 to enable the SYSCLK output on pin 15 + 6 - OEALL - 1 to enable both the pixel and system clocks? + 8 - SLATCH - serial latch + 9 - SDATA - serial data + 10 - SCLK - serial bit clock + 11, 14, 17, 23 = VDD, main +5 volt supply + 12 - DOTCLK - video dot clock output + 15 - SYSCLK - system clock output + 18 - C32M - outputs a mirror of the reference crystal clock + 21 - XTALOUT + 22 - XTALIN - connect the 31.3344 MHz reference crystal between XTALIN and XTALOUT + 24 - S1 - selects one of the canned system clock freqencies (24 is VDD, 25 is GND in LC III = 25 MHz) + 25 - S0 - " " " " " " " " + 27 - SYSFLTR - filter for the SYSCLK output + + SYSFLTR and DOTFLTR are connected like this: + + 604 ohms? 0.1uF + (pin 3 or 27) ----/\/\/\----||-----| + | |-----GND + |---||-------------| + 0.002uF + +***************************************************************************/ + +#include "emu.h" +#include "omega.h" + +#define VERBOSE (0) + +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(APPLE_OMEGA, omega_device, "aplomega", "Apple Omega PLL Clock Synthesizer") + +omega_device::omega_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, APPLE_OMEGA, tag, owner, clock), + m_write_pclock(*this), + m_data(false), + m_clock(false), + m_latch(false), + m_latch_byte(0), + m_N(0), + m_D(0), + m_P(0), + m_bit(0) +{ +} + +void omega_device::device_start() +{ + save_item(NAME(m_clock)); + save_item(NAME(m_data)); + save_item(NAME(m_latch)); + save_item(NAME(m_latch_byte)); + save_item(NAME(m_N)); + save_item(NAME(m_D)); + save_item(NAME(m_P)); + save_item(NAME(m_bit)); +} + +void omega_device::clock_write(int state) +{ + // take a bit on the rising edge of SCL + if (state && !m_clock) + { + m_latch_byte <<= 1; + m_latch_byte |= m_data & 1; + + switch (m_bit) + { + case 6: + m_N = m_latch_byte; + m_latch_byte = 0; + break; + + case 13: + m_D = m_latch_byte; + m_latch_byte = 0; + break; + + case 15: + m_P = m_latch_byte & 3; + + const u32 pclock = (u32)(31334400.0f * ((double)m_N / (double)m_D)) / (double)m_P; + m_write_pclock(pclock); + + LOG("%s: N = %d, D = %d, P = %d, pixel clock = %d\n", tag(), m_N, m_D, m_P, pclock); + break; + } + + m_bit++; + } + + m_clock = state; +} + +void omega_device::latch_write(int state) +{ + // start counting bits on the falling edge of the latch + if (state && !m_latch) + { + LOG("%s: latch rising edge, resetting bit count\n", tag()); + m_bit = 0; + m_latch_byte = 0; + } + + m_latch = state; +} + diff --git a/src/mame/apple/omega.h b/src/mame/apple/omega.h new file mode 100644 index 00000000000..19628981c53 --- /dev/null +++ b/src/mame/apple/omega.h @@ -0,0 +1,34 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +#ifndef MAME_APPLE_OMEGA_H +#define MAME_APPLE_OMEGA_H + +#pragma once + +class omega_device : public device_t +{ +public: + omega_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + auto pclock_changed() { return m_write_pclock.bind(); } + + // Omega uses the same 3-wire serial interface as DFAC, and is intended + // to share the bus with DFAC. + void data_write(int state) { m_data = state; } + void clock_write(int state); + void latch_write(int state); + +protected: + // device_r overrides + virtual void device_start() override; + +private: + devcb_write32 m_write_pclock; + bool m_data, m_clock, m_latch; + u8 m_latch_byte, m_N, m_D, m_P; + u32 m_bit; +}; + +DECLARE_DEVICE_TYPE(APPLE_OMEGA, omega_device) + +#endif // MAME_APPLE_OMEGA_H diff --git a/src/mame/apple/sonora.h b/src/mame/apple/sonora.h index 046a84386a7..9e3541595aa 100644 --- a/src/mame/apple/sonora.h +++ b/src/mame/apple/sonora.h @@ -43,6 +43,8 @@ public: template void slot_irq_w(int state); void scc_irq_w(int state); + void pixel_clock_w(u32 pclk) { m_video->set_pixel_clock(pclk); } + protected: // device-level overrides virtual void device_start() override; -- cgit v1.2.3