1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-25 16:31:42 +00:00

Converted the TimedEventLoop and the things that sit atop it into ClockReceivers.

This commit is contained in:
Thomas Harte 2017-07-24 21:19:05 -04:00
parent 9bff787ee1
commit 8a2bdb8d22
16 changed files with 37 additions and 33 deletions

View File

@ -124,10 +124,11 @@ uint8_t WD1770::get_register(int address) {
}
}
void WD1770::run_for_cycles(unsigned int number_of_cycles) {
Storage::Disk::Controller::run_for_cycles((int)number_of_cycles);
void WD1770::run_for(const Cycles &cycles) {
Storage::Disk::Controller::run_for(cycles);
if(delay_time_) {
unsigned int number_of_cycles = (unsigned int)cycles.as_int();
if(delay_time_ <= number_of_cycles) {
delay_time_ = 0;
posit_event(Event::Timer);

View File

@ -11,6 +11,7 @@
#include "../../Storage/Disk/DiskController.hpp"
#include "../../NumberTheory/CRC.hpp"
#include "../ClockReceiver.hpp"
namespace WD {
@ -18,7 +19,7 @@ namespace WD {
Provides an emulation of various Western Digital drive controllers, including the
WD1770, WD1772, FDC1773 and FDC1793.
*/
class WD1770: public Storage::Disk::Controller {
class WD1770: public ClockReceiver<WD1770>, public Storage::Disk::Controller {
public:
enum Personality {
P1770, // implies automatic motor-on management, with Type 2 commands offering a spin-up disable
@ -43,7 +44,7 @@ class WD1770: public Storage::Disk::Controller {
uint8_t get_register(int address);
/// Runs the controller for @c number_of_cycles cycles.
void run_for_cycles(unsigned int number_of_cycles);
void run_for(const Cycles &cycles);
enum Flag: uint8_t {
NotReady = 0x80,

View File

@ -83,7 +83,7 @@ void Machine::run_for_cycles(int number_of_cycles) {
CPU::MOS6502::Processor<Machine>::run_for(Cycles(number_of_cycles));
set_motor_on(drive_VIA_.get_motor_enabled());
if(drive_VIA_.get_motor_enabled()) // TODO: motor speed up/down
Storage::Disk::Controller::run_for_cycles(number_of_cycles);
Storage::Disk::Controller::run_for(Cycles(number_of_cycles));
}
#pragma mark - 6522 delegate

View File

@ -187,7 +187,7 @@ unsigned int Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation
typer_.reset();
}
}
tape_->run_for_cycles(1);
tape_->run_for(Cycles(1));
if(c1540_) c1540_->run_for_cycles(1);
return 1;

View File

@ -329,7 +329,7 @@ unsigned int Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation
}
if(typer_) typer_->update((int)cycles);
if(plus3_) plus3_->run_for_cycles(4*cycles);
if(plus3_) plus3_->run_for(Cycles(4*(int)cycles));
if(shift_restart_counter_) {
shift_restart_counter_ -= cycles;
if(shift_restart_counter_ <= 0) {

View File

@ -84,7 +84,7 @@ void Tape::run_for_cycles(unsigned int number_of_cycles) {
if(is_enabled_) {
if(is_in_input_mode_) {
if(is_running_) {
TapePlayer::run_for_cycles((int)number_of_cycles);
TapePlayer::run_for(Cycles((int)number_of_cycles));
}
} else {
output_.cycles_into_pulse += number_of_cycles;

View File

@ -109,7 +109,7 @@ void Microdisc::run_for_cycles(unsigned int number_of_cycles) {
head_load_request_counter_ += number_of_cycles;
if(head_load_request_counter_ >= head_load_request_counter_target) set_head_loaded(true);
}
WD::WD1770::run_for_cycles(number_of_cycles);
WD::WD1770::run_for(Cycles((int)number_of_cycles));
}
bool Microdisc::get_drive_is_ready() {

View File

@ -243,7 +243,7 @@ void Machine::VIA::flush() {
void Machine::VIA::run_for_cycles(unsigned int number_of_cycles) {
cycles_since_ay_update_ += number_of_cycles;
MOS::MOS6522<VIA>::run_for_cycles(number_of_cycles);
tape->run_for_cycles((int)number_of_cycles);
tape->run_for(Cycles((int)number_of_cycles));
}
void Machine::VIA::update_ay() {

View File

@ -55,7 +55,7 @@ int Machine::perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
if(is_zx81_) horizontal_counter_ %= HalfCycles(Cycles(207));
if(!tape_advance_delay_) {
tape_player_.run_for_cycles(cycle.length.as_int());
tape_player_.run_for(cycle.length);
} else {
tape_advance_delay_ = std::max(tape_advance_delay_ - cycle.length, HalfCycles(0));
}

View File

@ -78,13 +78,13 @@ class CommodoreGCRParser: public Storage::Disk::Controller {
// find end of lead-in
while(shift_register_ == 0x3ff && index_count_ < 2) {
run_for_cycles(1);
run_for(Cycles(1));
}
// continue for a further nine bits
bit_count_ = 0;
while(bit_count_ < 9 && index_count_ < 2) {
run_for_cycles(1);
run_for(Cycles(1));
}
return Storage::Encodings::CommodoreGCR::decoding_from_dectet(shift_register_);
@ -92,14 +92,14 @@ class CommodoreGCRParser: public Storage::Disk::Controller {
unsigned int get_next_byte() {
bit_count_ = 0;
while(bit_count_ < 10) run_for_cycles(1);
while(bit_count_ < 10) run_for(Cycles(1));
return Storage::Encodings::CommodoreGCR::decoding_from_dectet(shift_register_);
}
void proceed_to_shift_value(unsigned int shift_value) {
index_count_ = 0;
while(shift_register_ != shift_value && index_count_ < 2) {
run_for_cycles(1);
run_for(Cycles(1));
}
}

View File

@ -75,7 +75,7 @@ void Controller::run_for(const Cycles &cycles) {
}
}
}
TimedEventLoop::run_for_cycles(cycles_to_run_for);
TimedEventLoop::run_for(Cycles(cycles_to_run_for));
}
}
}

View File

@ -294,7 +294,7 @@ uint8_t Parser::get_byte_for_shift_value(uint16_t value) {
uint8_t Parser::get_next_byte() {
bit_count_ = 0;
while(bit_count_ < 16) run_for_cycles(1);
while(bit_count_ < 16) run_for(Cycles(1));
uint8_t byte = get_byte_for_shift_value((uint16_t)shift_register_);
crc_generator_.add(byte);
return byte;
@ -309,7 +309,7 @@ std::vector<uint8_t> Parser::get_track() {
// align to the next index hole
index_count_ = 0;
while(!index_count_) run_for_cycles(1);
while(!index_count_) run_for(Cycles(1));
// capture every other bit until the next index hole
index_count_ = 0;
@ -319,7 +319,7 @@ std::vector<uint8_t> Parser::get_track() {
bool found_sync = false;
while(!index_count_ && !found_sync && bit_count_ < 16) {
int previous_bit_count = bit_count_;
run_for_cycles(1);
run_for(Cycles(1));
if(!distance_until_permissible_sync && bit_count_ != previous_bit_count) {
uint16_t low_shift_register = (shift_register_&0xffff);
@ -393,7 +393,7 @@ std::shared_ptr<Sector> Parser::get_next_sector()
// look for an ID address mark
bool id_found = false;
while(!id_found) {
run_for_cycles(1);
run_for(Cycles(1));
if(is_mfm_) {
while(shift_register_ == MFMSync) {
uint8_t mark = get_next_byte();
@ -424,7 +424,7 @@ std::shared_ptr<Sector> Parser::get_next_sector()
// look for data mark
bool data_found = false;
while(!data_found) {
run_for_cycles(1);
run_for(Cycles(1));
if(is_mfm_) {
while(shift_register_ == MFMSync) {
uint8_t mark = get_next_byte();

View File

@ -92,9 +92,9 @@ void TapePlayer::get_next_pulse() {
set_next_event_time_interval(current_pulse_.length);
}
void TapePlayer::run_for_cycles(int number_of_cycles) {
void TapePlayer::run_for(const Cycles &cycles) {
if(has_tape()) {
TimedEventLoop::run_for_cycles(number_of_cycles);
TimedEventLoop::run_for(cycles);
}
}
@ -125,8 +125,8 @@ bool BinaryTapePlayer::get_input() {
return motor_is_running_ && input_level_;
}
void BinaryTapePlayer::run_for_cycles(int number_of_cycles) {
if(motor_is_running_) TapePlayer::run_for_cycles(number_of_cycles);
void BinaryTapePlayer::run_for(const Cycles &cycles) {
if(motor_is_running_) TapePlayer::run_for(cycles);
}
void BinaryTapePlayer::set_delegate(Delegate *delegate) {

View File

@ -11,6 +11,7 @@
#include <memory>
#include "../TimedEventLoop.hpp"
#include "../../Components/ClockReceiver.hpp"
namespace Storage {
namespace Tape {
@ -91,7 +92,7 @@ class Tape {
Will call @c process_input_pulse instantaneously upon reaching *the end* of a pulse. Therefore a subclass
can decode pulses into data within process_input_pulse, using the supplied pulse's @c length and @c type.
*/
class TapePlayer: public TimedEventLoop {
class TapePlayer: public ClockReceiver<TapePlayer>, public TimedEventLoop {
public:
TapePlayer(unsigned int input_clock_rate);
@ -99,7 +100,7 @@ class TapePlayer: public TimedEventLoop {
bool has_tape();
std::shared_ptr<Storage::Tape::Tape> get_tape();
void run_for_cycles(int number_of_cycles);
void run_for(const Cycles &cycles);
void run_for_input_pulse();
protected:
@ -121,14 +122,14 @@ class TapePlayer: public TimedEventLoop {
They can also provide a delegate to be notified upon any change in the input level.
*/
class BinaryTapePlayer: public TapePlayer {
class BinaryTapePlayer: public ClockReceiver<BinaryTapePlayer>, public TapePlayer {
public:
BinaryTapePlayer(unsigned int input_clock_rate);
void set_motor_control(bool enabled);
void set_tape_output(bool set);
bool get_input();
void run_for_cycles(int number_of_cycles);
void run_for(const Cycles &cycles);
class Delegate {
public:

View File

@ -15,8 +15,8 @@ using namespace Storage;
TimedEventLoop::TimedEventLoop(unsigned int input_clock_rate) :
input_clock_rate_(input_clock_rate) {}
void TimedEventLoop::run_for_cycles(int number_of_cycles) {
cycles_until_event_ -= number_of_cycles;
void TimedEventLoop::run_for(const Cycles &cycles) {
cycles_until_event_ -= cycles.as_int();
while(cycles_until_event_ <= 0) {
process_next_event();
}

View File

@ -13,6 +13,7 @@
#include <memory>
#include "../SignalProcessing/Stepper.hpp"
#include "../Components/ClockReceiver.hpp"
namespace Storage {
@ -36,7 +37,7 @@ namespace Storage {
@c reset_timer to initiate a distinctly-timed stream or @c jump_to_next_event to short-circuit the timing
loop and fast forward immediately to the next event.
*/
class TimedEventLoop {
class TimedEventLoop: public ClockReceiver<TimedEventLoop> {
public:
/*!
Constructs a timed event loop that will be clocked at @c input_clock_rate.
@ -46,7 +47,7 @@ namespace Storage {
/*!
Advances the event loop by @c number_of_cycles cycles.
*/
void run_for_cycles(int number_of_cycles);
void run_for(const Cycles &cycles);
/*!
@returns the number of whole cycles remaining until the next event is triggered.