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


  1. i am glad to see that 1080p will be supported too! while i have a 1200p monitor, i think 1080p is more like a standard. and i think it should be possible by scaling 1 pixel less in y-direction than in x-direction, and it looks a bit like this is what you are doing, could that be?

    1. Hello,
      Yes -- in 1200p C64 pixels are 5 high, so that 200x5=1000 pixels of the 1200 vertical pixels in the frame. In 1080p, I have yet to decide if it will be the same vertical exageration, or 4x for 800 of the 1080 vertical pixels.

      I'm just finishing off a few bits and pieces on this, and then I hope we will release a bitstream soon for our supporters to try out, and let us know which video modes work on their monitors (I have double-tap of RESTORE wired to cycle through the modes).


    2. Would you be able to do 1600x1200? I assume yes, since the amount of pixels is almost the same as 1920x1080, so with some tuning of the timing parameters it should fit within a 150MHz pixel clock.

      For me 1600x1200 would be the ideal situation: I have 1600x1200 LCD monitors and using a computer with 4:3 picture on a 16:9 screen will always be ugly in one way or another.

    3. One limitation we have is that our pixel clock is fixed at 150MHz. There is no 1600x1200 mode I can see that has a close pixel clock. There is 1600x1050 @ 60Hz with 147MHz, which is probably close enough to work, however, that would only be useful for NTSC timing, as you would have 60 FPS, not 50 FPS. When the new bitstream comes out, I will do a blog post on how to try different modes yourself, and we can start collecting feedback from folks as to which modes work. Of course, usingg any non-standard mode will mean that some new software may potentially not work, due to incorrect raster timings.


    4. Well, you need to tweak the hsync and vsync times to get exactly to 150 MHz. I have been playing a bit with the website http://xtiming.sourceforge.net and got this mode line for a 1600x1200 @ 50 Hz. No idea how (and if) this would translate to the VIC4 CRT controller.

      Modeline "1600x1200@50" 149.77 1600 1632 2336 2368 1200 1224 1237 1261

      Now being able to generate a modeline does mean the monitor will accept it (especially a problem with CRTs, less with LCDs). A quick test did on my Linux desktop shows my 1600x1200 monitor accepts it, but this is no guarantee for the general case. However, I have increased the sync times, this is less risky than decreasing them from the defaults.

    5. Hello,

      Yes, it should presumably work, although I am not sure how HDMI TVs handle custom modes. If you have a monitor that accepts that mode, and a nexys4 board, poke me an email and I will send you a bitstream you can use to test it.


  2. yes i understand, the borders are the problem. especially since there are games and demos which display graphics on the borders. of course another idea would be to leave this decision to the user, and offer multiple "zoom" modes to be selected. on the other hand, this might lead to people not being sure what is the "standard mode" and making developers unsure about how exactly their graphics will look like on other people's setups. on the other hand, there are already people today who use their C64s with different aspect ratios and zoom modes on their TV, different from what would be the "standard mode", so maybe this is not such a big issue after all (as compared to other stuff like PAL/NTSC, breadbin VIC/modern VIC, etc).

    1. Exactly. I hope to reduce it to just 1080p 50Hz PAL and 60Hz NTSC, so that it is as simple as on a C64, and we don't have fragmented video mode problems.