2016-06-19 13:10:52 -04:00
|
|
|
//
|
|
|
|
// Typer.cpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 19/06/2016.
|
|
|
|
// Copyright © 2016 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "Typer.hpp"
|
2017-11-10 20:37:18 -05:00
|
|
|
|
2017-12-29 15:26:03 -05:00
|
|
|
#include <sstream>
|
2016-06-19 13:10:52 -04:00
|
|
|
|
|
|
|
using namespace Utility;
|
|
|
|
|
2017-12-29 15:26:03 -05:00
|
|
|
Typer::Typer(const std::string &string, HalfCycles delay, HalfCycles frequency, std::unique_ptr<CharacterMapper> character_mapper, Delegate *delegate) :
|
2017-08-03 11:42:31 -04:00
|
|
|
frequency_(frequency),
|
2017-11-10 22:35:05 -05:00
|
|
|
counter_(-delay),
|
2017-08-03 11:42:31 -04:00
|
|
|
delegate_(delegate),
|
|
|
|
character_mapper_(std::move(character_mapper)) {
|
2017-12-29 15:26:03 -05:00
|
|
|
std::ostringstream string_stream;
|
|
|
|
string_stream << Typer::BeginString << string << Typer::EndString;
|
|
|
|
string_ = string_stream.str();
|
2016-11-05 14:47:09 -04:00
|
|
|
}
|
2016-06-19 13:10:52 -04:00
|
|
|
|
2017-07-27 22:05:29 -04:00
|
|
|
void Typer::run_for(const HalfCycles duration) {
|
2017-12-29 15:26:03 -05:00
|
|
|
if(string_pointer_ < string_.size()) {
|
2017-03-26 14:34:47 -04:00
|
|
|
if(counter_ < 0 && counter_ + duration >= 0) {
|
|
|
|
if(!type_next_character()) {
|
2016-12-03 10:55:50 -05:00
|
|
|
delegate_->typer_reset(this);
|
2016-11-05 14:47:09 -04:00
|
|
|
}
|
2016-06-19 13:10:52 -04:00
|
|
|
}
|
|
|
|
|
2016-12-03 10:55:50 -05:00
|
|
|
counter_ += duration;
|
2017-12-29 15:26:03 -05:00
|
|
|
while(string_pointer_ < string_.size() && counter_ > frequency_) {
|
2016-12-03 10:55:50 -05:00
|
|
|
counter_ -= frequency_;
|
2017-03-26 14:34:47 -04:00
|
|
|
if(!type_next_character()) {
|
2016-12-03 10:55:50 -05:00
|
|
|
delegate_->typer_reset(this);
|
2016-11-05 14:47:09 -04:00
|
|
|
}
|
2016-06-19 13:10:52 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-03 11:42:31 -04:00
|
|
|
bool Typer::try_type_next_character() {
|
|
|
|
uint16_t *sequence = character_mapper_->sequence_for_character(string_[string_pointer_]);
|
|
|
|
|
2017-10-12 22:25:02 -04:00
|
|
|
if(!sequence || sequence[0] == KeyboardMachine::Machine::KeyNotMapped) {
|
2017-08-03 11:42:31 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!phase_) delegate_->clear_all_keys();
|
|
|
|
else {
|
|
|
|
delegate_->set_key_state(sequence[phase_ - 1], true);
|
2017-10-12 22:25:02 -04:00
|
|
|
return sequence[phase_] != KeyboardMachine::Machine::KeyEndSequence;
|
2017-08-03 11:42:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-03-26 14:34:47 -04:00
|
|
|
bool Typer::type_next_character() {
|
2017-12-29 15:26:03 -05:00
|
|
|
if(string_pointer_ == string_.size()) return false;
|
2016-08-06 14:33:24 -04:00
|
|
|
|
2017-08-03 11:42:31 -04:00
|
|
|
if(!try_type_next_character()) {
|
2016-12-03 10:55:50 -05:00
|
|
|
phase_ = 0;
|
|
|
|
string_pointer_++;
|
2017-12-30 13:46:30 -05:00
|
|
|
if(string_pointer_ == string_.size()) return false;
|
2017-03-26 14:34:47 -04:00
|
|
|
} else {
|
2016-12-03 10:55:50 -05:00
|
|
|
phase_++;
|
2016-06-19 13:46:53 -04:00
|
|
|
}
|
2016-08-06 14:33:24 -04:00
|
|
|
|
|
|
|
return true;
|
2016-06-19 13:46:53 -04:00
|
|
|
}
|
|
|
|
|
2017-11-12 15:59:11 -05:00
|
|
|
// MARK: - Character mapper
|
2017-07-21 21:18:51 -04:00
|
|
|
|
2017-11-11 15:28:40 -05:00
|
|
|
uint16_t *CharacterMapper::table_lookup_sequence_for_character(KeySequence *sequences, std::size_t length, char character) {
|
|
|
|
std::size_t ucharacter = static_cast<std::size_t>((unsigned char)character);
|
2017-07-21 21:18:51 -04:00
|
|
|
if(ucharacter > (length / sizeof(KeySequence))) return nullptr;
|
2017-10-12 22:25:02 -04:00
|
|
|
if(sequences[ucharacter][0] == KeyboardMachine::Machine::KeyNotMapped) return nullptr;
|
2017-07-21 21:18:51 -04:00
|
|
|
return sequences[ucharacter];
|
|
|
|
}
|