1
0
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

455 lines
14 KiB

/******************************************************************************
*
* $Id: FST_AK8975.c 878 2012-11-30 07:57:24Z yamada.rj $
*
* -- Copyright Notice --
*
* Copyright (c) 2004 Asahi Kasei Microdevices Corporation, Japan
* All Rights Reserved.
*
* This software program is the proprietary program of Asahi Kasei Microdevices
* Corporation("AKM") licensed to authorized Licensee under the respective
* agreement between the Licensee and AKM only for use with AKM's electronic
* compass IC.
*
* THIS SOFTWARE IS PROVIDED TO YOU "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABLITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT OF
* THIRD PARTY RIGHTS, AND WE SHALL NOT BE LIABLE FOR ANY LOSSES AND DAMAGES
* WHICH MAY OCCUR THROUGH USE OF THIS SOFTWARE.
*
* -- End Asahi Kasei Microdevices Copyright Notice --
*
******************************************************************************/
#include "AKCommon.h"
#include "AKMD_Driver.h"
#include "FST.h"
#include "misc.h"
#ifndef AKMD_FOR_AK8975
#error "AKMD parameter is not set"
#endif
#define TLIMIT_TN_REVISION ""
#define TLIMIT_NO_RST_WIA "1-3"
#define TLIMIT_TN_RST_WIA "RST_WIA"
#define TLIMIT_LO_RST_WIA 0x48
#define TLIMIT_HI_RST_WIA 0x48
#define TLIMIT_NO_RST_INFO "1-4"
#define TLIMIT_TN_RST_INFO "RST_INFO"
#define TLIMIT_LO_RST_INFO 0
#define TLIMIT_HI_RST_INFO 255
#define TLIMIT_NO_RST_ST1 "1-5"
#define TLIMIT_TN_RST_ST1 "RST_ST1"
#define TLIMIT_LO_RST_ST1 0
#define TLIMIT_HI_RST_ST1 0
#define TLIMIT_NO_RST_HXL "1-6"
#define TLIMIT_TN_RST_HXL "RST_HXL"
#define TLIMIT_LO_RST_HXL 0
#define TLIMIT_HI_RST_HXL 0
#define TLIMIT_NO_RST_HXH "1-7"
#define TLIMIT_TN_RST_HXH "RST_HXH"
#define TLIMIT_LO_RST_HXH 0
#define TLIMIT_HI_RST_HXH 0
#define TLIMIT_NO_RST_HYL "1-8"
#define TLIMIT_TN_RST_HYL "RST_HYL"
#define TLIMIT_LO_RST_HYL 0
#define TLIMIT_HI_RST_HYL 0
#define TLIMIT_NO_RST_HYH "1-9"
#define TLIMIT_TN_RST_HYH "RST_HYH"
#define TLIMIT_LO_RST_HYH 0
#define TLIMIT_HI_RST_HYH 0
#define TLIMIT_NO_RST_HZL "1-10"
#define TLIMIT_TN_RST_HZL "RST_HZL"
#define TLIMIT_LO_RST_HZL 0
#define TLIMIT_HI_RST_HZL 0
#define TLIMIT_NO_RST_HZH "1-11"
#define TLIMIT_TN_RST_HZH "RST_HZH"
#define TLIMIT_LO_RST_HZH 0
#define TLIMIT_HI_RST_HZH 0
#define TLIMIT_NO_RST_ST2 "1-12"
#define TLIMIT_TN_RST_ST2 "RST_ST2"
#define TLIMIT_LO_RST_ST2 0
#define TLIMIT_HI_RST_ST2 0
#define TLIMIT_NO_RST_CNTL "1-13"
#define TLIMIT_TN_RST_CNTL "RST_CNTL"
#define TLIMIT_LO_RST_CNTL 0
#define TLIMIT_HI_RST_CNTL 0
#define TLIMIT_NO_RST_ASTC "1-14"
#define TLIMIT_TN_RST_ASTC "RST_ASTC"
#define TLIMIT_LO_RST_ASTC 0
#define TLIMIT_HI_RST_ASTC 0
#define TLIMIT_NO_RST_I2CDIS "1-15"
#define TLIMIT_TN_RST_I2CDIS "RST_I2CDIS"
#define TLIMIT_LO_RST_I2CDIS_USEI2C 0
#define TLIMIT_HI_RST_I2CDIS_USEI2C 0
#define TLIMIT_LO_RST_I2CDIS_USESPI 1
#define TLIMIT_HI_RST_I2CDIS_USESPI 1
#define TLIMIT_NO_ASAX "1-17"
#define TLIMIT_TN_ASAX "ASAX"
#define TLIMIT_LO_ASAX 1
#define TLIMIT_HI_ASAX 254
#define TLIMIT_NO_ASAY "1-18"
#define TLIMIT_TN_ASAY "ASAY"
#define TLIMIT_LO_ASAY 1
#define TLIMIT_HI_ASAY 254
#define TLIMIT_NO_ASAZ "1-19"
#define TLIMIT_TN_ASAZ "ASAZ"
#define TLIMIT_LO_ASAZ 1
#define TLIMIT_HI_ASAZ 254
#define TLIMIT_NO_WR_CNTL "1-20"
#define TLIMIT_TN_WR_CNTL "WR_CNTL"
#define TLIMIT_LO_WR_CNTL 0x0F
#define TLIMIT_HI_WR_CNTL 0x0F
#define TLIMIT_NO_SNG_ST1 "2-3"
#define TLIMIT_TN_SNG_ST1 "SNG_ST1"
#define TLIMIT_LO_SNG_ST1 1
#define TLIMIT_HI_SNG_ST1 1
#define TLIMIT_NO_SNG_HX "2-4"
#define TLIMIT_TN_SNG_HX "SNG_HX"
#define TLIMIT_LO_SNG_HX -4095
#define TLIMIT_HI_SNG_HX 4094
#define TLIMIT_NO_SNG_HY "2-6"
#define TLIMIT_TN_SNG_HY "SNG_HY"
#define TLIMIT_LO_SNG_HY -4095
#define TLIMIT_HI_SNG_HY 4094
#define TLIMIT_NO_SNG_HZ "2-8"
#define TLIMIT_TN_SNG_HZ "SNG_HZ"
#define TLIMIT_LO_SNG_HZ -4095
#define TLIMIT_HI_SNG_HZ 4094
#define TLIMIT_NO_SNG_ST2 "2-10"
#define TLIMIT_TN_SNG_ST2 "SNG_ST2"
#define TLIMIT_LO_SNG_ST2 0
#define TLIMIT_HI_SNG_ST2 0
#define TLIMIT_NO_SLF_ST1 "2-14"
#define TLIMIT_TN_SLF_ST1 "SLF_ST1"
#define TLIMIT_LO_SLF_ST1 1
#define TLIMIT_HI_SLF_ST1 1
#define TLIMIT_NO_SLF_RVHX "2-15"
#define TLIMIT_TN_SLF_RVHX "SLF_REVSHX"
#define TLIMIT_LO_SLF_RVHX -100
#define TLIMIT_HI_SLF_RVHX 100
#define TLIMIT_NO_SLF_RVHY "2-17"
#define TLIMIT_TN_SLF_RVHY "SLF_REVSHY"
#define TLIMIT_LO_SLF_RVHY -100
#define TLIMIT_HI_SLF_RVHY 100
#define TLIMIT_NO_SLF_RVHZ "2-19"
#define TLIMIT_TN_SLF_RVHZ "SLF_REVSHZ"
#define TLIMIT_LO_SLF_RVHZ -1000
#define TLIMIT_HI_SLF_RVHZ -300
#define TLIMIT_NO_SLF_ST2 "2-21"
#define TLIMIT_TN_SLF_ST2 "SLF_ST2"
#define TLIMIT_LO_SLF_ST2 0
#define TLIMIT_HI_SLF_ST2 0
/*!
@return If @a testdata is in the range of between @a lolimit and @a hilimit,
the return value is 1, otherwise -1.
@param[in] testno A pointer to a text string.
@param[in] testname A pointer to a text string.
@param[in] testdata A data to be tested.
@param[in] lolimit The maximum allowable value of @a testdata.
@param[in] hilimit The minimum allowable value of @a testdata.
@param[in,out] pf_total
*/
int16
TEST_DATA(const char testno[],
const char testname[],
const int16 testdata,
const int16 lolimit,
const int16 hilimit,
int16 * pf_total)
{
int16 pf; //Pass;1, Fail;-1
if ((testno == NULL) && (strncmp(testname, "START", 5) == 0)) {
// Display header
AKMDEBUG(AKMDBG_DISP1, "--------------------------------------------------------------------\n");
AKMDEBUG(AKMDBG_DISP1, " Test No. Test Name Fail Test Data [ Low High]\n");
AKMDEBUG(AKMDBG_DISP1, "--------------------------------------------------------------------\n");
pf = 1;
} else if ((testno == NULL) && (strncmp(testname, "END", 3) == 0)) {
// Display result
AKMDEBUG(AKMDBG_DISP1, "--------------------------------------------------------------------\n");
if (*pf_total == 1) {
AKMDEBUG(AKMDBG_DISP1, "Factory shipment test was passed.\n\n");
} else {
AKMDEBUG(AKMDBG_DISP1, "Factory shipment test was failed.\n\n");
}
pf = 1;
} else {
if ((lolimit <= testdata) && (testdata <= hilimit)) {
//Pass
pf = 1;
} else {
//Fail
pf = -1;
}
//display result
AKMDEBUG(AKMDBG_DISP1, " %7s %-10s %c %9d [%9d %9d]\n",
testno, testname, ((pf == 1) ? ('.') : ('F')), testdata,
lolimit, hilimit);
}
//Pass/Fail check
if (*pf_total != 0) {
if ((*pf_total == 1) && (pf == 1)) {
*pf_total = 1; //Pass
} else {
*pf_total = -1; //Fail
}
}
return pf;
}
/*!
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.
*/
int16 FST_AK8975(void)
{
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) {
AKMERROR;
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) {
AKMERROR;
return 0;
}
}
// Read values from WIA to ASTC.
if (AKD_RxData(AK8975_REG_WIA, i2cData, 13) != AKD_SUCCESS) {
AKMERROR;
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) {
AKMERROR;
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) {
AKMERROR;
return 0;
}
// Read values from ASAX to ASAZ
if (AKD_RxData(AK8975_FUSE_ASAX, i2cData, 3) != AKD_SUCCESS) {
AKMERROR;
return 0;
}
asax = (int16)i2cData[0];
asay = (int16)i2cData[1];
asaz = (int16)i2cData[2];
// 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) {
AKMERROR;
return 0;
}
// Set to PowerDown mode
if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) {
AKMERROR;
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) {
AKMERROR;
return 0;
}
// Wait for DRDY pin changes to HIGH.
//usleep(AKM_MEASURE_TIME_US);
// 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) {
AKMERROR;
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) {
AKMERROR;
return 0;
}
// Set to Self-test mode (Set CNTL register)
if (AKD_SetMode(AK8975_MODE_SELF_TEST) != AKD_SUCCESS) {
AKMERROR;
return 0;
}
// Wait for DRDY pin changes to HIGH.
//usleep(AKM_MEASURE_TIME_US);
// 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) {
AKMERROR;
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) {
AKMERROR;
return 0;
}
return pf_total;
}
/*!
Execute "Onboard Function Test" (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.
*/
int16 FST_Body(void)
{
int16 pf_total = 1;
//***********************************************
// Reset Test Result
//***********************************************
TEST_DATA(NULL, "START", 0, 0, 0, &pf_total);
//***********************************************
// Step 1 to 2
//***********************************************
pf_total = FST_AK8975();
//***********************************************
// Judge Test Result
//***********************************************
TEST_DATA(NULL, "END", 0, 0, 0, &pf_total);
return pf_total;
}