//#############################################################################
// FILE: usbtick.c
// TITLE: Functions related to USB stack tick timer handling
//#############################################################################
// $TI Release: F2837xD Support Library v210 $
// $Release Date: Tue Nov  1 14:46:15 CDT 2016 $
// $Copyright:
// Copyright (C) 2013-2016 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions 
// are met:
// 
//   Redistributions of source code must retain the above copyright 
//   notice, this list of conditions and the following disclaimer.
// 
//   Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the 
//   documentation and/or other materials provided with the   
//   distribution.
// 
//   Neither the name of Texas Instruments Incorporated nor the names of
//   its contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//#############################################################################

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "usblib/usblib.h"
#include "usblib/usblibpriv.h"

//*****************************************************************************
//
//! \addtogroup general_usblib_api
//! @{
//
//*****************************************************************************

//*****************************************************************************
//
// These are the internal timer tick handlers used by the USB stack.  Handlers
// in g_pfnTickHandlers are called in the context of the USB SOF interrupt
// every USB_SOF_TICK_DIVIDE milliseconds.
//
//*****************************************************************************
tUSBTickHandler g_pfnTickHandlers[MAX_USB_TICK_HANDLERS];
void *g_pvTickInstance[MAX_USB_TICK_HANDLERS];

//*****************************************************************************
//
// Flag to indicate whether or not we have been initialized.
//
//*****************************************************************************
bool g_bUSBTimerInitialized = false;

//*****************************************************************************
//
// This is the current tick value in ms for the system.  This is used for all
// instances of USB controllers and for all timer tick handlers.
//
//*****************************************************************************
uint32_t g_ui32CurrentUSBTick = 0;

//*****************************************************************************
//
// This is the total number of SOF interrupts received since the system
// booted.  The value is incremented by the low level device- or host-interrupt
// handler functions.
//
//*****************************************************************************
uint32_t g_ui32USBSOFCount = 0;

//*****************************************************************************
//
// This internal function initializes the variables used in processing timer
// ticks.
//
// This function should only be called from within the USB library.  It is set
// up to ensure that it can be called multiple times if necessary without
// the previous configuration being erased (to cater for OTG mode switching).
//
// \return None.
//
//*****************************************************************************
void
InternalUSBTickInit(void)
{
    uint32_t ui32Loop;

    if(!g_bUSBTimerInitialized)
    {
        for(ui32Loop = 0; ui32Loop < MAX_USB_TICK_HANDLERS; ui32Loop++)
        {
            g_pfnTickHandlers[ui32Loop] = (tUSBTickHandler)0;
            g_pvTickInstance[ui32Loop] = 0;
        }

        g_bUSBTimerInitialized = true;
    }
}

//*****************************************************************************
//
// This internal function resets the USB tick handler.
//
// This function should only be called from within the USB library.  It will
// clear out the tick handler state and should be called to allow the tick
// handlers to be initialized once USBDCDInit() function is called.
//
// \return None.
//
//*****************************************************************************
void
InternalUSBTickReset(void)
{
    //
    // Reset the initialized flag so that the next time InternalUSBTickInit()
    // is called.
    //
    g_bUSBTimerInitialized = 0;
}

//*****************************************************************************
//
// This internal function handles registering OTG, Host, or Device SOF timer
// handler functions.
//
// \param pfHandler specifies the handler to call for the given type of
// handler.
// \param pvInstance is the instance pointer that will be returned to the
// function provided in the \e pfHandler function.
//
// This function should only be called inside the USB library and only as a
// result to a call to reinitialize the stack in a new mode.  Currently the
// following 3 types of timer tick handlers can be registered:
// TICK_HANDLER_OTG, TICK_HANDLER_HOST, or TICK_HANDLER_DEVICE.  Handlers
// registered via this function are called in the context of the SOF interrupt.
//
// \return A value of zero means that the tick handler was registered and any
// other value indicates an error.
//
//*****************************************************************************
int32_t
InternalUSBRegisterTickHandler(tUSBTickHandler pfHandler, void *pvInstance)
{
    int32_t i32Idx;

    for(i32Idx = 0; i32Idx < MAX_USB_TICK_HANDLERS; i32Idx++)
    {
        if(g_pfnTickHandlers[i32Idx] == 0)
        {
            //
            // Save the handler.
            //
            g_pfnTickHandlers[i32Idx] = pfHandler;

            //
            // Save the instance data.
            //
            g_pvTickInstance[i32Idx] = pvInstance;
        }
    }

    if(i32Idx == MAX_USB_TICK_HANDLERS)
    {
        return(-1);
    }
    return(0);
}

//*****************************************************************************
//
//! \internal
//!
//! Calls internal handlers in response to a tick based on the start of frame
//! interrupt.
//!
//! \param ui32TicksmS specifies how many milliseconds have passed since the
//! last call to this function.
//!
//! This function is called every 5mS in the context of the Start of Frame
//! (SOF) interrupt.  It is used to call any registered internal tick
//! functions.
//!
//! This function should only be called from within the USB library.
//!
//! \return None.
//
//*****************************************************************************
void
InternalUSBStartOfFrameTick(uint32_t ui32TicksmS)
{
    int32_t i32Idx;

    //
    // Advance time.
    //
    g_ui32CurrentUSBTick += ui32TicksmS;

    //
    // Call any registered SOF tick handlers.
    //
    for(i32Idx = 0; i32Idx < MAX_USB_TICK_HANDLERS; i32Idx++)
    {
        if(g_pfnTickHandlers[i32Idx])
        {
            g_pfnTickHandlers[i32Idx](g_pvTickInstance[i32Idx], ui32TicksmS);
        }
    }
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
