diff options
Diffstat (limited to 'src/devices/bus/astrocde/cassette.cpp')
-rw-r--r-- | src/devices/bus/astrocde/cassette.cpp | 91 |
1 files changed, 87 insertions, 4 deletions
diff --git a/src/devices/bus/astrocde/cassette.cpp b/src/devices/bus/astrocde/cassette.cpp index 789b0d7e175..3e4cc80deb8 100644 --- a/src/devices/bus/astrocde/cassette.cpp +++ b/src/devices/bus/astrocde/cassette.cpp @@ -1,5 +1,8 @@ // license:BSD-3-Clause // copyright-holders:Ryan Holtz +// +// Decoding is done in hardware by an external box, and decoded bits are fed to bit 0 of the controller port, +// with sync bits being fed to bit 1. The current HLE is not remotely accurate to hardware, but works. #include "emu.h" #include "cassette.h" @@ -26,22 +29,102 @@ astrocade_cassette_device::~astrocade_cassette_device() { } +void astrocade_cassette_device::device_start() +{ + save_item(NAME(m_cass_wave)); + save_item(NAME(m_cass_delta)); + save_item(NAME(m_cass_wave_ticks)); + save_item(NAME(m_cass_cycles)); + save_item(NAME(m_cass_mark)); +} + +void astrocade_cassette_device::device_reset() +{ + m_cass_wave = 0.0; + m_cass_delta = 0.0; + m_cass_wave_ticks = 0; + m_cass_cycles = 0; + m_cass_mark = false; +} + uint8_t astrocade_cassette_device::read_handle() { - uint8_t data = m_cassette->input() > 0.0 ? 0 : 1; - logerror("%s: Cassette Handle Read: %d\n", machine().describe_context(), data); - return data; + if (m_cass_data.size()) + { + const uint8_t data = m_cass_data.front(); + m_cass_data.pop(); + return data; + } + return 0; } uint8_t astrocade_cassette_device::read_knob() { - logerror("%s: Cassette Knob Read\n", machine().describe_context()); return 0; } +TIMER_DEVICE_CALLBACK_MEMBER(astrocade_cassette_device::check_cassette_wave) +{ + if (m_cassette->get_state() & CASSETTE_MOTOR_DISABLED) + return; + + double old_cass_wave = m_cass_wave; + m_cass_wave = m_cassette->input(); + + bool cycled = false; + if (old_cass_wave != m_cass_wave) + { + double old_delta = m_cass_delta; + m_cass_delta = m_cass_wave - old_cass_wave; + if (old_delta < 0.0 && m_cass_delta > 0.0) + { + cycled = true; + } + } + + if (cycled) + { + m_cass_mark = m_cass_wave_ticks <= 30; + + m_cass_wave_ticks = 0; + + m_cass_cycles++; + if (m_cass_mark) + { + if (m_cass_cycles >= 8) + { + m_cass_data.push(1); + m_cass_cycles = 0; + } + } + else + { + if (m_cass_cycles >= 4) + { + m_cass_data.push(0); + m_cass_cycles = 0; + } + } + } + + m_cass_wave_ticks++; +} + +TIMER_DEVICE_CALLBACK_MEMBER(astrocade_cassette_device::pulse_cassette_clock) +{ + if (m_cass_data.size()) + { + write_ltpen(1); + write_ltpen(0); + } +} + void astrocade_cassette_device::device_add_mconfig(machine_config &config) { CASSETTE(config, m_cassette); m_cassette->set_default_state(CASSETTE_STOPPED); m_cassette->set_interface("astrocade_cass"); + + TIMER(config, "kcs_hle").configure_periodic(FUNC(astrocade_cassette_device::check_cassette_wave), attotime::from_hz(48000)); + TIMER(config, "kcs_clk").configure_periodic(FUNC(astrocade_cassette_device::pulse_cassette_clock), attotime::from_hz(300)); } |