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,
82#ifdef F__ps2sdk_init_timer
87 if (&_ps2sdk_init_timer_impl)
89 _ps2sdk_init_timer_impl();
94#ifdef F__ps2sdk_deinit_timer
99 if (&_ps2sdk_deinit_timer_impl)
101 _ps2sdk_deinit_timer_impl();
107void SetT2(
volatile void *ptr, u32 val)
110 *((
volatile u32 *)ptr) = val;
116void SetT2_COUNT(u32 val)
118 SetT2((
volatile void *)K_T2_COUNT, val);
123void SetT2_MODE(u32 val)
125 SetT2((
volatile void *)K_T2_MODE, val);
130void SetT2_COMP(u32 val)
132 SetT2((
volatile void *)K_T2_COMP, val);
143 if (g_Timer.intc_handler >= 0)
147 g_Timer.timer_handled_count = 0;
148 g_Timer.timer_counter_used = 0;
149 memset(g_CounterBuf, 0,
sizeof(g_CounterBuf));
150 g_Timer.timer_counter_buf_free = &g_CounterBuf[0];
151 for (u32 i = 0; i < ((
sizeof(g_CounterBuf) /
sizeof(g_CounterBuf[0])) - 1); i += 1)
153 g_CounterBuf[i].timer_next = &g_CounterBuf[i + 1];
155 g_CounterBuf[(
sizeof(g_CounterBuf) /
sizeof(g_CounterBuf[0])) - 1].timer_next = NULL;
156 ForTimer_InitAlarm();
157 handler = AddIntcHandler2(INTC_TIM2, TimerHandler_callback, 0, NULL);
162 g_Timer.intc_handler = handler;
164 mode = ((*T2_MODE) & (~0x3)) | in_mode;
165 mode |= (1 << 9) | (1 << 8);
166 if ((mode & (1 << 7)) == 0)
169 mode |= (1 << 11) | (1 << 10);
174 EnableIntc(INTC_TIM2);
188 if (g_Timer.intc_handler < 0)
192 if (g_Timer.timer_counter_used != 0)
197 if (RemoveIntcHandler(INTC_TIM2, g_Timer.intc_handler) == 0)
199 DisableIntc(INTC_TIM2);
200 SetT2_MODE((1 << 11) | (1 << 10));
203 g_Timer.timer_handled_count = 0;
204 g_Timer.intc_handler = -1;
213#ifdef F_GetTimerPreScaleFactor
214s32 GetTimerPreScaleFactor(
void)
216 if (g_Timer.intc_handler < 0)
220 return (*T2_MODE) & 3;
224#ifdef F_StartTimerSystemTime
236 if (((*T2_MODE) & (1 << 7)) != 0)
246 SetT2_MODE(((*T2_MODE) & (~((1 << 11) | (1 << 10)))) | (1 << 7));
247 SetNextComp(iGetTimerSystemTime());
257#ifdef F_StopTimerSystemTime
269 if (((*T2_MODE) & (1 << 7)) != 0)
271 SetT2_MODE((*T2_MODE) & (~((1 << 11) | (1 << 10))));
290#define CLOCKS_GAP 0x200
291void SetNextComp(u64 time_now)
293 u64 current_schedule, next_schedule;
294 counter_struct_t *timer_current;
296 if (g_Timer.current_handling_timer_id >= 0)
300 timer_current = g_Timer.timer_counter_buf_alarm;
301 if (timer_current == NULL)
304 SetT2_MODE((*T2_MODE) & (~(1 << 11)));
307 current_schedule = timer_current->timer_schedule + timer_current->timer_base_time - timer_current->timer_base_count;
308 timer_current = timer_current->timer_next;
311 while (timer_current != NULL)
313 next_schedule = timer_current->timer_schedule + timer_current->timer_base_time - timer_current->timer_base_count;
314 if (next_schedule < (current_schedule + CLOCKS_GAP))
316 current_schedule = next_schedule;
322 timer_current = timer_current->timer_next;
324 if (current_schedule < (time_now + CLOCKS_GAP))
326 SetT2_COMP((*T2_COUNT) + (CLOCKS_GAP >> (((*T2_MODE) & 3) << 2)));
327 SetT2_MODE((*T2_MODE) & (~(1 << 11)));
331 SetT2_MODE((*T2_MODE) & (~(1 << 11)));
332 SetT2_COMP(current_schedule >> (((*T2_MODE) & 3) << 2));
337#ifdef F_InsertAlarm_ForTimer
338void InsertAlarm_ForTimer(counter_struct_t *timer_link)
340 counter_struct_t *timer_current;
341 counter_struct_t *timer_next;
344 abs_cmp = timer_link->timer_schedule + timer_link->timer_base_time - timer_link->timer_base_count;
345 timer_current = NULL;
346 timer_next = g_Timer.timer_counter_buf_alarm;
347 while (timer_next != NULL)
349 u64 target_cmp = timer_next->timer_schedule + timer_next->timer_base_time - timer_next->timer_base_count;
350 if (abs_cmp < target_cmp)
354 timer_current = timer_next;
355 timer_next = timer_next->timer_next;
357 timer_link->timer_previous = timer_current;
358 timer_link->timer_next = timer_next;
359 if (timer_next != NULL)
361 timer_next->timer_previous = timer_link;
363 if (timer_current != NULL)
365 timer_current->timer_next = timer_link;
369 g_Timer.timer_counter_buf_alarm = timer_link;
374#ifdef F_UnlinkAlarm_ForTimer
375counter_struct_t *UnlinkAlarm_ForTimer(counter_struct_t *timer_unlink)
377 counter_struct_t *timer_next;
379 timer_next = timer_unlink->timer_next;
380 if (timer_unlink->timer_previous)
382 timer_unlink->timer_previous->timer_next = timer_next;
386 g_Timer.timer_counter_buf_alarm = timer_unlink->timer_next;
388 if (timer_next != NULL)
390 timer_next->timer_previous = timer_unlink->timer_previous;
392 timer_unlink->timer_previous = NULL;
397#ifdef F_TimerHandler_callback
398static inline u64 ApplyOverflow(
void)
400 u64 timer_system_time_now;
406 if ((mode & (1 << 11)) != 0)
408 g_Timer.timer_handled_count += 1;
409 SetT2_MODE(mode & (~(1 << 10)));
412 timer_system_time_now = (g_Timer.timer_handled_count << 16) | low;
413 timer_system_time_now = timer_system_time_now << ((mode & 3) << 2);
414 return timer_system_time_now;
417s32 TimerHandler_callback(s32 cause,
void *arg,
void *addr)
419 counter_struct_t *timer_current;
420 counter_struct_t *timer_next;
424 u64 timer_schedule_next;
426 if (((*T2_MODE) & (1 << 10)) != 0)
428 timer_current = g_Timer.timer_counter_buf_alarm;
429 while (timer_current != NULL)
431 target_cmp = timer_current->timer_schedule + timer_current->timer_base_time - timer_current->timer_base_count;
432 abs_cmp = ApplyOverflow();
433 if (abs_cmp < target_cmp)
437 timer_next = UnlinkAlarm_ForTimer(timer_current);
438 timer_id = PTR_TO_TIMER_ID(timer_current);
439 g_Timer.current_handling_timer_id = timer_id;
440 SetGP(timer_current->gp_value);
441 timer_schedule_next = timer_current->callback_handler(
443 timer_current->timer_schedule,
444 (abs_cmp + timer_current->timer_base_count) - timer_current->timer_base_time,
445 timer_current->callback_handler_arg,
447 if (timer_schedule_next == 0)
449 timer_current->timer_mode &= ~TIMER_MODE_HANDLER;
451 else if (timer_schedule_next == (u64)-1)
453 timer_current->timer_next = g_Timer.timer_counter_buf_free;
454 g_Timer.timer_counter_buf_free = timer_current;
455 timer_current->timer_key = 0;
456 timer_current->timer_mode = 0;
457 g_Timer.timer_counter_used -= 1;
461 if (timer_schedule_next < 0x3999)
463 timer_schedule_next = 0x3999;
465 timer_current->timer_schedule += timer_schedule_next;
466 InsertAlarm_ForTimer(timer_current);
468 timer_current = timer_next;
471 g_Timer.current_handling_timer_id = -1;
472 SetNextComp(ApplyOverflow());
479#ifdef F_iGetTimerSystemTime
488u64 iGetTimerSystemTime(
void)
490 u64 timer_handled_count, timer_system_time_now;
495 timer_handled_count = g_Timer.timer_handled_count;
496 if ((mode & (1 << 11)) != 0)
498 timer_handled_count += 1;
501 timer_system_time_now = (timer_handled_count << 16) | low;
502 timer_system_time_now = timer_system_time_now << ((mode & 3) << 2);
503 return timer_system_time_now;
506void _ps2sdk_init_timer_impl(
void)
509 StartTimerSystemTime();
512void _ps2sdk_deinit_timer_impl(
void)
514 StopTimerSystemTime();
519#ifdef F_GetTimerSystemTime
529u64 GetTimerSystemTime(
void)
535 ret = iGetTimerSystemTime();
544#ifdef F_iAllocTimerCounter
545s32 iAllocTimerCounter(
void)
547 counter_struct_t *timer_current;
549 timer_current = g_Timer.timer_counter_buf_free;
550 if (timer_current == NULL)
554 g_Timer.timer_counter_buf_free = timer_current->timer_next;
555 g_Timer.timer_counter_used += 1;
556 timer_current->timer_mode = 0;
557 timer_current->callback_handler = NULL;
558 timer_current->timer_base_count = 0;
559 g_Timer.timer_counter_total += 1;
560 timer_current->timer_key = ((g_Timer.timer_counter_total << 1) & 0x3FE) | 1;
561 return PTR_TO_TIMER_ID(timer_current);
565#ifdef F_AllocTimerCounter
566s32 AllocTimerCounter(
void)
572 ret = iAllocTimerCounter();
581#ifdef F_iFreeTimerCounter
582s32 iFreeTimerCounter(s32
id)
584 counter_struct_t *timer_current;
586 timer_current = TIMER_ID_TO_PTR(
id);
587 if (!TIMER_ID_IS_VALID(
id))
591 if (g_Timer.current_handling_timer_id ==
id)
595 if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
597 UnlinkAlarm_ForTimer(timer_current);
599 timer_current->timer_key = 0;
600 timer_current->timer_mode = 0;
601 timer_current->timer_next = g_Timer.timer_counter_buf_free;
602 g_Timer.timer_counter_buf_free = timer_current;
603 g_Timer.timer_counter_used -= 1;
608#ifdef F_FreeTimerCounter
609s32 FreeTimerCounter(s32
id)
615 ret = iFreeTimerCounter(
id);
624#ifdef F_iGetTimerUsedUnusedCounters
625s32 iGetTimerUsedUnusedCounters(u32 *used_counters, u32 *unused_counters)
627 if (g_Timer.intc_handler < 0)
631 if (used_counters != NULL)
633 *used_counters = g_Timer.timer_counter_used;
635 if (unused_counters != NULL)
637 *unused_counters = (
sizeof(g_CounterBuf) /
sizeof(g_CounterBuf[0])) - g_Timer.timer_counter_used;
643#ifdef F_GetTimerUsedUnusedCounters
644s32 GetTimerUsedUnusedCounters(u32 *used_counters, u32 *unused_counters)
650 ret = iGetTimerUsedUnusedCounters(used_counters, unused_counters);
659#ifdef F_iStartTimerCounter
660s32 iStartTimerCounter(s32
id)
662 counter_struct_t *timer_current;
663 u64 timer_system_time_now;
665 timer_current = TIMER_ID_TO_PTR(
id);
666 if (!TIMER_ID_IS_VALID(
id))
670 if (g_Timer.current_handling_timer_id ==
id)
674 if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
678 timer_system_time_now = iGetTimerSystemTime();
679 timer_current->timer_base_time = timer_system_time_now;
680 timer_current->timer_mode |= TIMER_MODE_START;
681 if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
683 InsertAlarm_ForTimer(timer_current);
684 SetNextComp(timer_system_time_now);
690#ifdef F_StartTimerCounter
691s32 StartTimerCounter(s32
id)
697 ret = iStartTimerCounter(
id);
706#ifdef F_iStopTimerCounter
707s32 iStopTimerCounter(s32
id)
709 counter_struct_t *timer_current;
710 u64 timer_system_time_now;
712 timer_current = TIMER_ID_TO_PTR(
id);
713 if (!TIMER_ID_IS_VALID(
id))
717 if (g_Timer.current_handling_timer_id ==
id)
721 if ((timer_current->timer_mode & TIMER_MODE_START) == 0)
725 timer_system_time_now = iGetTimerSystemTime();
726 timer_current->timer_base_count += timer_system_time_now - timer_current->timer_base_time;
727 timer_current->timer_mode &= ~TIMER_MODE_START;
728 if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
730 UnlinkAlarm_ForTimer(timer_current);
731 SetNextComp(timer_system_time_now);
737#ifdef F_StopTimerCounter
738s32 StopTimerCounter(s32
id)
744 ret = iStopTimerCounter(
id);
753#ifdef F_SetTimerCount
754u64 SetTimerCount(s32
id, u64 timer_count)
756 counter_struct_t *timer_current;
759 u64 timer_system_time_now;
761 timer_current = TIMER_ID_TO_PTR(
id);
763 if ((!TIMER_ID_IS_VALID(
id)) || g_Timer.current_handling_timer_id ==
id)
771 ret = timer_current->timer_base_count;
772 if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
774 timer_system_time_now = iGetTimerSystemTime();
775 ret += timer_system_time_now - timer_current->timer_base_time;
776 timer_current->timer_base_count = timer_count;
777 timer_current->timer_base_time = timer_system_time_now;
781 timer_current->timer_base_count = timer_count;
791#ifdef F_iGetTimerBaseTime
792u64 iGetTimerBaseTime(s32
id)
794 counter_struct_t *timer_current;
796 timer_current = TIMER_ID_TO_PTR(
id);
797 if (!TIMER_ID_IS_VALID(
id))
801 if ((timer_current->timer_mode & TIMER_MODE_START) == 0)
805 return timer_current->timer_base_time - timer_current->timer_base_count;
809#ifdef F_GetTimerBaseTime
810u64 GetTimerBaseTime(s32
id)
816 ret = iGetTimerBaseTime(
id);
825#ifdef F_iGetTimerCount
826u64 iGetTimerCount(s32
id)
829 counter_struct_t *timer_current;
831 timer_current = TIMER_ID_TO_PTR(
id);
832 if (!TIMER_ID_IS_VALID(
id))
836 ret = timer_current->timer_base_count;
837 if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
839 ret += iGetTimerSystemTime() - timer_current->timer_base_time;
845#ifdef F_GetTimerCount
846u64 GetTimerCount(s32
id)
852 ret = iGetTimerCount(
id);
861#ifdef F_iSetTimerHandler
862s32 iSetTimerHandler(s32
id, u64 scheduled_time, timer_alarm_handler_t callback_handler,
void *arg)
864 counter_struct_t *timer_current;
866 timer_current = TIMER_ID_TO_PTR(
id);
867 if (!TIMER_ID_IS_VALID(
id))
871 if (g_Timer.current_handling_timer_id ==
id)
875 if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
877 UnlinkAlarm_ForTimer(timer_current);
879 timer_current->callback_handler = callback_handler;
880 if (callback_handler == NULL)
882 timer_current->timer_mode &= ~TIMER_MODE_HANDLER;
886 timer_current->timer_schedule = scheduled_time;
887 timer_current->timer_mode |= TIMER_MODE_HANDLER;
888 timer_current->gp_value = GetGP();
889 timer_current->callback_handler_arg = arg;
890 if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
892 InsertAlarm_ForTimer(timer_current);
895 SetNextComp(iGetTimerSystemTime());
900#ifdef F_SetTimerHandler
901s32 SetTimerHandler(s32
id, u64 scheduled_time, timer_alarm_handler_t callback_handler,
void *arg)
907 ret = iSetTimerHandler(
id, scheduled_time, callback_handler, arg);
916#ifdef F_TimerBusClock2USec
917void TimerBusClock2USec(u64 clocks, u32 *seconds_result, u32 *microseconds_result)
921 seconds = (u32)(clocks / kBUSCLK);
922 if (seconds_result != NULL)
924 *seconds_result = seconds;
926 if (microseconds_result != NULL)
928 *microseconds_result = (u32)(1000 * 1000 * (clocks - (((s64)(s32)((kBUSCLK * (u64)seconds) >> 32) << 32) | (u32)(kBUSCLK * seconds))) / kBUSCLK);
933#ifdef F_TimerUSec2BusClock
934u64 TimerUSec2BusClock(u32 seconds, u32 microseconds)
936 return (seconds * kBUSCLK) + (microseconds * (u64)kBUSCLK / (1000 * 1000));
940#ifdef F_TimerBusClock2Freq
941float TimerBusClock2Freq(s64 clocks)
943 return (
float)kBUSCLK / (float)clocks;
947#ifdef F_TimerFreq2BusClock
948u64 TimerFreq2BusClock(
float timer_frequency)
950 return (u64)((float)kBUSCLK / timer_frequency);