1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-22 12:33:29 +00:00

Calling it 'number theory' probably isn't accurate but extracted the CRC stuff and started using it for [M]FM encoding.

This commit is contained in:
Thomas Harte 2016-09-18 18:33:26 -04:00
parent 55a7418cbf
commit 180c3df2d4
4 changed files with 111 additions and 26 deletions

11
NumberTheory/CRC.cpp Normal file
View File

@ -0,0 +1,11 @@
//
// CRC.cpp
// Clock Signal
//
// Created by Thomas Harte on 18/09/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
#include "CRC.hpp"
using namespace NumberTheory;

40
NumberTheory/CRC.hpp Normal file
View File

@ -0,0 +1,40 @@
//
// CRC.hpp
// Clock Signal
//
// Created by Thomas Harte on 18/09/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
#ifndef CRC_hpp
#define CRC_hpp
#include <cstdint>
namespace NumberTheory {
class CRC16 {
public:
CRC16(uint16_t polynomial, uint16_t reset_value) :
reset_value_(reset_value), value_(reset_value), polynomial_(polynomial) {}
inline void reset() { value_ = reset_value_; }
inline void add(uint8_t value) {
// TODO: go table based
value_ ^= (uint16_t)value << 8;
for(int c = 0; c < 8; c++)
{
uint16_t exclusive_or = (value_&0x8000) ? polynomial_ : 0x0000;
value_ = (uint16_t)(value_ << 1) ^ exclusive_or;
}
}
inline uint16_t get_value() { return value_; }
private:
uint16_t reset_value_, polynomial_;
uint16_t value_;
};
}
#endif /* CRC_hpp */

View File

@ -356,6 +356,7 @@
4BEF6AAC1D35D1C400E73575 /* DPLLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEF6AAB1D35D1C400E73575 /* DPLLTests.swift */; };
4BF1354C1D6D2C300054B2EA /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1354A1D6D2C300054B2EA /* StaticAnalyser.cpp */; };
4BF8295D1D8F048B001BAE39 /* MFM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8295B1D8F048B001BAE39 /* MFM.cpp */; };
4BF829601D8F3C87001BAE39 /* CRC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8295E1D8F3C87001BAE39 /* CRC.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -808,6 +809,8 @@
4BF1354B1D6D2C300054B2EA /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = StaticAnalyser.hpp; path = ../../StaticAnalyser/StaticAnalyser.hpp; sourceTree = "<group>"; };
4BF8295B1D8F048B001BAE39 /* MFM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MFM.cpp; path = Encodings/MFM.cpp; sourceTree = "<group>"; };
4BF8295C1D8F048B001BAE39 /* MFM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = MFM.hpp; path = Encodings/MFM.hpp; sourceTree = "<group>"; };
4BF8295E1D8F3C87001BAE39 /* CRC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CRC.cpp; path = ../../NumberTheory/CRC.cpp; sourceTree = "<group>"; };
4BF8295F1D8F3C87001BAE39 /* CRC.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CRC.hpp; path = ../../NumberTheory/CRC.hpp; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -1394,6 +1397,8 @@
isa = PBXGroup;
children = (
4BB697C61D4B558F00248BDF /* Factors.hpp */,
4BF8295E1D8F3C87001BAE39 /* CRC.cpp */,
4BF8295F1D8F3C87001BAE39 /* CRC.hpp */,
);
name = NumberTheory;
sourceTree = "<group>";
@ -2079,6 +2084,7 @@
4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */,
4B643F3F1D77B88000D431D6 /* DocumentController.swift in Sources */,
4BA799951D8B656E0045123D /* StaticAnalyser.cpp in Sources */,
4BF829601D8F3C87001BAE39 /* CRC.cpp in Sources */,
4B55CE591C3B7D360093A61B /* ElectronDocument.swift in Sources */,
4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */,
4BC3B74F1CD194CC00F86E85 /* Shader.cpp in Sources */,

View File

@ -9,6 +9,7 @@
#include "MFM.hpp"
#import "../PCMTrack.hpp"
#import "../../../NumberTheory/CRC.hpp"
using namespace Storage::Encodings::MFM;
@ -106,6 +107,19 @@ template <class T> class FMShifter: public Shifter<T> {
}
};
static uint8_t logarithmic_size_for_size(size_t size)
{
switch(size)
{
default: return 0;
case 256: return 1;
case 512: return 2;
case 1024: return 3;
case 2048: return 4;
case 4196: return 5;
}
}
template<class T> std::shared_ptr<Storage::Disk::Track>
GetTrackWithSectors(
const std::vector<Sector> &sectors,
@ -115,6 +129,7 @@ template<class T> std::shared_ptr<Storage::Disk::Track>
size_t inter_sector_gap)
{
T shifter;
NumberTheory::CRC16 crc_generator(0x1021, 0xffff);
// output the index mark
shifter.add_index_address_mark();
@ -125,30 +140,46 @@ template<class T> std::shared_ptr<Storage::Disk::Track>
// add sectors
for(const Sector &sector : sectors)
{
// gap
for(int c = 0; c < pre_address_mark_bytes; c++) shifter.add_byte(0x00);
// sector header
shifter.add_ID_address_mark();
shifter.add_byte(sector.track);
shifter.add_byte(sector.side);
shifter.add_byte(sector.sector);
switch(sector.data.size())
{
default: shifter.add_byte(0); break;
case 256: shifter.add_byte(1); break;
case 512: shifter.add_byte(2); break;
case 1024: shifter.add_byte(3); break;
case 2048: shifter.add_byte(4); break;
case 4196: shifter.add_byte(5); break;
}
// TODO: CRC of bytes since the track number
uint8_t size = logarithmic_size_for_size(sector.data.size());
shifter.add_byte(size);
// header CRC
crc_generator.reset();
crc_generator.add(sector.track);
crc_generator.add(sector.side);
crc_generator.add(sector.sector);
crc_generator.add(size);
uint16_t crc_value = crc_generator.get_value();
shifter.add_byte(crc_value & 0xff);
shifter.add_byte(crc_value >> 8);
// gap
for(int c = 0; c < post_address_mark_bytes; c++) shifter.add_byte(0x4e);
for(int c = 0; c < pre_data_mark_bytes; c++) shifter.add_byte(0x00);
// data
shifter.add_data_address_mark();
for(size_t c = 0; c < sector.data.size(); c++) shifter.add_byte(sector.data[c]);
// TODO: CRC of data
crc_generator.reset();
for(size_t c = 0; c < sector.data.size(); c++)
{
shifter.add_byte(sector.data[c]);
crc_generator.add(sector.data[c]);
}
// data CRC
crc_value = crc_generator.get_value();
shifter.add_byte(crc_value & 0xff);
shifter.add_byte(crc_value >> 8);
// gap
for(int c = 0; c < post_data_bytes; c++) shifter.add_byte(0x00);
for(int c = 0; c < inter_sector_gap; c++) shifter.add_byte(0x4e);
}
@ -159,17 +190,19 @@ template<class T> std::shared_ptr<Storage::Disk::Track>
return std::shared_ptr<Storage::Disk::Track>(new Storage::Disk::PCMTrack(std::move(segment)));
}
struct VectorReceiver {
void output_short(uint16_t value) {
data.push_back(value & 0xff);
data.push_back(value >> 8);
}
std::vector<uint8_t> data;
};
std::shared_ptr<Storage::Disk::Track> Storage::Encodings::MFM::GetFMTrackWithSectors(const std::vector<Sector> &sectors)
{
struct VectorShifter: public FMShifter<VectorShifter> {
void output_short(uint16_t value) {
data.push_back(value & 0xff);
data.push_back(value >> 8);
}
std::vector<uint8_t> data;
struct VectorShifter: public FMShifter<VectorShifter>, VectorReceiver {
using VectorReceiver::output_short;
};
return GetTrackWithSectors<VectorShifter>(
sectors,
16, 0x00,
@ -180,14 +213,9 @@ std::shared_ptr<Storage::Disk::Track> Storage::Encodings::MFM::GetFMTrackWithSec
std::shared_ptr<Storage::Disk::Track> Storage::Encodings::MFM::GetMFMTrackWithSectors(const std::vector<Sector> &sectors)
{
struct VectorShifter: public MFMShifter<VectorShifter> {
void output_short(uint16_t value) {
data.push_back(value & 0xff);
data.push_back(value >> 8);
}
std::vector<uint8_t> data;
struct VectorShifter: public MFMShifter<VectorShifter>, VectorReceiver {
using VectorReceiver::output_short;
};
return GetTrackWithSectors<VectorShifter>(
sectors,
50, 0x4e,