1 /*---------------------------------------------------------------------------*
2   Project:    WPAD health demo program
3   File:       wbc_simple.c
4 
5   Copyright (C) 2007 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   $Log: balance.c,v $
14   Revision 1.4.30.1  2009/12/08 06:23:06  miyamoto_satoshi
15   Modified cast and avoid warning.
16 
17   Revision 1.4  2008/06/17 08:03:33  tojo
18   Removed unused headers.
19 
20   Revision 1.3  2008/04/24 00:20:47  tojo
21   Updated WBCGetTGCWeight to latest spec.
22 
23   Revision 1.2  2008/04/17 05:25:33  tojo
24   Changed API for WBCSetupCalibration.
25 
26   Revision 1.1  2008/04/17 02:55:42  tojo
27   initial check-in.
28 
29  *---------------------------------------------------------------------------*/
30 #include <math.h>
31 
32 #include <revolution.h>
33 #include <revolution/wpad.h>
34 #include <revolution/wpadBalance.h>
35 #include <revolution/sc.h>
36 #include <revolution/wbc.h>
37 
38 #define DEMO_USE_MEMLIB=1 // This turns on the DEMO library's MEM heaps.
39 #include <demo.h>
40 
41 
42 /*---------------------------------------------------------------------------*
43  * Local Definitions
44  *---------------------------------------------------------------------------*/
45 static u8  workarea[WPAD_BLCINT_WORK_LEN] ATTRIBUTE_ALIGN(32);
46 static WPADBLStatus status;
47 static double zero[WPAD_PRESS_UNITS];
48 
49 /*---------------------------------------------------------------------------*
50  * Function prototypes
51  *---------------------------------------------------------------------------*/
52 // MEM2 memory allocation routines. The application must provide these to
53 // WPAD, so it can setup the data transfer buffer. This buffer must reside
54 // in MEM2.
55 static void *myAlloc                 ( u32 size );
56 static u8    myFree                  ( void *ptr );
57 
58 
59 // callbacks for CONNECT and EXTENSION events
60 static void connectCallback          ( s32 chan, s32 reason );
61 static void extensionCallback        ( s32 chan, s32 result );
62 
63 /*===========================================================================*
64  *                   F U N C T I O N    D E F I N I T I O N S
65  *===========================================================================*/
WaitMilliTime(s32 msec)66 static void WaitMilliTime(s32 msec)
67 {
68     OSTime t=OSGetTime();
69     while(OSTicksToMilliseconds(OSGetTime()-t) < msec)
70         ;
71 }
72 
73 
ZeroSetStart2(s32 chan,s32 result)74 static void ZeroSetStart2( s32 chan, s32 result )
75 {
76     #pragma unused(chan, result)
77 
78     // Wait about 200[ms] so that Board's press value rarely becomes unstable
79     // after updating Balance Wii Board's temperature.
80     WaitMilliTime(200);
81 
82     // Set Zero point.
83     zero[0] = (f64)status.press[0]; //Normally, set the average for 2 seconds.
84     zero[1] = (f64)status.press[1]; //Normally, set the average for 2 seconds.
85     zero[2] = (f64)status.press[2]; //Normally, set the average for 2 seconds.
86     zero[3] = (f64)status.press[3]; //Normally, set the average for 2 seconds.
87     WBCSetZEROPoint( zero,(u32)(sizeof(zero) / sizeof(zero[0])));
88 }
89 
90 
ZeroSetStart(s32 chan,s32 result)91 static void ZeroSetStart( s32 chan, s32 result )
92 {
93     #pragma unused(chan, result)
94 
95     // Check Board's temperature.
96     WPADRead(WPAD_CHAN3, &status);
97 
98 
99     if((status.temp == 127) || (status.temp == -128))
100     {
101         // Update Board's temperature again if you can not get correct Board's temperature.
102         WPADControlBLC(WPAD_CHAN3, WPAD_BLCMD_UPDATE_TEMP, ZeroSetStart2);
103     }
104     else
105     {
106         // Wait about 200[ms] so that Board's press value rarely becomes unstable
107         // after updating Balance Wii Board's temperature.
108         WaitMilliTime(200);
109 
110         // Set Zero point.
111         zero[0] = (f64)status.press[0]; //Normally, set the average for 2 seconds.
112         zero[1] = (f64)status.press[1]; //Normally, set the average for 2 seconds.
113         zero[2] = (f64)status.press[2]; //Normally, set the average for 2 seconds.
114         zero[3] = (f64)status.press[3]; //Normally, set the average for 2 seconds.
115         WBCSetZEROPoint( zero,(u32)(sizeof(zero) / sizeof(zero[0])));
116     }
117 }
118 
119 
120 /*---------------------------------------------------------------------------*
121  * Name        : main()
122  * Description :
123  * Arguments   : None.
124  * Returns     : None.
125  *---------------------------------------------------------------------------*/
main(void)126 int main( void )
127 {
128     double weight[WPAD_PRESS_UNITS];
129     u32 type;
130 
131     DEMOInit( NULL );
132     DEMOPadInit();
133 
134     // If Japan, need to call WPADRegisterBLCWorkarea to set a work buffer.
135     // If not Japan, WPADRegisterBLCWorkarea does nothing.
136     WPADRegisterBLCWorkarea( workarea );
137 
138     WPADRegisterAllocator(myAlloc, myFree);
139     WPADInit();
140     WPADSetConnectCallback(WPAD_CHAN3, connectCallback);
141 
142     while (WPAD_STATE_SETUP != WPADGetStatus())
143     {
144         ;
145     }
146 
147     // You can release the work buffer so initialize of WPAD library has finished.
148     // This sample program does nothing it uses static buffer.
149 
150 
151     if (DEMOInitROMFont() == 0)
152     {
153         OSHalt("FONT ERROR\n");
154         // NOT REACHED HERE
155     }
156 
157     while(1)
158     {
159         GXRenderModeObj *rmp = DEMOGetRenderModeObj();
160         s16 x,y;
161         double w1,w2,w3,w4;
162         double left,right,front,back;
163 
164         w1 = weight[0]; // front right
165         w2 = weight[1]; // back  right
166         w3 = weight[2]; // front left
167         w4 = weight[3]; // back  left
168 
169         if(fabs(w1) < 1) w1 = 1;
170         if(fabs(w2) < 1) w2 = 1;
171         if(fabs(w3) < 1) w3 = 1;
172         if(fabs(w4) < 1) w4 = 1;
173 
174         left  = (double)(w3 + w4);
175         right = (double)(w1 + w2);
176         front = (double)(w1 + w3);
177         back  = (double)(w4 + w2);
178 
179         // Calculate a balance point.
180         x = (s16)((right / (left + right)) * rmp->fbWidth);
181         y = (s16)((back  / (front + back)) * rmp->viHeight);
182 
183         DEMOBeforeRender();
184         DEMOInitCaption(DM_FT_XLU, (s16) rmp->fbWidth, (s16) rmp->efbHeight);
185         DEMOSetROMFontSize(16, -1);
186         DEMORFPrintf(x, y, 0, "X"); //Draw the center of gravity.
187         DEMODoneRender();
188 
189 
190         DEMOPadRead();
191 
192         if (DEMOPadGetButtonDown(0) & PAD_BUTTON_A)
193         {
194             // Update Board's temperature the eve of zero point correction.
195             WPADControlBLC(WPAD_CHAN3, WPAD_BLCMD_UPDATE_TEMP, ZeroSetStart);
196         }
197 
198         if (WPADProbe(WPAD_CHAN3, &type) == WPAD_ERR_NO_CONTROLLER)
199         {
200             if (WPADIsRegisteredBLC())
201             {
202                 OSReport("Balance Wii board is not connected.\n");
203             }
204             else
205             {
206                 OSReport("Balance Wii board is not registered. Please regist Balance Wii board with SYNC button.\n");
207             }
208         }
209         else
210         {
211             if (type == WPAD_DEV_BALANCE_CHECKER)
212             {
213                 WPADRead(WPAD_CHAN3, &status);
214 
215                 if(WBCGetCalibrationStatus() == TRUE)
216                 {
217                     double total;
218                     double tgc_weight;
219 
220                     WBCRead(&status, weight, (u32)(sizeof(weight) / sizeof(weight[0])));
221                     total = (double)(weight[0]+weight[1]+weight[2]+weight[3]);
222 
223                     // Show the total weight. Normally, "total" value is the average for 2 seconds.
224                     if (WBCGetTGCWeight(total, &tgc_weight, &status) == WBC_ERR_NONE)
225                     {
226                         OSReport("%3.1f[kg]\n", tgc_weight);
227                     }
228                 }
229                 else
230                 {
231                     OSReport("Calibration data read error. Please reconnect Balance Wii board.\n");
232                 }
233             }
234             else
235             {
236                 OSReport("No Balance Wii board is attached.\n");
237             }
238         }
239     }
240 } // end main()
241 
242 
243 /*---------------------------------------------------------------------------*
244  * Name        : connectCallback()
245  *
246  * Description : This callback is invoked when a controller is connected or
247  *               disconnected.
248  *
249  * Arguments   : The channel (chan) for which the event has occurred.
250  *               The channel status (reason):
251  *                 WPAD_ERR_NONE means a controller has been connected.
252  *                 WPAD_ERR_NO_CONTROLLER means a controller disconnected.
253  *
254  * Returns     : None.
255  *---------------------------------------------------------------------------*/
connectCallback(s32 chan,s32 reason)256 static void connectCallback(s32 chan, s32 reason)
257 {
258     u32 type;
259 
260     if (reason == WPAD_ERR_NONE)
261     {
262         // Disconnect 4P if 4P is not Balance Wii board.
263         // Because 4P is reserved for Balance Wii board.
264         WPADProbe(chan, &type);
265         if (chan == WPAD_CHAN0 && type != WPAD_DEV_BALANCE_CHECKER)
266         {
267             OSReport("Channel%d is reserved for Balance Wii board.\n", chan);
268             WPADDisconnect(chan);
269         }
270         else
271         {
272             // Read the calibration value for calculating a weight.
273             if(!WBCSetupCalibration())
274             {
275                 OSHalt("Balance Wii board FATAL ERROR!!\n");
276             }
277             OSReport("Channel%d is connected.\n", chan);
278             WPADSetExtensionCallback(chan, extensionCallback);
279         }
280     }
281     else
282     {
283         OSReport("Channel%d is disconnected.\n", chan);
284     }
285 } // end connectCallback()
286 
287 /*---------------------------------------------------------------------------*
288  * Name        : extensionCallback()
289  *
290  * Description : This callback is invoked when an Extension has been attached.
291  *
292  * Arguments   : The channel (chan) for which the extension event occurred.
293  *               The device type (result):
294  *
295  *                 WPAD_DEV_UNKNOWN means that something has been attached, but
296  *                 it's being initialized, and we won't know what it is until
297  *                 initialization is complete.
298  *
299  *                 WPAD_DEV_CORE means that an extension has been removed and
300  *                 we're back to just the core device.
301  *
302  *                 WPAD_DEV_FREESTYLE means that the "NUNCHAK" extension has
303  *                 been attached and initialized.
304  *
305  *                 WPAD_DEV_CLASSIC means that the "CLASSIC" extension has been
306  *                 attached and initialized.
307  *
308  * Returns     : None.
309  *---------------------------------------------------------------------------*/
extensionCallback(s32 chan,s32 result)310 static void extensionCallback(s32 chan, s32 result)
311 {
312     switch(result)
313     {
314         case WPAD_DEV_UNKNOWN:
315             OSReport("Initializing extension on channel%d...\n", chan);
316             break;
317 
318         case WPAD_DEV_CORE:
319             WPADControlDpd(chan, WPAD_DPD_EXP, NULL);
320             WPADSetDataFormat(chan, WPAD_FMT_CORE_ACC_DPD);
321 
322             OSReport("Extension removed on channel%d.\n", chan);
323             break;
324 
325         case WPAD_DEV_NOT_SUPPORTED:
326         case WPAD_DEV_FUTURE:
327             WPADControlDpd(chan, WPAD_DPD_EXP, NULL);
328             WPADSetDataFormat(chan, WPAD_FMT_CORE_ACC_DPD);
329 
330             OSReport("Extension is not useful on channel%d.\n", chan);
331             break;
332 
333         case WPAD_DEV_FREESTYLE:
334             WPADControlDpd(chan, WPAD_DPD_STD, NULL);
335             WPADSetDataFormat(chan, WPAD_FMT_FREESTYLE_ACC_DPD);
336 
337             OSReport("Freestyle initialized on channel%d.\n", chan);
338             break;
339 
340         case WPAD_DEV_CLASSIC:
341             WPADControlDpd(chan, WPAD_DPD_STD, NULL);
342             WPADSetDataFormat(chan, WPAD_FMT_CLASSIC_ACC_DPD);
343 
344             OSReport("Classicstyle initialized on channel%d.\n", chan);
345             break;
346 
347         case WPAD_DEV_BALANCE_CHECKER:
348             WPADControlDpd(chan, WPAD_DPD_OFF, NULL);
349             WPADSetDataFormat(chan, WPAD_FMT_BALANCE_CHECKER);
350             WPADControlBLC(chan, WPAD_BLCMD_ON, NULL);
351 
352             OSReport("Balance Wii board initialized on channel%d.\n", chan);
353             break;
354 
355         default:
356             // Here is WPAD_DEV_NOT_FOUND.
357             // If the controller is disconnected while the extension is initializing
358             // it reaches here. There is nothing to do.
359             break;
360 
361     } // end
362 } // end extensionCallback()
363 
364 /*---------------------------------------------------------------------------*
365  * Name        : myAlloc()
366  * Description : Callback needed by WPAD to allocate mem from MEM2 heap
367  * Arguments   : size of block, in bytes.
368  * Returns     : pointer to allocated block.
369  *---------------------------------------------------------------------------*/
myAlloc(u32 size)370 static void *myAlloc(u32 size)
371 {
372     void *ptr;
373 
374     ptr = MEMAllocFromAllocator(&DemoAllocator2, size);
375     ASSERTMSG(ptr, "Memory allocation failed\n");
376 
377     return(ptr);
378 
379 } // myAlloc()
380 
381 /*---------------------------------------------------------------------------*
382  * Name        : myFree()
383  * Description : Callback needed by WPAD to free mem from MEM2 heap
384  * Arguments   : None.
385  * Returns     : Always 1.
386  *---------------------------------------------------------------------------*/
myFree(void * ptr)387 static u8 myFree(void *ptr)
388 {
389 
390     MEMFreeToAllocator(&DemoAllocator2, ptr);
391 
392     // we should ensure that memory is free'd properly, but oh well
393     return(1);
394 
395 } // myFree()
396