From 5395f401ef4f2a46217ff987f67354227f0a41e4 Mon Sep 17 00:00:00 2001 From: Ryan Holtz Date: Fri, 27 Aug 2010 02:47:28 +0000 Subject: [PATCH] Updated the Fairchild F3853 SMI device to no longer be legacy. [Harmony] Non-whatsnew note: This is for MESS. No idea how to work the Chess Champion, either, so I can't really test it, but hey, it builds. --- src/emu/machine/f3853.c | 387 +++++++++++++++++++++++----------------- src/emu/machine/f3853.h | 133 +++++++++++--- 2 files changed, 331 insertions(+), 189 deletions(-) diff --git a/src/emu/machine/f3853.c b/src/emu/machine/f3853.c index 13747c9c864..8e689381296 100644 --- a/src/emu/machine/f3853.c +++ b/src/emu/machine/f3853.c @@ -1,233 +1,288 @@ -/* - fairchild f3853 smi static ram interface - with integrated interrupt controller and timer +/********************************************************************** - databook found at www.freetradezone.com -*/ + Fairchild F3853 SRAM interface with integrated interrupt + controller and timer (SMI) + + This chip is a timer shift register, basically the same as in the + F3851. + + Based on a datasheet obtained from www.freetradezone.com + + The SMI does not have DC0 and DC1, only DC0; as a result, it does + not respond to the main CPU's DC0/DC1 swap instruction. This may + lead to two devices responding to the same DC0 address and + attempting to place their bytes on the data bus simultaneously! + + 8-bit shift register: + Feedback in0 = !((out3 ^ out4) ^ (out5 ^ out7)) + Interrupts are at 0xfe + 0xff stops the register (0xfe is never reached) + +**********************************************************************/ #include "emu.h" #include "f3853.h" +#include "devhelpr.h" -/* - the smi does not have DC0 and DC1, only DC0 - it is not reacting to the cpus DC0/DC1 swap instruction - --> might lead to 2 devices having reacting to the same DC0 address - and placing their bytes to the databus! -*/ +/*************************************************************************** + MACROS +***************************************************************************/ + +#define INTERRUPT_VECTOR(external) ( external ? m_low | ( m_high << 8 ) | 0x80 \ +: ( m_low | ( m_high << 8 ) ) & ~0x80 ) -typedef struct _f3853 f3853_t; -struct _f3853 { - const f3853_config *config; - UINT8 high,low; // bit 7 set to 0 for timer interrupt, to 1 for external interrupt - int external_enable; - int timer_enable; +/*************************************************************************** + IMPLEMENTATION +***************************************************************************/ - int request_flipflop; +//************************************************************************** +// DEVICE CONFIGURATION +//************************************************************************** - int priority_line; /* inverted level*/ - int external_interrupt_line;/* inverted level */ +//------------------------------------------------- +// f3853_device_config - constructor +//------------------------------------------------- - emu_timer *timer; -}; - -/* - 8 bit shift register - feedback in0 = not ( (out3 xor out4) xor (out5 xor out7) ) - interrupt at 0xfe - 0xff stops register (0xfe never reached!) -*/ -static UINT8 f3853_value_to_cycle[0x100]; - - -static TIMER_CALLBACK( f3853_timer_callback ); -#define INTERRUPT_VECTOR(external) ( external ? f3853->low | ( f3853->high << 8 ) | 0x80 \ - : ( f3853->low | ( f3853->high << 8 ) ) & ~0x80 ) - - -INLINE f3853_t *get_safe_token(running_device *device) +f3853_device_config::f3853_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock) + : device_config(mconfig, static_alloc_device_config, "F3853", tag, owner, clock) { - assert( device != NULL ); - assert( device->type() == F3853 ); - return ( f3853_t * ) downcast(device)->token(); } -static void f3853_set_interrupt_request_line(running_device *device) +//------------------------------------------------- +// static_alloc_device_config - allocate a new +// configuration object +//------------------------------------------------- + +device_config *f3853_device_config::static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock) { - f3853_t *f3853 = get_safe_token( device ); - - if ( ! f3853->config->interrupt_request ) - return; - - if ( f3853->external_enable && ! f3853->priority_line ) - f3853->config->interrupt_request(device, INTERRUPT_VECTOR(TRUE), TRUE); - else if ( f3853->timer_enable && ! f3853->priority_line && f3853->request_flipflop) - f3853->config->interrupt_request(device, INTERRUPT_VECTOR(FALSE), TRUE); - else - f3853->config->interrupt_request(device, 0, FALSE); + return global_alloc(f3853_device_config(mconfig, tag, owner, clock)); } -static void f3853_timer_start(running_device *device, UINT8 value) +//------------------------------------------------- +// alloc_device - allocate a new device object +//------------------------------------------------- + +device_t *f3853_device_config::alloc_device(running_machine &machine) const { - f3853_t *f3853 = get_safe_token( device ); - - attotime period = (value != 0xff) ? attotime_mul(ATTOTIME_IN_HZ(device->clock()), f3853_value_to_cycle[value]*31) : attotime_never; - - timer_adjust_oneshot(f3853->timer, period, 0); + return auto_alloc(&machine, f3853_device(machine, *this)); } -static TIMER_CALLBACK( f3853_timer_callback ) -{ - running_device *device = (running_device *)ptr; - f3853_t *f3853 = get_safe_token( device ); +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- - if (f3853->timer_enable) +void f3853_device_config::device_config_complete() +{ + // inherit a copy of the static data + const f3853_interface *intf = reinterpret_cast(static_config()); + if (intf != NULL) { - f3853->request_flipflop = TRUE; - f3853_set_interrupt_request_line( device ); + *static_cast(this) = *intf; + } + + // or initialize to defaults if none provided + else + { + memset(&m_interrupt_request, 0, sizeof(m_interrupt_request)); + } +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +const device_type F3853 = f3853_device_config::static_alloc_device_config; + +//------------------------------------------------- +// f3853_device - constructor +//------------------------------------------------- + +f3853_device::f3853_device(running_machine &_machine, const f3853_device_config &config) + : device_t(_machine, config), + m_config(config) +{ + +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void f3853_device::device_start() +{ + UINT8 reg = 0xfe; + for(INT32 i=254 /* Known to get 0xfe after 255 cycles */; i >= 0; i--) + { + INT32 o7 = (reg & 0x80) ? TRUE : FALSE; + INT32 o5 = (reg & 0x20) ? TRUE : FALSE; + INT32 o4 = (reg & 0x10) ? TRUE : FALSE; + INT32 o3 = (reg & 0x08) ? TRUE : FALSE; + m_value_to_cycle[reg] = i; + reg <<= 1; + if(!((o7 != o5) != (o4 != o3))) + { + reg |= 1; + } + } + + m_timer = timer_alloc(&m_machine, f3853_timer_callback, (void *)this ); + + state_save_register_device_item(this, 0, m_high ); + state_save_register_device_item(this, 0, m_low ); + state_save_register_device_item(this, 0, m_external_enable ); + state_save_register_device_item(this, 0, m_timer_enable ); + state_save_register_device_item(this, 0, m_request_flipflop ); + state_save_register_device_item(this, 0, m_priority_line ); + state_save_register_device_item(this, 0, m_external_interrupt_line ); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void f3853_device::device_reset() +{ + m_high = 0; + m_low = 0; + m_external_enable = 0; + m_timer_enable = 0; + m_request_flipflop = 0; + m_priority_line = FALSE; + m_external_interrupt_line = TRUE; + + timer_enable(m_timer, 0); +} + + +void f3853_device::f3853_set_interrupt_request_line() +{ + if(!m_config.m_interrupt_request) + { + return; + } + + if(m_external_enable && !m_priority_line) + { + m_config.m_interrupt_request(this, INTERRUPT_VECTOR(TRUE), TRUE); + } + else if( m_timer_enable && !m_priority_line && m_request_flipflop) + { + m_config.m_interrupt_request(this, INTERRUPT_VECTOR(FALSE), TRUE); + } + else + { + m_config.m_interrupt_request(this, 0, FALSE); + } +} + + +void f3853_device::f3853_timer_start(UINT8 value) +{ + attotime period = (value != 0xff) ? attotime_mul(ATTOTIME_IN_HZ(clock()), m_value_to_cycle[value]*31) : attotime_never; + + timer_adjust_oneshot(m_timer, period, 0); +} + + +TIMER_CALLBACK( f3853_device::f3853_timer_callback ) +{ + reinterpret_cast(ptr)->f3853_timer(); +} + +void f3853_device::f3853_timer() +{ + if(m_timer_enable) + { + m_request_flipflop = TRUE; + f3853_set_interrupt_request_line(); } - f3853_timer_start( device, 0xfe); + f3853_timer_start(0xfe); } void f3853_set_external_interrupt_in_line(running_device *device, int level) { - f3853_t *f3853 = get_safe_token( device ); + downcast(device)->f3853_set_external_interrupt_in_line(level); +} - if ( f3853->external_interrupt_line && ! level && f3853->external_enable) - f3853->request_flipflop = TRUE; - f3853->external_interrupt_line = level; - f3853_set_interrupt_request_line( device ); +void f3853_device::f3853_set_external_interrupt_in_line(int level) +{ + if(m_external_interrupt_line && !level && m_external_enable) + { + m_request_flipflop = TRUE; + } + m_external_interrupt_line = level; + f3853_set_interrupt_request_line(); } void f3853_set_priority_in_line(running_device *device, int level) { - f3853_t *f3853 = get_safe_token( device ); + downcast(device)->f3853_set_priority_in_line(level); +} - f3853->priority_line = level; - f3853_set_interrupt_request_line( device ); +void f3853_device::f3853_set_priority_in_line(int level) +{ + m_priority_line = level; + f3853_set_interrupt_request_line(); } -READ8_DEVICE_HANDLER(f3853_r) +READ8_DEVICE_HANDLER_TRAMPOLINE(f3853, f3853_r) { - f3853_t *f3853 = get_safe_token( device ); - UINT8 data=0; + UINT8 data = 0; switch (offset) { case 0: - data = f3853->high; + data = m_high; break; + case 1: - data = f3853->low; + data = m_low; break; - case 2: // interrupt control; not readable - case 3: // timer; not readable + + case 2: // Interrupt control; not readable + case 3: // Timer; not readable break; } + return data; } -WRITE8_DEVICE_HANDLER(f3853_w) +WRITE8_DEVICE_HANDLER_TRAMPOLINE(f3853, f3853_w) { - f3853_t *f3853 = get_safe_token( device ); - switch (offset) + switch(offset) { case 0: - f3853->high = data; + m_high = data; break; + case 1: - f3853->low = data; + m_low = data; break; + case 2: //interrupt control - f3853->external_enable = ((data&3)==1); - f3853->timer_enable = ((data&3)==3); - f3853_set_interrupt_request_line( device ); + m_external_enable = ((data & 3) == 1); + m_timer_enable = ((data & 3) == 3); + f3853_set_interrupt_request_line(); break; + case 3: //timer - f3853->request_flipflop = FALSE; - f3853_set_interrupt_request_line( device ); - f3853_timer_start( device, data ); + m_request_flipflop = FALSE; + f3853_set_interrupt_request_line(); + f3853_timer_start(data); break; } } - - -static DEVICE_START( f3853 ) -{ - f3853_t *f3853 = get_safe_token( device ); - UINT8 reg=0xfe; - int i; - - f3853->config = (const f3853_config *)device->baseconfig().static_config(); - - for (i=254/*known to get 0xfe after 255 cycles*/; i>=0; i--) - { - int o7 = ( reg & 0x80 ) ? TRUE : FALSE; - int o5 = ( reg & 0x20 ) ? TRUE : FALSE; - int o4 = ( reg & 0x10 ) ? TRUE : FALSE; - int o3 = ( reg & 8 ) ? TRUE : FALSE; - f3853_value_to_cycle[reg]=i; - reg<<=1; - if (!((o7!=o5)!=(o4!=o3))) reg|=1; - } - - f3853->timer = timer_alloc( device->machine, f3853_timer_callback, (void *)device ); - - state_save_register_device_item( device, 0, f3853->high ); - state_save_register_device_item( device, 0, f3853->low ); - state_save_register_device_item( device, 0, f3853->external_enable ); - state_save_register_device_item( device, 0, f3853->timer_enable ); - state_save_register_device_item( device, 0, f3853->request_flipflop ); - state_save_register_device_item( device, 0, f3853->priority_line ); - state_save_register_device_item( device, 0, f3853->external_interrupt_line ); -} - - -static DEVICE_RESET( f3853 ) -{ - f3853_t *f3853 = get_safe_token( device ); - - f3853->high = 0; - f3853->low = 0; - f3853->external_enable = 0; - f3853->timer_enable = 0; - f3853->request_flipflop = 0; - f3853->priority_line = FALSE; - f3853->external_interrupt_line = TRUE; - - timer_enable( f3853->timer, 0 ); -} - - -DEVICE_GET_INFO( f3853 ) -{ - switch ( state ) - { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(f3853_t); break; - case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(f3853); break; - case DEVINFO_FCT_STOP: /* nothing */ break; - case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(f3853); break; - - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "F3853"); break; - case DEVINFO_STR_FAMILY: strcpy(info->s, "F8"); break; - case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; - case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; - case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright the MAME and MESS Teams"); break; - } -} - - -DEFINE_LEGACY_DEVICE(F3853, f3853); diff --git a/src/emu/machine/f3853.h b/src/emu/machine/f3853.h index 4f4b93233ac..716d8bb518c 100644 --- a/src/emu/machine/f3853.h +++ b/src/emu/machine/f3853.h @@ -1,41 +1,128 @@ -/* - fairchild f3853 static ram interface smi - with integrated interrupt controller and timer +/********************************************************************** - timer shift register basically the same as in f3851! -*/ + Fairchild F3853 SRAM interface with integrated interrupt + controller and timer + + This chip is a timer shift register, basically the same as in the + F3851. + +**********************************************************************/ #pragma once #ifndef __F3853_H__ #define __F3853_H__ -#include "devlegcy.h" - -DECLARE_LEGACY_DEVICE(F3853, f3853); - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -typedef struct _f3853_config f3853_config; -struct _f3853_config -{ - void (*interrupt_request)(running_device *device, UINT16 addr, int level); -}; +#include "emu.h" -/*************************************************************************** - DEVICE CONFIGURATION MACROS -***************************************************************************/ + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** #define MDRV_F3853_ADD(_tag, _clock, _intrf) \ MDRV_DEVICE_ADD(_tag, F3853, _clock) \ MDRV_DEVICE_CONFIG(_intrf) -READ8_DEVICE_HANDLER(f3853_r); -WRITE8_DEVICE_HANDLER(f3853_w); + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + + +// ======================> f3853_interface + +struct f3853_interface +{ + void (*m_interrupt_request)(running_device *device, UINT16 addr, int level); +}; + + +// ======================> f3853_device_config + +class f3853_device_config : public device_config, + public f3853_interface +{ + friend class f3853_device; + + // construction/destruction + f3853_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); + +public: + // allocators + static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); + virtual device_t *alloc_device(running_machine &machine) const; + +protected: + // device_config overrides + virtual void device_config_complete(); +}; + + +// ======================> f3853_device + +class f3853_device : public device_t +{ + friend class f3853_device_config; + + // construction/destruction + f3853_device(running_machine &_machine, const f3853_device_config &_config); + +public: + + UINT8 f3853_r(UINT32 offset); + void f3853_w(UINT32 offset, UINT8 data); + + void f3853_set_external_interrupt_in_line(int level); + void f3853_set_priority_in_line(int level); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual void device_post_load() { } + virtual void device_clock_changed() { } + + static TIMER_CALLBACK( f3853_timer_callback ); + +private: + + void f3853_set_interrupt_request_line(); + void f3853_timer_start(UINT8 value); + void f3853_timer(); + + UINT8 m_high; + UINT8 m_low; // Bit 7 is set to 0 for timer interrupts, 1 for external interrupts + INT32 m_external_enable; + INT32 m_timer_enable; + + INT32 m_request_flipflop; + + INT32 m_priority_line; /* inverted level*/ + INT32 m_external_interrupt_line; /* inverted level */ + + emu_timer *m_timer; + + UINT8 m_value_to_cycle[0x100]; + + const f3853_device_config &m_config; +}; + + +// device type definition +extern const device_type F3853; + + + +/*************************************************************************** + PROTOTYPES +***************************************************************************/ + +READ8_DEVICE_HANDLER( f3853_r ); +WRITE8_DEVICE_HANDLER( f3853_w ); void f3853_set_external_interrupt_in_line(running_device *device, int level); void f3853_set_priority_in_line(running_device *device, int level);