diff options
Diffstat (limited to 'fw')
-rw-r--r-- | fw/main.c | 130 |
1 files changed, 76 insertions, 54 deletions
@@ -99,7 +99,7 @@ volatile unsigned int sys_time_seconds = 0; volatile struct framebuf fb[2] = {0}; volatile struct framebuf *read_fb=fb+0, *write_fb=fb+1; volatile int led_state = 0; -volatile enum { FB_WRITE, FB_UPDATE } fb_op = FB_WRITE; +volatile enum { FB_WRITE, FB_FORMAT, FB_UPDATE } fb_op; volatile union { struct __attribute__((packed)) { struct framebuf fb; uint8_t end[0]; } set_fb_rq; struct __attribute__((packed)) { uint8_t nbits; uint8_t end[0]; } set_nbits_rq; @@ -174,6 +174,7 @@ void cfg_spi1() { } void SPI1_IRQHandler() { + GPIOA->BSRR = GPIO_BSRR_BS_0; // Debug switch (spi_state) { case SPI_AUX: strobe_aux(); @@ -190,6 +191,7 @@ void SPI1_IRQHandler() { break; } spi_state ++; + GPIOA->BSRR = GPIO_BSRR_BR_0; // Debug } uint8_t segment_map[8] = {5, 7, 6, 4, 1, 3, 0, 2}; @@ -234,19 +236,62 @@ int shift_data() { } SPI1->CR2 |= SPI_CR2_TXEIE; - return 1<<active_bit; + return active_bit; } +#define NBITS_MAX 14 + +/* Bit timing base value. This is the lowes bit interval used */ +#define PERIOD_BASE 4 + +/* This value is a constant offset added to every bit period to allow for the timer IRQ handler to execute. This is set + * empirically using a debugger and a logic analyzer. */ +#define TIMER_CYCLES_FOR_SPI_TRANSMISSIONS 25 + +/* Defines for brevity */ +#define A TIMER_CYCLES_FOR_SPI_TRANSMISSIONS +#define B PERIOD_BASE + +/* This is a constant offset containing some empirically determined correction values */ +#define C (0) + +/* This lookup table maps bit positions to timer period values. This is a lookup table to allow for the compensation for + * non-linear effects of ringing at lower bit durations. + */ +static uint16_t timer_period_lookup[NBITS_MAX] = { + /* LSB here */ + A - C + (B<< 0), + A - C + (B<< 1), + A - C + (B<< 2), + A - C + (B<< 3), + A - C + (B<< 4), + A - C + (B<< 5), + A - C + (B<< 6), + A - C + (B<< 7), + A - C + (B<< 8), + A - C + (B<< 9), + A - C + (B<<10), + A - C + (B<<11), + A - C + (B<<12), + A - C + (B<<13), + /* MSB here */ +}; + +/* Don't pollute the global namespace */ +#undef A +#undef B +#undef C + void cfg_timer3() { + /* FIXME update comment */ /* Capture/compare channel 1 is used to generate the LED driver !OE signal. Channel 2 is used to trigger the * interrupt to load the next bits in to the shift registers. Channel 2 triggers simultaneously with channel 1 at * long !OE periods but will be delayed slightly to a fixed 32 timer periods (12.8us) to allow for SPI1 to finish * shifting out all frame data before asserting !OE. */ - TIM3->CCMR1 = 6<<TIM_CCMR1_OC1M_Pos; /* PWM Mode 1 */ - TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P | TIM_CCER_CC2E | TIM_CCER_CC2P; /* Inverting output */ - TIM3->DIER = TIM_DIER_CC2IE; - TIM3->CCR2 = 1000; /* Schedule first interrupt */ - TIM3->PSC = SystemCoreClock/5000000 * 2; /* 0.40us/tick */ + TIM3->CCMR1 = (6<<TIM_CCMR1_OC1M_Pos) | TIM_CCMR1_OC1PE; /* PWM Mode 1, enable CCR preload */ + TIM3->CCER = TIM_CCER_CC1E; /* Inverting output */ + TIM3->DIER = TIM_DIER_UIE; + TIM3->PSC = SystemCoreClock/5000000 * 2 - 1; /* 0.20us/tick */ TIM3->ARR = 0xffff; TIM3->EGR |= TIM_EGR_UG; TIM3->CR1 = TIM_CR1_ARPE; @@ -256,18 +301,16 @@ void cfg_timer3() { } void TIM3_IRQHandler() { + GPIOA->BSRR = GPIO_BSRR_BS_4; // Debug //TIM3->CR1 &= ~TIM_CR1_CEN_Msk; FIXME - int period = shift_data(); - TIM3->CCR1 = period; - if (period < 32) /* FIXME this constant */ - TIM3->CCR2 = 32; - else - TIM3->CCR2 = period; - TIM3->CNT = 0xffff; /* To not enable OC1 riglt away */ + int idx = shift_data(); + TIM3->CCR1 = TIMER_CYCLES_FOR_SPI_TRANSMISSIONS; + TIM3->ARR = timer_period_lookup[idx]; - TIM3->SR &= ~TIM_SR_CC2IF_Msk; + TIM3->SR &= ~TIM_SR_UIF_Msk; //TIM3->CR1 |= TIM_CR1_CEN; + GPIOA->BSRR = GPIO_BSRR_BR_4; // Debug } enum Command { @@ -300,14 +343,13 @@ void uart_config(void) { | USART_CR1_MME /* WAKE clear */ /* PCE, PS clear */ - //| USART_CR1_RXNEIE + | USART_CR1_RXNEIE /* other interrupts clear */ | USART_CR1_TE | USART_CR1_RE; //USART1->CR2 = USART_CR2_RTOEN; /* Timeout enable */ - USART1->CR3 = USART_CR3_DEM; /* RS485 DE enable (output on RTS) */ - //| USART_CR3_DMAT; - /* Baud rate 2MBd */ + USART1->CR3 = USART_CR3_DEM /* RS485 DE enable (output on RTS) */ + | USART_CR3_DMAT; int usartdiv = 25; USART1->BRR = usartdiv; USART1->CR1 |= USART_CR1_UE; @@ -380,9 +422,11 @@ int main(void) { RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; GPIOA->MODER |= - (2<<GPIO_MODER_MODER1_Pos) /* PA1 - RS485 DE */ + (1<<GPIO_MODER_MODER0_Pos) /* PA0 - Debug */ + | (2<<GPIO_MODER_MODER1_Pos) /* PA1 - RS485 DE */ | (2<<GPIO_MODER_MODER2_Pos) /* PA2 - RS485 TX */ | (2<<GPIO_MODER_MODER3_Pos) /* PA3 - RS485 RX */ + | (1<<GPIO_MODER_MODER4_Pos) /* PA3 - Debug */ | (2<<GPIO_MODER_MODER5_Pos) /* PA5 - SCLK */ | (2<<GPIO_MODER_MODER6_Pos) /* PA6 - LED !OE */ | (2<<GPIO_MODER_MODER7_Pos) /* PA7 - MOSI */ @@ -391,9 +435,11 @@ int main(void) { /* Set shift register IO GPIO output speed */ GPIOA->OSPEEDR |= - (2<<GPIO_OSPEEDR_OSPEEDR1_Pos) /* RS485 DE */ + (2<<GPIO_OSPEEDR_OSPEEDR0_Pos) /* Debug */ + | (2<<GPIO_OSPEEDR_OSPEEDR1_Pos) /* RS485 DE */ | (2<<GPIO_OSPEEDR_OSPEEDR2_Pos) /* TX */ | (2<<GPIO_OSPEEDR_OSPEEDR3_Pos) /* RX */ + | (2<<GPIO_OSPEEDR_OSPEEDR4_Pos) /* Debug */ | (2<<GPIO_OSPEEDR_OSPEEDR5_Pos) /* SCLK */ | (2<<GPIO_OSPEEDR_OSPEEDR6_Pos) /* LED !OE */ | (2<<GPIO_OSPEEDR_OSPEEDR7_Pos) /* MOSI */ @@ -424,43 +470,19 @@ int main(void) { cfg_timer3(); SysTick_Config(SystemCoreClock/1000); /* 1ms interval */ uart_config(); - //adc_config(); + adc_config(); - int rx_idx = 0; - int expect_framing = 1; - uint8_t data; - unsigned int num_overrun_errors = 0; - /* FIXME document framing/rx state machine */ + volatile uint8_t *rxd = rx_buf.byte_data; while (42) { - if (USART1->ISR & USART_ISR_ORE) { - USART1->ICR |= USART_ICR_ORECF; - num_overrun_errors ++; - } else if (USART1->ISR & USART_ISR_FE) { - USART1->ICR |= USART_ICR_FECF; - } else if (USART1->ISR & USART_ISR_RXNE) { - data = USART1->RDR; - /* - if (expect_framing) { - if (data == 0x42) { - expect_framing = 0; - } else { - rx_idx = 0; - } - } else { - rx_buf.byte_data[rx_idx] = data; - rx_idx++; - if (rx_idx >= sizeof(rx_buf.set_fb_rq)) { - rx_idx = 0; - if (fb_op == FB_WRITE) { - transpose_data(rx_buf.byte_data, write_fb); - fb_op = FB_UPDATE; - } - } - if ((rx_idx&0x1F) == 0) { - expect_framing = 1; + if (USART1->ISR & USART_ISR_RXNE) { + *rxd++ = USART1->RDR; + if (rxd >= rx_buf.set_fb_rq.end) { + rxd = rx_buf.byte_data; + if (fb_op == FB_FORMAT) { + transpose_data(rx_buf.byte_data, write_fb); + fb_op = FB_UPDATE; } } - */ } } } |