mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Adds bit-level Spectrum-style tape parsing.
More to do, obviously.
This commit is contained in:
parent
8a1c6978de
commit
d93d380c88
@ -243,6 +243,8 @@
|
||||
4B59199C1DAC6C46005BB85C /* OricTAP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B59199A1DAC6C46005BB85C /* OricTAP.cpp */; };
|
||||
4B595FAD2086DFBA0083CAA8 /* AudioToggle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B595FAC2086DFBA0083CAA8 /* AudioToggle.cpp */; };
|
||||
4B595FAE2086DFBA0083CAA8 /* AudioToggle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B595FAC2086DFBA0083CAA8 /* AudioToggle.cpp */; };
|
||||
4B5D5C9725F56FC7001B4623 /* Spectrum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5D5C9525F56FC7001B4623 /* Spectrum.cpp */; };
|
||||
4B5D5C9825F56FC7001B4623 /* Spectrum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5D5C9525F56FC7001B4623 /* Spectrum.cpp */; };
|
||||
4B5FADBA1DE3151600AEC565 /* FileHolder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5FADB81DE3151600AEC565 /* FileHolder.cpp */; };
|
||||
4B5FADC01DE3BF2B00AEC565 /* Microdisc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B5FADBE1DE3BF2B00AEC565 /* Microdisc.cpp */; };
|
||||
4B622AE5222E0AD5008B59F2 /* DisplayMetrics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B622AE3222E0AD5008B59F2 /* DisplayMetrics.cpp */; };
|
||||
@ -1252,6 +1254,8 @@
|
||||
4B59199B1DAC6C46005BB85C /* OricTAP.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = OricTAP.hpp; sourceTree = "<group>"; };
|
||||
4B595FAB2086DFBA0083CAA8 /* AudioToggle.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = AudioToggle.hpp; sourceTree = "<group>"; };
|
||||
4B595FAC2086DFBA0083CAA8 /* AudioToggle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioToggle.cpp; sourceTree = "<group>"; };
|
||||
4B5D5C9525F56FC7001B4623 /* Spectrum.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Spectrum.cpp; path = Parsers/Spectrum.cpp; sourceTree = "<group>"; };
|
||||
4B5D5C9625F56FC7001B4623 /* Spectrum.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = Spectrum.hpp; path = Parsers/Spectrum.hpp; sourceTree = "<group>"; };
|
||||
4B5FADB81DE3151600AEC565 /* FileHolder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileHolder.cpp; sourceTree = "<group>"; };
|
||||
4B5FADB91DE3151600AEC565 /* FileHolder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FileHolder.hpp; sourceTree = "<group>"; };
|
||||
4B5FADBE1DE3BF2B00AEC565 /* Microdisc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Microdisc.cpp; path = Oric/Microdisc.cpp; sourceTree = "<group>"; };
|
||||
@ -3021,11 +3025,13 @@
|
||||
4B8805F21DCFD22A003085B1 /* Commodore.cpp */,
|
||||
4B0E61051FF34737002A9DBD /* MSX.cpp */,
|
||||
4B8805F91DCFF807003085B1 /* Oric.cpp */,
|
||||
4B5D5C9525F56FC7001B4623 /* Spectrum.cpp */,
|
||||
4BBFBB6A1EE8401E00C01E7A /* ZX8081.cpp */,
|
||||
4B8805EF1DCFC99C003085B1 /* Acorn.hpp */,
|
||||
4B8805F31DCFD22A003085B1 /* Commodore.hpp */,
|
||||
4B0E61061FF34737002A9DBD /* MSX.hpp */,
|
||||
4B8805FA1DCFF807003085B1 /* Oric.hpp */,
|
||||
4B5D5C9625F56FC7001B4623 /* Spectrum.hpp */,
|
||||
4B4518A71F76004200926311 /* TapeParser.hpp */,
|
||||
4BBFBB6B1EE8401E00C01E7A /* ZX8081.hpp */,
|
||||
);
|
||||
@ -5050,6 +5056,7 @@
|
||||
4B2E86BF25D74F160024F1E9 /* Mouse.cpp in Sources */,
|
||||
4B6ED2F1208E2F8A0047B343 /* WOZ.cpp in Sources */,
|
||||
4B055AD81FAE9B180060FFFF /* Video.cpp in Sources */,
|
||||
4B5D5C9825F56FC7001B4623 /* Spectrum.cpp in Sources */,
|
||||
4B2E86D025D8D8C70024F1E9 /* Keyboard.cpp in Sources */,
|
||||
4B89452F201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
4B894531201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
@ -5256,6 +5263,7 @@
|
||||
4B894530201967B4007DE474 /* StaticAnalyser.cpp in Sources */,
|
||||
4B4518A31F75FD1C00926311 /* HFE.cpp in Sources */,
|
||||
4B1B88BB202E2EC100B67DFF /* MultiKeyboardMachine.cpp in Sources */,
|
||||
4B5D5C9725F56FC7001B4623 /* Spectrum.cpp in Sources */,
|
||||
4B4518A11F75FD1C00926311 /* D64.cpp in Sources */,
|
||||
4B1558C01F844ECD006E9A97 /* BitReverse.cpp in Sources */,
|
||||
4BCE0052227CE8CA000CA200 /* DiskIICard.cpp in Sources */,
|
||||
|
98
Storage/Tape/Parsers/Spectrum.cpp
Normal file
98
Storage/Tape/Parsers/Spectrum.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
//
|
||||
// Spectrum.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 07/03/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Spectrum.hpp"
|
||||
|
||||
//
|
||||
// Source used for the logic below was primarily https://sinclair.wiki.zxnet.co.uk/wiki/Spectrum_tape_interface
|
||||
//
|
||||
|
||||
using namespace Storage::Tape::ZXSpectrum;
|
||||
|
||||
void Parser::process_pulse(const Storage::Tape::Tape::Pulse &pulse) {
|
||||
if(pulse.type == Storage::Tape::Tape::Pulse::Type::Zero) {
|
||||
push_wave(WaveType::Gap);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only pulse duration matters; the ZX Spectrum et al do not rely on polarity.
|
||||
const float t_states = pulse.length.get<float>() * 3'500'000.0f;
|
||||
|
||||
// Too long => gap.
|
||||
if(t_states > 2400.0f) {
|
||||
push_wave(WaveType::Gap);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1940–2400 t-states => pilot.
|
||||
if(t_states > 1940.0f) {
|
||||
push_wave(WaveType::Pilot);
|
||||
return;
|
||||
}
|
||||
|
||||
// 1282–1940 t-states => one.
|
||||
if(t_states > 1282.0f) {
|
||||
push_wave(WaveType::One);
|
||||
return;
|
||||
}
|
||||
|
||||
// 895–1282 => zero.
|
||||
if(t_states > 795.0f) {
|
||||
push_wave(WaveType::Zero);
|
||||
return;
|
||||
}
|
||||
|
||||
// 701–895 => sync 2.
|
||||
if(t_states > 701.0f) {
|
||||
push_wave(WaveType::Sync2);
|
||||
return;
|
||||
}
|
||||
|
||||
// Anything remaining above 600 => sync 1.
|
||||
if(t_states > 600.0f) {
|
||||
push_wave(WaveType::Sync1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Whatever this was, it's too short. Call it a gap.
|
||||
push_wave(WaveType::Gap);
|
||||
}
|
||||
|
||||
void Parser::inspect_waves(const std::vector<Storage::Tape::ZXSpectrum::WaveType> &waves) {
|
||||
switch(waves[0]) {
|
||||
// Gap and Pilot map directly.
|
||||
case WaveType::Gap: push_symbol(SymbolType::Gap, 1); break;
|
||||
case WaveType::Pilot: push_symbol(SymbolType::Pilot, 1); break;
|
||||
|
||||
// Encountering a sync 2 on its own is unexpected.
|
||||
case WaveType::Sync2:
|
||||
push_symbol(SymbolType::Gap, 1);
|
||||
break;
|
||||
|
||||
// A sync 1 should be followed by a sync 2 in order to make a sync.
|
||||
case WaveType::Sync1:
|
||||
if(waves.size() < 2) return;
|
||||
if(waves[1] == WaveType::Sync2) {
|
||||
push_symbol(SymbolType::Sync, 2);
|
||||
} else {
|
||||
push_symbol(SymbolType::Gap, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
// Both one and zero waves should come in pairs.
|
||||
case WaveType::One:
|
||||
case WaveType::Zero:
|
||||
if(waves.size() < 2) return;
|
||||
if(waves[1] == waves[0]) {
|
||||
push_symbol(waves[0] == WaveType::One ? SymbolType::One : SymbolType::Zero, 2);
|
||||
} else {
|
||||
push_symbol(SymbolType::Gap, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
48
Storage/Tape/Parsers/Spectrum.hpp
Normal file
48
Storage/Tape/Parsers/Spectrum.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Spectrum.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 07/03/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Storage_Tape_Parsers_Spectrum_hpp
|
||||
#define Storage_Tape_Parsers_Spectrum_hpp
|
||||
|
||||
#include "TapeParser.hpp"
|
||||
|
||||
namespace Storage {
|
||||
namespace Tape {
|
||||
namespace ZXSpectrum {
|
||||
|
||||
enum class WaveType {
|
||||
// All references to 't-states' below are cycles relative to the
|
||||
// ZX Spectrum's 3.5Mhz processor.
|
||||
|
||||
Pilot, // Nominally 2168 t-states.
|
||||
Sync1, // 667 t-states.
|
||||
Sync2, // 735 t-states.
|
||||
Zero, // 855 t-states.
|
||||
One, // 1710 t-states.
|
||||
Gap,
|
||||
};
|
||||
|
||||
enum class SymbolType {
|
||||
Pilot,
|
||||
Sync,
|
||||
Zero,
|
||||
One,
|
||||
Gap,
|
||||
};
|
||||
|
||||
class Parser: public Storage::Tape::PulseClassificationParser<WaveType, SymbolType> {
|
||||
private:
|
||||
void process_pulse(const Storage::Tape::Tape::Pulse &pulse) override;
|
||||
void inspect_waves(const std::vector<WaveType> &waves) override;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Spectrum_hpp */
|
Loading…
Reference in New Issue
Block a user