/*
 This project is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 Multiprotocol is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with Multiprotocol.  If not, see <http://www.gnu.org/licenses/>.
 */

#if defined(E129_CYRF6936_INO)

#include "iface_rf2500.h"

//#define E129_FORCE_ID
//#define C186_FORCE_ID

#define E129_BIND_CH		0x2D	//45
#define E129_PAYLOAD_SIZE	16
#define C186_PAYLOAD_SIZE	19

static void __attribute__((unused)) E129_build_data_packet()
{
	//Build the packet
	memset(packet,0,packet_length);
	packet[ 0] = packet_length - 1;						// Packet length
	if(IS_BIND_IN_PROGRESS)
	{
		packet[ 1] = 0xA4;
		packet[ 2] = bit_reverse(rx_tx_addr[2]);
		packet[ 3] = bit_reverse(rx_tx_addr[3]);
		packet[ 4] = bit_reverse(rx_tx_addr[0]);
		packet[ 5] = bit_reverse(rx_tx_addr[1]);
		for(uint8_t i=0; i<4; i++)
			packet[6+i]=hopping_frequency[i]-2;
	}
	else
	{
		packet[ 1] = 0xA6;								// Set to A5 every few packets??

		//Flags
		packet[ 2] = 0xF7;								// E129 High rate 0xF7, low 0xF4
		if(sub_protocol == E129_C186)
		{
			packet[ 2] = 0xFA;							// High rate 0xFA, medium 0xF7, low 0xF4
			packet[13] = bit_reverse(rx_tx_addr[2]);
			packet[14] = bit_reverse(rx_tx_addr[3]);
			packet[15] = bit_reverse(rx_tx_addr[0]);
			packet[16] = bit_reverse(rx_tx_addr[1]);
		}
		packet[ 3] = GET_FLAG(CH10_SW, 0x40)			// C159: loop flight 0x40
				   | GET_FLAG(CH11_SW, 0x08);			// C129V2: flip
		//Other flags seen in packet[3]
		//  Flag 0x04 is set on some helis (C159/C190)
		//  E129 Mode: short press=0x20->0x00->0x20->..., long press=0x10->0x30->0x10->... => C186 throttle trim is doing the same:up=short press and down=long press
		packet[ 4] = GET_FLAG(CH5_SW,  0x20)			// Take off/Land 0x20
				   | GET_FLAG(CH6_SW,  0x04)			// Emergency stop 0x04
				   | GET_FLAG(CH12_SW, 0x80);			// C190: debug mode->remote THR trim down sets 0x80
		//Other flags seen in packet[4]
		//  C190 remote LANDING sets 0x10
		//  C190 remote THR trim down sets 0x80

		//Channels and trims
		uint16_t val = convert_channel_10b(AILERON,false);
		uint8_t trim = convert_channel_8b(CH7) & 0xFC;
		packet[ 5] = trim | (val >>8);					// Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
		packet[ 6] = val;								// channel (0x000...0x200...0x3FF)
		val = convert_channel_10b(ELEVATOR,false);
		trim = convert_channel_8b(CH8) & 0xFC;
		packet[ 7] = trim | (val >>8);					// Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
		packet[ 8] = val;								// channel (0x000...0x200...0x3FF)
		if(packet_count>200)
			val = convert_channel_10b(THROTTLE,false);
		else
		{//Allow bind to complete with throttle not centered
			packet_count++;
			val=0x200;
		}
		packet[ 9] = (0x1F<<2) | (val >>8);				// Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
		packet[10] = val;								// channel (0x000...0x200...0x3FF)
		val = convert_channel_10b(RUDDER,false);
		trim = convert_channel_8b(CH9) & 0xFC;
		packet[11] = trim | (val >>8);					// Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
		packet[12] = val;								// channel (0x000...0x200...0x3FF)
	}
	//Check
	for(uint8_t i=0;i<packet_length-2;i++)
		packet[packet_length-2] += packet[i];
	if(sub_protocol == E129_C186)
		packet[packet_length-2] -= 0x80;

	RF2500_BuildPayload(packet);
}

uint16_t E129_callback()
{
	//Set RF channel
	if(phase==0)
		RF2500_RFChannel(IS_BIND_IN_PROGRESS ? E129_BIND_CH : hopping_frequency[hopping_frequency_no]);

	//Send packet
	RF2500_SendPayload();
	
	//E129 sends twice on same channel, not the C186 but there is a bug somewhere if I don't send the packets back to back
	if(phase==0)
	{
		phase++;
		return 1260;
	}

	//Bind
	if(bind_counter)
		if(--bind_counter==0)
		{
			BIND_DONE;
			RF2500_SetTXAddr(rx_tx_addr);	// 4 bytes of address
		}

	//Build packet
	E129_build_data_packet();
	
	//Set power
	RF2500_SetPower();
	
	//Hopp
	hopping_frequency_no++;
	hopping_frequency_no &= 3;

	phase=0;
	if(sub_protocol==E129_E129)
		return 5200-1260;
	return 5500-1260;						//E129_C186
}

void E129_init()
{
	BIND_IN_PROGRESS;						// Autobind protocol
    bind_counter = 384;						// ~2sec

	//RF2500 emu init
	packet_length = sub_protocol == E129_E129?E129_PAYLOAD_SIZE:C186_PAYLOAD_SIZE;
	RF2500_Init(packet_length, true);		// 16/19 bytes, Scrambled
   
	//Freq hopping
	calc_fh_channels(4);
	for(uint8_t i=0; i<4; i++)
		if(hopping_frequency[i]==E129_BIND_CH)
			hopping_frequency[i]++;
	
    #ifdef E129_FORCE_ID
        rx_tx_addr[0]=0xC1;
        rx_tx_addr[1]=0x22;
        rx_tx_addr[2]=0x05;
        rx_tx_addr[3]=0xA3;
        hopping_frequency[0]=0x3C;			//60
        hopping_frequency[1]=0x49;			//73
        hopping_frequency[2]=0x4B;			//75
        hopping_frequency[3]=0x41;			//65
    #endif
    #ifdef C186_FORCE_ID
        rx_tx_addr[0]=0x91;
        rx_tx_addr[1]=0x02;
        rx_tx_addr[2]=0x5D;
        rx_tx_addr[3]=0x33;
        hopping_frequency[0]=0x44 + 2;
        hopping_frequency[1]=0x41 + 2;
        hopping_frequency[2]=0x43 + 2;
        hopping_frequency[3]=0x49 + 2;
    #endif

	RF2500_SetTXAddr((uint8_t*)"\xE2\x32\xE0\xC8");	// 4 bytes of bind address

	E129_build_data_packet();
	hopping_frequency_no=0;
	packet_count=0;
	phase=0;
}

#endif
