AK8963

Dependents:   FreeIMU

Revision:
0:ec59a31e784b
Child:
1:f8ba8df44aab
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AK8963.cpp	Wed Mar 28 20:25:57 2018 +0000
@@ -0,0 +1,191 @@
+// I2Cdev library collection - AK8963 I2C device class header file
+// Based on AKM AK8963/B datasheet, 12/2009
+// 8/27/2011 by Jeff Rowberg <jeff@rowberg.net> for 8975
+// 6/14/2014 modified for AKM AK8963
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib for 8975
+//
+// Changelog:
+//     2011-08-27 - initial release
+//     2014-06-14 - modified for AK8963 based on Kris Wieners MPU-9250 Sketch
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2011 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include "AK8963.h"
+
+
+/** Default constructor, uses default I2C address.
+ * @see AK8963_DEFAULT_ADDRESS
+ */
+AK8963::AK8963() {
+    devAddr = AK8963_DEFAULT_ADDRESS;
+}
+
+/** Specific address constructor.
+ * @param address I2C address
+ * @see AK8963_DEFAULT_ADDRESS
+ * @see AK8963_ADDRESS_00
+ */
+AK8963::AK8963(bool useSPI, uint8_t address) {
+    bSPI = useSPI;
+    devAddr = address;
+}
+
+/** Power on and prepare for general usage.
+ * No specific pre-configuration is necessary for this device.
+ */
+void AK8963::initialize() {
+
+}
+
+/** Verify the I2C connection.
+ * Make sure the device is connected and responds as expected.
+ * @return True if connection is valid, false otherwise
+ */
+bool AK8963::testConnection() {
+    if (i2Cdev.readByte(devAddr, AK8963_RA_WIA, buffer) == 1) {
+        return (buffer[0] == 0x48);
+    }
+    return false;
+}
+
+// WIA register
+
+uint8_t AK8963::getDeviceID() {
+    i2Cdev.readByte(devAddr, AK8963_RA_WIA, buffer);
+    return buffer[0];
+}
+
+// INFO register
+
+uint8_t AK8963::getInfo() {
+    i2Cdev.readByte(devAddr, AK8963_RA_INFO, buffer);
+    return buffer[0];
+}
+
+// ST1 register
+
+bool AK8963::getDataReady() {
+    i2Cdev.readBit(devAddr, AK8963_RA_ST1, AK8963_ST1_DRDY_BIT, buffer);
+    return buffer[0];
+}
+
+bool AK8963::getDataOverRun() {
+    i2Cdev.readBit(devAddr, AK8963_RA_ST1, AK8963_ST1_DOR_BIT, buffer);
+    return buffer[0];
+}
+
+// H* registers
+void AK8963::getHeading(int16_t *x, int16_t *y, int16_t *z) {
+    //I2Cdev::writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_SINGLE);
+    //delay(10);
+    
+    if (getDataReady() & 0x01) {
+        i2Cdev.readBytes(devAddr, AK8963_RA_HXL, 7, buffer);
+        uint8_t c = buffer[6]; // End data read by reading ST2 register
+        if(!(c & 0x08)) { // Check if magnetic sensor overflow set, if not then report data
+            *x = (((int16_t)buffer[1]) << 8) | buffer[0];
+            *y = (((int16_t)buffer[3]) << 8) | buffer[2];
+            *z = (((int16_t)buffer[5]) << 8) | buffer[4];
+        }
+    }   
+}
+
+void AK8963::getSelfTest(int16_t *x, int16_t *y, int16_t *z) {
+    i2Cdev.writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_POWERDOWN); // Power down magnetometer  
+    Thread::wait(10);
+    setSelfTest(true);      // Set Self Test Bit
+    Thread::wait(10);
+    // Read mag registers
+    if(getDataReady() & 0x01) {
+        i2Cdev.readBytes(devAddr, AK8963_RA_HXL, 7, buffer);
+        uint8_t c = buffer[6]; // End data read by reading ST2 register
+        if(!(c & 0x08)) { // Check if magnetic sensor overflow set, if not then report data
+            *x = (((int16_t)buffer[1]) << 8) | buffer[0];
+            *y = (((int16_t)buffer[3]) << 8) | buffer[2];
+            *z = (((int16_t)buffer[5]) << 8) | buffer[4];
+        }
+    }
+    setSelfTest(false);     // Set Self Test Bit
+    Thread::wait(10);
+    i2Cdev.writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_POWERDOWN); // Power down magnetometer  
+    Thread::wait(10);
+    
+}
+
+// ST2 register
+bool AK8963::getOverflowStatus() {
+    i2Cdev.readBit(devAddr, AK8963_RA_ST2, AK8963_ST2_HOFL_BIT, buffer);
+    return buffer[0];
+}
+
+bool AK8963::getOutBitST() {
+    i2Cdev.readBit(devAddr, AK8963_RA_ST2, AK8963_ST2_BITM, buffer);
+    return buffer[0];
+}
+
+// CNTL1 register
+uint8_t AK8963::getMode() {
+    //I2Cdev::readBits(devAddr, AK8963_RA_CNTL1, AK8963_CNTL1_MODE_BIT, AK8963_CNTL1_MODE_LENGTH, buffer);
+    i2Cdev.readByte(devAddr, AK8963_RA_CNTL1, buffer);
+    return buffer[0];
+}
+
+//Configure magenetometer mode and resolution
+void AK8963::setModeRes(uint8_t mode, uint8_t Mscale) {
+    //I2Cdev::writeBits(devAddr, AK8963_RA_CNTL1, AK8963_CNTL1_MODE_BIT, AK8963_CNTL1_MODE_LENGTH, mode);
+    i2Cdev.writeByte(devAddr, AK8963_RA_CNTL1, Mscale << 4 | mode);
+    Thread::wait(10);
+}
+
+// CNTL2 register
+void AK8963::reset() {
+    i2Cdev.writeBytes(devAddr, AK8963_RA_CNTL2, AK8963_CNTL2_RESET, buffer);
+}
+
+// ASTC register
+void AK8963::setSelfTest(bool enabled) {
+    i2Cdev.writeBit(devAddr, AK8963_RA_ASTC, AK8963_ASTC_SELF_BIT, enabled);
+}
+
+// I2CDIS
+void AK8963::disableI2C() {
+    i2Cdev.writeBit(devAddr, AK8963_RA_I2CDIS, AK8963_I2CDIS_BIT, true);
+}
+
+// ASA* registers
+void AK8963::getAdjustment(uint8_t *x, uint8_t *y, uint8_t *z) {
+    i2Cdev.writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_POWERDOWN); // Power down magnetometer  
+    Thread::wait(10);
+    i2Cdev.writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_FUSEROM); // Enter Fuse ROM access mode
+    Thread::wait(10);
+    
+    i2Cdev.readBytes(devAddr, AK8963_RA_ASAX, 3, buffer);     // Read the x-, y-, and z-axis calibration values
+    *x = buffer[0];
+    *y = buffer[1];
+    *z = buffer[2];
+    
+    i2Cdev.writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_POWERDOWN); // Power down magnetometer  
+    Thread::wait(10);
+}
\ No newline at end of file