mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-26 09:29:45 +00:00
Factored out the stuff of playing a tape, started basic sketch of the Vic-related classes.
This commit is contained in:
parent
066db59773
commit
37ba42a52f
@ -166,7 +166,7 @@ template <class T> class MOS6522 {
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
inline void set_control_line_input(Port port, Line line, bool value)
|
||||
inline void set_control_line(Port port, Line line, bool value)
|
||||
{
|
||||
switch(line)
|
||||
{
|
||||
@ -258,6 +258,7 @@ template <class T> class MOS6522 {
|
||||
// Expected to be overridden
|
||||
uint8_t get_port_input(Port port) { return 0xff; }
|
||||
void set_port_output(Port port, uint8_t value, uint8_t direction_mask) {}
|
||||
bool get_control_line(Port port, Line line) { return true; }
|
||||
// void set_interrupt_status(bool status) {}
|
||||
|
||||
// Input/output multiplexer
|
||||
|
@ -901,35 +901,14 @@ void Speaker::set_is_enabled(bool is_enabled)
|
||||
*/
|
||||
|
||||
Tape::Tape() :
|
||||
TapePlayer(2000000),
|
||||
_is_running(false),
|
||||
_data_register(0),
|
||||
_delegate(nullptr),
|
||||
_output({.bits_remaining_until_empty = 0, .cycles_into_pulse = 0}),
|
||||
_last_posted_interrupt_status(0),
|
||||
_interrupt_status(0) {}
|
||||
|
||||
void Tape::set_tape(std::shared_ptr<Storage::Tape> tape)
|
||||
{
|
||||
_tape = tape;
|
||||
get_next_tape_pulse();
|
||||
}
|
||||
|
||||
inline void Tape::get_next_tape_pulse()
|
||||
{
|
||||
_input.time_into_pulse = 0;
|
||||
if(_tape)
|
||||
_input.current_pulse = _tape->get_next_pulse();
|
||||
else
|
||||
{
|
||||
_input.current_pulse.length.length = 1;
|
||||
_input.current_pulse.length.clock_rate = 1;
|
||||
_input.current_pulse.type = Storage::Tape::Pulse::Zero;
|
||||
}
|
||||
if(_input.pulse_stepper == nullptr || _input.current_pulse.length.clock_rate != _input.pulse_stepper->get_output_rate())
|
||||
{
|
||||
_input.pulse_stepper.reset(new SignalProcessing::Stepper(_input.current_pulse.length.clock_rate, 2000000));
|
||||
}
|
||||
}
|
||||
_interrupt_status(0)
|
||||
{}
|
||||
|
||||
inline void Tape::push_tape_bit(uint16_t bit)
|
||||
{
|
||||
@ -992,18 +971,16 @@ inline uint8_t Tape::get_data_register()
|
||||
return (uint8_t)(_data_register >> 2);
|
||||
}
|
||||
|
||||
inline void Tape::run_for_input_pulse()
|
||||
inline void Tape::process_input_pulse(Storage::Tape::Pulse pulse)
|
||||
{
|
||||
get_next_tape_pulse();
|
||||
|
||||
_crossings[0] = _crossings[1];
|
||||
_crossings[1] = _crossings[2];
|
||||
_crossings[2] = _crossings[3];
|
||||
|
||||
_crossings[3] = Tape::Unrecognised;
|
||||
if(_input.current_pulse.type != Storage::Tape::Pulse::Zero)
|
||||
if(pulse.type != Storage::Tape::Pulse::Zero)
|
||||
{
|
||||
float pulse_length = (float)_input.current_pulse.length.length / (float)_input.current_pulse.length.clock_rate;
|
||||
float pulse_length = (float)pulse.length.length / (float)pulse.length.clock_rate;
|
||||
if(pulse_length >= 0.35 / 2400.0 && pulse_length < 0.7 / 2400.0) _crossings[3] = Tape::Short;
|
||||
if(pulse_length >= 0.35 / 1200.0 && pulse_length < 0.7 / 1200.0) _crossings[3] = Tape::Long;
|
||||
}
|
||||
@ -1030,16 +1007,9 @@ inline void Tape::run_for_cycles(unsigned int number_of_cycles)
|
||||
{
|
||||
if(_is_in_input_mode)
|
||||
{
|
||||
if(_is_running && _tape != nullptr)
|
||||
if(_is_running)
|
||||
{
|
||||
while(number_of_cycles--)
|
||||
{
|
||||
_input.time_into_pulse += (unsigned int)_input.pulse_stepper->step();
|
||||
if(_input.time_into_pulse == _input.current_pulse.length.length)
|
||||
{
|
||||
run_for_input_pulse();
|
||||
}
|
||||
}
|
||||
TapePlayer::run_for_cycles(number_of_cycles);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -62,15 +62,11 @@ enum Key: uint16_t {
|
||||
TerminateSequence = 0, NotMapped = 0xfffe,
|
||||
};
|
||||
|
||||
class Tape {
|
||||
class Tape: public Storage::TapePlayer {
|
||||
public:
|
||||
Tape();
|
||||
|
||||
void set_tape(std::shared_ptr<Storage::Tape> tape);
|
||||
inline bool has_tape()
|
||||
{
|
||||
return (bool)_tape;
|
||||
}
|
||||
inline void run_for_cycles(unsigned int number_of_cycles);
|
||||
|
||||
inline uint8_t get_data_register();
|
||||
inline void set_data_register(uint8_t value);
|
||||
@ -85,23 +81,16 @@ class Tape {
|
||||
};
|
||||
inline void set_delegate(Delegate *delegate) { _delegate = delegate; }
|
||||
|
||||
inline void run_for_cycles(unsigned int number_of_cycles);
|
||||
inline void run_for_input_pulse();
|
||||
|
||||
inline void set_is_running(bool is_running) { _is_running = is_running; }
|
||||
inline void set_is_enabled(bool is_enabled) { _is_enabled = is_enabled; }
|
||||
inline void set_is_in_input_mode(bool is_in_input_mode);
|
||||
|
||||
private:
|
||||
void process_input_pulse(Storage::Tape::Pulse pulse);
|
||||
inline void push_tape_bit(uint16_t bit);
|
||||
inline void get_next_tape_pulse();
|
||||
|
||||
std::shared_ptr<Storage::Tape> _tape;
|
||||
|
||||
struct {
|
||||
Storage::Tape::Pulse current_pulse;
|
||||
std::unique_ptr<SignalProcessing::Stepper> pulse_stepper;
|
||||
uint32_t time_into_pulse;
|
||||
int minimum_bits_until_full;
|
||||
} _input;
|
||||
struct {
|
||||
|
@ -49,11 +49,33 @@ enum Key: uint16_t {
|
||||
TerminateSequence = 0, NotMapped = 0xffff
|
||||
};
|
||||
|
||||
class Tape {
|
||||
public:
|
||||
void set_motor_control(bool enabled);
|
||||
void set_tape_output(bool set);
|
||||
bool get_tape_input();
|
||||
bool has_tape();
|
||||
|
||||
void set_tape(std::shared_ptr<Storage::Tape> tape);
|
||||
void run_for_cycles(int number_of_cycles);
|
||||
|
||||
private:
|
||||
struct {
|
||||
Storage::Tape::Pulse current_pulse;
|
||||
std::unique_ptr<SignalProcessing::Stepper> pulse_stepper;
|
||||
uint32_t time_into_pulse;
|
||||
} _input;
|
||||
};
|
||||
|
||||
class UserPortVIA: public MOS::MOS6522<UserPortVIA>, public MOS::MOS6522IRQDelegate {
|
||||
};
|
||||
|
||||
class KeyboardVIA: public MOS::MOS6522<KeyboardVIA>, public MOS::MOS6522IRQDelegate {
|
||||
public:
|
||||
KeyboardVIA() {
|
||||
clear_all_keys();
|
||||
}
|
||||
|
||||
void set_key_state(Key key, bool isPressed) {
|
||||
if(isPressed)
|
||||
_columns[key & 7] &= ~(key >> 3);
|
||||
@ -85,9 +107,6 @@ class KeyboardVIA: public MOS::MOS6522<KeyboardVIA>, public MOS::MOS6522IRQDeleg
|
||||
_activation_mask = (value & mask) | (~mask);
|
||||
}
|
||||
|
||||
KeyboardVIA() {
|
||||
clear_all_keys();
|
||||
}
|
||||
private:
|
||||
uint8_t _columns[8];
|
||||
uint8_t _activation_mask;
|
||||
|
@ -14,3 +14,53 @@ void Tape::seek(Tape::Time seek_time)
|
||||
{
|
||||
// TODO: as best we can
|
||||
}
|
||||
|
||||
TapePlayer::TapePlayer(unsigned int input_clock_rate) :
|
||||
_input_clock_rate(input_clock_rate)
|
||||
{}
|
||||
|
||||
void TapePlayer::set_tape(std::shared_ptr<Storage::Tape> tape)
|
||||
{
|
||||
_tape = tape;
|
||||
get_next_pulse();
|
||||
}
|
||||
|
||||
bool TapePlayer::has_tape()
|
||||
{
|
||||
return (bool)_tape;
|
||||
}
|
||||
|
||||
void TapePlayer::get_next_pulse()
|
||||
{
|
||||
_input.time_into_pulse = 0;
|
||||
if(_tape)
|
||||
_input.current_pulse = _tape->get_next_pulse();
|
||||
else
|
||||
{
|
||||
_input.current_pulse.length.length = 1;
|
||||
_input.current_pulse.length.clock_rate = 1;
|
||||
_input.current_pulse.type = Storage::Tape::Pulse::Zero;
|
||||
}
|
||||
if(_input.pulse_stepper == nullptr || _input.current_pulse.length.clock_rate != _input.pulse_stepper->get_output_rate())
|
||||
{
|
||||
_input.pulse_stepper.reset(new SignalProcessing::Stepper(_input.current_pulse.length.clock_rate, _input_clock_rate));
|
||||
}
|
||||
}
|
||||
|
||||
void TapePlayer::run_for_cycles(unsigned int number_of_cycles)
|
||||
{
|
||||
if(has_tape())
|
||||
{
|
||||
_input.time_into_pulse += (unsigned int)_input.pulse_stepper->step();
|
||||
if(_input.time_into_pulse == _input.current_pulse.length.length)
|
||||
{
|
||||
run_for_input_pulse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TapePlayer::run_for_input_pulse()
|
||||
{
|
||||
process_input_pulse(_input.current_pulse);
|
||||
get_next_pulse();
|
||||
}
|
||||
|
@ -9,13 +9,13 @@
|
||||
#ifndef Tape_hpp
|
||||
#define Tape_hpp
|
||||
|
||||
#include <stdio.h>
|
||||
#include <memory>
|
||||
#include "../../SignalProcessing/Stepper.hpp"
|
||||
|
||||
namespace Storage {
|
||||
|
||||
class Tape {
|
||||
public:
|
||||
|
||||
struct Time {
|
||||
unsigned int length, clock_rate;
|
||||
};
|
||||
@ -33,7 +33,31 @@ class Tape {
|
||||
virtual void seek(Time seek_time);
|
||||
};
|
||||
|
||||
class TapePlayer {
|
||||
public:
|
||||
TapePlayer(unsigned int input_clock_rate);
|
||||
|
||||
void set_tape(std::shared_ptr<Storage::Tape> tape);
|
||||
bool has_tape();
|
||||
|
||||
void run_for_cycles(unsigned int number_of_cycles);
|
||||
void run_for_input_pulse();
|
||||
|
||||
protected:
|
||||
virtual void process_input_pulse(Tape::Pulse pulse) = 0;
|
||||
|
||||
private:
|
||||
inline void get_next_pulse();
|
||||
|
||||
unsigned int _input_clock_rate;
|
||||
std::shared_ptr<Storage::Tape> _tape;
|
||||
struct {
|
||||
Tape::Pulse current_pulse;
|
||||
std::unique_ptr<SignalProcessing::Stepper> pulse_stepper;
|
||||
uint32_t time_into_pulse;
|
||||
} _input;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* Tape_hpp */
|
||||
|
Loading…
Reference in New Issue
Block a user