mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
f3853: add notes (nw)
This commit is contained in:
parent
16f19a2a74
commit
7fa6825e45
@ -2,37 +2,45 @@
|
||||
// copyright-holders:Wilbert Pol, hap
|
||||
/**********************************************************************
|
||||
|
||||
Fairchild F3853 SRAM interface with integrated interrupt
|
||||
controller and timer (SMI)
|
||||
Fairchild F3853 SMI, F3851 PSU, F3856 PSU, F38T56 PSU
|
||||
|
||||
This chip is a timer shift register, basically the same as in the
|
||||
F3851.
|
||||
This device only emulates the I/O, interrupt, timer functions. Not the
|
||||
low-level ROMC signals.
|
||||
|
||||
Based on a datasheet obtained from www.freetradezone.com
|
||||
F3853: Static memory interface with integrated interrupt controller and timer.
|
||||
|
||||
8-bit shift register:
|
||||
The timer is a 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
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "f3853.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(F3853, f3853_device, "f3853_device", "F3853 SMI")
|
||||
DEFINE_DEVICE_TYPE(F3851, f3851_device, "f3851_device", "F3851 PSU")
|
||||
DEFINE_DEVICE_TYPE(F3856, f3856_device, "f3856_device", "F3856 PSU")
|
||||
DEFINE_DEVICE_TYPE(F38T56, f38t56_device, "f38t56_device", "F38T56 PSU")
|
||||
|
||||
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")
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// f3853_device - constructor
|
||||
// constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
f3853_device::f3853_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
|
||||
@ -72,6 +80,11 @@ f38t56_device::f38t56_device(const machine_config &mconfig, const char *tag, dev
|
||||
{ }
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// initialisation
|
||||
//-------------------------------------------------
|
||||
|
||||
void f3853_device::device_resolve_objects()
|
||||
{
|
||||
m_int_req_callback.resolve_safe();
|
||||
@ -90,11 +103,6 @@ void f3851_device::device_resolve_objects()
|
||||
cb.resolve_safe();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void f3853_device::device_start()
|
||||
{
|
||||
// lookup table for 3851/3853 lfsr timer
|
||||
@ -108,15 +116,15 @@ 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_enable = false;
|
||||
m_timer_enable = false;
|
||||
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_enable));
|
||||
save_item(NAME(m_timer_enable));
|
||||
save_item(NAME(m_external_int_enable));
|
||||
save_item(NAME(m_timer_int_enable));
|
||||
save_item(NAME(m_request_flipflop));
|
||||
save_item(NAME(m_priority_line));
|
||||
save_item(NAME(m_external_interrupt_line));
|
||||
@ -135,33 +143,34 @@ void f3856_device::device_start()
|
||||
save_item(NAME(m_timer_start));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void f3853_device::device_reset()
|
||||
{
|
||||
// clear ports
|
||||
// note that standalone peripherals don't have a reset pin, but 3870 does
|
||||
|
||||
// clear ports at power-on
|
||||
for (int i = 0; i < 4; i++)
|
||||
write(machine().dummy_space(), i, 0);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// 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_enable && !m_priority_line && m_request_flipflop)
|
||||
if (m_external_int_enable && !m_priority_line && m_request_flipflop)
|
||||
{
|
||||
m_request_flipflop = false;
|
||||
set_interrupt_request_line();
|
||||
return external_interrupt_vector();
|
||||
}
|
||||
else if (m_timer_enable && !m_priority_line && m_request_flipflop)
|
||||
else if (m_timer_int_enable && !m_priority_line && m_request_flipflop)
|
||||
{
|
||||
m_request_flipflop = false;
|
||||
set_interrupt_request_line();
|
||||
@ -187,7 +196,7 @@ void f3853_device::timer_start(uint8_t value)
|
||||
|
||||
TIMER_CALLBACK_MEMBER(f3853_device::timer_callback)
|
||||
{
|
||||
if(m_timer_enable)
|
||||
if(m_timer_int_enable)
|
||||
{
|
||||
m_request_flipflop = true;
|
||||
set_interrupt_request_line();
|
||||
@ -195,9 +204,10 @@ 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_enable)
|
||||
if(m_external_interrupt_line && !state && m_external_int_enable)
|
||||
{
|
||||
m_request_flipflop = true;
|
||||
}
|
||||
@ -242,8 +252,8 @@ WRITE8_MEMBER(f3853_device::write)
|
||||
|
||||
// interrupt control
|
||||
case 2:
|
||||
m_external_enable = (data & 3) == 1;
|
||||
m_timer_enable = (data & 3) == 3;
|
||||
m_external_int_enable = (data & 3) == 1;
|
||||
m_timer_int_enable = (data & 3) == 3;
|
||||
set_interrupt_request_line();
|
||||
break;
|
||||
|
||||
@ -257,6 +267,10 @@ WRITE8_MEMBER(f3853_device::write)
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// f3851_device-specific handlers
|
||||
//-------------------------------------------------
|
||||
|
||||
READ8_MEMBER(f3851_device::read)
|
||||
{
|
||||
switch (offset & 3)
|
||||
@ -288,6 +302,10 @@ WRITE8_MEMBER(f3851_device::write)
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// f3856_device-specific handlers
|
||||
//-------------------------------------------------
|
||||
|
||||
void f3856_device::timer_start(uint8_t value)
|
||||
{
|
||||
m_timer_count = value;
|
||||
@ -301,7 +319,7 @@ TIMER_CALLBACK_MEMBER(f3856_device::timer_callback)
|
||||
if (--m_timer_count == 0)
|
||||
{
|
||||
m_timer_count = m_timer_modulo;
|
||||
if (m_timer_enable)
|
||||
if (m_timer_int_enable)
|
||||
{
|
||||
m_request_flipflop = true;
|
||||
set_interrupt_request_line();
|
||||
@ -334,7 +352,7 @@ WRITE8_MEMBER(f3856_device::write)
|
||||
f3851_device::write(space, offset, data);
|
||||
break;
|
||||
|
||||
// interrupt control
|
||||
// interrupt/timer control
|
||||
case 2:
|
||||
{
|
||||
// timer prescaler
|
||||
@ -348,8 +366,8 @@ WRITE8_MEMBER(f3856_device::write)
|
||||
timer_start(m_timer_count);
|
||||
|
||||
// enable interrupts
|
||||
m_external_enable = (data & 3) == 1 || (data & 3) == 2;
|
||||
m_timer_enable = bool(data & 2);
|
||||
m_external_int_enable = (data & 3) == 1 || (data & 3) == 2;
|
||||
m_timer_int_enable = bool(data & 2);
|
||||
set_interrupt_request_line();
|
||||
break;
|
||||
}
|
||||
@ -362,16 +380,20 @@ WRITE8_MEMBER(f3856_device::write)
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// f38t56_device-specific handlers
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE8_MEMBER(f38t56_device::write)
|
||||
{
|
||||
switch (offset & 3)
|
||||
{
|
||||
// I/O ports: same as 3851
|
||||
default:
|
||||
case 0: case 1:
|
||||
f3851_device::write(space, offset, data);
|
||||
break;
|
||||
|
||||
// interrupt control
|
||||
// interrupt/timer control
|
||||
case 2:
|
||||
{
|
||||
// timer prescaler
|
||||
@ -387,8 +409,8 @@ WRITE8_MEMBER(f38t56_device::write)
|
||||
timer_start(m_timer_count);
|
||||
|
||||
// enable interrupts
|
||||
m_external_enable = bool(data & 1);
|
||||
m_timer_enable = bool(data & 2);
|
||||
m_external_int_enable = bool(data & 1);
|
||||
m_timer_int_enable = bool(data & 2);
|
||||
set_interrupt_request_line();
|
||||
break;
|
||||
}
|
||||
|
@ -1,49 +1,67 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Wilbert Pol, hap
|
||||
/***************************************************************************
|
||||
/*
|
||||
|
||||
Fairchild F3853 SRAM interface with integrated interrupt
|
||||
controller and timer
|
||||
Fairchild F3853 SMI, F3851 PSU, F3856 PSU, F38T56 PSU
|
||||
|
||||
This chip is a timer shift register, basically the same as in the
|
||||
F3851.
|
||||
|
||||
****************************************************************************
|
||||
_____ _____
|
||||
Vgg 1 |* \_/ | 40 Vdd
|
||||
PHI 2 | | 39 ROMC4
|
||||
WRITE 3 | | 38 ROMC3
|
||||
_INT REQ 4 | | 37 ROMC2
|
||||
_PRI IN 5 | | 36 ROMC1
|
||||
_RAM WRITE 6 | | 35 ROMC0
|
||||
_EXT INT 7 | | 34 CPU READ
|
||||
ADDR7 8 | | 33 REG DR
|
||||
ADDR6 9 | | 32 ADDR15
|
||||
ADDR5 10 | F3853 | 31 ADDR14
|
||||
ADDR4 11 | | 30 ADDR13
|
||||
ADDR3 12 | | 29 ADDR12
|
||||
ADDR2 13 | | 28 ADDR11
|
||||
ADDR1 14 | | 27 ADDR10
|
||||
ADDR0 15 | | 26 ADDR9
|
||||
DB0 16 | | 25 ADDR8
|
||||
DB1 17 | | 24 DB7
|
||||
DB2 18 | | 23 DB6
|
||||
DB3 19 | | 22 DB5
|
||||
Vss 20 |_____________| 21 DB4
|
||||
|
||||
***************************************************************************/
|
||||
*/
|
||||
|
||||
#ifndef MAME_MACHINE_F3853_H
|
||||
#define MAME_MACHINE_F3853_H
|
||||
|
||||
#pragma once
|
||||
|
||||
// pinout reference
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
/*
|
||||
_____ _____
|
||||
Vgg 1 |* \_/ | 40 Vdd
|
||||
PHI 2 | | 39 ROMC4
|
||||
WRITE 3 | | 38 ROMC3
|
||||
_INT REQ 4 | | 37 ROMC2
|
||||
_PRI IN 5 | | 36 ROMC1
|
||||
_RAM WRITE 6 | | 35 ROMC0
|
||||
_EXT INT 7 | | 34 CPU READ
|
||||
ADDR7 8 | | 33 REG DR
|
||||
ADDR6 9 | | 32 ADDR15
|
||||
ADDR5 10 | F3853 | 31 ADDR14
|
||||
ADDR4 11 | | 30 ADDR13
|
||||
ADDR3 12 | | 29 ADDR12
|
||||
ADDR2 13 | | 28 ADDR11
|
||||
ADDR1 14 | | 27 ADDR10
|
||||
ADDR0 15 | | 26 ADDR9
|
||||
DB0 16 | | 25 ADDR8
|
||||
DB1 17 | | 24 DB7
|
||||
DB2 18 | | 23 DB6
|
||||
DB3 19 | | 22 DB5
|
||||
Vss 20 |_____________| 21 DB4
|
||||
|
||||
_____ _____
|
||||
_I/O B7 1 |* \_/ | 40 DB7
|
||||
_I/O A7 2 | | 39 DB6
|
||||
Vgg 3 | | 38 _I/O B6
|
||||
Vdd 4 | | 37 _I/O A6
|
||||
_EXT INT 5 | | 36 _I/O A5
|
||||
_PRI OUT 6 | | 35 _I/O B5
|
||||
WRITE 7 | | 34 DB5
|
||||
PHI 8 | | 33 DB4
|
||||
_INT REQ 9 | F3851 | 32 _I/O B4
|
||||
_PRI IN 10 | F3856 | 31 _I/O A4
|
||||
_DBDR 11 | F38T56 | 30 _I/O A3
|
||||
STROBE 12 | | 29 _I/O B3
|
||||
ROMC4 13 | | 28 DB3
|
||||
ROMC3 14 | | 27 DB2
|
||||
ROMC2 15 | | 26 _I/O B2
|
||||
ROMC1 16 | | 25 _I/O A2
|
||||
ROMC0 17 | | 24 _I/O A1
|
||||
Vss 18 | | 23 _I/O B1
|
||||
_I/O A0 19 | | 22 DB1
|
||||
_I/O B0 20 |_____________| 21 DB0
|
||||
|
||||
F38T56 is internal in F3870
|
||||
note: STROBE is N/C on F3851
|
||||
*/
|
||||
|
||||
// ======================> f3853_device
|
||||
|
||||
class f3853_device : public device_t
|
||||
{
|
||||
@ -85,8 +103,8 @@ protected:
|
||||
|
||||
uint16_t m_int_vector; // Bit 7 is set to 0 for timer interrupts, 1 for external interrupts
|
||||
u8 m_prescaler;
|
||||
bool m_external_enable;
|
||||
bool m_timer_enable;
|
||||
bool m_external_int_enable;
|
||||
bool m_timer_int_enable;
|
||||
|
||||
bool m_request_flipflop;
|
||||
|
||||
|
@ -28,6 +28,9 @@ hardware notes:
|
||||
|
||||
TODO:
|
||||
- discrete sound, currently it's emulated crudely, just enough to make it beep when supposed to
|
||||
- MCU frequency was measured approx 2.1MHz on its XTL2 pin, but considering that
|
||||
the MK3870 has an internal /2 divider, this is way too slow when compared to
|
||||
video references of the game
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
@ -265,11 +268,11 @@ INPUT_PORTS_END
|
||||
void tgm_state::tgm(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
F8(config, m_maincpu, 2000000); // MK3870, measured around 2.1MHz
|
||||
F8(config, m_maincpu, 4000000/2); // MK3870, frequency is approximate
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &tgm_state::main_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &tgm_state::main_io);
|
||||
|
||||
f38t56_device &psu(F38T56(config, "psu", 2000000));
|
||||
f38t56_device &psu(F38T56(config, "psu", 4000000/2));
|
||||
psu.write_a().set(FUNC(tgm_state::sound_w));
|
||||
psu.write_b().set(FUNC(tgm_state::digit_w));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user