Notes behind Magic Morse

mrburnette

Senior Member
Note #1: Dealing with serial encoded data streams

Issue: Morse Code is a non-sequential (ASCII is sequential, A=65, B=66, C=67) code stream based on statistics of character usage. As such, the most used alphabetical characters (English) are given the shorter code sequence and less used characters are given longer unique sequences. Morse Code is not a block length (fixed length) code, characters can be a single "DIT" or "DAH" and grow to 5 elements (6 elements for some Prosigns.)

A solution: Create an algorithm that will uniquely encode individual elements in realtime (temporal since each element comes in serially and time is a component of decoding/encoding.) The algorithm should generate an index into a single dimensional array (EEPROM). The index must be unique for every Morse character (withing 5 elements). The index which is a numerical value between 0 - 255 must also be easily converted back to a serial DIT-DAH stream to allow Morse Code transmission.

Note #2: An encoding algorithm for Magic Morse numbers.
Code:
(c) Copyright 2011 M. Ray Burnette
ALL COMMERCIAL RIGHTS RESERVED

Example: 0 1 0 = R
               There are 3 elements, therefore bits 1, 2, 4 = 3 (1 / 1 / 0)
               The 1 is in the second character, therefore it is 
               weighted with a bit value of 16 ( 0 / 1/ 0 / 0 / 0 )
               The Index value is 1 + 2 + 16 = 19

Example:  1 1 = M
               There are 2 elements, therefore bits 1, 2, 4 = 2 (0 / 1 / 0)
               The 1 is the first and second character, therefore
               weighting is 8 and 16 = 24 (1 / 1 / x / x / x)
               The Index value is 2 + 24 = 26

Alphabet
	ASCII INDEX	MORSE CODE						# Elements-		---------- weight ---------
										1	2	4	8	16	32	64	128
E	69	1	DIT							1	0	0	0	x	x	x	x
I	73	2	DIT	DIT						0	1	0	0	0	x	x	x
S	83	3	DIT	DIT	DIT					1	1	0	0	0	0	x	x
H	72	4	DIT	DIT	DIT	DIT				0	0	1	0	0	0	0	x
5	53	5	DIT	DIT	DIT	DIT	DIT			1	0	1	0	0	0	0	0
T	84	9	DAH							1	0	0	1	x	x	x	x
N	78	10	DAH	DIT						0	1	0	1	0	x	x	x
D	68	11	DAH	DIT	DIT					1	1	0	1	0	0	x	x
B	66	12	DAH	DIT	DIT	DIT				0	0	1	1	0	0	0	x
6	54	13	DAH	DIT	DIT	DIT	DIT			1	0	1	1	0	0	0	0
A	65	18	DIT	DAH						0	1	0	0	1	x	x	x
R	82	19	DIT	DAH	DIT					1	1	0	0	1	0	x	x
L	76	20	DIT	DAH	DIT	DIT				0	0	1	0	1	0	0	x
M	77	26	DAH	DAH						0	1	0	1	1	x	x	x
G	71	27	DAH	DAH	DIT					1	1	0	1	1	0	x	x
Z	90	28	DAH	DAH	DIT	DIT				0	0	1	1	1	0	0	x
7	55	29	DAH	DAH	DIT	DIT	DIT			1	0	1	1	1	0	0	0
U	85	35	DIT	DIT	DAH					1	1	0	0	0	1	x	x
F	70	36	DIT	DIT	DAH	DIT				0	0	1	0	0	1	0	x
IN	0	41	DAH	DIT	DAH					1	1	0	1	0	1	x	x   <--- Prosign for Invite
K	75	43	DAH	DIT	DAH					1	1	0	1	0	1	x	x
C	67	44	DAH	DIT	DAH	DIT				0	0	1	1	0	1	0	x
__________________________________________________________________________________
Full list of standard ASCII --> Magic Morse
Alpha	
	ASCII
		Magic
0	48	253
1	49	245
2	50	229
3	51	197
4	52	133
5	53	5
6	54	13
7	55	29
8	56	61
9	57	125
A	65	18
B	66	12
C	67	44
D	68	11
E	69	1
F	70	36
G	71	27
H	72	4
I	73	2
J	74	116
K	75	43
L	76	20
M	77	26
N	78	10
O	79	59
P	80	52
Q	81	92
R	82	19
S	83	3
T	84	9
U	85	35
V	86	68
W	87	51
X	88	76
Y	89	108
Z	90	28
The Excel snippet shows that by using the DAH as the primary weighting element, a simple algorithm can be constructed for decoding Morse Code into a unique index in the range of 0-255. DAH's are weighted by received position in the stream and DAH's and DIT's are counted and stored in 3-bits to represent the number of Morse elements in a character. When the DAH weighting is added to the DIT+DAH counts, a unique number is created... called Magic Morse.

Note #3: Example of how this may look in PICAXE Basic.
Code:
' Point is the low-order 3 bits (element count) and DitDah is the DAH weighting of the incoming Morse stream
'... assume we have received an element on a PORT PIN and logic has discriminated it as a DIT or a DAH.... 
' count the elements, DITs or DAHs
INC Point
' some logic here to EXIT a nested LOOP if a DIT
'... if the element is a DAH, more math is required where DitDah is a partial index value composed of weighted DAHs
Select Case Point
		Case 1 : DitDah = DitDah OR %00001000
		Case 2 : DitDah = DitDah OR %00010000
		Case 3 : DitDah = DitDah OR %00100000
		Case 4 : DitDah = DitDah OR %01000000
		Case 5 : DitDah = DitDah OR %10000000
End Select

' ... after the end-of-character is detected by logic, calculate the final Magic Morse Index and look it up
DitDah = DitDah + Point	' Complete the two-part pointer algorithm
READ DitDah, Temp

' ... the ASCII character Temp or the ASCII value Temp can be used as required
Note #4: A way to recover Morse Code from the Magic Morse number: Assume that a need exists (telemetry maybe) where we have decoded (by lookup, etc) an ASCII character/numeral and wish to further encode that to a 5-bit Morse Code sequence. Here is an example.
Code:
DITDAH:

	'B3 = MM#	' Magic Morse number

	B11 = " " : B12 = " " : B13 = " " : B14 = " " : B15 = " " ' Initialize all to a single space

	If B3 > 128 then : B15 = "-" : B3 = B3 - 129 : ENDIF
	If B3 > 64  then : B14 = "-" : B3 = B3 - 65  : ENDIF
	If B3 > 32  then : B13 = "-" : B3 = B3 - 33  : ENDIF
	If B3 > 16  then : B12 = "-" : B3 = B3 - 17  : ENDIF
	IF B3 > 8   then : B11 = "-" : B3 = B3 - 9   : ENDIF
	
	IF B3 > 0 AND B11 = " " then : B11 = "." : B3 = B3 - 1 : ENDIF
	IF B3 > 0 AND B12 = " " then : B12 = "." : B3 = B3 - 1 : ENDIF
	IF B3 > 0 AND B13 = " " then : B13 = "." : B3 = B3 - 1 : ENDIF
	IF B3 > 0 AND B14 = " " then : B14 = "." : B3 = B3 - 1 : ENDIF
	IF B3 > 0 AND B15 = " " then : B15 = "." : B3 = B3 - 1 : ENDIF

	SerTxd ("Morse =  ",B11,B12,B13,B14,B15,LF,CR)
Of course, the code snippet must be enhanced in the final use to look through the B11, B12, B13, B14, B15 variables and to ONLY send those that and non-space, but that is trivial. The main purpose of the code is to show that a little brute-force can be used to turn a Magic Morse number into a 1-5 element stream of Morse Code.
In reality, the PICAXE "LookUp" command can be used to completely eliminate the need for EEPROM, but at the expense of program space. The correct selection will be based on the overall needs of the programmer, the uC selected, and the complexity of the overall program.

The EEPROM lookup table for decoding may be found here: http://www.picaxeforum.co.uk/showthread.php?19123-Morse-Code-Decoding-8WPM-with-a-PICAXE-08M2

Note #5: Finally, you can run this in the simulator:
Code:
' Demo code of converting ASCII to Magic Morse number and Back to Morse Code
' M. Ray Burnette, (c) 2011

' Variables used: B1, B2, B3, B11, B12, B13, B14, B15
' 275 Bytes / 4096
#picaxe 20x2
'
'
' Generate a look of ASCII values for the UPPER case Alphabet
For B2 = 65 to 90
	B1 = B2 - 65 ' Normalize to Lookup syntax
	' Of course, Magic Morse works for all numbers, characters, punctuation
	' But limited here for demo purposes
	'
	GoSub ASCII2MM	'B3 = MM#
	GoSub DITDAH
	SerTxd ("'",B2,"' in Morse Code is ",B11,B12,B13,B14,B15,CR,LF)
NEXT

END

ASCII2MM:
	'Literal     A, B, C, ...  Z
	'ASCII	65, 66, 67 ... 90
	Lookup B1, (18,12,44,11,1,36,27,4,2,116,43,20,26,10,59,52,92,19,3,9,35,68,51,76,108,28), B3

RETURN

DITDAH:
	'B3 = MM#	' Magic Morse number

	B11 = " "	' DIT = . or DAH = - or NOT TRANSMITTED = " "
	B12 = " "	' DIT = . or DAH = - or NOT TRANSMITTED = " "
	B13 = " "	' DIT = . or DAH = - or NOT TRANSMITTED = " "
	B14 = " "	' DIT = . or DAH = - or NOT TRANSMITTED = " "
	B15 = " "	' DIT = . or DAH = - or NOT TRANSMITTED = " "

	If B3 > 128 then : B15 = "-" : B3 = B3 - 129 : ENDIF
	If B3 > 64  then : B14 = "-" : B3 = B3 - 65  : ENDIF
	If B3 > 32  then : B13 = "-" : B3 = B3 - 33  : ENDIF
	If B3 > 16  then : B12 = "-" : B3 = B3 - 17  : ENDIF
	IF B3 > 8   then : B11 = "-" : B3 = B3 - 9   : ENDIF
	
	IF B3 > 0 AND B11 = " " then : B11 = "." : B3 = B3 - 1 : ENDIF
	IF B3 > 0 AND B12 = " " then : B12 = "." : B3 = B3 - 1 : ENDIF
	IF B3 > 0 AND B13 = " " then : B13 = "." : B3 = B3 - 1 : ENDIF
	IF B3 > 0 AND B14 = " " then : B14 = "." : B3 = B3 - 1 : ENDIF
	IF B3 > 0 AND B15 = " " then : B15 = "." : B3 = B3 - 1 : ENDIF
RETURN
- Ray
 

Attachments

SharkNose

New Member
Hi, Ray. I ordered your Magic Morse from Jameco and after 2 evening sessions, I got it working!



I have always wanted to learn Morse since the 1960's when I first became interested in Short Wave Listening. Your project is what it took me to finally take the plunge after 45 years! One thing I have discovered is that my Morse skills are atrocious! Well, that's what practice is for. My next step is to hook the Magic Morse up to the PC speaker and play some professional Morse Code through it.

Regards,

Andrew Jones
 

mrburnette

Senior Member
Andrew,

I am glad you got things assembled and that the project is helping you with learnjng Mode Code.

Over time, I have used my algorithm for such tbings as a Morse Code "flashing temperature orb" and have also published an Arduino version ... check out the popcycle magnetic key!

Cold-hearted Orb

Morse Sticks

Ray's Projects
 
Top