blob: 45b7d1602a1264e58a2249dceea83e483bd4e9f5 [file] [log] [blame]
Brian Silverman1b6fbd02013-12-12 18:08:47 -08001#include "cape/encoder.h"
2
3#include <STM32F2XX.h>
4
5#include "cape/util.h"
6
7// Here is where each encoder is hooked up:
8// 0: PC6,PC7 TIM8
9// 1: PC0,PC1 EXTI0,EXTI1
10// 2: PA0,PA1 TIM5(32)
11// 3: PA2,PA3 EXTI2,EXTI3
12// 4: PA8,PB0 TIM1
13// 5: PA5,PB3 TIM2(32)
14// 6: PA6,PB5 TIM3
15// 7: PB6,PB7 TIM4
16
17volatile int32_t encoder1_value = 0;
18volatile int32_t encoder3_value = 0;
19
20// 1.A
21void EXTI0_IRQHandler(void) {
22 EXTI->PR = EXTI_PR_PR0;
23 uint32_t inputs = GPIOA->IDR;
24 // This looks like a weird way to XOR the 2 inputs, but it compiles down to
25 // just 2 instructions, which is hard to beat.
26 if (((inputs >> 1) ^ inputs) & (1 << 0)) {
27 ++encoder1_value;
28 } else {
29 --encoder1_value;
30 }
31}
32
33// 1.B
34void EXTI1_IRQHandler(void) {
35 EXTI->PR = EXTI_PR_PR1;
36 uint32_t inputs = GPIOA->IDR;
37 if (((inputs >> 1) ^ inputs) & (1 << 0)) {
38 --encoder1_value;
39 } else {
40 ++encoder1_value;
41 }
42}
43
44// 3.A
45void EXTI2_IRQHandler(void) {
46 EXTI->PR = EXTI_PR_PR2;
47 uint32_t inputs = GPIOC->IDR;
48 if (((inputs >> 1) ^ inputs) & (1 << 2)) {
49 ++encoder3_value;
50 } else {
51 --encoder3_value;
52 }
53}
54
55// 3.B
56void EXTI3_IRQHandler(void) {
57 EXTI->PR = EXTI_PR_PR3;
58 uint32_t inputs = GPIOC->IDR;
59 if (((inputs >> 1) ^ inputs) & (1 << 2)) {
60 --encoder3_value;
61 } else {
62 ++encoder3_value;
63 }
64}
65
66static void encoder_setup(TIM_TypeDef *timer) {
67 timer->CR1 = TIM_CR1_UDIS;
68 timer->SMCR = 3; // 4x quadrature encoder mode
69 timer->CCMR1 =
70 TIM_CCMR1_CC2S_0 | /* input pin 2 -> timer input 2 */
71 TIM_CCMR1_CC1S_0; /* input pin 1 -> timer input 1*/
72 timer->EGR = TIM_EGR_UG;
73 timer->CR1 |= TIM_CR1_CEN;
74}
75
76void encoder_init(void) {
77 SYSCFG->EXTICR[0] =
78 SYSCFG_EXTICR1_EXTI0_PC |
79 SYSCFG_EXTICR1_EXTI1_PC |
80 SYSCFG_EXTICR1_EXTI2_PA |
81 SYSCFG_EXTICR1_EXTI3_PA;
82 EXTI->IMR |= EXTI_IMR_MR0 | EXTI_IMR_MR1 | EXTI_IMR_MR2 | EXTI_IMR_MR3;
83 EXTI->RTSR |= EXTI_RTSR_TR0 | EXTI_RTSR_TR1 | EXTI_RTSR_TR2 | EXTI_RTSR_TR3;
84 EXTI->FTSR |= EXTI_FTSR_TR0 | EXTI_FTSR_TR1 | EXTI_FTSR_TR2 | EXTI_FTSR_TR3;
85 NVIC_EnableIRQ(EXTI0_IRQn);
86 NVIC_EnableIRQ(EXTI1_IRQn);
87 NVIC_EnableIRQ(EXTI2_IRQn);
88 NVIC_EnableIRQ(EXTI3_IRQn);
89
90 gpio_setup_alt(GPIOA, 8, 1);
91 gpio_setup_alt(GPIOB, 0, 1);
92 RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
93 encoder_setup(TIM1);
94
95 gpio_setup_alt(GPIOA, 5, 1);
96 gpio_setup_alt(GPIOB, 3, 1);
97 RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
98 encoder_setup(TIM2);
99
100 gpio_setup_alt(GPIOA, 6, 2);
101 gpio_setup_alt(GPIOB, 5, 2);
102 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
103 encoder_setup(TIM3);
104
105 gpio_setup_alt(GPIOB, 6, 2);
106 gpio_setup_alt(GPIOB, 7, 2);
107 RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
108 encoder_setup(TIM4);
109
110 gpio_setup_alt(GPIOA, 0, 2);
111 gpio_setup_alt(GPIOA, 1, 2);
112 RCC->APB1ENR |= RCC_APB1ENR_TIM5EN;
113 encoder_setup(TIM5);
114
115 gpio_setup_alt(GPIOC, 6, 3);
116 gpio_setup_alt(GPIOC, 7, 3);
117 RCC->APB2ENR |= RCC_APB2ENR_TIM8EN;
118 encoder_setup(TIM8);
119}