Наш магазин на eBay Наш канал в telegram

Приём и декодирование F/2F частотно-кодированных сигналов

В этой статье описаны простейшие алгоритмы приёма и декодирования F/2F частотно-кодированных сигналов c помощью микроконтроллера и персонального компьютера..

Для начала давайте разберёмся, что представляет собой F/2F кодирование и какие преимущества в плане хранения и передачи информации оно предоставляет.

F/2F кодированный сигнал

Итак. Частотным кодированием F/2F называется такой способ кодирования, при котором "1" кодируется удвоенной частотой сигнала по отношению к "0" (смотрите рисунок слева). Для того, чтобы сохранить (записать) такой сигнал на физическом носителе, достаточно поставить на носителе какие-нибудь метки на определённом расстоянии друг от друга, причём таким образом, чтобы расстояние между метками было пропорционально интервалу времени между фронтами. В зависимости от физического носителя и способа записи, метками могут быть: изменение светоотражения при записи лазерной головкой на компакт-диск, изменение полярности намагничивания при записи магнитной головкой на магнитной полосе или ленте, дырочки от дырокола на перфоленте, насечки на коре дуба и т.д.

Казалось бы: "Ну и что тут интересного?". А интересного тут на самом деле очень много. Такой способ кодирования и записи информации предоставляет следующие преимущества: 1) одинаковая длительность сигнала для "0" и "1"; 2) возможность автоматической синхронизации в процессе приёма сообщения. Рассмотрим эти преимущества подробнее:

1) Одинаковая длительность сигнала для "0" и "1" (то есть одинаковая длительность бита, независимо от состояния) очень удобна для хранения информации. В этом случае, при записи информации описанным выше способом, длина записи (а значит и физические размеры носителя) не зависит от количества нулей и единиц в записанном сообщении, а зависит только от числа записываемых бит и от размеров участка, на котором умещается один бит информации (то есть от плотности записи).

2) Возможность автоматической синхронизации в процессе приёма очень удобна при считывании информации, поскольку в этом случае нам не нужно никаких дополнительных синхронизирующих сигналов, кроме самого информационного сигнала. Нам не только абсолютно наплевать с какой скоростью производилась запись сигнала, но даже если скорость считывания изменяется во времени, то в случае, когда она не может скачком измениться более чем в полтора раза, мы можем уверенно восстановить исходный сигнал. Единственное, что нам нужно — это точно знать, с какого бита начинается сообщение — с "0" или с "1", чтобы провести начальную синхронизацию. Можно просто договориться помещать в начале сообщения один или несколько нулей или единиц для начальной синхронизации (обычно всё же используют несколько таких дополнительных синхронизирующих битов, на тот случай, если некоторое количество первых битов по каким-либо причинам не будет считано или окажется утерянным).

Давайте попробуем представить себе, как может выглядеть простейший алгоритм приёма и декодирования такого F/2F кодированного сигнала. Пусть нам нужно декодировать сигнал, подобный изображённому на рисунке вверху, но считанный при неравномерном движении головки. Пусть мы при этом точно знаем, что сигнал начинается с нулевого бита. Идея заключается в следующем:

1) С помощью контроллера измеряется время между фронтами сигнала и передаётся на компьютер.

2) На компьютере сигнал декодируется, исходя из гипотезы о том, что скорость считывания не может скачком измениться более чем в 1,5 раза.

Таким образом наша задача разбивается на две части: а) измерение временных интервалов между фронтами и передача их на ПК, б) декодирование сигнала на основе этих интервалов.

Рассмотрим отдельно обе эти части.

Часть1. Для измерения интервалов между фронтами и передачи этой информации на компьютер подойдёт обычный микроконтроллер со встроенным UART, компаратором и таймером, например, PIC16F628A. Собственно, процесс измерения временных интервалов довольно тривиален: на одну ногу компаратора подаётся опорное напряжение, равное половине амплитуды читаемого сигнала, на другую ногу — читаемый сигнал. Запускается таймер. В момент изменения уровня читаемого сигнала с "0" на "1" или с "1" на "0" происходит переключение компаратора, в результате чего генерируется прерывание. В обработчике прерывания считывается и сохраняется значение таймера, после чего таймер перезапускается, а сохранённое значение отправляется на COM-порт компьютера. На этом обработка прерывания заканчивается.

Передаваемая контроллером информация принимается на ПК любой терминальной программой (например, нашей RH_Com).

В результате мы получим набор байт, соответствующих длительностям интервалов между фронтами. В этом наборе нулевому биту будет соответствовать один байт длительности, а единичному биту — 2 байта в два раза меньшего значения ( в идеальном случае). Почему? — Снова смотрите рисунок вверху. В дальнейшем будем называть такие байты "байтами нуля" и "байтами единицы". Таким образом, ноль у нас будет соответствовать одному байту нуля, а единица — двум байтам единицы.

Алгоритм для первой части (приём контроллером F/2F кодированных сигналов)

На рисунке справа показан вариант алгоритма для реализации первой части нашей задачи.

Попробуем оценить, сигналы какой частоты позволит считывать контроллер с помощью такого алгоритма.

Поскольку сигнал сразу передаётся на компьютер (без какой-либо буферизации), а наибольшее время затрачивается именно на передачу по UART (очевидно, что сам код обработчика получится небольшим, а значит и время его обработки будет значительно меньше времени передачи по UART), то в данном случае наше условие можно сформулировать так: контроллер должен успевать закончить передачу до прихода следующего фронта.

То есть теоретический предел скорости приёма информации по такому алгоритму равен установленной скорости передачи по UART.

Алгоритм для второй части (декодирование F/2F кодированного сигнала на компьютере)

Часть 2. Собственно, вторая часть такая же банальная как и первая. Вариант алгоритма, реализующего эту часть, показан на рисунке слева. Как я уже сказал, основная идея в том, что скорость чтения не может скачкообразно измениться более чем в 1,5 раза. Итак, мы имеем в программе на компьютере строку с принятой от контроллера информацией (byte_str), каждый байт которой соответствует длительности между фронтами сигнала. Мы точно знаем, что первый байт — это байт нуля. Организуем ещё одну строку (пустую, msg_str), куда будем складывать декодированную битовую информацию в виде нулей и единиц.

Первый бит сразу запишем равным 0, а байт, определяющий его длительность, используем для синхронизации (для определения текущих значений байта нуля и байта единицы).

Далее будем в цикле просматривать последующие байты, начиная со второго, и сравнивать их с байтами нуля и единицы. Если значение текущего анализируемого байта ближе к байту нуля, то и будем считать его байтом нуля. Допишем в msg_str ноль, а значение текущего байта примем за новое значение байта нуля (а так же вычислим на его основе новое значение байта единицы). Если же значение текущего анализируемого байта ближе к байту единицы, то будем считать текущий и следующий за ним байты — байтами единицы (помните, для единицы мы получаем 2 байта интервалов между фронтами, но оба в два раза меньше нулевого байта). Допишем в msg_str единицу, а сумму текущего и следующего за ним байтов будем считать новым значением байта нуля (опять же, разделив его пополам получим также новое значение байта единицы). И так до тех пор, пока не проанализируем все байты.

Вот, собственно, и всё! После выполнения действий, описанных в алгоритме, — в строке msg_str окажется декодированный исходный сигнал в двоичной форме.

Вот здесь можно почитать про то, как самостоятельно изготовить простейший считыватель магнитной полосы пластиковых карт.

Добавить комментарий