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