Skip to main content

Python Morse Code Generator

 
#!/usr/bin/python

"""
Morse Code Generator. Geoff Robinson, G4AKW, Version 1.0, 4th December 2011.
Requirements: Python 2.7, Linux OS, alsaaudio.
Usage # python mainmorse.py 

The basic element of Morse code is the dot and all other elements can be defined in terms of multiples of the dot length. The word PARIS is used because this is the length of a typical word in English plain text, it has a total length of 50 dot lengths. If the word PARIS is sent ten times in a minute using normal Morse code timing then the code speed is 10 WPM.

There are 500 dot lengths in a minute for 10 wpm or 1000 dot lengths per min for 20 wpm.
The dot length is therefore 60mS for 20 wpm. The python dictionary 'code'  and the function convert() converts
characters to their dot space equivalents i.e either on or off keying. 

"""
import serial
import time, thread
import random
import sys

import sched
import wave, struct, math
from alsaaudio import *
import signal

def convert(msg):
 """  Take msg and convert it to the correct True or False dot interval values."""
 global start, morselist

 code = {'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':'... ... ... ... ...',' ':' '}


 """ next we go character by character through the message and add in the correct spacing""" 
 
 for ch in msg: 
  
  morse = ''
  if ch == ' ':
   morse = morse + '    ' # 4 spaces plus 3 below = 7 for space
  else:  
   morse = morse + code[ch]
   morse = morse + '   ' # 3 spaces between chars 
   
  for ch1 in morse:
   if ch1 == '.':
    ch1 = True
   else: 
    ch1 = False
   morselist.append(ch1) # morselist is the input buffer
 
 start = 1  



def catcher(signum, _):
 """This is the handler function for the SIGALRM interupt which is generated every dot interval """
 global c,z,morselist,start 
 
 if c != 0:  # if c!=0 a dah is sounding so skip this function for 3 dot intervals
  c = c - 1
  return
 else:
  if (start == 1) and (z < len (morselist)): # check input buffer end not reached

  
   if morselist[z] and morselist[z+1]: # detect a dah
    z = z + 3
    c = 3
    out_dah.write(s_dah)
   
   elif morselist[z]:   # detect a dit
    z += 1
    out_dit.write(s_dit)
   else:     # detect a space
    z += 1

  else:
   return
  return


def mysound(freq, dur) :
 """ Function sounds a freq (Hz) sinusoid with dur (mS) length """

 global s_dit, s_dah, out_dit, out_dah, period_dit, period_dah

 
 rate = 44100    # frame rate
 period_dit = int(dur * 44) # number of frames (44 frames per mS)(slightly less)
 period_dah = int(dur * 44 * 3)

 sig_dit = [ math.sin( 2.0*math.pi*freq*x/rate ) for x in range(period_dit) ]
 sig_dah = [ math.sin( 2.0*math.pi*freq*x/rate ) for x in range(period_dah) ]

 # The scale factor for 32bit resolution

 scale = ( 2**32 - 1 )/2.0

 # Scale the signal list
 sig_32dit = [ int(scale*x) for x in sig_dit ]
 sig_32dah = [ int(scale*x) for x in sig_dah ]

 # sound card device initialization
 out_dit = PCM(type=PCM_PLAYBACK, mode=PCM_NONBLOCK, card='default')
 out_dah = PCM(type=PCM_PLAYBACK, mode=PCM_NONBLOCK, card='default')

 # parameters
 channels = 1
 out_dit.setchannels(channels)
 out_dah.setrate(rate)
 out_dah.setchannels(channels)
 out_dit.setrate(rate)


 # Signed 32 bit samples for each channel (Little Endian byte order)
 out_dit.setformat(PCM_FORMAT_S32_LE)
 out_dah.setformat(PCM_FORMAT_S32_LE)
 out_dit.setperiodsize(period_dit)
 out_dah.setperiodsize(period_dah)

 s_dit=struct.pack('<'+channels*period_dit*'l',*sig_32dit)
 s_dah=struct.pack('<'+channels*period_dah*'l',*sig_32dah) 
 
 # l is long integer size=4 pack requires (88100 times ?) arguments

 # use out_dit.write(s_dit) for dit sound
 # use out_dah.write(s_dah) for dah sound


def main():

 global morselist,y,w,z,c,start

 if (len(sys.argv) > 1):
  speed = sys.argv[1]
          print "The speed is set to", speed, "wpm"

 else:
  speed = 20
  print "The default speed is", speed, "wpm"
  
 y = int (speed)
 x = (1200/y)  # x is dot interval in mS
 w = x/1000.0 # w is dot interval in sec
 z = 0
 c = 0
 start = 0

 
 mysound (800, x) # Sound frequency set to 800Hz

 morselist = []

 signal.signal(signal.SIGALRM, catcher) # Set the handler for signal.SIGALRM to the function catcher.
 signal.setitimer(signal.ITIMER_REAL, w, w) #This timer sends a SIGALRM signal every dot interval.

 a = "_"
 print 'On a newline type cr to end input: '
 while a != '':
 
  try:
   a = raw_input()
 
  except EOFError:  # needed as SIGALRM interupts keyboard input
   
   continue

  
  a = a.lower()
  convert(a)  

main()

Comments

Popular posts from this blog

GNU Radio Waterfall and CW Filter

The following GNU radio application adds a waterfall spectrogram to the previous CW filter program. The plot show 4 CW signals in the audio band (lower sideband) at 7023 kHz. The 700Hz signal is filtered and output to the laptop headphones by the CW bandpass filter. The frequency display is shown after the script which is as follows: #!/usr/bin/env python from gnuradio import gr from gnuradio import audio from lpf_bpf_class import Bandpass from gnuradio.qtgui import qtgui from PyQt4 import QtGui import sys, sip     class cw_filter(gr.top_block):     def __init__(self):         gr.top_block.__init__(self)           sample_rate = 44100         out_rate = 8000         kaiser = Bandpass()         cw_flr = gr.fir_filter_fff(1, kaiser.bpftaps)         decimate = int(sample_rate/out_rate)         Bandpass.cutoff1 = 3000                pre_decim = Bandpass()         dec_flr = gr.fir_filter_fff(1, pre_decim.lpftaps)         dec = gr.keep_one_in_n(gr.sizeof_float, decima

Digital Bandpass Filter FIR design - Python

The python code generates the Finite Impulse Response (FIR) filter coefficients for a lowpass filter (LPF) at 10 (Hz) cut off using firwin from scipy.  A highpass filter is then created by subtracting the lowpass filter output(s) from the output of an allpass filter. To do this the coefficients of the LPF are multiplied by -1 and 1 added to the centre tap (to create the allpass filter with subtraction). A second LPF is then created with a cutoff at 15 (Hz) and the bandpass filter formed by addition of the LPF and HPF coefficients. The program also generates a test sine wave of a given amplitude and power and to this noise from a Normal distribution is added.  The graph below shows the signal and nois, and the signal (green) after filtering. The input snr is approximately 3dB. The frequency response below shows the passband centered on 12.5 (Hz), the Nyquist frequency is 50 (Hz). from numpy import cos, sin, pi, absolute, arange from numpy.random import normal from scipy.

Splunk Cheat Sheet (Linux)

1. set root's password:  sudo su passwd root Enter new UNIX password: < new_root_password > Retype new UNIX password: < new_root_password > passwd: password updated successfully # su - 2. Remove any existing Splunk directories & create user etc: # rm -rf /opt/splunkforwarder # userdel -r splunk # this will remove as above if user splunk's home directory # groupadd siem # useradd -g siem -s /bin/bash -d /home/siem -m siem # vi ~/.profile # chage -I -1 -m -0 -M -99999 -E -1 siem If above fails because of multiple passwd fails: # pam_tally --reset check with #chage -l siem # uname -a # check OS version # dpkg -i splunk-4.3.1...........intel.deb # chown -R siem:siem /opt/splunk # su - siem : $SPLUNK_HOME/bin/splunk start --accept-license : $SPLUNK_HOME/bin/splunk edit user admin -password newpassword -role admin -auth admin:changeme 3. vi ~/.profile (as follows) (OR .bash_profile) # ~/.profile: executed by the command interpreter for log