#ifndef _USB_H_
#define _USB_H_
#include "Type.h"
#include <MC9S08JM60.h> 

//设备版本号
#define USB_DRIVER_VERSION  0x0004

//发送和接受端点
#define USB_RX_EP_NO  3u
#define USB_TX_EP_NO  2u

/******************************************************************************
 ************************ Macro definitions ***********************************
 *****************************************************************************/
#define DIR_TX             BIT7
#define MIN(a,b)     ((a) < (b) ? (a) : (b))

/* Packet identifier values. */
#define SOF_PID_VALUE		    0xd
#define DATA_PID_VALUE      0x3
#define DATA0_PID_VALUE     0x3
#define DATA1_PID_VALUE     0xb

/* Control endpoint state machine state values. */
#define EPST_IDLE             0x0
#define EPST_DATA_TX          0x1
#define EPST_DATA_TX_LAST     0x2
#define EPST_DATA_RX          0x3
#define EPST_STATUS_TX        0x4
#define EPST_STATUS_RX        0x5
#define EPST_TX_STOP          0x6
#define EPST_ABORT_TX         0x7
#define EPST_DATA_TX_WAIT_DB  0x8
#define EPST_DATA_TX_EMPTY_DB 0x9

/* Configuration values for the CDC demo. */
#define USB_NO_OF_STRING_DESC  7u
#define CMD_IFC_INDEX          0u
#define DATA_IFC_INDEX         1u

#define EP0_PACKET_SIZE      8u
#define EP1_PACKET_SIZE     32u
#define EP2_PACKET_SIZE     64u
#define EP3_PACKET_SIZE     64u

/* Standard USB feature selector values. */
#define FEAT_ENDPOINT_HALT        0u
#define FEAT_DEVICE_REMOTE_WAKEUP 1u

/* Endpoint flag bits. */
#define EPFL_ERROR    (INT8U)BIT0  /* There was an error during the ongoing
                               transfer. */
#define EPFL_ZPACKET  (INT8U)BIT1  /* After the last data packet an additional zero
                               length packet needs to be transmitted to close
                               the transfer. */

//芯片USB模块支持的端点数
#define NO_OF_HW_EP     6

//BDT地址
#define BDT_BASE          0x1860u
#define BDT_CTRL(bndx)    (*(INT8U*)(BDT_BASE+(3*(bndx))+0))
#define BDT_LENGTH(bndx)  (*(INT8U*)(BDT_BASE+(3*(bndx))+1))
#define BDT_ADDR(bndx)    (*(INT8U*)(BDT_BASE+(3*(bndx))+2))

#define BDT_CTRL_OWN      (1u<<7)
#define BDT_CTRL_DATA01   (1u<<6)
#define BDT_CTRL_KEEP     (1u<<5)
#define BDT_CTRL_NINC     (1u<<4)
#define BDT_CTRL_DTS      (1u<<3)
#define BDT_CTRL_BDTSTALL (1u<<2)
#define BDT_CTRL_BDTKPID  (0xfu<<2)

#define BDT_END   0x20
#define EP_RAM_SIZE  256

/* This will give us array like access to EPCTL registers. */
#define EPCTL (&EPCTL0)

/* USB ram buffers must be 4 byte aligned. */
#define ALIGN_RAM_BUF(adr)  ((adr) & 0xf ? ((adr) & 0xf0)+0x10 : (adr))

/* This 16 bit counter is increased each mS while the USB is connected and not
   in sleep state. */
#define usb_get_frame_ctr() ((INT16U)((FRMNUMH<<8) | FRMNUML))

//访问USB的STEP域
#define STP_REQU_TYPE(a)	  (((INT8U*)(a))[0])
#define STP_REQUEST(a)      (((INT8U*)(a))[1])
#define STP_VALUE(a)        RD_LE16(((INT8U*)(a))+2)
#define STP_VALUE_LO(a)     (((INT8U*)(a))[2])
#define STP_VALUE_HI(a)     (((INT8U*)(a))[3])
#define STP_INDEX(a)        RD_LE16(((INT8U*)(a))+4)
#define STP_INDEX_LO(a)     (((INT8U*)(a))[4])
#define STP_INDEX_HI(a)     (((INT8U*)(a))[5])
#define STP_LENGTH(a)       RD_LE16(((INT8U*)(a))+6)
#define STP_LENGTH_LO(a)    (((INT8U*)(a))[6])
#define STP_LENGTH_HI(a)    (((INT8U*)(a))[7])


//标准的设备请求
#define USBRQ_GET_STATUS         0u
#define USBRQ_CLEAR_FEATURE      1u
#define USBRQ_SET_FEATURE        3u
#define USBRQ_SET_ADDRESS        5u
#define USBRQ_GET_DESCRIPTOR     6u
#define USBRQ_SET_DESCRIPTOR     7u
#define USBRQ_GET_CONFIGURATION  8u
#define USBRQ_SET_CONFIGURATION  9u
#define USBRQ_GET_INTERFACE      10u
#define USBRQ_SET_INTERFACE      11u
#define USBRQ_SYNCH_FRAME        12u

//标准的USB描述符
#define STDD_DEVICE         1u
#define STDD_CONFIG         2u
#define STDD_STRING         3u
#define STDD_INTERFACE      4u
#define STDD_ENDPOINT       5u

/* Endpoint type vaues. */
#define EP_TYPE_CONTROL 0u
#define EP_TYPE_ISO     1u
#define EP_TYPE_BULK    2u
#define EP_TYPE_IT      3u
#define EP_TYPE_DISABLE 4u

//设备状态
#define USBST_DISABLED    (1u<<0)
#define USBST_DEFAULT     (1u<<1) /* Only standard requests are handled on
                                     then default pipe. */
#define USBST_ADDRESSED   (1u<<2) /* USB has a unique address, but no
                                     configuration is active. */
#define USBST_CONFIGURED  (1u<<3) /* Device is configured, and fully
                                     functional. */

//usb_ep_error()返回的错误标志
#define USBEPERR_NONE             (0) /* No error. */
#define USBEPERR_TO_MANY_DATA     (BIT0) /* To many data received. */
#define USBEPERR_PROTOCOL_ERROR   (BIT1) /* Protocol error. */
#define USBEPERR_USER_ABORT       (BIT2) /* Transfer was aborted by the
                                             application. */
#define USBEPERR_HOST_ABORT       (BIT3) /* Host aborted the transfer. */

/* Values for the attrib field of the configuration descriptor. */
/* Devide ic BUS powered. */
#define CFGD_ATTR_BUS_PWR  (1u<<7)
/* Device is self powered. */
#define CFGD_ATTR_SELF_PWR (1u<<6)
/* Device can wake up the BUS. */
#define CFGD_ATTR_RWAKEUP  (1u<<5)

#ifdef NDEBUG
#define CMX_ASSERT(c) (void)0
#else
#define CMX_ASSERT(c)\
do {\
  if(!(c))\
  {\
    int a=1;\
    while(a)\
      ;\
  }\
}while(0)
#endif

#define BREW32(v)   ((INT32U)(((INT32U)(((INT32U)(v)) << 24)) \
                     | ((INT32U)(((INT32U)(v)) >> 24)) \
                     | (INT32U)((INT32U)((INT32U)(v) & (INT32U)0xff00ul) << 8)\
                     | (INT32U)((INT32U)((INT32U)(v) & (INT32U)0xff0000ul) >> 8)))
                     
#define BREW16(v)   ((INT16U)(((INT16U)(v)) << 8) | (INT16U)(((INT16U)(v)) >> 8))

#define WR_LE32(a, v) ((*(INT32U*)(a))=BREW32(v))
#define WR_LE16(a, v) ((*(INT16U*)(a))=BREW16(v))
#define RD_LE32(a)    (BREW32(*((INT32U*)(a))))
#define RD_LE16(a)    (BREW16(*((INT16U*)(a))))

/* Read 16 bit big endian value from address. */
#define RD_BE16(a) (*(INT16U*)(a))
/* Write 16bit value in v to address a in big endian order. */
#define WR_BE16(a, v) (*(INT16U*)(a) = (INT16U)(v))
/* Read 32 bit little endian value from address. */
#define RD_BE32(a) (*(INT32U*)(a))
/* Write 32bit value in v to address a in big endian order. */
#define WR_BE32(a, v) (*(INT32U*)(a) = (INT32U)(v))

#define BIT0 (1u<<0)
#define BIT1 (1u<<1)
#define BIT2 (1u<<2)
#define BIT3 (1u<<3)
#define BIT4 (1u<<4)
#define BIT5 (1u<<5)
#define BIT6 (1u<<6)
#define BIT7 (1u<<7)

/******************************************************************************
 ************************ Type definitions ************************************
 *****************************************************************************/
 
 typedef enum 
{
  usb_busy,       /* receiving data...*/
  usb_ready,      /* ready for next receive*/
  usb_unready,    /* not configured*/
} usb_state_t;

 /* Return values for callback functions. */
typedef enum 
{
  clbst_ok,       /* Callback executed ok. */
  clbst_in,       /* Start IN transfer. */
  clbst_out,      /* Start out transfer. */
  clbst_error,    /* Error encountered, stop endpoint. */
  clbst_not_ready /* No buffer avaiable, pause endpoint. */
} callback_state_t;  

typedef callback_state_t (*usb_callback_t)(void);

typedef struct 
{
  volatile INT32U tlength;
  volatile INT32U maxlength;
  void * volatile address;
  volatile usb_callback_t data_func;
  INT16U psize;
  volatile INT8U state;
  volatile INT8U flags;
  volatile INT8U error;
  volatile INT8U data0;      /* Data toggle bit for endpoint. */
} ep_info_t;

INT8U USBInit(void); //USB initialize
INT8U USBReceiveData(INT8U ep,INT8U* data); //USB Receive data ,max length = 63
void  USBSendData(INT8U ep,INT8U* data,INT8U length);//USB Send Data ,max length = 63

typedef INT8U hcc_imask;

/*****************************************************************************
 * Function predefinitions.
 *****************************************************************************/
INT8U USBInit(void);
void USBStop(void);
void USBInterrupt(void);
void USBSend(INT8U ep, usb_callback_t f, INT8U* data, INT32U tr_length, INT32U req_length);
INT8U USBReceive(INT8U ep,INT8U* data, INT32U tr_length);

/******************************************************************************
 ************************ Imported functions **********************************
 *****************************************************************************/
void usb_cfg_init(void);
INT8U usb_ep_is_busy(INT8U ep);
INT32U usb_get_done(INT8U ep);
INT8U usb_get_state(void);
INT8U *USBGetRxBDTAddr(INT8U ep); //端点刚接收到数据的缓冲区地址
void usb_stop_ep_rx(INT8U ep);
void usb_stop_ep_tx(INT8U ep);

/* Event callbacks. */
void USBBusErrorEvent(void);
void USBWakeupEvent(void);
void USBSuspendEvent(void);
void USBResetEvent(void);
callback_state_t usb_ep0_callback(void);

void* GetDeviceDescriptor(void);
void *GetCfgDescriptor(INT8U cndx);
void *GetStrDescriptor(INT8U sndx);
void *GetEpDescriptor(INT8U cndx, INT8U indx, INT8U iset, INT8U endx);
INT8U is_cfgd_index(INT16U cndx);
INT8U is_str_index(INT8U sndx);
INT8U is_ifc_ndx(INT8U cndx, INT8U indx, INT8U iset);
INT8U is_ep_ndx(INT8U cndx, INT8U indx, INT8U iset, INT8U endx);

static void EnterDefaultState(void);
static void ready_ep_rx(INT8U, INT8U);
static void ready_ep_tx(INT8U, INT8U);
static void send_zero_packet(INT8U ep);
static void _usb_send(INT8U ep);
static void _usb_receive(INT8U ep);
static callback_state_t USBDecodeSetup(void);//解SETUP包
static INT8U USBSetupEp(INT8U addr, INT8U type, INT8U ep, INT16U psize);
static void USBSetConfig(INT8U cfg_ndx);
  
void _irq_restore (hcc_imask ip);
hcc_imask _irq_disable (void);
#endif
/****************************** END OF FILE **********************************/
