1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 23:52:26 +00:00

Made an attempt to build in Oric slow/fast detection.

This commit is contained in:
Thomas Harte 2016-11-06 21:31:10 -05:00
parent d1ef2f7c63
commit 7205c3f82b
2 changed files with 131 additions and 29 deletions

View File

@ -12,7 +12,7 @@ using namespace Storage::Tape::Oric;
int Parser::get_next_byte(const std::shared_ptr<Storage::Tape::Tape> &tape, bool use_fast_encoding) int Parser::get_next_byte(const std::shared_ptr<Storage::Tape::Tape> &tape, bool use_fast_encoding)
{ {
_use_fast_encoding = use_fast_encoding; _detection_mode = use_fast_encoding ? FastData : SlowData;
_cycle_length = 0.0f; _cycle_length = 0.0f;
int result = 0; int result = 0;
@ -24,41 +24,57 @@ int Parser::get_next_byte(const std::shared_ptr<Storage::Tape::Tape> &tape, bool
result |= ((symbol == SymbolType::One) ? 1 : 0) << bit_count; result |= ((symbol == SymbolType::One) ? 1 : 0) << bit_count;
bit_count++; bit_count++;
} }
// TODO: check parity // TODO: check parity?
return tape->is_at_end() ? -1 : (result >> 1); return tape->is_at_end() ? -1 : (result >> 1);
} }
bool Parser::sync_and_get_encoding_speed(const std::shared_ptr<Storage::Tape::Tape> &tape)
{
_detection_mode = Sync;
while(!tape->is_at_end())
{
SymbolType symbol = get_next_symbol(tape);
switch(symbol)
{
case SymbolType::FoundSlow: return false;
case SymbolType::FoundFast: return true;
default: break;
}
}
return false;
}
void Parser::process_pulse(Storage::Tape::Tape::Pulse pulse) void Parser::process_pulse(Storage::Tape::Tape::Pulse pulse)
{ {
const float length_threshold = 0.0003125f; const float length_threshold = 0.0003125f;
bool wave_is_high = pulse.type == Storage::Tape::Tape::Pulse::High; bool wave_is_high = pulse.type == Storage::Tape::Tape::Pulse::High;
bool did_change = (wave_is_high != _wave_was_high && _cycle_length > 0.0f); bool did_change = (wave_is_high != _wave_was_high && _cycle_length > 0.0f);
_cycle_length += pulse.length.get_float(); _wave_was_high = wave_is_high;
if(did_change) if(did_change)
{ {
if(_cycle_length > 2.0 * length_threshold) push_wave(WaveType::Unrecognised); if(_cycle_length > 2.0 * length_threshold) push_wave(WaveType::Unrecognised);
else push_wave(_cycle_length < length_threshold ? WaveType::Short : WaveType::Long); else push_wave(_cycle_length < length_threshold ? WaveType::Short : WaveType::Long);
_cycle_length = 0.0f; _cycle_length = 0.0f;
_wave_was_high = wave_is_high;
} }
_cycle_length += pulse.length.get_float();
} }
void Parser::inspect_waves(const std::vector<WaveType> &waves) void Parser::inspect_waves(const std::vector<WaveType> &waves)
{ {
if(_use_fast_encoding) switch(_detection_mode)
{ {
case FastData:
if(waves.size() < 2) return; if(waves.size() < 2) return;
if(waves[0] == WaveType::Long && waves[1] != WaveType::Unrecognised) if(waves[0] == WaveType::Short && waves[1] != WaveType::Unrecognised)
{ {
push_symbol((waves[1] == WaveType::Long) ? SymbolType::Zero : SymbolType::One, 2); push_symbol((waves[1] == WaveType::Long) ? SymbolType::Zero : SymbolType::One, 2);
return; return;
} }
} break;
else
{ case SlowData:
if(waves.size() < 16) return;
#define CHECK_RUN(length, type, symbol) \ #define CHECK_RUN(length, type, symbol) \
if(waves.size() >= length)\ if(waves.size() >= length)\
{\ {\
@ -74,7 +90,81 @@ void Parser::inspect_waves(const std::vector<WaveType> &waves)
CHECK_RUN(8, WaveType::Long, SymbolType::Zero); CHECK_RUN(8, WaveType::Long, SymbolType::Zero);
CHECK_RUN(16, WaveType::Short, SymbolType::One); CHECK_RUN(16, WaveType::Short, SymbolType::One);
#undef CHECK_RUN #undef CHECK_RUN
if(waves.size() < 16) return; // TODO, maybe: if there are any inconsistencies in the first 8, don't return
break;
case Sync:
{
// Sync is 0x16, either encoded fast or slow; i.e. 0 0110 1000 1
// So, fast: [short, long]*2, [short, short]*2, [short, long], [short, short], [short, long]*3, [short, short] = 20
// [short, short] = 1; [short, long] = 0
// Slow: long*16, short*32, long*8, short*16, long*24, short*16 = 112
Pattern slow_sync[] =
{
{.type = WaveType::Long, 16},
{.type = WaveType::Short, 32},
{.type = WaveType::Long, 8},
{.type = WaveType::Short, 16},
{.type = WaveType::Long, 24},
{.type = WaveType::Short, 16},
{.type = WaveType::Unrecognised}
};
Pattern fast_sync[] =
{
{.type = WaveType::Short, 1},
{.type = WaveType::Long, 1},
{.type = WaveType::Short, 1},
{.type = WaveType::Long, 1},
{.type = WaveType::Short, 5},
{.type = WaveType::Long, 1},
{.type = WaveType::Short, 3},
{.type = WaveType::Long, 1},
{.type = WaveType::Short, 1},
{.type = WaveType::Long, 1},
{.type = WaveType::Short, 1},
{.type = WaveType::Long, 1},
{.type = WaveType::Short, 2},
{.type = WaveType::Unrecognised}
};
size_t slow_sync_matching_depth = pattern_matching_depth(waves, slow_sync);
size_t fast_sync_matching_depth = pattern_matching_depth(waves, fast_sync);
if(slow_sync_matching_depth == 112)
{
push_symbol(SymbolType::FoundSlow, 112);
return;
}
if(fast_sync_matching_depth == 20)
{
push_symbol(SymbolType::FoundFast, 20);
return;
}
if(slow_sync_matching_depth < waves.size() && fast_sync_matching_depth < waves.size())
remove_waves((int)std::min(slow_sync_matching_depth, fast_sync_matching_depth));
return;
}
break;
} }
remove_waves(1); remove_waves(1);
} }
size_t Parser::pattern_matching_depth(const std::vector<WaveType> &waves, Pattern *pattern)
{
size_t depth = 0;
int pattern_depth = 0;
while(depth < waves.size() && pattern->type != WaveType::Unrecognised)
{
if(waves[depth] != pattern->type) break;
pattern_depth++;
if(pattern_depth == pattern->count)
{
pattern_depth = 0;
pattern++;
}
}
return depth;
}

View File

@ -20,20 +20,32 @@ enum class WaveType {
}; };
enum class SymbolType { enum class SymbolType {
One, Zero One, Zero, FoundFast, FoundSlow
}; };
class Parser: public Storage::Tape::Parser<WaveType, SymbolType> { class Parser: public Storage::Tape::Parser<WaveType, SymbolType> {
public: public:
int get_next_byte(const std::shared_ptr<Storage::Tape::Tape> &tape, bool use_fast_encoding); int get_next_byte(const std::shared_ptr<Storage::Tape::Tape> &tape, bool use_fast_encoding);
bool sync_and_get_encoding_speed(const std::shared_ptr<Storage::Tape::Tape> &tape);
private: private:
void process_pulse(Storage::Tape::Tape::Pulse pulse); void process_pulse(Storage::Tape::Tape::Pulse pulse);
void inspect_waves(const std::vector<WaveType> &waves); void inspect_waves(const std::vector<WaveType> &waves);
bool _use_fast_encoding; enum DetectionMode {
FastData,
SlowData,
Sync
} _detection_mode;
bool _wave_was_high; bool _wave_was_high;
float _cycle_length; float _cycle_length;
struct Pattern
{
WaveType type;
int count;
};
size_t pattern_matching_depth(const std::vector<WaveType> &waves, Pattern *pattern);
}; };