1 /*---------------------------------------------------------------------------*
2   Project:    KPAD weight demo program
3   File:       weight.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  *---------------------------------------------------------------------------*/
14 #include <revolution.h>
15 #include <revolution/kpad.h>
16 #include <revolution/sc.h>
17 
18 #define DEMO_USE_MEMLIB=1 // This turns on the DEMO library's MEM heaps.
19 #include <demo.h>
20 
21 /*---------------------------------------------------------------------------*
22  * Local Definitions
23  *---------------------------------------------------------------------------*/
24 
25 #define SCREEN_WIDTH  320
26 #define SCREEN_HEIGHT 240
27 #define FONT_HEIGHT     8
28 #define BUFF_SIZE      16
29 
30 GXColor smoke_clr    = {  61, 61, 61, 255 } ;
31 GXColor red_clr      = { 237, 28, 36, 255 } ;
32 GXColor blue_clr     = {   0, 84,166, 255 } ;
33 GXColor yellow_clr   = { 255,242,  0, 255 } ;
34 GXColor peagreen_clr = { 141,198, 63, 255 } ;
35 
36 static KPADStatus            kpads   [ BUFF_SIZE + KPAD_RING_BUFS ] ;
37 static KPADUnifiedWpadStatus kpad_buf[ BUFF_SIZE * WPAD_MAX_CONTROLLERS ] ;
38 static s32                   kpad_reads ;
39 static s32                   kpad_err ;
40 
41 static u8 myWorkarea[ WPAD_BLCINT_WORK_LEN ] ATTRIBUTE_ALIGN( 32 ) ;
42 
43 /*---------------------------------------------------------------------------*
44  * Function prototypes
45  *---------------------------------------------------------------------------*/
46 
47 // MEM2 memory allocation routines. The application must provide these to
48 // WPAD, so it can setup the data transfer buffer. This buffer must reside
49 // in MEM2.
50 static void *myAlloc                 ( u32 size  ) ;
51 static u8    myFree                  ( void *ptr ) ;
52 
53 // Callbacks for CONNECT and EXTENSION events.
54 void         connectCallback         ( s32 chan, s32 reason ) ;
55 
56 // Internal functions
57 static void  initialize              ( void ) ;
58 static void  renderStatus            ( void ) ;
59 static void  init_draw_graphic       ( u16 fb_width, u16 fb_height ) ;
60 static void  draw_line               ( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width ) ;
61 static void  draw_box                ( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width ) ;
62 
63 /*===========================================================================*
64  *                   F U N C T I O N    D E F I N I T I O N S
65  *===========================================================================*/
66 /*---------------------------------------------------------------------------*
67  * Name        : main()
68  * Description :
69  * Arguments   : None.
70  * Returns     : None.
71  *---------------------------------------------------------------------------*/
main(void)72 int main( void )
73 {
74 
75     initialize() ;
76 
77     while( 1 )
78     {
79         kpad_reads = KPADReadEx( WPAD_CHAN3, kpads, KPAD_RING_BUFS + BUFF_SIZE/4, &kpad_err ) ;
80 
81         if ( kpad_reads > 0 && kpads[0].trig & KPAD_BUTTON_A )
82         {
83             KPADResetWbcZeroPoint() ;
84         }
85 
86         // Caption
87         DEMOInitCaption( DM_FT_XLU, SCREEN_WIDTH, SCREEN_HEIGHT ) ;
88         GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE ) ;
89         GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR ) ;
90 
91         DEMOBeforeRender() ;
92         renderStatus() ;
93         DEMODoneRender() ;
94     }
95 
96 } // End main()
97 
98 /*---------------------------------------------------------------------------*
99  * Name        : connectCallback()
100  *
101  * Description : This callback is invoked when a controller is connected or
102  *               disconnected.
103  *
104  * Arguments   : The channel (chan) for which the event has occurred.
105  *               The channel status (reason):
106  *                 WPAD_ERR_NONE means a controller has been connected.
107  *                 WPAD_ERR_NO_CONTROLLER means a controller disconnected.
108  *
109  * Returns     : None.
110  *---------------------------------------------------------------------------*/
connectCallback(s32 chan,s32 reason)111 void connectCallback( s32 chan, s32 reason )
112 {
113     u32 type ;
114 
115     if ( reason == WPAD_ERR_NONE )
116     {
117         // Disconnect 4P if 4P is not Wii Balance Board.
118         // Because 4P is reserved for Wii Balance Board.
119         WPADProbe( chan, &type ) ;
120         if ( chan == WPAD_CHAN3 && type != WPAD_DEV_BALANCE_CHECKER )
121         {
122             OSReport( "Channel%d is reserved for the balance checker.\n", chan ) ;
123             WPADDisconnect( chan ) ;
124         }
125     }
126     else
127     {
128         OSReport( "Channel%d is disconnected.\n", chan ) ;
129     }
130 } // End connectCallback()
131 
132 /*---------------------------------------------------------------------------*
133  * Name        : myAlloc()
134  * Description : Callback needed by WPAD to allocate mem from MEM2 heap.
135  * Arguments   : size of block, in bytes.
136  * Returns     : pointer to allocated block.
137  *---------------------------------------------------------------------------*/
myAlloc(u32 size)138 static void *myAlloc( u32 size )
139 {
140     void *ptr;
141 
142     ptr = MEMAllocFromAllocator( &DemoAllocator2, size ) ;
143     ASSERTMSG( ptr, "Memory allocation failed\n" ) ;
144 
145     return( ptr ) ;
146 
147 } // myAlloc()
148 
149 /*---------------------------------------------------------------------------*
150  * Name        : myFree()
151  * Description : Callback needed by WPAD to free mem from MEM2 heap.
152  * Arguments   : None.
153  * Returns     : Always 1.
154  *---------------------------------------------------------------------------*/
myFree(void * ptr)155 static u8 myFree( void *ptr )
156 {
157 
158     MEMFreeToAllocator( &DemoAllocator2, ptr ) ;
159 
160     // we should ensure that memory is free'd properly, but oh well
161     return( 1 ) ;
162 
163 } // myFree()
164 
165 
renderStatus(void)166 static void renderStatus( void )
167 {
168     if ( kpad_err == KPAD_READ_ERR_NO_CONTROLLER )
169     {
170         if ( WPADIsRegisteredBLC() )
171         {
172             DEMOPrintf( 50, 100, 0, "WBC is not connected." ) ;
173         }
174         else
175         {
176             DEMOPrintf( 20, 100, 0, "WBC is not registered." ) ;
177             DEMOPrintf( 20, 110, 0, "Please regist WBC with SYNC button." ) ;
178         }
179     }
180     else
181     {
182         if ( kpads[0].dev_type == WPAD_DEV_BALANCE_CHECKER )
183         {
184             if( kpads[0].ex_status.bl.weight_err < 0 )
185             {
186                 DEMOPrintf(  95,  55, 0, "wait..." ) ;
187                 DEMOPrintf(  95, 125, 0, "wait..." ) ;
188                 DEMOPrintf(  10,  55, 0, "wait..." ) ;
189                 DEMOPrintf(  10, 125, 0, "wait..." ) ;
190                 DEMOPrintf( 175,  60, 0, "Wt     :WAIT" ) ;
191                 DEMOPrintf( 175,  70, 0, "Wt(TGC):WAIT" ) ;
192             }
193             else
194             {
195                 DEMOPrintf(  95,  55, 0, "%3.1f", kpads[0].ex_status.bl.weight[0] ) ;
196                 DEMOPrintf(  95, 125, 0, "%3.1f", kpads[0].ex_status.bl.weight[1] ) ;
197                 DEMOPrintf(  10,  55, 0, "%3.1f", kpads[0].ex_status.bl.weight[2] ) ;
198                 DEMOPrintf(  10, 125, 0, "%3.1f", kpads[0].ex_status.bl.weight[3] ) ;
199                 DEMOPrintf( 175,  60, 0, "Wt     :%3.1f[kg]", ( kpads[0].ex_status.bl.weight_ave[0]  \
200                                                               + kpads[0].ex_status.bl.weight_ave[1]  \
201                                                               + kpads[0].ex_status.bl.weight_ave[2]  \
202                                                               + kpads[0].ex_status.bl.weight_ave[3] ) ) ;
203                 DEMOPrintf( 175,  70, 0, "Wt(TGC):%3.1f[kg]", kpads[0].ex_status.bl.tgc_weight ) ;
204             }
205             switch( kpads[0].ex_status.bl.weight_err ) {
206               case KPAD_WBC_ERR_NO_BATTERY :
207                 DEMOPrintf( 175,  30, 0, "Err     = NOBAT" ) ;
208                 break ;
209               case KPAD_WBC_ERR_SETUP :
210                 DEMOPrintf( 175,  30, 0, "Err     = SETUP" ) ;
211                 break ;
212               case KPAD_WBC_ERR_WRONG_TEMP :
213                 DEMOPrintf( 175,  30, 0, "Err     = TEMP"  ) ;
214                 break ;
215               case KPAD_WBC_ERR_WRONG_ZERO :
216                 DEMOPrintf( 175,  30, 0, "Err     = ZERO"  ) ;
217                 break ;
218               default :
219                 DEMOPrintf( 175,  30, 0, "Err     = %d", kpads[0].ex_status.bl.weight_err ) ;
220                 break ;
221             }
222 
223             DEMOPrintf( 175,  40, 0, "IsEXIST = %s", ( kpads[0].ex_status.bl.weight_err == 1 ) ? "EXIST" : "NONE" ) ;
224 
225             DEMOPrintf(  10, 160, 0, "A: Reset ZERO Point" ) ;
226 
227             init_draw_graphic( SCREEN_WIDTH, SCREEN_HEIGHT ) ;
228             draw_box( -143, -100, -68, -50, peagreen_clr, 2 ) ;
229             init_draw_graphic( SCREEN_WIDTH, SCREEN_HEIGHT ) ;
230             draw_box( -143,  -30, -68,  20, yellow_clr, 2 ) ;
231             init_draw_graphic( SCREEN_WIDTH, SCREEN_HEIGHT ) ;
232             draw_box( -63,  -100, 12, -50, blue_clr, 2 ) ;
233             init_draw_graphic( SCREEN_WIDTH, SCREEN_HEIGHT ) ;
234             draw_box( -63,   -30, 12,  20, red_clr, 2 ) ;
235         }
236         else
237         {
238             DEMOPrintf( 50, 100, 0, "No balance checker is attached." ) ;
239         }
240     }
241 
242 } // End renderStatus()
243 
244 
initialize(void)245 static void initialize( void )
246 {
247     DEMOInit( &GXNtsc480IntDf ) ;
248 
249     GXSetCopyClear( smoke_clr, GX_MAX_Z24 ) ;
250     GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE ) ;
251 
252     WPADRegisterAllocator( myAlloc, myFree ) ;
253     if ( SCGetLanguage() == SC_LANG_JAPANESE )
254     {
255         WPADRegisterBLCWorkarea( myWorkarea ) ;
256     }
257 
258     KPADInitEx( kpad_buf, BUFF_SIZE ) ;
259     KPADSetConnectCallback( WPAD_CHAN3, connectCallback ) ;
260 
261 } // End
262 
263 
init_draw_graphic(u16 fb_width,u16 fb_height)264 static void init_draw_graphic( u16 fb_width, u16 fb_height )
265 {
266     Mtx44   proj_mtx ;
267     Mtx     view_mtx ;
268     f32     canvas_wd, canvas_ht ;
269 
270     // CANVAS
271     canvas_wd = fb_width * 0.91346f ;
272     canvas_ht = fb_height ;
273 
274     // MTX
275     MTXOrtho( proj_mtx, canvas_ht * -0.5f,canvas_ht * 0.5f, canvas_wd * -0.5f,canvas_wd * 0.5f, -10.0f,10.0f ) ;
276     GXSetProjection( proj_mtx, GX_ORTHOGRAPHIC ) ;
277 
278     MTXIdentity( view_mtx ) ;
279     GXLoadPosMtxImm( view_mtx, GX_PNMTX0 ) ;
280     GXSetCurrentMtx( GX_PNMTX0 ) ;
281 
282     // VERTEX
283     GXClearVtxDesc() ;
284     GXSetVtxDesc( GX_VA_POS, GX_DIRECT ) ;
285     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_F32, 0 ) ;
286 
287     // CHANNEL
288     GXSetNumChans( 1 ) ;
289     GXSetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ) ;
290     GXSetChanCtrl( GX_COLOR1A1, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ) ;
291 
292     // TEXTURE
293     GXSetNumTexGens( 0 ) ;
294 
295     // TEV
296     GXSetNumTevStages( 1 ) ;
297     GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL ) ;
298     GXSetTevColorIn( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0 ) ;
299     GXSetTevColorOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ) ;
300     GXSetTevAlphaIn( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0 ) ;
301     GXSetTevAlphaOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ) ;
302     GXSetAlphaCompare( GX_ALWAYS,0, GX_AOP_OR, GX_ALWAYS,0 ) ;
303 
304     // SCREEN
305     GXSetBlendMode( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP ) ;
306     GXSetAlphaUpdate( GX_DISABLE ) ;
307 
308     GXSetZMode( GX_DISABLE, GX_ALWAYS, GX_DISABLE ) ;
309     GXSetCullMode( GX_CULL_BACK ) ;
310 }
311 
312 /*******************************************************************************
313     Draw object
314 *******************************************************************************/
draw_line(f32 x1,f32 y1,f32 x2,f32 y2,GXColor clr,f32 width)315 static void draw_line( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width )
316 {
317     GXSetTevColor( GX_TEVREG0, clr ) ;
318     GXSetLineWidth( (u8)(s32)( width * 6.0f + 0.5f ), GX_TO_ZERO ) ;
319 
320     GXBegin( GX_LINES, GX_VTXFMT0, 2 ) ;
321       GXPosition2f32( x1, y1 ) ;
322       GXPosition2f32( x2, y2 ) ;
323     GXEnd() ;
324 }
325 
draw_box(f32 x1,f32 y1,f32 x2,f32 y2,GXColor clr,f32 width)326 static void draw_box( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width )
327 {
328     draw_line( x1, y1, x2, y1, clr, width ) ;
329     draw_line( x2, y1, x2, y2, clr, width ) ;
330     draw_line( x2, y2, x1, y2, clr, width ) ;
331     draw_line( x1, y2, x1, y1, clr, width ) ;
332 }
333 
334