1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +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:
Thomas Harte 2016-12-24 13:07:23 -05:00
parent 42f25cdffc
commit 1e970a9772
3 changed files with 148 additions and 54 deletions

View File

@ -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)

View File

@ -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();
};
}

View File

@ -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);
}
};