From 7205c3f82b29163fc198acfcd97804379eff78d1 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 6 Nov 2016 21:31:10 -0500 Subject: [PATCH] Made an attempt to build in Oric slow/fast detection. --- Storage/Tape/Parsers/Oric.cpp | 144 +++++++++++++++++++++++++++------- Storage/Tape/Parsers/Oric.hpp | 16 +++- 2 files changed, 131 insertions(+), 29 deletions(-) diff --git a/Storage/Tape/Parsers/Oric.cpp b/Storage/Tape/Parsers/Oric.cpp index 722d7b175..e14069dd9 100644 --- a/Storage/Tape/Parsers/Oric.cpp +++ b/Storage/Tape/Parsers/Oric.cpp @@ -12,7 +12,7 @@ using namespace Storage::Tape::Oric; int Parser::get_next_byte(const std::shared_ptr &tape, bool use_fast_encoding) { - _use_fast_encoding = use_fast_encoding; + _detection_mode = use_fast_encoding ? FastData : SlowData; _cycle_length = 0.0f; int result = 0; @@ -24,57 +24,147 @@ int Parser::get_next_byte(const std::shared_ptr &tape, bool result |= ((symbol == SymbolType::One) ? 1 : 0) << bit_count; bit_count++; } - // TODO: check parity + // TODO: check parity? return tape->is_at_end() ? -1 : (result >> 1); } +bool Parser::sync_and_get_encoding_speed(const std::shared_ptr &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) { const float length_threshold = 0.0003125f; bool wave_is_high = pulse.type == Storage::Tape::Tape::Pulse::High; 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(_cycle_length > 2.0 * length_threshold) push_wave(WaveType::Unrecognised); else push_wave(_cycle_length < length_threshold ? WaveType::Short : WaveType::Long); _cycle_length = 0.0f; - _wave_was_high = wave_is_high; } + _cycle_length += pulse.length.get_float(); } void Parser::inspect_waves(const std::vector &waves) { - if(_use_fast_encoding) + switch(_detection_mode) { - if(waves.size() < 2) return; - if(waves[0] == WaveType::Long && waves[1] != WaveType::Unrecognised) + case FastData: + if(waves.size() < 2) return; + if(waves[0] == WaveType::Short && waves[1] != WaveType::Unrecognised) + { + push_symbol((waves[1] == WaveType::Long) ? SymbolType::Zero : SymbolType::One, 2); + return; + } + break; + + case SlowData: +#define CHECK_RUN(length, type, symbol) \ + if(waves.size() >= length)\ + {\ + size_t c;\ + for(c = 0; c < length; c++) if(waves[c] != type) break;\ + if(c == length)\ + {\ + push_symbol(symbol, 8);\ + return;\ + }\ + } + + CHECK_RUN(8, WaveType::Long, SymbolType::Zero); + CHECK_RUN(16, WaveType::Short, SymbolType::One); +#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: { - push_symbol((waves[1] == WaveType::Long) ? SymbolType::Zero : SymbolType::One, 2); + // 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; } - } - else - { - if(waves.size() < 16) return; -#define CHECK_RUN(length, type, symbol) \ - if(waves.size() >= length)\ - {\ - size_t c;\ - for(c = 0; c < length; c++) if(waves[c] != type) break;\ - if(c == length)\ - {\ - push_symbol(symbol, 8);\ - return;\ - }\ - } - - CHECK_RUN(8, WaveType::Long, SymbolType::Zero); - CHECK_RUN(16, WaveType::Short, SymbolType::One); -#undef CHECK_RUN + break; } remove_waves(1); } + +size_t Parser::pattern_matching_depth(const std::vector &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; +} diff --git a/Storage/Tape/Parsers/Oric.hpp b/Storage/Tape/Parsers/Oric.hpp index 7dae3ca67..cb5ffe96b 100644 --- a/Storage/Tape/Parsers/Oric.hpp +++ b/Storage/Tape/Parsers/Oric.hpp @@ -20,20 +20,32 @@ enum class WaveType { }; enum class SymbolType { - One, Zero + One, Zero, FoundFast, FoundSlow }; class Parser: public Storage::Tape::Parser { public: int get_next_byte(const std::shared_ptr &tape, bool use_fast_encoding); + bool sync_and_get_encoding_speed(const std::shared_ptr &tape); private: void process_pulse(Storage::Tape::Tape::Pulse pulse); void inspect_waves(const std::vector &waves); - bool _use_fast_encoding; + enum DetectionMode { + FastData, + SlowData, + Sync + } _detection_mode; bool _wave_was_high; float _cycle_length; + + struct Pattern + { + WaveType type; + int count; + }; + size_t pattern_matching_depth(const std::vector &waves, Pattern *pattern); };