Merge remote-tracking branch 'origin/master' into master

This commit is contained in:
rusefillc 2021-12-05 22:03:00 -05:00
commit 4be62ab521
56 changed files with 482 additions and 290 deletions

View File

@ -26,7 +26,7 @@ DDEFS += -DLED_COMMUNICATION_BRAIN_PIN_MODE=INVERTED_OUTPUT
# Disable serial ports on this board as UART3 causes a DMA conflict with the SD card
DDEFS += -DTS_NO_PRIMARY -DTS_NO_SECONDARY
DDEFS += -DEFI_CAN_SERIAL=TRUE -DTS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME=TRUE
DDEFS += -DEFI_CAN_SERIAL=TRUE
# todo debug:
DDEFS += -DDISABLE_CAN_UPDATE_DASH=TRUE

View File

@ -26,7 +26,7 @@ endif
# *TODO* need to give people the horrible choice between Bluetooth via TTL or SD card via SPI :( horrible choice
EFI_CONSOLE_TTL_PINS = -DEFI_CONSOLE_TX_BRAIN_PIN=GPIOB_10 -DEFI_CONSOLE_RX_BRAIN_PIN=GPIOB_11
DDEFS += -DEFI_CAN_SERIAL=TRUE -DTS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME=TRUE
DDEFS += -DEFI_CAN_SERIAL=TRUE
# Add them all together

View File

@ -811,6 +811,10 @@ void proteusHarley() {
engineConfiguration->camInputs[0] = PROTEUS_DIGITAL_6;
engineConfiguration->vvtMode[0] = VVT_MAP_V_TWIN;
engineConfiguration->mapCamAveragingLength = 16;
engineConfiguration->mapCamSkipFactor = 50;
engineConfiguration->mapCamLookForLowPeaks = true;
engineConfiguration->luaOutputPins[0] = PROTEUS_LS_12;
#if HW_PROTEUS
strncpy(config->luaScript, R"(

View File

@ -234,7 +234,7 @@ uint16_t rpmAcceleration;dRPM;"RPM/s",1, 0, 0, 0, 0
uint16_t autoscale rawTps2Primary;;"V",{1/@@PACK_MULT_VOLTAGE@@}, 0, 0, 0, 0
uint16_t autoscale rawTps2Secondary;;"V",{1/@@PACK_MULT_VOLTAGE@@}, 0, 0, 0, 0
uint16_t knockCount;@@GAUGE_NAME_KNOCK_LEVEL@@;"",1, 0, 0, 0, 0
uint16_t knockCount;"knock: count";"",1, 0, 0, 0, 0
uint16_t autoscale accelerationZ;@@GAUGE_NAME_ACCEL_Z@@;"G",{1/@@PACK_MULT_PERCENT@@}, 0, 0, 0, 0
uint16_t autoscale accelerationRoll;@@GAUGE_NAME_ACCEL_ROLL@@;"",{1/@@PACK_MULT_PERCENT@@}, 0, 0, 0, 0

View File

@ -26,7 +26,7 @@ static CanTsListener listener;
int CanStreamerState::sendFrame(const IsoTpFrameHeader & header, const uint8_t *data, int num, can_sysinterval_t timeout) {
int dlc = 8; // standard 8 bytes
CanTxMessage txmsg(CAN_SERIAL_TX_ID, dlc, false);
CanTxMessage txmsg(CAN_ECU_SERIAL_TX_ID, dlc, false);
// fill the frame data according to the CAN-TP protocol (ISO 15765-2)
txmsg[0] = (uint8_t)((header.frameType & 0xf) << 4);
@ -76,6 +76,7 @@ int CanStreamerState::sendFrame(const IsoTpFrameHeader & header, const uint8_t *
int CanStreamerState::receiveFrame(CANRxFrame *rxmsg, uint8_t *buf, int num, can_sysinterval_t timeout) {
if (rxmsg == nullptr || rxmsg->DLC < 1)
return 0;
engine->pauseCANdueToSerial = true;
int frameType = (rxmsg->data8[0] >> 4) & 0xf;
int numBytesAvailable, frameIdx;
uint8_t *srcBuf = rxmsg->data8;

View File

@ -27,10 +27,6 @@
#define CAN_FIFO_BUF_SIZE 64
#define CAN_FIFO_FRAME_SIZE 8
// todo: find a better place for these defs
#define CAN_SERIAL_RX_ID 0x100
#define CAN_SERIAL_TX_ID 0x102
#define CAN_FLOW_STATUS_OK 0
#define CAN_FLOW_STATUS_WAIT_MORE 1
#define CAN_FLOW_STATUS_ABORT 2
@ -114,7 +110,7 @@ public:
class CanTsListener : public CanListener {
public:
CanTsListener()
: CanListener(CAN_SERIAL_RX_ID)
: CanListener(CAN_ECU_SERIAL_RX_ID)
{
}

View File

@ -1,4 +1,4 @@
// this section was generated automatically by rusEFI tool ConfigDefinition.jar based on (unknown script) console/binary/output_channels.txt Sat Dec 04 23:26:00 UTC 2021
// this section was generated automatically by rusEFI tool ConfigDefinition.jar based on (unknown script) console/binary/output_channels.txt Sun Dec 05 04:34:28 UTC 2021
// by class com.rusefi.output.CHeaderConsumer
// begin
#pragma once
@ -790,7 +790,7 @@ struct ts_outputs_s {
*/
scaled_channel<uint16_t, 1000, 1> rawTps2Secondary = (uint16_t)0;
/**
* @@GAUGE_NAME_KNOCK_LEVEL@@
* "knock: count"
* offset 306
*/
uint16_t knockCount = (uint16_t)0;
@ -970,4 +970,4 @@ struct ts_outputs_s {
};
// end
// this section was generated automatically by rusEFI tool ConfigDefinition.jar based on (unknown script) console/binary/output_channels.txt Sat Dec 04 23:26:00 UTC 2021
// this section was generated automatically by rusEFI tool ConfigDefinition.jar based on (unknown script) console/binary/output_channels.txt Sun Dec 05 04:34:28 UTC 2021

View File

@ -31,76 +31,72 @@ static void pidReset() {
alternatorPid.reset();
}
class AlternatorController : public PeriodicTimerController {
int getPeriodMs() override {
return GET_PERIOD_LIMITED(&engineConfiguration->alternatorControl);
void AlternatorController::onFastCallback() {
if (!isBrainPinValid(engineConfiguration->alternatorControlPin)) {
return;
}
void PeriodicTask() override {
#if ! EFI_UNIT_TEST
if (shouldResetPid) {
pidReset();
shouldResetPid = false;
}
if (shouldResetPid) {
pidReset();
shouldResetPid = false;
}
#endif
// this block could be executed even in on/off alternator control mode
// but at least we would reflect latest state
// this block could be executed even in on/off alternator control mode
// but at least we would reflect latest state
#if EFI_TUNER_STUDIO
alternatorPid.postState(&tsOutputChannels.alternatorStatus);
alternatorPid.postState(&tsOutputChannels.alternatorStatus);
#endif /* EFI_TUNER_STUDIO */
// todo: migrate this to FSIO
bool alternatorShouldBeEnabledAtCurrentRpm = GET_RPM() > engineConfiguration->cranking.rpm;
// todo: migrate this to FSIO
bool alternatorShouldBeEnabledAtCurrentRpm = GET_RPM() > engineConfiguration->cranking.rpm;
if (!engineConfiguration->isAlternatorControlEnabled || !alternatorShouldBeEnabledAtCurrentRpm) {
// we need to avoid accumulating iTerm while engine is not running
pidReset();
if (!engineConfiguration->isAlternatorControlEnabled || !alternatorShouldBeEnabledAtCurrentRpm) {
// we need to avoid accumulating iTerm while engine is not running
pidReset();
// Shut off output if not needed
alternatorControl.setSimplePwmDutyCycle(0);
// Shut off output if not needed
alternatorControl.setSimplePwmDutyCycle(0);
return;
}
return;
}
auto vBatt = Sensor::get(SensorType::BatteryVoltage);
float targetVoltage = engineConfiguration->targetVBatt;
// todo: I am not aware of a SINGLE person to use this onOffAlternatorLogic
if (engineConfiguration->onOffAlternatorLogic) {
if (!vBatt) {
// Somehow battery voltage isn't valid, disable alternator control
enginePins.alternatorPin.setValue(false);
}
float h = 0.1;
bool newState = (vBatt.Value < targetVoltage - h) || (currentPlainOnOffState && vBatt.Value < targetVoltage);
enginePins.alternatorPin.setValue(newState);
currentPlainOnOffState = newState;
#if EFI_TUNER_STUDIO
tsOutputChannels.alternatorOnOff = newState;
#endif /* EFI_TUNER_STUDIO */
return;
}
auto vBatt = Sensor::get(SensorType::BatteryVoltage);
float targetVoltage = engineConfiguration->targetVBatt;
// todo: I am not aware of a SINGLE person to use this onOffAlternatorLogic
if (engineConfiguration->onOffAlternatorLogic) {
if (!vBatt) {
// Somehow battery voltage isn't valid, disable alternator control
alternatorPid.reset();
alternatorControl.setSimplePwmDutyCycle(0);
} else {
currentAltDuty = alternatorPid.getOutput(targetVoltage, vBatt.Value);
if (engineConfiguration->isVerboseAlternator) {
efiPrintf("alt duty: %.2f/vbatt=%.2f/p=%.2f/i=%.2f/d=%.2f int=%.2f", currentAltDuty, vBatt.Value,
alternatorPid.getP(), alternatorPid.getI(), alternatorPid.getD(), alternatorPid.getIntegration());
}
alternatorControl.setSimplePwmDutyCycle(PERCENT_TO_DUTY(currentAltDuty));
enginePins.alternatorPin.setValue(false);
}
}
};
static AlternatorController instance;
float h = 0.1;
bool newState = (vBatt.Value < targetVoltage - h) || (currentPlainOnOffState && vBatt.Value < targetVoltage);
enginePins.alternatorPin.setValue(newState);
currentPlainOnOffState = newState;
#if EFI_TUNER_STUDIO
tsOutputChannels.alternatorOnOff = newState;
#endif /* EFI_TUNER_STUDIO */
return;
}
if (!vBatt) {
// Somehow battery voltage isn't valid, disable alternator control
alternatorPid.reset();
alternatorControl.setSimplePwmDutyCycle(0);
} else {
currentAltDuty = alternatorPid.getOutput(targetVoltage, vBatt.Value, FAST_CALLBACK_PERIOD_MS / 1000.0f);
if (engineConfiguration->isVerboseAlternator) {
efiPrintf("alt duty: %.2f/vbatt=%.2f/p=%.2f/i=%.2f/d=%.2f int=%.2f", currentAltDuty, vBatt.Value,
alternatorPid.getP(), alternatorPid.getI(), alternatorPid.getD(), alternatorPid.getIntegration());
}
alternatorControl.setSimplePwmDutyCycle(PERCENT_TO_DUTY(currentAltDuty));
}
}
void showAltInfo(void) {
efiPrintf("alt=%s @%s t=%dms", boolToString(engineConfiguration->isAlternatorControlEnabled),
@ -135,7 +131,6 @@ void initAlternatorCtrl() {
&enginePins.alternatorPin,
engineConfiguration->alternatorPwmFrequency, 0);
}
instance.Start();
}
// todo: start invoking this method like 'startVvtControlPins'
@ -147,5 +142,4 @@ void stopAlternatorPin(void) {
// todo: implementation!
}
#endif /* EFI_ALTERNATOR_CONTROL */

View File

@ -18,4 +18,9 @@ void setAltIFactor(float p);
void setAltDFactor(float p);
void showAltInfo(void);
class AlternatorController : public EngineModule {
public:
void onFastCallback() override;
};
void onConfigurationChangeAlternatorCallback(engine_configuration_s *previousConfiguration);

View File

@ -34,6 +34,7 @@
#include "ac_control.h"
#include "type_list.h"
#include "boost_control.h"
#include "alternator_controller.h"
#ifndef EFI_UNIT_TEST
#error EFI_UNIT_TEST must be defined!
@ -119,6 +120,11 @@ public:
bool isPwmEnabled = true;
const char *prevOutputName = nullptr;
/**
* ELM327 cannot handle both RX and TX at the same time, we have to stay quite once first ISO/TP packet was detected
* this is a pretty temporary hack only while we are trying ELM327, long term ISO/TP and rusEFI broadcast should find a way to coexists
*/
bool pauseCANdueToSerial = false;
PinRepository pinRepository;
@ -136,7 +142,9 @@ public:
#if EFI_HPFP && EFI_ENGINE_CONTROL
HpfpController,
#endif // EFI_HPFP && EFI_ENGINE_CONTROL
#if EFI_ALTERNATOR_CONTROL
AlternatorController,
#endif /* EFI_ALTERNATOR_CONTROL */
FuelPumpController,
MainRelayController,
AcController,
@ -330,11 +338,6 @@ public:
void resetEngineSnifferIfInTestMode();
/**
* pre-calculated offset for given sequence index within engine cycle
* (not cylinder ID)
*/
angle_t ignitionPositionWithinEngineCycle[MAX_CYLINDER_COUNT];
/**
* pre-calculated reference to which output pin should be used for
* given sequence index within engine cycle

View File

@ -31,7 +31,7 @@ void CanWrite::PeriodicTask(efitime_t nowNt) {
CanCycle cycle(cycleCount);
//in case we have Verbose Can enabled, we should keep user configured period
if (engineConfiguration->enableVerboseCanTx) {
if (engineConfiguration->enableVerboseCanTx && !engine->pauseCANdueToSerial) {
uint16_t cycleCountsPeriodMs = cycleCount * CAN_CYCLE_PERIOD;
if (0 != engineConfiguration->canSleepPeriodMs) {
if (cycleCountsPeriodMs % engineConfiguration->canSleepPeriodMs) {

View File

@ -1,2 +1,2 @@
#pragma once
#define VCS_DATE 20211204
#define VCS_DATE 20211206

View File

@ -741,7 +741,7 @@ void initEngineContoller() {
* UNUSED_SIZE constants.
*/
#ifndef RAM_UNUSED_SIZE
#define RAM_UNUSED_SIZE 18000
#define RAM_UNUSED_SIZE 13000
#endif
#ifndef CCM_UNUSED_SIZE
#define CCM_UNUSED_SIZE 16

View File

@ -107,9 +107,7 @@ bool FuelSchedule::addFuelEventsForCylinder(int i ) {
warning(CUSTOM_OBD_INJECTION_NO_PIN_ASSIGNED, "no_pin_inj #%s", output->name);
}
angle_t ignitionPositionWithinEngineCycle = engine->ignitionPositionWithinEngineCycle[i];
float angle = baseAngle + ignitionPositionWithinEngineCycle;
float angle = baseAngle + getCylinderAngle(i, ev->cylinderNumber);
if (TRIGGER_WAVEFORM(getSize()) < 1) {
warning(CUSTOM_ERR_NOT_INITIALIZED_TRIGGER, "uninitialized TriggerWaveform");

View File

@ -111,7 +111,7 @@ void mapAveragingAdcCallback(adcsample_t adcValue) {
if (engineConfiguration->vvtMode[0] == VVT_MAP_V_TWIN &&
((fastMapCounter++ % engineConfiguration->mapCamSkipFactor) == 0)) {
engine->triggerCentral.mapState.add(instantMap);
bool isPeak = engine->triggerCentral.mapState.isPeak();
bool isPeak = engine->triggerCentral.mapState.isPeak(engineConfiguration->mapCamLookForLowPeaks);
#if EFI_TUNER_STUDIO
tsOutputChannels.TEMPLOG_map_length = MAP_CAM_BUFFER;
tsOutputChannels.TEMPLOG_MAP_INSTANT_AVERAGE = engine->triggerCentral.mapState.current;

View File

@ -73,12 +73,14 @@ static void prepareCylinderIgnitionSchedule(angle_t dwellAngleDuration, floatms_
// let's save planned duration so that we can later compare it with reality
event->sparkDwell = sparkDwell;
// change of sign here from 'before TDC' to 'after TDC'
angle_t ignitionPositionWithinEngineCycle = engine->ignitionPositionWithinEngineCycle[event->cylinderIndex];
assertAngleRange(ignitionPositionWithinEngineCycle, "aPWEC", CUSTOM_ERR_6566);
// this correction is usually zero (not used)
float perCylinderCorrection = engineConfiguration->timing_offset_cylinder[event->cylinderIndex];
const angle_t sparkAngle = -engine->engineState.timingAdvance + engine->knockController.getKnockRetard() + ignitionPositionWithinEngineCycle + perCylinderCorrection;
const angle_t sparkAngle =
// Negate because timing *before* TDC, and we schedule *after* TDC
- engine->engineState.timingAdvance
// Offset by this cylinder's position in the cycle
+ getCylinderAngle(event->cylinderIndex, event->cylinderNumber)
// Pull any extra timing for knock retard
+ engine->knockController.getKnockRetard();
efiAssertVoid(CUSTOM_SPARK_ANGLE_9, !cisnan(sparkAngle), "findAngle#9");
efiAssertVoid(CUSTOM_SPARK_ANGLE_1, !cisnan(sparkAngle), "sparkAngle#1");

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 3197887637
#define TS_SIGNATURE "rusEFI 2021.12.05.all.3197887637"
#define SIGNATURE_HASH 3288789643
#define TS_SIGNATURE "rusEFI 2021.12.06.all.3288789643"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 2723221938
#define TS_SIGNATURE "rusEFI 2021.12.05.atlas.2723221938"
#define SIGNATURE_HASH 3637249964
#define TS_SIGNATURE "rusEFI 2021.12.06.atlas.3637249964"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 3197887637
#define TS_SIGNATURE "rusEFI 2021.12.05.f429-discovery.3197887637"
#define SIGNATURE_HASH 3288789643
#define TS_SIGNATURE "rusEFI 2021.12.06.f429-discovery.3288789643"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 3299455356
#define TS_SIGNATURE "rusEFI 2021.12.05.frankenso_na6.3299455356"
#define SIGNATURE_HASH 3191121762
#define TS_SIGNATURE "rusEFI 2021.12.06.frankenso_na6.3191121762"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 457823260
#define TS_SIGNATURE "rusEFI 2021.12.05.hellen-nb1.457823260"
#define SIGNATURE_HASH 1641333250
#define TS_SIGNATURE "rusEFI 2021.12.06.hellen-nb1.1641333250"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 85952052
#define TS_SIGNATURE "rusEFI 2021.12.05.hellen121nissan.85952052"
#define SIGNATURE_HASH 2139263018
#define TS_SIGNATURE "rusEFI 2021.12.06.hellen121nissan.2139263018"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 3778592927
#define TS_SIGNATURE "rusEFI 2021.12.05.hellen121vag.3778592927"
#define SIGNATURE_HASH 2611336833
#define TS_SIGNATURE "rusEFI 2021.12.06.hellen121vag.2611336833"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 610111282
#define TS_SIGNATURE "rusEFI 2021.12.05.hellen128.610111282"
#define SIGNATURE_HASH 1589680428
#define TS_SIGNATURE "rusEFI 2021.12.06.hellen128.1589680428"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 2622481971
#define TS_SIGNATURE "rusEFI 2021.12.05.hellen154hyundai.2622481971"
#define SIGNATURE_HASH 3872583725
#define TS_SIGNATURE "rusEFI 2021.12.06.hellen154hyundai.3872583725"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 1244029733
#define TS_SIGNATURE "rusEFI 2021.12.05.hellen72.1244029733"
#define SIGNATURE_HASH 817591611
#define TS_SIGNATURE "rusEFI 2021.12.06.hellen72.817591611"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 4264296150
#define TS_SIGNATURE "rusEFI 2021.12.05.hellen81.4264296150"
#define SIGNATURE_HASH 2226579656
#define TS_SIGNATURE "rusEFI 2021.12.06.hellen81.2226579656"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 526087626
#define TS_SIGNATURE "rusEFI 2021.12.05.hellen88bmw.526087626"
#define SIGNATURE_HASH 1707500500
#define TS_SIGNATURE "rusEFI 2021.12.06.hellen88bmw.1707500500"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 3366363709
#define TS_SIGNATURE "rusEFI 2021.12.05.hellenNA6.3366363709"
#define SIGNATURE_HASH 2990257187
#define TS_SIGNATURE "rusEFI 2021.12.06.hellenNA6.2990257187"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on hellen_cypress_gen_config.bat integration/rusefi_config.txt
//
#define SIGNATURE_HASH 2221802281
#define TS_SIGNATURE "rusEFI 2021.12.05.hellen_cypress.2221802281"
#define SIGNATURE_HASH 4277343543
#define TS_SIGNATURE "rusEFI 2021.12.06.hellen_cypress.4277343543"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on kinetis_gen_config.bat integration/rusefi_config.txt
//
#define SIGNATURE_HASH 2076954581
#define TS_SIGNATURE "rusEFI 2021.12.05.kin.2076954581"
#define SIGNATURE_HASH 22469067
#define TS_SIGNATURE "rusEFI 2021.12.06.kin.22469067"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 230465057
#define TS_SIGNATURE "rusEFI 2021.12.05.mre_f4.230465057"
#define SIGNATURE_HASH 1998686271
#define TS_SIGNATURE "rusEFI 2021.12.06.mre_f4.1998686271"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 230465057
#define TS_SIGNATURE "rusEFI 2021.12.05.mre_f7.230465057"
#define SIGNATURE_HASH 1998686271
#define TS_SIGNATURE "rusEFI 2021.12.06.mre_f7.1998686271"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 4000398707
#define TS_SIGNATURE "rusEFI 2021.12.05.prometheus_405.4000398707"
#define SIGNATURE_HASH 2498505581
#define TS_SIGNATURE "rusEFI 2021.12.06.prometheus_405.2498505581"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 4000398707
#define TS_SIGNATURE "rusEFI 2021.12.05.prometheus_469.4000398707"
#define SIGNATURE_HASH 2498505581
#define TS_SIGNATURE "rusEFI 2021.12.06.prometheus_469.2498505581"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 44703546
#define TS_SIGNATURE "rusEFI 2021.12.05.proteus_f4.44703546"
#define SIGNATURE_HASH 2016872740
#define TS_SIGNATURE "rusEFI 2021.12.06.proteus_f4.2016872740"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 44703546
#define TS_SIGNATURE "rusEFI 2021.12.05.proteus_f7.44703546"
#define SIGNATURE_HASH 2016872740
#define TS_SIGNATURE "rusEFI 2021.12.06.proteus_f7.2016872740"

View File

@ -2,5 +2,5 @@
// was generated automatically by rusEFI tool ConfigDefinition.jar based on config/boards/subaru_eg33/config/gen_config.sh integration/rusefi_config.txt
//
#define SIGNATURE_HASH 2099376837
#define TS_SIGNATURE "rusEFI 2021.12.05.subaru_eg33_f7.2099376837"
#define SIGNATURE_HASH 129819867
#define TS_SIGNATURE "rusEFI 2021.12.06.subaru_eg33_f7.129819867"

View File

@ -440,10 +440,6 @@ void prepareOutputSignals() {
}
#endif /* EFI_UNIT_TEST */
for (size_t i = 0; i < engineConfiguration->specs.cylindersCount; i++) {
engine->ignitionPositionWithinEngineCycle[i] = engine->engineCycle * i / engineConfiguration->specs.cylindersCount;
}
prepareIgnitionPinIndices(engineConfiguration->ignitionMode);
TRIGGER_WAVEFORM(prepareShape(&engine->triggerCentral.triggerFormDetails));
@ -452,6 +448,21 @@ void prepareOutputSignals() {
engine->injectionEvents.invalidate();
}
angle_t getCylinderAngle(uint8_t cylinderIndex, uint8_t cylinderNumber) {
// base = position of this cylinder in the firing order.
// We get a cylinder every n-th of an engine cycle where N is the number of cylinders
auto base = engine->engineCycle * cylinderIndex / engineConfiguration->specs.cylindersCount;
// Plus or minus any adjustment if this is an odd-fire engine
auto adjustment = engineConfiguration->timing_offset_cylinder[cylinderNumber];
auto result = base + adjustment;
assertAngleRange(result, "getCylinderAngle", CUSTOM_ERR_6566);
return result;
}
void setTimingRpmBin(float from, float to) {
setRpmBin(config->ignitionRpmBins, IGN_RPM_COUNT, from, to);
}

View File

@ -62,3 +62,11 @@ void setSingleCoilDwell();
// while for toothed wheels user would have to provide a value
#define tdcPosition() \
(TRIGGER_WAVEFORM(tdcPosition) + engineConfiguration->globalTriggerAngleOffset)
/** Gets phase offset for a particular cylinder's ID and number
* For example on 4 cylinder engine with firing order 1-3-4-2, this
* returns 0-180-360-540 for index 0-1-2-3
* Cylinder number is used for per-cylinder adjustment, if you have
* an odd-fire engine (v-twin, V10, some v6, etc)
*/
angle_t getCylinderAngle(uint8_t cylinderIndex, uint8_t cylinderNumber);

View File

@ -48,8 +48,12 @@ struct MapState {
current = mapBuffer.sum(engineConfiguration->mapCamAveragingLength);
}
bool isPeak() {
return previous > prevPrevious && previous >= current;
bool isPeak(bool lookForLowPeak) {
if (lookForLowPeak) {
return previous < prevPrevious && previous <= current;
} else {
return previous > prevPrevious && previous >= current;
}
}
};

View File

@ -70,7 +70,7 @@
! Any time an incompatible change is made to the configuration format stored in flash,
! update this string to the current date! It is required to also update TS_SIGNATURE above
! when this happens.
#define FLASH_DATA_VERSION 10003
#define FLASH_DATA_VERSION 10004
#define LOG_DELIMITER "`"
@ -893,7 +893,7 @@ custom maf_sensor_type_e 4 bits, S32, @OFFSET@, [0:1], @@maf_sensor_type_e_enum@
bit enableInnovateLC2
bit showHumanReadableWarning
bit stftIgnoreErrorMagnitude;+If enabled, adjust at a constant rate instead of a rate proportional to the current lambda error. This mode may be easier to tune, and more tolerant of sensor noise. Use of this mode is required if you have a narrowband O2 sensor.
bit unused976b11
bit mapCamLookForLowPeaks
bit enableSoftwareKnock
bit verboseVVTDecoding;enable vvt_details
bit invertCamVVTSignal;get invertCamVVTSignal
@ -1548,7 +1548,7 @@ float[IDLE_ADVANCE_CURVE_SIZE] idleAdvance ;Optional timing advance table for
float[IDLE_VE_CURVE_SIZE] idleVeBins;Optional VE table for Idle (see useSeparateVEForIdle);"RPM", 1, 0, 0, 18000, 2
float[IDLE_VE_CURVE_SIZE] idleVe; Optional VE table for Idle (see useSeparateVEForIdle);"%", 1, 0, 0, 999, 2
#define LUA_SCRIPT_SIZE 3600
#define LUA_SCRIPT_SIZE 8000
custom lua_script_t @@LUA_SCRIPT_SIZE@@ string, ASCII, @OFFSET@, @@LUA_SCRIPT_SIZE@@
lua_script_t luaScript;
@ -1991,5 +1991,5 @@ end_struct
#define show_test_presets true
#define show_Frankenso_presets true
#define CAN_SERIAL_RX_ID 0x100
#define CAN_SERIAL_TX_ID 0x102
#define CAN_ECU_SERIAL_RX_ID 0x100
#define CAN_ECU_SERIAL_TX_ID 0x102

View File

@ -2773,7 +2773,6 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00"
field = "PWM frequency", alternatorPwmFrequency, {isAlternatorControlEnabled == 1 && onOffAlternatorLogic == 0}
field = "Off Above TPS", alternatorOffAboveTps, {isAlternatorControlEnabled == 1}
field = "Detailed status in console", isVerboseAlternator, {isAlternatorControlEnabled == 1}
field = "control period", alternatorControl_periodMs, {isAlternatorControlEnabled == 1}
field = "#PID control"
field = "offset", alternatorControl_offset, {isAlternatorControlEnabled == 1 && onOffAlternatorLogic == 0}
field = "P factor", alternatorControl_pFactor, {isAlternatorControlEnabled == 1 && onOffAlternatorLogic == 0}
@ -3401,6 +3400,7 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00"
field = "mapCamDetectionThreshold", mapCamDetectionThreshold
field = "mapCamAveragingLength", mapCamAveragingLength
field = "mapCamSkipFactor", mapCamSkipFactor
field = "mapCamLookForLowPeaks", mapCamLookForLowPeaks
field = "#System hacks"
field = "Global fuel correction", globalFuelCorrection
field = "MAP Averaging Logic @", mapAveragingSchedulingAtIndex

View File

@ -0,0 +1,11 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Launcher elm327_connector" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="com.rusefi.Launcher" />
<module name="ui" />
<option name="PROGRAM_PARAMETERS" value="elm327_connector" />
<option name="VM_PARAMETERS" value="-Dini_file_path=../firmware/tunerstudio -Dshow_etb_pane=true -Dhigh_speed_logger_rpm=10000" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@ -40,6 +40,7 @@ public class ControllerConnectorState {
port = PortDetector.autoDetectSerial(null).getSerialPort();
if (port == null)
throw new IllegalStateException("ECU serial not detected");
System.out.println("Auto-connected to " + port);
}
IoUtil.realHardwareConnect(linkManager, port);

View File

@ -12,7 +12,6 @@ import com.rusefi.Timeouts;
import com.rusefi.composite.CompositeEvent;
import com.rusefi.composite.CompositeParser;
import com.rusefi.config.generated.Fields;
import com.rusefi.core.MessagesCentral;
import com.rusefi.core.Pair;
import com.rusefi.core.Sensor;
import com.rusefi.core.SensorCentral;
@ -28,7 +27,6 @@ import com.rusefi.ui.livedocs.LiveDocsRegistry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@ -84,7 +82,7 @@ public class BinaryProtocol {
private boolean isCompositeLoggerEnabled;
private long lastLowRpmTime = System.currentTimeMillis();
private List<StreamFile> compositeLogs = new ArrayList<>();
private final List<StreamFile> compositeLogs = new ArrayList<>();
public static boolean DISABLE_LOCAL_CACHE;
public static String findCommand(byte command) {
@ -220,9 +218,9 @@ public class BinaryProtocol {
linkManager.getCommandQueue().handleConfirmationMessage(CommandQueue.CONFIRMATION_PREFIX + command);
}
public String getSignature() throws IOException {
public static String getSignature(IoStream stream) throws IOException {
HelloCommand.send(stream);
return HelloCommand.getHelloResponse(incomingData);
return HelloCommand.getHelloResponse(stream.getDataBuffer());
}
/**
@ -232,7 +230,7 @@ public class BinaryProtocol {
*/
public boolean connectAndReadConfiguration(DataListener listener) {
try {
signature = getSignature();
signature = getSignature(stream);
System.out.println("BinaryProtocol: Got " + signature + " signature");
SignatureHelper.downloadIfNotAvailable(SignatureHelper.getUrl(signature));
} catch (IOException e) {
@ -432,10 +430,7 @@ public class BinaryProtocol {
int crcOfLocallyCachedConfiguration = IoHelper.getCrc32(localCached.getContent());
log.info(String.format(CONFIGURATION_RUSEFI_BINARY + " Local cache CRC %x\n", crcOfLocallyCachedConfiguration));
byte packet[] = new byte[5];
packet[0] = Fields.TS_CRC_CHECK_COMMAND;
putShort(packet, 1, swap16(/*offset = */ 0));
putShort(packet, 3, swap16(localCached.getSize()));
byte[] packet = createCrcCommand(localCached.getSize());
byte[] response = executeCommand(packet, "get CRC32");
if (checkResponseCode(response, (byte) Fields.TS_RESPONSE_OK) && response.length == 5) {
@ -454,6 +449,14 @@ public class BinaryProtocol {
return null;
}
public static byte[] createCrcCommand(int size) {
byte[] packet = new byte[5];
packet[0] = Fields.TS_CRC_CHECK_COMMAND;
putShort(packet, 1, swap16(/*offset = */ 0));
putShort(packet, 3, swap16(size));
return packet;
}
public byte[] executeCommand(byte[] packet, String msg) {
return executeCommand(packet, msg, false);
}

View File

@ -140,6 +140,12 @@ public class IncomingDataBuffer {
return false; // looks good!
}
public int getPendingCount() {
synchronized (cbb) {
return cbb.length();
}
}
public void dropPending() {
// todo: when exactly do we need this logic?
synchronized (cbb) {

View File

@ -2,15 +2,12 @@ package com.rusefi.io.can;
import com.devexperts.logging.Logging;
import com.opensr5.io.DataListener;
import com.rusefi.config.generated.Fields;
import com.rusefi.io.IoStream;
import com.rusefi.io.serial.SerialIoStream;
import com.rusefi.io.tcp.BinaryProtocolProxy;
import com.rusefi.io.tcp.TcpConnector;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -21,81 +18,55 @@ public class Elm327Connector implements Closeable {
private final static Logging log = Logging.getLogging(Elm327Connector.class);
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes();
// public final static int ELM327_DEFAULT_BAUDRATE = 115200; // OBDlink SX, 1.3a
public final static int ELM327_DEFAULT_BAUDRATE = 38400;
private final static int BIG_TIMEOUT = 2 * SECOND;
private final static int TIMEOUT = 70;
public static final String HELLO = "ATZ";
public static final String ELM_EOL = "\r";
// those are inverted between ECU side and PC side
private static final int CAN_PC_SERIAL_RX_ID = Fields.CAN_ECU_SERIAL_TX_ID;
private static final int CAN_PC_SERIAL_TX_ID = Fields.CAN_ECU_SERIAL_RX_ID;
private final Object lock = new Object();
// these should match the defines in the firmware
private final static int CAN_SERIAL_TX_ID = 0x100;
private final static int CAN_SERIAL_RX_ID = 0x102;
private final static int ISO_TP_FRAME_SINGLE = 0;
private final static int ISO_TP_FRAME_FIRST = 1;
private final static int ISO_TP_FRAME_CONSECUTIVE = 2;
private final static int ISO_TP_FRAME_FLOW_CONTROL = 3;
private IoStream stream = null;
/**
* Connection to ELM327 device where text based ELM protocol happens
*/
private final IoStream underlyingStream;
/**
* Binary serial stream for TS traffic
*/
private final Elm327IoStream tsStream;
private String partialLine = "";
private final List<String> completeLines = new ArrayList<>();
private boolean isCommandMode = false;
private Elm327IoStream elmStream;
// CAN multiframe decoder state
static class CanDecoder {
public int waitingForNumBytes = 0;
public int waitingForFrameIndex = 0;
public byte [] decodePacket(byte [] data) throws Exception {
int frameType = (data[0] >> 4) & 0xf;
int numBytesAvailable, frameIdx;
int dataOffset;
switch (frameType) {
case ISO_TP_FRAME_SINGLE:
numBytesAvailable = data[0] & 0xf;
dataOffset = 1;
this.waitingForNumBytes = 0;
break;
case ISO_TP_FRAME_FIRST:
this.waitingForNumBytes = ((data[0] & 0xf) << 8) | data[1];
this.waitingForFrameIndex = 1;
numBytesAvailable = Math.min(this.waitingForNumBytes, 6);
dataOffset = 2;
break;
case ISO_TP_FRAME_CONSECUTIVE:
frameIdx = data[0] & 0xf;
if (this.waitingForNumBytes < 0 || this.waitingForFrameIndex != frameIdx) {
throw new Exception("ISO_TP_FRAME_CONSECUTIVE: That's an abnormal situation, and we probably should react?");
}
this.waitingForFrameIndex = (this.waitingForFrameIndex + 1) & 0xf;
numBytesAvailable = Math.min(this.waitingForNumBytes, 7);
dataOffset = 1;
break;
case ISO_TP_FRAME_FLOW_CONTROL:
throw new Exception("ISO_TP_FRAME_FLOW_CONTROL: should we just ignore the FC frame?");
default:
throw new Exception("Unknown frame type");
}
return Arrays.copyOfRange(data, dataOffset, dataOffset + numBytesAvailable);
}
public Elm327Connector(IoStream underlyingStream) {
this.underlyingStream = underlyingStream;
underlyingStream.setInputListener(listener);
tsStream = new Elm327IoStream(this, "elm327Stream");
}
public static boolean checkConnection(String serialPort, IoStream stream) {
Elm327Connector con = new Elm327Connector();
boolean found = con.initConnection(serialPort, stream);
con.close();
return found;
/**
* TODO: HUH? what's that about?!
*/
public static void whyDoWeNeedToSleepBetweenCommands() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
public void start(String serialPort) {
public Elm327IoStream getTsStream() {
return tsStream;
}
public void start(String msg) {
log.info("* Elm327.start()");
if (initConnection(serialPort, SerialIoStream.openPort(serialPort))) {
if (initConnection(msg)) {
// reset to defaults
sendCommand("ATD", "OK");
@ -107,16 +78,16 @@ public class Elm327Connector implements Closeable {
sendCommand("ATSP6", "OK");
// set rx ID
sendCommand("ATCF " + Integer.toHexString(CAN_SERIAL_RX_ID), "OK");
sendCommand("ATCF " + Integer.toHexString(CAN_PC_SERIAL_RX_ID), "OK");
// rx ID mask = "all bits set"
sendCommand("ATCM FFF", "OK");
// set tx ID
sendCommand("ATSH " + Integer.toHexString(CAN_SERIAL_TX_ID), "OK");
sendCommand("ATSH " + Integer.toHexString(CAN_PC_SERIAL_TX_ID), "OK");
// set FC tx ID (should match our tx ID)
sendCommand("ATFCSH " + Integer.toHexString(CAN_SERIAL_TX_ID), "OK");
sendCommand("ATFCSH " + Integer.toHexString(CAN_PC_SERIAL_TX_ID), "OK");
// set FC data
sendCommand("ATFCSD 30 00 00", "OK");
// use custom FC ID & data
@ -139,16 +110,13 @@ public class Elm327Connector implements Closeable {
log.info("* Ignition voltage = " + voltage);
}
startNetworkConnector(TcpConnector.DEFAULT_PORT);
//sendBytesToSerial(new byte[] { 0, 1, 83, 32, 96, (byte)239, (byte)195 });
//sendBytesToSerial(new byte[] { (byte)'V' });
}
@Override
public void close() {
log.info("* Elm327.close()");
if (stream != null)
stream.close();
if (underlyingStream != null)
underlyingStream.close();
}
private final DataListener listener = freshData -> {
@ -175,21 +143,21 @@ public class Elm327Connector implements Closeable {
};
public void sendBytesToSerial(byte [] bytes) {
log.info("-------sendBytesToSerial "+bytes.length+" bytes:");
log.info("-------sendBytesToSerial " + bytes.length + " byte(s):");
for (int i = 0; i < bytes.length; i++) {
log.info("["+i+"] " + ((int)bytes[i] & 0xff));
}
for (int i = 0; i < bytes.length; i++) {
log.info("[index=" + i + "] " + ((int) bytes[i] & 0xff));
}
// 1 frame
if (bytes.length <= 7) {
sendFrame((ISO_TP_FRAME_SINGLE << 4) | bytes.length, bytes, 0, bytes.length);
sendCanFrame((IsoTpCanDecoder.ISO_TP_FRAME_SINGLE << 4) | bytes.length, bytes, 0, bytes.length);
return;
}
// multiple frames
// send the first header frame
sendFrame((ISO_TP_FRAME_FIRST << 4) | ((bytes.length >> 8) & 0x0f), bytes.length & 0xff, bytes, 0, 6);
sendCanFrame((IsoTpCanDecoder.ISO_TP_FRAME_FIRST << 4) | ((bytes.length >> 8) & 0x0f), bytes.length & 0xff, bytes, 0, 6);
// get a flow control frame
receiveData();
@ -199,7 +167,7 @@ public class Elm327Connector implements Closeable {
while (remaining > 0) {
int len = Math.min(remaining, 7);
// send the consecutive frames
sendFrame((ISO_TP_FRAME_CONSECUTIVE << 4) | ((idx++) & 0x0f), bytes, offset, len);
sendCanFrame((IsoTpCanDecoder.ISO_TP_FRAME_CONSECUTIVE << 4) | ((idx++) & 0x0f), bytes, offset, len);
offset += len;
remaining -= len;
}
@ -207,15 +175,12 @@ public class Elm327Connector implements Closeable {
///////////////////////////////////////////////////////
private boolean initConnection(String msg, IoStream stream) {
this.stream = stream;
this.stream.setInputListener(listener);
private boolean initConnection(String msg) {
if (sendCommand(HELLO, "ELM327 v[0-9]+\\.[0-9]+", BIG_TIMEOUT) != null) {
log.info("ELM DETECTED on " + msg + "!");
log.info("ELM DETECTED on " + msg + "! " + ELM327_DEFAULT_BAUDRATE);
return true;
}
log.info("ELM NOT FOUND on " + msg + "!");
log.info("ELM NOT FOUND on " + msg + "! " + ELM327_DEFAULT_BAUDRATE);
return false;
}
@ -228,7 +193,7 @@ public class Elm327Connector implements Closeable {
isCommandMode = true;
this.completeLines.clear();
try {
this.stream.write((command + ELM_EOL).getBytes());
underlyingStream.write((command + ELM_EOL).getBytes());
waitForResponse(timeout);
} catch (IOException | InterruptedException ignore) {
return null;
@ -259,15 +224,15 @@ public class Elm327Connector implements Closeable {
return null;
}
private void sendFrame(int hdr0, byte [] data, int offset, int len) {
sendData(new byte[] { (byte)hdr0 }, data, offset, len);
private void sendCanFrame(int hdr0, byte [] data, int offset, int len) {
sendCanData(new byte[] { (byte)hdr0 }, data, offset, len);
}
private void sendFrame(int hdr0, int hdr1, byte [] data, int offset, int len) {
sendData(new byte[] { (byte)hdr0, (byte)hdr1 }, data, offset, len);
private void sendCanFrame(int hdr0, int hdr1, byte [] data, int offset, int len) {
sendCanData(new byte[] { (byte)hdr0, (byte)hdr1 }, data, offset, len);
}
private void sendData(byte [] hdr, byte [] data, int offset, int len) {
private void sendCanData(byte [] hdr, byte [] data, int offset, int len) {
//log.info("--------sendData offset="+Integer.toString(offset) + " len=" + Integer.toString(len) + "hdr.len=" + Integer.toString(hdr.length));
len += hdr.length;
@ -282,7 +247,7 @@ public class Elm327Connector implements Closeable {
//log.info("* Elm327.data: " + (new String(hexData)));
try {
this.stream.write(hexData);
underlyingStream.write(hexData);
} catch (IOException ignore) {
// ignore
}
@ -334,25 +299,13 @@ public class Elm327Connector implements Closeable {
private void sendDataBack(String line) {
byte [] canPacket = HexUtil.asBytes(line);
try {
elmStream.processCanPacket(canPacket);
} catch (Exception ignore) {
// todo: ?
}
tsStream.processCanPacket(canPacket);
}
private boolean startNetworkConnector(int controllerPort) {
try {
elmStream = new Elm327IoStream(this, "elm327Stream");
BinaryProtocolProxy.createProxy(elmStream, controllerPort, new BinaryProtocolProxy.ClientApplicationActivityListener() {
@Override
public void onActivity() {
}
});
} catch (IOException ignore) {
return false;
}
return true;
public static boolean checkConnection(String serialPort, IoStream stream) {
Elm327Connector con = new Elm327Connector(stream);
boolean found = con.initConnection(serialPort);
con.close();
return found;
}
}

View File

@ -3,15 +3,16 @@ package com.rusefi.io.can;
import com.opensr5.io.DataListener;
import com.rusefi.binaryprotocol.IncomingDataBuffer;
import com.rusefi.binaryprotocol.IoHelper;
import com.rusefi.io.ByteReader;
import com.rusefi.io.serial.AbstractIoStream;
import com.rusefi.shared.FileUtil;
import org.jetbrains.annotations.NotNull;
import java.io.*;
import java.nio.ByteBuffer;
import java.util.Arrays;
/**
*
*/
public class Elm327IoStream extends AbstractIoStream {
private final String loggingPrefix;
private final Elm327Connector con;
@ -22,27 +23,28 @@ public class Elm327IoStream extends AbstractIoStream {
// the buffer size is limited by CAN-TP protocol
private final static int OUT_BUFFER_SIZE = 4095;
private ByteBuffer inBuf;
private ByteBuffer outBuf;
private final ByteBuffer outBuf;
// this should match the TS_CAN_DEVICE_SHORT_PACKETS_IN_ONE_FRAME in the firmware
private final static boolean sendShortPacketsInOneFrame = true;
// todo: move this to rusefi_config.txt / prepend.txt?
private final static boolean sendShortPacketsInOneFrame = false;
//private final static boolean receiveShortPacketsInOneFrame = sendShortPacketsInOneFrame;
private final static boolean receiveShortPacketsInOneFrame = false;
private Elm327Connector.CanDecoder canDecoder = new Elm327Connector.CanDecoder();
private final IsoTpCanDecoder canDecoder = new IsoTpCanDecoder();
public Elm327IoStream(Elm327Connector con, String loggingPrefix) throws IOException {
public Elm327IoStream(Elm327Connector con, String loggingPrefix) {
this(con, loggingPrefix, DisconnectListener.VOID);
}
public Elm327IoStream(Elm327Connector con, String loggingPrefix, DisconnectListener disconnectListener) throws IOException {
private Elm327IoStream(Elm327Connector con, String loggingPrefix, DisconnectListener disconnectListener) {
this.con = con;
this.loggingPrefix = loggingPrefix;
this.disconnectListener = disconnectListener;
this.dataBuffer = IncomingDataBuffer.createDataBuffer(loggingPrefix, this);
inBuf = ByteBuffer.allocate(OUT_BUFFER_SIZE);
// ByteBuffer inBuf = ByteBuffer.allocate(OUT_BUFFER_SIZE);
outBuf = ByteBuffer.allocate(OUT_BUFFER_SIZE);
}
@ -62,6 +64,7 @@ public class Elm327IoStream extends AbstractIoStream {
return loggingPrefix;
}
@NotNull
@Override
public IncomingDataBuffer getDataBuffer() {
return dataBuffer;
@ -91,6 +94,7 @@ public class Elm327IoStream extends AbstractIoStream {
super.flush();
byte [] bytes;
// for smaller packets, send them in one 'simple' frame by stripping the header+footer off
// i.e. un-pack CRC32 TS protocol
// (2 = 16-bit length, 4 = 32-bit crc)
if (sendShortPacketsInOneFrame && outBuf.position() >= 2 + 1 + 4 && outBuf.position() <= 2 + 7 + 4) {
bytes = Arrays.copyOfRange(outBuf.array(), 2, outBuf.position() - 4);
@ -114,9 +118,7 @@ public class Elm327IoStream extends AbstractIoStream {
packet = new byte [2 + data.length + 4];
IoHelper.putShort(packet, 0, data.length);
for (int i = 0; i < data.length; i++) {
packet[i + 2] = data[i];
}
System.arraycopy(data, 0, packet, 2, data.length);
int crc = IoHelper.getCrc32(data);
IoHelper.putInt(packet, 2 + data.length, crc);
} else {
@ -127,9 +129,10 @@ public class Elm327IoStream extends AbstractIoStream {
dataListener.onDataArrived(packet);
}
public void processCanPacket(byte [] data) throws Exception {
public void processCanPacket(byte [] data) {
byte [] rawData = canDecoder.decodePacket(data);
sendDataToClient(rawData);
if (rawData.length != 0)
sendDataToClient(rawData);
}
public interface DisconnectListener {

View File

@ -0,0 +1,75 @@
package com.rusefi.io.can;
import com.devexperts.logging.Logging;
import com.rusefi.io.IoStream;
import java.util.Arrays;
// CAN multiframe decoder state
class IsoTpCanDecoder {
private static Logging log = Logging.getLogging(IsoTpCanDecoder.class);
static {
log.configureDebugEnabled(false);
}
private final static int ISO_TP_FRAME_FLOW_CONTROL = 3;
final static int ISO_TP_FRAME_SINGLE = 0;
final static int ISO_TP_FRAME_FIRST = 1;
final static int ISO_TP_FRAME_CONSECUTIVE = 2;
private final static int FC_ContinueToSend = 0;
public int waitingForNumBytes = 0;
public int waitingForFrameIndex = 0;
public byte[] decodePacket(byte[] data) {
int frameType = (data[0] >> 4) & 0xf;
int numBytesAvailable;
int frameIdx;
int dataOffset;
switch (frameType) {
case ISO_TP_FRAME_SINGLE:
numBytesAvailable = data[0] & 0xf;
dataOffset = 1;
this.waitingForNumBytes = 0;
if (log.debugEnabled())
log.debug("ISO_TP_FRAME_SINGLE " + numBytesAvailable);
break;
case ISO_TP_FRAME_FIRST:
this.waitingForNumBytes = ((data[0] & 0xf) << 8) | data[1];
if (log.debugEnabled())
log.debug("Total expected: " + waitingForNumBytes);
this.waitingForFrameIndex = 1;
numBytesAvailable = Math.min(this.waitingForNumBytes, 6);
waitingForNumBytes -= numBytesAvailable;
dataOffset = 2;
break;
case ISO_TP_FRAME_CONSECUTIVE:
frameIdx = data[0] & 0xf;
if (this.waitingForNumBytes < 0 || this.waitingForFrameIndex != frameIdx) {
throw new IllegalStateException("ISO_TP_FRAME_CONSECUTIVE: That's an abnormal situation, and we probably should react? " + waitingForNumBytes + " " + waitingForFrameIndex + " " + frameIdx);
}
this.waitingForFrameIndex = (this.waitingForFrameIndex + 1) & 0xf;
numBytesAvailable = Math.min(this.waitingForNumBytes, 7);
dataOffset = 1;
waitingForNumBytes -= numBytesAvailable;
if (log.debugEnabled())
log.debug("ISO_TP_FRAME_CONSECUTIVE Got " + numBytesAvailable + ", still expecting: " + waitingForNumBytes);
break;
case ISO_TP_FRAME_FLOW_CONTROL:
int flowStatus = data[0] & 0xf;
int blockSize = data[1];
int separationTime = data[2];
if (flowStatus == FC_ContinueToSend && blockSize == 0 && separationTime == 0)
return new byte[0];
throw new IllegalStateException("ISO_TP_FRAME_FLOW_CONTROL: should we just ignore the FC frame? " + flowStatus + " " + blockSize + " " + separationTime);
default:
throw new IllegalStateException("Unknown frame type");
}
byte[] bytes = Arrays.copyOfRange(data, dataOffset, dataOffset + numBytesAvailable);
if (log.debugEnabled())
log.debug(numBytesAvailable + " bytes(s) arrived in this packet: " + IoStream.printHexBinary(bytes));
return bytes;
}
}

View File

@ -1,25 +1,100 @@
package com.rusefi.binaryprotocol.test;
import com.rusefi.binaryprotocol.BinaryProtocol;
import com.rusefi.binaryprotocol.IncomingDataBuffer;
import com.rusefi.config.generated.Fields;
import com.rusefi.io.ConnectionStateListener;
import com.rusefi.io.IoStream;
import com.rusefi.io.LinkManager;
import com.rusefi.io.can.Elm327Connector;
import com.rusefi.io.serial.BaudRateHolder;
import com.rusefi.io.serial.BufferedSerialIoStream;
import com.rusefi.io.serial.SerialIoStream;
import com.rusefi.io.serial.StreamConnector;
import java.io.IOException;
import static com.rusefi.Timeouts.SECOND;
import static com.rusefi.binaryprotocol.IoHelper.checkResponseCode;
import static com.rusefi.io.can.Elm327Connector.ELM327_DEFAULT_BAUDRATE;
import static com.rusefi.io.can.Elm327Connector.ELM_EOL;
public class Elm327Sandbox {
public static void main(String[] args) throws InterruptedException, IOException {
BaudRateHolder.INSTANCE.baudRate = ELM327_DEFAULT_BAUDRATE;
String serialPort = "COM5";
String serialPort = "COM7";
Elm327Connector connector = new Elm327Connector(SerialIoStream.openPort(serialPort));
connector.start(serialPort);
IoStream stream = BufferedSerialIoStream.openPort(serialPort);
stream.setInputListener(freshData -> System.out.println("onDataArrived"));
IoStream tsStream = connector.getTsStream();
IncomingDataBuffer dataBuffer = tsStream.getDataBuffer();
System.out.println("Hello new ELM327 connection, pending=" + dataBuffer.getPendingCount());
runFcommand("First time", tsStream);
Elm327Connector.whyDoWeNeedToSleepBetweenCommands();
runFcommand("Second time", tsStream);
Elm327Connector.whyDoWeNeedToSleepBetweenCommands();
{
String signature = BinaryProtocol.getSignature(tsStream);
System.out.println("Got " + signature + " signature via CAN/ELM327");
if (signature == null)
return;
}
Elm327Connector.whyDoWeNeedToSleepBetweenCommands();
{
String signature = BinaryProtocol.getSignature(tsStream);
System.out.println("Let's do it again! Got " + signature + " signature via CAN/ELM327");
if (signature == null)
return;
}
Elm327Connector.whyDoWeNeedToSleepBetweenCommands();
{
tsStream.sendPacket(new byte[]{Fields.TS_HELLO_COMMAND});
byte[] response = dataBuffer.getPacket("[hello command]");
if (!checkResponseCode(response, (byte) Fields.TS_RESPONSE_OK))
return;
String signature = new String(response, 1, response.length - 1);
System.out.println(Fields.TS_HELLO_COMMAND + " returned " + signature);
}
Elm327Connector.whyDoWeNeedToSleepBetweenCommands();
{
tsStream.sendPacket(BinaryProtocol.createCrcCommand(1000));
byte[] fResponse = new byte[3];
dataBuffer.waitForBytes("CRC", System.currentTimeMillis(), fResponse.length);
dataBuffer.getData(fResponse);
System.out.println(" Got CRC response " + IoStream.printHexBinary(fResponse));
}
LinkManager linkManager = new LinkManager();
StreamConnector streamConnector = new StreamConnector(linkManager, () -> tsStream);
linkManager.setConnector(streamConnector);
streamConnector.connectAndReadConfiguration(new ConnectionStateListener() {
@Override
public void onConnectionEstablished() {
System.out.println("onConnectionEstablished");
}
@Override
public void onConnectionFailed() {
System.out.println("onConnectionFailed");
}
});
stream.write((Elm327Connector.HELLO + ELM_EOL).getBytes());
Thread.sleep(6 * SECOND);
}
private static void runFcommand(String prefix, IoStream tsStream) throws IOException {
IncomingDataBuffer dataBuffer = tsStream.getDataBuffer();
tsStream.sendPacket(new byte[]{Fields.TS_COMMAND_F});
byte[] fResponse = new byte[3];
dataBuffer.waitForBytes("hello", System.currentTimeMillis(), fResponse.length);
dataBuffer.getData(fResponse);
System.out.println(prefix + " Got F response " + IoStream.printHexBinary(fResponse));
}
}

View File

@ -6,7 +6,7 @@ import java.net.URL;
import java.util.concurrent.atomic.AtomicReference;
public class rusEFIVersion {
public static final int CONSOLE_VERSION = 20211130;
public static final int CONSOLE_VERSION = 20211206;
public static AtomicReference<String> firmwareVersion = new AtomicReference<>("N/A");
public static long classBuildTimeMillis() {

View File

@ -4,11 +4,16 @@ import com.devexperts.logging.Logging;
import com.rusefi.autodetect.PortDetector;
import com.rusefi.autodetect.SerialAutoChecker;
import com.rusefi.io.can.Elm327Connector;
import com.rusefi.io.serial.SerialIoStream;
import com.rusefi.io.tcp.BinaryProtocolProxy;
import com.rusefi.io.tcp.TcpConnector;
import java.io.IOException;
public class Elm327ConnectorStartup {
private final static Logging log = Logging.getLogging(Elm327ConnectorStartup.class);
public static void start() {
public static void start() throws IOException {
SerialAutoChecker.AutoDetectResult detectResult = PortDetector.autoDetectSerial(null, PortDetector.DetectorMode.DETECT_ELM327);
String autoDetectedPort = detectResult.getSerialPort();
//String autoDetectedPort = "COM73";
@ -17,7 +22,17 @@ public class Elm327ConnectorStartup {
return;
}
new Elm327Connector().start(autoDetectedPort);
Elm327Connector elm327Connector = new Elm327Connector(SerialIoStream.openPort(autoDetectedPort));
elm327Connector.start(autoDetectedPort);
BinaryProtocolProxy.createProxy(elm327Connector.getTsStream(), TcpConnector.DEFAULT_PORT, new BinaryProtocolProxy.ClientApplicationActivityListener() {
@Override
public void onActivity() {
System.out.println("onActivity");
Elm327Connector.whyDoWeNeedToSleepBetweenCommands();
}
});
log.info("Running Elm327 connector for " + autoDetectedPort);
}
}

View File

@ -131,6 +131,7 @@ public class EngineSnifferPanel {
JPanel lowerButtons = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
lowerButtons.add(new ConfigField(uiContext, Fields.GLOBALTRIGGERANGLEOFFSET, "Trigger Offset").getContent());
lowerButtons.add(new BitConfigField(uiContext, Fields.VERBOSETRIGGERSYNCHDETAILS, "Verbose trigger Sync").getContent());
lowerButtons.add(new BitConfigField(uiContext, Fields.VERBOSEVVTDECODING, "Verbose VVT Sync").getContent());
lowerButtons.add(new BitConfigField(uiContext, Fields.ISENGINECHARTENABLED, "Collect Engine Data").getContent());
lowerButtons.add(new ConfigField(uiContext, Fields.ENGINECHARTSIZE, "Engine Sniffer size").getContent());
lowerButtons.add(new ConfigField(uiContext, Fields.ENGINESNIFFERRPMTHRESHOLD, "RPM threshold").getContent());

View File

@ -0,0 +1,2 @@
STM32_Programmer_CLI.exe -c port=usb1 -r 0x08000000 0x0020000 dump_f0.hex

View File

@ -29,22 +29,43 @@ TEST(trigger, map_cam) {
MapState state;
int i = 0;
for (;i<404;i++) {
for (;i<403;i++) {
state.add(getZigZag(i));
if (state.mapBuffer.getCount() > engineConfiguration->mapCamAveragingLength) {
ASSERT_FALSE(state.isPeak()) << "At " << i;
ASSERT_FALSE(state.isPeak(false)) << "high At " << i;
ASSERT_FALSE(state.isPeak(true)) << "low At " << i;
}
}
state.add(getZigZag(i));
ASSERT_TRUE(state.isPeak()) << "At " << i;
ASSERT_FALSE(state.isPeak(false)) << "high At " << i;
ASSERT_FALSE(state.isPeak(true)) << "low At " << i;
i++;
for (;i<604;i++) {
state.add(getZigZag(i));
ASSERT_TRUE(state.isPeak(false)) << "high At " << i;
ASSERT_FALSE(state.isPeak(true)) << "low At " << i;
for (;i<504;i++) {
state.add(getZigZag(i));
ASSERT_FALSE(state.isPeak()) << "At " << i;
ASSERT_FALSE(state.isPeak(false)) << "high At " << i;
ASSERT_FALSE(state.isPeak(true)) << "low At " << i;
}
state.add(getZigZag(i));
ASSERT_TRUE(state.isPeak()) << "At " << i;
ASSERT_FALSE(state.isPeak(false)) << "high At " << i;
ASSERT_TRUE(state.isPeak(true)) << "low At " << i;
i++;
for (;i<604;i++) {
state.add(getZigZag(i));
ASSERT_FALSE(state.isPeak(false)) << "high At " << i;
ASSERT_FALSE(state.isPeak(true)) << "low At " << i;
}
state.add(getZigZag(i));
ASSERT_TRUE(state.isPeak(false)) << "high At " << i;
ASSERT_TRUE(state.isPeak(false)) << "low At " << i;
}