1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-30 22:29:56 +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;
}
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

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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();
}

View File

@ -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 */