Statistics
| Branch: | Tag: | Revision:

amiro-os / kernel / patches / QEI-driver.patch @ 20a4e01c

History | View | Annotate | Download (28 KB)

1
commit a23878ddb85bb8fd069f02042f15ad4be2a0d709
2
Author: Marc Rothmann <mrothmann@techfak.uni-bielefeld.de>
3
Date:   Mon Sep 17 11:40:39 2018 +0200
4

    
5
    Added QEI driver to HAL.
6

    
7
diff --git a/os/hal/hal.mk b/os/hal/hal.mk
8
index f177a3f..64d96d9 100644
9
--- a/os/hal/hal.mk
10
+++ b/os/hal/hal.mk
11
@@ -41,6 +41,9 @@ endif
12
 ifneq ($(findstring HAL_USE_ICU TRUE,$(HALCONF)),)
13
 HALSRC += $(CHIBIOS)/os/hal/src/hal_icu.c
14
 endif
15
+ifneq ($(findstring HAL_USE_QEI TRUE,$(HALCONF)),)
16
+HALSRC += $(CHIBIOS)/os/hal/src/hal_qei.c
17
+endif
18
 ifneq ($(findstring HAL_USE_MAC TRUE,$(HALCONF)),)
19
 HALSRC += $(CHIBIOS)/os/hal/src/hal_mac.c
20
 endif
21
@@ -94,6 +97,7 @@ HALSRC = $(CHIBIOS)/os/hal/src/hal.c \
22
          $(CHIBIOS)/os/hal/src/hal_i2c.c \
23
          $(CHIBIOS)/os/hal/src/hal_i2s.c \
24
          $(CHIBIOS)/os/hal/src/hal_icu.c \
25
+         $(CHIBIOS)/os/hal/src/hal_qei.c \
26
          $(CHIBIOS)/os/hal/src/hal_mac.c \
27
          $(CHIBIOS)/os/hal/src/hal_mmc_spi.c \
28
          $(CHIBIOS)/os/hal/src/hal_pal.c \
29
diff --git a/os/hal/include/hal_qei.h b/os/hal/include/hal_qei.h
30
new file mode 100644
31
index 0000000..aef5e62
32
--- /dev/null
33
+++ b/os/hal/include/hal_qei.h
34
@@ -0,0 +1,148 @@
35
+/*
36
+AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
37
+Copyright (C) 2016..2018  Thomas Schöpping et al.
38
+
39
+This program is free software: you can redistribute it and/or modify
40
+it under the terms of the GNU General Public License as published by
41
+the Free Software Foundation, either version 3 of the License, or
42
+(at your option) any later version.
43
+
44
+This program is distributed in the hope that it will be useful,
45
+but WITHOUT ANY WARRANTY; without even the implied warranty of
46
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
47
+GNU General Public License for more details.
48
+
49
+You should have received a copy of the GNU General Public License
50
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
51
+*/
52
+
53
+/**
54
+ * @file    hal_qei.h
55
+ * @brief   QEI Driver macros and structures.
56
+ *
57
+ * @addtogroup QEI
58
+ * @{
59
+ */
60
+
61
+#ifndef _HAL_QEI_H_
62
+#define _HAL_QEI_H_
63
+
64
+#if HAL_USE_QEI || defined(__DOXYGEN__)
65
+
66
+/*===========================================================================*/
67
+/* Driver constants.                                                         */
68
+/*===========================================================================*/
69
+
70
+/*===========================================================================*/
71
+/* Driver pre-compile time settings.                                         */
72
+/*===========================================================================*/
73
+
74
+/*===========================================================================*/
75
+/* Derived constants and error checks.                                       */
76
+/*===========================================================================*/
77
+
78
+/*===========================================================================*/
79
+/* Driver data structures and types.                                         */
80
+/*===========================================================================*/
81
+
82
+/**
83
+ * @brief   Driver state machine possible states.
84
+ */
85
+typedef enum {
86
+  QEI_UNINIT = 0,                   /**< Not initialized.                   */
87
+  QEI_STOP = 1,                     /**< Stopped.                           */
88
+  QEI_READY = 2,                    /**< Ready.                             */
89
+  QEI_ACTIVE = 4,                   /**< Active.                            */
90
+} qeistate_t;
91
+
92
+/**
93
+ * @brief   Type of a structure representing an QEI driver.
94
+ */
95
+typedef struct QEIDriver QEIDriver;
96
+
97
+#include "hal_qei_lld.h"
98
+
99
+/*===========================================================================*/
100
+/* Driver macros.                                                            */
101
+/*===========================================================================*/
102
+
103
+/**
104
+ * @name    Macro Functions
105
+ * @{
106
+ */
107
+/**
108
+ * @brief   Enables the quadrature encoder.
109
+ *
110
+ * @param[in] qeip      pointer to the @p QEIDriver object
111
+ *
112
+ * @iclass
113
+ */
114
+#define qeiEnableI(qeip) qei_lld_enable(qeip)
115
+
116
+/**
117
+ * @brief   Disables the quadrature encoder.
118
+ *
119
+ * @param[in] qeip      pointer to the @p QEIDriver object
120
+ *
121
+ * @iclass
122
+ */
123
+#define qeiDisableI(qeip) qei_lld_disable(qeip)
124
+
125
+/**
126
+ * @brief   Returns the direction of the last transition.
127
+ * @details The direction is defined as boolean and is
128
+ *          calculated at each transition on any input.
129
+ *
130
+ * @param[in] qeip      pointer to the @p QEIDriver object
131
+ * @return              The request direction.
132
+ * @retval FALSE        Position counted up.
133
+ * @retval TRUE         Position counted down.
134
+ * @iclass
135
+ */
136
+#define qeiGetDirectionI(qeip) qei_lld_get_direction(qeip)
137
+
138
+/**
139
+ * @brief   Returns the position of the encoder.
140
+ * @details The position is defined as number of pulses since last reset.
141
+ *
142
+ * @param[in] qeip      pointer to the @p QEIDriver object
143
+ * @return              The number of pulses.
144
+ *
145
+ * @iclass
146
+ */
147
+#define qeiGetPositionI(qeip) qei_lld_get_position(qeip)
148
+
149
+/**
150
+ * @brief   Returns the range of the encoder.
151
+ * @details The range is defined as number of maximum pulse count.
152
+ *
153
+ * @param[in] qeip      pointer to the @p QEIDriver object
154
+ * @return              The number of pulses.
155
+ *
156
+ * @iclass
157
+ */
158
+#define qeiGetRangeI(qeip) qei_lld_get_range(qeip)
159
+/** @} */
160
+
161
+/*===========================================================================*/
162
+/* External declarations.                                                    */
163
+/*===========================================================================*/
164
+
165
+#ifdef __cplusplus
166
+extern "C" {
167
+#endif
168
+  void qeiInit(void);
169
+  void qeiObjectInit(QEIDriver *qeip);
170
+  void qeiStart(QEIDriver *qeip, const QEIConfig *config);
171
+  void qeiStop(QEIDriver *qeip);
172
+  void qeiEnable(QEIDriver *qeip);
173
+  void qeiDisable(QEIDriver *qeip);
174
+#ifdef __cplusplus
175
+}
176
+#endif
177
+
178
+#endif /* HAL_USE_QEI */
179
+
180
+#endif /* _HAL_QEI_H_ */
181
+
182
+/** @} */
183
diff --git a/os/hal/ports/STM32/LLD/TIMv1/driver.mk b/os/hal/ports/STM32/LLD/TIMv1/driver.mk
184
index 032d75a..13e3571 100644
185
--- a/os/hal/ports/STM32/LLD/TIMv1/driver.mk
186
+++ b/os/hal/ports/STM32/LLD/TIMv1/driver.mk
187
@@ -10,10 +10,14 @@ endif
188
 ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),)
189
 PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c
190
 endif
191
+ifneq ($(findstring HAL_USE_QEI TRUE,$(HALCONF)),)
192
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c
193
+endif
194
 else
195
 PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c
196
 PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c
197
 PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c
198
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c
199
 endif
200
 
201
 PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1
202
diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c
203
new file mode 100644
204
index 0000000..700704a
205
--- /dev/null
206
+++ b/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c
207
@@ -0,0 +1,302 @@
208
+/*
209
+AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
210
+Copyright (C) 2016..2018  Thomas Schöpping et al.
211
+
212
+This program is free software: you can redistribute it and/or modify
213
+it under the terms of the GNU General Public License as published by
214
+the Free Software Foundation, either version 3 of the License, or
215
+(at your option) any later version.
216
+
217
+This program is distributed in the hope that it will be useful,
218
+but WITHOUT ANY WARRANTY; without even the implied warranty of
219
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
220
+GNU General Public License for more details.
221
+
222
+You should have received a copy of the GNU General Public License
223
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
224
+*/
225
+
226
+/**
227
+ * @file    STM32/hal_qei_lld.c
228
+ * @brief   STM32 QEI subsystem low level driver.
229
+ *
230
+ * @addtogroup QEI
231
+ * @{
232
+ */
233
+
234
+#include "hal.h"
235
+
236
+#include "hal_qei.h"
237
+
238
+#if HAL_USE_QEI || defined(__DOXYGEN__)
239
+
240
+/*===========================================================================*/
241
+/* Driver exported variables.                                                */
242
+/*===========================================================================*/
243
+
244
+/**
245
+ * @brief   QEID1 driver identifier.
246
+ * @note    The driver QEID1 allocates the complex timer TIM1 when enabled.
247
+ */
248
+#if STM32_QEI_USE_TIM1 || defined(__DOXYGEN__)
249
+QEIDriver QEID1;
250
+#endif
251
+
252
+/**
253
+ * @brief   QEID2 driver identifier.
254
+ * @note    The driver QEID1 allocates the timer TIM2 when enabled.
255
+ */
256
+#if STM32_QEI_USE_TIM2 || defined(__DOXYGEN__)
257
+QEIDriver QEID2;
258
+#endif
259
+
260
+/**
261
+ * @brief   QEID3 driver identifier.
262
+ * @note    The driver QEID1 allocates the timer TIM3 when enabled.
263
+ */
264
+#if STM32_QEI_USE_TIM3 || defined(__DOXYGEN__)
265
+QEIDriver QEID3;
266
+#endif
267
+
268
+/**
269
+ * @brief   QEID4 driver identifier.
270
+ * @note    The driver QEID4 allocates the timer TIM4 when enabled.
271
+ */
272
+#if STM32_QEI_USE_TIM4 || defined(__DOXYGEN__)
273
+QEIDriver QEID4;
274
+#endif
275
+
276
+/**
277
+ * @brief   QEID5 driver identifier.
278
+ * @note    The driver QEID5 allocates the timer TIM5 when enabled.
279
+ */
280
+#if STM32_QEI_USE_TIM5 || defined(__DOXYGEN__)
281
+QEIDriver QEID5;
282
+#endif
283
+
284
+/**
285
+ * @brief   QEID8 driver identifier.
286
+ * @note    The driver QEID8 allocates the timer TIM8 when enabled.
287
+ */
288
+#if STM32_QEI_USE_TIM8 || defined(__DOXYGEN__)
289
+QEIDriver QEID8;
290
+#endif
291
+
292
+/*===========================================================================*/
293
+/* Driver local variables.                                                   */
294
+/*===========================================================================*/
295
+
296
+/*===========================================================================*/
297
+/* Driver local functions.                                                   */
298
+/*===========================================================================*/
299
+
300
+/*===========================================================================*/
301
+/* Driver interrupt handlers.                                                */
302
+/*===========================================================================*/
303
+
304
+/*===========================================================================*/
305
+/* Driver exported functions.                                                */
306
+/*===========================================================================*/
307
+
308
+/**
309
+ * @brief   Low level QEI driver initialization.
310
+ *
311
+ * @notapi
312
+ */
313
+void qei_lld_init(void) {
314
+
315
+#if STM32_QEI_USE_TIM1
316
+  /* Driver initialization.*/
317
+  qeiObjectInit(&QEID1);
318
+  QEID1.tim = STM32_TIM1;
319
+#endif
320
+
321
+#if STM32_QEI_USE_TIM2
322
+  /* Driver initialization.*/
323
+  qeiObjectInit(&QEID2);
324
+  QEID2.tim = STM32_TIM2;
325
+#endif
326
+
327
+#if STM32_QEI_USE_TIM3
328
+  /* Driver initialization.*/
329
+  qeiObjectInit(&QEID3);
330
+  QEID3.tim = STM32_TIM3;
331
+#endif
332
+
333
+#if STM32_QEI_USE_TIM4
334
+  /* Driver initialization.*/
335
+  qeiObjectInit(&QEID4);
336
+  QEID4.tim = STM32_TIM4;
337
+#endif
338
+
339
+#if STM32_QEI_USE_TIM5
340
+  /* Driver initialization.*/
341
+  qeiObjectInit(&QEID5);
342
+  QEID5.tim = STM32_TIM5;
343
+#endif
344
+
345
+#if STM32_QEI_USE_TIM8
346
+  /* Driver initialization.*/
347
+  qeiObjectInit(&QEID8);
348
+  QEID8.tim = STM32_TIM8;
349
+#endif
350
+}
351
+
352
+/**
353
+ * @brief   Configures and activates the QEI peripheral.
354
+ *
355
+ * @param[in] qeip      pointer to the @p QEIDriver object
356
+ *
357
+ * @notapi
358
+ */
359
+void qei_lld_start(QEIDriver *qeip) {
360
+  uint32_t arr, ccer;
361
+
362
+  if (qeip->state == QEI_STOP) {
363
+    /* Clock activation and timer reset.*/
364
+#if STM32_QEI_USE_TIM1
365
+    if (&QEID1 == qeip) {
366
+      rccEnableTIM1();
367
+      rccResetTIM1();
368
+    }
369
+#endif
370
+#if STM32_QEI_USE_TIM2
371
+    if (&QEID2 == qeip) {
372
+      rccEnableTIM2();
373
+      rccResetTIM2();
374
+    }
375
+#endif
376
+#if STM32_QEI_USE_TIM3
377
+    if (&QEID3 == qeip) {
378
+      rccEnableTIM3();
379
+      rccResetTIM3();
380
+    }
381
+#endif
382
+#if STM32_QEI_USE_TIM4
383
+    if (&QEID4 == qeip) {
384
+      rccEnableTIM4();
385
+      rccResetTIM4();
386
+    }
387
+#endif
388
+
389
+#if STM32_QEI_USE_TIM5
390
+    if (&QEID5 == qeip) {
391
+      rccEnableTIM5();
392
+      rccResetTIM5();
393
+    }
394
+#endif
395
+#if STM32_QEI_USE_TIM8
396
+    if (&QEID8 == qeip) {
397
+      rccEnableTIM8();
398
+      rccResetTIM8();
399
+    }
400
+#endif
401
+  }
402
+  else {
403
+    /* Driver re-configuration scenario, it must be stopped first.*/
404
+    qeip->tim->CR1    = 0;                  /* Timer disabled.              */
405
+    qeip->tim->DIER   = 0;                  /* All IRQs disabled.           */
406
+    qeip->tim->SR     = 0;                  /* Clear eventual pending IRQs. */
407
+    qeip->tim->CCR[0] = 0;                  /* Comparator 1 disabled.       */
408
+    qeip->tim->CCR[1] = 0;                  /* Comparator 2 disabled.       */
409
+    qeip->tim->CNT    = 0;                  /* Counter reset to zero.       */
410
+  }
411
+
412
+  /* Timer configuration.*/
413
+  qeip->tim->PSC  = 0;
414
+  arr = qeip->config->range - 1;
415
+  osalDbgAssert((arr <= 0xFFFF), "qei_lld_start(), #1" /*, "invalid range"*/);
416
+  qeip->tim->ARR  = arr & 0xFFFF;
417
+
418
+  /* CCMR1_CC1S = 01 - CH1 Input on TI1.
419
+     CCMR1_CC2S = 01 - CH2 Input on TI2.*/
420
+  qeip->tim->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;
421
+
422
+  ccer = 0;
423
+  if (qeip->config->channels[0].mode == QEI_INPUT_INVERTED)
424
+    ccer |= TIM_CCER_CC1P;
425
+  if (qeip->config->channels[1].mode == QEI_INPUT_INVERTED)
426
+    ccer |= TIM_CCER_CC2P;
427
+  qeip->tim->CCER = ccer;
428
+
429
+  if (qeip->config->mode == QEI_COUNT_CH1)
430
+    qeip->tim->SMCR  = TIM_SMCR_SMS_1;
431
+  else if (qeip->config->mode == QEI_COUNT_CH2)
432
+    qeip->tim->SMCR  = TIM_SMCR_SMS_0;
433
+  else
434
+    qeip->tim->SMCR  = TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1;
435
+}
436
+
437
+/**
438
+ * @brief   Deactivates the QEI peripheral.
439
+ *
440
+ * @param[in] qeip      pointer to the @p QEIDriver object
441
+ *
442
+ * @notapi
443
+ */
444
+void qei_lld_stop(QEIDriver *qeip) {
445
+
446
+  if (qeip->state == QEI_READY) {
447
+    /* Clock deactivation.*/
448
+    qeip->tim->CR1  = 0;                    /* Timer disabled.              */
449
+
450
+#if STM32_QEI_USE_TIM1
451
+    if (&QEID1 == qeip) {
452
+      rccDisableTIM1();
453
+    }
454
+#endif
455
+#if STM32_QEI_USE_TIM2
456
+    if (&QEID2 == qeip) {
457
+      rccDisableTIM2();
458
+    }
459
+#endif
460
+#if STM32_QEI_USE_TIM3
461
+    if (&QEID3 == qeip) {
462
+      rccDisableTIM3();
463
+    }
464
+#endif
465
+#if STM32_QEI_USE_TIM4
466
+    if (&QEID4 == qeip) {
467
+      rccDisableTIM4();
468
+    }
469
+#endif
470
+#if STM32_QEI_USE_TIM5
471
+    if (&QEID5 == qeip) {
472
+      rccDisableTIM5();
473
+    }
474
+#endif
475
+  }
476
+#if STM32_QEI_USE_TIM8
477
+    if (&QEID8 == qeip) {
478
+      rccDisableTIM8();
479
+    }
480
+#endif
481
+}
482
+
483
+/**
484
+ * @brief   Enables the quadrature encoder.
485
+ *
486
+ * @param[in] qeip      pointer to the @p QEIDriver object
487
+ *
488
+ * @notapi
489
+ */
490
+void qei_lld_enable(QEIDriver *qeip) {
491
+
492
+  qeip->tim->CR1  = TIM_CR1_CEN;
493
+}
494
+
495
+/**
496
+ * @brief   Disables the quadrature encoder.
497
+ *
498
+ * @param[in] qeip      pointer to the @p QEIDriver object
499
+ *
500
+ * @notapi
501
+ */
502
+void qei_lld_disable(QEIDriver *qeip) {
503
+
504
+  qeip->tim->CR1  = 0;
505
+}
506
+
507
+#endif /* HAL_USE_QEI */
508
+
509
+/** @} */
510
diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.h
511
new file mode 100644
512
index 0000000..d4b7acc
513
--- /dev/null
514
+++ b/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.h
515
@@ -0,0 +1,302 @@
516
+/*
517
+AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
518
+Copyright (C) 2016..2018  Thomas Schöpping et al.
519
+
520
+This program is free software: you can redistribute it and/or modify
521
+it under the terms of the GNU General Public License as published by
522
+the Free Software Foundation, either version 3 of the License, or
523
+(at your option) any later version.
524
+
525
+This program is distributed in the hope that it will be useful,
526
+but WITHOUT ANY WARRANTY; without even the implied warranty of
527
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
528
+GNU General Public License for more details.
529
+
530
+You should have received a copy of the GNU General Public License
531
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
532
+*/
533
+
534
+/**
535
+ * @file    STM32/hal_qei_lld.h
536
+ * @brief   STM32 QEI subsystem low level driver header.
537
+ *
538
+ * @addtogroup QEI
539
+ * @{
540
+ */
541
+
542
+#ifndef _HAL_QEI_LLD_H_
543
+#define _HAL_QEI_LLD_H_
544
+
545
+#include "stm32_tim.h"
546
+
547
+#if HAL_USE_QEI || defined(__DOXYGEN__)
548
+
549
+/*===========================================================================*/
550
+/* Driver constants.                                                         */
551
+/*===========================================================================*/
552
+
553
+/**
554
+ * @brief   Number of input channels per QEI driver.
555
+ */
556
+#define QEI_CHANNELS                            2
557
+
558
+/*===========================================================================*/
559
+/* Driver pre-compile time settings.                                         */
560
+/*===========================================================================*/
561
+
562
+/**
563
+ * @name    Configuration options
564
+ * @{
565
+ */
566
+/**
567
+ * @brief   QEID1 driver enable switch.
568
+ * @details If set to @p TRUE the support for QEID1 is included.
569
+ * @note    The default is @p TRUE.
570
+ */
571
+#if !defined(STM32_QEI_USE_TIM1) || defined(__DOXYGEN__)
572
+#define STM32_QEI_USE_TIM1                  TRUE
573
+#endif
574
+
575
+/**
576
+ * @brief   QEID2 driver enable switch.
577
+ * @details If set to @p TRUE the support for QEID2 is included.
578
+ * @note    The default is @p TRUE.
579
+ */
580
+#if !defined(STM32_QEI_USE_TIM2) || defined(__DOXYGEN__)
581
+#define STM32_QEI_USE_TIM2                  TRUE
582
+#endif
583
+
584
+/**
585
+ * @brief   QEID3 driver enable switch.
586
+ * @details If set to @p TRUE the support for QEID3 is included.
587
+ * @note    The default is @p TRUE.
588
+ */
589
+#if !defined(STM32_QEI_USE_TIM3) || defined(__DOXYGEN__)
590
+#define STM32_QEI_USE_TIM3                  TRUE
591
+#endif
592
+
593
+/**
594
+ * @brief   QEID4 driver enable switch.
595
+ * @details If set to @p TRUE the support for QEID4 is included.
596
+ * @note    The default is @p TRUE.
597
+ */
598
+#if !defined(STM32_QEI_USE_TIM4) || defined(__DOXYGEN__)
599
+#define STM32_QEI_USE_TIM4                  TRUE
600
+#endif
601
+
602
+/**
603
+ * @brief   QEID5 driver enable switch.
604
+ * @details If set to @p TRUE the support for QEID5 is included.
605
+ * @note    The default is @p TRUE.
606
+ */
607
+#if !defined(STM32_QEI_USE_TIM5) || defined(__DOXYGEN__)
608
+#define STM32_QEI_USE_TIM5                  TRUE
609
+#endif
610
+
611
+/**
612
+ * @brief   QEID8 driver enable switch.
613
+ * @details If set to @p TRUE the support for QEID8 is included.
614
+ * @note    The default is @p TRUE.
615
+ */
616
+#if !defined(STM32_QEI_USE_TIM8) || defined(__DOXYGEN__)
617
+#define STM32_QEI_USE_TIM8                  TRUE
618
+#endif
619
+/** @} */
620
+
621
+/*===========================================================================*/
622
+/* Derived constants and error checks.                                       */
623
+/*===========================================================================*/
624
+
625
+#if STM32_QEI_USE_TIM1 && !STM32_HAS_TIM1
626
+#error "TIM1 not present in the selected device"
627
+#endif
628
+
629
+#if STM32_QEI_USE_TIM2 && !STM32_HAS_TIM2
630
+#error "TIM2 not present in the selected device"
631
+#endif
632
+
633
+#if STM32_QEI_USE_TIM3 && !STM32_HAS_TIM3
634
+#error "TIM3 not present in the selected device"
635
+#endif
636
+
637
+#if STM32_QEI_USE_TIM4 && !STM32_HAS_TIM4
638
+#error "TIM4 not present in the selected device"
639
+#endif
640
+
641
+#if STM32_QEI_USE_TIM5 && !STM32_HAS_TIM5
642
+#error "TIM5 not present in the selected device"
643
+#endif
644
+
645
+#if STM32_QEI_USE_TIM8 && !STM32_HAS_TIM8
646
+#error "TIM8 not present in the selected device"
647
+#endif
648
+
649
+#if !STM32_QEI_USE_TIM1 && !STM32_QEI_USE_TIM2 &&                           \
650
+    !STM32_QEI_USE_TIM3 && !STM32_QEI_USE_TIM4 &&                           \
651
+    !STM32_QEI_USE_TIM5 && !STM32_QEI_USE_TIM8
652
+#error "QEI driver activated but no TIM peripheral assigned"
653
+#endif
654
+
655
+/*===========================================================================*/
656
+/* Driver data structures and types.                                         */
657
+/*===========================================================================*/
658
+
659
+/**
660
+ * @brief QEI driver mode.
661
+ */
662
+typedef enum {
663
+  QEI_COUNT_BOTH = 0,
664
+  QEI_COUNT_CH1 = 1,
665
+  QEI_COUNT_CH2 = 2,
666
+} qeimode_t;
667
+
668
+/**
669
+ * @brief QEI input mode.
670
+ */
671
+typedef enum {
672
+  QEI_INPUT_NONINVERTED = 0, /**< Input channel noninverted.*/
673
+  QEI_INPUT_INVERTED = 1, /**< Input channel inverted.*/
674
+} qeiinputmode_t;
675
+
676
+/**
677
+ * @brief   QEI count type.
678
+ */
679
+typedef uint32_t qeicnt_t;
680
+
681
+/**
682
+ * @brief   Driver channel configuration structure.
683
+ */
684
+typedef struct {
685
+  /**
686
+   * @brief Channel input logic.
687
+   */
688
+  qeiinputmode_t                 mode;
689
+  /* End of the mandatory fields.*/
690
+} QEIChannelConfig;
691
+
692
+/**
693
+ * @brief   Driver configuration structure.
694
+ */
695
+typedef struct {
696
+  /**
697
+   * @brief   Driver mode.
698
+   */
699
+  qeimode_t                 mode;
700
+  /**
701
+   * @brief   Channels configurations.
702
+   */
703
+  QEIChannelConfig          channels[QEI_CHANNELS];
704
+  /**
705
+   * @brief   Range in pulses.
706
+   */
707
+  qeicnt_t                  range;
708
+  /* End of the mandatory fields.*/
709
+} QEIConfig;
710
+
711
+/**
712
+ * @brief   Structure representing an QEI driver.
713
+ */
714
+struct QEIDriver {
715
+  /**
716
+   * @brief Driver state.
717
+   */
718
+  qeistate_t                state;
719
+  /**
720
+   * @brief Current configuration data.
721
+   */
722
+  const QEIConfig           *config;
723
+#if defined(QEI_DRIVER_EXT_FIELDS)
724
+  QEI_DRIVER_EXT_FIELDS
725
+#endif
726
+  /* End of the mandatory fields.*/
727
+  /**
728
+   * @brief Pointer to the TIMx registers block.
729
+   */
730
+  stm32_tim_t               *tim;
731
+};
732
+
733
+/*===========================================================================*/
734
+/* Driver macros.                                                            */
735
+/*===========================================================================*/
736
+
737
+/**
738
+ * @brief   Returns the direction of the last transition.
739
+ * @details The direction is defined as boolean and is
740
+ *          calculated at each transition on any input.
741
+ *
742
+ * @param[in] qeip      pointer to the @p QEIDriver object
743
+ * @return              The request direction.
744
+ * @retval FALSE        Position counted up.
745
+ * @retval TRUE         Position counted down.
746
+ *
747
+ * @iclass
748
+ */
749
+#define qei_lld_get_direction(qeip) !!((qeip)->tim->CR1 & TIM_CR1_DIR)
750
+
751
+/**
752
+ * @brief   Returns the position of the encoder.
753
+ * @details The position is defined as number of pulses since last reset.
754
+ *
755
+ * @param[in] qeip      pointer to the @p QEIDriver object
756
+ * @return              The number of pulses.
757
+ *
758
+ * @iclass
759
+ */
760
+#define qei_lld_get_position(qeip) ((qeip)->tim->CNT)
761
+
762
+/**
763
+ * @brief   Returns the range of the encoder.
764
+ * @details The range is defined as number of maximum pulse count.
765
+ *
766
+ * @param[in] qeip      pointer to the @p QEIDriver object
767
+ * @return              The number of pulses.
768
+ *
769
+ * @iclass
770
+ */
771
+#define qei_lld_get_range(qeip) ((qeip)->tim->ARR + 1)
772
+
773
+/*===========================================================================*/
774
+/* External declarations.                                                    */
775
+/*===========================================================================*/
776
+
777
+#if STM32_QEI_USE_TIM1 && !defined(__DOXYGEN__)
778
+extern QEIDriver QEID1;
779
+#endif
780
+
781
+#if STM32_QEI_USE_TIM2 && !defined(__DOXYGEN__)
782
+extern QEIDriver QEID2;
783
+#endif
784
+
785
+#if STM32_QEI_USE_TIM3 && !defined(__DOXYGEN__)
786
+extern QEIDriver QEID3;
787
+#endif
788
+
789
+#if STM32_QEI_USE_TIM4 && !defined(__DOXYGEN__)
790
+extern QEIDriver QEID4;
791
+#endif
792
+
793
+#if STM32_QEI_USE_TIM5 && !defined(__DOXYGEN__)
794
+extern QEIDriver QEID5;
795
+#endif
796
+
797
+#if STM32_QEI_USE_TIM8 && !defined(__DOXYGEN__)
798
+extern QEIDriver QEID8;
799
+#endif
800
+
801
+#ifdef __cplusplus
802
+extern "C" {
803
+#endif
804
+  void qei_lld_init(void);
805
+  void qei_lld_start(QEIDriver *qeip);
806
+  void qei_lld_stop(QEIDriver *qeip);
807
+  void qei_lld_enable(QEIDriver *qeip);
808
+  void qei_lld_disable(QEIDriver *qeip);
809
+#ifdef __cplusplus
810
+}
811
+#endif
812
+
813
+#endif /* HAL_USE_QEI */
814
+
815
+#endif /* _HAL_QEI_LLD_H_ */
816
+
817
+/** @} */
818
diff --git a/os/hal/src/hal_qei.c b/os/hal/src/hal_qei.c
819
new file mode 100644
820
index 0000000..c08d175
821
--- /dev/null
822
+++ b/os/hal/src/hal_qei.c
823
@@ -0,0 +1,156 @@
824
+/*
825
+AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
826
+Copyright (C) 2016..2018  Thomas Schöpping et al.
827
+
828
+This program is free software: you can redistribute it and/or modify
829
+it under the terms of the GNU General Public License as published by
830
+the Free Software Foundation, either version 3 of the License, or
831
+(at your option) any later version.
832
+
833
+This program is distributed in the hope that it will be useful,
834
+but WITHOUT ANY WARRANTY; without even the implied warranty of
835
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
836
+GNU General Public License for more details.
837
+
838
+You should have received a copy of the GNU General Public License
839
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
840
+*/
841
+
842
+/**
843
+ * @file    hal_qei.c
844
+ * @brief   QEI Driver code.
845
+ *
846
+ * @addtogroup QEI
847
+ * @{
848
+ */
849
+
850
+#include "hal.h"
851
+#include "hal_qei.h"
852
+
853
+#if HAL_USE_QEI || defined(__DOXYGEN__)
854
+
855
+/*===========================================================================*/
856
+/* Driver local definitions.                                                 */
857
+/*===========================================================================*/
858
+
859
+/*===========================================================================*/
860
+/* Driver exported variables.                                                */
861
+/*===========================================================================*/
862
+
863
+/*===========================================================================*/
864
+/* Driver local variables.                                                   */
865
+/*===========================================================================*/
866
+
867
+/*===========================================================================*/
868
+/* Driver local functions.                                                   */
869
+/*===========================================================================*/
870
+
871
+/*===========================================================================*/
872
+/* Driver exported functions.                                                */
873
+/*===========================================================================*/
874
+
875
+/**
876
+ * @brief   QEI Driver initialization.
877
+ * @note    This function is implicitly invoked by @p halInit(), there is
878
+ *          no need to explicitly initialize the driver.
879
+ *
880
+ * @init
881
+ */
882
+void qeiInit(void) {
883
+
884
+  qei_lld_init();
885
+}
886
+
887
+/**
888
+ * @brief   Initializes the standard part of a @p QEIDriver structure.
889
+ *
890
+ * @param[out] qeip     pointer to the @p QEIDriver object
891
+ *
892
+ * @init
893
+ */
894
+void qeiObjectInit(QEIDriver *qeip) {
895
+
896
+  qeip->state  = QEI_STOP;
897
+  qeip->config = NULL;
898
+}
899
+
900
+/**
901
+ * @brief   Configures and activates the QEI peripheral.
902
+ *
903
+ * @param[in] qeip      pointer to the @p QEIDriver object
904
+ * @param[in] config    pointer to the @p QEIConfig object
905
+ *
906
+ * @api
907
+ */
908
+void qeiStart(QEIDriver *qeip, const QEIConfig *config) {
909
+
910
+  chDbgCheck((qeip != NULL) && (config != NULL) /*, "qeiStart"*/);
911
+
912
+  chSysLock();
913
+  chDbgAssert((qeip->state == QEI_STOP) || (qeip->state == QEI_READY),
914
+              "qeiStart(), #1" /*, "invalid state"*/);
915
+  qeip->config = config;
916
+  qei_lld_start(qeip);
917
+  qeip->state = QEI_READY;
918
+  chSysUnlock();
919
+}
920
+
921
+/**
922
+ * @brief   Deactivates the QEI peripheral.
923
+ *
924
+ * @param[in] qeip      pointer to the @p QEIDriver object
925
+ *
926
+ * @api
927
+ */
928
+void qeiStop(QEIDriver *qeip) {
929
+
930
+  chDbgCheck(qeip != NULL /*, "qeiStop"*/);
931
+
932
+  chSysLock();
933
+  chDbgAssert((qeip->state == QEI_STOP) || (qeip->state == QEI_READY),
934
+              "qeiStop(), #1" /*, "invalid state"*/);
935
+  qei_lld_stop(qeip);
936
+  qeip->state = QEI_STOP;
937
+  chSysUnlock();
938
+}
939
+
940
+/**
941
+ * @brief   Enables the quadrature encoder.
942
+ *
943
+ * @param[in] qeip      pointer to the @p QEIDriver object
944
+ *
945
+ * @api
946
+ */
947
+void qeiEnable(QEIDriver *qeip) {
948
+
949
+  chDbgCheck(qeip != NULL /*, "qeiEnable"*/);
950
+
951
+  chSysLock();
952
+  chDbgAssert(qeip->state == QEI_READY, "qeiEnable(), #1" /*, "invalid state"*/);
953
+  qei_lld_enable(qeip);
954
+  qeip->state = QEI_ACTIVE;
955
+  chSysUnlock();
956
+}
957
+
958
+/**
959
+ * @brief   Disables the quadrature encoder.
960
+ *
961
+ * @param[in] qeip      pointer to the @p QEIDriver object
962
+ *
963
+ * @api
964
+ */
965
+void qeiDisable(QEIDriver *qeip) {
966
+
967
+  chDbgCheck(qeip != NULL /*, "qeiDisable"*/);
968
+
969
+  chSysLock();
970
+  chDbgAssert((qeip->state == QEI_READY) || (qeip->state == QEI_ACTIVE),
971
+              "qeiDisable(), #1" /*, "invalid state"*/);
972
+  qei_lld_disable(qeip);
973
+  qeip->state = QEI_READY;
974
+  chSysUnlock();
975
+}
976
+
977
+#endif /* HAL_USE_QEI */
978
+
979
+/** @} */