You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Unit test fuel & ignition channel cut code (speeduino#1376)
* Add calculateFuelIgnitionChannelCut() + unit tests
* Keep tests DRY
* Compute oil protection end time in millis, instead of calling div100() on every pass.
* Add rolling cut test cases
* Capture the scheduler channel cut state in statuses. This feeds the prior state into calculateFuelIgnitionChannelCut(), which allows the rolling cut code to set pending ignition channels.
* Add pending ignition cut test
* Remove redundant tests, consolidate others
* Enhance checkOilPressureLimit tests
* Enhance checkBoostLimit test
* Enhanced checkAFRLimit() tests
* Deterministic rolling cut tests - requires injecting RNG
* afrProtectCount -> afrProtectedActivateTime. Since this is now a non-zero future time, we can remove afrProtectCountEnabled
* Enhanced checkAFRLimit() tests
* Force calculateFuelIgnitionChannelCut() inline
//Check for any of the engine protections or rev limiters being turned on
202
+
uint16_t maxAllowedRPM = checkRevLimit(current, page4, page6, page9); //The maximum RPM allowed by all the potential limiters (Engine protection, 2-step, flat shift etc). Divided by 100. `checkRevLimit()` returns the current maximum RPM allow (divided by 100) based on either the fixed hard limit or the current coolant temp
203
+
//Check each of the functions that has an RPM limit. Update the max allowed RPM if the function is active and has a lower RPM than already set
maxAllowedRPM = maxAllowedRPM * 100U; //All of the above limits are divided by 100, convert back to RPM
207
+
if ( (current.flatShiftingHard == true) && (current.clutchEngagedRPM < maxAllowedRPM) ) { maxAllowedRPM = current.clutchEngagedRPM; } //Flat shifting is a special case as the RPM limit is based on when the clutch was engaged. It is not divided by 100 as it is set with the actual RPM
elseif( (page2.hardCutType == HARD_CUT_ROLLING) && (current.RPM > (maxAllowedRPM + (rollingCutTable.axis[0] * 10))) ) //Limit for rolling is the max allowed RPM minus the lowest value in the delta table (Delta values are negative!)
246
+
{
247
+
uint8_t revolutionsToCut = 1;
248
+
if(page2.strokes == FOUR_STROKE) { revolutionsToCut *= 2; } //4 stroke needs to cut for at least 2 revolutions
249
+
if( (page4.sparkMode != IGN_MODE_SEQUENTIAL) || (page2.injLayout != INJ_SEQUENTIAL) ) { revolutionsToCut *= 2; } //4 stroke and non-sequential will cut for 4 revolutions minimum. This is to ensure no half fuel ignition cycles take place
if ( (current.startRevolutions >= (rollingCutLastRev + revolutionsToCut)) || (current.RPM > maxAllowedRPM) ) //If current RPM is over the max allowed RPM always cut, otherwise check if the required number of revolutions have passed since the last cut
253
+
{
254
+
uint8_t cutPercent = 0;
255
+
int16_t rpmDelta = current.RPM - maxAllowedRPM;
256
+
if(rpmDelta >= 0) { cutPercent = 100; } //If the current RPM is over the max allowed RPM then cut is full (100%)
BIT_CLEAR(cutState.ignitionChannels, x); //Turn off this ignition channel
273
+
break;
274
+
case PROTECT_CUT_FUEL:
275
+
BIT_CLEAR(cutState.fuelChannels, x); //Turn off this fuel channel
276
+
break;
277
+
case PROTECT_CUT_BOTH:
278
+
BIT_CLEAR(cutState.ignitionChannels, x); //Turn off this ignition channel
279
+
BIT_CLEAR(cutState.fuelChannels, x); //Turn off this fuel channel
280
+
break;
281
+
default:
282
+
BIT_CLEAR(cutState.ignitionChannels, x); //Turn off this ignition channel
283
+
BIT_CLEAR(cutState.fuelChannels, x); //Turn off this fuel channel
284
+
break;
285
+
}
286
+
}
287
+
else
288
+
{
289
+
//Turn fuel and ignition channels on
290
+
291
+
//Special case for non-sequential, 4-stroke where both fuel and ignition are cut. The ignition pulses should wait 1 cycle after the fuel channels are turned back on before firing again
292
+
if( (revolutionsToCut == 4) && //4 stroke and non-sequential
293
+
(BIT_CHECK(cutState.fuelChannels, x) == false) && //Fuel on this channel is currently off, meaning it is the first revolution after a cut
294
+
(page6.engineProtectType == PROTECT_CUT_BOTH) //Both fuel and ignition are cut
295
+
)
296
+
{ BIT_SET(cutState.ignitionChannelsPending, x); } //Set this ignition channel as pending
297
+
else { BIT_SET(cutState.ignitionChannels, x); } //Turn on this ignition channel
298
+
299
+
300
+
BIT_SET(cutState.fuelChannels, x); //Turn on this fuel channel
301
+
}
302
+
}
303
+
rollingCutLastRev = current.startRevolutions;
304
+
}
305
+
306
+
//Check whether there are any ignition channels that are waiting for injection pulses to occur before being turned back on. This can only occur when at least 2 revolutions have taken place since the fuel was turned back on
307
+
//Note that ignitionChannelsPending can only be >0 on 4 stroke, non-sequential fuel when protect type is Both
0 commit comments