summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2020-12-24 09:56:49 -0500
committer AJR <ajrhacker@users.noreply.github.com>2020-12-24 09:56:49 -0500
commit5bf175cb0599ca0f76621bb6ba5ac6195977e376 (patch)
treed2734cf1bd8ed7473ebace23051757faeca781fc /src/devices/machine
parent051c0374538b17d957db5fe766dfdf71f22e4642 (diff)
New device: Fairchild 4702B Bit Rate Generator
Diffstat (limited to 'src/devices/machine')
-rw-r--r--src/devices/machine/f4702.cpp274
-rw-r--r--src/devices/machine/f4702.h76
2 files changed, 350 insertions, 0 deletions
diff --git a/src/devices/machine/f4702.cpp b/src/devices/machine/f4702.cpp
new file mode 100644
index 00000000000..40a1d0be517
--- /dev/null
+++ b/src/devices/machine/f4702.cpp
@@ -0,0 +1,274 @@
+// 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 "machine/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)
+ , 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_resolve_objects - resolve objects that
+// may be needed for other devices to set
+// initial conditions at start time
+//-------------------------------------------------
+
+void f4702_device::device_resolve_objects()
+{
+ // resolve callbacks
+ m_s_callback.resolve_safe(15);
+ m_z_callback.resolve_safe();
+}
+
+
+//-------------------------------------------------
+// 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
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER(f4702_device::im_w)
+{
+ 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);
+}
diff --git a/src/devices/machine/f4702.h b/src/devices/machine/f4702.h
new file mode 100644
index 00000000000..c48601b1e3c
--- /dev/null
+++ b/src/devices/machine/f4702.h
@@ -0,0 +1,76 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/****************************************************************************
+
+ Fairchild 4702B Programmable Bit Rate Generator
+
+*****************************************************************************
+ ____ ____
+ Q0 1 |* \_/ | 16 Vdd
+ Q1 2 | | 15 Im
+ Q2 3 | | 14 S0
+ _Ecp 4 | | 13 S1
+ CP 5 | 4702BPC | 12 S2
+ Ox 6 | | 11 S3
+ Ix 7 | | 10 Z
+ Vss 8 |___________| 9 CO
+
+****************************************************************************/
+
+#ifndef MAME_MACHINE_F4702_H
+#define MAME_MACHINE_F4702_H
+
+#pragma once
+
+
+// ======================> f4702_device
+
+class f4702_device : public device_t, public device_execute_interface
+{
+public:
+ f4702_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // callback configuration
+ auto s_callback() { return m_s_callback.bind(); }
+ auto z_callback() { return m_z_callback.bind(); }
+
+ // external rate input
+ DECLARE_WRITE_LINE_MEMBER(im_w);
+
+ // reset control (optional)
+ void reset_counters();
+
+protected:
+ // device-level overrides
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+
+ // device_execute_interface overrides
+ virtual void execute_run() override;
+
+private:
+ // internal helpers
+ bool z_output() const;
+
+ // input & output callbacks
+ devcb_read8 m_s_callback;
+ devcb_write8 m_z_callback;
+
+ // internal counters
+ u16 m_main_counter;
+ u8 m_div_200_50;
+ u8 m_div_134_5;
+ u8 m_div_110;
+ u8 m_div_1800;
+
+ // miscellaneous state
+ bool m_im;
+ u8 m_s;
+ s32 m_icount;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(F4702, f4702_device)
+
+#endif // MAME_MACHINE_F4702_H
+