A compilation of some hardware sensors and their shared programming interfaces.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MAG3110.cpp Source File

MAG3110.cpp

00001 /* MAG3110.cpp
00002  * Tested with mbed board: FRDM-KL46Z
00003  * Author: Mark Gottscho
00004  * mgottscho@ucla.edu
00005  */
00006  
00007 #include "mbed.h"
00008 #include "I2CSensor.h"
00009 #include "PeriodicSensor.h"
00010 #include "MAG3110.h"
00011 
00012 using namespace std;
00013 
00014 MAG3110::MAG3110 (PinName sda, PinName scl, int i2c_addr) : 
00015                                     I2CSensor(sda, scl, i2c_addr),
00016                                     PeriodicSensor(0.05), //default max sampling rate of 20Hz
00017                                     __x(0),
00018                                     __y(0),
00019                                     __z(0),
00020                                     __active(false),
00021                                     __adc_rate(adc_smpl_rate_t(0)),
00022                                     __ratio(oversmpl_ratio_t(0)),
00023                                     __rate(smpl_rate_t(0))
00024                                     {
00025 }
00026 
00027 MAG3110::~MAG3110() {}
00028 
00029 void MAG3110::selfInit() {
00030     __i2c.frequency(400000);
00031     setOutputSamplingParameters (HZ80, O16, NULL);
00032     
00033     //Enable auto magnetic sensor reset before each sample, as recommended in the datasheet
00034     uint8_t data = getRegister(CTRL_REG2);
00035     data |= CTRL_REG2_AUTO_MRST_EN_MASK; //Set the AUTO_MRST_EN bit
00036     setRegister(CTRL_REG2, data);
00037 }
00038 
00039 uint8_t MAG3110::whoAmI() {
00040     return getRegister(WHO_AM_I);
00041 }
00042         
00043 uint8_t MAG3110::getDataRegisterStatus () {
00044     return getRegister(DR_STATUS);      
00045 }
00046 
00047 uint8_t MAG3110::getSystemMode () {
00048     return getRegister(SYSMOD);       
00049 }
00050 
00051 bool MAG3110::isActive () {
00052     return (bool) (getRegister(CTRL_REG1) & 0x01);
00053 }
00054 
00055 void MAG3110::setActive (bool activate) {
00056     uint8_t data;
00057     data = getRegister(CTRL_REG1);
00058     if (activate)
00059         data |= CTRL_REG1_AC_MASK; //Set bit
00060     else
00061         data &= ~CTRL_REG1_AC_MASK; //Clear bit
00062     setRegister(CTRL_REG1, data);
00063     __active = activate;
00064 }
00065 
00066 
00067 void MAG3110::getOutputSamplingParameters (smpl_rate_t *rate, oversmpl_ratio_t *ratio, adc_smpl_rate_t *adc_rate) {
00068     if (rate != NULL)
00069         *rate = __rate;
00070     if (ratio != NULL)
00071         *ratio = __ratio;
00072     if (ratio != NULL)
00073         *adc_rate = __adc_rate;
00074 }
00075 
00076 
00077 bool MAG3110::setOutputSamplingParameters (smpl_rate_t rate, oversmpl_ratio_t ratio, adc_smpl_rate_t *adc_rate) {
00078     uint8_t dr;
00079     uint8_t os;
00080     adc_smpl_rate_t tmp_adc_rate;
00081     
00082     switch (rate) {
00083         default:
00084         case HZ80:
00085             switch (ratio) {
00086                 case O16:
00087                     tmp_adc_rate = AHZ1280;
00088                     dr = 0;
00089                     os = 0;
00090                     break;
00091                 //Other rate-ratio combinations are illegal
00092                 default:
00093                     return false;
00094             }
00095             break;
00096         
00097         case HZ40:
00098             switch (ratio) {
00099                 case O16:
00100                     tmp_adc_rate = AHZ640;
00101                     dr = 1;
00102                     os = 0;
00103                     break;
00104                 case O32:
00105                     tmp_adc_rate = AHZ1280;
00106                     dr = 0;
00107                     os = 1;
00108                     break;
00109                 //Other rate-ratio combinations are illegal
00110                 default:
00111                     return false; 
00112             }  
00113             break;
00114         
00115         case HZ20:
00116             switch (ratio) {
00117                 case O16:
00118                     tmp_adc_rate = AHZ320;
00119                     dr = 2;
00120                     os = 0;
00121                     break;
00122                 case O32: 
00123                     tmp_adc_rate = AHZ640;
00124                     dr = 1;
00125                     os = 1;
00126                     break;
00127                 case O64:
00128                     tmp_adc_rate = AHZ1280;
00129                     dr = 0;
00130                     os = 2;
00131                     break;
00132                 //Other rate-ratio combinations are illegal
00133                 default:
00134                     return false;
00135             }
00136             break;
00137             
00138         case HZ10:
00139             switch (ratio) {
00140                 case O16:
00141                     tmp_adc_rate = AHZ160;
00142                     dr = 3;
00143                     os = 0;
00144                     break;
00145                 case O32:
00146                     tmp_adc_rate = AHZ320;
00147                     dr = 2;
00148                     os = 1;
00149                     break;
00150                 case O64:
00151                     tmp_adc_rate = AHZ640;
00152                     dr = 1;
00153                     os = 2;
00154                     break;
00155                 case O128:
00156                     tmp_adc_rate = AHZ1280;
00157                     dr = 0;
00158                     os = 3;
00159                     break;
00160                 //This should be impossible
00161                 default:
00162                     return false;     
00163             }
00164             break;
00165         
00166         case HZ5:
00167             switch (ratio) {
00168                 case O16:
00169                     tmp_adc_rate = AHZ80;
00170                     dr = 4;
00171                     os = 0;
00172                     break;
00173                 case O32:
00174                     tmp_adc_rate = AHZ160;
00175                     dr = 3;
00176                     os = 1;
00177                     break;
00178                 case O64:
00179                     tmp_adc_rate = AHZ320;
00180                     dr = 2;
00181                     os = 2;
00182                     break;
00183                 case O128:
00184                     tmp_adc_rate = AHZ640;
00185                     dr = 1;
00186                     os = 3;
00187                     break;
00188                 //This should be impossible
00189                 default:
00190                     return false;  
00191             }
00192             break;
00193             
00194         case HZ2_5:
00195             switch (ratio) {
00196                 case O16:
00197                     tmp_adc_rate = AHZ80;
00198                     dr = 5;
00199                     os = 0;
00200                     break;
00201                 case O32:
00202                     tmp_adc_rate = AHZ80;
00203                     dr = 4;
00204                     os = 1;
00205                     break;
00206                 case O64:
00207                     tmp_adc_rate = AHZ160;
00208                     dr = 3;
00209                     os = 2;
00210                     break;
00211                 case O128:
00212                     tmp_adc_rate = AHZ320;
00213                     dr = 2;
00214                     os = 3;
00215                     break;
00216                 //This should be impossible
00217                 default:
00218                     return false;
00219             }
00220             break;
00221             
00222             case HZ1_25:
00223                 switch (ratio) {
00224                     case O16:
00225                         tmp_adc_rate = AHZ80;
00226                         dr = 6;
00227                         os = 0;
00228                         break;
00229                     case O32:
00230                         tmp_adc_rate = AHZ80;
00231                         dr = 5;
00232                         os = 1;
00233                         break;
00234                     case O64:
00235                         tmp_adc_rate = AHZ80;
00236                         dr = 4;
00237                         os = 2;
00238                         break;
00239                     case O128:
00240                         tmp_adc_rate = AHZ160;
00241                         dr = 3;
00242                         os = 3;
00243                         break;
00244                     //This should be impossible
00245                     default:
00246                         return false;   
00247                 }
00248                 break;
00249             
00250             case HZ0_63:
00251                 switch (ratio) {
00252                     case O16:
00253                         tmp_adc_rate = AHZ80;
00254                         dr = 7;
00255                         os = 0;
00256                         break;
00257                     case O32:
00258                         tmp_adc_rate = AHZ80;
00259                         dr = 6;
00260                         os = 1;
00261                         break;
00262                     case O64:
00263                         tmp_adc_rate = AHZ80;
00264                         dr = 5;
00265                         os = 2;
00266                         break;
00267                     case O128:
00268                         tmp_adc_rate = AHZ80;
00269                         dr = 4;
00270                         os = 3;
00271                         break;
00272                     //This should be impossible
00273                     default:
00274                         return false;   
00275                 }
00276                 break;
00277                 
00278             case HZ0_31:
00279                 switch (ratio) {
00280                     case O32:
00281                         tmp_adc_rate = AHZ80;
00282                         dr = 7;
00283                         os = 1;
00284                         break;
00285                     case O64:
00286                         tmp_adc_rate = AHZ80;
00287                         dr = 6;
00288                         os = 2;
00289                         break;
00290                     case O128:
00291                         tmp_adc_rate = AHZ80;
00292                         dr = 5;
00293                         os = 3;
00294                         break;
00295                     default:
00296                         return false;   
00297                 }
00298                 break;
00299                 
00300             case HZ0_16:
00301                 switch (ratio) {
00302                     case O64:
00303                         tmp_adc_rate = AHZ80;
00304                         dr = 7;
00305                         os = 2;
00306                         break;
00307                     case O128:
00308                         tmp_adc_rate = AHZ80;
00309                         dr = 6;
00310                         os = 3;
00311                         break;
00312                     default:
00313                         return false;   
00314                 }
00315                 break;
00316                 
00317             case HZ0_08:
00318                 switch (ratio) {
00319                     case O128:
00320                         tmp_adc_rate = AHZ80;
00321                         dr = 7;
00322                         os = 3;
00323                         break;
00324                     default:
00325                         return false;   
00326                 }
00327                 break;
00328     }
00329     
00330     //Deactivate to update register
00331     bool wasActive = __active;
00332     setActive (false);
00333     
00334     //Update value for the caller
00335     if (adc_rate != NULL)
00336         *adc_rate = tmp_adc_rate;
00337         
00338     //Update CTRL_REG1 DR and OS fields
00339     uint8_t data = getRegister(CTRL_REG1);
00340     uint8_t dr_os = (dr << 5) | (os << 3); //Set DR in 3 MSB, OS in next 2 bits. 3 LSB are 0
00341     data = (data & ~(CTRL_REG1_DR_MASK | CTRL_REG1_OS_MASK)) | ((CTRL_REG1_DR_MASK | CTRL_REG1_OS_MASK) & dr_os); //Update 5 MSB
00342     setRegister(CTRL_REG1, data);
00343     
00344     //Update cached values
00345     __adc_rate = tmp_adc_rate;
00346     __ratio = ratio;
00347     __rate = rate;
00348     
00349     if (wasActive)
00350         setActive (true);
00351     
00352     return true;
00353 }
00354 
00355 
00356 
00357 int16_t MAG3110::getX (bool sampleNow) {
00358     __disable_irq();
00359     if (sampleNow) {
00360         uint8_t data_msb, data_lsb;
00361         data_msb = getRegister(OUT_X_MSB);
00362         data_lsb = getRegister(OUT_X_LSB);
00363         __x = data_msb << 8;
00364         __x |= data_lsb;
00365     }
00366     
00367     __dataReady = false;
00368     __enable_irq();
00369     
00370     return __x;
00371 }
00372 
00373 int16_t MAG3110::getY (bool sampleNow) {
00374     __disable_irq();
00375     if (sampleNow) {
00376         uint8_t data_msb, data_lsb;
00377         data_msb = getRegister(OUT_Y_MSB);
00378         data_lsb = getRegister(OUT_Y_LSB);
00379         __y = data_msb << 8;
00380         __y |= data_lsb;
00381     }
00382     
00383     __dataReady = false;
00384     __enable_irq();
00385     
00386     return __y;
00387 }
00388 
00389 int16_t MAG3110::getZ (bool sampleNow) {
00390     __disable_irq();    
00391     if (sampleNow) {
00392         uint8_t data_msb, data_lsb;
00393         data_msb = getRegister(OUT_Z_MSB);
00394         data_lsb = getRegister(OUT_Z_LSB);
00395         __z = data_msb << 8;
00396         __z |= data_lsb;
00397     }
00398     
00399     __dataReady = false;
00400     __enable_irq();
00401     
00402     return __z;
00403 }  
00404 
00405 float MAG3110::getFloatX (bool sampleNow) {
00406     return getX (sampleNow) * DATA_CONVERSION;   
00407 }
00408 
00409 float MAG3110::getFloatY (bool sampleNow) {
00410     return getY (sampleNow) * DATA_CONVERSION;   
00411 }
00412 
00413 float MAG3110::getFloatZ (bool sampleNow) {
00414     return getZ (sampleNow) * DATA_CONVERSION;   
00415 }
00416 
00417 int8_t MAG3110::getDieTemp() {
00418     return (int8_t) getRegister(DIE_TEMP);
00419 }
00420 
00421 float MAG3110::getFloatDieTemp () {
00422     return getDieTemp() * TEMP_DIV;   
00423 }
00424 
00425 void MAG3110::__sample_data_ISR() {
00426     getX (true);
00427     getY (true);
00428     getZ (true);
00429     __dataReady = true;
00430 }