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