1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - demos.TWL - SPI - pm-2
3   File:     main.c
4 
5   Copyright 2008-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:: 2008-11-13#$
14   $Rev: 0 $
15   $Author: yada $
16  *---------------------------------------------------------------------------*/
17 #include  <nitro.h>
18 #include  "font.h"
19 #include  "screen.h"
20 
21 #define EXIT_COUNT 0xA0
22 
23 //---- For RTC
24 static RTCTime myCurrentTime;
25 
26 //---- VCount
27 static u32 myVCount;
28 
29 //---- Auto exit flag
30 static BOOL isAutoExit = FALSE;
31 
32 //---- Exit callback info
33 static PMExitCallbackInfo exitCallbackInfo;
34 
35 //---- Whether exit callback was called
36 static BOOL isExit = FALSE;
37 
38 //---- Exit delay counter
39 static int  exitCounter;
40 
41 static void myInit(void);
42 static void myVBlankIntr(void);
43 static void myExitCallback(void *arg);
44 
45 /*---------------------------------------------------------------------------*
46   Name:         NitroMain
47 
48   Description:  Main.
49 
50   Arguments:    None.
51 
52   Returns:      None.
53  *---------------------------------------------------------------------------*/
NitroMain(void)54 void NitroMain(void)
55 {
56     u16     preButton;
57     u16     button;
58     u16     trigger;
59 
60     //---------------- Initialize
61     myInit();
62     RTC_Init();
63 
64     if ( OS_IsRunOnTwl() )
65     {
66         PM_SetAutoExit( isAutoExit );
67     }
68     else
69     {
70         OS_Printf("\nThis demo is only for TWL mode.");
71         OS_Exit(0);
72     }
73 
74     OS_Printf("[ARM9] set exit callback\n");
75     PM_SetExitCallbackInfo( &exitCallbackInfo, myExitCallback, (void*)100 );
76     PM_AppendPreExitCallback( &exitCallbackInfo );
77 
78     preButton = PAD_Read();            // Dummy read for pressing 'A' on IPL
79 
80     //---------------- Main loop
81     while (TRUE)
82     {
83         button = PAD_Read();
84         trigger = (u16)((button ^ preButton) & button);
85         preButton = button;
86 
87         //---- V-Blank count
88         myVCount = OS_GetVBlankCount();
89 
90         //---- Counter
91         if ( isExit )
92         {
93             if ( -- exitCounter < 0 )
94             {
95                 PM_ReadyToExit();
96             }
97         }
98 
99         //---- Clear screen buffer
100         ClearScreen();
101 
102         //---- Display key description
103         PrintString(3, 4, 15, "A : toggle Auto Exit mode");
104         PrintString(3, 6, 15, "X : do hardware reset");
105 
106         //---- Display time
107         if (RTC_GetTime(&myCurrentTime) == 0 /*no error */ )
108         {
109             PrintString(5, 20, 8, "%02d:%02d:%02d", myCurrentTime.hour, myCurrentTime.minute, myCurrentTime.second);
110         }
111 
112         //---- Display AutoExit mode
113         {
114             BOOL a = PM_GetAutoExit();
115             PrintString(8, 16, 15, "AUTO EXIT : %s", a? "TRUE": "FALSE" );
116         }
117 
118         //---- Display v-counter
119         PrintString(18, 20, 4, "%08X", myVCount);
120 
121         //---- Display count
122         if ( isExit )
123         {
124             static int blinkCount = 0;
125             if ( (++ blinkCount) & 0x4 )
126             {
127                 PrintString(12, 12, 1, "NOW EXIT...");
128             }
129             PrintString(15, 10, 4, "%X", exitCounter / 0x10);
130         }
131 
132         //---- Push A to switch top backlight on/off
133         if (trigger & PAD_BUTTON_A)
134         {
135             isAutoExit = (isAutoExit == FALSE);
136             PM_SetAutoExit( isAutoExit );
137         }
138 
139         //---- Push X to do hardware reset
140         if (trigger & PAD_BUTTON_X)
141         {
142             (void)OS_RebootSystem();
143             // Do not call the PM_ForceToResetHardware function directly
144         }
145 
146         OS_WaitVBlankIntr();
147     }
148 }
149 
150 //----------------------------------------------------------------
151 //  myInit
152 //
myInit(void)153 void myInit(void)
154 {
155     //---- Init
156     OS_Init();
157     OS_InitTick();
158     OS_InitAlarm();
159     FX_Init();
160     GX_Init();
161     GX_DispOff();
162     GXS_DispOff();
163 
164     //---- Display init
165     GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
166     MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
167     (void)GX_DisableBankForLCDC();
168 
169     MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);
170     MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
171     MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);
172     MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
173 
174     //---- Setting 2D for top screen
175     GX_SetBankForBG(GX_VRAM_BG_128_A);
176 
177     G2_SetBG0Control(GX_BG_SCRSIZE_TEXT_256x256,
178                      GX_BG_COLORMODE_16,
179                      GX_BG_SCRBASE_0xf800, GX_BG_CHARBASE_0x00000, GX_BG_EXTPLTT_01);
180     G2_SetBG0Priority(0);
181     G2_BG0Mosaic(FALSE);
182     GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_2D);
183     GX_SetVisiblePlane(GX_PLANEMASK_BG0);
184 
185     GX_LoadBG0Char(d_CharData, 0, sizeof(d_CharData));
186     GX_LoadBGPltt(d_PaletteData, 0, sizeof(d_PaletteData));
187 
188 
189 
190     //---- Setting 2D for bottom screen
191     GX_SetBankForSubBG(GX_VRAM_SUB_BG_128_C);
192 
193     G2S_SetBG0Control(GX_BG_SCRSIZE_TEXT_256x256,
194                       GX_BG_COLORMODE_16,
195                       GX_BG_SCRBASE_0xf800, GX_BG_CHARBASE_0x00000, GX_BG_EXTPLTT_01);
196     G2S_SetBG0Priority(0);
197     G2S_BG0Mosaic(FALSE);
198     GXS_SetGraphicsMode(GX_BGMODE_0);
199     GXS_SetVisiblePlane(GX_PLANEMASK_BG0);
200 
201     GXS_LoadBG0Char(d_CharData, 0, sizeof(d_CharData));
202     GXS_LoadBGPltt(d_PaletteData, 0, sizeof(d_PaletteData));
203 
204 
205     //---- Screen
206     MI_CpuFillFast((void *)gScreen, 0, sizeof(gScreen));
207     DC_FlushRange(gScreen, sizeof(gScreen));
208     /* I/O register is accessed using DMA operation, so cache wait is not needed */
209     // DC_WaitWriteBufferEmpty();
210     GX_LoadBG0Scr(gScreen, 0, sizeof(gScreen));
211     GXS_LoadBG0Scr(gScreen, 0, sizeof(gScreen));
212 
213     //---- Init interrupt
214     OS_SetIrqFunction(OS_IE_V_BLANK, myVBlankIntr);
215     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
216     (void)GX_VBlankIntr(TRUE);
217     (void)OS_EnableIrq();
218     (void)OS_EnableInterrupts();
219 
220     //---- FileSytem init
221     FS_Init(FS_DMA_NOT_USE);
222 
223     //---- Start displaying
224     GX_DispOn();
225     GXS_DispOn();
226 }
227 
228 //----------------------------------------------------------------
229 //  myVBlankIntr
230 //             V-Blank interrupt handler
231 //
myVBlankIntr(void)232 static void myVBlankIntr(void)
233 {
234     //---- Upload pseudo screen to VRAM
235     DC_FlushRange(gScreen, sizeof(gScreen));
236     /* I/O register is accessed using DMA operation, so cache wait is not needed */
237     // DC_WaitWriteBufferEmpty();
238     GX_LoadBG0Scr(gScreen, 0, sizeof(gScreen));
239     GXS_LoadBG0Scr(gScreen, 0, sizeof(gScreen));
240 
241     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
242 }
243 
244 //================================================================
245 //----------------------------------------------------------------
246 //  myExitCallback
247 //
myExitCallback(void * arg)248 void myExitCallback(void *arg)
249 {
250 #ifdef SDK_FINALROM
251 #pragma unused( arg )
252 #endif
253     OS_Printf("exit callback. arg=%d factor=%d\n", arg, PM_GetExitFactor() );
254 
255     exitCounter = EXIT_COUNT;
256     isExit = TRUE;
257 }
258