mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-26 15:32:04 +00:00
Started stepping slowly towards allowing writing on the disk controller, taking the opportunity to introduce self-simplifying behaviour to Storage::Time.
This commit is contained in:
parent
42f25cdffc
commit
1e970a9772
@ -13,6 +13,8 @@ using namespace Storage::Disk;
|
||||
Controller::Controller(unsigned int clock_rate, unsigned int clock_rate_multiplier, unsigned int revolutions_per_minute) :
|
||||
clock_rate_(clock_rate * clock_rate_multiplier),
|
||||
clock_rate_multiplier_(clock_rate_multiplier),
|
||||
is_reading_(true),
|
||||
track_is_dirty_(false),
|
||||
|
||||
TimedEventLoop(clock_rate * clock_rate_multiplier)
|
||||
{
|
||||
@ -28,18 +30,20 @@ Controller::Controller(unsigned int clock_rate, unsigned int clock_rate_multipli
|
||||
void Controller::setup_track()
|
||||
{
|
||||
track_ = drive_->get_track();
|
||||
track_is_dirty_ = false;
|
||||
|
||||
Time offset;
|
||||
if(track_ && time_into_track_.length > 0)
|
||||
Time track_time_now = get_time_into_track();
|
||||
if(track_ && track_time_now > Time(0))
|
||||
{
|
||||
Time time_found = track_->seek_to(time_into_track_).simplify();
|
||||
offset = (time_into_track_ - time_found).simplify();
|
||||
time_into_track_ = time_found;
|
||||
Time time_found = track_->seek_to(track_time_now);
|
||||
offset = track_time_now - time_found;
|
||||
time_into_track_of_last_event_ = time_found;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = time_into_track_;
|
||||
time_into_track_.set_zero();
|
||||
offset = track_time_now;
|
||||
time_into_track_of_last_event_.set_zero();
|
||||
}
|
||||
|
||||
reset_timer_to_offset(offset * rotational_multiplier_);
|
||||
@ -56,7 +60,10 @@ void Controller::run_for_cycles(int number_of_cycles)
|
||||
{
|
||||
int cycles_until_next_event = (int)get_cycles_until_next_event();
|
||||
int cycles_to_run_for = std::min(cycles_until_next_event, number_of_cycles);
|
||||
|
||||
cycles_since_index_hole_ += (unsigned int)cycles_to_run_for;
|
||||
cycles_since_event_ += (unsigned int)cycles_to_run_for;
|
||||
|
||||
number_of_cycles -= cycles_to_run_for;
|
||||
pll_->run_for_cycles(cycles_to_run_for);
|
||||
TimedEventLoop::run_for_cycles(cycles_to_run_for);
|
||||
@ -84,21 +91,51 @@ void Controller::get_next_event()
|
||||
|
||||
void Controller::process_next_event()
|
||||
{
|
||||
cycles_since_event_ = 0;
|
||||
switch(current_event_.type)
|
||||
{
|
||||
case Track::Event::FluxTransition:
|
||||
pll_->add_pulse();
|
||||
time_into_track_ += current_event_.length;
|
||||
time_into_track_of_last_event_ += current_event_.length;
|
||||
break;
|
||||
case Track::Event::IndexHole:
|
||||
printf("%d [/%d = %d]\n", cycles_since_index_hole_, clock_rate_multiplier_, cycles_since_index_hole_ / clock_rate_multiplier_);
|
||||
cycles_since_index_hole_ = 0;
|
||||
time_into_track_.set_zero();
|
||||
time_into_track_of_last_event_.set_zero();
|
||||
process_index_hole();
|
||||
break;
|
||||
}
|
||||
get_next_event();
|
||||
}
|
||||
|
||||
Storage::Time Controller::get_time_into_track()
|
||||
{
|
||||
// this is proportion of a second
|
||||
Time result(cycles_since_index_hole_, 8000000 * clock_rate_multiplier_);
|
||||
result /= rotational_multiplier_;
|
||||
result.simplify();
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma mark - Writing
|
||||
|
||||
void Controller::begin_writing()
|
||||
{
|
||||
write_segment_.length_of_a_bit = bit_length_ * rotational_multiplier_;
|
||||
write_segment_.data.clear();
|
||||
write_segment_.number_of_bits = 0;
|
||||
|
||||
// write_start_time_;
|
||||
}
|
||||
|
||||
void Controller::write_bit(bool value)
|
||||
{
|
||||
}
|
||||
|
||||
void Controller::end_writing()
|
||||
{
|
||||
}
|
||||
|
||||
#pragma mark - PLL control and delegate
|
||||
|
||||
void Controller::set_expected_bit_length(Time bit_length)
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "Drive.hpp"
|
||||
#include "DigitalPhaseLockedLoop.hpp"
|
||||
#include "PCMSegment.hpp"
|
||||
#include "../TimedEventLoop.hpp"
|
||||
|
||||
namespace Storage {
|
||||
@ -107,14 +108,20 @@ class Controller: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop
|
||||
std::shared_ptr<DigitalPhaseLockedLoop> pll_;
|
||||
std::shared_ptr<Drive> drive_;
|
||||
std::shared_ptr<Track> track_;
|
||||
unsigned int cycles_since_index_hole_;
|
||||
unsigned int cycles_since_index_hole_, cycles_since_event_;
|
||||
|
||||
inline void get_next_event();
|
||||
Track::Event current_event_;
|
||||
Time time_into_track_;
|
||||
Time time_into_track_of_last_event_;
|
||||
bool motor_is_on_;
|
||||
|
||||
bool is_reading_;
|
||||
bool track_is_dirty_;
|
||||
PCMSegment write_segment_;
|
||||
Time write_start_time_;
|
||||
|
||||
void setup_track();
|
||||
Time get_time_into_track();
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,9 @@
|
||||
#define Storage_hpp
|
||||
|
||||
#include "../NumberTheory/Factors.hpp"
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace Storage {
|
||||
|
||||
@ -20,19 +23,27 @@ namespace Storage {
|
||||
struct Time {
|
||||
unsigned int length, clock_rate;
|
||||
Time() : length(0), clock_rate(1) {}
|
||||
Time(unsigned int int_value) : length(int_value), clock_rate(1) {}
|
||||
Time(unsigned int unsigned_int_value) : length(unsigned_int_value), clock_rate(1) {}
|
||||
Time(int int_value) : Time((unsigned int)int_value) {}
|
||||
Time(unsigned int length, unsigned int clock_rate) : length(length), clock_rate(clock_rate) {}
|
||||
Time(uint64_t length, uint64_t clock_rate)
|
||||
{
|
||||
install_result(length, clock_rate);
|
||||
}
|
||||
Time(float value)
|
||||
{
|
||||
install_float(value);
|
||||
}
|
||||
|
||||
/*!
|
||||
Reduces this @c Time to its simplest form — eliminates all common factors from @c length
|
||||
and @c clock_rate.
|
||||
*/
|
||||
inline Time &simplify()
|
||||
void simplify()
|
||||
{
|
||||
unsigned int common_divisor = NumberTheory::greatest_common_divisor(length, clock_rate);
|
||||
length /= common_divisor;
|
||||
clock_rate /= common_divisor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -50,116 +61,116 @@ struct Time {
|
||||
|
||||
inline bool operator < (const Time &other) const
|
||||
{
|
||||
return other.clock_rate * length < clock_rate * other.length;
|
||||
return (uint64_t)other.clock_rate * (uint64_t)length < (uint64_t)clock_rate * (uint64_t)other.length;
|
||||
}
|
||||
|
||||
inline bool operator <= (const Time &other) const
|
||||
{
|
||||
return other.clock_rate * length <= clock_rate * other.length;
|
||||
return (uint64_t)other.clock_rate * (uint64_t)length <= (uint64_t)clock_rate * (uint64_t)other.length;
|
||||
}
|
||||
|
||||
inline bool operator > (const Time &other) const
|
||||
{
|
||||
return other.clock_rate * length > clock_rate * other.length;
|
||||
return (uint64_t)other.clock_rate * (uint64_t)length > (uint64_t)clock_rate * (uint64_t)other.length;
|
||||
}
|
||||
|
||||
inline bool operator >= (const Time &other) const
|
||||
{
|
||||
return other.clock_rate * length >= clock_rate * other.length;
|
||||
return (uint64_t)other.clock_rate * (uint64_t)length >= (uint64_t)clock_rate * (uint64_t)other.length;
|
||||
}
|
||||
|
||||
inline bool operator == (const Time &other) const
|
||||
{
|
||||
return other.clock_rate * length == clock_rate * other.length;
|
||||
return (uint64_t)other.clock_rate * (uint64_t)length == (uint64_t)clock_rate * (uint64_t)other.length;
|
||||
}
|
||||
|
||||
inline Time operator + (const Time &other) const
|
||||
{
|
||||
Time result;
|
||||
result.clock_rate = NumberTheory::least_common_multiple(clock_rate, other.clock_rate);
|
||||
result.length = length * (result.clock_rate / clock_rate) + other.length * (result.clock_rate / other.clock_rate);
|
||||
return result;
|
||||
uint64_t result_length = (uint64_t)length * (uint64_t)other.clock_rate + (uint64_t)other.length * (uint64_t)clock_rate;
|
||||
uint64_t result_clock_rate = (uint64_t)clock_rate * (uint64_t)other.clock_rate;
|
||||
return Time(result_length, result_clock_rate);
|
||||
}
|
||||
|
||||
inline Time &operator += (const Time &other)
|
||||
{
|
||||
unsigned int combined_clock_rate = NumberTheory::least_common_multiple(clock_rate, other.clock_rate);
|
||||
length = length * (combined_clock_rate / clock_rate) + other.length * (combined_clock_rate / other.clock_rate);
|
||||
clock_rate = combined_clock_rate;
|
||||
uint64_t result_length = (uint64_t)length * (uint64_t)other.clock_rate + (uint64_t)other.length * (uint64_t)clock_rate;
|
||||
uint64_t result_clock_rate = (uint64_t)clock_rate * (uint64_t)other.clock_rate;
|
||||
install_result(result_length, result_clock_rate);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Time operator - (const Time &other) const
|
||||
{
|
||||
Time result;
|
||||
result.clock_rate = NumberTheory::least_common_multiple(clock_rate, other.clock_rate);
|
||||
result.length = length * (result.clock_rate / clock_rate) - other.length * (result.clock_rate / other.clock_rate);
|
||||
return result;
|
||||
uint64_t result_length = (uint64_t)length * (uint64_t)other.clock_rate - (uint64_t)other.length * (uint64_t)clock_rate;
|
||||
uint64_t result_clock_rate = (uint64_t)clock_rate * (uint64_t)other.clock_rate;
|
||||
return Time(result_length, result_clock_rate);
|
||||
}
|
||||
|
||||
inline Time operator -= (const Time &other)
|
||||
{
|
||||
unsigned int combined_clock_rate = NumberTheory::least_common_multiple(clock_rate, other.clock_rate);
|
||||
length = length * (combined_clock_rate / clock_rate) - other.length * (combined_clock_rate / other.clock_rate);
|
||||
clock_rate = combined_clock_rate;
|
||||
uint64_t result_length = (uint64_t)length * (uint64_t)other.clock_rate - (uint64_t)other.length * (uint64_t)clock_rate;
|
||||
uint64_t result_clock_rate = (uint64_t)clock_rate * (uint64_t)other.clock_rate;
|
||||
install_result(result_length, result_clock_rate);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Time operator * (const Time &other) const
|
||||
{
|
||||
Time result;
|
||||
result.clock_rate = clock_rate * other.clock_rate;
|
||||
result.length = length * other.length;
|
||||
return result;
|
||||
uint64_t result_length = (uint64_t)length * (uint64_t)other.length;
|
||||
uint64_t result_clock_rate = (uint64_t)clock_rate * (uint64_t)other.clock_rate;
|
||||
return Time(result_length, result_clock_rate);
|
||||
}
|
||||
|
||||
inline Time &operator *= (const Time &other)
|
||||
{
|
||||
length *= other.length;
|
||||
clock_rate *= other.clock_rate;
|
||||
uint64_t result_length = (uint64_t)length * (uint64_t)other.length;
|
||||
uint64_t result_clock_rate = (uint64_t)clock_rate * (uint64_t)other.clock_rate;
|
||||
install_result(result_length, result_clock_rate);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Time operator * (unsigned int multiplier) const
|
||||
{
|
||||
Time result;
|
||||
result.clock_rate = clock_rate;
|
||||
result.length = length * multiplier;
|
||||
return result;
|
||||
uint64_t result_length = (uint64_t)length * (uint64_t)multiplier;
|
||||
uint64_t result_clock_rate = (uint64_t)clock_rate;
|
||||
return Time(result_length, result_clock_rate);
|
||||
}
|
||||
|
||||
inline Time &operator *= (unsigned int multiplier)
|
||||
{
|
||||
length *= multiplier;
|
||||
uint64_t result_length = (uint64_t)length * (uint64_t)multiplier;
|
||||
uint64_t result_clock_rate = (uint64_t)clock_rate;
|
||||
install_result(result_length, result_clock_rate);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Time operator / (const Time &other) const
|
||||
{
|
||||
Time result;
|
||||
result.clock_rate = clock_rate * other.length;
|
||||
result.length = length * other.clock_rate;
|
||||
return result;
|
||||
uint64_t result_length = (uint64_t)length * (uint64_t)other.clock_rate;
|
||||
uint64_t result_clock_rate = (uint64_t)clock_rate * (uint64_t)other.length;
|
||||
return Time(result_length, result_clock_rate);
|
||||
}
|
||||
|
||||
inline Time &operator /= (const Time &other)
|
||||
{
|
||||
length *= other.clock_rate;
|
||||
clock_rate *= other.length;
|
||||
uint64_t result_length = (uint64_t)length * (uint64_t)other.clock_rate;
|
||||
uint64_t result_clock_rate = (uint64_t)clock_rate * (uint64_t)other.length;
|
||||
install_result(result_length, result_clock_rate);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Time operator / (unsigned int divisor) const
|
||||
{
|
||||
Time result;
|
||||
result.length = length;
|
||||
result.clock_rate = clock_rate * divisor;
|
||||
return result;
|
||||
uint64_t result_length = (uint64_t)length;
|
||||
uint64_t result_clock_rate = (uint64_t)clock_rate * (uint64_t)divisor;
|
||||
return Time(result_length, result_clock_rate);
|
||||
}
|
||||
|
||||
inline Time &operator /= (unsigned int divisor)
|
||||
{
|
||||
clock_rate *= divisor;
|
||||
uint64_t result_length = (uint64_t)length;
|
||||
uint64_t result_clock_rate = (uint64_t)clock_rate * (uint64_t)divisor;
|
||||
install_result(result_length, result_clock_rate);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -174,6 +185,45 @@ struct Time {
|
||||
length = 1;
|
||||
clock_rate = 1;
|
||||
}
|
||||
|
||||
private:
|
||||
inline void install_result(uint64_t long_length, uint64_t long_clock_rate)
|
||||
{
|
||||
// TODO: switch to appropriate values if the result is too large or small to fit, even with trimmed accuracy.
|
||||
|
||||
while(!(long_length&1) && !(long_clock_rate&1))
|
||||
{
|
||||
long_length >>= 1;
|
||||
long_clock_rate >>= 1;
|
||||
}
|
||||
|
||||
if(long_length > std::numeric_limits<unsigned int>::max() || long_clock_rate > std::numeric_limits<unsigned int>::max())
|
||||
{
|
||||
uint64_t common_divisor = NumberTheory::greatest_common_divisor(long_length, long_clock_rate);
|
||||
long_length /= common_divisor;
|
||||
long_clock_rate /= common_divisor;
|
||||
|
||||
// Okay, in desperation accept a loss of accuracy.
|
||||
while(long_length > std::numeric_limits<unsigned int>::max() || long_clock_rate > std::numeric_limits<unsigned int>::max())
|
||||
{
|
||||
long_length >>= 1;
|
||||
long_clock_rate >>= 1;
|
||||
}
|
||||
}
|
||||
length = (unsigned int)long_length;
|
||||
clock_rate = (unsigned int)long_clock_rate;
|
||||
}
|
||||
|
||||
inline void install_float(float value)
|
||||
{
|
||||
int exponent;
|
||||
float mantissa = frexpf(value, &exponent);
|
||||
float loaded_mantissa = ldexpf(mantissa, 24);
|
||||
|
||||
uint64_t result_length = (uint64_t)loaded_mantissa;
|
||||
uint64_t result_clock_rate = 1 << (exponent - 24);
|
||||
install_result(result_length, result_clock_rate);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user