#include "udpl_dll_imp.h"
#include "command_list.h"
#include "setting_no.h"

uint32_t __stdcall UdplChipImp::getClock(void)
{
	// コマンドを発行しないで内部ステータスから返す
	return pchipInfo->clock;
}

// ************************************************************************************************************
// クロックを更新する
// ignore_lock : ボードに、PLL がロックするまで待たせるかどうか指定する
//   false = lock するまで待たせる。経験上、多くて3回くらい I2C で lock bit を読むことになる 
//   true  = lock を待たせない。ボードはノーウェイトでコマンドを実行するが、クロックが安定しない場合もありうる
// ************************************************************************************************************
bool __stdcall UdplChipImp::setClock(uint32_t clock, bool ignore_lock)
{
	bool ret = false;
	if (variable_clk && (clock >= MIN_PLLCLK) && (clock <= MAX_PLLCLK)) {
		// クロックセットコマンド発行
		uint8_t *p = send_command;
		memcpy(p, COMMAND_SET_CLOCK, sizeof(COMMAND_SET_CLOCK));
		p += sizeof(COMMAND_SET_CLOCK);
		if (!ignore_lock) {
			*p++ = slotno;
		} else {
			*p++ = slotno | 0x80;	// ignore bit を立てる
		}
		*p++ = clock & 0xff;
		*p++ = (clock >> 8) & 0xff;
		*p++ = (clock >> 16) & 0xff;
		*p++ = (clock >> 24) & 0xff;
		psockIf->pushData(send_command, COMMAND_SET_CLOCK[0] + 1);
		setWaits(clock);	// ウェイトを再計算.継承先がない時（継承先コンストラクタ内）は中身がない
		pchipInfo->clock = clock;
		
		ret = true;
	}
	else if (clock == pchipInfo->clock) {
		ret = true;
	}
	return ret;
}

bool __stdcall UdplChipImp::init(void)
{
	bool ret = true;
	if (hwreset) {
		ret = reset();
	}
	initRegs();

	return ret;
}

bool __stdcall UdplChipImp::reset(void)
{
	bool ret = false;
	
	uint8_t *p = send_command;
	memset(recv_command, '\0', sizeof(recv_command));

	// reset command
	memcpy(p, COMMAND_RESET, sizeof(COMMAND_RESET));
	p += sizeof(COMMAND_RESET);
	*p++ = (0x01 << slotno);
	psockIf->pushRecv(send_command, COMMAND_RESET[0] + 1, recv_command, sizeof(recv_command));

	if (memcmp(recv_command, RESPONSE_RESET, sizeof(RESPONSE_RESET)) == 0) {
		ret = true;
	}

	return ret;
}

const char* __stdcall UdplChipImp::getBoardAddress(uint32_t interface_protocol) {
	char* ret = nullptr;
	if (interface_protocol == IPV6UDP) {
		ret = pboard_address_ipv6;
	}
	return ret;
}