summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorGravatarGravatar Nigel Barnes <Pernod70@users.noreply.github.com>2020-12-04 12:13:54 +0000
committerGravatarGravatar Nigel Barnes <Pernod70@users.noreply.github.com>2020-12-04 12:23:11 +0000
commitf25283c81f9bbe7b5fa58a90aa212c674359ce62 (patch)
tree61eef9ffb9b01d1c32deb497e203224bcb8f5873
parent84264c5efb9a2e642436dd7db53364b87d7ac560 (diff)
accomm: Added PCF8573 RTC.
- Added RTC interrupt, fixes TIME function. - Realigned video handling with the Electron.
-rw-r--r--scripts/src/machine.lua12
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/machine/pcf8573.cpp356
-rw-r--r--src/devices/machine/pcf8573.h131
-rw-r--r--src/mame/drivers/accomm.cpp148
5 files changed, 595 insertions, 53 deletions
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
@@ -2432,6 +2432,18 @@ 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<g65816_device> m_maincpu;
required_memory_region m_maincpu_region;
+ required_device<input_merger_device> m_irqs;
+ required_device<screen_device> m_screen;
required_device<beep_device> m_beeper;
required_device<ram_device> m_ram;
+ required_device<pcf8573_device> m_rtc;
required_device<via6522_device> m_via;
required_device<acia6850_device> m_acia;
required_device<clock_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));