Пример #1
0
/* This function is called just before a measurement sequence starts.
  Load parameters from a file and initialize library. This function must be
  called when a sequential measurement thread boots up.
  @return The return value is #AKM_SUCCESS.
  @param[in/out] mem A pointer to a handler.
  @param[in] path The path to a setting file to be read out. The path name
  should be terminated with NULL.
 */
int16 AKFS_Start(void *mem, const char *path)
{
    AKMPRMS *prms;
#ifdef AKM_VALUE_CHECK
    if (mem == NULL || path == NULL) {
        AKMDEBUG(AKMDATA_CHECK, "%s: Invalid mem pointer.", __FUNCTION__);
        return AKM_ERROR;
    }
#endif
    AKMDEBUG(AKMDATA_DUMP, "%s: path=%s\n", __FUNCTION__, path);

    /* Copy pointer */
    prms = (AKMPRMS *)mem;

    /* Read setting files from a file */
    if (AKFS_LoadParameters(prms, path) != AKM_SUCCESS) {
        AKMERROR_STR("AKFS_LoadParameters");
    }

    /* Initialize buffer */
    AKFS_InitBuffer(AKFS_HDATA_SIZE, prms->fva_hdata);
    AKFS_InitBuffer(AKFS_HDATA_SIZE, prms->fva_hvbuf);
    AKFS_InitBuffer(AKFS_ADATA_SIZE, prms->fva_avbuf);

    /* Initialize for AOC */
    AKFS_InitAOC(&prms->s_aocv);
    /* Initialize magnetic status */
    prms->i16_hstatus = 0;

    return AKM_SUCCESS;
}
Пример #2
0
/*!
 Output main menu to stdout and wait for user input from stdin.
 @return Selected mode.
 */
MODE Menu_Main(void)
{
	char msg[20];
	memset(msg, 0, sizeof(msg));

	AKMDEBUG(DBG_LEVEL1,
	" --------------------  AK8975 Console Application -------------------- \n"
	"   1. Start measurement. \n"
	"   2. Self-test. \n"
	"   Q. Quit application. \n"
	" --------------------------------------------------------------------- \n"
	" Please select a number.\n"
	"   ---> ");
	fgets(msg, 10, stdin);
	AKMDEBUG(DBG_LEVEL1, "\n");

	/* BUG : If 2-digits number is input, */
	/*    only the first character is compared. */
	if (!strncmp(msg, "1", 1)) {
		return MODE_Measure;
	} else if (!strncmp(msg, "2", 1)) {
		return MODE_SelfTest;
	} else if (strncmp(msg, "Q", 1) == 0 || strncmp(msg, "q", 1) == 0) {
		return MODE_Quit;
	} else {
		return MODE_ERROR;
	}
}
Пример #3
0
/*!
 Print result
 */
void Disp_Result(int buf[YPR_DATA_SIZE])
{
	AKMDEBUG(DBG_LEVEL1,
		"Flag=%d\n", buf[0]);
	AKMDEBUG(DBG_LEVEL1,
		"Acc(%d):%8.2f, %8.2f, %8.2f\n",
		buf[4], REVERT_ACC(buf[1]), REVERT_ACC(buf[2]), REVERT_ACC(buf[3]));
	AKMDEBUG(DBG_LEVEL1,
		"Mag(%d):%8.2f, %8.2f, %8.2f\n",
		buf[8], REVERT_MAG(buf[5]), REVERT_MAG(buf[6]), REVERT_MAG(buf[7]));
	AKMDEBUG(DBG_LEVEL1,
		"Ori(%d)=%8.2f, %8.2f, %8.2f\n",
		buf[8], REVERT_ORI(buf[9]), REVERT_ORI(buf[10]), REVERT_ORI(buf[11]));
}
Пример #4
0
/*!
  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_ERROR.
  @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_ReadConf(
		uint8	regs[3]
)
{
	BYTE conf[AKM_SENSOR_CONF_SIZE];

#ifdef AKM_VALUE_CHECK
	if (AKM_SENSOR_CONF_SIZE != 3) {
		AKMERROR_STR("You may refer invalid header file.");
		return AKM_ERROR;
	}
#endif

	if (AKD_GetSensorConf(conf) != AKD_SUCCESS) {
		AKMERROR;
		return AKM_ERROR;
	}
	regs[0] = conf[0];
	regs[1] = conf[1];
	regs[2] = conf[2];

	AKMDEBUG(AKMDATA_DUMP, "%s: asa(dec)=%d,%d,%d\n",
			__FUNCTION__, regs[0], regs[1], regs[2]);

	return AKM_SUCCESS;
}
/*!
  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;
}
Пример #6
0
/*! Release allocated memory. This function must be called at the end of using
  APIs. Currently this function is empty.
  @return None
  @param[in/out] mem A pointer to a handler.
 */
void AKFS_Release(void *mem)
{
#ifdef AKM_VALUE_CHECK
	if (mem == NULL) {
		AKMDEBUG(AKMDATA_CHECK, "%s: Invalid mem pointer.", __FUNCTION__);
		return;
	}
#endif
	/* Do nothing */
}
Пример #7
0
/*! This function is called when a measurement sequence is done.
  Save parameters to a file. This function must be called when a sequential
  measurement thread ends.
  @return The return value is #AKM_SUCCESS.
  @param[in/out] mem A pointer to a handler.
  @param[in] path The path to a setting file to be written. The path name
  should be terminated with NULL.
 */
int16 AKFS_Stop(void *mem, const char *path)
{
    AKMPRMS *prms;
#ifdef AKM_VALUE_CHECK
    if (mem == NULL || path == NULL) {
        AKMDEBUG(AKMDATA_CHECK, "%s: Invalid mem pointer.", __FUNCTION__);
        return AKM_ERROR;
    }
#endif
    AKMDEBUG(AKMDATA_DUMP, "%s: path=%s\n", __FUNCTION__, path);

    /* Copy pointer */
    prms = (AKMPRMS *)mem;

    /* Write setting files to a file */
    if (AKFS_SaveParameters(prms, path) != AKM_SUCCESS) {
        AKMERROR_STR("AKFS_SaveParameters");
    }

    return AKM_SUCCESS;
}
Пример #8
0
/*! Initialize #AKMPRMS structure and make APIs ready to use. This function
  must be called before application uses any APIs in this file.  If #AKMPRMS
  are already initialized, this function discards all existing data. When APIs
  are not used anymore, #AKM_Release function must be called at the end.
  When this function succeeds, form factor number is set to 0.
  @return #AKM_SUCCESS on success. #AKM_ERROR if an error occurred.
  @param[in/out] mem A pointer to a handler.
  @param[in] hpat Specify a layout pattern number.  The number is determined
  according to the mount orientation of the magnetometer.
  @param[in] regs[3] Specify the ASA values which are read out from
  fuse ROM.  regs[0] is ASAX, regs[1] is ASAY, regs[2] is ASAZ.
 */
int16 AKFS_Init(
			void		*mem,
	const	AKFS_PATNO	hpat,
	const	uint8		regs[]
)
{
	AKMPRMS *prms;
#ifdef AKM_VALUE_CHECK
	if (mem == NULL) {
		AKMDEBUG(AKMDATA_CHECK, "%s: Invalid mem pointer.", __FUNCTION__);
		return AKM_ERROR;
	}
#endif
	AKMDEBUG(AKMDATA_DUMP, "%s: hpat=%d, r[0]=0x%02X, r[1]=0x%02X, r[2]=0x%02X\n",
		__FUNCTION__, hpat, regs[0], regs[1], regs[2]);

	/* Copy pointer */
	prms = (AKMPRMS *)mem;

	/* Clear all data. */
	memset(prms, 0, sizeof(AKMPRMS));

	/* Sensitivity */
	prms->fv_hs.u.x = AKM_MAG_SENSE;
	prms->fv_hs.u.y = AKM_MAG_SENSE;
	prms->fv_hs.u.z = AKM_MAG_SENSE;
	prms->fv_as.u.x = AKM_ACC_SENSE;
	prms->fv_as.u.y = AKM_ACC_SENSE;
	prms->fv_as.u.z = AKM_ACC_SENSE;

	/* Copy ASA values */
	prms->i8v_asa.u.x = regs[0];
	prms->i8v_asa.u.y = regs[1];
	prms->i8v_asa.u.z = regs[2];

	/* Copy layout pattern */
	prms->e_hpat = hpat;

	return AKM_SUCCESS;
}
Пример #9
0
/*!
 Acquires data from a register or the EEPROM of the AKM E-Compass.
 @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
 the return value is #AKD_FAIL.
 @param[in] address Specify the address of a register from which data is to be
 read.
 @param[out] data Specify a pointer to a data array which the read data are
 stored.
 @param[in] numberOfBytesToRead Specify the number of bytes that make up the
 data to read.  When a pointer to an array is specified in data, this argument
 equals the number of elements of the array.
 */
int16_t AKD_RxData(
		const BYTE address,
		BYTE * data,
		const uint16_t numberOfBytesToRead)
{
	int i;
	char buf[AKM_RWBUF_SIZE];

	memset(data, 0, numberOfBytesToRead);

	if (s_fdDev < 0) {
		AKMERROR;
		return AKD_FAIL;
	}
	if (numberOfBytesToRead > (AKM_RWBUF_SIZE-1)) {
		AKMERROR;
		return AKD_FAIL;
	}

	buf[0] = numberOfBytesToRead;
	buf[1] = address;

	if (ioctl(s_fdDev, ECS_IOCTL_READ, buf) < 0) {
		AKMERROR_STR("ioctl");
		return AKD_FAIL;
	} else {
		for (i = 0; i < numberOfBytesToRead; i++) {
			data[i] = buf[i + 1];
		}
#if ENABLE_AKMDEBUG
		AKMDEBUG(AKMDBG_MAGDRV, "addr(HEX)=%02x len=%d data(HEX)=",
				address, numberOfBytesToRead);
		for (i = 0; i < numberOfBytesToRead; i++) {
			AKMDEBUG(AKMDBG_MAGDRV, " %02x", data[i]);
		}
		AKMDEBUG(AKMDBG_MAGDRV, "\n");
#endif
		return AKD_SUCCESS;
	}
}
Пример #10
0
/*!
 This function parse the option.
 @retval 1 Parse succeeds.
 @retval 0 Parse failed.
 @param[in] argc Argument count
 @param[in] argv Argument vector
 @param[out] layout_patno
 */
int OptParse(
	int	argc,
	char*	argv[],
	AKMD_PATNO*	hlayout_patno)
{
	int	opt;
	char optVal;

	/* Initial value */
	*hlayout_patno = PAT_INVALID;

	while ((opt = getopt(argc, argv, "sm:z:")) != -1) {
		switch(opt){
			case 'm':
				optVal = (char)(optarg[0] - '0');
				if ((PAT1 <= optVal) && (optVal <= PAT8)) {
					*hlayout_patno = (AKMD_PATNO)optVal;
				}
				break;
			case 'z':
				/* If error detected, hopefully 0 is returned. */
				g_dbgzone = (int)strtol(optarg, (char**)NULL, 0);
				break;
			case 's':
				g_opmode |= OPMODE_CONSOLE;
				break;
			default:
				ALOGE("%s: Invalid argument", argv[0]);
				return 0;
		}
	}

	AKMDEBUG(AKMDBG_DEBUG, "%s: Mode=0x%04X\n", __FUNCTION__, g_opmode);
	AKMDEBUG(AKMDBG_DEBUG, "%s: Layout=%d\n", __FUNCTION__, *hlayout_patno);
	AKMDEBUG(AKMDBG_DEBUG, "%s: Dbg Zone=0x%04X\n", __FUNCTION__, g_dbgzone);

	return 1;
}
Пример #11
0
/*!
 Acquire magnetic data from AKM E-Compass. If measurement is not done, this
 function waits until measurement completion.
 @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
 the return value is #AKD_FAIL.
 @param[out] data A magnetic data array. The size should be larger than
 #AKM_SENSOR_DATA_SIZE.
 */
int16_t AKD_GetMagneticData(BYTE data[AKM_SENSOR_DATA_SIZE])
{
	int ret;
	int i;

	memset(data, 0, AKM_SENSOR_DATA_SIZE);

	if (s_fdDev < 0) {
		AKMERROR;
		return AKD_FAIL;
	}

	for (i = 0; i < AKM_MEASURE_RETRY_NUM; i++) {
		ret = ioctl(s_fdDev, ECS_IOCTL_GETDATA, data);

		if (ret >= 0) {
			/* Success */
			break;
		}
		if (errno != EAGAIN) {
			AKMERROR_STR("ioctl");
			return AKD_FAIL;
		}
		AKMDEBUG(AKMDBG_MAGDRV, "Try Again.");
		usleep(AKM_MEASURE_TIME_US);
	}

	if (i >= AKM_MEASURE_RETRY_NUM) {
		AKMERROR;
		return AKD_FAIL;
	}

	AKMDEBUG(AKMDBG_MAGDRV,
			"bdata(HEX)= %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
			data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]);

	return AKD_SUCCESS;
}
Пример #12
0
/*!
 Writes data to a register of the AKM E-Compass.  When more than one byte of
 data is specified, the data is written in contiguous locations starting at an
 address specified in \a address.
 @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
 the return value is #AKD_FAIL.
 @param[in] address Specify the address of a register in which data is to be
 written.
 @param[in] data Specify data to write or a pointer to a data array containing
 the data.  When specifying more than one byte of data, specify the starting
 address of the array.
 @param[in] numberOfBytesToWrite Specify the number of bytes that make up the
 data to write.  When a pointer to an array is specified in data, this argument
 equals the number of elements of the array.
 */
int16_t AKD_TxData(
		const BYTE address,
		const BYTE * data,
		const uint16_t numberOfBytesToWrite)
{
	int i;
	char buf[AKM_RWBUF_SIZE];

	if (s_fdDev < 0) {
		AKMERROR;
		return AKD_FAIL;
	}
	if (numberOfBytesToWrite > (AKM_RWBUF_SIZE-2)) {
		AKMERROR;
		return AKD_FAIL;
	}

	buf[0] = numberOfBytesToWrite + 1;
	buf[1] = address;

	for (i = 0; i < numberOfBytesToWrite; i++) {
		buf[i + 2] = data[i];
	}
	if (ioctl(s_fdDev, ECS_IOCTL_WRITE, buf) < 0) {
		AKMERROR_STR("ioctl");
		return AKD_FAIL;
	} else {

#if ENABLE_AKMDEBUG
		AKMDEBUG(AKMDBG_MAGDRV, "addr(HEX)=%02x data(HEX)=", address);
		for (i = 0; i < numberOfBytesToWrite; i++) {
			AKMDEBUG(AKMDBG_MAGDRV, " %02x", data[i]);
		}
		AKMDEBUG(AKMDBG_MAGDRV, "\n");
#endif
		return AKD_SUCCESS;
	}
}
Пример #13
0
/*!
  This function is called when new accelerometer data is available.  The output
  vector format and coordination system follow the Android definition.
  @return The return value is #AKM_SUCCESS when function succeeds. Otherwise
   the return value is #AKM_ERROR.
  @param[in] acc A set of measurement data from accelerometer.  X axis value
   should be in acc[0], Y axis value should be in acc[1], Z axis value should be 
   in acc[2].
  @param[in] status A status of accelerometer.  This status indicates the result
   of acceleration data, i.e. overflow, success or fail, etc.
 */
int16 AKFS_Get_ACCELEROMETER(
			void		*mem,
	const   int16		acc[3],
	const	int16		status,
			AKFLOAT		*ax,
			AKFLOAT		*ay,
			AKFLOAT		*az,
			int16		*accuracy
)
{
	AKMPRMS *prms;
#ifdef AKM_VALUE_CHECK
	if (mem == NULL) {
		AKMDEBUG(AKMDATA_CHECK, "%s: Invalid mem pointer.", __FUNCTION__);
		return AKM_ERROR;
	}
	if (ax == NULL || ay == NULL || az == NULL || accuracy == NULL) {
		AKMDEBUG(AKMDATA_CHECK, "%s: Invalid data pointer.", __FUNCTION__);
		return AKM_ERROR;
	}
#endif

	/* Copy pointer */
	prms = (AKMPRMS *)mem;

	if (AKFS_Set_ACCELEROMETER(prms, acc, status) != AKM_SUCCESS) {
		return AKM_ERROR;
	}

	/* Success */
	*ax = prms->fv_avec.u.x;
	*ay = prms->fv_avec.u.y;
	*az = prms->fv_avec.u.z;
	*accuracy = 3;

	return AKM_SUCCESS;
}
Пример #14
0
/*!
  This function is called when new magnetometer data is available.  The output
  vector format and coordination system follow the Android definition.
  @return The return value is #AKM_SUCCESS.
   Otherwise the return value is #AKM_ERROR.
  @param[in/out] mem A pointer to a handler.
  @param[in] mag A set of measurement data from magnetometer.  X axis value
   should be in mag[0], Y axis value should be in mag[1], Z axis value should be 
   in mag[2].
  @param[in] status A status of magnetometer.  This status indicates the result
   of measurement data, i.e. overflow, success or fail, etc.
 */
int16 AKFS_Get_MAGNETIC_FIELD(
			void		*mem,
	const   int16		mag[3],
	const	int16		status,
			AKFLOAT		*hx,
			AKFLOAT		*hy,
			AKFLOAT		*hz,
			int16		*accuracy
)
{
	AKMPRMS *prms;
//#define AKM_VALUE_CHECK
#ifdef AKM_VALUE_CHECK
	if (mem == NULL) {
		AKMDEBUG(AKMDATA_CHECK, "%s: Invalid mem pointer.", __FUNCTION__);
		return AKM_ERROR;
	}
	if (hx == NULL || hy == NULL || hz == NULL || accuracy == NULL) {
		AKMDEBUG(AKMDATA_CHECK, "%s: Invalid data pointer.", __FUNCTION__);
		return AKM_ERROR;
	}
#endif

	/* Copy pointer */
	prms = (AKMPRMS *)mem;
	if (AKFS_Set_MAGNETIC_FIELD(prms, mag, status) != AKM_SUCCESS) {
		return AKM_ERROR;
	}

	/* Success */
	*hx = prms->fv_hvec.u.x;
	*hy = prms->fv_hvec.u.y;
	*hz = prms->fv_hvec.u.z;
	*accuracy = prms->i16_hstatus;

	return AKM_SUCCESS;
}
Пример #15
0
/*!
  Get interval of each sensors from device driver.
  @return If this function succeeds, the return value is #AKM_SUCCESS.
   Otherwise the return value is #AKM_ERROR.
  @param flag This variable indicates what sensor frequency is updated.
  @param minimum This value show the minimum loop period in all sensors.
 */
int16 AKFS_GetInterval(
		uint16*  flag,
		int64_t* minimum
)
{
	/* Accelerometer, Magnetometer, Fusion */
	/* Delay is in nano second unit. */
	/* Negative value means the sensor is disabled.*/
	int64_t delay[AKM_NUM_SENSORS];
	int i;

#ifdef AKM_VALUE_CHECK
	if (AKM_NUM_SENSORS != 3) {
		AKMERROR_STR("You may refer invalid header file.");
		return AKM_ERROR;
	}
#endif

	if (AKD_GetDelay(delay) != AKD_SUCCESS) {
		AKMERROR;
		return AKM_ERROR;
	}
	AKMDEBUG(AKMDATA_LOOP, "delay[A,M,O]=%lld,%lld,%lld\n",
		delay[0], delay[1], delay[2]);

	/* update */
	*minimum = 1000000000;
	*flag = 0;
	for (i=0; i<AKM_NUM_SENSORS; i++) {
		/* Set flag */
		if (delay[i] >= 0) {
			*flag |= 1 << i;
			if (*minimum > delay[i]) {
				*minimum = delay[i];
			}
		}
	}
	return AKM_SUCCESS;
}
Пример #16
0
/*!
 This is main function.
 */
int main(int argc, char **argv)
{
	AK8963PRMS prms;
	int retValue = 0;
	AKMD_PATNO pat;
	int16 outbit;

	/* Show the version info of this software. */
	Disp_StartMessage();

#if ENABLE_AKMDEBUG
	/* Register signal handler */
	signal(SIGINT, signal_handler);
#endif

#if ENABLE_FORMATION
	RegisterFormClass(&s_formClass);
#endif

	/* Open device driver. */
	if (AKD_InitDevice() != AKD_SUCCESS) {
		retValue = ERROR_INITDEVICE;
		goto THE_END_OF_MAIN_FUNCTION;
	}

	/* Parse command-line options */
	if (OptParse(argc, argv, &pat, &outbit) == 0) {
		retValue = ERROR_OPTPARSE;
		goto THE_END_OF_MAIN_FUNCTION;
	}

	/* Initialize parameters structure. */
	InitAK8963PRMS(&prms);

	/* Put argument to PRMS. */
	prms.m_layout = pat;
	prms.m_outbit = outbit;

	/* Read Fuse ROM */
	if (ReadAK8963FUSEROM(&prms) != AKRET_PROC_SUCCEED) {
		retValue = ERROR_FUSEROM;
		goto THE_END_OF_MAIN_FUNCTION;
	}

	/* Here is the Main Loop */
	if (g_opmode) {
		/*** Console Mode *********************************************/
		while (AKD_TRUE) {
			/* Select operation */
			switch (Menu_Main()) {
				case MODE_FctShipmntTestBody:
					FctShipmntTest_Body(&prms);
					break;

				case MODE_MeasureSNG:
					/* Read Parameters from file. */
					if (LoadParameters(&prms) == 0) {
						SetDefaultPRMS(&prms);
					}
					/* Reset flag */
					g_stopRequest = 0;
					/* Measurement routine */
					MeasureSNGLoop(&prms);

					/* Write Parameters to file. */
					SaveParameters(&prms);
					break;

				case MODE_Quit:
					goto THE_END_OF_MAIN_FUNCTION;
					break;

				default:
					AKMDEBUG(DBG_LEVEL0, "Unknown operation mode.\n");
					break;
			}
		}
	} else {
		/*** Daemon Mode *********************************************/
		while (g_mainQuit == AKD_FALSE) {
			int st = 0;
			/* Wait until device driver is opened. */
			if (AKD_GetOpenStatus(&st) != AKD_SUCCESS) {
				retValue = ERROR_GETOPEN_STAT;
				goto THE_END_OF_MAIN_FUNCTION;
			}
			if (st == 0) {
				ALOGI("Suspended.");
			} else {
				ALOGI("Compass Opened.");
				/* Read Parameters from file. */
				if (LoadParameters(&prms) == 0) {
					SetDefaultPRMS(&prms);
				}
				/* Reset flag */
				g_stopRequest = 0;
				/* Start measurement thread. */
				if (startClone(&prms) == 0) {
					retValue = ERROR_STARTCLONE;
					goto THE_END_OF_MAIN_FUNCTION;
				}

				/* Wait until device driver is closed. */
				if (AKD_GetCloseStatus(&st) != AKD_SUCCESS) {
					retValue = ERROR_GETCLOSE_STAT;
					g_mainQuit = AKD_TRUE;
				}
				/* Wait thread completion. */
				g_stopRequest = 1;
				pthread_join(s_thread, NULL);
				ALOGI("Compass Closed.");

				/* Write Parameters to file. */
				SaveParameters(&prms);
			}
		}
	}

THE_END_OF_MAIN_FUNCTION:

	/* Close device driver. */
	AKD_DeinitDevice();

	/* Show the last message. */
	Disp_EndMessage(retValue);

	return retValue;
}
Пример #17
0
/*!
 This function parse the option.
 @retval 1 Parse succeeds.
 @retval 0 Parse failed.
 @param[in] argc Argument count
 @param[in] argv Argument vector
 @param[out] layout_patno
 */
int OptParse(
	int	argc,
	char*	argv[],
	AKMD_PATNO*	layout_patno,
	int16*	outbit)
{
	int	opt;
	char	optVal;

	*layout_patno = PAT_INVALID;
	*outbit = OUTBIT_INVALID;

	while ((opt = getopt(argc, argv, "sm:o:z:")) != -1) {
		switch(opt){
			case 'm':
				optVal = (char)(optarg[0] - '0');
				if ((PAT1 <= optVal) && (optVal <= PAT8)) {
					*layout_patno = (AKMD_PATNO)optVal;
					AKMDEBUG(DBG_LEVEL2, "%s: Layout=%d\n", __FUNCTION__, optVal);
				}
				break;
			case 'o':
				optVal = (char)(optarg[0] - '0');
				if ((optVal == OUTBIT_14) || (optVal == OUTBIT_16)) {
					*outbit = optVal;
					AKMDEBUG(DBG_LEVEL2, "%s: outbit=%d\n", __FUNCTION__, *outbit);
				}
				break;
			case 'z':
				/* If error detected, hopefully 0 is returned. */
				errno = 0;
				g_dbgzone = (int)strtol(optarg, (char**)NULL, 0);
				AKMDEBUG(DBG_LEVEL2, "%s: Dbg Zone=%d\n", __FUNCTION__, g_dbgzone);
				break;
			case 's':
				g_opmode = 1;
				break;
			default:
				ALOGE("%s: Invalid argument", argv[0]);
				return 0;
		}
	}

	/* If layout is not specified with argument, get parameter from driver */
	if (*layout_patno == PAT_INVALID) {
		int16_t n;
		if (AKD_GetLayout(&n) == AKD_SUCCESS) {
			if ((PAT1 <= n) && (n <= PAT8)) {
				*layout_patno = (AKMD_PATNO)n;
			}
		}
	}
	/* Error */
	if (*layout_patno == PAT_INVALID) {
		ALOGE("No layout is specified.");
		return 0;
	}
	
	/* If outbit is not specified with argument, get parameter from driver */
	if (*outbit == OUTBIT_INVALID) {
		int16_t b;
		if (AKD_GetOutbit(&b) == AKD_SUCCESS) {
			if ((b == OUTBIT_14) || (b == OUTBIT_16)) {
				*outbit = b;
			}
		}
	}
	/* Error */
	if (*outbit == OUTBIT_INVALID) {
		ALOGE("No outbit is specified.");
		return 0;
	}

	return 1;
}
/*!
  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;
	}
}
Пример #19
0
/*!
 This is main function.
 */
int main(int argc, char **argv)
{
	AKSCPRMS prms;
	int retValue = 0;

	/* Show the version info of this software. */
	Disp_StartMessage();

#if ENABLE_AKMDEBUG
	/* Register signal handler */
	signal(SIGINT, signal_handler);
#endif

#if ENABLE_FORMATION
	RegisterFormClass(&s_formClass);
#endif

	/* Initialize parameters structure. */
	InitAKSCPRMS(&prms);

	/* Parse command-line options */
	if (OptParse(argc, argv, &prms.m_hlayout) == 0) {
		retValue = ERROR_OPTPARSE;
		goto THE_END_OF_MAIN_FUNCTION;
	}

	/* Open device driver. */
	if (AKD_InitDevice() != AKD_SUCCESS) {
		retValue = ERROR_INITDEVICE;
		goto THE_END_OF_MAIN_FUNCTION;
	}

	/* If layout is not specified with argument, get parameter from driver */
	if (prms.m_hlayout == PAT_INVALID) {
		int16_t n;
		if (AKD_GetLayout(&n) == AKD_SUCCESS) {
			if ((PAT1 <= n) && (n <= PAT8)) {
				prms.m_hlayout = (AKMD_PATNO)n;
			}
		}
		/* Error */
		if (prms.m_hlayout == PAT_INVALID) {
			ALOGE("Magnetic sensor's layout is specified.");
			retValue = ERROR_HLAYOUT;
			goto THE_END_OF_MAIN_FUNCTION;
		}
	}

	/* Read Fuse ROM */
	if (ReadFUSEROM(&prms) != AKRET_PROC_SUCCEED) {
		retValue = ERROR_FUSEROM;
		goto THE_END_OF_MAIN_FUNCTION;
	}

	/* PDC */
	LoadPDC(&prms);

	/* Here is the Main Loop */
	if (g_opmode & OPMODE_CONSOLE) {
		/*** Console Mode *********************************************/
		while (AKD_TRUE) {
			/* Select operation */
			switch (Menu_Main()) {
				case MODE_FST:
					FST_Body();
					break;

				case MODE_MeasureSNG:
					/* Read Parameters from file. */
					if (LoadParameters(&prms) == 0) {
						SetDefaultPRMS(&prms);
					}
					/* Reset flag */
					g_stopRequest = 0;
					/* Measurement routine */
					MeasureSNGLoop(&prms);

					/* Write Parameters to file. */
					SaveParameters(&prms);
					break;

				case MODE_OffsetCalibration:
					/* Read Parameters from file. */
					if (LoadParameters(&prms) == 0) {
						SetDefaultPRMS(&prms);
					}
					/* measure offset (NOT sensitivity) */
					if (SimpleCalibration(&prms) == AKRET_PROC_SUCCEED) {
						SaveParameters(&prms);
					}
					break;

				case MODE_Quit:
					goto THE_END_OF_MAIN_FUNCTION;
					break;

				default:
					AKMDEBUG(AKMDBG_DEBUG, "Unknown operation mode.\n");
					break;
			}
		}
	} else {
		/*** Daemon Mode *********************************************/
		while (g_mainQuit == AKD_FALSE) {
			int st = 0;
			/* Wait until device driver is opened. */
			if (AKD_GetOpenStatus(&st) != AKD_SUCCESS) {
				retValue = ERROR_GETOPEN_STAT;
				goto THE_END_OF_MAIN_FUNCTION;
			}
			if (st == 0) {
				AKMDEBUG(AKMDBG_DEBUG, "Suspended.");
			} else {
				AKMDEBUG(AKMDBG_DEBUG, "Compass Opened.");
				/* Read Parameters from file. */
				if (LoadParameters(&prms) == 0) {
					SetDefaultPRMS(&prms);
				}
				/* Reset flag */
				g_stopRequest = 0;
				/* Start measurement thread. */
				if (startClone(&prms) == 0) {
					retValue = ERROR_STARTCLONE;
					goto THE_END_OF_MAIN_FUNCTION;
				}

				/* Wait until device driver is closed. */
				if (AKD_GetCloseStatus(&st) != AKD_SUCCESS) {
					retValue = ERROR_GETCLOSE_STAT;
					g_mainQuit = AKD_TRUE;
				}
				/* Wait thread completion. */
				g_stopRequest = 1;
				pthread_join(s_thread, NULL);
				AKMDEBUG(AKMDBG_DEBUG, "Compass Closed.");

				/* Write Parameters to file. */
				SaveParameters(&prms);
			}
		}
	}

THE_END_OF_MAIN_FUNCTION:

	/* Close device driver. */
	AKD_DeinitDevice();

	/* Show the last message. */
	Disp_EndMessage(retValue);

	return retValue;
}
Пример #20
0
int main(int argc, char **argv)
{
	int			retValue = 0;
	AKMPRMS		prms;
	AKFS_PATNO	pat;
	uint8		regs[3];

	/* Show the version info of this software. */
	Disp_StartMessage();

#if ENABLE_AKMDEBUG
	/* Register signal handler */
	signal(SIGINT, signal_handler);
#endif

	/* Open device driver */
	if(AKD_InitDevice() != AKD_SUCCESS) {
		retValue = ERROR_INITDEVICE;
		goto MAIN_QUIT;
	}

	/* Parse command-line options */
	/* This function calls device driver function to get layout */
	if (OptParse(argc, argv, &pat) == 0) {
		retValue = ERROR_OPTPARSE;
		goto MAIN_QUIT;
	}

	/* Self Test */
	/*
	if (g_opmode & OPMODE_FST){
		if (AKFS_SelfTest() != AKD_SUCCESS) {
			retValue = ERROR_SELF_TEST;
			goto MAIN_QUIT;
		}
	}*/

	/* OK, then start */
	if (AKFS_ReadConf(regs) != AKM_SUCCESS) {
		retValue = ERROR_READ_FUSE;
		goto MAIN_QUIT;
	}

	/* Initialize library. */
	if (AKFS_Init(&prms, pat, regs) != AKM_SUCCESS) {
		retValue = ERROR_INIT;
		goto MAIN_QUIT;
	}

	/* Start console mode */
	if (g_opmode & OPMODE_CONSOLE) {
		ConsoleMode((void *)&prms);
		goto MAIN_QUIT;
	}

	/*** Start Daemon ********************************************/
	while (g_mainQuit == AKD_FALSE) {
		int st = 0;
		/* Wait until device driver is opened. */
		if (AKD_GetOpenStatus(&st) != AKD_SUCCESS) {
			retValue = ERROR_GETOPEN_STAT;
			goto MAIN_QUIT;
		}
		if (st == 0) {
			AKMDEBUG(AKMDATA_LOOP, "Suspended.");
		} else {
			AKMDEBUG(AKMDATA_LOOP, "Compass Opened.");
			/* Reset flag */
			g_stopRequest = 0;
			/* Start measurement thread. */
			if (startClone((void *)&prms) == 0) {
				retValue = ERROR_STARTCLONE;
				goto MAIN_QUIT;
			}

			/* Wait until device driver is closed. */
			if (AKD_GetCloseStatus(&st) != AKD_SUCCESS) {
				retValue = ERROR_GETCLOSE_STAT;
				g_mainQuit = AKD_TRUE;
			}
			/* Wait thread completion. */
			g_stopRequest = 1;
			pthread_join(s_thread, NULL);
			AKMDEBUG(AKMDATA_LOOP, "Compass Closed.");
		}
	}

MAIN_QUIT:

	/* Release library */
	AKFS_Release(&prms);
	/* Close device driver. */
	AKD_DeinitDevice();
	/* Show the last message. */
	Disp_EndMessage(retValue);

	return retValue;
}
Пример #21
0
/*!
 This function parse the option.
 @retval 1 Parse succeeds.
 @retval 0 Parse failed.
 @param[in] argc Argument count
 @param[in] argv Argument vector
 @param[out] layout_patno
 */
int OptParse(
	int		argc,
	char*	argv[],
	AKFS_PATNO*	layout_patno)
{
#ifdef WIN32
	/* Static */
#if defined(AKFS_WIN32_PAT1)
	*layout_patno = PAT1;
#elif defined(AKFS_WIN32_PAT2)
	*layout_patno = PAT2;
#elif defined(AKFS_WIN32_PAT3)
	*layout_patno = PAT3;
#elif defined(AKFS_WIN32_PAT4)
	*layout_patno = PAT4;
#elif defined(AKFS_WIN32_PAT5)
	*layout_patno = PAT5;
#else
	*layout_patno = PAT1;
#endif
	g_opmode = OPMODE_CONSOLE;
	/*g_opmode = 0;*/
	g_dbgzone = AKMDATA_DUMP | AKMDATA_DEBUG | AKMDATA_CONSOLE;
#else
	int		opt;
	char	optVal;

	*layout_patno = PAT_INVALID;

	while ((opt = getopt(argc, argv, "sm:z:")) != -1) {
		switch(opt){
			case 'm':
				optVal = (char)(optarg[0] - '0');
				if ((PAT1 <= optVal) && (optVal <= PAT8)) {
					*layout_patno = (AKFS_PATNO)optVal;
					AKMDEBUG(AKMDATA_DEBUG, "%s: Layout=%d\n", __FUNCTION__, optVal);
				}
				break;
			case 's':
				g_opmode |= OPMODE_CONSOLE;
				break;
            case 'z':
                /* If error detected, hopefully 0 is returned. */
                errno = 0;
                g_dbgzone = (int)strtol(optarg, (char**)NULL, 0); 
                AKMDEBUG(AKMDATA_DEBUG, "%s: Dbg Zone=%d\n", __FUNCTION__, g_dbgzone);
                break;
			default:
				AKMERROR_STR("Invalid argument");
				return 0;
		}
	}

	/* If layout is not specified with argument, get parameter from driver */
	if (*layout_patno == PAT_INVALID) {
		int16_t n = 0;
		if (AKD_GetLayout(&n) == AKD_SUCCESS) {
			if ((PAT1 <= n) && (n <= PAT8)) {
				*layout_patno = (AKFS_PATNO)n;
			}
		}
		AKMDEBUG(AKMDATA_DEBUG, "Layout=%d\n", n);
	}
	/* Error */
	if (*layout_patno == PAT_INVALID) {
		AKMERROR_STR("No layout is specified.");
		return 0;
	}
#endif

	return 1;
}
Пример #22
0
/*!
 A thread function which is raised when measurement is started.
 @param[in] args This parameter is not used currently.
 */
static void* thread_main(void* args)
{
	AKMPRMS	*prms;
	BYTE    i2cData[AKM_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;

	prms = (AKMPRMS *)args;
	minimum = -1;

	/* Initialize library functions and device */
	if (AKFS_Start(prms, 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 & FUSION_DATA_READY)) {
			/* Get accelerometer */
			if (AKD_GetAccelerationData(acc) != AKD_SUCCESS) {
				AKMERROR;
				goto MEASURE_END;
			}

			/* Calculate accelerometer vector */
			if (AKFS_Get_ACCELEROMETER(prms, 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 &= ~FUSION_DATA_READY;
			}
		}

		if ((flag & MAG_DATA_READY) || (flag & FUSION_DATA_READY)) {
			/* Set to measurement mode  */
			if (AKD_SetMode(AKM_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];

			/* Calculate magnetic field vector */
			if (AKFS_Get_MAGNETIC_FIELD(prms, 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 &= ~FUSION_DATA_READY;
			}
		}

		if (flag & FUSION_DATA_READY) {
			if (AKFS_Get_ORIENTATION(prms, &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 &= ~FUSION_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);
		AKMDEBUG(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(AKM_MODE_POWERDOWN) != AKD_SUCCESS) {
		AKMERROR;
	}

	/* Save parameters */
	if (AKFS_Stop(prms, CSPEC_SETTING_FILE) != AKM_SUCCESS) {
		AKMERROR;
	}
	return ((void*)0);
}
Пример #23
0
/*!
  Get orientation sensor's elements. The vector format and coordination system
   follow the Android definition.  Before this function is called, magnetic
   field vector and acceleration vector should be stored in the buffer by 
   calling #AKFS_Get_MAGNETIC_FIELD and #AKFS_Get_ACCELEROMETER.
  @return The return value is #AKM_SUCCESS when function succeeds. Otherwise
   the return value is #AKM_ERROR.
  @param[out] azimuth Azimuthal angle in degree.
  @param[out] pitch Pitch angle in degree.
  @param[out] roll Roll angle in degree.
  @param[out] accuracy Accuracy of orientation sensor.
 */
int16 AKFS_Get_ORIENTATION(
			void		*mem,
			AKFLOAT		*azimuth,
			AKFLOAT		*pitch,
			AKFLOAT		*roll,
			int16		*accuracy
)
{
	int16 akret;
	AKMPRMS *prms;
#ifdef AKM_VALUE_CHECK
	if (mem == NULL) {
		AKMDEBUG(AKMDATA_CHECK, "%s: Invalid mem pointer.", __FUNCTION__);
		return AKM_ERROR;
	}
	if (pitch== NULL || pitch == NULL || roll == NULL || accuracy == NULL) {
		AKMDEBUG(AKMDATA_CHECK, "%s: Invalid data pointer.", __FUNCTION__);
		return AKM_ERROR;
	}
#endif

	/* Copy pointer */
	prms = (AKMPRMS *)mem;

	/* Azimuth calculation */
	/* hvbuf[in] : Android coordinate, sensitivity adjusted, */
	/*			   offset subtracted. */
	/* avbuf[in] : Android coordinate, sensitivity adjusted, */
	/*			   offset subtracted. */
	/* azimuth[out]: Android coordinate and unit (degree). */
	/* pitch  [out]: Android coordinate and unit (degree). */
	/* roll   [out]: Android coordinate and unit (degree). */
	akret = AKFS_Direction(
		AKFS_HDATA_SIZE,
		prms->fva_hvbuf,
		CSPEC_HNAVE_D,
		AKFS_ADATA_SIZE,
		prms->fva_avbuf,
		CSPEC_ANAVE_D,
		&prms->f_azimuth,
		&prms->f_pitch,
		&prms->f_roll
	);

	if (akret == AKFS_ERROR) {
		AKMERROR;
		return AKM_ERROR;
	}

	/* Success */
	*azimuth = prms->f_azimuth;
	*pitch   = prms->f_pitch;
	*roll    = prms->f_roll;
	*accuracy = 3;

	/* Debug output */
	AKMDEBUG(AKMDATA_ORI, "Ori(?):%8.2f, %8.2f, %8.2f\n",
			*azimuth, *pitch, *roll);

	return AKM_SUCCESS;
}