2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <peripheral_io.h>
21 #define ENABLE_SERVO_TIMEOUT
23 /* This value is only for Servo Motor - SG90 */
24 #define SERVO_MOTOR_DEFAULT_PERIOD 20.0
25 #define SERVO_MOTOR_DUTY_CYCLE_COUNTER_CLOCKWISE 0.9
26 #define SERVO_MOTOR_DUTY_CYCLE_CLOCKWISE 2.4
28 #ifdef ENABLE_SERVO_TIMEOUT
29 #define SERVO_TIMEOUT_INTERVAL 150
30 #endif /* ENABLE_SERVO_TIMEOUT */
32 /* This APIs are only made for Eagleye530s */
33 /* There are 2 pins for PWM */
34 static peripheral_pwm_h g_pwm0_h;
35 static peripheral_pwm_h g_pwm2_h;
37 #ifdef ENABLE_SERVO_TIMEOUT
38 static guint g_timer_id0;
39 static guint g_timer_id2;
41 static gboolean __timeout_cb(void *data)
43 int channel = GPOINTER_TO_INT(data);
45 _D("pwm channel[%d] disable", channel);
46 if (channel == 0 && g_pwm0_h) {
47 peripheral_pwm_set_enabled(g_pwm0_h, false);
49 } else if (channel == 2 && g_pwm2_h) {
50 peripheral_pwm_set_enabled(g_pwm2_h, false);
56 static void __remove_timeout_cb(int channel)
60 g_source_remove(g_timer_id0);
63 } else if (channel == 2) {
65 g_source_remove(g_timer_id0);
71 static void __add_timeout_cb(int channel)
74 g_timer_id0 = g_timeout_add(SERVO_TIMEOUT_INTERVAL,
75 __timeout_cb, GINT_TO_POINTER(channel));
76 } else if (channel == 2) {
77 g_timer_id2 = g_timeout_add(SERVO_TIMEOUT_INTERVAL,
78 __timeout_cb, GINT_TO_POINTER(channel));
81 #endif /* ENABLE_SERVO_TIMEOUT */
83 void resource_close_servo_motor(int channel)
85 #ifdef ENABLE_SERVO_TIMEOUT
86 __remove_timeout_cb(channel);
87 #endif /* ENABLE_SERVO_TIMEOUT */
89 if (channel == 0 && g_pwm0_h) {
90 peripheral_pwm_close(g_pwm0_h);
92 } else if (channel == 2 && g_pwm2_h) {
93 peripheral_pwm_close(g_pwm2_h);
98 int resource_set_servo_motor_sg90_value(int channel, double duty_cycle_ms)
101 peripheral_pwm_h *pwm_h = NULL;
103 if (duty_cycle_ms >= SERVO_MOTOR_DEFAULT_PERIOD) {
104 _E("Too large duty cycle");
108 #ifdef ENABLE_SERVO_TIMEOUT
109 __remove_timeout_cb(channel);
110 #endif /* ENABLE_SERVO_TIMEOUT */
114 } else if (channel == 2) {
117 _E("unsupported channel - %d", channel);
122 ret = peripheral_pwm_open(0, channel, pwm_h);
123 if (ret != PERIPHERAL_ERROR_NONE) {
124 _E("failed to open servo motor with channel(%d) : %s", channel, get_error_message(ret));
129 ret = peripheral_pwm_set_period(*pwm_h, SERVO_MOTOR_DEFAULT_PERIOD * 1000 * 1000);
130 if (ret != PERIPHERAL_ERROR_NONE) {
131 _E("failed to set period : %s", get_error_message(ret));
135 ret = peripheral_pwm_set_duty_cycle(*pwm_h, duty_cycle_ms * 1000 * 1000);
136 if (ret != PERIPHERAL_ERROR_NONE) {
137 _E("failed to set duty cycle : %s", get_error_message(ret));
141 ret = peripheral_pwm_set_enabled(*pwm_h, true);
142 if (ret != PERIPHERAL_ERROR_NONE) {
143 _E("failed to enable : %s", get_error_message(ret));
147 #ifdef ENABLE_SERVO_TIMEOUT
148 __add_timeout_cb(channel);
149 #endif /* ENABLE_SERVO_TIMEOUT */
154 int resource_rotate_servo_motor_by_percent(int channel, double percent)
157 double duty_cycle = 0.0f;
159 duty_cycle = ((SERVO_MOTOR_DUTY_CYCLE_CLOCKWISE - SERVO_MOTOR_DUTY_CYCLE_COUNTER_CLOCKWISE)
161 + SERVO_MOTOR_DUTY_CYCLE_COUNTER_CLOCKWISE;
163 ret = resource_set_servo_motor_sg90_value(channel, duty_cycle);