blob: 881f2a81c0911ad03d4ad88f4a3941e24b4c104b [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:
Brian Silvermane6e9df72014-02-18 15:14:27 -08008// 0: PC6,PC7 TIM8(APB2)
Brian Silverman1b6fbd02013-12-12 18:08:47 -08009// 1: PC0,PC1 EXTI0,EXTI1
10// 2: PA0,PA1 TIM5(32)
Brian Silvermand4a64d92013-12-25 15:52:59 -080011// 3: PA2,PA3 TIM9.1,EXTI3
12// 4: PA8,PB0 TIM1.1,TIM3.3
Brian Silverman1b6fbd02013-12-12 18:08:47 -080013// 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;
Brian Silvermand4a64d92013-12-25 15:52:59 -080019volatile int32_t encoder4_value = 0;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080020
21// 1.A
22void EXTI0_IRQHandler(void) {
Brian Silvermand4a64d92013-12-25 15:52:59 -080023 uint32_t inputs = GPIOC->IDR;
Brian Silverman25a06d92013-12-15 16:28:52 -080024 EXTI->PR = EXTI_PR_PR0;
Brian Silvermand4a64d92013-12-25 15:52:59 -080025 int32_t old_value = encoder1_value;
26 int32_t new_value;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080027 // This looks like a weird way to XOR the 2 inputs, but it compiles down to
28 // just 2 instructions, which is hard to beat.
29 if (((inputs >> 1) ^ inputs) & (1 << 0)) {
Brian Silvermand4a64d92013-12-25 15:52:59 -080030 new_value = old_value + 1;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080031 } else {
Brian Silvermand4a64d92013-12-25 15:52:59 -080032 new_value = old_value - 1;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080033 }
Brian Silvermand4a64d92013-12-25 15:52:59 -080034 encoder1_value = new_value;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080035}
36
37// 1.B
38void EXTI1_IRQHandler(void) {
Brian Silvermand4a64d92013-12-25 15:52:59 -080039 uint32_t inputs = GPIOC->IDR;
Brian Silverman25a06d92013-12-15 16:28:52 -080040 EXTI->PR = EXTI_PR_PR1;
Brian Silvermand4a64d92013-12-25 15:52:59 -080041 int32_t old_value = encoder1_value;
42 int32_t new_value;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080043 if (((inputs >> 1) ^ inputs) & (1 << 0)) {
Brian Silvermand4a64d92013-12-25 15:52:59 -080044 new_value = old_value - 1;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080045 } else {
Brian Silvermand4a64d92013-12-25 15:52:59 -080046 new_value = old_value + 1;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080047 }
Brian Silvermand4a64d92013-12-25 15:52:59 -080048 encoder1_value = new_value;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080049}
50
51// 3.A
Brian Silvermand4a64d92013-12-25 15:52:59 -080052void TIM1_BRK_TIM9_IRQHandler(void) {
53 uint32_t inputs = GPIOA->IDR;
Brian Silverman176c6762013-12-19 16:28:09 -080054 TIM9->SR = ~TIM_SR_CC1IF;
Brian Silvermand4a64d92013-12-25 15:52:59 -080055 int32_t old_value = encoder3_value;
56 int32_t new_value;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080057 if (((inputs >> 1) ^ inputs) & (1 << 2)) {
Brian Silvermand4a64d92013-12-25 15:52:59 -080058 new_value = old_value + 1;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080059 } else {
Brian Silvermand4a64d92013-12-25 15:52:59 -080060 new_value = old_value - 1;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080061 }
Brian Silvermand4a64d92013-12-25 15:52:59 -080062 encoder3_value = new_value;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080063}
64
65// 3.B
66void EXTI3_IRQHandler(void) {
Brian Silvermand4a64d92013-12-25 15:52:59 -080067 uint32_t inputs = GPIOA->IDR;
Brian Silverman25a06d92013-12-15 16:28:52 -080068 EXTI->PR = EXTI_PR_PR3;
Brian Silvermand4a64d92013-12-25 15:52:59 -080069 int32_t old_value = encoder3_value;
70 int32_t new_value;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080071 if (((inputs >> 1) ^ inputs) & (1 << 2)) {
Brian Silvermand4a64d92013-12-25 15:52:59 -080072 new_value = old_value - 1;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080073 } else {
Brian Silvermand4a64d92013-12-25 15:52:59 -080074 new_value = old_value + 1;
Brian Silverman1b6fbd02013-12-12 18:08:47 -080075 }
Brian Silvermand4a64d92013-12-25 15:52:59 -080076 encoder3_value = new_value;
77}
78
Brian Silverman1b7fe842014-04-01 14:25:18 -070079#if 0
80TODO(brians): Figure out a good way to let robot_comp override this.
Brian Silvermand4a64d92013-12-25 15:52:59 -080081// 4.A
82void TIM1_CC_IRQHandler(void) {
83 uint32_t a_inputs = GPIOA->IDR, b_inputs = GPIOB->IDR;
84 TIM1->SR = ~TIM_SR_CC1IF;
85 int32_t old_value = encoder4_value;
86 int32_t new_value;
87 if (((a_inputs >> 8) ^ b_inputs) & (1 << 0)) {
88 new_value = old_value + 1;
89 } else {
90 new_value = old_value - 1;
91 }
92 encoder4_value = new_value;
93}
Brian Silverman1b7fe842014-04-01 14:25:18 -070094#endif
Brian Silvermand4a64d92013-12-25 15:52:59 -080095
96// 4.B
97void TIM3_IRQHandler(void) {
98 uint32_t a_inputs = GPIOA->IDR, b_inputs = GPIOB->IDR;
99 TIM3->SR = ~TIM_SR_CC3IF;
100 int32_t old_value = encoder4_value;
101 int32_t new_value;
102 if (((a_inputs >> 8) ^ b_inputs) & (1 << 0)) {
103 new_value = old_value - 1;
104 } else {
105 new_value = old_value + 1;
106 }
107 encoder4_value = new_value;
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800108}
109
Brian Silvermane6e9df72014-02-18 15:14:27 -0800110static void encoder_setup(TIM_TypeDef *timer, int fast) {
Brian Silvermanffeef3f2013-12-22 14:06:23 -0800111 timer->CR1 =
Brian Silvermane6e9df72014-02-18 15:14:27 -0800112 TIM_CR1_URS | /* don't generate spurious update interrupts that
113 might be shared with other timers */
114 (fast ? (1 << 8) : 0) /* divide filter clock by 2 on fast encoders */;
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800115 timer->SMCR = 3; // 4x quadrature encoder mode
Brian Silverman5f4bfe02014-02-18 00:57:53 -0800116 timer->CCER = 0;
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800117 timer->CCMR1 =
118 TIM_CCMR1_CC2S_0 | /* input pin 2 -> timer input 2 */
Brian Silverman5f4bfe02014-02-18 00:57:53 -0800119 TIM_CCMR1_CC1S_0 | /* input pin 1 -> timer input 1 */
Brian Silvermane6e9df72014-02-18 15:14:27 -0800120 (0xE << 4) | /* divide filter clock by 32, need 6 in a row to trigger */
121 (0xE << 12) /* same for other input */;
Brian Silverman5f4bfe02014-02-18 00:57:53 -0800122 timer->PSC = 0;
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800123 timer->EGR = TIM_EGR_UG;
124 timer->CR1 |= TIM_CR1_CEN;
125}
126
127void encoder_init(void) {
Brian Silverman25a06d92013-12-15 16:28:52 -0800128 // Set up the 3 simple software encoder inputs.
129 EXTI_set(0, 2);
130 EXTI_set(1, 2);
131 EXTI_set(3, 0);
132 EXTI->IMR |= EXTI_IMR_MR0 | EXTI_IMR_MR1 | EXTI_IMR_MR3;
133 EXTI->RTSR |= EXTI_RTSR_TR0 | EXTI_RTSR_TR1 | EXTI_RTSR_TR3;
134 EXTI->FTSR |= EXTI_FTSR_TR0 | EXTI_FTSR_TR1 | EXTI_FTSR_TR3;
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800135 NVIC_EnableIRQ(EXTI0_IRQn);
136 NVIC_EnableIRQ(EXTI1_IRQn);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800137 NVIC_EnableIRQ(EXTI3_IRQn);
138
Brian Silvermand4a64d92013-12-25 15:52:59 -0800139 // Set up the A2 software encoder input through TIM9 input 1.
Brian Silverman25a06d92013-12-15 16:28:52 -0800140 gpio_setup_alt(GPIOA, 2, 3);
141 RCC->APB2ENR |= RCC_APB2ENR_TIM9EN;
Brian Silvermanffeef3f2013-12-22 14:06:23 -0800142 TIM9->CR1 = 0;
Brian Silverman25a06d92013-12-15 16:28:52 -0800143 TIM9->DIER = TIM_DIER_CC1IE;
144 TIM9->CCMR1 = TIM_CCMR1_CC1S_0; /* input pin 1 -> timer input 1 */
145 TIM9->CCER = TIM_CCER_CC1NP | TIM_CCER_CC1P | TIM_CCER_CC1E;
146 TIM9->EGR = TIM_EGR_UG;
147 TIM9->CR1 |= TIM_CR1_CEN;
148 NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);
149
Brian Silvermand4a64d92013-12-25 15:52:59 -0800150 // Set up the A4 software encoder input through TIM1 input 1.
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800151 gpio_setup_alt(GPIOA, 8, 1);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800152 RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
Brian Silvermand4a64d92013-12-25 15:52:59 -0800153 TIM1->CR1 = 0;
154 TIM1->DIER = TIM_DIER_CC1IE;
155 TIM1->CCMR1 = TIM_CCMR1_CC1S_0; /* input pin 1 -> timer input 1 */
156 TIM1->CCER = TIM_CCER_CC1NP | TIM_CCER_CC1P | TIM_CCER_CC1E;
157 TIM1->EGR = TIM_EGR_UG;
158 TIM1->CR1 |= TIM_CR1_CEN;
159 NVIC_EnableIRQ(TIM1_CC_IRQn);
160
161 // Set up the B4 software encoder input through TIM3 input 3.
162 gpio_setup_alt(GPIOB, 0, 2);
163 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
164 TIM3->CR1 = 0;
165 TIM3->DIER = TIM_DIER_CC3IE;
166 TIM3->CCMR2 = TIM_CCMR2_CC3S_0; /* input pin 3 -> timer input 3 */
167 TIM3->CCER = TIM_CCER_CC3NP | TIM_CCER_CC3P | TIM_CCER_CC3E;
168 TIM3->EGR = TIM_EGR_UG;
169 TIM3->CR1 |= TIM_CR1_CEN;
170 NVIC_EnableIRQ(TIM3_IRQn);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800171
172 gpio_setup_alt(GPIOA, 5, 1);
173 gpio_setup_alt(GPIOB, 3, 1);
174 RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
Brian Silvermane6e9df72014-02-18 15:14:27 -0800175 encoder_setup(TIM2, 0);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800176
177 gpio_setup_alt(GPIOA, 6, 2);
178 gpio_setup_alt(GPIOB, 5, 2);
179 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
Brian Silvermane6e9df72014-02-18 15:14:27 -0800180 encoder_setup(TIM3, 0);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800181
182 gpio_setup_alt(GPIOB, 6, 2);
183 gpio_setup_alt(GPIOB, 7, 2);
184 RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
Brian Silvermane6e9df72014-02-18 15:14:27 -0800185 encoder_setup(TIM4, 0);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800186
187 gpio_setup_alt(GPIOA, 0, 2);
188 gpio_setup_alt(GPIOA, 1, 2);
189 RCC->APB1ENR |= RCC_APB1ENR_TIM5EN;
Brian Silvermane6e9df72014-02-18 15:14:27 -0800190 encoder_setup(TIM5, 0);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800191
192 gpio_setup_alt(GPIOC, 6, 3);
193 gpio_setup_alt(GPIOC, 7, 3);
194 RCC->APB2ENR |= RCC_APB2ENR_TIM8EN;
Brian Silvermane6e9df72014-02-18 15:14:27 -0800195 encoder_setup(TIM8, 1);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800196}