diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index ac96f03e4cc..db520225ce0 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -2430,6 +2430,18 @@ if (MACHINES["NSCSI"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/pcf8573.h,MACHINES["PCF8573"] = true +--------------------------------------------------- + +if (MACHINES["PCF8573"]~=null) then + files { + MAME_DIR .. "src/devices/machine/pcf8573.cpp", + MAME_DIR .. "src/devices/machine/pcf8573.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/pcf8583.h,MACHINES["PCF8583"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index bfe2b6b3982..ed649a5cb0c 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -619,6 +619,7 @@ MACHINES["OUTPUT_LATCH"] = true MACHINES["PC_FDC"] = true MACHINES["PC_LPT"] = true MACHINES["PCCARD"] = true +MACHINES["PCF8573"] = true MACHINES["PCF8583"] = true --MACHINES["PCF8584"] = true MACHINES["PCF8593"] = true diff --git a/src/devices/machine/pcf8573.cpp b/src/devices/machine/pcf8573.cpp new file mode 100644 index 00000000000..5a33d716be8 --- /dev/null +++ b/src/devices/machine/pcf8573.cpp @@ -0,0 +1,356 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************* + + Philips PCF8573 Clock and Calendar with Power Fail Detector + + TODO: + - status bits 3/4 seconds/minutes are not set. + +*********************************************************************/ + +#include "emu.h" +#include "pcf8573.h" + +#define LOG_DATA (1 << 1) +#define LOG_LINE (1 << 2) + +#define VERBOSE (0) +#include "logmacro.h" + + +DEFINE_DEVICE_TYPE(PCF8573, pcf8573_device, "pcf8573", "PCF8573 RTC with Power Fail Detector") + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// pcf8573_device - constructor +//------------------------------------------------- + +pcf8573_device::pcf8573_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, PCF8573, tag, owner, clock) + , device_rtc_interface(mconfig, *this) + , m_comp_cb(*this) + , m_min_cb(*this) + , m_sec_cb(*this) + , m_clock_timer(nullptr) + , m_slave_address(PCF8573_SLAVE_ADDRESS) + , m_scl(0) + , m_sdaw(0) + , m_sdar(1) + , m_state(STATE_IDLE) + , m_bits(0) + , m_shift(0) + , m_devsel(0) + , m_mode_pointer(0) + , m_address(0) + , m_status(0) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void pcf8573_device::device_start() +{ + m_comp_cb.resolve_safe(); + m_min_cb.resolve_safe(); + m_sec_cb.resolve_safe(); + + // allocate timers + m_clock_timer = timer_alloc(); + m_clock_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768)); + + // state saving + save_item(NAME(m_scl)); + save_item(NAME(m_sdaw)); + save_item(NAME(m_sdar)); + save_item(NAME(m_state)); + save_item(NAME(m_bits)); + save_item(NAME(m_shift)); + save_item(NAME(m_devsel)); + save_item(NAME(m_mode_pointer)); + save_item(NAME(m_address)); + save_item(NAME(m_status)); + save_item(NAME(m_data)); + save_item(NAME(m_slave_address)); +} + +//------------------------------------------------- +// device_timer - handler timer events +//------------------------------------------------- + +void pcf8573_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + advance_seconds(); + + // one pulse per second output + m_sec_cb(1); + m_sec_cb(0); +} + +void pcf8573_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) +{ + if (m_data[REG_MINUTES] == convert_to_bcd(minute)) + return; + + // update registers + set_time_minute(minute); + set_time_hour(hour); + set_date_day(day); + set_date_month(month); + + // one pulse per minute output + m_min_cb(1); + m_min_cb(0); + + // comparator output + if (m_data[REG_HOURS] == m_data[REG_ALARM_HOURS] && m_data[REG_MINUTES] == m_data[REG_ALARM_MINUTES]) + { + if (BIT(m_status, 2) || (m_data[REG_DAYS] == m_data[REG_ALARM_DAYS] && m_data[REG_MONTHS] == m_data[REG_ALARM_MONTHS])) + { + // set COMP flag + m_status |= 1 << 1; + m_comp_cb(1); + } + } +} + +//************************************************************************** +// READ/WRITE HANDLERS +//************************************************************************** + +WRITE_LINE_MEMBER(pcf8573_device::a0_w) +{ + state &= 1; + if (BIT(m_slave_address, 1) != state) + { + LOGMASKED(LOG_LINE, "set a0 %d\n", state ); + m_slave_address = (m_slave_address & 0xfd) | (state << 1); + } +} + +WRITE_LINE_MEMBER(pcf8573_device::a1_w) +{ + state &= 1; + if (BIT(m_slave_address, 2) != state) + { + LOGMASKED(LOG_LINE, "set a1 %d\n", state ); + m_slave_address = (m_slave_address & 0xfb) | (state << 2); + } +} + +WRITE_LINE_MEMBER(pcf8573_device::scl_w) +{ + if (m_scl != state) + { + m_scl = state; + LOGMASKED(LOG_LINE, "set_scl_line %d\n", m_scl); + + switch (m_state) + { + case STATE_ADDRESS: + case STATE_MODE: + case STATE_DATAIN: + if (m_bits < 8) + { + if (m_scl) + { + m_shift = ((m_shift << 1) | m_sdaw) & 0xff; + m_bits++; + } + } + else + { + if (m_scl) + { + switch (m_state) + { + case STATE_ADDRESS: + m_devsel = m_shift; + + if ((m_devsel & 0xfe) != m_slave_address) + { + LOGMASKED(LOG_DATA, "address %02x: not this device\n", m_devsel); + m_state = STATE_IDLE; + } + else if ((m_devsel & 1) == 0) + { + LOGMASKED(LOG_DATA, "address %02x: write\n", m_devsel); + m_state = STATE_MODE; + } + else + { + LOGMASKED(LOG_DATA, "address %02x: read\n", m_devsel); + m_state = STATE_DATAOUT; + } + break; + + case STATE_MODE: + m_mode_pointer = m_shift; + + LOGMASKED(LOG_DATA, "mode pointer %02x\n", m_shift); + + switch (m_mode_pointer & 0x70) + { + case 0x00: // execute address + m_address = m_mode_pointer & 0x07; + break; + case 0x10: // read control/status flags + break; + case 0x20: // reset prescaler + set_clock_register(RTC_SECOND, 0); + adjust_seconds(); + break; + case 0x30: // time adjust + adjust_seconds(); + break; + case 0x40: // reset NODA flag + m_status &= ~(1 << 2); + break; + case 0x50: // set NODA flag + m_status |= 1 << 2; + break; + case 0x60: // reset COMP flag + m_status &= ~(1 << 1); + m_comp_cb(0); + break; + } + + m_state = STATE_DATAIN; + break; + + case STATE_DATAIN: + switch (m_mode_pointer & 0x70) + { + case 0x00: // execute address + m_data[m_address] = m_shift; + + LOGMASKED(LOG_DATA, "data[ %02x ] <- %02x\n", m_address, m_shift); + + switch (m_address) + { + case REG_HOURS: set_clock_register(RTC_HOUR, bcd_to_integer(m_data[REG_HOURS])); break; + case REG_MINUTES: set_clock_register(RTC_MINUTE, bcd_to_integer(m_data[REG_MINUTES])); break; + case REG_DAYS: set_clock_register(RTC_DAY, bcd_to_integer(m_data[REG_DAYS])); break; + case REG_MONTHS: set_clock_register(RTC_MONTH, bcd_to_integer(m_data[REG_MONTHS])); break; + } + + m_address = (m_address & 0x04) | ((m_address + 1) & 0x03); + break; + } + break; + } + + m_bits++; + } + else + { + if (m_bits == 8) + { + m_sdar = 0; + } + else + { + m_bits = 0; + m_sdar = 1; + } + } + } + break; + + case STATE_DATAOUT: + if (m_bits < 8) + { + if (m_scl) + { + if (m_bits == 0) + { + switch (m_mode_pointer & 0x70) + { + case 0x00: // execute address + m_shift = m_data[m_address]; + LOGMASKED(LOG_DATA, "data[ %02x ] -> %02x\n", m_address, m_shift); + m_address = (m_address & 0x04) | ((m_address + 1) & 0x03); + break; + + case 0x10: // read control/status flags + m_shift = m_status; + LOGMASKED(LOG_DATA, "status -> %02x\n", m_address, m_shift); + break; + } + } + + m_sdar = (m_shift >> 7) & 1; + + m_shift = (m_shift << 1) & 0xff; + m_bits++; + } + } + else + { + if (m_scl) + { + if (m_sdaw) + { + LOGMASKED(LOG_DATA, "nack\n"); + m_state = STATE_IDLE; + } + + m_bits++; + } + else + { + if (m_bits == 8) + { + m_sdar = 1; + } + else + { + m_bits = 0; + } + } + } + break; + } + } +} + +WRITE_LINE_MEMBER(pcf8573_device::sda_w) +{ + state &= 1; + if (m_sdaw != state) + { + LOGMASKED(LOG_LINE, "set sda %d\n", state); + m_sdaw = state; + + if (m_scl) + { + if (m_sdaw) + { + LOGMASKED(LOG_DATA, "stop\n"); + m_state = STATE_IDLE; + } + else + { + LOGMASKED(LOG_DATA, "start\n"); + m_state = STATE_ADDRESS; + m_bits = 0; + } + + m_sdar = 1; + } + } +} + +READ_LINE_MEMBER(pcf8573_device::sda_r) +{ + int res = m_sdar & 1; + + LOGMASKED(LOG_LINE, "read sda %d\n", res); + + return res; +} diff --git a/src/devices/machine/pcf8573.h b/src/devices/machine/pcf8573.h new file mode 100644 index 00000000000..1a7fade8c1b --- /dev/null +++ b/src/devices/machine/pcf8573.h @@ -0,0 +1,131 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************* + + Philips PCF8573 Clock and Calendar with Power Fail Detector + +********************************************************************** + + The PCF8573 comes in two package configurations: + + PCF8573P - 16-pin dual-inline package (DIP16) + PCF8573T - 16-pin small-outline package (SO16) + +********************************************************************** + + Pinning: ____ ____ + | \/ | + A0 1 | | 16 Vdd + A1 2 | | 15 Vss1 + COMP 3 | | 14 OSC0 + SDA 4 | PCF8573P | 13 OSC1 + SDL 5 | PCF8573T | 12 TEST + EXTPF 6 | | 11 FSET + PFIN 7 | | 10 SEC + Vss2 8 | | 9 MIN + |__________| + +*********************************************************************/ + +#ifndef MAME_MACHINE_PCF8573_H +#define MAME_MACHINE_PCF8573_H + +#pragma once + +#include "dirtc.h" + + +/*************************************************************************** +CONSTANTS +***************************************************************************/ + +#define PCF8573_SLAVE_ADDRESS ( 0xd0 ) + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> pcf8573_device + +class pcf8573_device : + public device_t, + public device_rtc_interface +{ +public: + pcf8573_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + auto comp_cb() { return m_comp_cb.bind(); } + auto min_cb() { return m_min_cb.bind(); } + auto sec_cb() { return m_sec_cb.bind(); } + + void set_a0(int a0) { m_slave_address = (m_slave_address & 0xfd) | (a0 << 1); } + void set_a1(int a1) { m_slave_address = (m_slave_address & 0xfb) | (a1 << 2); } + + DECLARE_WRITE_LINE_MEMBER(a0_w); + DECLARE_WRITE_LINE_MEMBER(a1_w); + DECLARE_WRITE_LINE_MEMBER(scl_w); + DECLARE_WRITE_LINE_MEMBER(sda_w); + DECLARE_READ_LINE_MEMBER(sda_r); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + // device_rtc_interface overrides + virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) override; + +private: + enum + { + REG_HOURS = 0x00, + REG_MINUTES = 0x01, + REG_DAYS = 0x02, + REG_MONTHS = 0x03, + REG_ALARM_HOURS = 0x04, + REG_ALARM_MINUTES = 0x05, + REG_ALARM_DAYS = 0x06, + REG_ALARM_MONTHS = 0x07 + }; + + // get/set time + uint8_t get_time_minute() { return bcd_to_integer(m_data[REG_MINUTES]); } + void set_time_minute(uint8_t minute){ m_data[REG_MINUTES] = convert_to_bcd(minute); } + uint8_t get_time_hour() { return bcd_to_integer(m_data[REG_HOURS]); } + void set_time_hour(uint8_t hour) { m_data[REG_HOURS] = convert_to_bcd(hour); } + + // get/set date + uint8_t get_date_day() { return bcd_to_integer(m_data[REG_DAYS]); } + void set_date_day(uint8_t day) { m_data[REG_DAYS] = convert_to_bcd(day); } + uint8_t get_date_month() { return bcd_to_integer(m_data[REG_MONTHS]); } + void set_date_month(uint8_t month) { m_data[REG_MONTHS] = convert_to_bcd(month); } + + devcb_write_line m_comp_cb; + devcb_write_line m_min_cb; + devcb_write_line m_sec_cb; + + // timers + emu_timer *m_clock_timer; + + // internal state + uint8_t m_data[8]; + int m_slave_address; + int m_scl; + int m_sdaw; + int m_sdar; + int m_state; + int m_bits; + int m_shift; + int m_devsel; + int m_mode_pointer; + int m_address; + int m_status; + + enum { STATE_IDLE, STATE_ADDRESS, STATE_MODE, STATE_DATAIN, STATE_DATAOUT }; +}; + +// device type definition +DECLARE_DEVICE_TYPE(PCF8573, pcf8573_device) + +#endif // MAME_MACHINE_PCF8573_H diff --git a/src/mame/drivers/accomm.cpp b/src/mame/drivers/accomm.cpp index 34194c84a3f..9f4c4bff070 100644 --- a/src/mame/drivers/accomm.cpp +++ b/src/mame/drivers/accomm.cpp @@ -8,7 +8,7 @@ Electron ULA emulation by Wilbert Pol Main CPU: 65C816 - Other chips: 6850 UART, 6522 VIA, SAA5240(video?), AM7910 modem, PCF0335(?), PCF8573P + Other chips: 6850 UART, 6522 VIA, SAA5240(teletext), AM7910(modem), PCF0335(dialler?), PCF8573P(RTC) ****************************************************************************/ @@ -17,9 +17,11 @@ #include "machine/6522via.h" #include "machine/6850acia.h" #include "machine/clock.h" +#include "machine/input_merger.h" #include "machine/mc6854.h" #include "machine/ram.h" #include "machine/nvram.h" +#include "machine/pcf8573.h" #include "machine/bankdev.h" #include "sound/beep.h" #include "bus/econet/econet.h" @@ -47,8 +49,11 @@ public: driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), m_maincpu_region(*this, "maincpu"), + m_irqs(*this, "irqs"), + m_screen(*this, "screen"), m_beeper(*this, "beeper"), m_ram(*this, RAM_TAG), + m_rtc(*this, "rtc"), m_via(*this, "via6522"), m_acia(*this, "acia"), m_acia_clock(*this, "acia_clock"), @@ -71,6 +76,8 @@ protected: virtual void machine_start() override; virtual void video_start() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + private: uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); @@ -83,15 +90,17 @@ private: void sheila_w(offs_t offset, uint8_t data); void accomm_palette(palette_device &palette) const; - INTERRUPT_GEN_MEMBER(vbl_int); void main_map(address_map &map); // devices required_device m_maincpu; required_memory_region m_maincpu_region; + required_device m_irqs; + required_device m_screen; required_device m_beeper; required_device m_ram; + required_device m_rtc; required_device m_via; required_device m_acia; required_device m_acia_clock; @@ -107,6 +116,11 @@ private: bool m_ch00rom_enabled; + enum + { + TIMER_SCANLINE_INTERRUPT + }; + /* ULA context */ struct ULA @@ -116,15 +130,14 @@ private: uint8_t rompage; uint16_t screen_start; uint16_t screen_base; - int screen_size; + uint16_t screen_size; uint16_t screen_addr; - uint8_t *vram; + int screen_dispend; int current_pal[16]; int communication_mode; int screen_mode; int shiftlock_mode; int capslock_mode; - // int scanline; /* tape reading related */ uint32_t tape_value; int tape_steps; @@ -136,27 +149,18 @@ private: uint8_t tape_byte; }; - ULA m_ula; int m_map4[256]; int m_map16[256]; -}; - -static const rgb_t electron_palette[8]= -{ - rgb_t(0x0ff,0x0ff,0x0ff), - rgb_t(0x000,0x0ff,0x0ff), - rgb_t(0x0ff,0x000,0x0ff), - rgb_t(0x000,0x000,0x0ff), - rgb_t(0x0ff,0x0ff,0x000), - rgb_t(0x000,0x0ff,0x000), - rgb_t(0x0ff,0x000,0x000), - rgb_t(0x000,0x000,0x000) + emu_timer *m_scanline_timer; }; void accomm_state::accomm_palette(palette_device &palette) const { - palette.set_pen_colors(0, electron_palette); + for (int i = 0; i < palette.entries(); i++) + { + palette.set_pen_color(i ^ 7, rgb_t(pal1bit(i >> 0), pal1bit(i >> 1), pal1bit(i >> 2))); + } } uint8_t accomm_state::read_keyboard1(offs_t offset) @@ -187,11 +191,6 @@ uint8_t accomm_state::read_keyboard2(offs_t offset) return data; } -INTERRUPT_GEN_MEMBER(accomm_state::vbl_int) -{ - interrupt_handler( INT_SET, INT_DISPLAY_END ); -} - void accomm_state::machine_reset() { m_ula.communication_mode = 0x04; @@ -201,11 +200,10 @@ void accomm_state::machine_reset() m_ula.screen_start = 0x3000; m_ula.screen_base = 0x3000; m_ula.screen_size = 0x8000 - 0x3000; - m_ula.screen_addr = 0; + m_ula.screen_addr = 0x3000; m_ula.tape_running = 0; m_ula.interrupt_status = 0x82; m_ula.interrupt_control = 0; - m_ula.vram = (uint8_t *)m_vram.target() + m_ula.screen_base; m_ch00rom_enabled = true; } @@ -217,6 +215,21 @@ void accomm_state::machine_start() m_ula.interrupt_status = 0x82; m_ula.interrupt_control = 0x00; + + save_item(STRUCT_MEMBER(m_ula, interrupt_status)); + save_item(STRUCT_MEMBER(m_ula, interrupt_control)); + save_item(STRUCT_MEMBER(m_ula, rompage)); + save_item(STRUCT_MEMBER(m_ula, screen_start)); + save_item(STRUCT_MEMBER(m_ula, screen_base)); + save_item(STRUCT_MEMBER(m_ula, screen_size)); + save_item(STRUCT_MEMBER(m_ula, screen_addr)); + save_item(STRUCT_MEMBER(m_ula, screen_dispend)); + save_item(STRUCT_MEMBER(m_ula, current_pal)); + save_item(STRUCT_MEMBER(m_ula, communication_mode)); + save_item(STRUCT_MEMBER(m_ula, screen_mode)); + save_item(STRUCT_MEMBER(m_ula, shiftlock_mode)); + save_item(STRUCT_MEMBER(m_ula, capslock_mode)); + save_item(NAME(m_ch00rom_enabled)); } void accomm_state::video_start() @@ -226,6 +239,8 @@ void accomm_state::video_start() m_map4[i] = ( ( i & 0x10 ) >> 3 ) | ( i & 0x01 ); m_map16[i] = ( ( i & 0x40 ) >> 3 ) | ( ( i & 0x10 ) >> 2 ) | ( ( i & 0x04 ) >> 1 ) | ( i & 0x01 ); } + m_scanline_timer = timer_alloc(TIMER_SCANLINE_INTERRUPT); + m_scanline_timer->adjust( m_screen->time_until_pos(0), 0, m_screen->scan_period() ); } void accomm_state::ch00switch_w(offs_t offset, uint8_t data) @@ -237,7 +252,8 @@ void accomm_state::ch00switch_w(offs_t offset, uint8_t data) inline uint8_t accomm_state::read_vram(uint16_t addr) { - return m_ula.vram[ addr % m_ula.screen_size ]; + if ( addr & 0x8000 ) addr -= m_ula.screen_size; + return m_vram[ addr ]; } inline void accomm_state::plot_pixel(bitmap_ind16 &bitmap, int x, int y, uint32_t color) @@ -253,9 +269,6 @@ uint32_t accomm_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap rectangle r = cliprect; r.sety(scanline, scanline); - if (scanline == 0) - m_ula.screen_addr = m_ula.screen_start - m_ula.screen_base; - /* set up palette */ int pal[16]; switch( m_ula.screen_mode ) @@ -439,11 +452,35 @@ uint32_t accomm_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap } break; } + if ( m_ula.screen_addr & 0x8000 ) + m_ula.screen_addr -= m_ula.screen_size; return 0; } +void accomm_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_SCANLINE_INTERRUPT) + { + switch (m_screen->vpos()) + { + case 99: + interrupt_handler( INT_SET, INT_RTC ); + break; + case 249: + case 255: + if ( m_screen->vpos() == m_ula.screen_dispend ) + interrupt_handler( INT_SET, INT_DISPLAY_END ); + break; + case 311: + m_ula.screen_addr = m_ula.screen_start; + break; + } + } +} + + uint8_t accomm_state::ram_r(offs_t offset) { uint8_t data = 0xff; @@ -499,17 +536,17 @@ uint8_t accomm_state::sheila_r(offs_t offset) data = m_ula.tape_byte; break; } - logerror( "ULA: read offset %02x: %02x\n", offset, data ); return data; } static const int palette_offset[4] = { 0, 4, 5, 1 }; -static const uint16_t screen_base[8] = { 0x3000, 0x3000, 0x3000, 0x4000, 0x5800, 0x5800, 0x6000, 0x5800 }; +static const uint16_t screen_base[8] = { 0x3000, 0x3000, 0x3000, 0x4000, 0x5800, 0x5800, 0x6000, 0x6000 }; +static const int mode_end[8] = { 255, 255, 255 ,249 ,255, 255, 249, 249 }; void accomm_state::sheila_w(offs_t offset, uint8_t data) { int i = palette_offset[(( offset >> 1 ) & 0x03)]; - logerror( "ULA: write offset %02x <- %02x\n", offset & 0x0f, data ); + switch( offset & 0x0f ) { case 0x00: /* Interrupt control */ @@ -519,11 +556,9 @@ void accomm_state::sheila_w(offs_t offset, uint8_t data) break; case 0x02: /* Screen start address #1 */ m_ula.screen_start = ( m_ula.screen_start & 0x7e00 ) | ( ( data & 0xe0 ) << 1 ); - logerror( "screen_start changed to %04x\n", m_ula.screen_start ); break; case 0x03: /* Screen start address #2 */ - m_ula.screen_start = ( m_ula.screen_start & 0x1c0 ) | ( ( data & 0x3f ) << 9 ); - logerror( "screen_start changed to %04x\n", m_ula.screen_start ); + m_ula.screen_start = ( m_ula.screen_start & 0x1ff ) | ( ( data & 0x3f ) << 9 ); break; case 0x04: /* Cassette data shift register */ break; @@ -585,23 +620,22 @@ void accomm_state::sheila_w(offs_t offset, uint8_t data) m_ula.screen_mode = ( data >> 3 ) & 0x07; m_ula.screen_base = screen_base[ m_ula.screen_mode ]; m_ula.screen_size = 0x8000 - m_ula.screen_base; - m_ula.vram = (uint8_t *)m_vram.target() + m_ula.screen_base; - logerror( "ULA: screen mode set to %d\n", m_ula.screen_mode ); + m_ula.screen_dispend = mode_end[ m_ula.screen_mode ]; m_ula.shiftlock_mode = !BIT(data, 6); m_shiftlock_led = m_ula.shiftlock_mode; m_ula.capslock_mode = BIT(data, 7); m_capslock_led = m_ula.capslock_mode; break; - case 0x08: case 0x0A: case 0x0C: case 0x0E: - // video_update - m_ula.current_pal[i+10] = (m_ula.current_pal[i+10] & 0x01) | (((data & 0x80) >> 5) | ((data & 0x08) >> 1)); + case 0x08: case 0x0a: case 0x0c: case 0x0e: + /* colour palette */ + m_ula.current_pal[i+10] = (m_ula.current_pal[i+10] & 0x01) | (((data & 0x80) >> 5) | ((data & 0x08) >> 2)); m_ula.current_pal[i+8] = (m_ula.current_pal[i+8] & 0x01) | (((data & 0x40) >> 4) | ((data & 0x04) >> 1)); m_ula.current_pal[i+2] = (m_ula.current_pal[i+2] & 0x03) | ((data & 0x20) >> 3); m_ula.current_pal[i] = (m_ula.current_pal[ i] & 0x03) | ((data & 0x10) >> 2); break; - case 0x09: case 0x0B: case 0x0D: case 0x0F: - // video_update + case 0x09: case 0x0b: case 0x0d: case 0x0f: + /* colour palette */ m_ula.current_pal[i+10] = (m_ula.current_pal[i+10] & 0x06) | ((data & 0x08) >> 3); m_ula.current_pal[i+8] = (m_ula.current_pal[i+8] & 0x06) | ((data & 0x04) >> 2); m_ula.current_pal[i+2] = (m_ula.current_pal[i+2] & 0x04) | (((data & 0x20) >> 4) | ((data & 0x02) >> 1)); @@ -840,15 +874,14 @@ void accomm_state::accomm(machine_config &config) { G65816(config, m_maincpu, 16_MHz_XTAL / 8); m_maincpu->set_addrmap(AS_PROGRAM, &accomm_state::main_map); - m_maincpu->set_vblank_int("screen", FUNC(accomm_state::vbl_int)); - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_refresh_hz(50.08); - screen.set_size(640, 312); - screen.set_visarea(0, 640 - 1, 0, 256 - 1); - screen.set_screen_update(FUNC(accomm_state::screen_update)); - screen.set_video_attributes(VIDEO_UPDATE_SCANLINE); - screen.set_palette("palette"); + INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set_inputline(m_maincpu, G65816_LINE_IRQ); + + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_raw(16_MHz_XTAL, 1024, 0, 640, 312, 0, 256); + m_screen->set_screen_update(FUNC(accomm_state::screen_update)); + m_screen->set_video_attributes(VIDEO_UPDATE_SCANLINE); + m_screen->set_palette("palette"); PALETTE(config, "palette", FUNC(accomm_state::accomm_palette), 16); @@ -863,18 +896,27 @@ void accomm_state::accomm(machine_config &config) SPEAKER(config, "mono").front_center(); BEEP(config, m_beeper, 300).add_route(ALL_OUTPUTS, "mono", 1.00); - /* rtc pcf8573 */ + /* rtc */ + PCF8573(config, m_rtc, 32.768_kHz_XTAL); + m_rtc->comp_cb().set(m_via, FUNC(via6522_device::write_cb1)); + + /* teletext */ + //SAA5240(config, m_cct); /* via */ VIA6522(config, m_via, 16_MHz_XTAL / 16); m_via->writepa_handler().set("cent_data_out", FUNC(output_latch_device::write)); m_via->ca2_handler().set("centronics", FUNC(centronics_device::write_strobe)); + m_via->readpb_handler().set(m_rtc, FUNC(pcf8573_device::sda_r)).bit(0); + m_via->writepb_handler().set(m_rtc, FUNC(pcf8573_device::sda_w)).bit(1).invert(); + m_via->writepb_handler().append(m_rtc, FUNC(pcf8573_device::scl_w)).bit(2).invert(); + m_via->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>)); /* acia */ ACIA6850(config, m_acia, 0); m_acia->txd_handler().set("serial", FUNC(rs232_port_device::write_txd)); m_acia->rts_handler().set("serial", FUNC(rs232_port_device::write_rts)); - m_acia->irq_handler().set_inputline("maincpu", G65816_LINE_IRQ); + m_acia->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<1>)); rs232_port_device &serial(RS232_PORT(config, "serial", default_rs232_devices, nullptr)); serial.rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd));