Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ntp / scripts / stats / clock.awk
blobef62da9ebdc076644f0d2745c2d3bc07fa15c9d9
1 # awk program to scan clockstat files and report errors/statistics
3 # usage: awk -f check.awk clockstats
5 # This program works for the following radios:
6 # PST/Traconex 1020 WWV reciever
7 # Arbiter 1088 GPS receiver
8 # Spectracom 8170/Netclock-2 WWVB receiver
9 # IRIG audio decoder
10 # Austron 2200A/2201A GPS receiver (see README.austron file)
12 BEGIN {
13 etf_min = osc_vmin = osc_tmin = 1e9
14 etf_max = osc_vmax = osc_tmax = -1e9
17 # scan all records in file
21 # select PST/Traconex WWV records
22 # 00:00:37.234 96/07/08/190 O6@0:5281825C07510394
24 if (NF >= 4 && $3 == "127.127.3.1") {
25 if (substr($6, 14, 4) > "0010")
26 wwv_sync++
27 if (substr($6, 13, 1) == "C")
28 wwv_wwv++
29 if (substr($6, 13, 1) == "H")
30 wwv_wwvh++
31 x = substr($6, 12, 1)
32 if (x == "1")
33 wwv_2.5++
34 else if (x == "2")
35 wwv_5++
36 else if (x == "3")
37 wwv_10++
38 else if (x == "4")
39 wwv_15++
40 else if (x == "5")
41 wwv_20++
42 continue
45 # select Arbiter GPS records
46 # 96 190 00:00:37.000 0 V=08 S=44 T=3 P=10.6 E=00
47 # N39:42:00.951 W075:46:54.880 210.55 2.50 0.00
49 if (NF >= 4 && $3 == "127.127.11.1") {
50 if (NF > 8) {
51 arb_count++
52 if ($7 != 0)
53 arb_sync++
54 x = substr($10, 3, 1)
55 if (x == "0")
56 arb_0++
57 else if (x == "1")
58 arb_1++
59 else if (x == "2")
60 arb_2++
61 else if (x == "3")
62 arb_3++
63 else if (x == "4")
64 arb_4++
65 else if (x == "5")
66 arb_5++
67 else if (x == "6")
68 arb_6++
69 } else if (NF == 8) {
70 arbn++
71 arb_mean += $7
72 arb_rms += $7 * $7
73 if (arbn > 0) {
74 x = $7 - arb_val
75 arb_var += x * x
77 arb_val = $7
79 continue
82 # select Spectracom WWVB records
83 # see summary for decode
84 # 96 189 23:59:32.248 D
86 if (NF >= 4 && $3 == "127.127.4.1") {
87 if ($4 == "SIGNAL" || NF > 7)
88 printf "%s\n", $0
89 else {
90 wwvb_count++
91 if ($4 ~ /\?/)
92 wwvb_x++
93 else if ($4 ~ /A/)
94 wwvb_a++
95 else if ($4 ~ /B/)
96 wwvb_b++
97 else if ($4 ~ /C/)
98 wwvb_c++
99 else if ($4 ~ /D/)
100 wwvb_d++
102 continue
105 # select IRIG audio decoder records
106 # see summary for decode
108 if (NF >= 4 && $3 == "127.127.6.0") {
109 irig_count++
110 if ($5 ~ /\?/)
111 irig_error++
112 continue
115 # select Austron GPS LORAN ENSEMBLE records
116 # see summary for decode
118 else if (NF >= 13 && $6 == "ENSEMBLE") {
119 ensemble_count++
120 if ($9 <= 0)
121 ensemble_badgps++
122 else if ($12 <= 0)
123 ensemble_badloran++
124 else {
125 if ($13 > 200e-9 || $13 < -200e-9)
126 ensemble_200++
127 else if ($13 > 100e-9 || $13 < -100e-9)
128 ensemble_100++
129 ensemble_mean += $13
130 ensemble_rms += $13 * $13
132 continue
135 # select Austron LORAN TDATA records
136 # see summary for decode; note that signal quality log is simply
137 # copied to output
139 else if (NF >= 7 && $6 == "TDATA") {
140 tdata_count++
141 for (i = 7; i < NF; i++) {
142 if ($i == "M" && $(i+1) == "OK") {
143 i += 5
144 m += $i
145 tdata_m++
147 else if ($i == "W" && $(i+1) == "OK") {
148 i += 5
149 w += $i
150 tdata_w++
152 else if ($i == "X" && $(i+1) == "OK") {
153 i += 5
154 x += $i
155 tdata_x++
157 else if ($i == "Y" && $(i+1) == "OK") {
158 i += 5
159 y += $i
160 tdata_y++
162 else if ($i == "Z" && $(i+1) == "OK") {
163 i += 5
164 z += $i
165 tdata_z++
168 continue
171 # select Austron ITF records
172 # see summary for decode
174 else if (NF >= 13 && $5 == "ITF" && $12 >= 100) {
175 itf_count++
176 if ($9 > 200e-9 || $9 < -200e-9)
177 itf_200++
178 else if ($9 > 100e-9 || $9 < -100e-9)
179 itf_100++
180 itf_mean += $9
181 itf_rms += $9 * $9
182 itf_var += $10 * $10
183 continue
186 # select Austron ETF records
187 # see summary for decode
189 else if (NF >= 13 && $5 == "ETF" && $13 >= 100) {
190 etf_count++
191 if ($6 > etf_max)
192 etf_max = $6
193 else if ($6 < etf_min)
194 etf_min = $6
195 etf_mean += $6
196 etf_rms += $6 * $6
197 etf_var += $9 * $9
198 continue
201 # select Austron TRSTAT records
202 # see summary for decode
204 else if (NF >= 5 && $5 == "TRSTAT") {
205 trstat_count++
206 j = 0
207 for (i = 6; i <= NF; i++)
208 if ($i == "T")
210 trstat_sat[j]++
211 continue
214 # select Austron ID;OPT;VER records
216 # config GPS 2201A TTY1 TC1 LORAN IN OUT1 B.00 B.00 28-Apr-93
218 # GPS 2201A receiver model
219 # TTY1 rs232 moduel
220 # TC1 IRIG module
221 # LORAN LORAN assist module
222 # IN input module
223 # OUT1 output module
224 # B.00 B.00 firmware revision
225 # 28-Apr-9 firmware date3
227 else if (NF >= 5 && $5 == "ID;OPT;VER") {
228 id_count++
229 id_temp = ""
230 for (i = 6; i <= NF; i++)
231 id_temp = id_temp " " $i
232 if (id_string != id_temp)
233 printf "config%s\n", id_temp
234 id_string = id_temp
235 continue
238 # select Austron POS;PPS;PPSOFF records
240 # position +39:40:48.425 -075:45:02.392 +74.09 Stored UTC 0 200 0
242 # +39:40:48.425 position north latitude
243 # -075:45:02.392 position east longitude
244 # +74.09 elevation (meters)
245 # Stored position is stored
246 # UTC time is relative to UTC
247 # 0 200 0 PPS offsets
249 else if (NF >= 5 && $5 == "POS;PPS;PPSOFF") {
250 pos_count++
251 pos_temp = ""
252 for (i = 6; i <= NF; i++)
253 pos_temp = pos_temp " " $i
254 if (pos_string != pos_temp)
255 printf "position%s\n", pos_temp
256 pos_string = pos_temp
257 continue
260 # select Austron OSC;ET;TEMP records
262 # loop 1121 Software Control Locked
264 # 1121 oscillator type
265 # Software Control loop is under software control
266 # Locked loop is locked
268 else if (NF >= 5 && $5 == "OSC;ET;TEMP") {
269 osc_count++
270 osc_temp = $6 " " $7 " " $8 " " $9
271 if (osc_status != osc_temp)
272 printf "loop %s\n", osc_temp
273 osc_status = osc_temp
274 if ($10 > osc_vmax)
275 osc_vmax = $10
276 if ($10 < osc_vmin)
277 osc_vmin = $10
278 if ($11 > osc_tmax)
279 osc_tmax = $11
280 if ($11 < osc_tmin)
281 osc_tmin = $11
282 continue
285 # select Austron UTC records
286 # these ain't ready yet
288 else if (NF >= 5 && $5 == "UTC") {
289 utc_count++
290 utc_temp = ""
291 for (i = 6; i <= NF; i++)
292 utc_temp = utc_temp " " $i
293 if (utc_string != utc_temp)
294 # printf "utc%s\n", utc_temp
295 utc_string = utc_temp
296 continue
298 } END {
300 # PST/Traconex WWV summary data
302 if (wwv_wwv + wwv_wwvh > 0)
303 printf "wwv %d, wwvh %d, err %d, MHz (2.5) %d, (5) %d, (10) %d, (15) %d, (20) %d\n", wwv_wwv, wwv_wwvh, wwv_sync, wwv_2.5, wwv_5, wwv_10, wwv_15, wwv_20
305 # Arbiter 1088 summary data
307 # gps record count
308 # err error count
309 # sats(0-6) satellites tracked
310 # mean 1 PPS mean (us)
311 # rms 1 PPS rms error (us)
312 # var 1 PPS Allan variance
314 if (arb_count > 0) {
315 printf "gps %d, err %d, sats(0-6) %d %d %d %d %d %d %d", arb_count, arb_sync, arb_0, arb_1, arb_2, arb_3, arb_4, arb_5, arb_6
316 if (arbn > 1) {
317 arb_mean /= arbn
318 arb_rms = sqrt(arb_rms / arbn - arb_mean * arb_mean)
319 arb_var = sqrt(arb_var / (2 * (arbn - 1)))
320 printf ", mean %.2f, rms %.2f, var %.2e\n", arb_mean, arb_rms, arb_var * 1e-6
321 } else {
322 printf "\n"
326 # ensemble summary data
328 # ensemble record count
329 # badgps gps data unavailable
330 # badloran loran data unavailable
331 # rms ensemble rms error (ns)
332 # >200 ensemble error >200 ns
333 # >100 100 ns < ensemble error < 200 ns
335 if (ensemble_count > 0) {
336 ensemble_mean /= ensemble_count
337 ensemble_rms = sqrt(ensemble_rms / ensemble_count - ensemble_mean * ensemble_mean) * 1e9
338 printf "ensemble %d, badgps %d, badloran %d, rms %.1f, >200 %d, >100 %d\n", ensemble_count, ensemble_badgps, ensemble_badloran, ensemble_rms, ensemble_200, ensemble_100
341 # wwvb summary data
343 # wwvb record count
344 # ? unsynchronized
345 # >1 error > 1 ms
346 # >10 error > 10 ms
347 # >100 error > 100 ms
348 # >500 error > 500 ms
350 if (wwvb_count > 0)
351 printf "wwvb %d, ? %d, >1 %d, >10 %d, >100 %d, >500 %d\n", wwvb_count, wwvb_x, wwvb_a, wwvb_b, wwvb_c, wwvb_d
353 # irig summary data
355 # irig record count
356 # err error count
358 if (irig_count > 0)
359 printf "irig %d, err %d\n", irig_count, irig_error
361 # tdata summary data
363 # tdata record count
364 # m M master OK-count, mean level (dB)
365 # w W slave OK-count, mean level (dB)
366 # x X slave OK-count, mean level (dB)
367 # y Y slave OK-count, mean level (dB)
368 # z Z slave OK-count, mean level (dB)
370 if (tdata_count > 0 ) {
371 if (tdata_m > 0)
372 m /= tdata_count
373 if (tdata_x > 0)
374 w /= tdata_count
375 if (tdata_x > 0)
376 x /= tdata_count
377 if (tdata_y > 0)
378 y /= tdata_count
379 if (tdata_z > 0)
380 z /= tdata_count
381 printf "tdata %d, m %d %.1f, w %d %.1f, x %d %.1f, y %d %.1f, z %d %.1f\n", tdata_count, tdata_m, m, tdata_w, w, tdata_x, x, tdata_y, y, tdata_z, z
384 # itf summary data
386 # itf record count
387 # rms itf rms error (ns)
388 # >200 itf error > 200 ns
389 # >100 itf error > 100 ns
390 # var Allan variance
392 if (itf_count > 1) {
393 itf_mean /= itf_count
394 itf_rms = sqrt(itf_rms / itf_count - itf_mean * itf_mean) * 1e9
395 itf_var = sqrt(itf_var / (2 * (itf_count - 1)))
396 printf "itf %d, rms %.1f, >200 %d, >100 %d, var %.2e\n", itf_count, itf_rms, itf_200, itf_100, itf_var
399 # etf summary data
401 # etf record count
402 # mean etf mean (ns)
403 # rms etf rms error (ns)
404 # max etf maximum (ns)
405 # min etf minimum (ns)
406 # var Allan variance
408 if (etf_count > 0) {
409 etf_mean /= etf_count
410 etf_rms = sqrt(etf_rms / etf_count - etf_mean * etf_mean)
411 etf_var = sqrt(etf_var / (2 * (etf_count - 1)))
412 printf "etf %d, mean %.1f, rms %.1f, max %d, min %d, var %.2e\n", etf_count, etf_mean, etf_rms, etf_max, etf_min, etf_var
415 # trstat summary data
417 # trstat record count
418 # sat histogram of tracked satellites (0 - 7)
420 if (trstat_count > 0)
421 printf "trstat %d, sat %d %d %d %d %d %d %d %d\n", trstat_count, trstat_sat[0], trstat_sat[1], trstat_sat[2], trstat_sat[2], trstat_sat[3], trstat_sat[4], trstat_sat[5], trstat_sat[6], trstat_sat[7]
423 # osc summary data
425 # osc record count
426 # control control midrange (V) +/- deviation (mV)
427 # temp oven temperature midrange +/- deviation (deg C)
429 if (osc_count > 0)
430 printf "osc %d, control %.3f+/-%.3f, temp %.1f+/-%.2f\n", osc_count, (osc_vmax + osc_vmin) / 2, (osc_vmax - osc_vmin) / 2 * 1e3, (osc_tmax + osc_tmin) / 2, (osc_tmax - osc_tmin) / 2