20#define TIMER_MODE_START 0x00000001
21#define TIMER_MODE_HANDLER 0x00000002
32 timer_alarm_handler_t callback_handler;
34 void *callback_handler_arg;
40 vu64 timer_handled_count;
42 vu32 timer_counter_total;
43 vu32 timer_counter_used;
44 counter_struct_t *timer_counter_buf_free;
45 counter_struct_t *timer_counter_buf_alarm;
46 vs32 current_handling_timer_id;
49#define PTR_TO_TIMER_ID(ptr_) ((s32)((((uiptr)(ptr_)) << 4) | ((ptr_)->timer_key)))
50#define TIMER_ID_TO_PTR(id_) ((counter_struct_t *)((((uiptr)(id_)) >> 10) << 6))
51#define TIMER_ID_IS_VALID(id_) ((TIMER_ID_TO_PTR(id_) != NULL) && ((siptr)(id_) >= 0) && (((uiptr)(id_) & 0x3FF) == ((TIMER_ID_TO_PTR(id_))->timer_key)))
54extern void ForTimer_InitAlarm(
void);
56extern void SetT2(
volatile void *ptr, u32 val);
57extern void SetT2_COUNT(u32 val);
58extern void SetT2_MODE(u32 val);
59extern void SetT2_COMP(u32 val);
60extern void InsertAlarm_ForTimer(counter_struct_t *timer_link);
61extern counter_struct_t *UnlinkAlarm_ForTimer(counter_struct_t *timer_unlink);
62extern s32 TimerHandler_callback(s32 cause,
void *arg,
void *addr);
64#define COUNTER_COUNT 128
68 .timer_handled_count = 0,
70 .timer_counter_total = 1,
71 .timer_counter_used = 0,
72 .timer_counter_buf_free = NULL,
73 .timer_counter_buf_alarm = NULL,
74 .current_handling_timer_id = -1,
83void SetT2(
volatile void *ptr, u32 val)
86 *((
volatile u32 *)ptr) = val;
92void SetT2_COUNT(u32 val)
94 SetT2((
volatile void *)K_T2_COUNT, val);
99void SetT2_MODE(u32 val)
101 SetT2((
volatile void *)K_T2_MODE, val);
106void SetT2_COMP(u32 val)
108 SetT2((
volatile void *)K_T2_COMP, val);
119 if (g_Timer.intc_handler >= 0)
123 g_Timer.timer_handled_count = 0;
124 g_Timer.timer_counter_used = 0;
125 memset(g_CounterBuf, 0,
sizeof(g_CounterBuf));
126 g_Timer.timer_counter_buf_free = &g_CounterBuf[0];
127 for (u32 i = 0; i < ((
sizeof(g_CounterBuf) /
sizeof(g_CounterBuf[0])) - 1); i += 1)
129 g_CounterBuf[i].timer_next = &g_CounterBuf[i + 1];
131 g_CounterBuf[(
sizeof(g_CounterBuf) /
sizeof(g_CounterBuf[0])) - 1].timer_next = NULL;
132 ForTimer_InitAlarm();
133 handler = AddIntcHandler2(INTC_TIM2, TimerHandler_callback, 0, NULL);
138 g_Timer.intc_handler = handler;
140 mode = ((*T2_MODE) & (~0x3)) | in_mode;
141 mode |= (1 << 9) | (1 << 8);
142 if ((mode & (1 << 7)) == 0)
145 mode |= (1 << 11) | (1 << 10);
150 EnableIntc(INTC_TIM2);
164 if (g_Timer.intc_handler < 0)
168 if (g_Timer.timer_counter_used != 0)
173 if (RemoveIntcHandler(INTC_TIM2, g_Timer.intc_handler) == 0)
175 DisableIntc(INTC_TIM2);
176 SetT2_MODE((1 << 11) | (1 << 10));
179 g_Timer.timer_handled_count = 0;
180 g_Timer.intc_handler = -1;
189#ifdef F_GetTimerPreScaleFactor
190s32 GetTimerPreScaleFactor(
void)
192 if (g_Timer.intc_handler < 0)
196 return (*T2_MODE) & 3;
200#ifdef F_StartTimerSystemTime
212 if (((*T2_MODE) & (1 << 7)) != 0)
222 SetT2_MODE(((*T2_MODE) & (~((1 << 11) | (1 << 10)))) | (1 << 7));
223 SetNextComp(iGetTimerSystemTime());
233#ifdef F_StopTimerSystemTime
245 if (((*T2_MODE) & (1 << 7)) != 0)
247 SetT2_MODE((*T2_MODE) & (~((1 << 11) | (1 << 10))));
266void SetNextComp(u64 time_now)
269 counter_struct_t *timer_current;
271 if (g_Timer.current_handling_timer_id >= 0)
275 timer_current = g_Timer.timer_counter_buf_alarm;
276 if (timer_current == NULL)
279 SetT2_MODE((*T2_MODE) & (~(1 << 11)));
282 a0 = timer_current->timer_schedule + timer_current->timer_base_time - timer_current->timer_base_count;
283 timer_current = timer_current->timer_next;
284 while (timer_current != NULL)
286 a1 = timer_current->timer_schedule + timer_current->timer_base_time - timer_current->timer_base_count;
287 if (a1 < (a0 + 0x733))
295 timer_current = timer_current->timer_next;
297 if (a0 < (time_now + 0x733))
299 SetT2_COMP((*T2_COUNT) + (0x733 >> (((*T2_MODE) & 3) << 2)));
300 SetT2_MODE((*T2_MODE) & (~(1 << 11)));
304 SetT2_MODE((*T2_MODE) & (~(1 << 11)));
305 SetT2_COMP(a0 >> (((*T2_MODE) & 3) << 2));
310#ifdef F_InsertAlarm_ForTimer
311void InsertAlarm_ForTimer(counter_struct_t *timer_link)
313 counter_struct_t *timer_current;
314 counter_struct_t *timer_next;
317 abs_cmp = timer_link->timer_schedule + timer_link->timer_base_time - timer_link->timer_base_count;
318 timer_current = NULL;
319 timer_next = g_Timer.timer_counter_buf_alarm;
320 while (timer_next != NULL)
322 u64 target_cmp = timer_next->timer_schedule + timer_next->timer_base_time - timer_next->timer_base_count;
323 if (abs_cmp < target_cmp)
327 timer_current = timer_next;
328 timer_next = timer_next->timer_next;
330 timer_link->timer_previous = timer_current;
331 timer_link->timer_next = timer_next;
332 if (timer_next != NULL)
334 timer_next->timer_previous = timer_link;
336 if (timer_current != NULL)
338 timer_current->timer_next = timer_link;
342 g_Timer.timer_counter_buf_alarm = timer_link;
347#ifdef F_UnlinkAlarm_ForTimer
348counter_struct_t *UnlinkAlarm_ForTimer(counter_struct_t *timer_unlink)
350 counter_struct_t *timer_next;
352 timer_next = timer_unlink->timer_next;
353 if (timer_unlink->timer_previous)
355 timer_unlink->timer_previous->timer_next = timer_next;
359 g_Timer.timer_counter_buf_alarm = timer_unlink->timer_next;
361 if (timer_next != NULL)
363 timer_next->timer_previous = timer_unlink->timer_previous;
365 timer_unlink->timer_previous = NULL;
370#ifdef F_TimerHandler_callback
371static inline u64 ApplyOverflow(
void)
373 u64 timer_system_time_now;
379 if ((mode & (1 << 11)) != 0)
381 g_Timer.timer_handled_count += 1;
382 SetT2_MODE(mode & (~(1 << 10)));
385 timer_system_time_now = (g_Timer.timer_handled_count << 16) | low;
386 timer_system_time_now = timer_system_time_now << ((mode & 3) << 2);
387 return timer_system_time_now;
390s32 TimerHandler_callback(s32 cause,
void *arg,
void *addr)
392 counter_struct_t *timer_current;
393 counter_struct_t *timer_next;
397 u64 timer_schedule_next;
399 if (((*T2_MODE) & (1 << 10)) != 0)
401 timer_current = g_Timer.timer_counter_buf_alarm;
402 while (timer_current != NULL)
404 target_cmp = timer_current->timer_schedule + timer_current->timer_base_time - timer_current->timer_base_count;
405 abs_cmp = ApplyOverflow();
406 if (abs_cmp < target_cmp)
410 timer_next = UnlinkAlarm_ForTimer(timer_current);
411 timer_id = PTR_TO_TIMER_ID(timer_current);
412 g_Timer.current_handling_timer_id = timer_id;
413 SetGP(timer_current->gp_value);
414 timer_schedule_next = timer_current->callback_handler(
416 timer_current->timer_schedule,
417 (abs_cmp + timer_current->timer_base_count) - timer_current->timer_base_time,
418 timer_current->callback_handler_arg,
420 if (timer_schedule_next == 0)
422 timer_current->timer_mode &= ~TIMER_MODE_HANDLER;
424 else if (timer_schedule_next == (u64)-1)
426 timer_current->timer_next = g_Timer.timer_counter_buf_free;
427 g_Timer.timer_counter_buf_free = timer_current;
428 timer_current->timer_key = 0;
429 timer_current->timer_mode = 0;
430 g_Timer.timer_counter_used -= 1;
434 if (timer_schedule_next < 0x3999)
436 timer_schedule_next = 0x3999;
438 timer_current->timer_schedule += timer_schedule_next;
439 InsertAlarm_ForTimer(timer_current);
441 timer_current = timer_next;
444 g_Timer.current_handling_timer_id = -1;
445 SetNextComp(ApplyOverflow());
452#ifdef F_iGetTimerSystemTime
461u64 iGetTimerSystemTime(
void)
463 u64 timer_handled_count, timer_system_time_now;
468 timer_handled_count = g_Timer.timer_handled_count;
469 if ((mode & (1 << 11)) != 0)
471 timer_handled_count += 1;
474 timer_system_time_now = (timer_handled_count << 16) | low;
475 timer_system_time_now = timer_system_time_now << ((mode & 3) << 2);
476 return timer_system_time_now;
480#ifdef F_GetTimerSystemTime
490u64 GetTimerSystemTime(
void)
496 ret = iGetTimerSystemTime();
505#ifdef F_iAllocTimerCounter
506s32 iAllocTimerCounter(
void)
508 counter_struct_t *timer_current;
510 timer_current = g_Timer.timer_counter_buf_free;
511 if (timer_current == NULL)
515 g_Timer.timer_counter_buf_free = timer_current->timer_next;
516 g_Timer.timer_counter_used += 1;
517 timer_current->timer_mode = 0;
518 timer_current->callback_handler = NULL;
519 timer_current->timer_base_count = 0;
520 g_Timer.timer_counter_total += 1;
521 timer_current->timer_key = ((g_Timer.timer_counter_total << 1) & 0x3FE) | 1;
522 return PTR_TO_TIMER_ID(timer_current);
526#ifdef F_AllocTimerCounter
527s32 AllocTimerCounter(
void)
533 ret = iAllocTimerCounter();
542#ifdef F_iFreeTimerCounter
543s32 iFreeTimerCounter(s32
id)
545 counter_struct_t *timer_current;
547 timer_current = TIMER_ID_TO_PTR(
id);
548 if (!TIMER_ID_IS_VALID(
id))
552 if (g_Timer.current_handling_timer_id ==
id)
556 if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
558 UnlinkAlarm_ForTimer(timer_current);
560 timer_current->timer_key = 0;
561 timer_current->timer_mode = 0;
562 timer_current->timer_next = g_Timer.timer_counter_buf_free;
563 g_Timer.timer_counter_buf_free = timer_current;
564 g_Timer.timer_counter_used -= 1;
569#ifdef F_FreeTimerCounter
570s32 FreeTimerCounter(s32
id)
576 ret = iFreeTimerCounter(
id);
585#ifdef F_iGetTimerUsedUnusedCounters
586s32 iGetTimerUsedUnusedCounters(u32 *used_counters, u32 *unused_counters)
588 if (g_Timer.intc_handler < 0)
592 if (used_counters != NULL)
594 *used_counters = g_Timer.timer_counter_used;
596 if (unused_counters != NULL)
598 *unused_counters = (
sizeof(g_CounterBuf) /
sizeof(g_CounterBuf[0])) - g_Timer.timer_counter_used;
604#ifdef F_GetTimerUsedUnusedCounters
605s32 GetTimerUsedUnusedCounters(u32 *used_counters, u32 *unused_counters)
611 ret = iGetTimerUsedUnusedCounters(used_counters, unused_counters);
620#ifdef F_iStartTimerCounter
621s32 iStartTimerCounter(s32
id)
623 counter_struct_t *timer_current;
624 u64 timer_system_time_now;
626 timer_current = TIMER_ID_TO_PTR(
id);
627 if (!TIMER_ID_IS_VALID(
id))
631 if (g_Timer.current_handling_timer_id ==
id)
635 if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
639 timer_system_time_now = iGetTimerSystemTime();
640 timer_current->timer_base_time = timer_system_time_now;
641 timer_current->timer_mode |= TIMER_MODE_START;
642 if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
644 InsertAlarm_ForTimer(timer_current);
645 SetNextComp(timer_system_time_now);
651#ifdef F_StartTimerCounter
652s32 StartTimerCounter(s32
id)
658 ret = iStartTimerCounter(
id);
667#ifdef F_iStopTimerCounter
668s32 iStopTimerCounter(s32
id)
670 counter_struct_t *timer_current;
671 u64 timer_system_time_now;
673 timer_current = TIMER_ID_TO_PTR(
id);
674 if (!TIMER_ID_IS_VALID(
id))
678 if (g_Timer.current_handling_timer_id ==
id)
682 if ((timer_current->timer_mode & TIMER_MODE_START) == 0)
686 timer_system_time_now = iGetTimerSystemTime();
687 timer_current->timer_base_count += timer_system_time_now - timer_current->timer_base_time;
688 timer_current->timer_mode &= ~TIMER_MODE_START;
689 if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
691 UnlinkAlarm_ForTimer(timer_current);
692 SetNextComp(timer_system_time_now);
698#ifdef F_StopTimerCounter
699s32 StopTimerCounter(s32
id)
705 ret = iStopTimerCounter(
id);
714#ifdef F_SetTimerCount
715u64 SetTimerCount(s32
id, u64 timer_count)
717 counter_struct_t *timer_current;
720 u64 timer_system_time_now;
722 timer_current = TIMER_ID_TO_PTR(
id);
724 if ((!TIMER_ID_IS_VALID(
id)) || g_Timer.current_handling_timer_id ==
id)
732 ret = timer_current->timer_base_count;
733 if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
735 timer_system_time_now = iGetTimerSystemTime();
736 ret += timer_system_time_now - timer_current->timer_base_time;
737 timer_current->timer_base_count = timer_count;
738 timer_current->timer_base_time = timer_system_time_now;
742 timer_current->timer_base_count = timer_count;
752#ifdef F_iGetTimerBaseTime
753u64 iGetTimerBaseTime(s32
id)
755 counter_struct_t *timer_current;
757 timer_current = TIMER_ID_TO_PTR(
id);
758 if (!TIMER_ID_IS_VALID(
id))
762 if ((timer_current->timer_mode & TIMER_MODE_START) == 0)
766 return timer_current->timer_base_time - timer_current->timer_base_count;
770#ifdef F_GetTimerBaseTime
771u64 GetTimerBaseTime(s32
id)
777 ret = iGetTimerBaseTime(
id);
786#ifdef F_iGetTimerCount
787u64 iGetTimerCount(s32
id)
790 counter_struct_t *timer_current;
792 timer_current = TIMER_ID_TO_PTR(
id);
793 if (!TIMER_ID_IS_VALID(
id))
797 ret = timer_current->timer_base_count;
798 if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
800 ret += iGetTimerSystemTime() - timer_current->timer_base_time;
806#ifdef F_GetTimerCount
807u64 GetTimerCount(s32
id)
813 ret = iGetTimerCount(
id);
822#ifdef F_iSetTimerHandler
823s32 iSetTimerHandler(s32
id, u64 scheduled_time, timer_alarm_handler_t callback_handler,
void *arg)
825 counter_struct_t *timer_current;
827 timer_current = TIMER_ID_TO_PTR(
id);
828 if (!TIMER_ID_IS_VALID(
id))
832 if (g_Timer.current_handling_timer_id ==
id)
836 if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
838 UnlinkAlarm_ForTimer(timer_current);
840 timer_current->callback_handler = callback_handler;
841 if (callback_handler == NULL)
843 timer_current->timer_mode &= ~TIMER_MODE_HANDLER;
847 timer_current->timer_schedule = scheduled_time;
848 timer_current->timer_mode |= TIMER_MODE_HANDLER;
849 timer_current->gp_value = GetGP();
850 timer_current->callback_handler_arg = arg;
851 if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
853 InsertAlarm_ForTimer(timer_current);
856 SetNextComp(iGetTimerSystemTime());
861#ifdef F_SetTimerHandler
862s32 SetTimerHandler(s32
id, u64 scheduled_time, timer_alarm_handler_t callback_handler,
void *arg)
868 ret = iSetTimerHandler(
id, scheduled_time, callback_handler, arg);
877#ifdef F_TimerBusClock2USec
878void TimerBusClock2USec(u64 clocks, u32 *seconds_result, u32 *microseconds_result)
882 seconds = (u32)(clocks / kBUSCLK);
883 if (seconds_result != NULL)
885 *seconds_result = seconds;
887 if (microseconds_result != NULL)
889 *microseconds_result = (u32)(1000 * 1000 * (clocks - (((s64)(s32)((kBUSCLK * (u64)seconds) >> 32) << 32) | (u32)(kBUSCLK * seconds))) / kBUSCLK);
894#ifdef F_TimerUSec2BusClock
895u64 TimerUSec2BusClock(u32 seconds, u32 microseconds)
897 return (seconds * kBUSCLK) + (microseconds * (u64)kBUSCLK / (1000 * 1000));
901#ifdef F_TimerBusClock2Freq
902float TimerBusClock2Freq(s64 clocks)
904 return (
float)kBUSCLK / (float)clocks;
908#ifdef F_TimerFreq2BusClock
909u64 TimerFreq2BusClock(
float timer_frequency)
911 return (u64)((float)kBUSCLK / timer_frequency);