#!/usr/bin/env slsh

require ("cmdopt");

private variable WD;
private define awg_to_in (gauge)
{
   if (typeof (gauge) == String_Type)
     gauge = atof (gauge);
   WD = 0.005 * 92^((36-gauge)/39.0);
}

private define mm_to_in (x)
{
   return x / 25.4;
}

define nec_to_nearest (x, c, n)
{
   variable s = 1;
   if (x < 0)
     {
	x = -x;
	s = -1;
     }
   variable ix = int(x);
   variable dx = x-ix;
   if (c == NULL)
     c = &c;

   dx = nint (dx * n);
   if (dx == n)
     {
	ix++;
	dx = 0;
     }

   @c = ix + dx/double(n);

   if (dx == 0)
     return sprintf ("%d in.", s*ix);
   while ((dx mod 2) == 0)
     {
	dx /= 2;
	n /= 2;
     }
   if (ix == 0)
     return sprintf ("%d/%d in.", s*dx, n);

   return sprintf ("%d %d/%d in.", s*ix, dx, n);
}

define nec_to_16th ()
{
   variable x, c;
   if (_NARGS == 1)
     NULL;
   (x,c) = ();
   return nec_to_nearest (x, c, 16);
}


private define to16th (x)
{
   return nec_to_16th (x);
}

private define to_mm (x)
{
   return nint (x*25.4);
}

define moxon (f, wd)
{
   variable WLI=11802.71/f, DW=wd/WLI;
   vmessage ("Wire Diameter in Wavelengths: %g", DW);

    variable d1 = 0.4342945*log(DW);
   if (d1<-6)
     message ("Wire diameter less than 1E-6 wavelengths:  results uncertain.");
   else if (d1>-2)
     message ("Wire diameter greater than 1E-2 wavelengths:  results uncertain.");

   variable AA=-.0008571428571, AB=-.009571428571, AC=.3398571429;
   variable A=(AA*(d1^2))+(AB*d1)+AC;

   variable BA=-.002142857143, BB=-.02035714286, BC=.008285714286;
   
   variable B=(BA*(d1^2))+(BB*d1)+BC;
   variable CA=.001809523381, CB=.01780952381, CC=.05164285714;
   variable C=(CA*(d1^2))+(CB*d1)+CC;

   variable DA=.001, DB=.07178571429;
   variable D=(DA*d1)+DB;
   variable E=(B+C)+D;

   message ("Moxon Dimensions in Wavelengths:");
   message ("A = $A"$);
   message ("B = $B"$);
   message ("C = $C"$);
   message ("D = $D"$);
   message ("E = $E"$);
   variable WF=983.5592/f, WFI=WF*12;
   vmessage ("Wavelength: %g inches (%g mm)", WFI, WFI*25.4);
   message ("Dimensions:");

   vmessage ("A = %S  (%d mm)", to16th(A*WFI), to_mm(A*WFI));
   vmessage ("B = %S  (%d mm)", to16th(B*WFI), to_mm(B*WFI));
   vmessage ("C = %S  (%d mm)", to16th(C*WFI), to_mm(C*WFI));
   vmessage ("D = %S  (%d mm)", to16th(D*WFI), to_mm(D*WFI));
   vmessage ("E = %S  (%d mm)", to16th(E*WFI), to_mm(E*WFI));
   
   vmessage ("A+2B = %S  (%d mm)", to16th((A+2*B)*WFI), to_mm((A+2*B)*WFI));
   vmessage ("A+2D = %S  (%d mm)", to16th((A+2*D)*WFI), to_mm((A+2*D)*WFI));
   vmessage ("B+C+D = %S  (%d mm)", to16th((B+C+D)*WFI), to_mm((B+C+D)*WFI));
   
}

private define exit_usage ()
{
   () = fprintf (stderr, "Usage: %s [options] freq[MHz]\n", __argv[0]);
   () = fprintf (stderr, "Options:\n");
   () = fprintf (stderr, " --help               This message\n");
   () = fprintf (stderr, " --wd-in=VAL          Wire diameter [inches]\n");
   () = fprintf (stderr, " --wd-awg=VAL         Wire diameter [AWG]\n");
   () = fprintf (stderr, " --wd-mm=VAL          Wire diameter [mm]\n");
   () = fprintf (stderr, "\nThe default is to use #12 AWG wire\n");
   exit (1);
}

define slsh_main ()
{
   awg_to_in (12);

   variable c = cmdopt_new ();
   c.add ("help", &exit_usage);
   c.add ("wd-awg", &awg_to_in; type="float");
   c.add ("wd-in", &WD; type="float");
   c.add ("wd-mm", &mm_to_in; type="float");
   variable i = c.process (__argv, 1);

   if (i + 1 != __argc)
     exit_usage ();
   
   variable freq = atof (__argv[i]);

   vmessage ("Wire Diameter: %g in (%g mm)", WD, WD*25.4);
   moxon (freq, WD);
}
