accomm: Added PCF8573 RTC.

- Added RTC interrupt, fixes TIME function.
- Realigned video handling with the Electron.
This commit is contained in:
Nigel Barnes 2020-12-04 12:13:54 +00:00
parent 84264c5efb
commit f25283c81f
5 changed files with 595 additions and 53 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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));