1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-22 12:33:29 +00:00

Took some small steps towards having a disk drive that at least can select a track and pump relevant events into a PLL.

This commit is contained in:
Thomas Harte 2016-07-29 07:31:02 -04:00
parent 0e581c7607
commit f984de42a3
3 changed files with 74 additions and 18 deletions

View File

@ -13,17 +13,21 @@ using namespace Storage;
DiskDrive::DiskDrive(unsigned int clock_rate, unsigned int revolutions_per_minute) :
_clock_rate(clock_rate),
_revolutions_per_minute(revolutions_per_minute),
_head_position(0) {}
_head_position(0),
TimedEventLoop(clock_rate)
{}
void DiskDrive::set_expected_bit_length(Time bit_length)
{
_bit_length = bit_length;
// _pll.reset(new DigitalPhaseLockedLoop();
}
void DiskDrive::set_disk(std::shared_ptr<Disk> disk)
{
_disk = disk;
// _track.reset();
set_track();
}
bool DiskDrive::has_disk()
@ -39,21 +43,65 @@ bool DiskDrive::get_is_track_zero()
void DiskDrive::step(int direction)
{
_head_position = std::max(_head_position + direction, 0);
_track = _disk->get_track_at_position((unsigned int)_head_position);
set_track();
}
void DiskDrive::digital_phase_locked_loop_output_bit(int value)
void DiskDrive::set_track()
{
process_input_bit(value, _cycles_since_index_hole);
_track = _disk->get_track_at_position((unsigned int)_head_position);
reset_timer();
get_next_event();
}
void DiskDrive::run_for_cycles(unsigned int number_of_cycles)
{
if(has_disk())
{
while(number_of_cycles--)
{
}
_cycles_since_index_hole += number_of_cycles;
TimedEventLoop::run_for_cycles(number_of_cycles);
}
}
#pragma mark - Track timed event loop
void DiskDrive::get_next_event()
{
if(_track)
_current_event = _track->get_next_event();
else
{
_current_event.length.length = 1;
_current_event.length.clock_rate = 1;
_current_event.type = Track::Event::IndexHole;
}
// divide interval, which is in terms of a rotation of the disk, by rotation speed, and
// convert it into revolutions per second
Time event_interval = _current_event.length;
event_interval.length *= 60;
event_interval.clock_rate *= _revolutions_per_minute;
event_interval.simplify();
set_next_event_time_interval(event_interval);
}
void DiskDrive::process_next_event()
{
switch(_current_event.type)
{
case Track::Event::FluxTransition:
_pll->add_pulse();
break;
case Track::Event::IndexHole:
_cycles_since_index_hole = 0;
process_index_hole();
break;
}
get_next_event();
}
#pragma mark - PLL delegate
void DiskDrive::digital_phase_locked_loop_output_bit(int value)
{
process_input_bit(value, _cycles_since_index_hole);
}

View File

@ -11,11 +11,11 @@
#include "Disk.hpp"
#include "DigitalPhaseLockedLoop.hpp"
#include "../../SignalProcessing/Stepper.hpp"
#include "../TimedEventLoop.hpp"
namespace Storage {
class DiskDrive: public DigitalPhaseLockedLoop::Delegate {
class DiskDrive: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop {
public:
DiskDrive(unsigned int clock_rate, unsigned int revolutions_per_minute);
@ -37,6 +37,9 @@ class DiskDrive: public DigitalPhaseLockedLoop::Delegate {
virtual void process_input_bit(int value, unsigned int cycles_since_index_hole) = 0;
virtual void process_index_hole() = 0;
// for TimedEventLoop
virtual void process_next_event();
private:
Time _bit_length;
unsigned int _clock_rate;
@ -47,14 +50,10 @@ class DiskDrive: public DigitalPhaseLockedLoop::Delegate {
std::shared_ptr<Track> _track;
int _head_position;
unsigned int _cycles_since_index_hole;
void set_track();
void install_track();
struct {
Track::Event current_event;
std::unique_ptr<SignalProcessing::Stepper> pulse_stepper;
uint32_t time_into_pulse;
} _input;
inline void get_next_event();
Track::Event _current_event;
};
}

View File

@ -9,10 +9,19 @@
#ifndef Storage_hpp
#define Storage_hpp
#include "../NumberTheory/Factors.hpp"
namespace Storage {
struct Time {
unsigned int length, clock_rate;
inline void simplify()
{
unsigned int common_divisor = NumberTheory::greatest_common_divisor(length, clock_rate);
length /= common_divisor;
clock_rate /= common_divisor;
}
};
}