#include "app_config.h" #include "asm/clock.h" #include "asm/cpu.h" #include "generic/typedef.h" #include "generic/gpio.h" #include "typedef.h" #include "system/includes.h" #include "media/includes.h" #include "asm/iic_hw.h" #include "asm/iic_soft.h" #include "asm/timer.h" #include "imuSensor_manage.h" #include "qmi8658c.h" // #include "spi1.h" // #include "port_wkup.h" #if TCFG_QMI8658_ENABLE /*************Betterlife ic debug***********/ #undef LOG_TAG_CONST #define LOG_TAG "[QMI8658]" #define LOG_ERROR_ENABLE #define LOG_INFO_ENABLE #include "debug.h" void delay(volatile u32 t); void udelay(u32 us); #define MDELAY(n) mdelay(n) static qmi8658_param *qmi8658_info; // static qmi8658_data qmi8658_raw_data={0}; /****************************************************************** * Description: I2C or SPI bus interface functions and delay time function * * Parameters: * devAddr: I2C device address, modify the macro(QMI8658_ADDRESS @qmi8658.h) based on your I2C function. * If SPI interface, please ingnore the parameter. * regAddr: register address * readLen: data length to read * *readBuf: data buffer to read * writeLen: data length to write * *writeBuf: data buffer to write * ******************************************************************/ #if (QMI8658_USER_INTERFACE==QMI8658_USE_I2C) #if TCFG_QMI8658_USER_IIC_TYPE #define iic_init(iic) hw_iic_init(iic) #define iic_uninit(iic) hw_iic_uninit(iic) #define iic_start(iic) hw_iic_start(iic) #define iic_stop(iic) hw_iic_stop(iic) #define iic_tx_byte(iic, byte) hw_iic_tx_byte(iic, byte) #define iic_rx_byte(iic, ack) hw_iic_rx_byte(iic, ack) #define iic_read_buf(iic, buf, len) hw_iic_read_buf(iic, buf, len) #define iic_write_buf(iic, buf, len) hw_iic_write_buf(iic, buf, len) #define iic_suspend(iic) hw_iic_suspend(iic) #define iic_resume(iic) hw_iic_resume(iic) #else #define iic_init(iic) soft_iic_init(iic) #define iic_uninit(iic) soft_iic_uninit(iic) #define iic_start(iic) soft_iic_start(iic) #define iic_stop(iic) soft_iic_stop(iic) #define iic_tx_byte(iic, byte) soft_iic_tx_byte(iic, byte) #define iic_rx_byte(iic, ack) soft_iic_rx_byte(iic, ack) #define iic_read_buf(iic, buf, len) soft_iic_read_buf(iic, buf, len) #define iic_write_buf(iic, buf, len) soft_iic_write_buf(iic, buf, len) #define iic_suspend(iic) soft_iic_suspend(iic) #define iic_resume(iic) soft_iic_resume(iic) #endif //起止信号间隔:standard mode(100khz):4.7us; fast mode(400khz):1.3us //return: readLen:ok, other:fail u16 qmi8658_I2C_Read_NBytes(unsigned char devAddr, unsigned char regAddr, unsigned char *readBuf, u16 readLen) { u16 i = 0; local_irq_disable(); iic_start(qmi8658_info->iic_hdl); if (0 == iic_tx_byte(qmi8658_info->iic_hdl, devAddr)) { log_error("qmi8658 iic read err1"); goto __iic_exit_r; } delay(qmi8658_info->iic_delay); /* if (0 == iic_tx_byte(qmi8658_info->iic_hdl, regAddr |0x80)) {//|0x80地址自动递增 */ if (0 == iic_tx_byte(qmi8658_info->iic_hdl, regAddr)) {//|0x80地址自动递增 log_error("qmi8658 iic read err2"); goto __iic_exit_r; } delay(qmi8658_info->iic_delay); iic_start(qmi8658_info->iic_hdl); if (0 == iic_tx_byte(qmi8658_info->iic_hdl, devAddr + 1)) { log_error("qmi8658 iic read err3"); goto __iic_exit_r; } for (i = 0; i < readLen; i++) { delay(qmi8658_info->iic_delay); if (i == (readLen - 1)) { *readBuf++ = iic_rx_byte(qmi8658_info->iic_hdl, 0); } else { *readBuf++ = iic_rx_byte(qmi8658_info->iic_hdl, 1); } /* if(i%100==0)wdt_clear(); */ } __iic_exit_r: iic_stop(qmi8658_info->iic_hdl); local_irq_enable(); return i; } //起止信号间隔:standard mode(100khz):4.7us; fast mode(400khz):1.3us //return:1:ok, 0:fail unsigned char qmi8658_I2C_Write_Byte(unsigned char devAddr, //芯片支持1byte写 unsigned char regAddr, unsigned char byte) { u8 ret = 1; local_irq_disable(); iic_start(qmi8658_info->iic_hdl); if (0 == iic_tx_byte(qmi8658_info->iic_hdl, devAddr)) { log_error("qmi8658 iic write err1"); ret = 0; goto __iic_exit_w; } delay(qmi8658_info->iic_delay); if (0 == iic_tx_byte(qmi8658_info->iic_hdl, regAddr)) { log_error("qmi8658 iic write err2"); ret = 0; goto __iic_exit_w; } delay(qmi8658_info->iic_delay); if (0 == iic_tx_byte(qmi8658_info->iic_hdl, byte)) { log_error("qmi8658 iic write err3"); ret = 0; goto __iic_exit_w; } __iic_exit_w: iic_stop(qmi8658_info->iic_hdl); local_irq_enable(); return ret; } //起止信号间隔:standard mode(100khz):4.7us; fast mode(400khz):1.3us //return: readLen:ok, other:fail unsigned char qmi8658_I2C_Write_NBytes(unsigned char devAddr, //芯片支持1byte写 unsigned char regAddr, unsigned char *writeBuf, u16 writeLen) { u16 i; for (i = 0; i < writeLen; i++) { if (qmi8658_I2C_Write_Byte(devAddr, regAddr + i, writeBuf[i]) == 0) { log_error("qmi8658_I2C_Write_NBytes error N:%d", i); return i; } udelay(5);//delay5us } return i; } IMU_read Qmi8658_read = qmi8658_I2C_Read_NBytes; IMU_write Qmi8658_write = qmi8658_I2C_Write_Byte; #elif (QMI8658_USER_INTERFACE==QMI8658_USE_SPI) #define spi_cs_init() \ do { \ gpio_write(qmi8658_info->spi_cs_pin, 1); \ gpio_set_direction(qmi8658_info->spi_cs_pin, 0); \ gpio_set_die(qmi8658_info->spi_cs_pin, 1); \ } while (0) #define spi_cs_uninit() \ do { \ gpio_set_die(qmi8658_info->spi_cs_pin, 0); \ gpio_set_direction(qmi8658_info->spi_cs_pin, 1); \ gpio_set_pull_up(qmi8658_info->spi_cs_pin, 0); \ gpio_set_pull_down(qmi8658_info->spi_cs_pin, 0); \ } while (0) #define spi_cs_h() gpio_write(qmi8658_info->spi_cs_pin, 1) #define spi_cs_l() gpio_write(qmi8658_info->spi_cs_pin, 0) #define spi_read_byte() spi_recv_byte(qmi8658_info->spi_hdl, NULL) #define spi_write_byte(x) spi_send_byte(qmi8658_info->spi_hdl, x) #define spi_dma_read(x, y) spi_dma_recv(qmi8658_info->spi_hdl, x, y) #define spi_dma_write(x, y) spi_dma_send(qmi8658_info->spi_hdl, x, y) #define spi_set_width(x) spi_set_bit_mode(qmi8658_info->spi_hdl, x) #define spi_init() spi_open(qmi8658_info->spi_hdl) #define spi_closed() spi_close(qmi8658_info->spi_hdl) #define spi_suspend() hw_spi_suspend(qmi8658_info->spi_hdl) #define spi_resume() hw_spi_resume(qmi8658_info->spi_hdl) u16 qmi8658_SPI_readNBytes(unsigned char devAddr, unsigned char regAddr, unsigned char *readBuf, u16 readLen) { spi_cs_l(); spi_write_byte(regAddr | 0x80);//| 0x80:read mode spi_dma_read(readBuf, readLen); spi_cs_h(); //SPIRead((regAddr | 0x80), readBuf, readLen); return (readLen); } unsigned char qmi8658_SPI_writeByte(unsigned char devAddr, unsigned char regAddr, unsigned char writebyte) { spi_cs_l(); spi_write_byte((regAddr) & 0x7F); spi_write_byte(writebyte); spi_cs_h(); udelay(5);//delay5us return (1); } unsigned char qmi8658_SPI_writeNBytes(unsigned char devAddr, unsigned char regAddr, unsigned char *writeBuf, u16 writeLen) { #if 0 //多字节dma写 spi_cs_l(); spi_write_byte(regAddr & 0x7F); spi_dma_write(writeBuf, writeLen); spi_cs_h(); #else u16 i = 0; for (; i < writeLen; i++) { qmi8658_SPI_writeByte(devAddr, regAddr + i, writeBuf[i]); } #endif //SPIWrite((regAddr & 0x7F), writeBuf, writeLen); return (i); } IMU_read Qmi8658_read = qmi8658_SPI_readNBytes; IMU_write Qmi8658_write = qmi8658_SPI_writeByte; #else //I3C #endif void Qmi8658_delay(int ms) { //your delay code(mSecond: millisecond): MDELAY(ms); } static unsigned short acc_lsb_div = 0; static unsigned short gyro_lsb_div = 0; static unsigned short ae_q_lsb_div = (1 << 14); static unsigned short ae_v_lsb_div = (1 << 10); static unsigned int imu_timestamp = 0; static struct Qmi8658Config qmi8658_config; enum { AXIS_X = 0, AXIS_Y = 1, AXIS_Z = 2, AXIS_TOTAL }; #if 0 typedef struct { short sign[AXIS_TOTAL]; unsigned short map[AXIS_TOTAL]; } qst_imu_layout; static qst_imu_layout imu_map; void Qmi8658_set_layout(short layout) { if (layout == 0) { imu_map.sign[AXIS_X] = 1; imu_map.sign[AXIS_Y] = 1; imu_map.sign[AXIS_Z] = 1; imu_map.map[AXIS_X] = AXIS_X; imu_map.map[AXIS_Y] = AXIS_Y; imu_map.map[AXIS_Z] = AXIS_Z; } else if (layout == 1) { imu_map.sign[AXIS_X] = -1; imu_map.sign[AXIS_Y] = 1; imu_map.sign[AXIS_Z] = 1; imu_map.map[AXIS_X] = AXIS_Y; imu_map.map[AXIS_Y] = AXIS_X; imu_map.map[AXIS_Z] = AXIS_Z; } else if (layout == 2) { imu_map.sign[AXIS_X] = -1; imu_map.sign[AXIS_Y] = -1; imu_map.sign[AXIS_Z] = 1; imu_map.map[AXIS_X] = AXIS_X; imu_map.map[AXIS_Y] = AXIS_Y; imu_map.map[AXIS_Z] = AXIS_Z; } else if (layout == 3) { imu_map.sign[AXIS_X] = 1; imu_map.sign[AXIS_Y] = -1; imu_map.sign[AXIS_Z] = 1; imu_map.map[AXIS_X] = AXIS_Y; imu_map.map[AXIS_Y] = AXIS_X; imu_map.map[AXIS_Z] = AXIS_Z; } else if (layout == 4) { imu_map.sign[AXIS_X] = -1; imu_map.sign[AXIS_Y] = 1; imu_map.sign[AXIS_Z] = -1; imu_map.map[AXIS_X] = AXIS_X; imu_map.map[AXIS_Y] = AXIS_Y; imu_map.map[AXIS_Z] = AXIS_Z; } else if (layout == 5) { imu_map.sign[AXIS_X] = 1; imu_map.sign[AXIS_Y] = 1; imu_map.sign[AXIS_Z] = -1; imu_map.map[AXIS_X] = AXIS_Y; imu_map.map[AXIS_Y] = AXIS_X; imu_map.map[AXIS_Z] = AXIS_Z; } else if (layout == 6) { imu_map.sign[AXIS_X] = 1; imu_map.sign[AXIS_Y] = -1; imu_map.sign[AXIS_Z] = -1; imu_map.map[AXIS_X] = AXIS_X; imu_map.map[AXIS_Y] = AXIS_Y; imu_map.map[AXIS_Z] = AXIS_Z; } else if (layout == 7) { imu_map.sign[AXIS_X] = -1; imu_map.sign[AXIS_Y] = -1; imu_map.sign[AXIS_Z] = -1; imu_map.map[AXIS_X] = AXIS_Y; imu_map.map[AXIS_Y] = AXIS_X; imu_map.map[AXIS_Z] = AXIS_Z; } else { imu_map.sign[AXIS_X] = 1; imu_map.sign[AXIS_Y] = 1; imu_map.sign[AXIS_Z] = 1; imu_map.map[AXIS_X] = AXIS_X; imu_map.map[AXIS_Y] = AXIS_Y; imu_map.map[AXIS_Z] = AXIS_Z; } } #endif void Qmi8658_config_acc(enum Qmi8658_AccRange range, enum Qmi8658_AccOdr odr, enum Qmi8658_LpfConfig lpfEnable, enum Qmi8658_StConfig stEnable) { unsigned char ctl_dada; switch (range) { case Qmi8658AccRange_2g: acc_lsb_div = (1 << 14); break; case Qmi8658AccRange_4g: acc_lsb_div = (1 << 13); break; case Qmi8658AccRange_8g: acc_lsb_div = (1 << 12); break; case Qmi8658AccRange_16g: acc_lsb_div = (1 << 11); break; default: range = Qmi8658AccRange_8g; acc_lsb_div = (1 << 12); } if (stEnable == Qmi8658St_Enable) { ctl_dada = (unsigned char)range | (unsigned char)odr | 0x80; } else { ctl_dada = (unsigned char)range | (unsigned char)odr; } Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl2, ctl_dada); // set LPF & HPF Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl5, &ctl_dada, 1); ctl_dada &= 0xf0; if (lpfEnable == Qmi8658Lpf_Enable) { ctl_dada |= A_LSP_MODE_3; ctl_dada |= 0x01; } else { ctl_dada &= ~0x01; } /* ctl_dada = 0x00; */ Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl5, ctl_dada); // set LPF & HPF } void Qmi8658_config_gyro(enum Qmi8658_GyrRange range, enum Qmi8658_GyrOdr odr, enum Qmi8658_LpfConfig lpfEnable, enum Qmi8658_StConfig stEnable) { // Set the CTRL3 register to configure dynamic range and ODR unsigned char ctl_dada; // Store the scale factor for use when processing raw data switch (range) { case Qmi8658GyrRange_16dps: gyro_lsb_div = 2048; break; case Qmi8658GyrRange_32dps: gyro_lsb_div = 1024; break; case Qmi8658GyrRange_64dps: gyro_lsb_div = 512; break; case Qmi8658GyrRange_128dps: gyro_lsb_div = 256; break; case Qmi8658GyrRange_256dps: gyro_lsb_div = 128; break; case Qmi8658GyrRange_512dps: gyro_lsb_div = 64; break; case Qmi8658GyrRange_1024dps: gyro_lsb_div = 32; break; case Qmi8658GyrRange_2048dps: gyro_lsb_div = 16; break; // case Qmi8658GyrRange_4096dps: // gyro_lsb_div = 8; // break; default: range = Qmi8658GyrRange_512dps; gyro_lsb_div = 64; break; } if (stEnable == Qmi8658St_Enable) { ctl_dada = (unsigned char)range | (unsigned char)odr | 0x80; } else { ctl_dada = (unsigned char)range | (unsigned char)odr; } Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl3, ctl_dada); // Conversion from degrees/s to rad/s if necessary // set LPF & HPF Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl5, &ctl_dada, 1); ctl_dada &= 0x0f; if (lpfEnable == Qmi8658Lpf_Enable) { ctl_dada |= G_LSP_MODE_3; ctl_dada |= 0x10; } else { ctl_dada &= ~0x10; } /* ctl_dada = 0x00; */ Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl5, ctl_dada); // set LPF & HPF } void Qmi8658_config_mag(enum Qmi8658_MagDev device, enum Qmi8658_MagOdr odr) { Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl4, device | odr); } void Qmi8658_config_ae(enum Qmi8658_AeOdr odr) { //Qmi8658_config_acc(Qmi8658AccRange_8g, AccOdr_1000Hz, Lpf_Enable, St_Enable); //Qmi8658_config_gyro(Qmi8658GyrRange_2048dps, GyrOdr_1000Hz, Lpf_Enable, St_Enable); Qmi8658_config_acc(qmi8658_config.accRange, qmi8658_config.accOdr, Qmi8658Lpf_Enable, Qmi8658St_Disable); Qmi8658_config_gyro(qmi8658_config.gyrRange, qmi8658_config.gyrOdr, Qmi8658Lpf_Enable, Qmi8658St_Disable); Qmi8658_config_mag(qmi8658_config.magDev, qmi8658_config.magOdr); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl6, odr); } void Qmi8658_send_ctl9cmd(enum Qmi8658_Ctrl9Command cmd) //cmd=0x0d { unsigned char status1 = 0x00; unsigned short count = 0; //void* pi2c = qmi8658_i2c_init(); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl9, (unsigned char)cmd); // write commond to ctrl9 #if defined(QMI8658_HANDSHAKE_NEW) #if defined(QMI8658_HANDSHAKE_TO_STATUS) unsigned char status_reg = Qmi8658Register_StatusInt; unsigned char cmd_done = 0x80; #else unsigned char status_reg = Qmi8658Register_Status1;// Qmi8658Register_Status1 unsigned char cmd_done = 0x01; #endif //count = 0; Qmi8658_read(QMI8658_SLAVE_ADDRESS, status_reg, &status1, 1); /* log_info("status1=%x\n",status1); */ while (((status1 & cmd_done) != cmd_done) && (count++ < 200)) { // read statusINT until bit7 is 1 Qmi8658_delay(1); Qmi8658_read(QMI8658_SLAVE_ADDRESS, status_reg, &status1, 1); //log_info("first %d status_reg: 0x%x\n", count,status1); } /* log_info("Qmi8658_config_fifo ctrl9 done-1: %d\n", count); */ Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl9, Qmi8658_Ctrl9_Cmd_NOP); // write commond 0x00 to ctrl9 count = 0; Qmi8658_read(QMI8658_SLAVE_ADDRESS, status_reg, &status1, 1); while (((status1 & cmd_done) == cmd_done) && (count++ < 200)) { // read statusINT until bit7 is 0 Qmi8658_delay(1); /* log_info("second %d status_reg: 0x%x\n", count,status1); */ Qmi8658_read(QMI8658_SLAVE_ADDRESS, status_reg, &status1, 1); } /* log_info("ctrl9 done-2: %d\n", count); */ #else while (((status1 & QMI8658_STATUS1_CMD_DONE) == 0) && (count++ < 200)) { Qmi8658_delay(2); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Status1, &status1, sizeof(status1)); } //log_info("fifo rst done : %d\n", count); #endif //qmi8658_i2c_deinit(pi2c); } #if (QMI8658_USE_FIFO_EN) /* * if mode=Qmi8658_Fifo_Stream then watermark <= size 否则不会输出中断信息 * */ void Qmi8658_config_fifo(uint8_t watermark, enum Qmi8658_FifoSize size, enum Qmi8658_FifoMode mode, enum Qmi8658_fifo_format format) { /* Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, 0x00); */ Qmi8658_delay(1); #if (QMI8658_NEW_HANDSHAKE == 1) u8 temp_data; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, &temp_data, 1); #if (QMI8658_FIFO_INT_OMAP_INT1 == 1) temp_data |= BIT(2); // #else temp_data &= ~BIT(2); // #endif Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, temp_data); #endif qmi8658_config.fifo_format = format; //QMI8658_FORMAT_12_BYTES; qmi8658_config.fifo_ctrl = (uint8_t)size | (uint8_t)mode; Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_FifoCtrl, qmi8658_config.fifo_ctrl); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_FifoWmkTh, (unsigned char)watermark); Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_Rst_Fifo); /* if(format == QMI8658_FORMAT_ACCEL_6_BYTES) */ /* Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, 0x01); */ /* else if(format == QMI8658_FORMAT_GYRO_6_BYTES) */ /* Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, 0x02); */ /* else if(format == QMI8658_FORMAT_12_BYTES) */ /* Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, 0x03); */ } /* *sensor data formal: * 3 sensor:acc, gyro, mag * AX_L[0] AX_H[0] AY_L[0] AY_H[0] AZ_L[0] AZ_H[0] * GX_L[0] GX_H[0] GY_L[0] GY_H[0] GZ_L[0] GZ_H[0] * MX_L[0] MX_H[0] MY_L[0] MY_H[0] MZ_L[0] MZ_H[0] * AX_L[1] AX_H[1] ...... * 2 sensor:acc, gyro * AX_L[0] AX_H[0] AY_L[0] AY_H[0] AZ_L[0] AZ_H[0] * GX_L[0] GX_H[0] GY_L[0] GY_H[0] GZ_L[0] GZ_H[0] * AX_L[1] AX_H[1] ...... * 1 sensor:acc or gyro * AX_L[0] AX_H[0]] AY_L[0] AY_H[0] AZ_L [0] AZ_H[0] AX_L[1] ...... * */ unsigned short Qmi8658_read_fifo(unsigned char *data) { unsigned char fifo_status[2] = {0, 0}; unsigned short fifo_bytes = 0; unsigned short fifo_level = 0; //unsigned short i; Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_Req_Fifo); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_FifoCount, fifo_status, 2); fifo_bytes = (unsigned short)(((fifo_status[1] & 0x03) << 8) | fifo_status[0]); fifo_bytes *= 2; if ((qmi8658_config.fifo_format == QMI8658_FORMAT_ACCEL_6_BYTES) || (qmi8658_config.fifo_format == QMI8658_FORMAT_GYRO_6_BYTES) || (qmi8658_config.fifo_format == QMI8658_FORMAT_MAG_6_BYTES)) { fifo_level = fifo_bytes / 6; // one sensor fifo_bytes = fifo_level * 6; } else if (qmi8658_config.fifo_format == QMI8658_FORMAT_12_BYTES) { fifo_level = fifo_bytes / 12; // two sensor fifo_bytes = fifo_level * 12; } else if (qmi8658_config.fifo_format == QMI8658_FORMAT_18_BYTES) { fifo_level = fifo_bytes / 18; // three sensor fifo_bytes = fifo_level * 18; } /* log_info("fifo byte=%d level=%d\n", fifo_bytes, fifo_level); */ if (fifo_level > 0) { #if 0 for (i = 1; i < fifo_level; i++) { Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_FifoData, data + i * 12, 12); } #else Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_FifoData, data, fifo_bytes); #endif } Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_FifoCtrl, qmi8658_config.fifo_ctrl); return fifo_bytes; } void Qmi8658_get_fifo_format(enum Qmi8658_fifo_format *format) { if (format) { *format = qmi8658_config.fifo_format; } } #endif /* status0:46(0x2e) * BIT: 7:4 3 2 1 0 * reserved AE(new data) mag gyro acc */ unsigned char Qmi8658_readStatus0(void) { unsigned char status[2]; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Status0, status, sizeof(status)); log_info("status[0:0x%x 1:0x%x]", status[0], status[1]); return status[0]; } /*!status1:47(0x2f) * \brief Blocking read of data status register 1 (::Qmi8658Register_Status1). * bit7~bit1: reserved * bit0: Used to indicate ctrl9 Command was done. * \returns Status byte \see STATUS1 for flag definitions. */ unsigned char Qmi8658_readStatus1(void) { unsigned char status; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Status1, &status, sizeof(status)); /* log_info("status1[0x%x]\n",status); */ return status; } /* * Sample time stamp. Count incremented by one for each sample (x, y, z data set) from sensor with highest ODR (circular register 0x0-0xFFFFFF) */ unsigned char Qmi8658_read_time_stamp_reg(void) { unsigned char time_stamp[3]; u32 sample_time = 0; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Timestamp_L, time_stamp, sizeof(time_stamp)); sample_time = (u32)(time_stamp[2] << 16) | (u32)(time_stamp[1] << 8) | time_stamp[0]; /* log_info("Sample time stamp =[0x%x]\n",sample_time); */ return sample_time; } /************************0x59地址文档未介绍*****************************/ unsigned char Qmi8658_read_temptap_reg(void) { unsigned char status; Qmi8658_read(QMI8658_SLAVE_ADDRESS, 0x59, &status, sizeof(status)); log_info("tap_temp_reg =[0x%x]\n", status); return status; } float Qmi8658_readTemp(void) { unsigned char buf[2]; short temp = 0; float temp_f = 0; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Tempearture_L, buf, 2); temp = ((short)buf[1] << 8) | buf[0]; temp_f = (float)temp / 256.0f; return temp_f; } void Qmi8658_read_acc_xyz(float acc_xyz[3]) { unsigned char buf_reg[6]; short raw_acc_xyz[3]; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ax_L, buf_reg, 6); // 0x35, 53 raw_acc_xyz[0] = (short)((unsigned short)(buf_reg[1] << 8) | (buf_reg[0])); raw_acc_xyz[1] = (short)((unsigned short)(buf_reg[3] << 8) | (buf_reg[2])); raw_acc_xyz[2] = (short)((unsigned short)(buf_reg[5] << 8) | (buf_reg[4])); acc_xyz[0] = (raw_acc_xyz[0] * ONE_G) / acc_lsb_div; acc_xyz[1] = (raw_acc_xyz[1] * ONE_G) / acc_lsb_div; acc_xyz[2] = (raw_acc_xyz[2] * ONE_G) / acc_lsb_div; //log_info("fis210x acc: %f %f %f\n", acc_xyz[0], acc_xyz[1], acc_xyz[2]); } void Qmi8658_read_gyro_xyz(float gyro_xyz[3]) { unsigned char buf_reg[6]; short raw_gyro_xyz[3]; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Gx_L, buf_reg, 6); // 0x3b, 59 raw_gyro_xyz[0] = (short)((unsigned short)(buf_reg[1] << 8) | (buf_reg[0])); raw_gyro_xyz[1] = (short)((unsigned short)(buf_reg[3] << 8) | (buf_reg[2])); raw_gyro_xyz[2] = (short)((unsigned short)(buf_reg[5] << 8) | (buf_reg[4])); /* log_info("gyro: %d %d %d\n", raw_gyro_xyz[0], raw_gyro_xyz[1], raw_gyro_xyz[2]); */ gyro_xyz[0] = (raw_gyro_xyz[0] * 1.0f) / gyro_lsb_div; gyro_xyz[1] = (raw_gyro_xyz[1] * 1.0f) / gyro_lsb_div; gyro_xyz[2] = (raw_gyro_xyz[2] * 1.0f) / gyro_lsb_div; //log_info("fis210x gyro: %f %f %f\n", gyro_xyz[0], gyro_xyz[1], gyro_xyz[2]); } /****** * tim_count: Sample time stamp. Count incremented by one for each sample (x, y, z data set) from sensor with highest ODR (circular register 0x0-0xFFFFFF). *****/ void Qmi8658_read_xyz(float acc[3], float gyro[3], unsigned int *tim_count) { unsigned char buf_reg[12]; short raw_acc_xyz[3]; short raw_gyro_xyz[3]; // float acc_t[3]; // float gyro_t[3]; if (tim_count) { unsigned char buf[3]; unsigned int timestamp; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Timestamp_L, buf, 3); // 0x18 24 timestamp = (unsigned int)(((unsigned int)buf[2] << 16) | ((unsigned int)buf[1] << 8) | buf[0]); if (timestamp > imu_timestamp) { imu_timestamp = timestamp; } else { imu_timestamp = (timestamp + 0x1000000 - imu_timestamp); } *tim_count = imu_timestamp; } Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ax_L, buf_reg, 12); // 0x19, 25 raw_acc_xyz[0] = (short)((unsigned short)(buf_reg[1] << 8) | (buf_reg[0])); raw_acc_xyz[1] = (short)((unsigned short)(buf_reg[3] << 8) | (buf_reg[2])); raw_acc_xyz[2] = (short)((unsigned short)(buf_reg[5] << 8) | (buf_reg[4])); raw_gyro_xyz[0] = (short)((unsigned short)(buf_reg[7] << 8) | (buf_reg[6])); raw_gyro_xyz[1] = (short)((unsigned short)(buf_reg[9] << 8) | (buf_reg[8])); raw_gyro_xyz[2] = (short)((unsigned short)(buf_reg[11] << 8) | (buf_reg[10])); #if (QMI8658_UINT_MG_DPS) // mg acc[AXIS_X] = (float)(raw_acc_xyz[AXIS_X] * 1000.0f) / acc_lsb_div; acc[AXIS_Y] = (float)(raw_acc_xyz[AXIS_Y] * 1000.0f) / acc_lsb_div; acc[AXIS_Z] = (float)(raw_acc_xyz[AXIS_Z] * 1000.0f) / acc_lsb_div; #else // m/s2 acc[AXIS_X] = (float)(raw_acc_xyz[AXIS_X] * ONE_G) / acc_lsb_div; acc[AXIS_Y] = (float)(raw_acc_xyz[AXIS_Y] * ONE_G) / acc_lsb_div; acc[AXIS_Z] = (float)(raw_acc_xyz[AXIS_Z] * ONE_G) / acc_lsb_div; #endif // acc[AXIS_X] = imu_map.sign[AXIS_X]*acc_t[imu_map.map[AXIS_X]]; // acc[AXIS_Y] = imu_map.sign[AXIS_Y]*acc_t[imu_map.map[AXIS_Y]]; // acc[AXIS_Z] = imu_map.sign[AXIS_Z]*acc_t[imu_map.map[AXIS_Z]]; #if (QMI8658_UINT_MG_DPS) // dps gyro[0] = (float)(raw_gyro_xyz[0] * 1.0f) / gyro_lsb_div; gyro[1] = (float)(raw_gyro_xyz[1] * 1.0f) / gyro_lsb_div; gyro[2] = (float)(raw_gyro_xyz[2] * 1.0f) / gyro_lsb_div; #else // rad/s gyro[AXIS_X] = (float)(raw_gyro_xyz[AXIS_X] * 0.01745f) / gyro_lsb_div; // *pi/180 gyro[AXIS_Y] = (float)(raw_gyro_xyz[AXIS_Y] * 0.01745f) / gyro_lsb_div; gyro[AXIS_Z] = (float)(raw_gyro_xyz[AXIS_Z] * 0.01745f) / gyro_lsb_div; #endif // gyro[AXIS_X] = imu_map.sign[AXIS_X]*gyro_t[imu_map.map[AXIS_X]]; // gyro[AXIS_Y] = imu_map.sign[AXIS_Y]*gyro_t[imu_map.map[AXIS_Y]]; // gyro[AXIS_Z] = imu_map.sign[AXIS_Z]*gyro_t[imu_map.map[AXIS_Z]]; } /****** * tim_count: Sample time stamp. Count incremented by one for each sample (x, y, z data set) from sensor with highest ODR (circular register 0x0-0xFFFFFF). *****/ void Qmi8658_read_xyz_raw(short raw_acc_xyz[3], short raw_gyro_xyz[3], unsigned int *tim_count) { unsigned char buf_reg[12]; if (tim_count) { unsigned char buf[3]; unsigned int timestamp; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Timestamp_L, buf, 3); // 0x18 24 timestamp = (unsigned int)(((unsigned int)buf[2] << 16) | ((unsigned int)buf[1] << 8) | buf[0]); if (timestamp > imu_timestamp) { imu_timestamp = timestamp; } else { imu_timestamp = (timestamp + 0x1000000 - imu_timestamp); } *tim_count = imu_timestamp; } if (raw_acc_xyz && raw_gyro_xyz) { Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ax_L, buf_reg, 12); // 0x19, 25 raw_acc_xyz[0] = (short)((unsigned short)(buf_reg[1] << 8) | (buf_reg[0])); raw_acc_xyz[1] = (short)((unsigned short)(buf_reg[3] << 8) | (buf_reg[2])); raw_acc_xyz[2] = (short)((unsigned short)(buf_reg[5] << 8) | (buf_reg[4])); raw_gyro_xyz[0] = (short)((unsigned short)(buf_reg[7] << 8) | (buf_reg[6])); raw_gyro_xyz[1] = (short)((unsigned short)(buf_reg[9] << 8) | (buf_reg[8])); raw_gyro_xyz[2] = (short)((unsigned short)(buf_reg[11] << 8) | (buf_reg[10])); } else if (raw_acc_xyz) { Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ax_L, buf_reg, 6); // 0x19, 25 raw_acc_xyz[0] = (short)((unsigned short)(buf_reg[1] << 8) | (buf_reg[0])); raw_acc_xyz[1] = (short)((unsigned short)(buf_reg[3] << 8) | (buf_reg[2])); raw_acc_xyz[2] = (short)((unsigned short)(buf_reg[5] << 8) | (buf_reg[4])); } else if (raw_gyro_xyz) { Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Gx_L, buf_reg, 6); // 0x19, 25 raw_gyro_xyz[0] = (short)((unsigned short)(buf_reg[1] << 8) | (buf_reg[0])); raw_gyro_xyz[1] = (short)((unsigned short)(buf_reg[3] << 8) | (buf_reg[2])); raw_gyro_xyz[2] = (short)((unsigned short)(buf_reg[5] << 8) | (buf_reg[4])); } } void Qmi8658_read_raw_acc_xyz(void *acc_data) { unsigned char buf_reg[8]; imu_axis_data_t *raw_acc_xyz = (imu_axis_data_t *)acc_data; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ax_L, buf_reg, 6); // 53 raw_acc_xyz->x = (short)((unsigned short)(buf_reg[1] << 8) | (buf_reg[0])); raw_acc_xyz->y = (short)((unsigned short)(buf_reg[3] << 8) | (buf_reg[2])); raw_acc_xyz->z = (short)((unsigned short)(buf_reg[5] << 8) | (buf_reg[4])); /* log_info("Qmi8658 acc: %d %d %d\n", raw_acc_xyz->x, raw_acc_xyz->y, raw_acc_xyz->z); */ } void Qmi8658_read_raw_gyro_xyz(void *gyro_data) { unsigned char buf_reg[6]; imu_axis_data_t *raw_gyro_xyz = (imu_axis_data_t *)gyro_data; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Gx_L, buf_reg, 6); // 53 raw_gyro_xyz->x = (short)((unsigned short)(buf_reg[1] << 8) | (buf_reg[0])); raw_gyro_xyz->y = (short)((unsigned short)(buf_reg[3] << 8) | (buf_reg[2])); raw_gyro_xyz->z = (short)((unsigned short)(buf_reg[5] << 8) | (buf_reg[4])); /* log_info("Qmi8658 gyro: %d %d %d\n", raw_gyro_xyz->x, raw_gyro_xyz->y, raw_gyro_xyz->z); */ } void Qmi8658_read_raw_acc_gyro_xyz(void *raw_data) { unsigned char buf_reg[14]; short temp = 0; imu_sensor_data_t *raw_sensor_data = (imu_sensor_data_t *)raw_data; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Tempearture_L, buf_reg, 14); // 0x3b, 59 temp = ((short)buf_reg[1] << 8) | buf_reg[0]; raw_sensor_data->acc.x = (short)((unsigned short)(buf_reg[3] << 8) | (buf_reg[2])); raw_sensor_data->acc.y = (short)((unsigned short)(buf_reg[5] << 8) | (buf_reg[4])); raw_sensor_data->acc.z = (short)((unsigned short)(buf_reg[7] << 8) | (buf_reg[6])); raw_sensor_data->gyro.x = (short)((unsigned short)(buf_reg[9] << 8) | (buf_reg[8])); raw_sensor_data->gyro.y = (short)((unsigned short)(buf_reg[11] << 8) | (buf_reg[10])); raw_sensor_data->gyro.z = (short)((unsigned short)(buf_reg[13] << 8) | (buf_reg[12])); raw_sensor_data->temp_data = (float)temp / 256.0f; /* log_info("Qmi8658 raw:acc_x:%d acc_y:%d acc_z:%d gyro_x:%d gyro_y:%d gyro_z:%d", raw_sensor_data->acc.x, raw_sensor_data->acc.y, raw_sensor_data->acc.z, raw_sensor_data->gyro.x, raw_sensor_data->gyro.y, raw_sensor_data->gyro.z); */ /* log_info("Qmi8658 temp:%d.%d\n", (u16)(raw_sensor_data->temp_data), (u16)(((u16)((raw_sensor_data->temp_data)* 100)) % 100)); */ } void Qmi8658_read_ae(float quat[4], float velocity[3]) { unsigned char buf_reg[14]; short raw_q_xyz[4]; short raw_v_xyz[3]; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Q1_L, buf_reg, 14); raw_q_xyz[0] = (short)((unsigned short)(buf_reg[1] << 8) | (buf_reg[0])); raw_q_xyz[1] = (short)((unsigned short)(buf_reg[3] << 8) | (buf_reg[2])); raw_q_xyz[2] = (short)((unsigned short)(buf_reg[5] << 8) | (buf_reg[4])); raw_q_xyz[3] = (short)((unsigned short)(buf_reg[7] << 8) | (buf_reg[6])); raw_v_xyz[1] = (short)((unsigned short)(buf_reg[9] << 8) | (buf_reg[8])); raw_v_xyz[2] = (short)((unsigned short)(buf_reg[11] << 8) | (buf_reg[10])); raw_v_xyz[2] = (short)((unsigned short)(buf_reg[13] << 8) | (buf_reg[12])); quat[0] = (float)(raw_q_xyz[0] * 1.0f) / ae_q_lsb_div; quat[1] = (float)(raw_q_xyz[1] * 1.0f) / ae_q_lsb_div; quat[2] = (float)(raw_q_xyz[2] * 1.0f) / ae_q_lsb_div; quat[3] = (float)(raw_q_xyz[3] * 1.0f) / ae_q_lsb_div; velocity[0] = (float)(raw_v_xyz[0] * 1.0f) / ae_v_lsb_div; velocity[1] = (float)(raw_v_xyz[1] * 1.0f) / ae_v_lsb_div; velocity[2] = (float)(raw_v_xyz[2] * 1.0f) / ae_v_lsb_div; } void Qmi8658_enableWakeOnMotion(enum Qmi8658_Interrupt int_set, enum Qmi8658_WakeOnMotionThreshold threshold, unsigned char blankingTime) { unsigned char cal1_1_reg = (unsigned char)threshold; unsigned char cal1_2_reg = (unsigned char)int_set | (blankingTime & 0x3F); unsigned char status1 = 0; int count = 0; Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, QMI8658_CTRL7_DISABLE_ALL); Qmi8658_config_acc(Qmi8658AccRange_8g, Qmi8658AccOdr_LowPower_21Hz, Qmi8658Lpf_Disable, Qmi8658St_Disable); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, cal1_1_reg); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, cal1_2_reg); // ctrl9 wom setting Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_WoM_Setting); // ctrl9 wom setting Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, QMI8658_CTRL7_ACC_ENABLE); } void Qmi8658_disableWakeOnMotion(void) { unsigned char status1 = 0; int count = 0; Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, QMI8658_CTRL7_DISABLE_ALL); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, 0); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, 0); Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_WoM_Setting); } void Qmi8658_enableSensors(unsigned char enableFlags) { if (enableFlags & QMI8658_CONFIG_AE_ENABLE) { enableFlags |= QMI8658_CTRL7_ACC_ENABLE | QMI8658_CTRL7_GYR_ENABLE; } #if (QMI8658_SYNC_SAMPLE_MODE) Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, enableFlags | 0x80); #else Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, enableFlags & QMI8658_CTRL7_ENABLE_MASK); #endif } void Qmi8658_enable_acc_Sensors(unsigned char enableFlags) { unsigned char ctrl7 = 0; if (enableFlags) { // Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Timestamp_L, &ctrl7, 1);// Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, &ctrl7, 1); ctrl7 |= QMI8658_CTRL7_ACC_ENABLE; Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, ctrl7 & QMI8658_CTRL7_ENABLE_MASK); } else { // close acc // Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Timestamp_L, &ctrl7, 1); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, &ctrl7, 1); ctrl7 &= (~QMI8658_CTRL7_ACC_ENABLE); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, ctrl7 & QMI8658_CTRL7_ENABLE_MASK); } } void Qmi8658_enable_gyro_Sensors(unsigned char enableFlags) { unsigned char ctrl7 = 0; if (enableFlags) { // Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Timestamp_L, &ctrl7, 1); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, &ctrl7, 1); ctrl7 |= QMI8658_CTRL7_GYR_ENABLE; Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, ctrl7 & QMI8658_CTRL7_ENABLE_MASK); } else { // close gyro // Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Timestamp_L, &ctrl7, 1); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, &ctrl7, 1); ctrl7 &= (~QMI8658_CTRL7_GYR_ENABLE); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, ctrl7 & QMI8658_CTRL7_ENABLE_MASK); } } /************************************************* ************************************************* 模式切换具体时间查数据手册(差异较大) ************************************************* *************************************************/ //15ms 后完成 void Qmi8658_reset(void)// { log_info("qmi8658_soft_reset \n"); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Reset, 0xb0);// Qmi8658_delay(20); // delay } //如果是spi3wire模式,执行powerdown后, 必须配置spi为3wire(Qmi8658Register_Ctrl1[bit7=1]) /* void Qmi8658_power_down(void)//??? */ /* { */ /* Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, 0);//clk disable??? */ /* Qmi8658_enableSensors(0); */ /* } */ //进入: 只能Power-On Default 进入该模式 //退出: 先soft reset再init u8 Qmi8658_power_down(void)// { u8 temp_data = 0; /* Qmi8658_reset(); */ log_info("qmi8658_power_down\n"); //sensorDisable Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, &temp_data, 1); temp_data |= BIT(0); //sensorDisable Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, temp_data);// //close acc,gyro,, Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, &temp_data, 1); temp_data &= ~0x0f; Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, temp_data);// Qmi8658_delay(10); // delay return 1; } //进入: 只能Power-On Default, Low Power Accel Only进入该模式 //退出: 先soft reset再init void Qmi8658_low_power(void)// { u8 temp_data = 0; /* Qmi8658_reset(); */ log_info("qmi8658_low_power\n"); //sensorenable Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, &temp_data, 1); temp_data &= ~BIT(0); //sensor enable Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, temp_data);// //close acc,gyro,, Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, &temp_data, 1); temp_data &= ~0x0f; Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, temp_data);// //aODR = 11xx Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl2, &temp_data, 1); temp_data |= 0x0f; Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl2, temp_data);// Qmi8658_delay(10); // delay } /* * spi set: * ctrl1: bit7: 3_wire_en * bit6: iic/spi_addr_auto_inc * bit5: spi_read_big_endian_en * 4:1 : reserved * bit0: disable internal 2 MHz oscillator */ void Qmi8658_spi_mode_set(u8 spi_3_wire_en)//仅上电初始化调用 { unsigned char ctrl1 = 0; if (spi_3_wire_en) { ctrl1 = 0xa0; //默认开大端模式 } else { ctrl1 = 0x20; } Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, ctrl1); } void Qmi8658_spi_mode_switch(u8 spi_3_wire_en) { unsigned char ctrl1 = 0; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, &ctrl1, 1); if (spi_3_wire_en) { ctrl1 |= 0xa0; //默认开大端模式 } else { ctrl1 &= ~0x80; ctrl1 |= 0x20; } Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, ctrl1); } void Qmi8658_Config_apply(struct Qmi8658Config const *config) { unsigned char fisSensors = config->inputSelection; Qmi8658_enableSensors(QMI8658_CTRL7_DISABLE_ALL); if (fisSensors & QMI8658_CONFIG_AE_ENABLE) { Qmi8658_config_ae(config->aeOdr); } else { if (config->inputSelection & QMI8658_CONFIG_ACC_ENABLE) { Qmi8658_config_acc(config->accRange, config->accOdr, Qmi8658Lpf_Disable, Qmi8658St_Disable); } if (config->inputSelection & QMI8658_CONFIG_GYR_ENABLE) { Qmi8658_config_gyro(config->gyrRange, config->gyrOdr, Qmi8658Lpf_Enable, Qmi8658St_Disable); } } if (config->inputSelection & QMI8658_CONFIG_MAG_ENABLE) { Qmi8658_config_mag(config->magDev, config->magOdr); } Qmi8658_enableSensors(fisSensors); } #if (QMI8658_USE_STEP_EN) unsigned char stepConfig(unsigned short odr) //11hz=0x0 ??? { unsigned short ped_fix_peak, ped_sample_cnt, ped_time_up, ped_fix_peak2peak; unsigned char ped_time_low, ped_time_cnt_entry, ped_fix_precision, ped_sig_count, basedODR; //void* pi2c = qmi8658_i2c_init(); float finalRate; //finalRate = 100.0/odr; finalRate = 100.0 / odr; //14.285 ped_sample_cnt = (unsigned short)(0x0032 / finalRate) ;//6;//(unsigned short)(0x0032 / finalRate) ; ped_fix_peak2peak = 0x00CC; ped_fix_peak = 0x00CC; ped_time_up = (unsigned short)(200.0 / finalRate); ped_time_low = (unsigned char)(20 / finalRate) ; ped_time_cnt_entry = 1; ped_fix_precision = 0; ped_sig_count = 1;//????? Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, ped_sample_cnt & 0xFF); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, (ped_sample_cnt >> 8) & 0xFF); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_L, ped_fix_peak2peak & 0xFF); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_H, (ped_fix_peak2peak >> 8) & 0xFF); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_L, ped_fix_peak & 0xFF); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_H, (ped_fix_peak >> 8) & 0xFF); //Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_L, 0x01); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_H, 0x01); log_info("+"); Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_EnablePedometer); log_info("."); /////////////////////////////// Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, ped_time_up & 0xFF); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, (ped_time_up >> 8) & 0xFF); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_L, ped_time_low); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_H, ped_time_cnt_entry); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_L, ped_fix_precision); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_H, ped_sig_count); //Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_L, 0x02 ); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_H, 0x02); log_info("-"); Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_EnablePedometer); log_info("*"); // qmi8658_i2c_deinit(pi2c); } uint32_t Qmi8658_step_read_stepcounter(uint32_t *step) { uint8_t reg_data[3] = {0}; uint8_t reg_47 = 0; uint32_t rslt; #if 1 Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_AccEl_X, reg_data, 3); #else Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_AccEl_X, reg_data, 1); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_AccEl_Y, ®_data[1], 1); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_AccEl_Z, ®_data[2], 1); #endif rslt = reg_data[2] << 16 | reg_data[1] << 8 | reg_data[0]; *step = rslt; return rslt; } void step_disable(void) { unsigned char ctrl8_data = 0x00; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl8, &ctrl8_data, 1); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl8, ctrl8_data & (~0x10)); // 0xD0 Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_L, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_H, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_L, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_H, 0x00); //Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_L, 0x01); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_H, 0x01); log_info("+"); Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_Reset_Pedometer); log_info("."); /////////////////////////////// Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_L, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_H, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_L, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_H, 0x00); //Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_L, 0x02 ); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_H, 0x02); log_info("-"); Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_Reset_Pedometer); log_info("*"); } #endif /***************************** *********** any motion config ctrl9 First CTRL9 Command: write to CAL1_L the value of AnyMotionXThr. write to CAL1_H the value of AnyMotionYThr. write to CAL2_L the value of AnyMotionZThr. write to CAL2_H the value of NoMotionXThr. write to CAL3_L the value of NoMotionYThr. write to CAL3_H the value of NoMotionZThr. write to CAL4_L the value of MOTION_MODE_CTRL write to CAL4_H the value of 0x01 write to CTRL9 the value of 0x0E // CTRL_CMD_CONFIGURE_MOTION = 0x0E Second CTRL9 Command: write to CAL1_L the value of AnyMotionWindow. write to CAL1_H the value of NoMotionWindow write to CAL2_L the value of SigMotionWaitWindow[7:0] write to CAL2_H the value of SigMotionWaitWindow [15:8] write to CAL3_L the value of SigMotionConfirmWindow[7:0] write to CAL3_H the value of SigMotionConfirmWindow[15:8] write to CAL4_H the value of 0x02 write to CTRL9 the value of 0x0E // CTRL_CMD_CONFIGURE_MOTION 0x0E ************************************/ #if (QMI8658_USE_ANYMOTION_EN) /*******/ /*motion_g_th is bit5~bit7 , 1 bit is 1G . such as : 001 is 1G, 111 is 7G . */ /*motion_mg_th is bit0 ~bit4, 1bit is 1/32G = 32.25mg; 00001 is 32.25mg , 00002 is 32.25*2mg . motion_mg_th set range is 0~ 31 */ /*****/ unsigned char anymotion_Config(enum Qmi8658_anymotion_G_TH motion_g_th, unsigned char motion_mg_th) //11hz=0x0 ????? { Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, (motion_g_th + motion_mg_th)); //0x03 // any motion X threshold U 3.5 first three bit(uint 1g) last five bit (uint 1/32 g) Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, (motion_g_th + motion_mg_th)); //0x03 //the value of AnyMotionYThr. Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_L, (motion_g_th + motion_mg_th)); //0x03 //the value of AnyMotionZThr. Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_H, 0x03); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_L, 0x03); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_H, 0x03); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_L, 0x07); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_H, 0x01); log_info("+"); Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_Motion); log_info("."); /////////////////////////////// Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, 0x03); //0x05 Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, 0x1a); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_L, 0x2c); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_H, 0x01); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_L, 0x64); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_H, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_H, 0x02); log_info("-"); Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_Motion); log_info("*"); return 1; } void anymotion_lowpwr_config(void) { qmi8658_config.inputSelection = QMI8658_CONFIG_ACC_ENABLE;//QMI8658_CONFIG_ACCGYR_ENABLE; qmi8658_config.accRange = Qmi8658AccRange_8g; qmi8658_config.accOdr = Qmi8658AccOdr_LowPower_11Hz;//Qmi8658AccOdr_LowPower_3Hz;//Qmi8658AccOdr_LowPower_11Hz; qmi8658_config.gyrRange = Qmi8658GyrRange_1024dps; //Qmi8658GyrRange_2048dps Qmi8658GyrRange_1024dps qmi8658_config.gyrOdr = Qmi8658GyrOdr_250Hz; Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl8, 0xc2); // 0xC2 anymotion_Config(Qmi8658_1G, 3) ; // th = 1.1g; //Qmi8658_Config_apply(&qmi8658_config); } void anymotion_high_odr_enable(void) { unsigned char ctrl8_data = 0x00; /* qmi8658_config.inputSelection = QMI8658_CONFIG_ACC_ENABLE;//QMI8658_CONFIG_ACCGYR_ENABLE; qmi8658_config.accRange = Qmi8658AccRange_8g; qmi8658_config.accOdr = Qmi8658AccOdr_125Hz; qmi8658_config.gyrRange = Qmi8658GyrRange_1024dps; //Qmi8658GyrRange_2048dps Qmi8658GyrRange_1024dps qmi8658_config.gyrOdr = Qmi8658GyrOdr_125Hz; // qmi8658_config.magOdr = Qmi8658MagOdr_125Hz; // qmi8658_config.magDev = MagDev_AKM09918; // qmi8658_config.aeOdr = Qmi8658AeOdr_128Hz; */ Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl8, &ctrl8_data, 1); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl8, ctrl8_data | 0xC2); // 0xC2 anymotion_Config(Qmi8658_1G, 3) ; //// th = 1.1g; //Qmi8658_Config_apply(&qmi8658_config); } void anymotion_disable(void) { unsigned char ctrl8_data = 0x00; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl8, &ctrl8_data, 1); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl8, ctrl8_data & (~0x02)); // 0xC2 Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, 0x23); //0x03 // any motion X threshold U 3.5 first three bit(uint 1g) last five bit (uint 1/32 g) Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, 0x23); //0x03 //the value of AnyMotionYThr. Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_L, 0x23); //0x03 //the value of AnyMotionZThr. Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_H, 0x03); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_L, 0x03); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_H, 0x03); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_L, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_H, 0x01); log_info("+"); Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_Motion); log_info("."); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, 0x03); //0x05 Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, 0x1a); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_L, 0x2c); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_H, 0x01); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_L, 0x64); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_H, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_H, 0x02); log_info("-"); Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_Motion); log_info("*"); } #endif /*********************************** First CTRL9 Command: write to CAL1_L the value of peakWindow. //30表示, 30 ms at 1000 Hz .就是ODR的个数。 write to CAL1_H the value of priority. write to CAL2_L the value of TapWindow low byte. //100表示, 100 ms at 1000 Hz 就是ODR的个数。 write to CAL2_H the value of TapWindow high byte. write to CAL3_L the value of DTapWindow low byte. write to CAL3_H the value of DTapWindow high byte. write to CAL4_H the value of 0x01 write to CTRL9 the value of 0x0C // CTRL_CMD_CONFIGURE_TAP = 0x0C Second CTRL9 Command: write to CAL1_L the value of alpha. //更新下个数据的百分比 write to CAL1_H the value of gamma. //差值数据更新的百分比 write to CAL2_L the value of peakMagThr low byte. xyz 模值的阀值。 敲的力度阀值 write to CAL2_H the value of peakMagThr high byte. write to CAL3_L the value of UDMThr low byte. //停止敲击的,阀值,gamma与其有关。值设置越大,越容易满足条件。 write to CAL3_H the value of UDMThr high byte. write to CAL4_H the value of 0x02 write to CTRL9 the value of 0x0C // CTRL_CMD_CONFIGURE_TAP 0x0C *************************************************/ #if (QMI8658_USE_TAP_EN) unsigned char tap_Config(void) //11hz=0x0e ???? { #if 1 //alpha tap param uint8_t peakWindow = 0x0e; //0x1e 30ms at 1000hz ODR. uint8_t priority = 0x04; uint16_t TapWindow = 0x000c; //0x0016 //0x0064 100MS at 100hz odr uint16_t DTapWindow = 0x0058; // uint8_t alpha = 0x40; //0x40; //0x08; //0.065 //alpha 百分比 =alpha[7] + alpha[6~0]* (1/128) uint8_t gamma = 0x20; //0x10; //0x20;//0x20; //0.25 //gamma 百分比 =gamma[7] + gamma[6~0]* (1/128) uint16_t peakMagThr = 0x0069;//0x0200;//0x0599//0x0599; // 1.4g uint16_t UDMThr = 0x0049; //0x0100; //0x0199; // 0.4g #endif // Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, peakWindow); //0x1E Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, priority); //0x03 Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_L, TapWindow & 0xff); //0x64 Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_H, (TapWindow >> 8) & 0xff); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_L, DTapWindow & 0xff); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_H, (DTapWindow >> 8) & 0xff); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_H, 0x01); log_info("+"); Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_EnableTap); log_info("."); /////////////////////////////// Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, alpha); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, gamma); //0x20 Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_L, peakMagThr & 0xff); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_H, (peakMagThr >> 8) & 0xff); //0x05 Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_L, UDMThr & 0xff); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_H, (UDMThr >> 8) & 0xff); //0x01 Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal4_H, 0x02); log_info("-"); Qmi8658_send_ctl9cmd(Qmi8658_Ctrl9_Cmd_EnableTap); log_info("*"); } void tap_enable(void) { unsigned char ctrl8_data = 0x00; /* qmi8658_config.inputSelection = QMI8658_CONFIG_ACCGYR_ENABLE;//QMI8658_CONFIG_ACCGYR_ENABLE; qmi8658_config.accRange = Qmi8658AccRange_2g; qmi8658_config.accOdr = Qmi8658AccOdr_125Hz; qmi8658_config.gyrRange = Qmi8658GyrRange_1024dps; //Qmi8658GyrRange_2048dps Qmi8658GyrRange_1024dps qmi8658_config.gyrOdr = Qmi8658GyrOdr_125Hz; //qmi8658_config.magOdr = Qmi8658MagOdr_125Hz; //qmi8658_config.magDev = MagDev_AKM09918; //qmi8658_config.aeOdr = Qmi8658AeOdr_128Hz; */ Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl8, &ctrl8_data, 1); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl8, ctrl8_data | 0xc1); // 0xC2 tap_Config() ; //Qmi8658_Config_apply(&qmi8658_config); } #endif #if (QMI8658_NEW_HANDSHAKE) void qmi8658_on_demand_cali(void) { unsigned char cod_status = 0x00; unsigned char cod_data[6]; log_info("qmi8658_on_demand_cali start"); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl9, (unsigned char)Qmi8658_Ctrl9_Cmd_On_Demand_Cali); Qmi8658_delay(2200); // delay 2000ms above Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl9, 0x00);//qmi8658_Ctrl9_Cmd_Ack Qmi8658_delay(10); // delay Qmi8658_read(QMI8658_SLAVE_ADDRESS, 0x70/* Qmi8658Register_Cod_Status */, &cod_status, 1); if (cod_status) { log_info("qmi8658_on_demand_cali fail! status=0x%x", cod_status); } else { Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Dvx_L, &cod_data[0], 6);//qmi8658_get_gyro_gain log_info("qmi8658_on_demand_cali done! cod[%d %d %d]", (unsigned short)(cod_data[1] << 8 | cod_data[0]), (unsigned short)(cod_data[3] << 8 | cod_data[2]), (unsigned short)(cod_data[5] << 8 | cod_data[4])); } } void qmi8658_apply_gyr_gain(unsigned char cod_data[6]) { u8 cod_data_temp[8]; /* Qmi8658_enableSensors(QMI8658_CTRL7_DISABLE_ALL); */ Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_L, cod_data[0]); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal1_H, cod_data[1]); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_L, cod_data[2]); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal2_H, cod_data[3]); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_L, cod_data[4]); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Cal3_H, cod_data[5]); Qmi8658_send_ctl9cmd(0xaa);//(qmi8658_Ctrl9_Cmd_Apply_Gyro_Gain); /* Qmi8658_enableSensors(QMI8658_CONFIG_ACCGYR_ENABLE); */ } #endif unsigned char qmi8658_init(u8 demand_cali_en) { unsigned char qmi8658_chip_id = 0x00; unsigned char qmi8658_revision_id = 0x00; unsigned char iCount = 0; unsigned char fw_version[3] = {0}; unsigned char usid_version[6] = {0}; #if (QMI8658_USER_INTERFACE==QMI8658_USE_SPI) if (qmi8658_info->spi_work_mode) { Qmi8658_spi_mode_set(1);//使能spi_3_wire } else { Qmi8658_spi_mode_set(0);//使能spi_4_wire } #endif while ((qmi8658_chip_id == 0x00) && (iCount < 10)) { Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_WhoAmI, &qmi8658_chip_id, 1); if (qmi8658_chip_id == 0x05) { break; } iCount++; mdelay(1); } /* Qmi8658_read(QMI8658_SLAVE_ADDRESS, 0x49, fw_version, 3); */ /* log_info("Qmi8658_fw_version(Quaternion Increment dQW?)=0x%x, 0x%x, 0x%x \n", fw_version[0],fw_version[1],fw_version[2]); */ Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Revision, &qmi8658_revision_id, 1); if (qmi8658_chip_id == 0x05) { log_info("Qmi8658_init slave=0x%x Qmi8658Register_WhoAmI=0x%x 0x%x\n", QMI8658_SLAVE_ADDRESS, qmi8658_chip_id, qmi8658_revision_id); /* Qmi8658_read(QMI8658_SLAVE_ADDRESS, 0x51, usid_version, 6); */ /* log_info("Qmi8658_usid_version(Velocity Increment along XYZ?)=0x%x, 0x%x, 0x%x ,0x%x, 0x%x, 0x%x \n", usid_version[0],usid_version[1],usid_version[2] ,usid_version[3],usid_version[4],usid_version[5]); */ #if (QMI8658_NEW_HANDSHAKE==0) Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, &iCount, 1); iCount |= 0x60; iCount &= ~ 0x01; /* iCount |= 0x04; */ Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, iCount);//bit7:1:spi_3_wire, bit6:addr_auto_inc, bit5:spi_read_big_endian(大端),bit0:0:clkosc #else /* Qmi8658_reset(); */ Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, 0x60 | 0x08 | 0x10); // 另一种qmi8658 if (demand_cali_en) { qmi8658_on_demand_cali(); /* printf("set cod"); */ } else { /* qmi8658_apply_gyr_gain(cod_data_copy); */ /* printf("restore cod"); */ } Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, 0x00); Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl8, 0xc0); #endif qmi8658_config.inputSelection = QMI8658_CONFIG_ACCGYR_ENABLE;//QMI8658_CONFIG_ACCGYR_ENABLE; qmi8658_config.accRange = Qmi8658AccRange_16g; qmi8658_config.accOdr = Qmi8658AccOdr_125Hz; qmi8658_config.gyrRange = Qmi8658GyrRange_2048dps; //Qmi8658GyrRange_2048dps Qmi8658GyrRange_1024dps qmi8658_config.gyrOdr = Qmi8658GyrOdr_125Hz; #if (QMI8658_USE_TAP_EN) tap_enable(); #endif #if (QMI8658_USE_ANYMOTION_EN) //anymotion_high_odr_enable(); anymotion_lowpwr_config(); #endif #if (QMI8658_USE_FIFO_EN) Qmi8658_config_fifo(128, Qmi8658_Fifo_128, Qmi8658_Fifo_Stream, QMI8658_FORMAT_12_BYTES); #endif #if (QMI8658_USE_STEP_EN) qmi8658_config.inputSelection = QMI8658_CONFIG_ACC_ENABLE; qmi8658_config.accRange = Qmi8658AccRange_8g; qmi8658_config.accOdr = Qmi8658AccOdr_LowPower_21Hz;//Qmi8658AccOdr_62_5Hz;//Qmi8658AccOdr_LowPower_21Hz; qmi8658_config.gyrRange = Qmi8658GyrRange_1024dps; //Qmi8658GyrRange_2048dps Qmi8658GyrRange_1024dps qmi8658_config.gyrOdr = Qmi8658GyrOdr_500Hz; Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, 0x00); // Qmi8658_write(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl8, 0xD0); stepConfig(21); //ODR = 21hz //stepConfig(62); //ODR = 62.5HZ #endif Qmi8658_Config_apply(&qmi8658_config); #if 0 unsigned char read_data = 0x00; Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl1, &read_data, 1); log_info("Qmi8658Register_Ctrl1=0x%x \n", read_data); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl2, &read_data, 1); log_info("Qmi8658Register_Ctrl2=0x%x \n", read_data); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl3, &read_data, 1); log_info("Qmi8658Register_Ctrl3=0x%x \n", read_data); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl4, &read_data, 1); log_info("Qmi8658Register_Ctrl4=0x%x \n", read_data); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl5, &read_data, 1); log_info("Qmi8658Register_Ctrl5=0x%x \n", read_data); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl6, &read_data, 1); log_info("Qmi8658Register_Ctrl6=0x%x \n", read_data); Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_Ctrl7, &read_data, 1); log_info("Qmi8658Register_Ctrl7=0x%x \n", read_data); Qmi8658_read(QMI8658_SLAVE_ADDRESS, 77, &qmi8658_revision_id, 1); log_info("teset:0x%x", qmi8658_revision_id); #endif // Qmi8658_set_layout(2); return 1; } else { log_error("Qmi8658_init fail\n"); qmi8658_chip_id = 0; return 0; } } static u8 qmi8658_int_pin1 = IO_PORTB_04; static u8 qmi8658_int_pin2 = IO_PORTB_03; //return:0:fail, 1:ok u8 qmi8658_sensor_init(void *priv) { if (priv == NULL) { log_error("qmi8658 init fail(no param)\n"); return 0; } qmi8658_info = (qmi8658_param *)priv; #if (QMI8658_USER_INTERFACE==QMI8658_USE_I2C) //iic interface iic_init(qmi8658_info->iic_hdl); #elif (QMI8658_USER_INTERFACE==QMI8658_USE_SPI)//spi interface spi_cs_init(); spi_init(); #else //I3C #endif gpio_set_die(qmi8658_int_pin1, 1); gpio_set_direction(qmi8658_int_pin1, 1); // gpio_set_pull_up(qmi8658_int_pin1,1); gpio_set_die(qmi8658_int_pin2, 1); gpio_set_direction(qmi8658_int_pin2, 1); // gpio_set_pull_up(qmi8658_int_pin2,1); return qmi8658_init(1); } static volatile u32 qmi8658_init_flag ; static u8 imu_busy = 0; static qmi8658_param qmi8658_info_data; /* #define SENSORS_MPU_BUFF_LEN 14 */ /* u8 read_qmi8658_buf[SENSORS_MPU_BUFF_LEN]; */ #if (QMI8658_USE_FIFO_EN) u8 fifo_data[1024];//size:Qmi8658_FifoSize * 6 * Number_of_enabled_sensors #endif void qmi8658_int_callback() { if (qmi8658_init_flag == 0) { log_error("qmi8658 init fail!"); return ; } if (imu_busy) { log_error("qmi8658 busy!"); return ; } imu_busy = 1; imu_sensor_data_t raw_sensor_datas; float TempData = 0.0; u8 status_temp = 0; #if (QMI8658_USE_FIFO_EN) u16 fifo_level = 0; fifo_level = Qmi8658_read_fifo(fifo_data); TempData = Qmi8658_readTemp(); /* log_info("qmi8658 raw:acc_x:%d acc_y:%d acc_z:%d gyro_x:%d gyro_y:%d gyro_z:%d, tim_count:%d", (s16)(fifo_data[1]<<8|fifo_data[0]), (s16)(fifo_data[3]<<8|fifo_data[2]), (s16)(fifo_data[5]<<8|fifo_data[4]), (s16)(fifo_data[7]<<8|fifo_data[6]), (s16)(fifo_data[9]<<8|fifo_data[8]), (s16)(fifo_data[11]<<8|fifo_data[10]),fifo_level);//共fifo_level组数据, 只打印第一组数据 */ #else status_temp = Qmi8658_readStatus0(); /* log_info("status:0x%x", status_temp); */ if (status_temp & 0x03) { Qmi8658_read_raw_acc_gyro_xyz(&raw_sensor_datas);//获取原始值 /* TempData=Qmi8658_readTemp(); */ TempData = raw_sensor_datas.temp_data; /* log_info("qmi8658 raw:acc_x:%d acc_y:%d acc_z:%d gyro_x:%d gyro_y:%d gyro_z:%d", raw_sensor_datas.acc.x, raw_sensor_datas.acc.y, raw_sensor_datas.acc.z, raw_sensor_datas.gyro.x, raw_sensor_datas.gyro.y, raw_sensor_datas.gyro.z); */ } #endif /* log_info("qmi8658 temp:%d.%d\n", (u16)TempData, (u16)(((u16)(TempData * 100)) % 100)); */ imu_busy = 0; } s8 qmi8658_dev_init(void *arg) { if (arg == NULL) { log_error("qmi8658 init fail(no arg)\n"); return -1; } #if (QMI8658_USER_INTERFACE==QMI8658_USE_I2C) qmi8658_info_data.iic_hdl = ((struct imusensor_platform_data *)arg)->peripheral_hdl; qmi8658_info_data.iic_delay = ((struct imusensor_platform_data *)arg)->peripheral_param0; //这个延时并非影响iic的时钟频率,而是2Byte数据之间的延时 // u8 iic_clk; //iic_clk: <=400kHz #elif (QMI8658_USER_INTERFACE==QMI8658_USE_SPI) qmi8658_info_data.spi_hdl = ((struct imusensor_platform_data *)arg)->peripheral_hdl, //SPIx (role:master) qmi8658_info_data.spi_cs_pin = ((struct imusensor_platform_data *)arg)->peripheral_param0; //IO_PORTA_05 qmi8658_info_data.spi_work_mode = ((struct imusensor_platform_data *)arg)->peripheral_param1; //1:3wire(SPI_MODE_UNIDIR_1BIT) or 0:4wire(SPI_MODE_BIDIR_1BIT) (与spi结构体一样) // u8 port; //SPIx group:A,B,C,D (spi结构体) // U8 spi_clk; //spi_clk: <=15MHz (spi结构体) #else //I3C #endif qmi8658_int_pin2 = ((struct imusensor_platform_data *)arg)->imu_sensor_int_io; qmi8658_int_pin1 = qmi8658_int_pin2; if (imu_busy) { log_error("qmi8658 busy!"); return -1; } imu_busy = 1; if (qmi8658_sensor_init(&qmi8658_info_data)) { #if (QMI8658_USE_INT_EN) //中断模式,暂不支持 log_info("int mode en!"); /* port_wkup_enable(qmi8658_int_pin2, 1, qmi8658_int_callback); //PA08-IO中断,1:下降沿触发,回调函数qmi8658_int_callback*/ #ifdef CONFIG_CPU_BR23 io_ext_interrupt_init(qmi8658_int_pin2, 1, qmi8658_int_callback); #elif defined(CONFIG_CPU_BR28) // br28外部中断回调函数,按照现在的外部中断注册方式 // io配置在板级,定义在板级头文件,这里只是注册回调函数 /* port_edge_wkup_set_callback_by_index(3, qmi8658_int_callback); // 序号需要和板级配置中的wk_param对应上 */ port_edge_wkup_set_callback(qmi8658_int_callback); #elif defined(CONFIG_CPU_BR27) port_edge_wkup_set_callback(qmi8658_int_callback); #endif #else //定时 #endif qmi8658_init_flag = 1; imu_busy = 0; log_info("qmi8658 Device init success!%d\n", qmi8658_init_flag); return 0; } else { log_info("qmi8658 Device init fail!\n"); imu_busy = 0; return -1; } } int qmi8658_dev_ctl(u8 cmd, void *arg); REGISTER_IMU_SENSOR(qmi8658_sensor) = { .logo = "qmi8658", .imu_sensor_init = qmi8658_dev_init, .imu_sensor_check = NULL, .imu_sensor_ctl = qmi8658_dev_ctl, }; int qmi8658_dev_ctl(u8 cmd, void *arg) { int ret = -1; u8 status_temp = 0; if (qmi8658_init_flag == 0) { log_error("qmi8658 init fail!"); return ret;//0:ok,,<0:err } if (imu_busy) { log_error("qmi8658 busy!"); return ret;//0:ok,,<0:err } imu_busy = 1; switch (cmd) { case IMU_GET_SENSOR_NAME: memcpy((u8 *)arg, &(qmi8658_sensor.logo), 20); ret = 0; break; case IMU_SENSOR_ENABLE: //enable demand cali /* cbuf_init(&hrsensor_cbuf, hrsensorcbuf, 24 * sizeof(int)); */ qmi8658_init(1); ret = 0; break; case IMU_SENSOR_DISABLE: /* cbuf_clear(&hrsensor_cbuf); */ //close power Qmi8658_power_down(); ret = 0; break; case IMU_SENSOR_RESET://reset后必须enable Qmi8658_reset(); ret = 0; break; case IMU_SENSOR_SLEEP: if (Qmi8658_power_down()) { log_info("qmi8658 enter sleep ok!"); ret = 0; } else { log_error("qmi8658 enter sleep fail!"); } break; case IMU_SENSOR_WAKEUP: //disable demand cali if (qmi8658_init(0)) { log_info("qmi8658 wakeup ok!"); ret = 0; } else { log_error("qmi8658 wakeup fail!"); } break; case IMU_SENSOR_INT_DET://传感器中断状态检查 break; case IMU_SENSOR_DATA_READY://传感器数据准备就绪待读 break; case IMU_SENSOR_CHECK_DATA://检查传感器缓存buf是否存满 break; case IMU_SENSOR_READ_DATA://默认读传感器所有数据 status_temp = Qmi8658_readStatus0(); /* log_info("status:0x%x", status_temp); */ if (status_temp & 0x03) { Qmi8658_read_raw_acc_gyro_xyz(arg);//获取原始值 ret = 0; } break; case IMU_GET_ACCEL_DATA://加速度数据 /* float TempData = 0.0; */ status_temp = Qmi8658_readStatus0(); /* log_info("status:0x%x", status_temp); */ if (status_temp & 0x01) { Qmi8658_read_raw_acc_xyz(arg);//获取原始值 ret = 0; /* TempData = Qmi8658_readTemp(); */ } break; case IMU_GET_GYRO_DATA://陀螺仪数据 status_temp = Qmi8658_readStatus0(); /* log_info("status:0x%x", status_temp); */ if (status_temp & 0x02) { Qmi8658_read_raw_gyro_xyz(arg);//获取原始值 ret = 0; } break; case IMU_GET_MAG_DATA://磁力计数据 log_error("qmi8658 have no mag!\n"); break; case IMU_SENSOR_SEARCH://检查传感器id Qmi8658_read(QMI8658_SLAVE_ADDRESS, Qmi8658Register_WhoAmI, (u8 *)arg, 1); if (*(u8 *)arg == 0x05) { ret = 0; log_info("qmi8658 online!\n"); } else { log_error("qmi8658 offline!\n"); } break; case IMU_GET_SENSOR_STATUS://获取传感器状态 status_temp = Qmi8658_readStatus0(); *(u8 *)arg = status_temp; ret = 0; break; case IMU_SET_SENSOR_FIFO_CONFIG://配置传感器FIFO #if (QMI8658_USE_FIFO_EN) u8 *tmp = (u8 *)arg; u8 wm_th = tmp[0]; u8 fifo_size = tmp[1];//Qmi8658_Fifo_64 u8 fifo_mode = tmp[2];//Qmi8658_Fifo_Stream u8 fifo_format = tmp[3];//QMI8658_FORMAT_12_BYTES Qmi8658_config_fifo(wm_th, fifo_size, fifo_mode, fifo_format); ret = 0; #endif break; case IMU_GET_SENSOR_READ_FIFO://读取传感器FIFO数据 #if (QMI8658_USE_FIFO_EN) ret = Qmi8658_read_fifo((u8 *)arg); #endif break; case IMU_SET_SENSOR_TEMP_DISABLE://温度传感器无法控制 u8 temp = *(u8 *)arg; ret = 0; break; default: log_error("--cmd err!\n"); break; } imu_busy = 0; return ret;//0:ok,,<0:err } #endif