mirror of
https://github.com/TomHarte/CLK.git
synced 2024-10-13 21:24:23 +00:00
Merge pull request #443 from TomHarte/DiskGainNoise
Ensures generation of random noise if too many zeroes exist on a disk.
This commit is contained in:
commit
6c8e6e9303
@ -12,6 +12,9 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <chrono>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
using namespace Storage::Disk;
|
using namespace Storage::Disk;
|
||||||
|
|
||||||
@ -20,6 +23,17 @@ Drive::Drive(unsigned int input_clock_rate, int revolutions_per_minute, int numb
|
|||||||
rotational_multiplier_(60, revolutions_per_minute),
|
rotational_multiplier_(60, revolutions_per_minute),
|
||||||
available_heads_(number_of_heads) {
|
available_heads_(number_of_heads) {
|
||||||
rotational_multiplier_.simplify();
|
rotational_multiplier_.simplify();
|
||||||
|
|
||||||
|
const auto seed = static_cast<std::default_random_engine::result_type>(std::chrono::system_clock::now().time_since_epoch().count());
|
||||||
|
std::default_random_engine randomiser(seed);
|
||||||
|
|
||||||
|
// Get at least 64 bits of random information; rounding is likey to give this a slight bias.
|
||||||
|
random_source_ = 0;
|
||||||
|
auto half_range = (randomiser.max() - randomiser.min()) / 2;
|
||||||
|
for(int bit = 0; bit < 64; ++bit) {
|
||||||
|
random_source_ <<= 1;
|
||||||
|
random_source_ |= ((randomiser() - randomiser.min()) >= half_range) ? 1 : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Drive::~Drive() {
|
Drive::~Drive() {
|
||||||
@ -161,10 +175,28 @@ void Drive::get_next_event(const Time &duration_already_passed) {
|
|||||||
// Grab a new track if not already in possession of one. This will recursively call get_next_event,
|
// Grab a new track if not already in possession of one. This will recursively call get_next_event,
|
||||||
// supplying a proper duration_already_passed.
|
// supplying a proper duration_already_passed.
|
||||||
if(!track_) {
|
if(!track_) {
|
||||||
|
random_interval_.set_zero();
|
||||||
setup_track();
|
setup_track();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If gain has now been turned up so as to generate noise, generate some noise.
|
||||||
|
if(random_interval_ > Time(0)) {
|
||||||
|
current_event_.type = Track::Event::IndexHole;
|
||||||
|
current_event_.length.length = 2 + (random_source_&1);
|
||||||
|
current_event_.length.clock_rate = 1000000;
|
||||||
|
random_source_ = (random_source_ >> 1) | (random_source_ << 63);
|
||||||
|
|
||||||
|
if(random_interval_ < current_event_.length) {
|
||||||
|
current_event_.length = random_interval_;
|
||||||
|
random_interval_.set_zero();
|
||||||
|
} else {
|
||||||
|
random_interval_ -= current_event_.length;
|
||||||
|
}
|
||||||
|
set_next_event_time_interval(current_event_.length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(track_) {
|
if(track_) {
|
||||||
current_event_ = track_->get_next_event();
|
current_event_ = track_->get_next_event();
|
||||||
} else {
|
} else {
|
||||||
@ -178,6 +210,15 @@ void Drive::get_next_event(const Time &duration_already_passed) {
|
|||||||
assert(current_event_.length <= Time(1) && current_event_.length >= Time(0));
|
assert(current_event_.length <= Time(1) && current_event_.length >= Time(0));
|
||||||
assert(current_event_.length > duration_already_passed);
|
assert(current_event_.length > duration_already_passed);
|
||||||
Time interval = (current_event_.length - duration_already_passed) * rotational_multiplier_;
|
Time interval = (current_event_.length - duration_already_passed) * rotational_multiplier_;
|
||||||
|
|
||||||
|
// An interval greater than 15ms => adjust gain up the point where noise starts happening.
|
||||||
|
// Seed that up and leave a 15ms gap until it starts.
|
||||||
|
const Time safe_gain_period(15, 1000000);
|
||||||
|
if(interval >= safe_gain_period) {
|
||||||
|
random_interval_ = interval - safe_gain_period;
|
||||||
|
interval = safe_gain_period;
|
||||||
|
}
|
||||||
|
|
||||||
set_next_event_time_interval(interval);
|
set_next_event_time_interval(interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +199,10 @@ class Drive: public Sleeper, public TimedEventLoop {
|
|||||||
Activity::Observer *observer_ = nullptr;
|
Activity::Observer *observer_ = nullptr;
|
||||||
std::string drive_name_;
|
std::string drive_name_;
|
||||||
bool announce_motor_led_ = false;
|
bool announce_motor_led_ = false;
|
||||||
|
|
||||||
|
// A rotating random data source.
|
||||||
|
uint64_t random_source_;
|
||||||
|
Time random_interval_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user