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