//###########################################################################
// FILE:   f05_DownloadImage.cpp
// TITLE:  Download Image function required for CAN flash programmer.
//
// This function is used to communicate and download with the device.  Code 
// will be broken up into words (16-bit messages) and sent using the PEAK CAN
// API for writing messages.
//###########################################################################
// $TI Release: $
// $Release Date: $
//###########################################################################
#include "stdafx.h"
#include "../include/f05_DownloadImage.h"

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#pragma once
#include <conio.h>
#include <windows.h>
#include <dos.h>

// Headers required for PCAN API
#include "../include/PCANBasic.h"

//*****************************************************************************
//
// Helpful macros for generating output depending upon verbose and quiet flags.
//
//*****************************************************************************
#define VERBOSEPRINT(...) if(g_bVerbose) { _tprintf(__VA_ARGS__); }
#define QUIETPRINT(...) if(!g_bQuiet) { _tprintf(__VA_ARGS__); }

//*****************************************************************************
//
// Globals whose values are set or overridden via command line parameters.
//
//*****************************************************************************
extern bool g_bVerbose;
extern bool g_bQuiet;
extern bool g_bWaitOnExit;
extern wchar_t *g_pszAppFile;
extern wchar_t *g_pszKernelFile;
extern wchar_t *g_pszDeviceName;

//*****************************************************************************
//
// Download an image to the the device identified by the passed handle.  The
// image to be downloaded and other parameters related to the operation are
// controlled by command line parameters via global variables.
//
// Returns 0 on success or a positive error return code on failure.
//
//*****************************************************************************
int
f05_DownloadImage(void)
{
	FILE *Kfh;
	FILE *Afh;

	unsigned int rcvData = 0;
	unsigned int rcvDataH = 0;
	int txCount = 0;

	unsigned int fileStatus;
	DWORD dwRead;
	errno_t error;
	DWORD dwWritten;
	unsigned char sendData[8];

	QUIETPRINT(_T("Downloading %s to device...\n"), g_pszAppFile);

	//
	// Does the input file exist?
	//
	// Opens the Flash Kernel File

	error = _wfopen_s(&Kfh, g_pszKernelFile, _T("rb"));
	if (!Kfh)
	{
		QUIETPRINT(_T("Unable to open Kernel file %s. Does it exist?\n"), g_pszKernelFile);
		return(10);
	}

	//Opens the application file

	error = _wfopen_s(&Afh, g_pszAppFile, L"rb");
	if (!Afh)
	{
		QUIETPRINT(_T("Unable to open Application file %s. Does it exist?\n"), g_pszAppFile);
		return(10);
	}

	//Both Kernel, Application and USB/CAN dongle are ready

	// Set up CAN message buffer to transmit 2 bytes at a time (one word)
	TPCANStatus gStatus;
	tagTPCANMsg MessageBuffer;
	MessageBuffer.MSGTYPE = PCAN_MESSAGE_STANDARD;
	MessageBuffer.ID = 0x1;
	MessageBuffer.LEN = 2;


	//Find the start of the kernel data
	getc(Kfh);
	getc(Kfh);
	getc(Kfh);


	fileStatus = fscanf_s(Kfh, "%x%x", &sendData[0], &sendData[1]);
	int i = 0;
	while (fileStatus == 2)
	{
		i++;

		//Send next word
		MessageBuffer.DATA[0] = sendData[0];
		MessageBuffer.DATA[1] = sendData[1];
		gStatus = CAN_Write(PCAN_USBBUS1, &MessageBuffer);

		if (gStatus != PCAN_ERROR_OK)
		{
			QUIETPRINT(_T("Error sending CAN frame?\n"), g_pszAppFile);
		}

		//Read next word
		fileStatus = fscanf_s(Kfh, "%x%x", &sendData[0], &sendData[1]);
	}

	VERBOSEPRINT(_T("\nKernel Loaded"));

	Sleep(5000);
	VERBOSEPRINT(_T("\nDone Waiting for kernel boot..."));

	//Find the start of the application data
	txCount = 0;
	getc(Afh);
	getc(Afh);
	getc(Afh);

	while (txCount < 11)
	{
		txCount++;
		fscanf_s(Afh, "%x%x", &sendData[0], &sendData[1]);
		//Send next word
		MessageBuffer.DATA[0] = sendData[0];
		MessageBuffer.DATA[1] = sendData[1];
		gStatus = CAN_Write(PCAN_USBBUS1, &MessageBuffer);

		if (gStatus != PCAN_ERROR_OK)
		{
			//QUIETPRINT(_T("Error sending CAN frame?\n"), g_pszAppFile);
		}
	}

	//RONNIES CODE
	int wordData;
	int byteData;
	txCount = 0;

	int totalCount = 0;
	wordData = 0x0000;
	byteData = 0x0000;
	fileStatus = 1;

	Sleep(10000);
	VERBOSEPRINT(_T("\nLoading flash application..."));
	//Load the flash application
	//Note: When using the CAN protocol, no explicit checksum or acknowledgment is needed from the target.
	//Because of this, it is possible to transfer too much code too quickly for the target Flash API to keep up.
	//To reconcile this, we manually insert sleep commands that are tuned to work with a program buffer of 0x200 words
	//and a CAN bit rate of 100 kbps. These values can be adjusted as needed.
	while (1) {

		fscanf_s(Afh, "%x%x", &sendData[0], &sendData[1]);
		if (fileStatus == 0)
			break;

		MessageBuffer.DATA[0] = sendData[0];
		MessageBuffer.DATA[1] = sendData[1];
		gStatus = CAN_Write(PCAN_USBBUS1, &MessageBuffer);

		if (gStatus != PCAN_ERROR_OK)
		{
			//QUIETPRINT(_T("Error sending CAN frame?\n"), g_pszAppFile);
		}


		// Get block size
		if (txCount == 0x00)
		{
			wordData = sendData[0];
			wordData |= (sendData[1] << 8);
		}

		txCount++;
		totalCount++;

		//If the next block size is 0, exit the while loop. 
		if (wordData == 0x00 && txCount > 0)
		{

			wordData = 0x0000;
			byteData = 0x0000;

			break;
		}
		// will execute when all the data in the block has been sent
		// half for word tx
		// add 3 to wordData since block size does not account for blocksize and block address words
		else if (txCount == (wordData + 3))
		{
			wordData = 0x0000;
			byteData = 0x0000;
			txCount = 0x00;
			Sleep(5000);

		}
		// will execute when the flash kernel buffer is full (0x200 words == 0x400 bytes)
		else if ((txCount - 3) % 0x200 == 0 && txCount > 3)
		{
			Sleep(5000);
		}

	}
	VERBOSEPRINT(_T("\nApplication Load Successful"));

	return 0;
}
