diff options
Diffstat (limited to 'src/devices/machine/f4702.cpp')
-rw-r--r-- | src/devices/machine/f4702.cpp | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/src/devices/machine/f4702.cpp b/src/devices/machine/f4702.cpp new file mode 100644 index 00000000000..499f1a6793a --- /dev/null +++ b/src/devices/machine/f4702.cpp @@ -0,0 +1,260 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/**************************************************************************** + + Fairchild 4702B Programmable Bit Rate Generator + + Originally numbered 34702 in Fairchild's isoplanar CMOS series (whose + lower-numbered products were logical equivalents of RCA CD4000 and + Motorola MC14500 series devices), this BRG incorporates some unusually + sophisticated features into its 16-pin package, which may be why + Fairchild classified it as a LSI IC. + + The standard 2.4576 MHz master clock, either generated from a crystal + oscillator (Ix, Ox) or provided as a TTL input (CP), is first prescaled + by dividing by 8 and then divided further down through a network of + counters with differing periods. These counters are tapped at 13 points, + each frequency being 16 times a common baud rate. The rate output (Z), + whose changes are synchronized with the master clock, is multiplexed + from any one of these internal sources or an external rate input (Im) by + a 4-bit select code (S0, S1, S2, S3). + + The buffered clock output (CO) and the three prescaler divisions (Q0, + Q1, Q2) are not only conveniently available externally for clocking + additional 4702s or other devices, but can also be exploited to + generate 8 baud rates simultaneously, with the aid of a Fairchild 93L34 + (or compatible) addressable latch for demultiplexing the channels. In + this configuration, the CO, Q and Z outputs are respectively tied to the + latch's enable, address and data inputs, and the Q outputs are directly + or indirectly fed back into the S inputs. (Fairchild even suggested + scanning 9LS170 register files with the Q outputs so as to make each + rate individually programmable.) + + The rate select codes are arranged so that connecting a simple five- + point switch to the S inputs can obtain 110, 150, 300, 1200 or 2400 + baud, and only three binary switches are needed to select between all + five of those rates plus 1800, 4800 and 9600 baud. 19200 baud can also + be obtained by tapping the Q2 output, but no more than 4 internally + multiplexed rates can be used at once if Im is generated from Q2. + + All inputs and outputs except Ix and Ox are TTL-compatible, with the + inputs also having internal pull-ups so switches can be connected + directly. + + To enable the Ix/Ox oscillator circuit, Ecp must be high and CP must + remain low, since Ecp and CP both being high places the chip in a + continuous reset mode (except for the CO output). If Ecp is brought + low, the initialization circuit produces an internal master reset + pulse the first time CP goes high. Neither of these two reset methods + was used much in practice. + + Intersil, one of not many companies to second-source the original 4702, + later produced IM4712, a minor variant which requires fewer external + discrete components to drive the crystal oscillator but is otherwise + logically identical. + +****************************************************************************/ + +#include "emu.h" +#include "f4702.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(F4702, f4702_device, "f4702", "Fairchild 4702B Bit Rate Generator") + + +//************************************************************************** +// DEVICE CONSTRUCTION AND INITIALIZATION +//************************************************************************** + +//------------------------------------------------- +// f4702_device - constructor +//------------------------------------------------- + +f4702_device::f4702_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, F4702, tag, owner, clock) + , device_execute_interface(mconfig, *this) + , m_s_callback(*this, 15) + , m_z_callback(*this) + , m_main_counter(0) + , m_div_200_50(0) + , m_div_134_5(0) + , m_div_110(0) + , m_div_1800(0) + , m_im(true) + , m_s(0) + , m_icount(0) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void f4702_device::device_start() +{ + set_icountptr(m_icount); + + save_item(NAME(m_main_counter)); + save_item(NAME(m_div_200_50)); + save_item(NAME(m_div_134_5)); + save_item(NAME(m_div_110)); + save_item(NAME(m_div_1800)); + save_item(NAME(m_im)); + save_item(NAME(m_s)); +} + + +//------------------------------------------------- +// reset_counters - optional master reset +//------------------------------------------------- + +void f4702_device::reset_counters() +{ + // Reset counter network + m_main_counter = 0; + m_div_200_50 = 0; + m_div_134_5 = 0; + m_div_1800 = 0; + + // Reset Q and Z outputs + m_z_callback(0, 0); +} + + +//************************************************************************** +// RATE GENERATION +//************************************************************************** + +//------------------------------------------------- +// im_w - set external rate input +//------------------------------------------------- + +void f4702_device::im_w(int state) +{ + m_im = state; +} + + +//------------------------------------------------- +// z_output - recalculate output state +//------------------------------------------------- + +bool f4702_device::z_output() const +{ + // Select Z output from one of the 13 counter taps or the external input + switch (m_s) + { + // S3–S0 = LLLL or LLLH: multiplexed input + case 0: + case 1: + default: + return m_im; + + // S3–S0 = LLHL: 50 baud + case 2: + return m_div_200_50 >= 12; + + // S3–S0 = LLHH: 75 baud + case 3: + return BIT(m_main_counter, 10); + + // S3–S0 = LHLL: 134.5 baud (-0.87% error) + case 4: + return m_div_134_5 >= 9; + + // S3–S0 = LHLH: 200 baud + case 5: + return (m_div_200_50 % 6) >= 3; + + // S3–S0 = LHHL: 600 baud + case 6: + return BIT(m_main_counter, 7); + + // S3–S0 = LHHH or HHLL: 2400 baud + case 7: + case 12: + return BIT(m_main_counter, 5); + + // S3–S0 = HLLL: 9600 baud + case 8: + return BIT(m_main_counter, 3); + + // S3–S0 = HLLH: 4800 baud + case 9: + return BIT(m_main_counter, 4); + + // S3–S0 = HLHL: 1800 baud + case 10: + return (m_div_1800 % 5) >= 2; + + // S3–S0 = HLHH: 1200 baud + case 11: + return BIT(m_main_counter, 6); + + // S3–S0 = HHLH: 300 baud + case 13: + return BIT(m_main_counter, 8); + + // S3–S0 = HHHL: 150 baud + case 14: + return BIT(m_main_counter, 9); + + // S3–S0 = HHHH: 110 baud (-0.83% error) + case 15: + return m_div_110 >= 11; + } +} + + +//------------------------------------------------- +// execute_run - execute a timeslice's worth of +// counting +//------------------------------------------------- + +void f4702_device::execute_run() +{ + do { + // Drive the main scan and frequency counter + m_main_counter++; + if ((m_main_counter & 0x00f) == 0) + { + // Divide 9600 baud by 16/3 (16 = 5 + 5 + 6) + m_div_1800++; + if (m_div_1800 >= 16) + m_div_1800 = 0; + + if ((m_main_counter & 0x03f) == 0) + { + // Divide 2400 baud by 18 + m_div_134_5++; + if (m_div_134_5 >= 18) + m_div_134_5 = 0; + + // Divide 2400 baud by 22 as well + m_div_110++; + if (m_div_110 >= 22) + m_div_110 = 0; + + if ((m_main_counter & 0x07f) == 0) + { + // Divide 1200 baud by 6 and then again by 4 + m_div_200_50++; + if (m_div_200_50 >= 24) + m_div_200_50 = 0; + } + } + } + + // Update Q and Z outputs + m_z_callback(m_main_counter & 0x007, z_output()); + + // S3–S0 inputs are valid on the rising edge of CO + m_s = m_s_callback(m_main_counter & 0x007) & 15; + } while (--m_icount > 0); +} |