/*
 * user_flash.c
 *
 *  Created on: May 30, 2018
 *      Author: sparr1
 */

#include "stm32f4xx_hal.h"
#include "OCPP.h"
#include "w25qxx.h"
/* Base address of the Flash sectors */
extern UART_HandleTypeDef huart6;
#define FLASH_USER_START_ADDR   0X0807FF00   /* Start @ of user Flash area */
#define FLASH_USER_END_ADDR     0X0807FFFF  /* End @ of user Flash area */
uint8_t InProcess = 0;
#define DATA_32                 ((uint32_t)0x12345678)

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

uint32_t Address = 0, PageError = 0;
__IO uint32_t data32 = 0 , MemoryProgramStatus = 0;
const struct Config_Parameter default_params =
{
	3,
	"/fota.bin", //link
	"113.20.17.179", //192.168.15.51
	"no",  // username
	"no",//  password
	"8080",   //port
	2,     //Communication Mode
	"LubiJio",  //ssid
	"onlyforlubiev", // password
	"1111",
	"1111",
	"1111",
	2,//ipv4V6				//V5.0.0
	"m2misafe",//apn		//V5.0.0
	0xbbaa,	//boot loader magic value
	0,
	"1234", //Password
	10,
	0,
	10,
	0,
	"/v1.6/LUBITESTAC",	//"/services/CentralSystemServiceJson16/LUBI-BS-007", //link
	"api.plugeasy.in",
	"no",
	"1234@123",
	"80",
	{1,1}, //ocpp status
	120, 	//4.X.8
	600,
	17,
	40,	//4.X.8
	"LUBI-type2",
	"12345678",
	//V501change
	3710,	//3810
	3180,	//3280
	2710,	//2810
	2160,	//2260
	0,
	60,
	4,
	0xAA77 //Magic Value
};
const struct Config_Parameter_OCPP default_params_ocpp =
{
	1, // LocalAuthListEnbl
	3600, //FailedTx_Intvl
	3,   //FailedAttempt
	1,   //StopTxInvalidId
	3,   // ResetRetry
	60,  //StatusDuration	//4.X.8
	30,  // MeterIntvl
	0,   //LocalPreAuth
	1,	 //LocalAuthOffln
	900, //ClkAlgnIntvl
	1,   //AuthRemotTx
	1,   //AuthCachEnable
	0,   //AllowOfflineTXUnknownId	//4.X.8
	300, //HeartbeatIntvl
	{0,0,0,0},   //Operative
	0,
	0,
	20,
	100,
	0,
	0xAA55, //Magic Value
};
/*Variable used for Erase procedure*/
//static FLASH_EraseInitTypeDef EraseInitStruct;

void Internal_Flash_Program(unsigned long int*, unsigned int);
void Internal_Flash_Read(unsigned long int *, unsigned int);
void Write_Params(void);
void Read_Params(void);
////////V4.1.4//////////
void Read_CACH_Params(void);
void Write_CACH_Params(void);
/////////////////////////
void Internal_Flash_Program(unsigned long int* ram_addr,unsigned int size)
{
	InProcess = 1;
	unsigned int addr=0,bal_size;
	char lcl_buff[50];

	/* Unlock the Flash to enable the flash control register access *************/
	HAL_FLASH_Unlock();

	/* Erase the user Flash area
    (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/
	FLASH_Erase_Sector(FLASH_SECTOR_11,VOLTAGE_RANGE_3);

	/* Program the user Flash area word by word
    (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/

	bal_size=size%4;
	if(bal_size) size=size+bal_size;

	Address = FLASH_USER_START_ADDR;

	while (Address < FLASH_USER_END_ADDR)
	{
		if(addr>=(size/4))break;
		if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, *ram_addr++) == HAL_OK)
		{
			Address = Address + 4;
			addr++;
		}
		else
		{
			/* Error occurred while writing data in Flash memory.
         	 User can add here some code to deal with this error */
			while (1)
			{
				//HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
				  sprintf(lcl_buff,"internal flash error.....\r\n");
					HAL_UART_Transmit(&huart6, (uint8_t*)lcl_buff, strlen(lcl_buff),500);
			}
		}
	}
	HAL_FLASH_Lock();
	InProcess = 0;
}
void Internal_Flash_Read(unsigned long int * addr_toread, unsigned int size)
{
	unsigned int addr=0,bal_size;

	bal_size=size%4;
	if(bal_size)
		size=size+bal_size;

	Address = FLASH_USER_START_ADDR;
	MemoryProgramStatus = 0x0;

	while (Address < FLASH_USER_END_ADDR)
	{
		if(addr>=(size/4))break;
		*addr_toread = *(__IO uint32_t *)Address;
		addr_toread++;addr++;
	    Address = Address + 4;
	}
}
void Read_Params(void)
{
//	Internal_Flash_Read((unsigned long int*)&OCPP, sizeof(struct Config_Parameter));

    uint8_t lcltemp_buff[2]; //,hour_ok=0;;
    uint16_t i=0; //j=0;//variable=0;
    uint32_t add=(3840*w25qxx.SectorSize);

    uint16_t frame_length;

    uint16_t data_len=0;

    if(sizeof(struct Config_Parameter)%2)
    	data_len=sizeof(OCPP)-1;  // SFlash_write(ptr,sizeof(data_to_flash)-1);
    else
    	data_len=sizeof(OCPP); //SFlash_write(ptr,sizeof(data_to_flash));

    frame_length = data_len;
    char *ptr= &OCPP.fw_status;

    for(i=0;i<frame_length;i++) //while(data_len--)
    {
    		W25qxx_ReadByte(&lcltemp_buff,add);
    		*ptr=lcltemp_buff[0];
    		ptr++;
    		add++;
    }
    data_len=0;
}

void Read_Key_Params(void)
{
//	Internal_Flash_Read((unsigned long int*)&OCPP, sizeof(struct Config_Parameter));

    uint8_t lcltemp_buff[2]; //,hour_ok=0;;
    uint16_t i=0; //j=0;//variable=0;
    uint32_t add=(3809*w25qxx.SectorSize);

    uint16_t frame_length;

    uint16_t data_len=0;

    if(sizeof(struct Config_Parameter_OCPP)%2)
    	data_len=sizeof(Ocpp_Setting)-1;  // SFlash_write(ptr,sizeof(data_to_flash)-1);
    else
    	data_len=sizeof(Ocpp_Setting); //SFlash_write(ptr,sizeof(data_to_flash));

    frame_length = data_len;
    char *ptr= &Ocpp_Setting.LocalAuthListEnbl;

    for(i=0;i<frame_length;i++) //while(data_len--)
    {
    		W25qxx_ReadByte(&lcltemp_buff,add);
    		*ptr=lcltemp_buff[0];
    		ptr++;
    		add++;
    }
    data_len=0;
}
void Write_Key_Params(void)
{
	char *data = &Ocpp_Setting.LocalAuthListEnbl;
	static uint32_t add=0;//pointer_loc;//(w25qxx.SectorCount-1)*w25qxx.SectorSize;
		uint16_t page_len;
	    uint16_t len=sizeof(Ocpp_Setting);

	if(InProcess == 0)
	{
		InProcess =1;
		//Internal_Flash_Program((unsigned long int*)&OCPP, );
		add = (3809*w25qxx.SectorSize);
		if( !(add % 4096))
		{
		  W25qxx_EraseSector((add/4096));
		}

	//	 First Page not starts from 00 and data length not in page boundary
		page_len = (add | 0xff) + 1 - add;
		if ((add & 0xff) && len > page_len)
		{
			//if (!writePage(add, data, page_len))
			//	return false;

			W25qxx_WritePage(data,add,0,page_len);

			len -= page_len;
			data += page_len;
			add += page_len;

			if( !(add % 4096))
			{
				W25qxx_EraseSector((add/4096));
			}
		}

		//if(add>=3824*w25qxx.SectorSize)
		//add=0;

		while (len)
		{
			page_len = len > 256 ? 256 : len;

			//if (!writePage(add, data, page_len))
			//	return false;
			W25qxx_WritePage(data,add,0,page_len);
			len -= page_len;
			data += page_len;
			add += page_len;

			if( !(add % 4096))
			{
				W25qxx_EraseSector((add/4096));
			}
		}
	}
	InProcess =0;
}
void Write_Params(void)
{
	char *data = &OCPP.fw_status;
	static uint32_t add=0;//pointer_loc;//(w25qxx.SectorCount-1)*w25qxx.SectorSize;
		uint16_t page_len;
	    uint16_t len=sizeof(OCPP);

	if(InProcess == 0)
	{
		InProcess =1;
		//Internal_Flash_Program((unsigned long int*)&OCPP, );
		add = (3840*w25qxx.SectorSize);
		if( !(add % 4096))
		{
		  W25qxx_EraseSector((add/4096));
		}

	//	 First Page not starts from 00 and data length not in page boundary
		page_len = (add | 0xff) + 1 - add;
		if ((add & 0xff) && len > page_len)
		{
			//if (!writePage(add, data, page_len))
			//	return false;

			W25qxx_WritePage(data,add,0,page_len);

			len -= page_len;
			data += page_len;
			add += page_len;

			if( !(add % 4096))
			{
				W25qxx_EraseSector((add/4096));
			}
		}

		//if(add>=3824*w25qxx.SectorSize)
		//add=0;

		while (len)
		{
			page_len = len > 256 ? 256 : len;

			//if (!writePage(add, data, page_len))
			//	return false;
			W25qxx_WritePage(data,add,0,page_len);
			len -= page_len;
			data += page_len;
			add += page_len;

			if( !(add % 4096))
			{
				W25qxx_EraseSector((add/4096));
			}
		}
	}
	InProcess =0;
}
void Read_CACH_Params(void)
{
//	Internal_Flash_Read((unsigned long int*)&OCPP, sizeof(struct Config_Parameter));

    uint8_t lcltemp_buff[2]; //,hour_ok=0;;
    uint16_t i=0; //j=0;//variable=0;
    uint32_t add=(3848*w25qxx.SectorSize);

    uint16_t frame_length;

    uint16_t data_len=0;

    if(sizeof(struct Config_Parameter_Cach_Memory)%2)
    	data_len=sizeof(Cash_Memory)-1;  // SFlash_write(ptr,sizeof(data_to_flash)-1);
    else
    	data_len=sizeof(Cash_Memory);    //SFlash_write(ptr,sizeof(data_to_flash));

    frame_length = data_len;
    char *ptr= &Cash_Memory.transaction_id[0];

    for(i=0;i<frame_length;i++) //while(data_len--)
    {
    		W25qxx_ReadByte(&lcltemp_buff,add);
    		*ptr=lcltemp_buff[0];
    		ptr++;
    		add++;
    }
    data_len=0;
}

void Write_CACH_Params(void)
{
	char *data = &Cash_Memory.transaction_id[0];
	static uint32_t add=0;//pointer_loc;//(w25qxx.SectorCount-1)*w25qxx.SectorSize;
	uint16_t page_len;
	uint16_t len=sizeof(Cash_Memory);

	if(InProcess == 0)
	{
		InProcess =1;
		//Internal_Flash_Program((unsigned long int*)&OCPP, );
		add = (3848*w25qxx.SectorSize);
		if( !(add % 4096))
		{
		  W25qxx_EraseSector((add/4096));
		}

	//	 First Page not starts from 00 and data length not in page boundary
		page_len = (add | 0xff) + 1 - add;
		if ((add & 0xff) && len > page_len)
		{
			//if (!writePage(add, data, page_len))
			//	return false;
			W25qxx_WritePage(data,add,0,page_len);

			len -= page_len;
			data += page_len;
			add += page_len;

			if( !(add % 4096))
			{
				W25qxx_EraseSector((add/4096));
			}
		}

		//if(add>=3824*w25qxx.SectorSize)
		//add=0;

		while (len)
		{
			page_len = len > 256 ? 256 : len;

			//if (!writePage(add, data, page_len))
			//	return false;
			W25qxx_WritePage(data,add,0,page_len);
			len -= page_len;
			data += page_len;
			add += page_len;

			if( !(add % 4096))
			{
				W25qxx_EraseSector((add/4096));
			}
		}
	}
	InProcess =0;
}
