1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - demos.TWL - spi - mic-4
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-09-11#$
14   $Rev: 8401 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 /*---------------------------------------------------------------------------*
19     This sample controls microphone sampling, and outputs sampling data.
20 
21     USAGE:
22         UP, DOWN: Control sampling span.
23         LEFT, RIGHT: Control sampling bit range. ( 8bit or 12 bit etc. )
24         A: start / stop sampling. (toggle)
25         B: force-stop. (stop and ignore rest data)
26         SELECT: Terminate program.
27 
28     HOWTO:
29         1. Initialize MIC library and SNDEX library.
30         2. When sampling is stopped, you can change parameters
31            and start automatic microphone sampling.
32            Debug-output is sampling data for tool "mic2wav.exe".
33         3. Debug-output log can make its waveform files by tool "mic2wav.exe".
34            > $(TWLSDK_ROOT)/tools/bin/mic2wav.exe [logfile] [,directory]
35            Each set of sampling data (separated by A-Button) creates a waveform file
36            in "[directory]/%08X.wav".
37 
38     NOTE:
39         1. The speed of debug-output is later than sampling.
40            When you stop sampling, then please wait all data is printed.
41  *---------------------------------------------------------------------------*/
42 
43 #include    <twl.h>
44 
45 /*---------------------------------------------------------------------------*
46     Constant Definitions
47  *---------------------------------------------------------------------------*/
48 #define     TEST_BUFFER_SIZE    (1024 * 1024)   // 1 Mbyte
49 #define     RETRY_MAX_COUNT     8
50 
51 /*---------------------------------------------------------------------------*
52     Internal Function Definitions
53  *---------------------------------------------------------------------------*/
54 static void     StartSampling(const MICAutoParam* param);
55 static void     StopSampling(void);
56 static SNDEXFrequency   GetI2SFrequency(void);
57 static void     SetI2SFrequency(SNDEXFrequency freq);
58 static void     SwitchI2SFrequency(void);
59 
60 static void     StepUpSamplingRate(void);
61 static void     StepDownSamplingRate(void);
62 static void     OnSamplingDone(MICResult result, void* arg);
63 static void     OutputSampleWave(void* dat, MICSamplingType type);
64 static void     StartSamplingOutput(void);
65 static void     StopSamplingOutput(void);
66 
67 static void     SetDrawData(void *address, MICSamplingType type);
68 static void     VBlankIntr(void);
69 static void     Init3D(void);
70 static void     Draw3D(void);
71 static void     DrawLine(s16 sx, s16 sy, s16 ex, s16 ey);
72 
73 /*---------------------------------------------------------------------------*
74     Internal Variable Definitions
75  *---------------------------------------------------------------------------*/
76 static MICAutoParam gMicAutoParam;
77 static u8           gDrawData[192];
78 static u8           gMicData[TEST_BUFFER_SIZE] ATTRIBUTE_ALIGN(HW_CACHE_LINE_SIZE);
79 
80 static volatile BOOL g_sample_busy  =   FALSE;
81 static void*        g_record_smps   =   NULL;
82 
83 /*---------------------------------------------------------------------------*
84   Name:         TwlMain
85 
86   Description:  Initialization and main loop.
87 
88   Arguments:    None.
89 
90   Returns:      None.
91  *---------------------------------------------------------------------------*/
TwlMain(void)92 void TwlMain(void)
93 {
94     /* Various types of initialization */
95     OS_Init();
96     FX_Init();
97     GX_Init();
98     GX_DispOff();
99     GXS_DispOff();
100 
101     /* Initializes display settings */
102     GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
103     MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
104     (void)GX_DisableBankForLCDC();
105     MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);
106     MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
107     MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);
108     MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
109 
110     /* 3D-related initialization */
111     Init3D();
112 
113     /* Interrupt settings */
114     OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
115     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
116     (void)OS_EnableIrq();
117     (void)OS_EnableInterrupts();
118     (void)GX_VBlankIntr(TRUE);
119 
120     /* Initialize related libraries*/
121     {
122         (void)PM_SetAmp(PM_AMP_ON);
123         SNDEX_Init();
124         MIC_Init();
125 
126         gMicAutoParam.type      =   MIC_SAMPLING_TYPE_12BIT;
127         gMicAutoParam.buffer    =   (void *)gMicData;
128         gMicAutoParam.size      =   TEST_BUFFER_SIZE;
129         if ((OS_IsRunOnTwl() == TRUE) && (GetI2SFrequency() == SNDEX_FREQUENCY_47610))
130         {
131             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_23810;
132         }
133         else
134         {
135             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_16360;
136         }
137         gMicAutoParam.loop_enable   =   FALSE;
138         gMicAutoParam.full_callback =   OnSamplingDone;
139     }
140 
141     /* Initialize internal variables */
142     MI_CpuFill8(gDrawData, 0x80, sizeof(gDrawData));
143 
144     /* LCD display start */
145     GX_DispOn();
146     GXS_DispOn();
147 
148     /* Debug string output */
149     OS_Printf("# mic-4 demo started.\n");
150     OS_Printf("#   up/down    -> change sampling rate\n");
151     OS_Printf("#   left/right -> change bit range\n");
152     OS_Printf("#   A          -> start / stop\n");
153     OS_Printf("#   B          -> force-stop\n");
154     OS_Printf("#   select     -> terminate\n");
155 
156     /* Empty call for getting key input data (strategy for pressing A Button in the IPL) */
157     (void)PAD_Read();
158 
159     {
160         u16     keyOld  =   0;
161         u16     keyTrg;
162         u16     keyNow;
163 
164         /* Main loop */
165         while (TRUE)
166         {
167             /* Get key input data */
168             keyNow  =   PAD_Read();
169             keyTrg  =   (u16)((keyOld ^ keyNow) & keyNow);
170             keyOld  =   keyNow;
171 
172             /* Start/stop sampling with the A Button*/
173             if (keyTrg & PAD_BUTTON_A)
174             {
175                 if (!g_sample_busy)
176                 {
177                     g_sample_busy = TRUE;
178                     g_record_smps = gMicData;
179                     StartSamplingOutput();
180                     StartSampling(&gMicAutoParam);
181                 }
182                 else
183                 {
184                     StopSampling();
185                     OnSamplingDone(MIC_RESULT_SUCCESS, NULL);
186                 }
187             }
188             /* B Button stops sampling, ignores remaining data*/
189             if (keyTrg & PAD_BUTTON_B)
190             {
191                 if (g_sample_busy)
192                 {
193                     StopSampling();
194                     OnSamplingDone(MIC_RESULT_SUCCESS, NULL);
195                 }
196                 if (g_record_smps)
197                 {
198                     StopSamplingOutput();
199                 }
200             }
201             /* SELECT Button forcibly quits the program*/
202             if (keyTrg & PAD_BUTTON_SELECT)
203             {
204                 OS_Exit(0);
205             }
206             /* Change variable parameters */
207             if (!g_record_smps)
208             {
209                 /* Change sampling type (bit width) */
210                 if (keyTrg & (PAD_KEY_LEFT | PAD_KEY_RIGHT))
211                 {
212                     if (gMicAutoParam.type == MIC_SAMPLING_TYPE_8BIT)
213                     {
214                         gMicAutoParam.type = MIC_SAMPLING_TYPE_12BIT;
215                     }
216                     else
217                     {
218                         gMicAutoParam.type = MIC_SAMPLING_TYPE_8BIT;
219                     }
220                     StartSamplingOutput();
221                 }
222                 /* Change sampling rate */
223                 if (keyTrg & PAD_KEY_UP)
224                 {
225                     StepUpSamplingRate();
226                     StartSamplingOutput();
227                 }
228                 if (keyTrg & PAD_KEY_DOWN)
229                 {
230                     StepDownSamplingRate();
231                     StartSamplingOutput();
232                 }
233             }
234 
235             /* Output a log of sampling results*/
236             OutputSampleWave(MIC_GetLastSamplingAddress(), gMicAutoParam.type);
237 
238             /* Render waveform */
239             if (g_sample_busy)
240             {
241                 SetDrawData(MIC_GetLastSamplingAddress(), gMicAutoParam.type);
242                 Draw3D();
243             }
244 
245             /* Waiting for the V-Blank */
246             OS_WaitVBlankIntr();
247         }
248     }
249 }
250 
251 /*---------------------------------------------------------------------------*
252   Name:         StartSampling
253 
254   Description:  Calls the MIC_StartLimitedSampling function and performs error processing.
255 
256   Arguments:    param: Parameter passed to the microphone functions
257 
258   Returns:      None.
259  *---------------------------------------------------------------------------*/
260 static void
StartSampling(const MICAutoParam * param)261 StartSampling(const MICAutoParam* param)
262 {
263     MICResult   result;
264     s32         retry   =   0;
265 
266     while (TRUE)
267     {
268         result  =   MIC_StartLimitedSampling(param);
269         switch (result)
270         {
271         case MIC_RESULT_SUCCESS:            // Success
272             return;
273         case MIC_RESULT_BUSY:               // Microphone in use by other thread
274         case MIC_RESULT_SEND_ERROR:         // PXI queue is full
275             if (++ retry <= RETRY_MAX_COUNT)
276             {
277                 OS_Sleep(1);
278                 continue;
279             }
280             OS_TWarning("Retry count overflow.\n");
281             return;
282         case MIC_RESULT_ILLEGAL_STATUS:     // Not in an autosampling stopped state
283             OS_TWarning("Already started sampling.\n");
284             return;
285         case MIC_RESULT_ILLEGAL_PARAMETER:  // The specified parameter is not supported
286             OS_TWarning("Illegal parameter to start automatic sampling.\n");
287             return;
288         default:                            // Other fatal error
289             OS_Panic("Fatal error (%d).\n", result);
290             /* Never return */
291         }
292     }
293 }
294 
295 /*---------------------------------------------------------------------------*
296   Name:         StopSampling
297 
298   Description:  Calls the MIC_StopLimitedSampling function and performs error processing.
299 
300   Arguments:    None.
301 
302   Returns:      None.
303  *---------------------------------------------------------------------------*/
304 static void
StopSampling(void)305 StopSampling(void)
306 {
307     MICResult   result;
308     s32         retry   =   0;
309 
310     while (TRUE)
311     {
312         result  =   MIC_StopLimitedSampling();
313         switch (result)
314         {
315         case MIC_RESULT_SUCCESS:            // Success
316         case MIC_RESULT_ILLEGAL_STATUS:     // Not in an auto-sampling state.
317             return;
318         case MIC_RESULT_BUSY:               // Microphone in use by other thread
319         case MIC_RESULT_SEND_ERROR:         // PXI queue is full
320             if (++ retry <= RETRY_MAX_COUNT)
321             {
322                 OS_Sleep(1);
323                 continue;
324             }
325             OS_TWarning("Retry count overflow.\n");
326             return;
327         default:                            // Other fatal error
328             OS_Panic("Fatal error (%d).\n", result);
329             /* Never return */
330         }
331     }
332 }
333 
334 #include <twl/ltdmain_begin.h>
335 /*---------------------------------------------------------------------------*
336   Name:         GetI2SFrequency
337 
338   Description:  Gets the I2S operating frequency.
339 
340   Arguments:    None.
341 
342   Returns:      SDNEXFrequency: Returns the I2S operating frequency.
343  *---------------------------------------------------------------------------*/
344 static SNDEXFrequency
GetI2SFrequency(void)345 GetI2SFrequency(void)
346 {
347     SNDEXResult     result;
348     SNDEXFrequency  freq;
349     s32             retry   =   0;
350 
351     while (TRUE)
352     {
353         result  =   SNDEX_GetI2SFrequency(&freq);
354         switch (result)
355         {
356         case SNDEX_RESULT_SUCCESS:          // Success
357             return freq;
358         case SNDEX_RESULT_EXCLUSIVE:        // Exclusion error
359         case SNDEX_RESULT_PXI_SEND_ERROR:   // PXI queue is full
360             if (++ retry <= RETRY_MAX_COUNT)
361             {
362                 OS_Sleep(1);
363                 continue;
364             }
365             OS_TWarning("Retry count overflow.\n");
366             break;
367         case SNDEX_RESULT_BEFORE_INIT:      // Pre-initialization
368         case SNDEX_RESULT_ILLEGAL_STATE:    // Abnormal state
369             OS_TWarning("Illegal state to get I2S frequency.\n");
370             break;
371         case SNDEX_RESULT_FATAL_ERROR:      // Fatal error
372         default:
373             OS_Panic("Fatal error (%d).\n", result);
374             /* Never return */
375         }
376     }
377     return SNDEX_FREQUENCY_32730;
378 }
379 
380 /*---------------------------------------------------------------------------*
381   Name:         SetI2SFrequency
382 
383   Description:  Changes the I2S operating frequency.
384 
385   Arguments:    freq: I2S operating frequency
386 
387   Returns:      None.
388  *---------------------------------------------------------------------------*/
389 static void
SetI2SFrequency(SNDEXFrequency freq)390 SetI2SFrequency(SNDEXFrequency freq)
391 {
392     SNDEXResult     result;
393     s32             retry   =   0;
394 
395     while (TRUE)
396     {
397         result  =   SNDEX_SetI2SFrequency(freq);
398         switch (result)
399         {
400         case SNDEX_RESULT_SUCCESS:          // Success
401             return;
402         case SNDEX_RESULT_EXCLUSIVE:        // Exclusion error
403         case SNDEX_RESULT_PXI_SEND_ERROR:   // PXI queue is full
404             if (++ retry <= RETRY_MAX_COUNT)
405             {
406                 OS_Sleep(1);
407                 continue;
408             }
409             OS_TWarning("Retry count overflow.\n");
410             return;
411         case SNDEX_RESULT_BEFORE_INIT:      // Pre-initialization
412         case SNDEX_RESULT_ILLEGAL_STATE:    // Abnormal state
413             OS_TWarning("Illegal state to set I2S frequency.\n");
414             return;
415         case SNDEX_RESULT_INVALID_PARAM:    // Abnormal argument
416             OS_TWarning("Could not set I2S frequency into %d.\n", freq);
417             return;
418         case SNDEX_RESULT_FATAL_ERROR:      // Fatal error
419         default:
420             OS_Panic("Fatal error (%d)\n", result);
421             /* Never return */
422         }
423     }
424 }
425 
426 /*---------------------------------------------------------------------------*
427   Name:         SwitchI2SFrequency
428 
429   Description:  Changes the I2S operating frequency in conjunction with the microphone sampling frequency.
430 
431   Arguments:    None.
432 
433   Returns:      None.
434  *---------------------------------------------------------------------------*/
435 static void
SwitchI2SFrequency(void)436 SwitchI2SFrequency(void)
437 {
438     SNDEXFrequency  freq;
439 
440     freq    =   GetI2SFrequency();
441     switch (gMicAutoParam.rate)
442     {
443     case MIC_SAMPLING_RATE_8180:
444     case MIC_SAMPLING_RATE_10910:
445     case MIC_SAMPLING_RATE_16360:
446     case MIC_SAMPLING_RATE_32730:
447         if (freq != SNDEX_FREQUENCY_32730)
448         {
449             SetI2SFrequency(SNDEX_FREQUENCY_32730);
450         }
451         break;
452     case MIC_SAMPLING_RATE_11900:
453     case MIC_SAMPLING_RATE_15870:
454     case MIC_SAMPLING_RATE_23810:
455     case MIC_SAMPLING_RATE_47610:
456         if (freq != SNDEX_FREQUENCY_47610)
457         {
458             SetI2SFrequency(SNDEX_FREQUENCY_47610);
459         }
460         break;
461     }
462 }
463 
464 #include <twl/ltdmain_end.h>
465 
466 /*---------------------------------------------------------------------------*
467   Name:         StepUpSamplingRate
468 
469   Description:  Increases the microphone sampling frequency by one level.
470 
471   Arguments:    None.
472 
473   Returns:      None.
474  *---------------------------------------------------------------------------*/
475 static void
StepUpSamplingRate(void)476 StepUpSamplingRate(void)
477 {
478     if (OS_IsRunOnTwl() == TRUE)
479     {
480         switch (gMicAutoParam.rate)
481         {
482         case MIC_SAMPLING_RATE_8180:    // 32.73k / 4
483             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_10910;
484             break;
485         case MIC_SAMPLING_RATE_10910:   // 32.73k / 3
486             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_11900;
487             break;
488         case MIC_SAMPLING_RATE_11900:   // 47.61k / 4
489             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_15870;
490             break;
491         case MIC_SAMPLING_RATE_15870:   // 47.61k / 3
492             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_16360;
493             break;
494         case MIC_SAMPLING_RATE_16360:   // 32.73k / 2
495             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_23810;
496             break;
497         case MIC_SAMPLING_RATE_23810:   // 47.61k / 2
498             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_32730;
499             break;
500         case MIC_SAMPLING_RATE_32730:   // 32.73k / 1
501             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_47610;
502             break;
503         case MIC_SAMPLING_RATE_47610:   // 47.61k / 1
504         default:
505             /* Do nothing */
506             return;
507         }
508         SwitchI2SFrequency();
509     }
510     else
511     {
512         switch (gMicAutoParam.rate)
513         {
514         case MIC_SAMPLING_RATE_8180:    // 32.73k / 4
515             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_10910;
516             break;
517         case MIC_SAMPLING_RATE_10910:   // 32.73k / 3
518             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_11900;
519             break;
520         case MIC_SAMPLING_RATE_11900:   // 47.61k / 4
521             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_15870;
522             break;
523         case MIC_SAMPLING_RATE_15870:   // 47.61k / 3
524             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_16360;
525             break;
526         case MIC_SAMPLING_RATE_16360:   // 32.73k / 2
527             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_23810;
528             break;
529         case MIC_SAMPLING_RATE_23810:   // 47.61k / 2
530         default:
531             /* Do nothing */
532             return;
533         }
534     }
535 }
536 
537 /*---------------------------------------------------------------------------*
538   Name:         StepUpSamplingRate
539 
540   Description:  Decreases the microphone sampling frequency by one level.
541 
542   Arguments:    None.
543 
544   Returns:      None.
545  *---------------------------------------------------------------------------*/
546 static void
StepDownSamplingRate(void)547 StepDownSamplingRate(void)
548 {
549     if (OS_IsRunOnTwl() == TRUE)
550     {
551         switch (gMicAutoParam.rate)
552         {
553         case MIC_SAMPLING_RATE_47610:   // 47.61k / 1
554             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_32730;
555             break;
556         case MIC_SAMPLING_RATE_32730:   // 32.73k / 1
557             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_23810;
558             break;
559         case MIC_SAMPLING_RATE_23810:   // 47.61k / 2
560             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_16360;
561             break;
562         case MIC_SAMPLING_RATE_16360:   // 32.73k / 2
563             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_15870;
564             break;
565         case MIC_SAMPLING_RATE_15870:   // 47.61k / 3
566             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_11900;
567             break;
568         case MIC_SAMPLING_RATE_11900:   // 47.61k / 4
569             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_10910;
570             break;
571         case MIC_SAMPLING_RATE_10910:   // 32.73k / 3
572             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_8180;
573             break;
574         case MIC_SAMPLING_RATE_8180:    // 32.73k / 4
575         default:
576             /* Do nothing */
577             return;
578         }
579         SwitchI2SFrequency();
580     }
581     else
582     {
583         switch (gMicAutoParam.rate)
584         {
585         case MIC_SAMPLING_RATE_23810:   // 47.61k / 2
586             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_16360;
587             break;
588         case MIC_SAMPLING_RATE_16360:   // 32.73k / 2
589             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_15870;
590             break;
591         case MIC_SAMPLING_RATE_15870:   // 47.61k / 3
592             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_11900;
593             break;
594         case MIC_SAMPLING_RATE_11900:   // 47.61k / 4
595             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_10910;
596             break;
597         case MIC_SAMPLING_RATE_10910:   // 32.73k / 3
598             gMicAutoParam.rate  =   MIC_SAMPLING_RATE_8180;
599             break;
600         case MIC_SAMPLING_RATE_8180:    // 32.73k / 4
601         default:
602             /* Do nothing */
603             return;
604         }
605     }
606 }
607 
608 /*---------------------------------------------------------------------------*
609   Name:         OnSamplingDone
610 
611   Description:  Updates the status flag when autosampling completes.
612 
613   Arguments:    result: Unused
614                 arg: Unused
615 
616   Returns:      None.
617  *---------------------------------------------------------------------------*/
618 static void
OnSamplingDone(MICResult result,void * arg)619 OnSamplingDone(MICResult result, void* arg)
620 {
621 #pragma unused(result, arg)
622 
623     if (g_sample_busy)
624     {
625         g_sample_busy = FALSE;
626     }
627 }
628 
629 /*---------------------------------------------------------------------------*
630   Name:         OutputSampleWave
631 
632   Description:  Debug output of sampling data.
633 
634   Arguments:    dat: Starting address of data to be output
635                 type: Microphone sampling type
636 
637   Returns:      None.
638  *---------------------------------------------------------------------------*/
639 static void
OutputSampleWave(void * dat,MICSamplingType type)640 OutputSampleWave(void* dat, MICSamplingType type)
641 {
642     /* Up to 2 lines at once with 16-sample units.
643        If you output more than this amount, the log may contain omissions. */
644     enum    { smps_per_line = 16, max_line_per_frame = 2 };
645     char    buf[1 + (((MATH_MAX(sizeof(u8), sizeof(u16)) * 2) + 1) * smps_per_line) + 2];
646     char*   s;
647     int     lines, i, j;
648     u32     sample;
649     u8      temp;
650 
651     if (!g_record_smps || !dat)
652     {
653         return;
654     }
655 
656     DC_InvalidateRange((void*)g_record_smps, (u32)((u8*)dat - (u8*)g_record_smps));
657     switch (type)
658     {
659     case MIC_SAMPLING_TYPE_8BIT:
660         /* In the case of 8-bit sampling */
661         for (lines = 0; (lines < max_line_per_frame) && ((u8*)g_record_smps + smps_per_line <= (u8*)dat); lines ++)
662         {
663             s   =   buf;
664             *s ++   =   '|';
665             for (i = 0; i < smps_per_line; i ++)
666             {
667                 sample  =   (u32)(((u8*)g_record_smps)[i]);
668                 for (j = 0; j < (sizeof(u8) * 2); j ++)
669                 {
670                     temp    =   (u8)((sample >> (((sizeof(u8) * 2) - 1 - j) * 4)) & 0x0f);
671                     *s ++   =   (char)((temp < 10) ? ('0' + temp) : ('A' + temp - 10));
672                 }
673                 *s ++   =   ',';
674             }
675             *s ++   =   '\n';
676             *s      =   '\0';
677             OS_FPutString(OS_PRINT_OUTPUT_CURRENT, buf);
678             g_record_smps   =   (void*)((u8*)g_record_smps + smps_per_line);
679         }
680         break;
681     case MIC_SAMPLING_TYPE_12BIT:
682         /* In the case of 12-bit sampling */
683         for (lines = 0; (lines < max_line_per_frame) && ((u16*)g_record_smps + smps_per_line <= (u16*)dat); lines ++)
684         {
685             s   =   buf;
686             *s ++   =   '|';
687             for (i = 0; i < smps_per_line; i ++)
688             {
689                 sample  =   (u32)(((u16*)g_record_smps)[i]);
690                 for (j = 0; j < (sizeof(u16) * 2); j ++)
691                 {
692                     temp    =   (u8)((sample >> (((sizeof(u16) * 2) - 1 - j) * 4)) & 0x0f);
693                     *s ++   =   (char)((temp < 10) ? ('0' + temp) : ('A' + temp - 10));
694                 }
695                 *s ++   =   ',';
696             }
697             *s ++   =   '\n';
698             *s      =   '\0';
699             OS_FPutString(OS_PRINT_OUTPUT_CURRENT, buf);
700             g_record_smps   =   (void*)((u16*)g_record_smps + smps_per_line);
701         }
702         break;
703     }
704 
705     if (!g_sample_busy && g_record_smps)
706     {
707         if (((u8*)g_record_smps + (smps_per_line * max_line_per_frame)) >= (u8*)dat)
708         {
709             StopSamplingOutput();
710         }
711     }
712 }
713 
714 /*---------------------------------------------------------------------------*
715   Name:         StartSamplingOutput
716 
717   Description:  Debug output of string indicating start of sampling output.
718 
719   Arguments:    None.
720 
721   Returns:      None.
722  *---------------------------------------------------------------------------*/
723 static void
StartSamplingOutput(void)724 StartSamplingOutput(void)
725 {
726     s32     range   =   0;
727     s32     rate    =   0;
728 
729     switch (gMicAutoParam.type)
730     {
731     case MIC_SAMPLING_TYPE_8BIT:    range = 8;      break;
732     case MIC_SAMPLING_TYPE_12BIT:   range = 16;     break;
733     }
734 
735     switch (gMicAutoParam.rate)
736     {
737     case MIC_SAMPLING_RATE_32730:   rate = 32730;   break;
738     case MIC_SAMPLING_RATE_16360:   rate = 16360;   break;
739     case MIC_SAMPLING_RATE_10910:   rate = 10910;   break;
740     case MIC_SAMPLING_RATE_8180:    rate = 8180;    break;
741     case MIC_SAMPLING_RATE_47610:   rate = 47610;   break;
742     case MIC_SAMPLING_RATE_23810:   rate = 23810;   break;
743     case MIC_SAMPLING_RATE_15870:   rate = 15870;   break;
744     case MIC_SAMPLING_RATE_11900:   rate = 11900;   break;
745     }
746 
747     OS_Printf("$rate=%d\n$bits=%d\n", rate, range);
748 }
749 
750 /*---------------------------------------------------------------------------*
751   Name:         StopSamplingOutput
752 
753   Description:  Debug output of string indicating end of sampling output.
754 
755   Arguments:    None.
756 
757   Returns:      None.
758  *---------------------------------------------------------------------------*/
759 static void
StopSamplingOutput(void)760 StopSamplingOutput(void)
761 {
762     OS_Printf("$end\n\n");
763     g_record_smps = NULL;
764 }
765 
766 /*---------------------------------------------------------------------------*
767   Name:         SetDrawData
768 
769   Description:  Stores the current newest sampled data in the buffer that puts it on the display.
770 
771 
772   Arguments:    address:   Location in main memory where the most recent sampling data was stored by the component
773 
774                 type:      Sampling type (bit width)
775 
776   Returns:      None.
777  *---------------------------------------------------------------------------*/
SetDrawData(void * address,MICSamplingType type)778 static void SetDrawData(void *address, MICSamplingType type)
779 {
780     s32     i;
781 
782     /* If sampling has never been performed, do nothing and stop.
783        (Because it would delete memory cache(s) unrelated to the microphone) */
784     if ((address < gMicData) || (address >= (gMicData + TEST_BUFFER_SIZE)))
785     {
786         return;
787     }
788 
789     switch (type)
790     {
791     case MIC_SAMPLING_TYPE_8BIT:
792         /* In the case of 8-bit sampling */
793         {
794             u8     *p;
795 
796             p = (u8 *)((u32)address - 191);
797             if (p < gMicData)
798             {
799                 p = (u8 *)((u32)p + TEST_BUFFER_SIZE);
800             }
801             DC_InvalidateRange((void *)((u32)p & ~(HW_CACHE_LINE_SIZE - 1)), HW_CACHE_LINE_SIZE);
802             for (i = 0; i < 192; i++)
803             {
804                 gDrawData[i] = *p;
805                 p++;
806                 if ((u32)p >= (u32)(gMicData + TEST_BUFFER_SIZE))
807                 {
808                     p -= TEST_BUFFER_SIZE;
809                 }
810                 if (((u32)p % HW_CACHE_LINE_SIZE) == 0)
811                 {
812                     DC_InvalidateRange(p, HW_CACHE_LINE_SIZE);
813                 }
814             }
815         }
816         break;
817     case MIC_SAMPLING_TYPE_12BIT:
818         /* For 12-bit sampling*/
819         {
820             u16    *p;
821 
822             p = (u16 *)((u32)address - 382);
823             if ((u32)p < (u32)gMicData)
824             {
825                 p = (u16 *)((u32)p + TEST_BUFFER_SIZE);
826             }
827             DC_InvalidateRange((void *)((u32)p & ~(HW_CACHE_LINE_SIZE - 1)), HW_CACHE_LINE_SIZE);
828             for (i = 0; i < 192; i++)
829             {
830                 gDrawData[i] = (u8)((*p >> 8) & 0x00ff);
831                 p++;
832                 if ((u32)p >= (u32)(gMicData + TEST_BUFFER_SIZE))
833                 {
834                     p = (u16 *)((u32)p - TEST_BUFFER_SIZE);
835                 }
836                 if (((u32)p % HW_CACHE_LINE_SIZE) == 0)
837                 {
838                     DC_InvalidateRange(p, HW_CACHE_LINE_SIZE);
839                 }
840             }
841         }
842         break;
843     }
844 }
845 
846 /*---------------------------------------------------------------------------*
847   Name:         VBlankIntr
848 
849   Description:  V-Blank interrupt vector.
850 
851   Arguments:    None.
852 
853   Returns:      None.
854  *---------------------------------------------------------------------------*/
VBlankIntr(void)855 static void VBlankIntr(void)
856 {
857     /* Sets the IRQ check flag */
858     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
859 }
860 
861 /*---------------------------------------------------------------------------*
862   Name:         Init3D
863 
864   Description:  Initialization for 3D display.
865 
866   Arguments:    None.
867 
868   Returns:      None.
869  *---------------------------------------------------------------------------*/
Init3D(void)870 static void Init3D(void)
871 {
872     G3X_Init();
873     G3X_InitMtxStack();
874     GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_3D);
875     GX_SetVisiblePlane(GX_PLANEMASK_BG0);
876     G2_SetBG0Priority(0);
877     G3X_AlphaTest(FALSE, 0);
878     G3X_AntiAlias(TRUE);
879     G3X_EdgeMarking(FALSE);
880     G3X_SetFog(FALSE, (GXFogBlend)0, (GXFogSlope)0, 0);
881     G3X_SetClearColor(0, 0, 0x7fff, 63, FALSE);
882     G3_ViewPort(0, 0, 255, 191);
883     G3_MtxMode(GX_MTXMODE_POSITION_VECTOR);
884 }
885 
886 /*---------------------------------------------------------------------------*
887   Name:         Draw3D
888 
889   Description:  Displays waveforms in 3D
890 
891   Arguments:    None.
892 
893   Returns:      None.
894  *---------------------------------------------------------------------------*/
Draw3D(void)895 static void Draw3D(void)
896 {
897     G3X_Reset();
898     G3_Identity();
899     G3_PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGONMODE_MODULATE, GX_CULL_NONE, 0, 31, 0);
900 
901     {
902         s32     i;
903 
904         if ((gMicAutoParam.type == MIC_SAMPLING_TYPE_SIGNED_8BIT) ||
905             (gMicAutoParam.type == MIC_SAMPLING_TYPE_SIGNED_12BIT) ||
906             (gMicAutoParam.type == MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF))
907         {
908             for (i = 0; i < 191; i++)
909             {
910                 DrawLine((s16)((s8)gDrawData[i]),
911                          (s16)i, (s16)((s8)gDrawData[i + 1]), (s16)(i + 1));
912             }
913         }
914         else
915         {
916             for (i = 0; i < 191; i++)
917             {
918                 DrawLine((s16)(gDrawData[i]), (s16)i, (s16)(gDrawData[i + 1]), (s16)(i + 1));
919             }
920         }
921     }
922 
923     G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
924 }
925 
926 /*---------------------------------------------------------------------------*
927   Name:         DrawLine
928 
929   Description:  Renders lines with triangular polygons.
930 
931   Arguments:    sx:   X-coordinate of line's starting point
932                 sy:   Y-coordinate of line's starting point
933                 ex:   X-coordinate of line's ending point
934                 ey:   Y-coordinate of line's ending point
935 
936   Returns:      None.
937  *---------------------------------------------------------------------------*/
DrawLine(s16 sx,s16 sy,s16 ex,s16 ey)938 static void DrawLine(s16 sx, s16 sy, s16 ex, s16 ey)
939 {
940     fx16    fsx = (fx16)(((sx - 128) * 0x1000) / 128);
941     fx16    fsy = (fx16)(((96 - sy) * 0x1000) / 96);
942     fx16    fex = (fx16)(((ex - 128) * 0x1000) / 128);
943     fx16    fey = (fx16)(((96 - ey) * 0x1000) / 96);
944 
945     G3_Begin(GX_BEGIN_TRIANGLES);
946     {
947         G3_Color(GX_RGB(31, 31, 31));
948         G3_Vtx(fsx, fsy, 0);
949         G3_Color(GX_RGB(31, 31, 31));
950         G3_Vtx(fex, fey, 0);
951         G3_Color(GX_RGB(31, 31, 31));
952         G3_Vtx(fsx, fsy, 1);
953     }
954     G3_End();
955 }
956 
957 /*---------------------------------------------------------------------------*
958   End of file
959  *---------------------------------------------------------------------------*/
960