got the gyro and adc (I think) working
diff --git a/bbb_cape/src/cape/Makefile b/bbb_cape/src/cape/Makefile
index 39aa3aa..18fb048 100644
--- a/bbb_cape/src/cape/Makefile
+++ b/bbb_cape/src/cape/Makefile
@@ -41,6 +41,7 @@
led \
analog \
digital \
+ util \
OBJECTS_bootloader := bootloader \
uart_common \
@@ -49,7 +50,6 @@
OBJECTS_main_test := $(OBJECTS_main_common) \
robot_test \
- uart_byte \
OUTPUTS := main_test bootloader
diff --git a/bbb_cape/src/cape/analog.c b/bbb_cape/src/cape/analog.c
index 7345916..8ad047d 100644
--- a/bbb_cape/src/cape/analog.c
+++ b/bbb_cape/src/cape/analog.c
@@ -29,7 +29,7 @@
// (100ns+8ns)*120MHz = 12.96
// Clear the CSEL pin to select it.
- for (int i = 0; i < 9; ++i) CSEL_GPIO->BSRRL = 1 << CSEL_NUM;
+ for (int i = 0; i < 9; ++i) gpio_off(CSEL_GPIO, CSEL_NUM);
current_channel = channel;
uint16_t data = 1 << 8 /* start bit */ |
0 << 7 /* not differential */ |
@@ -44,7 +44,7 @@
// Masking off the high bits is important because there's nothing driving
// the MISO line during the time the MCU receives them.
analog_readings[current_channel] = value & 0x3FF;
- CSEL_GPIO->BSRRH = 1 << CSEL_NUM;
+ gpio_on(CSEL_GPIO, CSEL_NUM);
TIM->CR1 = TIM_CR1_OPM;
TIM->EGR = TIM_EGR_UG;
@@ -65,7 +65,7 @@
RCC->APB1ENR |= RCC_APB1ENR_TIMEN;
gpio_setup_out(CSEL_GPIO, CSEL_NUM, 3);
- CSEL_GPIO->BSRRH = 1 << CSEL_NUM; // make sure it's deselected
+ gpio_on(CSEL_GPIO, CSEL_NUM); // deselect it
gpio_setup_alt(GPIOB, 13, 5); // SCK
gpio_setup_alt(GPIOB, 14, 5); // MISO
diff --git a/bbb_cape/src/cape/fill_packet.c b/bbb_cape/src/cape/fill_packet.c
index 32e59a3..d2dc01e 100644
--- a/bbb_cape/src/cape/fill_packet.c
+++ b/bbb_cape/src/cape/fill_packet.c
@@ -87,7 +87,7 @@
(size_t)(flash_end - MAIN_FLASH_START) / 4);
led_set(LED_ERR, 0);
- //gyro_init();
+ gyro_init();
uart_common_configure(1500000);
uart_dma_configure(DATA_STRUCT_SEND_SIZE, buffer1, buffer2);
diff --git a/bbb_cape/src/cape/gyro.c b/bbb_cape/src/cape/gyro.c
index b565ed8..d650d4b 100644
--- a/bbb_cape/src/cape/gyro.c
+++ b/bbb_cape/src/cape/gyro.c
@@ -32,7 +32,7 @@
// 1 if the latest result is potentially bad and 0 if it's good.
static volatile int bad_reading;
-// 1 if the gyro is bad adn we're not going to get any more readings.
+// 1 if the gyro is bad and we're not going to get any more readings.
static volatile int bad_gyro;
// The new reading waiting for the next timer cycle to be outputted.
static volatile int16_t new_reading;
@@ -98,7 +98,7 @@
// Do it 8 times (9 cycles) to wait for the amount of time the gyro datasheet
// says we need to.
// (1/2/(7.5MHz)+8ns)*120MHz = 8.96
- for (int i = 0; i < 8; ++i) CSEL_GPIO->BSRRL = 1 << CSEL_NUM;
+ for (int i = 0; i < 8; ++i) gpio_off(CSEL_GPIO, CSEL_NUM);
}
// Blocks until there is space to enqueue data.
@@ -128,153 +128,161 @@
return (value >> 1) & 0x7F;
}
-static void process_reading(int16_t reading) {
- switch (state) {
- case STATE_SETUP0:
- if (parity_error) {
- switch_state(STATE_SETUP0, 100);
- } else {
- if (reading != 1) {
- printf("gyro unexpected initial response 0x%"PRIx32"\n", reading);
- // There's a chance that we're retrying because of a parity error
- // previously, so keep going.
- }
- // Wait for it to assert the fault conditions before reading them.
- switch_state(STATE_SETUP1, 50);
- }
- break;
- case STATE_SETUP1:
- if (parity_error) {
- switch_state(STATE_SETUP0, 100);
- } else {
- // Wait for it to clear the fault conditions before reading again.
- switch_state(STATE_SETUP2, 50);
- }
- break;
- case STATE_SETUP2:
- if (parity_error) {
- switch_state(STATE_SETUP0, 100);
- } else {
- // If it's not reporting self test data.
- if (gyro_status(reading) != 2) {
- printf("gyro first value 0x%"PRIx32" not self test data\n", reading);
+static void reading_received(uint32_t reading) {
+ switch (state) {
+ case STATE_SETUP0:
+ if (parity_error) {
switch_state(STATE_SETUP0, 100);
- break;
+ } else {
+ if (reading != 1) {
+ printf("gyro unexpected initial response 0x%" PRIx32 "\n", reading);
+ // There's a chance that we're retrying because of a parity error
+ // previously, so keep going.
+ }
+ // Wait for it to assert the fault conditions before reading them.
+ switch_state(STATE_SETUP1, 50);
}
- // If we don't see all of the errors.
- if (gyro_errors(reading) != 0x7F) {
- printf("gyro self test value 0x%"PRIx32" is bad\n", reading);
- gyro_setup_failed();
- break;
- }
- // Wait for the sequential transfer delay before reading out the last of
- // the self test data.
- switch_state(STATE_SETUP3, 1);
- }
- break;
- case STATE_SETUP3:
- if (parity_error) {
- switch_state(STATE_SETUP0, 100);
- } else {
- // It should still be reporting self test data.
- if (gyro_status(reading) != 2) {
- printf("gyro second value 0x%"PRIx32" not self test data\n", reading);
+ break;
+ case STATE_SETUP1:
+ if (parity_error) {
switch_state(STATE_SETUP0, 100);
- break;
+ } else {
+ // Wait for it to clear the fault conditions before reading again.
+ switch_state(STATE_SETUP2, 50);
}
+ break;
+ case STATE_SETUP2:
+ if (parity_error) {
+ switch_state(STATE_SETUP0, 100);
+ } else {
+ // If it's not reporting self test data.
+ if (gyro_status(reading) != 2) {
+ printf("gyro first value 0x%" PRIx32 " not self test data\n",
+ reading);
+ switch_state(STATE_SETUP0, 100);
+ break;
+ }
+ // If we don't see all of the errors.
+ if (gyro_errors(reading) != 0x7F) {
+ printf("gyro self test value 0x%" PRIx32 " is bad\n", reading);
+ gyro_setup_failed();
+ break;
+ }
+ // Wait for the sequential transfer delay before reading out the last
+ // of
+ // the self test data.
+ switch_state(STATE_SETUP3, 1);
+ }
+ break;
+ case STATE_SETUP3:
+ if (parity_error) {
+ switch_state(STATE_SETUP0, 100);
+ } else {
+ // It should still be reporting self test data.
+ if (gyro_status(reading) != 2) {
+ printf("gyro second value 0x%" PRIx32 " not self test data\n",
+ reading);
+ switch_state(STATE_SETUP0, 100);
+ break;
+ }
- gyro_output.initialized = 1;
- gyro_output.angle = 0;
- gyro_output.last_reading_bad = 1; // until we're started up
- gyro_output.gyro_bad = 0;
- // Start reading values (after the sequential transfer delay).
- switch_state(STATE_READ, 1);
- }
- break;
- case STATE_READ:
- new_reading = reading;
- switch_state(STATE_READ, 1000 / kGyroReadFrequency);
- break;
- }
+ gyro_output.initialized = 1;
+ gyro_output.angle = 0;
+ gyro_output.last_reading_bad = 1; // until we're started up
+ gyro_output.gyro_bad = bad_gyro = 0;
+ // Start reading values (after the sequential transfer delay).
+ switch_state(STATE_READ, 1);
+ }
+ break;
+ case STATE_READ:
+ if (parity_error) {
+ bad_reading = 1;
+ } else {
+ // This check assumes that the sequence bits are all 0, but they should
+ // be
+ // because that's all we send.
+ if (gyro_status(reading) != 1) {
+ uint8_t status = gyro_status(reading);
+ if (status == 0) {
+ printf("gyro says sensor data is bad\n");
+ } else {
+ printf("gyro gave weird status 0x%" PRIx8 "\n", status);
+ }
+ bad_reading = 1;
+ }
+
+ if (gyro_errors(reading) != 0) {
+ uint8_t errors = gyro_errors(reading);
+ if (errors & ~(1 << 1)) {
+ bad_reading = 1;
+ // Error 1 (continuous self-test error) will set status to 0 if it's
+ // bad
+ // enough by itself.
+ }
+ if (errors & (1 << 6)) {
+ printf("gyro PLL error\n");
+ }
+ if (errors & (1 << 5)) {
+ printf("gyro quadrature error\n");
+ }
+ if (errors & (1 << 4)) {
+ printf("gyro non-volatile memory error\n");
+ bad_gyro = 1;
+ }
+ if (errors & (1 << 3)) {
+ printf("gyro volatile memory error\n");
+ bad_gyro = 1;
+ }
+ if (errors & (1 << 2)) {
+ printf("gyro power error\n");
+ }
+ if (errors & (1 << 1)) {
+ printf("gyro continuous self-test error\n");
+ }
+ if (errors & 1) {
+ printf("gyro unexpected self check mode\n");
+ }
+ }
+ if (bad_gyro) {
+ bad_reading = 1;
+ }
+ new_reading = -(int16_t)(reading >> 10 & 0xFFFF);
+ }
+ switch_state(STATE_READ, 1000 / kGyroReadFrequency);
+ break;
+ }
}
-static void reading_received(uint32_t value) {
- if (parity_error) {
- bad_reading = 1;
- } else {
- // This check assumes that the sequence bits are all 0, but they should be
- // because that's all we send.
- if (gyro_status(value) != 1) {
- uint8_t status = gyro_status(value);
- if (status == 0) {
- printf("gyro says sensor data is bad\n");
- } else {
- printf("gyro gave weird status 0x%"PRIx8"\n", status);
- }
- bad_reading = 1;
- }
-
- if (gyro_errors(value) != 0) {
- uint8_t errors = gyro_errors(value);
- if (errors & ~(1 << 1)) {
- bad_reading = 1;
- // Error 1 (continuous self-test error) will set status to 0 if it's bad
- // enough by itself.
- }
- if (errors & (1 << 6)) {
- printf("gyro PLL error\n");
- }
- if (errors & (1 << 5)) {
- printf("gyro quadrature error\n");
- }
- if (errors & (1 << 4)) {
- printf("gyro non-volatile memory error\n");
- bad_gyro = 1;
- }
- if (errors & (1 << 3)) {
- printf("gyro volatile memory error\n");
- bad_gyro = 1;
- }
- if (errors & (1 << 2)) {
- printf("gyro power error\n");
- }
- if (errors & (1 << 1)) {
- printf("gyro continuous self-test error\n");
- }
- if (errors & 1) {
- printf("gyro unexpected self check mode\n");
- }
- }
- if (bad_gyro) {
- bad_reading = 1;
- }
- }
- process_reading(-(int16_t)(value >> 10 & 0xFFFF));
-}
void SPI_IRQHandler(void) {
uint32_t status = SPI->SR;
if (status & SPI_SR_RXNE) {
uint16_t value = SPI->DR;
- if (__builtin_parity(value) != 1) {
- parity_error = 1;
- for (int i = -2; i < 16; ++i) {
- led_set(LED_Z, i < 0);
- for (int ii = 0; ii < 1000000; ++ii) {
- led_set(LED_ERR, i >= 0 && ii < 500000);
- if (i >= 0) led_set(LED_DB, value & (1 << i));
- else led_set(LED_DB, 0);
- }
- }
- }
if (receive_byte == 0) {
receive_byte = 1;
- high_value = value;
+
+ if (__builtin_parity(value) != 1) {
+ parity_error = 1;
+ high_value = 0;
+ } else {
+ high_value = value;
+ }
} else {
uint32_t full_value = high_value << 16 | value;
+ if (__builtin_parity(full_value) != 1) {
+ parity_error = 1;
+ }
+
+ // We have to wait for the hardware to finish sending all the bits first.
+ while (SPI->SR & SPI_SR_BSY) {}
+ // Do it 8 times (9 cycles) to wait for the amount of time the gyro datasheet
+ // says we need to.
+ // (1/2/(7.5MHz)+8ns)*120MHz = 8.96
+ for (int i = 0; i < 8; ++i) gpio_off(CSEL_GPIO, CSEL_NUM);
+
// Set the CSEL pin high to deselect it.
- // The parity calculation etc took long enough that this is safe now.
- CSEL_GPIO->BSRRH = 1 << CSEL_NUM;
+ gpio_on(CSEL_GPIO, CSEL_NUM);
+
reading_received(full_value);
}
}
@@ -370,10 +378,8 @@
RCC->APB1ENR |= RCC_APB1ENR_TIMEN;
// Set up CSEL.
- // It's is just a GPIO pin because we're the master (it would be special if we
- // were a slave).
gpio_setup_out(CSEL_GPIO, CSEL_NUM, 3);
- CSEL_GPIO->BSRRH = 1 << CSEL_NUM; // make sure it's deselected
+ gpio_on(CSEL_GPIO, CSEL_NUM); // deselect it
// Set up SCK, MISO, and MOSI.
gpio_setup_alt(GPIOC, 10, 6); // SCK
@@ -390,6 +396,7 @@
TIM->CCMR1 = 0;
// Make it generate 1 tick every ms.
TIM->PSC = 60000 - 1;
+ TIM->EGR = TIM_EGR_UG;
SPI->CR1 = 0; // make sure it's disabled
SPI->CR1 =
@@ -401,5 +408,6 @@
SPI->CR1 |= SPI_CR1_SPE; // enable it
setup_counter = 0;
+ led_set(LED_Z, 1);
switch_state(STATE_SETUP0, 100);
}
diff --git a/bbb_cape/src/cape/gyro.h b/bbb_cape/src/cape/gyro.h
index 1536718..5af74e9 100644
--- a/bbb_cape/src/cape/gyro.h
+++ b/bbb_cape/src/cape/gyro.h
@@ -22,9 +22,9 @@
// Must be called from a lower-priority ISR than TIM10's.
static inline void gyro_get_output(struct GyroOutput *output) {
extern struct GyroOutput gyro_output;
- NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn);
+ NVIC_DisableIRQ(TIM8_UP_TIM13_IRQn);
memcpy(output, &gyro_output, sizeof(gyro_output));
- NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
+ NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn);
}
#endif // GYRO_BOARD_SRC_USB_GYRO_H_
diff --git a/bbb_cape/src/cape/led.c b/bbb_cape/src/cape/led.c
index 97d5a06..92edaf1 100644
--- a/bbb_cape/src/cape/led.c
+++ b/bbb_cape/src/cape/led.c
@@ -12,10 +12,12 @@
// ERR = PB11
static void do_led_set(GPIO_TypeDef *port, int number, int on) {
+ // The LEDs are hooked up between 3.3V and the GPIO pin, so these are
+ // backwards.
if (on) {
- port->BSRRH = 1 << number;
+ gpio_off(port, number);
} else {
- port->BSRRL = 1 << number;
+ gpio_on(port, number);
}
}
diff --git a/bbb_cape/src/cape/uart_common.c b/bbb_cape/src/cape/uart_common.c
index 3b8cd9a..03d4cdd 100644
--- a/bbb_cape/src/cape/uart_common.c
+++ b/bbb_cape/src/cape/uart_common.c
@@ -11,7 +11,6 @@
void uart_common_configure(int baud) {
gpio_setup_alt(GPIOA, 9, 7);
gpio_setup_alt(GPIOA, 10, 7);
- GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9; // we want to go FAST!
RCC->APB2ENR |= RCC_APB2ENR_UARTEN;
// baud = 60MHz / kMultiplier * (whole_part + fraction / kMultiplier))
diff --git a/bbb_cape/src/cape/util.c b/bbb_cape/src/cape/util.c
new file mode 100644
index 0000000..4f2d9e1
--- /dev/null
+++ b/bbb_cape/src/cape/util.c
@@ -0,0 +1,17 @@
+#include "cape/util.h"
+
+#include "cape/led.h"
+
+void led_write(uint32_t value, int bits) {
+ for (int i = -2; i < bits; ++i) {
+ led_set(LED_Z, i < 0);
+ for (int ii = 0; ii < 1000000; ++ii) {
+ led_set(LED_ERR, i >= 0 && ii < 500000);
+ if (i >= 0) {
+ led_set(LED_DB, value & (1 << i));
+ } else {
+ led_set(LED_DB, 0);
+ }
+ }
+ }
+}
diff --git a/bbb_cape/src/cape/util.h b/bbb_cape/src/cape/util.h
index 02e72fb..d19a7e9 100644
--- a/bbb_cape/src/cape/util.h
+++ b/bbb_cape/src/cape/util.h
@@ -1,6 +1,8 @@
#ifndef CAPE_UTIL_H_
#define CAPE_UTIL_H_
+#include <stdint.h>
+
#include <STM32F2XX.h>
#define ALIAS_WEAK(f) __attribute__ ((weak, alias (#f)))
@@ -51,10 +53,24 @@
SET_BITS(port->OSPEEDR, 2, speed, pin);
}
+static inline void gpio_setup_in(GPIO_TypeDef *port, int pin) {
+ SET_BITS(port->MODER, 2, 0 /* input */, 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);
}
+static inline void gpio_on(GPIO_TypeDef *port, int pin) {
+ port->BSRRL = 1 << pin;
+}
+
+static inline void gpio_off(GPIO_TypeDef *port, int pin) {
+ port->BSRRH = 1 << pin;
+}
+
+void led_write(uint32_t value, int bits);
+
#endif // CAPE_UTIL_H_