Advertisement
osteth

BaudRate.py

Apr 16th, 2017
302
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.67 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. import sys
  4. import time
  5. import serial
  6. from threading import Thread
  7.  
  8. class RawInput:
  9.     """Gets a single character from standard input.  Does not echo to the screen."""
  10.     def __init__(self):
  11.         try:
  12.             self.impl = RawInputWindows()
  13.         except ImportError:
  14.             self.impl = RawInputUnix()
  15.  
  16.     def __call__(self): return self.impl()
  17.  
  18.  
  19. class RawInputUnix:
  20.     def __init__(self):
  21.         import tty, sys
  22.  
  23.     def __call__(self):
  24.         import sys, tty, termios
  25.         fd = sys.stdin.fileno()
  26.         old_settings = termios.tcgetattr(fd)
  27.         try:
  28.             tty.setraw(sys.stdin.fileno())
  29.             ch = sys.stdin.read(1)
  30.         finally:
  31.             termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
  32.         return ch
  33.  
  34.  
  35. class RawInputWindows:
  36.     def __init__(self):
  37.         import msvcrt
  38.  
  39.     def __call__(self):
  40.         import msvcrt
  41.         return msvcrt.getch()
  42.  
  43. class Baudrate:
  44.  
  45.     VERSION = '1.0'
  46.     READ_TIMEOUT = 5
  47.     BAUDRATES = [
  48. #            "1200",
  49. #            "1800",
  50. #            "2400",
  51. #            "4800",
  52.             "9600",
  53.             "38400",
  54.             "19200",
  55.             "57600",
  56.             "115200",
  57.     ]
  58.  
  59.     UPKEYS = ['u', 'U', 'A']
  60.     DOWNKEYS = ['d', 'D', 'B']
  61.  
  62.     MIN_CHAR_COUNT = 25
  63.     WHITESPACE = [' ', '\t', '\r', '\n']
  64.     PUNCTUATION = ['.', ',', ':', ';', '?', '!']
  65.     VOWELS = ['a', 'A', 'e', 'E', 'i', 'I', 'o', 'O', 'u', 'U']
  66.  
  67.     def __init__(self, port=None, threshold=MIN_CHAR_COUNT, timeout=READ_TIMEOUT, name=None, auto=True, verbose=False):
  68.         self.port = port
  69.         self.threshold = threshold
  70.         self.timeout = timeout
  71.         self.name = name
  72.         self.auto_detect = auto
  73.         self.verbose = verbose
  74.         self.index = len(self.BAUDRATES) - 1
  75.         self.valid_characters = []
  76.         self.ctlc = False
  77.         self.thread = None
  78.  
  79.         self._gen_char_list()
  80.  
  81.     def _gen_char_list(self):
  82.         c = ' '
  83.  
  84.         while c <= '~':
  85.             self.valid_characters.append(c)
  86.             c = chr(ord(c) + 1)
  87.  
  88.         for c in self.WHITESPACE:
  89.             if c not in self.valid_characters:
  90.                 self.valid_characters.append(c)
  91.  
  92.     def _print(self, data):
  93.         if self.verbose:
  94.             sys.stderr.write(data)
  95.  
  96.     def Open(self):
  97.         self.serial = serial.Serial(self.port, timeout=self.timeout)
  98.         self.NextBaudrate(0)
  99.  
  100.     def NextBaudrate(self, updn):
  101.  
  102.         self.index += updn
  103.  
  104.         if self.index >= len(self.BAUDRATES):
  105.             self.index = 0
  106.         elif self.index < 0:
  107.             self.index = len(self.BAUDRATES) - 1
  108.  
  109.         sys.stderr.write('\n\n@@@@@@@@@@@@@@@@@@@@@ Baudrate: %s @@@@@@@@@@@@@@@@@@@@@\n\n' % self.BAUDRATES[self.index])
  110.  
  111.         self.serial.flush()
  112.         self.serial.baudrate = self.BAUDRATES[self.index]
  113.         self.serial.flush()
  114.  
  115.     def Detect(self):
  116.         count = 0
  117.         whitespace = 0
  118.         punctuation = 0
  119.         vowels = 0
  120.         start_time = 0
  121.         timed_out = False
  122.         clear_counters = False
  123.  
  124.         if not self.auto_detect:
  125.             self.thread = Thread(None, self.HandleKeypress, None, (self, 1))
  126.             self.thread.start()
  127.  
  128.         while True:
  129.             if start_time == 0:
  130.                 start_time = time.time()
  131.  
  132.             byte = self.serial.read(1)
  133.  
  134.             if byte:
  135.                 if self.auto_detect and byte in self.valid_characters:
  136.                     if byte in self.WHITESPACE:
  137.                         whitespace += 1
  138.                     elif byte in self.PUNCTUATION:
  139.                         punctuation += 1
  140.                     elif byte in self.VOWELS:
  141.                         vowels += 1
  142.  
  143.                     count += 1
  144.                 else:
  145.                     clear_counters = True
  146.  
  147.                 self._print(byte)
  148.  
  149.                 if count >= self.threshold and whitespace > 0 and punctuation > 0 and vowels > 0:
  150.                     break
  151.                 elif (time.time() - start_time) >= self.timeout:
  152.                     timed_out = True
  153.             else:
  154.                 timed_out = True
  155.  
  156.             if timed_out and self.auto_detect:
  157.                 start_time = 0
  158.                 self.NextBaudrate(-1)
  159.                 clear_counters = True
  160.                 timed_out = False
  161.  
  162.             if clear_counters:
  163.                 whitespace = 0
  164.                 punctuation = 0
  165.                 vowels = 0
  166.                 count = 0
  167.                 clear_counters = False
  168.  
  169.             if self.ctlc:
  170.                 break
  171.  
  172.         self._print("\n")
  173.         return self.BAUDRATES[self.index]
  174.  
  175.     def HandleKeypress(self, *args):
  176.         userinput = RawInput()
  177.  
  178.         while not self.ctlc:
  179.             c = userinput()
  180.             if c in self.UPKEYS:
  181.                 self.NextBaudrate(1)
  182.             elif c in self.DOWNKEYS:
  183.                 self.NextBaudrate(-1)
  184.             elif c == '\x03':
  185.                 self.ctlc = True
  186.  
  187.     def MinicomConfig(self, name=None):
  188.         success = True
  189.  
  190.         if name is None:
  191.             name = self.name
  192.  
  193.         config =  "########################################################################\n"
  194.         config += "# Minicom configuration file - use \"minicom -s\" to change parameters.\n"
  195.         config += "pu port             %s\n" % self.port
  196.         config += "pu baudrate         %s\n" % self.BAUDRATES[self.index]
  197.         config += "pu bits             8\n"
  198.         config += "pu parity           N\n"
  199.         config += "pu stopbits         1\n"
  200.         config += "pu rtscts           No\n"
  201.         config += "########################################################################\n"
  202.  
  203.         if name is not None and name:
  204.             try:
  205.                 open("/etc/minicom/minirc.%s" % name, "w").write(config)
  206.             except Exception, e:
  207.                 print "Error saving minicom config file:", str(e)
  208.                 success = False
  209.  
  210.         return (success, config)
  211.  
  212.     def Close(self):
  213.         self.ctlc = True
  214.         self.serial.close()
  215.  
  216.  
  217.  
  218. if __name__ == '__main__':
  219.  
  220.     import subprocess
  221.     from getopt import getopt as GetOpt, GetoptError
  222.  
  223.     def usage():
  224.         baud = Baudrate()
  225.  
  226.         print ""
  227.         print "Baudrate v%s" % baud.VERSION
  228.         print "Craig Heffner, http://www.devttys0.com"
  229.         print ""
  230.         print "Usage: %s [OPTIONS]" % sys.argv[0]
  231.         print ""
  232.         print "\t-p <serial port>       Specify the serial port to use [/dev/ttyUSB0]"
  233.         print "\t-t <seconds>           Set the timeout period used when switching baudrates in auto detect mode [%d]" % baud.READ_TIMEOUT
  234.         print "\t-c <num>               Set the minimum ASCII character threshold used during auto detect mode [%d]" % baud.MIN_CHAR_COUNT
  235.         print "\t-n <name>              Save the resulting serial configuration as <name> and automatically invoke minicom (implies -a)"
  236.         print "\t-a                     Enable auto detect mode"
  237.         print "\t-b                     Display supported baud rates and exit"
  238.         print "\t-q                     Do not display data read from the serial port"
  239.         print "\t-h                     Display help"
  240.         print ""
  241.         sys.exit(1)
  242.  
  243.     def main():
  244.         display = False
  245.         verbose = True
  246.         auto = False
  247.         run = False
  248.         threshold = 25
  249.         timeout = 5
  250.         name = None
  251.         port = '/dev/ttyUSB0'
  252.  
  253.         try:
  254.             (opts, args) = GetOpt(sys.argv[1:], 'p:t:c:n:abqh')
  255.         except GetoptError, e:
  256.             print e
  257.             usage()
  258.  
  259.         for opt, arg in opts:
  260.             if opt == '-t':
  261.                 timeout = int(arg)
  262.             elif opt == '-c':
  263.                 threshold = int(arg)
  264.             elif opt == '-p':
  265.                 port = arg
  266.             elif opt == '-n':
  267.                 name = arg
  268.                 auto = True
  269.                 run = True
  270.             elif opt == '-a':
  271.                 auto = True
  272.             elif opt == '-b':
  273.                 display = True
  274.             elif opt == '-q':
  275.                 verbose = False
  276.             else:
  277.                 usage()
  278.  
  279.         baud = Baudrate(port, threshold=threshold, timeout=timeout, name=name, verbose=verbose, auto=auto)
  280.  
  281.         if display:
  282.             print ""
  283.             for rate in baud.BAUDRATES:
  284.                 print "\t%s" % rate
  285.             print ""
  286.         else:
  287.             print ""
  288.             print "Starting baudrate detection on %s, turn on your serial device now." % port
  289.             print "Press Ctl+C to quit."
  290.             print ""
  291.  
  292.             baud.Open()
  293.  
  294.             try:
  295.                 rate = baud.Detect()
  296.                 print "\nDetected baudrate: %s" % rate
  297.  
  298.                 if name is None:
  299.                     print "\nSave minicom configuration as: ",
  300.                     name = sys.stdin.readline().strip()
  301.                     print ""
  302.  
  303.                 (ok, config) = baud.MinicomConfig(name)
  304.                 if name and name is not None:
  305.                     if ok:
  306.                         if not run:
  307.                             print "Configuration saved. Run minicom now [n/Y]? ",
  308.                             yn = sys.stdin.readline().strip()
  309.                             print ""
  310.                             if yn == "" or yn.lower().startswith('y'):
  311.                                 run = True
  312.  
  313.                         if run:
  314.                             subprocess.call(["minicom", name])
  315.                     else:
  316.                         print config
  317.                 else:
  318.                     print config
  319.             except KeyboardInterrupt:
  320.                 pass
  321.  
  322.             baud.Close()
  323.  
  324.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement