File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / scripts / stats / clock.awk
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (13 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: # awk program to scan clockstat files and report errors/statistics
    2: #
    3: # usage: awk -f check.awk clockstats
    4: #
    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)
   11: #
   12: BEGIN {
   13: 	etf_min = osc_vmin = osc_tmin = 1e9
   14: 	etf_max = osc_vmax = osc_tmax = -1e9
   15: }
   16: #
   17: # scan all records in file
   18: #
   19: {
   20: 	#
   21: 	# select PST/Traconex WWV records
   22: 	# 00:00:37.234  96/07/08/190 O6@0:5281825C07510394
   23: 	#
   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
   43: 	}
   44: 	#
   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
   48: 	#
   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
   76: 			}
   77: 			arb_val = $7
   78: 		}
   79: 		continue
   80: 	}
   81: 	#
   82: 	# select Spectracom WWVB records
   83: 	# see summary for decode
   84: 	#   96 189 23:59:32.248  D
   85: 	#
   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++
  101: 		}
  102: 		continue
  103: 	}
  104: 	#
  105: 	# select IRIG audio decoder records
  106: 	# see summary for decode
  107: 	#
  108: 	if (NF >= 4 && $3 == "127.127.6.0") {
  109: 		irig_count++
  110: 		if ($5 ~ /\?/)
  111: 			irig_error++
  112: 		continue
  113: 	}
  114: 	#
  115: 	# select Austron GPS LORAN ENSEMBLE records
  116: 	# see summary for decode
  117: 	#
  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
  131: 		}
  132: 		continue
  133: 	}
  134: 	#
  135: 	# select Austron LORAN TDATA records
  136: 	# see summary for decode; note that signal quality log is simply
  137: 	# copied to output
  138: 	#
  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++
  146: 		        }
  147:                         else if ($i == "W" && $(i+1) == "OK") {
  148:                                 i += 5
  149:                                 w += $i
  150:                         	tdata_w++
  151: 			}
  152:                         else if ($i == "X" && $(i+1) == "OK") {
  153:                                 i += 5
  154:                                 x += $i
  155:                         	tdata_x++
  156: 			}
  157:                         else if ($i == "Y" && $(i+1) == "OK") {
  158:                                 i += 5
  159:                                 y += $i
  160:                         	tdata_y++
  161: 			}
  162:                         else if ($i == "Z" && $(i+1) == "OK") {
  163:                                 i += 5
  164:                                 z += $i
  165:                         	tdata_z++
  166: 			}
  167: 		}	
  168: 		continue
  169: 	}
  170: 	#
  171: 	# select Austron ITF records
  172: 	# see summary for decode
  173: 	#
  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
  184: 	}
  185: 	#
  186: 	# select Austron ETF records
  187: 	# see summary for decode
  188: 	#
  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
  199: 	}
  200: 	#
  201: 	# select Austron TRSTAT records
  202: 	# see summary for decode
  203: 	#
  204: 	else if (NF >= 5 && $5 == "TRSTAT") {
  205: 		trstat_count++
  206: 		j = 0
  207: 		for (i = 6; i <= NF; i++)
  208: 			if ($i == "T")
  209: 				j++
  210: 		trstat_sat[j]++
  211: 		continue
  212: 	}
  213: 	#
  214: 	# select Austron ID;OPT;VER records
  215: 	#
  216: 	# config GPS 2201A TTY1 TC1 LORAN IN OUT1 B.00 B.00 28-Apr-93
  217: 	#
  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
  226:         #
  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	
  236: 	}
  237: 	#
  238: 	# select Austron POS;PPS;PPSOFF records
  239: 	#
  240: 	# position +39:40:48.425 -075:45:02.392 +74.09 Stored UTC 0 200 0
  241: 	#
  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
  248: 	#
  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
  258: 	}
  259: 	#
  260: 	# select Austron OSC;ET;TEMP records
  261: 	#
  262: 	# loop 1121 Software Control Locked
  263: 	#
  264: 	# 1121		oscillator type
  265: 	# Software Control loop is under software control
  266: 	# Locked	loop is locked
  267: 	#
  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
  283: 	}
  284: 	#
  285: 	# select Austron UTC records
  286: 	# these ain't ready yet
  287: 	#
  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
  297: 	}
  298: } END {
  299: #
  300: # PST/Traconex WWV summary data
  301: #
  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
  304: #
  305: # Arbiter 1088 summary data
  306: #
  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
  313: #
  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"
  323: 		}
  324: 	}
  325: #
  326: # ensemble summary data
  327: #
  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
  334: #
  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
  339: 	}
  340: #
  341: # wwvb summary data
  342: #
  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
  349: #
  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
  352: #
  353: # irig summary data
  354: #
  355: # irig		record count
  356: # err		error count
  357: #
  358: 	if (irig_count > 0)
  359: 		printf "irig %d, err %d\n", irig_count, irig_error
  360: #
  361: # tdata summary data
  362: #
  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)
  369: #
  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
  382: 	}
  383: #
  384: # itf summary data
  385: #
  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
  391: #
  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
  397: 	}
  398: #
  399: # etf summary data
  400: #
  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
  407: #
  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
  413: 	}
  414: #
  415: # trstat summary data
  416: #
  417: # trstat	record count
  418: # sat		histogram of tracked satellites (0 - 7)
  419: #
  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]
  422: #
  423: # osc summary data
  424: #
  425: # osc		record count
  426: # control	control midrange (V) +/- deviation (mV)
  427: # temp		oven temperature midrange +/- deviation (deg C)
  428: #
  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
  431: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>