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:: 2009-07-06#$
14   $Rev: 10864 $
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("\n");
183     PrintfVariableData();
184     gTpData.touch = TP_TOUCH_OFF;
185 
186     // Empty call for getting key input data (strategy for pressing A button in the IPL)
187     KeyRead(&gKey);
188 
189     // Main loop
190     while (TRUE)
191     {
192         // Get key input data
193         KeyRead(&gKey);
194 
195         // TP sampling can be executed once during automatic MIC sampling.
196         // However, it is only executed after the next MIC sampling, so there is a brief delay before the results of the request are returned.
197         //
198         {
199             TP_RequestSamplingAsync();
200             // <- During MIC automatic sampling, it will take a bit longer for the TP results to return.
201 
202             if (TP_WaitCalibratedResult(&gTpData) != 0)
203             {
204                 OS_Printf("TP_RequestSampling command fail\n");
205             }
206         }
207 
208         // Change variable parameters
209         {
210             // Change sampling type (bit width)
211             if ((gKey.trg | gKey.rep) & (PAD_KEY_LEFT | PAD_KEY_RIGHT))
212             {
213                 //****************************************************************
214                 (void)MIC_StopAutoSampling();
215                 gMicAutoParam.type =
216                     (MICSamplingType)((gMicAutoParam.type + 1) % MIC_SAMPLING_TYPE_MAX);
217                 (void)MIC_StartAutoSampling(&gMicAutoParam);
218                 //****************************************************************
219                 PrintfVariableData();
220             }
221             // Change sampling rate
222             if ((gKey.trg | gKey.rep) & PAD_KEY_UP)
223             {
224                 //****************************************************************
225                 (void)MIC_StopAutoSampling();
226                 gMicAutoParam.rate = (u32)(gMicAutoParam.rate / 2);
227                 if (gMicAutoParam.rate < MY_SAMPLING_RATE_LIMIT)
228                 {
229                     gMicAutoParam.rate = MY_SAMPLING_RATE_LIMIT;
230                 }
231 
232                 (void)MIC_StartAutoSampling(&gMicAutoParam);
233                 //****************************************************************
234                 PrintfVariableData();
235             }
236             if ((gKey.trg | gKey.rep) & PAD_KEY_DOWN)
237             {
238                 //****************************************************************
239                 (void)MIC_StopAutoSampling();
240                 gMicAutoParam.rate = (u32)(gMicAutoParam.rate * 2);
241                 if (gMicAutoParam.rate < MY_SAMPLING_RATE_LIMIT)
242                 {
243                     gMicAutoParam.rate = MY_SAMPLING_RATE_LIMIT;
244                 }
245                 (void)MIC_StartAutoSampling(&gMicAutoParam);
246                 //****************************************************************
247                 PrintfVariableData();
248             }
249         }
250 
251         // Render waveform
252         SetDrawData(MIC_GetLastSamplingAddress(), gMicAutoParam.type);
253 
254         // Render
255         Draw3D();
256 
257         // Sound
258         while (SND_RecvCommandReply(SND_COMMAND_NOBLOCK) != NULL)
259         {
260         }
261         (void)SND_FlushCommand(SND_COMMAND_NOBLOCK);
262 
263         // Waiting for the V-Blank
264         OS_WaitVBlankIntr();
265     }
266 }
267 
268 
269 /*---------------------------------------------------------------------------*
270   Name:         InitializeAllocateSystem
271 
272   Description:  Initializes the memory allocation system within the main memory arena.
273 
274   Arguments:    None.
275 
276   Returns:      None.
277  *---------------------------------------------------------------------------*/
InitializeAllocateSystem(void)278 static void InitializeAllocateSystem(void)
279 {
280     void   *tempLo;
281     OSHeapHandle hh;
282 
283     // Based on the premise that OS_Init has been already called
284     tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
285     OS_SetArenaLo(OS_ARENA_MAIN, tempLo);
286     hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
287     if (hh < 0)
288     {
289         OS_Panic("ARM9: Fail to create heap...\n");
290     }
291     hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
292 }
293 
294 
295 /*---------------------------------------------------------------------------*
296   Name:         Init3D
297 
298   Description:  Initialization for 3D display.
299 
300   Arguments:    None.
301 
302   Returns:      None.
303  *---------------------------------------------------------------------------*/
Init3D(void)304 static void Init3D(void)
305 {
306     G3X_Init();
307     G3X_InitMtxStack();
308     G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
309     GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_3D);
310     GX_SetVisiblePlane(GX_PLANEMASK_BG0);
311     G2_SetBG0Priority(0);
312     G3X_SetShading(GX_SHADING_TOON);
313     G3X_AlphaTest(FALSE, 0);
314     G3X_AlphaBlend(TRUE);
315     G3X_AntiAlias(TRUE);
316     G3X_EdgeMarking(FALSE);
317     G3X_SetFog(FALSE, (GXFogBlend)0, (GXFogSlope)0, 0);
318     G3X_SetClearColor(0, 0, 0x7fff, 63, FALSE);
319     G3_ViewPort(0, 0, 255, 191);
320 }
321 
322 /*---------------------------------------------------------------------------*
323   Name:         Draw3D
324 
325   Description:  Displays waveforms in 3D.
326 
327   Arguments:    None.
328 
329   Returns:      None.
330  *---------------------------------------------------------------------------*/
Draw3D(void)331 static void Draw3D(void)
332 {
333     G3X_Reset();
334 
335     G3_MtxMode(GX_MTXMODE_PROJECTION);
336     G3_Identity();
337     G3_MtxMode(GX_MTXMODE_POSITION_VECTOR);
338     G3_Identity();
339 
340     G3_PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGONMODE_MODULATE, GX_CULL_NONE, 0, 31, 0);
341 
342     {
343         s32     i;
344 
345         if ((gMicAutoParam.type == MIC_SAMPLING_TYPE_SIGNED_8BIT) ||
346             (gMicAutoParam.type == MIC_SAMPLING_TYPE_SIGNED_12BIT) ||
347             (gMicAutoParam.type == MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF))
348         {
349             for (i = 0; i < 191; i++)
350             {
351                 DrawLine((s16)((s8)gDrawData[i]),
352                          (s16)i, (s16)((s8)gDrawData[i + 1]), (s16)(i + 1), GX_RGB(31, 31, 0));
353             }
354         }
355         else
356         {
357             for (i = 0; i < 191; i++)
358             {
359                 DrawLine((s16)(gDrawData[i]),
360                          (s16)i, (s16)(gDrawData[i + 1]), (s16)(i + 1), GX_RGB(31, 31, 0));
361             }
362         }
363 
364         // Display Touch Panel contact as '+' mark
365         if (gTpData.touch == TP_TOUCH_ON)
366         {
367             if (!(gTpData.validity & TP_VALIDITY_INVALID_X))
368             {
369                 // Display the x coordinate with a line
370                 DrawLine((s16)(gTpData.x),
371                          (s16)(0), (s16)(gTpData.x), (s16)(191), GX_RGB(31, 31, 31));
372             }
373             if (!(gTpData.validity & TP_VALIDITY_INVALID_Y))
374             {
375                 // Display the y coordinate with a line
376                 DrawLine((s16)(0),
377                          (s16)(gTpData.y), (s16)(255), (s16)(gTpData.y), GX_RGB(31, 31, 31));
378             }
379         }
380     }
381 
382     G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
383 }
384 
385 /*---------------------------------------------------------------------------*
386   Name:         DrawLine
387 
388   Description:  Renders lines with triangular polygons.
389 
390   Arguments:    sx: X-coordinate of line's starting point
391                 sy: Y-coordinate of line's starting point
392                 ex: X-coordinate of line's ending point
393                 ey: Y-coordinate of line's ending point
394                 color: Color of line drawn
395 
396   Returns:      None.
397  *---------------------------------------------------------------------------*/
DrawLine(s16 sx,s16 sy,s16 ex,s16 ey,GXRgb color)398 static void DrawLine(s16 sx, s16 sy, s16 ex, s16 ey, GXRgb color)
399 {
400     fx16    fsx;
401     fx16    fsy;
402     fx16    fex;
403     fx16    fey;
404 
405     fsx = (fx16)(((sx - 128) * 0x1000) / 128);
406     fsy = (fx16)(((96 - sy) * 0x1000) / 96);
407     fex = (fx16)(((ex - 128) * 0x1000) / 128);
408     fey = (fx16)(((96 - ey) * 0x1000) / 96);
409 
410     G3_Begin(GX_BEGIN_TRIANGLES);
411     {
412         G3_Color(color);
413         G3_Vtx(fsx, fsy, 0);
414         G3_Color(color);
415         G3_Vtx(fex, fey, 0);
416         G3_Color(color);
417         G3_Vtx(fsx, fsy, 1);
418     }
419     G3_End();
420 }
421 
422 /*---------------------------------------------------------------------------*
423   Name:         VBlankIntr
424 
425   Description:  V-Blank interrupt vector.
426 
427   Arguments:    None.
428 
429   Returns:      None.
430  *---------------------------------------------------------------------------*/
VBlankIntr(void)431 static void VBlankIntr(void)
432 {
433     // Sets the IRQ check flag
434     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
435 }
436 
437 /*---------------------------------------------------------------------------*
438   Name:         KeyRead
439 
440   Description:  Edits key input data.
441                 Detects press trigger, release trigger, and press-and-hold repeat.
442 
443   Arguments:    pKey: Structure that holds key input data to be edited
444 
445   Returns:      None.
446  *---------------------------------------------------------------------------*/
KeyRead(KeyInformation * pKey)447 static void KeyRead(KeyInformation * pKey)
448 {
449     static u16 repeat_count[12];
450     int     i;
451     u16     r;
452 
453     r = PAD_Read();
454     pKey->trg = 0x0000;
455     pKey->up = 0x0000;
456     pKey->rep = 0x0000;
457 
458     for (i = 0; i < 12; i++)
459     {
460         if (r & (0x0001 << i))
461         {
462             if (!(pKey->cnt & (0x0001 << i)))
463             {
464                 pKey->trg |= (0x0001 << i);     // Press trigger
465                 repeat_count[i] = 1;
466             }
467             else
468             {
469                 if (repeat_count[i] > KEY_REPEAT_START)
470                 {
471                     pKey->rep |= (0x0001 << i); // Press-and-hold repeat
472                     repeat_count[i] = KEY_REPEAT_START - KEY_REPEAT_SPAN;
473                 }
474                 else
475                 {
476                     repeat_count[i]++;
477                 }
478             }
479         }
480         else
481         {
482             if (pKey->cnt & (0x0001 << i))
483             {
484                 pKey->up |= (0x0001 << i);      // Release trigger
485             }
486         }
487     }
488     pKey->cnt = r;                     // Unprocessed key input
489 }
490 
491 /*---------------------------------------------------------------------------*
492   Name:         SetDrawData
493 
494   Description:  Stores the current newest sampled data in the buffer that puts it on the display.
495 
496 
497   Arguments:    address: Location in main memory where the most recent sampling data is stored by the components
498 
499                 type: Sampling type (bit width)
500 
501   Returns:      None.
502  *---------------------------------------------------------------------------*/
SetDrawData(void * address,MICSamplingType type)503 static void SetDrawData(void *address, MICSamplingType type)
504 {
505     s32     i;
506 
507     // If sampling has never been performed, do nothing and stop.
508     // (Because it would delete memory cache(s) unrelated to the microphone)
509     if ((address < gMicData) || (address >= (gMicData + TEST_BUFFER_SIZE)))
510     {
511         return;
512     }
513 
514     // In the case of 8-bit sampling
515     switch (type)
516     {
517     case MIC_SAMPLING_TYPE_8BIT:
518     case MIC_SAMPLING_TYPE_SIGNED_8BIT:
519         {
520             u8     *p;
521 
522             p = (u8 *)((u32)address - 191);
523             if (p < gMicData)
524             {
525                 p = (u8 *)((u32)p + TEST_BUFFER_SIZE);
526             }
527             DC_InvalidateRange((void *)((u32)p & 0xffffffe0), 32);
528             for (i = 0; i < 192; i++)
529             {
530                 gDrawData[i] = *p;
531                 p++;
532                 if ((u32)p >= (u32)(gMicData + TEST_BUFFER_SIZE))
533                 {
534                     p -= TEST_BUFFER_SIZE;
535                 }
536                 if (((u32)p % 32) == 0)
537                 {
538                     DC_InvalidateRange(p, 32);
539                 }
540             }
541         }
542         break;
543     case MIC_SAMPLING_TYPE_12BIT:
544     case MIC_SAMPLING_TYPE_SIGNED_12BIT:
545     case MIC_SAMPLING_TYPE_12BIT_FILTER_OFF:
546     case MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF:
547         {
548             u16    *p;
549 
550             p = (u16 *)((u32)address - 382);
551             if ((u32)p < (u32)gMicData)
552             {
553                 p = (u16 *)((u32)p + TEST_BUFFER_SIZE);
554             }
555             DC_InvalidateRange((void *)((u32)p & 0xffffffe0), 32);
556             for (i = 0; i < 192; i++)
557             {
558                 gDrawData[i] = (u8)((*p >> 8) & 0x00ff);
559                 p++;
560                 if ((u32)p >= (u32)(gMicData + TEST_BUFFER_SIZE))
561                 {
562                     p = (u16 *)((u32)p - TEST_BUFFER_SIZE);
563                 }
564                 if (((u32)p % 32) == 0)
565                 {
566                     DC_InvalidateRange(p, 32);
567                 }
568             }
569         }
570         break;
571     }
572 }
573 
574 /*---------------------------------------------------------------------------*
575   Name:         PrintfVariableData
576 
577   Description:  Print out the variable sampling settings.
578 
579   Arguments:    None.
580 
581   Returns:      None.
582  *---------------------------------------------------------------------------*/
PrintfVariableData(void)583 static void PrintfVariableData(void)
584 {
585     s32     range = 0;
586 
587     OS_Printf(" sampling-span: %d , bit-range: ", gMicAutoParam.rate);
588     switch (gMicAutoParam.type)
589     {
590     case MIC_SAMPLING_TYPE_8BIT:
591         OS_Printf("8");
592         break;
593     case MIC_SAMPLING_TYPE_12BIT:
594         OS_Printf("12");
595         break;
596     case MIC_SAMPLING_TYPE_SIGNED_8BIT:
597         OS_Printf("signed 8");
598         break;
599     case MIC_SAMPLING_TYPE_SIGNED_12BIT:
600         OS_Printf("signed 12");
601         break;
602     case MIC_SAMPLING_TYPE_12BIT_FILTER_OFF:
603         OS_Printf("12(filter off)");
604         break;
605     case MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF:
606         OS_Printf("signed 12(filter off)");
607         break;
608     }
609     if (gMicAutoParam.loop_enable)
610     {
611         OS_Printf(" , loop: on\n");
612     }
613     else
614     {
615         OS_Printf(" , loop: off\n");
616     }
617 }
618 
619 
620 /*---------------------------------------------------------------------------*
621   End of file
622  *---------------------------------------------------------------------------*/
623