diff --git a/src/W800 SDK v1.00.08/app/drivers/i2c/QMC5883L.c b/src/W800 SDK v1.00.08/app/drivers/i2c/QMC5883L.c new file mode 100644 index 0000000..d1e356f --- /dev/null +++ b/src/W800 SDK v1.00.08/app/drivers/i2c/QMC5883L.c @@ -0,0 +1,59 @@ +#include "i2c.h" +#include "QMC5883L.h" + +bool QMC5883L_init(void) +{ + return i2c_write_reg(QMC5883L_I2C_ADDR, QMC5883L_SETRES_REG, 0x01); +} + +float QMC5883L_get_temperature(void) +{ + uint8_t data; + int16_t raw_temp; + + i2c_read_reg(QMC5883L_I2C_ADDR, QMC5883L_TEMP_MSB_REG, &data); + + raw_temp = data << 8; + + i2c_read_reg(QMC5883L_I2C_ADDR, QMC5883L_TEMP_LSB_REG, &data); + + raw_temp |= data; + + return (float) raw_temp / 100.0; +} + +bool QMC5883L_is_data_available(void) +{ + uint8_t data; + + i2c_read_reg(QMC5883L_I2C_ADDR, QMC5883L_STATUS_REG, &data); + + return data & QMC5883L_DRDY_BIT ? true : false; +} + +QMC5883L_MData_t QMC5883L_get_MFields(void) +{ + uint8_t data[6]; + QMC5883L_MData_t Mdata = {.MFieldX = -1, .MFieldY = -1, .MFieldZ = -1}; + + if(i2c_read(QMC5883L_I2C_ADDR, QMC5883L_DATA_X_LSB_REG, data, sizeof data)) + { + Mdata.MFieldX = (data[1] << 8) | data[0]; + Mdata.MFieldY = (data[3] << 8) | data[2]; + Mdata.MFieldZ = (data[5] << 8) | data[4]; + } + + return Mdata; +} + +bool QMC5883L_set_power_mode(QMC5883L_Mode_Control_e MC) +{ + uint8_t data; + + if(!i2c_read_reg(QMC5883L_I2C_ADDR, QMC5883L_CTRL1_REG, &data))return false; + + data &= 0xFC; + data |= MC; + + return i2c_write_reg(QMC5883L_I2C_ADDR, QMC5883L_CTRL1_REG, data); +} diff --git a/src/W800 SDK v1.00.08/app/drivers/i2c/QMC5883L.h b/src/W800 SDK v1.00.08/app/drivers/i2c/QMC5883L.h new file mode 100644 index 0000000..e7004a7 --- /dev/null +++ b/src/W800 SDK v1.00.08/app/drivers/i2c/QMC5883L.h @@ -0,0 +1,78 @@ +#ifndef QMC5883L_H +#define QMC5883L_H + +/* Device i2c address */ +#define QMC5883L_I2C_ADDR 0x0D + +/* Device registers list */ +#define QMC5883L_DATA_X_LSB_REG 0x00 +#define QMC5883L_STATUS_REG 0x06 +#define QMC5883L_TEMP_LSB_REG 0x07 +#define QMC5883L_TEMP_MSB_REG 0x08 +#define QMC5883L_CTRL1_REG 0x09 +#define QMC5883L_CTRL2_REG 0x0A +#define QMC5883L_SETRES_REG 0x0B + +/* Field masks */ +#define QMC5883L_DRDY_BIT 0x01 +#define QMC5883L_OVL_BIT 0x02 +#define QMC5883L_DOR_BIT 0x04 + +/* Configuration enumerations */ +typedef enum +{ + Standby = 0, + Continuous = 1, +} QMC5883L_Mode_Control_e; + +typedef enum +{ + ODR_10HZ = 0, + ODR_50HZ = 1, + ODR_100HZ = 2, + ODR_200HZ = 3, +} QMC5883L_Output_Data_Rate_e; + +typedef enum +{ + FS_2G = 0, + FS_8G = 1, +} QMC5883L_Full_Scale_e; + +typedef enum +{ + OSR_512 = 0, + OSR_256 = 1, + OSR_128 = 2, + OSR_64 = 3, +} QMC5883L_Over_Sample_Ratio_e; + + +typedef struct +{ + int16_t MFieldX; + int16_t MFieldY; + int16_t MFieldZ; +} QMC5883L_MData_t; + + +/* QMC5883L Driver API */ + +bool QMC5883L_init(void); + +bool QMC5883L_software_reset(void); + +float QMC5883L_get_temperature(void); + +bool QMC5883L_is_data_available(void); + +QMC5883L_MData_t QMC5883L_get_MFields(void); + +bool QMC5883L_configure_1(QMC5883L_Output_Data_Rate_e ODR, QMC5883L_Full_Scale_e RNG, QMC5883L_Over_Sample_Ratio_e OSR); + +bool QMC5883L_configure_2(bool rolling_ptr, bool data_ready_int); + +bool QMC5883L_set_power_mode(QMC5883L_Mode_Control_e MC); + + +#endif //QMC5883L_H \ No newline at end of file diff --git a/src/W800 SDK v1.00.08/app/drivers/i2c/i2c.c b/src/W800 SDK v1.00.08/app/drivers/i2c/i2c.c index 19783fa..371b716 100644 --- a/src/W800 SDK v1.00.08/app/drivers/i2c/i2c.c +++ b/src/W800 SDK v1.00.08/app/drivers/i2c/i2c.c @@ -31,16 +31,31 @@ bool i2c_write_reg(uint8_t address, uint8_t reg, uint8_t data) return true; } -bool i2c_read(uint8_t address, const uint8_t *data, size_t length, bool sendStop) +bool i2c_read(uint8_t address, uint8_t reg, uint8_t * const data, size_t length) { if(!data)return false; + //First we send the address followed by the register from where we want to start reading: + tls_i2c_write_byte(address << 1, true); + if(tls_i2c_wait_ack() != WM_SUCCESS) return false; + tls_i2c_write_byte(reg, false); + if(tls_i2c_wait_ack() != WM_SUCCESS) return false; + + tls_i2c_write_byte((address << 1) | 1, true); + if(tls_i2c_wait_ack() != WM_SUCCESS) return false; + + for(size_t i = 0; i < length - 1; i++ ) + { + data[i] = tls_i2c_read_byte(true, false); + } + + data[length - 1] = tls_i2c_read_byte(false, true); + return true; } bool i2c_read_reg(uint8_t address, uint8_t reg, uint8_t * const data) { - if(!data) return false; //First we send the address followed by the register we want to read from: tls_i2c_write_byte(address << 1, true); if(tls_i2c_wait_ack() != WM_SUCCESS) return false; @@ -49,7 +64,9 @@ bool i2c_read_reg(uint8_t address, uint8_t reg, uint8_t * const data) tls_i2c_write_byte((address << 1) | 1, true); if(tls_i2c_wait_ack() != WM_SUCCESS) return false; - *data = tls_i2c_read_byte(false, true); + + uint8_t val = tls_i2c_read_byte(false, true); + if(data) *data = val; return true; } diff --git a/src/W800 SDK v1.00.08/app/drivers/i2c/i2c.h b/src/W800 SDK v1.00.08/app/drivers/i2c/i2c.h index 2566dff..ba806f7 100644 --- a/src/W800 SDK v1.00.08/app/drivers/i2c/i2c.h +++ b/src/W800 SDK v1.00.08/app/drivers/i2c/i2c.h @@ -1,16 +1,18 @@ #ifndef I2C_H #define I2C_H +#include +#include #include "wm_type_def.h" #include "wm_io.h" void i2c_init(enum tls_io_name SDAPin, enum tls_io_name SCLPin, uint32_t frequency); -bool i2c_write(uint8_t address, const uint8_t *data, size_t length, bool sendStop); +//bool i2c_write(uint8_t address, const uint8_t *data, size_t length); bool i2c_write_reg(uint8_t address, uint8_t reg, uint8_t data); -bool i2c_read(uint8_t address, const uint8_t *data, size_t length, bool sendStop); +bool i2c_read(uint8_t address, uint8_t reg, uint8_t * const data, size_t length); bool i2c_read_reg(uint8_t address, uint8_t reg, uint8_t * const data);