/*
 * @file exo_io_al_spi_common.c
 *
 * @brief This file contains abstracted function definition for SPI interface
 *
 * @copyright Copyright 2023 Antaris, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <unistd.h>
#include "exo_io_al_spi_common.h"
#include "exo_hal_io_al_common.h"
#include "exo_common.h"
#ifndef LINUX_TEMP_PORT
#include "exo_io_al_stm32f7xx_spi.h"
#else
#include "exo_io_al_linux_spi.h"
#endif

#define IOAL_SPI_TX_CPLT_CB		io_hal_spi_tx_cplt_cb		///< SPI TX complete callback event
#define IOAL_SPI_RX_CPLT_CB		io_hal_spi_rx_cplt_cb		///< SPI RX complete callback event
#define IOAL_SPI_TX_RX_CPLT_CB		io_hal_spi_tx_rx_cplt_cb    	///< SPI TX RX complete callback event
#define IOAL_SPI_ABORT_CPLT_CB		io_hal_spi_abort_cplt_cb    	///< SPI Abort complete callback event
#define IOAL_SPI_ERROR_CB		io_hal_spi_error_cb             ///< SPI error callback event

extern void *intf_inst_hdle_ptr[MAX_IO_INST_ID];


/*
 * @brief This API initialize the SPI interface
 */
hal_ret_sts io_hal_spi_init(ioal_spi_hdle *ioal_hspi, io_inst_id inst_id)
{
#ifdef LINUX_TEMP_PORT
    DEBUG_CPRINT(("\n EXO IO AL SPI Initialise"));
    usleep(100000);
#endif
    hal_ret_sts sts=HAL_IO_INIT_ERR;
    if(ioal_hspi != NULL)
    {
        switch(inst_id)
        {
            case IOAL_INST_SPI1:
                if(HAL_SCS == io_hal_common_spi1_init(ioal_hspi))
                {
                    intf_inst_hdle_ptr[IOAL_INST_SPI1] = ioal_hspi;
                    io_hal_spi1_cb_init(ioal_hspi);
                }
                else
                {
                    sts = HAL_IO_INIT_ERR;
                }
                break;
            case IOAL_INST_SPI2:
                if(HAL_SCS == io_hal_common_spi2_init(ioal_hspi))
                {
                    intf_inst_hdle_ptr[IOAL_INST_SPI2] = ioal_hspi;
                    io_hal_spi2_cb_init(ioal_hspi);

                }
                else
                {

                    sts = HAL_IO_INIT_ERR;
                }
                break;
            default:
                sts = HAL_IO_INIT_INVALID_INSTANCE;
                break;
        }
    }
    else
    {
        sts = HAL_IO_INVLD_ARG;
    }
#ifdef LINUX_TEMP_PORT
    DEBUG_CPRINT(("\n EXO IO AL SPI Initialisation completed successfully"));
#endif
    return sts;
}

/*
 * @brief This API initialize the callback event
 */
void io_hal_spi1_cb_init(ioal_spi_hdle *hspi1)
{
    hspi1->spi_tx_cplt_cb = IOAL_SPI_TX_CPLT_CB;
    hspi1->spi_rx_cplt_cb = IOAL_SPI_RX_CPLT_CB;
    hspi1->spi_tx_rx_cplt_cb = IOAL_SPI_TX_RX_CPLT_CB;
    hspi1->spi_abort_cplt_cb = IOAL_SPI_ABORT_CPLT_CB;
    hspi1->spi_error_cb = IOAL_SPI_ERROR_CB;
}

void io_hal_spi2_cb_init(ioal_spi_hdle *hspi2)
{
    hspi2->spi_tx_cplt_cb = IOAL_SPI_TX_CPLT_CB;
    hspi2->spi_rx_cplt_cb = IOAL_SPI_RX_CPLT_CB;
    hspi2->spi_tx_rx_cplt_cb = IOAL_SPI_TX_RX_CPLT_CB;
    hspi2->spi_abort_cplt_cb = IOAL_SPI_ABORT_CPLT_CB;
    hspi2->spi_error_cb = IOAL_SPI_ERROR_CB;
}

/*
 * @brief This API transmit the data in SPI interface with blocking mode
 */
hal_ret_sts io_hal_spi_transmit(ioal_spi_hdle *hspi, uint8 *pdata, uint16 size, uint32 timeout)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    hspi->intf_gen_info.state = IO_BUSY_STATE;
    if(hspi != NULL && pdata != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_transmit(hspi,pdata,size,timeout))
        {
            ret_sts = HAL_SCS;
            hspi->intf_gen_info.state = IO_FREE_STATE;
        }
        else
        {
            ret_sts = HAL_IO_TX_ERR;
            hspi->intf_gen_info.state = IO_FREE_STATE;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

/*
 * @brief This API receive the data from SPI interface with blocking mode
 */
hal_ret_sts io_hal_spi_receive(ioal_spi_hdle *hspi, uint8 *pdata, uint16 size, uint32 timeout)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    hspi->intf_gen_info.state = IO_BUSY_STATE;
    if(hspi != NULL && pdata != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_receive(hspi,pdata,size,timeout))
        {
            ret_sts = HAL_SCS;
            hspi->intf_gen_info.state = IO_FREE_STATE;
        }
        else
        {
            ret_sts = HAL_IO_RX_ERR;
            hspi->intf_gen_info.state = IO_FREE_STATE;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

#ifndef LINUX_TEMP_PORT
/*
 * @brief This API transmit and receive the data
 */
hal_ret_sts io_hal_spi_transmit_receive(ioal_spi_hdle *hspi, uint8 *ptxdata, uint8 *prxdata, uint16 size, uint32 timeout)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    hspi->intf_gen_info.state = IO_BUSY_STATE;
    if(hspi != NULL && ptxdata != NULL && prxdata != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_transmit_receive(hspi,ptxdata,prxdata,size,timeout))
        {
            ret_sts = HAL_SCS;
            hspi->intf_gen_info.state = IO_FREE_STATE;
        }
        else
        {
            ret_sts = HAL_IO_RX_ERR;
            hspi->intf_gen_info.state = IO_FREE_STATE;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

/*
 * @brief This API transmit the data in SPI interface with interrupt mode
 */
hal_ret_sts io_hal_spi_transmit_it(ioal_spi_hdle *hspi, ahw_al_gen_info* ahw_info, uint8 *pdata, uint16 size)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    hspi->intf_gen_info.state = IO_BUSY_STATE;
    hspi->app_callbacks=ahw_info->intr_hdl.io_cb_list.spi_callbacks;
    hspi->cb_context=ahw_info->intr_hdl.cb_context;
    if(hspi != NULL && pdata != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_transmit_it(hspi,pdata,size))
        {
            ret_sts = HAL_SCS;

        }
        else
        {
            ret_sts = HAL_IO_RX_ERR;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

/*
 * @brief This API receive the data from SPI interface with interrupt mode
 */
hal_ret_sts io_hal_spi_receive_it(ioal_spi_hdle *hspi, ahw_al_gen_info* ahw_info, uint8 *pdata, uint16 size)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    hspi->intf_gen_info.state = IO_BUSY_STATE;
    hspi->app_callbacks=ahw_info->intr_hdl.io_cb_list.spi_callbacks;
    hspi->cb_context=ahw_info->intr_hdl.cb_context;
    if(hspi != NULL && pdata != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_receive_it(hspi,pdata,size))
        {
            ret_sts = HAL_SCS;

        }
        else
        {
            ret_sts = HAL_IO_RX_ERR;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

/*
 * @brief This API transmit and receive the data in interrupt mode
 */
hal_ret_sts io_hal_spi_transmit_receive_it(ioal_spi_hdle *hspi, ahw_al_gen_info* ahw_info, uint8 *ptxdata, uint8 *prxdata, uint16 size)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    hspi->intf_gen_info.state = IO_BUSY_STATE;
    hspi->app_callbacks=ahw_info->intr_hdl.io_cb_list.spi_callbacks;
    hspi->cb_context=ahw_info->intr_hdl.cb_context;
    if(hspi != NULL && ptxdata != NULL && prxdata != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_transmit_receive_it(hspi,ptxdata, prxdata, size))
        {
            ret_sts = HAL_SCS;

        }
        else
        {
            ret_sts = HAL_IO_RX_ERR;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

/*
 * @brief This API transmit the data in SPI interface in DMA mode
 */
hal_ret_sts io_hal_spi_transmit_dma(ioal_spi_hdle *hspi, ahw_al_gen_info* ahw_info, uint8 *pdata, uint16 size)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    hspi->intf_gen_info.state = IO_BUSY_STATE;
    hspi->app_callbacks=ahw_info->intr_hdl.io_cb_list.spi_callbacks;
    hspi->cb_context=ahw_info->intr_hdl.cb_context;
    if(hspi != NULL && pdata != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_transmit_dma(hspi,pdata, size))
        {
            ret_sts = HAL_SCS;

        }
        else
        {
            ret_sts = HAL_IO_RX_ERR;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

/*
 * @brief This API receive the data from SPI interface in DMA mode
 */
hal_ret_sts io_hal_spi_receive_dma(ioal_spi_hdle *hspi, ahw_al_gen_info* ahw_info, uint8 *pdata, uint16 size)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    hspi->intf_gen_info.state = IO_BUSY_STATE;
    hspi->app_callbacks=ahw_info->intr_hdl.io_cb_list.spi_callbacks;
    hspi->cb_context=ahw_info->intr_hdl.cb_context;
    if(hspi != NULL && pdata != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_receive_dma(hspi,pdata, size))
        {
            ret_sts = HAL_SCS;
        }
        else
        {
            ret_sts = HAL_IO_RX_ERR;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

/*
 * @brief This API transmit and receive the data in DMA mode
 */
hal_ret_sts io_hal_spi_transmit_receive_dma(ioal_spi_hdle *hspi, ahw_al_gen_info* ahw_info,uint8 *ptxdata, uint8 *prxdata, uint16 size)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    hspi->intf_gen_info.state = IO_BUSY_STATE;
    hspi->app_callbacks=ahw_info->intr_hdl.io_cb_list.spi_callbacks;
    hspi->cb_context=ahw_info->intr_hdl.cb_context;
    if(hspi != NULL && ptxdata != NULL && prxdata != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_transmit_receive_dma(hspi,ptxdata, prxdata, size))
        {
            ret_sts = HAL_SCS;

        }
        else
        {
            ret_sts = HAL_IO_RX_ERR;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

/*
 * @brief This API abort the transmission of data in SPI interface
 */
hal_ret_sts io_hal_spi_abort(ioal_spi_hdle *hspi)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    if(hspi != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_abort(hspi))
        {
            ret_sts = HAL_SCS;

        }
        else
        {
            ret_sts = HAL_IO_RX_ERR;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

/*
 * @brief This API pause the transmission of data in DMA mode
 */
hal_ret_sts io_hal_spi_dma_pause(ioal_spi_hdle *hspi)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    if(hspi != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_dma_pause(hspi))
        {
            ret_sts = HAL_SCS;

        }
        else
        {
            ret_sts = HAL_IO_RX_ERR;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

/*
 * @brief This API resume the transmission of data in DMA mode
 */
hal_ret_sts io_hal_spi_dma_resume(ioal_spi_hdle *hspi)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    if(hspi != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_dma_resume(hspi))
        {
            ret_sts = HAL_SCS;

        }
        else
        {
            ret_sts = HAL_IO_RX_ERR;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

/*
 * @brief This API stop the transmission of data in DMA mode
 */
hal_ret_sts io_hal_spi_dma_stop(ioal_spi_hdle *hspi)
{
    hal_ret_sts ret_sts = HAL_MAX_ERR;
    if(hspi != NULL)
    {
        if(HAL_SCS == io_hal_common_spi_dma_stop(hspi))
        {
            ret_sts = HAL_SCS;

        }
        else
        {
            ret_sts = HAL_IO_RX_ERR;
        }
    }
    else
    {
        ret_sts = HAL_IO_INVLD_ARG;
    }
    return ret_sts;
}

#endif



void io_hal_spi_tx_cplt_cb(ioal_spi_hdle *hspi)
{
    hspi->intf_gen_info.state = IO_FREE_STATE;
    hspi->app_callbacks.spi_tx_cplt_cb(hspi);
}
void io_hal_spi_rx_cplt_cb(ioal_spi_hdle *hspi)
{
    hspi->intf_gen_info.state = IO_FREE_STATE;
    hspi->app_callbacks.spi_rx_cplt_cb(hspi);
}
void io_hal_spi_tx_rx_cplt_cb(ioal_spi_hdle *hspi)
{
    hspi->intf_gen_info.state = IO_FREE_STATE;
    hspi->app_callbacks.spi_tx_rx_cplt_cb(hspi);
}
void io_hal_spi_abort_cplt_cb(ioal_spi_hdle *hspi)
{
    hspi->intf_gen_info.state = IO_FREE_STATE;
    hspi->app_callbacks.spi_abort_cplt_cb(hspi);
}
void io_hal_spi_error_cb(ioal_spi_hdle *hspi)
{
    hspi->intf_gen_info.state = IO_FREE_STATE;
  //  hspi->app_callbacks.spi_error_cb(hspi);
}

