summaryrefslogtreecommitdiff
path: root/src/model/model_hw.c
blob: e990759fc7e433f7ea394aa3362f0f9f1ccfbef0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
* 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 "gear-racing-controller.h"
#include "model/model_hw.h"
#include "model/model_car_connection.h"
#include "model/model_device_to_connection.h"

#include <efl_extension.h>

#include "log.h"

typedef struct _s_model_hw {
	t_model_hw_update_cb hw_update_cb;
	float bezel_position;
	bool rotary_deactivated;

	float bezel_step;
	float bezel_dead_zone;
	bool use_direction_blocker;
	int blocker_count;
	bool set_to_zero_when_stop;
	float bezel_min;
	float bezel_max;
} s_model_hw;

static s_model_hw s_info = { 0, };

static inline void _update_direction_blocker(int *last_movement_dir, int step, int direction, int new_dir)
{
	if (*last_movement_dir * direction > 0) {
		*last_movement_dir += step;
		s_info.bezel_position = 0;
	} else {
		*last_movement_dir = new_dir;
	}
}

static Eina_Bool _rotary_cb(void *data, Eext_Rotary_Event_Info *info)
{
	static s_model_hw_cb_data cb_data = { 0, };

	if (s_info.rotary_deactivated) {
		return true;
	}

	float prev = s_info.bezel_position;

	if (info->direction == EEXT_ROTARY_DIRECTION_CLOCKWISE) {
		s_info.bezel_position += s_info.bezel_step;
	} else {
		s_info.bezel_position -= s_info.bezel_step;
	}

	if (s_info.bezel_position > s_info.bezel_max) {
		s_info.bezel_position = s_info.bezel_max;
	} else if (s_info.bezel_position < s_info.bezel_min) {
		s_info.bezel_position = s_info.bezel_min;
	}


	if (s_info.use_direction_blocker) {
		static int last_movement_dir = 0;

		if (fabsf(s_info.bezel_position) < s_info.bezel_dead_zone) {
			s_info.bezel_position = 0;
		} else if (s_info.bezel_position < 0.0f) {
			_update_direction_blocker(&last_movement_dir, -1, 1, -s_info.blocker_count);
		} else if(s_info.bezel_position > 0.0f) {
			_update_direction_blocker(&last_movement_dir, 1, -1, s_info.blocker_count);
		}
	} else {

		if (fabsf(s_info.bezel_position) < s_info.bezel_dead_zone) {
			s_info.bezel_position = 0;
		} else if (s_info.bezel_position * prev < 0.0f) {
			s_info.bezel_position = 0;
		}
	}

	cb_data.bezel_position = s_info.bezel_position;
	s_info.hw_update_cb(&cb_data);

	_D("BEZEL: %f", cb_data.bezel_position);
	model_device_to_connection_bezel(s_info.bezel_position);

	return true;
}

void model_hw_deactivate_rotatry(bool deactivate)
{
	static s_model_hw_cb_data cb_data = { 0, };

	if (!s_info.set_to_zero_when_stop) {
		return;
	}

	s_info.rotary_deactivated = deactivate;

	s_info.bezel_position = 0;

	if (s_info.hw_update_cb) {
		s_info.hw_update_cb(&cb_data);
	}
}

void model_hw_init(void)
{
	Eina_Bool ret = eext_rotary_event_handler_add(_rotary_cb, NULL);
	ASSERT_FUNCTION(!ret);
}

void model_hw_subscribe_event(t_model_hw_update_cb model_update_cb)
{
	s_info.hw_update_cb = model_update_cb;
}

void model_hw_unsubscirbe_event(void)
{
	s_info.hw_update_cb = NULL;
}

void model_hw_set_bezel_params(float step, float dead_zone, bool use_blocker, int blocker_count, bool set_to_zero_when_stop)
{
	s_info.bezel_step = step;
	s_info.bezel_dead_zone = dead_zone;
	s_info.use_direction_blocker = use_blocker;
	s_info.blocker_count = blocker_count;
	s_info.set_to_zero_when_stop = set_to_zero_when_stop;
}

void model_hw_set_bezel_max_min(float min, float max)
{
	s_info.bezel_min = min;
	s_info.bezel_max = max;
}