1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-23 20:29:42 +00:00

Introduces necessary storage and interface for writing.

This commit is contained in:
Thomas Harte 2017-09-10 16:23:31 -04:00
parent 90d2347c90
commit ff6e65cca9

View File

@ -9,11 +9,14 @@
#ifndef Drive_hpp
#define Drive_hpp
#include <memory>
#include "Disk.hpp"
#include "../../ClockReceiver/Sleeper.hpp"
#include "PCMSegment.hpp"
#include "PCMPatchedTrack.hpp"
#include "../TimedEventLoop.hpp"
#include "../../ClockReceiver/Sleeper.hpp"
#include <memory>
namespace Storage {
namespace Disk {
@ -78,16 +81,50 @@ class Drive: public Sleeper, public TimedEventLoop {
*/
void set_motor_on(bool);
/*!
@returns @c true if the motor is on; @c false otherwise.
*/
bool get_motor_on();
/*!
Begins write mode, initiating a PCM sampled region of data. Bits should be written via
@c write_bit. They will be written with the length set via @c set_expected_bit_length.
It is acceptable to supply a backlog of bits. Flux transition events will not be reported
while writing.
@param clamp_to_index_hole If @c true then writing will automatically be truncated by
the index hole. Writing will continue over the index hole otherwise.
*/
void begin_writing(bool clamp_to_index_hole);
/*!
Writes the bit @c value as the next in the PCM stream initiated by @c begin_writing.
*/
void write_bit(bool value);
/*!
Ends write mode, switching back to read mode. The drive will stop overwriting events.
*/
void end_writing();
/*!
Advances the drive by @c number_of_cycles cycles.
*/
void run_for(const Cycles cycles);
/*!
Provides a mechanism to receive track events as they occur.
Provides a mechanism to receive track events as they occur, including the synthetic
event of "you told me to output the following data, and I've done that now".
*/
struct EventDelegate {
/// Informs the delegate that @c event has been reached.
virtual void process_event(const Track::Event &event) = 0;
/*!
If the drive is in write mode, announces that all queued bits have now been written.
If the controller provides further bits now then there will be no gap in written data.
*/
virtual void process_write_completed() {}
};
/// Sets the current event delegate.
@ -97,22 +134,53 @@ class Drive: public Sleeper, public TimedEventLoop {
bool is_sleeping();
private:
std::shared_ptr<Track> track_;
// Drives [usually] contain an entire disk; from that a certain track
// will be currently under the head.
std::shared_ptr<Disk> disk_;
int cycles_since_index_hole_ = 0;
Time rotational_multiplier_;
std::shared_ptr<Track> track_;
bool has_disk_ = false;
// Contains the multiplier that converts between track-relative lengths
// to real-time lengths — so it's the reciprocal of rotation speed.
Time rotational_multiplier_;
// A count of time since the index hole was last seen. Which is used to
// determine how far the drive is into a full rotation when switching to
// a new track.
int cycles_since_index_hole_ = 0;
// A record of head position and active head.
int head_position_ = 0;
unsigned int head_ = 0;
// Motor control state.
bool motor_is_on_ = false;
// If the drive is not currently reading then it is writing. While writing
// it can optionally be told to clamp to the index hole.
bool is_reading_;
bool clamp_writing_to_index_hole_;
// If writing is occurring then the drive will be accumulating a write segment,
// for addition to a patched track.
std::shared_ptr<PCMPatchedTrack> patched_track_;
PCMSegment write_segment_;
Time write_start_time_;
// Maintains appropriate counting to know when to indicate that writing
// is complete.
Time cycles_until_bits_written_;
Time cycles_per_bit_;
// TimedEventLoop call-ins and state.
void process_next_event();
void get_next_event(const Time &duration_already_passed);
Track::Event current_event_;
bool motor_is_on_ = false;
// Helper for track changes.
Time get_time_into_track();
// The target (if any) for track events.
EventDelegate *event_delegate_ = nullptr;
};