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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
* Fourier Series Function for SPICE
* This script is offered here for learning purposes, even if it is outdated
* and superseeded by the spec function and especially by the much faster fft function.
* You may use this script in conjunction with e.g. a ringoscillator output (see
* the ngspice manual, chapter 17).
.control
begin
* Variable argc delivers the number of command line parameters given by the user
* after the 'spectrum' command
if ($argc lt 4)
echo Error: Too few arguments.
echo ' 'Spectrum produces a plot containing a fourier series transformation of
echo ' 'the specified vectors
echo usage: spectrum startfreq stop step vec [[vec] ...]
goto bottom
end
* Check if vectors 'time' and any input vector(s) are available
* argv[n] delivers the command line entries after the 'spectrum' command,
* starting with argv[1]. $argv[4-len] delivers the value of all tokens,
* starting with postion 4 till the end of the command line
if ( time eq time )
foreach vec $argv[4-len]
if ( $vec eq $vec )
else
goto bottom
end
end
else
echo ' 'Spectrum can not work without a time vector from a transient analysis.
goto bottom
end
* generate a new plot entitled 'scratch', which will hold intermediate
* results and will be discarded after their evaluation.
set dt=$curplot
set title=$curplottitle
set curplot=new
set scratch=$curplot
* A vector 'span' is created in the 'scratch' plot to hold the time difference
* of the transient simulation. {$dt}.time allows to access the 'time' vector
* from the dt plot (which is normally named 'tranx' with x a consecutoive
* integer number, depending on the amount of transient simulations already run
* in the present job.
let span={$dt}.time[length({$dt}.time)-1]-{$dt}.time[0]
* Calculate the number of steps in all of the spectra to be evaluated below
if ($argv[3] gt 0.999/span)
let fpoints= ( $argv[2] - $argv[1] ) / $argv[3] +1
if (fpoints < 2)
echo frequency start stop or step not correctly specified
goto reset
end
else
echo Error: time span is not long enough for a step frequency of $argv[3] Hz
goto reset
end
let lent = length({$dt}.time)
set lent = "$&lent"
let nyquist = {$lent}/2/span
if ($argv[2] gt nyquist)
echo Error: The nyquist limit is exceeded, try a frequency less than "$&nyquist" Hz
goto reset
end
set fpoints="$&fpoints"
* generate a new plot to hold the spectra
set curplot=new
set spec=$curplot
set curplottitle=$title
set curplotname='Spectrum Analysis'
* argv[3] is the third agrgument from the input line
* spectrum 1 1000MEG 10MEG v(out25)
* that is the delta frequency
* The fcn vector(n) creates a vector of length n, its elements have
* the values 0, 1, 2, 3, ..., n-2, n-1. Each element then is multiplied
* with the frequency step value.
let frequency=vector( $fpoints )*$argv[3]
* Add an frequency offset to each element of vector 'frequency'
* to suppress the (typically) large dc component.
dowhile frequency[1] < ( $argv[1] + 1e-9 )
let frequency = frequency + $argv[3]
end
* For each input vector given on the command line,
* create a new vector for complex numbers
foreach vec $argv[4-len]
let $vec = vector( $fpoints ) + j(vector( $fpoints ))
reshape $vec [{$fpoints}]
end
* $scratch is a plot for intermediate results, will be destroyed during cleanup
* $dt is the plot with the original data
* $spec is a plot for storing the spectrum
set curplot=$scratch
* some test
let npers=1
let test = span-2/$argv[3] + 1e-9
while test > 0
let npers = npers + 1
let test = test-1/$argv[3]
end
* Do the spectrum calculations
let ircle = 2*pi*max(-1,({$dt}.time-{$dt}.time[{$lent}-1])*{$argv[3]}/npers)
let win = 1 - cos(ircle)
let ircle = npers*ircle
let circle = ircle * ({$spec}.frequency[0]/$argv[3] - 1)
let k=vector( $fpoints )
foreach k $&k
let circle = circle + ircle
foreach vec $argv[4-len]
let tmp = win*{$dt}.{$vec}
let {$spec}.{$vec}[{$k}] = 2*(mean(cos(circle)*tmp),mean(sin(circle)*tmp))
end
end
* plot (and write) the generated spectrum
set curplot = $spec
settype frequency frequency
foreach vec $argv[4-len]
let spectrum = mag({$vec})
plot spectrum
write specout.out spectrum
end
* If you have an oscillator, fimd its frequency
* as maximum of vector spectrum or goto end (uncomment next line)
* goto cleanup
set curplot=$scratch
let counter = 0
let contents = 0
let freqmax = 0
let spectrum = {$spec}.spectrum
foreach spectrum $&spectrum
if counter > 4
if ( contents < $spectrum )
let contents = $spectrum
set count = "$&counter"
let freqmax = {$spec}.frequency[{$count}]
end
end
let counter = counter + 1
end
echo
echo Osc. frequency at "$&freqmax" Hz
echo
goto cleanup
label reset
set curplot=$dt
label cleanup
destroy $scratch
unset fpoints dt scratch spec vec k title lent
label bottom
end
|