/*
 * Userspace program that communicates with the led_vga device driver
 * primarily through ioctls
 *
 * Stephen A. Edwards
 * Columbia University
 */

#include <stdlib.h>
#include <stdio.h>
#include "vga_led.h"
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

#include <math.h>

#include "usbmouse.h"



struct libusb_device_handle *mouse;
uint8_t endpoint_address;
int vga_led_fd;


int CtrlP[17]={17};
int start=0;
int change=0;
float base0[10]={0.8333,	0.5855,	0.3924,	0.2473,	0.1432,	0.0734,	0.0310,	0.0092,	0.0012,	0.0000};  //base function coefficient*scale
float base1[10]={3.3333,	3.2751,	3.1143,	2.8712,	2.5665,	2.2206,	1.8541,	1.4874,	1.1412,	0.8358};  //base function coefficient*scale
float base2[10]={0.8333,	1.1382,	1.4842,	1.8507,	2.2174,	2.5635,	2.8687,	3.1124,	3.2741,	3.3333};
float base3[10]={0.0000,	0.0011,	0.0091,	0.0308,	0.0729,	0.1425,	0.2462,	0.3909,	0.5835,	0.8308};

int min(int a, int b){
    if (a<=b)return a;
    else return b;
}

struct coordinate
{
     int a[140];
}y;

struct coordinate getY()
{

     int i=0;
     int j=0;
     float y0[140]={17};
     int index;

     for(i=0; i<14; i++){

         for(j=0;j<10;j++){

             index=10*i+j;

             y0[index]=base0[j]*CtrlP[i]+base1[j]*CtrlP[i+1]+base2[j]*CtrlP[i+2]+base3[j]*CtrlP[i+3];

             if (y0[index]-(int)y0[index]>=0.5){
                 y.a[index]=y0[index]+1;
            }else{
                 y.a[index]=y0[index];
            }

            // printf("y %d ",index);
            // printf("is %f*****************  ",y0[index]);
            // printf("y_int is %d*****************\n",y.a[index]);

         }
     }

    return y;
}


////////updata CtrlP and the modifeid ellipse according to the change of CtrlP
struct coordinate changeY()  //change=0:nochange change=1:increase radius by2 change=2:decrease radius by2  start=position_changed start=0,1,2,...,16
{
    if(change!=1&&change!=2)
    {
    }else if (change==1&&CtrlP[start]>22){
    }else if (change==2&&CtrlP[start]< 3){
    }else{

     float y0[140]={17};
     int i=0;
     int j=0;

     if(change==1&&CtrlP[start]<23){CtrlP[start]+=2;}
     if(change==2&&CtrlP[start]> 2){CtrlP[start]-=2;}



     int index;
     int end=start-4;

     for(i=min(start,13); i>=0&&i>end; i--){

         for(j=0;j<10;j++){

             index=10*i+j;

             y0[index]=base0[j]*CtrlP[i]+base1[j]*CtrlP[i+1]+base2[j]*CtrlP[i+2]+base3[j]*CtrlP[i+3];

             if (y0[index]-(int)y0[index]>=0.5){
                 y.a[index]=y0[index]+1;
            }else{
                 y.a[index]=y0[index];
            }

             printf("y %d ",index);
             printf("is %f*****************  ",y0[index]);
             printf("y_int_changed is %d*****************\n",y.a[index]);

     }

    }
    }
    return y;

}


/* Read and print the segment values */
void print_segment_info() {
  vga_led_arg_t vla;
  int i;

  for (i = 0 ; i < VGA_LED_DIGITS ; i++) {
    vla.digit = i;
    if (ioctl(vga_led_fd, VGA_LED_READ_DIGIT, &vla)) {
      perror("ioctl(VGA_LED_READ_DIGIT) failed");
      return;
    }
    printf("%02x ", vla.segments);
  }
  printf("\n");
}

/* Write the contents of the array to the display */
void write_segments(const unsigned char segs[8])
{
  vga_led_arg_t vla;
  int i;
  for (i = 0 ; i < VGA_LED_DIGITS ; i++) {
    vla.digit = i;
    vla.segments = segs[i];
    if (ioctl(vga_led_fd, VGA_LED_WRITE_DIGIT, &vla)) {
      perror("ioctl(VGA_LED_WRITE_DIGIT) failed");
      return;
    }
  }
}



int main()
{
  struct usb_mouse_packet packet;
  int transferred;
  char keystate[6];
  unsigned char message0[20][8]={0};
  unsigned char message[10]={0};


  mouse=openmouse(&endpoint_address);

  int clear_key = 1;



  vga_led_arg_t vla;
  //printf("01\n");
  static const char filename[] = "/dev/vga_led";// the driver.c
//printf("02\n");
  //initial position of every object and its flag,
   //static unsigned int message[6]={0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
  

  printf("VGA axis Userspace program started\n");

  if ( (vga_led_fd = open(filename, O_RDWR)) == -1) {
    fprintf(stderr, "could not open %s\n", filename);
    return -1;
  }

  //printf("initial state: ");
  print_segment_info();

  write_segments(message);


  //printf("current state: ");
  print_segment_info();


  

  int seed=7;
  int rad=24;
  int i;
  int j;
  int k;
  int mes_1;
  int mes_2;
  int index;


     srand(seed);
     for (i=0;i<17;i++){
         CtrlP[i]=rand()%rad+1;
     }
     y=getY();

while(1){
    libusb_interrupt_transfer(mouse, endpoint_address,(unsigned char *) &packet, 
			sizeof(packet),&transferred, 10);

    //printf("packet is %d ",sizeof(packet));
   // printf("this is trans %d ",transferred);
    //printf("endpoint_address %05x\n", endpoint_address);



      //sprintf(keystate, "%02x %02x %02x", packet.various_func, packet.X_displacement,
	//      packet.Y_displacement/*packet.keycode[2],packet.keycode[3],packet.keycode[4],packet.keycode[5]*/);
      //printf("%s\n", keystate);

      

     //seed=(seed+1)%10;



      //    printf("this is control Point %d before change",6);
      // printf(" of value %d \n",CtrlP[5]);

     start=5;
     change=0;
     if(packet.various_func==1){change=1;}
     if(packet.various_func==2){change=2;}

     y=changeY();










  index=0;


  for (mes_1=0;mes_1<20;mes_1++){
    for (mes_2=0;mes_2<8;mes_2++){
        if(mes_2==0){
            message0[mes_1][mes_2]=mes_1;
	      //   printf("this is message offset %d ",mes_1);
         //   printf("**********************************************\n");
        }else{
            message0[mes_1][mes_2]=y.a[index];
            index=index+1;
            //printf("this is message  %d ",mes_2);
           // printf("the content is %d \n",message0[mes_1][mes_2]);
	      printf("the mouse displacement is %x,%x \n",message[8],message[9]);
        }
    }
  }

  //printf("VGA LED Userspace program started\n");

  if ( (vga_led_fd = open(filename, O_RDWR)) == -1) {
    fprintf(stderr, "could not open %s\n", filename);
    return -1;
  }




  printf("initial state: ");
  print_segment_info();

  for(j=0;j<20;j++){

      for(k=0;k<8;k++){
          message[k]=message0[j][k];
      }
  if((packet.X_displacement & 0x80)==0x80)
  message[8]=(0x80|(((0xff-(packet.X_displacement & 0x7f)) >> 4)& 0xf7));
  else message[8]=packet.X_displacement >>4;
  if((packet.Y_displacement & 0x80)==0x80)
  message[9]=(0x80|(((0xff-(packet.Y_displacement & 0x7f)) >> 4)& 0xf7));
  else message[9]=packet.Y_displacement >>4;
  write_segments(message);
  
  }
 /* message[8]=packet.X_displacement;
  message[9]=packet.Y_displacement;
  write_segments(message);
  usleep(1000000);
  */

  }
  //printf("VGA LED Userspace program terminating\n");
  return 0;
}
