//clearing screen
void clear_screen(Xuint32 BaseAddress){
	int i;
	for (i = 0; i < 4800; i++){
		VGA_PERIPH_MEM_mWriteMemory(BaseAddress + TEXT_MEM_OFF + i*4, 0x20);
		VGA_PERIPH_MEM_mWriteMemory(BaseAddress + GRAPHICS_MEM_OFF + i*4, 0x0);
	}
	for (i = 4800; i < 9600; i++){
	    VGA_PERIPH_MEM_mWriteMemory(BaseAddress + GRAPHICS_MEM_OFF + i*4, 0x0);
	}
}
void draw_square(Xuint32 BaseAddress){
	int i, j, k;
		for (j = 0; j < 480; j++){
			for (k = 0; k<(640/32); k++){
				i = j*(640/32) + k;
				if ((j > 200) && (j < 280) && (k > 8) && (k < 12)) {
					VGA_PERIPH_MEM_mWriteMemory(BaseAddress + GRAPHICS_MEM_OFF + i*4, 0xFFFFFFFF);
				}
				else{
					VGA_PERIPH_MEM_mWriteMemory(BaseAddress + GRAPHICS_MEM_OFF + i*4, 0x0);
				}
			}
		}
}
//printing char
void print_char(Xuint32 BaseAddress, int boja, unsigned char znak){
	int zapis;
	zapis = boja<<6;
	if(znak >= 0x40){
		znak -= 0x40;
	}
	zapis|=znak;
	VGA_PERIPH_MEM_mWriteMemory(BaseAddress + TEXT_MEM_OFF + cursor_position*4, zapis);
}
//printing all chars
void print_all(Xuint32 BaseAddress, int boja){
	int zapis;
	unsigned char i;
	int znak;
	znak = boja<<6;
	cursor_position = 0;
	for(i=0;i<64;i++){
			zapis = znak | (i+0x40);
			VGA_PERIPH_MEM_mWriteMemory(BaseAddress + TEXT_MEM_OFF + cursor_position*4, zapis);
			cursor_position+=2;
	}
}
void print_string(Xuint32 BaseAddress, int boja, unsigned char string_s[], int lenght){
	int i;
	int bojaSh = boja<<6;
	int zapis;
	for (i = 0; i < lenght; i++){
		unsigned char znak = string_s[i];
		zapis = bojaSh;
		if(znak >= 0x40){
			znak -= 0x40;
		}
		zapis|=znak;
		VGA_PERIPH_MEM_mWriteMemory(BaseAddress + TEXT_MEM_OFF + (cursor_position + i)*4, zapis);
	}
}
/**
 *
 * Run a self-test on the driver/device. Note this may be a destructive test if
 * resets of the device are performed.
 *
 * If the hardware system is not built correctly, this function may never
 * return to the caller.
 *
 * @param   baseaddr_p is the base address of the VGA_PERIPH_MEM instance to be worked on.
 *
 * @return
 *
 *    - XST_SUCCESS   if all self-test code passed
 *    - XST_FAILURE   if any self-test code failed
 *
 * @note    Caching must be turned off for this function to work.
 * @note    Self test may fail if data memory and device are not on the same bus.
 *
 */
XStatus VGA_PERIPH_MEM_SelfTest(void * baseaddr_p)
{
  int     Index;
  Xuint32 baseaddr;
  Xuint32 Mem32Value;

  /*
   * Check and get the device address
   */
  /*
   * Base Address maybe 0. Up to developer to uncomment line below.
  XASSERT_NONVOID(baseaddr_p != XNULL);
   */
  baseaddr = (Xuint32) baseaddr_p;

  xil_printf("******************************\n\r");
  xil_printf("* User Peripheral Self Test\n\r");
  xil_printf("******************************\n\n\r");

  /*
   * Write data to user logic BRAMs and read back
   */
  xil_printf("User logic memory test...\n\r");
  xil_printf("   - local memory address is 0x%08x\n\r", baseaddr);
  xil_printf("   - write pattern to local BRAM and read back\n\r");
  for ( Index = 0; Index < 256; Index++ )
  {
    VGA_PERIPH_MEM_mWriteMemory(baseaddr+4*Index, (0xDEADBEEF % Index));
  }

  for ( Index = 0; Index < 256; Index++ )
  {
    Mem32Value = VGA_PERIPH_MEM_mReadMemory(baseaddr+4*Index);
    if ( Mem32Value != (0xDEADBEEF % Index) )
    {
      xil_printf("   - write/read memory failed on address 0x%08x\n\r", baseaddr+4*Index);
      return XST_FAILURE;
    }
  }
  xil_printf("   - write/read memory passed\n\n\r");

  return XST_SUCCESS;
}
void font_size(Xuint32 BaseAddress, int size){
	VGA_PERIPH_MEM_mWriteMemory(BaseAddress+0x0C, size);
}
void set_foreground_color(Xuint32 BaseAddress, int color) {
	VGA_PERIPH_MEM_mWriteMemory(BaseAddress + 0x10, color);
}
void print_char(Xuint32 BaseAddress,unsigned char string_s){

	VGA_PERIPH_MEM_mWriteMemory(BaseAddress + TEXT_MEM_OFF + cursor_position, (string_s-0x40));
}
void clear_graphics_screen(Xuint32 BaseAddress){
	int i;
	for (i = 0; i < 9600; i++){
	    VGA_PERIPH_MEM_mWriteMemory(BaseAddress + GRAPHICS_MEM_OFF + i*4, 0x0);
	}
}
void print_string(Xuint32 BaseAddress, unsigned char string_s[], int lenght){
	int i;
	for (i = 0; i < lenght; i++){
		VGA_PERIPH_MEM_mWriteMemory(BaseAddress + TEXT_MEM_OFF + cursor_position + i*4, (string_s[i]-0x40));
	}
}
void clear_text_screen(Xuint32 BaseAddress){
	int i;
	for (i = 0; i < 4800; i++){
		VGA_PERIPH_MEM_mWriteMemory(BaseAddress + TEXT_MEM_OFF + i*4, 0x20);
	}
}
void set_font_size(Xuint32 BaseAddress, unsigned char size){
	VGA_PERIPH_MEM_mWriteMemory(BaseAddress + 0x0C, size);
}
void set_background_color(Xuint32 BaseAddress, Xuint32 color){
	VGA_PERIPH_MEM_mWriteMemory(BaseAddress + 0x14, color);
}
int main()
{

	int i;
	int prekidac;
    init_platform();
	XStatus Status;
	//Set Terminal count for my_timer
	//XIo_Out32(XPAR_MY_TIMER_0_BASEADDR + 0x0, 0x5F5E100);
	// Run my_timer
	XIo_Out32(XPAR_MY_TIMER_0_BASEADDR + 0x4, 0x2);
	Status = XIntc_Initialize (&Intc, XPAR_INTC_0_DEVICE_ID);
	if (Status != XST_SUCCESS)
		xil_printf ("\r\nInterrupt controller initialization failure");
	else
		xil_printf("\r\nInterrupt controller initialized");
	// Connect my_timer_interrupt_handler
	Status = XIntc_Connect (&Intc, XPAR_INTC_0_DEVICE_ID,
							(XInterruptHandler) my_timer_interrupt_handler,(void *)0);
	if (Status != XST_SUCCESS)
		xil_printf ("\r\nRegistering MY_TIMER Interrupt Failed");
	else
		xil_printf("\r\nMY_TIMER Interrupt registered");

	//start the interrupt controller in real mode
	Status = XIntc_Start(&Intc, XIN_REAL_MODE);
	//enable interrupt controller
	XIntc_Enable (&Intc, XPAR_INTC_0_DEVICE_ID);
	microblaze_enable_interrupts();

    unsigned char string_s[] = "LPRS 2 BRATE\n";

    VGA_PERIPH_MEM_mWriteMemory(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR + 0x00, 0x0);// direct mode   0
    VGA_PERIPH_MEM_mWriteMemory(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR + 0x04, 0x3);// display_mode  1
    VGA_PERIPH_MEM_mWriteMemory(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR + 0x08, 0x1);// show frame      2
    VGA_PERIPH_MEM_mWriteMemory(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR + 0x0C, 0x1);// font size       3
    VGA_PERIPH_MEM_mWriteMemory(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR + 0x10, 0xFF0000);// foreground 4 crvena
    VGA_PERIPH_MEM_mWriteMemory(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR + 0x14, 0x00FF00);// foreground 4 green
    VGA_PERIPH_MEM_mWriteMemory(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR + 0x18, 0x0000FF);// foreground 4 plava
    VGA_PERIPH_MEM_mWriteMemory(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR + 0x1c, 0xffff00);// foreground 4 zuta
    VGA_PERIPH_MEM_mWriteMemory(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR + 0x20, 0x000000);// background color crna
    VGA_PERIPH_MEM_mWriteMemory(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR + 0x24, 0xFF0000);// frame color      6

    xil_printf("Hello World\n\r");

    clear_text_screen(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR);
    clear_graphics_screen(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR);

    for(i=0;i<1200;i++){
    	set_cursor(i);
        print_char(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR, 0, '2');

    }
    /*
    set_cursor(0);
    print_char(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR, 0, '2');
    set_cursor(1);
    print_char(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR, 1, 'G');
    set_cursor(2);
    print_char(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR, 2, 'B');
    set_cursor(3);
    print_char(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR, 3, 'Y');
    set_cursor(6);
    print_string(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR, 2, string_s, 12);

    set_cursor(45);
    unsigned char znak = '2';
    if(znak >= 0x40){
    	znak -= 0x40;
    }
    VGA_PERIPH_MEM_mWriteMemory(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR + TEXT_MEM_OFF + 4*4, znak);

    for(i=64;i<76;i++){
    	set_cursor(i);
        print_char(XPAR_VGA_PERIPH_MEM_0_S_AXI_MEM0_BASEADDR, 2, string_s[i-64]);
    }*/
	while (1){
		prekidac = Xil_In8(XPAR_MY_PERIPHERAL_0_BASEADDR);//iscitavanje prekidaca
		//xil_printf("0x%08x\r\n", prekidac);

		/*
			value3 = XIo_In32(XPAR_MY_TIMER_0_BASEADDR + 0x0);
			value1 = XIo_In32(XPAR_MY_TIMER_0_BASEADDR + 0x4);
			value2 = XIo_In32(XPAR_MY_TIMER_0_BASEADDR + 0x8);
			xil_printf("\n\rvalue1 = %x, value2 = %x, value3 = %x.", value1, value2, value3);
		*/
	}

    cleanup_platform();
    return 0;
}