Example #1
0
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)
Example #2
0
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)