/* --------------------------------------------------------------------------
 * Copyright (c) 2013-2016 ARM Limited. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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
 *
 * 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.
 *
 *      Name:    main.c
 *      Purpose: RTX for Kneron
 *
 *---------------------------------------------------------------------------*/

#include <string.h>
#include "project.h"

#include "kdrv_cmsis_core.h"
#include "kdrv_pinmux.h"
#include "kdrv_ddr.h"
#include "kdrv_system.h"
#include "kdrv_uart.h"
#include "kdrv_i2c.h"

#include "kmdw_memory.h"
#include "kmdw_console.h"
#include "kmdw_camera.h"


static uint32_t pinmux_array[PIN_NUM] = PINMUX_ARRAY;

typedef struct myCamera_ctx {
    bool init;
    enum camera_state state;
    uint32_t width;
    uint32_t height;
    uint32_t pixelformat;
} myCamera_exp_ctx;

myCamera_exp_ctx m_kdp_cam_exp_ctx[IMGSRC_NUM + 2] = {
    {false, CAMERA_STATE_IDLE, 0, 0, 0},
    {false, CAMERA_STATE_IDLE, 0, 0, 0},
};
static uint32_t myCamera_example_open(uint8_t cam_idx)
{
    uint32_t ret;

    struct cam_capability cap;
    struct cam_format fmt;

    char fmtstr[8];
    memset(&cap, 0, sizeof(cap));
    memset(&fmt, 0, sizeof(fmt));

    if (0 != (ret = kmdw_camera_open(cam_idx)))
        return ret;

    if (0 != (ret = kmdw_camera_get_device_info(cam_idx, &cap)))
        return ret;

    fmt.width = m_kdp_cam_exp_ctx[cam_idx].width;
    fmt.height = m_kdp_cam_exp_ctx[cam_idx].height;
    fmt.pixelformat = m_kdp_cam_exp_ctx[cam_idx].pixelformat;
    kmdw_printf("[%s] cam_idx:%d, width:%d, height:%d,  pixelformat: %d\n", __func__, cam_idx, fmt.width, fmt.height, fmt.pixelformat);
    if (0 != (ret = kmdw_camera_set_frame_format(cam_idx, (struct cam_format *)&fmt)))
        return ret;

    if (0 != (ret = kmdw_camera_get_frame_format(cam_idx, &fmt)))
        return ret;

    memset(fmtstr, 0, 8);
    memcpy(fmtstr, &fmt.pixelformat, 4);

    // two buffers for MIPI camera
    uint32_t buffer_addr[2] = {0};
    buffer_addr[0] = kmdw_ddr_reserve(1024*1024);
    buffer_addr[1] = kmdw_ddr_reserve(1024*1024);

    if (0 != (ret = kmdw_camera_buffer_init(cam_idx, buffer_addr[0], buffer_addr[1])))
        return ret;

    m_kdp_cam_exp_ctx[cam_idx].state = CAMERA_STATE_INITED;
    return 0;
}

static uint32_t myCamera_example_setting(uint8_t cam_idx, unsigned int width, unsigned int height, unsigned int pixelformat)
{
    if(true == m_kdp_cam_exp_ctx[cam_idx].init) {
        kmdw_printf("[%s] camera index %d is already initialized\n", __func__, cam_idx);
        return 1;
    }
    m_kdp_cam_exp_ctx[cam_idx].init = true;
    m_kdp_cam_exp_ctx[cam_idx].width = width;
    m_kdp_cam_exp_ctx[cam_idx].height = height;
    m_kdp_cam_exp_ctx[cam_idx].pixelformat = pixelformat;
    return 0;
}

static uint32_t myCamera_example_start(uint32_t cam_idx)
{
    uint32_t ret;

    if (0 != (ret = kmdw_camera_start(cam_idx, NULL))) {
        return ret;
    }

    m_kdp_cam_exp_ctx[cam_idx].state = CAMERA_STATE_RUNNING;
    return 0;
}
void myCameratest()
{
#if (IMGSRC_IN_0)
    myCamera_example_setting(0, IMGSRC_0_WIDTH, IMGSRC_0_HEIGHT, IMGSRC_0_FORMAT);
    myCamera_example_open(0);
    myCamera_example_start(0);
#endif
    kmdw_printf("============================================================================================\n");
    kmdw_printf("Camera dvp example :\n");
    kmdw_printf("Use customer's evb board to transfer color bar Raw8 yuv image to Kneron's evb board.\n");
    kmdw_printf("Please use keil command window to input save image cmd to store image from rgb/nir sensor.\n");
    kmdw_printf("    ex: save rgb.hex 0x62f42800, 0x62f42800+(640*480*2)\n");
    kmdw_printf("Then use thirdparty's tool to verify image.\n");
    kmdw_printf("rgb sensor : size 640*480*2, with color bar image \n");
    kmdw_printf("============================================================================================\n");
}

int main(void)
{
    SystemCoreClockUpdate();
    osKernelInitialize();

    kdrv_system_init();
    kdrv_system_init_ncpu();
    kdrv_ddr_system_init(DDR_INIT_ALL);
    kdrv_pinmux_initialize(PIN_NUM, pinmux_array);
    kmdw_ddr_init(DDR_HEAP_BEGIN, DDR_HEAP_END);
    kdrv_uart_initialize();

    kdrv_uart_console_init(MSG_PORT, MSG_PORT_BAUDRATE, NULL);
    kmdw_console_set_log_level_scpu(LOG_PROFILE);

    kmdw_camera_init();
    myCameratest();

    if (osKernelGetState() == osKernelReady)
    {
        osKernelStart();
    }

    while (1)
    {
    }
}
