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