Non-blocking DMA

From WikiPrizm
Revision as of 15:40, 2 August 2014 by Gbl08ma (talk | contribs)
Jump to navigationJump to search

This function allows you to perform calculations while drawing to the screen. This should increase frame rate, for certain applications. It is based on an assembly function found in Simon's documentation. I rewrote it in C.

#define LCD_GRAM 0x202
#define LCD_BASE	0xB4000000
#define VRAM_ADDR 0xA8000000
#define SYNCO() __asm__ volatile("SYNCO\n\t":::"memory");
// Module Stop Register 0
#define MSTPCR0	(volatile unsigned *)0xA4150030
// DMA0 operation register
#define DMA0_DMAOR	(volatile unsigned short*)0xFE008060
#define DMA0_SAR_0	(volatile unsigned *)0xFE008020
#define DMA0_DAR_0  (volatile unsigned *)0xFE008024
#define DMA0_TCR_0	(volatile unsigned *)0xFE008028
#define DMA0_CHCR_0	(volatile unsigned *)0xFE00802C
void DmaWaitNext(void){
		if((*DMA0_DMAOR)&4)//Address error has occured stop looping
		if((*DMA0_CHCR_0)&2)//Transfer is done

void DoDMAlcdNonblock(void){

	*MSTPCR0&=~(1<<21);//Clear bit 21
	*DMA0_CHCR_0&=~1;//Disable DMA on channel 0
	*DMA0_DMAOR=0;//Disable all DMA
	*DMA0_SAR_0=VRAM_ADDR&0x1FFFFFFF;//Source address is VRAM
	*DMA0_DAR_0=LCD_BASE&0x1FFFFFFF;//Desination is LCD
	*DMA0_TCR_0=(216*384)/16;//Transfer count bytes/32
	*DMA0_DMAOR|=1;//Enable DMA on all channels
	*DMA0_DMAOR&=~6;//Clear flags
	*DMA0_CHCR_0|=1;//Enable channel0 DMA

As you can see, there are two functions. Call DoDMAlcdNonblock() to start a transfer and DmaWaitNext() before doing another transfer.