Library for interfacing with the RM3100 magnetometer from PNI Sensor Corporation
Dependents: Hello_RM3100 RM3100
Rm3100.cpp
- Committer:
- fwrawx
- Date:
- 2018-05-24
- Revision:
- 1:8646c63a8dbe
- Parent:
- 0:b6ab7f28cde2
File content as of revision 1:8646c63a8dbe:
#include <stdint.h> #include "Rm3100.hpp" Rm3100::Rm3100(PinName sda, PinName scl, uint8_t addr) : _i2c(sda, scl), _addr(addr), _scale(1.0f, 1.0f, 1.0f), _sample_delay_ms(1) {} Rm3100::~Rm3100() {} int Rm3100::Begin(void) { uint8_t revid = 0x00; struct CycleCounts cc = { 0 }; int ret; // get hardware revision and validate ret = GetHardwareRevision(&revid); if (ret) { return ret; } if (revid != RM3100_REVID) { return RM3100_RET_ENODEV; } // get current cycle counts ret = GetCycleCounts(&cc); if (ret) { return ret; } // update scale UpdateMeasurementScale(&cc); return RM3100_RET_OK; } /* * (0x00) POLL */ int Rm3100::GetSingleMeasurementMode(struct SingleMeasurementMode *smm) { return Read(RM3100_REG_POLL, (uint8_t *)smm, sizeof(*smm)); } int Rm3100::SetSingleMeasurementMode(struct SingleMeasurementMode *smm) { return Write(RM3100_REG_POLL, (uint8_t *)smm, sizeof(*smm)); } int Rm3100::SetSingleMeasurementMode(bool x, bool y, bool z) { struct SingleMeasurementMode smm = { .res0 = 0, .pmx = x, .pmy = y, .pmz = z, .res7 = 0, }; return SetSingleMeasurementMode(&smm); } /* * (0x01) CMM */ int Rm3100::GetContinuousMeasurementMode(struct ContinuousMeasurementMode *cmm) { return Read(RM3100_REG_CMM, (uint8_t *)cmm, sizeof(*cmm)); } int Rm3100::SetContinuousMeasurementMode(struct ContinuousMeasurementMode *cmm) { return Write(RM3100_REG_CMM, (uint8_t *)cmm, sizeof(*cmm)); } int Rm3100::SetContinuousMeasurementMode(bool enabled, uint8_t drdm, bool x, bool y, bool z) { struct ContinuousMeasurementMode cmm = { .start = enabled, .res1 = 0, .drdm = (drdm & RM3100_DRDM_MASK), .cmx = x, .cmy = y, .cmz = z, .res7 = 0, }; return SetContinuousMeasurementMode(&cmm); } int Rm3100::SetContinuousMeasurementMode(bool enabled) { return SetContinuousMeasurementMode(enabled, RM3100_DRDM_ALL_AXES, enabled, enabled, enabled); } /* * (0x04 -- 0x09) CCX, CCY, CCZ */ int Rm3100::GetCycleCounts(struct CycleCounts *cc) { uint8_t buffer[6]; int ret = Read(RM3100_REG_CCX, buffer, sizeof(buffer)); if (ret) { return ret; } cc->x = (buffer[0] << 8) | buffer[1]; cc->y = (buffer[2] << 8) | buffer[3]; cc->z = (buffer[4] << 8) | buffer[5]; return RM3100_RET_OK; } int Rm3100::SetCycleCounts(struct CycleCounts *cc) { // convert to BE uint8_t buffer[] = { (cc->x >> 8), (cc->x & 0xFF), (cc->y >> 8), (cc->y & 0xFF), (cc->z >> 8), (cc->z & 0xFF), }; UpdateMeasurementScale(cc); return Write(RM3100_REG_CCX, buffer, sizeof(buffer)); } int Rm3100::SetCycleCounts(uint16_t x, uint16_t y, uint16_t z) { struct CycleCounts cc = { .x = x, .y = y, .z = z, }; return SetCycleCounts(&cc); } int Rm3100::SetCycleCounts(uint16_t xy, uint16_t z) { return SetCycleCounts(xy, xy, z); } int Rm3100::SetCycleCounts(uint16_t xyz) { return SetCycleCounts(xyz, xyz, xyz); } void Rm3100::UpdateMeasurementScale(struct CycleCounts *cc) { _scale.x = 1.0f / ((cc->x * 0.3627f) + 1.85f); _scale.y = 1.0f / ((cc->y * 0.3627f) + 1.85f); _scale.z = 1.0f / ((cc->z * 0.3627f) + 1.85f); } /* * (0x0B) TMRC */ int Rm3100::GetContinuousMeasurementModeUpdateRate(uint8_t *tmrc) { return Read(RM3100_REG_TMRC, tmrc, sizeof(*tmrc)); } int Rm3100::SetContinuousMeasurementModeUpdateRate(uint8_t tmrc) { uint8_t value = (tmrc & RM3100_CMM_RATE_MASK) | RM3100_CMM_RATE_MSB; return Write(RM3100_REG_TMRC, &value, sizeof(value)); } int Rm3100::SetRate(float rate) { float r = 600.0f; uint8_t tmrc = RM3100_CMM_RATE_600_0_HZ; while ((tmrc < RM3100_CMM_RATE_MASK) && ((r / 2.0f) >= rate)) { r /= 2.0f; tmrc++; } return SetContinuousMeasurementModeUpdateRate(tmrc); } int Rm3100::GetStatus(struct Status *status) { return Read(RM3100_REG_STATUS, (uint8_t *)status, sizeof(*status)); } int Rm3100::GetMeasurement(struct Measurement *m) { uint8_t buffer[9] = { 0 }; int ret = Read(RM3100_REG_MX, buffer, sizeof(buffer)); if (ret) { return ret; } m->x = (((int8_t)buffer[0]) << 16) | (buffer[1] << 8) | (buffer[2]); m->y = (((int8_t)buffer[3]) << 16) | (buffer[4] << 8) | (buffer[5]); m->z = (((int8_t)buffer[6]) << 16) | (buffer[7] << 8) | (buffer[8]); return RM3100_RET_OK; } int Rm3100::GetSample(struct Sample *s) { struct Measurement m = { 0 }; int ret = GetMeasurement(&m); if (ret) { return ret; } s->x = (float)m.x * _scale.x; s->y = (float)m.y * _scale.y; s->z = (float)m.z * _scale.z; return RM3100_RET_OK; } int Rm3100::GetSelfTestConfig(struct SelfTestConfig *cfg) { return Read(RM3100_REG_BIST, (uint8_t *)cfg, sizeof(*cfg)); } int Rm3100::SetSelfTestConfig(struct SelfTestConfig *cfg) { return Write(RM3100_REG_BIST, (uint8_t *)cfg, sizeof(*cfg)); } int Rm3100::SetSelfTestConfig(uint8_t count, uint8_t timeout, bool enabled) { struct SelfTestConfig cfg = { .bp = (count & RM3100_SELF_TEST_COUNT_MASK), .bw = (timeout & RM3100_SELF_TEST_TIMEOUT_MASK), .ste = enabled, }; return SetSelfTestConfig(&cfg); } int Rm3100::PerformSelfTest(uint8_t count, uint8_t timeout, struct SelfTestConfig *result) { // configure test int ret = SetSelfTestConfig(count, timeout, true); if (ret) { return ret; } osDelay(1); // initiate single measurement ret = SetSingleMeasurementMode(true, true, true); if (ret) { return ret; } // wait 1 ms for measurement osDelay(1); // get result ret = GetSelfTestConfig(result); if (ret) { return ret; } osDelay(1); return ClearSelfTest(); } int Rm3100::ClearSelfTest() { uint8_t value = 0; return Write(RM3100_REG_BIST, &value, sizeof(value)); } int Rm3100::GetHandShakeConfig(struct HandShakeConfig *cfg) { return Read(RM3100_REG_HSHAKE, (uint8_t *)cfg, sizeof(*cfg)); } int Rm3100::SetHandShakeConfig(struct HandShakeConfig *cfg) { cfg->res2 = 0; cfg->res3 = 1; return Write(RM3100_REG_HSHAKE, (uint8_t *)cfg, sizeof(*cfg)); } int Rm3100::SetDrdyClearConfig(bool on_write, bool on_read_measurement) { struct HandShakeConfig cfg = { .drc0 = on_write, .drc1 = on_read_measurement, }; return SetHandShakeConfig(&cfg); } int Rm3100::GetHardwareRevision(uint8_t *rev) { return Read(RM3100_REG_REVID, rev, sizeof(*rev)); } int Rm3100::Read(uint8_t reg, uint8_t *buffer, uint8_t count) { _i2c.write(_addr, (const char *)®, sizeof(reg), true); return _i2c.read(_addr, (char *)buffer, count, false) ? RM3100_RET_EIO : RM3100_RET_OK; } int Rm3100::Write(uint8_t reg, uint8_t *buffer, uint8_t count) { uint8_t data[count + 1]; data[0] = reg; memcpy(&data[1], buffer, count); return _i2c.write(_addr, (const char *)data, count + 1, false) ? RM3100_RET_EIO : RM3100_RET_OK; }