#4817 - rome - Thu Apr 10, 2003 8:00 pm
i?m currently coding a GBA Sound engine and i?m having a problem: i used DMA and a sound buffer to fill with sounds. DMA is always reading data from sound buffer. But when dma must be restarted to read again the sound buffer, a noise garbage is audible.
there is a problem when restart DMA in timer 1 interrupt?
when sound is filled into the buffer, the noise is louder
here is my code:
this code is very simple, and can be compiled to test.
the code fill buffer with data 22 and make dma to play it forever.
when timer 1 is triggered, DMA restart to original source position and begins. then noise can be hearded.
thanks so much!!!
there is a problem when restart DMA in timer 1 interrupt?
when sound is filled into the buffer, the noise is louder
here is my code:
Code: |
///////////////Interrupts///////////////////////////// #define INT_TIMER0 0x0008 #define INT_TIMER1 0x0010 // Sound Buffer Size #define SOUND_BUFFER_SIZE 1024 // prototype void InterruptProcess(void) __attribute__ ((section (".iwram"), long_call)); // struct to initialize sound parameters typedef struct stSountCntH { int Ch1to4OutputRatio : 2; int DSndAOutRatio : 1; int DSndBOutRatio : 1; int unused : 4; int EnableDSndAToRightSpeaker : 1; int EnableDSndAToLeftSpeaker : 1; int DSndASampleRateTimer : 1; int DSndAFIFOReset : 1; int EnableDSndBToRightSpeaker : 1; int EnableDSndBToLeftSpeaker : 1; int DSndBSampleRateTimer : 1; int DSndBFIFOReset : 1; }SountCntH; // gbasound device class class WGBASoundDevice { public: s8 SoundBuffer[SOUND_BUFFER_SIZE]; // Sound Buffer volatile u32 BufferPos; // buffer Pos int Initialize(); // init sound device }; // Sound Device Global variable WGBASoundDevice SndDev __attribute__ ((section (".ewram"))); //---------------------------------------------------------------------------- // Name: Interrupt Handler // Desc: // Pams: //---------------------------------------------------------------------------- void InterruptProcess() { if(REG_IF & INT_TIMER1) // end of buffer { // disable DMA REG_DM1CNT_H &= 0x7FFF; // reset DMA Source // HERE MUST BE THE PROBLEM!!! REG_DM1SAD = (unsigned long)SndDev.SoundBuffer; // enable DMA REG_DM1CNT_H |= 0x8000; // reset sound buffer pos SndDev.BufferPos = 0; } else if(REG_IF & INT_TIMER0) // enter here at 16Khz { // inc sound buffer pos SndDev.BufferPos++; } REG_IF |= REG_IF; } //---------------------------------------------------------------------------- // Name: Initialize() // Desc: Initialize GBASound (timers, etc...) // Pams: //---------------------------------------------------------------------------- int WGBASoundDevice::Initialize() { SountCntH snd_ctrl; snd_ctrl.Ch1to4OutputRatio = 0; snd_ctrl.DSndAOutRatio = 1; // 100% snd_ctrl.DSndBOutRatio = 0; snd_ctrl.unused = 0; snd_ctrl.EnableDSndAToRightSpeaker = 1; snd_ctrl.EnableDSndAToLeftSpeaker = 1; snd_ctrl.DSndASampleRateTimer = 0; //Timer 0 snd_ctrl.DSndAFIFOReset = 1; snd_ctrl.EnableDSndBToRightSpeaker = 0; snd_ctrl.EnableDSndBToLeftSpeaker = 0; snd_ctrl.DSndBSampleRateTimer = 0; // Timer 0 snd_ctrl.DSndBFIFOReset = 0; // reset sound buffer pos BufferPos = 0; REG_SGCNT0_H = *(u16*) &snd_ctrl; // init sound parameters REG_SGCNT1 = 0x80; //turn sound chip on // Initialize DMA channel REG_DM1CNT_L = 0; REG_DM1SAD = (unsigned long)SoundBuffer; REG_DM1DAD = 0x040000a0; // set dest in FIFO A REG_DM1CNT_H = 0xB640; // init DMA: repeat, 32 bit, Enable // will be triggered when buffer reaches the end REG_TM1D = 0xFFFF - SOUND_BUFFER_SIZE; // Enable timer 1 + IRQ + cascade from timer 0; REG_TM1CNT = 0xC4; // Generete IRQ when buffer reaches the end // Enable IRQ for timer 0 and 1 REG_IE |= 0x18; // Enable Master IRQ REG_IME=1; //enable timer at CPU freq/1024 +irq =16384Khz sample rate REG_TM0D = 0xFFFF; REG_TM0CNT = 0x00C3; return 1; } // main routine int main(void) { REG_INTERUPT = (u32)InterruptProcess; // fill buffer with any data to increase NOISE // problem on Return of DMA to Read Buffer (22 is a stupid data) memset(SndDev.SoundBuffer,22,sizeof(char)*SOUND_BUFFER_SIZE); // initialize sound (timers and DMA) SndDev.Initialize(); while(1) { } return 0; } |
this code is very simple, and can be compiled to test.
the code fill buffer with data 22 and make dma to play it forever.
when timer 1 is triggered, DMA restart to original source position and begins. then noise can be hearded.
thanks so much!!!