2 * Copyright (c) 2014 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.
19 #include "tilt-sensor-impl.h"
23 #ifdef DALI_PROFILE_LITE
24 #include <sensor_internal.h>
29 #include <dali/public-api/object/type-registry.h>
30 #include <dali/integration-api/debug.h>
33 #include <adaptor-impl.h>
36 #define SENSOR_ENABLED
39 namespace // unnamed namespace
42 const int NUMBER_OF_SAMPLES = 10;
44 const float MAX_ACCELEROMETER_XY_VALUE = 9.8f;
47 Dali::BaseHandle Create()
49 return Dali::Internal::Adaptor::TiltSensor::Get();
52 Dali::TypeRegistration typeRegistration( typeid(Dali::TiltSensor), typeid(Dali::BaseHandle), Create );
54 Dali::SignalConnectorType signalConnector1( typeRegistration, Dali::TiltSensor::SIGNAL_TILTED, Dali::Internal::Adaptor::TiltSensor::DoConnectSignal );
56 } // unnamed namespace
67 Dali::TiltSensor TiltSensor::New()
69 Dali::TiltSensor sensor = Dali::TiltSensor(new TiltSensor());
74 Dali::TiltSensor TiltSensor::Get()
76 Dali::TiltSensor sensor;
78 if ( Adaptor::IsAvailable() )
80 // Check whether the keyboard focus manager is already created
81 Dali::BaseHandle handle = Dali::Adaptor::Get().GetSingleton( typeid( Dali::TiltSensor ) );
84 // If so, downcast the handle of singleton to keyboard focus manager
85 sensor = Dali::TiltSensor( dynamic_cast< TiltSensor* >( handle.GetObjectPtr() ) );
89 // Create a singleton instance
90 Adaptor& adaptorImpl( Adaptor::GetImplementation( Adaptor::Get() ) );
91 sensor = TiltSensor::New();
92 adaptorImpl.RegisterSingleton( typeid( sensor ), sensor );
100 TiltSensor::~TiltSensor()
105 bool TiltSensor::Enable()
107 // Make sure sensor API is responding
108 bool success = Update();
114 mTimer = Dali::Timer::New( 1000.0f / mFrequencyHertz );
115 mTimer.TickSignal().Connect( mTimerSlot, &TiltSensor::Update );
119 !mTimer.IsRunning() )
128 void TiltSensor::Disable()
137 bool TiltSensor::IsEnabled() const
139 return ( mTimer && mTimer.IsRunning() );
142 float TiltSensor::GetRoll() const
147 float TiltSensor::GetPitch() const
152 Quaternion TiltSensor::GetRotation() const
157 TiltSensor::TiltedSignalV2& TiltSensor::TiltedSignal()
159 return mTiltedSignalV2;
162 void TiltSensor::SetUpdateFrequency( float frequencyHertz )
164 DALI_ASSERT_ALWAYS( frequencyHertz > 0.0f && "Frequency must have a positive value" );
166 if ( fabsf(mFrequencyHertz - frequencyHertz) >= GetRangedEpsilon(mFrequencyHertz, frequencyHertz) )
168 mFrequencyHertz = frequencyHertz;
172 mTimer.SetInterval( 1000.0f / mFrequencyHertz );
177 float TiltSensor::GetUpdateFrequency() const
179 return mFrequencyHertz;
182 void TiltSensor::SetRotationThreshold(Radian rotationThreshold)
184 mRotationThreshold = rotationThreshold;
187 Radian TiltSensor::GetRotationThreshold() const
189 return mRotationThreshold;
192 bool TiltSensor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
194 bool connected( true );
195 TiltSensor* sensor = dynamic_cast<TiltSensor*>( object );
198 Dali::TiltSensor::SIGNAL_TILTED == signalName )
200 sensor->TiltedSignal().Connect( tracker, functor );
204 // signalName does not match any signal
211 TiltSensor::TiltSensor()
212 : mFrequencyHertz( Dali::TiltSensor::DEFAULT_UPDATE_FREQUENCY ),
214 mSensorFrameworkHandle( -1 ),
217 mRotation( 0.0f, Vector3::YAXIS ),
218 mRotationThreshold( 0.0f )
220 mRollValues.resize( NUMBER_OF_SAMPLES, 0.0f );
221 mPitchValues.resize( NUMBER_OF_SAMPLES, 0.0f );
224 bool TiltSensor::Update()
226 float newRoll = 0.0f;
227 float newPitch = 0.0f;
228 Quaternion newRotation;
229 #ifdef SENSOR_ENABLED
231 // Read accelerometer data
233 mSensorFrameworkHandle = sf_connect( ACCELEROMETER_SENSOR );
234 if ( mSensorFrameworkHandle < 0 )
236 DALI_LOG_ERROR( "Failed to connect to sensor framework" );
240 if ( sf_start(mSensorFrameworkHandle, 0) < 0 )
242 DALI_LOG_ERROR( "Failed to start sensor" );
243 sf_disconnect(mSensorFrameworkHandle);
247 sensor_data_t* base_data_values = (sensor_data_t*)malloc(sizeof(sensor_data_t));
249 int dataErr = sf_get_data(mSensorFrameworkHandle, ACCELEROMETER_BASE_DATA_SET, base_data_values);
252 DALI_LOG_ERROR( "Failed to retrieve sensor data" );
253 free(base_data_values);
254 sf_stop(mSensorFrameworkHandle);
255 sf_disconnect(mSensorFrameworkHandle);
259 sf_stop(mSensorFrameworkHandle);
260 sf_disconnect(mSensorFrameworkHandle);
262 mRollValues.push_back( base_data_values->values[0] );
263 mRollValues.pop_front();
265 mPitchValues.push_back( base_data_values->values[1] );
266 mPitchValues.pop_front();
268 free(base_data_values);
269 base_data_values = NULL;
271 float averageRoll( 0.0f );
272 for ( std::deque<float>::const_iterator iter = mRollValues.begin(); mRollValues.end() != iter; ++iter )
274 averageRoll += *iter;
276 averageRoll /= mRollValues.size();
278 float averagePitch( 0.0f );
279 for ( std::deque<float>::const_iterator iter = mPitchValues.begin(); mPitchValues.end() != iter; ++iter )
281 averagePitch += *iter;
283 averagePitch /= mPitchValues.size();
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*/ );
288 newRotation = Quaternion( newRoll * Math::PI * -0.5f, Vector3::YAXIS ) *
289 Quaternion( newPitch * Math::PI * -0.5f, Vector3::XAXIS );
290 #endif // SENSOR_ENABLED
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 )
298 mRotation = newRotation;
300 if ( !mTiltedSignalV2.Empty() )
302 Dali::TiltSensor handle( this );
303 mTiltedSignalV2.Emit( handle );
310 } // namespace Adaptor
312 } // namespace Internal