From: Keith Packard Date: Sun, 20 Nov 2016 09:42:22 +0000 (-0800) Subject: altos/stm-vga: Fix DMA reset to load scanline each time X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=fd05d495b463685d81e75115a93fdda2764c7113;p=fw%2Faltos altos/stm-vga: Fix DMA reset to load scanline each time If we load the scanline register while DMA is running, it doesn't actually get reloaded until after the first transfer from the next line, leaving a weird jog in the middle of the screen. Also flip to SPI1, as Bdale is using that on the 1802 board. Signed-off-by: Keith Packard --- diff --git a/src/drivers/ao_vga.c b/src/drivers/ao_vga.c index 24a645c7..eecf58f0 100644 --- a/src/drivers/ao_vga.c +++ b/src/drivers/ao_vga.c @@ -55,21 +55,21 @@ const struct ao_modeline vga_640x480x30 = { .htotal = 800, .vactive = 480, - .vsync_start = 481, - .vsync_end = 484, - .vtotal = 497 + .vsync_start = 490, + .vsync_end = 492, + .vtotal = 525, }; #define mode vga_640x480x60 #define WIDTH_BYTES (AO_VGA_WIDTH >> 3) -#define SCANOUT ((WIDTH_BYTES + 2) >> 1) +#define SCANOUT ((WIDTH_BYTES+2) >> 1) uint32_t ao_vga_fb[AO_VGA_STRIDE * AO_VGA_HEIGHT]; static uint32_t *scanline; -#define DMA_INDEX STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX) +#define DMA_INDEX STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX) static int line; static int vblank; @@ -85,7 +85,7 @@ static int vblank; (0 << STM_DMA_CCR_TCIE) | \ (en << STM_DMA_CCR_EN)) -int vblank_off = 13; +int vblank_off = 25; void stm_tim2_isr(void) { @@ -94,21 +94,24 @@ void stm_tim2_isr(void) /* Disable */ stm_dma.channel[DMA_INDEX].ccr = DMA_CCR(0); /* Reset DMA engine for the next scanline */ + stm_dma.channel[DMA_INDEX].cmar = scanline; stm_dma.channel[DMA_INDEX].cndtr = SCANOUT; /* Enable */ stm_dma.channel[DMA_INDEX].ccr = DMA_CCR(1); } stm_tim2.sr = ~(1 << STM_TIM234_SR_CC2IF); line = stm_tim3.cnt; - if (vblank_off <= line && line < (AO_VGA_HEIGHT << 1) + vblank_off + 12) { + if (vblank_off <= line && line < (AO_VGA_HEIGHT << 1) + vblank_off) { vblank = 0; - if ((line - vblank_off) & 1) + if (((line - vblank_off) & 1) == 0) scanline += AO_VGA_STRIDE; } else { - scanline = ao_vga_fb; - vblank = 1; + if (!vblank) { + stm_systick_isr(); + scanline = ao_vga_fb; + vblank = 1; + } } - stm_dma.channel[DMA_INDEX].cmar = scanline; ao_arch_release_interrupts(); } @@ -159,27 +162,29 @@ ao_vga_fb_init(void) ao_text("UL", ao_vga_fb, AO_VGA_STRIDE, - 0); + 1); ao_text("BL", ao_vga_fb + (240 - 7) * AO_VGA_STRIDE, AO_VGA_STRIDE, - 0); + 1); + + memset(ao_vga_fb + 120 * AO_VGA_STRIDE, '\0', WIDTH_BYTES); } void ao_vga_init(void) { - /* Initialize spi2 using PB15 for output */ + /* Initialize spi1 using PB5 for output */ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); - stm_ospeedr_set(&stm_gpiob, 15, STM_OSPEEDR_40MHz); - stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5); + stm_ospeedr_set(&stm_gpiob, 5, STM_OSPEEDR_40MHz); + stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5); /* turn on SPI */ - stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); - stm_spi2.cr1 = ((1 << STM_SPI_CR1_BIDIMODE) | /* Two wire mode */ + stm_spi1.cr1 = ((1 << STM_SPI_CR1_BIDIMODE) | /* Two wire mode */ (1 << STM_SPI_CR1_BIDIOE) | (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */ (0 << STM_SPI_CR1_CRCNEXT) | @@ -193,18 +198,18 @@ ao_vga_init(void) (1 << STM_SPI_CR1_MSTR) | (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); - stm_spi2.cr2 = ((0 << STM_SPI_CR2_TXEIE) | + stm_spi1.cr2 = ((0 << STM_SPI_CR2_TXEIE) | (0 << STM_SPI_CR2_RXNEIE) | (0 << STM_SPI_CR2_ERRIE) | (0 << STM_SPI_CR2_SSOE) | (1 << STM_SPI_CR2_TXDMAEN) | (0 << STM_SPI_CR2_RXDMAEN)); - (void) stm_spi2.dr; - (void) stm_spi2.sr; + (void) stm_spi1.dr; + (void) stm_spi1.sr; - /* Grab the DMA channel for SPI2 MOSI */ - stm_dma.channel[DMA_INDEX].cpar = &stm_spi2.dr; + /* Grab the DMA channel for SPI1 MOSI */ + stm_dma.channel[DMA_INDEX].cpar = &stm_spi1.dr; stm_dma.channel[DMA_INDEX].cmar = ao_vga_fb; /* hclock on timer 2 */ @@ -225,7 +230,7 @@ ao_vga_init(void) /* Channel 2 trigger scanout */ /* wait for the time to start scanout */ - stm_tim2.ccr2 = 90; + stm_tim2.ccr2 = mode.htotal - mode.hsync_end; stm_tim2.ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) | (STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH << STM_TIM234_CCMR1_OC2M) | @@ -342,7 +347,6 @@ ao_vga_init(void) stm_ospeedr_set(&stm_gpiob, 4, STM_OSPEEDR_40MHz); stm_afr_set(&stm_gpiob, 4, STM_AFR_AF2); - /* Enable the scanline interrupt */ stm_nvic_set_priority(STM_ISR_TIM2_POS, 0); stm_nvic_set_enable(STM_ISR_TIM2_POS); diff --git a/src/stm-vga/ao_demo.c b/src/stm-vga/ao_demo.c index 582e4156..3b582cc2 100644 --- a/src/stm-vga/ao_demo.c +++ b/src/stm-vga/ao_demo.c @@ -24,6 +24,67 @@ #include #include +struct ao_task ball_task; + +#define BALL_WIDTH 5 +#define BALL_HEIGHT 5 + +static int ball_x; +static int ball_y; +static int ball_dx, ball_dy; + +uint8_t ball_enable; + +void +ao_ball(void) +{ + ball_dx = 1; + ball_dy = 1; + ball_x = 0; + ball_y = 0; + for (;;) { + while (!ball_enable) + ao_sleep(&ball_enable); + for (;;) { + ao_solid(AO_ALLONES, + AO_ALLONES, + ao_vga_fb + ball_y * AO_VGA_STRIDE, + AO_VGA_STRIDE, + ball_x, + BALL_WIDTH, + BALL_HEIGHT); + ao_delay(AO_MS_TO_TICKS(10)); + ao_solid(AO_ALLONES, + AO_ALLONES, + ao_vga_fb + ball_y * AO_VGA_STRIDE, + AO_VGA_STRIDE, + ball_x, + BALL_WIDTH, + BALL_HEIGHT); + if (!ball_enable) + break; + ball_x += ball_dx; + ball_y += ball_dy; + if (ball_x + BALL_WIDTH > AO_VGA_WIDTH) { + ball_x = AO_VGA_WIDTH - BALL_WIDTH; + ball_dx = -ball_dx; + } + if (ball_x < 0) { + ball_x = -ball_x; + ball_dx = -ball_dx; + } + if (ball_y + BALL_HEIGHT > AO_VGA_HEIGHT) { + ball_y = AO_VGA_HEIGHT - BALL_HEIGHT; + ball_dy = -ball_dy; + } + if (ball_y < 0) { + ball_y = -ball_y; + ball_dy = -ball_dy; + } + } + } +} + static void ao_video_toggle(void) { @@ -31,8 +92,17 @@ ao_video_toggle(void) ao_vga_enable(ao_cmd_lex_i); } +static void +ao_ball_toggle(void) +{ + ao_cmd_decimal(); + ball_enable = ao_cmd_lex_i; + ao_wakeup(&ball_enable); +} + __code struct ao_cmds ao_demo_cmds[] = { { ao_video_toggle, "V\0Toggle video" }, + { ao_ball_toggle, "B\0Toggle ball" }, { 0, NULL } }; @@ -52,6 +122,7 @@ main(void) ao_vga_init(); ao_usb_init(); + ao_add_task(&ball_task, ao_ball, "ball"); ao_cmd_register(&ao_demo_cmds[0]); ao_start_scheduler(); diff --git a/src/stm-vga/ao_pins.h b/src/stm-vga/ao_pins.h index 3526cb6c..0e5a1903 100644 --- a/src/stm-vga/ao_pins.h +++ b/src/stm-vga/ao_pins.h @@ -69,7 +69,7 @@ #define HAS_BEEP 0 #define PACKET_HAS_SLAVE 0 -#define STM_DMA1_5_STOLEN 1 +#define STM_DMA1_3_STOLEN 1 #define AO_BOOT_CHAIN 1 diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index 0c86b49a..a24c6d3a 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -48,7 +48,11 @@ ao_dma_isr(uint8_t index) { void stm_dma1_channel1_isr(void) { ao_dma_isr(STM_DMA_INDEX(1)); } void stm_dma1_channel2_isr(void) { ao_dma_isr(STM_DMA_INDEX(2)); } +#ifdef STM_DMA1_3_STOLEN +#define LEAVE_DMA_ON +#else void stm_dma1_channel3_isr(void) { ao_dma_isr(STM_DMA_INDEX(3)); } +#endif void stm_dma1_channel4_isr(void) { ao_dma_isr(STM_DMA_INDEX(4)); } #ifdef STM_DMA1_5_STOLEN #define LEAVE_DMA_ON @@ -178,6 +182,13 @@ ao_dma_init(void) ao_dma_mutex[index] = 0xff; continue; } +#endif +#if STM_DMA1_3_STOLEN + if (index == STM_DMA_INDEX(3)) { + ao_dma_allocated[index] = 1; + ao_dma_mutex[index] = 0xff; + continue; + } #endif stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index); stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, 4);