A pedido de um dos amantes do uso de códigos in no artesanato eletrônico, tornou-se necessário escrever uma função (sub-rotina, procedimento) que emitisse um trinado a partir de uma sequência de pontos e traços. Em um código Morse, o tamanho de um caractere pode variar de 1 caractere (letras E e T) a 9 caracteres (trigrama SOS). O que passar para a função acima como parâmetro? Se você não se sobrecarrega com os termos da
licença, convido você a se familiarizar com o processo de inserir o código Morse em 1 byte.
No código Morse, os caracteres mais usados têm de 1 a 6 caracteres.
; . 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
Esses caracteres serão colocados em um argumento de 8 bits. Um byte deve conter uma sequência de caracteres (de 1 a 6) e seu número (também de 1 a 6). A sequência de caracteres deve ser alinhada no bit menos significativo ou mais alto para facilitar a inserção no sinalizador de transporte (transporte) por comandos de deslocamento. Temos duas opções para a localização do contador (c) e a sequência (s) de caracteres:
; arg [s, x, x, x, x, c, c, c] - 1 caractere
; arg [s, s, x, x, x, c, c, c] - 2 caracteres
; arg [s, s, s, x, x, c, c, c] - 3 caracteres
; arg [s, s, s, s, x, c, c, c] - 4 caracteres
; arg [s, s, s, s, s, c, c, c] - 5 caracteres
; arg [s, s, s, s, s / c, c, c] - 6 caracteres
; arg [c, c, c, x, x, x, x, s] - 1 caractere
; arg [c, c, c, x, x, x, s, s] - 2 caracteres
; arg [c, c, c, x, x, s, s, s] - 3 caracteres
; arg [c, c, c, x, s, s, s, s] - 4 caracteres
; arg [c, c, c, s, s, s, s, s] - 5 caracteres
; arg [c, c, c / s, s, s, s, s, s] - 6 caracteres
Na primeira modalidade, com o comprimento máximo de sequência, o sexto caractere é sobreposto no bit mais significativo do contador.
Na segunda modalidade, com o comprimento máximo de sequência, o 1º caractere é sobreposto no bit menos significativo do contador. Nesse caso, o bit menos significativo do contador pode ser considerado insignificante, uma vez que ambas as combinações 110 e 111 podem ser tomadas como o valor máximo do contador (6). Se o valor do contador for 5 ou menos, sinais significativos não serão sobrepostos nos bits do contador.
Nós escolhemos a segunda opção. Chamamos os pontos de zeros, traços - unidades. Como a sequência de caracteres está alinhada com o bit menos significativo do argumento, a sequência de caracteres é organizada na ordem inversa para ser empurrada para a direita. Nós obtemos a codificação do argumento:
; arg [c2, c1, c0 / s6, s5, s4, s3, s2, s1]
No código Morse, a duração de um ponto é tomada como um intervalo de tempo unitário. A duração do traço é de 3 intervalos. A pausa entre os caracteres dentro do caractere é de 1 intervalo. Pausa entre caracteres - 4 intervalos. Pausa entre palavras - 7 intervalos. Para informar à função que não é necessário calcular os sinais, basta inserir a combinação de pausa:
; arg [0, 0, 0, 0, 0, 0, 0, 0]
Tendo aceitado o argumento arg [c2, c1, c0 / s6, s5, s4, s3, s2, s1], a função deve extrair o contador e a sequência, “cortar” o caractere e terminar com uma pausa de 3 intervalos.
Para formar uma pausa entre as palavras, passamos o argumento arg [0, 0, 0, 0, 0, 0, 0, 0, 0] para a função. A função deve, além de uma pós-pausa de 3 intervalos do caractere anterior, realizar uma pausa de 4 intervalos (total de 7 intervalos).
Para extrair o contador, a função deve deslocar a cópia do conteúdo do arg para a direita em 5 bits, aplicar a máscara AND (00000111), equiparar o contador a 6 se for igual a 7. Em seguida, passo a passo à direita, extrair caracteres do arg original. Se "0" for um ponto: 1 intervalo de bipe, 1 intervalo de pausa. Se "1" for um traço: 3 intervalos de bipe, 1 intervalo de pausa. Depois de praticar o último personagem - 2 intervalos de pausa. Se arg = 0: apenas uma pausa de 4 intervalos.
Essa codificação de 8 bits abrange todos os caracteres e algarismos Morse de 1 a 6 caracteres. Considere os seguintes exemplos:
; . 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]
Se você observar atentamente o que resta no resíduo seco:
; ...-..- Dollar sign [$] [SX] digraph ; ........ Error/correction [HH] digraph or [EEEEEEEE] ; ...---... [SOS]
seria lógico introduzir uma função adicional void dot3woPostPause () após a qual trabalhe [X] (-..-), [5] (.....) ou [:] (---...).
Para completar, considere o caminho "difícil". Para calcular os algarismos e trigramas Morse com um comprimento superior a 6 caracteres, é necessário adicionar uma codificação para calcular caracteres "extras" sem uma pausa entre caracteres (sem uma pausa após 2 intervalos após os caracteres "extras").
O número de caracteres “extras” é de 1 a 3. A capacidade de dígitos do contador 2. Colocamos o medidor nos bits de arg [4,3] e a sequência nos bits de arg [2,1,0]:
; arg [0, 0, 0, c1, c0, s3, s2, s1]
Com arg [7,6,5] = 000, para extrair o contador, a função deve deslocar a cópia do conteúdo do arg para a direita em 3 bits, aplicar a máscara AND (00000011). Em seguida, passo a passo à direita para extrair caracteres do argumento original. Se "0" for um ponto: 1 intervalo de bipe, 1 intervalo de pausa. Se "1" for um traço: 3 intervalos de bipe, 1 intervalo de pausa. Após calcular o último caractere, nenhuma pausa adicional é adicionada.
Agora, para descobrir o símbolo "longo", você deve primeiro processar os caracteres sem uma pós-pausa, depois os caracteres com uma pós-pausa. Dois argumentos de 8 bits são necessários para isso. O número total de caracteres nos argumentos deve corresponder ao comprimento do caractere:
; ...-..- 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]
A compactação de caracteres de código Morse em código de 8 bits pode ser implementada em diferentes linguagens de programação e em diferentes plataformas. Para Max (amante dos códigos)), preparei o código fonte do "peixe" no
STM8 asm .
Codificação alternativa de 8 bits do usuário "Akon32", permitindo que você se livre do segundo argumento:
; 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
Diferentemente de uma sequência de letras (por exemplo, [S], [O], [S]), os dígrafos e trigramas (por exemplo, [SOS]) são processados sem pausas entre letras.