diff --git a/Components/6522/6522.hpp b/Components/6522/6522.hpp index e6f1fbd32..a9cebfe6f 100644 --- a/Components/6522/6522.hpp +++ b/Components/6522/6522.hpp @@ -166,7 +166,7 @@ template 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 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 diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index fbbb1b91e..c65516912 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -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 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 diff --git a/Machines/Electron/Electron.hpp b/Machines/Electron/Electron.hpp index 6fe964641..2571b7538 100644 --- a/Machines/Electron/Electron.hpp +++ b/Machines/Electron/Electron.hpp @@ -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 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 _tape; - struct { - Storage::Tape::Pulse current_pulse; - std::unique_ptr pulse_stepper; - uint32_t time_into_pulse; int minimum_bits_until_full; } _input; struct { diff --git a/Machines/Vic-20/Vic20.hpp b/Machines/Vic-20/Vic20.hpp index 1862daca8..fb6d5c007 100644 --- a/Machines/Vic-20/Vic20.hpp +++ b/Machines/Vic-20/Vic20.hpp @@ -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 tape); + void run_for_cycles(int number_of_cycles); + + private: + struct { + Storage::Tape::Pulse current_pulse; + std::unique_ptr pulse_stepper; + uint32_t time_into_pulse; + } _input; +}; + class UserPortVIA: public MOS::MOS6522, public MOS::MOS6522IRQDelegate { }; class KeyboardVIA: public MOS::MOS6522, 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, public MOS::MOS6522IRQDeleg _activation_mask = (value & mask) | (~mask); } - KeyboardVIA() { - clear_all_keys(); - } private: uint8_t _columns[8]; uint8_t _activation_mask; diff --git a/Storage/Tape/Tape.cpp b/Storage/Tape/Tape.cpp index e90165245..dc8ac86bd 100644 --- a/Storage/Tape/Tape.cpp +++ b/Storage/Tape/Tape.cpp @@ -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 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(); +} diff --git a/Storage/Tape/Tape.hpp b/Storage/Tape/Tape.hpp index 9ee6c1fd0..eecae2862 100644 --- a/Storage/Tape/Tape.hpp +++ b/Storage/Tape/Tape.hpp @@ -9,13 +9,13 @@ #ifndef Tape_hpp #define Tape_hpp -#include +#include +#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 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 _tape; + struct { + Tape::Pulse current_pulse; + std::unique_ptr pulse_stepper; + uint32_t time_into_pulse; + } _input; +}; + } - #endif /* Tape_hpp */