Extended clock calibration to correctly handle 624-line non-interlaced modes

Change-Id: I6aaf957512e0f9d77df89d835f8cf40b4d801506
issue_1022
David Banks 2017-04-30 12:55:40 +01:00
rodzic 4cf99c2a91
commit 127c804a5e
3 zmienionych plików z 42 dodań i 15 usunięć

Wyświetl plik

@ -30,4 +30,6 @@
#define CSYNC_MASK (1 << CSYNC_PIN)
#define MODE7_MASK (1 << MODE7_PIN)
#define INTERLACED_FLAG (1 << 31)
#endif

Wyświetl plik

@ -1,9 +1,6 @@
#include "rpi-base.h"
#include "defs.h"
// TODO:
// - calibration gives incorrect result in non-interlaced modes
.text
.global rgb_to_fb
.global measure_vsync
@ -307,26 +304,42 @@ measure_vsync:
// Initialize the cycle counter, and set r4=GPLEV0
bl init_timer_and_io
// wait for vsync, r6 contains the time of the subsequenct hsync rising edge
// wait for vsync, r6 contains the time of the subsequent hsync rising edge
bl wait_for_vsync
mov r0, r6
// Wait for a complete frame
// Wait for a first field of frame
bl wait_for_vsync
// Record field type
sub r6, r6, r7
cmp r6, #32768
movlt r3, #0 // Odd
movge r3, #1 // Even
// Wait for a second field of frame
bl wait_for_vsync
// Return the time for a complete frame (should be 40ms)
sub r0, r6, r0
// Test for non-interlaced by looking for two successive fields of the same type
sub r6, r6, r7
cmp r6, #32768
eorlt r3, r3, #1 // Odd
tst r3, #1
// Set bit 31 of result if frame was interlaced
orreq r0, r0, #INTERLACED_FLAG
pop {r4-r12, lr}
mov pc, lr
clear_screen:
mov r11, r0 // r0 is the start of the frame buffer
mov r11, r0 // r0 is the start of the frame buffer
mov r7, #0
mov r5, #512 // fixed 512 lines
mov r5, #512 // fixed 512 lines
clear_loop1:
mov r6, r2 // r2 is bytes per line
mov r6, r2 // r2 is bytes per line
clear_loop2:
str r7, [r11], #4
subs r6, r6, #4

Wyświetl plik

@ -199,16 +199,28 @@ int delay;
int calibrate_clock() {
int a = 13;
log_info("Nominal clock = %d", CORE_FREQ);
unsigned int frame_ref;
int frame_time = measure_vsync();
log_info(" Frame time = %dns", frame_time);
log_info(" Nominal clock = %d Hz", CORE_FREQ);
double error = (double) frame_time / (double) 40000000;
log_info(" Frame error = %d PPM", (int) ((error - 1.0) * 1e6));
unsigned int frame_time = measure_vsync();
if (frame_time & INTERLACED_FLAG) {
frame_ref = 40000000;
log_info("Nominal frame time = %d ns (interlaced)", frame_ref);
} else {
frame_ref = 40000000 - 64000;
log_info("Nominal frame time = %d ns (non-interlaced)", frame_ref);
}
frame_time &= ~INTERLACED_FLAG;
log_info(" Actual frame time = %d ns", frame_time);
double error = (double) frame_time / (double) frame_ref;
log_info(" Frame time error = %d PPM", (int) ((error - 1.0) * 1e6));
int new_clock = (int) (((double) CORE_FREQ) / error);
log_info(" Ideal clock = %d", new_clock);
log_info(" Optimal clock = %d Hz", new_clock);
// Sanity check clock
if (new_clock < 380000000 || new_clock > 388000000) {
@ -231,7 +243,7 @@ int calibrate_clock() {
// Check the new clock
int actual_clock = get_clock_rate(CORE_CLK_ID);
log_info(" New clock = %d", actual_clock);
log_info(" Final clock = %d Hz", actual_clock);
return a;
}