mirror of https://github.com/rusefi/wideband.git
max3185x: support also max31856 (#253)
(cherry picked from commit 703985dc709afad2df0ff69d929751894da51b34) Co-authored-by: Andrey Gusakov <dron0gus@gmail.com>
This commit is contained in:
parent
e52e4a0768
commit
4667e991d4
|
@ -151,7 +151,7 @@ CPPSRC = $(ALLCPPSRC) \
|
|||
heater_control.cpp \
|
||||
pid.cpp \
|
||||
pump_control.cpp \
|
||||
max31855.cpp \
|
||||
max3185x.cpp \
|
||||
uart.cpp \
|
||||
auxout.cpp \
|
||||
livedata.cpp \
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "wideband_config.h"
|
||||
|
||||
#include "max31855.h"
|
||||
#include "max3185x.h"
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "sampling.h"
|
||||
#include "pump_dac.h"
|
||||
#include "heater_control.h"
|
||||
#include "max31855.h"
|
||||
#include "max3185x.h"
|
||||
#include "fault.h"
|
||||
|
||||
#include <rusefi/arrays.h>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "uart.h"
|
||||
#include "io_pins.h"
|
||||
#include "auxout.h"
|
||||
#include "max31855.h"
|
||||
#include "max3185x.h"
|
||||
#include "port.h"
|
||||
#include "tunerstudio.h"
|
||||
#include "indication.h"
|
||||
|
|
|
@ -1,163 +0,0 @@
|
|||
#include <math.h>
|
||||
|
||||
#include "io_pins.h"
|
||||
#include "wideband_config.h"
|
||||
#include "bit.h"
|
||||
#include "livedata.h"
|
||||
|
||||
#include "max31855.h"
|
||||
|
||||
#if (EGT_CHANNELS > 0)
|
||||
|
||||
static SPIConfig spi_config[2] =
|
||||
{
|
||||
{
|
||||
.circular = false,
|
||||
.end_cb = NULL,
|
||||
.ssport = EGT_CS0_PORT,
|
||||
.sspad = EGT_CS0_PIN,
|
||||
.cr1 =
|
||||
/* SPI_CR1_LSBFIRST | */
|
||||
((3 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | /* div = 16 */
|
||||
/* SPI_CR1_CPOL | */ // = 0
|
||||
SPI_CR1_CPHA | // = 1
|
||||
0,
|
||||
.cr2 = 0
|
||||
},
|
||||
{
|
||||
.circular = false,
|
||||
.end_cb = NULL,
|
||||
.ssport = EGT_CS1_PORT,
|
||||
.sspad = EGT_CS1_PIN,
|
||||
.cr1 =
|
||||
/* SPI_CR1_LSBFIRST | */
|
||||
((3 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | /* div = 16 */
|
||||
/* SPI_CR1_CPOL | */ // = 0
|
||||
SPI_CR1_CPHA | // = 1
|
||||
0,
|
||||
.cr2 = 0
|
||||
}
|
||||
};
|
||||
|
||||
static Max31855 instances[] = {&spi_config[0], &spi_config[1]};
|
||||
|
||||
static Max31855Thread EgtThread(instances);
|
||||
|
||||
int Max31855::spi_rx(uint32_t *data)
|
||||
{
|
||||
uint8_t rx[4];
|
||||
|
||||
/* Acquire ownership of the bus. */
|
||||
spiAcquireBus(EGT_SPI_DRIVER);
|
||||
/* Setup transfer parameters. */
|
||||
spiStart(EGT_SPI_DRIVER, spi);
|
||||
/* Slave Select assertion. */
|
||||
spiSelect(EGT_SPI_DRIVER);
|
||||
//spiExchange(spi, 4, tx, rx);
|
||||
spiReceive(EGT_SPI_DRIVER, 4, rx);
|
||||
/* Slave Select de-assertion. */
|
||||
spiUnselect(EGT_SPI_DRIVER);
|
||||
/* Ownership release. */
|
||||
spiReleaseBus(EGT_SPI_DRIVER);
|
||||
|
||||
if (data) {
|
||||
*data = (rx[0] << 24) |
|
||||
(rx[1] << 16) |
|
||||
(rx[2] << 8) |
|
||||
(rx[3] << 0);
|
||||
}
|
||||
|
||||
/* no errors for now */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Max31855::readPacket()
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
int ret = spi_rx(&data);
|
||||
|
||||
/* TODO: also check for 0x00000000? */
|
||||
if ((ret) || (data == 0xffffffff)) {
|
||||
livedata.state = MAX31855_NO_REPLY;
|
||||
|
||||
ret = -1;
|
||||
} else if (data & BIT(16)) {
|
||||
if (data & BIT(0)) {
|
||||
livedata.state = MAX31855_OPEN_CIRCUIT;
|
||||
} else if (data & BIT(1)) {
|
||||
livedata.state = MAX31855_SHORT_TO_GND;
|
||||
} else if (data & BIT(2)) {
|
||||
livedata.state = MAX31855_SHORT_TO_VCC;
|
||||
}
|
||||
|
||||
ret = -1;
|
||||
} else {
|
||||
livedata.state = MAX31855_OK;
|
||||
|
||||
/* 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;
|
||||
/* extend sign */
|
||||
tmp = tmp << 2;
|
||||
tmp = tmp >> 2; /* shifting right signed is not a good idea */
|
||||
temperature = (float) tmp * 0.25;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
coldJunctionTemperature = NAN;
|
||||
livedata.coldJunctionTemperature = 0;
|
||||
temperature = NAN;
|
||||
livedata.temperature = 0;
|
||||
} else {
|
||||
/* update livedata: float to int */
|
||||
livedata.coldJunctionTemperature = coldJunctionTemperature;
|
||||
livedata.temperature = temperature;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Max31855Thread::ThreadTask() {
|
||||
|
||||
while (true) {
|
||||
for (int ch = 0; ch < EGT_CHANNELS; ch++) {
|
||||
Max31855 ¤t = max31855[ch];
|
||||
current.readPacket();
|
||||
}
|
||||
|
||||
chThdSleepMilliseconds(500);
|
||||
}
|
||||
}
|
||||
|
||||
void StartEgt() {
|
||||
EgtThread.Start();
|
||||
}
|
||||
|
||||
Max31855* getEgtDrivers() {
|
||||
return instances;
|
||||
}
|
||||
|
||||
template<>
|
||||
const livedata_egt_s* getLiveData(size_t ch)
|
||||
{
|
||||
if (ch < EGT_CHANNELS)
|
||||
return &getEgtDrivers()[ch].livedata;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<>
|
||||
const livedata_egt_s* getLiveData(size_t)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif /* EGT_CHANNELS > 0 */
|
|
@ -0,0 +1,266 @@
|
|||
#include <math.h>
|
||||
|
||||
#include "io_pins.h"
|
||||
#include "wideband_config.h"
|
||||
#include "bit.h"
|
||||
#include "livedata.h"
|
||||
|
||||
#include "max3185x.h"
|
||||
|
||||
#if (EGT_CHANNELS > 0)
|
||||
|
||||
static SPIConfig spi_config[2] =
|
||||
{
|
||||
{
|
||||
.circular = false,
|
||||
.end_cb = NULL,
|
||||
.ssport = EGT_CS0_PORT,
|
||||
.sspad = EGT_CS0_PIN,
|
||||
.cr1 =
|
||||
/* SPI_CR1_LSBFIRST | */
|
||||
((3 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | /* div = 16 */
|
||||
/* SPI_CR1_CPOL | */ // = 0
|
||||
SPI_CR1_CPHA | // = 1
|
||||
0,
|
||||
.cr2 = 0
|
||||
},
|
||||
{
|
||||
.circular = false,
|
||||
.end_cb = NULL,
|
||||
.ssport = EGT_CS1_PORT,
|
||||
.sspad = EGT_CS1_PIN,
|
||||
.cr1 =
|
||||
/* SPI_CR1_LSBFIRST | */
|
||||
((3 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | /* div = 16 */
|
||||
/* SPI_CR1_CPOL | */ // = 0
|
||||
SPI_CR1_CPHA | // = 1
|
||||
0,
|
||||
.cr2 = 0
|
||||
}
|
||||
};
|
||||
|
||||
static Max3185x instances[] = {&spi_config[0], &spi_config[1]};
|
||||
|
||||
static Max3185xThread EgtThread(instances);
|
||||
|
||||
int Max3185x::spi_txrx(uint8_t tx[], uint8_t rx[], size_t n)
|
||||
{
|
||||
/* Acquire ownership of the bus. */
|
||||
spiAcquireBus(EGT_SPI_DRIVER);
|
||||
/* Setup transfer parameters. */
|
||||
spiStart(EGT_SPI_DRIVER, spi);
|
||||
/* Slave Select assertion. */
|
||||
spiSelect(EGT_SPI_DRIVER);
|
||||
spiExchange(EGT_SPI_DRIVER, n, tx, rx);
|
||||
/* Slave Select de-assertion. */
|
||||
spiUnselect(EGT_SPI_DRIVER);
|
||||
/* Ownership release. */
|
||||
spiReleaseBus(EGT_SPI_DRIVER);
|
||||
|
||||
/* no errors for now */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Max3185x::spi_rx32(uint32_t *data)
|
||||
{
|
||||
int ret;
|
||||
/* dummy */
|
||||
uint8_t tx[4] = {0};
|
||||
uint8_t rx[4];
|
||||
|
||||
ret = spi_txrx(tx, rx, 4);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
if (data) {
|
||||
*data = (rx[0] << 24) |
|
||||
(rx[1] << 16) |
|
||||
(rx[2] << 8) |
|
||||
(rx[3] << 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Max3185x::detect()
|
||||
{
|
||||
uint8_t rx[4];
|
||||
/* read MASK, CJHF, CJLF */
|
||||
uint8_t tx[4] = {0x02, 0x00, 0x00, 0x00};
|
||||
uint32_t data;
|
||||
|
||||
int ret = spi_txrx(tx, rx, 4);
|
||||
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;
|
||||
}
|
||||
if (data != 0xffffffff) {
|
||||
type = MAX31855_TYPE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
livedata.state = MAX3185X_NO_REPLY;
|
||||
type = UNKNOWN_TYPE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Max3185x::readPacket31855()
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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[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;
|
||||
|
||||
/* update livedata: float to int */
|
||||
livedata.coldJunctionTemperature = coldJunctionTemperature;
|
||||
livedata.temperature = temperature;
|
||||
|
||||
livedata.state = MAX3185X_OK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Max3185x::readPacket31856()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == MAX31855_TYPE) {
|
||||
return readPacket31855();
|
||||
} else if (type == MAX31856_TYPE) {
|
||||
return readPacket31856();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Max3185xThread::ThreadTask() {
|
||||
|
||||
while (true) {
|
||||
for (int ch = 0; ch < EGT_CHANNELS; ch++) {
|
||||
Max3185x ¤t = max3185x[ch];
|
||||
current.readPacket();
|
||||
}
|
||||
|
||||
chThdSleepMilliseconds(500);
|
||||
}
|
||||
}
|
||||
|
||||
void StartEgt() {
|
||||
EgtThread.Start();
|
||||
}
|
||||
|
||||
Max3185x* getEgtDrivers() {
|
||||
return instances;
|
||||
}
|
||||
|
||||
template<>
|
||||
const livedata_egt_s* getLiveData(size_t ch)
|
||||
{
|
||||
if (ch < EGT_CHANNELS)
|
||||
return &getEgtDrivers()[ch].livedata;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<>
|
||||
const livedata_egt_s* getLiveData(size_t)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif /* EGT_CHANNELS > 0 */
|
|
@ -6,12 +6,18 @@
|
|||
#include "thread_controller.h"
|
||||
|
||||
typedef enum {
|
||||
MAX31855_OK = 0,
|
||||
MAX31855_OPEN_CIRCUIT = 1,
|
||||
MAX31855_SHORT_TO_GND = 2,
|
||||
MAX31855_SHORT_TO_VCC = 3,
|
||||
MAX31855_NO_REPLY = 4,
|
||||
} Max31855State;
|
||||
UNKNOWN_TYPE = 0,
|
||||
MAX31855_TYPE = 1,
|
||||
MAX31856_TYPE = 2,
|
||||
} Max3185xType;
|
||||
|
||||
typedef enum {
|
||||
MAX3185X_OK = 0,
|
||||
MAX3185X_OPEN_CIRCUIT = 1,
|
||||
MAX3185X_SHORT_TO_GND = 2,
|
||||
MAX3185X_SHORT_TO_VCC = 3,
|
||||
MAX3185X_NO_REPLY = 4,
|
||||
} Max3185xState;
|
||||
|
||||
/* livedata: +96/112 offset, size = 16 */
|
||||
struct livedata_egt_s {
|
||||
|
@ -30,38 +36,43 @@ const struct livedata_egt_s * getEgtLiveDataStructAddr(const int ch);
|
|||
|
||||
#if (EGT_CHANNELS > 0)
|
||||
|
||||
#define MAX31855_THREAD_STACK (512)
|
||||
#define MAX31855_THREAD_PRIO (NORMALPRIO + 1)
|
||||
#define MAX3185X_THREAD_STACK (512)
|
||||
#define MAX3185X_THREAD_PRIO (NORMALPRIO + 1)
|
||||
|
||||
class Max31855 {
|
||||
class Max3185x {
|
||||
public:
|
||||
Max31855(SPIConfig *spi) {
|
||||
Max3185x(SPIConfig *spi) {
|
||||
this->spi = spi;
|
||||
}
|
||||
livedata_egt_s livedata;
|
||||
/* do we need float temperatures? */
|
||||
float coldJunctionTemperature;
|
||||
float temperature;
|
||||
Max3185xType type;
|
||||
int readPacket();
|
||||
private:
|
||||
SPIConfig *spi;
|
||||
int spi_rx(uint32_t *data);
|
||||
int detect();
|
||||
int readPacket31855();
|
||||
int readPacket31856();
|
||||
int spi_rx32(uint32_t *data);
|
||||
int spi_txrx(uint8_t tx[], uint8_t rx[], size_t n);
|
||||
};
|
||||
|
||||
class Max31855Thread : public ThreadController<MAX31855_THREAD_STACK> {
|
||||
class Max3185xThread : public ThreadController<MAX3185X_THREAD_STACK> {
|
||||
public:
|
||||
Max31855Thread(Max31855 max31855[EGT_CHANNELS])
|
||||
: ThreadController("egt", MAX31855_THREAD_PRIO)
|
||||
Max3185xThread(Max3185x max3185x[EGT_CHANNELS])
|
||||
: ThreadController("egt", MAX3185X_THREAD_PRIO)
|
||||
{
|
||||
this->max31855 = max31855;
|
||||
this->max3185x = max3185x;
|
||||
}
|
||||
|
||||
void ThreadTask() override;
|
||||
private:
|
||||
Max31855 *max31855;
|
||||
Max3185x *max3185x;
|
||||
};
|
||||
|
||||
void StartEgt();
|
||||
Max31855* getEgtDrivers();
|
||||
Max3185x* getEgtDrivers();
|
||||
|
||||
#endif // (EGT_CHANNELS > 0)
|
|
@ -5,7 +5,7 @@
|
|||
#include "lambda_conversion.h"
|
||||
#include "sampling.h"
|
||||
#include "heater_control.h"
|
||||
#include "max31855.h"
|
||||
#include "max3185x.h"
|
||||
#include "fault.h"
|
||||
#include "uart.h"
|
||||
|
||||
|
|
Loading…
Reference in New Issue