/*
 *  * Copyright (c) 2004 Xilinx, Inc.  All rights reserved.
 *
 * Xilinx, Inc.
 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A 
 * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
 * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR 
 * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION 
 * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE 
 * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION
 * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO 
 * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO 
 * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE 
 * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY 
 * AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// Located in: microblaze_0/include/xparameters.h
#include "xparameters.h"

#include "xutil.h"
#include "xintc_l.h"
#include "xuartlite_l.h"
#include "xgpio_l.h"

#define FONT_OFFSET 0xA00

/* Address of a particular character on the screen (rows are 80) */
#define CHAR(c,r) \
   (((unsigned char *)(XPAR_VGA_BASEADDR))[(c) + ((r) << 6) + ((r) << 4)])

/* Start of font memory */
#define FONT ((unsigned char *)XPAR_VGA_BASEADDR + FONT_OFFSET)

int uart_interrupt_count = 0;
char uart_character;
 
/* UART interrupt service routine */
void uart_int_handler(void *baseaddr_p) {
   
   /* While UART receive FIFO has data */
   while (!XUartLite_mIsReceiveEmpty(XPAR_RS232_BASEADDR)) {
     /* Read a character */
     uart_character = XUartLite_RecvByte(XPAR_RS232_BASEADDR);
     ++uart_interrupt_count;
   }
}

/* Write a text string on the display */
void put_string(char *string, int column, int row)
{
  char *p = &(CHAR(column, row));
  while (*p++ = *string++)
    ;
}

int main (void) {
   int i;

   print("Hello World!\r\n");

   put_string("The Digilent Spartan 3 board says \"Hello from NCTU\"", 0, 1);

   /* Enable MicroBlaze interrupts */
   microblaze_enable_interrupts();
   /* Register the UART interrupt handler in the vector table */
   XIntc_RegisterHandler(XPAR_OPB_INTC_0_BASEADDR,XPAR_OPB_INTC_0_RS232_INTERRUPT_INTR,
      (XInterruptHandler)uart_int_handler,(void *)XPAR_RS232_BASEADDR);
   /* Start the interrupt controller */
   XIntc_mMasterEnable(XPAR_OPB_INTC_0_BASEADDR);
   /* Enable timer and UART interrupt requests in the interrupt controller */
   XIntc_mEnableIntr(XPAR_OPB_INTC_0_BASEADDR, XPAR_RS232_INTERRUPT_MASK);
   /* Enable UART interrupts */
   XUartLite_mEnableIntr(XPAR_RS232_BASEADDR);
   
  /* Periodically report the latest character received */
  put_string("Latest character received:", 0, 3);
  for (;;) {
    char buf[2];
    buf[1] = '\0';

    print("Character number ");
    putnum(uart_interrupt_count);
    print(" is ");
    buf[0] = uart_character;
    print(buf);
    print("\r\n");

    put_string(buf, 26, 3);
     
    for (i = 0 ; i < 10000000 ; i++ )  ; /* delay */
  }
  
   print("Goodbye! \r\n");
   return 0;
}

