2 # Script that can read from a serial device and show timestamps.
4 # Copyright (C) 2009 Kevin O'Connor <kevin@koconnor.net>
6 # This file may be distributed under the terms of the GNU GPLv3 license.
9 # scripts/readserial.py /dev/ttyUSB0 115200
11 import sys, os, time, select, optparse
13 from python23compat import as_bytes
15 # Reset time counter after this much idle time.
17 # Number of bits in a transmitted byte - 8N1 is 1 start bit + 8 data
21 def calibrateserialwrite(outfile, byteadjust):
22 # Build 4000 bytes of dummy data.
23 data = "0123456789" * 4 + "012345678" + "\n"
27 outfile.write(as_bytes(data))
31 "Wrote %d - %.1fus per char (theory states %.1fus)\n" % (
32 len(data), (et-st) / len(data) * 1000000, byteadjust * 1000000))
36 def calibrateserialread(infile, byteadjust):
37 starttime = lasttime = 0
40 select.select([infile], [], [])
43 if curtime - lasttime > 1.0:
44 if starttime and totalchars:
46 "Calibrating on %d bytes - %.1fus per char"
47 " (theory states %.1fus)\n" % (
49 float(lasttime - starttime) * 1000000 / totalchars,
50 byteadjust * 1000000))
57 def readserial(infile, logfile, byteadjust):
62 res = select.select([infile, sys.stdin], [], [])
63 except KeyboardInterrupt:
64 sys.stdout.write("\n")
66 if sys.stdin in res[0]:
67 # Got keyboard input - force reset on next serial input
75 datatime = time.time()
77 datatime -= len(d) * byteadjust
79 # Reset start time if no data for some time
80 if datatime - lasttime > RESTARTINTERVAL:
84 msg = "\n\n======= %s (adjust=%.1fus)\n" % (
85 time.asctime(time.localtime(datatime)), byteadjust * 1000000)
87 logfile.write(as_bytes(msg))
90 # Translate unprintable chars; add timestamps
94 delta = datatime - starttime - (charcount * byteadjust)
95 out += "%06.3f: " % delta
99 datatime += byteadjust
110 if oc < 0x20 or oc >= 0x7f and oc != 0x09:
115 if (sys.version_info > (3, 0)):
116 sys.stdout.buffer.write(out)
118 sys.stdout.write(out)
124 usage = "%prog [options] [<serialdevice> [<baud>]]"
125 opts = optparse.OptionParser(usage)
126 opts.add_option("-f", "--file",
127 action="store_false", dest="serial", default=True,
128 help="read from unix named pipe instead of serialdevice")
129 opts.add_option("-n", "--no-adjust",
130 action="store_false", dest="adjustbaud", default=True,
131 help="don't adjust times by serial rate")
132 opts.add_option("-c", "--calibrate-read",
133 action="store_true", dest="calibrate_read", default=False,
134 help="read from serial port to calibrate it")
135 opts.add_option("-C", "--calibrate-write",
136 action="store_true", dest="calibrate_write", default=False,
137 help="write to serial port to calibrate it")
138 opts.add_option("-t", "--time",
139 type="float", dest="time", default=None,
140 help="time to write one byte on serial port (in us)")
141 options, args = opts.parse_args()
145 opts.error("Too many arguments")
150 byteadjust = float(BITSPERBYTE) / baud
151 if options.time is not None:
152 byteadjust = options.time / 1000000.0
153 if not options.adjustbaud:
157 # Read from serial port
162 Unable to find pyserial package ( http://pyserial.sourceforge.net/ ).
163 On Linux machines try: yum install pyserial
164 Or: apt-get install python-serial
167 ser = serial.Serial(serialport, baud, timeout=0)
169 if options.calibrate_read:
170 calibrateserialread(ser, byteadjust)
172 if options.calibrate_write:
173 calibrateserialwrite(ser, byteadjust)
176 logname = time.strftime("seriallog-%Y%m%d_%H%M%S.log")
177 f = open(logname, 'wb')
179 readserial(ser, f, byteadjust)
183 ser = os.fdopen(os.open(serialport, os.O_RDONLY|os.O_NONBLOCK), 'rb')
184 res = readserial(ser, f, byteadjust)
189 if __name__ == '__main__':