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