Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
5e74f41
Camera Control
geoffsim Nov 29, 2024
10ec0ea
Break from boxid loop when camera box id found.
geoffsim Nov 30, 2024
319bfac
Merge branch 'main' into Camera-Control
geoffsim Jan 22, 2025
d1a6c17
First cut of camera control.
geoffsim Jan 27, 2025
ec3a53a
Add manual mode
geoffsim Jan 29, 2025
fac03f8
Update VTX menu to show connected camera type and the current camera …
geoffsim Jan 29, 2025
bab66d4
Ensure both cameras are in sync (for now).
geoffsim Jan 31, 2025
6fcf96c
V1.3
geoffsim Feb 1, 2025
1b7cfed
Disable interrupts.
geoffsim Feb 1, 2025
92c706a
Further optimisation to message requests from the VTX.
geoffsim Feb 17, 2025
57beac9
Use MSP2_INAV_STATUS instead of MSP_STATUS when variant is INAV, and …
geoffsim Feb 19, 2025
b640911
Spelling
geoffsim Feb 21, 2025
239b78e
1st cut of independent camera settings
geoffsim Feb 23, 2025
9fcfb76
Sync video mode changes across both camera settings
geoffsim Feb 23, 2025
8a5b521
2.0 Alpha
geoffsim Feb 23, 2025
9ae1d05
Detect camera switch presence
geoffsim Feb 25, 2025
ee381cd
Add camera_switch_profile function to change profile when camera is c…
geoffsim Feb 25, 2025
9ffc9ec
Remove ALPHA version info
geoffsim Feb 25, 2025
adda2a5
Send camera id to the VRX
geoffsim Feb 26, 2025
df18d3e
Set BOXIDs only valid for INAV/BTFL/EMUF.
geoffsim Mar 1, 2025
8ce4699
Use BOXCAMERA1/2/3 to support up to 3 cameras.
geoffsim Mar 6, 2025
5cf593d
Only use 2 boxcamera controls to choose between three cameras.
geoffsim Mar 6, 2025
4f7ddf6
Switch description change on VTX menu to DUAL/TREBLE
geoffsim Mar 6, 2025
e374e0a
Include CAM switch version information (temporary).
geoffsim Mar 9, 2025
168dad2
Simplify PCA9557 detection during startup.
geoffsim Mar 9, 2025
0ac1cea
Do not set colorbars if camera not recognised.
geoffsim Mar 10, 2025
973be3e
Swap camera 1 and camera 3 on the 3-camera switch.
geoffsim Mar 10, 2025
4ed146e
Remove temporary camera switch version information
geoffsim Mar 10, 2025
21f8b6b
Comment location to use to send camera id to the VRX in the future
geoffsim Mar 10, 2025
410ffac
Ensure camera is initialised properly when selected for the first time.
geoffsim Mar 12, 2025
b1e5578
Remove static initialisation values and pass an init flag when requir…
geoffsim Mar 28, 2025
c31336f
Add UNUSED definition to help compiler
geoffsim Mar 28, 2025
0921380
Better define camera switch capabilities
geoffsim Mar 28, 2025
fa99270
Rename "reset_isp_need" to "isp_reset_reqd" for clarity.
geoffsim Mar 28, 2025
23f7abf
Fix conflicts with main merge
geoffsim Apr 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 72 additions & 43 deletions src/camera.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@ uint8_t camera_profile_menu;
uint8_t video_format = VDO_FMT_720P60;
uint8_t camRatio = 0; // 0->16:9 1->4:3
uint8_t camMenuStatus = CAM_STATUS_IDLE;
uint8_t reset_isp_need = 0;
uint8_t isp_reset_reqd = 0;

uint8_t camera_is_3v3 = 0;

extern uint8_t g_camera_id;
extern uint8_t g_camera_switch;

void camera_type_detect(void) {
camera_type = CAMERA_TYPE_UNKNOW;
camera_type = CAMERA_TYPE_UNKNOWN;

runcam_type_detect();
if (camera_type == CAMERA_TYPE_RUNCAM_MICRO_V1 ||
Expand Down Expand Up @@ -67,13 +70,11 @@ void camera_ratio_detect(void) {

#ifdef USE_TP9950
void camera_mode_detect(uint8_t init) {

UNUSED(init);
uint32_t frame = 0;
uint32_t agc_en = 0;
uint8_t id = 0;

init = 0;

#ifdef USE_TC3587_RSTB
TC3587_RSTB = 0;
WAIT(100);
Expand Down Expand Up @@ -232,7 +233,7 @@ void camera_mode_detect(uint8_t init) {

if (cycles == 0) {
Set_720P60(0);
// WriteReg(0, 0x50, 0x01);
// WriteReg(0, 0x50, 0x01); // Do not output colorbar
video_format = VDO_FMT_720P60;
I2C_Write16(ADDR_TC3587, 0x0058, 0x00e0);
camera_type = CAMERA_TYPE_RESERVED;
Expand Down Expand Up @@ -303,10 +304,16 @@ void camera_setting_profile_check(uint8_t profile) {
}
}
void camera_profile_read(void) {
camera_profile_eep = camera_reg_read_eep(EEP_ADDR_CAM_PROFILE);
if (g_camera_switch) {
camera_profile_eep = g_camera_id-1;
} else {
camera_profile_eep = camera_reg_read_eep(EEP_ADDR_CAM_PROFILE);
}
}
void camera_profile_write(void) {
camera_reg_write_eep(EEP_ADDR_CAM_PROFILE, camera_profile_eep);
if (!g_camera_switch) {
camera_reg_write_eep(EEP_ADDR_CAM_PROFILE, camera_profile_eep);
}
}
void camera_profile_reset(void) {
camera_profile_eep = 0;
Expand All @@ -322,7 +329,7 @@ void camera_setting_read(void) {
uint8_t camera_type_last;
uint8_t i;

if (camera_type == CAMERA_TYPE_UNKNOW ||
if (camera_type == CAMERA_TYPE_UNKNOWN ||
camera_type == CAMERA_TYPE_OUTDATED ||
camera_type == CAMERA_TYPE_RESERVED)
return;
Expand Down Expand Up @@ -357,35 +364,55 @@ 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++)
camera_setting_reg_eep[camera_profile_menu][i] = camera_setting_reg_menu[i];
for (i = 0; i < CAMERA_SETTING_NUM; i++) {
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;
camera_setting_reg_eep[1][i] = value;
if (g_camera_switch == SWITCH_TYPE_PCA9557) {
camera_setting_reg_eep[2][i] = value;
}
} else {
camera_setting_reg_eep[camera_profile_menu][i] = camera_setting_reg_menu[i];
}
}
}

uint8_t camera_set(uint8_t *camera_setting_reg, uint8_t save, uint8_t init) {
uint8_t ret = 0;
if (camera_mfr == CAMERA_MFR_RUNCAM) {
ret = runcam_set(camera_setting_reg);
ret = runcam_set(camera_setting_reg, init);
if (save || (init & ret))
runcam_save();
}

return ret;
}

void camera_switch_profile(void) {
camera_setting_read();
camera_setting_reg_menu_update();
isp_reset_reqd = camera_set(camera_setting_reg_menu, 0, 1);
if (isp_reset_reqd) {
if (camera_mfr == CAMERA_MFR_RUNCAM) {
runcam_reset_isp();
camera_mode_detect(0);
}
}
}

void camera_init(void) {
camera_type_detect();
camera_setting_read();
camera_setting_reg_menu_update();
reset_isp_need = camera_set(camera_setting_reg_menu, 0, 1);

if (reset_isp_need) {
isp_reset_reqd = camera_set(camera_setting_reg_menu, 0, 1);
if (isp_reset_reqd) {
if (camera_mfr == CAMERA_MFR_RUNCAM) {
runcam_reset_isp();
}
}

camera_mode_detect(1);

camera_button_init();
}

Expand Down Expand Up @@ -438,7 +465,7 @@ void camera_menu_draw_value(void) {
osd_buf[0][osd_menu_offset + 28] = '1' + camera_profile_menu;

for (i = CAM_STATUS_BRIGHTNESS; i <= CAM_STATUS_VDO_FMT; i++) {
if (camera_attribute[i - 1][CAM_SETTING_ITEM_ENBALE] == 0)
if (camera_attribute[i - 1][CAM_SETTING_ITEM_ENABLE] == 0)
strcpy(&osd_buf[i][osd_menu_offset + 27], "-");
else {
switch (i) {
Expand Down Expand Up @@ -597,18 +624,20 @@ void camera_menu_item_toggle(uint8_t op) {
}

void camera_profile_menu_toggle(uint8_t op) {
if (op == BTN_RIGHT) {
camera_profile_menu++;
if (camera_profile_menu == CAMERA_PROFILE_NUM)
camera_profile_menu = 0;
camera_setting_reg_menu_update();
reset_isp_need |= camera_set(camera_setting_reg_menu, 0, 0);
} else if (op == BTN_LEFT) {
camera_profile_menu--;
if (camera_profile_menu > CAMERA_PROFILE_NUM)
camera_profile_menu = CAMERA_PROFILE_NUM - 1;
camera_setting_reg_menu_update();
reset_isp_need |= camera_set(camera_setting_reg_menu, 0, 0);
if (!g_camera_switch) {
if (op == BTN_RIGHT) {
camera_profile_menu++;
if (camera_profile_menu == CAMERA_PROFILE_NUM)
camera_profile_menu = 0;
camera_setting_reg_menu_update();
isp_reset_reqd |= camera_set(camera_setting_reg_menu, 0, 0);
} else if (op == BTN_LEFT) {
camera_profile_menu--;
if (camera_profile_menu > CAMERA_PROFILE_NUM)
camera_profile_menu = CAMERA_PROFILE_NUM - 1;
camera_setting_reg_menu_update();
isp_reset_reqd |= camera_set(camera_setting_reg_menu, 0, 0);
}
}
}

Expand Down Expand Up @@ -637,7 +666,7 @@ void camera_setting_reg_menu_toggle(uint8_t op, uint8_t last_op) {
case CAM_STATUS_BRIGHTNESS:
case CAM_STATUS_WBRED:
case CAM_STATUS_WBBLUE:
if (!camera_attribute[item][CAM_SETTING_ITEM_ENBALE])
if (!camera_attribute[item][CAM_SETTING_ITEM_ENABLE])
return;
#if (0)
// if wb mode if auto, do not modify wbred/wbblue
Expand Down Expand Up @@ -682,7 +711,7 @@ void camera_setting_reg_menu_toggle(uint8_t op, uint8_t last_op) {
case CAM_STATUS_NIGHT_MODE:
case CAM_STATUS_LED_MODE:
case CAM_STATUS_VDO_FMT:
if (!camera_attribute[item][CAM_SETTING_ITEM_ENBALE])
if (!camera_attribute[item][CAM_SETTING_ITEM_ENABLE])
return;

if (op == BTN_RIGHT) {
Expand All @@ -691,7 +720,7 @@ void camera_setting_reg_menu_toggle(uint8_t op, uint8_t last_op) {
camera_setting_reg_menu[item] = camera_attribute[item][CAM_SETTING_ITEM_MIN];

if (camMenuStatus != CAM_STATUS_VDO_FMT) { // vdo format will be configured when exit camera menu
camera_set(camera_setting_reg_menu, 0, 0);
isp_reset_reqd |= camera_set(camera_setting_reg_menu, 0, 0);
}
} else if (op == BTN_LEFT) {
camera_setting_reg_menu[item]--;
Expand All @@ -702,7 +731,7 @@ void camera_setting_reg_menu_toggle(uint8_t op, uint8_t last_op) {
camera_setting_reg_menu[item] = camera_attribute[item][CAM_SETTING_ITEM_MAX];

if (camMenuStatus != CAM_STATUS_VDO_FMT) { // vdo format will be configured when exit camera menu
camera_set(camera_setting_reg_menu, 0, 0);
isp_reset_reqd |= camera_set(camera_setting_reg_menu, 0, 0);
}
}
break;
Expand All @@ -723,7 +752,7 @@ uint8_t camera_status_update(uint8_t op) {
if (op >= BTN_INVALID)
return ret;

if (camera_type == CAMERA_TYPE_UNKNOW ||
if (camera_type == CAMERA_TYPE_UNKNOWN ||
camera_type == CAMERA_TYPE_OUTDATED) {
camera_button_op(op);
return ret;
Expand All @@ -732,7 +761,7 @@ uint8_t camera_status_update(uint8_t op) {
switch (camMenuStatus) {
case CAM_STATUS_IDLE:
if (op == BTN_MID) {
reset_isp_need = 0;
isp_reset_reqd = 0;
camera_menu_long_press(op, last_op, 1);

camMenuStatus = CAM_STATUS_PROFILE;
Expand Down Expand Up @@ -812,11 +841,11 @@ uint8_t camera_status_update(uint8_t op) {
camMenuStatus = CAM_STATUS_REPOWER;
} else {
camera_profile_write();
reset_isp_need |= camera_set(camera_setting_reg_menu, 1, 0);
isp_reset_reqd |= camera_set(camera_setting_reg_menu, 1, 0);
camera_setting_reg_eep_update();
camera_setting_profile_write(0xff);

if (reset_isp_need) {
if (isp_reset_reqd) {
if (camera_mfr == CAMERA_MFR_RUNCAM) {
runcam_reset_isp();
camera_mode_detect(0);
Expand All @@ -831,10 +860,10 @@ uint8_t camera_status_update(uint8_t op) {
case CAM_STATUS_REPOWER:
if (op == BTN_RIGHT) {
camera_profile_write();
reset_isp_need |= camera_set(camera_setting_reg_menu, 1, 0);
isp_reset_reqd |= camera_set(camera_setting_reg_menu, 1, 0);
camera_setting_reg_eep_update();
camera_setting_profile_write(0xff);
if (reset_isp_need) {
if (isp_reset_reqd) {
if (camera_mfr == CAMERA_MFR_RUNCAM) {
runcam_reset_isp();
camera_mode_detect(0);
Expand Down Expand Up @@ -892,7 +921,7 @@ void camera_select_menu_init(void) {
osd_buf_p = osd_buf[i] + osd_menu_offset;
strcpy(osd_buf_p, cam_select_menu_string[i]);
}
camera_select_menu_ratio_upate();
camera_select_menu_ratio_update();
}

void camera_select_menu_cursor_update(uint8_t index) {
Expand All @@ -905,14 +934,14 @@ void camera_select_menu_cursor_update(uint8_t index) {
}
}

void camera_select_menu_ratio_upate() {
void camera_select_menu_ratio_update() {
if (camRatio == 1)
strcpy(osd_buf[2] + osd_menu_offset + 28, "<4:3> ");
else
strcpy(osd_buf[2] + osd_menu_offset + 28, "<16:9>");
}

void camera_menu_mode_exit_note() {
const char note_string[] = "LEFT MOVE THROTTLE TO EXIT CAMERA MENU";
const char note_string[] = "MOVE THROTTLE LEFT TO EXIT CAMERA MENU";
strcpy(osd_buf[15] + 5, note_string);
}
11 changes: 6 additions & 5 deletions src/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ typedef enum {
} camera_manufacture_e;

typedef enum {
CAMERA_TYPE_UNKNOW,
CAMERA_TYPE_UNKNOWN,
CAMERA_TYPE_RESERVED, // include foxeer digisight v3
CAMERA_TYPE_OUTDATED, // include runcam(orange)
CAMERA_TYPE_RUNCAM_MICRO_V1, // include hdz nano v1
Expand All @@ -53,7 +53,7 @@ typedef enum {
} video_format_e;

typedef enum {
CAM_SETTING_ITEM_ENBALE,
CAM_SETTING_ITEM_ENABLE,
CAM_SETTING_ITEM_MIN,
CAM_SETTING_ITEM_MAX,
CAM_SETTING_ITEM_DEFAULT,
Expand Down Expand Up @@ -91,13 +91,14 @@ typedef enum {
CAM_SELECT_EXIT,
} camera_select_e;

void camera_init();
void camera_init(void);
void camera_switch_profile(void);
uint8_t camera_status_update(uint8_t op);
void camera_menu_init(void);
void camera_select_menu_init(void);
void camera_select_menu_cursor_update(uint8_t index);
void camera_select_menu_ratio_upate();
void camera_menu_mode_exit_note();
void camera_select_menu_ratio_update(void);
void camera_menu_mode_exit_note(void);

extern uint8_t camRatio;
extern uint8_t video_format;
Expand Down
4 changes: 4 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,8 @@

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))

#if !defined(UNUSED)
#define UNUSED(x) ((void)(x)) /* To avoid gcc/g++ warnings */
#endif /* UNUSED */

#endif /* __COMMON_H_ */
5 changes: 4 additions & 1 deletion src/hardware.c
Original file line number Diff line number Diff line change
Expand Up @@ -514,10 +514,13 @@ void Init_HW() {
#ifdef RESET_CONFIG
reset_config();
#endif

GetVtxParameter();
Get_EEP_LifeTime();

camera_switch_init();
camera_init();

#ifdef _RF_CALIB
RF_POWER = 0; // max power
RF_FREQ = 0; // ch1
Expand Down
Loading