aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--README.md7
-rw-r--r--demo/DMP2305U.mod25
-rw-r--r--demo/reverse-polarity/reverse-polarity_normal.asc46
-rw-r--r--demo/reverse-polarity/reverse-polarity_normal.plt26
-rw-r--r--demo/reverse-polarity/reverse-polarity_reversed.asc46
-rw-r--r--ee/__init__.py109
-rw-r--r--ee/tools/__init__.py0
-rw-r--r--ee/tools/read_ltspice_raw.py27
-rw-r--r--requirements.txt6
10 files changed, 299 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b7e58a7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+*.pyc
+env
+
+# LTSpice
+demo/*/*.net
+demo/*/*.raw
+demo/*/*.log
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1bcc212
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+# LTSpice binary format
+
+## 'real' data
+
+The data are a sequence of chunks, one chunk for each point. Each chunk
+contain values for all variables. The first variable is a float64,
+all the others are float32.
diff --git a/demo/DMP2305U.mod b/demo/DMP2305U.mod
new file mode 100644
index 0000000..3935b20
--- /dev/null
+++ b/demo/DMP2305U.mod
@@ -0,0 +1,25 @@
+*---------- DMP2305U Spice Model ----------
+.SUBCKT DMP2305U 10 20 30
+* TERMINALS: D G S
+M1 1 2 3 3 PMOS L = 1E-006 W = 1E-006
+RD 10 1 0.03653
+RS 30 3 0.001
+RG 20 2 23
+CGS 2 3 6.954E-010
+EGD 12 30 2 1 1
+VFB 14 30 0
+FFB 2 1 VFB 1
+CGD 13 14 8.85E-010
+R1 13 30 1
+D1 13 12 DLIM
+DDG 14 15 DCGD
+R2 12 15 1
+D2 30 15 DLIM
+DSD 10 3 DSUB
+.MODEL PMOS PMOS LEVEL = 3 U0 = 400 VMAX = 1.385E+005 ETA = 0.001
++ TOX = 6E-008 NSUB = 1E+016 KP = 24.44 KAPPA = 0.8442 VTO = -0.8978
+.MODEL DCGD D CJO = 3.468E-010 VJ = 0.2064 M = 0.3945
+.MODEL DSUB D IS = 4.536E-009 N = 1.339 RS = 0.05752 BV = 30 CJO = 2.406E-011 VJ = 1.677E-012 M = 0.8
+.MODEL DLIM D IS = 0.0001
+.ENDS
+*Diodes DMP2305U Spice Model v1.0 Last Revised 2011/6/20 \ No newline at end of file
diff --git a/demo/reverse-polarity/reverse-polarity_normal.asc b/demo/reverse-polarity/reverse-polarity_normal.asc
new file mode 100644
index 0000000..1a15aff
--- /dev/null
+++ b/demo/reverse-polarity/reverse-polarity_normal.asc
@@ -0,0 +1,46 @@
+Version 4
+SHEET 1 2056 680
+WIRE 320 -208 144 -208
+WIRE 544 -208 416 -208
+WIRE 656 -208 544 -208
+WIRE 144 -160 144 -208
+WIRE 544 -96 544 -208
+WIRE 656 -96 656 -208
+WIRE 144 -48 144 -80
+WIRE 144 -32 144 -48
+WIRE 144 80 144 48
+WIRE 400 80 400 -160
+WIRE 400 80 144 80
+WIRE 544 80 544 -32
+WIRE 544 80 400 80
+WIRE 656 80 656 -16
+WIRE 656 80 544 80
+WIRE 144 112 144 80
+FLAG 144 112 0
+FLAG 144 -208 Bat
+FLAG 656 -208 Load
+FLAG 144 -48 BatI
+SYMBOL pmos 320 -160 R270
+SYMATTR InstName M1
+SYMATTR Value DMP2305U
+SYMATTR Prefix X
+SYMBOL res 160 -64 R180
+WINDOW 0 36 76 Left 2
+WINDOW 3 36 40 Left 2
+SYMATTR InstName Rint
+SYMATTR Value {Rint}
+SYMBOL voltage 144 -48 R0
+WINDOW 3 24 44 Left 2
+WINDOW 123 0 0 Left 2
+WINDOW 39 0 0 Left 2
+SYMATTR Value 3.3
+SYMATTR InstName V1
+SYMBOL res 640 -112 R0
+SYMATTR InstName Rload
+SYMATTR Value 1000
+SYMBOL cap 528 -96 R0
+SYMATTR InstName Cdec
+SYMATTR Value 10µ
+TEXT 120 192 Left 2 !.include ../DMP2305U.mod
+TEXT 120 224 Left 2 !.op 1us
+TEXT 120 248 Left 2 !.step param Rint list 25 125 200\n* http://data.energizer.com/pdfs/cr2032.pdf
diff --git a/demo/reverse-polarity/reverse-polarity_normal.plt b/demo/reverse-polarity/reverse-polarity_normal.plt
new file mode 100644
index 0000000..1ae4c52
--- /dev/null
+++ b/demo/reverse-polarity/reverse-polarity_normal.plt
@@ -0,0 +1,26 @@
+[Operating Point]
+{
+ Npanes: 2
+ Active Pane: 1
+ {
+ traces: 1 {524291,0,"V(load)"}
+ X: (' ',0,25,20,200)
+ Y[0]: (' ',2,2.7,0.05,3.25)
+ Y[1]: ('p',0,1e+308,5e-012,-1e+308)
+ Volts: (' ',0,0,2,2.7,0.05,3.25)
+ Log: 0 0 0
+ PltMag: 1
+ PltPhi: 1 0
+ },
+ {
+ traces: 2 {336592898,0,"Ix(M1:G)"} {524292,1,"(V(bat)-V(load))*I(Rload)"}
+ X: (' ',0,25,20,200)
+ Y[0]: ('p',0,-3e-010,5e-012,-2.45e-010)
+ Y[1]: ('n',0,4.5e-007,1e-008,5.8e-007)
+ Amps: ('p',0,0,0,-3e-010,5e-012,-2.45e-010)
+ Units: "W" ('n',0,0,2,4.5e-007,1e-008,5.8e-007)
+ Log: 0 0 0
+ PltMag: 1
+ PltPhi: 1 0
+ }
+}
diff --git a/demo/reverse-polarity/reverse-polarity_reversed.asc b/demo/reverse-polarity/reverse-polarity_reversed.asc
new file mode 100644
index 0000000..b0e4d0c
--- /dev/null
+++ b/demo/reverse-polarity/reverse-polarity_reversed.asc
@@ -0,0 +1,46 @@
+Version 4
+SHEET 1 2056 680
+WIRE 320 -208 144 -208
+WIRE 544 -208 416 -208
+WIRE 656 -208 544 -208
+WIRE 144 -160 144 -208
+WIRE 544 -96 544 -208
+WIRE 656 -96 656 -208
+WIRE 144 -48 144 -80
+WIRE 144 -32 144 -48
+WIRE 144 80 144 48
+WIRE 400 80 400 -160
+WIRE 400 80 144 80
+WIRE 544 80 544 -32
+WIRE 544 80 400 80
+WIRE 656 80 656 -16
+WIRE 656 80 544 80
+WIRE 144 112 144 80
+FLAG 144 112 0
+FLAG 144 -208 Bat
+FLAG 656 -208 Load
+FLAG 144 -48 BatI
+SYMBOL pmos 320 -160 R270
+SYMATTR InstName M1
+SYMATTR Value DMP2305U
+SYMATTR Prefix X
+SYMBOL res 160 -64 R180
+WINDOW 0 36 76 Left 2
+WINDOW 3 36 40 Left 2
+SYMATTR InstName Rint
+SYMATTR Value {Rint}
+SYMBOL voltage 144 64 R180
+WINDOW 3 24 44 Left 2
+WINDOW 123 0 0 Left 2
+WINDOW 39 0 0 Left 2
+SYMATTR Value 3.3
+SYMATTR InstName V1
+SYMBOL res 640 -112 R0
+SYMATTR InstName Rload
+SYMATTR Value 1000
+SYMBOL cap 528 -96 R0
+SYMATTR InstName Cdec
+SYMATTR Value 10µ
+TEXT 120 192 Left 2 !.include ../DMP2305U.mod
+TEXT 120 224 Left 2 !.op 1us
+TEXT 120 248 Left 2 !.step param Rint list 25 125 200\n* http://data.energizer.com/pdfs/cr2032.pdf
diff --git a/ee/__init__.py b/ee/__init__.py
new file mode 100644
index 0000000..5c26c0a
--- /dev/null
+++ b/ee/__init__.py
@@ -0,0 +1,109 @@
+import sympy
+import numpy as np
+
+__all__ = [
+ 'read_ltspice_raw'
+]
+
+class LtSpiceRaw(object):
+ def __init__(self, variables, values):
+ self.variables = variables
+ self.values = values
+
+ def get_values(self, variable):
+ v = [v for v in self.variables if v.expression == variable]
+ if len(v) != 1:
+ raise Error('Unknown variable: ' + str(variable))
+ return self.values[v[0].idx]
+
+class LtSpiceVariable(object):
+ def __init__(self, idx, expression, kind):
+ self.idx = idx
+ self.expression = expression
+ self.kind = kind
+
+class LtSpiceReader(object):
+
+ def __init__(self, f):
+ self.f = f
+ self.mode = 'header'
+ self.headers = {}
+
+ def read_header(self, line):
+ sep = line.find(':')
+ key = line[0:sep]
+ value = line[sep + 1:].strip()
+
+# print("key='{}', value='{}'".format(key, str(value)))
+
+ if key == 'Binary':
+ self.set_binary_mode()
+ elif key == 'Variables':
+ self.no_variables = int(self.headers['No. Variables'])
+ self.variables = []
+ self.mode = 'variables'
+ else:
+ self.headers[key] = value
+
+ def read_variable(self, line):
+ parts = line.split('\t')
+ idx = int(parts[1])
+ expression = parts[2]
+ kind = parts[3]
+ self.variables.append(LtSpiceVariable(idx, expression, kind))
+
+ if len(self.variables) == self.no_variables:
+ self.mode = 'header'
+
+ def set_binary_mode(self):
+ self.mode = 'binary'
+
+ def read_binary(self):
+ pos = self.f.tell()
+ # Skip an extra '\0'
+ self.f.seek(pos + 1)
+ no_points = int(self.headers['No. Points'])
+ no_variables = int(self.headers['No. Variables'])
+# print("variables={}, no_points={}, pos={}".format(no_variables, no_points, pos))
+ self.values = vs = np.zeros((no_variables, no_points))
+ for p in range(no_points):
+ vs[0][p] = np.fromfile(self.f, count=1, dtype='float64')
+ pointdata = np.fromfile(self.f, count=no_variables - 1, dtype='float32')
+# print("value={:0=0.15e}".format(vs[0][p]))
+ for v in range(1, no_variables):
+# print("p={}, v={}".format(p, v))
+# print(" value={:0=0.15e}".format(pointdata[v - 1]))
+ vs[v][p] = pointdata[v - 1]
+
+ def read(self):
+ while True:
+ line = self.f.readline();
+
+ if len(line) == 0:
+ break
+
+ if line[0] == 0:
+ line = line[1:]
+ if line[-1] == 10:
+ line = line[:-1]
+# print("len(line)={}, line={}".format(len(line), str(line)))
+ line = str(line, encoding="utf-16")
+
+ if self.mode == 'header':
+ self.read_header(line)
+ elif self.mode == 'variables':
+ self.read_variable(line)
+
+ # The binary data can't be read with readline()
+ if self.mode == 'binary':
+# self.f.read()
+ self.read_binary()
+ break
+
+ return LtSpiceRaw(self.variables, self.values)
+
+def read_ltspice_raw(filename):
+
+ with open(filename, mode="rb") as f:
+ r = LtSpiceReader(f)
+ return r.read()
diff --git a/ee/tools/__init__.py b/ee/tools/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ee/tools/__init__.py
diff --git a/ee/tools/read_ltspice_raw.py b/ee/tools/read_ltspice_raw.py
new file mode 100644
index 0000000..0b3b7e1
--- /dev/null
+++ b/ee/tools/read_ltspice_raw.py
@@ -0,0 +1,27 @@
+import ee
+import sys
+
+raw = ee.read_ltspice_raw(sys.argv[1])
+
+#print("Variables:")
+#for i, v in enumerate(raw.variables):
+# print("{:2}: kind: {:20} expression: {}".format(i, v.kind, v.expression))
+
+#for i, v in enumerate(raw.variables):
+# print("{:2}: kind: {:20} expression: {}".format(i, v.kind, v.expression))
+# for p in raw.values[i]:
+# print(" {}".format(p))
+
+xs = raw.get_values('V(load)')
+
+import matplotlib
+matplotlib.use('Agg')
+
+import matplotlib.pyplot as plt
+from matplotlib.ticker import FuncFormatter, MaxNLocator
+fig = plt.figure()
+ax = fig.add_subplot(111)
+ax.plot(xs)
+
+with open("ltspice.png", "wb") as f:
+ plt.savefig(f, format="png")
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..5308763
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,6 @@
+sympy==1.0
+mpmath==0.19
+pkg-resources==0.0.0
+numpy==1.13.1
+parsec==3.3
+matplotlib==2.0.2