1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - RTC - demos - rtc-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 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17 /*---------------------------------------------------------------------------*
18 NOTICE: This sample includes functionality that confirms the operation of the RTC alarm. As of 2004/10/06, it may not work properly with versions of the IS-NITRO-DEBUGGER software older than 1.11.
19
20
21 Specifically, alarms are not triggered in situations where they should be triggered.
22 This is due to a conflict between the Nintendo DS system and the IS-NITRO-EMULATOR hardware; this problem does not occur on the production prototype of the machine.
23
24
25 *---------------------------------------------------------------------------*/
26
27 #ifdef SDK_TWL
28 #include <twl.h>
29 #include <twl/rtc.h>
30 #else
31 #include <nitro.h>
32 #include <nitro/rtc.h>
33 #endif
34
35 #include "font.h"
36
37
38 /*---------------------------------------------------------------------------*
39 Constant Definitions
40 *---------------------------------------------------------------------------*/
41 #define KEY_REPEAT_START 25 // Number of frames until key repeat starts
42 #define KEY_REPEAT_SPAN 10 // Number of frames between key repeats
43
44
45 /*---------------------------------------------------------------------------*
46 Character string constant definitions
47 *---------------------------------------------------------------------------*/
48 // Day of the week
49 const char *StrWeek[7] = {
50 "Sunday",
51 "Monday",
52 "Tuesday",
53 "Wednesday",
54 "Thursday",
55 "Friday",
56 "Saturday"
57 };
58
59 // Alarm status
60 const char *StrAlarmStatus[2] = {
61 "OFF",
62 "ON"
63 };
64
65 // Alarm enable flag
66 const char *StrAlarmEnable[8] = {
67 "- - -", // No enabled flag
68 "W - -", // Week setting enabled
69 "- H -", // Hour setting enabled
70 "W H -", // Week, hour setting enabled
71 "- - M", // Minute setting enabled
72 "W - M", // Week, minute setting enabled
73 "- H M", // Hour, minute setting enabled
74 "W H M" // Week, hour, minute setting enabled
75 };
76
77
78 /*---------------------------------------------------------------------------*
79 Structure Definitions
80 *---------------------------------------------------------------------------*/
81 // Key input data
82 typedef struct KeyInformation
83 {
84 u16 cnt; // Unprocessed input value
85 u16 trg; // Push trigger input
86 u16 up; // Release trigger input
87 u16 rep; // Press and hold repeat input
88
89 }
90 KeyInformation;
91
92 // Edit mode
93 typedef enum EditMode
94 {
95 EDIT_MODE_NONE = 0, // No edit mode
96 EDIT_MODE_DATE_TIME, // Date and time edit mode
97 EDIT_MODE_ALARM_1, // Alarm 1 status and setting value edit mode
98 EDIT_MODE_ALARM_2, // Alarm 2 status and setting value edit mode
99 EDIT_MODE_MAX
100 }
101 EditMode;
102
103
104 /*---------------------------------------------------------------------------*
105 Internal Function Definitions
106 *---------------------------------------------------------------------------*/
107 static void VBlankIntr(void);
108 static void AlarmIntrCallback(void);
109
110 static void IncValue(void);
111 static void DecValue(void);
112 static void IncSelect(void);
113 static void DecSelect(void);
114
115 static void KeyRead(KeyInformation * pKey);
116 static void ClearString(void);
117 static void PrintString(s16 x, s16 y, u8 palette, char *text, ...);
118 static void ColorString(s16 x, s16 y, s16 length, u8 palette);
119
120
121 /*---------------------------------------------------------------------------*
122 Internal Variable Definitions
123 *---------------------------------------------------------------------------*/
124 static u16 gScreen[32 * 32]; // Virtual screen
125 static KeyInformation gKey; // Key input
126
127 static RTCDate gRtcDate; // Date
128 static RTCTime gRtcTime; // Time
129 static RTCAlarmStatus gRtcAlarmStatus1; // Alarm 1 status
130 static RTCAlarmParam gRtcAlarmParam1; // Alarm 1 setting value
131 static RTCAlarmStatus gRtcAlarmStatus2; // Alarm 2 status
132 static RTCAlarmParam gRtcAlarmParam2; // Alarm 2 setting value
133
134 static EditMode gEditMode; // Edit mode
135 static u32 gSelect; // Selected place index
136 static s32 gMosaic; // Mosaic display counter
137
138
139 /*---------------------------------------------------------------------------*
140 Name: NitroMain
141
142 Description: Initialization and main loop.
143
144 Arguments: None.
145
146 Returns: None.
147 *---------------------------------------------------------------------------*/
NitroMain(void)148 void NitroMain(void)
149 {
150 // Various types of initialization
151 OS_Init();
152 FX_Init();
153 GX_Init();
154 GX_DispOff();
155 GXS_DispOff();
156
157 // Initializes display settings
158 GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
159 MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
160 (void)GX_DisableBankForLCDC();
161 MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);
162 MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
163 MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);
164 MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
165
166 // 2D display settings for text string display
167 GX_SetBankForBG(GX_VRAM_BG_128_A);
168 G2_SetBG0Control(GX_BG_SCRSIZE_TEXT_256x256, GX_BG_COLORMODE_16, GX_BG_SCRBASE_0xf800, // SCR base block 31
169 GX_BG_CHARBASE_0x00000, // CHR base block 0
170 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 GX_LoadBG0Char(d_CharData, 0, sizeof(d_CharData));
176 GX_LoadBGPltt(d_PaletteData, 0, sizeof(d_PaletteData));
177 MI_CpuFillFast((void *)gScreen, 0, sizeof(gScreen));
178 DC_FlushRange(gScreen, sizeof(gScreen));
179 /* I/O register is accessed using DMA operation, so cache wait is not needed */
180 // DC_WaitWriteBufferEmpty();
181 GX_LoadBG0Scr(gScreen, 0, sizeof(gScreen));
182
183 // Interrupt settings
184 OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
185 (void)OS_EnableIrqMask(OS_IE_V_BLANK);
186 (void)GX_VBlankIntr(TRUE);
187 (void)OS_EnableIrq();
188 (void)OS_EnableInterrupts();
189
190
191 //****************************************************************
192 // RTC initialization
193 RTC_Init();
194 // Set up jump destination vector for when the time alarm is generated
195 RTC_SetAlarmInterrupt(AlarmIntrCallback);
196 //****************************************************************
197
198 // Initialize internal variables
199 gEditMode = EDIT_MODE_NONE;
200 gSelect = 0;
201 gMosaic = 0;
202
203 // LCD display start
204 GX_DispOn();
205 GXS_DispOn();
206
207 // Debug string output
208 OS_Printf("ARM9: RTC demo started.\n");
209
210 // Empty call for getting key input data (strategy for pressing A button in the IPL)
211 KeyRead(&gKey);
212
213 // Main loop
214 while (TRUE)
215 {
216 // Get key input data
217 KeyRead(&gKey);
218
219 // Clear the screen
220 ClearString();
221
222 //****************************************************************
223 // Read current status from RTC
224 if (gEditMode != EDIT_MODE_DATE_TIME)
225 {
226 // Read date and time
227 (void)RTC_GetDateTime(&gRtcDate, &gRtcTime);
228 }
229 if (gEditMode != EDIT_MODE_ALARM_1)
230 {
231 // Read alarm 1 status
232 (void)RTC_GetAlarmStatus(RTC_ALARM_CHAN_1, &gRtcAlarmStatus1);
233 if (gRtcAlarmStatus1 == RTC_ALARM_STATUS_ON)
234 {
235 // Read setting value if alarm 1 is ON
236 (void)RTC_GetAlarmParam(RTC_ALARM_CHAN_1, &gRtcAlarmParam1);
237 }
238 }
239 if (gEditMode != EDIT_MODE_ALARM_2)
240 {
241 // Read alarm 2 status
242 (void)RTC_GetAlarmStatus(RTC_ALARM_CHAN_2, &gRtcAlarmStatus2);
243 if (gRtcAlarmStatus2 == RTC_ALARM_STATUS_ON)
244 {
245 // Read setting value if alarm 2 is ON
246 (void)RTC_GetAlarmParam(RTC_ALARM_CHAN_2, &gRtcAlarmParam2);
247 }
248 }
249 //****************************************************************
250
251 // Display date and time
252 PrintString(7, 3, 0xf, "%04d/%02d/%02d/%s",
253 gRtcDate.year + 2000, gRtcDate.month, gRtcDate.day, StrWeek[gRtcDate.week]);
254 PrintString(9, 5, 0xf, " %02d:%02d:%02d", gRtcTime.hour, gRtcTime.minute, gRtcTime.second);
255 // Change color of selected location if in date and time edit mode.
256 if (gEditMode == EDIT_MODE_DATE_TIME)
257 {
258 switch (gSelect)
259 {
260 case 0:
261 ColorString(7, 3, 4, 0x1);
262 break;
263 case 1:
264 ColorString(12, 3, 2, 0x1);
265 break;
266 case 2:
267 ColorString(15, 3, 2, 0x1);
268 break;
269 case 3:
270 ColorString(18, 3, 9, 0x1);
271 break;
272 case 4:
273 ColorString(10, 5, 2, 0x1);
274 break;
275 case 5:
276 ColorString(13, 5, 2, 0x1);
277 break;
278 case 6:
279 ColorString(16, 5, 2, 0x1);
280 break;
281 }
282 }
283
284 // Display alarm 1 status and setting value
285 PrintString(3, 8, 0x4, "ALARM-1 %s", StrAlarmStatus[gRtcAlarmStatus1]);
286 PrintString(4, 10, 0xf, "% 9s %02d:%02d %s",
287 StrWeek[gRtcAlarmParam1.week],
288 gRtcAlarmParam1.hour,
289 gRtcAlarmParam1.minute, StrAlarmEnable[gRtcAlarmParam1.enable]);
290 // Change color of selected location if in alarm 1 edit mode
291 if (gEditMode == EDIT_MODE_ALARM_1)
292 {
293 switch (gSelect)
294 {
295 case 0:
296 ColorString(11, 8, 6, 0x1);
297 break;
298 case 1:
299 ColorString(4, 10, 9, 0x1);
300 break;
301 case 2:
302 ColorString(15, 10, 2, 0x1);
303 break;
304 case 3:
305 ColorString(18, 10, 2, 0x1);
306 break;
307 case 4:
308 ColorString(22, 10, 5, 0x1);
309 break;
310 }
311 }
312
313 // Display alarm 2 status and setting value
314 PrintString(3, 12, 0x4, "ALARM-2 %s", StrAlarmStatus[gRtcAlarmStatus2]);
315 PrintString(4, 14, 0xf, "% 9s %02d:%02d %s",
316 StrWeek[gRtcAlarmParam2.week],
317 gRtcAlarmParam2.hour,
318 gRtcAlarmParam2.minute, StrAlarmEnable[gRtcAlarmParam2.enable]);
319 // Change color of selected location if in alarm 2 edit mode
320 if (gEditMode == EDIT_MODE_ALARM_2)
321 {
322 switch (gSelect)
323 {
324 case 0:
325 ColorString(11, 12, 6, 0x1);
326 break;
327 case 1:
328 ColorString(4, 14, 9, 0x1);
329 break;
330 case 2:
331 ColorString(15, 14, 2, 0x1);
332 break;
333 case 3:
334 ColorString(18, 14, 2, 0x1);
335 break;
336 case 4:
337 ColorString(22, 14, 5, 0x1);
338 break;
339 }
340 }
341
342 // Display explanation of button operations
343 if (gEditMode == EDIT_MODE_NONE)
344 {
345 PrintString(1, 19, 0x3, "DOWN > Change Date & Time.");
346 PrintString(1, 20, 0x3, "LEFT > Change Alarm1 Setting.");
347 PrintString(1, 21, 0x3, "RIGHT > Change Alarm2 Setting.");
348 }
349 else
350 {
351 PrintString(1, 18, 0x3, "UP > Increment value.");
352 PrintString(1, 19, 0x3, "DOWN > Decrement value.");
353 PrintString(1, 20, 0x3, "LEFT > Move selector left.");
354 PrintString(1, 21, 0x3, "RIGHT > Move selector right.");
355 PrintString(1, 22, 0x3, "A > Commit editing.");
356 PrintString(1, 23, 0x3, "B > Cancel editing.");
357 }
358
359 // Button input operation
360 if (gEditMode == EDIT_MODE_NONE)
361 {
362 // Down-arrow key
363 if ((gKey.trg | gKey.rep) & PAD_KEY_DOWN)
364 {
365 // Change to date and time edit mode
366 gSelect = 0;
367 gEditMode = EDIT_MODE_DATE_TIME;
368 }
369 // Left-arrow key
370 if ((gKey.trg | gKey.rep) & PAD_KEY_LEFT)
371 {
372 // Change to alarm 1 status and setting value edit mode
373 gSelect = 0;
374 gEditMode = EDIT_MODE_ALARM_1;
375 }
376 // Right-arrow key
377 if ((gKey.trg | gKey.rep) & PAD_KEY_RIGHT)
378 {
379 // Change to alarm 2 status and setting value edit mode
380 gSelect = 0;
381 gEditMode = EDIT_MODE_ALARM_2;
382 }
383 }
384 else // Edit mode common key operation
385 {
386 // Up-arrow key
387 if ((gKey.trg | gKey.rep) & PAD_KEY_UP)
388 {
389 IncValue();
390 }
391 // Down-arrow key
392 if ((gKey.trg | gKey.rep) & PAD_KEY_DOWN)
393 {
394 DecValue();
395 }
396 // Left-arrow key
397 if ((gKey.trg | gKey.rep) & PAD_KEY_LEFT)
398 {
399 DecSelect();
400 }
401 // Right-arrow key
402 if ((gKey.trg | gKey.rep) & PAD_KEY_RIGHT)
403 {
404 IncSelect();
405 }
406 // A button
407 if ((gKey.trg | gKey.rep) & PAD_BUTTON_A)
408 {
409 //****************************************************************
410 // Write changed variable in RTC
411 switch (gEditMode)
412 {
413 case EDIT_MODE_DATE_TIME:
414 // Write date and time
415 (void)RTC_SetDateTime(&gRtcDate, &gRtcTime);
416 break;
417 case EDIT_MODE_ALARM_1:
418 // Write alarm 1 status
419 (void)RTC_SetAlarmStatus(RTC_ALARM_CHAN_1, &gRtcAlarmStatus1);
420 if (gRtcAlarmStatus1 == RTC_ALARM_STATUS_ON)
421 {
422 // Write setting value if alarm 1 is ON
423 (void)RTC_SetAlarmParam(RTC_ALARM_CHAN_1, &gRtcAlarmParam1);
424 }
425 break;
426 case EDIT_MODE_ALARM_2:
427 // Write alarm 2 status
428 (void)RTC_SetAlarmStatus(RTC_ALARM_CHAN_2, &gRtcAlarmStatus2);
429 if (gRtcAlarmStatus2 == RTC_ALARM_STATUS_ON)
430 {
431 // Write setting value if alarm 2 is ON
432 (void)RTC_SetAlarmParam(RTC_ALARM_CHAN_2, &gRtcAlarmParam2);
433 }
434 break;
435 }
436 //****************************************************************
437
438 // Change to no edit mode
439 gEditMode = EDIT_MODE_NONE;
440 }
441 // B button
442 if ((gKey.trg | gKey.rep) & PAD_BUTTON_B)
443 {
444 // Change to no edit mode
445 gEditMode = EDIT_MODE_NONE;
446 }
447 }
448
449 // Waiting for the V-Blank
450 OS_WaitVBlankIntr();
451 }
452 }
453
454 /*---------------------------------------------------------------------------*
455 Name: VBlankIntr
456
457 Description: V-Blank interrupt vector.
458
459 Arguments: None.
460
461 Returns: None.
462 *---------------------------------------------------------------------------*/
VBlankIntr(void)463 static void VBlankIntr(void)
464 {
465 // Reflect virtual screen in VRAM
466 DC_FlushRange(gScreen, sizeof(gScreen));
467 /* I/O register is accessed using DMA operation, so cache wait is not needed */
468 // DC_WaitWriteBufferEmpty();
469 GX_LoadBG0Scr(gScreen, 0, sizeof(gScreen));
470
471 // Display mosaic according to mosaic display counter
472 if (gMosaic)
473 {
474 int w;
475 int i = 5;
476
477 w = gMosaic / 4 % (i * 2);
478 w = w - (w - ((w - i) * 2)) * (w / (i + 1));
479 gMosaic--;
480
481 G2_BG0Mosaic(TRUE);
482 G2_SetBGMosaicSize(w, w);
483 }
484 else
485 {
486 G2_BG0Mosaic(FALSE);
487 }
488
489 // Sets the IRQ check flag
490 OS_SetIrqCheckFlag(OS_IE_V_BLANK);
491 }
492
493 /*---------------------------------------------------------------------------*
494 Name: AlarmIntrCallback
495
496 Description: Interrupt vector when RTC alarm occurs
497
498 Arguments: None.
499
500 Returns: None.
501 *---------------------------------------------------------------------------*/
AlarmIntrCallback(void)502 static void AlarmIntrCallback(void)
503 {
504 // Debug string output
505 OS_Printf("ARM9: Alarm interrupt on %04d/%02d/%02d (%s) %02d:%02d:%02d .\n",
506 gRtcDate.year + 2000,
507 gRtcDate.month,
508 gRtcDate.day,
509 StrWeek[gRtcDate.week], gRtcTime.hour, gRtcTime.minute, gRtcTime.second);
510 // Start mosaic animation
511 gMosaic = 300;
512 }
513
514 /*---------------------------------------------------------------------------*
515 Name: IncValue
516
517 Description: Add 1 to selected value using edit mode.
518
519 Arguments: None.
520
521 Returns: None.
522 *---------------------------------------------------------------------------*/
IncValue(void)523 static void IncValue(void)
524 {
525 switch (gEditMode)
526 {
527
528 // Date and time edit mode
529 case EDIT_MODE_DATE_TIME:
530 {
531 RTCDate *d = &gRtcDate;
532 RTCTime *t = &gRtcTime;
533
534 switch (gSelect)
535 {
536 case 0:
537 d->year = (d->year + 1) % 100;
538 break;
539 case 1:
540 d->month = (d->month % 12) + 1;
541 break;
542 case 2:
543 d->day = (d->day % 31) + 1;
544 break;
545 case 3:
546 d->week = (RTCWeek)((d->week + 1) % RTC_WEEK_MAX);
547 break;
548 case 4:
549 t->hour = (t->hour + 1) % 24;
550 break;
551 case 5:
552 t->minute = (t->minute + 1) % 60;
553 break;
554 case 6:
555 t->second = (t->second + 1) % 60;
556 break;
557 }
558 }
559 break;
560
561 // Alarm 1 or 2 edit mode
562 case EDIT_MODE_ALARM_1:
563 case EDIT_MODE_ALARM_2:
564 {
565 RTCAlarmStatus *s;
566 RTCAlarmParam *p;
567
568 s = (gEditMode == EDIT_MODE_ALARM_1 ? &gRtcAlarmStatus1 : &gRtcAlarmStatus2);
569 p = (gEditMode == EDIT_MODE_ALARM_1 ? &gRtcAlarmParam1 : &gRtcAlarmParam2);
570
571 switch (gSelect)
572 {
573 case 0:
574 *s = (RTCAlarmStatus)((*s + 1) % RTC_ALARM_STATUS_MAX);
575 break;
576 case 1:
577 p->week = (RTCWeek)((p->week + 1) % RTC_WEEK_MAX);
578 break;
579 case 2:
580 p->hour = (p->hour + 1) % 24;
581 break;
582 case 3:
583 p->minute = (p->minute + 1) % 60;
584 break;
585 case 4:
586 p->enable = (p->enable + 1) % (RTC_ALARM_ENABLE_ALL + 1);
587 break;
588 }
589 }
590 break;
591
592 }
593 }
594
595 /*---------------------------------------------------------------------------*
596 Name: DecValue
597
598 Description: Subtract 1 from selected value using edit mode.
599
600 Arguments: None.
601
602 Returns: None.
603 *---------------------------------------------------------------------------*/
DecValue(void)604 static void DecValue(void)
605 {
606 switch (gEditMode)
607 {
608
609 // Date and time edit mode
610 case EDIT_MODE_DATE_TIME:
611 {
612 RTCDate *d = &gRtcDate;
613 RTCTime *t = &gRtcTime;
614
615 switch (gSelect)
616 {
617 case 0:
618 d->year = (d->year + 99) % 100;
619 break;
620 case 1:
621 d->month = ((d->month + 10) % 12) + 1;
622 break;
623 case 2:
624 d->day = ((d->day + 29) % 31) + 1;
625 break;
626 case 3:
627 d->week = (RTCWeek)((d->week + (RTC_WEEK_MAX - 1)) % RTC_WEEK_MAX);
628 break;
629 case 4:
630 t->hour = (t->hour + 23) % 24;
631 break;
632 case 5:
633 t->minute = (t->minute + 59) % 60;
634 break;
635 case 6:
636 t->second = (t->second + 59) % 60;
637 break;
638 }
639 }
640 break;
641
642 // Alarm 1 or 2 edit mode
643 case EDIT_MODE_ALARM_1:
644 case EDIT_MODE_ALARM_2:
645 {
646 RTCAlarmStatus *s;
647 RTCAlarmParam *p;
648
649 s = (gEditMode == EDIT_MODE_ALARM_1 ? &gRtcAlarmStatus1 : &gRtcAlarmStatus2);
650 p = (gEditMode == EDIT_MODE_ALARM_1 ? &gRtcAlarmParam1 : &gRtcAlarmParam2);
651
652 switch (gSelect)
653 {
654 case 0:
655 *s = (RTCAlarmStatus)((*s + (RTC_ALARM_STATUS_MAX - 1)) % RTC_ALARM_STATUS_MAX);
656 break;
657 case 1:
658 p->week = (RTCWeek)((p->week + (RTC_WEEK_MAX - 1)) % RTC_WEEK_MAX);
659 break;
660 case 2:
661 p->hour = (p->hour + 23) % 24;
662 break;
663 case 3:
664 p->minute = (p->minute + 59) % 60;
665 break;
666 case 4:
667 p->enable = (p->enable + RTC_ALARM_ENABLE_ALL) % (RTC_ALARM_ENABLE_ALL + 1);
668 break;
669 }
670 }
671 break;
672
673 }
674 }
675
676 /*---------------------------------------------------------------------------*
677 Name: IncSelect
678
679 Description: Add 1 to selection index using edit mode.
680
681 Arguments: None.
682
683 Returns: None.
684 *---------------------------------------------------------------------------*/
IncSelect(void)685 static void IncSelect(void)
686 {
687 switch (gEditMode)
688 {
689
690 // Date and time edit mode
691 case EDIT_MODE_DATE_TIME:
692 gSelect = (gSelect + 1) % 7;
693 break;
694
695 // Alarm 1 or 2 edit mode
696 case EDIT_MODE_ALARM_1:
697 case EDIT_MODE_ALARM_2:
698 gSelect = (gSelect + 1) % 5;
699 break;
700
701 }
702 }
703
704 /*---------------------------------------------------------------------------*
705 Name: DecSelect
706
707 Description: Subtract 1 from selection index by edit mode.
708
709 Arguments: None.
710
711 Returns: None.
712 *---------------------------------------------------------------------------*/
DecSelect(void)713 static void DecSelect(void)
714 {
715 switch (gEditMode)
716 {
717
718 // Date and time edit mode
719 case EDIT_MODE_DATE_TIME:
720 gSelect = (gSelect + 6) % 7;
721 break;
722
723 // Alarm 1 or 2 edit mode
724 case EDIT_MODE_ALARM_1:
725 case EDIT_MODE_ALARM_2:
726 gSelect = (gSelect + 4) % 5;
727 break;
728
729 }
730 }
731
732 /*---------------------------------------------------------------------------*
733 Name: KeyRead
734
735 Description: Edits key input data.
736 Detects press trigger, release trigger, and press-and-hold repeat.
737
738 Arguments: pKey: Structure that holds key input data to be edited
739
740 Returns: None.
741 *---------------------------------------------------------------------------*/
KeyRead(KeyInformation * pKey)742 static void KeyRead(KeyInformation * pKey)
743 {
744 static u16 repeat_count[12];
745 int i;
746 u16 r;
747
748 r = PAD_Read();
749 pKey->trg = 0x0000;
750 pKey->up = 0x0000;
751 pKey->rep = 0x0000;
752
753 for (i = 0; i < 12; i++)
754 {
755 if (r & (0x0001 << i))
756 {
757 if (!(pKey->cnt & (0x0001 << i)))
758 {
759 pKey->trg |= (0x0001 << i); // Press trigger
760 repeat_count[i] = 1;
761 }
762 else
763 {
764 if (repeat_count[i] > KEY_REPEAT_START)
765 {
766 pKey->rep |= (0x0001 << i); // Press-and-hold repeat
767 repeat_count[i] = KEY_REPEAT_START - KEY_REPEAT_SPAN;
768 }
769 else
770 {
771 repeat_count[i]++;
772 }
773 }
774 }
775 else
776 {
777 if (pKey->cnt & (0x0001 << i))
778 {
779 pKey->up |= (0x0001 << i); // Release trigger
780 }
781 }
782 }
783 pKey->cnt = r; // Unprocessed key input
784 }
785
786 /*---------------------------------------------------------------------------*
787 Name: ClearString
788
789 Description: Clears the virtual screen.
790
791 Arguments: None.
792
793 Returns: None.
794 *---------------------------------------------------------------------------*/
ClearString(void)795 static void ClearString(void)
796 {
797 MI_CpuClearFast((void *)gScreen, sizeof(gScreen));
798 }
799
800 /*---------------------------------------------------------------------------*
801 Name: PrintString
802
803 Description: Positions the text string on the virtual screen. The string can be up to 32 chars.
804
805 Arguments: x: X-oordinate where character string starts (x 8 dots)
806 y: Y-coordinate where character string starts (x 8 dots)
807 palette: Specify text color by palette number
808 text: Text string to position. NULL terminated
809 ...: Virtual argument
810
811 Returns: None.
812 *---------------------------------------------------------------------------*/
PrintString(s16 x,s16 y,u8 palette,char * text,...)813 static void PrintString(s16 x, s16 y, u8 palette, char *text, ...)
814 {
815 va_list vlist;
816 char temp[32 + 2];
817 s32 i;
818
819 va_start(vlist, text);
820 (void)vsnprintf(temp, 33, text, vlist);
821 va_end(vlist);
822
823 *(u16 *)(&temp[32]) = 0x0000;
824 for (i = 0;; i++)
825 {
826 if (temp[i] == 0x00)
827 {
828 break;
829 }
830 gScreen[((y * 32) + x + i) % (32 * 32)] = (u16)((palette << 12) | temp[i]);
831 }
832 }
833
834 /*---------------------------------------------------------------------------*
835 Name: ColorString
836
837 Description: Changes the color of character strings printed on the virtual screen.
838
839 Arguments: x: X-coordinate (x 8 dots ) from which to start color change
840 y: Y-coordinate (x 8 dots ) from which to start color change
841 length: Number of characters to continue the color change for
842 palette: Specify text color by palette number
843
844 Returns: None.
845 *---------------------------------------------------------------------------*/
ColorString(s16 x,s16 y,s16 length,u8 palette)846 static void ColorString(s16 x, s16 y, s16 length, u8 palette)
847 {
848 s32 i;
849 u16 temp;
850 s32 index;
851
852 if (length < 0)
853 return;
854
855 for (i = 0; i < length; i++)
856 {
857 index = ((y * 32) + x + i) % (32 * 32);
858 temp = gScreen[index];
859 temp &= 0x0fff;
860 temp |= (palette << 12);
861 gScreen[index] = temp;
862 }
863 }
864
865 /*---------------------------------------------------------------------------*
866 End of file
867 *---------------------------------------------------------------------------*/
868