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