feilipu / ux_module

User Experience Module - RC2014
MIT License
11 stars 1 forks source link

Graphics Support via VJET #1

Open feilipu opened 3 years ago

feilipu commented 3 years ago

Opening a thread on VJET graphics support for @Wuerfel21.

feilipu commented 3 years ago

You mean the VJET polygon drawing stuff? Yes, it is quite similar in concept to the FTDI EVE hardware, just significantly less powerful - with the 4 rasterizer cogs @80MHz I usually use, that is. 117 MHz is a good bit faster and you may be able to use 5 or 6 cogs. Also, the display list doesn't contain triangles/lines/polygons per se, it contains "trapezoid stacks", essentially a representation of a y-monotonous polygon as set of trapezoids defined by height and left/right slope. If you've ever written a triangle/poly fill algorithm, you probably understand what I mean. There's some computation involved in generating these from a polygon (triangles as a special case are quite simple though).

I don't think the cog budget will stretch so far. Cog 0 for Spin, 1 for ACIA Z80, 1 for Tx/Rx serial, 1 for keyboard, 2 for VGA. I make only 2 cogs spare for rendering. Hmm. Still might be enough to get something.

I've kept 3 base addresses free in the UX Module design. 0x80 is for the ACIA emulation so it will work with the standard RC2014 software. Another is to separate the serial Tx/Rx onto another "TTY" port.

The final base address is to build a graphics device. It might be TMS9918 like, or better I'd prefer it to be based on VJET like solution. Ideally it would work to the same VGA memory as the HiRes VGA driver. A bit like a graphic overlay.

Running both hires text and any sort of graphics at the same time is just not going to happen. However, if you're OK with switching between highres text and lowres text + graphics, it'll work out. One cog is needed to drive the VGA from line buffers, leaving 3 render cogs. 3 might be ok at 108 MHz, but 4 is really the sweet spot. If we can get rid of that pesky keyboard cog that spends of it's time doing absolutely nothing, that'd be 4 render cogs. Just need to find some other place to stuff the PS/2 bitbanging and then the scancode conversion and stuff can be just be done in Spin.

Anyways, the terminal emulation can be incorporated into the graphics rendering by simply placing some text commands into the display list that point into the terminal buffer. Can be an overlay or an underlay depending on where the commands are inserted. However, the code handling the terminal buffer will need to be adjusted for smaller screen size. VJET as-is runs in 256x238 with non-square pixels. Could be bumped to 256x240 (The reason it's 238 is because I couldn't get my code to do 240 lines and it literally makes zero difference on TV due to overscan, so I didn't bother fixing it) If we assume most of that isn't overscanned, you can reasonably get 40x28 characters (each character being 6x8, TMS9918 style). (However, I think to actually render a screen full of text, it will need 4 render cogs.) Also, it'd really help if the terminal emulation would automagically zero-terminate each line of display memory instead of just having spaces till the end.

I'm actually more inclined to close the serial interface cog (at least when development is done) as a preference, as the keyboard needs to be "fast" (in its own cog?) to allow gaming control.

And, absolutely no problem to make the video modal (lowres text + graphics) and highres.

I'm going to focus on getting the highres text working, as that's just a matter of matching terminal emulation codes and keyboard scanning. This part is critical for CP/M and general usage. The graphics part is a "stretch"

I'd like to have a command processor, so that the nice GL language can exist. It might be useful without the Z80 bus interface for other people too, so I wouldn't want the Z80 to know too much.

The EVE hardware has 32bit GL commands which are executed out of an on chip buffer. The command buffer is rendered line by line for display. I'm not sure but, I'm imagining a cog rendering a slice of the screen out of a Hub memory GL command list, and then displaying it. With 4 cogs sharing the render / display it would be real dance. It looks like the VJET geometry processing code is quite similar in function.

Yeah, it is like that a bit, the main difference is that the high-level commands have to be pre-chewed by the geometry code. The display list also has space for temp values in it used to stregnth-reduce some multiplications out of the rendering cogs.

Adding some macro commands to draw common GUI elements is definitely very easy to do.

Other thing is: What is filling the display list? Letting the Z80 write it directly would not only be quite slow, but would also require the Z80 code to know about hub RAM layout (and if it messed up, the render cogs will spill their temp values all over and cause a really bad time). So instead it probably should be a command interface. If the bus interface code can just dump whatever data arrives at its port to the Spin code, that could handle generating the display list from commands, similar to the spin interface existing VJET geometry processing code.

Problem with that is that normal spin is kinda slow at doing that. Flexspin compiles to LMM assembler and is a lot faster, but it'll make your code size explode and as such requires careful optimization to fit everything. Also when you use it, you'll find and report a bug every 2 days, it's inevitable :) I also do think that the geometry code (especially the polygon function) could be optimized more. Or if flexspin is used, anyways, custom inline ASM could also help.

Yeah closing the serial interface also works (you could even make it an option to leave it running at the expense of reduced rendering cogs) and is very much the easier option. However, do know that moving the keyboard handling somewhere else would not make it measurably slower - the reason it generally is handled in it's own cog is because the keyboard controls the data transfer speed and thus the the pins have to be monitored constantly. Compare to something like a SNES controller, where the speed is controlled entirely by the host - that is generally read once per frame in a simple spin routine.

feilipu commented 3 years ago

I have put up a video of a "first draft" for the HiRes Text mode. Excuse the slow Basic programming. I had a Basic language WTF moment.

User Experience Module for RC2014

The UX Module has a major port (0x40, 0x80, 0xC0), and a minor port at one higher. I'm thinking the Major port can be a 8bit Command/Status port (like the ACIA), and the Minor port can be for 4x 8bit data.

It would be easy to write Z80 assembly to upload 32-bit longs in LSB->MSB order from the Z80 to Parallax. If the Display Commands were assumed always 32bit, then parsing the command data would become simpler too.

And, If I can dig into the EVE DL Commands a bit more then it might even be possible to replicate them (to some extent).

More when the next PCB is available.

feilipu commented 3 years ago

I'm still unhappy with the Z80 bus interface solution. Works with a small MS Basic (classic) configuration, but is unreliable with larger configurations.

I've ordered some 200pf capacitors, and digital (pre biased) transistors to experiment some more. EDIT Changed to 200pf capacitors, but still need to check the waveforms. Still need to get the capacitance off the /WAIT line for the APU Module.

I'm suspicious of the data bus being too slow, because unreliable behaviour seems to be bit flipping (or not settling) on the bus. EDIT Just added one nop to the Propeller transmit, to allow the bus more time to settle. Seems to cure the issue.

I'm also working on VT100 codes. Anna has collected VT100 games that I'll be "forced" to play for testing.

feilipu commented 3 years ago

I went down the path of turning the ACIA interface into an object that could be replicated in multiple cogs, and then spent some time trying to understand why it didn't work. Long story short, there is only one /WAIT line that is ORed, so an individual instance of ACIA could never pull a shared /WAIT low.

So, lesson is there's no point trying to build multiple simultaneous interfaces to the Z80. Either the ACIA emulation is running, or the VJET interface is running, but not both. A modal state switch is required with keyboard, serial, and Z80 interface inputs.

That gives much more flexibility on cogs budget.

I couldn't find a VJET with VGA interface. This OBEX VGA64 driver looks imho the closest, so I've put it in as a template.

Probably the first step to achieve is to draw a polygon on VGA, without worrying about Z80 interfacing.

Wuerfel21 commented 3 years ago

Oh yes indeed, there's no VGA output driver yet. The composite one was basically borrowed from regular JET and then filed down, but the VGA one is such spaghetti (due to having to support horizontal scrolling) that I wouldn't want to use it for VJET.

Can the graphics ports not be handled by the ACIA cog, too?

feilipu commented 3 years ago

Yes, certainly the Z80 interface can be handled by one cog with no issue. I was previously hoping that I could just clone instances of ACIA code, to make debugging easy. Leider nicht.

So my job will be to write a new Z80 interface that looks like an ACIA on one set of ports, and has additional features on the other ports. It can only run in one cog because of the /WAIT control factor, but that won't be a problem, I'm sure.

The way the UX Module hardware is set up, there are only two ports 0xC0 and 0xC1 that can be used by the VJET interface.

If I take the example of the SIO/2 interface, then the port 0 is used partly as a register write pointer (3 bits) and write control bits, and read status port. The port 1 is then the data input and output port, and loads the register set by the write pointer control. There are 7 registers (from memory). For the VJET interface, we could also read additional status bits from port 1 because there's no input to the Z80 per se.

So ideally, the interface would auto-increment to load polygons or pixels, or whatever needed, once set up with a x,y pixel origin. But I'm not sure what is needed, so just guessing now.

Wuerfel21 commented 3 years ago

Also just noticed that the VJET files need to be ASCII'd, oof.

Eitherhow, will probably get the VGA backend going soon™. Right now I've got a shiny new P2 on my desk, so I'll toy with that for today. First order of business will be getting VJET going on that (Spin Hexagon on P2...), so It'll be fresh in my mind when doing the P1 VGA

Wuerfel21 commented 3 years ago

Okay, am ready to make the VGA backend now. Should be done, like, tomorrow or the day after, hopefully

Wuerfel21 commented 3 years ago

(Actually, wait no, I have something else to do in the weekend)

Wuerfel21 commented 3 years ago

Well, I started messing with it and just remembered that 256px wide 8bpp VGA always needs that hub sync at 80MHz (forcing 20MHz pixel clock). UX Module runs at much higher clock so no sync may be fine? If not I fear the picture will have to be squished a bit. Will certainly have to develop on the module itself, which diminishes the usefulness in more general circumstances, but VGA on P1 sucks, anyways, so no big loss.

feilipu commented 3 years ago

The existing text mode VGA seems to work ok with odd 7.3MHz multiples. I've had to tweak timing things a little, but irrelevant really.

At the moment occupied fighting bit rot. Always on interface z180<~>Am9511A, who are not friends. Old binary works. New binary doesn't. Disassemble and line by line comparison produces no result, except self pity. 😖

Wuerfel21 commented 3 years ago

Haven't really looked into what the text driver does. In theory this is actually really simple, just have to pump RDLONGs into WAITVID, but the bandwidth is so high.

Old binary works. New binary doesn't. Disassemble and line by line comparison produces no result, except self pity.

I assume you don't have a working version in git? Because this sort of thing is where the git bisect tool really shines

feilipu commented 3 years ago

I have a gist which I think matches. And a running old binary. And yet, I just can't recreate it working, and that is infuriating.

Wuerfel21 commented 3 years ago

The relevant PASM blobs are identical, yet one binary doesn't work?

Have you thought about what gets loaded into RES'd / unused cog ram? That's usually a source of tricky problems.

Wuerfel21 commented 3 years ago

Also, speaking of that text mode timing, have I ever mentioned that I can not get the clock/phase to line up on my particular monitor? Would be easier to get a grip on though if there was a way to fill the screen with a checkerboard

Wuerfel21 commented 3 years ago

And yep, 256 wide 8bpp works fine at the UX module clock speed without funky code ux_256widetest.zip

feilipu commented 3 years ago

The only thing(s) I touched in the hires text mode was the divisor which in the Obex was hard coded to "5". I changed it to "7" nominally even though it is really 7.3.

I also found the front / back porch pixels needed to be tuned from the documented values, but that is probably more monitor / adaptor related.

Also, speaking of that text mode timing, have I ever mentioned that I can not get the clock/phase to line up on my particular monitor?

If you've the interest to play Hexagon on your "big TV" (or where you can't take your own VGA monitor), I am recommending the Vention VGA->HDMI adaptor. It seems to be really good at swallowing random frame rates and producing a stable picture. I only see some bit crawl at edge cases, but otherwise very solid video no matter what you send it. And it is cheap.

Wuerfel21 commented 3 years ago

The "big TV" I usually speak of is a big ol' Phillips CRT. Multistandard, RGB and Svideo inputs, beautiful picture. Infact, I don't think I myself have any HDMI displays. I rarely buy new stuff when random old guff from The Stash™ does the job.

Do these HDMI adapters have any way of adjusting them? I can't imagine the quality being very good without being able to tweak the digitization parameters.

Eitherhow, the mode that's uncommented in there is 640x480, whereas whatever firmware I have on right now runs 1024x768. Maybe I can line up the sampling with that. On the other hand, it'll never be as sharp (my monitor is a native 1024x768 panel)

feilipu commented 3 years ago

The "big TV" I usually speak of is a big ol' Phillips CRT. Multistandard, RGB and Svideo inputs, beautiful picture.

I used to have a Sony Trinitron, quite similar. But afraid it went out on the street. :disappointed: Still have the turntable it used to sit on, tho. Box was about 50kg from memory.

Do these HDMI adapters have any way of adjusting them?

No they're very much "plug'n'play". But they work at all the settings I've pushed in, including all of the random frame rates that I've come up with. The chip described on their web site is MacroSilicon MS9282.

Eitherhow, the mode that's uncommented in there is 640x480, whereas whatever firmware I have on right now runs 1024x768.

I was playing with different resolutions. The retro-brains-trust seem to like the display having 80 columns, so I set 80x40 as the default. Also it syncs at 85Hz which should look extra nice on a real VGA screen.

The latest git clone should work, if you want to flash it. If it doesn't work, then there's an issue I should fix.

feilipu commented 3 years ago

One thing that still annoys me though is the screen flash that happens during booting the RC2014. It is almost like the Propeller is freezing for a moment.

But actually everything is happening on the RC2014 side. The UX Module is essentially just a slave at that point, so I don't have a reason for the screen flash.

Wuerfel21 commented 3 years ago

Oh, my monitor doesn't like 640x480 85Hz very much, either. By which I mean it displays just fine, but has a big red "out of range" banner on top of it. IDK what that is about, the monitor really does suck.

Wuerfel21 commented 3 years ago

triangles.zip Got something going. Seems to glitch intermittently though, IDK what's going on.

Wuerfel21 commented 3 years ago

graphtest.zip Here's another example that feigns some amount of productivity and also shows off how terrible the line drawing function is. Still glitches, will figure those out eventually.

feilipu commented 3 years ago

Wooo! Spinning Triangles! :tada: Looks like you've already got it almost perfect! Here are some proof videos from my end.

I can see the tearing on my monitor too. I captured a screenshot, which might give you a fingerprint to where it is coming from. Screenshot from 2021-03-03 11-58-41

Wuerfel21 commented 3 years ago

That's actually a really strange one. But I'm fairly certain it must have to do with the video out code, because the rendering code didn't really change from what is proven to work (well, I made the buffers relocatable...)

feilipu commented 3 years ago

And yet, I just can't recreate it working, and that is infuriating.

Totally OT: I needed ld hl,(z_2) rather than ld (z_2),hl. Obvious in hindsight, and I also know how it happened. But now I can get my focus back here.

Wuerfel21 commented 3 years ago

Oh, that is an infuriating one.

Wuerfel21 commented 3 years ago

Figured out the glitches: there's a line in the VGA code that says wrbyte refreshCounter, syncIndicatorAddress. That should be commented out.

Wuerfel21 commented 3 years ago

Here that is in action, also some more colors triangles2.zip

feilipu commented 3 years ago

Looks good. I made a youtube video to show it off for you.

It looks like the refreshCounter variable isn't used at all with that line deleted, so all references can be removed.

I'll need to learn how at least the render language works, so that we can design a good efficient way to interact with it from the Z80 side. I'll spend some time tonight looking into it, and will have some questions I'm sure.

Wuerfel21 commented 3 years ago

Nice.

Oh BTW, I think all these examples have a bug: They forget to multiply DLIST_SIZE by 4 when passing it into gl.start, wasting ¾ of the memory...

feilipu commented 3 years ago

No worries. Just check in what you're happy with and we can get going with the Z80 interface. It looks great as is.

I'm thinking of asking RC2014 Group for suggestions on the interface too. Always nice to be inclusive.

Wuerfel21 commented 3 years ago

Yeah, will have to ASCIIfy it, clean some stuff up and then I'll check it in.

I'm thinking of asking RC2014 Group for suggestions on the interface too. Always nice to be inclusive.

Good idea, I think.

Wuerfel21 commented 3 years ago

done

Wuerfel21 commented 3 years ago

Also, if you're a lunatic who wants to do those kinds of things, you can flash this cut down version of Spin Hexagon to the UX module because why not hexagon_uxm.zip

There's weird glitches in the Hyper Hexagoner stage only, idk why

Wuerfel21 commented 3 years ago

Wait, changing one of the color values for the stage from $EFEF to $ECEC (which is only changing the "don't care" bits) makes it have less glitches. I am very confused and will investigate if that is a general VJET bug. Tomorrow, that is hexagon_uxm.zip

feilipu commented 3 years ago

There's \draw in the demos that is a non affecting typo, right?

And the font file is needed too, right?

Will make a hexagon vid too if you think the demo is ready?

Wuerfel21 commented 3 years ago

\method means that it catches any ABORTs that that method may throw. See propeller manual. The font file is needed to draw text. You probably want a different one though. There is a font conversion helper script in the VJET 1.0 release ZIP.

You can try making a video of Spin Hexagon on the UX Module if you want and it doesn't glitch too much for you. It's really just here because it took like 15 minutes to port. Here's a build with a more accurate version string: hexagon_uxm.zip

feilipu commented 3 years ago

Ok. I didn't know about the \ abort catch method. I will read about it.

I'll make another video, to explain why RC2014ers should be interested. Will help I'm sure.

Good luck investigating glitches 🤞(Daumen drücken).

feilipu commented 3 years ago

I tried with the checked in versions, and I found the spinning triangles glitching horribly. I am sure the only thing you changed was the length of the display list to 150. When I set it back to 900 the glitching disappeared.

Perhaps the display list length contributes to the glitching with Spin Hexagon, too?

Wuerfel21 commented 3 years ago

I checked the files and they were fine. Will have to check tomorrow. Insufficient dlist space should not cause glitches, just missing shapes

feilipu commented 3 years ago

There is a font conversion helper script in the VJET 1.0 release ZIP.

Sorry for being super doof, but I can't find where the font conversion helper is, nor where the "release" for VJET is either. I've checked your Gitlab signature, and parallax forum, etc, but nothing looks right.

EDIT More perseverance, and I think this post #34 has your release V1.0, but not the font conversion helper???

feilipu commented 3 years ago

Just to add a bit to this glitching issue.

Experimenting with vjet_test.spin, value of DLIST_SIZE less than about 195 glitches for me.

Here's a 1 sec video of the glitch with DLIST_SIZE = 190

Wuerfel21 commented 3 years ago

The files as committed (plus the font I forgot...) work perfectly fine for me and that is not the kind of problem insufficent dlist should cause.

Also yes, I thought that script was in there, but it is infact not. Here it is. Takes a PNG and spits out some character definitions that you need to manually edit a bit to get a useful font font2spin.zip

Wuerfel21 commented 3 years ago

Infact it isn't even close to using all the 150 longs. I can add a couple extra triangles and it's still fine on my end. What compiler do you use again? vjet_test.zip

feilipu commented 3 years ago

Using the Propeller IDE. Yes I can't imagine there being a direct issue. It may be in the VGA code rolling over or an addressing mode change. IDK really. But it is consistent and repeatable.

Wuerfel21 commented 3 years ago

Works on PropellerIDE here, too.

Also, I think I may be a step closer to figuring it out: It happens a ton when I change it to use 4 render cogs. There was a similar issue with the P2 version. I think it has to do with the timing with which the video code updates the line counter.

vjet_test.zip

Wuerfel21 commented 3 years ago

Can you look in the preferences for PropellerIDE and copy me whatever file is set as the compiler?

feilipu commented 3 years ago

Ok. I'll have to dig around for the actual file, but in preferences it is set to bstc, and the version in the attached pic.

There is an openspin option for the spin compiler too. I haven't tried that, but I will now. Screenshot from 2021-03-05 23-39-04 Screenshot from 2021-03-05 23-40-22

Wuerfel21 commented 3 years ago

Ahhh