From 7080aa92fddce0dc1c81dec36a9dabb0c200ac0b Mon Sep 17 00:00:00 2001 From: Robbbert Date: Mon, 17 Jun 2019 02:18:19 +1000 Subject: [PATCH] (nw) amu880: added a cassette interface --- src/mame/drivers/huebler.cpp | 68 +++++++++++++++++++++++++++--------- src/mame/includes/huebler.h | 10 ++++-- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/src/mame/drivers/huebler.cpp b/src/mame/drivers/huebler.cpp index f8ce25a5d03..3608530c423 100644 --- a/src/mame/drivers/huebler.cpp +++ b/src/mame/drivers/huebler.cpp @@ -9,7 +9,7 @@ /* - TODO: +TODO: - keyboard repeat - shift lock is not PORT_TOGGLE, instead RS flipflop @@ -18,10 +18,27 @@ - eprom programmer - power off +Cassette considerations + + - It operates at 4883 baud but may not be fully compatible with real + hardware. A partial translation of the available text seems to + indicate an overcomplicated and unreliable interface. The one + implemented is 100% reliable at the same speed. I've been unable + to locate any real recordings to compare against. + - To save a range of memory: S name start end + - To load it back: L name + - To save an unnamed file: S "" start end + - To load an unnamed file: L + - When loading, if the name doesn't match, there's no message, and no + way to determine the name. + - For some reason, the system saves the file 3 times. Maybe it was an + attempt to guard against the inherent unreliable design. */ #include "emu.h" #include "includes/huebler.h" +#include "sound/wave.h" +#include "speaker.h" #include "screen.h" /* Keyboard */ @@ -103,7 +120,7 @@ void amu880_state::amu880_io(address_map &map) map(0x0c, 0x0f).rw(Z80PIO2_TAG, FUNC(z80pio_device::read_alt), FUNC(z80pio_device::write_alt)); map(0x10, 0x13).rw(Z80PIO1_TAG, FUNC(z80pio_device::read_alt), FUNC(z80pio_device::write_alt)); map(0x14, 0x17).rw(Z80CTC_TAG, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write)); - map(0x18, 0x1b).rw(m_z80sio, FUNC(z80sio0_device::ba_cd_r), FUNC(z80sio0_device::ba_cd_w)); + map(0x18, 0x1b).rw(m_sio, FUNC(z80sio0_device::ba_cd_r), FUNC(z80sio0_device::ba_cd_w)); } /* Input Ports */ @@ -252,19 +269,36 @@ WRITE_LINE_MEMBER(amu880_state::ctc_z0_w) WRITE_LINE_MEMBER(amu880_state::ctc_z2_w) { - /* cassette transmit/receive clock */ + /* cassette clock @ 39kHz */ + if (state) + { + m_cnt++; + switch (m_cnt & 7) // divide by 8 to get 4883Hz + { + case 0: + m_cassette->output(m_cassbit ? 1.0 : -1.0); + break; + case 2: + m_sio->txca_w(0); + m_sio->rxca_w(0); + break; + case 4: + m_sio->txca_w(1); + m_sio->rxca_w(1); + break; + case 6: + m_sio->rxa_w((m_cassette->input() > 0.04) ? 1 : 0); + default: + break; + } + } } /* Z80-SIO Interface */ -TIMER_DEVICE_CALLBACK_MEMBER( amu880_state::tape_tick ) -{ - m_z80sio->rxa_w(m_cassette->input() < 0.0); -} - WRITE_LINE_MEMBER(amu880_state::cassette_w) { - m_cassette->output(state ? -1.0 : +1.0); + m_cassbit = state; } /* Z80 Daisy Chain */ @@ -329,11 +363,15 @@ void amu880_state::amu880(machine_config &config) GFXDECODE(config, "gfxdecode", m_palette, gfx_amu880); PALETTE(config, m_palette, palette_device::MONOCHROME); + /* sound hardware */ + SPEAKER(config, "mono").front_center(); + WAVE(config, "wave", m_cassette).add_route(ALL_OUTPUTS, "mono", 0.05); + /* devices */ z80ctc_device& ctc(Z80CTC(config, Z80CTC_TAG, XTAL(10'000'000)/4)); ctc.intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); ctc.zc_callback<0>().set(FUNC(amu880_state::ctc_z0_w)); - ctc.zc_callback<1>().set(m_z80sio, FUNC(z80dart_device::rxtxcb_w)); + ctc.zc_callback<1>().set(m_sio, FUNC(z80dart_device::rxtxcb_w)); ctc.zc_callback<2>().set(FUNC(amu880_state::ctc_z2_w)); z80pio_device& pio1(Z80PIO(config, Z80PIO1_TAG, XTAL(10'000'000)/4)); @@ -342,14 +380,12 @@ void amu880_state::amu880(machine_config &config) z80pio_device& pio2(Z80PIO(config, Z80PIO2_TAG, XTAL(10'000'000)/4)); pio2.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); - Z80SIO0(config, m_z80sio, XTAL(10'000'000)/4); // U856 - m_z80sio->out_txda_callback().set(FUNC(amu880_state::cassette_w)); - m_z80sio->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + Z80SIO0(config, m_sio, XTAL(10'000'000)/4); // U856 + m_sio->out_txda_callback().set(FUNC(amu880_state::cassette_w)); + m_sio->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); CASSETTE(config, m_cassette); - m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_MUTED); - - TIMER(config, "tape").configure_periodic(FUNC(amu880_state::tape_tick), attotime::from_hz(44100)); + m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED); /* internal ram */ RAM(config, RAM_TAG).set_default_size("64K"); diff --git a/src/mame/includes/huebler.h b/src/mame/includes/huebler.h index 163e52f7581..5df0dcb8ce6 100644 --- a/src/mame/includes/huebler.h +++ b/src/mame/includes/huebler.h @@ -28,7 +28,7 @@ public: : driver_device(mconfig, type, tag) , m_maincpu(*this, Z80_TAG) , m_cassette(*this, "cassette") - , m_z80sio(*this, Z80SIO_TAG) + , m_sio(*this, Z80SIO_TAG) , m_palette(*this, "palette") , m_kb_rom(*this, "keyboard") , m_char_rom(*this, "chargen") @@ -44,11 +44,12 @@ public: protected: virtual void machine_start() override; + virtual void machine_reset() override { m_maincpu->set_pc(0xf000); } private: required_device m_maincpu; required_device m_cassette; - required_device m_z80sio; + required_device m_sio; required_device m_palette; required_memory_region m_kb_rom; required_memory_region m_char_rom; @@ -59,7 +60,6 @@ private: uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); DECLARE_READ8_MEMBER( keyboard_r ); - TIMER_DEVICE_CALLBACK_MEMBER( tape_tick ); void scan_keyboard(); @@ -77,6 +77,10 @@ private: DECLARE_WRITE_LINE_MEMBER(cassette_w); void amu880_io(address_map &map); void amu880_mem(address_map &map); + + // cassette variables + u8 m_cnt; + bool m_cassbit; }; #endif