4 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
6 This file is part of simavr.
8 simavr is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 simavr is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with simavr. If not, see <http://www.gnu.org/licenses/>.
25 #include "sim_cycle_timers.h"
27 void avr_cycle_timer_register(avr_t * avr, avr_cycle_count_t when, avr_cycle_timer_t timer, void * param)
29 avr_cycle_timer_cancel(avr, timer, param);
31 if (avr->cycle_timer_map == 0xffffffff) {
32 fprintf(stderr, "avr_cycle_timer_register is full!\n");
36 if (when < avr->next_cycle_timer)
37 avr->next_cycle_timer = when;
38 for (int i = 0; i < 32; i++)
39 if (!(avr->cycle_timer_map & (1 << i))) {
40 avr->cycle_timer[i].timer = timer;
41 avr->cycle_timer[i].param = param;
42 avr->cycle_timer[i].when = when;
43 avr->cycle_timer_map |= (1 << i);
48 void avr_cycle_timer_register_usec(avr_t * avr, uint32_t when, avr_cycle_timer_t timer, void * param)
50 avr_cycle_timer_register(avr, avr_usec_to_cycles(avr, when), timer, param);
53 void avr_cycle_timer_cancel(avr_t * avr, avr_cycle_timer_t timer, void * param)
55 if (!avr->cycle_timer_map)
57 for (int i = 0; i < 32; i++)
58 if ((avr->cycle_timer_map & (1 << i)) &&
59 avr->cycle_timer[i].timer == timer &&
60 avr->cycle_timer[i].param == param) {
61 avr->cycle_timer[i].timer = NULL;
62 avr->cycle_timer[i].param = NULL;
63 avr->cycle_timer[i].when = 0;
64 avr->cycle_timer_map &= ~(1 << i);
65 // no need to reset next_cycle_timer; having too small
66 // a value there only causes some harmless extra
73 * Check to see if a timer is present, if so, return the number (+1) of
74 * cycles left for it to fire, and if not present, return zero
77 avr_cycle_timer_status(avr_t * avr, avr_cycle_timer_t timer, void * param)
79 uint32_t map = avr->cycle_timer_map;
83 if (avr->cycle_timer[bit].timer == timer &&
84 avr->cycle_timer[bit].param == param) {
85 return 1 + (avr->cycle_timer[bit].when - avr->cycle);
94 * run thru all the timers, call the ones that needs it,
95 * clear the ones that wants it, and calculate the next
96 * potential cycle we could sleep for...
98 avr_cycle_count_t avr_cycle_timer_process(avr_t * avr)
100 // If we have previously determined that we don't need to fire
101 // cycle timers yet, we can do an early exit
102 if (avr->next_cycle_timer > avr->cycle)
103 return avr->next_cycle_timer - avr->cycle;
105 if (!avr->cycle_timer_map) {
106 avr->next_cycle_timer = (avr_cycle_count_t)-1;
107 return (avr_cycle_count_t)-1;
110 avr_cycle_count_t min = (avr_cycle_count_t)-1;
111 uint32_t map = avr->cycle_timer_map;
114 int bit = ffs(map)-1;
115 // do it several times, in case we're late
116 while (avr->cycle_timer[bit].when && avr->cycle_timer[bit].when <= avr->cycle) {
118 avr->cycle_timer[bit].when =
119 avr->cycle_timer[bit].timer(avr,
120 avr->cycle_timer[bit].when,
121 avr->cycle_timer[bit].param);
122 if (avr->cycle_timer[bit].when == 0) {
124 avr->cycle_timer[bit].timer = NULL;
125 avr->cycle_timer[bit].param = NULL;
126 avr->cycle_timer[bit].when = 0;
127 avr->cycle_timer_map &= ~(1 << bit);
131 if (avr->cycle_timer[bit].when && avr->cycle_timer[bit].when < min)
132 min = avr->cycle_timer[bit].when;
135 avr->next_cycle_timer = min;
136 return min - avr->cycle;