@@ -56,7 +56,7 @@
 
		
	
		
			
				//--------------------------------------------------------------------+  
		
	
		
			
				// MACRO CONSTANT TYPEDEF  
		
	
		
			
				//--------------------------------------------------------------------+  
		
	
		
			
				# define DCD_LPC13XX_QHD  10  
		
	
		
			
				# define DCD_11U_13U_QHD_COUNT  10  
		
	
		
			
				 
		
	
		
			
				enum  {  
		
	
		
			
				  INT_MASK_SOF            =  BIT_ ( 30 ) , 
 
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -98,9 +98,9 @@ typedef struct {
 
		
	
		
			
				    } bits ; 
 
		
	
		
			
				    uint32_t  value ; 
 
		
	
		
			
				  } ; 
 
		
	
		
			
				}  lpc13xx _dev_cmd_stat;  
		
	
		
			
				}  reg _dev_cmd_stat_t ;  
		
	
		
			
				 
		
	
		
			
				STATIC_ASSERT (  sizeof ( lpc13xx _dev_cmd_stat)  = =  4 ,  " size is not correct "  ) ;  
		
	
		
			
				STATIC_ASSERT (  sizeof ( reg _dev_cmd_stat_t )  = =  4 ,  " size is not correct "  ) ;  
		
	
		
			
				 
		
	
		
			
				 
		
	
		
			
				// buffer input must be 64 byte alignment  
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -114,26 +114,26 @@ typedef struct {
 
		
	
		
			
				uint16_t  stall                 :  1   ;  ///< 0: The selected endpoint is not stalled 1: The selected endpoint is stalled The Active bit has always higher priority than the Stall bit. This means that a Stall handshake is only sent when the active bit is zero and the stall bit is one. Software can only modify this bit when the active bit is zero.  
		
	
		
			
				uint16_t  disable               :  1   ;  ///< 0: The selected endpoint is enabled. 1: The selected endpoint is disabled. If a USB token is received for an endpoint that has the disabled bit set, hardware will ignore the token and not return any data or handshake. When a bus reset is received, software must set the disable bit of all endpoints to 1. Software can only modify this bit when the active bit is zero.  
		
	
		
			
				volatile  uint16_t  active       :  1   ;  ///< The buffer is enabled. HW can use the buffer to store received OUT data or to transmit data on the IN endpoint. Software can only set this bit to ‘ ’   
		
	
		
			
				} dcd_lpc13xx _qhd_t ;  
		
	
		
			
				} dcd_11u_13u _qhd_t ;  
		
	
		
			
				 
		
	
		
			
				STATIC_ASSERT (  sizeof ( dcd_lpc13xx _qhd_t )  = =  4 ,  " size is not correct "  ) ;  
		
	
		
			
				STATIC_ASSERT (  sizeof ( dcd_11u_13u _qhd_t )  = =  4 ,  " size is not correct "  ) ;  
		
	
		
			
				 
		
	
		
			
				typedef  struct  {  
		
	
		
			
				  dcd_lpc13xx _qhd_t  qhd [ DCD_LPC13XX_QHD  ] [ 2 ] ;  ///< must be 256 byte alignment, 2 for double buffer 
 
		
	
		
			
				  dcd_11u_13u _qhd_t  qhd [ DCD_11U_13U_QHD_COUNT  ] [ 2 ] ;  ///< must be 256 byte alignment, 2 for double buffer 
 
		
	
		
			
				 
		
	
		
			
				  uint16_t  expected_bytes [ DCD_LPC13XX_QHD  ] ;  ///< expected bytes of the queued transfer 
 
		
	
		
			
				uint8_t   class_code [ DCD_LPC13XX_QHD  ] ;  // class where the endpoints belongs to TODO no need for control endpoints  
		
	
		
			
				  uint16_t  expected_bytes [ DCD_11U_13U_QHD_COUNT  ] ;  ///< expected bytes of the queued transfer 
 
		
	
		
			
				uint8_t   class_code [ DCD_11U_13U_QHD_COUNT  ] ;  // class where the endpoints belongs to TODO no need for control endpoints  
		
	
		
			
				// there is padding from 80 --> 128 = 48 bytes  
		
	
		
			
				 
		
	
		
			
				  // should start from 128 
 
		
	
		
			
				ATTR_ALIGNED ( 64 )  tusb_control_request_t  setup_request ;  
		
	
		
			
				 
		
	
		
			
				} dcd_lpc13xx _data_t ;  
		
	
		
			
				} dcd_11u_13u _data_t ;  
		
	
		
			
				 
		
	
		
			
				//--------------------------------------------------------------------+  
		
	
		
			
				// INTERNAL OBJECT & FUNCTION DECLARATION  
		
	
		
			
				//--------------------------------------------------------------------+  
		
	
		
			
				ATTR_ALIGNED ( 256 )  static  dcd_lpc13xx _data_t  dcd_data  TUSB_CFG_ATTR_USBRAM ;  
		
	
		
			
				ATTR_ALIGNED ( 256 )  static  dcd_11u_13u _data_t  dcd_data  TUSB_CFG_ATTR_USBRAM ;  
		
	
		
			
				 
		
	
		
			
				static  inline  uint16_t  addr_offset ( void  const  *  p_buffer )  ATTR_CONST  ATTR_ALWAYS_INLINE ;  
		
	
		
			
				static  inline  uint16_t  addr_offset ( void  const  *  p_buffer )  
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -151,7 +151,7 @@ void dcd_controller_connect(uint8_t coreid)
 
		
	
		
			
				  LPC_USB - > DEVCMDSTAT  | =  CMDSTAT_MASK_CMD_CONNECT ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				void  dcd_controller_set_configuration ( uint8_t  coreid ,  uint8_t  config_num  
		
	
		
			
				void  dcd_controller_set_configuration ( uint8_t  coreid )  
		
	
		
			
				{  
		
	
		
			
				 
		
	
		
			
				}  
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -168,7 +168,6 @@ tusb_error_t dcd_init(void)
 
		
	
		
			
				{  
		
	
		
			
				  LPC_USB - > EPLISTSTART   =  ( uint32_t )  dcd_data . qhd ; 
 
		
	
		
			
				  LPC_USB - > DATABUFSTART  =  0x20000000 ;  // only SRAM1 & USB RAM can be used for transfer 
 
		
	
		
			
				LPC_USB - > EPBUFCFG      =  0 ;  // TODO double buffering  
		
	
		
			
				 
		
	
		
			
				  LPC_USB - > INTSTAT       =  LPC_USB - > INTSTAT ;  // clear all pending interrupt 
 
		
	
		
			
				LPC_USB - > INTEN         =  INT_MASK_DEVICE_STATUS ;  
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -179,8 +178,8 @@ tusb_error_t dcd_init(void)
 
		
	
		
			
				 
		
	
		
			
				static  void  bus_reset ( void )  
		
	
		
			
				{  
		
	
		
			
				  memclr_ ( & dcd_data ,  sizeof ( dcd_lpc13xx _data_t ) ) ; 
 
		
	
		
			
				  for ( uint8_t  ep_id  =  2 ;  ep_id  <  DCD_LPC13XX_QHD  ;  ep_id + + ) 
 
		
	
		
			
				  memclr_ ( & dcd_data ,  sizeof ( dcd_11u_13u _data_t ) ) ; 
 
		
	
		
			
				  for ( uint8_t  ep_id  =  2 ;  ep_id  <  DCD_11U_13U_QHD_COUNT  ;  ep_id + + ) 
 
		
	
		
			
				  {  // disable all non-control endpoints on bus reset 
 
		
	
		
			
				dcd_data . qhd [ ep_id ] [ 0 ] . disable  =  dcd_data . qhd [ ep_id ] [ 1 ] . disable  =  1 ;  
		
	
		
			
				  } 
 
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -188,6 +187,7 @@ static void bus_reset(void)
 
		
	
		
			
				  dcd_data . qhd [ 0 ] [ 1 ] . buff_addr_offset  =  addr_offset ( & dcd_data . setup_request ) ; 
 
		
	
		
			
				 
		
	
		
			
				  LPC_USB - > EPINUSE       =  0 ; 
 
		
	
		
			
				  LPC_USB - > EPBUFCFG      =  0 ;  // all start with single buffer 
 
		
	
		
			
				LPC_USB - > EPSKIP        =  0xFFFFFFFF ;  
		
	
		
			
				 
		
	
		
			
				  LPC_USB - > INTSTAT       =  LPC_USB - > INTSTAT ;  // clear all pending interrupt 
 
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -245,20 +245,29 @@ void dcd_isr(uint8_t coreid)
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  //------------- Non-Control Endpoints -------------// 
 
		
	
		
			
				for ( uint8_t  ep_id  =  2 ;  ep_id  <  DCD_LPC13XX_QHD  ;  ep_id + +  )  
		
	
		
			
				for ( uint8_t  ep_id  =  2 ;  ep_id  <  DCD_11U_13U_QHD_COUNT  ;  ep_id + +  )  
		
	
		
			
				  { 
 
		
	
		
			
				    if  (  BIT_TEST_ ( int_status ,  ep_id )  ) 
 
		
	
		
			
				    { 
 
		
	
		
			
				      endpoint_handle_t  edpt_hdl  = 
 
		
	
		
			
				      // Ignore if interrupt caused by buffer0 while we only have "Interrupt On Complete" with buffer1 
 
		
	
		
			
				// usbd/class driver under no situations to set "Interrupt On Complete" on both buffers  
		
	
		
			
				// Single Buffering and (Double with completed on buffer1) is valid  
		
	
		
			
				if  (  ! BIT_TEST_ ( LPC_USB - > EPBUFCFG ,  ep_id )  | |  ! BIT_TEST_ ( LPC_USB - > EPINUSE ,  ep_id )  )  
		
	
		
			
				      { 
 
		
	
		
			
				          . coreid      =  coreid ,  
 
		
	
		
			
				          . index       =  ep_id ,  
 
		
	
		
			
				          . class_code  =  dcd_data . class_code [ ep_ id ] 
 
		
	
		
			
				      } ; 
 
		
	
		
			
				        endpoint_handle_t  edpt_hdl  = 
 
		
	
		
			
				        { 
 
		
	
		
			
				             . coreid      =  core id , 
 
		
	
		
			
				             . index       =  ep_id ,  
		
	
		
			
				            . class_code  =  dcd_data . class_code [ ep_id ] 
 
		
	
		
			
				        } ; 
 
		
	
		
			
				 
		
	
		
			
				      // TODO no way determine if the transfer is failed or not 
 
		
	
		
			
				usbd_xfer_isr ( edpt_hdl ,  TUSB_EVENT_XFER_COMPLETE ,  
		
	
		
			
				                    dcd_data . expected_bytes [ ep_id ]  -  dcd_data . qhd [ ep_id ] [ 0 ] . total_bytes ) ;  // only number of bytes in the IOC qtd   
		
	
		
			
				        LPC_USB - > INTEN     =  BIT_CLR_ ( LPC_USB - > INTEN     ,  ep_id ) ;  // clear interrupt on completion  
 
		
	
		
			
				  LPC_USB - > EPBUFCFG  =  BIT_CLR_ ( LPC_USB - > EPBUFCFG  ,  ep_id ) ;  // clear double buffering   
		
	
		
			
				 
		
	
		
			
				        // TODO no way determine if the transfer is failed or not 
 
		
	
		
			
				usbd_xfer_isr ( edpt_hdl ,  TUSB_EVENT_XFER_COMPLETE ,  
		
	
		
			
				                      dcd_data . expected_bytes [ ep_id ]  -  dcd_data . qhd [ ep_id ] [ 0 ] . total_bytes ) ;  // only number of bytes in the IOC qtd 
 
		
	
		
			
				}  
		
	
		
			
				    } 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -309,11 +318,11 @@ tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void *
 
		
	
		
			
				//  return (pos < DCD_QHD_MAX/2) ? (2*pos) : (2*(pos-16)+1);  
		
	
		
			
				//}  
		
	
		
			
				 
		
	
		
			
				( )  ;  
		
	
		
			
				( )  
		
	
		
			
				{  
		
	
		
			
				  / 2  +  (  ( physical_endpoint % 2 )  ?  16  :  0 ) ; 
 
		
	
		
			
				}  
		
	
		
			
				// static  inline  uint8_t  edpt_phy2pos( uint8_t  physical_endpoint)  ATTR_CONST  ATTR_ALWAYS_INLINE;  
		
	
		
			
				// static  inline  uint8_t  edpt_phy2pos( uint8_t  physical_endpoint)  
		
	
		
			
				//{  
		
	
		
			
				//   return  physical_endpoint/2 + ( (physical_endpoint%2) ? 16 : 0);  
		
	
		
			
				//}  
		
	
		
			
				 
		
	
		
			
				static  inline  uint8_t  edpt_addr2phy ( uint8_t  endpoint_addr )  ATTR_CONST  ATTR_ALWAYS_INLINE ;  
		
	
		
			
				static  inline  uint8_t  edpt_addr2phy ( uint8_t  endpoint_addr )  
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -334,7 +343,7 @@ tusb_error_t dcd_pipe_stall(endpoint_handle_t edpt_hdl)
 
		
	
		
			
				{  
		
	
		
			
				  ASSERT (  ! dcd_pipe_is_busy ( edpt_hdl ) ,  TUSB_ERROR_INTERFACE_IS_BUSY ) ;  // endpoint must not in transferring 
 
		
	
		
			
				 
		
	
		
			
				  dcd_data . qhd [ edpt_hdl . index ] [ 0 ] . stall  =  1 ; 
 
		
	
		
			
				  dcd_data . qhd [ edpt_hdl . index ] [ 0 ] . stall  =  dcd_data . qhd [ edpt_hdl . index ] [ 1 ] . stall  =   1 ; 
 
		
	
		
			
				 
		
	
		
			
				  return  TUSB_ERROR_NONE ; 
 
		
	
		
			
				}  
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -342,10 +351,12 @@ tusb_error_t dcd_pipe_stall(endpoint_handle_t edpt_hdl)
 
		
	
		
			
				tusb_error_t  dcd_pipe_clear_stall ( uint8_t  coreid ,  uint8_t  edpt_addr )  
		
	
		
			
				{  
		
	
		
			
				  uint8_t  ep_id  =  edpt_addr2phy ( edpt_addr ) ; 
 
		
	
		
			
				  uint8_t  active_buffer  =  BIT_TEST_ ( LPC_USB - > EPINUSE ,  ep_id )  ?  1  :  0 ; 
 
		
	
		
			
				 
		
	
		
			
				  dcd_data . qhd [ ep_id ] [ 0 ] . stall             =  0 ; 
 
		
	
		
			
				  dcd_data . qhd [ ep_id ] [ 0 ] . toggle_reset     =  1 ; 
 
		
	
		
			
				  dcd_data . qhd [ ep_id ] [ 0 ] . feedback_toggle =  0 ; 
 
		
	
		
			
				  dcd_data . qhd [ ep_id ] [ 0 ] . stall  =  dcd_data . qhd [ ep_id ] [ 1 ] . stall =  0 ; 
 
		
	
		
			
				 
		
	
		
			
				  dcd_data . qhd [ ep_id ] [ active_buffer ] . toggle_reset    =  1 ; 
 
		
	
		
			
				  dcd_data . qhd [ ep_id ] [ active_buffer ] . feedback_toggle  =  0 ; 
 
		
	
		
			
				 
		
	
		
			
				  return  TUSB_ERROR_NONE ; 
 
		
	
		
			
				}  
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -362,10 +373,10 @@ endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const
 
		
	
		
			
				  //------------- Prepare Queue Head -------------// 
 
		
	
		
			
				uint8_t  ep_id  =  edpt_addr2phy ( p_endpoint_desc - > bEndpointAddress ) ;  
		
	
		
			
				 
		
	
		
			
				  ASSERT (  dcd_data . qhd [ ep_id ] [ 0 ] . disable ,  null_handle  ) ;  // endpoint must not previously opened 
 
		
	
		
			
				  ASSERT (  dcd_data . qhd [ ep_id ] [ 0 ] . disable  & &  dcd_data . qhd [ ep_id ] [ 1 ] . disable  ,  null_handle  ) ;  // endpoint must not previously opened 
 
		
	
		
			
				 
		
	
		
			
				  memclr_ ( dcd_data . qhd [ ep_id ] ,  2 * sizeof ( dcd_lpc13xx _qhd_t ) ) ; 
 
		
	
		
			
				  dcd_data . qhd [ ep_id ] [ 0 ] . is_isochronous  =  ( p_endpoint_desc - > bmAttributes . xfer  = =  TUSB_XFER_ISOCHRONOUS ) ; 
 
		
	
		
			
				  memclr_ ( dcd_data . qhd [ ep_id ] ,  2 * sizeof ( dcd_11u_13u _qhd_t ) ) ; 
 
		
	
		
			
				  dcd_data . qhd [ ep_id ] [ 0 ] . is_isochronous  =  dcd_data . qhd [ ep_id ] [ 1 ] . is_isochronous  =   ( p_endpoint_desc - > bmAttributes . xfer  = =  TUSB_XFER_ISOCHRONOUS ) ; 
 
		
	
		
			
				  dcd_data . class_code [ ep_id ]  =  class_code ; 
 
		
	
		
			
				 
		
	
		
			
				  dcd_data . qhd [ ep_id ] [ 0 ] . disable  =  dcd_data . qhd [ ep_id ] [ 1 ] . disable  =  0 ; 
 
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -380,7 +391,7 @@ endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const
 
		
	
		
			
				 
		
	
		
			
				bool  dcd_pipe_is_busy ( endpoint_handle_t  edpt_hdl )  
		
	
		
			
				{  
		
	
		
			
				  return  dcd_data . qhd [ edpt_hdl . index ] [ 0 ] . active ; 
 
		
	
		
			
				  return  dcd_data . qhd [ edpt_hdl . index ] [ 0 ] . active  | |  dcd_data . qhd [ edpt_hdl . index ] [ 1 ] . active  ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				//// add only, controller virtually cannot know  
		
	
	
		
			
				
					
					
						
					 
				
			
			@@ -391,28 +402,43 @@ bool dcd_pipe_is_busy(endpoint_handle_t edpt_hdl)
 
		
	
		
			
				//  return TUSB_ERROR_NONE;  
		
	
		
			
				//}  
		
	
		
			
				 
		
	
		
			
				// tusb_error_t  dcd_pipe_queue_xfer( endpoint_handle_t  edpt_hdl, void * buffer,  uint16_t  total_bytes)  
		
	
		
			
				//{  
		
	
		
			
				//  
		
	
		
			
				//}  
		
	
		
			
				 
		
	
		
			
				tusb_error_t   dcd_pipe_xfer ( endpoint_handle_t  edpt_hdl ,  void *  buffer ,  uint16_t  total_bytes ,  bool  int_on_complete )  
		
	
		
			
				( ,  void  *  buffer ,  )  
		
	
		
			
				{  
		
	
		
			
				  ASSERT (  ! dcd_pipe_is_busy ( edpt_hdl ) ,  TUSB_ERROR_INTERFACE_IS_BUSY ) ;  // endpoint must not in transferring 
 
		
	
		
			
				 
		
	
		
			
				  if  ( int_on_complete ) 
 
		
	
		
			
				  { 
 
		
	
		
			
				    LPC_USB - > INTEN  =  BIT_SET_ ( LPC_USB - > INTEN ,  edpt_hdl . index ) ; 
 
		
	
		
			
				  } else 
 
		
	
		
			
				  { 
 
		
	
		
			
				    LPC_USB - > INTEN  =  BIT_CLR_ ( LPC_USB - > INTEN ,  edpt_hdl . index ) ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  dcd_data . qhd [ edpt_hdl . index ] [ 0 ] . buff_addr_offset  =  addr_offset ( buffer ) ; 
 
		
	
		
			
				  dcd_data . qhd [ edpt_hdl . index ] [ 0 ] . total_bytes       =  total_bytes ; 
 
		
	
		
			
				  dcd_data . expected_bytes [ edpt_hdl . index ]           =  total_bytes ; 
 
		
	
		
			
				 
		
	
		
			
				  dcd_data . qhd [ edpt_hdl . index ] [ 0 ] . active            =  1 ; 
 
		
	
		
			
				  LPC_USB - > EPBUFCFG  =  BIT_SET_ ( LPC_USB - > EPBUFCFG ,  edpt_hdl . index ) ;  // queue xfer requires double buffering 
 
		
	
		
			
				 
		
	
		
			
				  return  TUSB_ERROR_NONE ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				tusb_error_t   dcd_pipe_xfer ( endpoint_handle_t  edpt_hdl ,  void *  buffer ,  uint16_t  total_bytes ,  bool  int_on_complete )  
		
	
		
			
				{  
		
	
		
			
				  ASSERT (  ! dcd_pipe_is_busy ( edpt_hdl ) ,  TUSB_ERROR_INTERFACE_IS_BUSY ) ;  // endpoint must not in transferring 
 
		
	
		
			
				 
		
	
		
			
				 
		
	
		
			
				  // In case both Buffers (0 & 1) have xfer and only buffer1 has int_on_complete, enable interrupt will also cause buffer0's 
 
		
	
		
			
				// xfer completion assert interrupt. This is unintentional side effect, and only can be handled in dcd_isr  
		
	
		
			
				LPC_USB - > INTEN    =  int_on_complete  ?  BIT_SET_ ( LPC_USB - > INTEN ,  edpt_hdl . index )  :  BIT_CLR_ ( LPC_USB - > INTEN ,  edpt_hdl . index ) ;  
		
	
		
			
				 
		
	
		
			
				  // double buffering means there is another xfer has been queued in buffer0 
 
		
	
		
			
				uint8_t  buff_idx  =  BIT_TEST_ ( LPC_USB - > EPBUFCFG ,  edpt_hdl . index )  ?  1  :  0 ;  
		
	
		
			
				 
		
	
		
			
				  dcd_data . qhd [ edpt_hdl . index ] [ buff_idx ] . buff_addr_offset  =  addr_offset ( buffer ) ; 
 
		
	
		
			
				  dcd_data . qhd [ edpt_hdl . index ] [ buff_idx ] . total_bytes       =  total_bytes ; 
 
		
	
		
			
				  dcd_data . expected_bytes [ edpt_hdl . index ]                  =  total_bytes ;  // TODO currently only calculate xferred bytes on IOC one 
 
		
	
		
			
				 
		
	
		
			
				  if  ( buff_idx ) 
 
		
	
		
			
				  { 
 
		
	
		
			
				    LPC_USB - > EPINUSE  =  BIT_CLR_ ( LPC_USB - > EPINUSE ,  edpt_hdl . index ) ;  // force HW to use buffer0 
 
		
	
		
			
				dcd_data . qhd [ edpt_hdl . index ] [ 1 ] . active  =  1 ;  
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  dcd_data . qhd [ edpt_hdl . index ] [ 0 ] . active  =  1 ;  // buffer0 always has queued xfer 
 
		
	
		
			
				 
		
	
		
			
				 
		
	
		
			
					return  TUSB_ERROR_NONE ; 
 
		
	
		
			
				}