Golem  v0.1.1
Generic Operating system Libraries for Embedded Multitasking
 All Data Structures Files Functions Variables Pages
/home/ruud/Engineering/software/projects/golem-project-code/trunk/glm_alarm.c
1 
11 /* INCLUDES *******************************************************************/
12 #include <math.h>
13 #include "glm_alarm.h"
14 #include "glm_tick.h"
15 #include "ADT/glm_list.h"
16 
17 
18 /* TYPES **********************************************************************/
19 typedef struct
20 {
21  uint_base_t delay;
22  tickstamp_t start;
23  signal_t signal;
24  void (*cb_func)(void);
25 } alarm_t;
26 
27 
28 
29 /* PRIVATE VARIABLES **********************************************************/
30 static bool m_initialized = false;
31 static list_t *m_alarms = NULL;
32 static heap_id_t m_heap_id = 0;
33 
34 /* PRIVATE CONSTANTS **********************************************************/
35 static const char *m_name = "glm_alarm";
36 
37 
38 /* PRIVATE FUNCTION DECLARATIONS **********************************************/
39 
40 
41 // Allocates memory for a new alarm with the given parameters and returns a
42 // pointer to the new alarm if successful or NULL otherwise
43 static alarm_t * alarm_create( uint_base_t a_time, signal_t a_signal,
44  p_callback_func_t a_func );
45 
46 // Calculates the time in ticks until the alarm is due
47 static uint_base_t alarm_ticks_till_due(uint_base_t a_start_tick,
48  uint_base_t a_delay );
49 
50 
51 // Adds alarm to alarm-list in a sorted way (first alarm at the top of the list)
52 // and returns TRUE if successful or FALSE otherwise
53 bool alarm_add( alarm_t *a_alarm );
54 
55 
56 /* PUBLIC FUNCTIONS ***********************************************************/
57 
58 bool
59 alarm_init()
60 {
61  if( !m_initialized )
62  {
63  if( heap_create_hid( (char*) m_name, &m_heap_id ) )
64  {
65  // Try to create the list for alarm storage
66  m_alarms = list_create( m_heap_id );
67 
68  // If this failed, the initialization failed
69  if(NULL != m_alarms)
70  {
71  m_initialized = true;
72  }
73  }
74  }
75 
76  return m_initialized;
77 }
78 
79 
80 void
81 alarm_reset()
82 {
83  list_destroy(m_alarms);
84 }
85 
86 
87 char *
88 alarm_name()
89 {
90  return (char*) m_name;
91 }
92 
93 
94 bool
95 alarm_set( uint_base_t a_time, signal_t a_signal )
96 {
97  bool is_set = false;
98  alarm_t *alarm = NULL;
99 
100  // Continue only if timer functionality is initialized
101  if(m_initialized)
102  {
103  // Create new alarm
104  alarm = alarm_create(a_time, a_signal, NULL);
105 
106  // Check if successful
107  if(NULL != alarm)
108  {
109  // Try to add the alarm
110  is_set = alarm_add(alarm);
111 
112  // If adding failed, there's no need to keep l_alarm, so destroy it.
113  if(!is_set)
114  {
115  heap_free(alarm);
116  }
117  }
118  }
119 
120  return is_set;
121 }
122 
123 
124 bool
125 alarm_set_cb(uint_base_t a_time, p_callback_func_t a_func)
126 {
127  bool is_set = false;
128  alarm_t *alarm = NULL;
129 
130  // Continue only if timer functionality is initialized
131  if(m_initialized)
132  {
133  // Create new alarm
134  alarm = alarm_create(a_time, 0, a_func);
135 
136  // Check if successful
137  if(NULL != alarm)
138  {
139  // Try to add the alarm
140  is_set = alarm_add(alarm);
141 
142  // If adding failed, there's no need to keep l_alarm, so destory it.
143  if(!is_set) heap_free(alarm);
144  }
145  }
146 
147  return is_set;
148 }
149 
150 
151 void
152 alarm_check_due()
153 {
154  tickstamp_t cur = {0,0};
155  list_item_t *item = NULL;
156  alarm_t *alarm = NULL;
157  bool is_done = false;
158 
159  // First check if there are alarms
160  if(m_initialized && (NULL != m_alarms))
161  {
162  // Get first item of the list
163  item = list_first_item(m_alarms);
164 
165  // Iterate through the list
166  while((NULL != item) && !is_done)
167  {
168  // Get the alarm-object
169  alarm = (alarm_t*) item->object;
170 
171  // Check if this alarm should go off now
172  tick_current(&cur);
173  if(abs(cur.tick - alarm->start.tick) >= alarm->delay)
174  {
175  // Emit signal or call callback function
176  if(alarm->signal > 0 ) signal_emit(alarm->signal);
177  if(alarm->cb_func != NULL ) alarm->cb_func();
178 
179  // Remove alarm from the list (and get next item automatically)
180  item = list_item_delete(m_alarms, item);
181  }
182  else
183  {
184  // No more alarms for now
185  is_done = true;
186  }
187  }
188  }
189 }
190 
191 
192 /* PRIVATE FUNCTION IMPLEMENTATION ********************************************/
193 alarm_t *
194 alarm_create(uint_base_t a_time, signal_t a_signal, p_callback_func_t a_func)
195 {
196  alarm_t *alarm = NULL;
197 
198  // Make sure the timer functionality is initialized
199  if(m_initialized)
200  {
201  alarm = heap_malloc(m_heap_id, sizeof(alarm_t));
202 
203  // Check if successful
204  if(NULL != alarm)
205  {
206  // Fill properties
207  tick_current( &(alarm->start) );
208  alarm->delay = a_time;
209  alarm->signal = a_signal;
210  alarm->cb_func = a_func;
211  }
212  }
213 
214  return alarm;
215 }
216 
217 
218 bool
219 alarm_add(alarm_t *a_alarm)
220 {
221  list_item_t *item = NULL;
222  list_item_t *item_new = NULL;
223  alarm_t *alarm = NULL;
224  bool is_added = false;
225 
226  // First check if there are alarms
227  if(m_initialized && (NULL != m_alarms))
228  {
229  // Get first item of the list
230  item = list_first_item(m_alarms);
231 
232  // Now create a new list item holding the alarm
233  item_new = list_item_create(m_alarms, (void*) a_alarm);
234 
235  // Continuing is only useful when new list item could be created
236  if(NULL != item_new)
237  {
238  // Iterate through the list
239  while(NULL != item)
240  {
241  // Get the alarm-object from the ADT-object
242  alarm = (alarm_t*) item->object;
243 
244  // Check if alarm in list goes off earlier than new one
245  if( alarm_ticks_till_due(alarm->start.tick, alarm->delay) <=
246  alarm_ticks_till_due(a_alarm->start.tick, a_alarm->delay) )
247  {
248  // Continue with next item on the list (if there are any)
249  item = item->next;
250  }
251  else
252  {
253  // The alarm we want to add goes off earlier than the current
254  // listed alarm, so insert new alarm just before this one
255  list_insert_before_item(m_alarms, item, item_new);
256 
257  // Break while-loop and return TRUE
258  is_added = true;
259  item = NULL;
260  }
261  }
262 
263  // Check if we're at the end of the list and haven't inserted the new
264  // alarm yet. If so, append it to the (empty) list.
265  if(!is_added)
266  {
267  list_append(m_alarms, item_new);
268  is_added = true;
269  }
270  }
271  }
272 
273  return is_added;
274 } // alarm_add()
275 
276 
277 uint_base_t
278 alarm_ticks_till_due(uint_base_t a_start_tick, uint_base_t a_delay)
279 {
280  tickstamp_t cur = {0,0};
281 
282  tick_current(&cur);
283 
284  return a_delay - abs(cur.tick - a_start_tick);
285 }