8-bit morse code

At the request of one of the lovers of using -codes in electronic crafts, it became necessary to write a function (subroutine, procedure) that will issue a trill from a sequence of dots and dashes. In a Morse code, the length of a character can be from 1 character (letters E and T) to 9 characters (SOS trigraph). What to pass to the above function as a parameter? If you are not burdened by the terms of the license, I invite you to get acquainted with the process of stuffing the Morse code into 1 byte.



In Morse code, the most commonly used characters are 1-6 characters long.



; . 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
      
      





These characters will be placed in an 8-bit argument. A byte must contain a sequence of characters (from 1 to 6) and their number (also from 1 to 6). The sequence of characters should be aligned on the least significant or highest bit for ease of pushing into the carry flag (Carry) by shift commands. We get two options for the location of the counter (c) and the sequence (s) of characters:



; arg [s, x, x, x, x, c, c, c] - 1 character

; arg [s, s, x, x, x, c, c, c] - 2 characters

; arg [s, s, s, x, x, c, c, c] - 3 characters

; arg [s, s, s, s, x, c, c, c] - 4 characters

; arg [s, s, s, s, s, c, c, c] - 5 characters

; arg [s, s, s, s, s, s / c, c, c] - 6 characters



; arg [c, c, c, x, x, x, x, s] - 1 character

; arg [c, c, c, x, x, x, s, s] - 2 characters

; arg [c, c, c, x, x, s, s, s] - 3 characters

; arg [c, c, c, x, s, s, s, s] - 4 characters

; arg [c, c, c, s, s, s, s, s] - 5 characters

; arg [c, c, c / s, s, s, s, s, s] - 6 characters



In the first embodiment, with the maximum sequence length, the 6th character is superimposed on the most significant bit of the counter.



In the second embodiment, with the maximum sequence length, the 1st character is superimposed on the least significant bit of the counter. In this case, the least significant bit of the counter can be considered insignificant, since both combinations 110 and 111 can be taken as the maximum value of the counter (6). If the value of the counter is 5 or less, significant signs are not superimposed on the bits of the counter.



We choose the second option. We call the points zeros, dashes - units. Since the sequence of characters is aligned with the least significant bit of the argument, the sequence of characters is arranged in the reverse order to be pushed to the right. We get the encoding of the argument:



; arg [c2, c1, c0 / s6, s5, s4, s3, s2, s1]



In the Morse code, the duration of a point is taken as a unit time interval. Dash duration - 3 intervals. The pause between the characters inside the character is 1 interval. Pause between characters - 4 intervals. Pause between words - 7 intervals. To inform the function that it is not necessary to work out the signs, just enter the pause combination:



; arg [0, 0, 0, 0, 0, 0, 0, 0]



Having accepted the argument arg [c2, c1, c0 / s6, s5, s4, s3, s2, s1], the function must extract the counter and sequence from it, β€œsaw off” the character and end it with a pause of 3 intervals.



To form a pause between words, we pass the argument arg [0, 0, 0, 0, 0, 0, 0, 0] to the function. The function must, in addition to a post-pause of 3 intervals from the previous character, work out a pause of 4 intervals (total 7 intervals).



To extract the counter, the function must shift the copy of the contents of arg to the right by 5 bits, apply the AND mask (00000111), equate the counter to 6 if equal to 7. Next, step by step to the right, extract characters from the original arg. If β€œ0” is a point: 1 beep interval, 1 pause interval. If ”1” is a dash: 3 beep intervals, 1 pause interval. After practicing the last character - 2 pause intervals. If arg = 0: only a pause of 4 intervals.



This 8-bit encoding covers all Morse characters and digraphs from 1 to 6 characters long. Consider the following examples:



 ; . 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]
      
      





If you look closely at what remains in the dry residue:



 ; ...-..- Dollar sign [$] [SX] digraph ; ........ Error/correction [HH] digraph or [EEEEEEEE] ; ...---... [SOS]
      
      





it would be logical to introduce an additional function void dot3woPostPause () after which work out [X] (-..-), [5] (.....) or [:] (---...).



For completeness, consider the "difficult" path. To work out Morse digraphs and trigraphs with a length of more than 6 characters, it is necessary to make an addition to the encoding in order to work out the "extra" characters without an intersymbol pause (without a post-pause of 2 intervals after the "extra" characters).



The number of β€œextra” characters is from 1 to 3. The digit capacity of the counter 2. We place the meter in the arg bits [4,3], and the sequence in the arg bits [2,1,0]:



; arg [0, 0, 0, c1, c0, s3, s2, s1]



With arg [7,6,5] = 000, to extract the counter, the function must shift the copy of arg contents to the right by 3 bits, apply the AND mask (00000011). Next, step by step to the right to extract characters from the original arg. If β€œ0” is a point: 1 beep interval, 1 pause interval. If ”1” is a dash: 3 beep intervals, 1 pause interval. After practicing the last character, no additional pauses are added.



Now, to work out the β€œlong” symbol, you must first process the characters without a post-pause, then the characters with a post-pause. Two 8-bit arguments are needed for this. The total number of characters in the arguments must correspond to the length of the character:



 ; ...-..- 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]
      
      





Packing Morse code characters into 8-bit code can be implemented in different programming languages ​​and on different platforms. For Max (lover of -codes) I prepared the source code of the "fish" on STM8 asm .



Alternative 8-bit encoding from the user "Akon32", allowing to get rid of the second argument:

 ; 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    
      
      







In contrast to a sequence of letters (eg [S], [O], [S]) digraphs and trigraphs (eg [SOS]) are processed without inter-letter pauses.



All Articles