mirror of
https://github.com/holub/mame
synced 2025-10-08 17:37:56 +03:00
mc14411: NEW DEVICE Motorola MC14411 Bit Rate Generator
This commit is contained in:
parent
d7452d300a
commit
4af3d0ac83
@ -1574,6 +1574,18 @@ if (MACHINES["MC146818"]~=null) then
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------
|
||||||
|
--
|
||||||
|
--@src/devices/machine/mc14411.h,MACHINES["MC14411"] = true
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
if (MACHINES["MC14411"]~=null) then
|
||||||
|
files {
|
||||||
|
MAME_DIR .. "src/devices/machine/mc14411.cpp",
|
||||||
|
MAME_DIR .. "src/devices/machine/mc14411.h",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
--
|
--
|
||||||
--@src/devices/machine/mc2661.h,MACHINES["MC2661"] = true
|
--@src/devices/machine/mc2661.h,MACHINES["MC2661"] = true
|
||||||
|
@ -472,6 +472,7 @@ MACHINES["MB87078"] = true
|
|||||||
--MACHINES["MB8795"] = true
|
--MACHINES["MB8795"] = true
|
||||||
MACHINES["MB89352"] = true
|
MACHINES["MB89352"] = true
|
||||||
MACHINES["MB89371"] = true
|
MACHINES["MB89371"] = true
|
||||||
|
--MACHINES["MC14411"] = true
|
||||||
MACHINES["MC146818"] = true
|
MACHINES["MC146818"] = true
|
||||||
MACHINES["MC2661"] = true
|
MACHINES["MC2661"] = true
|
||||||
MACHINES["MC6843"] = true
|
MACHINES["MC6843"] = true
|
||||||
|
@ -461,6 +461,7 @@ MACHINES["MB87078"] = true
|
|||||||
MACHINES["MB8795"] = true
|
MACHINES["MB8795"] = true
|
||||||
MACHINES["MB89352"] = true
|
MACHINES["MB89352"] = true
|
||||||
MACHINES["MB89371"] = true
|
MACHINES["MB89371"] = true
|
||||||
|
MACHINES["MC14411"] = true
|
||||||
MACHINES["MC146818"] = true
|
MACHINES["MC146818"] = true
|
||||||
MACHINES["MC2661"] = true
|
MACHINES["MC2661"] = true
|
||||||
MACHINES["MC6843"] = true
|
MACHINES["MC6843"] = true
|
||||||
|
217
src/devices/machine/mc14411.cpp
Normal file
217
src/devices/machine/mc14411.cpp
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Joakim Larsson Edstrom
|
||||||
|
/*********************************************************************
|
||||||
|
|
||||||
|
mc14411.cpp
|
||||||
|
|
||||||
|
Motorola Bit Rate Generator
|
||||||
|
|
||||||
|
This device assumed a fixed rate clock/crystal and does not support
|
||||||
|
changing it through pin 21. All other features are implemented.
|
||||||
|
|
||||||
|
*********************************************************************/
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "mc14411.h"
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
MACROS
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
//#define LOG_GENERAL (1U << 0) // Already defined in logmacro.h
|
||||||
|
#define LOG_SETUP (1U << 1)
|
||||||
|
|
||||||
|
//#define VERBOSE (LOG_GENERAL|LOG_SETUP)
|
||||||
|
//#define LOG_OUTPUT_FUNC printf
|
||||||
|
|
||||||
|
#include "logmacro.h"
|
||||||
|
|
||||||
|
//#define LOG(...) LOGMASKED(LOG_GENERAL, __VA_ARGS__) // Already defined in logmacro.h
|
||||||
|
#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define FUNCNAME __func__
|
||||||
|
#define LLFORMAT "%I64d"
|
||||||
|
#else
|
||||||
|
#define FUNCNAME __PRETTY_FUNCTION__
|
||||||
|
#define LLFORMAT "%lld"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
LOCAL VARIABLES
|
||||||
|
***************************************************************************/
|
||||||
|
// 0/0 0/1 1/0 1/1 RSB/RSA
|
||||||
|
// X1 X8 X16 X64
|
||||||
|
const int mc14411_device::counter_divider[16][4] = {
|
||||||
|
{ 192, 24, 12, 3 }, // F1
|
||||||
|
{ 256, 32, 16, 4 }, // F2
|
||||||
|
{ 384, 48, 24, 6 }, // F3
|
||||||
|
{ 512, 64, 32, 8 }, // F4
|
||||||
|
{ 768, 96, 48, 12 }, // F5
|
||||||
|
{ 1024, 128, 64, 16 }, // F6
|
||||||
|
{ 1536, 192, 96, 24 }, // F7
|
||||||
|
{ 3072, 384, 192, 48 }, // F8
|
||||||
|
{ 6144, 768, 384, 96 }, // F9
|
||||||
|
{ 9216, 1152, 576, 144 }, // F10
|
||||||
|
{ 12288, 1536, 768, 192 }, // F11
|
||||||
|
{ 13696, 1712, 856, 214 }, // F12
|
||||||
|
{ 16768, 2096, 1048, 262 }, // F13
|
||||||
|
{ 24576, 3072, 1536, 384 }, // F14
|
||||||
|
{ 2, 2, 2, 2 }, // F15
|
||||||
|
{ 1, 1, 1, 1 } // F16
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// DEVICE DEFINITIONS
|
||||||
|
//**************************************************************************
|
||||||
|
// device type definition
|
||||||
|
DEFINE_DEVICE_TYPE(MC14411, mc14411_device, "mc14411", "MC14411 BRG")
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
LIVE DEVICE
|
||||||
|
***************************************************************************/
|
||||||
|
mc14411_device::mc14411_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||||
|
: mc14411_device(mconfig, MC14411, tag, owner, clock)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
mc14411_device::mc14411_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||||
|
: device_t(mconfig, type, tag, owner, clock)
|
||||||
|
, m_out_fx_cbs{*this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this }
|
||||||
|
, m_divider(0)
|
||||||
|
, m_reset(CLEAR_LINE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// device_start - device-specific startup
|
||||||
|
//-------------------------------------------------
|
||||||
|
void mc14411_device::device_start()
|
||||||
|
{
|
||||||
|
LOGSETUP("%s\n", FUNCNAME);
|
||||||
|
|
||||||
|
memset(m_fx_timer, '\0', sizeof(m_fx_timer));
|
||||||
|
for (int i = F1; i <= F16; i++)
|
||||||
|
{
|
||||||
|
m_out_fx_cbs[i].resolve();
|
||||||
|
if (!m_out_fx_cbs[i].isnull()) m_fx_timer[i] = timer_alloc(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
save_item(NAME(m_divider));
|
||||||
|
save_item(NAME(m_reset));
|
||||||
|
|
||||||
|
m_reset_timer = timer_alloc(TIMER_ID_RESET);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// device_reset - is called by the mame framework or by the owning device
|
||||||
|
// driver or by ASSERTING the reset line through set_reset_line
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
void mc14411_device::device_reset()
|
||||||
|
{
|
||||||
|
LOGSETUP("%s\n", FUNCNAME);
|
||||||
|
|
||||||
|
for (int i = F1; i <= F16; i++)
|
||||||
|
{
|
||||||
|
if (!m_out_fx_cbs[i].isnull())
|
||||||
|
{
|
||||||
|
// Reset line according to datasheet and remember it for transitions to come
|
||||||
|
(m_out_fx_cbs[i])(m_fx_state[i] = (i < F15 ? 0 : 1));
|
||||||
|
|
||||||
|
// Arm the timer based on the selected divider and the crystal value
|
||||||
|
double hz = clock()/counter_divider[i][m_divider] * 2; // 2 flanks per cycle
|
||||||
|
m_fx_timer[i]->adjust(attotime::from_hz(hz), i, attotime::from_hz(hz));
|
||||||
|
LOGSETUP(" - arming timer for F%d at %fHz\n", i + 1, hz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_reset == ASSERT_LINE)
|
||||||
|
{
|
||||||
|
m_reset_timer->adjust(attotime::from_nsec((double)900), TIMER_ID_RESET, attotime::from_nsec((double)900));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// device_timer - handler timer events
|
||||||
|
//-------------------------------------------------
|
||||||
|
void mc14411_device::device_timer (emu_timer &timer, device_timer_id id, int32_t param, void *ptr)
|
||||||
|
{
|
||||||
|
switch(id)
|
||||||
|
{
|
||||||
|
case F1:
|
||||||
|
case F2:
|
||||||
|
case F3:
|
||||||
|
case F4:
|
||||||
|
case F5:
|
||||||
|
case F6:
|
||||||
|
case F7:
|
||||||
|
case F8:
|
||||||
|
case F9:
|
||||||
|
case F10:
|
||||||
|
case F11:
|
||||||
|
case F12:
|
||||||
|
case F13:
|
||||||
|
case F14:
|
||||||
|
case F15:
|
||||||
|
case F16:
|
||||||
|
(m_out_fx_cbs[id])(m_fx_state[id]++ & 1);
|
||||||
|
break;
|
||||||
|
case TIMER_ID_RESET:
|
||||||
|
// NOTE: This check could be triggered by either faulty hardware design or non accurate emulation so is just informative if the reset line is handled
|
||||||
|
// explicitelly instead of relying on calling device_reset
|
||||||
|
if (!(m_reset == ASSERT_LINE))
|
||||||
|
{
|
||||||
|
LOG("Reset pulse is too short, should be 900nS minimum");
|
||||||
|
logerror("Reset pulse is too short, should be 900nS minimum");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG("Unhandled Timer ID %d\n", id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// rate_select_w - implements the RSA and RSB input pins
|
||||||
|
// TODO: Needs to check real device behaviour how changing
|
||||||
|
// divider at run time affects wave forms
|
||||||
|
//--------------------------------------------------------
|
||||||
|
WRITE8_MEMBER( mc14411_device::rate_select_w)
|
||||||
|
{
|
||||||
|
LOGSETUP("%s %02x\n", FUNCNAME, data);
|
||||||
|
|
||||||
|
m_divider = data & 3;
|
||||||
|
|
||||||
|
for (int i = F1; i <= F16; i++)
|
||||||
|
{
|
||||||
|
if (!m_out_fx_cbs[i].isnull())
|
||||||
|
{
|
||||||
|
// Re-arm the timer based on the new selected divider and the crystal value
|
||||||
|
double hz = clock()/counter_divider[i][m_divider] * 2; // 2 flanks per cycle
|
||||||
|
m_fx_timer[i]->adjust(attotime::from_hz(hz), i, attotime::from_hz(hz));
|
||||||
|
LOGSETUP(" - Re-arming timer for F%d at %fHz\n", i + 1, hz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------
|
||||||
|
// reset_w - implements software controlled reset
|
||||||
|
//------------------------------------------------
|
||||||
|
WRITE_LINE_MEMBER( mc14411_device::reset_w)
|
||||||
|
{
|
||||||
|
LOGSETUP("%s %02x\n", FUNCNAME, state);
|
||||||
|
|
||||||
|
m_reset = state;
|
||||||
|
|
||||||
|
if (m_reset == ASSERT_LINE)
|
||||||
|
{
|
||||||
|
LOGSETUP(" - Asserting reset\n");
|
||||||
|
device_reset();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGSETUP(" - Clearing reset\n");
|
||||||
|
}
|
||||||
|
}
|
160
src/devices/machine/mc14411.h
Normal file
160
src/devices/machine/mc14411.h
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Joakim Larsson Edstrom
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* Motorola MC14411 - bit rate generator. It utilizes a frequency divider
|
||||||
|
* network to provide a wide range of output frequencies. A crystal controlled
|
||||||
|
* oscillator is the clock source for the network. A 2 bit adress is used to
|
||||||
|
* select one of four multiple output clock rates.
|
||||||
|
*
|
||||||
|
* - Single 5V sower supply
|
||||||
|
* - Internal Oscillator Crystal Controlled for stability (1.8432 MHz)
|
||||||
|
* - Sixteen Different Output Clock Rates
|
||||||
|
* - 50% Output Duty Cycle
|
||||||
|
* - Programmable Time Bases for one of four Multiple Output Rates
|
||||||
|
* - Buffered Output compatible with low power TTL
|
||||||
|
* - Noice immunity = 45% of VDD Typlical
|
||||||
|
* - Diode protection on All Inputs
|
||||||
|
* - External Clock may be applied to pin 21
|
||||||
|
* - Internal pullup on reset input
|
||||||
|
* _____ _____
|
||||||
|
* F1 1 |* \_/ | 24 VDD
|
||||||
|
* F3 2 | | 23 Rate Select A
|
||||||
|
* F5 3 | | 22 Rate Select B
|
||||||
|
* F7 4 | | 21 Xtal In
|
||||||
|
* F8 5 | | 20 Xtal Out
|
||||||
|
* F10 6 | | 19 F16
|
||||||
|
* F9 7 | MC14411 | 18 F15
|
||||||
|
* F11 8 | | 17 F2
|
||||||
|
* F14 9 | | 16 F4
|
||||||
|
* Reset* 10 | | 15 F6
|
||||||
|
* Not Used 11 | | 14 F12
|
||||||
|
* VSS 12 |_____________| 13 F13
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* +----------+-------Output Rates (Hz)-------+
|
||||||
|
* | Output | Rate Select B and A pins |
|
||||||
|
* | Number | X64 11| X16 10| X8 01 | X1 00 |
|
||||||
|
* |----------+-------------------------------+
|
||||||
|
* | Fl | 614.4k| 153.6k| 76.8k| 9600 |
|
||||||
|
* | F2 | 46O.8k| 115.2k| 57.6k| 7200 |
|
||||||
|
* | F3 | 3O7.2k| 76.8k| 38.4k| 4800 |
|
||||||
|
* | F4 | 23O.4k| 57.6k| 28.8k| 3600 |
|
||||||
|
* | F5 | 153.6k| 38.4k| 19.2k| 2400 |
|
||||||
|
* | F6 | 115.2k| 28.8k| 14.4k| 1800 |
|
||||||
|
* | F7 | 76.8k| 19.2k| 9600 | 1200 |
|
||||||
|
* | FS | 38.4k| 9600 | 4800 | 600 |
|
||||||
|
* | F9 | 19.2k| 4800 | 2400 | 300 |
|
||||||
|
* | F1O | 12.8k| 3200 | 1600 | 200 |
|
||||||
|
* | Fll | 9600 | 2400 | 1200 | 150 |
|
||||||
|
* | F12 | 8613.2| 2153.3| 1076.6| 134.5|
|
||||||
|
* | F13 | 7035.5| 1758.8| 879.4| 109.9|
|
||||||
|
* | F14 | 4800 | 1200 | 600 | 75 |
|
||||||
|
* | F15 | 921.6k| 921.6k| 921.6k| 921.6k|
|
||||||
|
* | F16 | 1.843M| 1.843M| 1.843M| 1.843M|
|
||||||
|
* +------------------------------------------+
|
||||||
|
* - F16 is a buffered oscillator output
|
||||||
|
*
|
||||||
|
* The device is designed to work with 1.843MHz crystal so it is assumed that
|
||||||
|
* an external clock source attached to pin 21 is also fixed thus not need to
|
||||||
|
* interface through a callback interface.
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAME_MACHINE_MC14411_H
|
||||||
|
#define MAME_MACHINE_MC14411_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// DEVICE CONFIGURATION MACROS
|
||||||
|
//**************************************************************************
|
||||||
|
#define MCFG_MC14411_ADD(_tag, _clock) MCFG_DEVICE_ADD(_tag, MC14411, _clock)
|
||||||
|
|
||||||
|
#define MCFG_MC14411_F1_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 0, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F2_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 1, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F3_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 2, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F4_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 3, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F5_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 4, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F6_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 5, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F7_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 6, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F8_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 7, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F9_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 8, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F10_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 9, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F11_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 10, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F12_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 11, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F13_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 12, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F14_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 13, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F15_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 14, DEVCB_##_devcb);
|
||||||
|
#define MCFG_MC14411_F16_CB(_devcb) devcb = &mc14411_device::set_out_fx_cb(*device, 15, DEVCB_##_devcb);
|
||||||
|
|
||||||
|
#define MCFG_MC14411_RSA 0x01
|
||||||
|
#define MCFG_MC14411_RSB 0x02
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// TYPE DEFINITIONS
|
||||||
|
//**************************************************************************
|
||||||
|
class mc14411_device : public device_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// construction/destruction
|
||||||
|
mc14411_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||||
|
|
||||||
|
template <class Object> static devcb_base &set_out_fx_cb(device_t &device, int index, Object &&cb) { return downcast<mc14411_device &>(device).m_out_fx_cbs[index].set_callback(std::forward<Object>(cb)); }
|
||||||
|
|
||||||
|
DECLARE_WRITE_LINE_MEMBER(reset_w);
|
||||||
|
DECLARE_WRITE8_MEMBER(rate_select_w);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
mc14411_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||||
|
|
||||||
|
// device-level overrides
|
||||||
|
virtual void device_start() override;
|
||||||
|
virtual void device_reset() override;
|
||||||
|
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// timers
|
||||||
|
enum // indexes
|
||||||
|
{
|
||||||
|
F1 = 0,
|
||||||
|
F2 = 1,
|
||||||
|
F3 = 2,
|
||||||
|
F4 = 3,
|
||||||
|
F5 = 4,
|
||||||
|
F6 = 5,
|
||||||
|
F7 = 6,
|
||||||
|
F8 = 7,
|
||||||
|
F9 = 8,
|
||||||
|
F10 = 9,
|
||||||
|
F11 = 10,
|
||||||
|
F12 = 11,
|
||||||
|
F13 = 12,
|
||||||
|
F14 = 13,
|
||||||
|
F15 = 14,
|
||||||
|
F16 = 15
|
||||||
|
};
|
||||||
|
|
||||||
|
emu_timer *m_fx_timer[16];
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
TIMER_ID_RESET = 16
|
||||||
|
};
|
||||||
|
emu_timer *m_reset_timer;
|
||||||
|
|
||||||
|
// F1-F16 Output line states
|
||||||
|
uint32_t m_fx_state[16];
|
||||||
|
|
||||||
|
// divider matrix
|
||||||
|
static const int counter_divider[16][4];
|
||||||
|
|
||||||
|
devcb_write_line m_out_fx_cbs[16];
|
||||||
|
|
||||||
|
uint32_t m_divider; // main divider to use, 0-3 column index into counter_divider
|
||||||
|
uint32_t m_reset; // Reset line state
|
||||||
|
};
|
||||||
|
|
||||||
|
// device type definition
|
||||||
|
DECLARE_DEVICE_TYPE(MC14411, mc14411_device)
|
||||||
|
|
||||||
|
#endif // MAME_MACHINE_MC14411_H
|
Loading…
Reference in New Issue
Block a user