2016-01-18 21:46:41 +00:00
|
|
|
//
|
|
|
|
// Tape.cpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 18/01/2016.
|
|
|
|
// Copyright © 2016 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "Tape.hpp"
|
2016-07-29 09:19:01 +00:00
|
|
|
#include "../../NumberTheory/Factors.hpp"
|
2016-01-18 21:46:41 +00:00
|
|
|
|
2016-08-27 21:18:12 +00:00
|
|
|
using namespace Storage::Tape;
|
2016-01-18 21:46:41 +00:00
|
|
|
|
2017-11-12 20:59:11 +00:00
|
|
|
// MARK: - Lifecycle
|
2016-06-26 23:03:57 +00:00
|
|
|
|
|
|
|
TapePlayer::TapePlayer(unsigned int input_clock_rate) :
|
2016-07-29 11:15:46 +00:00
|
|
|
TimedEventLoop(input_clock_rate)
|
2016-06-26 23:03:57 +00:00
|
|
|
{}
|
|
|
|
|
2017-11-12 20:59:11 +00:00
|
|
|
// MARK: - Seeking
|
2016-09-11 21:09:00 +00:00
|
|
|
|
2017-06-11 21:29:22 +00:00
|
|
|
void Storage::Tape::Tape::seek(Time &seek_time) {
|
2017-07-21 22:55:03 +00:00
|
|
|
Time next_time(0);
|
|
|
|
reset();
|
|
|
|
while(next_time <= seek_time) {
|
|
|
|
get_next_pulse();
|
|
|
|
next_time += pulse_.length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Storage::Time Tape::get_current_time() {
|
|
|
|
Time time(0);
|
|
|
|
uint64_t steps = get_offset();
|
|
|
|
reset();
|
|
|
|
while(steps--) {
|
|
|
|
get_next_pulse();
|
|
|
|
time += pulse_.length;
|
|
|
|
}
|
|
|
|
return time;
|
2016-09-11 21:09:00 +00:00
|
|
|
}
|
|
|
|
|
2017-06-11 21:29:22 +00:00
|
|
|
void Storage::Tape::Tape::reset() {
|
2017-07-21 22:55:03 +00:00
|
|
|
offset_ = 0;
|
2016-09-11 21:09:00 +00:00
|
|
|
virtual_reset();
|
|
|
|
}
|
|
|
|
|
2017-06-11 21:29:22 +00:00
|
|
|
Tape::Pulse Tape::get_next_pulse() {
|
2017-07-21 22:55:03 +00:00
|
|
|
pulse_ = virtual_get_next_pulse();
|
|
|
|
offset_++;
|
|
|
|
return pulse_;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t Tape::get_offset() {
|
|
|
|
return offset_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Tape::set_offset(uint64_t offset) {
|
2017-07-22 00:43:20 +00:00
|
|
|
if(offset == offset_) return;
|
|
|
|
if(offset < offset_) {
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
offset -= offset_;
|
2017-07-21 22:55:03 +00:00
|
|
|
while(offset--) get_next_pulse();
|
2016-09-11 21:09:00 +00:00
|
|
|
}
|
|
|
|
|
2017-11-12 20:59:11 +00:00
|
|
|
// MARK: - Player
|
2016-09-11 21:09:00 +00:00
|
|
|
|
2017-08-20 16:18:36 +00:00
|
|
|
bool TapePlayer::is_sleeping() {
|
|
|
|
return !tape_ || tape_->is_at_end();
|
|
|
|
}
|
|
|
|
|
2017-06-11 21:29:22 +00:00
|
|
|
void TapePlayer::set_tape(std::shared_ptr<Storage::Tape::Tape> tape) {
|
2016-12-03 17:05:19 +00:00
|
|
|
tape_ = tape;
|
2016-07-29 11:15:46 +00:00
|
|
|
reset_timer();
|
2016-06-26 23:03:57 +00:00
|
|
|
get_next_pulse();
|
2017-08-20 16:18:36 +00:00
|
|
|
update_sleep_observer();
|
2016-06-26 23:03:57 +00:00
|
|
|
}
|
|
|
|
|
2017-06-11 21:29:22 +00:00
|
|
|
std::shared_ptr<Storage::Tape::Tape> TapePlayer::get_tape() {
|
2016-12-03 17:05:19 +00:00
|
|
|
return tape_;
|
2016-09-13 02:22:23 +00:00
|
|
|
}
|
|
|
|
|
2017-06-11 21:29:22 +00:00
|
|
|
bool TapePlayer::has_tape() {
|
2016-12-03 17:05:19 +00:00
|
|
|
return (bool)tape_;
|
2016-06-26 23:03:57 +00:00
|
|
|
}
|
|
|
|
|
2017-06-11 21:29:22 +00:00
|
|
|
void TapePlayer::get_next_pulse() {
|
2016-07-29 09:19:01 +00:00
|
|
|
// get the new pulse
|
2017-08-20 16:18:36 +00:00
|
|
|
if(tape_) {
|
2016-12-03 17:05:19 +00:00
|
|
|
current_pulse_ = tape_->get_next_pulse();
|
2017-08-20 16:18:36 +00:00
|
|
|
if(tape_->is_at_end()) update_sleep_observer();
|
2017-12-23 23:42:04 +00:00
|
|
|
} else {
|
2016-12-03 17:05:19 +00:00
|
|
|
current_pulse_.length.length = 1;
|
|
|
|
current_pulse_.length.clock_rate = 1;
|
|
|
|
current_pulse_.type = Tape::Pulse::Zero;
|
2016-06-26 23:03:57 +00:00
|
|
|
}
|
2016-07-29 09:19:01 +00:00
|
|
|
|
2016-12-03 17:05:19 +00:00
|
|
|
set_next_event_time_interval(current_pulse_.length);
|
2016-06-26 23:03:57 +00:00
|
|
|
}
|
|
|
|
|
2017-07-28 02:05:29 +00:00
|
|
|
void TapePlayer::run_for(const Cycles cycles) {
|
2017-06-11 21:29:22 +00:00
|
|
|
if(has_tape()) {
|
2017-07-25 01:19:05 +00:00
|
|
|
TimedEventLoop::run_for(cycles);
|
2016-06-26 23:03:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-11 21:29:22 +00:00
|
|
|
void TapePlayer::run_for_input_pulse() {
|
2016-07-29 11:15:46 +00:00
|
|
|
jump_to_next_event();
|
|
|
|
}
|
|
|
|
|
2017-06-11 21:29:22 +00:00
|
|
|
void TapePlayer::process_next_event() {
|
2016-12-03 17:05:19 +00:00
|
|
|
process_input_pulse(current_pulse_);
|
2016-06-26 23:03:57 +00:00
|
|
|
get_next_pulse();
|
|
|
|
}
|
2016-10-20 23:33:25 +00:00
|
|
|
|
2017-11-12 20:59:11 +00:00
|
|
|
// MARK: - Binary Player
|
2016-10-20 23:33:25 +00:00
|
|
|
|
|
|
|
BinaryTapePlayer::BinaryTapePlayer(unsigned int input_clock_rate) :
|
2017-11-11 03:57:03 +00:00
|
|
|
TapePlayer(input_clock_rate)
|
2016-10-20 23:33:25 +00:00
|
|
|
{}
|
|
|
|
|
2017-08-20 16:18:36 +00:00
|
|
|
bool BinaryTapePlayer::is_sleeping() {
|
|
|
|
return !motor_is_running_ || TapePlayer::is_sleeping();
|
|
|
|
}
|
|
|
|
|
2017-06-11 21:29:22 +00:00
|
|
|
void BinaryTapePlayer::set_motor_control(bool enabled) {
|
2017-08-20 17:18:46 +00:00
|
|
|
if(motor_is_running_ != enabled) {
|
|
|
|
motor_is_running_ = enabled;
|
|
|
|
update_sleep_observer();
|
|
|
|
}
|
2016-10-20 23:33:25 +00:00
|
|
|
}
|
|
|
|
|
2017-12-27 03:13:28 +00:00
|
|
|
bool BinaryTapePlayer::get_motor_control() const {
|
|
|
|
return motor_is_running_;
|
|
|
|
}
|
|
|
|
|
2017-06-11 21:29:22 +00:00
|
|
|
void BinaryTapePlayer::set_tape_output(bool set) {
|
2016-10-20 23:33:25 +00:00
|
|
|
// TODO
|
|
|
|
}
|
|
|
|
|
2017-12-27 03:13:28 +00:00
|
|
|
bool BinaryTapePlayer::get_input() const {
|
2017-07-19 02:49:11 +00:00
|
|
|
return motor_is_running_ && input_level_;
|
2016-10-20 23:33:25 +00:00
|
|
|
}
|
|
|
|
|
2017-07-28 02:05:29 +00:00
|
|
|
void BinaryTapePlayer::run_for(const Cycles cycles) {
|
2017-07-25 01:19:05 +00:00
|
|
|
if(motor_is_running_) TapePlayer::run_for(cycles);
|
2016-10-20 23:33:25 +00:00
|
|
|
}
|
|
|
|
|
2017-06-11 21:29:22 +00:00
|
|
|
void BinaryTapePlayer::set_delegate(Delegate *delegate) {
|
2016-12-03 17:05:19 +00:00
|
|
|
delegate_ = delegate;
|
2016-10-20 23:33:25 +00:00
|
|
|
}
|
|
|
|
|
2017-07-16 23:49:31 +00:00
|
|
|
void BinaryTapePlayer::process_input_pulse(const Storage::Tape::Tape::Pulse &pulse) {
|
2017-06-22 02:13:24 +00:00
|
|
|
bool new_input_level = pulse.type == Tape::Pulse::High;
|
2017-06-11 21:29:22 +00:00
|
|
|
if(input_level_ != new_input_level) {
|
2016-12-03 17:05:19 +00:00
|
|
|
input_level_ = new_input_level;
|
|
|
|
if(delegate_) delegate_->tape_did_change_input(this);
|
2016-10-20 23:33:25 +00:00
|
|
|
}
|
|
|
|
}
|