Initial commit

Dependencies:   FastPWM

Committer:
lypinator
Date:
Wed Sep 16 01:11:49 2020 +0000
Revision:
0:bb348c97df44
Added PWM

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lypinator 0:bb348c97df44 1 /* mbed Microcontroller Library
lypinator 0:bb348c97df44 2 * Copyright (c) 2015 ARM Limited
lypinator 0:bb348c97df44 3 *
lypinator 0:bb348c97df44 4 * Licensed under the Apache License, Version 2.0 (the "License");
lypinator 0:bb348c97df44 5 * you may not use this file except in compliance with the License.
lypinator 0:bb348c97df44 6 * You may obtain a copy of the License at
lypinator 0:bb348c97df44 7 *
lypinator 0:bb348c97df44 8 * http://www.apache.org/licenses/LICENSE-2.0
lypinator 0:bb348c97df44 9 *
lypinator 0:bb348c97df44 10 * Unless required by applicable law or agreed to in writing, software
lypinator 0:bb348c97df44 11 * distributed under the License is distributed on an "AS IS" BASIS,
lypinator 0:bb348c97df44 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
lypinator 0:bb348c97df44 13 * See the License for the specific language governing permissions and
lypinator 0:bb348c97df44 14 * limitations under the License.
lypinator 0:bb348c97df44 15 */
lypinator 0:bb348c97df44 16 #include <stdio.h>
lypinator 0:bb348c97df44 17 #include <stddef.h>
lypinator 0:bb348c97df44 18 #include "hal/ticker_api.h"
lypinator 0:bb348c97df44 19 #include "platform/mbed_critical.h"
lypinator 0:bb348c97df44 20 #include "mbed_assert.h"
lypinator 0:bb348c97df44 21
lypinator 0:bb348c97df44 22 static void schedule_interrupt(const ticker_data_t *const ticker);
lypinator 0:bb348c97df44 23 static void update_present_time(const ticker_data_t *const ticker);
lypinator 0:bb348c97df44 24
lypinator 0:bb348c97df44 25 /*
lypinator 0:bb348c97df44 26 * Initialize a ticker instance.
lypinator 0:bb348c97df44 27 */
lypinator 0:bb348c97df44 28 static void initialize(const ticker_data_t *ticker)
lypinator 0:bb348c97df44 29 {
lypinator 0:bb348c97df44 30 // return if the queue has already been initialized, in that case the
lypinator 0:bb348c97df44 31 // interface used by the queue is already initialized.
lypinator 0:bb348c97df44 32 if (ticker->queue->initialized) {
lypinator 0:bb348c97df44 33 return;
lypinator 0:bb348c97df44 34 }
lypinator 0:bb348c97df44 35
lypinator 0:bb348c97df44 36 ticker->interface->init();
lypinator 0:bb348c97df44 37
lypinator 0:bb348c97df44 38 const ticker_info_t *info = ticker->interface->get_info();
lypinator 0:bb348c97df44 39 uint32_t frequency = info->frequency;
lypinator 0:bb348c97df44 40 if (info->frequency == 0) {
lypinator 0:bb348c97df44 41 MBED_ASSERT(0);
lypinator 0:bb348c97df44 42 frequency = 1000000;
lypinator 0:bb348c97df44 43 }
lypinator 0:bb348c97df44 44
lypinator 0:bb348c97df44 45 uint8_t frequency_shifts = 0;
lypinator 0:bb348c97df44 46 for (uint8_t i = 31; i > 0; --i) {
lypinator 0:bb348c97df44 47 if ((1 << i) == frequency) {
lypinator 0:bb348c97df44 48 frequency_shifts = i;
lypinator 0:bb348c97df44 49 break;
lypinator 0:bb348c97df44 50 }
lypinator 0:bb348c97df44 51 }
lypinator 0:bb348c97df44 52
lypinator 0:bb348c97df44 53 uint32_t bits = info->bits;
lypinator 0:bb348c97df44 54 if ((info->bits > 32) || (info->bits < 4)) {
lypinator 0:bb348c97df44 55 MBED_ASSERT(0);
lypinator 0:bb348c97df44 56 bits = 32;
lypinator 0:bb348c97df44 57 }
lypinator 0:bb348c97df44 58 uint32_t max_delta = 0x7 << (bits - 4); // 7/16th
lypinator 0:bb348c97df44 59 uint64_t max_delta_us =
lypinator 0:bb348c97df44 60 ((uint64_t)max_delta * 1000000 + frequency - 1) / frequency;
lypinator 0:bb348c97df44 61
lypinator 0:bb348c97df44 62 ticker->queue->event_handler = NULL;
lypinator 0:bb348c97df44 63 ticker->queue->head = NULL;
lypinator 0:bb348c97df44 64 ticker->queue->tick_last_read = ticker->interface->read();
lypinator 0:bb348c97df44 65 ticker->queue->tick_remainder = 0;
lypinator 0:bb348c97df44 66 ticker->queue->frequency = frequency;
lypinator 0:bb348c97df44 67 ticker->queue->frequency_shifts = frequency_shifts;
lypinator 0:bb348c97df44 68 ticker->queue->bitmask = ((uint64_t)1 << bits) - 1;
lypinator 0:bb348c97df44 69 ticker->queue->max_delta = max_delta;
lypinator 0:bb348c97df44 70 ticker->queue->max_delta_us = max_delta_us;
lypinator 0:bb348c97df44 71 ticker->queue->present_time = 0;
lypinator 0:bb348c97df44 72 ticker->queue->dispatching = false;
lypinator 0:bb348c97df44 73 ticker->queue->initialized = true;
lypinator 0:bb348c97df44 74
lypinator 0:bb348c97df44 75 update_present_time(ticker);
lypinator 0:bb348c97df44 76 schedule_interrupt(ticker);
lypinator 0:bb348c97df44 77 }
lypinator 0:bb348c97df44 78
lypinator 0:bb348c97df44 79 /**
lypinator 0:bb348c97df44 80 * Set the event handler function of a ticker instance.
lypinator 0:bb348c97df44 81 */
lypinator 0:bb348c97df44 82 static void set_handler(const ticker_data_t *const ticker, ticker_event_handler handler)
lypinator 0:bb348c97df44 83 {
lypinator 0:bb348c97df44 84 ticker->queue->event_handler = handler;
lypinator 0:bb348c97df44 85 }
lypinator 0:bb348c97df44 86
lypinator 0:bb348c97df44 87 /*
lypinator 0:bb348c97df44 88 * Convert a 32 bit timestamp into a 64 bit timestamp.
lypinator 0:bb348c97df44 89 *
lypinator 0:bb348c97df44 90 * A 64 bit timestamp is used as the point of time of reference while the
lypinator 0:bb348c97df44 91 * timestamp to convert is relative to this point of time.
lypinator 0:bb348c97df44 92 *
lypinator 0:bb348c97df44 93 * The lower 32 bits of the timestamp returned will be equal to the timestamp to
lypinator 0:bb348c97df44 94 * convert.
lypinator 0:bb348c97df44 95 *
lypinator 0:bb348c97df44 96 * If the timestamp to convert is less than the lower 32 bits of the time
lypinator 0:bb348c97df44 97 * reference then the timestamp to convert is seen as an overflowed value and
lypinator 0:bb348c97df44 98 * the upper 32 bit of the timestamp returned will be equal to the upper 32 bit
lypinator 0:bb348c97df44 99 * of the reference point + 1.
lypinator 0:bb348c97df44 100 * Otherwise, the upper 32 bit returned will be equal to the upper 32 bit of the
lypinator 0:bb348c97df44 101 * reference point.
lypinator 0:bb348c97df44 102 *
lypinator 0:bb348c97df44 103 * @param ref: The 64 bit timestamp of reference.
lypinator 0:bb348c97df44 104 * @param timestamp: The timestamp to convert.
lypinator 0:bb348c97df44 105 */
lypinator 0:bb348c97df44 106 static us_timestamp_t convert_timestamp(us_timestamp_t ref, timestamp_t timestamp)
lypinator 0:bb348c97df44 107 {
lypinator 0:bb348c97df44 108 bool overflow = timestamp < ((timestamp_t) ref) ? true : false;
lypinator 0:bb348c97df44 109
lypinator 0:bb348c97df44 110 us_timestamp_t result = (ref & ~((us_timestamp_t)UINT32_MAX)) | timestamp;
lypinator 0:bb348c97df44 111 if (overflow) {
lypinator 0:bb348c97df44 112 result += (1ULL << 32);
lypinator 0:bb348c97df44 113 }
lypinator 0:bb348c97df44 114
lypinator 0:bb348c97df44 115 return result;
lypinator 0:bb348c97df44 116 }
lypinator 0:bb348c97df44 117
lypinator 0:bb348c97df44 118 /**
lypinator 0:bb348c97df44 119 * Update the present timestamp value of a ticker.
lypinator 0:bb348c97df44 120 */
lypinator 0:bb348c97df44 121 static void update_present_time(const ticker_data_t *const ticker)
lypinator 0:bb348c97df44 122 {
lypinator 0:bb348c97df44 123 ticker_event_queue_t *queue = ticker->queue;
lypinator 0:bb348c97df44 124 uint32_t ticker_time = ticker->interface->read();
lypinator 0:bb348c97df44 125 if (ticker_time == ticker->queue->tick_last_read) {
lypinator 0:bb348c97df44 126 // No work to do
lypinator 0:bb348c97df44 127 return;
lypinator 0:bb348c97df44 128 }
lypinator 0:bb348c97df44 129
lypinator 0:bb348c97df44 130 uint64_t elapsed_ticks = (ticker_time - queue->tick_last_read) & queue->bitmask;
lypinator 0:bb348c97df44 131 queue->tick_last_read = ticker_time;
lypinator 0:bb348c97df44 132
lypinator 0:bb348c97df44 133 uint64_t elapsed_us;
lypinator 0:bb348c97df44 134 if (1000000 == queue->frequency) {
lypinator 0:bb348c97df44 135 // Optimized for 1MHz
lypinator 0:bb348c97df44 136
lypinator 0:bb348c97df44 137 elapsed_us = elapsed_ticks;
lypinator 0:bb348c97df44 138 } else if (0 != queue->frequency_shifts) {
lypinator 0:bb348c97df44 139 // Optimized for frequencies divisible by 2
lypinator 0:bb348c97df44 140 uint64_t us_x_ticks = elapsed_ticks * 1000000;
lypinator 0:bb348c97df44 141 elapsed_us = us_x_ticks >> queue->frequency_shifts;
lypinator 0:bb348c97df44 142
lypinator 0:bb348c97df44 143 // Update remainder
lypinator 0:bb348c97df44 144 queue->tick_remainder += us_x_ticks - (elapsed_us << queue->frequency_shifts);
lypinator 0:bb348c97df44 145 if (queue->tick_remainder >= queue->frequency) {
lypinator 0:bb348c97df44 146 elapsed_us += 1;
lypinator 0:bb348c97df44 147 queue->tick_remainder -= queue->frequency;
lypinator 0:bb348c97df44 148 }
lypinator 0:bb348c97df44 149 } else {
lypinator 0:bb348c97df44 150 // General case
lypinator 0:bb348c97df44 151
lypinator 0:bb348c97df44 152 uint64_t us_x_ticks = elapsed_ticks * 1000000;
lypinator 0:bb348c97df44 153 elapsed_us = us_x_ticks / queue->frequency;
lypinator 0:bb348c97df44 154
lypinator 0:bb348c97df44 155 // Update remainder
lypinator 0:bb348c97df44 156 queue->tick_remainder += us_x_ticks - elapsed_us * queue->frequency;
lypinator 0:bb348c97df44 157 if (queue->tick_remainder >= queue->frequency) {
lypinator 0:bb348c97df44 158 elapsed_us += 1;
lypinator 0:bb348c97df44 159 queue->tick_remainder -= queue->frequency;
lypinator 0:bb348c97df44 160 }
lypinator 0:bb348c97df44 161 }
lypinator 0:bb348c97df44 162
lypinator 0:bb348c97df44 163 // Update current time
lypinator 0:bb348c97df44 164 queue->present_time += elapsed_us;
lypinator 0:bb348c97df44 165 }
lypinator 0:bb348c97df44 166
lypinator 0:bb348c97df44 167 /**
lypinator 0:bb348c97df44 168 * Given the absolute timestamp compute the hal tick timestamp.
lypinator 0:bb348c97df44 169 */
lypinator 0:bb348c97df44 170 static timestamp_t compute_tick(const ticker_data_t *const ticker, us_timestamp_t timestamp)
lypinator 0:bb348c97df44 171 {
lypinator 0:bb348c97df44 172 ticker_event_queue_t *queue = ticker->queue;
lypinator 0:bb348c97df44 173 us_timestamp_t delta_us = timestamp - queue->present_time;
lypinator 0:bb348c97df44 174
lypinator 0:bb348c97df44 175 timestamp_t delta = ticker->queue->max_delta;
lypinator 0:bb348c97df44 176 if (delta_us <= ticker->queue->max_delta_us) {
lypinator 0:bb348c97df44 177 // Checking max_delta_us ensures the operation will not overflow
lypinator 0:bb348c97df44 178
lypinator 0:bb348c97df44 179 if (1000000 == queue->frequency) {
lypinator 0:bb348c97df44 180 // Optimized for 1MHz
lypinator 0:bb348c97df44 181
lypinator 0:bb348c97df44 182 delta = delta_us;
lypinator 0:bb348c97df44 183 if (delta > ticker->queue->max_delta) {
lypinator 0:bb348c97df44 184 delta = ticker->queue->max_delta;
lypinator 0:bb348c97df44 185 }
lypinator 0:bb348c97df44 186 } else if (0 != queue->frequency_shifts) {
lypinator 0:bb348c97df44 187 // Optimized frequencies divisible by 2
lypinator 0:bb348c97df44 188
lypinator 0:bb348c97df44 189 delta = (delta_us << ticker->queue->frequency_shifts) / 1000000;
lypinator 0:bb348c97df44 190 if (delta > ticker->queue->max_delta) {
lypinator 0:bb348c97df44 191 delta = ticker->queue->max_delta;
lypinator 0:bb348c97df44 192 }
lypinator 0:bb348c97df44 193 } else {
lypinator 0:bb348c97df44 194 // General case
lypinator 0:bb348c97df44 195
lypinator 0:bb348c97df44 196 delta = delta_us * queue->frequency / 1000000;
lypinator 0:bb348c97df44 197 if (delta > ticker->queue->max_delta) {
lypinator 0:bb348c97df44 198 delta = ticker->queue->max_delta;
lypinator 0:bb348c97df44 199 }
lypinator 0:bb348c97df44 200 }
lypinator 0:bb348c97df44 201 }
lypinator 0:bb348c97df44 202 return (queue->tick_last_read + delta) & queue->bitmask;
lypinator 0:bb348c97df44 203 }
lypinator 0:bb348c97df44 204
lypinator 0:bb348c97df44 205 /**
lypinator 0:bb348c97df44 206 * Return 1 if the tick has incremented to or past match_tick, otherwise 0.
lypinator 0:bb348c97df44 207 */
lypinator 0:bb348c97df44 208 int _ticker_match_interval_passed(timestamp_t prev_tick, timestamp_t cur_tick, timestamp_t match_tick)
lypinator 0:bb348c97df44 209 {
lypinator 0:bb348c97df44 210 if (match_tick > prev_tick) {
lypinator 0:bb348c97df44 211 return (cur_tick >= match_tick) || (cur_tick < prev_tick);
lypinator 0:bb348c97df44 212 } else {
lypinator 0:bb348c97df44 213 return (cur_tick < prev_tick) && (cur_tick >= match_tick);
lypinator 0:bb348c97df44 214 }
lypinator 0:bb348c97df44 215 }
lypinator 0:bb348c97df44 216
lypinator 0:bb348c97df44 217 /**
lypinator 0:bb348c97df44 218 * Compute the time when the interrupt has to be triggered and schedule it.
lypinator 0:bb348c97df44 219 *
lypinator 0:bb348c97df44 220 * If there is no event in the queue or the next event to execute is in more
lypinator 0:bb348c97df44 221 * than ticker.queue.max_delta ticks from now then the ticker irq will be
lypinator 0:bb348c97df44 222 * scheduled in ticker.queue.max_delta ticks. Otherwise the irq will be
lypinator 0:bb348c97df44 223 * scheduled to happen when the running counter reach the timestamp of the
lypinator 0:bb348c97df44 224 * first event in the queue.
lypinator 0:bb348c97df44 225 *
lypinator 0:bb348c97df44 226 * @note If there is no event in the queue then the interrupt is scheduled to
lypinator 0:bb348c97df44 227 * in ticker.queue.max_delta. This is necessary to keep track
lypinator 0:bb348c97df44 228 * of the timer overflow.
lypinator 0:bb348c97df44 229 */
lypinator 0:bb348c97df44 230 static void schedule_interrupt(const ticker_data_t *const ticker)
lypinator 0:bb348c97df44 231 {
lypinator 0:bb348c97df44 232 ticker_event_queue_t *queue = ticker->queue;
lypinator 0:bb348c97df44 233 if (ticker->queue->dispatching) {
lypinator 0:bb348c97df44 234 // Don't schedule the next interrupt until dispatching is
lypinator 0:bb348c97df44 235 // finished. This prevents repeated calls to interface->set_interrupt
lypinator 0:bb348c97df44 236 return;
lypinator 0:bb348c97df44 237 }
lypinator 0:bb348c97df44 238
lypinator 0:bb348c97df44 239 update_present_time(ticker);
lypinator 0:bb348c97df44 240
lypinator 0:bb348c97df44 241 if (ticker->queue->head) {
lypinator 0:bb348c97df44 242 us_timestamp_t present = ticker->queue->present_time;
lypinator 0:bb348c97df44 243 us_timestamp_t match_time = ticker->queue->head->timestamp;
lypinator 0:bb348c97df44 244
lypinator 0:bb348c97df44 245 // if the event at the head of the queue is in the past then schedule
lypinator 0:bb348c97df44 246 // it immediately.
lypinator 0:bb348c97df44 247 if (match_time <= present) {
lypinator 0:bb348c97df44 248 ticker->interface->fire_interrupt();
lypinator 0:bb348c97df44 249 return;
lypinator 0:bb348c97df44 250 }
lypinator 0:bb348c97df44 251
lypinator 0:bb348c97df44 252 timestamp_t match_tick = compute_tick(ticker, match_time);
lypinator 0:bb348c97df44 253 // The time has been checked to be future, but it could still round
lypinator 0:bb348c97df44 254 // to the last tick as a result of us to ticks conversion
lypinator 0:bb348c97df44 255 if (match_tick == queue->tick_last_read) {
lypinator 0:bb348c97df44 256 // Match time has already expired so fire immediately
lypinator 0:bb348c97df44 257 ticker->interface->fire_interrupt();
lypinator 0:bb348c97df44 258 return;
lypinator 0:bb348c97df44 259 }
lypinator 0:bb348c97df44 260
lypinator 0:bb348c97df44 261 ticker->interface->set_interrupt(match_tick);
lypinator 0:bb348c97df44 262 timestamp_t cur_tick = ticker->interface->read();
lypinator 0:bb348c97df44 263
lypinator 0:bb348c97df44 264 if (_ticker_match_interval_passed(queue->tick_last_read, cur_tick, match_tick)) {
lypinator 0:bb348c97df44 265 ticker->interface->fire_interrupt();
lypinator 0:bb348c97df44 266 }
lypinator 0:bb348c97df44 267 } else {
lypinator 0:bb348c97df44 268 uint32_t match_tick =
lypinator 0:bb348c97df44 269 (queue->tick_last_read + queue->max_delta) & queue->bitmask;
lypinator 0:bb348c97df44 270 ticker->interface->set_interrupt(match_tick);
lypinator 0:bb348c97df44 271 }
lypinator 0:bb348c97df44 272 }
lypinator 0:bb348c97df44 273
lypinator 0:bb348c97df44 274 void ticker_set_handler(const ticker_data_t *const ticker, ticker_event_handler handler)
lypinator 0:bb348c97df44 275 {
lypinator 0:bb348c97df44 276 initialize(ticker);
lypinator 0:bb348c97df44 277
lypinator 0:bb348c97df44 278 core_util_critical_section_enter();
lypinator 0:bb348c97df44 279 set_handler(ticker, handler);
lypinator 0:bb348c97df44 280 core_util_critical_section_exit();
lypinator 0:bb348c97df44 281 }
lypinator 0:bb348c97df44 282
lypinator 0:bb348c97df44 283 void ticker_irq_handler(const ticker_data_t *const ticker)
lypinator 0:bb348c97df44 284 {
lypinator 0:bb348c97df44 285 core_util_critical_section_enter();
lypinator 0:bb348c97df44 286
lypinator 0:bb348c97df44 287 ticker->interface->clear_interrupt();
lypinator 0:bb348c97df44 288
lypinator 0:bb348c97df44 289 /* Go through all the pending TimerEvents */
lypinator 0:bb348c97df44 290 ticker->queue->dispatching = true;
lypinator 0:bb348c97df44 291 while (1) {
lypinator 0:bb348c97df44 292 if (ticker->queue->head == NULL) {
lypinator 0:bb348c97df44 293 break;
lypinator 0:bb348c97df44 294 }
lypinator 0:bb348c97df44 295
lypinator 0:bb348c97df44 296 // update the current timestamp used by the queue
lypinator 0:bb348c97df44 297 update_present_time(ticker);
lypinator 0:bb348c97df44 298
lypinator 0:bb348c97df44 299 if (ticker->queue->head->timestamp <= ticker->queue->present_time) {
lypinator 0:bb348c97df44 300 // This event was in the past:
lypinator 0:bb348c97df44 301 // point to the following one and execute its handler
lypinator 0:bb348c97df44 302 ticker_event_t *p = ticker->queue->head;
lypinator 0:bb348c97df44 303 ticker->queue->head = ticker->queue->head->next;
lypinator 0:bb348c97df44 304 if (ticker->queue->event_handler != NULL) {
lypinator 0:bb348c97df44 305 (*ticker->queue->event_handler)(p->id); // NOTE: the handler can set new events
lypinator 0:bb348c97df44 306 }
lypinator 0:bb348c97df44 307 /* Note: We continue back to examining the head because calling the
lypinator 0:bb348c97df44 308 * event handler may have altered the chain of pending events. */
lypinator 0:bb348c97df44 309 } else {
lypinator 0:bb348c97df44 310 break;
lypinator 0:bb348c97df44 311 }
lypinator 0:bb348c97df44 312 }
lypinator 0:bb348c97df44 313 ticker->queue->dispatching = false;
lypinator 0:bb348c97df44 314
lypinator 0:bb348c97df44 315 schedule_interrupt(ticker);
lypinator 0:bb348c97df44 316
lypinator 0:bb348c97df44 317 core_util_critical_section_exit();
lypinator 0:bb348c97df44 318 }
lypinator 0:bb348c97df44 319
lypinator 0:bb348c97df44 320 void ticker_insert_event(const ticker_data_t *const ticker, ticker_event_t *obj, timestamp_t timestamp, uint32_t id)
lypinator 0:bb348c97df44 321 {
lypinator 0:bb348c97df44 322 core_util_critical_section_enter();
lypinator 0:bb348c97df44 323
lypinator 0:bb348c97df44 324 // update the current timestamp
lypinator 0:bb348c97df44 325 update_present_time(ticker);
lypinator 0:bb348c97df44 326 us_timestamp_t absolute_timestamp = convert_timestamp(
lypinator 0:bb348c97df44 327 ticker->queue->present_time,
lypinator 0:bb348c97df44 328 timestamp
lypinator 0:bb348c97df44 329 );
lypinator 0:bb348c97df44 330
lypinator 0:bb348c97df44 331 // defer to ticker_insert_event_us
lypinator 0:bb348c97df44 332 ticker_insert_event_us(
lypinator 0:bb348c97df44 333 ticker,
lypinator 0:bb348c97df44 334 obj, absolute_timestamp, id
lypinator 0:bb348c97df44 335 );
lypinator 0:bb348c97df44 336
lypinator 0:bb348c97df44 337 core_util_critical_section_exit();
lypinator 0:bb348c97df44 338 }
lypinator 0:bb348c97df44 339
lypinator 0:bb348c97df44 340 void ticker_insert_event_us(const ticker_data_t *const ticker, ticker_event_t *obj, us_timestamp_t timestamp, uint32_t id)
lypinator 0:bb348c97df44 341 {
lypinator 0:bb348c97df44 342 core_util_critical_section_enter();
lypinator 0:bb348c97df44 343
lypinator 0:bb348c97df44 344 // update the current timestamp
lypinator 0:bb348c97df44 345 update_present_time(ticker);
lypinator 0:bb348c97df44 346
lypinator 0:bb348c97df44 347 // initialise our data
lypinator 0:bb348c97df44 348 obj->timestamp = timestamp;
lypinator 0:bb348c97df44 349 obj->id = id;
lypinator 0:bb348c97df44 350
lypinator 0:bb348c97df44 351 /* Go through the list until we either reach the end, or find
lypinator 0:bb348c97df44 352 an element this should come before (which is possibly the
lypinator 0:bb348c97df44 353 head). */
lypinator 0:bb348c97df44 354 ticker_event_t *prev = NULL, *p = ticker->queue->head;
lypinator 0:bb348c97df44 355 while (p != NULL) {
lypinator 0:bb348c97df44 356 /* check if we come before p */
lypinator 0:bb348c97df44 357 if (timestamp < p->timestamp) {
lypinator 0:bb348c97df44 358 break;
lypinator 0:bb348c97df44 359 }
lypinator 0:bb348c97df44 360 /* go to the next element */
lypinator 0:bb348c97df44 361 prev = p;
lypinator 0:bb348c97df44 362 p = p->next;
lypinator 0:bb348c97df44 363 }
lypinator 0:bb348c97df44 364
lypinator 0:bb348c97df44 365 /* if we're at the end p will be NULL, which is correct */
lypinator 0:bb348c97df44 366 obj->next = p;
lypinator 0:bb348c97df44 367
lypinator 0:bb348c97df44 368 /* if prev is NULL we're at the head */
lypinator 0:bb348c97df44 369 if (prev == NULL) {
lypinator 0:bb348c97df44 370 ticker->queue->head = obj;
lypinator 0:bb348c97df44 371 schedule_interrupt(ticker);
lypinator 0:bb348c97df44 372 } else {
lypinator 0:bb348c97df44 373 prev->next = obj;
lypinator 0:bb348c97df44 374 }
lypinator 0:bb348c97df44 375
lypinator 0:bb348c97df44 376 core_util_critical_section_exit();
lypinator 0:bb348c97df44 377 }
lypinator 0:bb348c97df44 378
lypinator 0:bb348c97df44 379 void ticker_remove_event(const ticker_data_t *const ticker, ticker_event_t *obj)
lypinator 0:bb348c97df44 380 {
lypinator 0:bb348c97df44 381 core_util_critical_section_enter();
lypinator 0:bb348c97df44 382
lypinator 0:bb348c97df44 383 // remove this object from the list
lypinator 0:bb348c97df44 384 if (ticker->queue->head == obj) {
lypinator 0:bb348c97df44 385 // first in the list, so just drop me
lypinator 0:bb348c97df44 386 ticker->queue->head = obj->next;
lypinator 0:bb348c97df44 387 schedule_interrupt(ticker);
lypinator 0:bb348c97df44 388 } else {
lypinator 0:bb348c97df44 389 // find the object before me, then drop me
lypinator 0:bb348c97df44 390 ticker_event_t *p = ticker->queue->head;
lypinator 0:bb348c97df44 391 while (p != NULL) {
lypinator 0:bb348c97df44 392 if (p->next == obj) {
lypinator 0:bb348c97df44 393 p->next = obj->next;
lypinator 0:bb348c97df44 394 break;
lypinator 0:bb348c97df44 395 }
lypinator 0:bb348c97df44 396 p = p->next;
lypinator 0:bb348c97df44 397 }
lypinator 0:bb348c97df44 398 }
lypinator 0:bb348c97df44 399
lypinator 0:bb348c97df44 400 core_util_critical_section_exit();
lypinator 0:bb348c97df44 401 }
lypinator 0:bb348c97df44 402
lypinator 0:bb348c97df44 403 timestamp_t ticker_read(const ticker_data_t *const ticker)
lypinator 0:bb348c97df44 404 {
lypinator 0:bb348c97df44 405 return ticker_read_us(ticker);
lypinator 0:bb348c97df44 406 }
lypinator 0:bb348c97df44 407
lypinator 0:bb348c97df44 408 us_timestamp_t ticker_read_us(const ticker_data_t *const ticker)
lypinator 0:bb348c97df44 409 {
lypinator 0:bb348c97df44 410 initialize(ticker);
lypinator 0:bb348c97df44 411
lypinator 0:bb348c97df44 412 core_util_critical_section_enter();
lypinator 0:bb348c97df44 413 update_present_time(ticker);
lypinator 0:bb348c97df44 414 core_util_critical_section_exit();
lypinator 0:bb348c97df44 415
lypinator 0:bb348c97df44 416 return ticker->queue->present_time;
lypinator 0:bb348c97df44 417 }
lypinator 0:bb348c97df44 418
lypinator 0:bb348c97df44 419 int ticker_get_next_timestamp(const ticker_data_t *const data, timestamp_t *timestamp)
lypinator 0:bb348c97df44 420 {
lypinator 0:bb348c97df44 421 int ret = 0;
lypinator 0:bb348c97df44 422
lypinator 0:bb348c97df44 423 /* if head is NULL, there are no pending events */
lypinator 0:bb348c97df44 424 core_util_critical_section_enter();
lypinator 0:bb348c97df44 425 if (data->queue->head != NULL) {
lypinator 0:bb348c97df44 426 *timestamp = data->queue->head->timestamp;
lypinator 0:bb348c97df44 427 ret = 1;
lypinator 0:bb348c97df44 428 }
lypinator 0:bb348c97df44 429 core_util_critical_section_exit();
lypinator 0:bb348c97df44 430
lypinator 0:bb348c97df44 431 return ret;
lypinator 0:bb348c97df44 432 }