How to detect that DMA transfer is finished

Discuss ZX Spectrum Next Games, Tools and more.
User avatar
Maziac
Posts: 55
Joined: Sun Jul 09, 2017 5:56 am

How to detect that DMA transfer is finished

Post by Maziac » Wed Jan 30, 2019 5:50 pm

Hi,

I could not find this in the docs or the example program:
Let's say I transfer a block of RAM to the HW sprites port via DMA.
How do I know that the DMA has finished and is ready to be used for other tasks?

Alcoholics Anonymous
Posts: 489
Joined: Mon May 29, 2017 7:00 pm

Re: How to detect that DMA transfer is finished

Post by Alcoholics Anonymous » Wed Jan 30, 2019 7:01 pm

If you're using continuous mode (as you almost always will be), the dma is finished by the time your next instruction executes. This is because the DMA is given the bus by the CPU which waits until the DMA gives it back. In continuous mode, the DMA does the entire transfer before giving it back.

In burst mode, which is mainly for DMA audio, the DMA will transfer one byte at a time, returning the bus to the CPU between each byte transferred. In this mode the CPU and DMA take turns and to find out when the DMA is finished you would have to read the DMA status register.

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

Re: How to detect that DMA transfer is finished

Post by Maziac » Wed Jan 30, 2019 8:15 pm

Does this also mean that in burst mode the cpu is slowed down by the dma?

Alcoholics Anonymous
Posts: 489
Joined: Mon May 29, 2017 7:00 pm

Re: How to detect that DMA transfer is finished

Post by Alcoholics Anonymous » Wed Jan 30, 2019 9:27 pm

Maziac wrote:
Wed Jan 30, 2019 8:15 pm
Does this also mean that in burst mode the cpu is slowed down by the dma?
Yes but it's not by very much.

If you're doing 32kHz sampled audio, you're sending about 640 bytes of sampled data in a 50Hz frame. Each sample takes 4 cycles plus maybe a couple cycles overhead for the DMA to hand back the bus, so in total about 3840 cycles are taken by the DMA in a frame. At 3.5MHz that's about 5.5% of CPU time taken, at 7MHz it's 2.7% and at 14MHz it's 1.4%. 32kHz is a pretty high sample rate - you're more likely doing 16kHz; it really depends on whether you need high frequencies in your audio.

Also keep in mind that when operated in continuous mode, the CPU is not able to respond to interrupts since it's sleeping while the DMA runs. On the spectrum, interrupts are only asserted for a short time so it's possible they will be missed in continuous mode. Usually, in a game situation, DMA operations are scheduled in the frame so there's no need to worry about that.

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

Re: How to detect that DMA transfer is finished

Post by Maziac » Thu Jan 31, 2019 6:11 pm

I was thinking more of the case that DMA and CPU is running in parallel.
I.e. in order not to loose any precious CPU cycle the burst mode could be used such that in almost every
CPU instruction also a DMA operation takes place.
What would be the "loss" for the CPU in that case?

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

Re: How to detect that DMA transfer is finished

Post by Ped7g » Thu Jan 31, 2019 6:30 pm

I don't think they are capable to operate in parallel .. at least the original Z80 DMA was inhibiting the CPU completely IIRC (it's already quite some months since I read through that data sheet, so I'm not sure).

Alcoholics Anonymous
Posts: 489
Joined: Mon May 29, 2017 7:00 pm

Re: How to detect that DMA transfer is finished

Post by Alcoholics Anonymous » Thu Jan 31, 2019 7:27 pm

They can't operate in parallel. There is only one address bus and one data bus in the system and either the CPU is controlling them or the DMA is controlling them.

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

Re: How to detect that DMA transfer is finished

Post by Maziac » Tue Feb 05, 2019 8:14 pm

If DMA is used in burst mode for audio for example.
Is it possible to interrupt DMA in order to to use DMA for byte block transfer (continuous mode) and then
continue to use DMA in burst mode for audio?

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

Re: How to detect that DMA transfer is finished

Post by Ped7g » Tue Feb 05, 2019 8:42 pm

Maziac wrote:
Tue Feb 05, 2019 8:14 pm
If DMA is used in burst mode for audio for example.
Is it possible to interrupt DMA in order to to use DMA for byte block transfer (continuous mode) and then
continue to use DMA in burst mode for audio?
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 also read all counters and preserve them and upload later. Although to time the re-run precisely may be quite tricky.

AFAIK there's no buffer or two+ channels in the DMA itself, so you have to do it "manually".

(I'm not suggesting it will be easy to mix these, I would personally avoid such solution unless I would get really bored and wanted to do lot of debugging and writing timing critical code)

Alcoholics Anonymous
Posts: 489
Joined: Mon May 29, 2017 7:00 pm

Re: How to detect that DMA transfer is finished

Post by Alcoholics Anonymous » 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.

About detecting when the DMA is finished during burst mode operation - you can read the number of bytes remaining or you can read the destination address or you can read the status register (starting with core 2.00.27 as the status register is not implemented prior to this) which will indicate if the whole block has completed transfer.

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.

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.

The problem with using the copper to do the sampled audio is that the copper's speed, unsurprisingly, is tied to the video frame and the video frame is different for all the different video timings the next can generate for various displays. So VGA0 is the perfect spectrum display mode where all the timings will be identical to the original machine. VGA1-6 speed up the video frame so the machine itself actually runs faster in realtime and audio will sound higher pitch. HDMI has a different number of lines in the display (as does a 60Hz display) so a copper program waiting on scanlines to output audio would have to be different than a 50 Hz VGA version. So pogie2 is setting the machine to a certain video timing so the copper audio will work properly. 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.

Post Reply