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