1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - SPI - demos - pm-1
3 File: main.c
4
5 Copyright 2003-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 $Log: main.c,v $
14 Revision 1.23 2006/01/18 02:11:29 kitase_hirotake
15 do-indent
16
17 $NoKeywords: $
18 *---------------------------------------------------------------------------*/
19 #include <nitro.h>
20 #include "font.h"
21 #include "screen.h"
22
23 //---- For battery display
24 char *myBatteryStr[] = { "HI", "LO", "--" };
25 #define MY_BATTERY_HI 0
26 #define MY_BATTERY_LO 1
27 #define MY_BATTERY_UNKNOWN 2
28
29 //---- For LCD switch (next status)
30 #define MY_LCD_KEEP 0 // No change
31 #define MY_LCD_OFF 1
32 #define MY_LCD_ON 2
33
34 static int myLCDNext = MY_LCD_KEEP;
35
36 //---- For power save
37 #define MY_POWER_SAVE_PERIOD 3000 // Milliseconds
38
39 //---- For battery check
40 #define MY_BATTERY_CHECK_INTERVAL 10 // Frame
41
42 static int myBatteryStatus = MY_BATTERY_UNKNOWN;
43 static u32 myBatteryCount;
44
45 //---- For RTC
46 static RTCTime myCurrentTime;
47 static int myResult;
48
49 //---- Alarm
50 static OSAlarm myAlarm;
51
52 //---- Message
53 #define MY_MESSAGE_SIZE 4
54
55 static OSMessage myMessageBuffer[MY_MESSAGE_SIZE];
56 static OSMessageQueue myMessageQueue;
57
58 //---- V-Count
59 static u32 myVCount;
60
61 //---- Sleep reason
62 #define MY_SLEEP_BY_CLOSE_COVER 0
63 #define MY_SLEEP_BY_PUSH_START 1
64 #define MY_SLEEP_BY_PUSH_LEFT 2
65 static u32 mySleepReason;
66
67 static void myInit(void);
68 static void myVBlankIntr(void);
69 static void myAlarmHandler(void *arg);
70
71 void myPreCallback(void *arg);
72 void myPostCallback(void *arg);
73 PMSleepCallbackInfo myPreCallbackInfo;
74 PMSleepCallbackInfo myPostCallbackInfo;
75
76 #ifdef SDK_TWL
77 //---- exit callback
78 PMExitCallbackInfo info;
79 void exitCallback(void*arg);
80 void batteryLowCallback(void*arg);
81 #endif
82
83 /*---------------------------------------------------------------------------*
84 Name: NitroMain
85
86 Description: Main.
87
88 Arguments: None.
89
90 Returns: None.
91 *---------------------------------------------------------------------------*/
NitroMain(void)92 void NitroMain(void)
93 {
94 u16 preButton;
95 u16 button;
96 u16 trigger;
97
98 //---------------- Initialize
99 #ifdef SDK_TWL
100 if ( OS_IsRunOnTwl() )
101 {
102 PM_SetAutoExit( TRUE );
103 }
104 #endif
105 myInit();
106 RTC_Init();
107
108 #ifdef SDK_TWL
109 if ( OS_IsRunOnTwl() )
110 {
111 OS_Printf("[ARM9] set exit callback\n");
112 PM_SetExitCallbackInfo( &info, exitCallback, (void*)100 );
113 PM_AppendPreExitCallback( &info );
114
115 PM_SetBatteryLowCallback( batteryLowCallback, NULL );
116 }
117 #endif
118
119 OS_InitMessageQueue(&myMessageQueue, &myMessageBuffer[0], MY_MESSAGE_SIZE);
120 OS_CreateAlarm(&myAlarm);
121
122 preButton = PAD_Read(); // Dummy read for pressing 'A' on IPL
123
124 //---- set SleepMode callbacks
125 PM_SetSleepCallbackInfo(&myPreCallbackInfo, myPreCallback, (void *)&mySleepReason);
126 PM_SetSleepCallbackInfo(&myPostCallbackInfo, myPostCallback, NULL);
127 PM_AppendPreSleepCallback(&myPreCallbackInfo);
128 PM_AppendPostSleepCallback(&myPostCallbackInfo);
129
130 //---------------- Main loop
131 while (TRUE)
132 {
133 button = PAD_Read();
134 trigger = (u16)((button ^ preButton) & button);
135 preButton = button;
136
137 //---- V-Blank count
138 myVCount = OS_GetVBlankCount();
139
140 //---- Clear screen buffer
141 ClearScreen();
142
143 //---- Display key description
144 PrintString(3, 2, 15, "START : sleep till push");
145 PrintString(3, 3, 15, " SELECT");
146 PrintString(3, 4, 15, "A : top back light");
147 PrintString(3, 5, 15, "B : bottom back light");
148 #ifdef SDK_TWL
149 if ( OS_IsRunOnTwl() )
150 {
151 PrintString(3, 6, 15, "X : do hardware reset");
152 }
153 #endif
154 PrintString(3, 7, 15, "UP : power save till push");
155 PrintString(3, 8, 15, " DOWN or pass 3 secs");
156 PrintString(3, 9, 15, "LEFT : sleep till next min");
157 PrintString(3, 10, 15, " by RTC or push RIGHT");
158 PrintString(3, 12, 15, "CLOSE : sleep till open");
159 PrintString(3, 13, 15, "L & R : power off");
160
161 //---- Display time
162 myResult = RTC_GetTime(&myCurrentTime);
163 if (myResult == 0 /*No error */ )
164 {
165 PrintString(5, 20, 8, "%02d:%02d:%02d",
166 myCurrentTime.hour, myCurrentTime.minute, myCurrentTime.second);
167 }
168
169 //---- Display battery status
170 if (myBatteryCount < myVCount || myBatteryStatus == MY_BATTERY_UNKNOWN)
171 {
172 PMBattery battery;
173 u32 result = PM_GetBattery(&battery);
174
175 if ( result == PM_RESULT_SUCCESS )
176 {
177 myBatteryStatus = (battery == PM_BATTERY_HIGH) ? MY_BATTERY_HI : MY_BATTERY_LO;
178 }
179 else
180 {
181 OS_Printf("battery level busy\n");
182 myBatteryStatus = MY_BATTERY_UNKNOWN;
183 }
184
185 myBatteryCount = myVCount + MY_BATTERY_CHECK_INTERVAL;
186 }
187 {
188 PMBatteryLevel level;
189 if ( PM_GetBatteryLevel( &level ) == PM_RESULT_SUCCESS )
190 {
191 PrintString(3, 16, 15, "Battery status : %s val:%d", myBatteryStr[myBatteryStatus], level );
192 }
193 else
194 {
195 PrintString(3, 16, 15, "Battery status : %s val:-", myBatteryStr[myBatteryStatus] );
196 }
197 }
198
199 //---- Display AC adapter
200 {
201 BOOL isConnected;
202
203 if ( PM_GetACAdapter( &isConnected ) == PM_RESULT_SUCCESS )
204 {
205 PrintString(3, 17, 15, "AC Adapter : %s", isConnected? "PLUGGED": "NOT PLUGGED" );
206 }
207 else
208 {
209 PrintString(3, 17, 15, "AC Adapter : -" );
210 }
211 }
212
213 //---- Display counter
214 PrintString(18, 20, 4, "%08X", myVCount);
215
216 //---- Display LED pattern
217 {
218 PMLEDPattern pattern;
219 if ( PM_GetLEDPattern(&pattern) == PM_RESULT_SUCCESS )
220 {
221 PrintString(3, 18, 15, "LED Pattern : %d", pattern);
222 }
223 else
224 {
225 PrintString(3, 18, 15, "LED Pattern : -");
226 }
227 }
228
229 //---- Push START to sleep
230 if (trigger & PAD_BUTTON_START)
231 {
232 mySleepReason = MY_SLEEP_BY_PUSH_START;
233 PM_GoSleepMode(PM_TRIGGER_KEY, PM_PAD_LOGIC_AND, PAD_BUTTON_SELECT);
234 }
235
236 //---- Push A to switch top backlight on/off
237 if (trigger & PAD_BUTTON_A)
238 {
239 static int cnt = 0;
240 switch (cnt % 2)
241 {
242 case 0:
243 if ( PM_SetBackLight(PM_LCD_TOP, PM_BACKLIGHT_OFF) == PM_RESULT_SUCCESS )
244 {
245 cnt++;
246 }
247 break;
248 case 1:
249 if ( PM_SetBackLight(PM_LCD_TOP, PM_BACKLIGHT_ON) == PM_RESULT_SUCCESS )
250 {
251 cnt++;
252 }
253 break;
254 }
255 }
256
257 //---- Push B to switch top backlight on/off
258 if (trigger & PAD_BUTTON_B)
259 {
260 static int cnt = 0;
261 switch (cnt % 2)
262 {
263 case 0:
264 if ( PM_SetBackLight(PM_LCD_BOTTOM, PM_BACKLIGHT_OFF) == PM_RESULT_SUCCESS )
265 {
266 cnt++;
267 }
268 break;
269 case 1:
270 if ( PM_SetBackLight(PM_LCD_BOTTOM, PM_BACKLIGHT_ON) == PM_RESULT_SUCCESS )
271 {
272 cnt++;
273 }
274 break;
275 }
276 }
277
278 #ifdef SDK_TWL
279 if ( OS_IsRunOnTwl() )
280 {
281 //---- Push X to do hardware reset
282 if (trigger & PAD_BUTTON_X)
283 {
284 (void)OS_RebootSystem();
285 // Do not call PM_ForceToResetHardware directly
286 }
287
288 //---- Push Y to change wireless LED
289 if (trigger & PAD_BUTTON_Y)
290 {
291 static PMWirelessLEDStatus sw = PM_WIRELESS_LED_OFF;
292
293 if ( PMi_SetWirelessLED(sw) == PM_RESULT_SUCCESS )
294 {
295 sw = (sw == PM_WIRELESS_LED_OFF)? PM_WIRELESS_LED_ON: PM_WIRELESS_LED_OFF;
296 }
297 }
298 }
299 #endif
300
301 //---- Push UP for power save mode
302 if (trigger & PAD_KEY_UP && PM_GetLCDPower() == PM_LCD_POWER_ON && myLCDNext == MY_LCD_KEEP)
303 {
304 //---- Set 3-second alarm
305 OS_CancelAlarm(&myAlarm);
306 OS_SetAlarm(&myAlarm, OS_MilliSecondsToTicks(MY_POWER_SAVE_PERIOD), myAlarmHandler,
307 NULL);
308
309 //---- Turn LCD off
310 myLCDNext = MY_LCD_OFF;
311 }
312
313 //---- Push LEFT to sleep till next minute
314 if (trigger & PAD_KEY_LEFT)
315 {
316 RTCAlarmStatus st = RTC_ALARM_STATUS_ON;
317 RTCAlarmParam p;
318
319 p.week = RTC_WEEK_SUNDAY; // Dummy
320 p.hour = 1; // Dummy
321 p.minute = (myCurrentTime.minute == 59) ? 0 : (myCurrentTime.minute + 1);
322 p.enable = RTC_ALARM_ENABLE_MINUTE;
323
324 myResult = RTC_SetAlarmStatus(RTC_ALARM_CHAN_1, &st);
325 myResult = RTC_SetAlarmParam(RTC_ALARM_CHAN_1, &p);
326
327 mySleepReason = MY_SLEEP_BY_PUSH_LEFT;
328 PM_GoSleepMode(PM_TRIGGER_KEY | PM_TRIGGER_RTC_ALARM, PM_PAD_LOGIC_AND, PAD_KEY_RIGHT);
329 }
330
331 //---- Push DOWN to return from power save mode
332 if (trigger & PAD_KEY_DOWN && PM_GetLCDPower() == PM_LCD_POWER_OFF
333 && myLCDNext == MY_LCD_KEEP)
334 {
335 //---- Turn LCD on
336 myLCDNext = MY_LCD_ON;
337 OS_CancelAlarm(&myAlarm);
338 }
339
340 //---- Close cover to sleep
341 if (PAD_DetectFold() == TRUE)
342 {
343 myLCDNext = MY_LCD_KEEP;
344 mySleepReason = MY_SLEEP_BY_CLOSE_COVER;
345 PM_GoSleepMode(PM_TRIGGER_COVER_OPEN | PM_TRIGGER_CARD, 0, 0);
346 }
347
348 //---- Push L & R to power off
349 if ((button & (PAD_BUTTON_L | PAD_BUTTON_R)) == (PAD_BUTTON_L | PAD_BUTTON_R))
350 {
351 (void)PM_ForceToPowerOff();
352 }
353
354 //---- Switch LCD power
355 if (myLCDNext != MY_LCD_KEEP)
356 {
357 if (myLCDNext == MY_LCD_OFF)
358 {
359 OS_WaitVBlankIntr();
360 GX_DispOff();
361 GXS_DispOff();
362 OS_WaitVBlankIntr();
363 if (PM_SetLCDPower(PM_LCD_POWER_OFF))
364 {
365 myLCDNext = MY_LCD_KEEP;
366 }
367 }
368 else if (myLCDNext == MY_LCD_ON)
369 {
370 if (PM_SetLCDPower(PM_LCD_POWER_ON))
371 {
372 OS_WaitVBlankIntr();
373 GX_DispOn();
374 GXS_DispOn();
375 OS_WaitVBlankIntr();
376 myLCDNext = MY_LCD_KEEP;
377 }
378 }
379 }
380
381 OS_WaitVBlankIntr();
382 }
383 }
384
385 //----------------------------------------------------------------
386 // myInit
387 //
myInit(void)388 void myInit(void)
389 {
390 //---- Init
391 OS_Init();
392 OS_InitTick();
393 OS_InitAlarm();
394 FX_Init();
395 GX_Init();
396 GX_DispOff();
397 GXS_DispOff();
398
399 //---- Display init
400 GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
401 MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
402 (void)GX_DisableBankForLCDC();
403
404 MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);
405 MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
406 MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);
407 MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
408
409 //---- Setting 2D for top screen
410 GX_SetBankForBG(GX_VRAM_BG_128_A);
411
412 G2_SetBG0Control(GX_BG_SCRSIZE_TEXT_256x256,
413 GX_BG_COLORMODE_16,
414 GX_BG_SCRBASE_0xf800, GX_BG_CHARBASE_0x00000, GX_BG_EXTPLTT_01);
415 G2_SetBG0Priority(0);
416 G2_BG0Mosaic(FALSE);
417 GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_2D);
418 GX_SetVisiblePlane(GX_PLANEMASK_BG0);
419
420 GX_LoadBG0Char(d_CharData, 0, sizeof(d_CharData));
421 GX_LoadBGPltt(d_PaletteData, 0, sizeof(d_PaletteData));
422
423
424
425 //---- Setting 2D for bottom screen
426 GX_SetBankForSubBG(GX_VRAM_SUB_BG_128_C);
427
428 G2S_SetBG0Control(GX_BG_SCRSIZE_TEXT_256x256,
429 GX_BG_COLORMODE_16,
430 GX_BG_SCRBASE_0xf800, GX_BG_CHARBASE_0x00000, GX_BG_EXTPLTT_01);
431 G2S_SetBG0Priority(0);
432 G2S_BG0Mosaic(FALSE);
433 GXS_SetGraphicsMode(GX_BGMODE_0);
434 GXS_SetVisiblePlane(GX_PLANEMASK_BG0);
435
436 GXS_LoadBG0Char(d_CharData, 0, sizeof(d_CharData));
437 GXS_LoadBGPltt(d_PaletteData, 0, sizeof(d_PaletteData));
438
439
440 //---- Screen
441 MI_CpuFillFast((void *)gScreen, 0, sizeof(gScreen));
442 DC_FlushRange(gScreen, sizeof(gScreen));
443 /* I/O register is accessed using DMA operation, so cache wait is not needed */
444 // DC_WaitWriteBufferEmpty();
445 GX_LoadBG0Scr(gScreen, 0, sizeof(gScreen));
446 GXS_LoadBG0Scr(gScreen, 0, sizeof(gScreen));
447
448 //---- Init interrupt
449 OS_SetIrqFunction(OS_IE_V_BLANK, myVBlankIntr);
450 (void)OS_EnableIrqMask(OS_IE_V_BLANK);
451 (void)GX_VBlankIntr(TRUE);
452 (void)OS_EnableIrq();
453 (void)OS_EnableInterrupts();
454
455 //---- FileSytem init
456 FS_Init(FS_DMA_NOT_USE);
457
458 //---- Start displaying
459 GX_DispOn();
460 GXS_DispOn();
461 }
462
463 //----------------------------------------------------------------
464 // myVBlankIntr
465 // V-Blank interrupt handler
466 //
myVBlankIntr(void)467 static void myVBlankIntr(void)
468 {
469 //---- Upload pseudo screen to VRAM
470 DC_FlushRange(gScreen, sizeof(gScreen));
471 /* I/O register is accessed using DMA operation, so cache wait is not needed */
472 // DC_WaitWriteBufferEmpty();
473 GX_LoadBG0Scr(gScreen, 0, sizeof(gScreen));
474 GXS_LoadBG0Scr(gScreen, 0, sizeof(gScreen));
475
476 OS_SetIrqCheckFlag(OS_IE_V_BLANK);
477 }
478
479 //----------------------------------------------------------------
480 // myAlarmHandler
481 // Alarm interrupt handler
482 //
myAlarmHandler(void * arg)483 void myAlarmHandler(void *arg)
484 {
485 #pragma unused(arg)
486 if (PM_GetLCDPower() == PM_LCD_POWER_OFF && myLCDNext == MY_LCD_KEEP)
487 {
488 myLCDNext = MY_LCD_ON;
489 }
490 }
491
492 //================================================================
493 //----------------------------------------------------------------
494 // myPreCallback
495 //
496 static const char *myCallbackReasonStr[] = {
497 "closing cover",
498 "pushing START",
499 "pushing LEFT"
500 };
501
myPreCallback(void * arg)502 void myPreCallback(void *arg)
503 {
504 int reason = *(int *)arg;
505 OS_Printf("Go to sleep mode by %s\n", myCallbackReasonStr[reason]);
506 }
507
508 //----------------------------------------------------------------
509 // myPostCallback
510 //
myPostCallback(void * arg)511 void myPostCallback(void *arg)
512 {
513 #pragma unused(arg)
514 OS_Printf("Return from sleep mode.\n");
515 }
516
517 #ifdef SDK_TWL
518 //----------------------------------------------------------------
519 // exitCallback
520 //
exitCallback(void * arg)521 void exitCallback(void *arg)
522 {
523 #ifdef SDK_FINALROM
524 #pragma unused( arg )
525 #endif
526 OS_Printf("exit callback. arg=%d factor=%d\n", arg, PM_GetExitFactor() );
527 }
528
529 //----------------------------------------------------------------
530 // batteryLowCallback
531 //
batteryLowCallback(void * arg)532 void batteryLowCallback(void *arg)
533 {
534 #ifdef SDK_FINALROM
535 #pragma unused( arg )
536 #endif
537 OS_Printf("battery low callback. arg=%d\n", arg);
538 }
539 #endif
540