/****************************************************************************************************
* created by sunpeng 2017 all rights reserved!
****************************************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "string.h"
#include "include.h"
#include "InnerFlash.h"
#include "wireless.h"

#if ARCH_MODE == NRF52832_Slave_Mode
#include "ble_flash.h"
#include "fds.h"
#include "nrf_fstorage.h"

#elif ARCH_MODE == CC254X_Peripheral_Mode
#include "simpleBLE.h"

#elif ARCH_MODE == NRF51802_Peripheral_Mode
#include "nrf.h"

#endif

#if ARCH_MODE == NRF52832_Slave_Mode
/* Private typedef -----------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#define APP_DATA_START_PAGE_ADDR	118									/*App用户数据存储Flash起始页  0x76*/
#define APP_DATA_START_BASE_ADDR	(APP_DATA_START_PAGE_ADDR*0x1000UL)	/*App用户数据存储Flash起始地址*/

#define FLASH_PAGE_SIZE    ((uint16_t)0x800)

#define GAMSCORE_FILE_ID     0x1000
#define GAMSCORE_REC_KEY     0x2000

/* Private define ------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
uint32_t StartAddress = 0x10000000;		 //起始地址 250k 处
static volatile uint8_t write_flag = 0;
static volatile uint8_t fds_init_flag = 0;

#define GAMSCORE_FILE_ID     	0x1000
#define GAMSCORE_REC_KEY		0x2000
#define GAMSCORE_REC_KEY_SUM	(GAMSCORE_REC_KEY-1)


/* Extern variables ---------------------------------------------------------*/

/* Private function prototypes -----------------------------------------------*/
static ret_code_t my_fds_init (void);
static ret_code_t fds_find_and_delete (uint16_t rec_key);


/****************************************************************************************/
uint8_t init_InnerFlash(void)
{
    uint32_t err_code;
	
    //初始化FDS
	//printf("FDS TEST STEP1:  FDS Register and Init\r\n");
	err_code = my_fds_init();
	APP_ERROR_CHECK(err_code);
	while (fds_init_flag==0);
	
	return true;
}	


//FDS事件处理函数
static void my_fds_evt_handler(fds_evt_t const * const p_fds_evt)
{
    switch (p_fds_evt->id)
    {
	case FDS_EVT_INIT:
		if (p_fds_evt->result == FDS_SUCCESS)
		{
			//FDS初始化成功
			//printf("FDS init successfully! \r\n");
			//printf("\r\n");
			fds_init_flag = 1;
		}
		break;
	case FDS_EVT_WRITE:
		if (p_fds_evt->result == FDS_SUCCESS)
		{
			  write_flag=1;
		}
		break;
	default:
		break;
    }
}

static ret_code_t my_fds_init(void)
{
    //注册FDS事件句柄，在调用fds_init()函数之前，一定要先注册
    ret_code_t ret = fds_register(my_fds_evt_handler);
    if (ret != FDS_SUCCESS)
    {
        return ret;    
    }
    ret = fds_init();
    if (ret != FDS_SUCCESS)
    {
        return ret;
    }
    
    return NRF_SUCCESS;    
}

static ret_code_t inf_read_record(uint16_t rec_key, uint32_t *p_data, uint32_t p_data_len, uint32_t *dataLen)
{
    uint32_t err_code;
    fds_flash_record_t  flash_record;
    fds_record_desc_t   record_desc;
    fds_find_token_t    ftok ={0};   //初始化为0，从头开始查找。
	if((NULL == p_data)||(NULL == dataLen))
	{
		return NRF_ERROR_INVALID_PARAM;
	}
    
    //使用给定的记录key查找给定文件中的所有匹配的记录

    while(FDS_SUCCESS == fds_record_find(GAMSCORE_FILE_ID, rec_key, &record_desc, &ftok))
    {
        //读之前要先打开记录
        err_code = fds_record_open(&record_desc, &flash_record);
        if( err_code != FDS_SUCCESS)
        {
            return err_code;    
        }
        
		*dataLen = flash_record.p_header->length_words;
		if(p_data_len < *dataLen)
		{
			*dataLen = p_data_len;
		}
        memcpy(p_data, (uint32_t *)flash_record.p_data, (*dataLen)*sizeof(uint32_t));
		
        // 读完后，一定记得关闭记录
        err_code = fds_record_close(&record_desc);
        if (err_code != FDS_SUCCESS)
        {
            return err_code;    
        }
    }
    
    return err_code;
}

static ret_code_t fds_find_and_delete (uint16_t rec_key)
{
    fds_record_desc_t   record_desc;
    fds_find_token_t    ftok;
    
    ftok.page=0;
    ftok.p_addr=NULL;
    // Loop and find records with same ID and rec key and mark them as deleted. 
    while (fds_record_find(GAMSCORE_FILE_ID, rec_key, &record_desc, &ftok) == FDS_SUCCESS)
    {
        fds_record_delete(&record_desc);
    
        //printf("Deleted record ID: %d \r\n",record_desc.record_id);
    }
	
    return NRF_SUCCESS;
}

//fds写入多条记录
static ret_code_t fds_write_record_multi(uint16_t rec_key, uint32_t *p_data, uint32_t dataLen)
{    
    fds_record_t        record;
    fds_record_desc_t   record_desc;
	
	if((0 == dataLen)||(NULL == p_data))
	{
		return NRF_ERROR_INVALID_PARAM;
	}
	
	fds_find_and_delete(rec_key);
    
	write_flag = 0;
    	
    //写入的记录：需要设置文件ID、记录key和数据块
    record.file_id              = GAMSCORE_FILE_ID;
    record.key                  = rec_key;
    record.data.p_data        = &p_data;
    record.data.length_words      = dataLen;
    
    ret_code_t ret = fds_record_write(&record_desc, &record);
	if(FDS_ERR_NO_SPACE_IN_FLASH == ret)
	{
		//碎片整理
		fds_gc();
		ret = fds_record_write(&record_desc, &record);
	}
	
    if (ret != FDS_SUCCESS)
    {
        return ret;
    }
	
	//等待写入完成
	while(0 == write_flag){};
	
    return NRF_SUCCESS;
}

//获取记录总数
int8_t get_record_total_num(uint32_t *record_num)
{
	uint32_t data_offset_len = 0;
	uint32_t p_data_offset = 0;
	
	if(NRF_SUCCESS == inf_read_record(GAMSCORE_REC_KEY_SUM, &p_data_offset, 1, &data_offset_len))
	{
		if(1 == data_offset_len)
		{
			*record_num = p_data_offset;
			return true;
		}
	}
	
	return false;
}

void cycle_get_record_total_num(void)
{
	uint32_t record_num = 0;
	//获取记录总数
	if(true == get_record_total_num(&record_num))
	{
		
	}
}


/**
  * @brief  Read 4 word at a specified Option Data address.
  * @note   This function can be used for nRF5x devices.
  * @param  startAddr: specifies the starting address to be programmed.
  * @param  addrOffset: specifies the address offset to be programmed.
  * @param  pData: specifies the data ptr to be write to storage data readed.
  * @param  lenRead: the number to read from flash
  * @retval if success return NRF_SUCCESS, others if error
  */
uint32_t Flash_Read_Specific(uint32_t startAddr, uint32_t addrOffset, uint32_t *pData, uint32_t lenRead)
{
	uint32_t err_code = NRF_SUCCESS;
	uint32_t i=0;
	uint32_t *addrStartPos;
	
	if(NULL == pData)
	{
		return NRF_ERROR_INVALID_PARAM;
	}
	
	addrStartPos = (uint32_t *)(startAddr + addrOffset);
	
	if(0 == lenRead)
	{
		return NRF_ERROR_INVALID_LENGTH;
	}
	
	for(i=0; i<lenRead; i++)
	{
		*(pData + i) = (uint32_t)*(addrStartPos + i);
	}
	
	return err_code;
}
#endif

//读取芯片内安全码
//pData		: 读取的数据指针
//len		: 读取的数据长度
uint32_t read_secure_code(uint8_t *pData, uint16_t len)
{
	uint32_t err_code = NRF_SUCCESS;
	uint8_t i = 0;
	uint8_t device_addr[6] = {0x0};
	uint8_t device_sn[8] = {0x0};
	
	if(NULL == pData)
	{
		return NRF_ERROR_INVALID_PARAM;
	}
	
	if(len < 28)
	{
		return NRF_ERROR_INVALID_LENGTH;
	}
	
	device_addr[0] = NRF_FICR->DEVICEADDR[0] >> 0;
	device_addr[1] = NRF_FICR->DEVICEADDR[0] >> 8;
	device_addr[2] = NRF_FICR->DEVICEADDR[0] >> 16;
	device_addr[3] = NRF_FICR->DEVICEADDR[0] >> 24;
	device_addr[4] = NRF_FICR->DEVICEADDR[1] >> 0;
	device_addr[5] = NRF_FICR->DEVICEADDR[1] >> 8;
#if ARCH_MODE != NRF51802_Peripheral_Mode
	device_sn[0] = NRF_UICR->CUSTOMER[0] >> 0;
	device_sn[1] = NRF_UICR->CUSTOMER[0] >> 8;
	device_sn[2] = NRF_UICR->CUSTOMER[0] >> 16;
	device_sn[3] = NRF_UICR->CUSTOMER[0] >> 24;
	device_sn[4] = NRF_UICR->CUSTOMER[1] >> 0;
	device_sn[5] = NRF_UICR->CUSTOMER[1] >> 8;
	device_sn[6] = NRF_UICR->CUSTOMER[1] >> 16;
	device_sn[7] = NRF_UICR->CUSTOMER[1] >> 24;
#endif
	
	for(i=0; i<sizeof(device_addr); i++)
	{
		*(pData + i*2	 ) = 33 + device_addr[i] / 90;
		*(pData + i*2 + 1) = 33 + device_addr[i] % 90;
	}
	
	for(i=0; i<sizeof(device_sn); i++)
	{
		*(pData + i*2	  + sizeof(device_addr)*2) = 33 + device_sn[i] / 90;
		*(pData + i*2 + 1 + sizeof(device_addr)*2) = 33 + device_sn[i] % 90;
	}
	*(pData + sizeof(device_addr)*2 + sizeof(device_sn)*2) = 0x0;
	
	return err_code;
}


/***********************************************end of file********************************************/

