Lap counter peripheral added 10/191510/4
authorMichal Skorupinski <m.skorupinsk@samsung.com>
Wed, 17 Oct 2018 17:22:17 +0000 (19:22 +0200)
committerMichal Skorupinski <m.skorupinsk@samsung.com>
Thu, 25 Oct 2018 18:04:52 +0000 (20:04 +0200)
Change-Id: I806b3841d86d41d2d689570338ddc81ab85f3635
Signed-off-by: Michal Skorupinski <m.skorupinsk@samsung.com>
CMakeLists.txt
inc/log.h
inc/resource.h
inc/resource/resource_lap_counter.h [new file with mode: 0644]
src/app.c
src/resource/resource_lap_counter.c [new file with mode: 0644]

index ead3d4f..4db9490 100644 (file)
@@ -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
index ba19887..de60f3a 100644 (file)
--- a/inc/log.h
+++ b/inc/log.h
        } \
 } 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); \
index 5aacc4a..34f9df0 100644 (file)
@@ -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 (file)
index 0000000..3bee466
--- /dev/null
@@ -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_ */
index 03e3e95..0092caf 100644 (file)
--- 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 (file)
index 0000000..bde429c
--- /dev/null
@@ -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 <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <peripheral_io.h>
+#include <time.h>
+#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, &timestamp);
+       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, &timestamp);
+       } 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);
+}
+