|
|
1.1 root 1: #!/usr/bin/env python
2: # Script that can read from a serial device and show timestamps.
3: #
4: # Copyright (C) 2009 Kevin O'Connor <[email protected]>
5: #
6: # This file may be distributed under the terms of the GNU GPLv3 license.
7:
8: # Usage:
9: # tools/readserial.py /dev/ttyUSB0 115200
10:
11: import sys
12: import time
13: import select
1.1.1.2 root 14: import optparse
1.1 root 15:
16: # Reset time counter after this much idle time.
17: RESTARTINTERVAL = 60
18: # Number of bits in a transmitted byte - 8N1 is 1 start bit + 8 data
19: # bits + 1 stop bit.
20: BITSPERBYTE = 10
21:
1.1.1.4 ! root 22: def calibrateserialwrite(outfile, byteadjust):
! 23: # Build 4000 bytes of dummy data.
! 24: data = "0123456789" * 4 + "012345678" + "\n"
! 25: data = data * 80
! 26: while 1:
! 27: st = time.time()
! 28: outfile.write(data)
! 29: outfile.flush()
! 30: et = time.time()
! 31: sys.stdout.write(
! 32: "Wrote %d - %.1fus per char (theory states %.1fus)\n" % (
! 33: len(data), (et-st) / len(data) * 1000000, byteadjust * 1000000))
! 34: sys.stdout.flush()
! 35: time.sleep(3)
! 36:
! 37: def calibrateserialread(infile, byteadjust):
! 38: starttime = lasttime = 0
! 39: totalchars = 0
! 40: while 1:
! 41: select.select([infile], [], [])
! 42: d = infile.read(4096)
! 43: curtime = time.time()
! 44: if curtime - lasttime > 1.0:
! 45: if starttime and totalchars:
! 46: sys.stdout.write(
! 47: "Calibrating on %d bytes - %.1fus per char"
! 48: " (theory states %.1fus)\n" % (
! 49: totalchars,
! 50: float(lasttime - starttime) * 1000000 / totalchars,
! 51: byteadjust * 1000000))
! 52: totalchars = 0
! 53: starttime = curtime
! 54: else:
! 55: totalchars += len(d)
! 56: lasttime = curtime
! 57:
! 58: def readserial(infile, logfile, byteadjust):
1.1 root 59: lasttime = 0
60: while 1:
61: # Read data
62: try:
63: res = select.select([infile, sys.stdin], [], [])
64: except KeyboardInterrupt:
65: sys.stdout.write("\n")
66: break
67: if sys.stdin in res[0]:
68: # Got keyboard input - force reset on next serial input
69: sys.stdin.read(1)
70: lasttime = 0
71: if len(res[0]) == 1:
72: continue
73: d = infile.read(4096)
1.1.1.2 root 74: if not d:
75: break
1.1 root 76: datatime = time.time()
77:
78: datatime -= len(d) * byteadjust
79:
80: # Reset start time if no data for some time
81: if datatime - lasttime > RESTARTINTERVAL:
82: starttime = datatime
83: charcount = 0
84: isnewline = 1
1.1.1.4 ! root 85: msg = "\n\n======= %s (adjust=%.1fus)\n" % (
! 86: time.asctime(time.localtime(datatime)), byteadjust * 1000000)
1.1 root 87: sys.stdout.write(msg)
88: logfile.write(msg)
89: lasttime = datatime
90:
91: # Translate unprintable chars; add timestamps
92: out = ""
93: for c in d:
94: if isnewline:
95: delta = datatime - starttime - (charcount * byteadjust)
96: out += "%06.3f: " % delta
97: isnewline = 0
98: oc = ord(c)
99: charcount += 1
100: datatime += byteadjust
101: if oc == 0x0d:
102: continue
103: if oc == 0x00:
104: out += "<00>\n"
105: isnewline = 1
106: continue
107: if oc == 0x0a:
108: out += "\n"
109: isnewline = 1
110: continue
111: if oc < 0x20 or oc >= 0x7f and oc != 0x09:
112: out += "<%02x>" % oc
113: continue
114: out += c
115:
116: sys.stdout.write(out)
117: sys.stdout.flush()
118: logfile.write(out)
119: logfile.flush()
120:
121: def main():
1.1.1.2 root 122: usage = "%prog [options] [<serialdevice> [<baud>]]"
123: opts = optparse.OptionParser(usage)
124: opts.add_option("-f", "--file",
125: action="store_false", dest="serial", default=True,
126: help="read from file instead of serialdevice")
127: opts.add_option("-n", "--no-adjust",
128: action="store_false", dest="adjustbaud", default=True,
129: help="don't adjust times by serial rate")
1.1.1.4 ! root 130: opts.add_option("-c", "--calibrate-read",
! 131: action="store_true", dest="calibrate_read", default=False,
! 132: help="read from serial port to calibrate it")
! 133: opts.add_option("-C", "--calibrate-write",
! 134: action="store_true", dest="calibrate_write", default=False,
! 135: help="write to serial port to calibrate it")
! 136: opts.add_option("-t", "--time",
! 137: type="float", dest="time", default=None,
! 138: help="time to write one byte on serial port (in us)")
1.1.1.2 root 139: options, args = opts.parse_args()
1.1 root 140: serialport = 0
141: baud = 115200
1.1.1.2 root 142: if len(args) > 2:
143: opts.error("Too many arguments")
144: if len(args) > 0:
145: serialport = args[0]
146: if len(args) > 1:
147: baud = int(args[1])
1.1.1.4 ! root 148: byteadjust = float(BITSPERBYTE) / baud
! 149: if options.time is not None:
! 150: byteadjust = options.time / 1000000.0
! 151: if not options.adjustbaud:
! 152: byteadjust = 0.0
1.1.1.2 root 153:
154: if options.serial:
155: # Read from serial port
1.1.1.3 root 156: try:
157: import serial
158: except ImportError:
159: print """
160: Unable to find pyserial package ( http://pyserial.sourceforge.net/ ).
161: On Linux machines try: yum install pyserial
162: Or: apt-get install python-serial
163: """
164: sys.exit(1)
1.1.1.2 root 165: ser = serial.Serial(serialport, baud, timeout=0)
166: else:
167: # Read from a file
168: ser = open(serialport, 'rb')
169: import fcntl
170: import os
171: fcntl.fcntl(ser, fcntl.F_SETFL
172: , fcntl.fcntl(ser, fcntl.F_GETFL) | os.O_NONBLOCK)
1.1 root 173:
1.1.1.4 ! root 174: if options.calibrate_read:
! 175: calibrateserialread(ser, byteadjust)
! 176: return
! 177: if options.calibrate_write:
! 178: calibrateserialwrite(ser, byteadjust)
! 179: return
! 180:
1.1 root 181: logname = time.strftime("seriallog-%Y%m%d_%H%M%S.log")
182: f = open(logname, 'wb')
1.1.1.4 ! root 183: readserial(ser, f, byteadjust)
1.1 root 184:
185: if __name__ == '__main__':
186: main()
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.