/* $Id$ */

#include <cstring>
#include <cstdio>
#include "owxendian.h"
#include "wouxun.h"
#include "util.h"
#include "throw.h"
#include "intl.h"

#define DEFAULT_TIMEOUT 5

CWouxun::CWouxun(): m_timeout(DEFAULT_TIMEOUT)
{
}

void CWouxun::SetPort(const std::string &port)
{
	m_port = port;
}

void CWouxun::SetTimeout(unsigned timeout)
{
	m_timeout = timeout;
}

void CWouxun::Open(const std::string &welcome)
{
	m_comm.Open(m_port, m_timeout);

	m_comm.Send(welcome.c_str(), welcome.size());
	RecvAck(true);

	m_comm.SendChar(0x02);
	RecvAck();

	char buf[7];
	m_comm.Recv(buf, sizeof(buf));
	m_id = Util::Sanitize(std::string(buf, 6));

	// xxx - what is in buf[6]? version?
	// m_version = buf[6];

	m_comm.SendChar(0x06);
	RecvAck();
}

const std::string &CWouxun::GetIDString() const
{
	return m_id;
}

void CWouxun::PrepareAddress(char *buf, unsigned short addr)
{
#ifdef OWX_LITTLE_ENDIAN
	buf[0] = addr >> 8;
	buf[1] = addr & 0xFF;
#else
	buf[0] = addr & 0xFF;
	buf[1] = addr >> 8;
#endif
}

void CWouxun::GetPage(unsigned short addr, char *buf)
{
	char txbuf[4] = { 'R', 0x00, 0x00, 0x40 };
	char rxbuf[4];

	PrepareAddress(txbuf + 1, addr);

	m_comm.Send(txbuf, sizeof(txbuf));
	m_comm.Recv(rxbuf, sizeof(rxbuf));

	txbuf[0] = 'W';
	if (memcmp(txbuf, rxbuf, sizeof(txbuf)) != 0)
		Throw(_("Radio returned nonsense"));

	m_comm.Recv(buf, 0x40);

	m_comm.SendChar(0x06);
	RecvAck();
}

void CWouxun::PutPage(unsigned short addr, const char *buf)
{
	char txbuf[4] = { 'W', 0x00, 0x00, 0x10 };

	PrepareAddress(txbuf + 1, addr);

	m_comm.Send(txbuf, sizeof(txbuf));
	m_comm.Send(buf, 0x10);
	RecvAck();
}

void CWouxun::RecvAck(bool checkecho)
{
	unsigned char ch(m_comm.RecvChar());

	if (ch == 0x06)
		return;

	if (checkecho && ch == 'H')
		Throw(_("RX-to-TX loopback detected"));

	Throw(_("Invalid ACK char received: 0x%02X"), ch);
}
