blob: d85392eba67933e85ff58ab1ad53db6dd3759b29 [file] [log] [blame]
Kevin O'Connor2547bb82009-04-19 11:04:59 -04001#!/usr/bin/env python
2# Script that can read from a serial device and show timestamps.
3#
4# Copyright (C) 2009 Kevin O'Connor <kevin@koconnor.net>
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
11import sys
12import time
13import select
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -040014import optparse
Kevin O'Connor2547bb82009-04-19 11:04:59 -040015
16# Reset time counter after this much idle time.
17RESTARTINTERVAL = 60
Kevin O'Connor77443202009-12-05 14:23:27 -050018# Number of bits in a transmitted byte - 8N1 is 1 start bit + 8 data
19# bits + 1 stop bit.
20BITSPERBYTE = 10
Kevin O'Connor2547bb82009-04-19 11:04:59 -040021
Kevin O'Connor8365dee2011-07-09 13:16:24 -040022def 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
37def 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
58def readserial(infile, logfile, byteadjust):
Kevin O'Connora1dadf42009-04-26 21:24:16 -040059 lasttime = 0
Kevin O'Connor2547bb82009-04-19 11:04:59 -040060 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)
Kevin O'Connora1dadf42009-04-26 21:24:16 -040070 lasttime = 0
Kevin O'Connor2547bb82009-04-19 11:04:59 -040071 if len(res[0]) == 1:
72 continue
Kevin O'Connor2547bb82009-04-19 11:04:59 -040073 d = infile.read(4096)
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -040074 if not d:
75 break
Kevin O'Connor58db9c42009-12-12 13:28:38 -050076 datatime = time.time()
77
78 datatime -= len(d) * byteadjust
Kevin O'Connor2547bb82009-04-19 11:04:59 -040079
80 # Reset start time if no data for some time
Kevin O'Connor58db9c42009-12-12 13:28:38 -050081 if datatime - lasttime > RESTARTINTERVAL:
82 starttime = datatime
Kevin O'Connor2547bb82009-04-19 11:04:59 -040083 charcount = 0
84 isnewline = 1
Kevin O'Connor8365dee2011-07-09 13:16:24 -040085 msg = "\n\n======= %s (adjust=%.1fus)\n" % (
86 time.asctime(time.localtime(datatime)), byteadjust * 1000000)
Kevin O'Connora53ab002009-12-05 13:44:39 -050087 sys.stdout.write(msg)
88 logfile.write(msg)
Kevin O'Connor58db9c42009-12-12 13:28:38 -050089 lasttime = datatime
Kevin O'Connor2547bb82009-04-19 11:04:59 -040090
91 # Translate unprintable chars; add timestamps
92 out = ""
93 for c in d:
94 if isnewline:
Kevin O'Connor58db9c42009-12-12 13:28:38 -050095 delta = datatime - starttime - (charcount * byteadjust)
Kevin O'Connor2547bb82009-04-19 11:04:59 -040096 out += "%06.3f: " % delta
97 isnewline = 0
98 oc = ord(c)
99 charcount += 1
Kevin O'Connor58db9c42009-12-12 13:28:38 -0500100 datatime += byteadjust
Kevin O'Connor2547bb82009-04-19 11:04:59 -0400101 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
Kevin O'Connor2547bb82009-04-19 11:04:59 -0400121def main():
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -0400122 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")
Kevin O'Connor8365dee2011-07-09 13:16:24 -0400130 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)")
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -0400139 options, args = opts.parse_args()
Kevin O'Connor2547bb82009-04-19 11:04:59 -0400140 serialport = 0
141 baud = 115200
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -0400142 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])
Kevin O'Connor8365dee2011-07-09 13:16:24 -0400148 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
Kevin O'Connor2547bb82009-04-19 11:04:59 -0400153
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -0400154 if options.serial:
155 # Read from serial port
Kevin O'Connor94330982010-10-17 21:38:38 -0400156 try:
157 import serial
158 except ImportError:
159 print """
160Unable to find pyserial package ( http://pyserial.sourceforge.net/ ).
161On Linux machines try: yum install pyserial
162Or: apt-get install python-serial
163"""
164 sys.exit(1)
Kevin O'Connor2dcd9fa2010-08-28 14:55:32 -0400165 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)
Kevin O'Connor2547bb82009-04-19 11:04:59 -0400173
Kevin O'Connor8365dee2011-07-09 13:16:24 -0400174 if options.calibrate_read:
175 calibrateserialread(ser, byteadjust)
176 return
177 if options.calibrate_write:
178 calibrateserialwrite(ser, byteadjust)
179 return
180
Kevin O'Connor2547bb82009-04-19 11:04:59 -0400181 logname = time.strftime("seriallog-%Y%m%d_%H%M%S.log")
182 f = open(logname, 'wb')
Kevin O'Connor8365dee2011-07-09 13:16:24 -0400183 readserial(ser, f, byteadjust)
Kevin O'Connor2547bb82009-04-19 11:04:59 -0400184
185if __name__ == '__main__':
186 main()