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