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