summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/machine.lua12
-rw-r--r--scripts/target/mame/arcade.lua1
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/machine/mm5307.cpp222
-rw-r--r--src/devices/machine/mm5307.h99
-rw-r--r--src/mame/drivers/poly88.cpp13
-rw-r--r--src/mame/includes/poly88.h14
-rw-r--r--src/mame/machine/poly88.cpp33
8 files changed, 366 insertions, 29 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index a456bf31ef8..e58809b2470 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -1976,6 +1976,18 @@ end
---------------------------------------------------
--
+--@src/devices/machine/mm5307.h,MACHINES["MM5307"] = true
+---------------------------------------------------
+
+if (MACHINES["MM5307"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/machine/mm5307.cpp",
+ MAME_DIR .. "src/devices/machine/mm5307.h",
+ }
+end
+
+---------------------------------------------------
+--
--@src/devices/machine/mm58274c.h,MACHINES["MM58274C"] = true
---------------------------------------------------
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index 29b374473b5..1602d1ea032 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -520,6 +520,7 @@ MACHINES["MCF5206E"] = true
MACHINES["METERS"] = true
MACHINES["MICROTOUCH"] = true
--MACHINES["MIOT6530"] = true
+--MACHINES["MM5307"] = true
--MACHINES["MM58167"] = true
MACHINES["MM58274C"] = true
MACHINES["MM74C922"] = true
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index af94de5ab22..86c89d6b5be 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -524,6 +524,7 @@ MACHINES["MCCS1850"] = true
MACHINES["MCF5206E"] = true
MACHINES["MICROTOUCH"] = true
MACHINES["MIOT6530"] = true
+MACHINES["MM5307"] = true
MACHINES["MM58167"] = true
MACHINES["MM58274C"] = true
MACHINES["MM74C922"] = true
diff --git a/src/devices/machine/mm5307.cpp b/src/devices/machine/mm5307.cpp
new file mode 100644
index 00000000000..7d97136149a
--- /dev/null
+++ b/src/devices/machine/mm5307.cpp
@@ -0,0 +1,222 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ National Semiconductor MM5307 Baud Rate Generator/Programmable Divider
+
+ The MM5307 divides the frequency of a crystal oscillator or external
+ clock (maximum 1 MHz, ideally 921.6 kHz) to generate a single baud
+ rate output. (The undivided frequency is also output on another pin,
+ not emulated here.)
+
+ The four control inputs (A, B, C, D) select one of 15 mask-programmed
+ divisors or an independent external frequency. When the selected
+ divisor is 2N, the output has a duty cycle of exactly 50%. When the
+ selected divisor is 2N + 1, the high output is always one clock cycle
+ longer than the low output. When the selected divisor is 2N + 0.5,
+ the duty cycle varies slightly from phase to phase.
+
+ The MM5307 resets its output frequency when the reset input is pulsed
+ low or the control inputs change.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mm5307.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definitions
+DEFINE_DEVICE_TYPE(MM5307AA, mm5307aa_device, "mm5307aa", "MM5307AA Baud Rate Generator")
+DEFINE_DEVICE_TYPE(MM5307AB, mm5307ab_device, "mm5307ab", "MM5307AB Baud Rate Generator")
+
+
+//**************************************************************************
+// DIVISOR TABLES
+//**************************************************************************
+
+const std::array<u16, 16> mm5307aa_device::s_divisors_x2 = {
+ 0, // external frequency (not divided)
+ 2304, // 50 baud (divide by 1152)
+ 1536, // 75 baud (divide by 768)
+ 1048, // 110 baud (divide by 524)
+ 857, // 134.5 baud (divide by 428.5)
+ 768, // 150 baud (divide by 384)
+ 384, // 300 baud (divide by 192)
+ 192, // 600 baud (divide by 96)
+ 128, // 900 baud (divide by 64)
+ 96, // 1200 baud (divide by 48)
+ 64, // 1800 baud (divide by 32)
+ 48, // 2400 baud (divide by 24)
+ 32, // 3600 baud (divide by 16)
+ 24, // 4800 baud (divide by 12)
+ 16, // 7200 baud (divide by 8)
+ 12 // 9600 baud (divide by 6)
+};
+
+
+const std::array<u16, 16> mm5307ab_device::s_divisors_x2 = {
+ 0, // external frequency (not divided)
+ 2304, // 50 baud (divide by 1152)
+ 576, // 200 baud (divide by 288)
+ 1048, // 110 baud (divide by 524)
+ 857, // 134.5 baud (divide by 428.5)
+ 768, // 150 baud (divide by 384)
+ 384, // 300 baud (divide by 192)
+ 192, // 600 baud (divide by 96)
+ 128, // 900 baud (divide by 64)
+ 96, // 1200 baud (divide by 48)
+ 64, // 1800 baud (divide by 32)
+ 48, // 2400 baud (divide by 24)
+ 32, // 3600 baud (divide by 16)
+ 24, // 4800 baud (divide by 12)
+ 1536, // 75 baud (divide by 768)
+ 12 // 9600 baud (divide by 6)
+};
+
+
+//**************************************************************************
+// DEVICE IMPLEMENTATION
+//**************************************************************************
+
+//-------------------------------------------------
+// mm5307_device - constructor
+//-------------------------------------------------
+
+mm5307_device::mm5307_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const std::array<u16, 16> &divisors_x2)
+ : device_t(mconfig, type, tag, owner, clock)
+ , m_divisors_x2(divisors_x2)
+ , m_output_cb(*this)
+ , m_ext_freq(0)
+ , m_freq_control(0)
+ , m_phase(0)
+ , m_periodic_timer(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// mm5307aa_device - constructor
+//-------------------------------------------------
+
+mm5307aa_device::mm5307aa_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : mm5307_device(mconfig, MM5307AA, tag, owner, clock, s_divisors_x2)
+{
+}
+
+
+//-------------------------------------------------
+// mm5307ab_device - constructor
+//-------------------------------------------------
+
+mm5307ab_device::mm5307ab_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : mm5307_device(mconfig, MM5307AB, tag, owner, clock, s_divisors_x2)
+{
+}
+
+
+//-------------------------------------------------
+// device_resolve_objects - resolve objects that
+// may be needed for other devices to set
+// initial conditions at start time
+//-------------------------------------------------
+
+void mm5307_device::device_resolve_objects()
+{
+ // Resolve callback
+ m_output_cb.resolve_safe();
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mm5307_device::device_start()
+{
+ // Create timer
+ m_periodic_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mm5307_device::periodic_update), this));
+
+ // Register for saving
+ save_item(NAME(m_freq_control));
+ save_item(NAME(m_phase));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void mm5307_device::device_reset()
+{
+ // Output delay from reset
+ m_periodic_timer->adjust(attotime::from_usec(500) + clocks_to_attotime(4));
+}
+
+
+//-------------------------------------------------
+// control_w - set frequency control
+//-------------------------------------------------
+
+void mm5307_device::control_w(u8 data)
+{
+ data &= 15;
+ if (data != m_freq_control)
+ {
+ m_freq_control = data;
+
+ if (m_divisors_x2[data] == 0)
+ LOG("%s: External frequency selected\n", machine().describe_context());
+ else
+ LOG("%s: %.1f baud selected\n", machine().describe_context(), clock() / (8.0 * m_divisors_x2[data]));
+
+ // Emulate access time
+ m_periodic_timer->adjust(attotime::from_usec(2800) + clocks_to_attotime(13));
+ }
+}
+
+
+//-------------------------------------------------
+// periodic_update - update output state and
+// reset timer for next period
+//-------------------------------------------------
+
+TIMER_CALLBACK_MEMBER(mm5307_device::periodic_update)
+{
+ // Up to four different phases
+ m_phase = (m_phase + 1) & 3;
+ m_output_cb(BIT(m_phase, 0));
+
+ u16 divisor = m_divisors_x2[m_freq_control];
+ if (divisor == 0)
+ {
+ m_periodic_timer->adjust(m_ext_freq == 0 ? attotime::never : attotime::from_hz(m_ext_freq) / 2);
+ }
+ else switch (m_phase)
+ {
+ // First low output phase
+ case 0:
+ m_periodic_timer->adjust(clocks_to_attotime(divisor & ~2) / 2);
+ break;
+
+ // First high output phase
+ case 1:
+ m_periodic_timer->adjust(clocks_to_attotime(divisor >> 1));
+ break;
+
+ // Second low output phase
+ case 2:
+ m_periodic_timer->adjust(clocks_to_attotime((divisor & ~2) >> 1 | (divisor & 1)));
+ break;
+
+ // Second high output phase
+ case 3:
+ m_periodic_timer->adjust(clocks_to_attotime(divisor - ((divisor & 1) << 1)) / 2);
+ break;
+ }
+}
diff --git a/src/devices/machine/mm5307.h b/src/devices/machine/mm5307.h
new file mode 100644
index 00000000000..d46124e89ee
--- /dev/null
+++ b/src/devices/machine/mm5307.h
@@ -0,0 +1,99 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ National Semiconductor MM5307 Baud Rate Generator/Programmable Divider
+
+****************************************************************************
+ ___ ___
+ EXTERNAL FREQ 1 |* \__/ | 14 ϕOUT
+ NC 2 | | 13 RESET
+ OUTPUT 3 | | 12 Vgg
+ Vss 4 | MM5307 | 11 A
+ EXTERNAL CLOCK 5 | | 10 B
+ CRYSTAL 6 | | 9 C
+ CRYSTAL 7 |__________| 8 D
+
+***************************************************************************/
+
+#ifndef MAME_MACHINE_MM5307_H
+#define MAME_MACHINE_MM5307_H 1
+
+#pragma once
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mm5307_device
+
+class mm5307_device : public device_t
+{
+public:
+ // configuration
+ void set_ext_freq(u32 freq) { m_ext_freq = freq; }
+ void set_ext_freq(const XTAL &freq) { m_ext_freq = freq.value(); }
+ auto output_cb() { return m_output_cb.bind(); }
+
+ // frequency control
+ void control_w(u8 data);
+
+protected:
+ // base class constructor
+ mm5307_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const std::array<u16, 16> &divisors_x2);
+
+ // device-specific overrides
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ // timed update callback
+ TIMER_CALLBACK_MEMBER(periodic_update);
+
+ // internal divisors
+ const std::array<u16, 16> &m_divisors_x2;
+
+ // callbacks
+ devcb_write_line m_output_cb;
+
+ // external input frequency
+ u32 m_ext_freq;
+
+ // internal state
+ u8 m_freq_control;
+ u8 m_phase;
+
+ // timer
+ emu_timer *m_periodic_timer;
+};
+
+// ======================> mm5307aa_device
+
+class mm5307aa_device : public mm5307_device
+{
+public:
+ // construction/destruction
+ mm5307aa_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+private:
+ static const std::array<u16, 16> s_divisors_x2;
+};
+
+// ======================> mm5307ab_device
+
+class mm5307ab_device : public mm5307_device
+{
+public:
+ // construction/destruction
+ mm5307ab_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+private:
+ static const std::array<u16, 16> s_divisors_x2;
+};
+
+// device type declarations
+DECLARE_DEVICE_TYPE(MM5307AA, mm5307aa_device)
+DECLARE_DEVICE_TYPE(MM5307AB, mm5307ab_device)
+
+#endif // MAME_MACHINE_MM5307_H
diff --git a/src/mame/drivers/poly88.cpp b/src/mame/drivers/poly88.cpp
index f6df50ec578..180078aff0f 100644
--- a/src/mame/drivers/poly88.cpp
+++ b/src/mame/drivers/poly88.cpp
@@ -69,7 +69,7 @@ void poly88_state::poly88_io(address_map &map)
{
map.unmap_value_high();
map.global_mask(0xff);
- map(0x00, 0x01).rw(m_uart, FUNC(i8251_device::read), FUNC(i8251_device::write));
+ map(0x00, 0x01).rw(m_usart, FUNC(i8251_device::read), FUNC(i8251_device::write));
map(0x04, 0x04).w(FUNC(poly88_state::poly88_baud_rate_w));
map(0x08, 0x08).w(FUNC(poly88_state::poly88_intr_w));
map(0xf8, 0xf8).r(FUNC(poly88_state::poly88_keyboard_r));
@@ -201,7 +201,7 @@ GFXDECODE_END
MACHINE_CONFIG_START(poly88_state::poly88)
/* basic machine hardware */
- I8080A(config, m_maincpu, XTAL(16'588'800) / 9); // uses 8224 clock generator
+ I8080A(config, m_maincpu, 16.5888_MHz_XTAL / 9); // uses 8224 clock generator
m_maincpu->set_addrmap(AS_PROGRAM, &poly88_state::poly88_mem);
m_maincpu->set_addrmap(AS_IO, &poly88_state::poly88_io);
m_maincpu->set_vblank_int("screen", FUNC(poly88_state::poly88_interrupt));
@@ -230,9 +230,12 @@ MACHINE_CONFIG_START(poly88_state::poly88)
m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED);
/* uart */
- I8251(config, m_uart, XTAL(16'588'800) / 9);
- m_uart->txd_handler().set(FUNC(poly88_state::write_cas_tx));
- m_uart->rxrdy_handler().set(FUNC(poly88_state::poly88_usart_rxready));
+ I8251(config, m_usart, 16.5888_MHz_XTAL / 9);
+ m_usart->txd_handler().set(FUNC(poly88_state::write_cas_tx));
+ m_usart->rxrdy_handler().set(FUNC(poly88_state::poly88_usart_rxready));
+
+ MM5307AA(config, m_brg, 16.5888_MHz_XTAL / 18);
+ m_brg->output_cb().set(FUNC(poly88_state::cassette_txc_rxc_w));
/* snapshot */
MCFG_SNAPSHOT_ADD("snapshot", poly88_state, poly88, "img", attotime::from_seconds(2))
diff --git a/src/mame/includes/poly88.h b/src/mame/includes/poly88.h
index 22e8071d21f..29d39c049fa 100644
--- a/src/mame/includes/poly88.h
+++ b/src/mame/includes/poly88.h
@@ -11,6 +11,7 @@
#pragma once
#include "machine/i8251.h"
+#include "machine/mm5307.h"
#include "imagedev/cassette.h"
#include "imagedev/snapquik.h"
@@ -20,15 +21,15 @@ public:
enum
{
TIMER_USART,
- TIMER_KEYBOARD,
- TIMER_CASSETTE
+ TIMER_KEYBOARD
};
poly88_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_video_ram(*this, "video_ram"),
m_maincpu(*this, "maincpu"),
- m_uart(*this, "uart"),
+ m_usart(*this, "usart"),
+ m_brg(*this, "brg"),
m_cassette(*this, "cassette"),
m_linec(*this, "LINEC"),
m_line0(*this, "LINE0"),
@@ -51,8 +52,8 @@ private:
uint8_t m_intr;
uint8_t m_last_code;
uint8_t m_int_vector;
- emu_timer * m_cassette_timer;
emu_timer * m_usart_timer;
+ emu_timer * m_keyboard_timer;
int m_previous_level;
int m_clk_level;
int m_clk_level_tape;
@@ -65,7 +66,7 @@ private:
INTERRUPT_GEN_MEMBER(poly88_interrupt);
TIMER_CALLBACK_MEMBER(poly88_usart_timer_callback);
TIMER_CALLBACK_MEMBER(keyboard_callback);
- TIMER_CALLBACK_MEMBER(poly88_cassette_timer_callback);
+ DECLARE_WRITE_LINE_MEMBER(cassette_txc_rxc_w);
DECLARE_WRITE_LINE_MEMBER(write_cas_tx);
DECLARE_WRITE_LINE_MEMBER(poly88_usart_rxready);
IRQ_CALLBACK_MEMBER(poly88_irq_callback);
@@ -77,7 +78,8 @@ private:
void poly88_mem(address_map &map);
required_device<cpu_device> m_maincpu;
- required_device<i8251_device> m_uart;
+ required_device<i8251_device> m_usart;
+ required_device<mm5307_device> m_brg;
required_device<cassette_image_device> m_cassette;
required_ioport m_linec;
required_ioport m_line0;
diff --git a/src/mame/machine/poly88.cpp b/src/mame/machine/poly88.cpp
index 6b2b022a9d0..1d317a1182e 100644
--- a/src/mame/machine/poly88.cpp
+++ b/src/mame/machine/poly88.cpp
@@ -24,9 +24,6 @@ void poly88_state::device_timer(emu_timer &timer, device_timer_id id, int param,
case TIMER_KEYBOARD:
keyboard_callback(ptr, param);
break;
- case TIMER_CASSETTE:
- poly88_cassette_timer_callback(ptr, param);
- break;
default:
assert_always(false, "Unknown id in poly88_state::device_timer");
}
@@ -42,9 +39,10 @@ TIMER_CALLBACK_MEMBER(poly88_state::poly88_usart_timer_callback)
WRITE8_MEMBER(poly88_state::poly88_baud_rate_w)
{
logerror("poly88_baud_rate_w %02x\n",data);
- m_usart_timer = timer_alloc(TIMER_USART);
- m_usart_timer->adjust(attotime::zero, 0, attotime::from_hz(300));
+ m_brg->control_w(data & 15);
+ // FIXME
+ m_usart_timer->adjust(attotime::zero, 0, attotime::from_hz(300));
}
uint8_t poly88_state::row_number(uint8_t code) {
@@ -149,8 +147,6 @@ TIMER_CALLBACK_MEMBER(poly88_state::keyboard_callback)
} else {
m_last_code = key_code;
}
-
- timer_set(attotime::from_hz(24000), TIMER_KEYBOARD);
}
IRQ_CALLBACK_MEMBER(poly88_state::poly88_irq_callback)
@@ -163,7 +159,7 @@ WRITE_LINE_MEMBER(poly88_state::write_cas_tx)
m_cas_tx = state;
}
-TIMER_CALLBACK_MEMBER(poly88_state::poly88_cassette_timer_callback)
+WRITE_LINE_MEMBER(poly88_state::cassette_txc_rxc_w)
{
int data;
int current_level;
@@ -186,13 +182,13 @@ TIMER_CALLBACK_MEMBER(poly88_state::poly88_cassette_timer_callback)
{
data = (!m_previous_level && current_level) ? 1 : 0;
//data = current_level;
- m_uart->write_rxd(data);
+ m_usart->write_rxd(data);
m_clk_level_tape = 1;
}
}
- m_uart->write_rxc(m_clk_level_tape);
+ m_usart->write_rxc(m_clk_level_tape);
}
/* tape writing */
@@ -203,15 +199,14 @@ TIMER_CALLBACK_MEMBER(poly88_state::poly88_cassette_timer_callback)
m_cassette->output(data&0x01 ? 1 : -1);
m_clk_level_tape = m_clk_level_tape ? 0 : 1;
- m_uart->write_txc(m_clk_level_tape);
+ m_usart->write_txc(m_clk_level_tape);
return;
}
m_clk_level_tape = 1;
- m_clk_level = m_clk_level ? 0 : 1;
- m_uart->write_txc(m_clk_level);
+ m_usart->write_txc(state);
// }
}
@@ -219,17 +214,19 @@ TIMER_CALLBACK_MEMBER(poly88_state::poly88_cassette_timer_callback)
void poly88_state::init_poly88()
{
m_previous_level = 0;
- m_clk_level = m_clk_level_tape = 1;
- m_cassette_timer = timer_alloc(TIMER_CASSETTE);
- m_cassette_timer->adjust(attotime::zero, 0, attotime::from_hz(600));
+ m_clk_level_tape = 1;
- timer_set(attotime::from_hz(24000), TIMER_KEYBOARD);
+ m_usart_timer = timer_alloc(TIMER_USART);
+ m_keyboard_timer = timer_alloc(TIMER_KEYBOARD);
+ m_keyboard_timer->adjust(attotime::from_hz(24000), 0, attotime::from_hz(24000));
}
void poly88_state::machine_reset()
{
m_intr = 0;
m_last_code = 0;
+
+ m_brg->control_w(0);
}
INTERRUPT_GEN_MEMBER(poly88_state::poly88_interrupt)
@@ -327,6 +324,6 @@ SNAPSHOT_LOAD_MEMBER( poly88_state, poly88 )
}
pos+=recordLen;
}
- m_uart->reset();
+ m_usart->reset();
return image_init_result::PASS;
}