blob: 5a69835a59cba33df79e742e62ea72a3775e3d04 [file] [log] [blame]
Brian Silverman1b6fbd02013-12-12 18:08:47 -08001#ifndef CAPE_ENCODER_H_
2#define CAPE_ENCODER_H_
3
4#include <stdint.h>
5#include <limits.h>
6
7#include <STM32F2XX.h>
8
9void encoder_init(void);
10
11// Updates a signed 32-bit counter with a new 16-bit value. Assumes that the
12// value will not more than half-wrap between updates.
13// new is 32 bits so it doesn't have to get masked, but the value passed in must
14// be <= UINT16_MAX.
15// Useful for 16-bit encoder counters.
16static inline void counter_update_s32_u16(int32_t *restrict counter,
17 uint32_t new) {
18 static const uint16_t kHalf = 0xFFFF / 2;
19 uint16_t old = *counter & 0xFFFF;
20 int32_t counter_top = *counter ^ old;
21 int32_t delta = (int32_t)new - (int32_t)old;
22 int32_t new_counter;
23 if (__builtin_expect(delta < -kHalf, 0)) {
24 new_counter = counter_top - 0x10000;
25 } else if (__builtin_expect(delta > kHalf, 0)) {
26 new_counter = counter_top + 0x10000;
27 } else {
28 new_counter = counter_top;
29 }
30 *counter = new_counter | new;
31}
32
33// Updates an unsigned 64-bit counter with a new 16-bit value. Assumes that the
34// value will not wrap more than once between updates.
35// new is 32 bits so it doesn't have to get masked, but the value passed in must
36// be <= UINT16_MAX.
37// Useful for 16-bit timers being used for absolute timings.
38static inline void counter_update_u64_u16(uint64_t *restrict counter,
39 uint32_t new) {
40 uint16_t old = *counter & 0xFFFF;
41 int64_t counter_top = *counter ^ old;
42 if (__builtin_expect(new < old, 0)) {
43 *counter = counter_top + 0x10000;
44 } else {
45 *counter = counter_top;
46 }
47 *counter |= new;
48}
49
50// number is the 0-indexed number on the silkscreen
51static inline int32_t encoder_read(int number) {
52 static int32_t value0, value4, value6, value7;
53 extern volatile int32_t encoder1_value, encoder3_value;
54 switch (number) {
55 case 0:
56 counter_update_s32_u16(&value0, TIM8->CNT);
57 return value0;
58 case 1:
59 return encoder1_value;
60 case 2:
61 return TIM5->CNT;
62 case 3:
63 return encoder3_value;
64 case 4:
65 counter_update_s32_u16(&value4, TIM1->CNT);
66 return value4;
67 case 5:
68 return TIM2->CNT;
69 case 6:
70 counter_update_s32_u16(&value6, TIM3->CNT);
71 return value6;
72 case 7:
73 counter_update_s32_u16(&value7, TIM4->CNT);
74 return value7;
75 default:
76 return INT32_MAX;
77 }
78}
79
80#endif // CAPE_ENCODER_H_