#!/usr/skunk/bin/gawk -f #!/usr/bin/awk -f # @(#) find_cryst.awk 1.1 93/07/02 # 93/03/20 john h. dubois iii (john@armory.com) # 93/07/02 Added help & sorting # 94/03/09 Use gawk so - options can be given. BEGIN { Usage = "Usage: findcrystal [-hs] desired min max [step]\n" if (ARGV[1] ~ "^[-+]h$") { print \ "findcrystal: find a crystal that can be divided down as close as possible\n"\ "to a desired frequency.\n"\ Usage \ "desired is the desired frequency. min and max are two crystal frequencies.\n"\ "For each integer value between them, the two divisors that bring the\n"\ "crystal frequency closest to the desired frequency are determined,\n"\ "and the divisor and the resulting frequencies and errors are printed.\n"\ "If step is given, every step'th integer between min and max is checked.\n"\ "If -s is given, the results are sorted by error percentage." exit(0) } argstart = 1 Sort = 0 if (ARGV[argstart] ~ "^[-+]s$") { Sort = 1 argstart++ } if ((ARGC - argstart) < 3) { printf "%s",Usage exit(1) } Desired = ARGV[argstart++] Min = ARGV[argstart++] Max = ARGV[argstart++] if (ARGC - argstart > 0) Step = ARGV[argstart++] else Step = 1 Format = "%8s %7s %8s %6s %7s %8s %6s" printf \ Format "\n","Freq","Divisor","DivFreq","%Err","Divisor","DivFreq","%Err" n = 0 for (i = Min; i <= Max; i += Step) { divisor = int(i / Desired) LowFreq = i / (divisor+1) HighFreq = i / divisor LowErr = Error(Desired,LowFreq) HighErr = Error(Desired,HighFreq) Result = sprintf(Format,i,divisor+1,LowFreq,sprintf("%5.2f",LowErr), divisor,HighFreq,sprintf("%5.2f",HighErr)) if (Sort) { Res[++n] = Result Errs[n] = min(abs(LowErr),abs(HighErr)) } else print Result } if (Sort) { qsort_arb_ind(Errs,k) for (i = 1; i <= n; i++) { print Res[k[i]] } } } # returns the % of a that b is away from it function Error(a,b) { return ((b - a) / a)*100 } function abs(a) { return a < 0 ? -a : a } function min(a,b) { if (a < b) return a else return b } # Arr is an array of values with arbitrary indices. # Array k is returned with numeric indices 1..n. # The values in k are the indices of array arr, # ordered so that if array arr is stepped through # in the order arr[k[1]] .. arr[k[n]], it will be stepped # through in order of the values of its elements. # The return value is the number of elements in the array (n). function qsort_arb_ind(arr,k, ArrInd,end) { end = 0 for (ArrInd in arr) k[++end] = ArrInd; qsortseg(arr,k,1,end); return end } function qsortseg(arr,k,start,end, left,right,sepval,tmp,tmpe,tmps) { # handle two-element case explicitely for a tiny speedup if ((end - start) == 1) { if (arr[tmps = k[start]] > arr[tmpe = k[end]]) { k[start] = tmpe k[end] = tmps } return } left = start; right = end; sepval = arr[k[int((left + right) / 2)]] # Make every element <= sepval be to the left of every element > sepval while (left < right) { while (arr[k[left]] < sepval) left++ while (arr[k[right]] > sepval) right-- if (left < right) { tmp = k[left] k[left++] = k[right] k[right--] = tmp } } if (left == right) if (arr[k[left]] < sepval) left++ else right-- if (start < right) qsortseg(arr,k,start,right) if (left < end) qsortseg(arr,k,left,end) }