/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer *
* Copyright (C) 2014 Renesas Electronics Corporation
* and Renesas Solutions Corp. All rights reserved.
*******************************************************************************/
/*******************************************************************************
* File Name    : r_pdc_apl.c
* Version      : 1.00
* Device(s)    : Renesas
* Tool-Chain   : Renesas
* OS           : None
* H/W Platform : Independent
* Description  : This is PDC application program code.
******************************************************************************/
/*****************************************************************************
* History : DD.MM.YYYY Version Description
*         : 01.09.2014 1.00    First Release
******************************************************************************/

/******************************************************************************
Includes <System Includes> , "Project Includes"
******************************************************************************/
#include "platform.h"
#include "r_dmaca_rx_if.h"
#include "r_pdc_rx_if.h"
#include "r_dmac_apl.h"
#include "r_compress_jpege.h"
#include "r_jpeg_enc_apl.h"
#include "ov7740.h"

#define  PDC_INITIAL
#include "r_pdc_apl.h"

#pragma section _CAPT_IMAGE_BUFFER
uint8_t buf_cap[IMG_SESOR_OUTOUT_PIXEL_SIZE];
#pragma section

/******************************************************************************
Macro definitions
******************************************************************************/

/******************************************************************************
Typedef definitions
******************************************************************************/

/******************************************************************************
Exported global variables and functions (to be accessed by other files)
******************************************************************************/
extern struct r_jpeg_encode_t *R_get_jpeg_compress_info( void );
extern int32_t R_exec_jpeg_compress( struct r_jpeg_encode_t *jpeg_info );

extern void R_req_capture_retry( uint8_t retry );

/******************************************************************************
Private global variables and functions
******************************************************************************/
static void pdc_err_interrupt( void );
static void pdc_frame_end( void );
static void pdc_pcdfi(void);

static pdc_data_cfg_t    p_data_pdc;

/******************************************************************************
Function Name   : R_pdc_init
Description     : PDC initialize step1
Arguments       : none
Return Value    : none
******************************************************************************/
void R_pdc_init( void )
{
    pdc_return_t    ret;

    p_data_pdc.priority.pcdfi_level = PDC_INT_PRI_DMAC;
    p_data_pdc.inticu_req.pcdfi_ien = true;
    p_data_pdc.inticu_req.pcfei_ien = true;
    p_data_pdc.inticu_req.pceri_ien = true;

    ret = R_PDC_Open(&p_data_pdc);
    if (PDC_SUCCESS != ret)
    {
        /* do something */
    }
    /* registe callback function of pdc */
    ret = R_PDC_IntWrite(PDC_INTERRUPT_PCDFI, (bsp_int_cb_t)pdc_pcdfi);
    if (PDC_SUCCESS != ret)
    {
        /* do something */
    }
    ret = R_PDC_IntWrite(PDC_INTERRUPT_PCFEI, (bsp_int_cb_t)pdc_frame_end);
    if (PDC_SUCCESS != ret)
    {
        /* do something */
    }
    ret = R_PDC_IntWrite(PDC_INTERRUPT_PCERI, (bsp_int_cb_t)pdc_err_interrupt);
    if (PDC_SUCCESS != ret)
    {
        /* do something */
    }
}

/******************************************************************************
Function Name   : R_pdc_crete
Description     : PDC initialize step2
Arguments       : none
Return Value    : none
******************************************************************************/
void R_pdc_create( void )
{
    pdc_return_t     ret;

    p_data_pdc.intpdc_req.dfie_ien      = true;
    p_data_pdc.intpdc_req.feie_ien      = true;
    p_data_pdc.intpdc_req.ovie_ien      = true;
    p_data_pdc.intpdc_req.udrie_ien     = true;
    p_data_pdc.intpdc_req.verie_ien     = true;
    p_data_pdc.intpdc_req.herie_ien     = true;
#if VSYNC_ACTIVE == VSYNC_ACTIVE_L
    p_data_pdc.vps_select               = PDC_VSYNC_SIGNAL_POLARITY_LOW;
#else
    p_data_pdc.vps_select               = PDC_VSYNC_SIGNAL_POLARITY_HIGH;
#endif
#if HSYNC_ACTIVE == HSYNC_ACTIVE_H
    p_data_pdc.hps_select               = PDC_HSYNC_SIGNAL_POLARITY_HIGH;
#else
    p_data_pdc.hps_select               = PDC_HSYNC_SIGNAL_POLARITY_LOW;
#endif
    p_data_pdc.capture_pos.vst_position = 0;
    p_data_pdc.capture_pos.hst_position = 0;
    p_data_pdc.capture_size.vsz_size    = IMG_SENSOR_OUTPUT_HEIGHT;
    p_data_pdc.capture_size.hsz_size    = IMG_SENSOR_OUTPUT_WIDTH * 2;  //16bit(4:2:2)

    ret = R_PDC_Create(&p_data_pdc);
    if (PDC_SUCCESS != ret)
    {
        /* do something */
    }
}

/******************************************************************************
Function Name   : pdc_err_interrupt
Description     : PDC recive interrupt
Arguments       : none
Return Value    : none
******************************************************************************/
static void pdc_err_interrupt( void )
{
    volatile dmaca_return_t      ret_dmac;
    dmaca_stat_t                 p_stat_dmac;
    volatile pdc_return_t        ret_pdc;
    pdc_data_cfg_t               p_dummy;
    pdc_stat_t                   p_stat_pdc;

    /* Operations for reception are disabled. */
    ret_pdc = R_PDC_Control(PDC_CMD_DISABLE, &p_dummy, &p_stat_pdc);
    if (PDC_SUCCESS != ret_pdc)
    {
        /* do something */
    }

    /* Disable the DMAC transfer. */
    {
        ret_dmac = R_DMACA_Control(DMACA_CH0, DMACA_CMD_DISABLE, &p_stat_dmac);
        if (DMACA_SUCCESS != ret_dmac)
        {
            /* do something */
        }
    }

    ret_pdc = R_PDC_Control(PDC_CMD_STATUS_GET, &p_dummy, &p_stat_pdc);
    if (PDC_SUCCESS != ret_pdc)
    {
        /* do something */
    }

    if (true == p_stat_pdc.pcsr_stat.overrun)
    {
        /* Clear Overrun flag. */
        p_stat_pdc.pcsr_stat.overrun = true;
        ret_pdc = R_PDC_Control(PDC_CMD_STATUS_CLR, &p_dummy, &p_stat_pdc);
        if (PDC_SUCCESS != ret_pdc)
        {
            /* do something */
        }
    }
    if (true == p_stat_pdc.pcsr_stat.underrun)
    {
        /* Clear Underrun flag. */
        p_stat_pdc.pcsr_stat.underrun = true;
        ret_pdc = R_PDC_Control(PDC_CMD_STATUS_CLR, &p_dummy, &p_stat_pdc);
        if (PDC_SUCCESS != ret_pdc)
        {
            /* do something */
        }
    }
    if (true == p_stat_pdc.pcsr_stat.verf_error)
    {
        /* Clear Vertical line setting error flag. */
        p_stat_pdc.pcsr_stat.verf_error = true;
        ret_pdc = R_PDC_Control(PDC_CMD_STATUS_CLR, &p_dummy, &p_stat_pdc);
        if (PDC_SUCCESS != ret_pdc)
        {
            /* do something */
        }
    }
    if (true == p_stat_pdc.pcsr_stat.herf_error)
    {
        /* Clear Horizontal byte setting error flag. */
        p_stat_pdc.pcsr_stat.herf_error = true;
        ret_pdc = R_PDC_Control(PDC_CMD_STATUS_CLR, &p_dummy, &p_stat_pdc);
        if (PDC_SUCCESS != ret_pdc)
        {
            /* do something */
        }
    }

    ret_pdc = R_PDC_Control(PDC_CMD_RESET, &p_dummy, &p_stat_pdc);
    if (PDC_SUCCESS != ret_pdc)
    {
        /* do something */
    }

// R_pdc_receive_again( 1 );
    R_req_capture_retry(1);
}

/******************************************************************************
Function Name   : pdc_frame_end
Description     : PDC frame end interrupt
Arguments       : none
Return Value    : none
******************************************************************************/
static void pdc_frame_end( void )
{
    int16_t      r_ret;

// unsigned long dma_addr;
    volatile dmaca_return_t      ret_dmac;
    dmaca_stat_t                 p_stat_dmac;
    volatile pdc_return_t        ret_pdc;
    pdc_data_cfg_t               p_dummy;
    pdc_stat_t                   p_stat_pdc;

    R_BSP_InterruptsEnable();

    /* Check FIFO empty and UDRF flag. */
    do
    {
        ret_pdc = R_PDC_Control(PDC_CMD_STATUS_GET, &p_dummy, &p_stat_pdc);
        if (PDC_SUCCESS != ret_pdc)
        {
            /* do something */
        }
        if (true == p_stat_pdc.pcsr_stat.underrun)
        {
            p_stat_pdc.pcsr_stat.fifo_empty = true;
            ret_pdc = R_PDC_Control(PDC_CMD_STATUS_CLR, &p_dummy, &p_stat_pdc);
            if (PDC_SUCCESS != ret_pdc)
            {
                /* do something */
            }
            pdc_err_interrupt();
            return;
        }
    }
    while (true != p_stat_pdc.pcsr_stat.fifo_empty);

    /* Operations for reception are disabled. */
    ret_pdc = R_PDC_Control(PDC_CMD_DISABLE, &p_dummy, &p_stat_pdc);
    if (PDC_SUCCESS != ret_pdc)
    {
        /* do something */
    }

    /* Clear FIFO empty flag. */
    p_stat_pdc.pcsr_stat.fifo_empty = true;
    ret_pdc = R_PDC_Control(PDC_CMD_STATUS_CLR, &p_dummy, &p_stat_pdc);
    if (PDC_SUCCESS != ret_pdc)
    {
        /* do something */
    }

    {
        ret_dmac = R_DMACA_Control(DMACA_CH0, DMACA_CMD_DISABLE, &p_stat_dmac);
        if (DMACA_SUCCESS != ret_dmac)
        {
            /* do something */
        }
    }

    /* JPEG COMPRESS */
    r_ret = R_exec_jpeg_compress( R_get_jpeg_compress_info() );
    if ( r_ret != COMPRESS_JPEGE_OK )
    {
        /* do something */
    }

// R_pdc_receive_again( 1 );
    R_req_capture_retry(1);

}

/******************************************************************************
Function Name   : pdc_receive_again
Description     : PDC receive processing restart
Arguments       : input param : unsigned char continue_flag; 0:dst_addr reset ,1:dst_addr continue
Return Value    : none
******************************************************************************/
void R_pdc_receive_again( uint8_t continue_flag )
{
    pdc_return_t       ret_pdc;
    pdc_data_cfg_t     p_data_pdc;
    pdc_stat_t         p_stat_pdc;

#if RAMDATA_ADDR != RAMDATA_ADDR_SDRAM
    continue_flag = 0;
#endif

    g_pdc_picture_block = (( g_pdc_picture_block + 1 ) >= D_PDC_MAX_PICTURE_BLOCK ) ? 0 : g_pdc_picture_block + 1;

    if ( continue_flag == 0 )
    {
        g_pdc_picture_block = 0;
    }

    {
        R_dmac_ch0_init( g_pdc_picture_block );            // DMAC0 initialize
    }

    ret_pdc = R_PDC_Control(PDC_CMD_CAPTURE_START, &p_data_pdc, &p_stat_pdc);
    if (PDC_SUCCESS == ret_pdc)
    {
        /* do something */
    }
}

/******************************************************************************
Function Name   : pdc_pcdfi
Description     : --
Arguments       : none
Return Value    : none
******************************************************************************/
static void pdc_pcdfi(void)
{
}

/******************************************************************************
Function Name   : R_get_pdc_capture_buf_adr
Description     : get buffer address for PDC capture
Arguments       : none
Return Value    : buffer address
******************************************************************************/
uint8_t *R_get_pdc_capture_buf_adr( void )
{
    return buf_cap;
}

/******************************************************************************
End of file
******************************************************************************/
