From af05a2979f97d00eab36261374af1eaf2ac3c833 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 27 Apr 2021 12:36:28 +0200 Subject: Add DMA control macros and small memory copy test --- src/common.h | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'src/common.h') diff --git a/src/common.h b/src/common.h index 669fb6e..e3405be 100644 --- a/src/common.h +++ b/src/common.h @@ -305,6 +305,7 @@ unpack_1bb(u8 hex) { } // Unpack N tiles packed at 1bpp. +static inline void unpack_tiles(u32 *src, u32 *dst, size_t n_tiles) { u32 *target_src = src + n_tiles * 2; while (src != target_src) { @@ -316,4 +317,72 @@ unpack_tiles(u32 *src, u32 *dst, size_t n_tiles) { } } +// +// Direct Memory Access (DMA) +// + + +// Source, destination, and control registers. +#define DMA_SRC(N) *((vu32*) 0x040000B0 + (N) * 12) +#define DMA_DST(N) *((vu32*) 0x040000B4 + (N) * 12) +#define DMA_CTRL(N) *((vu32*) 0x040000B8 + (N) * 12) + +// DMA control bits. +#define DMA_DST_INC (0 << 0x15) +#define DMA_DST_DEC (1 << 0x15) +#define DMA_DST_FIXED (2 << 0x15) +#define DMA_DST_RELOAD (3 << 0x15) +#define DMA_SRC_INC (0 << 0x17) +#define DMA_SRC_DEC (1 << 0x17) +#define DMA_SRC_FIXED (2 << 0x17) +#define DMA_REPEAT (1 << 0x19) +#define DMA_CHUNK_16 (0 << 0x1A) +#define DMA_CHUNK_32 (1 << 0x1A) +#define DMA_NOW (0 << 0x1C) +#define DMA_VBLANK (1 << 0x1C) +#define DMA_HBLANK (2 << 0x1C) +#define DMA_REFRESH (3 << 0x1C) +#define DMA_IRQ (1 << 0x1E) +#define DMA_ENABLE (1 << 0x1F) + +// Custom struct for cleaner DMA transfer functions. +typedef struct DmaStr { + const void *src; + void *dst; + u32 ctrl; +} DmaStr; + +#define DMA_TRANSFER ((volatile DmaStr*) 0x040000B0) + +// Transfer `count` number of chunks from src to dst using a DMA channel. Note +// that chunks are not bytes, but instead configured based on bits set by +// DMA_CTRL. +inline void +dma_transfer_copy(void *dst, const void *src, u32 count, int channel, u32 options) { + DMA_TRANSFER[channel].ctrl = 0; + DMA_TRANSFER[channel].src = src; + DMA_TRANSFER[channel].dst = dst; + DMA_TRANSFER[channel].ctrl = count | options; +} + +inline void +dma_transfer_fill(void *dst, volatile u32 src, u32 count, int channel, u32 options) { + DMA_TRANSFER[channel].ctrl = 0; + DMA_TRANSFER[channel].src = (const void *)&src; + DMA_TRANSFER[channel].dst = dst; + DMA_TRANSFER[channel].ctrl = count | options | DMA_SRC_FIXED; +} + +// Copy N number of bytes using a DMA channel. +inline void +dma_copy(void *dst, const void *src, u32 size, int channel) { + dma_transfer_copy(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE); +} + +// Fill the dst location with the word set at src. +inline void +dma_fill(void *dst, const void *src, u32 size, int channel) { + dma_transfer_fill(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE); +} + #endif // GBAEXP_COMMON_H -- cgit v1.2.1