По просьбе одного из любителей применения Щ-кодов в электронных поделках возникла необходимость написать функцию (подпрограмму, процедуру), которая будет издавать трель из последовательности точек и тире. В коде Морзе длина символа может быть от 1 знака (буквы Е и Т) до 9 знаков (триграф SOS). Что передавать вышеназванной функции в качестве параметра? Если вам не в тягость условия лицензии приглашаю познакомиться с процессом запихивания кода Морзе в 1 байт.
В коде Морзе наиболее часто применяются символы длиной 1-6 знаков.
Эти символы будем помещать в 8-разрядный аргумент. Байт должен содержать последовательность знаков (от 1 до 6) и их количество (также от 1 до 6). Последовательность знаков должна быть выровнена по младшему или старшему биту для удобства проталкивания во флаг переноса (Carry) командами сдвига. Получаем два варианта расположения счетчика ( c ) и последовательности ( s ) знаков:
; arg[s, x, x, x, x, c, c, c] – 1 знак
; arg[s, s, x, x, x, c, c, c] – 2 знака
; arg[s, s, s, x, x, c, c, c] – 3 знака
; arg[s, s, s, s, x, c, c, c] – 4 знака
; arg[s, s, s, s, s, c, c, c] – 5 знаков
; arg[s, s, s, s, s, s/c, c, c] – 6 знаков
; arg[c, c, c, x, x, x, x, s] – 1 знак
; arg[c, c, c, x, x, x, s, s] – 2 знака
; arg[c, c, c, x, x, s, s, s] – 3 знака
; arg[c, c, c, x, s, s, s, s] – 4 знака
; arg[c, c, c, s, s, s, s, s] – 5 знаков
; arg[c, c, c/s, s, s, s, s, s] – 6 знаков
В первом варианте при максимальной длине последовательности 6-й знак накладывается на старший бит счетчика.
Во втором варианте при максимальной длине последовательности 1-й знак накладывается на младший бит счетчика. В данном случае младший бит счетчика можно считать незначащим, так как за максимальное значение счетчика (6) можно принять обе комбинации 110 и 111. При значении счетчика 5 и меньше значащие знаки не накладывается на разряды счетчика.
Выбираем второй вариант. Называем точки нулями, тире – единицами. Так как последовательность знаков выровнена по младшему биту аргумента последовательность знаков располагаем в обратном порядке для проталкивания сдвигом вправо. Получаем кодировку аргумента:
; arg[c2, c1, c0/s6, s5, s4, s3, s2, s1]
В коде Морзе за единичный временной интервал принята длительность точки. Длительность тире – 3 интервала. Пауза между знаками внутри символа – 1 интервал. Пауза между символами – 4 интервала. Пауза между словами – 7 интервалов. Для сообщения функции, что не надо отрабатывать знаки, а только паузу введем комбинацию:
; arg[0, 0, 0, 0, 0, 0, 0, 0]
Приняв аргумент arg[c2, c1, c0/s6, s5, s4, s3, s2, s1] функция должна извлечь из него счетчик и последовательность, «отпиликать» символ и завершить его паузой длительностью 3 интервала.
Для формирования паузы между словами передаем функции аргумент arg[0, 0, 0, 0, 0, 0, 0, 0]. Функция должна в дополнение к постпаузе длительностью 3 интервала от предыдущего символа отработать паузу длительностью 4 интервала (итого 7 интервалов).
Для извлечения счетчика функция должна сдвинуть копию содержимого arg вправо на 5 битов, применить маску И(00000111), приравнять счетчик к 6 если равен 7. Далее пошаговыми сдвигами вправо извлечь знаки из оригинала arg. Если “0” – точка: 1 интервал beep, 1 интервал пауза. Если ”1” – тире: 3 интервала beep, 1 интервал пауза. После отработки последнего знака – 2 интервала пауза. Если arg=0: только пауза длительностью 4 интервала.
Даная 8-разрядная кодировка покрывает все символы и диграфы Морзе длиной от 1 до 6 знаков. Рассмотрим примеры:
Если присмотреться к тому, что осталось в сухом остатке:
логично было бы внести дополнительную функцию void dot3woPostPause() после которой отработать [X](-..-), [5](.....) или [:](---...).
Для полноты картины рассмотрим «сложный» путь. Для отработки диграфов и триграфов Морзе длиной более 6 знаков необходимо внести дополнение в кодировку с целью отработки «лишних» знаков без межсимвольной паузы (без постпаузы длительностью 2 интервала после «лишних» знаков).
Количество «лишних» знаков от 1 до 3. Разрядность счетчика 2. Расположим счетчик в разрядах arg[4,3], а последовательность в разрядах arg[2,1,0]:
; arg[0, 0, 0, c1, c0, s3, s2, s1]
При arg[7,6,5]=000 для извлечения счетчика функция должна сдвинуть копию содержимого arg вправо на 3 бита, применить маску И(00000011). Далее пошаговыми сдвигами вправо извлечь знаки из оригинала arg. Если “0” – точка: 1 интервал beep, 1 интервал пауза. Если ”1” – тире: 3 интервала beep, 1 интервал пауза. После отработки последнего знака не добавляются какие либо дополнительные паузы.
Теперь чтобы отработать «длинный» символ надо сначала обработать знаки без постпаузы потом знаки с постпаузой. Для этого нужны два 8-разрядных аргумента. Суммарное количество знаков в аргументах должно соответствовать длине символа:
Упаковка символов кода Морзе в 8-разрядный код может быть реализована на разных языках программирования и на разных платформах. Для Макса (любителя Щ-кодов) приготовил исходный код «рыбы» на STM8 asm.
Альтернативная 8-разрядная кодировка от пользователя «Akon32», позволяющая избавиться от второго аргумента:
В отличие от последовательности букв (напр. [S], [O], [S]) диграфы и триграфы (напр. [SOS]) отрабатываются без межбуквенных пауз.
В коде Морзе наиболее часто применяются символы длиной 1-6 знаков.
; . Ee Ее Ёё ; - Tt Тт ; .. Ii Ии ; .- Aa Аа ; -. Nn Нн ; -- Mm Мм ; ... Ss Сс ; ..- Uu Уу ; .-. Rr Рр ; .-- Ww Вв ; -.. Dd Дд ; -.- Kk Кк ; --. Gg Гг ; --- Oo Оо ; .... Hh Хх ; ...- Vv Жж ; ..-. Ff Фф ; ..-- Юю ; .-.. Ll Лл ; .-.- Яя [AA] digraph UNKNOWN STATION ; .--. Pp Пп ; .--- Jj Йй ; -... Bb Бб ; -..- Xx Ьь Ъъ ; -.-. Cc Цц ; -.-- Yy Ыы ; --.. Zz Зз ; --.- Qq Щщ ; ---. Чч ; ---- Шш ; .---- 1 ; ..--- 2 ; ...-- 3 ; ....- 4 ; ..... 5 ; -.... 6 ; --... 7 ; ---.. 8 ; ----. 9 ; ----- 0 ; ..-.. Ээ ; ..-.- [INT] trigraph - military network question marker ; -..-. Slash/Fraction Bar [/] ; -.--. Parenthesis (Open) ; .-... [AS] digraph - Ampersand (or "Wait") [&] ; -...- [BT] digraph - Double Dash = or -- ; .-.-. Plus sign [+] ; .-.-. [AR] digraph - New Page Signal ; -.-.- Starting Signal ; ...-. Understood ; .--.-. Ъъ ; .-.-.- Period [.] ; --..-- Comma [,] ; ..--.. [UD] digraph Question Mark [?] ; .----. Apostrophe ['] ; -.-.-- [KW] digraph - Exclamation Point [!] ; -.--.- Parenthesis (Close) ; ---... Colon [:] ; -.-.-. Semicolon [;] ; -....- Hyphen, Minus Sign [-] ; ..--.- Underscore [_] ; .-..-. Quotation mark ["] ; .--.-. [AC] digraph - At Sign [@] ; ...-.- End of work ; ...-..- [SX] digraph - Dollar sign [$] ; ........ [HH] digraph - Error/correction ; ...---... [SOS] trigraph
Эти символы будем помещать в 8-разрядный аргумент. Байт должен содержать последовательность знаков (от 1 до 6) и их количество (также от 1 до 6). Последовательность знаков должна быть выровнена по младшему или старшему биту для удобства проталкивания во флаг переноса (Carry) командами сдвига. Получаем два варианта расположения счетчика ( c ) и последовательности ( s ) знаков:
; arg[s, x, x, x, x, c, c, c] – 1 знак
; arg[s, s, x, x, x, c, c, c] – 2 знака
; arg[s, s, s, x, x, c, c, c] – 3 знака
; arg[s, s, s, s, x, c, c, c] – 4 знака
; arg[s, s, s, s, s, c, c, c] – 5 знаков
; arg[s, s, s, s, s, s/c, c, c] – 6 знаков
; arg[c, c, c, x, x, x, x, s] – 1 знак
; arg[c, c, c, x, x, x, s, s] – 2 знака
; arg[c, c, c, x, x, s, s, s] – 3 знака
; arg[c, c, c, x, s, s, s, s] – 4 знака
; arg[c, c, c, s, s, s, s, s] – 5 знаков
; arg[c, c, c/s, s, s, s, s, s] – 6 знаков
В первом варианте при максимальной длине последовательности 6-й знак накладывается на старший бит счетчика.
Во втором варианте при максимальной длине последовательности 1-й знак накладывается на младший бит счетчика. В данном случае младший бит счетчика можно считать незначащим, так как за максимальное значение счетчика (6) можно принять обе комбинации 110 и 111. При значении счетчика 5 и меньше значащие знаки не накладывается на разряды счетчика.
Выбираем второй вариант. Называем точки нулями, тире – единицами. Так как последовательность знаков выровнена по младшему биту аргумента последовательность знаков располагаем в обратном порядке для проталкивания сдвигом вправо. Получаем кодировку аргумента:
; arg[c2, c1, c0/s6, s5, s4, s3, s2, s1]
В коде Морзе за единичный временной интервал принята длительность точки. Длительность тире – 3 интервала. Пауза между знаками внутри символа – 1 интервал. Пауза между символами – 4 интервала. Пауза между словами – 7 интервалов. Для сообщения функции, что не надо отрабатывать знаки, а только паузу введем комбинацию:
; arg[0, 0, 0, 0, 0, 0, 0, 0]
Приняв аргумент arg[c2, c1, c0/s6, s5, s4, s3, s2, s1] функция должна извлечь из него счетчик и последовательность, «отпиликать» символ и завершить его паузой длительностью 3 интервала.
Для формирования паузы между словами передаем функции аргумент arg[0, 0, 0, 0, 0, 0, 0, 0]. Функция должна в дополнение к постпаузе длительностью 3 интервала от предыдущего символа отработать паузу длительностью 4 интервала (итого 7 интервалов).
Для извлечения счетчика функция должна сдвинуть копию содержимого arg вправо на 5 битов, применить маску И(00000111), приравнять счетчик к 6 если равен 7. Далее пошаговыми сдвигами вправо извлечь знаки из оригинала arg. Если “0” – точка: 1 интервал beep, 1 интервал пауза. Если ”1” – тире: 3 интервала beep, 1 интервал пауза. После отработки последнего знака – 2 интервала пауза. Если arg=0: только пауза длительностью 4 интервала.
Даная 8-разрядная кодировка покрывает все символы и диграфы Морзе длиной от 1 до 6 знаков. Рассмотрим примеры:
; . Ee Ее Ёё arg[0, 0, 1, x, x, x, x, 0] ; - Tt Тт arg[0, 0, 1, x, x, x, x, 1] ; .. Ii Ии arg[0, 1, 0, x, x, x, 0, 0] ; .- Aa Аа arg[0, 1, 0, x, x, x, 1, 0] ; -. Nn Нн arg[0, 1, 0, x, x, x, 0, 1] ; -- Mm Мм arg[0, 1, 0, x, x, x, 1, 1] ; ... Ss Сс arg[0, 1, 1, x, x, 0, 0, 0] ; ..- Uu Уу arg[0, 1, 1, x, x, 1, 0, 0] ; .-. Rr Рр arg[0, 1, 1, x, x, 0, 1, 0] ; .-- Ww Вв arg[0, 1, 1, x, x, 1, 1, 0] ; -.. Dd Дд arg[0, 1, 1, x, x, 0, 0, 1] ; -.- Kk Кк arg[0, 1, 1, x, x, 1, 0, 1] ; --. Gg Гг arg[0, 1, 1, x, x, 0, 1, 1] ; --- Oo Оо arg[0, 1, 1, x, x, 1, 1, 1] ; .... Hh Хх arg[1, 0, 0, x, 0, 0, 0, 0] ; ...- Vv Жж arg[1, 0, 0, x, 1, 0, 0, 0] ; ..-. Ff Фф arg[1, 0, 0, x, 0, 1, 0, 0] ; ..-- Юю arg[1, 0, 0, x, 1, 1, 0, 0] ; .-.. Ll Лл arg[1, 0, 0, x, 0, 0, 1, 0] ; .-.- Яя arg[1, 0, 0, x, 1, 0, 1, 0] ; .--. Pp Пп arg[1, 0, 0, x, 0, 1, 1, 1] ; .--- Jj Йй arg[1, 0, 0, x, 1, 1, 1, 0] ; -... Bb Бб arg[1, 0, 0, x, 0, 0, 0, 1] ; -..- Xx Ьь Ъъ arg[1, 0, 0, x, 1, 0, 0, 1] ; -.-. Cc Цц arg[1, 0, 0, x, 0, 1, 0, 1] ; -.-- Yy Ыы arg[1, 0, 0, x, 1, 1, 0, 1] ; --.. Zz Зз arg[1, 0, 0, x, 0, 0, 1, 1] ; --.- Qq Щщ arg[1, 0, 0, x, 1, 0, 1, 1] ; ---. Чч arg[1, 0, 0, x, 0, 1, 1, 1] ; ---- Шш arg[1, 0, 0, x, 1, 1, 1, 1] ; .---- 1 arg[1, 0, 1, 1, 1, 1, 1, 0] ; ..--- 2 arg[1, 0, 1, 1, 1, 1, 0, 0] ; ...-- 3 arg[1, 0, 1, 1, 1, 0, 0, 0] ; ....- 4 arg[1, 0, 1, 1, 0, 0, 0, 0] ; ..... 5 arg[1, 0, 1, 0, 0, 0, 0, 0] ; -.... 6 arg[1, 0, 1, 0, 0, 0, 0, 1] ; --... 7 arg[1, 0, 1, 0, 0, 0, 1, 1] ; ---.. 8 arg[1, 0, 1, 0, 0, 1, 1, 1] ; ----. 9 arg[1, 0, 1, 0, 1, 1, 1, 1] ; ----- 0 arg[1, 0, 1, 1, 1, 1, 1, 1] ; ..-.. Ээ arg[1, 0, 1, 0, 0, 1, 0, 0] ; ..-.- [INT] arg[1, 0, 1, 1, 0, 1, 0, 0] ; -..-. [/] arg[1, 0, 1, 0, 1, 0, 0, 1] ; -.--. Parenthesis arg[1, 0, 1, 1, 0, 1, 1, 0] ; .-... [&] arg[1, 0, 1, 0, 0, 0, 1, 0] ; -...- [=] arg[1, 0, 1, 1, 0, 0, 0, 1] ; .-.-. [+] arg[1, 0, 1, 0, 1, 0, 1, 0] ; -.-.- Starting Signal arg[1, 0, 1, 1, 0, 1, 0, 1] ; ...-. Understood arg[1, 0, 1, 0, 1, 0, 0, 0] ; .--.-. Ъъ arg[1, 1, 0, 1, 0, 1, 1, 0] ; .-.-.- [.] arg[1, 1, 1, 0, 1, 0, 1, 0] ; --..-- [,] arg[1, 1, 1, 1, 0, 0, 1, 1] ; ..--.. [?] arg[1, 1, 0, 0, 1, 1, 0, 0] ; .----. ['] arg[1, 1, 0, 1, 1, 1, 1, 0] ; -.-.-- [!] arg[1, 1, 1, 1, 0, 1, 0, 1] ; -.--.- Parenthesis arg[1, 1, 1, 0, 1, 1, 0, 1] ; ---... [:] arg[1, 1, 0, 0, 0, 1, 1, 1] ; -.-.-. [;] arg[1, 1, 0, 1, 0, 1, 0, 1] ; -....- [-] arg[1, 1, 1, 0, 0, 0, 0, 1] ; ..--.- [_] arg[1, 1, 1, 0, 1, 1, 0, 0] ; .-..-. ["] arg[1, 1, 0, 1, 0, 0, 1, 0] ; .--.-. [@] arg[1, 1, 0, 1, 0, 1, 1, 0] ; ...-.- End of work arg[1, 1, 1, 0, 1, 0, 0, 0]
Если присмотреться к тому, что осталось в сухом остатке:
; ...-..- Dollar sign [$] [SX] digraph ; ........ Error/correction [HH] digraph or [EEEEEEEE] ; ...---... [SOS]
логично было бы внести дополнительную функцию void dot3woPostPause() после которой отработать [X](-..-), [5](.....) или [:](---...).
Для полноты картины рассмотрим «сложный» путь. Для отработки диграфов и триграфов Морзе длиной более 6 знаков необходимо внести дополнение в кодировку с целью отработки «лишних» знаков без межсимвольной паузы (без постпаузы длительностью 2 интервала после «лишних» знаков).
Количество «лишних» знаков от 1 до 3. Разрядность счетчика 2. Расположим счетчик в разрядах arg[4,3], а последовательность в разрядах arg[2,1,0]:
; arg[0, 0, 0, c1, c0, s3, s2, s1]
При arg[7,6,5]=000 для извлечения счетчика функция должна сдвинуть копию содержимого arg вправо на 3 бита, применить маску И(00000011). Далее пошаговыми сдвигами вправо извлечь знаки из оригинала arg. Если “0” – точка: 1 интервал beep, 1 интервал пауза. Если ”1” – тире: 3 интервала beep, 1 интервал пауза. После отработки последнего знака не добавляются какие либо дополнительные паузы.
Теперь чтобы отработать «длинный» символ надо сначала обработать знаки без постпаузы потом знаки с постпаузой. Для этого нужны два 8-разрядных аргумента. Суммарное количество знаков в аргументах должно соответствовать длине символа:
; ...-..- Dollar sign [$] [SX] digraph ; arg1[0, 0, 0, 0, 1, x, x, 0] arg2[1, 1, 1, 0, 0, 1, 0, 0] ; arg1[0, 0, 0, 1, 0, x, 0, 0] arg2[1, 0, 1, 1, 0, 0, 1, 0] ; arg1[0, 0, 0, 1, 1, 0, 0, 0] arg2[1, 0, 0, x, 1, 0, 0, 1] ; ; ........ Error/correction [HH] digraph or [EEEEEEEE] ; arg1[0, 0, 0, 1, 0, x, 0, 0] arg2[1, 1, 0, 0, 0, 0, 0, 0] ; arg1[0, 0, 0, 1, 1, 0, 0, 0] arg2[1, 0, 1, 0, 0, 0, 0, 0] ; ; ...---... [SOS] ; arg1[0, 0, 0, 1, 1, 0, 0, 0] arg2[1, 1, 0, 0, 0, 1, 1, 1]
Упаковка символов кода Морзе в 8-разрядный код может быть реализована на разных языках программирования и на разных платформах. Для Макса (любителя Щ-кодов) приготовил исходный код «рыбы» на STM8 asm.
Альтернативная 8-разрядная кодировка от пользователя «Akon32», позволяющая избавиться от второго аргумента:
; arg[0, 0, 0, 0, 0, 0, 0, 0] — [HH] + пауза длительностью 2 интервала ; arg[0, 0, 0, 0, 1, 0, 0, 1] — [$] + пауза длительностью 2 интервала ; arg[1, 0, s1, s2, s3, s4, s5, s6] — [6 знаков] + пауза длительностью 2 интервала ; arg[1, 1, 0, s1, s2, s3, s4, s5] — [5 знаков] + пауза длительностью 2 интервала ; arg[1, 1, 1, 0, s1, s2, s3, s4] — [4 знака] + пауза длительностью 2 интервала ; arg[1, 1, 1, 1, 0, s1, s2, s3] — [3 знака] + пауза длительностью 2 интервала ; arg[1, 1, 1, 1, 1, 0, s1, s2] — [2 знака] + пауза длительностью 2 интервала ; arg[1, 1, 1, 1, 1, 1, 0, s1] — [1 знак] + пауза длительностью 2 интервала ; arg[1, 1, 1, 1, 1, 1, 1, 0] — только пауза длительностью 4 интервала ; arg[1, 1, 1, 1, 1, 1, 1, 1] — [SOS] + пауза длительностью 2 интервала ; начальный счетчик цикла равен 8 ; далее пошаговый сдвиг влево через Carry флаг ; старшие единицы ('1') незначащие ; наличие нуля ('0') во флаге переноса (Carry) - условие для передачи последующих знаков ; комбинации 0b00000000, 0b11111111, 0b11111110 обрабатываются вне основного цикла
В отличие от последовательности букв (напр. [S], [O], [S]) диграфы и триграфы (напр. [SOS]) отрабатываются без межбуквенных пауз.
