1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - SND - demos - channel
3   File:     main.c
4 
5   Copyright 2007-2008 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2008-09-18#$
14   $Rev: 8573 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 #ifdef SDK_TWL
18 #include <twl.h>
19 #else
20 #include <nitro.h>
21 #endif
22 
23 #include "organ_det.g3.pcm16.h"
24 #include "wihaho.pcm16.h"
25 
26 // Macro to calculate PSG frequency
27 #define FreqToTimer(freq) (SND_TIMER_CLOCK / ( 8 * (freq) ))
28 #define KeyToTimer(key) (SND_CalcTimer(FreqToTimer(440), ((key)-69)*64))
29 
30 #define PCM_PLAY_CHANNEL1   4
31 #define PCM_PLAY_CHANNEL2   5
32 #define PSG_PLAY_CHANNEL    8
33 #define NOISE_PLAY_CHANNEL  14
34 
35 #define CENTER_PAN 64
36 
37 u16     Cont;
38 u16     Trg;
39 u8      key = 60;
40 
41 void    VBlankIntr(void);
42 
43 /*---------------------------------------------------------------------------*
44   Name:         NitroMain
45 
46   Description:  Main.
47 
48   Arguments:    None.
49 
50   Returns:      None.
51  *---------------------------------------------------------------------------*/
NitroMain()52 void NitroMain()
53 {
54     // Initialization
55     OS_Init();
56     GX_Init();
57     SND_Init();
58 
59     // V-Blank interrupt settings
60     OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
61     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
62     (void)OS_EnableIrq();
63     (void)GX_VBlankIntr(TRUE);
64 
65     // Print usage
66     OS_Printf("=================================\n");
67     OS_Printf("USAGE:\n");
68     OS_Printf(" A, B, X, Y : start sound\n");
69     OS_Printf(" START : stop sound\n");
70     OS_Printf("=================================\n");
71 
72     // Lock the channel
73     SND_LockChannel((1 << PCM_PLAY_CHANNEL1) | (1 << PCM_PLAY_CHANNEL2) | (1 << PSG_PLAY_CHANNEL) |
74                     (1 << NOISE_PLAY_CHANNEL), 0);
75 
76     while (1)
77     {
78         u16     ReadData;
79 
80         OS_WaitVBlankIntr();
81 
82         // Receive ARM7 command reply
83         while (SND_RecvCommandReply(SND_COMMAND_NOBLOCK) != NULL)
84         {
85         }
86 
87         ReadData = PAD_Read();
88         Trg = (u16)(ReadData & (ReadData ^ Cont));
89         Cont = ReadData;
90 
91         // Play PCM
92         if (Trg & PAD_BUTTON_A)
93         {
94             SND_SetupChannelPcm(PCM_PLAY_CHANNEL1,
95                                 ORGAN_DET_G3_PCM16_FORMAT,
96                                 organ_det_g3_pcm16,
97                                 ORGAN_DET_G3_PCM16_LOOPFLAG ? SND_CHANNEL_LOOP_REPEAT :
98                                 SND_CHANNEL_LOOP_1SHOT, ORGAN_DET_G3_PCM16_LOOPSTART,
99                                 ORGAN_DET_G3_PCM16_LOOPLEN, 127, SND_CHANNEL_DATASHIFT_NONE,
100                                 SND_CalcTimer(ORGAN_DET_G3_PCM16_TIMER, ((key) - 67) * 64),
101                                 CENTER_PAN);
102             SND_StartTimer(1 << PCM_PLAY_CHANNEL1, 0, 0, 0);
103         }
104 
105         if (Trg & PAD_BUTTON_B)
106         {
107             SND_SetupChannelPcm(PCM_PLAY_CHANNEL2,
108                                 WIHAHO_PCM16_FORMAT,
109                                 wihaho_pcm16,
110                                 WIHAHO_PCM16_LOOPFLAG ? SND_CHANNEL_LOOP_REPEAT :
111                                 SND_CHANNEL_LOOP_1SHOT, WIHAHO_PCM16_LOOPSTART,
112                                 WIHAHO_PCM16_LOOPLEN, 127, SND_CHANNEL_DATASHIFT_NONE,
113                                 WIHAHO_PCM16_TIMER, CENTER_PAN);
114             SND_StartTimer(1 << PCM_PLAY_CHANNEL2, 0, 0, 0);
115         }
116 
117         // Plays the PSG square wave
118         if (Trg & PAD_BUTTON_X)
119         {
120             SND_SetupChannelPsg(PSG_PLAY_CHANNEL,
121                                 SND_DUTY_4_8,
122                                 64, SND_CHANNEL_DATASHIFT_NONE, KeyToTimer(key), CENTER_PAN);
123             SND_StartTimer(1 << PSG_PLAY_CHANNEL, 0, 0, 0);
124         }
125 
126         // Plays noise
127         if (Trg & PAD_BUTTON_Y)
128         {
129             SND_SetupChannelNoise(NOISE_PLAY_CHANNEL,
130                                   64, SND_CHANNEL_DATASHIFT_NONE, KeyToTimer(key), CENTER_PAN);
131             SND_StartTimer(1 << NOISE_PLAY_CHANNEL, 0, 0, 0);
132         }
133 
134         // Stop
135         if (Trg & PAD_BUTTON_START)
136         {
137             SND_StopTimer((1 << PCM_PLAY_CHANNEL1) | (1 << PCM_PLAY_CHANNEL2) |
138                           (1 << PSG_PLAY_CHANNEL) | (1 << NOISE_PLAY_CHANNEL), 0, 0, 0);
139         }
140 
141         // Raises the playback a half-step
142         if (Trg & PAD_KEY_UP)
143         {
144             key++;
145             SND_SetChannelTimer(1 << PCM_PLAY_CHANNEL1,
146                                 SND_CalcTimer(ORGAN_DET_G3_PCM16_TIMER, ((key) - 67) * 64));
147             SND_SetChannelTimer((1 << PSG_PLAY_CHANNEL) | (1 << NOISE_PLAY_CHANNEL),
148                                 KeyToTimer(key));
149             OS_Printf("key: %d\n", key);
150         }
151 
152         // Lowers the playback a half-step
153         if (Trg & PAD_KEY_DOWN)
154         {
155             key--;
156             SND_SetChannelTimer(1 << PCM_PLAY_CHANNEL1,
157                                 SND_CalcTimer(ORGAN_DET_G3_PCM16_TIMER, ((key) - 67) * 64));
158             SND_SetChannelTimer((1 << PSG_PLAY_CHANNEL) | (1 << NOISE_PLAY_CHANNEL),
159                                 KeyToTimer(key));
160             OS_Printf("key: %d\n", key);
161         }
162 
163         // Command flush
164         (void)SND_FlushCommand(SND_COMMAND_NOBLOCK);
165     }
166 }
167 
168 //--------------------------------------------------------------------------------
169 //    V-Blank interrupt process
170 //
VBlankIntr(void)171 void VBlankIntr(void)
172 {
173     OS_SetIrqCheckFlag(OS_IE_V_BLANK); // Checking V-Blank interrupt
174 }
175