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


Symbolizer::Symbolizer()
: Processor::Block(1, 1)
, m_symbolBitCount(0)
, m_lastSymbol(0)
, m_symbolMask(0)
{
	setNumBitsPerSymbol(8);
}

void Symbolizer::setNumBitsPerSymbol(uint32_t nBitsPerSym)
{
	m_symbolBitCount = 0;
	m_nBitsPerSym = nBitsPerSym;
	m_lastSymbol = 0;
	m_symbolMask = symbol_t(1 << m_nBitsPerSym) - 1;
}

void Symbolizer::commit(symbol_t sym)
{
	symbol_t symbol_encoded = differentialEncode(sym);
	m_buf_out->write(&symbol_encoded, 1);
}

void Symbolizer::assemble_and_commit(uint8_t data)
{
	static symbol_t sym;

	// Transmission order MSB first
	for (size_t i=0; i < SIZEOF_DATA_BITS; i++)
	{
		sym <<= 1;
		sym |= (symbol_t)(data >> (SIZEOF_DATA_BITS-1) & 1);
		data <<= 1;
		m_symbolBitCount++;
		if (m_symbolBitCount == m_nBitsPerSym)
		{
			commit(sym);
			m_symbolBitCount = 0;
			sym = 0;
		}
	}
}

void Symbolizer::prepare()
{
	// Get buffers
	m_buf_in = buffer_in<uint8_t>();
	m_buf_out = buffer_out<symbol_t>();
}

void Symbolizer::process()
{
	if (m_nBitsPerSym == SIZEOF_DATA_BITS)
	{
		// Process input
		while(m_buf_in->len())
		{
			uint8_t data;
			m_buf_in->read(&data, 1);
			commit((symbol_t)data);
		}
	}
	else
	{
		while(m_buf_in->len())
		{
			uint8_t data;
			m_buf_in->read(&data, 1);
			assemble_and_commit(data);
		}
	}
}

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

	return m_lastSymbol;
}

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