got all the digital inputs hooked up
diff --git a/bbb_cape/src/cape/Makefile b/bbb_cape/src/cape/Makefile
index 710cfcf..5046615 100644
--- a/bbb_cape/src/cape/Makefile
+++ b/bbb_cape/src/cape/Makefile
@@ -40,6 +40,7 @@
gyro \
led \
analog \
+ digital \
OBJECTS_bootloader := bootloader \
uart_common \
diff --git a/bbb_cape/src/cape/digital.c b/bbb_cape/src/cape/digital.c
new file mode 100644
index 0000000..a15b00b
--- /dev/null
+++ b/bbb_cape/src/cape/digital.c
@@ -0,0 +1,213 @@
+#include "cape/digital.h"
+
+#include <STM32F2XX.h>
+
+#include "cape/util.h"
+
+static void digital_capture_default(void) {}
+
+void digital_capture_0P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_0N(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_1P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_1N(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_2P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_2N(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_3P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_3N(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_4P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_4N(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_5P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_5N(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_6P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_6N(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_7P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_7N(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_8P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_8N(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_9P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_9N(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_10P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_10N(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_11P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_11N(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_12P(void) ALIAS_WEAK(digital_capture_default);
+void digital_capture_12N(void) ALIAS_WEAK(digital_capture_default);
+
+typedef void (*EXTIHandler)(uint32_t);
+
+void EXTI2_IRQHandler(void) {
+ uint32_t inputs = GPIOB->IDR;
+ EXTI->PR = EXTI_PR_PR2;
+ if (inputs & (1 << 2)) {
+ digital_capture_11N();
+ } else {
+ digital_capture_11P();
+ }
+}
+
+void EXTI4_IRQHandler(void) {
+ uint32_t inputs = GPIOC->IDR;
+ EXTI->PR = EXTI_PR_PR4;
+ if (inputs & (1 << 4)) {
+ digital_capture_0N();
+ } else {
+ digital_capture_0P();
+ }
+}
+
+static void EXTI5_Handler(uint32_t inputs) {
+ if (inputs & (1 << 5)) {
+ digital_capture_1N();
+ } else {
+ digital_capture_1P();
+ }
+}
+
+static void EXTI7_Handler(uint32_t inputs) {
+ if (inputs & (1 << 7)) {
+ digital_capture_10N();
+ } else {
+ digital_capture_10P();
+ }
+}
+
+static void EXTI8_Handler(uint32_t inputs) {
+ if (inputs & (1 << 7)) {
+ digital_capture_7N();
+ } else {
+ digital_capture_7P();
+ }
+}
+
+static void EXTI9_Handler(uint32_t inputs) {
+ if (inputs & (1 << 9)) {
+ digital_capture_6N();
+ } else {
+ digital_capture_6P();
+ }
+}
+
+void EXTI9_5_IRQHandler(void) {
+ uint32_t inputs = GPIOC->IDR;
+ uint32_t exti = __clz(EXTI->PR);
+ EXTI->PR = (1 << 31) >> exti;
+ switch (exti) {
+ case 31 - 5:
+ EXTI5_Handler(inputs);
+ break;
+ case 31 - 7:
+ EXTI7_Handler(inputs);
+ break;
+ case 31 - 8:
+ EXTI8_Handler(inputs);
+ break;
+ case 31 - 9:
+ EXTI9_Handler(inputs);
+ break;
+ }
+}
+
+static void EXTI10_Handler(uint32_t inputs) {
+ if (inputs & (1 << 10)) {
+ digital_capture_5N();
+ } else {
+ digital_capture_5P();
+ }
+}
+
+static void EXTI11_Handler(uint32_t inputs) {
+ if (inputs & (1 << 11)) {
+ digital_capture_9N();
+ } else {
+ digital_capture_9P();
+ }
+}
+
+static void EXTI12_Handler(uint32_t inputs) {
+ if (inputs & (1 << 12)) {
+ digital_capture_8N();
+ } else {
+ digital_capture_8P();
+ }
+}
+
+static void EXTI13_Handler(uint32_t inputs) {
+ if (inputs & (1 << 13)) {
+ digital_capture_2N();
+ } else {
+ digital_capture_2P();
+ }
+}
+
+static void EXTI14_Handler(uint32_t inputs) {
+ if (inputs & (1 << 14)) {
+ digital_capture_3N();
+ } else {
+ digital_capture_3P();
+ }
+}
+
+static void EXTI15_Handler(uint32_t inputs) {
+ if (inputs & (1 << 15)) {
+ digital_capture_4N();
+ } else {
+ digital_capture_4P();
+ }
+}
+
+void EXTI15_10_IRQHandler(void) {
+ uint32_t inputs = GPIOC->IDR;
+ uint32_t exti = __clz(EXTI->PR);
+ EXTI->PR = (1 << 31) >> exti;
+ switch (exti) {
+ case 31 - 10:
+ EXTI10_Handler(inputs);
+ break;
+ case 31 - 11:
+ EXTI11_Handler(inputs);
+ break;
+ case 31 - 12:
+ EXTI12_Handler(inputs);
+ break;
+ case 31 - 13:
+ EXTI13_Handler(inputs);
+ break;
+ case 31 - 14:
+ EXTI14_Handler(inputs);
+ break;
+ case 31 - 15:
+ EXTI15_Handler(inputs);
+ break;
+ }
+}
+
+static void init_exti(int exti, int port) {
+ EXTI_set(exti, port);
+ EXTI->IMR |= 1 << exti;
+ EXTI->RTSR |= 1 << exti;
+ EXTI->FTSR |= 1 << exti;
+}
+
+void digital_init(void) {
+ init_exti(2, 1);
+ init_exti(4, 2);
+ init_exti(5, 2);
+ init_exti(7, 0);
+ init_exti(8, 1);
+ init_exti(9, 1);
+ init_exti(10, 1);
+ init_exti(11, 0);
+ init_exti(12, 0);
+ init_exti(13, 2);
+ init_exti(14, 2);
+ init_exti(15, 2);
+
+ NVIC_SetPriority(EXTI2_IRQn, 1);
+ NVIC_EnableIRQ(EXTI2_IRQn);
+ NVIC_SetPriority(EXTI4_IRQn, 1);
+ NVIC_EnableIRQ(EXTI4_IRQn);
+ NVIC_SetPriority(EXTI9_5_IRQn, 1);
+ NVIC_EnableIRQ(EXTI9_5_IRQn);
+ NVIC_SetPriority(EXTI15_10_IRQn, 1);
+ NVIC_EnableIRQ(EXTI15_10_IRQn);
+}
diff --git a/bbb_cape/src/cape/digital.h b/bbb_cape/src/cape/digital.h
new file mode 100644
index 0000000..4905c23
--- /dev/null
+++ b/bbb_cape/src/cape/digital.h
@@ -0,0 +1,47 @@
+#ifndef CAPE_DIGITAL_H_
+#define CAPE_DIGITAL_H_
+
+#include <STM32F2XX.h>
+
+void digital_init(void);
+
+static inline int digital_read(int num) {
+ switch (num) {
+ case 0:
+ return GPIOC->IDR & (1 << 4);
+ case 1:
+ return GPIOC->IDR & (1 << 5);
+ case 2:
+ return GPIOC->IDR & (1 << 13);
+ case 3:
+ return GPIOC->IDR & (1 << 14);
+ case 4:
+ return GPIOC->IDR & (1 << 15);
+ case 5:
+ return GPIOB->IDR & (1 << 10);
+ case 6:
+ return GPIOB->IDR & (1 << 9);
+ case 7:
+ return GPIOB->IDR & (1 << 8);
+ case 8:
+ return GPIOA->IDR & (1 << 12);
+ case 9:
+ return GPIOA->IDR & (1 << 11);
+ case 10:
+ return GPIOA->IDR & (1 << 7);
+ case 11:
+ return GPIOB->IDR & (1 << 2);
+ default:
+ return 0;
+ }
+}
+
+// These are the functions for handling edges on the inputs. They have
+// default (weak symbol) implementations that do nothing.
+//void digital_capture_0P(void);
+//void digital_capture_0N(void);
+//void digital_capture_1P(void);
+//void digital_capture_1N(void);
+//...
+
+#endif // CAPE_DIGITAL_H_
diff --git a/bbb_cape/src/cape/encoder.c b/bbb_cape/src/cape/encoder.c
index 45b7d16..31374db 100644
--- a/bbb_cape/src/cape/encoder.c
+++ b/bbb_cape/src/cape/encoder.c
@@ -19,8 +19,8 @@
// 1.A
void EXTI0_IRQHandler(void) {
- EXTI->PR = EXTI_PR_PR0;
uint32_t inputs = GPIOA->IDR;
+ EXTI->PR = EXTI_PR_PR0;
// This looks like a weird way to XOR the 2 inputs, but it compiles down to
// just 2 instructions, which is hard to beat.
if (((inputs >> 1) ^ inputs) & (1 << 0)) {
@@ -32,8 +32,8 @@
// 1.B
void EXTI1_IRQHandler(void) {
- EXTI->PR = EXTI_PR_PR1;
uint32_t inputs = GPIOA->IDR;
+ EXTI->PR = EXTI_PR_PR1;
if (((inputs >> 1) ^ inputs) & (1 << 0)) {
--encoder1_value;
} else {
@@ -42,9 +42,9 @@
}
// 3.A
-void EXTI2_IRQHandler(void) {
- EXTI->PR = EXTI_PR_PR2;
+void TIM1_TRG_COM_TIM11_IRQHandler(void) {
uint32_t inputs = GPIOC->IDR;
+ TIM9->SR = TIM_SR_CC1IF;
if (((inputs >> 1) ^ inputs) & (1 << 2)) {
++encoder3_value;
} else {
@@ -54,8 +54,8 @@
// 3.B
void EXTI3_IRQHandler(void) {
- EXTI->PR = EXTI_PR_PR3;
uint32_t inputs = GPIOC->IDR;
+ EXTI->PR = EXTI_PR_PR3;
if (((inputs >> 1) ^ inputs) & (1 << 2)) {
--encoder3_value;
} else {
@@ -64,7 +64,9 @@
}
static void encoder_setup(TIM_TypeDef *timer) {
- timer->CR1 = TIM_CR1_UDIS;
+ timer->CR1 = TIM_CR1_UDIS /* wait until we tell it to do anything */ |
+ TIM_CR1_URS /* don't generate spurious update interrupts that
+ might be shared with other timers */;
timer->SMCR = 3; // 4x quadrature encoder mode
timer->CCMR1 =
TIM_CCMR1_CC2S_0 | /* input pin 2 -> timer input 2 */
@@ -74,19 +76,28 @@
}
void encoder_init(void) {
- SYSCFG->EXTICR[0] =
- SYSCFG_EXTICR1_EXTI0_PC |
- SYSCFG_EXTICR1_EXTI1_PC |
- SYSCFG_EXTICR1_EXTI2_PA |
- SYSCFG_EXTICR1_EXTI3_PA;
- EXTI->IMR |= EXTI_IMR_MR0 | EXTI_IMR_MR1 | EXTI_IMR_MR2 | EXTI_IMR_MR3;
- EXTI->RTSR |= EXTI_RTSR_TR0 | EXTI_RTSR_TR1 | EXTI_RTSR_TR2 | EXTI_RTSR_TR3;
- EXTI->FTSR |= EXTI_FTSR_TR0 | EXTI_FTSR_TR1 | EXTI_FTSR_TR2 | EXTI_FTSR_TR3;
+ // Set up the 3 simple software encoder inputs.
+ EXTI_set(0, 2);
+ EXTI_set(1, 2);
+ EXTI_set(3, 0);
+ EXTI->IMR |= EXTI_IMR_MR0 | EXTI_IMR_MR1 | EXTI_IMR_MR3;
+ EXTI->RTSR |= EXTI_RTSR_TR0 | EXTI_RTSR_TR1 | EXTI_RTSR_TR3;
+ EXTI->FTSR |= EXTI_FTSR_TR0 | EXTI_FTSR_TR1 | EXTI_FTSR_TR3;
NVIC_EnableIRQ(EXTI0_IRQn);
NVIC_EnableIRQ(EXTI1_IRQn);
- NVIC_EnableIRQ(EXTI2_IRQn);
NVIC_EnableIRQ(EXTI3_IRQn);
+ // Set up the A2 software encoder input through TIM9.
+ gpio_setup_alt(GPIOA, 2, 3);
+ RCC->APB2ENR |= RCC_APB2ENR_TIM9EN;
+ TIM9->CR1 = TIM_CR1_UDIS;
+ TIM9->DIER = TIM_DIER_CC1IE;
+ TIM9->CCMR1 = TIM_CCMR1_CC1S_0; /* input pin 1 -> timer input 1 */
+ TIM9->CCER = TIM_CCER_CC1NP | TIM_CCER_CC1P | TIM_CCER_CC1E;
+ TIM9->EGR = TIM_EGR_UG;
+ TIM9->CR1 |= TIM_CR1_CEN;
+ NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);
+
gpio_setup_alt(GPIOA, 8, 1);
gpio_setup_alt(GPIOB, 0, 1);
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
diff --git a/bbb_cape/src/cape/fill_packet.c b/bbb_cape/src/cape/fill_packet.c
index b525c2f..700df1d 100644
--- a/bbb_cape/src/cape/fill_packet.c
+++ b/bbb_cape/src/cape/fill_packet.c
@@ -14,6 +14,7 @@
#include "cape/led.h"
#include "cape/analog.h"
#include "cape/robot.h"
+#include "cape/digital.h"
#define TIMESTAMP_TIM TIM6
#define RCC_APB1ENR_TIMESTAMP_TIMEN RCC_APB1ENR_TIM6EN
@@ -76,6 +77,7 @@
analog_init();
encoder_init();
gyro_init();
+ digital_init();
uint8_t *flash_end = &__etext + (&__data_start__ - &__data_end__) + 8;
flash_checksum = crc_calculate((void *)MAIN_FLASH_START,
diff --git a/bbb_cape/src/cape/hardware.notes b/bbb_cape/src/cape/hardware.notes
index 05b0dfe..73593b6 100644
--- a/bbb_cape/src/cape/hardware.notes
+++ b/bbb_cape/src/cape/hardware.notes
@@ -56,11 +56,10 @@
[GPIOs]
C0 enc
C1 enc
-A2 enc
+A2 enc (as TIM9.1)
A3 enc
B2
-#A2 TIM9.1
C4
C5
A7
diff --git a/bbb_cape/src/cape/peripherial_usage.notes b/bbb_cape/src/cape/peripherial_usage.notes
index 987113e..5980be0 100644
--- a/bbb_cape/src/cape/peripherial_usage.notes
+++ b/bbb_cape/src/cape/peripherial_usage.notes
@@ -32,9 +32,15 @@
[encoders]
encoder
TIM1,TIM2,TIM3,TIM4,TIM5,TIM8
- EXTI0,EXTI1,EXTI2,EXTI3
- EXTI0_IRQ:0,EXTI1_IRQ:0,EXTI2_IRQ:0,EXTI3_IRQ:0
+ EXTI0,EXTI1,EXTI3
+ EXTI0_IRQ:0,EXTI1_IRQ:0,EXTI3_IRQ:0
+ TIM9 (for its input capture 1)
+ TIM9_IRQ:0 (aka TIM1_BRK)
+[digital inputs]
+digital
+ EXTI2,EXTI4-15
+ EXTI2_IRQ:1,EXTI4-15_IRQ:1
[sensor packet sending]
fill_packet
diff --git a/bbb_cape/src/cape/util.h b/bbb_cape/src/cape/util.h
index 893c95b..02e72fb 100644
--- a/bbb_cape/src/cape/util.h
+++ b/bbb_cape/src/cape/util.h
@@ -13,6 +13,14 @@
__asm__ __volatile__("" ::: "memory");
}
+// Count leading zeros.
+// Returns 0 if bit 31 is set etc.
+__attribute__((always_inline)) static __INLINE uint32_t __clz(uint32_t value) {
+ uint32_t result;
+ __asm__("clz %0, %1" : "=r" (result) : "r" (value));
+ return result;
+}
+
// Sets number_of_bits (shifted left shift number of slots) to value in
// variable.
// This means that the total shift is number_bits*shift.
@@ -43,4 +51,10 @@
SET_BITS(port->OSPEEDR, 2, speed, pin);
}
+// exti is which EXTI line to set
+// port is 0 for A, 1 for B, etc
+static inline void EXTI_set(int exti, int port) {
+ SET_BITS(SYSCFG->EXTICR[exti / 4], 4, port, exti % 4);
+}
+
#endif // CAPE_UTIL_H_