8位莫尔斯电码

在电子工艺中使用代码的爱好者之一的要求下,有必要编写一个函数(子例程,过程),该函数将从点和点的序列中发出颤音。 在摩尔斯电码中,字符的长度可以从1个字符(字母E和T)到9个字符(SOS三字母组合)。 将什么作为参数传递给上述函数? 如果您不受许可证条款的限制,我邀请您熟悉将莫尔斯电码填充到1个字节的过程。

在摩尔斯电码中,最常用的字符是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个字符被叠加在计数器的最高有效位上。

在第二实施例中,在序列的最大长度的情况下,第一个字符被叠加在计数器的最低有效位上。 在这种情况下,由于组合110和111都可以作为计数器的最大值(6),因此计数器的最低有效位可以忽略不计。如果计数器的值等于或小于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位,应用AND掩码(00000111),将计数器等于6(如果等于7)。接下来,逐步向右,从原始arg中提取字符。 如果“ 0”是一个点:1个蜂鸣间隔,1个暂停间隔。 如果“ 1”是破折号:3个蜂鸣间隔,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位,并应用AND掩码(00000011)。 接下来,逐步从右侧逐步提取原始arg中的字符。 如果“ 0”是一个点:1个蜂鸣间隔,1个暂停间隔。 如果“ 1”是破折号:3个蜂鸣间隔,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位代码可以用不同的编程语言和不同的平台实现。 对于Max(代码的爱人),我在STM8 asm上准备了“ fish”的源代码。

用户“ Akon32”提供的备用8位编码,使您可以摆脱第二个参数:
 ; 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])的处理没有字母间的停顿。

Source: https://habr.com/ru/post/zh-CN473038/


All Articles