Skip to content

Commit

Permalink
Pi Firmware: implemented capture of N frames and OSD_EXPIRED for dela…
Browse files Browse the repository at this point in the history
…yed exit of OSD

Change-Id: I93a75ae4f6fb34fc778250431d65c63fd7593579
  • Loading branch information
hoglet67 committed Nov 18, 2018
1 parent 8212858 commit bb06d34
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 38 deletions.
5 changes: 4 additions & 1 deletion src/defs.h
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -125,6 +126,7 @@
#define O_NLINES 20
#define O_H_OFFSET 24
#define O_V_OFFSET 28
#define O_NCAPTURE 32

#else

Expand All @@ -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 {
Expand Down
17 changes: 8 additions & 9 deletions src/osd.c
Expand Up @@ -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:
Expand Down Expand Up @@ -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) {

Expand All @@ -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;
Expand Down Expand Up @@ -928,6 +926,7 @@ void osd_key(int key) {
}
break;
}
return ret;
}

void osd_init() {
Expand Down
9 changes: 5 additions & 4 deletions 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)

Expand Down Expand Up @@ -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();
Expand Down
26 changes: 18 additions & 8 deletions src/rgb_to_fb.S
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -994,14 +999,19 @@ skip_osd_update:
FLIP_BUFFER
#endif

// Loop back if not calibrate mode...
tst r3, #BIT_CALIBRATE
beq 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
// 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

// Setup the response code
mov r0, r3
and r0, #BIT_MODE7
orr r0, #RET_EXPIRED

// Return
exit:
Expand Down
47 changes: 31 additions & 16 deletions src/rgb_to_hdmi.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit bb06d34

Please sign in to comment.