#include <io.h>
#include <system.h>
#include <stdio.h>
#include "DM9000A.h"

#define IOWR_VGA_DATA(base, offset, data) \
    IOWR_16DIRECT(base, (offset) * 2, data) 
#define IORD_VGA_DATA(base, offset) \
    IORD_16DIRECT(base, (offset) * 2)  
#define ROUND_NUMBER 3 

#define MAX_MSG_LENGTH 128

// Ethernet MAC address.  Choose the last three bytes yourself
unsigned char mac_address[6] = { 0x01, 0x60, 0x6E, 0x11, 0x02, 0x0A  };
unsigned int interrupt_number;
unsigned int checksum;
int curMsgChar = 0;
unsigned int receive_buffer_length;
unsigned char receive_buffer[1600];
#define UDP_PACKET_PAYLOAD_OFFSET 42
#define UDP_PACKET_LENGTH_OFFSET 38
#define UDP_PACKET_PAYLOAD (transmit_buffer + UDP_PACKET_PAYLOAD_OFFSET)
  
    int counter=0;
    int x_ball=312;// default x location of ball
    int y_ball=232;// default y location of ball
    int delta_x=1;// delta x of ball
    int delta_y=1;// delta y of ball
    int k; //delay counter
    int l; //delay counter
    int x_lpad=0;//default x location of left paddle
    int y_lpad=150;//default y location of left paddle
    int t=1;// delta x of left paddle 
    int o=1;// delta y of left paddle
    int x_rpad=619;//x location of right paddle
    int y_rpad=150;//y location of right paddle
    int deltax_rpad=1;// delta x of right paddle 
    int deltay_rpad=1;// delta y of right paddle
    
    int loop_length[]={2500,1500,1200};// speed of the ball
    int score_rctrl=0; // the score of the rotary controller
    int score_ai=0; // the score of AI
    int level_stage=1;//default is 1, the total levels will be 3
    int winning_flag=0; //default is 0, when 1, rotary controller wins.otherwise, AI wins.
    int step_level=1;//default is 1(level 1), total number of levels are 3 
    int *pt_loop;
    int divcounter=0;// change the frequency of the refreshment of left padder
    int counter_map[]={64,16,2};
    int *pt_cntmap;
    int temp_x_lpad;
    int temp_y_lpad;
    int temp_x_rpad;
    int temp_y_rpad;
    int update_flag=1;
    
    
    unsigned char transmit_buffer[] = {
  // Ethernet MAC header
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Destination MAC address
  0x01, 0x60, 0x6E, 0x11, 0x02, 0x0F, // Source MAC address
  0x08, 0x00,                         // Packet Type: 0x800 = IP
                          
  // IP Header
  0x45,                // version (IPv4), header length = 20 bytes
  0x00,                // differentiated services field
  0x00,0x9C,           // total length: 20 bytes for IP header +
                       // 8 bytes for UDP header + 128 bytes for payload
  0x3d, 0x35,          // packet ID
  0x00,                // flags
  0x00,                // fragment offset
  0x80,                // time-to-live
  0x11,                // protocol: 11 = UDP
  0xa3,0x43,           // header checksum: incorrect
  0xc0,0xa8,0x01,0x01, // source IP address
  0xc0,0xa8,0x01,0xff, // destination IP address
                          
  // UDP Header
  0x67,0xd9, // source port port (26585: garbage)
  0x27,0x2b, // destination port (10027: garbage)
  0x00,0x88, // length (136: 8 for UDP header + 128 for data)
  0x00,0x00, // checksum: 0 = none
                          
  // UDP payload
  0x41, 0x41, 0x41, ' ', ' ', 0x20, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67,
  0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x73, 0x67
};   

static void ethernet_interrupt_handler() {
  unsigned int receive_status;
  int i;
  
  receive_status = ReceivePacket(receive_buffer, &receive_buffer_length);

  if (receive_status == DMFE_SUCCESS) {

#if 1
    printf("\n\nReceive Packet Length = %d", receive_buffer_length);
    for(i=0;i<receive_buffer_length;i++) {
      if (i%8==0) printf("\n");
      printf("0x%.2X,", receive_buffer[i]);
    }
    printf("\n");
#endif

    if (receive_buffer_length >= 14) {
      //  A real Ethernet packet
      if (receive_buffer[12] == 8 && receive_buffer[13] == 0 &&
      receive_buffer_length >= 34) {
    // An IP packet
    if (receive_buffer[23] == 0x11) {
      // A UDP packet
      if (receive_buffer_length >= UDP_PACKET_PAYLOAD_OFFSET) 
      {
         printf("Received: %s\n",
           receive_buffer + UDP_PACKET_PAYLOAD_OFFSET);
         //check checksum 
      }
    } else {
      printf("Received non-UDP packet\n");
    }
      } else {
    printf("Received non-IP packet\n");
      }
    } else {
      printf("Malformed Ethernet packet\n");
    }

  } else {
    printf("Error receiving packet\n");
  }

  /* Display the number of interrupts on the LEDs */
  interrupt_number++;
  outport(SEG7_DISPLAY_BASE, interrupt_number);

  /* Clear the DM9000A ISR: PRS, PTS, ROS, ROOS 4 bits, by RW/C1 */
  dm9000a_iow(ISR, 0x3F);
              
  /* Re-enable DM9000A interrupts */
  dm9000a_iow(IMR, INTR_set);
}
    
    
    
    
//Rotary Controller Interrupt 
static void interrupt_rotary (void * context, alt_u32 id)
{
    int flag_right_left;    
    counter ++;
    printf ("%d\n",counter); 
    flag_right_left=IORD_16DIRECT(ROTARY_BASE, 0);
    //Rotary Left
    if(flag_right_left==1)
    {   
        if(y_rpad>5)
        {
        y_rpad=y_rpad-5;
        
        }
        printf ("Left\n");
     }
     
    //Rotary Right
    if(flag_right_left==2)
    {
        if(y_rpad<355)
        {
        
        y_rpad=y_rpad+5;
        }
        printf ("Right\n");}
    // reset the interrupt request
    IOWR_16DIRECT(ROTARY_BASE, 0, 0);  
}

void sound()
{
             IOWR_16DIRECT(AUDIO_BASE, 0, 0);
             for(k=0;k<60;k++){} 
             IORD_16DIRECT(AUDIO_BASE, 0); 
}

int main()
{
    //
    alt_u8 key = 0;
    int status = 0;
    unsigned int packet_length;
    
      // Initalize the DM9000 and the Ethernet interrupt handler
    DM9000_init(mac_address);
    interrupt_number = 0;
    alt_irq_register(DM9000A_IRQ, NULL, (void*)ethernet_interrupt_handler); 
    
    //
    int tepm10;
    pt_loop=loop_length;// default is assigning the address of loop_length[0] to p_loop
    pt_cntmap=counter_map; //default *pt_cnt=counter_map[0]
    alt_irq_register( ROTARY_IRQ, NULL,(void*)interrupt_rotary ); // register IRQSOURCE
    
    

      
    
    for(;;)
    {
        
        
        for(k=0;k<*pt_loop;k++)
             {;}//delay
 /*****************************************************************************/
 //          temp_x_lpad=x_lpad;
           temp_y_lpad=y_lpad;
 //          temp_x_rpad=x_rpad;
           temp_y_rpad=y_rpad;             
           
           x_ball=x_ball+delta_x;
           y_ball=y_ball+delta_y;
       
 /*****************************************************************************/      
      switch(level_stage){
      case 1:pt_cntmap=counter_map;
             break;
             
      case 2:pt_cntmap=counter_map+1;
             break;
      
      case 3:pt_cntmap=counter_map+2;
             break;
      default:
             break;                     
      
      }
 /****************************************************************************/      
     if(score_rctrl+score_ai==ROUND_NUMBER){
        
        if(score_rctrl>score_ai){
          winning_flag=1;
        if(level_stage==3){
         level_stage=1;
         pt_loop=loop_length;
        } 
       
        else{
         level_stage++;
         pt_loop++;
        }
        
      }
       
       
       else{
         winning_flag=0;
       }
       
        score_rctrl=0;
        score_ai=0; 
     }      
       
       
                 
 /*******************************************************************************/       
 // left padder control part 
    if(divcounter=*pt_cntmap){
      
       if(delta_x==-1){
            
          if(y_lpad>=y_ball+16){
            if(y_lpad<=0){
              y_lpad=0;
            }
            else if(y_lpad>=360){
              y_lpad=360;
            }
            
            else{
            y_lpad=y_lpad-step_level;
            }
          }
          else if(y_lpad<=y_ball-120){
            
            if(y_lpad<=0){
              y_lpad=0;
            }
            else if(y_lpad>=360){
              y_lpad=360;
            }
            else{
              y_lpad=y_lpad+step_level;
            }
            
          }
          else
            y_lpad=y_lpad;
            
            divcounter=0;
        }
    } 
    
    else{
         divcounter++;
    }     
 /*************************************************************************************/       
     

    if( x_ball==21)
    {
        if(y_ball>=y_lpad & y_ball<=(y_lpad+120))
        {
            delta_x=1;
            sound();
        }
        else
        {
            x_ball=312;
            y_ball=232;
            IOWR_VGA_DATA(VGA_BASE, 0, x_ball);  // ball h
            IOWR_VGA_DATA(VGA_BASE, 1, y_ball);  // ball v
            score_rctrl++; 
            for(k=0;k<2000;k++)
            {
                for(l=0;l<200;l++)
            {;}//delay//delay
            }
            

        }
        
    }
    
    if( x_ball==603)
    {
            if(y_ball>=y_rpad & y_ball<=(y_rpad+120))
        {
            delta_x=-1;
            sound();
        }
        else
        {
            x_ball=312;
            y_ball=232;
            IOWR_VGA_DATA(VGA_BASE, 0, x_ball);  // ball h
            IOWR_VGA_DATA(VGA_BASE, 1, y_ball);  // ball v 
            score_ai++;
            for(k=0;k<2000;k++)
            {
                for(l=0;l<200;l++)
                  {;}//delay//delay
            }
            

        }
    }
 
    if(y_ball==0)
    {
        delta_y=1;
        sound();
    }
    if(y_ball==464)
    {
        delta_y=-1;
        sound();
    }
  /************************************************************************/

      
    IOWR_VGA_DATA(VGA_BASE, 0, x_ball);  // ball h
    IOWR_VGA_DATA(VGA_BASE, 1, y_ball);  // ball v
 
    IOWR_VGA_DATA(VGA_BASE, 2, x_lpad);  // plot x_lpad
    IOWR_VGA_DATA(VGA_BASE, 4, x_rpad);  // plot x_rpad

    
    IOWR_VGA_DATA(VGA_BASE, 3, y_lpad);  // plot y_lpad
    IOWR_VGA_DATA(VGA_BASE, 5, y_rpad);  // plot y_rpad
    

 //   printf ("ball h : %d \n", IORD_VGA_DATA(VGA_BASE, 2));
 //   printf ("ball v : %d \n", IORD_VGA_DATA(VGA_BASE, 3));
 //   printf ("score of AI : %d\n ",score_ai);
 //   printf ("score of ROTARY : %d\n", score_rctrl);
 //   printf ("who wins(1 or 0): %d %d\n", winning_flag,level_stage);
 //   printf ("game round number: %d\n", ROUND_NUMBER);
  }
  return 0;
}
