1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - MB - demos - multiboot
3   File:     main.c
4 
5   Copyright 2006-2008 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-03-02#$
14   $Rev: 10122 $
15   $Author: kitase_hirotake $
16  *---------------------------------------------------------------------------*/
17 
18 
19 #include <nitro.h>
20 #include <nitro/wm.h>
21 #include <nitro/mb.h>
22 
23 
24 #include "common.h"
25 #include "dispfunc.h"
26 
27 /*
28  * For BeaconPeriod randomization (rand)
29  */
30 #include <stdlib.h>
31 
32 /*
33  * A simple example of a multiboot parent
34  *
35  * Because the MB library samples use the multiboot functionality, multiple development units with the same communications environment (wired or wireless) are required
36  *
37  * The mb_child_NITRO.srl and mb_child_TWL.srl sample programs in the $TwlSDK/bin/ARM9-TS/Rom/ directory provide the same features as a multiboot child for final retail units. Load these binaries on other hardware as with any sample program, and run them together.
38  *
39  *
40  *
41  *
42  */
43 
44 
45 /*---------------------------------------------------------------------------*/
46 /* Functions */
47 
48 static void Menu(void);
49 
50 /* V-Blank interrupt process */
VBlankIntr(void)51 static void VBlankIntr(void)
52 {
53     //---- OAM updating
54     DC_FlushRange(oamBak, sizeof(oamBak));
55     /* I/O register is accessed using DMA operation, so cache wait is not needed */
56     // DC_WaitWriteBufferEmpty();
57     MI_DmaCopy32(3, oamBak, (void *)HW_OAM, sizeof(oamBak));
58 
59     //---- BG screen update
60     BgScrSetVblank();
61 
62     (void)rand();
63 
64     //---- Interrupt check flag
65     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
66 }
67 
68 /* Main */
NitroMain()69 void NitroMain()
70 {
71     /* OS initialization */
72     OS_Init();
73     OS_InitTick();
74     OS_InitAlarm();
75     FX_Init();
76 
77     /* GX initialization */
78     GX_Init();
79     GX_DispOff();
80     GXS_DispOff();
81 
82     {                                  /* Memory allocation initialization */
83         OSHeapHandle heapHandle;       // Heap handle
84         enum
85         { MAIN_HEAP_SIZE = 0x80000 };
86         void   *heapStart, *nstart;
87         nstart = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 16);
88         OS_SetMainArenaLo(nstart);
89         heapStart = OS_AllocFromMainArenaLo((u32)MAIN_HEAP_SIZE, 32);
90         heapHandle =
91             OS_CreateHeap(OS_ARENA_MAIN, heapStart, (void *)((u32)heapStart + MAIN_HEAP_SIZE));
92         if (heapHandle < 0)
93         {
94             OS_Panic("ARM9: Fail to create heap...\n");
95         }
96         heapHandle = OS_SetCurrentHeap(OS_ARENA_MAIN, heapHandle);
97     }
98 
99     (void)OS_EnableIrq();
100     (void)OS_EnableInterrupts();
101 
102     /* FS initialization */
103     FS_Init(FS_DMA_NOT_USE);
104     {
105         u32     need_size = FS_GetTableSize();
106         void   *p_table = OS_Alloc(need_size);
107         SDK_ASSERT(p_table != NULL);
108         (void)FS_LoadTable(p_table, need_size);
109     }
110 
111     {                                  /* Initialize drawing setting */
112         GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
113         MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
114         (void)GX_DisableBankForLCDC();
115         MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);
116         MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
117         MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);
118         MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
119         BgInitForPrintStr();
120         GX_SetBankForOBJ(GX_VRAM_OBJ_128_B);
121         GX_SetOBJVRamModeChar(GX_OBJVRAMMODE_CHAR_2D);
122         GX_SetVisiblePlane(GX_PLANEMASK_BG0 | GX_PLANEMASK_OBJ);
123         GXS_SetVisiblePlane(GX_PLANEMASK_BG0 | GX_PLANEMASK_OBJ);
124         GX_LoadOBJ(sampleCharData, 0, sizeof(sampleCharData));
125         GX_LoadOBJPltt(samplePlttData, 0, sizeof(samplePlttData));
126         MI_DmaFill32(3, oamBak, 0xc0, sizeof(oamBak));
127     }
128 
129     /* V-Blank interrupt configuration */
130     (void)OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
131     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
132     (void)OS_EnableIrqMask(OS_IE_FIFO_RECV);
133 
134     (void)GX_VBlankIntr(TRUE);
135 
136     // RTC initialization
137     RTC_Init();
138 
139     /* Start display */
140     GX_DispOn();
141     GXS_DispOn();
142     G2_SetBG0Offset(0, 0);
143     G2S_SetBG0Offset(0, 0);
144 
145     /* Initialization of the pointer to the file buffer */
146     InitFileBuffer();
147 
148     /* Main loop */
149     prog_state = STATE_MENU;
150     for (;;)
151     {
152         OS_WaitVBlankIntr();
153 
154         switch (prog_state)
155         {
156         case STATE_MENU:
157             Menu();
158             break;
159         case STATE_MB_PARENTINIT:
160             ParentInit();
161             break;
162         case STATE_MB_PARENT:
163             ParentMain();
164             break;
165         default:
166             break;
167         }
168     }
169 
170 }
171 
172 /*
173  * -------------------------------------------------------------
174  * Menu processing functions
175  * -------------------------------------------------------------
176  */
177 
178 enum
179 {
180     MENU_SENDSIZE,
181     MENU_MAX_CHILDREN,
182     MENU_AUTO_ACCEPT,
183     MENU_AUTO_SENDFILE,
184     MENU_AUTO_BOOTREQUEST,
185     MENU_NUM
186 };
187 
188 /* Send size table */
189 u16     sendsize_table[] = {
190     256, 384, 510,
191 };
192 
193 /* Work for the menu */
194 typedef struct
195 {
196     u8      item_no;
197     u8      size_index;
198     u8      channel;
199     u8      auto_accept_flag;
200     u8      auto_send_flag;
201     u8      auto_boot_flag;
202 }
203 MenuData;
204 
205 /* Menu */
Menu(void)206 static void Menu(void)
207 {
208     const u16 keyData = ReadKeySetTrigger(PAD_Read());
209     static MenuData menu;
210     enum
211     { DISP_OX = 5, DISP_OY = 5 };
212 
213     /* Change cursor number */
214     if (keyData & PAD_KEY_DOWN)
215     {
216         (void)RotateU8(&menu.item_no, 0, MENU_NUM - 1, 1);
217     }
218     else if (keyData & PAD_KEY_UP)
219     {
220         (void)RotateU8(&menu.item_no, 0, MENU_NUM - 1, -1);
221     }
222     else if (keyData & (PAD_BUTTON_A | PAD_BUTTON_START))
223     {
224         prog_state = STATE_MB_PARENTINIT;
225     }
226 
227     /* Start display */
228     BgClear();
229     BgPutString((s16)(DISP_OX + 3), (s16)(DISP_OY - 3), WHITE, "Multiboot Sample");
230 
231     BgPrintf((s16)(DISP_OX), (s16)(DISP_OY), WHITE,
232              "Send Size(Bytes)    [%3d]", GetParentSendSize());
233     BgPrintf((s16)(DISP_OX), (s16)(DISP_OY + 1), WHITE, "Children Entry Max  [%2d]", GetMaxEntry());
234     BgPrintf((s16)(DISP_OX), (s16)(DISP_OY + 2), WHITE,
235              "Auto Accept Entries %s", (menu.auto_accept_flag) ? "[Yes]" : "[No ]");
236     BgPrintf((s16)(DISP_OX), (s16)(DISP_OY + 3), WHITE,
237              "Auto Send Start     %s", (menu.auto_send_flag) ? "[Yes]" : "[No ]");
238     BgPrintf((s16)(DISP_OX), (s16)(DISP_OY + 4), WHITE,
239              "Auto Boot           %s", (menu.auto_boot_flag) ? "[Yes]" : "[No ]");
240     /* Cursor display */
241     BgPutChar((s16)(DISP_OX - 2), (s16)(DISP_OY + menu.item_no), RED, '*');
242     /* Wait for A button */
243     BgPutString(DISP_OX, DISP_OY + 14, WHITE, " Push A or START Button");
244 
245     switch (menu.item_no)
246     {
247         /* MP send size configuration */
248     case MENU_SENDSIZE:
249         if (keyData & PAD_KEY_RIGHT)
250         {
251             (void)RotateU8(&menu.size_index, 0, sizeof(sendsize_table) / sizeof(u16) - 1, 1);
252         }
253         else if (keyData & PAD_KEY_LEFT)
254         {
255             (void)RotateU8(&menu.size_index, 0, sizeof(sendsize_table) / sizeof(u16) - 1, -1);
256         }
257         SetParentSendSize(sendsize_table[menu.size_index]);
258         break;
259 
260         /* Set the maximum number of child connections */
261     case MENU_MAX_CHILDREN:
262         {
263             u8      entry = GetMaxEntry();
264             if (keyData & PAD_KEY_RIGHT)
265             {
266                 (void)RotateU8(&entry, 1, MB_MAX_CHILD, 1);
267             }
268             else if (keyData & PAD_KEY_LEFT)
269             {
270                 (void)RotateU8(&entry, 1, MB_MAX_CHILD, -1);
271             }
272             SetMaxEntry(entry);
273         }
274         break;
275 
276         /* AUTO ACCEPT configuration */
277     case MENU_AUTO_ACCEPT:
278         if (keyData & (PAD_KEY_RIGHT | PAD_KEY_LEFT))
279         {
280             menu.auto_accept_flag ^= 1;
281         }
282         break;
283 
284         /* AUTO SEND configuration */
285     case MENU_AUTO_SENDFILE:
286         if (keyData & (PAD_KEY_RIGHT | PAD_KEY_LEFT))
287         {
288             menu.auto_send_flag ^= 1;
289         }
290         break;
291 
292         /* AUTO BOOT configuration */
293     case MENU_AUTO_BOOTREQUEST:
294         if (keyData & (PAD_KEY_RIGHT | PAD_KEY_LEFT))
295         {
296             menu.auto_boot_flag ^= 1;
297         }
298         break;
299     default:
300         break;
301     }
302 
303     SetAutoOperation(menu.auto_accept_flag, menu.auto_send_flag, menu.auto_boot_flag);
304 
305 }
306