Add AMD/Plessey 2812 FIFO device (for WIP Star Rider driver)

This commit is contained in:
Vas Crabb 2019-04-21 13:43:52 +10:00
parent e837e67101
commit 112062f7bb
6 changed files with 338 additions and 14 deletions

View File

@ -177,6 +177,18 @@ if (MACHINES["LSI53C810"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/machine/2812fifo.h,MACHINES["2812FIFO"] = true
---------------------------------------------------
if (MACHINES["2812FIFO"]~=null) then
files {
MAME_DIR .. "src/devices/machine/2812fifo.cpp",
MAME_DIR .. "src/devices/machine/2812fifo.h",
}
end
---------------------------------------------------
--
--@src/devices/machine/6522via.h,MACHINES["6522VIA"] = true

View File

@ -371,6 +371,7 @@ MACHINES["DMAC"] = true
MACHINES["GAYLE"] = true
MACHINES["NCR53C7XX"] = true
MACHINES["LSI53C810"] = true
MACHINES["2812FIFO"] = true
MACHINES["6522VIA"] = true
MACHINES["TPI6525"] = true
MACHINES["RIOT6532"] = true

View File

@ -0,0 +1,235 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/**************************************************************************
2812 32*8 First-In First-Out Memory (AMD, Plessey, and others)
These devices contain a file of 32 data registers and corresponding
control registers indicating when the data registers are valid.
Data ripples from the input register towards the output until it
reaches a register containing valid data. The first and last data
registers support serial operation.
The half-full flag responds to the number of valid locations. It
favours glitch-free operation over precision. It's never asserted
when fewer than 13 registers are valid, and it's always asserted
when at least 16 registers are valid.
TODO:
* Propagation delays
* Serial I/O
* Am2813 32*9 version without serial I/O
**************************************************************************/
#include "emu.h"
#include "2812fifo.h"
#include <algorithm>
#include <cassert>
DEFINE_DEVICE_TYPE(FIFO2812, fifo2812_device, "fifo2812", "2812 32*8 FIFO Memory");
fifo2812_device::fifo2812_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
device_t(mconfig, FIFO2812, tag, owner, clock),
m_q_cb(*this),
m_ir_cb(*this),
m_or_cb(*this),
m_flag_cb(*this),
m_control(0U),
m_count(0U),
m_d(0U), m_mr(1U), m_pl(0U), m_pd(0U), m_oe(1U)
{
std::fill(std::begin(m_data), std::end(m_data), 0U);
}
WRITE_LINE_MEMBER(fifo2812_device::mr_w)
{
if (bool(state) != bool(m_mr))
{
m_mr = state ? 1U : 0U;
if (!m_mr)
device_reset();
}
}
WRITE_LINE_MEMBER(fifo2812_device::pl_w)
{
if (bool(state) != bool(m_pl))
{
m_pl = state ? 1U : 0U;
if (m_mr)
{
if (m_pl)
{
m_data[0] = m_d;
if (!BIT(m_control, 0))
{
m_control |= u32(1) << 0;
m_ir_cb(1);
if (15U == ++m_count)
m_flag_cb(1);
}
}
else if (BIT(m_control, 0) && !BIT(m_control, 1))
{
unsigned bit(1);
m_data[bit] = m_data[bit - 1];
m_control |= u32(1) << bit;
m_control &= ~(u32(1) << (bit - 1));
m_ir_cb(0);
for (++bit; ((LENGTH - 1) > bit) && !BIT(m_control, bit); ++bit)
{
m_data[bit] = m_data[bit - 1];
m_control |= u32(1) << bit;
m_control &= ~(u32(1) << (bit - 1));
}
if (!m_pd && ((LENGTH - 1) == bit) && !BIT(m_control, bit))
{
if (m_data[bit] != m_data[bit - 1])
{
m_data[bit] = m_data[bit - 1];
if (m_oe)
m_q_cb(0U, m_data[bit], 0xffU);
}
m_control |= u32(1) << bit;
m_control &= ~(u32(1) << (bit - 1));
m_or_cb(1);
}
}
}
}
}
WRITE_LINE_MEMBER(fifo2812_device::pd_w)
{
if (bool(state) != bool(m_pd))
{
m_pd = state ? 1U : 0U;
if (m_mr)
{
if (m_pd)
{
if (BIT(m_control, LENGTH - 1))
{
m_control &= ~(u32(1) << (LENGTH - 1));
m_or_cb(0);
if (15U == m_count--)
m_flag_cb(0);
}
}
else if (BIT(m_control, LENGTH - 2))
{
unsigned bit(LENGTH - 2);
if (m_data[bit + 1] != m_data[bit])
{
m_data[bit + 1] = m_data[bit];
if (m_oe)
m_q_cb(0U, m_data[bit + 1], 0xffU);
}
m_control |= u32(1) << (bit + 1);
m_control &= ~(u32(1) << bit);
m_or_cb(1);
for (--bit; (0U < bit) && BIT(m_control, bit); --bit)
{
m_data[bit + 1] = m_data[bit];
m_control |= u32(1) << (bit + 1);
m_control &= ~(u32(1) << bit);
}
if (!m_pl && (0U == bit) && BIT(m_control, bit))
{
m_data[bit + 1] = m_data[bit];
m_control |= u32(1) << (bit + 1);
m_control &= ~(u32(1) << bit);
m_ir_cb(0);
}
}
}
}
}
WRITE_LINE_MEMBER(fifo2812_device::oe_w)
{
if (bool(state) != bool(m_oe))
{
m_oe = state ? 1U : 0U;
if (m_oe)
m_q_cb(0U, m_data[LENGTH - 1], 0xffU);
else
m_q_cb(0U, 0xffU, 0x00U);
}
}
u8 fifo2812_device::read()
{
if (machine().side_effects_disabled())
{
return m_data[LENGTH - 1];
}
else
{
assert(!m_pd);
pd_w(1);
u8 const data(m_data[LENGTH - 1]);
pd_w(0);
return data;
}
}
void fifo2812_device::write(u8 data)
{
assert(!m_pl);
d_w(data);
pl_w(1);
pl_w(0);
}
void fifo2812_device::device_resolve_objects()
{
m_q_cb.resolve_safe();
m_ir_cb.resolve_safe();
m_or_cb.resolve_safe();
m_flag_cb.resolve_safe();
m_d = 0U;
m_mr = 1U;
m_pl = 0U;
m_pd = 0U;
m_oe = 1U;
}
void fifo2812_device::device_start()
{
save_item(NAME(m_control));
save_item(NAME(m_data));
save_item(NAME(m_count));
save_item(NAME(m_d));
save_item(NAME(m_mr));
save_item(NAME(m_pl));
save_item(NAME(m_pd));
save_item(NAME(m_oe));
}
void fifo2812_device::device_reset()
{
u32 const prev_ir(BIT(m_control, 0));
u32 const prev_or(BIT(m_control, LENGTH - 1));
u8 const prev_q(m_data[LENGTH - 1]);
bool const prev_flag(15U <= m_count);
m_control = 0U;
std::fill(std::begin(m_data), std::end(m_data), 0U);
m_count = 0U;
if (m_oe && (0U != prev_q))
m_q_cb(0U, 0U, 0xffU);
if (prev_ir)
m_ir_cb(0);
if (prev_or)
m_or_cb(0);
if (prev_flag)
m_flag_cb(0);
}

View File

@ -0,0 +1,84 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/**************************************************************************
2812 32*8 First-In First-Out Memory (AMD, Plessey, and others)
____ ____
D0 1 |* \_/ | 28 D1
Vgg 2 | | 27 D2
OR 3 | | 26 D3
/MR 4 | | 25 /IR
PD 5 | | 24 Vss
SD 6 | | 23 D4
Q0 7 | 2812 | 22 D5
Q1 8 | | 21 D6
Q2 9 | | 20 D7
Q3 10 | | 19 FLAG
OE 11 | | 18 PL
Q4 12 | | 17 SL
Q5 13 | | 16 Vdd
Q6 14 |___________| 15 Q7
**************************************************************************/
#ifndef MAME_MACHINE_2812FIFO_H
#define MAME_MACHINE_2812FIFO_H
#pragma once
#include <array>
class fifo2812_device : public device_t
{
public:
// standard constructor
fifo2812_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
// callbacks
auto q_cb() { return m_q_cb.bind(); }
auto ir_cb() { return m_ir_cb.bind(); }
auto or_cb() { return m_or_cb.bind(); }
auto flag_cb() { return m_flag_cb.bind(); }
// control signal interface
void d_w(u8 data) { m_d = data; }
DECLARE_WRITE_LINE_MEMBER(mr_w);
DECLARE_WRITE_LINE_MEMBER(pl_w);
DECLARE_WRITE_LINE_MEMBER(pd_w);
DECLARE_WRITE_LINE_MEMBER(oe_w);
u8 q_r() const { return m_oe ? m_data[LENGTH - 1] : 0xff; }
DECLARE_READ_LINE_MEMBER(ir_r) const { return BIT(m_control, 0); }
DECLARE_READ_LINE_MEMBER(or_r) const { return BIT(m_control, LENGTH - 1); }
DECLARE_READ_LINE_MEMBER(flag_r);
// read/write interface
u8 read();
void write(u8 data);
protected:
// device_t implementation
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
private:
enum { LENGTH = 32 };
// output callbacks
devcb_write8 m_q_cb;
devcb_write_line m_ir_cb;
devcb_write_line m_or_cb;
devcb_write_line m_flag_cb;
// registers/state
u32 m_control;
std::array<u8, LENGTH> m_data;
u8 m_count;
// input line states
u8 m_d, m_mr, m_pl, m_pd, m_oe;
};
DECLARE_DEVICE_TYPE(FIFO2812, fifo2812_device)
#endif // MAME_MACHINE_2812FIFO_H

View File

@ -660,10 +660,6 @@ void ptm6840_device::set_gate(int idx, int state)
m_gate[idx] = state;
}
WRITE_LINE_MEMBER( ptm6840_device::set_g1 ) { set_gate(0, state); }
WRITE_LINE_MEMBER( ptm6840_device::set_g2 ) { set_gate(1, state); }
WRITE_LINE_MEMBER( ptm6840_device::set_g3 ) { set_gate(2, state); }
//-------------------------------------------------
// set_clock - set clock status (0 or 1)
@ -682,10 +678,6 @@ void ptm6840_device::set_clock(int idx, int state)
}
}
WRITE_LINE_MEMBER( ptm6840_device::set_c1 ) { set_clock(0, state); }
WRITE_LINE_MEMBER( ptm6840_device::set_c2 ) { set_clock(1, state); }
WRITE_LINE_MEMBER( ptm6840_device::set_c3 ) { set_clock(2, state); }
//-------------------------------------------------
// set_ext_clock - set external clock frequency

View File

@ -43,14 +43,14 @@ public:
uint8_t read(offs_t offset);
void set_gate(int idx, int state);
DECLARE_WRITE_LINE_MEMBER( set_g1 );
DECLARE_WRITE_LINE_MEMBER( set_g2 );
DECLARE_WRITE_LINE_MEMBER( set_g3 );
DECLARE_WRITE_LINE_MEMBER( set_g1 ) { set_gate(0, state); }
DECLARE_WRITE_LINE_MEMBER( set_g2 ) { set_gate(1, state); }
DECLARE_WRITE_LINE_MEMBER( set_g3 ) { set_gate(2, state); }
void set_clock(int idx, int state);
DECLARE_WRITE_LINE_MEMBER( set_c1 );
DECLARE_WRITE_LINE_MEMBER( set_c2 );
DECLARE_WRITE_LINE_MEMBER( set_c3 );
DECLARE_WRITE_LINE_MEMBER( set_c1 ) { set_clock(0, state); }
DECLARE_WRITE_LINE_MEMBER( set_c2 ) { set_clock(1, state); }
DECLARE_WRITE_LINE_MEMBER( set_c3 ) { set_clock(2, state); }
void update_interrupts();