#include <Windows.h>
#include <tchar.h>
#include <stdio.h>
#include "udpl_dll.h"
#include "chipname.h"
#include "i2c_list.h"

bool oledClr(UdplManager *pm, const char *address)
{
	bool ret = true;
	uint8_t tmp[128 + 1];

	for (int y = 0; y < 8; ++y) {
		tmp[0] = 0x00;		// command
		tmp[1] = 0x21;		// カラム範囲
		tmp[2] = 0x00;		// 0-
		tmp[3] = 127;		// -127
		tmp[4] = 0x22;		// ページ範囲
		tmp[5] = 0x00;		// 0-
		tmp[6] = 0x07;		// -7
		tmp[7] = 0xb0 | y;	// ページ
		ret &= pm->writeI2C(address, OLED_ADDR, tmp, 8);

		memset(tmp, 0x0, sizeof(tmp));	// クリア
		tmp[0] = 0x40;	// data
		ret &= pm->writeI2C(address, OLED_ADDR, tmp, sizeof(tmp));
	}

	return ret;
}

bool oledFill(UdplManager* pm, const char* address)
{
	bool ret = true;
	uint8_t tmp[128 + 1];

	for (int y = 0; y < 8; ++y) {
		tmp[0] = 0x00;		// command
		tmp[1] = 0x21;		// カラム範囲
		tmp[2] = 0x00;		// 0-
		tmp[3] = 127;		// -127
		tmp[4] = 0x22;		// ページ範囲
		tmp[5] = 0x00;		// 0-
		tmp[6] = 0x07;		// -7
		tmp[7] = 0xb0 | y;	// ページ
		ret &= pm->writeI2C(address, OLED_ADDR, tmp, 8);

		memset(tmp, 0xFF, sizeof(tmp));	// ベタ
		tmp[0] = 0x40;	// data
		ret &= pm->writeI2C(address, OLED_ADDR, tmp, sizeof(tmp));
	}

	return ret;
}

int _tmain(int argc, TCHAR **argv[]) {

	TCHAR fullPath[MAX_PATH] = { _T('\0') };
	
	GetModuleFileName(NULL, fullPath, _countof(fullPath));	// フルパスパス取得
	
	TCHAR* sla = _tcsrchr(fullPath, _T('\\'));
	if (!sla) {
		exit(0);
	}
	*(sla + 1) = _T('\0');
	_tcscat_s(fullPath, _countof(fullPath), _T("udpl.dll"));

	HMODULE hdl = nullptr;

	hdl = ::LoadLibrary(fullPath);
	if (hdl == nullptr) {
		MessageBox(NULL, _T("DLL load error"), _T("DLL loading error"), MB_OK);
		return NULL;
	}

	UDPLFUNC getManager = (UDPLFUNC)GetProcAddress(hdl, "getManager");
	if (getManager == nullptr) {
		MessageBox(NULL, _T("getManager 取得ミス"), _T("error"), MB_OK);
		return NULL;
	}

	UdplManager *manager = getManager();

	manager->initialize();

	uint32_t board_num = manager->getBoardCount();
	uint32_t chip_num = manager->getChipCount();

	UDPL_BOARD_INFO *pbinfo = nullptr;
	UDPL_CHIP_INFO *pcinfo = nullptr;
	if (board_num) {
		pbinfo = new UDPL_BOARD_INFO[board_num];
		memset(pbinfo, 0, sizeof(UDPL_BOARD_INFO)*board_num);
		manager->getBoardInfoList(pbinfo, board_num);
	}
	if (chip_num) {
		pcinfo = new UDPL_CHIP_INFO[chip_num];
		memset(pcinfo, 0, sizeof(UDPL_CHIP_INFO)*chip_num);
		manager->getChipInfoList(pcinfo, chip_num);
	}
	_tprintf(_T("ライブラリパス = %s\n"), fullPath);
	_tprintf(_T("-------------------------------------------------\n"));
	_tprintf(_T("[ボードの数 = %u]\n"), board_num);
	for (uint32_t i = 0; i < board_num; ++i) {
		_tprintf(_T("name = %hs\n"), pbinfo[i].name);
		_tprintf(_T("local = %hs\n"), pbinfo[i].host_address_ipv6);
		_tprintf(_T("board = %hs\n"), pbinfo[i].board_address_ipv6);
		_tprintf(_T("ver = %08x\n"), pbinfo[i].version);
		_tprintf(_T("slot num = %u\n"), pbinfo[i].slotnum);
		_tprintf(_T("protocol = %u\n"), pbinfo[i].protocol);
		_tprintf(_T("listen port = %u\n"), pbinfo[i].listen_port);
		_tprintf(_T("send port = %u\n"), pbinfo[i].send_port);
		_tprintf(_T("buffer size = %u\n"), pbinfo[i].bufsize);
		_tprintf(_T("wait = %u[ms]\n"), pbinfo[i].wait);
		_tprintf(_T("-------------------------------------------------\n"));
	}

	_tprintf(_T("[チップの数 = %u]\n"), chip_num);
	for (uint32_t i = 0; i < chip_num; ++i) {
		_tprintf(_T("name = %hs\n"), pcinfo[i].name);
		_tprintf(_T("address = %hs\n"), pcinfo[i].board_address_ipv6);
		_tprintf(_T("slot no = %u\n"), pcinfo[i].slotNo);
		_tprintf(_T("clock = %u\n"), pcinfo[i].clock);
		_tprintf(_T("valiable clock = %u\n"), pcinfo[i].variable_clock);
		_tprintf(_T("hardware reset = %u\n"), pcinfo[i].hardware_reset);
		_tprintf(_T("extinfo = %hs\n"), pcinfo[i].extinfo);
		_tprintf(_T("-------------------------------------------------\n"));
	}

	if (board_num) {
		bool ret;
		uint32_t read;
		uint8_t recvbuf[16] = { 0 };
		uint8_t sendbuf[16] = { 0 };
		ret = manager->checkI2CAddr(pbinfo[0].board_address_ipv6, OLED_ADDR);
		_tprintf(_T("i2c 0x3c = %d\n"), ret ? 1 : 0);

		ret = manager->checkI2CAddr(pbinfo[0].board_address_ipv6, POTENT_OUT_ADDR);
		_tprintf(_T("i2c 0x28 = %d\n"), ret ? 1 : 0);

		read = manager->readI2C(pbinfo[0].board_address_ipv6, POTENT_OUT_ADDR, recvbuf, sizeof(recvbuf), 3);
		_tprintf(_T("i2c 0x28 = [%d] "), read);
		for (uint32_t i = 0; i < read; ++i) {
			_tprintf(_T("%x, "), recvbuf[i]);
		}
		_tprintf(_T("\n"));

		sendbuf[0] = 0x87;	// 33 position
		ret = manager->writeI2C(pbinfo[0].board_address_ipv6, POTENT_OUT_ADDR, sendbuf, 1);

		read = manager->readI2C(pbinfo[0].board_address_ipv6, POTENT_OUT_ADDR, recvbuf, sizeof(recvbuf), 3);
		_tprintf(_T("i2c 0x28 = [%d] "), read);
		for (uint32_t i = 0; i < read; ++i) {
			_tprintf(_T("%x, "), recvbuf[i]);
		}
		_tprintf(_T("\n"));

		sendbuf[0] = 0x00;	// -0 db
		sendbuf[1] = 0x40;	// -0 db
		ret = manager->writeI2C(pbinfo[0].board_address_ipv6, POTENT_OUT_ADDR, sendbuf, 2);

		read = manager->readI2C(pbinfo[0].board_address_ipv6, POTENT_OUT_ADDR, recvbuf, sizeof(recvbuf), 3);
		_tprintf(_T("i2c 0x28 = [%d] "), read);
		for (uint32_t i = 0; i < read; ++i) {
			_tprintf(_T("%x, "), recvbuf[i]);
		}
		_tprintf(_T("\n"));

		oledClr(manager, pbinfo[0].board_address_ipv6);		// OLED クリア
		Sleep(1000);
		oledFill(manager, pbinfo[0].board_address_ipv6);	// OLED ベタ塗り
		Sleep(1000);
		oledClr(manager, pbinfo[0].board_address_ipv6);		// OLED クリア
	}

	UdplChip *chip0 = manager->getChip(CHIP_YM2151, 4000000);
	if (chip0) {
		_tprintf(_T("chip0 name = %hs, clock = %u\n"), chip0->getChipName(), chip0->getClock());
	}
	else {
		_tprintf(_T("YM2151 は見つからなかった\n"));
	}

	UdplChip *chip1 = manager->getChip(CHIP_YM2149, 4000000);
	if (chip1) {
		_tprintf(_T("chip1 name = %hs, clock = %u\n"), chip1->getChipName(), chip1->getClock());
	}
	else {
		_tprintf(_T("YM2149 は見つからなかった\n"));
	}

	system("pause");

	manager->releseChip(chip0);
	manager->releseChip(chip1);

	manager->suicide();
	FreeLibrary(hdl);

	if (pbinfo != nullptr) {
		delete[] pbinfo;
	}
	if (pcinfo != nullptr) {
		delete[] pcinfo;
	}

	return 0;
}

