1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-23 20:29:42 +00:00

Adds the ability for a PCMSegment to maintain 'fuzzy' (i.e. random) bits. Implements an LFSR for bit generation.

I'm not necessarily happy with the idea of just shoving in a [pseudo-]random number generator in rather than emulating the proper process underneath, but for now I throw my arms up.
This commit is contained in:
Thomas Harte 2020-01-19 20:09:11 -05:00
parent f3f8345e5e
commit 5391a699a4
4 changed files with 84 additions and 10 deletions

60
NumberTheory/LFSR.hpp Normal file
View File

@ -0,0 +1,60 @@
//
// LFSR.hpp
// Clock Signal
//
// Created by Thomas Harte on 19/01/2020.
// Copyright © 2020 Thomas Harte. All rights reserved.
//
#ifndef LFSR_h
#define LFSR_h
template <typename IntType> struct LSFRPolynomial {
};
// The following were taken 'at random' from https://users.ece.cmu.edu/~koopman/lfsr/index.html
template <> struct LSFRPolynomial<uint64_t> {
static constexpr uint64_t value = 0x80000000000019E2;
};
template <> struct LSFRPolynomial<uint32_t> {
static constexpr uint32_t value = 0x80000C34;
};
template <> struct LSFRPolynomial<uint16_t> {
static constexpr uint16_t value = 0x853E;
};
template <> struct LSFRPolynomial<uint8_t> {
static constexpr uint8_t value = 0xAF;
};
/*!
Provides a linear-feedback shift register with a random initial state; if no polynomial is supplied
then one will be picked that is guaranteed to give the maximal number of LFSR states that can fit
in the specified int type.
*/
template <typename IntType = uint64_t, IntType polynomial = LSFRPolynomial<IntType>::value> class LFSR {
public:
LFSR() {
// Randomise the value, ensuring it doesn't end up being 0.
while(!value_) {
uint8_t *value_byte = reinterpret_cast<uint8_t *>(&value_);
for(size_t c = 0; c < sizeof(IntType); ++c) {
*value_byte = uint8_t(uint64_t(rand()) * 255 / RAND_MAX);
++value_byte;
}
}
}
IntType next() {
auto result = value_ & 1;
value_ = (value_ >> 1) ^ (result * polynomial);
return result;
}
private:
IntType value_ = 0;
};
#endif /* LFSR_h */

View File

@ -1185,6 +1185,7 @@
4B7BA03523CEB86000B98D9E /* BD500.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BD500.cpp; path = Oric/BD500.cpp; sourceTree = "<group>"; };
4B7BA03623CEB86000B98D9E /* BD500.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = BD500.hpp; path = Oric/BD500.hpp; sourceTree = "<group>"; };
4B7BA03823CEB8D200B98D9E /* DiskController.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = DiskController.hpp; path = Oric/DiskController.hpp; sourceTree = "<group>"; };
4B7BA03923D5302C00B98D9E /* LFSR.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = LFSR.hpp; path = ../../NumberTheory/LFSR.hpp; sourceTree = "<group>"; };
4B7F188C2154825D00388727 /* MasterSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MasterSystem.cpp; sourceTree = "<group>"; };
4B7F188D2154825D00388727 /* MasterSystem.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MasterSystem.hpp; sourceTree = "<group>"; };
4B7F1895215486A100388727 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StaticAnalyser.hpp; sourceTree = "<group>"; };
@ -3186,6 +3187,7 @@
children = (
4BB697C61D4B558F00248BDF /* Factors.hpp */,
4BF8295F1D8F3C87001BAE39 /* CRC.hpp */,
4B7BA03923D5302C00B98D9E /* LFSR.hpp */,
);
name = NumberTheory;
sourceTree = "<group>";

View File

@ -9,6 +9,7 @@
#include "PCMSegment.hpp"
#include <cassert>
#include <cstdlib>
using namespace Storage::Disk;
@ -70,31 +71,33 @@ void PCMSegment::rotate_right(size_t length) {
}
Storage::Disk::Track::Event PCMSegmentEventSource::get_next_event() {
// track the initial bit pointer for potentially considering whether this was an
// initial index hole or a subsequent one later on
// Track the initial bit pointer for potentially considering whether this was an
// initial index hole or a subsequent one later on.
const std::size_t initial_bit_pointer = bit_pointer_;
// if starting from the beginning, pull half a bit backward, as if the initial bit
// is set, it should be in the centre of its window
// If starting from the beginning, pull half a bit backward, as if the initial bit
// is set, it should be in the centre of its window.
next_event_.length.length = bit_pointer_ ? 0 : -(segment_->length_of_a_bit.length >> 1);
// search for the next bit that is set, if any
while(bit_pointer_ < segment_->data.size()) {
bool bit = segment_->data[bit_pointer_];
bit_pointer_++; // so this always points one beyond the most recent bit returned
++bit_pointer_; // so this always points one beyond the most recent bit returned
next_event_.length.length += segment_->length_of_a_bit.length;
// if this bit is set, return the event
if(bit) return next_event_;
// if this bit is set, or is fuzzy and a random bit of 1 is selected, return the event.
if(bit ||
(!segment_->fuzzy_mask.empty() && segment_->fuzzy_mask[bit_pointer_] && lfsr_.next())
) return next_event_;
}
// if the end is reached without a bit being set, it'll be index holes from now on
// If the end is reached without a bit being set, it'll be index holes from now on.
next_event_.type = Track::Event::IndexHole;
// test whether this is the very first time that bits have been exhausted. If so then
// Test whether this is the very first time that bits have been exhausted. If so then
// allow an extra half bit's length to run from the position of the potential final transition
// event to the end of the segment. Otherwise don't allow any extra time, as it's already
// been consumed
// been consumed.
if(initial_bit_pointer <= segment_->data.size()) {
next_event_.length.length += (segment_->length_of_a_bit.length >> 1);
bit_pointer_++;

View File

@ -14,6 +14,7 @@
#include <vector>
#include "../../Storage.hpp"
#include "../../../NumberTheory/LFSR.hpp"
#include "Track.hpp"
namespace Storage {
@ -39,6 +40,13 @@ struct PCMSegment {
*/
std::vector<bool> data;
/*!
If a segment has a fuzzy mask then anywhere the mask has a value
of @c true, a random bit will be ORd onto whatever is in the
corresponding slot in @c data.
*/
std::vector<bool> fuzzy_mask;
/*!
Constructs an instance of PCMSegment with the specified @c length_of_a_bit
and @c data.
@ -192,6 +200,7 @@ class PCMSegmentEventSource {
std::shared_ptr<PCMSegment> segment_;
std::size_t bit_pointer_;
Track::Event next_event_;
LFSR<uint64_t> lfsr_;
};
}