-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdrive_phase_state.c
More file actions
252 lines (214 loc) · 8.1 KB
/
drive_phase_state.c
File metadata and controls
252 lines (214 loc) · 8.1 KB
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
247
248
249
250
251
252
#include "drive_phase_state.h"
#include "drive_phase_sync.h"
#include "defs/defs.h"
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
typedef enum _Phase_State {
PHASE_STATE_UNK = 0,
PHASE_STATE_A = 1,
PHASE_STATE_B = 2,
PHASE_STATE_C = 3,
PHASE_STATE_A_FWD = 4,
PHASE_STATE_B_FWD = 5,
PHASE_STATE_C_FWD = 6,
PHASE_STATE_A_BWD = 7,
PHASE_STATE_B_BWD = 8,
PHASE_STATE_C_BWD = 9,
PHASE_STATE_ERROR = 10
} phase_state_t;
typedef struct _Phase_State_Values {
phase_state_t state;
drive_dir_t dir;
drive_phase_error_t error;
} phase_state_values_t;
#define PHASE_STATES_COUNT 11
#define PHASE_VALUES_COUNT 4 /* UNK + A + B + C */
static const phase_state_values_t
phase_states [PHASE_STATES_COUNT][PHASE_VALUES_COUNT] = {
{ // PHASE_STATE_UNK
{ PHASE_STATE_UNK, DRIVE_DIR_UNK, PHASE_NO_ERROR }, // PHASE_UNK
{ PHASE_STATE_A, DRIVE_DIR_UNK, PHASE_NO_ERROR }, // PHASE_A
{ PHASE_STATE_B, DRIVE_DIR_UNK, PHASE_NO_ERROR }, // PHASE_B
{ PHASE_STATE_C, DRIVE_DIR_UNK, PHASE_NO_ERROR }, // PHASE_C
},
{ // PHASE_STATE_A
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_UNK_ERROR }, // PHASE_UNK
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_BC_ERROR }, // PHASE_A
{ PHASE_STATE_B_FWD, DRIVE_DIR_FORW, PHASE_NO_ERROR }, // PHASE_B
{ PHASE_STATE_C_BWD, DRIVE_DIR_BACKW, PHASE_NO_ERROR }, // PHASE_C
},
{ // PHASE_STATE_B
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_UNK_ERROR }, // PHASE_UNK
{ PHASE_STATE_A_BWD, DRIVE_DIR_BACKW, PHASE_NO_ERROR }, // PHASE_A
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_AC_ERROR }, // PHASE_B
{ PHASE_STATE_C_FWD, DRIVE_DIR_FORW, PHASE_NO_ERROR }, // PHASE_C
},
{ // PHASE_STATE_C
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_UNK_ERROR }, // PHASE_UNK
{ PHASE_STATE_A_FWD, DRIVE_DIR_FORW, PHASE_NO_ERROR }, // PHASE_A
{ PHASE_STATE_B_BWD, DRIVE_DIR_BACKW, PHASE_NO_ERROR }, // PHASE_B
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_AB_ERROR }, // PHASE_C
},
{ // PHASE_STATE_A_FWD
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_UNK_ERROR }, // PHASE_UNK
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_BC_ERROR }, // PHASE_A
{ PHASE_STATE_B_FWD, DRIVE_DIR_FORW, PHASE_NO_ERROR }, // PHASE_B
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_B_ERROR }, // PHASE_C
},
{ // PHASE_STATE_B_FWD
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_UNK_ERROR }, // PHASE_UNK
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_C_ERROR }, // PHASE_A
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_AC_ERROR }, // PHASE_B
{ PHASE_STATE_C_FWD, DRIVE_DIR_FORW, PHASE_NO_ERROR }, // PHASE_C
},
{ // PHASE_STATE_C_FWD
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_UNK_ERROR }, // PHASE_UNK
{ PHASE_STATE_A_FWD, DRIVE_DIR_FORW, PHASE_NO_ERROR }, // PHASE_A
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_A_ERROR }, // PHASE_B
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_AB_ERROR }, // PHASE_C
},
{ // PHASE_STATE_A_BWD
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_UNK_ERROR }, // PHASE_UNK
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_BC_ERROR }, // PHASE_A
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_C_ERROR }, // PHASE_B
{ PHASE_STATE_C_BWD, DRIVE_DIR_BACKW, PHASE_NO_ERROR }, // PHASE_C
},
{ // PHASE_STATE_B_BWD
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_UNK_ERROR }, // PHASE_UNK
{ PHASE_STATE_A_BWD, DRIVE_DIR_BACKW, PHASE_NO_ERROR }, // PHASE_A
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_AC_ERROR }, // PHASE_B
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_A_ERROR }, // PHASE_C
},
{ // PHASE_STATE_C_BWD
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_UNK_ERROR }, // PHASE_UNK
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_B_ERROR }, // PHASE_A
{ PHASE_STATE_B_BWD, DRIVE_DIR_BACKW, PHASE_NO_ERROR }, // PHASE_B
{ PHASE_STATE_ERROR, DRIVE_DIR_UNK, PHASE_AB_ERROR }, // PHASE_C
},
{ // PHASE_STATE_ERROR
{ PHASE_STATE_UNK, DRIVE_DIR_UNK, PHASE_NO_ERROR }, // PHASE_UNK
{ PHASE_STATE_A, DRIVE_DIR_UNK, PHASE_NO_ERROR }, // PHASE_A
{ PHASE_STATE_B, DRIVE_DIR_UNK, PHASE_NO_ERROR }, // PHASE_B
{ PHASE_STATE_C, DRIVE_DIR_UNK, PHASE_NO_ERROR }, // PHASE_C
}/*,
{ // PHASE_STATE_
{ PHASE_STATE_, DRIVE_DIR_, PHASE__ERROR }, // PHASE_UNK
{ PHASE_STATE_, DRIVE_DIR_, PHASE__ERROR }, // PHASE_A
{ PHASE_STATE_, DRIVE_DIR_, PHASE__ERROR }, // PHASE_B
{ PHASE_STATE_, DRIVE_DIR_, PHASE__ERROR }, // PHASE_C
},*/
};
//! Тип состояния фазы.
typedef struct _DrivePhaseState {
phase_state_t state; //!< Состояние фаз.
phase_t cur_phase; //!< Текущая фаза.
phase_t last_phase; //!< Предыдущая фаза.
phase_t half_phase; //!< Полуфаза.
bool zero_reached; //!< Флаг прохождения нуля.
drive_dir_t drive_dir; //!< Направление.
drive_phase_errors_t phase_errs; //!< Ошибки.
drive_phase_state_error_callback_t error_callback; //!< Каллбэк ошибки фаз.
} drive_phase_state_t;
static drive_phase_state_t state;
ALWAYS_INLINE static void drive_phase_state_on_error(void)
{
if(state.error_callback) state.error_callback();
}
err_t drive_phase_state_init(void)
{
memset(&state, 0x0, sizeof(drive_phase_state_t));
return E_NO_ERROR;
}
void drive_phase_state_set_error_callback(drive_phase_state_error_callback_t callback)
{
state.error_callback = callback;
}
void drive_phase_state_handle(phase_t phase)
{
const phase_state_values_t* state_values =
&phase_states[state.state][phase];
state.state = state_values->state;
state.drive_dir = state_values->dir;
state.phase_errs = state_values->error;
state.last_phase = state.cur_phase;
state.cur_phase = phase;
state.zero_reached = true;
if(state.phase_errs != PHASE_NO_ERROR) drive_phase_state_on_error();
}
bool drive_phase_state_zero_reached(void)
{
return state.zero_reached;
}
void drive_phase_state_half_handle(void)
{
if(state.zero_reached) state.half_phase = state.last_phase;
else state.half_phase = state.cur_phase;
state.zero_reached = false;
}
phase_t drive_phase_state_half_phase(void)
{
return state.half_phase;
}
drive_phase_errors_t drive_phase_state_errors(void)
{
return state.phase_errs;
}
phase_t drive_phase_state_current_phase(void)
{
return state.cur_phase;
}
phase_t drive_phase_state_last_phase(void)
{
return state.last_phase;
}
drive_dir_t drive_phase_state_direction(void)
{
return state.drive_dir;
}
#define NEXT_PHASE_TABLE
phase_t drive_phase_state_next_phase(phase_t phase, drive_dir_t dir)
{
if(phase == PHASE_UNK) return PHASE_UNK;
if(dir == DRIVE_DIR_UNK) return PHASE_UNK;
#ifdef NEXT_PHASE_TABLE
#define PHASES_TABLE_SIZE_DIRS 2
#define PHASES_TABLE_SIZE_PHASES 3
static const phase_t next_phase_table[PHASES_TABLE_SIZE_DIRS][PHASES_TABLE_SIZE_PHASES] = {
{PHASE_B, PHASE_C, PHASE_A},
{PHASE_C, PHASE_A, PHASE_B}
};
return next_phase_table[dir - 1][phase - 1];
#undef PHASES_TABLE_SIZE_PHASES
#undef PHASES_TABLE_SIZE_DIRS
#else
// Обработаем фазу.
switch(phase){
case PHASE_A:
return (dir == DRIVE_DIR_FORW) ? PHASE_B : PHASE_C;
break;
case PHASE_B:
return (dir == DRIVE_DIR_FORW) ? PHASE_C : PHASE_A;
break;
case PHASE_C:
return (dir == DRIVE_DIR_FORW) ? PHASE_A : PHASE_B;
break;
default:
break;
}
return PHASE_UNK;
#endif
}
void drive_phase_state_clear_errors(void)
{
state.phase_errs = PHASE_NO_ERROR;
}
void drive_phase_state_reset(void)
{
state.last_phase = PHASE_UNK;
state.cur_phase = PHASE_UNK;
state.drive_dir = DRIVE_DIR_UNK;
state.phase_errs = PHASE_NO_ERROR;
state.state = PHASE_STATE_UNK;
state.zero_reached = false;
}