Core API compatibility
[platform/core/uifw/dali-adaptor.git] / adaptors / tizen / tilt-sensor-impl-tizen.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
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
18 // CLASS HEADER
19 #include "tilt-sensor-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <cmath>
23
24 #ifdef UNDER_TIZEN_2_3_CAPI
25 #include <sensor.h>
26 #else
27 #include <sensor_internal.h>
28 #endif
29
30
31 #include <dali/public-api/object/type-registry.h>
32 #include <dali/integration-api/debug.h>
33
34 // INTERNAL INCLUDES
35 #include <singleton-service-impl.h>
36
37 #ifdef __arm__
38 #define SENSOR_ENABLED
39 #endif
40
41 namespace // unnamed namespace
42 {
43
44 const int NUMBER_OF_SAMPLES = 10;
45
46 const float MAX_ACCELEROMETER_XY_VALUE = 9.8f;
47
48 // Type Registration
49 Dali::BaseHandle Create()
50 {
51   return Dali::Internal::Adaptor::TiltSensor::Get();
52 }
53
54 Dali::TypeRegistration typeRegistration( typeid(Dali::TiltSensor), typeid(Dali::BaseHandle), Create );
55
56 Dali::SignalConnectorType signalConnector1( typeRegistration, Dali::TiltSensor::SIGNAL_TILTED, Dali::Internal::Adaptor::TiltSensor::DoConnectSignal );
57
58 } // unnamed namespace
59
60 namespace Dali
61 {
62
63 namespace Internal
64 {
65
66 namespace Adaptor
67 {
68
69 Dali::TiltSensor TiltSensor::New()
70 {
71   Dali::TiltSensor sensor = Dali::TiltSensor(new TiltSensor());
72
73   return sensor;
74 }
75
76 Dali::TiltSensor TiltSensor::Get()
77 {
78   Dali::TiltSensor sensor;
79
80   Dali::SingletonService service( SingletonService::Get() );
81   if ( service )
82   {
83     // Check whether the keyboard focus manager is already created
84     Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::TiltSensor ) );
85     if(handle)
86     {
87       // If so, downcast the handle of singleton to keyboard focus manager
88       sensor = Dali::TiltSensor( dynamic_cast< TiltSensor* >( handle.GetObjectPtr() ) );
89     }
90     else
91     {
92       // Create a singleton instance
93       sensor = TiltSensor::New();
94       service.Register( typeid( sensor ), sensor );
95       handle = sensor;
96     }
97   }
98
99   return sensor;
100 }
101
102 TiltSensor::~TiltSensor()
103 {
104   Disable();
105 }
106
107 bool TiltSensor::Enable()
108 {
109   // Make sure sensor API is responding
110   bool success = Update();
111
112   if ( success )
113   {
114     if ( !mTimer )
115     {
116       mTimer = Dali::Timer::New( 1000.0f / mFrequencyHertz );
117       mTimer.TickSignal().Connect( mTimerSlot, &TiltSensor::Update );
118     }
119
120     if ( mTimer &&
121          !mTimer.IsRunning() )
122     {
123       mTimer.Start();
124     }
125   }
126
127   return success;
128 }
129
130 void TiltSensor::Disable()
131 {
132   if ( mTimer )
133   {
134     mTimer.Stop();
135     mTimer.Reset();
136   }
137 }
138
139 bool TiltSensor::IsEnabled() const
140 {
141   return ( mTimer && mTimer.IsRunning() );
142 }
143
144 float TiltSensor::GetRoll() const
145 {
146   return mRoll;
147 }
148
149 float TiltSensor::GetPitch() const
150 {
151   return mPitch;
152 }
153
154 Quaternion TiltSensor::GetRotation() const
155 {
156   return mRotation;
157 }
158
159 TiltSensor::TiltedSignalV2& TiltSensor::TiltedSignal()
160 {
161   return mTiltedSignalV2;
162 }
163
164 void TiltSensor::SetUpdateFrequency( float frequencyHertz )
165 {
166   DALI_ASSERT_ALWAYS( frequencyHertz > 0.0f && "Frequency must have a positive value" );
167
168   if ( fabsf(mFrequencyHertz - frequencyHertz) >= GetRangedEpsilon(mFrequencyHertz, frequencyHertz) )
169   {
170     mFrequencyHertz = frequencyHertz;
171
172     if ( mTimer )
173     {
174       mTimer.SetInterval( 1000.0f / mFrequencyHertz );
175     }
176   }
177 }
178
179 float TiltSensor::GetUpdateFrequency() const
180 {
181   return mFrequencyHertz;
182 }
183
184 void TiltSensor::SetRotationThreshold(Radian rotationThreshold)
185 {
186   mRotationThreshold = rotationThreshold;
187 }
188
189 Radian TiltSensor::GetRotationThreshold() const
190 {
191   return mRotationThreshold;
192 }
193
194 bool TiltSensor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
195 {
196   bool connected( true );
197   TiltSensor* sensor = dynamic_cast<TiltSensor*>( object );
198
199   if( sensor &&
200       Dali::TiltSensor::SIGNAL_TILTED == signalName )
201   {
202     sensor->TiltedSignal().Connect( tracker, functor );
203   }
204   else
205   {
206     // signalName does not match any signal
207     connected = false;
208   }
209
210   return connected;
211 }
212
213 TiltSensor::TiltSensor()
214 : mFrequencyHertz( Dali::TiltSensor::DEFAULT_UPDATE_FREQUENCY ),
215   mTimerSlot( this ),
216   mSensorFrameworkHandle( -1 ),
217   mRoll( 0.0f ),
218   mPitch( 0.0f ),
219   mRotation( 0.0f, Vector3::YAXIS ),
220   mRotationThreshold( 0.0f )
221 {
222   mRollValues.resize( NUMBER_OF_SAMPLES, 0.0f );
223   mPitchValues.resize( NUMBER_OF_SAMPLES, 0.0f );
224 }
225
226 bool TiltSensor::Update()
227 {
228   float newRoll = 0.0f;
229   float newPitch = 0.0f;
230   Quaternion newRotation;
231 #ifdef SENSOR_ENABLED
232
233   // Read accelerometer data
234
235   mSensorFrameworkHandle = sf_connect( ACCELEROMETER_SENSOR );
236   if ( mSensorFrameworkHandle < 0 )
237   {
238     DALI_LOG_ERROR( "Failed to connect to sensor framework" );
239     return false;
240   }
241
242   if ( sf_start(mSensorFrameworkHandle, 0) < 0 )
243   {
244     DALI_LOG_ERROR( "Failed to start sensor" );
245     sf_disconnect(mSensorFrameworkHandle);
246     return false;
247   }
248
249   sensor_data_t* base_data_values = (sensor_data_t*)malloc(sizeof(sensor_data_t));
250
251   int dataErr = sf_get_data(mSensorFrameworkHandle, ACCELEROMETER_BASE_DATA_SET, base_data_values);
252   if ( dataErr < 0 )
253   {
254     DALI_LOG_ERROR( "Failed to retrieve sensor data" );
255     free(base_data_values);
256     sf_stop(mSensorFrameworkHandle);
257     sf_disconnect(mSensorFrameworkHandle);
258     return false;
259   }
260
261   sf_stop(mSensorFrameworkHandle);
262   sf_disconnect(mSensorFrameworkHandle);
263
264   mRollValues.push_back( base_data_values->values[0] );
265   mRollValues.pop_front();
266
267   mPitchValues.push_back( base_data_values->values[1] );
268   mPitchValues.pop_front();
269
270   free(base_data_values);
271   base_data_values = NULL;
272
273   float averageRoll( 0.0f );
274   for ( std::deque<float>::const_iterator iter = mRollValues.begin(); mRollValues.end() != iter; ++iter )
275   {
276     averageRoll += *iter;
277   }
278   averageRoll /= mRollValues.size();
279
280   float averagePitch( 0.0f );
281   for ( std::deque<float>::const_iterator iter = mPitchValues.begin(); mPitchValues.end() != iter; ++iter )
282   {
283     averagePitch += *iter;
284   }
285   averagePitch /= mPitchValues.size();
286
287   newRoll  = Clamp( float(averageRoll  / MAX_ACCELEROMETER_XY_VALUE), -1.0f/*min*/, 1.0f/*max*/ );
288   newPitch = Clamp( float(averagePitch / MAX_ACCELEROMETER_XY_VALUE), -1.0f/*min*/, 1.0f/*max*/ );
289
290   newRotation = Quaternion( newRoll  * Math::PI * -0.5f, Vector3::YAXIS ) *
291               Quaternion( newPitch * Math::PI * -0.5f, Vector3::XAXIS );
292 #endif // SENSOR_ENABLED
293
294   Radian angle(Quaternion::AngleBetween(newRotation, mRotation));
295   // If the change in value is more than the threshold then emit tilted signal.
296   if( angle > mRotationThreshold )
297   {
298     mRoll = newRoll;
299     mPitch = newPitch;
300     mRotation = newRotation;
301
302     if ( !mTiltedSignalV2.Empty() )
303     {
304       Dali::TiltSensor handle( this );
305       mTiltedSignalV2.Emit( handle );
306     }
307   }
308
309   return true;
310 }
311
312 } // namespace Adaptor
313
314 } // namespace Internal
315
316 } // namespace Dali