/*! Read sensitivity adjustment data from fuse ROM. @return If data are read successfully, the return value is #AKM_SUCCESS. Otherwise the return value is #AKM_FAIL. @param[out] regs The read ASA values. When this function succeeds, ASAX value is saved in regs[0], ASAY is saved in regs[1], ASAZ is saved in regs[2]. */ int16 AKFS_ReadAK8975FUSEROM( uint8 regs[3] ) { /* Set to FUSE ROM access mode */ if (AKD_SetMode(AK8975_MODE_FUSE_ACCESS) != AKD_SUCCESS) { AKMERROR; return AKM_FAIL; } /* Read values. ASAX, ASAY, ASAZ */ if (AKD_RxData(AK8975_FUSE_ASAX, regs, 3) != AKD_SUCCESS) { AKMERROR; return AKM_FAIL; } /* Set to PowerDown mode */ if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) { AKMERROR; return AKM_FAIL; } AKMDEBUG(DBG_LEVEL2, "%s: asa(dec)=%d,%d,%d\n", __FUNCTION__, regs[0], regs[1], regs[2]); return AKM_SUCCESS; }
/*! Read hard coded value (Fuse ROM) from AK8975. Then set the read value to calculation parameter. @return If parameters are read successfully, the return value is #AKRET_PROC_SUCCEED. Otherwise the return value is #AKRET_PROC_FAIL. No error code is reserved to show which operation has failed. @param[out] prms A pointer to #AK8975PRMS structure. */ int16 ReadAK8975FUSEROM(AK8975PRMS* prms) { BYTE i2cData[6]; // Set to PowerDown mode if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return AKRET_PROC_FAIL; } // Set to FUSE ROM access mode if (AKD_SetMode(AK8975_MODE_FUSE_ACCESS) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return AKRET_PROC_FAIL; } // Read values. ASAX, ASAY, ASAZ if (AKD_RxData(AK8975_FUSE_ASAX, i2cData, 3) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return AKRET_PROC_FAIL; } prms->m_asa.u.x = (int16)i2cData[0]; prms->m_asa.u.y = (int16)i2cData[1]; prms->m_asa.u.z = (int16)i2cData[2]; DBGPRINT(DBG_LEVEL3, "%s: asa(dec)=%d,%d,%d\n", __FUNCTION__, prms->m_asa.u.x, prms->m_asa.u.y, prms->m_asa.u.z); #ifdef NOASA if((prms->m_asa.u.x==0)||(prms->m_asa.u.y==0)||(prms->m_asa.u.z==0)){ prms->m_asa.u.x = i2cData[0] = 128; prms->m_asa.u.y = i2cData[1] = 128; prms->m_asa.u.z = i2cData[2] = 128; } #endif // Set keywords for SmartCompassLibrary certification prms->m_key[2] = (int16)i2cData[0]; prms->m_key[3] = (int16)i2cData[1]; prms->m_key[4] = (int16)i2cData[2]; // Set to PowerDown mode if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return AKRET_PROC_FAIL; } // Set keywords for SmartCompassLibrary certification if (AKD_RxData(AK8975_REG_WIA, i2cData, 1) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return AKRET_PROC_FAIL; } prms->m_key[0] = CSPEC_CI_AK_DEVICE; prms->m_key[1] = (int16)i2cData[0]; strncpy(prms->m_licenser, CSPEC_CI_LICENSER, AKSC_CI_MAX_CHARSIZE); strncpy(prms->m_licensee, CSPEC_CI_LICENSEE, AKSC_CI_MAX_CHARSIZE); return AKRET_PROC_SUCCEED; }
/*! Set initial values to registers of AK8975. Then initialize algorithm parameters. @return If parameters are read successfully, the return value is #AKRET_PROC_SUCCEED. Otherwise the return value is #AKRET_PROC_FAIL. No error code is reserved to show which operation has failed. @param[in,out] prms A pointer to a #AK8975PRMS structure. */ int16 InitAK8975_Measure(AK8975PRMS* prms) { BYTE i2cData[AKSC_BDATA_SIZE]; // Set to PowerDown mode if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return AKRET_PROC_FAIL; } prms->m_form = getFormation(); // Restore the value when succeeding in estimating of HOffset. prms->m_ho = prms->HSUC_HO[prms->m_form]; prms->m_hdst = prms->HSUC_HDST[prms->m_form]; // Initialize the decompose parameters AKSC_InitDecomp8975(prms->m_hdata); // Initialize HDOE parameters AKSC_InitHDOEProcPrmsS3( &prms->m_hdoev, 1, &prms->m_ho, prms->m_hdst ); AKSC_InitHFlucCheck( &(prms->m_hflucv), &(prms->HFLUCV_HREF[prms->m_form]), HFLUCV_TH ); // Reset counter prms->m_cntSuspend = 0; prms->m_callcnt = 0; return AKRET_PROC_SUCCEED; }
/*! This is the main routine of measurement. @param[in,out] prms A pointer to a #AK8975PRMS structure. */ void MeasureSNGLoop(AK8975PRMS* prms) { BYTE i2cData[AKSC_BDATA_SIZE]; int16 i; int16 bData[AKSC_BDATA_SIZE]; // Measuring block data int16 ret; int32 ch; int32 doze; int32_t delay; AKMD_INTERVAL interval; struct timespec tsstart, tsend; if (openKey() < 0) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return; } if (openFormation() < 0) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return; } // Get initial interval GetValidInterval(CSPEC_INTERVAL_SNG, &interval); // Initialize if(InitAK8975_Measure(prms) != AKD_SUCCESS){ return; } while(TRUE){ // Get start time if (clock_gettime(CLOCK_REALTIME, &tsstart) < 0) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return; } // Set to SNG measurement pattern (Set CNTL register) if (AKD_SetMode(AK8975_MODE_SNG_MEASURE) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return; } // .! : 获取 M snesor 的原始数据. 这里可能阻塞. // Get measurement data from AK8975 // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + ST2 // = 1 + (1 + 1) + (1 + 1) + (1 + 1) + 1 = 8 bytes if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return; } // Copy to local variable // DBGPRINT(DBG_LEVEL3, "%s: bData(Hex)=", __FUNCTION__); for(i=0; i<AKSC_BDATA_SIZE; i++){ bData[i] = i2cData[i]; // DBGPRINT(DBG_LEVEL3, "%02x,", bData[i]); } // DBGPRINT(DBG_LEVEL3, "\n"); D_WHEN_REPEAT(100, "raw mag x : %d, raw mag y : %d, raw mag z : %d.", (signed short)(bData[1] + (bData[2] << 8) ), (signed short)(bData[3] + (bData[4] << 8) ), (signed short)(bData[5] + (bData[6] << 8) ) ); // .! : // Get acceelration sensor's measurement data. if (GetAccVec(prms) != AKRET_PROC_SUCCEED) { return; } /* DBGPRINT(DBG_LEVEL3, "%s: acc(Hex)=%02x,%02x,%02x\n", __FUNCTION__, prms->m_avec.u.x, prms->m_avec.u.y, prms->m_avec.u.z); */ ret = MeasuringEventProcess( bData, prms, getFormation(), interval.decimator, CSPEC_CNTSUSPEND_SNG ); // Check the return value if(ret == AKRET_PROC_SUCCEED){ if(prms->m_cntSuspend > 0){ // Show message DBGPRINT(DBG_LEVEL2, "Suspend cycle count = %d\n", prms->m_cntSuspend); } else if (prms->m_callcnt <= 1){ // Check interval if (AKD_GetDelay(&delay) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); } else { GetValidInterval(delay, &interval); } } // Display(or dispatch) the result. Disp_MeasurementResultHook(prms); } else if(ret == AKRET_FORMATION_CHANGED){ // Switch formation. SwitchFormation(prms); } else if(ret == AKRET_DATA_READERROR){ DBGPRINT(DBG_LEVEL2, "Data read error occurred.\n\n"); } else if(ret == AKRET_DATA_OVERFLOW){ DBGPRINT(DBG_LEVEL2, "Data overflow occurred.\n\n"); } else if(ret == AKRET_HFLUC_OCCURRED){ DBGPRINT(DBG_LEVEL2, "AKSC_HFlucCheck did not return 1.\n\n"); } else{ // Does not reach here LOGE("MeasuringEventProcess has failed.\n"); break; } // Check user order ch = checkKey(); if (ch == AKKEY_STOP_MEASURE) { break; } else if(ch < 0){ LOGD("Bad key code.\n"); break; } // Get end time if (clock_gettime(CLOCK_REALTIME, &tsend) < 0) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return; } // calculate wait time doze = interval.interval - ((tsend.tv_sec - tsstart.tv_sec)*1000000 + (tsend.tv_nsec - tsstart.tv_nsec)/1000); if (doze < 0) { doze = 0; } // Adjust sampling frequency // DBGPRINT(DBG_LEVEL3, "Sleep %d usec.\n", doze); usleep(doze); } // Set to PowerDown mode if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); } closeFormation(); closeKey(); }
/*! Execute "Onboard Function Test" (NOT includes "START" and "END" command). @retval 1 The test is passed successfully. @retval -1 The test is failed. @retval 0 The test is aborted by kind of system error. @param[in] prms A pointer to a #AK8975PRMS structure. */ int16 FctShipmntTestProcess_Body(AK8975PRMS* prms) { int16 pf_total; //p/f flag for this subtest BYTE i2cData[16]; int16 hdata[3]; int16 asax; int16 asay; int16 asaz; //*********************************************** // Reset Test Result //*********************************************** pf_total = 1; //*********************************************** // Step1 //*********************************************** // Set to PowerDown mode if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } // When the serial interface is SPI, // write "00011011" to I2CDIS register(to disable I2C,). if(CSPEC_SPI_USE == 1){ i2cData[0] = 0x1B; if (AKD_TxData(AK8975_REG_I2CDIS, i2cData, 1) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } } // Read values from WIA to ASTC. if (AKD_RxData(AK8975_REG_WIA, i2cData, 13) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } // TEST TEST_DATA(TLIMIT_NO_RST_WIA, TLIMIT_TN_RST_WIA, (int16)i2cData[0], TLIMIT_LO_RST_WIA, TLIMIT_HI_RST_WIA, &pf_total); TEST_DATA(TLIMIT_NO_RST_INFO, TLIMIT_TN_RST_INFO, (int16)i2cData[1], TLIMIT_LO_RST_INFO, TLIMIT_HI_RST_INFO, &pf_total); TEST_DATA(TLIMIT_NO_RST_ST1, TLIMIT_TN_RST_ST1, (int16)i2cData[2], TLIMIT_LO_RST_ST1, TLIMIT_HI_RST_ST1, &pf_total); TEST_DATA(TLIMIT_NO_RST_HXL, TLIMIT_TN_RST_HXL, (int16)i2cData[3], TLIMIT_LO_RST_HXL, TLIMIT_HI_RST_HXL, &pf_total); TEST_DATA(TLIMIT_NO_RST_HXH, TLIMIT_TN_RST_HXH, (int16)i2cData[4], TLIMIT_LO_RST_HXH, TLIMIT_HI_RST_HXH, &pf_total); TEST_DATA(TLIMIT_NO_RST_HYL, TLIMIT_TN_RST_HYL, (int16)i2cData[5], TLIMIT_LO_RST_HYL, TLIMIT_HI_RST_HYL, &pf_total); TEST_DATA(TLIMIT_NO_RST_HYH, TLIMIT_TN_RST_HYH, (int16)i2cData[6], TLIMIT_LO_RST_HYH, TLIMIT_HI_RST_HYH, &pf_total); TEST_DATA(TLIMIT_NO_RST_HZL, TLIMIT_TN_RST_HZL, (int16)i2cData[7], TLIMIT_LO_RST_HZL, TLIMIT_HI_RST_HZL, &pf_total); TEST_DATA(TLIMIT_NO_RST_HZH, TLIMIT_TN_RST_HZH, (int16)i2cData[8], TLIMIT_LO_RST_HZH, TLIMIT_HI_RST_HZH, &pf_total); TEST_DATA(TLIMIT_NO_RST_ST2, TLIMIT_TN_RST_ST2, (int16)i2cData[9], TLIMIT_LO_RST_ST2, TLIMIT_HI_RST_ST2, &pf_total); TEST_DATA(TLIMIT_NO_RST_CNTL, TLIMIT_TN_RST_CNTL, (int16)i2cData[10], TLIMIT_LO_RST_CNTL, TLIMIT_HI_RST_CNTL, &pf_total); // i2cData[11] is BLANK. TEST_DATA(TLIMIT_NO_RST_ASTC, TLIMIT_TN_RST_ASTC, (int16)i2cData[12], TLIMIT_LO_RST_ASTC, TLIMIT_HI_RST_ASTC, &pf_total); // Read values from I2CDIS. if (AKD_RxData(AK8975_REG_I2CDIS, i2cData, 1) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } if(CSPEC_SPI_USE == 1){ TEST_DATA(TLIMIT_NO_RST_I2CDIS, TLIMIT_TN_RST_I2CDIS, (int16)i2cData[0], TLIMIT_LO_RST_I2CDIS_USESPI, TLIMIT_HI_RST_I2CDIS_USESPI, &pf_total); }else{ TEST_DATA(TLIMIT_NO_RST_I2CDIS, TLIMIT_TN_RST_I2CDIS, (int16)i2cData[0], TLIMIT_LO_RST_I2CDIS_USEI2C, TLIMIT_HI_RST_I2CDIS_USEI2C, &pf_total); } // Set to FUSE ROM access mode if (AKD_SetMode(AK8975_MODE_FUSE_ACCESS) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } // Read values from ASAX to ASAZ if (AKD_RxData(AK8975_FUSE_ASAX, i2cData, 3) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } asax = (int16)i2cData[0]; asay = (int16)i2cData[1]; asaz = (int16)i2cData[2]; #ifdef NOASA if((asax==0)||(asay==0)||(asaz==0)){ asax = 128; asay = 128; asaz = 128; } #endif // TEST TEST_DATA(TLIMIT_NO_ASAX, TLIMIT_TN_ASAX, asax, TLIMIT_LO_ASAX, TLIMIT_HI_ASAX, &pf_total); TEST_DATA(TLIMIT_NO_ASAY, TLIMIT_TN_ASAY, asay, TLIMIT_LO_ASAY, TLIMIT_HI_ASAY, &pf_total); TEST_DATA(TLIMIT_NO_ASAZ, TLIMIT_TN_ASAZ, asaz, TLIMIT_LO_ASAZ, TLIMIT_HI_ASAZ, &pf_total); // Read values. CNTL if (AKD_RxData(AK8975_REG_CNTL, i2cData, 1) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } // Set to PowerDown mode if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } // TEST TEST_DATA(TLIMIT_NO_WR_CNTL, TLIMIT_TN_WR_CNTL, (int16)i2cData[0], TLIMIT_LO_WR_CNTL, TLIMIT_HI_WR_CNTL, &pf_total); //*********************************************** // Step2 //*********************************************** // Set to SNG measurement pattern (Set CNTL register) if (AKD_SetMode(AK8975_MODE_SNG_MEASURE) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } // Wait for DRDY pin changes to HIGH. // Get measurement data from AK8975 // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + ST2 // = 1 + (1 + 1) + (1 + 1) + (1 + 1) + 1 = 8 bytes if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } hdata[0] = (int16)((((uint16)(i2cData[2]))<<8)+(uint16)(i2cData[1])); hdata[1] = (int16)((((uint16)(i2cData[4]))<<8)+(uint16)(i2cData[3])); hdata[2] = (int16)((((uint16)(i2cData[6]))<<8)+(uint16)(i2cData[5])); // TEST TEST_DATA(TLIMIT_NO_SNG_ST1, TLIMIT_TN_SNG_ST1, (int16)i2cData[0], TLIMIT_LO_SNG_ST1, TLIMIT_HI_SNG_ST1, &pf_total); TEST_DATA(TLIMIT_NO_SNG_HX, TLIMIT_TN_SNG_HX, hdata[0], TLIMIT_LO_SNG_HX, TLIMIT_HI_SNG_HX, &pf_total); TEST_DATA(TLIMIT_NO_SNG_HY, TLIMIT_TN_SNG_HY, hdata[1], TLIMIT_LO_SNG_HY, TLIMIT_HI_SNG_HY, &pf_total); TEST_DATA(TLIMIT_NO_SNG_HZ, TLIMIT_TN_SNG_HZ, hdata[2], TLIMIT_LO_SNG_HZ, TLIMIT_HI_SNG_HZ, &pf_total); TEST_DATA(TLIMIT_NO_SNG_ST2, TLIMIT_TN_SNG_ST2, (int16)i2cData[7], TLIMIT_LO_SNG_ST2, TLIMIT_HI_SNG_ST2, &pf_total); // Generate magnetic field for self-test (Set ASTC register) i2cData[0] = 0x40; if (AKD_TxData(AK8975_REG_ASTC, i2cData, 1) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } // Set to Self-test mode (Set CNTL register) if (AKD_SetMode(AK8975_MODE_SELF_TEST) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } // Wait for DRDY pin changes to HIGH. // Get measurement data from AK8975 // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + ST2 // = 1 + (1 + 1) + (1 + 1) + (1 + 1) + 1 = 8Byte if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } // TEST TEST_DATA(TLIMIT_NO_SLF_ST1, TLIMIT_TN_SLF_ST1, (int16)i2cData[0], TLIMIT_LO_SLF_ST1, TLIMIT_HI_SLF_ST1, &pf_total); hdata[0] = (int16)((((uint16)(i2cData[2]))<<8)+(uint16)(i2cData[1])); hdata[1] = (int16)((((uint16)(i2cData[4]))<<8)+(uint16)(i2cData[3])); hdata[2] = (int16)((((uint16)(i2cData[6]))<<8)+(uint16)(i2cData[5])); // TEST TEST_DATA( TLIMIT_NO_SLF_RVHX, TLIMIT_TN_SLF_RVHX, (hdata[0])*((asax - 128)*0.5f/128.0f + 1), TLIMIT_LO_SLF_RVHX, TLIMIT_HI_SLF_RVHX, &pf_total ); TEST_DATA( TLIMIT_NO_SLF_RVHY, TLIMIT_TN_SLF_RVHY, (hdata[1])*((asay - 128)*0.5f/128.0f + 1), TLIMIT_LO_SLF_RVHY, TLIMIT_HI_SLF_RVHY, &pf_total ); TEST_DATA( TLIMIT_NO_SLF_RVHZ, TLIMIT_TN_SLF_RVHZ, (hdata[2])*((asaz - 128)*0.5f/128.0f + 1), TLIMIT_LO_SLF_RVHZ, TLIMIT_HI_SLF_RVHZ, &pf_total ); // TEST TEST_DATA(TLIMIT_NO_SLF_ST2, TLIMIT_TN_SLF_ST2, (int16)i2cData[7], TLIMIT_LO_SLF_ST2, TLIMIT_HI_SLF_ST2, &pf_total); // Set to Normal mode for self-test. i2cData[0] = 0x00; if (AKD_TxData(AK8975_REG_ASTC, i2cData, 1) != AKD_SUCCESS) { DBGPRINT(DBG_LEVEL1, "%s:%d Error.\n", __FUNCTION__, __LINE__); return 0; } return pf_total; }
/*! Carry out self-test. @return If this function succeeds, the return value is #AKM_SUCCESS. Otherwise the return value is #AKM_FAIL. */ int16 AKFS_SelfTest(void) { BYTE i2cData[SENSOR_DATA_SIZE]; BYTE asa[3]; AKFLOAT hdata[3]; int16 ret; /* Set to FUSE ROM access mode */ if (AKD_SetMode(AK8975_MODE_FUSE_ACCESS) != AKD_SUCCESS) { AKMERROR; return AKM_FAIL; } /* Read values from ASAX to ASAZ */ if (AKD_RxData(AK8975_FUSE_ASAX, asa, 3) != AKD_SUCCESS) { AKMERROR; return AKM_FAIL; } /* Set to PowerDown mode */ if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) { AKMERROR; return AKM_FAIL; } /* Set to self-test mode */ i2cData[0] = 0x40; if (AKD_TxData(AK8975_REG_ASTC, i2cData, 1) != AKD_SUCCESS) { AKMERROR; return AKM_FAIL; } /* Set to Self-test mode */ if (AKD_SetMode(AK8975_MODE_SELF_TEST) != AKD_SUCCESS) { AKMERROR; return AKM_FAIL; } /* Wait for DRDY pin changes to HIGH. Get measurement data from AK8975 */ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) { AKMERROR; return AKM_FAIL; } hdata[0] = AK8975_HDATA_CONVERTER(i2cData[2], i2cData[1], asa[0]); hdata[1] = AK8975_HDATA_CONVERTER(i2cData[4], i2cData[3], asa[1]); hdata[2] = AK8975_HDATA_CONVERTER(i2cData[6], i2cData[5], asa[2]); /* Test */ ret = 1; if ((hdata[0] < AK8975_SELFTEST_MIN_X) || (AK8975_SELFTEST_MAX_X < hdata[0])) { ret = 0; } if ((hdata[1] < AK8975_SELFTEST_MIN_Y) || (AK8975_SELFTEST_MAX_Y < hdata[1])) { ret = 0; } if ((hdata[2] < AK8975_SELFTEST_MIN_Z) || (AK8975_SELFTEST_MAX_Z < hdata[2])) { ret = 0; } AKMDEBUG(DBG_LEVEL2, "Test(%s):%8.2f, %8.2f, %8.2f\n", (ret ? "Success" : "fail"), hdata[0], hdata[1], hdata[2]); if (ret) { return AKM_SUCCESS; } else { return AKM_FAIL; } }
/*! This is the main routine of measurement. */ void AKFS_MeasureLoop(void) { BYTE i2cData[SENSOR_DATA_SIZE]; /* ST1 ~ ST2 */ int16 mag[3]; int16 mstat; int16 acc[3]; struct timespec tsstart= {0, 0}; struct timespec tsend = {0, 0}; struct timespec doze; int64_t minimum; uint16 flag; AKSENSOR_DATA sv_acc; AKSENSOR_DATA sv_mag; AKSENSOR_DATA sv_ori; AKFLOAT tmpx, tmpy, tmpz; int16 tmp_accuracy; minimum = -1; #ifdef WIN32 clock_init_time(); #endif /* Initialize library functions and device */ if (AKFS_Start(CSPEC_SETTING_FILE) != AKM_SUCCESS) { AKMERROR; goto MEASURE_END; } while (g_stopRequest != AKM_TRUE) { /* Beginning time */ if (clock_gettime(CLOCK_MONOTONIC, &tsstart) < 0) { AKMERROR; goto MEASURE_END; } /* Get interval */ if (AKFS_GetInterval(&flag, &minimum) != AKM_SUCCESS) { AKMERROR; goto MEASURE_END; } if ((flag & ACC_DATA_READY) || (flag & ORI_DATA_READY)) { /* Get accelerometer */ if (AKD_GetAccelerationData(acc) != AKD_SUCCESS) { AKMERROR; goto MEASURE_END; } /* Calculate accelerometer vector */ if (AKFS_Get_ACCELEROMETER(acc, 0, &tmpx, &tmpy, &tmpz, &tmp_accuracy) == AKM_SUCCESS) { sv_acc.x = tmpx; sv_acc.y = tmpy; sv_acc.z = tmpz; sv_acc.status = tmp_accuracy; } else { flag &= ~ACC_DATA_READY; flag &= ~ORI_DATA_READY; } } if ((flag & MAG_DATA_READY) || (flag & ORI_DATA_READY)) { /* Set to measurement mode */ if (AKD_SetMode(AK8975_MODE_SNG_MEASURE) != AKD_SUCCESS) { AKMERROR; goto MEASURE_END; } /* Wait for DRDY and get data from device */ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) { AKMERROR; goto MEASURE_END; } /* raw data to x,y,z value */ mag[0] = (int)((int16_t)(i2cData[2]<<8)+((int16_t)i2cData[1])); mag[1] = (int)((int16_t)(i2cData[4]<<8)+((int16_t)i2cData[3])); mag[2] = (int)((int16_t)(i2cData[6]<<8)+((int16_t)i2cData[5])); mstat = i2cData[0] | i2cData[7]; AKMDATA(AKMDATA_BDATA, "bData=%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X\n", i2cData[0], i2cData[1], i2cData[2], i2cData[3], i2cData[4], i2cData[5], i2cData[6], i2cData[7]); /* Calculate magnetic field vector */ if (AKFS_Get_MAGNETIC_FIELD(mag, mstat, &tmpx, &tmpy, &tmpz, &tmp_accuracy) == AKM_SUCCESS) { sv_mag.x = tmpx; sv_mag.y = tmpy; sv_mag.z = tmpz; sv_mag.status = tmp_accuracy; } else { flag &= ~MAG_DATA_READY; flag &= ~ORI_DATA_READY; } } if (flag & ORI_DATA_READY) { if (AKFS_Get_ORIENTATION(&tmpx, &tmpy, &tmpz, &tmp_accuracy) == AKM_SUCCESS) { sv_ori.x = tmpx; sv_ori.y = tmpy; sv_ori.z = tmpz; sv_ori.status = tmp_accuracy; } else { flag &= ~ORI_DATA_READY; } } /* Output result */ AKFS_OutputResult(flag, &sv_acc, &sv_mag, &sv_ori); /* Ending time */ if (clock_gettime(CLOCK_MONOTONIC, &tsend) < 0) { AKMERROR; goto MEASURE_END; } /* Calculate duration */ doze = AKFS_CalcSleep(&tsend, &tsstart, minimum); AKMDATA(AKMDATA_LOOP, "Sleep: %6.2f msec\n", (doze.tv_nsec/1000000.0f)); nanosleep(&doze, NULL); #ifdef WIN32 if (_kbhit()) { _getch(); break; } #endif } MEASURE_END: /* Set to PowerDown mode */ if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) { AKMERROR; return; } /* Save parameters */ if (AKFS_Stop(CSPEC_SETTING_FILE) != AKM_SUCCESS) { AKMERROR; } }