altos/stm-vga: Fix DMA reset to load scanline each time
authorKeith Packard <keithp@keithp.com>
Sun, 20 Nov 2016 09:42:22 +0000 (01:42 -0800)
committerKeith Packard <keithp@keithp.com>
Sun, 20 Nov 2016 09:42:22 +0000 (01:42 -0800)
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 <keithp@keithp.com>
src/drivers/ao_vga.c
src/stm-vga/ao_demo.c
src/stm-vga/ao_pins.h
src/stm/ao_dma_stm.c

index 24a645c733ff6e47885e1e30430df3febad4e2df..eecf58f0ed5014daf4cd72639c0de414eadcf448 100644 (file)
@@ -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);
index 582e4156b1a5601dc9075931e61a8e1912db5a36..3b582cc2ec41dfc46357e24f38942d4b16efe503 100644 (file)
 #include <ao_boot.h>
 #include <ao_vga.h>
 
+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();
index 3526cb6c9a1b5aa752923410887ade7687bd110f..0e5a1903a235f713a6f32aaa32b557ddc31082db 100644 (file)
@@ -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
 
index 0c86b49af271255c93bdff9cd3c92c2bcb13a1a9..a24c6d3a7e2c7078bfcb1afc529b56902b4b67ba 100644 (file)
@@ -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);