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
10 # Austron 2200A/2201A GPS receiver (see README.austron file)
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")
27 if (substr($
6, 13, 1) ==
"C")
29 if (substr($
6, 13, 1) ==
"H")
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") {
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)
105 # select IRIG audio decoder records
106 # see summary for decode
108 if (NF >=
4 && $
3 ==
"127.127.6.0") {
115 # select Austron GPS LORAN ENSEMBLE records
116 # see summary for decode
118 else if (NF >=
13 && $
6 ==
"ENSEMBLE") {
125 if ($
13 > 200e-9 || $
13 < -200e-9)
127 else if ($
13 > 100e-9 || $
13 < -100e-9)
130 ensemble_rms
+= $
13 * $
13
135 # select Austron LORAN TDATA records
136 # see summary for decode; note that signal quality log is simply
139 else if (NF >=
7 && $
6 ==
"TDATA") {
141 for (i =
7; i
< NF; i
++) {
142 if ($i ==
"M" && $
(i
+1) ==
"OK") {
147 else if ($i ==
"W" && $
(i
+1) ==
"OK") {
152 else if ($i ==
"X" && $
(i
+1) ==
"OK") {
157 else if ($i ==
"Y" && $
(i
+1) ==
"OK") {
162 else if ($i ==
"Z" && $
(i
+1) ==
"OK") {
171 # select Austron ITF records
172 # see summary for decode
174 else if (NF >=
13 && $
5 ==
"ITF" && $
12 >=
100) {
176 if ($
9 > 200e-9 || $
9 < -200e-9)
178 else if ($
9 > 100e-9 || $
9 < -100e-9)
186 # select Austron ETF records
187 # see summary for decode
189 else if (NF >=
13 && $
5 ==
"ETF" && $
13 >=
100) {
193 else if ($
6 < etf_min
)
201 # select Austron TRSTAT records
202 # see summary for decode
204 else if (NF >=
5 && $
5 ==
"TRSTAT") {
207 for (i =
6; i
<=
NF; i
++)
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
221 # LORAN LORAN assist module
224 # B.00 B.00 firmware revision
225 # 28-Apr-9 firmware date3
227 else if (NF >=
5 && $
5 ==
"ID;OPT;VER") {
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
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") {
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
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") {
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
285 # select Austron UTC records
286 # these ain't ready yet
288 else if (NF >=
5 && $
5 ==
"UTC") {
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
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
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
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
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
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
347 # >100 error > 100 ms
348 # >500 error > 500 ms
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
359 printf "irig %d, err %d\n", irig_count
, irig_error
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 ) {
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
387 # rms itf rms error (ns)
388 # >200 itf error > 200 ns
389 # >100 itf error > 100 ns
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
403 # rms etf rms error (ns)
404 # max etf maximum (ns)
405 # min etf minimum (ns)
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]
426 # control control midrange (V) +/- deviation (mV)
427 # temp oven temperature midrange +/- deviation (deg C)
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