/*
 * This file is part of Cleanflight.
 *
 * Cleanflight 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.
 *
 * Cleanflight 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 Cleanflight.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <platform.h>
#include "drivers/transponder_ir.h"
#include "drivers/transponder_ir_erlt.h"

#if defined(STM32F3) || defined(STM32F4) || defined(UNIT_TEST)

static uint16_t dmaBufferOffset;
extern const struct transponderVTable erltTansponderVTable;

void transponderIrInitERLT(transponder_t *transponder){
    transponder->dma_buffer_size    = TRANSPONDER_DMA_BUFFER_SIZE_ERLT;
    transponder->vTable             = &erltTansponderVTable;
    transponder->timer_hz           = TRANSPONDER_TIMER_MHZ_ERLT;
    transponder->timer_carrier_hz   = TRANSPONDER_CARRIER_HZ_ERLT;
    memset(&(transponder->transponderIrDMABuffer.erlt), 0, TRANSPONDER_DMA_BUFFER_SIZE_ERLT);
}

void addBitToBuffer(transponder_t *transponder, uint8_t cycles, uint8_t pulsewidth)
{
	for (int i = 0; i < cycles; i++) {
		transponder->transponderIrDMABuffer.erlt[dmaBufferOffset++] = pulsewidth;
    }
}

void updateTransponderDMABufferERLT(transponder_t *transponder, const uint8_t* transponderData)
{
	uint8_t byteToSend = ~(*transponderData); //transponderData is stored inverted, so invert before using
	uint8_t paritysum = 0; //sum of one bits

	dmaBufferOffset = 0; //reset buffer count

	//start bit 1, always pulsed, bit value = 0
	addBitToBuffer(transponder, ERLTCyclesForZeroBit, transponder->bitToggleOne);

	//start bit 2, always not pulsed, bit value = 0
	addBitToBuffer(transponder, ERLTCyclesForZeroBit, ERLTBitQuiet);

	//add data bits, only the 6 LSB
	for (int i = 5; i >= 0; i--)
	{
		uint8_t bv = (byteToSend >> i) & 0x01;
		paritysum += bv;
		addBitToBuffer(transponder, (bv ? ERLTCyclesForOneBit : ERLTCyclesForZeroBit), ((i % 2) ? transponder->bitToggleOne : ERLTBitQuiet));
	}

	//parity bit, always pulsed, bit value is zero if sum is even, one if odd
	addBitToBuffer(transponder, ((paritysum % 2) ?  ERLTCyclesForOneBit : ERLTCyclesForZeroBit), transponder->bitToggleOne);

	//add final zero after the pulsed parity bit to stop pulses until the next update
	transponder->transponderIrDMABuffer.erlt[dmaBufferOffset++] = ERLTBitQuiet;

	//reset buffer size to that required by this ERLT id
	transponder->dma_buffer_size = dmaBufferOffset;
}

const struct transponderVTable erltTansponderVTable = {
     updateTransponderDMABufferERLT,
};

#endif
