-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from jepler/redo-mfm-add-decoding
redesign MFM decoding & add encoding
- Loading branch information
Showing
15 changed files
with
849 additions
and
264 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
# | ||
# SPDX-License-Identifier: MIT | ||
|
||
/mfm | ||
/html | ||
/ci | ||
/doxygen | ||
/examples/*/build | ||
/html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
[submodule "doxygen-awesome-css"] | ||
path = doxygen-awesome-css | ||
url = https://github.com/jothepro/doxygen-awesome-css.git | ||
[submodule "host_src/greaseweazle"] | ||
path = host_src/greaseweazle | ||
url = https://github.com/keirf/greaseweazle.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
#include <Adafruit_Floppy.h> | ||
|
||
#if defined(ADAFRUIT_FEATHER_M4_EXPRESS) | ||
#define DENSITY_PIN A1 // IDC 2 | ||
#define INDEX_PIN A5 // IDC 8 | ||
#define SELECT_PIN A0 // IDC 12 | ||
#define MOTOR_PIN A2 // IDC 16 | ||
#define DIR_PIN A3 // IDC 18 | ||
#define STEP_PIN A4 // IDC 20 | ||
#define WRDATA_PIN 13 // IDC 22 | ||
#define WRGATE_PIN 12 // IDC 24 | ||
#define TRK0_PIN 10 // IDC 26 | ||
#define PROT_PIN 11 // IDC 28 | ||
#define READ_PIN 9 // IDC 30 | ||
#define SIDE_PIN 6 // IDC 32 | ||
#define READY_PIN 5 // IDC 34 | ||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) | ||
#define DENSITY_PIN A1 // IDC 2 | ||
#define INDEX_PIN 25 // IDC 8 | ||
#define SELECT_PIN A0 // IDC 12 | ||
#define MOTOR_PIN A2 // IDC 16 | ||
#define DIR_PIN A3 // IDC 18 | ||
#define STEP_PIN 24 // IDC 20 | ||
#define WRDATA_PIN 13 // IDC 22 | ||
#define WRGATE_PIN 12 // IDC 24 | ||
#define TRK0_PIN 10 // IDC 26 | ||
#define PROT_PIN 11 // IDC 28 | ||
#define READ_PIN 9 // IDC 30 | ||
#define SIDE_PIN 8 // IDC 32 | ||
#define READY_PIN 7 // IDC 34 | ||
#ifndef USE_TINYUSB | ||
#error "Please set Adafruit TinyUSB under Tools > USB Stack" | ||
#endif | ||
#elif defined(ARDUINO_RASPBERRY_PI_PICO) | ||
#define DENSITY_PIN 2 // IDC 2 | ||
#define INDEX_PIN 3 // IDC 8 | ||
#define SELECT_PIN 4 // IDC 12 | ||
#define MOTOR_PIN 5 // IDC 16 | ||
#define DIR_PIN 6 // IDC 18 | ||
#define STEP_PIN 7 // IDC 20 | ||
#define WRDATA_PIN 8 // IDC 22 (not used during read) | ||
#define WRGATE_PIN 9 // IDC 24 (not used during read) | ||
#define TRK0_PIN 10 // IDC 26 | ||
#define PROT_PIN 11 // IDC 28 | ||
#define READ_PIN 12 // IDC 30 | ||
#define SIDE_PIN 13 // IDC 32 | ||
#define READY_PIN 14 // IDC 34 | ||
#ifndef USE_TINYUSB | ||
#error "Please set Adafruit TinyUSB under Tools > USB Stack" | ||
#endif | ||
#elif defined(ARDUINO_ADAFRUIT_FLOPPSY_RP2040) | ||
// Yay built in pin definitions! | ||
#else | ||
#error "Please set up pin definitions!" | ||
#endif | ||
|
||
|
||
Adafruit_Floppy floppy(DENSITY_PIN, INDEX_PIN, SELECT_PIN, | ||
MOTOR_PIN, DIR_PIN, STEP_PIN, | ||
WRDATA_PIN, WRGATE_PIN, TRK0_PIN, | ||
PROT_PIN, READ_PIN, SIDE_PIN, READY_PIN); | ||
|
||
// You can select IBMPC1440K or IBMPC360K (check adafruit_floppy_disk_t options!) | ||
Adafruit_MFM_Floppy mfm_floppy(&floppy, IBMPC1440K); | ||
|
||
|
||
uint32_t time_stamp = 0; | ||
|
||
void setup() { | ||
pinMode(LED_BUILTIN, OUTPUT); | ||
Serial.begin(115200); | ||
while (!Serial) delay(100); | ||
|
||
#if defined(FLOPPY_DIRECTION_PIN) | ||
pinMode(FLOPPY_DIRECTION_PIN, OUTPUT); | ||
digitalWrite(FLOPPY_DIRECTION_PIN, HIGH); | ||
#endif | ||
|
||
delay(500); // wait for serial to open | ||
Serial.println("its time for a nice floppy transfer!"); | ||
|
||
floppy.debug_serial = &Serial; | ||
|
||
if (! mfm_floppy.begin()) { | ||
Serial.println("Failed to spin up motor & find index pulse"); | ||
while (1) yield(); | ||
} | ||
} | ||
|
||
void hexdump(size_t offset, const uint8_t *data, size_t n) { | ||
for (size_t i = 0; i < n; i += 16) { | ||
size_t addr = offset + i; | ||
Serial.printf("%08x", addr); | ||
for (size_t j = 0; j < 16; j++) { | ||
if(i+j > n) Serial.printf(" ");else | ||
Serial.printf(" %02x", mfm_floppy.track_data[addr + j]); | ||
} | ||
Serial.print(" | "); | ||
for (size_t j = 0; j < 16; j++) { | ||
if(i+j > n) break; | ||
uint8_t d = mfm_floppy.track_data[addr + j]; | ||
if (! isprint(d)) { | ||
d = ' '; | ||
} | ||
Serial.write(d); | ||
} | ||
Serial.print("\n"); | ||
} | ||
} | ||
|
||
uint8_t track = 0; | ||
bool head = 0; | ||
int i = 0; | ||
void loop() { | ||
int32_t captured_sectors; | ||
|
||
uint8_t sector[512]; | ||
int lba = (i++ % 2 == 0) ? 0 : 18; | ||
if (!mfm_floppy.readSector(lba, sector)) { | ||
Serial.println("Failed to read sector"); | ||
return; | ||
} | ||
|
||
hexdump(lba * 512, sector, 512); | ||
|
||
memset(sector, 0, 512); | ||
snprintf(reinterpret_cast<char*>(sector), sizeof(sector), "Hello from iteration %zd of Adafruit Floppy MFM writing\n", i); | ||
|
||
if (!mfm_floppy.writeSector(lba, sector)) { | ||
Serial.println("Failed to write sectorn"); | ||
return; | ||
} | ||
if (!mfm_floppy.syncDevice()) { | ||
Serial.println("Failed to sync device"); | ||
return; | ||
} | ||
|
||
delay(1000); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
test_flux.h | ||
main | ||
flux[01] | ||
check[01] | ||
decode[01] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
PYTHON3 = env PYTHONPATH=greaseweazle/scripts python3 | ||
|
||
.PHONY: check | ||
check: main check_flux.py | ||
./main | ||
$(PYTHON3) check_flux.py flux0 > decode0 | ||
$(PYTHON3) check_flux.py flux1 > decode1 | ||
|
||
main: main.c ../src/mfm_impl.h Makefile test_flux.h | ||
gcc -iquote ../src -Wall -Werror -ggdb3 -Og -o $@ $< | ||
|
||
test_flux.h: make_flux.py greaseweazle/scripts/greaseweazle/version.py | ||
$(PYTHON3) $< $@ | ||
|
||
greaseweazle/scripts/greaseweazle/version.py: | ||
$(MAKE) -C greaseweazle |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import sys | ||
from greaseweazle.track import MasterTrack | ||
from greaseweazle.codec.ibm.mfm import IBM_MFM | ||
from bitarray import bitarray | ||
|
||
with open(sys.argv[1]) as flux1: | ||
content = bitarray("".join(c for c in flux1.read() if c in "01")) | ||
|
||
nominal_bitrate = 1_000_000 | ||
|
||
master = MasterTrack(content[:200_000], 0.2) | ||
print(master.flux().list[:25]) | ||
track = IBM_MFM(0,0) | ||
track.time_per_rev = 0.2 | ||
track.clock = 1e-6 | ||
|
||
|
||
track.decode_raw(master) | ||
print(sys.argv[1], track.summary_string(), file=sys.stderr) | ||
print(sys.argv[1], track.summary_string()) | ||
print("".join("E."[sec.crc == 0] for sec in track.sectors)) | ||
for i in track.iams: | ||
print(i) | ||
for s in track.sectors: | ||
print(s) | ||
|
||
if n := track.nr_missing(): | ||
print(f"{n} missing sector(s)", file=sys.stderr) | ||
raise SystemExit(1) |
Submodule greaseweazle
added at
f155a3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#include <stdint.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
#define DEBUG_PRINTF(...) printf(__VA_ARGS__) | ||
#include "mfm_impl.h" | ||
|
||
uint8_t flux[] = { | ||
#include "test_flux.h" | ||
}; | ||
|
||
enum { sector_count = 18 }; | ||
|
||
uint8_t track_buf[sector_count * mfm_io_block_size]; | ||
uint8_t validity[sector_count]; | ||
|
||
mfm_io_t io = { | ||
.T1_nom = 2, | ||
.T2_max = 5, | ||
.T3_max = 7, | ||
.pulses = flux, | ||
.n_pulses = sizeof(flux), | ||
.sectors = track_buf, | ||
.sector_validity = validity, | ||
.n_sectors = sizeof(track_buf) / mfm_io_block_size, | ||
}; | ||
|
||
static void flux_bins(mfm_io_t *io) { | ||
io->pos = 0; | ||
int bins[3] = {}; | ||
while (!mfm_io_eof(io)) { | ||
bins[mfm_io_read_symbol(io)]++; | ||
} | ||
printf("Flux bins: %d %d %d\n", bins[0], bins[1], bins[2]); | ||
} | ||
|
||
static void dump_flux(const char *filename, mfm_io_t *io) { | ||
FILE *f = fopen(filename, "w"); | ||
io->pos = 0; | ||
uint32_t state = 0; | ||
while (!mfm_io_eof(io)) { | ||
int s = mfm_io_read_symbol(io); | ||
state = ((state << 2) | s) & mfm_io_triple_mark_mask; | ||
fprintf(f, "10"); | ||
if (s > mfm_io_pulse_10) { | ||
fprintf(f, "0"); | ||
} | ||
if (s > mfm_io_pulse_100) { | ||
fprintf(f, "0"); | ||
} | ||
if (state == mfm_io_triple_mark_magic) { | ||
DEBUG_PRINTF("triple mark @%zd\n", io->pos); | ||
fprintf(f, "\n"); | ||
} | ||
} | ||
#if 0 | ||
for(size_t i=0; i<io->num_pulses; i++) { | ||
fprintf(f, "%d\n", io->pulses[i]); | ||
} | ||
#endif | ||
fclose(f); | ||
} | ||
|
||
int main() { | ||
flux_bins(&io); | ||
printf("Decoded %zd sectors\n", decode_track_mfm(&io)); | ||
|
||
dump_flux("flux0", &io); | ||
|
||
memset(flux, 0, sizeof(flux)); | ||
|
||
#if 0 | ||
for (size_t i = 0; i < sizeof(track_buf); i++) | ||
track_buf[i] = i & 0xff; | ||
#endif | ||
|
||
printf("Create new flux data\n"); | ||
(void)encode_track_mfm; | ||
encode_track_mfm(&io); | ||
dump_flux("flux1", &io); | ||
|
||
memset(track_buf, 0, sizeof(track_buf)); | ||
|
||
io.n_valid = 0; | ||
memset(validity, 0, sizeof(validity)); | ||
flux_bins(&io); | ||
size_t decoded = decode_track_mfm(&io); | ||
printf("Decoded %zd sectors\n", decoded); | ||
|
||
return decoded != 18; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import sys | ||
from greaseweazle.codec.ibm.mfm import IBM_MFM_1440 | ||
|
||
track = IBM_MFM_1440(0, 0) | ||
track.set_img_track(b'adaf00' + b'\0' * 512 * 18) | ||
track.decode_raw(track) | ||
print(track.summary_string()) | ||
flux = track.flux().flux_for_writeout() | ||
print(flux.list[:25],len(flux.list)) | ||
with open(sys.argv[1], "wt") as f: | ||
for i, fi in enumerate(flux.list): | ||
print(f"{fi*2},", end="\n" if i % 16 == 15 else " ", file=f) | ||
print(file=f) |
Oops, something went wrong.