summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/astrocde/cassette.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/astrocde/cassette.cpp')
-rw-r--r--src/devices/bus/astrocde/cassette.cpp91
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));
}