/*---------------------------------------------------------------------------* Project: KPAD weight demo program File: weight.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. *---------------------------------------------------------------------------*/ #include #include #include #define DEMO_USE_MEMLIB=1 // This turns on the DEMO library's MEM heaps. #include /*---------------------------------------------------------------------------* * Local Definitions *---------------------------------------------------------------------------*/ #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 240 #define BOX_WIDTH 80 #define BOX_HEIGHT 70 #define FONT_HEIGHT 10 #define BUFF_SIZE 16 GXColor smoke_clr = { 61, 61, 61, 255 } ; GXColor red_clr = { 237, 28, 36, 255 } ; GXColor blue_clr = { 0, 84,166, 255 } ; GXColor yellow_clr = { 255,242, 0, 255 } ; GXColor peagreen_clr = { 141,198, 63, 255 } ; static KPADStatus kpads [ BUFF_SIZE + KPAD_RING_BUFS ] ; static KPADUnifiedWpadStatus kpad_buf[ BUFF_SIZE * WPAD_MAX_CONTROLLERS ] ; static s32 kpad_reads ; static s32 kpad_err ; static u8 myWorkarea[ WPAD_BLCINT_WORK_LEN ] ATTRIBUTE_ALIGN( 32 ) ; /*---------------------------------------------------------------------------* * Function prototypes *---------------------------------------------------------------------------*/ // MEM2 memory allocation routines. The application must provide these to // WPAD, so it can setup the data transfer buffer. This buffer must reside // in MEM2. static void *myAlloc ( u32 size ) ; static u8 myFree ( void *ptr ) ; // callbacks for CONNECT and EXTENSION events void connectCallback ( s32 chan, s32 reason ) ; // internal functions static void initialize ( void ) ; static void renderStatus ( void ) ; static void init_draw_graphic ( u16 fb_width, u16 fb_height ) ; static void draw_line ( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width ) ; static void draw_box ( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width ) ; /*===========================================================================* * F U N C T I O N D E F I N I T I O N S *===========================================================================*/ /*---------------------------------------------------------------------------* * Name : main() * Description : * Arguments : None. * Returns : None. *---------------------------------------------------------------------------*/ int main( void ) { initialize() ; while( 1 ) { DEMOPadRead(); if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_A ) { KPADResetWbcZeroPoint() ; } if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_B ) { KPADResetWbcTgcWeight() ; } kpad_reads = KPADReadEx( WPAD_CHAN3, kpads, KPAD_RING_BUFS + BUFF_SIZE/4, &kpad_err ) ; // Caption DEMOInitCaption( DM_FT_XLU, SCREEN_WIDTH, SCREEN_HEIGHT ) ; GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE ) ; GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR ) ; DEMOBeforeRender() ; renderStatus() ; DEMODoneRender() ; } } // end main() /*---------------------------------------------------------------------------* * Name : connectCallback() * * Description : This callback is invoked when a controller is connected or * disconnected. * * Arguments : The channel (chan) for which the event has occurred. * The channel status (reason): * WPAD_ERR_NONE means a controller has been connected. * WPAD_ERR_NO_CONTROLLER means a controller disconnected. * * Returns : None. *---------------------------------------------------------------------------*/ void connectCallback( s32 chan, s32 reason ) { u32 type ; if ( reason == WPAD_ERR_NONE ) { // Disconnect 4P if 4P is not Balance Wii board. // Because 4P is reserved for Balance Wii board. WPADProbe( chan, &type ) ; if ( chan == WPAD_CHAN3 && type != WPAD_DEV_BALANCE_CHECKER ) { OSReport( "Channel%d is reserved for the balance checker.\n", chan ) ; WPADDisconnect( chan ) ; } } else { OSReport( "Channel%d is disconnected.\n", chan ) ; } } // end connectCallback() /*---------------------------------------------------------------------------* * Name : myAlloc() * Description : Callback needed by WPAD to allocate mem from MEM2 heap * Arguments : size of block, in bytes. * Returns : pointer to allocated block. *---------------------------------------------------------------------------*/ static void *myAlloc( u32 size ) { void *ptr; ptr = MEMAllocFromAllocator( &DemoAllocator2, size ) ; ASSERTMSG( ptr, "Memory allocation failed\n" ) ; return( ptr ) ; } // myAlloc() /*---------------------------------------------------------------------------* * Name : myFree() * Description : Callback needed by WPAD to free mem from MEM2 heap * Arguments : None. * Returns : Always 1. *---------------------------------------------------------------------------*/ static u8 myFree( void *ptr ) { MEMFreeToAllocator( &DemoAllocator2, ptr ) ; // we should ensure that memory is free'd properly, but oh well return( 1 ) ; } // myFree() static void renderStatus( void ) { s16 x = 20 ; s16 y = 100 ; s16 x1 = 96 ; s16 x2 = 10 ; s16 y1 = 55 ; s16 y2 = 125 ; f32 b1 = -143 ; f32 b2 = -100 ; f32 b3 = -68 ; f32 b4 = -50 ; if ( kpad_err == KPAD_READ_ERR_NO_CONTROLLER ) { if ( WPADIsRegisteredBLC() ) { DEMOPrintf( x, y, 0, "WBC is not connected." ) ; } else { DEMOPrintf( x, y += FONT_HEIGHT, 0, "WBC is not registered." ) ; DEMOPrintf( x, y += FONT_HEIGHT, 0, "Please regist WBC with SYNC button." ) ; } } else { if ( kpads[0].dev_type == WPAD_DEV_BALANCE_CHECKER ) { DEMOPrintf( x1, y1, 0, "%3.1f", kpads[0].ex_status.bl.weight[0] ) ; DEMOPrintf( x1, y2, 0, "%3.1f", kpads[0].ex_status.bl.weight[1] ) ; DEMOPrintf( x2, y1, 0, "%3.1f", kpads[0].ex_status.bl.weight[2] ) ; DEMOPrintf( x2, y2, 0, "%3.1f", kpads[0].ex_status.bl.weight[3] ) ; x = 180 ; y = 10 ; DEMOPrintf( x, y+=FONT_HEIGHT, 0, "+--------------+" ) ; DEMOPrintf( x, y+=FONT_HEIGHT, 0, "| Weight |" ) ; DEMOPrintf( x, y+=FONT_HEIGHT, 0, "+--------------+" ) ; DEMOPrintf( x, y+=FONT_HEIGHT, 0, "Wt : %3.1f[kg]", ( kpads[0].ex_status.bl.weight[0] \ + kpads[0].ex_status.bl.weight[1] \ + kpads[0].ex_status.bl.weight[2] \ + kpads[0].ex_status.bl.weight[3] ) ) ; y+=FONT_HEIGHT ; switch( kpads[0].ex_status.bl.weight_err ) { case KPAD_WBC_ERR_EXIST : DEMOPrintf( x, y, 0, "Err: EXIST" ) ; break ; case KPAD_WBC_ERR_NO_BATTERY : DEMOPrintf( x, y, 0, "Err: NO BATTERY" ) ; break ; case KPAD_WBC_ERR_SETUP : DEMOPrintf( x, y, 0, "Err: SETUP" ) ; break ; case KPAD_WBC_ERR_WRONG_TEMP : DEMOPrintf( x, y, 0, "Err: WRONG TEMP" ) ; break ; case KPAD_WBC_ERR_WRONG_ZERO : DEMOPrintf( x, y, 0, "Err: WRONG ZERO" ) ; break ; case KPAD_WBC_ERR_WEIGHT_OVER : DEMOPrintf( x, y, 0, "Err: WEIGHT OVER" ) ; break ; case KPAD_WBC_ERR_CALIBRATION : DEMOPrintf( x, y, 0, "Err: CALIBRATION" ) ; break ; case KPAD_WBC_ERR_NO_ZEROPOINT : DEMOPrintf( x, y, 0, "Err: NO ZEROPOINT" ) ; break ; case KPAD_WBC_ERR_ZEROPOINT : DEMOPrintf( x, y, 0, "Err: ZEROPOINT" ) ; break ; default : DEMOPrintf( x, y, 0, "Err: %d", kpads[0].ex_status.bl.weight_err ) ; break ; } y+=FONT_HEIGHT ; y+=FONT_HEIGHT ; DEMOPrintf( x, y+=FONT_HEIGHT, 0, "+--------------+" ) ; DEMOPrintf( x, y+=FONT_HEIGHT, 0, "| TGC Weight |" ) ; DEMOPrintf( x, y+=FONT_HEIGHT, 0, "+--------------+" ) ; DEMOPrintf( x, y+=FONT_HEIGHT, 0, "Wt : %3.1f[kg]", kpads[0].ex_status.bl.tgc_weight ) ; y+=FONT_HEIGHT ; switch( kpads[0].ex_status.bl.tgc_weight_err ) { case KPAD_WBC_ERR_TGC_UNSTABLE : DEMOPrintf( x, y, 0, "Err: UNSTABLE" ) ; break; case KPAD_WBC_ERR_TGC_TIMEOUT : DEMOPrintf( x, y, 0, "Err: TIMEOUT" ) ; break; case KPAD_WBC_ERR_TGC_UNKNOWN : DEMOPrintf( x, y, 0, "Err: UNKNOWN" ) ; break; case KPAD_WBC_ERR_TGC_READY : DEMOPrintf( x, y, 0, "Err: READY" ) ; break; case KPAD_WBC_ERR_TGC_BUSY : DEMOPrintf( x, y, 0, "Err: BUSY" ) ; break; default : DEMOPrintf( x, y, 0, "Err: %d", kpads[0].ex_status.bl.tgc_weight_err ) ; break ; } x = 10 ; y = 160 ; DEMOPrintf( x, y+=FONT_HEIGHT, 0, "GC CONTROLLER 1P" ) ; DEMOPrintf( x, y+=FONT_HEIGHT, 0, " A: Reset ZERO Point" ) ; DEMOPrintf( x, y+=FONT_HEIGHT, 0, " B: Reset TGC Weight" ) ; init_draw_graphic( SCREEN_WIDTH, SCREEN_HEIGHT ) ; draw_box( b1, b2, b3, b4, peagreen_clr, 2 ) ; init_draw_graphic( SCREEN_WIDTH, SCREEN_HEIGHT ) ; draw_box( b1, b2+BOX_HEIGHT, b3, b4+BOX_HEIGHT, yellow_clr, 2 ) ; init_draw_graphic( SCREEN_WIDTH, SCREEN_HEIGHT ) ; draw_box( b1+BOX_WIDTH, b2, b3+BOX_WIDTH, b4, blue_clr, 2 ) ; init_draw_graphic( SCREEN_WIDTH, SCREEN_HEIGHT ) ; draw_box( b1+BOX_WIDTH, b2+BOX_HEIGHT, b3+BOX_WIDTH, b4+BOX_HEIGHT, red_clr, 2 ) ; } else { DEMOPrintf( x, y, 0, "No balance checker is attached." ) ; } } } // end renderStatus() static void initialize( void ) { DEMOInit( &GXNtsc480IntDf ) ; DEMOPadInit(); GXSetCopyClear( smoke_clr, GX_MAX_Z24 ) ; GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE ) ; WPADRegisterAllocator( myAlloc, myFree ) ; if ( SCGetLanguage() == SC_LANG_JAPANESE ) { WPADRegisterBLCWorkarea( myWorkarea ) ; } KPADInitEx( kpad_buf, BUFF_SIZE ) ; KPADSetConnectCallback( WPAD_CHAN3, connectCallback ) ; } // end static void init_draw_graphic( u16 fb_width, u16 fb_height ) { Mtx44 proj_mtx ; Mtx view_mtx ; f32 canvas_wd, canvas_ht ; // CANVAS canvas_wd = fb_width * 0.91346f ; canvas_ht = (f32)fb_height ; // MTX MTXOrtho( proj_mtx, canvas_ht * -0.5f,canvas_ht * 0.5f, canvas_wd * -0.5f,canvas_wd * 0.5f, -10.0f,10.0f ) ; GXSetProjection( proj_mtx, GX_ORTHOGRAPHIC ) ; MTXIdentity( view_mtx ) ; GXLoadPosMtxImm( view_mtx, GX_PNMTX0 ) ; GXSetCurrentMtx( GX_PNMTX0 ) ; // VERTEX GXClearVtxDesc() ; GXSetVtxDesc( GX_VA_POS, GX_DIRECT ) ; GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_F32, 0 ) ; // CHANNEL GXSetNumChans( 1 ) ; GXSetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ) ; GXSetChanCtrl( GX_COLOR1A1, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ) ; // TEXTURE GXSetNumTexGens( 0 ) ; // TEV GXSetNumTevStages( 1 ) ; GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL ) ; GXSetTevColorIn( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0 ) ; GXSetTevColorOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ) ; GXSetTevAlphaIn( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0 ) ; GXSetTevAlphaOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ) ; GXSetAlphaCompare( GX_ALWAYS,0, GX_AOP_OR, GX_ALWAYS,0 ) ; // SCREEN GXSetBlendMode( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP ) ; GXSetAlphaUpdate( GX_DISABLE ) ; GXSetZMode( GX_DISABLE, GX_ALWAYS, GX_DISABLE ) ; GXSetCullMode( GX_CULL_BACK ) ; } /******************************************************************************* Draw object *******************************************************************************/ static void draw_line( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width ) { GXSetTevColor( GX_TEVREG0, clr ) ; GXSetLineWidth( (u8)(s32)( width * 6.0f + 0.5f ), GX_TO_ZERO ) ; GXBegin( GX_LINES, GX_VTXFMT0, 2 ) ; GXPosition2f32( x1, y1 ) ; GXPosition2f32( x2, y2 ) ; GXEnd() ; } static void draw_box( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width ) { draw_line( x1, y1, x2, y1, clr, width ) ; draw_line( x2, y1, x2, y2, clr, width ) ; draw_line( x2, y2, x1, y2, clr, width ) ; draw_line( x1, y2, x1, y1, clr, width ) ; }