Zikzak - crummiest 8bit console/computer ever .. but I'm making it!


To get some practice at making pcbs and losing my money, I gather the progression should be ..

i) get cart pcb made (very simple, just 1 IC and straight routing), some silk screen

ii) get zikburner made .. a little complex with routing, maybe some solder mask, silk screen, LEDs etc.. not too hard though.

iii) then zikzak itself

iv) maybe a mini 1-chip version

I could just home-etch the cart pcbs really, but hopefulyl they'd be like $30/10pcbs or something, so be worth doing; just buying ET or Combat carts for Atari 2600 are like $5-$10 each around town; ebay has some, but they play +$16shipping stupidity scams :p Worry about carty cases later, anyway..

So, yeah, maybe I'll work a bit on getting a basic website up so I can record details in one place, and get cart pcb made, for lulz...

jeff
 
Here is an Atari 2600 cart 'teardown'; theres not much to it (some carts probably had bank switching in there and some other business, but most were just a single ROM chip.) 24pin .. 12pin address, 8 pin data, a couple Vcc and GNDs.. thats it.

Dropbox folder has a few in sequence:

https://www.dropbox.com/home/Public/zikzak/atari-2600-cart-teardown

But the final image is the mother load:

https://dl.dropboxusercontent.com/u/10949453/zikzak/atari-2600-cart-teardown/Photo%20Jan%2030%2C%2010%2025%2030%20PM.jpg

(I did this so I could measure a typical cart, to make sure my cart will fit inside somehow or another. This is an Activision cart mind you, which may be slightly different to an Atari one, so I may have to bust a Combat open.)

jeff

edit: added a photo with an arcade edge connector sitting in the mouth; you can see that the edge connector is numbered, and I only care about the first 16 teeth, and that just barely fits into the maw of the cart; of note is that width does not fit into the main body of the cart, as theres some 'struts' or something in there, and some doins'; the little 'guide skis' in the maw could be clipped off, since who cares :eek:
 
Last edited by a moderator:
Great! Good job about getting stable VGA output :)

You generate quite a few colors, really nice.

Is the chip strong enough to support a full 640*480 VGA signal from a 320*240 frame buffer? (I love large pixels lol)

I had no real hope that the 7" "monitor kit" I talked about sooner was HDCP compliant, and now seller confirmed it isn't.

Not a big surprise since it's pretty cheap and made in china :D

As I want to play content that could be encrypted (I.E. PS3 has "always on" HDCP, even during menu and games), I have to find a workaround.

I have found a few possible solutions, while roaming the internet. But since in most countries it's not legal to talk about circumventing "copy protections" (even if it's broken, HDCP's master key is available on internet) I won't get into details here :p
 
VGA itself isn't too bad; the hard part, that cost another couple of weeks, was wrestling with cpu unknowns. This level of chip is so powerful/complex that they just don't seem able to document it well enough; there is quite literally thousands of pages in the reference guides and ARM general guides, but they never quite seem to get to the nitty gritty. So while I was detecting and clearing the TCIF flag (interupt ackowledge) in the DMA ISR, I apparently needed to detect and clear TCIF1, which wasn't mentioned anywhere that I saw :/ I likely just missed it in the sea of charts.. that one character, that cost so much time..

Anyway, so now I'm using per-raster-line DMA, nice and simple. (The whole code that dfoes VGA is probably 2-3 pages, very short, just all fiddly timings and registers :p ); the DMA can be configured to follow a clock, so release each byte from the FIFO when the timer ticks.. so once you get the pixelclock timer set up just-so and attached to DMA, just fire it off. The DMA is pretty neat; I didn't even bother (this round) with trying the options yet.. burst on one end or the other, and fifo settings.. I've fiddled last week and you could just make it _go faster_, but we're already slowing it down with timer to keep it nice. Good to know we can go faster still :)

(and imagine .. could recode standard-C library memcpy and memmove and strcpy and so on, to use DMA if the length is worth the cost; ie: for a string, with 'strcpy', ou dont' want to pre-count the length, too expensive; but a strncpy(), or a memcpy(), you are given the length; if your length is say 1K or more, or whatever, it'd be worth (possiby) setting up a timer and DMA and doing that, and letting it go for 'free' on hardware, relieving the cpu; but then you end up with javascript like callback chains ("I'm done!") or having code not worry about it; usually after a memmove you want to use the new buffer immediately, and not do  a 'while not done, spin' loop; but in some special cases, like blitting to screen or sending audio out to headphone jack or other cases, you just want to memmove out a buffer, having it magicly use DMA would rock. Hence my routine is dma_memcpy(), but I need to add a couple flag-bitvalue vars, so yo can specify bolleans to 'increment source pointer yes/no' and so on.. a nice general purpose dma memcpy.. sweet!

The rate of release versus the rate of raster gun on the CRT makes the pixels .. so if you speed up the pixelclock, you get higher horizontal resolution up to monitor capacity; you slow it down, you get pixel doubling/tripling/blurring depending how you set it; so halving the timer should double your pixels.. for free :)

Now, I could set up the DMA 'circular' (repeating forever), and then just halt/restart the timer at each line; this would save on timer setup/start time (moving image more to the left), and would allow almost cpu-less operation.. the isr has 1 line to stop/start the timer at the right times, and no calcualtion; the loss there is pixel doubling vertical resolution -- right now the ISR enters, and it divides the linecount by 2 and jumps to the right part of the framebuffer array. If your fb matches your display 1:1, you could do the pure dma/timer/isr trick and it'd be glorious.. but risky; if the timing isn't just-so, I image so blur at the bottom and top or page, possibly out of sync the whole image more and more over time; with per-line dma, you know its pretty darned close.

I really should link the hsync and dma timer together, so that XXuS after hsync it wakes the DMA timer, to get a perfectly timed ikage (each line precisley same start point, every time), but so far it seems bullet proof sharp on my monitor, so I'm not going to sweat that additional level of timing chaining.

..

Right now though, the priority to fix on VGA is performance; the main loop is just 'while(1);' and its all interupt driven as Crom intended; if you expand the while() to do _stuff_, even really long lasting stuff, it shoudln't bollox the image at all, since interupt has priority.. but somehow it _Does_; if I do image blitting of any significance in the loop, the image gets messy at the top; I need to busy up crazy in the main loop and see if it blows the whole screen up, but I think it does; doesn't add up. Even if my main loop is "while(1){ nop }" you woudl think the main loop is '100% busy', and ISRs taking over and its perfectly fine; how does that differ to busy blitting loop in there, to the cpu? But it does.

Of interest..

i) Adjusting the mhz rate on the chip between 120 and 168 doesn't break the image; it should completely blow it up, unless it just luckily happens that I'm cutting from 640x480 to 800x600 by changing the rates; I couldn't be that lucky, could I? So jhanging the cpu speed is possibly changing some of the clocks but not all (I need to go over the timer dependancy chain again) .. I may not be speeding up all of the chip!

ii) I'm using volatiles too much; volatile is maybe slowing down some of these operations too much, but shoudln't break this even if, I think.. still.

iii) .. what else .. something else is screwing with the same timer as DMA maybe, or otherwise holding up the DMA? Theres not a lot in that code, but I dont' really understand the ARM Cortex M3/M4 arch that well.. just too expansive to grok it all yet, so I'm probably missing something.

Anyway, if its still an issue soon, I'll clean up the code to a simpler test case, and post it for some help.. but I'll keep at it. ie: I need this chip to be able to poll joystick in main loop, and I'd really like if it coudl take some reasonably high freq interupts from GPIO and not flicker. ie: this defines how z80 talks to it .. if z80 can talk memory bus to it, that would be outstanding; if it has to talk OUT/IN that works too, but a little lesser. Or do I need to use z180 (boo ;) , and hook up I2C or something instead ... etc, all depends on how much performance I have to burn.

Always the details, with simple resolutions after enough head pounding :)

..

Sad that it is hard to even discuss some of these encryption issues without getting red taped; the foundation of cryptology is that it must be open; if your protocol is fully documented to the attacker, and holds up, then it counts; if it doesn't hold up in that regard, it is a failure; security through obscurity is no security at all. So chit chat must be encouraged.. assholes :p

jeff
 
Last edited by a moderator:
Adjusting the mhz rate on the chip between 120 and 168 doesn't break the image;
It's been a few months since I toyed with the STM32F4 but I remember that the obvious thing that looked like it should change the speed did not actually change the speed. I needed to manually change the divider and something else in order to get it to change the clock speed. If I ever remember what that was I'll let you know.
 
When I change the speed, it definately changes.. things go faster in the animation loop, etc; its easy enough to check.. I just need to throw the hsync and vsync on the oscope and see if their timings changed based on speed .. just not had time to yet. Not enough time to do all the things floating around in the head :) I'm just rambling out here in the forum as thoughts pop into my head.. more forum time, than real world experiment time (sigh!)

Of interest.. whatever lib the ARM gcc toolchain build uses (newlib for the libc?), the 'memcpy' totally blows up the timers; instead of using memcpy to blit from one test offscreen array to the other, if I just for-loop copy it over brute force.. no real problems, so thats part of the performance bottle neck cleared up.

If I do (say) 50 screen blits per frame instead of just one, it does futz up the image; so depending what you are doing, it could throw the sync timers off.. very odd. I want those high speed interupts to be all cool..

Especially given 90% of the time is spent in DMAs (running in hardware, not in cpu user code), it should be half totally freed up :/

jeff

edit: Its defiantely changing .. screen is approx 16ms in 120MHz, and 10ms in 168Mhz.

Consider:

http://tinyvga.com/vga-timing/800x600@60Hz

Whole frame 628

16.5792

So changing to 10ms should totally blow up the image; but checking some other VGA modes..

Looks like its reasonably close to 800x600 100Hz .. maybe I'm just lucky, or maybe its VGA designers and these are common MHz rates or something.. but looks like just jumping between 120 and 168MHz works out. Boggles the mind.

..

edit 2:

FWIW, my test code right now just does some number of 10x10 brute force pixel fills, and then blits the whole offscreen 64K buffer onto the onscreen one; pretty lame, but does the job for a test. That works fine.

I can do about 50 10x10 rect blits, brute force, and no impact on the image, per frame. Completely unoptimized... and really, there should be no image impact _anyway_ so that shoudl be fixed. But even as-is, without tweaking anything anymore, that'd still be enough for many purposes and probably more than a lot of retro machines could do; ie: text modes.. no problem; space invader game, no problem; pacman etc, no problem; scrolling backgrounds would be hard on it though as is, but shoudl be doable easily enough too. I've just not put any work into it yet :p
 
Last edited by a moderator:
Doh .. Obvious .. Pretty certain the dma is using same memory bus as rest of cpu so I'm likely saturating the bus.. Cpu is free but unable to use memory half the time


Time to fiddle with larger fifo, moving stack, timing blits between dma hits ... Fun! :/
 
Fiddling with some options .. definately related to dma; I've tried putting some 'while dma busy, sit and wait' type loops before every pixel copy and that works, just slows everything down (and that polling is a real drag :)

Making sure you fit into the vblank period sure solves the problems.

I'll look into it as time goes on; theres a _lot_ of little tricks that can be done, but I'm not at the 'writing serious code' and drivers yet; this is all just proof of concept stage. Theres apparently 20K put aside for ethernet controller I'm not using, and a 64K buffer reserved for something else, and so on; the extra 64K is non-DMA memory (no peripheral has access, its just on the CPU for CPU-specific stuff); I need to check which bus that uses (if any) for instance .. maybe I can have free use of that 64K chunk while DMA is busy, etc.

Even now, with completely unoptimized code, no asm, no tricks, I'm getting the following...

260 8x8 blits; theres some other code going on, but at minimum then we're talking 8*8*260 or 16000 pixels per vblank, in full colour. (Given a 320x200 screen is 64kB, we're talking about renderting 1/4 of the screen per vblank.) Thats not bad - takes 4 vblanks to clear the screen say (1/15th of a second).

With sprites of 8x8, if they move, you rather need to clear/draw where they were too, so they dont' leave a trail.

For scrolling backgrounds it could be a pain, too.  (and if you recall, most retro games in the vic20, c64 etc era tended to not have scrolling backgrounds or any background at all, for this reason.)

But theres still soo much optimization to be done.

Suboptimal to be sure, but not too bad, and just getting started...

Now, to re-design how this possible gpu talks to the z80, to see how efficient can get that..

jeff

edit: OKay, make that 300.

I shoudl but in some performance analysis stuff.. turn up a stupid fast timer and count how much times go by in a vblank, so I really know how much cpu we can burn..
 
Last edited by a moderator:
Oh ho .. The Core Memory (ccm) that can only be used by cpu (no dma :/) might well be 64K ... Thats a sweet little compositing buffer waiting to happen. While dma busy rendering screen just draw there and blit at vblank.


Beautiful..
 
Alright, trivial change to make use of the CCM (Core Coupled Memory); this RAM is only usable directly by core but is very fast (no wait states, 1 cycle access); the down side is you can't use it with a peripheral (so you can't DMA copy right from it to your VGA output.. damned shame.)

They built this so when your DMA is busy as heck, your cpu can still process something safely, without hitting the DMA busied bus.

So using a really dumb main loop ..

i) animate in 'offscreen buffer' (in CCM memory)

ii) blit from CCM to the framebuffer that VGA rendering pulls from - this is what effects the display, since if you're writing to this while the VGA render is reading, you get a turd-line of garbage

In this scenario, we go from rendering 300 8x8 rectangles (see above) to _more than 2000_. ie: Thats is redrawing the entire screen _Twice_ in CCM memory, and then slow-copying it to the framebuffer. For each frame. ie: 60hz .. so this is 2000 8x8 rects, * 60fps. Thats pretty frickin' fast!

_Now we're talking!_ (course, we need to save some of this processing time for other tasks, and the big question is still can we take some interupts from the z80 without borking up the whole image, but thats some effort to set up a test for. Well, I suppose I could configure another timer, and do something goofy in its interrupt, to simulate the z80 hammering the guy, so thats not too bad to set up.. I'll do that when I get a moment.)

Were this actual 8x8 sprites, it'd take a little bit more time so a few less of them; but what if we did 16x16 ore 32x32 sprites or something.. we could do a bunch of them no problem; this implies we're exceeding the C64 graphics by quite a margin. C64 had a few reoslution options, but 320x200 was generally monochrome; most games used a low res higher colour option 160x200 with 4 or so colours per block and a limit of 8 sprites (changable per scanline); we've so far got double the resolution, full colour, and probably a hell of a lot more sprites than that.. hundreds of equivilent sprites. The NES was what, 256x200 or 256x240, and had 64 sprites, etc; (ignoring RAM etc, which zikzak will have much more of.) I imagine its closer to SNES in capability, though the SNES had a lot of slick modes and layer tricks it could do which may or may not be doable here. Still, not bad for a hack. If we can spit out the entire screen twice, that should be able to spit out a ful screen background image, and then layer a bunch of sprites onto it, for smooth animation. (mind you,m the CCM is only 64K, so if we have a 64KB framebuffer we're rather stuck.. going back to main RAM will break the performance and interupt the DMA. So worst case for scrolling games woudl be to slightly reduce the resolution, turn down the pixel clock so the image scales up in size a touch, and thus reclaim some memory..)

Anyway, this is very promising! But the big show stopper test is yet to come .. but soon...

edit: Ah, lol, updating pgio to toggle LEDs was causing me some dma interference; cutting that out, and back to crystal clear image, not a single pixel of distortion, and spitting out some 2500 8x8 rects; can do higher, too, looks like.. but onto the interupt pain tolerance testing....

*prays*

This is still really damned sweet :)

https://www.youtube.com/embed/wItvKnvm1HY?feature=oembed
 
Last edited by a moderator:
Hmm, I think I might have a solution to the picking up data from other chips issue; or at least, a first idea, that might work, before getting creative. (I mean, could put another chip in the middle.. serialize z80 parallel hits through shift registers, or an stm8 or avr8 in the way that marshalls/queues up requests or changes them into i2c or something, etc and so on.)

Maybe theres another bus I can leverage maybe some GPIOs are on one bus, and some GPIOs are on another.. maybe possible to set up pins just-so so that can read opposite bus GPIO, and store to CCM? hmm..

First idea is ..

i) interrupt comes in from z80; I set up a timer and had interupt go 1000 times a second, no problem; didn't try faster, but seemed the interrupt itself was harmless enough. I did it via timer, but normally it'd be an whenever the z80 did an OUT say, or the bus came the stm32's way, or whatever. Presumably I'll do an OUT bus, so the z80 can send instructions or data to the stm32 via OUT. Set up a sprite, do a pre-load series of OUTs to stream over the sprite data, and then during actual frames its just a matter of updating the sprite positions, which is very little data. (say 50 sprites, updating x and y of each would be say 100 writes plus some framing, so not too big a deal; but they'd be 100 all in a row... each frame.. so 100 * 60 is 6000 per second .. assume twice that at least and we're needing some serious bandwidth.

ii) when interupt comes in, rather than deal with it immediately (which is very likely during a dma, and thus would turd the image) just set a flag

iii) next hsync, if flag is set, pull the GPIO pins values during hsync. During hsync, vsync/vblank, we can do whatever we like since we know DMA is not active. We can do something before DMA but that could shift something over. We could do something at end of DMA as well, but if we set timings just so DMA width should be full screen, so nothing left before or after..

So in theory, at 800x600x60hz we've got 600*60 or 36000 hsyncs per second; now, theres still tiing issues galore.. if we're not ACKing the reception of the interupt, then the z80 couldn't exceed the timing there, couldn't do two OUTs within the same scanline or we'd miss one; if we pull af ew values, maybe we can, but too much and we'd distort the image, since GPIOs take up bus the DMA needs.

Hmm. Well, time to dig around for options, but at least that worst case is still workable. ie: turn off the display, stream data full speed to stm32 (which would be fast, since not doing vga at the time, so full speed of the z80 as limiting factor), then turn on the display and send orders to the sprites.

For text mode, its just not a problem at all.

...

But lets hope theres some other-bus trick..

jeff
 
Sad that it is hard to even discuss some of these encryption issues without getting red taped; the foundation of cryptology is that it must be open; if your protocol is fully documented to the attacker, and holds up, then it counts; if it doesn't hold up in that regard, it is a failure; security through obscurity is no security at all. So chit chat must be encouraged.. assholes
Moreover HDCP is completely useless and broken : it couldn't prevent blu-ray rip, nor TV rip in HD. So it's more a pain in the ass for the common user than an effective "copy protection" for the content. The only reason HDCP is still somewhat "secure" is that you can't order HDCP compliant chips from a chip maker if not a member of the authorized screen manufacturers.Anyway, I'm probably going to drop the 7" screen kit. I've an "old" and broken portable computer.

The LCD panel is fine and should be using LVDS, like most of those screens.

The keyboard is fine too.

So using the old computer case, hacking a screen controller and a USB keyboard controller in it shouldn't be impossible to do. TI produce quite a few LVDS chips and documentation about them is available :p

---

As I said previously, having a "slow mode" with "high" resolution + lots of colours and a "fast mode" with a "low" resolution and only a few colours would be great. That way, we could do RPG and other slow-paced games in slow mode to get large and detailed sprites and backgrounds and Shmup and other fast-paced games in fast mode to use a lot of small sprites :)
 
Last edited by a moderator:
I've not worried about that sort of thing yet; its not likely a problem, but I'm still nailing down the architecture.

By deliberately imposing Z8 0on the system, it rather makes things challenging, since its such an old chip with no peripherals built in.. they just do it like that anymore, so you can' interface easily to anything, and yet, I need to:) So 'making it work, at all well' is the foremost concvern, and how you code it will come from that.

But it is 99% certain that the z80 will have its model of whats going on (there will be plenty of RAM, unlike in the z80 of old .. I'm going to hook up as much as it can handle; and if I use a modern z180 then it means 1MB of RAM..), and the GPU here will also have a model of what is going on; I'm thinking currently (but very much subjecty to change) the Z80 will have a list of instructions it can send to the gpu; obvious thigns like set video mode and clear screen, and lesser obvious things like 'suspend screen display but keep sync going' to 'turn display off/on' (so that you can disable rendering to display, do a big data dump that woudl blow up the image due to contention, and then turn the rendering back on.) But simple primitives too .. draw a line here, move sprite N to (x,y), that sort of thing.

So in this case, its more like a modern scenegraph in zx80 space, and a framebuffer or two in gpu space, with the z80 informing the gpu when it can. The hard part right now is trying to get as much bandwidth from z80 to gpu as we can without buggering up the VGA image by overloading things. Right now I'm looking at not a lot of bandwidth, but theres a few tricks I'm investigating which may relieve all that.

At best, if I can relieve the gpu of contention on its buses, I could just have it sit on the bus with the z80 and they coudl chatter back and forth; this would be outstanding. But worst case is a slower connection where the z80 can try to only chat a little bit to avoid glitching the display.. or perhaps talk over a serial connection if using a z180, at reasonably high speed, since I can try to have the gpu serial peripheral not contend with the gpu dma bus. Lots of trick to try..

The very worst case is introducing a buffer chip inbetween; if z80 -> ?? -> gpu, then I coudl use another microcontroller in there (such as a 8bit limited version of a similar chip to the gpu, so same programming hardware needed to reflash it); that way the z80 could talk at _its_ full speed to the intermediary, who in turn meters it out to the gpu when the gpu is clear; by adding in another chip, it makes things a lot easier. I used ot be calling that the I/O chip since you coudl then hang keyboards and SDIO and such off _that_ and avoid loading the gpu with any of this stuff. But I'm really trying to avoid putting an extra IC in there .. it does make things more traditional (cpu, I/O, and display as separate), but adds cost, a little complexity, and more possibility for breakage. For this project, I'm trying to be goofy, but keep it simple so peopel can hack it, or understand it easily.. a simple schematic.

We'll see :)

If I can get lucky, and get all the bus contention sorted out easily and get the gpu just sitting on the bus with the z80 chit chatting together, or better still, sitting on the same RAM as the z80 and interleaving each others access... then there can be a single framebuffer image in RAM, and both guys can work on it, and it makes our lives really easy and interesting.

..

Sorry, I distracted myself; for collision though .. if we're dong it where the z80 side just has a array of sprites:

sprite1          10,10

sprite2          20,30

...etc

Then it could quite easily do a rectangle check to see about collisions if it wanted to; I was originally going to run the z80 slow like the old days.. 1-2Mhz, but I've tossed that idea out now I think; I'm going to make the clock come out of the very fast GPU, so that its variable and adjustable; ie: zuo could ask the gpu to tun up or down its clock. Likewise, the z80 I'm using can run up to say 20MHz or even 30MHz, depending. (If you run them 'slower' at 20MHz, you can use lower voltage for a lot of the parts; if I can have the whole board run at 3V it'd be much handier than having to run half the board at 5V and the other half at 3V, with regulators and so on inbetween.

I don't anticipate 'hardware sprite collision handling' or any 'hardware' at all per se, though it'll look like hardware since the gpu os so fast. Its all codable though, so we can ad features to the gpu willy nilly, grow it over time or have multiple renderers; one idea I had was the z80 could push executable code over to the gpu, so the z80 carts could have replacement renderer code for the gpu if they wanted (say), so that one game coudl use a gpu acting one way, while anothe could code up the gpu entirely differently. Maybe one game will want the gpu doing collision detection, since its so fast .. if the sprite table on gpu side is in CCM RAM (or other 'safe' fast RAM), its entirely possible its more efficient and 'free' to do it in gpu, while the z80 does other kinds of processing..

Crazy stuff we can do here :)
 
I suppose worst case is upping to the F429 itself; that chip has a DMA2d accelerator in it, but also has a third bank of 64KB SRAM; so while the chip I intended to use (F405, 64pin LQFP package.. hard to solder, but not impossible for average joe) has the 64KB CCM, and the main 112KB SRAM, and a sneaky little 16KB SRAM on the side. The F429 (LQFP100 paclkage, really really hard to solder without a hot air station) has 112K, 16K, the CCM 674KB, and also another SRAM 64KB. I'd have to check the busing diagram but I believe they've separated out those SRAMs specifically so you can use different bus for each, and less contention.

Still, lots of tricks to do.. trying to work out if I can load stuff into that little 16KB buffer during hscync and DMA from that to alleviate the main SRAM contention; ... etc.

GPU is all about performance isn't it.. squeezing every last drop out of it, since every penny saved makes your life 10x better on the z80 side..

jeff

edit: Dont' think cutting over to the F429 would solve the issue .. its really an issue with GPIO _and_ SRAM in this case; even if I'm clever and use SRAM2 during hsync to feed DMAs, or use the F429 and have an extra 64K SRAM for framebuffer.. _any_ GPIO hit (to read from z80) during a DMA will glitch.. since the DMA and SRAM1 and GPIO are all on the same bus. ie: If during hsync we send over a few lines of data to the SRAM2, and then DMA is from SRAM2 to VGA, great.. but when a z80 event causing a GPIO to interupt, and then we pull in the GPIO values.. we'll glitch.

Options now are then..

i) the FSMC (memory controller) is on another bus than GPIO, SRAM1, and DMA; if timing is right, it may be possible then to just mount the z80 RAM via FSMC, and put some logic on the board to enforce no electrical collision; would be pretty ideal, but some work and a lot of work to set up and test.

ii) just go with serial; z80 can use SIO chip, or Z180 has a couple built in serial USARTs; z180 claims can do 512kbit or 64KB per second, which is pretty good. STM32 GPU side coudl have DMA1 pick up from USART and feed to SRAM2, and thus have a serial pipe right into gpu; could just have z80 post an action log byte by byte over serial. Sort of goofy, but 64KB per second is pretty darned fast, that should be enough. Even if its half or 1/4 that, its not bad; 1sec of uploading sprites while game starts, and then just sending the action list 'move sprite N to (x,y)' sort of thing.

iii) or do it as-is .. interupt comes in since z80 wants to say something, then wait till hsync and pick up the GPIOs then. But that limits us to only pickin gup 480B per frame or so .. should be enough, but may not be enough; its about the same as serial, but riskier it could glitch .. but tempting.

Time to meditate ... serial is easy, but goofy; RAM mounting woudl be amazing, shared memory between the two is pretty ideal, but could be tricky. Also may slow down the z80 if we have to suspend its clock so we can dip into RAM without collision.
 
Last edited by a moderator:
OKay, so mulling it over a touch, here are the options for resolution of this particular challenge to excellence (theres always one .. you solve it, you get the next challenge :) VGA performs buetifulyl now, so now we're figring out how to feed the damned data in :p

Options:

1) as-is, try and do z80 to gpu during hsync (about 10-30KB per second bandwidth); which is to say, about 500B/frame; can you adequaltey describe all scenegraph changes in 500B per frame, for 60fps with a dozen sprites? Yes, but tight.

2) try to work out FSMC on gpu, so it can mount same RAM as z80, and just keep framebvuffer there, and action todo log there; pretty ideal, but maybe hard, and could be clumsy in the end.

3) serial .. use zip with SIO (pricey) or z180 (neat) or even ez80 (newest z80) to talk to gpu; probably get us 20KB-64KB per second; similar to hsync limits, but shoudl be more seamless, less risky and less painful, and maybe much more bandwidth. Best case is double the best case of hsync method (64KB per second, at 60fps means about 1K/frame.

4) add an intermediate chip, that _can_ talk i2c or bitbang during vblank/hsync. So the z80 woudl talk to intermediate, which queues up orders, and feeds them to thestm32 GPU. The intermediary woudl be an avr8 or an st8 say.. a microcontroller, but a teeny low end one; The advantage here id the intermediate knows i2c or serial or bitbang, and can know when to do it and not be disruptive. LEt rhw z80 run willy nilly, let the gpu do what it ahs to do, but gpu raise a pin when vblank happens, and then read GPIOs like crazy from the buffering intermediary chip until vblank ends, say. Also advantage is intermediary can do the I/O.

--> another advantage is the intermediary can drive the whole thing; so you could ignore the z80, and just have the intermediary be the business logic (though it wouldn't have cart access, so this is of limited value.)

** This was the original design all along, but I've been trying to get rid of the intermediary chip for the last 2 months, but its challenging as you can see :)

5) cut over to ez80 and use i2c instead of serial; just a different protocol really, but should be theoretically possible to get a higher bandwidth again (about 128KB/second, maybe more)

6) dump the z80 entirely;

   - such as single chip (gpu does it all, may be tight due to gpio limits.. but at least it can do gpio to audio chip when its free, since it knows)

   - or dual STM32's .. add another high speed chip that does the I/O and whatever it wants, and shoves everything over to the gpu via i2c or memory mapping or whatever. Lots of options here.

So while (6) is amusing, if I was going to try and make a more modern or beefier console/computer, I'd go about it entirely differently and end up with a console version of Pandora :p So it seems out since we're here for old school and fun and learn stuff.

So my inclination is to go back to what I'd always intended.. (4), with the intermediary, or perhaps the serial or i2c methods.

The intermediary makes things simple (gpu is gpu, intermediary is the chip liason/bridge, and the I/O stuff), and the brain is the z80. Nice and well defined. Protocol from intermediary to gpu can be sorted out and shoudl be no problem since it can be smart and unintrusive. The only trick then (since there always is one), is how the z80 talks to the intermediary .. but presumably since intermediary is fast as z80 or more, its just going to wait for the OUT interupt, pick up the pins, and queue them up. Should be a piece of cake.

Also makes testing a lot easier.. can test z80 -> intermediary (with serial logging over USB to a PC), and likewise can test intermediary to GPU to nail _that_ down. Two halves testing independantly makes life a lot easier than having to hook it _all_ up and test end to end, while just prototyping.

Hell who knows, maybe the intermediary can read the cart space too, and drop the z80 if you dont' want it for that cart. *shrug*

So what do you think..

Z80 -> STM8 or AVR8 -> STM32 GPU.

Z80 wil be programmed via carts

STM32 is flashable via a special JTAG cable <- folks would need one, if they want to reflash gpu code

So to avoid having a third programmer style, I'd likely opt to go with STM8 8bit chip, instead of my beloved AVRs, just so one JTAG cabl coudl do both the GPU and the intermediary.  If it was just me, I'd use an AVR8 (atmega644 say) as the intermediary since I love it and have a pile of them, but I'm trying to deal you guys in :)

jeff
 
I think having only one programmer for all the chips would be easier than multiple ones.

Even more when Atmel is a PITA to get free samples while ST seems really "friendly" to amateur electronic hackers.
 
Hmm, still interesting.

Some really knowledgeable people are trying to school me, but its still above my head; so in background will keep working on it, see if we can sort it out; theres just so much complexity in the chip design, theres probabyl a lot of ways around this I'm not aware of yet. ie: the 'mesh' of connections between the internal bits of the CPU really matters, more so than the 'buses'; trying to find an optimal combination is the way to go, might just solve all problems.

But of interest..

- using DMA frees up the CPU, which is why I wanted to use it; ie: using DMA means you can do more sprite updates and so on, since CPU free to do all the buffer updates etc

--> but DMA ties up the damned bus, hard, so while cpu is free, we have limited things we can do (doh!) .. GPIO access glitches the display unless we're careful to meter it in using another chip

- using brute-force rendering can get a pretty sharp image, but not as crisp as DMA since its not exactly meter out; might be able to crispen up with a timer, but I'd image DMA would alwsys be sharper; still, its not _that_ unsharp, so may be usable (certainly could toggle between which mode is desired, if we wanted; z80 could send a render-more instruction over.)

--> when using brute-force, everythign is slower since the CPU is busy doing the work

--> as a result of that, the bus is a little free'er, so GPIO access _do not glitch_ unless theres a boatload of them, and glitching is much reduced; at 7KB per second theres some flickery bits splashed around, but not too baad; its annoying though, but doesn't destroy the image; you can go to about 60K/sec before it really trashes things..

Hmrf

An I/O chip would clean it all up, but still trying to avoid it :)

Talking to more knowledgable folks though, theres some brilliant peopel who coudl sovle this easily :)

Hell, glitching only occurs where there is colour.. since the glitching is where the pixels 'slide over a bit' due to the delays caused by GPIOs; so if your screen is black, with some space invaders on it, the glitchign is just a bit of fuizz aroundsome of the invaders.
 
Last edited by a moderator:
Back
Top