kopia lustrzana https://github.com/hoglet67/RGBtoHDMI
Pi Firmware: implemented capture of N frames and OSD_EXPIRED for delayed exit of OSD
Change-Id: I93a75ae4f6fb34fc778250431d65c63fd7593579pull/11/head
rodzic
8212858fa6
commit
bb06d34cc7
|
@ -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_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_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_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 OFFSET_LAST_BUFFER 12 // bit 12-13 LAST_BUFFER
|
||||||
#define MASK_LAST_BUFFER (3 << OFFSET_LAST_BUFFER)
|
#define MASK_LAST_BUFFER (3 << OFFSET_LAST_BUFFER)
|
||||||
|
@ -63,6 +63,7 @@
|
||||||
#define RET_SW1 0x02
|
#define RET_SW1 0x02
|
||||||
#define RET_SW2 0x04
|
#define RET_SW2 0x04
|
||||||
#define RET_SW3 0x08
|
#define RET_SW3 0x08
|
||||||
|
#define RET_EXPIRED 0x10
|
||||||
|
|
||||||
// Channel definitions
|
// Channel definitions
|
||||||
#define NUM_CHANNELS 3
|
#define NUM_CHANNELS 3
|
||||||
|
@ -125,6 +126,7 @@
|
||||||
#define O_NLINES 20
|
#define O_NLINES 20
|
||||||
#define O_H_OFFSET 24
|
#define O_H_OFFSET 24
|
||||||
#define O_V_OFFSET 28
|
#define O_V_OFFSET 28
|
||||||
|
#define O_NCAPTURE 32
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -137,6 +139,7 @@ typedef struct {
|
||||||
int nlines; // number of active lines to capture each field
|
int nlines; // number of active lines to capture each field
|
||||||
int h_offset; // horizontal offset (in psync clocks)
|
int h_offset; // horizontal offset (in psync clocks)
|
||||||
int v_offset; // vertical offset (in lines)
|
int v_offset; // vertical offset (in lines)
|
||||||
|
int ncapture; // number of fields to capture, or -1 to capture forever
|
||||||
} capture_info_t;
|
} capture_info_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
17
src/osd.c
17
src/osd.c
|
@ -388,10 +388,6 @@ static void update_palette() {
|
||||||
RPI_PropertyProcess();
|
RPI_PropertyProcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void delay() {
|
|
||||||
for (volatile int i = 0; i < 100000000; i++);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_feature(int num) {
|
static int get_feature(int num) {
|
||||||
switch (num) {
|
switch (num) {
|
||||||
case F_PALETTE:
|
case F_PALETTE:
|
||||||
|
@ -793,12 +789,13 @@ void osd_refresh() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void osd_key(int key) {
|
int osd_key(int key) {
|
||||||
item_type_t type;
|
item_type_t type;
|
||||||
base_menu_item_t *item = current_menu[depth]->items[current_item[depth]];
|
base_menu_item_t *item = current_menu[depth]->items[current_item[depth]];
|
||||||
child_menu_item_t *child_item = (child_menu_item_t *)item;
|
child_menu_item_t *child_item = (child_menu_item_t *)item;
|
||||||
param_menu_item_t *param_item = (param_menu_item_t *)item;
|
param_menu_item_t *param_item = (param_menu_item_t *)item;
|
||||||
int val;
|
int val;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
switch (osd_state) {
|
switch (osd_state) {
|
||||||
|
|
||||||
|
@ -813,14 +810,15 @@ void osd_key(int key) {
|
||||||
// Clock Calibration
|
// Clock Calibration
|
||||||
osd_set(0, ATTR_DOUBLE_SIZE, "Clock Calibration");
|
osd_set(0, ATTR_DOUBLE_SIZE, "Clock Calibration");
|
||||||
action_calibrate_clocks();
|
action_calibrate_clocks();
|
||||||
// Note: due to multiple buffering, the message sometimes doesn't get displayed
|
// Fire OSD_EXPIRED in 50 frames time
|
||||||
delay();
|
ret = 50;
|
||||||
osd_clear();
|
|
||||||
} else if (key == key_auto_cal) {
|
} else if (key == key_auto_cal) {
|
||||||
// Auto Calibration
|
// Auto Calibration
|
||||||
osd_set(0, ATTR_DOUBLE_SIZE, "Auto Calibration");
|
osd_set(0, ATTR_DOUBLE_SIZE, "Auto Calibration");
|
||||||
action_calibrate_auto();
|
action_calibrate_auto();
|
||||||
delay();
|
// Fire OSD_EXPIRED in 50 frames time
|
||||||
|
ret = 50;
|
||||||
|
} else if (key == OSD_EXPIRED) {
|
||||||
osd_clear();
|
osd_clear();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -928,6 +926,7 @@ void osd_key(int key) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void osd_init() {
|
void osd_init() {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#define OSD_SW1 1
|
#define OSD_SW1 1
|
||||||
#define OSD_SW2 2
|
#define OSD_SW2 2
|
||||||
#define OSD_SW3 3
|
#define OSD_SW3 3
|
||||||
|
#define OSD_EXPIRED 4
|
||||||
|
|
||||||
#define ATTR_DOUBLE_SIZE (1 << 0)
|
#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(uint32_t *osd_base, int bytes_per_line);
|
||||||
void osd_update_fast(uint32_t *osd_base, int bytes_per_line);
|
void osd_update_fast(uint32_t *osd_base, int bytes_per_line);
|
||||||
int osd_active();
|
int osd_active();
|
||||||
void osd_key(int key);
|
int osd_key(int key);
|
||||||
uint32_t *osd_get_palette();
|
uint32_t *osd_get_palette();
|
||||||
|
|
||||||
void action_calibrate_clocks();
|
void action_calibrate_clocks();
|
||||||
|
|
|
@ -678,6 +678,8 @@ rgb_to_fb:
|
||||||
str r2, param_h_offset
|
str r2, param_h_offset
|
||||||
ldr r2, [r0, #O_V_OFFSET]
|
ldr r2, [r0, #O_V_OFFSET]
|
||||||
str r2, param_v_offset
|
str r2, param_v_offset
|
||||||
|
ldr r2, [r0, #O_NCAPTURE]
|
||||||
|
str r2, param_ncapture
|
||||||
ldr r2, [r0, #O_FB_BASE]
|
ldr r2, [r0, #O_FB_BASE]
|
||||||
str r2, param_framebuffer0
|
str r2, param_framebuffer0
|
||||||
|
|
||||||
|
@ -963,6 +965,9 @@ param_h_offset:
|
||||||
param_v_offset:
|
param_v_offset:
|
||||||
.word 0
|
.word 0
|
||||||
|
|
||||||
|
param_ncapture:
|
||||||
|
.word 0
|
||||||
|
|
||||||
// Insert the current literal pool, otherwise constants are to far away and you get a build error
|
// Insert the current literal pool, otherwise constants are to far away and you get a build error
|
||||||
.ltorg
|
.ltorg
|
||||||
|
|
||||||
|
@ -994,14 +999,19 @@ skip_osd_update:
|
||||||
FLIP_BUFFER
|
FLIP_BUFFER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Loop back if not calibrate mode...
|
// Loop back if required number of fields has not been reached
|
||||||
tst r3, #BIT_CALIBRATE
|
// or if negative (capture forever)
|
||||||
beq frame
|
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
|
// Setup the response code
|
||||||
tst r3, #BIT_CAL_COUNT
|
mov r0, r3
|
||||||
orr r3, #BIT_CAL_COUNT
|
and r0, #BIT_MODE7
|
||||||
beq frame
|
orr r0, #RET_EXPIRED
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
exit:
|
exit:
|
||||||
|
|
|
@ -520,7 +520,10 @@ static int test_for_elk(capture_info_t *capinfo, int elk, int mode7) {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ret;
|
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
|
// Grab one field
|
||||||
ret = rgb_to_fb(capinfo, flags);
|
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;
|
unsigned int t_compare = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// In mode 0..6, set BIT_CAL_COUNT to 1 (capture 1 field)
|
unsigned int flags = mode7 | BIT_CALIBRATE | ((elk & !mode7) ? BIT_ELK : 0) | (2 << OFFSET_NBUFFERS);
|
||||||
// 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);
|
// In mode 0..6, capture one field
|
||||||
|
// In mode 7, capture two fields
|
||||||
|
capinfo->ncapture = mode7 ? 2 : 1;
|
||||||
|
|
||||||
#ifdef INSTRUMENT_CAL
|
#ifdef INSTRUMENT_CAL
|
||||||
t = _get_cycle_counter();
|
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);
|
unsigned int flags = BIT_MODE7 | BIT_CALIBRATE | (2 << OFFSET_NBUFFERS);
|
||||||
|
|
||||||
|
// Capture two fields
|
||||||
|
capinfo->ncapture = 2;
|
||||||
|
|
||||||
// Grab a frame
|
// Grab a frame
|
||||||
int ret = rgb_to_fb(capinfo, flags);
|
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;
|
unsigned int t_compare = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// In mode 0..6, set BIT_CAL_COUNT to 1 (capture 1 field)
|
unsigned int flags = mode7 | BIT_CALIBRATE | ((elk & !mode7) ? BIT_ELK : 0) | (2 << OFFSET_NBUFFERS);
|
||||||
// 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);
|
// 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++) {
|
for (int i = 0; i < n; i++) {
|
||||||
int total = 0;
|
int total = 0;
|
||||||
|
@ -1039,6 +1049,7 @@ void rgb_to_hdmi_main() {
|
||||||
int fb_size_changed;
|
int fb_size_changed;
|
||||||
int active_size_decreased;
|
int active_size_decreased;
|
||||||
int clk_changed;
|
int clk_changed;
|
||||||
|
int ncapture;
|
||||||
|
|
||||||
capture_info_t last_capinfo;
|
capture_info_t last_capinfo;
|
||||||
clk_info_t last_clkinfo;
|
clk_info_t last_clkinfo;
|
||||||
|
@ -1051,6 +1062,9 @@ void rgb_to_hdmi_main() {
|
||||||
// Determine initial mode
|
// Determine initial mode
|
||||||
mode7 = rgb_to_fb(capinfo, BIT_PROBE) & BIT_MODE7 & !m7disable;
|
mode7 = rgb_to_fb(capinfo, BIT_PROBE) & BIT_MODE7 & !m7disable;
|
||||||
|
|
||||||
|
// Default to capturing indefinitely
|
||||||
|
ncapture = -1;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
// Switch the the approriate capinfo structure instance
|
// Switch the the approriate capinfo structure instance
|
||||||
|
@ -1073,7 +1087,6 @@ void rgb_to_hdmi_main() {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
log_debug("Entering rgb_to_fb");
|
|
||||||
int flags = mode7 | clear;
|
int flags = mode7 | clear;
|
||||||
if (!m7disable) {
|
if (!m7disable) {
|
||||||
flags |= BIT_MODE_DETECT;
|
flags |= BIT_MODE_DETECT;
|
||||||
|
@ -1104,18 +1117,20 @@ void rgb_to_hdmi_main() {
|
||||||
#ifdef MULTI_BUFFER
|
#ifdef MULTI_BUFFER
|
||||||
flags |= nbuffers << OFFSET_NBUFFERS;
|
flags |= nbuffers << OFFSET_NBUFFERS;
|
||||||
#endif
|
#endif
|
||||||
|
capinfo->ncapture = ncapture;
|
||||||
|
log_debug("Entering rgb_to_fb, flags=%08x", flags);
|
||||||
result = rgb_to_fb(capinfo, flags);
|
result = rgb_to_fb(capinfo, flags);
|
||||||
log_debug("Leaving rgb_to_fb, result=%04x", result);
|
log_debug("Leaving rgb_to_fb, result=%04x", result);
|
||||||
clear = 0;
|
clear = 0;
|
||||||
|
|
||||||
if (result & RET_SW1) {
|
if (result & RET_EXPIRED) {
|
||||||
osd_key(OSD_SW1);
|
ncapture = osd_key(OSD_EXPIRED);
|
||||||
}
|
} else if (result & RET_SW1) {
|
||||||
if (result & RET_SW2) {
|
ncapture = osd_key(OSD_SW1);
|
||||||
osd_key(OSD_SW2);
|
} else if (result & RET_SW2) {
|
||||||
}
|
ncapture = osd_key(OSD_SW2);
|
||||||
if (result & RET_SW3) {
|
} else if (result & RET_SW3) {
|
||||||
osd_key(OSD_SW3);
|
ncapture = osd_key(OSD_SW3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Possibly the size or offset has been adjusted, so update current capinfo
|
// Possibly the size or offset has been adjusted, so update current capinfo
|
||||||
|
|
Ładowanie…
Reference in New Issue