1 /*---------------------------------------------------------------------------*
2   Project:  Sampling callback demo
3   File:     sampling.c
4 
5   Copyright (C) 1998-2006 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: sampling.c,v $
14   Revision 1.1  02/02/2006 06:11:49  yasuh-to
15   Initial import
16 
17 
18     5     11/27/01 11:56 Shiki
19     Revised using SISetSamplingRate().
20 
21     4     11/21/01 14:32 Shiki
22     Revised.
23 
24     3     9/08/01 14:59 Shiki
25     Clean up.
26 
27     2     9/07/01 22:00 Shiki
28     Fixed to make this program work even if no controller is attached
29     initially.
30 
31     1     9/03/01 19:40:00 Shiki
32     Initial check-in.
33   $NoKeywords: $
34  *---------------------------------------------------------------------------*/
35 
36 #include <stdlib.h>
37 #include <string.h>
38 #include <demo.h>
39 
40 volatile PADStatus Pads[SI_MAX_CHAN];
41 vu64     Count;
42 
SamplingCallback(void)43 static void SamplingCallback(void)
44 {
45     PADStatus pads[SI_MAX_CHAN];
46     s32       chan;
47 
48     PADRead(pads);
49     PADClamp(pads);
50     for (chan = 0; chan < SI_MAX_CHAN; ++chan)
51     {
52         if (pads[chan].err != PAD_ERR_TRANSFER)
53         {
54             memcpy((PADStatus*) &Pads[chan], &pads[chan], sizeof(PADStatus));
55         }
56     }
57 
58     ++Count;
59 }
60 
main(int argc,char * argv[])61 void main(int argc, char* argv[])
62 {
63     BOOL             reset = FALSE;  // TRUE if reset is requested
64     BOOL             enabled;
65     PADStatus        pads[SI_MAX_CHAN];
66     s32              chan;
67     u32              chanBit;
68     u32              resetBits;
69     u32              msec;
70     GXRenderModeObj* rmp;
71     GXColor          blue = { 0, 0, 127, 0 };
72     s16              x, y;
73 
74     DEMOInit(NULL);     // for VIInit() and PADInit()
75 
76     for (chan = 0; chan < SI_MAX_CHAN; ++chan)
77     {
78         Pads[chan].err = PAD_ERR_NO_CONTROLLER;
79     }
80     PADInit();
81     PADSetSamplingCallback(SamplingCallback);
82 
83     msec = 0;
84     if (argc == 2)
85     {
86         msec = (u32) atoi(argv[1]);
87         if (11 < msec)
88         {
89             msec = 0;
90         }
91     }
92     SISetSamplingRate(msec);
93 
94     // Clear EFB
95     GXSetCopyClear(blue, 0x00ffffff);
96     GXCopyDisp(DEMOGetCurrentBuffer(), GX_TRUE);
97 
98     for (;;)
99     {
100         DEMOBeforeRender();
101 
102         x = 25;
103         y = 30;
104 
105         rmp = DEMOGetRenderModeObj();
106         DEMOInitCaption(DM_FT_XLU, (s16) rmp->fbWidth * 3 / 4, (s16) rmp->efbHeight * 3 / 4);
107 
108         enabled = OSDisableInterrupts();
109         memcpy(pads, (PADStatus*) Pads, sizeof Pads);
110         OSRestoreInterrupts(enabled);
111 
112         // The user specified sampling callback function is usually beginning
113         // to be called after the next vertical retrace interrupt. Please make
114         // sure that your program does not call PADReset() more than once before
115         // the sampling callback function is called, or the controller is
116         // removed from the controller port.
117         resetBits = 0;
118         for (chan = 0; chan < SI_MAX_CHAN; ++chan)
119         {
120             chanBit = SI_CHAN_BIT(chan);
121             switch (SIProbe(chan))
122             {
123               case SI_GC_CONTROLLER:
124               case SI_GC_WAVEBIRD:
125                 if (pads[chan].err == PAD_ERR_NO_CONTROLLER)
126                 {
127                     resetBits |= chanBit;
128                     // Prevent the 2nd call to PADReset() before SamplingCallback() is called.
129                     Pads[chan].err = PAD_ERR_NOT_READY;
130                 }
131                 break;
132               default:
133                 Pads[chan].err = PAD_ERR_NO_CONTROLLER;
134                 break;
135             }
136         }
137         if (resetBits)
138         {
139             PADReset(resetBits);
140         }
141 
142         DEMOPrintf(x, y += 16, 0, "Port  AB XY M ZLR +Pad Left       Right      Trigger");
143         //                         1[-2] AB XY M ZLR <>^v (123, 123) (123, 123) (123, 123)
144         for (chan = 0; chan < SI_MAX_CHAN; chan++)
145         {
146             DEMOPrintf(x, y += 16, 0, "%d[%-2d] %c%c %c%c %c %c%c%c %c%c%c%c (%3d, %3d) (%3d, %3d) (%3d, %3d)",
147                        chan,
148                        pads[chan].err,
149                        (pads[chan].button & PAD_BUTTON_A) ? 'O' : '_',
150                        (pads[chan].button & PAD_BUTTON_B) ? 'O' : '_',
151                        (pads[chan].button & PAD_BUTTON_X) ? 'O' : '_',
152                        (pads[chan].button & PAD_BUTTON_Y) ? 'O' : '_',
153                        (pads[chan].button & PAD_BUTTON_MENU) ? 'O' : '_',
154                        (pads[chan].button & PAD_TRIGGER_Z) ? 'O' : '_',
155                        (pads[chan].button & PAD_TRIGGER_L) ? 'O' : '_',
156                        (pads[chan].button & PAD_TRIGGER_R) ? 'O' : '_',
157 
158                        (pads[chan].button & PAD_BUTTON_LEFT)  ? '<' : '_',
159                        (pads[chan].button & PAD_BUTTON_RIGHT) ? '>' : '_',
160                        (pads[chan].button & PAD_BUTTON_UP)    ? '^' : '_',
161                        (pads[chan].button & PAD_BUTTON_DOWN)  ? 'v' : '_',
162 
163                        pads[chan].stickX,
164                        pads[chan].stickY,
165                        pads[chan].substickX,
166                        pads[chan].substickY,
167                        pads[chan].triggerLeft,
168                        pads[chan].triggerRight);
169         }
170         DEMOPrintf(x, y += 16, 0, "Samples: %llu", Count);
171         DEMOPrintf(x, y += 16, 0, "Retrace: %u",   VIGetRetraceCount());
172 
173         DEMODoneRender();
174 
175         // Handle reset button
176         if (OSGetResetButtonState())
177         {
178             reset = TRUE;
179         }
180         else if (reset)
181         {
182             // Restart
183             OSResetSystem(FALSE, 0x01, FALSE);
184         }
185     }
186 }
187