432 lines
10 KiB
Awk
Executable File
432 lines
10 KiB
Awk
Executable File
# awk program to scan clockstat files and report errors/statistics
|
|
#
|
|
# usage: awk -f check.awk clockstats
|
|
#
|
|
# This program works for the following radios:
|
|
# PST/Traconex 1020 WWV reciever
|
|
# Arbiter 1088 GPS receiver
|
|
# Spectracom 8170/Netclock-2 WWVB receiver
|
|
# IRIG audio decoder
|
|
# Austron 2200A/2201A GPS receiver (see README.austron file)
|
|
#
|
|
BEGIN {
|
|
etf_min = osc_vmin = osc_tmin = 1e9
|
|
etf_max = osc_vmax = osc_tmax = -1e9
|
|
}
|
|
#
|
|
# scan all records in file
|
|
#
|
|
{
|
|
#
|
|
# select PST/Traconex WWV records
|
|
# 00:00:37.234 96/07/08/190 O6@0:5281825C07510394
|
|
#
|
|
if (NF >= 4 && $3 == "127.127.3.1") {
|
|
if (substr($6, 14, 4) > "0010")
|
|
wwv_sync++
|
|
if (substr($6, 13, 1) == "C")
|
|
wwv_wwv++
|
|
if (substr($6, 13, 1) == "H")
|
|
wwv_wwvh++
|
|
x = substr($6, 12, 1)
|
|
if (x == "1")
|
|
wwv_2.5++
|
|
else if (x == "2")
|
|
wwv_5++
|
|
else if (x == "3")
|
|
wwv_10++
|
|
else if (x == "4")
|
|
wwv_15++
|
|
else if (x == "5")
|
|
wwv_20++
|
|
continue
|
|
}
|
|
#
|
|
# select Arbiter GPS records
|
|
# 96 190 00:00:37.000 0 V=08 S=44 T=3 P=10.6 E=00
|
|
# N39:42:00.951 W075:46:54.880 210.55 2.50 0.00
|
|
#
|
|
if (NF >= 4 && $3 == "127.127.11.1") {
|
|
if (NF > 8) {
|
|
arb_count++
|
|
if ($7 != 0)
|
|
arb_sync++
|
|
x = substr($10, 3, 1)
|
|
if (x == "0")
|
|
arb_0++
|
|
else if (x == "1")
|
|
arb_1++
|
|
else if (x == "2")
|
|
arb_2++
|
|
else if (x == "3")
|
|
arb_3++
|
|
else if (x == "4")
|
|
arb_4++
|
|
else if (x == "5")
|
|
arb_5++
|
|
else if (x == "6")
|
|
arb_6++
|
|
} else if (NF == 8) {
|
|
arbn++
|
|
arb_mean += $7
|
|
arb_rms += $7 * $7
|
|
if (arbn > 0) {
|
|
x = $7 - arb_val
|
|
arb_var += x * x
|
|
}
|
|
arb_val = $7
|
|
}
|
|
continue
|
|
}
|
|
#
|
|
# select Spectracom WWVB records
|
|
# see summary for decode
|
|
# 96 189 23:59:32.248 D
|
|
#
|
|
if (NF >= 4 && $3 == "127.127.4.1") {
|
|
if ($4 == "SIGNAL" || NF > 7)
|
|
printf "%s\n", $0
|
|
else {
|
|
wwvb_count++
|
|
if ($4 ~ /\?/)
|
|
wwvb_x++
|
|
else if ($4 ~ /A/)
|
|
wwvb_a++
|
|
else if ($4 ~ /B/)
|
|
wwvb_b++
|
|
else if ($4 ~ /C/)
|
|
wwvb_c++
|
|
else if ($4 ~ /D/)
|
|
wwvb_d++
|
|
}
|
|
continue
|
|
}
|
|
#
|
|
# select IRIG audio decoder records
|
|
# see summary for decode
|
|
#
|
|
if (NF >= 4 && $3 == "127.127.6.0") {
|
|
irig_count++
|
|
if ($5 ~ /\?/)
|
|
irig_error++
|
|
continue
|
|
}
|
|
#
|
|
# select Austron GPS LORAN ENSEMBLE records
|
|
# see summary for decode
|
|
#
|
|
else if (NF >= 13 && $6 == "ENSEMBLE") {
|
|
ensemble_count++
|
|
if ($9 <= 0)
|
|
ensemble_badgps++
|
|
else if ($12 <= 0)
|
|
ensemble_badloran++
|
|
else {
|
|
if ($13 > 200e-9 || $13 < -200e-9)
|
|
ensemble_200++
|
|
else if ($13 > 100e-9 || $13 < -100e-9)
|
|
ensemble_100++
|
|
ensemble_mean += $13
|
|
ensemble_rms += $13 * $13
|
|
}
|
|
continue
|
|
}
|
|
#
|
|
# select Austron LORAN TDATA records
|
|
# see summary for decode; note that signal quality log is simply
|
|
# copied to output
|
|
#
|
|
else if (NF >= 7 && $6 == "TDATA") {
|
|
tdata_count++
|
|
for (i = 7; i < NF; i++) {
|
|
if ($i == "M" && $(i+1) == "OK") {
|
|
i += 5
|
|
m += $i
|
|
tdata_m++
|
|
}
|
|
else if ($i == "W" && $(i+1) == "OK") {
|
|
i += 5
|
|
w += $i
|
|
tdata_w++
|
|
}
|
|
else if ($i == "X" && $(i+1) == "OK") {
|
|
i += 5
|
|
x += $i
|
|
tdata_x++
|
|
}
|
|
else if ($i == "Y" && $(i+1) == "OK") {
|
|
i += 5
|
|
y += $i
|
|
tdata_y++
|
|
}
|
|
else if ($i == "Z" && $(i+1) == "OK") {
|
|
i += 5
|
|
z += $i
|
|
tdata_z++
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
#
|
|
# select Austron ITF records
|
|
# see summary for decode
|
|
#
|
|
else if (NF >= 13 && $5 == "ITF" && $12 >= 100) {
|
|
itf_count++
|
|
if ($9 > 200e-9 || $9 < -200e-9)
|
|
itf_200++
|
|
else if ($9 > 100e-9 || $9 < -100e-9)
|
|
itf_100++
|
|
itf_mean += $9
|
|
itf_rms += $9 * $9
|
|
itf_var += $10 * $10
|
|
continue
|
|
}
|
|
#
|
|
# select Austron ETF records
|
|
# see summary for decode
|
|
#
|
|
else if (NF >= 13 && $5 == "ETF" && $13 >= 100) {
|
|
etf_count++
|
|
if ($6 > etf_max)
|
|
etf_max = $6
|
|
else if ($6 < etf_min)
|
|
etf_min = $6
|
|
etf_mean += $6
|
|
etf_rms += $6 * $6
|
|
etf_var += $9 * $9
|
|
continue
|
|
}
|
|
#
|
|
# select Austron TRSTAT records
|
|
# see summary for decode
|
|
#
|
|
else if (NF >= 5 && $5 == "TRSTAT") {
|
|
trstat_count++
|
|
j = 0
|
|
for (i = 6; i <= NF; i++)
|
|
if ($i == "T")
|
|
j++
|
|
trstat_sat[j]++
|
|
continue
|
|
}
|
|
#
|
|
# select Austron ID;OPT;VER records
|
|
#
|
|
# config GPS 2201A TTY1 TC1 LORAN IN OUT1 B.00 B.00 28-Apr-93
|
|
#
|
|
# GPS 2201A receiver model
|
|
# TTY1 rs232 moduel
|
|
# TC1 IRIG module
|
|
# LORAN LORAN assist module
|
|
# IN input module
|
|
# OUT1 output module
|
|
# B.00 B.00 firmware revision
|
|
# 28-Apr-9 firmware date3
|
|
#
|
|
else if (NF >= 5 && $5 == "ID;OPT;VER") {
|
|
id_count++
|
|
id_temp = ""
|
|
for (i = 6; i <= NF; i++)
|
|
id_temp = id_temp " " $i
|
|
if (id_string != id_temp)
|
|
printf "config%s\n", id_temp
|
|
id_string = id_temp
|
|
continue
|
|
}
|
|
#
|
|
# select Austron POS;PPS;PPSOFF records
|
|
#
|
|
# position +39:40:48.425 -075:45:02.392 +74.09 Stored UTC 0 200 0
|
|
#
|
|
# +39:40:48.425 position north latitude
|
|
# -075:45:02.392 position east longitude
|
|
# +74.09 elevation (meters)
|
|
# Stored position is stored
|
|
# UTC time is relative to UTC
|
|
# 0 200 0 PPS offsets
|
|
#
|
|
else if (NF >= 5 && $5 == "POS;PPS;PPSOFF") {
|
|
pos_count++
|
|
pos_temp = ""
|
|
for (i = 6; i <= NF; i++)
|
|
pos_temp = pos_temp " " $i
|
|
if (pos_string != pos_temp)
|
|
printf "position%s\n", pos_temp
|
|
pos_string = pos_temp
|
|
continue
|
|
}
|
|
#
|
|
# select Austron OSC;ET;TEMP records
|
|
#
|
|
# loop 1121 Software Control Locked
|
|
#
|
|
# 1121 oscillator type
|
|
# Software Control loop is under software control
|
|
# Locked loop is locked
|
|
#
|
|
else if (NF >= 5 && $5 == "OSC;ET;TEMP") {
|
|
osc_count++
|
|
osc_temp = $6 " " $7 " " $8 " " $9
|
|
if (osc_status != osc_temp)
|
|
printf "loop %s\n", osc_temp
|
|
osc_status = osc_temp
|
|
if ($10 > osc_vmax)
|
|
osc_vmax = $10
|
|
if ($10 < osc_vmin)
|
|
osc_vmin = $10
|
|
if ($11 > osc_tmax)
|
|
osc_tmax = $11
|
|
if ($11 < osc_tmin)
|
|
osc_tmin = $11
|
|
continue
|
|
}
|
|
#
|
|
# select Austron UTC records
|
|
# these ain't ready yet
|
|
#
|
|
else if (NF >= 5 && $5 == "UTC") {
|
|
utc_count++
|
|
utc_temp = ""
|
|
for (i = 6; i <= NF; i++)
|
|
utc_temp = utc_temp " " $i
|
|
if (utc_string != utc_temp)
|
|
# printf "utc%s\n", utc_temp
|
|
utc_string = utc_temp
|
|
continue
|
|
}
|
|
} END {
|
|
#
|
|
# PST/Traconex WWV summary data
|
|
#
|
|
if (wwv_wwv + wwv_wwvh > 0)
|
|
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
|
|
#
|
|
# Arbiter 1088 summary data
|
|
#
|
|
# gps record count
|
|
# err error count
|
|
# sats(0-6) satellites tracked
|
|
# mean 1 PPS mean (us)
|
|
# rms 1 PPS rms error (us)
|
|
# var 1 PPS Allan variance
|
|
#
|
|
if (arb_count > 0) {
|
|
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
|
|
if (arbn > 1) {
|
|
arb_mean /= arbn
|
|
arb_rms = sqrt(arb_rms / arbn - arb_mean * arb_mean)
|
|
arb_var = sqrt(arb_var / (2 * (arbn - 1)))
|
|
printf ", mean %.2f, rms %.2f, var %.2e\n", arb_mean, arb_rms, arb_var * 1e-6
|
|
} else {
|
|
printf "\n"
|
|
}
|
|
}
|
|
#
|
|
# ensemble summary data
|
|
#
|
|
# ensemble record count
|
|
# badgps gps data unavailable
|
|
# badloran loran data unavailable
|
|
# rms ensemble rms error (ns)
|
|
# >200 ensemble error >200 ns
|
|
# >100 100 ns < ensemble error < 200 ns
|
|
#
|
|
if (ensemble_count > 0) {
|
|
ensemble_mean /= ensemble_count
|
|
ensemble_rms = sqrt(ensemble_rms / ensemble_count - ensemble_mean * ensemble_mean) * 1e9
|
|
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
|
|
}
|
|
#
|
|
# wwvb summary data
|
|
#
|
|
# wwvb record count
|
|
# ? unsynchronized
|
|
# >1 error > 1 ms
|
|
# >10 error > 10 ms
|
|
# >100 error > 100 ms
|
|
# >500 error > 500 ms
|
|
#
|
|
if (wwvb_count > 0)
|
|
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
|
|
#
|
|
# irig summary data
|
|
#
|
|
# irig record count
|
|
# err error count
|
|
#
|
|
if (irig_count > 0)
|
|
printf "irig %d, err %d\n", irig_count, irig_error
|
|
#
|
|
# tdata summary data
|
|
#
|
|
# tdata record count
|
|
# m M master OK-count, mean level (dB)
|
|
# w W slave OK-count, mean level (dB)
|
|
# x X slave OK-count, mean level (dB)
|
|
# y Y slave OK-count, mean level (dB)
|
|
# z Z slave OK-count, mean level (dB)
|
|
#
|
|
if (tdata_count > 0 ) {
|
|
if (tdata_m > 0)
|
|
m /= tdata_count
|
|
if (tdata_x > 0)
|
|
w /= tdata_count
|
|
if (tdata_x > 0)
|
|
x /= tdata_count
|
|
if (tdata_y > 0)
|
|
y /= tdata_count
|
|
if (tdata_z > 0)
|
|
z /= tdata_count
|
|
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
|
|
}
|
|
#
|
|
# itf summary data
|
|
#
|
|
# itf record count
|
|
# rms itf rms error (ns)
|
|
# >200 itf error > 200 ns
|
|
# >100 itf error > 100 ns
|
|
# var Allan variance
|
|
#
|
|
if (itf_count > 1) {
|
|
itf_mean /= itf_count
|
|
itf_rms = sqrt(itf_rms / itf_count - itf_mean * itf_mean) * 1e9
|
|
itf_var = sqrt(itf_var / (2 * (itf_count - 1)))
|
|
printf "itf %d, rms %.1f, >200 %d, >100 %d, var %.2e\n", itf_count, itf_rms, itf_200, itf_100, itf_var
|
|
}
|
|
#
|
|
# etf summary data
|
|
#
|
|
# etf record count
|
|
# mean etf mean (ns)
|
|
# rms etf rms error (ns)
|
|
# max etf maximum (ns)
|
|
# min etf minimum (ns)
|
|
# var Allan variance
|
|
#
|
|
if (etf_count > 0) {
|
|
etf_mean /= etf_count
|
|
etf_rms = sqrt(etf_rms / etf_count - etf_mean * etf_mean)
|
|
etf_var = sqrt(etf_var / (2 * (etf_count - 1)))
|
|
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
|
|
}
|
|
#
|
|
# trstat summary data
|
|
#
|
|
# trstat record count
|
|
# sat histogram of tracked satellites (0 - 7)
|
|
#
|
|
if (trstat_count > 0)
|
|
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]
|
|
#
|
|
# osc summary data
|
|
#
|
|
# osc record count
|
|
# control control midrange (V) +/- deviation (mV)
|
|
# temp oven temperature midrange +/- deviation (deg C)
|
|
#
|
|
if (osc_count > 0)
|
|
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
|
|
}
|