kopia lustrzana https://github.com/hoglet67/RGBtoHDMI
Pi Firmware: Test build for issue 1022
Change-Id: I49a18b786aabfdc46747a019a75a333f01790594issue_1022
rodzic
695249b650
commit
1d1ed94aac
|
@ -61,17 +61,12 @@ file( GLOB core_files
|
|||
armc-cstartup.c
|
||||
armc-cstubs.c
|
||||
rgb_to_hdmi.c
|
||||
rgb_to_fb.S
|
||||
defs.h
|
||||
arm-exception.c
|
||||
cache.c
|
||||
cache.h
|
||||
rpi-gpio.c
|
||||
rpi-gpio.h
|
||||
rpi-aux.c
|
||||
rpi-aux.h
|
||||
rpi-interrupts.c
|
||||
rpi-interrupts.h
|
||||
rpi-mailbox.c
|
||||
rpi-mailbox.h
|
||||
rpi-mailbox-interface.c
|
||||
|
@ -80,15 +75,6 @@ file( GLOB core_files
|
|||
info.h
|
||||
logging.c
|
||||
logging.h
|
||||
cpld.h
|
||||
cpld_normal.h
|
||||
cpld_normal.c
|
||||
cpld_alternative.h
|
||||
cpld_alternative.c
|
||||
osd.h
|
||||
osd.c
|
||||
saa5050_font.h
|
||||
saa5050_font.c
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,782 +1,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include "cache.h"
|
||||
#include "defs.h"
|
||||
#include "cpld.h"
|
||||
#include "rpi-aux.h"
|
||||
#include "rpi-mailbox-interface.h"
|
||||
#include "info.h"
|
||||
#include "logging.h"
|
||||
#include "rpi-aux.h"
|
||||
#include "rpi-gpio.h"
|
||||
#include "rpi-mailbox-interface.h"
|
||||
#include "startup.h"
|
||||
#include "rpi-mailbox.h"
|
||||
#include "osd.h"
|
||||
#include "cpld.h"
|
||||
#include "cpld_normal.h"
|
||||
#include "cpld_alternative.h"
|
||||
|
||||
// #define INSTRUMENT_CAL
|
||||
#define NUM_CAL_PASSES 1
|
||||
|
||||
#define SHORT_PRESS 0
|
||||
#define LONG_PRESS 1
|
||||
|
||||
#ifdef DOUBLE_BUFFER
|
||||
#include "rpi-interrupts.h"
|
||||
#endif
|
||||
|
||||
typedef void (*func_ptr)();
|
||||
|
||||
#define GZ_CLK_BUSY (1 << 7)
|
||||
#define GP_CLK1_CTL (volatile uint32_t *)(PERIPHERAL_BASE + 0x101078)
|
||||
#define GP_CLK1_DIV (volatile uint32_t *)(PERIPHERAL_BASE + 0x10107C)
|
||||
|
||||
// =============================================================
|
||||
// Global variables
|
||||
// =============================================================
|
||||
|
||||
cpld_t *cpld = NULL;
|
||||
unsigned char *fb = NULL;
|
||||
int pitch = 0;
|
||||
int clock_error_ppm = 0;
|
||||
|
||||
// =============================================================
|
||||
// Local variables
|
||||
// =============================================================
|
||||
|
||||
static int width = 0;
|
||||
static int height = 0;
|
||||
static uint32_t cpld_version_id;
|
||||
static volatile int delay;
|
||||
static int elk;
|
||||
static int mode7;
|
||||
static int clear;
|
||||
static int scanlines = 0;
|
||||
static int last_mode7;
|
||||
static int result;
|
||||
static int chars_per_line;
|
||||
|
||||
// TODO: Don't hardcode pitch!
|
||||
static unsigned char last[SCREEN_HEIGHT * 336] __attribute__((aligned(32)));
|
||||
|
||||
#ifndef USE_PROPERTY_INTERFACE_FOR_FB
|
||||
typedef struct {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t virtual_width;
|
||||
uint32_t virtual_height;
|
||||
volatile uint32_t pitch;
|
||||
volatile uint32_t depth;
|
||||
uint32_t x_offset;
|
||||
uint32_t y_offset;
|
||||
volatile uint32_t pointer;
|
||||
volatile uint32_t size;
|
||||
} framebuf;
|
||||
// The + 0x10000 is to miss the property buffer
|
||||
static framebuf *fbp = (framebuf *) (UNCACHED_MEM_BASE + 0x10000);
|
||||
#endif
|
||||
|
||||
// =============================================================
|
||||
// External symbols from rgb_to_fb.S
|
||||
// =============================================================
|
||||
|
||||
extern int rgb_to_fb(unsigned char *fb, int chars_per_line, int bytes_per_line, int mode7);
|
||||
extern int measure_vsync();
|
||||
|
||||
|
||||
// =============================================================
|
||||
// Private methods
|
||||
// =============================================================
|
||||
|
||||
|
||||
// 0 0 Hz Ground
|
||||
// 1 19.2 MHz oscillator
|
||||
// 2 0 Hz testdebug0
|
||||
// 3 0 Hz testdebug1
|
||||
// 4 0 Hz PLLA
|
||||
// 5 1000 MHz PLLC (changes with overclock settings)
|
||||
// 6 500 MHz PLLD
|
||||
// 7 216 MHz HDMI auxiliary
|
||||
// 8-15 0 Hz Ground
|
||||
|
||||
|
||||
// Source 1 = OSC = 19.2MHz
|
||||
// Source 4 = PLLA = 0MHz
|
||||
// Source 5 = PLLC = core_freq * 3 = (384 * 3) = 1152
|
||||
// Source 6 = PLLD = 500MHz
|
||||
|
||||
static void init_gpclk(int source, int divisor) {
|
||||
log_debug("A GP_CLK1_DIV = %08"PRIx32, *GP_CLK1_DIV);
|
||||
|
||||
log_debug("B GP_CLK1_CTL = %08"PRIx32, *GP_CLK1_CTL);
|
||||
|
||||
// Stop the clock generator
|
||||
*GP_CLK1_CTL = 0x5a000000 | source;
|
||||
|
||||
// Wait for BUSY low
|
||||
log_debug("C GP_CLK1_CTL = %08"PRIx32, *GP_CLK1_CTL);
|
||||
while ((*GP_CLK1_CTL) & GZ_CLK_BUSY) {}
|
||||
log_debug("D GP_CLK1_CTL = %08"PRIx32, *GP_CLK1_CTL);
|
||||
|
||||
// Configure the clock generator
|
||||
*GP_CLK1_DIV = 0x5A000000 | (divisor << 12);
|
||||
*GP_CLK1_CTL = 0x5A000000 | source;
|
||||
|
||||
log_debug("E GP_CLK1_CTL = %08"PRIx32, *GP_CLK1_CTL);
|
||||
|
||||
// Start the clock generator
|
||||
*GP_CLK1_CTL = 0x5A000010 | source;
|
||||
|
||||
log_debug("F GP_CLK1_CTL = %08"PRIx32, *GP_CLK1_CTL);
|
||||
while (!((*GP_CLK1_CTL) & GZ_CLK_BUSY)) {} // Wait for BUSY high
|
||||
log_debug("G GP_CLK1_CTL = %08"PRIx32, *GP_CLK1_CTL);
|
||||
|
||||
log_debug("H GP_CLK1_DIV = %08"PRIx32, *GP_CLK1_DIV);
|
||||
}
|
||||
|
||||
#ifdef USE_PROPERTY_INTERFACE_FOR_FB
|
||||
|
||||
static void init_framebuffer(int mode7) {
|
||||
|
||||
rpi_mailbox_property_t *mp;
|
||||
|
||||
int w = mode7 ? SCREEN_WIDTH_MODE7 : SCREEN_WIDTH_MODE06;
|
||||
|
||||
/* Initialise a framebuffer... */
|
||||
RPI_PropertyInit();
|
||||
RPI_PropertyAddTag( TAG_ALLOCATE_BUFFER );
|
||||
RPI_PropertyAddTag( TAG_SET_PHYSICAL_SIZE, w, SCREEN_HEIGHT );
|
||||
#ifdef DOUBLE_BUFFER
|
||||
RPI_PropertyAddTag( TAG_SET_VIRTUAL_SIZE, w, SCREEN_HEIGHT * 2 );
|
||||
#else
|
||||
RPI_PropertyAddTag( TAG_SET_VIRTUAL_SIZE, w, SCREEN_HEIGHT );
|
||||
#endif
|
||||
RPI_PropertyAddTag( TAG_SET_DEPTH, SCREEN_DEPTH );
|
||||
if (SCREEN_DEPTH <= 8) {
|
||||
RPI_PropertyAddTag( TAG_SET_PALETTE, osd_get_palette());
|
||||
}
|
||||
RPI_PropertyAddTag( TAG_GET_PITCH );
|
||||
RPI_PropertyAddTag( TAG_GET_PHYSICAL_SIZE );
|
||||
RPI_PropertyAddTag( TAG_GET_DEPTH );
|
||||
|
||||
RPI_PropertyProcess();
|
||||
|
||||
// FIXME: A small delay (like the log) is neccessary here
|
||||
// or the RPI_PropertyGet seems to return garbage
|
||||
log_info( "Initialised Framebuffer" );
|
||||
|
||||
if( ( mp = RPI_PropertyGet( TAG_GET_PHYSICAL_SIZE ) ) )
|
||||
{
|
||||
width = mp->data.buffer_32[0];
|
||||
height = mp->data.buffer_32[1];
|
||||
|
||||
log_info( "Size: %dx%d ", width, height );
|
||||
}
|
||||
|
||||
if( ( mp = RPI_PropertyGet( TAG_GET_PITCH ) ) )
|
||||
{
|
||||
pitch = mp->data.buffer_32[0];
|
||||
log_info( "Pitch: %d bytes", pitch );
|
||||
}
|
||||
|
||||
if( ( mp = RPI_PropertyGet( TAG_ALLOCATE_BUFFER ) ) )
|
||||
{
|
||||
fb = (unsigned char*)mp->data.buffer_32[0];
|
||||
log_info( "Framebuffer address: %8.8X", (unsigned int)fb );
|
||||
}
|
||||
|
||||
// On the Pi 2/3 the mailbox returns the address with bits 31..30 set, which is wrong
|
||||
fb = (unsigned char *)(((unsigned int) fb) & 0x3fffffff);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// An alternative way to initialize the framebuffer using mailbox channel 1
|
||||
//
|
||||
// I was hoping it would then be possible to page flip just by modifying the structure
|
||||
// in-place. Unfortunately that didn't work, but the code might be useful in the future.
|
||||
|
||||
static void init_framebuffer(int mode7) {
|
||||
log_info( "Framebuf struct address: %p", fbp );
|
||||
|
||||
int w = mode7 ? SCREEN_WIDTH_MODE7 : SCREEN_WIDTH_MODE06;
|
||||
|
||||
// Fill in the frame buffer structure
|
||||
fbp->width = w;
|
||||
fbp->height = SCREEN_HEIGHT;
|
||||
fbp->virtual_width = w;
|
||||
#ifdef DOUBLE_BUFFER
|
||||
fbp->virtual_height = SCREEN_HEIGHT * 2;
|
||||
#else
|
||||
fbp->virtual_height = SCREEN_HEIGHT;
|
||||
#endif
|
||||
fbp->pitch = 0;
|
||||
fbp->depth = SCREEN_DEPTH;
|
||||
fbp->x_offset = 0;
|
||||
fbp->y_offset = 0;
|
||||
fbp->pointer = 0;
|
||||
fbp->size = 0;
|
||||
|
||||
// Send framebuffer struct to the mailbox
|
||||
//
|
||||
// The +0x40000000 ensures the GPU bypasses it's cache when accessing
|
||||
// the framebuffer struct. If this is not done, the screen still initializes
|
||||
// but the ARM doesn't see the updated value for a very long time
|
||||
// i.e. the commented out section of code below is needed, and this eventually
|
||||
// exits with i=4603039
|
||||
//
|
||||
// 0xC0000000 should be added if disable_l2cache=1
|
||||
RPI_Mailbox0Write(MB0_FRAMEBUFFER, ((unsigned int)fbp) + 0xC0000000 );
|
||||
|
||||
// Wait for the response (0)
|
||||
RPI_Mailbox0Read( MB0_FRAMEBUFFER );
|
||||
|
||||
pitch = fbp->pitch;
|
||||
fb = (unsigned char*)(fbp->pointer);
|
||||
width = fbp->width;
|
||||
height = fbp->height;
|
||||
|
||||
// See comment above
|
||||
// int i = 0;
|
||||
// while (!pitch || !fb) {
|
||||
// pitch = fbp->pitch;
|
||||
// fb = (unsigned char*)(fbp->pointer);
|
||||
// i++;
|
||||
// }
|
||||
// log_info( "i=%d", i);
|
||||
|
||||
log_info( "Initialised Framebuffer: %dx%d ", width, height );
|
||||
log_info( "Pitch: %d bytes", pitch );
|
||||
log_info( "Framebuffer address: %8.8X", (unsigned int)fb );
|
||||
|
||||
// Initialize the palette
|
||||
if (SCREEN_DEPTH <= 8) {
|
||||
RPI_PropertyInit();
|
||||
RPI_PropertyAddTag( TAG_SET_PALETTE, osd_get_palette());
|
||||
RPI_PropertyProcess();
|
||||
}
|
||||
|
||||
// On the Pi 2/3 the mailbox returns the address with bits 31..30 set, which is wrong
|
||||
fb = (unsigned char *)(((unsigned int) fb) & 0x3fffffff);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int calibrate_clock() {
|
||||
int a = 13;
|
||||
unsigned int frame_ref;
|
||||
|
||||
log_info(" Nominal clock = %d Hz", CORE_FREQ);
|
||||
|
||||
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;
|
||||
clock_error_ppm = ((error - 1.0) * 1e6);
|
||||
log_info(" Frame time error = %d PPM", clock_error_ppm );
|
||||
|
||||
int new_clock = (int) (((double) CORE_FREQ) / error);
|
||||
log_info(" Optimal clock = %d Hz", new_clock);
|
||||
|
||||
// Sanity check clock
|
||||
if (new_clock < 380000000 || new_clock > 388000000) {
|
||||
log_info("Clock out of range 380MHz-388MHz, defaulting to 384MHz");
|
||||
new_clock = CORE_FREQ;
|
||||
}
|
||||
|
||||
// Wait a while to allow UART time to empty
|
||||
for (delay = 0; delay < 100000; delay++) {
|
||||
a = a * 13;
|
||||
}
|
||||
|
||||
// Switch to new core clock speed
|
||||
RPI_PropertyInit();
|
||||
RPI_PropertyAddTag( TAG_SET_CLOCK_RATE, CORE_CLK_ID, new_clock, 1);
|
||||
RPI_PropertyProcess();
|
||||
|
||||
// Re-initialize UART, as system clock rate changed
|
||||
RPI_AuxMiniUartInit( 115200, 8 );
|
||||
|
||||
// Check the new clock
|
||||
int actual_clock = get_clock_rate(CORE_CLK_ID);
|
||||
log_info(" Final clock = %d Hz", actual_clock);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static void init_hardware() {
|
||||
int i;
|
||||
for (i = 0; i < 12; i++) {
|
||||
RPI_SetGpioPinFunction(PIXEL_BASE + i, FS_INPUT);
|
||||
}
|
||||
RPI_SetGpioPinFunction(PSYNC_PIN, FS_INPUT);
|
||||
RPI_SetGpioPinFunction(CSYNC_PIN, FS_INPUT);
|
||||
RPI_SetGpioPinFunction(SW1_PIN, FS_INPUT);
|
||||
RPI_SetGpioPinFunction(SW2_PIN, FS_INPUT);
|
||||
RPI_SetGpioPinFunction(SW3_PIN, FS_INPUT);
|
||||
RPI_SetGpioPinFunction(SPARE_PIN, FS_INPUT);
|
||||
|
||||
RPI_SetGpioPinFunction(VERSION_PIN, FS_OUTPUT);
|
||||
RPI_SetGpioPinFunction(MODE7_PIN, FS_OUTPUT);
|
||||
RPI_SetGpioPinFunction(MUX_PIN, FS_OUTPUT);
|
||||
RPI_SetGpioPinFunction(SP_CLK_PIN, FS_OUTPUT);
|
||||
RPI_SetGpioPinFunction(SP_DATA_PIN, FS_OUTPUT);
|
||||
RPI_SetGpioPinFunction(SP_CLKEN_PIN, FS_OUTPUT);
|
||||
RPI_SetGpioPinFunction(LED1_PIN, FS_OUTPUT);
|
||||
|
||||
RPI_SetGpioValue(VERSION_PIN, 1);
|
||||
RPI_SetGpioValue(MODE7_PIN, 1);
|
||||
RPI_SetGpioValue(MUX_PIN, 0);
|
||||
RPI_SetGpioValue(SP_CLK_PIN, 1);
|
||||
RPI_SetGpioValue(SP_DATA_PIN, 0);
|
||||
RPI_SetGpioValue(SP_CLKEN_PIN, 0);
|
||||
RPI_SetGpioValue(LED1_PIN, 0); // active high
|
||||
|
||||
#ifdef DOUBLE_BUFFER
|
||||
// This line enables IRQ interrupts
|
||||
// Enable smi_int which is IRQ 48
|
||||
// https://github.com/raspberrypi/firmware/issues/67
|
||||
RPI_GetIrqController()->Enable_IRQs_2 = (1 << VSYNCINT);
|
||||
#endif
|
||||
|
||||
// Initialize hardware cycle counter
|
||||
_init_cycle_counter();
|
||||
|
||||
// Configure the GPCLK pin as a GPCLK
|
||||
RPI_SetGpioPinFunction(GPCLK_PIN, FS_ALT5);
|
||||
|
||||
// The divisor us now the same for both modes
|
||||
log_debug("Setting up divisor");
|
||||
init_gpclk(GPCLK_SOURCE, DEFAULT_GPCLK_DIVISOR);
|
||||
log_debug("Done setting up divisor");
|
||||
|
||||
// Measure the frame time and set a clock to 384MHz +- the error
|
||||
calibrate_clock();
|
||||
|
||||
// Initialise the info system with cached values (as we break the GPU property interface)
|
||||
init_info();
|
||||
|
||||
#ifdef DEBUG
|
||||
dump_useful_info();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void cpld_init() {
|
||||
// Assert the active low version pin
|
||||
RPI_SetGpioValue(VERSION_PIN, 0);
|
||||
// The CPLD now outputs a identifier and version number on the 12-bit pixel quad bus
|
||||
cpld_version_id = 0;
|
||||
for (int i = PIXEL_BASE + 11; i >= PIXEL_BASE; i--) {
|
||||
cpld_version_id <<= 1;
|
||||
cpld_version_id |= RPI_GetGpioValue(i) & 1;
|
||||
}
|
||||
// Release the active low version pin
|
||||
RPI_SetGpioValue(VERSION_PIN, 1);
|
||||
|
||||
// Set the appropriate cpld "driver" based on the version
|
||||
if ((cpld_version_id >> VERSION_DESIGN_BIT) == DESIGN_NORMAL) {
|
||||
cpld = &cpld_normal;
|
||||
} else if ((cpld_version_id >> VERSION_DESIGN_BIT) == DESIGN_ALTERNATIVE) {
|
||||
cpld = &cpld_alternative;
|
||||
} else {
|
||||
log_info("Unknown CPLD: identifier = %03x", cpld_version_id);
|
||||
log_info("Halting\n");
|
||||
while (1);
|
||||
}
|
||||
log_info("CPLD Design: %s", cpld->name);
|
||||
log_info("CPLD Version: %x.%x", (cpld_version_id >> VERSION_MAJOR_BIT) & 0x0f, (cpld_version_id >> VERSION_MINOR_BIT) & 0x0f);
|
||||
|
||||
// Initialize the CPLD's default sampling points
|
||||
cpld->init();
|
||||
}
|
||||
|
||||
static int test_for_elk(int elk, int mode7, int chars_per_line) {
|
||||
|
||||
// If mode 7, then assume the Beeb
|
||||
if (mode7) {
|
||||
// Leave the setting unchanged
|
||||
return elk;
|
||||
}
|
||||
|
||||
unsigned int ret;
|
||||
unsigned int flags = BIT_CALIBRATE | BIT_CAL_COUNT;
|
||||
|
||||
// Grab one field
|
||||
ret = rgb_to_fb(fb, chars_per_line, pitch, flags);
|
||||
unsigned char *fb1 = fb + ((ret & BIT_LAST_BUFFER) ? SCREEN_HEIGHT * pitch : 0);
|
||||
|
||||
// Grab second field
|
||||
ret = rgb_to_fb(fb, chars_per_line, pitch, flags);
|
||||
unsigned char *fb2 = fb + ((ret & BIT_LAST_BUFFER) ? SCREEN_HEIGHT * pitch : 0);
|
||||
|
||||
if (fb1 == fb2) {
|
||||
log_warn("test_for_elk() failed, both buffers the same!");
|
||||
// Leave the setting unchanged
|
||||
return elk;
|
||||
}
|
||||
|
||||
unsigned int min_diff = INT_MAX;
|
||||
unsigned int min_offset = 0;
|
||||
|
||||
for (int offset = -2; offset <= 2; offset += 2) {
|
||||
|
||||
uint32_t *p1 = (uint32_t *)(fb1 + 2 * pitch);
|
||||
uint32_t *p2 = (uint32_t *)(fb2 + 2 * pitch + offset * pitch);
|
||||
unsigned int diff = 0;
|
||||
for (int i = 0; i < (SCREEN_HEIGHT - 4) * pitch; i += 4) {
|
||||
uint32_t d = (*p1++) ^ (*p2++);
|
||||
while (d) {
|
||||
if (d & 0x0F) {
|
||||
diff++;
|
||||
}
|
||||
d >>= 4;
|
||||
}
|
||||
}
|
||||
if (diff < min_diff) {
|
||||
min_diff = diff;
|
||||
min_offset = offset;
|
||||
}
|
||||
log_debug("offset = %d, diff = %u", offset, diff);
|
||||
|
||||
}
|
||||
log_debug("min offset = %d", min_offset);
|
||||
return min_offset != 0;
|
||||
}
|
||||
|
||||
#ifdef HAS_MULTICORE
|
||||
static void start_core(int core, func_ptr func) {
|
||||
printf("starting core %d\r\n", core);
|
||||
*(unsigned int *)(0x4000008C + 0x10 * core) = (unsigned int) func;
|
||||
}
|
||||
#endif
|
||||
|
||||
// =============================================================
|
||||
// Public methods
|
||||
// =============================================================
|
||||
|
||||
int *diff_N_frames(int n, int mode7, int elk, int chars_per_line) {
|
||||
|
||||
unsigned int ret;
|
||||
static int sum[3];
|
||||
static int min[3];
|
||||
static int max[3];
|
||||
static int diff[3];
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
sum[i] = 0;
|
||||
min[i] = INT_MAX;
|
||||
max[i] = INT_MIN;
|
||||
}
|
||||
|
||||
#ifdef INSTRUMENT_CAL
|
||||
unsigned int t;
|
||||
unsigned int t_capture = 0;
|
||||
unsigned int t_memcpy = 0;
|
||||
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);
|
||||
|
||||
#ifdef INSTRUMENT_CAL
|
||||
t = _get_cycle_counter();
|
||||
#endif
|
||||
// Grab an initial frame
|
||||
ret = rgb_to_fb(fb, chars_per_line, pitch, flags);
|
||||
#ifdef INSTRUMENT_CAL
|
||||
t_capture += _get_cycle_counter() - t;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
diff[0] = 0;
|
||||
diff[1] = 0;
|
||||
diff[2] = 0;
|
||||
|
||||
#ifdef INSTRUMENT_CAL
|
||||
t = _get_cycle_counter();
|
||||
#endif
|
||||
// Save the last frame
|
||||
memcpy((void *)last, (void *)(fb + ((ret & BIT_LAST_BUFFER) ? SCREEN_HEIGHT * pitch : 0)), SCREEN_HEIGHT * pitch);
|
||||
#ifdef INSTRUMENT_CAL
|
||||
t_memcpy += _get_cycle_counter() - t;
|
||||
t = _get_cycle_counter();
|
||||
#endif
|
||||
// Grab the next frame
|
||||
ret = rgb_to_fb(fb, chars_per_line, pitch, flags);
|
||||
#ifdef INSTRUMENT_CAL
|
||||
t_capture += _get_cycle_counter() - t;
|
||||
t = _get_cycle_counter();
|
||||
#endif
|
||||
// Compare the frames
|
||||
uint32_t *fbp = (uint32_t *)(fb + ((ret & BIT_LAST_BUFFER) ? SCREEN_HEIGHT * pitch : 0));
|
||||
uint32_t *lastp = (uint32_t *)last;
|
||||
for (int line = 0; line < SCREEN_HEIGHT; line++) {
|
||||
int skip = 0;
|
||||
// Skip lines that might contain flashing cursor
|
||||
// (the cursor rows were determined empirically)
|
||||
if (elk) {
|
||||
// Eliminate cursor lines in 32 row modes (0,1,2,4,5)
|
||||
if (!mode7 && ((line >> 1) % 8) == 5) {
|
||||
skip = 1;
|
||||
}
|
||||
// Eliminate cursor lines in 25 row modes (3, 6)
|
||||
if (!mode7 && ((line >> 1) % 10) == 3) {
|
||||
skip = 1;
|
||||
}
|
||||
// Eliminate cursor lines in mode 7
|
||||
// (this case is untested as I don't have a Jafa board)
|
||||
if (mode7 && ((line % 20) == 13 || (line % 20) == 14)) {
|
||||
skip = 1;
|
||||
}
|
||||
} else {
|
||||
// Eliminate cursor lines in 32 row modes (0,1,2,4,5)
|
||||
if (!mode7 && ((line >> 1) % 8) == 7) {
|
||||
skip = 1;
|
||||
}
|
||||
// Eliminate cursor lines in 25 row modes (3, 6)
|
||||
if (!mode7 && ((line >> 1) % 10) >= 5 && ((line >> 1) % 10) <= 7) {
|
||||
skip = 1;
|
||||
}
|
||||
// Eliminate cursor lines in mode 7
|
||||
if (mode7 && ((line % 20) == 13 || (line % 20) == 14)) {
|
||||
skip = 1;
|
||||
}
|
||||
}
|
||||
if (skip) {
|
||||
// For debugging it's useful to see if the lines being eliminated align with the cursor
|
||||
// for (int x = 0; x < pitch; x += 4) {
|
||||
// *fbp++ = 0x11111111;
|
||||
// }
|
||||
fbp += pitch >> 2;
|
||||
lastp += pitch >> 2;
|
||||
} else {
|
||||
for (int x = 0; x < pitch; x += 4) {
|
||||
uint32_t d = (*fbp++) ^ (*lastp++);
|
||||
// Mask out OSD
|
||||
d &= 0x77777777;
|
||||
while (d) {
|
||||
if (d & 0x01) {
|
||||
diff[0]++;
|
||||
}
|
||||
if (d & 0x02) {
|
||||
diff[1]++;
|
||||
}
|
||||
if (d & 0x04) {
|
||||
diff[2]++;
|
||||
}
|
||||
d >>= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef INSTRUMENT_CAL
|
||||
t_compare += _get_cycle_counter() - t;
|
||||
#endif
|
||||
|
||||
// Accumulate the result
|
||||
for (int j = 0; j < 3; j++) {
|
||||
sum[j] += diff[j];
|
||||
if (diff[j] < min[j]) {
|
||||
min[j] = diff[j];
|
||||
}
|
||||
if (diff[j] > max[j]) {
|
||||
max[j] = diff[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (int j = 0; j < 3; j++) {
|
||||
int mean = sum[j] / n;
|
||||
log_debug("channel %d: diff: sum = %d mean = %d, min = %d, max = %d", j, sum[j], mean, min[j], max[j]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef INSTRUMENT_CAL
|
||||
log_debug("t_capture total = %d, mean = %d ", t_capture, t_capture / (n + 1));
|
||||
log_debug("t_compare total = %d, mean = %d ", t_compare, t_compare / n);
|
||||
log_debug("t_memcpy total = %d, mean = %d ", t_memcpy, t_memcpy / n);
|
||||
log_debug("total = %d", t_capture + t_compare + t_memcpy);
|
||||
#endif
|
||||
return sum;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int total_N_frames(int n, int mode7, int elk, int chars_per_line) {
|
||||
|
||||
int sum = 0;
|
||||
int min = INT_MAX;
|
||||
int max = INT_MIN;
|
||||
|
||||
#ifdef INSTRUMENT_CAL
|
||||
unsigned int t;
|
||||
unsigned int t_capture = 0;
|
||||
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);
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
int total = 0;
|
||||
|
||||
// Grab the next frame
|
||||
ret = rgb_to_fb(fb, chars_per_line, pitch, flags);
|
||||
#ifdef INSTRUMENT_CAL
|
||||
t_capture += _get_cycle_counter() - t;
|
||||
t = _get_cycle_counter();
|
||||
#endif
|
||||
// Compare the frames
|
||||
uint32_t *fbp = (uint32_t *)(fb + ((ret & BIT_LAST_BUFFER) ? SCREEN_HEIGHT * pitch : 0));
|
||||
for (int j = 0; j < SCREEN_HEIGHT * pitch; j += 4) {
|
||||
uint32_t f = *fbp++;
|
||||
// Mask out OSD
|
||||
f &= 0x77777777;
|
||||
while (f) {
|
||||
if (f & 0x0F) {
|
||||
total++;
|
||||
}
|
||||
f >>= 4;
|
||||
}
|
||||
}
|
||||
#ifdef INSTRUMENT_CAL
|
||||
t_compare += _get_cycle_counter() - t;
|
||||
#endif
|
||||
|
||||
// Accumulate the result
|
||||
sum += total;
|
||||
if (total < min) {
|
||||
min = total;
|
||||
}
|
||||
if (total > max) {
|
||||
max = total;
|
||||
}
|
||||
}
|
||||
|
||||
int mean = sum / n;
|
||||
log_debug("total: sum = %d mean = %d, min = %d, max = %d", sum, mean, min, max);
|
||||
#ifdef INSTRUMENT_CAL
|
||||
log_debug("t_capture total = %d, mean = %d ", t_capture, t_capture / (n + 1));
|
||||
log_debug("t_compare total = %d, mean = %d ", t_compare, t_compare / n);
|
||||
log_debug("total = %d", t_capture + t_compare + t_memcpy);
|
||||
#endif
|
||||
return sum;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DOUBLE_BUFFER
|
||||
void swapBuffer(int buffer) {
|
||||
// Flush the previous response from the GPU->ARM mailbox
|
||||
// Doing it like this avoids stalling for the response
|
||||
RPI_Mailbox0Flush( MB0_TAGS_ARM_TO_VC );
|
||||
RPI_PropertyInit();
|
||||
if (buffer) {
|
||||
RPI_PropertyAddTag( TAG_SET_VIRTUAL_OFFSET, 0, SCREEN_HEIGHT);
|
||||
} else {
|
||||
RPI_PropertyAddTag( TAG_SET_VIRTUAL_OFFSET, 0, 0);
|
||||
}
|
||||
// Use version that doesn't wait for the response
|
||||
RPI_PropertyProcessNoCheck();
|
||||
}
|
||||
#endif
|
||||
|
||||
void set_elk(int on) {
|
||||
elk = on;
|
||||
clear = BIT_CLEAR;
|
||||
}
|
||||
|
||||
int get_elk() {
|
||||
return elk;
|
||||
}
|
||||
|
||||
void action_scanlines(int on) {
|
||||
if (on) {
|
||||
scanlines = BIT_SCANLINES;
|
||||
} else {
|
||||
scanlines = 0;
|
||||
}
|
||||
clear = BIT_CLEAR;
|
||||
}
|
||||
|
||||
void action_calibrate() {
|
||||
// During calibration we do our best to auto-delect an Electron
|
||||
elk = test_for_elk(elk, mode7, chars_per_line);
|
||||
log_debug("Elk mode = %d", elk);
|
||||
for (int c = 0; c < NUM_CAL_PASSES; c++) {
|
||||
cpld->calibrate(elk, chars_per_line);
|
||||
}
|
||||
}
|
||||
|
||||
void rgb_to_hdmi_main() {
|
||||
|
||||
// Initialize the cpld after the gpclk generator has been started
|
||||
cpld_init();
|
||||
|
||||
// Initialize the On-Screen Display
|
||||
osd_init();
|
||||
|
||||
// Determine initial mode
|
||||
mode7 = rgb_to_fb(fb, 0, 0, BIT_PROBE) & BIT_MODE7;
|
||||
|
||||
while (1) {
|
||||
log_debug("Setting mode7 = %d", mode7);
|
||||
RPI_SetGpioValue(MODE7_PIN, mode7);
|
||||
|
||||
log_debug("Setting up frame buffer");
|
||||
init_framebuffer(mode7);
|
||||
log_debug("Done setting up frame buffer");
|
||||
|
||||
log_debug("Loading sample points");
|
||||
cpld->set_mode(mode7);
|
||||
log_debug("Done loading sample points");
|
||||
|
||||
chars_per_line = mode7 ? MODE7_CHARS_PER_LINE : DEFAULT_CHARS_PER_LINE;
|
||||
|
||||
clear = BIT_CLEAR;
|
||||
|
||||
osd_refresh();
|
||||
|
||||
do {
|
||||
|
||||
log_debug("Entering rgb_to_fb");
|
||||
result = rgb_to_fb(fb, chars_per_line, pitch, mode7 | BIT_INITIALIZE | ((elk & !mode7) ? BIT_ELK : 0) | clear | scanlines);
|
||||
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);
|
||||
}
|
||||
|
||||
last_mode7 = mode7;
|
||||
mode7 = result & BIT_MODE7;
|
||||
|
||||
} while (mode7 == last_mode7);
|
||||
|
||||
osd_clear();
|
||||
}
|
||||
}
|
||||
|
||||
void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags)
|
||||
{
|
||||
|
@ -784,24 +9,13 @@ void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags)
|
|||
|
||||
log_info("RGB to HDMI booted");
|
||||
|
||||
init_hardware();
|
||||
// Switch to new core clock speed
|
||||
RPI_PropertyInit();
|
||||
RPI_PropertyAddTag( TAG_SET_CLOCK_RATE, CORE_CLK_ID, 384123456, 1);
|
||||
RPI_PropertyProcess();
|
||||
|
||||
enable_MMU_and_IDCaches();
|
||||
_enable_unaligned_access();
|
||||
dump_useful_info();
|
||||
|
||||
#ifdef HAS_MULTICORE
|
||||
int i;
|
||||
while(1);
|
||||
|
||||
printf("main running on core %d\r\n", _get_core());
|
||||
|
||||
for (i = 0; i < 10000000; i++);
|
||||
start_core(1, _spin_core);
|
||||
for (i = 0; i < 10000000; i++);
|
||||
start_core(2, _spin_core);
|
||||
for (i = 0; i < 10000000; i++);
|
||||
start_core(3, _spin_core);
|
||||
for (i = 0; i < 10000000; i++);
|
||||
#endif
|
||||
|
||||
rgb_to_hdmi_main();
|
||||
}
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
# ======================================================================
|
||||
# cmdline.txt file for RGBtoHDMI (https://github.com/hoglet67/RGBtoHDMI)
|
||||
# ======================================================================
|
||||
#
|
||||
# sampling06: Sample points for modes 0..6
|
||||
# - Specify a single value here, in the range 0..5
|
||||
#
|
||||
# The sampling06 value can be copied from the Calibration Summary screen:
|
||||
# - Select Mode 6 screen
|
||||
# - Type *HELP to get some text on the screen
|
||||
# - Press Auto Calibation (right button)
|
||||
# - Select: Feature Menu/Info/Calibration Summary
|
||||
# - Use the value of the "Offset" (all should be the same)
|
||||
#
|
||||
# sampling7: Sample points for mode 7
|
||||
# - Specify eight comma seperated values: 0,A,B,C,D,E,F,Half
|
||||
# -- or --
|
||||
# - Specify a single value here, in the range 0..7
|
||||
#
|
||||
# The sampling7 values can be copied from the Calibration Summary screen:
|
||||
# - Select Mode 7 screen
|
||||
# - Type *HELP to get some text on the screen
|
||||
# - Press Auto Calibation (right button)
|
||||
# - Select: Feature Menu/Info/Calibration Summary
|
||||
# - For A..F use the six "Offset" values
|
||||
# - For H use the "Half" value
|
||||
#
|
||||
# info: the default info screen
|
||||
# - 0 is the firmware version
|
||||
# - 1 is the calibration summary
|
||||
# - 2 is the calibration detail
|
||||
#
|
||||
# palette: colour palette number
|
||||
# - 0 is Default
|
||||
# - 1 is Inverse
|
||||
# - 2 is Mono 1
|
||||
# - 3 is Mono 2
|
||||
# - 4 is Just Red
|
||||
# - 5 is Just Green
|
||||
# - 6 is Just Blue
|
||||
# - 7 is Not Red
|
||||
# - 8 is Not Green
|
||||
# - 9 is Not Blue
|
||||
#
|
||||
# scalines: show visible scanlines in modes 0..6
|
||||
# - 0 is scanlines off
|
||||
# - 1 is scanlines on
|
||||
#
|
||||
# mux: initial setting of the input mux
|
||||
# - 0 is direct
|
||||
# - 1 is via the 74LS08 buffer (for Issue 2/4 Elk only)
|
||||
#
|
||||
# elk: indicates the interface is connected to an elk
|
||||
# - 0 is Model B/Master
|
||||
# - 1 is Elk
|
||||
#
|
||||
# debug: enables debug mode
|
||||
# - 0 is debug off
|
||||
# - 1 is debug on
|
||||
#
|
||||
# Important: All the properties must be on a single line, and no blank lines!
|
||||
#
|
||||
sampling06=3 sampling7=0,2,2,2,2,2,2,0 info=1 palette=0 scanlines=0 mux=0 elk=0 debug=0
|
|
@ -1,28 +1,6 @@
|
|||
# =====================================================================
|
||||
# config.txt file for RGBtoHDMI (https://github.com/hoglet67/RGBtoHDMI)
|
||||
# =====================================================================
|
||||
|
||||
# =====================================================================
|
||||
# Default options
|
||||
# =====================================================================
|
||||
|
||||
# No need to change these
|
||||
|
||||
# Kernel name
|
||||
kernel=kernelrpi.img
|
||||
|
||||
# Boot quickly
|
||||
boot_delay=0
|
||||
|
||||
# Disable adjusting the refresh rate of RAM every 500 ms
|
||||
disable_pvt=1
|
||||
|
||||
# Don't allow ARM to use Level 2 Cache - this actually speeds up cache misses
|
||||
disable_l2cache=1
|
||||
|
||||
# Enable VSYNC interrupt
|
||||
fake_vsync_isr=1
|
||||
|
||||
# Clock frequency override to make sure we run at 1000MHz
|
||||
force_turbo=1
|
||||
arm_freq=1000
|
||||
|
@ -32,224 +10,3 @@ kernel_address=0x1f00000
|
|||
start_file=start_cd.elf
|
||||
fixup_file=fixup_cd.dat
|
||||
|
||||
# =====================================================================
|
||||
# Common video settings
|
||||
# =====================================================================
|
||||
|
||||
# Use "DVI mode", so the TV's external audio inputs will be activiated
|
||||
hdmi_drive=1
|
||||
|
||||
# Allow framebuffer to have it's aspect ratio warped when scaling
|
||||
# (needed for mode 7, 504x540 with 4/3 aspect ratio pixels)
|
||||
framebuffer_aspect=-1
|
||||
|
||||
# Ensure default overscan values are 0 (rather than 32/48)
|
||||
# Without this, the overscan calculation below are more complex and error prone
|
||||
disable_overscan=1
|
||||
|
||||
# =====================================================================
|
||||
# Monitor configuration
|
||||
# =====================================================================
|
||||
|
||||
# Uncomment the section that matches your monitor resolution
|
||||
# (and make sure the remaining ones are commented)
|
||||
|
||||
## 1920x1080 @ 50Hz
|
||||
##
|
||||
## Scale by 1:2 - 672x540 => 1344x1080
|
||||
## l/r overscan = (1920-1344)/2 = 288
|
||||
## t/b overscan = (1080-1080)/2 = 0
|
||||
##
|
||||
hdmi_group=1
|
||||
hdmi_mode=31
|
||||
overscan_left=288
|
||||
overscan_right=288
|
||||
overscan_top=0
|
||||
overscan_bottom=0
|
||||
|
||||
## Example using hdmi_timings
|
||||
##
|
||||
## hdmi_timings=
|
||||
## <h_active_pixels>
|
||||
## <h_sync_polarity
|
||||
## <h_front_porch>
|
||||
## <h_sync_pulse>
|
||||
## <h_back_porch>
|
||||
## <v_active_lines>
|
||||
## <v_sync_polarity>
|
||||
## <v_front_porch>
|
||||
## <v_sync_pulse>
|
||||
## <v_back_porch>
|
||||
## <v_sync_offset_a>
|
||||
## <v_sync_offset_b>
|
||||
## <pixel_rep>
|
||||
## <frame_rate>
|
||||
## <interlaced>
|
||||
## <pixel_freq>
|
||||
## <aspect_ratio>
|
||||
##
|
||||
#hdmi_group=2
|
||||
#hdmi_mode=87
|
||||
#hdmi_timings=1920 1 528 44 148 1080 1 5 5 35 0 0 0 50 0 148626953 3
|
||||
#hdmi_timings=1920 1 528 44 148 1080 1 5 5 35 0 0 0 50 0 148000000 3
|
||||
#overscan_left=288
|
||||
#overscan_right=288
|
||||
#overscan_top=0
|
||||
#overscan_bottom=0
|
||||
|
||||
## 1920x1200 @ 50Hz
|
||||
##
|
||||
## Scale by 1:2 - 672x540 => 1344x1080
|
||||
## l/r overscan = (1920-1344)/2 = 288
|
||||
## t/b overscan = (1200-1080)/2 = 60
|
||||
##
|
||||
#hdmi_group=2
|
||||
#hdmi_mode=87
|
||||
#hdmi_cvt=1920 1200 50 5 0 0 0
|
||||
#overscan_left=288
|
||||
#overscan_right=288
|
||||
#overscan_top=60
|
||||
#overscan_bottom=60
|
||||
|
||||
## 1600x1200 @ 50Hz
|
||||
##
|
||||
## Scale by 1:2 - 672x540 => 1344x1080
|
||||
## l/r overscan = (1600-1344)/2 = 128
|
||||
## t/b overscan = (1200-1080)/2 = 60
|
||||
##
|
||||
#hdmi_group=2
|
||||
#hdmi_mode=87
|
||||
#hdmi_cvt=1600 1200 50 1 0 0 0
|
||||
#overscan_left=128
|
||||
#overscan_right=128
|
||||
#overscan_top=60
|
||||
#overscan_bottom=60
|
||||
|
||||
## 720x576 @ 50Hz
|
||||
##
|
||||
## Scale by 1:1 - 672x540 => 672x540
|
||||
## l/r overscan = (720-672)/2 = 24
|
||||
## t/b overscan = (576-540)/2 = 18
|
||||
##
|
||||
#hdmi_group=1
|
||||
#hdmi_mode=17
|
||||
#overscan_left=24
|
||||
#overscan_right=24
|
||||
#overscan_top=18
|
||||
#overscan_bottom=18
|
||||
|
||||
## 1280x1024 @ 50Hz
|
||||
##
|
||||
## Scale by 1:1.5 - 672x540 => 1008x810
|
||||
## l/r overscan = (1280-1008)/2 = 136
|
||||
## t/b overscan = (1024- 810)/2 = 107
|
||||
##
|
||||
#hdmi_group=2
|
||||
#hdmi_mode=87
|
||||
#hdmi_cvt=1280 1024 50 4 0 0
|
||||
#overscan_left=136
|
||||
#overscan_right=136
|
||||
#overscan_top=107
|
||||
#overscan_bottom=107
|
||||
|
||||
## 1280x720 @ 50Hz
|
||||
## 1280x800 @ 50Hz
|
||||
## 1366x768 @ 50Hz
|
||||
##
|
||||
## If your native resolution 720p or 768p (i.e. "HD Ready" rather than
|
||||
## "Full HD") you are not get a very good result:
|
||||
## - With 1:1 pixel mapping the Beeb image will seem quite small
|
||||
## - With 1:2 pixel mapping the Beeb image will overflow the screen
|
||||
## - With something in between there will be nasty scaling artifacts
|
||||
##
|
||||
## You are probably best to select 1920x1080 and let the TV do the scaling
|
||||
##
|
||||
## Consider the below experimental!
|
||||
|
||||
## 1280x720 @ 50Hz
|
||||
##
|
||||
## Scale by 1:1.333 - 672x540 => 896x720
|
||||
## l/r overscan = (1280-896)/2 = 192
|
||||
## t/b overscan = ( 720-720)/2 = 0
|
||||
##
|
||||
#hdmi_group=1
|
||||
#hdmi_mode=19
|
||||
#overscan_left=192
|
||||
#overscan_right=192
|
||||
#overscan_top=0
|
||||
#overscan_bottom=0
|
||||
|
||||
## 1280x800 @ 50Hz
|
||||
##
|
||||
## Scale by 1:1.333 - 672x540 => 896x720
|
||||
## l/r overscan = (1280-896)/2 = 192
|
||||
## t/b overscan = ( 800-720)/2 = 40
|
||||
##
|
||||
#hdmi_group=2
|
||||
#hdmi_mode=87
|
||||
#hdmi_cvt=1280 800 50 5 0 0
|
||||
#overscan_left=192
|
||||
#overscan_right=192
|
||||
#overscan_top=40
|
||||
#overscan_bottom=40
|
||||
|
||||
## 1368x768 @ 50Hz
|
||||
##
|
||||
## Scale by 1:1.333 - 672x540 => 896x720
|
||||
## l/r overscan = (1368-896)/2 = 236
|
||||
## t/b overscan = ( 768-720)/2 = 24
|
||||
##
|
||||
#hdmi_group=2
|
||||
#hdmi_mode=87
|
||||
#hdmi_cvt=1368 768 50 3 0 0
|
||||
#overscan_left=236
|
||||
#overscan_right=236
|
||||
#overscan_top=24
|
||||
#overscan_bottom=24
|
||||
|
||||
# Further notes....
|
||||
#
|
||||
# Currently the RGBtoHDMI frame buffer sizes are:
|
||||
# - Mode 0..6 : 672x540 (pixel aspect 1:1)
|
||||
# - Mode 7 : 504x540 (pixel aspect 4:3)
|
||||
#
|
||||
# This is set in defs.h and is slightly larger than the Beeb's
|
||||
# display to allow a bit of tolerance in where the active area
|
||||
# is placed (i.e. *TV or games that play with sync position)
|
||||
#
|
||||
# For the display to look optimal on HDMI, it's important
|
||||
# that each Beeb pixel maps exactly 1x1 or 2x2 HDMI pixels.
|
||||
#
|
||||
# This is achieved by carefully setting the overscan params.
|
||||
#
|
||||
# Start by setting disable_overscan=1. Otherwise the firmware
|
||||
# mangles the overscan values by adding 32 (SD) or 48 (HD) and
|
||||
# it all gets very confusing. (HD is 1280 or wider)
|
||||
#
|
||||
# It's also important to make sure you monitor doesn't rescale. Look for
|
||||
# a setting called Just Scan. On my LG 22MN43 this is only available in HD.
|
||||
#
|
||||
# Using M0TEST, the difference between the different monitor scaling options
|
||||
# is very obvious.
|
||||
#
|
||||
# Defining custom screen modes is very easy:
|
||||
#
|
||||
# hdmi_cvt=<width> <height> <framerate> <aspect> <margins> <interlace> <rb>
|
||||
#
|
||||
# Value: Default: Description:
|
||||
# width (required) width in pixels
|
||||
# height (required) height in pixels
|
||||
# framerate (required) framerate in Hz
|
||||
# aspect 3 aspect ratio 1=4:3, 2=14:9, 3=16:9, 4=5:4, 5=16:10, 6=15:9
|
||||
# margins 0 0=margins disabled, 1=margins enabled
|
||||
# interlace 0 0=progressive, 1=interlaced
|
||||
# rb 0 0=normal, 1=reduced blanking
|
||||
#
|
||||
# See https://www.raspberrypi.org/documentation/configuration/config-txt/video.md
|
||||
#
|
||||
#
|
||||
# See also fully annotated config.txt at
|
||||
# https://raw.githubusercontent.com/Evilpaul/RPi-config/master/config.txt
|
||||
# (via http://elinux.org/RPiconfig)
|
||||
#
|
||||
#
|
||||
|
|
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
|
@ -38,7 +38,7 @@ RGBtoHDMI
|
|||
build version: ${NAME}
|
||||
EOF
|
||||
|
||||
cp config.txt cmdline.txt ${DIR}
|
||||
cp config.txt ${DIR}
|
||||
cd releases/${NAME}
|
||||
zip -qr ../${NAME}.zip .
|
||||
cd ../..
|
||||
|
|
Ładowanie…
Reference in New Issue