/*---------------------------------------------------------------------------* Project: Revolution PMIC simple demo File: pmic_simple.c Copyright (C)2008 Nintendo All Rights Reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Log: pmic_simple.c,v $ Revision 1.5.2.3 2009/12/14 00:21:52 aka Fixed misspelling. Revision 1.5.2.2 2009/11/19 07:30:49 aka Copied from HEAD. Revision 1.7 2009/11/19 07:28:06 aka Removed WPADShutdown() & WPADDisconnect(). Revision 1.6 2009/10/15 07:15:34 aka Revised error handling of PMICQuit(). Revision 1.5 2009/04/17 06:34:21 ozeki_kohei Correct behavior for the case that device is detached while PMICQuit(). Revision 1.4 2009/03/11 07:24:21 aka Added SOUT meter. Revision 1.1.4.2 2009/03/11 07:21:41 aka Added SOUT meter. Revision 1.1.4.1 2008/08/28 01:36:31 aka Copied from HEAD. Revision 1.3 2008/08/06 01:39:14 carlmu Added graphic demo. Revision 1.2 2008/08/04 23:52:55 carlmu Simplified the demo state machine. Added ability to exit the demo completely. Revision 1.1 2008/01/22 02:50:19 aka initial check-in. $NoKeywords: $ *---------------------------------------------------------------------------*/ #include #include #include #include #include #include "audio.h" #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 240 BOOL PMICIsUp( void ); static MEMHeapHandle mem2Heap; static u16 button; static void* myAlloc ( u32 size ); static u8 myFree ( void* ptr ); static BOOL usePMIC ( void ); static void printInfo ( void ); static void printLM ( void ); /*---------------------------------------------------------------------------* Name: main Description: main func. Arguments: none. Returns: none. *---------------------------------------------------------------------------*/ void main(void) { void* arenaMem2Lo; void* arenaMem2Hi; s32 status; u32 type; WPADStatus currWpad; WPADStatus prevWpad; BOOL running = TRUE; // init DEMO lib. DEMOInit(&GXNtsc480IntDf); DEMOInitCaption(DM_FT_XLU, SCREEN_WIDTH, SCREEN_HEIGHT); DEMOPadInit(); // init MEM lib. arenaMem2Lo = OSGetMEM2ArenaLo(); arenaMem2Hi = OSGetMEM2ArenaHi(); mem2Heap = MEMCreateExpHeap(arenaMem2Lo, (u32)arenaMem2Hi - (u32) arenaMem2Lo); // init Audio libs. AUDIOInit(&mem2Heap, NULL); // NULL means use default processing function // init WPAD. WPADRegisterAllocator(myAlloc, myFree); WPADInit(); OSReport ("\n\n"); OSReport ("************************************************\n"); OSReport ("pmic_simple: Simple demo for Party Mic device\n"); OSReport ("************************************************\n"); OSReport ("This demo requires the Party Mic and a Wii Remote.\n"); OSReport ("Push Button A to start recording, speak,\n"); OSReport ("then push button A again to hear results.\n"); OSReport ("See messages for other instructions.\n"); OSReport ("\n"); do { status = WPADGetStatus(); } while (WPAD_STATE_SETUP != status); memset(&currWpad, 0, sizeof(WPADStatus)); memset(&prevWpad, 0, sizeof(WPADStatus)); // spin... while (running) { // read Remote. status = WPADProbe(WPAD_CHAN0, &type); if (WPAD_ERR_NONE == status) { WPADRead(WPAD_CHAN0, &currWpad); } button = WPADButtonDown(prevWpad.button, currWpad.button); prevWpad = currWpad; // operate P-Mic. running = usePMIC(); // print info & SOUT meter DEMOBeforeRender(); printInfo(); printLM(); DEMODoneRender(); } // Kill audio AUDIOQuit(); OSHalt("Demo finished!\n"); } /*---------------------------------------------------------------------------* Name: myAlloc Description: allocate memory. Arguments: size bytes to allocate. Returns: pointer. *---------------------------------------------------------------------------*/ static void* myAlloc(u32 size) { void *ptr; ptr = MEMAllocFromExpHeap(mem2Heap, size); return ptr; } /*---------------------------------------------------------------------------* Name: myFree Description: free memory. Arguments: ptr pointer to free. Returns: always 1. *---------------------------------------------------------------------------*/ static u8 myFree(void* ptr) { MEMFreeToExpHeap(mem2Heap, ptr); return 1; } /*---------------------------------------------------------------------------* *---------------------------------------------------------------------------* * very simple P-Mic operation... * *---------------------------------------------------------------------------* *---------------------------------------------------------------------------*/ enum { STATE_NOT_INITIALIZED=0, STATE_NOT_READY, STATE_PROBE, STATE_OPEN, STATE_WAIT_FOR_OPEN, STATE_STOPPED, STATE_START, STATE_WAIT_FOR_START, STATE_RUN, STATE_DO_STOP, STATE_WAIT_FOR_STOP, STATE_CLOSE, STATE_WAIT_FOR_CLOSE, STATE_WAIT_REOPEN, STATE_QUIT, STATE_WAIT_RESTART, STATE_DIE }; static u32 state = STATE_NOT_INITIALIZED; static volatile PMIC_ERR errCode; static volatile BOOL gettingSout = FALSE; static volatile u16 sout; static void funcCb ( PMIC_ERR result, void* arg ); static void levelCb ( PMIC_ERR result, void* arg ); /*---------------------------------------------------------------------------* Name: PMICIsUp Description: Indicates if P-Mic library has been initialized Arguments: none. Returns: BOOL indicating whether P-Mic library has been initialized *---------------------------------------------------------------------------*/ BOOL PMICIsUp(void) { if (state == STATE_NOT_INITIALIZED || state == STATE_QUIT || state == STATE_WAIT_RESTART) { return FALSE; } return TRUE; } /*---------------------------------------------------------------------------* Name: usePMIC Description: operate P-Mic. Arguments: none. Returns: BOOL indicating whether to continue running or not. *---------------------------------------------------------------------------*/ static BOOL usePMIC(void) { static s32 count = 0; static u8* work; PMIC_ERR retval; switch (state) { case STATE_NOT_INITIALIZED: work = MEMAllocFromExpHeapEx(mem2Heap, PMIC_MEM2_WORK, 32); retval = PMICInit(work); if (retval == PMIC_ERR_OK) { OSReport("(%ld) ok to call PMICInit() -> %ld\n", count++, retval); state = STATE_NOT_READY; } else { OSReport("(%ld) fail to call PMICInit() -> %ld\n", count++, retval); state = STATE_DIE; // fatal } break; case STATE_NOT_READY: state = STATE_PROBE; break; case STATE_PROBE: retval = PMICProbe(); if (retval == PMIC_ERR_OK) { OSReport("(%ld) P-Mic is inserted -> %ld\n", count++, retval); state = STATE_OPEN; } else if (retval != PMIC_ERR_NO_DEVICE) { OSReport("(%ld) fail to call PMICProbe() -> %ld\n", count++, retval); state = STATE_DIE; } else if (button & WPAD_BUTTON_B) { state = STATE_QUIT; } break; case STATE_OPEN: errCode = (PMIC_ERR)(PMIC_ERR_OK + 1); retval = PMICOpenAsync(funcCb, NULL); if (retval == PMIC_ERR_OK) { OSReport("(%ld) ok to call PMICOpenAsync() -> %ld\n", count++, retval); state = STATE_WAIT_FOR_OPEN; } else { OSReport("(%ld) fail to call PMICOpenAsync() -> %ld\n", count++, retval); state = STATE_NOT_READY; // probe again } break; case STATE_WAIT_FOR_OPEN: // errCode comes from the PMICOpenAsync callback if (errCode > PMIC_ERR_OK) { // still waiting? break; } else if (errCode == PMIC_ERR_OK) { OSReport("(%ld) ok to open P-Mic -> %ld.\n", count++, errCode); state = STATE_STOPPED; } else { OSReport("(%ld) fail to open P-Mic -> %ld.\n", count++, errCode); state = STATE_NOT_READY; // probe again } break; case STATE_STOPPED: retval = PMICProbe(); if (retval == PMIC_ERR_NO_DEVICE) { OSReport("(%ld) P-Mic is removed -> %ld\n", count++, retval); state = STATE_NOT_READY; } else if (retval != PMIC_ERR_OK) { OSReport("(%ld) fail to call PMICProbe() -> %ld\n", count++, retval); state = STATE_DIE; } else if (button & WPAD_BUTTON_A) { AUDIOStopPlay(); // stop playing p-mic data state = STATE_START; } else if (button & WPAD_BUTTON_B) { state = STATE_CLOSE; } break; case STATE_START: errCode = (PMIC_ERR)(PMIC_ERR_OK + 1); retval = PMICStartAsync(funcCb, NULL); if (retval == PMIC_ERR_OK) { OSReport("(%ld) ok to call PMICStartAsync() -> %ld\n", count++, retval); state = STATE_WAIT_FOR_START; } else { OSReport("(%ld) fail to call PMICStartAsync() -> %ld\n", count++, retval); state = STATE_NOT_READY; } break; case STATE_WAIT_FOR_START: // errCode is returned by PMICStartAsync callback if (errCode > PMIC_ERR_OK) { // still waiting? break; } else if (errCode == PMIC_ERR_OK) { OSReport("(%ld) ok to start P-Mic -> %ld.\n", count++, errCode); state = STATE_RUN; sout = 0; } else { OSReport("(%ld) fail to start P-Mic -> %ld.\n", count++, errCode); state = STATE_NOT_READY; } break; case STATE_RUN: retval = PMICProbe(); if (retval == PMIC_ERR_NO_DEVICE) { OSReport("(%ld) P-Mic is removed -> %ld\n", count++, retval); state = STATE_NOT_READY; sout = 0; } else if (retval != PMIC_ERR_OK) { OSReport("(%ld) fail to call PMICProbe() -> %ld\n", count++, retval); state = STATE_DIE; sout = 0; } else if (button & WPAD_BUTTON_A) { AUDIOStartPlay(); // start playing p-mic data state = STATE_DO_STOP; sout = 0; } else if (button & WPAD_BUTTON_B) { state = STATE_CLOSE; sout = 0; } else if (!gettingSout) { // get current sout level retval = PMICGetLevelAsync(PMIC_LEVEL_SOUT, (u16*)&sout, levelCb, NULL); if (retval == PMIC_ERR_OK) { gettingSout = TRUE; } } break; case STATE_DO_STOP: errCode = (PMIC_ERR)(PMIC_ERR_OK + 1); retval = PMICStopAsync(funcCb, NULL); if (retval == PMIC_ERR_OK) { OSReport("(%ld) ok to call PMICStopAsync() -> %ld\n", count++, retval); state = STATE_WAIT_FOR_STOP; } else { OSReport("(%ld) fail to call PMICStopAsync() -> %ld\n", count++, retval); state = STATE_NOT_READY; } break; case STATE_WAIT_FOR_STOP: // errCode comes from the PMICStopAsync callback if (errCode > PMIC_ERR_OK) // still waiting? { break; } else if (errCode == PMIC_ERR_OK) { OSReport("(%ld) ok to stop P-Mic -> %ld.\n", count++, errCode); state = STATE_STOPPED; } else { OSReport("(%ld) fail to stop P-Mic -> %ld.\n", count++, errCode); state = STATE_NOT_READY; } break; case STATE_CLOSE: errCode = (PMIC_ERR)(PMIC_ERR_OK + 1); retval = PMICCloseAsync(funcCb, NULL); if (retval == PMIC_ERR_OK) { OSReport("(%ld) ok to call PMICCloseAsync() -> %ld\n", count++, retval); state = STATE_WAIT_FOR_CLOSE; } else { OSReport("(%ld) fail to call PMICCloseAsync() -> %ld\n", count++, retval); state = STATE_NOT_READY; } break; case STATE_WAIT_FOR_CLOSE: // errCode comes from the PMICCloseAsync callback if (errCode > PMIC_ERR_OK) // still waiting? { break; } else if (errCode == PMIC_ERR_OK) { OSReport("(%ld) ok to close P-Mic -> %ld.\n", count++, errCode); state = STATE_WAIT_REOPEN; } else { OSReport("(%ld) fail to close P-Mic -> %ld.\n", count++, errCode); state = STATE_NOT_READY; // or DIE? } break; case STATE_WAIT_REOPEN: if (button & WPAD_BUTTON_A) { state = STATE_OPEN; } else if (button & WPAD_BUTTON_B) { state = STATE_QUIT; } break; case STATE_QUIT: retval = PMICQuit(); if (retval == PMIC_ERR_OK) { MEMFreeToExpHeap(mem2Heap, work); OSReport("(%ld) ok to call PMICQuit() -> %ld\n", count++, retval); state = STATE_WAIT_RESTART; } else { OSReport("(%ld) fail to call PMICQuit() -> %ld\n", count++, retval); state = STATE_DIE; } break; case STATE_WAIT_RESTART: if (button & WPAD_BUTTON_A) { state = STATE_NOT_INITIALIZED; } else if (button & WPAD_BUTTON_B) { state = STATE_DIE; } break; case STATE_DIE: return FALSE; } return TRUE; } /*---------------------------------------------------------------------------* Name: funcCb Description: callback for PMICOpen/Close/Start/StopAsync Arguments: result error code. arg (not used.) Returns: none. *---------------------------------------------------------------------------*/ static void funcCb(PMIC_ERR result, void* arg) { #pragma unused(arg) errCode = result; } /*---------------------------------------------------------------------------* Name: levelCb Description: callback for PMICGetLevelAsync Arguments: result (not used.) arg (not used.) Returns: none. *---------------------------------------------------------------------------*/ static void levelCb(PMIC_ERR result, void* arg) { #pragma unused(result) #pragma unused(arg) gettingSout = FALSE; } /*---------------------------------------------------------------------------* Name: printInfo Description: print P-Mic information. Arguments: none. Returns: none. *---------------------------------------------------------------------------*/ static void printInfo(void) { DEMOPrintf(10, 10, 0, "************************************"); DEMOPrintf(10, 20, 0, " pmic_simple: Simple demo for P-Mic"); DEMOPrintf(10, 30, 0, "************************************"); switch (state) { case STATE_NOT_INITIALIZED: case STATE_NOT_READY: break; case STATE_PROBE: DEMOPrintf(60, 50, 0, "Insert P-Mic,"); DEMOPrintf(60, 60, 0, "or Push B to quit lib."); break; case STATE_OPEN: case STATE_WAIT_FOR_OPEN: DEMOPrintf(60, 50, 0, "Got P-Mic. Opening..."); break; case STATE_STOPPED: DEMOPrintf(60, 50, 0, "Push A to start P-Mic,"); DEMOPrintf(60, 60, 0, "or B to close P-Mic,"); DEMOPrintf(60, 70, 0, "or Remove P-Mic."); break; case STATE_START: case STATE_WAIT_FOR_START: DEMOPrintf(60, 50, 0, "Starting..."); break; case STATE_RUN: DEMOPrintf(60, 50, 0, "Push A to stop P-Mic,"); DEMOPrintf(60, 60, 0, "or B to close P-Mic,"); DEMOPrintf(60, 70, 0, "or Remove P-Mic."); break; case STATE_DO_STOP: case STATE_WAIT_FOR_STOP: DEMOPrintf(60, 50, 0, "Stopping..."); break; case STATE_CLOSE: case STATE_WAIT_FOR_CLOSE: DEMOPrintf(60, 50, 0, "Closing..."); break; case STATE_WAIT_REOPEN: DEMOPrintf(60, 50, 0, "Push A to open P-Mic,"); DEMOPrintf(60, 60, 0, "or B to quit lib."); break; case STATE_QUIT: break; case STATE_WAIT_RESTART: DEMOPrintf(60, 50, 0, "Push A to init P-Mic,"); DEMOPrintf(60, 60, 0, "or B to quit application."); break; case STATE_DIE: DEMOPrintf(60, 50, 0, "done"); break; } } /*---------------------------------------------------------------------------* Name: printLM Description: print Level Meter. Arguments: none. Returns: none. *---------------------------------------------------------------------------*/ static u16 maxLevels[17] = { 0x0053, // <= -39dBm0 0x0075, // <= -36dBm0 0x00A5, // <= -33dBm0 0x00EA, // <= -30dBm0 0x014A, // <= -27dBm0 0x01D3, // <= -24dBm0 0x0293, // <= -21dBm0 0x03A3, // <= -18dBm0 0x0524, // <= -15dBm0 0x0743, // <= -12dBm0 0x0A42, // <= - 9dBm0 0x0E7D, // <= - 6dBm0 0x1477, // <= - 3dBm0 0x1CE9, // <= + 0dBm0 0x28D7, // <= + 3dBm0 0x39B0, // <= + 6dBm0 0x517C // <= + 9dBm0 }; static char showLevels[17][39] = { "................ <-39dBm0", ">............... -36dBm0", ">>.............. -33dBm0", ">>>............. -30dBm0", ">>>>............ -27dBm0", ">>>>>........... -24dBm0", ">>>>>>.......... -21dBm0", ">>>>>>>......... -18dBm0", ">>>>>>>>........ -15dBm0", ">>>>>>>>>....... -12dBm0", ">>>>>>>>>>...... -9dBm0", ">>>>>>>>>>>..... -6dBm0", ">>>>>>>>>>>>.... -3dBm0", ">>>>>>>>>>>>>... +0dBm0", ">>>>>>>>>>>>>>.. +3dBm0", ">>>>>>>>>>>>>>>. +6dBm0", ">>>>>>>>>>>>>>>> >+6dBm0" }; static void printLM(void) { s32 i; for (i = 0; i < 16; i++) { if (sout <= maxLevels[i]) { break; } } DEMOPrintf(60, 110, 0, "Level Meter"); DEMOPrintf(60, 120, 0, "%s", showLevels[i]); }