diff options
Diffstat (limited to 'src/devices/bus/astrocde/cassette.cpp')
-rw-r--r-- | src/devices/bus/astrocde/cassette.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/devices/bus/astrocde/cassette.cpp b/src/devices/bus/astrocde/cassette.cpp new file mode 100644 index 00000000000..3e4cc80deb8 --- /dev/null +++ b/src/devices/bus/astrocde/cassette.cpp @@ -0,0 +1,130 @@ +// 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" + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +DEFINE_DEVICE_TYPE(ASTROCADE_CASSETTE, astrocade_cassette_device, "astrocade_cass", "Bally Astrocade Cassette") + + +//************************************************************************** +// Bally Astrocade cassette input +//************************************************************************** + +astrocade_cassette_device::astrocade_cassette_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, ASTROCADE_CASSETTE, tag, owner, clock) + , device_astrocade_ctrl_interface(mconfig, *this) + , m_cassette(*this, "cassette") +{ +} + +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() +{ + 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() +{ + 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)); +} |