def morse_to_text(verbose, gpio, period, maxbpm, dashduration): sleep_time = 1 / maxbpm # Calculate minimum sleep duration possible to detect the maximum BPM debounce_delay = 60000 / maxbpm milliseconds_pressed = 0 char_in_morse = "" # Holds string of "-" and "." if not dashduration: print '\nThe duration of dashes and dots and between words and letters needs to be determined.', \ '\nBegin tapping a tempo to set the duration of a dash (also space between letters).', \ '\nTiming will begin upon the first buttom press and be measured for {} milliseconds.\n'.format(period) # Calculate the exact durations for a dot, dash, letter space, and word space count, duration_average = beatcount.beat_counter( verbose, gpio, period, maxbpm) milliseconds_space_dash = duration_average else: milliseconds_space_dash = dashduration milliseconds_dot = milliseconds_space_dash / 3 milliseconds_between_words = milliseconds_dot * 7 # Since pressing a button for an exact period of time, accurate to milliseconds, # is difficult, ranges of acceptable durations are calcuated, with the point # exactly between the exact durations serving as the bounds of acceptable error. milliseconds_dash_error_high = (milliseconds_space_dash + milliseconds_between_words) / 2 milliseconds_dot_error_high = (milliseconds_dot + milliseconds_space_dash) / 2 # Present the exact durations for each unit print '\nDurations acquired (ms = milliseconds):' print 'Between words: {} ms'.format(milliseconds_between_words) print 'Between letters: {} ms'.format(milliseconds_space_dash) print 'Dash: {} ms'.format(milliseconds_space_dash) print 'Dot: {} ms'.format(milliseconds_dot) # Present the ranges of durations that are acceptable for translation print '\nA Dot will register when the pressed duration is between {} and {} ms'.format( debounce_delay, milliseconds_dot_error_high) print 'A Dash will register when the pressed duration is between {} and {} ms'.format( milliseconds_dot_error_high, milliseconds_dash_error_high) print 'A new letter will register when the unpressed duration is between between {} and {} ms'.format( milliseconds_dot_error_high, milliseconds_dash_error_high) print 'A new word will register when the unpressed duration is greater than {} ms'.format( milliseconds_dash_error_high) if not dashduration: print '\nWait 5 seconds before beginning Morse code...\n' time.sleep(5) else: print '' print 'Ready! Morse code translation will begin automatically.\n' while GPIO.input(gpio): # while the button is not pressed time.sleep(sleep_time) while True: # # Begin timing how long the button is pressed # button_duration = int(round(time.time() * 1000)) # Wait while the button is pressed # This times how long the button is pressed for, and excludes periods below the maxbpm # The second condition debounces the input, preventing registering of multiple presses while (GPIO.input(gpio) == False or int(round(time.time() * 1000)) - button_duration < debounce_delay): time.sleep(sleep_time) milliseconds_pressed = int(round(time.time() * 1000)) - button_duration if verbose: print 'Pressed {} ms'.format(milliseconds_pressed), # The duration of the press can only be translated to a dot or a dash # Holding a press for longer than milliseconds_dash_error_high will result in neither a dot or a dash if milliseconds_dot_error_high > milliseconds_pressed > 50: char_in_morse = char_in_morse + "." # Append Dot to Morse code string sys.stdout.write('.') elif milliseconds_dash_error_high > milliseconds_pressed > milliseconds_dot_error_high: char_in_morse = char_in_morse + "-" # Append Dash to Morse code string sys.stdout.write('-') sys.stdout.flush() # # Begin timing how long the button is unpressed # button_duration = int(round(time.time() * 1000)) # Wait for a button press or the wait time exceeds that of a space between letters while ( (GPIO.input(gpio) or int(round(time.time() * 1000)) - button_duration < debounce_delay) and int(round(time.time() * 1000)) - button_duration <= milliseconds_dot_error_high): time.sleep(sleep_time) # If the unpressed duration exceeds that for a new letter, # issue a letter and clear char_in_morse, the Morse code-holding string if int(round(time.time() * 1000)) - button_duration >= milliseconds_dot_error_high: if char_in_morse in morse_to_letters: sys.stdout.write(' [%s] ' % morse_to_letters[char_in_morse]) else: sys.stdout.write(' [NA] ') char_in_morse = "" sys.stdout.flush() # Wait for a button press or the wait time exceeds that of a space between words while (GPIO.input(gpio) and int(round(time.time() * 1000)) - button_duration <= milliseconds_dash_error_high): time.sleep(sleep_time) # If the unpressed duration exceeds that for a space, issue a space if int(round(time.time() * 1000)) - button_duration >= milliseconds_dash_error_high: sys.stdout.write('[ ] ') sys.stdout.flush() # Wait while the button is unpressed # This is a catch if the letter has been translated and a word space has been inserted while GPIO.input(gpio): time.sleep(sleep_time) if verbose: print 'Unpressed {} ms'.format( int(round(time.time() * 1000)) - button_duration)
def morse_to_text(verbose, gpio, period, maxbpm, dashduration): sleep_time = 1 / maxbpm # Calculate minimum sleep duration possible to detect the maximum BPM debounce_delay = 60000 / maxbpm milliseconds_pressed = 0 char_in_morse = "" # Holds string of "-" and "." if not dashduration: print '\nThe duration of dashes and dots and between words and letters needs to be determined.', \ '\nBegin tapping a tempo to set the duration of a dash (also space between letters).', \ '\nTiming will begin upon the first buttom press and be measured for {} milliseconds.\n'.format(period) # Calculate the exact durations for a dot, dash, letter space, and word space count, duration_average = beatcount.beat_counter(verbose, gpio, period, maxbpm) milliseconds_space_dash = duration_average else: milliseconds_space_dash = dashduration milliseconds_dot = milliseconds_space_dash / 3 milliseconds_between_words = milliseconds_dot * 7 # Since pressing a button for an exact period of time, accurate to milliseconds, # is difficult, ranges of acceptable durations are calcuated, with the point # exactly between the exact durations serving as the bounds of acceptable error. milliseconds_dash_error_high = (milliseconds_space_dash + milliseconds_between_words) / 2 milliseconds_dot_error_high = (milliseconds_dot + milliseconds_space_dash) / 2 # Present the exact durations for each unit print '\nDurations acquired (ms = milliseconds):' print 'Between words: {} ms'.format(milliseconds_between_words) print 'Between letters: {} ms'.format(milliseconds_space_dash) print 'Dash: {} ms'.format(milliseconds_space_dash) print 'Dot: {} ms'.format(milliseconds_dot) # Present the ranges of durations that are acceptable for translation print '\nA Dot will register when the pressed duration is between {} and {} ms'.format(debounce_delay, milliseconds_dot_error_high) print 'A Dash will register when the pressed duration is between {} and {} ms'.format(milliseconds_dot_error_high, milliseconds_dash_error_high) print 'A new letter will register when the unpressed duration is between between {} and {} ms'.format(milliseconds_dot_error_high, milliseconds_dash_error_high) print 'A new word will register when the unpressed duration is greater than {} ms'.format(milliseconds_dash_error_high) if not dashduration: print '\nWait 5 seconds before beginning Morse code...\n' time.sleep(5) else: print '' print 'Ready! Morse code translation will begin automatically.\n' while GPIO.input(gpio): # while the button is not pressed time.sleep(sleep_time) while True: # # Begin timing how long the button is pressed # button_duration = int(round(time.time()*1000)) # Wait while the button is pressed # This times how long the button is pressed for, and excludes periods below the maxbpm # The second condition debounces the input, preventing registering of multiple presses while (GPIO.input(gpio) == False or int(round(time.time()*1000)) - button_duration < debounce_delay): time.sleep(sleep_time) milliseconds_pressed = int(round(time.time()*1000)) - button_duration if verbose: print 'Pressed {} ms'.format(milliseconds_pressed), # The duration of the press can only be translated to a dot or a dash # Holding a press for longer than milliseconds_dash_error_high will result in neither a dot or a dash if milliseconds_dot_error_high > milliseconds_pressed > 50: char_in_morse = char_in_morse + "." # Append Dot to Morse code string sys.stdout.write('.') elif milliseconds_dash_error_high > milliseconds_pressed > milliseconds_dot_error_high: char_in_morse = char_in_morse + "-" # Append Dash to Morse code string sys.stdout.write('-') sys.stdout.flush() # # Begin timing how long the button is unpressed # button_duration = int(round(time.time()*1000)) # Wait for a button press or the wait time exceeds that of a space between letters while ((GPIO.input(gpio) or int(round(time.time()*1000)) - button_duration < debounce_delay) and int(round(time.time()*1000)) - button_duration <= milliseconds_dot_error_high): time.sleep(sleep_time) # If the unpressed duration exceeds that for a new letter, # issue a letter and clear char_in_morse, the Morse code-holding string if int(round(time.time()*1000)) - button_duration >= milliseconds_dot_error_high: if char_in_morse in morse_to_letters: sys.stdout.write(' [%s] ' % morse_to_letters[char_in_morse]) else: sys.stdout.write(' [NA] ') char_in_morse = "" sys.stdout.flush() # Wait for a button press or the wait time exceeds that of a space between words while (GPIO.input(gpio) and int(round(time.time()*1000)) - button_duration <= milliseconds_dash_error_high): time.sleep(sleep_time) # If the unpressed duration exceeds that for a space, issue a space if int(round(time.time()*1000)) - button_duration >= milliseconds_dash_error_high: sys.stdout.write('[ ] ') sys.stdout.flush() # Wait while the button is unpressed # This is a catch if the letter has been translated and a word space has been inserted while GPIO.input(gpio): time.sleep(sleep_time) if verbose: print 'Unpressed {} ms'.format(int(round(time.time()*1000)) - button_duration)
def menu(): parser = argparse.ArgumentParser( description='Beat counter (bpm) and Morse code translator') beat_counter = parser.add_argument_group('Beat counter') beat_counter.add_argument('-b', '--bpmcount', action='store_true', help="Start program to count beats (bpm)") beat_counter.add_argument( '-m', '--maxbpm', metavar='MAXBPM', type=int, help= 'Set maximum detectable BPM (lower number improves accuracy, higher numbers may register erroneous taps, below 2000 should be accurate), default: 2000', default=2000, required=False) beat_counter.add_argument( '-p', '--period', metavar='PERIOD', type=int, help= 'Period of time between BPM calculations (milliseconds), default: 5000', default=5000, required=False) morse_translator = parser.add_argument_group('Morse code translator') morse_translator.add_argument('-mt', '--morsetotext', action='store_true', help="Translate Morse code to text") morse_translator.add_argument('-tm', '--texttomorse', action='store_true', help="Translate text to Morse code") morse_translator.add_argument( '-d', '--dashduration', metavar='DASHDURATION', type=int, help= 'Duration of a dash (Morse-to-text default: none, Text-to-Morse default: 300 ms). If set with -mt the tempo detection will be overridden.', default=0, required=False) misc_options = parser.add_argument_group('Miscelaneous') misc_options.add_argument( '-g', '--gpio', metavar='GPIO', type=int, help='GPIO pin connected to the telegraph (using BCM numbering)') misc_options.add_argument('-v', '--verbose', action='store_true', help="Print more information to the terminal") args = parser.parse_args() if os.geteuid() and not args.texttomorse: print "Script must be ran as root to access GPIO" sys.exit(0) ######################################## # # # Setup Options # # # ######################################## if not (args.bpmcount or args.morsetotext or args.texttomorse): parser.error( 'No action requested, add --bpmcount or --morsetotext or --texttomorse' ) elif sum(map(bool, [args.bpmcount, args.morsetotext, args.texttomorse])) != 1: parser.error( 'Can only select one: --bpmcount (-b), --morsetotext (-mt), or --texttomorse (-tm)' ) elif args.bpmcount: if not args.gpio: parser.error('Need to specify GPIO pin with --gpio') else: print 'Beats per minute (BPM) counter', elif args.morsetotext: if not args.gpio: parser.error('Need to specify GPIO pin with --gpio') else: print 'Morse code to text translator', elif args.texttomorse: print 'Text to Morse code translator (use only A-Z, 0-9, spaces, and symbols /?\'!@$&()_-+=,.;:")', if args.verbose: print '(Verbose)' else: print '' ######################################## # # # Setup GPIO # # # ######################################## if args.gpio: print 'Setting up GPIO {}:'.format(args.gpio), try: GPIO.setmode(GPIO.BCM) GPIO.setup(args.gpio, GPIO.IN, pull_up_down=GPIO.PUD_UP) except: print 'Fail' else: print 'Success' ######################################## # # # Beat Counter # # # ######################################## if args.bpmcount: print 'Tempo calculation period: {} milliseconds, Max BPM: {} BPM, Debounce Delay: {} ms'.format( args.period, args.maxbpm, 60000 / args.maxbpm) print '\nBegin tapping a tempo to identify the duration between beats.', \ '\nCalculations will only be performed while there is tapping.', \ '\nTiming will begin upon the first buttom press and be measured every {} milliseconds.\n'.format(args.period) while True: count, duration_average = beatcount.beat_counter( args.verbose, args.gpio, args.period, args.maxbpm) print '\nCalculated from total number of beats over time: {} beats per {} ms = {} BPM'.format( count, args.period, count * (60 / (args.period / 1000))) print 'Calculated from average duration between beats: {} ms per beat = {} BPM\n'.format( duration_average, 60000 / duration_average) ######################################## # # # Morse Code to Text Translator # # # ######################################## if args.morsetotext: if args.dashduration == 0: dashduration = 300 else: dashduration = args.dashduration if dashduration / 3 < 60000 / args.maxbpm: parser.error('--dashduration too low. Increase -d or degrease -b') print 'Tempo calculation period: {} milliseconds, Max BPM: {} BPM, Debounce Delay: {} ms'.format( args.period, args.maxbpm, 60000 / args.maxbpm) translate.morse_to_text(args.verbose, args.gpio, args.period, args.maxbpm, args.dashduration) ######################################## # # # Text to Morse Code Translator # # # ######################################## if args.texttomorse: dashduration = args.dashduration if not dashduration: dashduration = 300 # Default dash time (milliseconds) print 'Dash Duration: {} ms'.format(dashduration) translate.text_to_morse(dashduration)
def menu(): parser = argparse.ArgumentParser(description='Beat counter (bpm) and Morse code translator') beat_counter = parser.add_argument_group('Beat counter') beat_counter.add_argument('-b', '--bpmcount', action='store_true', help="Start program to count beats (bpm)") beat_counter.add_argument('-m','--maxbpm', metavar='MAXBPM', type=int, help='Set maximum detectable BPM (lower number improves accuracy, higher numbers may register erroneous taps, below 2000 should be accurate), default: 2000', default=2000, required=False) beat_counter.add_argument('-p','--period', metavar='PERIOD', type=int, help='Period of time between BPM calculations (milliseconds), default: 5000', default=5000, required=False) morse_translator = parser.add_argument_group('Morse code translator') morse_translator.add_argument('-mt', '--morsetotext', action='store_true', help="Translate Morse code to text") morse_translator.add_argument('-tm', '--texttomorse', action='store_true', help="Translate text to Morse code") morse_translator.add_argument('-d','--dashduration', metavar='DASHDURATION', type=int, help='Duration of a dash (Morse-to-text default: none, Text-to-Morse default: 300 ms). If set with -mt the tempo detection will be overridden.', default=0, required=False) misc_options = parser.add_argument_group('Miscelaneous') misc_options.add_argument('-g','--gpio', metavar='GPIO', type=int, help='GPIO pin connected to the telegraph (using BCM numbering)') misc_options.add_argument('-v', '--verbose', action='store_true', help="Print more information to the terminal") args = parser.parse_args() if os.geteuid() and not args.texttomorse: print "Script must be ran as root to access GPIO" sys.exit(0) ######################################## # # # Setup Options # # # ######################################## if not (args.bpmcount or args.morsetotext or args.texttomorse): parser.error('No action requested, add --bpmcount or --morsetotext or --texttomorse') elif sum(map(bool, [args.bpmcount, args.morsetotext, args.texttomorse])) != 1: parser.error('Can only select one: --bpmcount (-b), --morsetotext (-mt), or --texttomorse (-tm)') elif args.bpmcount: if not args.gpio: parser.error('Need to specify GPIO pin with --gpio') else: print 'Beats per minute (BPM) counter', elif args.morsetotext: if not args.gpio: parser.error('Need to specify GPIO pin with --gpio') else: print 'Morse code to text translator', elif args.texttomorse: print 'Text to Morse code translator (use only A-Z, 0-9, spaces, and symbols /?\'!@$&()_-+=,.;:")', if args.verbose: print '(Verbose)' else: print '' ######################################## # # # Setup GPIO # # # ######################################## if args.gpio: print 'Setting up GPIO {}:'.format(args.gpio), try: GPIO.setmode(GPIO.BCM) GPIO.setup(args.gpio, GPIO.IN, pull_up_down=GPIO.PUD_UP) except: print 'Fail' else: print 'Success' ######################################## # # # Beat Counter # # # ######################################## if args.bpmcount: print 'Tempo calculation period: {} milliseconds, Max BPM: {} BPM, Debounce Delay: {} ms'.format(args.period, args.maxbpm, 60000 / args.maxbpm) print '\nBegin tapping a tempo to identify the duration between beats.', \ '\nCalculations will only be performed while there is tapping.', \ '\nTiming will begin upon the first buttom press and be measured every {} milliseconds.\n'.format(args.period) while True: count, duration_average = beatcount.beat_counter(args.verbose, args.gpio, args.period, args.maxbpm) print '\nCalculated from total number of beats over time: {} beats per {} ms = {} BPM'.format(count, args.period, count * (60 / (args.period / 1000))) print 'Calculated from average duration between beats: {} ms per beat = {} BPM\n'.format(duration_average, 60000 / duration_average) ######################################## # # # Morse Code to Text Translator # # # ######################################## if args.morsetotext: if args.dashduration == 0: dashduration = 300 else: dashduration = args.dashduration if dashduration / 3 < 60000 / args.maxbpm: parser.error('--dashduration too low. Increase -d or degrease -b') print 'Tempo calculation period: {} milliseconds, Max BPM: {} BPM, Debounce Delay: {} ms'.format(args.period, args.maxbpm, 60000 / args.maxbpm) translate.morse_to_text(args.verbose, args.gpio, args.period, args.maxbpm, args.dashduration) ######################################## # # # Text to Morse Code Translator # # # ######################################## if args.texttomorse: dashduration = args.dashduration if not dashduration: dashduration = 300 # Default dash time (milliseconds) print 'Dash Duration: {} ms'.format(dashduration) translate.text_to_morse(dashduration)