/*
*********************************************************************************************************
*                                       IAR Development Kits
*                                              on the
*
*                                    M451
*
* Filename      : spi_fram.h
* Version       : V1.00
* Programmer(s) : Qian Xianghong
*********************************************************************************************************
*/

#ifndef  USER_SPI_FRAM_PRESENT
#define  USER_SPI_FRAM_PRESENT

#include "type.h"

// FRAM存储规划如下：
// 0~21: 	升级进度记录（含标志位、CRC等)
// 22~4117: 最近的升级数据（4K缓存，还未写入SFlash中）

// 4118~4129: SFLASH和FRAM一致性标识记录（含标志位、CRC等）

// 4130~4141: 保留
// 4142~4153: SLFASH的历史数据记录（含标志位、CRC等)，因为要频繁擦写，故放在铁电里
// 4154~4165: SLFASH的历史数据上传记录（含标志位、CRC等)，因为要频繁擦写，故放在铁电里

// 4166~4171:  储罐档案总数（含标志位、CRC等）
// 4172~12363: 储罐档案，共512条，因为要频繁擦写，故放在铁电里（512x16=8K）
// 12364~12369:  储罐扩展档案总数（含标志位、CRC等）
// 12370~24657: 储罐扩展档案，共512条，因为要频繁擦写，故放在铁电里（512x24=12K）/

// 24658~24679: 最近一次定位的GPS记录（含标志位、CRC等）

// 24680~32767: 保留（共8088字节）

// 存储起始地址
#define FRAM_UPGRADE_INFO_BASE 			0
#define FRAM_UPGRADE_DATA_BASE 			22

#define FRAM_SFLASH_VALID_INFO_BASE		4118

#define FRAM_DATA_INFO_BASE				4142
#define FRAM_TRAN_INFO_BASE				4154

#define FRAM_BOTTLE_INFO_BASE			4166
#define FRAM_BOTTLE_DATA_BASE			4172

#define FRAM_BOX_INFO_BASE				12364
#define FRAM_BOX_DATA_BASE				12370

#define FRAM_GPS_INFO_BASE				24658

#define FRAM_BOTTLE_COUNT 512
#define FRAM_BOX_COUNT 512

// 铁电存储容量: 32K bytes
#define FRAM_SIZE	32768ul

// 初始化引脚

// 打开设备和允许中断
void FRAM_Open();

void FRAM_ReadID();
uint8_t FRAM_WriteEN();
uint16_t FRAM_BufferWrite(uint32_t Addr, uint8_t *buf, uint32_t nbytes);
uint16_t FRAM_BufferRead(uint32_t Addr, uint8_t *buf, uint32_t nbytes);
uint32_t FRAM_BufferVerify(uint32_t Addr, uint8_t *buf, uint32_t nbytes);
void FRAM_Sleep(uint8_t sleep);

// 允许匿名结构
#pragma anon_unions
#pragma pack(push, 1)

typedef struct
{
	uint16_t check; // 标志位，必须为0x55AA
	volatile int32_t rdPtr;
	volatile int32_t wtPtr;
	uint16_t crc;	// 校验位
} loopbuff_info_t;

typedef struct
{
	loopbuff_info_t info;
	uint16_t itemSize;
	int32_t maxItemCount;
	uint32_t info_base;
	union
	{
		uint32_t data_base;
		uint8_t *data;
	};
} loopbuff_t;

// 在FRAM和SFLASH中写入相同记录，标识铁电和SFlash的对应关系。
// 一旦检测到两者记录不一致，或者任一方的记录非法，则SFlash中存储的记录无效。
typedef struct
{
	uint16_t check; 			// 标志位，必须为0x55AA
	uint32_t relative_time;	 	// 获取到系统时间的相对时间
	uint32_t offset_seconds; 	// 获取到系统时间的时基偏移
	uint16_t crc;				// 校验位
} fram_sflash_valid_t;

#pragma pack(pop)

// 循环缓冲实现部分

void LoopBuff_Create(loopbuff_t *lpbuf, uint16_t itemSize, int32_t maxItemCount, uint32_t info_base, uint32_t data_base);

void LoopBuff_Clear(loopbuff_t *lpbuf);
uint32_t LoopBuff_GetCount(loopbuff_t *lpbuf);
uint32_t LoopBuff_GetNextPtr(loopbuff_t *lpbuf, uint32_t ptr);
void LoopBuff_PutItem(loopbuff_t *lpbuf, uint8_t *item);
void LoopBuff_RemoveItems(loopbuff_t *lpbuf, uint32_t count);
uint32_t LoopBuff_GetDataPos(loopbuff_t *lpbuf, uint32_t ptr);
uint8_t *LoopBuff_GetDataPtr(loopbuff_t *lpbuf, uint32_t ptr);

// 从FRAM读取记录（前面2个字节为标志0x55AA，最后两个字节为crc）
uint32_t FRAM_LoadInfo(uint32_t Addr, uint8_t *buf, uint32_t nbytes);
// 保存记录到FRAM中（前面2个字节为标志0x55AA，最后两个字节为crc）
uint32_t FRAM_SaveInfo(uint32_t Addr, uint8_t *buf, uint32_t nbytes);

#endif
