#include "drivers/i2c/i2c.h" #include "app/thermo/tsensor_ll.h" #include "stm32l1xx_hal.h" #include "stm32l1xx_hal_i2c.h" #include "stm32l1xx_hal_gpio.h" #include "core/main.h" #include "core/csect.h" #include "core/config_pins.h" #define pI2CHandle (&I2C_Handle) #define GENERAL_TIMEOUT 100 // Due to USB interrupt there is a latency #define WRITE_ADDRESS_TIMEOUT GENERAL_TIMEOUT #define WRITE_CONFIG_TIMEOUT GENERAL_TIMEOUT #define READ_CONFIG_TIMEOUT GENERAL_TIMEOUT #define READ_TEMP_TIMEOUT GENERAL_TIMEOUT static bool TSensor_Init(); static void TSensor_DeInit(); static bool TSensor_GetMomentaryTemp( tTSensorTemp * temp ); // Typical startup time is 4us for AD74xx, let it be 10us #define AD74XX_POWERUP_TIME_us (10) // 4us typical // Typical conversion time for AD74xx, let it be 40us #define AD74XX_CONVERSION_TIME_us (40) // 25us typical #define AD74XX_REG_TEMPERATURE 0x0 #define AD74XX_REG_CONFIGURATION 0x1 #define AD7414_REG_THIGH 0x2 #define AD7414_REG_TLOW 0x3 // AD74xx sensor peroforms the single conversions // during 4ms startup time plus 29us conversion time #define AD74XX_ONESHOT_DELAY_us ((AD74XX_POWERUP_TIME_us)+(AD74XX_CONVERSION_TIME_us)) #pragma pack(push,1) typedef union { #if THERMO_SENSOR_MODEL == AD7414 struct ad7414 { uint8_t test_mode: 2; uint8_t one_shot: 1; uint8_t alert_reset: 1; uint8_t alert_polarity: 1; uint8_t alert_disable: 1; uint8_t i2c_filter: 1; uint8_t power_down: 1; }; #endif #if THERMO_SENSOR_MODEL == AD7415 struct ad7415 { uint8_t test_mode: 2; uint8_t one_shot: 1; uint8_t test_mode_2: 3; uint8_t i2c_filter: 1; uint8_t power_down: 1; }; #endif uint8_t rawbyte; } sTSensorConfig; #pragma pack(pop) static bool AD74XX_ReadConfiguration( sTSensorConfig * pcfg ); static bool AD74XX_WriteConfiguration( sTSensorConfig cfg ); static bool AD74XX_ReadTemperature( uint8_t * pData, size_t nBytes ); #if THERMO_SENSOR_POWERCONTROL_HW #if THERMO_SENSOR_POWERCONTROL_HW_KEEPPOWERED #if THERMO_SENSOR_POWERCONTROL_HW_LAZYCONFIG static bool Sensor_Configured = false; #endif #endif #endif const sI2CTempSensorHandle_t I2CTempSensor = { .Init = TSensor_Init, .DeInit = TSensor_DeInit, .GetTemp = TSensor_GetMomentaryTemp }; static bool TSensor_Init() { #if THERMO_SENSOR_POWERCONTROL_HW // Deinitialize I2C with the lines pulled down pI2CHandle->DeInit( eI2CPinMode_KeepPullDown ); // Enable sensor VCC power // Deliver the sensor power directly from the MCU Pin PB5 { // Initialize POWER PIN GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = CONFIG_PIN__TSENS_PWR; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(CONFIG_PORT__TSENS_PWR, &GPIO_InitStruct); HAL_GPIO_WritePin( CONFIG_PORT__TSENS_PWR, CONFIG_PIN__TSENS_PWR, GPIO_PIN_SET ); // It is required to wait for some time while sensor starting up HAL_Wait_us( AD74XX_POWERUP_TIME_us ); } #endif #if (THERMO_SENSOR_POWERCONTROL_HW != 0) && (THERMO_SENSOR_POWERCONTROL_HW_KEEPPOWERED != 0) bool ret = pI2CHandle->Init( eI2CPinMode_KeepPullUp ); #else bool ret = pI2CHandle->Init( eI2CPinMode_Default ); #endif if( ret ) { ret = false; // It is required to wait for some time while sensor starting up // Typical startup time is 4us for AD7414 HAL_Wait_us( AD74XX_POWERUP_TIME_us ); #if THERMO_SENSOR_POWERCONTROL_HW #if THERMO_SENSOR_POWERCONTROL_HW_KEEPPOWERED #if THERMO_SENSOR_POWERCONTROL_HW_LAZYCONFIG if( ! Sensor_Configured ) #endif #endif #endif { sTSensorConfig sensor_cfg; // Read configuration register if( AD74XX_ReadConfiguration( &sensor_cfg ) ) { sensor_cfg.one_shot = 0; // One-Shot conversion - disabled sensor_cfg.power_down = 1; // Enable POWER-DOWN mode (without periodical conversion) sensor_cfg.i2c_filter = 1; // Enable I2C-pins filtering #if THERMO_SENSOR_MODEL == AD7414 sensor_cfg.alert_reset = 0; // Disable ALERT function sensor_cfg.alert_polarity = 0; // Disable ALERT function sensor_cfg.alert_disable = 1; // Disable ALERT function #endif // Write configuration register: if( AD74XX_WriteConfiguration( sensor_cfg ) ) { // Now the sensor is power-down mode #if THERMO_SENSOR_POWERCONTROL_HW #if THERMO_SENSOR_POWERCONTROL_HW_KEEPPOWERED #if THERMO_SENSOR_POWERCONTROL_HW_LAZYCONFIG Sensor_Configured = true; #endif #endif #endif ret = true; } } } #if THERMO_SENSOR_POWERCONTROL_HW #if THERMO_SENSOR_POWERCONTROL_HW_KEEPPOWERED #if THERMO_SENSOR_POWERCONTROL_HW_LAZYCONFIG else ret = true; #endif #endif #endif } if( !ret ) { TSensor_DeInit(); } return ret; } static void TSensor_DeInit() { #if THERMO_SENSOR_POWERCONTROL_HW #if THERMO_SENSOR_POWERCONTROL_HW_KEEPPOWERED == 0 // Disable sensor VCC power // The sensor power is delivered directly from the MCU Pin PB5 { // Disable this pin GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = CONFIG_PIN__TSENS_PWR; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(CONFIG_PORT__TSENS_PWR, &GPIO_InitStruct); // #if THERMO_SENSOR_POWERCONTROL_HW_LAZYCONFIG // Sensor_Configured = false; // #endif } #endif #endif #if (THERMO_SENSOR_POWERCONTROL_HW != 0) && (THERMO_SENSOR_POWERCONTROL_HW_KEEPPOWERED != 0) pI2CHandle->DeInit(eI2CPinMode_KeepPullUp); #else pI2CHandle->DeInit(eI2CPinMode_Default); #endif } static bool AD74XX_WriteConfiguration( sTSensorConfig cfg ) { #if THERMO_SENSOR_MODEL == AD7414 cfg.test_mode = 0; #endif #if THERMO_SENSOR_MODEL == AD7415 cfg.test_mode = 0; cfg.test_mode_2 = 0; #endif uint8_t write_transaction[2] = { [0] = AD74XX_REG_CONFIGURATION, [1] = cfg.rawbyte }; if( HAL_OK == pI2CHandle->Transmit( THERMO_SENSOR_8bit_ADDRESS, write_transaction, sizeof(write_transaction), WRITE_CONFIG_TIMEOUT ) ) { return true; } return false; } static bool AD74XX_ReadConfiguration( sTSensorConfig * pcfg ) { uint8_t register_address = AD74XX_REG_CONFIGURATION; if( NULL != pcfg ) { if( HAL_OK == pI2CHandle->Transmit( THERMO_SENSOR_8bit_ADDRESS, ®ister_address, 1, WRITE_ADDRESS_TIMEOUT ) ) { if( HAL_OK == pI2CHandle->Receive( THERMO_SENSOR_8bit_ADDRESS, &pcfg->rawbyte, 1, READ_CONFIG_TIMEOUT ) ) { return true; } } } return false; } static bool AD74XX_ReadTemperature( uint8_t * pData, size_t nBytes ) { uint8_t register_address = AD74XX_REG_TEMPERATURE; if( NULL != pData && (nBytes>0) ) { if( HAL_OK == pI2CHandle->Transmit( THERMO_SENSOR_8bit_ADDRESS, ®ister_address, 1, WRITE_ADDRESS_TIMEOUT ) ) { if( nBytes > 2 ) nBytes = 2; // maximum 2 bytes if( HAL_OK == pI2CHandle->Receive( THERMO_SENSOR_8bit_ADDRESS, pData, nBytes, READ_TEMP_TIMEOUT ) ) { return true; } } } return false; } static bool TSensor_GetMomentaryTemp( tTSensorTemp * temp ) { sTSensorConfig sensor_cfg; // Read configuration register if( AD74XX_ReadConfiguration( &sensor_cfg ) ) { sensor_cfg.power_down = 1; // set the POWER-DOWN mode (do not measure by itself) sensor_cfg.one_shot = 1; // set ONE-SHOT measuing mode if( AD74XX_WriteConfiguration( sensor_cfg ) ) { HAL_Wait_us( AD74XX_ONESHOT_DELAY_us ); uint8_t raw_temp[2]; if( AD74XX_ReadTemperature( raw_temp, sizeof(raw_temp) ) ) { *((uint16_t*)temp) = ((uint16_t)raw_temp[0] << 8) | (uint16_t)raw_temp[1]; return true; } } } return false; }