#include <io.h>
#include <system.h>
#include <stdio.h>
#include <alt_types.h>
#include <math.h>
#include "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 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_BUSY()                  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()
{      
  printf("\nWelcome to the AES 128-bit decryption project!");  
  
  unsigned int data = 0;
  unsigned long int i = 0, addr=0;
  int j =0,count=0,k=0, m=0, limit=0;
  unsigned long int frame = 0, frameStartAddr=0, frameSize=0x13040;    //0x13038
  unsigned long int frameEndAddr=0, startBlock, endBlock;    
  unsigned long int keydata[4]=//{0x00000000,0x00000000,0x00000000,0x00000000};
                               {0x2b28ab09,0x7eaef7cf, 0x15d2154f, 0x16a6883c}; //This is the passphrase!
  
  printf("\n\nPlease enter the decryption key (32 hex digits).\n");
  
 /* 
  //Passphrase keyboard entry; If this section is 
  key = getKey();
  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");         
    printf("\nWriting into SRAM");
  
  for(frame = 0; frame <= NUM_FRAME; frame=frame+1)
  { 
      VGA_GO();
      addr = 0;     //Reset the SRAM address
      frameStartAddr = frame*frameSize;
      frameEndAddr = frame*frameSize + frameSize;
      
      startBlock = abs(frameStartAddr/512)*512;
      endBlock = abs(frameEndAddr/512 )*512;
      
      for(i = startBlock; i <= endBlock; i = i+512)
      {        
                        
        if (i == startBlock)
        {   
            m = (frame%8);   //64
        }
        else
        { 
            m=0;
        }
        if (m == 0)
        {
            SPI_CHOOSE_CARD_ADDR(i);
            SPI_START();
            SPI_END();
        }
        k = m*64;
        
        while(!SPI_READY());
           
        if (i == (endBlock))
        {
            limit = 64*((frame+1)%8);
        }
         else
            limit = 512;
                 
        for (;k<limit; k=k+4)
            {                
                SPI_CHOOSE_BUFF_ADDR(k);
                data = SPI_GET_BUFF_DATA();
                AES_WRITE_DATA(count,data);
                count++;
                if(k%16 == 0)
                  while(!VGA_BUSY());                                
                if(count==4) 
                  {           
                    for (j=0;j<4;j++)
                      {
                        data = AES_READ_DATA(j);
                        VGA_NO();
                        SRAM_WRITE(addr++,(data&0xFFFF0000)>>16);
                        SRAM_WRITE(addr++,(data&0x0000FFFF));
                        VGA_GO();
                      }  
                    count=0;
                  }
            }
      }
   //if(frame % 1000)   printf("."); 
   //if(frame >= NUM_FRAME)     frame = 0;
  }
  printf("\nDone.");
  return 0;       
}    
