Drop SingleChannelStateSequence in favor of MultiChannelStateSequenceWithData (#3519)
* Drop SingleChannelStateSequence in favor of MultiChannelStateSequenceWithData Most all the users were Multi* anyways, so just improve that: 1. Allow up to 8 waveforms to share one byte per timestamp. It could be better but this is simple and gets most of the benefit. 2. Use a wrapper structure to handle reserving space for the arrays. Makes the interface simpler and more rigid. Also saves 4 bytes per Multi*. Downside is access is now via -> and *, not . and (nothing). Saves 224 bytes of BSS, 1832 bytes of RAM4/CCM, 952 bytes of TEXT, and 103 bytes of RODATA * Instantiate a base_t to make debugging easier. Also fixes crash on real firmware by using &m_base instead - LTO optimization issue? * No magical templated StaticAlloc thingy. Just virtual functions.
This commit is contained in:
parent
9a28e8d938
commit
ba4a00d3bb
|
@ -9,86 +9,24 @@
|
|||
#include "state_sequence.h"
|
||||
#include "trigger_structure.h"
|
||||
|
||||
SingleChannelStateSequence::SingleChannelStateSequence() {
|
||||
init(NULL);
|
||||
}
|
||||
|
||||
SingleChannelStateSequence::SingleChannelStateSequence(pin_state_t *ps) {
|
||||
init(ps);
|
||||
}
|
||||
|
||||
void SingleChannelStateSequence::init(pin_state_t *pinStates) {
|
||||
this->pinStates = pinStates;
|
||||
}
|
||||
|
||||
pin_state_t SingleChannelStateSequence::getState(int switchIndex) const {
|
||||
pin_state_t state = pinStates[switchIndex];
|
||||
efiAssert(OBD_PCM_Processor_Fault, state == 0 || state == 1, "wave state get", TV_FALL);
|
||||
return state;
|
||||
}
|
||||
|
||||
void SingleChannelStateSequence::setState(int switchIndex, pin_state_t state) {
|
||||
efiAssertVoid(OBD_PCM_Processor_Fault, state == 0 || state == 1, "wave state set");
|
||||
pinStates[switchIndex] = state;
|
||||
}
|
||||
|
||||
MultiChannelStateSequence::MultiChannelStateSequence() {
|
||||
reset();
|
||||
}
|
||||
|
||||
MultiChannelStateSequence::MultiChannelStateSequence(float *switchTimes, SingleChannelStateSequence *waves) : MultiChannelStateSequence() {
|
||||
init(switchTimes, waves);
|
||||
}
|
||||
|
||||
void MultiChannelStateSequence::init(float *switchTimes, SingleChannelStateSequence *channels) {
|
||||
this->switchTimes = switchTimes;
|
||||
this->channels = channels;
|
||||
}
|
||||
|
||||
void MultiChannelStateSequence::reset(void) {
|
||||
waveCount = 0;
|
||||
}
|
||||
|
||||
float MultiChannelStateSequence::getSwitchTime(const int index) const {
|
||||
return switchTimes[index];
|
||||
}
|
||||
|
||||
void MultiChannelStateSequence::checkSwitchTimes(const float scale) const {
|
||||
if (switchTimes[phaseCount - 1] != 1) {
|
||||
firmwareError(CUSTOM_ERR_WAVE_1, "last switch time has to be 1/%f not %.2f/%f", scale,
|
||||
switchTimes[phaseCount - 1], scale * switchTimes[phaseCount - 1]);
|
||||
if (getSwitchTime(phaseCount - 1) != 1) {
|
||||
firmwareError(CUSTOM_ERR_WAVE_1, "last switch time has to be 1/%f not %.2f/%f",
|
||||
scale, getSwitchTime(phaseCount - 1),
|
||||
scale * getSwitchTime(phaseCount - 1));
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < phaseCount - 1; i++) {
|
||||
if (switchTimes[i] >= switchTimes[i + 1]) {
|
||||
firmwareError(CUSTOM_ERR_WAVE_2, "invalid switchTimes @%d: %.2f/%.2f", i, switchTimes[i], switchTimes[i + 1]);
|
||||
if (getSwitchTime(i) >= getSwitchTime(i + 1)) {
|
||||
firmwareError(CUSTOM_ERR_WAVE_2, "invalid switchTimes @%d: %.2f/%.2f",
|
||||
i, getSwitchTime(i), getSwitchTime(i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pin_state_t MultiChannelStateSequence::getChannelState(const int channelIndex, const int phaseIndex) const {
|
||||
if (channelIndex >= waveCount) {
|
||||
// todo: would be nice to get this asserting working
|
||||
//firmwareError(OBD_PCM_Processor_Fault, "channel index %d/%d", channelIndex, waveCount);
|
||||
}
|
||||
return channels[channelIndex].pinStates[phaseIndex];
|
||||
}
|
||||
|
||||
void MultiChannelStateSequence::setChannelState(const int channelIndex, const int phaseIndex,
|
||||
pin_state_t state) {
|
||||
if (channelIndex >= waveCount) {
|
||||
// todo: would be nice to get this asserting working
|
||||
//firmwareError(OBD_PCM_Processor_Fault, "channel index %d/%d", channelIndex, waveCount);
|
||||
}
|
||||
channels[channelIndex].pinStates[phaseIndex] = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the index at which given value would need to be inserted into sorted array
|
||||
*/
|
||||
int MultiChannelStateSequence::findInsertionAngle(const float angle) const {
|
||||
for (int i = phaseCount - 1; i >= 0; i--) {
|
||||
if (angle > switchTimes[i])
|
||||
if (angle > getSwitchTime(i))
|
||||
return i + 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -96,13 +34,8 @@ int MultiChannelStateSequence::findInsertionAngle(const float angle) const {
|
|||
|
||||
int MultiChannelStateSequence::findAngleMatch(const float angle) const {
|
||||
for (int i = 0; i < phaseCount; i++) {
|
||||
if (isSameF(switchTimes[i], angle))
|
||||
if (isSameF(getSwitchTime(i), angle))
|
||||
return i;
|
||||
}
|
||||
return EFI_ERROR_CODE;
|
||||
}
|
||||
|
||||
void MultiChannelStateSequence::setSwitchTime(const int index, const float value) {
|
||||
efiAssertVoid(CUSTOM_ERR_PWM_SWITCH_ASSERT, switchTimes != NULL, "switchTimes");
|
||||
switchTimes[index] = value;
|
||||
}
|
||||
|
|
|
@ -26,72 +26,72 @@
|
|||
#endif /* PWM_PHASE_MAX_COUNT */
|
||||
#define PWM_PHASE_MAX_WAVE_PER_PWM 3
|
||||
|
||||
/**
|
||||
* int8_t is probably less efficient then int32_t but we need
|
||||
* to reduce memory footprint
|
||||
*
|
||||
* todo: migrate to bit-array to save memory?
|
||||
* this would cost some CPU cycles. see std::vector<bool>
|
||||
*/
|
||||
typedef trigger_value_e pin_state_t;
|
||||
|
||||
/**
|
||||
* This class represents one channel of a digital signal state sequence
|
||||
* Each element represents either a HIGH or LOW state - while at the moment this
|
||||
* is not implemented using a bit array, it could absolutely be a bit array
|
||||
*
|
||||
* This sequence does not know anything about signal lengths - only signal state at a given index
|
||||
* This sequence can have consecutive zeros and ones since these sequences work as a group within MultiChannelStateSequence
|
||||
*
|
||||
* @brief PWM configuration for the specific output pin
|
||||
*/
|
||||
class SingleChannelStateSequence {
|
||||
public:
|
||||
SingleChannelStateSequence();
|
||||
explicit SingleChannelStateSequence(pin_state_t *pinStates);
|
||||
void init(pin_state_t *pinStates);
|
||||
/**
|
||||
* todo: confirm that we only deal with two states here, no magic '-1'?
|
||||
* @return HIGH or LOW state at given index
|
||||
*/
|
||||
pin_state_t getState(int switchIndex) const;
|
||||
void setState(int switchIndex, pin_state_t state);
|
||||
|
||||
// todo: make this private by using 'getState' and 'setState' methods
|
||||
pin_state_t *pinStates;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class represents multi-channel logical signals with shared time axis
|
||||
*
|
||||
* This is a semi-abstract interface so that implementations can exist for either regularized
|
||||
* patterns (60-2, etc) or completely arbitrary patterns stored in arrays.
|
||||
*/
|
||||
class MultiChannelStateSequence {
|
||||
public:
|
||||
MultiChannelStateSequence();
|
||||
MultiChannelStateSequence(float *switchTimes, SingleChannelStateSequence *waves);
|
||||
void init(float *switchTimes, SingleChannelStateSequence *waves);
|
||||
void reset(void);
|
||||
float getSwitchTime(const int phaseIndex) const;
|
||||
void setSwitchTime(const int phaseIndex, const float value);
|
||||
void checkSwitchTimes(const float scale) const;
|
||||
pin_state_t getChannelState(const int channelIndex, const int phaseIndex) const;
|
||||
void setChannelState(const int channelIndex, const int phaseIndex, pin_state_t state);
|
||||
|
||||
int findAngleMatch(const float angle) const;
|
||||
int findInsertionAngle(const float angle) const;
|
||||
|
||||
/**
|
||||
* Number of signal channels
|
||||
* values in the (0..1] range which refer to points within the period at at which pin state
|
||||
* should be changed So, in the simplest case we turn pin off at 0.3 and turn it on at 1 -
|
||||
* that would give us a 70% duty cycle PWM
|
||||
*/
|
||||
uint16_t phaseCount;
|
||||
uint16_t waveCount;
|
||||
SingleChannelStateSequence *channels = nullptr;
|
||||
//private:
|
||||
/**
|
||||
* values in the (0..1] range which refer to points within the period at at which pin state should be changed
|
||||
* So, in the simplest case we turn pin off at 0.3 and turn it on at 1 - that would give us a 70% duty cycle PWM
|
||||
*/
|
||||
float *switchTimes = nullptr;
|
||||
virtual float getSwitchTime(int phaseIndex) const = 0;
|
||||
virtual pin_state_t getChannelState(int channelIndex, int phaseIndex) const = 0;
|
||||
|
||||
// Make sure the switch times are in order and end at the very end.
|
||||
void checkSwitchTimes(float scale) const;
|
||||
|
||||
// Find the exact angle, or EFI_ERROR_CODE if it doesn't exist
|
||||
int findAngleMatch(float angle) const;
|
||||
|
||||
// returns the index at which given value would need to be inserted into sorted array
|
||||
int findInsertionAngle(float angle) const;
|
||||
|
||||
uint16_t phaseCount = 0; // Number of timestamps
|
||||
uint16_t waveCount = 0; // Number of waveforms
|
||||
};
|
||||
|
||||
template<unsigned max_phase>
|
||||
class MultiChannelStateSequenceWithData : public MultiChannelStateSequence {
|
||||
public:
|
||||
float getSwitchTime(int phaseIndex) const override {
|
||||
return switchTimes[phaseIndex];
|
||||
}
|
||||
|
||||
pin_state_t getChannelState(int channelIndex, int phaseIndex) const override {
|
||||
if (channelIndex >= waveCount) {
|
||||
// todo: would be nice to get this asserting working
|
||||
//firmwareError(OBD_PCM_Processor_Fault, "channel index %d/%d", channelIndex, waveCount);
|
||||
}
|
||||
return ((waveForm[phaseIndex] >> channelIndex) & 1) ? TV_RISE : TV_FALL;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
waveCount = 0;
|
||||
}
|
||||
|
||||
void setSwitchTime(const int phaseIndex, const float value) {
|
||||
efiAssertVoid(CUSTOM_ERR_PWM_SWITCH_ASSERT, switchTimes != nullptr, "switchTimes");
|
||||
switchTimes[phaseIndex] = value;
|
||||
}
|
||||
|
||||
void setChannelState(const int channelIndex, const int phaseIndex, pin_state_t state) {
|
||||
if (channelIndex >= waveCount) {
|
||||
// todo: would be nice to get this asserting working
|
||||
//firmwareError(OBD_PCM_Processor_Fault, "channel index %d/%d", channelIndex, waveCount);
|
||||
}
|
||||
uint8_t & ref = waveForm[phaseIndex];
|
||||
ref = (ref & ~(1U << channelIndex)) | ((state == TV_RISE ? 1 : 0) << channelIndex);
|
||||
}
|
||||
|
||||
private:
|
||||
float switchTimes[max_phase];
|
||||
uint8_t waveForm[max_phase];
|
||||
};
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
#define ZERO_PWM_THRESHOLD 0.01
|
||||
|
||||
SimplePwm::SimplePwm()
|
||||
: sr(pinStates)
|
||||
, seq(_switchTimes, &sr)
|
||||
{
|
||||
seq.waveCount = 1;
|
||||
seq.phaseCount = 2;
|
||||
|
@ -87,7 +85,7 @@ void SimplePwm::setSimplePwmDutyCycle(float dutyCycle) {
|
|||
mode = PM_FULL;
|
||||
} else {
|
||||
mode = PM_NORMAL;
|
||||
_switchTimes[0] = dutyCycle;
|
||||
seq.setSwitchTime(0, dutyCycle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,15 +314,15 @@ void startSimplePwm(SimplePwm *state, const char *msg, ExecutorInterface *execut
|
|||
return;
|
||||
}
|
||||
|
||||
state->_switchTimes[0] = dutyCycle;
|
||||
state->_switchTimes[1] = 1;
|
||||
state->pinStates[0] = TV_FALL;
|
||||
state->pinStates[1] = TV_RISE;
|
||||
state->seq.setSwitchTime(0, dutyCycle);
|
||||
state->seq.setSwitchTime(1, 1);
|
||||
state->seq.setChannelState(0, 0, TV_FALL);
|
||||
state->seq.setChannelState(0, 1, TV_RISE);
|
||||
|
||||
state->outputPins[0] = output;
|
||||
|
||||
state->setFrequency(frequency);
|
||||
state->setSimplePwmDutyCycle(dutyCycle); // TODO: DUP ABOVE?
|
||||
state->setSimplePwmDutyCycle(dutyCycle);
|
||||
state->weComplexInit(msg, executor, &state->seq, NULL, (pwm_gen_callback*)applyPinState);
|
||||
}
|
||||
|
||||
|
|
|
@ -120,10 +120,7 @@ public:
|
|||
SimplePwm();
|
||||
explicit SimplePwm(const char *name);
|
||||
void setSimplePwmDutyCycle(float dutyCycle) override;
|
||||
pin_state_t pinStates[2];
|
||||
SingleChannelStateSequence sr;
|
||||
float _switchTimes[2];
|
||||
MultiChannelStateSequence seq;
|
||||
MultiChannelStateSequenceWithData<2> seq;
|
||||
hardware_pwm* hardPwm = nullptr;
|
||||
};
|
||||
|
||||
|
|
|
@ -49,18 +49,8 @@ void event_trigger_position_s::setAngle(angle_t angle) {
|
|||
this, angle);
|
||||
}
|
||||
|
||||
trigger_shape_helper::trigger_shape_helper() {
|
||||
memset(&pinStates, 0, sizeof(pinStates));
|
||||
for (int channelIndex = 0; channelIndex < TRIGGER_CHANNEL_COUNT; channelIndex++) {
|
||||
channels[channelIndex].init(pinStates[channelIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
TriggerWaveform::TriggerWaveform()
|
||||
: waveStorage(switchTimesBuffer, NULL)
|
||||
, wave(&waveStorage) {
|
||||
TriggerWaveform::TriggerWaveform() {
|
||||
initialize(OM_NONE);
|
||||
wave->channels = h.channels;
|
||||
}
|
||||
|
||||
void TriggerWaveform::initialize(operation_mode_e operationMode) {
|
||||
|
@ -85,11 +75,10 @@ void TriggerWaveform::initialize(operation_mode_e operationMode) {
|
|||
this->operationMode = operationMode;
|
||||
triggerShapeSynchPointIndex = 0;
|
||||
memset(initialState, 0, sizeof(initialState));
|
||||
memset(switchTimesBuffer, 0, sizeof(switchTimesBuffer));
|
||||
memset(expectedEventCount, 0, sizeof(expectedEventCount));
|
||||
wave->reset();
|
||||
wave->waveCount = TRIGGER_CHANNEL_COUNT;
|
||||
wave->phaseCount = 0;
|
||||
wave.reset();
|
||||
wave.waveCount = TRIGGER_CHANNEL_COUNT;
|
||||
wave.phaseCount = 0;
|
||||
previousAngle = 0;
|
||||
memset(isRiseEvent, 0, sizeof(isRiseEvent));
|
||||
#if EFI_UNIT_TEST
|
||||
|
@ -99,7 +88,7 @@ void TriggerWaveform::initialize(operation_mode_e operationMode) {
|
|||
}
|
||||
|
||||
size_t TriggerWaveform::getSize() const {
|
||||
return wave->phaseCount;
|
||||
return wave.phaseCount;
|
||||
}
|
||||
|
||||
int TriggerWaveform::getTriggerWaveformSynchPointIndex() const {
|
||||
|
@ -149,9 +138,9 @@ angle_t TriggerWaveform::getAngle(int index) const {
|
|||
* See also trigger_central.cpp
|
||||
* See also getEngineCycleEventCount()
|
||||
*/
|
||||
efiAssert(CUSTOM_ERR_ASSERT, wave->phaseCount != 0, "shapeSize=0", NAN);
|
||||
int crankCycle = index / wave->phaseCount;
|
||||
int remainder = index % wave->phaseCount;
|
||||
efiAssert(CUSTOM_ERR_ASSERT, wave.phaseCount != 0, "shapeSize=0", NAN);
|
||||
int crankCycle = index / wave.phaseCount;
|
||||
int remainder = index % wave.phaseCount;
|
||||
|
||||
auto cycleStartAngle = getCycleDuration() * crankCycle;
|
||||
auto positionWithinCycle = getSwitchAngle(remainder);
|
||||
|
@ -235,9 +224,9 @@ void TriggerWaveform::addEvent(angle_t angle, trigger_wheel_e const channelIndex
|
|||
#endif
|
||||
|
||||
#if EFI_UNIT_TEST
|
||||
assertIsInBounds(wave->phaseCount, triggerSignalIndeces, "trigger shape overflow");
|
||||
triggerSignalIndeces[wave->phaseCount] = channelIndex;
|
||||
triggerSignalStates[wave->phaseCount] = state;
|
||||
assertIsInBounds(wave.phaseCount, triggerSignalIndeces, "trigger shape overflow");
|
||||
triggerSignalIndeces[wave.phaseCount] = channelIndex;
|
||||
triggerSignalStates[wave.phaseCount] = state;
|
||||
#endif // EFI_UNIT_TEST
|
||||
|
||||
|
||||
|
@ -249,46 +238,39 @@ void TriggerWaveform::addEvent(angle_t angle, trigger_wheel_e const channelIndex
|
|||
}
|
||||
|
||||
efiAssertVoid(CUSTOM_ERR_6599, angle > 0 && angle <= 1, "angle should be positive not above 1");
|
||||
if (wave->phaseCount > 0) {
|
||||
if (wave.phaseCount > 0) {
|
||||
if (angle <= previousAngle) {
|
||||
warning(CUSTOM_ERR_TRG_ANGLE_ORDER, "invalid angle order %s %s: new=%.2f/%f and prev=%.2f/%f, size=%d",
|
||||
getTrigger_wheel_e(channelIndex),
|
||||
getTrigger_value_e(state),
|
||||
angle, angle * getCycleDuration(),
|
||||
previousAngle, previousAngle * getCycleDuration(),
|
||||
wave->phaseCount);
|
||||
wave.phaseCount);
|
||||
setShapeDefinitionError(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
previousAngle = angle;
|
||||
if (wave->phaseCount == 0) {
|
||||
wave->phaseCount = 1;
|
||||
if (wave.phaseCount == 0) {
|
||||
wave.phaseCount = 1;
|
||||
for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) {
|
||||
SingleChannelStateSequence *swave = &wave->channels[i];
|
||||
|
||||
if (swave->pinStates == nullptr) {
|
||||
warning(CUSTOM_ERR_STATE_NULL, "wave pinStates is NULL");
|
||||
setShapeDefinitionError(true);
|
||||
return;
|
||||
}
|
||||
wave->setChannelState(i, /* switchIndex */ 0, /* value */ initialState[i]);
|
||||
wave.setChannelState(i, /* switchIndex */ 0, /* value */ initialState[i]);
|
||||
}
|
||||
|
||||
isRiseEvent[0] = TV_RISE == state;
|
||||
wave->setSwitchTime(0, angle);
|
||||
wave->setChannelState(channelIndex, /* channelIndex */ 0, /* value */ state);
|
||||
wave.setSwitchTime(0, angle);
|
||||
wave.setChannelState(channelIndex, /* channelIndex */ 0, /* value */ state);
|
||||
return;
|
||||
}
|
||||
|
||||
int exactMatch = wave->findAngleMatch(angle);
|
||||
int exactMatch = wave.findAngleMatch(angle);
|
||||
if (exactMatch != (int)EFI_ERROR_CODE) {
|
||||
warning(CUSTOM_ERR_SAME_ANGLE, "same angle: not supported");
|
||||
setShapeDefinitionError(true);
|
||||
return;
|
||||
}
|
||||
|
||||
int index = wave->findInsertionAngle(angle);
|
||||
int index = wave.findInsertionAngle(angle);
|
||||
|
||||
/**
|
||||
* todo: it would be nice to be able to provide trigger angles without sorting them externally
|
||||
|
@ -298,29 +280,29 @@ void TriggerWaveform::addEvent(angle_t angle, trigger_wheel_e const channelIndex
|
|||
/*
|
||||
for (int i = size - 1; i >= index; i--) {
|
||||
for (int j = 0; j < PWM_PHASE_MAX_WAVE_PER_PWM; j++) {
|
||||
wave->waves[j].pinStates[i + 1] = wave->getChannelState(j, index);
|
||||
wave.waves[j].pinStates[i + 1] = wave.getChannelState(j, index);
|
||||
}
|
||||
wave->setSwitchTime(i + 1, wave->getSwitchTime(i));
|
||||
wave.setSwitchTime(i + 1, wave.getSwitchTime(i));
|
||||
}
|
||||
*/
|
||||
isRiseEvent[index] = TV_RISE == state;
|
||||
|
||||
if ((unsigned)index != wave->phaseCount) {
|
||||
if ((unsigned)index != wave.phaseCount) {
|
||||
firmwareError(ERROR_TRIGGER_DRAMA, "are we ever here?");
|
||||
}
|
||||
|
||||
wave->phaseCount++;
|
||||
wave.phaseCount++;
|
||||
|
||||
for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) {
|
||||
pin_state_t value = wave->getChannelState(/* channelIndex */i, index - 1);
|
||||
wave->setChannelState(i, index, value);
|
||||
pin_state_t value = wave.getChannelState(/* channelIndex */i, index - 1);
|
||||
wave.setChannelState(i, index, value);
|
||||
}
|
||||
wave->setSwitchTime(index, angle);
|
||||
wave->setChannelState(channelIndex, index, state);
|
||||
wave.setSwitchTime(index, angle);
|
||||
wave.setChannelState(channelIndex, index, state);
|
||||
}
|
||||
|
||||
angle_t TriggerWaveform::getSwitchAngle(int index) const {
|
||||
return getCycleDuration() * wave->getSwitchTime(index);
|
||||
return getCycleDuration() * wave.getSwitchTime(index);
|
||||
}
|
||||
|
||||
void setToothedWheelConfiguration(TriggerWaveform *s, int total, int skipped,
|
||||
|
@ -761,7 +743,7 @@ void TriggerWaveform::initializeTriggerWaveform(operation_mode_e ambiguousOperat
|
|||
version++;
|
||||
|
||||
if (!shapeDefinitionError) {
|
||||
wave->checkSwitchTimes(getCycleDuration());
|
||||
wave.checkSwitchTimes(getCycleDuration());
|
||||
}
|
||||
|
||||
if (bothFrontsRequired && useOnlyRisingEdgeForTrigger) {
|
||||
|
|
|
@ -60,15 +60,6 @@ public:
|
|||
|
||||
#define TRIGGER_CHANNEL_COUNT 3
|
||||
|
||||
class trigger_shape_helper {
|
||||
public:
|
||||
trigger_shape_helper();
|
||||
|
||||
SingleChannelStateSequence channels[TRIGGER_CHANNEL_COUNT];
|
||||
private:
|
||||
pin_state_t pinStates[TRIGGER_CHANNEL_COUNT][PWM_PHASE_MAX_COUNT];
|
||||
};
|
||||
|
||||
class Engine;
|
||||
class TriggerState;
|
||||
class TriggerFormDetails;
|
||||
|
@ -199,8 +190,7 @@ public:
|
|||
* but name is supposed to hint at the fact that decoders should not be assigning to it
|
||||
* Please use "getTriggerSize()" macro or "getSize()" method to read this value
|
||||
*/
|
||||
MultiChannelStateSequence waveStorage; // DON'T USE - WILL BE REMOVED LATER
|
||||
MultiChannelStateSequence * const wave;
|
||||
MultiChannelStateSequenceWithData<PWM_PHASE_MAX_COUNT> wave;
|
||||
|
||||
// todo: add a runtime validation which would verify that this field was set properly
|
||||
// todo: maybe even automate this flag calculation?
|
||||
|
@ -276,14 +266,6 @@ public:
|
|||
uint16_t findAngleIndex(TriggerFormDetails *details, angle_t angle) const;
|
||||
|
||||
private:
|
||||
trigger_shape_helper h;
|
||||
|
||||
/**
|
||||
* Working buffer for 'wave' instance
|
||||
* Values are in the 0..1 range
|
||||
*/
|
||||
float switchTimesBuffer[PWM_PHASE_MAX_COUNT];
|
||||
|
||||
/**
|
||||
* These angles are in trigger DESCRIPTION coordinates - i.e. the way you add events while declaring trigger shape
|
||||
*/
|
||||
|
@ -326,4 +308,4 @@ void setToothedWheelConfiguration(TriggerWaveform *s, int total, int skipped, op
|
|||
|
||||
#define TRIGGER_WAVEFORM(x) engine->triggerCentral.triggerShape.x
|
||||
|
||||
#define getTriggerSize() TRIGGER_WAVEFORM(wave->phaseCount)
|
||||
#define getTriggerSize() TRIGGER_WAVEFORM(wave.phaseCount)
|
||||
|
|
|
@ -20,7 +20,7 @@ int getPreviousIndex(const int currentIndex, const int size) {
|
|||
return (currentIndex + size - 1) % size;
|
||||
}
|
||||
|
||||
bool needEvent(const int currentIndex, const MultiChannelStateSequence& mcss, int channelIndex) {
|
||||
bool needEvent(const int currentIndex, const MultiChannelStateSequence & mcss, int channelIndex) {
|
||||
int prevIndex = getPreviousIndex(currentIndex, mcss.phaseCount);
|
||||
pin_state_t previousValue = mcss.getChannelState(channelIndex, /*phaseIndex*/prevIndex);
|
||||
pin_state_t currentValue = mcss.getChannelState(channelIndex, /*phaseIndex*/currentIndex);
|
||||
|
@ -106,7 +106,7 @@ static void updateTriggerWaveformIfNeeded(PwmConfig *state) {
|
|||
|
||||
|
||||
TriggerWaveform *s = &engine->triggerCentral.triggerShape;
|
||||
copyPwmParameters(state, s->wave);
|
||||
copyPwmParameters(state, &s->wave);
|
||||
state->safe.periodNt = -1; // this would cause loop re-initialization
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ static void initTriggerPwm() {
|
|||
setTriggerEmulatorRPM(engineConfiguration->triggerSimulatorFrequency);
|
||||
triggerSignal.weComplexInit("position sensor",
|
||||
&engine->executor,
|
||||
s->wave,
|
||||
&s->wave,
|
||||
updateTriggerWaveformIfNeeded, (pwm_gen_callback*)emulatorApplyPinState);
|
||||
|
||||
hasInitTriggerEmulator = true;
|
||||
|
|
|
@ -33,7 +33,7 @@ int getSimulatedEventTime(const TriggerWaveform& shape, int i) {
|
|||
int stateIndex = i % shape.getSize();
|
||||
int loopIndex = i / shape.getSize();
|
||||
|
||||
return (int) (SIMULATION_CYCLE_PERIOD * (loopIndex + shape.wave->getSwitchTime(stateIndex)));
|
||||
return (int) (SIMULATION_CYCLE_PERIOD * (loopIndex + shape.wave.getSwitchTime(stateIndex)));
|
||||
}
|
||||
|
||||
void TriggerStimulatorHelper::feedSimulatedEvent(
|
||||
|
@ -48,7 +48,7 @@ void TriggerStimulatorHelper::feedSimulatedEvent(
|
|||
|
||||
int time = getSimulatedEventTime(shape, i);
|
||||
|
||||
const MultiChannelStateSequence& multiChannelStateSequence = *shape.wave;
|
||||
const auto & multiChannelStateSequence = shape.wave;
|
||||
|
||||
#if EFI_UNIT_TEST
|
||||
int prevIndex = getPreviousIndex(stateIndex, shape.getSize());
|
||||
|
|
|
@ -103,31 +103,31 @@ static void configureFordAspireTriggerWaveform(TriggerWaveform * s) {
|
|||
s->addEvent720(657.03, T_SECONDARY, TV_FALL);
|
||||
s->addEvent720(720, T_PRIMARY, TV_FALL);
|
||||
|
||||
ASSERT_FLOAT_EQ(53.747 / 720, s->wave->getSwitchTime(0));
|
||||
ASSERT_EQ( 1, s->wave->getChannelState(1, 0)) << "@0";
|
||||
ASSERT_EQ( 1, s->wave->getChannelState(1, 0)) << "@0";
|
||||
ASSERT_FLOAT_EQ(53.747 / 720, s->wave.getSwitchTime(0));
|
||||
ASSERT_EQ( 1, s->wave.getChannelState(1, 0)) << "@0";
|
||||
ASSERT_EQ( 1, s->wave.getChannelState(1, 0)) << "@0";
|
||||
|
||||
ASSERT_EQ( 0, s->wave->getChannelState(0, 1)) << "@1";
|
||||
ASSERT_EQ( 0, s->wave->getChannelState(1, 1)) << "@1";
|
||||
ASSERT_EQ( 0, s->wave.getChannelState(0, 1)) << "@1";
|
||||
ASSERT_EQ( 0, s->wave.getChannelState(1, 1)) << "@1";
|
||||
|
||||
ASSERT_EQ( 0, s->wave->getChannelState(0, 2)) << "@2";
|
||||
ASSERT_EQ( 1, s->wave->getChannelState(1, 2)) << "@2";
|
||||
ASSERT_EQ( 0, s->wave.getChannelState(0, 2)) << "@2";
|
||||
ASSERT_EQ( 1, s->wave.getChannelState(1, 2)) << "@2";
|
||||
|
||||
ASSERT_EQ( 0, s->wave->getChannelState(0, 3)) << "@3";
|
||||
ASSERT_EQ( 0, s->wave->getChannelState(1, 3)) << "@3";
|
||||
ASSERT_EQ( 0, s->wave.getChannelState(0, 3)) << "@3";
|
||||
ASSERT_EQ( 0, s->wave.getChannelState(1, 3)) << "@3";
|
||||
|
||||
ASSERT_EQ( 1, s->wave->getChannelState(0, 4)) << "@4";
|
||||
ASSERT_EQ( 1, s->wave->getChannelState(1, 5)) << "@5";
|
||||
ASSERT_EQ( 0, s->wave->getChannelState(1, 8)) << "@8";
|
||||
ASSERT_FLOAT_EQ(121.90 / 720, s->wave->getSwitchTime(1));
|
||||
ASSERT_FLOAT_EQ(657.03 / 720, s->wave->getSwitchTime(8));
|
||||
ASSERT_EQ( 1, s->wave.getChannelState(0, 4)) << "@4";
|
||||
ASSERT_EQ( 1, s->wave.getChannelState(1, 5)) << "@5";
|
||||
ASSERT_EQ( 0, s->wave.getChannelState(1, 8)) << "@8";
|
||||
ASSERT_FLOAT_EQ(121.90 / 720, s->wave.getSwitchTime(1));
|
||||
ASSERT_FLOAT_EQ(657.03 / 720, s->wave.getSwitchTime(8));
|
||||
|
||||
ASSERT_EQ( 0, s->wave->findAngleMatch(53.747 / 720.0)) << "expecting 0";
|
||||
assertEqualsM("expecting not found", -1, s->wave->findAngleMatch(53 / 720.0));
|
||||
ASSERT_EQ(7, s->wave->findAngleMatch(588.045 / 720.0));
|
||||
ASSERT_EQ( 0, s->wave.findAngleMatch(53.747 / 720.0)) << "expecting 0";
|
||||
assertEqualsM("expecting not found", -1, s->wave.findAngleMatch(53 / 720.0));
|
||||
ASSERT_EQ(7, s->wave.findAngleMatch(588.045 / 720.0));
|
||||
|
||||
ASSERT_EQ( 0, s->wave->findInsertionAngle(23.747 / 720.0)) << "expecting 0";
|
||||
ASSERT_EQ( 1, s->wave->findInsertionAngle(63.747 / 720.0)) << "expecting 1";
|
||||
ASSERT_EQ( 0, s->wave.findInsertionAngle(23.747 / 720.0)) << "expecting 0";
|
||||
ASSERT_EQ( 1, s->wave.findInsertionAngle(63.747 / 720.0)) << "expecting 1";
|
||||
}
|
||||
|
||||
TEST(misc, testAngleResolver) {
|
||||
|
@ -142,9 +142,9 @@ TEST(misc, testAngleResolver) {
|
|||
engine->initializeTriggerWaveform();
|
||||
|
||||
assertEqualsM("index 2", 52.76, triggerFormDetails->eventAngles[3]); // this angle is relation to synch point
|
||||
assertEqualsM("time 2", 0.3233, ts->wave->getSwitchTime(2));
|
||||
assertEqualsM("time 2", 0.3233, ts->wave.getSwitchTime(2));
|
||||
assertEqualsM("index 5", 412.76, triggerFormDetails->eventAngles[6]);
|
||||
assertEqualsM("time 5", 0.5733, ts->wave->getSwitchTime(5));
|
||||
assertEqualsM("time 5", 0.5733, ts->wave.getSwitchTime(5));
|
||||
|
||||
ASSERT_EQ(4, ts->getTriggerWaveformSynchPointIndex());
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ TEST(miata, miata_na_tdc) {
|
|||
eth.setTimeAndInvokeEventsUs(time);
|
||||
|
||||
emulatorHelper.handleEmulatorCallback(
|
||||
*shape.wave,
|
||||
shape.wave,
|
||||
i % shape.getSize());
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@ public:
|
|||
static void func(TriggerCallback *callback) {
|
||||
int formIndex = callback->toothIndex % callback->form->getSize();
|
||||
Engine *engine = callback->engine;
|
||||
|
||||
|
||||
int value = callback->form->wave->getChannelState(0, formIndex);
|
||||
|
||||
int value = callback->form->wave.getChannelState(0, formIndex);
|
||||
efitick_t nowNt = getTimeNowNt();
|
||||
if (callback->isVvt) {
|
||||
trigger_value_e v = value ? TV_RISE : TV_FALL;
|
||||
|
|
|
@ -466,10 +466,10 @@ TEST(misc, testTriggerDecoder) {
|
|||
s->useOnlyRisingEdgeForTriggerTemp = false;
|
||||
initializeSkippedToothTriggerWaveformExt(s, 2, 0, FOUR_STROKE_CAM_SENSOR);
|
||||
assertEqualsM("shape size", s->getSize(), 4);
|
||||
ASSERT_EQ(s->wave->getSwitchTime(0), 0.25);
|
||||
ASSERT_EQ(s->wave->getSwitchTime(1), 0.5);
|
||||
ASSERT_EQ(s->wave->getSwitchTime(2), 0.75);
|
||||
ASSERT_EQ(s->wave->getSwitchTime(3), 1);
|
||||
ASSERT_EQ(s->wave.getSwitchTime(0), 0.25);
|
||||
ASSERT_EQ(s->wave.getSwitchTime(1), 0.5);
|
||||
ASSERT_EQ(s->wave.getSwitchTime(2), 0.75);
|
||||
ASSERT_EQ(s->wave.getSwitchTime(3), 1);
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue