mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-31 11:17:01 -07:00 
			
		
		
		
	formatspecs, making for much cleaner code. Reformatted everything. This actually happened in multiple steps but then I corrupted my local repository and I had to recover from the working tree.
		
			
				
	
	
		
			211 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			211 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "globals.h"
 | 
						|
#include "decoders/decoders.h"
 | 
						|
#include "encoders/encoders.h"
 | 
						|
#include "victor9k.h"
 | 
						|
#include "crc.h"
 | 
						|
#include "sector.h"
 | 
						|
#include "readerwriter.h"
 | 
						|
#include "image.h"
 | 
						|
#include "fmt/format.h"
 | 
						|
#include "arch/victor9k/victor9k.pb.h"
 | 
						|
#include "lib/encoders/encoders.pb.h"
 | 
						|
#include "lib/layout.h"
 | 
						|
#include <ctype.h>
 | 
						|
#include "bytes.h"
 | 
						|
 | 
						|
static bool lastBit;
 | 
						|
 | 
						|
static void write_zero_bits(
 | 
						|
    std::vector<bool>& bits, unsigned& cursor, unsigned count)
 | 
						|
{
 | 
						|
    while (count--)
 | 
						|
    {
 | 
						|
        if (cursor < bits.size())
 | 
						|
            lastBit = bits[cursor++] = 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void write_one_bits(
 | 
						|
    std::vector<bool>& bits, unsigned& cursor, unsigned count)
 | 
						|
{
 | 
						|
    while (count--)
 | 
						|
    {
 | 
						|
        if (cursor < bits.size())
 | 
						|
            lastBit = bits[cursor++] = 1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void write_bits(
 | 
						|
    std::vector<bool>& bits, unsigned& cursor, const std::vector<bool>& src)
 | 
						|
{
 | 
						|
    for (bool bit : src)
 | 
						|
    {
 | 
						|
        if (cursor < bits.size())
 | 
						|
            lastBit = bits[cursor++] = bit;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void write_bits(
 | 
						|
    std::vector<bool>& bits, unsigned& cursor, uint64_t data, int width)
 | 
						|
{
 | 
						|
    cursor += width;
 | 
						|
    lastBit = data & 1;
 | 
						|
    for (int i = 0; i < width; i++)
 | 
						|
    {
 | 
						|
        unsigned pos = cursor - i - 1;
 | 
						|
        if (pos < bits.size())
 | 
						|
            bits[pos] = data & 1;
 | 
						|
        data >>= 1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void write_bits(
 | 
						|
    std::vector<bool>& bits, unsigned& cursor, const Bytes& bytes)
 | 
						|
{
 | 
						|
    ByteReader br(bytes);
 | 
						|
    BitReader bitr(br);
 | 
						|
 | 
						|
    while (!bitr.eof())
 | 
						|
    {
 | 
						|
        if (cursor < bits.size())
 | 
						|
            bits[cursor++] = bitr.get();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static int encode_data_gcr(uint8_t data)
 | 
						|
{
 | 
						|
    switch (data & 0x0f)
 | 
						|
    {
 | 
						|
#define GCR_ENTRY(gcr, data) \
 | 
						|
    case data:               \
 | 
						|
        return gcr;
 | 
						|
#include "data_gcr.h"
 | 
						|
#undef GCR_ENTRY
 | 
						|
    }
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
static void write_byte(std::vector<bool>& bits, unsigned& cursor, uint8_t b)
 | 
						|
{
 | 
						|
    write_bits(bits, cursor, encode_data_gcr(b >> 4), 5);
 | 
						|
    write_bits(bits, cursor, encode_data_gcr(b), 5);
 | 
						|
}
 | 
						|
 | 
						|
static void write_bytes(
 | 
						|
    std::vector<bool>& bits, unsigned& cursor, const Bytes& bytes)
 | 
						|
{
 | 
						|
    for (uint8_t b : bytes)
 | 
						|
        write_byte(bits, cursor, b);
 | 
						|
}
 | 
						|
 | 
						|
static void write_gap(std::vector<bool>& bits, unsigned& cursor, int length)
 | 
						|
{
 | 
						|
    for (int i = 0; i < length / 10; i++)
 | 
						|
        write_byte(bits, cursor, '0');
 | 
						|
}
 | 
						|
 | 
						|
static void write_sector(std::vector<bool>& bits,
 | 
						|
    unsigned& cursor,
 | 
						|
    const Victor9kEncoderProto::TrackdataProto& trackdata,
 | 
						|
    const Sector& sector)
 | 
						|
{
 | 
						|
    write_one_bits(bits, cursor, trackdata.pre_header_sync_bits());
 | 
						|
    write_bits(bits, cursor, VICTOR9K_SECTOR_RECORD, 10);
 | 
						|
 | 
						|
    uint8_t encodedTrack = sector.logicalTrack | (sector.logicalSide << 7);
 | 
						|
    uint8_t encodedSector = sector.logicalSector;
 | 
						|
    write_bytes(bits,
 | 
						|
        cursor,
 | 
						|
        Bytes{
 | 
						|
            encodedTrack,
 | 
						|
            encodedSector,
 | 
						|
            (uint8_t)(encodedTrack + encodedSector),
 | 
						|
        });
 | 
						|
 | 
						|
    write_gap(bits, cursor, trackdata.post_header_gap_bits());
 | 
						|
 | 
						|
    write_one_bits(bits, cursor, trackdata.pre_data_sync_bits());
 | 
						|
    write_bits(bits, cursor, VICTOR9K_DATA_RECORD, 10);
 | 
						|
 | 
						|
    write_bytes(bits, cursor, sector.data);
 | 
						|
 | 
						|
    Bytes checksum(2);
 | 
						|
    checksum.writer().write_le16(sumBytes(sector.data));
 | 
						|
    write_bytes(bits, cursor, checksum);
 | 
						|
    write_gap(bits, cursor, trackdata.post_data_gap_bits());
 | 
						|
}
 | 
						|
 | 
						|
class Victor9kEncoder : public Encoder
 | 
						|
{
 | 
						|
public:
 | 
						|
    Victor9kEncoder(const EncoderProto& config):
 | 
						|
        Encoder(config),
 | 
						|
        _config(config.victor9k())
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    void getTrackFormat(Victor9kEncoderProto::TrackdataProto& trackdata,
 | 
						|
        unsigned track,
 | 
						|
        unsigned head)
 | 
						|
    {
 | 
						|
        trackdata.Clear();
 | 
						|
        for (const auto& f : _config.trackdata())
 | 
						|
        {
 | 
						|
            if (f.has_min_track() && (track < f.min_track()))
 | 
						|
                continue;
 | 
						|
            if (f.has_max_track() && (track > f.max_track()))
 | 
						|
                continue;
 | 
						|
            if (f.has_head() && (head != f.head()))
 | 
						|
                continue;
 | 
						|
 | 
						|
            trackdata.MergeFrom(f);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
public:
 | 
						|
    std::unique_ptr<Fluxmap> encode(std::shared_ptr<const TrackInfo>& trackInfo,
 | 
						|
        const std::vector<std::shared_ptr<const Sector>>& sectors,
 | 
						|
        const Image& image) override
 | 
						|
    {
 | 
						|
        Victor9kEncoderProto::TrackdataProto trackdata;
 | 
						|
        getTrackFormat(
 | 
						|
            trackdata, trackInfo->logicalTrack, trackInfo->logicalSide);
 | 
						|
 | 
						|
        unsigned bitsPerRevolution = (trackdata.rotational_period_ms() * 1e3) /
 | 
						|
                                     trackdata.clock_period_us();
 | 
						|
        std::vector<bool> bits(bitsPerRevolution);
 | 
						|
        nanoseconds_t clockPeriod =
 | 
						|
            calculatePhysicalClockPeriod(trackdata.clock_period_us() * 1e3,
 | 
						|
                trackdata.rotational_period_ms() * 1e6);
 | 
						|
        unsigned cursor = 0;
 | 
						|
 | 
						|
        fillBitmapTo(bits,
 | 
						|
            cursor,
 | 
						|
            trackdata.post_index_gap_us() * 1e3 / clockPeriod,
 | 
						|
            {true, false});
 | 
						|
        lastBit = false;
 | 
						|
 | 
						|
        for (const auto& sector : sectors)
 | 
						|
            write_sector(bits, cursor, trackdata, *sector);
 | 
						|
 | 
						|
        if (cursor >= bits.size())
 | 
						|
            error("track data overrun by {} bits", cursor - bits.size());
 | 
						|
        fillBitmapTo(bits, cursor, bits.size(), {true, false});
 | 
						|
 | 
						|
        std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
 | 
						|
        fluxmap->appendBits(bits, clockPeriod);
 | 
						|
        return fluxmap;
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    const Victor9kEncoderProto& _config;
 | 
						|
};
 | 
						|
 | 
						|
std::unique_ptr<Encoder> createVictor9kEncoder(const EncoderProto& config)
 | 
						|
{
 | 
						|
    return std::unique_ptr<Encoder>(new Victor9kEncoder(config));
 | 
						|
}
 | 
						|
 | 
						|
// vim: sw=4 ts=4 et
 |