Кодирование MFM
2026-01-03 18:10Увлёкся я внезапно флопиками. Сижу, отлаживаю алгоритм цифрового PLL, вспоминаю былое. Прикольно, когда от твоих действий что-то на столе жужжит и щёлкает. 😀 С современными компьютерами мы лишились этого удовольствия.
Кто занимался цифровыми коммуникациями, в курсе разных NRZ, NRZI и прочих манчестеров. Это разные способы кодирования информации в цифровом канале. Флопик устроен ровно как цифровой канал. Каждая отдельно взятая дорожка - как зацикленная грампластинка, с которой непрерывно сыпется сигнал с магнитной головки. Сигнал (физически намагниченность) бывает в одну сторону или в другую. Плюс или минус, а для программистов проще представить как 1 или 0. Я считал сигнал с реального флопика и визуализировал, вот как выглядят 100 микросекунд.

Называется это умным словом MFM. Как образуется такой сигнал? Правила простые. Для ясности сначала сформируем вспомогательный битовый поток, в котором в 2 раза больше битов.
В чём прелесть такого кодирования? Имеем гарантированные изменения сигнала не реже чем каждые два бита данных. Но не чаще чем каждый бит. Другая приятность: средний уровень сигнала близкий к 0.5. Первое помогает приёмнику подстроиться к частоте сигнала. Второе даёт возможность точнее выделить фронты.
К примеру, запишем байт 0xA1.

Писать на флопик нетрудно: знай себе формируй нолики и единички по тактовому сигналу. А как быть при считывании? Границы битов нам никто не подскажет. Надо их добыть из самого сигнала.
Что вообще видит приёмный тракт флоповода? А вот что. Это буквально данные, снятые с USB адаптера (или Greaseweazle или другие).
Делается это посредством PLL, ала ФАПЧ по русски. Phase Locked Loop или фазовая автоподстройка частоты. В электронике оно обычно делается посредством управляемого генератора, автомагически подстраивающегося к фронтам принимаемого сигнала. Здесь же пришлось провернуть аналогичный фокус программно. Этот алгоритм я когда-то наваял для проекта Megadrive от
tnt23 . Здесь же приспособил по месту.
После PLL в приёмнике имеем сырые биты MFM, которые еще предстоит превратить в данные юзера:
Но это на будущее, а пока что я в новоиспечённой утилите fdx сделал считывание флопика в файл в сыром формате MFM. Для архивации это идеальное решение. Разбираться в каком там формате оказался флопик можно потом. Главное - все битики в целости и сохранности. Есть такой формат файлов HFE, не то чтобы стандарт, но широко используемый в узких кругах. Придумали его изначально для аппаратных эмуляторов флопов. В частности для флоповодов Gotek есть соответствующая опенсорсная прошивка. Формат HFE признан библиотекой Конгресса США как архивный.
Пока работает только считывание флопов в файлы HFE. Запись как нибудь потом.
Кто занимался цифровыми коммуникациями, в курсе разных NRZ, NRZI и прочих манчестеров. Это разные способы кодирования информации в цифровом канале. Флопик устроен ровно как цифровой канал. Каждая отдельно взятая дорожка - как зацикленная грампластинка, с которой непрерывно сыпется сигнал с магнитной головки. Сигнал (физически намагниченность) бывает в одну сторону или в другую. Плюс или минус, а для программистов проще представить как 1 или 0. Я считал сигнал с реального флопика и визуализировал, вот как выглядят 100 микросекунд.

Называется это умным словом MFM. Как образуется такой сигнал? Правила простые. Для ясности сначала сформируем вспомогательный битовый поток, в котором в 2 раза больше битов.
- Хотим передать бит "1" - записываем 0, потом 1.
- Хотим передать бит "0" - записываем не то, что в предыдущем бите. Затем 0.
В чём прелесть такого кодирования? Имеем гарантированные изменения сигнала не реже чем каждые два бита данных. Но не чаще чем каждый бит. Другая приятность: средний уровень сигнала близкий к 0.5. Первое помогает приёмнику подстроиться к частоте сигнала. Второе даёт возможность точнее выделить фронты.
К примеру, запишем байт 0xA1.
Писать на флопик нетрудно: знай себе формируй нолики и единички по тактовому сигналу. А как быть при считывании? Границы битов нам никто не подскажет. Надо их добыть из самого сигнала.
Что вообще видит приёмный тракт флоповода? А вот что. Это буквально данные, снятые с USB адаптера (или Greaseweazle или другие).
3014, 5000, 6945, 10736, 13084, 15070, 17000, 20042, 23014, 26070, 29139, 31125, 33056, 36125, 39070, 42153, 45209, 47209, 49097, 52195, 55139, 58209, 61278, 63278, 65181, 68278, 71195, 74292, 77334, 79334, 81264, 84306, 87278, 90347, 93403, 95403, 97306, 100389, 103334, 106417, 109459, 111459, 113375, 116417, 119389, 122431, 125514, 127528, 129417, 132528, 135472, 138542, 141597, 143597, 145500, 148556, 151528, 154597, 157653, 159653, 161570, 164639, 167584, 170667, 173709, 175722, 177625, 180709, 183653, 186722, 189792, 191778, 193695, 196750, 199736, 202792, 205847, 207847, 209750, 212834, 215792, 218861, 221903, 223917, 225834, 228903, 231847, 234917, 237959, 239986, 241903, 244959, 247931, 251000, 254028, 256056, 257972, 261028, 263986, 267056, 270097, 272111, 274042, 277097, 280070, 283097, 286167, 288195, 290070, 293181, 296125, 299195, 302236, 304250, 306167, 309250, 312195, 315264, 318292, 320320, 322236, 325306, 328278, 331334, 334375, 336389, 338320, 341389, 344334, 347389, 350445, 352445, 354403, 357431, 360403, ...Это моменты времени, когда считанный сигнал с флопика меняет полярность. Время измерено в наносекундах, с точностью плюс-минус несколько (десятки) наносекунд. Чуть по разному у разных адаптеров. Из этой каши декодер должен извлечь биты MFM.
Делается это посредством PLL, ала ФАПЧ по русски. Phase Locked Loop или фазовая автоподстройка частоты. В электронике оно обычно делается посредством управляемого генератора, автомагически подстраивающегося к фронтам принимаемого сигнала. Здесь же пришлось провернуть аналогичный фокус программно. Этот алгоритм я когда-то наваял для проекта Megadrive от
После PLL в приёмнике имеем сырые биты MFM, которые еще предстоит превратить в данные юзера:
MFM: 0100010010101001Тут возникает очередная проблема: где границы байтов и секторов? Эту задачу разные производители решают по разному. К компьютерах IBM оно сделано одним образом, у Amiga другим, а в древних маках совершенно третьим. Разнообразия вагон. Технически всё решается введением "нарушений" в правила кодирования MFM, изложенные выше. Скажем, убрать один битик при кодировании байта A1. Так делает IBM в заголовке каждого сектора. Приёмник видит такие нарушения и понимает: ага, закончился предыдущий сектор и начинается новый.
данные: 1 0 1 0 0 0 0 1
Но это на будущее, а пока что я в новоиспечённой утилите fdx сделал считывание флопика в файл в сыром формате MFM. Для архивации это идеальное решение. Разбираться в каком там формате оказался флопик можно потом. Главное - все битики в целости и сохранности. Есть такой формат файлов HFE, не то чтобы стандарт, но широко используемый в узких кругах. Придумали его изначально для аппаратных эмуляторов флопов. В частности для флоповодов Gotek есть соответствующая опенсорсная прошивка. Формат HFE признан библиотекой Конгресса США как архивный.
Пока работает только считывание флопов в файлы HFE. Запись как нибудь потом.

no subject
Date: 2026-01-04 05:12 (UTC)no subject
Date: 2026-01-04 08:42 (UTC)Здесь постоянная составляющая не идеальная, но терпимая. Бывают и получше кодирования.
no subject
Date: 2026-01-04 09:39 (UTC)no subject
Date: 2026-01-04 06:14 (UTC)no subject
Date: 2026-01-04 07:23 (UTC)Eh?...
> MFM: 0100010010101001
^^^000
no subject
Date: 2026-01-04 08:38 (UTC)no subject
Date: 2026-01-04 07:43 (UTC)no subject
Date: 2026-01-04 08:46 (UTC)Архивируем флопики на уровне MFM, максимально сохраняя все биты, присутствующие на носителе. Включая разнообразные методы защиты от копирования, что народ наизобретал в то время. Имея архивную копию, уже можно разбираться, что там с секторами и контрольными суммами.
no subject
Date: 2026-01-04 09:24 (UTC)no subject
Date: 2026-01-04 11:19 (UTC)no subject
Date: 2026-01-04 12:00 (UTC)no subject
Date: 2026-01-04 13:12 (UTC)Принцип совсем другой - "легко прочесть - но сложно записать".
Причем такой фокус можно провернуть на совершенно стандартном дисководе. Один из путей - они имеют естественный разброс скорости вращения, он невелик, но измеряем и уникален. Были такие защиты.
Слабые биты - которые читаются и так, и сяк тоже можно записать на стандартном приводе. Зависит от контроллера, но именно один из наиболее распространенных, от Интел, позволял такое.
no subject
Date: 2026-01-04 13:26 (UTC)no subject
Date: 2026-01-04 13:57 (UTC)no subject
Date: 2026-01-04 14:23 (UTC)no subject
Date: 2026-01-04 14:34 (UTC)Я же вам указал, где детали реализации -
Защита от Western Security
no subject
Date: 2026-01-04 11:16 (UTC)Лучший учитель - практика. С ней и спорьте - сохраняет ли один проход MFM максимально ВСЕ биты.
no subject
Date: 2026-01-06 22:30 (UTC)no subject
Date: 2026-01-04 08:56 (UTC)PS И на гитхабе похожий проект есть.
no subject
Date: 2026-01-04 09:07 (UTC)https://hxc2001.com/docs/gotek-floppy-emulator-hxc-firmware/pages/firmware-update.html
Когда все механические флопики заржавеют от старости, перейдём на готеки. 😀
Готек с опенсорсной прошивкой любые форматы поддерживает, не только писишные.
no subject
Date: 2026-01-04 09:21 (UTC)no subject
Date: 2026-01-04 10:28 (UTC)Not drop, but corrupt.
Eg p, q, r, s get recorded as p, p nor q, q, q nor r, r, r nor s, s. Now, if p, q, r, s are 0, then the bits between them are 1, and they act as a check that all are 0. If we record q nor r as 0, then we can still check that it was meant to be 1, but being a deliberate corruption, it acts as a unique marker.