
    /hS                        d dl Z d dlZd dlmZ 	 d dlZdZ ed           n# e$ r dZ ed           Y nw xY w G d d          Ze	d	k    r d
 Z
d Z ee
          Ze                    e            ed            ede                                           e                    dddd            ede                                           e                    d            ede                                           e                    d            ede                                           	  ej        d           n# e$ r Y nw xY we                                 dS dS )    N)DeadbandControllerTz:gpiod library loaded successfully - GPIO functions enabledFz5Warning: gpiod not available, GPIO functions disabledc                   t    e Zd ZdZddZd Zd Zd Zd ZddZ	dd	Z
d
 Zd Z	 	 ddZd ZddZd Zd ZdS )GPIOControllerz3Handles all GPIO operations for the CSEM TriggerboxNc                    |pd | _         d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d | _	        d | _
        d | _        d| _        d | _        d | _        d | _        d | _        d | _        t$          | _        d | _        t+                      | _        | j                            dd           | j                            dd           |                                  d S )	Nc                 &    t          d|            S )Nz[GPIO] printmsgs    0/home/morepork/Documents/CSEM/gpio_controller.py<lambda>z)GPIOController.__init__.<locals>.<lambda>   s    u_s__?U?U                 F   )	rising_ms
falling_ms)status_callbacktx_status_pinfrequency_pin
gpio26_pinpps_pin
gpio_stategpio26_state	pps_statetransmittingfrequency_output_threadgpio26_threadpps_monitoring_threadpps_monitoring	gpio_chiptx_status_linefrequency_linegpio26_linepps_lineGPIO_AVAILABLEgpio_availablepps_callbackr   deadband_controllerset_duty_deadbandsset_polarity_deadbands
_init_gpio)selfr   s     r   __init__zGPIOController.__init__   s   .V3U3U    ! "'+$!%)"# "", ! $6#7#7  33aA3NNN 77!PQ7RRRr   c           
      <   | j         s|                     d           dS 	 t          j        d          | _        | j                            | j                  | _        | j                            dt          j	                   | j        
                    d           | j                            | j                  | _        | j                            dt          j	                   | j        
                    d           | j                            | j                  | _        | j                            dt          j	                   | j        
                    d           | j                            | j                  | _        | j                            d	t          j                   |                     d
| j         d| j         d| j         d| j                    dS # t$          $ r+}|                     d| d           d| _         Y d}~dS d}~ww xY w)zInitialize GPIO pinsz*GPIO not available - PPS will be simulatedN	gpiochip4	tx_status)consumertyper   frequency_outputgpio26_output	pps_inputz+GPIO initialized successfully - TX Status: z, Frequency: z
, GPIO26: z, PPS: zFailed to initialize GPIO: z - PPS will be simulatedF)r)   r   gpiodChipr#   get_liner   r$   requestLINE_REQ_DIR_OUT	set_valuer   r%   r   r&   r   r'   LINE_REQ_DIR_IN	Exceptionr/   es     r   r.   zGPIOController._init_gpio8   sP   " 	  !MNNNF	("Z44DN #'."9"9$:L"M"MD''5CY'ZZZ))!,,, #'."9"9$:L"M"MD''1C%J`'aaa))!,,,  $~66tGGD$$oEDZ$[[[&&q))) !N33DLAADMM!!;U=R!SSS    "utOa  "u  "upt  qC  "u  "u  OS  O^  "u  "u  gk  gs  "u  "u  v  v  v  v  v 	( 	( 	(  !Zq!Z!Z!Z[[["'D	(s   GG& &
H0 HHc                 *   | j         rdS || _        d| _         t          j        | j        d          | _        | j                                         | j        r&| j        r| 	                    d| j
                    dS | 	                    d           dS )z
        Start monitoring PPS signal on GPIO 17
        
        Args:
            pps_callback: Function to call with PPS state changes (True/False)
        NT)targetdaemonz$Started REAL PPS monitoring on GPIO z5Started SIMULATED PPS monitoring (GPIO not available))r"   r*   	threadingThread_pps_monitoring_loopr!   startr)   r'   r   r   )r/   r*   s     r   start_pps_monitoringz#GPIOController.start_pps_monitoringZ   s      	F(" &/%5,&
 &
 &
" 	"((*** 	[4= 	[  !V!V!VWWWWW  !YZZZZZr   c                     d| _         | j        r4| j                                        r| j                            d           |                     d           dS )zStop PPS monitoringF      ?timeoutzStopped PPS monitoringN)r"   r!   is_alivejoinr   r/   s    r   stop_pps_monitoringz"GPIOController.stop_pps_monitorings   s`    #% 	9$*D*M*M*O*O 	9&++C+888566666r   c                 X   d}| j         r| j        r| j        r	 t          | j                                                  }||k    r%|| _        | j        r|                     |           |}n# t          $ r#}|                     d|            Y d}~dS d}~ww xY wt          j	                    }t          |          dz  dk    }||k    rA|| _        | j        r|                     |           |}|                     d|rdnd            t          j        d	           | j         dS dS )
z.PPS monitoring loop running in separate threadFzPPS monitoring error: N   r   zPPS (simulated): HIGHLOW{Gz?)r"   r)   r'   bool	get_valuer   r*   r@   r   timeintsleep)r/   last_pps_statecurrent_pps_staterB   current_timesimulated_ppss         r   rH   z#GPIOController._pps_monitoring_loop|   s   ! 	" ct} c(,T]-D-D-F-F(G(G% )N::):, A --.?@@@):    (()E!)E)EFFFEEEEE  $y{{!$\!2!2Q!61 < N22%2DN( 9))-888%2N(()a}=_VVZ_)a)abbbJt9 ! 	 	 	 	 	s   AA, ,
B6BBc                 n   	
 |dk    rt          d          d _         j                                         |r|                    d          nd}|r|                    d          nd	|r|                    d          nd
	 fd}
 fd	} j        r} j        rv	  j                            d
           |r |d                                d j	         d           nQ# t          $ r"}                     d|            Y d}~n*d}~ww xY w|r |d                                d           t          j         j        |dz  |fd           _         j                                         t          j         j        ||fd           _         j                                          j                                        } j        rdnd}                     d| d|dz   d| d                                d|d         dd|d         dd|d         dd|d         dd	           dS ) z
        Start GPIO transmission at specified frequency
        
        Args:
            frequency: Transmission frequency in Hz
            indicator_callbacks: Dict with 'onoff', 'duty', 'polarity' callback functions
        r   zFrequency must be positiveTonoffNdutypolarityc                 F    rj                             |            d S d S N)r+   apply_duty_deadband)stateoriginal_duty_callbackr/   s    r   duty_with_deadbandz=GPIOController.start_transmission.<locals>.duty_with_deadband   s8    % \(<<UDZ[[[[[\ \r   c                 F    rj                             |            d S d S rf   )r+   apply_polarity_deadband)rh   original_polarity_callbackr/   s    r   polarity_with_deadbandzAGPIOController.start_transmission.<locals>.polarity_with_deadband   s8    ) d(@@Hbcccccd dr      TX Status pin z	 set HIGHzFailed to set TX status HIGH: zTX Status (simulated): HIGHrT   )rD   argsrE   	REAL GPIO	SIMULATEDzStarted z. - Status pin HIGH, Frequency pin toggling at z Hz, GPIO26 toggling at z HzzDeadbands: Duty(duty_rising_ms.1f/duty_falling_msms), Polarity(polarity_rising_mspolarity_falling_msms))
ValueErrorr   r+   reset_stategetr)   r$   r>   r   r   r@   rF   rG   _frequency_output_loopr   rI   _gpio26_loopr    get_deadband_info)r/   	frequencyindicator_callbacksoriginal_onoff_callbackrj   rn   rB   deadband_infotransmission_moderi   rm   s   `        @@r   start_transmissionz!GPIOController.start_transmission   s    >>9:::  	 ,,... GZ"c"5"9"9'"B"B"B_cDW!a!4!8!8!@!@!@]aL_%i%8%<%<Z%H%H%Hei"	\ 	\ 	\ 	\ 	\ 	\	d 	d 	d 	d 	d 	d
  	A4#6 	AK#--a000* 2++D111$$%Sd6H%S%S%STTTT K K K$$%Ia%I%IJJJJJJJJK ' .''---  !?@@@ (1'7.a-!34(
 (
 (
$
 	$**,,, '-$34
 
 

 	  """ 0BBDD+/+>OKKK  _(9  _  _iruviv  _  _  QZ  _  _  _  	`  	`  	`  b>N0O  b  b  bVcduVv  b  b  b  KX  Ym  Kn  b  b  b  uB  CX  uY  b  b  b  b  	c  	c  	c  	c  	cs   AC% %
D/DDc                    d| _         | j                                         | j        r4| j                                        r| j                            d           | j        r4| j                                        r| j                            d           | j        r| j        r	 | j        	                    d           |rd|v r |d         d           | 
                    d| j         d           n/# t          $ r"}| 
                    d|            Y d	}~nd	}~ww xY w| j        r	 | j        	                    d           d| _        |rd
|v r |d
         d           | 
                    d| j         d           n/# t          $ r"}| 
                    d|            Y d	}~nd	}~ww xY w| j        r	 | j        	                    d           d| _        |rd|v r |d         d           | 
                    d| j         d           nV# t          $ r"}| 
                    d|            Y d	}~n/d	}~ww xY wn&|r$|                                D ]}|r |d           | j        rdnd}| 
                    d| d           d	S )zStop GPIO transmissionFrL   rM   r   rb   rp   z set LOWzFailed to set TX status LOW: Nrc   zFrequency pin z$Failed to set frequency output LOW: rd   zGPIO26 pin zFailed to set GPIO26 LOW: rr   rs   zStopped z - All GPIO pins set LOW)r   r+   r}   r   rO   rP   r    r)   r$   r>   r   r   r@   r%   r   r   r&   r   r   values)r/   r   rB   callbackr   s        r   stop_transmissionz GPIOController.stop_transmission   s    " 	 ,,... ' 	;D,H,Q,Q,S,S 	;(--c-::: 	1$"4"="="?"? 	1##C#000  "	(" NN'11!444* <w:M/M/M4+G4U;;;(()V$:L)V)V)VWWWW  N N N(()L)L)LMMMMMMMMN " UU'11!444&+DO* ;v9L/L/L3+F3E:::(()V$:L)V)V)VWWWW  U U U(()SPQ)S)STTTTTTTTU  KK$..q111(-D%* ?z=P/P/P7+J7>>>(()Pt)P)P)PQQQQ  K K K(()Ia)I)IJJJJJJJJKK # ( 3 : : < < ( (H ( +/+>OKKKS(9SSSTTTTTsK   'AC7 7
D#DD#.AF 
F1F,,F1<AH 
H?H::H?c                    d|z  }| j         r| j        r{| j        rt	 | j         | _        | j                            | j        rdnd           |r || j                   nO# t
          $ r#}|                     d|            Y d}~dS d}~ww xY w| j         | _        |r || j                   t          j        |           | j         dS dS )z.GPIO 26 output loop running in separate threadrL   ro   r   zGPIO 26 output error: N)	r   r)   r&   r   r>   r@   r   rZ   r\   )r/   r   indicator_callbackhalf_periodrB   s        r   r   zGPIOController._gpio26_loop  s$   Io 	$" :t'7 :,0,=(=D%$..D4E/Lqq1MMM) >**4+<===    (()E!)E)EFFFEEEEE
 )-(9$9!% :&&t'8999J{###!  	$ 	$ 	$ 	$ 	$   AA 
B)BBc                    d|z  }| j         r| j        r{| j        rt	 | j         | _        | j                            | j        rdnd           |r || j                   nO# t
          $ r#}|                     d|            Y d}~dS d}~ww xY w| j         | _        |r || j                   t          j        |           | j         dS dS )z0Frequency output loop running in separate threadrL   ro   r   zFrequency output error: N)	r   r)   r%   r   r>   r@   r   rZ   r\   )r/   toggle_frequencyr   r   rB   s        r   r   z%GPIOController._frequency_output_loop.  s   ,, 	$" 8t': 8*./&9DO'11t2M!!ANNN) <**4?;;;    (()GA)G)GHHHEEEEE
 '+o"5% 8&&t777J{###!  	$ 	$ 	$ 	$ 	$r   c                    ||L| j                                         }||n|d         }||n|d         }| j                             ||           ||L| j                                         }||n|d         }||n|d         }| j                             ||           | j                                         }|                     d|d         dd|d         dd	|d         dd|d         dd
	           dS )a  
        Configure deadband timing for GPIO signals
        
        Args:
            duty_rising_ms: Duty signal rising edge deadband (milliseconds)
            duty_falling_ms: Duty signal falling edge deadband (milliseconds)
            polarity_rising_ms: Polarity signal rising edge deadband (milliseconds)
            polarity_falling_ms: Polarity signal falling edge deadband (milliseconds)
        Nrt   rw   ry   rz   zDeadbands updated: Duty(ru   rv   rx   r{   )r+   r   r,   r-   r   )	r/   rt   rw   ry   rz   currentrisingfallingr   s	            r   configure_deadbandsz"GPIOController.configure_deadbandsD  s    %)D.@@BBG'5'A^^wO_G`F)8)Doo'RcJdG$77HHH)-@-L.@@BBG+=+I''wWkOlF-@-L))RYZoRpG$;;FGLLL0BBDD  jFV8W  j  j  j^kl}^~  j  j  j  S`  au  Sv  j  j  j  }J  K`  }a  j  j  j  j  	k  	k  	k  	k  	kr   c                 4    | j                                         S )z"Get current deadband configuration)r+   r   rQ   s    r   get_deadband_statusz"GPIOController.get_deadband_status^  s    '99;;;r   standardc                    |dk    r| j                             dddd           nn|dk    r| j                             ddd	d	           nI|d
k    r| j                             dddd           n$|dk    r| j                             dddd           | j                                         }|                     d| d|d         dd|d         dd|d         dd|d         dd           dS )z'Set deadbands using predefined profilescsem_optimizedgMb?g~jth?g~jt?{Gzt?)duty_risingduty_fallingpolarity_risingpolarity_fallingfast_responseMbP?gMb`?r   no_deadbandg        z	Profile 'z' loaded: Duty(rt   ru   rv   rw   rx   ry   rz   r{   N)r+   r   r   r   )r/   profiler   s      r   set_custom_deadbandsz#GPIOController.set_custom_deadbandsb  s   &&&$88!" %!&	 9     ''$88!" %!&	 9     
""$88!" %!&	 9     %%$88  #!$	 9    0BBDD  s  s  sO_A`  s  s  sgt  vG  hH  s  s  s  \i  j~  \  s  s  s  FS  Ti  Fj  s  s  s  s  	t  	t  	t  	t  	tr   c                 &   d|z  }|dk    rd}n|dk    rd}nd}|dz  }t          ||          }| j                            |dz  |dz             | j                            |dz  |dz             |                     d	| d
|dz  dd           dS )z>Automatically adjust deadbands based on transmission frequencyg      ?
   r   ro   r   rW   g?i  zAuto-adjusted deadbands for z Hz: ru   msN)minr+   r,   r-   r   )r/   r   periodbase_deadbandmax_deadbandactual_deadbands         r   adjust_deadbands_for_frequencyz-GPIOController.adjust_deadbands_for_frequency  s    y r>>!MM]]!MM!M |m\:: 33Od4JO^bLbccc 77$8NP_bfPfgggjIjjO^bLbjjjjkkkkkr   c                 H   d| _         |                                  | j                                         | j        r| j        rd	 | j                            d           | j                                         n/# t          $ r"}| 	                    d|            Y d}~nd}~ww xY w| j
        rd	 | j
                            d           | j
                                         n/# t          $ r"}| 	                    d|            Y d}~nd}~ww xY w| j        rd	 | j                            d           | j                                         n/# t          $ r"}| 	                    d|            Y d}~nd}~ww xY w| j        rJ	 | j                                         n/# t          $ r"}| 	                    d|            Y d}~nd}~ww xY w| j        rL	 | j                                         dS # t          $ r#}| 	                    d|            Y d}~dS d}~ww xY wdS )	zClean up GPIO resourcesFr   zTX status cleanup error: Nz Frequency output cleanup error: zGPIO26 cleanup error: zPPS cleanup error: zChip close error: )r   rR   r+   r}   r)   r$   r>   releaser@   r   r%   r&   r'   r#   closerA   s     r   cleanupzGPIOController.cleanup  s   ! 	  """ 	 ,,... 	D" JJ'11!444'//1111  J J J(()HQ)H)HIIIIIIIIJ " QQ'11!444'//1111  Q Q Q(()OA)O)OPPPPPPPPQ  GG$..q111$,,....  G G G(()E!)E)EFFFFFFFFG } DDM))++++  D D D(()Bq)B)BCCCCCCCCD > 	??$$&&&&& ? ? ?$$%=!%=%=>>>>>>>>>?	? 	?sx   3A9 9
B%B  B%03C$ $
D.DD3E 
E;E66E;F   
G*GGG2 2
H<HHrf   )NNNN)r   )__name__
__module____qualname____doc__r0   r.   rJ   rR   rH   r   r   r   r   r   r   r   r   r    r   r   r   r      s/       ==& & & &P (  (  (D[ [ [27 7 7     DAc Ac Ac AcF5U 5U 5U 5Un$ $ $,$ $ $, HLHLk k k k4< < < t  t  t  tDl l l**? *? *? *? *?r   r   __main__c                 *    t          d|             d S )Nz[TEST] r   r
   s    r   test_callbackr     s    ooor   c                 2    t          d| rdnd            d S )Nz[PPS] rU   rV   r   )rh   s    r   pps_test_callbackr     s(    31vvE3344444r   )r   z 
Testing deadband configuration:zCurrent deadbands:         r   )rt   rw   ry   rz   zAfter custom config:r   zAfter fast profile:rL   z"After frequency adaptive (0.5 Hz):)rF   rZ   	deadbandsr   r9   r(   r	   ImportErrorr   r   r   r   gpiorJ   r   r   r   r   r\   KeyboardInterruptr   r   r   r   <module>r      sD        ( ( ( ( ( (CLLLN	E
FGGGG C C CN	E
ABBBBBCv? v? v? v? v? v? v? v?t z  5 5 5 >-888D 	/000 
E
-...	E
 8 8 : :;;; 	AqUWmnooo	E
 $":":"<"<=== 	o...	E
!9!9!;!;<<< 	'',,,	E
.0H0H0J0JKKK
1    	LLNNNNNG s   " 77<E EE