# Animacija s komponentami VGAram, axi_fill in VGAmouse
Primer sistema za prikaz slike na izhodu VGA razvojne plošče ZedBoard s komponento, ki bere slikovne točke iz BRAM. Primerjava premikanja (animacije) kvadrata na zaslonu, ki jo izvaja CPU s pisanjem posameznih točk in strojna komponenta za risanje kvadrata. Uporaba prekinitev za tekočo animacijo.
Projekt je narejen za ploščo ZedBoard, poleg komponent iz knjižnic potrebujemo še:
[VGAram](src/VGAram_1.2.zip).
**TODO:** *manjka podrobnejši opis sistema in uporabljenih komponent.*
![](./img/bd_vga.png)
[Celoten blokovni diagram](img/bd_vga_irq.png)
## Aplikacija
V kodi so komentarji z razlago nastavitev prekinitev in uporabe prekinitvene rutine.
Na zaslonu se prikažeta dva kvadrata - enega izrisuje strojna komponenta in ga premikamo v prekinitveni
rutini, drugega pa rišemo s pisanjem v BRAM znotraj neskončne zanke. Prekinitev se proži ob koncu prikaza
posamezne slike na zaslon, da je premikanje usklajeno z osveževanjem slike. Če povečujemo velikost kvadrata,
počasnejše nastavljanje točk s pisanjem v BRAM ne more več slediti.
```c
#include
#include "xparameters.h"
#include "xil_io.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "sleep.h"
// definiraj registre axi_fill
#define RGB XPAR_VGA_AXI_FILL_0_S00_AXI_BASEADDR
#define SIZE XPAR_VGA_AXI_FILL_0_S00_AXI_BASEADDR+4
#define XP XPAR_VGA_AXI_FILL_0_S00_AXI_BASEADDR+8
#define YP XPAR_VGA_AXI_FILL_0_S00_AXI_BASEADDR+12
// definiraj BRAM
#define BRAM XPAR_VGA_AXI_BRAM_CTRL_0_S_AXI_BASEADDR
// definiraj GPIO_1 (VGA MOUSE)
#define MX XPAR_AXI_GPIO_1_BASEADDR
#define MY XPAR_AXI_GPIO_1_BASEADDR+8
// definicije za prekinitveni krmilnik (VGA RAM)
#define INTC_INTERRUPT_ID XPAR_FABRIC_VGA_VGARAM_0_IRQ_INTR // 61
#define INTC_DEVICE_ID XPAR_PS7_SCUGIC_0_DEVICE_ID // =0
static XScuGic Intc; // prekinitvena struktura
int ir = 0; // zastavica za status prekinitve
void service(void *InstancePtr) { // prekinitvena rutina
static int x = 0;
ir = 1; // prekinitev sprozena
Xil_Out8(XP, x); // brisi kvadrat na koordinati x
Xil_Out8(RGB, 0);
usleep(500); // cakaj vsaj size*size*2/50 us, da se izvede
Xil_Out8(XP, ++x); // narisi kvadrat na x+1
Xil_Out8(RGB, 0x0f);
Xil_Out8(MX, x); // premakni kurzor miske
Xil_Out8(MY, 255-x);
}
int SetupInterruptSystem() { // nastavi prekinitve
int result;
XScuGic *IntcInstancePtr = &Intc;
XScuGic_Config *IntcConfig;
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (IntcConfig == NULL) {
return XST_FAILURE;
}
result = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress);
if (result != XST_SUCCESS) {
return XST_FAILURE;
}
XScuGic_SetPriorityTriggerType(IntcInstancePtr, INTC_INTERRUPT_ID,0x00, 0x3);
/* Povezi prekinitveno rutino (service) */
result = XScuGic_Connect(IntcInstancePtr, INTC_INTERRUPT_ID, (Xil_ExceptionHandler) service, 0);
if (result != XST_SUCCESS) {
return result;
}
/* Omogoci prekinitve */
XScuGic_Enable(IntcInstancePtr, INTC_INTERRUPT_ID);
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler, IntcInstancePtr);
Xil_ExceptionEnable(); /* omogoci nekriticne izjeme */
return XST_SUCCESS;
}
int main()
{
int size = 100; // velikost kvadratov
char *c;
int i, j, xk=0;
Xil_Out8(XP, 0); // narisi crn kvadrat, da se pocisti cel zaslon
Xil_Out8(YP, 0);
Xil_Out8(SIZE, 255);
Xil_Out8(RGB, 0);
usleep(3000); // cakaj vsaj 256*256*2/50 us
Xil_Out8(SIZE, size);
// nastavi prekinitve
if (SetupInterruptSystem() != XST_SUCCESS) {
return XST_FAILURE;
}
// animacija v neskoncni zanki
while(1) {
while(ir==0); // cakaj novo prekinitev in
ir=0; // ponastavi zastavico
for (j=0; j