# include  "config.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "obj/gitversion.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ********************* includes *********************
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "libc.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "safety.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "provision.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "drivers/drivers.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "drivers/llgpio.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "gpio.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "drivers/uart.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "drivers/adc.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "drivers/usb.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "drivers/gmlan_alt.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "drivers/can.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "drivers/spi.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "drivers/timer.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ***************************** fan *****************************
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  fan_init ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // timer for fan PWM
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  TIM3 - > CCMR2  =  TIM_CCMR2_OC3M_2  |  TIM_CCMR2_OC3M_1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  TIM3 - > CCER  =  TIM_CCER_CC3E ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  timer_init ( TIM3 ,  10 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  fan_set_speed ( int  fan_speed )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  TIM3 - > CCR3  =  fan_speed ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ********************* serial debugging *********************
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  debug_ring_callback ( uart_ring  * ring )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  char  rcv ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  while  ( getc ( ring ,  & rcv ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    putc ( ring ,  rcv ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // jump to DFU flash
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( rcv  = =  ' z ' )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      enter_bootloader_mode  =  ENTER_BOOTLOADER_MAGIC ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      NVIC_SystemReset ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // normal reset
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( rcv  = =  ' x ' )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      NVIC_SystemReset ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // enable CDP mode
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( rcv  = =  ' C ' )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puts ( " switching USB to CDP mode \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      set_usb_power_mode ( USB_POWER_CDP ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( rcv  = =  ' c ' )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puts ( " switching USB to client mode \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      set_usb_power_mode ( USB_POWER_CLIENT ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( rcv  = =  ' D ' )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puts ( " switching USB to DCP mode \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      set_usb_power_mode ( USB_POWER_DCP ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ***************************** USB port *****************************
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								int  get_health_pkt ( void  * dat )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  struct  __attribute__ ( ( packed ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint32_t  voltage ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint32_t  current ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  started ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  controls_allowed ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  gas_interceptor_detected ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  started_signal_detected ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  started_alt ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  }  * health  =  dat ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  //Voltage will be measured in mv. 5000 = 5V
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  uint32_t  voltage  =  adc_get ( ADCCHAN_VOLTAGE ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( revision  = =  PANDA_REV_AB )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //REVB has a 100, 27 (27/127) voltage divider
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Here is the calculation for the scale
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //ADCV = VIN_S * (27/127) * (4095/3.3)
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //RETVAL = ADCV * s = VIN_S*1000
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //s = 1000/((4095/3.3)*(27/127)) = 3.79053046
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Avoid needing floating point math
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    health - > voltage  =  ( voltage  *  3791 )  /  1000 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //REVC has a 10, 1 (1/11) voltage divider
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Here is the calculation for the scale (s)
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //ADCV = VIN_S * (1/11) * (4095/3.3)
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //RETVAL = ADCV * s = VIN_S*1000
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //s = 1000/((4095/3.3)*(1/11)) = 8.8623046875
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Avoid needing floating point math
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    health - > voltage  =  ( voltage  *  8862 )  /  1000 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# ifdef PANDA 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  health - > current  =  adc_get ( ADCCHAN_CURRENT ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  int  safety_ignition  =  safety_ignition_hook ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( safety_ignition  <  0 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Use the GPIO pin to determine ignition
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    health - > started  =  ( GPIOA - > IDR  &  ( 1  < <  1 ) )  = =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Current safety hooks want to determine ignition (ex: GM)
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    health - > started  =  safety_ignition ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# else 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  health - > current  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  health - > started  =  ( GPIOC - > IDR  &  ( 1  < <  13 ) )  ! =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  health - > controls_allowed  =  controls_allowed ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  health - > gas_interceptor_detected  =  gas_interceptor_detected ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // DEPRECATED
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  health - > started_alt  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  health - > started_signal_detected  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  sizeof ( * health ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								int  usb_cb_ep1_in ( uint8_t  * usbdata ,  int  len ,  int  hardwired )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  CAN_FIFOMailBox_TypeDef  * reply  =  ( CAN_FIFOMailBox_TypeDef  * ) usbdata ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  int  ilen  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  while  ( ilen  <  min ( len / 0x10 ,  4 )  & &  can_pop ( & can_rx_q ,  & reply [ ilen ] ) )  ilen + + ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  ilen * 0x10 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// send on serial, first byte to select the ring
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  usb_cb_ep2_out ( uint8_t  * usbdata ,  int  len ,  int  hardwired )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( len  = =  0 )  return ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  uart_ring  * ur  =  get_ring_by_number ( usbdata [ 0 ] ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( ! ur )  return ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( ( usbdata [ 0 ]  <  2 )  | |  safety_tx_lin_hook ( usbdata [ 0 ] - 2 ,  usbdata + 1 ,  len - 1 ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( int  i  =  1 ;  i  <  len ;  i + + )  while  ( ! putc ( ur ,  usbdata [ i ] ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// send on CAN
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  usb_cb_ep3_out ( uint8_t  * usbdata ,  int  len ,  int  hardwired )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  int  dpkt  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  for  ( dpkt  =  0 ;  dpkt  <  len ;  dpkt  + =  0x10 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint32_t  * tf  =  ( uint32_t * ) ( & usbdata [ dpkt ] ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // make a copy
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CAN_FIFOMailBox_TypeDef  to_push ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    to_push . RDHR  =  tf [ 3 ] ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    to_push . RDLR  =  tf [ 2 ] ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    to_push . RDTR  =  tf [ 1 ] ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    to_push . RIR  =  tf [ 0 ] ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  bus_number  =  ( to_push . RDTR  > >  4 )  &  CAN_BUS_NUM_MASK ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    can_send ( & to_push ,  bus_number ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								int  is_enumerated  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  usb_cb_enumeration_complete ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  puts ( " USB enumeration complete \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  is_enumerated  =  1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								int  usb_cb_control_msg ( USB_Setup_TypeDef  * setup ,  uint8_t  * resp ,  int  hardwired )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  int  resp_len  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  uart_ring  * ur  =  NULL ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  int  i ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  switch  ( setup - > b . bRequest )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xc0: get CAN debug info
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xc0 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puts ( " can tx:  " ) ;  puth ( can_tx_cnt ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puts ( "  txd:  " ) ;  puth ( can_txd_cnt ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puts ( "  rx:  " ) ;  puth ( can_rx_cnt ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puts ( "  err:  " ) ;  puth ( can_err_cnt ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puts ( " \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xc1: is grey panda
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xc1 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      resp [ 0 ]  =  is_grey_panda ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      resp_len  =  1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xd0: fetch serial number
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xd0 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      # ifdef PANDA 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // addresses are OTP
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( setup - > b . wValue . w  = =  1 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          memcpy ( resp ,  ( void  * ) 0x1fff79c0 ,  0x10 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          resp_len  =  0x10 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          get_provision_chunk ( resp ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          resp_len  =  PROVISION_CHUNK_LEN ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      # endif 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xd1: enter bootloader mode
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xd1 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // this allows reflashing of the bootstub
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // so it's blocked over wifi
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      switch  ( setup - > b . wValue . w )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  0 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          if  ( hardwired )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            puts ( " -> entering bootloader \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            enter_bootloader_mode  =  ENTER_BOOTLOADER_MAGIC ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            NVIC_SystemReset ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  1 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          puts ( " -> entering softloader \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          enter_bootloader_mode  =  ENTER_SOFTLOADER_MAGIC ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          NVIC_SystemReset ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xd2: get health packet
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xd2 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      resp_len  =  get_health_pkt ( resp ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xd3: set fan speed
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xd3 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      fan_set_speed ( setup - > b . wValue . w ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xd6: get version
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xd6 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      COMPILE_TIME_ASSERT ( sizeof ( gitversion )  < =  MAX_RESP_LEN ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      memcpy ( resp ,  gitversion ,  sizeof ( gitversion ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      resp_len  =  sizeof ( gitversion ) - 1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xd8: reset ST
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xd8 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      NVIC_SystemReset ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xd9: set ESP power
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xd9 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( setup - > b . wValue . w  = =  1 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        set_esp_mode ( ESP_ENABLED ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  if  ( setup - > b . wValue . w  = =  2 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        set_esp_mode ( ESP_BOOTMODE ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        set_esp_mode ( ESP_DISABLED ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xda: reset ESP, with optional boot mode
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xda : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      set_esp_mode ( ESP_DISABLED ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      delay ( 1000000 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( setup - > b . wValue . w  = =  1 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        set_esp_mode ( ESP_BOOTMODE ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        set_esp_mode ( ESP_ENABLED ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      delay ( 1000000 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      set_esp_mode ( ESP_ENABLED ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xdb: set GMLAN multiplexing mode
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xdb : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      # ifdef PANDA 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( setup - > b . wValue . w  = =  1 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          // GMLAN ON
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          if  ( setup - > b . wIndex . w  = =  1 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            can_set_gmlan ( 1 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          }  else  if  ( setup - > b . wIndex . w  = =  2 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // might be ignored on rev b panda
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            can_set_gmlan ( 2 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          can_set_gmlan ( - 1 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      # endif 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xdc: set safety mode
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xdc : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // this is the only way to leave silent mode
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // and it's blocked over WiFi
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // Allow ELM security mode to be set over wifi.
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( hardwired  | |  setup - > b . wValue . w  = =  SAFETY_NOOUTPUT  | |  setup - > b . wValue . w  = =  SAFETY_ELM327 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        safety_set_mode ( setup - > b . wValue . w ,  ( int16_t ) setup - > b . wIndex . w ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        switch  ( setup - > b . wValue . w )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          case  SAFETY_NOOUTPUT : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            can_silent  =  ALL_CAN_SILENT ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          case  SAFETY_ELM327 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            can_silent  =  ALL_CAN_BUT_MAIN_SILENT ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            can_autobaud_enabled [ 0 ]  =  false ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          default : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            can_silent  =  ALL_CAN_LIVE ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            can_autobaud_enabled [ 0 ]  =  false ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            can_autobaud_enabled [ 1 ]  =  false ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # ifdef PANDA 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              can_autobaud_enabled [ 2 ]  =  false ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # endif 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        can_init_all ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xdd: enable can forwarding
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xdd : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // wValue = Can Bus Num to forward from
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // wIndex = Can Bus Num to forward to
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( setup - > b . wValue . w  <  BUS_MAX  & &  setup - > b . wIndex . w  <  BUS_MAX  & & 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          setup - > b . wValue . w  ! =  setup - > b . wIndex . w )  {  // set forwarding
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        can_set_forwarding ( setup - > b . wValue . w ,  setup - > b . wIndex . w  &  CAN_BUS_NUM_MASK ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  if ( setup - > b . wValue . w  <  BUS_MAX  & &  setup - > b . wIndex . w  = =  0xFF ) {  //Clear Forwarding
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        can_set_forwarding ( setup - > b . wValue . w ,  - 1 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xde: set can bitrate
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xde : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( setup - > b . wValue . w  <  BUS_MAX )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        can_autobaud_enabled [ setup - > b . wValue . w ]  =  false ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        can_speed [ setup - > b . wValue . w ]  =  setup - > b . wIndex . w ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        can_init ( CAN_NUM_FROM_BUS_NUM ( setup - > b . wValue . w ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xe0: uart read
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xe0 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      ur  =  get_ring_by_number ( setup - > b . wValue . w ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( ! ur )  break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( ur  = =  & esp_ring )  uart_dma_drain ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // read
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      while  ( ( resp_len  <  min ( setup - > b . wLength . w ,  MAX_RESP_LEN ) )  & & 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         getc ( ur ,  ( char * ) & resp [ resp_len ] ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        + + resp_len ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xe1: uart set baud rate
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xe1 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      ur  =  get_ring_by_number ( setup - > b . wValue . w ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( ! ur )  break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      uart_set_baud ( ur - > uart ,  setup - > b . wIndex . w ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xe2: uart set parity
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xe2 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      ur  =  get_ring_by_number ( setup - > b . wValue . w ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( ! ur )  break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      switch  ( setup - > b . wIndex . w )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  0 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          // disable parity, 8-bit
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ur - > uart - > CR1  & =  ~ ( USART_CR1_PCE  |  USART_CR1_M ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  1 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          // even parity, 9-bit
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ur - > uart - > CR1  & =  ~ USART_CR1_PS ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ur - > uart - > CR1  | =  USART_CR1_PCE  |  USART_CR1_M ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  2 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          // odd parity, 9-bit
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ur - > uart - > CR1  | =  USART_CR1_PS ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ur - > uart - > CR1  | =  USART_CR1_PCE  |  USART_CR1_M ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        default : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xe4: uart set baud rate extended
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xe4 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      ur  =  get_ring_by_number ( setup - > b . wValue . w ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( ! ur )  break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      uart_set_baud ( ur - > uart ,  ( int ) setup - > b . wIndex . w * 300 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xe5: set CAN loopback (for testing)
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xe5 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      can_loopback  =  ( setup - > b . wValue . w  >  0 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      can_init_all ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xe6: set USB power
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xe6 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( revision  = =  PANDA_REV_C )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( setup - > b . wValue . w  = =  1 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          puts ( " user setting CDP mode \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          set_usb_power_mode ( USB_POWER_CDP ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if  ( setup - > b . wValue . w  = =  2 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          puts ( " user setting DCP mode \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          set_usb_power_mode ( USB_POWER_DCP ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          puts ( " user setting CLIENT mode \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          set_usb_power_mode ( USB_POWER_CLIENT ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xf0: do k-line wValue pulse on uart2 for Acura
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xf0 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( setup - > b . wValue . w  = =  1 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        GPIOC - > ODR  & =  ~ ( 1  < <  10 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        GPIOC - > MODER  & =  ~ GPIO_MODER_MODER10_1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        GPIOC - > MODER  | =  GPIO_MODER_MODER10_0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        GPIOC - > ODR  & =  ~ ( 1  < <  12 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        GPIOC - > MODER  & =  ~ GPIO_MODER_MODER12_1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        GPIOC - > MODER  | =  GPIO_MODER_MODER12_0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      for  ( i  =  0 ;  i  <  80 ;  i + + )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        delay ( 8000 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( setup - > b . wValue . w  = =  1 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          GPIOC - > ODR  | =  ( 1  < <  10 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          GPIOC - > ODR  & =  ~ ( 1  < <  10 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          GPIOC - > ODR  | =  ( 1  < <  12 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          GPIOC - > ODR  & =  ~ ( 1  < <  12 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( setup - > b . wValue . w  = =  1 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        GPIOC - > MODER  & =  ~ GPIO_MODER_MODER10_0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        GPIOC - > MODER  | =  GPIO_MODER_MODER10_1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        GPIOC - > MODER  & =  ~ GPIO_MODER_MODER12_0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        GPIOC - > MODER  | =  GPIO_MODER_MODER12_1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      delay ( 140  *  9000 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xf1: Clear CAN ring buffer.
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xf1 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( setup - > b . wValue . w  = =  0xFFFF )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        puts ( " Clearing CAN Rx queue \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        can_clear ( & can_rx_q ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  if  ( setup - > b . wValue . w  <  BUS_MAX )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        puts ( " Clearing CAN Tx queue \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        can_clear ( can_queues [ setup - > b . wValue . w ] ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // **** 0xf2: Clear UART ring buffer.
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0xf2 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        uart_ring  *  rb  =  get_ring_by_number ( setup - > b . wValue . w ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( rb )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          puts ( " Clearing UART queue. \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          clear_uart_buff ( rb ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puts ( " NO HANDLER  " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puth ( setup - > b . bRequest ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puts ( " \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  resp_len ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# ifdef PANDA 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								int  spi_cb_rx ( uint8_t  * data ,  int  len ,  uint8_t  * data_out )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // data[0]  = endpoint
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // data[2]  = length
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // data[4:] = data
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  int  resp_len  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  switch  ( data [ 0 ] )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  0 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // control transfer
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      resp_len  =  usb_cb_control_msg ( ( USB_Setup_TypeDef  * ) ( data + 4 ) ,  data_out ,  0 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  1 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // ep 1, read
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      resp_len  =  usb_cb_ep1_in ( data_out ,  0x40 ,  0 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  2 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // ep 2, send serial
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      usb_cb_ep2_out ( data + 4 ,  data [ 2 ] ,  0 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  3 : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // ep 3, send CAN
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      usb_cb_ep3_out ( data + 4 ,  data [ 2 ] ,  0 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  resp_len ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# else 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								int  spi_cb_rx ( uint8_t  * data ,  int  len ,  uint8_t  * data_out )  {  return  0 ;  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// ***************************** main code *****************************
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  __initialize_hardware_early ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  early ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  __attribute__  ( ( noinline ) )  enable_fpu ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // enable the FPU
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  SCB - > CPACR  | =  ( ( 3UL  < <  10 * 2 )  |  ( 3UL  < <  11 * 2 ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								int  main ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // shouldn't have interrupts here, but just in case
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  __disable_irq ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // init early devices
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  clock_init ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  periph_init ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  detect ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // print hello
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  puts ( " \n \n \n ************************ MAIN START ************************ \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // detect the revision and init the GPIOs
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  puts ( " config: \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  # ifdef PANDA 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    puts ( revision  = =  PANDA_REV_C  ?  "   panda rev c \n "  :  "   panda rev a or b \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  # else 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    puts ( "   legacy \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  # endif 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  puts ( has_external_debug_serial  ?  "   real serial \n "  :  "   USB serial \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  puts ( is_giant_panda  ?  "   GIANTpanda detected \n "  :  "   not GIANTpanda \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  puts ( is_grey_panda  ?  "   gray panda detected! \n "  :  "   white panda \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  puts ( is_entering_bootmode  ?  "   ESP wants bootmode \n "  :  "   no bootmode \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  gpio_init ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# ifdef PANDA 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // panda has an FPU, let's use it!
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  enable_fpu ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // enable main uart if it's connected
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( has_external_debug_serial )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // WEIRDNESS: without this gate around the UART, it would "crash", but only if the ESP is enabled
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // assuming it's because the lines were left floating and spurious noise was on them
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uart_init ( USART2 ,  115200 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# ifdef PANDA 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( is_grey_panda )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uart_init ( USART1 ,  9600 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // enable ESP uart
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uart_init ( USART1 ,  115200 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // enable LIN
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  uart_init ( UART5 ,  10400 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  UART5 - > CR2  | =  USART_CR2_LINEN ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  uart_init ( USART3 ,  10400 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  USART3 - > CR2  | =  USART_CR2_LINEN ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // init microsecond system timer
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // increments 1000000 times per second
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // generate an update to set the prescaler
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  TIM2 - > PSC  =  48 - 1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  TIM2 - > CR1  =  TIM_CR1_CEN ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  TIM2 - > EGR  =  TIM_EGR_UG ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // use TIM2->CNT to read
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // enable USB
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  usb_init ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // default to silent mode to prevent issues with Ford
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  safety_set_mode ( SAFETY_NOOUTPUT ,  0 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  can_silent  =  ALL_CAN_SILENT ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  can_init_all ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  adc_init ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# ifdef PANDA 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  spi_init ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // set PWM
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  fan_init ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  fan_set_speed ( 0 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  puts ( " **** INTERRUPTS ON **** \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  __enable_irq ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // if the error interrupt is enabled to quickly when the CAN bus is active
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // something bad happens and you can't connect to the device over USB
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  delay ( 10000000 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  CAN1 - > IER  | =  CAN_IER_ERRIE  |  CAN_IER_LECIE ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // LED should keep on blinking all the time
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  uint64_t  cnt  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  # ifdef PANDA 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint64_t  marker  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # define CURRENT_THRESHOLD 0xF00 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # define CLICKS 8 
  
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // Enough clicks to ensure that enumeration happened. Should be longer than bootup time of the device connected to EON
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # define CLICKS_BOOTUP 30 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  # endif 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  for  ( cnt = 0 ; ; cnt + + )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    can_live  =  pending_can_live ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //puth(usart1_dma); puts(" "); puth(DMA2_Stream5->M0AR); puts(" "); puth(DMA2_Stream5->NDTR); puts("\n");
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # ifdef PANDA 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      int  current  =  adc_get ( ADCCHAN_CURRENT ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      switch  ( usb_power_mode )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  USB_POWER_CLIENT : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          if  ( ( cnt - marker )  > =  CLICKS )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! is_enumerated )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              puts ( " USBP: didn't enumerate, switching to CDP mode \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              // switch to CDP
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              set_usb_power_mode ( USB_POWER_CDP ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              marker  =  cnt ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          // keep resetting the timer if it's enumerated
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          if  ( is_enumerated )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            marker  =  cnt ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  USB_POWER_CDP : 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								          // been CLICKS_BOOTUP clicks since we switched to CDP
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          if  ( ( cnt - marker )  > =  CLICKS_BOOTUP  )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // measure current draw, if positive and no enumeration, switch to DCP
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! is_enumerated  & &  current  <  CURRENT_THRESHOLD )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              puts ( " USBP: no enumeration with current draw, switching to DCP mode \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              set_usb_power_mode ( USB_POWER_DCP ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              marker  =  cnt ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          // keep resetting the timer if there's no current draw in CDP
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          if  ( current  > =  CURRENT_THRESHOLD )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            marker  =  cnt ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  USB_POWER_DCP : 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          // been at least CLICKS clicks since we switched to DCP
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          if  ( ( cnt - marker )  > =  CLICKS )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // if no current draw, switch back to CDP
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( current  > =  CURRENT_THRESHOLD )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              puts ( " USBP: no current draw, switching back to CDP mode \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              set_usb_power_mode ( USB_POWER_CDP ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              marker  =  cnt ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          // keep resetting the timer if there's current draw in DCP
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          if  ( current  <  CURRENT_THRESHOLD )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            marker  =  cnt ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          break ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // ~0x9a = 500 ma
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      /*puth(current);
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puts ( " \n " ) ; */ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # endif 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // reset this every 16th pass
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ( cnt & 0xF )  = =  0 )  pending_can_live  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # ifdef DEBUG 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puts ( " ** blink  " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puth ( can_rx_q . r_ptr ) ;  puts ( "   " ) ;  puth ( can_rx_q . w_ptr ) ;  puts ( "    " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puth ( can_tx1_q . r_ptr ) ;  puts ( "   " ) ;  puth ( can_tx1_q . w_ptr ) ;  puts ( "    " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      puth ( can_tx2_q . r_ptr ) ;  puts ( "   " ) ;  puth ( can_tx2_q . w_ptr ) ;  puts ( " \n " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # endif 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // set green LED to be controls allowed
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    set_led ( LED_GREEN ,  controls_allowed ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // blink the red LED
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  div_mode  =  ( ( usb_power_mode  = =  USB_POWER_DCP )  ?  4  :  1 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( int  div_mode_loop  =  0 ;  div_mode_loop  <  div_mode ;  div_mode_loop + + )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      for  ( int  fade  =  0 ;  fade  <  1024 ;  fade  + =  8 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  ( int  i  =  0 ;  i  <  128 / div_mode ;  i + + )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          set_led ( LED_RED ,  0 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          if  ( fade  <  512 )  {  delay ( 512 - fade ) ;  }  else  {  delay ( fade - 512 ) ;  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          set_led ( LED_RED ,  1 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          if  ( fade  <  512 )  {  delay ( fade ) ;  }  else  {  delay ( 1024 - fade ) ;  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // turn off the blue LED, turned on by CAN
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # ifdef PANDA 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      set_led ( LED_BLUE ,  0 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # endif 
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}