From d6c1573ac909f62409eee87c141045bc6b398bf1 Mon Sep 17 00:00:00 2001 From: Ligen Date: Tue, 30 Sep 2025 11:54:52 +0800 Subject: [PATCH 1/5] support HDZCS --- src/i2c_device.c | 70 ++++++++++++++++++++++++++----------------- src/i2c_device.h | 7 +++-- src/msp_displayport.c | 55 ++++++++++++++++++---------------- src/msp_displayport.h | 12 ++++---- 4 files changed, 82 insertions(+), 62 deletions(-) diff --git a/src/i2c_device.c b/src/i2c_device.c index 6a6a46b..cd395e9 100644 --- a/src/i2c_device.c +++ b/src/i2c_device.c @@ -140,6 +140,16 @@ void pca9557_set(uint8_t reg, uint8_t val) { I2C_Write8(ADDR_PCA9557, reg, val); } +// Read from 3 camera switch +uint8_t hdzcs_get(uint8_t reg) { + return I2C_Read8(ADDR_HDZCS, reg); +} + +// Write to 3 camera switch +void hdzcs_set(uint8_t reg, uint8_t val) { + I2C_Write8_Wait(10, ADDR_HDZCS, reg, val); +} + uint8_t get_camera_switch_type(void) { uint8_t camera_switch = SWITCH_TYPE_NONE; @@ -147,14 +157,15 @@ uint8_t get_camera_switch_type(void) { camera_switch = SWITCH_TYPE_PI4IO; } else if (pca9557_get(0x02) == 0xF0) { // polarity inversion register defaults to 0xF0 camera_switch = SWITCH_TYPE_PCA9557; + } else if (hdzcs_get(0xff) == 0x01) { + camera_switch = SWITCH_TYPE_HDZCS; } return camera_switch; } void select_camera(uint8_t camera_id) { - if (g_camera_switch) - { + if (g_camera_switch) { // Check camera id is within range, else default to 1 uint8_t camera = (camera_id == 0 || camera_id > g_max_camera) ? 1 : camera_id; if (g_camera_id != camera) { @@ -162,26 +173,28 @@ void select_camera(uint8_t camera_id) { uint8_t command; switch (g_camera_id) { - case 1: - default: - command = (g_camera_switch == SWITCH_TYPE_PI4IO) ? 0x11 : 0x1B; - break; - case 2: - command = (g_camera_switch == SWITCH_TYPE_PI4IO) ? 0x64 : 0x16; - break; - case 3: - command = (g_camera_switch == SWITCH_TYPE_PI4IO) ? 0x11 : 0x0D; - break; + case 1: + default: + command = (g_camera_switch == SWITCH_TYPE_PI4IO) ? 0x11 : 0x1B; + break; + case 2: + command = (g_camera_switch == SWITCH_TYPE_PI4IO) ? 0x64 : 0x16; + break; + case 3: + command = (g_camera_switch == SWITCH_TYPE_PI4IO) ? 0x11 : 0x0D; + break; } if (g_camera_switch == SWITCH_TYPE_PI4IO) { pi4io_set(0x05, command); - } - else { // SWITCH_TYPE_PCA9557 + } else if (g_camera_switch == SWITCH_TYPE_PCA9557) { // SWITCH_TYPE_PCA9557 pca9557_set(0x01, command); - WAIT(200); // wait for camera power up + WAIT(200); // wait for camera power up + } else if (g_camera_switch == SWITCH_TYPE_HDZCS) { + hdzcs_set(0x00, g_camera_id); } - camera_switch_profile(); + camera_init(); + // camera_switch_profile(); } } } @@ -189,21 +202,22 @@ void select_camera(uint8_t camera_id) { void camera_switch_init() { g_camera_switch = get_camera_switch_type(); if (g_camera_switch == SWITCH_TYPE_PI4IO) { - //pi4io_set(0x01, 0xFF); // reset - pi4io_set(0x0B, 0xFF); // Disable pullup/pulldown resistors - pi4io_set(0x11, 0xFF); // Disable interrupts on inputs - pi4io_get(0x13); // De-assert the interrrupt - pi4io_set(0x03, 0x77); // Set P3 and P7 as inputs - pi4io_set(0x07, 0x00); // Set outputs to follow the output port register - pi4io_set(0x05, 0x11); // camera 1 default + // pi4io_set(0x01, 0xFF); // reset + pi4io_set(0x0B, 0xFF); // Disable pullup/pulldown resistors + pi4io_set(0x11, 0xFF); // Disable interrupts on inputs + pi4io_get(0x13); // De-assert the interrrupt + pi4io_set(0x03, 0x77); // Set P3 and P7 as inputs + pi4io_set(0x07, 0x00); // Set outputs to follow the output port register + pi4io_set(0x05, 0x11); // camera 1 default g_max_camera = PI4IO_CAMS; } else if (g_camera_switch == SWITCH_TYPE_PCA9557) { g_max_camera = PCA9557_CAMS; - pca9557_set(0x03, 0x00); // all outputs - pca9557_set(0x01, 0x1B); // camera 1 default - WAIT(200); // wait for camera power up - } else { - g_camera_id = 1; + pca9557_set(0x03, 0x00); // all outputs + pca9557_set(0x01, 0x1B); // camera 1 default + WAIT(200); // wait for camera power up + } else if (g_camera_switch == SWITCH_TYPE_HDZCS) { + g_max_camera = HDZCS_CAMS; + hdzcs_set(0x00, 0x01); // camera 1 default } } diff --git a/src/i2c_device.h b/src/i2c_device.h index 87a273d..30d961c 100644 --- a/src/i2c_device.h +++ b/src/i2c_device.h @@ -13,16 +13,19 @@ #define ADDR_RUNCAM 0x21 #define ADDR_PI4IO 0x43 // 2 camera switch #define ADDR_PCA9557 0x18 // 3 camera switch +#define ADDR_HDZCS 0x60 typedef enum { SWITCH_TYPE_NONE, SWITCH_TYPE_PI4IO, - SWITCH_TYPE_PCA9557 + SWITCH_TYPE_PCA9557, + SWITCH_TYPE_HDZCS, } switch_type_e; typedef enum { PI4IO_CAMS = 2, - PCA9557_CAMS = 3 + PCA9557_CAMS = 3, + HDZCS_CAMS = 3, } switch_cams_e; void set_segment(uint32_t val); diff --git a/src/msp_displayport.c b/src/msp_displayport.c index d9330d8..86ba99d 100644 --- a/src/msp_displayport.c +++ b/src/msp_displayport.c @@ -771,7 +771,7 @@ void msp_send_type(uint8_t dl, uint8_t version, uint8_t header_type) { } void msp_send_command(uint8_t dl, uint8_t version) { - msp_send_type(dl, version, MSP_HEADER_COMMAND); + msp_send_type(dl, version, MSP_HEADER_COMMAND); } void msp_send_response(uint8_t dl, uint8_t version) { @@ -810,14 +810,12 @@ void msp_send_cmd_tx_v2(uint16_t request) { msp_tx(msp_send_header_v2(0, request)); } - // Send requests to the FC. -void msp_cmd_tx() -{ +// Send requests to the FC. +void msp_cmd_tx() { if ((fc_lock & FC_STARTUP_LOCK) == 0) { if ((fc_lock & FC_VARIANT_LOCK) == 0) { msp_send_cmd_tx(MSP_FC_VARIANT); - } - else if ((fc_lock & FC_VTX_CONFIG_LOCK) == 0) { + } else if ((fc_lock & FC_VTX_CONFIG_LOCK) == 0) { msp_send_cmd_tx(MSP_GET_VTX_CONFIG); } else { fc_lock |= FC_STARTUP_LOCK; @@ -836,7 +834,7 @@ void msp_cmd_tx() msp_send_cmd_tx(MSP_GET_OSD_CANVAS); msp_send_cmd_tx(MSP_STATUS); } - + // These messages are not required when armed. if (!g_IS_ARMED) { if (timer_2hz) { // in case box ids move (say during configuration) @@ -1030,21 +1028,21 @@ void parse_status() { uint8_t isBTFL = msp_cmp_fc_variant("BTFL"); if (g_arm_mask) { - offset = (isBTFL && g_arm_page > 3) ? 12 : 6; - g_IS_ARMED = msp_rx_buf[offset+g_arm_page] & g_arm_mask; + offset = (isBTFL && g_arm_page > 3) ? 12 : 6; + g_IS_ARMED = msp_rx_buf[offset + g_arm_page] & g_arm_mask; } if (g_boxCamera1_mask) { - offset = (isBTFL && g_boxCamera1_page > 3) ? 12 : 6; - if (msp_rx_buf[offset+g_boxCamera1_page] & g_boxCamera1_mask) { + offset = (isBTFL && g_boxCamera1_page > 3) ? 12 : 6; + if (msp_rx_buf[offset + g_boxCamera1_page] & g_boxCamera1_mask) { camSelected = camera_switch(2); } } - + if (!camSelected && g_boxCamera2_mask) { - offset = (isBTFL && g_boxCamera2_page > 3) ? 12 : 6; - if (msp_rx_buf[offset+g_boxCamera2_page] & g_boxCamera2_mask) { - if (g_camera_switch == SWITCH_TYPE_PCA9557) { + offset = (isBTFL && g_boxCamera2_page > 3) ? 12 : 6; + if (msp_rx_buf[offset + g_boxCamera2_page] & g_boxCamera2_mask) { + if (g_camera_switch == SWITCH_TYPE_PCA9557 || g_camera_switch == SWITCH_TYPE_HDZCS) { camSelected = camera_switch(3); } } @@ -1052,7 +1050,7 @@ void parse_status() { if (!camSelected) { camera_switch(1); - } + } #if (0) g_IS_PARALYZE = (msp_rx_buf[9] & 0x80); @@ -1090,7 +1088,7 @@ void parse_boxids(uint8_t msgLen) { g_arm_mask = g_boxCamera1_mask = g_boxCamera2_mask = 0; - for (idx = 0, boxCount = 0; idx < msgLen && boxCount < 4 ; idx++) { + for (idx = 0, boxCount = 0; idx < msgLen && boxCount < 4; idx++) { if (msp_rx_buf[idx] == armBox) { g_arm_page = idx / 8; g_arm_mask = 1 << (idx % 8); @@ -1339,21 +1337,21 @@ void parseiNavMspStatus(void) { uint8_t camSelected = 0; if (g_arm_mask) { - g_IS_ARMED = msp_rx_buf[13+g_arm_page] & g_arm_mask; + g_IS_ARMED = msp_rx_buf[13 + g_arm_page] & g_arm_mask; } if (g_boxCamera1_mask) { - if (msp_rx_buf[13+g_boxCamera1_page] & g_boxCamera1_mask) { + if (msp_rx_buf[13 + g_boxCamera1_page] & g_boxCamera1_mask) { camSelected = camera_switch(2); } } - + if (!camSelected && g_boxCamera2_mask) { - if (msp_rx_buf[13+g_boxCamera2_page] & g_boxCamera2_mask) { + if (msp_rx_buf[13 + g_boxCamera2_page] & g_boxCamera2_mask) { if (g_camera_switch == SWITCH_TYPE_PCA9557) { camSelected = camera_switch(3); } - } + } } if (!camSelected) { @@ -1976,8 +1974,8 @@ void update_vtx_menu_param(uint8_t state) { const char *pitString[] = {" OFF", " P1MW", " 0MW"}; const char *treamRaceString[] = {" OFF", "MODE1", "MODE2"}; const char *shortcutString[] = {"OPT_A", "OPT_B"}; - const char *cameraTypeString[] = {"UNKNOWN", "RESERVED", "OUTDATED", "MICRO_V1", "MICRO_V2", "NANO_90", "MICRO_V3" }; - const char *cameraSwitchString[] = {"NONE", "DUAL", "TREBLE"}; + const char *cameraTypeString[] = {"UNKNOWN", "RESERVED", "OUTDATED", "MICRO_V1", "MICRO_V2", "NANO_90", "MICRO_V3"}; + const char *cameraSwitchString[] = {"NONE", "DUAL", "TRIPLE"}; // cursor state += 2; @@ -2028,11 +2026,16 @@ void update_vtx_menu_param(uint8_t state) { strcpy(osd_buf[8] + osd_menu_offset + 20, shortcutString[vtx_shortcut]); // camera switch info - strcpy(osd_buf[12] + osd_menu_offset + 13, cameraSwitchString[g_camera_switch]); + if (g_camera_switch == SWITCH_TYPE_NONE) + strcpy(osd_buf[12] + osd_menu_offset + 13, cameraSwitchString[0]); + else if (g_camera_switch == SWITCH_TYPE_PI4IO) + strcpy(osd_buf[12] + osd_menu_offset + 13, cameraSwitchString[1]); + else if (g_camera_switch == SWITCH_TYPE_PCA9557 || g_camera_switch == SWITCH_TYPE_HDZCS) + strcpy(osd_buf[12] + osd_menu_offset + 13, cameraSwitchString[2]); // camera selection osd_buf[13][osd_menu_offset + 10] = '0' + g_camera_id; - osd_buf[13][osd_menu_offset + 11] = (g_manual_camera_sel) ? 'M' : ' '; + osd_buf[13][osd_menu_offset + 11] = (g_manual_camera_sel) ? 'M' : ' '; strcpy(osd_buf[13] + osd_menu_offset + 13, cameraTypeString[camera_type]); strcpy(osd_buf[16] + osd_menu_offset + 13, parseLifeTime()); diff --git a/src/msp_displayport.h b/src/msp_displayport.h index 1e2eeb2..30cd836 100644 --- a/src/msp_displayport.h +++ b/src/msp_displayport.h @@ -34,7 +34,7 @@ typedef enum { } vtxPtiType_e; typedef enum { - BOXARM_BTFL = 0, // for completeness + BOXARM_BTFL = 0, // for completeness BOXCAMERA1_BTFL = 32, // 0x20 BOXCAMERA2_BTFL = 33, // 0x21 @@ -126,12 +126,12 @@ typedef enum { typedef enum { VTXDEV_UNSUPPORTED = 0, // reserved for MSP - VTXDEV_RTC6705 = 1, + VTXDEV_RTC6705 = 1, // 2 reserved - VTXDEV_SMARTAUDIO = 3, - VTXDEV_TRAMP = 4, - VTXDEV_MSP = 5, - VTXDEV_UNKNOWN = 0xFF, + VTXDEV_SMARTAUDIO = 3, + VTXDEV_TRAMP = 4, + VTXDEV_MSP = 5, + VTXDEV_UNKNOWN = 0xFF, } vtxDevType_e; typedef enum { From d2aa83475f76b06e4aefcb50dfc891af58b49554 Mon Sep 17 00:00:00 2001 From: Ligen Date: Tue, 30 Sep 2025 12:17:06 +0800 Subject: [PATCH 2/5] support vrx resync --- src/msp_displayport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/msp_displayport.c b/src/msp_displayport.c index 86ba99d..e862162 100644 --- a/src/msp_displayport.c +++ b/src/msp_displayport.c @@ -568,13 +568,13 @@ uint8_t get_tx_data_5680() // prepare data to VRX tx_buf[12] = 0x00; // deprecated - tx_buf[13] = VTX_ID; + tx_buf[13] = g_camera_id; // Send g_camera_id in the future to allow the VRX to resync on a camera change tx_buf[14] = fc_lock & 0x03; tx_buf[15] = (camRatio == 0) ? 0x55 : 0xaa; - tx_buf[16] = VTX_VERSION_MAJOR; // Send g_camera_id in the future to allow the VRX to resync on a camera change + tx_buf[16] = VTX_VERSION_MAJOR; tx_buf[17] = VTX_VERSION_MINOR; tx_buf[18] = VTX_VERSION_PATCH_LEVEL; From 92396f2fd7e8c9e940450b19390c67e3ddbf730a Mon Sep 17 00:00:00 2001 From: Ligen Date: Tue, 30 Sep 2025 16:06:05 +0800 Subject: [PATCH 3/5] faster camera switch --- src/camera.c | 11 +++++++++-- src/camera.h | 2 ++ src/i2c_device.c | 17 +++++++++++++++-- src/msp_displayport.c | 10 ++++++++++ src/msp_displayport.h | 2 ++ 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/camera.c b/src/camera.c index 0535a0d..f6020ed 100644 --- a/src/camera.c +++ b/src/camera.c @@ -305,7 +305,7 @@ void camera_setting_profile_check(uint8_t profile) { } void camera_profile_read(void) { if (g_camera_switch) { - camera_profile_eep = g_camera_id-1; + camera_profile_eep = g_camera_id - 1; } else { camera_profile_eep = camera_reg_read_eep(EEP_ADDR_CAM_PROFILE); } @@ -365,7 +365,7 @@ void camera_setting_reg_menu_update(void) { void camera_setting_reg_eep_update(void) { uint8_t i; for (i = 0; i < CAMERA_SETTING_NUM; i++) { - if (g_camera_switch && i == (CAM_STATUS_VDO_FMT-1)) { + if (g_camera_switch && i == (CAM_STATUS_VDO_FMT - 1)) { // Sync all cameras on the camera switch to the same video setting if changed uint8_t value = camera_setting_reg_menu[i]; camera_setting_reg_eep[0][i] = value; @@ -416,6 +416,13 @@ void camera_init(void) { camera_button_init(); } +void camera_reinit(void) { + camera_type_detect(); + camera_setting_read(); + camera_setting_reg_menu_update(); + camera_mode_detect(1); +} + void camera_button_op(uint8_t op) { switch (op) { case BTN_UP: diff --git a/src/camera.h b/src/camera.h index b1a5d85..b04cc9e 100644 --- a/src/camera.h +++ b/src/camera.h @@ -38,6 +38,7 @@ typedef enum { CAMERA_TYPE_RUNCAM_MICRO_V2, // include hzd nano v2 / hdz nano lite CAMERA_TYPE_RUNCAM_NANO_90, CAMERA_TYPE_RUNCAM_MICRO_V3, + CAMERA_TYPE_NUM, } camera_type_e; typedef enum { @@ -92,6 +93,7 @@ typedef enum { } camera_select_e; void camera_init(void); +void camera_reinit(void); void camera_switch_profile(void); uint8_t camera_status_update(uint8_t op); void camera_menu_init(void); diff --git a/src/i2c_device.c b/src/i2c_device.c index cd395e9..ba9faa2 100644 --- a/src/i2c_device.c +++ b/src/i2c_device.c @@ -5,12 +5,14 @@ #include "global.h" #include "hardware.h" #include "i2c.h" +#include "msp_displayport.h" #include "print.h" uint8_t g_camera_switch = SWITCH_TYPE_NONE; uint8_t g_camera_id = 0; uint8_t g_max_camera = 0; uint8_t g_manual_camera_sel = 0; +static uint8_t camera_list[3] = {255, 254, 253}; ///////////////////////////////////////////////////////////////// // MAX7315 @@ -165,6 +167,7 @@ uint8_t get_camera_switch_type(void) { } void select_camera(uint8_t camera_id) { + static uint8_t camera_last = 0x00; if (g_camera_switch) { // Check camera id is within range, else default to 1 uint8_t camera = (camera_id == 0 || camera_id > g_max_camera) ? 1 : camera_id; @@ -193,8 +196,18 @@ void select_camera(uint8_t camera_id) { } else if (g_camera_switch == SWITCH_TYPE_HDZCS) { hdzcs_set(0x00, g_camera_id); } - camera_init(); - // camera_switch_profile(); + + if (camera_last != camera_list[g_camera_id]) { + if (camera_list[g_camera_id] < CAMERA_TYPE_NUM) { // camera has inited + camera_reinit(); + } else { + camera_init(); + camera_list[g_camera_id] = camera_type; + } + camera_last = camera_type; + } + + resync_vrx_vtmg(); } } } diff --git a/src/msp_displayport.c b/src/msp_displayport.c index e862162..bb94e17 100644 --- a/src/msp_displayport.c +++ b/src/msp_displayport.c @@ -2212,6 +2212,15 @@ uint8_t bfChannel_to_channel(uint8_t const channel) { return INVALID_CHANNEL; } +void resync_vrx_vtmg() { + uint8_t i, len; + len = get_tx_data_5680(); + for (i = 0; i < 8; i++) { + insert_tx_buf(len); + WAIT(50); + } +} + #ifdef INIT_VTX_TABLE #define FACTORY_BAND 0 // BF requires band to be CUSTOM with VTX_MSP @@ -2353,4 +2362,5 @@ uint8_t bfChannel_to_channel(uint8_t const channel) { return INVALID_CHANNEL; } +void resync_vrx_vtmg() {} #endif diff --git a/src/msp_displayport.h b/src/msp_displayport.h index 30cd836..7d2660b 100644 --- a/src/msp_displayport.h +++ b/src/msp_displayport.h @@ -174,6 +174,8 @@ void msp_set_vtx_config(uint8_t power, uint8_t save); void set_vtx_param(); uint8_t channel_to_bfChannel(uint8_t const channel); uint8_t bfChannel_to_channel(uint8_t const channel); +void resync_vrx_vtmg(); + #ifdef INIT_VTX_TABLE void InitVtxTable(); #endif From 6b620c8dc15e1ee342f38d90e80dd70bcc98cdd7 Mon Sep 17 00:00:00 2001 From: Ligen Date: Tue, 4 Nov 2025 12:03:20 +0800 Subject: [PATCH 4/5] support hdzcs cvbs camera --- src/camera.c | 33 +++++++++++++++++++++++---------- src/camera.h | 2 ++ src/hardware.c | 18 +++++++++++++----- src/msp_displayport.c | 2 +- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/camera.c b/src/camera.c index f6020ed..da011ab 100644 --- a/src/camera.c +++ b/src/camera.c @@ -33,13 +33,18 @@ extern uint8_t g_camera_switch; void camera_type_detect(void) { camera_type = CAMERA_TYPE_UNKNOWN; - runcam_type_detect(); - if (camera_type == CAMERA_TYPE_RUNCAM_MICRO_V1 || - camera_type == CAMERA_TYPE_RUNCAM_MICRO_V2 || - camera_type == CAMERA_TYPE_RUNCAM_NANO_90 || - camera_type == CAMERA_TYPE_RUNCAM_MICRO_V3) { - camera_mfr = CAMERA_MFR_RUNCAM; - return; + if (g_camera_switch == SWITCH_TYPE_HDZCS && g_camera_id == 3) { + camera_type = CAMERA_TYPE_HDZCS_CVBS; + camera_mfr = CAMERA_MFR_HDZERO; + } else { + runcam_type_detect(); + if (camera_type == CAMERA_TYPE_RUNCAM_MICRO_V1 || + camera_type == CAMERA_TYPE_RUNCAM_MICRO_V2 || + camera_type == CAMERA_TYPE_RUNCAM_NANO_90 || + camera_type == CAMERA_TYPE_RUNCAM_MICRO_V3) { + camera_mfr = CAMERA_MFR_RUNCAM; + return; + } } } @@ -62,6 +67,9 @@ void camera_ratio_detect(void) { camRatio = 1; break; #endif + case CAMERA_TYPE_HDZCS_CVBS: + camRatio = 1; + break; default: camRatio = 0; break; @@ -169,8 +177,12 @@ void camera_mode_detect(uint8_t init) { // init tc3587 and detect fps WriteReg(0, 0x8F, 0x91); - - if (camera_type == CAMERA_TYPE_RUNCAM_NANO_90) { + if (camera_type == CAMERA_TYPE_HDZCS_CVBS) { + Init_TC3587(0); + Set_720P60(IS_RX); + video_format = VDO_FMT_720P60; + I2C_Write16(ADDR_TC3587, 0x0058, 0x00e0); + } else if (camera_type == CAMERA_TYPE_RUNCAM_NANO_90) { Init_TC3587(1); if (camera_setting_reg_set[11] == 0) { Set_540P90(0); @@ -331,7 +343,8 @@ void camera_setting_read(void) { if (camera_type == CAMERA_TYPE_UNKNOWN || camera_type == CAMERA_TYPE_OUTDATED || - camera_type == CAMERA_TYPE_RESERVED) + camera_type == CAMERA_TYPE_RESERVED || + camera_type == CAMERA_TYPE_HDZCS_CVBS) return; camera_type_last = camera_reg_read_eep(EEP_ADDR_CAM_TYPE); diff --git a/src/camera.h b/src/camera.h index b04cc9e..a6a4d88 100644 --- a/src/camera.h +++ b/src/camera.h @@ -28,6 +28,7 @@ typedef enum { CAMERA_MFR_UNKNOW, CAMERA_MFR_FOXEER, CAMERA_MFR_RUNCAM, + CAMERA_MFR_HDZERO, } camera_manufacture_e; typedef enum { @@ -38,6 +39,7 @@ typedef enum { CAMERA_TYPE_RUNCAM_MICRO_V2, // include hzd nano v2 / hdz nano lite CAMERA_TYPE_RUNCAM_NANO_90, CAMERA_TYPE_RUNCAM_MICRO_V3, + CAMERA_TYPE_HDZCS_CVBS, CAMERA_TYPE_NUM, } camera_type_e; diff --git a/src/hardware.c b/src/hardware.c index 5105d6d..b925a13 100644 --- a/src/hardware.c +++ b/src/hardware.c @@ -514,10 +514,10 @@ void Init_HW() { #ifdef RESET_CONFIG reset_config(); #endif - + GetVtxParameter(); Get_EEP_LifeTime(); - + camera_switch_init(); camera_init(); @@ -1023,14 +1023,20 @@ void video_detect(void) { } cameraLost = (ReadReg(0, 0x02) >> 4) & 1; +#ifdef USE_TP9950 if (camera_type == CAMERA_TYPE_OUTDATED) { cameraLost |= (I2C_Read8(ADDR_TP9950, 0x01) != 0x7E); return; } +#endif + if (camera_type == CAMERA_TYPE_HDZCS_CVBS) { + return; + } - if (sec == 3) { - sec = 0; - if (cameraLost) { // video loss + if (cameraLost) { + sec++; + if (sec == 3) { // video loss + sec = 0; if (video_format == VDO_FMT_720P50) { Set_720P60(IS_RX); video_format = VDO_FMT_720P60; @@ -1039,6 +1045,8 @@ void video_detect(void) { video_format = VDO_FMT_720P50; } } + } else { + sec = 0; } } } diff --git a/src/msp_displayport.c b/src/msp_displayport.c index bb94e17..7b2115e 100644 --- a/src/msp_displayport.c +++ b/src/msp_displayport.c @@ -1974,7 +1974,7 @@ void update_vtx_menu_param(uint8_t state) { const char *pitString[] = {" OFF", " P1MW", " 0MW"}; const char *treamRaceString[] = {" OFF", "MODE1", "MODE2"}; const char *shortcutString[] = {"OPT_A", "OPT_B"}; - const char *cameraTypeString[] = {"UNKNOWN", "RESERVED", "OUTDATED", "MICRO_V1", "MICRO_V2", "NANO_90", "MICRO_V3"}; + const char *cameraTypeString[] = {"UNKNOWN ", "RESERVED", "OUTDATED", "MICRO_V1", "MICRO_V2", "NANO_90 ", "MICRO_V3", "CVBS "}; const char *cameraSwitchString[] = {"NONE", "DUAL", "TRIPLE"}; // cursor From e9d4bb91a20c3d681c826ed43c4a58ef55130f08 Mon Sep 17 00:00:00 2001 From: Ligen Date: Tue, 9 Dec 2025 18:31:01 +0800 Subject: [PATCH 5/5] hdzero camera switch support manual mode --- src/i2c_device.c | 29 ++++++++++++++++++++++++++--- src/i2c_device.h | 1 + 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/i2c_device.c b/src/i2c_device.c index ba9faa2..fda4b43 100644 --- a/src/i2c_device.c +++ b/src/i2c_device.c @@ -197,12 +197,12 @@ void select_camera(uint8_t camera_id) { hdzcs_set(0x00, g_camera_id); } - if (camera_last != camera_list[g_camera_id]) { - if (camera_list[g_camera_id] < CAMERA_TYPE_NUM) { // camera has inited + if (camera_last != camera_list[g_camera_id - 1]) { + if (camera_list[g_camera_id - 1] < CAMERA_TYPE_NUM) { // camera has inited camera_reinit(); } else { camera_init(); - camera_list[g_camera_id] = camera_type; + camera_list[g_camera_id - 1] = camera_type; } camera_last = camera_type; } @@ -244,5 +244,28 @@ void manual_select_camera(void) { uint8_t camera_id = ((command & 0x80) >> 7) + 1; select_camera(camera_id); } + } else if (g_camera_switch == SWITCH_TYPE_HDZCS) { + uint8_t command = hdzcs_get(0x01); + switch (command) { + case 0: + g_manual_camera_sel = 3; // manual analog camera + break; + case 1: + g_manual_camera_sel = 2; // manual mipi camera 2 + break; + case 2: + g_manual_camera_sel = 1; // manual mipi camera 1 + break; + case 3: + g_manual_camera_sel = 0; + break; // assign by FC + default: + g_manual_camera_sel = 0; + break; + } + + if (g_manual_camera_sel) { + select_camera(g_manual_camera_sel); + } } } diff --git a/src/i2c_device.h b/src/i2c_device.h index 30d961c..f631d3c 100644 --- a/src/i2c_device.h +++ b/src/i2c_device.h @@ -36,6 +36,7 @@ void Init_TC3587(uint8_t fmt); uint8_t pi4io_get(uint8_t reg); void pi4io_set(uint8_t reg, uint8_t val); +uint8_t hdzcs_get(uint8_t reg); void camera_switch_init(void); void select_camera(uint8_t camera_id); void manual_select_camera(void);