1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - demos - math - qsort
3   File:     main.c
4 
5   Copyright 2007-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:: 2008-09-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 #include    <nitro.h>
19 
20 /*---------------------------------------------------------------------------*
21     Prototype definitions
22  *---------------------------------------------------------------------------*/
23 static void VBlankIntr(void);
24 static void KeyInit(void);
25 static void KeyRead(void);
26 
27 
28 // Key States
29 static struct
30 {
31     u16     con;
32     u16     trg;
33 }
34 keys;
35 
36 #define DATA_NUM    1024
37 
38 /*---------------------------------------------------------------------------*
39     Static variable definitions
40  *---------------------------------------------------------------------------*/
41 static u32 gDataArray[DATA_NUM];
42 static u8 *gSortBuf;
43 
44 
45 /*---------------------------------------------------------------------------*
46   Name:         KeyInit
47 
48   Description:  Initialize Pad Keys.
49 
50   Arguments:    None.
51 
52   Returns:      None.
53  *---------------------------------------------------------------------------*/
KeyInit(void)54 static void KeyInit(void)
55 {
56 
57     keys.trg = 0;
58     keys.con = 0;
59 
60 }
61 
62 /*---------------------------------------------------------------------------*
63   Name:         KeyRead
64 
65   Description:  Read Pad Keys.
66 
67   Arguments:    None.
68 
69   Returns:      None.
70  *---------------------------------------------------------------------------*/
KeyRead(void)71 static void KeyRead(void)
72 {
73     u16     r = PAD_Read();
74 
75     keys.trg = (u16)(~keys.con & r);
76     keys.con = r;
77 }
78 
79 
80 /*---------------------------------------------------------------------------*
81   Name:         InitializeAllocateSystem
82 
83   Description:  Initializes the memory allocation system within the main memory arena.
84 
85   Arguments:    None.
86 
87   Returns:      None.
88  *---------------------------------------------------------------------------*/
InitializeAllocateSystem(void)89 static void InitializeAllocateSystem(void)
90 {
91     void   *tempLo;
92     OSHeapHandle hh;
93 
94     // Based on the premise that OS_Init has been already called
95     tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
96     OS_SetArenaLo(OS_ARENA_MAIN, tempLo);
97     hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
98     if (hh < 0)
99     {
100         OS_Panic("ARM9: Fail to create heap...\n");
101     }
102     hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
103 }
104 
105 
106 
107 /*---------------------------------------------------------------------------*
108   Name:         DisplayInit
109 
110   Description:  Graphics Initialization
111 
112   Arguments:    None.
113 
114   Returns:      None.
115  *---------------------------------------------------------------------------*/
DisplayInit()116 static void DisplayInit()
117 {
118 
119     GX_Init();
120     FX_Init();
121 
122     GX_DispOff();
123     GXS_DispOff();
124 
125     GX_SetDispSelect(GX_DISP_SELECT_SUB_MAIN);
126 
127     OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
128     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
129     (void)GX_VBlankIntr(TRUE);         // To generate V-Blank interrupt request
130     (void)OS_EnableIrq();
131 
132 
133     GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
134     MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
135 
136     MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);   // Clear OAM
137     MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);     // Clear the standard palette
138 
139     MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);     // Clear OAM
140     MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);       // Clear the standard palette
141     MI_DmaFill32(3, (void *)HW_LCDC_VRAM_C, 0x7FFF7FFF, 256 * 192 * sizeof(u16));
142 
143 
144     GX_SetBankForOBJ(GX_VRAM_OBJ_256_AB);       // Set VRAM-A,B for OBJ
145 
146     GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS,    // 2D / 3D Mode
147                        GX_BGMODE_0,    // BGMODE 0
148                        GX_BG0_AS_2D);  // Set BG0 as 2D
149 
150     GX_SetVisiblePlane(GX_PLANEMASK_OBJ);       // Make OBJs visible
151     GX_SetOBJVRamModeBmp(GX_OBJVRAMMODE_BMP_1D_128K);   // 2D mapping OBJ
152 
153     OS_WaitVBlankIntr();               // Waiting for the end of the V-Blank interrupt
154     GX_DispOn();
155 
156 }
157 
158 
159 
160 
161 
162 
163 
164 /* User data comparison function */
compare(void * elem1,void * elem2)165 static s32 compare(void *elem1, void *elem2)
166 {
167     // To ensure there is no overflow into the sign bit, promote to s64 and then compare.
168     s64     diff = (s64)*(u32 *)elem1 - (s64)*(u32 *)elem2;
169     // Normalize only the large-small ordering to {+1,0,-1}, and return it.
170     return (diff > 0) ? +1 : ((diff < 0) ? -1 : 0);
171 }
172 
173 /* Function for debug output of array data */
PrintArray(u32 * array,u32 size)174 static void PrintArray(u32 *array, u32 size)
175 {
176 #pragma unused( array )
177     u32     i;
178 
179     for (i = 0; i < size; i++)
180     {
181         if ((i & 0x7) == 0)
182         {
183             OS_TPrintf("\n");
184         }
185         OS_TPrintf("%08lx,", array[i]);
186     }
187     OS_TPrintf("\n");
188 }
189 
190 
191 /*---------------------------------------------------------------------------*
192   Name:         NitroMain
193 
194   Description:  Initialization and main loop
195 
196   Arguments:    None.
197 
198   Returns:      None.
199  *---------------------------------------------------------------------------*/
NitroMain(void)200 void NitroMain(void)
201 {
202     MATHRandContext32 context;
203 
204     // Initialization
205     KeyInit();
206     OS_Init();
207     TP_Init();
208     OS_InitTick();
209 
210     // Memory allocation
211     InitializeAllocateSystem();
212 
213     DisplayInit();
214 
215     // Empty call for getting key input data (strategy for pressing A Button in the IPL)
216     KeyRead();
217     // Bury data with random numbers
218     MATH_InitRand32(&context, 0);
219 
220     OS_TPrintf("Press A Button to start MATH_QSort() test\n");
221 
222     while (TRUE)
223     {
224         static u32 cnt = 0;
225         static OSTick sum = 0;
226 
227         KeyRead();
228 
229         if ((keys.trg & PAD_BUTTON_A) != 0)
230         {
231             u32     i;
232 
233             {
234                 for (i = 0; i < DATA_NUM; i++)
235                 {
236                     gDataArray[i] = MATH_Rand32(&context, 0);
237                 }
238             }
239             {
240                 OSTick  before, after;
241 
242                 // Quick sort
243                 gSortBuf = (u8 *)OS_Alloc(MATH_QSortStackSize(DATA_NUM));
244 
245                 before = OS_GetTick();
246                 MATH_QSort(gDataArray, DATA_NUM, sizeof(u32), compare, NULL);
247                 after = OS_GetTick();
248                 OS_Free(gSortBuf);
249 
250                 // * Verify it is correctly sorted in ascending order
251                 for (i = 0; i < DATA_NUM; i++)
252                 {
253                     u32 lower = gDataArray[MATH_MAX(i - 1, 0)];
254                     u32 upper = gDataArray[i];
255                     if (lower > upper)
256                     {
257                         OS_TPanic("result array is not sorted correctly!");
258                     }
259                 }
260 
261                 // Print and display sort results
262                 PrintArray(gDataArray, DATA_NUM);
263                 cnt++;
264                 sum += OS_TicksToMicroSeconds(after - before);
265 
266                 OS_TPrintf("time = %lld us (avg %lld us)\n", OS_TicksToMicroSeconds(after - before),
267                            sum / cnt);
268                 OS_TPrintf("Press A Button to start MATH_QSort() test again\n");
269             }
270         }
271         // Wait for V-Blank interrupt
272         OS_WaitVBlankIntr();
273     }
274 }
275 
276 
277 /*---------------------------------------------------------------------------*
278   Name:         VBlankIntr
279 
280   Description:  V-Blank function
281 
282   Arguments:    None.
283 
284   Returns:      None.
285  *---------------------------------------------------------------------------*/
VBlankIntr(void)286 static void VBlankIntr(void)
287 {
288 
289     // Set IRQ check flag
290     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
291 }
292 
293 
294 
295 /*---------------------------------------------------------------------------*
296   End of file
297  *---------------------------------------------------------------------------*/
298