From 71ad806c888027f90c5e0a149252263857b97bcc Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 15 Aug 2017 10:30:35 +0200 Subject: Working on uart code --- fw/.gitignore | 1 + fw/main.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 147 insertions(+), 35 deletions(-) (limited to 'fw') diff --git a/fw/.gitignore b/fw/.gitignore index 619130b..02752e1 100644 --- a/fw/.gitignore +++ b/fw/.gitignore @@ -6,3 +6,4 @@ *.expand *.bin *.hex +*.pp diff --git a/fw/main.c b/fw/main.c index 7153d59..3c10696 100644 --- a/fw/main.c +++ b/fw/main.c @@ -54,13 +54,15 @@ enum { struct framebuf { /* Multiplexing order: first Digits, then Time/bits, last Segments */ uint32_t data[nbits*frame_size_words]; - int brightness; /* 0 or 1; controls global brighntess control */ + uint8_t brightness; /* 0 or 1; controls global brighntess control */ }; -struct framebuf fb[2] = {0}; -struct framebuf *read_fb=fb+0, *write_fb=fb+1; +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; +volatile enum { FB_WRITE, FB_FORMAT, FB_UPDATE } fb_op; +volatile uint8_t rx_buf[sizeof(struct framebuf)]; +volatile uint8_t this_addr = 0x05; /* FIXME */ #define LED_COMM 0x0001 #define LED_ERROR 0x0002 @@ -68,6 +70,34 @@ volatile enum { FB_WRITE, FB_UPDATE } fb_op; #define SR_ILED_HIGH 0x0080 #define SR_ILED_LOW 0x0040 +void transpose_data(volatile uint8_t *rx_buf, volatile struct framebuf *out_fb) { + memset((uint8_t *)out_fb, 0, sizeof(*out_fb)); + struct data_format { + union { + uint8_t high[8]; + struct { uint8_t ah, bh, ch, dh, eh, fh, gh, dph; }; + }; + union { + uint16_t low; + struct { uint8_t al:2, bl:2, cl:2, dl:2, el:2, fl:2, gl:2, dpl:2; }; + }; + }; + struct data_format *rxp = (struct data_format *)rx_buf; + for (unsigned int digit=0; digitdata; + for (int bit=0x80; bit; bit>>=1, outp+=frame_size_words) + outp[segment] |= !!(rxp->high[segment] & bit) << digit; + } + uint16_t low = rxp->low; + for (int segment=0; segment<8; segment++) { + uint32_t *outp = out_fb->data; + for (int bit=0x8000; bit; bit>>=1, outp+=frame_size_words) + outp[segment] |= !!(rxp->high[segment] & bit) << digit; + } + } +} + void shift_aux(int global_current, int leds, int active_segment) { spi_send( (global_current ? SR_ILED_HIGH : SR_ILED_LOW) @@ -96,7 +126,7 @@ int shift_data() { frame_duration = time - last_frame_sys_time; last_frame_sys_time = sys_time; if (fb_op == FB_UPDATE) { - struct framebuf *tmp = read_fb; + volatile struct framebuf *tmp = read_fb; read_fb = write_fb; write_fb = tmp; fb_op = FB_WRITE; @@ -129,14 +159,10 @@ void cfg_timer3() { TIM_TypeDef *tim3 = TIM3; void TIM3_IRQHandler() { - //TIM3->CR1 &= ~TIM_CR1_CEN_Msk; + //TIM3->CR1 &= ~TIM_CR1_CEN_Msk; FIXME - static int last_ivl; - last_ivl = TIM3->CNT; /* This takes about 10us */ int period = shift_data(); - static int ivl; - ivl = TIM3->CNT - last_ivl; TIM3->CCR1 = period; TIM3->CNT = 0xffff; /* To not enable OC1 right away */ @@ -144,6 +170,47 @@ void TIM3_IRQHandler() { //TIM3->CR1 |= TIM_CR1_CEN; } +enum Command { + CMD_PING, + CMD_SET_ADDR, + CMD_SET_FB, + CMD_GET_DESC, +}; + +void USART1_IRQHandler() { + int addr = USART1->RDR; + int cmd = addr>>5; + addr &= 0x1F; + /* Are we addressed? */ + if (addr != this_addr) { + /* We are not. Mute USART until next idle condition */ + USART1->RQR |= USART_RQR_MMRQ; + } else { + /* We are. Switch by command. */ + switch (cmd) { + case CMD_SET_FB: + /* Are we ready to process new frame data? */ + if (fb_op != FB_WRITE) + goto errout; /* Error: Not yet ready to receive new packet */ + /* Disable this RX interrupt for duration of DMA transfer */ + USART1->CR1 &= ~USART_CR1_RXNEIE_Msk; + /* Enable DMA transfer to write buffer */ + DMA1_Channel3->CCR |= DMA_CCR_EN; + /* Kick off formatting code in main loop outside interrupt context */ + fb_op = FB_FORMAT; + break; + } + } +errout: + /* FIXME */ + return; +} + +void DMA1_Channel2_3_IRQHandler() { + /* DMA Transfer complete, re-enable receive interrupt */ + USART1->CR1 |= USART_CR1_RXNEIE; +} + int main(void) { RCC->CR |= RCC_CR_HSEON; while (!(RCC->CR&RCC_CR_HSERDY)); @@ -158,12 +225,15 @@ int main(void) { LL_Init1msTick(SystemCoreClock); - RCC->AHBENR |= RCC_AHBENR_GPIOAEN; - RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; + RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_DMAEN; + RCC->APB2ENR |= RCC_APB2ENR_SPI1EN | RCC_APB2ENR_USART1EN; RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; GPIOA->MODER |= - (2<OSPEEDR |= - (2<AFR[0] |= - (0<PUPDR |= + (2<I2SCFGR = 0; SPI1->CR2 &= ~SPI_CR2_DS_Msk; SPI1->CR2 &= ~SPI_CR2_DS_Msk; SPI1->CR2 |= LL_SPI_DATAWIDTH_16BIT; - /* FIXME maybe try w/o BIDI */ + + /* Configure USART1 */ + USART1->CR1 = /* 8-bit -> M1, M0 clear */ + /* RTOIE clear */ + (8 << USART_CR1_DEAT_Pos) /* 8 sample cycles/1 bit DE assertion time */ + | (8 << USART_CR1_DEDT_Pos) /* 8 sample cycles/1 bit DE assertion time */ + | USART_CR1_OVER8 + /* CMIF clear */ + | USART_CR1_MME + /* WAKE clear */ + /* PCE, PS clear */ + | 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) */ + int usartdiv = 25; + USART1->BRR = (usartdiv&0xFFF0) | ((usartdiv>>1) & 0x7); + USART1->CR1 |= USART_CR1_UE; + + /* Configure DMA for USART frame data reception */ + USART1->CR3 |= USART_CR3_DMAR; + DMA1_Channel3->CPAR = (unsigned int)&USART1->RDR; + DMA1_Channel3->CMAR = (unsigned int)rx_buf; + DMA1_Channel3->CNDTR = sizeof(rx_buf); + DMA1_Channel3->CCR = (0<CCR |= + (0< 25MHz */ - SPI1->CR1 = SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_SPE | (0<CR1 = + SPI_CR1_BIDIMODE + | SPI_CR1_BIDIOE + | SPI_CR1_SSM + | SPI_CR1_SSI + | SPI_CR1_SPE + | (0<brightness = 1; for (int i=0; idata)/sizeof(uint32_t); i++) { @@ -205,24 +328,12 @@ int main(void) { while (42) { led_state = (sys_time>>8)&7; - int ctr = sys_time>>2; - for (int bit=0, bmask=1; bitdata[bit*frame_size_words + seg] = data; + if (fb_op == FB_FORMAT) { + transpose_data(rx_buf, read_fb); + fb_op = FB_UPDATE; + while (fb_op == FB_UPDATE) + ; } - fb_op = FB_UPDATE; - while (fb_op == FB_UPDATE) - ; } } -- cgit