diff --git a/MiSTer.vcxproj b/MiSTer.vcxproj
index 870f043..5f9a3a9 100644
--- a/MiSTer.vcxproj
+++ b/MiSTer.vcxproj
@@ -86,6 +86,7 @@
+
@@ -135,6 +136,7 @@
+
diff --git a/MiSTer.vcxproj.filters b/MiSTer.vcxproj.filters
index e8118cd..8c36384 100644
--- a/MiSTer.vcxproj.filters
+++ b/MiSTer.vcxproj.filters
@@ -142,6 +142,9 @@
Source Files
+
+ Source Files
+
@@ -285,5 +288,8 @@
Header Files
+
+ Header Files
+
\ No newline at end of file
diff --git a/file_io.cpp b/file_io.cpp
index 7abe7d0..5dddd5e 100644
--- a/file_io.cpp
+++ b/file_io.cpp
@@ -25,6 +25,7 @@
#include "input.h"
#include "miniz_zip.h"
#include "scheduler.h"
+#include "video.h"
#define MIN(a,b) (((a)<(b)) ? (a) : (b))
@@ -766,7 +767,7 @@ void FindStorage(void)
device = 0;
MiSTer_ini_parse();
device = saveddev;
- parse_video_mode();
+ video_mode_load();
user_io_send_buttons(1);
printf("Waiting for USB...\n");
diff --git a/input.cpp b/input.cpp
index 0f1d7d0..aa12a78 100644
--- a/input.cpp
+++ b/input.cpp
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include "input.h"
#include "user_io.h"
@@ -16,7 +17,7 @@
#include "cfg.h"
#include "fpga_io.h"
#include "osd.h"
-#include "errno.h"
+#include "video.h"
#define NUMDEV 20
#define NUMPLAYERS 6
diff --git a/menu.cpp b/menu.cpp
index 8f2c8b8..845539b 100644
--- a/menu.cpp
+++ b/menu.cpp
@@ -50,6 +50,7 @@ along with this program. If not, see .
#include "battery.h"
#include "bootcore.h"
#include "cheats.h"
+#include "video.h"
#include "support.h"
@@ -1517,22 +1518,22 @@ void HandleUI(void)
OsdWrite(n++, s, menusub == 3);
}
- if (user_io_get_scaler_flt() >= 0)
+ if (video_get_scaler_flt() >= 0)
{
OsdWrite(n++);
menumask |= 0x60;
- sprintf(s, " Scale Filter - %s", config_scaler_msg[user_io_get_scaler_flt() ? 1 : 0]);
+ sprintf(s, " Scale Filter - %s", config_scaler_msg[video_get_scaler_flt() ? 1 : 0]);
OsdWrite(n++, s, menusub == 5);
memset(s, 0, sizeof(s));
s[0] = ' ';
- if (strlen(user_io_get_scaler_coeff())) strncpy(s+1, user_io_get_scaler_coeff(),25);
+ if (strlen(video_get_scaler_coeff())) strncpy(s+1, video_get_scaler_coeff(),25);
else strcpy(s, " < none >");
while(strlen(s) < 26) strcat(s, " ");
strcat(s, " \x16 ");
- OsdWrite(n++, s, menusub == 6, !user_io_get_scaler_flt() || !S_ISDIR(getFileType(COEFF_DIR)));
+ OsdWrite(n++, s, menusub == 6, !video_get_scaler_flt() || !S_ISDIR(getFileType(COEFF_DIR)));
}
m = 0;
@@ -1617,14 +1618,14 @@ void HandleUI(void)
break;
case 5:
- user_io_set_scaler_flt(user_io_get_scaler_flt() ? 0 : 1);
+ video_set_scaler_flt(video_get_scaler_flt() ? 0 : 1);
menustate = MENU_8BIT_SYSTEM1;
break;
case 6:
- if (user_io_get_scaler_flt())
+ if (video_get_scaler_flt())
{
- sprintf(SelectedPath, COEFF_DIR"/%s", user_io_get_scaler_coeff());
+ sprintf(SelectedPath, COEFF_DIR"/%s", video_get_scaler_coeff());
SelectFile(0, SCANO_COEFF, MENU_COEFF_FILE_SELECTED, MENU_8BIT_SYSTEM1);
}
break;
@@ -1823,8 +1824,8 @@ void HandleUI(void)
case MENU_COEFF_FILE_SELECTED:
{
char *p = strrchr(SelectedPath, '/');
- if (!p) user_io_set_scaler_coeff(SelectedPath);
- else user_io_set_scaler_coeff(p+1);
+ if (!p) video_set_scaler_coeff(SelectedPath);
+ else video_set_scaler_coeff(p+1);
menustate = MENU_8BIT_SYSTEM1;
}
break;
@@ -2810,7 +2811,7 @@ void HandleUI(void)
OsdWrite(m++, " Startup config:");
for (uint i = 0; i < 10; i++)
{
- const char *info = minimig_GetCfgInfo(i);
+ const char *info = minimig_get_cfg_info(i);
static char name[128];
if (info)
@@ -2852,7 +2853,7 @@ void HandleUI(void)
if (menusub<10)
{
OsdDisable();
- minimig_LoadCfg(menusub);
+ minimig_cfg_load(menusub);
menustate = MENU_NONE1;
}
else
@@ -3085,7 +3086,7 @@ void HandleUI(void)
if (m)
{
menustate = MENU_NONE1;
- MinimigReset();
+ minimig_reset();
}
else if(m == 2)
{
@@ -3121,7 +3122,7 @@ void HandleUI(void)
OsdWrite(m++, " Startup config:");
for (uint i = 0; i < 10; i++)
{
- const char *info = minimig_GetCfgInfo(i);
+ const char *info = minimig_get_cfg_info(i);
static char name[128];
if (info)
@@ -3180,7 +3181,7 @@ void HandleUI(void)
strncat(minimig_config.info, p, sizeof(minimig_config.info) - strlen(minimig_config.info) - 1);
minimig_config.info[sizeof(minimig_config.info) - 1] = 0;
- if (menusub<10) minimig_SaveCfg(menusub);
+ if (menusub<10) minimig_cfg_save(menusub);
menustate = MENU_MAIN1;
menusub = 9;
}
@@ -3411,7 +3412,7 @@ void HandleUI(void)
break;
case MENU_ROMFILE_SELECTED:
- SetKickstart(SelectedPath);
+ minimig_set_kickstart(SelectedPath);
menustate = MENU_SETTINGS_MEMORY1;
break;
@@ -3599,7 +3600,7 @@ void HandleUI(void)
OsdWrite(5, s, menusub == 3, 0);
OsdWrite(6, "", 0, 0);
OsdWrite(7, "", 0, 0);
- OsdWrite(8, user_io_minimig_get_adjust() ? " Finish screen adjustment" : " Adjust screen position", menusub == 4, 0);
+ OsdWrite(8, minimig_get_adjust() ? " Finish screen adjustment" : " Adjust screen position", menusub == 4, 0);
OsdWrite(9, "", 0, 0);
OsdWrite(10, "", 0, 0);
OsdWrite(11, "", 0, 0);
@@ -3644,7 +3645,7 @@ void HandleUI(void)
else if (menusub == 4)
{
menustate = MENU_NONE1;
- user_io_minimig_set_adjust(!user_io_minimig_get_adjust());
+ minimig_set_adjust(minimig_get_adjust() ? 0 : 1);
}
else if (menusub == 5)
{
@@ -4450,21 +4451,21 @@ void menu_bt_pair()
}
int menu_lightgun_cb(uint16_t type, uint16_t code, int value)
-{
- if (type == EV_ABS)
- {
- if (code == 0 && value) wm_x = value;
- if (code == 1 && value != 1023) wm_y = value;
- }
-
- if (type == EV_KEY)
- {
- if (code == 0x131 && menustate == MENU_LGCAL1)
- {
- if (value == 1) wm_ok = 1;
- if (value == 0) wm_ok = 2;
- return 1;
- }
- }
- return 0;
-}
+{
+ if (type == EV_ABS)
+ {
+ if (code == 0 && value) wm_x = value;
+ if (code == 1 && value != 1023) wm_y = value;
+ }
+
+ if (type == EV_KEY)
+ {
+ if (code == 0x131 && menustate == MENU_LGCAL1)
+ {
+ if (value == 1) wm_ok = 1;
+ if (value == 0) wm_ok = 2;
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/support/minimig/minimig_boot.cpp b/support/minimig/minimig_boot.cpp
index 7245d33..13fe2bf 100644
--- a/support/minimig/minimig_boot.cpp
+++ b/support/minimig/minimig_boot.cpp
@@ -445,7 +445,7 @@ void BootInit()
}
minimig_config.kickstart[0] = 0;
- minimig_LoadCfg(0);
+ minimig_cfg_load(0);
}
void BootPrintEx(const char * str)
diff --git a/support/minimig/minimig_config.cpp b/support/minimig/minimig_config.cpp
index 286d4bb..73458ef 100644
--- a/support/minimig/minimig_config.cpp
+++ b/support/minimig/minimig_config.cpp
@@ -267,12 +267,12 @@ static char* GetConfigurationName(int num, int chk)
return name+strlen(CONFIG_DIR)+1;
}
-int minimig_SaveCfg(int num)
+int minimig_cfg_save(int num)
{
return FileSaveConfig(GetConfigurationName(num, 0), &minimig_config, sizeof(minimig_config));
}
-const char* minimig_GetCfgInfo(int num)
+const char* minimig_get_cfg_info(int num)
{
char *filename = GetConfigurationName(num, 1);
if (!filename) return NULL;
@@ -366,7 +366,7 @@ static void ApplyConfiguration(char reloadkickstart)
ConfigAutofire(minimig_config.autofire, 0xC);
}
-int minimig_LoadCfg(int num)
+int minimig_cfg_load(int num)
{
static const char config_id[] = "MNMGCFG0";
char updatekickstart = 0;
@@ -486,13 +486,13 @@ int minimig_LoadCfg(int num)
return(result);
}
-void MinimigReset()
+void minimig_reset()
{
ApplyConfiguration(0);
user_io_rtc_reset();
}
-void SetKickstart(char *name)
+void minimig_set_kickstart(char *name)
{
uint len = strlen(name);
if (len > (sizeof(minimig_config.kickstart) - 1)) len = sizeof(minimig_config.kickstart) - 1;
@@ -500,3 +500,127 @@ void SetKickstart(char *name)
minimig_config.kickstart[len] = 0;
force_reload_kickstart = 1;
}
+
+static char minimig_adjust = 0;
+
+typedef struct
+{
+ uint32_t mode;
+ uint32_t hpos;
+ uint32_t vpos;
+ uint32_t reserved;
+} vmode_adjust_t;
+
+vmode_adjust_t vmodes_adj[64] = {};
+
+static void adjust_vsize(char force)
+{
+ static uint16_t nres = 0;
+ spi_uio_cmd_cont(UIO_GET_VMODE);
+ uint16_t res = spi_w(0);
+ if ((res & 0x8000) && (nres != res || force))
+ {
+ nres = res;
+ uint16_t scr_hsize = spi_w(0);
+ uint16_t scr_vsize = spi_w(0);
+ DisableIO();
+
+ printf("\033[1;37mVMODE: resolution: %u x %u, mode: %u\033[0m\n", scr_hsize, scr_vsize, res & 255);
+
+ static int loaded = 0;
+ if (~loaded)
+ {
+ FileLoadConfig("minimig_vadjust.dat", vmodes_adj, sizeof(vmodes_adj));
+ loaded = 1;
+ }
+
+ uint32_t mode = scr_hsize | (scr_vsize << 12) | ((res & 0xFF) << 24);
+ if (mode)
+ {
+ for (uint i = 0; i < sizeof(vmodes_adj) / sizeof(vmodes_adj[0]); i++)
+ {
+ if (vmodes_adj[i].mode == mode)
+ {
+ spi_uio_cmd_cont(UIO_SET_VPOS);
+ spi_w(vmodes_adj[i].hpos >> 16);
+ spi_w(vmodes_adj[i].hpos);
+ spi_w(vmodes_adj[i].vpos >> 16);
+ spi_w(vmodes_adj[i].vpos);
+ printf("\033[1;37mVMODE: set positions: [%u-%u, %u-%u]\033[0m\n", vmodes_adj[i].hpos >> 16, (uint16_t)vmodes_adj[i].hpos, vmodes_adj[i].vpos >> 16, (uint16_t)vmodes_adj[i].vpos);
+ DisableIO();
+ return;
+ }
+ }
+ printf("\033[1;37mVMODE: preset not found.\033[0m\n");
+ spi_uio_cmd_cont(UIO_SET_VPOS); spi_w(0); spi_w(0); spi_w(0); spi_w(0);
+ DisableIO();
+ }
+ }
+ else
+ {
+ DisableIO();
+ }
+}
+
+static void store_vsize()
+{
+ Info("Stored");
+ minimig_adjust = 0;
+
+ spi_uio_cmd_cont(UIO_GET_VMODE);
+ uint16_t res = spi_w(0);
+ uint16_t scr_hsize = spi_w(0);
+ uint16_t scr_vsize = spi_w(0);
+ uint16_t scr_hbl_l = spi_w(0);
+ uint16_t scr_hbl_r = spi_w(0);
+ uint16_t scr_vbl_t = spi_w(0);
+ uint16_t scr_vbl_b = spi_w(0);
+ DisableIO();
+
+ printf("\033[1;37mVMODE: store position: [%u-%u, %u-%u]\033[0m\n", scr_hbl_l, scr_hbl_r, scr_vbl_t, scr_vbl_b);
+
+ uint32_t mode = scr_hsize | (scr_vsize << 12) | ((res & 0xFF) << 24);
+ if (mode)
+ {
+ int applied = 0;
+ int empty = -1;
+ for (int i = 0; (uint)i < sizeof(vmodes_adj) / sizeof(vmodes_adj[0]); i++)
+ {
+ if (vmodes_adj[i].mode == mode)
+ {
+ vmodes_adj[i].hpos = (scr_hbl_l << 16) | scr_hbl_r;
+ vmodes_adj[i].vpos = (scr_vbl_t << 16) | scr_vbl_b;
+ applied = 1;
+ }
+ if (empty < 0 && !vmodes_adj[i].mode) empty = i;
+ }
+
+ if (!applied && empty >= 0)
+ {
+ vmodes_adj[empty].mode = mode;
+ vmodes_adj[empty].hpos = (scr_hbl_l << 16) | scr_hbl_r;
+ vmodes_adj[empty].vpos = (scr_vbl_t << 16) | scr_vbl_b;
+ applied = 1;
+ }
+
+ if (applied)
+ {
+ FileSaveConfig("minimig_vadjust.dat", vmodes_adj, sizeof(vmodes_adj));
+ }
+ }
+}
+
+// 0 - disable
+// 1 - enable
+// 2 - cancel
+void minimig_set_adjust(char n)
+{
+ if (minimig_adjust && !n) store_vsize();
+ minimig_adjust = (n == 1) ? 1 : 0;
+ if (n == 2) adjust_vsize(1);
+}
+
+char minimig_get_adjust()
+{
+ return minimig_adjust;
+}
diff --git a/support/minimig/minimig_config.h b/support/minimig/minimig_config.h
index 1a16c9b..612a434 100644
--- a/support/minimig/minimig_config.h
+++ b/support/minimig/minimig_config.h
@@ -44,11 +44,14 @@ typedef struct
extern mm_configTYPE minimig_config;
-int minimig_LoadCfg(int num);
-int minimig_SaveCfg(int num);
-const char* minimig_GetCfgInfo(int num);
+int minimig_cfg_load(int num);
+int minimig_cfg_save(int num);
+const char* minimig_get_cfg_info(int num);
-void MinimigReset();
-void SetKickstart(char *name);
+void minimig_reset();
+void minimig_set_kickstart(char *name);
+
+void minimig_set_adjust(char n);
+char minimig_get_adjust();
#endif
diff --git a/user_io.cpp b/user_io.cpp
index 6dd080f..c89ea2c 100644
--- a/user_io.cpp
+++ b/user_io.cpp
@@ -30,6 +30,7 @@
#include "scaler.h"
#include "miniz.h"
#include "cheats.h"
+#include "video.h"
#include "support.h"
@@ -68,8 +69,6 @@ static bool caps_status = 0;
static bool num_status = 0;
static bool scrl_status = 0;
-static char minimig_adjust = 0;
-
static char last_filename[1024] = {};
void user_io_store_filename(char *filename)
{
@@ -533,7 +532,8 @@ void user_io_init(const char *path)
{
bootcore_init(path);
}
- parse_video_mode();
+
+ video_mode_load();
if(strlen(cfg.font)) LoadFont(cfg.font);
FileLoadConfig("Volume.dat", &vol_att, 1);
vol_att &= 0x1F;
@@ -1574,8 +1574,6 @@ void user_io_rtc_reset()
static int coldreset_req = 0;
-static int adjust_video_mode(uint32_t vtime);
-static uint32_t show_video_info(int force);
static uint32_t res_timer = 0;
void user_io_poll()
@@ -2149,15 +2147,9 @@ void user_io_poll()
else if(CheckTimer(res_timer))
{
res_timer = GetTimer(500);
- if (!minimig_adjust)
+ if (!minimig_get_adjust())
{
- uint32_t vtime = show_video_info(0);
- if (vtime && cfg.vsync_adjust && !is_menu_core())
- {
- adjust_video_mode(vtime);
- usleep(100000);
- show_video_info(1);
- }
+ video_mode_adjust();
}
}
@@ -2196,19 +2188,6 @@ char user_io_user_button()
return((!user_io_menu_button() && (fpga_get_buttons() & BUTTON_USR)) ? 1 : 0);
}
-static void adjust_vsize(char force);
-static void store_vsize();
-void user_io_minimig_set_adjust(char n)
-{
- if (minimig_adjust & !n) store_vsize();
- minimig_adjust = n;
-}
-
-char user_io_minimig_get_adjust()
-{
- return minimig_adjust;
-}
-
static void send_keycode(unsigned short key, int press)
{
if (core_type == CORE_TYPE_MINIMIG2)
@@ -2239,11 +2218,11 @@ static void send_keycode(unsigned short key, int press)
}
code &= 0xff;
- if (minimig_adjust)
+ if (minimig_get_adjust())
{
if (code == 0x44)
{
- store_vsize();
+ minimig_set_adjust(0);
res_timer = 0;
return;
}
@@ -2252,8 +2231,7 @@ static void send_keycode(unsigned short key, int press)
{
Info("Canceled");
res_timer = 0;
- minimig_adjust = 0;
- adjust_vsize(1);
+ minimig_set_adjust(2);
return;
}
code |= OSD;
@@ -2470,7 +2448,7 @@ void user_io_check_reset(unsigned short modifiers, char useKeys)
switch (core_type)
{
case CORE_TYPE_MINIMIG2:
- MinimigReset();
+ minimig_reset();
break;
case CORE_TYPE_ARCHIE:
@@ -2714,606 +2692,3 @@ unsigned char user_io_ext_idx(char *name, char* ext)
printf("not found! use 0\n");
return 0;
}
-
-struct vmode_t
-{
- uint32_t vpar[8];
- double Fpix;
-};
-
-vmode_t vmodes[] =
-{
- { { 1280, 110, 40, 220, 720, 5, 5, 20 }, 74.25 }, //0
- { { 1024, 24, 136, 160, 768, 3, 6, 29 }, 65 }, //1
- { { 720, 16, 62, 60, 480, 9, 6, 30 }, 27 }, //2
- { { 720, 12, 64, 68, 576, 5, 5, 39 }, 27 }, //3
- { { 1280, 48, 112, 248, 1024, 1, 3, 38 }, 108 }, //4
- { { 800, 40, 128, 88, 600, 1, 4, 23 }, 40 }, //5
- { { 640, 16, 96, 48, 480, 10, 2, 33 }, 25.175 }, //6
- { { 1280, 440, 40, 220, 720, 5, 5, 20 }, 74.25 }, //7
- { { 1920, 88, 44, 148, 1080, 4, 5, 36 }, 148.5 }, //8
- { { 1920, 528, 44, 148, 1080, 4, 5, 36 }, 148.5 }, //9
- { { 1366, 70, 143, 213, 768, 3, 3, 24 }, 85.5 }, //10
- { { 1024, 40, 104, 144, 600, 1, 3, 18 }, 48.96 }, //11
-};
-#define VMODES_NUM (sizeof(vmodes) / sizeof(vmodes[0]))
-
-struct vmode_custom_t
-{
- uint32_t item[32];
- double Fpix;
-};
-
-static vmode_custom_t v_cur = {}, v_def = {}, v_pal = {}, v_ntsc = {};
-static int vmode_def = 0, vmode_pal = 0, vmode_ntsc = 0;
-
-static uint32_t getPLLdiv(uint32_t div)
-{
- if (div & 1) return 0x20000 | (((div / 2) + 1) << 8) | (div / 2);
- return ((div / 2) << 8) | (div / 2);
-}
-
-static int findPLLpar(double Fout, uint32_t *pc, uint32_t *pm, double *pko)
-{
- uint32_t c = 1;
- while ((Fout*c) < 400) c++;
-
- while (1)
- {
- double fvco = Fout*c;
- uint32_t m = (uint32_t)(fvco / 50);
- double ko = ((fvco / 50) - m);
-
- fvco = ko + m;
- fvco *= 50.f;
-
- if (ko && (ko <= 0.05f || ko >= 0.95f))
- {
- printf("Fvco=%f, C=%d, M=%d, K=%f ", fvco, c, m, ko);
- if (fvco > 1500.f)
- {
- printf("-> No exact parameters found\n");
- return 0;
- }
- printf("-> K is outside allowed range\n");
- c++;
- }
- else
- {
- *pc = c;
- *pm = m;
- *pko = ko;
- return 1;
- }
- }
-
- //will never reach here
- return 0;
-}
-
-static void setPLL(double Fout, vmode_custom_t *v)
-{
- double Fpix;
- double fvco, ko;
- uint32_t m, c;
-
- printf("Calculate PLL for %.4f MHz:\n", Fout);
-
- if (!findPLLpar(Fout, &c, &m, &ko))
- {
- c = 1;
- while ((Fout*c) < 400) c++;
-
- fvco = Fout*c;
- m = (uint32_t)(fvco / 50);
- ko = ((fvco / 50) - m);
-
- //Make sure K is in allowed range.
- if (ko <= 0.05f)
- {
- ko = 0;
- }
- else if (ko >= 0.95f)
- {
- m++;
- ko = 0;
- }
- }
-
- uint32_t k = ko ? (uint32_t)(ko * 4294967296) : 1;
-
- fvco = ko + m;
- fvco *= 50.f;
- Fpix = fvco / c;
-
- printf("Fvco=%f, C=%d, M=%d, K=%f(%u) -> Fpix=%f\n", fvco, c, m, ko, k, Fpix);
-
- v->item[9] = 4;
- v->item[10] = getPLLdiv(m);
- v->item[11] = 3;
- v->item[12] = 0x10000;
- v->item[13] = 5;
- v->item[14] = getPLLdiv(c);
- v->item[15] = 9;
- v->item[16] = 2;
- v->item[17] = 8;
- v->item[18] = 7;
- v->item[19] = 7;
- v->item[20] = k;
-
- v->Fpix = Fpix;
-}
-
-static char scaler_flt_cfg[1024] = { 0 };
-static char new_scaler = 0;
-
-static void setScaler()
-{
- fileTYPE f = {};
- static char filename[1024];
-
- if (!spi_uio_cmd_cont(UIO_SET_FLTNUM))
- {
- DisableIO();
- return;
- }
-
- new_scaler = 1;
- spi8(scaler_flt_cfg[0]);
- DisableIO();
- sprintf(filename, COEFF_DIR"/%s", scaler_flt_cfg + 1);
-
- if (FileOpen(&f, filename))
- {
- printf("Read scaler coefficients\n");
- char *buf = (char*)malloc(f.size+1);
- if (buf)
- {
- memset(buf, 0, f.size + 1);
- int size;
- if ((size = FileReadAdv(&f, buf, f.size)))
- {
- spi_uio_cmd_cont(UIO_SET_FLTCOEF);
-
- char *end = buf + size;
- char *pos = buf;
- int phase = 0;
- while (pos < end)
- {
- char *st = pos;
- while ((pos < end) && *pos && (*pos != 10)) pos++;
- *pos = 0;
- while (*st == ' ' || *st == '\t' || *st == 13) st++;
- if (*st == '#' || *st == ';' || !*st) pos++;
- else
- {
- int c0, c1, c2, c3;
- int n = sscanf(st, "%d,%d,%d,%d", &c0, &c1, &c2, &c3);
- if (n == 4)
- {
- printf(" phase %c-%02d: %4d,%4d,%4d,%4d\n", (phase >= 16) ? 'V' : 'H', phase % 16, c0, c1, c2, c3);
- //printf("%03X: %03X %03X %03X %03X;\n",phase*4, c0 & 0x1FF, c1 & 0x1FF, c2 & 0x1FF, c3 & 0x1FF);
-
- spi_w((c0 & 0x1FF) | (((phase * 4) + 0) << 9));
- spi_w((c1 & 0x1FF) | (((phase * 4) + 1) << 9));
- spi_w((c2 & 0x1FF) | (((phase * 4) + 2) << 9));
- spi_w((c3 & 0x1FF) | (((phase * 4) + 3) << 9));
-
- phase++;
- if (phase >= 32) break;
- }
- }
- }
- DisableIO();
- }
-
- free(buf);
- }
- }
-}
-
-int user_io_get_scaler_flt()
-{
- return new_scaler ? scaler_flt_cfg[0] : -1;
-}
-
-char* user_io_get_scaler_coeff()
-{
- return scaler_flt_cfg + 1;
-}
-
-static char scaler_cfg[128] = { 0 };
-
-void user_io_set_scaler_flt(int n)
-{
- scaler_flt_cfg[0] = (char)n;
- FileSaveConfig(scaler_cfg, &scaler_flt_cfg, sizeof(scaler_flt_cfg));
- spi_uio_cmd8(UIO_SET_FLTNUM, scaler_flt_cfg[0]);
- spi_uio_cmd(UIO_SET_FLTCOEF);
-}
-
-void user_io_set_scaler_coeff(char *name)
-{
- strcpy(scaler_flt_cfg + 1, name);
- FileSaveConfig(scaler_cfg, &scaler_flt_cfg, sizeof(scaler_flt_cfg));
- setScaler();
- user_io_send_buttons(1);
-}
-
-static void loadScalerCfg()
-{
- sprintf(scaler_cfg, "%s_scaler.cfg", user_io_get_core_name_ex());
- if (!FileLoadConfig(scaler_cfg, &scaler_flt_cfg, sizeof(scaler_flt_cfg) - 1) || scaler_flt_cfg[0]>4)
- {
- memset(scaler_flt_cfg, 0, sizeof(scaler_flt_cfg));
- }
-}
-
-static void setVideo(vmode_custom_t *v, double Fpix)
-{
- loadScalerCfg();
- setScaler();
-
- printf("Send HDMI parameters:\n");
- spi_uio_cmd_cont(UIO_SET_VIDEO);
- printf("video: ");
- for (int i = 1; i <= 8; i++)
- {
- v_cur.item[i] = v->item[i];
- spi_w(v_cur.item[i]);
- printf("%d, ", v_cur.item[i]);
- }
-
- for (int i = 9; i < 21; i++) v_cur.item[i] = v->item[i];
- v_cur.Fpix = v->Fpix;
-
- if(Fpix) setPLL(Fpix, &v_cur);
-
- printf("\nPLL: ");
- for (int i = 9; i < 21; i++)
- {
- printf("0x%X, ", v_cur.item[i]);
- if (i & 1) spi_w(v_cur.item[i] | ((i == 9 && (is_menu_core() ? cfg.menu_pal : (Fpix && cfg.vsync_adjust == 2))) ? 0x8000 : 0));
- else
- {
- spi_w(v_cur.item[i]);
- spi_w(v_cur.item[i] >> 16);
- }
- }
-
- printf("Fpix=%f\n", v_cur.Fpix);
- DisableIO();
-}
-
-static int parse_custom_video_mode(char* vcfg, vmode_custom_t *v)
-{
- int khz = 0;
- int cnt = 0;
- char *orig = vcfg;
- while (*vcfg)
- {
- char *next;
- if (cnt == 9 && v->item[0] == 1)
- {
- double Fpix = khz ? strtoul(vcfg, &next, 0)/1000.f : strtod(vcfg, &next);
- if (vcfg == next || (Fpix < 2.f || Fpix > 300.f))
- {
- printf("Error parsing video_mode parameter: ""%s""\n", orig);
- return -1;
- }
-
- setPLL(Fpix, v);
- break;
- }
-
- uint32_t val = strtoul(vcfg, &next, 0);
- if (vcfg == next || (*next != ',' && *next))
- {
- printf("Error parsing video_mode parameter: ""%s""\n", orig);
- return -1;
- }
-
- if (!cnt && val >= 100)
- {
- v->item[cnt++] = 1;
- khz = 1;
- }
- if (cnt < 32) v->item[cnt] = val;
- if (*next == ',') next++;
- vcfg = next;
- cnt++;
- }
-
- if (cnt == 1)
- {
- printf("Set predefined video_mode to %d\n", v->item[0]);
- return v->item[0];
- }
-
- if ((v->item[0] == 0 && cnt < 21) || (v->item[0] == 1 && cnt < 9))
- {
- printf("Incorrect amount of items in video_mode parameter: %d\n", cnt);
- return -1;
- }
-
- if (v->item[0] > 1)
- {
- printf("Incorrect video_mode parameter\n");
- return -1;
- }
-
- return -2;
-}
-
-static int store_custom_video_mode(char* vcfg, vmode_custom_t *v)
-{
- int ret = parse_custom_video_mode(vcfg, v);
- if (ret == -2) return 1;
-
- uint mode = (ret < 0) ? 0 : ret;
- if (mode >= VMODES_NUM) mode = 0;
- for (int i = 0; i < 8; i++) v->item[i + 1] = vmodes[mode].vpar[i];
- setPLL(vmodes[mode].Fpix, v);
-
- return ret >= 0;
-}
-
-void parse_video_mode()
-{
- vmode_def = store_custom_video_mode(cfg.video_conf, &v_def);
- vmode_pal = store_custom_video_mode(cfg.video_conf_pal, &v_pal);
- vmode_ntsc = store_custom_video_mode(cfg.video_conf_ntsc, &v_ntsc);
- setVideo(&v_def, 0);
-}
-
-static int adjust_video_mode(uint32_t vtime)
-{
- printf("\033[1;33madjust_video_mode(%u): vsync_adjust=%d", vtime, cfg.vsync_adjust);
-
- int adjust = 1;
- vmode_custom_t *v = &v_def;
- if (vmode_pal || vmode_ntsc)
- {
- if (vtime > 1800000)
- {
- if (vmode_pal)
- {
- printf(", using PAL mode");
- v = &v_pal;
- }
- else
- {
- printf(", PAL mode cannot be used. Using predefined NTSC mode");
- v = &v_ntsc;
- adjust = 0;
- }
- }
- else
- {
- if (vmode_ntsc)
- {
- printf(", using NTSC mode");
- v = &v_ntsc;
- }
- else
- {
- printf(", NTSC mode cannot be used. Using predefined PAL mode");
- v = &v_pal;
- adjust = 0;
- }
- }
- }
-
- printf(".\033[0m\n");
-
- double Fpix = 0;
- if (adjust)
- {
- Fpix = 100 * (v->item[1] + v->item[2] + v->item[3] + v->item[4]) * (v->item[5] + v->item[6] + v->item[7] + v->item[8]);
- Fpix /= vtime;
- if (Fpix < 2.f || Fpix > 300.f)
- {
- printf("Estimated Fpix(%.4f MHz) is outside supported range. Canceling auto-adjust.\n", Fpix);
- Fpix = 0;
- }
- }
-
- setVideo(v, Fpix);
- user_io_send_buttons(1);
- return 1;
-}
-
-typedef struct
-{
- uint32_t mode;
- uint32_t hpos;
- uint32_t vpos;
- uint32_t reserved;
-} vmode_adjust_t;
-
-vmode_adjust_t vmodes_adj[64] = {};
-
-static void adjust_vsize(char force)
-{
- static uint16_t nres = 0;
- spi_uio_cmd_cont(UIO_GET_VMODE);
- uint16_t res = spi_w(0);
- if ((res & 0x8000) && (nres != res || force))
- {
- nres = res;
- uint16_t scr_hsize = spi_w(0);
- uint16_t scr_vsize = spi_w(0);
- DisableIO();
-
- printf("\033[1;37mVMODE: resolution: %u x %u, mode: %u\033[0m\n", scr_hsize, scr_vsize, res & 255);
-
- static int loaded = 0;
- if (~loaded)
- {
- FileLoadConfig("minimig_vadjust.dat", vmodes_adj, sizeof(vmodes_adj));
- loaded = 1;
- }
-
- uint32_t mode = scr_hsize | (scr_vsize << 12) | ((res & 0xFF) << 24);
- if (mode)
- {
- for (uint i = 0; i < sizeof(vmodes_adj) / sizeof(vmodes_adj[0]); i++)
- {
- if (vmodes_adj[i].mode == mode)
- {
- spi_uio_cmd_cont(UIO_SET_VPOS);
- spi_w(vmodes_adj[i].hpos >> 16);
- spi_w(vmodes_adj[i].hpos);
- spi_w(vmodes_adj[i].vpos >> 16);
- spi_w(vmodes_adj[i].vpos);
- printf("\033[1;37mVMODE: set positions: [%u-%u, %u-%u]\033[0m\n", vmodes_adj[i].hpos >> 16, (uint16_t)vmodes_adj[i].hpos, vmodes_adj[i].vpos >> 16, (uint16_t)vmodes_adj[i].vpos);
- DisableIO();
- return;
- }
- }
- printf("\033[1;37mVMODE: preset not found.\033[0m\n");
- spi_uio_cmd_cont(UIO_SET_VPOS); spi_w(0); spi_w(0); spi_w(0); spi_w(0);
- DisableIO();
- }
- }
- else
- {
- DisableIO();
- }
-}
-
-static void store_vsize()
-{
- Info("Stored");
- minimig_adjust = 0;
-
- spi_uio_cmd_cont(UIO_GET_VMODE);
- uint16_t res = spi_w(0);
- uint16_t scr_hsize = spi_w(0);
- uint16_t scr_vsize = spi_w(0);
- uint16_t scr_hbl_l = spi_w(0);
- uint16_t scr_hbl_r = spi_w(0);
- uint16_t scr_vbl_t = spi_w(0);
- uint16_t scr_vbl_b = spi_w(0);
- DisableIO();
-
- printf("\033[1;37mVMODE: store position: [%u-%u, %u-%u]\033[0m\n", scr_hbl_l, scr_hbl_r, scr_vbl_t, scr_vbl_b);
-
- uint32_t mode = scr_hsize | (scr_vsize << 12) | ((res & 0xFF) << 24);
- if (mode)
- {
- int applied = 0;
- int empty = -1;
- for (int i = 0; (uint)i < sizeof(vmodes_adj) / sizeof(vmodes_adj[0]); i++)
- {
- if (vmodes_adj[i].mode == mode)
- {
- vmodes_adj[i].hpos = (scr_hbl_l << 16) | scr_hbl_r;
- vmodes_adj[i].vpos = (scr_vbl_t << 16) | scr_vbl_b;
- applied = 1;
- }
- if (empty < 0 && !vmodes_adj[i].mode) empty = i;
- }
-
- if (!applied && empty >= 0)
- {
- vmodes_adj[empty].mode = mode;
- vmodes_adj[empty].hpos = (scr_hbl_l << 16) | scr_hbl_r;
- vmodes_adj[empty].vpos = (scr_vbl_t << 16) | scr_vbl_b;
- applied = 1;
- }
-
- if (applied)
- {
- FileSaveConfig("minimig_vadjust.dat", vmodes_adj, sizeof(vmodes_adj));
- }
- }
-}
-
-static int api1_5 = 0;
-static uint32_t show_video_info(int force)
-{
- uint32_t ret = 0;
- static uint16_t nres = 0;
- spi_uio_cmd_cont(UIO_GET_VRES);
- uint16_t res = spi_w(0);
- if ((nres != res) || force)
- {
- nres = res;
- uint32_t width = spi_w(0) | (spi_w(0) << 16);
- uint32_t height = spi_w(0) | (spi_w(0) << 16);
- uint32_t htime = spi_w(0) | (spi_w(0) << 16);
- uint32_t vtime = spi_w(0) | (spi_w(0) << 16);
- uint32_t ptime = spi_w(0) | (spi_w(0) << 16);
- uint32_t vtimeh = spi_w(0) | (spi_w(0) << 16);
- DisableIO();
-
- float vrate = 100000000;
- if (vtime) vrate /= vtime; else vrate = 0;
- float hrate = 100000;
- if (htime) hrate /= htime; else hrate = 0;
-
- float prate = width * 100;
- prate /= ptime;
-
- printf("\033[1;33mINFO: Video resolution: %u x %u%s, fHorz = %.1fKHz, fVert = %.1fHz, fPix = %.2fMHz\033[0m\n", width, height, (res & 0x100) ? "i" : "", hrate, vrate, prate);
- printf("\033[1;33mINFO: Frame time (100MHz counter): VGA = %d, HDMI = %d\033[0m\n", vtime, vtimeh);
-
- if (vtimeh) api1_5 = 1;
- if (hasAPI1_5() && cfg.video_info)
- {
- static char str[128], res1[16], res2[16];
- float vrateh = 100000000;
- if (vtimeh) vrateh /= vtimeh; else vrateh = 0;
- sprintf(res1, "%dx%d%s", width, height, (res & 0x100) ? "i" : "");
- sprintf(res2, "%dx%d", v_cur.item[1], v_cur.item[5]);
- sprintf(str, "%9s %6.2fKHz %4.1fHz\n" \
- "\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\n" \
- "%9s %6.2fMHz %4.1fHz",
- res1, hrate, vrate, res2, v_cur.Fpix, vrateh);
- Info(str, cfg.video_info * 1000);
- }
-
- uint32_t scrh = v_cur.item[5];
- if (height && scrh)
- {
- if (cfg.vscale_border)
- {
- uint32_t border = cfg.vscale_border * 2;
- if ((border + 100) > scrh) border = scrh - 100;
- scrh -= border;
- }
-
- if (cfg.vscale_mode)
- {
- uint32_t div = 1 << (cfg.vscale_mode - 1);
- uint32_t mag = (scrh*div) / height;
- scrh = (height * mag) / div;
- }
-
- if(cfg.vscale_border || cfg.vscale_mode)
- {
- printf("*** Set vertical scaling to : %d\n", scrh);
- spi_uio_cmd16(UIO_SETHEIGHT, scrh);
- }
- else
- {
- spi_uio_cmd16(UIO_SETHEIGHT, 0);
- }
- }
-
- if (vtime && vtimeh) ret = vtime;
- }
- else
- {
- DisableIO();
- }
-
- adjust_vsize(0);
- return ret;
-}
-
-int hasAPI1_5()
-{
- return api1_5;
-}
diff --git a/user_io.h b/user_io.h
index 76aa667..cee5d09 100644
--- a/user_io.h
+++ b/user_io.h
@@ -67,6 +67,8 @@
#define UIO_GET_VMODE 0x2C // Get video mode parameters
#define UIO_SET_VPOS 0x2D // Set video positions
#define UIO_GET_OSDMASK 0x2E // Get mask
+#define UIO_SET_FBUF 0x2F // Set frame buffer for HPS output
+#define UIO_WAIT_VSYNC 0x30 // Wait for VSync
// codes as used by 8bit for file loading from OSD
#define UIO_FILE_TX 0x53
@@ -222,7 +224,6 @@ void user_io_set_joyswap(int swap);
int user_io_get_joyswap();
char user_io_osd_is_visible();
void user_io_send_buttons(char);
-void parse_video_mode();
void user_io_set_index(unsigned char index);
unsigned char user_io_ext_idx(char *, char*);
@@ -231,19 +232,9 @@ void user_io_check_reset(unsigned short modifiers, char useKeys);
void user_io_rtc_reset();
-int hasAPI1_5();
-
const char* get_rbf_dir();
const char* get_rbf_name();
-int user_io_get_scaler_flt();
-char* user_io_get_scaler_coeff();
-void user_io_set_scaler_flt(int n);
-void user_io_set_scaler_coeff(char *name);
-
-void user_io_minimig_set_adjust(char n);
-char user_io_minimig_get_adjust();
-
#define HomeDir (is_minimig() ? "Amiga" : is_archie() ? "Archie" : is_menu_core() ? "Scripts" : user_io_get_core_name())
int GetUARTMode();
diff --git a/video.cpp b/video.cpp
new file mode 100644
index 0000000..589de2f
--- /dev/null
+++ b/video.cpp
@@ -0,0 +1,515 @@
+#include
+#include
+#include
+#include
+
+#include "hardware.h"
+#include "user_io.h"
+#include "spi.h"
+#include "cfg.h"
+#include "file_io.h"
+#include "menu.h"
+#include "video.h"
+
+#include "support.h"
+
+struct vmode_t
+{
+ uint32_t vpar[8];
+ double Fpix;
+};
+
+vmode_t vmodes[] =
+{
+ { { 1280, 110, 40, 220, 720, 5, 5, 20 }, 74.25 }, //0
+ { { 1024, 24, 136, 160, 768, 3, 6, 29 }, 65 }, //1
+ { { 720, 16, 62, 60, 480, 9, 6, 30 }, 27 }, //2
+ { { 720, 12, 64, 68, 576, 5, 5, 39 }, 27 }, //3
+ { { 1280, 48, 112, 248, 1024, 1, 3, 38 }, 108 }, //4
+ { { 800, 40, 128, 88, 600, 1, 4, 23 }, 40 }, //5
+ { { 640, 16, 96, 48, 480, 10, 2, 33 }, 25.175 }, //6
+ { { 1280, 440, 40, 220, 720, 5, 5, 20 }, 74.25 }, //7
+ { { 1920, 88, 44, 148, 1080, 4, 5, 36 }, 148.5 }, //8
+ { { 1920, 528, 44, 148, 1080, 4, 5, 36 }, 148.5 }, //9
+ { { 1366, 70, 143, 213, 768, 3, 3, 24 }, 85.5 }, //10
+ { { 1024, 40, 104, 144, 600, 1, 3, 18 }, 48.96 }, //11
+};
+#define VMODES_NUM (sizeof(vmodes) / sizeof(vmodes[0]))
+
+struct vmode_custom_t
+{
+ uint32_t item[32];
+ double Fpix;
+};
+
+static vmode_custom_t v_cur = {}, v_def = {}, v_pal = {}, v_ntsc = {};
+static int vmode_def = 0, vmode_pal = 0, vmode_ntsc = 0;
+
+static uint32_t getPLLdiv(uint32_t div)
+{
+ if (div & 1) return 0x20000 | (((div / 2) + 1) << 8) | (div / 2);
+ return ((div / 2) << 8) | (div / 2);
+}
+
+static int findPLLpar(double Fout, uint32_t *pc, uint32_t *pm, double *pko)
+{
+ uint32_t c = 1;
+ while ((Fout*c) < 400) c++;
+
+ while (1)
+ {
+ double fvco = Fout*c;
+ uint32_t m = (uint32_t)(fvco / 50);
+ double ko = ((fvco / 50) - m);
+
+ fvco = ko + m;
+ fvco *= 50.f;
+
+ if (ko && (ko <= 0.05f || ko >= 0.95f))
+ {
+ printf("Fvco=%f, C=%d, M=%d, K=%f ", fvco, c, m, ko);
+ if (fvco > 1500.f)
+ {
+ printf("-> No exact parameters found\n");
+ return 0;
+ }
+ printf("-> K is outside allowed range\n");
+ c++;
+ }
+ else
+ {
+ *pc = c;
+ *pm = m;
+ *pko = ko;
+ return 1;
+ }
+ }
+
+ //will never reach here
+ return 0;
+}
+
+static void setPLL(double Fout, vmode_custom_t *v)
+{
+ double Fpix;
+ double fvco, ko;
+ uint32_t m, c;
+
+ printf("Calculate PLL for %.4f MHz:\n", Fout);
+
+ if (!findPLLpar(Fout, &c, &m, &ko))
+ {
+ c = 1;
+ while ((Fout*c) < 400) c++;
+
+ fvco = Fout*c;
+ m = (uint32_t)(fvco / 50);
+ ko = ((fvco / 50) - m);
+
+ //Make sure K is in allowed range.
+ if (ko <= 0.05f)
+ {
+ ko = 0;
+ }
+ else if (ko >= 0.95f)
+ {
+ m++;
+ ko = 0;
+ }
+ }
+
+ uint32_t k = ko ? (uint32_t)(ko * 4294967296) : 1;
+
+ fvco = ko + m;
+ fvco *= 50.f;
+ Fpix = fvco / c;
+
+ printf("Fvco=%f, C=%d, M=%d, K=%f(%u) -> Fpix=%f\n", fvco, c, m, ko, k, Fpix);
+
+ v->item[9] = 4;
+ v->item[10] = getPLLdiv(m);
+ v->item[11] = 3;
+ v->item[12] = 0x10000;
+ v->item[13] = 5;
+ v->item[14] = getPLLdiv(c);
+ v->item[15] = 9;
+ v->item[16] = 2;
+ v->item[17] = 8;
+ v->item[18] = 7;
+ v->item[19] = 7;
+ v->item[20] = k;
+
+ v->Fpix = Fpix;
+}
+
+static char scaler_flt_cfg[1024] = { 0 };
+static char new_scaler = 0;
+
+static void setScaler()
+{
+ fileTYPE f = {};
+ static char filename[1024];
+
+ if (!spi_uio_cmd_cont(UIO_SET_FLTNUM))
+ {
+ DisableIO();
+ return;
+ }
+
+ new_scaler = 1;
+ spi8(scaler_flt_cfg[0]);
+ DisableIO();
+ sprintf(filename, COEFF_DIR"/%s", scaler_flt_cfg + 1);
+
+ if (FileOpen(&f, filename))
+ {
+ printf("Read scaler coefficients\n");
+ char *buf = (char*)malloc(f.size+1);
+ if (buf)
+ {
+ memset(buf, 0, f.size + 1);
+ int size;
+ if ((size = FileReadAdv(&f, buf, f.size)))
+ {
+ spi_uio_cmd_cont(UIO_SET_FLTCOEF);
+
+ char *end = buf + size;
+ char *pos = buf;
+ int phase = 0;
+ while (pos < end)
+ {
+ char *st = pos;
+ while ((pos < end) && *pos && (*pos != 10)) pos++;
+ *pos = 0;
+ while (*st == ' ' || *st == '\t' || *st == 13) st++;
+ if (*st == '#' || *st == ';' || !*st) pos++;
+ else
+ {
+ int c0, c1, c2, c3;
+ int n = sscanf(st, "%d,%d,%d,%d", &c0, &c1, &c2, &c3);
+ if (n == 4)
+ {
+ printf(" phase %c-%02d: %4d,%4d,%4d,%4d\n", (phase >= 16) ? 'V' : 'H', phase % 16, c0, c1, c2, c3);
+ //printf("%03X: %03X %03X %03X %03X;\n",phase*4, c0 & 0x1FF, c1 & 0x1FF, c2 & 0x1FF, c3 & 0x1FF);
+
+ spi_w((c0 & 0x1FF) | (((phase * 4) + 0) << 9));
+ spi_w((c1 & 0x1FF) | (((phase * 4) + 1) << 9));
+ spi_w((c2 & 0x1FF) | (((phase * 4) + 2) << 9));
+ spi_w((c3 & 0x1FF) | (((phase * 4) + 3) << 9));
+
+ phase++;
+ if (phase >= 32) break;
+ }
+ }
+ }
+ DisableIO();
+ }
+
+ free(buf);
+ }
+ }
+}
+
+int video_get_scaler_flt()
+{
+ return new_scaler ? scaler_flt_cfg[0] : -1;
+}
+
+char* video_get_scaler_coeff()
+{
+ return scaler_flt_cfg + 1;
+}
+
+static char scaler_cfg[128] = { 0 };
+
+void video_set_scaler_flt(int n)
+{
+ scaler_flt_cfg[0] = (char)n;
+ FileSaveConfig(scaler_cfg, &scaler_flt_cfg, sizeof(scaler_flt_cfg));
+ spi_uio_cmd8(UIO_SET_FLTNUM, scaler_flt_cfg[0]);
+ spi_uio_cmd(UIO_SET_FLTCOEF);
+}
+
+void video_set_scaler_coeff(char *name)
+{
+ strcpy(scaler_flt_cfg + 1, name);
+ FileSaveConfig(scaler_cfg, &scaler_flt_cfg, sizeof(scaler_flt_cfg));
+ setScaler();
+ user_io_send_buttons(1);
+}
+
+static void loadScalerCfg()
+{
+ sprintf(scaler_cfg, "%s_scaler.cfg", user_io_get_core_name_ex());
+ if (!FileLoadConfig(scaler_cfg, &scaler_flt_cfg, sizeof(scaler_flt_cfg) - 1) || scaler_flt_cfg[0]>4)
+ {
+ memset(scaler_flt_cfg, 0, sizeof(scaler_flt_cfg));
+ }
+}
+
+static void set_video(vmode_custom_t *v, double Fpix)
+{
+ loadScalerCfg();
+ setScaler();
+
+ printf("Send HDMI parameters:\n");
+ spi_uio_cmd_cont(UIO_SET_VIDEO);
+ printf("video: ");
+ for (int i = 1; i <= 8; i++)
+ {
+ v_cur.item[i] = v->item[i];
+ spi_w(v_cur.item[i]);
+ printf("%d, ", v_cur.item[i]);
+ }
+
+ for (int i = 9; i < 21; i++) v_cur.item[i] = v->item[i];
+ v_cur.Fpix = v->Fpix;
+
+ if(Fpix) setPLL(Fpix, &v_cur);
+
+ printf("\nPLL: ");
+ for (int i = 9; i < 21; i++)
+ {
+ printf("0x%X, ", v_cur.item[i]);
+ if (i & 1) spi_w(v_cur.item[i] | ((i == 9 && (is_menu_core() ? cfg.menu_pal : (Fpix && cfg.vsync_adjust == 2))) ? 0x8000 : 0));
+ else
+ {
+ spi_w(v_cur.item[i]);
+ spi_w(v_cur.item[i] >> 16);
+ }
+ }
+
+ printf("Fpix=%f\n", v_cur.Fpix);
+ DisableIO();
+}
+
+static int parse_custom_video_mode(char* vcfg, vmode_custom_t *v)
+{
+ int khz = 0;
+ int cnt = 0;
+ char *orig = vcfg;
+ while (*vcfg)
+ {
+ char *next;
+ if (cnt == 9 && v->item[0] == 1)
+ {
+ double Fpix = khz ? strtoul(vcfg, &next, 0)/1000.f : strtod(vcfg, &next);
+ if (vcfg == next || (Fpix < 2.f || Fpix > 300.f))
+ {
+ printf("Error parsing video_mode parameter: ""%s""\n", orig);
+ return -1;
+ }
+
+ setPLL(Fpix, v);
+ break;
+ }
+
+ uint32_t val = strtoul(vcfg, &next, 0);
+ if (vcfg == next || (*next != ',' && *next))
+ {
+ printf("Error parsing video_mode parameter: ""%s""\n", orig);
+ return -1;
+ }
+
+ if (!cnt && val >= 100)
+ {
+ v->item[cnt++] = 1;
+ khz = 1;
+ }
+ if (cnt < 32) v->item[cnt] = val;
+ if (*next == ',') next++;
+ vcfg = next;
+ cnt++;
+ }
+
+ if (cnt == 1)
+ {
+ printf("Set predefined video_mode to %d\n", v->item[0]);
+ return v->item[0];
+ }
+
+ if ((v->item[0] == 0 && cnt < 21) || (v->item[0] == 1 && cnt < 9))
+ {
+ printf("Incorrect amount of items in video_mode parameter: %d\n", cnt);
+ return -1;
+ }
+
+ if (v->item[0] > 1)
+ {
+ printf("Incorrect video_mode parameter\n");
+ return -1;
+ }
+
+ return -2;
+}
+
+static int store_custom_video_mode(char* vcfg, vmode_custom_t *v)
+{
+ int ret = parse_custom_video_mode(vcfg, v);
+ if (ret == -2) return 1;
+
+ uint mode = (ret < 0) ? 0 : ret;
+ if (mode >= VMODES_NUM) mode = 0;
+ for (int i = 0; i < 8; i++) v->item[i + 1] = vmodes[mode].vpar[i];
+ setPLL(vmodes[mode].Fpix, v);
+
+ return ret >= 0;
+}
+
+void video_mode_load()
+{
+ vmode_def = store_custom_video_mode(cfg.video_conf, &v_def);
+ vmode_pal = store_custom_video_mode(cfg.video_conf_pal, &v_pal);
+ vmode_ntsc = store_custom_video_mode(cfg.video_conf_ntsc, &v_ntsc);
+ set_video(&v_def, 0);
+}
+
+static int api1_5 = 0;
+static uint32_t show_video_info(int force)
+{
+ uint32_t ret = 0;
+ static uint16_t nres = 0;
+ spi_uio_cmd_cont(UIO_GET_VRES);
+ uint16_t res = spi_w(0);
+ if ((nres != res) || force)
+ {
+ nres = res;
+ uint32_t width = spi_w(0) | (spi_w(0) << 16);
+ uint32_t height = spi_w(0) | (spi_w(0) << 16);
+ uint32_t htime = spi_w(0) | (spi_w(0) << 16);
+ uint32_t vtime = spi_w(0) | (spi_w(0) << 16);
+ uint32_t ptime = spi_w(0) | (spi_w(0) << 16);
+ uint32_t vtimeh = spi_w(0) | (spi_w(0) << 16);
+ DisableIO();
+
+ float vrate = 100000000;
+ if (vtime) vrate /= vtime; else vrate = 0;
+ float hrate = 100000;
+ if (htime) hrate /= htime; else hrate = 0;
+
+ float prate = width * 100;
+ prate /= ptime;
+
+ printf("\033[1;33mINFO: Video resolution: %u x %u%s, fHorz = %.1fKHz, fVert = %.1fHz, fPix = %.2fMHz\033[0m\n", width, height, (res & 0x100) ? "i" : "", hrate, vrate, prate);
+ printf("\033[1;33mINFO: Frame time (100MHz counter): VGA = %d, HDMI = %d\033[0m\n", vtime, vtimeh);
+
+ if (vtimeh) api1_5 = 1;
+ if (hasAPI1_5() && cfg.video_info)
+ {
+ static char str[128], res1[16], res2[16];
+ float vrateh = 100000000;
+ if (vtimeh) vrateh /= vtimeh; else vrateh = 0;
+ sprintf(res1, "%dx%d%s", width, height, (res & 0x100) ? "i" : "");
+ sprintf(res2, "%dx%d", v_cur.item[1], v_cur.item[5]);
+ sprintf(str, "%9s %6.2fKHz %4.1fHz\n" \
+ "\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\n" \
+ "%9s %6.2fMHz %4.1fHz",
+ res1, hrate, vrate, res2, v_cur.Fpix, vrateh);
+ Info(str, cfg.video_info * 1000);
+ }
+
+ uint32_t scrh = v_cur.item[5];
+ if (height && scrh)
+ {
+ if (cfg.vscale_border)
+ {
+ uint32_t border = cfg.vscale_border * 2;
+ if ((border + 100) > scrh) border = scrh - 100;
+ scrh -= border;
+ }
+
+ if (cfg.vscale_mode)
+ {
+ uint32_t div = 1 << (cfg.vscale_mode - 1);
+ uint32_t mag = (scrh*div) / height;
+ scrh = (height * mag) / div;
+ }
+
+ if(cfg.vscale_border || cfg.vscale_mode)
+ {
+ printf("*** Set vertical scaling to : %d\n", scrh);
+ spi_uio_cmd16(UIO_SETHEIGHT, scrh);
+ }
+ else
+ {
+ spi_uio_cmd16(UIO_SETHEIGHT, 0);
+ }
+ }
+
+ if (vtime && vtimeh) ret = vtime;
+ }
+ else
+ {
+ DisableIO();
+ }
+
+ minimig_set_adjust(2);
+ return ret;
+}
+
+void video_mode_adjust()
+{
+ uint32_t vtime = show_video_info(0);
+ if (vtime && cfg.vsync_adjust && !is_menu_core())
+ {
+ printf("\033[1;33madjust_video_mode(%u): vsync_adjust=%d", vtime, cfg.vsync_adjust);
+
+ int adjust = 1;
+ vmode_custom_t *v = &v_def;
+ if (vmode_pal || vmode_ntsc)
+ {
+ if (vtime > 1800000)
+ {
+ if (vmode_pal)
+ {
+ printf(", using PAL mode");
+ v = &v_pal;
+ }
+ else
+ {
+ printf(", PAL mode cannot be used. Using predefined NTSC mode");
+ v = &v_ntsc;
+ adjust = 0;
+ }
+ }
+ else
+ {
+ if (vmode_ntsc)
+ {
+ printf(", using NTSC mode");
+ v = &v_ntsc;
+ }
+ else
+ {
+ printf(", NTSC mode cannot be used. Using predefined PAL mode");
+ v = &v_pal;
+ adjust = 0;
+ }
+ }
+ }
+
+ printf(".\033[0m\n");
+
+ double Fpix = 0;
+ if (adjust)
+ {
+ Fpix = 100 * (v->item[1] + v->item[2] + v->item[3] + v->item[4]) * (v->item[5] + v->item[6] + v->item[7] + v->item[8]);
+ Fpix /= vtime;
+ if (Fpix < 2.f || Fpix > 300.f)
+ {
+ printf("Estimated Fpix(%.4f MHz) is outside supported range. Canceling auto-adjust.\n", Fpix);
+ Fpix = 0;
+ }
+ }
+
+ set_video(v, Fpix);
+ user_io_send_buttons(1);
+ usleep(100000);
+ show_video_info(1);
+ }
+}
+
+int hasAPI1_5()
+{
+ return api1_5;
+}
diff --git a/video.h b/video.h
new file mode 100644
index 0000000..2808dc0
--- /dev/null
+++ b/video.h
@@ -0,0 +1,14 @@
+#ifndef VIDEO_H
+#define VIDEO_H
+
+int video_get_scaler_flt();
+void video_set_scaler_flt(int n);
+char* video_get_scaler_coeff();
+void video_set_scaler_coeff(char *name);
+
+void video_mode_load();
+void video_mode_adjust();
+
+int hasAPI1_5();
+
+#endif // VIDEO_H