DMA: Difference between revisions

From WSdev Wiki
Jump to navigationJump to search
No edit summary
(document SDMA hold and bus behaviour)
Line 66: Line 66:
Due to its need to access the external cartridge bus, Sound DMA steals 7 cycles - the same amount of time GDMA would take for transferring one byte - every 128 cycles. These are always cycles <code>{117, 118, 119, 120, 121, 122, 123} mod 128</code>.
Due to its need to access the external cartridge bus, Sound DMA steals 7 cycles - the same amount of time GDMA would take for transferring one byte - every 128 cycles. These are always cycles <code>{117, 118, 119, 120, 121, 122, 123} mod 128</code>.


TODO: How does Sound DMA interact with the cartridge waitstate configuration?
Sound DMA supports ''holding'' - if enabled, the offset/length counters will be paused, allowing for resuming without losing auto-repeat state. The DMA cycles still occur, but they write <code>$00</code> to the target port instead of the in-memory value.
 
While General DMA uses word access, Sound DMA uses byte access. This means that SRAM is supported as an input source. Also unlike General DMA, streaming from "slow" (>1 cycle) locations is supported; doing so lengthens Sound DMA by the difference.


{{Anchor|SDMA Source Address Low}}
{{Anchor|SDMA Source Address Low}}
Line 98: Line 100:
7  bit  0
7  bit  0
---- ----
---- ----
ed.t r?ff
ed.t rhff
|| | | ||
|| | ||||
|| | | ++- Frequency/Rate:
|| | ||++- Frequency/Rate:
|| | |       0 = 24000/1 = 24000 Hz
|| | ||      0 = 24000/6 = 4000 Hz
|| | |       1 = 24000/2 = 12000 Hz
|| | ||      1 = 24000/4 = 6000 Hz
|| | |       2 = 24000/4 = 6000 Hz
|| | ||      2 = 24000/2 = 12000 Hz
|| | |       3 = 24000/6 = 4000 Hz
|| | ||      3 = 24000/1 = 24000 Hz
|| | |+--- Hold: 0 = normal playback, 1 = hold
|| | +---- Repeat: 0 = one-shot, 1 = auto-repeat
|| | +---- Repeat: 0 = one-shot, 1 = auto-repeat
|| +------ Target:
|| +------ Target:

Revision as of 14:14, 1 September 2023

The WonderSwan Color introduced two DMA blocks:

  • General DMA (GDMA) - allowing for fast IRAM/ROM -> IRAM transfers,
  • Sound DMA (SDMA) - allowing for IRAM/ROM -> sound transfers in a much less CPU-intensive way than an interrupt.

General DMA

GDMA Source Address ($40, $41, $42)

23  bit  16 15  bit  8   7  bit  0
 ---- ----   ---- ----   ---- ----
 .... hhhh   llll llll   llll lll.
      ||||   |||| ||||   |||| |||
      ++++---++++-++++---++++-++++- Linear source address
                                    ($00000 - $FFFFE)

DMA allows source addresses which can be accessed with a 16-bit width and without waitstates; any attempt to access SRAM (8-bit width) or "slow" ROM ($A0 bit 3 set) will cause DMA to immediately return, even if in the middle of a transfer.

GDMA Destination Address ($44, $45)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 aaaa aaaa  aaaa aaa.
 |||| ||||  |||| |||
 ++++-++++--++++-+++-- Destination address in IRAM

GDMA allows destination addresses in IRAM.

GDMA Length ($46, $47)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 bbbb bbbb  bbbb bbb.
 |||| ||||  |||| |||
 ++++-++++--++++-+++-- Transfer length, in words
                       (if including bit 0: in bytes)

GDMA Control ($48)

7  bit  0
---- ----
ed.. ....
||
|+-------- Direction: 0 = increment, 1 = decrement
+--------- Enable DMA: 0 = off, 1 = on

The CPU is stalled immediately after General DMA is enabled. General DMA takes (5 + 2 * words) cycles to complete, where words is the number of words (2-bytes) transferred.

Sound DMA

Sound DMA is a specialized form of General DMA with a hard-coded destination and built-in timer logic. As such, all of the rules for GDMA apply to SDMA as well.

Due to its need to access the external cartridge bus, Sound DMA steals 7 cycles - the same amount of time GDMA would take for transferring one byte - every 128 cycles. These are always cycles {117, 118, 119, 120, 121, 122, 123} mod 128.

Sound DMA supports holding - if enabled, the offset/length counters will be paused, allowing for resuming without losing auto-repeat state. The DMA cycles still occur, but they write $00 to the target port instead of the in-memory value.

While General DMA uses word access, Sound DMA uses byte access. This means that SRAM is supported as an input source. Also unlike General DMA, streaming from "slow" (>1 cycle) locations is supported; doing so lengthens Sound DMA by the difference.

SDMA Source Address ($4A, $4B, $4C)

23  bit  16 15  bit  8   7  bit  0
 ---- ----   ---- ----   ---- ----
 .... hhhh   llll llll   llll llll
      ||||   |||| ||||   |||| ||||
      ++++---++++-++++---++++-++++- Linear source address
                                  ($00000 - $FFFFF)

SDMA Length ($4E, $4F, $50)

23  bit  16 15  bit  8   7  bit  0
 ---- ----   ---- ----   ---- ----
 .... hhhh   llll llll   llll llll
      ||||   |||| ||||   |||| ||||
      ++++---++++-++++---++++-++++- Transfer length, in bytes

SDMA Control ($52)

7  bit  0
---- ----
ed.t rhff
|| | ||||
|| | ||++- Frequency/Rate:
|| | ||      0 = 24000/6 =  4000 Hz
|| | ||      1 = 24000/4 =  6000 Hz
|| | ||      2 = 24000/2 = 12000 Hz
|| | ||      3 = 24000/1 = 24000 Hz
|| | |+--- Hold: 0 = normal playback, 1 = hold
|| | +---- Repeat: 0 = one-shot, 1 = auto-repeat
|| +------ Target:
||           0 = Channel 2 (port $89)
||           1 = Hyper Voice
|+-------- Direction: 0 = increment, 1 = decrement
+--------- Enable DMA: 0 = off, 1 = on