display_driver_b

#include <stdio.h>#include "altera_avalon_pio_regs.h"#include <altera_avalon_sgdma.h>#include <altera_avalon_sgdma_descriptor.h>#include <altera_avalon_sgdma_regs.h>// some useful structs ----------------------------//// a pixel in 32 bittypedef union { alt_u32 color32; struct allColor { alt_u8 b; alt_u8 g; alt_u8 r; alt_u8 blank; }color8; }Color; // a particle, just for funsiestypedef struct { int x, y; int vx, vy; }Particle; // global variables -----------------------------//// DMA descriptors alt_sgdma_descriptor dmaDescA[8]; alt_sgdma_descriptor dmaDescEND; // we locate our first framebuffer at the beginning of the SDRAM alt_u32* frameBufferA = (alt_u32*)SDRAM_BASE; // DMA -------------------------------------//// The InterruptService Routine (actually a callback function called by the ISR)//void my_dma_callback(void *data) { // reset the OWNED_BY_HW bit in the descriptors to reuse the chain int i; for(i = 0; i < 8;++i) dmaDescA[i].control |=

1<<ALTERA_AVALON_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_OFST;

// trigger another transfer all over again alt_avalon_sgdma_do_async_transfer((alt_sgdma_dev*)data, dmaDescA); } // this subroutine initializes a chain of descriptors, registers the// interrupt service routine and starts the first asynchronous transfer//void init_and_start_framebuffer(alt_sgdma_dev *dma) { // 480*272 lines * 4 bytes = 522240 bytes // 65532 (0xfffc) bytes * 7 = 458724 // +63516 (0xf81c) bytes // frame buffer A alt_u8* buff = (alt_u8*)frameBufferA; int i; for(i = 0; i < 8; ++i) { alt_u16 size = (i<7)?0xfffc:0xf81c; alt_avalon_sgdma_construct_mem_to_stream_desc( &dmaDescA[i], (i<7) ? (&dmaDescA[i+1]) : &dmaDescEND, (alt_u32*)buff, size, 0, i==0, i==7, 0); buff+= size; } alt_avalon_sgdma_register_callback(

dma, my_dma_callback,

ALTERA_AVALON_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK

|ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK,

(void*)dma); alt_avalon_sgdma_do_async_transfer(dma, dmaDescA); } // basic drawing routines --------------------------------------//// draw a pixelinline void setPix(const int x, const int y, const Color col, alt_u32* buffer) { buffer[x + y * 480] = col.color32; } // bresenham line drawingvoid line(alt_u32* buffer, int x0, int y0, int x1, int y1, Color color) { int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1; int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1; int err = (dx>dy ? dx : -dy)/2, e2; for(;;){ setPix(x0, y0, color, buffer); if (x0==x1 && y0==y1) break; e2 = err; if (e2 >-dx) { err -= dy; x0 += sx; } if (e2 < dy) { err += dx; y0 += sy; } } }

// fill the screen with a fractal (quite slow)

void MandelBrot(alt_u32* buffer) { alt_32 x,xx,y,cx,cy; int iteration,hx,hy; int itermax = 64; /* how many iterations to do */ int px, py; Color ramp[67]; memset(ramp, 0, sizeof(ramp)); // lets prepare some pretty colors for(x = 0; x < 32; x++) { ramp[x].color8.r = x*8; ramp[x].color8.g = 255- x*8; ramp[x].color8.b = 0; } for(x = 0; x < 32; x++) { ramp[32+x].color8.r = 255 - x*8; ramp[32+x].color8.g = 0; ramp[32+x].color8.b = x*8; } py = 0; for (hy=-1500;py<272; hy+=6, ++py) { cy = hy; px=0; for (hx=-2200;px<480; hx+=6, ++px) { cx = hx; x = y = 0; for (iteration=0; iteration < itermax; iteration++) { x/=8;y/=8; xx = x*x/16-y*y/16+cx; y = 2*x*y/16+cy; x = xx; if ((x/32)*(x/32)+(y/32)*(y/32)>1000000) break; } setPix(px, py, ramp[iteration], buffer); } } }

// useful to fill parts of the screen without blocking the SDRAM for too long

// use this instead of memset when doing frame buffer fills

void nonburst_memset(alt_u32* trg, alt_u32 val, alt_u32 size) { const int chunkSize = 12;// <-size of burst, lower this if the display gets corrupted. alt_u32 s; while(size) { s = (size>chunkSize)?chunkSize:size; memset(trg, val, s*4); trg+=s; size-=s; } } int main() { // switch on the backlight // IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, 64); // initialize the DMA and get a device handle // alt_sgdma_dev *dma = alt_avalon_sgdma_open("/dev/sgdma"); printf("open dma returned %ld\n", (alt_u32)dma); printf("framebuffer 1 at %lx\n", (alt_u32)frameBufferA); // assert the DISP signal // IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, 128+64); init_and_start_framebuffer(dma); // now we actually have some time to draw something // Particle particles[2] = { {100,0, -1, -1}, {0, 120, -1, -1} }; Color col; int count;

for(count=1;;count++) { // blink an led to see the program running IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, (count & 0x0001)+128+64); // draw a line in a random color col.color8.r = rand()%256; col.color8.g = rand()%256; col.color8.b = rand()%256; line(frameBufferA, particles[0].x, particles[0].y,

particles[1].x, particles[1].y, col); // bounce the particles around int i; for(i = 0; i < 2; ++i) { if(particles[i].x == 0 || particles[i].x == 479) particles[i].vx *= -1; particles[i].x += particles[i].vx; if(particles[i].y == 0 || particles[i].y == 271) particles[i].vy *= -1; particles[i].y += particles[i].vy; } } return 0; }