This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TDA4VM: question about csitx data

Part Number: TDA4VM


HI TI:

now i add csitx node in app_multi_cam demo. my path is csirx->capture.obj->ldc.obj->mosaic.obj->display.obj. now i add csitx_image and input is captureObj.raw_image_arr[0].  create tx_frame .and then i initializing transmit buffer ,create csitx node. vxGraphParameterEnqueueReadyRef and vxGraphParameterDequeueDoneRef in app_run_graph_for_one_frame_pipeline. now demo can run normal,but csitx data is wrong. i want csitx send captureObj.raw_image_arr. how to modify it?

diff --git a/apps/basic_demos/app_multi_cam/main.c b/apps/basic_demos/app_multi_cam/main.c
index 808566c..bf105db 100755
--- a/apps/basic_demos/app_multi_cam/main.c
+++ b/apps/basic_demos/app_multi_cam/main.c
@@ -66,6 +66,9 @@
 #include <utils/grpx/include/app_grpx.h>
 #include <utils/hwa/include/app_hwa_api.h>
 #include <VX/vx_khr_pipelining.h>
+#include <VX/vx.h>
+#include <TI/tivx.h>
+#include <TI/tivx_config.h>
 
 #include "app_common.h"
 #include "app_sensor_module.h"
@@ -76,10 +79,54 @@
 #include "app_img_mosaic_module.h"
 #include "app_display_module.h"
 #include "app_test.h"
+
+#define VX_CALL(fn_call) fn_call
+#define VX_CALL_(ret_code, fn_call) fn_call
+#define VX_CALL_RET(fn_call) fn_call
 
 #define APP_BUFFER_Q_DEPTH   (4)
 #define APP_PIPELINE_DEPTH   (7)
 
+#define CSITX_WDP (0)
+#define CSITX_NODE_W (1)
+#define CSITX_FORMAT           (VX_DF_IMAGE_YUYV)
+#define NUM_CHANNELS (1)
+#define CSITX_INST_ID       (0U)
+#define CAPT_INST_ID        (0U)
+
+#define CSITX_LANE_BAND_SPEED       (TIVX_CSITX_LANE_BAND_SPEED_1200_TO_1400_MBPS)
+#define CSIRX_LANE_BAND_SPEED       (TIVX_CAPTURE_LANE_BAND_SPEED_720_TO_800_MBPS)
+#define CSITX_LANE_SPEED_MBPS       (800U)
 typedef struct {
 
     SensorObj     sensorObj;
@@ -129,10 +176,54 @@ typedef struct {
     vx_uint32 enable_configure_hwa_freq;
     vx_uint32 hwa_freq_config;
 
+    int32_t modify_width;
+    int32_t modify_height;
 } AppObj;
 
 AppObj gAppObj;
 
+#if (CSITX_NODE_W == 1U)
+typedef struct {
+    /*! csitx node object */
+    vx_node  csitx_node;
+
+    /*! Display node user data object for configuration of display node */
+    vx_user_data_object csitx_params_obj;
+
+    /*! Display node params structure to initialize disp_params_obj object */
+    tivx_display_params_t csitx_params;
+
+    /*! Display option value; must be set to 1 to use the display */
+    vx_int32 csitx_option;
+
+    /*! Display node graph parameter index */
+    vx_int32 graph_parameter_index;
+
+    /*! Name of display module */
+    vx_char objName[512];
+
+} CsiTxObj;
+
+CsiTxObj gCsiTxObj;
+
+static vx_int32 csitx_index;
+static vx_object_array tx_frame = 0;
+static vx_user_data_object csitx_config;
+static tivx_csitx_params_t local_csitx_config;
+static uint32_t  loopCnt;
+static vx_node csitx_node = 0;
+#endif
+

 static void app_parse_cmd_line_args(AppObj *obj, vx_int32 argc, vx_char *argv[]);
 static vx_status app_init(AppObj *obj);
 static void app_deinit(AppObj *obj);
@@ -522,6 +613,26 @@ static void app_parse_cfg_file(AppObj *obj, vx_char *cfg_file_name)
                     obj->captureObj.test_mode = atoi(token);
                 }
             }
+            else
+            if(strcmp(token, "modify_width")==0)
+            {
+                token = strtok(NULL, s);
+                if(token != NULL)
+                {
+                    obj->modify_width = atoi(token);
+                    //obj->displayObj.display_width = obj->modify_width;
+                }
+            }
+            else
+            if(strcmp(token, "modify_height")==0)
+            {
+                token = strtok(NULL, s);
+                if(token != NULL)
+                {
+                    obj->modify_height = atoi(token);
+                    //obj->displayObj.display_height = obj->modify_height;
+                }
+            }
         }
     }
 
@@ -621,7 +732,11 @@ vx_int32 app_multi_cam_main(vx_int32 argc, vx_char* argv[])
 
     /* Querry sensor parameters */
     status = app_querry_sensor(&obj->sensorObj);
-    if(1 == obj->sensorObj.sensor_out_format)
+
+    obj->sensorObj.sensorParams.sensorInfo.raw_params.width =  obj->sensorObj.image_width = obj->modify_width;
+    obj->sensorObj.sensorParams.sensorInfo.raw_params.height =  obj->sensorObj.image_height = obj->modify_height;
+    printf("wdp111 image width is %d,height is %d\n",obj->sensorObj.image_width,obj->sensorObj.image_height);
+    if (1 == obj->sensorObj.sensor_out_format)
     {
         printf("YUV Input selected. VISS, AEWB and Mosaic nodes will be bypassed. \n");
         obj->enable_viss = 0;
@@ -821,6 +936,16 @@ static void app_deinit(AppObj *obj)
         APP_PRINTF("Img Mosaic deinit done!\n");
     }
 
+    #if (CSITX_NODE_W ==1U )
+    vxReleaseObjectArray(&tx_frame);
+    vxReleaseUserDataObject(&csitx_config);
+    #endif
     app_deinit_display(&obj->displayObj);
     APP_PRINTF("Display deinit done!\n");
 
@@ -853,6 +978,15 @@ static void app_delete_graph(AppObj *obj)
     app_delete_img_mosaic(&obj->imgMosaicObj);
     APP_PRINTF("Img Mosaic delete done!\n");
 
+
+    #if (CSITX_NODE_W == 1U)
+    vxReleaseNode(&csitx_node);
+    #endif
     app_delete_display(&obj->displayObj);
     APP_PRINTF("Display delete done!\n");
 
@@ -956,6 +1170,90 @@ static vx_status app_create_graph(AppObj *obj)
         APP_PRINTF("Display graph done!\n");
     }
 
+    #if (CSITX_NODE_W ==1U)
+    vx_image csitx_image;
+    csitx_image = (vx_image)vxGetObjectArrayItem(obj->captureObj.raw_image_arr[0], 0); //obj->imgMosaicObj.output_image[0];
+    //csitx_image = vxCreateImage(obj->context, 1920, 1080, CSITX_FORMAT);
+    printf("wdp111 csitx image is from mosaic image\n");
+    tx_frame = vxCreateObjectArray(obj->context, (vx_reference)csitx_image, NUM_CHANNELS);
+    status = vxGetStatus((vx_reference)tx_frame);
+    if (status == VX_SUCCESS){
+        printf("wdp111 tx_frame create done!!!!\n");
+    }
+    printf("wdp111 start CSITX Config initialization\n");
+
+    #if 1
+    vx_map_id map_id;
+    vx_int32 i,j;
+    vx_imagepatch_addressing_t addr;
+    uint16_t *ptr = NULL;
+    uint16_t frmIdx;
+    tivx_raw_image tx_frame_array_item=0;
+    vx_rectangle_t rect;
+    vx_int16 width, height;
+    width = 1936;
+    height = 1096;
+    rect.start_x = 0;
+    rect.start_y = 0;
+    rect.end_x = width;
+    rect.end_y = height;
+
+    printf("Initializing Transmit Buffers...\n");
+    for (frmIdx = 0U ; frmIdx < NUM_CHANNELS ; frmIdx++)
+    {
+        tx_frame_array_item = (tivx_raw_image)vxGetObjectArrayItem(tx_frame , frmIdx);
+        /* Initialize raw_image with running pattern using WRITE ONLY MAP */
+        VX_CALL(tivxMapRawImagePatch(tx_frame_array_item, &rect, 0U, &map_id, &addr, (void **)&ptr,
+                                        VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, TIVX_RAW_IMAGE_PIXEL_BUFFER));
+        if (ptr != NULL){
+            printf("wdp111 ptr is not null\n");
+        }
+        for (i = 0; i <height; i++)
+        {
+            for(j=0; j<width; j++)
+            {
+                ptr[((i*width)+j)] = (j + frmIdx);
+            }
+        }
+        /* Do cache operations on each buffer to avoid coherency issues */
+        appMemCacheWb(ptr, (width * height * sizeof(uint16_t)));
+        VX_CALL(tivxUnmapRawImagePatch(tx_frame_array_item, map_id));
+        VX_CALL(tivxReleaseRawImage(&tx_frame_array_item));
+    }
+    printf("Initializing Transmit Buffers Done.\n");
+    #endif
+    /* CSITX Config initialization */
+    tivx_csitx_params_init(&local_csitx_config);
+    local_csitx_config.numInst = 1U;
+    local_csitx_config.numCh = NUM_CHANNELS;
+    local_csitx_config.instId[0U] = CSITX_INST_ID;
+    local_csitx_config.instCfg[0U].rxCompEnable = (uint32_t)vx_true_e;
+    local_csitx_config.instCfg[0U].rxv1p3MapEnable = (uint32_t)vx_true_e;
+    local_csitx_config.instCfg[0U].laneBandSpeed = CSITX_LANE_BAND_SPEED;
+    local_csitx_config.instCfg[0U].laneSpeedMbps = CSITX_LANE_SPEED_MBPS;
+    local_csitx_config.instCfg[0U].numDataLanes = 4U;
+    for (loopCnt = 0U;
+         loopCnt < local_csitx_config.instCfg[0U].numDataLanes;
+         loopCnt++)
+    {
+        local_csitx_config.instCfg[0U].lanePolarityCtrl[loopCnt] = 0u;
+        }
+        for (loopCnt = 0U; loopCnt < NUM_CHANNELS; loopCnt++)
+        {
+            local_csitx_config.chVcNum[loopCnt]   = loopCnt;
+            local_csitx_config.chInstMap[loopCnt] = CSITX_INST_ID;
+        }
+
+    //ASSERT_VX_OBJECT(csitx_config = vxCreateUserDataObject(obj->context, "tivx_csitx_params_t", sizeof(tivx_csitx_params_t), &local_csitx_config), (enum vx_type_e)VX_TYPE_USER_DATA_OBJECT);
+    csitx_config = vxCreateUserDataObject(obj->context, "tivx_csitx_params_t", sizeof(tivx_csitx_params_t), &local_csitx_config);
+    //ASSERT_VX_OBJECT(csitx_node = tivxCsitxNode(csitx_graph, csitx_config, tx_frame), VX_TYPE_NODE);
+    csitx_node = tivxCsitxNode(obj->graph, csitx_config, tx_frame);
+    VX_CALL(vxSetNodeTarget(csitx_node, VX_TARGET_STRING, TIVX_TARGET_CSITX));
+    status = vxGetStatus((vx_reference)csitx_node);
+    if (status == VX_SUCCESS){
+        printf("wdp111 csitx_node create done!!!!\n");
+    }
+    #endif
     if(status == VX_SUCCESS)
     {
         graph_parameter_index = 0;
@@ -976,6 +1274,16 @@ static vx_status app_create_graph(AppObj *obj)
             graph_parameter_index++;
         }
 
+        #if (CSITX_NODE_W ==1U)
+        /* input @ node index 0, becomes csitx_graph parameter 1 */
+        add_graph_parameter_by_node_index(obj->graph, csitx_node, 1);
+        csitx_index = graph_parameter_index;
+        /* set csitx_graph schedule config such that csitx_graph parameter @ index 0 and 1 are enqueuable */
+        graph_parameters_queue_params_list[graph_parameter_index].graph_parameter_index = graph_parameter_index;
+        graph_parameters_queue_params_list[graph_parameter_index].refs_list_size = 1;
+        graph_parameters_queue_params_list[graph_parameter_index].refs_list = (vx_reference*)&tx_frame;
+        graph_parameter_index++;
+        #endif
         status = vxSetGraphScheduleConfig(obj->graph,
                 VX_GRAPH_SCHEDULE_MODE_QUEUE_AUTO,
                 graph_parameter_index,
@@ -1075,6 +1383,12 @@ static vx_status app_run_graph_for_one_frame_pipeline(AppObj *obj, vx_int32 fram
         {
             status = vxGraphParameterEnqueueReadyRef(obj->graph, captureObj->graph_parameter_index, (vx_reference*)&obj->captureObj.raw_image_arr[obj->enqueueCnt], 1);
         }
+        #if (CSITX_NODE_W == 1U)
+        if (status == VX_SUCCESS)
+        {
+            status = vxGraphParameterEnqueueReadyRef(obj->graph, csitx_index, (vx_reference*)&tx_frame, 1);
+        }
+        #endif
         obj->enqueueCnt++;
         obj->enqueueCnt   = (obj->enqueueCnt  >= APP_BUFFER_Q_DEPTH)? 0 : obj->enqueueCnt;
         obj->pipeline++;
@@ -1092,6 +1406,14 @@ static vx_status app_run_graph_for_one_frame_pipeline(AppObj *obj, vx_int32 fram
         {
             status = vxGraphParameterEnqueueReadyRef(obj->graph, captureObj->graph_parameter_index, (vx_reference*)&obj->captureObj.raw_image_arr[obj->enqueueCnt], 1);
         }
+
+        #if (CSITX_NODE_W == 1U)
+        if (status == VX_SUCCESS)
+        {
+            status = vxGraphParameterEnqueueReadyRef(obj->graph, csitx_index, (vx_reference*)&tx_frame, 1);
+        }
+        #endif
+
         obj->enqueueCnt++;
         obj->enqueueCnt   = (obj->enqueueCnt  >= APP_BUFFER_Q_DEPTH)? 0 : obj->enqueueCnt;
         obj->pipeline++;
@@ -1105,6 +1427,23 @@ static vx_status app_run_graph_for_one_frame_pipeline(AppObj *obj, vx_int32 fram
 
         /* Dequeue input */
         status = vxGraphParameterDequeueDoneRef(obj->graph, captureObj->graph_parameter_index, (vx_reference*)&capture_input_arr, 1, &num_refs);
+
+        #if (CSITX_NODE_W == 1U)
+            APP_PRINTF("wdp111: trigger graph csitx node\n");
+            //uint32_t num_refs;
+            //vx_object_array transmitted_frames = NULL;
+            status = vxGraphParameterDequeueDoneRef(obj->graph, csitx_index, (vx_reference*)&tx_frame, 1, &num_refs);
+            if (status == VX_SUCCESS)
+            {
+                status = vxGraphParameterEnqueueReadyRef(obj->graph, csitx_index, (vx_reference *)&tx_frame, 1);
+                if(status == VX_SUCCESS)
+                {
+                    printf("wdp111 csitx dequeue and enqueue ok\n");
+                }
+            }
+        #endif
+
+

  • the sensor data is RAW12 resolution 1936*1096. csitx node path is csirx->capture.obj->csitxnode

  • Hi wu dunpeng,

    Any specific reason for transmitting raw12 data via CSITX? 

    Can you please refer to the example ti-processor-sdk-rtos-j721e-evm-08_01_00_13\tiovx\kernels_j7\hwa\test\test_csitx_csirx.c? This example transfers raw12 images via CSITX and captures them back via CSIRX. You could just change to do exactly opposite ie CSIRX -> CSITX..

    I will review your code and get back to you by this Friday. 

    Regards,

    Brijesh

  • HI TI:

    now i can send a static raw picture though csitx node. so the path csirx->capture.obj->csitxnode has no problem. now i want to ask how csitx transmit dynamic csirx data(sensor data). i use a ways tranmit dynamic picture in below code,but it is too slow.

    @@ -1105,6 +1427,23 @@ static vx_status app_run_graph_for_one_frame_pipeline(AppObj *obj, vx_int32 fram

    /* Dequeue input */
    status = vxGraphParameterDequeueDoneRef(obj->graph, captureObj->graph_parameter_index, (vx_reference*)&capture_input_arr, 1, &num_refs);
    +
    + #if (CSITX_NODE_W == 1U)
    + APP_PRINTF("wdp111: trigger graph csitx node\n");
    + //uint32_t num_refs;
    + //vx_object_array transmitted_frames = NULL;
    + status = vxGraphParameterDequeueDoneRef(obj->graph, csitx_index, (vx_reference*)&tx_frame, 1, &num_refs);

    vxStatus = tivxMapRawImagePatch(raw_image,
    + &rect,
    + 0,
    + &map_id,
    + &image_addr,
    + &data_ptr,
    + VX_READ_AND_WRITE,
    + VX_MEMORY_TYPE_HOST,
    + TIVX_RAW_IMAGE_PIXEL_BUFFER
    + );
    +
    + if(!data_ptr)
    + {
    + APP_PRINTF("data_ptr is NULL \n");
    + fclose(fp);
    + return VX_FAILURE;
    + }
    + num_bytes_read_from_file = 0;
    +
    + imgaddr_width = image_addr.dim_x;
    + imgaddr_height = image_addr.dim_y;
    + imgaddr_stride = image_addr.stride_y;
    +
    + printf("raw12:imgaddr_width = %d \timgaddr_height = %d \timgaddr_stride = %d\n", imgaddr_width, imgaddr_height, imgaddr_stride);
    +
    + for(i=0;i<imgaddr_height;i++)
    + {
    + num_bytes_read_from_file += fread(data_ptr, 1, imgaddr_width*num_bytes_per_pixel, fp);
    + data_ptr += imgaddr_stride;
    + }
    +
    + tivxUnmapRawImagePatch(raw_image, map_id);
    +


    + if (status == VX_SUCCESS)
    + {
    + status = vxGraphParameterEnqueueReadyRef(obj->graph, csitx_index, (vx_reference *)&tx_frame, 1);
    + if(status == VX_SUCCESS)
    + {
    + printf("wdp111 csitx dequeue and enqueue ok\n");
    + }
    + }
    + #endif
    +

  • so my question is how csitx buffer associate with csirx buffer? can It run like display node relate to capture node

  • Hi dunpeng wu,

    Yes, we can consider as if it is display/sink node, with the difference that there isn't any vsync interrupt and it works in burst mode. So as and when frame is available, TX would transmit the data, based on lane band speed.

    Regards,

    Brijesh

  • HI TI:

    how send csirx capture frame to csitx node?can you give the code? i have try

     raw_image_exemplar = (tivx_raw_image)vxGetObjectArrayItem(obj->captureObj.raw_image_arr[0], 0);

     tx_frame = vxCreateObjectArray(obj->context, (vx_reference)raw_image_exemplar, NUM_CHANNELS);

     csitx_node = tivxCsitxNode(obj->graph, csitx_config, tx_frame);

    but  when app_run_graph_for_one_frame_pipeline , it seems csitx node haven't get csirx capture node frame. so how to change the code? thanks a lot

  • HI TI:

    can anybody help to look this question? thanks very much

  • Hello Wu dunpeng,

    Is your CSIRX capture working fine? Because once you connect CSIRX to CSITX node, CSITX should get frames from CSIRX if it is working fine. There is no reason for it to not work.. 

    In addition, are you making capture/CSIRX output as graph parameter?

    Regards,

    Brijesh

  • HI TI:

     i'sure csirx capture working fine. what you mean making capture/CSIRX output as graph parameter?do you mean

    graph_parameter_index = 0;
    add_graph_parameter_by_node_index(obj->graph, obj->captureObj.node, 1);
    obj->captureObj.graph_parameter_index = graph_parameter_index;
    graph_parameters_queue_params_list[graph_parameter_index].graph_parameter_index = graph_parameter_index;
    graph_parameters_queue_params_list[graph_parameter_index].refs_list_size = APP_BUFFER_Q_DEPTH;
    graph_parameters_queue_params_list[graph_parameter_index].refs_list = (vx_reference*)&obj->captureObj.raw_image_arr[0];
    graph_parameter_index++;

  • can you help me to check my code? thanks very much4682.main.c

  • Hi We Dunpeng,

    I reviewed code, one comment i have is, why do you create new object array for the CSITX? can you use output object array of CSIRX to create CSITX node? 

    Regards,

    Brijesh

  • HI TI:

       i try it , the pipeline stop. now i use app_multi_cam demo and i only enable one camera. number of cameras is one. i'm sure with one camera sensor the app_multi_cam demo run normal before add csitx node code. so i doubt pipeline params set wrong.can you please check it. thanks very much.

    obj->csitx_node = tivxCsitxNode(obj->graph, csitx_config,  obj->captureObj.raw_image_arr[0]);

    /* input @ node index 0, becomes csitx_graph parameter 1 */
    add_graph_parameter_by_node_index(obj->graph, obj->csitx_node, 1);
    csitx_index = graph_parameter_index;
    /* set csitx_graph schedule config such that csitx_graph parameter @ index 0 and 1 are enqueuable */
    graph_parameters_queue_params_list[graph_parameter_index].graph_parameter_index = graph_parameter_index;
    graph_parameters_queue_params_list[graph_parameter_index].refs_list_size = APP_BUFFER_Q_DEPTH;
    graph_parameters_queue_params_list[graph_parameter_index].refs_list = (vx_reference*)&obj->captureObj.raw_image_arr[0];
    graph_parameter_index++;

     

  • and i also has some questions. does it need to create two threads? one for csirx another for csitx. csitx thread pipeline should run first then post event to csirx thread. and csirx need wait some time needed for DPHY hand shake. i see the test_csitx_csirx.c design like this.but it's csitx to csirx. so i invert it

  • Hi,

    add_graph_parameter_by_node_index(obj->graph, obj->csitx_node, 1);

    Why do you want to add CSITX as graph parameter? I think you just need one graph parameter, which is CSIRX output.

    and i also has some questions. does it need to create two threads?

    No, it is not required although possible. 

    Can you please updated multi-camera example and just use CSIRX and CSITX nodes, removing VISS, AEWB, LDC and Mosaic nodes? We can add nodes later if required.  Lets first get simple usecase of CSIRX-> CSITX working.. 

    Regards,

    Brijesh

  • HI TI:

    i will create a new thread for this questions. please close this thread.  thanks for support.