/*
 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/>.
 */
// compatible with JJRC345

#if defined(JJRC345_NRF24L01_INO)

#include "iface_xn297.h"

//#define JJRC345_FORCE_ID

#define JJRC345_PACKET_PERIOD		7450 // Timeout for callback in uSec
#define JJRC345_INITIAL_WAIT		500
#define JJRC345_PACKET_SIZE			16
#define JJRC345_RF_BIND_CHANNEL		5
#define SKYTMBLR_RF_BIND_CHANNEL	40
#define JJRC345_BIND_COUNT			500
#define JJRC345_NUM_CHANNELS		4


enum JJRC345_FLAGS {
    // flags going to packet[8]
	JJRC345_FLAG_HEADLESS	= 0x40,
	JJRC345_FLAG_RTH		= 0x80,
    // flags going to packet[9]
	SKYTMBLR_FLAG_UNK1	    = 0x40,
	SKYTMBLR_FLAG_UNK2	    = 0x80,
    // flags going to packet[10]
	SKYTMBLR_FLAG_LED	    = 0x40,
	SKYTMBLR_FLAG_UNK3	    = 0x80,
};

static uint8_t __attribute__((unused)) JJRC345_convert_channel(uint8_t num)
{
	uint8_t val=convert_channel_8b(num);
	// 7E..60..41..01, 80 center, 81..C1..E0..FE
	if(val<0x80)
	{
		val=0x80-val;	// 80..01
		if(val>0x7E)
			val=0x7E;	// 7E..01
	}
	else if(val>0xFE)
		val=0xFE;			// 81..FE
	return val;
}

static void __attribute__((unused)) JJRC345_send_packet()
{
	packet[0] = 0x00;
	packet[2] = 0x00;
	if (IS_BIND_IN_PROGRESS)
	{ //00 05 00 0A 46 4A 41 47 00 00 40 46 A5 4A F1 18
		packet[1]  = (sub_protocol == JJRC345 ? JJRC345_RF_BIND_CHANNEL:SKYTMBLR_RF_BIND_CHANNEL);
		packet[4]  = hopping_frequency[0];
		packet[5]  = hopping_frequency[1];
		packet[6]  = hopping_frequency[2];
		packet[7]  = hopping_frequency[3];
		packet[12] = 0xa5;
	}
	else
	{ //00 41 00 0A 00 80 80 80 00 00 40 46 00 49 F1 18
		XN297_Hopping(hopping_frequency_no);
		hopping_frequency_no++;
		hopping_frequency_no %= JJRC345_NUM_CHANNELS;
		packet[1]  = hopping_frequency[hopping_frequency_no];	// next packet will be sent on this channel

		packet[4]  = convert_channel_8b(THROTTLE);				// throttle: 00..FF
		packet[5]  = JJRC345_convert_channel(RUDDER);			// rudder: 70..60..41..01, 80 center, 81..C1..E0..F0
		packet[6]  = JJRC345_convert_channel(ELEVATOR);			// elevator: 70..60..41..01, 80 center, 81..C1..E0..F0
		packet[7]  = JJRC345_convert_channel(AILERON);			// aileron: 70..60..41..01, 80 center, 81..C1..E0..F0

		if(CH5_SW)	//Flip
		{
			if(packet[6]>0xF0)
				packet[6]=0xFF;
			else if(packet[6]<0x80 && packet[6]>0x70)
				packet[6]=0x7F;
			if(packet[7]>0xF0)
				packet[7]=0xFF;
			else if(packet[7]<0x80 && packet[7]>0x70)
				packet[7]=0x7F;
		}
		
		packet[12] = 0x02;										// Rate: 00-01-02
	}

	packet[3] = 0x00;											// Checksum upper bits

	packet[8] = 0x00											// Rudder trim, 00 when not used, 01..1F when trimmed left, 20..3F
				| GET_FLAG(CH6_SW ,JJRC345_FLAG_HEADLESS)		// 0x40 HeadLess
				| GET_FLAG(CH7_SW ,JJRC345_FLAG_RTH);			// 0x80 RTH
	packet[9] = 0x00												// Elevator trim, 00 when not used, 20..25 when trimmed up, 0..1F when trimmed down
				| GET_FLAG(CH9_SW ,SKYTMBLR_FLAG_UNK1)			// 0x40 Unknown
				| GET_FLAG(CH10_SW,SKYTMBLR_FLAG_UNK2);			// 0x80 Unknown
	packet[10] = 0x00											// Aileron  trim, 00 when not used, 00..1F when trimmed left, 21..3F when trimmed right
				| GET_FLAG(!CH8_SW,SKYTMBLR_FLAG_LED)			// 0x40 LED
				| GET_FLAG(CH11_SW,SKYTMBLR_FLAG_UNK3);			// 0x80 Unknown

	packet[11] = hopping_frequency[0];							// First hopping frequency

	// Checksum
	uint16_t sum=2;
	for (uint8_t i = 0; i < 13; i++)
		sum += packet[i];
	packet[13]=sum;
	packet[3]=((sum>>8)<<2)+2;
	
	// TX ID
	packet[14] = rx_tx_addr[2];
	packet[15] = rx_tx_addr[3];

	// Send
	XN297_SetPower();
	XN297_SetTxRxMode(TX_EN);
	XN297_WritePayload(packet, JJRC345_PACKET_SIZE);
}

static void __attribute__((unused)) JJRC345_RF_init()
{
	XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
    XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
	//XN297_HoppingCalib(JJRC345_NUM_CHANNELS);
	XN297_RFChannel(sub_protocol == JJRC345 ? JJRC345_RF_BIND_CHANNEL:SKYTMBLR_RF_BIND_CHANNEL);	// Bind channel
}

uint16_t JJRC345_callback()
{
	#ifdef MULTI_SYNC
		telemetry_set_input_sync(JJRC345_PACKET_PERIOD);
	#endif
	if(bind_counter)
	{
		bind_counter--;
		if (bind_counter==0)
			BIND_DONE;
	}
	JJRC345_send_packet();
	return	JJRC345_PACKET_PERIOD;
}

static void __attribute__((unused)) JJRC345_initialize_txid()
{
	calc_fh_channels(JJRC345_NUM_CHANNELS);
	
	#ifdef JJRC345_FORCE_ID
		//TX 1
		rx_tx_addr[2]=0x1B;
		rx_tx_addr[3]=0x12;
        hopping_frequency[0] = 0x3f;
        hopping_frequency[1] = 0x49;
        hopping_frequency[2] = 0x47;
        hopping_frequency[3] = 0x47;
		//TX 2
		rx_tx_addr[2]=0xF1;
		rx_tx_addr[3]=0x18;
        hopping_frequency[0] = 0x46;
        hopping_frequency[1] = 0x4A;
        hopping_frequency[2] = 0x41;
        hopping_frequency[3] = 0x47;
	#endif
}

void JJRC345_init(void)
{
	BIND_IN_PROGRESS;	// autobind protocol
    bind_counter = JJRC345_BIND_COUNT;
	JJRC345_initialize_txid();
	JJRC345_RF_init();
}

#endif
