/*
*  Author Kim Mattsson, base from  Kroeske, additional usefull info from Rcgroups members.
*  Hitec Telemetry simulator for Arduino board.
*  Uses Arduino Wire library and can be embedded into Arducopter/Ardupirates
*  Connect ARduino direct to Optima, remember to add the pullups 1-4.7k.connect only SDA,SCL and ground between optima & arduino.
*  Don't connect plus between Optima and Arduino, the USB powers arduino and batterypack the receiver.
*/



#include <avr/interrupt.h>
#include <avr/io.h>
//#include <io.h>
#include <util/twi.h>
#include <Wire.h>


#define Hitec_i2c  0x08 // Hitec Telemetry module address

char Hitec_TWI_busy =0; // Check this so that transmissions don't get overlapped.

char  data[8][7] =

		{{ 0x11, 0xAF, 0x00, 0x2D, 0x00, 0x00, 0x11 }, // 1 Frametype, 4&5 Internal  SPC voltage
		{ 0x12, 0x00, 0x2C, 0x2C, 0x2E, 0x25, 0x12 }, // 1-4 Latitude 5=gps sec,
		{ 0x13, 0x18, 0x01, 0xD4, 0x22, 0x28, 0x13 }, // 1-4 Longitude, 5 = TEMP2
		{ 0x14, 0x00, 0x00, 0x00, 0x00, 0x28, 0x14 }, //1&2=Speed,,3&4 = altitude,5= Temp1
		{ 0x15, 0x00, 0xFF, 0x01, 0xFE, 0x01, 0x15 }, // 1 = Fuelgauge, 2&3 RPM1, 4&5 RPM2
		{ 0x16, 0x3C, 0x04, 0x1D, 0x00, 0x00, 0x16 }, // 1= year,m,date, h, min 
		{ 0x17, 0x00, 0x99, 0x06, 0x28, 0x28, 0x17 }, // 3= GPS Signal 4=Temp3, 5=Temp4
		{ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18 }} // 1&2 Voltage


 ; 

// Remove setup when implementing, this is only for testing. Ardupirates has its own setup.
void setup(){}

void loop()
{
int i=0;
int s;
char c=0,x,y=0;



//Serial.begin(115200);           // start serial for output
//  Serial.println("Setup Complete");

       Wire.onRequest(Send_Hitec);  // initiate the routine, when Hitec telemetry address is recognised 
      	while(1==1)
	{

  	 if (!Hitec_TWI_busy) Wire.begin(Hitec_i2c);
         for(int idx = 0; idx < 50; idx++)
		{
			delay(20); // adjust lower and display on A9 transmitter can't see change
		}
// Transmission halts, when Serial buffer in Arduino is Full, open the Serial monitor, and it will continue.
//Serial.println("Loop to change values");

		i=i+1;
                if (i>30000) i=0;
                setRpm(1,i); //works
                setRpm(2,10000+i); //works
                setVoltage(i);  //Works
                setAmpere(i); //Works
                setTemp(1,c); //Works
                setTemp(2,c+40); //Works
                setTemp(3,c+25); //Works
                setTemp(4,c+45); //Works
                setAltitude(i); //Works
                setSpeed(i); //Works
                FuelGauge(c); //Works
                setGPSValue(i,i);
                setGPSDate(i,i,i);
                setGPSTime(i,i,i);
                setGPSSignal(c);
                c++;
}

}
// Signal strength indicator, 5 bars, f.ex amount of satelites detected



// This is the routine, that  pushes the data from inside the irq routine. In your main program put Wire.onRequest(Send_Hitec)
void Send_Hitec()
{
  
    static unsigned char msgId = 0;

if (TWAR != (Hitec_i2c<<1)) return; //check if Hitecs telemetry address

// We need to send only one Idrow/request, because of receiver  "odd" handshaking that Wire lib not support (TWEA after every row)
  Wire.send((uint8_t *) data+msgId*7,7);
  msgId++;
  msgId%=8;
  if (msgId>0) Hitec_TWI_busy=1; // Without this check 
  else Hitec_TWI_busy=0;

} //routine
// Works  , nr is channel, and value is rpm
void setRpm(int nr, unsigned int value)
{

  	unsigned char rpml = (value/10) % 0x100;
	unsigned char rpmh = (value/10) / 0x100;
	switch( nr )
	{
		case 1:
			data[4][2] = rpml;
			data[4][3] = rpmh;
			break;
		case 2:
			data[4][4] = rpml;
			data[4][5] = rpmh;
			break;
		default:
			break;
	}
}
/*
 *  Valuerange 0-5
 
 */
void FuelGauge(unsigned char value)
{
if (value>4) data[4][1]=4;
else   	data[4][1] = value;
}
//works, Values are 0-255, value 0 is -40C 255 =215C
//
void setTemp(int nr,  unsigned char value)
{
  
  	switch( nr )
	{
		case 1:
			data[3][5] = value;
			break;
		case 2:
			data[2][5] = value;
			break;
		case 3:
			data[6][4] = value;
			break;
		case 4:
			data[6][5] = value;
		default:
			break;
	}
}
//  Works Values 0-500km/h

void setSpeed(unsigned int value)
{
if(value<=500)
{
  	data[3][2] = value % 0x100;
	data[3][1] = value / 0x100;
}
}
// Value in meters 
void setAltitude(unsigned int value)
{
  
if (value<9999)
{
  	data[3][4] = value % 0x100;
	data[3][3] = value / 0x100;
}
}
// Value is 6-1002, Value is 0.1 volt)
void setVoltage(unsigned int  value)
{
if ((value>6) & (value <1001))
{
  data[7][1] = (value-2) % 0x100; ;// % 0x100;
  data[7][2] = value /0x100;
}
}
 // value  1 = 0.1mA, presented function is close enough, more accurate with float, but don't want to include the huge library
void setAmpere(unsigned int value)
{
 uint32_t t;
 uint16_t v;
 t=(value-1);
 t=t*1435;
 t=t/1000;
 v=(uint16_t) (t)+167;
//if ((value>6) & (value <1001))
{
  data[7][3] =  v % 0x100; ;// % 0x100;
  data[7][4] =  v /0x100;
}
}
/*
 *
 */
 // values need to be prechecked.
void setGPSValue(uint32_t longitude, uint32_t latitude) 


{
  char x;
  data[2][4] = longitude % 0x100;     // ew
   data[2][3] = longitude / 0x100;    // min
if (data[2][3]>59) data[2][3]=59;
  data[2][2] = longitude / 0x10000;   // 1/100 
  data[2][1] = longitude / 0x1000000; // sec
if (data[2][1]>59) data[2][1]=59;
   data[1][4] = latitude % 0x100;     // NW
  data[1][3] = latitude / 0x100;       //min
if (data[1][3]>59) data[1][3]=59;
  data[1][2] = latitude /  0x10000;    // 1/100
  data[1][1] = latitude / 0x1000000;   // sec
if (data[1][1]>59) data[1][1]=59;
   
}
void setGPSDate(char y,char m,char d)

{
  	data[5][1] = y;
  	data[5][2] = m;
  	data[5][3] = d;
}
 void setGPSTime(char h,char m,char s)
{
  	data[5][4] = h;
  	data[5][5] = m;
  	data[1][5] = s;
} 

void setGPSSignal(char c)
{
data[6][3] = c;
}

