1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-02 20:30:00 +00:00

Factored out the stuff of playing a tape, started basic sketch of the Vic-related classes.

This commit is contained in:
Thomas Harte 2016-06-26 19:03:57 -04:00
parent 066db59773
commit 37ba42a52f
6 changed files with 112 additions and 59 deletions

View File

@ -166,7 +166,7 @@ template <class T> class MOS6522 {
return 0xff; 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) switch(line)
{ {
@ -258,6 +258,7 @@ template <class T> class MOS6522 {
// Expected to be overridden // Expected to be overridden
uint8_t get_port_input(Port port) { return 0xff; } uint8_t get_port_input(Port port) { return 0xff; }
void set_port_output(Port port, uint8_t value, uint8_t direction_mask) {} 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) {} // void set_interrupt_status(bool status) {}
// Input/output multiplexer // Input/output multiplexer

View File

@ -901,35 +901,14 @@ void Speaker::set_is_enabled(bool is_enabled)
*/ */
Tape::Tape() : Tape::Tape() :
TapePlayer(2000000),
_is_running(false), _is_running(false),
_data_register(0), _data_register(0),
_delegate(nullptr), _delegate(nullptr),
_output({.bits_remaining_until_empty = 0, .cycles_into_pulse = 0}), _output({.bits_remaining_until_empty = 0, .cycles_into_pulse = 0}),
_last_posted_interrupt_status(0), _last_posted_interrupt_status(0),
_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));
}
}
inline void Tape::push_tape_bit(uint16_t bit) 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); 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[0] = _crossings[1];
_crossings[1] = _crossings[2]; _crossings[1] = _crossings[2];
_crossings[2] = _crossings[3]; _crossings[2] = _crossings[3];
_crossings[3] = Tape::Unrecognised; _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 / 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; 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_in_input_mode)
{ {
if(_is_running && _tape != nullptr) if(_is_running)
{ {
while(number_of_cycles--) TapePlayer::run_for_cycles(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();
}
}
} }
} }
else else

View File

@ -62,15 +62,11 @@ enum Key: uint16_t {
TerminateSequence = 0, NotMapped = 0xfffe, TerminateSequence = 0, NotMapped = 0xfffe,
}; };
class Tape { class Tape: public Storage::TapePlayer {
public: public:
Tape(); Tape();
void set_tape(std::shared_ptr<Storage::Tape> tape); inline void run_for_cycles(unsigned int number_of_cycles);
inline bool has_tape()
{
return (bool)_tape;
}
inline uint8_t get_data_register(); inline uint8_t get_data_register();
inline void set_data_register(uint8_t value); inline void set_data_register(uint8_t value);
@ -85,23 +81,16 @@ class Tape {
}; };
inline void set_delegate(Delegate *delegate) { _delegate = delegate; } 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_running(bool is_running) { _is_running = is_running; }
inline void set_is_enabled(bool is_enabled) { _is_enabled = is_enabled; } inline void set_is_enabled(bool is_enabled) { _is_enabled = is_enabled; }
inline void set_is_in_input_mode(bool is_in_input_mode); inline void set_is_in_input_mode(bool is_in_input_mode);
private: private:
void process_input_pulse(Storage::Tape::Pulse pulse);
inline void push_tape_bit(uint16_t bit); inline void push_tape_bit(uint16_t bit);
inline void get_next_tape_pulse(); inline void get_next_tape_pulse();
std::shared_ptr<Storage::Tape> _tape;
struct { struct {
Storage::Tape::Pulse current_pulse;
std::unique_ptr<SignalProcessing::Stepper> pulse_stepper;
uint32_t time_into_pulse;
int minimum_bits_until_full; int minimum_bits_until_full;
} _input; } _input;
struct { struct {

View File

@ -49,11 +49,33 @@ enum Key: uint16_t {
TerminateSequence = 0, NotMapped = 0xffff 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 UserPortVIA: public MOS::MOS6522<UserPortVIA>, public MOS::MOS6522IRQDelegate {
}; };
class KeyboardVIA: public MOS::MOS6522<KeyboardVIA>, public MOS::MOS6522IRQDelegate { class KeyboardVIA: public MOS::MOS6522<KeyboardVIA>, public MOS::MOS6522IRQDelegate {
public: public:
KeyboardVIA() {
clear_all_keys();
}
void set_key_state(Key key, bool isPressed) { void set_key_state(Key key, bool isPressed) {
if(isPressed) if(isPressed)
_columns[key & 7] &= ~(key >> 3); _columns[key & 7] &= ~(key >> 3);
@ -85,9 +107,6 @@ class KeyboardVIA: public MOS::MOS6522<KeyboardVIA>, public MOS::MOS6522IRQDeleg
_activation_mask = (value & mask) | (~mask); _activation_mask = (value & mask) | (~mask);
} }
KeyboardVIA() {
clear_all_keys();
}
private: private:
uint8_t _columns[8]; uint8_t _columns[8];
uint8_t _activation_mask; uint8_t _activation_mask;

View File

@ -14,3 +14,53 @@ void Tape::seek(Tape::Time seek_time)
{ {
// TODO: as best we can // 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();
}

View File

@ -9,13 +9,13 @@
#ifndef Tape_hpp #ifndef Tape_hpp
#define Tape_hpp #define Tape_hpp
#include <stdio.h> #include <memory>
#include "../../SignalProcessing/Stepper.hpp"
namespace Storage { namespace Storage {
class Tape { class Tape {
public: public:
struct Time { struct Time {
unsigned int length, clock_rate; unsigned int length, clock_rate;
}; };
@ -33,7 +33,31 @@ class Tape {
virtual void seek(Time seek_time); 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 */ #endif /* Tape_hpp */