66using MbientLab . MetaWear . Sensor . AccelerometerMma8452q ;
77using System . Threading . Tasks ;
88using System . Collections . Generic ;
9+ using MbientLab . MetaWear . Data ;
910
1011namespace MbientLab . MetaWear . Impl {
12+ [ KnownType ( typeof ( Mma8452QCartesianFloatData ) ) ]
1113 [ DataContract ]
1214 class AccelerometerMma8452q : ModuleImplBase , IAccelerometerMma8452q {
1315 internal static string createIdentifier ( DataTypeBase dataType ) {
1416 switch ( dataType . eventConfig [ 1 ] ) {
1517 case DATA_VALUE :
1618 return dataType . attributes . length ( ) > 2 ? "acceleration" : string . Format ( "acceleration[{0}]" , ( dataType . attributes . offset >> 1 ) ) ;
19+ case ORIENTATION_VALUE :
20+ return "orientation" ;
1721 /*
18- case ORIENTATION_VALUE:
19- return "orientation";
20- case SHAKE_STATUS:
21- return "mma8452q-shake";
22- case PULSE_STATUS:
23- return "mma8452q-tap";
24- case MOVEMENT_VALUE:
25- return "mma8452q-movement";
26- */
22+ case SHAKE_STATUS:
23+ return "mma8452q-shake";
24+ case PULSE_STATUS:
25+ return "mma8452q-tap";
26+ case MOVEMENT_VALUE:
27+ return "mma8452q-movement";
28+ */
2729 default :
2830 return null ;
2931 }
@@ -32,12 +34,61 @@ internal static string createIdentifier(DataTypeBase dataType) {
3234 public const byte IMPLEMENTATION = 0 , PACKED_ACC_REVISION = 1 ;
3335 private const byte GLOBAL_ENABLE = 1 ,
3436 DATA_ENABLE = 2 , DATA_CONFIG = 3 , DATA_VALUE = 4 ,
37+ ORIENTATION_ENABLE = 8 , ORIENTATION_CONFIG = 9 , ORIENTATION_VALUE = 0xa ,
3538 PACKED_ACC_DATA = 0x12 ;
3639
3740 private static readonly float [ ] FREQUENCIES = new float [ ] { 800f , 400f , 200f , 100f , 50f , 12.5f , 6.25f , 1.56f } ,
3841 RANGES = new float [ ] { 2f , 4f , 8f } ;
42+ private static readonly float [ ] [ ] motionCountSteps = {
43+ new float [ ] { 1.25f , 2.5f , 5 , 10 , 20 , 20 , 20 , 20 } ,
44+ new float [ ] { 1.25f , 2.5f , 5 , 10 , 20 , 80 , 80 , 80 } ,
45+ new float [ ] { 1.25f , 2.5f , 2.5f , 2.5f , 2.5f , 2.5f , 2.5f , 2.5f } ,
46+ new float [ ] { 1.25f , 2.5f , 5 , 10 , 20 , 80 , 160 , 160 }
47+ } , orientationSteps = motionCountSteps ;
48+ private static readonly float [ ] [ ] [ ] OS_CUTOFF_FREQS = {
49+ new float [ ] [ ] {
50+ new float [ ] { 16f , 8f , 4f , 2f } ,
51+ new float [ ] { 16f , 8f , 4f , 2f } ,
52+ new float [ ] { 8f , 4f , 2f , 1f } ,
53+ new float [ ] { 4f , 2f , 1f , 0.5f } ,
54+ new float [ ] { 2f , 1f , 0.5f , 0.25f } ,
55+ new float [ ] { 2f , 1f , 0.5f , 0.25f } ,
56+ new float [ ] { 2f , 1f , 0.5f , 0.25f } ,
57+ new float [ ] { 2f , 1f , 0.5f , 0.25f }
58+ } ,
59+ new float [ ] [ ] {
60+ new float [ ] { 16f , 8f , 4f , 2f } ,
61+ new float [ ] { 16f , 8f , 4f , 2f } ,
62+ new float [ ] { 8f , 4f , 2f , 1f } ,
63+ new float [ ] { 4f , 2f , 1f , 0.5f } ,
64+ new float [ ] { 2f , 1f , 0.5f , 0.25f } ,
65+ new float [ ] { 0.5f , 0.25f , 0.125f , 0.063f } ,
66+ new float [ ] { 0.5f , 0.25f , 0.125f , 0.063f } ,
67+ new float [ ] { 0.5f , 0.25f , 0.125f , 0.063f }
68+ } ,
69+ new float [ ] [ ] {
70+ new float [ ] { 16f , 8f , 4f , 2f } ,
71+ new float [ ] { 16f , 8f , 4f , 2f } ,
72+ new float [ ] { 16f , 8f , 4f , 2f } ,
73+ new float [ ] { 16f , 8f , 4f , 2f } ,
74+ new float [ ] { 16f , 8f , 4f , 2f } ,
75+ new float [ ] { 16f , 8f , 4f , 2f } ,
76+ new float [ ] { 16f , 8f , 4f , 2f } ,
77+ new float [ ] { 16f , 8f , 4f , 2f }
78+ } ,
79+ new float [ ] [ ] {
80+ new float [ ] { 16f , 8f , 4f , 2f } ,
81+ new float [ ] { 8f , 4f , 2f , 1f } ,
82+ new float [ ] { 4f , 2f , 1f , 0.5f } ,
83+ new float [ ] { 2f , 1f , 0.5f , 0.25f } ,
84+ new float [ ] { 1f , 0.5f , 0.25f , 0.125f } ,
85+ new float [ ] { 0.25f , 0.125f , 0.063f , 0.031f } ,
86+ new float [ ] { 0.25f , 0.125f , 0.063f , 0.031f } ,
87+ new float [ ] { 0.25f , 0.125f , 0.063f , 0.031f }
88+ }
89+ } ;
3990
40- [ DataContract ]
91+ [ DataContract ]
4192 private class Mma8452QCartesianFloatData : FloatVectorDataType {
4293 private Mma8452QCartesianFloatData ( DataTypeBase input , Module module , byte register , byte id , DataAttributes attributes ) :
4394 base ( input , module , register , id , attributes ) { }
@@ -49,7 +100,7 @@ public override DataTypeBase copy(DataTypeBase input, Module module, byte regist
49100 return new Mma8452QCartesianFloatData ( input , module , register , id , attributes ) ;
50101 }
51102
52- public override IData createData ( bool logData , IModuleBoardBridge bridge , byte [ ] data , DateTime timestamp ) {
103+ public override DataBase createData ( bool logData , IModuleBoardBridge bridge , byte [ ] data , DateTime timestamp ) {
53104 return new AccelerationData ( bridge , this , timestamp , data ) ;
54105 }
55106
@@ -66,12 +117,80 @@ protected override DataTypeBase[] createSplits() {
66117 }
67118 }
68119
120+ [ DataContract ]
121+ private class Mma8452qOrientationDataType : DataTypeBase {
122+ private class OrientationData : DataBase {
123+ internal OrientationData ( DataTypeBase datatype , IModuleBoardBridge bridge , DateTime timestamp , byte [ ] bytes ) :
124+ base ( bridge , datatype , timestamp , bytes ) {
125+ }
126+
127+ public override Type [ ] Types => new Type [ ] { typeof ( SensorOrientation ) } ;
128+
129+ public override T Value < T > ( ) {
130+ var type = typeof ( T ) ;
131+
132+ if ( type == typeof ( SensorOrientation ) ) {
133+ int offset = ( bytes [ 0 ] & 0x06 ) >> 1 ;
134+ return ( T ) Convert . ChangeType ( ( SensorOrientation ) ( 4 * ( bytes [ 0 ] & 0x01 ) + ( ( offset == 2 || offset == 3 ) ? offset ^ 0x1 : offset ) ) , type ) ;
135+ }
136+
137+ return base . Value < T > ( ) ;
138+ }
139+ }
140+
141+ internal Mma8452qOrientationDataType ( ) : base ( ACCELEROMETER , ORIENTATION_VALUE , new DataAttributes ( new byte [ ] { 1 } , 1 , 0 , false ) ) {
142+ }
143+
144+ internal Mma8452qOrientationDataType ( DataTypeBase input , Module module , byte register , byte id , DataAttributes attributes ) :
145+ base ( input , module , register , id , attributes ) {
146+ }
147+
148+ public override DataTypeBase copy ( DataTypeBase input , Module module , byte register , byte id , DataAttributes attributes ) {
149+ return new Mma8452qOrientationDataType ( input , module , register , id , attributes ) ;
150+ }
151+
152+ public override DataBase createData ( bool logData , IModuleBoardBridge bridge , byte [ ] data , DateTime timestamp ) {
153+ return new OrientationData ( this , bridge , timestamp , data ) ;
154+ }
155+ }
156+ private class OrientationDataProducer : AsyncDataProducer , IOrientationDataProducer {
157+ private int delay = 100 ;
158+
159+ internal OrientationDataProducer ( DataTypeBase dataTypeBase , IModuleBoardBridge bridge ) : base ( ORIENTATION_ENABLE , dataTypeBase , bridge ) {
160+ }
161+
162+ public void Configure ( int delay = 100 ) {
163+ this . delay = delay ;
164+ }
165+
166+ public override void Start ( ) {
167+ AccelerometerMma8452q acc = bridge . GetModule < IAccelerometerMma8452q > ( ) as AccelerometerMma8452q ;
168+ bridge . sendCommand ( ACCELEROMETER , ORIENTATION_CONFIG , new byte [ ] { 0x00 , 0xc0 , ( byte ) ( delay / orientationSteps [ acc . PwMode ] [ acc . Odr ] ) , 0x44 , 0x84 } ) ;
169+
170+ base . Start ( ) ;
171+ }
172+
173+ public override void Stop ( ) {
174+ base . Stop ( ) ;
175+
176+ bridge . sendCommand ( ACCELEROMETER , ORIENTATION_CONFIG , new byte [ ] { 0x00 , 0x80 , 0x00 , 0x44 , 0x84 } ) ;
177+ }
178+ }
179+
69180 [ DataMember ] private readonly byte [ ] dataSettings = new byte [ ] { 0x00 , 0x00 , 0x18 , 0x00 , 0x00 } ;
70181 [ DataMember ] private Mma8452QCartesianFloatData accDataType , packedAccDataType ;
182+ [ DataMember ] private Mma8452qOrientationDataType orientationDataType ;
71183
72184 private IAsyncDataProducer acceleration = null , packedAcceleration = null ;
185+ private IOrientationDataProducer orientation = null ;
73186 private TimedTask < byte [ ] > readConfigTask ;
74187
188+ private int PwMode => dataSettings [ 3 ] & 0x3 ;
189+
190+ private int Odr => ( dataSettings [ 2 ] & ~ 0xc7 ) >> 3 ;
191+
192+ private int PulseLpfEn => ( dataSettings [ 1 ] & ~ 0x10 ) >> 4 ;
193+
75194 public AccelerometerMma8452q ( IModuleBoardBridge bridge ) : base ( bridge ) {
76195 accDataType = new Mma8452QCartesianFloatData ( DATA_VALUE , 1 ) ;
77196 packedAccDataType = new Mma8452QCartesianFloatData ( PACKED_ACC_DATA , 3 ) ;
@@ -97,6 +216,15 @@ public IAsyncDataProducer PackedAcceleration {
97216 }
98217 }
99218
219+ public IOrientationDataProducer Orientation {
220+ get {
221+ if ( orientation == null ) {
222+ orientation = new OrientationDataProducer ( orientationDataType , bridge ) ;
223+ }
224+ return orientation ;
225+ }
226+ }
227+
100228 internal override void aggregateDataType ( ICollection < DataTypeBase > collection ) {
101229 collection . Add ( accDataType ) ;
102230 collection . Add ( packedAccDataType ) ;
@@ -106,11 +234,26 @@ protected override void init() {
106234 readConfigTask = new TimedTask < byte [ ] > ( ) ;
107235 bridge . addRegisterResponseHandler ( Tuple . Create ( ( byte ) ACCELEROMETER , Util . setRead ( DATA_CONFIG ) ) ,
108236 response => readConfigTask . SetResult ( response ) ) ;
237+
238+ if ( orientationDataType == null ) {
239+ orientationDataType = new Mma8452qOrientationDataType ( ) ;
240+ }
109241 }
110242
111- public void Configure ( OutputDataRate odr , DataRange range ) {
112- dataSettings [ 2 ] |= ( byte ) ( ( byte ) odr << 3 ) ;
113- dataSettings [ 0 ] |= ( byte ) range ;
243+ public void Configure ( OutputDataRate odr = OutputDataRate . _100Hz , DataRange range = DataRange . _2g , float ? highPassCutoff = null ,
244+ Oversampling oversample = Oversampling . Normal ) {
245+ for ( int i = 0 ; i < dataSettings . Length ; i ++ ) {
246+ dataSettings [ i ] = 0 ;
247+ }
248+
249+ dataSettings [ 3 ] |= ( byte ) oversample ;
250+ dataSettings [ 2 ] |= ( byte ) ( ( byte ) odr << 3 ) ;
251+ dataSettings [ 0 ] |= ( byte ) range ;
252+
253+ if ( highPassCutoff != null ) {
254+ dataSettings [ 1 ] |= ( byte ) ( Util . closestIndex ( OS_CUTOFF_FREQS [ ( int ) oversample ] [ ( int ) odr ] , highPassCutoff . Value ) & 0x3 ) ;
255+ dataSettings [ 0 ] |= 0x10 ;
256+ }
114257
115258 bridge . sendCommand ( ACCELEROMETER , DATA_CONFIG , dataSettings ) ;
116259 }
0 commit comments