diff options
Diffstat (limited to 'fw')
-rw-r--r-- | fw/.gitignore | 1 | ||||
-rw-r--r-- | fw/Makefile | 12 | ||||
-rw-r--r-- | fw/main.c | 213 | ||||
-rw-r--r-- | fw/transpose.c | 61 | ||||
-rw-r--r-- | fw/transpose.h | 45 | ||||
-rw-r--r-- | fw/transpose_main.c | 77 |
6 files changed, 280 insertions, 129 deletions
diff --git a/fw/.gitignore b/fw/.gitignore index 02752e1..2d9d6e6 100644 --- a/fw/.gitignore +++ b/fw/.gitignore @@ -7,3 +7,4 @@ *.bin *.hex *.pp +transpose.elf diff --git a/fw/Makefile b/fw/Makefile index 6ff1686..8296708 100644 --- a/fw/Makefile +++ b/fw/Makefile @@ -34,6 +34,9 @@ LDFLAGS += -L$(CMSIS_PATH)/Lib/GCC -larm_cortexM0l_math all: main.elf main.pdf +cmsis_exports.c: $(CMSIS_DEV_PATH)/Include/stm32f030x6.h $(CMSIS_PATH)/Include/core_cm0.h + python3 gen_cmsis_exports.py $^ > $@ + %.o: %.c $(CC) -c $(CFLAGS) -o $@ $^ $(CC) -E $(CFLAGS) -o $(@:.o=.pp) $^ @@ -45,7 +48,7 @@ all: main.elf main.pdf %.dot: %.elf r2 -a arm -qc 'aa;agC' $< 2>/dev/null >$@ -main.elf: main.o startup_stm32f030x6.o system_stm32f0xx.o $(HAL_PATH)/Src/stm32f0xx_ll_utils.o base.o semihosting.o +main.elf: main.o startup_stm32f030x6.o system_stm32f0xx.o $(HAL_PATH)/Src/stm32f0xx_ll_utils.o base.o semihosting.o cmsis_exports.o transpose.o $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) $(OBJCOPY) -O ihex $@ $(@:.elf=.hex) $(OBJCOPY) -O binary $@ $(@:.elf=.bin) @@ -55,6 +58,13 @@ main.elf: main.o startup_stm32f030x6.o system_stm32f0xx.o $(HAL_PATH)/Src/stm32f program: main.elf openocd.cfg openocd -f openocd.cfg -c "program $< verify reset exit" +transpose.elf: transpose.c transpose_main.c + gcc -g -Wall -Wpedantic -o $@ $^ + +.PHONY: transpose_test +transpose_test: transpose.elf + ./transpose.elf + clean: rm -f **.o rm -f main.elf main.hex main.bin main.map main.lst @@ -13,6 +13,8 @@ #include <string.h> #include <unistd.h> +#include "transpose.h" + /* * Part number: STM32F030F4C6 */ @@ -43,28 +45,6 @@ void strobe_leds(void) { static volatile unsigned int sys_time = 0; -enum Segment { SegA, SegB, SegC, SegD, SegE, SegF, SegG, SegDP, nsegments }; -enum { - nrows = 4, - ncols = 8, - nbits = 10, -}; -enum { - frame_size_words = nrows*ncols*nsegments/32, -}; -struct framebuf { - /* Multiplexing order: first Digits, then Time/bits, last Segments */ - union { - uint32_t data[nbits*frame_size_words]; - struct { - struct { - uint32_t data[frame_size_words]; - } frame[nbits]; - }; - }; - uint8_t brightness; /* 0 or 1; controls global brighntess control */ -}; - volatile struct framebuf fb[2] = {0}; volatile struct framebuf *read_fb=fb+0, *write_fb=fb+1; volatile int led_state = 0; @@ -78,48 +58,6 @@ volatile uint8_t this_addr = 0x05; /* FIXME */ #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 dpl:2, gl:2, fl:2, el:2, dl:2, cl:2, bl:2, al:2; }; - }; - }; - struct data_format *rxp = (struct data_format *)rx_buf; - for (int bit=0; bit<8; bit++) { /* bits */ - uint32_t bit_mask = 1U<<bit; - volatile uint32_t *frame_data = out_fb->frame[bit+2].data; - uint8_t *start_inp = rxp->high; - for (volatile uint32_t *outp=frame_data; outp<frame_data+8; outp++) { /* segments */ - uint32_t acc = 0; - uint8_t *inp = start_inp++; - for (int digit=0; digit<32; digit++) { - acc |= (*inp & bit_mask) >> bit << digit; - inp += sizeof(struct data_format); - } - *outp = acc; - } - } - for (int bit=0; bit<2; bit++) { /* bits */ - volatile uint32_t *frame_data = out_fb->frame[bit].data; - uint16_t *inp = &rxp->low; - for (int seg=0; seg<8; seg++) { /* segments */ - uint32_t mask = 1 << bit << seg; - uint32_t acc = 0; - for (int digit=0; digit<32; digit++) { - acc |= (*inp & mask) >> bit >> seg << digit; - inp += sizeof(struct data_format)/sizeof(uint16_t); - } - frame_data[seg] = acc; - } - } -} - void shift_aux(int global_current, int leds, int active_segment) { spi_send( (global_current ? SR_ILED_HIGH : SR_ILED_LOW) @@ -128,6 +66,14 @@ void shift_aux(int global_current, int leds, int active_segment) { strobe_aux(); } +inline unsigned int stk_start() { + return SysTick->VAL; +} + +inline unsigned int stk_end(unsigned int start) { + return (start - SysTick->VAL) & 0xffffff; +} + static volatile int frame_duration; /* returns new bit time in cycles */ int shift_data() { @@ -176,15 +122,16 @@ void cfg_timer3() { TIM3->EGR |= TIM_EGR_UG; TIM3->CR1 = TIM_CR1_ARPE; TIM3->CR1 |= TIM_CR1_CEN; + NVIC_EnableIRQ(TIM3_IRQn); + NVIC_SetPriority(TIM3_IRQn, 2); } -TIM_TypeDef *tim3 = TIM3; void TIM3_IRQHandler() { //TIM3->CR1 &= ~TIM_CR1_CEN_Msk; FIXME /* This takes about 10us */ - int period = 0; /* FIXME DEBUG shift_data(); */ + int period = shift_data(); TIM3->CCR1 = period; TIM3->CNT = 0xffff; /* To not enable OC1 right away */ @@ -199,8 +146,11 @@ enum Command { CMD_GET_DESC, }; +int gaddr; void USART1_IRQHandler() { - int addr = USART1->RDR; + gaddr = USART1->RDR; + USART1->RQR |= USART_RQR_RXFRQ; + int addr = gaddr; /* FIXME DEBUG */ int cmd = addr>>5; addr &= 0x1F; /* Are we addressed? */ @@ -212,32 +162,78 @@ void USART1_IRQHandler() { switch (cmd) { case CMD_SET_FB: /* Are we ready to process new frame data? */ - if (fb_op != FB_WRITE) + if (fb_op != FB_WRITE) { + //asm("bkpt"); /* FIXME DEBUG */ 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->IFCR |= DMA_IFCR_CGIF3; DMA1_Channel3->CCR |= DMA_CCR_EN; - /* Kick off formatting code in main loop outside interrupt context */ - fb_op = FB_FORMAT; + USART1->CR3 |= USART_CR3_DMAR; break; } } errout: /* FIXME */ - return; +return; } void DMA1_Channel2_3_IRQHandler() { /* DMA Transfer complete, re-enable receive interrupt */ USART1->CR1 |= USART_CR1_RXNEIE; + /* ...and disable this DMA channel */ + USART1->CR3 &= ~USART_CR3_DMAR_Msk; + DMA1_Channel3->CCR &= ~DMA_CCR_EN_Msk; + /* Kick off formatting code in main loop outside interrupt context */ + fb_op = FB_FORMAT; + DMA1->IFCR |= DMA_IFCR_CGIF3; +} + +void uart_config(void) { + 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 FIXME debug? + /* 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; + USART1->CR1 |= USART_CR1_UE; + + /* Configure DMA for USART frame data reception */ + DMA1_Channel3->CPAR = (unsigned int)&USART1->RDR; + DMA1_Channel3->CMAR = (unsigned int)rx_buf; + DMA1_Channel3->CNDTR = sizeof(rx_buf); + DMA1_Channel3->CCR = (0<<DMA_CCR_PL_Pos); + DMA1_Channel3->CCR |= + (0<<DMA_CCR_MSIZE_Pos) + | (0<<DMA_CCR_PSIZE_Pos) + | DMA_CCR_MINC + | DMA_CCR_TCIE + | DMA_CCR_CIRC; + + NVIC_EnableIRQ(USART1_IRQn); + NVIC_SetPriority(USART1_IRQn, 3); + NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); + NVIC_SetPriority(DMA1_Channel2_3_IRQn, 3); } int main(void) { RCC->CR |= RCC_CR_HSEON; while (!(RCC->CR&RCC_CR_HSERDY)); RCC->CFGR &= ~RCC_CFGR_PLLMUL_Msk & ~RCC_CFGR_SW_Msk & ~RCC_CFGR_PPRE_Msk & ~RCC_CFGR_HPRE_Msk; - RCC->CFGR |= (1<<RCC_CFGR_PLLMUL_Pos) | RCC_CFGR_PLLSRC_HSE_PREDIV; /* PLL x4 -> 50.0MHz */ + RCC->CFGR |= (2<<RCC_CFGR_PLLMUL_Pos) | RCC_CFGR_PLLSRC_HSE_PREDIV; /* PLL x4 -> 50.0MHz */ RCC->CFGR2 &= ~RCC_CFGR2_PREDIV_Msk; RCC->CFGR2 |= RCC_CFGR2_PREDIV_DIV2; /* prediv :2 -> 12.5MHz */ RCC->CR |= RCC_CR_PLLON; @@ -245,25 +241,7 @@ int main(void) { RCC->CFGR |= (2<<RCC_CFGR_SW_Pos); SystemCoreClockUpdate(); - //SysTick_Config(SystemCoreClock/1000); /* 1ms interval */ - //NVIC_DisableIRQ(SysTick_IRQn); - SysTick->VAL = 0U; - SysTick->LOAD = 0x00FFFFFF; - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; - while (42) { - static unsigned int cvr __attribute__((used)); - cvr = SysTick->VAL; - //if (fb_op == FB_FORMAT) { - transpose_data(rx_buf, write_fb); - write_fb->brightness = rx_buf[offsetof(struct framebuf, brightness)]; - // fb_op = FB_UPDATE; - // while (fb_op == FB_UPDATE) - // ; - //} - cvr = cvr - SysTick->VAL; - asm volatile ("bkpt"); - } - //LL_Init1msTick(SystemCoreClock); + LL_Init1msTick(SystemCoreClock); RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_DMAEN; RCC->APB2ENR |= RCC_APB2ENR_SPI1EN | RCC_APB2ENR_USART1EN; @@ -309,38 +287,6 @@ int main(void) { SPI1->CR2 &= ~SPI_CR2_DS_Msk; SPI1->CR2 |= LL_SPI_DATAWIDTH_16BIT; - /* 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<<DMA_CCR_PL_Pos); - DMA1_Channel3->CCR |= - (0<<DMA_CCR_MSIZE_Pos) - | (0<<DMA_CCR_PSIZE_Pos) - | DMA_CCR_MINC - | DMA_CCR_TCIE; - /* Baud rate PCLK/2 -> 25MHz */ SPI1->CR1 = SPI_CR1_BIDIMODE @@ -354,19 +300,30 @@ int main(void) { | SPI_CR1_CPHA; /* FIXME maybe try w/o BIDI */ + /* Clear frame buffer */ read_fb->brightness = 1; for (int i=0; i<sizeof(read_fb->data)/sizeof(uint32_t); i++) { - read_fb->data[i] = 0xffffffff; + read_fb->data[i] = 0xffffffff; /*FIXME debug replace with 0x00000000 */ } - cfg_timer3(); - NVIC_EnableIRQ(TIM3_IRQn); - NVIC_SetPriority(TIM3_IRQn, 2); - + cfg_timer3(); SysTick_Config(SystemCoreClock/1000); /* 1ms interval */ + uart_config(); + uint8_t i=0; + int last_sys_time=0; while (42) { led_state = (sys_time>>8)&7; + if ((sys_time ^ last_sys_time) & (1<<4)) { + USART1->TDR = i++; + } + last_sys_time = sys_time; + if (fb_op == FB_FORMAT) { + //transpose_data(rx_buf, read_fb); + fb_op = FB_UPDATE; + while (fb_op == FB_UPDATE) + ; + } } } diff --git a/fw/transpose.c b/fw/transpose.c new file mode 100644 index 0000000..1c5f982 --- /dev/null +++ b/fw/transpose.c @@ -0,0 +1,61 @@ + +#include <unistd.h> +#include <string.h> + +#include "transpose.h" + +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 *rxp = (struct data_format *)rx_buf; + for (int bit=0; bit<8; bit++) { /* bits */ + uint32_t bit_mask = 1U<<bit; + volatile uint32_t *frame_data = out_fb->frame[bit+2].data; + uint8_t *start_inp = rxp->high; + for (volatile uint32_t *outp=frame_data; outp<frame_data+8; outp++) { /* segments */ + uint32_t acc = 0; + uint8_t *inp = start_inp++; + for (int digit=0; digit<32; digit++) { + acc |= (*inp & bit_mask) >> bit << digit; + inp += sizeof(struct data_format); + } + *outp = acc; + } + } + for (int bit=0; bit<2; bit++) { /* bits */ + volatile uint32_t *frame_data = out_fb->frame[bit].data; + uint16_t *inp = &rxp->low; + for (int seg=0; seg<8; seg++) { /* segments */ + uint32_t mask = 1 << bit << (seg*2); + uint32_t acc = 0; + for (int digit=0; digit<32; digit++) { + acc |= (*inp & mask) >> bit >> seg << digit; + inp += sizeof(struct data_format)/sizeof(uint16_t); + } + frame_data[seg] = acc; + } + } +} + + +void untranspose_data(struct framebuf *fb, uint8_t *txbuf) { + memset(txbuf, 0, sizeof(*fb)); + + struct data_format *tx = (struct data_format *) txbuf; + + for (size_t i=0; i<32; i++) { /* digit */ + for (size_t j=0; j<8; j++) { /* segment */ + for (size_t k=0; k<8; k++) { /* bit */ + tx[i].high[j] |= (fb->frame[k+2].data[j] & (1<<i)) ? (1<<k) : 0; + } + } + } + + for (size_t i=0; i<32; i++) { /* digit */ + for (size_t j=0; j<8; j++) { /* segment */ + for (size_t k=0; k<2; k++) { /* bit */ + tx[i].low |= (fb->frame[k].data[j] & (1<<i)) ? (1<<k<<(j*2)) : 0; + } + } + } +} + diff --git a/fw/transpose.h b/fw/transpose.h new file mode 100644 index 0000000..1927a72 --- /dev/null +++ b/fw/transpose.h @@ -0,0 +1,45 @@ +#ifndef __TRANSPOSE_H__ +#define __TRANSPOSE_H__ + +#include <stdint.h> + +enum Segment { SegA, SegB, SegC, SegD, SegE, SegF, SegG, SegDP, nsegments }; +enum { + nrows = 4, + ncols = 8, + nbits = 10, +}; + +enum { + frame_size_words = nrows*ncols*nsegments/32, +}; + +struct framebuf { + /* Multiplexing order: first Digits, then Time/bits, last Segments */ + union { + uint32_t data[nbits*frame_size_words]; + struct { + struct { + uint32_t data[frame_size_words]; + } frame[nbits]; + }; + }; + uint8_t brightness; /* 0 or 1; controls global brighntess control */ +}; + +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 dpl:2, gl:2, fl:2, el:2, dl:2, cl:2, bl:2, al:2; }; + }; +} __attribute__((packed)); + + +void transpose_data(volatile uint8_t *rx_buf, volatile struct framebuf *out_fb); +void untranspose_data(struct framebuf *fb, uint8_t *txbuf); + +#endif//__TRANSPOSE_H__ diff --git a/fw/transpose_main.c b/fw/transpose_main.c new file mode 100644 index 0000000..793872d --- /dev/null +++ b/fw/transpose_main.c @@ -0,0 +1,77 @@ + +#include <stdio.h> +#include <stdint.h> +#include <malloc.h> +#include <string.h> +#include <assert.h> + +#include "transpose.h" + +void rxbuf_dump(struct data_format *rx) { + fprintf(stdout, "\033[38;5;244m high | low\n"); + fprintf(stdout, " a b c d e f g . | a b c d e f g .\033[0m\n"); + + for (int i=0; i<32; i++) { + for (int j=0; j<8; j++) + fprintf(stdout, "%02x ", rx[i].high[j]); + fprintf(stdout, "\033[38;5;244m|\033[0m"); + for (int j=0; j<8; j++) + fprintf(stdout, " %1x", (rx[i].low>>(2*j))&0x3); + fprintf(stdout, "\n"); + } +} + +void fb_dump(struct framebuf *fb) { + fprintf(stdout, "\033[38;5;244mbit | "); + for (int i=0; i<8; i++) + fprintf(stdout, " %d ", i); + fprintf(stdout, "\033[0m\n"); + + for (int i=0; i<10; i++) { + fprintf(stdout, " %2d |", i); + for (int j=0; j<8; j++) + fprintf(stdout, " %08x", fb->frame[i].data[j]); + fprintf(stdout, "\n"); + } +} + +int main(int argc, char **argv) { + FILE *randf = fopen("/dev/urandom", "r"); + if (!randf) + return 2; + + struct framebuf *fb = malloc(sizeof(struct framebuf)); + if (!fb) + return 2; + assert(sizeof(*fb) == 32*sizeof(struct data_format)+4); + + uint8_t *rxbuf1 = malloc(sizeof(*fb)); + if (!rxbuf1) + return 2; + if (fread(rxbuf1, 1, sizeof(*fb), randf) != sizeof(*fb)) + return 2; + + uint8_t *rxbuf2 = malloc(sizeof(*fb)); + if (!rxbuf2) + return 2; + memcpy(rxbuf2, rxbuf1, sizeof(*fb)); + + memset((void *)fb, 0, sizeof(*fb)); + + transpose_data(rxbuf1, fb); + untranspose_data(fb, rxbuf1); + + assert(!memcmp(rxbuf1, rxbuf2, sizeof(fb))); + + fprintf(stdout, "\n\033[93mDUMP of ORIGINAL\033[0m\n"); + rxbuf_dump((struct data_format *)rxbuf2); + + fprintf(stdout, "\n\033[93mDUMP of FRAME BUFFER\033[0m\n"); + fb_dump(fb); + + fprintf(stdout, "\n\033[93mDUMP of RESULT\033[0m\n"); + rxbuf_dump((struct data_format *)rxbuf1); + + fprintf(stderr, "PASS"); + return 0; +} |