1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-01 22:41:32 +00:00

Factor out bit spreading.

(And do a better job of it)
This commit is contained in:
Thomas Harte 2021-10-12 14:49:01 -07:00
parent fc4ca4f8e3
commit 955cb6411c
4 changed files with 46 additions and 54 deletions

37
Numeric/BitSpread.hpp Normal file
View File

@ -0,0 +1,37 @@
//
// BitSpread.hpp
// Clock Signal
//
// Created by Thomas Harte on 12/10/2021.
// Copyright © 2021 Thomas Harte. All rights reserved.
//
#ifndef BitSpread_hpp
#define BitSpread_hpp
namespace Numeric {
/// @returns The bits of @c input with a 0 bit inserted between each and
/// keeping the least-significant bit in its original position.
///
/// i.e. if @c input is abcdefgh then the result is 0a0b0c0d0e0f0g0h
constexpr uint16_t spread_bits(uint8_t input) {
uint16_t result = uint16_t(input); // 0000 0000 abcd efgh
result = (result | (result << 4)) & 0x0f0f; // 0000 abcd 0000 efgh
result = (result | (result << 2)) & 0x3333; // 00ab 00cd 00ef 00gh
return (result | (result << 1)) & 0x5555; // 0a0b 0c0d 0e0f 0g0h
}
/// Performs the opposite action to @c spread_bits; given the 16-bit input
/// @c abcd @c efgh @c ijkl @c mnop, returns the byte value @c bdfhjlnp
/// i.e. every other bit is retained, keeping the least-significant bit in place.
constexpr uint8_t unspread_bits(uint16_t input) {
input &= 0x5555; // 0a0b 0c0d 0e0f 0g0h
input = (input | (input >> 1)) & 0x3333; // 00ab 00cd 00ef 00gh
input = (input | (input >> 2)) & 0x0f0f; // 0000 abcd 0000 efgh
return uint8_t(input | (input >> 4)); // 0000 0000 abcd efgh
}
}
#endif /* BitSpread_hpp */

View File

@ -2009,6 +2009,7 @@
4BD0FBC2233706A200148981 /* CSApplication.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CSApplication.m; sourceTree = "<group>"; };
4BD1552E270B14AC00410C6E /* MemoryMap.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MemoryMap.hpp; sourceTree = "<group>"; };
4BD1552F2711E5FD00410C6E /* kickstart13 boot logo.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "kickstart13 boot logo.json"; path = "Kickstart 1.3 boot logo/kickstart13 boot logo.json"; sourceTree = "<group>"; };
4BD155312716362A00410C6E /* BitSpread.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = BitSpread.hpp; sourceTree = "<group>"; };
4BD191D9219113B80042E144 /* OpenGL.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = OpenGL.hpp; sourceTree = "<group>"; };
4BD191F22191180E0042E144 /* ScanTarget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ScanTarget.cpp; sourceTree = "<group>"; };
4BD191F32191180E0042E144 /* ScanTarget.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ScanTarget.hpp; sourceTree = "<group>"; };
@ -3154,6 +3155,7 @@
4B7BA03C23D55E7900B98D9E /* Numeric */ = {
isa = PBXGroup;
children = (
4BD155312716362A00410C6E /* BitSpread.hpp */,
4B7BA03E23D55E7900B98D9E /* CRC.hpp */,
4B7BA03F23D55E7900B98D9E /* LFSR.hpp */,
4BFEA2F12682A90200EBF94C /* Sizes.hpp */,

View File

@ -10,6 +10,7 @@
#include "../../Encodings/MFM/Constants.hpp"
#include "../../Encodings/MFM/Encoder.hpp"
#include "../../../../Numeric/BitSpread.hpp"
#include "../../Track/PCMTrack.hpp"
#include <type_traits>
@ -78,16 +79,7 @@ template <typename IteratorT> auto checksum(IteratorT begin, IteratorT end) {
++begin;
// Do a clockless MFM encode.
const auto spread = uint16_t(
((value&0x80) << 7) |
((value&0x40) << 6) |
((value&0x20) << 5) |
((value&0x10) << 4) |
((value&0x08) << 3) |
((value&0x04) << 2) |
((value&0x02) << 1) |
((value&0x01) << 0)
);
const auto spread = Numeric::spread_bits(value);
checksum[offset] ^= spread;
offset ^= 1;
}

View File

@ -11,6 +11,7 @@
#include "Constants.hpp"
#include "../../Track/PCMTrack.hpp"
#include "../../../../Numeric/CRC.hpp"
#include "../../../../Numeric/BitSpread.hpp"
#include <cassert>
#include <set>
@ -29,32 +30,11 @@ class MFMEncoder: public Encoder {
void add_byte(uint8_t input, uint8_t fuzzy_mask = 0) final {
crc_generator_.add(input);
const uint16_t spread_value =
uint16_t(
((input & 0x01) << 0) |
((input & 0x02) << 1) |
((input & 0x04) << 2) |
((input & 0x08) << 3) |
((input & 0x10) << 4) |
((input & 0x20) << 5) |
((input & 0x40) << 6) |
((input & 0x80) << 7)
);
const uint16_t spread_value = Numeric::spread_bits(input);
const uint16_t spread_mask = Numeric::spread_bits(fuzzy_mask);
const uint16_t or_bits = uint16_t((spread_value << 1) | (spread_value >> 1) | (last_output_ << 15));
const uint16_t output = spread_value | ((~or_bits) & 0xaaaa);
const uint16_t spread_mask =
uint16_t(
((fuzzy_mask & 0x01) << 0) |
((fuzzy_mask & 0x02) << 1) |
((fuzzy_mask & 0x04) << 2) |
((fuzzy_mask & 0x08) << 3) |
((fuzzy_mask & 0x10) << 4) |
((fuzzy_mask & 0x20) << 5) |
((fuzzy_mask & 0x40) << 6) |
((fuzzy_mask & 0x80) << 7)
);
output_short(output, spread_mask);
}
@ -108,27 +88,8 @@ class FMEncoder: public Encoder {
void add_byte(uint8_t input, uint8_t fuzzy_mask = 0) final {
crc_generator_.add(input);
output_short(
uint16_t(
((input & 0x01) << 0) |
((input & 0x02) << 1) |
((input & 0x04) << 2) |
((input & 0x08) << 3) |
((input & 0x10) << 4) |
((input & 0x20) << 5) |
((input & 0x40) << 6) |
((input & 0x80) << 7) |
0xaaaa
),
uint16_t(
((fuzzy_mask & 0x01) << 0) |
((fuzzy_mask & 0x02) << 1) |
((fuzzy_mask & 0x04) << 2) |
((fuzzy_mask & 0x08) << 3) |
((fuzzy_mask & 0x10) << 4) |
((fuzzy_mask & 0x20) << 5) |
((fuzzy_mask & 0x40) << 6) |
((fuzzy_mask & 0x80) << 7)
)
Numeric::spread_bits(input) | 0xaaaa,
Numeric::spread_bits(fuzzy_mask)
);
}