// --------------------------------------------------------------
#include <string.h>
#include <math.h>
#include <stdint.h>
#include "Symbolizer.hpp"


Symbolizer::Symbolizer(ISymbolizer *pSymbolHandler)
	: m_pSymbolHandler(pSymbolHandler)
	, m_symbolBitCount(0)
	, m_lastSymbol(0)
	, m_symbolMask(0)
{
	setNumBitsPerSymbol(8);
}

Symbolizer::~Symbolizer()
{
}

void Symbolizer::setNumBitsPerSymbol(uint32_t nBitsPerSym)
{
	m_symbolBitCount = 0;
	m_nBitsPerSym = nBitsPerSym;
	m_lastSymbol = 0;
	m_symbolMask = 0;
	for(uint32_t k=0; k < nBitsPerSym; k++)
	{
		m_symbolMask <<= 1;
		m_symbolMask |= 1;
	}
}

void Symbolizer::process(uint8_t src)
{
	uint32_t i;
	static uint32_t dst;

	// Speed up
	if (m_nBitsPerSym == SIZEOF_DATA_BITS)
	{
		m_pSymbolHandler->onSymbol(differentialEncode((uint32_t)src));
		return;
	}

	// Transmission order MSB first
	for (i=0; i < SIZEOF_DATA_BITS; i++)
	{
		dst <<= 1;
		dst |= (uint32_t)((src >> (SIZEOF_DATA_BITS-1) & 1) != 0);
		src <<= 1;
		m_symbolBitCount++;
		if (m_symbolBitCount == m_nBitsPerSym)
		{
			m_pSymbolHandler->onSymbol(differentialEncode(dst));
			m_symbolBitCount = 0;
			dst = 0;
		}
	}
}

void Symbolizer::process(void *pSrc, uint32_t len)
{
	data_t *pData;

	pData = (data_t*)pSrc;
	
	while(len--)
	{
		process(*(pData++));
	}
}

uint32_t Symbolizer::differentialEncode(uint32_t symbol)
{
	// Differential encode
	m_lastSymbol = (uint32_t)(m_symbolMask & (symbol + m_lastSymbol));

	return m_lastSymbol;
}

void Symbolizer::onFrame(void *pFrame, uint32_t size)
{
	data_t *pData = (data_t*)pFrame;

	while(size)
	{
		process(*(pData++));
		size -= sizeof(data_t);
	}
}

DeSymbolizer::DeSymbolizer(IData *pDataHandler)
	: m_pDataHandler(pDataHandler)
	, m_dataBitCount(0)
	, m_lastSymbol(0)
	, m_symbolMask(0)
	, m_nBitsPerSym(0)
{
	setNumBitsPerSymbol(8);
}

DeSymbolizer::~DeSymbolizer()
{
}

void DeSymbolizer::setNumBitsPerSymbol(uint32_t nBitsPerSym)
{
	m_nBitsPerSym = nBitsPerSym;
	m_symbolMask = 0;
	for(uint32_t k=0; k < nBitsPerSym; k++)
	{
		m_symbolMask <<= 1;
		m_symbolMask |= 1;
	}
	m_bitCount = 0;
	m_dataBitCount = 0;
	m_lastSymbol = 0;
}

void DeSymbolizer::process(uint32_t src)
{
	uint32_t i, j;
	static uint8_t dst;
	static uint16_t preamble;
	uint16_t preamble_soll;
	uint32_t symSync;
	const uint32_t frameLengthInBits = 8*sizeof(frame_t);
	src = differentialDecode(src);
	symSync = src;

	preamble_soll = ((uint16_t)FRAME_PREAMBLE_IV << 8) | (~(uint16_t)FRAME_PREAMBLE_IV & 0xFF);

	j = 0;
	for (i=0; i < m_nBitsPerSym; i++)
	{
		preamble <<= 1;
		preamble |= (uint32_t)((symSync >> (m_nBitsPerSym-1) & 1) != 0);
		symSync <<= 1;
		m_bitCount++;
		if (preamble == preamble_soll)
		{
			preamble = 0;
			// We have data sync
			if (m_bitCount == frameLengthInBits)
			{
				m_dataBitCount = 0;
				m_pDataHandler->onReset();
				j = i + 1;
				src = symSync;
			}
			if (m_bitCount >= frameLengthInBits)
			{
				m_bitCount = 0;
			}
		}
	}

	// Transmission order MSB first
	for (i=j; i < m_nBitsPerSym; i++)
	{
		dst <<= 1;
		dst |= (uint32_t)((src >> (m_nBitsPerSym-1) & 1) != 0);
		src <<= 1;
		m_dataBitCount++;
		if (m_dataBitCount == SIZEOF_DATA_BITS)
		{
			m_pDataHandler->onData(dst);
			m_dataBitCount = 0;
			dst = 0;
		}
	}
}

uint32_t DeSymbolizer::differentialDecode(uint32_t symbol)
{
	uint32_t res;

	// Differential decode
	res = (uint32_t)(m_symbolMask & (symbol - m_lastSymbol));
	m_lastSymbol = symbol;

	return res;
}

// --------------------------------------------------------------
