1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - SPI - demos
3   File:     main.c
4 
5   Copyright 2003-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-12-22#$
14   $Rev: 9714 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 #include    <nitro.h>
19 #include    <nitro/spi/common/pm_common.h>
20 #include    <nitro/spi/ARM9/pm.h>
21 
22 #include    "snd_data.h"
23 
24 
25 /*---------------------------------------------------------------------------*
26     Constant Definitions
27  *---------------------------------------------------------------------------*/
28 #define     KEY_REPEAT_START    25     // Number of frames until key repeat starts
29 #define     KEY_REPEAT_SPAN     10     // Number of frames between key repeats
30 #define     TEST_BUFFER_SIZE    ( 1024 * 1024 ) // 1M
31 
32 //
33 // Maximum sampling rate for the microphone
34 //  Using the mic simultaneously with SOUND or the touch screen lowers the maximum sampling rate, so here we limit it to a maximum of 22K.
35 //
36 //  If concentrating only on mic sampling, it is possible to operate up to LIMIT.
37 //
38 #define     MY_SAMPLING_RATE_LIMIT  MIC_SAMPLING_RATE_22K
39 
40 
41 /*---------------------------------------------------------------------------*
42     Structure Definitions
43  *---------------------------------------------------------------------------*/
44 // Key input data
45 typedef struct KeyInformation
46 {
47     u16     cnt;                       // Unprocessed input value
48     u16     trg;                       // Push trigger input
49     u16     up;                        // Release trigger input
50     u16     rep;                       // Press and hold repeat input
51 
52 }
53 KeyInformation;
54 
55 /*---------------------------------------------------------------------------*
56     Internal Function Definitions
57  *---------------------------------------------------------------------------*/
58 static void InitializeAllocateSystem(void);
59 static void Init3D(void);
60 static void Draw3D(void);
61 static void DrawLine(s16 sx, s16 sy, s16 ex, s16 ey, GXRgb color);
62 static void VBlankIntr(void);
63 static void KeyRead(KeyInformation * pKey);
64 static void SetDrawData(void *address, MICSamplingType type);
65 static void PrintfVariableData(void);
66 
67 
68 
69 /*---------------------------------------------------------------------------*
70     Internal Variable Definitions
71  *---------------------------------------------------------------------------*/
72 static KeyInformation gKey;
73 static MICAutoParam gMicAutoParam;
74 static u8 *gMicData;
75 static TPData gTpData;
76 static u8 gDrawData[192];
77 
78 
79 /*---------------------------------------------------------------------------*
80   Name:         NitroMain
81 
82   Description:  Initialization and main loop.
83 
84   Arguments:    None.
85 
86   Returns:      None.
87  *---------------------------------------------------------------------------*/
NitroMain(void)88 void NitroMain(void)
89 {
90     // Various types of initialization
91     OS_Init();
92     FX_Init();
93     GX_Init();
94     GX_DispOff();
95     GXS_DispOff();
96     GX_SetDispSelect(GX_DISP_SELECT_SUB_MAIN);
97 
98     // Initializes display settings
99     GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
100     MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
101     (void)GX_DisableBankForLCDC();
102     MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);
103     MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
104     MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);
105     MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
106 
107     // 3D-related initialization
108     Init3D();
109 
110     // Interrupt settings
111     OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
112     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
113     (void)OS_EnableIrq();
114     (void)OS_EnableInterrupts();
115     (void)GX_VBlankIntr(TRUE);
116 
117     //****************************************************************
118     // Initialize MIC.
119     InitializeAllocateSystem();
120     // Because the memory allocated with OS_Alloc is 32-byte aligned, other memory is not destroyed even if the cache is manipulated
121     //
122     gMicData = (u8 *)OS_Alloc(TEST_BUFFER_SIZE);
123     MIC_Init();
124 
125     // Initialize PMIC
126     PM_Init();
127     // AMP on
128     (void)PM_SetAmp(PM_AMP_ON);
129     // Adjust AMP gain
130     (void)PM_SetAmpGain(PM_AMPGAIN_80);
131 
132     gMicAutoParam.type = MIC_SAMPLING_TYPE_8BIT;
133     gMicAutoParam.buffer = (void *)gMicData;
134     gMicAutoParam.size = TEST_BUFFER_SIZE;
135     gMicAutoParam.rate = MIC_SAMPLING_RATE_8K;
136     gMicAutoParam.loop_enable = TRUE;
137     gMicAutoParam.full_callback = NULL;
138     (void)MIC_StartAutoSampling(&gMicAutoParam);
139     //****************************************************************
140 
141     // Touch Panel API Initialization.
142     {
143         TPCalibrateParam calibrate;
144 
145         TP_Init();
146         if (TP_GetUserInfo(&calibrate))
147         {
148             TP_SetCalibrateParam(&calibrate);
149         }
150         else
151         {
152             OS_Panic("Can't find TP calibration data.");
153         }
154     }
155 
156 
157     // Initialize sound
158     {
159         SND_Init();
160         SND_AssignWaveArc((SNDBankData *)sound_bank_data, 0, (SNDWaveArc *)sound_wave_data);
161         SND_StartSeq(0, sound_seq_data, 0, (SNDBankData *)sound_bank_data);
162     }
163 
164     // Initialize internal variables
165     {
166         s32     i;
167 
168         for (i = 0; i < 192; i++)
169         {
170             gDrawData[i] = 0x80;
171         }
172     }
173 
174     // LCD display start
175     GX_DispOn();
176     GXS_DispOn();
177 
178     // Debug string output
179     OS_Printf("ARM9: MIC demo started.\n");
180     OS_Printf("   up/down    -> change sampling span\n");
181     OS_Printf("   left/right -> change bit range\n");
182     OS_Printf("   select     -> change loop setting\n");
183     OS_Printf("\n");
184     PrintfVariableData();
185     gTpData.touch = TP_TOUCH_OFF;
186 
187     // Empty call for getting key input data (strategy for pressing A button in the IPL)
188     KeyRead(&gKey);
189 
190     // Main loop
191     while (TRUE)
192     {
193         // Get key input data
194         KeyRead(&gKey);
195 
196         // TP sampling can be executed once during automatic MIC sampling.
197         // However, it is only executed after the next MIC sampling, so there is a brief delay before the results of the request are returned.
198         //
199         {
200             TP_RequestSamplingAsync();
201             // <- During MIC automatic sampling, it will take a bit longer for the TP results to return.
202 
203             if (TP_WaitCalibratedResult(&gTpData) != 0)
204             {
205                 OS_Printf("TP_RequestSampling command fail\n");
206             }
207         }
208 
209         // Change variable parameters
210         {
211             // Change sampling type (bit width)
212             if ((gKey.trg | gKey.rep) & (PAD_KEY_LEFT | PAD_KEY_RIGHT))
213             {
214                 //****************************************************************
215                 (void)MIC_StopAutoSampling();
216                 gMicAutoParam.type =
217                     (MICSamplingType)((gMicAutoParam.type + 1) % MIC_SAMPLING_TYPE_MAX);
218                 (void)MIC_StartAutoSampling(&gMicAutoParam);
219                 //****************************************************************
220                 PrintfVariableData();
221             }
222             // Change sampling rate
223             if ((gKey.trg | gKey.rep) & PAD_KEY_UP)
224             {
225                 //****************************************************************
226                 (void)MIC_StopAutoSampling();
227                 gMicAutoParam.rate = (u32)(gMicAutoParam.rate / 2);
228                 if (gMicAutoParam.rate < MY_SAMPLING_RATE_LIMIT)
229                 {
230                     gMicAutoParam.rate = MY_SAMPLING_RATE_LIMIT;
231                 }
232 
233                 (void)MIC_StartAutoSampling(&gMicAutoParam);
234                 //****************************************************************
235                 PrintfVariableData();
236             }
237             if ((gKey.trg | gKey.rep) & PAD_KEY_DOWN)
238             {
239                 //****************************************************************
240                 (void)MIC_StopAutoSampling();
241                 gMicAutoParam.rate = (u32)(gMicAutoParam.rate * 2);
242                 if (gMicAutoParam.rate < MY_SAMPLING_RATE_LIMIT)
243                 {
244                     gMicAutoParam.rate = MY_SAMPLING_RATE_LIMIT;
245                 }
246                 (void)MIC_StartAutoSampling(&gMicAutoParam);
247                 //****************************************************************
248                 PrintfVariableData();
249             }
250         }
251 
252         // Render waveform
253         SetDrawData(MIC_GetLastSamplingAddress(), gMicAutoParam.type);
254 
255         // Render
256         Draw3D();
257 
258         // Sound
259         while (SND_RecvCommandReply(SND_COMMAND_NOBLOCK) != NULL)
260         {
261         }
262         (void)SND_FlushCommand(SND_COMMAND_NOBLOCK);
263 
264         // Waiting for the V-Blank
265         OS_WaitVBlankIntr();
266     }
267 }
268 
269 
270 /*---------------------------------------------------------------------------*
271   Name:         InitializeAllocateSystem
272 
273   Description:  Initializes the memory allocation system within the main memory arena.
274 
275   Arguments:    None.
276 
277   Returns:      None.
278  *---------------------------------------------------------------------------*/
InitializeAllocateSystem(void)279 static void InitializeAllocateSystem(void)
280 {
281     void   *tempLo;
282     OSHeapHandle hh;
283 
284     // Based on the premise that OS_Init has been already called
285     tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
286     OS_SetArenaLo(OS_ARENA_MAIN, tempLo);
287     hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
288     if (hh < 0)
289     {
290         OS_Panic("ARM9: Fail to create heap...\n");
291     }
292     hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
293 }
294 
295 
296 /*---------------------------------------------------------------------------*
297   Name:         Init3D
298 
299   Description:  Initialization for 3D display.
300 
301   Arguments:    None.
302 
303   Returns:      None.
304  *---------------------------------------------------------------------------*/
Init3D(void)305 static void Init3D(void)
306 {
307     G3X_Init();
308     G3X_InitMtxStack();
309     G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
310     GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_3D);
311     GX_SetVisiblePlane(GX_PLANEMASK_BG0);
312     G2_SetBG0Priority(0);
313     G3X_SetShading(GX_SHADING_TOON);
314     G3X_AlphaTest(FALSE, 0);
315     G3X_AlphaBlend(TRUE);
316     G3X_AntiAlias(TRUE);
317     G3X_EdgeMarking(FALSE);
318     G3X_SetFog(FALSE, (GXFogBlend)0, (GXFogSlope)0, 0);
319     G3X_SetClearColor(0, 0, 0x7fff, 63, FALSE);
320     G3_ViewPort(0, 0, 255, 191);
321 }
322 
323 /*---------------------------------------------------------------------------*
324   Name:         Draw3D
325 
326   Description:  Displays waveforms in 3D.
327 
328   Arguments:    None.
329 
330   Returns:      None.
331  *---------------------------------------------------------------------------*/
Draw3D(void)332 static void Draw3D(void)
333 {
334     G3X_Reset();
335 
336     G3_MtxMode(GX_MTXMODE_PROJECTION);
337     G3_Identity();
338     G3_MtxMode(GX_MTXMODE_POSITION_VECTOR);
339     G3_Identity();
340 
341     G3_PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGONMODE_MODULATE, GX_CULL_NONE, 0, 31, 0);
342 
343     {
344         s32     i;
345 
346         if ((gMicAutoParam.type == MIC_SAMPLING_TYPE_SIGNED_8BIT) ||
347             (gMicAutoParam.type == MIC_SAMPLING_TYPE_SIGNED_12BIT) ||
348             (gMicAutoParam.type == MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF))
349         {
350             for (i = 0; i < 191; i++)
351             {
352                 DrawLine((s16)((s8)gDrawData[i]),
353                          (s16)i, (s16)((s8)gDrawData[i + 1]), (s16)(i + 1), GX_RGB(31, 31, 0));
354             }
355         }
356         else
357         {
358             for (i = 0; i < 191; i++)
359             {
360                 DrawLine((s16)(gDrawData[i]),
361                          (s16)i, (s16)(gDrawData[i + 1]), (s16)(i + 1), GX_RGB(31, 31, 0));
362             }
363         }
364 
365         // Display Touch Panel contact as '+' mark
366         if (gTpData.touch == TP_TOUCH_ON)
367         {
368             if (!(gTpData.validity & TP_VALIDITY_INVALID_X))
369             {
370                 // Display the x coordinate with a line
371                 DrawLine((s16)(gTpData.x),
372                          (s16)(0), (s16)(gTpData.x), (s16)(191), GX_RGB(31, 31, 31));
373             }
374             if (!(gTpData.validity & TP_VALIDITY_INVALID_Y))
375             {
376                 // Display the y coordinate with a line
377                 DrawLine((s16)(0),
378                          (s16)(gTpData.y), (s16)(255), (s16)(gTpData.y), GX_RGB(31, 31, 31));
379             }
380         }
381     }
382 
383     G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
384 }
385 
386 /*---------------------------------------------------------------------------*
387   Name:         DrawLine
388 
389   Description:  Renders lines with triangular polygons.
390 
391   Arguments:    sx: X-coordinate of line's starting point
392                 sy: Y-coordinate of line's starting point
393                 ex: X-coordinate of line's ending point
394                 ey: Y-coordinate of line's ending point
395                 color: Color of line drawn
396 
397   Returns:      None.
398  *---------------------------------------------------------------------------*/
DrawLine(s16 sx,s16 sy,s16 ex,s16 ey,GXRgb color)399 static void DrawLine(s16 sx, s16 sy, s16 ex, s16 ey, GXRgb color)
400 {
401     fx16    fsx;
402     fx16    fsy;
403     fx16    fex;
404     fx16    fey;
405 
406     fsx = (fx16)(((sx - 128) * 0x1000) / 128);
407     fsy = (fx16)(((96 - sy) * 0x1000) / 96);
408     fex = (fx16)(((ex - 128) * 0x1000) / 128);
409     fey = (fx16)(((96 - ey) * 0x1000) / 96);
410 
411     G3_Begin(GX_BEGIN_TRIANGLES);
412     {
413         G3_Color(color);
414         G3_Vtx(fsx, fsy, 0);
415         G3_Color(color);
416         G3_Vtx(fex, fey, 0);
417         G3_Color(color);
418         G3_Vtx(fsx, fsy, 1);
419     }
420     G3_End();
421 }
422 
423 /*---------------------------------------------------------------------------*
424   Name:         VBlankIntr
425 
426   Description:  V-Blank interrupt vector.
427 
428   Arguments:    None.
429 
430   Returns:      None.
431  *---------------------------------------------------------------------------*/
VBlankIntr(void)432 static void VBlankIntr(void)
433 {
434     // Sets the IRQ check flag
435     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
436 }
437 
438 /*---------------------------------------------------------------------------*
439   Name:         KeyRead
440 
441   Description:  Edits key input data.
442                 Detects press trigger, release trigger, and press-and-hold repeat.
443 
444   Arguments:    pKey: Structure that holds key input data to be edited
445 
446   Returns:      None.
447  *---------------------------------------------------------------------------*/
KeyRead(KeyInformation * pKey)448 static void KeyRead(KeyInformation * pKey)
449 {
450     static u16 repeat_count[12];
451     int     i;
452     u16     r;
453 
454     r = PAD_Read();
455     pKey->trg = 0x0000;
456     pKey->up = 0x0000;
457     pKey->rep = 0x0000;
458 
459     for (i = 0; i < 12; i++)
460     {
461         if (r & (0x0001 << i))
462         {
463             if (!(pKey->cnt & (0x0001 << i)))
464             {
465                 pKey->trg |= (0x0001 << i);     // Press trigger
466                 repeat_count[i] = 1;
467             }
468             else
469             {
470                 if (repeat_count[i] > KEY_REPEAT_START)
471                 {
472                     pKey->rep |= (0x0001 << i); // Press-and-hold repeat
473                     repeat_count[i] = KEY_REPEAT_START - KEY_REPEAT_SPAN;
474                 }
475                 else
476                 {
477                     repeat_count[i]++;
478                 }
479             }
480         }
481         else
482         {
483             if (pKey->cnt & (0x0001 << i))
484             {
485                 pKey->up |= (0x0001 << i);      // Release trigger
486             }
487         }
488     }
489     pKey->cnt = r;                     // Unprocessed key input
490 }
491 
492 /*---------------------------------------------------------------------------*
493   Name:         SetDrawData
494 
495   Description:  Stores the current newest sampled data in the buffer that puts it on the display.
496 
497 
498   Arguments:    address: Location in main memory where the most recent sampling data is stored by the components
499 
500                 type: Sampling type (bit width)
501 
502   Returns:      None.
503  *---------------------------------------------------------------------------*/
SetDrawData(void * address,MICSamplingType type)504 static void SetDrawData(void *address, MICSamplingType type)
505 {
506     s32     i;
507 
508     // If sampling has never been performed, do nothing and stop.
509     // (Because it would delete memory cache(s) unrelated to the microphone)
510     if ((address < gMicData) || (address >= (gMicData + TEST_BUFFER_SIZE)))
511     {
512         return;
513     }
514 
515     // In the case of 8-bit sampling
516     switch (type)
517     {
518     case MIC_SAMPLING_TYPE_8BIT:
519     case MIC_SAMPLING_TYPE_SIGNED_8BIT:
520         {
521             u8     *p;
522 
523             p = (u8 *)((u32)address - 191);
524             if (p < gMicData)
525             {
526                 p = (u8 *)((u32)p + TEST_BUFFER_SIZE);
527             }
528             DC_InvalidateRange((void *)((u32)p & 0xffffffe0), 32);
529             for (i = 0; i < 192; i++)
530             {
531                 gDrawData[i] = *p;
532                 p++;
533                 if ((u32)p >= (u32)(gMicData + TEST_BUFFER_SIZE))
534                 {
535                     p -= TEST_BUFFER_SIZE;
536                 }
537                 if (((u32)p % 32) == 0)
538                 {
539                     DC_InvalidateRange(p, 32);
540                 }
541             }
542         }
543         break;
544     case MIC_SAMPLING_TYPE_12BIT:
545     case MIC_SAMPLING_TYPE_SIGNED_12BIT:
546     case MIC_SAMPLING_TYPE_12BIT_FILTER_OFF:
547     case MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF:
548         {
549             u16    *p;
550 
551             p = (u16 *)((u32)address - 382);
552             if ((u32)p < (u32)gMicData)
553             {
554                 p = (u16 *)((u32)p + TEST_BUFFER_SIZE);
555             }
556             DC_InvalidateRange((void *)((u32)p & 0xffffffe0), 32);
557             for (i = 0; i < 192; i++)
558             {
559                 gDrawData[i] = (u8)((*p >> 8) & 0x00ff);
560                 p++;
561                 if ((u32)p >= (u32)(gMicData + TEST_BUFFER_SIZE))
562                 {
563                     p = (u16 *)((u32)p - TEST_BUFFER_SIZE);
564                 }
565                 if (((u32)p % 32) == 0)
566                 {
567                     DC_InvalidateRange(p, 32);
568                 }
569             }
570         }
571         break;
572     }
573 }
574 
575 /*---------------------------------------------------------------------------*
576   Name:         PrintfVariableData
577 
578   Description:  Print out the variable sampling settings.
579 
580   Arguments:    None.
581 
582   Returns:      None.
583  *---------------------------------------------------------------------------*/
PrintfVariableData(void)584 static void PrintfVariableData(void)
585 {
586     s32     range = 0;
587 
588     OS_Printf(" sampling-span: %d , bit-range: ", gMicAutoParam.rate);
589     switch (gMicAutoParam.type)
590     {
591     case MIC_SAMPLING_TYPE_8BIT:
592         OS_Printf("8");
593         break;
594     case MIC_SAMPLING_TYPE_12BIT:
595         OS_Printf("12");
596         break;
597     case MIC_SAMPLING_TYPE_SIGNED_8BIT:
598         OS_Printf("signed 8");
599         break;
600     case MIC_SAMPLING_TYPE_SIGNED_12BIT:
601         OS_Printf("signed 12");
602         break;
603     case MIC_SAMPLING_TYPE_12BIT_FILTER_OFF:
604         OS_Printf("12(filter off)");
605         break;
606     case MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF:
607         OS_Printf("signed 12(filter off)");
608         break;
609     }
610     if (gMicAutoParam.loop_enable)
611     {
612         OS_Printf(" , loop: on\n");
613     }
614     else
615     {
616         OS_Printf(" , loop: off\n");
617     }
618 }
619 
620 
621 /*---------------------------------------------------------------------------*
622   End of file
623  *---------------------------------------------------------------------------*/
624