Simple DMA example

Do you live and breathe hexadecimal? Do you like speaking to hardware directly?

Moderator: Programming Moderators

User avatar
SevenFFF
Posts: 211
Joined: Mon Jun 05, 2017 5:30 pm
Location: USA

Re: Simple DMA example

Post by SevenFFF » Fri May 11, 2018 5:19 pm

Just another general note, for other people reading: Seperately from the VCC voltage confusion, these cables also exist with 5V CMOS levels on RX and TX, instead of 3.3V. The seller should usually make this clear, but be aware that you could easily damage the FPGA by plugging in the wrong kind, so it's worth knowing upfront what to avoid.

FTDI cables also come with 3.5mm stereo headphone plugs on the board end. I am considering a breakout board that will use the speaker disconnect switches inside a 3.5mm stereo socket to switch between COM port and ESP module in a cased next. My Next will be in a retroradionics rubber case, so if anyone else likes this idea, let's explore it together. I am not a hardware designer!
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel Spectron 2084blog

User avatar
gavin1969
Posts: 6
Joined: Sun Jul 16, 2017 8:20 pm

Re: Simple DMA example

Post by gavin1969 » Sat May 12, 2018 2:26 pm

Just to confirm I am now DMAing via ParaSys! Success!
Learnt about Zeus along the way too, but still need to work out all the ParaSys commands.
Thanks for help along the way, look forward to the public versions of these resources being available so we can help others get started too.

Now to work out a better wiring solution, so I can toggle ParaSys and the WIFI!

User avatar
SevenFFF
Posts: 211
Joined: Mon Jun 05, 2017 5:30 pm
Location: USA

Re: Simple DMA example

Post by SevenFFF » Sat May 12, 2018 3:17 pm

Excellent, good stuff. I will still document it when I get time.

Here's my ParaSys command cheat sheet:

Code: Select all

T <addr> (view memory)
M <addr> <data> (modify memory)
C <addr> (call code)
U <src> <dst> <length> (Copy up LDIR)
L <src> <dst> <length> (Copy down LDDR)
D <addr> (disassemble)
I <addr> (in) i/O ports are 0-FFFF, Next registers are 10000-100FF
O <addr> <data> (out) i/O ports are 0-FFFF, Next registers are 10000-100FF
R <reg> (nextreg in)
W <reg> <data> (nextreg out)
> <start> <length> <filename> (read)
< <start> <length> <filename> (write)
B (boot) b0 (rst0), b1 or b (F4 reset), b2 (F1 reset)
X (settings) sends parameter to the slave, to select whatever variations of slave behaviour the slave code supports
E (exit)
? (ask slave to identify itself)
/command (Sends command across link)
All values in hex.
Addresses are valid for $00000 to $2FFFF then repeat paged memory accesses.
Calling addresses outside $0000 ... $FFFF just calls the 16-bit part of the address.
The note about addresses might change - at some point ParaSys might support Next 25-bit world addresses. At the moment it only sends to addresses corresponding to classic 128K pages.

This experimental version of Zeus also has the zeusmmu(8kBankNo) function, which works like zeuspage(128kPageNo) in the regular Zeus. And a zeusemulate "Next" target for the emulator, which enables the enhanced opcodes and MMU paging.

Zeus only emulates MMU paging and sprites so far, but MMU paging is enough for me to be able to use source stepping and zeusdatabreakpoints when I need to really see what's going on.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel Spectron 2084blog

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

Re: Simple DMA example

Post by Ped7g » Wed Jul 18, 2018 8:01 am

I did check the DMA informations over internet, the Czech paper and MB-02 related stuff is designed for the East-German clone of Z80-DMA chip "UA880D", which may cause some discrepancies, also the MB-02 DMA did not connect interrupt wiring, thus things like "pulse" or "burst" mode are pretty much useless there, only per-byte or continuous block are relevant. But enabling DMA by writing into WR3 before the other commands are finished is IMO bug even for "UA880D", either that, or that chip must have ignored that bit completely then, anyway that short example in Czech magazine is clearly bugged when applied to Z80-DMA original chip, there should be only one DMA-enable by the final command #87.

Also some other IMO important notes from original user manual:
* whenever some WRx register is modified, the DMA gets disabled (i.e. enabling it by writing WR3 and then writing further configuration in that "LDIR example" makes even less sense, as that would start some transfer, but as soon as CPU would execute next `out`, it would get disabled again) ... also the "enable" must be obviously last value sent.
* When changing between PortA <-> PortB direction (WR0.D2), it should be not the first command received after DMA being enabled/active, any other command/write should be issued prior to that (DMA disable #83 is safe bet).
* end-of-block state, DMA disable, one of the reset commands, and similar, all cancel the internal "force RDY" condition, so for mem-to-mem copies it seems to me like the #B3 is mandatory (probably right before #87 DMA-enable).

Which makes me wonder which chip exactly (Zilog or some limited clone) is emulated by NEXT core and if it does support also interrupts and burst mode, etc...

As I don't have the board, I can't try myself, but if anyone is interested in cooperation, I can provide him with few theoretical Z80 sources to test various things about DMA, which may eventually work also as short examples of how to do things with it, after somebody would be kind enough to debug them for me and fix them together into working state.

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

Re: Simple DMA example

Post by Ped7g » Wed Jul 18, 2018 8:10 am

Also I'm wondering all the time, if the "proper" initialization of "ready signal low/high" (WR5.D3) would cause the transfer start in mem-to-mem continuous block mode even without the #B3 force RDY command, anyone with enough electronics insight to tell me if I'm not intermixing two different things, and if there's a change the RDY in mem-to-mem is in some particular fixed state, so WR5.D3 can be set "correctly"? Avoiding that one #B3 out makes quite some difference to my hypothetical init-DMA source, 6 bytes long re-init for short "rectangle in layer2' transfers would fit into available registers, 7 bytes long re-init does not, and this single #B3 is ruining it at this moment... (mind you, I'm working purely theoretically, as I don't have the HW yet, so this whole 7 byte re-init may be wrong and non-functional).

So definitely, if somebody understands NEXT enough, or is willing to run several different code variants on his board and let me know about results (debugging skills probably needed, compiling ASM + uploading to your board is a *must*, as you know probably more about it, than me, at this moment) = I can provide you with some codes, to make some wholesome information about how one can use DMA on NEXT..

User avatar
SevenFFF
Posts: 211
Joined: Mon Jun 05, 2017 5:30 pm
Location: USA

Re: Simple DMA example

Post by SevenFFF » Wed Jul 18, 2018 11:11 pm

It's based on the Zilog chip, with some extra Next-specific features. All three modes are implemented.
is probably the best person to discuss this with.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel Spectron 2084blog

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

Re: Simple DMA example

Post by Alcoholics Anonymous » Thu Jul 19, 2018 2:24 am

The zx next dma is exactly documented here:

https://github.com/z88dk/z88dk/blob/mas ... zxn_dma.m4

This documentation is generated from the vhdl source.

There are two outstanding bugs:

1 - In burst mode, the time taken to transfer each byte depends on the cpu speed. This means audio sample playback can only happen when the cpu is running at a fixed 3.5 or 7MHz currently, with 7MHz leading to high sample rates (min 28kHz).

2 - In burst mode, the cpu is only given half the idle time instead of all of it.

Both of these are slated to be fixed.

The zx next dma is based on the z80 dma with some things removed and one feature added. The most important thing removed is probably interrupt capability. The new feature is a new burst mode that allows you to progam how much time each byte transferred takes. The idle time is given back to the cpu while the dma waits to transfer the next byte.

Reading the doc above should answer most questions about how to use the dma. The dma operates in two modes. In continuous mode, the dma takes the bus and keeps it until it's finished. So the z80 would start the dma, then know the dma operation was completed when the next instruction was executed and the dma would be in a stopped state. In burst mode, the dma gives time to the cpu while it is idle. The cpu can poll the dma to find out if it's finished or it can stop the dma by writing a disable command to WR6.

Post Reply