diff --git a/MiSTer.ini b/MiSTer.ini index b2b03c7..4bd5eb0 100644 --- a/MiSTer.ini +++ b/MiSTer.ini @@ -1,7 +1,8 @@ [MiSTer] key_menu_as_rgui=0 ; set to 1 to make the MENU key map to RGUI in Minimig (e.g. for Right Amiga) forced_scandoubler=0 ; set to 1 to run scandoubler on VGA output always (depends on core). -ypbpr=0 ; set to 1 for YPbPr on VGA output. +;ypbpr=0 ; set to 1 for YPbPr on VGA output. (obsolete. see vga_mode) +vga_mode=rgb ; supported modes: rgb, ypbpr, svideo, cvbs. rgb is default. composite_sync=0 ; set to 1 for composite sync on HSync signal of VGA output. vga_scaler=0 ; set to 1 to connect VGA to scaler output. hdmi_audio_96k=0 ; set to 1 for 96khz/16bit HDMI audio (48khz/16bit otherwise) diff --git a/cfg.cpp b/cfg.cpp index 7e4a40c..34ebdcf 100644 --- a/cfg.cpp +++ b/cfg.cpp @@ -33,7 +33,7 @@ typedef struct static const ini_var_t ini_vars[] = { - { "YPBPR", (void*)(&(cfg.ypbpr)), UINT8, 0, 1 }, + { "YPBPR", (void*)(&(cfg.vga_mode_int)), UINT8, 0, 1 }, { "COMPOSITE_SYNC", (void*)(&(cfg.csync)), UINT8, 0, 1 }, { "FORCED_SCANDOUBLER", (void*)(&(cfg.forced_scandoubler)), UINT8, 0, 1 }, { "VGA_SCALER", (void*)(&(cfg.vga_scaler)), UINT8, 0, 1 }, @@ -115,6 +115,7 @@ static const ini_var_t ini_vars[] = { "VIDEO_HUE", (void *)(&(cfg.video_hue)), UINT16, 0, 360}, { "VIDEO_GAIN_OFFSET", (void *)(&(cfg.video_gain_offset)), STRING, 0, sizeof(cfg.video_gain_offset)}, { "HDR", (void*)(&cfg.hdr), UINT8, 0, 2 }, + { "vga_mode", (void*)(&(cfg.vga_mode)), STRING, 0, sizeof(cfg.vga_mode) - 1 }, }; static const int nvars = (int)(sizeof(ini_vars) / sizeof(ini_var_t)); @@ -463,7 +464,13 @@ void cfg_parse() ini_parse(altcfg(), video_get_core_mode_name(0)); } - + if (strlen(cfg.vga_mode)) + { + if (!strcasecmp(cfg.vga_mode, "rgb")) cfg.vga_mode_int = 0; + if (!strcasecmp(cfg.vga_mode, "ypbpr")) cfg.vga_mode_int = 1; + if (!strcasecmp(cfg.vga_mode, "svideo")) cfg.vga_mode_int = 2; + if (!strcasecmp(cfg.vga_mode, "cvbs")) cfg.vga_mode_int = 3; + } } bool cfg_has_video_sections() diff --git a/cfg.h b/cfg.h index 9a361dc..4bb4ea3 100644 --- a/cfg.h +++ b/cfg.h @@ -13,7 +13,6 @@ typedef struct { uint8_t forced_scandoubler; uint8_t key_menu_as_rgui; uint8_t reset_combo; - uint8_t ypbpr; uint8_t csync; uint8_t vga_scaler; uint8_t vga_sog; @@ -87,6 +86,8 @@ typedef struct { uint16_t video_hue; char video_gain_offset[256]; uint8_t hdr; + char vga_mode[16]; + char vga_mode_int; } cfg_t; extern cfg_t cfg; diff --git a/user_io.cpp b/user_io.cpp index 0a67451..4c24b54 100644 --- a/user_io.cpp +++ b/user_io.cpp @@ -2696,9 +2696,9 @@ void user_io_send_buttons(char force) if (kbd_reset || kbd_reset_ovr) map |= BUTTON2; if (cfg.vga_scaler) map |= CONF_VGA_SCALER; - if (cfg.vga_sog) map |= CONF_VGA_SOG; + if (cfg.vga_sog || cfg.vga_mode_int >= 2) map |= CONF_VGA_SOG; if (cfg.csync) map |= CONF_CSYNC; - if (cfg.ypbpr) map |= CONF_YPBPR; + if (cfg.vga_mode_int == 1) map |= CONF_YPBPR; if (cfg.forced_scandoubler) map |= CONF_FORCED_SCANDOUBLER; if (cfg.hdmi_audio_96k) map |= CONF_AUDIO_96K; if (cfg.dvi_mode == 1) map |= CONF_DVI; diff --git a/user_io.h b/user_io.h index 802348f..eb6f971 100644 --- a/user_io.h +++ b/user_io.h @@ -72,6 +72,7 @@ #define UIO_SHADOWMASK 0x3E #define UIO_GET_RUMBLE 0x3F #define UIO_GET_FB_PAR 0x40 +#define UIO_SET_YC_PAR 0x41 // codes as used by 8bit for file loading from OSD #define FIO_FILE_TX 0x53 diff --git a/video.cpp b/video.cpp index ac33c3b..15fd199 100644 --- a/video.cpp +++ b/video.cpp @@ -1020,7 +1020,7 @@ void video_loadPreset(char *name, bool save) { char *arg; fileTextReader reader; - + bool scaler_dirty = false; bool mask_dirty = false; bool gamma_dirty = false; @@ -1163,7 +1163,7 @@ static void hdmi_config_set_csc() const float pi = float(M_PI); - int ypbpr = cfg.ypbpr && cfg.direct_video; + int ypbpr = (cfg.vga_mode_int == 1) && cfg.direct_video; // out-of-scope defines, not used with ypbpr int16_t csc_int16[12]; @@ -1371,7 +1371,7 @@ static void hdmi_config_set_csc() static void hdmi_config_init() { - int ypbpr = cfg.ypbpr && cfg.direct_video; + int ypbpr = (cfg.vga_mode_int == 1) && cfg.direct_video; // address, value uint8_t init_data[] = { @@ -2400,7 +2400,7 @@ void video_init() video_mode_load(); has_gamma = spi_uio_cmd(UIO_SET_GAMMA); - + video_cfg_init(); video_set_mode(&v_def, 0); @@ -2431,6 +2431,7 @@ static bool get_video_info(bool force, VideoInfo *video_info) video_info->vtime = spi_w(0) | (spi_w(0) << 16); video_info->ptime = spi_w(0) | (spi_w(0) << 16); video_info->vtimeh = spi_w(0) | (spi_w(0) << 16); + video_info->ctime = spi_w(0) | (spi_w(0) << 16); video_info->interlaced = ( res & 0x100 ) != 0; video_info->rotated = ( res & 0x200 ) != 0; } @@ -2523,8 +2524,11 @@ static void show_video_info(const VideoInfo *vi, const vmode_custom_t *vm) float prate = vi->width * 100; prate /= vi->ptime; - printf("\033[1;33mINFO: Video resolution: %u x %u%s, fHorz = %.1fKHz, fVert = %.1fHz, fPix = %.2fMHz\033[0m\n", - vi->width, vi->height, vi->interlaced ? "i" : "", hrate, vrate, prate); + float crate = vi->ctime * 100; + crate /= vi->ptime; + + printf("\033[1;33mINFO: Video resolution: %u x %u%s, fHorz = %.1fKHz, fVert = %.1fHz, fPix = %.2fMHz, fVid = %.2fMHz\033[0m\n", + vi->width, vi->height, vi->interlaced ? "i" : "", hrate, vrate, prate, crate); printf("\033[1;33mINFO: Frame time (100MHz counter): VGA = %d, HDMI = %d\033[0m\n", vi->vtime, vi->vtimeh); printf("\033[1;33mINFO: AR = %d:%d, fb_en = %d, fb_width = %d, fb_height = %d\033[0m\n", vi->arx, vi->ary, vi->fb_en, vi->fb_width, vi->fb_height); if (vi->vtimeh) api1_5 = 1; @@ -2717,6 +2721,37 @@ bool video_mode_select(uint32_t vtime, vmode_custom_t* out_mode) return adjustable; } +static void set_yc_mode() +{ + if (cfg.vga_mode_int >= 2) + { + int pal = (!current_video_info.vtime || (100000000 / current_video_info.vtime) < 55); + double CLK_REF = pal ? 4.43361875f : 3.579545f; + double CLK_VIDEO = current_video_info.ctime * 100.f / current_video_info.ptime; + + int64_t PHASE_INC = ((int64_t)((CLK_REF / CLK_VIDEO) * 1099511627776LL)) & 0xFFFFFFFFFFLL; + + int COLORBURST_START = (int)(3.7f * (CLK_VIDEO / CLK_REF)); + int COLORBURST_END = (int)(9.0f * (CLK_VIDEO / CLK_REF)) + COLORBURST_START; + int COLORBURST_RANGE = (COLORBURST_START << 10) | COLORBURST_END; + + spi_uio_cmd_cont(UIO_SET_YC_PAR); + spi_w((pal ? 4 : 0) | ((cfg.vga_mode_int == 3) ? 3 : 1)); + spi_w(PHASE_INC); + spi_w(PHASE_INC >> 16); + spi_w(PHASE_INC >> 32); + spi_w(COLORBURST_RANGE); + spi_w(COLORBURST_RANGE >> 16); + DisableIO(); + + printf("Send YC parameters: %s PHASE_INC=%lld, COLORBURST_START=%d, COLORBURST_END=%d\n", pal ? "PAL" : "NTSC", PHASE_INC, COLORBURST_START, COLORBURST_END); + } + else + { + spi_uio_cmd8(UIO_SET_YC_PAR, 0); + } +} + void video_mode_adjust() { static bool force = false; @@ -2728,8 +2763,8 @@ void video_mode_adjust() if (vid_changed || force) { current_video_info = video_info; - show_video_info(&video_info, &v_cur); + set_yc_mode(); } force = false; diff --git a/video.h b/video.h index 837ef20..e740acb 100644 --- a/video.h +++ b/video.h @@ -12,6 +12,7 @@ struct VideoInfo uint32_t htime; uint32_t vtime; uint32_t ptime; + uint32_t ctime; uint32_t vtimeh; uint32_t arx; uint32_t ary;