/* * bme_config.c * * Created on: Jan 11, 2022 * */ #include #include #include /* POSIX Header files */ #include #include #include /* Driver Header files */ #include #include #include #include #include /* Driver configuration */ #include "ti_drivers_config.h" extern Display_Handle display; extern SPI_Handle spi; /* =========== INIT BME FUNCTION ============ */ uint8_t init_bme(struct bme *bme){ //#ifdef DEBUG Display_printf(display, 0, 0,"Initializing BME.\n"); //#endif // Set up the SPI parameters SPI_Params_init(&(bme->spiParams)); bme->spiParams.frameFormat = SPI_POL1_PHA1; bme->spiParams.bitRate = 100000; bme->spiParams.dataSize = 8; // 8-bit data size bme->spiParams.mode = SPI_MASTER; bme->spi = SPI_open(CONFIG_SPI_0, &(bme->spiParams)); if (bme->spi == NULL) { Display_printf(display, 0, 0, "SPI open failed.\n"); return 0; } else{ Display_printf(display, 0, 0, "SPI open passed.\n"); } /// Variable to store the status codes uint8_t rslt; // Copy the pointer to the global version gBME = bme; rslt = bme68x_interface_init(&(bme->bme_dev), BME68X_SPI_INTF); _check_rslt("Interface_init", rslt); rslt = bme68x_init(&(bme->bme_dev)); _check_rslt("bme68x_init", rslt); rslt = config_bme(bme); _check_rslt("set config", rslt); rslt = config_heatr(bme); _check_rslt("set heatr config", rslt); return 1; } /* ========== CONFIGURE BME =========== */ uint8_t config_bme(struct bme *bme){ bme->conf.filter = BME68X_FILTER_OFF; bme->conf.odr = BME68X_ODR_NONE; bme->conf.os_hum = BME68X_OS_16X; bme->conf.os_pres = BME68X_OS_1X; bme->conf.os_temp = BME68X_OS_2X; uint8_t rslt = bme68x_set_conf(&(bme->conf), &(bme->bme_dev)); return rslt; } /* ========== CONFIGURE BME GAS HEATER =========== */ uint8_t config_heatr(struct bme *bme){ bme->heatr_conf.enable = BME68X_ENABLE; bme->heatr_conf.heatr_temp = 300; bme->heatr_conf.heatr_dur = 100; uint8_t rslt = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &(bme->heatr_conf), &(bme->bme_dev)); return rslt; } /* ========== GET DATA FROM DEVICE ============ */ uint8_t get_data(struct bme *bme){ uint8_t rslt; // Temp variable for status codes uint32_t del_period; // Temp variable for device delay uint8_t n_fields; // Temp variable for number of data fields retrieved bool gotData = false; // Flag to see if we got all the data Display_printf(display, 0, 0, "GET DATA!!!\n"); while(!gotData){ // While we have not gotten enough data /* Set the operation mode of BME device */ Display_printf(display, 0, 0, "--------Set Operation Mode ------\n"); rslt = bme68x_set_op_mode(BME68X_FORCED_MODE, &(bme->bme_dev)); _check_rslt("bme68x_set_op_mode", rslt); /* Calculate delay period in microseconds */ Display_printf(display, 0, 0, "-------- Calculate Delay ------\n"); del_period = bme68x_get_meas_dur(BME68X_FORCED_MODE, &(bme->conf), &(bme->bme_dev)) + (bme->heatr_conf.heatr_dur * 1000); bme->bme_dev.delay_us(del_period, bme->bme_dev.intf_ptr); Display_printf(display, 0, 0, "-------- Get Data Function ------\n"); /* Check if rslt == BME68X_OK, report or handle if otherwise */ rslt = bme68x_get_data(BME68X_FORCED_MODE, &(bme->data), &n_fields, &(bme->bme_dev)); _check_rslt("bme68x_get_data", rslt); if(n_fields){ // If we got any data we will exit gotData = true; } } return n_fields; // return how many data fields we got } /* ========== INITIALIZE SPI INTERFACE ============ */ int8_t bme68x_interface_init(struct bme68x_dev *bme, uint8_t intf) { uint8_t dev_addr = BME68X_I2C_ADDR_LOW; int8_t rslt = BME68X_OK; bme->read = bme68x_spi_read; bme->write = bme68x_spi_write; bme->intf = BME68X_SPI_INTF; bme->delay_us = bme68x_delay_us; bme->intf_ptr = &dev_addr; bme->amb_temp = 25; /* The ambient temperature in deg C is used for defining the heater temperature */ return rslt; } /* ========== SPI READ IMPLEMENTATION ============ */ BME68X_INTF_RET_TYPE bme68x_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr){ uint8_t txBuffer[len+1]; uint8_t rxBuffer[len+1]; bool transferOK; txBuffer[0] = reg_addr; int i; for(i = 0; i < len; i++){ txBuffer[i+1] = 0x00; } Display_printf(display, 0, 0, "----- Length: 0x%x. -----\n", len); Display_printf(display, 0, 0, "SPI Read Address: 0x%x.\n", txBuffer[0]); gBME->spiTransaction.count = len + 1; gBME->spiTransaction.txBuf = txBuffer; gBME->spiTransaction.rxBuf = rxBuffer; /* Do actual transaction */ GPIO_write(BME_CS, 0); // Drop the CS Line transferOK = SPI_transfer(gBME->spi, &(gBME->spiTransaction)); if (transferOK){ for(i = 0; i < len; i++){ *reg_data = rxBuffer[i+1]; Display_printf(display, 0, 0, "SPI Read Data: 0x%x.\n", rxBuffer[i+1]); } #ifdef DEBUG Display_printf(display, 0, 0,"BME read OK.\n"); #endif } else{ #ifdef DEBUG Display_printf(display, 0, 0,"BME read fail.\n"); #endif } GPIO_write(BME_CS, 1); // Drop the CS Line return 0; } /* ========== SPI WRITE IMPLEMENTATION ============ */ BME68X_INTF_RET_TYPE bme68x_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr){ uint8_t txBuffer[len+1]; bool transferOK; txBuffer[0] = reg_addr; Display_printf(display, 0, 0, "SPI Write Address: 0x%x.\n", txBuffer[0]); int i = 0; for(i = 0; i < len; i++){ txBuffer[i+1] = reg_data[i]; Display_printf(display, 0, 0, "SPI Write Data: 0x%x.\n", txBuffer[i+1]); } gBME->spiTransaction.count = len + 1; gBME->spiTransaction.txBuf = txBuffer; gBME->spiTransaction.rxBuf = NULL; GPIO_write(BME_CS, 0); // Drop the CS Line transferOK = SPI_transfer(gBME->spi, &(gBME->spiTransaction)); if (transferOK){ #ifdef DEBUG Display_printf(display, 0, 0,"BME write OK.\n"); #endif } else{ #ifdef DEBUG Display_printf(display, 0, 0,"BME write not OK.\n"); #endif } GPIO_write(BME_CS, 1); // Drop the CS Line return 0; } /* ========== DELAY IMPLEMENTATION ============ */ void bme68x_delay_us(uint32_t period, void *intf_ptr){ #ifdef DEBUG Display_printf(display, 0, 0,"Waiting %d us.\n", period); #endif Task_sleep(period/Clock_tickPeriod); } /* ========== DEINIT BME ============ */ void deinit_bme(struct bme *bme){ SPI_close(gBME->spi); gBME = NULL; Display_printf(display, 0, 0,"Close SPI.\n"); } /* ========== READ BOSCH STATUS CODES ============ */ void _check_rslt(const char api_name[], int8_t rslt) { #ifdef DEBUG switch (rslt) { case BME68X_OK: Display_printf(display, 0, 0,"API name [%s] Good to go\r\n", api_name); break; case BME68X_E_NULL_PTR: Display_printf(display, 0, 0,"API name [%s] Error [%d] : Null pointer\r\n", api_name, rslt); break; case BME68X_E_COM_FAIL: Display_printf(display, 0, 0,"API name [%s] Error [%d] : Communication failure\r\n", api_name, rslt); break; case BME68X_E_INVALID_LENGTH: Display_printf(display, 0, 0,"API name [%s] Error [%d] : Incorrect length parameter\r\n", api_name, rslt); break; case BME68X_E_DEV_NOT_FOUND: Display_printf(display, 0, 0,"API name [%s] Error [%d] : Device not found\r\n", api_name, rslt); break; case BME68X_E_SELF_TEST: Display_printf(display, 0, 0,"API name [%s] Error [%d] : Self test error\r\n", api_name, rslt); break; case BME68X_W_NO_NEW_DATA: Display_printf(display, 0, 0,"API name [%s] Warning [%d] : No new data found\r\n", api_name, rslt); break; default: Display_printf(display, 0, 0,"API name [%s] Error [%d] : Unknown error code\r\n", api_name, rslt); break; } #endif }