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:
parent
066db59773
commit
37ba42a52f
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user