// MakePacketDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MakePacket.h"
#include "MakePacketDlg.h"
#include ".\makepacketdlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CMakePacketDlg dialog
CMakePacketDlg::CMakePacketDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMakePacketDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	XmtCmd = XMTPT_SEND_CONFIG_PACKET_EX;
}

void CMakePacketDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CMakePacketDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
	ON_BN_CLICKED(IDC_RADIO_MESSAGE_TYPE1, OnBnClickedRadioMessageType1)
	ON_BN_CLICKED(IDC_RADIO_MESSAGE_TYPE2, OnBnClickedRadioMessageType2)
	ON_BN_CLICKED(IDC_RADIO_MESSAGE_TYPE3, OnBnClickedRadioMessageType3)
END_MESSAGE_MAP()

// CMakePacketDlg message handlers
BOOL CMakePacketDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	CButton *chkXmtCmd;				// Set transmit command default
	chkXmtCmd = (CButton *)GetDlgItem(IDC_RADIO_MESSAGE_TYPE1);
	chkXmtCmd->SetCheck(TRUE);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.
void CMakePacketDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMakePacketDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CMakePacketDlg::OnBnClickedButton1()
{
	CString strData("");
	CString strPacket("");
	CString strStatus("");
	BOOL bCmdFound;
    Packet_Out POUT;
	BYTE Buffer[1024];
	int idxMiscData;
	int iDataLen;
    bCmdFound = FALSE;
    POUT.LEN = 0;

	GetDlgItem(IDC_EDIT1)->GetWindowText(strData);	// get input message data
	// configurations should be in upper case ASCII
	if ((XmtCmd == XMTPT_SEND_CONFIG_PACKET_EX) 
				|| (XmtCmd == XMTPT_READ_CONFIG_PACKET_EX)) {
		strData.Trim();
		strData.MakeUpper();
		GetDlgItem(IDC_EDIT1)->SetWindowText(strData);
	}
	if ((XmtCmd == XMTPT_SEND_CONFIG_PACKET_EX) 
		|| (XmtCmd == XMTPT_READ_CONFIG_PACKET_EX)
			|| (XmtCmd == XMTPT_WRITE_512_BYTE_MISC_DATA)) {
		bCmdFound = TRUE;
		switch (XmtCmd) {
			case XMTPT_SEND_CONFIG_PACKET_EX:					// bypass any filters
				iDataLen = strData.GetLength();
				if (iDataLen > 0) {
					strData.MakeUpper();
					CopyAsciiData(POUT.DATA, strData, iDataLen);	//Force ASCII
				}
				POUT.PID1 = PID1_REQ_CONFIG;
				POUT.PID2 = PID2_TEXT_CONFIG_PACKET;			// text config packet
				POUT.LEN = (USHORT)iDataLen;
				strStatus = " Created Text Configuration Packet";
				break;
			case XMTPT_READ_CONFIG_PACKET_EX:					// bypass any filters
				iDataLen = strData.GetLength();
				if (iDataLen > 0) {
					strData.MakeUpper();
					CopyAsciiData(POUT.DATA, strData, iDataLen);	//Force ASCII 
				}
				POUT.PID1 = PID1_REQ_CONFIG;
				POUT.PID2 = PID2_CONFIG_READBACK_PACKET;		// text config packet
				POUT.LEN = (USHORT)iDataLen;
				strStatus = " Created Text Configuration Readback Packet";
				break;
			case XMTPT_WRITE_512_BYTE_MISC_DATA:				// 0 bytes data clears misc text
				POUT.PID1 = PID1_VENDOR_REQ;
				POUT.PID2 = PID2_WRITE_512_BYTE_MISC_DATA;		// write misc data
				POUT.LEN = 512;
				iDataLen = strData.GetLength();
				for(idxMiscData=0;idxMiscData<512;idxMiscData++) {
					if (idxMiscData < iDataLen) {		// create byte array padded with NULLs
						POUT.DATA[idxMiscData] = (BYTE)strData.GetAt(idxMiscData);
					} else {
						POUT.DATA[idxMiscData] = 0;
					}
				}
				strStatus = " Created Write 512 BYTE MISC Data Packet";
				break;
			default:
				bCmdFound = FALSE;
				break;
		}
		if (bCmdFound) {						// create packet
			if (! POUT_Buffer(POUT, Buffer)) {
				bCmdFound = FALSE;				// packet buffer could not be created
				strStatus += " Output Buffer Creation Error";
			} else {							// display packet
				strPacket = ShowBytes(Buffer,(POUT.LEN+8));
				CString strTestPkt("");
				strTestPkt.Format(" %s",((TestPacketCkSumOK(Buffer)) ? "Passed" : "Failed"));
				GetDlgItem(IDC_CHECKSUMTEST2)->SetWindowText(strTestPkt);
				GetDlgItem(IDC_EDIT2)->SetWindowText(strPacket);
			}
		} else {
			strStatus += " Command Not Found Error";
		}
	}
	if (!bCmdFound) {
		GetDlgItem(IDC_CHECKSUMTEST)->SetWindowText("");
		GetDlgItem(IDC_CHECKSUMTEST2)->SetWindowText("");
		if ((strData.GetLength() == 0 ) && (XmtCmd == XMTPT_SEND_CONFIG_PACKET_EX)) {
			strStatus += " Send Text Configuration Command must have settings data";
		} else if ((strData.GetLength() >0 ) && (XmtCmd == XMTPT_READ_CONFIG_PACKET_EX)) {
			strStatus += " Text Configuration Readback Command must have settings data";
		} else {
			strStatus += " Unknown Error";
		}
	}
	GetDlgItem(IDC_MAKE_PACKET_STATUS)->SetWindowText(strStatus);
}

BOOL CMakePacketDlg::CopyAsciiData(BYTE Data[], CString strData, long lLen)
{
	long idxData;
	if (lLen > 0) {
		for(idxData=0;idxData<lLen;idxData++) {
			CT2A asciiData(strData, CP_UTF8);	// Convert to UTF8
			Data[idxData] = asciiData.m_psz[idxData];
		}
		return TRUE;
	} else {
		return FALSE;
	}
	return FALSE;
}

BOOL CMakePacketDlg::POUT_Buffer(Packet_Out POUT, BYTE Buffer[])
{
    long idxBuffer;
    long CS;
    
    Buffer[0] = SYNC1_;
    Buffer[1] = SYNC2_;
    Buffer[2] = POUT.PID1;
    Buffer[3] = POUT.PID2;
    Buffer[4] = (POUT.LEN & 0xFF00) / 256;
    Buffer[5] = POUT.LEN & 0xFF;

    CS = SYNC1_ + SYNC2_ + POUT.PID1 + POUT.PID2 + ((POUT.LEN & 0xFF00) / 256) + (POUT.LEN & 0xFF);

	if (POUT.LEN > 0) {
		for (idxBuffer=0; idxBuffer<POUT.LEN;idxBuffer++) {
            Buffer[idxBuffer + 6] = POUT.DATA[idxBuffer];
            CS = CS + POUT.DATA[idxBuffer];
		}
    }
    CS = (CS ^ 0xFFFF) + 1;
    Buffer[POUT.LEN + 6] = (BYTE)((CS & 0xFF00) / 256);
    Buffer[POUT.LEN + 7] = (BYTE)(CS & 0xFF);
    return TRUE;
}

void CMakePacketDlg::OnBnClickedRadioMessageType1()
{
	XmtCmd = XMTPT_SEND_CONFIG_PACKET_EX;
}

void CMakePacketDlg::OnBnClickedRadioMessageType2()
{
	XmtCmd = XMTPT_READ_CONFIG_PACKET_EX;
}

void CMakePacketDlg::OnBnClickedRadioMessageType3()
{
	XmtCmd = XMTPT_WRITE_512_BYTE_MISC_DATA;
}

//@mfunc converts a UCHAR configuration value to a Hex display string
//@parm value label
//@parm configuration value
//@rdesc config data value display string
//@comm each configuration value is displayed on a separate line
CString CMakePacketDlg::ConfigUChHexValCStr(LPCTSTR lpstrLabel, long intValue) {
	CString strVal("");
	CString fmtStr("");
	fmtStr = fmtStr + lpstrLabel + "%.2X";
    strVal.Format((LPCTSTR)fmtStr, intValue);
	return strVal;
}

//@mfunc show buffer in hex string format
//@parm buffer to be displayed
//@rdesc display string in hex value display format
CString CMakePacketDlg::ShowBytes(UCHAR Buffer[], long lLen) { 
    int i; 
    CString strMsg("");
	for(i=0; i<lLen; i++) {
		strMsg += ConfigUChHexValCStr("",Buffer[i]);
		if (((i+1) % 2) == 0 ) { 
			strMsg += " ";
		}
		if (((i+1) % 32) == 0 ) { 
			strMsg += "\r\n";
		}
    }
    return strMsg;
}

BOOL CMakePacketDlg::TestPacketCkSumOK(BYTE Data[])
{
    long idxBuffer;
    long CS;
	long PktLen;
	BYTE CHKSUM_MSB;
	BYTE CHKSUM_LSB;
    
	PktLen = (Data[4] * 256) + Data[5];
    CS = Data[0] + Data[1] + Data[2] + Data[3] + Data[4] + Data[5];
	if (PktLen > 0) {
		for (idxBuffer=0; idxBuffer<PktLen;idxBuffer++) {
            CS = CS + Data[idxBuffer + 6];
		}
    }
    CS = (CS ^ 0xFFFF) + 1;
    CHKSUM_MSB = (BYTE)((CS & 0xFF00) / 256);	// calculated checksum
    CHKSUM_LSB = (BYTE)(CS & 0xFF);
	CString strChecksum("");
	strChecksum.Format(" 0x%.2X%.2X",CHKSUM_MSB,CHKSUM_LSB);
	GetDlgItem(IDC_CHECKSUMTEST)->SetWindowText(strChecksum);
	if ((Data[PktLen + 6] == CHKSUM_MSB) && (Data[PktLen + 7] == CHKSUM_LSB)) {
		return TRUE;
	} else {
		return FALSE;
	}
}


