// Calculate gearing required to display seconds, minutes, and hours with arnfield escapement using 5 reductions, constraining largest gear diameter to fit within Ender 3 build plate.
// 20 Aug 2023 DL
//
#include <stdio.h>
#include <math.h>

/*
 Layout
 ------
                  s1
    (-a-)(---b---)->|    s2
      |    (-c-)(---d---)->|    s3
      |      |    (-e-)(---f---)->|    s4
      |      |      |    (-g-)(---h---)->|
      |      |      |      |    (-i-)(---j---)
      |      |      |      |      |      |
    star   seconds inter minutes inter  hours
    CCW      CW     CCW   CW      CCW    CW

    star wheel:         5 rev per minute  [ 6 step / rev * 2 sec / step = 12 sec / rev = 5 rev / minute ]
    seconds wheel:      1 rev per minute  [ reduction from star wheel: 5:1 ]
    intermediate wheel: don't care
    minutes wheel:      1 rev per hour    [ reduction from star wheel: 300:1 ]
    intermediate wheel  don't care
    hour wheel:         1 rev per 12 hour [ reduction from minutes wheel: 12:1 ]

 Clearances so that wheels don't hit neighboring axles
 -----------------------------------------------------

    s1 >= c / 2 + d / 2 - b / 2
    s2 >= e / 2 + f / 2 - d / 2
    s3 >= g / 2 + h / 2 - f / 2
    s4 >= i / 2 + j / 2 - h / 2
    
 Maximum wheel size
 ------------------
    
    204mm pitch circle corresponds to a 208mm outer diameter gear which just fits on Ender 3 build plate
 
 Results
 -------

    a=12 b=60 
         c=12 d=90
              e=12 f=96 
                   g=28 h=84 
                        i=20 j=80

 */

const float MIN_CLEARANCE = 5;

void
minutes()
   {
   int n = 0;
   
   float PINION_MIN = 11;
   float PINION_MAX = 15;
   
   float WHEEL_MIN =  30;
   float WHEEL_MAX = 100;
   
   for (float a = PINION_MIN; a <= PINION_MAX; a += 1)
      for (float b = WHEEL_MIN; b <= WHEEL_MAX; b += 1)
         for (float c = PINION_MIN; c <= PINION_MAX; c += 1)
            for (float d = WHEEL_MIN; d <= WHEEL_MAX; d += 1)
               for (float e = PINION_MIN; e <= PINION_MAX; e += 1)
                  for (float f = WHEEL_MIN; f <= WHEEL_MAX; f += 1)
               {
               n += 1;

               float s1 = c / 2 + d / 2 - b / 2;
               float s2 = e / 2 + f / 2 - d / 2;

               if (s1 < MIN_CLEARANCE || s2 < MIN_CLEARANCE) continue;

               if ( b/a             !=   5)  continue; // seconds wheel
               if ( b/a * d/c * f/e != 300)  continue; // minutes wheel
            
            #if 1
               // hilight gear combo we'd like to use
               if (a == 12 && b == 60 && c == 12 && d == 90 && e == 12 && f == 96) printf(">> ");
               else                                                                printf("   ");
            #endif
             
               printf("a=%2.0f b=%3.0f c=%2.0f d=%3.0f e=%2.0f f=%3.0f s1=%4.1f s2=%4.1f ", a, b, c, d, e, f, s1, s2);
               printf("seconds=%.0f:1 inter=%.3f:1 minutes=%.0f:1 ", b/a, d/c * b/a, f/e * d/c * b/a);
               
               printf("\n");
               }

   printf("%d iterations\n", n);
   }

void
hours()
   {
   int n = 0;
   
   float PINION_MIN =  15;
   float PINION_MAX = 100;
   
   float WHEEL_MIN =  15;
   float WHEEL_MAX = 100;
   
   float f = 96; // <== value selected by minutes() calculation, above
   for (float g = PINION_MIN; g <= PINION_MAX; g += 1)
      for (float h = WHEEL_MIN; h <= WHEEL_MAX; h += 1)
         for (float i = PINION_MIN; i <= PINION_MAX; i += 1)
            for (float j = WHEEL_MIN; j <= WHEEL_MAX; j += 1)
               {
               n += 1;

               float s3 = g / 2 + h / 2 - f / 2;
               float s4 = i / 2 + j / 2 - h / 2;
               
               if (s3 < MIN_CLEARANCE || s4 < MIN_CLEARANCE) continue;

               if (h/g * j/i != 12) continue;
               
               if (h > 85) continue;
               if (j > 85) continue;
 
            #if 1
               // hilight gear combo we'd like to use
            ///if (g == 28 && h == 84 && i == 21 && j == 84) printf(">> ");
               if (g == 28 && h == 84 && i == 20 && j == 80) printf(">> ");
               else                                          printf("   ");
            #endif

               printf("f=%2.0f g=%2.0f h=%3.0f i=%2.0f j=%3.0f s3=%4.1f s4=%4.1f ", f, g, h, i, j, s3, s4);
               printf("inter=%.3f:1 hours=%.0f:1 ", h/g, h/g * j/i);
               printf("\n");
               }

   printf("%d iterations\n", n);
   }

int
main()
   {
   minutes();
   hours();
   return 0;
   }
