-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathi2c-plot.py
executable file
·120 lines (100 loc) · 3.46 KB
/
i2c-plot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
i2c-plot.py
Script for plotting data streams from I2C. Needs file for each SDA and SCL capture in a TSV format with the first column for time (microseconds) and second being state (1 or 0). These are generated by the gpio-dump.py
The script uses the gpio-dump-template.svg as a template and adds elements to it.
The SCL is depicted as a square wave and high periods on the SDA are depicted as blue blocks.
Dependencies:
python-bs4
python-lxml
ToDo:
-set image width to match plot.
-make a I2C reading library which automatically assigns labels.
Changelog:
2015-12-25: Created (Devon Fyson)
'''
from bs4 import BeautifulSoup #http://www.crummy.com/software/BeautifulSoup/bs4/doc/
#user vars
offset=20 #pixels to offset first transition.
#scaleAuto=False #automatically scale time.
timeScale=10 #microseconds per pixel.
sdaLog="gpio-dump_sda.log" #file with i2c sda data.
sclLog="gpio-dump_scl.log" #file with i2c scl data
outputFile="gpio-dump.svg"
limit=100 #max number of state changes to process incase things get crazy.
#internal vars
sda1=0 #time of first SDA interupt.
scl1=0 #time of first SCL interupt.
logOffset=0 #offset in logfile.
f1 = open(sdaLog, 'r')
f2 = open(sclLog, 'r')
sda1 = int(f1.readline().split("\t",1)[0]) #get the first timestamp
scl1 = int(f2.readline().split("\t",1)[0])
f1.seek(0)
f2.seek(0)
# load the SVG template.
with open ("gpio-dump-template.svg", "r") as f:
data=f.read()#.replace('\n', '')
soup = BeautifulSoup(data, "xml")
sdaXML=soup.find(id="sda")
sclXML=soup.find(id="scl")
# get the time of the first state change for either SDA or SCL (SDA should usually be first)
if scl1 <= sda1:
logOffset=scl1
else:
logOffset=sda1
# parse SDA data to SVG.
t2 = s2 = i = 0
for line in f1:
if line.strip():
l = line.split("\t",2) #get time and state
t1 = int(l[0])-logOffset+float(offset*timeScale)
s1 = int(l[1])
if s1 == 0:
tag = soup.new_tag("rect")
tag['y'] = "-15"
tag['x'] = str(float(t2/timeScale))
tag['height'] = "30"
tag['width'] = str(float((t1-t2)/timeScale))
tag['class'] = "sda"
sdaXML.append(tag)
if (s1 == s2) & (t2 > 0): #two consecutive interrupts shouldn't have same value. But dont check fisrt.
print("Warning: two consecutive states are the same for SDA at "+str(t2+logOffset-float(offset*timeScale)))
t2 = t1
s2 = s1
i = i+1
if i >= limit:
break
# parse SCL data to SVG.
t2 = s2 = i = 0
for line in f2:
if line.strip():
l = line.split("\t",2) #get time and state
t1 = int(l[0])-logOffset+float(offset*timeScale)
s1 = int(l[1])
#vertical line denoting a new clock sequence (transition from 1 to 0)
tag = soup.new_tag("path")
tag['d'] = "m "+str(float(t1/timeScale))+",-15 0,30"
tag['class'] = "scl"+str(s1)
sclXML.append(tag)
#put in connecting lines between adjacent vertical lines to make it look more like a square wave clock signal.
tag = soup.new_tag("path")
if (s1 == 0):
tag['d'] = "m "+str(float(t2/timeScale))+",-15 "+str(float((t1-t2)/timeScale))+",0"
else:
tag['d'] = "m "+str(float(t2/timeScale))+",15 "+str(float((t1-t2)/timeScale))+",0"
tag['class'] = "scl1"
sclXML.append(tag)
if (s1 == s2) & (t2 > 0): #two consecutive interrupts shouldn't have same value. But dont check fisrt.
print("Warning: two consecutive states are the same for SCL at "+str(t2+logOffset-float(offset*timeScale)))
t2 = t1
s2 = s1
i = i+1
if i >= limit:
break
f1.close()
f2.close()
#write the SVG to file.
with open(outputFile, 'w') as f:
f.write(soup.prettify())