the do / gr-peach-opencv-project

Fork of gr-peach-opencv-project by the do

Committer:
thedo
Date:
Thu Jun 29 11:01:39 2017 +0000
Revision:
167:1657b442184c
Opencv 3.1 project on GR-PEACH board, 4 apps

Who changed what in which revision?

UserRevisionLine numberNew contents of line
thedo 167:1657b442184c 1 /* mbed Microcontroller Library
thedo 167:1657b442184c 2 * Copyright (c) 2015 ARM Limited
thedo 167:1657b442184c 3 *
thedo 167:1657b442184c 4 * Licensed under the Apache License, Version 2.0 (the "License");
thedo 167:1657b442184c 5 * you may not use this file except in compliance with the License.
thedo 167:1657b442184c 6 * You may obtain a copy of the License at
thedo 167:1657b442184c 7 *
thedo 167:1657b442184c 8 * http://www.apache.org/licenses/LICENSE-2.0
thedo 167:1657b442184c 9 *
thedo 167:1657b442184c 10 * Unless required by applicable law or agreed to in writing, software
thedo 167:1657b442184c 11 * distributed under the License is distributed on an "AS IS" BASIS,
thedo 167:1657b442184c 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
thedo 167:1657b442184c 13 * See the License for the specific language governing permissions and
thedo 167:1657b442184c 14 * limitations under the License.
thedo 167:1657b442184c 15 */
thedo 167:1657b442184c 16 #include <stdio.h>
thedo 167:1657b442184c 17 #include <stddef.h>
thedo 167:1657b442184c 18 #include "hal/ticker_api.h"
thedo 167:1657b442184c 19 #include "platform/mbed_critical.h"
thedo 167:1657b442184c 20
thedo 167:1657b442184c 21 static void schedule_interrupt(const ticker_data_t *const ticker);
thedo 167:1657b442184c 22 static void update_present_time(const ticker_data_t *const ticker);
thedo 167:1657b442184c 23
thedo 167:1657b442184c 24 /*
thedo 167:1657b442184c 25 * Initialize a ticker instance.
thedo 167:1657b442184c 26 */
thedo 167:1657b442184c 27 static void initialize(const ticker_data_t *ticker)
thedo 167:1657b442184c 28 {
thedo 167:1657b442184c 29 // return if the queue has already been initialized, in that case the
thedo 167:1657b442184c 30 // interface used by the queue is already initialized.
thedo 167:1657b442184c 31 if (ticker->queue->initialized) {
thedo 167:1657b442184c 32 return;
thedo 167:1657b442184c 33 }
thedo 167:1657b442184c 34
thedo 167:1657b442184c 35 ticker->interface->init();
thedo 167:1657b442184c 36
thedo 167:1657b442184c 37 ticker->queue->event_handler = NULL;
thedo 167:1657b442184c 38 ticker->queue->head = NULL;
thedo 167:1657b442184c 39 ticker->queue->present_time = 0;
thedo 167:1657b442184c 40 ticker->queue->initialized = true;
thedo 167:1657b442184c 41
thedo 167:1657b442184c 42 update_present_time(ticker);
thedo 167:1657b442184c 43 schedule_interrupt(ticker);
thedo 167:1657b442184c 44 }
thedo 167:1657b442184c 45
thedo 167:1657b442184c 46 /**
thedo 167:1657b442184c 47 * Set the event handler function of a ticker instance.
thedo 167:1657b442184c 48 */
thedo 167:1657b442184c 49 static void set_handler(const ticker_data_t *const ticker, ticker_event_handler handler)
thedo 167:1657b442184c 50 {
thedo 167:1657b442184c 51 ticker->queue->event_handler = handler;
thedo 167:1657b442184c 52 }
thedo 167:1657b442184c 53
thedo 167:1657b442184c 54 /*
thedo 167:1657b442184c 55 * Convert a 32 bit timestamp into a 64 bit timestamp.
thedo 167:1657b442184c 56 *
thedo 167:1657b442184c 57 * A 64 bit timestamp is used as the point of time of reference while the
thedo 167:1657b442184c 58 * timestamp to convert is relative to this point of time.
thedo 167:1657b442184c 59 *
thedo 167:1657b442184c 60 * The lower 32 bits of the timestamp returned will be equal to the timestamp to
thedo 167:1657b442184c 61 * convert.
thedo 167:1657b442184c 62 *
thedo 167:1657b442184c 63 * If the timestamp to convert is less than the lower 32 bits of the time
thedo 167:1657b442184c 64 * reference then the timestamp to convert is seen as an overflowed value and
thedo 167:1657b442184c 65 * the upper 32 bit of the timestamp returned will be equal to the upper 32 bit
thedo 167:1657b442184c 66 * of the reference point + 1.
thedo 167:1657b442184c 67 * Otherwise, the upper 32 bit returned will be equal to the upper 32 bit of the
thedo 167:1657b442184c 68 * reference point.
thedo 167:1657b442184c 69 *
thedo 167:1657b442184c 70 * @param ref: The 64 bit timestamp of reference.
thedo 167:1657b442184c 71 * @param timestamp: The timestamp to convert.
thedo 167:1657b442184c 72 */
thedo 167:1657b442184c 73 static us_timestamp_t convert_timestamp(us_timestamp_t ref, timestamp_t timestamp)
thedo 167:1657b442184c 74 {
thedo 167:1657b442184c 75 bool overflow = timestamp < ((timestamp_t) ref) ? true : false;
thedo 167:1657b442184c 76
thedo 167:1657b442184c 77 us_timestamp_t result = (ref & ~((us_timestamp_t)UINT32_MAX)) | timestamp;
thedo 167:1657b442184c 78 if (overflow) {
thedo 167:1657b442184c 79 result += (1ULL<<32);
thedo 167:1657b442184c 80 }
thedo 167:1657b442184c 81
thedo 167:1657b442184c 82 return result;
thedo 167:1657b442184c 83 }
thedo 167:1657b442184c 84
thedo 167:1657b442184c 85 /**
thedo 167:1657b442184c 86 * Update the present timestamp value of a ticker.
thedo 167:1657b442184c 87 */
thedo 167:1657b442184c 88 static void update_present_time(const ticker_data_t *const ticker)
thedo 167:1657b442184c 89 {
thedo 167:1657b442184c 90 ticker->queue->present_time = convert_timestamp(
thedo 167:1657b442184c 91 ticker->queue->present_time,
thedo 167:1657b442184c 92 ticker->interface->read()
thedo 167:1657b442184c 93 );
thedo 167:1657b442184c 94 }
thedo 167:1657b442184c 95
thedo 167:1657b442184c 96 /**
thedo 167:1657b442184c 97 * Compute the time when the interrupt has to be triggered and schedule it.
thedo 167:1657b442184c 98 *
thedo 167:1657b442184c 99 * If there is no event in the queue or the next event to execute is in more
thedo 167:1657b442184c 100 * than MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA us from now then the ticker
thedo 167:1657b442184c 101 * irq will be scheduled in MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA us.
thedo 167:1657b442184c 102 * Otherwise the irq will be scheduled to happen when the running counter reach
thedo 167:1657b442184c 103 * the timestamp of the first event in the queue.
thedo 167:1657b442184c 104 *
thedo 167:1657b442184c 105 * @note If there is no event in the queue then the interrupt is scheduled to
thedo 167:1657b442184c 106 * in MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA. This is necessary to keep track
thedo 167:1657b442184c 107 * of the timer overflow.
thedo 167:1657b442184c 108 */
thedo 167:1657b442184c 109 static void schedule_interrupt(const ticker_data_t *const ticker)
thedo 167:1657b442184c 110 {
thedo 167:1657b442184c 111 update_present_time(ticker);
thedo 167:1657b442184c 112 uint32_t relative_timeout = MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA;
thedo 167:1657b442184c 113
thedo 167:1657b442184c 114 if (ticker->queue->head) {
thedo 167:1657b442184c 115 us_timestamp_t present = ticker->queue->present_time;
thedo 167:1657b442184c 116 us_timestamp_t next_event_timestamp = ticker->queue->head->timestamp;
thedo 167:1657b442184c 117
thedo 167:1657b442184c 118 // if the event at the head of the queue is in the past then schedule
thedo 167:1657b442184c 119 // it immediately.
thedo 167:1657b442184c 120 if (next_event_timestamp < present) {
thedo 167:1657b442184c 121 relative_timeout = 0;
thedo 167:1657b442184c 122 } else if ((next_event_timestamp - present) < MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA) {
thedo 167:1657b442184c 123 relative_timeout = next_event_timestamp - present;
thedo 167:1657b442184c 124 }
thedo 167:1657b442184c 125 }
thedo 167:1657b442184c 126
thedo 167:1657b442184c 127 ticker->interface->set_interrupt(ticker->queue->present_time + relative_timeout);
thedo 167:1657b442184c 128 }
thedo 167:1657b442184c 129
thedo 167:1657b442184c 130 void ticker_set_handler(const ticker_data_t *const ticker, ticker_event_handler handler)
thedo 167:1657b442184c 131 {
thedo 167:1657b442184c 132 initialize(ticker);
thedo 167:1657b442184c 133 set_handler(ticker, handler);
thedo 167:1657b442184c 134 }
thedo 167:1657b442184c 135
thedo 167:1657b442184c 136 void ticker_irq_handler(const ticker_data_t *const ticker)
thedo 167:1657b442184c 137 {
thedo 167:1657b442184c 138 ticker->interface->clear_interrupt();
thedo 167:1657b442184c 139
thedo 167:1657b442184c 140 /* Go through all the pending TimerEvents */
thedo 167:1657b442184c 141 while (1) {
thedo 167:1657b442184c 142 if (ticker->queue->head == NULL) {
thedo 167:1657b442184c 143 break;
thedo 167:1657b442184c 144 }
thedo 167:1657b442184c 145
thedo 167:1657b442184c 146 // update the current timestamp used by the queue
thedo 167:1657b442184c 147 update_present_time(ticker);
thedo 167:1657b442184c 148
thedo 167:1657b442184c 149 if (ticker->queue->head->timestamp <= ticker->queue->present_time) {
thedo 167:1657b442184c 150 // This event was in the past:
thedo 167:1657b442184c 151 // point to the following one and execute its handler
thedo 167:1657b442184c 152 ticker_event_t *p = ticker->queue->head;
thedo 167:1657b442184c 153 ticker->queue->head = ticker->queue->head->next;
thedo 167:1657b442184c 154 if (ticker->queue->event_handler != NULL) {
thedo 167:1657b442184c 155 (*ticker->queue->event_handler)(p->id); // NOTE: the handler can set new events
thedo 167:1657b442184c 156 }
thedo 167:1657b442184c 157 /* Note: We continue back to examining the head because calling the
thedo 167:1657b442184c 158 * event handler may have altered the chain of pending events. */
thedo 167:1657b442184c 159 } else {
thedo 167:1657b442184c 160 break;
thedo 167:1657b442184c 161 }
thedo 167:1657b442184c 162 }
thedo 167:1657b442184c 163
thedo 167:1657b442184c 164 schedule_interrupt(ticker);
thedo 167:1657b442184c 165 }
thedo 167:1657b442184c 166
thedo 167:1657b442184c 167 void ticker_insert_event(const ticker_data_t *const ticker, ticker_event_t *obj, timestamp_t timestamp, uint32_t id)
thedo 167:1657b442184c 168 {
thedo 167:1657b442184c 169 core_util_critical_section_enter();
thedo 167:1657b442184c 170
thedo 167:1657b442184c 171 // update the current timestamp
thedo 167:1657b442184c 172 update_present_time(ticker);
thedo 167:1657b442184c 173 us_timestamp_t absolute_timestamp = convert_timestamp(
thedo 167:1657b442184c 174 ticker->queue->present_time,
thedo 167:1657b442184c 175 timestamp
thedo 167:1657b442184c 176 );
thedo 167:1657b442184c 177 core_util_critical_section_exit();
thedo 167:1657b442184c 178
thedo 167:1657b442184c 179 // defer to ticker_insert_event_us
thedo 167:1657b442184c 180 ticker_insert_event_us(
thedo 167:1657b442184c 181 ticker,
thedo 167:1657b442184c 182 obj, absolute_timestamp, id
thedo 167:1657b442184c 183 );
thedo 167:1657b442184c 184 }
thedo 167:1657b442184c 185
thedo 167:1657b442184c 186 void ticker_insert_event_us(const ticker_data_t *const ticker, ticker_event_t *obj, us_timestamp_t timestamp, uint32_t id)
thedo 167:1657b442184c 187 {
thedo 167:1657b442184c 188 core_util_critical_section_enter();
thedo 167:1657b442184c 189
thedo 167:1657b442184c 190 // update the current timestamp
thedo 167:1657b442184c 191 update_present_time(ticker);
thedo 167:1657b442184c 192
thedo 167:1657b442184c 193 // initialise our data
thedo 167:1657b442184c 194 obj->timestamp = timestamp;
thedo 167:1657b442184c 195 obj->id = id;
thedo 167:1657b442184c 196
thedo 167:1657b442184c 197 /* Go through the list until we either reach the end, or find
thedo 167:1657b442184c 198 an element this should come before (which is possibly the
thedo 167:1657b442184c 199 head). */
thedo 167:1657b442184c 200 ticker_event_t *prev = NULL, *p = ticker->queue->head;
thedo 167:1657b442184c 201 while (p != NULL) {
thedo 167:1657b442184c 202 /* check if we come before p */
thedo 167:1657b442184c 203 if (timestamp < p->timestamp) {
thedo 167:1657b442184c 204 break;
thedo 167:1657b442184c 205 }
thedo 167:1657b442184c 206 /* go to the next element */
thedo 167:1657b442184c 207 prev = p;
thedo 167:1657b442184c 208 p = p->next;
thedo 167:1657b442184c 209 }
thedo 167:1657b442184c 210
thedo 167:1657b442184c 211 /* if we're at the end p will be NULL, which is correct */
thedo 167:1657b442184c 212 obj->next = p;
thedo 167:1657b442184c 213
thedo 167:1657b442184c 214 /* if prev is NULL we're at the head */
thedo 167:1657b442184c 215 if (prev == NULL) {
thedo 167:1657b442184c 216 ticker->queue->head = obj;
thedo 167:1657b442184c 217 } else {
thedo 167:1657b442184c 218 prev->next = obj;
thedo 167:1657b442184c 219 }
thedo 167:1657b442184c 220
thedo 167:1657b442184c 221 schedule_interrupt(ticker);
thedo 167:1657b442184c 222
thedo 167:1657b442184c 223 core_util_critical_section_exit();
thedo 167:1657b442184c 224 }
thedo 167:1657b442184c 225
thedo 167:1657b442184c 226 void ticker_remove_event(const ticker_data_t *const ticker, ticker_event_t *obj)
thedo 167:1657b442184c 227 {
thedo 167:1657b442184c 228 core_util_critical_section_enter();
thedo 167:1657b442184c 229
thedo 167:1657b442184c 230 // remove this object from the list
thedo 167:1657b442184c 231 if (ticker->queue->head == obj) {
thedo 167:1657b442184c 232 // first in the list, so just drop me
thedo 167:1657b442184c 233 ticker->queue->head = obj->next;
thedo 167:1657b442184c 234 schedule_interrupt(ticker);
thedo 167:1657b442184c 235 } else {
thedo 167:1657b442184c 236 // find the object before me, then drop me
thedo 167:1657b442184c 237 ticker_event_t* p = ticker->queue->head;
thedo 167:1657b442184c 238 while (p != NULL) {
thedo 167:1657b442184c 239 if (p->next == obj) {
thedo 167:1657b442184c 240 p->next = obj->next;
thedo 167:1657b442184c 241 break;
thedo 167:1657b442184c 242 }
thedo 167:1657b442184c 243 p = p->next;
thedo 167:1657b442184c 244 }
thedo 167:1657b442184c 245 }
thedo 167:1657b442184c 246
thedo 167:1657b442184c 247 core_util_critical_section_exit();
thedo 167:1657b442184c 248 }
thedo 167:1657b442184c 249
thedo 167:1657b442184c 250 timestamp_t ticker_read(const ticker_data_t *const ticker)
thedo 167:1657b442184c 251 {
thedo 167:1657b442184c 252 return ticker_read_us(ticker);
thedo 167:1657b442184c 253 }
thedo 167:1657b442184c 254
thedo 167:1657b442184c 255 us_timestamp_t ticker_read_us(const ticker_data_t *const ticker)
thedo 167:1657b442184c 256 {
thedo 167:1657b442184c 257 update_present_time(ticker);
thedo 167:1657b442184c 258 return ticker->queue->present_time;
thedo 167:1657b442184c 259 }
thedo 167:1657b442184c 260
thedo 167:1657b442184c 261 int ticker_get_next_timestamp(const ticker_data_t *const data, timestamp_t *timestamp)
thedo 167:1657b442184c 262 {
thedo 167:1657b442184c 263 int ret = 0;
thedo 167:1657b442184c 264
thedo 167:1657b442184c 265 /* if head is NULL, there are no pending events */
thedo 167:1657b442184c 266 core_util_critical_section_enter();
thedo 167:1657b442184c 267 if (data->queue->head != NULL) {
thedo 167:1657b442184c 268 *timestamp = data->queue->head->timestamp;
thedo 167:1657b442184c 269 ret = 1;
thedo 167:1657b442184c 270 }
thedo 167:1657b442184c 271 core_util_critical_section_exit();
thedo 167:1657b442184c 272
thedo 167:1657b442184c 273 return ret;
thedo 167:1657b442184c 274 }
thedo 167:1657b442184c 275