//******************************************************************************
//* LOGSYS SD card bootloader.                                                 *
//* Written by   : Tamas Raikovich                                             *
//* Version      : 1.0                                                         *
//* Last modified: 2013.10.26.                                                 *
//******************************************************************************
#include <xparameters.h>
#include <xintc_l.h>
#include <mb_interface.h>
#include <stdio.h>
#include <string.h>
#include "timer\timer.h"
#include "spi\spi.h"
#include "memcard\memory_card.h"
#include "memcard\fat_filesystem.h"
#include "settings.h"


//******************************************************************************
//* Global variables.                                                          *
//******************************************************************************
FATFS fatfs;


//******************************************************************************
//* Endless loop.                                                              *
//******************************************************************************
void Halt()
{
	while (1);
}


//******************************************************************************
//* Main function.                                                             *
//******************************************************************************
int main()
{
	unsigned long result;
	unsigned short bytesRead;
	unsigned short bytesToRead;
	unsigned long remainingBytes;
	unsigned char *memoryAddress;
	unsigned long processedBytes;
	unsigned long percent;
	unsigned long prevPercent;
	void (*entryPoint)(void);

	//Enable the interrupts on the MicroBlaze processor.
	microblaze_enable_interrupts();
	//Enable the interrupts on the interrupt controller.
	XIntc_MasterEnable(INTC_BASEADDR);

	//Initialize the timer.
	TimerInitialize(100);

	//Display the initial message.
	xil_printf("\x1b[2J");
	xil_printf("\x1b[0;0H");
	xil_printf("LOGSYS SD card bootloader\r\n");
	xil_printf("Copyright (C) 2013, Tamas Raikovich\r\n");
	xil_printf("Boot image file: " BOOTIMAGE_NAME "\r\n");

	//Initializing the memory card.
	xil_printf("Initializing the memory card......");
	result = MemCardInitialize();
	if (result != DISK_OK)
	{
		xil_printf("Error %d\r\n", result);
		Halt();
	}
	xil_printf("OK\r\n");

	//Mounting the filesystem.
	xil_printf("Mounting the filesystem...........");
	result = pf_mount(&fatfs);
	if (result != FR_OK)
	{
		xil_printf("Error %d\r\n", result);
		Halt();
	}
	xil_printf("OK (");
	switch (fatfs.fs_type)
	{
		case FS_FAT12:
			xil_printf("FAT12)\r\n");
			break;
		case FS_FAT16:
			xil_printf("FAT16)\r\n");
			break;
		case FS_FAT32:
			xil_printf("FAT32)\r\n");
			break;
	}

	//Opening the image file.
	xil_printf("Loading the image file............000 %%");
	result = pf_open(BOOTIMAGE_NAME);
	if (result != FR_OK)
	{
		xil_printf("\x1b[5D");
		xil_printf("Error %d\r\n", result);
		Halt();
	}

	//Load the content of the image file into the memory.
	memoryAddress = (unsigned char *)START_ADDRESS;
	remainingBytes = fatfs.fsize;
	processedBytes = 0;
	prevPercent = 0;

	while (remainingBytes > 0)
	{
		bytesToRead = (remainingBytes > 32768) ? 32768 : (unsigned short)remainingBytes;

		result = pf_read(memoryAddress, bytesToRead, &bytesRead);
		if (result != FR_OK)
		{
			xil_printf("\x1b[5D");
			xil_printf("Error %d\r\n", result);
			Halt();
		}

		remainingBytes -= bytesToRead;
		memoryAddress += bytesToRead;

		//Update the progress value.
		processedBytes += bytesToRead;
		percent = (100 * processedBytes) / fatfs.fsize;
		xil_printf("\x1b[5D");
		xil_printf("%3d %%", percent);
	}

	xil_printf("\r\n\r\n");

	//Jump to the start address.
	entryPoint = (void (*)(void))START_ADDRESS;
	entryPoint();

	return 0;
}


