/*
             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.
*/

/** \file
 *
 *  Header file for Joystick.c.
 */

#ifndef _JOYSTICK_H_
#define _JOYSTICK_H_

	/* Includes: */
		#include <avr/io.h>
		#include <avr/wdt.h>
		#include <avr/power.h>
		#include <avr/interrupt.h>
		#include <string.h>

		#include "Descriptors.h"

		#include <LUFA/Drivers/USB/USB.h>
		#include <LUFA/Drivers/Board/Joystick.h>
		#include <LUFA/Drivers/Board/LEDs.h>
		#include <LUFA/Drivers/Board/Buttons.h>
		#include <LUFA/Platform/Platform.h>

	/* Macros: */
		/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
	//	#define LEDMASK_USB_NOTREADY      LEDS_LED1

		/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
	//	#define LEDMASK_USB_ENUMERATING  (LEDS_LED2 | LEDS_LED3)

		/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
	//	#define LEDMASK_USB_READY        (LEDS_LED2 | LEDS_LED4)

		/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
	//	#define LEDMASK_USB_ERROR        (LEDS_LED1 | LEDS_LED3)


	/* Type Defines: */
		/** Type define for the joystick HID report structure, for creating and sending HID reports to the host PC.
		 *  This mirrors the layout described to the host in the HID report descriptor, in Descriptors.c.
		 */
		typedef struct
		{
					int8_t repID;
					int16_t axis[8];
					int8_t Buttons[4];
					int8_t Hat[2];
				
		} USB_JoystickReport_Data_t;

typedef struct
{ // FFB: PID Pool Feature Report
	uint8_t	reportId;	// =3
	uint16_t	ramPoolSize;	// ?
	uint8_t		maxSimultaneousEffects;	// ?? 40?
	uint8_t		memoryManagement;	// Bits: 0=DeviceManagedPool, 1=SharedParameterBlocks
} Features;

typedef struct
{ // FFB: PID Block Load Feature Report
	uint8_t	reportId;	// =2
	uint8_t effectBlockIndex;	// 1..40
	uint8_t	loadStatus;	// 1=Success,2=Full,3=Error
	uint16_t	ramPoolAvailable;	// =0 or 0xFFFF?
} PID_Report;

typedef struct
{ // FFB: Create New Effect Feature Report
	uint8_t		reportId;	// =1
	uint8_t	effectType;	// Enum (1..12): ET 26,27,30,31,32,33,34,40,41,42,43,28
	uint16_t	byteCount;	// 0..511
} New_Efect_data;

typedef struct
{ // FFB: Block Free Output Report
	uint8_t	reportId;	// =11
	uint8_t effectBlockIndex;	// 1..40
} USB_FFBReport_BlockFree_Output_Data_t;


typedef struct {
	uint8_t state;	// see constants <MEffectState_*> 1=set 2= Aktiv 0= free
	uint16_t usb_duration, usb_fadeTime;	// used to calculate fadeTime to MIDI, since in USB it is given as time difference from the end while in MIDI it is given as time from start
	// These are used to calculate effects of USB gain to MIDI data
	uint8_t usb_gain, usb_offset, usb_attackLevel, usb_fadeLevel;
	uint8_t usb_magnitude;
} TEffectState;

typedef struct
{ // FFB: Set Condition Output Report
	uint8_t	reportId;	// =3
	uint8_t	effectBlockIndex;	// 1..40
	uint8_t	parameterBlockOffset;	// bits: 0..3=parameterBlockOffset, 4..5=instance1, 6..7=instance2
	uint16_t cpOffset;	// 0..255
	int16_t	positiveCoefficient;	// -128..127
	int16_t	negativeCoefficient;	// -128..127
	uint16_t	positiveSaturation;	// -128..127
	uint16_t	negativeSaturation;	// -128..127
	uint16_t	deadBand;	// 0..255
} USB_FFBReport_SetCondition_Output_Data_t;

typedef struct
{ // FFB: Set Condition Output Report
	//	uint8_t	reportId;	// =3
	//uint8_t	effectBlockIndex;	// 1..40
//	uint8_t	parameterBlockOffset;	// bits: 0..3=parameterBlockOffset, 4..5=instance1, 6..7=instance2
	uint16_t cpOffset;	// 0..255
	int16_t	positiveCoefficient;	// -128..127
	int16_t	negativeCoefficient;	// -128..127
	uint16_t	positiveSaturation;	// -128..127
	uint16_t	negativeSaturation;	// -128..127
	uint16_t	deadBand;	// 0..255
} Condition_Output_Data_t;


typedef struct
{ // FFB: Set Effect Output Report
	uint8_t	reportId;	// =1
	uint8_t	effectBlockIndex;	// 1..40
	uint8_t	effectType;	// 1..12 (effect usages: 26,27,30,31,32,33,34,40,41,42,43,28)
	uint16_t	duration; // 0..32767 ms
	uint16_t	triggerRepeatInterval; // 0..32767 ms
	uint16_t	samplePeriod;	// 0..32767 ms
	uint8_t	gain;	// 0..255	 (physical 0..10000)
	uint8_t	triggerButton;	// button ID (0..8)
	uint8_t	enableAxis; // bits: 0=X, 1=Y, 2=DirectionEnable
	uint8_t	directionX;	// angle (0=0 .. 255=360deg)
	uint8_t	directionY;	// angle (0=0 .. 255=360deg)
	uint16_t	startDelay;	// 0..32767 ms
	uint16_t aktual_time;
} SetEffect_Output_Data;

typedef struct
{ // FFB: Set Effect Output Report
//	uint8_t	reportId;	// =1
	uint8_t	effectBlockIndex;	// 1..40
	uint8_t	effectType;	// 1..12 (effect usages: 26,27,30,31,32,33,34,40,41,42,43,28)
	uint16_t	duration; // 0..32767 ms
	uint16_t	triggerRepeatInterval; // 0..32767 ms
	uint16_t	samplePeriod;	// 0..32767 ms
	uint8_t	gain;	// 0..255	 (physical 0..10000)
	uint8_t	triggerButton;	// button ID (0..8)
	uint8_t	enableAxis; // bits: 0=X, 1=Y, 2=DirectionEnable
	uint8_t	directionX;	// angle (0=0 .. 255=360deg)
	uint8_t	directionY;	// angle (0=0 .. 255=360deg)
	uint16_t	startDelay;	// 0..32767 ms
	uint16_t aktual_time;
//	uint16_t mili;
//	uint8_t sec;
//	uint8_t min;
//	uint8_t hour;
} SetEffect_Data;

typedef struct
{ // FFB: Set Envelope Output Report
	uint8_t	reportId;	// =2
	uint8_t	effectBlockIndex;	// 1..40
	uint16_t attackLevel;
	uint16_t	fadeLevel;
	uint16_t	attackTime;	// ms
	uint16_t	fadeTime;	// ms
	

	
} USB_FFBReport_SetEnvelope_Output_Data_t;

typedef struct
{ // FFB: Set Envelope Output Report
//	uint8_t	effectBlockIndex;	// 1..40
	uint16_t attackLevel;
	uint16_t	attackTime;	// ms
	uint16_t	fadeLevel;	
	uint16_t	fadeTime;	// ms
} Envelope_Output_Data_t;


typedef struct
{ // FFB: Set EffectOperation Output Report
	uint8_t	reportId;	// =10
	uint8_t effectBlockIndex;	// 1..40
	uint8_t operation; // 1=Start, 2=StartSolo, 3=Stop
	uint8_t	loopCount;
} USB_FFBReport_EffectOperation_Output_Data_t;



typedef struct
{ // FFB: Device Control Output Report
	uint8_t	reportId;	// =12
	uint8_t control;	// 1=Enable Actuators, 2=Disable Actuators, 4=Stop All Effects, 8=Reset, 16=Pause, 32=Continue
} USB_FFBReport_DeviceControl_Output_Data_t;




typedef struct
{ // FFB: Set Periodic Output Report
	uint8_t	reportId;	// =4
	uint8_t	effectBlockIndex;	// 1..40
	uint8_t magnitude;
	int8_t	offset;
	uint8_t	phase;	// 0..255 (=0..359, exp-2)
	uint16_t	period;	// 0..32767 ms
} USB_FFBReport_SetPeriodic_Output_Data_t;

typedef struct
{ // FFB: Set Periodic Output Report
//	uint8_t	effectBlockIndex;	// 1..40
	uint8_t magnitude;
	int8_t	offset;
	uint8_t	phase;	// 0..255 (=0..359, exp-2)
	uint16_t	period;	// 0..32767 ms
	uint16_t ortung;
} Periodic_Output_Data_t;

typedef struct
{
	uint8_t	reportId;	// =2
	uint8_t	status;	// Bits: 0=Device Paused,1=Actuators Enabled,2=Safety Switch,3=Actuator Override Switch,4=Actuator Power
	uint8_t	effectBlockIndex;	// Bit7=Effect Playing, Bit0..7=EffectId (1..40)
} USB_FFBReport_PIDStatus_Input_Data_t;


typedef struct
{
	uint8_t	status;	// Bits: 0=Device Paused,1=Actuators Enabled,2=Safety Switch,3=Actuator Override Switch,4=Actuator Power
	uint8_t	effectBlockIndex;	// Bit7=Effect Playing, Bit0..7=EffectId (1..40)
} PIDStatus_Input_Data_t;

typedef struct
{ // FFB: Set ConstantForce Output Report
	uint8_t	reportId;	// =5
	uint8_t	effectBlockIndex;	// 1..40
	int16_t magnitude;	// -255..255
} USB_FFBReport_SetConstantForce_Output_Data_t;
typedef struct
{ // FFB: Set ConstantForce Output Report
	int16_t magnitude;	// -255..255
} ConstantForce_Output_Data_t;


typedef struct
{ // FFB: Set RampForce Output Report
	uint8_t	reportId;	// =6
	uint8_t	effectBlockIndex;	// 1..40
	int8_t start;
	int8_t	end;
} USB_FFBReport_SetRampForce_Output_Data_t;

typedef struct
{ // FFB: Set RampForce Output Report
	//uint8_t	reportId;	// =6
//	uint8_t	effectBlockIndex;	// 1..40
	int8_t start;
	int8_t	end;
} RampForce_Output_Data_t;


	/* Function Prototypes: */
		void SetupHardware(void);
		void HID_Task(void);
		void FFB_Task(void);
		void einlesen(void);

		void EVENT_USB_Device_Connect(void);
		void EVENT_USB_Device_Disconnect(void);
		void EVENT_USB_Device_ConfigurationChanged(void);
		void EVENT_USB_Device_ControlRequest(void);
		void condition(uint16_t xwert,uint16_t ywert, uint8_t i);
		void Timing(uint8_t i);
		void constant(uint8_t i);
		void ramp(uint8_t i);
		void squarset(uint8_t i);
		void sinset(uint8_t i);
		void sawupset(uint8_t i);
		
		bool GetNextReport(USB_JoystickReport_Data_t* const ReportData,uint8_t id);

#endif

