-
Notifications
You must be signed in to change notification settings - Fork 0
/
Logic_out.c
247 lines (206 loc) · 6.8 KB
/
Logic_out.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/*!\file Logic_out.c
** \author SMFSW
** \copyright MIT (c) 2017-2024, SMFSW
** \brief Logic output handling
** \note Define LOGIC_OUT_IT symbol at project level to use Logic_out from timer interrupts (for more timing precision if required)
** \note When using Logic_out from interrupts, LOGIC_OUT_IT_PER period is defined by default with a period of 1000µs (can be customly defined)
** \warning Logic_out & GPIO_out shares interrupt behavior, thus needs to be implemented the same way (it or loop) if both are used at the same time
**/
/****************************************************************/
#include "Logic_out.h"
/****************************************************************/
/*!\brief Logic output variable setter
** \param[in] out - Logic_out instance
** \param[in] state - Logic_out state
**/
__STATIC_INLINE void NONNULL_INLINE__ Logic_out_setter(const Logic_out * const out, const GPIO_PinState state)
{
const uint32_t bit_mask = LSHIFT(1U, out->cfg.LOG_Pos);
if (out->cfg.LOGx) { SET_BITS_VAL(*((uint32_t *) out->cfg.LOGx), bit_mask, state ? bit_mask : 0); }
}
/*!\brief Set GPIO port value
** \param[in,out] out - Logic_out instance
** \return Error code
**/
FctERR NONNULL__ Logic_out_update(Logic_out * const out)
{
if (out->action == Reset) { out->currentState = GPIO_PIN_RESET; }
else if (out->action == Set) { out->currentState = GPIO_PIN_SET; }
else if (out->action == Toggle) { out->currentState ^= 1; }
else { return ERROR_VALUE; }
const GPIO_PinState val = out->currentState ^ (out->cfg.polarity ? 0 : 1);
if (out->cfg.set) { out->cfg.set(out, val); }
else { Logic_out_setter(out, val); }
return ERROR_OK;
}
FctERR NONNULLX__(1) Logic_out_init(Logic_out * const out, void (*setter)(const Logic_out * const, const GPIO_PinState),
uint32_t * const addr, const uint16_t pos, const GPIO_PinState polarity)
{
/* Check the parameters */
//assert_param(pos < 32); // Would raise an assert error in case of GPIO pin
out->cfg.set = setter;
out->cfg.LOGx = addr;
out->cfg.LOG_Pos = pos;
out->cfg.polarity = polarity;
out->currentState = GPIO_PIN_RESET;
out->memState = GPIO_PIN_RESET;
out->action = Reset;
out->idle = true;
out->init = true;
return Logic_out_update(out); // Immediately set to reset value
}
FctERR NONNULL__ Logic_out_Abort(Logic_out * const out)
{
FctERR err = ERROR_OK;
if ((out->init) && (!out->idle))
{
err = Logic_out_SetStatic(out, out->memState, 0);
}
return err;
}
/*!\brief Start Logic_out change
** \param[in,out] out - Logic_out instance
** \param[in] mode - Logic_out mode
** \param[in] action - action to perform on output port pin for active state (Reset/Set/Toggle)
** \param[in] delay - delay before pulse (in ms)
** \param[in] active - active time (in ms) for pulse/blink mode only
** \param[in] inactive - inactive time (in ms) for blink mode only
** \param[in] count - blink count (0 for infinite) for blink mode only
** \return Error code
**/
static FctERR NONNULL__ Logic_out_Start(Logic_out * const out, const eLogic_out_mode mode, const eGPIOState action,
uint32_t delay, uint32_t active, uint32_t inactive, const uint32_t count)
{
if (!out->init) { return ERROR_INSTANCE; }
if (action > Toggle) { return ERROR_VALUE; }
#if defined(LOGIC_OUT_IT) || defined(GPIO_OUT_IT)
delay = (delay * LOGIC_OUT_IT_PER) / 1000;
active = (active * LOGIC_OUT_IT_PER) / 1000;
inactive = (inactive * LOGIC_OUT_IT_PER) / 1000;
out->hOut = 0;
diInterrupts();
#else
out->hOut = HALTicks();
#endif
out->mode = mode;
out->action = action;
out->delay = delay;
out->timeActive = active;
out->timeInactive = inactive;
out->infinite = count ? false : true;
out->cnt = count;
out->start = true;
out->active = true;
out->idle = false;
#if defined(LOGIC_OUT_IT) || defined(GPIO_OUT_IT)
enInterrupts();
#endif
return ERROR_OK;
}
FctERR NONNULL__ Logic_out_SetStatic(Logic_out * const out, const eGPIOState action, const uint32_t delay) {
return Logic_out_Start(out, outStatic, action, delay, 0, 0, 0); }
FctERR NONNULL__ Logic_out_StartPulse(Logic_out * const out, const eGPIOState action, const uint32_t delay, const uint32_t active) {
return Logic_out_Start(out, outPulse, action, delay, active, 0, 0); }
FctERR NONNULL__ Logic_out_StartBlink( Logic_out * const out, const eGPIOState action,
const uint32_t delay, const uint32_t active, const uint32_t inactive, const uint32_t count) {
return Logic_out_Start(out, outBlink, action, delay, active, inactive, count); }
void NONNULL__ Logic_out_handler(Logic_out * const out)
{
if ((out->init) && (!out->idle))
{
#if defined(LOGIC_OUT_IT) || defined(GPIO_OUT_IT)
out->hOut++; // Increment timer count
if ( (!out->delay)
|| (out->delay && (out->hOut > out->delay)))
#else
if ( (!out->delay)
|| (out->delay && (TPSSUP_MS(out->hOut, out->delay))))
#endif
{
out->delay = 0;
switch (out->mode)
{
case outPulse:
{
if (out->start)
{
Logic_out_update(out);
out->start = false;
#if defined(LOGIC_OUT_IT) || defined(GPIO_OUT_IT)
out->hOut = 0;
#else
out->hOut = HALTicks();
#endif
}
#if defined(LOGIC_OUT_IT) || defined(GPIO_OUT_IT)
if (out->hOut > out->timeActive)
#else
if (TPSSUP_MS(out->hOut, out->timeActive))
#endif
{
Logic_out_Abort(out);
goto stop; // Go back to memorized state in current cycle
}
}
break;
case outBlink:
{
bool set = false;
if (out->start)
{
Logic_out_update(out);
out->action = Toggle; // Force toggle if action set was Reset or Set
out->start = false;
#if defined(LOGIC_OUT_IT) || defined(GPIO_OUT_IT)
out->hOut = 0;
#else
out->hOut = HALTicks();
#endif
}
#if defined(LOGIC_OUT_IT) || defined(GPIO_OUT_IT)
if ((out->active) && (out->hOut > out->timeActive))
#else
if ((out->active) && (TPSSUP_MS(out->hOut, out->timeActive)))
#endif
{
set = true;
}
#if defined(LOGIC_OUT_IT) || defined(GPIO_OUT_IT)
else if ((!out->active) && (out->hOut > out->timeInactive))
#else
else if ((!out->active) && (TPSSUP_MS(out->hOut, out->timeInactive)))
#endif
{
if (--out->cnt == 0)
{
Logic_out_Abort(out);
goto stop; // Go back to memorized state in current cycle
}
set = true;
}
if (set)
{
Logic_out_update(out);
out->active ^= true;
#if defined(LOGIC_OUT_IT) || defined(GPIO_OUT_IT)
out->hOut = 0;
#else
out->hOut = HALTicks();
#endif
}
}
break;
case outStatic:
{
stop: // label used only by Pulse and Blink cases when finished to revert to memorized state in current cycle
Logic_out_update(out);
out->memState = out->currentState;
out->idle = true;
}
break;
default:
break;
}
}
}
}