diff --git a/firmware/controllers/engine_cycle/rpm_calculator.cpp b/firmware/controllers/engine_cycle/rpm_calculator.cpp index 272f5ddb5a..c3576382d2 100644 --- a/firmware/controllers/engine_cycle/rpm_calculator.cpp +++ b/firmware/controllers/engine_cycle/rpm_calculator.cpp @@ -288,7 +288,9 @@ void rpmShaftPositionCallback(trigger_event_e ckpSignalType, #endif /* EFI_SENSOR_CHART */ // Always update instant RPM even when not spinning up - engine->triggerCentral.triggerState.updateInstantRpm(&engine->triggerCentral.triggerFormDetails, index, nowNt PASS_ENGINE_PARAMETER_SUFFIX); + engine->triggerCentral.triggerState.updateInstantRpm( + engine->triggerCentral.triggerShape, &engine->triggerCentral.triggerFormDetails, + index, nowNt PASS_ENGINE_PARAMETER_SUFFIX); if (rpmState->isSpinningUp()) { float instantRpm = engine->triggerCentral.triggerState.getInstantRpm(); diff --git a/firmware/controllers/trigger/decoders/trigger_structure.cpp b/firmware/controllers/trigger/decoders/trigger_structure.cpp index 4f485bb3b2..18a856e030 100644 --- a/firmware/controllers/trigger/decoders/trigger_structure.cpp +++ b/firmware/controllers/trigger/decoders/trigger_structure.cpp @@ -61,17 +61,12 @@ TriggerWaveform::TriggerWaveform() : wave.channels = h.channels; } -TriggerFormDetails::TriggerFormDetails() { - memset(triggerIndexByAngle, 0, sizeof(triggerIndexByAngle)); -} - void TriggerWaveform::initialize(operation_mode_e operationMode) { isSynchronizationNeeded = true; // that's default value bothFrontsRequired = false; needSecondTriggerInput = false; shapeWithoutTdc = false; memset(expectedDutyCycle, 0, sizeof(expectedDutyCycle)); -// memset(triggerIndexByAngle, 0, sizeof(triggerIndexByAngle)); setTriggerSynchronizationGap(2); for (int gapIndex = 1; gapIndex < GAP_TRACKING_LENGTH ; gapIndex++) { @@ -355,13 +350,11 @@ void TriggerWaveform::setTriggerSynchronizationGap3(int gapIndex, float syncRati } -/** - * this method is only used on initialization - */ uint16_t TriggerWaveform::findAngleIndex(TriggerFormDetails *details, angle_t targetAngle) const { size_t engineCycleEventCount = getLength(); - efiAssert(CUSTOM_ERR_ASSERT, engineCycleEventCount != 0 && engineCycleEventCount <= 0xFFFF, "engineCycleEventCount", 0); + efiAssert(CUSTOM_ERR_ASSERT, engineCycleEventCount != 0 && engineCycleEventCount <= 0xFFFF, + "engineCycleEventCount", 0); uint32_t left = 0; uint32_t right = engineCycleEventCount - 1; @@ -370,20 +363,20 @@ uint16_t TriggerWaveform::findAngleIndex(TriggerFormDetails *details, angle_t ta * Let's find the last trigger angle which is less or equal to the desired angle * todo: extract binary search as template method? */ - while (left <= right) { - int middle = (left + right) / 2; - angle_t eventAngle = details->eventAngles[middle]; + do { + uint32_t middle = (left + right) / 2; - if (eventAngle < targetAngle) { - left = middle + 1; - } else if (eventAngle > targetAngle) { - right = middle - 1; - } else { - // Values are equal - return middle; // Key found - } - } - return left - 1; + if (details->eventAngles[middle] <= targetAngle) { + left = middle + 1; + } else { + right = middle - 1; + } + } while (left <= right); + left -= 1; + if (useOnlyRisingEdgeForTriggerTemp) { + left &= ~1U; + } + return left; } void TriggerWaveform::setShapeDefinitionError(bool value) { @@ -408,7 +401,7 @@ void findTriggerPosition(TriggerWaveform *triggerShape, efiAssertVoid(CUSTOM_ERR_6577, !cisnan(angle), "findAngle#2"); fixAngle2(angle, "addFuel#2", CUSTOM_ERR_6555, getEngineCycle(triggerShape->getOperationMode())); - int triggerEventIndex = details->triggerIndexByAngle[(int)angle]; + int triggerEventIndex = triggerShape->findAngleIndex(details, angle); angle_t triggerEventAngle = details->eventAngles[triggerEventIndex]; angle_t offsetFromTriggerEvent = angle - triggerEventAngle; @@ -435,18 +428,6 @@ void TriggerWaveform::prepareShape(TriggerFormDetails *details DECLARE_ENGINE_PA } prepareEventAngles(this, details PASS_ENGINE_PARAMETER_SUFFIX); - - int engineCycleInt = (int) getEngineCycle(operationMode); - for (int angle = 0; angle < engineCycleInt; angle++) { - uint16_t triggerShapeIndex = findAngleIndex(details, angle); - - if (useOnlyRisingEdgeForTriggerTemp) { - // we need even index for front_only mode - so if odd indexes are rounded down by clearing the low bit - triggerShapeIndex &= 0xFFFE; - } - - details->triggerIndexByAngle[angle] = triggerShapeIndex; - } #endif } diff --git a/firmware/controllers/trigger/decoders/trigger_structure.h b/firmware/controllers/trigger/decoders/trigger_structure.h index 2e33f50cd5..9532ec010e 100644 --- a/firmware/controllers/trigger/decoders/trigger_structure.h +++ b/firmware/controllers/trigger/decoders/trigger_structure.h @@ -308,17 +308,11 @@ private: */ class TriggerFormDetails { public: - TriggerFormDetails(); /** * These angles are in event coordinates - with synchronization point located at angle zero. * These values are pre-calculated for performance reasons. */ angle_t eventAngles[PWM_PHASE_MAX_COUNT]; - /** - * this cache allows us to find a close-enough (with one degree precision) trigger wheel index by - * given angle with fast constant speed. That's a performance optimization for event scheduling. - */ - uint16_t triggerIndexByAngle[MAX(TWO_STROKE_CYCLE_DURATION, FOUR_STROKE_CYCLE_DURATION)]; }; void findTriggerPosition( diff --git a/firmware/controllers/trigger/trigger_decoder.cpp b/firmware/controllers/trigger/trigger_decoder.cpp index bdbe19c532..06c1355d8d 100644 --- a/firmware/controllers/trigger/trigger_decoder.cpp +++ b/firmware/controllers/trigger/trigger_decoder.cpp @@ -242,7 +242,10 @@ void TriggerStateWithRunningStatistics::movePreSynchTimestamps(DECLARE_ENGINE_PA memcpy(timeOfLastEvent + firstDst, spinningEvents + firstSrc, eventsToCopy * sizeof(timeOfLastEvent[0])); } -float TriggerStateWithRunningStatistics::calculateInstantRpm(TriggerFormDetails *triggerFormDetails, uint32_t current_index, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) { +float TriggerStateWithRunningStatistics::calculateInstantRpm( + TriggerWaveform const & triggerShape, TriggerFormDetails *triggerFormDetails, + uint32_t current_index, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) { + assertIsInBoundsWithResult((int)current_index, timeOfLastEvent, "calc timeOfLastEvent", 0); // Record the time of this event so we can calculate RPM from it later @@ -257,7 +260,7 @@ float TriggerStateWithRunningStatistics::calculateInstantRpm(TriggerFormDetails // Hunt for a tooth ~90 degrees ago to compare to the current time angle_t previousAngle = currentAngle - 90; fixAngle(previousAngle, "prevAngle", CUSTOM_ERR_TRIGGER_ANGLE_RANGE); - int prevIndex = triggerFormDetails->triggerIndexByAngle[(int)previousAngle]; + int prevIndex = triggerShape.findAngleIndex(triggerFormDetails, previousAngle); // now let's get precise angle for that event angle_t prevIndexAngle = triggerFormDetails->eventAngles[prevIndex]; @@ -307,8 +310,12 @@ void TriggerStateWithRunningStatistics::setLastEventTimeForInstantRpm(efitick_t spinningEvents[spinningEventIndex++] = nowNt; } -void TriggerStateWithRunningStatistics::updateInstantRpm(TriggerFormDetails *triggerFormDetails, uint32_t index, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) { - m_instantRpm = calculateInstantRpm(triggerFormDetails, index, nowNt PASS_ENGINE_PARAMETER_SUFFIX); +void TriggerStateWithRunningStatistics::updateInstantRpm( + TriggerWaveform const & triggerShape, TriggerFormDetails *triggerFormDetails, + uint32_t index, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) { + + m_instantRpm = calculateInstantRpm(triggerShape, triggerFormDetails, index, + nowNt PASS_ENGINE_PARAMETER_SUFFIX); #if EFI_SENSOR_CHART diff --git a/firmware/controllers/trigger/trigger_decoder.h b/firmware/controllers/trigger/trigger_decoder.h index a697d6b900..09a105540e 100644 --- a/firmware/controllers/trigger/trigger_decoder.h +++ b/firmware/controllers/trigger/trigger_decoder.h @@ -202,7 +202,9 @@ public: void movePreSynchTimestamps(DECLARE_ENGINE_PARAMETER_SIGNATURE); #if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT - void updateInstantRpm(TriggerFormDetails *triggerFormDetails, uint32_t index, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); + void updateInstantRpm( + TriggerWaveform const & triggerShape, TriggerFormDetails *triggerFormDetails, + uint32_t index, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); #endif /** * Update timeOfLastEvent[] on every trigger event - even without synchronization @@ -211,7 +213,9 @@ public: void setLastEventTimeForInstantRpm(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); private: - float calculateInstantRpm(TriggerFormDetails *triggerFormDetails, uint32_t index, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); + float calculateInstantRpm( + TriggerWaveform const & triggerShape, TriggerFormDetails *triggerFormDetails, + uint32_t index, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); float m_instantRpm = 0; float m_instantRpmRatio = 0; diff --git a/unit_tests/tests/trigger/test_trigger_decoder.cpp b/unit_tests/tests/trigger/test_trigger_decoder.cpp index 97bf023881..092ed354e0 100644 --- a/unit_tests/tests/trigger/test_trigger_decoder.cpp +++ b/unit_tests/tests/trigger/test_trigger_decoder.cpp @@ -323,8 +323,8 @@ TEST(misc, testRpmCalculator) { ASSERT_EQ(0, GET_RPM()); // triggerIndexByAngle update is now fixed! prepareOutputSignals() wasn't reliably called - ASSERT_EQ(5, engine->triggerCentral.triggerFormDetails.triggerIndexByAngle[240]); - ASSERT_EQ(5, engine->triggerCentral.triggerFormDetails.triggerIndexByAngle[241]); + ASSERT_EQ(5, engine->triggerCentral.triggerShape.findAngleIndex(&engine->triggerCentral.triggerFormDetails, 240)); + ASSERT_EQ(5, engine->triggerCentral.triggerShape.findAngleIndex(&engine->triggerCentral.triggerFormDetails, 241)); eth.fireTriggerEvents(/* count */ 48); @@ -389,8 +389,8 @@ TEST(misc, testRpmCalculator) { assertEqualsM("3/3", start + 14777, engine->executor.getForUnitTest(2)->momentX); engine->executor.clear(); - ASSERT_EQ(5, engine->triggerCentral.triggerFormDetails.triggerIndexByAngle[240]); - ASSERT_EQ(5, engine->triggerCentral.triggerFormDetails.triggerIndexByAngle[241]); + ASSERT_EQ(5, engine->triggerCentral.triggerShape.findAngleIndex(&engine->triggerCentral.triggerFormDetails, 240)); + ASSERT_EQ(5, engine->triggerCentral.triggerShape.findAngleIndex(&engine->triggerCentral.triggerFormDetails, 241)); eth.fireFall(5); diff --git a/unit_tests/triggers.txt b/unit_tests/triggers.txt index 15e2837e28..3e371c650d 100644 --- a/unit_tests/triggers.txt +++ b/unit_tests/triggers.txt @@ -3001,270 +3001,270 @@ event 276 1 1 362.67 event 277 1 0 364.00 event 278 1 1 365.33 event 279 1 0 366.67 -event 280 1 1 0.00 -event 281 1 0 0.00 -event 282 1 1 0.00 -event 283 1 0 0.00 -event 284 1 1 0.00 -event 285 1 0 0.00 -event 286 1 1 0.00 -event 287 1 0 0.00 -event 288 1 1 0.00 -event 289 1 0 0.00 -event 290 1 1 0.00 -event 291 1 0 0.00 -event 292 1 1 0.00 -event 293 1 0 0.00 -event 294 1 1 0.00 -event 295 1 0 0.00 -event 296 1 1 0.00 -event 297 1 0 0.00 -event 298 1 1 0.00 -event 299 1 0 0.00 -event 300 1 1 0.00 -event 301 1 0 0.00 -event 302 1 1 0.00 -event 303 1 0 0.00 -event 304 1 1 0.00 -event 305 1 0 0.00 -event 306 1 1 0.00 -event 307 1 0 0.00 -event 308 1 1 0.00 -event 309 1 0 0.00 -event 310 1 1 0.00 -event 311 1 0 0.00 -event 312 1 1 0.00 -event 313 1 0 0.00 -event 314 1 1 0.00 -event 315 1 0 0.00 -event 316 1 1 0.00 -event 317 1 0 0.00 -event 318 1 1 0.00 -event 319 1 0 0.00 -event 320 1 1 0.00 -event 321 1 0 0.00 -event 322 1 1 0.00 -event 323 1 0 0.00 -event 324 1 1 0.00 -event 325 1 0 0.00 -event 326 1 1 0.00 -event 327 1 0 0.00 -event 328 1 1 0.00 -event 329 1 0 0.00 -event 330 1 1 0.00 -event 331 1 0 0.00 -event 332 1 1 0.00 -event 333 1 0 0.00 -event 334 1 1 0.00 -event 335 1 0 0.00 -event 336 1 1 0.00 -event 337 1 0 0.00 -event 338 1 1 0.00 -event 339 1 0 0.00 -event 340 1 1 0.00 -event 341 1 0 0.00 -event 342 1 1 0.00 -event 343 1 0 0.00 -event 344 1 1 0.00 -event 345 1 0 0.00 -event 346 1 1 0.00 -event 347 1 0 0.00 -event 348 1 1 0.00 -event 349 1 0 0.00 -event 350 1 1 0.00 -event 351 1 0 0.00 -event 352 1 1 0.00 -event 353 1 0 0.00 -event 354 1 1 0.00 -event 355 1 0 0.00 -event 356 1 1 0.00 -event 357 1 0 0.00 -event 358 1 1 0.00 -event 359 1 0 0.00 -event 360 1 1 0.00 -event 361 1 0 0.00 -event 362 1 1 0.00 -event 363 1 0 0.00 -event 364 1 1 0.00 -event 365 1 0 0.00 -event 366 1 1 0.00 -event 367 1 0 0.00 -event 368 1 1 0.00 -event 369 1 0 0.00 -event 370 1 1 0.00 -event 371 1 0 0.00 -event 372 1 1 0.00 -event 373 1 0 0.00 -event 374 1 1 0.00 -event 375 1 0 0.00 -event 376 1 1 0.00 -event 377 1 0 0.00 -event 378 1 1 0.00 -event 379 1 0 0.00 -event 380 1 1 0.00 -event 381 1 0 0.00 -event 382 1 1 0.00 -event 383 1 0 0.00 -event 384 1 1 0.00 -event 385 1 0 0.00 -event 386 1 1 0.00 -event 387 1 0 0.00 -event 388 1 1 0.00 -event 389 1 0 0.00 -event 390 1 1 0.00 -event 391 1 0 0.00 -event 392 1 1 0.00 -event 393 1 0 0.00 -event 394 1 1 0.00 -event 395 1 0 0.00 -event 396 1 1 0.00 -event 397 1 0 0.00 -event 398 1 1 0.00 -event 399 1 0 0.00 -event 400 1 1 0.00 -event 401 1 0 0.00 -event 402 1 1 0.00 -event 403 1 0 0.00 -event 404 1 1 0.00 -event 405 1 0 0.00 -event 406 1 1 0.00 -event 407 1 0 0.00 -event 408 1 1 0.00 -event 409 1 0 0.00 -event 410 1 1 0.00 -event 411 1 0 0.00 -event 412 1 1 0.00 -event 413 1 0 0.00 -event 414 1 1 0.00 -event 415 1 0 0.00 -event 416 1 1 0.00 -event 417 1 0 0.00 -event 418 1 1 0.00 -event 419 1 0 0.00 -event 420 1 1 0.00 -event 421 1 0 0.00 -event 422 1 1 0.00 -event 423 1 0 0.00 -event 424 1 1 0.00 -event 425 1 0 0.00 -event 426 1 1 0.00 -event 427 1 0 0.00 -event 428 1 1 0.00 -event 429 1 0 0.00 -event 430 1 1 0.00 -event 431 1 0 0.00 -event 432 1 1 0.00 -event 433 1 0 0.00 -event 434 1 1 0.00 -event 435 1 0 0.00 -event 436 1 1 0.00 -event 437 1 0 0.00 -event 438 1 1 0.00 -event 439 1 0 0.00 -event 440 1 1 0.00 -event 441 1 0 0.00 -event 442 1 1 0.00 -event 443 1 0 0.00 -event 444 1 1 0.00 -event 445 1 0 0.00 -event 446 1 1 0.00 -event 447 1 0 0.00 -event 448 1 1 0.00 -event 449 1 0 0.00 -event 450 1 1 0.00 -event 451 1 0 0.00 -event 452 1 1 0.00 -event 453 1 0 0.00 -event 454 1 1 0.00 -event 455 1 0 0.00 -event 456 1 1 0.00 -event 457 1 0 0.00 -event 458 1 1 0.00 -event 459 1 0 0.00 -event 460 1 1 0.00 -event 461 1 0 0.00 -event 462 1 1 0.00 -event 463 1 0 0.00 -event 464 1 1 0.00 -event 465 1 0 0.00 -event 466 1 1 0.00 -event 467 1 0 0.00 -event 468 1 1 0.00 -event 469 1 0 0.00 -event 470 1 1 0.00 -event 471 1 0 0.00 -event 472 1 1 0.00 -event 473 1 0 0.00 -event 474 1 1 0.00 -event 475 1 0 0.00 -event 476 1 1 0.00 -event 477 1 0 0.00 -event 478 1 1 0.00 -event 479 1 0 0.00 -event 480 1 1 0.00 -event 481 1 0 0.00 -event 482 1 1 0.00 -event 483 1 0 0.00 -event 484 1 1 0.00 -event 485 1 0 0.00 -event 486 1 1 0.00 -event 487 1 0 0.00 -event 488 1 1 0.00 -event 489 1 0 0.00 -event 490 1 1 0.00 -event 491 1 0 0.00 -event 492 1 1 0.00 -event 493 1 0 0.00 -event 494 1 1 0.00 -event 495 1 0 0.00 -event 496 1 1 0.00 -event 497 1 0 0.00 -event 498 1 1 0.00 -event 499 1 0 0.00 -event 500 1 1 0.00 -event 501 1 0 0.00 -event 502 1 1 0.00 -event 503 1 0 0.00 -event 504 1 1 0.00 -event 505 1 0 0.00 -event 506 1 1 0.00 -event 507 1 0 0.00 -event 508 1 1 0.00 -event 509 1 0 0.00 -event 510 1 1 0.00 -event 511 1 0 0.00 -event 512 1 1 0.00 -event 513 1 0 0.00 -event 514 1 1 0.00 -event 515 1 0 0.00 -event 516 1 1 0.00 -event 517 1 0 0.00 -event 518 1 1 0.00 -event 519 1 0 0.00 -event 520 1 1 0.00 -event 521 1 0 0.00 -event 522 1 1 0.00 -event 523 1 0 0.00 -event 524 1 1 0.00 -event 525 1 0 0.00 -event 526 1 1 0.00 -event 527 1 0 0.00 -event 528 1 1 0.00 -event 529 1 0 0.00 -event 530 1 1 0.00 -event 531 1 0 0.00 -event 532 1 1 0.00 -event 533 1 0 0.00 -event 534 1 1 0.00 -event 535 1 0 0.00 -event 536 1 1 0.00 -event 537 1 0 0.00 -event 538 1 1 0.00 -event 539 1 0 0.00 -event 540 1 1 0.00 -event 541 1 0 0.00 -event 542 1 1 0.00 -event 543 1 0 0.00 +event 280 1 1 368.00 +event 281 1 0 369.33 +event 282 1 1 370.67 +event 283 1 0 372.00 +event 284 1 1 373.33 +event 285 1 0 374.67 +event 286 1 1 376.00 +event 287 1 0 377.33 +event 288 1 1 378.67 +event 289 1 0 380.00 +event 290 1 1 381.33 +event 291 1 0 382.67 +event 292 1 1 384.00 +event 293 1 0 385.33 +event 294 1 1 386.67 +event 295 1 0 388.00 +event 296 1 1 389.33 +event 297 1 0 390.67 +event 298 1 1 392.00 +event 299 1 0 393.33 +event 300 1 1 394.67 +event 301 1 0 396.00 +event 302 1 1 397.33 +event 303 1 0 398.67 +event 304 1 1 400.00 +event 305 1 0 401.33 +event 306 1 1 402.67 +event 307 1 0 404.00 +event 308 1 1 405.33 +event 309 1 0 406.67 +event 310 1 1 408.00 +event 311 1 0 409.33 +event 312 1 1 410.67 +event 313 1 0 412.00 +event 314 1 1 413.33 +event 315 1 0 414.67 +event 316 1 1 416.00 +event 317 1 0 417.33 +event 318 1 1 418.67 +event 319 1 0 420.00 +event 320 1 1 421.33 +event 321 1 0 422.67 +event 322 1 1 424.00 +event 323 1 0 425.33 +event 324 1 1 426.67 +event 325 1 0 428.00 +event 326 1 1 429.33 +event 327 1 0 430.67 +event 328 1 1 432.00 +event 329 1 0 433.33 +event 330 1 1 434.67 +event 331 1 0 436.00 +event 332 1 1 437.33 +event 333 1 0 438.67 +event 334 1 1 440.00 +event 335 1 0 441.33 +event 336 1 1 442.67 +event 337 1 0 444.00 +event 338 1 1 445.33 +event 339 1 0 446.67 +event 340 1 1 448.00 +event 341 1 0 449.33 +event 342 1 1 450.67 +event 343 1 0 452.00 +event 344 1 1 453.33 +event 345 1 0 454.67 +event 346 1 1 456.00 +event 347 1 0 457.33 +event 348 1 1 458.67 +event 349 1 0 460.00 +event 350 1 1 461.33 +event 351 1 0 462.67 +event 352 1 1 464.00 +event 353 1 0 465.33 +event 354 1 1 466.67 +event 355 1 0 468.00 +event 356 1 1 469.33 +event 357 1 0 470.67 +event 358 1 1 472.00 +event 359 1 0 473.33 +event 360 1 1 474.67 +event 361 1 0 476.00 +event 362 1 1 477.33 +event 363 1 0 478.67 +event 364 1 1 480.00 +event 365 1 0 481.33 +event 366 1 1 482.67 +event 367 1 0 484.00 +event 368 1 1 485.33 +event 369 1 0 486.67 +event 370 1 1 488.00 +event 371 1 0 489.33 +event 372 1 1 490.67 +event 373 1 0 492.00 +event 374 1 1 493.33 +event 375 1 0 494.67 +event 376 1 1 496.00 +event 377 1 0 497.33 +event 378 1 1 498.67 +event 379 1 0 500.00 +event 380 1 1 501.33 +event 381 1 0 502.67 +event 382 1 1 504.00 +event 383 1 0 505.33 +event 384 1 1 506.67 +event 385 1 0 508.00 +event 386 1 1 509.33 +event 387 1 0 510.67 +event 388 1 1 512.00 +event 389 1 0 513.33 +event 390 1 1 514.67 +event 391 1 0 516.00 +event 392 1 1 517.33 +event 393 1 0 518.67 +event 394 1 1 520.00 +event 395 1 0 521.33 +event 396 1 1 522.67 +event 397 1 0 524.00 +event 398 1 1 525.33 +event 399 1 0 526.67 +event 400 1 1 528.00 +event 401 1 0 529.33 +event 402 1 1 530.67 +event 403 1 0 532.00 +event 404 1 1 533.33 +event 405 1 0 534.67 +event 406 1 1 536.00 +event 407 1 0 537.33 +event 408 1 1 538.67 +event 409 1 0 540.00 +event 410 1 1 541.33 +event 411 1 0 542.67 +event 412 1 1 544.00 +event 413 1 0 545.33 +event 414 1 1 546.67 +event 415 1 0 548.00 +event 416 1 1 549.33 +event 417 1 0 550.67 +event 418 1 1 552.00 +event 419 1 0 553.33 +event 420 1 1 554.67 +event 421 1 0 556.00 +event 422 1 1 557.33 +event 423 1 0 558.67 +event 424 1 1 560.00 +event 425 1 0 561.33 +event 426 1 1 562.67 +event 427 1 0 564.00 +event 428 1 1 565.33 +event 429 1 0 566.67 +event 430 1 1 568.00 +event 431 1 0 569.33 +event 432 1 1 570.67 +event 433 1 0 572.00 +event 434 1 1 573.33 +event 435 1 0 574.67 +event 436 1 1 576.00 +event 437 1 0 577.33 +event 438 1 1 578.67 +event 439 1 0 580.00 +event 440 1 1 581.33 +event 441 1 0 582.67 +event 442 1 1 584.00 +event 443 1 0 585.33 +event 444 1 1 586.67 +event 445 1 0 588.00 +event 446 1 1 589.33 +event 447 1 0 590.67 +event 448 1 1 592.00 +event 449 1 0 593.33 +event 450 1 1 594.67 +event 451 1 0 596.00 +event 452 1 1 597.33 +event 453 1 0 598.67 +event 454 1 1 600.00 +event 455 1 0 601.33 +event 456 1 1 602.67 +event 457 1 0 604.00 +event 458 1 1 605.33 +event 459 1 0 606.67 +event 460 1 1 608.00 +event 461 1 0 609.33 +event 462 1 1 610.67 +event 463 1 0 612.00 +event 464 1 1 613.33 +event 465 1 0 614.67 +event 466 1 1 616.00 +event 467 1 0 617.33 +event 468 1 1 618.67 +event 469 1 0 620.00 +event 470 1 1 621.33 +event 471 1 0 622.67 +event 472 1 1 624.00 +event 473 1 0 625.33 +event 474 1 1 626.67 +event 475 1 0 628.00 +event 476 1 1 629.33 +event 477 1 0 630.67 +event 478 1 1 632.00 +event 479 1 0 633.33 +event 480 1 1 634.67 +event 481 1 0 636.00 +event 482 1 1 637.33 +event 483 1 0 638.67 +event 484 1 1 640.00 +event 485 1 0 641.33 +event 486 1 1 642.67 +event 487 1 0 644.00 +event 488 1 1 645.33 +event 489 1 0 646.67 +event 490 1 1 648.00 +event 491 1 0 649.33 +event 492 1 1 650.67 +event 493 1 0 652.00 +event 494 1 1 653.33 +event 495 1 0 654.67 +event 496 1 1 656.00 +event 497 1 0 657.33 +event 498 1 1 658.67 +event 499 1 0 660.00 +event 500 1 1 661.33 +event 501 1 0 662.67 +event 502 1 1 664.00 +event 503 1 0 665.33 +event 504 1 1 666.67 +event 505 1 0 668.00 +event 506 1 1 669.33 +event 507 1 0 670.67 +event 508 1 1 672.00 +event 509 1 0 673.33 +event 510 1 1 674.67 +event 511 1 0 676.00 +event 512 1 1 677.33 +event 513 1 0 678.67 +event 514 1 1 680.00 +event 515 1 0 681.33 +event 516 1 1 682.67 +event 517 1 0 684.00 +event 518 1 1 685.33 +event 519 1 0 686.67 +event 520 1 1 688.00 +event 521 1 0 689.33 +event 522 1 1 690.67 +event 523 1 0 692.00 +event 524 1 1 693.33 +event 525 1 0 694.67 +event 526 1 1 696.00 +event 527 1 0 697.33 +event 528 1 1 698.67 +event 529 1 0 700.00 +event 530 1 1 701.33 +event 531 1 0 702.67 +event 532 1 1 704.00 +event 533 1 0 705.33 +event 534 1 1 706.67 +event 535 1 0 708.00 +event 536 1 1 709.33 +event 537 1 0 710.67 +event 538 1 1 712.00 +event 539 1 0 713.33 +event 540 1 1 714.67 +event 541 1 0 716.00 +event 542 1 1 717.33 +event 543 1 0 718.67 TRIGGERTYPE 54 110 TT_GM_60_2_2_2 0.00 # duty 0.98 0.45 event 0 0 1 0.00