From bb06d34cc7159e3010807672b6cc69d56467e995 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 18 Nov 2018 14:54:29 +0000 Subject: [PATCH] Pi Firmware: implemented capture of N frames and OSD_EXPIRED for delayed exit of OSD Change-Id: I93a75ae4f6fb34fc778250431d65c63fd7593579 --- src/defs.h | 5 ++++- src/osd.c | 17 ++++++++--------- src/osd.h | 9 +++++---- src/rgb_to_fb.S | 24 +++++++++++++++++------- src/rgb_to_hdmi.c | 47 +++++++++++++++++++++++++++++++---------------- 5 files changed, 65 insertions(+), 37 deletions(-) diff --git a/src/defs.h b/src/defs.h index 68a065aa..44f3a0ea 100644 --- a/src/defs.h +++ b/src/defs.h @@ -34,7 +34,7 @@ #define BIT_FIELD_TYPE 0x100 // bit 8, indicates the field type (0 = odd, 1 = even) of the last field #define BIT_CLEAR 0x200 // bit 9, indicates the frame buffer should be cleared #define BIT_VSYNC 0x400 // bit 10, indicates the vsync frequency is being probed -#define BIT_CAL_COUNT 0x800 // bit 11, indicates how many fields to capture during calibration (1 or 2) + // bit 11, unused #define OFFSET_LAST_BUFFER 12 // bit 12-13 LAST_BUFFER #define MASK_LAST_BUFFER (3 << OFFSET_LAST_BUFFER) @@ -63,6 +63,7 @@ #define RET_SW1 0x02 #define RET_SW2 0x04 #define RET_SW3 0x08 +#define RET_EXPIRED 0x10 // Channel definitions #define NUM_CHANNELS 3 @@ -125,6 +126,7 @@ #define O_NLINES 20 #define O_H_OFFSET 24 #define O_V_OFFSET 28 +#define O_NCAPTURE 32 #else @@ -137,6 +139,7 @@ typedef struct { int nlines; // number of active lines to capture each field int h_offset; // horizontal offset (in psync clocks) int v_offset; // vertical offset (in lines) + int ncapture; // number of fields to capture, or -1 to capture forever } capture_info_t; typedef struct { diff --git a/src/osd.c b/src/osd.c index 9ea8997b..e1002b46 100644 --- a/src/osd.c +++ b/src/osd.c @@ -388,10 +388,6 @@ static void update_palette() { RPI_PropertyProcess(); } -static void delay() { - for (volatile int i = 0; i < 100000000; i++); -} - static int get_feature(int num) { switch (num) { case F_PALETTE: @@ -793,12 +789,13 @@ void osd_refresh() { } } -void osd_key(int key) { +int osd_key(int key) { item_type_t type; base_menu_item_t *item = current_menu[depth]->items[current_item[depth]]; child_menu_item_t *child_item = (child_menu_item_t *)item; param_menu_item_t *param_item = (param_menu_item_t *)item; int val; + int ret = -1; switch (osd_state) { @@ -813,14 +810,15 @@ void osd_key(int key) { // Clock Calibration osd_set(0, ATTR_DOUBLE_SIZE, "Clock Calibration"); action_calibrate_clocks(); - // Note: due to multiple buffering, the message sometimes doesn't get displayed - delay(); - osd_clear(); + // Fire OSD_EXPIRED in 50 frames time + ret = 50; } else if (key == key_auto_cal) { // Auto Calibration osd_set(0, ATTR_DOUBLE_SIZE, "Auto Calibration"); action_calibrate_auto(); - delay(); + // Fire OSD_EXPIRED in 50 frames time + ret = 50; + } else if (key == OSD_EXPIRED) { osd_clear(); } break; @@ -928,6 +926,7 @@ void osd_key(int key) { } break; } + return ret; } void osd_init() { diff --git a/src/osd.h b/src/osd.h index c06f5b28..af99a9d7 100644 --- a/src/osd.h +++ b/src/osd.h @@ -1,9 +1,10 @@ #ifndef OSD_H #define OSD_H -#define OSD_SW1 1 -#define OSD_SW2 2 -#define OSD_SW3 3 +#define OSD_SW1 1 +#define OSD_SW2 2 +#define OSD_SW3 3 +#define OSD_EXPIRED 4 #define ATTR_DOUBLE_SIZE (1 << 0) @@ -53,7 +54,7 @@ void osd_refresh(); void osd_update(uint32_t *osd_base, int bytes_per_line); void osd_update_fast(uint32_t *osd_base, int bytes_per_line); int osd_active(); -void osd_key(int key); +int osd_key(int key); uint32_t *osd_get_palette(); void action_calibrate_clocks(); diff --git a/src/rgb_to_fb.S b/src/rgb_to_fb.S index 342045e7..33a128fc 100644 --- a/src/rgb_to_fb.S +++ b/src/rgb_to_fb.S @@ -678,6 +678,8 @@ rgb_to_fb: str r2, param_h_offset ldr r2, [r0, #O_V_OFFSET] str r2, param_v_offset + ldr r2, [r0, #O_NCAPTURE] + str r2, param_ncapture ldr r2, [r0, #O_FB_BASE] str r2, param_framebuffer0 @@ -963,6 +965,9 @@ param_h_offset: param_v_offset: .word 0 +param_ncapture: + .word 0 + // Insert the current literal pool, otherwise constants are to far away and you get a build error .ltorg @@ -994,14 +999,19 @@ skip_osd_update: FLIP_BUFFER #endif - // Loop back if not calibrate mode... - tst r3, #BIT_CALIBRATE - beq frame + // Loop back if required number of fields has not been reached + // or if negative (capture forever) + ldr r5, param_ncapture + cmp r5, #0 + blt frame + sub r5, #1 + str r5, param_ncapture + bne frame - // In calibrate mode, have the required number of fields (1 or 2) been captured - tst r3, #BIT_CAL_COUNT - orr r3, #BIT_CAL_COUNT - beq frame + // Setup the response code + mov r0, r3 + and r0, #BIT_MODE7 + orr r0, #RET_EXPIRED // Return exit: diff --git a/src/rgb_to_hdmi.c b/src/rgb_to_hdmi.c index 5c7edfed..7c1f2ec1 100644 --- a/src/rgb_to_hdmi.c +++ b/src/rgb_to_hdmi.c @@ -520,7 +520,10 @@ static int test_for_elk(capture_info_t *capinfo, int elk, int mode7) { } unsigned int ret; - unsigned int flags = BIT_CALIBRATE | BIT_CAL_COUNT | (2 << OFFSET_NBUFFERS); + unsigned int flags = BIT_CALIBRATE | (2 << OFFSET_NBUFFERS); + + // Set to capture exactly one field + capinfo->ncapture = 1; // Grab one field ret = rgb_to_fb(capinfo, flags); @@ -615,9 +618,11 @@ int *diff_N_frames_by_sample(capture_info_t *capinfo, int n, int mode7, int elk) unsigned int t_compare = 0; #endif - // In mode 0..6, set BIT_CAL_COUNT to 1 (capture 1 field) - // In mode 7, set BIT_CAL_COUNT to 0 (capture two fields, doesn't matter whether odd-even or even-odd) - unsigned int flags = mode7 | BIT_CALIBRATE | (mode7 ? 0 : BIT_CAL_COUNT) | ((elk & !mode7) ? BIT_ELK : 0) | (2 << OFFSET_NBUFFERS); + unsigned int flags = mode7 | BIT_CALIBRATE | ((elk & !mode7) ? BIT_ELK : 0) | (2 << OFFSET_NBUFFERS); + + // In mode 0..6, capture one field + // In mode 7, capture two fields + capinfo->ncapture = mode7 ? 2 : 1; #ifdef INSTRUMENT_CAL t = _get_cycle_counter(); @@ -783,6 +788,9 @@ int analyze_mode7_alignment(capture_info_t *capinfo) { unsigned int flags = BIT_MODE7 | BIT_CALIBRATE | (2 << OFFSET_NBUFFERS); + // Capture two fields + capinfo->ncapture = 2; + // Grab a frame int ret = rgb_to_fb(capinfo, flags); @@ -858,9 +866,11 @@ int total_N_frames(capture_info_t *capinfo, int n, int mode7, int elk) { unsigned int t_compare = 0; #endif - // In mode 0..6, set BIT_CAL_COUNT to 1 (capture 1 field) - // In mode 7, set BIT_CAL_COUNT to 0 (capture two fields, doesn't matter whether odd-even or even-odd) - unsigned int flags = mode7 | BIT_CALIBRATE | (mode7 ? 0 : BIT_CAL_COUNT) | ((elk & !mode7) ? BIT_ELK : 0) | (2 << OFFSET_NBUFFERS); + unsigned int flags = mode7 | BIT_CALIBRATE | ((elk & !mode7) ? BIT_ELK : 0) | (2 << OFFSET_NBUFFERS); + + // In mode 0..6, capture one field + // In mode 7, capture two fields + capinfo->ncapture = mode7 ? 2 : 1; for (int i = 0; i < n; i++) { int total = 0; @@ -1039,6 +1049,7 @@ void rgb_to_hdmi_main() { int fb_size_changed; int active_size_decreased; int clk_changed; + int ncapture; capture_info_t last_capinfo; clk_info_t last_clkinfo; @@ -1051,6 +1062,9 @@ void rgb_to_hdmi_main() { // Determine initial mode mode7 = rgb_to_fb(capinfo, BIT_PROBE) & BIT_MODE7 & !m7disable; + // Default to capturing indefinitely + ncapture = -1; + while (1) { // Switch the the approriate capinfo structure instance @@ -1073,7 +1087,6 @@ void rgb_to_hdmi_main() { do { - log_debug("Entering rgb_to_fb"); int flags = mode7 | clear; if (!m7disable) { flags |= BIT_MODE_DETECT; @@ -1104,18 +1117,20 @@ void rgb_to_hdmi_main() { #ifdef MULTI_BUFFER flags |= nbuffers << OFFSET_NBUFFERS; #endif + capinfo->ncapture = ncapture; + log_debug("Entering rgb_to_fb, flags=%08x", flags); result = rgb_to_fb(capinfo, flags); log_debug("Leaving rgb_to_fb, result=%04x", result); clear = 0; - if (result & RET_SW1) { - osd_key(OSD_SW1); - } - if (result & RET_SW2) { - osd_key(OSD_SW2); - } - if (result & RET_SW3) { - osd_key(OSD_SW3); + if (result & RET_EXPIRED) { + ncapture = osd_key(OSD_EXPIRED); + } else if (result & RET_SW1) { + ncapture = osd_key(OSD_SW1); + } else if (result & RET_SW2) { + ncapture = osd_key(OSD_SW2); + } else if (result & RET_SW3) { + ncapture = osd_key(OSD_SW3); } // Possibly the size or offset has been adjusted, so update current capinfo