#include <io.h>
#include <system.h>
#include <stdio.h>
#include <alt_types.h>
#include "/home/user5/spring08/sb2784/Desktop/4840/project/aes128_sd_sram/vhd/altera_up_avalon_character_lcd/sdk/alt_up_character_lcd.h"
#include "keyboard.h"

//Macros to interface to the AES block
#define AES_WRITE_KEY(offset,data)          IOWR_32DIRECT(AES128_BASE,(offset*4),data)
#define AES_READ_KEY(offset)                IORD_32DIRECT(AES128_BASE,(offset*4))
#define AES_WRITE_DATA(addr,data)           IOWR_32DIRECT(AES128_BASE,16+(addr*4),data)
#define AES_READ_DATA(addr)                 IORD_32DIRECT(AES128_BASE,16+(addr*4))

//Macros to read from the PS/2 keyboard
//#define KEYBOARD_READY()            IORD_8DIRECT(KEYBOARD_BASE, 0)   //Poll status of keyboard
//#define KEYBOARD_READ()             IORD_8DIRECT(KEYBOARD_BASE, 4)   //Get one byte from the keyboard

//Macros to write into VGA
#define VGA_GO()                    IOWR_16DIRECT(VGASRAM_BASE,524288*2,1)      //Tell VGA that it is safe to read data from SRAM
#define VGA_NO()                    IOWR_16DIRECT(VGASRAM_BASE,524288*2,0)      //Tell VGA to not read data
#define VGA_IDLE()                 IORD_16DIRECT(VGASRAM_BASE,524288*4)        //Are we inside the rectangle?

//Macros to get data from SPI
#define SPI_CHOOSE_CARD_ADDR(addr)  IOWR_32DIRECT(SPI_BASE, 2*4, addr)
#define SPI_START()                 IOWR_32DIRECT(SPI_BASE, 1*4, 1)
#define SPI_END()                   IOWR_32DIRECT(SPI_BASE, 1*4, 0)
#define SPI_READY()                 IORD_32DIRECT(SPI_BASE, 16*4)
#define SPI_CHOOSE_BUFF_ADDR(addr)  IOWR_32DIRECT(SPI_BASE, 64*4, addr)
#define SPI_GET_BUFF_DATA()         IORD_32DIRECT(SPI_BASE, 128*4)

//Macros to write into SRAM
#define SRAM_WRITE(addr, data)      IOWR_16DIRECT(VGASRAM_BASE,(addr*2),data)
#define SRAM_READ(addr)             IORD_16DIRECT(VGASRAM_BASE,(addr*2))

#define NUM_FRAME                   3270 //short = 84 //long = 3274

int main()
{
  //int = 32 bits; long int = 64 bits(?); short int = 16 bits; char = 8 bits
  
      
  printf("\nWelcome to the AES 128-bit decryption project!");  
 
  
  unsigned long int i = 0, addr=0;
  int j =0,count=0,k=0, q=0;
  unsigned int data = 0;
  unsigned short int t0,t1;
  int size = 4646;
  unsigned short *key;
  unsigned long int keydata[4]=//{0x00000000,0x00000000,0x00000000,0x00000000};
                               {0x2b28ab09,0x7eaef7cf, 0x15d2154f, 0x16a6883c};
  
  printf("\n\nPlease enter the decryption key (32 hex digits).\n");
  
  //key = getKey();
  
  // Debug statement to ensure key returned properly
/*
     for(i=0;i<32;i++) {
     keydata[i>>3] = (keydata[i>>3]<<4)|(key[i]&0xF);
     }
  
  
*/
     for(i=0;i<4;i++)
     AES_WRITE_KEY(i,keydata[i]);
     

     
  printf("\nEntering Decryption... \n");    
  
  unsigned long int frame = 0, frameStartAddr=0, delay=0, frameSize=0x13040;    //0x13038
  unsigned long int frameEndAddr=0, startBlock, endBlock;
  
  //Write 0's into the SRAM
  /* printf("\nClearing part of the SRAM.");
  for(q = 0; q <= 0x4B440; q++)
    SRAM_WRITE(q,0); */
  
  unsigned long int qu=0, t=0;
    
  printf("\nWriting into SRAM");
  for(frame = 0; frame <= NUM_FRAME; frame=frame+1)    //84 = short, 3274 = long

  //for(;;t++)
  { 
      VGA_GO();
      //frame = t%85;      
      //frame = 36;//35; 
      addr = 0;     //Reset the SRAM address
      //frameStartAddr = frame*76800;
      //frameEndAddr = frame*76800 + 76800;
      frameStartAddr = frame*frameSize;
      frameEndAddr = frame*frameSize + frameSize;
      
      startBlock = abs(frameStartAddr/512)*512;
      endBlock = abs(frameEndAddr/512 )*512;
      
      //printf("startBlock = %d\nendBlock = %d\n",startBlock,endBlock);
      
      //printf("%X\n", frameStartAddr);
      //printf("%X\n", frameEndAddr);
      
      //for(i = 0; i <= 0x4B440; i = i+512)
      
      for(i = startBlock; i < endBlock; i = i+512)  //0x4B440 = 640*480, 0x12D10 = 320*240
 //     for(i = frameStartAddr; i < frameEndAddr; i+=512)
      {
        //qu = i / 512; 
        //VGA_NO();
        //SPI_CHOOSE_CARD_ADDR(qu*512);
        SPI_CHOOSE_CARD_ADDR(i);
        SPI_START();
        SPI_END();
        //data=read_4_byte(i);
        
        //printf("read_sd %d address -> %lx\n",i,data);
        //printf("\nGoing into SPI ready wait: %X", i);
        while(!SPI_READY());
        //printf("\nEnd wait.");
        
        if (i == startBlock)
        {   
            k = 64*(frame%8);   //64
        }
        else
        { 
            k=0;
        } 
        //printf("k=%d\n",k);
        //while(!VGA_IDLE());              
        for (;k<512; k=k+4)
            {                
                SPI_CHOOSE_BUFF_ADDR(k);
                data = SPI_GET_BUFF_DATA();
                AES_WRITE_DATA(count,data);
                count++;
 
                while(!VGA_IDLE());
                  /* if (VGA_IDLE())
                  {
                    printf("\n!\n");
                    return;
                  } */
                
               //if(i==startBlock) 
               //printf("\n%08lx",data);
                                
                if(count==4) 
                  {                    
                    //VGA_NO();
                    //while(!VGA_IDLE());      //Wait to leave the rectangle                    
                    for (j=0;j<4;j++)
                      {
                        
                        data = AES_READ_DATA(j);
                        //printf("dt = %08lx\n",data);
                        //while(!VGA_IDLE());
                        VGA_NO();
                        SRAM_WRITE(addr++,(data&0xFFFF0000)>>16);
                        SRAM_WRITE(addr++,(data&0x0000FFFF));
                        VGA_GO();
                        //for(delay = 0; delay<500; delay++);  
                        //if((addr % 0x1440) == 0)      printf(".");
                      }  
                    //VGA_GO();
                    count=0;
                  }
                   
                /*if(k < 2)
                printf("Buffer %d over\n\n",k); */ 
            }
      }
   //break;
   //for(delay = 0; delay<500; delay++);
   //for(q = 0; q <= frameEndAddr; q++)    SRAM_WRITE(q,0);    //Flush SRAM
   //printf("\nData ready. Toggle go%d.\n",q++);
   if (frame >= NUM_FRAME)     frame = 0;
   
  }
  printf("\nDone.");
  return 0;
    
       
}    
