Aux serial (#1422)

* aux serial updates from last PR

* trying to guess

* wow that's old! also not working maybe?

* hiding diag code which was messing with GP2/GP3 i.e. TLE8888_PIN_22 TLE8888_PIN_23

* date

* Mc33 undervolt (#1421)

* mc33 flash check

* DI sanity checks for setting HV config

* mc33 under voltage check

* mc33 under voltage check

Co-authored-by: Christopher W. Anderson <gitstuff@pswitch.com>

* fixed {}

Co-authored-by: rusefi <rusefillc@gmail.com>
Co-authored-by: NOx-z <50815960+NOx-z@users.noreply.github.com>
Co-authored-by: Christopher W. Anderson <gitstuff@pswitch.com>
Co-authored-by: kon <dev@triggerdevel>
This commit is contained in:
kon 2020-05-11 09:17:42 -07:00 committed by GitHub
parent ff724bdc74
commit ae44c0fce7
17 changed files with 491 additions and 6 deletions

View File

@ -178,6 +178,10 @@
#define EFI_CAN_SUPPORT TRUE
#endif
#ifndef EFI_AUX_SERIAL
#define EFI_AUX_SERIAL TRUE
#endif
#ifndef EFI_HD44780_LCD
#define EFI_HD44780_LCD TRUE
#endif
@ -343,6 +347,8 @@
//#define TS_UART_DEVICE (&UARTD3)
#define TS_SERIAL_DEVICE (&SD3)
#define AUX_SERIAL_DEVICE (&SD6)
// todo: add DMA-mode for Console?
#if (TS_UART_DMA_MODE || TS_UART_MODE)
#undef EFI_CONSOLE_SERIAL_DEVICE

View File

@ -303,7 +303,7 @@
#define STM32_SERIAL_USE_USART3 TRUE
#define STM32_SERIAL_USE_UART4 FALSE
#define STM32_SERIAL_USE_UART5 FALSE
#define STM32_SERIAL_USE_USART6 FALSE
#define STM32_SERIAL_USE_USART6 TRUE
/**
* UART priority should not be too low so that we do not miss bytes
*/

View File

@ -50,11 +50,12 @@
#define BOARD_TLE8888_COUNT 1
#endif
#undef EFI_CAN_SUPPORT
#define EFI_CAN_SUPPORT TRUE
#undef EFI_AUX_SERIAL
#define EFI_AUX_SERIAL TRUE
#undef EFI_HD44780_LCD
#define EFI_HD44780_LCD TRUE
@ -89,6 +90,8 @@
#undef TS_SERIAL_DEVICE
#define TS_SERIAL_DEVICE (&SD3)
#define AUX_SERIAL_DEVICE (&SD6)
// todo: add DMA-mode for Console?
#if (TS_UART_DMA_MODE || TS_UART_MODE)
#undef EFI_CONSOLE_SERIAL_DEVICE

View File

@ -315,7 +315,7 @@
#define STM32_SERIAL_USE_USART3 TRUE
#define STM32_SERIAL_USE_UART4 FALSE
#define STM32_SERIAL_USE_UART5 FALSE
#define STM32_SERIAL_USE_USART6 FALSE
#define STM32_SERIAL_USE_USART6 TRUE
#define STM32_SERIAL_USE_UART7 FALSE
#define STM32_SERIAL_USE_UART8 FALSE
#define STM32_SERIAL_USART1_PRIORITY (PRECISE_SCHEDULING_TIMER_PRIORITY + 2)

View File

@ -45,6 +45,8 @@ CONTROLLERS_SRC_CPP = \
$(CONTROLLERS_DIR)/engine_controller.cpp \
$(CONTROLLERS_DIR)/engine_controller_misc.cpp \
$(CONTROLLERS_DIR)/persistent_store.cpp \
$(CONTROLLERS_DIR)/serial/serial_rx.cpp \
$(CONTROLLERS_DIR)/serial/serial_sensor.cpp \
CONTROLLERS_INC=\
@ -64,4 +66,5 @@ CONTROLLERS_INC=\
$(CONTROLLERS_DIR)/generated \
$(CONTROLLERS_DIR)/actuators \
$(CONTROLLERS_DIR)/actuators/gppwm \
$(CONTROLLERS_DIR)/serial \

View File

@ -96,7 +96,7 @@ void initEgoAveraging(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
#endif
bool hasAfrSensor(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
if (CONFIG(enableAemXSeries)) {
if (CONFIG(enableAemXSeries) || CONFIG(enableInnovateLC2)) {
return true;
}
@ -109,6 +109,7 @@ bool hasAfrSensor(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
}
extern float aemXSeriesLambda;
extern float InnovateLC2AFR;
float getAfr(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
#if EFI_CAN_SUPPORT
@ -117,6 +118,11 @@ float getAfr(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
}
#endif
#if EFI_AUX_SERIAL
if (CONFIG(enableInnovateLC2))
return InnovateLC2AFR;
#endif
#if EFI_CJ125 && HAL_USE_SPI
if (CONFIG(isCJ125Enabled)) {
return cjGetAfr(PASS_ENGINE_PARAMETER_SIGNATURE);

View File

@ -0,0 +1,37 @@
/**
* @file serial.h
*
* @date Mar 19, 2020
* @author Konstantin Smola, (c) 2020
*/
#pragma once
#include "hal.h"
#include "periodic_thread_controller.h"
#define TIME_100MSEC ((sysinterval_t)chTimeMS2I(100))
#define SERBUFFLEN 64
constexpr uint8_t lc2_header_mask = 162;
constexpr uint16_t lc2_pcklen_mask = 383;
class Logging;
typedef enum {UNKNOWN, HEADER_FOUND, IDENTIFIED} innovate_serial_id_state_t;
extern uint8_t ser_buffer[SERBUFFLEN]; //buffer for incoming serial data
extern size_t innovate_msg_len;
extern innovate_serial_id_state_t innovate_serial_id_state;
extern uint8_t sb;
extern bool clear_ser_buffer;
class SerialRead final : public ThreadController<256> {
public:
SerialRead();
void ThreadTask();
uint16_t len;
};

View File

@ -0,0 +1,58 @@
/**
* @file serial_rx.cpp
*
* This file handles auxilery serial communication.
*
* @date Mar 19, 2020
* @author Konstantin Smola, (c) 2020
*/
#include "globalaccess.h"
#if EFI_AUX_SERIAL
#include "engine.h"
#include "serial.h"
#include "serial_hw.h"
#include "serial_sensor.h"
#include "allsensors.h"
#include "vehicle_speed.h"
EXTERN_ENGINE;
static LoggingWithStorage logger("AUX Serial RX");
uint8_t ser_buffer[SERBUFFLEN] = {};
size_t innovate_msg_len = 1;
innovate_serial_id_state_t innovate_serial_id_state = UNKNOWN;
uint8_t sb = 0;
bool clear_ser_buffer = false;
SerialRead::SerialRead()
: ThreadController("AUX Serial RX", NORMALPRIO) {
}
void SerialRead::ThreadTask() {
while (true) {
if (CONFIG(enableInnovateLC2)) {
len = innovate_msg_len;
}
if (len >= SERBUFFLEN)
len = SERBUFFLEN;
if (sdReadTimeout(AUX_SERIAL_DEVICE, &ser_buffer[sb], len, TIME_100MSEC) == len) {
ParseSerialData();
} else {
ResetSerialSensor();
}
//clear buffer every frame to avoid parsing old data
if (clear_ser_buffer) {
ClearSerialBuffer();
clear_ser_buffer = false;
}
}
}
#endif // EFI_AUX_SERIAL

View File

@ -0,0 +1,191 @@
/**
* @file serial_sensor.cpp
*
*
* @date Mar 19, 2020
* @author Konstantin Smola, (c) 2020
*/
#include "global.h"
#if EFI_AUX_SERIAL
#include "serial.h"
#include "serial_sensor.h"
#include "engine.h"
#define NUM_INNOVATE_O2_SENSORS 1
#define AFR_MULTIPLIER 147
EXTERN_ENGINE;
volatile float InnovateLC2AFR = AFR_ERROR;
typedef enum
{
NO_ERROR = 0,
HEATER_SHORTED = 1,
HEATER_OPEN = 2,
PUMPCELL_SHORTED = 3,
PUMPCELL_OPEN = 4,
REFCELL_SHORTED = 5,
REFCELL_OPEN = 6,
SYSTEM_ERROR = 7,
SENSOR_TIMING_ERR = 8,
SUPP_V_LOW = 9
} sensor_error_code_t;
typedef struct
{
int function_code;
float AFR;
float AFR_multiplier;
float lambda;
float warmup;
sensor_error_code_t error_code;
} sensor_data_t;
static sensor_data_t innovate_o2_sensor[NUM_INNOVATE_O2_SENSORS];
static size_t tmsglen;
void IdentifyInnovateSerialMsg() { //this identifies an innovate LC1/LC2 o2 sensor by it's first word (header)
if (CONFIG(enableInnovateLC2)) {
if ((((ser_buffer[0]) & lc2_header_mask) != lc2_header_mask) && innovate_serial_id_state == IDENTIFIED) { //not serial header word
innovate_serial_id_state = UNKNOWN;
innovate_msg_len = 1;
sb = 0;
}
switch (innovate_serial_id_state) {
case UNKNOWN:
InnovateLC2AFR = AFR_ERROR;
// read one byte, identify with mask, advance and read next byte
if (((ser_buffer[0]) & lc2_header_mask) == lc2_header_mask) { // check if it's the first byte of header
// first byte identified, now continue reading and advance statemachine
innovate_serial_id_state = HEADER_FOUND;
innovate_msg_len = 1;
sb = 1;
} else {
innovate_serial_id_state = UNKNOWN;
}
break;
case HEADER_FOUND:
// now we should have both header bytes in array, and we can read the total packet length
tmsglen = (((ser_buffer[0] << 8) | ser_buffer[1]) & lc2_pcklen_mask); //0000000101111111 mask
if (tmsglen) {
tmsglen += 1; // length in words including header (2 bytes)
tmsglen *= 2; // length in bytes (incl header)
innovate_msg_len = tmsglen - 2;
sb = 2;
innovate_serial_id_state = IDENTIFIED; //advance state machine
} else {
innovate_serial_id_state = UNKNOWN;
}
break;
case IDENTIFIED:
innovate_msg_len = tmsglen;
sb = 0;
// serial packet fully identified
ParseInnovateSerialMsg(); //takes about 570ns
clear_ser_buffer = true;
break;
default:
break;
}
}
}
void ParseInnovateSerialMsg() {
float raw_afr;
//get error code and afr
// 000 Lambda valid and Aux data valid, normal operation.
// 001 Lambda value contains O2 level in 1/10%
// 010 Free air Calib in progress, Lambda data not valid
// 011 Need Free air Calibration Request, Lambda data not valid
// 100 Warming up, Lambda value is temp in 1/10% of operating temp.
// 101 Heater Calibration, Lambda value contains calibration countdown.
// 110 Error code in Lambda value
// 111 reserved
for (size_t i = 0; i < ((tmsglen - 2) / 4) && i < NUM_INNOVATE_O2_SENSORS; i++) {
innovate_o2_sensor[i].function_code = (ser_buffer[2 + i * 4] >> 2 & 0x7);
// innovate_o2_sensor[i].AFR_multiplier = ((ser_buffer[2 + i * 4] << 7 | ser_buffer[3 + i * 4]) & 0xFF);
innovate_o2_sensor[i].AFR_multiplier = AFR_MULTIPLIER;
switch (innovate_o2_sensor[i].function_code) {
case 0: //Lambda valid and aux data valid, normal operation
case 1: //Lambda value contains o2 level in 1/10%
innovate_o2_sensor[i].lambda = ((ser_buffer[4 + i * 4] << 7 | ser_buffer[5 + i * 4]) & 0x1FFF);
raw_afr = ((innovate_o2_sensor[i].lambda + 500) * innovate_o2_sensor[i].AFR_multiplier);
if (innovate_o2_sensor[i].function_code) {//case 1
innovate_o2_sensor[i].AFR = raw_afr * 0.001;
} else { // case 0
innovate_o2_sensor[i].AFR = raw_afr * 0.0001;
}
if (innovate_o2_sensor[i].AFR > AFRMAX) {
innovate_o2_sensor[i].AFR = AFRMAX;
} else if (innovate_o2_sensor[i].AFR < AFRMIN)
innovate_o2_sensor[i].AFR = AFRMIN;
}
InnovateLC2AFR = innovate_o2_sensor[0].AFR; //only using one sensor right now
break;
// this is invalid o2 data, so we can ignore it:
// case 2: // Free air Calib in progress, Lambda data not valid
// break;
// case 3: // Need Free air Calibration Request, Lambda data not valid
// break;
case 4: // Warming up, Lambda value is temp in 1/10% of operating temp
InnovateLC2AFR = AFR_ERROR;
innovate_o2_sensor[i].warmup = ((ser_buffer[4 + i * 4] << 7 | ser_buffer[5 + i * 4]) & 0x1FFF);
//catch potential overflow:
if (innovate_o2_sensor[i].warmup >= 1023) {
innovate_o2_sensor[i].warmup = 1023;
} else if (innovate_o2_sensor[i].warmup <= 0)
innovate_o2_sensor[i].warmup = 0;
}
break;
// case 5: // Heater Calibration, Lambda value contains calibration countdown
// break;
case 6: // Error code in Lambda value
InnovateLC2AFR = AFR_ERROR;
innovate_o2_sensor[i].error_code = (sensor_error_code_t)((ser_buffer[4 + i * 4] << 7 | ser_buffer[5 + i * 4]) & 0x1FFF);
//catch potential overflow:
if (innovate_o2_sensor[i].error_code >= (sensor_error_code_t)1023) {
innovate_o2_sensor[i].error_code = (sensor_error_code_t)1023;
} else if (innovate_o2_sensor[i].error_code <= 0) {
innovate_o2_sensor[i].error_code = (sensor_error_code_t)0;
}
break;
// case 7: // reserved
// break;
default:
InnovateLC2AFR = AFR_ERROR;
break;
}
}
}
void ResetSerialSensor() {
ClearSerialBuffer();
ParseSerialData();
}
void ClearSerialBuffer() {
memset(ser_buffer, 0, sizeof(ser_buffer));
}
void ParseSerialData() {
if (CONFIG(enableInnovateLC2))
IdentifyInnovateSerialMsg();
}
#endif

View File

@ -0,0 +1,20 @@
/**
* @file serial_sensor.h
*
*
* @date Mar 19, 2020
* @author Konstantin Smola, (c) 2020
*/
#pragma once
#define AFRMIN 0
#define AFRMAX 33
#define AFR_ERROR 30
void IdentifyInnovateSerialMsg();
void ParseInnovateSerialMsg();
void ParseSerialData();
void ResetSerialSensor();
void ClearSerialBuffer();

View File

@ -694,6 +694,14 @@ static void setCanTxPin(const char *pinName) {
setIndividualPin(pinName, &engineConfiguration->canTxPin, "CAN TX");
}
static void setAuxRxpin(const char *pinName) {
setIndividualPin(pinName, &engineConfiguration->auxSerialRxPin, "AUX RX");
}
static void setAuxTxpin(const char *pinName) {
setIndividualPin(pinName, &engineConfiguration->auxSerialTxPin, "AUX TX");
}
static void setAlternatorPin(const char *pinName) {
setIndividualPin(pinName, &engineConfiguration->alternatorControlPin, "alternator");
}
@ -1444,6 +1452,9 @@ void initSettings(void) {
addConsoleActionS("set_can_rx_pin", setCanRxPin);
addConsoleActionS("set_can_tx_pin", setCanTxPin);
addConsoleActionS("set_aux_tx_pin", setAuxTxpin);
addConsoleActionS("set_aux_rx_pin", setAuxRxpin);
#if HAL_USE_ADC
addConsoleActionSS("set_analog_input_pin", setAnalogInputPin);
#endif

View File

@ -4,6 +4,7 @@ HW_LAYER_DRIVERS_INC = \
$(DRIVERS_DIR) \
$(DRIVERS_DIR)/gpio \
$(DRIVERS_DIR)/can \
$(DRIVERS_DIR)/serial \
HW_LAYER_DRIVERS_CORE = \
$(DRIVERS_DIR)/gpio/core.c \
@ -17,4 +18,4 @@ HW_LAYER_DRIVERS = \
HW_LAYER_DRIVERS_CPP = \
$(DRIVERS_DIR)/can/can_hw.cpp \
$(DRIVERS_DIR)/can/can_msg_tx.cpp \
$(DRIVERS_DIR)/serial/serial_hw.cpp \

View File

@ -0,0 +1,93 @@
/**
* @file serial_hw.cpp
* @brief SERIAL bus low level code
*
* @date Apr 17, 2020
* @author Konstantin Smola, (c) 2020
*/
#include "global.h"
#if EFI_AUX_SERIAL
#include "serial.h"
#include "engine_configuration.h"
#include "pin_repository.h"
#include "serial_hw.h"
#include "string.h"
#include "mpu_util.h"
#include "engine.h"
EXTERN_ENGINE;
static bool isSerialEnabled = false;
static bool isSerialTXEnabled = false;
static bool isSerialRXEnabled = false;
static LoggingWithStorage logger("SERIAL driver");
static SerialConfig uartCfg;
static SerialRead serialRead;
static void auxInfo(void) {
if (!isSerialEnabled) {
scheduleMsg(&logger, "AUX Serial is not enabled, please enable & restart");
return;
}
scheduleMsg(&logger, "AUX Serial TX %s", hwPortname(CONFIG(auxSerialTxPin)));
scheduleMsg(&logger, "AUX Serial RX %s", hwPortname(CONFIG(auxSerialRxPin)));
}
void enableAuxSerial(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
engineConfiguration->auxSerialTxPin = CONFIG(auxSerialTxPin);
engineConfiguration->auxSerialRxPin = CONFIG(auxSerialRxPin);
engineConfiguration->auxSerialSpeed = CONFIG(auxSerialSpeed);
uartCfg.speed = engineConfiguration->auxSerialSpeed;
sdStart(AUX_SERIAL_DEVICE, &uartCfg);
scheduleMsg(&logger, "AUX Serial started");
}
void stopAuxSerialPins(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
brain_pin_markUnused(activeConfiguration.auxSerialTxPin);
brain_pin_markUnused(activeConfiguration.auxSerialRxPin);
}
void startAuxSerialPins(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
if (CONFIG(auxSerialTxPin))
efiSetPadMode("AuxSerial TX", CONFIG(auxSerialTxPin), PAL_MODE_ALTERNATE(8));
if (CONFIG(auxSerialRxPin))
efiSetPadMode("AuxSerial RX", CONFIG(auxSerialRxPin), PAL_MODE_ALTERNATE(8));
enableAuxSerial();
}
void initAuxSerial(void) {
addConsoleAction("auxinfo", auxInfo);
isSerialEnabled =
(CONFIG(auxSerialTxPin)) || // we need at least one pin set
(CONFIG(auxSerialRxPin));
isSerialRXEnabled = CONFIG(auxSerialRxPin);
isSerialTXEnabled = CONFIG(auxSerialTxPin);
// exit if no pin is configured
if (!isSerialEnabled)
return;
// Validate pins
if (isSerialTXEnabled && !isValidSerialTxPin(CONFIG(auxSerialTxPin)))
return;
if (isSerialRXEnabled && !isValidSerialRxPin(CONFIG(auxSerialRxPin)))
return;
startAuxSerialPins();
if (isSerialRXEnabled)
serialRead.Start();
}
#endif // EFI_AUX_SERIAL

View File

@ -0,0 +1,21 @@
/**
* @file serial_hw.h
* @brief SERIAL bus low level code
*
* @date Apr 17, 2020
* @author Konstantin Smola, (c) 2020
*/
#pragma once
#include "efifeatures.h"
#if EFI_TUNER_STUDIO
#include "tunerstudio_configuration.h"
#endif /* EFI_TUNER_STUDIO */
void initAuxSerial(void);
#if EFI_AUX_SERIAL
void stopAuxSerialPins(DECLARE_ENGINE_PARAMETER_SIGNATURE);
void startAuxSerialPins(DECLARE_ENGINE_PARAMETER_SIGNATURE);
void enableAuxSerial(DECLARE_ENGINE_PARAMETER_SIGNATURE);
#endif //EFI_AUX_SERIAL

View File

@ -28,6 +28,7 @@
#include "eficonsole.h"
#include "console_io.h"
#include "sensor_chart.h"
#include "serial_hw.h"
#include "mpu_util.h"
//#include "usb_msd.h"
@ -289,6 +290,10 @@ void applyNewHardwareSettings(void) {
stopCanPins();
#endif /* EFI_CAN_SUPPORT */
#if EFI_AUX_SERIAL
stopAuxSerialPins();
#endif /* EFI_AUX_SERIAL */
#if EFI_HIP_9011
stopHip9001_pins();
#endif /* EFI_HIP_9011 */
@ -364,6 +369,10 @@ void applyNewHardwareSettings(void) {
startCanPins();
#endif /* EFI_CAN_SUPPORT */
#if EFI_AUX_SERIAL
startAuxSerialPins();
#endif /* EFI_AUX_SERIAL */
#if EFI_HIP_9011
startHip9001_pins();
#endif /* EFI_HIP_9011 */
@ -559,6 +568,9 @@ void initHardware(Logging *l) {
addConsoleActionII("i2c", sendI2Cbyte);
#endif
#if EFI_AUX_SERIAL
initAuxSerial();
#endif /* EFI_AUX_SERIAL */
// USBMassStorageDriver UMSD1;

View File

@ -15,6 +15,9 @@ bool isValidCanRxPin(brain_pin_e pin);
CANDriver * detectCanDevice(brain_pin_e pinRx, brain_pin_e pinTx);
#endif // HAL_USE_CAN
bool isValidSerialTxPin(brain_pin_e pin);
bool isValidSerialRxPin(brain_pin_e pin);
// SPI
#if HAL_USE_SPI
void initSpiModule(SPIDriver *driver, brain_pin_e sck, brain_pin_e miso,

View File

@ -145,3 +145,23 @@ void jump_to_bootloader() {
NVIC_SystemReset();
}
#endif /* EFI_PROD_CODE */
#if EFI_AUX_SERIAL
static bool isValidUART6TxPin(brain_pin_e pin) {
return pin == GPIOC_6 || pin == GPIOG_14;
}
static bool isValidUART6RxPin(brain_pin_e pin) {
return pin == GPIOC_7 || pin == GPIOG_9;
}
bool isValidSerialTxPin(brain_pin_e pin) {
return isValidUART6TxPin(pin);
}
bool isValidSerialRxPin(brain_pin_e pin) {
return isValidUART6RxPin(pin);
}
#endif /*EFI_AUX_SERIAL*/