//
//    This file is part of Dire Wolf, an amateur radio packet TNC.
//
//    Copyright (C) 2021  John Langner, WB2OSZ
//
//    This program 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 2 of the License, or
//    (at your option) any later version.
//
//    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
//

#include "direwolf.h"

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>

#include "il2p.h"
#include "textcolor.h"
#include "audio.h"
#include "gen_tone.h"


static int number_of_bits_sent[MAX_CHANS];		// Count number of bits sent by "il2p_send_frame"

static void send_bytes (int chan, unsigned char *b, int count, int polarity);
static void send_bit (int chan, int b, int polarity);



/*-------------------------------------------------------------
 *
 * Name:	il2p_send_frame
 *
 * Purpose:	Convert frames to a stream of bits in IL2P format.
 *
 * Inputs:	chan	- Audio channel number, 0 = first.
 *
 *		pp	- Pointer to packet object.
 *
 *		max_fec	- 1 to force 16 parity symbols for each payload block.
 *			  0 for automatic depending on block size.
 *
 *		polarity - 0 for normal.  1 to invert signal.
 *			   2 special case for testing - introduce some errors to test FEC.
 *
 * Outputs:	Bits are shipped out by calling tone_gen_put_bit().
 *
 * Returns:	Number of bits sent including
 *		- Preamble   (01010101...)
 *		- 3 byte Sync Word.
 *		- 15 bytes for Header.
 *		- Optional payload.
 *		The required time can be calculated by dividing this
 *		number by the transmit rate of bits/sec.
 *		-1 is returned for failure.
 *
 * Description:	Generate an IL2P encoded frame.
 *
 * Assumptions:	It is assumed that the tone_gen module has been
 *		properly initialized so that bits sent with 
 *		tone_gen_put_bit() are processed correctly.
 *
 * Errors:	Return -1 for error.  Probably frame too large.
 *
 * Note:	Inconsistency here. ax25 version has just a byte array
 *		and length going in.  Here we need the full packet object.
 *
 *--------------------------------------------------------------*/

int il2p_send_frame (int chan, packet_t pp, int max_fec, int polarity)
{
	unsigned char encoded[IL2P_MAX_PACKET_SIZE];

	encoded[0] = ( IL2P_SYNC_WORD >> 16 ) & 0xff;
	encoded[1] = ( IL2P_SYNC_WORD >> 8  ) & 0xff;
	encoded[2] = ( IL2P_SYNC_WORD       ) & 0xff;

	int elen = il2p_encode_frame (pp, max_fec, encoded + IL2P_SYNC_WORD_SIZE);
	if (elen <= 0) {
	  text_color_set(DW_COLOR_ERROR);
	  dw_printf ("IL2P: Unable to encode frame into IL2P.\n");
	  return (-1);
	}

	elen += IL2P_SYNC_WORD_SIZE;

	number_of_bits_sent[chan] = 0;

	if (il2p_get_debug() >= 1) {
	  text_color_set(DW_COLOR_DEBUG);
	  dw_printf ("IL2P frame, max_fec = %d, %d encoded bytes total\n", max_fec, elen);
	  fx_hex_dump (encoded, elen);
	}

	// Clobber some bytes for testing.
	if (polarity >= 2) {
	    for (int j = 10; j < elen; j+=100) {
	        encoded[j] = ~ encoded[j];
	    }
	}

	// Send bits to modulator.

	static unsigned char preamble = IL2P_PREAMBLE;

	send_bytes (chan, &preamble, 1, polarity);
	send_bytes (chan, encoded, elen, polarity);
	
	return (number_of_bits_sent[chan]);
}


static void send_bytes (int chan, unsigned char *b, int count, int polarity)
{
	for (int j = 0; j < count; j++) {
	  unsigned int x = b[j];
	  for (int k = 0; k < 8; k++) {
	    send_bit (chan, (x & 0x80) != 0, polarity);
	    x <<= 1;
	  }
	}
}

// NRZI would be applied for AX.25 but IL2P does not use it.
// However we do have an option to invert the signal.
// The direwolf receive implementation will automatically compensate
// for either polarity but other implementations might not.

static void send_bit (int chan, int b, int polarity)
{
	tone_gen_put_bit (chan, (b ^ polarity) & 1);
	number_of_bits_sent[chan]++;
}



// end il2p_send.c