Decode Morse Code with Python (2)

$ ~/anaconda3/bin/python test4.py ~/40wpm.wav 0 -1
 
<BT> 
NOW 
40 
WPM 
<BT> 
TEXT 
IS 
FROM 
JANUARY 
2014 
QST 
PAGE 
46
<BT>
SETTING 
THE 
VFO. 
WITH 
THE 
TRANSMITTER 
OUTPUT 
CONNECTED 
TO 
A 
DUMMY 
LOAD, 
SET 
THE 
VFO 
TO 
THE 
CORRECT 
FREQUENCY 
FOR 
THE 
BAND 
OF 
INTEREST.
import sys
import numpy as np
import matplotlib.pyplot as plt
import soundfile as sf
from scipy.signal import hilbert

morse ={
	"" : "",
	"A" : ".-",
	"B" : "-...",
	"C" : "-.-.",
	"D" : "-..",
	"E" : ".",
	"F" : "..-.",
	"G" : "--.",
	"H" : "....",
	"I" : "..",
	"J" : ".---",
	"K" : "-.-",
	"L" : ".-..",
	"M" : "--",
	"N" : "-.",
	"O" : "---",
	"P" : ".--.",
	"Q" : "--.-",
	"R" : ".-.",
	"S" : "...",
	"T" : "-",
	"U" : "..-",
	"V" : "...-",
	"W" : ".--",
	"X" : "-..-",
	"Y" : "-.--",
	"Z" : "--..",
	"1" : ".----",
	"2" : "..---",
	"3" : "...--",
	"4" : "....-",
	"5" : ".....",
	"6" : "-....",
	"7" : "--...",
	"8" : "---..",
	"9" : "----.",
	"0" : "-----",
	"." : ".-.-.-",
	"," : "--..--",
	":" : "---...",
	"?" : "..--..",
	"'" : ".----.",
	"-" : "-....-",
	"/" : "-..-.",
	"@" : ".--.-.",
	"<BT>" : "-...-"
}

morse_inv = dict((v,k) for (k,v) in morse.items())

filename = sys.argv[1]
nstart   = int(sys.argv[2])
nframes  = int(sys.argv[3])

wav, fs  = sf.read(filename,start=nstart,frames=nframes)
analytic_signal = hilbert(wav)
env = np.abs(analytic_signal)

th = 0.5*max(env)
env[env<th] = 0
env[env!=0] = 1

t_up = 0
t_down = 0
up = []
down = []
string = ''
t_ws = 5000
t_ls = 2500
t_dd = 2500

for t in range(1, len(env-1)):
	if env[t-1] == 0 and env[t] == 1:
		t_up = t
		t_down_duration = t - t_down
		down.append(t_down_duration)
		if t_down_duration > t_ls:
			print(morse_inv[string], end='')
			string = ''
		if t_down_duration > t_ws:
			print(' ')
	if env[t-1] == 1 and env[t] == 0:
		t_down = t
		t_up_duration = t - t_up
		up.append(t_up_duration)
		if t_up_duration < t_dd:
			string = string + '.'
		else:
			string = string + '-'

print('')

Decode Morse Code with Python

$ ~/anaconda3/bin/python test4.py ~/40wpm.wav 0 500000

-...-
-. --- .--
....- -----
.-- .--. --
-...-
- . -..- -
.. ...
..-. .-. --- --
.--- .- -. ..- .- .-. -.--

$

import sys
import numpy as np
import matplotlib.pyplot as plt
import soundfile as sf
from scipy.signal import hilbert

filename = sys.argv[1]
nstart   = int(sys.argv[2])
nframes  = int(sys.argv[3])

wav, fs  = sf.read(filename,start=nstart,frames=nframes)
analytic_signal = hilbert(wav)
env = np.abs(analytic_signal)

th = 0.5*max(env)
env[env<th] = 0
env[env!=0] = 1

t_up = 0
t_down = 0
up = []
down = []
string = ''
t_ws = 5000
t_ls = 2500
t_dd = 2500

for t in range(1, len(env-1)):
	if env[t-1] == 0 and env[t] == 1:
		t_up = t
		t_down_duration = t - t_down
		down.append(t_down_duration)
		if t_down_duration > t_ws:
			print(string)
			string = ''
		elif t_down_duration > t_ls:
			string = string + ' '
	if env[t-1] == 1 and env[t] == 0:
		t_down = t
		t_up_duration = t - t_up
		up.append(t_up_duration)
		if t_up_duration < t_dd:
			string = string + '.'
		else:
			string = string + '-'

print('')

Python and SciPy (2)

Once you get the envelope, it is easy to draw a histogram of the Dot/Dash durations.

import sys
import numpy as np
import matplotlib.pyplot as plt
import soundfile as sf
from scipy.signal import hilbert

filename = sys.argv[1]
nstart   = int(sys.argv[2])
nframes  = int(sys.argv[3])

wav, fs  = sf.read(filename,start=nstart,frames=nframes)
analytic_signal = hilbert(wav)
env = np.abs(analytic_signal)

th = 0.5*max(env)
env[env<th] = 0
env[env!=0] = 1

t_up = 0
t_down = 0
up = []
down = []

for t in range(1, len(env-1)):
	if env[t-1] == 0 and env[t] == 1:
		t_up = t
		t_down_duration = t - t_down
		down.append(t_down_duration)
	if env[t-1] == 1 and env[t] == 0:
		t_down = t
		t_up_duration = t - t_up
		up.append(t_up_duration)

plt.figure(1)

plt.subplot(221)
plt.plot(wav, color='green')
plt.title("input signal")

plt.subplot(222)
plt.plot(env, color='red')
plt.title("binary signal")


plt.subplot(223)
plt.hist(up, bins=50, color="orange")
plt.title("Dot/Dash Histogram")
plt.grid(True)

plt.subplot(224)
plt.hist(down, bins=50, color="blue")
plt.title("Spaces Histogram")
plt.grid(True)

plt.subplots_adjust(hspace=0.5, wspace=0.35)
plt.show()

Python and SciPy

The envelope of the signal is obtained by computing the magnitude of the analytic signal.

import sys
import numpy as np
import matplotlib.pyplot as plt
import soundfile as sf
from scipy.signal import hilbert

filename = sys.argv[1]
nstart   = int(sys.argv[2])
nframes  = int(sys.argv[3])

wav, fs  = sf.read(filename,start=nstart,frames=nframes)
analytic_signal = hilbert(wav)
env = np.abs(analytic_signal)

plt.plot(wav, color='green')
plt.plot(env, color='red')
plt.title("input signal")
plt.xlabel("time")
plt.ylabel("amplitude")

plt.show()

In my previous aritcle, Analytic Signals (2), the same thing is done using the C language.

Python and PySoundFile

A short Python program to show the waveform from a sound file.

import sys
import numpy as np
import matplotlib.pyplot as plt
import soundfile as sf

filename = sys.argv[1]
nsbegin  = int(sys.argv[2])
nsend    = int(sys.argv[3])

wav, fs  = sf.read(filename)

plt.plot(wav[nsbegin:nsend], color='green')
plt.title("input signal")
plt.xlabel("time")
plt.ylabel("amplitude")

plt.show()

Anaconda Distribution

$ which python
/opt/local/bin/python

$ python --version
Python 2.7.14

$ which curl
/opt/local/bin/curl

$ curl --version
curl 7.57.0 (x86_64-apple-darwin17.3.0) libcurl/7.57.0 OpenSSL/1.0.2n zlib/1.2.11 libidn2/2.0.4 libpsl/0.19.1 (+libidn2/2.0.4)
Release-Date: 2017-11-29

$ ./anaconda3/bin/python
Python 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 12:04:33) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin

$ ./anaconda3/bin/curl --version
curl 7.58.0 (x86_64-apple-darwin13.4.0) libcurl/7.58.0 OpenSSL/1.0.2n zlib/1.2.11
Release-Date: 2018-01-24

KiCad and WebGL

You can move the board with your mouse.

What I really would like to display is the board populated with all the components.

STL files and WebGL

You can move around the object using your mouse.

Left click on the image, and move your mouse while holding down. Other controls are also available.

<script src="/js/three.js-dev/build/three.js"></script>
<script src="/js/three.js-dev/examples/js/loaders/STLLoader.js"></script>

<script>
        var loader = new THREE.STLLoader();
        loader.load( 'SMA.stl', function ( geometry ) {
                var material = new THREE.MeshLambertMaterial( { ambient: 0xff5533, color: 0x8f55f3} );
                mesh = new THREE.Mesh( geometry, material );
                APP.scene.add( mesh );
                APP.controls = new THREE.TrackballControls( APP.camera );
                APP.animate();
        });

KiCad and 3D Models (6)

// dimensions in 0.1mm
l=63;
r1=23/2;
r2=6/2;
h2h=8*(50/1000)*25.4*10; echo(h2h);
ll=(h2h-l)/2; echo(ll);

module pin() {
translate([0,0,-r1]) rotate([0,0,0]) cylinder(r=r2,h=r1*3-5, $fn=16); // vertical
translate([0,-5,r1*2]) rotate([90,0,0]) cylinder(r=r2,h=ll-5, $fn=16); // horizozntal
translate([0,-5,r1*2-5]) rotate([0,-90,0]) 
rotate_extrude(angle=90, convexity=10) translate([5, 0]) circle(r2, $fn=16);
}

translate([0,l/2,r1*2]) rotate([90,0,0]) cylinder(r=r1,h=l, $fn=16); // body
translate([0,  h2h/2, 0]) pin();
translate([0, -h2h/2, 0]) rotate([0,0,180]) pin();