libraries / Mitov / Mitov_Compass_AK8963.hon commit Added link to project report (97a3ba0)
   1////////////////////////////////////////////////////////////////////////////////
   2//                                                                            //
   3//     This software is supplied under the terms of a license agreement or    //
   4//     nondisclosure agreement with Mitov Software and may not be copied      //
   5//     or disclosed except in accordance with the terms of that agreement.    //
   6//         Copyright(c) 2002-2016 Mitov Software. All Rights Reserved.        //
   7//                                                                            //
   8////////////////////////////////////////////////////////////////////////////////
   9
  10#ifndef _MITOV_AK8963_h
  11#define _MITOV_COMPASS_AK8963_h
  12
  13#include <Mitov.h>
  14#include <Wire.h> //I2C Arduino Library
  15#include <Mitov_Basic_I2C.h>
  16
  17namespace Mitov
  18{
  19//---------------------------------------------------------------------------
  20        enum CompassAK8963Mode { cmSingleMeasurement, cm8Hz, cm100Hz, cmExternalTrigger };
  21//---------------------------------------------------------------------------
  22        namespace CompassAK8963Const
  23        {
  24                const byte CompassModes[] =
  25                {
  26                        0b00000001,
  27                        0b00000010,
  28                        0b00000110,
  29                        0b00000100
  30                };
  31        }
  32//---------------------------------------------------------------------------
  33        class CompassAK8963 : public Mitov::EnabledComponent, public Mitov::ClockingSupport
  34        {
  35                typedef Mitov::EnabledComponent inherited;
  36
  37        protected:
  38                static const byte MPU9150_RA_MAG_ST1            = 0x02;
  39                static const byte MPU9150_RA_MAG_XOUT_L         = 0x03;
  40                static const byte MPU9150_RA_MAG_XOUT_H         = 0x04;
  41                static const byte MPU9150_RA_MAG_YOUT_L         = 0x05;
  42                static const byte MPU9150_RA_MAG_YOUT_H         = 0x06;
  43                static const byte MPU9150_RA_MAG_ZOUT_L         = 0x07;
  44                static const byte MPU9150_RA_MAG_ZOUT_H         = 0x08;
  45                static const byte MPU9150_RA_MAG_ST2            = 0x09;
  46                static const byte MPU9150_RA_MAG_CNTL1          = 0x0A;
  47                static const byte MPU9150_RA_MAG_CNTL2          = 0x0B;
  48
  49                static const byte MPU9150_RA_MAG_ASAX           = 0x10;
  50                static const byte MPU9150_RA_MAG_ASAY           = 0x11;
  51                static const byte MPU9150_RA_MAG_ASAZ           = 0x12;
  52
  53        public:
  54                OpenWire::SourcePin     OutputPins[ 3 ];
  55
  56                OpenWire::SinkPin       ResetInputPin;
  57                OpenWire::SourcePin OverflowOutputPin;
  58
  59        public:
  60                CompassAK8963Mode       Mode : 2;
  61                bool Enabled : 1;
  62                bool SelfTest : 1; // Added to save space as bitfield
  63                byte Address : 2;
  64                bool HighResolution : 1;
  65
  66        protected:
  67                float CompassAdjustmentValues[ 3 ];
  68
  69        protected:
  70                void PerformRead()
  71                {
  72                        const float CompassCoefficients[] =
  73                        {
  74                                10.0f *4219.0f / 8190.0f,
  75                                10.0f *4219.0f / 32760.0f
  76                        };
  77
  78                        uint8_t AIntValues[ 7 ];
  79                        if( ReadBytes( MPU9150_RA_MAG_XOUT_L, 7, AIntValues ))
  80                                for( int i = 0; i < 3; ++i )
  81                                {
  82                                        float AValue = (( ((int16_t)AIntValues[ i * 2 + 1 ] ) << 8 ) | AIntValues[ i * 2 ] ) * CompassCoefficients[ HighResolution & 1 ] * CompassAdjustmentValues[ i ];
  83                                        OutputPins[ i ].Notify( &AValue );
  84                                }
  85
  86                }
  87
  88                void ReadSensors()
  89                {
  90                        uint8_t AIntValue;
  91
  92                        if( Mode == cmSingleMeasurement )
  93                        {
  94                                UpdateCompassControlReg();
  95                                delay(10);
  96                                PerformRead();
  97                        }
  98
  99                        if( ReadBytes( MPU9150_RA_MAG_ST1, 1, &AIntValue ))
 100                        {
 101                                OverflowOutputPin.SendValue( AIntValue & 0b00000010 );
 102                                if( AIntValue & 0b00000001 )
 103                                        PerformRead();
 104                        }
 105
 106                }
 107
 108                void UpdateCompassControlReg()
 109                {
 110                        byte AValue;
 111                        if( Enabled )
 112                                AValue = CompassAK8963Const::CompassModes[ Mode ];
 113
 114                        else
 115                                AValue = 0;
 116
 117                        AValue |=       ( HighResolution        ? 0b00010000 : 0 );
 118
 119                        WriteByte( MPU9150_RA_MAG_CNTL1, AValue );
 120                }
 121
 122                void ReagCompassAdjustmentValues()
 123                {
 124                        uint8_t AValues[ 3 ];
 125
 126                        ReadBytes( MPU9150_RA_MAG_ASAX, sizeof( AValues ), AValues );
 127                        for( int i = 0; i < 3; ++i )
 128                                CompassAdjustmentValues[ i ] = (((float) AValues[ i ] ) - 128.0f) / 256.0f + 1.0f;
 129
 130                }
 131
 132        protected:
 133                inline void WriteByte( byte ARegister, byte AData )
 134                {
 135                        I2C::WriteByte( Address + 0x0C, ARegister, AData );
 136                }
 137
 138                bool ReadBytes( uint8_t regAddr, uint8_t length, void *data )
 139                {
 140                        return I2C::ReadBytes( Address + 0x0C, regAddr, length, data );
 141                }
 142
 143        protected:
 144                virtual void SystemStart() override
 145                {
 146                        UpdateCompassControlReg();
 147                        ReagCompassAdjustmentValues();
 148
 149                        inherited::SystemStart();
 150                }
 151
 152                virtual void SystemLoopBegin( unsigned long currentMicros ) override
 153                {
 154
 155                        if( Enabled )
 156                                if( ! ClockInputPin.IsConnected() )
 157                                        ReadSensors();
 158
 159                        inherited::SystemLoopBegin( currentMicros );
 160                }
 161
 162        protected:
 163                virtual void DoClockReceive( void *_Data ) override
 164                {
 165                        ReadSensors();
 166                }
 167
 168                void DoResetReceive( void *_Data )
 169                {
 170                        WriteByte( MPU9150_RA_MAG_CNTL2, 0b00000001 );
 171                }
 172
 173        public:
 174                CompassAK8963() :
 175                        Mode( cm100Hz ),
 176                        Enabled( true ),
 177                        SelfTest( false ),
 178                        HighResolution( true ),
 179                        Address( 0 )
 180                {
 181                        ResetInputPin.SetCallback( MAKE_CALLBACK( CompassAK8963::DoResetReceive ));
 182                }
 183        };
 184//---------------------------------------------------------------------------
 185        class CompassAK8963I2C : public Mitov::CompassAK8963
 186        {
 187                typedef Mitov::CompassAK8963    inherited;
 188        };
 189//---------------------------------------------------------------------------
 190}
 191
 192#endif