/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  upstream_spi . c 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *   Created  on :  21 / 06 / 2015 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *       Author :  Robert  Fisk 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  This  Source  Code  Form  is  subject  to  the  terms  of  the  Mozilla  Public 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  License ,  v .  2.0 .  If  a  copy  of  the  MPL  was  not  distributed  with  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  file ,  You  can  obtain  one  at  https : //mozilla.org/MPL/2.0/.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "upstream_interface_def.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "upstream_spi.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "stm32f4xx_hal.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "board_config.h" 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "interrupts.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								SPI_HandleTypeDef            Hspi1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								UpstreamPacketTypeDef        UpstreamPacket0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								UpstreamPacketTypeDef        UpstreamPacket1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								UpstreamPacketTypeDef *       CurrentWorkingPacket ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								UpstreamPacketTypeDef *       NextTxPacket         =  NULL ;          //Indicates we have a pending TX packet
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								InterfaceStateTypeDef                UpstreamInterfaceState       =  UPSTREAM_INTERFACE_IDLE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								FreePacketCallbackTypeDef            PendingFreePacketCallback    =  NULL ;  //Indicates someone is waiting for a packet buffer to become available
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								SpiPacketReceivedCallbackTypeDef     ReceivePacketCallback        =  NULL ;  //Indicates someone is waiting for a received packet
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								uint32_t                     TemporaryIncomingPacketLength ;       //We don't actually care about what Downstream sends us when we are transmitting. We just need somewhere to put it so that our own packet length is not overwritten.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								uint8_t                      TxOkInterruptReceived  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								uint8_t                      SentCommandClass ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								uint8_t                      SentCommand ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  Upstream_BeginTransmitPacketSize ( void ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  Upstream_BeginTransmitPacketBody ( void ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								HAL_StatusTypeDef  Upstream_CheckBeginPacketReception ( void ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  Upstream_BeginReceivePacketSize ( UpstreamPacketTypeDef *  freePacket ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  Upstream_BeginReceivePacketBody ( void ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  Upstream_InitSPI ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    UpstreamPacket0 . Busy  =  NOT_BUSY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    UpstreamPacket1 . Busy  =  NOT_BUSY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . Instance  =  SPI1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . State  =  HAL_SPI_STATE_RESET ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . Init . Mode  =  SPI_MODE_MASTER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . Init . Direction  =  SPI_DIRECTION_2LINES ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . Init . DataSize  =  SPI_DATASIZE_16BIT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . Init . CLKPolarity  =  SPI_POLARITY_LOW ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . Init . CLKPhase  =  SPI_PHASE_1EDGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . Init . NSS  =  SPI_NSS_SOFT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . Init . BaudRatePrescaler  =  SPI_BAUDRATEPRESCALER_4 ;  //42MHz APB2 / 4 = 10.5Mbaud
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . Init . FirstBit  =  SPI_FIRSTBIT_MSB ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . Init . TIMode  =  SPI_TIMODE_DISABLED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . Init . CRCCalculation  =  SPI_CRCCALCULATION_ENABLED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Hspi1 . Init . CRCPolynomial  =  SPI_CRC_DEFAULTPOLYNOMIAL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    HAL_SPI_Init ( & Hspi1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( DOWNSTREAM_TX_OK_ACTIVE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        TxOkInterruptReceived  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Used by USB interface classes, and by our internal RX code.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								HAL_StatusTypeDef  Upstream_GetFreePacket ( FreePacketCallbackTypeDef  callback ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  > =  UPSTREAM_INTERFACE_ERROR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Do we already have a queued callback?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( PendingFreePacketCallback  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Check if there is a free buffer now
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamPacket0 . Busy  = =  NOT_BUSY ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UpstreamPacket0 . Busy  =  BUSY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        callback ( & UpstreamPacket0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamPacket1 . Busy  = =  NOT_BUSY ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UpstreamPacket1 . Busy  =  BUSY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        callback ( & UpstreamPacket1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Otherwise save requested address for when a buffer becomes free in the future
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PendingFreePacketCallback  =  callback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  HAL_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								UpstreamPacketTypeDef *  Upstream_GetFreePacketImmediately ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  > =  UPSTREAM_INTERFACE_ERROR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //We are expecting a free buffer now
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamPacket0 . Busy  = =  NOT_BUSY ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UpstreamPacket0 . Busy  =  BUSY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  & UpstreamPacket0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamPacket1 . Busy  = =  NOT_BUSY ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UpstreamPacket1 . Busy  =  BUSY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  & UpstreamPacket1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Should not happen:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Used by USB interface classes, and by our internal RX code.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  Upstream_ReleasePacket ( UpstreamPacketTypeDef *  packetToRelease ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    FreePacketCallbackTypeDef  tempCallback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  > =  UPSTREAM_INTERFACE_ERROR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ( packetToRelease  ! =  & UpstreamPacket0 )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ( packetToRelease  ! =  & UpstreamPacket1 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( packetToRelease - > Busy  ! =  BUSY ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( PendingFreePacketCallback  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        tempCallback  =  PendingFreePacketCallback ;    //In extreme situations, running this callback can trigger another request for a free packet,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        PendingFreePacketCallback  =  NULL ;            //thereby causing GetFreePacket to freak out. So we need to clear the callback indicator first.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        tempCallback ( packetToRelease ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        packetToRelease - > Busy  =  NOT_BUSY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Used by USB interface classes only.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//OK to call when still transmitting another packet.
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								//Not OK to call when receiving or waiting for downstream reply,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//as we can't let the size/packet sequence get out of sync.
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								HAL_StatusTypeDef  Upstream_TransmitPacket ( UpstreamPacketTypeDef *  packetToWrite ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  > =  UPSTREAM_INTERFACE_ERROR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Sanity checks
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ( packetToWrite  ! =  & UpstreamPacket0 )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ( packetToWrite  ! =  & UpstreamPacket1 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ( packetToWrite - > Busy  ! =  BUSY )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ( packetToWrite - > Length16  <  UPSTREAM_PACKET_LEN_MIN_16 )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ( packetToWrite - > Length16  >  UPSTREAM_PACKET_LEN_16 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( NextTxPacket  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( UpstreamInterfaceState ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  UPSTREAM_INTERFACE_TX_SIZE_WAIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  UPSTREAM_INTERFACE_TX_SIZE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  UPSTREAM_INTERFACE_TX_PACKET_WAIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  UPSTREAM_INTERFACE_TX_PACKET : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        NextTxPacket  =  packetToWrite ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  UPSTREAM_INTERFACE_IDLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UpstreamInterfaceState  =  UPSTREAM_INTERFACE_TX_SIZE_WAIT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        CurrentWorkingPacket  =  packetToWrite ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        SentCommandClass  =  CurrentWorkingPacket - > CommandClass ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        SentCommand  =  CurrentWorkingPacket - > Command ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //Downstream may have set TxOk pin before we wanted to transmit.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //In this case we can go ahead and transmit now.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( TxOkInterruptReceived ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            TxOkInterruptReceived  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Upstream_BeginTransmitPacketSize ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  HAL_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								//Called at the end of the SPI TxRx transfer,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//at SPI1 interrupt priority. Assume *hspi points to our hspi1.
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								//We TxRx our outgoing packet because the SPI hardware freaks out if we only Tx it :-/
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  HAL_SPI_TxRxCpltCallback ( SPI_HandleTypeDef  * hspi ) 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    UNUSED ( hspi ) ; 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    SpiPacketReceivedCallbackTypeDef  tempPacketCallback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    UpstreamPacketTypeDef *  tempPacketToFree ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    SPI1_NSS_DEASSERT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  > =  UPSTREAM_INTERFACE_ERROR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Finished transmitting packet size
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  = =  UPSTREAM_INTERFACE_TX_SIZE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UpstreamInterfaceState  =  UPSTREAM_INTERFACE_TX_PACKET_WAIT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( TxOkInterruptReceived ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            TxOkInterruptReceived  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Upstream_BeginTransmitPacketBody ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //Finished transmitting packet body
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  = =  UPSTREAM_INTERFACE_TX_PACKET ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ( PendingFreePacketCallback  ! =  NULL )  & &  ( NextTxPacket  = =  NULL ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        tempPacketToFree  =  CurrentWorkingPacket ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( NextTxPacket  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            //NextTxPacket has already passed the checks in Upstream_TransmitPacket.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            //So we just need to pass it to HAL_SPI_Transmit_DMA.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            UpstreamInterfaceState  =  UPSTREAM_INTERFACE_TX_SIZE_WAIT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            CurrentWorkingPacket  =  NextTxPacket ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            NextTxPacket  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            SentCommandClass  =  CurrentWorkingPacket - > CommandClass ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            SentCommand  =  CurrentWorkingPacket - > Command ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( TxOkInterruptReceived ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                TxOkInterruptReceived  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Upstream_BeginTransmitPacketSize ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            //No packet queued for transmission:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            UpstreamInterfaceState  =  UPSTREAM_INTERFACE_IDLE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ReceivePacketCallback  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Upstream_CheckBeginPacketReception ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //Release old packet after moving Next to Current
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Upstream_ReleasePacket ( tempPacketToFree ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  = =  UPSTREAM_INTERFACE_RX_SIZE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ( CurrentWorkingPacket - > Length16  <  UPSTREAM_PACKET_LEN_MIN_16 )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ( CurrentWorkingPacket - > Length16  >  UPSTREAM_PACKET_LEN_16 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UpstreamInterfaceState  =  UPSTREAM_INTERFACE_RX_PACKET_WAIT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( TxOkInterruptReceived ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            TxOkInterruptReceived  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Upstream_BeginReceivePacketBody ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  = =  UPSTREAM_INTERFACE_RX_PACKET ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UpstreamInterfaceState  =  UPSTREAM_INTERFACE_IDLE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ReceivePacketCallback  = =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ( CurrentWorkingPacket - > CommandClass  = =  COMMAND_CLASS_ERROR )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ( CurrentWorkingPacket - > Command  = =  COMMAND_ERROR_DEVICE_DISCONNECTED ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Upstream_ReleasePacket ( CurrentWorkingPacket ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ReceivePacketCallback  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Upstream_StateMachine_DeviceDisconnected ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ( ( CurrentWorkingPacket - > CommandClass  &  COMMAND_CLASS_MASK )  ! =  ( SentCommandClass  &  COMMAND_CLASS_MASK ) )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ( CurrentWorkingPacket - > Command  ! =  SentCommand ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Upstream_ReleasePacket ( CurrentWorkingPacket ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            CurrentWorkingPacket  =  NULL ;         //Call back with a NULL packet to indicate error
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //USB interface may want to receive another packet immediately,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //so clear ReceivePacketCallback before the call.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //It is the callback's responsibility to release the packet buffer we are passing to it!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        tempPacketCallback  =  ReceivePacketCallback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ReceivePacketCallback  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        tempPacketCallback ( CurrentWorkingPacket ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //case default:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Used by USB interface classes.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Ok to call when idle or transmitting.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Not OK to call when receiving or waiting for downstream reply.
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								HAL_StatusTypeDef  Upstream_ReceivePacket ( SpiPacketReceivedCallbackTypeDef  callback ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  > =  UPSTREAM_INTERFACE_ERROR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ReceivePacketCallback  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ReceivePacketCallback  =  callback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  Upstream_CheckBeginPacketReception ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Internal use only.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								HAL_StatusTypeDef  Upstream_CheckBeginPacketReception ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  > =  UPSTREAM_INTERFACE_ERROR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  > =  UPSTREAM_INTERFACE_RX_SIZE_WAIT ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  HAL_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  = =  UPSTREAM_INTERFACE_IDLE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UpstreamInterfaceState  =  UPSTREAM_INTERFACE_RX_SIZE_WAIT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( TxOkInterruptReceived ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            TxOkInterruptReceived  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Upstream_GetFreePacket ( Upstream_BeginReceivePacketSize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  HAL_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//This is called by EXTI3 falling edge interrupt,
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								//indicating that downstream is ready for the next transaction.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  Upstream_TxOkInterrupt ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  > =  UPSTREAM_INTERFACE_ERROR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( UpstreamInterfaceState ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  UPSTREAM_INTERFACE_IDLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        TxOkInterruptReceived  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  UPSTREAM_INTERFACE_TX_SIZE_WAIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Upstream_BeginTransmitPacketSize ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  UPSTREAM_INTERFACE_TX_PACKET_WAIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Upstream_BeginTransmitPacketBody ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  UPSTREAM_INTERFACE_RX_SIZE_WAIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Upstream_GetFreePacket ( Upstream_BeginReceivePacketSize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  UPSTREAM_INTERFACE_RX_PACKET_WAIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Upstream_BeginReceivePacketBody ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  Upstream_BeginTransmitPacketSize ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    UpstreamInterfaceState  =  UPSTREAM_INTERFACE_TX_SIZE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    SPI1_NSS_ASSERT ; 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( HAL_SPI_TransmitReceive ( & Hspi1 , 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                    ( uint8_t * ) & CurrentWorkingPacket - > Length16 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    ( uint8_t * ) & TemporaryIncomingPacketLength , 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                    2 ,                                   //We only need to write one word, but the peripheral library freaks out...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    SPI_TIMEOUT_VALUE )  ! =  HAL_OK ) 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    HAL_SPI_TxRxCpltCallback ( & Hspi1 ) ; 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  Upstream_BeginTransmitPacketBody ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    UpstreamInterfaceState  =  UPSTREAM_INTERFACE_TX_PACKET ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    SPI1_NSS_ASSERT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( HAL_SPI_TransmitReceive_DMA ( & Hspi1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    & CurrentWorkingPacket - > CommandClass , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    & CurrentWorkingPacket - > CommandClass , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    ( ( CurrentWorkingPacket - > Length16  <  2 )  ?  2  :  CurrentWorkingPacket - > Length16 ) )  ! =  HAL_OK ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Internal use only.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Called when we want to receive downstream packet, and a packet buffer has become free.
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  Upstream_BeginReceivePacketSize ( UpstreamPacketTypeDef *  freePacket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  > =  UPSTREAM_INTERFACE_ERROR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  ! =  UPSTREAM_INTERFACE_RX_SIZE_WAIT ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    UpstreamInterfaceState  =  UPSTREAM_INTERFACE_RX_SIZE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CurrentWorkingPacket  =  freePacket ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CurrentWorkingPacket - > Length16  =  0 ;      //Our RX buffer is used by HAL_SPI_TransmitReceive_DMA as dummy TX data, we set Length to 0 so downstream will know this is a dummy packet.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    SPI1_NSS_ASSERT ; 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( HAL_SPI_TransmitReceive ( & Hspi1 , 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                    ( uint8_t * ) & CurrentWorkingPacket - > Length16 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    ( uint8_t * ) & CurrentWorkingPacket - > Length16 , 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                    2 ,                                      //We only need to write one word, but the peripheral library freaks out...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    SPI_TIMEOUT_VALUE )  ! =  HAL_OK ) 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    HAL_SPI_TxRxCpltCallback ( & Hspi1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  Upstream_BeginReceivePacketBody ( void ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    UpstreamInterfaceState  =  UPSTREAM_INTERFACE_RX_PACKET ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    SPI1_NSS_ASSERT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( HAL_SPI_TransmitReceive_DMA ( & Hspi1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    & CurrentWorkingPacket - > CommandClass , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    & CurrentWorkingPacket - > CommandClass , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    ( ( CurrentWorkingPacket - > Length16  <  2 )  ?  2  :  CurrentWorkingPacket - > Length16 ) )  ! =  HAL_OK ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Something bad happened! Possibly CRC error...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  HAL_SPI_ErrorCallback ( SPI_HandleTypeDef  * hspi ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    UNUSED ( hspi ) ; 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    SpiPacketReceivedCallbackTypeDef  tempPacketCallback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( UpstreamInterfaceState  > =  UPSTREAM_INTERFACE_ERROR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    UPSTREAM_SPI_FREAKOUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ReceivePacketCallback  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        tempPacketCallback  =  ReceivePacketCallback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ReceivePacketCallback  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        tempPacketCallback ( NULL ) ;            //Call back with a NULL packet to indicate error
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}