1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - DSP - demos.TWL - snd-mic
3 File: main.c
4
5 Copyright 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-12-08#$
14 $Rev: 9562 $
15 $Author: kitase_hirotake $
16 *---------------------------------------------------------------------------*/
17
18
19 #include <twl.h>
20 #include <twl/dsp.h>
21 #include <twl/dsp/common/g711.h>
22
23 #include <DEMO.h>
24
25
26 /*---------------------------------------------------------------------------*/
27 /* Constants */
28
29 #define TEST_BUFFER_SIZE (1024 * 32)
30 #define WAV_BUFFER_SIZE (1024 * 512)
31
32
33 /*---------------------------------------------------------------------------*/
34 /* Variables */
35
36 // Audio buffer for sound playback test
37 static u8 gWavData[WAV_BUFFER_SIZE] ATTRIBUTE_ALIGN(4);
38 static u32 gWavSize;
39
40 // Ring buffer for microphone sampling test
41 static u8 gDspData[TEST_BUFFER_SIZE] ATTRIBUTE_ALIGN(2);
42
43 // Control information for MIC library sampling run as comparison against DSP
44 static MICAutoParam gMicAutoParam;
45 static u8 gMicData[TEST_BUFFER_SIZE] ATTRIBUTE_ALIGN(HW_CACHE_LINE_SIZE);
46
47
48 /*---------------------------------------------------------------------------*/
49 /* Functions */
50
51 /*---------------------------------------------------------------------------*
52 Name: NormalizeRingBuffer
53
54 Description: Gets an amount of the newest ring buffer data equal to HW_LCD_HEIGHT samples.
55
56 Arguments: dst: Where the sample is to be stored
57 type: The MICSamplingType type indicating sample type
58 buffer: The starting address for the ring buffer where the sample is stored
59 position: The final sampling position (in bytes)
60
61 Returns: None.
62 *---------------------------------------------------------------------------*/
NormalizeRingBuffer(void * dst,MICSamplingType type,const void * buffer,int position)63 static void NormalizeRingBuffer(void *dst, MICSamplingType type, const void *buffer, int position)
64 {
65 const u8 *src = (const u8 *)buffer;
66 u8 *tmp = (u8 *)dst;
67 int smp = 1;
68 switch (type)
69 {
70 case MIC_SAMPLING_TYPE_8BIT:
71 case MIC_SAMPLING_TYPE_SIGNED_8BIT:
72 smp = sizeof(u8);
73 break;
74 case MIC_SAMPLING_TYPE_12BIT:
75 case MIC_SAMPLING_TYPE_12BIT_FILTER_OFF:
76 case MIC_SAMPLING_TYPE_SIGNED_12BIT:
77 case MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF:
78 smp = sizeof(u16);
79 break;
80 }
81 {
82 int max = TEST_BUFFER_SIZE / smp;
83 int ofs = (position / smp - (HW_LCD_HEIGHT - 1)) & (max - 1);
84 int pos = 0;
85 while (pos < HW_LCD_HEIGHT)
86 {
87 int n = MATH_MIN(HW_LCD_HEIGHT - pos, max - ofs);
88 MI_CpuCopy8(&src[ofs * smp], &tmp[pos * smp], (u32)(n * smp));
89 ofs = (ofs + n) & (max - 1);
90 pos += n;
91 }
92 }
93 }
94
95 /*---------------------------------------------------------------------------*
96 Name: DrawWaveGraph
97
98 Description: Renders waveforms with triangular polygons.
99
100 Arguments: type: The MICSamplingType type indicating sample type
101 color: Waveform color
102 buffer: Waveform array stored in the specified sample type
103
104 Returns: None.
105 *---------------------------------------------------------------------------*/
DrawWaveGraph(MICSamplingType type,GXRgb color,const void * buffer)106 static void DrawWaveGraph(MICSamplingType type, GXRgb color, const void *buffer)
107 {
108 int i;
109 int bits = 8;
110 BOOL isSigned = FALSE;
111 switch (type)
112 {
113 default:
114 case MIC_SAMPLING_TYPE_8BIT:
115 bits = 8, isSigned = FALSE;
116 break;
117 case MIC_SAMPLING_TYPE_SIGNED_8BIT:
118 bits = 8, isSigned = TRUE;
119 break;
120 case MIC_SAMPLING_TYPE_12BIT:
121 case MIC_SAMPLING_TYPE_12BIT_FILTER_OFF:
122 bits = 16, isSigned = FALSE;
123 break;
124 case MIC_SAMPLING_TYPE_SIGNED_12BIT:
125 case MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF:
126 bits = 16, isSigned = TRUE;
127 break;
128 }
129 for (i = 0; i < HW_LCD_HEIGHT - 1; ++i)
130 {
131 u8 cur8 = (u8)((bits == 8) ? ((const u8*)buffer)[i] : (((const u16*)buffer)[i] >> 8));
132 u8 nxt8 = (u8)((bits == 8) ? ((const u8*)buffer)[i + 1] : (((const u16*)buffer)[i + 1] >> 8));
133 int cur = isSigned ? (((s8)cur8) + 128) : cur8;
134 int nxt = isSigned ? (((s8)nxt8) + 128) : nxt8;
135 fx16 fsx = (fx16)(((cur - 128) * 0x1000) / 128);
136 fx16 fsy = (fx16)(((96 - i) * 0x1000) / 96);
137 fx16 fex = (fx16)(((nxt - 128) * 0x1000) / 128);
138 fx16 fey = (fx16)(((96 - i + 1) * 0x1000) / 96);
139 G3_Begin(GX_BEGIN_TRIANGLES);
140 {
141 G3_Color(color);
142 G3_Vtx(fsx, fsy, 0);
143 G3_Color(color);
144 G3_Vtx(fex, fey, 0);
145 G3_Color(color);
146 G3_Vtx(fsx, fsy, 1);
147 }
148 G3_End();
149 }
150 }
151
152 /*---------------------------------------------------------------------------*
153 Name: TwlMain
154
155 Description: Main
156
157 Arguments: None.
158
159 Returns: None.
160 *---------------------------------------------------------------------------*/
TwlMain(void)161 void TwlMain(void)
162 {
163 // OS initialization
164 OS_Init();
165 OS_InitTick();
166 OS_InitAlarm();
167 (void)OS_EnableIrq();
168 (void)OS_EnableInterrupts();
169 FS_Init(FS_DMA_NOT_USE);
170 SNDEX_Init();
171
172 // Initialize screen display
173 DEMOInitCommon();
174 DEMOInitVRAM();
175 DEMOInitDisplayBitmap();
176 DEMOHookConsole();
177 G3X_InitMtxStack();
178 DEMOSetBitmapTextColor(GX_RGBA(31, 31, 0, 1));
179 DEMOSetBitmapGroundColor(DEMO_RGB_CLEAR);
180 DEMOStartDisplay();
181
182 OS_TPrintf("A button: start DSP sampling\n");
183 OS_TPrintf("B button: stop DSP sampling\n");
184 OS_TPrintf("X button: pause rendering\n");
185 OS_TPrintf("Y button: play oneshot sound\n");
186 DEMOSetBitmapTextColor(GX_RGBA(31, 31, 31, 1));
187 DEMODrawText(0, 170, "--- DSP");
188 DEMOSetBitmapTextColor(GX_RGBA(31, 31, 0, 1));
189 DEMODrawText(0, 180, "--- MIC");
190 DEMOSetBitmapTextColor(GX_RGBA( 0, 31, 0, 1));
191 DEMODrawText(220, 5, "OLD");
192 DEMODrawText(220, 180, "NEW");
193
194 // Turn the microphone module power ON
195 (void)PM_SetAmp(PM_AMP_ON);
196
197 // Start the MIC library's autosampling
198 {
199 MIC_Init();
200 gMicAutoParam.type = MIC_SAMPLING_TYPE_12BIT;
201 gMicAutoParam.buffer = (void *)gMicData;
202 gMicAutoParam.size = TEST_BUFFER_SIZE;
203 gMicAutoParam.rate = MIC_SAMPLING_RATE_32730;
204 gMicAutoParam.loop_enable = TRUE;
205 gMicAutoParam.full_callback = NULL;
206 for (;;)
207 {
208 MICResult result = MIC_StartLimitedSampling(&gMicAutoParam);
209 if (result == MIC_RESULT_SUCCESS)
210 {
211 break;
212 }
213 else if ((result == MIC_RESULT_BUSY) || (result == MIC_RESULT_SEND_ERROR))
214 {
215 OS_Sleep(1);
216 }
217 else if (result == MIC_RESULT_ILLEGAL_STATUS)
218 {
219 OS_TWarning("Already started sampling.\n");
220 break;
221 }
222 else if (result == MIC_RESULT_ILLEGAL_PARAMETER)
223 {
224 OS_TWarning("Illegal parameter to start automatic sampling.\n");
225 break;
226 }
227 else
228 {
229 OS_TPanic("MIC_StartLimtedSampling() replied fatal error (%d).\n", result);
230 }
231 }
232 }
233
234 // Load the DSP components.
235 // (Any component is fine, so we use G.711 here.)
236 {
237 (void)MI_FreeWram_B(MI_WRAM_ARM9);
238 (void)MI_CancelWram_B(MI_WRAM_ARM9);
239 (void)MI_FreeWram_C(MI_WRAM_ARM9);
240 (void)MI_CancelWram_C(MI_WRAM_ARM9);
241 {
242 FSFile file[1];
243 DSP_OpenStaticComponentG711(file);
244 if (!DSP_LoadG711(file, 0xFF, 0xFF))
245 {
246 OS_TPanic("can't allocate WRAM Slot");
247 }
248 }
249 }
250
251 // Prepare the PCM waveform for sound playback testing
252 {
253 FSFile file[1];
254 u32 chunk;
255 FS_InitFile(file);
256 if (!FS_OpenFileEx(file, "rom:/fanfare.32.wav", FS_FILEMODE_R) ||
257 !FS_SeekFile(file, 0x24, FS_SEEK_SET) ||
258 (FS_ReadFile(file, &chunk, 4) != 4) ||
259 (chunk != (('d'<<0)|('a'<<8)|('t'<<16) |('a'<<24))) ||
260 (FS_ReadFile(file, &gWavSize, 4) != 4) ||
261 (FS_ReadFile(file, gWavData, (s32)gWavSize) != gWavSize))
262 {
263 OS_TPanic("cannot prepare sample waveform!");
264 }
265 (void)FS_CloseFile(file);
266 DC_StoreRange(gWavData, gWavSize);
267 }
268
269 // Set DSP sound to 100%
270 (void)SNDEX_SetDSPMixRate(0);
271
272 // Main loop
273 for (;;)
274 {
275 static BOOL pauseRendering = FALSE;
276
277 DEMOReadKey();
278
279 // Start and stop DSP sampling with the A and B Buttons
280 if (DEMO_IS_TRIG(PAD_BUTTON_A))
281 {
282 DSP_StartSampling(gDspData, sizeof(gDspData));
283 }
284 if (DEMO_IS_TRIG(PAD_BUTTON_B))
285 {
286 DSP_StopSampling();
287 }
288 // Pause waveform rendering with the X Button
289 if (DEMO_IS_TRIG(PAD_BUTTON_X))
290 {
291 pauseRendering = !pauseRendering;
292 }
293 // Play sound with the Y Button
294 if (DEMO_IS_TRIG(PAD_BUTTON_Y))
295 {
296 DSP_PlaySound(gWavData, gWavSize, FALSE);
297 }
298
299 // For comparison's sake, get the MIC and DSP sampling position as simultaneously as possible
300 {
301 const u8 *dsp, *mic;
302
303 // No need to invalidate the cache because the CPU periodically synchronizes it with the DSP's internal sampling buffer
304 //
305 DSP_SyncSamplingBuffer();
306 dsp = (const u8 *)DSP_GetLastSamplingAddress();
307 mic = (const u8 *)MIC_GetLastSamplingAddress();
308 // Explicit synchronization is not needed with the MIC library because the ARM7 writes directly to main memory, but cache invalidation is needed
309 //
310 DC_InvalidateRange(gMicData, sizeof(gMicData));
311
312 // Render the most recent waveforms for both
313 if (!pauseRendering)
314 {
315 G3X_Reset();
316 G3_Identity();
317 G3_PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGONMODE_MODULATE, GX_CULL_NONE, 0, 31, 0);
318
319 {
320 u8 tmp[HW_LCD_HEIGHT * sizeof(u16)];
321 const u8 *src = gDspData;
322 MICSamplingType type = MIC_SAMPLING_TYPE_SIGNED_12BIT;
323 NormalizeRingBuffer(tmp, type, src, dsp - src);
324 DrawWaveGraph(type, GX_RGB(31, 31, 31), tmp);
325 }
326
327 if (mic != NULL)
328 {
329 u8 tmp[HW_LCD_HEIGHT * sizeof(u16)];
330 const u8 *src = gMicData;
331 MICSamplingType type = gMicAutoParam.type;
332 NormalizeRingBuffer(tmp, type, src, mic - src);
333 DrawWaveGraph(type, GX_RGB(31, 31, 0), tmp);
334 }
335
336 G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
337 }
338 }
339
340 DEMO_DrawFlip();
341 OS_WaitVBlankIntr();
342 }
343
344 OS_Terminate();
345 }
346