21#define TIMER_MODE_START 0x00000001
22#define TIMER_MODE_HANDLER 0x00000002
33 timer_alarm_handler_t callback_handler;
35 void *callback_handler_arg;
41 vu64 timer_handled_count;
43 vu32 timer_counter_total;
44 vu32 timer_counter_used;
45 counter_struct_t *timer_counter_buf_free;
46 counter_struct_t *timer_counter_buf_alarm;
47 vs32 current_handling_timer_id;
48} timer_ee_global_struct;
50#define PTR_TO_TIMER_ID(ptr_) ((s32)((((uiptr)(ptr_)) << 4) | ((ptr_)->timer_key)))
51#define TIMER_ID_TO_PTR(id_) ((counter_struct_t *)((((uiptr)(id_)) >> 10) << 6))
52#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)))
55extern void ForTimer_InitAlarm(
void);
57extern void SetT2(
volatile void *ptr, u32 val);
58extern void SetT2_COUNT(u32 val);
59extern void SetT2_MODE(u32 val);
60extern void SetT2_COMP(u32 val);
61extern void InsertAlarm_ForTimer(counter_struct_t *timer_link);
62extern counter_struct_t *UnlinkAlarm_ForTimer(counter_struct_t *timer_unlink);
63extern s32 TimerHandler_callback(s32 cause,
void *arg,
void *addr);
65#define COUNTER_COUNT 128
67timer_ee_global_struct g_Timer;
68counter_struct_t g_CounterBuf[COUNTER_COUNT]
__attribute__((aligned(64)));
74 if (&_ps2sdk_init_timer_impl)
76 _ps2sdk_init_timer_impl();
84 if (&_ps2sdk_deinit_timer_impl)
86 _ps2sdk_deinit_timer_impl();
90void SetT2(
volatile void *ptr, u32 val)
93 *((
volatile u32 *)ptr) = val;
97void SetT2_COUNT(u32 val)
99 SetT2((
volatile void *)K_T2_COUNT, val);
102void SetT2_MODE(u32 val)
104 SetT2((
volatile void *)K_T2_MODE, val);
107void SetT2_COMP(u32 val)
109 SetT2((
volatile void *)K_T2_COMP, val);
118 if (g_Timer.intc_handler > 0)
122 g_Timer.timer_handled_count = 0;
123 g_Timer.timer_counter_used = 0;
124 g_Timer.timer_counter_total = 1;
125 g_Timer.current_handling_timer_id = -1;
126 memset(g_CounterBuf, 0,
sizeof(g_CounterBuf));
127 g_Timer.timer_counter_buf_free = &g_CounterBuf[0];
128 for (u32 i = 0; i < ((
sizeof(g_CounterBuf) /
sizeof(g_CounterBuf[0])) - 1); i += 1)
130 g_CounterBuf[i].timer_next = &g_CounterBuf[i + 1];
132 g_CounterBuf[(
sizeof(g_CounterBuf) /
sizeof(g_CounterBuf[0])) - 1].timer_next = NULL;
133 g_Timer.timer_counter_buf_alarm = NULL;
134 ForTimer_InitAlarm();
135 handler = AddIntcHandler2(INTC_TIM2, TimerHandler_callback, 0, NULL);
140 g_Timer.intc_handler = handler;
142 mode = ((*T2_MODE) & (~0x3)) | in_mode;
143 mode |= (1 << 9) | (1 << 8);
144 if ((mode & (1 << 7)) == 0)
147 mode |= (1 << 11) | (1 << 10);
152 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;
188s32 GetTimerPreScaleFactor(
void)
190 if (g_Timer.intc_handler < 0)
194 return (*T2_MODE) & 3;
208 if (((*T2_MODE) & (1 << 7)) != 0)
218 SetT2_MODE(((*T2_MODE) & (~((1 << 11) | (1 << 10)))) | (1 << 7));
239 if (((*T2_MODE) & (1 << 7)) != 0)
241 SetT2_MODE((*T2_MODE) & (~((1 << 11) | (1 << 10))));
258#define CLOCKS_GAP 0x200
259void SetNextComp(u64 time_now)
261 u64 current_schedule, next_schedule;
262 counter_struct_t *timer_current;
264 if (g_Timer.current_handling_timer_id >= 0)
268 timer_current = g_Timer.timer_counter_buf_alarm;
269 if (timer_current == NULL)
272 SetT2_MODE((*T2_MODE) & (~(1 << 11)));
275 current_schedule = timer_current->timer_schedule + timer_current->timer_base_time - timer_current->timer_base_count;
276 timer_current = timer_current->timer_next;
279 while (timer_current != NULL)
281 next_schedule = timer_current->timer_schedule + timer_current->timer_base_time - timer_current->timer_base_count;
282 if (next_schedule < (current_schedule + CLOCKS_GAP))
284 current_schedule = next_schedule;
290 timer_current = timer_current->timer_next;
292 if (current_schedule < (time_now + CLOCKS_GAP))
294 SetT2_COMP((*T2_COUNT) + (CLOCKS_GAP >> (((*T2_MODE) & 3) << 2)));
295 SetT2_MODE((*T2_MODE) & (~(1 << 11)));
299 SetT2_MODE((*T2_MODE) & (~(1 << 11)));
300 SetT2_COMP(current_schedule >> (((*T2_MODE) & 3) << 2));
304void InsertAlarm_ForTimer(counter_struct_t *timer_link)
306 counter_struct_t *timer_current;
307 counter_struct_t *timer_next;
310 abs_cmp = timer_link->timer_schedule + timer_link->timer_base_time - timer_link->timer_base_count;
311 timer_current = NULL;
312 timer_next = g_Timer.timer_counter_buf_alarm;
313 while (timer_next != NULL)
315 u64 target_cmp = timer_next->timer_schedule + timer_next->timer_base_time - timer_next->timer_base_count;
316 if (abs_cmp < target_cmp)
320 timer_current = timer_next;
321 timer_next = timer_next->timer_next;
323 timer_link->timer_previous = timer_current;
324 timer_link->timer_next = timer_next;
325 if (timer_next != NULL)
327 timer_next->timer_previous = timer_link;
329 if (timer_current != NULL)
331 timer_current->timer_next = timer_link;
335 g_Timer.timer_counter_buf_alarm = timer_link;
339counter_struct_t *UnlinkAlarm_ForTimer(counter_struct_t *timer_unlink)
341 counter_struct_t *timer_next;
343 timer_next = timer_unlink->timer_next;
344 if (timer_unlink->timer_previous)
346 timer_unlink->timer_previous->timer_next = timer_next;
350 g_Timer.timer_counter_buf_alarm = timer_unlink->timer_next;
352 if (timer_next != NULL)
354 timer_next->timer_previous = timer_unlink->timer_previous;
356 timer_unlink->timer_previous = NULL;
360static inline u64 ApplyOverflow(
void)
362 u64 timer_system_time_now;
368 if ((mode & (1 << 11)) != 0)
370 g_Timer.timer_handled_count += 1;
371 SetT2_MODE(mode & (~(1 << 10)));
374 timer_system_time_now = (g_Timer.timer_handled_count << 16) | low;
375 timer_system_time_now = timer_system_time_now << ((mode & 3) << 2);
376 return timer_system_time_now;
379s32 TimerHandler_callback(s32 cause,
void *arg,
void *addr)
381 counter_struct_t *timer_current;
382 counter_struct_t *timer_next;
386 u64 timer_schedule_next;
388 if (((*T2_MODE) & (1 << 10)) != 0)
390 timer_current = g_Timer.timer_counter_buf_alarm;
391 while (timer_current != NULL)
393 target_cmp = timer_current->timer_schedule + timer_current->timer_base_time - timer_current->timer_base_count;
394 abs_cmp = ApplyOverflow();
395 if (abs_cmp < target_cmp)
399 timer_next = UnlinkAlarm_ForTimer(timer_current);
400 timer_id = PTR_TO_TIMER_ID(timer_current);
401 g_Timer.current_handling_timer_id = timer_id;
402 SetGP(timer_current->gp_value);
403 timer_schedule_next = timer_current->callback_handler(
405 timer_current->timer_schedule,
406 (abs_cmp + timer_current->timer_base_count) - timer_current->timer_base_time,
407 timer_current->callback_handler_arg,
409 if (timer_schedule_next == 0)
411 timer_current->timer_mode &= ~TIMER_MODE_HANDLER;
413 else if (timer_schedule_next == (u64)-1)
415 timer_current->timer_next = g_Timer.timer_counter_buf_free;
416 g_Timer.timer_counter_buf_free = timer_current;
417 timer_current->timer_key = 0;
418 timer_current->timer_mode = 0;
419 g_Timer.timer_counter_used -= 1;
423 if (timer_schedule_next < 0x3999)
425 timer_schedule_next = 0x3999;
427 timer_current->timer_schedule += timer_schedule_next;
428 InsertAlarm_ForTimer(timer_current);
430 timer_current = timer_next;
433 g_Timer.current_handling_timer_id = -1;
434 SetNextComp(ApplyOverflow());
450 u64 timer_handled_count, timer_system_time_now;
455 timer_handled_count = g_Timer.timer_handled_count;
456 if ((mode & (1 << 11)) != 0)
458 timer_handled_count += 1;
461 timer_system_time_now = (timer_handled_count << 16) | low;
462 timer_system_time_now = timer_system_time_now << ((mode & 3) << 2);
463 return timer_system_time_now;
466void _ps2sdk_init_timer_impl(
void)
469 StartTimerSystemTime();
472void _ps2sdk_deinit_timer_impl(
void)
474 StopTimerSystemTime();
501s32 iAllocTimerCounter(
void)
503 counter_struct_t *timer_current;
505 timer_current = g_Timer.timer_counter_buf_free;
506 if (timer_current == NULL)
510 g_Timer.timer_counter_buf_free = timer_current->timer_next;
511 g_Timer.timer_counter_used += 1;
512 timer_current->timer_mode = 0;
513 timer_current->callback_handler = NULL;
514 timer_current->timer_base_count = 0;
515 g_Timer.timer_counter_total += 1;
516 timer_current->timer_key = ((g_Timer.timer_counter_total << 1) & 0x3FE) | 1;
517 return PTR_TO_TIMER_ID(timer_current);
520s32 AllocTimerCounter(
void)
526 ret = iAllocTimerCounter();
534s32 iFreeTimerCounter(s32
id)
536 counter_struct_t *timer_current;
538 timer_current = TIMER_ID_TO_PTR(
id);
539 if (!TIMER_ID_IS_VALID(
id))
543 if (g_Timer.current_handling_timer_id ==
id)
547 if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
549 UnlinkAlarm_ForTimer(timer_current);
551 timer_current->timer_key = 0;
552 timer_current->timer_mode = 0;
553 timer_current->timer_next = g_Timer.timer_counter_buf_free;
554 g_Timer.timer_counter_buf_free = timer_current;
555 g_Timer.timer_counter_used -= 1;
559s32 FreeTimerCounter(s32
id)
565 ret = iFreeTimerCounter(
id);
573s32 iGetTimerUsedUnusedCounters(u32 *used_counters, u32 *unused_counters)
575 if (g_Timer.intc_handler < 0)
579 if (used_counters != NULL)
581 *used_counters = g_Timer.timer_counter_used;
583 if (unused_counters != NULL)
585 *unused_counters = (
sizeof(g_CounterBuf) /
sizeof(g_CounterBuf[0])) - g_Timer.timer_counter_used;
590s32 GetTimerUsedUnusedCounters(u32 *used_counters, u32 *unused_counters)
596 ret = iGetTimerUsedUnusedCounters(used_counters, unused_counters);
604s32 iStartTimerCounter(s32
id)
606 counter_struct_t *timer_current;
607 u64 timer_system_time_now;
609 timer_current = TIMER_ID_TO_PTR(
id);
610 if (!TIMER_ID_IS_VALID(
id))
614 if (g_Timer.current_handling_timer_id ==
id)
618 if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
623 timer_current->timer_base_time = timer_system_time_now;
624 timer_current->timer_mode |= TIMER_MODE_START;
625 if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
627 InsertAlarm_ForTimer(timer_current);
628 SetNextComp(timer_system_time_now);
633s32 StartTimerCounter(s32
id)
639 ret = iStartTimerCounter(
id);
647s32 iStopTimerCounter(s32
id)
649 counter_struct_t *timer_current;
650 u64 timer_system_time_now;
652 timer_current = TIMER_ID_TO_PTR(
id);
653 if (!TIMER_ID_IS_VALID(
id))
657 if (g_Timer.current_handling_timer_id ==
id)
661 if ((timer_current->timer_mode & TIMER_MODE_START) == 0)
666 timer_current->timer_base_count += timer_system_time_now - timer_current->timer_base_time;
667 timer_current->timer_mode &= ~TIMER_MODE_START;
668 if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
670 UnlinkAlarm_ForTimer(timer_current);
671 SetNextComp(timer_system_time_now);
676s32 StopTimerCounter(s32
id)
682 ret = iStopTimerCounter(
id);
690u64 SetTimerCount(s32
id, u64 timer_count)
692 counter_struct_t *timer_current;
695 u64 timer_system_time_now;
697 timer_current = TIMER_ID_TO_PTR(
id);
699 if ((!TIMER_ID_IS_VALID(
id)) || g_Timer.current_handling_timer_id ==
id)
707 ret = timer_current->timer_base_count;
708 if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
711 ret += timer_system_time_now - timer_current->timer_base_time;
712 timer_current->timer_base_count = timer_count;
713 timer_current->timer_base_time = timer_system_time_now;
717 timer_current->timer_base_count = timer_count;
726u64 iGetTimerBaseTime(s32
id)
728 counter_struct_t *timer_current;
730 timer_current = TIMER_ID_TO_PTR(
id);
731 if (!TIMER_ID_IS_VALID(
id))
735 if ((timer_current->timer_mode & TIMER_MODE_START) == 0)
739 return timer_current->timer_base_time - timer_current->timer_base_count;
742u64 GetTimerBaseTime(s32
id)
748 ret = iGetTimerBaseTime(
id);
756u64 iGetTimerCount(s32
id)
759 counter_struct_t *timer_current;
761 timer_current = TIMER_ID_TO_PTR(
id);
762 if (!TIMER_ID_IS_VALID(
id))
766 ret = timer_current->timer_base_count;
767 if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
774u64 GetTimerCount(s32
id)
780 ret = iGetTimerCount(
id);
788s32 iSetTimerHandler(s32
id, u64 scheduled_time, timer_alarm_handler_t callback_handler,
void *arg)
790 counter_struct_t *timer_current;
792 timer_current = TIMER_ID_TO_PTR(
id);
793 if (!TIMER_ID_IS_VALID(
id))
797 if (g_Timer.current_handling_timer_id ==
id)
801 if ((timer_current->timer_mode & TIMER_MODE_HANDLER) != 0)
803 UnlinkAlarm_ForTimer(timer_current);
805 timer_current->callback_handler = callback_handler;
806 if (callback_handler == NULL)
808 timer_current->timer_mode &= ~TIMER_MODE_HANDLER;
812 timer_current->timer_schedule = scheduled_time;
813 timer_current->timer_mode |= TIMER_MODE_HANDLER;
814 timer_current->gp_value = GetGP();
815 timer_current->callback_handler_arg = arg;
816 if ((timer_current->timer_mode & TIMER_MODE_START) != 0)
818 InsertAlarm_ForTimer(timer_current);
825s32 SetTimerHandler(s32
id, u64 scheduled_time, timer_alarm_handler_t callback_handler,
void *arg)
831 ret = iSetTimerHandler(
id, scheduled_time, callback_handler, arg);
839void TimerBusClock2USec(u64 clocks, u32 *seconds_result, u32 *microseconds_result)
843 seconds = (u32)(clocks / kBUSCLK);
844 if (seconds_result != NULL)
846 *seconds_result = seconds;
848 if (microseconds_result != NULL)
850 *microseconds_result = (u32)(1000 * 1000 * (clocks - (((s64)(s32)((kBUSCLK * (u64)seconds) >> 32) << 32) | (u32)(kBUSCLK * seconds))) / kBUSCLK);
854u64 TimerUSec2BusClock(u32 seconds, u32 microseconds)
856 return (seconds * kBUSCLK) + (microseconds * (u64)kBUSCLK / (1000 * 1000));
859float TimerBusClock2Freq(s64 clocks)
861 return (
float)kBUSCLK / (float)clocks;
864u64 TimerFreq2BusClock(
float timer_frequency)
866 return (u64)((float)kBUSCLK / timer_frequency);
u64 iGetTimerSystemTime(void)
u64 GetTimerSystemTime(void)