#!/usr/bin/env python

import getopt, sys, serial, threading

# positive-only int -> binary string
bstr_pos = lambda n: n>0 and bstr_pos(n>>1)+str(n&1) or ''

def binary_format(n):
   b = bstr_pos(n)
   if len(b) < 8:
       b = "0" * (8 - len(b)) + b
   b = b[:4] + "." + b[4:]
   return b
    
def next_byte():
   return ord(ser.read())
    
def to_16(slice):
   return (slice[0] << 8) | slice[1]

def usage():
    print """
        rx.py [-n<num>] [-f] [-h] [-b] [-p]

        -n<num>   Number of bytes per line
        -e        Equal spacing of numbers 
        -f        Use framing (won't print until 1,2,3,4 received)
        -h        Hide count
        -b        Format numbers in binary
        -r<rate>  Baud rate
        -p<port>  Port to use (e.g. /dev/ttyS0)

        Press 'return' to reset count while receiving.
        """
#----- main
try:

    count = 0
    class KeyInput( threading.Thread ):
        def run(self):
            global count
            while True:
                sys.stdin.readline()
                count = 0
    KeyInput().start()
    
    try:
        opts, args = getopt.getopt(sys.argv[1:], "n:efhbr:p:")
    except getopt.GetoptError, err:
        print str(err)
        usage()
        sys.exit(1)
    
    n_per_line = 1
    use_framing = False
    hide_count = False
    baud = 115200
    port = "/dev/ttyUSB0"
    format = lambda n: n
    padding = lambda n: n
    for o,a in opts:
        if o == "-n":
            n_per_line = int(a)
        elif o == "-e":
            padding = lambda n: "% 4i" % n
        elif o == "-f":
            use_framing = True
        elif o == "-h":
            hide_count = True
        elif o == "-b":
            format = binary_format
        elif o == "-r":
            baud = int(a)
        elif o == "-p":
            port = a
        else:
            assert False, "unknown option"
    
    ser = serial.Serial(port, baud)
    ser.flushInput()
    
    #print "Reading serial from %s at %i." % (port, baud)
    
    a, b, c, d = 0, 0, 0, 0
    while 1:
       if use_framing:
          while (a, b, c, d) != (1, 2, 3, 4):
             a, b, c, d = b, c, d, next_byte()
    
       if not hide_count:
           print count,
           count += 1
            
       if n_per_line == 1:
           print format(padding(ord(ser.read())))
       else:
           print [format(padding(ord(ser.read()))) for i in range(n_per_line)]

except KeyboardInterrupt:
    sys.exit(1)
except:
    # kill threads by exiting manually on any unhandled exception
    # (prevents "hanging" in surviving threads with KeyboardInterrupt
    # disabled)
    sys.excepthook(*sys.exc_info())
    sys.exit(1)

