#pragma once /* * This file is part of open_agb_firm * Copyright (C) 2021 derrek, profi200 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "types.h" #include "mem_map.h" #include "util.h" #define NDMA_REGS_BASE (IO_MEM_ARM9_ONLY + 0x2000) #define REG_NDMA_GCNT *((vu32*)NDMA_REGS_BASE) // Global control. // Note: The channel regs are offset by 4 (REG_NDMA_GLOBAL_CNT). typedef struct { vu32 sad; // 0x00 Source address. vu32 dad; // 0x04 Destination address. vu32 tcnt; // 0x08 Total repeat length in words. vu32 wcnt; // 0x0C Logical block size in words. vu32 bcnt; // 0x10 Block transfer timing/interval. vu32 fdata; // 0x14 Fill data. vu32 cnt; // 0x18 Control. } NdmaCh; static_assert(offsetof(NdmaCh, cnt) == 0x18, "Error: Member cnt of NdmaCh is not at offset 0x18!"); ALWAYS_INLINE NdmaCh* getNdmaChRegs(u8 c) { return &((NdmaCh*)(NDMA_REGS_BASE + 4))[c]; } // REG_NDMA_GCNT #define NDMA_REG_READBACK (1u) // Show internal state on REG_NDMAx_SAD/DAD/TCNT/WCNT. 3DS mode only. #define NDMA_ROUND_ROBIN(n) (1u<<31 | (intLog2(n) + 1)<<16) // DSP DMA/CPU cycles (power of 2). Maximum 16384. #define NDMA_HIGHEST_PRIO (0u) // REG_NDMA_BCNT // TODO: When is the delay happening during transfers? // TODO: Does NDMA run at 67 MHz in 3DS mode? We will assume so for now. #define NDMA_CYCLES(n) (n) // Maximum 65535. 0 means no delay/interval. #define NDMA_PRESCALER_1 (0u) // 67027964 Hz. #define NDMA_PRESCALER_4 (1u<<16) // 16756991 Hz. #define NDMA_PRESCALER_16 (2u<<16) // 4189247.75 Hz. #define NDMA_PRESCALER_64 (3u<<16) // 1047311.9375 Hz. #define NDMA_FASTEST (NDMA_PRESCALER_1 | NDMA_CYCLES(0)) // Convenience macro. // REG_NDMA_CNT #define NDMA_DAD_INC (0u) // Destination address increment. #define NDMA_DAD_DEC (1u<<10) // Destination address decrement. #define NDMA_DAD_FIX (2u<<10) // Destination address fixed. #define NDMA_DAD_RELOAD (1u<<12) // Reload destination address on logical block end (REG_NDMAx_WCNT). #define NDMA_SAD_INC (0u) // Source address increment. #define NDMA_SAD_DEC (1u<<13) // Source address decrement. #define NDMA_SAD_FIX (2u<<13) // Source address fixed. #define NDMA_SAD_FILL (3u<<13) // Source is REG_NDMAx_FDATA. #define NDMA_SAD_RELOAD (1u<<15) // Reload source address on logical block end (REG_NDMAx_WCNT). #define NDMA_BURST_SHIFT (16u) #define NDMA_BURST(n) (intLog2(n)<