目前来说,我能找到的最古老的系统化字符编码,似乎就是 Morse code(摩尔斯电码 / 摩斯密码) 了,今天就来探寻一番。

字符编码开坑第一篇,希望能够坚持住。
先说点题外话,在写本文之前,惯例我会先搜集相关的内容来做前期准备,让我非常惊讶的是,许多人对摩尔斯电码最深刻的记忆,都来自同一部电影:《无间道》。

在《无间道》三部曲中,多次出现摩尔斯电码的身影:陈永仁逃跑时敲击墙壁,在天台山敲击自己的胳膊,交易时通过窃听器传输摩尔斯电码报信;警局卧底的档案密码是摩尔斯电码;最后刘建明在轮椅上敲出了 HEL ...,却没人知道最后一位字母是什么。以上这些都是大家津津乐道的情节,可以说,摩尔斯电码几乎成为了谍战类影视剧的标配。

那么,就先从它开始探索吧。

摩尔斯电码

编码表

摩尔斯电码的一个特点就是所有的字母并不是等长的,我们可以从它的编码表中直观的看到。

其实换一种方式来看这张编码表,会更好理解,因为这其实就是一棵 霍夫曼树Huffman Tree

此处使用霍夫曼树的原因也很简单,英文字符在日常使用中是有 频率差异 的,这棵树大致就是按照这个频率进行构建。

与常见的霍夫曼编码略有不同的是,常见的霍夫曼编码只有叶子节点才会分配给字符,而摩尔斯电码非叶子节点也被分配了字符,也就是说,摩尔斯电码并不是前缀编码,这也间接导致了接下来我们要讨论的结构问题。

结构组成

只有 点 和 划 嘛?

如果不仔细翻看资料,可能大部分人会认为摩尔斯电码是由 ·- 组成的,也就是我们常说的 『点』和『划』,也可以写作 dotdash

  • 点 / dot / · / 滴 / di
  • 划 / dash / - / 嗒 / dah

但是实际上,无论从什么角度来考虑,摩尔斯电码都不止包含这两个元素。

先来简单测试一下,如果我们只使用 ·- 来编码 hello world会怎样:

诶?好像和我们经常见到的不一样啊,难道不应该是这样的么?

另一个角度,我们知道 - 实际上是三倍长度的 ·

那么,假如我发送了 ... ,我要发送的是 S 呢?还是 EEE呢?还是 T 呢?

隐藏的分隔符

此时我们似乎发现了一个隐藏的字符,那就是『空格』,或者说『分隔符』

我们都知道,使用摩尔斯电码发送电报的时候需要使用『电键』,而电键的基础原理其实就是控制电路在 『通』『断』两种状态间切换,通过按下时长的长短来区分 『点』『划』。

也就是说,『点』与『点』之间,『字符』与『字符』之前,其实是通过间隔来进行分隔的。

我们假定一个『点』的时长为一个单位长度 T,那么『划』的时长就是 3T 。

同一个字符内部的『点』『划』间的间隔也是 T,字符间的间隔是 3T ,而单词间的间隔则是 7T 。

此处我们选择两个字符 OR 作为示意,在发报的过程中,电路的通断情况其实是下面这样的。

这样,我们就可以用简单的 『通』『断』来表示出摩尔斯电码了。

原来是二进制啊

其实看到上面的示意图就会发现,其实电路状态的『通』『断』,完全可以理解为二进制的 10,而摩尔斯电码的基本组成结构,也可以理解为只有 『通』『断』。

当然,我们也可以理解按常见的方式去理解它的结构,只是这下我们知道它背后的底层内容了。

  • 点 ( 1 )
  • 划 ( 111 )
  • 分隔符

    • 点划分隔 ( 0 )
    • 字符分隔 ( 000 )
    • 单词分隔 ( 0000000)

可以看到,其实 OR 的摩尔斯编码,其实也可以用二进制 1 0 来进行表示:

OR => 010111010001011101010

其实换一个角度也很容易想明白,基于电路通断的摩尔斯电码,不论上层怎么定义,都不可能绕开底层只有两种状态这件事。

传输效率

从上面的示意图中,其实我们还能发现另一个问题,摩尔斯电码的效率并不高。

发送 OR 两个字符,总共用了 21T 的时长,操作手按下电键 7 次,这个效率用作信息传递不免让人觉得有些焦躁。

于是,就有了各种提升摩尔斯电码效率的操作。

信息压缩

需要说明的是,需要被压缩的并不是摩尔斯电码,而是 『英文单词』。

正如许多人使用 "tks" 来代指 "thanks" ,"BTW" 来代指 "by the way" 一样,英文世界里也存在着大量的对常用词汇的缩写。一百多年前的前辈们,也是对它进行了充分的利用。

这些缩写分为两类,一类是简单的拼接字符,形成『短词』,相当于 『单词缩写』;

另一类则是直接造了新的『字符』出来,称为 『特殊符号(统一符号)』。

单词缩写

单词缩写的例子非常多,这里简单列举一小部分。

可以看到,这些词汇大部分都是首字母缩写,许多缩写后面也有了更广泛的用法。

缩写全写注释
AAAll after某字以后
ABAll before字以前
BNAll between……之间
CYes是,好
CQCalling any station调用任意台站
CULSee you later再见
CYCopy抄收
DEFrom来自
GAGood afternoon or Go ahead午安;请发报(依上下文而定)
GEGood evening晚安
GMGood morning早安
HILaughter
RReceived,Roger or decimal point收到;小数点(依上下文而定)
RPTRepeat or report (depending on context)重复;报告(依上下文而定)
RXReceive接收
TNXThanks谢谢
TUThank you谢谢你
TXTransmit发射
UYou
URYour or you're你的;你是(依上下文而定)
73Best regards致敬
88Love and kisses吻别
99go way走开(非友善)

特殊符号

特殊符号的主要特点在于各个原本的字符之间,是不存在字符间隔的,符号整体相当于一个『字符』。

可以看到的是,K T R 等单个字符,也直接被赋予了特殊涵义

符号代码意义
AAAAA·-·-·-·-·-调用信号,表示“我有消息发送”。
AAA(.)·-·-·-表示“本句完,接下一句”。
HH········表示“有错,从上一字重新开始”。
AR(+)·-·-·表示“消息结束”。
AS(&)·-···等待。
TTTTT-----表示“我正在接收你的消息”。
K-·-表示“我已准备好,请开始发送消息”。
T-表示“字收到了”。
IMI(?)··--··表示“请重复你的电码,我不是很明白”。
R·-·表示“消息已收到”。
SK···-·-表示终止(联系结束)。
BT(=)-···-分隔符。
SOS···---···求救信号。

通过以上这些缩写和特殊符号,就可以将一次沟通所需的字符尽可能压缩了,例如 维基百科 上所列出的这个示例:

s1:

CQ CQ CQ DE s1 K
呼叫任何人(CQ),這是(DE)s1,結束(K)。

s2:

s1 DE s2 K
呼叫s1,這是s2,結束。

(現在兩個電台就建立通訊連接了)

s1:

SK
再見。

s2:

SK
再見。

可以看到,对话双方,仅用 30 个字符就完成了一次对话的建立和结束,这极大的提升了使用摩尔斯电码沟通的效率。

电键改造

除了尽可能的压缩要发送的信息,提升发报员的手速自然也是一个重要的方向。

但是好马也要配好鞍,发报员离不开的『电键』也需要好好花功夫进行升级。

手动电键

传统的 手动电键(straight key) 的原理非常简单,触点 + 弹簧,发报员通过 按下/松开 触点的动作来完成发报。

这个过程完全手动完成,发报员的按键频率,直接决定了发报的速率。

臭虫电键

臭虫电键(bug key) 也叫 快键(Speed Key) 也就是 机械半自动电键

之所以叫它半自动,是因为它实现了『点』的自动发送:

  • 将按键向右拨,会发出『点』,一直按住不放,会按相应的频率一直发送『点』直到松手
  • 将按键向左拨,会发出 『划』,但是此处不具备按住一直发送的功能

即便只是半自动,臭虫电键也已经节约了不少时间。

单杆电子键

单杆电子键(single lever paddle) 其实就是 『全自动』版的臭虫电键,它不止可以通过长时间向右按键发出连续的 『点』,长时间向左按键也可以发出连续的『划』,这下子就算完整的自动化了。

双杆电子键

双杆电子键(Dual Lever Paddle/lambic Paddle) 乍一看好像和单杆的没什么区别,也是左桨『点』,右桨『划』,其实它还加入了第三种重要的自动功能:挤压双桨,就会自动发送『点』『划』间隔的序列,这对于特定的字母和符号非常有效。

关于电键,哈罗 CQ 火腿社区网友 VR2UW 的帖子 “发报电键的演进” 做出了非常详细的介绍,此处仅摘录部分。

总结

从现在的角度来看,摩尔斯电码存在许多问题,性能差,长度不统一等等。

但更需要看到的是,它的许多优秀之处:

  • 使用『点』『划』对底层的 0 1 进行包装,更易于被人理解。
  • 使用霍夫曼树、缩写词等方式,尽可能减小数据体长度,节约带宽。
  • 改进辅助工具,提升工作效率。

同时,也需要认识到一个重要的误区:

  • 编码的组成结构,未必就是表面上看到的那样

最后,这里有一张摩尔斯电码助记图,想要学习的可以参考一下:

相关链接

为了写这篇文章,翻阅各种网站查阅了许多资料,在此一并列出,读者有兴趣可以进行参考:

文章目录