/*
             LUFA Library
     Copyright (C) Dean Camera, 2015.

  dean [at] fourwalledcubicle [dot] com
           www.lufa-lib.org
*/

/*
  Copyright 2015  Dean Camera (dean [at] fourwalledcubicle [dot] com)

  Permission to use, copy, modify, distribute, and sell this
  software and its documentation for any purpose is hereby granted
  without fee, provided that the above copyright notice appear in
  all copies and that both that the copyright notice and this
  permission notice and warranty disclaimer appear in supporting
  documentation, and that the name of the author not be used in
  advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.

  The author disclaims all warranties with regard to this
  software, including all implied warranties of merchantability
  and fitness.  In no event shall the author be liable for any
  special, indirect or consequential damages or any damages
  whatsoever resulting from loss of use, data or profits, whether
  in an action of contract, negligence or other tortious action,
  arising out of or in connection with the use or performance of
  this software.
*/

/*

ADC7 = X Axis Pro Micro pin A0
ADC6 = Y Axis Pro Micro pin A1
PORTD7 = X Axis PWM = Pro Micro Pin 06
PORTD0 = Y Axis PWM = Pro Micro Pin 03  -> to PORTC6 = Pro Micro Pin 05
PORTB6 = X Axis Direction left = Pro Micro pin 10
PORTB1 = X Axis Direction right = Pro Micro pin 15
PORTB2 = Y Axis Direction left = Pro Micro pin 14
PORTB3 = Y Axis Direction right = Pro Micro pin 16
PORTB4 = load					= Pro Micro pin 8
PORTB5 = Data1					= Pro Micro pin 9
PORTD1 = Data2					= Pro Micro pin 2 -> to PORTD4 = Pro Micro Pin 04
PORTE6 = clock					= Pro Micro pin 7



uncomented Port-bits set for testing 
*/


#include "Joystick.h"
#include <math.h>
#include <stdlib.h>


#define maxeffect  15
volatile uint8_t nummerID = 2;
// remember to change to better/variable  Memory usage 
static volatile TEffectState EffectStates[maxeffect+1];	// one for each effect (array index 0 is unused to simplify things)
static volatile Condition_Output_Data_t EffectCondition1[maxeffect +1];
static volatile Condition_Output_Data_t EffectCondition2[maxeffect +1];
static volatile SetEffect_Data EffectSetting[maxeffect+1];
static volatile Envelope_Output_Data_t EffectEnvelope[maxeffect +1];
static volatile Periodic_Output_Data_t EffectPeriodic[maxeffect +1];
static volatile ConstantForce_Output_Data_t EffectMag[maxeffect +1];
static volatile RampForce_Output_Data_t EffectRamp[maxeffect +1];
volatile PIDStatus_Input_Data_t pidState;	// For device status // 2=Enable Actuators, 1=Disable Actuators, 3=Stop All Effects, 4=Reset, 5=Pause, 6=Continue
volatile uint16_t XAchse;
volatile uint16_t YAchse;
volatile int16_t forcex; //signed 
volatile int16_t forcey; //signed 
volatile uint8_t time1;
volatile uint16_t posmemox;
volatile uint16_t posmemoy;
volatile uint8_t merk =0;
volatile uint16_t stepper =0;

//volatile uint16_t memo1 =0;



/** Main program entry point. This routine configures the hardware required by the application, then
 *  enters a loop to run the application tasks in sequence.
 */
int main(void)
{

	SetupHardware();
	GlobalInterruptEnable();
	sei();

	 DDRB = 0xff;
	 PORTB = 0xff;
//original STK600 pins
	 //  PORTF 0 = xAchse
	 //  PORTF 1 = yAchse
	 //PORT B 0-3 direction
	 //PORT B 7 PWM Y
	 //PORT D 0 PWM X
	 
//	 DDRC = 0xff;
//	 PORTC = 0xff;
	  DDRD = 0xff;
      PORTD = 0xff;

 // PORTD ^= 0b10000000;
 //PORTD ^= 0b00000001;  
	// DDRD =  0b010000001;
	// PORTD = 0b010000001;
	 pidState.status = 0x04;
	//  PORTD =0b000000001;
	for (;;)
	{
		einlesen();
		
		HID_Task();
		USB_USBTask();
		FFB_Task();
	}
}

void einlesen(void)
{
	 ADMUX = 0b00100111;
	 ADCSRA |= (1<<ADSC);
	 while (ADCSRA & (1<<ADSC) ) {     }
		 
	 ADMUX = 0b00100111;
	 ADCSRA |= (1<<ADSC);
	 while (ADCSRA & (1<<ADSC) ) {     }
	XAchse = ADCH;
	
	
	 	 ADMUX = 0b00100110;
	 	 ADCSRA |= (1<<ADSC);
	 	 while (ADCSRA & (1<<ADSC) ) {     }
			  
	 ADMUX = 0b00100110;
	 ADCSRA |= (1<<ADSC);
	 while (ADCSRA & (1<<ADSC) ) {     }
	 YAchse = ADCH;
	 
}



void Timing(uint8_t i)
{
	if (EffectSetting[i].duration != 0)
	{
		EffectSetting[i].aktual_time +=  time1;	
		if ( EffectSetting[i].aktual_time >= EffectSetting[i].duration)
		{
			EffectStates[i].state = 1;
			EffectSetting[i].aktual_time = 0;
		}
	}
}

ISR (TIMER1_COMPA_vect)
{
	time1 ++;
//keep it fast	
}

void FFB_Task(void)
{
	//add exit jumps and step -USB- step 
	//Motoren
	if (pidState.status == 0x04)
	{
 		//Auto Center   
		 //max to remember 32.767
		OCR4A = 255-((abs(XAchse - 128))*2);
		OCR4B = 255-((abs(YAchse - 128))*2);
		if (XAchse > 128)
		{
			 PORTB |=(1<<6); PORTB &=~(1<<1);
		}
		 else
		{
			 PORTB &= ~(1<<6);	PORTB |=(1<<1);
		}  
		if (YAchse > 128)
		{
			PORTB |=(1<<2);		PORTB &=~(1<<3);
		}
		else
		{
			PORTB &= ~(1<<2);	PORTB |=(1<<3);
		}
	}
	else if (pidState.status == 0x03)
	{
		forcex =0;
		forcey =0;
		merk =0;
		uint8_t alloff = 0;
		//	PORTB &= ~(1<<5);//test
		for (uint8_t i=0; i<maxeffect; i++) 
		{
			if (EffectStates[i].state == 2)
			{
			//	merk =1;
				alloff = 1;
			
				if (EffectSetting[i].effectType == 1)	// Constant
				{
					//merk =1;
					Timing(i);
					constant(i);
				//	if (EffectEnvelope[i].attackTime > 5000) merk =1;
					
				}
				if (EffectSetting[i].effectType == 2)	// Ramp	
				{	
					Timing(i);
					ramp(i);
				}
				if (EffectSetting[i].effectType == 3)	// Square	
				{
					Timing(i);
					squarset(i);
				}
				if (EffectSetting[i].effectType == 4)	// Sin	
				{
					Timing(i);
					sinset(i);
				}
				if (EffectSetting[i].effectType == 5)	// triangle	
				{
					Timing(i);
					squarset(i);
				}
				if (EffectSetting[i].effectType == 6)	//saw up	
				{
					Timing(i);
					sawupset(i);
				}
				if (EffectSetting[i].effectType == 7)	// saw down	
				{
					Timing(i);
					squarset(i);
				}
				if (EffectSetting[i].effectType == 8) // Spring
				{
				  Timing(i);
				   condition(XAchse,YAchse,i);
				   
			  	}
				if (EffectSetting[i].effectType == 9) // Dampfer
				{
					Timing(i);	 	
					condition(128-((posmemox-XAchse)*5),128-((posmemoy-YAchse)*5),i);
					
				}
				if (EffectSetting[i].effectType == 10) //interia
				{
						Timing(i);
							condition(128-((posmemox-XAchse)*5),128-((posmemoy-YAchse)*5),i);
							
				}
		  	}	
		}
	//	if (forcex != 0)
	//	{
		if (alloff == 1)
		{
			 if (forcex > 0)
			 {
				 PORTB |=(1<<6); PORTB &=~(1<<1);
			 }
			 else
			 {
				 PORTB &= ~(1<<6);	PORTB |=(1<<1);
			 }
			 if (forcex > 127) forcex = 127;
			 if (forcex < -127) forcex = -127;
			 
			OCR4A =255- (abs(forcex)*2);
			//OCR0B = 255-((abs(YAchse - 128))*2);
	//	}
	//	if (forcey != 0)
	//	{
			if (forcey > 0)
			{
				 PORTB |=(1<<2);		PORTB &=~(1<<3);
			}
			else
			{
				PORTB &= ~(1<<2);	PORTB |=(1<<3);
			}
			if (forcey > 127) forcey = 127;
			if (forcey < -127) forcey = -127;
			OCR4B =255- abs(forcey)*2;		
	//	}
	}
	else
	{
	//	merk =1;
		OCR4B = 255;
		OCR4A = 255;
	}
		if (merk ==1)PORTB &= ~(1<<4);
		if (merk ==0)PORTB |=  (1<<4);
		
		
	}
	else 
	{


	}
	if (time1 > 0)
	{
		stepper += time1;
		if (stepper >= 1000)
		{
			PORTB ^= (1<<5);
			stepper = 0;
		}
		
		time1 = 0;
		posmemox = XAchse;
		posmemoy = YAchse;
	}
	
}
void sawupset(uint8_t i)
{
	float direction = (EffectSetting[i].directionX*1.4117)*0.01745	;//360/255 = 1,4117
	uint8_t Power ;
	int8_t Powerrange = (EffectRamp[i].end+127) - (EffectRamp[i].start+127);
	float powerstep = (Powerrange /EffectSetting[i].duration);
	Power = (EffectRamp[i].start+127) + (((powerstep/100)*EffectSetting[i].aktual_time)*0.4);
	if (Power > 255 ) Power =255;
	forcex =sin(direction) *(Power);
	forcey = cos(direction)*(Power);
}

void sinset(uint8_t i)
{
//call
	
}



void squarset(uint8_t i)
{
	//merk =1;
	float direction = (EffectSetting[i].directionX*1.4117)*0.01745	;
	uint8_t Power =245 ;
	EffectPeriodic[i].ortung += time1;
	if (EffectPeriodic[i].ortung  > EffectPeriodic[i].period) EffectPeriodic[i].ortung  -= EffectPeriodic[i].period;
	//if (EffectSetting[i].duration > 2000)
	//{
	//		merk =1;
	//}
	if (EffectPeriodic[i].ortung  > (EffectPeriodic[i].period*0.5))
	{
		Power = EffectPeriodic[i].offset + (EffectPeriodic[i].magnitude);
	} 
	else
	{
		Power = EffectPeriodic[i].offset - (EffectPeriodic[i].magnitude);
	}

	forcex =sin(direction) *(Power);
	forcey = cos(direction)*(Power);
	
}

void ramp(uint8_t i)
{
	float direction = (EffectSetting[i].directionX*1.4117)*0.01745	;//360/255 = 1,4117
	uint8_t Power ;
	int8_t Powerrange = (EffectRamp[i].end+127) - (EffectRamp[i].start+127);
	float powerstep = (Powerrange /EffectSetting[i].duration);
	Power = (EffectRamp[i].start+127) + (((powerstep/100)*EffectSetting[i].aktual_time)*0.4);
	if (Power > 255 ) Power =255;
	  forcex =sin(direction) *(Power);
	  forcey = cos(direction)*(Power);

}

void constant(uint8_t i)
{
  float direction = (EffectSetting[i].directionX*1.4117)*0.01745	;//360/255 = 1,4117
 uint16_t Power = EffectMag[i].magnitude;
   //PORTB = EffectSetting[i].duration;
   
  // if (EffectSetting[i].duration == 65535) merk =1;;
 /* if (EffectSetting[i].duration != 65535 )
  {
	 if (  EffectEnvelope[i].attackTime > EffectSetting[i].aktual_time )//EffectEnvelope[i].attackTime != 0 |||| EffectEnvelope[i].attackLevel !=0
	  {	  	
	//	uint16_t Powerlvl = abs(Power) - (EffectEnvelope[i].attackLevel*0.0255);
	//	float Powerstep = Powerlvl / EffectEnvelope[i].attackTime;  
		//PORTB = Powerstep*1000;
		Power =EffectEnvelope[i].attackLevel +  (( (abs(Power) - (EffectEnvelope[i].attackLevel*0.0255)) / EffectEnvelope[i].attackTime) * EffectSetting[i].aktual_time);//
	  }
  }*/
  forcex =sin(direction) *(Power*0.5);
  forcey = cos(direction)*(Power*0.5);
}


void condition(uint16_t xwert,uint16_t ywert,uint8_t i)	
			{

					float offsetx = (EffectCondition1[i].cpOffset *0.0255);
					float offsety = EffectCondition2[i].cpOffset *0.0255;
					float dead1 = EffectCondition1[i].deadBand *0.0128;
					float dead2 = EffectCondition2[i].deadBand *0.0128;
					 if ( (xwert - (offsetx-dead1)) < 0) forcex = (xwert - (offsetx-dead1))*(EffectCondition1[i].negativeCoefficient*0.0001);
					 if ( (xwert - (offsetx+dead1)) >= 0)   forcex = (xwert - (offsetx+dead1))*(EffectCondition1[i].positiveCoefficient*0.0001);
					 if ( (ywert - (offsety-dead2)) < 0) forcey = (ywert - (offsety-dead2))*(EffectCondition2[i].negativeCoefficient*0.0001);
					 if ( (ywert - (offsety+dead2)) >= 0) forcey = (ywert - (offsety+dead2))*(EffectCondition2[i].positiveCoefficient*0.0001);
				if (EffectCondition1[i].positiveSaturation != 0  && forcex > ((EffectCondition1[i].positiveSaturation*0.0128))) 
						forcex =	((EffectCondition1[i].positiveSaturation*0.0128));
				if (EffectCondition1[i].negativeSaturation != 0  && forcex <  -((EffectCondition1[i].negativeSaturation*0.0128)))
							forcex =	-((EffectCondition1[i].negativeSaturation*0.0128));		
				if (EffectCondition2[i].positiveSaturation != 0  && forcey > ((EffectCondition2[i].positiveSaturation*0.0128)))
					forcey =	((EffectCondition2[i].positiveSaturation*0.0128));
				if (EffectCondition2[i].negativeSaturation != 0  && forcey <  -((EffectCondition2[i].negativeSaturation*0.0128)))
					forcey =	-((EffectCondition2[i].negativeSaturation*0.0128));
			
				   }

/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void)
{
	MCUSR &= ~(1 << WDRF);
	wdt_disable();
	clock_prescale_set(clock_div_1);
	ADMUX = 0b01100000; 
	ADCSRA = 0b11000010;
	 // ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung 
  while (ADCSRA & (1<<ADSC) ) {     }
  (void) ADCW;
 TCCR4A = 0b10100011;
 TCCR4B = 0b00000011;

 TCCR1A = 0b00000000;
 TCCR1B = 0b00001010;
 TIFR1  = 0b00000010;
 
 TCNT1 = 0;
 OCR1A = 2100; //vergleichs wert 1400
 //OCR1A = F_CPU / 1000/8;
 TIMSK1 = 0b00000010;
//	Joystick_Init();
//	Buttons_Init();
	USB_Init();
}

/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
 *  of the USB device after enumeration - the device endpoints are configured and the joystick reporting task started.
 */
void EVENT_USB_Device_ConfigurationChanged(void)
{
	bool ConfigSuccess = true;

	/* Setup HID Report Endpoint */
	ConfigSuccess &= Endpoint_ConfigureEndpoint(JOYSTICK_EPADDR, EP_TYPE_INTERRUPT, JOYSTICK_EPSIZE, 1);
//	LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
}






void NewEffect(New_Efect_data* inData, PID_Report *outData)
{
		while (EffectStates[nummerID].state != 0)
		{
			if (nummerID >= maxeffect)
			break;	// the last spot was taken
			nummerID++;
		}

		EffectStates[nummerID].state = 1;
		EffectSetting[nummerID].effectType = inData->effectType;
		//memset((void*) &gEffectStates[id].data, 0, sizeof(gEffectStates[id].data));
		 
	if (nummerID == maxeffect)
	{
		 outData->loadStatus=2;  //Full
	}
	else
	{
		outData->loadStatus=1;	//ok
	}
    
	outData->effectBlockIndex = nummerID;
	outData->reportId =6;
	outData->ramPoolAvailable = 0xFFFF;	

	
}
void SetEffect(SetEffect_Output_Data *data)
	{
	EffectSetting[data->effectBlockIndex].directionX = data->directionX;
	EffectSetting[data->effectBlockIndex].directionY = data->directionY;
	EffectSetting[data->effectBlockIndex].duration = data->duration;
	EffectSetting[data->effectBlockIndex].aktual_time = 0;
	
	EffectSetting[data->effectBlockIndex].effectBlockIndex = data->effectBlockIndex;
	//EffectSetting[data->effectBlockIndex].effectType = data->effectType;  // no longer used
	EffectSetting[data->effectBlockIndex].enableAxis = data->enableAxis;
	EffectSetting[data->effectBlockIndex].gain = data->gain;
	EffectSetting[data->effectBlockIndex].samplePeriod= data->samplePeriod;
	EffectSetting[data->effectBlockIndex].startDelay= data->startDelay;
	EffectSetting[data->effectBlockIndex].triggerButton= data->triggerButton;
	EffectSetting[data->effectBlockIndex].triggerRepeatInterval= data->triggerRepeatInterval;
	}

void BlockFree(USB_FFBReport_BlockFree_Output_Data_t *data)
{
	if (data->effectBlockIndex == 0xFF)
	{	// all effects
		for (uint8_t i=0; i<maxeffect; i++)
		{
			EffectStates[i].state = 0;	
			EffectSetting[i].aktual_time = 0;
		}
			
	}
	else
	{
		EffectStates[data->effectBlockIndex].state = 0;
		EffectSetting[data->effectBlockIndex].aktual_time = 0;
	}
}

void SetCondition(USB_FFBReport_SetCondition_Output_Data_t *data)
{
	switch (data->parameterBlockOffset)
	{
		case 0:
		 EffectCondition1[data->effectBlockIndex]. cpOffset = data-> cpOffset;
		 EffectCondition1[data->effectBlockIndex].positiveCoefficient = data->positiveCoefficient;
		 EffectCondition1[data->effectBlockIndex].negativeCoefficient = data->negativeCoefficient;
		 EffectCondition1[data->effectBlockIndex].positiveSaturation = data->negativeSaturation;
		 EffectCondition1[data->effectBlockIndex].negativeSaturation = data->positiveSaturation;
		 EffectCondition1[data->effectBlockIndex].deadBand = data->deadBand;
		 break;
		case 1: 
		 EffectCondition2[data->effectBlockIndex]. cpOffset = data-> cpOffset;
		 EffectCondition2[data->effectBlockIndex].positiveCoefficient = data->positiveCoefficient;
		 EffectCondition2[data->effectBlockIndex].negativeCoefficient = data->negativeCoefficient;
		 EffectCondition2[data->effectBlockIndex].positiveSaturation = data->negativeSaturation;
		 EffectCondition2[data->effectBlockIndex].negativeSaturation = data->positiveSaturation;
		 EffectCondition2[data->effectBlockIndex].deadBand = data->deadBand;	 
		break;
		
	}
}

void SetEnvelope(USB_FFBReport_SetEnvelope_Output_Data_t *data)
{
  EffectEnvelope[data->effectBlockIndex].attackLevel = data->attackLevel;
  EffectEnvelope[data->effectBlockIndex].attackTime = data->attackTime;
  EffectEnvelope[data->effectBlockIndex].fadeLevel = data->fadeLevel;
  EffectEnvelope[data->effectBlockIndex].fadeTime = data->fadeTime;
}

void SetPeriodic(USB_FFBReport_SetPeriodic_Output_Data_t *data)
{
  EffectPeriodic[data->effectBlockIndex].magnitude = data->magnitude;
  EffectPeriodic[data->effectBlockIndex].offset = data->offset;
  EffectPeriodic[data->effectBlockIndex].period = data->period;
  EffectPeriodic[data->effectBlockIndex].phase = data->phase;
  EffectPeriodic[data->effectBlockIndex].ortung = 0;
  
}


void Setmag(USB_FFBReport_SetConstantForce_Output_Data_t *data)
{
  EffectMag[data->effectBlockIndex].magnitude  = data->magnitude;	
}


void SetRampForce(USB_FFBReport_SetRampForce_Output_Data_t *data)
{
	EffectRamp[data->effectBlockIndex].end  = data->end;
	EffectRamp[data->effectBlockIndex].start = data->start;
}

void EffectOperation(USB_FFBReport_EffectOperation_Output_Data_t *data)
{

	uint8_t eid = data->effectBlockIndex;

	if (eid == 0xFF)
	eid = 0x7F;	// All effects
// Start
	if (data->operation == 1){	EffectStates[data->effectBlockIndex].state =2;	}
	else if (data->operation == 2)
	{	// StartSolo
		for (uint8_t i=0; i<maxeffect; i++)
		{
			EffectStates[i].state = 0;	
			EffectSetting[i].aktual_time =0;
			} //stop all
		EffectStates[data->effectBlockIndex].state =2;					//Start 
		//EffectSetting[data->effectBlockIndex].aktual_time =0;
	}
	else if (data->operation == 3)	
	{
		EffectStates[data->effectBlockIndex].state = 1;
		EffectSetting[data->effectBlockIndex].aktual_time =0;
	 }  //stop
	}
		
		
		
		
void DeviceControl(USB_FFBReport_DeviceControl_Output_Data_t *data)
	{
	pidState.status = data->control;
	// 2=Enable Actuators, 1=Disable Actuators, 3=Stop All Effects, 4=Reset, 5=Pause, 6=Continue
	

	if (pidState.status  == 0x03)
		{
		// Stop all effects (e.g. FFB-application to foreground)
		for (uint8_t i=0; i<maxeffect; i++)
		{
			if (EffectStates[i].state > 0)
			{
			EffectStates[i].state = 1;
			}
		}
		// Disable auto-center spring and stop all effects
	
		}
	else if (pidState.status == 0x04)
		{
		// Reset (e.g. FFB-application out of focus)
		// Enable auto-center spring and stop all effects
		for (uint8_t i=0; i<maxeffect; i++){EffectStates[i].state = 0;	}
		}

	
	}



void EVENT_USB_Device_ControlRequest(void)
{
	/* Handle HID Class specific requests */
	
	switch (USB_ControlRequest.bRequest)
	{
		
		case HID_REQ_GetReport:
			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
			{
				
				if (USB_ControlRequest.wValue == 0x0307)
				{	// Feature 3: PID Pool Feature Report
					
							Endpoint_ClearSETUP();
							// Write the report data to the control endpoint
								Features Feature;
								Feature.reportId = 7;
								Feature.ramPoolSize = 0xFFFF;
								Feature.maxSimultaneousEffects = 0x02;	// FFP supports playing up to 10 simultaneous effects
								Feature.memoryManagement = 3;
							//	nummerID = 2;
							//	memset((void*) gEffectStates, 0, sizeof(gEffectStates));
								
							Endpoint_Write_Control_Stream_LE(&Feature, sizeof(Features));
							Endpoint_ClearOUT();
				}
				else
				{
				USB_JoystickReport_Data_t JoystickReportData;
				GetNextReport(&JoystickReportData,1);
				
				
				Endpoint_ClearSETUP();
				Endpoint_Write_Control_Stream_LE(&JoystickReportData, sizeof(JoystickReportData));	
				Endpoint_ClearOUT();
				
				
				
				}
			}
			break;
			case HID_REQ_SetReport:
			{
				if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
				{
					// auch start stop	
					Endpoint_ClearSETUP();
					uint8_t data[20];	// This is enough room for all reports
					uint16_t len = 0;	// again, enough for all
					len = USB_ControlRequest.wLength;
					Endpoint_Read_Control_Stream_LE(&data, len);
					Endpoint_ClearStatusStage();
				
					
					if (USB_ControlRequest.wValue == 0x0305)
					{	// Feature 1
						_delay_us(500);	// Windows does not like to be answered too quickly
					//	LogData("=> SetReport:", USB_ControlRequest.wValue , data, len);
						
						PID_Report ReportData;
						NewEffect((New_Efect_data*) data, & ReportData);
						Endpoint_ClearSETUP();
						Endpoint_Write_Control_Stream_LE(&ReportData, sizeof(PID_Report));
						Endpoint_ClearOUT();
					}
					else if (USB_ControlRequest.wValue == 0x0201)
					{	// set effect 
					  	SetEffect((SetEffect_Output_Data*) data);
						  
					}
					else if (USB_ControlRequest.wValue == 0x0203)
					{	// set effect
					 SetCondition((USB_FFBReport_SetCondition_Output_Data_t*) data);	
					
					}
					else if (USB_ControlRequest.wValue == 0x0206)
					{	// set effect
						SetRampForce((USB_FFBReport_SetRampForce_Output_Data_t*) data);
					}
					else if (USB_ControlRequest.wValue == 0x0202)
					{	// set effect
						SetEnvelope((USB_FFBReport_SetEnvelope_Output_Data_t*) data);
					}
					else if (USB_ControlRequest.wValue == 0x0204)
					{	// set effect
						SetPeriodic((USB_FFBReport_SetPeriodic_Output_Data_t*) data);
					}
					else if (USB_ControlRequest.wValue == 0x0205)
					{	// set effect
						Setmag((USB_FFBReport_SetConstantForce_Output_Data_t*) data);
						
					} 
					else if (USB_ControlRequest.wValue == 0x020a)
					{	// set effect
						EffectOperation((USB_FFBReport_EffectOperation_Output_Data_t*) data);
					}
					else if (USB_ControlRequest.wValue == 0x020b)
					{	// set effect
						BlockFree((USB_FFBReport_BlockFree_Output_Data_t *) data);
					}
					else if (USB_ControlRequest.wValue == 0x020c)
					{	// set effect
						DeviceControl((USB_FFBReport_DeviceControl_Output_Data_t*) data);
					}
				}
			}
	
	
	}
}



bool GetNextReport(USB_JoystickReport_Data_t* const ReportData, uint8_t id)
{

	bool           InputChanged     = false;
  // uint8_t i;

   
   
	ReportData->repID =id;

	ReportData->Buttons[0] = 0;
	ReportData->Buttons[1] = 0;
	ReportData->Buttons[2] = 0;
	ReportData->Buttons[3] = 0;
	ReportData->axis[0] = (XAchse<<8);
	ReportData->axis[1] = (YAchse<<8);
	ReportData->axis[2] = 0;
	ReportData->axis[3] = 0;
	ReportData->axis[4] = 0;
	ReportData->axis[5] = 0;
	ReportData->axis[6] = 0;
	ReportData->axis[7] = 0;
	ReportData->Hat[1] =0;
	ReportData->Hat[2] =0;
	
	
	ReportData->Buttons[1] |=(1<<6);  //to hard set one Button
	PORTE &=~(1<<6); if (!(PINB & (1<<PB5))){ ReportData->Buttons[0] |= (1<<0);	} 	else	{ ReportData->Buttons[0] &=~ (1<<0);}  PORTE |= (1<<6);
	
	/*
	//----Read Daisy Chain---
 PORTB &= ~(1<<4);
 PORTB |= (1<<4);
// PORTD ^= (1<<0);
  PORTE &=~(1<<6);  ReportData->Buttons[0] |= (1<<0);   PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[0] |= (1<<1);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[0] |= (1<<2);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[0] |= (1<<3);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[0] |= (1<<4);  PORTE |= (1<<6); 
  PORTE &=~(1<<6);  ReportData->Buttons[0] |= (1<<5);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[0] |= (1<<6);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[0] |= (1<<7);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[1] |= (1<<0);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[1] |= (1<<1);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[1] |= (1<<2);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[1] |= (1<<3);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[1] |= (1<<4);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[1] |= (1<<5);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[1] |= (1<<6);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[1] |= (1<<7);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[2] |= (1<<0);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[2] |= (1<<1);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[2] |= (1<<2);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[2] |= (1<<3);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[2] |= (1<<4);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[2] |= (1<<5);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[2] |= (1<<6);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[2] |= (1<<7);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[3] |= (1<<0);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[3] |= (1<<1);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[3] |= (1<<2);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[3] |= (1<<3);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[3] |= (1<<4);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[3] |= (1<<5);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[3] |= (1<<6);  PORTE |= (1<<6);
  PORTE &=~(1<<6);  ReportData->Buttons[3] |= (1<<7);  PORTE |= (1<<6);

	ReportData->Buttons[1] |=(1<<5);

*/
	return InputChanged;
}

/** Function to manage HID report generation and transmission to the host. */
void HID_Task(void)
{
	/* Device must be connected and configured for the task to run */
	if (USB_DeviceState != DEVICE_STATE_Configured)
	  return;
	/* Select the Joystick Report Endpoint */
	Endpoint_SelectEndpoint(JOYSTICK_EPADDR);

	/* Check to see if the host is ready for another packet */
	if (Endpoint_IsINReady())
	{
	
		USB_JoystickReport_Data_t JoystickReportData;
			
		/* Create the next HID report to send to the host */
		GetNextReport(&JoystickReportData,1);
		//PORTB ^= (1<<4);
		/* Write Joystick Report Data */
		//JoystickReportData.Buttons[0] =1; 
		Endpoint_Write_Stream_LE(&JoystickReportData, sizeof(JoystickReportData), NULL);

		/* Finalize the stream transfer to send the last packet */
		Endpoint_ClearIN();

		
		memset(&JoystickReportData, 0, sizeof(JoystickReportData));
		
		
	}
	
	if (Endpoint_IsOUTReceived())
	{
		// wird nie getriggert
		
	}
}

