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