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:: 2009-09-24#$
14 $Rev: 11063 $
15 $Author: okubata_ryoma $
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 {
246 FSFile file[1];
247 DSP_OpenStaticComponentG711(file);
248 if (!DSP_LoadG711(file, 0xFF, 0xFF))
249 {
250 OS_TPanic("can't allocate WRAM Slot");
251 }
252 }
253 }
254
255 // Prepare the PCM waveform for sound playback testing
256 {
257 FSFile file[1];
258 u32 chunk;
259 FS_InitFile(file);
260 if (!FS_OpenFileEx(file, "rom:/fanfare.32.wav", FS_FILEMODE_R) ||
261 !FS_SeekFile(file, 0x24, FS_SEEK_SET) ||
262 (FS_ReadFile(file, &chunk, 4) != 4) ||
263 (chunk != (('d'<<0)|('a'<<8)|('t'<<16) |('a'<<24))) ||
264 (FS_ReadFile(file, &gWavSize, 4) != 4) ||
265 (FS_ReadFile(file, gWavData, (s32)gWavSize) != gWavSize))
266 {
267 OS_TPanic("cannot prepare sample waveform!");
268 }
269 (void)FS_CloseFile(file);
270 DC_StoreRange(gWavData, gWavSize);
271 }
272
273 // Set DSP sound to 100%
274 (void)SNDEX_SetDSPMixRate(0);
275
276 // Main loop
277 for (;;)
278 {
279 static BOOL pauseRendering = FALSE;
280
281 DEMOReadKey();
282
283 // Start and stop DSP sampling with the A and B Buttons
284 if (DEMO_IS_TRIG(PAD_BUTTON_A))
285 {
286 DSP_StartSampling(gDspData, sizeof(gDspData));
287 }
288 if (DEMO_IS_TRIG(PAD_BUTTON_B))
289 {
290 DSP_StopSampling();
291 }
292 // Pause waveform rendering with the X Button
293 if (DEMO_IS_TRIG(PAD_BUTTON_X))
294 {
295 pauseRendering = !pauseRendering;
296 }
297 // Play sound with the Y Button
298 if (DEMO_IS_TRIG(PAD_BUTTON_Y))
299 {
300 DSP_PlaySound(gWavData, gWavSize, FALSE);
301 }
302
303 // For comparison's sake, get the MIC and DSP sampling position as simultaneously as possible
304 {
305 const u8 *dsp, *mic;
306
307 // No need to invalidate the cache because the CPU periodically synchronizes it with the DSP's internal sampling buffer
308 //
309 DSP_SyncSamplingBuffer();
310 dsp = (const u8 *)DSP_GetLastSamplingAddress();
311 mic = (const u8 *)MIC_GetLastSamplingAddress();
312 // Explicit synchronization is not needed with the MIC library because the ARM7 writes directly to main memory, but cache invalidation is needed
313 //
314 DC_InvalidateRange(gMicData, sizeof(gMicData));
315
316 // Render the most recent waveforms for both
317 if (!pauseRendering)
318 {
319 G3X_Reset();
320 G3_Identity();
321 G3_PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGONMODE_MODULATE, GX_CULL_NONE, 0, 31, 0);
322
323 {
324 u8 tmp[HW_LCD_HEIGHT * sizeof(u16)];
325 const u8 *src = gDspData;
326 MICSamplingType type = MIC_SAMPLING_TYPE_SIGNED_12BIT;
327 NormalizeRingBuffer(tmp, type, src, dsp - src);
328 DrawWaveGraph(type, GX_RGB(31, 31, 31), tmp);
329 }
330
331 if (mic != NULL)
332 {
333 u8 tmp[HW_LCD_HEIGHT * sizeof(u16)];
334 const u8 *src = gMicData;
335 MICSamplingType type = gMicAutoParam.type;
336 NormalizeRingBuffer(tmp, type, src, mic - src);
337 DrawWaveGraph(type, GX_RGB(31, 31, 0), tmp);
338 }
339
340 G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
341 }
342 }
343
344 DEMO_DrawFlip();
345 OS_WaitVBlankIntr();
346 }
347
348 OS_Terminate();
349 }
350