Modernized upd7002 device. (nw)

This commit is contained in:
Ivan Vangelista 2014-01-04 13:57:27 +00:00
parent e68c36a77a
commit 9bf65a23b5
5 changed files with 159 additions and 188 deletions

View File

@ -10,112 +10,126 @@
#include "emu.h"
#include "upd7002.h"
#include "devlegcy.h"
struct uPD7002_t
/* Device Interface */
const device_type UPD7002 = &device_creator<upd7002_device>;
upd7002_device::upd7002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, UPD7002, "uPD7002", tag, owner, clock, "upd7002", __FILE__)
{
/* Pointer to our interface */
const uPD7002_interface *intf;
}
/* Status Register
D0 and D1 define the currently selected input channel
D2 flag output
D3 0 = 8 bit mode 1 = 12 bit mode
D4 2nd MSB of conversion
D5 MSB of conversion
D6 0 = busy, 1 = not busy (~busy)
D7 0 = conversion completed, 1 = conversion not completed (~EOC)
*/
int status;
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
/* High data byte
This byte contains the 8 most significant bits of the analogue to digital conversion. */
int data1;
void upd7002_device::device_config_complete()
{
// inherit a copy of the static data
const upd7002_interface *intf = reinterpret_cast<const upd7002_interface *>(static_config());
if (intf != NULL)
*static_cast<upd7002_interface *>(this) = *intf;
/* Low data byte
In 12 bit mode: Bits 7 to 4 define the four low order bits of the conversion.
In 8 bit mode. All bits 7 to 4 are inaccurate.
Bits 3 to 0 are always set to low. */
int data0;
// or initialize to defaults if none provided
else
{
get_analogue_func = NULL;
eoc_func = NULL;
}
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
/* temporary store of the next A to D conversion */
int digitalvalue;
void upd7002_device::device_start()
{
// register for state saving
save_item(NAME(m_status));
save_item(NAME(m_data1));
save_item(NAME(m_data0));
save_item(NAME(m_digitalvalue));
save_item(NAME(m_conversion_counter));
}
/* this counter is used to check a full end of conversion has been reached
if the uPD7002 is half way through one conversion and a new conversion is requested
the counter at the end of the first conversion will not match and not be processed
only then at the end of the second conversion will the conversion complete function run */
int conversion_counter;
};
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void upd7002_device::device_reset()
{
m_status = 0;
m_data1 = 0;
m_data0 = 0;
m_digitalvalue = 0;
m_conversion_counter = 0;
}
/*****************************************************************************
Implementation
*****************************************************************************/
INLINE uPD7002_t *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == UPD7002);
return (uPD7002_t *)downcast<uPD7002_device *>(device)->token();
}
READ8_DEVICE_HANDLER ( uPD7002_EOC_r )
READ8_MEMBER( upd7002_device::eoc_r )
{
uPD7002_t *uPD7002 = get_safe_token(device);
return (uPD7002->status>>7)&0x01;
return (m_status>>7)&0x01;
}
static TIMER_CALLBACK(uPD7002_conversioncomplete)
void upd7002_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
device_t *device = (device_t *)ptr;
uPD7002_t *uPD7002 = get_safe_token(device);
int counter_value = param;
if (counter_value==uPD7002->conversion_counter)
switch (id)
{
// this really always does a 12 bit conversion
uPD7002->data1 = uPD7002->digitalvalue>>8;
uPD7002->data0 = uPD7002->digitalvalue&0xf0;
case TIMER_CONVERSION_COMPLETE:
{
int counter_value = param;
if (counter_value==m_conversion_counter)
{
// this really always does a 12 bit conversion
m_data1 = m_digitalvalue>>8;
m_data0 = m_digitalvalue&0xf0;
// set the status register with top 2 MSB, not busy and conversion complete
uPD7002->status = (uPD7002->status & 0x0f)|((uPD7002->data1 & 0xc0)>>2)|0x40;
// set the status register with top 2 MSB, not busy and conversion complete
m_status = (m_status & 0x0f)|((m_data1 & 0xc0)>>2)|0x40;
// call the EOC function with EOC from status
// uPD7002_EOC_r(0) this has just been set to 0
if (uPD7002->intf->EOC_func) (uPD7002->intf->EOC_func)(device,0);
uPD7002->conversion_counter=0;
// call the EOC function with EOC from status
// eoc_r(0) this has just been set to 0
if (eoc_func) (eoc_func)(this,0);
m_conversion_counter=0;
}
break;
}
default:
assert_always(FALSE, "Unknown id in upd7002_device::device_timer");
}
}
READ8_DEVICE_HANDLER ( uPD7002_r )
READ8_MEMBER( upd7002_device::read )
{
uPD7002_t *uPD7002 = get_safe_token(device);
switch(offset&0x03)
{
case 0:
return uPD7002->status;
return m_status;
case 1:
return uPD7002->data1;
return m_data1;
case 2: case 3:
return uPD7002->data0;
return m_data0;
}
return 0;
}
WRITE8_DEVICE_HANDLER ( uPD7002_w )
WRITE8_MEMBER( upd7002_device::write )
{
uPD7002_t *uPD7002 = get_safe_token(device);
/* logerror("write to uPD7002 $%02X = $%02X\n",offset,data); */
switch(offset&0x03)
@ -135,28 +149,28 @@ WRITE8_DEVICE_HANDLER ( uPD7002_w )
*/
/* set D6=0 busy ,D7=1 conversion not complete */
uPD7002->status=(data & 0x0f) | 0x80;
m_status=(data & 0x0f) | 0x80;
// call the EOC function with EOC from status
// uPD7002_EOC_r(0) this has just been set to 1
if (uPD7002->intf->EOC_func) uPD7002->intf->EOC_func(device, 1);
// eoc_r(0) this has just been set to 1
if (eoc_func) eoc_func(this, 1);
/* the uPD7002 works by sampling the analogue value at the start of the conversion
so it is read hear and stored until the end of the A to D conversion */
// this function should return a 16 bit value.
uPD7002->digitalvalue = uPD7002->intf->get_analogue_func(device, uPD7002->status & 0x03);
m_digitalvalue = get_analogue_func(this, m_status & 0x03);
uPD7002->conversion_counter++;
m_conversion_counter++;
// call a timer to start the conversion
if (uPD7002->status & 0x08)
if (m_status & 0x08)
{
// 12 bit conversion takes 10ms
space.machine().scheduler().timer_set(attotime::from_msec(10), FUNC(uPD7002_conversioncomplete), uPD7002->conversion_counter, (void *)device);
timer_set(attotime::from_msec(10), TIMER_CONVERSION_COMPLETE, m_conversion_counter);
} else {
// 8 bit conversion takes 4ms
space.machine().scheduler().timer_set(attotime::from_msec(4), FUNC(uPD7002_conversioncomplete), uPD7002->conversion_counter, (void *)device);
timer_set(attotime::from_msec(4), TIMER_CONVERSION_COMPLETE, m_conversion_counter);
}
break;
@ -172,75 +186,3 @@ WRITE8_DEVICE_HANDLER ( uPD7002_w )
break;
}
}
/* Device Interface */
static DEVICE_START( uPD7002 )
{
uPD7002_t *uPD7002 = get_safe_token(device);
// validate arguments
assert(device != NULL);
assert(device->tag() != NULL);
assert(device->static_config() != NULL);
uPD7002->intf = (const uPD7002_interface*)device->static_config();
uPD7002->status = 0;
uPD7002->data1 = 0;
uPD7002->data0 = 0;
uPD7002->digitalvalue = 0;
uPD7002->conversion_counter = 0;
// register for state saving
state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->status);
state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->data1);
state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->data0);
state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->digitalvalue);
state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->conversion_counter);
}
static DEVICE_RESET( uPD7002 )
{
uPD7002_t *uPD7002 = get_safe_token(device);
uPD7002->status = 0;
uPD7002->data1 = 0;
uPD7002->data0 = 0;
uPD7002->digitalvalue = 0;
uPD7002->conversion_counter = 0;
}
const device_type UPD7002 = &device_creator<uPD7002_device>;
uPD7002_device::uPD7002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, UPD7002, "uPD7002", tag, owner, clock, "upd7002", __FILE__)
{
m_token = global_alloc_clear(uPD7002_t);
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void uPD7002_device::device_config_complete()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void uPD7002_device::device_start()
{
DEVICE_START_NAME( uPD7002 )(this);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void uPD7002_device::device_reset()
{
DEVICE_RESET_NAME( uPD7002 )(this);
}

View File

@ -11,59 +11,88 @@
#ifndef UPD7002_H_
#define UPD7002_H_
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef int (*upd7002_get_analogue_func)(device_t *device, int channel_number);
#define UPD7002_GET_ANALOGUE(name) int name(device_t *device, int channel_number )
typedef void (*upd7002_eoc_func)(device_t *device, int data);
#define UPD7002_EOC(name) void name(device_t *device, int data )
struct upd7002_interface
{
upd7002_get_analogue_func get_analogue_func;
upd7002_eoc_func eoc_func;
};
/***************************************************************************
MACROS
***************************************************************************/
class uPD7002_device : public device_t
class upd7002_device : public device_t,
public upd7002_interface
{
public:
uPD7002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~uPD7002_device() { global_free(m_token); }
upd7002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~upd7002_device() {}
// access to legacy token
void *token() const { assert(m_token != NULL); return m_token; }
DECLARE_READ8_MEMBER ( eoc_r );
DECLARE_READ8_MEMBER ( read );
DECLARE_WRITE8_MEMBER ( write );
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
virtual void device_reset();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private:
// internal state
void *m_token;
/* Status Register
D0 and D1 define the currently selected input channel
D2 flag output
D3 0 = 8 bit mode 1 = 12 bit mode
D4 2nd MSB of conversion
D5 MSB of conversion
D6 0 = busy, 1 = not busy (~busy)
D7 0 = conversion completed, 1 = conversion not completed (~EOC)
*/
int m_status;
/* High data byte
This byte contains the 8 most significant bits of the analogue to digital conversion. */
int m_data1;
/* Low data byte
In 12 bit mode: Bits 7 to 4 define the four low order bits of the conversion.
In 8 bit mode. All bits 7 to 4 are inaccurate.
Bits 3 to 0 are always set to low. */
int m_data0;
/* temporary store of the next A to D conversion */
int m_digitalvalue;
/* this counter is used to check a full end of conversion has been reached
if the uPD7002 is half way through one conversion and a new conversion is requested
the counter at the end of the first conversion will not match and not be processed
only then at the end of the second conversion will the conversion complete function run */
int m_conversion_counter;
enum
{
TIMER_CONVERSION_COMPLETE
};
};
extern const device_type UPD7002;
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef int (*uPD7002_get_analogue_func)(device_t *device, int channel_number);
#define UPD7002_GET_ANALOGUE(name) int name(device_t *device, int channel_number )
typedef void (*uPD7002_eoc_func)(device_t *device, int data);
#define UPD7002_EOC(name) void name(device_t *device, int data )
struct uPD7002_interface
{
uPD7002_get_analogue_func get_analogue_func;
uPD7002_eoc_func EOC_func;
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
/* Standard handlers */
DECLARE_READ8_DEVICE_HANDLER ( uPD7002_EOC_r );
DECLARE_READ8_DEVICE_HANDLER ( uPD7002_r );
DECLARE_WRITE8_DEVICE_HANDLER ( uPD7002_w );
/***************************************************************************
DEVICE CONFIGURATION MACROS
***************************************************************************/

View File

@ -46,7 +46,6 @@
#include "cpu/m6502/m65sc02.h"
#include "machine/6522via.h"
#include "machine/mc146818.h" /* RTC & CMOS RAM */
#include "machine/upd7002.h"
#include "bus/centronics/ctronics.h"
#include "bus/econet/econet.h"
#include "sound/tms5220.h" /* Speech */
@ -184,7 +183,7 @@ static ADDRESS_MAP_START( bbcb_mem, AS_PROGRAM, 8, bbc_state )
AM_RANGE(0xfe60, 0xfe7f) AM_DEVREADWRITE("via6522_1", via6522_device, read, write) /* fe60-fe7f 6522 VIA USER VIA */
AM_RANGE(0xfe80, 0xfe9f) AM_READWRITE(bbc_disc_r, bbc_disc_w) /* fe80-fe9f 8271 FDC Floppy disc controller */
AM_RANGE(0xfea0, 0xfebf) AM_READ(bbc_fe_r) /* fea0-febf 68B54 ADLC ECONET controller */
AM_RANGE(0xfec0, 0xfedf) AM_DEVREADWRITE_LEGACY("upd7002", uPD7002_r, uPD7002_w) /* fec0-fedf uPD7002 Analogue to digital converter */
AM_RANGE(0xfec0, 0xfedf) AM_DEVREADWRITE("upd7002", upd7002_device, read, write) /* fec0-fedf uPD7002 Analogue to digital converter */
AM_RANGE(0xfee0, 0xfeff) AM_READ(bbc_fe_r) /* fee0-feff Tube ULA Tube system interface */
AM_RANGE(0xff00, 0xffff) AM_ROM AM_REGION("user1", 0x43f00) /* ff00-ffff OS Rom (continued) */
ADDRESS_MAP_END
@ -213,7 +212,7 @@ static ADDRESS_MAP_START( bbcbp_mem, AS_PROGRAM, 8, bbc_state )
AM_RANGE(0xfe60, 0xfe7f) AM_DEVREADWRITE("via6522_1", via6522_device, read, write) /* fe60-fe7f 6522 VIA USER VIA */
AM_RANGE(0xfe80, 0xfe9f) AM_READWRITE(bbc_wd1770_read, bbc_wd1770_write) /* fe80-fe9f 1770 FDC Floppy disc controller */
AM_RANGE(0xfea0, 0xfebf) AM_READ(bbc_fe_r) /* fea0-febf 68B54 ADLC ECONET controller */
AM_RANGE(0xfec0, 0xfedf) AM_DEVREADWRITE_LEGACY("upd7002", uPD7002_r, uPD7002_w) /* fec0-fedf uPD7002 Analogue to digital converter */
AM_RANGE(0xfec0, 0xfedf) AM_DEVREADWRITE("upd7002", upd7002_device, read, write) /* fec0-fedf uPD7002 Analogue to digital converter */
AM_RANGE(0xfee0, 0xfeff) AM_READ(bbc_fe_r) /* fee0-feff Tube ULA Tube system interface */
AM_RANGE(0xff00, 0xffff) AM_ROM AM_REGION("user1", 0x43f00) /* ff00-ffff OS Rom (continued) */
ADDRESS_MAP_END
@ -243,7 +242,7 @@ static ADDRESS_MAP_START( bbcbp128_mem, AS_PROGRAM, 8, bbc_state )
AM_RANGE(0xfe60, 0xfe7f) AM_DEVREADWRITE("via6522_1", via6522_device, read, write) /* fe60-fe7f 6522 VIA USER VIA */
AM_RANGE(0xfe80, 0xfe9f) AM_READWRITE(bbc_wd1770_read, bbc_wd1770_write) /* fe80-fe9f 1770 FDC Floppy disc controller */
AM_RANGE(0xfea0, 0xfebf) AM_READ(bbc_fe_r) /* fea0-febf 68B54 ADLC ECONET controller */
AM_RANGE(0xfec0, 0xfedf) AM_DEVREADWRITE_LEGACY("upd7002", uPD7002_r, uPD7002_w) /* fec0-fedf uPD7002 Analogue to digital converter */
AM_RANGE(0xfec0, 0xfedf) AM_DEVREADWRITE("upd7002", upd7002_device, read, write) /* fec0-fedf uPD7002 Analogue to digital converter */
AM_RANGE(0xfee0, 0xfeff) AM_READ(bbc_fe_r) /* fee0-feff Tube ULA Tube system interface */
AM_RANGE(0xff00, 0xffff) AM_ROM AM_REGION("user1", 0x43f00) /* ff00-ffff OS Rom (continued) */
ADDRESS_MAP_END
@ -1108,8 +1107,8 @@ ROM_START(bbcb)
//ROM_LOAD("torchz80_094.bin", 0x0000, 0x2000, CRC(49989bd4) SHA1(62b57c858a3baa4ff943c31f77d331c414772a61))
//ROM_LOAD("torchz80_102.bin", 0x0000, 0x2000, CRC(2eb40a21) SHA1(e6ee738e5f2f8556002b79d18caa8ef21f14e08d))
ROM_REGION(0x8000, "vsm", 0) /* system speech PHROM */
ROM_LOAD("phroma.bin", 0x0000, 0x4000, CRC(98e1bf9e) SHA1(b369809275cb67dfd8a749265e91adb2d2558ae6))
//ROM_REGION(0x8000, "vsm", 0) /* system speech PHROM */
//ROM_LOAD("phroma.bin", 0x0000, 0x4000, CRC(98e1bf9e) SHA1(b369809275cb67dfd8a749265e91adb2d2558ae6))
ROM_END
ROM_START(bbcb_de)

View File

@ -44,6 +44,7 @@ public:
m_rs232(*this, RS232_TAG),
m_via6522_0(*this, "via6522_0"),
m_via6522_1(*this, "via6522_1"),
m_upd7002(*this, "upd7002"),
m_ACCCON_IRR(CLEAR_LINE),
m_via_system_irq(CLEAR_LINE),
m_via_user_irq(CLEAR_LINE),
@ -72,6 +73,7 @@ public:
optional_device<rs232_port_device> m_rs232;
required_device<via6522_device> m_via6522_0;
optional_device<via6522_device> m_via6522_1;
optional_device<upd7002_device> m_upd7002;
void check_interrupts();
@ -405,6 +407,6 @@ extern const wd17xx_interface bbc_wd17xx_interface;
/* tape support */
extern const uPD7002_interface bbc_uPD7002;
extern const upd7002_interface bbc_uPD7002;
#endif /* BBC_H_ */

View File

@ -18,7 +18,6 @@
#include "machine/wd17xx.h"
#include "imagedev/flopdrv.h"
#include "includes/bbc.h"
#include "machine/upd7002.h"
#include "machine/i8271.h"
#include "machine/mc146818.h"
#include "bus/centronics/ctronics.h"
@ -582,7 +581,7 @@ READ8_MEMBER(bbc_state::bbcm_r)
return m_acia->data_read(space,0);
}
if ((myo>=0x10) && (myo<=0x17)) return 0xfe; /* Serial System Chip */
if ((myo>=0x18) && (myo<=0x1f)) return uPD7002_r(machine().device("upd7002"), space, myo-0x18); /* A to D converter */
if ((myo>=0x18) && (myo<=0x1f)) return m_upd7002->read(space, myo-0x18); /* A to D converter */
if ((myo>=0x20) && (myo<=0x23)) return 0xfe; /* VideoULA */
if ((myo>=0x24) && (myo<=0x27)) return bbcm_wd1770l_read(space, myo-0x24); /* 1770 */
if ((myo>=0x28) && (myo<=0x2f)) return bbcm_wd1770_read(space, myo-0x28); /* disc control latch */
@ -616,7 +615,7 @@ WRITE8_MEMBER(bbc_state::bbcm_w)
m_acia->data_write(space, 0, data);
}
if ((myo>=0x10) && (myo<=0x17)) bbc_SerialULA_w(space, myo-0x10, data); /* Serial System Chip */
if ((myo>=0x18) && (myo<=0x1f)) uPD7002_w(machine().device("upd7002"), space, myo-0x18, data); /* A to D converter */
if ((myo>=0x18) && (myo<=0x1f)) m_upd7002->write(space, myo-0x18, data); /* A to D converter */
if ((myo>=0x20) && (myo<=0x23)) bbc_videoULA_w(space, myo-0x20, data); /* VideoULA */
if ((myo>=0x24) && (myo<=0x27)) bbcm_wd1770l_write(space, myo-0x24, data); /* 1770 */
if ((myo>=0x28) && (myo<=0x2f)) bbcm_wd1770_write(space, myo-0x28, data); /* disc control latch */
@ -1210,7 +1209,7 @@ static UPD7002_EOC(BBC_uPD7002_EOC)
via_0->write_cb1(data);
}
const uPD7002_interface bbc_uPD7002 =
const upd7002_interface bbc_uPD7002 =
{
BBC_get_analogue_input,
BBC_uPD7002_EOC