Files
zTC1/mico-os/libraries/drivers/sensor/BMA2x2/bma2x2_user.c
2025-03-11 15:54:45 +08:00

570 lines
22 KiB
C

/**
******************************************************************************
* @file bma2x2_user.c
* @author William Xu
* @version V1.0.0
* @date 21-May-2015
* @brief bma2x2 sensor control demo.
******************************************************************************
* UNPUBLISHED PROPRIETARY SOURCE CODE
* Copyright (c) 2016 MXCHIP Inc.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of MXCHIP Corporation.
******************************************************************************
*/
/*---------------------------------------------------------------------------*/
/* Includes*/
/*---------------------------------------------------------------------------*/
#include "bma2x2.h"
#include "bma2x2_user.h"
#define bma2x2_user_log(M, ...) custom_log("BMA2x2_USER", M, ##__VA_ARGS__)
#define bma2x2_user_log_trace() custom_log_trace("BMA2x2_USER")
#define BMA2x2_API
/* I2C device */
mico_i2c_device_t bma2x2_i2c_device = {
BMA2x2_I2C_DEVICE, BMA2x2_I2C_ADDR1, I2C_ADDRESS_WIDTH_7BIT, I2C_STANDARD_SPEED_MODE
};
/*----------------------------------------------------------------------------*
* The following functions are used for reading and writing of
* sensor data using I2C or SPI communication
*----------------------------------------------------------------------------*/
#ifdef BMA2x2_API
/* \Brief: The function is used as I2C bus read
* \Return : Status of the I2C read
* \param dev_addr : The device address of the sensor
* \param reg_addr : Address of the first register, will data is going to be read
* \param reg_data : This data read from the sensor, which is hold in an array
* \param cnt : The no of byte of data to be read
*/
s8 BMA2x2_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
/* \Brief: The function is used as I2C bus write
* \Return : Status of the I2C write
* \param dev_addr : The device address of the sensor
* \param reg_addr : Address of the first register, will data is going to be written
* \param reg_data : It is a value hold in the array,
* will be used for write the value into the register
* \param cnt : The no of byte of data to be write
*/
s8 BMA2x2_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
/* \Brief: The function is used as SPI bus write
* \Return : Status of the SPI write
* \param dev_addr : The device address of the sensor
* \param reg_addr : Address of the first register, will data is going to be written
* \param reg_data : It is a value hold in the array,
* will be used for write the value into the register
* \param cnt : The no of byte of data to be write
*/
s8 BMA2x2_SPI_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
/* \Brief: The function is used as SPI bus read
* \Return : Status of the SPI read
* \param dev_addr : The device address of the sensor
* \param reg_addr : Address of the first register, will data is going to be read
* \param reg_data : This data read from the sensor, which is hold in an array
* \param cnt : The no of byte of data to be read */
s8 BMA2x2_SPI_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
/*
* \Brief: SPI/I2C init routine
*/
s8 BMA2x2_I2C_routine(void);
s8 BMA2x2_SPI_routine(void);
#endif
/********************End of I2C/SPI function declarations***********************/
/* Brief : The delay routine
* \param : delay in ms
*/
void BMA2x2_delay_msek(u32 msek);
/*!
* @brief This function is an example for delay
* @param : None
* @return : communication result
*/
s32 bma2x2_data_readout_template(void);
/*----------------------------------------------------------------------------*
* struct bma2x2_t parameters can be accessed by using bma2x2
* bma2x2_t having the following parameters
* Bus write function pointer: BMA2x2_WR_FUNC_PTR
* Bus read function pointer: BMA2x2_RD_FUNC_PTR
* Burst read function pointer: BMA2x2_BRD_FUNC_PTR
* Delay function pointer: delay_msec
* I2C address: dev_addr
* Chip id of the sensor: chip_id
*---------------------------------------------------------------------------*/
struct bma2x2_t bma2x2;
/*----------------------------------------------------------------------------*
* V_BMA2x2RESOLUTION_u8R used for selecting the accelerometer resolution
* 12 bit
* 14 bit
* 10 bit
*----------------------------------------------------------------------------*/
extern u8 V_BMA2x2RESOLUTION_u8R;
/* This function is an example for reading sensor data
* \param: None
* \return: communication result
*/
s32 bma2x2_data_readout_template(void)
{
/*Local variables for reading accel x, y and z data*/
s16 v_accel_x_s16, v_accel_y_s16, v_accel_z_s16 = 0;
/* bma2x2acc_data structure used to read accel xyz data*/
struct bma2x2_accel_data sample_xyz;
/* bma2x2acc_data_temp structure used to read accel xyz and temperature data*/
struct bma2x2_accel_data_temp sample_xyzt;
/* Local variable used to assign the bandwidth value*/
u8 v_bw_value_u8 = 0;
/* Local variable used to set the bandwidth value*/
u8 banwid = 0;
/* status of communication*/
s32 com_rslt = 0;
/*********************** START INITIALIZATION ************************
* Based on the user need configure I2C or SPI interface.
* It is example code to explain how to use the bma2x2 API*/
#ifdef BMA2x2_API
BMA2x2_I2C_routine();
/*BMA2x2_SPI_routine(); */
#endif
/*--------------------------------------------------------------------------*
* This function used to assign the value/reference of
* the following parameters
* I2C address
* Bus Write
* Bus read
* Chip id
*-------------------------------------------------------------------------*/
com_rslt = bma2x2_init(&bma2x2);
/* For initialization it is required to set the mode of
* the sensor as "NORMAL"
* NORMAL mode is set from the register 0x11 and 0x12
* 0x11 -> bit 5,6,7 -> set value as 0
* 0x12 -> bit 5,6 -> set value as 0
* data acquisition/read/write is possible in this mode
* by using the below API able to set the power mode as NORMAL
* For the Normal/standby/Low power 2 mode Idle time of at least 2us(micro seconds)
* required for read/write operations*/
/* Set the power mode as NORMAL*/
com_rslt += bma2x2_set_power_mode(BMA2x2_MODE_NORMAL);
/* Note:
* For the Suspend/Low power1 mode Idle time of at least 450us(micro seconds)
* required for read/write operations*/
/************************* END INITIALIZATION *************************/
/*------------------------------------------------------------------------*
************************* START GET and SET FUNCTIONS DATA ****************
*---------------------------------------------------------------------------*/
/* This API used to Write the bandwidth of the sensor input
value have to be given
bandwidth is set from the register 0x10 bits from 1 to 4*/
v_bw_value_u8 = 0x08;/* set bandwidth of 7.81Hz*/
com_rslt += bma2x2_set_bw(v_bw_value_u8);
/* This API used to read back the written value of bandwidth*/
com_rslt += bma2x2_get_bw(&banwid);
/*-----------------------------------------------------------------*
************************* END GET and SET FUNCTIONS ****************
*-------------------------------------------------------------------*/
/*------------------------------------------------------------------*
************************* START READ SENSOR DATA(X,Y and Z axis) ********
*---------------------------------------------------------------------*/
com_rslt += bma2x2_read_accel_x(&v_accel_x_s16);/* Read the accel X data*/
com_rslt += bma2x2_read_accel_y(&v_accel_y_s16);/* Read the accel Y data*/
com_rslt += bma2x2_read_accel_z(&v_accel_z_s16);/* Read the accel Z data*/
/* accessing the bma2x2acc_data parameter by using sample_xyz*/
com_rslt += bma2x2_read_accel_xyz(&sample_xyz);/* Read the accel XYZ data*/
/* accessing the bma2x2acc_data_temp parameter by using sample_xyzt*/
com_rslt += bma2x2_read_accel_xyzt(&sample_xyzt);/* Read the accel XYZT data*/
/*--------------------------------------------------------------------*
************************* END READ SENSOR DATA(X,Y and Z axis) ************
*-------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*
************************* START DE-INITIALIZATION ***********************
*-------------------------------------------------------------------------*/
/* For de-initialization it is required to set the mode of
* the sensor as "DEEP SUSPEND"
* DEEP SUSPEND mode is set from the register 0x11
* 0x11 -> bit 5 -> set value as 1
* the device reaches the lowest power consumption only
* interface selection is kept alive
* No data acquisition is performed
* by using the below API able to set the power mode as DEEPSUSPEND*/
/* Set the power mode as DEEPSUSPEND*/
com_rslt += bma2x2_set_power_mode(BMA2x2_MODE_DEEP_SUSPEND);
/*---------------------------------------------------------------------*
************************* END DE-INITIALIZATION **********************
*---------------------------------------------------------------------*/
return com_rslt;
}
#ifdef BMA2x2_API
/*--------------------------------------------------------------------------*
* The following function is used to map the I2C bus read, write, delay and
* device address with global structure bma2x2_t
*-------------------------------------------------------------------------*/
s8 BMA2x2_I2C_routine(void) {
/*--------------------------------------------------------------------------*
* By using bma2x2 the following structure parameter can be accessed
* Bus write function pointer: BMA2x2_WR_FUNC_PTR
* Bus read function pointer: BMA2x2_RD_FUNC_PTR
* Delay function pointer: delay_msec
* I2C address: dev_addr
*--------------------------------------------------------------------------*/
bma2x2.bus_write = BMA2x2_I2C_bus_write;
bma2x2.bus_read = BMA2x2_I2C_bus_read;
bma2x2.delay_msec = BMA2x2_delay_msek;
bma2x2.dev_addr = BMA2x2_I2C_ADDR2;
return 0;
}
/*---------------------------------------------------------------------------*
* The following function is used to map the SPI bus read, write and delay
* with global structure bma2x2_t
// *--------------------------------------------------------------------------*/
//s8 BMA2x2_SPI_routine(void) {
///*--------------------------------------------------------------------------*
// * By using bma2x2 the following structure parameter can be accessed
// * Bus write function pointer: BMA2x2_WR_FUNC_PTR
// * Bus read function pointer: BMA2x2_RD_FUNC_PTR
// * Delay function pointer: delay_msec
// *--------------------------------------------------------------------------*/
// bma2x2.bus_write = BMA2x2_SPI_bus_write;
// bma2x2.bus_read = BMA2x2_SPI_bus_read;
// bma2x2.delay_msec =BMA2x2_delay_msek;
// return 0;
//}
/************** I2C/SPI buffer length ******/
#define I2C_BUFFER_LEN 8
#define SPI_BUFFER_LEN 5
/*-------------------------------------------------------------------*
* This is a sample code for read and write the data by using I2C/SPI
* Use either I2C or SPI based on your need
*
*-----------------------------------------------------------------------*/
/* For configuring the I2C it is required to switch ON
* SDI, SDO and CLk and also select the device address
* The following definition of I2C address is used for the following sensors
* BMA255
* BMA355
* BMA280
* BMA282
* BMA223
* BMA254
* BMA284
* BMA250E
* BMA222E
#define BMA2x2_I2C_ADDR1 0x18
#define BMA2x2_I2C_ADDR2 0x19
* The following definition of I2C address is used for the following sensors
* BMC150
* BMC056
* BMC156
#define BMA2x2_I2C_ADDR3 0x10
#define BMA2x2_I2C_ADDR4 0x11
*************************************************************************/
/* \Brief: The function is used as I2C bus write
* \Return : Status of the I2C write
* \param dev_addr : The device address of the sensor
* \param reg_addr : Address of the first register, will data is going to be written
* \param reg_data : It is a value hold in the array,
* will be used for write the value into the register
* \param cnt : The no of byte of data to be write
*/
s8 BMA2x2_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
{
mico_i2c_message_t bma2x2_i2c_msg = {NULL, NULL, 0, 0, 0, false};
s32 iError = 0;
u8 array[I2C_BUFFER_LEN];
u8 stringpos = 0;
array[0] = reg_addr;
for (stringpos = 0; stringpos < cnt; stringpos++) {
array[stringpos + 1] = *(reg_data + stringpos);
}
/*
* Please take the below function as your reference for
* write the data using I2C communication
* "IERROR = I2C_WRITE_STRING(DEV_ADDR, ARRAY, CNT+1)"
* add your I2C write function here
* iError is an return value of I2C read function
* Please select your valid return value
* In the driver SUCCESS defined as 0
* and FAILURE defined as -1
* Note :
* This is a full duplex operation,
* The first read data is discarded, for that extra write operation
* have to be initiated. For that cnt+1 operation done in the I2C write string function
* For more information please refer data sheet SPI communication:
*/
iError = MicoI2cBuildTxMessage(&bma2x2_i2c_msg, array, cnt + 1, 3);
iError = MicoI2cTransfer(&bma2x2_i2c_device, &bma2x2_i2c_msg, 1);
if(0 != iError){
iError = -1;
}
return (s8)iError;
}
/* \Brief: The function is used as I2C bus read
* \Return : Status of the I2C read
* \param dev_addr : The device address of the sensor
* \param reg_addr : Address of the first register, will data is going to be read
* \param reg_data : This data read from the sensor, which is hold in an array
* \param cnt : The no of byte of data to be read
*/
s8 BMA2x2_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
{
mico_i2c_message_t bma2x2_i2c_msg = {NULL, NULL, 0, 0, 0, false};
s32 iError = 0;
u8 array[I2C_BUFFER_LEN] = {0};
// u8 stringpos = 0;
array[0] = reg_addr;
/* Please take the below function as your reference
* for read the data using I2C communication
* add your I2C rad function here.
* "IERROR = I2C_WRITE_READ_STRING(DEV_ADDR, ARRAY, ARRAY, 1, CNT)"
* iError is an return value of SPI write function
* Please select your valid return value
* In the driver SUCCESS defined as 0
* and FAILURE defined as -1
*/
iError = MicoI2cBuildCombinedMessage(&bma2x2_i2c_msg, array, reg_data, 1, cnt, 3);
if(0 != iError){
return (s8)iError;
}
iError = MicoI2cTransfer(&bma2x2_i2c_device, &bma2x2_i2c_msg, 1);
if(0 != iError){
return (s8)iError;
}
// for (stringpos = 0; stringpos < cnt; stringpos++) {
// *(reg_data + stringpos) = array[stringpos];
// }
return (s8)iError;
}
/* \Brief: The function is used as SPI bus read
* \Return : Status of the SPI read
* \param dev_addr : The device address of the sensor
* \param reg_addr : Address of the first register, will data is going to be read
* \param reg_data : This data read from the sensor, which is hold in an array
* \param cnt : The no of byte of data to be read */
s8 BMA2x2_SPI_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
{
s32 iError=0;
u8 array[SPI_BUFFER_LEN]={0xFF};
u8 stringpos;
/* For the SPI mode only 7 bits of register addresses are used.
The MSB of register address is declared the bit what functionality it is
read/write (read as 1/write as 0)*/
array[0] = reg_addr|0x80;/*read routine is initiated register address is mask with 0x80*/
/*
* Please take the below function as your reference for
* read the data using SPI communication
* " IERROR = SPI_READ_WRITE_STRING(ARRAY, ARRAY, CNT+1)"
* add your SPI read function here
* iError is an return value of SPI read function
* Please select your valid return value
* In the driver SUCCESS defined as 0
* and FAILURE defined as -1
* Note :
* This is a full duplex operation,
* The first read data is discarded, for that extra write operation
* have to be initiated. For that cnt+1 operation done in the SPI read
* and write string function
* For more information please refer data sheet SPI communication:
*/
for (stringpos = 0; stringpos < cnt; stringpos++) {
*(reg_data + stringpos) = array[stringpos+1];
}
return (s8)iError;
}
//
///* \Brief: The function is used as SPI bus write
// * \Return : Status of the SPI write
// * \param dev_addr : The device address of the sensor
// * \param reg_addr : Address of the first register, will data is going to be written
// * \param reg_data : It is a value hold in the array,
// * will be used for write the value into the register
// * \param cnt : The no of byte of data to be write
// */
//s8 BMA2x2_SPI_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
//{
// s32 iError = 0;
// u8 array[SPI_BUFFER_LEN * 2];
// u8 stringpos = 0;
// for (stringpos = 0; stringpos < cnt; stringpos++) {
// /* the operation of (reg_addr++)&0x7F done: because it ensure the
// 0 and 1 of the given value
// It is done only for 8bit operation*/
// array[stringpos * 2] = (reg_addr++) & 0x7F;
// array[stringpos * 2 + 1] = *(reg_data + stringpos);
// }
// /* Please take the below function as your reference
// * for write the data using SPI communication
// * add your SPI write function here.
// * "IERROR = SPI_WRITE_STRING(ARRAY, CNT*2)"
// * iError is an return value of SPI write function
// * Please select your valid return value
// * In the driver SUCCESS defined as 0
// * and FAILURE defined as -1
// */
// return (s8)iError;
//}
/* Brief : The delay routine
* \param : delay in ms
*/
void BMA2x2_delay_msek(u32 msek)
{
/*Here you can write your own delay routine*/
mico_thread_msleep(msek);
}
#endif
OSStatus bma2x2_sensor_init(void)
{
OSStatus err = kUnknownErr;
/* Local variable used to assign the bandwidth value*/
u8 v_bw_value_u8 = 0;
/* Local variable used to set the bandwidth value*/
u8 banwid = 0;
s32 com_rslt = BMA2x2_ERROR; // result of communication results
// u8 v_stand_by_time_u8 = BME280_INIT_VALUE; // The variable used to assign the standby time
// I2C init
MicoI2cFinalize(&bma2x2_i2c_device); // in case error
err = MicoI2cInitialize(&bma2x2_i2c_device);
require_noerr_action( err, exit, bma2x2_user_log("BMA2x2_ERROR: MicoI2cInitialize err = %d.", err) );
if( false == MicoI2cProbeDevice(&bma2x2_i2c_device, 5) ){
bma2x2_user_log("BMA2x2_ERROR: no i2c device found!");
err = kNotFoundErr;
goto exit;
}
// sensor init
/*********************** START INITIALIZATION ************************/
/* Based on the user need configure I2C or SPI interface.
* It is example code to explain how to use the bme280 API*/
#ifdef BMA2x2_API
BMA2x2_I2C_routine();
com_rslt = bma2x2_init(&bma2x2);
com_rslt += bma2x2_set_power_mode(BMA2x2_MODE_NORMAL);
/*------------------------------------------------------------------------*
************************* START GET and SET FUNCTIONS DATA ****************
*---------------------------------------------------------------------------*/
/* This API used to Write the bandwidth of the sensor input
value have to be given
bandwidth is set from the register 0x10 bits from 1 to 4*/
v_bw_value_u8 = 0x08;/* set bandwidth of 7.81Hz*/
com_rslt += bma2x2_set_bw(v_bw_value_u8);
/* This API used to read back the written value of bandwidth*/
com_rslt += bma2x2_get_bw(&banwid);
/*-----------------------------------------------------------------*
************************* END GET and SET FUNCTIONS ****************
*-------------------------------------------------------------------*/
if(com_rslt < 0){
bma2x2_user_log("BMA2x2_ERROR: bme280 sensor init failed!");
err = kNotInitializedErr;
goto exit;
}
/************************* END INITIALIZATION *************************/
#endif
return kNoErr;
exit:
return err;
}
OSStatus bma2x2_data_readout(s16 *v_accel_x_s16, s16 *v_accel_y_s16, s16 *v_accel_z_s16)
{
OSStatus err = kUnknownErr;
/* result of communication results*/
s32 com_rslt = BMA2x2_ERROR;
//-------------------------- NOTE ----------------------------------
// this is to avoid i2c pin is re-init by other module because they use the same pin.
MicoI2cInitialize(&bma2x2_i2c_device);
//------------------------------------------------------------------
/************ START READ TRUE PRESSURE, TEMPERATURE AND HUMIDITY DATA *********/
com_rslt = bma2x2_read_accel_x(v_accel_x_s16);/* Read the accel X data*/
com_rslt += bma2x2_read_accel_y(v_accel_y_s16);/* Read the accel Y data*/
com_rslt += bma2x2_read_accel_z(v_accel_z_s16);/* Read the accel Z data*/
/************ END READ TRUE PRESSURE, TEMPERATURE AND HUMIDITY ********/
if(0 == com_rslt){
err = kNoErr;
}
return err;
}
OSStatus bma2x2_sensor_deinit(void)
{
OSStatus err = kUnknownErr;
s32 com_rslt = BMA2x2_ERROR;
err = MicoI2cFinalize(&bma2x2_i2c_device);
require_noerr_action( err, exit, bma2x2_user_log("BMA2x2_ERROR: MicoI2cFinalize err = %d.", err));
/*-----------------------------------------------------------------------*
************************* START DE-INITIALIZATION ***********************
*-------------------------------------------------------------------------*/
/* For de-initialization it is required to set the mode of
* the sensor as "DEEP SUSPEND"
* DEEP SUSPEND mode is set from the register 0x11
* 0x11 -> bit 5 -> set value as 1
* the device reaches the lowest power consumption only
* interface selection is kept alive
* No data acquisition is performed
* by using the below API able to set the power mode as DEEPSUSPEND*/
/* Set the power mode as DEEPSUSPEND*/
com_rslt = bma2x2_set_power_mode(BMA2x2_MODE_DEEP_SUSPEND);
/*---------------------------------------------------------------------*
************************* END DE-INITIALIZATION **********************
*---------------------------------------------------------------------*/
if(0 == com_rslt){
err = kNoErr;
}
exit:
return err;
}