Tuesday, August 1, 2017

Getting 1080p 50Hz working ... using a video mode editor written in BASIC v2

One of the joys of the MEGA65 project is that it is all about doing something that is not grounded in conventional measures of wisdom or practice -- at least none invented since the 1980s.

One of the TODO items for a while now has been to get 1080p at 50Hz (for PAL) and 60Hz (for NTSC) video modes working, ready for the move to HDMI on the new MEGA65 mother board.

This has been a bit of a drawn out process, partly because of everything else I have going on, and partly because I didn't have the tools to quickly and easily test and move forward.  That latter problem has now been substantially improved on several fronts:

1. The monitor_load program makes it easy to try a new bitstream and/or Hypervisor ROM on the MEGA65, without having to fiddle about with SD cards.

2. I now have a native Linux machine, so that I don't have to muck about with transferring bitstreams and source back and forth in and out of a virtual machine on my mac.  It also means that synthesis is a bit faster, without the overhead of the virtual machine.

Together, those two things, while not particularly ground shaking, have made a huge difference to what I can achieve in the little puddles of time I have.

The next step today was to implement a monitor_save program, that lets me save whatever is loaded in C64 mode, even if the program is running. This isn't a freeze function, but rather just saving BASIC program memory.  This makes it easy to work on a BASIC program on the MEGA65, saving it as I go along.

So now I had the means to save and load a program from my Linux box from and onto the MEGA65 in a second or two, as well as build and try out new bitstreams quickly, thus allowing me to do even more in the limited time available to me.

Back to 1080p video modes, I have worked over the past week to make VIC-IV registers at $D072-$D07C that allow complete control over the VGA video signal generation, so that I could try out various mode lines, with a view to generating the 1080p modes.

I also found out by accident that one of the VGA monitors at work is totally happy to do very low frame rates, down to and below 50Hz.

Now I was set, I had the tools to allow me to write a simple program to try out and modify video parameters on the MEGA65, to tweak them for proper video image placement and timing.

One of the joys of the C64, is that it contains a powerful and simple programming language out of the box, i.e., BASIC. While BASIC v2 is a bit minimal, it is totally functional, so I started hacking away on an interactive video mode line explorer.

Within an hour or so, I had not only a functional video mode editor, but had also worked out the correct parameters for 1080p 50Hz,  1080p 60Hz, and 1200p 60Hz, all using a fixed 150MHz pixel clock.  Here are some screen shots of my program in the various modes, and as I was testing them on the monitor:

First we have 1080p @ 60Hz. The BASIC program calculates a rough estimate of the horizontal and vertical frequencies of the mode. The letters and numbers in  brackets let you adjust the value to the left by -10, -1, +1 and +10 respectively.  If you look carefully you can see the bit of letter-boxing, because this monitor is actually nativelly 1200p.

Then a ~50Hz mode as I was trying to figure out a good 50Hz mode, and checking what the monitor thought of the mode.  This monitor, while nice for such funny modes, is a pain to get it to show the current mode. You have to navigate through quite a few menus to see the current mode info.

 And 1920x1200 @ 60-ish Hz.

In that mode in particular we can see that the scaling of the video imag is not correct within the borders. This is one of the next things on the list to fix.  It isn't hard, as the VIC-IV already has the necessary scaling registers.

Meanwhile, for the curious, here is the BASIC listing of the program I wrote to let me tweak and fiddle with the video modes, as output using petcat -2

   10 k=53295
   20 pokek,asc("g")
   30 pokek,asc("s")
   40 poke0,65
   50 r0=53248+7*16+2
   60 poke650,128
   70 poke53280,6:poke53281,11
  100 rem default mode values
  110 ss=2290:se=100
  120 fh=1072:dh=1056
  130 fw=2432:dw=1920
  140 fp=128
 1000 printchr$(147);"{wht}mega65 video mode editor"
 1010 print
 1020 print"hsync start=";ss;"  (a,s,d,f)"
 1030 print"hsync end=";se;"  (q,w,e,r)"
 1040 print"front porch=";fp;"  (z,x,c,v)"
 1050 print"frame width=";fw;"  (t,y,u,i)"
 1060 print"display width=";dw;"  (g,h,j,k)"
 1070 print"frame height=";fh;"  (1,2,3,4)"
 1080 print"display height=";dh;"  (5,6,7,8)"
 1900 print"hfreq = ";150000/fw;"khz"
 1910 print"vfreq = ";150000000/fw/fh;"hz"
 2000 poker0+1,se/256
 2010 poker0+2,seand255
 2020 poker0+10,ss/256
 2030 poker0+9,ssand255
 2040 poker0+0,fp
 2050 poker0+3,dwand255
 2060 poker0+4,fwand255
 2070 poker0+5,int(dw/256)+16*int(fw/256)
 2080 poker0+6,dhand255
 2090 poker0+7,fhand255
 2100 poker0+8,int(dh/256)+16*int(fh/256)
 3000 geta$:ifa$=""goto3000
 3005 printa$
 3010 ifa$="q"thense=se-10
 3020 ifa$="w"thense=se-1
 3030 ifa$="e"thense=se+1
 3040 ifa$="r"thense=se+10
 3050 ifa$="a"thenss=ss-10
 3060 ifa$="s"thenss=ss-1
 3070 ifa$="d"thenss=ss+1
 3080 ifa$="f"thenss=ss+10
 3090 ifa$="z"thenfp=fp-10
 3100 ifa$="x"thenfp=fp-1
 3110 ifa$="c"thenfp=fp+1
 3120 ifa$="v"thenfp=fp+10
 3130 ifa$="t"thenfw=fw-10
 3140 ifa$="y"thenfw=fw-1
 3150 ifa$="u"thenfw=fw+1
 3160 ifa$="i"thenfw=fw+10
 3170 ifa$="1"thenfh=fh-10
 3180 ifa$="2"thenfh=fh-1
 3190 ifa$="3"thenfh=fh+1
 3200 ifa$="4"thenfh=fh+10
 3210 ifa$="5"thendh=dh-10
 3220 ifa$="6"thendh=dh-1
 3230 ifa$="7"thendh=dh+1
 3240 ifa$="8"thendh=dh+10
 3500 ifss<0thenss=2999
 3510 ifse<0thense=2999
 3520 iffp<0thenfp=255
 3530 iffw<dwthenfp=dw+1000
 3540 ifdw<640thendw=1920
 3800 ifss>2999thenss=0
 3810 ifse>2999thense=0
 3820 iffp>255 thenfp=0
 3830 iffw>3000thenfw=dw+50
 3840 ifdw>1920thendw=640
 3850 iffw<ssthenss=fw-10
 3860 iffh<480thenfh=1500
 3870 ifdh<480thendh=fh-10
 3880 iffh<dhthenfh=dh+2
 3890 ifdh>1300thendh=480
 3900 iffh>1300thenfh=480
 4000 goto1000