1 /*---------------------------------------------------------------------------*
2   Project:     KPAD sample program
3   File:        sample.c
4   Programmer:  Keizo Ohta
5                HIRATSU Daisuke
6                Tojo Haruki
7 
8   Copyright 2005-2006 Nintendo. All rights reserved.
9 
10   These coded instructions, statements, and computer programs contain
11   proprietary information of Nintendo of America Inc. and/or Nintendo
12   Company Ltd., and are protected by Federal copyright law.  They may
13   not be disclosed to third parties or copied or duplicated in any form,
14   in whole or in part, without the prior written consent of Nintendo.
15  *---------------------------------------------------------------------------*/
16 
17 #include <revolution.h>
18 #include <math.h>
19 #include <stdio.h>
20 
21 #include <revolution/kpad.h>
22 #include "main.h"
23 #include "kfont.h"
24 #include "graphic.h"
25 #include "sample.h"
26 
27 
28 /***************************************************************
29     Definitions
30 ***************************************************************/
31 #define CMD_LEFT        ( (kpads[0][0].trig & KPAD_BUTTON_LEFT ) != 0 ) // Cursor movement
32 #define CMD_RIGHT       ( (kpads[0][0].trig & KPAD_BUTTON_RIGHT) != 0 )
33 #define CMD_UP          ( (kpads[0][0].trig & KPAD_BUTTON_UP   ) != 0 )
34 #define CMD_DOWN        ( (kpads[0][0].trig & KPAD_BUTTON_DOWN ) != 0 )
35 
36 #define CMD_INC         ( (kpads[0][0].trig & KPAD_BUTTON_A    ) != 0 ) // Increase/decrease value
37 #define CMD_DEC         ( (kpads[0][0].trig & KPAD_BUTTON_B    ) != 0 )
38 
39 #define CMD_ENABLE_DPD  ( (kpads[0][0].trig & KPAD_BUTTON_1    ) != 0 ) // DPD ON/OFF
40 #define CMD_DISABLE_DPD ( (kpads[0][0].trig & KPAD_BUTTON_2    ) != 0 )
41 
42 #define BTN_CALIBRATE   ( KPAD_BUTTON_PLUS | KPAD_BUTTON_MINUS )        // Calibration operation
43 #define CMD_CALIBRATE   ( (kpads[0][0].hold & BTN_CALIBRATE) == BTN_CALIBRATE && kpads[0][0].trig )
44 
45 #define CMD_AIMMODE     ( (kpads[0][0].trig & KPAD_BUTTON_HOME ) != 0 )
46 
47 #define CMD_STICK_CLAMP_HOLD1 ( kpads[0][0].dev_type == WPAD_DEV_FREESTYLE && (kpads[0][0].hold & KPAD_BUTTON_Z) != 0 )
48 #define CMD_STICK_CLAMP_HOLD2 ( ( kpads[0][0].dev_type == WPAD_DEV_CLASSIC ) \
49                              && ( kpads[0][0].ex_status.cl.hold & KPAD_CL_BUTTON_PLUS ) != 0 )
50 
51 #define CMD_STICK_CLAMP_TRIG1 ( kpads[0][0].dev_type == WPAD_DEV_FREESTYLE && (kpads[0][0].trig & KPAD_BUTTON_C) != 0 )
52 #define CMD_STICK_CLAMP_TRIG2 ( ( kpads[0][0].dev_type == WPAD_DEV_CLASSIC ) \
53                              && ( kpads[0][0].ex_status.cl.trig & KPAD_CL_BUTTON_MINUS ) != 0 )
54 
55 
56 /***************************************************************
57  Adjustment item
58 ***************************************************************/
59 static f32 pointing_scale = 200.0f ; // Screen pointing scale
60 
61 static f32 obj_interval     = 0.20f ; // TV side light emitting point placement interval (in meters)
62 
63 static f32 pos_play_radius  = 0.00f ; // 'pos' sensitivity setting
64 static f32 pos_sensitivity  = 1.00f ;
65 static f32 pos_play_mode    = (f32)KPAD_PLAY_MODE_LOOSE ;
66 static f32 hori_play_radius = 0.00f ; // 'horizon' sensitivity setting
67 static f32 hori_sensitivity = 1.00f ;
68 static f32 hori_play_mode   = (f32)KPAD_PLAY_MODE_LOOSE ;
69 static f32 dist_play_radius = 0.00f ; // 'dist' sensitivity setting
70 static f32 dist_sensitivity = 1.00f ;
71 static f32 dist_play_mode   = KPAD_PLAY_MODE_LOOSE ;
72 static f32 acc_play_radius  = 0.00f ; // 'acc' sensitivity setting
73 static f32 acc_sensitivity  = 1.00f ;
74 static f32 acc_play_mode    = KPAD_PLAY_MODE_LOOSE ;
75 
76 static f32 repeat_delay_sec = 0.75f ; // Key repeat settings
77 static f32 repeat_pulse_sec = 0.25f ;
78 
79 #define EDIT_DATA_MAX 16 // Edit data count
80 
81 typedef struct {
82     f32 *vp ;   // Pointer to variables
83     f32 min ;   // Variable minimum value
84     f32 max ;   // Variable maximum value
85     u8  y ;     // y-cursor position
86     u8  x[3] ;  // x-cursor position of each digit
87     f32 v[3] ;  // Value change for each digit
88 } EditData ;
89 
90 static EditData  edit_data[ EDIT_DATA_MAX ] = {
91     { &  pointing_scale, 0.0f,900.0f,  3, {10,11,12}, {100.0f, 10.0f, 1.0f} },
92     { &    obj_interval, 0.00f,9.00f,  5, { 9,11,12}, {1.00f, 0.10f, 0.01f} },
93     { & pos_play_radius, 0.00f,9.00f,  8, { 4, 6, 7}, {1.00f, 0.10f, 0.01f} },
94     { & pos_sensitivity, 0.00f,1.00f,  8, { 9,11,12}, {1.00f, 0.10f, 0.01f} },
95     { & pos_play_mode,   0.00f,1.00f,  8, {14,14,14}, {1.00f, 1.00f, 1.00f} },
96     { &hori_play_radius, 0.00f,9.00f,  9, { 4, 6, 7}, {1.00f, 0.10f, 0.01f} },
97     { &hori_sensitivity, 0.00f,1.00f,  9, { 9,11,12}, {1.00f, 0.10f, 0.01f} },
98     { &hori_play_mode,   0.00f,1.00f,  9, {14,14,14}, {1.00f, 1.00f, 1.00f} },
99     { &dist_play_radius, 0.00f,9.00f, 10, { 4, 6, 7}, {1.00f, 0.10f, 0.01f} },
100     { &dist_sensitivity, 0.00f,1.00f, 10, { 9,11,12}, {1.00f, 0.10f, 0.01f} },
101     { &dist_play_mode,   0.00f,1.00f, 10, {14,14,14}, {1.00f, 1.00f, 1.00f} },
102     { & acc_play_radius, 0.00f,9.00f, 11, { 4, 6, 7}, {1.00f, 0.10f, 0.01f} },
103     { & acc_sensitivity, 0.00f,1.00f, 11, { 9,11,12}, {1.00f, 0.10f, 0.01f} },
104     { & acc_play_mode,   0.00f,1.00f, 11, {14,14,14}, {1.00f, 1.00f, 1.00f} },
105     { &repeat_delay_sec, 0.00f,9.00f, 14, { 4, 6, 7}, {1.00f, 0.10f, 0.01f} },
106     { &repeat_pulse_sec, 0.00f,9.00f, 14, { 9,11,12}, {1.00f, 0.10f, 0.01f} },
107 } ;
108 
109 
110 /***************************************************************
111  Variables
112 ***************************************************************/
113 static const f32 O1Y = -1.5f;
114 static const f32 O2Y = -0.5f;
115 static const f32 O3Y = -1.0f;
116 static const f32 O4Y = -20.8f;
117 static const f32 O5Y = -20.8f;
118 static const f32 O6Y = -1.0f;
119 
120 
121 static s32 csr_x, csr_y ;   // Value adjustment cursor position
122 static s32 csr_i, csr_k ;   // Position of edited data index and digit
123 static s32 calib_disp_ct ;  // Calibration message display count
124 
125 static f32 dpd_disp_scale = 140.0f ; // DPD object display scale
126 static f32 dpd_disp_ox    = 205.0f ; // DPD object display position
127 static f32 dpd_disp_oy    =  65.0f+O5Y ;
128 
129 static BOOL aim_mode;
130 static BOOL stick_clamp_mode;
131 static BOOL stick_clamp_mode_work;
132 static BOOL reset_request;
133 
134 static KPADUnifiedWpadStatus unified_status[ KPAD_RING_BUFS ];
135 
136 s32                 MyDpdCallbackLatestIdx = -1;
137 MyDpdCallbackStatus MyDpdCallbackStatusBuf[MY_DPD_START_COUNTS_MAX];
138 vu32                MySamplingCount;
139 
140 /*******************************************************************************
141  Initialization Functions
142 *******************************************************************************/
init_sample(void)143 void init_sample( void )
144 {
145     //----- Controller initialization setting
146     KPADReset() ;
147     KPADSetPosParam ( 0,  pos_play_radius,  pos_sensitivity ) ;
148     KPADSetHoriParam( 0, hori_play_radius, hori_sensitivity ) ;
149     KPADSetDistParam( 0, dist_play_radius, dist_sensitivity ) ;
150     KPADSetAccParam ( 0,  acc_play_radius,  acc_sensitivity ) ;
151     KPADSetBtnRepeat( 0, repeat_delay_sec, repeat_pulse_sec ) ;
152 
153     //----- Cursor position initialization
154     csr_i = 0 ;  // Data index being edited
155     csr_k = 2 ;  // Digit being edited
156     csr_x = edit_data[ csr_i ].x[ csr_k ] ;
157     csr_y = edit_data[ csr_i ].y ;
158 
159     //----- Calibration message count initialization
160     calib_disp_ct = 0 ; // Negative: display failed, 0: not displayed, positive: successful display
161 
162     aim_mode = TRUE;
163     stick_clamp_mode = stick_clamp_mode_work = FALSE;
164 }
165 
166 
167 /*******************************************************************************
168  Cursor movement process
169 *******************************************************************************/
move_cursor(void)170 static void move_cursor( void )
171 {
172     EditData *ep ;
173     s32  vx,vy, wx,wy, fy ;
174     s32  i,w,k, im,wm,km ;
175 
176     /***********************************************************************
177     Cursor movement process
178     ***********************************************************************/
179     //------ Temporary movement vector
180     if ( CMD_LEFT ) vx = -1 ;
181     else if ( CMD_RIGHT ) vx = 1 ;
182     else vx = 0 ;
183 
184     if ( CMD_UP ) vy = -1 ;
185     else if ( CMD_DOWN ) vy = 1 ;
186     else vy = 0 ;
187 
188     //------ Move to the nearest digit location using edit data
189     wm = 1 << 30 ;  // Maximum distance
190     i = EDIT_DATA_MAX - 1 ;
191     do {
192         ep = &edit_data[i] ;
193 
194         fy = ( wy = ep->y - csr_y ) * vy ; // Preparation for inner product calculation
195         wy *= wy ;    // Preparation for distance calculation
196         k = 0 ;
197         do {
198             //----- Inner product must be positive
199             wx = ep->x[k] - csr_x ;
200             if ( wx * vx + fy <= 0 ) continue ;
201 
202             //----- Distance must be shortest
203             w = wx * wx + wy ;
204             if ( w >= wm ) continue ;
205 
206             //----- Candidate recording
207             wm = w ;
208             im = i ;
209             km = k ;
210         } while ( ++k < 3 ) ;
211     } while ( --i >= 0 ) ;
212 
213     //----- Move cursor if candidate is recorded
214     if ( wm != 1 << 30 ) {
215         csr_i = im ;
216         csr_k = km ;
217         csr_x = edit_data[ csr_i ].x[ csr_k ] ;
218         csr_y = edit_data[ csr_i ].y ;
219     }
220 }
221 
222 
223 /*******************************************************************************
224  Increase/decrease value process
225 *******************************************************************************/
push_cursor(void)226 static void push_cursor( void )
227 {
228     EditData *ep = &edit_data[ csr_i ] ;
229 
230     //----- Is button pressed?
231     if ( CMD_INC ) {
232         *(ep->vp) += ep->v[ csr_k ] ;
233         if ( *(ep->vp) > ep->max ) *(ep->vp) = ep->max ;
234     } else if ( CMD_DEC ) {
235         *(ep->vp) -= ep->v[ csr_k ] ;
236         if ( *(ep->vp) < ep->min ) *(ep->vp) = ep->min ;
237     } else {
238         return ; // No value change
239     }
240 
241     //----- Reset because value has changed
242     if ( csr_i >= 14 ) {
243         KPADSetBtnRepeat( 0, repeat_delay_sec, repeat_pulse_sec ) ;
244     } else if ( csr_i >=11 ) {
245         KPADSetAccParam    ( 0, acc_play_radius,  acc_sensitivity ) ;
246         KPADSetAccPlayMode ( 0, (KPADPlayMode)acc_play_mode ) ;
247     } else if ( csr_i >= 8 ) {
248         KPADSetDistParam   ( 0, dist_play_radius, dist_sensitivity ) ;
249         KPADSetDistPlayMode( 0, (KPADPlayMode)dist_play_mode ) ;
250     } else if ( csr_i >= 5 ) {
251         KPADSetHoriParam   ( 0, hori_play_radius, hori_sensitivity ) ;
252         KPADSetHoriPlayMode( 0, (KPADPlayMode)hori_play_mode ) ;
253     } else if ( csr_i >= 2 ) {
254         KPADSetPosParam    ( 0, pos_play_radius,  pos_sensitivity ) ;
255         KPADSetPosPlayMode ( 0, (KPADPlayMode)pos_play_mode ) ;
256     } else if ( csr_i == 1 ) {
257         KPADSetObjInterval( obj_interval ) ;
258         reset_request = TRUE;
259     }
260 }
261 
262 
263 /*******************************************************************************
264  CPU process function
265 *******************************************************************************/
work_sample(void)266 void work_sample( void )
267 {
268     if (kpad_reads <= 0) {
269         return;
270     }
271 
272     if (kpads[0][0].hold == 0 && reset_request) {
273         reset_request = FALSE;
274         OSReport("KPADReset() from work_sample()\n");
275         KPADReset();
276         return;
277     }
278 
279     /***********************************************************************
280     Calibration
281     ***********************************************************************/
282     if ( calib_disp_ct < 0 ) ++ calib_disp_ct ;
283     else if ( calib_disp_ct ) -- calib_disp_ct ;
284 
285     if ( CMD_CALIBRATE ) {
286         if ( KPADCalibrateDPD( 0 ) == 2 ) {
287             calib_disp_ct = 180 ; // Successful
288         } else {
289             calib_disp_ct = -180 ; // Failed
290         }
291     }
292 
293     /***********************************************************************
294     DPD ON/OFF
295     ***********************************************************************/
296     if ( CMD_ENABLE_DPD ) {
297         KPADEnableDPD( 0 );
298     }
299     if ( CMD_DISABLE_DPD ) {
300         KPADDisableDPD( 0 );
301     }
302 
303     /***********************************************************************
304     AIMMODE on/off
305     ***********************************************************************/
306     if ( CMD_AIMMODE ) {
307         aim_mode = (aim_mode) ? FALSE : TRUE;
308         if( aim_mode ) {
309             KPADEnableAimingMode( 0 );
310         }
311         else {
312             KPADDisableAimingMode( 0 );
313         }
314     }
315 
316     /***********************************************************************
317     Stick clamp mode ON/OFF
318     ***********************************************************************/
319     if ( CMD_STICK_CLAMP_TRIG1 || CMD_STICK_CLAMP_TRIG2 ) {
320         stick_clamp_mode_work = (stick_clamp_mode_work) ? FALSE : TRUE;
321     }
322     if ( CMD_STICK_CLAMP_HOLD1 || CMD_STICK_CLAMP_HOLD2 ) {
323         stick_clamp_mode = (stick_clamp_mode_work) ? FALSE : TRUE;
324     } else {
325         stick_clamp_mode = stick_clamp_mode_work;
326     }
327     if ( stick_clamp_mode ) {
328         KPADEnableStickCrossClamp();
329     } else {
330         KPADDisableStickCrossClamp();
331     }
332 
333     /***********************************************************************
334     Value edit process
335     ***********************************************************************/
336     move_cursor() ;  // Cursor movement process
337     push_cursor() ;  // Increase/decrease value process
338 }
339 
340 
341 /*******************************************************************************
342  Rendering pointing scale frame
343 *******************************************************************************/
draw_pointing_frame(void)344 static void draw_pointing_frame( void )
345 {
346     draw_line( -pointing_scale,-pointing_scale, pointing_scale,-pointing_scale, blue_clr, 2.5f ) ;
347     draw_line(  pointing_scale,-pointing_scale, pointing_scale, pointing_scale, blue_clr, 2.5f ) ;
348     draw_line(  pointing_scale, pointing_scale,-pointing_scale, pointing_scale, blue_clr, 2.5f ) ;
349     draw_line( -pointing_scale, pointing_scale,-pointing_scale,-pointing_scale, blue_clr, 2.5f ) ;
350 }
351 
352 
353 /*******************************************************************************
354  Rendering pointing coordinate
355 *******************************************************************************/
draw_position(KPADStatus * sp)356 static void draw_position( KPADStatus *sp )
357 {
358     Vec2  pos, vec ;
359     f32  scale ;
360 
361     if (sp->dpd_valid_fg <= 0) {
362         return;
363     }
364     switch (sp->data_format) {
365       case WPAD_FMT_CORE_ACC_DPD:
366       case WPAD_FMT_FREESTYLE_ACC_DPD:
367       case WPAD_FMT_CLASSIC_ACC_DPD:
368         break;
369 
370       default:
371         return;
372     }
373 
374     //------ +Control Pad
375     pos.x = pointing_scale * sp->pos.x ; // Center coordinate
376     pos.y = pointing_scale * sp->pos.y ;
377 
378     scale = 72.0f ;
379     vec.x = scale * sp->horizon.x ;  // Right direction vector
380     vec.y = scale * sp->horizon.y ;
381     draw_line( pos.x-vec.x,pos.y-vec.y, pos.x+vec.x,pos.y+vec.y, yellow_clr, 3 ) ;
382 
383     scale = 28.0f ;
384     vec.x = scale * -sp->horizon.y ; // Lower direction vector
385     vec.y = scale *  sp->horizon.x ;
386     draw_arrow( pos.x+vec.x,pos.y+vec.y, pos.x-vec.x,pos.y-vec.y, silver_clr, 3 ) ;
387 
388     //------ Center point
389     draw_point( pos.x,pos.y, black_clr, 11 ) ;
390     draw_point( pos.x,pos.y,  cyan_clr,  9 ) ;
391 }
392 
393 
394 /*******************************************************************************
395  Rendering grids
396 *******************************************************************************/
draw_grid(f32 ox,f32 oy,f32 radius,GXColor clr)397 static void draw_grid( f32 ox, f32 oy, f32 radius, GXColor clr )
398 {
399     f32  r = radius * 1.4f ; // Cross length
400 
401     draw_arrow( ox-r,oy, ox+r,oy, clr, 3 ) ; // Horizontal line
402     draw_arrow( ox,oy+r, ox,oy-r, clr, 3 ) ; // Vertical line
403     draw_circle( ox,oy, radius, clr, 3 ) ;  // Circle
404 }
405 
406 
407 /*******************************************************************************
408  Rendering acceleration
409 *******************************************************************************/
draw_acc(f32 ox,f32 oy,f32 radius,f32 ax,f32 ay)410 static void draw_acc( f32 ox, f32 oy, f32 radius, f32 ax, f32 ay )
411 {
412     f32  px = ax * radius + ox ;
413     f32  py = ay * radius + oy ;
414 
415     draw_arrow( ox,oy, px,py, red_clr, 4 ) ;
416     draw_point( px,py, white_clr, 4 ) ;
417 }
418 
419 
420 /*******************************************************************************
421  Rendering Nunchuk unit acceleration
422 *******************************************************************************/
draw_acc2(f32 ox,f32 oy,f32 radius,f32 ax,f32 ay)423 static void draw_acc2( f32 ox, f32 oy, f32 radius, f32 ax, f32 ay )
424 {
425     f32  px = ax * radius + ox ;
426     f32  py = ay * radius + oy ;
427 
428     draw_dashed_arrow( ox,oy, px,py, red_clr, 4 ) ;
429     draw_point( px,py, white_clr, 4 ) ;
430 }
431 
432 
draw_stick(f32 ox,f32 oy,f32 radius,f32 sx,f32 sy,GXColor clr,BOOL dashed)433 static void draw_stick( f32 ox, f32 oy, f32 radius, f32 sx, f32 sy, GXColor clr, BOOL dashed )
434 {
435     f32 px = sx * radius + ox;
436     f32 py = sy * radius + oy;
437 
438     if ( dashed ) {
439         draw_dashed_arrow( ox,oy, px,py, clr, 4 ) ;
440     } else {
441         draw_arrow( ox,oy, px,py, clr, 4 ) ;
442     }
443     draw_point( px,py, white_clr, 4 ) ;
444 }
445 
446 
447 /*******************************************************************************
448  Rendering value adjustment cursor
449 *******************************************************************************/
draw_cursor(void)450 static void draw_cursor( void )
451 {
452     f32  x1,y1, x2,y2 ;
453 
454     x1 = calc_kfont_x1( csr_x ) ;
455     y1 = calc_kfont_y1( csr_y+O1Y ) ;
456     y2 = calc_kfont_y2( csr_y+O1Y ) - 1.0f ;
457     if ( csr_x > 12 ) {
458         x2 = calc_kfont_x2( csr_x + 4.0f ) - 1.0f ;
459     } else {
460         x2 = calc_kfont_x2( csr_x ) - 1.0f ;
461     }
462     draw_line( x1,y1, x2,y1, white_clr, 2 ) ;
463     draw_line( x2,y1, x2,y2, white_clr, 2 ) ;
464     draw_line( x2,y2, x1,y2, white_clr, 2 ) ;
465     draw_line( x1,y2, x1,y1, white_clr, 2 ) ;
466 }
467 
468 
469 /*******************************************************************************
470  Rendering DPD sensor frame
471 *******************************************************************************/
draw_dpd_frame(void)472 static void draw_dpd_frame( void )
473 {
474     f32  rx,ry, x1,y1, x2,y2 ;
475 
476     rx = dpd_disp_scale * 0.5f ;
477     ry = rx * (f32)WPAD_DPD_IMG_RESO_WY / (f32)WPAD_DPD_IMG_RESO_WX ;
478     x1 = dpd_disp_ox - rx ;
479     y1 = dpd_disp_oy - ry ;
480     x2 = dpd_disp_ox + rx ;
481     y2 = dpd_disp_oy + ry ;
482 
483     GXSetTevColor( GX_TEVREG0, smoke_clr ) ;
484 
485     GXBegin( GX_QUADS, GX_VTXFMT0, 4 ) ;
486       GXPosition2f32( x1, y1 ) ;
487       GXPosition2f32( x2, y1 ) ;
488       GXPosition2f32( x2, y2 ) ;
489       GXPosition2f32( x1, y2 ) ;
490     GXEnd() ;
491 }
492 
493 
494 /*******************************************************************************
495  Rendering DPD object
496 *******************************************************************************/
draw_object(void)497 static void draw_object( void )
498 {
499     DPDObject              *op, *op1 ;
500     f32                     px,py, scale, ofx,ofy ;
501     s32                     n;
502     KPADUnifiedWpadStatus  *up;
503 
504     // Caution: The return value of KPADRead (number of samples) is not the same as the effective number of samples inside unified_status.
505     //
506     //
507     // Also, KPADGetUnifiedWpadStatus() gets the latest data at this point.
508     // Accordingly, buffer contents are not the same as data retrieved inside KPADRead().
509     //
510     //
511     // In order to get exactly the same data as obtained inside KPADRead(), while interrupts are disabled, call KPADRead() and KPADGetUnifiedWpadStatus() in succession. However, the period during which interrupts are disabled will become longer.
512     //
513     //
514 
515     // In this sample program, kpad_reads is used as the number of samples without strictly synchronizing data in order to draw DPD objects easily.
516     //
517     n = kpad_reads ;   // Current sampling count
518     if (n <= 0) {
519         return;
520     }
521 
522     KPADGetUnifiedWpadStatus( 0, unified_status, (u32)n );
523 
524     //----- Display position calculation
525     scale = dpd_disp_scale / (f32)WPAD_DPD_IMG_RESO_WX ;
526     ofx = dpd_disp_scale * -0.5f ;
527     ofy = ofx * (f32)WPAD_DPD_IMG_RESO_WY / (f32)WPAD_DPD_IMG_RESO_WX ;
528     ofx += dpd_disp_ox ;
529     ofy += dpd_disp_oy ;
530 
531     //----- Display all values sampled at 200Hz
532         // Render starting from older items
533 
534     while ( --n >= 0 ) {
535         up = &unified_status[n];
536         if (up->u.core.err == WPAD_ERR_NONE) {
537             switch (up->fmt) {
538               case WPAD_FMT_CORE_ACC:
539               case WPAD_FMT_CORE_ACC_DPD:
540               case WPAD_FMT_FREESTYLE_ACC:
541               case WPAD_FMT_FREESTYLE_ACC_DPD:
542               case WPAD_FMT_CLASSIC_ACC:
543               case WPAD_FMT_CLASSIC_ACC_DPD:
544                 op1 = up->u.core.obj;
545                 break;
546 
547               default:
548                 op1 = NULL;
549                 break;
550             }
551             if (op1) {
552                 op = op1 + (WPAD_DPD_MAX_OBJECTS - 1);
553                 do {
554                     if ( op->size == 0 ) continue ;
555 
556                     //----- Change to display coordinates
557                     px = (f32)op->x * scale + ofx ;
558                     py = (f32)op->y * scale + ofy ;
559 
560                     //----- Render object
561                     draw_point( px,py, white_clr, 5 ) ;
562                     draw_circle( px,py, 5, black_clr, 2 ) ;
563                     draw_circle( px,py, 4, smoke_clr, 2 ) ;
564                     draw_circle( px,py, 3,  gray_clr, 2 ) ;
565                 } while ( --op >= op1 ) ;
566             }
567         }
568     }
569 }
570 
draw_object_by_kpad1_style(void)571 static void draw_object_by_kpad1_style( void )
572 {
573     WPADStatus   *wp ;
574     WPADFSStatus *fp ;
575     WPADCLStatus *cp ;
576     DPDObject    *op, *op1 ;
577     f32          px,py, scale, ofx,ofy ;
578     s32          n, i ;
579 
580 
581     if ( kpads[0][0].dev_type == WPAD_DEV_NOT_FOUND ) {
582         return ;
583     }
584 
585     //----- Display position calculation
586     scale = dpd_disp_scale / (f32)WPAD_DPD_IMG_RESO_WX ;
587     ofx = dpd_disp_scale * -0.5f ;
588     ofy = ofx * (f32)WPAD_DPD_IMG_RESO_WY / (f32)WPAD_DPD_IMG_RESO_WX ;
589     ofx += dpd_disp_ox ;
590     ofy += dpd_disp_oy ;
591 
592     //----- Display all values sampled at 200Hz
593     switch ( kpads[0][0].dev_type ) {
594       case WPAD_DEV_CORE:
595       case WPAD_DEV_FUTURE:
596       case WPAD_DEV_NOT_SUPPORTED:
597       case WPAD_DEV_UNKNOWN:
598         wp = KPADGetWPADRingBuffer( 0 ) ;   // WPAD ring buffer
599         break;
600       case WPAD_DEV_FREESTYLE:
601         fp = KPADGetWPADFSRingBuffer( 0 ) ; // WPAD ring buffer
602         break;
603       case WPAD_DEV_CLASSIC:
604         cp = KPADGetWPADCLRingBuffer( 0 ) ; // WPAD ring buffer
605         break;
606     }
607     i = (s32)WPADGetLatestIndexInBuf( 0 ) ; // Latest index
608     n = kpad_reads ;                        // Current sampling count
609 
610     i -= n - 1 ;    // Render starting from older items
611     if ( i < 0 ) i += KPAD_RING_BUFS ;
612 
613     while ( --n >= 0 ) {
614         switch( kpads[0][0].dev_type ) {
615           case WPAD_DEV_CORE:
616           case WPAD_DEV_FUTURE:
617           case WPAD_DEV_NOT_SUPPORTED:
618           case WPAD_DEV_UNKNOWN:
619             op = &wp[i].obj[ WPAD_DPD_MAX_OBJECTS - 1 ] ;
620             op1 = wp[i].obj ;
621             break;
622           case WPAD_DEV_FREESTYLE:
623             op = &fp[i].obj[ WPAD_DPD_MAX_OBJECTS - 1 ] ;
624             op1 = fp[i].obj ;
625             break;
626           case WPAD_DEV_CLASSIC:
627             op = &cp[i].obj[ WPAD_DPD_MAX_OBJECTS - 1 ] ;
628             op1 = cp[i].obj ;
629         }
630         do {
631             if ( op->size == 0 ) continue ;
632 
633             //----- Change to display coordinates
634             px = (f32)op->x * scale + ofx ;
635             py = (f32)op->y * scale + ofy ;
636 
637             //----- Render object
638             draw_point( px,py, white_clr, 5 ) ;
639             draw_circle( px,py, 5, black_clr, 2 ) ;
640             draw_circle( px,py, 4, smoke_clr, 2 ) ;
641             draw_circle( px,py, 3,  gray_clr, 2 ) ;
642         } while ( --op >= op1 ) ;
643 
644         if ( ++i == KPAD_RING_BUFS ) i = 0 ;
645     }
646 }
647 
draw_sampling_rate(void)648 static void draw_sampling_rate( void )
649 {
650     static OSTime time;
651     static u32 countDisp;
652     BOOL enabled;
653     OSTime t;
654 
655     t = OSGetTime();
656     if (OSTicksToSeconds((OSTime)(t - time)) > 0) {
657         time = t;
658         enabled = OSDisableInterrupts();
659         countDisp = MySamplingCount;
660         MySamplingCount = 0;
661         (void)OSRestoreInterrupts( enabled );
662     }
663 
664     draw_kfont_letter( 0,17+O6Y, gray_clr, "SMP.RATE" );
665     (void)draw_kfont_s32( 14,17+O6Y, white_clr, (s32)countDisp );
666 }
667 
draw_dpd_callback_status(void)668 static void draw_dpd_callback_status( void )
669 {
670     u32 i;
671     MyDpdCallbackStatus buf[MY_DPD_START_COUNTS_MAX];
672     BOOL enabled;
673     char str[32];
674     s32  latestIdx;
675 
676     enabled = OSDisableInterrupts();
677     for (i = 0; i < MY_DPD_START_COUNTS_MAX; i++) {
678         if (MyDpdCallbackStatusBuf[i].count) {
679             MyDpdCallbackStatusBuf[i].count--;
680         }
681         buf[i] = MyDpdCallbackStatusBuf[i];
682     }
683     latestIdx = MyDpdCallbackLatestIdx;
684     (void)OSRestoreInterrupts( enabled );
685 
686     for (i = 0; i < MY_DPD_START_COUNTS_MAX; i++) {
687         if ((s32)i == latestIdx ||
688             buf[i].count) {
689             sprintf(str, "DPDCB %d", buf[i].reason);
690             draw_kfont_letter( (f32)(buf[i].reason == KPAD_STATE_CTRL_DPD_START
691                                      ? 0.0f
692                                      : 8.0f),
693                                buf[i].count * 0.05f + 0.5f, white_clr, str );
694         }
695     }
696 }
697 
698 
699 /*******************************************************************************
700  Drawing function
701 *******************************************************************************/
draw_sample(void)702 void draw_sample( void )
703 {
704     s32     cx,cy ;
705     f32     x1,x2, y, r ;
706     u32     hold, trig, release;
707     u32     flag;
708 
709     /***********************************************************************
710         Pointing scale frame
711     ***********************************************************************/
712     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
713     draw_pointing_frame() ;
714 
715     /***********************************************************************
716         Adjustment item
717     ***********************************************************************/
718     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 15.6f, 20.8f ) ;
719     cx = 0 ;
720     cy = 3 ;
721     draw_kfont_letter( cx,cy+O1Y, gray_clr, "POINTING") ;
722     (void)draw_kfont_s32( cx+12,cy+O1Y, blue_clr, (s32)pointing_scale ) ;
723     cy += 2 ;
724     draw_kfont_letter( cx,cy+O1Y, gray_clr, "INTERVAL") ;
725     (void)draw_kfont_f32( cx+9,cy+O1Y, peagreen_clr, obj_interval, 2 ) ;
726     cy += 2 ;
727     draw_kfont_letter( cx,cy+O1Y, gray_clr, "    PLAY SENS MODE") ;
728     ++ cy ;
729     draw_kfont_letter( cx,cy+O1Y, gray_clr, "POS" ) ;
730     (void)draw_kfont_f32   ( cx+ 4,cy+O1Y,   cyan_clr,  pos_play_radius, 2 ) ;
731     (void)draw_kfont_f32   ( cx+ 9,cy+O1Y,   cyan_clr,  pos_sensitivity, 2 ) ;
732     (void)draw_kfont_letter( cx+14,cy+O1Y,   cyan_clr, (pos_play_mode) ? "TIGHT" : "LOOSE" ) ;
733     ++ cy ;
734     draw_kfont_letter( cx,cy+O1Y, gray_clr, "HOR" ) ;
735     (void)draw_kfont_f32   ( cx+ 4,cy+O1Y, yellow_clr, hori_play_radius, 2 ) ;
736     (void)draw_kfont_f32   ( cx+ 9,cy+O1Y, yellow_clr, hori_sensitivity, 2 ) ;
737     (void)draw_kfont_letter( cx+14,cy+O1Y, yellow_clr,(hori_play_mode) ? "TIGHT" : "LOOSE" ) ;
738     ++ cy ;
739     draw_kfont_letter( cx,cy+O1Y, gray_clr, "DIS" ) ;
740     (void)draw_kfont_f32   ( cx+ 4,cy+O1Y,  green_clr, dist_play_radius, 2 ) ;
741     (void)draw_kfont_f32   ( cx+ 9,cy+O1Y,  green_clr, dist_sensitivity, 2 ) ;
742     (void)draw_kfont_letter( cx+14,cy+O1Y,  green_clr,(dist_play_mode) ? "TIGHT" : "LOOSE" ) ;
743     ++ cy ;
744     draw_kfont_letter( cx,cy+O1Y, gray_clr, "ACC" ) ;
745     (void)draw_kfont_f32   ( cx+ 4,cy+O1Y,    red_clr,  acc_play_radius, 2 ) ;
746     (void)draw_kfont_f32   ( cx+ 9,cy+O1Y,    red_clr,  acc_sensitivity, 2 ) ;
747     (void)draw_kfont_letter( cx+14,cy+O1Y,    red_clr, (acc_play_mode) ? "TIGHT" : "LOOSE" ) ;
748     cy += 2 ;
749     draw_kfont_letter( cx,cy+O1Y, gray_clr, "    DLAY PULS") ;
750     ++ cy ;
751     draw_kfont_letter( cx,cy+O1Y, gray_clr, "RPT") ;
752     (void)draw_kfont_f32( cx+4,cy+O1Y, orange_clr, repeat_delay_sec, 2 ) ;
753     (void)draw_kfont_f32( cx+9,cy+O1Y, orange_clr, repeat_pulse_sec, 2 ) ;
754 
755     //----- Various data title
756     draw_kfont_letter( 29.0f, 3.0f+O6Y, gray_clr, "ACC"  ) ; // Acceleration information
757     draw_kfont_letter( 15.2f,12.5f+O6Y, gray_clr, "VALID") ; // DPD enable flag
758     draw_kfont_letter( 23.0f,12.5f+O6Y, gray_clr, "DIST" ) ; // Distance information
759     draw_kfont_letter( 33.8f,10.1f+O6Y, gray_clr, "OBJ"  ) ; // Object
760 
761     /***********************************************************************
762         Value adjustment cursor
763     ***********************************************************************/
764     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
765     draw_cursor() ;
766 
767     /***********************************************************************
768         DPD enable flag & distance information
769     ***********************************************************************/
770     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 30.0f, 40.0f ) ;
771     (void)draw_kfont_s32(  8.6f,7.4f+O2Y, violet_clr, kpads[0][0].dpd_valid_fg ) ;
772     (void)draw_kfont_f32( 10.6f,7.4f+O2Y,  green_clr, kpads[0][0].dist, 2 ) ;
773 
774     /***********************************************************************
775         Show sampling rate
776     ***********************************************************************/
777     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 14.0f, 18.8f ) ;
778     draw_sampling_rate() ;
779 
780     /***********************************************************************
781         Button bit information
782     ***********************************************************************/
783     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 14.0f, 18.8f ) ;
784     cx =  0 ;
785     cy =  18 ;
786 
787     hold    = kpads[0][0].hold;
788     trig    = kpads[0][0].trig;
789     release = kpads[0][0].release;
790 
791     draw_kfont_letter( cx,cy+O6Y, gray_clr, "HLD") ;
792     if (kpad_reads > 0) {
793         draw_kfont_bit( cx+39,cy+O6Y, orange_clr, hold   , 32 ) ;
794     }
795     ++ cy ;
796     draw_kfont_letter( cx,cy+O6Y, gray_clr, "TRG") ;
797     if (kpad_reads > 0) {
798         draw_kfont_bit( cx+39,cy+O6Y, orange_clr, trig   , 32 ) ;
799     }
800     ++ cy ;
801     draw_kfont_letter( cx,cy+O6Y, gray_clr, "REL") ;
802     if (kpad_reads > 0) {
803         draw_kfont_bit( cx+39,cy+O6Y, orange_clr, release, 32 ) ;
804     }
805 
806     if (kpad_reads > 0) {
807         if ( kpads[0][0].wpad_err == WPAD_ERR_NONE && kpads[0][0].dev_type == WPAD_DEV_CLASSIC ) {
808             hold    = kpads[0][0].ex_status.cl.hold;
809             trig    = kpads[0][0].ex_status.cl.trig;
810             release = kpads[0][0].ex_status.cl.release;
811 
812             ++ cy ;
813             draw_kfont_letter( cx,cy+O6Y, gray_clr, "HLD") ;
814             draw_kfont_bit( cx+39,cy+O6Y, peagreen_clr, hold   , 32 ) ;
815             ++ cy ;
816             draw_kfont_letter( cx,cy+O6Y, gray_clr, "TRG") ;
817             draw_kfont_bit( cx+39,cy+O6Y, peagreen_clr, trig   , 32 ) ;
818             ++ cy ;
819             draw_kfont_letter( cx,cy+O6Y, gray_clr, "REL") ;
820             draw_kfont_bit( cx+39,cy+O6Y, peagreen_clr, release, 32 ) ;
821         }
822     } else {
823         if (WPADProbe(0, NULL) == WPAD_ERR_NO_CONTROLLER) {
824             cy -= 1;
825             draw_kfont_letter( cx+8,cy+O6Y, white_clr, "OTHER TESTS BY GC CONT. 1P") ;
826             ++ cy ;
827             draw_kfont_letter( cx+8,cy+O6Y, white_clr, " A BUTTON - KPADRESET") ;
828             ++ cy ;
829             draw_kfont_letter( cx+8,cy+O6Y, white_clr, " B BUTTON - SKIP KPADREAD") ;
830         }
831     }
832 
833     /***********************************************************************
834         Acceleration information
835     ***********************************************************************/
836     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 15.0f, 20.0f ) ;
837     draw_kfont_letter( 25.0f,2.5f+O3Y, smoke_clr, "Y            Y") ;
838     draw_kfont_letter( 29.0f,6.5f+O3Y, smoke_clr, "X            Z") ;
839 
840     x1 =   35.0f ;      // x-coordinate of left grid
841     x2 =  210.0f ;      // x-coordinate of right grid
842     y  = -100.0f+O4Y ;  // Common y-coordinate
843     r  =   60.0f ;      // Common radius
844 
845     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
846     draw_grid( x1, y, r, smoke_clr ) ;
847     draw_grid( x2, y, r, smoke_clr ) ;
848 
849     cx = kpad_reads ;
850     while ( --cx >= 0 ) {
851         if (kpads[0][cx].wpad_err == WPAD_ERR_NONE) {
852             switch (kpads[0][cx].data_format) {
853               case WPAD_FMT_CORE_ACC:
854               case WPAD_FMT_CORE_ACC_DPD:
855               case WPAD_FMT_CLASSIC_ACC:
856               case WPAD_FMT_CLASSIC_ACC_DPD:
857                 flag = 0x01;
858                 break;
859 
860               case WPAD_FMT_FREESTYLE_ACC:
861               case WPAD_FMT_FREESTYLE_ACC_DPD:
862                 flag = 0x03;
863                 break;
864 
865               default:
866                 flag = 0x00;
867                 break;
868             }
869 
870             if (flag & 0x01) {
871                 draw_acc( x1, y, r, kpads[0][cx].acc.x, -kpads[0][cx].acc.y ) ;
872                 draw_acc( x2, y, r, kpads[0][cx].acc.z, -kpads[0][cx].acc.y ) ;
873             }
874             if (flag & 0x02) {
875                 draw_acc2( x1, y, r, kpads[0][cx].ex_status.fs.acc.x, -kpads[0][cx].ex_status.fs.acc.y ) ;
876                 draw_acc2( x2, y, r, kpads[0][cx].ex_status.fs.acc.z, -kpads[0][cx].ex_status.fs.acc.y ) ;
877             }
878         }
879     }
880 
881     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
882     cx = kpad_reads ;
883     while ( --cx >= 0 ) {
884         if (kpads[0][cx].wpad_err == WPAD_ERR_NONE) {
885             if(kpads[0][cx].dev_type == WPAD_DEV_FREESTYLE) {
886                 draw_stick( x1, y, r, kpads[0][cx].ex_status.fs.stick.x, -kpads[0][cx].ex_status.fs.stick.y, yellow_clr, TRUE ) ;
887             } else if (kpads[0][cx].dev_type == WPAD_DEV_CLASSIC) {
888                 draw_stick( x1, y, r, kpads[0][cx].ex_status.cl.lstick.x, -kpads[0][cx].ex_status.cl.lstick.y, blue_clr,  FALSE ) ;
889                 draw_stick( x1, y, r, kpads[0][cx].ex_status.cl.rstick.x, -kpads[0][cx].ex_status.cl.rstick.y, green_clr, FALSE ) ;
890             }
891         }
892     }
893 
894 
895     /***********************************************************************
896         DPD object display
897     ***********************************************************************/
898     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
899     draw_dpd_frame() ;
900     draw_object() ;
901 //  draw_object_by_kpad1_style() ;
902 
903     /***********************************************************************
904         Pointing cursor
905     ***********************************************************************/
906     init_draw_graphic( rmode_p->fbWidth, rmode_p->efbHeight ) ;
907     cx = kpad_reads ;
908     while ( --cx >= 0 ) {
909         draw_position( &kpads[0][cx] ) ;
910     }
911 
912     /***********************************************************************
913         Calibration message
914     ***********************************************************************/
915     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 60.0f, 80.0f ) ;
916     if ( calib_disp_ct < 0 ) {
917         draw_kfont_letter( 0.5f,1.4f, magenta_clr, "  ERROR  ") ; // Fail message
918     } else if ( calib_disp_ct ) {
919         draw_kfont_letter( 0.5f,1.4f, magenta_clr, "CALIBRATE") ; // Success message
920     }
921 
922     /***********************************************************************
923         Show KPAD DPD callback status
924     ***********************************************************************/
925     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 15.0f, 20.0f ) ;
926     draw_dpd_callback_status() ;
927 
928     /***********************************************************************
929         Show AIMMODE and stick clamp mode
930     ***********************************************************************/
931     init_draw_kfont( rmode_p->fbWidth, rmode_p->efbHeight, 15.0f, 20.0f ) ;
932     draw_kfont_letter( 20.0f,0.5f, white_clr, aim_mode ? "AIM ON" : "AIM OFF");
933     draw_kfont_letter( 30.0f,0.5f, white_clr, stick_clamp_mode ? "CROSS CLAMP" : "CIRCLE CLAMP");
934 }
935 
936