238 lines
7.0 KiB
C++
238 lines
7.0 KiB
C++
/**
|
|
* @file main_trigger_callback.cpp
|
|
* @brief Main logic is here!
|
|
*
|
|
* See http://rusefi.com/docs/html/
|
|
*
|
|
* @date Feb 7, 2013
|
|
* @author Andrey Belomutskiy, (c) 2012-2014
|
|
*
|
|
* This file is part of rusEfi - see http://rusefi.com
|
|
*
|
|
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
|
|
* the GNU General Public License as published by the Free Software Foundation; either
|
|
* version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
|
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with this program.
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "main.h"
|
|
#include "main_trigger_callback.h"
|
|
#include "ec2.h"
|
|
|
|
extern "C" {
|
|
//#include "settings.h"
|
|
#include "trigger_central.h"
|
|
#include "rpm_calculator.h"
|
|
#include "signal_executor.h"
|
|
#include "eficonsole.h"
|
|
#include "engine_math.h"
|
|
//#include "injector_central.h"
|
|
//#include "ignition_central.h"
|
|
#include "engine_configuration.h"
|
|
#include "interpolation.h"
|
|
#include "advance_map.h"
|
|
#include "allsensors.h"
|
|
#include "cyclic_buffer.h"
|
|
#include "histogram.h"
|
|
#include "fuel_math.h"
|
|
#include "histogram.h"
|
|
#include "rfiutil.h"
|
|
#include "LocalVersionHolder.h"
|
|
|
|
static LocalVersionHolder localVersion;
|
|
|
|
int isInjectionEnabled(void);
|
|
|
|
}
|
|
|
|
// todo: move this to engine_configuration2_s for now
|
|
|
|
extern engine_configuration_s *engineConfiguration;
|
|
extern engine_configuration2_s *engineConfiguration2;
|
|
|
|
static cyclic_buffer ignitionErrorDetection;
|
|
|
|
static Logging logger;
|
|
|
|
/**
|
|
* this field is accessed only from shaft sensor event handler.
|
|
* This is not a method variable just to save us from stack overflow.
|
|
*/
|
|
static ActuatorEventList events;
|
|
|
|
static void handleFuelInjectionEvent(ActuatorEvent *event, int rpm) {
|
|
float fuelMs = getFuelMs(rpm) * engineConfiguration->globalFuelCorrection;
|
|
if (fuelMs < 0) {
|
|
scheduleMsg(&logger, "ERROR: negative injectionPeriod %f", fuelMs);
|
|
return;
|
|
}
|
|
|
|
float delay = getOneDegreeTimeMs(rpm) * event->angleOffset;
|
|
|
|
// if (isCranking())
|
|
// scheduleMsg(&logger, "crankingFuel=%f for CLT=%fC", fuelMs, getCoolantTemperature());
|
|
|
|
scheduleOutput(event->actuator, delay, fuelMs);
|
|
}
|
|
|
|
static void handleFuel(int eventIndex) {
|
|
if (!isInjectionEnabled())
|
|
return;
|
|
chDbgCheck(eventIndex < engineConfiguration2->triggerShape.shaftPositionEventCount, "event index");
|
|
|
|
/**
|
|
* Ignition events are defined by addFuelEvents() according to selected
|
|
* fueling strategy
|
|
*/
|
|
ActuatorEventList *source =
|
|
isCranking() ?
|
|
&engineConfiguration2->engineEventConfiguration.crankingInjectionEvents :
|
|
&engineConfiguration2->engineEventConfiguration.injectionEvents;
|
|
findEvents(eventIndex, source, &events);
|
|
|
|
if (events.size == 0)
|
|
return;
|
|
|
|
// scheduleSimpleMsg(&logger, "eventId size=", events.size);
|
|
|
|
int rpm = getRpm();
|
|
|
|
for (int i = 0; i < events.size; i++) {
|
|
ActuatorEvent *event = &events.events[i];
|
|
handleFuelInjectionEvent(event, rpm);
|
|
}
|
|
}
|
|
|
|
static void handleSparkEvent(ActuatorEvent *event, int rpm) {
|
|
efiAssert(rpm != 0, "non-zero RPM expected here");
|
|
|
|
// float advance = getAdvance(rpm, getEngineLoad());
|
|
|
|
// float sparkAdvanceMs = getOneDegreeTimeMs(rpm) * advance;
|
|
|
|
float dwellMs = getSparkDwellMs(rpm);
|
|
if (dwellMs < 0)
|
|
firmwareError("invalid dwell: %f at %d", dwellMs, rpm);
|
|
|
|
float sparkDelay = getOneDegreeTimeMs(rpm) * event->angleOffset;
|
|
int isIgnitionError = sparkDelay < 0;
|
|
ignitionErrorDetection.add(isIgnitionError);
|
|
if (isIgnitionError) {
|
|
scheduleMsg(&logger, "Negative spark delay=%f", sparkDelay);
|
|
sparkDelay = 0;
|
|
//return;
|
|
}
|
|
|
|
scheduleOutput(event->actuator, sparkDelay, dwellMs);
|
|
}
|
|
|
|
static void handleSpark(int eventIndex) {
|
|
int rpm = getRpm();
|
|
|
|
/**
|
|
* Ignition schedule is defined once per revolution
|
|
* See initializeIgnitionActions()
|
|
*/
|
|
findEvents(eventIndex, &engineConfiguration2->engineEventConfiguration.ignitionEvents, &events);
|
|
if (events.size == 0)
|
|
return;
|
|
|
|
// scheduleSimpleMsg(&logger, "eventId spark ", eventIndex);
|
|
|
|
for (int i = 0; i < events.size; i++) {
|
|
ActuatorEvent *event = &events.events[i];
|
|
handleSparkEvent(event, rpm);
|
|
}
|
|
}
|
|
|
|
static histogram_s mainLoopHisto;
|
|
|
|
void showMainHistogram(void) {
|
|
printHistogram(&logger, &mainLoopHisto);
|
|
}
|
|
|
|
/**
|
|
* This is the main entry point into the primary shaft signal handler signal. Both injection and ignition are controlled from this method.
|
|
*/
|
|
static void onShaftSignal(ShaftEvents ckpSignalType, int eventIndex) {
|
|
chDbgCheck(eventIndex < engineConfiguration2->triggerShape.shaftPositionEventCount, "event index");
|
|
|
|
int rpm = getRpm();
|
|
if (rpm == 0) {
|
|
// this happens while we just start cranking
|
|
// todo: check for 'trigger->is_synchnonized?'
|
|
return;
|
|
}
|
|
if (rpm == NOISY_RPM) {
|
|
scheduleMsg(&logger, "noisy trigger");
|
|
return;
|
|
}
|
|
if (rpm > engineConfiguration->rpmHardLimit) {
|
|
warning(OBD_PCM_Processor_Fault, "skipping stroke due to rpm=%d", rpm);
|
|
return;
|
|
}
|
|
|
|
int beforeCallback = hal_lld_get_counter_value();
|
|
if (eventIndex == 0) {
|
|
if (localVersion.isOld())
|
|
prepareOutputSignals(engineConfiguration, engineConfiguration2);
|
|
|
|
/**
|
|
* TODO: warning. there is a bit of a hack here, todo: improve.
|
|
* currently output signals/times signalTimerUp from the previous revolutions could be
|
|
* still used because they have crossed the revolution boundary
|
|
* but we are already repurposing the output signals, but everything works because we
|
|
* are not affecting that space in memory. todo: use two instances of 'ignitionSignals'
|
|
*/
|
|
|
|
float dwellMs = getSparkDwellMs(rpm);
|
|
float advance = getAdvance(rpm, getEngineLoad());
|
|
|
|
float dwellAngle = dwellMs / getOneDegreeTimeMs(rpm);
|
|
|
|
initializeIgnitionActions(advance - dwellAngle, engineConfiguration, engineConfiguration2);
|
|
}
|
|
|
|
handleFuel(eventIndex);
|
|
handleSpark(eventIndex);
|
|
int diff = hal_lld_get_counter_value() - beforeCallback;
|
|
if (diff > 0)
|
|
hsAdd(&mainLoopHisto, diff);
|
|
}
|
|
|
|
static void showTriggerHistogram(void) {
|
|
printAllCallbacksHistogram();
|
|
showMainHistogram();
|
|
}
|
|
|
|
static void showMainInfo(void) {
|
|
int rpm = getRpm();
|
|
float el = getEngineLoad();
|
|
scheduleMsg(&logger, "rpm %d engine_load %f", rpm, el);
|
|
scheduleMsg(&logger, "fuel %fms timing %f", getFuelMs(rpm), getAdvance(rpm, el));
|
|
}
|
|
|
|
void initMainEventListener() {
|
|
addConsoleAction("performanceinfo", showTriggerHistogram);
|
|
addConsoleAction("maininfo", showMainInfo);
|
|
|
|
initLogging(&logger, "main event handler");
|
|
printMsg(&logger, "initMainLoop: %d", currentTimeMillis());
|
|
initHistogram(&mainLoopHisto, "main callback");
|
|
|
|
if (!isInjectionEnabled())
|
|
printMsg(&logger, "!!!!!!!!!!!!!!!!!!! injection disabled");
|
|
|
|
addTriggerEventListener(&onShaftSignal, "main loop");
|
|
}
|
|
|
|
int isIgnitionTimingError(void) {
|
|
return ignitionErrorDetection.sum(6) > 4;
|
|
}
|