#include <io.h>
#include <system.h>
#include <stdio.h>
//write data
#define IOWR_DATA(base, offset, data) \
		IOWR_16DIRECT(base, (offset) * 2, data)
//read data
#define IORD_DATA(base, offset) \
		IORD_16DIRECT(base, (offset) * 2)

#define RD_SYNC 0
#define RD_start 1
#define WR_start 2
#define WR_readselects 3
#define RD_readselects 4
#define WR_aggr 5
#define WR_box 6
#define WR_reset 7
#define RD_leftclick 0
#define RD_rightclick 1
#define RD_dx 2
#define RD_dy 3
#define RD_snum 4

/*void delay(int input){

    int i, j;
    for (i=0;i<input;i++){
        j=0;
    }

}*/

int main()
{
	//alt_u8 blank = 0;
	int i = 0;
	//bottom right corner of pixel dump
	alt_u16 xcoordinate = 0;
	alt_u16 ycoordinate = 0;

	int outOfBoundsX = 0;
	int outOfBoundsY= 0;
	alt_8 deltaX;
	alt_8 deltaY;

	int isOutOfBounds=0;
	//alt_8 lastDeltaX = IORD_DATA(GPIO_BASE, RD_dx);
	//alt_8 lastDeltaY = IORD_DATA(GPIO_BASE, RD_dy);
	//alt_u16 last_sample = IORD(GPIO_BASE, RD_snum);
	//alt_u16 this_sample;
	//alt_u16 writeable = 1;
	alt_u16 leftclick = 1;

	int xcoordinate_temp = 0;
	int ycoordinate_temp = 0;

	//alt_u16 start_RAM = 0;

	IOWR_DATA(VGA_BASE, WR_readselects, 1);
	IOWR_DATA(VGA_BASE,WR_start,0);
	IOWR_DATA(VGA_BASE, WR_reset, 0);

	alt_u16 lastcurrentAllRAMS=0x0;

	for(;;){


		//reset
		if(IORD_DATA(GPIO_BASE, RD_rightclick)==0){
			IOWR_DATA(VGA_BASE, WR_aggr, 0);
			IOWR_DATA(VGA_BASE, WR_start, 0);
			xcoordinate = 0;
			ycoordinate = 0;
			outOfBoundsX = 0;
			outOfBoundsY = 0;
			isOutOfBounds=0;
			IOWR_DATA(VGA_BASE, WR_aggr, 1);
			for(i=0; i<15; i++){
				IOWR_DATA(VGA_BASE, WR_reset, 1);
			}
			IOWR_DATA(VGA_BASE, WR_aggr, 0);

			continue;
		}
		else {
			IOWR_DATA(VGA_BASE, WR_reset, 0);
			//read from address 1 for x position of sample
			deltaX = IORD_DATA(GPIO_BASE, RD_dx);

			//read from address 2 for y position of sample
			deltaY = IORD_DATA(GPIO_BASE, RD_dy);

			leftclick = IORD_DATA(GPIO_BASE, RD_leftclick);
			//IOWR_DATA(VGA_BASE, WR_reset, 0);



			alt_u16  currentAllRAMS = IORD_DATA(GPIO_BASE,RD_snum);
			//printf("%x\n",currentAllRAMS);

			if (currentAllRAMS == lastcurrentAllRAMS){
				continue;
			}
			alt_u16 currentRAM1 = currentAllRAMS & 0xF;
			alt_u16 currentRAM2 = (currentAllRAMS>>4) & 0xF;
			alt_u16 currentRAM3 = (currentAllRAMS>>8) & 0xF;
			alt_u16  currentRAM4 = (currentAllRAMS>>12) & 0xF;
			alt_u16  lastRAM1 = lastcurrentAllRAMS & 0xF;
			alt_u16  lastRAM2 = (lastcurrentAllRAMS>>4) & 0xF;
			alt_u16  lastRAM3 = (lastcurrentAllRAMS>>8) & 0xF;
			alt_u16  lastRAM4 = (lastcurrentAllRAMS>>12) & 0xF;
			alt_u16  ramWhichIsDifferent;
			if(currentRAM1!=lastRAM1){
				//printf("%x\n",currentAllRAMS);
				ramWhichIsDifferent = 0x1;
			}
			else if(currentRAM2!=lastRAM2){
				//printf("%x\n",currentAllRAMS);
				ramWhichIsDifferent=0x2;
			}
			else if(currentRAM3!=lastRAM3){
				//printf("%x\n",currentAllRAMS);
				ramWhichIsDifferent=0x4;
			}
			else{
				//printf("%x\n",currentAllRAMS);
				ramWhichIsDifferent=0x8;
			}
			IOWR(VGA_BASE, WR_readselects, ramWhichIsDifferent);

			lastcurrentAllRAMS = currentAllRAMS;


			if (!isOutOfBounds){
				xcoordinate_temp=xcoordinate-deltaX;
				ycoordinate_temp=ycoordinate+deltaY;

			}else{
				xcoordinate_temp=outOfBoundsX-deltaX;
				ycoordinate_temp=outOfBoundsY+deltaY;
			}

			//Boundary conditions
			printf("xcoordinate_temp is %d\n", xcoordinate_temp);
			printf("ycoordinate_temp is %d\n", ycoordinate_temp);
			IOWR_DATA(VGA_BASE, WR_box, 0);
			IOWR_DATA(VGA_BASE, WR_aggr, 0);
			if(xcoordinate_temp>=0 && ycoordinate_temp>=0 && xcoordinate_temp<=112 && ycoordinate_temp<=112){
				xcoordinate-=deltaX;
				ycoordinate+=deltaY;

				outOfBoundsX = xcoordinate;
				outOfBoundsY = ycoordinate;

				if ((deltaX == 0) && (deltaY == 0)){
					printf("er\n");
				}

				//write back new position
				IOWR_DATA(VGA_BASE, WR_start, ycoordinate+xcoordinate*128);

				if((!leftclick)){
					//green if writing
					//IOWR_DATA(VGA_BASE, WR_box, 1);
					//for(i=0; i<15; i++){
					//	IOWR_DATA(VGA_BASE, WR_aggr, 1);
					//}

					//printf("ag\n");
					//IOWR_DATA(VGA_BASE, WR_aggr, 0);
				}else{
					//yellow if not writing
					//IOWR_DATA(VGA_BASE, WR_box, 0);
					//IOWR_DATA(VGA_BASE, WR_aggr, 0);
				}
				isOutOfBounds=0;
			}else{
				printf("got here");
				outOfBoundsX-=deltaX;
				outOfBoundsY+=deltaY;

				//red if out of bounds
				//IOWR_DATA(VGA_BASE, WR_box, 2);

				isOutOfBounds=1;

				if(xcoordinate_temp<0){
					//bottom right corner
					if(ycoordinate_temp<0){
						IOWR_DATA(VGA_BASE, WR_start, 0);
					//top right corner
					}else if(ycoordinate_temp>112){
						IOWR_DATA(VGA_BASE, WR_start, 112);
					}else{
						ycoordinate=ycoordinate_temp;
						IOWR_DATA(VGA_BASE, WR_start, ycoordinate_temp);
					}
				}
				else if(ycoordinate_temp<0){
					//bottom right corner
					if(xcoordinate_temp<0){
						IOWR_DATA(VGA_BASE, WR_start, 0);
					//bottom left corner
					}else if(xcoordinate_temp>112){
						IOWR_DATA(VGA_BASE, WR_start, 112*128);
					}else{
						xcoordinate=xcoordinate_temp;
						IOWR_DATA(VGA_BASE, WR_start, xcoordinate_temp*128);
					}
				}
				else if(xcoordinate_temp>112){
					//bottom left corner
					if(ycoordinate_temp<0){
						IOWR_DATA(VGA_BASE, WR_start, 112*128);
					//top left corner
					}else if(ycoordinate_temp>112){
						IOWR_DATA(VGA_BASE, WR_start, 112+112*128);
					}else{
						ycoordinate=ycoordinate_temp;
						IOWR_DATA(VGA_BASE, WR_start, 112*128 + ycoordinate_temp);
					}
				}
				else if(ycoordinate_temp>112){
					//top right corner
					if(xcoordinate_temp<0){
						IOWR_DATA(VGA_BASE, WR_start, 112);
					//top left corner
					}else if(xcoordinate_temp>112){
						IOWR_DATA(VGA_BASE, WR_start, 112+112*128);
					}else{
						xcoordinate=xcoordinate_temp;
						IOWR_DATA(VGA_BASE, WR_start, xcoordinate_temp*128 + 112);
					}
				}
			}
		}
	}
}




