auto-sync
This commit is contained in:
parent
09077f84ec
commit
53ebcf4c17
|
@ -73,8 +73,6 @@ extern bool main_loop_started;
|
|||
#include "vehicle_speed.h"
|
||||
#endif
|
||||
|
||||
extern engine_pins_s enginePins;
|
||||
|
||||
static bool subscription[(int) RO_LAST_ELEMENT];
|
||||
|
||||
// this 'true' value is needed for simulator
|
||||
|
@ -521,7 +519,6 @@ static THD_WORKING_AREA(blinkingStack, 128);
|
|||
static OutputPin communicationPin;
|
||||
OutputPin warningPin;
|
||||
OutputPin runningPin;
|
||||
extern engine_pins_s enginePins;
|
||||
|
||||
static OutputPin *leds[] = { &warningPin, &runningPin, &enginePins.errorLedPin, &communicationPin, &enginePins.checkEnginePin };
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
static LoggingWithStorage logger("engine");
|
||||
|
||||
extern engine_pins_s enginePins;
|
||||
extern fuel_Map3D_t veMap;
|
||||
extern afr_Map3D_t afrMap;
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ EXTERN_ENGINE
|
|||
static Logging *logger;
|
||||
|
||||
extern pin_output_mode_e DEFAULT_OUTPUT;
|
||||
extern engine_pins_s enginePins;
|
||||
int alternatorPidResetCounter = 0;
|
||||
|
||||
static SimplePwm alternatorControl;
|
||||
|
|
|
@ -61,8 +61,6 @@ static float currentEtbDuty;
|
|||
|
||||
EXTERN_ENGINE;
|
||||
|
||||
extern engine_pins_s enginePins;
|
||||
|
||||
static bool wasEtbBraking = false;
|
||||
|
||||
static msg_t etbThread(void *arg) {
|
||||
|
|
|
@ -40,7 +40,6 @@ static THD_WORKING_AREA(ivThreadStack, UTILITY_THREAD_STACK_SIZE);
|
|||
|
||||
static Logging *logger;
|
||||
extern TunerStudioOutputChannels tsOutputChannels;
|
||||
extern engine_pins_s enginePins;
|
||||
EXTERN_ENGINE
|
||||
;
|
||||
|
||||
|
|
|
@ -448,11 +448,6 @@ void setTimingLoadBin(float from, float to DECLARE_ENGINE_PARAMETER_S) {
|
|||
setTableBin(config->ignitionLoadBins, IGN_LOAD_COUNT, from, to);
|
||||
}
|
||||
|
||||
int isInjectionEnabled(engine_configuration_s *engineConfiguration) {
|
||||
// todo: is this worth a method? should this be inlined?
|
||||
return engineConfiguration->isInjectionEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* this method sets algorithm and ignition table scale
|
||||
*/
|
||||
|
|
|
@ -154,7 +154,5 @@ void seTurnPinHigh(InjectorOutputPin *output);
|
|||
void seTurnPinLow(InjectorOutputPin *output);
|
||||
void turnPinHigh(NamedOutputPin *output);
|
||||
void turnPinLow(NamedOutputPin *output);
|
||||
void turnSparkPinHigh(NamedOutputPin *output);
|
||||
void turnSparkPinLow(NamedOutputPin *output);
|
||||
|
||||
#endif /* EFIGPIO_H_ */
|
||||
|
|
|
@ -66,17 +66,6 @@ extern bool hasFirmwareErrorFlag;
|
|||
static LocalVersionHolder triggerVersion;
|
||||
static const char *prevOutputName = NULL;
|
||||
|
||||
extern engine_pins_s enginePins;
|
||||
|
||||
/**
|
||||
* In order to archive higher event precision, we are using a hybrid approach
|
||||
* where we are scheduling events based on the closest trigger event with a time offset.
|
||||
*
|
||||
* This queue is using global trigger event index as 'time'
|
||||
*/
|
||||
//static EventQueue triggerEventsQueue;
|
||||
static cyclic_buffer<int> ignitionErrorDetection;
|
||||
|
||||
static Logging *logger;
|
||||
|
||||
// todo: figure out if this even helps?
|
||||
|
@ -291,134 +280,6 @@ static ALWAYS_INLINE void handleFuel(const bool limitedFuel, uint32_t trgEventIn
|
|||
}
|
||||
}
|
||||
|
||||
void turnSparkPinLow(NamedOutputPin *output) {
|
||||
turnPinLow(output);
|
||||
#if EFI_PROD_CODE || defined(__DOXYGEN__)
|
||||
if (CONFIG(dizzySparkOutputPin) != GPIO_UNASSIGNED) {
|
||||
turnPinLow(&enginePins.dizzyOutput);
|
||||
}
|
||||
#endif /* EFI_PROD_CODE */
|
||||
}
|
||||
|
||||
void turnSparkPinHigh(NamedOutputPin *output) {
|
||||
turnPinHigh(output);
|
||||
#if EFI_PROD_CODE || defined(__DOXYGEN__)
|
||||
if (CONFIG(dizzySparkOutputPin) != GPIO_UNASSIGNED) {
|
||||
turnPinHigh(&enginePins.dizzyOutput);
|
||||
}
|
||||
#endif /* EFI_PROD_CODE */
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventIndex, IgnitionEvent *iEvent,
|
||||
int rpm DECLARE_ENGINE_PARAMETER_S) {
|
||||
|
||||
float dwellMs = ENGINE(engineState.sparkDwell);
|
||||
if (cisnan(dwellMs) || dwellMs < 0) {
|
||||
warning(CUSTOM_OBD_45, "invalid dwell: %f at %d", dwellMs, rpm);
|
||||
return;
|
||||
}
|
||||
|
||||
floatus_t chargeDelayUs = ENGINE(rpmCalculator.oneDegreeUs) * iEvent->dwellPosition.angleOffset;
|
||||
int isIgnitionError = chargeDelayUs < 0;
|
||||
ignitionErrorDetection.add(isIgnitionError);
|
||||
if (isIgnitionError) {
|
||||
#if EFI_PROD_CODE || defined(__DOXYGEN__)
|
||||
scheduleMsg(logger, "Negative spark delay=%f", chargeDelayUs);
|
||||
#endif
|
||||
chargeDelayUs = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cisnan(dwellMs)) {
|
||||
firmwareError("NaN in scheduleOutput", dwellMs);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* We are alternating two event lists in order to avoid a potential issue around revolution boundary
|
||||
* when an event is scheduled within the next revolution.
|
||||
*/
|
||||
scheduling_s * sUp = &iEvent->signalTimerUp;
|
||||
scheduling_s * sDown = &iEvent->signalTimerDown;
|
||||
|
||||
/**
|
||||
* The start of charge is always within the current trigger event range, so just plain time-based scheduling
|
||||
*/
|
||||
if (!limitedSpark) {
|
||||
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
|
||||
printf("spark charge delay=%f\r\n", chargeDelayUs);
|
||||
#endif
|
||||
/**
|
||||
* Note how we do not check if spark is limited or not while scheduling 'spark down'
|
||||
* This way we make sure that coil dwell started while spark was enabled would fire and not burn
|
||||
* the coil.
|
||||
*/
|
||||
scheduleTask("spark up", sUp, chargeDelayUs, (schfunc_t) &turnSparkPinHigh, iEvent->output);
|
||||
}
|
||||
/**
|
||||
* Spark event is often happening during a later trigger event timeframe
|
||||
* TODO: improve precision
|
||||
*/
|
||||
findTriggerPosition(&iEvent->sparkPosition, iEvent->advance PASS_ENGINE_PARAMETER);
|
||||
|
||||
if (iEvent->sparkPosition.eventIndex == trgEventIndex) {
|
||||
/**
|
||||
* Spark should be fired before the next trigger event - time-based delay is best precision possible
|
||||
*/
|
||||
float timeTillIgnitionUs = ENGINE(rpmCalculator.oneDegreeUs) * iEvent->sparkPosition.angleOffset;
|
||||
|
||||
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
|
||||
printf("spark delay=%f angle=%f\r\n", timeTillIgnitionUs, iEvent->sparkPosition.angleOffset);
|
||||
#endif
|
||||
|
||||
scheduleTask("spark1 down", sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnSparkPinLow, iEvent->output);
|
||||
} else {
|
||||
/**
|
||||
* Spark should be scheduled in relation to some future trigger event, this way we get better firing precision
|
||||
*/
|
||||
bool isPending = assertNotInList<IgnitionEvent>(ENGINE(iHead), iEvent);
|
||||
if (isPending)
|
||||
return;
|
||||
|
||||
LL_APPEND(ENGINE(iHead), iEvent);
|
||||
}
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void handleSpark(bool limitedSpark, uint32_t trgEventIndex, int rpm,
|
||||
IgnitionEventList *list DECLARE_ENGINE_PARAMETER_S) {
|
||||
if (!isValidRpm(rpm) || !CONFIG(isIgnitionEnabled)) {
|
||||
// this might happen for instance in case of a single trigger event after a pause
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Ignition schedule is defined once per revolution
|
||||
* See initializeIgnitionActions()
|
||||
*/
|
||||
|
||||
IgnitionEvent *current, *tmp;
|
||||
|
||||
LL_FOREACH_SAFE(ENGINE(iHead), current, tmp)
|
||||
{
|
||||
if (current->sparkPosition.eventIndex == trgEventIndex) {
|
||||
// time to fire a spark which was scheduled previously
|
||||
LL_DELETE(ENGINE(iHead), current);
|
||||
|
||||
scheduling_s * sDown = ¤t->signalTimerDown;
|
||||
|
||||
float timeTillIgnitionUs = ENGINE(rpmCalculator.oneDegreeUs) * current->sparkPosition.angleOffset;
|
||||
scheduleTask("spark 2down", sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnSparkPinLow, current->output);
|
||||
}
|
||||
}
|
||||
|
||||
// scheduleSimpleMsg(&logger, "eventId spark ", eventIndex);
|
||||
for (int i = 0; i < list->size; i++) {
|
||||
IgnitionEvent *event = &list->elements[i];
|
||||
if (event->dwellPosition.eventIndex != trgEventIndex)
|
||||
continue;
|
||||
handleSparkEvent(limitedSpark, trgEventIndex, event, rpm PASS_ENGINE_PARAMETER);
|
||||
}
|
||||
}
|
||||
|
||||
static histogram_s mainLoopHisto;
|
||||
|
||||
void showMainHistogram(void) {
|
||||
|
@ -572,8 +433,6 @@ void mainTriggerCallback(trigger_event_e ckpSignalType, uint32_t trgEventIndex D
|
|||
scheduleIgnitionAndFuelEvents(rpm, revolutionIndex PASS_ENGINE_PARAMETER);
|
||||
}
|
||||
|
||||
// triggerEventsQueue.executeAll(getCrankEventCounter());
|
||||
|
||||
/**
|
||||
* For fuel we schedule start of injection based on trigger angle, and then inject for
|
||||
* specified duration of time
|
||||
|
@ -619,6 +478,7 @@ static void showMainInfo(Engine *engine) {
|
|||
void initMainEventListener(Logging *sharedLogger, Engine *engine) {
|
||||
logger = sharedLogger;
|
||||
efiAssertVoid(engine!=NULL, "null engine");
|
||||
initSparkLogic(logger);
|
||||
|
||||
#if EFI_PROD_CODE || defined(__DOXYGEN__)
|
||||
addConsoleAction("performanceinfo", showTriggerHistogram);
|
||||
|
@ -636,8 +496,4 @@ void initMainEventListener(Logging *sharedLogger, Engine *engine) {
|
|||
addTriggerEventListener(mainTriggerCallback, "main loop", engine);
|
||||
}
|
||||
|
||||
int isIgnitionTimingError(void) {
|
||||
return ignitionErrorDetection.sum(6) > 4;
|
||||
}
|
||||
|
||||
#endif /* EFI_ENGINE_CONTROL */
|
||||
|
|
|
@ -5,6 +5,152 @@
|
|||
* @author Andrey Belomutskiy, (c) 2012-2016
|
||||
*/
|
||||
|
||||
#include "engine_math.h"
|
||||
#include "utlist.h"
|
||||
#include "event_queue.h"
|
||||
|
||||
EXTERN_ENGINE;
|
||||
|
||||
static cyclic_buffer<int> ignitionErrorDetection;
|
||||
static Logging *logger;
|
||||
|
||||
int isInjectionEnabled(engine_configuration_s *engineConfiguration) {
|
||||
// todo: is this worth a method? should this be inlined?
|
||||
return engineConfiguration->isInjectionEnabled;
|
||||
}
|
||||
|
||||
int isIgnitionTimingError(void) {
|
||||
return ignitionErrorDetection.sum(6) > 4;
|
||||
}
|
||||
|
||||
void turnSparkPinLow(NamedOutputPin *output) {
|
||||
turnPinLow(output);
|
||||
#if EFI_PROD_CODE || defined(__DOXYGEN__)
|
||||
if (CONFIG(dizzySparkOutputPin) != GPIO_UNASSIGNED) {
|
||||
turnPinLow(&enginePins.dizzyOutput);
|
||||
}
|
||||
#endif /* EFI_PROD_CODE */
|
||||
}
|
||||
|
||||
void turnSparkPinHigh(NamedOutputPin *output) {
|
||||
turnPinHigh(output);
|
||||
#if EFI_PROD_CODE || defined(__DOXYGEN__)
|
||||
if (CONFIG(dizzySparkOutputPin) != GPIO_UNASSIGNED) {
|
||||
turnPinHigh(&enginePins.dizzyOutput);
|
||||
}
|
||||
#endif /* EFI_PROD_CODE */
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventIndex, IgnitionEvent *iEvent,
|
||||
int rpm DECLARE_ENGINE_PARAMETER_S) {
|
||||
|
||||
float dwellMs = ENGINE(engineState.sparkDwell);
|
||||
if (cisnan(dwellMs) || dwellMs < 0) {
|
||||
warning(CUSTOM_OBD_45, "invalid dwell: %f at %d", dwellMs, rpm);
|
||||
return;
|
||||
}
|
||||
|
||||
floatus_t chargeDelayUs = ENGINE(rpmCalculator.oneDegreeUs) * iEvent->dwellPosition.angleOffset;
|
||||
int isIgnitionError = chargeDelayUs < 0;
|
||||
ignitionErrorDetection.add(isIgnitionError);
|
||||
if (isIgnitionError) {
|
||||
#if EFI_PROD_CODE || defined(__DOXYGEN__)
|
||||
scheduleMsg(logger, "Negative spark delay=%f", chargeDelayUs);
|
||||
#endif
|
||||
chargeDelayUs = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cisnan(dwellMs)) {
|
||||
firmwareError("NaN in scheduleOutput", dwellMs);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* We are alternating two event lists in order to avoid a potential issue around revolution boundary
|
||||
* when an event is scheduled within the next revolution.
|
||||
*/
|
||||
scheduling_s * sUp = &iEvent->signalTimerUp;
|
||||
scheduling_s * sDown = &iEvent->signalTimerDown;
|
||||
|
||||
/**
|
||||
* The start of charge is always within the current trigger event range, so just plain time-based scheduling
|
||||
*/
|
||||
if (!limitedSpark) {
|
||||
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
|
||||
printf("spark charge delay=%f\r\n", chargeDelayUs);
|
||||
#endif
|
||||
/**
|
||||
* Note how we do not check if spark is limited or not while scheduling 'spark down'
|
||||
* This way we make sure that coil dwell started while spark was enabled would fire and not burn
|
||||
* the coil.
|
||||
*/
|
||||
scheduleTask("spark up", sUp, chargeDelayUs, (schfunc_t) &turnSparkPinHigh, iEvent->output);
|
||||
}
|
||||
/**
|
||||
* Spark event is often happening during a later trigger event timeframe
|
||||
* TODO: improve precision
|
||||
*/
|
||||
findTriggerPosition(&iEvent->sparkPosition, iEvent->advance PASS_ENGINE_PARAMETER);
|
||||
|
||||
if (iEvent->sparkPosition.eventIndex == trgEventIndex) {
|
||||
/**
|
||||
* Spark should be fired before the next trigger event - time-based delay is best precision possible
|
||||
*/
|
||||
float timeTillIgnitionUs = ENGINE(rpmCalculator.oneDegreeUs) * iEvent->sparkPosition.angleOffset;
|
||||
|
||||
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
|
||||
printf("spark delay=%f angle=%f\r\n", timeTillIgnitionUs, iEvent->sparkPosition.angleOffset);
|
||||
#endif
|
||||
|
||||
scheduleTask("spark1 down", sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnSparkPinLow, iEvent->output);
|
||||
} else {
|
||||
/**
|
||||
* Spark should be scheduled in relation to some future trigger event, this way we get better firing precision
|
||||
*/
|
||||
bool isPending = assertNotInList<IgnitionEvent>(ENGINE(iHead), iEvent);
|
||||
if (isPending)
|
||||
return;
|
||||
|
||||
LL_APPEND(ENGINE(iHead), iEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void handleSpark(bool limitedSpark, uint32_t trgEventIndex, int rpm,
|
||||
IgnitionEventList *list DECLARE_ENGINE_PARAMETER_S) {
|
||||
if (!isValidRpm(rpm) || !CONFIG(isIgnitionEnabled)) {
|
||||
// this might happen for instance in case of a single trigger event after a pause
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Ignition schedule is defined once per revolution
|
||||
* See initializeIgnitionActions()
|
||||
*/
|
||||
|
||||
IgnitionEvent *current, *tmp;
|
||||
|
||||
LL_FOREACH_SAFE(ENGINE(iHead), current, tmp)
|
||||
{
|
||||
if (current->sparkPosition.eventIndex == trgEventIndex) {
|
||||
// time to fire a spark which was scheduled previously
|
||||
LL_DELETE(ENGINE(iHead), current);
|
||||
|
||||
scheduling_s * sDown = ¤t->signalTimerDown;
|
||||
|
||||
float timeTillIgnitionUs = ENGINE(rpmCalculator.oneDegreeUs) * current->sparkPosition.angleOffset;
|
||||
scheduleTask("spark 2down", sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnSparkPinLow, current->output);
|
||||
}
|
||||
}
|
||||
|
||||
// scheduleSimpleMsg(&logger, "eventId spark ", eventIndex);
|
||||
for (int i = 0; i < list->size; i++) {
|
||||
IgnitionEvent *event = &list->elements[i];
|
||||
if (event->dwellPosition.eventIndex != trgEventIndex)
|
||||
continue;
|
||||
handleSparkEvent(limitedSpark, trgEventIndex, event, rpm PASS_ENGINE_PARAMETER);
|
||||
}
|
||||
}
|
||||
|
||||
void initSparkLogic(Logging *sharedLogger) {
|
||||
logger = sharedLogger;
|
||||
}
|
||||
|
|
|
@ -11,5 +11,10 @@
|
|||
#include "engine.h"
|
||||
|
||||
int isInjectionEnabled(engine_configuration_s *engineConfiguration);
|
||||
void handleSpark(bool limitedSpark, uint32_t trgEventIndex, int rpm,
|
||||
IgnitionEventList *list DECLARE_ENGINE_PARAMETER_S);
|
||||
void initSparkLogic(Logging *sharedLogger);
|
||||
void turnSparkPinHigh(NamedOutputPin *output);
|
||||
void turnSparkPinLow(NamedOutputPin *output);
|
||||
|
||||
#endif /* CONTROLLERS_TRIGGER_SPARK_LOGIC_H_ */
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
|
||||
EXTERN_ENGINE
|
||||
;
|
||||
extern engine_pins_s enginePins;
|
||||
|
||||
static cyclic_buffer<int> errorDetection;
|
||||
static bool isInitializingTrigger = false; // #286 miata NA config - sync error on startup
|
||||
|
|
|
@ -90,7 +90,8 @@ typedef VirtualTimer virtual_timer_t;
|
|||
extern persistent_config_container_s persistentState; \
|
||||
extern Engine _engine; \
|
||||
extern persistent_config_s *config; \
|
||||
extern engine_configuration2_s * engineConfiguration2
|
||||
extern engine_configuration2_s * engineConfiguration2; \
|
||||
extern engine_pins_s enginePins
|
||||
|
||||
#define DECLARE_ENGINE_PARAMETER_F void
|
||||
#define DECLARE_ENGINE_PARAMETER_S
|
||||
|
|
|
@ -52,7 +52,6 @@ EXTERN_ENGINE
|
|||
;
|
||||
extern bool hasFirmwareErrorFlag;
|
||||
extern engine_configuration_s activeConfiguration;
|
||||
extern engine_pins_s enginePins;
|
||||
|
||||
static Mutex spiMtx;
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ CPPSRC = $(UTILSRC_CPP) \
|
|||
$(SYSTEMSRC_CPP) \
|
||||
$(PROJECT_DIR)/controllers/trigger/trigger_central.cpp \
|
||||
$(PROJECT_DIR)/controllers/trigger/rpm_calculator.cpp \
|
||||
$(PROJECT_DIR)/controllers/trigger/spark_logic.cpp \
|
||||
$(PROJECT_DIR)/controllers/trigger/main_trigger_callback.cpp \
|
||||
main.cpp
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ typedef int bool_t;
|
|||
|
||||
#define CCM_OPTIONAL
|
||||
|
||||
#define EXTERN_ENGINE
|
||||
#define EXTERN_ENGINE extern engine_pins_s enginePins
|
||||
|
||||
#ifdef __cplusplus
|
||||
class Engine;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "engine_test_helper.h"
|
||||
#include "speed_density.h"
|
||||
#include "fuel_math.h"
|
||||
#include "spark_logic.h"
|
||||
|
||||
extern int timeNow;
|
||||
extern float unitTestValue;
|
||||
|
|
|
@ -99,7 +99,8 @@ void applyNewConfiguration(void);
|
|||
extern board_configuration_s *boardConfiguration; \
|
||||
extern persistent_config_s *config; \
|
||||
extern persistent_config_container_s persistentState; \
|
||||
extern engine_configuration2_s * engineConfiguration2
|
||||
extern engine_configuration2_s * engineConfiguration2; \
|
||||
extern engine_pins_s enginePins
|
||||
|
||||
#define DECLARE_ENGINE_PARAMETER_F void
|
||||
#define DECLARE_ENGINE_PARAMETER_S
|
||||
|
|
Loading…
Reference in New Issue