1 /*
2  * Trigger.h
3  *
4  *  Created on: 29 Jan 2020
5  *      Author: crocoduck
6  */
7 
8 #ifndef CORE_UTIL_TRIGGER_H_
9 #define CORE_UTIL_TRIGGER_H_
10 
11 #include <core/types.h>
12 #include <core/IStateDumper.h>
13 
14 namespace lsp
15 {
16     enum trg_mode_t
17     {
18         TRG_MODE_SINGLE,
19         TRG_MODE_MANUAL,
20         TRG_MODE_REPEAT,
21         TRG_MODE_MAX
22     };
23 
24     enum trg_type_t
25     {
26         TRG_TYPE_NONE,
27         TRG_TYPE_SIMPLE_RISING_EDGE,
28         TRG_TYPE_SIMPLE_FALLING_EDGE,
29         TRG_TYPE_ADVANCED_RISING_EDGE,
30         TRG_TYPE_ADVANCED_FALLING_EDGE,
31         TRG_TYPE_MAX
32     };
33 
34     enum trg_state_t
35     {
36         TRG_STATE_WAITING,
37         TRG_STATE_ARMED,
38         TRG_STATE_FIRED,
39         TRG_STATE_MAX
40     };
41 
42     class Trigger
43     {
44         protected:
45 
46             // To use with Manual and Single Mode
47             typedef struct trg_locks_t
48             {
49                 bool    bSingleLock;
50                 bool    bManualAllow;
51                 bool    bManualLock;
52             } trg_locks_t;
53 
54             typedef struct simple_trg_t
55             {
56                 float   fThreshold;
57             } simple_trg_t;
58 
59             typedef struct advanced_trg_t
60             {
61                 float   fThreshold;
62                 float   fHysteresis;
63                 float   fLowerThreshold;
64                 float   fUpperThreshold;
65                 bool    bDisarm;
66             } advanced_trg_t;
67 
68         private:
69             Trigger & operator = (const Trigger &);
70 
71         private:
72             float           fPrevious;
73 
74             trg_mode_t      enTriggerMode;
75             trg_type_t      enTriggerType;
76             trg_state_t     enTriggerState;
77 
78             size_t          nTriggerHold;
79             size_t          nTriggerHoldCounter;
80 
81             trg_locks_t     sLocks;
82 
83             simple_trg_t    sSimpleTrg;
84             advanced_trg_t  sAdvancedTrg;
85 
86             bool            bSync;
87 
88         public:
89             explicit Trigger();
90             ~Trigger();
91 
92             void            construct();
93             void            destroy();
94 
95         protected:
set_simple_trg_threshold(float threshold)96             inline void set_simple_trg_threshold(float threshold)
97             {
98                 sSimpleTrg.fThreshold = threshold;
99             }
100 
update_advanced_trg()101             inline void update_advanced_trg()
102             {
103                 sAdvancedTrg.fLowerThreshold = sAdvancedTrg.fThreshold - sAdvancedTrg.fHysteresis;
104                 sAdvancedTrg.fUpperThreshold = sAdvancedTrg.fThreshold + sAdvancedTrg.fHysteresis;
105             }
106 
set_advanced_trg_threshold(float threshold)107             inline void set_advanced_trg_threshold(float threshold)
108             {
109                 sAdvancedTrg.fThreshold = threshold;
110 
111                 update_advanced_trg();
112             }
113 
set_advanced_trg_hysteresis(float hysteresis)114             inline void set_advanced_trg_hysteresis(float hysteresis)
115             {
116                 if (hysteresis < 0.0f)
117                     hysteresis = -hysteresis;
118 
119                 sAdvancedTrg.fHysteresis = hysteresis;
120 
121                 update_advanced_trg();
122             }
123 
124         public:
125 
126             /** Check that trigger needs settings update.
127              *
128              * @return true if trigger needs settings update.
129              */
needs_update()130             inline bool needs_update() const
131             {
132                 return bSync;
133             }
134 
135             /** This method should be called if needs_update() returns true.
136              * before calling process() methods.
137              *
138              */
139             void update_settings();
140 
141             /** Set the trigger mode.
142              *
143              * @param mode trigger mode.
144              */
set_trigger_mode(trg_mode_t mode)145             inline void set_trigger_mode(trg_mode_t mode)
146             {
147                 if ((mode < TRG_MODE_SINGLE) || (mode >= TRG_MODE_MAX) || (enTriggerMode == mode))
148                     return;
149 
150                 enTriggerMode = mode;
151                 bSync = true;
152             }
153 
154             /** Reset the single trigger.
155              *
156              */
reset_single_trigger()157             inline void reset_single_trigger()
158             {
159                 sLocks.bSingleLock = false;
160                 bSync = true;
161             }
162 
163             /** Activate the manual trigger.
164              *
165              */
activate_manual_trigger()166             inline void activate_manual_trigger()
167             {
168                 sLocks.bManualAllow = true;
169                 sLocks.bManualLock = false;
170                 bSync = true;
171             }
172 
173             /** Set the post-trigger samples. The trigger can be allowed to fire only after the post-trigger samples have elapsed.
174              *
175              * @param nSamples number of post-trigger samples.
176              */
set_trigger_hold_samples(size_t nSamples)177             inline void set_trigger_hold_samples(size_t nSamples)
178             {
179                 if (nSamples == nTriggerHold)
180                     return;
181 
182                 nTriggerHold = nSamples;
183                 nTriggerHoldCounter = 0;
184             }
185 
186             /** Set the trigger type.
187              *
188              * @param type trigger type.
189              */
set_trigger_type(trg_type_t type)190             inline void set_trigger_type(trg_type_t type)
191             {
192                 if ((type < TRG_TYPE_NONE) || (type >= TRG_TYPE_MAX) || (enTriggerType == type))
193                     return;
194 
195                 enTriggerType = type;
196                 bSync = true;
197             }
198 
199             /** Set the trigger threshold.
200              *
201              * @param trigger threshold.
202              */
set_trigger_threshold(float threshold)203             inline void set_trigger_threshold(float threshold)
204             {
205                 set_simple_trg_threshold(threshold);
206                 set_advanced_trg_threshold(threshold);
207                 bSync = true;
208             }
209 
210             /** Set the trigger hysteresis.
211              *
212              * @param hysteresis hysteresis.
213              */
set_trigger_hysteresis(float hysteresis)214             inline void set_trigger_hysteresis(float hysteresis)
215             {
216                 set_advanced_trg_hysteresis(hysteresis);
217                 bSync = true;
218             }
219 
220             /** Return he trigger state.
221              *
222              * @return trigger state.
223              */
get_trigger_state()224             inline trg_state_t get_trigger_state() const
225             {
226                 return enTriggerState;
227             }
228 
229             /** Feed a single sample to the trigger. Query the trigger status afterwards.
230              *
231              */
232             void single_sample_processor(float value);
233 
234             /**
235              * Dump the state
236              * @param dumper dumper
237              */
238             void dump(IStateDumper *v) const;
239     };
240 }
241 
242 #endif /* CORE_UTIL_TRIGGER_H_ */
243