summaryrefslogtreecommitdiff
path: root/controller/fw/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'controller/fw/src/main.c')
-rw-r--r--controller/fw/src/main.c143
1 files changed, 119 insertions, 24 deletions
diff --git a/controller/fw/src/main.c b/controller/fw/src/main.c
index 3131df1..58977f7 100644
--- a/controller/fw/src/main.c
+++ b/controller/fw/src/main.c
@@ -1,45 +1,126 @@
#include <stdbool.h>
+#include <stdint.h>
+#include <assert.h>
-#include <libopencm3/stm32/rcc.h>
-#include <libopencm3/stm32/spi.h>
-#include <libopencm3/stm32/gpio.h>
+#include <stm32f407xx.h>
+#include "sr_global.h"
+#include "adc.h"
#include "spi_flash.h"
+#include "freq_meas.h"
+#include "dsss_demod.h"
static struct spi_flash_if spif;
+
+void __libc_init_array(void) { /* we don't need this. */ }
+void __assert_func (unused_a const char *file, unused_a int line, unused_a const char *function, unused_a const char *expr) {
+ asm volatile ("bkpt");
+ while(1) {}
+}
+
static void clock_setup(void)
{
- rcc_clock_setup_pll(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
- rcc_periph_clock_enable(RCC_GPIOA);
- rcc_periph_clock_enable(RCC_GPIOB);
- rcc_periph_clock_enable(RCC_SPI1);
+ /* 8MHz HSE clock as PLL source.
+ *
+ * Divide by 8 -> 1 MHz */
+#define PLL_M 8
+ /* Multiply by 336 -> 336 MHz VCO frequency */
+#define PLL_N 336
+ /* Divide by 2 -> 168 MHz (max freq for our chip) */
+#define PLL_P 2
+ /* Aux clock for USB OTG, SDIO, RNG: divide VCO frequency (336 MHz) by 7 -> 48 MHz (required by USB OTG) */
+#define PLL_Q 7
+
+ RCC->CR |= RCC_CR_HSEON;
+ while(!(RCC->CR & RCC_CR_HSERDY));
+
+ RCC->APB1ENR |= RCC_APB1ENR_PWREN;
+
+ /* set voltage scale to 1 for max frequency
+ * (0b0) scale 2 for fCLK <= 144 Mhz
+ * (0b1) scale 1 for 144 Mhz < fCLK <= 168 Mhz
+ */
+ PWR->CR |= PWR_CR_VOS;
+
+ /* set AHB prescaler to /1 (CFGR:bits 7:4) */
+ RCC->CFGR |= (0 << RCC_CFGR_HPRE_Pos);
+ /* set ABP1 prescaler to 4 */
+ RCC->CFGR |= (5 << RCC_CFGR_PPRE1_Pos);
+ /* set ABP2 prescaler to 2 */
+ RCC->CFGR |= (0x4 << RCC_CFGR_PPRE2_Pos);
+
+ /* Configure PLL */
+ static_assert(PLL_P % 2 == 0);
+ static_assert(PLL_P >= 2 && PLL_P <= 8);
+ static_assert(PLL_N >= 50 && PLL_N <= 432);
+ static_assert(PLL_M >= 2 && PLL_M <= 63);
+ static_assert(PLL_Q >= 2 && PLL_Q <= 15);
+ RCC->PLLCFGR = (PLL_M<<RCC_PLLCFGR_PLLM_Pos)
+ | (PLL_N << RCC_PLLCFGR_PLLM_Pos)
+ | ((PLL_P/2 - 1) << RCC_PLLCFGR_PLLP_Pos)
+ | (PLL_Q << RCC_PLLCFGR_PLLQ_Pos)
+ | RCC_PLLCFGR_PLLSRC; /* select HSE as PLL source */
+ RCC->CR |= RCC_CR_PLLON;
+
+ /* Wait for main PLL */
+ while(!(RCC->CR & RCC_CR_PLLRDY))
+ ;
+
+ /* Configure Flash: enable prefetch, insn cache, data cache; set latency = 5 wait states
+ * See reference manual (RM0090), Section 3.5.1, Table 10 (p. 80)
+ */
+ FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | (5<<FLASH_ACR_LATENCY);
+
+ /* Select PLL as system clock source */
+ RCC->CFGR &= ~RCC_CFGR_SW_Msk;
+ RCC->CFGR |= 2 << RCC_CFGR_SW_Pos;
+
+ /* Wait for clock to switch over */
+ while ((RCC->CFGR & RCC_CFGR_SWS_Msk)>>RCC_CFGR_SWS_Pos != 2)
+ ;
}
static void led_setup(void)
{
- gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO6 | GPIO7);
+ GPIOA->MODER |= (1<<GPIO_MODER_MODER6_Pos) | (1<<GPIO_MODER_MODER7_Pos);
}
static void spi_flash_if_set_cs(bool val) {
if (val)
- gpio_set(GPIOB, GPIO0);
+ GPIOB->BSRR = 1<<0;
else
- gpio_clear(GPIOB, GPIO0);
+ GPIOB->BSRR = 1<<16;
}
static void spi_flash_setup(void)
{
- gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO3 | GPIO4 | GPIO5); /* SPI flash SCK/MISO/MOSI */
- gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO0); /* SPI flash CS */
- gpio_set_output_options(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO0 | GPIO3 | GPIO4 | GPIO5);
- gpio_set_af(GPIOB, 5, GPIO3 | GPIO4 | GPIO5);
+ GPIOB->MODER &= ~GPIO_MODER_MODER3_Msk & ~GPIO_MODER_MODER4_Msk & ~GPIO_MODER_MODER5_Msk & ~GPIO_MODER_MODER0_Msk;
+ GPIOB->MODER |= (2<<GPIO_MODER_MODER3_Pos) /* SCK */
+ | (2<<GPIO_MODER_MODER4_Pos) /* MISO */
+ | (2<<GPIO_MODER_MODER5_Pos) /* MOSI */
+ | (1<<GPIO_MODER_MODER0_Pos); /* CS */
+
+ GPIOB->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED3_Msk & ~GPIO_OSPEEDR_OSPEED4_Msk
+ & ~GPIO_OSPEEDR_OSPEED5_Msk & ~GPIO_OSPEEDR_OSPEED0_Msk;
+ GPIOB->OSPEEDR |= (2<<GPIO_OSPEEDR_OSPEED3_Pos) /* SCK */
+ | (2<<GPIO_OSPEEDR_OSPEED4_Pos) /* MISO */
+ | (2<<GPIO_OSPEEDR_OSPEED5_Pos) /* MOSI */
+ | (2<<GPIO_OSPEEDR_OSPEED0_Pos); /* CS */
+
+ GPIOB->AFR[0] &= ~GPIO_AFRL_AFSEL3_Msk & ~GPIO_AFRL_AFSEL4_Msk & ~GPIO_AFRL_AFSEL5_Msk;
+ GPIOB->AFR[0] |= (5<<GPIO_AFRL_AFSEL3_Pos) | (5<<GPIO_AFRL_AFSEL4_Pos) | (5<<GPIO_AFRL_AFSEL5_Pos);
+
+ RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
+ RCC->APB2RSTR |= RCC_APB2RSTR_SPI1RST;
+ RCC->APB2RSTR &= RCC_APB2RSTR_SPI1RST;
spif_init(&spif, 256, SPI1, &spi_flash_if_set_cs);
}
-/*
+/* SPI flash test routine to be called from gdb */
+#ifdef SPI_FLASH_TEST
void spi_flash_test(void) {
spif_clear_mem(&spif);
@@ -48,7 +129,7 @@ void spi_flash_test(void) {
for (size_t i=0; i<sizeof(buf); i+= sizeof(buf[0]))
buf[i/sizeof(buf[0])] = addr + i;
- spif_write(&spif, addr, sizeof(buf), (char *)buf);
+ spif_write(&spif, addr, sizeof(buf), (char *)buf);
}
for (size_t i=0; i<sizeof(buf)/sizeof(buf[0]); i++)
@@ -56,21 +137,35 @@ void spi_flash_test(void) {
spif_read(&spif, 0x1030, sizeof(buf), (char *)buf);
asm volatile ("bkpt");
}
-*/
+#endif
+
+static unsigned int measurement_errors = 0;
+static struct dsss_demod_state demod_state;
+static uint32_t freq_sample_ts = 0;
int main(void)
{
clock_setup();
led_setup();
spi_flash_setup();
-
- gpio_set(GPIOA, GPIO6);
-
- while (1) {
- gpio_toggle(GPIOA, GPIO6 | GPIO7);
- for (int i = 0; i < 6000000; i++)
- __asm__("nop");
+ adc_init();
+
+ while (23) {
+ if (adc_fft_buf_ready_idx != -1) {
+ float out;
+ if (adc_buf_measure_freq(adc_fft_buf[adc_fft_buf_ready_idx], &out)) {
+ measurement_errors++;
+ continue;
+ }
+
+ dsss_demod_init(&demod_state);
+ dsss_demod_step(&demod_state, out, freq_sample_ts);
+
+ freq_sample_ts++; /* TODO: also increase in case of freq measurement error? */
+ adc_fft_buf_ready_idx = -1;
+ }
}
return 0;
}
+