2016-01-18 21:46:41 +00:00
|
|
|
//
|
|
|
|
// Tape.hpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 18/01/2016.
|
|
|
|
// Copyright © 2016 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef Tape_hpp
|
|
|
|
#define Tape_hpp
|
|
|
|
|
2016-06-26 23:03:57 +00:00
|
|
|
#include <memory>
|
2016-07-29 11:15:46 +00:00
|
|
|
#include "../TimedEventLoop.hpp"
|
2016-01-18 21:46:41 +00:00
|
|
|
|
|
|
|
namespace Storage {
|
|
|
|
|
2016-07-10 12:54:39 +00:00
|
|
|
/*!
|
|
|
|
Models a tape as a sequence of pulses, each pulse being of arbitrary length and described
|
|
|
|
by their relationship with zero:
|
|
|
|
- high pulses exit from zero upward before returning to it;
|
|
|
|
- low pulses exit from zero downward before returning to it;
|
|
|
|
- zero pulses run along zero.
|
|
|
|
|
|
|
|
Subclasses should implement at least @c get_next_pulse and @c reset to provide a serial feeding
|
|
|
|
of pulses and the ability to return to the start of the feed. They may also implement @c seek if
|
|
|
|
a better implementation than a linear search from the @c reset time can be implemented.
|
|
|
|
*/
|
2016-01-18 21:46:41 +00:00
|
|
|
class Tape {
|
|
|
|
public:
|
2016-01-18 23:06:09 +00:00
|
|
|
struct Pulse {
|
2016-01-18 21:46:41 +00:00
|
|
|
enum {
|
|
|
|
High, Low, Zero
|
|
|
|
} type;
|
|
|
|
Time length;
|
|
|
|
};
|
|
|
|
|
2016-01-18 23:06:09 +00:00
|
|
|
virtual Pulse get_next_pulse() = 0;
|
2016-01-18 21:46:41 +00:00
|
|
|
virtual void reset() = 0;
|
|
|
|
|
2016-07-10 12:54:39 +00:00
|
|
|
virtual void seek(Time seek_time); // TODO
|
2016-01-18 21:46:41 +00:00
|
|
|
};
|
|
|
|
|
2016-07-10 12:54:39 +00:00
|
|
|
/*!
|
|
|
|
Provides a helper for: (i) retaining a reference to a tape; and (ii) running the tape at a certain
|
|
|
|
input clock rate.
|
|
|
|
|
|
|
|
Will call @c process_input_pulse instantaneously upon reaching *the end* of a pulse. Therefore a subclass
|
|
|
|
can decode pulses into data within process_input_pulse, using the supplied pulse's @c length and @c type.
|
|
|
|
*/
|
2016-07-29 11:15:46 +00:00
|
|
|
class TapePlayer: public TimedEventLoop {
|
2016-06-26 23:03:57 +00:00
|
|
|
public:
|
|
|
|
TapePlayer(unsigned int input_clock_rate);
|
|
|
|
|
|
|
|
void set_tape(std::shared_ptr<Storage::Tape> tape);
|
|
|
|
bool has_tape();
|
|
|
|
|
2016-07-29 15:03:09 +00:00
|
|
|
void run_for_cycles(int number_of_cycles);
|
2016-06-26 23:03:57 +00:00
|
|
|
void run_for_input_pulse();
|
2016-01-18 21:46:41 +00:00
|
|
|
|
2016-06-26 23:03:57 +00:00
|
|
|
protected:
|
2016-07-29 11:15:46 +00:00
|
|
|
virtual void process_next_event();
|
2016-06-26 23:03:57 +00:00
|
|
|
virtual void process_input_pulse(Tape::Pulse pulse) = 0;
|
|
|
|
|
|
|
|
private:
|
|
|
|
inline void get_next_pulse();
|
|
|
|
|
|
|
|
std::shared_ptr<Storage::Tape> _tape;
|
2016-07-29 11:15:46 +00:00
|
|
|
Tape::Pulse _current_pulse;
|
2016-06-26 23:03:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
2016-01-18 21:46:41 +00:00
|
|
|
|
|
|
|
#endif /* Tape_hpp */
|