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:: 2010-05-17#$
14 $Rev: 11335 $
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
170 // When in NITRO mode, stopped by Panic
171 DEMOCheckRunOnTWL();
172
173 FS_Init(FS_DMA_NOT_USE);
174 SNDEX_Init();
175
176 // Initialize screen display
177 DEMOInitCommon();
178 DEMOInitVRAM();
179 DEMOInitDisplayBitmap();
180 DEMOHookConsole();
181 G3X_InitMtxStack();
182 DEMOSetBitmapTextColor(GX_RGBA(31, 31, 0, 1));
183 DEMOSetBitmapGroundColor(DEMO_RGB_CLEAR);
184 DEMOStartDisplay();
185
186 OS_TPrintf("A button: start DSP sampling\n");
187 OS_TPrintf("B button: stop DSP sampling\n");
188 OS_TPrintf("X button: pause rendering\n");
189 OS_TPrintf("Y button: play oneshot sound\n");
190 DEMOSetBitmapTextColor(GX_RGBA(31, 31, 31, 1));
191 DEMODrawText(0, 170, "--- DSP");
192 DEMOSetBitmapTextColor(GX_RGBA(31, 31, 0, 1));
193 DEMODrawText(0, 180, "--- MIC");
194 DEMOSetBitmapTextColor(GX_RGBA( 0, 31, 0, 1));
195 DEMODrawText(220, 5, "OLD");
196 DEMODrawText(220, 180, "NEW");
197
198 // Turn the microphone module power ON
199 (void)PM_SetAmp(PM_AMP_ON);
200
201 // Start the MIC library's autosampling
202 {
203 MIC_Init();
204 gMicAutoParam.type = MIC_SAMPLING_TYPE_12BIT;
205 gMicAutoParam.buffer = (void *)gMicData;
206 gMicAutoParam.size = TEST_BUFFER_SIZE;
207 gMicAutoParam.rate = MIC_SAMPLING_RATE_32730;
208 gMicAutoParam.loop_enable = TRUE;
209 gMicAutoParam.full_callback = NULL;
210 for (;;)
211 {
212 MICResult result = MIC_StartLimitedSampling(&gMicAutoParam);
213 if (result == MIC_RESULT_SUCCESS)
214 {
215 break;
216 }
217 else if ((result == MIC_RESULT_BUSY) || (result == MIC_RESULT_SEND_ERROR))
218 {
219 OS_Sleep(1);
220 }
221 else if (result == MIC_RESULT_ILLEGAL_STATUS)
222 {
223 OS_TWarning("Already started sampling.\n");
224 break;
225 }
226 else if (result == MIC_RESULT_ILLEGAL_PARAMETER)
227 {
228 OS_TWarning("Illegal parameter to start automatic sampling.\n");
229 break;
230 }
231 else
232 {
233 OS_TPanic("MIC_StartLimtedSampling() replied fatal error (%d).\n", result);
234 }
235 }
236 }
237
238 // Load the DSP components
239 // (Any component is fine, so we use G.711 here.)
240 {
241 (void)MI_FreeWram_B(MI_WRAM_ARM9);
242 (void)MI_CancelWram_B(MI_WRAM_ARM9);
243 (void)MI_FreeWram_C(MI_WRAM_ARM9);
244 (void)MI_CancelWram_C(MI_WRAM_ARM9);
245 (void)MI_FreeWram_B( MI_WRAM_ARM7 );
246 (void)MI_CancelWram_B( MI_WRAM_ARM7 );
247 (void)MI_FreeWram_C( MI_WRAM_ARM7 );
248 (void)MI_CancelWram_C( MI_WRAM_ARM7 );
249 {
250 FSFile file[1];
251 DSP_OpenStaticComponentG711(file);
252 if (!DSP_LoadG711(file, 0xFF, 0xFF))
253 {
254 OS_TPanic("can't allocate WRAM Slot");
255 }
256 }
257 }
258
259 // Prepare the PCM waveform for sound playback testing
260 {
261 FSFile file[1];
262 u32 chunk;
263 FS_InitFile(file);
264 if (!FS_OpenFileEx(file, "rom:/fanfare.32.wav", FS_FILEMODE_R) ||
265 !FS_SeekFile(file, 0x24, FS_SEEK_SET) ||
266 (FS_ReadFile(file, &chunk, 4) != 4) ||
267 (chunk != (('d'<<0)|('a'<<8)|('t'<<16) |('a'<<24))) ||
268 (FS_ReadFile(file, &gWavSize, 4) != 4) ||
269 (FS_ReadFile(file, gWavData, (s32)gWavSize) != gWavSize))
270 {
271 OS_TPanic("cannot prepare sample waveform!");
272 }
273 (void)FS_CloseFile(file);
274 DC_StoreRange(gWavData, gWavSize);
275 }
276
277 // Set DSP sound to 100%
278 (void)SNDEX_SetDSPMixRate(0);
279
280 // Main loop
281 for (;;)
282 {
283 static BOOL pauseRendering = FALSE;
284
285 DEMOReadKey();
286
287 // Start and stop DSP sampling with the A and B Buttons
288 if (DEMO_IS_TRIG(PAD_BUTTON_A))
289 {
290 DSP_StartSampling(gDspData, sizeof(gDspData));
291 }
292 if (DEMO_IS_TRIG(PAD_BUTTON_B))
293 {
294 DSP_StopSampling();
295 }
296 // Pause waveform rendering with the X Button
297 if (DEMO_IS_TRIG(PAD_BUTTON_X))
298 {
299 pauseRendering = !pauseRendering;
300 }
301 // Play sound with the Y Button
302 if (DEMO_IS_TRIG(PAD_BUTTON_Y))
303 {
304 DSP_PlaySound(gWavData, gWavSize, FALSE);
305 }
306
307 // For comparison's sake, get the MIC and DSP sampling position as simultaneously as possible
308 {
309 const u8 *dsp, *mic;
310
311 // No need to invalidate the cache because the CPU periodically synchronizes it with the DSP's internal sampling buffer
312 //
313 DSP_SyncSamplingBuffer();
314 dsp = (const u8 *)DSP_GetLastSamplingAddress();
315 mic = (const u8 *)MIC_GetLastSamplingAddress();
316 // Explicit synchronization is not needed with the MIC library because the ARM7 writes directly to main memory, but cache invalidation is needed
317 //
318 DC_InvalidateRange(gMicData, sizeof(gMicData));
319
320 // Render the most recent waveforms for both
321 if (!pauseRendering)
322 {
323 G3X_Reset();
324 G3_Identity();
325 G3_PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGONMODE_MODULATE, GX_CULL_NONE, 0, 31, 0);
326
327 {
328 u8 tmp[HW_LCD_HEIGHT * sizeof(u16)];
329 const u8 *src = gDspData;
330 MICSamplingType type = MIC_SAMPLING_TYPE_SIGNED_12BIT;
331 NormalizeRingBuffer(tmp, type, src, dsp - src);
332 DrawWaveGraph(type, GX_RGB(31, 31, 31), tmp);
333 }
334
335 if (mic != NULL)
336 {
337 u8 tmp[HW_LCD_HEIGHT * sizeof(u16)];
338 const u8 *src = gMicData;
339 MICSamplingType type = gMicAutoParam.type;
340 NormalizeRingBuffer(tmp, type, src, mic - src);
341 DrawWaveGraph(type, GX_RGB(31, 31, 0), tmp);
342 }
343
344 G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
345 }
346 }
347
348 DEMO_DrawFlip();
349 OS_WaitVBlankIntr();
350 }
351
352 OS_Terminate();
353 }
354