From 97a9959f164a4a07e7b91db89b42b91a15f07958 Mon Sep 17 00:00:00 2001 From: Michael Jakob Date: Tue, 26 Jan 2016 00:05:08 +0100 Subject: [PATCH] SPI driver support Add HMC5883/5983 driver Add BMP280 driver Add MS5611 driver --- src/main/drivers/barometer_bmp280.c | 24 +++++- src/main/drivers/barometer_ms5611.c | 79 ++++++++----------- src/main/drivers/compass_hmc5883l.c | 100 ++++++++++++++++++++++--- src/main/target/ALIENFLIGHTF4/target.h | 21 +++--- 4 files changed, 151 insertions(+), 73 deletions(-) diff --git a/src/main/drivers/barometer_bmp280.c b/src/main/drivers/barometer_bmp280.c index 4f796a930..a67f05ec0 100644 --- a/src/main/drivers/barometer_bmp280.c +++ b/src/main/drivers/barometer_bmp280.c @@ -31,6 +31,8 @@ #include "barometer_bmp280.h" +//#define DEBUG_BMP280 + #ifdef BARO #ifndef BMP280_I2C_INSTANCE @@ -108,8 +110,10 @@ static void bmp280_get_up(void); STATIC_UNIT_TESTED void bmp280_calculate(int32_t *pressure, int32_t *temperature); #if defined(USE_SPI) && defined(BMP280_SPI_INSTANCE) -#define DISABLE_BMP280 GPIO_SetBits(BMP280_CS_GPIO, BMP280_CS_PIN) -#define ENABLE_BMP280 GPIO_ResetBits(BMP280_CS_GPIO, BMP280_CS_PIN) +#define DISABLE_BMP280 IOHi(bmp280CsPin) +#define ENABLE_BMP280 IOLo(bmp280CsPin) + +static IO_t bmp280CsPin = IO_NONE; bool baroBMP280Write(uint8_t reg, uint8_t data) { @@ -152,6 +156,12 @@ bool bmp280Detect(baro_t *baro) if (bmp280InitDone) return true; +#if defined(USE_SPI) && defined(BMP280_SPI_INSTANCE) + bmp280CsPin = IOGetByTag(IO_TAG(BMP280_CS_PIN)); + IOInit(bmp280CsPin, OWNER_SYSTEM, RESOURCE_SPI); + IOConfigGPIO(bmp280CsPin, SPI_IO_CS_CFG); +#endif + delay(20); baroBMP280Read(BMP280_CHIP_ID_REG, 1, &bmp280_chip_id); /* read Chip Id */ @@ -204,6 +214,11 @@ static void bmp280_get_up(void) baroBMP280Read(BMP280_PRESSURE_MSB_REG, BMP280_DATA_FRAME_SIZE, data); bmp280_up = (int32_t)((((uint32_t)(data[0])) << 12) | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4)); bmp280_ut = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) | ((uint32_t)data[5] >> 4)); + +#ifdef DEBUG_BMP280 + debug[0] = bmp280_up; + debug[1] = bmp280_ut; +#endif } // Returns temperature in DegC, resolution is 0.01 DegC. Output value of "5123" equals 51.23 DegC @@ -249,6 +264,11 @@ STATIC_UNIT_TESTED void bmp280_calculate(int32_t *pressure, int32_t *temperature t = bmp280_compensate_T(bmp280_ut); p = bmp280_compensate_P(bmp280_up); +#ifdef DEBUG_BMP280 + debug[2] = t; + debug[3] = p; +#endif + if (pressure) *pressure = (int32_t)(p / 256); if (temperature) diff --git a/src/main/drivers/barometer_ms5611.c b/src/main/drivers/barometer_ms5611.c index 70bf8f656..aa2a04db9 100644 --- a/src/main/drivers/barometer_ms5611.c +++ b/src/main/drivers/barometer_ms5611.c @@ -24,14 +24,14 @@ #include "barometer.h" -#include "gpio.h" +#include "io.h" #include "system.h" #include "bus_i2c.h" #include "bus_spi.h" #include "build_config.h" -#define DEBUG_MS5611 +//#define DEBUG_MS5611 #ifndef MS5611_I2C_INSTANCE #define MS5611_I2C_INSTANCE I2C_DEVICE @@ -69,33 +69,13 @@ STATIC_UNIT_TESTED uint32_t ms5611_up; // static result of pressure measurement STATIC_UNIT_TESTED uint16_t ms5611_c[PROM_NB]; // on-chip ROM static uint8_t ms5611_osr = CMD_ADC_4096; -typedef bool (*baroMS5611ReadRegisterFunc)(uint8_t reg_, uint8_t len_, uint8_t *buf); -typedef bool (*baroMS5611WriteRegisterFunc)(uint8_t reg_, uint8_t data); - -typedef struct baroMS5611Config_s { - baroMS5611ReadRegisterFunc read; - baroMS5611WriteRegisterFunc write; -} baroMS5611Config_t; - -baroMS5611Config_t baroMS5611config; - -#ifdef USE_I2C -bool baroMS5611WriteI2C(uint8_t reg, uint8_t data) -{ - return i2cWrite(MS5611_I2C_INSTANCE, MS5611_ADDR, reg, data); -} - -bool baroMS5611ReadI2C(uint8_t reg, uint8_t length, uint8_t *data) -{ - return i2cRead(MS5611_I2C_INSTANCE, MS5611_ADDR, reg, length, data); -} -#endif - #if defined(USE_SPI) && defined(MS5611_SPI_INSTANCE) -#define DISABLE_MS5611 GPIO_SetBits(MS5611_CS_GPIO, MS5611_CS_PIN) -#define ENABLE_MS5611 GPIO_ResetBits(MS5611_CS_GPIO, MS5611_CS_PIN) +#define DISABLE_MS5611 IOHi(ms5611CsPin) +#define ENABLE_MS5611 IOLo(ms5611CsPin) + +static IO_t ms5611CsPin = IO_NONE; -bool baroMS5611WriteSPI(uint8_t reg, uint8_t data) +bool baroMS5611Write(uint8_t reg, uint8_t data) { ENABLE_MS5611; delayMicroseconds(1); @@ -106,7 +86,7 @@ bool baroMS5611WriteSPI(uint8_t reg, uint8_t data) return true; } -bool baroMS5611ReadSPI(uint8_t reg, uint8_t length, uint8_t *data) +bool baroMS5611Read(uint8_t reg, uint8_t length, uint8_t *data) { bool ack = false; @@ -118,6 +98,16 @@ bool baroMS5611ReadSPI(uint8_t reg, uint8_t length, uint8_t *data) return ack; } +#else +bool baroMS5611Write(uint8_t reg, uint8_t data) +{ + return i2cWrite(MS5611_I2C_INSTANCE, MS5611_ADDR, reg, data); +} + +bool baroMS5611Read(uint8_t reg, uint8_t length, uint8_t *data) +{ + return i2cRead(MS5611_I2C_INSTANCE, MS5611_ADDR, reg, length, data); +} #endif bool ms5611Detect(baro_t *baro) @@ -126,23 +116,16 @@ bool ms5611Detect(baro_t *baro) uint8_t sig; int i; - delay(10); // No idea how long the chip takes to power-up, but let's make it 10ms - -#ifdef USE_I2C - ack = i2cRead(MS5611_I2C_INSTANCE, MS5611_ADDR, CMD_PROM_RD, 1, &sig); - if (ack) { - baroMS5611config.read = baroMS5611ReadI2C; - baroMS5611config.write = baroMS5611WriteI2C; - } -#endif #if defined(USE_SPI) && defined(MS5611_SPI_INSTANCE) - ack = baroMS5611ReadSPI(CMD_PROM_RD, 1, &sig); - if (ack) { - baroMS5611config.read = baroMS5611ReadSPI; - baroMS5611config.write = baroMS5611WriteSPI; - } + ms5611CsPin = IOGetByTag(IO_TAG(MS5611_CS_PIN)); + IOInit(ms5611CsPin, OWNER_SYSTEM, RESOURCE_SPI); + IOConfigGPIO(ms5611CsPin, SPI_IO_CS_CFG); #endif - else + + delay(10); // No idea how long the chip takes to power-up, but let's make it 10ms + + ack = baroMS5611Read(CMD_PROM_RD, 1, &sig); + if (!ack) return false; ms5611_reset(); @@ -167,14 +150,14 @@ bool ms5611Detect(baro_t *baro) static void ms5611_reset(void) { - baroMS5611config.write(CMD_RESET, 1); + baroMS5611Write(CMD_RESET, 1); delayMicroseconds(2800); } static uint16_t ms5611_prom(int8_t coef_num) { uint8_t rxbuf[2] = { 0, 0 }; - baroMS5611config.read(CMD_PROM_RD + coef_num * 2, 2, rxbuf); // send PROM READ command + baroMS5611Read(CMD_PROM_RD + coef_num * 2, 2, rxbuf); // send PROM READ command return rxbuf[0] << 8 | rxbuf[1]; } @@ -211,13 +194,13 @@ STATIC_UNIT_TESTED int8_t ms5611_crc(uint16_t *prom) static uint32_t ms5611_read_adc(void) { uint8_t rxbuf[3]; - baroMS5611config.read(CMD_ADC_READ, 3, rxbuf); // read ADC + baroMS5611Read(CMD_ADC_READ, 3, rxbuf); // read ADC return (rxbuf[0] << 16) | (rxbuf[1] << 8) | rxbuf[2]; } static void ms5611_start_ut(void) { - baroMS5611config.write(CMD_ADC_CONV + CMD_ADC_D2 + ms5611_osr, 1); // D2 (temperature) conversion start! + baroMS5611Write(CMD_ADC_CONV + CMD_ADC_D2 + ms5611_osr, 1); // D2 (temperature) conversion start! } static void ms5611_get_ut(void) @@ -230,7 +213,7 @@ static void ms5611_get_ut(void) static void ms5611_start_up(void) { - baroMS5611config.write(CMD_ADC_CONV + CMD_ADC_D1 + ms5611_osr, 1); // D1 (pressure) conversion start! + baroMS5611Write(CMD_ADC_CONV + CMD_ADC_D1 + ms5611_osr, 1); // D1 (pressure) conversion start! } static void ms5611_get_up(void) diff --git a/src/main/drivers/compass_hmc5883l.c b/src/main/drivers/compass_hmc5883l.c index ff8c0b2a5..b77c193de 100644 --- a/src/main/drivers/compass_hmc5883l.c +++ b/src/main/drivers/compass_hmc5883l.c @@ -31,6 +31,7 @@ #include "nvic.h" #include "gpio.h" #include "bus_i2c.h" +#include "bus_spi.h" #include "light_led.h" #include "drivers/exti.h" @@ -151,15 +152,90 @@ void hmc5883_extiHandler(extiCallbackRec_t* cb) } #endif +#if defined(USE_SPI) && defined(HMC5883_SPI_INSTANCE) +#define DISABLE_HMC5883 IOHi(hmc5883CsPin) +#define ENABLE_HMC5883 IOLo(hmc5883CsPin) + +static IO_t hmc5883CsPin = IO_NONE; + +bool baroHMC5883WriteRegister(uint8_t reg, uint8_t data) +{ +// spiSetDivisor(HMC5883_SPI_INSTANCE, 16); + + ENABLE_HMC5883; + delayMicroseconds(1); + spiTransferByte(HMC5883_SPI_INSTANCE, reg); + spiTransferByte(HMC5883_SPI_INSTANCE, data); + DISABLE_HMC5883; + + return true; +} + +bool baroHMC5883Read(uint8_t reg, uint8_t length, uint8_t *data) +{ + bool ack = false; + +// spiSetDivisor(HMC5883_SPI_INSTANCE, 16); + + ENABLE_HMC5883; + delayMicroseconds(1); + spiTransferByte(HMC5883_SPI_INSTANCE, reg | 0x80); // read transaction + ack = spiTransfer(HMC5883_SPI_INSTANCE, data, NULL, length); + DISABLE_HMC5883; + + return ack; +} + +bool baroHMC5883Write(uint8_t reg, uint8_t data) { + + uint8_t in; + uint8_t attemptsRemaining = 20; + +// spiSetDivisor(HMC5883_SPI_INSTANCE, 16); + + baroHMC5883WriteRegister(reg, data); + delayMicroseconds(10); + + do { + baroHMC5883Read(reg, 1, &in); + if (in == data) { + return true; + } else { + debug[3]++; + baroHMC5883WriteRegister(reg, data); + delayMicroseconds(10); + } + } while (attemptsRemaining--); + return false; +} +#else +bool baroHMC5883Read(uint8_t reg, uint8_t length, uint8_t *data) +{ + return i2cRead(HMC5883L_I2C_INSTANCE, MAG_ADDRESS, reg, length, data); +} + +bool baroHMC5883Write(uint8_t reg, uint8_t data) +{ + return i2cWrite(HMC5883L_I2C_INSTANCE, MAG_ADDRESS, reg, data); +} +#endif + + bool hmc5883lDetect(mag_t* mag, const hmc5883Config_t *hmc5883ConfigToUse) { bool ack = false; - uint8_t sig = 0; + uint8_t buf[3]; + +#if defined(USE_SPI) && defined(HMC5883_SPI_INSTANCE) + hmc5883CsPin = IOGetByTag(IO_TAG(HMC5883_CS_PIN)); + IOInit(hmc5883CsPin, OWNER_SYSTEM, RESOURCE_SPI); + IOConfigGPIO(hmc5883CsPin, SPI_IO_CS_CFG); +#endif hmc5883Config = hmc5883ConfigToUse; - ack = i2cRead(HMC5883L_I2C_INSTANCE, MAG_ADDRESS, 0x0A, 1, &sig); - if (!ack || sig != 'H') + ack = baroHMC5883Read(0x0A, 3, buf); + if (!ack || buf[0] != 'H') // || buf[1] != '4' || buf[2] != '3') return false; mag->init = hmc5883lInit; @@ -183,15 +259,15 @@ void hmc5883lInit(void) } #endif delay(50); - i2cWrite(HMC5883L_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFA, 0x010 + HMC_POS_BIAS); // Reg A DOR = 0x010 + MS1, MS0 set to pos bias + baroHMC5883Write(HMC58X3_R_CONFA, 0x010 + HMC_POS_BIAS); // Reg A DOR = 0x010 + MS1, MS0 set to pos bias // Note that the very first measurement after a gain change maintains the same gain as the previous setting. // The new gain setting is effective from the second measurement and on. - i2cWrite(HMC5883L_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFB, 0x60); // Set the Gain to 2.5Ga (7:5->011) + baroHMC5883Write(HMC58X3_R_CONFB, 0x60); // Set the Gain to 2.5Ga (7:5->011) delay(100); hmc5883lRead(magADC); for (i = 0; i < 10; i++) { // Collect 10 samples - i2cWrite(HMC5883L_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_MODE, 1); + baroHMC5883Write(HMC58X3_R_MODE, 1); delay(50); hmc5883lRead(magADC); // Get the raw values in case the scales have already been changed. @@ -209,9 +285,9 @@ void hmc5883lInit(void) } // Apply the negative bias. (Same gain) - i2cWrite(HMC5883L_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFA, 0x010 + HMC_NEG_BIAS); // Reg A DOR = 0x010 + MS1, MS0 set to negative bias. + baroHMC5883Write(HMC58X3_R_CONFA, 0x010 + HMC_NEG_BIAS); // Reg A DOR = 0x010 + MS1, MS0 set to negative bias. for (i = 0; i < 10; i++) { - i2cWrite(HMC5883L_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_MODE, 1); + baroHMC5883Write(HMC58X3_R_MODE, 1); delay(50); hmc5883lRead(magADC); // Get the raw values in case the scales have already been changed. @@ -233,9 +309,9 @@ void hmc5883lInit(void) magGain[Z] = fabsf(660.0f * HMC58X3_Z_SELF_TEST_GAUSS * 2.0f * 10.0f / xyz_total[Z]); // leave test mode - i2cWrite(HMC5883L_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFA, 0x70); // Configuration Register A -- 0 11 100 00 num samples: 8 ; output rate: 15Hz ; normal measurement mode - i2cWrite(HMC5883L_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFB, 0x20); // Configuration Register B -- 001 00000 configuration gain 1.3Ga - i2cWrite(HMC5883L_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_MODE, 0x00); // Mode register -- 000000 00 continuous Conversion Mode + baroHMC5883Write(HMC58X3_R_CONFA, 0x70); // Configuration Register A -- 0 11 100 00 num samples: 8 ; output rate: 15Hz ; normal measurement mode + baroHMC5883Write(HMC58X3_R_CONFB, 0x20); // Configuration Register B -- 001 00000 configuration gain 1.3Ga + baroHMC5883Write(HMC58X3_R_MODE, 0x00); // Mode register -- 000000 00 continuous Conversion Mode delay(100); if (!bret) { // Something went wrong so get a best guess @@ -263,7 +339,7 @@ bool hmc5883lRead(int16_t *magData) { uint8_t buf[6]; - bool ack = i2cRead(HMC5883L_I2C_INSTANCE, MAG_ADDRESS, MAG_DATA_REGISTER, 6, buf); + bool ack = baroHMC5883Read(MAG_DATA_REGISTER, 6, buf); if (!ack) { return false; } diff --git a/src/main/target/ALIENFLIGHTF4/target.h b/src/main/target/ALIENFLIGHTF4/target.h index 4d262b0cf..9bf32e53f 100644 --- a/src/main/target/ALIENFLIGHTF4/target.h +++ b/src/main/target/ALIENFLIGHTF4/target.h @@ -48,25 +48,24 @@ #define USE_GYRO_SPI_MPU9250 #define GYRO_MPU9250_ALIGN CW270_DEG +#define HMC5883_CS_PIN PA15 +#define HMC5883_SPI_INSTANCE SPI3 + #define MAG #define USE_MAG_HMC5883 -//#define MAG_HMC5883_ALIGN CW180_DEG -#define USE_MAG_AK8963 -#define MAG_AK8963_ALIGN CW270_DEG +#define MAG_HMC5883_ALIGN CW180_DEG +//#define USE_MAG_AK8963 +//#define MAG_AK8963_ALIGN CW270_DEG -#define MS5611_CS_GPIO GPIOA -#define MS5611_CS_PIN GPIO_Pin_15 -#define MS5611_CS_GPIO_CLK_PERIPHERAL RCC_AHB1Periph_GPIOA +#define MS5611_CS_PIN PA15 #define MS5611_SPI_INSTANCE SPI3 -//#define BMP280_CS_GPIO GPIOA -//#define BMP280_CS_PIN GPIO_Pin_15 -//#define BMP280_CS_GPIO_CLK_PERIPHERAL RCC_AHB1Periph_GPIOA +//#define BMP280_CS_PIN PA15 //#define BMP280_SPI_INSTANCE SPI3 #define BARO -#define USE_BARO_MS5611 -//#define USE_BARO_BMP280 +//#define USE_BARO_MS5611 +#define USE_BARO_BMP280 #define USE_SDCARD