#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);
    */
    
    // Write the passphrase to the AES module
    for(i=0;i<4;i++)
        AES_WRITE_KEY(i,keydata[i]);
        
    printf("\nStarting Decryption...");
  
    for(frame = 0; frame <= NUM_FRAME; frame=frame+1)
    { 
        VGA_GO();
        addr = 0;     //Reset the SRAM address
        frameStartAddr = frame*frameSize;
        frameEndAddr = frame*frameSize + frameSize;
      
        // Calculate the address to the nearest 512-byte multiple        
        startBlock = abs(frameStartAddr/512)*512;
        endBlock = abs(frameEndAddr/512 )*512;
      
        for(i = startBlock; i <= endBlock; i = i+512)
        {           
            m = (i=startBlock)?(frame%8):0;                     
//            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("\nEncryption Completed.");
  return 0;       
}    
