/*********************************************************************************************************************
* TC264 Opensourec Library TC264 Դ⣩һڹٷ SDK ӿڵĵԴ
* Copyright (c) 2022 SEEKFREE ɿƼ
*
* ļ TC264 Դһ
*
* TC264 Դ 
* Ըᷢ GPLGNU General Public License GNUͨù֤
*  GPL ĵ3棨 GPL3.0ѡģκκİ汾·/޸
*
* Դķϣܷãδκεı֤
* ûԻʺض;ı֤
* ϸμ GPL
*
* ӦյԴͬʱյһ GPL ĸ
* ûУ<https://www.gnu.org/licenses/>
*
* ע
* Դʹ GPL3.0 Դ֤Э Ϊİ汾
* Ӣİ libraries/doc ļµ GPL3_permission_statement.txt ļ
* ֤ libraries ļ ļµ LICENSE ļ
* ӭλʹò ޸ʱ뱣ɿƼİȨ
*
* ļ          zf_device_camera
* ˾          ɶɿƼ޹˾
* 汾Ϣ          鿴 libraries/doc ļ version ļ 汾˵
*           ADS v1.9.4
* ƽ̨          TC264D
*           https://seekfree.taobao.com/
*
* ޸ļ¼
*                               ע
* 2022-09-15       pudding           first version
* 2023-04-25       pudding           ע˵
********************************************************************************************************************/

#include "zf_common_debug.h"
#include "zf_common_interrupt.h"
#include "zf_driver_gpio.h"
#include "zf_driver_dma.h"
#include "zf_driver_exti.h"
#include "zf_device_mt9v03x.h"
#include "zf_device_ov7725.h"
#include "zf_device_scc8660.h"
#include "zf_device_camera.h"


fifo_struct camera_receiver_fifo;                                           // ͷfifoṹ
uint8 camera_receiver_buffer[CAMERA_RECEIVER_BUFFER_SIZE];                  // ͷݻ
uint8 camera_send_image_frame_header[4] = {0x00, 0xFF, 0x01, 0x01};         // ͷݷ͵λ֡ͷ

//-------------------------------------------------------------------------------------------------------------------
//        ͷͼݽѹΪʮưλ С
// ˵       *data1          ͷͼ
// ˵       *data2          Žѹݵĵַ
// ˵       image_size      ͼĴС
// @return      void
// Sample usage:   camera_binary_image_decompression(&ov7725_image_binary[0][0], &data_buffer[0][0], OV7725_SIZE);
//-------------------------------------------------------------------------------------------------------------------
void camera_binary_image_decompression (const uint8 *data1, uint8 *data2, uint32 image_size)
{
    zf_assert(NULL != data1);
    zf_assert(NULL != data2);
    uint8  i = 8;

    while(image_size --)
    {
        i = 8;
        while(i --)
        {
            *data2 ++ = (((*data1 >> i) & 0x01) ? 255 : 0);
        }
        data1 ++;
    }
}

//-------------------------------------------------------------------------------------------------------------------
//        ͷͼλ鿴ͼ
// ˵       uartn           ʹõĴں
// ˵       *image_addr     Ҫ͵ͼַ
// ˵       image_size      ͼĴС
// @return      void
// Sample usage:                camera_send_image(DEBUG_UART_INDEX, &mt9v03x_image[0][0], MT9V03X_IMAGE_SIZE);
//-------------------------------------------------------------------------------------------------------------------
void camera_send_image (uart_index_enum uartn, const uint8 *image_addr, uint32 image_size)
{
    zf_assert(NULL != image_addr);
    // 
    uart_write_buffer(uartn, camera_send_image_frame_header, 4);

    // ͼ
    uart_write_buffer(uartn, (uint8 *)image_addr, image_size);
}

//-------------------------------------------------------------------------------------------------------------------
//      ͷ FIFO ʼ
// ˵     void
// ز     void
// ʹʾ     camera_fifo_init();
// עϢ
//-------------------------------------------------------------------------------------------------------------------
void camera_fifo_init (void)
{
    fifo_init(&camera_receiver_fifo, FIFO_DATA_8BIT, camera_receiver_buffer, CAMERA_RECEIVER_BUFFER_SIZE);
}


//-------------------------------------------------------------------------------------------------------------------
//        ͷɼʼ
// ˵       image_size      ͼĴС
// @return      void
// ˵       image_size      ͼĴС
// ˵       data_addr       Դַ
// ˵       buffer_addr     ͼ񻺳ַ
// @return      void
// Sample usage:                camera_init();
//-------------------------------------------------------------------------------------------------------------------
uint8 camera_init (uint8 *source_addr, uint8 *destination_addr, uint16 image_size)
{
    uint8 num;
    uint8 link_list_num;
    switch(camera_type)
    {
        case CAMERA_BIN_IIC:                                                    // IIC С
        case CAMERA_BIN_UART:                                                   // UART С
            for(num = 0; num < 8; num ++)
            {
                gpio_init((gpio_pin_enum)(OV7725_DATA_PIN + num), GPI, GPIO_LOW, GPI_FLOATING_IN);
            }
            link_list_num = dma_init(OV7725_DMA_CH,
                                     source_addr,
                                     destination_addr,
                                     OV7725_PCLK_PIN,
                                     EXTI_TRIGGER_FALLING,
                                     image_size);
            exti_init(OV7725_VSYNC_PIN, EXTI_TRIGGER_FALLING);                  //ʼжϣΪ½شж
            break;
        case CAMERA_GRAYSCALE:                                                  // 
            for(num = 0; num < 8; num ++)
            {
                gpio_init((gpio_pin_enum)(MT9V03X_DATA_PIN + num), GPI, GPIO_LOW, GPI_FLOATING_IN);
            }
            link_list_num = dma_init(MT9V03X_DMA_CH,
                                     source_addr,
                                     destination_addr,
                                     MT9V03X_PCLK_PIN,
                                     EXTI_TRIGGER_RISING,
                                     image_size);                               // Ƶ300M ڶΪFALLING

            exti_init(MT9V03X_VSYNC_PIN, EXTI_TRIGGER_FALLING);                 // ʼжϣΪ½شж
            break;
        case CAMERA_COLOR:                                                      // ͫ
            for(num=0; num<8; num++)
            {
                gpio_init((gpio_pin_enum)(SCC8660_DATA_PIN + num), GPI, GPIO_LOW, GPI_FLOATING_IN);
            }

            link_list_num = dma_init(SCC8660_DMA_CH,
                                     source_addr,
                                     destination_addr,
                                     SCC8660_PCLK_PIN,
                                     EXTI_TRIGGER_RISING,
                                     image_size);                               // Ƶ300M ڶΪFALLING

            exti_init(SCC8660_VSYNC_PIN, EXTI_TRIGGER_FALLING);                 // ʼжϣΪ½شж
            break;
        default:
            break;
    }
    return link_list_num;
}
