summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/f3853.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/f3853.cpp')
-rw-r--r--src/devices/machine/f3853.cpp353
1 files changed, 69 insertions, 284 deletions
diff --git a/src/devices/machine/f3853.cpp b/src/devices/machine/f3853.cpp
index 45511f334ab..f4713f3fa3a 100644
--- a/src/devices/machine/f3853.cpp
+++ b/src/devices/machine/f3853.cpp
@@ -1,29 +1,19 @@
// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol, hap
+// copyright-holders:Wilbert Pol
/**********************************************************************
-Fairchild F3853 SMI, F3851 PSU, F3856 PSU, F38T56 PSU
+ Fairchild F3853 SRAM interface with integrated interrupt
+ controller and timer (SMI)
-This device only emulates the I/O, interrupt, timer functions. Not the
-low-level ROMC signals.
+ This chip is a timer shift register, basically the same as in the
+ F3851.
-F3853: Static memory interface with integrated interrupt controller and timer.
+ Based on a datasheet obtained from www.freetradezone.com
-The timer is an 8-bit linear feedback shift register:
-Feedback in0 = !((out3 ^ out4) ^ (out5 ^ out7))
-Interrupts are at 0xfe
-0xff stops the register (0xfe is never reached)
-
-F3851: Program Storage Unit, same timer and interrupt controller as F3853,
-but has 2 I/O ports instead of a programmable interrupt vector.
-
-F3856/F38T56 Program Storage Unit: similar interrupt controller, timer
-is more versatile, a simple downcounter instead of shift register.
-
-TODO:
-- emulate at lower level and place this stuff into devices/cpu/f8 folder
-- interrupt priority pin
-- 3856/38T56 timer pulse counter mode, event counter mode
+ 8-bit shift register:
+ Feedback in0 = !((out3 ^ out4) ^ (out5 ^ out7))
+ Interrupts are at 0xfe
+ 0xff stops the register (0xfe is never reached)
**********************************************************************/
@@ -31,60 +21,31 @@ TODO:
#include "f3853.h"
-// device type definition
-
-DEFINE_DEVICE_TYPE(F3853, f3853_device, "f3853_smi", "Fairchild F3853 SMI")
-DEFINE_DEVICE_TYPE(F3851, f3851_device, "f3851_psu", "Fairchild F3851 PSU")
-DEFINE_DEVICE_TYPE(F3856, f3856_device, "f3856_psu", "Fairchild F3856 PSU")
-DEFINE_DEVICE_TYPE(F38T56, f38t56_device, "f38t56_psu", "Fairchild F38T56 PSU")
-
-
-//-------------------------------------------------
-// constructor
-//-------------------------------------------------
-
-f3853_device::f3853_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
- device_t(mconfig, type, tag, owner, clock),
- m_int_req_callback(*this),
- m_pri_out_callback(*this),
- m_int_vector(0),
- m_prescaler(31),
- m_priority_line(false),
- m_external_interrupt_line(true)
-{ }
-
-f3853_device::f3853_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
- f3853_device(mconfig, F3853, tag, owner, clock)
-{ }
-
-f3851_device::f3851_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
- f3853_device(mconfig, type, tag, owner, clock),
- m_read_port{{*this}, {*this}},
- m_write_port{{*this}, {*this}}
-{ }
-
-f3851_device::f3851_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
- f3851_device(mconfig, F3851, tag, owner, clock)
-{ }
-
-f3856_device::f3856_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
- f3851_device(mconfig, type, tag, owner, clock)
-{ }
-
-f3856_device::f3856_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
- f3856_device(mconfig, F3856, tag, owner, clock)
-{ }
-f38t56_device::f38t56_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
- f3856_device(mconfig, F38T56, tag, owner, clock)
-{ }
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+// device type definition
+DEFINE_DEVICE_TYPE(F3853, f3853_device, "f3853_device", "F3853 SMI")
//-------------------------------------------------
-// initialisation
+// f3853_device - constructor
//-------------------------------------------------
+f3853_device::f3853_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, F3853, tag, owner, clock)
+ , m_int_req_callback(*this)
+ , m_pri_out_callback(*this)
+ , m_priority_line(false)
+ , m_external_interrupt_line(true)
+{
+}
+
void f3853_device::device_resolve_objects()
{
m_int_req_callback.resolve_safe();
@@ -92,20 +53,12 @@ void f3853_device::device_resolve_objects()
m_int_daisy_chain_callback.bind_relative_to(*owner());
}
-void f3851_device::device_resolve_objects()
-{
- f3853_device::device_resolve_objects();
-
- // 2 I/O ports
- for (devcb_read8 &cb : m_read_port)
- cb.resolve_safe(0);
- for (devcb_write8 &cb : m_write_port)
- cb.resolve_safe();
-}
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
void f3853_device::device_start()
{
- // lookup table for 3851/3853 lfsr timer
uint8_t reg = 0xfe; // Known to get 0xfe after 255 cycles
for(int i = reg; i >= 0; i--)
{
@@ -115,62 +68,47 @@ void f3853_device::device_start()
m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(f3853_device::timer_callback),this));
- // zerofill (what's not in constructor)
- m_external_int_enable = false;
- m_timer_int_enable = false;
- m_request_flipflop = false;
-
- // register for savestates
save_item(NAME(m_int_vector));
- save_item(NAME(m_prescaler));
- save_item(NAME(m_external_int_enable));
- save_item(NAME(m_timer_int_enable));
+ save_item(NAME(m_external_enable));
+ save_item(NAME(m_timer_enable));
save_item(NAME(m_request_flipflop));
save_item(NAME(m_priority_line));
save_item(NAME(m_external_interrupt_line));
}
-void f3856_device::device_start()
-{
- f3853_device::device_start();
- m_timer_count = 0;
- m_timer_modulo = 0;
- m_timer_start = false;
-
- save_item(NAME(m_timer_count));
- save_item(NAME(m_timer_modulo));
- save_item(NAME(m_timer_start));
-}
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
void f3853_device::device_reset()
{
- // note that standalone peripherals don't have a reset pin, but 3870 does
+ m_int_vector = 0;
+ m_external_enable = false;
+ m_timer_enable = false;
+ m_request_flipflop = false;
+ m_external_interrupt_line = true;
+ set_interrupt_request_line();
- // clear ports at power-on
- for (int i = 0; i < 4; i++)
- write(machine().dummy_space(), i, 0);
+ m_timer->enable(false);
}
-//-------------------------------------------------
-// implementation
-//-------------------------------------------------
-
void f3853_device::set_interrupt_request_line()
{
m_int_req_callback(m_request_flipflop && !m_priority_line ? ASSERT_LINE : CLEAR_LINE);
}
+
IRQ_CALLBACK_MEMBER(f3853_device::int_acknowledge)
{
- if (m_external_int_enable && !m_priority_line && m_request_flipflop)
+ if (m_external_enable && !m_priority_line && m_request_flipflop)
{
m_request_flipflop = false;
set_interrupt_request_line();
return external_interrupt_vector();
}
- else if (m_timer_int_enable && !m_priority_line && m_request_flipflop)
+ else if (m_timer_enable && !m_priority_line && m_request_flipflop)
{
m_request_flipflop = false;
set_interrupt_request_line();
@@ -189,14 +127,14 @@ IRQ_CALLBACK_MEMBER(f3853_device::int_acknowledge)
void f3853_device::timer_start(uint8_t value)
{
- attotime period = (value != 0xff) ? attotime::from_hz(clock()) * (m_value_to_cycle[value] * m_prescaler) : attotime::never;
+ attotime period = (value != 0xff) ? attotime::from_hz(clock()) * (m_value_to_cycle[value]*31) : attotime::never;
m_timer->adjust(period);
}
TIMER_CALLBACK_MEMBER(f3853_device::timer_callback)
{
- if(m_timer_int_enable)
+ if(m_timer_enable)
{
m_request_flipflop = true;
set_interrupt_request_line();
@@ -204,10 +142,9 @@ TIMER_CALLBACK_MEMBER(f3853_device::timer_callback)
timer_start(0xfe);
}
-
WRITE_LINE_MEMBER(f3853_device::ext_int_w)
{
- if(m_external_interrupt_line && !state && m_external_int_enable)
+ if(m_external_interrupt_line && !state && m_external_enable)
{
m_request_flipflop = true;
}
@@ -224,201 +161,49 @@ WRITE_LINE_MEMBER(f3853_device::pri_in_w)
READ8_MEMBER(f3853_device::read)
{
- switch (offset & 3)
+ uint8_t data = 0;
+
+ switch (offset)
{
- // interrupt vector
case 0:
- return m_int_vector >> 8;
+ data = m_int_vector >> 8;
+ break;
+
case 1:
- return m_int_vector & 0xff;
+ data = m_int_vector & 0xff;
+ break;
- // interrupt control, timer: write-only
- default:
- return 0;
+ case 2: // Interrupt control; not readable
+ case 3: // Timer; not readable
+ break;
}
+
+ return data;
}
+
WRITE8_MEMBER(f3853_device::write)
{
- switch (offset & 3)
+ switch(offset)
{
- // interrupt vector
case 0:
m_int_vector = (data << 8) | (m_int_vector & 0x00ff);
break;
+
case 1:
m_int_vector = data | (m_int_vector & 0xff00);
break;
- // interrupt control
- case 2:
- m_external_int_enable = (data & 3) == 1;
- m_timer_int_enable = (data & 3) == 3;
+ case 2: //interrupt control
+ m_external_enable = ((data & 3) == 1);
+ m_timer_enable = ((data & 3) == 3);
set_interrupt_request_line();
break;
- // set timer
- case 3:
+ case 3: //timer
m_request_flipflop = false;
set_interrupt_request_line();
timer_start(data);
break;
}
}
-
-
-//-------------------------------------------------
-// f3851_device-specific handlers
-//-------------------------------------------------
-
-READ8_MEMBER(f3851_device::read)
-{
- switch (offset & 3)
- {
- // I/O ports
- case 0: case 1:
- return (m_read_port[offset & 1])(offs_t(offset & 1));
-
- // interrupt control, timer: write-only
- default:
- return 0;
- }
-}
-
-WRITE8_MEMBER(f3851_device::write)
-{
- switch (offset & 3)
- {
- // I/O ports
- case 0: case 1:
- (m_write_port[offset & 1])(offs_t(offset & 1), data);
- break;
-
- // interrupt control, timer: same as 3853
- case 2: case 3:
- f3853_device::write(space, offset, data);
- break;
- }
-}
-
-
-//-------------------------------------------------
-// f3856_device-specific handlers
-//-------------------------------------------------
-
-void f3856_device::timer_start(uint8_t value)
-{
- m_timer_count = value;
- attotime period = (m_timer_start) ? (attotime::from_hz(clock()) * m_prescaler) : attotime::never;
-
- m_timer->adjust(period);
-}
-
-TIMER_CALLBACK_MEMBER(f3856_device::timer_callback)
-{
- if (--m_timer_count == 0)
- {
- m_timer_count = m_timer_modulo;
- if (m_timer_int_enable)
- {
- m_request_flipflop = true;
- set_interrupt_request_line();
- }
- }
-
- timer_start(m_timer_count);
-}
-
-READ8_MEMBER(f3856_device::read)
-{
- switch (offset & 3)
- {
- // timer: active counter
- case 3:
- return m_timer_count;
-
- // other: same as 3851
- default:
- return f3851_device::read(space, offset);
- }
-}
-
-WRITE8_MEMBER(f3856_device::write)
-{
- switch (offset & 3)
- {
- // I/O ports: same as 3851
- case 0: case 1:
- f3851_device::write(space, offset, data);
- break;
-
- // interrupt/timer control
- case 2:
- {
- // timer prescaler
- static const u8 prescaler[8] = { 32, 128, 8, 2 };
- m_prescaler = prescaler[data >> 5 & 7];
-
- // start/stop timer
- bool prev = m_timer_start;
- m_timer_start = bool(~data & 0x10);
- if (m_timer_start != prev)
- timer_start(m_timer_count);
-
- // enable interrupts
- m_external_int_enable = (data & 3) == 1 || (data & 3) == 2;
- m_timer_int_enable = bool(data & 2);
- set_interrupt_request_line();
- break;
- }
-
- // set timer
- case 3:
- f3853_device::write(space, offset, data);
- break;
- }
-}
-
-
-//-------------------------------------------------
-// f38t56_device-specific handlers
-//-------------------------------------------------
-
-WRITE8_MEMBER(f38t56_device::write)
-{
- switch (offset & 3)
- {
- // I/O ports: same as 3851
- case 0: case 1:
- f3851_device::write(space, offset, data);
- break;
-
- // interrupt/timer control
- case 2:
- {
- // timer prescaler
- m_prescaler = 200;
- if (~data & 0x80) m_prescaler /= 20;
- if (~data & 0x40) m_prescaler /= 5;
- if (~data & 0x20) m_prescaler /= 2;
-
- // start/stop timer
- bool prev = m_timer_start;
- m_timer_start = bool(data & 8);
- if (m_timer_start != prev)
- timer_start(m_timer_count);
-
- // enable interrupts
- m_external_int_enable = bool(data & 1);
- m_timer_int_enable = bool(data & 2);
- set_interrupt_request_line();
- break;
- }
-
- // set timer
- case 3:
- m_timer_modulo = data;
- f3853_device::write(space, offset, data);
- break;
- }
-}