1 /*---------------------------------------------------------------------------*
2   Project:  Revolution PMIC simple demo
3   File:     pmic_simple.c
4 
5   Copyright (C)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   $Log: pmic_simple.c,v $
14   Revision 1.5.2.3  2009/12/14 00:21:52  aka
15   Fixed misspelling.
16 
17   Revision 1.5.2.2  2009/11/19 07:30:49  aka
18   Copied from HEAD.
19 
20   Revision 1.7  2009/11/19 07:28:06  aka
21   Removed WPADShutdown() & WPADDisconnect().
22 
23   Revision 1.6  2009/10/15 07:15:34  aka
24   Revised error handling of PMICQuit().
25 
26   Revision 1.5  2009/04/17 06:34:21  ozeki_kohei
27   Correct behavior for the case that device is detached while PMICQuit().
28 
29   Revision 1.4  2009/03/11 07:24:21  aka
30   Added SOUT meter.
31 
32   Revision 1.1.4.2  2009/03/11 07:21:41  aka
33   Added SOUT meter.
34 
35   Revision 1.1.4.1  2008/08/28 01:36:31  aka
36   Copied from HEAD.
37 
38   Revision 1.3  2008/08/06 01:39:14  carlmu
39   Added graphic demo.
40 
41   Revision 1.2  2008/08/04 23:52:55  carlmu
42   Simplified the demo state machine.
43   Added ability to exit the demo completely.
44 
45   Revision 1.1  2008/01/22 02:50:19  aka
46   initial check-in.
47 
48   $NoKeywords: $
49  *---------------------------------------------------------------------------*/
50 
51 #include <string.h>
52 #include <demo.h>
53 #include <revolution/mem.h>
54 #include <revolution/pmic.h>
55 #include <revolution/wpad.h>
56 
57 #include "audio.h"
58 
59 #define SCREEN_WIDTH  320
60 #define SCREEN_HEIGHT 240
61 
62 BOOL  PMICIsUp( void );
63 
64 static MEMHeapHandle  mem2Heap;
65 static u16            button;
66 
67 static void* myAlloc   ( u32 size );
68 static u8    myFree    ( void* ptr );
69 static BOOL  usePMIC   ( void );
70 static void  printInfo ( void );
71 static void  printLM   ( void );
72 
73 /*---------------------------------------------------------------------------*
74   Name:         main
75 
76   Description:  main func.
77 
78   Arguments:    none.
79 
80   Returns:      none.
81  *---------------------------------------------------------------------------*/
82 
main(void)83 void main(void)
84 {
85     void*       arenaMem2Lo;
86     void*       arenaMem2Hi;
87     s32         status;
88     u32         type;
89     WPADStatus  currWpad;
90     WPADStatus  prevWpad;
91     BOOL        running = TRUE;
92 
93     // init DEMO lib.
94     DEMOInit(&GXNtsc480IntDf);
95     DEMOInitCaption(DM_FT_XLU, SCREEN_WIDTH, SCREEN_HEIGHT);
96     DEMOPadInit();
97 
98     // init MEM lib.
99     arenaMem2Lo = OSGetMEM2ArenaLo();
100     arenaMem2Hi = OSGetMEM2ArenaHi();
101     mem2Heap    = MEMCreateExpHeap(arenaMem2Lo, (u32)arenaMem2Hi - (u32) arenaMem2Lo);
102 
103     // init Audio libs.
104     AUDIOInit(&mem2Heap, NULL); // NULL means use default processing function
105 
106     // init WPAD.
107     WPADRegisterAllocator(myAlloc, myFree);
108     WPADInit();
109 
110     OSReport ("\n\n");
111     OSReport ("************************************************\n");
112     OSReport ("pmic_simple: Simple demo for Party Mic device\n");
113     OSReport ("************************************************\n");
114     OSReport ("This demo requires the Party Mic and a Wii Remote.\n");
115     OSReport ("Push Button A to start recording, speak,\n");
116     OSReport ("then push button A again to hear results.\n");
117     OSReport ("See messages for other instructions.\n");
118     OSReport ("\n");
119 
120     do
121     {
122         status = WPADGetStatus();
123 
124     } while (WPAD_STATE_SETUP != status);
125 
126     memset(&currWpad, 0, sizeof(WPADStatus));
127     memset(&prevWpad, 0, sizeof(WPADStatus));
128 
129     // spin...
130     while (running)
131     {
132         // read Remote.
133         status = WPADProbe(WPAD_CHAN0, &type);
134 
135         if (WPAD_ERR_NONE == status)
136         {
137             WPADRead(WPAD_CHAN0, &currWpad);
138         }
139 
140         button   = WPADButtonDown(prevWpad.button, currWpad.button);
141         prevWpad = currWpad;
142 
143         // operate P-Mic.
144         running = usePMIC();
145 
146         // print info & SOUT meter
147         DEMOBeforeRender();
148         printInfo();
149         printLM();
150         DEMODoneRender();
151     }
152 
153     // Kill audio
154     AUDIOQuit();
155 
156     OSHalt("Demo finished!\n");
157 }
158 
159 /*---------------------------------------------------------------------------*
160   Name:         myAlloc
161 
162   Description:  allocate memory.
163 
164   Arguments:    size    bytes to allocate.
165 
166   Returns:      pointer.
167  *---------------------------------------------------------------------------*/
168 
myAlloc(u32 size)169 static void* myAlloc(u32 size)
170 {
171     void *ptr;
172 
173     ptr = MEMAllocFromExpHeap(mem2Heap, size);
174 
175     return ptr;
176 }
177 
178 /*---------------------------------------------------------------------------*
179   Name:         myFree
180 
181   Description:  free memory.
182 
183   Arguments:    ptr    pointer to free.
184 
185   Returns:      always 1.
186  *---------------------------------------------------------------------------*/
187 
myFree(void * ptr)188 static u8 myFree(void* ptr)
189 {
190     MEMFreeToExpHeap(mem2Heap, ptr);
191 
192     return 1;
193 }
194 
195 /*---------------------------------------------------------------------------*
196  *---------------------------------------------------------------------------*
197  *                      very simple P-Mic operation...                       *
198  *---------------------------------------------------------------------------*
199  *---------------------------------------------------------------------------*/
200 
201 enum
202 {
203     STATE_NOT_INITIALIZED=0,
204     STATE_NOT_READY,
205     STATE_PROBE,
206     STATE_OPEN,
207     STATE_WAIT_FOR_OPEN,
208     STATE_STOPPED,
209     STATE_START,
210     STATE_WAIT_FOR_START,
211     STATE_RUN,
212     STATE_DO_STOP,
213     STATE_WAIT_FOR_STOP,
214 
215     STATE_CLOSE,
216     STATE_WAIT_FOR_CLOSE,
217     STATE_WAIT_REOPEN,
218     STATE_QUIT,
219     STATE_WAIT_RESTART,
220     STATE_DIE
221 };
222 
223 static u32 state = STATE_NOT_INITIALIZED;
224 
225 static volatile PMIC_ERR  errCode;
226 static volatile BOOL      gettingSout = FALSE;
227 static volatile u16       sout;
228 
229 static void funcCb  ( PMIC_ERR result, void* arg );
230 static void levelCb ( PMIC_ERR result, void* arg );
231 
232 /*---------------------------------------------------------------------------*
233   Name:         PMICIsUp
234 
235   Description:  Indicates if P-Mic library has been initialized
236 
237   Arguments:    none.
238 
239   Returns:      BOOL indicating whether P-Mic library has been initialized
240  *---------------------------------------------------------------------------*/
241 
PMICIsUp(void)242 BOOL PMICIsUp(void)
243 {
244     if (state == STATE_NOT_INITIALIZED ||
245         state == STATE_QUIT ||
246         state == STATE_WAIT_RESTART)
247     {
248             return FALSE;
249     }
250 
251     return TRUE;
252 }
253 
254 /*---------------------------------------------------------------------------*
255   Name:         usePMIC
256 
257   Description:  operate P-Mic.
258 
259   Arguments:    none.
260 
261   Returns:      BOOL indicating whether to continue running or not.
262  *---------------------------------------------------------------------------*/
263 
usePMIC(void)264 static BOOL usePMIC(void)
265 {
266     static s32 count = 0;
267     static u8* work;
268 
269     PMIC_ERR  retval;
270 
271     switch (state)
272     {
273 
274         case STATE_NOT_INITIALIZED:
275 
276             work = MEMAllocFromExpHeapEx(mem2Heap, PMIC_MEM2_WORK, 32);
277             retval = PMICInit(work);
278 
279             if (retval == PMIC_ERR_OK)
280             {
281                 OSReport("(%ld) ok to call PMICInit() -> %ld\n", count++, retval);
282                 state = STATE_NOT_READY;
283             }
284             else
285             {
286                 OSReport("(%ld) fail to call PMICInit() -> %ld\n", count++, retval);
287                 state = STATE_DIE; // fatal
288             }
289             break;
290 
291         case STATE_NOT_READY:
292 
293             state = STATE_PROBE;
294             break;
295 
296         case STATE_PROBE:
297 
298             retval = PMICProbe();
299 
300             if (retval == PMIC_ERR_OK)
301             {
302                 OSReport("(%ld) P-Mic is inserted -> %ld\n", count++, retval);
303                 state = STATE_OPEN;
304             }
305             else if (retval != PMIC_ERR_NO_DEVICE)
306             {
307                 OSReport("(%ld) fail to call PMICProbe() -> %ld\n", count++, retval);
308                 state = STATE_DIE;
309             }
310             else if (button & WPAD_BUTTON_B)
311             {
312                 state = STATE_QUIT;
313             }
314             break;
315 
316         case STATE_OPEN:
317 
318             errCode = (PMIC_ERR)(PMIC_ERR_OK + 1);
319             retval = PMICOpenAsync(funcCb, NULL);
320 
321             if (retval == PMIC_ERR_OK)
322             {
323                 OSReport("(%ld) ok to call PMICOpenAsync() -> %ld\n", count++, retval);
324                 state = STATE_WAIT_FOR_OPEN;
325             }
326             else
327             {
328                 OSReport("(%ld) fail to call PMICOpenAsync() -> %ld\n", count++, retval);
329                 state = STATE_NOT_READY; // probe again
330             }
331             break;
332 
333         case STATE_WAIT_FOR_OPEN:
334 
335             // errCode comes from the PMICOpenAsync callback
336             if (errCode > PMIC_ERR_OK) { // still waiting?
337                 break;
338             }
339             else if (errCode == PMIC_ERR_OK)
340             {
341                 OSReport("(%ld) ok to open P-Mic -> %ld.\n", count++, errCode);
342                 state = STATE_STOPPED;
343             }
344             else
345             {
346                 OSReport("(%ld) fail to open P-Mic -> %ld.\n", count++, errCode);
347                 state = STATE_NOT_READY; // probe again
348             }
349             break;
350 
351         case STATE_STOPPED:
352 
353             retval = PMICProbe();
354 
355             if (retval == PMIC_ERR_NO_DEVICE)
356             {
357                 OSReport("(%ld) P-Mic is removed -> %ld\n", count++, retval);
358                 state = STATE_NOT_READY;
359             }
360             else if (retval != PMIC_ERR_OK)
361             {
362                 OSReport("(%ld) fail to call PMICProbe() -> %ld\n", count++, retval);
363                 state = STATE_DIE;
364             }
365             else if (button & WPAD_BUTTON_A)
366             {
367                 AUDIOStopPlay(); // stop playing p-mic data
368                 state = STATE_START;
369             }
370             else if (button & WPAD_BUTTON_B)
371             {
372                 state = STATE_CLOSE;
373             }
374             break;
375 
376         case STATE_START:
377 
378             errCode = (PMIC_ERR)(PMIC_ERR_OK + 1);
379             retval = PMICStartAsync(funcCb, NULL);
380 
381             if (retval == PMIC_ERR_OK)
382             {
383                 OSReport("(%ld) ok to call PMICStartAsync() -> %ld\n", count++, retval);
384                 state = STATE_WAIT_FOR_START;
385             }
386             else
387             {
388                 OSReport("(%ld) fail to call PMICStartAsync() -> %ld\n", count++, retval);
389                 state = STATE_NOT_READY;
390             }
391             break;
392 
393         case STATE_WAIT_FOR_START:
394 
395             // errCode is returned by PMICStartAsync callback
396             if (errCode > PMIC_ERR_OK)
397             {
398                 // still waiting?
399                 break;
400             }
401             else if (errCode == PMIC_ERR_OK)
402             {
403                 OSReport("(%ld) ok to start P-Mic -> %ld.\n", count++, errCode);
404                 state = STATE_RUN;
405                 sout  = 0;
406             }
407             else
408             {
409                 OSReport("(%ld) fail to start P-Mic -> %ld.\n", count++, errCode);
410                 state = STATE_NOT_READY;
411             }
412             break;
413 
414         case STATE_RUN:
415 
416             retval = PMICProbe();
417 
418             if (retval == PMIC_ERR_NO_DEVICE)
419             {
420                 OSReport("(%ld) P-Mic is removed -> %ld\n", count++, retval);
421                 state = STATE_NOT_READY;
422                 sout  = 0;
423             }
424             else if (retval != PMIC_ERR_OK)
425             {
426                 OSReport("(%ld) fail to call PMICProbe() -> %ld\n", count++, retval);
427                 state = STATE_DIE;
428                 sout  = 0;
429             }
430             else if (button & WPAD_BUTTON_A)
431             {
432                 AUDIOStartPlay(); // start playing p-mic data
433                 state = STATE_DO_STOP;
434                 sout  = 0;
435             }
436             else if (button & WPAD_BUTTON_B)
437             {
438                 state = STATE_CLOSE;
439                 sout  = 0;
440             }
441             else if (!gettingSout)
442             {
443                 // get current sout level
444                 retval = PMICGetLevelAsync(PMIC_LEVEL_SOUT, (u16*)&sout, levelCb, NULL);
445 
446                 if (retval == PMIC_ERR_OK)
447                 {
448                     gettingSout = TRUE;
449                 }
450             }
451             break;
452 
453         case STATE_DO_STOP:
454 
455             errCode = (PMIC_ERR)(PMIC_ERR_OK + 1);
456             retval = PMICStopAsync(funcCb, NULL);
457 
458             if (retval == PMIC_ERR_OK)
459             {
460                 OSReport("(%ld) ok to call PMICStopAsync() -> %ld\n", count++, retval);
461                 state = STATE_WAIT_FOR_STOP;
462             }
463             else
464             {
465                 OSReport("(%ld) fail to call PMICStopAsync() -> %ld\n", count++, retval);
466                 state = STATE_NOT_READY;
467             }
468             break;
469 
470         case STATE_WAIT_FOR_STOP:
471 
472             // errCode comes from the PMICStopAsync callback
473             if (errCode > PMIC_ERR_OK) // still waiting?
474             {
475                 break;
476             }
477             else if (errCode == PMIC_ERR_OK)
478             {
479                 OSReport("(%ld) ok to stop P-Mic -> %ld.\n", count++, errCode);
480                 state = STATE_STOPPED;
481             }
482             else
483             {
484                 OSReport("(%ld) fail to stop P-Mic -> %ld.\n", count++, errCode);
485                 state = STATE_NOT_READY;
486             }
487             break;
488 
489         case STATE_CLOSE:
490 
491             errCode = (PMIC_ERR)(PMIC_ERR_OK + 1);
492             retval = PMICCloseAsync(funcCb, NULL);
493 
494             if (retval == PMIC_ERR_OK)
495             {
496                 OSReport("(%ld) ok to call PMICCloseAsync() -> %ld\n", count++, retval);
497                 state = STATE_WAIT_FOR_CLOSE;
498             }
499             else
500             {
501                 OSReport("(%ld) fail to call PMICCloseAsync() -> %ld\n", count++, retval);
502                 state = STATE_NOT_READY;
503             }
504             break;
505 
506         case STATE_WAIT_FOR_CLOSE:
507 
508             // errCode comes from the PMICCloseAsync callback
509             if (errCode > PMIC_ERR_OK) // still waiting?
510             {
511                 break;
512             } else if (errCode == PMIC_ERR_OK)
513             {
514                 OSReport("(%ld) ok to close P-Mic -> %ld.\n", count++, errCode);
515                 state = STATE_WAIT_REOPEN;
516             }
517             else
518             {
519                 OSReport("(%ld) fail to close P-Mic -> %ld.\n", count++, errCode);
520                 state = STATE_NOT_READY; // or DIE?
521             }
522             break;
523 
524         case STATE_WAIT_REOPEN:
525 
526             if (button & WPAD_BUTTON_A)
527             {
528                 state = STATE_OPEN;
529             }
530             else if (button & WPAD_BUTTON_B)
531             {
532                 state = STATE_QUIT;
533             }
534             break;
535 
536         case STATE_QUIT:
537 
538             retval = PMICQuit();
539 
540             if (retval == PMIC_ERR_OK)
541             {
542                 MEMFreeToExpHeap(mem2Heap, work);
543 
544                 OSReport("(%ld) ok to call PMICQuit() -> %ld\n", count++, retval);
545                 state = STATE_WAIT_RESTART;
546             }
547             else
548             {
549                 OSReport("(%ld) fail to call PMICQuit() -> %ld\n", count++, retval);
550                 state = STATE_DIE;
551             }
552             break;
553 
554         case STATE_WAIT_RESTART:
555 
556             if (button & WPAD_BUTTON_A)
557             {
558                 state = STATE_NOT_INITIALIZED;
559             }
560             else if (button & WPAD_BUTTON_B)
561             {
562                 state = STATE_DIE;
563             }
564             break;
565 
566         case STATE_DIE:
567 
568             return FALSE;
569     }
570 
571     return TRUE;
572 }
573 
574 /*---------------------------------------------------------------------------*
575   Name:         funcCb
576 
577   Description:  callback for PMICOpen/Close/Start/StopAsync
578 
579   Arguments:    result    error code.
580                 arg       (not used.)
581 
582   Returns:      none.
583  *---------------------------------------------------------------------------*/
584 
funcCb(PMIC_ERR result,void * arg)585 static void funcCb(PMIC_ERR result, void* arg)
586 {
587 #pragma unused(arg)
588 
589     errCode = result;
590 }
591 
592 /*---------------------------------------------------------------------------*
593   Name:         levelCb
594 
595   Description:  callback for PMICGetLevelAsync
596 
597   Arguments:    result    (not used.)
598                 arg       (not used.)
599 
600   Returns:      none.
601  *---------------------------------------------------------------------------*/
602 
levelCb(PMIC_ERR result,void * arg)603 static void levelCb(PMIC_ERR result, void* arg)
604 {
605 #pragma unused(result)
606 #pragma unused(arg)
607 
608     gettingSout = FALSE;
609 }
610 
611 /*---------------------------------------------------------------------------*
612   Name:         printInfo
613 
614   Description:  print P-Mic information.
615 
616   Arguments:    none.
617 
618   Returns:      none.
619  *---------------------------------------------------------------------------*/
620 
printInfo(void)621 static void printInfo(void)
622 {
623     DEMOPrintf(10, 10, 0, "************************************");
624     DEMOPrintf(10, 20, 0, " pmic_simple: Simple demo for P-Mic");
625     DEMOPrintf(10, 30, 0, "************************************");
626 
627     switch (state)
628     {
629         case STATE_NOT_INITIALIZED:
630         case STATE_NOT_READY:
631 
632             break;
633 
634         case STATE_PROBE:
635 
636             DEMOPrintf(60, 50, 0, "Insert P-Mic,");
637             DEMOPrintf(60, 60, 0, "or Push B to quit lib.");
638             break;
639 
640         case STATE_OPEN:
641         case STATE_WAIT_FOR_OPEN:
642 
643             DEMOPrintf(60, 50, 0, "Got P-Mic. Opening...");
644             break;
645 
646         case STATE_STOPPED:
647 
648             DEMOPrintf(60, 50, 0, "Push A to start P-Mic,");
649             DEMOPrintf(60, 60, 0, "or B to close P-Mic,");
650             DEMOPrintf(60, 70, 0, "or Remove P-Mic.");
651             break;
652 
653         case STATE_START:
654         case STATE_WAIT_FOR_START:
655 
656             DEMOPrintf(60, 50, 0, "Starting...");
657             break;
658 
659         case STATE_RUN:
660 
661             DEMOPrintf(60, 50, 0, "Push A to stop P-Mic,");
662             DEMOPrintf(60, 60, 0, "or B to close P-Mic,");
663             DEMOPrintf(60, 70, 0, "or Remove P-Mic.");
664             break;
665 
666         case STATE_DO_STOP:
667         case STATE_WAIT_FOR_STOP:
668 
669             DEMOPrintf(60, 50, 0, "Stopping...");
670             break;
671 
672         case STATE_CLOSE:
673         case STATE_WAIT_FOR_CLOSE:
674 
675             DEMOPrintf(60, 50, 0, "Closing...");
676             break;
677 
678         case STATE_WAIT_REOPEN:
679 
680             DEMOPrintf(60, 50, 0, "Push A to open P-Mic,");
681             DEMOPrintf(60, 60, 0, "or B to quit lib.");
682             break;
683 
684         case STATE_QUIT:
685 
686             break;
687 
688         case STATE_WAIT_RESTART:
689 
690             DEMOPrintf(60, 50, 0, "Push A to init P-Mic,");
691             DEMOPrintf(60, 60, 0, "or B to quit application.");
692             break;
693 
694         case STATE_DIE:
695 
696             DEMOPrintf(60, 50, 0, "done");
697             break;
698     }
699 }
700 
701 /*---------------------------------------------------------------------------*
702   Name:         printLM
703 
704   Description:  print Level Meter.
705 
706   Arguments:    none.
707 
708   Returns:      none.
709  *---------------------------------------------------------------------------*/
710 
711 static u16 maxLevels[17] =
712 {
713     0x0053, // <= -39dBm0
714     0x0075, // <= -36dBm0
715     0x00A5, // <= -33dBm0
716     0x00EA, // <= -30dBm0
717     0x014A, // <= -27dBm0
718     0x01D3, // <= -24dBm0
719     0x0293, // <= -21dBm0
720     0x03A3, // <= -18dBm0
721     0x0524, // <= -15dBm0
722     0x0743, // <= -12dBm0
723     0x0A42, // <= - 9dBm0
724     0x0E7D, // <= - 6dBm0
725     0x1477, // <= - 3dBm0
726     0x1CE9, // <= + 0dBm0
727     0x28D7, // <= + 3dBm0
728     0x39B0, // <= + 6dBm0
729     0x517C  // <= + 9dBm0
730 };
731 
732 static char showLevels[17][39] =
733 {
734     "................ <-39dBm0",
735     ">...............  -36dBm0",
736     ">>..............  -33dBm0",
737     ">>>.............  -30dBm0",
738     ">>>>............  -27dBm0",
739     ">>>>>...........  -24dBm0",
740     ">>>>>>..........  -21dBm0",
741     ">>>>>>>.........  -18dBm0",
742     ">>>>>>>>........  -15dBm0",
743     ">>>>>>>>>.......  -12dBm0",
744     ">>>>>>>>>>......   -9dBm0",
745     ">>>>>>>>>>>.....   -6dBm0",
746     ">>>>>>>>>>>>....   -3dBm0",
747     ">>>>>>>>>>>>>...   +0dBm0",
748     ">>>>>>>>>>>>>>..   +3dBm0",
749     ">>>>>>>>>>>>>>>.   +6dBm0",
750     ">>>>>>>>>>>>>>>>  >+6dBm0"
751 };
752 
printLM(void)753 static void printLM(void)
754 {
755     s32 i;
756 
757     for (i = 0; i < 16; i++)
758     {
759         if (sout <= maxLevels[i])
760         {
761             break;
762         }
763     }
764 
765     DEMOPrintf(60, 110, 0, "Level Meter");
766     DEMOPrintf(60, 120, 0, "%s", showLevels[i]);
767 }
768