mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-09 01:10:10 +00:00
104 lines
2.7 KiB
C++
104 lines
2.7 KiB
C++
//
|
|
// TimedMachine.hpp
|
|
// Clock Signal
|
|
//
|
|
// Created by Thomas Harte on 31/03/2020.
|
|
// Copyright © 2020 Thomas Harte. All rights reserved.
|
|
//
|
|
|
|
#ifndef TimedMachine_h
|
|
#define TimedMachine_h
|
|
|
|
#include "../ClockReceiver/ClockReceiver.hpp"
|
|
#include "../ClockReceiver/TimeTypes.hpp"
|
|
|
|
#include "AudioProducer.hpp"
|
|
#include "ScanProducer.hpp"
|
|
|
|
#include <cmath>
|
|
|
|
namespace MachineTypes {
|
|
|
|
/*!
|
|
A timed machine is any which requires the owner to provide time-based updates,
|
|
i.e. run_for(<some number of seconds>)-type calls.
|
|
|
|
*/
|
|
class TimedMachine {
|
|
public:
|
|
/// Runs the machine for @c duration seconds.
|
|
virtual void run_for(Time::Seconds duration) {
|
|
const double cycles = (duration * clock_rate_ * speed_multiplier_) + clock_conversion_error_;
|
|
clock_conversion_error_ = std::fmod(cycles, 1.0);
|
|
run_for(Cycles(int(cycles)));
|
|
}
|
|
|
|
/*!
|
|
Sets a speed multiplier to apply to this machine; e.g. a multiplier of 1.5 will cause the
|
|
emulated machine to run 50% faster than a real machine. This speed-up is an emulation
|
|
fiction: it will apply across the system, including to the CRT.
|
|
*/
|
|
virtual void set_speed_multiplier(double multiplier) {
|
|
if(speed_multiplier_ == multiplier) {
|
|
return;
|
|
}
|
|
|
|
speed_multiplier_ = multiplier;
|
|
|
|
auto audio_producer = dynamic_cast<AudioProducer *>(this);
|
|
if(!audio_producer) return;
|
|
|
|
auto speaker = audio_producer->get_speaker();
|
|
if(speaker) {
|
|
speaker->set_input_rate_multiplier(float(multiplier));
|
|
}
|
|
}
|
|
|
|
/*!
|
|
@returns The current speed multiplier.
|
|
*/
|
|
virtual double get_speed_multiplier() const {
|
|
return speed_multiplier_;
|
|
}
|
|
|
|
/// @returns The confidence that this machine is running content it understands.
|
|
virtual float get_confidence() { return 0.5f; }
|
|
virtual std::string debug_type() { return ""; }
|
|
|
|
struct Output {
|
|
static constexpr int Video = 1 << 0;
|
|
static constexpr int Audio = 1 << 1;
|
|
|
|
static constexpr int All = Video | Audio;
|
|
};
|
|
/// Ensures all locally-buffered output is posted onward for the types of output indicated
|
|
/// by the bitfield argument, which is comprised of flags from the namespace @c Output.
|
|
virtual void flush_output(int) {}
|
|
|
|
protected:
|
|
/// Runs the machine for @c cycles.
|
|
virtual void run_for(const Cycles cycles) = 0;
|
|
|
|
/// Sets this machine's clock rate.
|
|
void set_clock_rate(double clock_rate) {
|
|
clock_rate_ = clock_rate;
|
|
}
|
|
|
|
/// Gets this machine's clock rate.
|
|
double get_clock_rate() const {
|
|
return clock_rate_;
|
|
}
|
|
|
|
private:
|
|
// Give the ScanProducer access to this machine's clock rate.
|
|
friend class ScanProducer;
|
|
|
|
double clock_rate_ = 1.0;
|
|
double clock_conversion_error_ = 0.0;
|
|
double speed_multiplier_ = 1.0;
|
|
};
|
|
|
|
}
|
|
|
|
#endif /* TimedMachine_h */
|