blob: af68de340c785f9c92ffaae3057ff394a5f43dfc [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
79// 4.A
80void TIM1_CC_IRQHandler(void) {
81 uint32_t a_inputs = GPIOA->IDR, b_inputs = GPIOB->IDR;
82 TIM1->SR = ~TIM_SR_CC1IF;
83 int32_t old_value = encoder4_value;
84 int32_t new_value;
85 if (((a_inputs >> 8) ^ b_inputs) & (1 << 0)) {
86 new_value = old_value + 1;
87 } else {
88 new_value = old_value - 1;
89 }
90 encoder4_value = new_value;
91}
92
93// 4.B
94void TIM3_IRQHandler(void) {
95 uint32_t a_inputs = GPIOA->IDR, b_inputs = GPIOB->IDR;
96 TIM3->SR = ~TIM_SR_CC3IF;
97 int32_t old_value = encoder4_value;
98 int32_t new_value;
99 if (((a_inputs >> 8) ^ b_inputs) & (1 << 0)) {
100 new_value = old_value - 1;
101 } else {
102 new_value = old_value + 1;
103 }
104 encoder4_value = new_value;
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800105}
106
Brian Silvermane6e9df72014-02-18 15:14:27 -0800107static void encoder_setup(TIM_TypeDef *timer, int fast) {
Brian Silvermanffeef3f2013-12-22 14:06:23 -0800108 timer->CR1 =
Brian Silvermane6e9df72014-02-18 15:14:27 -0800109 TIM_CR1_URS | /* don't generate spurious update interrupts that
110 might be shared with other timers */
111 (fast ? (1 << 8) : 0) /* divide filter clock by 2 on fast encoders */;
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800112 timer->SMCR = 3; // 4x quadrature encoder mode
Brian Silverman5f4bfe02014-02-18 00:57:53 -0800113 timer->CCER = 0;
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800114 timer->CCMR1 =
115 TIM_CCMR1_CC2S_0 | /* input pin 2 -> timer input 2 */
Brian Silverman5f4bfe02014-02-18 00:57:53 -0800116 TIM_CCMR1_CC1S_0 | /* input pin 1 -> timer input 1 */
Brian Silvermane6e9df72014-02-18 15:14:27 -0800117 (0xE << 4) | /* divide filter clock by 32, need 6 in a row to trigger */
118 (0xE << 12) /* same for other input */;
Brian Silverman5f4bfe02014-02-18 00:57:53 -0800119 timer->PSC = 0;
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800120 timer->EGR = TIM_EGR_UG;
121 timer->CR1 |= TIM_CR1_CEN;
122}
123
124void encoder_init(void) {
Brian Silverman25a06d92013-12-15 16:28:52 -0800125 // Set up the 3 simple software encoder inputs.
126 EXTI_set(0, 2);
127 EXTI_set(1, 2);
128 EXTI_set(3, 0);
129 EXTI->IMR |= EXTI_IMR_MR0 | EXTI_IMR_MR1 | EXTI_IMR_MR3;
130 EXTI->RTSR |= EXTI_RTSR_TR0 | EXTI_RTSR_TR1 | EXTI_RTSR_TR3;
131 EXTI->FTSR |= EXTI_FTSR_TR0 | EXTI_FTSR_TR1 | EXTI_FTSR_TR3;
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800132 NVIC_EnableIRQ(EXTI0_IRQn);
133 NVIC_EnableIRQ(EXTI1_IRQn);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800134 NVIC_EnableIRQ(EXTI3_IRQn);
135
Brian Silvermand4a64d92013-12-25 15:52:59 -0800136 // Set up the A2 software encoder input through TIM9 input 1.
Brian Silverman25a06d92013-12-15 16:28:52 -0800137 gpio_setup_alt(GPIOA, 2, 3);
138 RCC->APB2ENR |= RCC_APB2ENR_TIM9EN;
Brian Silvermanffeef3f2013-12-22 14:06:23 -0800139 TIM9->CR1 = 0;
Brian Silverman25a06d92013-12-15 16:28:52 -0800140 TIM9->DIER = TIM_DIER_CC1IE;
141 TIM9->CCMR1 = TIM_CCMR1_CC1S_0; /* input pin 1 -> timer input 1 */
142 TIM9->CCER = TIM_CCER_CC1NP | TIM_CCER_CC1P | TIM_CCER_CC1E;
143 TIM9->EGR = TIM_EGR_UG;
144 TIM9->CR1 |= TIM_CR1_CEN;
145 NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);
146
Brian Silvermand4a64d92013-12-25 15:52:59 -0800147 // Set up the A4 software encoder input through TIM1 input 1.
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800148 gpio_setup_alt(GPIOA, 8, 1);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800149 RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
Brian Silvermand4a64d92013-12-25 15:52:59 -0800150 TIM1->CR1 = 0;
151 TIM1->DIER = TIM_DIER_CC1IE;
152 TIM1->CCMR1 = TIM_CCMR1_CC1S_0; /* input pin 1 -> timer input 1 */
153 TIM1->CCER = TIM_CCER_CC1NP | TIM_CCER_CC1P | TIM_CCER_CC1E;
154 TIM1->EGR = TIM_EGR_UG;
155 TIM1->CR1 |= TIM_CR1_CEN;
156 NVIC_EnableIRQ(TIM1_CC_IRQn);
157
158 // Set up the B4 software encoder input through TIM3 input 3.
159 gpio_setup_alt(GPIOB, 0, 2);
160 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
161 TIM3->CR1 = 0;
162 TIM3->DIER = TIM_DIER_CC3IE;
163 TIM3->CCMR2 = TIM_CCMR2_CC3S_0; /* input pin 3 -> timer input 3 */
164 TIM3->CCER = TIM_CCER_CC3NP | TIM_CCER_CC3P | TIM_CCER_CC3E;
165 TIM3->EGR = TIM_EGR_UG;
166 TIM3->CR1 |= TIM_CR1_CEN;
167 NVIC_EnableIRQ(TIM3_IRQn);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800168
169 gpio_setup_alt(GPIOA, 5, 1);
170 gpio_setup_alt(GPIOB, 3, 1);
171 RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
Brian Silvermane6e9df72014-02-18 15:14:27 -0800172 encoder_setup(TIM2, 0);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800173
174 gpio_setup_alt(GPIOA, 6, 2);
175 gpio_setup_alt(GPIOB, 5, 2);
176 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
Brian Silvermane6e9df72014-02-18 15:14:27 -0800177 encoder_setup(TIM3, 0);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800178
179 gpio_setup_alt(GPIOB, 6, 2);
180 gpio_setup_alt(GPIOB, 7, 2);
181 RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
Brian Silvermane6e9df72014-02-18 15:14:27 -0800182 encoder_setup(TIM4, 0);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800183
184 gpio_setup_alt(GPIOA, 0, 2);
185 gpio_setup_alt(GPIOA, 1, 2);
186 RCC->APB1ENR |= RCC_APB1ENR_TIM5EN;
Brian Silvermane6e9df72014-02-18 15:14:27 -0800187 encoder_setup(TIM5, 0);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800188
189 gpio_setup_alt(GPIOC, 6, 3);
190 gpio_setup_alt(GPIOC, 7, 3);
191 RCC->APB2ENR |= RCC_APB2ENR_TIM8EN;
Brian Silvermane6e9df72014-02-18 15:14:27 -0800192 encoder_setup(TIM8, 1);
Brian Silverman1b6fbd02013-12-12 18:08:47 -0800193}