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:
parent
d1ef2f7c63
commit
7205c3f82b
@ -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,57 +24,147 @@ 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)
|
||||||
{
|
{
|
||||||
if(waves.size() < 2) return;
|
case FastData:
|
||||||
if(waves[0] == WaveType::Long && waves[1] != WaveType::Unrecognised)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user