#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)<