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.
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.
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.
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:
- Ray
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