atronic.cpp: Add more onboard devices, including new PCF8584 skeleton (nw)

This commit is contained in:
AJR 2019-08-17 22:38:28 -04:00
parent ab68b239f1
commit de57ef7b97
6 changed files with 400 additions and 4 deletions

View File

@ -2265,6 +2265,18 @@ if (MACHINES["PCF8583"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/machine/pcf8584.h,MACHINES["PCF8584"] = true
---------------------------------------------------
if (MACHINES["PCF8584"]~=null) then
files {
MAME_DIR .. "src/devices/machine/pcf8584.cpp",
MAME_DIR .. "src/devices/machine/pcf8584.h",
}
end
---------------------------------------------------
--
--@src/devices/machine/pcf8593.h,MACHINES["PCF8593"] = true

View File

@ -446,7 +446,7 @@ MACHINES["DS1204"] = true
MACHINES["DS1205"] = true
MACHINES["DS1302"] = true
--MACHINES["DS1315"] = true
--MACHINES["DS1386"] = true
MACHINES["DS1386"] = true
MACHINES["DS17X85"] = true
MACHINES["DS1994"] = true
MACHINES["DS2401"] = true
@ -558,6 +558,8 @@ MACHINES["OUTPUT_LATCH"] = true
MACHINES["PC_FDC"] = true
MACHINES["PC_LPT"] = true
--MACHINES["PCCARD"] = true
--MACHINES["PCF8583"] = true
MACHINES["PCF8584"] = true
MACHINES["PCF8593"] = true
MACHINES["PCI"] = true
MACHINES["PCKEYBRD"] = true

View File

@ -568,6 +568,7 @@ MACHINES["PC_FDC"] = true
MACHINES["PC_LPT"] = true
MACHINES["PCCARD"] = true
MACHINES["PCF8583"] = true
--MACHINES["PCF8584"] = true
MACHINES["PCF8593"] = true
MACHINES["PCI"] = true
MACHINES["PCKEYBRD"] = true

View File

@ -0,0 +1,245 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/**********************************************************************
Philips PCF8584 I²C Bus Controller
This is a comprehensive protocol interface chip for Philips' I²C
serial bus, supporting master and slave modes for both receiving
and transmitting data. The register interface is similar but not
identical to that provided by certain Philips 80C51-derived
microcontrollers.
TODO: actually implement the protocol
**********************************************************************/
#include "emu.h"
#include "pcf8584.h"
#define VERBOSE 1
#include "logmacro.h"
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// device type definition
DEFINE_DEVICE_TYPE(PCF8584, pcf8584_device, "pcf8584", "PCF8584 I2C Bus Controller")
//**************************************************************************
// LOOKUP TABLES
//**************************************************************************
// prescalers based on 1.5 MHz internal frequency
const u32 pcf8584_device::s_prescaler[4] = { 50, 100, 400, 3000 };
// dividers for clock input
const u32 pcf8584_device::s_divider[8] = { 2, 2, 2, 2, 3, 4, 5, 8 };
// debugging strings
const char *const pcf8584_device::s_nominal_clock[8] = { "3", "3", "3", "3", "4.43", "6", "8", "12" };
const char *const pcf8584_device::s_bus_function[4] = { "NOP", "stop", "start", "data chaining" };
//**************************************************************************
// DEVICE CONSTRUCTION AND INITIALIZATION
//**************************************************************************
//-------------------------------------------------
// pcf8584_device - constructor
//-------------------------------------------------
pcf8584_device::pcf8584_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, PCF8584, tag, owner, clock)
, m_sda_callback(*this)
, m_sda_out_callback(*this)
, m_scl_callback(*this)
, m_int_callback(*this)
, m_68k_bus(false)
, m_s0_data_buffer(0)
, m_s0_shift_register(0)
, m_s0_own_address(0)
, m_s1_status(0)
, m_s1_control(0)
, m_s2_clock(0)
, m_s3_vector(0)
{
}
//-------------------------------------------------
// device_resolve_objects - resolve objects that
// may be needed for other devices to set
// initial conditions at start time
//-------------------------------------------------
void pcf8584_device::device_resolve_objects()
{
m_sda_callback.resolve_safe(1);
m_sda_out_callback.resolve_safe();
m_scl_callback.resolve_safe();
m_int_callback.resolve_safe();
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void pcf8584_device::device_start()
{
// register internal state
save_item(NAME(m_s0_data_buffer));
save_item(NAME(m_s0_shift_register));
save_item(NAME(m_s0_own_address));
save_item(NAME(m_s1_status));
save_item(NAME(m_s1_control));
save_item(NAME(m_s2_clock));
save_item(NAME(m_s3_vector));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void pcf8584_device::device_reset()
{
// reset all flags except for PIN
m_s1_status = 0x80;
m_s1_control = 0x00;
// vector isn't actually set to 0x0f until R/_W is pulled low without _CS, but who's counting?
m_s3_vector = m_68k_bus ? 0x0f : 0x00;
}
//**************************************************************************
// REGISTER INTERFACE
//**************************************************************************
//-------------------------------------------------
// set_shift_register - write data to S0
//-------------------------------------------------
void pcf8584_device::set_shift_register(u8 data)
{
LOG("%s: Shift register = %s%02XH\n", machine().describe_context(), data >= 0xa0 ? "0" : "", data);
m_s0_shift_register = data;
}
//-------------------------------------------------
// set_own_address - write data to S0'
//-------------------------------------------------
void pcf8584_device::set_own_address(u8 data)
{
LOG("%s: Own address = %s%02XH\n", machine().describe_context(), (data & 0x7f) >= 0x60 ? "0" : "", (data << 1) & 0xfe);
m_s0_own_address = data;
}
//-------------------------------------------------
// set_control - write data to S1
//-------------------------------------------------
void pcf8584_device::set_control(u8 data)
{
if (BIT(data, 7) != BIT(m_s1_status, 7))
{
LOG("%s: PIN %sactive\n", machine().describe_context(), BIT(data, 7) ? "in" : "");
if (BIT(data, 7))
m_s1_status = 0x80;
else
m_s1_status &= 0x7f;
}
if (BIT(data, 6) != BIT(m_s1_control, 6))
LOG("%s: Serial output %sabled%s\n", machine().describe_context(), BIT(data, 6) ? "en" : "dis",
(data & 0x60) == 0x60 ? " (4-wire)" : "");
if (BIT(data, 3) != BIT(m_s1_control, 3))
LOG("%s: Interrupt output %sabled\n", machine().describe_context(), BIT(data, 3) ? "en" : "dis");
if ((data & 0x06) != (m_s1_control & 0x06))
LOG("%s: Bus function = %s\n", machine().describe_context(), s_bus_function[(data & 0x06) >> 1]);
if (BIT(data, 0) != BIT(m_s1_control, 0))
LOG("%s: Acknowledge pulse %sabled\n", machine().describe_context(), BIT(data, 0) ? "en" : "dis");
m_s1_control = data & 0x7f;
}
//-------------------------------------------------
// set_clock_frequency - write data to S2
//-------------------------------------------------
void pcf8584_device::set_clock_frequency(u8 data)
{
LOG("%s: SCL frequency = %.2f kHz (fCLK is nominally %s MHz)\n", machine().describe_context(),
(clocks_to_attotime(s_divider[(data & 0x1c) >> 2] * s_prescaler[data & 0x03]) / 3).as_hz() / 1000.0,
s_nominal_clock[(data & 0x1c) >> 2]);
m_s2_clock = data & 0x1f;
}
//-------------------------------------------------
// set_vector - write data to S3
//-------------------------------------------------
void pcf8584_device::set_vector(u8 data)
{
LOG("%s: Interrupt vector = %s%02XH\n", machine().describe_context(), data >= 0xa0 ? "0" : "", data);
m_s3_vector = data;
}
//-------------------------------------------------
// read - input from register to bus
//-------------------------------------------------
u8 pcf8584_device::read(offs_t offset)
{
if (BIT(offset, 0))
return eso() ? m_s1_status : m_s1_control | (m_s1_status & 0x80);
else if (es2() && !es1())
return m_s3_vector;
else if (eso())
return m_s0_data_buffer;
else if (es1())
return m_s2_clock;
else
return m_s0_own_address;
}
//-------------------------------------------------
// write - output from bus to register
//-------------------------------------------------
void pcf8584_device::write(offs_t offset, u8 data)
{
if (BIT(offset, 0))
set_control(data);
else if (es2() && !es1())
set_vector(data);
else if (eso())
set_shift_register(data);
else if (es1())
set_clock_frequency(data);
else
set_own_address(data);
}
//-------------------------------------------------
// iack - acknowledge interrupt with vector
//-------------------------------------------------
IRQ_CALLBACK_MEMBER(pcf8584_device::iack)
{
return m_s3_vector;
}

View File

@ -0,0 +1,101 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/**********************************************************************
Philips PCF8584 I²C Bus Controller
***********************************************************************
____ ____
CLK 1 |* \_/ | 20 Vdd
(SDA OUT) SDA 2 | | 19 _RESET/_STROBE
(SCL IN) SCL 3 | | 18 _WR (R/_W)
(SDA IN) _IACK 4 | | 17 _CS
(SCL OUT) _INT 5 | | 16 _RD (_DTACK)
A0 6 | PCF8584 | 15 DB7
DB0 7 | | 14 DB6
DB1 8 | | 13 DB5
DB2 9 | | 12 DB4
Vss 10 |___________| 11 DB3
**********************************************************************/
#ifndef MAME_MACHINE_PCF8584_H
#define MAME_MACHINE_PCF8584_H 1
#pragma once
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> pcf8584_device
class pcf8584_device : public device_t
{
static const u32 s_prescaler[4];
static const u32 s_divider[8];
static const char *const s_nominal_clock[8];
static const char *const s_bus_function[4];
public:
// device type constructor
pcf8584_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// callback configuration
auto sda_cb() { return m_sda_callback.bind(); }
auto sda_out_cb() { return m_sda_out_callback.bind(); }
auto scl_cb() { return m_scl_callback.bind(); }
auto int_cb() { return m_int_callback.bind(); }
// bus type configuration
void set_80xx_bus() { m_68k_bus = false; }
void set_68000_bus() { m_68k_bus = true; }
// CPU interface
u8 read(offs_t offset);
void write(offs_t offset, u8 data);
IRQ_CALLBACK_MEMBER(iack);
protected:
// device-specific overrides
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
private:
// internal helpers
bool eso() const { return BIT(m_s1_control, 6); }
bool es1() const { return BIT(m_s1_control, 5); }
bool es2() const { return BIT(m_s1_control, 4); }
bool eni() const { return BIT(m_s1_control, 3); }
// write helpers
void set_shift_register(u8 data);
void set_own_address(u8 data);
void set_control(u8 data);
void set_clock_frequency(u8 data);
void set_vector(u8 data);
// callback objects
devcb_read_line m_sda_callback;
devcb_write_line m_sda_out_callback;
devcb_write_line m_scl_callback;
devcb_write_line m_int_callback;
// misc. parameters
bool m_68k_bus;
// internal registers
u8 m_s0_data_buffer;
u8 m_s0_shift_register;
u8 m_s0_own_address;
u8 m_s1_status;
u8 m_s1_control;
u8 m_s2_clock;
u8 m_s3_vector;
};
// device type declaration
DECLARE_DEVICE_TYPE(PCF8584, pcf8584_device)
#endif // MAME_MACHINE_PCF8584_H

View File

@ -317,6 +317,9 @@ Markings bottom: 6 470.5020 00.07
#include "emu.h"
#include "cpu/z180/z180.h"
#include "cpu/tms34010/tms34010.h"
#include "machine/ds1386.h"
#include "machine/pcf8584.h"
#include "machine/z80scc.h"
#include "emupal.h"
#include "screen.h"
#include "video/ramdac.h"
@ -336,6 +339,11 @@ public:
void atronic(machine_config &config);
private:
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
u8 serial_r();
void serial_w(u8 data);
void atronic_map(address_map &map);
void atronic_portmap(address_map &map);
@ -357,18 +365,39 @@ private:
};
u32 atronic_state::screen_update( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect )
{
return 0;
}
u8 atronic_state::serial_r()
{
// bit 3 = serial input?
return 0xff;
}
void atronic_state::serial_w(u8 data)
{
// bits 7 & 6 = serial clock and data?
}
void atronic_state::atronic_map(address_map &map)
{
map(0x00000, 0x7ffff).rom();
map(0xf8000, 0xfffff).ram();
map(0xf8000, 0xfffff).rw("timekpr", FUNC(ds1386_32k_device::data_r), FUNC(ds1386_32k_device::data_w));
}
void atronic_state::atronic_portmap(address_map &map)
{
// ADDRESS_MAP_GLOBAL_MASK(0xff)
map.unmap_value_high();
map(0x00, 0x3f).ram();
map(0x0000, 0x003f).noprw(); // internal registers
map(0x0068, 0x0069).rw("i2cbc", FUNC(pcf8584_device::read), FUNC(pcf8584_device::write));
map(0x0074, 0x0074).r(FUNC(atronic_state::serial_r));
map(0x0078, 0x007b).rw("scc", FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w));
map(0x0270, 0x0270).w(FUNC(atronic_state::serial_w));
}
@ -440,6 +469,12 @@ void atronic_state::atronic(machine_config &config)
m_maincpu->set_addrmap(AS_IO, &atronic_state::atronic_portmap);
m_maincpu->set_vblank_int("screen", FUNC(atronic_state::irq0_line_hold));
DS1386_32K(config, "timekpr", 32768);
PCF8584(config, "i2cbc", 3000000);
SCC85C30(config, "scc", 5000000);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(VIDEO_CLOCK/2, 640, 0, 512, 257, 0, 224); // ??
m_screen->set_screen_update("tms", FUNC(tms34020_device::tms340x0_rgb32));