From e835187e21c308bc337eb58e6ca2bd179b6c132f Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 8 Feb 2023 10:34:08 +0000 Subject: [PATCH 1/9] Add doWrite parameter for shadow bits. Update getTemperature Set the TM_T bit using shadow memory - instead of doing a read-modify-write. Reading INT_CTRL_0_REG returns 0x61 (OTP_Read, Auto_SR_En and TM_M). I don't know why... --- src/SparkFun_MMC5983MA_Arduino_Library.cpp | 23 +++++++++++++++------- src/SparkFun_MMC5983MA_Arduino_Library.h | 8 ++++---- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/SparkFun_MMC5983MA_Arduino_Library.cpp b/src/SparkFun_MMC5983MA_Arduino_Library.cpp index d685e3c..3d8334f 100644 --- a/src/SparkFun_MMC5983MA_Arduino_Library.cpp +++ b/src/SparkFun_MMC5983MA_Arduino_Library.cpp @@ -15,7 +15,7 @@ #include "SparkFun_MMC5983MA_Arduino_Library.h" #include "SparkFun_MMC5983MA_Arduino_Library_Constants.h" -bool SFE_MMC5983MA::setShadowBit(uint8_t registerAddress, const uint8_t bitMask) +bool SFE_MMC5983MA::setShadowBit(uint8_t registerAddress, const uint8_t bitMask, bool doWrite) { uint8_t *shadowRegister = nullptr; @@ -53,13 +53,15 @@ bool SFE_MMC5983MA::setShadowBit(uint8_t registerAddress, const uint8_t bitMask) if (shadowRegister) { *shadowRegister |= bitMask; - return (mmc_io.writeSingleByte(registerAddress, *shadowRegister)); + if (doWrite) + return (mmc_io.writeSingleByte(registerAddress, *shadowRegister)); + return true; } return false; } -bool SFE_MMC5983MA::clearShadowBit(uint8_t registerAddress, const uint8_t bitMask) +bool SFE_MMC5983MA::clearShadowBit(uint8_t registerAddress, const uint8_t bitMask, bool doWrite) { uint8_t *shadowRegister = nullptr; @@ -97,7 +99,9 @@ bool SFE_MMC5983MA::clearShadowBit(uint8_t registerAddress, const uint8_t bitMas if (shadowRegister) { *shadowRegister &= ~bitMask; - return (mmc_io.writeSingleByte(registerAddress, *shadowRegister)); + if (doWrite) + return (mmc_io.writeSingleByte(registerAddress, *shadowRegister)); + return true; } return false; @@ -234,10 +238,13 @@ bool SFE_MMC5983MA::isConnected() int SFE_MMC5983MA::getTemperature() { - // Send command to device. Since TM_T clears itself we don't need to - // use the shadow register for this - we can send the command directly to the IC. - if (!mmc_io.setRegisterBit(INT_CTRL_0_REG, TM_T)) + // Set the TM_T bit to start the temperature conversion. + // Do this using the shadow register. If we do it with setRegisterBit + // (read-modify-write) we end up setting the Auto_SR_en bit too as that + // always seems to read as 1...? I don't know why. + if (!setShadowBit(INT_CTRL_0_REG, TM_T)) { + clearShadowBit(INT_CTRL_0_REG, TM_T, false); // Clear the bit - in shadow memory only SAFE_CALLBACK(errorCallback, SF_MMC5983MA_ERROR::BUS_ERROR); return -99; } @@ -249,6 +256,8 @@ int SFE_MMC5983MA::getTemperature() delay(1); } while (!mmc_io.isBitSet(STATUS_REG, MEAS_T_DONE)); + clearShadowBit(INT_CTRL_0_REG, TM_T, false); // Clear the bit - in shadow memory only + // Get raw temperature value from the IC. uint8_t result = 0; if (!mmc_io.readSingleByte(T_OUT_REG, &result)) diff --git a/src/SparkFun_MMC5983MA_Arduino_Library.h b/src/SparkFun_MMC5983MA_Arduino_Library.h index a07b573..6d0691a 100644 --- a/src/SparkFun_MMC5983MA_Arduino_Library.h +++ b/src/SparkFun_MMC5983MA_Arduino_Library.h @@ -42,11 +42,11 @@ class SFE_MMC5983MA uint8_t internalControl3 = 0x0; } memoryShadow; - // Sets register bit(s) on memory shadows and then registers - bool setShadowBit(uint8_t registerAddress, const uint8_t bitMask); + // Sets register bit(s) on memory shadows and then registers (if doWrite is true) + bool setShadowBit(uint8_t registerAddress, const uint8_t bitMask, bool doWrite = true); - // Clears register bit(s) on memory shadows and then registers - bool clearShadowBit(uint8_t registerAddress, const uint8_t bitMask); + // Clears register bit(s) on memory shadows and then registers (if doWrite is true) + bool clearShadowBit(uint8_t registerAddress, const uint8_t bitMask, bool doWrite = true); // Checks if a specific bit is set on a register memory shadow bool isShadowBitSet(uint8_t registerAddress, const uint8_t bitMask); From 997ce6b14ebca117a82e2f3bcb886946f33541a1 Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 8 Feb 2023 10:43:51 +0000 Subject: [PATCH 2/9] Update softReset Set the SW_RST bit using shadow memory instead of read-modify-write. INT_CTRL_1_REG reads as 0x61: the two reserved bits and BW_0 are set. If we do read-modify-write, we set the bandwidth to 200Hz. --- src/SparkFun_MMC5983MA_Arduino_Library.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/SparkFun_MMC5983MA_Arduino_Library.cpp b/src/SparkFun_MMC5983MA_Arduino_Library.cpp index 3d8334f..8e0d65f 100644 --- a/src/SparkFun_MMC5983MA_Arduino_Library.cpp +++ b/src/SparkFun_MMC5983MA_Arduino_Library.cpp @@ -275,9 +275,13 @@ int SFE_MMC5983MA::getTemperature() bool SFE_MMC5983MA::softReset() { - // Since SW_RST bit clears itself we don't need to to through the shadow - // register for this - we can send the command directly to the IC. - bool success = mmc_io.setRegisterBit(INT_CTRL_1_REG, SW_RST); + // Set the SW_RST bit to perform a software reset. + // Do this using the shadow register. If we do it with setRegisterBit + // (read-modify-write) we end up setting the reserved and BW_0 bits too as they + // always seems to read as 1...? I don't know why. + bool success = setShadowBit(INT_CTRL_1_REG, SW_RST); + + clearShadowBit(INT_CTRL_1_REG, SW_RST, false); // Clear the bit - in shadow memory only // The reset time is 10 msec. but we'll wait 15 msec. just in case. delay(15); From 9a26ec00b2e4275f9d158fcd46396f5f4e18a350 Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 8 Feb 2023 10:54:08 +0000 Subject: [PATCH 3/9] Update performSetOperation and performResetOperation --- src/SparkFun_MMC5983MA_Arduino_Library.cpp | 24 ++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/SparkFun_MMC5983MA_Arduino_Library.cpp b/src/SparkFun_MMC5983MA_Arduino_Library.cpp index 8e0d65f..ae4682c 100644 --- a/src/SparkFun_MMC5983MA_Arduino_Library.cpp +++ b/src/SparkFun_MMC5983MA_Arduino_Library.cpp @@ -333,11 +333,15 @@ bool SFE_MMC5983MA::is3WireSPIEnabled() bool SFE_MMC5983MA::performSetOperation() { - // Since SET bit clears itself we don't need to to through the shadow - // register for this - we can send the command directly to the IC. - bool success = mmc_io.setRegisterBit(INT_CTRL_0_REG, SET_OPERATION); + // Set the SET bit to perform a set operation. + // Do this using the shadow register. If we do it with setRegisterBit + // (read-modify-write) we end up setting the Auto_SR_en bit too as that + // always seems to read as 1...? I don't know why. + bool success = setShadowBit(INT_CTRL_0_REG, SET_OPERATION); + + clearShadowBit(INT_CTRL_0_REG, SET_OPERATION, false); // Clear the bit - in shadow memory only - // Wait until bit clears itself. + // Wait for the set operation to complete (500ns). delay(1); return success; @@ -345,11 +349,15 @@ bool SFE_MMC5983MA::performSetOperation() bool SFE_MMC5983MA::performResetOperation() { - // Since RESET bit clears itself we don't need to to through the shadow - // register for this - we can send the command directly to the IC. - bool success = mmc_io.setRegisterBit(INT_CTRL_0_REG, RESET_OPERATION); + // Set the RESET bit to perform a reset operation. + // Do this using the shadow register. If we do it with setRegisterBit + // (read-modify-write) we end up setting the Auto_SR_en bit too as that + // always seems to read as 1...? I don't know why. + bool success = setShadowBit(INT_CTRL_0_REG, RESET_OPERATION); + + clearShadowBit(INT_CTRL_0_REG, RESET_OPERATION, false); // Clear the bit - in shadow memory only - // Wait until bit clears itself. + // Wait for the reset operation to complete (500ns). delay(1); return success; From f1ad9ddd79c3bd6a2bc5e3464f6430ccfe06e885 Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 8 Feb 2023 11:10:09 +0000 Subject: [PATCH 4/9] Update getMeasurement to use shadow memory too --- src/SparkFun_MMC5983MA_Arduino_Library.cpp | 40 +++++++++++++++++----- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/SparkFun_MMC5983MA_Arduino_Library.cpp b/src/SparkFun_MMC5983MA_Arduino_Library.cpp index ae4682c..ad5bae3 100644 --- a/src/SparkFun_MMC5983MA_Arduino_Library.cpp +++ b/src/SparkFun_MMC5983MA_Arduino_Library.cpp @@ -903,9 +903,13 @@ bool SFE_MMC5983MA::isExtraCurrentAppliedNegToPos() uint32_t SFE_MMC5983MA::getMeasurementX() { - // Send command to device. TM_M self clears so we can access it directly. - if (!mmc_io.setRegisterBit(INT_CTRL_0_REG, TM_M)) + // Set the TM_M bit to start the measurement. + // Do this using the shadow register. If we do it with setRegisterBit + // (read-modify-write) we end up setting the Auto_SR_en bit too as that + // always seems to read as 1...? I don't know why. + if (!setShadowBit(INT_CTRL_0_REG, TM_M)) { + clearShadowBit(INT_CTRL_0_REG, TM_M, false); // Clear the bit - in shadow memory only SAFE_CALLBACK(errorCallback, SF_MMC5983MA_ERROR::BUS_ERROR); return 0; } @@ -917,6 +921,8 @@ uint32_t SFE_MMC5983MA::getMeasurementX() delay(1); } while (!mmc_io.isBitSet(STATUS_REG, MEAS_M_DONE)); + clearShadowBit(INT_CTRL_0_REG, TM_M, false); // Clear the bit - in shadow memory only + uint32_t result = 0; uint8_t buffer[2] = {0}; uint8_t buffer2bit = 0; @@ -933,9 +939,13 @@ uint32_t SFE_MMC5983MA::getMeasurementX() uint32_t SFE_MMC5983MA::getMeasurementY() { - // Send command to device. TM_M self clears so we can access it directly. - if (!mmc_io.setRegisterBit(INT_CTRL_0_REG, TM_M)) + // Set the TM_M bit to start the measurement. + // Do this using the shadow register. If we do it with setRegisterBit + // (read-modify-write) we end up setting the Auto_SR_en bit too as that + // always seems to read as 1...? I don't know why. + if (!setShadowBit(INT_CTRL_0_REG, TM_M)) { + clearShadowBit(INT_CTRL_0_REG, TM_M, false); // Clear the bit - in shadow memory only SAFE_CALLBACK(errorCallback, SF_MMC5983MA_ERROR::BUS_ERROR); return 0; } @@ -947,6 +957,8 @@ uint32_t SFE_MMC5983MA::getMeasurementY() delay(1); } while (!mmc_io.isBitSet(STATUS_REG, MEAS_M_DONE)); + clearShadowBit(INT_CTRL_0_REG, TM_M, false); // Clear the bit - in shadow memory only + uint32_t result = 0; uint8_t buffer[2] = {0}; uint8_t buffer2bit = 0; @@ -963,9 +975,13 @@ uint32_t SFE_MMC5983MA::getMeasurementY() uint32_t SFE_MMC5983MA::getMeasurementZ() { - // Send command to device. TM_M self clears so we can access it directly. - if (!mmc_io.setRegisterBit(INT_CTRL_0_REG, TM_M)) + // Set the TM_M bit to start the measurement. + // Do this using the shadow register. If we do it with setRegisterBit + // (read-modify-write) we end up setting the Auto_SR_en bit too as that + // always seems to read as 1...? I don't know why. + if (!setShadowBit(INT_CTRL_0_REG, TM_M)) { + clearShadowBit(INT_CTRL_0_REG, TM_M, false); // Clear the bit - in shadow memory only SAFE_CALLBACK(errorCallback, SF_MMC5983MA_ERROR::BUS_ERROR); return 0; } @@ -977,6 +993,8 @@ uint32_t SFE_MMC5983MA::getMeasurementZ() delay(1); } while (!mmc_io.isBitSet(STATUS_REG, MEAS_M_DONE)); + clearShadowBit(INT_CTRL_0_REG, TM_M, false); // Clear the bit - in shadow memory only + uint32_t result = 0; uint8_t buffer[3] = {0}; @@ -991,11 +1009,15 @@ uint32_t SFE_MMC5983MA::getMeasurementZ() bool SFE_MMC5983MA::getMeasurementXYZ(uint32_t *x, uint32_t *y, uint32_t *z) { - // Send command to device. TM_M self clears so we can access it directly. - bool success = mmc_io.setRegisterBit(INT_CTRL_0_REG, TM_M); + // Set the TM_M bit to start the measurement. + // Do this using the shadow register. If we do it with setRegisterBit + // (read-modify-write) we end up setting the Auto_SR_en bit too as that + // always seems to read as 1...? I don't know why. + bool success = setShadowBit(INT_CTRL_0_REG, TM_M); if (!success) { + clearShadowBit(INT_CTRL_0_REG, TM_M, false); // Clear the bit - in shadow memory only SAFE_CALLBACK(errorCallback, SF_MMC5983MA_ERROR::BUS_ERROR); return false; } @@ -1007,6 +1029,8 @@ bool SFE_MMC5983MA::getMeasurementXYZ(uint32_t *x, uint32_t *y, uint32_t *z) delay(1); } while (!mmc_io.isBitSet(STATUS_REG, MEAS_M_DONE)); + clearShadowBit(INT_CTRL_0_REG, TM_M, false); // Clear the bit - in shadow memory only + return (readFieldsXYZ(x, y, z)); } From 9177d5a43bdc2a75618789af7dfdbd440a5562ee Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 8 Feb 2023 11:22:48 +0000 Subject: [PATCH 5/9] Prevent unnecessary register writes --- src/SparkFun_MMC5983MA_Arduino_Library.cpp | 78 ++++++++++++---------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/src/SparkFun_MMC5983MA_Arduino_Library.cpp b/src/SparkFun_MMC5983MA_Arduino_Library.cpp index ad5bae3..a434f59 100644 --- a/src/SparkFun_MMC5983MA_Arduino_Library.cpp +++ b/src/SparkFun_MMC5983MA_Arduino_Library.cpp @@ -406,6 +406,9 @@ bool SFE_MMC5983MA::isXChannelEnabled() { // Get the bit value from the shadow register since the IC does not // allow reading INT_CTRL_1_REG register. + // + // Note: this returns true when the X channel is inhibited. + // Strictly, it should be called isXChannelInhibited. return (isShadowBitSet(INT_CTRL_1_REG, X_INHIBIT)); } @@ -431,6 +434,9 @@ bool SFE_MMC5983MA::areYZChannelsEnabled() { // Get the bit value from the shadow register since the IC does not // allow reading INT_CTRL_1_REG register. + // + // Note: this returns true when the Y and Z channels are inhibited. + // Strictly, it should be called areYZChannelsInhibited. return (isShadowBitSet(INT_CTRL_1_REG, YZ_INHIBIT)); } @@ -444,28 +450,28 @@ bool SFE_MMC5983MA::setFilterBandwidth(uint16_t bandwidth) { case 800: { - success = setShadowBit(INT_CTRL_1_REG, BW0); + success = setShadowBit(INT_CTRL_1_REG, BW0, false); success &= setShadowBit(INT_CTRL_1_REG, BW1); } break; case 400: { - success = clearShadowBit(INT_CTRL_1_REG, BW0); + success = clearShadowBit(INT_CTRL_1_REG, BW0, false); success &= setShadowBit(INT_CTRL_1_REG, BW1); } break; case 200: { - success = setShadowBit(INT_CTRL_1_REG, BW0); + success = setShadowBit(INT_CTRL_1_REG, BW0, false); success &= clearShadowBit(INT_CTRL_1_REG, BW1); } break; case 100: { - success = clearShadowBit(INT_CTRL_1_REG, BW0); + success = clearShadowBit(INT_CTRL_1_REG, BW0, false); success &= clearShadowBit(INT_CTRL_1_REG, BW1); } break; @@ -543,8 +549,8 @@ bool SFE_MMC5983MA::setContinuousModeFrequency(uint16_t frequency) case 1: { // CM_FREQ[2:0] = 001 - success = clearShadowBit(INT_CTRL_2_REG, CM_FREQ_2); - success &= clearShadowBit(INT_CTRL_2_REG, CM_FREQ_1); + success = clearShadowBit(INT_CTRL_2_REG, CM_FREQ_2, false); + success &= clearShadowBit(INT_CTRL_2_REG, CM_FREQ_1, false); success &= setShadowBit(INT_CTRL_2_REG, CM_FREQ_0); } break; @@ -552,8 +558,8 @@ bool SFE_MMC5983MA::setContinuousModeFrequency(uint16_t frequency) case 10: { // CM_FREQ[2:0] = 010 - success = clearShadowBit(INT_CTRL_2_REG, CM_FREQ_2); - success &= setShadowBit(INT_CTRL_2_REG, CM_FREQ_1); + success = clearShadowBit(INT_CTRL_2_REG, CM_FREQ_2, false); + success &= setShadowBit(INT_CTRL_2_REG, CM_FREQ_1, false); success &= clearShadowBit(INT_CTRL_2_REG, CM_FREQ_0); } break; @@ -561,8 +567,8 @@ bool SFE_MMC5983MA::setContinuousModeFrequency(uint16_t frequency) case 20: { // CM_FREQ[2:0] = 011 - success = clearShadowBit(INT_CTRL_2_REG, CM_FREQ_2); - success &= setShadowBit(INT_CTRL_2_REG, CM_FREQ_1); + success = clearShadowBit(INT_CTRL_2_REG, CM_FREQ_2, false); + success &= setShadowBit(INT_CTRL_2_REG, CM_FREQ_1, false); success &= setShadowBit(INT_CTRL_2_REG, CM_FREQ_0); } break; @@ -570,8 +576,8 @@ bool SFE_MMC5983MA::setContinuousModeFrequency(uint16_t frequency) case 50: { // CM_FREQ[2:0] = 100 - success = setShadowBit(INT_CTRL_2_REG, CM_FREQ_2); - success &= clearShadowBit(INT_CTRL_2_REG, CM_FREQ_1); + success = setShadowBit(INT_CTRL_2_REG, CM_FREQ_2, false); + success &= clearShadowBit(INT_CTRL_2_REG, CM_FREQ_1, false); success &= clearShadowBit(INT_CTRL_2_REG, CM_FREQ_0); } break; @@ -579,8 +585,8 @@ bool SFE_MMC5983MA::setContinuousModeFrequency(uint16_t frequency) case 100: { // CM_FREQ[2:0] = 101 - success = setShadowBit(INT_CTRL_2_REG, CM_FREQ_2); - success &= clearShadowBit(INT_CTRL_2_REG, CM_FREQ_1); + success = setShadowBit(INT_CTRL_2_REG, CM_FREQ_2, false); + success &= clearShadowBit(INT_CTRL_2_REG, CM_FREQ_1, false); success &= setShadowBit(INT_CTRL_2_REG, CM_FREQ_0); } break; @@ -588,8 +594,8 @@ bool SFE_MMC5983MA::setContinuousModeFrequency(uint16_t frequency) case 200: { // CM_FREQ[2:0] = 110 - success = setShadowBit(INT_CTRL_2_REG, CM_FREQ_2); - success &= setShadowBit(INT_CTRL_2_REG, CM_FREQ_1); + success = setShadowBit(INT_CTRL_2_REG, CM_FREQ_2, false); + success &= setShadowBit(INT_CTRL_2_REG, CM_FREQ_1, false); success &= clearShadowBit(INT_CTRL_2_REG, CM_FREQ_0); } break; @@ -597,8 +603,8 @@ bool SFE_MMC5983MA::setContinuousModeFrequency(uint16_t frequency) case 1000: { // CM_FREQ[2:0] = 111 - success = setShadowBit(INT_CTRL_2_REG, CM_FREQ_2); - success &= setShadowBit(INT_CTRL_2_REG, CM_FREQ_1); + success = setShadowBit(INT_CTRL_2_REG, CM_FREQ_2, false); + success &= setShadowBit(INT_CTRL_2_REG, CM_FREQ_1, false); success &= setShadowBit(INT_CTRL_2_REG, CM_FREQ_0); } break; @@ -606,8 +612,8 @@ bool SFE_MMC5983MA::setContinuousModeFrequency(uint16_t frequency) case 0: { // CM_FREQ[2:0] = 000 - success = clearShadowBit(INT_CTRL_2_REG, CM_FREQ_2); - success &= clearShadowBit(INT_CTRL_2_REG, CM_FREQ_1); + success = clearShadowBit(INT_CTRL_2_REG, CM_FREQ_2, false); + success &= clearShadowBit(INT_CTRL_2_REG, CM_FREQ_1, false); success &= clearShadowBit(INT_CTRL_2_REG, CM_FREQ_0); } break; @@ -717,8 +723,8 @@ bool SFE_MMC5983MA::setPeriodicSetSamples(const uint16_t numberOfSamples) case 25: { // PRD_SET[2:0] = 001 - success = clearShadowBit(INT_CTRL_2_REG, PRD_SET_2); - success &= clearShadowBit(INT_CTRL_2_REG, PRD_SET_1); + success = clearShadowBit(INT_CTRL_2_REG, PRD_SET_2, false); + success &= clearShadowBit(INT_CTRL_2_REG, PRD_SET_1, false); success &= setShadowBit(INT_CTRL_2_REG, PRD_SET_0); } break; @@ -726,8 +732,8 @@ bool SFE_MMC5983MA::setPeriodicSetSamples(const uint16_t numberOfSamples) case 75: { // PRD_SET[2:0] = 010 - success = clearShadowBit(INT_CTRL_2_REG, PRD_SET_2); - success &= setShadowBit(INT_CTRL_2_REG, PRD_SET_1); + success = clearShadowBit(INT_CTRL_2_REG, PRD_SET_2, false); + success &= setShadowBit(INT_CTRL_2_REG, PRD_SET_1, false); success &= clearShadowBit(INT_CTRL_2_REG, PRD_SET_0); } break; @@ -735,8 +741,8 @@ bool SFE_MMC5983MA::setPeriodicSetSamples(const uint16_t numberOfSamples) case 100: { // PRD_SET[2:0] = 011 - success = clearShadowBit(INT_CTRL_2_REG, PRD_SET_2); - success &= setShadowBit(INT_CTRL_2_REG, PRD_SET_1); + success = clearShadowBit(INT_CTRL_2_REG, PRD_SET_2, false); + success &= setShadowBit(INT_CTRL_2_REG, PRD_SET_1, false); success &= setShadowBit(INT_CTRL_2_REG, PRD_SET_0); } break; @@ -744,8 +750,8 @@ bool SFE_MMC5983MA::setPeriodicSetSamples(const uint16_t numberOfSamples) case 250: { // PRD_SET[2:0] = 100 - success = setShadowBit(INT_CTRL_2_REG, PRD_SET_2); - success &= clearShadowBit(INT_CTRL_2_REG, PRD_SET_1); + success = setShadowBit(INT_CTRL_2_REG, PRD_SET_2, false); + success &= clearShadowBit(INT_CTRL_2_REG, PRD_SET_1, false); success &= clearShadowBit(INT_CTRL_2_REG, PRD_SET_0); } break; @@ -753,8 +759,8 @@ bool SFE_MMC5983MA::setPeriodicSetSamples(const uint16_t numberOfSamples) case 500: { // PRD_SET[2:0] = 101 - success = setShadowBit(INT_CTRL_2_REG, PRD_SET_2); - success &= clearShadowBit(INT_CTRL_2_REG, PRD_SET_1); + success = setShadowBit(INT_CTRL_2_REG, PRD_SET_2, false); + success &= clearShadowBit(INT_CTRL_2_REG, PRD_SET_1, false); success &= setShadowBit(INT_CTRL_2_REG, PRD_SET_0); } break; @@ -762,8 +768,8 @@ bool SFE_MMC5983MA::setPeriodicSetSamples(const uint16_t numberOfSamples) case 1000: { // PRD_SET[2:0] = 110 - success = setShadowBit(INT_CTRL_2_REG, PRD_SET_2); - success &= setShadowBit(INT_CTRL_2_REG, PRD_SET_1); + success = setShadowBit(INT_CTRL_2_REG, PRD_SET_2, false); + success &= setShadowBit(INT_CTRL_2_REG, PRD_SET_1, false); success &= clearShadowBit(INT_CTRL_2_REG, PRD_SET_0); } break; @@ -771,8 +777,8 @@ bool SFE_MMC5983MA::setPeriodicSetSamples(const uint16_t numberOfSamples) case 2000: { // PRD_SET[2:0] = 111 - success = setShadowBit(INT_CTRL_2_REG, PRD_SET_2); - success &= setShadowBit(INT_CTRL_2_REG, PRD_SET_1); + success = setShadowBit(INT_CTRL_2_REG, PRD_SET_2, false); + success &= setShadowBit(INT_CTRL_2_REG, PRD_SET_1, false); success &= setShadowBit(INT_CTRL_2_REG, PRD_SET_0); } break; @@ -780,8 +786,8 @@ bool SFE_MMC5983MA::setPeriodicSetSamples(const uint16_t numberOfSamples) case 1: { // PRD_SET[2:0] = 000 - success = clearShadowBit(INT_CTRL_2_REG, PRD_SET_2); - success &= clearShadowBit(INT_CTRL_2_REG, PRD_SET_1); + success = clearShadowBit(INT_CTRL_2_REG, PRD_SET_2, false); + success &= clearShadowBit(INT_CTRL_2_REG, PRD_SET_1, false); success &= clearShadowBit(INT_CTRL_2_REG, PRD_SET_0); } break; From 9cedafd76c52a82ecba75ce3e207cd883975e43a Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 8 Feb 2023 11:23:31 +0000 Subject: [PATCH 6/9] Clarify the polarity of isXChannelEnabled and areYZChannelsEnabled --- src/SparkFun_MMC5983MA_Arduino_Library.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/SparkFun_MMC5983MA_Arduino_Library.h b/src/SparkFun_MMC5983MA_Arduino_Library.h index 6d0691a..d0faa13 100644 --- a/src/SparkFun_MMC5983MA_Arduino_Library.h +++ b/src/SparkFun_MMC5983MA_Arduino_Library.h @@ -121,6 +121,8 @@ class SFE_MMC5983MA bool disableXChannel(); // Checks if X channel output is enabled + // Note: this returns true when the X channel is inhibited. + // Strictly, it should be called isXChannelInhibited. bool isXChannelEnabled(); // Enables Y and Z channels outputs @@ -130,6 +132,8 @@ class SFE_MMC5983MA bool disableYZChannels(); // Checks if YZ channels outputs are enabled + // Note: this returns true when the Y and Z channels are inhibited. + // Strictly, it should be called areYZChannelsInhibited. bool areYZChannelsEnabled(); // Sets decimation filter bandwidth. Allowed values are 800, 400, 200 or 100. Defaults to 100 on invalid values. From 81e722e97050fbd71db79c1947018c49cf45caf7 Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 8 Feb 2023 11:27:03 +0000 Subject: [PATCH 7/9] Update comments for clearMeasDoneInterrupt --- src/SparkFun_MMC5983MA_Arduino_Library.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/SparkFun_MMC5983MA_Arduino_Library.cpp b/src/SparkFun_MMC5983MA_Arduino_Library.cpp index a434f59..a823cb9 100644 --- a/src/SparkFun_MMC5983MA_Arduino_Library.cpp +++ b/src/SparkFun_MMC5983MA_Arduino_Library.cpp @@ -1068,6 +1068,10 @@ bool SFE_MMC5983MA::readFieldsXYZ(uint32_t *x, uint32_t *y, uint32_t *z) bool SFE_MMC5983MA::clearMeasDoneInterrupt(uint8_t measMask) { - measMask &= (MEAS_T_DONE | MEAS_M_DONE); // Ensure only the Meas_T_Done and Meas_M_Done interrupts can be cleared - return (mmc_io.setRegisterBit(STATUS_REG, measMask)); // Writing 1 into these bits will clear the corresponding interrupt + // Ensure only the Meas_T_Done and Meas_M_Done interrupts can be cleared + measMask &= (MEAS_T_DONE | MEAS_M_DONE); + + // Writing 1 into these bits will clear the corresponding interrupt + // Read-modify-write is OK here + return (mmc_io.setRegisterBit(STATUS_REG, measMask)); } \ No newline at end of file From 6bf0b5f81cab63b950830a0bed8c2388d073c061 Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 8 Feb 2023 11:35:50 +0000 Subject: [PATCH 8/9] v1.1.0 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index ba91f6e..9f19b82 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun MMC5983MA Magnetometer Arduino Library -version=1.0.3 +version=1.1.0 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=A I2C/SPI library for the MMC5983MA magnetic compass sensor. From 2a1628c956fdc903ef26e10f594666e255392d2c Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 8 Feb 2023 11:48:34 +0000 Subject: [PATCH 9/9] Update the SPI examples It's rare, but I have seen the mag fail to start on SPI. Reading the PROD_ID returns 0xFF instead of 0x30. Doing a softReset fixes it. (It is OK to call softReset if begin has been called first.) --- .../Example4-SPI_Simple_measurement.ino | 9 +++++---- .../Example5-SPI_Digital_compass.ino | 9 +++++---- .../Example6-SPI_Fast_Continuous_measurement.ino | 9 +++++---- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/examples/Example4-SPI_Simple_measurement/Example4-SPI_Simple_measurement.ino b/examples/Example4-SPI_Simple_measurement/Example4-SPI_Simple_measurement.ino index a12c3f1..2983fe5 100644 --- a/examples/Example4-SPI_Simple_measurement/Example4-SPI_Simple_measurement.ino +++ b/examples/Example4-SPI_Simple_measurement/Example4-SPI_Simple_measurement.ino @@ -30,11 +30,12 @@ void setup() SPI.begin(); - if (myMag.begin(csPin) == false) + while (myMag.begin(csPin) == false) { - Serial.println("MMC5983MA did not respond - check your wiring. Freezing."); - while (true) - ; + Serial.println("MMC5983MA did not respond. Retrying..."); + delay(500); + myMag.softReset(); + delay(500); } Serial.println("MMC5983MA connected"); diff --git a/examples/Example5-SPI_Digital_compass/Example5-SPI_Digital_compass.ino b/examples/Example5-SPI_Digital_compass/Example5-SPI_Digital_compass.ino index 6ce949f..205210c 100644 --- a/examples/Example5-SPI_Digital_compass/Example5-SPI_Digital_compass.ino +++ b/examples/Example5-SPI_Digital_compass/Example5-SPI_Digital_compass.ino @@ -30,11 +30,12 @@ void setup() SPI.begin(); - if (myMag.begin(csPin) == false) + while (myMag.begin(csPin) == false) { - Serial.println("MMC5983MA did not respond - check your wiring. Freezing."); - while (true) - ; + Serial.println("MMC5983MA did not respond. Retrying..."); + delay(500); + myMag.softReset(); + delay(500); } Serial.println("MMC5983MA connected"); diff --git a/examples/Example6-SPI_Fast_Continuous_measurement/Example6-SPI_Fast_Continuous_measurement.ino b/examples/Example6-SPI_Fast_Continuous_measurement/Example6-SPI_Fast_Continuous_measurement.ino index a21bbe5..2d8f068 100644 --- a/examples/Example6-SPI_Fast_Continuous_measurement/Example6-SPI_Fast_Continuous_measurement.ino +++ b/examples/Example6-SPI_Fast_Continuous_measurement/Example6-SPI_Fast_Continuous_measurement.ino @@ -45,11 +45,12 @@ void setup() pinMode(interruptPin, INPUT); attachInterrupt(digitalPinToInterrupt(interruptPin), interruptRoutine, RISING); - if (myMag.begin(csPin) == false) + while (myMag.begin(csPin) == false) { - Serial.println("MMC5983MA did not respond - check your wiring. Freezing."); - while (true) - ; + Serial.println("MMC5983MA did not respond. Retrying..."); + delay(500); + myMag.softReset(); + delay(500); } myMag.softReset();