aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fw/main.c130
1 files changed, 76 insertions, 54 deletions
diff --git a/fw/main.c b/fw/main.c
index d40dbff..0aa7c32 100644
--- a/fw/main.c
+++ b/fw/main.c
@@ -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;
}
}
- */
}
}
}