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         DEMOPadRead();
80         if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_A )
81         {
82             KPADResetWbcZeroPoint() ;
83         }
84         if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_B )
85         {
86             KPADResetWbcTgcWeight() ;
87         }
88         kpad_reads = KPADReadEx( WPAD_CHAN3, kpads, KPAD_RING_BUFS + BUFF_SIZE/4, &kpad_err ) ;
89 
90         // Caption
91         DEMOInitCaption( DM_FT_XLU, SCREEN_WIDTH, SCREEN_HEIGHT ) ;
92         GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE ) ;
93         GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR ) ;
94 
95         DEMOBeforeRender() ;
96         renderStatus() ;
97         DEMODoneRender() ;
98     }
99 
100 } // end main()
101 
102 /*---------------------------------------------------------------------------*
103  * Name        : connectCallback()
104  *
105  * Description : This callback is invoked when a controller is connected or
106  *               disconnected.
107  *
108  * Arguments   : The channel (chan) for which the event has occurred.
109  *               The channel status (reason):
110  *                 WPAD_ERR_NONE means a controller has been connected.
111  *                 WPAD_ERR_NO_CONTROLLER means a controller disconnected.
112  *
113  * Returns     : None.
114  *---------------------------------------------------------------------------*/
connectCallback(s32 chan,s32 reason)115 void connectCallback( s32 chan, s32 reason )
116 {
117     u32 type ;
118 
119     if ( reason == WPAD_ERR_NONE )
120     {
121         // Disconnect 4P if 4P is not Balance Wii board.
122         // Because 4P is reserved for Balance Wii board.
123         WPADProbe( chan, &type ) ;
124         if ( chan == WPAD_CHAN3 && type != WPAD_DEV_BALANCE_CHECKER )
125         {
126             OSReport( "Channel%d is reserved for the balance checker.\n", chan ) ;
127             WPADDisconnect( chan ) ;
128         }
129     }
130     else
131     {
132         OSReport( "Channel%d is disconnected.\n", chan ) ;
133     }
134 } // end connectCallback()
135 
136 /*---------------------------------------------------------------------------*
137  * Name        : myAlloc()
138  * Description : Callback needed by WPAD to allocate mem from MEM2 heap
139  * Arguments   : size of block, in bytes.
140  * Returns     : pointer to allocated block.
141  *---------------------------------------------------------------------------*/
myAlloc(u32 size)142 static void *myAlloc( u32 size )
143 {
144     void *ptr;
145 
146     ptr = MEMAllocFromAllocator( &DemoAllocator2, size ) ;
147     ASSERTMSG( ptr, "Memory allocation failed\n" ) ;
148 
149     return( ptr ) ;
150 
151 } // myAlloc()
152 
153 /*---------------------------------------------------------------------------*
154  * Name        : myFree()
155  * Description : Callback needed by WPAD to free mem from MEM2 heap
156  * Arguments   : None.
157  * Returns     : Always 1.
158  *---------------------------------------------------------------------------*/
myFree(void * ptr)159 static u8 myFree( void *ptr )
160 {
161 
162     MEMFreeToAllocator( &DemoAllocator2, ptr ) ;
163 
164     // we should ensure that memory is free'd properly, but oh well
165     return( 1 ) ;
166 
167 } // myFree()
168 
169 
renderStatus(void)170 static void renderStatus( void )
171 {
172     if ( kpad_err == KPAD_READ_ERR_NO_CONTROLLER )
173     {
174         if ( WPADIsRegisteredBLC() )
175         {
176             DEMOPrintf( 50, 100, 0, "WBC is not connected." ) ;
177         }
178         else
179         {
180             DEMOPrintf( 20, 100, 0, "WBC is not registered." ) ;
181             DEMOPrintf( 20, 110, 0, "Please regist WBC with SYNC button." ) ;
182         }
183     }
184     else
185     {
186         if ( kpads[0].dev_type == WPAD_DEV_BALANCE_CHECKER )
187         {
188             if( kpads[0].ex_status.bl.weight_err < 0 )
189             {
190                 DEMOPrintf(  95,  55, 0, "wait..." ) ;
191                 DEMOPrintf(  95, 125, 0, "wait..." ) ;
192                 DEMOPrintf(  10,  55, 0, "wait..." ) ;
193                 DEMOPrintf(  10, 125, 0, "wait..." ) ;
194                 DEMOPrintf( 175,  60, 0, "Wt     :WAIT" ) ;
195                 DEMOPrintf( 175,  70, 0, "Wt     :WAIT" ) ;
196                 DEMOPrintf( 175,  80, 0, "Wt(TGC):WAIT" ) ;
197             }
198             else
199             {
200                 DEMOPrintf(  95,  55, 0, "%3.1f", kpads[0].ex_status.bl.weight[0] ) ;
201                 DEMOPrintf(  95, 125, 0, "%3.1f", kpads[0].ex_status.bl.weight[1] ) ;
202                 DEMOPrintf(  10,  55, 0, "%3.1f", kpads[0].ex_status.bl.weight[2] ) ;
203                 DEMOPrintf(  10, 125, 0, "%3.1f", kpads[0].ex_status.bl.weight[3] ) ;
204                 DEMOPrintf( 175,  60, 0, "Wt     :%3.1f[kg]", ( kpads[0].ex_status.bl.weight[0]  \
205                                                               + kpads[0].ex_status.bl.weight[1]  \
206                                                               + kpads[0].ex_status.bl.weight[2]  \
207                                                               + kpads[0].ex_status.bl.weight[3] ) ) ;
208                 DEMOPrintf( 175,  70, 0, "Wt     :%3.1f[kg]", ( kpads[0].ex_status.bl.weight_ave[0]  \
209                                                               + kpads[0].ex_status.bl.weight_ave[1]  \
210                                                               + kpads[0].ex_status.bl.weight_ave[2]  \
211                                                               + kpads[0].ex_status.bl.weight_ave[3] ) ) ;
212                 if ( kpads[0].ex_status.bl.tgc_weight_err )
213                 {
214                     DEMOPrintf( 175,  80, 0, "Wt(TGC):WAIT" ) ;
215                 }
216                 else
217                 {
218                     DEMOPrintf( 175,  80, 0, "Wt(TGC):%3.1f[kg]", kpads[0].ex_status.bl.tgc_weight ) ;
219                 }
220             }
221             switch( kpads[0].ex_status.bl.weight_err ) {
222               case KPAD_WBC_ERR_NO_BATTERY :
223                 DEMOPrintf( 175,  30, 0, "Err     = NOBAT" ) ;
224                 break ;
225               case KPAD_WBC_ERR_SETUP :
226                 DEMOPrintf( 175,  30, 0, "Err     = SETUP" ) ;
227                 break ;
228               case KPAD_WBC_ERR_WRONG_TEMP :
229                 DEMOPrintf( 175,  30, 0, "Err     = TEMP"  ) ;
230                 break ;
231               case KPAD_WBC_ERR_WRONG_ZERO :
232                 DEMOPrintf( 175,  30, 0, "Err     = ZERO"  ) ;
233                 break ;
234               default :
235                 DEMOPrintf( 175,  30, 0, "Err     = %d", kpads[0].ex_status.bl.weight_err ) ;
236                 break ;
237             }
238 
239             DEMOPrintf( 175,  40, 0, "IsEXIST = %s", ( kpads[0].ex_status.bl.weight_err == 1 ) ? "EXIST" : "NONE" ) ;
240 
241             DEMOPrintf(  10, 160, 0, "GC CONTROLLER 1P" ) ;
242             DEMOPrintf(  10, 170, 0, " A: Reset ZERO Point" ) ;
243             DEMOPrintf(  10, 180, 0, " B: Reset TGC  Weight" ) ;
244 
245             init_draw_graphic( SCREEN_WIDTH, SCREEN_HEIGHT ) ;
246             draw_box( -143, -100, -68, -50, peagreen_clr, 2 ) ;
247             init_draw_graphic( SCREEN_WIDTH, SCREEN_HEIGHT ) ;
248             draw_box( -143,  -30, -68,  20, yellow_clr, 2 ) ;
249             init_draw_graphic( SCREEN_WIDTH, SCREEN_HEIGHT ) ;
250             draw_box( -63,  -100, 12, -50, blue_clr, 2 ) ;
251             init_draw_graphic( SCREEN_WIDTH, SCREEN_HEIGHT ) ;
252             draw_box( -63,   -30, 12,  20, red_clr, 2 ) ;
253         }
254         else
255         {
256             DEMOPrintf( 50, 100, 0, "No balance checker is attached." ) ;
257         }
258     }
259 
260 } // end renderStatus()
261 
262 
initialize(void)263 static void initialize( void )
264 {
265     DEMOInit( &GXNtsc480IntDf ) ;
266     DEMOPadInit();
267 
268     GXSetCopyClear( smoke_clr, GX_MAX_Z24 ) ;
269     GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE ) ;
270 
271     WPADRegisterAllocator( myAlloc, myFree ) ;
272     if ( SCGetLanguage() == SC_LANG_JAPANESE )
273     {
274         WPADRegisterBLCWorkarea( myWorkarea ) ;
275     }
276 
277     KPADInitEx( kpad_buf, BUFF_SIZE ) ;
278     KPADSetConnectCallback( WPAD_CHAN3, connectCallback ) ;
279 
280 } // end
281 
282 
init_draw_graphic(u16 fb_width,u16 fb_height)283 static void init_draw_graphic( u16 fb_width, u16 fb_height )
284 {
285     Mtx44   proj_mtx ;
286     Mtx     view_mtx ;
287     f32     canvas_wd, canvas_ht ;
288 
289     // CANVAS
290     canvas_wd = fb_width * 0.91346f ;
291     canvas_ht = fb_height ;
292 
293     // MTX
294     MTXOrtho( proj_mtx, canvas_ht * -0.5f,canvas_ht * 0.5f, canvas_wd * -0.5f,canvas_wd * 0.5f, -10.0f,10.0f ) ;
295     GXSetProjection( proj_mtx, GX_ORTHOGRAPHIC ) ;
296 
297     MTXIdentity( view_mtx ) ;
298     GXLoadPosMtxImm( view_mtx, GX_PNMTX0 ) ;
299     GXSetCurrentMtx( GX_PNMTX0 ) ;
300 
301     // VERTEX
302     GXClearVtxDesc() ;
303     GXSetVtxDesc( GX_VA_POS, GX_DIRECT ) ;
304     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_F32, 0 ) ;
305 
306     // CHANNEL
307     GXSetNumChans( 1 ) ;
308     GXSetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ) ;
309     GXSetChanCtrl( GX_COLOR1A1, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ) ;
310 
311     // TEXTURE
312     GXSetNumTexGens( 0 ) ;
313 
314     // TEV
315     GXSetNumTevStages( 1 ) ;
316     GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL ) ;
317     GXSetTevColorIn( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0 ) ;
318     GXSetTevColorOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ) ;
319     GXSetTevAlphaIn( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0 ) ;
320     GXSetTevAlphaOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ) ;
321     GXSetAlphaCompare( GX_ALWAYS,0, GX_AOP_OR, GX_ALWAYS,0 ) ;
322 
323     // SCREEN
324     GXSetBlendMode( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP ) ;
325     GXSetAlphaUpdate( GX_DISABLE ) ;
326 
327     GXSetZMode( GX_DISABLE, GX_ALWAYS, GX_DISABLE ) ;
328     GXSetCullMode( GX_CULL_BACK ) ;
329 }
330 
331 /*******************************************************************************
332     Draw object
333 *******************************************************************************/
draw_line(f32 x1,f32 y1,f32 x2,f32 y2,GXColor clr,f32 width)334 static void draw_line( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width )
335 {
336     GXSetTevColor( GX_TEVREG0, clr ) ;
337     GXSetLineWidth( (u8)(s32)( width * 6.0f + 0.5f ), GX_TO_ZERO ) ;
338 
339     GXBegin( GX_LINES, GX_VTXFMT0, 2 ) ;
340       GXPosition2f32( x1, y1 ) ;
341       GXPosition2f32( x2, y2 ) ;
342     GXEnd() ;
343 }
344 
draw_box(f32 x1,f32 y1,f32 x2,f32 y2,GXColor clr,f32 width)345 static void draw_box( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width )
346 {
347     draw_line( x1, y1, x2, y1, clr, width ) ;
348     draw_line( x2, y1, x2, y2, clr, width ) ;
349     draw_line( x2, y2, x1, y2, clr, width ) ;
350     draw_line( x1, y2, x1, y1, clr, width ) ;
351 }
352 
353