mirror of
https://github.com/mck1117/wideband.git
synced 2026-09-30 09:57:06 -04:00
Max3185x update (#328)
* max3185x: more const * max3185x: deinit SPI bus after use * max3185x: improve chip type detection * max3185x: no magic numbers * max3185x: check spi_txrx return value * max3185x: simplify, fix negative values for max31856 * max3185x: SPI ts buffer is const * max3185x: paranoid check for max31856 * max3185x: start in proper state * max3185x: communication error counter to TS
This commit is contained in:
@@ -125,11 +125,13 @@ AFR1_heater = scalar, U08, 93, "", 1, 0
|
||||
EGT0_temp = scalar, F32, 96, "C", 1, 0
|
||||
EGT0_coldJunction = scalar, F32, 100, "C", 1, 0
|
||||
EGT0_state = scalar, U08, 104, "", 1, 0
|
||||
EGT0_commErrors = scalar, U32, 108, "n", 1, 0
|
||||
|
||||
; EGT1
|
||||
EGT1_temp = scalar, F32, 112, "C", 1, 0
|
||||
EGT1_coldJunction = scalar, F32, 116, "C", 1, 0
|
||||
EGT1_state = scalar, U08, 120, "", 1, 0
|
||||
EGT1_commErrors = scalar, U32, 124, "n", 1, 0
|
||||
|
||||
; TODO: something is wrong with these
|
||||
Aux0InputSig = { (Aux0InputSel == 0) ? AFR0_lambda : ((Aux0InputSel == 1) ? AFR1_lambda : ((Aux0InputSel == 2) ? EGT0_temp : EGT1_temp)) }
|
||||
@@ -205,6 +207,7 @@ gaugeCategory = EGT channel 0
|
||||
EGT0_Gauge = EGT0_temp, "0: EGT", "C", 0.0, 1600.0, 100.0, 250.0, 900.0, 1000.0, 0, 0
|
||||
EGT0_ColdJunctionGauge = EGT0_coldJunction, "0: EGT CJ", "C", 0.0, 130.0, -55.0, -20.0, 95.0, 105.0, 1, 1
|
||||
EGT0_StateGauge = EGT0_state, "0: EGT state", "", 0.0, 5.0, 0.0, 0.0, 0.5, 0.5, 0, 0
|
||||
EGT0_CommErrorsGauge = EGT0_commErrors,"0: EGT comm errors", "", 0.0, 10, 0.0, 0.0, 1, 1, 0, 0
|
||||
|
||||
; EGT1
|
||||
gaugeCategory = EGT channel 1
|
||||
@@ -212,6 +215,7 @@ gaugeCategory = EGT channel 1
|
||||
EGT1_Gauge = EGT1_temp, "1: EGT", "C", 0.0, 1600.0, 100.0, 250.0, 900.0, 1000.0, 0, 0
|
||||
EGT1_ColdJunctionGauge = EGT1_coldJunction, "1: EGT CJ", "C", 0.0, 130.0, -55.0, -20.0, 95.0, 105.0, 1, 1
|
||||
EGT1_StateGauge = EGT1_state, "1: EGT state", "", 0.0, 5.0, 0.0, 0.0, 0.5, 0.5, 0, 0
|
||||
EGT1_CommErrorsGauge = EGT1_commErrors,"1: EGT comm errors", "", 0.0, 10, 0.0, 0.0, 1, 1, 0, 0
|
||||
|
||||
; AUX outputs
|
||||
Aux0InputGauge = { (Aux0InputSel == 0) ? AFR0_AfrGauge : ((Aux0InputSel == 1) ? AFR1_AfrGauge : ((Aux0InputSel == 2) ? EGT0_Gauge : EGT1_Gauge)) }
|
||||
@@ -280,11 +284,13 @@ entry = AFR1_esr, "1: ESR", float, "%.1f"
|
||||
entry = EGT0_temp, "EGT 0: EGT", int, "%d"
|
||||
entry = EGT0_coldJunction, "EGT 0: CJ", int, "%d"
|
||||
entry = EGT0_state, "EGT 0: State", int, "%d"
|
||||
entry = EGT0_commErrors, "EGT 0: comm errors", int, "%d"
|
||||
|
||||
; EGT1
|
||||
entry = EGT1_temp, "EGT 1: EGT", int, "%d"
|
||||
entry = EGT1_coldJunction, "EGT 1: CJ", int, "%d"
|
||||
entry = EGT1_state, "EGT 1: State", int, "%d"
|
||||
entry = EGT1_commErrors, "EGT 1: comm errors", int, "%d"
|
||||
|
||||
[Menu]
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#if (EGT_CHANNELS > 0)
|
||||
|
||||
static SPIConfig spi_config[2] =
|
||||
static const SPIConfig spi_config[EGT_CHANNELS] =
|
||||
{
|
||||
{
|
||||
.circular = false,
|
||||
@@ -43,11 +43,11 @@ static SPIConfig spi_config[2] =
|
||||
}
|
||||
};
|
||||
|
||||
static Max3185x instances[] = {&spi_config[0], &spi_config[1]};
|
||||
static Max3185x instances[EGT_CHANNELS] = {Max3185x(&spi_config[0]), Max3185x(&spi_config[1])};
|
||||
|
||||
static Max3185xThread EgtThread(instances);
|
||||
|
||||
int Max3185x::spi_txrx(uint8_t tx[], uint8_t rx[], size_t n)
|
||||
int Max3185x::spi_txrx(const uint8_t tx[], uint8_t rx[], size_t n)
|
||||
{
|
||||
/* Acquire ownership of the bus. */
|
||||
spiAcquireBus(EGT_SPI_DRIVER);
|
||||
@@ -58,6 +58,8 @@ int Max3185x::spi_txrx(uint8_t tx[], uint8_t rx[], size_t n)
|
||||
spiExchange(EGT_SPI_DRIVER, n, tx, rx);
|
||||
/* Slave Select de-assertion. */
|
||||
spiUnselect(EGT_SPI_DRIVER);
|
||||
/* Bus deinit */
|
||||
spiStop(EGT_SPI_DRIVER);
|
||||
/* Ownership release. */
|
||||
spiReleaseBus(EGT_SPI_DRIVER);
|
||||
|
||||
@@ -85,152 +87,198 @@ int Max3185x::spi_rx32(uint32_t *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Max3185x::detect()
|
||||
{
|
||||
uint8_t rx[4];
|
||||
/* read MASK, CJHF, CJLF */
|
||||
uint8_t tx[4] = {0x02, 0x00, 0x00, 0x00};
|
||||
uint32_t data;
|
||||
// bits D17 and D3 are always expected to be zero
|
||||
#define MAX31855_RESERVED_BITS 0x20008
|
||||
|
||||
int ret = spi_txrx(tx, rx, 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
data = (rx[0] << 24) |
|
||||
(rx[1] << 16) |
|
||||
(rx[2] << 8) |
|
||||
(rx[3] << 0);
|
||||
/* MASK, CJHF, CJLF defaults: 0xff, 0x7f, 0xc0 */
|
||||
if ((data & 0x00ffffff) == 0x00ff7fc0) {
|
||||
/* configure */
|
||||
/* CR0: 50 Hz mode
|
||||
* Change the notch frequency only while in the "Normally Off" mode - not in the Automatic
|
||||
* Conversion mode.*/
|
||||
tx[0] = 0x80;
|
||||
tx[1] = 0x01;
|
||||
spi_txrx(tx, rx, 2);
|
||||
/* CR0: Automatic Conversion mode, OCFAULT = 2, 50Hz mode */
|
||||
tx[1] = BIT(7) | BIT(0) | 2 << 4;
|
||||
/* CR1: 4 samples average, K type */
|
||||
tx[2] = (2 << 4) | (3 << 0);
|
||||
spi_txrx(tx, rx, 3);
|
||||
type = MAX31856_TYPE;
|
||||
return 0;
|
||||
Max3185xType Max3185x::detect()
|
||||
{
|
||||
int ret;
|
||||
uint8_t rx[4];
|
||||
uint8_t tx[4];
|
||||
|
||||
/* try to apply settings to max31956 and then read back settings */
|
||||
// Wr, register 0x00
|
||||
tx[0] = 0x00 | BIT(7);
|
||||
// CR0: 50Hz mode
|
||||
// Change the notch frequency only while in the "Normally Off" mode - not in the Automatic
|
||||
tx[1] = BIT(0);
|
||||
// CR1: 4 samples average, K type
|
||||
// The Thermocouple Voltage Conversion Averaging Mode settings should not be changed while
|
||||
// conversions are taking place.
|
||||
tx[2] = (2 << 4) | (3 << 0);
|
||||
|
||||
// Stop any conversion
|
||||
ret = spi_txrx(tx, rx, 2);
|
||||
if (ret) {
|
||||
return UNKNOWN_TYPE;
|
||||
}
|
||||
if (data != 0xffffffff) {
|
||||
type = MAX31855_TYPE;
|
||||
return 0;
|
||||
|
||||
// Apply notch frequency and averaging
|
||||
ret = spi_txrx(tx, rx, 3);
|
||||
if (ret) {
|
||||
return UNKNOWN_TYPE;
|
||||
}
|
||||
|
||||
// Start Automatic Conversion mode
|
||||
// CR0: Automatic Conversion mode, OCFAULT = 2, 50Hz mode
|
||||
tx[1] = BIT(7) | BIT(0) | (2 << 4);
|
||||
// CR1: 4 samples average, K type
|
||||
tx[2] = (2 << 4) | (3 << 0);
|
||||
ret = spi_txrx(tx, rx, 3);
|
||||
if (ret) {
|
||||
return UNKNOWN_TYPE;
|
||||
}
|
||||
|
||||
/* Now readback settings */
|
||||
tx[0] = 0x00;
|
||||
ret = spi_txrx(tx, rx, 4);
|
||||
if ((rx[1] == tx[1]) && (rx[2] == tx[2])) {
|
||||
return MAX31856_TYPE;
|
||||
}
|
||||
|
||||
/* in case of max31855 we get standart reply with few reserved, always zero bits */
|
||||
uint32_t data = (rx[0] << 24) |
|
||||
(rx[1] << 16) |
|
||||
(rx[2] << 8) |
|
||||
(rx[3] << 0);
|
||||
|
||||
/* MISO is constantly low or high */
|
||||
if ((data == 0xffffffff) || (data == 0x0)) {
|
||||
return UNKNOWN_TYPE;
|
||||
}
|
||||
|
||||
if ((data & MAX31855_RESERVED_BITS) == 0x0) {
|
||||
return MAX31855_TYPE;
|
||||
}
|
||||
|
||||
livedata.state = MAX3185X_NO_REPLY;
|
||||
type = UNKNOWN_TYPE;
|
||||
return -1;
|
||||
|
||||
return UNKNOWN_TYPE;
|
||||
}
|
||||
|
||||
int Max3185x::readPacket31855()
|
||||
Max3185xState Max3185x::readPacket31855()
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
#define MAX33855_FAULT_BIT BIT(16)
|
||||
#define MAX33855_OPEN_BIT BIT(0)
|
||||
#define MAX33855_GND_BIT BIT(1)
|
||||
#define MAX33855_VCC_BIT BIT(2)
|
||||
|
||||
int ret = spi_rx32(&data);
|
||||
|
||||
/* TODO: also check for 0x00000000? */
|
||||
if ((ret) || (data == 0xffffffff)) {
|
||||
livedata.state = MAX3185X_NO_REPLY;
|
||||
|
||||
ret = -1;
|
||||
} else if (data & BIT(16)) {
|
||||
if (data & BIT(0)) {
|
||||
livedata.state = MAX3185X_OPEN_CIRCUIT;
|
||||
} else if (data & BIT(1)) {
|
||||
livedata.state = MAX3185X_SHORT_TO_GND;
|
||||
} else if (data & BIT(2)) {
|
||||
livedata.state = MAX3185X_SHORT_TO_VCC;
|
||||
if ((ret) ||
|
||||
((data & MAX31855_RESERVED_BITS) != 0) ||
|
||||
(data == 0x0) ||
|
||||
(data == 0xffffffff)) {
|
||||
return MAX3185X_NO_REPLY;
|
||||
} else if (data & MAX33855_FAULT_BIT) {
|
||||
if (data & MAX33855_OPEN_BIT) {
|
||||
return MAX3185X_OPEN_CIRCUIT;
|
||||
} else if (data & MAX33855_GND_BIT) {
|
||||
return MAX3185X_SHORT_TO_GND;
|
||||
} else if (data & MAX33855_VCC_BIT) {
|
||||
return MAX3185X_SHORT_TO_VCC;
|
||||
}
|
||||
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
coldJunctionTemperature = NAN;
|
||||
livedata.coldJunctionTemperature = 0;
|
||||
temperature = NAN;
|
||||
livedata.temperature = 0;
|
||||
} else {
|
||||
/* D[15:4] */
|
||||
int16_t tmp = (data >> 4) & 0xfff;
|
||||
/* extend sign */
|
||||
tmp = tmp << 4;
|
||||
tmp = tmp >> 4; /* shifting right signed is not a good idea */
|
||||
coldJunctionTemperature = (float)tmp * 0.0625;
|
||||
/* D[15:4] */
|
||||
int16_t tmp = (data >> 4) & 0xfff;
|
||||
/* extend sign */
|
||||
tmp = tmp << 4;
|
||||
tmp = tmp >> 4; /* shifting right signed is not a good idea */
|
||||
coldJunctionTemperature = (float)tmp * 0.0625;
|
||||
|
||||
/* D[31:18] */
|
||||
tmp = (data >> 18) & 0x3fff;
|
||||
/* D[31:18] */
|
||||
tmp = (data >> 18) & 0x3fff;
|
||||
/* extend sign */
|
||||
tmp = tmp << 2;
|
||||
tmp = tmp >> 2; /* shifting right signed is not a good idea */
|
||||
temperature = (float) tmp * 0.25;
|
||||
|
||||
return MAX3185X_OK;
|
||||
}
|
||||
|
||||
Max3185xState Max3185x::readPacket31856()
|
||||
{
|
||||
uint8_t rx[1 + 6];
|
||||
/* read one dummy byte, Cold-Junction temperature MSB, LSB, Linearized TC temperature 3 bytes and Fault Status */
|
||||
const uint8_t tx[1 + 6] = {0x0a};
|
||||
|
||||
int ret = spi_txrx(tx, rx, sizeof(rx));
|
||||
|
||||
if (ret) {
|
||||
return MAX3185X_NO_REPLY;
|
||||
} else if (rx[6] & BIT(0)) {
|
||||
return MAX3185X_OPEN_CIRCUIT;
|
||||
} else if (rx[6] & BIT(1)) {
|
||||
return MAX3185X_SHORT_TO_VCC;
|
||||
}
|
||||
|
||||
// Paranoid check.
|
||||
bool allZero = true;
|
||||
for (int i = 1; i < 6; i++) {
|
||||
if (rx[i] != 0x00) {
|
||||
allZero = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allZero) {
|
||||
return MAX3185X_NO_REPLY;
|
||||
}
|
||||
|
||||
if (1) {
|
||||
// 10 bit before point and 7 bits after
|
||||
int32_t tmp = (rx[3] << 11) | (rx[4] << 3) | (rx[5] >> 5);
|
||||
/* extend sign: move top bit 18 to 31 */
|
||||
tmp = tmp << 13;
|
||||
tmp = tmp >> 13; /* shifting right signed is not a good idea */
|
||||
temperature = ((float)tmp) / 128.0;
|
||||
}
|
||||
if (1) {
|
||||
int16_t tmp = (rx[1] << 6) | (rx[2] >> 2);
|
||||
/* extend sign */
|
||||
tmp = tmp << 2;
|
||||
tmp = tmp >> 2; /* shifting right signed is not a good idea */
|
||||
temperature = (float) tmp * 0.25;
|
||||
|
||||
/* update livedata: float to int */
|
||||
livedata.coldJunctionTemperature = coldJunctionTemperature;
|
||||
livedata.temperature = temperature;
|
||||
|
||||
livedata.state = MAX3185X_OK;
|
||||
coldJunctionTemperature = ((float)tmp) / 64.0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return MAX3185X_OK;
|
||||
}
|
||||
|
||||
int Max3185x::readPacket31856()
|
||||
Max3185xState Max3185x::readPacket()
|
||||
{
|
||||
uint8_t rx[7];
|
||||
/* read Cold-Junction temperature MSB, LSB, Linearized TC temperature 3 bytes and Fault Status */
|
||||
uint8_t tx[7] = {0x0a};
|
||||
|
||||
int ret = spi_txrx(tx, rx, 7);
|
||||
|
||||
if (rx[6] & BIT(0)) {
|
||||
livedata.state = MAX3185X_OPEN_CIRCUIT;
|
||||
ret = -1;
|
||||
} else if (rx[6] & BIT(1)) {
|
||||
livedata.state = MAX3185X_SHORT_TO_VCC;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
coldJunctionTemperature = NAN;
|
||||
livedata.coldJunctionTemperature = 0;
|
||||
temperature = NAN;
|
||||
livedata.temperature = 0;
|
||||
} else {
|
||||
/* update livedata: float to int */
|
||||
coldJunctionTemperature = (float)(rx[1] << 8 | rx[2]) / 256.0;
|
||||
temperature = (float)((rx[3] << 11) | (rx[4] << 3) | (rx[5] >> 5)) / 128.0;
|
||||
livedata.coldJunctionTemperature = coldJunctionTemperature;
|
||||
livedata.temperature = temperature;
|
||||
|
||||
livedata.state = MAX3185X_OK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Max3185x::readPacket()
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (type == UNKNOWN_TYPE) {
|
||||
ret = detect();
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
type = detect();
|
||||
if (type == UNKNOWN_TYPE) {
|
||||
livedata.state = MAX3185X_NO_REPLY;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == MAX31855_TYPE) {
|
||||
return readPacket31855();
|
||||
livedata.state = readPacket31855();
|
||||
} else if (type == MAX31856_TYPE) {
|
||||
return readPacket31856();
|
||||
livedata.state = readPacket31856();
|
||||
}
|
||||
|
||||
return -1;
|
||||
if (livedata.state == MAX3185X_OK) {
|
||||
/* update livedata: float to int */
|
||||
livedata.coldJunctionTemperature = coldJunctionTemperature;
|
||||
livedata.temperature = temperature;
|
||||
} else {
|
||||
coldJunctionTemperature = NAN;
|
||||
livedata.coldJunctionTemperature = 0;
|
||||
temperature = NAN;
|
||||
livedata.temperature = 0;
|
||||
}
|
||||
|
||||
/* in case of communication problems - reinit */
|
||||
if (livedata.state == MAX3185X_NO_REPLY) {
|
||||
livedata.commErrors++;
|
||||
type = UNKNOWN_TYPE;
|
||||
}
|
||||
|
||||
return MAX3185X_OK;
|
||||
}
|
||||
|
||||
void Max3185xThread::ThreadTask() {
|
||||
|
||||
@@ -26,6 +26,8 @@ struct livedata_egt_s {
|
||||
float temperature;
|
||||
float coldJunctionTemperature;
|
||||
uint8_t state;
|
||||
uint8_t pad0[3];
|
||||
uint32_t commErrors;
|
||||
} __attribute__((packed));
|
||||
uint8_t pad[16];
|
||||
};
|
||||
@@ -41,22 +43,22 @@ const struct livedata_egt_s * getEgtLiveDataStructAddr(const int ch);
|
||||
|
||||
class Max3185x {
|
||||
public:
|
||||
Max3185x(SPIConfig *spi) {
|
||||
Max3185x(const SPIConfig *spi) {
|
||||
this->spi = spi;
|
||||
}
|
||||
livedata_egt_s livedata;
|
||||
/* do we need float temperatures? */
|
||||
float coldJunctionTemperature;
|
||||
float temperature;
|
||||
Max3185xType type;
|
||||
int readPacket();
|
||||
Max3185xType type = UNKNOWN_TYPE;
|
||||
Max3185xState readPacket();
|
||||
private:
|
||||
SPIConfig *spi;
|
||||
int detect();
|
||||
int readPacket31855();
|
||||
int readPacket31856();
|
||||
const SPIConfig *spi;
|
||||
Max3185xType detect();
|
||||
Max3185xState readPacket31855();
|
||||
Max3185xState readPacket31856();
|
||||
int spi_rx32(uint32_t *data);
|
||||
int spi_txrx(uint8_t tx[], uint8_t rx[], size_t n);
|
||||
int spi_txrx(const uint8_t tx[], uint8_t rx[], size_t n);
|
||||
};
|
||||
|
||||
class Max3185xThread : public ThreadController<MAX3185X_THREAD_STACK> {
|
||||
|
||||
Reference in New Issue
Block a user