mirror of
https://github.com/holub/mame
synced 2025-04-16 13:34:55 +03:00
Add bus/adb for real ADB device emulation [O. Galibert, R. Belmont]
This commit is contained in:
parent
ec1cbee4c4
commit
e42e059b23
@ -190,6 +190,19 @@ if (BUSES["ADAMNET"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/bus/adb/adb.h,BUSES["ADB"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (BUSES["ADB"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/bus/adb/adb.cpp",
|
||||
MAME_DIR .. "src/devices/bus/adb/adb.h",
|
||||
MAME_DIR .. "src/devices/bus/adb/adbhle.cpp",
|
||||
MAME_DIR .. "src/devices/bus/adb/adbhle.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
|
@ -754,6 +754,7 @@ MACHINES["VRENDER0"] = true
|
||||
--BUSES["ABCKB"] = true
|
||||
--BUSES["ADAM"] = true
|
||||
--BUSES["ADAMNET"] = true
|
||||
--BUSES["ADB"] = true
|
||||
--BUSES["APF"] = true
|
||||
BUSES["AMIGA_KEYBOARD"] = true
|
||||
--BUSES["ARCADIA"] = true
|
||||
|
@ -824,6 +824,7 @@ BUSES["ABCKB"] = true
|
||||
BUSES["ACORN"] = true
|
||||
BUSES["ADAM"] = true
|
||||
BUSES["ADAMNET"] = true
|
||||
BUSES["ADB"] = true
|
||||
BUSES["APF"] = true
|
||||
BUSES["APRICOT_EXPANSION"] = true
|
||||
BUSES["APRICOT_KEYBOARD"] = true
|
||||
|
64
src/devices/bus/adb/adb.cpp
Normal file
64
src/devices/bus/adb/adb.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Olivier Galibert
|
||||
|
||||
// ADB - Apple Desktop Bus
|
||||
//
|
||||
// The serial desktop device bus from before USB was cool.
|
||||
//
|
||||
// Single data wire + poweron line, open collector
|
||||
|
||||
#include "emu.h"
|
||||
#include "adb.h"
|
||||
|
||||
#include "adbhle.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(ADB_CONNECTOR, adb_connector, "adbslot", "ADB connector")
|
||||
|
||||
adb_connector::adb_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, ADB_CONNECTOR, tag, owner, clock),
|
||||
device_single_card_slot_interface<adb_slot_card_interface>(mconfig, *this)
|
||||
{
|
||||
}
|
||||
|
||||
void adb_connector::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
adb_device *adb_connector::get_device()
|
||||
{
|
||||
adb_slot_card_interface *const connected = get_card_device();
|
||||
if (connected)
|
||||
return connected->device().subdevice<adb_device>(connected->m_adb.finder_tag());
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
adb_slot_card_interface::adb_slot_card_interface(const machine_config &mconfig, device_t &device, const char *adb_tag) :
|
||||
device_interface(device, "adb"),
|
||||
m_adb(*this, adb_tag)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
adb_device::adb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, type, tag, owner, clock),
|
||||
m_adb_cb(*this),
|
||||
m_poweron_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
void adb_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
void adb_device::device_reset()
|
||||
{
|
||||
m_adb_istate = true;
|
||||
m_adb_ostate = true;
|
||||
}
|
||||
|
||||
void adb_device::default_devices(device_slot_interface &device)
|
||||
{
|
||||
device.option_add("hle", ADB_HLE);
|
||||
}
|
73
src/devices/bus/adb/adb.h
Normal file
73
src/devices/bus/adb/adb.h
Normal file
@ -0,0 +1,73 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Olivier Galibert
|
||||
|
||||
// ADB - Apple Desktop Bus
|
||||
//
|
||||
// The serial desktop device bus from before USB was cool.
|
||||
//
|
||||
// Single data wire + poweron line, open collector
|
||||
|
||||
#ifndef MAME_BUS_ADB_ADB_H
|
||||
#define MAME_BUS_ADB_ADB_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class adb_device;
|
||||
class adb_slot_card_interface;
|
||||
|
||||
class adb_connector: public device_t, public device_single_card_slot_interface<adb_slot_card_interface>
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
adb_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, bool fixed = false)
|
||||
: adb_connector(mconfig, tag, owner, 0)
|
||||
{
|
||||
option_reset();
|
||||
opts(*this);
|
||||
set_default_option(dflt);
|
||||
set_fixed(fixed);
|
||||
}
|
||||
|
||||
adb_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
virtual ~adb_connector() = default;
|
||||
|
||||
adb_device *get_device();
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
};
|
||||
|
||||
class adb_slot_card_interface : public device_interface
|
||||
{
|
||||
friend class adb_connector;
|
||||
|
||||
public:
|
||||
adb_slot_card_interface(const machine_config &mconfig, device_t &device, const char *adb_tag);
|
||||
|
||||
private:
|
||||
required_device<adb_device> m_adb;
|
||||
};
|
||||
|
||||
class adb_device: public device_t
|
||||
{
|
||||
public:
|
||||
virtual void adb_w(int state) = 0;
|
||||
auto adb_r() { return m_adb_cb.bind(); }
|
||||
auto poweron_r() { return m_poweron_cb.bind(); }
|
||||
|
||||
static void default_devices(device_slot_interface &device);
|
||||
|
||||
protected:
|
||||
adb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
devcb_write_line m_adb_cb;
|
||||
devcb_write_line m_poweron_cb;
|
||||
bool m_adb_istate, m_adb_ostate;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(ADB_CONNECTOR, adb_connector)
|
||||
|
||||
#endif
|
45
src/devices/bus/adb/adbhle.cpp
Normal file
45
src/devices/bus/adb/adbhle.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Olivier Galibert
|
||||
|
||||
// ADB - Apple Desktop Bus
|
||||
//
|
||||
// Generic HLE
|
||||
|
||||
#include "emu.h"
|
||||
#include "adbhle.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(ADB_HLE, adb_hle_device, "adbhle", "ADB HLE")
|
||||
|
||||
adb_hle_device::adb_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
adb_device(mconfig, ADB_HLE, tag, owner, clock),
|
||||
adb_slot_card_interface(mconfig, *this, DEVICE_SELF)
|
||||
{
|
||||
}
|
||||
|
||||
void adb_hle_device::device_start()
|
||||
{
|
||||
adb_device::device_start();
|
||||
|
||||
save_item(NAME(m_last_state));
|
||||
save_item(NAME(m_last_state_time));
|
||||
}
|
||||
|
||||
void adb_hle_device::device_reset()
|
||||
{
|
||||
adb_device::device_reset();
|
||||
m_last_state = true;
|
||||
m_last_state_time = machine().time();
|
||||
}
|
||||
|
||||
void adb_hle_device::adb_w(int state)
|
||||
{
|
||||
if(m_last_state != state) {
|
||||
attotime delta = machine().time() - m_last_state_time;
|
||||
u32 dt = delta.as_ticks(1000000);
|
||||
|
||||
logerror("level %d duration %6d us\n", m_last_state, dt);
|
||||
|
||||
m_last_state = state;
|
||||
m_last_state_time = machine().time();
|
||||
}
|
||||
}
|
33
src/devices/bus/adb/adbhle.h
Normal file
33
src/devices/bus/adb/adbhle.h
Normal file
@ -0,0 +1,33 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Olivier Galibert
|
||||
|
||||
// ADB - Apple Desktop Bus
|
||||
//
|
||||
// Generic HLE
|
||||
|
||||
#ifndef MAME_BUS_ADB_ADBHLE_H
|
||||
#define MAME_BUS_ADB_ADBHLE_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "adb.h"
|
||||
|
||||
class adb_hle_device : public adb_device, public adb_slot_card_interface
|
||||
{
|
||||
public:
|
||||
adb_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual void adb_w(int state) override;
|
||||
|
||||
private:
|
||||
bool m_last_state;
|
||||
attotime m_last_state_time;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(ADB_HLE, adb_hle_device)
|
||||
|
||||
#endif
|
@ -97,21 +97,49 @@ const tiny_rom_entry *egret_device::device_rom_region() const
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
#if USE_BUS_ADB
|
||||
void egret_device::adb_w(int id, int state)
|
||||
{
|
||||
m_adb_device_out[id] = state;
|
||||
adb_change();
|
||||
}
|
||||
|
||||
void egret_device::adb_poweron_w(int id, int state)
|
||||
{
|
||||
m_adb_device_poweron[id] = state;
|
||||
}
|
||||
|
||||
void egret_device::adb_change()
|
||||
{
|
||||
bool adb = m_adb_out & m_adb_device_out[0] & m_adb_device_out[1];
|
||||
logerror("adb c:%d 1:%d 2:%d -> %d (%02x %02x)\n", m_adb_out, m_adb_device_out[0], m_adb_device_out[1], adb, ddrs[0], ports[0]);
|
||||
for (int i = 0; i != 2; i++)
|
||||
if (m_adb_device[i])
|
||||
{
|
||||
m_adb_device[i]->adb_w(adb);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void egret_device::send_port(uint8_t offset, uint8_t data)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // port A
|
||||
/* printf("ADB:%d DFAC:%d PowerEnable:%d\n",
|
||||
case 0: // port A
|
||||
/* printf("ADB:%d DFAC:%d PowerEnable:%d\n",
|
||||
(data & 0x80) ? 1 : 0,
|
||||
(data & 0x10) ? 1 : 0,
|
||||
(data & 0x02) ? 1 : 0);*/
|
||||
|
||||
if ((data & 0x80) != last_adb)
|
||||
{
|
||||
m_adb_dtime = (int)(machine().time().as_ticks(1000000) - last_adb_time);
|
||||
/*
|
||||
#if USE_BUS_ADB
|
||||
// the line goes to a mosfet pulling the adb data line to graound, hence the inversion
|
||||
m_adb_out = !(data & 0x80);
|
||||
adb_change();
|
||||
#else
|
||||
if ((data & 0x80) != last_adb)
|
||||
{
|
||||
m_adb_dtime = (int)(machine().time().as_ticks(1000000) - last_adb_time);
|
||||
/*
|
||||
if (data & 0x80)
|
||||
{
|
||||
printf("EG ADB: 1->0 time %d\n", m_adb_dtime);
|
||||
@ -121,14 +149,15 @@ void egret_device::send_port(uint8_t offset, uint8_t data)
|
||||
printf("EG ADB: 0->1 time %d\n", m_adb_dtime);
|
||||
}
|
||||
*/
|
||||
// allow the linechange handler to override us
|
||||
adb_in = (data & 0x80) ? true : false;
|
||||
// allow the linechange handler to override us
|
||||
adb_in = (data & 0x80) ? true : false;
|
||||
|
||||
write_linechange(((data & 0x80) >> 7) ^ 1);
|
||||
write_linechange(((data & 0x80) >> 7) ^ 1);
|
||||
|
||||
last_adb = data & 0x80;
|
||||
last_adb_time = machine().time().as_ticks(1000000);
|
||||
last_adb = data & 0x80;
|
||||
last_adb_time = machine().time().as_ticks(1000000);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 1: // port B
|
||||
@ -205,8 +234,12 @@ uint8_t egret_device::ports_r(offs_t offset)
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // port A
|
||||
#if USE_BUS_ADB
|
||||
incoming |= (m_adb_out & m_adb_device_out[0] & m_adb_device_out[1]) ? 0x40 : 0;
|
||||
incoming |= (m_adb_device_poweron[0] & m_adb_device_poweron[1]) ? 0x04 : 0;
|
||||
#else
|
||||
incoming |= adb_in ? 0x40 : 0;
|
||||
|
||||
#endif
|
||||
if (egret_controls_power)
|
||||
{
|
||||
incoming |= 0x02; // indicate soft power, indicate chassis switch on
|
||||
@ -327,12 +360,15 @@ void egret_device::pram_w(offs_t offset, uint8_t data)
|
||||
|
||||
egret_device::egret_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, EGRET, tag, owner, clock),
|
||||
device_nvram_interface(mconfig, *this),
|
||||
write_reset(*this),
|
||||
write_linechange(*this),
|
||||
write_via_clock(*this),
|
||||
write_via_data(*this),
|
||||
m_maincpu(*this, EGRET_CPU_TAG)
|
||||
device_nvram_interface(mconfig, *this),
|
||||
write_reset(*this),
|
||||
write_linechange(*this),
|
||||
write_via_clock(*this),
|
||||
write_via_data(*this),
|
||||
m_maincpu(*this, EGRET_CPU_TAG)
|
||||
#if USE_BUS_ADB
|
||||
, m_adb_connector{{*this, ":adb1"}, {*this, finder_base::DUMMY_TAG}}
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@ -347,6 +383,18 @@ void egret_device::device_start()
|
||||
write_via_clock.resolve_safe();
|
||||
write_via_data.resolve_safe();
|
||||
|
||||
#if USE_BUS_ADB
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
m_adb_device[i] = m_adb_connector[i] ? m_adb_connector[i]->get_device() : nullptr;
|
||||
if (m_adb_device[i])
|
||||
{
|
||||
m_adb_device[i]->adb_r().set([this, i](int state) { adb_w(i, state); });
|
||||
m_adb_device[i]->poweron_r().set([this, i](int state) { adb_poweron_w(i, state); });
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m_timer = timer_alloc(0, nullptr);
|
||||
save_item(NAME(ddrs[0]));
|
||||
save_item(NAME(ddrs[1]));
|
||||
@ -369,6 +417,11 @@ void egret_device::device_start()
|
||||
save_item(NAME(pram_loaded));
|
||||
save_item(NAME(pram));
|
||||
save_item(NAME(disk_pram));
|
||||
#if USE_BUS_ADB
|
||||
save_item(NAME(m_adb_out));
|
||||
save_item(NAME(m_adb_device_out));
|
||||
save_item(NAME(m_adb_device_poweron));
|
||||
#endif
|
||||
|
||||
uint8_t *rom = device().machine().root_device().memregion(device().subtag(EGRET_CPU_TAG))->base();
|
||||
|
||||
@ -388,6 +441,11 @@ void egret_device::device_reset()
|
||||
ddrs[0] = ddrs[1] = ddrs[2] = 0;
|
||||
ports[0] = ports[1] = ports[2] = 0;
|
||||
|
||||
#if USE_BUS_ADB
|
||||
m_adb_device_out[0] = m_adb_device_out[1] = true;
|
||||
m_adb_device_poweron[0] = m_adb_device_poweron[1] = true;
|
||||
#endif
|
||||
|
||||
m_timer->adjust(attotime::never);
|
||||
|
||||
egret_controls_power = false; // set to hard power control
|
||||
|
@ -5,7 +5,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define USE_BUS_ADB (0)
|
||||
|
||||
#if USE_BUS_ADB
|
||||
#include "bus/adb/adb.h"
|
||||
#endif
|
||||
|
||||
//**************************************************************************
|
||||
// MACROS / CONSTANTS
|
||||
@ -59,6 +63,12 @@ public:
|
||||
uint8_t pram_r(offs_t offset);
|
||||
void pram_w(offs_t offset, uint8_t data);
|
||||
|
||||
#if USE_BUS_ADB
|
||||
void adb_w(int id, int state);
|
||||
void adb_poweron_w(int id, int state);
|
||||
void adb_change();
|
||||
#endif
|
||||
|
||||
// interface routines
|
||||
uint8_t get_xcvr_session() { return xcvr_session; }
|
||||
void set_via_full(uint8_t val) { via_full = val; }
|
||||
@ -107,6 +117,14 @@ private:
|
||||
uint8_t pram[0x100], disk_pram[0x100];
|
||||
bool pram_loaded;
|
||||
|
||||
#if USE_BUS_ADB
|
||||
optional_device <adb_connector> m_adb_connector[2];
|
||||
adb_device *m_adb_device[2];
|
||||
bool m_adb_device_out[2];
|
||||
bool m_adb_device_poweron[2];
|
||||
bool m_adb_out;
|
||||
#endif
|
||||
|
||||
void send_port(uint8_t offset, uint8_t data);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user