A nostalgic HDMI display driver [0.90 beta in post #34 - beta stage reached]
0.90 beta available in post #34
0.07 alpha in post #32. 6 different modes at different CPU speed (280,320,360 MHz), it sets the clock automatically after selecting the mode, LUT usage changed to save CPU cycles in the main loop
0.06 alpha in post #31. Color model changed from rgb to 8-bit palette, code cleanup done.
0.05 alpha in post #26. Cursor and ntsc-type mode with narrow borders.
0.04 alpha in post 21. Vblank functions added, color buffer bug fixed.
Edit: (20210224): 0.03 alpha. Now every characters has its own colors, 6000 longs wasted for a color buffer. The file added to post #20
Edit (20210223): 0.02 alpha ready for testing.
So... I want to have a lot of nostalgic things out of P2, but the first I want is a retro player. The SIDCog and a mod player is ready, but I need a display driver. A 50 Hz one.
So the goal was to convert "nostalgic VGA" used in PropPlay to a new environment
I decided to use PAL Atari/Amiga related CPU frequency. This will allow to write Paula and Pokey emulators at their real speed. I also decided to use PAL related 576 line resolution and Atari 8-bit refresh rate.
To make 9:16 resolution I had to use 1024 pixels horizontal.
The result is very tight blanking, but then I hope most modern monitors should handle it. I made a test topic here
So what I got is a HDMI 100x30 text driver with border, signalling 1024x576@49.86 Hz using 1 cog and P2 clocked at PAL Amigax45=319_220_550
As there is time to go to sleep, I post the first screen... and no code yet. To be continued tomorrow. TODO is to service LUT entries to get one set of colors for every 4 letter field and attach a bunch of spin methods to use the driver - converted from P1 Nostalgic VGA driver
Comments
As I left the code at home, I tried to write the graphics driver, which is much simpler. The only problem is RAM it needs. This thing displays 16-color graphics @ 1024x576 and eats 288 KB of RAM for its framebuffer.
Yeah external memory is the go for resolutions like that. You should be able to get truecolour with HyperRAM at that original resolution @319MHz with sysclk/2 speed transfers (159MB/s transfer rate and you need around 4kB per scan line every 36us or 113MB/s). When I fire up my HyperRAM again soon I'll try that clock rate with my video driver and see if it can be done. There won't be a lot of spare bandwidth for writes though, and sysclk/1 is just a bit too much at 319MHz. It tops out around 305-310MHz IIRC.
I don't have a hyperram board: I forgot to order it with the eval board... Delivery time was over 2 months so... maybe it will be faster to order a board from a local manufacturer, then solder these chips.
4 layers and BGA
Another solution is what I want to write after learning basics: displaylisted video driver, so you can choose where, from where, and how detailed the graphics may be. The empty backround will take only several bytes. I think I have the basic stuff learned although I didn't try interrupts and events which can be useful for doing such a driver
Yeah exactly pik33, a display list is the way to go. My own P2 video driver uses a display list of independent regions which can be a mix of text and graphics in any colour mode. It is really flexible when done that way and you can have different COGs putting data into different screen regions read from different areas of memory with no chances of data collisions with multiple writers etc. Some displayed regions can be sourcing their data from external memory, some from internal memory. Check it out when you get a chance if you are interested in this sort of stuff. The original driverdoc.txt file documentation in the earlier released driver code covers the registers that control it all and shows what it can do but I'm working on more documentation.
By the way not sure if you've been lurking in the P2 forums or not but there's a lot of ideas, tests and issues we discussed in these older threads if you are not yet familiar with them. It might assist getting up to speed with what is possible on the P2 with the streamer. There are other threads too, but I know these ones I started:
https://forums.parallax.com/discussion/170601/all-pasm2-gurus-help-optimizing-a-text-driver-over-dvi/p1
https://forums.parallax.com/discussion/170676/p2-dvi-vga-driver/p1
https://forums.parallax.com/discussion/171176/hyperram-driver-for-p2/p1
The HyperRAM device is a fairly cheap part but it is a little hard to build yourself being BGA based with a fine pitch. You can have a lot of fun with the Parallax board if you can get your hands on it and the included 32MB HyperFlash part is a very fast memory too for resource storage (eg, large midi sample wavetables for audio synthesis etc).
We have a Mouser here, but these boards are not in their product list. Good news is they got the P2 Edge so I can at last buy them without months of waiting and then having problems with customs office.
I have a RPi Zero, which can work as a memory module for P2, but I don't expect more than 40 MBps using 8 pins for data transfer. I need some time to experiments. I am still learning this strange beast which is P2, but I already feel at home with this chip: it has (near) all I want
I have also 3 P2 chips and maybe it may be a good idea to make a board for all 3, making one of them a dedicated "video card", another one a MIDI synth, then the third should rule them all. Put all of this in retrocomputer type case. This is the project for (unknown) future,.
Well the faster SMI mode of the RPi could be tried too, check this out:
https://iosoft.blog/2020/07/16/raspberry-pi-smi/
Parallax's 16MB HyperRAM board can be clocked up to ~150MBytes/s or 300MB/s when overclocked. This supports video rate transfers, so you might try to get one once you can (or build a board with the part fitted, a driver is already available). Peter Jakacki 's P2D2 board with its P2PAL is another option to consider once it is available to you in EU (not sure when), as that also supports HyperRAM and will hopefully be low cost. Some future P2 Edge should get a high speed memory option too.
That sounds great too. I feel the P2 would be fabulous as a midi synth. There's a lot of processing power and internal bandwidth between all the COGs to do all sorts of things with lots of channels and it can rapidly shuffle bulk data around in a processing pipeline. Each COG gets over 1GByte/s of sustained memory bandwidth to play with, it's insane!
And this is in a 180nm process. If we could build the P2 in a leading-edge process, we could get 10 times the bandwidth and speed.
Hi @pik33
I have modified your code above to use my video driver with the custom timings you used for your 1024x576 to see it that was supported and so you can see how to use my code. I wasn't sure what sync polarity you used so I just picked negative for both syncs but it worked with other values as well. I see it working nicely on my own setup here (minus the font resource which I don't have). I did need to slightly change the allotment of vertical blanking lines between the porches and sync because my driver is limited to 7 vertical sync lines maximum. It's still 20 total vertical blanking lines so the frame frequency is the same.
You just need to grab my p2videodrv.spin2 from the latest zipfile I posted in my VGA/DVI text driver thread.
Here's your own SPIN2 sample code with the minor mods I made and with your PASM driver replaced:
Here is the font. It is 8x16, 128 chars font, defined byte by byte, from top to bottom.
I tried fontvga16 from the driver instead, but the definitions are different: a garbage displayed on the screen instrad of ABC. How to use these fonts?
The program compiled and works. The driver is.... complex....
My fonts are just in a different format to yours. The index to read the 8 bit pixel row data for each character's scan line data is this:
index = character + (scanline<<8)
and then the byte data is read from the table
data = fontdata[index]
That encoding allows for arbitrary height fonts and a 256 character set.
Yeah the driver is very complicated and packed in, it has many different features. It is not really a driver to read through to learn how to write a video driver. It is a driver that can be just used in multiple applications (though I still need to better document how to do that...).
After some fighting with timings (calculators didn't work well there, I managed to got (using my own test code) 2560x1440/60 Hz on a VGA output (as I have a 2560x1440 monitor) using timings:
_clkfreq=250_000_000
Horizontal: 2560-32-48-128
Vertical: 1440-6-10-45
The test code as it is now displays a color bacgkround and nothing else, a full framebuffer for this needs at least 460800 bytes (monochrome). As I am still thinking of a displaylist, this can be of course worked around. The next step is to check if the picture can be sharp and stable at these frequencies on the analog output.
Edit: nothing good the monitor detects 1920x1440. All 2560x1440 "official" timings I could find don't work (black screen) with this monitor. Either 2560x1440 is impossible via VGA on it, or it needs weird timings. The best test I can do is to connedt it to a PC via D-Sub and check it out.
This is a test code:
Did you try the 4 different polarity combinations?
Not yet. Then I read 2048 is the limit. I pulled out the timings from the monitor EDID: they didn't work.
Yeah I've not seen any monitor yet that does more than 2048x1536 with analog VGA, but maybe something specialized is out there that can.
fwiw we couldnt get 2560x1440 working in vga on philips 288p6 either
HDMI nostalgic driver v.0.02 is now ready.
200x Atari PAL 8bit CPU speed, 1x Atari PAL refresh rate, signalling 624 lines, displaying 576.
This is not 100% conversion from P1 VGA driver. The differences are:
A starting point to recreate PropPlay done.
Nice job pik33. Your demo fully works on my Dell monitor and looks clean and colourful.
Are you able to allow it to set an independent foreground and background colour per character? Running at 354MHz the P2 should have a lot of cycles per scan line. Or was this only done because that particular 4 character colour system is more compatible with some existing Atari platform and you want to save HUB RAM (eg. 100x30x2 longs = 24000 extra bytes)? I'm unfamiliar with the Atari ST/PAL family text capabilities.
This 4-color system was used in a P1 player Propplay - https://forums.parallax.com/discussion/140767/a-new-topic-for-vga-not-only-sid-player - which I want to conver to P2 as an initial learning task.
These frequencies are common for Atari 8 bit and Amiga, which works 4xfaster, all of these frequencies derived from color carrier frequency. For NTSC machines it was 3.579545 MHz.
Atari 8-bit 6502 CPU has 114 CPU cycles per scan line. The Propeller2 using this driver has 11400 cycles per scan line.
Atari 8-bit has much less text/graphics capabilities. It can display up to 384 (normally 320) pixels per scan line, and this gives 40 characters
I thought about adding a color for every character displayed and of course I will try this. To avoid too many longs wasted, a palette can be loaded into LUT RAM and then the color buffer will be 1500 longs.
In this kind of code the cycles available for decoding don't depend on CPU speed as it is always 10 cycles per pixel.
There was no problem to make every character to have individual color I forgot P2 uses 2, not 4, cycles for one instruction, so 40 instructions are available between xconts.
Now the character buffer is 3000 bytes and color buffer is 6000 longs... Seems to be an overkill... but then I can add font redefining function which can be copied from P1 version and all kind of color semigraphics is available in this mode.
0.03 added
0.04
A color buffer bug fixed. The streamer is a strange thing: I don't understand it fully but it seems it accepts the command (xcont) but then it doesn't catch the parameters together with the command. The parameters seems to be catched when command starts to be executed (?) . So it seems you have (1) use xcont (2) prepare its parameters, or else it will use the next ones, moving all colors 1 character left.
Although I don't understand it fully, the 0.04 version seems to display colors as expected.
I also added a vblank waiting functions so everything can be sychronized with vblanks (a module player?)
I bet it's the command buffering throwing your perception of the timings. When the XCONT instruction unblocks and you program continues executing is when that command has been placed in the buffer - to be the next command used. The prior issued command is the one only just starting then - as the currently actioning command.
The currently actioning command has its own period of activity where by live hubRAM data can be manipulated, by any cog, as it's being fetched by the streamer. When that time period actually is can be a little confusing when factoring in the command buffering.
While there were no problems if the P2 was connected directly to the monitor, there were stability problem when the P2 was connected to a HDMI switch, and the quality (or rather the "disappearing frequency") depended on a HDMI cable (better cable=less dropouts).
I changed this
to this
which solved the switch stability problem
Full logic drive exceeds the HDMI specs. Have you tried this one?
wrpin ##%10110_1111_0111_10_00000_0, a '123 ohm BITDAC for pins
This seems to work with this switch.
0.05 with alternative font zipped with it (MS DOS VGA type)
Added:
The result in mode 256 looks like this - with a SD card playground (poor picture quality, using a cheap 15" TV as a HDMI monitor)
Got it working, full text colours now looks good. The 354MHz operation is pushing the P2 hard but it's managing ok with the two COGs and is not even warm. How well it goes when all the other COGs are running flat out as well is gonna be interesting. It'll certainly need more current then.
By the way to avoid this warning below, just add the 0-0 format so the compiler doesn't get confused that you are doing the wrong thing.
For this narrow border 60 Hz mode the cpu clock can be much lower. This "256" mode displays 816 visible pixels and 1140 (10x Atari CPU clocks per display line) total, 912 total pixels should be enough and this gives something like 290 MHz - to be tested in the next version. I want to do an 8-bit Atari emulator, so I keep these numbers Atari compatible. It displays 624/524 line screen with 114 CPU cycles per line, so total lines has to be 524 or 624 and total pixel count has to be n*114.
Great progress pik33...
I would really like to see a full Atari 8 bit system running on the P2, that would be really cool. The Pokey should be quite easy to emulate I think. The 6502 can be a little bit tricky if you try to implement all illegal opcodes as well; Some of them are not even fully understood if I remember correctly. But all "normal" opcodes are very easy to emulate and just took me a "day" to implement in my SID dump tool that I made for SIDcog on the P1.
I may even do a 6502 emulator myself, to get some real RSID's running on the P2. Then I could finally get 4 bit volume register samples to work.
I have a 6502 emulator on RPi, with illegal opcodes, too, for... playing SIDs in my own bare metal player (a winamp clone). There is also 8080 emulator available on P2 uxing XBYTE to do its job, so I will start from this - 6502 asm can be treated as a bytecode.
This is the project (a big mess of test code...) https://github.com/pik33/ultibo_retro_gui
0.06. Now with palette: no more 6k longs for the color buffer. To do: add functions for defining colors in the palette and characters in the font
The 256 colors palette resides in the upper half of the LUT. It seems to be possible to move it to the lower half, saving 4 cycles in the main loop: to do
The driver starts to be usable now.
Available methods:
pub cursoron() - switch the cursor on
pub cursoroff() - switch the cursor off
pub setcursorpos(x,y) - set the (x,y) position of cursor
pub setcursorshape(shape) - define a cursor shape (0-full..15-line)
pub waitvbl(amount) - wait for start of vblank. Amount=delay in frames
pub waitvblend(amount) - wait for end of vblank. Amount=delay in frames
pub setscreencolors(ff,bb) - set foreground and background colors for all screen - from a 256 colors palette
pub setbordercolors(r,g,b) - set border color for all the border using rgb
pub setfontcolor(x,y,c) - set the character color at line (0..29) and position (0..99)
pub setbackcolor(x,y,c) - set the background color at line (0..29) and position (0..99)
pub setbordercolor(line,r,g,b) - set the border color at line 0..31, 0 is upper border, 31 is lower border, add #1 to the text line# to get a border line#
pub setwritecolors(ff,bb) - set colors for write and writeln
pub outtextxy(x,y,text) - output a string at position x,y - set the colors first
pub write(text) - output a string at the cursor position x,y, move the cursor
pub writeln(text) - output a string at the cursor position x,y, move the cursor to the next line
pub cls(fc,bc) - clear the screen, set its foreground/background color
pub scrollup() - scroll the screen one line up
pub scrolldown() - scroll the screen one line down
pub inttostr(i) - convert a integer to dec string, return a pointer
pub inttohex(i,d) - convert a integer to hex string with d digits, return a pointer
pub start(mode) - start the driver, mode=0 - start at PAL timings, 624 lines, mode=256 - start at NTSC timings, 524 lines, return a cog#