Lap counter peripheral added
[apps/native/gear-racing-car.git] / src / resource / resource_lap_counter.c
1 /*
2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3 *
4 * Licensed under the Flora License, Version 1.1 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://floralicense.org/license/
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <limits.h>
19 #include <stdlib.h>
20 #include <peripheral_io.h>
21 #include <time.h>
22 #include "log.h"
23
24
25 #define GPIO_PIN 26
26 #define MIN_LAP_TIME 5
27
28 typedef struct _lap_counter_s {
29         peripheral_gpio_h gpio;
30         struct timespec last_timestamp;
31         uint32_t gpio_initial_value;
32         uint32_t gpio_prev_value;
33 } lap_counter_s;
34
35 static lap_counter_s s_info = { 0, };
36
37 #define  CHECK_GPIO_ERROR(pin, ret) \
38         if (ret != PERIPHERAL_ERROR_NONE) { \
39                 peripheral_gpio_close(pin); \
40                 _E("GPIO ERROR: %s, %s[%d]", get_error_message(ret), __FILE__, __LINE__); \
41                 return; \
42         }
43
44 void _print_time(const char *title, struct timespec *ts)
45 {
46         char buf[PATH_MAX];
47         struct tm *_tm = localtime(&(ts->tv_sec));
48         strftime(&buf[0], PATH_MAX, "%H:%M:%S", _tm);
49
50         snprintf(&buf[strlen(buf)], PATH_MAX, ".%03ld", ts->tv_nsec / (long)1e6);
51
52         _D ("%s %s", title, buf);
53 }
54
55 static struct timespec _calculate_lap_time(struct timespec *prev, struct timespec *now)
56 {
57         struct timespec lap;
58
59         lap.tv_sec = now->tv_sec - prev->tv_sec;
60         lap.tv_nsec = now->tv_nsec - prev->tv_nsec;
61
62
63         _D("----------------------------------------------");
64         _print_time("PREV:\t", prev);
65         _print_time("NOW:\t", now);
66
67         if (lap.tv_sec < MIN_LAP_TIME) {
68                 lap.tv_sec = 0;
69                 lap.tv_nsec = 0;
70                 _D ("TOO SHORT LAP");
71                 return lap;
72         }
73
74
75         _print_time("LAP:\t", &lap);
76
77         if (lap.tv_nsec < 0) {
78                 lap.tv_sec--;
79                 lap.tv_nsec = 1e9 + lap.tv_nsec;
80
81                 _print_time("LAP_MOD:\t", &lap);
82         }
83         _D("----------------------------------------------");
84
85         return lap;
86 }
87
88 static inline void _get_lap_time()
89 {
90         struct timespec timestamp;
91         int ret = clock_gettime(CLOCK_MONOTONIC, &timestamp);
92         retv_error_message(ret != 0, ret);
93
94         if (s_info.last_timestamp.tv_nsec != 0 || s_info.last_timestamp.tv_sec != 0) {
95                 _calculate_lap_time(&s_info.last_timestamp, &timestamp);
96         } else {
97                 _D("Starting first lap");
98         }
99
100         s_info.last_timestamp.tv_sec = timestamp.tv_sec;
101         s_info.last_timestamp.tv_nsec = timestamp.tv_nsec;
102 }
103
104 static void _gpio_interrupted_cb(peripheral_gpio_h gpio, peripheral_error_e error, void *user_data)
105 {
106         uint32_t gpio_value = 0;
107         int ret = peripheral_gpio_read(s_info.gpio, &gpio_value);
108         CHECK_GPIO_ERROR(s_info.gpio, ret);
109
110         _D("GPIO_%d value: %d initial: %d, prev: %d", GPIO_PIN, gpio_value, s_info.gpio_initial_value, s_info.gpio_prev_value);
111
112         if (gpio_value != s_info.gpio_initial_value && s_info.gpio_prev_value == s_info.gpio_initial_value) {
113                 _get_lap_time();
114         }
115
116
117         s_info.gpio_prev_value = gpio_value;
118 }
119
120 void resource_lap_counter_init(void)
121 {
122         int ret = PERIPHERAL_ERROR_NONE;
123
124         ret = peripheral_gpio_open(GPIO_PIN, &s_info.gpio);
125         retv_error_message(ret != PERIPHERAL_ERROR_NONE, ret);
126
127         ret = peripheral_gpio_set_direction(s_info.gpio, PERIPHERAL_GPIO_DIRECTION_IN);
128         CHECK_GPIO_ERROR(s_info.gpio, ret);
129
130         ret = peripheral_gpio_set_edge_mode(s_info.gpio, PERIPHERAL_GPIO_EDGE_BOTH);
131         CHECK_GPIO_ERROR(s_info.gpio, ret);
132
133         ret = peripheral_gpio_set_interrupted_cb(s_info.gpio, _gpio_interrupted_cb, NULL);
134         CHECK_GPIO_ERROR(s_info.gpio, ret);
135
136         ret = peripheral_gpio_read(s_info.gpio, &s_info.gpio_initial_value);
137         CHECK_GPIO_ERROR(s_info.gpio, ret);
138
139         _D("GPIO_%d initial value: %d", GPIO_PIN, s_info.gpio_initial_value);
140         s_info.gpio_prev_value = s_info.gpio_initial_value;
141 }
142
143 void resource_lap_counter_destroy(void)
144 {
145         peripheral_gpio_unset_interrupted_cb(s_info.gpio);
146         peripheral_gpio_close(s_info.gpio);
147 }
148