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