/**
 * tieschw.c
 *
*/
/*
 * Copyright (c) 2015, Texas Instruments Incorporated
 * All rights reserved.
 *
 * 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.
 **/

/*
*  This file is derived from MCI h/w source
*/

//---------------------------------------------------------------------------------------
/**
\ingroup tieschw
\file tieschw.c
\brief Implementation.
*/
//---------------------------------------------------------------------------------------
/*-----------------------------------------------------------------------------------------
------
------  Includes
------
-----------------------------------------------------------------------------------------*/
#include <stdio.h>
#include "hw_prm_device.h"
#ifdef AM43XX_FAMILY_BUILD
    #include "am437x.h"
#elif defined(AM335X_FAMILY_BUILD)
    #include "soc_am335x.h"
#endif
#include "tieschw.h"
#include "tiescutils.h"
#include "ecat_def.h"
#include "types.h"
#include "hw_types.h"

extern PRUICSS_Handle pruIcss1Handle;
extern Uint32 pd_read_addr_err, pd_write_addr_err;
/*--------------------------------------------------------------------------------------
------
------  local Types and Defines
------
--------------------------------------------------------------------------------------*/
typedef struct
{
    Uint16 PhysicalStartAddress;
    Uint16 Length;
    Uint8 Settings[4];
} __attribute__((packed)) TSYNCMAN;

/*-----------------------------------------------------------------------------------------
------
------  local variables and constants
------
-----------------------------------------------------------------------------------------*/
TSYNCMAN TmpSyncMan;
Uint16 nAlEventMask;

/*-----------------------------------------------------------------------------------------
------
------  local functions
------
-----------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------
------
------  functions
------
-----------------------------------------------------------------------------------------*/

/**
\addtogroup tieschw
@{
*/

/////////////////////////////////////////////////////////////////////////////////////////
/**
\return  0 if initialization was successful

           \brief   This function intializes the EtherCAT Slave Interface.
*////////////////////////////////////////////////////////////////////////////////////////

Uint8 HW_Init(void)
{
    Uint16 u16PdiCtrl;
    /* the memory interface to the ESC, the ESC-interrupt and the ECAT-timer for the
       watchdog monitoring should be initialized here microcontroller specific */

    bsp_init(pruIcss1Handle);

    /* we have to wait here, until the ESC is started */
    do
    {
        HW_EscReadWord(u16PdiCtrl, ESC_ADDR_PDI_CONTROL);
        u16PdiCtrl = SWAPWORD(u16PdiCtrl) & 0xFF;

    }
    while(u16PdiCtrl != 0x80);           //Looking for onchip bus

    bsp_start_esc_isr(pruIcss1Handle);

    return 0;
}

void HW_Release(void)
{

    bsp_exit(pruIcss1Handle);
}

void HW_EscRead(Uint8 *pData, Uint16 Address, Uint16 Len)
{
    bsp_read(pruIcss1Handle, pData, Address, Len);
    bsp_pdi_post_read_indication(pruIcss1Handle, Address);
}

void HW_EscReadIsr(Uint8 *pData, Uint16 Address, Uint16 Len)
{
    Int16 sm_index;
    Uint16 ActAddress = bsp_get_process_data_address(pruIcss1Handle, Address, Len,
                        &sm_index);

    if(ActAddress < ESC_ADDR_MEMORY)
    {
        pd_read_addr_err++;
        return;
    }

    bsp_read(pruIcss1Handle, pData, ActAddress, Len);

    bsp_process_data_access_complete(pruIcss1Handle, Address, Len, sm_index);
}

Uint8 __HW_EscReadByteIsr(PRUICSS_Handle pruIcssHandle, Uint16 Address)
{
    Uint8 ByteValue;
    Int16 sm_index;
    Uint16 ActAddress = bsp_get_process_data_address(pruIcssHandle, Address, 1,
                        &sm_index);

    if(ActAddress < ESC_ADDR_MEMORY)
    {
        pd_read_addr_err++;
        return 0;
    }

    ByteValue = bsp_read_byte_isr(pruIcssHandle, ActAddress);

    bsp_process_data_access_complete(pruIcssHandle, Address, 1, sm_index);
    return ByteValue;
}
Uint16 __HW_EscReadWordIsr(PRUICSS_Handle pruIcssHandle, Uint16 Address)
{
    Int16 sm_index;
    Uint16 WordValue, ActAddress = bsp_get_process_data_address(pruIcssHandle,
                                   Address, 2, &sm_index);

    if(ActAddress < ESC_ADDR_MEMORY)
    {
        pd_read_addr_err++;
        return 0;
    }

    WordValue = bsp_read_word_isr(pruIcssHandle, ActAddress);

    bsp_process_data_access_complete(pruIcssHandle, Address, 2, sm_index);
    return WordValue;
}

Uint32 __HW_EscReadDWordIsr(PRUICSS_Handle pruIcssHandle, Uint16 Address)
{
    Int16 sm_index;
    Uint16 ActAddress = bsp_get_process_data_address(pruIcssHandle, Address, 4,
                        &sm_index);
    Uint32 DWordValue;

    if(ActAddress < ESC_ADDR_MEMORY)
    {
        pd_read_addr_err++;
        return 0;
    }

    DWordValue = bsp_read_dword_isr(pruIcssHandle, ActAddress);

    bsp_process_data_access_complete(pruIcssHandle, Address, 4, sm_index);
    return DWordValue;
}
void HW_EscReadMbxMem(Uint8 *pData, Uint16 Address, Uint16 Len)
{
    t_sm_properties *p_sm_properties = bsp_get_sm_properties(MAILBOX_WRITE);
    bsp_pdi_mbx_read_start(pruIcss1Handle);
    bsp_read(pruIcss1Handle, pData, Address, Len);

    if(Len >= p_sm_properties->length - 2)
    {
        bsp_pdi_mbx_read_complete(pruIcss1Handle);
    }
}

void HW_EscWrite(Uint8 *pData, Uint16 Address, Uint16 Len)
{
    bsp_write(pruIcss1Handle, pData, Address, Len);
    bsp_pdi_write_indication(pruIcss1Handle, Address, 0);
}

void HW_EscWriteIsr(Uint8 *pData, Uint16 Address, Uint16 Len)
{
    Int16 sm_index;
    Uint16 ActualAddr = bsp_get_process_data_address(pruIcss1Handle, Address, Len,
                        &sm_index);

    if(ActualAddr < ESC_ADDR_MEMORY)
    {
        pd_write_addr_err++;
        return;
    }

    bsp_write(pruIcss1Handle, pData, ActualAddr, Len);

    bsp_process_data_access_complete(pruIcss1Handle, Address, Len, sm_index);
}

void HW_EscWriteDWord(Uint32 DWordValue, Uint16 Address)
{
    t_sm_properties *p_sm_properties = bsp_get_sm_properties(MAILBOX_READ);
    bsp_write_dword(pruIcss1Handle, DWordValue, Address);

    if(Address == (p_sm_properties->physical_start_addr + p_sm_properties->length
                   - 4))
    {
        bsp_pdi_mbx_write_complete(pruIcss1Handle);
    }

    else
    {
        bsp_pdi_write_indication(pruIcss1Handle, Address, (Uint16)DWordValue);
    }
}

void HW_EscWriteDWordIsr(Uint32 DWordValue, Uint16 Address)
{
    Int16 sm_index;
    Uint16 ActualAddr = bsp_get_process_data_address(pruIcss1Handle, Address, 4,
                        &sm_index);

    if(ActualAddr < ESC_ADDR_MEMORY)
    {
        pd_write_addr_err++;
        return;
    }

    bsp_write_dword(pruIcss1Handle, DWordValue, ActualAddr);
    bsp_process_data_access_complete(pruIcss1Handle, Address, 4, sm_index);

}
void HW_EscWriteWord(Uint16 WordValue, Uint16 Address)
{
    t_sm_properties *p_sm_properties = bsp_get_sm_properties(MAILBOX_READ);
    bsp_write_word(pruIcss1Handle, WordValue, Address);

    if(Address == (p_sm_properties->physical_start_addr + p_sm_properties->length- 2))
    {
        bsp_pdi_mbx_write_complete(pruIcss1Handle);
    }

    else
    {
        bsp_pdi_write_indication(pruIcss1Handle, Address, WordValue);
    }
}

void HW_EscWriteWordIsr(Uint16 WordValue, Uint16 Address)
{
    Int16 sm_index;
    Uint16 ActualAddr = bsp_get_process_data_address(pruIcss1Handle, Address, 2,
                        &sm_index);

    if(ActualAddr < ESC_ADDR_MEMORY)
    {
        pd_write_addr_err++;
        return;
    }

    bsp_write_word(pruIcss1Handle, WordValue, ActualAddr);
    bsp_process_data_access_complete(pruIcss1Handle, Address, 2, sm_index);
}

void HW_EscWriteByte(Uint8 ByteValue, Uint16 Address)
{
    t_sm_properties *p_sm_properties = bsp_get_sm_properties(MAILBOX_READ);
    bsp_write_byte(pruIcss1Handle, ByteValue, Address);

    if(Address == (p_sm_properties->physical_start_addr + p_sm_properties->length
                   - 1))
    {
        bsp_pdi_mbx_write_complete(pruIcss1Handle);
    }

    else
    {
        bsp_pdi_write_indication(pruIcss1Handle, Address, ByteValue);
    }
}

void HW_EscWriteByteIsr(Uint8 ByteValue, Uint16 Address)
{
    Int16 sm_index;
    Uint16 ActualAddr  = bsp_get_process_data_address(pruIcss1Handle, Address, 1,
                         &sm_index);

    if(ActualAddr < ESC_ADDR_MEMORY)
    {
        pd_write_addr_err++;
        return;
    }

    bsp_write_byte(pruIcss1Handle, ByteValue, ActualAddr);

    bsp_process_data_access_complete(pruIcss1Handle, Address, 1, sm_index);
}

void HW_EscWriteMbxMem(Uint8 *pData, Uint16 Address, Uint16 Len)
{
    t_sm_properties *p_sm_properties = bsp_get_sm_properties(MAILBOX_READ);

    //Do not write to mailbox if already full
    if((bsp_read_byte(pruIcss1Handle,
                      ESC_ADDR_SM1_STATUS) & SM_STATUS_MBX_FULL))
    {
        return;
    }

    bsp_pdi_mbx_write_start(pruIcss1Handle);
    bsp_write(pruIcss1Handle, pData, Address, Len);

    if(Len >= p_sm_properties->length - 2)
    {
        bsp_pdi_mbx_write_complete(pruIcss1Handle);
    }
}

/////////////////////////////////////////////////////////////////////////////////////////
/**

           \brief   This function resets the hardware
*////////////////////////////////////////////////////////////////////////////////////////

void HW_RestartTarget(void)
{
    #ifdef AM43XX_FAMILY_BUILD
    /* Warm reset */
    HWREG(SOC_PRM_DEVICE_REG + PRCM_PRM_RSTCTRL) = 1;
    #elif defined(AM335X_FAMILY_BUILD)
    HWREG(SOC_PRM_DEVICE_REGS + PRM_DEVICE_PRM_RSTCTRL) = 1;
    #endif
}

void HW_SetLed(Uint8 RunLed, Uint8 ErrLed)
{
    Board_setTriColorLED(BOARD_TRICOLOR0_GREEN, RunLed);
    Board_setTriColorLED(BOARD_TRICOLOR1_RED, ErrLed);
}

unsigned int HW_GetTimer()
{
    return bsp_get_timer_register();
}

void HW_ClearTimer()
{
    bsp_clear_timer_register();
}

UInt16 HW_EepromReload()
{
    Uint16 retval;
    retval = bsp_eeprom_emulation_reload(pruIcss1Handle);
    return retval;
}
/** @} */
