306 lines
9.1 KiB
C
Executable File
306 lines
9.1 KiB
C
Executable File
/*
|
|
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. 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.
|
|
* 3. Neither the name of XRADIO TECHNOLOGY CO., LTD. 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.
|
|
*/
|
|
|
|
#if ((CONFIG_CHIP_ARCH_VER == 1) || (CONFIG_CHIP_ARCH_VER == 2))
|
|
#include "common/cmd/cmd_util.h"
|
|
#include "driver/component/csi_camera/camera.h"
|
|
#include "cmd_camera.h"
|
|
#include "kernel/os/os.h"
|
|
#include "driver/chip/hal_i2c.h"
|
|
|
|
//#define SENSOR_GC0308
|
|
#ifdef SENSOR_GC0308
|
|
#include "driver/component/csi_camera/gc0308/drv_gc0308.h"
|
|
|
|
#define SENSOR_FUNC_INIT HAL_GC0308_Init
|
|
#define SENSOR_FUNC_DEINIT HAL_GC0308_DeInit
|
|
#define SENSOR_FUNC_IOCTL HAL_GC0308_IoCtl
|
|
#else
|
|
#include "driver/component/csi_camera/gc0328c/drv_gc0328c.h"
|
|
|
|
#define SENSOR_FUNC_INIT HAL_GC0328C_Init
|
|
#define SENSOR_FUNC_DEINIT HAL_GC0328C_DeInit
|
|
#define SENSOR_FUNC_IOCTL HAL_GC0328C_IoCtl
|
|
#endif
|
|
|
|
#define CSI_JPEG_PSRAM_EN (1)
|
|
#if CSI_JPEG_PSRAM_EN
|
|
#include "sys/dma_heap.h"
|
|
|
|
#define CSI_JPEG_PSRAM_SIZE (520*1024)
|
|
#endif
|
|
|
|
#define CSI_JPEG_MEMPART_EN (0)
|
|
#if CSI_JPEG_MEMPART_EN
|
|
#define CSI_JPEG_BUFF_SIZE (8*1024)
|
|
#else
|
|
#define CSI_JPEG_BUFF_SIZE (45*1024)
|
|
#endif
|
|
|
|
#define CSI_JPEG_VIDEO_EN (0)
|
|
#define CSI_JPEG_ONLINE_EN (1)
|
|
#define CSI_JPEG_SRAM_SIZE (100*1024)
|
|
|
|
#define IMAGE_SENSOR_I2CID I2C0_ID
|
|
#define SENSOR_RESET_PIN GPIO_PIN_15
|
|
#define SENSOR_RESET_PORT GPIO_PORT_A
|
|
#define SENSOR_POWERDOWN_PIN GPIO_PIN_14
|
|
#define SENSOR_POWERDOWN_PORT GPIO_PORT_A
|
|
|
|
static uint8_t *gmemaddr;
|
|
static CAMERA_Mgmt mem_mgmt;
|
|
|
|
static CAMERA_Cfg camera_cfg = {
|
|
.jpeg_cfg.jpeg_en = 1,
|
|
.jpeg_cfg.quality = 64,
|
|
.jpeg_cfg.jpeg_clk = 0, //no use
|
|
.jpeg_cfg.memPartEn = CSI_JPEG_MEMPART_EN,
|
|
.jpeg_cfg.memPartNum = CSI_JPEG_MEMPART_EN ? JPEG_MEM_BLOCK4 : 0,
|
|
.jpeg_cfg.jpeg_mode = CSI_JPEG_ONLINE_EN ? JPEG_MOD_ONLINE : JPEG_MOD_OFFLINE,
|
|
.jpeg_cfg.width = 640,
|
|
.jpeg_cfg.height = 480,
|
|
|
|
.csi_cfg.csi_clk = 24000000, // no use
|
|
|
|
/* sensor config */
|
|
.sensor_cfg.i2c_id = IMAGE_SENSOR_I2CID,
|
|
.sensor_cfg.pwcfg.Pwdn_Port = SENSOR_POWERDOWN_PORT,
|
|
.sensor_cfg.pwcfg.Reset_Port = SENSOR_RESET_PORT,
|
|
.sensor_cfg.pwcfg.Pwdn_Pin = SENSOR_POWERDOWN_PIN,
|
|
.sensor_cfg.pwcfg.Reset_Pin = SENSOR_RESET_PIN,
|
|
|
|
.sensor_func.init = SENSOR_FUNC_INIT,
|
|
.sensor_func.deinit = SENSOR_FUNC_DEINIT,
|
|
.sensor_func.ioctl = SENSOR_FUNC_IOCTL,
|
|
};
|
|
|
|
static int camera_mem_create(CAMERA_JpegCfg *jpeg_cfg, CAMERA_Mgmt *mgmt)
|
|
{
|
|
uint8_t *addr;
|
|
uint8_t *end_addr;
|
|
|
|
#if CSI_JPEG_PSRAM_EN
|
|
addr = (uint8_t *)dma_malloc(CSI_JPEG_PSRAM_SIZE, DMAHEAP_PSRAM);
|
|
if (addr == NULL) {
|
|
CMD_SYSLOG("malloc fail\n");
|
|
return -1;
|
|
}
|
|
cmd_memset(addr, 0, CSI_JPEG_PSRAM_SIZE);
|
|
end_addr = addr + CSI_JPEG_PSRAM_SIZE;
|
|
#else
|
|
addr = (uint8_t *)cmd_malloc(CSI_JPEG_SRAM_SIZE);//imgbuf;
|
|
if (addr == NULL) {
|
|
CMD_SYSLOG("malloc fail\n");
|
|
return -1;
|
|
}
|
|
cmd_memset(addr, 0, CSI_JPEG_SRAM_SIZE);
|
|
end_addr = addr + CSI_JPEG_SRAM_SIZE;
|
|
#endif
|
|
|
|
CMD_SYSLOG("malloc addr: %p -> %p\n", addr, end_addr);
|
|
|
|
mgmt->yuv_buf.addr = (uint8_t *)ALIGN_16B((uint32_t)addr);
|
|
mgmt->yuv_buf.size = camera_cfg.jpeg_cfg.width * camera_cfg.jpeg_cfg.height / 2 * 3;
|
|
|
|
#if CSI_JPEG_ONLINE_EN
|
|
mgmt->jpeg_buf[0].addr = (uint8_t *)ALIGN_1K((uint32_t)addr + CAMERA_JPEG_HEADER_LEN);
|
|
#if (CSI_JPEG_VIDEO_EN && !CSI_JPEG_MEMPART_EN)
|
|
mgmt->jpeg_buf[1].addr = (uint8_t *)ALIGN_1K(
|
|
(uint32_t)mgmt->jpeg_buf[0].addr + CSI_JPEG_BUFF_SIZE + CAMERA_JPEG_HEADER_LEN);
|
|
mgmt->jpeg_buf[1].size = CSI_JPEG_BUFF_SIZE;
|
|
#endif
|
|
#else
|
|
mgmt->jpeg_buf[0].addr = (uint8_t *)ALIGN_1K(
|
|
(uint32_t)mgmt->yuv_buf.addr + CAMERA_JPEG_HEADER_LEN + mgmt->yuv_buf.size);//after yuv data
|
|
#endif
|
|
mgmt->jpeg_buf[0].size = CSI_JPEG_BUFF_SIZE;
|
|
|
|
if ((mgmt->yuv_buf.addr + mgmt->yuv_buf.size) > end_addr ||
|
|
(mgmt->jpeg_buf[0].addr + mgmt->jpeg_buf[0].size) > end_addr) {
|
|
CMD_ERR("aadr exceeded\n");
|
|
return -1;
|
|
}
|
|
gmemaddr = addr;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void camera_mem_destroy(void)
|
|
{
|
|
if (gmemaddr) {
|
|
#if CSI_JPEG_PSRAM_EN
|
|
dma_free(gmemaddr, DMAHEAP_PSRAM);
|
|
#else
|
|
cmd_free(gmemaddr);
|
|
#endif
|
|
gmemaddr = NULL;
|
|
}
|
|
}
|
|
|
|
enum cmd_status cmd_camera_init_exec(char *cmd)
|
|
{
|
|
|
|
/* malloc mem */
|
|
cmd_memset(&mem_mgmt, 0, sizeof(CAMERA_Mgmt));
|
|
if (camera_mem_create(&camera_cfg.jpeg_cfg, &mem_mgmt) != 0)
|
|
return CMD_STATUS_FAIL;
|
|
|
|
/* camera init */
|
|
camera_cfg.mgmt = &mem_mgmt;
|
|
if (HAL_CAMERA_Init(&camera_cfg) != HAL_OK) {
|
|
CMD_ERR("%s init fail\n", cmd);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
enum cmd_status cmd_camera_cap_one_image_exec(char *cmd)
|
|
{
|
|
int i;
|
|
uint8_t *addr;
|
|
int size;
|
|
CAMERA_JpegBuffInfo jpeg_info;
|
|
|
|
size = HAL_CAMERA_CaptureImage(CAMERA_OUT_JPEG, &jpeg_info, 1);
|
|
if (size < 0) {
|
|
CMD_ERR("cap one image failed\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
CMD_SYSLOG("fm_szie %d\n", jpeg_info.size);
|
|
|
|
/* jpeg header data*/
|
|
addr = mem_mgmt.jpeg_buf[jpeg_info.buff_index].addr - CAMERA_JPEG_HEADER_LEN;
|
|
for (i = 0; i < CAMERA_JPEG_HEADER_LEN; i++)
|
|
CMD_SYSLOG("%02x ", addr[i]);
|
|
|
|
/* jpeg body data*/
|
|
for (i = 0; i < jpeg_info.size; i++) {
|
|
addr = mem_mgmt.jpeg_buf[jpeg_info.buff_index].addr;
|
|
CMD_SYSLOG("%02x ", addr[i]);
|
|
}
|
|
CMD_SYSLOG("\n write jpeg ok\n");
|
|
|
|
/* yuv420 NV12 data */
|
|
if (camera_cfg.jpeg_cfg.jpeg_mode == JPEG_MOD_OFFLINE) {
|
|
for (i = 0; i < camera_cfg.jpeg_cfg.width*camera_cfg.jpeg_cfg.height*3/2; i++)
|
|
CMD_SYSLOG("%02x ", mem_mgmt.yuv_buf.addr[i]);
|
|
CMD_SYSLOG("\n write yuv420 nv12 ok\n");
|
|
}
|
|
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
/* user need quickly take data away, otherwise easy data coverage */
|
|
/* need pixel small, the cmd example suppose the data can not bigger
|
|
* than 20k, you can set pixel width 160,height 120;
|
|
*/
|
|
enum cmd_status cmd_camera_cap_video_exec(char *cmd)
|
|
{
|
|
int i;
|
|
uint8_t *tmp_buf[2];
|
|
uint32_t tmp_size[2];
|
|
CAMERA_JpegBuffInfo jpeg_info;
|
|
|
|
tmp_buf[0] = (uint8_t *)cmd_malloc(30 * 1024);
|
|
if (tmp_buf[0] == NULL) {
|
|
CMD_ERR("malloc tmp_buf[0] failed\n");
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
tmp_buf[1] = (uint8_t *)cmd_malloc(30 * 1024);
|
|
if (tmp_buf[1] == NULL) {
|
|
CMD_ERR("malloc tmp_buf[1] failed\n");
|
|
cmd_free(tmp_buf[0]);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
cmd_memset(tmp_buf[0], 0, 30 * 1024);
|
|
cmd_memset(tmp_buf[1], 0, 30 * 1024);
|
|
|
|
if (HAL_CAMERA_CaptureVideoStart() != HAL_OK) {
|
|
CMD_ERR("start video failed\n");
|
|
cmd_free(tmp_buf[0]);
|
|
cmd_free(tmp_buf[1]);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) { /* for example, 2 frame continue */
|
|
int ret = HAL_CAMERA_CaptureVideoData(&jpeg_info);
|
|
CMD_SYSLOG("frame index=%d size=%d\n", jpeg_info.buff_index, jpeg_info.size);
|
|
if (ret != 0) {
|
|
CMD_ERR("cap video image failed\n");
|
|
cmd_free(tmp_buf[0]);
|
|
cmd_free(tmp_buf[1]);
|
|
return CMD_STATUS_FAIL;
|
|
}
|
|
tmp_size[i] = jpeg_info.size + CAMERA_JPEG_HEADER_LEN;
|
|
cmd_memcpy(tmp_buf[i],
|
|
mem_mgmt.jpeg_buf[jpeg_info.buff_index].addr - CAMERA_JPEG_HEADER_LEN,
|
|
jpeg_info.size + CAMERA_JPEG_HEADER_LEN);
|
|
}
|
|
|
|
HAL_CAMERA_CaptureVideoStop();
|
|
|
|
for (i = 0; i < tmp_size[0]; i++) { /* first frame */
|
|
CMD_SYSLOG("%02x ", *(tmp_buf[0] + i));
|
|
}
|
|
CMD_SYSLOG("\nwrite jpeg ok\n");
|
|
|
|
for (i = 0; i < tmp_size[1]; i++) { /* sencond frame */
|
|
CMD_SYSLOG("%02x ", *(tmp_buf[1] + i));
|
|
}
|
|
CMD_SYSLOG("\nwrite jpeg ok\n");
|
|
|
|
cmd_free(tmp_buf[0]);
|
|
cmd_free(tmp_buf[1]);
|
|
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
enum cmd_status cmd_camera_deinit_exec(char *cmd)
|
|
{
|
|
HAL_CAMERA_DeInit();
|
|
|
|
camera_mem_destroy();
|
|
|
|
return CMD_STATUS_OK;
|
|
}
|
|
|
|
static const struct cmd_data g_camera_cmds[] = {
|
|
{ "init", cmd_camera_init_exec},
|
|
{ "cap_one_image", cmd_camera_cap_one_image_exec},
|
|
{ "cap_video_image", cmd_camera_cap_video_exec},
|
|
{ "deinit", cmd_camera_deinit_exec},
|
|
};
|
|
|
|
enum cmd_status cmd_camera_exec(char *cmd)
|
|
{
|
|
return cmd_exec(cmd, g_camera_cmds, cmd_nitems(g_camera_cmds));
|
|
}
|
|
#endif
|