/*
**************************************************************************************************************
*                                         INITIALIZE THE HOST CONTROLLER
*
* Description: This function initializes lpc17xx host controller
*
* Arguments  : None
*
* Returns    : 
*
**************************************************************************************************************
*/
void  Host_Init (void)
{
    PRINT_Log("In Host_Init\n");
    NVIC_DisableIRQ(USB_IRQn);                           /* Disable the USB interrupt source           */
    
    // turn on power for USB
    LPC_SC->PCONP       |= (1UL<<31);
    // Enable USB host clock, port selection and AHB clock
    LPC_USB->USBClkCtrl |= CLOCK_MASK;
    // Wait for clocks to become available
    while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
        ;
    
    // it seems the bits[0:1] mean the following
    // 0: U1=device, U2=host
    // 1: U1=host, U2=host
    // 2: reserved
    // 3: U1=host, U2=device
    // NB: this register is only available if OTG clock (aka "port select") is enabled!!
    // since we don't care about port 2, set just bit 0 to 1 (U1=host)
    LPC_USB->OTGStCtrl |= 1;
    
    // now that we've configured the ports, we can turn off the portsel clock
    LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;
    
    // power pins are not connected on mbed, so we can skip them
    /* P1[18] = USB_UP_LED, 01 */
    /* P1[19] = /USB_PPWR,     10 */
    /* P1[22] = USB_PWRD, 10 */
    /* P1[27] = /USB_OVRCR, 10 */
    /*LPC_PINCON->PINSEL3 &= ~((3<<4) | (3<<6) | (3<<12) | (3<<22));  
    LPC_PINCON->PINSEL3 |=  ((1<<4)|(2<<6) | (2<<12) | (2<<22));   // 0x00802080
    */

    // configure USB D+/D- pins
    /* P0[29] = USB_D+, 01 */
    /* P0[30] = USB_D-, 01 */
    LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));  
    LPC_PINCON->PINSEL1 |=  ((1<<26)|(1<<28));     // 0x14000000
        
    PRINT_Log("Initializing Host Stack\n");

    Hcca       = (volatile  HCCA       *)(HostBuf+0x000);
    TDHead     = (volatile  HCTD       *)(HostBuf+0x100);
    TDTail     = (volatile  HCTD       *)(HostBuf+0x110);
    EDCtrl     = (volatile  HCED       *)(HostBuf+0x120); 
    EDBulkIn   = (volatile  HCED       *)(HostBuf+0x130);
    EDBulkOut  = (volatile  HCED       *)(HostBuf+0x140);
    TDBuffer   = (volatile  USB_INT08U *)(HostBuf+0x150);
    
    /* Initialize all the TDs, EDs and HCCA to 0  */
    Host_EDInit(EDCtrl);
    Host_EDInit(EDBulkIn);
    Host_EDInit(EDBulkOut);
    Host_TDInit(TDHead);
    Host_TDInit(TDTail);
    Host_HCCAInit(Hcca);
    
    Host_DelayMS(50);                                   /* Wait 50 ms before apply reset              */
    LPC_USB->HcControl       = 0;                       /* HARDWARE RESET                             */
    LPC_USB->HcControlHeadED = 0;                       /* Initialize Control list head to Zero       */
    LPC_USB->HcBulkHeadED    = 0;                       /* Initialize Bulk list head to Zero          */
    
                                                        /* SOFTWARE RESET                             */
    LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
    LPC_USB->HcFmInterval    = DEFAULT_FMINTERVAL;      /* Write Fm Interval and Largest Data Packet Counter */

                                                        /* Put HC in operational state                */
    LPC_USB->HcControl  = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
    LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC;            /* Set Global Power                           */
    
    LPC_USB->HcHCCA = (USB_INT32U)Hcca;
    LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;                   /* Clear Interrrupt Status                    */


    LPC_USB->HcInterruptEnable  = OR_INTR_ENABLE_MIE |
                         OR_INTR_ENABLE_WDH |
                         OR_INTR_ENABLE_RHSC;

    NVIC_SetPriority(USB_IRQn, 0);       /* highest priority */

    /* Enable the USB Interrupt */
    NVIC_EnableIRQ(USB_IRQn);
    PRINT_Log("Host Initialized\n");
}
void  Host_Init (void)
{
    USB_INT32U  pinsel;

    PCONP         |= 0x80000000;
    VICIntEnClr    = (1 << 22);                               /* Enable the USB interrupt source            */
		OTG_CLK_CTRL = 0x00000009;
	while ((OTG_CLK_STAT & 0x00000009) == 0) {
        ;
    }
	/* Set port func bits so that both U1 and U2 can be hosts. */
	OTG_STAT_CTRL &= ~0x03;
	OTG_STAT_CTRL |= 0x01;
                                                              /* P0[12] = USB_PPWR2          01             */
    pinsel    = PINSEL0;
    pinsel   &= 0xFCFFFFFF;
    pinsel   |= 0x01000000;
    PINSEL0   = pinsel;
                                                              /* P0[29] = USB_D+1                           */
                                                              /* P0[30] = USB_D-1                           */
                                                              /* P0[31] = USB_D+2                           */
    pinsel    = PINSEL1;
    pinsel   &= 0x03FFFFFF;
    pinsel   |= 0x54000000;
    PINSEL1   = pinsel;
                                                              /* P1[19] = USB_PPWR1          10             */
                                                              /* P1[22] = USB_PWRD1          10             */
                                                              /* P1[27] = USB_OVRCR1         10             */
                                                              /* P1[31] = USB_OVRCR2         01             */
    pinsel    = PINSEL3;
    pinsel   &= 0x3F3FCF3F;
    pinsel   |= 0x40802080;
    PINSEL3   = pinsel;
		
    Hcca       = (volatile  HCCA       *)(HOST_BASE_ADDR+0x000);
    TDHead     = (volatile  HCTD       *)(HOST_BASE_ADDR+0x100);
    TDTail     = (volatile  HCTD       *)(HOST_BASE_ADDR+0x110);
    EDCtrl     = (volatile  HCED       *)(HOST_BASE_ADDR+0x120); 
		
		EDIntIn   = (volatile  HCED       *)(HOST_BASE_ADDR+0x130);
    EDIntOut  = (volatile  HCED       *)(HOST_BASE_ADDR+0x140);
		
    TDBuffer   = (volatile  USB_INT08U *)(HOST_BASE_ADDR+0x150);
                                                              /* Initialize all the TDs, EDs and HCCA to 0  */
    Host_EDInit(EDCtrl);
    Host_EDInit(EDIntIn);
    Host_EDInit(EDIntOut);
    Host_TDInit(TDHead);
    Host_TDInit(TDTail);
    Host_HCCAInit(Hcca);

    
    Host_DelayMS(50);                                         /* Wait 50 ms before apply reset              */
    HcControl       = 0;                                      /* HARDWARE RESET                             */
    HcControlHeadED = 0;                                      /* Initialize Control list head to Zero       */
		HcPeriodCurrentED = 0;
    
                                                              /* SOFTWARE RESET                             */
    HcCommandStatus = OR_CMD_STATUS_HCR;
    HcFmInterval    = DEFAULT_FMINTERVAL;              /* Write Fm Interval and Largest Data Packet Counter */
		
		HC_LS_THRHLD = 0x628;

                                                              /* Put HC in operational state                */
    HcControl  = (HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
    HcRhStatus = OR_RH_STATUS_LPSC;                           /* Set Global Power                           */
    
    HcHCCA = (USB_INT32U)Hcca;
    HcInterruptStatus |= HcInterruptStatus;                   /* Clear Interrrupt Status                    */
                                                              /* Enable  interrupts                         */
    HcInterruptEnable  = OR_INTR_ENABLE_MIE |
                         OR_INTR_ENABLE_WDH |																																					
                         OR_INTR_ENABLE_RHSC |
												 OR_INTR_ENABLE_SO |
												 OR_INTR_ENABLE_RD |
												 OR_INTR_ENABLE_UE |
												 OR_INTR_ENABLE_FNO |
												 OR_INTR_ENABLE_OC;


    VICIntSelect &= ~(1 << 22);                               /* Configure the ISR handler                  */
    VICVectAddr22 =  (USB_INT32U)Host_Isr;                    /* Set the vector address                     */
    VICIntEnable  = (1 << 22);                                /* Enable the USB interrupt source            */
		VICVectPriority22 &= 0xFFFFFFF0;
}