Modified for compatibility with Rev.E. hardware

Fork of AkmSensor by AKM Development Platform

akmakd.cpp

Committer:
masahikofukasawa
Date:
2016-04-28
Revision:
0:7a00359e701e
Child:
7:e269411568c9

File content as of revision 0:7a00359e701e:

#include "akmakd.h"
#include "ak8963.h"
#include "ak099xx.h"
#include "debug.h"

/**
 * Constructor.
 *
 */
AkmAkd::AkmAkd(){
    event = false;
    compass = NULL;
    drdy = NULL;
    sensorName = "";
}

/**
 * Destructor.
 *
 */
AkmAkd::~AkmAkd(){
    drdy->rise(0);
    if (compass) delete compass;
    if (drdy) delete drdy;
}

AkmSensor::Status AkmAkd::init(const uint8_t id, const uint8_t subid){
    primaryId = id;
    subId = subid;
    
    AkmECompass::SensorType type;

    drdy = new InterruptIn(DRDY);    
    drdy->rise(0);

    if(primaryId == AKM_PRIMARY_ID_AKD_I2C){

        I2C* i2c = new I2C(I2C_SDA,I2C_SCL);
        i2c->frequency(I2C_SPEED_100KHZ);

        AK099XX* ak099xx;
        AK8963* ak8963;

        switch(subid){
            case AkmAkd::SUB_ID_AK8963N:
            case AkmAkd::SUB_ID_AK8963C:
                type = AkmECompass::AK8963;
                ak8963 = new AK8963();
                compass = ak8963;
                AkmAkd::sensorName = "AK8963";
                break;          
            case AkmAkd::SUB_ID_AK09911:
                type = AkmECompass::AK09911;
                ak099xx = new AK099XX();
                compass = ak099xx;
                AkmAkd::sensorName = "AK09911";
                break;
            case AkmAkd::SUB_ID_AK09912:
                type = AkmECompass::AK09912;
                ak099xx = new AK099XX();
                compass = ak099xx;
                AkmAkd::sensorName = "AK09912";
                break;
            case AkmAkd::SUB_ID_AK09915:
                type = AkmECompass::AK09915;
                ak099xx = new AK099XX();
                compass = ak099xx;
                AkmAkd::sensorName = "AK09915";
                break;
            case AkmAkd::SUB_ID_AK09916C:
                type = AkmECompass::AK09916C;
                ak099xx = new AK099XX();
                compass = ak099xx;
                AkmAkd::sensorName = "AK09916C";
                break;
            default:
                return AkmSensor::ERROR;
//                break;
        }
        
        bool foundSensor = false;
        
        AkmECompass::SlaveAddress slaveAddr[] 
            = { AkmECompass::SLAVE_ADDR_1,
                AkmECompass::SLAVE_ADDR_2,
                AkmECompass::SLAVE_ADDR_3,
                AkmECompass::SLAVE_ADDR_4};

        for(int i=0; i<sizeof(slaveAddr); i++)
        {
            compass->init(i2c, slaveAddr[i], type);
            // Checks connectivity
            if(compass->checkConnection() == AkmECompass::SUCCESS) {
                // found
                foundSensor = true;
                break;
            }
        }
        if(foundSensor != true) return AkmSensor::ERROR;
        
        // read a data to reset DRDY 
        AkmECompass::MagneticVector mag;
        compass->getMagneticVector(&mag);
        
    }else if(primaryId == AKM_PRIMARY_ID_AKD_SPI){
        MSG("#Error: SPI doesn't support.\n"); 

        return AkmSensor::ERROR_DOESNT_SUPPORT;
//        spi = new SPI(SPI_MOSI, SPI_MISO, SPI_SCK);
//        spi->format(8,3);    // 8bit, Mode=3
//        spi->frequency(100000);
    }
    
    MSG("#%s detected.\n", AkmAkd::sensorName);
    return AkmSensor::SUCCESS;
}


void AkmAkd::checkDRDY(){
    AkmECompass::Status  status = compass->isDataReady();
    if( status == AkmECompass::DATA_READY || 
        status == AkmECompass::DATA_OVER_RUN ) event = true;
}

void AkmAkd::detectDRDY(){
    event = true;
}

bool AkmAkd::isEvent(){
    return event;
}

AkmSensor::Status AkmAkd::startSensor(){
    // Puts the device into continuous measurement mode.
    if(compass->setOperationMode((AkmECompass::OperationMode)0x02) != AkmECompass::SUCCESS) {
        return AkmSensor::ERROR;
    }
    
    // DRDY interrupt enable for AK8963/AK09912/AK09915
    if(compass->getSensorType() == AkmECompass::AK8963 ||
       compass->getSensorType() == AkmECompass::AK09912 ||
       compass->getSensorType() == AkmECompass::AK09915 ){       
        drdy->rise(this, &AkmAkd::detectDRDY);
    }
    else{
        ticker.attach(this, &AkmAkd::checkDRDY, 0.01);  // 100Hz
    }
    return AkmSensor::SUCCESS;
}

AkmSensor::Status AkmAkd::startSensor(const float sec){
    return AkmSensor::ERROR;    // doesn't support
}

AkmSensor::Status AkmAkd::stopSensor(){
    ticker.detach();
 
    // Puts the device into power down mode.
    if(compass->setOperationMode(AkmECompass::MODE_POWER_DOWN) != AkmECompass::SUCCESS) {
        return AkmSensor::ERROR;
    }
    return AkmSensor::SUCCESS;
}

AkmSensor::Status AkmAkd::readSensorData(Message* msg){
    event = false;

    AkmECompass::MagneticVector mag;
    AkmECompass::Status status = compass->getMagneticVector(&mag);
    if( status != AkmECompass::SUCCESS){
        return AkmSensor::ERROR;
    }
    msg->setCommand(Message::CMD_START_MEASUREMENT);
    msg->setArgument( 0, (mag.isOverflow ? 1 : 0) );
    msg->setArgument( 1,(char)((int32_t)(mag.mx/0.15) >> 8));
    msg->setArgument( 2, (char)((int32_t)(mag.mx/0.15) & 0x00FF) );
    msg->setArgument( 3, (char)((int32_t)(mag.my/0.15) >> 8) );
    msg->setArgument( 4, (char)((int32_t)(mag.my/0.15) & 0x00FF) );
    msg->setArgument( 5, (char)((int32_t)(mag.mz/0.15) >> 8) );
    msg->setArgument( 6, (char)((int32_t)(mag.mz/0.15) & 0x00FF) );
    return AkmSensor::SUCCESS;
}

AkmSensor::Status AkmAkd::requestCommand(Message* in, Message* out){    
    return AkmSensor::SUCCESS;
}

char* AkmAkd::getSensorName(){
    return sensorName;
}