rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
state_sequence.h
Go to the documentation of this file.
1/**
2 * @file state_sequence.h
3 *
4 * @date May 18, 2014
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 */
7
8#pragma once
9
10#include <stdint.h>
11#include "rusefi_enums.h"
12#include <rusefi/expected.h>
13
14enum class TriggerValue : uint8_t {
15 FALL = 0,
16 RISE = 1
17};
18
19// see also 'HW_EVENT_TYPES'
26
27/**
28 * This layer has two primary usages:
29 * 1) 'simple' PWM generation is used to produce actuator square control wave
30 * 2) 'complex' PWM generation is used for trigger simulator.
31 * Some triggers like Nissan 360 slot optical wheel need a lot of points to describe the shape of the wave.
32 * Looks like 252 is explained by 60 tooth * 2 (number of fronts) * 2 (number of crank rotations within engine cycle)
33 */
34#ifndef PWM_PHASE_MAX_COUNT
35// as of April 2020, trigger which requires most array length is REMIX_66_2_2_2
36// we can probably reduce RAM usage if we have more custom logic of triggers with large number of tooth while
37// pretty easy logic. like we do not need to REALLY have an array to remember the shape of evenly spaces 360 or 60/2 trigger :)
38// todo https://github.com/rusefi/rusefi/issues/3003
39#define PWM_PHASE_MAX_COUNT 280
40#endif /* PWM_PHASE_MAX_COUNT */
41// todo: rename to TRIGGER_CHANNEL_COUNT?
42#define PWM_PHASE_MAX_WAVE_PER_PWM 2
43
45
46/**
47 * This class represents multi-channel logical signals with shared time axis
48 *
49 * This is a semi-abstract interface so that implementations can exist for either regularized
50 * patterns (60-2, etc) or completely arbitrary patterns stored in arrays.
51 */
53public:
54 /**
55 * values in the (0..1] range which refer to points within the period at at which pin state
56 * should be changed So, in the simplest case we turn pin off at 0.3 and turn it on at 1 -
57 * that would give us a 70% duty cycle PWM
58 */
59 virtual float getSwitchTime(int phaseIndex) const = 0;
60 virtual pin_state_t getChannelState(int channelIndex, int phaseIndex) const = 0;
61
62 // Make sure the switch times are in order and end at the very end.
63 void checkSwitchTimes(float scale) const;
64
65 // Find the exact angle, or unexpected if it doesn't exist
66 expected<int> findAngleMatch(float angle) const;
67
68 // returns the index at which given value would need to be inserted into sorted array
69 int findInsertionAngle(float angle) const;
70
71 uint16_t phaseCount = 0; // Number of timestamps
72 uint16_t waveCount = 0; // Number of waveforms
73};
74
75template<unsigned max_phase>
77public:
78 float getSwitchTime(int phaseIndex) const override {
79 return switchTimes[phaseIndex];
80 }
81
82 pin_state_t getChannelState(int channelIndex, int phaseIndex) const override {
83 if (channelIndex >= waveCount) {
84 // todo: would be nice to get this asserting working
85 //criticalError("channel index %d/%d", channelIndex, waveCount);
86 }
87 return ((waveForm[phaseIndex] >> channelIndex) & 1) ? TriggerValue::RISE : TriggerValue::FALL;
88 }
89
90 void reset() {
91 waveCount = 0;
92 }
93
94 void setSwitchTime(const int phaseIndex, const float value) {
95 switchTimes[phaseIndex] = value;
96 }
97
98 void setChannelState(const int channelIndex, const int phaseIndex, pin_state_t state) {
99 if (channelIndex >= waveCount) {
100 // todo: would be nice to get this asserting working
101 //criticalError("channel index %d/%d", channelIndex, waveCount);
102 }
103 uint8_t & ref = waveForm[phaseIndex];
104 ref = (ref & ~(1U << channelIndex)) | ((state == TriggerValue::RISE ? 1 : 0) << channelIndex);
105 }
106
107private:
108 float switchTimes[max_phase];
109 uint8_t waveForm[max_phase];
110};
111
void checkSwitchTimes(float scale) const
virtual float getSwitchTime(int phaseIndex) const =0
virtual pin_state_t getChannelState(int channelIndex, int phaseIndex) const =0
int findInsertionAngle(float angle) const
expected< int > findAngleMatch(float angle) const
pin_state_t getChannelState(int channelIndex, int phaseIndex) const override
float getSwitchTime(int phaseIndex) const override
void setSwitchTime(const int phaseIndex, const float value)
void setChannelState(const int channelIndex, const int phaseIndex, pin_state_t state)
Fundamental rusEFI enumerable types live here.
state("state", SensorCategory.SENSOR_INPUTS, FieldType.INT8, 1871, 1.0, -1.0, -1.0, "")
TriggerValue pin_state_t
trigger_event_e
@ SHAFT_SECONDARY_RISING
@ SHAFT_SECONDARY_FALLING
@ SHAFT_PRIMARY_FALLING
@ SHAFT_PRIMARY_RISING
TriggerValue