1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - libraries - snd - common
3   File:     snd_alarm.c
4 
5   Copyright 2004-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-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 #include <nitro/snd/common/alarm.h>
19 
20 #include <nitro/pxi.h>
21 #include <nitro/snd/common/work.h>
22 
23 /******************************************************************************
24 	structure definition
25  ******************************************************************************/
26 
27 #ifdef SDK_ARM9
28 
29 typedef struct AlarmCallbackInfo
30 {
31     void    (*func) (void *);
32     void   *arg;
33     u8      id;
34     u8      pad;
35     u16     pad2;
36 }
37 AlarmCallbackInfo;
38 
39 #endif
40 
41 /******************************************************************************
42 	static variable
43  ******************************************************************************/
44 
45 #ifdef SDK_ARM9
46 
47 static AlarmCallbackInfo sCallbackTable[SND_ALARM_NUM];
48 
49 #endif
50 
51 /******************************************************************************
52 	static function declaration
53  ******************************************************************************/
54 
55 #ifdef SDK_ARM7
56 
57 static void AlarmHandler(void *arg);
58 
59 #endif
60 
61 /******************************************************************************
62 	public function
63  ******************************************************************************/
64 
65 #ifdef SDK_ARM9
66 
SND_AlarmInit(void)67 void SND_AlarmInit(void)
68 {
69     int     alarmNo;
70 
71     for (alarmNo = 0; alarmNo < SND_ALARM_NUM; alarmNo++)
72     {
73         AlarmCallbackInfo *info;
74 
75         info = &sCallbackTable[alarmNo];
76 
77         info->func = NULL;
78         info->arg = NULL;
79         info->id = 0;
80     }
81 }
82 
83 #else
84 
SND_AlarmInit(void)85 void SND_AlarmInit(void)
86 {
87     int     alarmNo;
88 
89     for (alarmNo = 0; alarmNo < SND_ALARM_NUM; alarmNo++)
90     {
91         SNDi_Work.alarm[alarmNo].enable = FALSE;
92         SNDi_Work.alarm[alarmNo].id = 0;
93     }
94 }
95 
SND_SetupAlarm(int alarmNo,OSTick tick,OSTick period,int id)96 void SND_SetupAlarm(int alarmNo, OSTick tick, OSTick period, int id)
97 {
98     SNDAlarm *alarm;
99 
100     SDK_MINMAX_ASSERT(alarmNo, SND_ALARM_MIN, SND_ALARM_MAX);
101     SDK_MINMAX_ASSERT(id, 0x00, 0xff);
102 
103     alarm = &SNDi_Work.alarm[alarmNo];
104 
105     if (alarm->enable)
106     {
107         OS_CancelAlarm(&alarm->alarm);
108         alarm->enable = FALSE;
109     }
110 
111     alarm->setting.tick = tick;
112     alarm->setting.period = period;
113     alarm->id = (u8)id;
114     alarm->count = 0;
115 }
116 
SND_StartAlarm(int alarmNo)117 void SND_StartAlarm(int alarmNo)
118 {
119     OSTick  tick;
120     OSTick  period;
121     SNDAlarm *alarm;
122     void   *arg;
123 
124     SDK_MINMAX_ASSERT(alarmNo, SND_ALARM_MIN, SND_ALARM_MAX);
125 
126     alarm = &SNDi_Work.alarm[alarmNo];
127 
128     if (alarm->enable)
129     {
130         OS_CancelAlarm(&alarm->alarm);
131         alarm->enable = FALSE;
132     }
133 
134     tick = alarm->setting.tick;
135     period = alarm->setting.period;
136     arg = (void *)((alarm->id << 8) | alarmNo);
137 
138     OS_CreateAlarm(&alarm->alarm);
139 
140     if (period == 0)
141     {
142         OS_SetAlarm(&alarm->alarm, tick, AlarmHandler, arg);
143     }
144     else
145     {
146         OS_SetPeriodicAlarm(&alarm->alarm, OS_GetTick() + tick, period, AlarmHandler, arg);
147     }
148 
149     alarm->enable = TRUE;
150 }
151 
SND_StopAlarm(int alarmNo)152 void SND_StopAlarm(int alarmNo)
153 {
154     SNDAlarm *alarm;
155 
156     SDK_MINMAX_ASSERT(alarmNo, SND_ALARM_MIN, SND_ALARM_MAX);
157 
158     alarm = &SNDi_Work.alarm[alarmNo];
159 
160     if (!alarm->enable)
161         return;
162 
163     OS_CancelAlarm(&alarm->alarm);
164 
165     alarm->id++;
166     alarm->enable = FALSE;
167 }
168 #endif
169 
170 /******************************************************************************
171 	static function
172  ******************************************************************************/
173 
174 #ifdef SDK_ARM7
175 
AlarmHandler(void * arg)176 static void AlarmHandler(void *arg)
177 {
178     u32 msg = (u32)arg;
179     u32 alarmNo = msg & 0xff;
180     u32 id = (msg >> 8) & 0xff;
181     SNDAlarm *alarm;
182 
183     SDK_MINMAX_ASSERT(alarmNo, SND_ALARM_MIN, SND_ALARM_MAX);
184 
185     alarm = &SNDi_Work.alarm[alarmNo];
186     if ( id != alarm->id ) {
187         return;
188     }
189 
190     if ( alarm->count < 0xff ) {
191         alarm->count++;
192     }
193 
194     while (alarm->count > 0)
195     {
196         if (PXI_SendWordByFifo(PXI_FIFO_TAG_SOUND, msg, FALSE) < 0) {
197             break;
198         }
199         alarm->count--;
200     }
201 }
202 
203 #endif
204 
205 /******************************************************************************
206 	private function
207  ******************************************************************************/
208 
209 #ifdef SDK_ARM9
210 
SNDi_IncAlarmId(int alarmNo)211 void SNDi_IncAlarmId(int alarmNo)
212 {
213     AlarmCallbackInfo *info;
214 
215     SDK_MINMAX_ASSERT(alarmNo, SND_ALARM_MIN, SND_ALARM_MAX);
216 
217     info = &sCallbackTable[alarmNo];
218 
219     info->id++;
220 }
221 
SNDi_SetAlarmHandler(int alarmNo,SNDAlarmHandler handler,void * arg)222 u8 SNDi_SetAlarmHandler(int alarmNo, SNDAlarmHandler handler, void *arg)
223 {
224     AlarmCallbackInfo *info;
225 
226     SDK_MINMAX_ASSERT(alarmNo, SND_ALARM_MIN, SND_ALARM_MAX);
227 
228     info = &sCallbackTable[alarmNo];
229 
230     info->func = handler;
231     info->arg = arg;
232     info->id++;
233 
234     return info->id;
235 }
236 
SNDi_CallAlarmHandler(int msg)237 void SNDi_CallAlarmHandler(int msg)
238 {
239     AlarmCallbackInfo *info;
240     int     alarmNo = msg & 0xff;
241     int     id = (msg >> 8) & 0xff;
242 
243     SDK_MINMAX_ASSERT(alarmNo, SND_ALARM_MIN, SND_ALARM_MAX);
244 
245     info = &sCallbackTable[alarmNo];
246 
247     if (id == info->id)
248     {
249         if (info->func != NULL)
250         {
251             info->func(info->arg);
252         }
253     }
254 }
255 
256 #endif
257 
258 /*====== End of snd_alarm.c ======*/
259