Motion Master
Loading...
Searching...
No Matches
circulo_encoder_configuration.h
Go to the documentation of this file.
1#pragma once
2
3#include <chrono>
4#include <cstdint>
5
6#include "util.h"
7
8class Cia402Drive;
10
12 public:
14 Cia402Drive &cia402_drive, uint8_t encoder_ordinal,
15 uint8_t battery_mode_max_acceleration,
16 uint32_t external_circulo_type,
17 const std::function<void()> &started_callback = {},
18 const std::function<void(uint8_t)> &progress_callback = {});
19
21
22 private:
23 Cia402Drive &cia402_drive_;
24 uint8_t encoder_ordinal_;
25 uint8_t battery_mode_max_acceleration_;
26 uint32_t external_circulo_type_;
27 EncoderLocation encoder_location_ = EncoderLocation::kUnspecified;
28 CirculoType circulo_type_ = CirculoType::kUnspecified;
29 uint8_t singleturn_bits_ = 0;
30
31 const std::function<void()> &started_callback_;
32 const std::function<void(uint8_t)> &progress_callback_;
33
34 double progress_ = 0;
35
36 // Prevent multiple encoder configurations from running on the same device
37 // at the same time
38 static inline std::unordered_map<int32_t, std::mutex> mutex_map_;
39
40 // Registers that have CALIBRATION written are not used by
41 // configuration. They will be written when calibrating the encoder.
42
43 // Singleturn
44 // Tuple: {Circulo type that uses the register value, address, value}
45 static inline const std::list<std::tuple<CirculoType, uint8_t, uint8_t>>
46 singleturn_address_value_list_ = {
47 // Register 0x00 = 0x00 (default=0x00)
48 {CirculoType::kUnspecified, 0x00, 0x00},
49
50 // Register 0x01 = CALIBRATION (default = 0x00)
51 // Register 0x02 = CALIBRATION (default = 0x00)
52 // Register 0x03 = CALIBRATION (default = 0x00)
53 // Register 0x04 = CALIBRATION (default = 0x00)
54 // Register 0x05 = 0x88 (default = 0x88)
55 {CirculoType::kUnspecified, 0x05, 0x88},
56
57 // Register 0x06 = 0x00 (default = 0x00)
58 {CirculoType::kUnspecified, 0x06, 0x00},
59
60 // Register 0x07 = CALIBRATION (default = 0x00)
61 // Register 0x08 = CALIBRATION (default = 0x00)
62 // Register 0x09 = CALIBRATION (default = 0x00)
63 // Register 0x0A = CALIBRATION (default = 0x00)
64 // Register 0x0B = 0x02 (default = 0x02)
65 {CirculoType::kCirculo7, 0x0B, 0x02},
66 {CirculoType::kCirculo7Smm, 0x0B, 0x52},
67 {CirculoType::kCirculo9, 0x0B, 0x02},
68 {CirculoType::kCirculo9Smm, 0x0B, 0x52},
69
70 // Register 0x0C = 0x6C (Mask AN_MAX error; default = 0x00)
71 {CirculoType::kUnspecified, 0x0C, 0x6C},
72
73 // Register 0x0D = 0xC0 (default = 0x00)
74 {CirculoType::kUnspecified, 0x0D, 0xC0},
75
76 // Register 0x0E = 0x04 (default=0x06)
77 {CirculoType::kUnspecified, 0x0E, 0x04},
78
79 // Register 0x0F = {Circulo 7: 0x05, Circulo 9: 0x06} (default=0x05)
80 {CirculoType::kCirculo7, 0x0F, 0x05},
81 {CirculoType::kCirculo7Smm, 0x0F, 0x05},
82 {CirculoType::kCirculo9, 0x0F, 0x06},
83 {CirculoType::kCirculo9Smm, 0x0F, 0x06},
84
85 // Register 0x10 = 0x00 (default=0x00)
86 {CirculoType::kUnspecified, 0x10, 0x00},
87
88 // Register 0x11 = {Circulo 7: 0x05, Circulo 9: 0x06} (default=0xA5)
89 {CirculoType::kCirculo7, 0x11, 0x05},
90 {CirculoType::kCirculo7Smm, 0x11, 0x05},
91 {CirculoType::kCirculo9, 0x11, 0x06},
92 {CirculoType::kCirculo9Smm, 0x11, 0x06},
93
94 // Register 0x12 = 0x00 (default=0x00)
95 {CirculoType::kUnspecified, 0x12, 0x00},
96
97 // Register 0x13/0x14 = 0xFF/0x0F (default=0xFF/0x0F)
98 {CirculoType::kUnspecified, 0x13, 0xFF},
99 {CirculoType::kUnspecified, 0x14, 0x0F},
100
101 // Register 0x15 = 0x13 (default=0x13)
102 {CirculoType::kUnspecified, 0x15, 0x13},
103
104 // Register 0x16 = 0x10 (default=0x10)
105 {CirculoType::kUnspecified, 0x16, 0x10},
106
107 // Register 0x17 = 0x02 (default=0x02)
108 {CirculoType::kUnspecified, 0x17, 0x02},
109
110 // Register 0x18 = 0x00 (default=0x00)
111 {CirculoType::kUnspecified, 0x18, 0x00},
112
113 // Write the iC-MU configuration to EEPROM
114 {CirculoType::kUnspecified, 0x75, 0x01}};
115
116 // Multiturn - Stage 1
117 // Tuple: {Circulo type that uses the register value, address, value}
118 static inline const std::list<std::tuple<CirculoType, uint8_t, uint8_t>>
119 multiturn_address_value_stage_1_list_ = {
122 // Register 0x00 = 0x00 (default=0x00)
123 {CirculoType::kUnspecified, 0x00, 0x00},
124
125 // Register 0x01 = CALIBRATION (default=0x00)
126 // Register 0x02 = CALIBRATION (default=0x00)
127 // Register 0x03 = CALIBRATION (default=0x00)
128 // Register 0x04 = CALIBRATION (default=0x00)
129 // Register 0x05 = 0x88 (default=0x88)
130 {CirculoType::kUnspecified, 0x05, 0x88},
131
132 // Register 0x06 = 0x00 (default=0x00)
133 {CirculoType::kUnspecified, 0x06, 0x00},
134
135 // Register 0x07 = CALIBRATION (default=0x00)
136 // Register 0x08 = CALIBRATION (default=0x00)
137 // Register 0x09 = CALIBRATION (default=0x00)
138 // Register 0x0A = CALIBRATION (default=0x00)
139 // Register 0x0B = 0x02 (default=0x02)
140 {CirculoType::kCirculo7, 0x0B, 0x02},
141 {CirculoType::kCirculo7Smm, 0x0B, 0x52},
142 {CirculoType::kCirculo9, 0x0B, 0x02},
143 {CirculoType::kCirculo9Smm, 0x0B, 0x52},
144
145 // Register 0x0C = 0x6C (Mask AN_MAX error; default=0x00)
146 {CirculoType::kUnspecified, 0x0C, 0x6C},
147
148 // Register 0x0D = 0xC0 (default=0x00)
149 {CirculoType::kUnspecified, 0x0D, 0xC0},
150
151 // Register 0x0E = 0x44 (default=0x06)
152 {CirculoType::kUnspecified, 0x0E, 0x44},
153
154 // Register 0x0F = {Circulo 7: 0x05, Circulo 9: 0x06} (default=0x05)
155 {CirculoType::kCirculo7, 0x0F, 0x05},
156 {CirculoType::kCirculo7Smm, 0x0F, 0x05},
157 {CirculoType::kCirculo9, 0x0F, 0x06},
158 {CirculoType::kCirculo9Smm, 0x0F, 0x06},
159
160 // Register 0x10 = 0x6F (default=0x00)
161 {CirculoType::kUnspecified, 0x10, 0x6F},
162
163 // Register 0x11 = {Circulo 7: 0x17, Circulo 9: 0x18} (default=0xA5)
164 {CirculoType::kCirculo7, 0x11, 0x17},
165 {CirculoType::kCirculo7Smm, 0x11, 0x17},
166 {CirculoType::kCirculo9, 0x11, 0x18},
167 {CirculoType::kCirculo9Smm, 0x11, 0x18},
168
169 // Register 0x12 = 0x00 (default=0x00)
170 {CirculoType::kUnspecified, 0x12, 0x00},
171
172 // Register 0x13/0x14 = 0xFF/0x0F (default=0xFF/0x0F)
173 {CirculoType::kUnspecified, 0x13, 0xFF},
174 {CirculoType::kUnspecified, 0x14, 0x0F},
175
176 // Register 0x15 = 0x13 (default=0x13)
177 {CirculoType::kUnspecified, 0x15, 0x13},
178
179 // Register 0x16 = 0x10 (default=0x10)
180 {CirculoType::kUnspecified, 0x16, 0x10},
181
182 // Register 0x17 = 0x02 (default=0x02)
183 {CirculoType::kUnspecified, 0x17, 0x02},
184
185 // Register 0x18 = 0x00 (default=0x00)
186 {CirculoType::kUnspecified, 0x18, 0x00},
187
190 // Configure I2C_DEVID (0x5E) to WRITE_EEPROM (0xA0). This tells the
191 // iC-MU that we want to use the I2C communication to write to the
192 // EEPROM.
193 {CirculoType::kUnspecified, 0x5E, 0xA0},
194
195 // Set the I2C_RAM_START (0x5C) to USER_EXCHANGE_REGISTERS_1 (0x60).
196 // This tells the iC-MU that the first value that he should write to
197 // the EEPROM is in the iC-MU RAM address 0x60. These
198 // USER_EXCHANGE_REGISTERS are used exclusively to store values that
199 // should be written to an external device via I2C (like the EEPROM
200 // or the iC-PVL).
201 {CirculoType::kUnspecified, 0x5C, 0x60},
202
203 // Set I2C_DEV_START (0x5B) to 0x40. This sets the first EEPROM
204 // address that should be written. Basically this means that the
205 // value written in the iC-MU RAM address 0x60 will be written to
206 // the EEPROM address 0x40. The reason why we start at EEPROM
207 // address 0x40 is that the EEPROM range 0x00-0x3F is used for the
208 // iC-MU configuration, and the iC-PVL configuration is stored in
209 // the range 0x40-0x4C, storing the value of the iC-PVL register
210 // 0x00 in EEPROM address 0x40, iC-PVL register 0x01 in EEPROM
211 // address 0x41, and so on.
212 {CirculoType::kUnspecified, 0x5B, 0x40},
213
214 // Set I2C_RAM_END (0x5D) to 0x6C. This tells the iC-MU when to stop
215 // writing the values in the USER_EXCHANGE_REGISTERS to the EEPROM.
216 // Since we want to write 13 values (EEPROM address 0x40 to address
217 // 0x4C), we need to use USER_EXCHANGE_REGISTERS_1 (0x60) to
218 // USER_EXCHANGE_REGISTERS_13 (0x6C).
219 {CirculoType::kUnspecified, 0x5D, 0x6C}};
220
221 // Multiturn - Stage 2 - CRC
222 // Tuple: {Circulo type that uses the register value, encoder position,
223 // address, value}
224 static inline const std::list<
225 std::tuple<CirculoType, EncoderLocation, uint8_t, uint8_t>>
226 multiturn_address_value_stage_2_list_ = {
227 // iC-PVL register 0x00 = 0x28 (default=0x00)
228 {CirculoType::kUnspecified, EncoderLocation::kUnspecified, 0x60,
229 0x28},
230
231 // iC-PVL register 0x01 = 0x09 (default=0x00)
232 {CirculoType::kUnspecified, EncoderLocation::kUnspecified, 0x61,
233 0x09},
234
235 // iC-PVL register 0x02 = {Circulo 7: 0x1F, Circulo 9: 0x3F}
236 // (default=0x00)
237 {CirculoType::kCirculo7, EncoderLocation::kUnspecified, 0x62, 0x1F},
238 {CirculoType::kCirculo7Smm, EncoderLocation::kUnspecified, 0x62,
239 0x1F},
240 {CirculoType::kCirculo9, EncoderLocation::kUnspecified, 0x62, 0x3F},
241 {CirculoType::kCirculo9Smm, EncoderLocation::kUnspecified, 0x62,
242 0x3F},
243
244 // iC-PVL register 0x03 = {Motor shaft: 0x5D, Driving shaft: 0x68}
245 // (default=0x00)
246 {CirculoType::kUnspecified, EncoderLocation::kMotorShaft, 0x63, 0x5D},
247 {CirculoType::kUnspecified, EncoderLocation::kDrivingShaft, 0x63,
248 0x68},
249
250 // iC-PVL register 0x04 = 0x50 (default=0x00)
251 {CirculoType::kUnspecified, EncoderLocation::kUnspecified, 0x64,
252 0x50},
253
254 // iC-PVL register 0x05 = 0x30 (default=0x00)
255 {CirculoType::kUnspecified, EncoderLocation::kUnspecified, 0x65, 0x30}
256
257 // iC-PVL register 0x06 - calculated CRC value of the previous
258 // registers: 0x00-0x05 (default=0x00)
259 };
260
261 // Multiturn - Stage 3
262 // Tuple: {address, value}
263 static inline const std::list<std::tuple<uint8_t, uint8_t>>
264 multiturn_address_value_stage_3_list_ = {
265 // iC-PVL registers 0x07-0x0B = 0x0000000000 (default=0x00)
266 {0x67, 0x00}, {0x68, 0x00}, {0x69, 0x00}, {0x6A, 0x00}, {0x6B, 0x00},
267
268 // iC-PVL register 0x0C - calculated CRC value of the previous
269 // registers: 0x07-0x0B (default=0x00)
270 };
271
272 // Multiturn - Stage 4 - Write REBOOT to iC-PVL. This will force iC-PVL to
273 // re-read the EEPROM and load those values in the RAM.
274 static inline const std::list<std::tuple<uint8_t, uint8_t>>
275 multiturn_address_value_stage_4_list_ = {
276 // Configure I2C_DEVID (0x5E) to WRITE_ICPVL (0xC2). This tells the
277 // iC-MU that we want to use the I2C communication to write to the
278 // iC-PVL.
279 {0x5E, 0xC2},
280
281 // Set the I2C_RAM_START (0x5C) to USER_EXCHANGE_REGISTERS_1 (0x60).
282 // This tells the iC-MU that the first value that he should write to
283 // the iC-PVL is in the iC-MU RAM address 0x60. These
284 // USER_EXCHANGE_REGISTERS are used exclusively to store values that
285 // should be written to an external device via I2C (like the EEPROM
286 // or the iC-PVL).
287 {0x5C, 0x60},
288
289 // Set I2C_DEV_START (0x5B) to 0x11. This sets the first iC-PVL
290 // register that should be written. Basically this means that the
291 // value written in the iC-MU RAM address 0x60 will be written to
292 // the iC-PVL register 0x11.
293 {0x5B, 0x11},
294
295 // Set I2C_RAM_END (0x5D) to 0x60. This tells the iC-MU when to stop
296 // writing the values in the USER_EXCHANGE_REGISTERS to the iC-PVL.
297 // Since we want to only write one value (iC-PVL address 0x11), we
298 // need to use only USER_EXCHANGE_REGISTERS_1 (0x60), so both
299 // I2C_RAM_END and I2C_RAM_START are set to that value.
300 {0x5D, 0x60},
301
302 // Now we can write each of the values we want to write to the
303 // iC-PVL in the USER_EXCHANGE_REGISTERS. iC-PVL register 0x11 =
304 // 0x03 (default=0x00). This will write REBOOT to the iC-PVL CMD
305 // register.
306 {0x60, 0x03},
307
308 // Set CMD_MU (0x75) to I2C_COM (0x0A). This will start the I2C
309 // communication with all the parameters that were configured above,
310 // effectively writing the REBOOT command to the iC-PVL.
311 {0x75, 0x0A}};
312
313 // Multiturn - Stage 5 - Reset iC-PVL errors (SCLR) and re-calculate
314 // absolute position (ABS_RESET)
315 static inline const std::list<std::tuple<uint8_t, uint8_t>>
316 multiturn_address_value_stage_5_list_ = {
317 // Configure I2C_DEVID (0x5E) to WRITE_ICPVL (0xC2). This tells the
318 // iC-MU that we want to use the I2C communication to write to the
319 // iC-PVL.
320 {0x5E, 0xC2},
321
322 // Set the I2C_RAM_START (0x5C) to USER_EXCHANGE_REGISTERS_1 (0x60).
323 // This tells the iC-MU that the first value that he should write to
324 // the iC-PVL is in the iC-MU RAM address 0x60. These
325 // USER_EXCHANGE_REGISTERS are used exclusively to store values that
326 // should be written to an external device via I2C (like the EEPROM
327 // or the iC-PVL).
328 {0x5C, 0x60},
329
330 // Set I2C_DEV_START (0x5B) to 0x11. This sets the first iC-PVL
331 // register that should be written. Basically this means that the
332 // value written in the iC-MU RAM address 0x60 will be written to
333 // the iC-PVL register 0x11.
334 {0x5B, 0x11},
335
336 // Set I2C_RAM_END (0x5D) to 0x60. This tells the iC-MU when to stop
337 // writing the values in the USER_EXCHANGE_REGISTERS to the iC-PVL.
338 // Since we want to only write one value (iC-PVL address 0x11), we
339 // need to use only USER_EXCHANGE_REGISTERS_1 (0x60), so both
340 // I2C_RAM_END and I2C_RAM_START are set to that value.
341 {0x5D, 0x60},
342
343 // Now we can write each of the values we want to write to the
344 // iC-PVL in the USER_EXCHANGE_REGISTERS.
345
346 // iC-PVL register 0x11 = 0x05 (default=0x00). This will write SCLR
347 // to the iC-PVL CMD register.
348 {0x60, 0x05},
349
350 // Set CMD_MU (0x75) to I2C_COM (0x0A). This will start the I2C
351 // communication with all the parameters
352 // that were configured above, effectively writing the SCLR command
353 // to the iC-PVL.
354 {0x75, 0x0A},
355
356 // Send ABS_RESET command to iC-MU
357 {0x75, 0x03}};
358
359 // Stage 6
360 static inline const std::list<std::tuple<uint8_t, uint8_t>>
361 multiturn_address_value_stage_6_list_ = {
362 // Change value of I2C_POS to 1 to be able to read the sync bits
363 // iC-PVL register 0x05 = 0xB0 (value before = 0x30)
364 // Configure I2C_DEVID (0x5E) to WRITE_ICPVL (0xC2). This tells the
365 // iC-MU that we want to use the I2C communication to write to the
366 // iC-PVL.
367 {0x5E, 0xC2},
368
369 // Set the I2C_RAM_START (0x5C) to USER_EXCHANGE_REGISTERS_1 (0x60).
370 // This tells the iC-MU that the first value that he should write to
371 // the iC-PVL is in the iC-MU RAM address 0x60. These
372 // USER_EXCHANGE_REGISTERS are used exclusively to store values that
373 // should be written to an external device via I2C (like the EEPROM
374 // or the iC-PVL).
375 {0x5C, 0x60},
376
377 // Set I2C_DEV_START (0x5B) to 0x05. This sets the first iC-PVL
378 // register that should be written. Basically this means that the
379 // value written in the iC-MU RAM address 0x60 will be written to
380 // the iC-PVL register 0x05.
381 {0x5B, 0x05},
382
383 // Set I2C_RAM_END (0x5D) to 0x60. This tells the iC-MU when to stop
384 // writing the values in the USER_EXCHANGE_REGISTERS to the iC-PVL.
385 // Since we want to only write one value (iC-PVL address 0x05), we
386 // need to use only USER_EXCHANGE_REGISTERS_1 (0x60), so both
387 // I2C_RAM_END and I2C_RAM_START are set to that value.
388 {0x5D, 0x60},
389
390 // Now we can write each of the values we want to write to the
391 // iC-PVL in the USER_EXCHANGE_REGISTERS.
392
393 // iC-PVL register 0x05 = 0xB0 (default=0x00). This will write 0xB0
394 // to the iC-PVL 0x05 register.
395 {0x60, 0xB0},
396
397 // Set CMD_MU (0x75) to I2C_COM (0x0A). This will start the I2C
398 // communication with all the parameters that were configured above,
399 // effectively writing the SCLR command to the iC-PVL.
400 {0x75, 0x0A},
401
402 // Read iC-PVL sync bits (iC-PVL address 0x0D, bit 2:0)
403
404 // Configure I2C_DEVID (0x5E) to READ_ICPVL (0xC3). This tells the
405 // iC-MU that we want to use the I2C communication to read the
406 // iC-PVL.
407 {0x5E, 0xC3},
408
409 // Set the I2C_RAM_START (0x5C) to USER_EXCHANGE_REGISTERS_1 (0x60).
410 // This tells the iC-MU that the first value that he should write to
411 // the iC-PVL is in the iC-MU RAM address 0x60. These
412 // USER_EXCHANGE_REGISTERS are used exclusively to store values that
413 // should be written to an external device via I2C (like the EEPROM
414 // or the iC-PVL).
415 {0x5C, 0x60},
416
417 // Set I2C_DEV_START (0x5B) to 0x0D. This sets the first iC-PVL
418 // register that should be read. Basically this means that the value
419 // read in the iC-PVL register 0x0D will be written in the iC-MU RAM
420 // address 0x60.
421 {0x5B, 0x0D},
422
423 // Set I2C_RAM_END (0x5D) to 0x60. This tells the iC-MU when to stop
424 // reading the values and writing them to the
425 // USER_EXCHANGE_REGISTERS to the iC-PVL. Since we want to only read
426 // one value (iC-PVL address 0x0D), we need to use only
427 // USER_EXCHANGE_REGISTERS_1 (0x60), so both I2C_RAM_END and
428 // I2C_RAM_START are set to that value.
429 {0x5D, 0x60},
430
431 // Set CMD_MU (0x75) to I2C_COM (0x0A). This will start the I2C
432 // communication with all the parameters that were configured above,
433 // effectively reading the iC-PVL register 0x0D to the iC-MU
434 // register 0x60.
435 {0x75, 0x0A}};
436
437 // Stage 7
438 static inline const std::list<std::tuple<uint8_t, uint8_t>>
439 multiturn_address_value_stage_7_list_ = {
440 // Change value of I2C_POS back to 0
441
442 // iC-PVL register 0x05 = 0x30
443 // Configure I2C_DEVID (0x5E) to WRITE_ICPVL (0xC2). This tells the
444 // iC-MU that we want to use the I2C communication to write to the
445 // iC-PVL.
446 {0x5E, 0xC2},
447
448 // Set the I2C_RAM_START (0x5C) to USER_EXCHANGE_REGISTERS_1 (0x60).
449 // This tells the iC-MU that the first value that he should write to
450 // the iC-PVL is in the iC-MU RAM address 0x60. These
451 // USER_EXCHANGE_REGISTERS are used exclusively to store values that
452 // should be written to an external device via I2C (like the EEPROM
453 // or the iC-PVL).
454 {0x5C, 0x60},
455
456 // Set I2C_DEV_START (0x5B) to 0x05. This sets the first iC-PVL
457 // register that should be written. Basically this means that the
458 // value written in the iC-MU RAM address 0x60 will be written to
459 // the iC-PVL register 0x05.
460 {0x5B, 0x05},
461
462 // Set I2C_RAM_END (0x5D) to 0x60. This tells the iC-MU when to stop
463 // writing the values in the USER_EXCHANGE_REGISTERS to the iC-PVL.
464 // Since we want to only write one value (iC-PVL address 0x05), we
465 // need to use only USER_EXCHANGE_REGISTERS_1 (0x60), so both
466 // I2C_RAM_END and I2C_RAM_START are set to that value.
467 {0x5D, 0x60},
468
469 // Now we can write each of the values we want to write to the
470 // iC-PVL in the USER_EXCHANGE_REGISTERS.
471
472 // iC-PVL register 0x05 = 0x30 (default=0x00). This will write 0x30
473 // to the iC-PVL 0x05 register.
474 {0x60, 0x30},
475
476 // Set CMD_MU (0x75) to I2C_COM (0x0A). This will start the I2C
477 // communication with all the parameters that were configured above,
478 // effectively writing the SCLR command to the iC-PVL.
479 {0x75, 0x0A}};
480
481 MotionMasterError configure_singleturn();
482
483 MotionMasterError configure_multiturn();
484
485 void add_action_to_progress(uint32_t total_actions,
486 uint32_t actions_to_add = 1);
487
488 void sleep_with_progress(uint32_t milliseconds, uint32_t total_actions);
489
490 MotionMasterError ignore_biss_status_bits(bool ignore);
491
492 MotionMasterError write_register(uint8_t address, uint8_t value);
493
494 static uint8_t crc(const std::vector<uint8_t> &data);
495};
Definition: cia402_drive.h:48
Definition: circulo_encoder_configuration.h:11
MotionMasterError start()
Definition: circulo_encoder_configuration.cc:29
Definition: motion_master_error.h:6
uint8_t * value
Definition: co_dictionary.h:9
CirculoType
Definition: util.h:48
EncoderLocation
Definition: util.h:64