// File: jkingan[P]ladyheather/heather.cpp
// Function: set_cpu_clock()
void set_cpu_clock()
{
int hhh, mmm, sss;
double milli;
double rcvr_jd;
double delta_jd;
int time_set;

   // This routine sets the system clock to the GPS receiver time
   // It can do this when requested, on a regular interval or whenever
   // the two clocks diverge by a specified amount.
   //
   // On Linux and OSX Heather must have root privledges to set the system clock.

   if(have_time == 0) return;         // we have no GPS receiver time
   if(have_timing_mode == 0) return;  // we don't know if the receiver time is UTC or GPS
   if(saw_icm) {
      if(time_flags & TFLAGS_BAD_TIME) return;   // GPS receiver time is not valid
   }
   else if(time_flags & (TFLAGS_BAD_TIME | TFLAGS_GLONASS)) return; // GPS receiver time is not valid  // !!!! saw_icm?

   if(fake_time_stamp) return;          // dont sync on faked UCCM time stamps

   if(set_system_time) ;        // a time set is scheduled
   else if(set_time_anytime) ;  // set time if clock has drifted
   else return;                 // nothing to do here, move along

   rcvr_jd = jd_utc;

   if(set_system_time > 1) {    // waiting for system to stabilze before setting time
      --set_system_time;
      if(set_system_time == 0) goto set_clock;
      return;
   }
   else if(set_system_time < 0) {  // dont resync time if we just did it
      ++set_system_time;
      return;
   }

   if(time_flags & TFLAGS_UTC) {  // receiver time is in UTC
      if(force_utc_time == 0) {  // we want to set system clock to GPS time
         rcvr_jd += ((double) utc_offset) / (24.0*60.0*60.0);
      }
   }
   else {  // receiver time is in GPS time
      if(force_utc_time) {  // we want to set system clock to UTC time
         rcvr_jd -= ((double) utc_offset) / (24.0*60.0*60.0);
      }
   }

   // adjust the receiver message time for the offset between when it arrived
   // and the true time
   rcvr_jd += ((time_sync_offset / 1000.0) / (24.0*60.0*60.0));

   // now we set the system time from the GPS receiver
   milli = 0.0;
   if(set_time_anytime) {  // set system clock anytime x milliseconds of drift is seen
      get_clock_time();    // get the system clock in UTC

      delta_jd = (rcvr_jd - clk_jd) * 24.0*60.0*60.0 * 1000.0;
      milli = fabs(time_sync_median(delta_jd));
//    milli = fabs(delta_jd);  // milliseconds of divergence between the system and receiver

//sprintf(debug_text2, "tset %.1f: delta:%f  tflags:%02X  futc:%d  tso:%g  jdo:%g",
//set_time_anytime, milli, time_flags,force_utc_time, time_sync_offset, delta_jd);  // rrrrrrr

      if(milli >= set_time_anytime) {  // we need a time set
         need_time_set();
         return;
      }
   }

   if(set_system_time == 0) return;   // we are not setting the time

   set_clock:
   time_set = 0;

   gregorian(0, rcvr_jd);   // convert needed to to broken down format

   #ifdef WINDOWS
      hhh = g_hours;
      mmm = g_minutes;
      sss = g_seconds;
   #endif
   #if defined(__linux__) || defined(__MACH__) || defined(__FreeBSD__)
      hhh = g_hours;
      mmm = g_minutes;
      sss = g_seconds;
   #endif

   // adjust receiver time for message offset delay to get true time
   #ifdef WINDOWS
      SYSTEMTIME t;
      milli = (long) (g_frac * 1000.0);

      t.wYear = g_year;
      t.wMonth = g_month;
      t.wDay = g_day;
      t.wHour = hhh;
      t.wMinute = mmm;
      t.wSecond = sss;
      t.wMilliseconds = (int) (milli + 0.50);
      time_set = (int) SetSystemTime(&t);
   #endif

   #if defined(__linux__) || defined(__MACH__) || defined(__FreeBSD__)
      struct timeval tv;
      time_t rawtime;
      double gmt;
      struct tm *tt;

      rcvr_jd -= LINUX_EPOCH;       // convert receiver time to Linux epoch
      rcvr_jd *= (24.0*60.0*60.0);  // convert days to seconds

      tv.tv_sec = (time_t) rcvr_jd;
      rcvr_jd -= floor(rcvr_jd);
      tv.tv_usec = (suseconds_t) (rcvr_jd * 1.0E6);

      time_set = settimeofday(&tv, 0);
      if(time_set == 0) time_set = 1;
      else time_set = 0;
   #endif

   if(time_set) {  // clock has been set
      if(!set_time_anytime) { // don't annoy if doing periodic time sets
         BEEP(3);
      }
   }

   set_system_time = (-3);  // time has been set, don't set it again for at least three seconds
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movzbl 0x29343d(%rip), %eax    # 0x29e0bc
cmpl $0x0, %eax
jne 0xac89
jmp 0xaf78
cmpl $0x0, 0x36191c(%rip)    # 0x36c5ac
jne 0xac97
jmp 0xaf78
cmpb $0x0, 0x29346f(%rip)    # 0x29e10d
je 0xacb5
movl 0x3619de(%rip), %eax    # 0x36c684
andl $0xc, %eax
cmpl $0x0, %eax
je 0xacb3
jmp 0xaf78
jmp 0xacca
movl 0x3619c9(%rip), %eax    # 0x36c684
andl $0x1c, %eax
cmpl $0x0, %eax
je 0xacc8
jmp 0xaf78
jmp 0xacca
cmpl $0x0, 0x361bff(%rip)    # 0x36c8d0
je 0xacd8
jmp 0xaf78
cmpl $0x0, 0x3623b9(%rip)    # 0x36d098
je 0xace3
jmp 0xad01
movsd 0x3623b5(%rip), %xmm0   # 0x36d0a0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0xacf8
jp 0xacf8
jmp 0xacfa
jmp 0xacff
jmp 0xaf78
jmp 0xad01
movsd 0x361a07(%rip), %xmm0   # 0x36c710
movsd %xmm0, -0x20(%rbp)
cmpl $0x1, 0x362383(%rip)    # 0x36d098
jle 0xad39
movl 0x36237b(%rip), %eax    # 0x36d098
addl $-0x1, %eax
movl %eax, 0x362372(%rip)    # 0x36d098
cmpl $0x0, 0x36236b(%rip)    # 0x36d098
jne 0xad34
jmp 0xae92
jmp 0xaf78
cmpl $0x0, 0x362358(%rip)    # 0x36d098
jge 0xad56
movl 0x362350(%rip), %eax    # 0x36d098
addl $0x1, %eax
movl %eax, 0x362347(%rip)    # 0x36d098
jmp 0xaf78
jmp 0xad58
movl 0x361926(%rip), %eax    # 0x36c684
andl $0x1, %eax
cmpl $0x0, %eax
je 0xad92
movzbl 0x362324(%rip), %eax    # 0x36d091
cmpl $0x0, %eax
jne 0xad90
cvtsi2sdl 0x361b8e(%rip), %xmm0 # 0x36c908
movsd 0x164286(%rip), %xmm1   # 0x16f008
divsd %xmm1, %xmm0
addsd -0x20(%rbp), %xmm0
movsd %xmm0, -0x20(%rbp)
jmp 0xadbf
cmpb $0x0, 0x3622f8(%rip)    # 0x36d091
je 0xadbd
cvtsi2sdl 0x361b65(%rip), %xmm1 # 0x36c908
movsd 0x16425d(%rip), %xmm0   # 0x16f008
divsd %xmm0, %xmm1
movsd -0x20(%rbp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, -0x20(%rbp)
jmp 0xadbf
movsd 0x3622e1(%rip), %xmm0   # 0x36d0a8
movsd 0x164261(%rip), %xmm1   # 0x16f030
divsd %xmm1, %xmm0
movsd 0x16422d(%rip), %xmm1   # 0x16f008
divsd %xmm1, %xmm0
addsd -0x20(%rbp), %xmm0
movsd %xmm0, -0x20(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x18(%rbp)
movsd 0x3622a7(%rip), %xmm0   # 0x36d0a0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0xae06
jp 0xae06
jmp 0xae82
callq 0xa750
movsd -0x20(%rbp), %xmm0
subsd 0x361aa8(%rip), %xmm0   # 0x36c8c0
movsd 0x164218(%rip), %xmm1   # 0x16f038
mulsd %xmm1, %xmm0
movsd 0x1641ec(%rip), %xmm1   # 0x16f018
mulsd %xmm1, %xmm0
movsd 0x1641e0(%rip), %xmm1   # 0x16f018
mulsd %xmm1, %xmm0
movsd 0x1641ec(%rip), %xmm1   # 0x16f030
mulsd %xmm1, %xmm0
movsd %xmm0, -0x28(%rbp)
movsd -0x28(%rbp), %xmm0
callq 0x1389a0
movaps 0x164432(%rip), %xmm1   # 0x16f290
pand %xmm1, %xmm0
movsd %xmm0, -0x18(%rbp)
movsd -0x18(%rbp), %xmm0
ucomisd 0x36222c(%rip), %xmm0   # 0x36d0a0
jb 0xae80
callq 0x138980
jmp 0xaf78
jmp 0xae82
cmpl $0x0, 0x36220f(%rip)    # 0x36d098
jne 0xae90
jmp 0xaf78
jmp 0xae92
movl $0x0, -0x2c(%rbp)
movsd -0x20(%rbp), %xmm0
xorl %edi, %edi
callq 0x11dd00
movl 0x3619dd(%rip), %eax    # 0x36c888
movl %eax, -0x4(%rbp)
movl 0x3619d8(%rip), %eax    # 0x36c88c
movl %eax, -0x8(%rbp)
movl 0x3619d3(%rip), %eax    # 0x36c890
movl %eax, -0xc(%rbp)
movsd -0x20(%rbp), %xmm0
movsd 0x164153(%rip), %xmm1   # 0x16f020
subsd %xmm1, %xmm0
movsd %xmm0, -0x20(%rbp)
movsd 0x16412a(%rip), %xmm0   # 0x16f008
mulsd -0x20(%rbp), %xmm0
movsd %xmm0, -0x20(%rbp)
cvttsd2si -0x20(%rbp), %rax
movq %rax, -0x40(%rbp)
movsd -0x20(%rbp), %xmm0
callq 0x9660
movaps %xmm0, %xmm1
movsd -0x20(%rbp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, -0x20(%rbp)
movsd 0x16412b(%rip), %xmm0   # 0x16f040
mulsd -0x20(%rbp), %xmm0
cvttsd2si %xmm0, %rax
movq %rax, -0x38(%rbp)
leaq -0x40(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x9710
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0xaf42
movl $0x1, -0x2c(%rbp)
jmp 0xaf49
movl $0x0, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
je 0xaf6e
movsd 0x362149(%rip), %xmm0   # 0x36d0a0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0xaf6c
jp 0xaf6c
movl $0x3, %edi
callq 0x9ec0
jmp 0xaf6e
movl $0xfffffffd, 0x362120(%rip) # imm = 0xFFFFFFFD
addq $0x60, %rsp
popq %rbp
retq
nop