// // Test program for GBA devkitadv // #include "pwave.h" // 型情報 typedef unsigned char u8; typedef unsigned short u16; typedef unsigned long u32; typedef signed char s8; typedef signed short s16; typedef signed long s32; // 制御レジスタ情報 #define SND_ABCTRL 0x04000082 #define SND_SWITCH 0x04000084 #define SND_CHAFIFO 0x040000A0 #define SND_CHBFIFO 0x040000A4 #define DMA1_SRCAD 0x040000BC #define DMA1_DSTAD 0x040000C0 #define DMA1_COUNT 0x040000C4 #define DMA1_CTRL 0x040000C6 #define TIMER0_COUNT 0x04000100 #define TIMER0_CTRL 0x04000102 #define TIMER1_COUNT 0x04000104 #define TIMER1_CTRL 0x04000106 #define TIMER2_COUNT 0x04000108 #define TIMER2_CTRL 0x0400010A #define TIMER3_COUNT 0x0400010C #define TIMER3_CTRL 0x0400010E #define KEY_INPUT 0x04000130 #define KEY_INTERRUPT 0x04000132 #define INT_IE 0x04000200 #define INT_IF 0x04000202 #define INT_IME 0x04000208 #define register(p) *((u16*) p) #define register4(p) *((u32*) p) #define KEY_A 0x0001 #define KEY_B 0x0002 #define KEY_SELECT 0x0004 #define KEY_START 0x0008 #define KEY_RIGHT 0x0010 #define KEY_LEFT 0x0020 #define KEY_UP 0x0040 #define KEY_DOWN 0x0080 #define KEY_R 0x0100 #define KEY_L 0x0200 #define KEY_INTEN 0x4000 #define KEY_INTAND 0x8000 #define TIM_PRESCALAR0 0x0000 // about 60 ns #define TIM_PRESCALAR1 0x0001 // about 380 ns #define TIM_PRESCALAR2 0x0002 // about 15300 ns #define TIM_PRESCALAR3 0x0003 // about 61000 ns #define TIM_CASCADE 0x0004 #define TIM_INTEN 0x0040 #define TIM_ON 0x0080 #define INT_VBLANK 0x0001 #define INT_HBLANK 0x0002 #define INT_VCOUNT 0x0004 #define INT_TIMER0 0x0008 #define INT_TIMER1 0x0010 #define INT_TIMER2 0x0020 #define INT_TIMER3 0x0040 #define INT_COMM 0x0080 #define INT_DMA0 0x0100 #define INT_DMA1 0x0200 #define INT_DMA2 0x0400 #define INT_DMA3 0x0800 #define INT_KEY 0x1000 #define INT_GAMEP 0x2000 #define SND_ALL_ON 0x0080 #define SND_CHARESET 0x0800 #define SND_CHATIMER0 0x0000 #define SND_CHATIMER1 0x0400 #define SND_CHALEFT 0x0200 #define SND_CHARIGHT 0x0100 #define SND_CHAHALF 0x0000 #define SND_CHAFULL 0x0004 #define SND_CHBRESET 0x8000 #define SND_CHBTIMER0 0x0000 #define SND_CHBTIMER1 0x4000 #define SND_CHBLEFT 0x2000 #define SND_CHBRIGHT 0x1000 #define SND_CHBHALF 0x0000 #define SND_CHBFULL 0x0008 #define DMA_DISABLE 0x0000 #define DMA_ENABLE 0x8000 #define DMA_INTEN 0x4000 #define DMA_STARTIMD 0x0000 #define DMA_STARTVBL 0x1000 #define DMA_STARTHBL 0x2000 #define DMA_STARTFIFO 0x3000 #define DMA_SIZE16 0x0000 #define DMA_SIZE32 0x0400 #define DMA_ONCE 0x0000 #define DMA_REPEAT 0x0200 #define DMA_SRCINC 0x0000 #define DMA_SRCDEC 0x0080 #define DMA_SRCFIX 0x0100 #define DMA_DSTINC 0x0000 #define DMA_DSTDEC 0x0020 #define DMA_DSTFIX 0x0040 #define DMA_DSTREL 0x0060 // 増加とリロード // マルチブート指定 int __gba_multiboot = 0; volatile u8 playing = 0; volatile u32 wave_count = 0; volatile u32 wave_size = 117156; volatile u32 wave_freq = 11000; void StopMusic(){ // 再生フラグをオフに playing = 0; // サウンドの設定をオフに register(SND_ABCTRL) = 0; // DMA1 停止 register(DMA1_CTRL) = 0; // タイマー0 停止 register(TIMER0_CTRL) = 0; // カウントを 0 に wave_count = 0; } void StartMusic() { int count; if(playing == 1){ // 再生中なら曲を停止 StopMusic(); } // サウンドを有効に register(SND_SWITCH) = SND_ALL_ON; // チャンネルAの設定 register(SND_ABCTRL) = SND_CHARESET | SND_CHATIMER0 | SND_CHALEFT | SND_CHARIGHT | SND_CHAFULL; // DMA転送元と先の設定 register4(DMA1_SRCAD) = (u32)pwave; register4(DMA1_DSTAD) = SND_CHAFIFO; // タイマーの設定 count = 16777216 / wave_freq; // 16777216 = 2^24 register(TIMER0_COUNT) = (u16)-count; // DMA転送の設定 register(DMA1_CTRL) = DMA_ENABLE | DMA_STARTFIFO | DMA_SIZE32 | DMA_REPEAT | DMA_SRCINC | DMA_DSTFIX; // タイマー0を開始 register(TIMER0_CTRL) = TIM_ON | TIM_INTEN | TIM_PRESCALAR0; // 再生フラグをオンに playing = 1; } void IRQ_Handler() { u16 Int_Flag; register(INT_IME) = 0; Int_Flag = register(INT_IF); if(Int_Flag & INT_KEY){ if((register(KEY_INPUT) & KEY_A) == 0){ StartMusic(); } if((register(KEY_INPUT) & KEY_B) == 0){ // DMA1 停止 register(DMA1_CTRL) = 0; // タイマー0 停止 register(TIMER0_CTRL) = 0; } } if(Int_Flag & INT_TIMER0){ if(playing == 1){ wave_count++; if(wave_count >= (wave_size - 20)){ StopMusic(); } if(playing == 0){ StartMusic(); } } } register(INT_IF) = Int_Flag; register(INT_IME) = 1; } void WaitForVsync(void) { while(*(volatile u16*)0x4000006 >= 160){}; while(*(volatile u16*)0x4000006 < 160){}; } // メインプログラム int main(void) { // サウンドの設定 register(SND_ABCTRL) = 0; // 割り込みの設定 register(INT_IME) = 0; *(u32*)0x03007FFC = (u32)IRQ_Handler; register(KEY_INTERRUPT) = KEY_INTEN | KEY_A | KEY_B; register(INT_IE) |= (INT_TIMER0 | INT_KEY); // 割り込み開始 register(INT_IME) = 1; // 無限ループ while(1){ // Vブランクまで待機 WaitForVsync(); } }