Fixed aux cycle

This commit is contained in:
jaseg 2017-12-09 14:41:58 +01:00
parent 1c58250425
commit d2194c5ae2

105
fw/main.c
View file

@ -141,14 +141,6 @@ unsigned int stk_microseconds(void) {
return sys_time*1000 + (1000 - (SysTick->VAL / (SystemCoreClock/1000000)));
}
enum {
SPI_AUX,
SPI_WORD0,
SPI_WORD1,
SPI_IDLE,
} spi_state;
static volatile uint32_t spi_word = 0;
void cfg_spi1() {
/* Configure SPI controller */
SPI1->I2SCFGR = 0;
@ -156,46 +148,23 @@ void cfg_spi1() {
SPI1->CR2 &= ~SPI_CR2_DS_Msk;
SPI1->CR2 |= LL_SPI_DATAWIDTH_16BIT;
/* Baud rate PCLK/2 -> 25MHz */
/* Baud rate PCLK/4 -> 12.5MHz */
SPI1->CR1 =
SPI_CR1_BIDIMODE
| SPI_CR1_BIDIOE
| SPI_CR1_SSM
| SPI_CR1_SSI
| SPI_CR1_SPE
| (0<<SPI_CR1_BR_Pos)
| (1<<SPI_CR1_BR_Pos)
| SPI_CR1_MSTR
| SPI_CR1_CPOL
| SPI_CR1_CPHA;
/* FIXME maybe try w/o BIDI */
NVIC_EnableIRQ(SPI1_IRQn);
NVIC_SetPriority(SPI1_IRQn, 2);
}
void SPI1_IRQHandler() {
GPIOA->BSRR = GPIO_BSRR_BS_0; // Debug
switch (spi_state) {
case SPI_AUX:
strobe_aux();
SPI1->DR = spi_word>>16;
break;
case SPI_WORD0:
SPI1->DR = spi_word&0xFFFF;
break;
default:
tick(); /* This one is important. Otherwise, weird stuff happens and parts of the aux register seem to leak
into the driver registers. */
strobe_leds();
SPI1->CR2 &= ~SPI_CR2_TXEIE;
break;
}
spi_state ++;
GPIOA->BSRR = GPIO_BSRR_BR_0; // Debug
}
uint8_t segment_map[8] = {5, 7, 6, 4, 1, 3, 0, 2};
static volatile uint32_t aux_reg = 0;
static volatile int frame_duration_us;
volatile int nbits = MAX_BITS;
/* returns new bit time in cycles */
@ -213,9 +182,11 @@ int shift_data() {
if (active_segment == NSEGMENTS) {
active_segment = 0;
/* FIXME remove this?
int time = stk_microseconds();
frame_duration_us = time - last_frame_time;
last_frame_time = time;
*/
if (fb_op == FB_UPDATE) {
volatile struct framebuf *tmp = read_fb;
read_fb = write_fb;
@ -224,17 +195,21 @@ int shift_data() {
}
}
spi_word = read_fb->data[active_bit*FRAME_SIZE_WORDS + active_segment];
spi_state = SPI_AUX;
SPI1->DR = (read_fb->brightness ? SR_ILED_HIGH : SR_ILED_LOW)
| (led_state<<1)
| (0xff00 ^ (0x100<<segment_map[active_segment]));
} else {
spi_word = read_fb->data[active_bit*FRAME_SIZE_WORDS + active_segment];
spi_state = SPI_WORD0;
SPI1->DR = spi_word>>16;
GPIOA->BSRR = GPIO_BSRR_BR_10;
SPI1->DR = aux_reg | segment_map[active_segment];
while (SPI1->SR & SPI_SR_BSY);
GPIOA->BSRR = GPIO_BSRR_BS_10;
}
SPI1->CR2 |= SPI_CR2_TXEIE;
uint32_t spi_word = read_fb->data[active_bit*FRAME_SIZE_WORDS + active_segment];
SPI1->DR = spi_word>>16;
spi_word &= 0xFFFF;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = spi_word;
while (!(SPI1->SR & SPI_SR_TXE));
//tick();
//strobe_leds();
// FIXME SPI1->CR2 |= SPI_CR2_TXEIE;
return active_bit;
}
@ -246,7 +221,9 @@ int shift_data() {
/* 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
#define TIMER_CYCLES_FOR_SPI_TRANSMISSIONS 21
#define TIMER_CYCLES_BEFORE_LED_STROBE 20
/* Defines for brevity */
#define A TIMER_CYCLES_FOR_SPI_TRANSMISSIONS
@ -288,14 +265,29 @@ void cfg_timer3() {
* 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->CR2 = (2<<TIM_CR2_MMS_Pos); /* master mode: update */
TIM3->CCMR1 = (6<<TIM_CCMR1_OC1M_Pos) | TIM_CCMR1_OC1PE; /* PWM Mode 1, enable CCR preload */
TIM3->CCER = TIM_CCER_CC1E; /* Inverting output */
TIM3->CCER = TIM_CCER_CC1E;
TIM3->CCR1 = TIMER_CYCLES_FOR_SPI_TRANSMISSIONS;
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;
TIM3->CR1 |= TIM_CR1_CEN;
TIM1->SR = 0;
TIM1->BDTR = TIM_BDTR_MOE;
TIM1->SMCR = (2<<TIM_SMCR_TS_Pos) | (4<<TIM_SMCR_SMS_Pos); /* Internal Trigger 2 (ITR2) -> TIM3; slave mode: reset */
TIM1->CCMR1 = (6<<TIM_CCMR1_OC2M_Pos) | TIM_CCMR1_OC2PE; /* PWM Mode 1, enable CCR preload */
TIM1->CCER = TIM_CCER_CC2E;
TIM1->CCR2 = TIMER_CYCLES_BEFORE_LED_STROBE;
TIM1->PSC = TIM3->PSC; /* 0.20us/tick */
TIM1->ARR = 0xffff;
TIM1->EGR |= TIM_EGR_UG;
TIM1->CR1 = TIM_CR1_ARPE;
TIM1->CR1 |= TIM_CR1_CEN;
NVIC_EnableIRQ(TIM3_IRQn);
NVIC_SetPriority(TIM3_IRQn, 2);
}
@ -305,7 +297,6 @@ void TIM3_IRQHandler() {
//TIM3->CR1 &= ~TIM_CR1_CEN_Msk; FIXME
int idx = shift_data();
TIM3->CCR1 = TIMER_CYCLES_FOR_SPI_TRANSMISSIONS;
TIM3->ARR = timer_period_lookup[idx];
TIM3->SR &= ~TIM_SR_UIF_Msk;
@ -418,7 +409,7 @@ int main(void) {
SystemCoreClockUpdate();
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_DMAEN | RCC_AHBENR_CRCEN | RCC_AHBENR_FLITFEN;
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_SYSCFGEN | RCC_APB2ENR_ADCEN | RCC_APB2ENR_DBGMCUEN;
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_SYSCFGEN | RCC_APB2ENR_ADCEN | RCC_APB2ENR_DBGMCUEN | RCC_APB2ENR_TIM1EN;
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
GPIOA->MODER |=
@ -430,7 +421,7 @@ int main(void) {
| (2<<GPIO_MODER_MODER5_Pos) /* PA5 - SCLK */
| (2<<GPIO_MODER_MODER6_Pos) /* PA6 - LED !OE */
| (2<<GPIO_MODER_MODER7_Pos) /* PA7 - MOSI */
| (1<<GPIO_MODER_MODER9_Pos) /* PA9 - LED strobe */
| (2<<GPIO_MODER_MODER9_Pos) /* PA9 - LED strobe */
| (1<<GPIO_MODER_MODER10_Pos);/* PA10 - Auxiliary strobe */
/* Set shift register IO GPIO output speed */
@ -453,6 +444,8 @@ int main(void) {
| (0<<GPIO_AFRL_AFRL5_Pos) /* SPI1_SCK */
| (1<<GPIO_AFRL_AFRL6_Pos) /* TIM3_CH1 */
| (0<<GPIO_AFRL_AFRL7_Pos); /* SPI1_MOSI */
GPIOA->AFR[1] |=
(2<<GPIO_AFRH_AFRH1_Pos); /* TIM1_CH2 */
GPIOA->PUPDR |=
(2<<GPIO_PUPDR_PUPDR1_Pos) /* RS485 DE: Pulldown */
@ -461,6 +454,11 @@ int main(void) {
cfg_spi1();
/* Pre-compute aux register values for timer ISR */
for (int i=0; i<sizeof(segment_map)/sizeof(segment_map[0]); i++) {
segment_map[i] = 0xff00 ^ (0x100<<segment_map[i]);
}
/* Clear frame buffer */
read_fb->brightness = 1;
for (int i=0; i<sizeof(read_fb->data)/sizeof(uint32_t); i++) {
@ -473,7 +471,14 @@ int main(void) {
adc_config();
volatile uint8_t *rxd = rx_buf.byte_data;
int k=0;
while (42) {
aux_reg = (read_fb->brightness ? SR_ILED_HIGH : SR_ILED_LOW) | (led_state<<1);
if (k++ == 1000000) {
k = 0;
led_state = (led_state+1)&7;
}
if (USART1->ISR & USART_ISR_RXNE) {
*rxd++ = USART1->RDR;
if (rxd >= rx_buf.set_fb_rq.end) {
@ -508,6 +513,6 @@ void SysTick_Handler(void) {
if (n++ == 1000) {
n = 0;
sys_time_seconds++;
}
}
}