From a65f4ac6e806b44a9dda82e2f69a5b89ebd2c801 Mon Sep 17 00:00:00 2001 From: David Banks Date: Fri, 13 Jul 2018 12:10:52 +0100 Subject: [PATCH] Pi Firmware: Added info feature Change-Id: I135917438b8827c282e425af9d8d6239571061b1 --- src/cpld.h | 3 ++ src/cpld_normal.c | 80 +++++++++++++++++++++++++++++++++++++++-------- src/osd.c | 80 ++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 138 insertions(+), 25 deletions(-) diff --git a/src/cpld.h b/src/cpld.h index 59cfbd5f..b6492ddc 100644 --- a/src/cpld.h +++ b/src/cpld.h @@ -25,6 +25,9 @@ typedef struct { param_t *(*get_params)(); int (*get_value)(int num); void (*set_value)(int num, int value); + // Support for info page + void (*show_cal_summary)(int line); + void (*show_cal_details)(int line); } cpld_t; int *diff_N_frames(int n, int mode7, int elk, int chars_per_line); diff --git a/src/cpld_normal.c b/src/cpld_normal.c index 5d766689..0f8b9db5 100644 --- a/src/cpld_normal.c +++ b/src/cpld_normal.c @@ -29,6 +29,18 @@ static int mode7; // OSD message buffer static char message[80]; +// Calibration metrics (i.e. errors) for mode 0..6 +static int metrics_default[8]; // Last two not used + +// Calibration metrics (i.e. errors) for mode 7 +static int metrics_mode7[8]; + +// Error count for final calibration values for mode 0..6 +static int errors_default; + +// Error count for final calibration values for mode 7 +static int errors_mode7; + // ============================================================= // Param definitions for OSD // ============================================================= @@ -95,15 +107,24 @@ static void write_config(config_t *config) { RPI_SetGpioValue(SP_DATA_PIN, 0); } -static void osd_sp(config_t *config, int metric) { +static void osd_sp(config_t *config, int line, int metric) { + if (mode7) { + osd_set(line, 0, " Mode: 7"); + } else { + osd_set(line, 0, " Mode: 0..6"); + } sprintf(message, "Offsets: %d %d %d %d %d %d", config->sp_offset[0], config->sp_offset[1], config->sp_offset[2], config->sp_offset[3], config->sp_offset[4], config->sp_offset[5]); - osd_set(1, 0, message); + osd_set(line + 1, 0, message); sprintf(message, " Half: %d", config->half_px_delay); - osd_set(2, 0, message); - sprintf(message, " Errors: %d", metric); - osd_set(3, 0, message); + osd_set(line + 2, 0, message); + if (metric < 0) { + sprintf(message, " Errors: unknown"); + } else { + sprintf(message, " Errors: %d", metric); + } + osd_set(line + 3, 0, message); } static void log_sp(config_t *config) { @@ -125,6 +146,12 @@ static void cpld_init() { default_config.half_px_delay = 0; mode7_config.half_px_delay = 0; config = &default_config; + for (int i = 0; i < 8; i++) { + metrics_default[i] = -1; + metrics_mode7[i] = -1; + } + errors_default = -1; + errors_mode7 = -1; } static void cpld_calibrate(int elk, int chars_per_line) { @@ -134,16 +161,23 @@ static void cpld_calibrate(int elk, int chars_per_line) { int win_metric; // this is a windowed value (over three sample offsets) int min_win_metric; int *rgb_metric; - int metrics[8]; // offsets are 3-bit values + int range; // 0..5 in Modes 0..6, 0..7 in Mode 7 + int *metrics; + int *errors; if (mode7) { log_info("Calibrating mode 7"); + range = 8; + metrics = metrics_mode7; + errors = &errors_mode7; } else { log_info("Calibrating modes 0..6"); + range = 6; + metrics = metrics_default; + errors = &errors_default; } - range = mode7 ? 8 : 6; min_metric = INT_MAX; config->half_px_delay = 0; for (int i = 0; i < range; i++) { @@ -154,7 +188,7 @@ static void cpld_calibrate(int elk, int chars_per_line) { rgb_metric = diff_N_frames(NUM_CAL_FRAMES, mode7, elk, chars_per_line); metric = rgb_metric[CHAN_RED] + rgb_metric[CHAN_GREEN] + rgb_metric[CHAN_BLUE]; metrics[i] = metric; - osd_sp(config, metric); + osd_sp(config, 1, metric); log_info("offset = %d: metric = %5d", i, metric); if (metric < min_metric) { min_metric = metric; @@ -198,7 +232,7 @@ static void cpld_calibrate(int elk, int chars_per_line) { write_config(config); rgb_metric = diff_N_frames(NUM_CAL_FRAMES, mode7, elk, chars_per_line); left = rgb_metric[CHAN_RED] + rgb_metric[CHAN_GREEN] + rgb_metric[CHAN_BLUE]; - osd_sp(config, left); + osd_sp(config, 1, left); config->sp_offset[i]++; } if (config->sp_offset[i] < 7) { @@ -206,7 +240,7 @@ static void cpld_calibrate(int elk, int chars_per_line) { write_config(config); rgb_metric = diff_N_frames(NUM_CAL_FRAMES, mode7, elk, chars_per_line); right = rgb_metric[CHAN_RED] + rgb_metric[CHAN_GREEN] + rgb_metric[CHAN_BLUE]; - osd_sp(config, right); + osd_sp(config, 1, right); config->sp_offset[i]--; } if (left < right && left < ref) { @@ -222,8 +256,8 @@ static void cpld_calibrate(int elk, int chars_per_line) { } write_config(config); rgb_metric = diff_N_frames(NUM_CAL_FRAMES, mode7, elk, chars_per_line); - metric = rgb_metric[CHAN_RED] + rgb_metric[CHAN_GREEN] + rgb_metric[CHAN_BLUE]; - osd_sp(config, metric); + *errors = rgb_metric[CHAN_RED] + rgb_metric[CHAN_GREEN] + rgb_metric[CHAN_BLUE]; + osd_sp(config, 1, *errors); log_info("Calibration complete"); log_sp(config); } @@ -299,6 +333,24 @@ static void cpld_set_value(int num, int value) { write_config(config); } +static void cpld_show_cal_summary(int line) { + osd_sp(config, line, mode7 ? errors_mode7 : errors_default); +} + +static void cpld_show_cal_details(int line) { + int *metrics = mode7 ? metrics_mode7 : metrics_default; + int num = (*metrics < 0) ? 0 : mode7 ? 8 : 6; + if (num == 0) { + sprintf(message, "No calibration data for this mode"); + osd_set(line, 0, message); + } else { + for (int i = 0; i < num; i++) { + sprintf(message, "Offset %d: Errors = %6d", i, metrics[i]); + osd_set(line + i, 0, message); + } + } +} + cpld_t cpld_normal = { .name = "Normal", .init = cpld_init, @@ -306,5 +358,7 @@ cpld_t cpld_normal = { .set_mode = cpld_set_mode, .get_params = cpld_get_params, .get_value = cpld_get_value, - .set_value = cpld_set_value + .set_value = cpld_set_value, + .show_cal_summary = cpld_show_cal_summary, + .show_cal_details = cpld_show_cal_details }; diff --git a/src/osd.c b/src/osd.c index a572267b..18e5f7ee 100644 --- a/src/osd.c +++ b/src/osd.c @@ -3,15 +3,16 @@ #include #include #include "defs.h" -#include "osd.h" #include "cpld.h" +#include "gitversion.h" #include "info.h" #include "logging.h" +#include "osd.h" #include "rpi-gpio.h" #include "rpi-mailbox-interface.h" #include "saa5050_font.h" -#define NLINES 4 +#define NLINES 12 #define LINELEN 40 static char buffer[LINELEN * NLINES]; @@ -27,8 +28,6 @@ static char message[80]; static int active = 0; -#define NUM_PALETTES 10 - enum { PALETTE_DEFAULT, PALETTE_INVERSE, @@ -39,7 +38,8 @@ enum { PALETTE_BLUE, PALETTE_NOT_RED, PALETTE_NOT_GREEN, - PALETTE_NOT_BLUE + PALETTE_NOT_BLUE, + NUM_PALETTES }; static const char *palette_names[] = { @@ -55,20 +55,34 @@ static const char *palette_names[] = { "Not Blue" }; +enum { + INFO_VERSION, + INFO_CAL_SUMMARY, + INFO_CAL_DETAILS, + NUM_INFOS +}; + +static const char *info_names[] = { + "Firmware Version", + "Calibration Summary", + "Calibration Detail" +}; // ============================================================= // Feature definitions for OSD // ============================================================= enum { + F_INFO, F_PALETTE, F_SCANLINES, F_MUX, F_ELK, - F_DEBUG, + F_DEBUG }; static param_t features[] = { + { "Info", 0, NUM_INFOS - 1 }, { "Color Palette", 0, NUM_PALETTES - 1 }, { "Scanlines", 0, 1 }, { "Input Mux", 0, 1 }, @@ -77,7 +91,7 @@ static param_t features[] = { { NULL, 0, 0 }, }; - +static int info = INFO_VERSION; static int palette = PALETTE_DEFAULT; static int scanlines = 0; static int mux = 0; @@ -158,13 +172,13 @@ static void update_palette() { void osd_clear() { if (active) { + memset(buffer, 0, sizeof(buffer)); + osd_update((uint32_t *)fb, pitch); + osd_update((uint32_t *)(fb + SCREEN_HEIGHT * pitch), pitch); active = 0; RPI_SetGpioValue(LED1_PIN, active); update_palette(); - memset(buffer, 0, sizeof(buffer)); } - osd_update((uint32_t *)fb, pitch); - osd_update((uint32_t *)(fb + SCREEN_HEIGHT * pitch), pitch); } void osd_set(int line, int attr, char *text) { @@ -209,9 +223,11 @@ static void show_param(int num) { static int get_feature(int num) { switch (num) { + case F_INFO: + return info; case F_PALETTE: return palette; - case F_SCANLINES: + case F_SCANLINES: return scanlines; case F_MUX: return mux; @@ -225,6 +241,9 @@ static int get_feature(int num) { static void set_feature(int num, int value) { switch (num) { + case F_INFO: + info = value; + break; case F_PALETTE: palette = value; update_palette(); @@ -249,9 +268,43 @@ static void set_feature(int num, int value) { } static void show_feature(int num) { + // Read the current value of the specified feature int value = get_feature(num); - sprintf(message, "%s = %s", features[num].name, (num == F_PALETTE) ? palette_names[value] : value ? "On" : "Off"); + // Convert that to a human readable string + const char *valstr = + (num == F_INFO) ? info_names[value] : + (num == F_PALETTE) ? palette_names[value] : + value ? "On" : "Off"; + // Clear lines 2 onwards + memset(buffer + 2 * LINELEN, 0, (NLINES - 2) * LINELEN); + // Dispay the feature name and value in line 1 + sprintf(message, "%s = %s", features[num].name, valstr); osd_set(1, 0, message); + // If the info screen, provide further info on lines 3 onwards + if (num == F_INFO) { + switch (info) { + case INFO_VERSION: + sprintf(message, "%s", GITVERSION); + osd_set(3, 0, message); + break; + case INFO_CAL_SUMMARY: + if (cpld->show_cal_summary) { + cpld->show_cal_summary(3); + } else { + sprintf(message, "show_cal_summary() not implemented"); + osd_set(3, 0, message); + } + break; + case INFO_CAL_DETAILS: + if (cpld->show_cal_details) { + cpld->show_cal_details(3); + } else { + sprintf(message, "show_cal_details() not implemented"); + osd_set(3, 0, message); + } + break; + } + } } void osd_key(int key) { @@ -473,6 +526,9 @@ void osd_init() { } void osd_update(uint32_t *osd_base, int bytes_per_line) { + if (!active) { + return; + } // SAA5050 character data is 12x20 uint32_t *line_ptr = osd_base; int words_per_line = bytes_per_line >> 2;