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