diff options
Diffstat (limited to 'afb-timer.c')
-rw-r--r-- | afb-timer.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/afb-timer.c b/afb-timer.c new file mode 100644 index 0000000..30ab80d --- /dev/null +++ b/afb-timer.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Fulup Ar Foll <fulup@iot.bzh> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <systemd/sd-event.h> + +#include "afb-timer.h" + +#define DEFAULT_PAUSE_DELAY 3000 +#define DEFAULT_TEST_COUNT 1 +typedef struct { + int value; + const char *uid; +} AutoTestCtxT; + + +static int TimerNext (sd_event_source* source, uint64_t timer, void* handle) { + TimerHandleT *timerHandle = (TimerHandleT*) handle; + int done; + uint64_t usec; + + done= timerHandle->callback(timerHandle); + if (!done) { + AFB_API_WARNING(timerHandle->api, "TimerNext Callback Fail Tag=%s", timerHandle->uid); + return -1; + } + + // Rearm timer if needed + timerHandle->count --; + if (timerHandle->count == 0) { + sd_event_source_unref(source); + if (timerHandle->freeCB) timerHandle->freeCB(timerHandle->context); + free (handle); + return 0; + } + else { + // otherwise validate timer for a new run + sd_event_now(afb_api_get_event_loop(timerHandle->api), CLOCK_MONOTONIC, &usec); + sd_event_source_set_enabled(source, SD_EVENT_ONESHOT); + sd_event_source_set_time(source, usec + timerHandle->delay*1000); + } + + return 0; +} + +void TimerEvtStop(TimerHandleT *timerHandle) { + + sd_event_source_unref(timerHandle->evtSource); + free (timerHandle); +} + + +void TimerEvtStart(afb_api_t apiHandle, TimerHandleT *timerHandle, timerCallbackT callback, void *context) { + uint64_t usec; + + // populate CB handle + timerHandle->callback=callback; + timerHandle->context=context; + timerHandle->api=apiHandle; + + // set a timer with ~250us accuracy + sd_event_now(afb_api_get_event_loop(apiHandle), CLOCK_MONOTONIC, &usec); + sd_event_add_time(afb_api_get_event_loop(apiHandle), &timerHandle->evtSource, CLOCK_MONOTONIC, usec+timerHandle->delay*1000, 250, TimerNext, timerHandle); +} + + +// Create Binding Event at Init +int TimerEvtInit (afb_api_t apiHandle) { + + AFB_API_DEBUG (apiHandle, "Timer-Init Done"); + return 0; +} + +uint64_t LockWait(afb_api_t apiHandle, uint64_t utimeout) { + uint64_t current_usec, pre_usec; + + struct sd_event *event = afb_api_get_event_loop(apiHandle); + + sd_event_now(event, CLOCK_MONOTONIC, &pre_usec); + sd_event_run(event, utimeout); + sd_event_now(event, CLOCK_MONOTONIC, ¤t_usec); + + uint64_t diff = current_usec - pre_usec; + utimeout = utimeout < diff ? 0 : utimeout - diff; + return utimeout; +} |