2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
5 Desc: Timer startup and device commands, reference code
7 This code uses VBlank interrupt as a source for both units. This can be
8 considered a reference code for building basic timer.device implementations,
9 using a periodic timer. However, in real life you'll want better timing source
10 than 50 Hz, so you'll likely replace this with your own code.
13 /****************************************************************************************/
15 #include <exec/types.h>
17 #include <exec/errors.h>
18 #include <exec/devices.h>
19 #include <exec/alerts.h>
20 #include <exec/initializers.h>
21 #include <devices/timer.h>
22 #include <hardware/intbits.h>
24 #include <proto/exec.h>
25 #include <proto/execlock.h>
26 #include <proto/timer.h>
28 #include <aros/symbolsets.h>
29 #include <aros/debug.h>
31 #include LC_LIBDEFS_FILE
33 #include "timer_macros.h"
35 /* exec.library VBlank interrupt handler */
36 static AROS_INTH1(VBlankInt
, struct TimerBase
*, TimerBase
)
41 * First increment the current time. No need to Disable() here as
42 * there are no other interrupts that are allowed to interrupt us
43 * that can do anything with this.
45 ADDTIME(&TimerBase
->tb_CurrentTime
, &TimerBase
->tb_Platform
.tb_VBlankTime
);
46 ADDTIME(&TimerBase
->tb_Elapsed
, &TimerBase
->tb_Platform
.tb_VBlankTime
);
47 TimerBase
->tb_ticks_total
++;
50 * Now go to handle requests.
51 * We are called at rather low rate, so don't bother and process both units.
53 handleMicroHZ(TimerBase
, SysBase
);
54 handleVBlank(TimerBase
, SysBase
);
61 /****************************************************************************************/
63 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR LIBBASE
)
67 #if defined(__AROSEXEC_SMP__)
68 struct ExecLockBase
*ExecLockBase
;
69 if ((ExecLockBase
= OpenResource("execlock.resource")) != NULL
)
71 LIBBASE
->tb_ExecLockBase
= ExecLockBase
;
72 LIBBASE
->tb_ListLock
= AllocLock();
76 /* If no frequency is set, assume 50Hz */
77 if (SysBase
->VBlankFrequency
== 0)
78 SysBase
->VBlankFrequency
= 50;
81 * Here we do no checks, we simply assume we have working VBlank interrupt,
82 * from whatever source it is.
85 LIBBASE
->tb_eclock_rate
= SysBase
->VBlankFrequency
;
86 D(bug("[timer] Timer IRQ is %d, frequency is %u Hz\n", INTB_VERTB
, LIBBASE
->tb_eclock_rate
));
88 /* Calculate timer period in us */
89 LIBBASE
->tb_Platform
.tb_VBlankTime
.tv_secs
= 0;
90 LIBBASE
->tb_Platform
.tb_VBlankTime
.tv_micro
= 1000000 / LIBBASE
->tb_eclock_rate
;
92 D(bug("Timer period: %ld secs, %ld micros\n",
93 LIBBASE
->tb_Platform
.tb_VBlankTime
.tv_secs
, LIBBASE
->tb_Platform
.tb_VBlankTime
.tv_micro
));
95 /* Start up the interrupt server */
96 is
= AllocMem(sizeof(struct Interrupt
), MEMF_PUBLIC
);
99 is
->is_Node
.ln_Pri
= 0;
100 is
->is_Node
.ln_Type
= NT_INTERRUPT
;
101 is
->is_Node
.ln_Name
= (STRPTR
)MOD_NAME_STRING
;
102 is
->is_Code
= (VOID_FUNC
)VBlankInt
;
103 is
->is_Data
= LIBBASE
;
105 AddIntServer(INTB_VERTB
, is
);
106 LIBBASE
->tb_TimerIRQHandle
= is
;
114 /****************************************************************************************/
116 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)