Compare commits

...

1 Commits

Author SHA1 Message Date
David Given
f634988356 Add support for emitting index sync bytes to the Northstar encoder. This tells
the FluxEngine to wait for the next index pulse before continuing the write.
This also allows FluxEngine to decode its own encoded bytestreams, allowing
encodedecodetest to work.
2022-03-14 22:11:08 +01:00
6 changed files with 211 additions and 159 deletions

View File

@@ -88,16 +88,6 @@ public:
now = tell().ns();
}
/* Discard a possible partial sector at the end of the track.
* This partial sector could be mistaken for a conflicted sector, if
* whatever data read happens to match the checksum of 0, which is
* rare, but has been observed on some disks.
*/
if (now > (getFluxmapDuration() - 21e6)) {
seekToIndexMark();
return 0;
}
int msSinceIndex = std::round(now / 1e6);
/* Note that the seekToPattern ignores the sector pulses, so if
@@ -108,11 +98,6 @@ public:
nanoseconds_t clock = seekToPattern(ANY_SECTOR_PATTERN);
_sector->headerStartTime = tell().ns();
/* Discard a possible partial sector. */
if (_sector->headerStartTime > (getFluxmapDuration() - 21e6)) {
return 0;
}
int sectorFoundTimeRaw = std::round(_sector->headerStartTime / 1e6);
int sectorFoundTime;
@@ -132,7 +117,16 @@ public:
void decodeSectorRecord() override
{
nanoseconds_t before = tell().ns();
uint64_t id = toBytes(readRawBits(64)).reader().read_be64();
nanoseconds_t after = tell().ns();
/* Discard any sectors which span the end of a revolution. This can sometimes
* cause spurious bad sectors which can trigger conflicts. */
if (int(before / 200e9) != int(after / 200e9))
return;
unsigned recordSize, payloadSize, headerSize;
if (id == MFM_ID) {

View File

@@ -17,30 +17,34 @@
#define TOTAL_SECTOR_BYTES ()
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const std::shared_ptr<const Sector>& sector)
static void write_sector(std::vector<bool>& bits,
unsigned& cursor,
const std::shared_ptr<const Sector>& sector)
{
int preambleSize = 0;
int encodedSectorSize = 0;
int gapFillSize = 0;
int preHeaderGapFillSize = 0;
bool doubleDensity;
switch (sector->data.size()) {
switch (sector->data.size())
{
case NORTHSTAR_PAYLOAD_SIZE_SD:
preambleSize = NORTHSTAR_PREAMBLE_SIZE_SD;
encodedSectorSize = PRE_HEADER_GAP_FILL_SIZE_SD + NORTHSTAR_ENCODED_SECTOR_SIZE_SD + GAP_FILL_SIZE_SD;
gapFillSize = GAP_FILL_SIZE_SD;
encodedSectorSize = PRE_HEADER_GAP_FILL_SIZE_SD +
NORTHSTAR_ENCODED_SECTOR_SIZE_SD;
preHeaderGapFillSize = PRE_HEADER_GAP_FILL_SIZE_SD;
doubleDensity = false;
break;
case NORTHSTAR_PAYLOAD_SIZE_DD:
preambleSize = NORTHSTAR_PREAMBLE_SIZE_DD;
encodedSectorSize = PRE_HEADER_GAP_FILL_SIZE_DD + NORTHSTAR_ENCODED_SECTOR_SIZE_DD + GAP_FILL_SIZE_DD;
gapFillSize = GAP_FILL_SIZE_DD;
encodedSectorSize = PRE_HEADER_GAP_FILL_SIZE_DD +
NORTHSTAR_ENCODED_SECTOR_SIZE_DD;
preHeaderGapFillSize = PRE_HEADER_GAP_FILL_SIZE_DD;
doubleDensity = true;
break;
default:
Error() << "unsupported sector size --- you must pick 256 or 512";
break;
@@ -61,44 +65,40 @@ static void write_sector(std::vector<bool>& bits, unsigned& cursor, const std::s
Bytes sectorData;
if (sector->data.size() == encodedSectorSize)
sectorData = sector->data;
else {
else
{
ByteWriter writer(sectorData);
writer.write_8(0xFB); /* sync character */
if (doubleDensity == true) {
if (doubleDensity == true)
writer.write_8(0xFB); /* Double-density has two sync characters */
}
writer += sector->data;
if (doubleDensity == true) {
if (doubleDensity == true)
writer.write_8(northstarChecksum(sectorData.slice(2)));
} else {
else
writer.write_8(northstarChecksum(sectorData.slice(1)));
}
}
for (uint8_t b : sectorData)
fullSector->push_back(b);
if (sector->logicalSector != 9) {
/* sector postamble */
for (int i = 0; i < gapFillSize; i++)
fullSector->push_back(GAP2_FILL_BYTE);
if (fullSector->size() != fullSectorSize)
Error() << "sector mismatched length (" << sector->data.size() << ") expected: " << fullSector->size() << " got " << fullSectorSize;
} else {
/* sector postamble */
for (int i = 0; i < gapFillSize; i++)
Error() << "sector mismatched length (" << sector->data.size()
<< ") expected: " << fullSector->size() << " got "
<< fullSectorSize;
/* A few bytes of sector postamble just so the blank skip area doesn't start
* immediately after the data. */
for (int i = 0; i < 10; i++)
fullSector->push_back(GAP2_FILL_BYTE);
}
bool lastBit = false;
if (doubleDensity == true) {
if (doubleDensity == true)
encodeMfm(bits, cursor, fullSector, lastBit);
}
else {
else
encodeFm(bits, cursor, fullSector);
}
}
class NorthstarEncoder : public AbstractEncoder
{
@@ -106,9 +106,11 @@ public:
NorthstarEncoder(const EncoderProto& config):
AbstractEncoder(config),
_config(config.northstar())
{}
{
}
std::vector<std::shared_ptr<const Sector>> collectSectors(int physicalTrack, int physicalSide, const Image& image) override
std::vector<std::shared_ptr<const Sector>> collectSectors(
int physicalTrack, int physicalSide, const Image& image) override
{
std::vector<std::shared_ptr<const Sector>> sectors;
@@ -116,7 +118,8 @@ public:
{
for (int sectorId = 0; sectorId < 10; sectorId++)
{
const auto& sector = image.get(physicalTrack, physicalSide, sectorId);
const auto& sector =
image.get(physicalTrack, physicalSide, sectorId);
if (sector)
sectors.push_back(sector);
}
@@ -125,8 +128,10 @@ public:
return sectors;
}
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide,
const std::vector<std::shared_ptr<const Sector>>& sectors, const Image& image) override
std::unique_ptr<Fluxmap> encode(int physicalTrack,
int physicalSide,
const std::vector<std::shared_ptr<const Sector>>& sectors,
const Image& image) override
{
int bitsPerRevolution = 100000;
double clockRateUs = 4.00;
@@ -135,23 +140,28 @@ public:
return std::unique_ptr<Fluxmap>();
const auto& sector = *sectors.begin();
if (sector->data.size() == NORTHSTAR_PAYLOAD_SIZE_SD) {
if (sector->data.size() == NORTHSTAR_PAYLOAD_SIZE_SD)
bitsPerRevolution /= 2; // FM
} else {
else
clockRateUs /= 2.00;
}
auto fluxmap = std::make_unique<Fluxmap>();
bool first = true;
for (const auto& sectorData : sectors)
{
if (!first)
fluxmap->appendIndex();
first = false;
std::vector<bool> bits(bitsPerRevolution);
unsigned cursor = 0;
for (const auto& sectorData : sectors)
write_sector(bits, cursor, sectorData);
if (cursor > bits.size())
Error() << "track data overrun";
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
fluxmap->appendBits(bits, clockRateUs * 1e3);
}
// if (fluxmap->duration() > 200e6)
// Error() << "track data overrun";
return fluxmap;
}
@@ -159,8 +169,8 @@ private:
const NorthstarEncoderProto& _config;
};
std::unique_ptr<AbstractEncoder> createNorthstarEncoder(const EncoderProto& config)
std::unique_ptr<AbstractEncoder> createNorthstarEncoder(
const EncoderProto& config)
{
return std::unique_ptr<AbstractEncoder>(new NorthstarEncoder(config));
}

View File

@@ -56,4 +56,3 @@ Fluxmap& Fluxmap::appendBits(const std::vector<bool>& bits, nanoseconds_t clock)
return *this;
}

View File

@@ -17,9 +17,12 @@ public:
unsigned zeroes = 0;
nanoseconds_t ns() const
{ return ticks * NS_PER_TICK; }
{
return ticks * NS_PER_TICK;
}
operator std::string () {
operator std::string()
{
return fmt::format("[b:{}, t:{}, z:{}]", bytes, ticks, zeroes);
}
};
@@ -32,14 +35,30 @@ public:
appendBytes((const uint8_t*)s.c_str(), s.size());
}
Fluxmap(const Bytes bytes):
_bytes(bytes)
{}
Fluxmap(const Bytes& bytes)
{
appendBytes(bytes);
}
nanoseconds_t duration() const { return _duration; }
unsigned ticks() const { return _ticks; }
size_t bytes() const { return _bytes.size(); }
const Bytes& rawBytes() const { return _bytes; }
nanoseconds_t duration() const
{
return _duration;
}
unsigned ticks() const
{
return _ticks;
}
size_t bytes() const
{
return _bytes.size();
}
const Bytes& rawBytes() const
{
return _bytes;
}
const uint8_t* ptr() const
{

View File

@@ -322,10 +322,10 @@ encodedecodetest() {
echo " format=$format"
echo " configs=$*"
echo " fluxx=flux"
echo "build $OBJDIR/$format.encodedecode.scp.stamp : encodedecode | fluxengine$EXTENSION scripts/encodedecodetest.sh $*"
echo " format=$format"
echo " configs=$*"
echo " fluxx=scp"
#echo "build $OBJDIR/$format.encodedecode.scp.stamp : encodedecode | fluxengine$EXTENSION scripts/encodedecodetest.sh $*"
#echo " format=$format"
#echo " configs=$*"
#echo " fluxx=scp"
}
buildlibrary libagg.a \
@@ -677,6 +677,7 @@ encodedecodetest rx50
encodedecodetest tids990
encodedecodetest victor9k_ss
encodedecodetest victor9k_ds
encodedecodetest northstar87 scripts/northstar87_test.textpb
# vim: sw=4 ts=4 et

View File

@@ -0,0 +1,29 @@
image_reader {
img {
tracks: 35
sides: 1
trackdata {
sector_size: 256
sector_range {
start_sector: 0
sector_count: 10
}
}
}
}
image_writer {
img {
tracks: 35
sides: 1
trackdata {
sector_size: 256
sector_range {
start_sector: 0
sector_count: 10
}
}
}
}