diff --git a/Storage/Disk/Drive.cpp b/Storage/Disk/Drive.cpp index 4458f5089..5fed936de 100644 --- a/Storage/Disk/Drive.cpp +++ b/Storage/Disk/Drive.cpp @@ -12,13 +12,15 @@ #include #include +#include using namespace Storage::Disk; Drive::Drive(unsigned int input_clock_rate, int revolutions_per_minute, int number_of_heads): Storage::TimedEventLoop(input_clock_rate), rotational_multiplier_(60, revolutions_per_minute), - available_heads_(number_of_heads) { + available_heads_(number_of_heads), + random_source_(static_cast(arc4random()) | (static_cast(arc4random()) << 32)) { rotational_multiplier_.simplify(); } @@ -161,10 +163,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, // supplying a proper duration_already_passed. if(!track_) { + random_interval_.set_zero(); setup_track(); 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_) { current_event_ = track_->get_next_event(); } else { @@ -178,6 +198,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 > duration_already_passed); 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); } diff --git a/Storage/Disk/Drive.hpp b/Storage/Disk/Drive.hpp index 445999906..a5601ea9a 100644 --- a/Storage/Disk/Drive.hpp +++ b/Storage/Disk/Drive.hpp @@ -199,6 +199,10 @@ class Drive: public Sleeper, public TimedEventLoop { Activity::Observer *observer_ = nullptr; std::string drive_name_; bool announce_motor_led_ = false; + + // A rotating random data source. + uint64_t random_source_; + Time random_interval_; };