# HG changeset patch # User Paul Boddie # Date 1540247881 -7200 # Node ID 8b24f43ed2e640c12ffa28b6322463164973edfb # Parent 0ec101def359aa8a3eb19f579077e91f61ea0be5 Added support for a framebuffer, also providing a common library function to initialise the framebuffer with a test pattern. diff -r 0ec101def359 -r 8b24f43ed2e6 examples/vga-timer/Makefile --- a/examples/vga-timer/Makefile Tue Oct 23 00:36:31 2018 +0200 +++ b/examples/vga-timer/Makefile Tue Oct 23 00:38:01 2018 +0200 @@ -27,7 +27,7 @@ # Ordering of objects is important and cannot be left to replacement rules. -SRC = $(START_SRC) main.c $(COMMON_SRC) -OBJ = $(START_OBJ) main.o $(COMMON_OBJ) +SRC = $(START_SRC) main.c $(COMMON_SRC) $(DISPLAY_SRC) +OBJ = $(START_OBJ) main.o $(COMMON_OBJ) $(DISPLAY_OBJ) include ../../mk/rules.mk diff -r 0ec101def359 -r 8b24f43ed2e6 examples/vga-timer/main.c --- a/examples/vga-timer/main.c Tue Oct 23 00:36:31 2018 +0200 +++ b/examples/vga-timer/main.c Tue Oct 23 00:38:01 2018 +0200 @@ -21,8 +21,12 @@ #include "pic32_c.h" #include "init.h" #include "debug.h" + +/* Specific functionality. */ + #include "main.h" #include "vga.h" +#include "display.h" @@ -31,20 +35,16 @@ static void (*state_handler)(void); static uint32_t line; +/* Pointers to pixel lines. */ + +static uint8_t *linedata, *linedatalimit, *screenstart; + /* Pixel data. */ -static uint8_t linedata[LINE_LENGTH]; static const uint8_t zerodata[ZERO_LENGTH] = {0}; - +static uint8_t framebuffer[SCREEN_SIZE]; -static void test_linedata(void) -{ - int i; - - for (i = 0; i < LINE_LENGTH; i++) - linedata[i] = (i % 2) ? 0xff : 0x00; -} /* Blink an attached LED with delays implemented using a loop. */ @@ -76,7 +76,12 @@ { line = 0; state_handler = vbp_active; - test_linedata(); + test_linedata(framebuffer); + + /* Initialise the current display line pointer and display limit. */ + + linedatalimit = framebuffer + SCREEN_SIZE; + screenstart = framebuffer; init_memory(); init_pins(); @@ -117,7 +122,7 @@ dma_init(1, 3); dma_set_chaining(1, dma_chain_previous); dma_set_interrupt(1, T3, 1); - dma_set_transfer(1, PHYSICAL((uint32_t) linedata), LINE_LENGTH, + dma_set_transfer(1, PHYSICAL((uint32_t) screenstart), LINE_LENGTH, HW_PHYSICAL(PORTB), 1, 1); dma_init_interrupt(1, 0b00001000, 1, 3); @@ -211,7 +216,10 @@ state_handler = visible_active; - /* NOTE: Set the line address. */ + /* Set the line address. */ + + linedata = screenstart; + dma_set_source(1, PHYSICAL((uint32_t) linedata), LINE_LENGTH); /* Enable the channel for the next line. */ @@ -237,8 +245,16 @@ if (line < VFP_START) { - /* NOTE: Update the line address and handle wraparound. */ + /* Update the line address and handle wraparound. */ + if (!(line % LINE_MULTIPLIER)) + { + linedata += LINE_LENGTH; + if (linedata >= linedatalimit) + linedata -= SCREEN_SIZE; + } + + dma_set_source(1, PHYSICAL((uint32_t) linedata), LINE_LENGTH); return; } diff -r 0ec101def359 -r 8b24f43ed2e6 examples/vga-timer/vga.h --- a/examples/vga-timer/vga.h Tue Oct 23 00:36:31 2018 +0200 +++ b/examples/vga-timer/vga.h Tue Oct 23 00:38:01 2018 +0200 @@ -20,7 +20,7 @@ #ifndef __VGA_H__ #define __VGA_H__ -#define LINE_LENGTH 80 /* pixels */ +#define LINE_LENGTH 80 /* pixels */ #define LINE_COUNT 256 /* distinct display lines */ #define ZERO_LENGTH 1 /* pixels */ @@ -45,11 +45,9 @@ #define VSYNC_END 622 -#define SCREEN_BASE 256 -#define SCREEN_SIZE (40 * 1024) -#define SCREEN_LIMIT (SCREEN_BASE + SCREEN_SIZE) +/* Framebuffer properties. */ -#define SCREEN_BASE_KSEG0 (KSEG0_BASE + SCREEN_BASE) -#define SCREEN_LIMIT_KSEG0 (KSEG0_BASE + SCREEN_LIMIT) +#define SCREEN_SIZE (LINE_LENGTH * LINE_COUNT) +#define LINE_MULTIPLIER 2 #endif /* __VGA_H__ */ diff -r 0ec101def359 -r 8b24f43ed2e6 examples/vga/Makefile --- a/examples/vga/Makefile Tue Oct 23 00:36:31 2018 +0200 +++ b/examples/vga/Makefile Tue Oct 23 00:38:01 2018 +0200 @@ -27,7 +27,7 @@ # Ordering of objects is important and cannot be left to replacement rules. -SRC = $(START_SRC) main.c $(COMMON_SRC) -OBJ = $(START_OBJ) main.o $(COMMON_OBJ) +SRC = $(START_SRC) main.c $(COMMON_SRC) $(DISPLAY_SRC) +OBJ = $(START_OBJ) main.o $(COMMON_OBJ) $(DISPLAY_OBJ) include ../../mk/rules.mk diff -r 0ec101def359 -r 8b24f43ed2e6 examples/vga/main.c --- a/examples/vga/main.c Tue Oct 23 00:36:31 2018 +0200 +++ b/examples/vga/main.c Tue Oct 23 00:38:01 2018 +0200 @@ -21,8 +21,12 @@ #include "pic32_c.h" #include "init.h" #include "debug.h" + +/* Specific functionality. */ + #include "main.h" #include "vga.h" +#include "display.h" @@ -31,20 +35,16 @@ static void (*state_handler)(void); static uint32_t line; +/* Pointers to pixel lines. */ + +static uint8_t *linedata, *linedatalimit, *screenstart; + /* Pixel data. */ -static uint8_t linedata[LINE_LENGTH]; static const uint8_t zerodata[ZERO_LENGTH] = {0}; - +static uint8_t framebuffer[SCREEN_SIZE]; -static void test_linedata(void) -{ - int i; - - for (i = 0; i < LINE_LENGTH; i++) - linedata[i] = (i % 2) ? 0xff : 0x00; -} /* Blink an attached LED with delays implemented using a loop. */ @@ -76,7 +76,12 @@ { line = 0; state_handler = vbp_active; - test_linedata(); + test_linedata(framebuffer); + + /* Initialise the current display line pointer and display limit. */ + + linedatalimit = framebuffer + SCREEN_SIZE; + screenstart = framebuffer; init_memory(); init_pins(); @@ -96,7 +101,7 @@ dma_init(0, 3); dma_set_auto_enable(0, 1); dma_set_interrupt(0, T2, 1); - dma_set_transfer(0, PHYSICAL((uint32_t) linedata), LINE_LENGTH, + dma_set_transfer(0, PHYSICAL((uint32_t) screenstart), LINE_LENGTH, HW_PHYSICAL(PORTB), 1, LINE_LENGTH); dma_init_interrupt(0, 0b00001000, 1, 3); @@ -185,7 +190,10 @@ state_handler = visible_active; - /* NOTE: Set the line address. */ + /* Set the line address. */ + + linedata = screenstart; + dma_set_source(0, PHYSICAL((uint32_t) linedata), LINE_LENGTH); /* Enable the channel for the next line. */ @@ -211,8 +219,16 @@ if (line < VFP_START) { - /* NOTE: Update the line address and handle wraparound. */ + /* Update the line address and handle wraparound. */ + if (!(line % LINE_MULTIPLIER)) + { + linedata += LINE_LENGTH; + if (linedata >= linedatalimit) + linedata -= SCREEN_SIZE; + } + + dma_set_source(0, PHYSICAL((uint32_t) linedata), LINE_LENGTH); return; } diff -r 0ec101def359 -r 8b24f43ed2e6 examples/vga/vga.h --- a/examples/vga/vga.h Tue Oct 23 00:36:31 2018 +0200 +++ b/examples/vga/vga.h Tue Oct 23 00:38:01 2018 +0200 @@ -45,11 +45,9 @@ #define VSYNC_END 622 -#define SCREEN_BASE 256 -#define SCREEN_SIZE (40 * 1024) -#define SCREEN_LIMIT (SCREEN_BASE + SCREEN_SIZE) +/* Framebuffer properties. */ -#define SCREEN_BASE_KSEG0 (KSEG0_BASE + SCREEN_BASE) -#define SCREEN_LIMIT_KSEG0 (KSEG0_BASE + SCREEN_LIMIT) +#define SCREEN_SIZE (LINE_LENGTH * LINE_COUNT) +#define LINE_MULTIPLIER 2 #endif /* __VGA_H__ */ diff -r 0ec101def359 -r 8b24f43ed2e6 include/display.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/display.h Tue Oct 23 00:38:01 2018 +0200 @@ -0,0 +1,27 @@ +/* + * Common display-related functions. + * + * Copyright (C) 2018 Paul Boddie + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __DISPLAY_H__ +#define __DISPLAY_H__ + +#include + +void test_linedata(uint8_t *framebuffer); + +#endif /* __DISPLAY_H__ */ diff -r 0ec101def359 -r 8b24f43ed2e6 lib/display.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/display.c Tue Oct 23 00:38:01 2018 +0200 @@ -0,0 +1,50 @@ +/* + * Common display-related functions. + * + * Copyright (C) 2018 Paul Boddie + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "display.h" + +/* Provided by the application. */ + +#include "vga.h" + + + +/* Provide a pattern to test the line data. */ + +void test_linedata(uint8_t *framebuffer) +{ + int x, y; + uint8_t *linedata = framebuffer; + + for (y = 0; y < LINE_COUNT; y++) + { + for (x = 0; x < LINE_LENGTH; x++) + { + /* Pixel: I0RRGGBB = Y0YYYYXX */ + + linedata[x] = (x % 2) ? + (((y / (LINE_COUNT / 32)) & 0b1) << 7) | + (((y / (LINE_COUNT / 16)) & 0b1111) << 2) | + ((x / (LINE_LENGTH / 4)) & 0b11) : + 0x00; + } + + linedata += LINE_LENGTH; + } +} diff -r 0ec101def359 -r 8b24f43ed2e6 mk/common.mk --- a/mk/common.mk Tue Oct 23 00:36:31 2018 +0200 +++ b/mk/common.mk Tue Oct 23 00:38:01 2018 +0200 @@ -48,8 +48,11 @@ # Application-specific files appear after the above but before those below in # the application Makefiles. -COMMON_SRC = $(LIBDIR)/init.c $(LIBDIR)/debug.c $(LIBDIR)/cpu.S -COMMON_OBJ = $(LIBDIR)/init.o $(LIBDIR)/debug.o $(LIBDIR)/cpu.o +COMMON_SRC = $(LIBDIR)/init.c $(LIBDIR)/debug.c $(LIBDIR)/cpu.S +COMMON_OBJ = $(LIBDIR)/init.o $(LIBDIR)/debug.o $(LIBDIR)/cpu.o + +DISPLAY_SRC = $(LIBDIR)/display.c +DISPLAY_OBJ = $(LIBDIR)/display.o # Common linker script.