Oberon space
General Category => Общий раздел => Тема начата: valexey_u от Сентябрь 22, 2012, 05:59:48 pm
-
Почитал я тут последние топики, и решил что эту парсерно-автоматную тематику нужно как-то разбавить чем-то более осязаемым, так что ловите еще одну задачку.
У задачки есть один нюанс - мне интересней всего увидеть идиоматическое решение на Обероне-1/07/12, то есть решение на этих языках тех, кто на Обероне (или его производных вроде КП) имеет опыт написание приложений (и желательно не на досуге забавы для, а для чего-то продакшинообразного).
Итак задачка: к нам идет поток данных (например с ком-порта, но это не важно), эти данные - грубо говоря амплитуда сигнала (интенсивность света, или громкость звука, по частотам там информации нет). Частоту сэмплирования мы знаем (можем считать, для определенности, что у нас 100 сэмплов в секунду). Ну и собственно задача - дешифровать посылку которая закодирована азбукой морзе. Думаю на картинке оно будет нагляднее:
(https://lh5.googleusercontent.com/-qgQ79oKwXLc/UF3pWndUPuI/AAAAAAAAAOw/X4P5lBaOYJU/s658/sos_g.png)
(https://lh5.googleusercontent.com/-5JuhDKSjFV4/UF3pWtA1WxI/AAAAAAAAAOs/Vnu_yt6ibok/s536/sos_b.png)
На обоих изображениях построен график по полученным данным. На обоих картинках сигнал SOS, только во втором случае, как видим, уровень сигнала плавал (ну и передатчики/генераторы сигнала были разные).
По мере дешифрации понятное дело нужно информацию выводить скажем через какой-нибудь модуль Out. Поток данных бесконечный, поэтому дождаться конца, а потом дешифровать все одним скопом не выйдет.
Возможные упрощения задачи (собственно которыми, видимо, нужно воспользоваться для первого "релиза", да, чем быстрее релиз первый, тем лучше):
1) Мы знаем темп передачи данных. То есть знаем длительность точки, тире и пауз между ними. Эти длительности зашиты в передатчике.
2) Можно считать что в первой версии пользователь вполне согласен вручную подстраивать декодер выставляя уровень сигнала (то есть в первом примере он скорее всего выставил бы, что все что выше 90та это сигнал (точка, или тире))
3) Можно считать что уровень сигнала у нас либо не плавает либо плавает слабо (не будет той каки что на втором графике). Но сам уровень сигнала мы не знаем (но см. пункт 2).
Вроде бы все. Если есть вопросы - задавайте.
Во вложении примеры данных (первая колонка - номер сэмпла, вторая колонка - сами данные).
Напомню, что интересней всего увидеть реализацию на идиоматическом Обероне (1/07/12) тех кто на Обероне пишет. Но конечно принимаются решения и на других языках от других людей :-)
-
Архитектурно я бы организовал так:
MODULE Morze;
CONST
short* = FALSE; long* = TRUE;
TYPE
Decoder* = POINTER TO ABSTRACT RECORD END;
Writer* = POINTER TO ABSTRACT RECORD END;
PROCEDURE (w: Writer) Write* (sign: BOOLEAN), NEW, ABSTRACT;
PROCEDURE (d: Decoder) ConnectTo* (w: Writer), NEW, ABSTRACT;
PROCEDURE (d: Decoder) ProcessSample* (x: BYTE), NEW, ABSTRACT;
PROCEDURE (d: Decoder) Config* (VAR settings: ANYREC), NEW, ABSTRACT;
END Morze.
Decoder - реагирующая на очередной сэмпл "машина состояний" с памятью. И "играть" с тем, что она там помнит и в какой момент переходит между состояниями. Конфигурирование может быть разным для разных реализаций.
В случае (1) Алексея знать длину пауз не нужно, это уж избытгочная роскошь. Можно для простейшего случая взять такой конфиг:
SimpleSettings* = RECORD
signLevel*: BYTE;
minShortLength, minLongLength: INTEGER (* в сэмплах *)
END;
Однако этот случай уже будет плевать на длину пауз и, кроме того, будет устойчив к совсем коротким "артефактам", короче, чем minShortLength.
И состояние Decoder-а:
currentSample: INTEGER;
state: (back, signal);
signalBeg: INTEGER
PROCEDURE (d: SimpleDecoder) ProcessSample* (x: BYTE);
VAR len: INTEGER;
BEGIN
INC(d.currentSample);
CASE d.state OF
| back:
IF x > d.conf.signLevel THEN
d.state := signal; d.signalBeg := currentSample
END
| signal:
IF x < d.conf.signLevel THEN
len := d.currentSample - d.signalBeg;
IF len > d.conf.minLongLength THEN
d.out.Write(long)
ELSIF len > d.conf.minShortLength THEN
d.out.Write(short)
END;
d.state := back
END
END
END ProcessSample;
-
Да, спасибо за общую архитектурную раскладку.
Длительность пауз, на сколько я помню, регламентирована, поэтому я и упомянул и их тоже.
И хотелось бы получить полное решение (желательно на обероне, так мне будет проще проверить/понять/протестировать, иначе какое-нибудь решение на КП мне придется вручную, в меру своего кривого понимания, транслировать в Оберон (не Оберон-2)). Меня кроме архитектуры и основных алгоритмов интересуют также нюансы реализации всего этого на Обероне.
-
Я пас, времени нет.
И не вижу я там дальше никаких нюансов реализации.... Если потом не вести речь про достижение сверхбыстродействия (когда не допустимо каждый сэмпл сообщать вызовом процедуры).
Есть чисто нюансы обработки сигнала (логика декодера - его состояния и Decode).
Касательно чистого Оберона - ну, ООП процедурными полями будешь имитировать, а как же...
-
Я пас, времени нет.
И не вижу я там дальше никаких нюансов реализации.... Если потом не вести речь про достижение сверхбыстродействия (когда не допустимо каждый сэмпл сообщать вызовом процедуры).
Есть чисто нюансы обработки сигнала (логика декодера - его состояния и Decode).
Точечки и тире надо еще в буквы сложить. И нужно уметь восстанавливаться после сбоя (ложные срабатывания/распознования точек-тире будут точно).
-
Есть чисто нюансы обработки сигнала (логика декодера - его состояния и Decode).
Если я правильно понял, Декодер у тебя это как раз то, что собирает из точек и тире буквы. И вот это то и есть самое интересное (процентов 65-70 от общего интересного). В том числе реализация :-)
Дергать на каждый сэмпл функцию можно конечно. Это достаточно дешево сейчас практически везде (ибо у нас всего 100 сэмплов в секунду).
-
По мне, так самая сложная часть задачи заключается в декодировании сигнала с помехами, то есть получении восстановленной битовой последовательности. А расшифровка Морзе - уже дело техники.
-
По мне, так самая сложная часть задачи заключается в декодировании сигнала с помехами, то есть получении восстановленной битовой последовательности. А расшифровка Морзе - уже дело техники.
Это не совсем так.
Во первых см. упрощения 1,2,3 задачи. они взяты не от балды, а из практики. Во вторых даже если у тебя есть идеальный сигнал (а с упрощениями оно примерно так и выходит), то все равно никто не гарантирует, что передача не прервется на половине буквы (банально вырубили передатчик до окончания передачи) и не продолжится затем с половины другой буквы. При этом, ясное дело, программа не должна впасть в маразм, она должна (возможно пропустив сколько-то точек-тире) продолжить корректно расшифровывать передачу.
Ясное дело, что поле первого "релиза" можно будет подумать как добавить помехозащищенность. Но вначале нужно обязательно выпустить релиз упрошенной версии. Лучше 20 раз по разу, чем ни разу 20 раз :-)
-
Я никогда не занимался цифровой фильтрацией, поэтому то, что изложу – взгляд абсолютного дилетанта.
Если все сделано по уму, последовательность точек и тире формируется в передатчике не абы как, а укладывается в исходный меандр, который задается генератором тактовой частоты. Поэтому входной сигнал надо распараллелить – один канал должен восстанавливать этот исходный меандр, второй – фильтровать исходный сигнал, в частности, убирать постоянную и низкочастотную составляющую. Чтобы отсчеты были положительными и отрицательными, и, в среднем, не плавали вверх-вниз относительно нуля.
Затем, имея опорный сигнал, делаем выборки из отфильтрованного. Если за период опорного сигнала было больше превышений нуля, то пишем в выходной буфер 1, если меньше – пишем -1. Если болтаемся вблизи нуля, можно записать 0 – неуверенный символ.
Затем, с помощью КА, измеряем длительности непрерывных отсчетов в буфере, например, -1 длиной 10 считаем разделителем символов, +1 длиной 3 и больше – тире, и т. д.
Затем распознаем то, что получилось между разделителями символов.
-
Итак задачка:
Во-первых, я уверен на 99%, что задачка имеет простое/шаблонное аппаратное решение. Что-то типа сдвигового регистра (по-моему так называется) + минимальная аналоговая обвязка для сглаживания/нормирования сигнала. Если уж ты взял в руки паяльник - почитай там какой-нибудь ликбез по цифровой электронике.
Во-вторых, все упирается в характер конкретного сигнала (и помех). Т.е., тебе самому медитировать/экспериментировать над этим сподручнее. Ну и ликбез по цифровым фильтрам (хотя ты вроде и так в этой теме хорошо разбираешься). Понятно, что там будет память на сколько-то последних сэмплов + эвристики.
Оберон здесь, как и другой ЯП - постольку поскольку. Ты давай пиши, а эксперты-оберонщики поправят :)
-
Итак задачка:
Во-первых, я уверен на 99%, что задачка имеет простое/шаблонное аппаратное решение. Что-то типа сдвигового регистра (по-моему так называется) + минимальная аналоговая обвязка для сглаживания/нормирования сигнала. Если уж ты взял в руки паяльник - почитай там какой-нибудь ликбез по цифровой электронике.
У меня пока нет паяльника :-)
И нет, простого аппаратного решения тут нет. Собственно вот пример работы детектора:
http://m.youtube.com/watch?v=7wdtTxa_YSc
Как видим, там та же самая ручная подстройка уровня. Единственное что у них лучше - сигнал можно выделять не только по амплитуде, но и по частоте. А у нас тут информации по частоте нет.
Во-вторых, все упирается в характер конкретного сигнала (и помех). Т.е., тебе самому медитировать/экспериментировать над этим сподручнее. Ну и ликбез по цифровым фильтрам (хотя ты вроде и так в этой теме хорошо разбираешься). Понятно, что там будет память на сколько-то последних сэмплов + эвристики.
Да не, у меня на самом деле есть какое-то решение. :-)
Кроме того, с упрощениями 1,2,3 та часть задачи, на которой вы все сосредоточились, скорее всего оказывается решена Ильей. Нужно лишь дополнить его решение декодером.
Оберон здесь, как и другой ЯП - постольку поскольку. Ты давай пиши, а эксперты-оберонщики поправят :)
А вот и нет. У Оберона я вижу ряд нюансов, и мне интересно как они будут отражены в коде тех, кто умеет на нем писать.
PS. Господа, вы переусложняете и откровенно игнорируете условия задачи :-)
-
Я никогда не занимался цифровой фильтрацией, поэтому то, что изложу – взгляд абсолютного дилетанта.
Если все сделано по уму, последовательность точек и тире формируется в передатчике не абы как, а укладывается в исходный меандр, который задается генератором тактовой частоты.
Ну-у. В принципе да, почему нет? С другой стороны этот меандр может быть весьма высокочастотным, либо низкочастотным и при этом не кратным нашим 100 сэмплам.
Поэтому входной сигнал надо распараллелить – один канал должен восстанавливать этот исходный меандр, второй – фильтровать исходный сигнал, в частности, убирать постоянную и низкочастотную составляющую. Чтобы отсчеты были положительными и отрицательными, и, в среднем, не плавали вверх-вниз относительно нуля.
Ну, в первой версии от нас этого не требуется, а во-второй версии, да. Фильтрацию можно прикрутить. Но у нас есть проблема - характерные частоты "помех' (плавание уровня) в принципе не далеко лежат от частоты полезного сигнала. Поэтому полностью фильтрацией избавиться от плавания туда-сюда не получится.
Затем, с помощью КА, измеряем длительности непрерывных отсчетов в буфере, например, -1 длиной 10 считаем разделителем символов, +1 длиной 3 и больше – тире, и т. д.
Затем распознаем то, что получилось между разделителями символов.
А вот этой части нам сейчас как раз и не хватает. На обероне.
-
Кстати, вскрытие показало, что первый образец (там где хорошо) был закодирован невалидно (там совершенно не правильные интервалы внутри буквы и между буквами). Так что вот новый образец, где уровень в общем то не плавает, и при этом закодирован верно. Точнее даже два образца (первый - одно слово, второй - два слова).
-
Оставлю ка я эту картинку здесь. Вдруг кто не видел еще:
(http://upload.wikimedia.org/wikipedia/commons/b/b5/International_Morse_Code.svg)
-
Хе, неожиданное открытие :)
Я всегда считал, что код Морзе префиксный - и паузы между буквами не нужны :)
-
valexey_u, издеваетесь что ли?
Да это не данные, а малина. Какие тут могут быть проблемы, какой, нах, Oberon.
Вот что выдает программка из 50 строк брутто (второй файл):
Пауза
тире тире Пауза
тире тире тире Пауза
тире точка точка Пауза
точка точка тире Пауза
точка тире точка точка Пауза
точка Пауза
тире тире Пауза
тире тире тире Пауза
точка тире точка Пауза
точка точка точка Пауза
точка
И что, типа есть проблемы с распознаванием этой туфты?
-
Хе, неожиданное открытие :)
Я всегда считал, что код Морзе префиксный - и паузы между буквами не нужны :)
А ты легко префиксный код в уме в реалтайме, на слух, без пауз между буквами, расшифруешь? :-) Морзе таки делался для людей а не для машин ( кодер - человек, декодер тоже).
Кстати, что там у префиксных кодов с декодингом потока после искажений (прилетело то, чего не было) и потерь (в реальной жизни это есть всегда это вам не архив разархивировать :-) ).
-
valexey_u, издеваетесь что ли?
Да это не данные, а малина. Какие тут могут быть проблемы, какой, нах, Oberon.
Вот что выдает программка из 50 строк брутто (второй файл):
Пауза
тире тире Пауза
тире тире тире Пауза
тире точка точка Пауза
точка точка тире Пауза
точка тире точка точка Пауза
точка Пауза
тире тире Пауза
тире тире тире Пауза
точка тире точка Пауза
точка точка точка Пауза
точка
И что, типа есть проблемы с распознаванием этой туфты?
Какая программа?
Вообще, поясню - я хочу для начала простую программу на обероне которая может декодировать (не до уровня точек и тире, а до уровня слов) эту самую малину. Это будет отправная точка. Затем задача будет усложняться, проследим эволюцию исходника.
-
Какая программа?
Ну, набросал на C#. Даже стыдно показывать.
Я так и не понял, какие проблемы с Обероном. Или просто лень замучала.
-
Какая программа?
Ну, набросал на C#. Даже стыдно показывать.
Я так и не понял, какие проблемы с Обероном. Или просто лень замучала.
Ну, ок. Если тебе хочется чего-то более сложного, то вот тебе еще один файлик.
А какие проблемы с Обероном мы не увидим пока не будет решения на Обероне :-)
-
Какая программа?
Ну, набросал на C#. Даже стыдно показывать.
Я так и не понял, какие проблемы с Обероном. Или просто лень замучала.
Ну, ок. Если тебе хочется чего-то более сложного, то вот тебе еще один файлик.
А какие проблемы с Обероном мы не увидим пока не будет решения на Обероне :-)
Да, разбор этого случая вообще говоря не обязателен в базовом решении (на Обероне, да). Но если кому-то программировать слишком скучно ту самую "малину", то можно заморочиться этим вот.
-
Ну, ок. Если тебе хочется чего-то более сложного, то вот тебе еще один файлик.
В чем сложность-то, что есть разделители слов?
Разделитель слов
точка точка тире Разделитель слов
тире тире Пауза
точка тире точка Разделитель слов
точка тире тире точка Пауза
точка Пауза
тире Пауза
тире точка Разделитель слов
точка тире Пауза
точка тире точка точка Пауза
тире тире Пауза
точка тире Пауза
тире точка Пауза
точка Пауза
тире тире тире Пауза
точка точка точка тире
-
Ну, ок. Если тебе хочется чего-то более сложного, то вот тебе еще один файлик.
В чем сложность-то, что есть разделители слов?
Сложность в том, что ты даже не увидел там проблем :-)
Расшифруй пожалуйста полностью. Да хоть руками.
-
Я, конечно, не прочь иногда заниматься х%№;%;№, но не до такой же степени :)
-
Я, конечно, не прочь иногда заниматься х%№;%;№, но не до такой же степени :)
Вот поэтому эта часть программы и нужна, чтобы ручками не делать :-)
-
Я, конечно, не прочь иногда заниматься х%№;%;№, но не до такой же степени :)
Если я правильно переве твою дешифровку в морзе, то у тебя получилось нечто вроде такого:
..- -- .-. .--. . - -. .- .-.. -- .- -. . --- ...-
Что, если верить вот этому онлайн-декодеру: http://webnet77.com/cgi-bin/helpers/morse.pl
расшифровывается как:
U MR PETN ALMANEOV
Что несколько не то, что передавалось :-) Таким образом, твой недоделанный декодер (ибо самого интересного в нем таки нет) во-первых неправильно дешифровал сообщение, и кроме того, даже не сообщил бы пользователю что возникли проблемы с декодингом и декодировка может содержать ошибки.
-
Что несколько не то, что передавалось :-)
Вот в это я "Не верю"(c). Слишком уж хороша форма сигнала, если смотреть на нее глазами. В результате сильных искажений картинка была бы другая.
Либо аппаратура работает с точностью до фантазирования. Тогда только в морг.
-
Таким образом, твой недоделанный декодер (ибо самого интересного в нем таки нет) во-первых неправильно дешифровал сообщение, и кроме того, даже не сообщил бы пользователю что возникли проблемы с декодингом и декодировка может содержать ошибки.
При такой постановке задачи (первый пост) ожидать, что кто-то на Обероне(!) сделает то, что здесь ожидается - это 5.
Как постановщик задач, ты даже vlad'а переплюнул.
Мои поздравления.
-
Что несколько не то, что передавалось :-)
Вот в это я "Не верю"(c). Слишком уж хороша форма сигнала, если смотреть на нее глазами. В результате сильных искажений картинка была бы другая.
Либо аппаратура работает с точностью до фантазирования. Тогда только в морг.
Аппаратура работает четко. Я же упоминал, что потера сигнала может быть не по вине аппаратуры и не из за шумов.
Представь себе такую схему: передаем данные азбукой морзе не по радио, а через свет. Грубо говоря у нас мигающий фонарик. Между приемником и передатчиком в момент передачи "точки" может оказаться постороннее тело (напримример птица, машина или что-то еще) и затенить приемник. В результате точка пропадет, как и не было. При этом амплитуда сигнала отличная, шумов нет.
И такие вещи, в большенстве случаев, можно детектировать (но не корректировать).
-
Таким образом, твой недоделанный декодер (ибо самого интересного в нем таки нет) во-первых неправильно дешифровал сообщение, и кроме того, даже не сообщил бы пользователю что возникли проблемы с декодингом и декодировка может содержать ошибки.
При такой постановке задачи (первый пост) ожидать, что кто-то на Обероне(!) сделает то, что здесь ожидается - это 5.
Как постановщик задач, ты даже vlad'а переплюнул.
Мои поздравления.
А я и не ожидал что кто-то это сделает сразу. Задача многоступенчатая, в исходном условии задачи обозначены примерно первые две ступени. По ступенькам предполагалось постепенно подниматься, а не сразу на скалу лезть без ступенек. Ты пожаловался, что задача тебе слишком простая, тебе скучно, ну я и показал одну из следующих ступенек (специально, для других, пояснив, что с этим пока бороться не нужно, пока нужно простейшее решение для первой ступеньки-малины, на Обероне, да).
Кроме того, ты так и первую ступеньку даже на шарпе не одолел. Нужен таки полный декодер, а не выделение точек и тире из приехавшего сигнала.
У меня такое ощущение, что целиком условие задачи воспринял только Илья Ермаков (то есть он хотя бы в своем наброске хотя бы обозначил и обработчик сэмплов, и декодер который из точек и тире собирает буквы).
-
Строг говоря, задача к азбуке Морзе имеет очень опосредованное отношение, это задача декодирования цифровых данных, передаваемых аналоговым методом.
Могу продать готовые модули почти на обероне )))
-
Строг говоря, задача к азбуке Морзе имеет очень опосредованное отношение, это задача декодирования цифровых данных, передаваемых аналоговым методом.
Могу продать готовые модули почти на обероне )))
А fabulous Сириус... когда, кстати, его "рассекречивание" произойдет?
-
А fabulous Сириус... когда, кстати, его "рассекречивание" произойдет?
Это не только от меня зависит. К тому же сейчас готовится 4-я ревизия языка, довольно много изменений, поэтому компиляторы переписываются, освобождаясь попутно от не лицензированного кода. Именно 4-я ревизия будет открыта.
-
А fabulous Сириус... когда, кстати, его "рассекречивание" произойдет?
Это не только от меня зависит. К тому же сейчас готовится 4-я ревизия языка, довольно много изменений, поэтому компиляторы переписываются, освобождаясь попутно от не лицензированного кода. Именно 4-я ревизия будет открыта.
Дайте знать , пожалуйста , как только... очень интересно увидеть и пощупать "ведомственное" изделие... то что я видел (из разработанного на шаболовках).. дерьмо (с точки зрения пользователя...).
-
Могу продать готовые модули почти на обероне )))
Не прокатит если НЕ ПОНИМАЕШЬ какой фильтр (или их последовательность) нужно применить...- то это как мертвому припарка... :D
-
Да, в коде Морзе паузы между буквами таки значение имеют... :)
Насчёт как всё организовано - в общем случае ручками... без привязки к какому бы то ни было меандру...
Вот для таких условий интересно было бы видеть решение...
-
Могу продать готовые модули почти на обероне )))
Не прокатит если НЕ ПОНИМАЕШЬ какой фильтр (или их последовательность) нужно применить...- то это как мертвому припарка... :D
легко. мы это используем для удаленного управления, для приема цифровых пакетов, передаваемых аналоговым способом. И хоть фотодиодами принимай, хоть фоторезистором, хоть фасеткой, хоть ...
-
Да, в коде Морзе паузы между буквами таки значение имеют... :)
разделители имеют значение везде - между тиками, между буквами и между словами. декодировать такое - очень легко
-
Да, в коде Морзе паузы между буквами таки значение имеют... :)
разделители имеют значение везде - между тиками, между буквами и между словами. декодировать такое - очень легко
А dummy decoder на Обероне написать слабо? Простейший случай (с упрощениями 1,2,3), но полный, вплоть до букв/слов :-)
-
Пусть для передачи используются два сигнала - высокий, назовем его "тик" и низкий, назовем его "так". "Таки" являются разделителями "тиков". В Морзе точка - это тик, за которым сразу следует так, а тире, по длительности это три тика(точки), за которым следует так, т.е., например буква S(три точки) = ТикТакТикТакТикТак (101010), а буква O(три тире) = ТикТикТикТакТикТикТикТакТикТикТикТак (111011101110). Разделитель между знаками букв - один Так, между буквами 3 Така, между словами 7 Таков. Сообщение SOS...---..., таким образом будет передано как-то так:
...Так] = разделитель между буквами
[ТикТакТикТакТик] = "S"
[ТакТакТак] = разделитель между буквами
[ТикТикТик][Так][ТикТикТик][Так][ТикТикТик] = "O"
[ТакТакТак] = разделитель между буквами
[ТикТакТикТакТик] = "S"
[ТакТак... = разделитель между буквами
Учитывая, что Тик и Так это высокий и низкий уровень сигнала (наличие/отсутствие, 1/0), то при всяких вышеуказанных допущениях и упрощениях, больших сложностей с декодированием нет. Преобразование полученной последовательности в букву можно банально по таблице перевода
-
Учитывая, что Тик и Так это высокий и низкий уровень сигнала (наличие/отсутствие, 1/0), то при всяких вышеуказанных допущениях и упрощениях, больших сложностей с декодированием нет. Преобразование полученной последовательности в букву можно банально по таблице перевода
Для первого варианта - можно. Я хочу увидеть как реализация этого простого варианта будет выглядеть на Обероне.
-
Учитывая, что Тик и Так это высокий и низкий уровень сигнала (наличие/отсутствие, 1/0), то при всяких вышеуказанных допущениях и упрощениях, больших сложностей с декодированием нет. Преобразование полученной последовательности в букву можно банально по таблице перевода
Для первого варианта - можно. Я хочу увидеть как реализация этого простого варианта будет выглядеть на Обероне.
Если разделить задачу на инженерную (распознавание сигнала и вывод битовой последовательности в некоторый канал) и программистскую (расшифровку Морзе-последовательности в читаемые фразы), то что для тебя представляет наибольший интерес?
-
Учитывая, что Тик и Так это высокий и низкий уровень сигнала (наличие/отсутствие, 1/0), то при всяких вышеуказанных допущениях и упрощениях, больших сложностей с декодированием нет. Преобразование полученной последовательности в букву можно банально по таблице перевода
Для первого варианта - можно. Я хочу увидеть как реализация этого простого варианта будет выглядеть на Обероне.
Если разделить задачу на инженерную (распознавание сигнала и вывод битовой последовательности в некоторый канал) и программистскую (расшифровку Морзе-последовательности в читаемые фразы), то что для тебя представляет наибольший интерес?
Прямо сейчас - программистская часть, потому как первая задача для примитивного случая уже вроде бы решена Ильей. То есть нужно вторую часть и соединить её с первой (что тоже програмистская часть работы).
На следующих итерациях вылезет опять инжерерно-dsp'шная часть, но и программисту найдется чем заняться.
-
Далее, с полным основанием мы можем предположить, что длительность Тика и Така равны.
Сигнал имеет устоячивую прямоугольную форму, т.е. как-то так:
__ __ __ __
| | | | | | | |
| | | | | | | |
а) _| |__| |__| |__| |_
а не так
/| /| /| /|
/ | / | / | / |
б) _| |__| |__| |__| |_
или даже так
/\ /\ /\ /\
/ \ / \ / \ / \
в) _| |__| |__| |__| |_
Т.е. в случае а), в отличии от б) и в), мы можем с большой долей уверенности отнести полученное значение к Тику или Таку.
Теперь о приемнике. Каждое чтение мы назовем Тактом. На каждом такте чтения мы можем попасть на любой участок Тика или Така. Понятно, что если частоты передатчика и примника несинхронизированны, то мы можем некоторое время попадать только на Тики или только на Таки. Определить, что мы прочитали можно только при смене уовня сигнала. Принимаем мы с некоторой частотой, и пока уровень сигнала не изменится, мы считаем, что принимаем один знак. Приняв Разделитель мы точно знаем - знак закончился, а проанализировав длительность Разделителя мы узнаем, может уже буква закончилась или даже слово.
Если взять за основу последний приложенный файл http://oberspace.dyndns.org/index.php/topic,338.msg9063.html#msg9063
Циферки в первом столбце - это как я понимаю, номер такта, в правом - уровень сигнала.
Вплоть до 530-го Такта мы не знаем ни что принимаем (не знаем, высокий это уровень или низкий, если высокий, то точка или тире, потому что и частоту не знаем...), но прием фиксируем.
На 530-м уровень возрастает и мы сразу понимаем, что раньше был разделитель, соотвественно, отмечаем это, фиксируем значения, дальше принимаем Такты. Тактами
530-541 - мы принимаем Тик(Тики), но пока не знаем, Точка это или Тире.
С 542-552 - низкий уровень- Так(Таки), по длительности они примерно равны, поэтому можем предположить, что это было либо ТикТак, либо ТикТикТикТакТакТак, т.е. либо Точка, за котрой средует разделитель между знаками буквы, либо Тире, за которым следует разделитель между буквами.
Читаем дольше
530 - 541 (11 Тактов) Тик
542 - 552 (10 Тактов) Так
553 - 563 (10 Тактов) Тик
564 - 575 (11 Тактов) Так
Начиная с 576 мы начинаем принимать высокий сигнал, и принимаем примерно 30 Тактов, причем к концу сигнал начинает падать, но на этом шаге мы знаем, что первый Тик был именно Тиком, первый Так именно Таком, определяем их длительность в Тактах. Понимаем, что на 576-606 приняли Тире, т.е. ТикТикТик
576 - 606 (30 Тактов) ТикТикТик
Также понимаем, что сигнал начал портиться, но к этому моменту мы уже знаем длительность Точки, Тире и Разделителей, и можем более уверенно принимать далее.
Далее примерно с 607-го Такта идет низкий уровень и мы, учитывая неуверенный прием отсчитываем с в сравнении с примерными длительностями Разделителей Так(~10-11 Тактов) для знака ТакТакТак(~30-33 Тактов) для буквы и ТакТакТакТакТакТакТак(~70-77 Таков) для Разделителя слова.
Итак, начали с 607-го, прошли 617-й+-, значит не знак, прошли 637-й+-, значит не буква, бежим дальше, проходим и 677..-й Такт, нифига нету, только на 723-ем Такте уровень существенно возрос (722-607 = 115, какие-то сбои, но учитывая разницу 722-677= 45, можно будет в дальнейшем восстановить, но дальше опять читаем нормально
723-757 (34 Такта DIV 10 ) = ТикТикТик - Тире
758-768 (10 Тактов)= Так
769-802 (33 DIV 3) = ТикТикТик
[code]
Т.е. на данный момент мы приняли
___ТикТакТикТакТикТикТикТакТак??ТикТикТикТакТикТикТик
..- ??--
-
Decoder - реагирующая на очередной сэмпл "машина состояний" с памятью. И "играть" с тем, что она там помнит и в какой момент переходит между состояниями. Конфигурирование может быть разным для разных реализаций.
А зачем этому автомату память? Разве собственно самого состояния не достаточно?
-
Да, еще картинка, вдруг кто не видел, и вдруг она поможет написать декодер
(ссылка на картинку: http://upload.wikimedia.org/wikipedia/commons/c/ca/Morse_code_tree3.png ):
(http://upload.wikimedia.org/wikipedia/commons/c/ca/Morse_code_tree3.png)
-
А что, накопить точки и тире до паузы и получить символ из хеш-таблицы религия не позволяет?
-
А что, накопить точки и тире до паузы и получить символ из хеш-таблицы религия не позволяет?
Ну попробуй сделать. На Обероне :-)
PS. Давеча товарисч один плакался что в C# нет HashSet (под WP7).
-
ну нет в Обероне проблемы накопить двоичные 1 и 0, а точка и тире это и есть 1 и 0, или 0 и 1, как захочешь. устанавливай для каждой 1-цы нужны бит в SET'е, например, даже сдвигать ничего не нужно
-
ну нет в Обероне проблемы накопить двоичные 1 и 0, а точка и тире это и есть 1 и 0, или 0 и 1, как захочешь. устанавливай для каждой 1-цы нужны бит в SET'е, например, даже сдвигать ничего не нужно
Вот про set'ы идея действительно хорошая.
Но я не понял почему сдвигать ничего не нужно. ".-" это не то же самое что "-.".
Кроме того, что делать если у нас в SET (32 бита) не влезло?
-
Да, еще картинка, вдруг кто не видел, и вдруг она поможет написать декодер
Только что сегодня вспоминал про эту картинку когда задумался, а как же в правильных языках извернуться , чтобы из тире-точек буковку получить :)
-
И всё обошлось одной строкой символов и вычисляемым смещением
-
Но я не понял почему сдвигать ничего не нужно. ".-" это не то же самое что "-.".
Кроме того, что делать если у нас в SET (32 бита) не влезло?
зачем вращать? читаешь сигнал ты всегда с одной стороны, в сет ты накапливаешь точки и тире всегда с одной стороны и только одного символа. То что они получатся задом-наперед не страшно - там вообще байта достаточно, а для байта таблица конвертации 256, не имеет значения с младшего бита или старшего учитывать, они же все с одной стороны упакованы.
-
Чтобы небыло недопонимания. В SET мы накапливаем не Такты, не Тики и Таки, а а уже распознанные Знаки Символа - точки и тире
-
Но я не понял почему сдвигать ничего не нужно. ".-" это не то же самое что "-.".
Кроме того, что делать если у нас в SET (32 бита) не влезло?
зачем вращать? читаешь сигнал ты всегда с одной стороны, в сет ты накапливаешь точки и тире всегда с одной стороны и только одного символа. То что они получатся задом-наперед не страшно - там вообще байта достаточно, а для байта таблица конвертации 256, не имеет значения с младшего бита или старшего учитывать, они же все с одной стороны упакованы.
На счет переполнения: к нам вполне может прилететь подряд 100 точек. Да, это не валидный код морзе, но такое может случиться.
На счет накопления: в обероне же нельзя сделать так:
VAR
acc : SET;
i : INTEGER; (* i - позиция символа, она растет *)
BEGIN
acc := acc + {i};
END;
-
Если хочется вообще весь сигнал загнать в SET'ы, то понятно, что это ARRAY OF SET и процедуры для доступа с произвольному биту/битам, в А2 что-то подобное есть, но перевести на ТруОберон не проблема.
-
Как-то не понятно с SETами, каким образом 0 от 00 к примеру собираетесь отличить? Или я совсем не в теме:)
-
Если хочется вообще весь сигнал загнать в SET'ы, то понятно, что это ARRAY OF SET и процедуры для доступа с произвольному биту/битам, в А2 что-то подобное есть, но перевести на ТруОберон не проблема.
Для начала мне хочется хотя бы в 32битный SET нормально загнать :-) Ниужели придется делать как то так?
VAR
acc : SET;
i : INTEGER; (* i - позиция символа, она растет *)
BEGIN
CASE i OF
0: acc := acc + {0};
| 1: acc := acc + {1};
| 2: acc := acc + {2};
| 3: acc := acc + {3};
| 4: acc := acc + {4};
| 5: acc := acc + {5};
| 6: acc := acc + {6};
| 7: acc := acc + {7};
| 8: acc := acc + {8};
| 9: acc := acc + {9};
| 10: acc := acc + {10};
| 11: acc := acc + {11};
| 12: acc := acc + {12};
| 13: acc := acc + {13};
| 14: acc := acc + {14};
| 15: acc := acc + {15};
| 16: acc := acc + {16};
| 17: acc := acc + {17};
| 18: acc := acc + {18};
| 19: acc := acc + {19};
| 20: acc := acc + {20};
| 21: acc := acc + {21};
| 22: acc := acc + {22};
| 23: acc := acc + {23};
| 24: acc := acc + {24};
| 25: acc := acc + {25};
| 26: acc := acc + {26};
| 27: acc := acc + {27};
| 28: acc := acc + {28};
| 29: acc := acc + {29};
| 30: acc := acc + {30};
| 31: acc := acc + {31};
END
END;
Да, а бесконечный SET не поможет. То есть если к нам прилетело много точек, то в этом случае у нас просто кончится память.
-
На счет переполнения: к нам вполне может прилететь подряд 100 точек. Да, это не валидный код морзе, но такое может случиться.
А кто сказал, что будет легко? получили разрыв между буквами, сбросили все биты, пробежали до конца Сета, сбросили все биты, ждем разделитель между буквами/словами, все равно дефективная передача, не распознали начали снова...
На счет накопления: в обероне же нельзя сделать так:
Ну к примеру CASE используй или LONGINT и множитель соответсвующий
-
Как-то не понятно с SETами, каким образом 0 от 00 к примеру собираетесь отличить? Или я совсем не в теме:)
Набор точек-тире это SET + INTEGER в котором лежит число точек/тире в этом сете.
-
Как-то не понятно с SETами, каким образом 0 от 00 к примеру собираетесь отличить? Или я совсем не в теме:)
У нас же счетчик битов есть, если загнали 2 тире, то ясно, что 00 это два тире
-
Я где-то встречал "Разработки на Глаголе", там очень подробно с примерами показано было как имитировать с помощью СЕТов логические операции, устанавливать/сбрасывать произвольные биты, учитывая, что Глагол это плохо переведенный Оберон, но там все одинаково
-
Я где-то встречал "Разработки на Глаголе", там очень подробно с примерами показано было как имитировать с помощью СЕТов логические операции, устанавливать/сбрасывать произвольные биты, учитывая, что Глагол это плохо переведенный Оберон, но там все одинаково
Ну, в принципе можно и на INTEGER'ах сделать. Умножение на 2 и целочисленное деление на 2 никто не отменял.
-
вот код из А2 для BitSets, где data = POINTER TO ARRAY OF SET
PROCEDURE SetBit* (pos: LONGINT; value: BOOLEAN);
BEGIN
ASSERT (pos >= 0); ASSERT (pos < size);
IF value THEN
INCL (data[pos DIV Elements], pos MOD Elements);
ELSE
EXCL (data[pos DIV Elements], pos MOD Elements);
END;
END SetBit;
PROCEDURE GetBit* (pos: LONGINT): BOOLEAN;
BEGIN
ASSERT (pos >= 0); ASSERT (pos < size);
RETURN pos MOD Elements IN data[pos DIV Elements];
END GetBit;
PROCEDURE SetBits* (startPos, bits, value: LONGINT);
VAR adr: SYSTEM.ADDRESS;
BEGIN
ASSERT (startPos >= 0); ASSERT (startPos+bits <= size);
IF (bits = 8) & (startPos MOD 8 = 0) THEN
adr := SYSTEM.ADR(data[0])+startPos DIV 8;
SYSTEM.PUT(adr, CHR(value));
ELSE
WHILE bits > 0 DO
SetBit (startPos, ODD (value)); value := value DIV 2;
INC(startPos); DEC(bits)
END;
WHILE bits < 0 DO
SetBit (startPos, ODD (value)); value := value DIV 2;
DEC(startPos); INC(bits)
END;
END;
END SetBits;
-
Я где-то встречал "Разработки на Глаголе", там очень подробно с примерами показано было как имитировать с помощью СЕТов логические операции, устанавливать/сбрасывать произвольные биты, учитывая, что Глагол это плохо переведенный Оберон, но там все одинаково
Ну, в принципе можно и на INTEGER'ах сделать. Умножение на 2 и целочисленное деление на 2 никто не отменял.
Другое дело что финальный CASE будет смотреться убого. Вместо понятной таблицы (или набора таблиц) со строками вида:
".-" -> 'A'
"---" -> 'S'
Ну или пусть даже даже
{1} : c := 'A'
|{0,1,2} : c := 'S'
Будет ужоз вида:
1H : c:= 'A'
| 7H : c:= 'S'
-
Т.е. в Активном Обероне так можно можно, без всяких заморочек
-
Поясню всё же свои недавние посты о трансляции кода в букву.
Преобразовывать имеет смысл, если длина кода не выходит за некие рамки. Если ограничится только цифро-буквенными, как в таблице из http://oberspace.dyndns.org/index.php/topic,338.msg9056.html#msg9056 (http://oberspace.dyndns.org/index.php/topic,338.msg9056.html#msg9056), то длина будет не больше 5.
Теперь можно посмотреть на дерево из http://oberspace.dyndns.org/index.php/topic,338.msg9137.html#msg9137 (http://oberspace.dyndns.org/index.php/topic,338.msg9137.html#msg9137)
Принятый код из 0(точек) и 1(тире) преобразуем в целое - получим смещение (на соответствующем длине кода горизонтальном уровне) в дереве. Вся идея в том, что все буковки из этого дерева выстроить в линию, сначала все с уровня 1, затем все с уровня 2 и т.д до уровня 5. Там, где символ не определён или всякие умляуты поставить некий символ-заменитель, означающий запрещённый код (можно, к примеру маленькую 'x').
Тогда символ соответствующий принятому коду будет на позиции в получившейся строке равной сумме вычисленного целого и "смещения до уровня", равного 2 в степени "длина принятого кода" минус 2
А сама строка буде такая:
ETIANMSURWDKGOHVFxLxPJBXCYZQxx54x3xxx2xx+xxxx16=/xxxxx7xxx8x90
-
В Обероне INCL тоже работает
-
Другое дело что финальный CASE будет смотреться убого. Вместо понятной таблицы (или набора таблиц) со строками вида:
".-" -> 'A'
"---" -> 'S'
Ну или пусть даже даже
{1} : c := 'A'
|{0,1,2} : c := 'S'
Будет ужоз вида:
1H : c:= 'A'
| 7H : c:= 'S'
А зачем, когда можно просто строку на 256 символов с пробелами в пустых местах и по индексу переводи
-
В Обероне INCL тоже работает
Но не так.
INCL(v, x) v: SET; x: INTEGER v:=v + {x}
Also for INCL and EXCL, x must be a constant.
-
Хех, ну тогда остается CASE )))
и
SetVal := SetVal + SYSTEM.VAL( SET, longintval )
или +-*/ над множествами тоже не работают?
-
Хех, ну тогда остается CASE )))
и
SetVal := SetVal + SYSTEM.VAL( SET, longintval )
или +-*/ над множествами тоже не работают?
+-*/ там перегружены же для другого:
symbol result
+ union
- difference
* intersection
/ symmetric set difference
-
А зачем этому автомату память? Разве собственно самого состояния не достаточно?
Допустим, хранить средний уровень сигнала за какой-то интервал назад...
-
Да, в Тру-Обероне сложнее...
лучше, видимо, множитель использовать и потом + для Сетов, хотя придется систем тянуть
можно, конечно, и просто множители для интов.
-
Хех, ну тогда остается CASE )))
и
SetVal := SetVal + SYSTEM.VAL( SET, longintval )
или +-*/ над множествами тоже не работают?
+-*/ там перегружены же для другого:
symbol result
+ union
- difference
* intersection
/ symmetric set difference
Ну правильно, + и даст нам объединение двух Сетов, т.е. логическое Или, главное в longintval нужный множитель закатать
-
А зачем этому автомату память? Разве собственно самого состояния не достаточно?
Допустим, хранить средний уровень сигнала за какой-то интервал назад...
Это обычно делается не в декодере (который оперирует уже бинарными данными), то есть не в конечном автомате, а в узле что данные "бинаризует". В DSP-модуле.
-
Ну правильно, + и даст нам объединение двух Сетов, т.е. логическое Или, главное в longintval нужный множитель закатать
Использовать SYSTEM на ровном месте - не кошерно же :-)
-
Использовать SYSTEM на ровном месте - не кошерно же :-)
Пожалуйся на Вирта в вашигтонский обком, пусть их нафик разбомбят, а то навыдумывали, обероны какие-то, даже INCL нормально не работает, в производных и то додумались сделать правильно )))
ну если систем не кошерен, а конкретная реализация также оторвана от жисти, то тогда только математика
правда CASE Вирт еще не удалил из языка... он знааал, что кому-нибудь да пригодится
я вот вспоминаю, что подобная проблема на Оберонкоре возникала, что-то вроде задачки от Галкова или ка-то так, я никак не мог понять в чем проблема, но я ТруОбероны не использовал, а в Сириусом более реальные вещи приходится решать, и там битовые операции имеются, и счас думал ну раз в А2 все работает... а оно вона как, Михалыч...
-
Если ничего не придумал, то как-то так:
VAR
m: INTEGER :=1;
bitCount: INTEGER :=0;
PROCEDURE SetNextBit ( VAR set: INTEGER, value: BOOLEAN );
DEGIN
INC( bitCount );
IF bitCount > 8 THEN bitCount := 1 END;
IF bitCount = 1 THEN m := 1 ELSE m := m + m END;
IF value THEN INC( set, m );
END SetNextBit;
-
VAR
m: INTEGER :=1;
bitCount: INTEGER :=0;
PROCEDURE SetNextBit ( VAR set: INTEGER, value: BOOLEAN );
DEGIN
IF bitCount > 8 THEN bitCount := 0 END;
IF bitCount = 0 THEN m := 1 ELSE m := m + m END;
IF value THEN INC( set, m );
INC( bitCount );
END SetNextBit;
-
Чегой-то не пойму, в чём трудности. Если в накоплении битов кода, то зачем их вообще накапливать?
Сразу преобразовывать в целое и считать кол-во битов.
пауза пришла - буква накопилась в виде кол-ва пришедших бит и преобразованного в целое.
А преобразование самое элементарное:
Изначально I:=0 и count:=0
С каждым пришедшим битом I:=I*2+пришедшее и count:=count+1
Ну и какое нибудь соглашение, что делать, если длина последовательности превысила допустимую.
Или считать, что всё есть лажа и ждать паузы, или продолжать накапливать в I но дополнить делением по модулю равному нужной степени двойки, чтобы I всегда соответствовало последним n битам
-
Использовать SYSTEM на ровном месте - не кошерно же :-)
Ты не учитываешь одну важнейшую вещь! Оберон - язык для SYSTEMного программирования!!! Об этом все Тру-Обеонщики говорят. Истину глаголят
-
Чегой-то не пойму, в чём трудности. Если в накоплении битов кода, то зачем их вообще накапливать?
Сложности в том, что спотыкачь на ровном месте, когда для установки бита приходится использовать умножение+сложение или кучу сложений и плюс еще кучу дополнительных переменных. А учитывая, что в камне и умножения может не быть, и оперативной памяти там всего несколько БАЙТ... и это при наличии в языке нужных средств, но вот не работающих так, как надо, и работающих в других, производных языках/компиляторах...
-
На всякий случай сделаю ещё пояснения к http://oberspace.dyndns.org/index.php/topic,338.msg9162.html#msg9162 (http://oberspace.dyndns.org/index.php/topic,338.msg9162.html#msg9162)
Пусть точка будет нулем , а тире - единицей. Каждый код в виде нулей и единиц рассматриваем как двоичное число (слева старший разряд, справа младший), но иметь ввиду будем уже в виде преобразованного в целое.
Тогда однобитовые коды имеют значение 0 и 1, двухбитовые - от 0 до 7, трёхбитовые - от 0 до 15 и т .д
То есть каждому закодированному символу соответствует некое целое число и к-во бит в коде.
Теперь сконструируем строку из символов.
Сначала все символы однобитовых кодов, целые значения которых возрастают от 0 до 1, затем символы двухбитовых кодов, целые значения которых упорядочены от 0 до 7 и т.д . Если некоторому целому в n-битовом коде нет соответствующего символа, или вдруг этот код используется для передачи несимвольной информации, то можно выбрать символы например нижнего регистра для представления этих кодов. Например маленькую 'x' для недопустимого кода.
Вот так и получилась строка в конце того сообщения. А для удобства, чтобы руками и глазами коды не мусолить, можно использовать картинку дерева из сообщения http://oberspace.dyndns.org/index.php/topic,338.msg9137.html#msg9137 (http://oberspace.dyndns.org/index.php/topic,338.msg9137.html#msg9137)
-
Что-то я не догоняю, как народ собирается различать 0, 00, 000, 0000 и т.д.
-
Что-то я не догоняю, как народ собирается различать 0, 00, 000, 0000 и т.д.
Надо бы уточнить какой народ и где различать. У меня проблем нет :)
-
Что-то я не догоняю, как народ собирается различать 0, 00, 000, 0000 и т.д.
В этом нет проблемы - мы всегда знаем длину последовательности, которая определяет поддиапазон. Соотвественно из массива мы можем получить букву(декодировать) например так: массив[длинапоследовательности][последовательность]
-
Тогда однобитовые коды имеют значение 0 и 1, двухбитовые - от 0 до 7, трёхбитовые - от 0 до 15 и т .д
Оговорка вышла.
Конечно так:
Тогда однобитовые коды имеют значение 0 и 1, двухбитовые - от 0 до 3, трёхбитовые - от 0 до 7 и т .д
-
Это обычно делается не в декодере (который оперирует уже бинарными данными), то есть не в конечном автомате, а в узле что данные "бинаризует". В DSP-модуле.
В моей архитектуре декодер - это как раз DSP. А с декодером в ваших терминах у меня работа идёт через Writer. Т.е. подразумевается, что Writer - это интерфейс к тому компоненту, который занимается раскодированием азбуки Морзе и дальнейшим применением полученного текста.
-
Поправьте, если ошибаюсь:
BitSets: ARRAY 32 OF SET;
BitSets[0] := {0};
...
BitSets[31] := {31};
VAR
Bits: SET;
BitN: INTEGER;
BEGIN
...
// Установим-ка BitN-ый бит в Bits
Bits := Bits + BitSets[BitN];
// Готово, проверим, установлен ли бит BitN
IF (Bits * BitSets[BitN]) # {} THEN
// Да, установлен
END;
END Test.
-
Как деМорзер? ДеМорзит?
-
Как деМорзер? ДеМорзит?
На выходных попробую собрать в кучу все предложения и оформить.