Pi Firmware: Remove need to specify n_lines (lines / frame)

Change-Id: Ia2409d346f27ef7798d6c3269c880b64f4ae03ae
pull/21/head
David Banks 2018-12-04 13:23:36 +00:00
rodzic 3badfc7535
commit 1ecf824152
6 zmienionych plików z 67 dodań i 48 usunięć

Wyświetl plik

@ -135,7 +135,6 @@ typedef struct {
typedef struct {
int clock; // sample clock frequency (Hz)
int line_len; // length of a line (in sample clocks)
int n_lines; // number of lines in a frame
} clk_info_t;
#endif // __ASSEMBLER__

Wyświetl plik

@ -10,8 +10,7 @@ enum {
FB_HEIGHT,
FB_BPP,
CLOCK,
LINE_LEN,
N_LINES,
LINE_LEN
};
static param_t params[] = {
@ -24,7 +23,6 @@ static param_t params[] = {
{ FB_BPP, "FB bits/pixel", 4, 8, 4 },
{ CLOCK, "Clock freq", 75000000, 100000000, 1 },
{ LINE_LEN, "Line length", 1000, 9999, 1 },
{ N_LINES, "Lines per frame", 500, 699, 1 },
{ -1, NULL, 0, 0, 0 },
};
@ -38,7 +36,6 @@ typedef struct {
int fb_bpp; // framebuffer bits per pixel
int clock; // cpld clock (in Hz)
int line_len; // number of clocks per horizontal line
int n_lines; // number of horizontal lines per frame (two fields)
} geometry_t;
static int mode7;
@ -73,7 +70,6 @@ void geometry_init(int version) {
mode7_geometry.fb_bpp = 4;
mode7_geometry.clock = 96000000;
mode7_geometry.line_len = 96 * 64;
mode7_geometry.n_lines = 625;
default_geometry.h_offset = 32;
default_geometry.v_offset = 21;
default_geometry.h_width = 672 / (32 / 4);
@ -83,7 +79,6 @@ void geometry_init(int version) {
default_geometry.fb_bpp = 4;
default_geometry.clock = 96000000;
default_geometry.line_len = 96 * 64;
default_geometry.n_lines = 625;
// For backwards compatibility with CPLDv1
int supports_delay = (((version >> VERSION_DESIGN_BIT) & 0x0F) == 0) &&
(((version >> VERSION_MAJOR_BIT ) & 0x0F) >= 2);
@ -121,8 +116,6 @@ int geometry_get_value(int num) {
return geometry->clock;
case LINE_LEN:
return geometry->line_len;
case N_LINES:
return geometry->n_lines;
}
return -1;
}
@ -157,9 +150,6 @@ void geometry_set_value(int num, int value) {
case LINE_LEN:
geometry->line_len = value;
break;
case N_LINES:
geometry->n_lines = value;
break;
}
}
@ -180,5 +170,4 @@ void geometry_get_fb_params(capture_info_t *capinfo) {
void geometry_get_clk_params(clk_info_t *clkinfo) {
clkinfo->clock = geometry->clock;
clkinfo->line_len = geometry->line_len;
clkinfo->n_lines = geometry->n_lines;
}

Wyświetl plik

@ -8,6 +8,7 @@
.text
.global rgb_to_fb
.global measure_vsync
.global measure_n_lines
.global sw1counter
.global sw2counter
.global sw3counter
@ -635,6 +636,43 @@ measure_vsync:
pop {r4-r12, pc}
// ======================================================================
// MEASURE_N_LINES
// ======================================================================
// TODO: We might want to mitigate the effects of any I-Cache misses
measure_n_lines:
push {r4-r12, lr}
// Setup R4 as a constant
ldr r4, =GPLEV0
// wait for vsync
bl wait_for_vsync
// skip 10 lines so we are well away from any double vsync pulses
mov r1, #10
measure_n_loop1:
WAIT_FOR_CSYNC_1
WAIT_FOR_CSYNC_0
subs r1, r1, #1
bne measure_n_loop1
READ_CYCLE_COUNTER r7
// now do the actual counting
measure_n_loop2:
WAIT_FOR_CSYNC_1
WAIT_FOR_CSYNC_0
subs r0, r0, #1
bne measure_n_loop2
READ_CYCLE_COUNTER r6
sub r0, r6, r7
pop {r4-r12, pc}
// ======================================================================
// CLEAR_SCREEN
// ======================================================================

Wyświetl plik

@ -9,6 +9,8 @@ extern int rgb_to_fb(capture_info_t *cap_info, int flags);
extern int measure_vsync();
extern int measure_n_lines(int n);
extern int sw1counter;
extern int sw2counter;

Wyświetl plik

@ -281,14 +281,12 @@ static int calibrate_sampling_clock() {
// Default values for the Beeb
clkinfo.clock = 96000000;
clkinfo.line_len = 64000;
clkinfo.n_lines = 625;
// Update from configuration
geometry_get_clk_params(&clkinfo);
log_info(" clkinfo.clock = %d Hz", clkinfo.clock);
log_info(" clkinfo.line_len = %d", clkinfo.line_len);
log_info(" clkinfo.n_lines = %d", clkinfo.n_lines);
// Pick the best value for core_freq and gpclk_divisor given the following constraints
// 1. Core Freq should be as high as possible, but <= 400MHz
@ -298,36 +296,20 @@ static int calibrate_sampling_clock() {
// i.e. gp_clk_divisor = floor(Core Freq * 3 / clkinfo.clock)
// and core_freq = clkinfo.clock * gp_clk_divisor / 3
int gpclk_divisor = 400000000 * 3 / clkinfo.clock;
int core_freq = clkinfo.clock * gpclk_divisor / 3;
int line_ref = (int) (1e9 * ((double) clkinfo.line_len) / ((double) clkinfo.clock));
int frame_ref = (int) (1e9 * ((double) clkinfo.line_len) * ((double) clkinfo.n_lines) / ((double) clkinfo.clock));
int gpclk_divisor = 400000000 * 3 / clkinfo.clock;
int core_freq = clkinfo.clock * gpclk_divisor / 3;
int nlines = 100; // Measure over N=100 lines
int nlines_ref_ns = nlines * (int) (1e9 * ((double) clkinfo.line_len) / ((double) clkinfo.clock));
int nlines_time_ns = measure_n_lines(nlines);
log_info(" GPCLK Divisor = %d", gpclk_divisor);
log_info("Nominal core clock = %d Hz", core_freq);
log_info(" Nominal Line time = %d ns", line_ref);
log_info("Nominal Frame time = %d ns", frame_ref);
log_info(" Nominal %3d lines = %d ns", nlines, nlines_ref_ns);
log_info(" Actual %3d lines = %d ns", nlines, nlines_time_ns);
vsync_time_ns = measure_vsync();
if (vsync_time_ns & INTERLACED_FLAG) {
log_info(" Target n lines = %d", clkinfo.n_lines);
log_info(" Target frame time = %d ns (interlaced)", frame_ref);
} else {
// If the video is non-interlaced and n_lines is odd, then loose a line
if (clkinfo.n_lines % 2) {
frame_ref -= line_ref;
}
log_info(" Target n lines = %d", clkinfo.n_lines);
log_info(" Target frame time = %d ns (non-interlaced)", frame_ref);
}
vsync_time_ns &= ~INTERLACED_FLAG;
log_info(" Actual frame time = %d ns", vsync_time_ns);
double error = (double) vsync_time_ns / (double) frame_ref;
double error = (double) nlines_time_ns / (double) nlines_ref_ns;
clock_error_ppm = ((error - 1.0) * 1e6);
log_info(" Frame time error = %d PPM", clock_error_ppm);
log_info(" Clock error = %d PPM", clock_error_ppm);
int new_clock;
if (abs(clock_error_ppm) > MAX_CLOCK_ERROR_PPM) {
@ -380,6 +362,17 @@ static int calibrate_sampling_clock() {
init_gpclk(GPCLK_SOURCE, gpclk_divisor);
log_debug("Done setting up divisor");
// Remeasure the vsync time
vsync_time_ns = measure_vsync();
// And log it
if (vsync_time_ns & INTERLACED_FLAG) {
vsync_time_ns &= ~INTERLACED_FLAG;
log_info(" Actual frame time = %d ns (interlaced)", vsync_time_ns);
} else {
log_info(" Actual frame time = %d ns (non-interlaced)", vsync_time_ns);
}
// Invalidate the current vlock mode to force an updated, as vsync_time_ns will have changed
current_vlockmode = -1;
@ -1276,7 +1269,7 @@ void rgb_to_hdmi_main() {
active_size_decreased = (capinfo->chars_per_line < last_capinfo.chars_per_line) || (capinfo->nlines < last_capinfo.nlines);
geometry_get_clk_params(&clkinfo);
clk_changed = (clkinfo.clock != last_clkinfo.clock) || (clkinfo.line_len != last_clkinfo.line_len) || (clkinfo.n_lines != last_clkinfo.n_lines);
clk_changed = (clkinfo.clock != last_clkinfo.clock) || (clkinfo.line_len != last_clkinfo.line_len);
last_mode7 = mode7;
mode7 = result & BIT_MODE7 & !m7disable;

Wyświetl plik

@ -65,7 +65,6 @@
# - FB Bits/pixel 4 or 8 4 4 | a Beeb or
# - Clock 75000000 100000000 96000000 96000000 | an Electron
# - Line Length 1000 9999 6144 6144 |
# - Lines per Frame 500 688 625 625 |
#
# Any number of these parameters can be specified but typically you would specify:
#
@ -83,7 +82,6 @@
# - FB Bits/pixel: defines the number of bits per pixel in the frame buffer (4 or 8)
# - Clock: the nominal sampling clock fed to the CPLD (in Hz)
# - Line Length: the length of a horizontal line (in sampling clocks)
# - Lines Per Frame: the number of horizontal lines per frame (two fields)
#
# info: the default info screen
# - 0 is the calibration summary
@ -185,16 +183,16 @@ sampling06=3 sampling7=0,2,2,2,2,2,2,0,8,5 info=1 palette=0 deinterlace=6 scanli
#sampling06=4 geometry06=23,26,100,270,800,540 info=1 palette=0 deinterlace=0 scanlines=0 mux=0 elk=0 vsync=0 vlockmode=0 nbuffers=2 debug=1 m7disable=1
#
# Here's an example that might work with an Atom (CPLDv1) (narrow border)
#sampling06=0,5,5,5,5,5,5,0 geometry06=3,37,66,200,528,400,4,85909091,5472,524 nbuffers=2 m7disable=1
#sampling06=0,5,5,5,5,5,5,0 geometry06=3,37,66,200,528,400,4,85909091,5472 nbuffers=2 m7disable=1
#
# Here's an example that might work with an Atom (CPLDv1) (wider border)
#sampling06=0,5,5,5,5,5,5,0 geometry06=0,31,69,212,552,424,4,85909091,5472,524 nbuffers=2 m7disable=1
#sampling06=0,5,5,5,5,5,5,0 geometry06=0,31,69,212,552,424,4,85909091,5472 nbuffers=2 m7disable=1
#
# Here's an example that might work with an Atom (CPLDv2) (even wider border)
#sampling06=0,5,5,5,5,5,5,0 geometry06=24,16,76,240,608,480,4,85909091,5472,524 nbuffers=2 m7disable=1
#sampling06=0,5,5,5,5,5,5,0 geometry06=24,16,76,240,608,480,4,85909091,5472 nbuffers=2 m7disable=1
#
# Here's an example that might work with an Atom (Atom CPLD)
#sampling06=0 geometry06=19,11,76,240,608,480,8,57272720,3648,524 palette=10 nbuffers=2 m7disable=1 keymap=1233232
#sampling06=0 geometry06=19,11,76,240,608,480,8,57272720,3648 palette=10 nbuffers=2 m7disable=1 keymap=1233232
#
# Here's an example that might work with a ZX80/ZX81
#sampling06=0,4,4,4,4,4,4,0 geometry06=9,18,84,270,672,540,4,78000000,4968,620 nbuffers=2 m7disable=1 keymap=1323232 return=0
#sampling06=0,4,4,4,4,4,4,0 geometry06=9,18,84,270,672,540,4,78000000,4968 nbuffers=2 m7disable=1 keymap=1323232 return=0