mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
125 lines
3.1 KiB
C++
125 lines
3.1 KiB
C++
#include "globals.h"
|
|
#include "fluxmap.h"
|
|
#include "decoders/fluxmapreader.h"
|
|
#include "protocol.h"
|
|
#include "decoders/decoders.h"
|
|
#include "sector.h"
|
|
#include "victor9k.h"
|
|
#include "crc.h"
|
|
#include "bytes.h"
|
|
#include "fmt/format.h"
|
|
#include <string.h>
|
|
#include <algorithm>
|
|
|
|
const FluxPattern SECTOR_RECORD_PATTERN(32, VICTOR9K_SECTOR_RECORD);
|
|
const FluxPattern DATA_RECORD_PATTERN(32, VICTOR9K_DATA_RECORD);
|
|
const FluxMatchers ANY_RECORD_PATTERN({ &SECTOR_RECORD_PATTERN, &DATA_RECORD_PATTERN });
|
|
|
|
static int decode_data_gcr(uint8_t gcr)
|
|
{
|
|
switch (gcr)
|
|
{
|
|
#define GCR_ENTRY(gcr, data) \
|
|
case gcr: return data;
|
|
#include "data_gcr.h"
|
|
#undef GCR_ENTRY
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static Bytes decode(const std::vector<bool>& bits)
|
|
{
|
|
Bytes output;
|
|
ByteWriter bw(output);
|
|
BitWriter bitw(bw);
|
|
|
|
auto ii = bits.begin();
|
|
while (ii != bits.end())
|
|
{
|
|
uint8_t inputfifo = 0;
|
|
for (size_t i=0; i<5; i++)
|
|
{
|
|
if (ii == bits.end())
|
|
break;
|
|
inputfifo = (inputfifo<<1) | *ii++;
|
|
}
|
|
|
|
uint8_t decoded = decode_data_gcr(inputfifo);
|
|
bitw.push(decoded, 4);
|
|
}
|
|
bitw.flush();
|
|
|
|
return output;
|
|
}
|
|
|
|
class Victor9kDecoder : public AbstractDecoder
|
|
{
|
|
public:
|
|
Victor9kDecoder(const DecoderProto& config):
|
|
AbstractDecoder(config)
|
|
{}
|
|
|
|
RecordType advanceToNextRecord()
|
|
{
|
|
const FluxMatcher* matcher = nullptr;
|
|
_sector->clock = _sector->bitcell = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
|
|
if (matcher == &SECTOR_RECORD_PATTERN)
|
|
return SECTOR_RECORD;
|
|
if (matcher == &DATA_RECORD_PATTERN)
|
|
return DATA_RECORD;
|
|
return UNKNOWN_RECORD;
|
|
}
|
|
|
|
void decodeSectorRecord()
|
|
{
|
|
/* Skip the sync marker bit. */
|
|
readRawBits(22);
|
|
|
|
/* Read header. */
|
|
|
|
auto bytes = decode(readRawBits(4*10)).slice(0, 4);
|
|
|
|
uint8_t rawTrack = bytes[1];
|
|
_sector->logicalSector = bytes[2];
|
|
uint8_t gotChecksum = bytes[3];
|
|
|
|
_sector->logicalTrack = rawTrack & 0x7f;
|
|
_sector->logicalSide = rawTrack >> 7;
|
|
uint8_t wantChecksum = bytes[1] + bytes[2];
|
|
if ((_sector->logicalSector > 20) || (_sector->logicalTrack > 85) || (_sector->logicalSide > 1))
|
|
return;
|
|
|
|
if (wantChecksum == gotChecksum)
|
|
_sector->status = Sector::DATA_MISSING; /* unintuitive but correct */
|
|
}
|
|
|
|
void decodeDataRecord()
|
|
{
|
|
/* Skip the sync marker bit. */
|
|
readRawBits(22);
|
|
|
|
/* Read data. */
|
|
|
|
auto bytes = decode(readRawBits((VICTOR9K_SECTOR_LENGTH+5)*10))
|
|
.slice(0, VICTOR9K_SECTOR_LENGTH+5);
|
|
ByteReader br(bytes);
|
|
|
|
/* Check that this is actually a data record. */
|
|
|
|
if (br.read_8() != 8)
|
|
return;
|
|
|
|
_sector->data = br.read(VICTOR9K_SECTOR_LENGTH);
|
|
uint16_t gotChecksum = sumBytes(_sector->data);
|
|
uint16_t wantChecksum = br.read_le16();
|
|
_sector->status = (gotChecksum == wantChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
|
|
}
|
|
};
|
|
|
|
std::unique_ptr<AbstractDecoder> createVictor9kDecoder(const DecoderProto& config)
|
|
{
|
|
return std::unique_ptr<AbstractDecoder>(new Victor9kDecoder(config));
|
|
}
|
|
|
|
|