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