1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - demos - spi - pmAmpGain
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-05-01#$
14 $Rev: 5860 $
15 $Author: terui $
16 *---------------------------------------------------------------------------*/
17
18 /*---------------------------------------------------------------------------*
19 A sample that controls the amplifier gain for microphone input.
20
21 USAGE:
22 UP, DOWN: Control amplifier gain
23
24 HOWTO:
25 1. Initialize MIC library.
26 2. Start auto sampling of MIC by default configuration.
27 3. When you change amplifier gain, you don't have to stop sampling.
28 *---------------------------------------------------------------------------*/
29
30 #ifdef SDK_TWL
31 #include <twl.h>
32 #else
33 #include <nitro.h>
34 #endif
35
36 /*---------------------------------------------------------------------------*
37 Constant Definitions
38 *---------------------------------------------------------------------------*/
39 #define TEST_BUFFER_SIZE (4 * 1024) // 4 KB
40 #define RETRY_MAX_COUNT 8
41
42 /*---------------------------------------------------------------------------*
43 Internal Function Definitions
44 *---------------------------------------------------------------------------*/
45 static void StepUpAmpGain(void);
46 static void StepDownAmpGain(void);
47 static u32 GetDefaultMicSamplingRate(void);
48 #ifdef SDK_TWL
49 static SNDEXFrequency GetI2SFrequency(void);
50 #endif
51 static void StartMicSampling(const MICAutoParam* param);
52
53 static void SetDrawData(void *address, MICSamplingType type);
54
55 static void VBlankIntr(void);
56 static void Init3D(void);
57 static void Draw3D(void);
58 static void DrawLine(s16 sx, s16 sy, s16 ex, s16 ey);
59
60 /*---------------------------------------------------------------------------*
61 Internal Variable Definitions
62 *---------------------------------------------------------------------------*/
63 static MICAutoParam gMicAutoParam;
64 static u8 gDrawData[192];
65 static u8 gMicData[TEST_BUFFER_SIZE] ATTRIBUTE_ALIGN(HW_CACHE_LINE_SIZE);
66
67 /*---------------------------------------------------------------------------*
68 Name: NitroMain / TwlMain
69
70 Description: Initialization and main loop.
71
72 Arguments: None.
73
74 Returns: None.
75 *---------------------------------------------------------------------------*/
76 #ifdef SDK_TWL
TwlMain(void)77 void TwlMain(void)
78 #else
79 void NitroMain(void)
80 #endif
81 {
82 /* Various types of initialization */
83 OS_Init();
84 GX_Init();
85 GX_DispOff();
86 GXS_DispOff();
87
88 /* Initializes display settings */
89 GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
90 MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
91 (void)GX_DisableBankForLCDC();
92 MI_CpuFillFast((void *)HW_OAM, GX_LCD_SIZE_Y, HW_OAM_SIZE);
93 MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
94 MI_CpuFillFast((void *)HW_DB_OAM, GX_LCD_SIZE_Y, HW_DB_OAM_SIZE);
95 MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
96
97 /* 3D-related initialization */
98 Init3D();
99
100 /* Interrupt settings */
101 OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
102 (void)OS_EnableIrqMask(OS_IE_V_BLANK);
103 (void)OS_EnableIrq();
104 (void)OS_EnableInterrupts();
105 (void)GX_VBlankIntr(TRUE);
106
107 /* Initialize related libraries */
108 {
109 (void)PM_SetAmp(PM_AMP_ON);
110 (void)PM_SetAmpGain(PM_AMPGAIN_80);
111
112 MIC_Init();
113 gMicAutoParam.type = MIC_SAMPLING_TYPE_8BIT;
114 gMicAutoParam.buffer = (void *)gMicData;
115 gMicAutoParam.size = TEST_BUFFER_SIZE;
116 gMicAutoParam.loop_enable = TRUE;
117 gMicAutoParam.full_callback = NULL;
118 gMicAutoParam.rate = GetDefaultMicSamplingRate();
119 StartMicSampling((const MICAutoParam *)&gMicAutoParam);
120 }
121
122 /* Initialize internal variables */
123 MI_CpuFill8(gDrawData, 0x80, sizeof(gDrawData));
124
125 /* LCD display start */
126 GX_DispOn();
127 GXS_DispOn();
128
129 /* Debug string output */
130 OS_Printf("pmAmpGain demo started.\n");
131 OS_Printf(" up/down -> change amplifier gain\n");
132 OS_Printf("\n");
133
134 /* Empty call for getting key input data (strategy for pressing A button in the IPL) */
135 (void)PAD_Read();
136
137 {
138 u16 keyOld = 0;
139 u16 keyTrg;
140 u16 keyNow;
141
142 /* Main loop */
143 while (TRUE)
144 {
145 /* Get key input data */
146 keyNow = PAD_Read();
147 keyTrg = (u16)((keyOld ^ keyNow) & keyNow);
148 keyOld = keyNow;
149
150 /* Change the amp gain */
151 if (keyTrg & PAD_KEY_UP)
152 {
153 StepUpAmpGain();
154 }
155 if (keyTrg & PAD_KEY_DOWN)
156 {
157 StepDownAmpGain();
158 }
159
160 /* Render waveform */
161 SetDrawData(MIC_GetLastSamplingAddress(), gMicAutoParam.type);
162 Draw3D();
163
164 /* Waiting for the V-Blank */
165 OS_WaitVBlankIntr();
166 }
167 }
168 }
169
170 /*---------------------------------------------------------------------------*
171 Name: StepDownAmpGain
172
173 Description: Raises the amp gain by one level.
174
175 Arguments: None.
176
177 Returns: None.
178 *---------------------------------------------------------------------------*/
179 static void
StepUpAmpGain(void)180 StepUpAmpGain(void)
181 {
182 PMAmpGain gain;
183
184 if (PM_GetAmpGain(&gain) == PM_RESULT_SUCCESS)
185 {
186 switch (gain)
187 {
188 case PM_AMPGAIN_20:
189 gain = PM_AMPGAIN_40;
190 break;
191 case PM_AMPGAIN_40:
192 gain = PM_AMPGAIN_80;
193 break;
194 case PM_AMPGAIN_80:
195 gain = PM_AMPGAIN_160;
196 break;
197 default:
198 return;
199 }
200 if (PM_SetAmpGain(gain) == PM_RESULT_SUCCESS)
201 {
202 OS_Printf("Amplifier gain was changed to %d\n", gain);
203 }
204 }
205 }
206
207 /*---------------------------------------------------------------------------*
208 Name: StepDownAmpGain
209
210 Description: Lowers the amp gain by one level.
211
212 Arguments: None.
213
214 Returns: None.
215 *---------------------------------------------------------------------------*/
216 static void
StepDownAmpGain(void)217 StepDownAmpGain(void)
218 {
219 PMAmpGain gain;
220
221 if (PM_GetAmpGain(&gain) == PM_RESULT_SUCCESS)
222 {
223 switch (gain)
224 {
225 case PM_AMPGAIN_40:
226 gain = PM_AMPGAIN_20;
227 break;
228 case PM_AMPGAIN_80:
229 gain = PM_AMPGAIN_40;
230 break;
231 case PM_AMPGAIN_160:
232 gain = PM_AMPGAIN_80;
233 break;
234 default:
235 return;
236 }
237 if (PM_SetAmpGain(gain) == PM_RESULT_SUCCESS)
238 {
239 OS_Printf("Amplifier gain was changed to %d\n", gain);
240 }
241 }
242 }
243
244 /*---------------------------------------------------------------------------*
245 Name: GetDefaultMicSamplingRate
246
247 Description: Determines the sampling rate for the microphone's auto-sampling.
248
249 Arguments: None.
250
251 Returns: u32: Returns an appropriate sampling rate.
252 *---------------------------------------------------------------------------*/
253 static u32
GetDefaultMicSamplingRate(void)254 GetDefaultMicSamplingRate(void)
255 {
256 #ifdef SDK_TWL
257 if ((OS_IsRunOnTwl() == TRUE) && (GetI2SFrequency() == SNDEX_FREQUENCY_47610))
258 {
259 return MIC_SAMPLING_RATE_15870;
260 }
261 else
262 {
263 return MIC_SAMPLING_RATE_16360;
264 }
265 #else
266 return MIC_SAMPLING_RATE_16K;
267 #endif
268 }
269
270 #ifdef SDK_TWL
271 #include <twl/ltdmain_begin.h>
272 /*---------------------------------------------------------------------------*
273 Name: GetI2SFrequency
274
275 Description: Gets the I2S operating frequency.
276
277 Arguments: None.
278
279 Returns: SDNEXFrequency: Returns the I2S operating frequency.
280 *---------------------------------------------------------------------------*/
281 static SNDEXFrequency
GetI2SFrequency(void)282 GetI2SFrequency(void)
283 {
284 SNDEXResult result;
285 SNDEXFrequency freq;
286 s32 retry = 0;
287
288 SNDEX_Init();
289 while (TRUE)
290 {
291 result = SNDEX_GetI2SFrequency(&freq);
292 switch (result)
293 {
294 case SNDEX_RESULT_SUCCESS: // Success
295 return freq;
296 case SNDEX_RESULT_EXCLUSIVE: // Exclusion error
297 case SNDEX_RESULT_PXI_SEND_ERROR: // PXI queue is full
298 if (++ retry <= RETRY_MAX_COUNT)
299 {
300 OS_Sleep(1);
301 continue;
302 }
303 OS_TWarning("%s: Retry count overflow.\n", __FUNCTION__);
304 break;
305 case SNDEX_RESULT_BEFORE_INIT: // Pre-initialization
306 case SNDEX_RESULT_ILLEGAL_STATE: // Abnormal state
307 OS_TWarning("%s: Illegal state to get I2S frequency.\n", __FUNCTION__);
308 break;
309 case SNDEX_RESULT_FATAL_ERROR: // Fatal error
310 default: // Other fatal error
311 OS_Panic("Fatal error (%d).\n", result);
312 /* Never return */
313 }
314 }
315 return SNDEX_FREQUENCY_32730;
316 }
317 #include <twl/ltdmain_end.h>
318 #endif
319
320 /*---------------------------------------------------------------------------*
321 Name: StartMicSampling
322
323 Description: Calls the microphone auto-sampling start function and performs error handling.
324
325 Arguments: param: Parameters passed to the mic API functions
326
327 Returns: None.
328 *---------------------------------------------------------------------------*/
329 static void
StartMicSampling(const MICAutoParam * param)330 StartMicSampling(const MICAutoParam* param)
331 {
332 MICResult result;
333 s32 retry = 0;
334
335 while (TRUE)
336 {
337 #ifdef SDK_TWL
338 result = MIC_StartLimitedSampling(param);
339 #else
340 result = MIC_StartAutoSampling(param);
341 #endif
342 switch (result)
343 {
344 case MIC_RESULT_SUCCESS: // Success
345 return;
346 case MIC_RESULT_BUSY: // Another thread is using the microphone
347 case MIC_RESULT_SEND_ERROR: // PXI queue is full
348 if (++retry <= RETRY_MAX_COUNT)
349 {
350 OS_Sleep(1);
351 continue;
352 }
353 OS_TWarning("%s: Retry count overflow.\n", __FUNCTION__);
354 return;
355 case MIC_RESULT_ILLEGAL_STATUS: // Auto-sampling is not currently paused
356 OS_TWarning("%s: Already started sampling.\n", __FUNCTION__);
357 return;
358 case MIC_RESULT_ILLEGAL_PARAMETER: // Unsupported parameter
359 OS_TWarning("%s: Illegal parameter to start automatic sampling.\n", __FUNCTION__);
360 return;
361 default: // Other fatal error
362 OS_Panic("Fatal error (%d).\n", result);
363 /* Never return */
364 }
365 }
366 }
367
368 /*---------------------------------------------------------------------------*
369 Name: SetDrawData
370
371 Description: Stores the current newest sampled data in the buffer that puts it on the display.
372
373
374 Arguments: address: Location in main memory where the most recent sampling data was stored by the component
375
376 type: Sampling type (bit width)
377
378 Returns: None.
379 *---------------------------------------------------------------------------*/
SetDrawData(void * address,MICSamplingType type)380 static void SetDrawData(void *address, MICSamplingType type)
381 {
382 s32 i;
383
384 /* If sampling has never been performed, do nothing and stop.
385 (Because it would delete memory cache(s) unrelated to the microphone) */
386 if ((address < gMicData) || (address >= (gMicData + TEST_BUFFER_SIZE)))
387 {
388 return;
389 }
390
391 switch (type)
392 {
393 case MIC_SAMPLING_TYPE_8BIT:
394 case MIC_SAMPLING_TYPE_SIGNED_8BIT:
395 /* In the case of 8-bit sampling */
396 {
397 u8 *p;
398
399 p = (u8 *)((u32)address - 191);
400 if (p < gMicData)
401 {
402 p = (u8 *)((u32)p + TEST_BUFFER_SIZE);
403 }
404 DC_InvalidateRange((void *)((u32)p & ~(HW_CACHE_LINE_SIZE - 1)), HW_CACHE_LINE_SIZE);
405 for (i = 0; i < 192; i++)
406 {
407 gDrawData[i] = *p;
408 p++;
409 if ((u32)p >= (u32)(gMicData + TEST_BUFFER_SIZE))
410 {
411 p -= TEST_BUFFER_SIZE;
412 }
413 if (((u32)p % HW_CACHE_LINE_SIZE) == 0)
414 {
415 DC_InvalidateRange(p, HW_CACHE_LINE_SIZE);
416 }
417 }
418 }
419 break;
420 case MIC_SAMPLING_TYPE_12BIT:
421 case MIC_SAMPLING_TYPE_SIGNED_12BIT:
422 case MIC_SAMPLING_TYPE_12BIT_FILTER_OFF:
423 case MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF:
424 /* For 12-bit sampling */
425 {
426 u16 *p;
427
428 p = (u16 *)((u32)address - 382);
429 if ((u32)p < (u32)gMicData)
430 {
431 p = (u16 *)((u32)p + TEST_BUFFER_SIZE);
432 }
433 DC_InvalidateRange((void *)((u32)p & ~(HW_CACHE_LINE_SIZE - 1)), HW_CACHE_LINE_SIZE);
434 for (i = 0; i < 192; i++)
435 {
436 gDrawData[i] = (u8)((*p >> 8) & 0x00ff);
437 p++;
438 if ((u32)p >= (u32)(gMicData + TEST_BUFFER_SIZE))
439 {
440 p = (u16 *)((u32)p - TEST_BUFFER_SIZE);
441 }
442 if (((u32)p % HW_CACHE_LINE_SIZE) == 0)
443 {
444 DC_InvalidateRange(p, HW_CACHE_LINE_SIZE);
445 }
446 }
447 }
448 break;
449 }
450 }
451
452 /*---------------------------------------------------------------------------*
453 Name: VBlankIntr
454
455 Description: V-Blank interrupt vector.
456
457 Arguments: None.
458
459 Returns: None.
460 *---------------------------------------------------------------------------*/
VBlankIntr(void)461 static void VBlankIntr(void)
462 {
463 /* Sets the IRQ check flag */
464 OS_SetIrqCheckFlag(OS_IE_V_BLANK);
465 }
466
467 /*---------------------------------------------------------------------------*
468 Name: Init3D
469
470 Description: Initialization for 3D display.
471
472 Arguments: None.
473
474 Returns: None.
475 *---------------------------------------------------------------------------*/
Init3D(void)476 static void Init3D(void)
477 {
478 G3X_Init();
479 G3X_InitMtxStack();
480 GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_3D);
481 GX_SetVisiblePlane(GX_PLANEMASK_BG0);
482 G2_SetBG0Priority(0);
483 G3X_AlphaTest(FALSE, 0);
484 G3X_AntiAlias(TRUE);
485 G3X_EdgeMarking(FALSE);
486 G3X_SetFog(FALSE, (GXFogBlend)0, (GXFogSlope)0, 0);
487 G3X_SetClearColor(0, 0, 0x7fff, 63, FALSE);
488 G3_ViewPort(0, 0, 255, 191);
489 G3_MtxMode(GX_MTXMODE_POSITION_VECTOR);
490 }
491
492 /*---------------------------------------------------------------------------*
493 Name: Draw3D
494
495 Description: Displays waveforms in 3D.
496
497 Arguments: None.
498
499 Returns: None.
500 *---------------------------------------------------------------------------*/
Draw3D(void)501 static void Draw3D(void)
502 {
503 G3X_Reset();
504 G3_Identity();
505 G3_PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGONMODE_MODULATE, GX_CULL_NONE, 0, 31, 0);
506
507 {
508 s32 i;
509
510 if ((gMicAutoParam.type == MIC_SAMPLING_TYPE_SIGNED_8BIT) ||
511 (gMicAutoParam.type == MIC_SAMPLING_TYPE_SIGNED_12BIT) ||
512 (gMicAutoParam.type == MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF))
513 {
514 for (i = 0; i < 191; i++)
515 {
516 DrawLine((s16)((s8)gDrawData[i]),
517 (s16)i, (s16)((s8)gDrawData[i + 1]), (s16)(i + 1));
518 }
519 }
520 else
521 {
522 for (i = 0; i < 191; i++)
523 {
524 DrawLine((s16)(gDrawData[i]), (s16)i, (s16)(gDrawData[i + 1]), (s16)(i + 1));
525 }
526 }
527 }
528
529 G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
530 }
531
532 /*---------------------------------------------------------------------------*
533 Name: DrawLine
534
535 Description: Renders lines with triangular polygons.
536
537 Arguments: sx: X-coordinate of line's starting point
538 sy: Y-coordinate of line's starting point
539 ex: X-coordinate of line's ending point
540 ey: Y-coordinate of line's ending point
541
542 Returns: None.
543 *---------------------------------------------------------------------------*/
DrawLine(s16 sx,s16 sy,s16 ex,s16 ey)544 static void DrawLine(s16 sx, s16 sy, s16 ex, s16 ey)
545 {
546 fx16 fsx = (fx16)(((sx - 128) * 0x1000) / 128);
547 fx16 fsy = (fx16)(((96 - sy) * 0x1000) / 96);
548 fx16 fex = (fx16)(((ex - 128) * 0x1000) / 128);
549 fx16 fey = (fx16)(((96 - ey) * 0x1000) / 96);
550
551 G3_Begin(GX_BEGIN_TRIANGLES);
552 {
553 G3_Color(GX_RGB(31, 31, 31));
554 G3_Vtx(fsx, fsy, 0);
555 G3_Color(GX_RGB(31, 31, 31));
556 G3_Vtx(fex, fey, 0);
557 G3_Color(GX_RGB(31, 31, 31));
558 G3_Vtx(fsx, fsy, 1);
559 }
560 G3_End();
561 }
562