From 3559e8b6dfa8196babb548c016b6b7577217320c Mon Sep 17 00:00:00 2001 From: Michal Skorupinski Date: Wed, 17 Oct 2018 19:22:17 +0200 Subject: [PATCH] Lap counter peripheral added Change-Id: I806b3841d86d41d2d689570338ddc81ab85f3635 Signed-off-by: Michal Skorupinski --- CMakeLists.txt | 1 + inc/log.h | 15 ++++ inc/resource.h | 1 + inc/resource/resource_lap_counter.h | 25 ++++++ src/app.c | 10 +++ src/resource/resource_lap_counter.c | 148 ++++++++++++++++++++++++++++++++++++ 6 files changed, 200 insertions(+) create mode 100644 inc/resource/resource_lap_counter.h create mode 100644 src/resource/resource_lap_counter.c diff --git a/CMakeLists.txt b/CMakeLists.txt index ead3d4f..4db9490 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ ADD_EXECUTABLE(${PROJECT_NAME} ${PROJECT_ROOT_DIR}/src/resource/resource_motor_driver_L298N.c ${PROJECT_ROOT_DIR}/src/resource/resource_PCA9685.c ${PROJECT_ROOT_DIR}/src/resource/resource_servo_motor.c + ${PROJECT_ROOT_DIR}/src/resource/resource_lap_counter.c ${PROJECT_ROOT_DIR}/src/cloud/car_info.c ${PROJECT_ROOT_DIR}/src/cloud/car_info_serializer.c ${PROJECT_ROOT_DIR}/src/cloud/cloud_request.c diff --git a/inc/log.h b/inc/log.h index ba19887..de60f3a 100644 --- a/inc/log.h +++ b/inc/log.h @@ -57,6 +57,21 @@ } \ } while (0) +#define retvm_error_message(expr, ret, val, fmt, arg...) do { \ + if (expr) { \ + _E(fmt, ##arg); \ + _E("(%s) Error= {%s} -> %s() return", #expr, get_error_message(ret), __FUNCTION__); \ + return val; \ + } \ +} while (0) + +#define retv_error_message(expr, ret) do { \ + if (expr) { \ + _E("(%s) Error= {%s} -> %s() return", #expr, get_error_message(ret), __FUNCTION__); \ + return; \ + } \ +} while (0) + #define retm_if(expr, fmt, arg...) do { \ if (expr) { \ _E(fmt, ##arg); \ diff --git a/inc/resource.h b/inc/resource.h index 5aacc4a..34f9df0 100644 --- a/inc/resource.h +++ b/inc/resource.h @@ -25,6 +25,7 @@ #include "resource/resource_infrared_obstacle_avoidance_sensor.h" #include "resource/resource_motor_driver_L298N.h" #include "resource/resource_servo_motor.h" +#include "resource/resource_lap_counter.h" void resource_close_all(void); diff --git a/inc/resource/resource_lap_counter.h b/inc/resource/resource_lap_counter.h new file mode 100644 index 0000000..3bee466 --- /dev/null +++ b/inc/resource/resource_lap_counter.h @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2018 Samsung Electronics Co., Ltd. +* +* Licensed under the Flora License, Version 1.1 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://floralicense.org/license/ +* +* 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. +*/ + + +#ifndef RESOURCE_RESOURCE_LAP_COUNTER_H_ + +void resource_lap_counter_init(void); +void resource_lap_counter_destroy(void); + +#define RESOURCE_RESOURCE_LAP_COUNTER_H_ + +#endif /* RESOURCE_RESOURCE_LAP_COUNTER_H_ */ diff --git a/src/app.c b/src/app.c index 03e3e95..0092caf 100644 --- a/src/app.c +++ b/src/app.c @@ -212,6 +212,12 @@ static bool service_app_create(void *data) int ret = 0; app_data *ad = data; + _D("-----------------------=======================================================================-----------------------"); + _D("-----------------------=======================================================================-----------------------"); + _D("-----------------------============================== APP %s %s ==============================-----------------------", __DATE__, __TIME__); + _D("-----------------------=======================================================================-----------------------"); + _D("-----------------------=======================================================================-----------------------"); + /* * if you want to use default configuration, * Do not need to call resource_set_motor_driver_L298N_configuration(), @@ -230,6 +236,8 @@ static bool service_app_create(void *data) } #endif + resource_lap_counter_init(); + _initialize_components(ad); cloud_communication_start(CLOUD_REQUESTS_FREQUENCY); @@ -262,6 +270,8 @@ static void service_app_terminate(void *data) resource_set_servo_motor_value(ELEVATION_SERVO_PIN, ELEVATION_MIN); resource_set_servo_motor_value(AZIMUTH_SERVO_PIN, (AZIMUTH_MIN + AZIMUTH_MAX) / 2); + resource_lap_counter_destroy(); + if (ad->idle_h) g_source_remove(ad->idle_h); diff --git a/src/resource/resource_lap_counter.c b/src/resource/resource_lap_counter.c new file mode 100644 index 0000000..bde429c --- /dev/null +++ b/src/resource/resource_lap_counter.c @@ -0,0 +1,148 @@ +/* +* Copyright (c) 2018 Samsung Electronics Co., Ltd. +* +* Licensed under the Flora License, Version 1.1 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://floralicense.org/license/ +* +* 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. +*/ + +#include +#include +#include +#include +#include +#include "log.h" + + +#define GPIO_PIN 26 +#define MIN_LAP_TIME 5 + +typedef struct _lap_counter_s { + peripheral_gpio_h gpio; + struct timespec last_timestamp; + uint32_t gpio_initial_value; + uint32_t gpio_prev_value; +} lap_counter_s; + +static lap_counter_s s_info = { 0, }; + +#define CHECK_GPIO_ERROR(pin, ret) \ + if (ret != PERIPHERAL_ERROR_NONE) { \ + peripheral_gpio_close(pin); \ + _E("GPIO ERROR: %s, %s[%d]", get_error_message(ret), __FILE__, __LINE__); \ + return; \ + } + +void _print_time(const char *title, struct timespec *ts) +{ + char buf[PATH_MAX]; + struct tm *_tm = localtime(&(ts->tv_sec)); + strftime(&buf[0], PATH_MAX, "%H:%M:%S", _tm); + + snprintf(&buf[strlen(buf)], PATH_MAX, ".%03ld", ts->tv_nsec / (long)1e6); + + _D ("%s %s", title, buf); +} + +static struct timespec _calculate_lap_time(struct timespec *prev, struct timespec *now) +{ + struct timespec lap; + + lap.tv_sec = now->tv_sec - prev->tv_sec; + lap.tv_nsec = now->tv_nsec - prev->tv_nsec; + + + _D("----------------------------------------------"); + _print_time("PREV:\t", prev); + _print_time("NOW:\t", now); + + if (lap.tv_sec < MIN_LAP_TIME) { + lap.tv_sec = 0; + lap.tv_nsec = 0; + _D ("TOO SHORT LAP"); + return lap; + } + + + _print_time("LAP:\t", &lap); + + if (lap.tv_nsec < 0) { + lap.tv_sec--; + lap.tv_nsec = 1e9 + lap.tv_nsec; + + _print_time("LAP_MOD:\t", &lap); + } + _D("----------------------------------------------"); + + return lap; +} + +static inline void _get_lap_time() +{ + struct timespec timestamp; + int ret = clock_gettime(CLOCK_MONOTONIC, ×tamp); + retv_error_message(ret != 0, ret); + + if (s_info.last_timestamp.tv_nsec != 0 || s_info.last_timestamp.tv_sec != 0) { + _calculate_lap_time(&s_info.last_timestamp, ×tamp); + } else { + _D("Starting first lap"); + } + + s_info.last_timestamp.tv_sec = timestamp.tv_sec; + s_info.last_timestamp.tv_nsec = timestamp.tv_nsec; +} + +static void _gpio_interrupted_cb(peripheral_gpio_h gpio, peripheral_error_e error, void *user_data) +{ + uint32_t gpio_value = 0; + int ret = peripheral_gpio_read(s_info.gpio, &gpio_value); + CHECK_GPIO_ERROR(s_info.gpio, ret); + + _D("GPIO_%d value: %d initial: %d, prev: %d", GPIO_PIN, gpio_value, s_info.gpio_initial_value, s_info.gpio_prev_value); + + if (gpio_value != s_info.gpio_initial_value && s_info.gpio_prev_value == s_info.gpio_initial_value) { + _get_lap_time(); + } + + + s_info.gpio_prev_value = gpio_value; +} + +void resource_lap_counter_init(void) +{ + int ret = PERIPHERAL_ERROR_NONE; + + ret = peripheral_gpio_open(GPIO_PIN, &s_info.gpio); + retv_error_message(ret != PERIPHERAL_ERROR_NONE, ret); + + ret = peripheral_gpio_set_direction(s_info.gpio, PERIPHERAL_GPIO_DIRECTION_IN); + CHECK_GPIO_ERROR(s_info.gpio, ret); + + ret = peripheral_gpio_set_edge_mode(s_info.gpio, PERIPHERAL_GPIO_EDGE_BOTH); + CHECK_GPIO_ERROR(s_info.gpio, ret); + + ret = peripheral_gpio_set_interrupted_cb(s_info.gpio, _gpio_interrupted_cb, NULL); + CHECK_GPIO_ERROR(s_info.gpio, ret); + + ret = peripheral_gpio_read(s_info.gpio, &s_info.gpio_initial_value); + CHECK_GPIO_ERROR(s_info.gpio, ret); + + _D("GPIO_%d initial value: %d", GPIO_PIN, s_info.gpio_initial_value); + s_info.gpio_prev_value = s_info.gpio_initial_value; +} + +void resource_lap_counter_destroy(void) +{ + peripheral_gpio_unset_interrupted_cb(s_info.gpio); + peripheral_gpio_close(s_info.gpio); +} + -- 2.7.4