
    fՓh)                     @    d dl Z d dlZd dlmZmZ  G d d          ZdS )    N)datetime	timedeltac                   V    e Zd ZdZddZd Zd Zd Zd Zd Z	d	 Z
d
 Zd Zd Zd ZdS )TimingControllerz>Handles synchronized timing operations for the CSEM TriggerboxNc                     || _         |pd | _        d | _        d| _        t	          j                    | _        d d d dd| _        d | _        d| _	        d| _
        d | _        d | _        d| _        d S )Nc                     d S N )timess    2/home/morepork/Documents/CSEM/timing_controller.py<lambda>z+TimingController.__init__.<locals>.<lambda>
   s         r   rpigpsrtc	timestampF)r   update_callbackgps_time_objlast_display_second	threadingLockdisplay_lockcached_timessync_timer_threadsync_timer_runningcountdown_activecountdown_callbacktransmission_start_callbackcountdown_completed)selfr   r   s      r   __init__zTimingController.__init__   s    .F3E3E !#% %N,, 	
 
 "&"' !&"&+/(#(   r   c                     d| _         t          j        | j        d          | _        | j                                         dS )z?Start synchronized timing system with precise second boundariesT)targetdaemonN)r   r   Thread_precision_sync_loopr   startr"   s    r   start_synchronized_timingz*TimingController.start_synchronized_timing#   sA    "&!*!19R[_!`!`!`$$&&&&&r   c                     d| _         | j        r6| j                                        r| j                            d           dS dS dS )z#Stop the synchronized timing systemFg      ?)timeoutN)r   r   is_alivejoinr*   s    r   stop_synchronized_timingz)TimingController.stop_synchronized_timing)   s_    "'! 	5d&<&E&E&G&G 	5"'''44444	5 	5 	5 	5r   c                 T    | j         5  || _        ddd           dS # 1 swxY w Y   dS )zUpdate GPS time from GPS readerN)r   r   )r"   gps_datetimes     r   update_gps_timez TimingController.update_gps_time/   sw     	- 	- ,D	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	-s   !!c                    	 | j                                         }d|j        z
  }|j        dk    rd}d| _        d| _        || _        || _        t          d| d           dS # t          $ r}t          d|            Y d}~dS d}~ww xY w)	z
        Start countdown to next minute based on RTC time
        
        Args:
            countdown_callback: Function to call with countdown updates
            transmission_start_callback: Function to call when transmission should start
        <   r   TFz[COUNTDOWN] Starting z) second countdown to next minute boundaryz!Error reading RTC for countdown: N)	r   	read_timesecondr   r!   r   r    print	Exception)r"   r   r    rtc_timeremaining_secondses         r   start_countdownz TimingController.start_countdown4   s    	x))++H !#X_ 4 !##$&!$(D!',D$&8D#/JD,f*;fffggg4 	 	 	9a99:::55555	s   AA# #
B
-BB
c                 >    d| _         d| _        d| _        d| _        dS )zStop the active countdownFN)r   r!   r   r    r*   s    r   stop_countdownzTimingController.stop_countdownR   s(     %#( "&+/(((r   c                 4    | j                                         S )z-Get the most recent cached synchronized times)r   copyr*   s    r   get_cached_timesz!TimingController.get_cached_timesY   s     %%'''r   c                 `   | j         rt          j                    }d|j        z
  }|dz  }|dk    rt	          j        |dz
             	 t          j                    }|j        dk     rnt	          j        d           4|                     |           t	          j        d           | j         d	S d	S )
z>High precision timing loop that synchronizes all time readingsi@B g    .Ag{Gz?g{Gzt?Ti'  gMbP?g?N)r   r   utcnowmicrosecondtimesleep_capture_synchronized_times)r"   nowmicroseconds_to_next_second
sleep_timeprecise_nows        r   r(   z%TimingController._precision_sync_loop]   s    % 	/##C +2CO*C'4y@J D  
:-..."&o//*U22
5!!!	" ,,[999 JsOOO/ % 	 	 	 	 	r   c                    |j         }|| j        k    r| j        5  || _        |}d}| j        r	 |j        r|                    d          n|}| j        j        r| j                            d          n| j        }||z
                                  }t          |          dk     r#t          |          }|t          |          z   }n|}n7# t          t          f$ r#}	t          d|	            | j        }Y d}	~	nd}	~	ww xY wd}
	 | j                                        }
n)# t          $ r}	t          d|	            Y d}	~	nd}	~	ww xY w|||
t!          j                    d| _        | j        r|                     | j                   | j        r|
r| j        r|                     |
           |                                  ddd           dS # 1 swxY w Y   dS dS )z1Capture all time sources at the exact same momentN)tzinfo   )secondsz[GPS SYNC ERROR] z[RTC ERROR] r   )r7   r   r   r   rN   replacetotal_secondsabsroundr   	TypeErrorAttributeErrorr8   r   r6   r9   rF   r   r   r   r   _update_countdown_sync_debug_sync_accuracy)r"   reference_timecurrent_secondrpi_timegps_timeref_time_naivegps_time_naive	time_diffseconds_to_addr<   r:   s              r   rH   z,TimingController._capture_synchronized_timesx   s   '. T555" 2, 2,+9( *  $ 55P^Pe)y)?)?t)?)L)L)LkySWSdSk  *C):)B)B$)B)O)O)Oqu  rC &4n%D$S$S$U$U	y>>A---29-=-=N'5	.8Y8Y8Y'YHH'5H%~6 5 5 55!55666#'#45
  .#x1133HH  . . .,,,--------.
 $##!%	% %! ' <(():;;; ( :X :$:Q ://999 ))+++e2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 65sf   GBCGD C;6G;D  GD G 
E*E<GEA:GGGc                      j         r j        sd|j        z
  }|j        dk    rd}|dk    r=t          |d          \  }}d|dd|d} j        r                     |           d
S d
S  j        sWd _         j        r                     d            fd}t          j        d	|          }|                                 d
S d
S d
S d
S )z1Update countdown display synchronized to RTC timer5   r   zCountdown: 02d:TzCountdown: 00:00c                  P    d _          j        r                                  d S d S )NF)r   r    r*   s   r   delayed_startz>TimingController._update_countdown_sync.<locals>.delayed_start   s8    05-; ? <<>>>>>? ?r   g      ?N)r   r!   r7   divmodr   r   Timerr)   )r"   r:   r;   minssecscountdown_textre   delay_timers   `       r   rW   z'TimingController._update_countdown_sync   s;     	()A 	( "X_ 4 !##$%! 1$$#$5r::
d!Dt!D!D!D$!D!D!D* <++N;;;;;< < / (/3D,. D//0BCCC? ? ? ? ? #,/#}"E"EK%%'''''9	( 	( 	( 	(( (r   c                    | j         }|d         r|d         r|d         j        dz  |d         j        dz  z   |d         j        z   }|d         j        dz  |d         j        dz  z   |d         j        z   }||z
  }|dk    r|dz  }n|dk     r|dz  }t	          |          dk    rt          d	| d
           |d         r|d         r|d         j        dz  |d         j        dz  z   |d         j        z   }|d         j        dz  |d         j        dz  z   |d         j        z   }||z
  }|dk    r|dz  }n|dk     r|dz  }t	          |          dk    rt          d| d
           dS dS dS dS )z-Debug output to console for sync verificationr   r   i  r5   i  iQ i@W   z([SYNC DEBUG] Time difference: RPI-RTC = z secondsr   z'[SYNC DEBUG] GPS difference: RPI-GPS = N)r   hourminuter7   rS   r8   )r"   cachedrpi_total_secondsrtc_total_secondsr_   gps_total_secondsgps_diffs          r   rX   z%TimingController._debug_sync_accuracy   s   "%= 	VVE] 	V &u 2T 9F5M<PSU<U UX^_dXeXl l &u 2T 9F5M<PSU<U UX^_dXeXl l),==I 5  U"		V##U"	9~~!!TTTTUUU %= 	TVE] 	T &u 2T 9F5M<PSU<U UX^_dXeXl l &u 2T 9F5M<PSU<U UX^_dXeXl l(+<<H %E!F""E!8}}q  RRRRSSSSS	T 	T 	T 	T ! r   r	   )__name__
__module____qualname____doc__r#   r+   r0   r3   r=   r?   rB   r(   rH   rW   rX   r
   r   r   r   r      s        HH) ) ) )6' ' '5 5 5- - -
  <0 0 0( ( (  68, 8, 8,t( ( (@T T T T Tr   r   )r   rF   r   r   r   r
   r   r   <module>ry      sx         ( ( ( ( ( ( ( (lT lT lT lT lT lT lT lT lT lTr   