Move src dir to nested main dir in preparation for sister test dir and cross compiled...
[freeems-vanilla.git] / src / main / decoderInterface.c
blob5b413979fe13bf0bde2c771e384aa0be7e80cafd
1 /* FreeEMS - the open source engine management system
3 * Copyright 2011-2012 Fred Cooke
5 * This file is part of the FreeEMS project.
7 * FreeEMS software is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * FreeEMS software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with any FreeEMS software. If not, see http://www.gnu.org/licenses/
20 * We ask that if you make any changes to this file you email them upstream to
21 * us at admin(at)diyefi(dot)org or, even better, fork the code on github.com!
23 * Thank you for choosing FreeEMS to run your engine!
27 /** @file
29 * @ingroup enginePositionRPMDecoders
31 * @brief shared functions used by all decoders
33 * To maximise code reuse and minimise bugs it is strongly recommended that you
34 * use these pre-canned functions to do work required in your decoder.
38 #define DECODER_INTERFACE_C
39 #include "inc/freeEMS.h"
40 #include "inc/decoderInterface.h"
43 /** @brief Reset key state
45 * Reset all important variables to their non-running state.
47 * @todo TODO bring this up to date and/or find a better way to do it.
49 * @param uniqueLossID 0 is reserved for system use, within your decoder never use the same value twice.
51 void resetToNonRunningState(unsigned char uniqueLossID){
52 if(uniqueLossID){
53 KeyUserDebugs.syncResetCalls++;
56 /* Reset RPM to zero */
57 ticksPerDegree0 = 0;
58 ticksPerDegree1 = 0;
60 // Keep track of lost sync in counters
61 if(KeyUserDebugs.decoderFlags & (CAM_SYNC | CRANK_SYNC | COMBUSTION_SYNC)){
62 FLAG_AND_INC_FLAGGABLE(FLAG_DECODER_SYNC_LOSSES_OFFSET);
63 }else{
64 FLAG_AND_INC_FLAGGABLE(FLAG_DECODER_SYNC_STATE_CLEARS_OFFSET);
67 // record unique loss ID
68 KeyUserDebugs.syncLostWithThisID = uniqueLossID;
70 // record current event
71 KeyUserDebugs.syncLostOnThisEvent = KeyUserDebugs.currentEvent;
73 /* Clear all sync flags to lost state */
74 KeyUserDebugs.decoderFlags = 0; // Nothing should use this except for us anyway!
75 perDecoderReset();
76 // TODO more stuff needs resetting here, but only critical things.
80 /** Schedule an ignition output event on port T
82 * @warning If you do not handle the skipEventFlags then excess advance may occur!
84 void schedulePortTPin(unsigned char outputEventNumber, LongTime timeStamp){
85 unsigned char pin = fixedConfigs1.schedulingSettings.outputEventPinNumbers[outputEventNumber];
86 unsigned short postReferenceEventDelay = 0;
87 if(skipEventFlags & (1UL << outputEventNumber)){
88 postReferenceEventDelay = decoderMaxCodeTime;
89 skipEventFlags &= ~(1UL << outputEventNumber); // Clear the flag
90 }else{
91 postReferenceEventDelay = outputEventDelayFinalPeriod[outputEventNumber];
93 // determine the long and short start times
94 unsigned short startTime = timeStamp.timeShorts[1] + postReferenceEventDelay;
95 // remove this temporarily too, no need for it without the later conditional code
96 unsigned long startTimeLong = timeStamp.timeLong + postReferenceEventDelay;
98 /// @todo TODO Make this more understandable as right now it is difficult to grok.
99 // determine whether or not to reschedule or self schedule assuming pin is currently scheduled
100 unsigned long diff = (injectorMainEndTimes[pin] + injectorSwitchOffCodeTime) - startTimeLong;
101 #define newStartIsAfterOutputEndTimeAndCanSelfSet (diff > LONGHALF)
102 // http://forum.diyefi.org/viewtopic.php?f=8&t=57&p=861#p861
105 fresh code again, five states, 6 possible behaviours:
107 not enabled - sched!!! always
108 enabled and low, ready to turn on - if too close, do nothing, or if far enough away, resched
109 enabled and high, ready to turn off - if too close, resched to turn on, if far enough away, self sched
112 // Is it enabled and about to do *something*?
113 if(TIE & injectorMainOnMasks[pin]){
114 // If configured to do something specific
115 if(*injectorMainControlRegisters[pin] & injectorMainActiveMasks[pin]){
116 // If that something is go high
117 if(*injectorMainControlRegisters[pin] & injectorMainGoHighMasks[pin]){
118 // GO HIGH SHOULD DO NOTHING CEPT COUNTER
119 // if too close, do nothing, or if far enough away, resched
120 // for now just always do nothing as it's going to fire, and whatever configured got it close enough...
121 Counters.pinScheduledAlready++;
122 }else{ // Otherwise it's go low
123 // if too close, resched to turn, ie, stay on... , if far enough away, self sched
124 if(newStartIsAfterOutputEndTimeAndCanSelfSet){
125 // self sched
126 injectorMainStartOffsetHolding[pin] = startTime - *injectorMainTimeRegisters[pin];
127 outputEventPulseWidthsHolding[pin] = outputEventPulseWidthsMath[outputEventNumber];
128 outputEventExtendNumberOfRepeatsHolding[pin] = outputEventExtendNumberOfRepeats[outputEventNumber];
129 outputEventExtendRepeatPeriodHolding[pin] = outputEventExtendRepeatPeriod[outputEventNumber];
130 outputEventDelayFinalPeriodHolding[pin] = outputEventDelayFinalPeriod[outputEventNumber];
131 selfSetTimer |= injectorMainOnMasks[pin]; // setup a bit to let the timer interrupt know to set its own new start from a var
132 Counters.pinScheduledToSelfSchedule++;
133 }else{
134 SCHEDULE_ONE_ECT_OUTPUT();
135 Counters.pinScheduledAgainToStayOn++;
138 }else{ // Configured to do nothing, or toggle
139 if(*injectorMainControlRegisters[pin] & injectorMainGoHighMasks[pin]){
140 // TOGGLE SHOULD EARN SOME SORT OF ERROR CONDITION/COUNTER
141 Counters.pinScheduledToToggleError++;
142 }else{
143 // DO NOTHING SHOULD DO THE SAME AS GO HIGH
144 // ie, do nothing
145 // if too close, do nothing, or if far enough away, resched
146 // for now just always do nothing as it's going to fire, and whatever configured got it close enough...
147 Counters.pinScheduledToDoNothing++;
150 }else{ // not enabled, schedule as normal
151 SCHEDULE_ONE_ECT_OUTPUT();
152 Counters.pinScheduledFromCold++;
155 #ifdef XGATE // This has to be here because the timing of the ECT stuff is critical and it must run first.
156 #include "xgateScheduler.c"
157 #endif // Also, this should always run so can't be inside the above if/else block.