Cycle timing is fixed again
This commit is contained in:
parent
a1eff91d77
commit
1c58250425
1 changed files with 76 additions and 54 deletions
130
fw/main.c
130
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;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue