Files
edgetx-gx12/radio/src/targets/common/arm/stm32/csd203_sensor.cpp
T

430 lines
12 KiB
C++

/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "csd203_sensor.h"
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "delays_driver.h"
#include "edgetx_types.h"
#include "hal.h"
#include "rtos.h"
#include "stm32_exti_driver.h"
#include "stm32_gpio_driver.h"
#include "stm32_hal.h"
#include "stm32_hal_ll.h"
#include "stm32_i2c_driver.h"
#include "hal/i2c_driver.h"
// clang-format off
/* CSD203 Regsistor map */
#define CONFIGURATION 0X00
/*Read Only*/
#define SHUNT_VOLTAGE 0X01
#define BUS_VOLTAGE 0X02
#define POWER 0X03
#define CURRENT 0x04
/*Read Only*/
#define CALIBRATION 0x05
#define MASKENABLE 0x06
#define ALERTLIMIT 0x07
#define ManufacturerID 0xFE //Manufacturer ID Register
#define DieID 0xFF //Die ID Register
#define ManIDCode 0x4153 //CHIP ID
/*Calibration Calculation parameter*/
/* This Parameter Gain*10000K*/
#define CalParam 51200
/* ↓ add your shunt here ↓ */
#define CSD_CONFIG_Rs_1mR 1
#define CSD_CONFIG_Rs_2mR 2
#define CSD_CONFIG_Rs_5mR 5
#define CSD_CONFIG_Rs_10mR 10
#define CSD_CONFIG_Rs_20mR 20
#define CSD_CONFIG_Rs_50mR 50
#define CSD_CONFIG_CurrentLsb1mA 10
#define CSD_CONFIG_CurrentLsb2mA 20
#define CSD_CONFIG_CurrentLsb5mA 50
#define CSD_CONFIG_CurrentLsb10mA 100
#define CSD_CONFIG_CurrentLsb20mA 200
/*Calibration Calculation parameter*/
/* CSD203 Regsistor Config*/
#define CSD_CONFIG_RST 1
#define CSD_CONFIG_UnRST 0
#define CSD_CONFIG_Avg1 0
#define CSD_CONFIG_Avg4 1
#define CSD_CONFIG_Avg16 2
#define CSD_CONFIG_Avg64 3
#define CSD_CONFIG_Avg128 4
#define CSD_CONFIG_Avg256 5
#define CSD_CONFIG_Avg512 6
#define CSD_CONFIG_Avg1024 7
#define CSD_CONFIG_VBUS_CT1_1mS 4
#define CSD_CONFIG_VShunt_CT1_1mS 4
#define CSD_CONFIG_ShuntBus_CON 7
#define CSD_CONFIG_ADDR_A1_GND_A0_GND 64
#define CSD_CONFIG_ADDR_A1_GND_VS_GND 65
#define CSD_CONFIG_ADDR_A1_GND_SDA_GND 66
#define CSD_CONFIG_ADDR_A1_GND_SCL_GND 67
#define CSD_CONFIG_ADDR_A1_VS_A0_GND 68
#define CSD_CONFIG_ADDR_A1_VS_A0_VS 69
#define CSD_CONFIG_ADDR_A1_VS_A0_SDA 70
#define CSD_CONFIG_ADDR_A1_VS_A0_SCL 71
#define CSD_CONFIG_ADDR_A1_SDA_A0_GND 72
#define CSD_CONFIG_ADDR_A1_SDA_A0_VS 73
#define CSD_CONFIG_ADDR_A1_SDA_A0_SDA 74
#define CSD_CONFIG_ADDR_A1_SDA_A0_SCL 75
#define CSD_CONFIG_ADDR_A1_SCL_A0_GND 76
#define CSD_CONFIG_ADDR_A1_SCL_A0_VS 77
#define CSD_CONFIG_ADDR_A1_SCL_A0_SDA 78
#define CSD_CONFIG_ADDR_A1_SCL_A0_SCL 79
/******************/
/*CSD Alert Option*/
/******************/
/*Vshunt Voltage Over Voltage*/
#define CSD_ALERT_VShunt_OVA_ON 1
#define CSD_ALERT_VShunt_OVA_OFF 0
/*Vshunt Voltage Under Voltage*/
#define CSD_ALERT_VShunt_UVA_ON 1
#define CSD_ALERT_VShunt_UVA_OFF 0
/*VBus Voltage Over Voltage*/
#define CSD_ALERT_VBUS_OVA_ON 1
#define CSD_ALERT_VBUS_OVA_OFF 0
/*VBus Voltage Under Voltage*/
#define CSD_ALERT_VBUS_UVA_ON 1
#define CSD_ALERT_VBUS_UVA_OFF 0
/* Power Over Limit */
#define CSD_ALERT_Power_Over_ON 1
#define CSD_ALERT_Power_Over_OFF 0
/* ADC Coversion Ready */
#define CSD_ALERT_CoversionReady_ON 1
#define CSD_ALERT_CoversionReady_OFF 0
#define CSD_ALERT_CNVR_FLAG_ON 1
#define CSD_ALERT_CNVR_FLAG_OFF 0
/* ALERT Function Flag and Alert latch Work Together */
#define CSD_ALERT_ALERT_FLAG_ON 1
#define CSD_ALERT_ALERT_FLAG_OFF 0
#define CSD_ALERT_ALERT_Latch_ON 1
#define CSD_ALERT_ALERT_Latch_OFF 0
/*Power over flow */
#define CSD_ALERT_OVF_ON 1
#define CSD_ALERT_OVF_OFF 0
/*Alert Pin */
#define CSD_ALERT_APOL_ActiveLow 1
#define CSD_ALERT_APOL_ActiveHigh 0
// clang-format on
/*CSD Basic Configuration struct*/
typedef struct {
uint8_t DeviceADDR;
uint8_t RST;
uint8_t Average;
uint8_t VBUS_Conv_Time;
uint8_t VShunt_Conv_Time;
uint8_t Mode;
uint16_t CurrentLSB;
uint16_t Rshunt;
} CSD_CONFIG;
/*CSD Basic Configuration struct*/
/*CSD ALERT Configuration struct*/
typedef struct {
uint8_t VShunt_OVA;
uint8_t VShuntUVA;
uint8_t VBUS_OVA;
uint8_t VBUS_UVA;
uint8_t Power_OVER_Limit;
uint8_t CNVR;
uint8_t ALERT_FLAG;
uint8_t CNVR_FLAG;
uint8_t OVF;
uint8_t APOL;
uint8_t ALERT_Latch;
} CSD_ALERT;
/*CSD ALERT Configuration struct*/
void CSD203_Init(CSD_CONFIG *CSD203_CFG); // Initialise CSD203 config
uint16_t CSD203_ReadVbus(CSD_CONFIG *CSD203_CFG); // Read Vbus Voltage
uint16_t CSD203_ReadRshunt(CSD_CONFIG *CSD203_CFG); // Read Rshunt
uint16_t CSD203_ReadPower(CSD_CONFIG *CSD203_CFG); // Read Power
uint16_t CSD203_ReadCurrent(CSD_CONFIG *CSD203_CFG); // Read Current
void IIC_DUT_W(uint8_t addr, uint8_t reg, uint16_t data);
uint16_t IIC_DUT_R(uint8_t addr, uint8_t reg);
bool CSD203MainInitFlag = false;
bool CSD203InInitFlag = false;
bool CSD203ExtInitFlag = false;
bool IICReadStatusFlag = false;
static uint16_t csd203extvbus = 0;
static CSD_CONFIG CSD203_MainSensorCFG;
static CSD_CONFIG CSD203_InSensorCFG;
static CSD_CONFIG CSD203_ExtSensorCFG;
bool I2C_CSD203_WriteRegister(uint8_t I2C_ADDR, uint8_t reg, uint8_t *buf,
uint8_t len)
{
uint8_t uAddrAndBuf[6];
uAddrAndBuf[0] = (uint8_t)(reg & 0x00FF);
if (len > 0) {
for (int i = 0; i < len; i++) {
uAddrAndBuf[i + 1] = buf[i];
}
}
if (stm32_i2c_master_tx(I2C_Bus_1, I2C_ADDR, uAddrAndBuf, len + 1, 100) <
0) {
TRACE("I2C B1 ERROR: WriteRegister failed");
return false;
}
return true;
}
bool I2C_CSD203_ReadRegister(uint8_t I2C_ADDR, uint8_t reg, uint8_t *buf,
uint8_t len)
{
uint8_t uRegAddr[2];
// uRegAddr[0] = (uint8_t)((reg & 0xFF00) >> 8);
uRegAddr[0] = (uint8_t)(reg & 0x00FF);
if (stm32_i2c_master_tx(I2C_Bus_1, I2C_ADDR, uRegAddr, 1, 100) < 0) {
TRACE("I2C B1 ERROR: ReadRegister write reg address failed");
return false;
}
if (stm32_i2c_master_rx(I2C_Bus_1, I2C_ADDR, buf, len, 100) < 0) {
TRACE("I2C B1 ERROR: ReadRegister read reg address failed");
return false;
}
return true;
}
void IIC_DUT_W(uint8_t addr, uint8_t reg, uint16_t data)
{
uint8_t buf[2];
buf[0] = data >> 8;
buf[1] = data & 0xff;
I2C_CSD203_WriteRegister(addr, reg, buf, 2);
}
uint16_t IIC_DUT_R(uint8_t addr, uint8_t reg)
{
uint8_t buf[2];
I2C_CSD203_ReadRegister(addr, reg, buf, 2);
return buf[0] << 8 | buf[1];
}
void CSD203_Init(CSD_CONFIG *CSD203_CFG)
{
uint16_t Data = 0, ADDR = 0;
Data |= (CSD203_CFG->RST) << 15;
Data |= (CSD203_CFG->Average) << 9;
Data |= (CSD203_CFG->VBUS_Conv_Time) << 5;
Data |= (CSD203_CFG->VShunt_Conv_Time) << 2;
Data |= CSD203_CFG->Mode;
ADDR = (CSD203_CFG->DeviceADDR);
IIC_DUT_W(ADDR, CONFIGURATION, Data);
Data = CalParam / ((CSD203_CFG->CurrentLSB) * (CSD203_CFG->Rshunt));
IIC_DUT_W(ADDR, CALIBRATION, Data);
}
/*Read Vbus*/
uint16_t CSD203_ReadVbus(CSD_CONFIG *CSD203_CFG)
{
uint16_t Data = 0, ADDR = 0;
ADDR = (CSD203_CFG->DeviceADDR);
Data = IIC_DUT_R(ADDR, BUS_VOLTAGE);
return Data;
}
/*Read Rshunt*/
uint16_t CSD203_ReadRshunt(CSD_CONFIG *CSD203_CFG)
{
uint16_t Data = 0, ADDR = 0;
ADDR = (CSD203_CFG->DeviceADDR);
Data = IIC_DUT_R(ADDR, SHUNT_VOLTAGE);
return Data;
}
/*Read Power*/
uint16_t CSD203_ReadPower(CSD_CONFIG *CSD203_CFG)
{
uint16_t Data = 0, ADDR = 0;
ADDR = (CSD203_CFG->DeviceADDR);
Data = IIC_DUT_R(ADDR, POWER);
return Data;
}
uint16_t CSD203_ReadCurrent(CSD_CONFIG *CSD203_CFG)
{
uint16_t Data = 0, ADDR = 0;
ADDR = (CSD203_CFG->DeviceADDR);
Data = IIC_DUT_R(ADDR, CURRENT);
return Data;
}
uint16_t CSD203_ReadCONFIGURATION(CSD_CONFIG *CSD203_CFG)
{
uint16_t Data = 0, ADDR = 0;
ADDR = (CSD203_CFG->DeviceADDR);
Data = IIC_DUT_R(ADDR, CONFIGURATION);
return Data;
}
uint16_t CSD203_ReadManufacturerID(CSD_CONFIG *CSD203_CFG)
{
uint16_t Data = 0, ADDR = 0;
ADDR = (CSD203_CFG->DeviceADDR);
Data = IIC_DUT_R(ADDR, ManufacturerID);
return Data;
}
void IICcsd203init(void)
{
if (i2c_init(I2C_Bus_1) < 0) {
return; //err
}
}
void ReIICcsd203init(void)
{
if (i2c_init(I2C_Bus_1) < 0) {
return; //err
}
}
void initCSD203(void)
{
CSD203MainInitFlag = false;
CSD203InInitFlag = false;
CSD203ExtInitFlag = false;
// TRACE("202 test ..."); //A0=CLK A1=SDA RadioSky
CSD203_MainSensorCFG.RST = CSD_CONFIG_RST;
CSD203_MainSensorCFG.Average = CSD_CONFIG_Avg16;
CSD203_MainSensorCFG.VBUS_Conv_Time = CSD_CONFIG_VBUS_CT1_1mS;
CSD203_MainSensorCFG.VShunt_Conv_Time = CSD_CONFIG_VShunt_CT1_1mS;
CSD203_MainSensorCFG.Rshunt = CSD_CONFIG_Rs_10mR;
CSD203_MainSensorCFG.CurrentLSB = CSD_CONFIG_CurrentLsb1mA;
CSD203_MainSensorCFG.Mode = 7;
CSD203_MainSensorCFG.DeviceADDR = CSD_CONFIG_ADDR_A1_VS_A0_GND; // 100 0100
// CSD203_MainSensorCFG.DeviceADDR=CSD_CONFIG_ADDR_A1_GND_A0_GND;
CSD203_InSensorCFG.RST = CSD_CONFIG_RST;
CSD203_InSensorCFG.Average = CSD_CONFIG_Avg16;
CSD203_InSensorCFG.VBUS_Conv_Time = CSD_CONFIG_VBUS_CT1_1mS;
CSD203_InSensorCFG.VShunt_Conv_Time = CSD_CONFIG_VShunt_CT1_1mS;
CSD203_InSensorCFG.Rshunt = CSD_CONFIG_Rs_10mR;
CSD203_InSensorCFG.CurrentLSB = CSD_CONFIG_CurrentLsb1mA;
CSD203_InSensorCFG.Mode = 7;
CSD203_InSensorCFG.DeviceADDR = CSD_CONFIG_ADDR_A1_VS_A0_VS; // 100 0101
// CSD203_InSensorCFG.DeviceADDR=CSD_CONFIG_ADDR_A1_GND_A0_GND;
CSD203_ExtSensorCFG.RST = CSD_CONFIG_RST;
CSD203_ExtSensorCFG.Average = CSD_CONFIG_Avg16;
CSD203_ExtSensorCFG.VBUS_Conv_Time = CSD_CONFIG_VBUS_CT1_1mS;
CSD203_ExtSensorCFG.VShunt_Conv_Time = CSD_CONFIG_VShunt_CT1_1mS;
CSD203_ExtSensorCFG.Rshunt = CSD_CONFIG_Rs_10mR;
CSD203_ExtSensorCFG.CurrentLSB = CSD_CONFIG_CurrentLsb1mA;
CSD203_ExtSensorCFG.Mode = 7;
CSD203_ExtSensorCFG.DeviceADDR = CSD_CONFIG_ADDR_A1_GND_VS_GND; // 100 0001
// CSD203_ExtSensorCFG.DeviceADDR=CSD_CONFIG_ADDR_A1_GND_A0_GND;
CSD203_Init(&CSD203_MainSensorCFG);
delay_ms(1);
uint16_t cfg = CSD203_ReadManufacturerID(&CSD203_MainSensorCFG);
if (cfg == ManIDCode) {
CSD203_ReadCurrent(&CSD203_MainSensorCFG);
CSD203MainInitFlag = true;
}
delay_ms(5);
CSD203_Init(&CSD203_InSensorCFG);
delay_ms(1);
cfg = CSD203_ReadManufacturerID(&CSD203_InSensorCFG);
if (cfg == ManIDCode) {
CSD203_ReadCurrent(&CSD203_InSensorCFG);
CSD203InInitFlag = true;
}
delay_ms(5);
CSD203_Init(&CSD203_ExtSensorCFG);
delay_ms(1);
cfg = CSD203_ReadManufacturerID(&CSD203_ExtSensorCFG);
if (cfg == ManIDCode) {
CSD203_ReadCurrent(&CSD203_ExtSensorCFG);
CSD203ExtInitFlag = true;
}
}
static uint16_t getCSD203BatteryVoltage(void)
{ // 1000=1000mV
return csd203extvbus;
}
uint16_t getBatteryVoltage()
{
return getCSD203BatteryVoltage() / 10;
}
void readCSD203(void)
{ // 5ms
static uint16_t GetSenSorStep = 0;
if (IICReadStatusFlag == true) return;
IICReadStatusFlag = true;
if (GetSenSorStep == 0 && CSD203MainInitFlag == true) {
CSD203_ReadCurrent(&CSD203_MainSensorCFG);
CSD203_ReadVbus(&CSD203_MainSensorCFG);
} else if (GetSenSorStep == 1 && CSD203InInitFlag == true) {
CSD203_ReadCurrent(&CSD203_InSensorCFG);
CSD203_ReadVbus(&CSD203_InSensorCFG);
} else if (GetSenSorStep == 2 && CSD203ExtInitFlag == true) {
CSD203_ReadCurrent(&CSD203_ExtSensorCFG);
csd203extvbus = (CSD203_ReadVbus(&CSD203_ExtSensorCFG) * 1.25);
// TRACE("Vbat=%d\r",csd203extvbus);
}
IICReadStatusFlag = false;
if (++GetSenSorStep >= 3) GetSenSorStep = 0;
}