2014-08-29 07:52:33 -07:00
|
|
|
/**
|
2014-12-15 17:03:49 -08:00
|
|
|
* @file HIP9011.cpp
|
2014-08-29 07:52:33 -07:00
|
|
|
* @brief HIP9011/TPIC8101 driver
|
|
|
|
*
|
|
|
|
* pin1 VDD
|
|
|
|
* pin2 GND
|
|
|
|
*
|
|
|
|
* pin8 Chip Select - CS
|
|
|
|
* pin11 Slave Data Out - MISO-
|
|
|
|
* pin12 Slave Data In - MOSI
|
|
|
|
* pin13 SPI clock - SCLK
|
|
|
|
*
|
2014-12-15 17:03:49 -08:00
|
|
|
* http://www.ti.com/lit/ds/symlink/tpic8101.pdf
|
2014-12-24 18:03:45 -08:00
|
|
|
* http://www.intersil.com/content/dam/Intersil/documents/hip9/hip9011.pdf
|
2014-12-15 17:03:49 -08:00
|
|
|
* http://www.intersil.com/content/dam/Intersil/documents/an97/an9770.pdf
|
|
|
|
* http://e2e.ti.com/cfs-file/__key/telligent-evolution-components-attachments/00-26-01-00-00-42-36-40/TPIC8101-Training.pdf
|
2014-08-29 07:52:33 -07:00
|
|
|
*
|
2014-12-26 12:04:16 -08:00
|
|
|
* SPI frequency: 5MHz max
|
2014-08-29 07:52:33 -07:00
|
|
|
*
|
|
|
|
* @date Nov 27, 2013
|
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2014
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "main.h"
|
2014-12-05 09:03:16 -08:00
|
|
|
#include "engine.h"
|
2014-12-15 17:03:49 -08:00
|
|
|
#include "settings.h"
|
|
|
|
#include "pin_repository.h"
|
2014-12-18 10:05:24 -08:00
|
|
|
#include "hardware.h"
|
|
|
|
#include "rpm_calculator.h"
|
|
|
|
#include "trigger_central.h"
|
2014-08-29 07:52:33 -07:00
|
|
|
|
2014-12-23 19:06:10 -08:00
|
|
|
#if EFI_HIP_9011 || defined(__DOXYGEN__)
|
2014-08-29 07:52:33 -07:00
|
|
|
|
2014-12-26 12:04:16 -08:00
|
|
|
#define HIP_DEBUG FALSE
|
|
|
|
|
2014-12-19 05:03:42 -08:00
|
|
|
extern pin_output_mode_e DEFAULT_OUTPUT;
|
|
|
|
|
|
|
|
static int bandIndex;
|
2015-01-02 06:03:46 -08:00
|
|
|
static int gainIndex;
|
2014-12-26 12:04:16 -08:00
|
|
|
static int intergratorIndex = -1;
|
|
|
|
static bool_t isHip9011Busy = false;
|
2014-12-19 05:03:42 -08:00
|
|
|
|
2014-12-18 10:05:24 -08:00
|
|
|
static scheduling_s startTimer[2];
|
|
|
|
static scheduling_s endTimer[2];
|
|
|
|
|
2014-12-15 17:03:49 -08:00
|
|
|
// 0b01000000
|
|
|
|
#define SET_PRESCALER_CMD 0x40
|
|
|
|
// 0b11100000
|
|
|
|
#define SET_CHANNEL_CMD 0xE0
|
|
|
|
// 0b00000000
|
|
|
|
#define SET_BAND_PASS_CMD 0x0
|
|
|
|
|
2014-12-19 05:03:42 -08:00
|
|
|
// 0b10000000
|
|
|
|
#define SET_GAIN_CMD 0x80
|
|
|
|
|
2014-12-15 17:03:49 -08:00
|
|
|
// 0b01110001
|
2014-12-19 05:03:42 -08:00
|
|
|
#define SET_ADVANCED_MODE 0x71
|
2014-12-15 17:03:49 -08:00
|
|
|
|
2014-08-29 07:52:33 -07:00
|
|
|
static Logging logger;
|
|
|
|
|
2014-12-26 12:04:16 -08:00
|
|
|
#if HIP_DEBUG
|
2014-08-29 07:52:33 -07:00
|
|
|
static THD_WORKING_AREA(htThreadStack, UTILITY_THREAD_STACK_SIZE);
|
2014-12-26 12:04:16 -08:00
|
|
|
#endif
|
2014-08-29 07:52:33 -07:00
|
|
|
|
|
|
|
// SPI_CR1_BR_1 // 5MHz
|
2014-12-24 18:03:45 -08:00
|
|
|
// SPI_CR1_CPHA Clock Phase
|
2014-12-23 18:03:36 -08:00
|
|
|
// todo: nicer method which would mention SPI speed explicitly?
|
2014-08-29 07:52:33 -07:00
|
|
|
|
2014-12-25 18:04:36 -08:00
|
|
|
static SPIConfig spicfg = { NULL,
|
2014-08-29 07:52:33 -07:00
|
|
|
/* HW dependent part.*/
|
2014-12-25 19:03:24 -08:00
|
|
|
NULL, 0,
|
|
|
|
SPI_CR1_MSTR |
|
2014-08-29 07:52:33 -07:00
|
|
|
//SPI_CR1_BR_1 // 5MHz
|
2014-12-25 19:03:24 -08:00
|
|
|
SPI_CR1_CPHA | SPI_CR1_BR_0 | SPI_CR1_BR_1 | SPI_CR1_BR_2 };
|
2014-08-29 07:52:33 -07:00
|
|
|
|
2014-12-25 18:04:36 -08:00
|
|
|
static unsigned char tx_buff[1];
|
|
|
|
static unsigned char rx_buff[1];
|
2014-08-29 07:52:33 -07:00
|
|
|
|
2014-12-26 12:04:16 -08:00
|
|
|
#define SPI_SYNCHRONOUS(value) \
|
|
|
|
spiSelect(driver); \
|
|
|
|
tx_buff[0] = value; \
|
|
|
|
spiExchange(driver, 1, tx_buff, rx_buff); \
|
|
|
|
spiUnselect(driver);
|
|
|
|
|
|
|
|
// todo: make this configurable
|
2014-08-29 07:52:33 -07:00
|
|
|
static SPIDriver *driver = &SPID2;
|
|
|
|
|
|
|
|
static msg_t ivThread(int param) {
|
|
|
|
chRegSetThreadName("HIP");
|
|
|
|
|
2014-12-18 10:05:24 -08:00
|
|
|
while (true) {
|
2014-08-29 07:52:33 -07:00
|
|
|
chThdSleepMilliseconds(10);
|
|
|
|
|
2014-12-18 10:05:24 -08:00
|
|
|
// scheduleMsg(&logger, "poking HIP=%d", counter++);
|
2014-08-29 07:52:33 -07:00
|
|
|
|
|
|
|
spiSelect(driver);
|
|
|
|
|
2014-12-25 19:03:24 -08:00
|
|
|
// // '0' for 4MHz
|
|
|
|
// tx_buff[0] = SET_PRESCALER_CMD + 0 + 2;
|
|
|
|
// spiExchange(driver, 1, tx_buff, rx_buff);
|
|
|
|
//
|
|
|
|
// // '0' for channel #1
|
|
|
|
// tx_buff[0] = SET_CHANNEL_CMD + 0;
|
|
|
|
// spiExchange(driver, 1, tx_buff, rx_buff);
|
|
|
|
//
|
|
|
|
// // band index depends on cylinder bore
|
|
|
|
// tx_buff[0] = SET_BAND_PASS_CMD + bandIndex;
|
|
|
|
// spiExchange(driver, 1, tx_buff, rx_buff);
|
|
|
|
//
|
|
|
|
// // todo
|
|
|
|
// tx_buff[0] = SET_GAIN_CMD + 41;
|
|
|
|
// spiExchange(driver, 1, tx_buff, rx_buff);
|
|
|
|
//
|
|
|
|
// tx_buff[0] = SET_ADVANCED_MODE;
|
|
|
|
// spiExchange(driver, 1, tx_buff, rx_buff);
|
|
|
|
|
2014-12-26 12:04:16 -08:00
|
|
|
// BAND_PASS_CMD
|
2015-01-01 12:03:40 -08:00
|
|
|
tx_buff[0] = 0x0 | (40 & 0x3F);
|
2014-12-25 18:04:36 -08:00
|
|
|
spiExchange(driver, 1, tx_buff, rx_buff);
|
|
|
|
|
2015-01-01 12:03:40 -08:00
|
|
|
// Set the gain 0b10000000
|
|
|
|
tx_buff[0] = 0x80 | (49 & 0x3F);
|
2014-12-25 18:04:36 -08:00
|
|
|
spiExchange(driver, 1, tx_buff, rx_buff);
|
|
|
|
|
2015-01-01 12:03:40 -08:00
|
|
|
// Set the integration time constant 0b11000000
|
|
|
|
tx_buff[0] = 0xC0 | (31 & 0x1F);
|
2014-12-25 18:04:36 -08:00
|
|
|
spiExchange(driver, 1, tx_buff, rx_buff);
|
|
|
|
|
2015-01-01 12:03:40 -08:00
|
|
|
// SET_ADVANCED_MODE 0b01110001
|
|
|
|
tx_buff[0] = 0x71;
|
2014-12-25 18:04:36 -08:00
|
|
|
spiExchange(driver, 1, tx_buff, rx_buff);
|
|
|
|
|
|
|
|
spiUnselect(driver);
|
2014-12-18 10:05:24 -08:00
|
|
|
|
2014-08-29 07:52:33 -07:00
|
|
|
}
|
|
|
|
#if defined __GNUC__
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-12-05 09:03:16 -08:00
|
|
|
EXTERN_ENGINE
|
|
|
|
;
|
|
|
|
|
2015-01-02 10:04:02 -08:00
|
|
|
#define INT_LOOKUP_SIZE 32
|
2014-12-05 13:03:30 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* These are HIP9011 magic values - integrator time constants in uS
|
|
|
|
*/
|
2015-01-02 10:04:02 -08:00
|
|
|
static const int integratorValues[INT_LOOKUP_SIZE] = { 40, 45, 50, 55, 60, 65,
|
2014-12-26 12:04:16 -08:00
|
|
|
70, 75, 80, 90, 100, 110, 120, 130, 140, 150, 160, 180, 200, 220, 240,
|
|
|
|
260, 280, 300, 320, 360, 400, 440, 480, 520, 560, 600 };
|
2014-12-05 13:03:30 -08:00
|
|
|
|
2015-01-02 10:04:02 -08:00
|
|
|
#define GAIN_LOOKUP_SIZE 64
|
|
|
|
|
|
|
|
static const float gainLookupInReverseOrder[GAIN_LOOKUP_SIZE] = {
|
|
|
|
/* 00 */ 0.111, 0.118, 0.125, 0.129, 0.133, 0.138, 0.143, 0.148,
|
|
|
|
/* 08 */ 0.154, 0.160, 0.167, 0.174, 0.182, 0.190, 0.200, 0.211,
|
|
|
|
/* 16 */ 0.222, 0.236, 0.250, 0.258, 0.267, 0.276, 0.286, 0.296,
|
|
|
|
/* 24 */ 0.308, 0.320, 0.333, 0.348, 0.364, 0.381, 0.400, 0.421,
|
|
|
|
/* 32 */ 0.444, 0.471, 0.500, 0.548, 0.567, 0.586, 0.607, 0.630,
|
|
|
|
/* 40 */ 0.654, 0.680, 0.708, 0.739, 0.773, 0.810, 0.850, 0.895,
|
|
|
|
/* 48 */ 0.944, 1.000, 1.063, 1.143, 1.185, 1.231, 1.280, 1.333,
|
|
|
|
/* 56 */ 1.391, 1.455, 1.523, 1.600, 1.684, 1.778, 1.882, 2.0
|
|
|
|
};
|
|
|
|
|
|
|
|
#define GAIN_INDEX(gain) (GAIN_LOOKUP_SIZE - 1 - findIndex(gainLookupInReverseOrder, GAIN_LOOKUP_SIZE, (gain)))
|
|
|
|
|
2014-12-15 17:03:49 -08:00
|
|
|
#define BAND_LOOKUP_SIZE 64
|
|
|
|
|
2014-12-26 12:04:16 -08:00
|
|
|
static const float bandFreqLookup[BAND_LOOKUP_SIZE] = { 1.22, 1.26, 1.31, 1.35,
|
|
|
|
1.4, 1.45, 1.51, 1.57, 1.63, 1.71, 1.78, 1.87, 1.96, 2.07, 2.18, 2.31,
|
|
|
|
2.46, 2.54, 2.62, 2.71, 2.81, 2.92, 3.03, 3.15, 3.28, 3.43, 3.59, 3.76,
|
|
|
|
3.95, 4.16, 4.39, 4.66, 4.95, 5.12, 5.29, 5.48, 5.68, 5.9, 6.12, 6.37,
|
|
|
|
6.64, 6.94, 7.27, 7.63, 8.02, 8.46, 8.95, 9.5, 10.12, 10.46, 10.83,
|
|
|
|
11.22, 11.65, 12.1, 12.6, 13.14, 13.72, 14.36, 15.07, 15.84, 16.71,
|
|
|
|
17.67, 18.76, 19.98 };
|
2014-12-15 17:03:49 -08:00
|
|
|
|
2014-12-05 13:03:30 -08:00
|
|
|
#define PIF 3.14159f
|
|
|
|
|
2015-01-02 10:04:02 -08:00
|
|
|
static float rpmLookup[INT_LOOKUP_SIZE];
|
2014-12-05 13:03:30 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 'TC is typically TINT/(2*Pi*VOUT)'
|
|
|
|
* Knock Sensor Training TPIC8101, page 24
|
|
|
|
*
|
|
|
|
* We know the set of possible integration times, we know the knock detection window width
|
|
|
|
*
|
|
|
|
* 2.2 volts should
|
|
|
|
*
|
|
|
|
*/
|
2014-12-26 12:04:16 -08:00
|
|
|
#define DESIRED_OUTPUT_VALUE 5.0f
|
2014-12-05 13:03:30 -08:00
|
|
|
static void prepareRpmLookup(engine_configuration_s *engineConfiguration) {
|
2015-01-02 10:04:02 -08:00
|
|
|
for (int i = 0; i < INT_LOOKUP_SIZE; i++) {
|
2014-12-05 13:03:30 -08:00
|
|
|
float windowWidthMult = (engineConfiguration->knockDetectionWindowEnd
|
|
|
|
- engineConfiguration->knockDetectionWindowStart) / 360.0f;
|
|
|
|
// '60000000' because revolutions per MINUTE in uS conversion
|
|
|
|
|
2014-12-26 12:04:16 -08:00
|
|
|
rpmLookup[i] = 60000000.0f
|
|
|
|
/ (integratorValues[i] * 2 * PIF * DESIRED_OUTPUT_VALUE
|
|
|
|
* windowWidthMult);
|
2014-12-05 13:03:30 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-15 17:03:49 -08:00
|
|
|
#define BAND(bore) (900 / (PIF * (bore) / 2))
|
|
|
|
|
2015-01-02 10:04:02 -08:00
|
|
|
#define INTEGRATOR_INDEX findIndex(rpmLookup, INT_LOOKUP_SIZE, engine->rpmCalculator.rpmValue)
|
2014-12-26 12:04:16 -08:00
|
|
|
|
2014-12-15 17:03:49 -08:00
|
|
|
static void showHipInfo(void) {
|
|
|
|
printSpiState(&logger, boardConfiguration);
|
2014-12-26 12:04:16 -08:00
|
|
|
scheduleMsg(&logger, "bore=%f freq=%f", engineConfiguration->cylinderBore,
|
|
|
|
BAND(engineConfiguration->cylinderBore));
|
2014-12-15 17:03:49 -08:00
|
|
|
|
2015-01-02 10:04:02 -08:00
|
|
|
scheduleMsg(&logger, "band_index=%d gain_index=%d", bandIndex, GAIN_INDEX(boardConfiguration->hip9011Gain));
|
2014-12-15 17:03:49 -08:00
|
|
|
|
2014-12-26 12:04:16 -08:00
|
|
|
scheduleMsg(&logger, "integrator index=%d", INTEGRATOR_INDEX);
|
|
|
|
|
|
|
|
scheduleMsg(&logger, "spi= int=%s CS=%s",
|
|
|
|
hwPortname(boardConfiguration->hip9011IntHoldPin),
|
2014-12-24 14:05:26 -08:00
|
|
|
hwPortname(boardConfiguration->hip9011CsPin));
|
2014-12-15 17:03:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void setHip9011FrankensoPinout(void) {
|
|
|
|
/**
|
|
|
|
* SPI on PB13/14/15
|
|
|
|
*/
|
|
|
|
boardConfiguration->isHip9011Enabled = true;
|
2014-12-24 18:03:45 -08:00
|
|
|
boardConfiguration->hip9011CsPin = GPIOD_11;
|
2014-12-15 17:03:49 -08:00
|
|
|
boardConfiguration->hip9011IntHoldPin = GPIOB_11;
|
2014-12-18 10:05:24 -08:00
|
|
|
boardConfiguration->is_enabled_spi_2 = true;
|
|
|
|
}
|
|
|
|
|
2014-12-26 12:04:16 -08:00
|
|
|
static void startIntegration(void) {
|
|
|
|
if(isHip9011Busy)
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
turnPinHigh(HIP9011_INT_HOLD);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void endIntegration(void) {
|
|
|
|
|
|
|
|
turnPinLow(HIP9011_INT_HOLD);
|
|
|
|
/**
|
|
|
|
* SPI communication is only allowed while not integrading, so we initiate the exchange
|
|
|
|
* once we are done inregratng
|
|
|
|
*/
|
|
|
|
|
|
|
|
isHip9011Busy = true;
|
|
|
|
|
|
|
|
int newValue = INTEGRATOR_INDEX;
|
|
|
|
if (newValue != intergratorIndex) {
|
|
|
|
intergratorIndex = newValue;
|
|
|
|
// todo: send new value, be sure to use non-synchnonious approach!
|
|
|
|
|
|
|
|
}
|
|
|
|
// todo: move this into the end callback
|
|
|
|
isHip9011Busy = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-12-18 10:05:24 -08:00
|
|
|
/**
|
|
|
|
* Shaft Position callback used to start or finish HIP integration
|
|
|
|
*/
|
2014-12-26 12:04:16 -08:00
|
|
|
static void intHoldCallback(trigger_event_e ckpEventType,
|
|
|
|
uint32_t index DECLARE_ENGINE_PARAMETER_S) {
|
2014-12-18 10:05:24 -08:00
|
|
|
// this callback is invoked on interrupt thread
|
|
|
|
|
|
|
|
if (index != 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int rpm = engine->rpmCalculator.rpmValue;
|
|
|
|
if (!isValidRpm(rpm))
|
|
|
|
return;
|
|
|
|
|
|
|
|
int structIndex = getRevolutionCounter() % 2;
|
|
|
|
// todo: schedule this based on closest trigger event, same as ignition works
|
2014-12-26 12:04:16 -08:00
|
|
|
scheduleByAngle(rpm, &startTimer[structIndex],
|
|
|
|
engineConfiguration->knockDetectionWindowStart,
|
|
|
|
(schfunc_t) &startIntegration, NULL);
|
|
|
|
scheduleByAngle(rpm, &endTimer[structIndex],
|
|
|
|
engineConfiguration->knockDetectionWindowEnd,
|
|
|
|
(schfunc_t) &endIntegration,
|
|
|
|
NULL);
|
2014-12-15 17:03:49 -08:00
|
|
|
}
|
|
|
|
|
2015-01-02 06:03:46 -08:00
|
|
|
static void setGain(float value) {
|
2015-01-02 10:04:02 -08:00
|
|
|
boardConfiguration->hip9011Gain = value;
|
|
|
|
showHipInfo();
|
2015-01-02 06:03:46 -08:00
|
|
|
}
|
|
|
|
|
2014-08-29 07:52:33 -07:00
|
|
|
void initHip9011(void) {
|
2014-12-05 09:03:16 -08:00
|
|
|
if (!boardConfiguration->isHip9011Enabled)
|
|
|
|
return;
|
2014-08-29 07:52:33 -07:00
|
|
|
initLogging(&logger, "HIP driver");
|
|
|
|
|
2014-12-18 10:05:24 -08:00
|
|
|
// driver = getSpiDevice(boardConfiguration->digitalPotentiometerSpiDevice);
|
|
|
|
|
|
|
|
spicfg.ssport = getHwPort(boardConfiguration->hip9011CsPin);
|
|
|
|
spicfg.sspad = getHwPin(boardConfiguration->hip9011CsPin);
|
|
|
|
|
2014-12-26 12:04:16 -08:00
|
|
|
|
|
|
|
outputPinRegisterExt2("hip int/hold", HIP9011_INT_HOLD,
|
|
|
|
boardConfiguration->hip9011IntHoldPin, &DEFAULT_OUTPUT);
|
|
|
|
outputPinRegisterExt2("hip CS", SPI_CS_HIP9011,
|
|
|
|
boardConfiguration->hip9011CsPin, &DEFAULT_OUTPUT);
|
|
|
|
|
2014-12-18 10:05:24 -08:00
|
|
|
scheduleMsg(&logger, "Starting HIP9011/TPIC8101 driver");
|
2014-08-29 07:52:33 -07:00
|
|
|
spiStart(driver, &spicfg);
|
2014-12-26 12:04:16 -08:00
|
|
|
/**
|
|
|
|
* Here we initialize the chip in synchronous mode
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if HIP_DEBUG
|
|
|
|
chThdCreateStatic(htThreadStack, sizeof(htThreadStack), NORMALPRIO,
|
|
|
|
(tfunc_t) ivThread, NULL);
|
|
|
|
#else
|
|
|
|
/**
|
|
|
|
* for runtime we are re-starting SPI in non-synchronous mode
|
|
|
|
*/
|
|
|
|
spiStop(driver);
|
|
|
|
// todo spicfg.end_cb = spiEndCallback;
|
|
|
|
spiStart(driver, &spicfg);
|
2014-08-29 07:52:33 -07:00
|
|
|
|
2014-12-18 10:05:24 -08:00
|
|
|
|
2014-12-15 17:03:49 -08:00
|
|
|
|
2014-12-26 12:04:16 -08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
bandIndex = findIndex(bandFreqLookup, BAND_LOOKUP_SIZE,
|
|
|
|
BAND(engineConfiguration->cylinderBore));
|
2014-12-15 17:03:49 -08:00
|
|
|
|
2014-12-18 10:05:24 -08:00
|
|
|
addTriggerEventListener(&intHoldCallback, "DD int/hold", engine);
|
|
|
|
|
2014-12-25 19:03:24 -08:00
|
|
|
// MISO PB14
|
|
|
|
// palSetPadMode(GPIOB, 14, PAL_MODE_ALTERNATE(EFI_SPI2_AF) | PAL_STM32_PUDR_PULLUP);
|
|
|
|
// MOSI PB15
|
|
|
|
// palSetPadMode(GPIOB, 15, PAL_MODE_ALTERNATE(EFI_SPI2_AF) | PAL_STM32_OTYPE_OPENDRAIN);
|
2014-12-15 17:03:49 -08:00
|
|
|
|
|
|
|
addConsoleAction("hipinfo", showHipInfo);
|
2015-01-02 06:03:46 -08:00
|
|
|
addConsoleActionF("set_gain", setGain);
|
2014-08-29 07:52:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|