Llibrary for the WiGo MPL3115A2, I2C Precision Altimeter sensor.
Fork of MPL3115A2 by
MPL3115A2.cpp
- Committer:
- clemente
- Date:
- 2013-05-30
- Revision:
- 4:fdf14a259af8
- Parent:
- 3:a2f1752add9a
- Child:
- 5:9edec5ee8bf4
File content as of revision 4:fdf14a259af8:
#include "MPL3115A2.h" #define REG_WHO_AM_I 0x0C // return 0xC4 by default #define REG_STATUS 0x00 #define REG_CTRL_REG_1 0x26 #define REG_CTRL_REG_3 0x28 #define REG_CTRL_REG_4 0x29 #define REG_CTRL_REG_5 0x2A #define REG_PRESSURE_MSB 0x01 // 3 byte pressure data #define REG_ALTIMETER_MSB 0x01 // 3 byte altimeter data #define REG_TEMP_MSB 0x04 // 2 byte temperature data #define REG_PT_DATA_CFG 0x13 #define REG_P_TGT_MSB 0x16 #define REG_P_WND_MSB 0x19 #define UINT14_MAX 16383 /** Interrupt schema * * :: The Altitude Trigger use the IRQ1. * * Altitude Trigger -- MPL3115A2_Int1.fall --- AltitudeTrg_IRQ --- user1_fptr * * * :: The Data ready use the IRQ2. * * Data Ready -- MPL3115A2_Int2.fall --- DataReady_IRQ --- user2_fptr * */ void (*user2_fptr)(void); // Pointers to user function called after void (*user1_fptr)(void); // IRQ assertion. // InterruptIn MPL3115A2_Int1( PTD4); // INT1 InterruptIn MPL3115A2_Int2( PTA12); // INT2 MPL3115A2::MPL3115A2(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr) { MPL3115A2_mode = BAROMETRIC_MODE; MPL3115A2_oversampling = OVERSAMPLE_RATIO_1; // user1_fptr = NULL; user2_fptr = NULL; MPL3115A2_Int1.fall( NULL); MPL3115A2_Int2.fall( NULL); } void MPL3115A2::Reset( void) { unsigned char t; // soft reset... readRegs( REG_CTRL_REG_1, &t, 1); unsigned char data[2] = { REG_CTRL_REG_1, t|0x04}; writeRegs(data, 2); wait( 0.1); } void MPL3115A2::DataReady( void(*fptr)(void), unsigned char OS) { unsigned char dt[5]; unsigned char data[2]; // Soft Reset Reset(); Standby(); // Clear all interrupts by reading the output registers. readRegs( REG_ALTIMETER_MSB, &dt[0], 5); getStatus(); // Configure INT active low and pullup data[0] = REG_CTRL_REG_3; data[1] = 0x00; writeRegs(data, 2); // Enable Interrupt fot data ready data[0] = REG_CTRL_REG_4; data[1] = 0x80; writeRegs(data, 2); // Configure Interrupt to route to INT2 data[0] = REG_CTRL_REG_5; data[1] = 0x00; writeRegs(data, 2); data[0] = REG_PT_DATA_CFG; data[1] = 0x07; writeRegs(data, 2); // Configure the OverSampling rate, Altimeter/Barometer mode and set the sensor Active data[0] = REG_CTRL_REG_1; data[1] = (OS<<3); // if (MPL3115A2_mode == BAROMETRIC_MODE) data[1] &= 0x7F; else data[1] |= 0x80; // data[1] |= 0x01; writeRegs(data, 2); user2_fptr = fptr; MPL3115A2_Int2.fall( this, &MPL3115A2::DataReady_IRQ); } void MPL3115A2::DataReady_IRQ( void) { // Clear the IRQ flag getStatus(); // Run the user supplied function user2_fptr(); } void MPL3115A2::AltitudeTrigger( void(*fptr)(void), unsigned short level) { unsigned char dt[5]; unsigned char data[2]; // Soft Reset Reset(); // The device is on standby Standby(); // Clear all interrupts by reading the output registers. readRegs( REG_ALTIMETER_MSB, &dt[0], 5); getStatus(); // Write Target and Window Values dt[0] = REG_P_TGT_MSB; dt[1] = (level>>8); dt[2] = (level&0xFF); writeRegs( dt, 3); // Window values are zero dt[0] = REG_P_WND_MSB; dt[1] = 0; dt[2] = 0; writeRegs( dt, 3); // Enable Pressure Threshold interrupt data[0] = REG_CTRL_REG_4; data[1] = 0x08; writeRegs( data, 2); // Interrupt is routed to INT1 data[0] = REG_CTRL_REG_5; data[1] = 0x08; writeRegs( data, 2); data[0] = REG_PT_DATA_CFG; data[1] = 0x07; writeRegs(data, 2); // Configure the OverSampling rate, Altimeter mode and set the sensor Active data[0] = REG_CTRL_REG_1; data[1] = 0x81 | (MPL3115A2_oversampling<<3); writeRegs(data, 2); user1_fptr = fptr; MPL3115A2_Int1.fall( this, &MPL3115A2::AltitudeTrg_IRQ); } void MPL3115A2::AltitudeTrg_IRQ( void) { // Clear the IRQ flag getStatus(); // Run the user supplied function user1_fptr(); } void MPL3115A2::Barometric_Mode( void) { unsigned char t; unsigned char data[2]; Standby(); // soft reset... Reset(); Standby(); readRegs( REG_CTRL_REG_1, &t, 1); // Set the Barometric mode data[0] = REG_CTRL_REG_1; data[1] = t&0x7F; writeRegs(data, 2); data[0] = REG_PT_DATA_CFG; data[1] = 0x07; writeRegs(data, 2); Oversample_Ratio( MPL3115A2_oversampling); Active(); MPL3115A2_mode = BAROMETRIC_MODE; } void MPL3115A2::Altimeter_Mode( void) { unsigned char t; unsigned char data[2]; Standby(); // soft reset... Reset(); Standby(); readRegs( REG_CTRL_REG_1, &t, 1); data[0] = REG_CTRL_REG_1; data[1] = t|0x80; writeRegs(data, 2); data[0] = REG_PT_DATA_CFG; data[1] = 0x07; writeRegs(data, 2); Oversample_Ratio( MPL3115A2_oversampling); Active(); MPL3115A2_mode = ALTIMETER_MODE; } void MPL3115A2::Oversample_Ratio( unsigned int ratio) { unsigned char t; Standby(); readRegs( REG_CTRL_REG_1, &t, 1); t = t & 0xE7; t = t | ( ratio<<3); unsigned char data[2] = { REG_CTRL_REG_1, t}; writeRegs(data, 2); Active(); MPL3115A2_oversampling = ratio; } void MPL3115A2::Active( void) { unsigned char t; // Activate the peripheral readRegs(REG_CTRL_REG_1, &t, 1); unsigned char data[2] = {REG_CTRL_REG_1, t|0x01}; writeRegs(data, 2); } void MPL3115A2::Standby( void) { unsigned char t; // Standby readRegs(REG_CTRL_REG_1, &t, 1); unsigned char data[2] = {REG_CTRL_REG_1, t&0xFE}; writeRegs(data, 2); } unsigned char MPL3115A2::getDeviceID() { unsigned char device_id = 0; readRegs(REG_WHO_AM_I, &device_id, 1); return device_id; } unsigned int MPL3115A2::isDataAvailable( void) { unsigned char status; readRegs( REG_STATUS, &status, 1); if ( status & 0x08) { return 1; } else { return 0; } } unsigned char MPL3115A2::getStatus( void) { unsigned char status; readRegs( REG_STATUS, &status, 1); return status; } void MPL3115A2::getAllData( float *f) { if ( MPL3115A2_mode == ALTIMETER_MODE) { f[0] = getAltimeter(); } else { f[0] = getPressure(); } f[1] = getTemperature(); } float MPL3115A2::getAltimeter( void) { unsigned char dt[3]; unsigned short altm; float faltm; /* * dt[0] = Bits 12-19 of 20-bit real-time Pressure sample. (b7-b0) * dt[1] = Bits 4-11 of 20-bit real-time Pressure sample. (b7-b0) * dt[2] = Bits 0-3 of 20-bit real-time Pressure sample (b7-b4) */ readRegs( REG_ALTIMETER_MSB, &dt[0], 3); altm = (dt[0]<<8) | dt[1]; // if ( dt[0] > 0x7F) { altm = ~altm + 1; faltm = (float)altm * -1.0f; } else { faltm = (float)altm * 1.0f; } // faltm = faltm+((float)(dt[2]>>4) * 0.0625f); return faltm; } float MPL3115A2::getPressure( void) { unsigned char dt[3]; unsigned int prs; float fprs; /* * dt[0] = Bits 12-19 of 20-bit real-time Pressure sample. (b7-b0) * dt[1] = Bits 4-11 of 20-bit real-time Pressure sample. (b7-b0) * dt[2] = Bits 0-3 of 20-bit real-time Pressure sample (b7-b4) */ readRegs( REG_PRESSURE_MSB, &dt[0], 3); prs = (dt[0]<<10) | (dt[1]<<2) | (dt[2]>>6); // fprs = (float)prs * 1.0f; if ( dt[2] & 0x20) fprs += 0.25f; if ( dt[2] & 0x10) fprs += 0.5f; return fprs; } float MPL3115A2::getTemperature( void) { unsigned char dt[2]; unsigned short temp; float ftemp; /* * dt[0] = Bits 4-11 of 16-bit real-time temperature sample. (b7-b0) * dt[1] = Bits 0-3 of 16-bit real-time temperature sample. (b7-b4) */ readRegs( REG_TEMP_MSB, &dt[0], 2); temp = dt[0]; // if ( dt[0] > 0x7F) { temp = ~temp + 1; ftemp = (float)temp * -1.0f; } else { ftemp = (float)temp * 1.0f; } // ftemp = ftemp+((float)(dt[1]>>4) * 0.0625f); return ftemp; } void MPL3115A2::readRegs(int addr, uint8_t * data, int len) { char t[1] = {addr}; m_i2c.write(m_addr, t, 1, true); m_i2c.read(m_addr, (char *)data, len); } void MPL3115A2::writeRegs(uint8_t * data, int len) { m_i2c.write(m_addr, (char *)data, len); }