rusefi/firmware/hw_layer/mc33816.cpp

224 lines
5.1 KiB
C++

/*
* @file mc33816.cpp
*
* TL,DR: GDI
*
* The NXP MC33816 is a programmable gate driver IC for precision solenoid control applications.
*
*
* Useful wires:
* 5v, 3(3.3v), Gnd, 12v, VccIO(3v) SPI, DRVEN, RSTB
*
* For MC33816 vs PT2000 differences see
* https://www.nxp.com/docs/en/application-note/AN5203.pdf
*
* @date May 3, 2019
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "pch.h"
#if EFI_MC33816
#include "hardware.h"
#include "mpu_util.h"
static SPIConfig spiCfg = { .circular = false,
.end_cb = NULL,
.ssport = NULL,
.sspad = 0,
.cr1 =
SPI_CR1_16BIT_MODE |
SPI_CR1_MSTR |
//SPI_CR1_BR_1 // 5MHz
SPI_CR1_CPHA | SPI_CR1_BR_0 | SPI_CR1_BR_1 | SPI_CR1_BR_2 | SPI_CR1_SPE,
.cr2 = SPI_CR2_SSOE};
class Pt2001 : public Pt2001Base {
public:
void init();
void initIfNeeded();
protected:
void select() override {
spiSelect(driver);
}
void deselect() override {
spiUnselect(driver);
}
uint16_t sendRecv(uint16_t tx) override {
return spiPolledExchange(driver, tx);
}
// Send `count` number of 16 bit words from `data`
void sendLarge(const uint16_t* data, size_t count) override {
spiSend(driver, count, data);
}
// GPIO reset and enable pins
void setResetB(bool state) override {
resetB.setValue(state);
}
void setDriveEN(bool state) override {
driven.setValue(state);
}
// GPIO inputs for various pins we need
bool readFlag0() const override {
return efiReadPin(engineConfiguration->mc33816_flag0);
}
// Get battery voltage - only try to init chip when powered
float getVbatt() const override {
return Sensor::get(SensorType::BatteryVoltage).value_or(VBAT_FALLBACK_VALUE);
}
// CONFIGURATIONS: currents, timings, voltages
float getBoostVoltage() const override {
return engineConfiguration->mc33_hvolt;
}
// Currents in amps
float getBoostCurrent() const override {
return engineConfiguration->mc33_i_boost;
}
float getPeakCurrent() const override {
return engineConfiguration->mc33_i_peak;
}
float getHoldCurrent() const override {
return engineConfiguration->mc33_i_hold;
}
float getPumpPeakCurrent() const override {
return engineConfiguration->mc33_hpfp_i_peak;
}
float getPumpHoldCurrent() const override {
return engineConfiguration->mc33_hpfp_i_hold;
}
// Timings in microseconds
uint16_t getTpeakOff() const override {
return engineConfiguration->mc33_t_peak_off;
}
uint16_t getTpeakTot() const override {
return engineConfiguration->mc33_t_peak_tot;
}
uint16_t getTbypass() const override {
return engineConfiguration->mc33_t_bypass;
}
uint16_t getTholdOff() const override {
return engineConfiguration->mc33_t_hold_off;
}
uint16_t getTHoldTot() const override {
return engineConfiguration->mc33_t_hold_tot;
}
uint16_t getTBoostMin() const override {
return engineConfiguration->mc33_t_min_boost;
}
uint16_t getTBoostMax() const override {
return engineConfiguration->mc33_t_max_boost;
}
uint16_t getPumpTholdOff() const override {
return engineConfiguration->mc33_hpfp_i_hold_off;
}
uint16_t getPumpTholdTot() const override {
return engineConfiguration->mc33_hpfp_max_hold;
}
// Print out an error message
void onError(const char* why) override {
efiPrintf("PT2001 error: %s", why);
}
void sleepMs(size_t ms) override {
chThdSleepMilliseconds(ms);
}
private:
SPIDriver* driver;
OutputPin resetB;
OutputPin driven;
OutputPin chipSelect;
};
void Pt2001::init() {
//
// see setTest33816EngineConfiguration for default configuration
// Pins
if (!isBrainPinValid(engineConfiguration->mc33816_cs) ||
!isBrainPinValid(engineConfiguration->mc33816_rstb) ||
!isBrainPinValid(engineConfiguration->mc33816_driven)) {
return;
}
if (isBrainPinValid(engineConfiguration->mc33816_flag0)) {
efiSetPadMode("mc33816 flag0", engineConfiguration->mc33816_flag0, getInputMode(PI_DEFAULT));
}
chipSelect.initPin("mc33 CS", engineConfiguration->mc33816_cs /*, &engineConfiguration->csPinMode*/);
// Initialize the chip via ResetB
resetB.initPin("mc33 RESTB", engineConfiguration->mc33816_rstb);
// High Voltage via DRIVEN
driven.initPin("mc33 DRIVEN", engineConfiguration->mc33816_driven);
spiCfg.ssport = getHwPort("mc33816", engineConfiguration->mc33816_cs);
spiCfg.sspad = getHwPin("mc33816", engineConfiguration->mc33816_cs);
// hard-coded for now, just resolve the conflict with SD card!
engineConfiguration->mc33816spiDevice = SPI_DEVICE_3;
driver = getSpiDevice(engineConfiguration->mc33816spiDevice);
if (driver == NULL) {
// error already reported
return;
}
spiStart(driver, &spiCfg);
// addConsoleAction("mc33_stats", showStats);
// addConsoleAction("mc33_restart", mcRestart);
initIfNeeded();
}
static bool isInitialized = false;
void Pt2001::initIfNeeded() {
if (Sensor::get(SensorType::BatteryVoltage).value_or(VBAT_FALLBACK_VALUE) < LOW_VBATT) {
isInitialized = false;
efiPrintf("unhappy mc33 due to battery voltage");
} else {
if (!isInitialized) {
isInitialized = restart();
if (isInitialized) {
efiPrintf("happy mc33/PT2001!");
} else {
efiPrintf("unhappy mc33 fault=%d", (int)fault);
}
}
}
}
static Pt2001 pt;
void initMc33816() {
pt.init();
}
#endif /* EFI_MC33816 */