mirror of
				https://github.com/TomHarte/CLK.git
				synced 2025-11-04 00:16:26 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			100 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//
 | 
						|
//  TimedMachine.hpp
 | 
						|
//  Clock Signal
 | 
						|
//
 | 
						|
//  Created by Thomas Harte on 31/03/2020.
 | 
						|
//  Copyright © 2020 Thomas Harte. All rights reserved.
 | 
						|
//
 | 
						|
 | 
						|
#pragma once
 | 
						|
 | 
						|
#include "ClockReceiver/ClockReceiver.hpp"
 | 
						|
#include "ClockReceiver/TimeTypes.hpp"
 | 
						|
 | 
						|
#include "AudioProducer.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(const 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(const 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) = 0;
 | 
						|
 | 
						|
	/// Sets this machine's clock rate.
 | 
						|
	void set_clock_rate(const 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;
 | 
						|
};
 | 
						|
 | 
						|
}
 |