How to detect that DMA transfer is finished

Discuss ZX Spectrum Next Games, Tools and more.
Ped7g
Posts: 72
Joined: Mon Jul 16, 2018 7:11 pm

Re: How to detect that DMA transfer is finished

Postby Ped7g » Thu Feb 07, 2019 7:33 am

Alcoholics Anonymous wrote:
Thu Feb 07, 2019 5:12 am
Ped7g wrote:
Tue Feb 05, 2019 8:42 pm
On original Z80DMA any write into DMA registers will stop current transfer (but it hadn't burst mode like ZXNDMA, so I'm not 100% sure if it does apply).
You can stop the DMA by sending a DISABLE_DMA command. Then you could read the registers to find out where the DMA is so that you could restart it later.
Well, that's kinda obvious, although good to have it confirmed. But let me repeat it, on original Z80DMA, write to any register (except ENABLE_DMA command) acts also as implicit DISABLE_DMA command. Would be nice to know, if this is also feature of ZXNDMA, or not.
Alcoholics Anonymous wrote:
Thu Feb 07, 2019 5:12 am
If using the DMA for audio, it's hard to interrupt it to do something else as any change in sample rate will cause crackles in the audio output. Multiple DMA channels would be the way to go to solve this reasonably.
Hm, there are already two DMA ports (MB-02 and Datagear standards), and I would expect there's precisely zero legacy SW using both at the same time.

So... thinking wild for a moment... if the FPGA implementation for ZXNDMA can use two sets of registers, each for the other port... and one port would have higher priority, so only one DMA would access bus/memory = just like now .... you have technically one-and-half channel DMA system. For continuous mode this would act the same way as single channel DMA, but with burst mode, if the audio would be done on higher priority DMA, which would be capable to interrupt memory DMA running on lower priority port, you would have "two" channel DMA, for the price of the continuous transfer taking variable amount of cycles instead of deterministic one, although it would be possible to expect quite accurately +- few cycles what the final duration will be, so this is not any major downside.

The question is, how difficult is to have two sets of DMA registers in FPGA, and how difficult it is to create this 1.5 channel dichotomy, and whether I overlooked some important detail making this whole idea invalid from start... :)

User avatar
Maziac
Posts: 54
Joined: Sun Jul 09, 2017 5:56 am

Re: How to detect that DMA transfer is finished

Postby Maziac » Thu Feb 07, 2019 5:54 pm

The question is, how difficult is to have two sets of DMA registers in FPGA, and how difficult it is to create this 1.5 channel dichotomy, and whether I overlooked some important detail making this whole idea invalid from start...
But, if we talk about HW changes, here is another thought:
wouldn't it be better to spent a simple timer interrupt that could be used for the audio.
This would have the further advantage that additionally the audio signal could be shaped or mixed or the general volume could be easily adjusted.
And, an even bigger advantage, the memory access can be handled easier.
One drawback when using audio with DMA is that the memory banks the samples are in have to be paged into the normal 64k.
Therefore, if audio DMA is used, at least one 8k block is lost for other usages.
In the interrupt approach the SW could page in the required memory bank read the sample, process it, send it to the DAC and then switch back to the previous bank.


And I must say I strongly disagree with anonymous in this point:
In a release situation, such a copper program would probably have to be written for all the next video timings and the program will have to use the right one depending on the user's selected timing. This probably isn't a huge deal to do actually but it is something you have to keep in mind.
This is a huge deal:
It means to prepare different samples for different video modes. And not only this. It also means that all those video modes have to be tested. This is nothing you can automate, i.e. it has to be tested manually for each video mode. Then you need the HW (TVs, monitors) for the video modes. So it's also a cost factor.
And so on. If you get another such dependency inside your code it even multiplies the effort.
So copper is for me , for these reasons, not really an alternative for using audio.

User avatar
varmfskii
Posts: 161
Joined: Fri Jun 23, 2017 1:13 pm
Location: Albuquerque, NM USA

Re: How to detect that DMA transfer is finished

Postby varmfskii » Thu Feb 07, 2019 6:20 pm

Alcoholics Anonymous wrote:
Thu Feb 07, 2019 5:12 am

Another way to generate sampled audio independent of the cpu is to use the copper to do it. If you have a board you can try running the pogie demo (enter ".run pogie2*" from basic). The demo will force 60Hz video for reasons described shortly so hopefully your display can do 60Hz in the mode you've set up (HDMI / VGA). I think it may have to be VGA as well, not sure, and VGA0 is probably the correct mode for correct pitch.
In a release situation, such a copper program would probably have to be written for all the next video timings and the program will have to use the right one depending on the user's selected timing. This probably isn't a huge deal to do actually but it is something you have to keep in mind.
Let us consider for a moment the commercial release of films on video tape (yeah a little old school): Films are shot at 24 fps, but video is either ~50Hz or ~60Hz (anybody who really knows video will know that I am simplifying the situation). So how do you convert 24 fps video to 60 fps video, you do 3:2 pull down conversion (you play one frame for 3 half frames and the next for 2 half frames), great we are at the same speed, so everything is pitch perfect. But what happens on 50Hz? Typically each frame of film is used for 2 half frames of video, but this results in 25 fps on average so the sound would quickly get out of sync with the video. This is very bad. So the sound track gets played 1-1/24 times as fast as it was on the original (about 0.7 semitones). This isn't ideal, but since most people, even those with good ears for music, only have relative pitch (everything has been transposed up a bit), the result is OK.

As a result, in a release situation, you could simply not bother to worry about it.
Backer #2741 - TS2068, Byte, ZX Evolution

Ped7g
Posts: 72
Joined: Mon Jul 16, 2018 7:11 pm

Re: How to detect that DMA transfer is finished

Postby Ped7g » Thu Feb 07, 2019 6:45 pm

Hm... with interrupts you have to decide on the priorities and what happens when there are two in parallel. The DMA inhibits interrupts, so in burst mode producing audio it may make interrupt stumble by couple of cycles (the memory read is 2T when DMA is configured to fastest mode ... if ZXNDMA operates like that, write to sounds port is who knows how many, if 2T is enough? but it should be fast enough for Z80 still catch the decaying INT signal from ULA), which may turn off the pixel-precise display sync through interrupts (so only Copper remains as pixel-precise option, as that one is autonomous on DMA and it doesn't need ZX memory access?). But the interrupt timing is being skewed by DMA audio either way, so this is not new issue.

Adding timer interrupt may make whole display interrupt skip, if it happens while timer interrupt handler is running, so it's even more essential to time graphics related frame dynamics by copper only (but you would be able to create "detect skipped display interrupt" through copper by modifying some NextReg to expected value when frame ends/begins, so you can then effectively create "wait for retrace" without im2, and leave interrupts fully available to timer only.

Or if the timer interrupt would be of lower priority, the timer handler may be completely skipped, unless the timer producing signals will hold INT until confirmed to be processed by some `out` or something. Not sure how few cycle delay would affect audio quality, probably not at all. Skipped interrupt would probably risk being "clicky".

I mean, the main issue is, that you have only single memory bus, and so many things needing to read memory (Z80, layer2, DMA) at the "same" time, and then there's that INT signal and DMA burst inhibiting everything every now and then. It's not accident more advanced machines introduced sound buffers, so the sound card can read the data from it's own buffer not disturbed by other parts of machine.

My proposal keeps the same pressure on bus usage (it's only one DMA chip processing, the lower priority waits), so it mess up with interrupt precise timing the same way how current system would (just a bit).

... so... if timer interrupt, it should be probably of lower priority, and it must somehow avoid display-INTs with reasonable granularity, to make sure the handler knows what caused it, but also hold it's own to not skip it completely. That would be probably easiest to handle on SW side.

-----------------

About the copper audio.. you probably misunderstood the idea, the sound data are identical, you just put different delta-offset to each copper WAIT instruction to launch at the proper time and send the data to sound port. It's just annoying to generate that copper code on fly with correct timing for all possible display timings, but it's also probably like one time effort to write such code. Also it kills the copper for other purposes.

Your idea of having sounds sampled in particular frequency sounds ... hmm, that would allow to put copper waits at fixed places, probably allowing at least for some limited copper usage.

--------

Overall I'm not sure what is good solution, whatever one picks, there's some hurdle.. as always with the old 8b systems. :)

User avatar
Maziac
Posts: 54
Joined: Sun Jul 09, 2017 5:56 am

Re: How to detect that DMA transfer is finished

Postby Maziac » Thu Feb 07, 2019 6:45 pm

As a result, in a release situation, you could simply not bother to worry about it.
Also a way to deal with this.
At least better than re-sampling and re-testing :-)


Who is online

Users browsing this forum: No registered users and 3 guests