From c3e3f6d5cf648ce07e05c08add7002db34d9ef91 Mon Sep 17 00:00:00 2001 From: Rocco Marco Guglielmi Date: Sun, 11 Mar 2018 16:46:12 +0000 Subject: Updated LIS3MDL driver git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11705 110e8d01-0319-4d1e-a829-52ad28d1bb01 --- os/ex/ST/lis3mdl.c | 502 ++++++++++++++------- os/ex/ST/lis3mdl.h | 430 ++++++++++++------ testex/STM32/STM32F4xx/I2C-LIS3MLD/Makefile | 34 +- ...4xx-I2C-LIS3MDL (OpenOCD, Flash and Run).launch | 2 +- testex/STM32/STM32F4xx/I2C-LIS3MLD/main.c | 157 ++----- testex/STM32/STM32F4xx/I2C-LPS25H/readme.txt | 2 +- 6 files changed, 668 insertions(+), 459 deletions(-) diff --git a/os/ex/ST/lis3mdl.c b/os/ex/ST/lis3mdl.c index 1106053af..65d227711 100644 --- a/os/ex/ST/lis3mdl.c +++ b/os/ex/ST/lis3mdl.c @@ -1,5 +1,5 @@ /* - ChibiOS - Copyright (C) 2016 Rocco Marco Guglielmi + ChibiOS - Copyright (C) 2016-2018 Rocco Marco Guglielmi This file is part of ChibiOS. @@ -92,218 +92,345 @@ msg_t lis3mdlI2CWriteRegister(I2CDriver *i2cp, lis3mdl_sad_t sad, uint8_t* txbuf } #endif /* LIS3MDL_USE_I2C */ -/* - * Interface implementation. +/** + * @brief Return the number of axes of the BaseCompass. + * + * @param[in] ip pointer to @p BaseCompass interface + * + * @return the number of axes. */ -static size_t get_axes_number(void *ip) { +static size_t comp_get_axes_number(void *ip) { osalDbgCheck(ip != NULL); - return LIS3MDL_NUMBER_OF_AXES; + return LIS3MDL_COMP_NUMBER_OF_AXES; } -static msg_t read_raw(void *ip, int32_t axes[LIS3MDL_NUMBER_OF_AXES]) { +/** + * @brief Retrieves raw data from the BaseCompass. + * @note This data is retrieved from MEMS register without any algebraical + * manipulation. + * @note The axes array must be at least the same size of the + * BaseCompass axes number. + * + * @param[in] ip pointer to @p BaseCompass interface. + * @param[out] axes a buffer which would be filled with raw data. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. + */ +static msg_t comp_read_raw(void *ip, int32_t axes[]) { + LIS3MDLDriver* devp; + uint8_t buff [LIS3MDL_COMP_NUMBER_OF_AXES * 2], i; int16_t tmp; - uint8_t i, buff[2 * LIS3MDL_NUMBER_OF_AXES]; - msg_t msg = MSG_OK; - + msg_t msg; + osalDbgCheck((ip != NULL) && (axes != NULL)); - osalDbgAssert((((LIS3MDLDriver *)ip)->state == LIS3MDL_READY), - "read_raw(), invalid state"); -#if LIS3MDL_USE_I2C - osalDbgAssert((((LIS3MDLDriver *)ip)->config->i2cp->state == I2C_READY), - "read_raw(), channel not ready"); - + + /* Getting parent instance pointer.*/ + devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip); + + osalDbgAssert((devp->state == LIS3MDL_READY), + "comp_read_raw(), invalid state"); + osalDbgAssert((devp->config->i2cp->state == I2C_READY), + "comp_read_raw(), channel not ready"); + #if LIS3MDL_SHARED_I2C - i2cAcquireBus(((LIS3MDLDriver *)ip)->config->i2cp); - i2cStart(((LIS3MDLDriver *)ip)->config->i2cp, - ((LIS3MDLDriver *)ip)->config->i2ccfg); + i2cAcquireBus(devp->config->i2cp); + i2cStart(devp->config->i2cp, + devp->config->i2ccfg); #endif /* LIS3MDL_SHARED_I2C */ - - msg = lis3mdlI2CReadRegister(((LIS3MDLDriver *)ip)->config->i2cp, - ((LIS3MDLDriver *)ip)->config->slaveaddress, - LIS3MDL_AD_OUT_X_L, buff, 2 * LIS3MDL_NUMBER_OF_AXES); + msg = lis3mdlI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress, + LIS3MDL_AD_OUT_X_L, buff, + LIS3MDL_COMP_NUMBER_OF_AXES * 2); #if LIS3MDL_SHARED_I2C - i2cReleaseBus(((LIS3MDLDriver *)ip)->config->i2cp); + i2cReleaseBus(devp->config->i2cp); #endif /* LIS3MDL_SHARED_I2C */ -#endif /* LIS3MDL_USE_I2C */ - - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) { - if(msg == MSG_OK) { - tmp = buff[2*i] + (buff[2*i+1] << 8); + + if(msg == MSG_OK) + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) { + tmp = buff[2 * i] + (buff[2 * i + 1] << 8); axes[i] = (int32_t)tmp; } - else{ - axes[i] = 0; - } - } return msg; } -static msg_t read_cooked(void *ip, float axes[]) { +/** + * @brief Retrieves cooked data from the BaseCompass. + * @note This data is manipulated according to the formula + * cooked = (raw * sensitivity) - bias. + * @note Final data is expressed as G. + * @note The axes array must be at least the same size of the + * BaseCompass axes number. + * + * @param[in] ip pointer to @p BaseCompass interface. + * @param[out] axes a buffer which would be filled with cooked data. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. + */ +static msg_t comp_read_cooked(void *ip, float axes[]) { + LIS3MDLDriver* devp; uint32_t i; - int32_t raw[LIS3MDL_NUMBER_OF_AXES]; + int32_t raw[LIS3MDL_COMP_NUMBER_OF_AXES]; msg_t msg; osalDbgCheck((ip != NULL) && (axes != NULL)); - osalDbgAssert((((LIS3MDLDriver *)ip)->state == LIS3MDL_READY), - "read_cooked(), invalid state"); - - msg = read_raw(ip, raw); - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES ; i++){ - axes[i] = raw[i] * ((LIS3MDLDriver *)ip)->sensitivity[i]; - axes[i] -= ((LIS3MDLDriver *)ip)->bias[i]; + + /* Getting parent instance pointer.*/ + devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip); + + osalDbgAssert((devp->state == LIS3MDL_READY), + "comp_read_cooked(), invalid state"); + + msg = comp_read_raw(ip, raw); + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES ; i++) { + axes[i] = (raw[i] * devp->compsensitivity[i]) - devp->compbias[i]; } return msg; } -static msg_t set_bias(void *ip, float *bp) { +/** + * @brief Set bias values for the BaseCompass. + * @note Bias must be expressed as G. + * @note The bias buffer must be at least the same size of the + * BaseCompass axes number. + * + * @param[in] ip pointer to @p BaseCompass interface. + * @param[in] bp a buffer which contains biases. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + */ +static msg_t comp_set_bias(void *ip, float *bp) { + LIS3MDLDriver* devp; uint32_t i; + msg_t msg = MSG_OK; - osalDbgCheck((ip != NULL) && (bp !=NULL)); + osalDbgCheck((ip != NULL) && (bp != NULL)); + + /* Getting parent instance pointer.*/ + devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip); - osalDbgAssert((((LIS3MDLDriver *)ip)->state == LIS3MDL_READY) || - (((LIS3MDLDriver *)ip)->state == LIS3MDL_STOP), - "set_bias(), invalid state"); - - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) { - ((LIS3MDLDriver *)ip)->bias[i] = bp[i]; + osalDbgAssert((devp->state == LIS3MDL_READY), + "comp_set_bias(), invalid state"); + + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) { + devp->compbias[i] = bp[i]; } - return MSG_OK; + return msg; } -static msg_t reset_bias(void *ip) { +/** + * @brief Reset bias values for the BaseCompass. + * @note Default biases value are obtained from device datasheet when + * available otherwise they are considered zero. + * + * @param[in] ip pointer to @p BaseCompass interface. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + */ +static msg_t comp_reset_bias(void *ip) { + LIS3MDLDriver* devp; uint32_t i; + msg_t msg = MSG_OK; osalDbgCheck(ip != NULL); + + /* Getting parent instance pointer.*/ + devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip); - osalDbgAssert((((LIS3MDLDriver *)ip)->state == LIS3MDL_READY) || - (((LIS3MDLDriver *)ip)->state == LIS3MDL_STOP), - "reset_bias(), invalid state"); + osalDbgAssert((devp->state == LIS3MDL_READY), + "comp_reset_bias(), invalid state"); - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - ((LIS3MDLDriver *)ip)->bias[i] = 0; - return MSG_OK; + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) + devp->compbias[i] = LIS3MDL_COMP_BIAS; + return msg; } -static msg_t set_sensivity(void *ip, float *sp) { +/** + * @brief Set sensitivity values for the BaseCompass. + * @note Sensitivity must be expressed as G/LSB. + * @note The sensitivity buffer must be at least the same size of the + * BaseCompass axes number. + * + * @param[in] ip pointer to @p BaseCompass interface. + * @param[in] sp a buffer which contains sensitivities. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + */ +static msg_t comp_set_sensivity(void *ip, float *sp) { + LIS3MDLDriver* devp; uint32_t i; + msg_t msg = MSG_OK; - osalDbgCheck((ip != NULL) && (sp !=NULL)); + /* Getting parent instance pointer.*/ + devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip); - osalDbgAssert((((LIS3MDLDriver *)ip)->state == LIS3MDL_READY), - "set_sensivity(), invalid state"); - - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) { - ((LIS3MDLDriver *)ip)->sensitivity[i] = sp[i]; + osalDbgCheck((ip != NULL) && (sp != NULL)); + + osalDbgAssert((devp->state == LIS3MDL_READY), + "comp_set_sensivity(), invalid state"); + + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) { + devp->compsensitivity[i] = sp[i]; } - return MSG_OK; + return msg; } -static msg_t reset_sensivity(void *ip) { +/** + * @brief Reset sensitivity values for the BaseCompass. + * @note Default sensitivities value are obtained from device datasheet. + * + * @param[in] ip pointer to @p BaseCompass interface. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET otherwise. + */ +static msg_t comp_reset_sensivity(void *ip) { + LIS3MDLDriver* devp; uint32_t i; + msg_t msg = MSG_OK; osalDbgCheck(ip != NULL); - - osalDbgAssert((((LIS3MDLDriver *)ip)->state == LIS3MDL_READY), - "reset_sensivity(), invalid state"); - - if(((LIS3MDLDriver *)ip)->config->fullscale == LIS3MDL_FS_4GA) - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - ((LIS3MDLDriver *)ip)->sensitivity[i] = LIS3MDL_SENS_4GA; - else if(((LIS3MDLDriver *)ip)->config->fullscale == LIS3MDL_FS_8GA) - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - ((LIS3MDLDriver *)ip)->sensitivity[i] = LIS3MDL_SENS_8GA; - else if(((LIS3MDLDriver *)ip)->config->fullscale == LIS3MDL_FS_12GA) - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - ((LIS3MDLDriver *)ip)->sensitivity[i] = LIS3MDL_SENS_12GA; - else if(((LIS3MDLDriver *)ip)->config->fullscale == LIS3MDL_FS_16GA) - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - ((LIS3MDLDriver *)ip)->sensitivity[i] = LIS3MDL_SENS_16GA; + + /* Getting parent instance pointer.*/ + devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip); + + osalDbgAssert((devp->state == LIS3MDL_READY), + "comp_reset_sensivity(), invalid state"); + + if(devp->config->compfullscale == LIS3MDL_COMP_FS_4GA) + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) + devp->compsensitivity[i] = LIS3MDL_COMP_SENS_4GA; + else if(devp->config->compfullscale == LIS3MDL_COMP_FS_8GA) + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) + devp->compsensitivity[i] = LIS3MDL_COMP_SENS_8GA; + else if(devp->config->compfullscale == LIS3MDL_COMP_FS_12GA) + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) + devp->compsensitivity[i] = LIS3MDL_COMP_SENS_12GA; + else if(devp->config->compfullscale == LIS3MDL_COMP_FS_16GA) + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) + devp->compsensitivity[i] = LIS3MDL_COMP_SENS_16GA; else { - osalDbgAssert(FALSE, "reset_sensivity(), compass full scale issue"); - return MSG_RESET; + osalDbgAssert(FALSE, "comp_reset_sensivity(), compass full scale issue"); + msg = MSG_RESET; } - return MSG_OK; + return msg; } -static msg_t set_full_scale(void *ip, lis3mdl_fs_t fs) { +/** + * @brief Changes the LIS3MDLDriver compass fullscale value. + * @note This function also rescale sensitivities and biases based on + * previous and next fullscale value. + * @note A recalibration is highly suggested after calling this function. + * + * @param[in] ip pointer to @p LIS3MDLDriver interface. + * @param[in] fs new fullscale value. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET otherwise. + */ +static msg_t comp_set_full_scale(LIS3MDLDriver *devp, + lis3mdl_comp_fs_t fs) { float newfs, scale; - uint8_t i, cr[2]; + uint8_t i, buff[2]; msg_t msg; + + osalDbgCheck(devp != NULL); + + osalDbgAssert((devp->state == LIS3MDL_READY), + "comp_set_full_scale(), invalid state"); + osalDbgAssert((devp->config->i2cp->state == I2C_READY), + "comp_set_full_scale(), channel not ready"); - if(fs == LIS3MDL_FS_4GA) { - newfs = LIS3MDL_4GA; + /* Computing new fullscale value.*/ + if(fs == LIS3MDL_COMP_FS_4GA) { + newfs = LIS3MDL_COMP_4GA; } - else if(fs == LIS3MDL_FS_8GA) { - newfs = LIS3MDL_8GA; + else if(fs == LIS3MDL_COMP_FS_8GA) { + newfs = LIS3MDL_COMP_8GA; } - else if(fs == LIS3MDL_FS_12GA) { - newfs = LIS3MDL_12GA; + else if(fs == LIS3MDL_COMP_FS_12GA) { + newfs = LIS3MDL_COMP_12GA; } - else if(fs == LIS3MDL_FS_16GA) { - newfs = LIS3MDL_16GA; + else if(fs == LIS3MDL_COMP_FS_16GA) { + newfs = LIS3MDL_COMP_16GA; } else { - return MSG_RESET; + msg = MSG_RESET; + return msg; } - if(newfs != ((LIS3MDLDriver *)ip)->fullscale) { - scale = newfs / ((LIS3MDLDriver *)ip)->fullscale; - ((LIS3MDLDriver *)ip)->fullscale = newfs; - + if(newfs != devp->compfullscale) { + /* Computing scale value.*/ + scale = newfs / devp->compfullscale; + devp->compfullscale = newfs; + #if LIS3MDL_SHARED_I2C - i2cAcquireBus(((LIS3MDLDriver *)ip)->config->i2cp); - i2cStart(((LIS3MDLDriver *)ip)->config->i2cp, - ((LIS3MDLDriver *)ip)->config->i2ccfg); + i2cAcquireBus(devp->config->i2cp); + i2cStart(devp->config->i2cp, devp->config->i2ccfg); #endif /* LIS3MDL_SHARED_I2C */ /* Updating register.*/ - msg = lis3mdlI2CReadRegister(((LIS3MDLDriver *)ip)->config->i2cp, - ((LIS3MDLDriver *)ip)->config->slaveaddress, - LIS3MDL_AD_CTRL_REG2, &cr[1], 1); + msg = lis3mdlI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress, + LIS3MDL_AD_CTRL_REG2, &buff[1], 1); + #if LIS3MDL_SHARED_I2C - i2cReleaseBus(((LIS3MDLDriver *)ip)->config->i2cp); -#endif /* LIS3MDL_SHARED_I2C */ + i2cReleaseBus(devp->config->i2cp); +#endif /* LIS3MDL_SHARED_I2C */ + if(msg != MSG_OK) return msg; - - cr[0] = LIS3MDL_AD_CTRL_REG2; - cr[1] &= ~(LIS3MDL_CTRL_REG2_FS_MASK); - cr[1] |= fs; + buff[1] &= ~(LIS3MDL_CTRL_REG2_FS_MASK); + buff[1] |= fs; + buff[0] = LIS3MDL_AD_CTRL_REG2; #if LIS3MDL_SHARED_I2C - i2cAcquireBus(((LIS3MDLDriver *)ip)->config->i2cp); - i2cStart(((LIS3MDLDriver *)ip)->config->i2cp, - ((LIS3MDLDriver *)ip)->config->i2ccfg); + i2cAcquireBus(devp->config->i2cp); + i2cStart(devp->config->i2cp, devp->config->i2ccfg); #endif /* LIS3MDL_SHARED_I2C */ - - msg = lis3mdlI2CWriteRegister(((LIS3MDLDriver *)ip)->config->i2cp, - ((LIS3MDLDriver *)ip)->config->slaveaddress, cr, 1); + + msg = lis3mdlI2CWriteRegister(devp->config->i2cp, + devp->config->slaveaddress, + buff, 1); + #if LIS3MDL_SHARED_I2C - i2cReleaseBus(((LIS3MDLDriver *)ip)->config->i2cp); + i2cReleaseBus(devp->config->i2cp); #endif /* LIS3MDL_SHARED_I2C */ + if(msg != MSG_OK) return msg; - /* Scaling sensitivity and bias. Re-calibration is suggested anyway. */ - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) { - ((LIS3MDLDriver *)ip)->sensitivity[i] *= scale; - ((LIS3MDLDriver *)ip)->bias[i] *= scale; + /* Scaling sensitivity and bias. Re-calibration is suggested anyway.*/ + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) { + devp->compsensitivity[i] *= scale; + devp->compbias[i] *= scale; } } return msg; } -static const struct BaseSensorVMT vmt_sensor = { - get_axes_number, read_raw, read_cooked +static const struct LIS3MDLVMT vmt_device = { + (size_t)0, + comp_set_full_scale }; -static const struct LIS3MDLCompassVMT vmt_compass = { - get_axes_number, read_raw, read_cooked, - set_bias, reset_bias, set_sensivity, reset_sensivity, - set_full_scale +static const struct BaseCompassVMT vmt_compass = { + sizeof(struct LIS3MDLVMT*), + comp_get_axes_number, comp_read_raw, comp_read_cooked, + comp_set_bias, comp_reset_bias, comp_set_sensivity, comp_reset_sensivity }; /*===========================================================================*/ @@ -318,12 +445,13 @@ static const struct LIS3MDLCompassVMT vmt_compass = { * @init */ void lis3mdlObjectInit(LIS3MDLDriver *devp) { - uint32_t i; - devp->vmt_sensor = &vmt_sensor; - devp->vmt_compass = &vmt_compass; + devp->vmt = &vmt_device; + devp->comp_if.vmt = &vmt_compass; + devp->config = NULL; - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - devp->bias[i] = 0.0f; + + devp->compaxes = LIS3MDL_COMP_NUMBER_OF_AXES; + devp->state = LIS3MDL_STOP; } @@ -348,9 +476,9 @@ void lis3mdlStart(LIS3MDLDriver *devp, const LIS3MDLConfig *config) { /* Control register 1 configuration block.*/ { cr[0] = LIS3MDL_AD_CTRL_REG1; - cr[1] = devp->config->outputdatarate; -#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__) - cr[1] |= devp->config->operationmodexy; + cr[1] = devp->config->compoutputdatarate; +#if LIS3MDL_COMP_USE_ADVANCED || defined(__DOXYGEN__) + cr[1] |= devp->config->compoperationmodexy; #else cr[1] |= LIS3MDL_CTRL_REG1_OM0 | LIS3MDL_CTRL_REG1_OM1; #endif @@ -358,29 +486,29 @@ void lis3mdlStart(LIS3MDLDriver *devp, const LIS3MDLConfig *config) { /* Control register 2 configuration block.*/ { - cr[2] = devp->config->fullscale; + cr[2] = devp->config->compfullscale; } /* Control register 3 configuration block.*/ { cr[3] = 0; -#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__) - cr[3] = devp->config->conversionmode; +#if LIS3MDL_COMP_USE_ADVANCED || defined(__DOXYGEN__) + cr[3] = devp->config->compconversionmode; #endif } /* Control register 4 configuration block.*/ { cr[4] = 0; -#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__) - cr[4] = devp->config->operationmodez | devp->config->endianness; +#if LIS3MDL_COMP_USE_ADVANCED || defined(__DOXYGEN__) + cr[4] = devp->config->compoperationmodez | devp->config->endianness; #endif } /* Control register 5 configuration block.*/ { cr[5] = 0; -#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__) +#if LIS3MDL_COMP_USE_ADVANCED || defined(__DOXYGEN__) cr[5] = devp->config->blockdataupdate; #endif } @@ -391,6 +519,7 @@ void lis3mdlStart(LIS3MDLDriver *devp, const LIS3MDLConfig *config) { #endif /* LIS3MDL_SHARED_I2C */ i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg); + lis3mdlI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress, cr, 5); @@ -399,44 +528,64 @@ void lis3mdlStart(LIS3MDLDriver *devp, const LIS3MDLConfig *config) { #endif /* LIS3MDL_SHARED_I2C */ #endif /* LIS3MDL_USE_I2C */ - if(devp->config->sensitivity == NULL) { - /* Storing sensitivity information according to full scale value */ - if(devp->config->fullscale == LIS3MDL_FS_4GA) { - devp->fullscale = LIS3MDL_4GA; - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - devp->sensitivity[i] = LIS3MDL_SENS_4GA; - } - else if(devp->config->fullscale == LIS3MDL_FS_8GA) { - devp->fullscale = LIS3MDL_8GA; - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - devp->sensitivity[i] = LIS3MDL_SENS_8GA; + if(devp->config->compfullscale == LIS3MDL_COMP_FS_4GA) { + devp->compfullscale = LIS3MDL_COMP_4GA; + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) { + if(devp->config->compsensitivity == NULL) { + devp->compsensitivity[i] = LIS3MDL_COMP_SENS_4GA; + } + else { + devp->compsensitivity[i] = devp->config->compsensitivity[i]; + } } - else if(devp->config->fullscale == LIS3MDL_FS_12GA) { - devp->fullscale = LIS3MDL_12GA; - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - devp->sensitivity[i] = LIS3MDL_SENS_12GA; + } + else if(devp->config->compfullscale == LIS3MDL_COMP_FS_8GA) { + devp->compfullscale = LIS3MDL_COMP_8GA; + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) { + if(devp->config->compsensitivity == NULL) { + devp->compsensitivity[i] = LIS3MDL_COMP_SENS_8GA; + } + else { + devp->compsensitivity[i] = devp->config->compsensitivity[i]; + } } - else if(devp->config->fullscale == LIS3MDL_FS_16GA) { - devp->fullscale = LIS3MDL_16GA; - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - devp->sensitivity[i] = LIS3MDL_SENS_16GA; + } + else if(devp->config->compfullscale == LIS3MDL_COMP_FS_12GA) { + devp->compfullscale = LIS3MDL_COMP_12GA; + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) { + if(devp->config->compsensitivity == NULL) { + devp->compsensitivity[i] = LIS3MDL_COMP_SENS_12GA; + } + else { + devp->compsensitivity[i] = devp->config->compsensitivity[i]; + } } - else - osalDbgAssert(FALSE, "lis3mdlStart(), compass full scale issue"); } - else{ - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - devp->sensitivity[i] = devp->config->sensitivity[i]; + else if(devp->config->compfullscale == LIS3MDL_COMP_FS_16GA) { + devp->compfullscale = LIS3MDL_COMP_16GA; + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) { + if(devp->config->compsensitivity == NULL) { + devp->compsensitivity[i] = LIS3MDL_COMP_SENS_16GA; + } + else { + devp->compsensitivity[i] = devp->config->compsensitivity[i]; + } + } } + else + osalDbgAssert(FALSE, "lis3mdlStart(), compass full scale issue"); + + /* Storing bias information */ + if(devp->config->compbias != NULL) + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) + devp->compbias[i] = devp->config->compbias[i]; + else + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) + devp->compbias[i] = LIS3MDL_COMP_BIAS; + + /* This is the MEMS transient recovery time */ + osalThreadSleepMilliseconds(5); - if(devp->config->bias == NULL) { - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - devp->bias[i] = 0.0f; - } - else { - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) - devp->bias[i] = devp->config->bias[i]; - } devp->state = LIS3MDL_READY; } @@ -461,10 +610,13 @@ void lis3mdlStop(LIS3MDLDriver *devp) { i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg); #endif /* LIS3MDL_SHARED_I2C */ + + /* Disabling compass. */ cr[0] = LIS3MDL_AD_CTRL_REG3; cr[1] = LIS3MDL_CTRL_REG3_MD0 | LIS3MDL_CTRL_REG3_MD1; lis3mdlI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress, cr, 1); + i2cStop((devp)->config->i2cp); #if LIS3MDL_SHARED_I2C i2cReleaseBus((devp)->config->i2cp); diff --git a/os/ex/ST/lis3mdl.h b/os/ex/ST/lis3mdl.h index de3c35eed..937064c81 100644 --- a/os/ex/ST/lis3mdl.h +++ b/os/ex/ST/lis3mdl.h @@ -1,5 +1,5 @@ /* - ChibiOS - Copyright (C) 2016 Rocco Marco Guglielmi + ChibiOS - Copyright (C) 2016-2018 Rocco Marco Guglielmi This file is part of ChibiOS. @@ -42,7 +42,7 @@ /** * @brief LIS3MDL driver version string. */ -#define EX_LIS3MDL_VERSION "1.0.5" +#define EX_LIS3MDL_VERSION "1.0.6" /** * @brief LIS3MDL driver version major number. @@ -57,25 +57,29 @@ /** * @brief LIS3MDL driver version patch number. */ -#define EX_LIS3MDL_PATCH 5 +#define EX_LIS3MDL_PATCH 6 /** @} */ /** - * @brief LIS3MDL characteristics. + * @brief LIS3MDL compass subsystem characteristics. + * @note Sensitivity is expressed as G/LSB whereas G stands for Gauss. + * @note Bias is expressed as G. * * @{ */ -#define LIS3MDL_NUMBER_OF_AXES 3U - -#define LIS3MDL_4GA 4.0f -#define LIS3MDL_8GA 8.0f -#define LIS3MDL_12GA 12.0f -#define LIS3MDL_16GA 16.0f - -#define LIS3MDL_SENS_4GA 0.00014615f -#define LIS3MDL_SENS_8GA 0.00029231f -#define LIS3MDL_SENS_12GA 0.0004384f -#define LIS3MDL_SENS_16GA 0.00058445f +#define LIS3MDL_COMP_NUMBER_OF_AXES 3U + +#define LIS3MDL_COMP_4GA 4.0f +#define LIS3MDL_COMP_8GA 8.0f +#define LIS3MDL_COMP_12GA 12.0f +#define LIS3MDL_COMP_16GA 16.0f + +#define LIS3MDL_COMP_SENS_4GA 0.00014615f +#define LIS3MDL_COMP_SENS_8GA 0.00029231f +#define LIS3MDL_COMP_SENS_12GA 0.0004384f +#define LIS3MDL_COMP_SENS_16GA 0.00058445f + +#define LIS3MDL_COMP_BIAS 0.0f /** @} */ /** @@ -121,57 +125,57 @@ * @name LIS3MDL_CTRL_REG1 register bits definitions * @{ */ -#define LIS3MDL_CTRL_REG1_MASK 0xFF /**< LIS3MDL_CTRL_REG1 mask */ -#define LIS3MDL_CTRL_REG1_ST (1 << 0) /**< Self test enable */ -#define LIS3MDL_CTRL_REG1_FAST_ODR (1 << 1) /**< Fast data rate */ -#define LIS3MDL_CTRL_REG1_DO0 (1 << 2) /**< Output data rate bit 0 */ -#define LIS3MDL_CTRL_REG1_DO1 (1 << 3) /**< Output data rate bit 1 */ -#define LIS3MDL_CTRL_REG1_DO2 (1 << 4) /**< Output data rate bit 2 */ -#define LIS3MDL_CTRL_REG1_OM0 (1 << 5) /**< X-Y mode bit 0 */ -#define LIS3MDL_CTRL_REG1_OM1 (1 << 6) /**< X-Y mode bit 1 */ -#define LIS3MDL_CTRL_REG1_TEMP_EN (1 << 7) /**< Temperature sensor */ +#define LIS3MDL_CTRL_REG1_MASK 0xFF +#define LIS3MDL_CTRL_REG1_ST (1 << 0) +#define LIS3MDL_CTRL_REG1_FAST_ODR (1 << 1) +#define LIS3MDL_CTRL_REG1_DO0 (1 << 2) +#define LIS3MDL_CTRL_REG1_DO1 (1 << 3) +#define LIS3MDL_CTRL_REG1_DO2 (1 << 4) +#define LIS3MDL_CTRL_REG1_OM0 (1 << 5) +#define LIS3MDL_CTRL_REG1_OM1 (1 << 6) +#define LIS3MDL_CTRL_REG1_TEMP_EN (1 << 7) /** @} */ /** * @name LIS3MDL_CTRL_REG2 register bits definitions * @{ */ -#define LIS3MDL_CTRL_REG2_MASK 0x6C /**< LIS3MDL_CTRL_REG2 mask */ -#define LIS3MDL_CTRL_REG2_SOFT_RST (1 << 2) /**< Soft reset */ -#define LIS3MDL_CTRL_REG2_REBOOT (1 << 3) /**< Reboot memory */ -#define LIS3MDL_CTRL_REG2_FS_MASK 0x60 /**< Full scale mask */ -#define LIS3MDL_CTRL_REG2_FS0 (1 << 5) /**< Full scale bit 0 */ -#define LIS3MDL_CTRL_REG2_FS1 (1 << 6) /**< Full scale bit 1 */ +#define LIS3MDL_CTRL_REG2_MASK 0x6C +#define LIS3MDL_CTRL_REG2_SOFT_RST (1 << 2) +#define LIS3MDL_CTRL_REG2_REBOOT (1 << 3) +#define LIS3MDL_CTRL_REG2_FS_MASK 0x60 +#define LIS3MDL_CTRL_REG2_FS0 (1 << 5) +#define LIS3MDL_CTRL_REG2_FS1 (1 << 6) /** @} */ /** * @name LIS3MDL_CTRL_REG3 register bits definitions * @{ */ -#define LIS3MDL_CTRL_REG3_MASK 0x27 /**< LIS3MDL_CTRL_REG3 mask */ -#define LIS3MDL_CTRL_REG3_MD0 (1 << 0) /**< Operating mode bit 0 */ -#define LIS3MDL_CTRL_REG3_MD1 (1 << 1) /**< Operating mode bit 1 */ -#define LIS3MDL_CTRL_REG3_SIM (1 << 2) /**< SPI interface mode */ -#define LIS3MDL_CTRL_REG3_LP (1 << 5) /**< Low power */ +#define LIS3MDL_CTRL_REG3_MASK 0x27 +#define LIS3MDL_CTRL_REG3_MD0 (1 << 0) +#define LIS3MDL_CTRL_REG3_MD1 (1 << 1) +#define LIS3MDL_CTRL_REG3_SIM (1 << 2) +#define LIS3MDL_CTRL_REG3_LP (1 << 5) /** @} */ /** * @name LIS3MDL_CTRL_REG4 register bits definitions * @{ */ -#define LIS3MDL_CTRL_REG4_MASK 0x0E /**< LIS3MDL_CTRL_REG4 mask */ -#define LIS3MDL_CTRL_REG4_BLE (1 << 1) /**< Endianess */ -#define LIS3MDL_CTRL_REG4_OMZ0 (1 << 2) /**< Z mode bit 0 */ -#define LIS3MDL_CTRL_REG4_OMZ1 (1 << 3) /**< Z mode bit 1 */ +#define LIS3MDL_CTRL_REG4_MASK 0x0E +#define LIS3MDL_CTRL_REG4_BLE (1 << 1) +#define LIS3MDL_CTRL_REG4_OMZ0 (1 << 2) +#define LIS3MDL_CTRL_REG4_OMZ1 (1 << 3) /** @} */ /** * @name LIS3MDL_CTRL_REG5 register bits definitions * @{ */ -#define LIS3MDL_CTRL_REG5_MASK 0xC0 /**< LIS3MDL_CTRL_REG5 mask */ -#define LIS3MDL_CTRL_REG5_BDU (1 << 6) /**< Block data update */ -#define LIS3MDL_CTRL_REG5_FAST_READ (1 << 7) /**< Fast read mode */ +#define LIS3MDL_CTRL_REG5_MASK 0xC0 +#define LIS3MDL_CTRL_REG5_BDU (1 << 6) +#define LIS3MDL_CTRL_REG5_FAST_READ (1 << 7) /** @} */ /*===========================================================================*/ @@ -191,6 +195,16 @@ #define LIS3MDL_USE_SPI FALSE #endif +/** + * @brief LIS3MDL shared SPI switch. + * @details If set to @p TRUE the device acquires SPI bus ownership + * on each transaction. + * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION. + */ +#if !defined(LIS3MDL_SHARED_SPI) || defined(__DOXYGEN__) +#define LIS3MDL_SHARED_SPI FALSE +#endif + /** * @brief LIS3MDL I2C interface switch. * @details If set to @p TRUE the support for I2C is included. @@ -200,15 +214,6 @@ #define LIS3MDL_USE_I2C TRUE #endif -/** - * @brief LIS3MDL advanced configurations switch. - * @details If set to @p TRUE more configurations are available. - * @note The default is @p FALSE. - */ -#if !defined(LIS3MDL_USE_ADVANCED) || defined(__DOXYGEN__) -#define LIS3MDL_USE_ADVANCED FALSE -#endif - /** * @brief LIS3MDL shared I2C switch. * @details If set to @p TRUE the device acquires I2C bus ownership @@ -218,6 +223,15 @@ #if !defined(LIS3MDL_SHARED_I2C) || defined(__DOXYGEN__) #define LIS3MDL_SHARED_I2C FALSE #endif + +/** + * @brief LIS3MDL advanced configurations switch. + * @details If set to @p TRUE more configurations are available. + * @note The default is @p FALSE. + */ +#if !defined(LIS3MDL_COMP_USE_ADVANCED) || defined(__DOXYGEN__) +#define LIS3MDL_COMP_USE_ADVANCED FALSE +#endif /** @} */ /*===========================================================================*/ @@ -232,6 +246,10 @@ #error "LIS3MDL_USE_SPI requires HAL_USE_SPI" #endif +#if LIS3MDL_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION +#error "LIS3MDL_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION" +#endif + #if LIS3MDL_USE_I2C && !HAL_USE_I2C #error "LIS3MDL_USE_I2C requires HAL_USE_I2C" #endif @@ -240,6 +258,13 @@ #error "LIS3MDL_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION" #endif +/** + * @todo Add support for LIS3MDL over SPI. + */ +#if LIS3MDL_USE_SPI +#error "LIS3MDL over SPI still not supported" +#endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -252,6 +277,11 @@ /** * @brief LIS3MDL slave address */ +/** + * @brief Structure representing a LIS3MDL driver. + */ +typedef struct LIS3MDLDriver LIS3MDLDriver; + typedef enum { LIS3MDL_SAD_GND = 0x1C, /**< Slave Address when SA1 is to GND */ LIS3MDL_SAD_VCC = 0x1E /**< Slave Address when SA1 is to VCC */ @@ -261,62 +291,62 @@ typedef enum { * @brief LIS3MDL full scale */ typedef enum { - LIS3MDL_FS_4GA = 0x00, /**< ±4 Gauss */ - LIS3MDL_FS_8GA = 0x20, /**< ±8 Gauss */ - LIS3MDL_FS_12GA = 0x40, /**< ±12 Gauss */ - LIS3MDL_FS_16GA = 0x60 /**< ±16 Gauss */ -}lis3mdl_fs_t; + LIS3MDL_COMP_FS_4GA = 0x00, /**< ±4 Gauss */ + LIS3MDL_COMP_FS_8GA = 0x20, /**< ±8 Gauss */ + LIS3MDL_COMP_FS_12GA = 0x40, /**< ±12 Gauss */ + LIS3MDL_COMP_FS_16GA = 0x60 /**< ±16 Gauss */ +}lis3mdl_comp_fs_t; /** * @brief LIS3MDL output data rate */ typedef enum { - LIS3MDL_ODR_0_625HZ = 0x00, /**< Output Data Rate = 0.625 Hz */ - LIS3MDL_ODR_1_25HZ = 0x04, /**< Output Data Rate = 1.25 Hz */ - LIS3MDL_ODR_2_5HZ = 0x08, /**< Output Data Rate = 2.5 Hz */ - LIS3MDL_ODR_5HZ = 0x0C, /**< Output Data Rate = 5 Hz */ - LIS3MDL_ODR_10HZ = 0x10, /**< Output Data Rate = 10 Hz */ - LIS3MDL_ODR_20HZ = 0x14, /**< Output Data Rate = 20 Hz */ - LIS3MDL_ODR_40HZ = 0x18, /**< Output Data Rate = 40 Hz */ - LIS3MDL_ODR_80HZ = 0x1C /**< Output Data Rate = 80 Hz */ -}lis3mdl_odr_t; + LIS3MDL_COMP_ODR_0_625HZ = 0x00, /**< Output Data Rate = 0.625 Hz */ + LIS3MDL_COMP_ODR_1_25HZ = 0x04, /**< Output Data Rate = 1.25 Hz */ + LIS3MDL_COMP_ODR_2_5HZ = 0x08, /**< Output Data Rate = 2.5 Hz */ + LIS3MDL_COMP_ODR_5HZ = 0x0C, /**< Output Data Rate = 5 Hz */ + LIS3MDL_COMP_ODR_10HZ = 0x10, /**< Output Data Rate = 10 Hz */ + LIS3MDL_COMP_ODR_20HZ = 0x14, /**< Output Data Rate = 20 Hz */ + LIS3MDL_COMP_ODR_40HZ = 0x18, /**< Output Data Rate = 40 Hz */ + LIS3MDL_COMP_ODR_80HZ = 0x1C /**< Output Data Rate = 80 Hz */ +}lis3mdl_comp_odr_t; /** * @brief LIS3MDL low power mode configuration */ typedef enum { - LIS3MDL_LP_DISABLED = 0x00, /**< Low Power mode disabled */ - LIS3MDL_LP_ENABLED = 0x20 /**< Low Power mode enabled */ -}lis3mdl_lp_t; + LIS3MDL_COMP_LP_DISABLED = 0x00, /**< Low Power mode disabled */ + LIS3MDL_COMP_LP_ENABLED = 0x20 /**< Low Power mode enabled */ +}lis3mdl_comp_lp_t; /** * @brief LIS3MDL conversion mode */ typedef enum { - LIS3MDL_MD_CONTINUOUS = 0x00, /**< Continuous conversion mode */ - LIS3MDL_MD_SINGLE = 0x01, /**< Single conversion mode */ - LIS3MDL_MD_POWER_DOWN = 0x02 /**< Power down mode */ -}lis3mdl_md_t; + LIS3MDL_COMP_MD_CONTINUOUS = 0x00,/**< Continuous conversion mode */ + LIS3MDL_COMP_MD_SINGLE = 0x01, /**< Single conversion mode */ + LIS3MDL_COMP_MD_POWER_DOWN = 0x02 /**< Power down mode */ +}lis3mdl_comp_md_t; /** * @brief LIS3MDL operation mode for X and Y axes */ typedef enum { - LIS3MDL_OMXY_LOW_POWER = 0x00, /**< X-Y axes low power mode */ - LIS3MDL_OMXY_MEDIUM = 0x20, /**< X-Y axes medium performance mode */ - LIS3MDL_OMXY_HIGH = 0x40, /**< X-Y axes high performance mode */ - LIS3MDL_OMXY_ULTRA = 0x60 /**< X-Y axes ultra performance mode */ -}lis3mdl_omxy_t; + LIS3MDL_COMP_OMXY_LP = 0x00, /**< X-Y axes low power mode */ + LIS3MDL_COMP_OMXY_MEDIUM = 0x20, /**< X-Y axes medium performance mode */ + LIS3MDL_COMP_OMXY_HIGH = 0x40, /**< X-Y axes high performance mode */ + LIS3MDL_COMP_OMXY_ULTRA = 0x60 /**< X-Y axes ultra performance mode */ +}lis3mdl_comp_omxy_t; /** * @brief LIS3MDL operation mode for Z axis */ typedef enum { - LIS3MDL_OMZ_LOW_POWER = 0x00, /**< Z axis low power mode */ - LIS3MDL_OMZ_MEDIUM = 0x04, /**< Z axis medium performance mode */ - LIS3MDL_OMZ_HIGH = 0x08, /**< Z axis high performance mode */ - LIS3MDL_OMZ_ULTRA = 0x0C /**< Z axis ultra performance mode */ -}lis3mdl_omz_t; + LIS3MDL_COMP_OMZ_LP = 0x00, /**< Z axis low power mode */ + LIS3MDL_COMP_OMZ_MEDIUM = 0x04, /**< Z axis medium performance mode */ + LIS3MDL_COMP_OMZ_HIGH = 0x08, /**< Z axis high performance mode */ + LIS3MDL_COMP_OMZ_ULTRA = 0x0C /**< Z axis ultra performance mode */ +}lis3mdl_comp_omz_t; /** * @brief LIS3MDL temperature sensor enabling @@ -374,76 +404,76 @@ typedef struct { * @brief I2C configuration associated to this LIS3MDL. */ const I2CConfig *i2ccfg; -#endif /* LIS3MDL_USE_I2C */ /** - * @brief LIS3MDL initial sensitivity. + * @brief LIS3MDL slave address */ - float *sensitivity; + lis3mdl_sad_t slaveaddress; +#endif /* LIS3MDL_USE_I2C */ /** - * @brief LIS3MDL initial bias. + * @brief LIS3MDL compass subsystem initial sensitivity. */ - float *bias; + float *compsensitivity; /** - * @brief LIS3MDL slave address + * @brief LIS3MDL compass subsystem initial bias. */ - lis3mdl_sad_t slaveaddress; + float *compbias; /** - * @brief LIS3MDL full scale + * @brief LIS3MDL compass subsystem full scale. */ - lis3mdl_fs_t fullscale; + lis3mdl_comp_fs_t compfullscale; /** - * @brief LIS3MDL output data rate + * @brief LIS3MDL compass subsystem output data rate. */ - lis3mdl_odr_t outputdatarate; -#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__) + lis3mdl_comp_odr_t compoutputdatarate; +#if LIS3MDL_COMP_USE_ADVANCED || defined(__DOXYGEN__) /** - * @brief LIS3MDL low power mode configuration + * @brief LIS3MDL compass subsystem low power mode configuration. */ - lis3mdl_lp_t lowpowermode; + lis3mdl_comp_lp_t complowpowermode; /** - * @brief LIS3MDL conversion mode + * @brief LIS3MDL compass subsystem conversion mode. */ - lis3mdl_md_t conversionmode; + lis3mdl_comp_md_t compconversionmode; /** - * @brief LIS3MDL operation mode for X and Y axes + * @brief LIS3MDL compass subsystem operation mode for X and Y axes. */ - lis3mdl_omxy_t operationmodexy; + lis3mdl_comp_omxy_t compoperationmodexy; /** - * @brief LIS3MDL operation mode for Z axis + * @brief LIS3MDL compass subsystem operation mode for Z axis. */ - lis3mdl_omz_t operationmodez; + lis3mdl_comp_omz_t compoperationmodez; /** - * @brief LIS3MDL block data update + * @brief LIS3MDL block data update. */ lis3mdl_bdu_t blockdataupdate; /** - * @brief LIS3MDL endianness + * @brief LIS3MDL endianness. */ lis3mdl_end_t endianness; #endif } LIS3MDLConfig; /** - * @brief @p LIS3MDL compass subsystem specific methods. + * @brief @p LIS3MDL specific methods. */ -#define _lis3msl_compass_methods_alone \ - /* Change full scale value of LIS3MDL.*/ \ - msg_t (*set_full_scale)(void *instance, lis3mdl_fs_t fs); +#define _lis3msl_methods_alone \ + /* Change full scale value of LIS3MDL compass subsystem.*/ \ + msg_t (*comp_set_full_scale)(LIS3MDLDriver *devp, lis3mdl_comp_fs_t fs); /** - * @brief @p LIS3MDL compass subsystem specific methods with inherited ones. + * @brief @p LIS3MDL specific methods with inherited ones. */ -#define _lis3mdl_compass_methods \ - _base_compass_methods \ - _lis3msl_compass_methods_alone +#define _lis3mdl_methods \ + _base_object_methods \ + _lis3msl_methods_alone /** * @extends BaseCompassVMT * - * @brief @p LIS3MDL compass virtual methods table. + * @brief @p LIS3MDL virtual methods table. */ -struct LIS3MDLCompassVMT { - _lis3mdl_compass_methods +struct LIS3MDLVMT { + _lis3mdl_methods }; /** @@ -455,34 +485,25 @@ struct LIS3MDLCompassVMT { lis3mdl_state_t state; \ /* Current configuration data.*/ \ const LIS3MDLConfig *config; \ - /* Current sensitivity.*/ \ - float sensitivity[LIS3MDL_NUMBER_OF_AXES]; \ - /* Bias data.*/ \ - float bias[LIS3MDL_NUMBER_OF_AXES]; \ - /* Current full scale value.*/ \ - float fullscale; + /* Compass subsystem axes number.*/ \ + size_t compaxes; \ + /* Compass subsystem current sensitivity.*/ \ + float compsensitivity[LIS3MDL_COMP_NUMBER_OF_AXES]; \ + /* Compass subsystem current bias.*/ \ + float compbias[LIS3MDL_COMP_NUMBER_OF_AXES]; \ + /* Compass subsystem current full scale value.*/ \ + float compfullscale; /** - * @extends BaseCompass - * - * @brief LIS3MDL 3-axis compass class. - * @details This class extends @p BaseCompass by adding physical - * driver implementation. + * @brief LIS3MDL 3-axis compass class. */ struct LIS3MDLDriver { - /** @brief BaseSensor Virtual Methods Table. */ - const struct BaseSensorVMT *vmt_sensor; - _base_sensor_data - /** @brief LIS3MDL Compass Virtual Methods Table. */ - const struct LIS3MDLCompassVMT *vmt_compass; -_base_compass_data + /** @brief Virtual Methods Table.*/ + const struct LIS3MDLVMT *vmt; + /** @brief Base compass interface.*/ + BaseCompass comp_if; _lis3mdl_data }; - -/** - * @brief Structure representing a LIS3MDL driver. - */ -typedef struct LIS3MDLDriver LIS3MDLDriver; /** @} */ /*===========================================================================*/ @@ -490,18 +511,141 @@ typedef struct LIS3MDLDriver LIS3MDLDriver; /*===========================================================================*/ /** - * @brief Change compass full scale value. + * @brief Return the number of axes of the BaseCompass. + * + * @param[in] devp pointer to @p LIS3MDLDriver. + * + * @return the number of axes. + * + * @api + */ +#define lis3mdlCompassGetAxesNumber(devp) \ + compassGetAxesNumber(&((devp)->comp_if)) + +/** + * @brief Retrieves raw data from the BaseCompass. + * @note This data is retrieved from MEMS register without any algebraical + * manipulation. + * @note The axes array must be at least the same size of the + * BaseCompass axes number. + * + * @param[in] ip pointer to @p BaseCompass interface. + * @param[out] axes a buffer which would be filled with raw data. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. + * + * @api + */ +#define lis3mdlCompassReadRaw(devp, axes) \ + compassReadRaw(&((devp)->comp_if), axes) + +/** + * @brief Retrieves cooked data from the BaseCompass. + * @note This data is manipulated according to the formula + * cooked = (raw * sensitivity) - bias. + * @note Final data is expressed as G. + * @note The axes array must be at least the same size of the + * BaseCompass axes number. + * + * @param[in] ip pointer to @p BaseCompass interface. + * @param[out] axes a buffer which would be filled with cooked data. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. + * + * @api + */ +#define lis3mdlCompassReadCooked(devp, axes) \ + compassReadCooked(&((devp)->comp_if), axes) + +/** + * @brief Set bias values for the BaseCompass. + * @note Bias must be expressed as G. + * @note The bias buffer must be at least the same size of the + * BaseCompass axes number. + * + * @param[in] ip pointer to @p BaseCompass interface. + * @param[in] bp a buffer which contains biases. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * + * @api + */ +#define lis3mdlCompassSetBias(devp, bp) \ + compassSetBias(&((devp)->comp_if), bp) + +/** + * @brief Reset bias values for the BaseCompass. + * @note Default biases value are obtained from device datasheet when + * available otherwise they are considered zero. + * + * @param[in] devp pointer to @p LIS3MDLDriver. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * + * @api + */ +#define lis3mdlCompassResetBias(devp) \ + compassResetBias(&((devp)->comp_if)) + +/** + * @brief Set sensitivity values for the BaseCompass. + * @note Sensitivity must be expressed as G/LSB. + * @note The sensitivity buffer must be at least the same size of the + * BaseCompass axes number. + * + * @param[in] devp pointer to @p LIS3MDLDriver. + * @param[in] sp a buffer which contains sensitivities. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * + * @api + */ +#define lis3mdlCompassSetSensitivity(devp, sp) \ + compassSetSensitivity(&((devp)->comp_if), sp) + +/** + * @brief Reset sensitivity values for the BaseCompass. + * @note Default sensitivities value are obtained from device datasheet. * - * @param[in] ip pointer to a @p LIS3MDLDriver class. - * @param[in] fs the new full scale value. + * @param[in] devp pointer to @p LIS3MDLDriver. * * @return The operation status. * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more errors occurred. + * @retval MSG_RESET otherwise. + * + * @api + */ +#define lis3mdlCompassResetSensitivity(devp) \ + compassResetSensitivity(&((devp)->comp_if)) + +/** + * @brief Changes the LIS3MDLDriver compass fullscale value. + * @note This function also rescale sensitivities and biases based on + * previous and next fullscale value. + * @note A recalibration is highly suggested after calling this function. + * + * @param[in] devp pointer to @p LIS3MDLDriver. + * @param[in] fs new fullscale value. + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET otherwise. + * * @api */ -#define compassSetFullScale(ip, fs) \ - (ip)->vmt_compass->set_full_scale(ip, fs) +#define lis3mdlCompassSetFullScale(devp, fs) \ + (devp)->vmt->comp_set_full_scale(devp, fs) /*===========================================================================*/ /* External declarations. */ diff --git a/testex/STM32/STM32F4xx/I2C-LIS3MLD/Makefile b/testex/STM32/STM32F4xx/I2C-LIS3MLD/Makefile index 227b708bd..16c7f7c57 100644 --- a/testex/STM32/STM32F4xx/I2C-LIS3MLD/Makefile +++ b/testex/STM32/STM32F4xx/I2C-LIS3MLD/Makefile @@ -87,6 +87,9 @@ PROJECT = ch # Imported source files and paths CHIBIOS = ../../../.. + +# Licensing files. +include $(CHIBIOS)/os/license/license.mk # Startup files. include $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk # HAL-OSAL files (optional). @@ -97,31 +100,23 @@ include $(CHIBIOS)/os/hal/osal/rt/osal.mk # RTOS files (optional). include $(CHIBIOS)/os/rt/rt.mk include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk -# Other files (optional). +# EX files (optional). include $(CHIBIOS)/os/ex/ST/lis3mdl.mk +# Other files (optional). include $(CHIBIOS)/os/hal/lib/streams/streams.mk -include $(CHIBIOS)/os/various/shell/shell.mk # Define linker script file here LDSCRIPT= $(STARTUPLD)/STM32F401xE.ld # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. -CSRC = $(STARTUPSRC) \ - $(KERNSRC) \ - $(PORTSRC) \ - $(OSALSRC) \ - $(HALSRC) \ - $(PLATFORMSRC) \ - $(BOARDSRC) \ - $(LIS3MDLSRC) \ - $(STREAMSSRC) \ - $(SHELLSRC) \ +CSRC = $(ALLCSRC) \ + $(TESTSRC) \ main.c # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. -CPPSRC = +CPPSRC = $(ALLCPPSRC) # C sources to be compiled in ARM mode regardless of the global setting. # NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler @@ -147,10 +142,11 @@ TCPPSRC = ASMSRC = ASMXSRC = $(STARTUPASM) $(PORTASM) $(OSALASM) -INCDIR = $(CHIBIOS)/os/license \ - $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ - $(HALINC) $(PLATFORMINC) $(BOARDINC) $(LIS3MDLINC) \ - $(STREAMSINC) $(SHELLINC) +# List ASM source files here +ASMSRC = $(ALLASMSRC) +ASMXSRC = $(ALLXASMSRC) + +INCDIR = $(ALLINC) $(TESTINC) # # Project, sources and paths @@ -200,8 +196,8 @@ CPPWARN = -Wall -Wextra -Wundef # # List all user C define here, like -D_DEBUG=1 -UDEFS = -DCHPRINTF_USE_FLOAT=1 -DSHELL_CMD_TEST_ENABLED=0 \ - -DLIS3MDL_USE_ADVANCED=0 -DLIS3MDL_SHARED_I2C=0 +UDEFS = -DCHPRINTF_USE_FLOAT=1 \ + -LIS3MDL_COMP_USE_ADVANCED=0 -DLIS3MDL_SHARED_I2C=0 # Define ASM defines here UADEFS = diff --git a/testex/STM32/STM32F4xx/I2C-LIS3MLD/debug/STM32F4xx-I2C-LIS3MDL (OpenOCD, Flash and Run).launch b/testex/STM32/STM32F4xx/I2C-LIS3MLD/debug/STM32F4xx-I2C-LIS3MDL (OpenOCD, Flash and Run).launch index b82cd6efd..44580bcc6 100644 --- a/testex/STM32/STM32F4xx/I2C-LIS3MLD/debug/STM32F4xx-I2C-LIS3MDL (OpenOCD, Flash and Run).launch +++ b/testex/STM32/STM32F4xx/I2C-LIS3MLD/debug/STM32F4xx-I2C-LIS3MDL (OpenOCD, Flash and Run).launch @@ -33,7 +33,7 @@ - + diff --git a/testex/STM32/STM32F4xx/I2C-LIS3MLD/main.c b/testex/STM32/STM32F4xx/I2C-LIS3MLD/main.c index 922003997..a80a8b0a5 100644 --- a/testex/STM32/STM32F4xx/I2C-LIS3MLD/main.c +++ b/testex/STM32/STM32F4xx/I2C-LIS3MLD/main.c @@ -16,12 +16,11 @@ #include "ch.h" #include "hal.h" -#include "string.h" -#include "shell.h" #include "chprintf.h" - #include "lis3mdl.h" +#define cls(chp) chprintf(chp, "\033[2J\033[1;1H") + /*===========================================================================*/ /* LIS3MDL related. */ /*===========================================================================*/ @@ -29,10 +28,11 @@ /* LIS3MDL Driver: This object represent an LIS3MDL instance.*/ static LIS3MDLDriver LIS3MDLD1; -static int32_t rawdata[LIS3MDL_NUMBER_OF_AXES]; -static float cookeddata[LIS3MDL_NUMBER_OF_AXES]; +static int32_t compraw[LIS3MDL_COMP_NUMBER_OF_AXES]; + +static float compcooked[LIS3MDL_COMP_NUMBER_OF_AXES]; -static char axisID[LIS3MDL_NUMBER_OF_AXES] = {'X', 'Y', 'Z'}; +static char axisID[LIS3MDL_COMP_NUMBER_OF_AXES] = {'X', 'Y', 'Z'}; static uint32_t i; static const I2CConfig i2ccfg = { @@ -41,114 +41,29 @@ static const I2CConfig i2ccfg = { FAST_DUTY_CYCLE_2, }; -static LIS3MDLConfig LIS3MDLcfg = { +static LIS3MDLConfig lis3mdlcfg = { &I2CD1, &i2ccfg, + LIS3MDL_SAD_VCC, NULL, NULL, - LIS3MDL_SAD_VCC, - LIS3MDL_FS_4GA, - LIS3MDL_ODR_40HZ, -#if LIS3MDL_USE_ADVANCED - LIS3MDL_LP_ENABLED, - LIS3MDL_MD_CONTINUOUS, - LIS3MDL_OMXY_LOW_POWER, - LIS3MDL_OMZ_LOW_POWER, + LIS3MDL_COMP_FS_4GA, + LIS3MDL_COMP_ODR_40HZ, +#if LIS3MDL_COMP_USE_ADVANCED + LIS3MDL_COMP_LP_ENABLED, + LIS3MDL_COMP_MD_CONTINUOUS, + LIS3MDL_COMP_OMXY_LP, + LIS3MDL_COMP_OMZ_LP, LIS3MDL_BDU_CONTINUOUS, LIS3MDL_END_LITTLE #endif }; /*===========================================================================*/ -/* Command line related. */ -/*===========================================================================*/ - -/* Enable use of special ANSI escape sequences.*/ -#define CHPRINTF_USE_ANSI_CODE TRUE -#define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(2048) - -static void cmd_read(BaseSequentialStream *chp, int argc, char *argv[]) { - (void)argv; - if (argc != 1) { - chprintf(chp, "Usage: read [raw|cooked]\r\n"); - return; - } - - while (chnGetTimeout((BaseChannel *)chp, 150) == Q_TIMEOUT) { - if (!strcmp (argv[0], "raw")) { -#if CHPRINTF_USE_ANSI_CODE - chprintf(chp, "\033[2J\033[1;1H"); -#endif - compassReadRaw(&LIS3MDLD1, rawdata); - chprintf(chp, "LIS3MDL compass raw data...\r\n"); - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) { - chprintf(chp, "%c-axis: %d\r\n", axisID[i], rawdata[i]); - } - } - else if (!strcmp (argv[0], "cooked")) { -#if CHPRINTF_USE_ANSI_CODE - chprintf(chp, "\033[2J\033[1;1H"); -#endif - compassReadCooked(&LIS3MDLD1, cookeddata); - chprintf(chp, "LIS3MDL compass cooked data...\r\n"); - for(i = 0; i < LIS3MDL_NUMBER_OF_AXES; i++) { - chprintf(chp, "%c-axis: %.3f Gauss\r\n", axisID[i], cookeddata[i]); - } - } - else { - chprintf(chp, "Usage: read [raw|cooked]\r\n"); - return; - } - } - chprintf(chp, "Stopped\r\n"); -} - -static void cmd_fullscale(BaseSequentialStream *chp, int argc, char *argv[]) { - (void)argv; - if (argc != 1) { - chprintf(chp, "Usage: fullscale [4|8|12|16]\r\n"); - return; - } -#if CHPRINTF_USE_ANSI_CODE - chprintf(chp, "\033[2J\033[1;1H"); -#endif - if(!strcmp (argv[0], "4")) { - compassSetFullScale(&LIS3MDLD1, LIS3MDL_FS_4GA); - chprintf(chp, "LIS3MDL compass full scale set to 4 Gauss...\r\n"); - } - else if(!strcmp (argv[0], "8")) { - compassSetFullScale(&LIS3MDLD1, LIS3MDL_FS_8GA); - chprintf(chp, "LIS3MDL compass full scale set to 8 Gauss...\r\n"); - } - else if(!strcmp (argv[0], "12")) { - compassSetFullScale(&LIS3MDLD1, LIS3MDL_FS_12GA); - chprintf(chp, "LIS3MDL compass full scale set to 12 Gauss...\r\n"); - } - else if(!strcmp (argv[0], "16")) { - compassSetFullScale(&LIS3MDLD1, LIS3MDL_FS_16GA); - chprintf(chp, "LIS3MDL compass full scale set to 16 Gauss...\r\n"); - } - else { - chprintf(chp, "Usage: fullscale [4|8|12|16]\r\n"); - return; - } -} - -static const ShellCommand commands[] = { - {"read", cmd_read}, - {"fullscale", cmd_fullscale}, - {NULL, NULL} -}; - -static const ShellConfig shell_cfg1 = { - (BaseSequentialStream *)&SD2, - commands -}; - -/*===========================================================================*/ -/* Main code. */ +/* Generic code. */ /*===========================================================================*/ +static BaseSequentialStream* chp = (BaseSequentialStream*)&SD2; /* * LED blinker thread, times are in milliseconds. */ @@ -158,10 +73,8 @@ static THD_FUNCTION(Thread1, arg) { (void)arg; chRegSetThreadName("blinker"); while (true) { - palClearLine(LINE_LED_GREEN); - chThdSleepMilliseconds(250); - palSetLine(LINE_LED_GREEN); - chThdSleepMilliseconds(250); + palToggleLine(LINE_LED_GREEN); + chThdSleepMilliseconds(500); } } @@ -180,35 +93,39 @@ int main(void) { halInit(); chSysInit(); + /* Configuring I2C SCK and I2C SDA related GPIOs .*/ palSetLineMode(LINE_ARD_D15, PAL_MODE_ALTERNATE(4) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_OTYPE_OPENDRAIN); palSetLineMode(LINE_ARD_D14, PAL_MODE_ALTERNATE(4) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_OTYPE_OPENDRAIN); - /* - * Activates the serial driver 2 using the driver default configuration. - */ + /* Activates the serial driver 1 using the driver default configuration.*/ sdStart(&SD2, NULL); - /* Creates the blinker thread.*/ - chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 1, Thread1, NULL); + chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); /* LIS3MDL Object Initialization.*/ lis3mdlObjectInit(&LIS3MDLD1); /* Activates the LIS3MDL driver.*/ - lis3mdlStart(&LIS3MDLD1, &LIS3MDLcfg); + lis3mdlStart(&LIS3MDLD1, &lis3mdlcfg); - /* Shell manager initialization.*/ - shellInit(); + /* Normal main() thread activity, printing MEMS data on the SD2. */ + while (true) { + lis3mdlCompassReadRaw(&LIS3MDLD1, compraw); + chprintf(chp, "LIS3MDL Compass raw data...\r\n"); + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) { + chprintf(chp, "%c-axis: %d\r\n", axisID[i], compraw[i]); + } - while(TRUE) { - thread_t *shelltp = chThdCreateFromHeap(NULL, SHELL_WA_SIZE, - "shell", NORMALPRIO + 1, - shellThread, (void *)&shell_cfg1); - chThdWait(shelltp); /* Waiting termination. */ + lis3mdlCompassReadCooked(&LIS3MDLD1, compcooked); + chprintf(chp, "LIS3MDL Compass cooked data...\r\n"); + for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) { + chprintf(chp, "%c-axis: %.3f\r\n", axisID[i], compcooked[i]); + } + chThdSleepMilliseconds(100); + cls(chp); } lis3mdlStop(&LIS3MDLD1); - return 0; } diff --git a/testex/STM32/STM32F4xx/I2C-LPS25H/readme.txt b/testex/STM32/STM32F4xx/I2C-LPS25H/readme.txt index 0bbfd4932..a7342717a 100644 --- a/testex/STM32/STM32F4xx/I2C-LPS25H/readme.txt +++ b/testex/STM32/STM32F4xx/I2C-LPS25H/readme.txt @@ -1,5 +1,5 @@ ***************************************************************************** -** ChibiOS/HAL + ChibiOS/EX - I2C + LPS25H demo for STM32L4xx. ** +** ChibiOS/HAL + ChibiOS/EX - I2C + LPS25H demo for STM32F4xx. ** ***************************************************************************** ** TARGET ** -- cgit v1.2.3