1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - WXC - demos - wxc-dataShare
3   File:     main.c
4 
5   Copyright 2005-2009 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   $Date:: 2009-08-31#$
14   $Rev: 11030 $
15   $Author: tominaga_masafumi $
16  *---------------------------------------------------------------------------*/
17 
18 /*
19  * This demo uses the WH library for wireless communications, but does not perform wireless shutdown processing.
20  *
21  * For details on WH library wireless shutdown processing, see the comments at the top of the WH library source code or the wm/dataShare-Model demo.
22  *
23  *
24  */
25 
26 #include <nitro.h>
27 
28 #include <nitro/wxc.h>
29 
30 #include "user.h"
31 #include "common.h"
32 #include "disp.h"
33 #include "gmain.h"
34 #include "wh.h"
35 
36 void VBlankIntr(void);          // V-Blank interrupt handler
37 
38 /*---------------------------------------------------------------------------*
39     Constant definitions
40  *---------------------------------------------------------------------------*/
41 #define     KEY_REPEAT_START    25     // Number of frames until key repeat starts
42 #define     KEY_REPEAT_SPAN     10     // Number of frames between key repeats
43 
44 #define     PICTURE_FRAME_PER_GAME_FRAME    2
45 
46 
47 /* GGID used for testing */
48 #define SDK_MAKEGGID_SYSTEM(num)              (0x003FFF00 | (num))
49 #define GGID_ORG_1                            SDK_MAKEGGID_SYSTEM(0x52)
50 
51 /* GGID used for this Sharing */
52 #define WH_GGID                 SDK_MAKEGGID_SYSTEM(0x21)
53 
54 /*---------------------------------------------------------------------------*
55     Structure definitions
56  *---------------------------------------------------------------------------*/
57 // Key input data
58 typedef struct KeyInfo
59 {
60     u16     cnt;                       // Unprocessed input value
61     u16     trg;                       // Push trigger input
62     u16     up;                        // Release trigger input
63     u16     rep;                       // Press and hold repeat input
64 
65 }
66 KeyInfo;
67 
68 
69 /*---------------------------------------------------------------------------*
70     Internal Function Definitions
71  *---------------------------------------------------------------------------*/
72 static void ModeSelect(void);          // Parent/child select screen
73 static void ModeError(void);           // Error display screen
74 
75 
76 // General purpose subroutines
77 static void KeyRead(KeyInfo * pKey);
78 static void InitializeAllocateSystem(void);
79 
80 static void GetMacAddress(u8 * macAddr, u16 * gScreen);
81 
82 
83 static void ModeConnect();
84 static void ModeWorking(void);
85 
86 /*---------------------------------------------------------------------------*
87     Internal Variable Definitions
88  *---------------------------------------------------------------------------*/
89 static KeyInfo gKey;                   // Key input
90 static vs32 gPictureFrame;             // Picture frame counter
91 
92 
93 /*---------------------------------------------------------------------------*
94     External Variable Definitions
95  *---------------------------------------------------------------------------*/
96 int passby_endflg;
97 WMBssDesc bssdesc;
98 WMParentParam parentparam;
99 u8 macAddress[6];
100 
101 
102 static void WaitPressButton(void);
103 static void GetChannelMain(void);
104 static BOOL ConnectMain(u16 tgid);
105 static void PrintChildState(void);
106 static BOOL JudgeConnectableChild(WMStartParentCallback *cb);
107 
108 
109 //============================================================================
110 //   Variable Definitions
111 //============================================================================
112 
113 static s32 gFrame;                     // Frame counter
114 
115 //============================================================================
116 //   Function definitions
117 //============================================================================
118 
119 /*---------------------------------------------------------------------------*
120   Name:         VBlankIntr
121 
122   Description:  Gets key trigger
123 
124   Arguments:    None.
125 
126   Returns:      None.
127  *---------------------------------------------------------------------------*/
VBlankIntr(void)128 void VBlankIntr(void)
129 {
130     // Increment picture frame counter
131     gPictureFrame++;
132 
133     // Repeat rendering to match game frame
134     if (!(gPictureFrame % PICTURE_FRAME_PER_GAME_FRAME))
135     {
136         DispVBlankFunc();
137     }
138 
139     //---- Interrupt check flag
140     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
141 }
142 
143 /*---------------------------------------------------------------------------*
144   Name:         NitroMain
145 
146   Description:  Main routine
147 
148   Arguments:    None.
149 
150   Returns:      None.
151  *---------------------------------------------------------------------------*/
NitroMain(void)152 void NitroMain(void)
153 {
154     u16 tgid = 0;
155 
156     // Initialize screen and OS
157     CommonInit();
158     // Initialize screen
159     DispInit();
160     // Initialize the heap
161     InitAllocateSystem();
162 
163     // Enable interrupts
164     (void)OS_EnableIrq();
165     (void)OS_EnableInterrupts();
166 
167     OS_InitTick();
168     FX_Init();
169 
170     DispOn();
171 
172     passby_endflg = 0;
173 
174     /* Initializes, registers, and runs chance encounter communications */
175     User_Init();
176 
177     for (gFrame = 0; passby_endflg == 0; gFrame++)
178     {
179         /* Get key input data */
180         KeyRead(&gKey);
181 
182         // Clear the screen
183         BgClear();
184 
185         /* Distributes processes based on communication status */
186         switch (WXC_GetStateCode())
187         {
188         case WXC_STATE_END:
189             ModeSelect();
190             break;
191         case WXC_STATE_ENDING:
192             break;
193         case WXC_STATE_ACTIVE:
194             if(WXC_IsParentMode() == TRUE)
195             {
196                 BgPutString(9, 2, 0x2, "Now parent...");
197             }
198             else
199             {
200                 BgPutString(9, 2, 0x2, "Now child...");
201             }
202             break;
203         }
204         if (gKey.trg & PAD_BUTTON_START)
205         {
206             (void)WXC_End();
207         }
208 
209         // Waiting for the V-Blank
210         OS_WaitVBlankIntr();
211     }
212 
213     (void)WXC_End();
214 
215     // Wait for WXC_End to complete
216     while( WXC_GetStateCode() != WXC_STATE_END )
217     {
218         ;
219     }
220 
221     // Variable initialization
222     gPictureFrame = 0;
223 
224     // Set buffer for data sharing communication
225     GInitDataShare();
226 
227     // Initialize wireless
228     if( WH_Initialize() == FALSE )
229     {
230         OS_Printf("\n WH_Initialize() ERROR!!\n");
231     }
232 
233     if(passby_endflg == 1)
234     {
235         WH_SetGgid(WH_GGID);
236 
237         // Set the function to determine connected children
238         WH_SetJudgeAcceptFunc(JudgeConnectableChild);
239 
240         /* Main routine */
241         for (gFrame = 0; TRUE; gFrame++)
242         {
243             BgClear();
244 
245             switch (WH_GetSystemState())
246             {
247             case WH_SYSSTATE_IDLE:
248                 (void)WH_ParentConnect(WH_CONNECTMODE_DS_PARENT, (u16)(parentparam.tgid+1), parentparam.channel);
249                 break;
250 
251             case WH_SYSSTATE_CONNECTED:
252             case WH_SYSSTATE_KEYSHARING:
253             case WH_SYSSTATE_DATASHARING:
254                 {
255                     BgPutString(8, 1, 0x2, "Parent mode");
256                     if(GStepDataShare(gPictureFrame) == FALSE)
257                     {
258                         gPictureFrame--;
259                     }
260                     GMain();
261                 }
262                 break;
263             }
264 
265             // Wait for completion of multiple cycles of picture frames
266             while (TRUE)
267             {
268                 // Wait for V-Blank
269                 OS_WaitVBlankIntr();
270                 if (!(gPictureFrame % PICTURE_FRAME_PER_GAME_FRAME))
271                 {
272                     break;
273                 }
274             }
275         }
276     }
277     else
278     {
279         OS_Printf("\nmacAddress = %02X:%02X:%02X:%02X:%02X:%02X\n", bssdesc.bssid[0],bssdesc.bssid[1],bssdesc.bssid[2],bssdesc.bssid[3],bssdesc.bssid[4],bssdesc.bssid[5]);
280 
281         bssdesc.gameInfo.tgid++;
282 
283         // Main loop
284         for (gFrame = 0; TRUE; gFrame++)
285         {
286             // Clear the screen
287             BgClear();
288 
289             // Distributes processes based on communication status
290             switch (WH_GetSystemState())
291             {
292             case WH_SYSSTATE_CONNECT_FAIL:
293                 {
294                     // Because the internal WM state is invalid if the WM_StartConnect function fails, WM_Reset must be called once to reset the state to IDLE
295                     //
296                     WH_Reset();
297                 }
298                 break;
299             case WH_SYSSTATE_IDLE:
300                 {
301                     static retry = 0;
302                     enum
303                     {
304                         MAX_RETRY = 30
305                     };
306 
307                     if (retry < MAX_RETRY)
308                     {
309                         ModeConnect(bssdesc.bssid);
310                         retry++;
311                         break;
312                     }
313                     // If connection to parent is not possible after MAX_RETRY, display ERROR
314                 }
315             case WH_SYSSTATE_ERROR:
316                 ModeError();
317                 break;
318             case WH_SYSSTATE_BUSY:
319             case WH_SYSSTATE_SCANNING:
320                 ModeWorking();
321                 break;
322 
323             case WH_SYSSTATE_CONNECTED:
324             case WH_SYSSTATE_KEYSHARING:
325             case WH_SYSSTATE_DATASHARING:
326                 {
327                     BgPutString(8, 1, 0x2, "Child mode");
328                     if(GStepDataShare(gPictureFrame) == FALSE)
329                     {
330                         gPictureFrame--;
331                     }
332                     GMain();
333                 }
334                 break;
335             }
336 
337             // Display of signal strength
338             {
339                 int level;
340                 level = WH_GetLinkLevel();
341                 BgPrintStr(31, 23, 0xf, "%d", level);
342             }
343 
344             // Wait for completion of multiple cycles of picture frames
345             while (TRUE)
346             {
347                 // Wait for V-Blank
348                 OS_WaitVBlankIntr();
349                 if (!(gPictureFrame % PICTURE_FRAME_PER_GAME_FRAME))
350                 {
351                     break;
352                 }
353             }
354         }
355     }
356 }
357 
358 
359 /*---------------------------------------------------------------------------*
360   Name:         ModeSelect
361 
362   Description:  Processing in parent/child selection screen.
363 
364   Arguments:    None.
365 
366   Returns:      None.
367  *---------------------------------------------------------------------------*/
ModeSelect(void)368 static void ModeSelect(void)
369 {
370     BgPutString(3, 1, 0x2, "Push A to start");
371 
372     if (gKey.trg & PAD_BUTTON_A)
373     {
374         //********************************
375         User_Init();
376         //********************************
377     }
378 }
379 
380 /*---------------------------------------------------------------------------*
381   Name:         ModeError
382 
383   Description:  Processing in error display screen.
384 
385   Arguments:    None.
386 
387   Returns:      None.
388  *---------------------------------------------------------------------------*/
ModeError(void)389 static void ModeError(void)
390 {
391     BgPutString(5, 10, 0x2, "======= ERROR! =======");
392     BgPutString(5, 13, 0x2, " Fatal error occured.");
393     BgPutString(5, 14, 0x2, "Please reboot program.");
394 }
395 
396 
397 /*---------------------------------------------------------------------------*
398   Name:         KeyRead
399 
400   Description:  Edits key input data
401                 Detects press trigger, release trigger, and press-and-hold repeat.
402 
403   Arguments:    pKey: Structure that holds key input data to be edited
404 
405   Returns:      None.
406  *---------------------------------------------------------------------------*/
KeyRead(KeyInfo * pKey)407 static void KeyRead(KeyInfo * pKey)
408 {
409     static u16 repeat_count[12];
410     int     i;
411     u16     r;
412 
413     r = PAD_Read();
414     pKey->trg = 0x0000;
415     pKey->up = 0x0000;
416     pKey->rep = 0x0000;
417 
418     for (i = 0; i < 12; i++)
419     {
420         if (r & (0x0001 << i))
421         {
422             if (!(pKey->cnt & (0x0001 << i)))
423             {
424                 pKey->trg |= (0x0001 << i);     // Press trigger
425                 repeat_count[i] = 1;
426             }
427             else
428             {
429                 if (repeat_count[i] > KEY_REPEAT_START)
430                 {
431                     pKey->rep |= (0x0001 << i); // Press-and-hold repeat
432                     repeat_count[i] = KEY_REPEAT_START - KEY_REPEAT_SPAN;
433                 }
434                 else
435                 {
436                     repeat_count[i]++;
437                 }
438             }
439         }
440         else
441         {
442             if (pKey->cnt & (0x0001 << i))
443             {
444                 pKey->up |= (0x0001 << i);      // Release trigger
445             }
446         }
447     }
448     pKey->cnt = r;                     // Unprocessed key input
449 }
450 
451 /*---------------------------------------------------------------------------*
452   Name:         JudgeConnectableChild
453 
454   Description:  Determines if the child is connectable during reconnect.
455 
456   Arguments:    cb: Information for the child attempting to connect
457 
458   Returns:      If connection is accepted, TRUE.
459                 If not accepted, FALSE.
460  *---------------------------------------------------------------------------*/
JudgeConnectableChild(WMStartParentCallback * cb)461 static BOOL JudgeConnectableChild(WMStartParentCallback *cb)
462 {
463     if (cb->macAddress[0] != macAddress[0] || cb->macAddress[1] != macAddress[1] ||
464         cb->macAddress[2] != macAddress[2] || cb->macAddress[3] != macAddress[3] ||
465         cb->macAddress[4] != macAddress[4] || cb->macAddress[5] != macAddress[5] )
466     {
467         return FALSE;
468     }
469 
470     return TRUE;
471 }
472 
473 /*---------------------------------------------------------------------------*
474   Name:         ModeConnect
475 
476   Description:  Connection start
477 
478   Arguments:    None.
479 
480   Returns:      None.
481  *---------------------------------------------------------------------------*/
ModeConnect()482 static void ModeConnect()
483 {
484     WH_SetGgid(WH_GGID);
485     //********************************
486     (void)WH_ChildConnectAuto(WH_CONNECTMODE_DS_CHILD, bssdesc.bssid,
487                               bssdesc.channel);
488     //********************************
489 }
490 
491 /*---------------------------------------------------------------------------*
492   Name:         ModeWorking
493 
494   Description:  Displays working screen
495 
496   Arguments:    None.
497 
498   Returns:      None.
499  *---------------------------------------------------------------------------*/
ModeWorking(void)500 static void ModeWorking(void)
501 {
502     BgPrintStr(9, 11, 0xf, "Now working...");
503 }
504